aboutsummaryrefslogtreecommitdiff
path: root/Sources/NorgUI/Views/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'Sources/NorgUI/Views/Blocks')
-rw-r--r--Sources/NorgUI/Views/Blocks/BlockTaskRow.swift23
-rw-r--r--Sources/NorgUI/Views/Blocks/BlockView.swift49
-rw-r--r--Sources/NorgUI/Views/Blocks/CodeBlockView.swift10
-rw-r--r--Sources/NorgUI/Views/Blocks/HeadingView.swift26
-rw-r--r--Sources/NorgUI/Views/Blocks/ListItemView.swift27
-rw-r--r--Sources/NorgUI/Views/Blocks/ParagraphView.swift12
-rw-r--r--Sources/NorgUI/Views/Blocks/QuoteView.swift29
-rw-r--r--Sources/NorgUI/Views/Blocks/RangeableBlockView.swift22
-rw-r--r--Sources/NorgUI/Views/Blocks/RangedTagView.swift10
9 files changed, 208 insertions, 0 deletions
diff --git a/Sources/NorgUI/Views/Blocks/BlockTaskRow.swift b/Sources/NorgUI/Views/Blocks/BlockTaskRow.swift
new file mode 100644
index 0000000..45255cd
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/BlockTaskRow.swift
@@ -0,0 +1,23 @@
+import NorgKit
+import SwiftUI
+
+/// Adapts any block with status to a NorgTaskView
+struct BlockTaskRow: View {
+ @Environment(\.norgTheme) private var theme
+
+ let status: TaskStatus
+ let content: [InlineSpan]
+ let font: Font
+ let line: Int
+ let onSetStatus: (Int, TaskStatus) -> Void
+
+ var body: some View {
+ NorgTaskView(
+ status: status,
+ text: AttributedString(norg: content, baseFont: font, theme: theme),
+ font: font,
+ onToggle: { onSetStatus(line, status == .done ? .undone : .done) },
+ onSetStatus: { onSetStatus(line, $0) }
+ )
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/BlockView.swift b/Sources/NorgUI/Views/Blocks/BlockView.swift
new file mode 100644
index 0000000..59fcb78
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/BlockView.swift
@@ -0,0 +1,49 @@
+import NorgKit
+import SwiftUI
+
+// General block renderer.
+struct BlockView: View {
+ let block: NorgBlock
+ let ordinal: Int?
+ let onSetStatus: (Int, TaskStatus) -> Void
+
+ var body: some View {
+ switch block {
+ case .heading(let level, let status, let content, let line):
+ HeadingView(
+ level: level, status: status, content: content, line: line, onSetStatus: onSetStatus)
+
+ case .paragraph(let content, _):
+ ParagraphView(content: content)
+
+ case .unorderedListItem(_, let status, let content, let line):
+ ListItemView(
+ marker: "•", status: status, content: content, line: line, onSetStatus: onSetStatus)
+
+ case .orderedListItem(_, let status, let content, let line):
+ ListItemView(
+ marker: "\(ordinal ?? 1).", status: status, content: content,
+ line: line, onSetStatus: onSetStatus)
+
+ case .quote(_, let status, let content, let line):
+ QuoteView(status: status, content: content, line: line, onSetStatus: onSetStatus)
+
+ case .codeBlock(let language, let code, _):
+ CodeBlockView(language: language, code: code)
+
+ case .definition(let title, let status, _, let line),
+ .footnote(let title, let status, _, let line),
+ .tableCell(let title, let status, _, let line):
+ RangeableBlockView(title: title, status: status, line: line, onSetStatus: onSetStatus)
+
+ case .rangedTag(let name, _, let content, _):
+ RangedTagView(name: name, content: content)
+
+ case .horizontalRule:
+ Divider()
+
+ case .weakDelimiter, .strongDelimiter:
+ EmptyView()
+ }
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/CodeBlockView.swift b/Sources/NorgUI/Views/Blocks/CodeBlockView.swift
new file mode 100644
index 0000000..2f1ebfb
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/CodeBlockView.swift
@@ -0,0 +1,10 @@
+import SwiftUI
+
+struct CodeBlockView: View {
+ let language: String?
+ let code: String
+
+ var body: some View {
+ VerbatimBlock(label: language, content: code)
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/HeadingView.swift b/Sources/NorgUI/Views/Blocks/HeadingView.swift
new file mode 100644
index 0000000..3b65134
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/HeadingView.swift
@@ -0,0 +1,26 @@
+import NorgKit
+import SwiftUI
+
+struct HeadingView: View {
+ @Environment(\.norgTheme) private var theme
+
+ let level: Int
+ let status: TaskStatus?
+ let content: [InlineSpan]
+ let line: Int
+ let onSetStatus: (Int, TaskStatus) -> Void
+
+ var body: some View {
+ let font = theme.heading(level)
+ Group {
+ if let status {
+ BlockTaskRow(
+ status: status, content: content, font: font, line: line, onSetStatus: onSetStatus)
+ } else {
+ Text(AttributedString(norg: content, baseFont: font, theme: theme))
+ .font(font)
+ }
+ }
+ .padding(.top, 4)
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/ListItemView.swift b/Sources/NorgUI/Views/Blocks/ListItemView.swift
new file mode 100644
index 0000000..581974b
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/ListItemView.swift
@@ -0,0 +1,27 @@
+import NorgKit
+import SwiftUI
+
+struct ListItemView: View {
+ @Environment(\.norgTheme) private var theme
+
+ let marker: String
+ let status: TaskStatus?
+ let content: [InlineSpan]
+ let line: Int
+ let onSetStatus: (Int, TaskStatus) -> Void
+
+ var body: some View {
+ HStack(alignment: .firstTextBaseline, spacing: 8) {
+ if let status {
+ BlockTaskRow(
+ status: status, content: content, font: theme.body, line: line, onSetStatus: onSetStatus
+ )
+ } else {
+ Text(marker)
+ .foregroundStyle(.secondary)
+ .monospacedDigit()
+ Text(AttributedString(norg: content, theme: theme))
+ }
+ }
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/ParagraphView.swift b/Sources/NorgUI/Views/Blocks/ParagraphView.swift
new file mode 100644
index 0000000..2ad0dd5
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/ParagraphView.swift
@@ -0,0 +1,12 @@
+import NorgKit
+import SwiftUI
+
+struct ParagraphView: View {
+ @Environment(\.norgTheme) private var theme
+
+ let content: [InlineSpan]
+
+ var body: some View {
+ Text(AttributedString(norg: content, theme: theme))
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/QuoteView.swift b/Sources/NorgUI/Views/Blocks/QuoteView.swift
new file mode 100644
index 0000000..0347d78
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/QuoteView.swift
@@ -0,0 +1,29 @@
+import NorgKit
+import SwiftUI
+
+struct QuoteView: View {
+ @Environment(\.norgTheme) private var theme
+
+ let status: TaskStatus?
+ let content: [InlineSpan]
+ let line: Int
+ let onSetStatus: (Int, TaskStatus) -> Void
+
+ var body: some View {
+ HStack(alignment: .top, spacing: 8) {
+ RoundedRectangle(cornerRadius: 1.5)
+ .fill(theme.quoteBarColor)
+ .frame(width: 3)
+ if let status {
+ BlockTaskRow(
+ status: status, content: content, font: theme.body, line: line, onSetStatus: onSetStatus
+ )
+ } else {
+ Text(AttributedString(norg: content, theme: theme))
+ .foregroundStyle(theme.quoteColor)
+ .italic()
+ }
+ }
+ .fixedSize(horizontal: false, vertical: true)
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/RangeableBlockView.swift b/Sources/NorgUI/Views/Blocks/RangeableBlockView.swift
new file mode 100644
index 0000000..433d89e
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/RangeableBlockView.swift
@@ -0,0 +1,22 @@
+import NorgKit
+import SwiftUI
+
+struct RangeableBlockView: View {
+ @Environment(\.norgTheme) private var theme
+
+ let title: [InlineSpan]
+ let status: TaskStatus?
+ let line: Int
+ let onSetStatus: (Int, TaskStatus) -> Void
+
+ var body: some View {
+ if let status {
+ BlockTaskRow(
+ status: status, content: title, font: theme.termFont, line: line, onSetStatus: onSetStatus
+ )
+ } else {
+ Text(AttributedString(norg: title, baseFont: theme.termFont, theme: theme))
+ .font(theme.termFont)
+ }
+ }
+}
diff --git a/Sources/NorgUI/Views/Blocks/RangedTagView.swift b/Sources/NorgUI/Views/Blocks/RangedTagView.swift
new file mode 100644
index 0000000..1cdf1d9
--- /dev/null
+++ b/Sources/NorgUI/Views/Blocks/RangedTagView.swift
@@ -0,0 +1,10 @@
+import SwiftUI
+
+struct RangedTagView: View {
+ let name: [String]
+ let content: String
+
+ var body: some View {
+ VerbatimBlock(label: name.joined(separator: "."), content: content)
+ }
+}