@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.
- package/README.md +188 -2
- package/dist/docs/DocsBlockMarkdownEditor.svelte +37 -0
- package/dist/docs/DocsBlockMarkdownEditor.svelte.d.ts +13 -0
- package/dist/docs/DocsBlockRefPicker.svelte +75 -0
- package/dist/docs/DocsBlockRefPicker.svelte.d.ts +11 -0
- package/dist/docs/DocsBookEditor.svelte +141 -0
- package/dist/docs/DocsBookEditor.svelte.d.ts +10 -0
- package/dist/docs/DocsBookNavigation.svelte +838 -0
- package/dist/docs/DocsBookNavigation.svelte.d.ts +11 -0
- package/dist/docs/DocsBooksColumn.svelte +82 -0
- package/dist/docs/DocsBooksColumn.svelte.d.ts +10 -0
- package/dist/docs/DocsCardBackMatter.svelte +32 -0
- package/dist/docs/DocsCardBackMatter.svelte.d.ts +10 -0
- package/dist/docs/DocsCardBlockExtra.svelte +43 -0
- package/dist/docs/DocsCardBlockExtra.svelte.d.ts +9 -0
- package/dist/docs/DocsCardPreviewFlip.svelte +143 -0
- package/dist/docs/DocsCardPreviewFlip.svelte.d.ts +17 -0
- package/dist/docs/DocsCardPreviewStack.svelte +135 -0
- package/dist/docs/DocsCardPreviewStack.svelte.d.ts +13 -0
- package/dist/docs/DocsCardPrompt.svelte +33 -0
- package/dist/docs/DocsCardPrompt.svelte.d.ts +8 -0
- package/dist/docs/DocsCardReviewAnswer.svelte +45 -0
- package/dist/docs/DocsCardReviewAnswer.svelte.d.ts +8 -0
- package/dist/docs/DocsCardTagChips.svelte +19 -0
- package/dist/docs/DocsCardTagChips.svelte.d.ts +7 -0
- package/dist/docs/DocsCardsPanel.svelte +232 -0
- package/dist/docs/DocsCardsPanel.svelte.d.ts +17 -0
- package/dist/docs/DocsCardsReview.css +1050 -0
- package/dist/docs/DocsChapterFooter.svelte +248 -0
- package/dist/docs/DocsChapterFooter.svelte.d.ts +11 -0
- package/dist/docs/DocsChapterScrollRing.svelte +101 -0
- package/dist/docs/DocsChapterScrollRing.svelte.d.ts +6 -0
- package/dist/docs/DocsDisplayPanel.css +627 -0
- package/dist/docs/DocsDisplayPanel.svelte +78 -0
- package/dist/docs/DocsDisplayPanel.svelte.d.ts +16 -0
- package/dist/docs/DocsEditorPanel.css +325 -0
- package/dist/docs/DocsEditorPanel.svelte +570 -0
- package/dist/docs/DocsEditorPanel.svelte.d.ts +22 -0
- package/dist/docs/DocsFlipCard.svelte +68 -0
- package/dist/docs/DocsFlipCard.svelte.d.ts +8 -0
- package/dist/docs/DocsFolderDirectoryList.svelte +206 -0
- package/dist/docs/DocsFolderDirectoryList.svelte.d.ts +14 -0
- package/dist/docs/DocsFolderPanel.css +357 -0
- package/dist/docs/DocsFolderPanel.svelte +102 -0
- package/dist/docs/DocsFolderPanel.svelte.d.ts +17 -0
- package/dist/docs/DocsLinksPanel.css +61 -0
- package/dist/docs/DocsLinksPanel.svelte +55 -0
- package/dist/docs/DocsLinksPanel.svelte.d.ts +11 -0
- package/dist/docs/DocsMarkdownField.svelte +93 -0
- package/dist/docs/DocsMarkdownField.svelte.d.ts +11 -0
- package/dist/docs/DocsMarkdownPreview.svelte +278 -0
- package/dist/docs/DocsMarkdownPreview.svelte.d.ts +17 -0
- package/dist/docs/DocsReviewPanel.svelte +63 -0
- package/dist/docs/DocsReviewPanel.svelte.d.ts +11 -0
- package/dist/docs/DocsRichBlock.svelte +291 -0
- package/dist/docs/DocsRichBlock.svelte.d.ts +13 -0
- package/dist/docs/DocsRichDisplay.svelte +316 -0
- package/dist/docs/DocsRichDisplay.svelte.d.ts +14 -0
- package/dist/docs/DocsSlidesPreview.css +243 -0
- package/dist/docs/DocsSlidesPreview.svelte +206 -0
- package/dist/docs/DocsSlidesPreview.svelte.d.ts +10 -0
- package/dist/docs/DocsWorkspace.css +570 -0
- package/dist/docs/DocsWorkspace.svelte +831 -0
- package/dist/docs/DocsWorkspace.svelte.d.ts +48 -0
- package/dist/docs/DocsWorkspaceToolbar.svelte +211 -0
- package/dist/docs/DocsWorkspaceToolbar.svelte.d.ts +27 -0
- package/dist/docs/candidates/ChoiceMenu.svelte +114 -0
- package/dist/docs/candidates/ChoiceMenu.svelte.d.ts +10 -0
- package/dist/docs/candidates/FlipCardDeck.svelte +800 -0
- package/dist/docs/candidates/FlipCardDeck.svelte.d.ts +36 -0
- package/dist/docs/candidates/MarkdownFloatingToc.svelte +313 -0
- package/dist/docs/candidates/MarkdownFloatingToc.svelte.d.ts +14 -0
- package/dist/docs/candidates/SearchableChoicePicker.css +161 -0
- package/dist/docs/candidates/SearchableChoicePicker.svelte +208 -0
- package/dist/docs/candidates/SearchableChoicePicker.svelte.d.ts +19 -0
- package/dist/docs/candidates/StructuredTable.svelte +98 -0
- package/dist/docs/candidates/StructuredTable.svelte.d.ts +8 -0
- package/dist/docs/candidates/StructuredTableEditor.svelte +374 -0
- package/dist/docs/candidates/StructuredTableEditor.svelte.d.ts +12 -0
- package/dist/docs/candidates/TagEditor.svelte +31 -0
- package/dist/docs/candidates/TagEditor.svelte.d.ts +14 -0
- package/dist/docs/candidates/WorkspaceHistoryControls.svelte +112 -0
- package/dist/docs/candidates/WorkspaceHistoryControls.svelte.d.ts +8 -0
- package/dist/docs/candidates/markdown-floating-toc.css +151 -0
- package/dist/docs/candidates/markdown-floating-toc.d.ts +1 -0
- package/dist/docs/candidates/markdown-floating-toc.js +1 -0
- package/dist/docs/docs-anki-import.d.ts +34 -0
- package/dist/docs/docs-anki-import.js +516 -0
- package/dist/docs/docs-book-view-model.d.ts +9 -0
- package/dist/docs/docs-book-view-model.js +71 -0
- package/dist/docs/docs-card-answer-markdown.d.ts +1 -0
- package/dist/docs/docs-card-answer-markdown.js +63 -0
- package/dist/docs/docs-card-display.d.ts +10 -0
- package/dist/docs/docs-card-display.js +18 -0
- package/dist/docs/docs-display-focus.d.ts +7 -0
- package/dist/docs/docs-display-focus.js +42 -0
- package/dist/docs/docs-document-surface.d.ts +7 -0
- package/dist/docs/docs-document-surface.js +25 -0
- package/dist/docs/docs-folder-directory.d.ts +21 -0
- package/dist/docs/docs-folder-directory.js +56 -0
- package/dist/docs/docs-link-mode.d.ts +16 -0
- package/dist/docs/docs-link-mode.js +94 -0
- package/dist/docs/docs-workspace-helpers.d.ts +25 -0
- package/dist/docs/docs-workspace-helpers.js +195 -0
- package/dist/docs/docs.tokens.css +13 -0
- package/dist/docs/import-anki-package.d.ts +10 -0
- package/dist/docs/import-anki-package.js +30 -0
- package/dist/docs/lapis-markdown-extensions.d.ts +9 -0
- package/dist/docs/lapis-markdown-extensions.js +128 -0
- package/dist/docs/pin-reading-chrome.d.ts +4 -0
- package/dist/docs/pin-reading-chrome.js +32 -0
- package/dist/docs/sidebar/DocsFoldersSidebar.svelte +134 -0
- package/dist/docs/sidebar/DocsFoldersSidebar.svelte.d.ts +15 -0
- package/dist/docs/sidebar/DocsLinksSidebar.svelte +105 -0
- package/dist/docs/sidebar/DocsLinksSidebar.svelte.d.ts +11 -0
- package/dist/docs/sidebar/DocsSidebar.css +346 -0
- package/dist/docs/sidebar/DocsSidebar.svelte +430 -0
- package/dist/docs/sidebar/DocsSidebar.svelte.d.ts +18 -0
- package/dist/docs/sidebar/DocsSidebarHost.svelte +139 -0
- package/dist/docs/sidebar/DocsSidebarHost.svelte.d.ts +12 -0
- package/dist/docs/sidebar/DocsTagsSidebar.svelte +176 -0
- package/dist/docs/sidebar/DocsTagsSidebar.svelte.d.ts +12 -0
- package/dist/docs/sidebar/docs-book-note-tree.d.ts +23 -0
- package/dist/docs/sidebar/docs-book-note-tree.js +88 -0
- package/dist/docs/sidebar/docs-note-sort.d.ts +26 -0
- package/dist/docs/sidebar/docs-note-sort.js +54 -0
- package/dist/docs/sidebar/docs-sidebar-filters.d.ts +17 -0
- package/dist/docs/sidebar/docs-sidebar-filters.js +74 -0
- package/dist/docs/sidebar/docs-sidebar-ui-storage.d.ts +24 -0
- package/dist/docs/sidebar/docs-sidebar-ui-storage.js +87 -0
- package/dist/docs/sidebar/docs-source-folder-tree.d.ts +16 -0
- package/dist/docs/sidebar/docs-source-folder-tree.js +143 -0
- package/dist/docs/sidebar/docs-tag-tree.d.ts +17 -0
- package/dist/docs/sidebar/docs-tag-tree.js +84 -0
- package/dist/docs-cards-view.d.ts +18 -0
- package/dist/docs-cards-view.js +52 -0
- package/dist/docs-document-view.d.ts +24 -0
- package/dist/docs-document-view.js +127 -0
- package/dist/docs-document-workspace.svelte +215 -0
- package/dist/docs-document-workspace.svelte.d.ts +16 -0
- package/dist/docs-index.d.ts +5 -0
- package/dist/docs-index.js +49 -0
- package/dist/docs-path.d.ts +6 -0
- package/dist/docs-path.js +10 -0
- package/dist/docs-plugin.d.ts +21 -0
- package/dist/docs-plugin.js +140 -0
- package/dist/docs-repository.d.ts +15 -0
- package/dist/docs-repository.js +75 -0
- package/dist/docs-review-view.d.ts +18 -0
- package/dist/docs-review-view.js +52 -0
- package/dist/docs-settings-tab.d.ts +8 -0
- package/dist/docs-settings-tab.js +25 -0
- package/dist/docs-settings.d.ts +17 -0
- package/dist/docs-settings.js +38 -0
- package/dist/docs-view.d.ts +22 -0
- package/dist/docs-view.js +51 -0
- package/dist/docs-workspace.svelte +394 -0
- package/dist/docs-workspace.svelte.d.ts +15 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/model/book.d.ts +6 -0
- package/dist/model/book.js +101 -0
- package/dist/model/coding-runtime.d.ts +4 -0
- package/dist/model/coding-runtime.js +9 -0
- package/dist/model/docs-card-context.d.ts +32 -0
- package/dist/model/docs-card-context.js +89 -0
- package/dist/model/docs-card-preview-stack-motion.d.ts +51 -0
- package/dist/model/docs-card-preview-stack-motion.js +94 -0
- package/dist/model/docs-media-context.d.ts +9 -0
- package/dist/model/docs-media-context.js +18 -0
- package/dist/model/docs-note-list.d.ts +8 -0
- package/dist/model/docs-note-list.js +25 -0
- package/dist/model/docs-relative-media.d.ts +30 -0
- package/dist/model/docs-relative-media.js +116 -0
- package/dist/model/docs-review-constants.d.ts +4 -0
- package/dist/model/docs-review-constants.js +13 -0
- package/dist/model/fsrs.d.ts +14 -0
- package/dist/model/fsrs.js +153 -0
- package/dist/model/graph.d.ts +12 -0
- package/dist/model/graph.js +169 -0
- package/dist/model/index.d.ts +14 -0
- package/dist/model/index.js +14 -0
- package/dist/model/markdown-normalize.d.ts +11 -0
- package/dist/model/markdown-normalize.js +755 -0
- package/dist/model/markdown.d.ts +167 -0
- package/dist/model/markdown.js +365 -0
- package/dist/model/sample.d.ts +7 -0
- package/dist/model/sample.js +524 -0
- package/dist/model/types.d.ts +328 -0
- package/dist/model/types.js +1 -0
- package/dist/model/workspace.d.ts +6 -0
- package/dist/model/workspace.js +81 -0
- package/dist/storybook.css +52 -0
- package/dist/styles.css +1 -0
- package/manifest.json +11 -0
- package/package.json +147 -4
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DocsBookChapterNavigation, DocsBookNavigation } from '../model';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
book: DocsBookNavigation;
|
|
4
|
+
activeNoteId: string;
|
|
5
|
+
chapterNavigation?: DocsBookChapterNavigation | null;
|
|
6
|
+
variant?: 'toc' | 'floating';
|
|
7
|
+
onOpenNote?: (noteId: string) => void;
|
|
8
|
+
};
|
|
9
|
+
declare const DocsBookNavigation: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
10
|
+
type DocsBookNavigation = ReturnType<typeof DocsBookNavigation>;
|
|
11
|
+
export default DocsBookNavigation;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DocsBookNavigation, DocsNoteListItem } from "../model";
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
books = [],
|
|
6
|
+
notes = [],
|
|
7
|
+
activeNoteId = null,
|
|
8
|
+
onOpenNote = () => {},
|
|
9
|
+
}: {
|
|
10
|
+
books?: DocsBookNavigation[];
|
|
11
|
+
notes?: DocsNoteListItem[];
|
|
12
|
+
activeNoteId?: string | null;
|
|
13
|
+
onOpenNote?: (noteId: string) => void;
|
|
14
|
+
} = $props();
|
|
15
|
+
|
|
16
|
+
const claimedIds = $derived(
|
|
17
|
+
new Set(
|
|
18
|
+
books.flatMap((book) => [
|
|
19
|
+
book.indexNoteId,
|
|
20
|
+
...book.chapters.map((chapter) => chapter.noteId),
|
|
21
|
+
]),
|
|
22
|
+
),
|
|
23
|
+
);
|
|
24
|
+
const standaloneNotes = $derived(
|
|
25
|
+
notes.filter((note) => !claimedIds.has(note.id)),
|
|
26
|
+
);
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<nav class="docs-books" aria-label="Books">
|
|
30
|
+
{#if books.length}
|
|
31
|
+
{#each books as book (book.id)}
|
|
32
|
+
<section class="docs-books__book" aria-label={book.title}>
|
|
33
|
+
<button
|
|
34
|
+
type="button"
|
|
35
|
+
class="docs-books__index"
|
|
36
|
+
aria-current={activeNoteId === book.indexNoteId ? "page" : undefined}
|
|
37
|
+
onclick={() => onOpenNote(book.indexNoteId)}
|
|
38
|
+
>
|
|
39
|
+
{book.title}
|
|
40
|
+
</button>
|
|
41
|
+
<ol>
|
|
42
|
+
{#each book.chapters as chapter (chapter.index + chapter.noteId)}
|
|
43
|
+
<li>
|
|
44
|
+
{#if chapter.resolved}
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
aria-current={activeNoteId === chapter.noteId ? "page" : undefined}
|
|
48
|
+
onclick={() => onOpenNote(chapter.noteId)}
|
|
49
|
+
>
|
|
50
|
+
<span>{chapter.index + 1}</span>
|
|
51
|
+
{chapter.title}
|
|
52
|
+
</button>
|
|
53
|
+
{:else}
|
|
54
|
+
<span class="docs-books__missing">{chapter.title}</span>
|
|
55
|
+
{/if}
|
|
56
|
+
</li>
|
|
57
|
+
{/each}
|
|
58
|
+
</ol>
|
|
59
|
+
</section>
|
|
60
|
+
{/each}
|
|
61
|
+
{:else}
|
|
62
|
+
<p class="docs-books__empty">No books in this vault.</p>
|
|
63
|
+
{/if}
|
|
64
|
+
{#if standaloneNotes.length}
|
|
65
|
+
<section class="docs-books__book" aria-label="Notes">
|
|
66
|
+
<p>Notes</p>
|
|
67
|
+
<ol>
|
|
68
|
+
{#each standaloneNotes as note (note.id)}
|
|
69
|
+
<li>
|
|
70
|
+
<button
|
|
71
|
+
type="button"
|
|
72
|
+
aria-current={activeNoteId === note.id ? "page" : undefined}
|
|
73
|
+
onclick={() => onOpenNote(note.id)}
|
|
74
|
+
>
|
|
75
|
+
{note.title || note.id}
|
|
76
|
+
</button>
|
|
77
|
+
</li>
|
|
78
|
+
{/each}
|
|
79
|
+
</ol>
|
|
80
|
+
</section>
|
|
81
|
+
{/if}
|
|
82
|
+
</nav>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DocsBookNavigation, DocsNoteListItem } from "../model";
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
books?: DocsBookNavigation[];
|
|
4
|
+
notes?: DocsNoteListItem[];
|
|
5
|
+
activeNoteId?: string | null;
|
|
6
|
+
onOpenNote?: (noteId: string) => void;
|
|
7
|
+
};
|
|
8
|
+
declare const DocsBooksColumn: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type DocsBooksColumn = ReturnType<typeof DocsBooksColumn>;
|
|
10
|
+
export default DocsBooksColumn;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import DocsCardBlockExtra from './DocsCardBlockExtra.svelte';
|
|
3
|
+
import DocsCardReviewAnswer from './DocsCardReviewAnswer.svelte';
|
|
4
|
+
import { resolveCardBlockRefs } from '../model/docs-card-context';
|
|
5
|
+
import type { DocsCard, DocsRevisionBlock } from '../model';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
card,
|
|
9
|
+
noteSourcePath = '',
|
|
10
|
+
noteBlocks = [],
|
|
11
|
+
showExtras = false
|
|
12
|
+
}: {
|
|
13
|
+
card: DocsCard;
|
|
14
|
+
noteSourcePath?: string;
|
|
15
|
+
noteBlocks?: DocsRevisionBlock[];
|
|
16
|
+
showExtras?: boolean;
|
|
17
|
+
} = $props();
|
|
18
|
+
|
|
19
|
+
const blockResolution = $derived(resolveCardBlockRefs({ blocks: noteBlocks }, card.blockRefs));
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<DocsCardReviewAnswer {card} {noteSourcePath} />
|
|
23
|
+
|
|
24
|
+
{#if showExtras}
|
|
25
|
+
{#if blockResolution.resolved.length > 0 || blockResolution.missing.length > 0}
|
|
26
|
+
<DocsCardBlockExtra
|
|
27
|
+
blocks={blockResolution.resolved.map((item) => item.block)}
|
|
28
|
+
missingRefs={blockResolution.missing.map((item) => item.ref)}
|
|
29
|
+
sourcePath={noteSourcePath}
|
|
30
|
+
/>
|
|
31
|
+
{/if}
|
|
32
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DocsCard, DocsRevisionBlock } from '../model';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
card: DocsCard;
|
|
4
|
+
noteSourcePath?: string;
|
|
5
|
+
noteBlocks?: DocsRevisionBlock[];
|
|
6
|
+
showExtras?: boolean;
|
|
7
|
+
};
|
|
8
|
+
declare const DocsCardBackMatter: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type DocsCardBackMatter = ReturnType<typeof DocsCardBackMatter>;
|
|
10
|
+
export default DocsCardBackMatter;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { renderDocsBlockMarkdown } from '../model/markdown';
|
|
3
|
+
import type { DocsRevisionBlock } from '../model';
|
|
4
|
+
import DocsMarkdownPreview from './DocsMarkdownPreview.svelte';
|
|
5
|
+
import { BLOCK_TYPE_LABELS } from './docs-workspace-helpers';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
blocks = [],
|
|
9
|
+
missingRefs = [],
|
|
10
|
+
sourcePath = ''
|
|
11
|
+
}: {
|
|
12
|
+
blocks: DocsRevisionBlock[];
|
|
13
|
+
missingRefs?: string[];
|
|
14
|
+
sourcePath?: string;
|
|
15
|
+
} = $props();
|
|
16
|
+
|
|
17
|
+
function blockTitle(block: DocsRevisionBlock) {
|
|
18
|
+
return block.title?.trim() || BLOCK_TYPE_LABELS[block.type] || block.type;
|
|
19
|
+
}
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
{#if blocks.length > 0 || missingRefs.length > 0}
|
|
23
|
+
<section class="docs-card-extra docs-card-extra--blocks" aria-label="From note">
|
|
24
|
+
<h4 class="docs-card-extra__heading">From note</h4>
|
|
25
|
+
<div class="docs-card-extra__items">
|
|
26
|
+
{#each blocks as block (block.id)}
|
|
27
|
+
<article class="docs-card-extra__block">
|
|
28
|
+
<p class="docs-card-extra__block-label">{blockTitle(block)}</p>
|
|
29
|
+
<div class="docs-card-extra__block-body application-markdown-preview is-compact">
|
|
30
|
+
<DocsMarkdownPreview
|
|
31
|
+
compact
|
|
32
|
+
value={renderDocsBlockMarkdown(block, 3)}
|
|
33
|
+
{sourcePath}
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
</article>
|
|
37
|
+
{/each}
|
|
38
|
+
{#each missingRefs as ref (ref)}
|
|
39
|
+
<p class="docs-card-extra__missing">Missing block: {ref}</p>
|
|
40
|
+
{/each}
|
|
41
|
+
</div>
|
|
42
|
+
</section>
|
|
43
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DocsRevisionBlock } from '../model';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
blocks: DocsRevisionBlock[];
|
|
4
|
+
missingRefs?: string[];
|
|
5
|
+
sourcePath?: string;
|
|
6
|
+
};
|
|
7
|
+
declare const DocsCardBlockExtra: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type DocsCardBlockExtra = ReturnType<typeof DocsCardBlockExtra>;
|
|
9
|
+
export default DocsCardBlockExtra;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import EyeIcon from '@lucide/svelte/icons/eye';
|
|
3
|
+
import DocsCardBackMatter from './DocsCardBackMatter.svelte';
|
|
4
|
+
import DocsCardPrompt from './DocsCardPrompt.svelte';
|
|
5
|
+
import DocsCardTagChips from './DocsCardTagChips.svelte';
|
|
6
|
+
import { REVIEW_RATINGS, REVIEW_RATING_LABELS } from '../model/docs-review-constants';
|
|
7
|
+
import { formatDocsReviewInterval, previewDocsCardRatings } from '../model/fsrs';
|
|
8
|
+
import type { DocsCard, DocsRevisionBlock, DocsReviewRating } from '../model';
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
card,
|
|
12
|
+
noteTitle,
|
|
13
|
+
noteSourcePath = '',
|
|
14
|
+
dueAt,
|
|
15
|
+
noteBlocks = [],
|
|
16
|
+
revealed = false,
|
|
17
|
+
peek = false,
|
|
18
|
+
showIntervalPreview = false,
|
|
19
|
+
onReveal,
|
|
20
|
+
onHide,
|
|
21
|
+
onReview
|
|
22
|
+
}: {
|
|
23
|
+
card: DocsCard;
|
|
24
|
+
noteTitle: string;
|
|
25
|
+
noteSourcePath?: string;
|
|
26
|
+
dueAt?: string;
|
|
27
|
+
noteBlocks?: DocsRevisionBlock[];
|
|
28
|
+
revealed?: boolean;
|
|
29
|
+
peek?: boolean;
|
|
30
|
+
showIntervalPreview?: boolean;
|
|
31
|
+
onReveal?: () => void;
|
|
32
|
+
onHide?: () => void;
|
|
33
|
+
onReview?: (rating: DocsReviewRating) => void | Promise<void>;
|
|
34
|
+
} = $props();
|
|
35
|
+
|
|
36
|
+
const ratingPreviews = $derived(
|
|
37
|
+
showIntervalPreview && revealed && onReview ? previewDocsCardRatings(card) : null
|
|
38
|
+
);
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<div
|
|
42
|
+
class={`docs-review-flip docs-card-preview-flip ${!peek && revealed ? 'docs-review-flip--revealed' : ''}`}
|
|
43
|
+
data-card-type={card.type}
|
|
44
|
+
data-card-status={card.status}
|
|
45
|
+
data-peek={peek ? 'true' : undefined}
|
|
46
|
+
>
|
|
47
|
+
{#if peek}
|
|
48
|
+
<article class="docs-review-face docs-review-face--front docs-review-face--peek">
|
|
49
|
+
<div class="docs-review-face__meta">
|
|
50
|
+
<span class="docs-review-face__label">{noteTitle}</span>
|
|
51
|
+
{#if card.tags.length}
|
|
52
|
+
<DocsCardTagChips tags={card.tags} />
|
|
53
|
+
{:else if dueAt}
|
|
54
|
+
<span class="docs-review-face__label">Due {dueAt}</span>
|
|
55
|
+
{/if}
|
|
56
|
+
</div>
|
|
57
|
+
<div class="docs-review-face__scroll">
|
|
58
|
+
<div class="docs-review-face__prompt">
|
|
59
|
+
<span>Question</span>
|
|
60
|
+
<h3>
|
|
61
|
+
<DocsCardPrompt {card} />
|
|
62
|
+
</h3>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</article>
|
|
66
|
+
{:else}
|
|
67
|
+
<div class="docs-review-flip__inner">
|
|
68
|
+
<article class="docs-review-face docs-review-face--front" aria-hidden={revealed}>
|
|
69
|
+
<div class="docs-review-face__meta">
|
|
70
|
+
<span class="docs-review-face__label">{noteTitle}</span>
|
|
71
|
+
{#if card.tags.length}
|
|
72
|
+
<DocsCardTagChips tags={card.tags} />
|
|
73
|
+
{:else if dueAt}
|
|
74
|
+
<span class="docs-review-face__label">Due {dueAt}</span>
|
|
75
|
+
{/if}
|
|
76
|
+
</div>
|
|
77
|
+
<div class="docs-review-face__scroll">
|
|
78
|
+
<div class="docs-review-face__prompt">
|
|
79
|
+
<span>Question</span>
|
|
80
|
+
<h3>
|
|
81
|
+
<DocsCardPrompt {card} />
|
|
82
|
+
</h3>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="docs-review-face__actions">
|
|
86
|
+
<button
|
|
87
|
+
type="button"
|
|
88
|
+
class="docs-review-show-answer"
|
|
89
|
+
disabled={revealed}
|
|
90
|
+
onclick={() => onReveal?.()}
|
|
91
|
+
>
|
|
92
|
+
<EyeIcon aria-hidden="true" />
|
|
93
|
+
Show Answer
|
|
94
|
+
</button>
|
|
95
|
+
</div>
|
|
96
|
+
</article>
|
|
97
|
+
|
|
98
|
+
<article class="docs-review-face docs-review-face--back" aria-hidden={!revealed}>
|
|
99
|
+
<div class="docs-review-face__meta">
|
|
100
|
+
<span class="docs-review-face__label">Answer</span>
|
|
101
|
+
<span class="docs-review-face__label">{card.type}</span>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="docs-review-face__scroll">
|
|
104
|
+
<DocsCardBackMatter
|
|
105
|
+
{card}
|
|
106
|
+
{noteSourcePath}
|
|
107
|
+
{noteBlocks}
|
|
108
|
+
showExtras={revealed}
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
<div class="docs-review-face__actions">
|
|
112
|
+
{#if onReview}
|
|
113
|
+
<div class="docs-rating-grid" aria-label="Rate your recall">
|
|
114
|
+
{#each REVIEW_RATINGS as rating (rating)}
|
|
115
|
+
<button
|
|
116
|
+
type="button"
|
|
117
|
+
class={`docs-rating-button docs-rating-button--${rating}`}
|
|
118
|
+
disabled={!revealed}
|
|
119
|
+
onclick={() => void onReview(rating)}
|
|
120
|
+
>
|
|
121
|
+
<span class="docs-rating-button__label">{REVIEW_RATING_LABELS[rating]}</span>
|
|
122
|
+
{#if ratingPreviews}
|
|
123
|
+
<span class="docs-rating-button__interval">
|
|
124
|
+
{formatDocsReviewInterval(ratingPreviews[rating].due)}
|
|
125
|
+
</span>
|
|
126
|
+
{/if}
|
|
127
|
+
</button>
|
|
128
|
+
{/each}
|
|
129
|
+
</div>
|
|
130
|
+
{:else}
|
|
131
|
+
<button
|
|
132
|
+
type="button"
|
|
133
|
+
class="docs-review-show-answer docs-card-preview-question-button"
|
|
134
|
+
onclick={() => onHide?.()}
|
|
135
|
+
>
|
|
136
|
+
Show Question
|
|
137
|
+
</button>
|
|
138
|
+
{/if}
|
|
139
|
+
</div>
|
|
140
|
+
</article>
|
|
141
|
+
</div>
|
|
142
|
+
{/if}
|
|
143
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DocsCard, DocsRevisionBlock, DocsReviewRating } from '../model';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
card: DocsCard;
|
|
4
|
+
noteTitle: string;
|
|
5
|
+
noteSourcePath?: string;
|
|
6
|
+
dueAt?: string;
|
|
7
|
+
noteBlocks?: DocsRevisionBlock[];
|
|
8
|
+
revealed?: boolean;
|
|
9
|
+
peek?: boolean;
|
|
10
|
+
showIntervalPreview?: boolean;
|
|
11
|
+
onReveal?: () => void;
|
|
12
|
+
onHide?: () => void;
|
|
13
|
+
onReview?: (rating: DocsReviewRating) => void | Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
declare const DocsCardPreviewFlip: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
16
|
+
type DocsCardPreviewFlip = ReturnType<typeof DocsCardPreviewFlip>;
|
|
17
|
+
export default DocsCardPreviewFlip;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import FlipCardDeck, { type FlipCardDeckContext } from "./candidates/FlipCardDeck.svelte";
|
|
3
|
+
import DocsCardBackMatter from './DocsCardBackMatter.svelte';
|
|
4
|
+
import DocsCardPrompt from './DocsCardPrompt.svelte';
|
|
5
|
+
import DocsCardTagChips from './DocsCardTagChips.svelte';
|
|
6
|
+
import { REVIEW_RATINGS, REVIEW_RATING_LABELS } from '../model/docs-review-constants';
|
|
7
|
+
import { formatDocsReviewInterval, previewDocsCardRatings } from '../model/fsrs';
|
|
8
|
+
import type {
|
|
9
|
+
DocsCardStackItem,
|
|
10
|
+
DocsCardStackMode,
|
|
11
|
+
DocsReviewRating
|
|
12
|
+
} from '../model';
|
|
13
|
+
let {
|
|
14
|
+
items,
|
|
15
|
+
previewAnswerOpenById = $bindable({}),
|
|
16
|
+
ariaLabel = 'Card previews',
|
|
17
|
+
mode = 'browse',
|
|
18
|
+
initialIndex = 0,
|
|
19
|
+
blockSwipeWhenRevealed = false,
|
|
20
|
+
onReviewCard
|
|
21
|
+
}: {
|
|
22
|
+
items: DocsCardStackItem[];
|
|
23
|
+
previewAnswerOpenById: Record<string, boolean>;
|
|
24
|
+
ariaLabel?: string;
|
|
25
|
+
mode?: DocsCardStackMode;
|
|
26
|
+
initialIndex?: number;
|
|
27
|
+
blockSwipeWhenRevealed?: boolean;
|
|
28
|
+
onReviewCard?: (
|
|
29
|
+
noteId: string,
|
|
30
|
+
cardId: string,
|
|
31
|
+
rating: DocsReviewRating
|
|
32
|
+
) => void | Promise<void>;
|
|
33
|
+
} = $props();
|
|
34
|
+
|
|
35
|
+
function keyFor(item: unknown) {
|
|
36
|
+
return (item as DocsCardStackItem).key;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function ratingPreviewsFor(item: DocsCardStackItem, revealed: boolean) {
|
|
40
|
+
return mode === 'study' && revealed && onReviewCard
|
|
41
|
+
? previewDocsCardRatings(item.card)
|
|
42
|
+
: null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function reviewItem(
|
|
46
|
+
item: DocsCardStackItem,
|
|
47
|
+
rating: DocsReviewRating,
|
|
48
|
+
context: FlipCardDeckContext
|
|
49
|
+
) {
|
|
50
|
+
if (!onReviewCard || !item.noteId) return;
|
|
51
|
+
await onReviewCard(item.noteId, item.card.id, rating);
|
|
52
|
+
context.hide();
|
|
53
|
+
if (mode === 'study') context.reset();
|
|
54
|
+
}
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<div class="docs-card-preview-stack">
|
|
58
|
+
<FlipCardDeck
|
|
59
|
+
{items}
|
|
60
|
+
{keyFor}
|
|
61
|
+
bind:revealedByKey={previewAnswerOpenById}
|
|
62
|
+
{ariaLabel}
|
|
63
|
+
mode={mode as 'browse' | 'study'}
|
|
64
|
+
{initialIndex}
|
|
65
|
+
{blockSwipeWhenRevealed}
|
|
66
|
+
emptyLabel="No cards yet."
|
|
67
|
+
>
|
|
68
|
+
{#snippet front(item, context)}
|
|
69
|
+
{@const stackItem = item as DocsCardStackItem}
|
|
70
|
+
<div
|
|
71
|
+
class="docs-review-face__content docs-review-face__content--front"
|
|
72
|
+
id={stackItem.noteId ? `docs-card-${stackItem.noteId}-${stackItem.card.id}` : undefined}
|
|
73
|
+
>
|
|
74
|
+
<div class="docs-review-face__meta">
|
|
75
|
+
<span class="docs-review-face__label">{stackItem.noteTitle}</span>
|
|
76
|
+
{#if stackItem.card.tags.length}
|
|
77
|
+
<DocsCardTagChips tags={stackItem.card.tags} />
|
|
78
|
+
{:else if stackItem.dueAt}
|
|
79
|
+
<span class="docs-review-face__label">Due {stackItem.dueAt}</span>
|
|
80
|
+
{/if}
|
|
81
|
+
</div>
|
|
82
|
+
<div class="docs-review-face__prompt">
|
|
83
|
+
<span>Question</span>
|
|
84
|
+
<h3>
|
|
85
|
+
<DocsCardPrompt card={stackItem.card} />
|
|
86
|
+
</h3>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
{/snippet}
|
|
90
|
+
|
|
91
|
+
{#snippet back(item, context)}
|
|
92
|
+
{@const stackItem = item as DocsCardStackItem}
|
|
93
|
+
<div class="docs-review-face__content docs-review-face__content--back">
|
|
94
|
+
<div class="docs-review-face__meta">
|
|
95
|
+
<span class="docs-review-face__label">Answer</span>
|
|
96
|
+
<span class="docs-review-face__label">{stackItem.card.type}</span>
|
|
97
|
+
</div>
|
|
98
|
+
<DocsCardBackMatter
|
|
99
|
+
card={stackItem.card}
|
|
100
|
+
noteSourcePath={stackItem.noteSourcePath}
|
|
101
|
+
noteBlocks={stackItem.noteBlocks ?? []}
|
|
102
|
+
showExtras={context.revealed}
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
{/snippet}
|
|
106
|
+
|
|
107
|
+
{#snippet backActions(item, context)}
|
|
108
|
+
{@const stackItem = item as DocsCardStackItem}
|
|
109
|
+
{@const ratingPreviews = ratingPreviewsFor(stackItem, context.revealed)}
|
|
110
|
+
{#if onReviewCard && stackItem.noteId}
|
|
111
|
+
<div class="docs-rating-grid" aria-label="Rate your recall">
|
|
112
|
+
{#each REVIEW_RATINGS as rating (rating)}
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
class={`docs-rating-button docs-rating-button--${rating}`}
|
|
116
|
+
disabled={!context.revealed}
|
|
117
|
+
onclick={() => void reviewItem(stackItem, rating, context)}
|
|
118
|
+
>
|
|
119
|
+
<span class="docs-rating-button__label">{REVIEW_RATING_LABELS[rating]}</span>
|
|
120
|
+
{#if ratingPreviews}
|
|
121
|
+
<span class="docs-rating-button__interval">
|
|
122
|
+
{formatDocsReviewInterval(ratingPreviews[rating].due)}
|
|
123
|
+
</span>
|
|
124
|
+
{/if}
|
|
125
|
+
</button>
|
|
126
|
+
{/each}
|
|
127
|
+
</div>
|
|
128
|
+
{:else}
|
|
129
|
+
<button type="button" class="flip-card-deck__primary-action docs-card-preview-question-button" onclick={context.hide}>
|
|
130
|
+
Show Question
|
|
131
|
+
</button>
|
|
132
|
+
{/if}
|
|
133
|
+
{/snippet}
|
|
134
|
+
</FlipCardDeck>
|
|
135
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DocsCardStackItem, DocsCardStackMode, DocsReviewRating } from '../model';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
items: DocsCardStackItem[];
|
|
4
|
+
previewAnswerOpenById: Record<string, boolean>;
|
|
5
|
+
ariaLabel?: string;
|
|
6
|
+
mode?: DocsCardStackMode;
|
|
7
|
+
initialIndex?: number;
|
|
8
|
+
blockSwipeWhenRevealed?: boolean;
|
|
9
|
+
onReviewCard?: (noteId: string, cardId: string, rating: DocsReviewRating) => void | Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
declare const DocsCardPreviewStack: import("svelte").Component<$$ComponentProps, {}, "previewAnswerOpenById">;
|
|
12
|
+
type DocsCardPreviewStack = ReturnType<typeof DocsCardPreviewStack>;
|
|
13
|
+
export default DocsCardPreviewStack;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { docsCardQuestionParts } from './docs-card-display';
|
|
3
|
+
import type { DocsCard } from '../model';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
card,
|
|
7
|
+
revealClozes = false
|
|
8
|
+
}: {
|
|
9
|
+
card: DocsCard;
|
|
10
|
+
revealClozes?: boolean;
|
|
11
|
+
} = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#each docsCardQuestionParts(card) as part}
|
|
15
|
+
{#if part.kind === 'cloze'}
|
|
16
|
+
<span
|
|
17
|
+
class={revealClozes
|
|
18
|
+
? 'docs-cloze-gap docs-cloze-gap--revealed'
|
|
19
|
+
: part.hint
|
|
20
|
+
? 'docs-cloze-gap docs-cloze-gap--hint'
|
|
21
|
+
: 'docs-cloze-gap'}
|
|
22
|
+
aria-label={revealClozes
|
|
23
|
+
? 'Revealed cloze answer'
|
|
24
|
+
: part.hint
|
|
25
|
+
? `Hidden cloze, hint: ${part.hint}`
|
|
26
|
+
: 'Hidden cloze'}
|
|
27
|
+
>
|
|
28
|
+
{revealClozes ? part.text : part.hint ?? ''}
|
|
29
|
+
</span>
|
|
30
|
+
{:else}
|
|
31
|
+
{part.text}
|
|
32
|
+
{/if}
|
|
33
|
+
{/each}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DocsCard } from '../model';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
card: DocsCard;
|
|
4
|
+
revealClozes?: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare const DocsCardPrompt: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type DocsCardPrompt = ReturnType<typeof DocsCardPrompt>;
|
|
8
|
+
export default DocsCardPrompt;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import BrainIcon from '@lucide/svelte/icons/brain';
|
|
3
|
+
import DocsCardPrompt from './DocsCardPrompt.svelte';
|
|
4
|
+
import DocsMarkdownPreview from './DocsMarkdownPreview.svelte';
|
|
5
|
+
import { docsCardAnswerMarkdown } from './docs-card-answer-markdown';
|
|
6
|
+
import type { DocsCard } from '../model';
|
|
7
|
+
|
|
8
|
+
let { card, noteSourcePath = '' }: { card: DocsCard; noteSourcePath?: string } = $props();
|
|
9
|
+
|
|
10
|
+
const renderedAnswer = $derived(docsCardAnswerMarkdown(card.answer));
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if card.type === 'cloze'}
|
|
14
|
+
<div class="docs-review-face__prompt docs-review-face__prompt--answer">
|
|
15
|
+
<h3>
|
|
16
|
+
<DocsCardPrompt {card} revealClozes />
|
|
17
|
+
</h3>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="docs-review-face__answer docs-review-face__answer--context">
|
|
20
|
+
<BrainIcon aria-hidden="true" />
|
|
21
|
+
<div>
|
|
22
|
+
<span class="docs-review-face__answer-label">Context</span>
|
|
23
|
+
<DocsMarkdownPreview
|
|
24
|
+
value={renderedAnswer}
|
|
25
|
+
empty="No additional context has been added yet."
|
|
26
|
+
compact
|
|
27
|
+
floatingToc="off"
|
|
28
|
+
sourcePath={noteSourcePath}
|
|
29
|
+
headingIdPrefix={`docs-card-${card.id}-answer`}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
{:else}
|
|
34
|
+
<div class="docs-review-face__answer">
|
|
35
|
+
<BrainIcon aria-hidden="true" />
|
|
36
|
+
<DocsMarkdownPreview
|
|
37
|
+
value={renderedAnswer}
|
|
38
|
+
empty="No answer has been added yet."
|
|
39
|
+
compact
|
|
40
|
+
floatingToc="off"
|
|
41
|
+
sourcePath={noteSourcePath}
|
|
42
|
+
headingIdPrefix={`docs-card-${card.id}-answer`}
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DocsCard } from '../model';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
card: DocsCard;
|
|
4
|
+
noteSourcePath?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const DocsCardReviewAnswer: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type DocsCardReviewAnswer = ReturnType<typeof DocsCardReviewAnswer>;
|
|
8
|
+
export default DocsCardReviewAnswer;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
let {
|
|
3
|
+
tags = [],
|
|
4
|
+
limit = 2
|
|
5
|
+
}: {
|
|
6
|
+
tags?: string[];
|
|
7
|
+
limit?: number;
|
|
8
|
+
} = $props();
|
|
9
|
+
|
|
10
|
+
const visibleTags = $derived(tags.slice(0, limit));
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if visibleTags.length}
|
|
14
|
+
<span class="docs-review-face__tags" aria-label="Tags">
|
|
15
|
+
{#each visibleTags as tag (tag)}
|
|
16
|
+
<span class="docs-review-face__tag">#{tag}</span>
|
|
17
|
+
{/each}
|
|
18
|
+
</span>
|
|
19
|
+
{/if}
|