@lapis-notes/lapis-plugin-docs 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.md +188 -2
  2. package/dist/docs/DocsBlockMarkdownEditor.svelte +37 -0
  3. package/dist/docs/DocsBlockMarkdownEditor.svelte.d.ts +13 -0
  4. package/dist/docs/DocsBlockRefPicker.svelte +75 -0
  5. package/dist/docs/DocsBlockRefPicker.svelte.d.ts +11 -0
  6. package/dist/docs/DocsBookEditor.svelte +141 -0
  7. package/dist/docs/DocsBookEditor.svelte.d.ts +10 -0
  8. package/dist/docs/DocsBookNavigation.svelte +838 -0
  9. package/dist/docs/DocsBookNavigation.svelte.d.ts +11 -0
  10. package/dist/docs/DocsBooksColumn.svelte +82 -0
  11. package/dist/docs/DocsBooksColumn.svelte.d.ts +10 -0
  12. package/dist/docs/DocsCardBackMatter.svelte +32 -0
  13. package/dist/docs/DocsCardBackMatter.svelte.d.ts +10 -0
  14. package/dist/docs/DocsCardBlockExtra.svelte +43 -0
  15. package/dist/docs/DocsCardBlockExtra.svelte.d.ts +9 -0
  16. package/dist/docs/DocsCardPreviewFlip.svelte +143 -0
  17. package/dist/docs/DocsCardPreviewFlip.svelte.d.ts +17 -0
  18. package/dist/docs/DocsCardPreviewStack.svelte +135 -0
  19. package/dist/docs/DocsCardPreviewStack.svelte.d.ts +13 -0
  20. package/dist/docs/DocsCardPrompt.svelte +33 -0
  21. package/dist/docs/DocsCardPrompt.svelte.d.ts +8 -0
  22. package/dist/docs/DocsCardReviewAnswer.svelte +45 -0
  23. package/dist/docs/DocsCardReviewAnswer.svelte.d.ts +8 -0
  24. package/dist/docs/DocsCardTagChips.svelte +19 -0
  25. package/dist/docs/DocsCardTagChips.svelte.d.ts +7 -0
  26. package/dist/docs/DocsCardsPanel.svelte +232 -0
  27. package/dist/docs/DocsCardsPanel.svelte.d.ts +17 -0
  28. package/dist/docs/DocsCardsReview.css +1050 -0
  29. package/dist/docs/DocsChapterFooter.svelte +248 -0
  30. package/dist/docs/DocsChapterFooter.svelte.d.ts +11 -0
  31. package/dist/docs/DocsChapterScrollRing.svelte +101 -0
  32. package/dist/docs/DocsChapterScrollRing.svelte.d.ts +6 -0
  33. package/dist/docs/DocsDisplayPanel.css +627 -0
  34. package/dist/docs/DocsDisplayPanel.svelte +78 -0
  35. package/dist/docs/DocsDisplayPanel.svelte.d.ts +16 -0
  36. package/dist/docs/DocsEditorPanel.css +325 -0
  37. package/dist/docs/DocsEditorPanel.svelte +570 -0
  38. package/dist/docs/DocsEditorPanel.svelte.d.ts +22 -0
  39. package/dist/docs/DocsFlipCard.svelte +68 -0
  40. package/dist/docs/DocsFlipCard.svelte.d.ts +8 -0
  41. package/dist/docs/DocsFolderDirectoryList.svelte +206 -0
  42. package/dist/docs/DocsFolderDirectoryList.svelte.d.ts +14 -0
  43. package/dist/docs/DocsFolderPanel.css +357 -0
  44. package/dist/docs/DocsFolderPanel.svelte +102 -0
  45. package/dist/docs/DocsFolderPanel.svelte.d.ts +17 -0
  46. package/dist/docs/DocsLinksPanel.css +61 -0
  47. package/dist/docs/DocsLinksPanel.svelte +55 -0
  48. package/dist/docs/DocsLinksPanel.svelte.d.ts +11 -0
  49. package/dist/docs/DocsMarkdownField.svelte +93 -0
  50. package/dist/docs/DocsMarkdownField.svelte.d.ts +11 -0
  51. package/dist/docs/DocsMarkdownPreview.svelte +278 -0
  52. package/dist/docs/DocsMarkdownPreview.svelte.d.ts +17 -0
  53. package/dist/docs/DocsReviewPanel.svelte +63 -0
  54. package/dist/docs/DocsReviewPanel.svelte.d.ts +11 -0
  55. package/dist/docs/DocsRichBlock.svelte +291 -0
  56. package/dist/docs/DocsRichBlock.svelte.d.ts +13 -0
  57. package/dist/docs/DocsRichDisplay.svelte +316 -0
  58. package/dist/docs/DocsRichDisplay.svelte.d.ts +14 -0
  59. package/dist/docs/DocsSlidesPreview.css +243 -0
  60. package/dist/docs/DocsSlidesPreview.svelte +206 -0
  61. package/dist/docs/DocsSlidesPreview.svelte.d.ts +10 -0
  62. package/dist/docs/DocsWorkspace.css +570 -0
  63. package/dist/docs/DocsWorkspace.svelte +831 -0
  64. package/dist/docs/DocsWorkspace.svelte.d.ts +48 -0
  65. package/dist/docs/DocsWorkspaceToolbar.svelte +211 -0
  66. package/dist/docs/DocsWorkspaceToolbar.svelte.d.ts +27 -0
  67. package/dist/docs/candidates/ChoiceMenu.svelte +114 -0
  68. package/dist/docs/candidates/ChoiceMenu.svelte.d.ts +10 -0
  69. package/dist/docs/candidates/FlipCardDeck.svelte +800 -0
  70. package/dist/docs/candidates/FlipCardDeck.svelte.d.ts +36 -0
  71. package/dist/docs/candidates/MarkdownFloatingToc.svelte +313 -0
  72. package/dist/docs/candidates/MarkdownFloatingToc.svelte.d.ts +14 -0
  73. package/dist/docs/candidates/SearchableChoicePicker.css +161 -0
  74. package/dist/docs/candidates/SearchableChoicePicker.svelte +208 -0
  75. package/dist/docs/candidates/SearchableChoicePicker.svelte.d.ts +19 -0
  76. package/dist/docs/candidates/StructuredTable.svelte +98 -0
  77. package/dist/docs/candidates/StructuredTable.svelte.d.ts +8 -0
  78. package/dist/docs/candidates/StructuredTableEditor.svelte +374 -0
  79. package/dist/docs/candidates/StructuredTableEditor.svelte.d.ts +12 -0
  80. package/dist/docs/candidates/TagEditor.svelte +31 -0
  81. package/dist/docs/candidates/TagEditor.svelte.d.ts +14 -0
  82. package/dist/docs/candidates/WorkspaceHistoryControls.svelte +112 -0
  83. package/dist/docs/candidates/WorkspaceHistoryControls.svelte.d.ts +8 -0
  84. package/dist/docs/candidates/markdown-floating-toc.css +151 -0
  85. package/dist/docs/candidates/markdown-floating-toc.d.ts +1 -0
  86. package/dist/docs/candidates/markdown-floating-toc.js +1 -0
  87. package/dist/docs/docs-anki-import.d.ts +34 -0
  88. package/dist/docs/docs-anki-import.js +516 -0
  89. package/dist/docs/docs-book-view-model.d.ts +9 -0
  90. package/dist/docs/docs-book-view-model.js +71 -0
  91. package/dist/docs/docs-card-answer-markdown.d.ts +1 -0
  92. package/dist/docs/docs-card-answer-markdown.js +63 -0
  93. package/dist/docs/docs-card-display.d.ts +10 -0
  94. package/dist/docs/docs-card-display.js +18 -0
  95. package/dist/docs/docs-display-focus.d.ts +7 -0
  96. package/dist/docs/docs-display-focus.js +42 -0
  97. package/dist/docs/docs-document-surface.d.ts +7 -0
  98. package/dist/docs/docs-document-surface.js +25 -0
  99. package/dist/docs/docs-folder-directory.d.ts +21 -0
  100. package/dist/docs/docs-folder-directory.js +56 -0
  101. package/dist/docs/docs-link-mode.d.ts +16 -0
  102. package/dist/docs/docs-link-mode.js +94 -0
  103. package/dist/docs/docs-workspace-helpers.d.ts +25 -0
  104. package/dist/docs/docs-workspace-helpers.js +195 -0
  105. package/dist/docs/docs.tokens.css +13 -0
  106. package/dist/docs/import-anki-package.d.ts +10 -0
  107. package/dist/docs/import-anki-package.js +30 -0
  108. package/dist/docs/lapis-markdown-extensions.d.ts +9 -0
  109. package/dist/docs/lapis-markdown-extensions.js +128 -0
  110. package/dist/docs/pin-reading-chrome.d.ts +4 -0
  111. package/dist/docs/pin-reading-chrome.js +32 -0
  112. package/dist/docs/sidebar/DocsFoldersSidebar.svelte +134 -0
  113. package/dist/docs/sidebar/DocsFoldersSidebar.svelte.d.ts +15 -0
  114. package/dist/docs/sidebar/DocsLinksSidebar.svelte +105 -0
  115. package/dist/docs/sidebar/DocsLinksSidebar.svelte.d.ts +11 -0
  116. package/dist/docs/sidebar/DocsSidebar.css +346 -0
  117. package/dist/docs/sidebar/DocsSidebar.svelte +430 -0
  118. package/dist/docs/sidebar/DocsSidebar.svelte.d.ts +18 -0
  119. package/dist/docs/sidebar/DocsSidebarHost.svelte +139 -0
  120. package/dist/docs/sidebar/DocsSidebarHost.svelte.d.ts +12 -0
  121. package/dist/docs/sidebar/DocsTagsSidebar.svelte +176 -0
  122. package/dist/docs/sidebar/DocsTagsSidebar.svelte.d.ts +12 -0
  123. package/dist/docs/sidebar/docs-book-note-tree.d.ts +23 -0
  124. package/dist/docs/sidebar/docs-book-note-tree.js +88 -0
  125. package/dist/docs/sidebar/docs-note-sort.d.ts +26 -0
  126. package/dist/docs/sidebar/docs-note-sort.js +54 -0
  127. package/dist/docs/sidebar/docs-sidebar-filters.d.ts +17 -0
  128. package/dist/docs/sidebar/docs-sidebar-filters.js +74 -0
  129. package/dist/docs/sidebar/docs-sidebar-ui-storage.d.ts +24 -0
  130. package/dist/docs/sidebar/docs-sidebar-ui-storage.js +87 -0
  131. package/dist/docs/sidebar/docs-source-folder-tree.d.ts +16 -0
  132. package/dist/docs/sidebar/docs-source-folder-tree.js +143 -0
  133. package/dist/docs/sidebar/docs-tag-tree.d.ts +17 -0
  134. package/dist/docs/sidebar/docs-tag-tree.js +84 -0
  135. package/dist/docs-cards-view.d.ts +18 -0
  136. package/dist/docs-cards-view.js +52 -0
  137. package/dist/docs-document-view.d.ts +24 -0
  138. package/dist/docs-document-view.js +127 -0
  139. package/dist/docs-document-workspace.svelte +215 -0
  140. package/dist/docs-document-workspace.svelte.d.ts +16 -0
  141. package/dist/docs-index.d.ts +5 -0
  142. package/dist/docs-index.js +49 -0
  143. package/dist/docs-path.d.ts +6 -0
  144. package/dist/docs-path.js +10 -0
  145. package/dist/docs-plugin.d.ts +21 -0
  146. package/dist/docs-plugin.js +140 -0
  147. package/dist/docs-repository.d.ts +15 -0
  148. package/dist/docs-repository.js +75 -0
  149. package/dist/docs-review-view.d.ts +18 -0
  150. package/dist/docs-review-view.js +52 -0
  151. package/dist/docs-settings-tab.d.ts +8 -0
  152. package/dist/docs-settings-tab.js +25 -0
  153. package/dist/docs-settings.d.ts +17 -0
  154. package/dist/docs-settings.js +38 -0
  155. package/dist/docs-view.d.ts +22 -0
  156. package/dist/docs-view.js +51 -0
  157. package/dist/docs-workspace.svelte +394 -0
  158. package/dist/docs-workspace.svelte.d.ts +15 -0
  159. package/dist/index.d.ts +12 -0
  160. package/dist/index.js +12 -0
  161. package/dist/model/book.d.ts +6 -0
  162. package/dist/model/book.js +101 -0
  163. package/dist/model/coding-runtime.d.ts +4 -0
  164. package/dist/model/coding-runtime.js +9 -0
  165. package/dist/model/docs-card-context.d.ts +32 -0
  166. package/dist/model/docs-card-context.js +89 -0
  167. package/dist/model/docs-card-preview-stack-motion.d.ts +51 -0
  168. package/dist/model/docs-card-preview-stack-motion.js +94 -0
  169. package/dist/model/docs-media-context.d.ts +9 -0
  170. package/dist/model/docs-media-context.js +18 -0
  171. package/dist/model/docs-note-list.d.ts +8 -0
  172. package/dist/model/docs-note-list.js +25 -0
  173. package/dist/model/docs-relative-media.d.ts +30 -0
  174. package/dist/model/docs-relative-media.js +116 -0
  175. package/dist/model/docs-review-constants.d.ts +4 -0
  176. package/dist/model/docs-review-constants.js +13 -0
  177. package/dist/model/fsrs.d.ts +14 -0
  178. package/dist/model/fsrs.js +153 -0
  179. package/dist/model/graph.d.ts +12 -0
  180. package/dist/model/graph.js +169 -0
  181. package/dist/model/index.d.ts +14 -0
  182. package/dist/model/index.js +14 -0
  183. package/dist/model/markdown-normalize.d.ts +11 -0
  184. package/dist/model/markdown-normalize.js +755 -0
  185. package/dist/model/markdown.d.ts +167 -0
  186. package/dist/model/markdown.js +365 -0
  187. package/dist/model/sample.d.ts +7 -0
  188. package/dist/model/sample.js +524 -0
  189. package/dist/model/types.d.ts +328 -0
  190. package/dist/model/types.js +1 -0
  191. package/dist/model/workspace.d.ts +6 -0
  192. package/dist/model/workspace.js +81 -0
  193. package/dist/storybook.css +52 -0
  194. package/dist/styles.css +1 -0
  195. package/manifest.json +11 -0
  196. package/package.json +147 -4
