@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
@@ -0,0 +1,48 @@
1
+ import './DocsWorkspace.css';
2
+ import './DocsCardsReview.css';
3
+ import type { Snippet } from 'svelte';
4
+ import { type YamlReviewDiff } from '@lapismd/design-core/forms';
5
+ import type { CreateDocsNoteInput, DocsCard, DocsNote, DocsNotePanel, DocsReviewRating, DocsReviewScope, DocsWorkspace, DocsWorkspaceIndex } from '../model';
6
+ type Props = {
7
+ workspace: DocsWorkspace | DocsWorkspaceIndex | null;
8
+ /** Full note for the active id; index rows are summaries only. */
9
+ activeNote?: DocsNote | null;
10
+ activeNoteId?: string | null;
11
+ activePanel?: DocsNotePanel;
12
+ activeCodingCardId?: string | null;
13
+ reviewScope?: DocsReviewScope;
14
+ previewMode?: boolean;
15
+ sidebarOpen?: boolean;
16
+ activeFolderTag?: string | null;
17
+ folderDisplayMode?: "panel" | "inline";
18
+ folderPanelCollapsed?: boolean;
19
+ loading?: boolean;
20
+ saving?: boolean;
21
+ error?: string | null;
22
+ onToggleSidebar?: () => void | Promise<void>;
23
+ onActiveNoteChange?: (noteId: string | null) => void;
24
+ onActivePanelChange?: (panel: DocsNotePanel) => void;
25
+ onActiveCodingCardChange?: (cardId: string | null) => void;
26
+ onReviewScopeChange?: (scope: DocsReviewScope) => void;
27
+ onPreviewModeChange?: (enabled: boolean) => void;
28
+ onActiveFolderTagChange?: (tag: string | null) => void;
29
+ onFolderPanelCollapsedChange?: (collapsed: boolean) => void;
30
+ onCreateNote?: (input?: CreateDocsNoteInput) => void | Promise<void>;
31
+ onSaveNote?: (note: DocsNote) => void | Promise<void>;
32
+ onDeleteNote?: (noteId: string) => void | Promise<void>;
33
+ onReviewCard?: (noteId: string, cardId: string, rating: DocsReviewRating) => void | Promise<void>;
34
+ onImportAnkiPackage?: (file: File) => void | Promise<void>;
35
+ onUploadAttachment?: (noteId: string, file: File) => Promise<string | null>;
36
+ /** Runtime media URL resolver for co-located docs images. */
37
+ resolveMediaUrl?: (relativePath: string) => string | Promise<string>;
38
+ loadingState?: Snippet;
39
+ emptyState?: Snippet<[() => void]>;
40
+ codingPractice?: Snippet<[DocsNote, DocsCard | null, (card: DocsCard) => void]>;
41
+ reviewContent?: Snippet;
42
+ reviewDiffs?: YamlReviewDiff[];
43
+ onUndoReview?: (id: string) => void;
44
+ onKeepReview?: (id: string) => void;
45
+ };
46
+ declare const DocsWorkspace: import("svelte").Component<Props, {}, "">;
47
+ type DocsWorkspace = ReturnType<typeof DocsWorkspace>;
48
+ export default DocsWorkspace;
@@ -0,0 +1,211 @@
1
+ <script lang="ts">
2
+ import BookOpenIcon from "@lucide/svelte/icons/book-open";
3
+ import ChevronsDownUpIcon from "@lucide/svelte/icons/chevrons-down-up";
4
+ import ChevronsUpDownIcon from "@lucide/svelte/icons/chevrons-up-down";
5
+ import ClipboardIcon from "@lucide/svelte/icons/clipboard";
6
+ import PencilIcon from "@lucide/svelte/icons/pencil";
7
+ import PlusIcon from "@lucide/svelte/icons/plus";
8
+ import PresentationIcon from "@lucide/svelte/icons/presentation";
9
+ import Trash2Icon from "@lucide/svelte/icons/trash-2";
10
+ import UploadIcon from "@lucide/svelte/icons/upload";
11
+
12
+ import type { DocsNote, DocsNotePanel } from '../model';
13
+ import type { DisplayMode } from "./docs-workspace-helpers";
14
+
15
+ let {
16
+ draftNote,
17
+ filenameDraft = $bindable(""),
18
+ yamlMode = false,
19
+ saving = false,
20
+ activePanel,
21
+ previewMode = false,
22
+ showCollapseAll = false,
23
+ hasCollapsedSections = false,
24
+ collapseAllDisabled = false,
25
+ displayMode = $bindable("document"),
26
+ renderedDisplayMarkdown = "",
27
+ onCommitFilename,
28
+ onYamlModeChange,
29
+ onPanelChange,
30
+ onPreviewModeChange = () => {},
31
+ onToggleAllSections = () => {},
32
+ onAddCard,
33
+ onImportAnkiPackage,
34
+ onCopyRenderedMarkdown = () => {},
35
+ onDeleteNote,
36
+ }: {
37
+ draftNote: DocsNote | null;
38
+ filenameDraft: string;
39
+ yamlMode?: boolean;
40
+ saving?: boolean;
41
+ activePanel: DocsNotePanel;
42
+ previewMode?: boolean;
43
+ showCollapseAll?: boolean;
44
+ hasCollapsedSections?: boolean;
45
+ collapseAllDisabled?: boolean;
46
+ displayMode?: DisplayMode;
47
+ renderedDisplayMarkdown?: string;
48
+ onCommitFilename: () => void | Promise<void>;
49
+ onYamlModeChange: (enabled: boolean) => void;
50
+ onPanelChange: (panel: DocsNotePanel) => void;
51
+ onPreviewModeChange?: (enabled: boolean) => void;
52
+ onToggleAllSections?: () => void;
53
+ onAddCard: () => void;
54
+ onImportAnkiPackage?: (file: File) => void | Promise<void>;
55
+ onCopyRenderedMarkdown?: () => void | Promise<void>;
56
+ onDeleteNote: () => void | Promise<void>;
57
+ } = $props();
58
+
59
+ function toggleDisplayMode() {
60
+ displayMode = displayMode === "slides" ? "document" : "slides";
61
+ }
62
+
63
+ const isPreviewActive = $derived(
64
+ activePanel === "display" || (activePanel === "cards" && previewMode),
65
+ );
66
+
67
+ function togglePreviewMode() {
68
+ if (activePanel === "cards") {
69
+ onPreviewModeChange(!previewMode);
70
+ return;
71
+ }
72
+ onPanelChange(activePanel === "display" ? "note" : "display");
73
+ }
74
+ </script>
75
+
76
+ <div class="docs-toolbar">
77
+ <div class="docs-toolbar__title">
78
+ <div>
79
+ {#if draftNote}
80
+ <input
81
+ class="docs-toolbar__filename-input"
82
+ bind:value={filenameDraft}
83
+ aria-label="Note filename"
84
+ spellcheck={false}
85
+ onblur={() => void onCommitFilename()}
86
+ onkeydown={(event) => {
87
+ if (event.key === "Enter") event.currentTarget.blur();
88
+ }}
89
+ />
90
+ {:else}
91
+ <h1>Docs</h1>
92
+ {/if}
93
+ </div>
94
+ </div>
95
+ <div class="docs-toolbar__actions">
96
+ {#if draftNote}
97
+ <button
98
+ type="button"
99
+ class="docs-yaml-switch"
100
+ role="switch"
101
+ aria-checked={yamlMode}
102
+ aria-label="YAML"
103
+ onclick={() => onYamlModeChange(!yamlMode)}
104
+ >
105
+ <span class="docs-yaml-switch-track" aria-hidden="true">
106
+ <span class="docs-yaml-switch-thumb"></span>
107
+ </span>
108
+ <span>YAML</span>
109
+ </button>
110
+ {#if activePanel !== "practice"}
111
+ <button
112
+ type="button"
113
+ class="docs-view-toggle"
114
+ aria-label={isPreviewActive ? "Switch to edit mode" : "Switch to preview mode"}
115
+ title={isPreviewActive ? "Switch to edit mode" : "Switch to preview mode"}
116
+ disabled={yamlMode}
117
+ onclick={togglePreviewMode}
118
+ >
119
+ {#if isPreviewActive}
120
+ <PencilIcon aria-hidden="true" />
121
+ {:else}
122
+ <BookOpenIcon aria-hidden="true" />
123
+ {/if}
124
+ </button>
125
+ {/if}
126
+ {#if showCollapseAll && !yamlMode}
127
+ <button
128
+ type="button"
129
+ class="docs-collapse-all-button"
130
+ aria-label={hasCollapsedSections ? "Expand all sections" : "Collapse all sections"}
131
+ title={hasCollapsedSections ? "Expand all sections" : "Collapse all sections"}
132
+ disabled={collapseAllDisabled}
133
+ onclick={onToggleAllSections}
134
+ >
135
+ {#if hasCollapsedSections}
136
+ <ChevronsUpDownIcon aria-hidden="true" />
137
+ {:else}
138
+ <ChevronsDownUpIcon aria-hidden="true" />
139
+ {/if}
140
+ </button>
141
+ {/if}
142
+ {#if activePanel === "display" && !yamlMode}
143
+ <button
144
+ type="button"
145
+ class="docs-display-mode-toggle"
146
+ aria-label={displayMode === "slides" ? "Switch to document view" : "Switch to slides view"}
147
+ title={displayMode === "slides" ? "Switch to document view" : "Switch to slides view"}
148
+ onclick={toggleDisplayMode}
149
+ >
150
+ {#if displayMode === "slides"}
151
+ <BookOpenIcon aria-hidden="true" />
152
+ <span>Document</span>
153
+ {:else}
154
+ <PresentationIcon aria-hidden="true" />
155
+ <span>Slides</span>
156
+ {/if}
157
+ </button>
158
+ <button
159
+ type="button"
160
+ class="docs-display-copy-button"
161
+ aria-label="Copy display markdown"
162
+ title="Copy display markdown"
163
+ disabled={!renderedDisplayMarkdown.trim()}
164
+ onclick={() => void onCopyRenderedMarkdown()}
165
+ >
166
+ <ClipboardIcon aria-hidden="true" />
167
+ </button>
168
+ {/if}
169
+ {/if}
170
+ {#if saving}
171
+ <span class="docs-save-status" aria-live="polite">Saving…</span>
172
+ {/if}
173
+ {#if onImportAnkiPackage}
174
+ <label
175
+ class="docs-import-anki-button"
176
+ aria-label="Import Anki package"
177
+ title="Import Anki package"
178
+ >
179
+ <UploadIcon aria-hidden="true" />
180
+ <input
181
+ class="docs-import-anki-input"
182
+ type="file"
183
+ accept=".apkg,application/octet-stream"
184
+ aria-label="Anki package file"
185
+ disabled={saving}
186
+ onchange={(event) => {
187
+ const input = event.currentTarget;
188
+ if (!(input instanceof HTMLInputElement)) return;
189
+ const file = input.files?.[0];
190
+ input.value = "";
191
+ if (file) void onImportAnkiPackage?.(file);
192
+ }}
193
+ />
194
+ </label>
195
+ {/if}
196
+ {#if activePanel === "cards" && !yamlMode && !previewMode}
197
+ <button type="button" disabled={!draftNote} onclick={onAddCard}>
198
+ <PlusIcon />
199
+ Add card
200
+ </button>
201
+ {/if}
202
+ <button
203
+ type="button"
204
+ disabled={!draftNote}
205
+ aria-label="Delete note"
206
+ onclick={onDeleteNote}
207
+ >
208
+ <Trash2Icon />
209
+ </button>
210
+ </div>
211
+ </div>
@@ -0,0 +1,27 @@
1
+ import type { DocsNote, DocsNotePanel } from '../model';
2
+ import type { DisplayMode } from "./docs-workspace-helpers";
3
+ type $$ComponentProps = {
4
+ draftNote: DocsNote | null;
5
+ filenameDraft: string;
6
+ yamlMode?: boolean;
7
+ saving?: boolean;
8
+ activePanel: DocsNotePanel;
9
+ previewMode?: boolean;
10
+ showCollapseAll?: boolean;
11
+ hasCollapsedSections?: boolean;
12
+ collapseAllDisabled?: boolean;
13
+ displayMode?: DisplayMode;
14
+ renderedDisplayMarkdown?: string;
15
+ onCommitFilename: () => void | Promise<void>;
16
+ onYamlModeChange: (enabled: boolean) => void;
17
+ onPanelChange: (panel: DocsNotePanel) => void;
18
+ onPreviewModeChange?: (enabled: boolean) => void;
19
+ onToggleAllSections?: () => void;
20
+ onAddCard: () => void;
21
+ onImportAnkiPackage?: (file: File) => void | Promise<void>;
22
+ onCopyRenderedMarkdown?: () => void | Promise<void>;
23
+ onDeleteNote: () => void | Promise<void>;
24
+ };
25
+ declare const DocsWorkspaceToolbar: import("svelte").Component<$$ComponentProps, {}, "displayMode" | "filenameDraft">;
26
+ type DocsWorkspaceToolbar = ReturnType<typeof DocsWorkspaceToolbar>;
27
+ export default DocsWorkspaceToolbar;
@@ -0,0 +1,114 @@
1
+ <script lang="ts">
2
+ /**
3
+ * DESIGN_CORE_CANDIDATE: ChoiceMenu — ported for Docs; promote to design-core/forms later.
4
+ */
5
+ let {
6
+ value,
7
+ options,
8
+ labels = {},
9
+ ariaLabel,
10
+ onChange = () => {},
11
+ }: {
12
+ value: string;
13
+ options: string[];
14
+ labels?: Record<string, string>;
15
+ ariaLabel: string;
16
+ onChange?: (value: string) => void;
17
+ } = $props();
18
+ </script>
19
+
20
+ <details class="cv-form-choice-menu">
21
+ <summary aria-label={ariaLabel}>{labels[value] ?? value}</summary>
22
+ <div>
23
+ {#each options as option (option)}
24
+ <button
25
+ type="button"
26
+ class:active={value === option}
27
+ onclick={(event) => {
28
+ onChange(option);
29
+ const details = event.currentTarget.closest("details");
30
+ if (details) details.open = false;
31
+ }}
32
+ >
33
+ {labels[option] ?? option}
34
+ </button>
35
+ {/each}
36
+ </div>
37
+ </details>
38
+
39
+ <style>
40
+ .cv-form-choice-menu {
41
+ position: relative;
42
+ width: fit-content;
43
+ max-width: 100%;
44
+ }
45
+
46
+ .cv-form-choice-menu summary {
47
+ display: inline-flex;
48
+ min-height: 1.65rem;
49
+ align-items: center;
50
+ border: 1px solid var(--cv-form-border, var(--kanban-border, var(--border)));
51
+ border-radius: 999px;
52
+ color: var(--cv-form-muted, var(--kanban-muted, var(--muted-foreground)));
53
+ cursor: pointer;
54
+ font-size: 0.75rem;
55
+ font-weight: 650;
56
+ list-style: none;
57
+ padding: 0 0.75rem;
58
+ }
59
+
60
+ .cv-form-choice-menu summary::-webkit-details-marker {
61
+ display: none;
62
+ }
63
+
64
+ .cv-form-choice-menu summary:hover,
65
+ .cv-form-choice-menu summary:focus-visible {
66
+ color: var(
67
+ --cv-form-foreground,
68
+ var(--kanban-foreground, var(--foreground))
69
+ );
70
+ outline: 0;
71
+ }
72
+
73
+ .cv-form-choice-menu > div {
74
+ position: absolute;
75
+ top: calc(100% + 0.3rem);
76
+ right: 0;
77
+ z-index: 30;
78
+ display: grid;
79
+ min-width: 10rem;
80
+ gap: 0.15rem;
81
+ border: 1px solid var(--cv-form-border, var(--kanban-border, var(--border)));
82
+ border-radius: 0.4rem;
83
+ background: var(--cv-form-popover, var(--kanban-card, var(--popover)));
84
+ box-shadow: 0 1rem 2rem
85
+ var(--cv-form-shadow, var(--kanban-shadow, rgb(15 23 42 / 12%)));
86
+ padding: 0.35rem;
87
+ }
88
+
89
+ .cv-form-choice-menu button {
90
+ min-height: 1.75rem;
91
+ border: 0;
92
+ border-radius: 0.25rem;
93
+ background: transparent;
94
+ color: var(
95
+ --cv-form-foreground,
96
+ var(--kanban-foreground, var(--foreground))
97
+ );
98
+ cursor: pointer;
99
+ font: inherit;
100
+ font-size: 0.8rem;
101
+ text-align: left;
102
+ padding: 0 0.5rem;
103
+ }
104
+
105
+ .cv-form-choice-menu button:hover,
106
+ .cv-form-choice-menu button:focus-visible,
107
+ .cv-form-choice-menu button.active {
108
+ background: var(
109
+ --cv-form-selection,
110
+ color-mix(in srgb, var(--card-color, var(--primary)) 12%, transparent)
111
+ );
112
+ outline: 0;
113
+ }
114
+ </style>
@@ -0,0 +1,10 @@
1
+ type $$ComponentProps = {
2
+ value: string;
3
+ options: string[];
4
+ labels?: Record<string, string>;
5
+ ariaLabel: string;
6
+ onChange?: (value: string) => void;
7
+ };
8
+ declare const ChoiceMenu: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type ChoiceMenu = ReturnType<typeof ChoiceMenu>;
10
+ export default ChoiceMenu;