package/README.md CHANGED
@@ -1,3 +1,189 @@
1
- # Temporary Holding Version
1
+ # `@lapis-notes/lapis-plugin-docs`
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![CI](https://github.com/lapismd/lapis-plugin-docs/actions/workflows/ci.yml/badge.svg)](https://github.com/lapismd/lapis-plugin-docs/actions/workflows/ci.yml)
4
+ [![Storybook Pages](https://github.com/lapismd/lapis-plugin-docs/actions/workflows/publish-storybook-pages.yml/badge.svg)](https://github.com/lapismd/lapis-plugin-docs/actions/workflows/publish-storybook-pages.yml)
5
+ [![Storybook](https://img.shields.io/badge/storybook-live-ff4785?logo=storybook&logoColor=white)](https://lapismd.github.io/lapis-plugin-docs/)
6
+
7
+ First-party external Docs plugin for Lapis. It provides vault-native
8
+ `*.doc.md` notes, ordered books, linked knowledge, cards, and FSRS review
9
+ through public Lapis and Design Core surfaces inside the host workspace.
10
+
11
+ The plugin owns the Docs domain model, document view, sidebar, cards, review,
12
+ settings, and native `--ui-docs-*` styling. Hosts own plugin loading, vault
13
+ state, persistence, and application policy.
14
+
15
+ [![Docs workspace](registry-assets/banner.preview.png)](registry-assets/banner.full.png)
16
+
17
+ <details>
18
+ <summary>Plugin screenshots</summary>
19
+
20
+ [![Structured reading](registry-assets/gallery/reading.preview.png)](registry-assets/gallery/reading.full.png)
21
+
22
+ [![Cards workspace](registry-assets/gallery/cards.preview.png)](registry-assets/gallery/cards.full.png)
23
+
24
+ </details>
25
+
26
+ ## Current package status
27
+
28
+ - Package version: `@lapis-notes/lapis-plugin-docs@0.1.0`.
29
+ - Runtime plugin id: `docs`.
30
+ - Runtime peers: `@lapis-notes/api@^0.2.6`,
31
+ `@lapismd/design-core@^0.12.1`, `@lapismd/mira@~0.1.4`,
32
+ `@lapismd/mira-editor@~0.0.3`, and `svelte@5.56.10`.
33
+ - Canonical repository: `lapismd/lapis-plugin-docs`.
34
+ - Live catalog: <https://lapismd.github.io/lapis-plugin-docs/>.
35
+ - Canonical requirements live in `spec/src/plugins/docs/`; verification
36
+ status is tracked in `spec/src/verification.md`.
37
+
38
+ ## Install
39
+
40
+ Hosts load the plugin class through the Lapis plugin lifecycle. `onload`
41
+ registers the Docs projection, document and sidebar views, commands, ribbon,
42
+ and settings.
43
+
44
+ ```sh
45
+ pnpm add @lapis-notes/lapis-plugin-docs
46
+ ```
47
+
48
+ Import the plugin stylesheet once at the application boundary:
49
+
50
+ ```ts
51
+ import "@lapis-notes/lapis-plugin-docs/styles.css";
52
+ ```
53
+
54
+ ## Runtime surfaces
55
+
56
+ | Surface | Entry | Use for |
57
+ | --- | --- | --- |
58
+ | Docs document | `*.doc.md` exclusive editor-view contribution | Structured editing, reading, slides, cards, and note-scoped review |
59
+ | Docs sidebar | Movable `docs` workspace view | Browse notes, folders, links, tags, due cards, and review queues |
60
+ | Projection | `docs/note` | Index Docs metadata and content from the configured vault root |
61
+ | Cards | Basic and cloze card panels | Create cards, inspect references, and manage scheduling metadata |
62
+ | Review | FSRS-backed note and workspace queues | Study due cards and persist review outcomes to the source note |
63
+ | Import | Lazy Anki package reader | Import supported `.apkg` collections and media into the vault |
64
+ | Settings | Versioned plugin data | Configure the Docs root, which defaults to `docs` |
65
+
66
+ ## Document and review coverage
67
+
68
+ Docs files are ordinary Markdown with YAML front matter. The filesystem is
69
+ authoritative: books order their chapters, wiki links and tags form a graph,
70
+ and review state travels with each card in its source document. Structured
71
+ reading uses the host `MarkdownRenderer` when available and public Mira
72
+ preview as the fallback.
73
+
74
+ The bundled sample book exercises structured blocks, Mermaid diagrams,
75
+ slides, links, tags, basic and cloze cards, due queues, and FSRS history. The
76
+ same deterministic fixtures power the package Storybook and the committed
77
+ README screenshots.
78
+
79
+ ## Styling contract
80
+
81
+ The plugin uses native CSS, Design Core semantic tokens, and Docs-owned
82
+ `docs-` classes with `--ui-docs-*` custom properties. Production sources stay
83
+ free of Tailwind utility strings (`pnpm check:no-tailwind`).
84
+
85
+ 1. Import `@lapis-notes/lapis-plugin-docs/styles.css` once.
86
+ 2. Theme through Design Core tokens and Docs custom properties.
87
+ 3. Keep package-owned surfaces independent of host-private selectors.
88
+
89
+ ## Layout conventions
90
+
91
+ ```text
92
+ src/
93
+ lib/ plugin class, views, repository, domain model, native CSS
94
+ stories/ App-backed shell, placement, and registry capture stories
95
+ fixtures/
96
+ sample-docs/ deterministic *.doc.md Storybook corpus
97
+ spec/
98
+ src/ canonical specification and verification evidence
99
+ ```
100
+
101
+ ## Usage example
102
+
103
+ A Docs document is Markdown with structured front matter:
104
+
105
+ ```markdown
106
+ ---
107
+ id: spaced-repetition
108
+ title: Spaced repetition
109
+ docType: revision
110
+ tags:
111
+ - learning/memory
112
+ cards:
113
+ - id: retrieval-practice
114
+ type: basic
115
+ status: active
116
+ prompt: Why use retrieval practice?
117
+ answer: Recalling an idea strengthens access to it.
118
+ ---
119
+
120
+ # Spaced repetition
121
+
122
+ Review material shortly before it would otherwise be forgotten.
123
+ ```
124
+
125
+ ## Storybook and local documentation
126
+
127
+ Run the local catalog (defaults to port 7040):
128
+
129
+ ```sh
130
+ pnpm storybook
131
+ pnpm storybook:stop
132
+ pnpm storybook:restart
133
+ ```
134
+
135
+ Build the static catalog:
136
+
137
+ ```sh
138
+ pnpm build-storybook
139
+ ```
140
+
141
+ `Plugins/Docs/Registry Screenshots` contains the deterministic workspace,
142
+ reading, and cards states used to refresh the committed README media. These
143
+ capture stories are intentionally separate from visual-regression baselines.
144
+
145
+ The canonical specification lives in `spec/src`. Validate it after protected
146
+ source, story, or presentation changes:
147
+
148
+ ```sh
149
+ pnpm exec spec-validator search "Storybook"
150
+ pnpm spec:check
151
+ ```
152
+
153
+ ### CI and local parity
154
+
155
+ CI runs specification, quality, unit, package, static Storybook, and sharded
156
+ Storybook interaction lanes on every pull request and push to `main`. The
157
+ static catalog is published to GitHub Pages from `main`.
158
+
159
+ `pnpm test:storybook` runs the Storybook Vitest project with Playwright.
160
+ Interaction and accessibility behaviour stays executable in the capture
161
+ stories; screenshot files are generated from their completed states.
162
+
163
+ ## Release and validation
164
+
165
+ Common validation commands:
166
+
167
+ ```sh
168
+ pnpm spec:first
169
+ pnpm spec:check
170
+ pnpm check
171
+ pnpm test
172
+ pnpm build
173
+ pnpm publint
174
+ pnpm test:storybook
175
+ pnpm build-storybook
176
+ ```
177
+
178
+ ## Further reading
179
+
180
+ | Resource | Use |
181
+ | --- | --- |
182
+ | [`spec/src/plugins/docs/index.md`](./spec/src/plugins/docs/index.md) | Canonical plugin ownership and package requirements |
183
+ | [`spec/src/plugins/docs/runtime.md`](./spec/src/plugins/docs/runtime.md) | Runtime, sidebar, Storybook, and import behaviour |
184
+ | [`spec/src/plugins/docs/notes.md`](./spec/src/plugins/docs/notes.md) | Document model and reading behaviour |
185
+ | [`spec/src/plugins/docs/cards.md`](./spec/src/plugins/docs/cards.md) | Cards and review behaviour |
186
+ | [`spec/src/spec-governance.md`](./spec/src/spec-governance.md) | Governance, validation, and discovery rules |
187
+ | [`spec/src/verification.md`](./spec/src/verification.md) | Requirement verification evidence |
188
+ | [`AGENTS.md`](./AGENTS.md) | Contributor and agent workflow |
189
+ | [`PROVENANCE.md`](./PROVENANCE.md) | Component provenance and exclusions |
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Block Markdown field. Document-mode MarkdownComposer replaces the
4
+ * CodeMirror markdown editor for prose and section bodies.
5
+ */
6
+ import DocsMarkdownField from "./DocsMarkdownField.svelte";
7
+
8
+ let {
9
+ value = $bindable(""),
10
+ placeholder = "Write with Markdown...",
11
+ ariaLabel = "Markdown block",
12
+ minRows: _minRows = 8,
13
+ compact: _compact = true,
14
+ floatingToc: _floatingToc = "off" as const,
15
+ sourcePath: _sourcePath = "",
16
+ attachmentUpload: _attachmentUpload,
17
+ }: {
18
+ value?: string;
19
+ placeholder?: string;
20
+ ariaLabel?: string;
21
+ minRows?: number;
22
+ compact?: boolean;
23
+ floatingToc?: "auto" | "off" | "always";
24
+ sourcePath?: string;
25
+ attachmentUpload?: unknown;
26
+ } = $props();
27
+ </script>
28
+
29
+ <DocsMarkdownField
30
+ {value}
31
+ label={ariaLabel}
32
+ showLabel={false}
33
+ {placeholder}
34
+ onChange={(next) => {
35
+ value = next;
36
+ }}
37
+ />
@@ -0,0 +1,13 @@
1
+ type $$ComponentProps = {
2
+ value?: string;
3
+ placeholder?: string;
4
+ ariaLabel?: string;
5
+ minRows?: number;
6
+ compact?: boolean;
7
+ floatingToc?: "auto" | "off" | "always";
8
+ sourcePath?: string;
9
+ attachmentUpload?: unknown;
10
+ };
11
+ declare const DocsBlockMarkdownEditor: import("svelte").Component<$$ComponentProps, {}, "value">;
12
+ type DocsBlockMarkdownEditor = ReturnType<typeof DocsBlockMarkdownEditor>;
13
+ export default DocsBlockMarkdownEditor;
@@ -0,0 +1,75 @@
1
+ <script lang="ts">
2
+ import { ReferencePicker } from "@lapismd/design-core/forms";
3
+ import {
4
+ docsBlockIdFromRef,
5
+ docsBlockReferenceIndex,
6
+ docsBlockRefMarker,
7
+ } from "../model/docs-card-context";
8
+ import type { DocsRevisionBlock } from "../model";
9
+
10
+ let {
11
+ blocks,
12
+ refs,
13
+ addOpen = $bindable(false),
14
+ onAddOpenChange = () => {},
15
+ onChange,
16
+ }: {
17
+ blocks: DocsRevisionBlock[];
18
+ refs: string[];
19
+ addOpen?: boolean;
20
+ onAddOpenChange?: (open: boolean) => void;
21
+ onChange: (refs: string[]) => void;
22
+ } = $props();
23
+
24
+ const referenceIndex = $derived(docsBlockReferenceIndex(blocks));
25
+ const pickerRefs = $derived(refs.map((id) => docsBlockRefMarker(id)));
26
+ </script>
27
+
28
+ <ReferencePicker
29
+ refs={pickerRefs}
30
+ {referenceIndex}
31
+ {addOpen}
32
+ addLabel="Add block"
33
+ addHeading="Block"
34
+ searchPlaceholder="Search note blocks..."
35
+ emptyLabel="No matching blocks."
36
+ unresolvedLabel="Missing block"
37
+ unresolvedDescription="This block is no longer on the note."
38
+ {onAddOpenChange}
39
+ onChange={(next) => onChange(next.map((ref) => docsBlockIdFromRef(ref)))}
40
+ >
41
+ {#snippet searchOption(reference)}
42
+ <span class="docs-block-ref-option">
43
+ <span class="docs-block-ref-option__title">{reference.label}</span>
44
+ {#if reference.excerpt}
45
+ <span class="docs-block-ref-option__snippet">{reference.excerpt}</span>
46
+ {/if}
47
+ </span>
48
+ {/snippet}
49
+ </ReferencePicker>
50
+
51
+ <style>
52
+ .docs-block-ref-option {
53
+ display: grid;
54
+ min-width: 0;
55
+ gap: 0.1rem;
56
+ }
57
+
58
+ .docs-block-ref-option__title {
59
+ overflow: hidden;
60
+ color: var(--foreground);
61
+ font-size: 0.75rem;
62
+ font-weight: 650;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ }
66
+
67
+ .docs-block-ref-option__snippet {
68
+ overflow: hidden;
69
+ color: var(--muted-foreground);
70
+ font-size: 0.72rem;
71
+ line-height: 1.35;
72
+ text-overflow: ellipsis;
73
+ white-space: nowrap;
74
+ }
75
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { DocsRevisionBlock } from "../model";
2
+ type $$ComponentProps = {
3
+ blocks: DocsRevisionBlock[];
4
+ refs: string[];
5
+ addOpen?: boolean;
6
+ onAddOpenChange?: (open: boolean) => void;
7
+ onChange: (refs: string[]) => void;
8
+ };
9
+ declare const DocsBlockRefPicker: import("svelte").Component<$$ComponentProps, {}, "addOpen">;
10
+ type DocsBlockRefPicker = ReturnType<typeof DocsBlockRefPicker>;
11
+ export default DocsBlockRefPicker;
@@ -0,0 +1,141 @@
1
+ <script lang="ts">
2
+ import PlusIcon from '@lucide/svelte/icons/plus';
3
+ import { EntryActions, type SearchableChoiceOption } from '@lapismd/design-core/forms';
4
+ import SearchableChoicePicker from './candidates/SearchableChoicePicker.svelte';
5
+ import { slugifyDocsId } from '../model/markdown';
6
+ import type { DocsBookMetadata } from '../model';
7
+
8
+ let {
9
+ book,
10
+ noteOptions = [],
11
+ onChange = () => {}
12
+ }: {
13
+ book: DocsBookMetadata;
14
+ noteOptions?: SearchableChoiceOption[];
15
+ onChange?: (book: DocsBookMetadata) => void;
16
+ } = $props();
17
+
18
+ function normalizeChapterId(value: string) {
19
+ const trimmed = value.trim();
20
+ if (!trimmed) return '';
21
+ return slugifyDocsId(trimmed, trimmed);
22
+ }
23
+
24
+ function setChapters(chapters: DocsBookMetadata['chapters']) {
25
+ onChange({ chapters });
26
+ }
27
+
28
+ function patchChapter(chapterIndex: number, noteId: string) {
29
+ setChapters(
30
+ book.chapters.map((chapter, index) =>
31
+ index === chapterIndex ? { noteId } : chapter
32
+ )
33
+ );
34
+ }
35
+
36
+ function addChapter() {
37
+ setChapters([...book.chapters, { noteId: '' }]);
38
+ }
39
+
40
+ function removeChapter(chapterIndex: number) {
41
+ setChapters(book.chapters.filter((_, index) => index !== chapterIndex));
42
+ }
43
+
44
+ function moveChapter(chapterIndex: number, direction: -1 | 1) {
45
+ const targetIndex = chapterIndex + direction;
46
+ if (targetIndex < 0 || targetIndex >= book.chapters.length) return;
47
+ const nextChapters = [...book.chapters];
48
+ const [chapter] = nextChapters.splice(chapterIndex, 1);
49
+ nextChapters.splice(targetIndex, 0, chapter);
50
+ setChapters(nextChapters);
51
+ }
52
+ </script>
53
+
54
+ <div class="docs-book-editor">
55
+ {#each book.chapters as chapter, chapterIndex (chapterIndex)}
56
+ <EntryActions
57
+ index={chapterIndex}
58
+ total={book.chapters.length}
59
+ removeLabel={`Remove chapter ${chapter.noteId || chapterIndex + 1}`}
60
+ onMove={(direction) => moveChapter(chapterIndex, direction)}
61
+ onRemove={() => removeChapter(chapterIndex)}
62
+ >
63
+ <div class="docs-book-editor__row">
64
+ <span>{chapterIndex + 1}</span>
65
+ <SearchableChoicePicker
66
+ value={chapter.noteId}
67
+ options={noteOptions}
68
+ placeholder="Select note"
69
+ searchPlaceholder="Search notes..."
70
+ emptyLabel="No notes found."
71
+ ariaLabel={`Book chapter ${chapterIndex + 1}`}
72
+ normalize={normalizeChapterId}
73
+ onChange={(noteId) => patchChapter(chapterIndex, noteId)}
74
+ />
75
+ </div>
76
+ </EntryActions>
77
+ {/each}
78
+ <button type="button" class="docs-book-editor__add" onclick={addChapter}>
79
+ <PlusIcon aria-hidden="true" />
80
+ <span>Add chapter</span>
81
+ </button>
82
+ </div>
83
+
84
+ <style>
85
+ .docs-book-editor {
86
+ display: grid;
87
+ gap: 0.4rem;
88
+ width: 100%;
89
+ min-width: 0;
90
+ }
91
+
92
+ .docs-book-editor__row {
93
+ display: grid;
94
+ grid-template-columns: 1.6rem minmax(0, 1fr);
95
+ align-items: center;
96
+ gap: 0.55rem;
97
+ min-width: 0;
98
+ padding-block: 0.2rem;
99
+ }
100
+
101
+ .docs-book-editor__row > span {
102
+ display: grid;
103
+ width: 1.35rem;
104
+ height: 1.35rem;
105
+ place-items: center;
106
+ border-radius: 999px;
107
+ background: color-mix(in srgb, currentColor 8%, transparent);
108
+ color: var(--muted-foreground);
109
+ font-size: 0.72rem;
110
+ font-weight: 650;
111
+ line-height: 1;
112
+ }
113
+
114
+ .docs-book-editor__add {
115
+ display: inline-flex;
116
+ align-items: center;
117
+ justify-content: center;
118
+ gap: 0.35rem;
119
+ width: 100%;
120
+ min-height: 2.1rem;
121
+ border: 1px dashed var(--border);
122
+ border-radius: 0.4rem;
123
+ background: transparent;
124
+ color: var(--muted-foreground);
125
+ font-size: 0.82rem;
126
+ font-weight: 650;
127
+ cursor: pointer;
128
+ }
129
+
130
+ .docs-book-editor__add:hover,
131
+ .docs-book-editor__add:focus-visible {
132
+ border-color: var(--ring);
133
+ color: var(--foreground);
134
+ outline: 0;
135
+ }
136
+
137
+ .docs-book-editor__add :global(svg) {
138
+ width: 0.95rem;
139
+ height: 0.95rem;
140
+ }
141
+ </style>
@@ -0,0 +1,10 @@
1
+ import { type SearchableChoiceOption } from '@lapismd/design-core/forms';
2
+ import type { DocsBookMetadata } from '../model';
3
+ type $$ComponentProps = {
4
+ book: DocsBookMetadata;
5
+ noteOptions?: SearchableChoiceOption[];
6
+ onChange?: (book: DocsBookMetadata) => void;
7
+ };
8
+ declare const DocsBookEditor: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type DocsBookEditor = ReturnType<typeof DocsBookEditor>;
10
+ export default DocsBookEditor;