@ecsplico/editor 3.2.0 → 3.3.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/CHANGELOG.md +7 -0
- package/dist/code/CodeSurface.vue.d.ts +3 -3
- package/dist/document/DocumentSurface.vue.d.ts +3 -3
- package/dist/features/ai/protocol/generate.d.ts +1 -1
- package/dist/features/composites/components/CompositeView.js +5 -1
- package/dist/features/composites/components/CompositeView.js.map +1 -1
- package/dist/features/composites/feature.js +12 -1
- package/dist/features/composites/feature.js.map +1 -1
- package/dist/features/composites/index.d.ts +2 -1
- package/dist/features/composites/index.js +2 -1
- package/dist/features/composites/kinds.d.ts +6 -1
- package/dist/features/composites/kinds.js.map +1 -1
- package/dist/features/composites/merge.d.ts +24 -0
- package/dist/features/composites/merge.js +47 -0
- package/dist/features/composites/merge.js.map +1 -0
- package/dist/features/composites/nodes.d.ts +1 -0
- package/dist/features/composites/nodes.js +1 -1
- package/dist/features/composites/nodes.js.map +1 -1
- package/dist/features/composites/react/CompositeView.js +4 -1
- package/dist/features/composites/react/CompositeView.js.map +1 -1
- package/dist/i18n/de/composites.js +1 -0
- package/dist/i18n/de/composites.js.map +1 -1
- package/dist/i18n/de/tree.js +1 -0
- package/dist/i18n/de/tree.js.map +1 -1
- package/dist/i18n/de.d.ts +2 -0
- package/dist/i18n/en/composites.js +1 -0
- package/dist/i18n/en/composites.js.map +1 -1
- package/dist/i18n/en/tree.js +1 -0
- package/dist/i18n/en/tree.js.map +1 -1
- package/dist/markdown/MarkdownSurface.vue.d.ts +7 -7
- package/dist/nuxt/module.d.ts +4 -0
- package/dist/server/handlers/ai.d.ts +3 -3
- package/dist/styles/composites.css +10 -1
- package/dist/tree/DocumentTree.js +20 -5
- package/dist/tree/DocumentTree.js.map +1 -1
- package/dist/tree/react/DocumentTree.js +12 -1
- package/dist/tree/react/DocumentTree.js.map +1 -1
- package/dist/tree/tree-host.js +10 -0
- package/dist/tree/tree-host.js.map +1 -1
- package/dist/tree/tree-items.js +1 -0
- package/dist/tree/tree-items.js.map +1 -1
- package/dist/tree/tree-model.js +9 -0
- package/dist/tree/tree-model.js.map +1 -1
- package/dist/vue/AdvancedEditor.vue.d.ts +4 -4
- package/dist/vue/SimpleEditor.vue.d.ts +4 -4
- package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
- package/package.json +1 -1
package/dist/i18n/en/tree.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","names":[],"sources":["../../../src/i18n/en/tree.ts"],"sourcesContent":["import type { de } from '../de/tree'\n\nexport const en: { [K in keyof typeof de]: string } = {\n 'tree.aria': 'Documents',\n 'tree.loading': 'Loading…',\n 'tree.loadFailed': 'Documents could not be loaded',\n 'tree.empty': 'No documents yet',\n 'tree.rootFallback': 'Document',\n 'tree.untitled': '(untitled)',\n 'tree.summary': 'Has a summary',\n 'tree.filter.show': 'Show',\n 'tree.filter.title': 'Filter view',\n 'tree.filter.reset': 'Reset filter',\n 'tree.add': 'Add',\n 'tree.delete': 'Delete',\n 'tree.menu.newDocument': 'New document',\n 'tree.menu.newFolder': 'New folder',\n 'tree.menu.newSubfolder': 'New subfolder',\n 'tree.menu.newCompositeFolder': 'New folder block',\n 'tree.menu.importFile': 'Import file…',\n 'tree.menu.rename': 'Rename',\n 'tree.folder.name': 'Folder name',\n 'tree.folder.placeholder': 'New folder',\n 'tree.folder.placeholderIn': 'New folder in {parent}',\n 'tree.folder.renameFailed': 'Folder not renamed',\n 'tree.removed': 'Document deleted',\n 'tree.undo': 'Undo',\n 'tree.filterText.placeholder': 'Filter by title',\n 'tree.filterText.clear': 'Clear title filter',\n 'tree.noMatches': 'No matches',\n 'tree.basketFilter.label': 'Filter by basket',\n 'tree.basketFilter.reset': 'Reset basket filter',\n 'tree.focus.root': 'Document',\n 'tree.focus.enter': 'Focus',\n 'tree.focus.leave': 'Leave focus',\n 'tree.root.folders': 'Folders',\n 'tree.root.file': 'File as root',\n 'tree.root.unavailable': 'Only with an open building-block file (setting “Structure: building blocks”).',\n\n 'tree.drop.nothing': 'Nothing is being dragged.',\n 'tree.drop.noDocumentMove': 'Documents and folders cannot be moved inside the open document.',\n 'tree.drop.foldersOnly': 'Only folders accept entries.',\n 'tree.drop.documentInFolder': 'The document is already in this folder.',\n 'tree.drop.folderIntoSelf': 'A folder cannot be moved into itself or one of its subfolders.',\n 'tree.drop.folderInFolder': 'The folder is already in this folder.',\n 'tree.drop.blocksOnlyInDocument': 'Building blocks can only be moved within the open document.',\n 'tree.drop.noBlocksHere': 'Building blocks cannot be dropped here.',\n 'tree.drop.noTransfer': 'This editor does not take building blocks from outside.',\n 'tree.drop.blockWithoutId': 'This building block has no ID yet and cannot be addressed as a target.',\n 'tree.drop.editorClosed': 'The editor is no longer open.',\n}\n"],"mappings":";AAEA,MAAa,KAAyC;CACpD,aAAa;CACb,gBAAgB;CAChB,mBAAmB;CACnB,cAAc;CACd,qBAAqB;CACrB,iBAAiB;CACjB,gBAAgB;CAChB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,YAAY;CACZ,eAAe;CACf,yBAAyB;CACzB,uBAAuB;CACvB,0BAA0B;CAC1B,gCAAgC;CAChC,wBAAwB;CACxB,oBAAoB;CACpB,oBAAoB;CACpB,2BAA2B;CAC3B,6BAA6B;CAC7B,4BAA4B;CAC5B,gBAAgB;CAChB,aAAa;CACb,+BAA+B;CAC/B,yBAAyB;CACzB,kBAAkB;CAClB,2BAA2B;CAC3B,2BAA2B;CAC3B,mBAAmB;CACnB,oBAAoB;CACpB,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,yBAAyB;CAEzB,qBAAqB;CACrB,4BAA4B;CAC5B,yBAAyB;CACzB,8BAA8B;CAC9B,4BAA4B;CAC5B,4BAA4B;CAC5B,kCAAkC;CAClC,0BAA0B;CAC1B,wBAAwB;CACxB,4BAA4B;CAC5B,0BAA0B;AAC5B"}
|
|
1
|
+
{"version":3,"file":"tree.js","names":[],"sources":["../../../src/i18n/en/tree.ts"],"sourcesContent":["import type { de } from '../de/tree'\n\nexport const en: { [K in keyof typeof de]: string } = {\n 'tree.aria': 'Documents',\n 'tree.loading': 'Loading…',\n 'tree.loadFailed': 'Documents could not be loaded',\n 'tree.empty': 'No documents yet',\n 'tree.rootFallback': 'Document',\n 'tree.untitled': '(untitled)',\n 'tree.summary': 'Has a summary',\n 'tree.filter.show': 'Show',\n 'tree.filter.title': 'Filter view',\n 'tree.filter.reset': 'Reset filter',\n 'tree.add': 'Add',\n 'tree.delete': 'Delete',\n 'tree.menu.newDocument': 'New document',\n 'tree.menu.newFolder': 'New folder',\n 'tree.menu.newSubfolder': 'New subfolder',\n 'tree.menu.newCompositeFolder': 'New folder block',\n 'tree.menu.importFile': 'Import file…',\n 'tree.menu.rename': 'Rename',\n 'tree.folder.name': 'Folder name',\n 'tree.folder.placeholder': 'New folder',\n 'tree.folder.placeholderIn': 'New folder in {parent}',\n 'tree.folder.renameFailed': 'Folder not renamed',\n 'tree.removed': 'Document deleted',\n 'tree.undo': 'Undo',\n 'tree.filterText.placeholder': 'Filter by title',\n 'tree.filterText.clear': 'Clear title filter',\n 'tree.noMatches': 'No matches',\n 'tree.basketFilter.label': 'Filter by basket',\n 'tree.basketFilter.reset': 'Reset basket filter',\n 'tree.focus.root': 'Document',\n 'tree.focus.enter': 'Focus',\n 'tree.focus.leave': 'Leave focus',\n 'tree.merge': 'Merge with next',\n 'tree.root.folders': 'Folders',\n 'tree.root.file': 'File as root',\n 'tree.root.unavailable': 'Only with an open building-block file (setting “Structure: building blocks”).',\n\n 'tree.drop.nothing': 'Nothing is being dragged.',\n 'tree.drop.noDocumentMove': 'Documents and folders cannot be moved inside the open document.',\n 'tree.drop.foldersOnly': 'Only folders accept entries.',\n 'tree.drop.documentInFolder': 'The document is already in this folder.',\n 'tree.drop.folderIntoSelf': 'A folder cannot be moved into itself or one of its subfolders.',\n 'tree.drop.folderInFolder': 'The folder is already in this folder.',\n 'tree.drop.blocksOnlyInDocument': 'Building blocks can only be moved within the open document.',\n 'tree.drop.noBlocksHere': 'Building blocks cannot be dropped here.',\n 'tree.drop.noTransfer': 'This editor does not take building blocks from outside.',\n 'tree.drop.blockWithoutId': 'This building block has no ID yet and cannot be addressed as a target.',\n 'tree.drop.editorClosed': 'The editor is no longer open.',\n}\n"],"mappings":";AAEA,MAAa,KAAyC;CACpD,aAAa;CACb,gBAAgB;CAChB,mBAAmB;CACnB,cAAc;CACd,qBAAqB;CACrB,iBAAiB;CACjB,gBAAgB;CAChB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,YAAY;CACZ,eAAe;CACf,yBAAyB;CACzB,uBAAuB;CACvB,0BAA0B;CAC1B,gCAAgC;CAChC,wBAAwB;CACxB,oBAAoB;CACpB,oBAAoB;CACpB,2BAA2B;CAC3B,6BAA6B;CAC7B,4BAA4B;CAC5B,gBAAgB;CAChB,aAAa;CACb,+BAA+B;CAC/B,yBAAyB;CACzB,kBAAkB;CAClB,2BAA2B;CAC3B,2BAA2B;CAC3B,mBAAmB;CACnB,oBAAoB;CACpB,oBAAoB;CACpB,cAAc;CACd,qBAAqB;CACrB,kBAAkB;CAClB,yBAAyB;CAEzB,qBAAqB;CACrB,4BAA4B;CAC5B,yBAAyB;CACzB,8BAA8B;CAC9B,4BAA4B;CAC5B,4BAA4B;CAC5B,kCAAkC;CAClC,0BAA0B;CAC1B,wBAAwB;CACxB,4BAA4B;CAC5B,0BAA0B;AAC5B"}
|
|
@@ -41,29 +41,29 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
41
41
|
settingsOpen: import("vue").WritableComputedRef<boolean, boolean>;
|
|
42
42
|
settingsTab: import("vue").WritableComputedRef<string | undefined, string | undefined>;
|
|
43
43
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
44
|
-
settingsOpen: (tab?: string | undefined) => any;
|
|
45
44
|
"update:sidebarOpen": (value: boolean) => any;
|
|
46
45
|
"update:commentsOpen": (value: boolean) => any;
|
|
47
|
-
"update:modelValue": (markdown: string) => any;
|
|
48
|
-
frontmatter: (frontmatter: string | null) => any;
|
|
49
46
|
ready: (editor: Editor) => any;
|
|
47
|
+
"update:modelValue": (markdown: string) => any;
|
|
50
48
|
metadataCreate: (list: string, item: MetadataItem) => any;
|
|
51
49
|
contentError: (error: Error) => any;
|
|
50
|
+
settingsOpen: (tab?: string | undefined) => any;
|
|
51
|
+
frontmatter: (frontmatter: string | null) => any;
|
|
52
52
|
diagnostics: (diagnostics: MarkdownDiagnostic[]) => any;
|
|
53
53
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
54
|
-
onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
|
|
55
54
|
"onUpdate:sidebarOpen"?: ((value: boolean) => any) | undefined;
|
|
56
55
|
"onUpdate:commentsOpen"?: ((value: boolean) => any) | undefined;
|
|
57
|
-
"onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
|
|
58
|
-
onFrontmatter?: ((frontmatter: string | null) => any) | undefined;
|
|
59
56
|
onReady?: ((editor: Editor) => any) | undefined;
|
|
57
|
+
"onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
|
|
60
58
|
onMetadataCreate?: ((list: string, item: MetadataItem) => any) | undefined;
|
|
61
59
|
onContentError?: ((error: Error) => any) | undefined;
|
|
60
|
+
onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
|
|
61
|
+
onFrontmatter?: ((frontmatter: string | null) => any) | undefined;
|
|
62
62
|
onDiagnostics?: ((diagnostics: MarkdownDiagnostic[]) => any) | undefined;
|
|
63
63
|
}>, {
|
|
64
|
+
modelValue: string;
|
|
64
65
|
editable: boolean;
|
|
65
66
|
settingsUi: "internal" | "external";
|
|
66
|
-
modelValue: string;
|
|
67
67
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
68
68
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
69
69
|
declare const _default: typeof __VLS_export;
|
package/dist/nuxt/module.d.ts
CHANGED
|
@@ -185,6 +185,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
|
|
|
185
185
|
"tree.focus.root"?: string | undefined;
|
|
186
186
|
"tree.focus.enter"?: string | undefined;
|
|
187
187
|
"tree.focus.leave"?: string | undefined;
|
|
188
|
+
"tree.merge"?: string | undefined;
|
|
188
189
|
"tree.root.folders"?: string | undefined;
|
|
189
190
|
"tree.root.file"?: string | undefined;
|
|
190
191
|
"tree.root.unavailable"?: string | undefined;
|
|
@@ -344,6 +345,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
|
|
|
344
345
|
"composites.split.children"?: string | undefined;
|
|
345
346
|
"composites.split.lengthChildren"?: string | undefined;
|
|
346
347
|
"composites.split.lengthSiblings"?: string | undefined;
|
|
348
|
+
"composites.merge.next"?: string | undefined;
|
|
347
349
|
"settings.editing.splitTargetChars"?: string | undefined;
|
|
348
350
|
"composites.toolbar.toKind"?: string | undefined;
|
|
349
351
|
"composites.toolbar.structure"?: string | undefined;
|
|
@@ -938,6 +940,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
|
|
|
938
940
|
"tree.focus.root"?: string | undefined;
|
|
939
941
|
"tree.focus.enter"?: string | undefined;
|
|
940
942
|
"tree.focus.leave"?: string | undefined;
|
|
943
|
+
"tree.merge"?: string | undefined;
|
|
941
944
|
"tree.root.folders"?: string | undefined;
|
|
942
945
|
"tree.root.file"?: string | undefined;
|
|
943
946
|
"tree.root.unavailable"?: string | undefined;
|
|
@@ -1097,6 +1100,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
|
|
|
1097
1100
|
"composites.split.children"?: string | undefined;
|
|
1098
1101
|
"composites.split.lengthChildren"?: string | undefined;
|
|
1099
1102
|
"composites.split.lengthSiblings"?: string | undefined;
|
|
1103
|
+
"composites.merge.next"?: string | undefined;
|
|
1100
1104
|
"settings.editing.splitTargetChars"?: string | undefined;
|
|
1101
1105
|
"composites.toolbar.toKind"?: string | undefined;
|
|
1102
1106
|
"composites.toolbar.structure"?: string | undefined;
|
|
@@ -11,9 +11,9 @@ export declare const chatBodySchema: z.ZodObject<{
|
|
|
11
11
|
feedback: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
12
12
|
op: z.ZodString;
|
|
13
13
|
type: z.ZodEnum<{
|
|
14
|
-
update: "update";
|
|
15
|
-
delete: "delete";
|
|
16
14
|
add: "add";
|
|
15
|
+
delete: "delete";
|
|
16
|
+
update: "update";
|
|
17
17
|
convert: "convert";
|
|
18
18
|
}>;
|
|
19
19
|
target: z.ZodNullable<z.ZodString>;
|
|
@@ -125,8 +125,8 @@ export declare const extractBodySchema: z.ZodObject<{
|
|
|
125
125
|
documentId: z.ZodString;
|
|
126
126
|
name: z.ZodOptional<z.ZodString>;
|
|
127
127
|
method: z.ZodEnum<{
|
|
128
|
-
description: "description";
|
|
129
128
|
transcription: "transcription";
|
|
129
|
+
description: "description";
|
|
130
130
|
bibliography: "bibliography";
|
|
131
131
|
auto: "auto";
|
|
132
132
|
"pdf-text": "pdf-text";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/* Styles of the composite feature (`@ecsplico/editor/composites`); import after `core.css`. */
|
|
2
2
|
/* Colour baskets (`compositeFeature({ baskets })`): the default set's colours, light and dark like `tokens.css` (the host sets
|
|
3
|
-
`.dark`). Declared under `:where()` (specificity 0), a host's rule always wins; a custom basket brings its own `color`.
|
|
3
|
+
`.dark`). Declared under `:where()` (specificity 0), a host's rule always wins; a custom basket brings its own `color`.
|
|
4
|
+
`--sk-kind-tone-mix` is how strongly a kind's tone (`CompositeKind.chrome.tone`) tints the Baustein surface. */
|
|
4
5
|
:where(:root) {
|
|
6
|
+
--sk-kind-tone-mix: 8%;
|
|
5
7
|
--sk-basket-red: #ef4444;
|
|
6
8
|
--sk-basket-orange: #f97316;
|
|
7
9
|
--sk-basket-yellow: #eab308;
|
|
@@ -10,6 +12,7 @@
|
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
:where(.dark) {
|
|
15
|
+
--sk-kind-tone-mix: 14%;
|
|
13
16
|
--sk-basket-red: #f87171;
|
|
14
17
|
--sk-basket-orange: #fb923c;
|
|
15
18
|
--sk-basket-yellow: #facc15;
|
|
@@ -26,6 +29,12 @@
|
|
|
26
29
|
padding-left: 1.25rem;
|
|
27
30
|
border-left: 2px solid var(--sk-border);
|
|
28
31
|
}
|
|
32
|
+
/* Kind tone: the node view sets `data-kind-tone` and `--sk-kind-tone` on a Baustein whose kind has `chrome.tone`; kinds without one are untouched.
|
|
33
|
+
Declared before the basket stripe, which wins on the border when both apply. */
|
|
34
|
+
.tiptap .composite[data-kind-tone] {
|
|
35
|
+
background: color-mix(in oklab, var(--sk-kind-tone) var(--sk-kind-tone-mix), transparent);
|
|
36
|
+
border-left-color: var(--sk-kind-tone);
|
|
37
|
+
}
|
|
29
38
|
/* The node view sets `--sk-basket-color` of a composite in a colour basket (`compositeFeature({ baskets })`); the colours of the default set are the tokens above. */
|
|
30
39
|
/* Basket stripe: the border takes the basket's colour; the inset shadow thickens it at every nesting depth without moving content. */
|
|
31
40
|
.tiptap .composite[data-basket] {
|
|
@@ -395,8 +395,9 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
395
395
|
}, null, 8, ["class", "onClick"])) : item.type === "composite" || item.type === "heading" ? (openBlock(), createElementBlock("span", _hoisted_17)) : createCommentVNode("v-if", true),
|
|
396
396
|
createVNode(unref(UIcon), {
|
|
397
397
|
name: item.icon,
|
|
398
|
-
class: "size-4 shrink-0"
|
|
399
|
-
|
|
398
|
+
class: "size-4 shrink-0",
|
|
399
|
+
style: normalizeStyle(item.tone ? { color: item.tone } : void 0)
|
|
400
|
+
}, null, 8, ["name", "style"]),
|
|
400
401
|
row(item).renaming ? (openBlock(), createElementBlock("div", _hoisted_18, [createVNode(unref(UInput), {
|
|
401
402
|
"model-value": row(item).renaming.draft,
|
|
402
403
|
size: "xs",
|
|
@@ -491,8 +492,22 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
491
492
|
"aria-label",
|
|
492
493
|
"onClick"
|
|
493
494
|
])) : createCommentVNode("v-if", true),
|
|
494
|
-
|
|
495
|
+
unref(model).canMerge(item) ? (openBlock(), createBlock(unref(UButton), {
|
|
495
496
|
key: 1,
|
|
497
|
+
icon: "i-lucide-merge",
|
|
498
|
+
size: "xs",
|
|
499
|
+
color: "neutral",
|
|
500
|
+
variant: "ghost",
|
|
501
|
+
title: unref(t)("tree.merge"),
|
|
502
|
+
"aria-label": unref(t)("tree.merge"),
|
|
503
|
+
onClick: ($event) => unref(model).merge(item)
|
|
504
|
+
}, null, 8, [
|
|
505
|
+
"title",
|
|
506
|
+
"aria-label",
|
|
507
|
+
"onClick"
|
|
508
|
+
])) : createCommentVNode("v-if", true),
|
|
509
|
+
addMenu(item).length ? (openBlock(), createBlock(unref(UDropdownMenu), {
|
|
510
|
+
key: 2,
|
|
496
511
|
items: addMenu(item),
|
|
497
512
|
content: {
|
|
498
513
|
align: "start",
|
|
@@ -512,9 +527,9 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
512
527
|
item.type === "document" ? renderSlot(_ctx.$slots, "document-actions", {
|
|
513
528
|
id: item.id,
|
|
514
529
|
title: item.label
|
|
515
|
-
}, void 0, void 0,
|
|
530
|
+
}, void 0, void 0, 3) : createCommentVNode("v-if", true),
|
|
516
531
|
item.type === "document" || item.type === "folder" ? (openBlock(), createBlock(unref(UButton), {
|
|
517
|
-
key:
|
|
532
|
+
key: 4,
|
|
518
533
|
icon: "i-lucide-trash-2",
|
|
519
534
|
size: "xs",
|
|
520
535
|
color: "error",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentTree.js","names":["_useModel","_openBlock","_createElementBlock","_createElementVNode","_createVNode","_unref","_withKeys","_createSlots","_withCtx","_createCommentVNode","_createBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle","_toDisplayString","_withModifiers","_createTextVNode","_renderSlot"],"sources":["../../src/tree/DocumentTree.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Editor } from '@tiptap/core'\nimport { computed } from 'vue'\nimport { BLOCK_MIME, blockTransferOf, readBlockTransfer, writeBlockTransfer } from '../core/block-transfer'\nimport { findBlockById } from '../core/schema/block-ids'\nimport type { DropdownItem } from '../vue/kit/types'\nimport { useUiKit } from '../vue/kit/use-ui-kit'\nimport { useEditorSettings } from '../vue/settings'\nimport { useEditorI18n } from '../vue/use-editor-i18n'\nimport type { DocumentStore } from './store'\nimport { basketById } from '../features/composites'\nimport { DRAG_MIME, focusCrumbs, itemBasket, type TreeItem } from './tree-items'\nimport { rowOf } from './tree-model'\nimport { useTreeModel } from './use-tree-model'\n\n// File browser of a document store: a „Dokumente“ root with folders and documents. It only renders the `TreeModel` (see\n// `tree-model.ts`), which owns what is open, filtered, selected, dragged and renamed; the React twin renders the same model.\n\nconst props = defineProps<{\n /** Where documents and folders live; the host implements it (see `DocumentStore`). */\n store: DocumentStore\n /** Editor of the open document (its outline is listed under the document); `undefined` while none is mounted. */\n editor: Editor | undefined\n}>()\n\ndefineSlots<{\n /** Host actions on a document row, rendered next to its delete button (e.g. a download link). */\n 'document-actions'?: (props: { id: string, title: string }) => unknown\n}>()\n\n/** The folder new documents, folders and host imports go to. Reset to `''` when it is deleted or moved away. */\nconst selectedFolder = defineModel<string>('selectedFolder', { default: '' })\n\nconst { t } = useEditorI18n()\nconst { Button: UButton, DropdownMenu: UDropdownMenu, Icon: UIcon, Input: UInput, Popover: UPopover, Tooltip: UTooltip, Tree: UTree } = useUiKit()\nconst { model, state } = useTreeModel({ store: () => props.store, editor: () => props.editor, selectedFolder })\nconst { settings } = useEditorSettings()\n\n// Mirrors the model's `isVirtual` rule: the file root only takes effect for a composite document that is open. Without\n// it the button is disabled (and says why) instead of letting the setting silently fall back to the folders.\nconst canUseFileRoot = computed(() => state.value.hasEditor && state.value.structure === 'composite')\n\nfunction toggleTreeRoot() {\n settings.value.blocks.treeRoot = settings.value.blocks.treeRoot === 'file' ? 'folders' : 'file'\n}\n\nconst row = (item: TreeItem) => rowOf(state.value, item, t)\n\n/** The basket `item` is in, when the open editor offers it (the row shows its colour as a dot). */\nconst basketOf = (item: TreeItem) => itemBasket(item, state.value.baskets)\n\n/** The basket filter button needs a live editor that offers baskets. */\nconst showBasketFilter = computed(() => state.value.hasEditor && state.value.baskets.length > 0)\n/** The chosen baskets the open editor offers (an unknown id never filters, see `TreeModel`). */\nconst shownBaskets = computed(() => state.value.basketFilter.filter(id => basketById(state.value.baskets, id)))\nconst basketOption = 'flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-[var(--sk-fg)] transition-colors duration-150 hover:bg-[var(--sk-bg-elevated)] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[var(--sk-primary)]'\n\n/** The breadcrumb of the focus: the document (first crumb, leaves focus) and the Bausteine down to the focused one. */\nconst breadcrumb = computed(() => focusCrumbs(state.value.focusPath))\n\n/** Why dropping the drag on `item` is refused, while the pointer is over it. */\nfunction refusal(item: TreeItem): string | null {\n const drop = row(item).drop\n return drop && !drop.ok ? drop.reason : null\n}\n\n/** UTree reports the keys of the rows it wants open; the model decides what that changes. */\nfunction onExpanded(next: string[]) {\n const wanted = new Set(next)\n const open = new Set(state.value.view.open)\n for (const key of wanted) if (!open.has(key)) model.value.setOpen(key, true)\n for (const key of open) if (!wanted.has(key)) model.value.setOpen(key, false)\n}\n\n/** The label split around the part the title filter matched, `null` when it did not match here. */\nfunction labelParts(item: TreeItem): [string, string, string] | null {\n const match = row(item).match\n if (!match) return null\n const [at, length] = match\n return [item.label.slice(0, at), item.label.slice(at, at + length), item.label.slice(at + length)]\n}\n\n// Folders and the root toggle through the tree's own row click; documents and outline entries (whose row click opens or\n// reveals) toggle through their chevron.\nfunction onChevronClick(event: Event, item: TreeItem) {\n if (item.type === 'root' || item.type === 'folder') return\n event.stopPropagation()\n model.value.toggle(item.key)\n}\n\nfunction filterMenu(item: TreeItem): DropdownItem[][] {\n const { filterKinds, hiddenKinds } = row(item)\n const groups: DropdownItem[][] = [[\n { type: 'label', label: t('tree.filter.show') },\n ...filterKinds.map<DropdownItem>(kind => ({\n label: kind.label,\n icon: kind.icon,\n type: 'checkbox',\n checked: !hiddenKinds.includes(kind.id),\n onUpdateChecked: visible => model.value.setKindHidden(item.key, kind.id, !visible),\n // Stay open: several kinds are usually toggled in one go.\n onSelect: event => event.preventDefault(),\n })),\n ]]\n if (hiddenKinds.length) groups.push([{ label: t('tree.filter.reset'), icon: 'i-lucide-filter-x', onSelect: () => model.value.clearFilter(item.key) }])\n return groups\n}\n\nfunction addMenu(item: TreeItem): DropdownItem[][] {\n return model.value.addMenu(item).map(group => group.map(entry => ({ label: entry.label, icon: entry.icon, onSelect: entry.run })))\n}\n\n// --- drag & drop -----------------------------------------------------------------------------------------------\n\nfunction onDragStart(event: DragEvent, item: TreeItem) {\n const payload = model.value.dragStart(item)\n if (!payload) return event.preventDefault()\n if (!event.dataTransfer) return model.value.dragEnd()\n event.dataTransfer.setData(DRAG_MIME, JSON.stringify(payload))\n // A Baustein row also carries the block itself, so another surface or tree can take a copy.\n const editor = props.editor\n const found = payload.type === 'composite' && editor && !editor.isDestroyed ? findBlockById(editor.state.doc, payload.blockId) : null\n const transfer = found && editor ? blockTransferOf(editor, found.pos) : null\n if (transfer) writeBlockTransfer(event.dataTransfer, transfer)\n event.dataTransfer.effectAllowed = transfer ? 'copyMove' : 'move'\n}\n\n/** A drag of this tree's own rows is running (a foreign drag is not). */\nconst ownDrag = () => !!state.value.drag && state.value.drag.source.type !== 'foreign-block'\n\nfunction onDragOver(event: DragEvent, item: TreeItem) {\n const foreign = !ownDrag() && !!event.dataTransfer?.types.includes(BLOCK_MIME)\n const verdict = foreign ? model.value.foreignDragOver(item) : model.value.dragOver(item)\n if (!verdict) return\n // Only an allowed target takes the drop; over a refused one the browser shows „not allowed“ and the row shows why.\n if (verdict.ok) event.preventDefault()\n if (event.dataTransfer) event.dataTransfer.dropEffect = verdict.ok ? (foreign ? 'copy' : 'move') : 'none'\n}\n\nfunction onDragLeave(event: DragEvent, item: TreeItem) {\n if (!(event.currentTarget as Node).contains(event.relatedTarget as Node | null)) model.value.dragLeave(item)\n}\n\nfunction onDrop(event: DragEvent, item: TreeItem) {\n if (ownDrag()) {\n event.preventDefault()\n return model.value.drop(item)\n }\n const payload = event.dataTransfer ? readBlockTransfer(event.dataTransfer) : null\n if (!payload) return\n event.preventDefault()\n return model.value.dropForeign(item, payload, event.shiftKey, event.clientX, event.clientY)\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center gap-1\">\n <UInput\n :model-value=\"state.filterText\"\n class=\"min-w-0 flex-1\"\n icon=\"i-lucide-search\"\n size=\"sm\"\n :placeholder=\"t('tree.filterText.placeholder')\"\n :aria-label=\"t('tree.filterText.placeholder')\"\n @update:model-value=\"model.setFilterText($event)\"\n @keydown.esc=\"model.setFilterText('')\"\n >\n <template v-if=\"state.filterText\" #trailing>\n <UButton\n icon=\"i-lucide-x\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"link\"\n :aria-label=\"t('tree.filterText.clear')\"\n @click=\"model.setFilterText('')\"\n />\n </template>\n </UInput>\n <!-- A popover, not a dropdown menu: a menu item cannot show a dot in an arbitrary CSS colour. -->\n <UPopover\n v-if=\"showBasketFilter\"\n :content=\"{ side: 'bottom', align: 'end', sideOffset: 4, onCloseAutoFocus: (event: Event) => event.preventDefault() }\"\n :ui=\"{ content: 'w-44 p-1' }\"\n >\n <UButton\n icon=\"i-lucide-paint-bucket\"\n size=\"xs\"\n :color=\"shownBaskets.length ? 'primary' : 'neutral'\"\n :variant=\"shownBaskets.length ? 'soft' : 'ghost'\"\n :title=\"t('tree.basketFilter.label')\"\n :aria-label=\"t('tree.basketFilter.label')\"\n />\n <template #content>\n <div role=\"menu\" :aria-label=\"t('tree.basketFilter.label')\">\n <button\n v-for=\"basket in state.baskets\"\n :key=\"basket.id\"\n type=\"button\"\n role=\"menuitemcheckbox\"\n :aria-checked=\"shownBaskets.includes(basket.id)\"\n :class=\"basketOption\"\n @click=\"model.setBasketShown(basket.id, !shownBaskets.includes(basket.id))\"\n >\n <span class=\"size-2.5 shrink-0 rounded-full\" :style=\"{ backgroundColor: basket.color }\" />\n <span class=\"truncate\">{{ basket.label }}</span>\n <UIcon v-if=\"shownBaskets.includes(basket.id)\" name=\"i-lucide-check\" class=\"ml-auto size-3.5 shrink-0\" />\n </button>\n <button v-if=\"shownBaskets.length\" type=\"button\" role=\"menuitem\" :class=\"basketOption\" @click=\"model.clearBasketFilter()\">\n <UIcon name=\"i-lucide-filter-x\" class=\"size-3.5 shrink-0 text-[var(--sk-muted)]\" />\n <span class=\"truncate\">{{ t('tree.basketFilter.reset') }}</span>\n </button>\n </div>\n </template>\n </UPopover>\n </div>\n\n <div class=\"flex items-center justify-end\">\n <UTooltip :text=\"canUseFileRoot ? '' : t('tree.root.unavailable')\">\n <!-- A disabled button swallows pointer events, so the tooltip hangs on the wrapper. -->\n <span class=\"inline-flex\">\n <UButton\n :icon=\"state.virtual ? 'i-lucide-file-stack' : 'i-lucide-folder-tree'\"\n :label=\"t(state.virtual ? 'tree.root.file' : 'tree.root.folders')\"\n size=\"xs\"\n color=\"neutral\"\n :variant=\"state.virtual ? 'soft' : 'ghost'\"\n :disabled=\"!canUseFileRoot\"\n :aria-pressed=\"state.virtual\"\n @click=\"toggleTreeRoot\"\n />\n </span>\n </UTooltip>\n </div>\n\n <div v-if=\"state.view.hasKindFilters\" class=\"flex items-center\">\n <UButton\n icon=\"i-lucide-filter-x\"\n :label=\"t('tree.filter.reset')\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"subtle\"\n @click=\"model.clearAllFilters\"\n />\n </div>\n\n <div v-if=\"state.creatingFolder\" class=\"flex flex-col gap-1\">\n <UInput\n :model-value=\"state.creatingFolder.draft\"\n size=\"sm\"\n autofocus\n :color=\"state.creatingFolder.error ? 'error' : undefined\"\n :highlight=\"!!state.creatingFolder.error\"\n :placeholder=\"state.creatingFolder.parent ? t('tree.folder.placeholderIn', { parent: state.creatingFolder.parent }) : t('tree.folder.placeholder')\"\n :aria-label=\"t('tree.folder.name')\"\n :aria-invalid=\"!!state.creatingFolder.error\"\n @update:model-value=\"model.setFolderDraft($event)\"\n @keydown.enter=\"model.commitCreateFolder\"\n @keydown.esc=\"model.cancelCreateFolder\"\n @blur=\"model.cancelCreateFolder\"\n />\n <p v-if=\"state.creatingFolder.error\" class=\"px-0.5 text-xs text-[var(--sk-danger)]\" role=\"alert\">\n {{ state.creatingFolder.error }}\n </p>\n </div>\n\n <div v-if=\"breadcrumb.crumbs.length\" class=\"flex flex-wrap items-center gap-0.5 text-xs\">\n <UButton\n icon=\"i-lucide-corner-up-left\"\n :label=\"breadcrumb.document?.label ?? t('tree.focus.root')\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"ghost\"\n :title=\"t('tree.focus.leave')\"\n :aria-label=\"t('tree.focus.leave')\"\n @click=\"model.defocus()\"\n />\n <template v-for=\"(crumb, index) in breadcrumb.crumbs\" :key=\"crumb.key\">\n <UIcon name=\"i-lucide-chevron-right\" class=\"size-3 shrink-0 text-[var(--sk-muted)]\" />\n <span v-if=\"index === breadcrumb.crumbs.length - 1\" class=\"min-w-0 truncate px-1.5 font-medium\" aria-current=\"location\">{{ crumb.label }}</span>\n <UButton v-else :label=\"crumb.label\" size=\"xs\" color=\"neutral\" variant=\"ghost\" @click=\"model.focus(crumb.key)\" />\n </template>\n </div>\n\n <p v-if=\"!state.tree && !state.virtual\" class=\"px-2.5 py-1.5 text-sm text-[var(--sk-muted)]\">\n {{ state.tree === null ? t('tree.loadFailed') : t('tree.loading') }}\n </p>\n\n <UTree\n v-else\n :expanded=\"state.view.open\"\n :items=\"state.view.items\"\n :get-key=\"(item: TreeItem) => item.key\"\n size=\"sm\"\n :aria-label=\"t('tree.aria')\"\n @update:expanded=\"onExpanded\"\n >\n <template #item-wrapper=\"{ item }: { item: TreeItem }\">\n <div class=\"w-full\">\n <div\n class=\"group flex w-full cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-sm select-none hover:bg-[color-mix(in_oklab,var(--sk-bg-elevated)_60%,transparent)]\"\n :class=\"[\n row(item).active && 'bg-[color-mix(in_oklab,var(--sk-primary)_10%,transparent)] font-medium text-[var(--sk-primary)]',\n row(item).selected && 'bg-[var(--sk-bg-elevated)]',\n row(item).drop?.ok && 'ring-1 ring-[var(--sk-primary)]',\n refusal(item) && 'bg-[color-mix(in_oklab,var(--sk-danger)_10%,transparent)] ring-1 ring-[var(--sk-danger)]',\n row(item).dimmed && 'opacity-60',\n ]\"\n :draggable=\"model.isDraggable(item)\"\n @dragstart=\"onDragStart($event, item)\"\n @dragover=\"onDragOver($event, item)\"\n @dragleave=\"onDragLeave($event, item)\"\n @drop=\"onDrop($event, item)\"\n @dragend=\"model.dragEnd\"\n >\n <UIcon\n v-if=\"row(item).expandable\"\n name=\"i-lucide-chevron-right\"\n class=\"size-3.5 shrink-0 text-[var(--sk-muted)] transition-transform\"\n :class=\"row(item).open && 'rotate-90'\"\n @click=\"onChevronClick($event, item)\"\n />\n <span v-else-if=\"item.type === 'composite' || item.type === 'heading'\" class=\"size-3.5 shrink-0\" />\n <UIcon :name=\"item.icon\" class=\"size-4 shrink-0\" />\n\n <div v-if=\"row(item).renaming\" class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <UInput\n :model-value=\"row(item).renaming!.draft\"\n size=\"xs\"\n class=\"min-w-0\"\n autofocus\n :color=\"row(item).renaming!.error ? 'error' : undefined\"\n :highlight=\"!!row(item).renaming!.error\"\n :aria-label=\"t('tree.folder.name')\"\n :aria-invalid=\"!!row(item).renaming!.error\"\n @update:model-value=\"model.setRenameDraft($event)\"\n @focus=\"($event.target as HTMLInputElement).select()\"\n @click.stop\n @keydown.stop\n @keydown.enter=\"model.commitRename\"\n @keydown.esc=\"model.cancelRename\"\n @blur=\"model.blurRename\"\n />\n <p v-if=\"row(item).renaming!.error\" class=\"text-xs text-[var(--sk-danger)]\" role=\"alert\" @click.stop>\n {{ row(item).renaming!.error }}\n </p>\n </div>\n <template v-else>\n <span\n v-if=\"basketOf(item)\"\n class=\"size-2 shrink-0 rounded-full\"\n :style=\"{ backgroundColor: basketOf(item)!.color }\"\n :title=\"basketOf(item)!.label\"\n :aria-label=\"basketOf(item)!.label\"\n role=\"img\"\n data-basket-dot\n />\n <span class=\"min-w-0 flex-1 truncate\" :title=\"item.label\">\n <template v-if=\"labelParts(item)\">{{ labelParts(item)![0] }}<mark class=\"rounded-sm bg-[color-mix(in_oklab,var(--sk-primary)_20%,transparent)] text-inherit\">{{ labelParts(item)![1] }}</mark>{{ labelParts(item)![2] }}</template>\n <template v-else>{{ item.label }}</template>\n </span>\n <UIcon\n v-if=\"item.hasSummary\"\n name=\"i-lucide-text-quote\"\n class=\"size-3.5 shrink-0 text-[var(--sk-muted)]\"\n :title=\"t('tree.summary')\"\n />\n <div class=\"flex shrink-0\" @click.stop>\n <UDropdownMenu v-if=\"row(item).showFilter\" :items=\"filterMenu(item)\" :content=\"{ align: 'start' }\">\n <UButton\n icon=\"i-lucide-filter\"\n size=\"xs\"\n :color=\"row(item).hiddenKinds.length ? 'primary' : 'neutral'\"\n :variant=\"row(item).hiddenKinds.length ? 'soft' : 'ghost'\"\n :class=\"!row(item).hiddenKinds.length && 'opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100'\"\n :title=\"t('tree.filter.title')\"\n :aria-label=\"t('tree.filter.title')\"\n />\n </UDropdownMenu>\n <div class=\"flex opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 has-data-[state=open]:opacity-100\">\n <UButton\n v-if=\"item.type === 'composite' && item.blockId\"\n icon=\"i-lucide-focus\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"ghost\"\n :title=\"t('tree.focus.enter')\"\n :aria-label=\"t('tree.focus.enter')\"\n @click=\"model.focus(item.key)\"\n />\n <UDropdownMenu v-if=\"addMenu(item).length\" :items=\"addMenu(item)\" :content=\"{ align: 'start', onCloseAutoFocus: (event: Event) => event.preventDefault() }\">\n <UButton\n icon=\"i-lucide-plus\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"ghost\"\n :title=\"t('tree.add')\"\n :aria-label=\"t('tree.add')\"\n />\n </UDropdownMenu>\n <slot v-if=\"item.type === 'document'\" name=\"document-actions\" :id=\"item.id!\" :title=\"item.label\" />\n <UButton\n v-if=\"item.type === 'document' || item.type === 'folder'\"\n icon=\"i-lucide-trash-2\"\n size=\"xs\"\n color=\"error\"\n variant=\"ghost\"\n :aria-label=\"t('tree.delete')\"\n loading-auto\n @click=\"model.remove(item)\"\n />\n </div>\n </div>\n </template>\n </div>\n <p v-if=\"refusal(item)\" class=\"px-2 pt-0.5 text-xs text-[var(--sk-danger)]\" role=\"status\">\n {{ refusal(item) }}\n </p>\n </div>\n </template>\n </UTree>\n\n <p v-if=\"state.view.noMatches\" class=\"px-2.5 py-1.5 text-sm text-[var(--sk-muted)]\">\n {{ t('tree.noMatches') }}\n </p>\n <p v-if=\"state.view.isEmpty\" class=\"px-2.5 py-1.5 text-sm text-[var(--sk-muted)]\">\n {{ t('tree.empty') }}\n </p>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocumentTree.js","names":["_useModel","_openBlock","_createElementBlock","_createElementVNode","_createVNode","_unref","_withKeys","_createSlots","_withCtx","_createCommentVNode","_createBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle","_toDisplayString","_withModifiers","_createTextVNode","_renderSlot"],"sources":["../../src/tree/DocumentTree.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Editor } from '@tiptap/core'\nimport { computed } from 'vue'\nimport { BLOCK_MIME, blockTransferOf, readBlockTransfer, writeBlockTransfer } from '../core/block-transfer'\nimport { findBlockById } from '../core/schema/block-ids'\nimport type { DropdownItem } from '../vue/kit/types'\nimport { useUiKit } from '../vue/kit/use-ui-kit'\nimport { useEditorSettings } from '../vue/settings'\nimport { useEditorI18n } from '../vue/use-editor-i18n'\nimport type { DocumentStore } from './store'\nimport { basketById } from '../features/composites'\nimport { DRAG_MIME, focusCrumbs, itemBasket, type TreeItem } from './tree-items'\nimport { rowOf } from './tree-model'\nimport { useTreeModel } from './use-tree-model'\n\n// File browser of a document store: a „Dokumente“ root with folders and documents. It only renders the `TreeModel` (see\n// `tree-model.ts`), which owns what is open, filtered, selected, dragged and renamed; the React twin renders the same model.\n\nconst props = defineProps<{\n /** Where documents and folders live; the host implements it (see `DocumentStore`). */\n store: DocumentStore\n /** Editor of the open document (its outline is listed under the document); `undefined` while none is mounted. */\n editor: Editor | undefined\n}>()\n\ndefineSlots<{\n /** Host actions on a document row, rendered next to its delete button (e.g. a download link). */\n 'document-actions'?: (props: { id: string, title: string }) => unknown\n}>()\n\n/** The folder new documents, folders and host imports go to. Reset to `''` when it is deleted or moved away. */\nconst selectedFolder = defineModel<string>('selectedFolder', { default: '' })\n\nconst { t } = useEditorI18n()\nconst { Button: UButton, DropdownMenu: UDropdownMenu, Icon: UIcon, Input: UInput, Popover: UPopover, Tooltip: UTooltip, Tree: UTree } = useUiKit()\nconst { model, state } = useTreeModel({ store: () => props.store, editor: () => props.editor, selectedFolder })\nconst { settings } = useEditorSettings()\n\n// Mirrors the model's `isVirtual` rule: the file root only takes effect for a composite document that is open. Without\n// it the button is disabled (and says why) instead of letting the setting silently fall back to the folders.\nconst canUseFileRoot = computed(() => state.value.hasEditor && state.value.structure === 'composite')\n\nfunction toggleTreeRoot() {\n settings.value.blocks.treeRoot = settings.value.blocks.treeRoot === 'file' ? 'folders' : 'file'\n}\n\nconst row = (item: TreeItem) => rowOf(state.value, item, t)\n\n/** The basket `item` is in, when the open editor offers it (the row shows its colour as a dot). */\nconst basketOf = (item: TreeItem) => itemBasket(item, state.value.baskets)\n\n/** The basket filter button needs a live editor that offers baskets. */\nconst showBasketFilter = computed(() => state.value.hasEditor && state.value.baskets.length > 0)\n/** The chosen baskets the open editor offers (an unknown id never filters, see `TreeModel`). */\nconst shownBaskets = computed(() => state.value.basketFilter.filter(id => basketById(state.value.baskets, id)))\nconst basketOption = 'flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-[var(--sk-fg)] transition-colors duration-150 hover:bg-[var(--sk-bg-elevated)] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[var(--sk-primary)]'\n\n/** The breadcrumb of the focus: the document (first crumb, leaves focus) and the Bausteine down to the focused one. */\nconst breadcrumb = computed(() => focusCrumbs(state.value.focusPath))\n\n/** Why dropping the drag on `item` is refused, while the pointer is over it. */\nfunction refusal(item: TreeItem): string | null {\n const drop = row(item).drop\n return drop && !drop.ok ? drop.reason : null\n}\n\n/** UTree reports the keys of the rows it wants open; the model decides what that changes. */\nfunction onExpanded(next: string[]) {\n const wanted = new Set(next)\n const open = new Set(state.value.view.open)\n for (const key of wanted) if (!open.has(key)) model.value.setOpen(key, true)\n for (const key of open) if (!wanted.has(key)) model.value.setOpen(key, false)\n}\n\n/** The label split around the part the title filter matched, `null` when it did not match here. */\nfunction labelParts(item: TreeItem): [string, string, string] | null {\n const match = row(item).match\n if (!match) return null\n const [at, length] = match\n return [item.label.slice(0, at), item.label.slice(at, at + length), item.label.slice(at + length)]\n}\n\n// Folders and the root toggle through the tree's own row click; documents and outline entries (whose row click opens or\n// reveals) toggle through their chevron.\nfunction onChevronClick(event: Event, item: TreeItem) {\n if (item.type === 'root' || item.type === 'folder') return\n event.stopPropagation()\n model.value.toggle(item.key)\n}\n\nfunction filterMenu(item: TreeItem): DropdownItem[][] {\n const { filterKinds, hiddenKinds } = row(item)\n const groups: DropdownItem[][] = [[\n { type: 'label', label: t('tree.filter.show') },\n ...filterKinds.map<DropdownItem>(kind => ({\n label: kind.label,\n icon: kind.icon,\n type: 'checkbox',\n checked: !hiddenKinds.includes(kind.id),\n onUpdateChecked: visible => model.value.setKindHidden(item.key, kind.id, !visible),\n // Stay open: several kinds are usually toggled in one go.\n onSelect: event => event.preventDefault(),\n })),\n ]]\n if (hiddenKinds.length) groups.push([{ label: t('tree.filter.reset'), icon: 'i-lucide-filter-x', onSelect: () => model.value.clearFilter(item.key) }])\n return groups\n}\n\nfunction addMenu(item: TreeItem): DropdownItem[][] {\n return model.value.addMenu(item).map(group => group.map(entry => ({ label: entry.label, icon: entry.icon, onSelect: entry.run })))\n}\n\n// --- drag & drop -----------------------------------------------------------------------------------------------\n\nfunction onDragStart(event: DragEvent, item: TreeItem) {\n const payload = model.value.dragStart(item)\n if (!payload) return event.preventDefault()\n if (!event.dataTransfer) return model.value.dragEnd()\n event.dataTransfer.setData(DRAG_MIME, JSON.stringify(payload))\n // A Baustein row also carries the block itself, so another surface or tree can take a copy.\n const editor = props.editor\n const found = payload.type === 'composite' && editor && !editor.isDestroyed ? findBlockById(editor.state.doc, payload.blockId) : null\n const transfer = found && editor ? blockTransferOf(editor, found.pos) : null\n if (transfer) writeBlockTransfer(event.dataTransfer, transfer)\n event.dataTransfer.effectAllowed = transfer ? 'copyMove' : 'move'\n}\n\n/** A drag of this tree's own rows is running (a foreign drag is not). */\nconst ownDrag = () => !!state.value.drag && state.value.drag.source.type !== 'foreign-block'\n\nfunction onDragOver(event: DragEvent, item: TreeItem) {\n const foreign = !ownDrag() && !!event.dataTransfer?.types.includes(BLOCK_MIME)\n const verdict = foreign ? model.value.foreignDragOver(item) : model.value.dragOver(item)\n if (!verdict) return\n // Only an allowed target takes the drop; over a refused one the browser shows „not allowed“ and the row shows why.\n if (verdict.ok) event.preventDefault()\n if (event.dataTransfer) event.dataTransfer.dropEffect = verdict.ok ? (foreign ? 'copy' : 'move') : 'none'\n}\n\nfunction onDragLeave(event: DragEvent, item: TreeItem) {\n if (!(event.currentTarget as Node).contains(event.relatedTarget as Node | null)) model.value.dragLeave(item)\n}\n\nfunction onDrop(event: DragEvent, item: TreeItem) {\n if (ownDrag()) {\n event.preventDefault()\n return model.value.drop(item)\n }\n const payload = event.dataTransfer ? readBlockTransfer(event.dataTransfer) : null\n if (!payload) return\n event.preventDefault()\n return model.value.dropForeign(item, payload, event.shiftKey, event.clientX, event.clientY)\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center gap-1\">\n <UInput\n :model-value=\"state.filterText\"\n class=\"min-w-0 flex-1\"\n icon=\"i-lucide-search\"\n size=\"sm\"\n :placeholder=\"t('tree.filterText.placeholder')\"\n :aria-label=\"t('tree.filterText.placeholder')\"\n @update:model-value=\"model.setFilterText($event)\"\n @keydown.esc=\"model.setFilterText('')\"\n >\n <template v-if=\"state.filterText\" #trailing>\n <UButton\n icon=\"i-lucide-x\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"link\"\n :aria-label=\"t('tree.filterText.clear')\"\n @click=\"model.setFilterText('')\"\n />\n </template>\n </UInput>\n <!-- A popover, not a dropdown menu: a menu item cannot show a dot in an arbitrary CSS colour. -->\n <UPopover\n v-if=\"showBasketFilter\"\n :content=\"{ side: 'bottom', align: 'end', sideOffset: 4, onCloseAutoFocus: (event: Event) => event.preventDefault() }\"\n :ui=\"{ content: 'w-44 p-1' }\"\n >\n <UButton\n icon=\"i-lucide-paint-bucket\"\n size=\"xs\"\n :color=\"shownBaskets.length ? 'primary' : 'neutral'\"\n :variant=\"shownBaskets.length ? 'soft' : 'ghost'\"\n :title=\"t('tree.basketFilter.label')\"\n :aria-label=\"t('tree.basketFilter.label')\"\n />\n <template #content>\n <div role=\"menu\" :aria-label=\"t('tree.basketFilter.label')\">\n <button\n v-for=\"basket in state.baskets\"\n :key=\"basket.id\"\n type=\"button\"\n role=\"menuitemcheckbox\"\n :aria-checked=\"shownBaskets.includes(basket.id)\"\n :class=\"basketOption\"\n @click=\"model.setBasketShown(basket.id, !shownBaskets.includes(basket.id))\"\n >\n <span class=\"size-2.5 shrink-0 rounded-full\" :style=\"{ backgroundColor: basket.color }\" />\n <span class=\"truncate\">{{ basket.label }}</span>\n <UIcon v-if=\"shownBaskets.includes(basket.id)\" name=\"i-lucide-check\" class=\"ml-auto size-3.5 shrink-0\" />\n </button>\n <button v-if=\"shownBaskets.length\" type=\"button\" role=\"menuitem\" :class=\"basketOption\" @click=\"model.clearBasketFilter()\">\n <UIcon name=\"i-lucide-filter-x\" class=\"size-3.5 shrink-0 text-[var(--sk-muted)]\" />\n <span class=\"truncate\">{{ t('tree.basketFilter.reset') }}</span>\n </button>\n </div>\n </template>\n </UPopover>\n </div>\n\n <div class=\"flex items-center justify-end\">\n <UTooltip :text=\"canUseFileRoot ? '' : t('tree.root.unavailable')\">\n <!-- A disabled button swallows pointer events, so the tooltip hangs on the wrapper. -->\n <span class=\"inline-flex\">\n <UButton\n :icon=\"state.virtual ? 'i-lucide-file-stack' : 'i-lucide-folder-tree'\"\n :label=\"t(state.virtual ? 'tree.root.file' : 'tree.root.folders')\"\n size=\"xs\"\n color=\"neutral\"\n :variant=\"state.virtual ? 'soft' : 'ghost'\"\n :disabled=\"!canUseFileRoot\"\n :aria-pressed=\"state.virtual\"\n @click=\"toggleTreeRoot\"\n />\n </span>\n </UTooltip>\n </div>\n\n <div v-if=\"state.view.hasKindFilters\" class=\"flex items-center\">\n <UButton\n icon=\"i-lucide-filter-x\"\n :label=\"t('tree.filter.reset')\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"subtle\"\n @click=\"model.clearAllFilters\"\n />\n </div>\n\n <div v-if=\"state.creatingFolder\" class=\"flex flex-col gap-1\">\n <UInput\n :model-value=\"state.creatingFolder.draft\"\n size=\"sm\"\n autofocus\n :color=\"state.creatingFolder.error ? 'error' : undefined\"\n :highlight=\"!!state.creatingFolder.error\"\n :placeholder=\"state.creatingFolder.parent ? t('tree.folder.placeholderIn', { parent: state.creatingFolder.parent }) : t('tree.folder.placeholder')\"\n :aria-label=\"t('tree.folder.name')\"\n :aria-invalid=\"!!state.creatingFolder.error\"\n @update:model-value=\"model.setFolderDraft($event)\"\n @keydown.enter=\"model.commitCreateFolder\"\n @keydown.esc=\"model.cancelCreateFolder\"\n @blur=\"model.cancelCreateFolder\"\n />\n <p v-if=\"state.creatingFolder.error\" class=\"px-0.5 text-xs text-[var(--sk-danger)]\" role=\"alert\">\n {{ state.creatingFolder.error }}\n </p>\n </div>\n\n <div v-if=\"breadcrumb.crumbs.length\" class=\"flex flex-wrap items-center gap-0.5 text-xs\">\n <UButton\n icon=\"i-lucide-corner-up-left\"\n :label=\"breadcrumb.document?.label ?? t('tree.focus.root')\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"ghost\"\n :title=\"t('tree.focus.leave')\"\n :aria-label=\"t('tree.focus.leave')\"\n @click=\"model.defocus()\"\n />\n <template v-for=\"(crumb, index) in breadcrumb.crumbs\" :key=\"crumb.key\">\n <UIcon name=\"i-lucide-chevron-right\" class=\"size-3 shrink-0 text-[var(--sk-muted)]\" />\n <span v-if=\"index === breadcrumb.crumbs.length - 1\" class=\"min-w-0 truncate px-1.5 font-medium\" aria-current=\"location\">{{ crumb.label }}</span>\n <UButton v-else :label=\"crumb.label\" size=\"xs\" color=\"neutral\" variant=\"ghost\" @click=\"model.focus(crumb.key)\" />\n </template>\n </div>\n\n <p v-if=\"!state.tree && !state.virtual\" class=\"px-2.5 py-1.5 text-sm text-[var(--sk-muted)]\">\n {{ state.tree === null ? t('tree.loadFailed') : t('tree.loading') }}\n </p>\n\n <UTree\n v-else\n :expanded=\"state.view.open\"\n :items=\"state.view.items\"\n :get-key=\"(item: TreeItem) => item.key\"\n size=\"sm\"\n :aria-label=\"t('tree.aria')\"\n @update:expanded=\"onExpanded\"\n >\n <template #item-wrapper=\"{ item }: { item: TreeItem }\">\n <div class=\"w-full\">\n <div\n class=\"group flex w-full cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-sm select-none hover:bg-[color-mix(in_oklab,var(--sk-bg-elevated)_60%,transparent)]\"\n :class=\"[\n row(item).active && 'bg-[color-mix(in_oklab,var(--sk-primary)_10%,transparent)] font-medium text-[var(--sk-primary)]',\n row(item).selected && 'bg-[var(--sk-bg-elevated)]',\n row(item).drop?.ok && 'ring-1 ring-[var(--sk-primary)]',\n refusal(item) && 'bg-[color-mix(in_oklab,var(--sk-danger)_10%,transparent)] ring-1 ring-[var(--sk-danger)]',\n row(item).dimmed && 'opacity-60',\n ]\"\n :draggable=\"model.isDraggable(item)\"\n @dragstart=\"onDragStart($event, item)\"\n @dragover=\"onDragOver($event, item)\"\n @dragleave=\"onDragLeave($event, item)\"\n @drop=\"onDrop($event, item)\"\n @dragend=\"model.dragEnd\"\n >\n <UIcon\n v-if=\"row(item).expandable\"\n name=\"i-lucide-chevron-right\"\n class=\"size-3.5 shrink-0 text-[var(--sk-muted)] transition-transform\"\n :class=\"row(item).open && 'rotate-90'\"\n @click=\"onChevronClick($event, item)\"\n />\n <span v-else-if=\"item.type === 'composite' || item.type === 'heading'\" class=\"size-3.5 shrink-0\" />\n <UIcon :name=\"item.icon\" class=\"size-4 shrink-0\" :style=\"item.tone ? { color: item.tone } : undefined\" />\n\n <div v-if=\"row(item).renaming\" class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <UInput\n :model-value=\"row(item).renaming!.draft\"\n size=\"xs\"\n class=\"min-w-0\"\n autofocus\n :color=\"row(item).renaming!.error ? 'error' : undefined\"\n :highlight=\"!!row(item).renaming!.error\"\n :aria-label=\"t('tree.folder.name')\"\n :aria-invalid=\"!!row(item).renaming!.error\"\n @update:model-value=\"model.setRenameDraft($event)\"\n @focus=\"($event.target as HTMLInputElement).select()\"\n @click.stop\n @keydown.stop\n @keydown.enter=\"model.commitRename\"\n @keydown.esc=\"model.cancelRename\"\n @blur=\"model.blurRename\"\n />\n <p v-if=\"row(item).renaming!.error\" class=\"text-xs text-[var(--sk-danger)]\" role=\"alert\" @click.stop>\n {{ row(item).renaming!.error }}\n </p>\n </div>\n <template v-else>\n <span\n v-if=\"basketOf(item)\"\n class=\"size-2 shrink-0 rounded-full\"\n :style=\"{ backgroundColor: basketOf(item)!.color }\"\n :title=\"basketOf(item)!.label\"\n :aria-label=\"basketOf(item)!.label\"\n role=\"img\"\n data-basket-dot\n />\n <span class=\"min-w-0 flex-1 truncate\" :title=\"item.label\">\n <template v-if=\"labelParts(item)\">{{ labelParts(item)![0] }}<mark class=\"rounded-sm bg-[color-mix(in_oklab,var(--sk-primary)_20%,transparent)] text-inherit\">{{ labelParts(item)![1] }}</mark>{{ labelParts(item)![2] }}</template>\n <template v-else>{{ item.label }}</template>\n </span>\n <UIcon\n v-if=\"item.hasSummary\"\n name=\"i-lucide-text-quote\"\n class=\"size-3.5 shrink-0 text-[var(--sk-muted)]\"\n :title=\"t('tree.summary')\"\n />\n <div class=\"flex shrink-0\" @click.stop>\n <UDropdownMenu v-if=\"row(item).showFilter\" :items=\"filterMenu(item)\" :content=\"{ align: 'start' }\">\n <UButton\n icon=\"i-lucide-filter\"\n size=\"xs\"\n :color=\"row(item).hiddenKinds.length ? 'primary' : 'neutral'\"\n :variant=\"row(item).hiddenKinds.length ? 'soft' : 'ghost'\"\n :class=\"!row(item).hiddenKinds.length && 'opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100'\"\n :title=\"t('tree.filter.title')\"\n :aria-label=\"t('tree.filter.title')\"\n />\n </UDropdownMenu>\n <div class=\"flex opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 has-data-[state=open]:opacity-100\">\n <UButton\n v-if=\"item.type === 'composite' && item.blockId\"\n icon=\"i-lucide-focus\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"ghost\"\n :title=\"t('tree.focus.enter')\"\n :aria-label=\"t('tree.focus.enter')\"\n @click=\"model.focus(item.key)\"\n />\n <UButton\n v-if=\"model.canMerge(item)\"\n icon=\"i-lucide-merge\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"ghost\"\n :title=\"t('tree.merge')\"\n :aria-label=\"t('tree.merge')\"\n @click=\"model.merge(item)\"\n />\n <UDropdownMenu v-if=\"addMenu(item).length\" :items=\"addMenu(item)\" :content=\"{ align: 'start', onCloseAutoFocus: (event: Event) => event.preventDefault() }\">\n <UButton\n icon=\"i-lucide-plus\"\n size=\"xs\"\n color=\"neutral\"\n variant=\"ghost\"\n :title=\"t('tree.add')\"\n :aria-label=\"t('tree.add')\"\n />\n </UDropdownMenu>\n <slot v-if=\"item.type === 'document'\" name=\"document-actions\" :id=\"item.id!\" :title=\"item.label\" />\n <UButton\n v-if=\"item.type === 'document' || item.type === 'folder'\"\n icon=\"i-lucide-trash-2\"\n size=\"xs\"\n color=\"error\"\n variant=\"ghost\"\n :aria-label=\"t('tree.delete')\"\n loading-auto\n @click=\"model.remove(item)\"\n />\n </div>\n </div>\n </template>\n </div>\n <p v-if=\"refusal(item)\" class=\"px-2 pt-0.5 text-xs text-[var(--sk-danger)]\" role=\"status\">\n {{ refusal(item) }}\n </p>\n </div>\n </template>\n </UTree>\n\n <p v-if=\"state.view.noMatches\" class=\"px-2.5 py-1.5 text-sm text-[var(--sk-muted)]\">\n {{ t('tree.noMatches') }}\n </p>\n <p v-if=\"state.view.isEmpty\" class=\"px-2.5 py-1.5 text-sm text-[var(--sk-muted)]\">\n {{ t('tree.empty') }}\n </p>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -153,7 +153,10 @@ function DocumentTree({ store, editor, selectedFolder, onSelectedFolderChange, d
|
|
|
153
153
|
className: cn("size-3.5 text-muted-foreground transition-transform", row.open && "rotate-90")
|
|
154
154
|
})
|
|
155
155
|
}) : isOutlineItem(item) && /* @__PURE__ */ jsx("span", { className: "size-3.5 shrink-0" }),
|
|
156
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
156
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
157
|
+
name: item.icon,
|
|
158
|
+
style: item.tone ? { color: item.tone } : void 0
|
|
159
|
+
}),
|
|
157
160
|
row.renaming ? /* @__PURE__ */ jsxs("div", {
|
|
158
161
|
className: "flex min-w-0 flex-1 flex-col gap-0.5",
|
|
159
162
|
children: [/* @__PURE__ */ jsx(Input, {
|
|
@@ -222,6 +225,14 @@ function DocumentTree({ store, editor, selectedFolder, onSelectedFolderChange, d
|
|
|
222
225
|
onClick: () => model.focus(item.key),
|
|
223
226
|
children: /* @__PURE__ */ jsx(Icon, { name: "i-lucide-focus" })
|
|
224
227
|
}),
|
|
228
|
+
model.canMerge(item) && /* @__PURE__ */ jsx(Button, {
|
|
229
|
+
size: "icon-xs",
|
|
230
|
+
variant: "ghost",
|
|
231
|
+
title: t("tree.merge"),
|
|
232
|
+
"aria-label": t("tree.merge"),
|
|
233
|
+
onClick: () => model.merge(item),
|
|
234
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "i-lucide-merge" })
|
|
235
|
+
}),
|
|
225
236
|
add.length > 0 && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
226
237
|
asChild: true,
|
|
227
238
|
children: /* @__PURE__ */ jsx(Button, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentTree.js","names":[],"sources":["../../../src/tree/react/DocumentTree.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { type DragEvent, Fragment, type KeyboardEvent, type ReactNode, useRef } from 'react'\nimport { BLOCK_MIME, blockTransferOf, readBlockTransfer, writeBlockTransfer } from '../../core/block-transfer'\nimport { findBlockById } from '../../core/schema/block-ids'\nimport { Icon } from '../../react/Icon'\nimport { useEditorI18n } from '../../react/use-editor-i18n'\nimport { useEditorSettings } from '../../react/settings'\nimport { Button } from '../../react/ui/button'\nimport { Collapsible, CollapsibleContent } from '../../react/ui/collapsible'\nimport { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '../../react/ui/dropdown-menu'\nimport { Input } from '../../react/ui/input'\nimport { Popover, PopoverContent, PopoverTrigger } from '../../react/ui/popover'\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../react/ui/tooltip'\nimport { cn } from '../../react/ui/utils'\nimport type { DocumentStore } from '../store'\nimport { basketById } from '../../features/composites'\nimport { DRAG_MIME, focusCrumbs, itemBasket, type TreeItem } from '../tree-items'\nimport { rowOf } from '../tree-model'\nimport { useTreeModel } from './use-tree-model'\n\n// File browser of a document store: a „Dokumente“ root with folders and documents. It only renders the `TreeModel` (see\n// `tree-model.ts`), which owns what is open, filtered, selected, dragged and renamed; the Vue twin renders the same model.\n\n/** Props of `DocumentTree`. */\nexport interface DocumentTreeProps {\n /** Where documents and folders live; the host implements it (see `DocumentStore`). */\n store: DocumentStore\n /** Editor of the open document (its outline is listed under the document); `undefined` while none is mounted. */\n editor: Editor | undefined\n /** The folder new documents, folders and host imports go to (controlled). Omit it to let the tree keep it. Reset to `''` when it is deleted or moved away. */\n selectedFolder?: string\n onSelectedFolderChange?: (folder: string) => void\n /** Host actions on a document row, rendered next to its delete button (e.g. a download link). */\n documentActions?: (document: { id: string, title: string }) => ReactNode\n className?: string\n}\n\nconst BASKET_OPTION = 'flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-foreground transition-colors duration-150 hover:bg-muted focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary'\n\nconst REVEAL_ON_HOVER = 'opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100'\nconst isOutlineItem = (item: TreeItem) => item.type === 'composite' || item.type === 'heading'\n\n/** The label with the part the title filter matched highlighted. */\nfunction Label({ label, match }: { label: string, match: readonly [number, number] | null }) {\n if (!match) return <>{label}</>\n const [at, length] = match\n return (\n <>\n {label.slice(0, at)}\n <mark className=\"rounded-sm bg-primary/20 text-inherit\">{label.slice(at, at + length)}</mark>\n {label.slice(at + length)}\n </>\n )\n}\n\n/** The file browser of a document store: folders and documents with their drag and drop, the open document's outline below it. */\nexport function DocumentTree({ store, editor, selectedFolder, onSelectedFolderChange, documentActions, className }: DocumentTreeProps) {\n const { t } = useEditorI18n()\n const { update } = useEditorSettings()\n const binding = useTreeModel({ store, editor, selectedFolder, onSelectedFolderChange })\n const treeElement = useRef<HTMLUListElement>(null)\n if (!binding) return null\n const { model, state } = binding\n // Mirrors the model's `isVirtual` rule: the file root only takes effect for a composite document that is open. Without\n // it the button is disabled (and says why) instead of letting the setting silently fall back to the folders.\n const canUseFileRoot = state.hasEditor && state.structure === 'composite'\n const { view, creatingFolder } = state\n\n /** The basket filter button needs a live editor that offers baskets. */\n const showBasketFilter = state.hasEditor && state.baskets.length > 0\n /** The chosen baskets the open editor offers (an unknown id never filters, see `TreeModel`). */\n const shownBaskets = state.basketFilter.filter(id => basketById(state.baskets, id))\n /** The breadcrumb of the focus: the document (first crumb, leaves focus) and the Bausteine down to the focused one. */\n const { document: focusDocument, crumbs } = focusCrumbs(state.focusPath)\n\n // Folders and the root toggle through the row click; documents and outline entries (whose row click opens or reveals)\n // toggle through their chevron.\n function onChevronClick(event: { stopPropagation: () => void }, item: TreeItem) {\n if (item.type === 'root' || item.type === 'folder') return\n event.stopPropagation()\n model.toggle(item.key)\n }\n\n function onRowKeyDown(event: KeyboardEvent<HTMLDivElement>, item: TreeItem) {\n if (event.target !== event.currentTarget) return\n const { expandable, open } = rowOf(state, item, t)\n if (event.key === 'Enter' || event.key === ' ') model.activate(item)\n else if (event.key === 'ArrowRight' && expandable && !open) model.setOpen(item.key, true)\n else if (event.key === 'ArrowLeft' && expandable && open) model.setOpen(item.key, false)\n else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n const rows = [...(treeElement.current?.querySelectorAll<HTMLElement>('[role=\"treeitem\"]') ?? [])]\n rows[rows.indexOf(event.currentTarget) + (event.key === 'ArrowDown' ? 1 : -1)]?.focus()\n } else return\n event.preventDefault()\n }\n\n // --- drag & drop -----------------------------------------------------------------------------------------------\n\n function onDragStart(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n const payload = model.dragStart(item)\n if (!payload) return event.preventDefault()\n event.dataTransfer.setData(DRAG_MIME, JSON.stringify(payload))\n // A Baustein row also carries the block itself, so another surface or tree can take a copy.\n const found = payload.type === 'composite' && editor && !editor.isDestroyed ? findBlockById(editor.state.doc, payload.blockId) : null\n const transfer = found && editor ? blockTransferOf(editor, found.pos) : null\n if (transfer) writeBlockTransfer(event.dataTransfer, transfer)\n event.dataTransfer.effectAllowed = transfer ? 'copyMove' : 'move'\n }\n\n /** A drag of this tree's own rows is running (a foreign drag is not). */\n const ownDrag = !!state.drag && state.drag.source.type !== 'foreign-block'\n\n function onDragOver(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n const foreign = !ownDrag && event.dataTransfer.types.includes(BLOCK_MIME)\n const verdict = foreign ? model.foreignDragOver(item) : model.dragOver(item)\n if (!verdict) return\n // Only an allowed target takes the drop; over a refused one the browser shows „not allowed“ and the row shows why.\n if (verdict.ok) event.preventDefault()\n event.dataTransfer.dropEffect = verdict.ok ? (foreign ? 'copy' : 'move') : 'none'\n }\n\n function onDragLeave(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) model.dragLeave(item)\n }\n\n function onDrop(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n if (ownDrag) {\n event.preventDefault()\n void model.drop(item)\n return\n }\n const payload = readBlockTransfer(event.dataTransfer)\n if (!payload) return\n event.preventDefault()\n void model.dropForeign(item, payload, event.shiftKey, event.clientX, event.clientY)\n }\n\n // --- rendering -------------------------------------------------------------------------------------------------\n\n const filterMenu = (item: TreeItem) => {\n const { filterKinds, hiddenKinds } = rowOf(state, item, t)\n return (\n <DropdownMenuContent align=\"start\" className=\"w-auto\">\n <DropdownMenuLabel>{t('tree.filter.show')}</DropdownMenuLabel>\n {filterKinds.map(kind => (\n <DropdownMenuCheckboxItem\n key={kind.id}\n checked={!hiddenKinds.includes(kind.id)}\n onCheckedChange={visible => model.setKindHidden(item.key, kind.id, !visible)}\n // Stay open: several kinds are usually toggled in one go.\n onSelect={event => event.preventDefault()}\n >\n <Icon name={kind.icon} />\n {kind.label}\n </DropdownMenuCheckboxItem>\n ))}\n {hiddenKinds.length > 0 && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={() => model.clearFilter(item.key)}>\n <Icon name=\"i-lucide-filter-x\" />\n {t('tree.filter.reset')}\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n )\n }\n\n const renderRow = (item: TreeItem, level: number) => {\n const row = rowOf(state, item, t)\n const add = model.addMenu(item)\n const filtered = row.hiddenKinds.length > 0\n const refused = row.drop && !row.drop.ok ? row.drop.reason : null\n const basket = itemBasket(item, state.baskets)\n return (\n <>\n <div\n role=\"treeitem\"\n tabIndex={0}\n aria-level={level + 1}\n aria-expanded={row.expandable ? row.open : undefined}\n aria-selected={row.active ? true : undefined}\n className={cn(\n 'group flex w-full cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-sm select-none outline-none hover:bg-muted/60 focus-visible:ring-1 focus-visible:ring-ring',\n row.active && 'bg-primary/10 font-medium text-primary',\n row.selected && 'bg-muted',\n row.drop?.ok && 'ring-1 ring-primary',\n refused && 'bg-destructive/10 ring-1 ring-destructive',\n row.dimmed && 'opacity-60',\n )}\n draggable={model.isDraggable(item)}\n onClick={() => model.activate(item)}\n onKeyDown={event => onRowKeyDown(event, item)}\n onDragStart={event => onDragStart(event, item)}\n onDragOver={event => onDragOver(event, item)}\n onDragLeave={event => onDragLeave(event, item)}\n onDrop={event => onDrop(event, item)}\n onDragEnd={() => model.dragEnd()}\n >\n {row.expandable\n ? (\n <span className=\"flex shrink-0\" onClick={event => onChevronClick(event, item)}>\n <Icon name=\"i-lucide-chevron-right\" className={cn('size-3.5 text-muted-foreground transition-transform', row.open && 'rotate-90')} />\n </span>\n )\n : isOutlineItem(item) && <span className=\"size-3.5 shrink-0\" />}\n <Icon name={item.icon} />\n\n {row.renaming\n ? (\n <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <Input\n value={row.renaming.draft}\n className=\"h-6 min-w-0 px-2 text-xs md:text-xs\"\n autoFocus\n aria-label={t('tree.folder.name')}\n aria-invalid={!!row.renaming.error}\n onChange={event => model.setRenameDraft(event.target.value)}\n onFocus={event => event.currentTarget.select()}\n onClick={event => event.stopPropagation()}\n onKeyDown={(event) => {\n event.stopPropagation()\n if (event.key === 'Enter') void model.commitRename()\n else if (event.key === 'Escape') model.cancelRename()\n }}\n onBlur={() => void model.blurRename()}\n />\n {row.renaming.error && <p className=\"text-xs text-destructive\" role=\"alert\" onClick={event => event.stopPropagation()}>{row.renaming.error}</p>}\n </div>\n )\n : (\n <>\n {basket && (\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: basket.color }}\n title={basket.label}\n aria-label={basket.label}\n role=\"img\"\n data-basket-dot\n />\n )}\n <span className=\"min-w-0 flex-1 truncate\" title={item.label}><Label label={item.label} match={row.match} /></span>\n {item.hasSummary && <Icon name=\"i-lucide-text-quote\" className=\"size-3.5 text-muted-foreground\" />}\n <div className=\"flex shrink-0\" onClick={event => event.stopPropagation()}>\n {row.showFilter && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"icon-xs\"\n variant={filtered ? 'secondary' : 'ghost'}\n className={cn(!filtered && REVEAL_ON_HOVER)}\n title={t('tree.filter.title')}\n aria-label={t('tree.filter.title')}\n >\n <Icon name=\"i-lucide-filter\" />\n </Button>\n </DropdownMenuTrigger>\n {filterMenu(item)}\n </DropdownMenu>\n )}\n <div className=\"flex opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 has-data-[state=open]:opacity-100\">\n {item.type === 'composite' && item.blockId && (\n <Button size=\"icon-xs\" variant=\"ghost\" title={t('tree.focus.enter')} aria-label={t('tree.focus.enter')} onClick={() => model.focus(item.key)}>\n <Icon name=\"i-lucide-focus\" />\n </Button>\n )}\n {add.length > 0 && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button size=\"icon-xs\" variant=\"ghost\" title={t('tree.add')} aria-label={t('tree.add')}>\n <Icon name=\"i-lucide-plus\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-auto\" onCloseAutoFocus={event => event.preventDefault()}>\n {add.map((group, index) => (\n <div key={index}>\n {index > 0 && <DropdownMenuSeparator />}\n {group.map(entry => (\n <DropdownMenuItem key={entry.label} onSelect={entry.run}>\n <Icon name={entry.icon} />\n {entry.label}\n </DropdownMenuItem>\n ))}\n </div>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n {item.type === 'document' && documentActions?.({ id: item.id!, title: item.label })}\n {(item.type === 'document' || item.type === 'folder') && (\n <Button\n size=\"icon-xs\"\n variant=\"ghost\"\n className=\"text-destructive hover:text-destructive\"\n aria-label={t('tree.delete')}\n disabled={row.removing}\n onClick={() => void model.remove(item)}\n >\n <Icon name={row.removing ? 'i-lucide-loader-circle' : 'i-lucide-trash-2'} className={cn(row.removing && 'animate-spin')} />\n </Button>\n )}\n </div>\n </div>\n </>\n )}\n </div>\n {refused && <p className=\"px-2 pt-0.5 text-xs text-destructive\" role=\"status\">{refused}</p>}\n </>\n )\n }\n\n const renderItems = (list: readonly TreeItem[], level: number): ReactNode => (\n <ul role={level === 0 ? 'tree' : 'group'} aria-label={level === 0 ? t('tree.aria') : undefined} ref={level === 0 ? treeElement : undefined} className={cn('m-0 list-none p-0', level > 0 && 'ml-3 border-l border-border pl-1')}>\n {list.map(item => (\n <li key={item.key} role=\"none\">\n <Collapsible open={rowOf(state, item, t).open}>\n {renderRow(item, level)}\n {item.children?.length ? <CollapsibleContent>{renderItems(item.children, level + 1)}</CollapsibleContent> : null}\n </Collapsible>\n </li>\n ))}\n </ul>\n )\n\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n <div className=\"flex items-center gap-1\">\n <div className=\"relative min-w-0 flex-1\">\n <Icon name=\"i-lucide-search\" className=\"pointer-events-none absolute top-1/2 left-2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={state.filterText}\n className=\"h-7 pr-7 pl-7 text-sm md:text-sm\"\n placeholder={t('tree.filterText.placeholder')}\n aria-label={t('tree.filterText.placeholder')}\n onChange={event => model.setFilterText(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') model.setFilterText('')\n }}\n />\n {state.filterText && (\n <Button\n size=\"icon-xs\"\n variant=\"ghost\"\n className=\"absolute top-1/2 right-1 -translate-y-1/2\"\n aria-label={t('tree.filterText.clear')}\n onClick={() => model.setFilterText('')}\n >\n <Icon name=\"i-lucide-x\" />\n </Button>\n )}\n </div>\n {showBasketFilter && (\n // A popover, not a dropdown menu: a menu item cannot show a dot in an arbitrary CSS colour.\n <Popover>\n <PopoverTrigger asChild>\n <Button\n size=\"icon-xs\"\n variant={shownBaskets.length ? 'secondary' : 'ghost'}\n title={t('tree.basketFilter.label')}\n aria-label={t('tree.basketFilter.label')}\n >\n <Icon name=\"i-lucide-paint-bucket\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent side=\"bottom\" align=\"end\" sideOffset={4} className=\"w-44 gap-0 p-1\" onCloseAutoFocus={event => event.preventDefault()}>\n <div role=\"menu\" aria-label={t('tree.basketFilter.label')}>\n {state.baskets.map((basket) => {\n const shown = shownBaskets.includes(basket.id)\n return (\n <button\n key={basket.id}\n type=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={shown}\n className={BASKET_OPTION}\n onClick={() => model.setBasketShown(basket.id, !shown)}\n >\n <span className=\"size-2.5 shrink-0 rounded-full\" style={{ backgroundColor: basket.color }} />\n <span className=\"truncate\">{basket.label}</span>\n {shown && <Icon name=\"i-lucide-check\" className=\"ml-auto size-3.5 shrink-0\" />}\n </button>\n )\n })}\n {shownBaskets.length > 0 && (\n <button type=\"button\" role=\"menuitem\" className={BASKET_OPTION} onClick={() => model.clearBasketFilter()}>\n <Icon name=\"i-lucide-filter-x\" className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{t('tree.basketFilter.reset')}</span>\n </button>\n )}\n </div>\n </PopoverContent>\n </Popover>\n )}\n </div>\n\n <div className=\"flex items-center justify-end\">\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n {/* A disabled button swallows pointer events, so the tooltip hangs on the wrapper. */}\n <span className=\"inline-flex\">\n <Button\n size=\"xs\"\n variant={state.virtual ? 'secondary' : 'ghost'}\n disabled={!canUseFileRoot}\n aria-pressed={state.virtual}\n onClick={() => update((draft) => { draft.blocks.treeRoot = draft.blocks.treeRoot === 'file' ? 'folders' : 'file' })}\n >\n <Icon name={state.virtual ? 'i-lucide-file-stack' : 'i-lucide-folder-tree'} />\n {t(state.virtual ? 'tree.root.file' : 'tree.root.folders')}\n </Button>\n </span>\n </TooltipTrigger>\n {!canUseFileRoot && <TooltipContent>{t('tree.root.unavailable')}</TooltipContent>}\n </Tooltip>\n </TooltipProvider>\n </div>\n\n {view.hasKindFilters && (\n <div className=\"flex items-center\">\n <Button size=\"xs\" variant=\"secondary\" onClick={() => model.clearAllFilters()}>\n <Icon name=\"i-lucide-filter-x\" />\n {t('tree.filter.reset')}\n </Button>\n </div>\n )}\n\n {creatingFolder && (\n <div className=\"flex flex-col gap-1\">\n <Input\n value={creatingFolder.draft}\n className=\"h-7 text-sm md:text-sm\"\n autoFocus\n placeholder={creatingFolder.parent ? t('tree.folder.placeholderIn', { parent: creatingFolder.parent }) : t('tree.folder.placeholder')}\n aria-label={t('tree.folder.name')}\n aria-invalid={!!creatingFolder.error}\n onChange={event => model.setFolderDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') void model.commitCreateFolder()\n else if (event.key === 'Escape') model.cancelCreateFolder()\n }}\n onBlur={() => model.cancelCreateFolder()}\n />\n {creatingFolder.error && <p className=\"px-0.5 text-xs text-destructive\" role=\"alert\">{creatingFolder.error}</p>}\n </div>\n )}\n\n {crumbs.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-0.5 text-xs\">\n <Button size=\"xs\" variant=\"ghost\" title={t('tree.focus.leave')} aria-label={t('tree.focus.leave')} onClick={() => model.defocus()}>\n <Icon name=\"i-lucide-corner-up-left\" />\n {focusDocument?.label ?? t('tree.focus.root')}\n </Button>\n {crumbs.map((crumb, index) => (\n <Fragment key={crumb.key}>\n <Icon name=\"i-lucide-chevron-right\" className=\"size-3 shrink-0 text-muted-foreground\" />\n {index === crumbs.length - 1\n ? <span className=\"min-w-0 truncate px-1.5 font-medium\" aria-current=\"location\">{crumb.label}</span>\n : <Button size=\"xs\" variant=\"ghost\" onClick={() => model.focus(crumb.key)}>{crumb.label}</Button>}\n </Fragment>\n ))}\n </div>\n )}\n\n {!state.tree && !state.virtual\n ? <p className=\"px-2.5 py-1.5 text-sm text-muted-foreground\">{state.tree === null ? t('tree.loadFailed') : t('tree.loading')}</p>\n : renderItems(view.items, 0)}\n\n {view.noMatches && <p className=\"px-2.5 py-1.5 text-sm text-muted-foreground\">{t('tree.noMatches')}</p>}\n {view.isEmpty && <p className=\"px-2.5 py-1.5 text-sm text-muted-foreground\">{t('tree.empty')}</p>}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocumentTree.js","names":[],"sources":["../../../src/tree/react/DocumentTree.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { type DragEvent, Fragment, type KeyboardEvent, type ReactNode, useRef } from 'react'\nimport { BLOCK_MIME, blockTransferOf, readBlockTransfer, writeBlockTransfer } from '../../core/block-transfer'\nimport { findBlockById } from '../../core/schema/block-ids'\nimport { Icon } from '../../react/Icon'\nimport { useEditorI18n } from '../../react/use-editor-i18n'\nimport { useEditorSettings } from '../../react/settings'\nimport { Button } from '../../react/ui/button'\nimport { Collapsible, CollapsibleContent } from '../../react/ui/collapsible'\nimport { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '../../react/ui/dropdown-menu'\nimport { Input } from '../../react/ui/input'\nimport { Popover, PopoverContent, PopoverTrigger } from '../../react/ui/popover'\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../react/ui/tooltip'\nimport { cn } from '../../react/ui/utils'\nimport type { DocumentStore } from '../store'\nimport { basketById } from '../../features/composites'\nimport { DRAG_MIME, focusCrumbs, itemBasket, type TreeItem } from '../tree-items'\nimport { rowOf } from '../tree-model'\nimport { useTreeModel } from './use-tree-model'\n\n// File browser of a document store: a „Dokumente“ root with folders and documents. It only renders the `TreeModel` (see\n// `tree-model.ts`), which owns what is open, filtered, selected, dragged and renamed; the Vue twin renders the same model.\n\n/** Props of `DocumentTree`. */\nexport interface DocumentTreeProps {\n /** Where documents and folders live; the host implements it (see `DocumentStore`). */\n store: DocumentStore\n /** Editor of the open document (its outline is listed under the document); `undefined` while none is mounted. */\n editor: Editor | undefined\n /** The folder new documents, folders and host imports go to (controlled). Omit it to let the tree keep it. Reset to `''` when it is deleted or moved away. */\n selectedFolder?: string\n onSelectedFolderChange?: (folder: string) => void\n /** Host actions on a document row, rendered next to its delete button (e.g. a download link). */\n documentActions?: (document: { id: string, title: string }) => ReactNode\n className?: string\n}\n\nconst BASKET_OPTION = 'flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-foreground transition-colors duration-150 hover:bg-muted focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary'\n\nconst REVEAL_ON_HOVER = 'opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100'\nconst isOutlineItem = (item: TreeItem) => item.type === 'composite' || item.type === 'heading'\n\n/** The label with the part the title filter matched highlighted. */\nfunction Label({ label, match }: { label: string, match: readonly [number, number] | null }) {\n if (!match) return <>{label}</>\n const [at, length] = match\n return (\n <>\n {label.slice(0, at)}\n <mark className=\"rounded-sm bg-primary/20 text-inherit\">{label.slice(at, at + length)}</mark>\n {label.slice(at + length)}\n </>\n )\n}\n\n/** The file browser of a document store: folders and documents with their drag and drop, the open document's outline below it. */\nexport function DocumentTree({ store, editor, selectedFolder, onSelectedFolderChange, documentActions, className }: DocumentTreeProps) {\n const { t } = useEditorI18n()\n const { update } = useEditorSettings()\n const binding = useTreeModel({ store, editor, selectedFolder, onSelectedFolderChange })\n const treeElement = useRef<HTMLUListElement>(null)\n if (!binding) return null\n const { model, state } = binding\n // Mirrors the model's `isVirtual` rule: the file root only takes effect for a composite document that is open. Without\n // it the button is disabled (and says why) instead of letting the setting silently fall back to the folders.\n const canUseFileRoot = state.hasEditor && state.structure === 'composite'\n const { view, creatingFolder } = state\n\n /** The basket filter button needs a live editor that offers baskets. */\n const showBasketFilter = state.hasEditor && state.baskets.length > 0\n /** The chosen baskets the open editor offers (an unknown id never filters, see `TreeModel`). */\n const shownBaskets = state.basketFilter.filter(id => basketById(state.baskets, id))\n /** The breadcrumb of the focus: the document (first crumb, leaves focus) and the Bausteine down to the focused one. */\n const { document: focusDocument, crumbs } = focusCrumbs(state.focusPath)\n\n // Folders and the root toggle through the row click; documents and outline entries (whose row click opens or reveals)\n // toggle through their chevron.\n function onChevronClick(event: { stopPropagation: () => void }, item: TreeItem) {\n if (item.type === 'root' || item.type === 'folder') return\n event.stopPropagation()\n model.toggle(item.key)\n }\n\n function onRowKeyDown(event: KeyboardEvent<HTMLDivElement>, item: TreeItem) {\n if (event.target !== event.currentTarget) return\n const { expandable, open } = rowOf(state, item, t)\n if (event.key === 'Enter' || event.key === ' ') model.activate(item)\n else if (event.key === 'ArrowRight' && expandable && !open) model.setOpen(item.key, true)\n else if (event.key === 'ArrowLeft' && expandable && open) model.setOpen(item.key, false)\n else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n const rows = [...(treeElement.current?.querySelectorAll<HTMLElement>('[role=\"treeitem\"]') ?? [])]\n rows[rows.indexOf(event.currentTarget) + (event.key === 'ArrowDown' ? 1 : -1)]?.focus()\n } else return\n event.preventDefault()\n }\n\n // --- drag & drop -----------------------------------------------------------------------------------------------\n\n function onDragStart(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n const payload = model.dragStart(item)\n if (!payload) return event.preventDefault()\n event.dataTransfer.setData(DRAG_MIME, JSON.stringify(payload))\n // A Baustein row also carries the block itself, so another surface or tree can take a copy.\n const found = payload.type === 'composite' && editor && !editor.isDestroyed ? findBlockById(editor.state.doc, payload.blockId) : null\n const transfer = found && editor ? blockTransferOf(editor, found.pos) : null\n if (transfer) writeBlockTransfer(event.dataTransfer, transfer)\n event.dataTransfer.effectAllowed = transfer ? 'copyMove' : 'move'\n }\n\n /** A drag of this tree's own rows is running (a foreign drag is not). */\n const ownDrag = !!state.drag && state.drag.source.type !== 'foreign-block'\n\n function onDragOver(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n const foreign = !ownDrag && event.dataTransfer.types.includes(BLOCK_MIME)\n const verdict = foreign ? model.foreignDragOver(item) : model.dragOver(item)\n if (!verdict) return\n // Only an allowed target takes the drop; over a refused one the browser shows „not allowed“ and the row shows why.\n if (verdict.ok) event.preventDefault()\n event.dataTransfer.dropEffect = verdict.ok ? (foreign ? 'copy' : 'move') : 'none'\n }\n\n function onDragLeave(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) model.dragLeave(item)\n }\n\n function onDrop(event: DragEvent<HTMLDivElement>, item: TreeItem) {\n if (ownDrag) {\n event.preventDefault()\n void model.drop(item)\n return\n }\n const payload = readBlockTransfer(event.dataTransfer)\n if (!payload) return\n event.preventDefault()\n void model.dropForeign(item, payload, event.shiftKey, event.clientX, event.clientY)\n }\n\n // --- rendering -------------------------------------------------------------------------------------------------\n\n const filterMenu = (item: TreeItem) => {\n const { filterKinds, hiddenKinds } = rowOf(state, item, t)\n return (\n <DropdownMenuContent align=\"start\" className=\"w-auto\">\n <DropdownMenuLabel>{t('tree.filter.show')}</DropdownMenuLabel>\n {filterKinds.map(kind => (\n <DropdownMenuCheckboxItem\n key={kind.id}\n checked={!hiddenKinds.includes(kind.id)}\n onCheckedChange={visible => model.setKindHidden(item.key, kind.id, !visible)}\n // Stay open: several kinds are usually toggled in one go.\n onSelect={event => event.preventDefault()}\n >\n <Icon name={kind.icon} />\n {kind.label}\n </DropdownMenuCheckboxItem>\n ))}\n {hiddenKinds.length > 0 && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={() => model.clearFilter(item.key)}>\n <Icon name=\"i-lucide-filter-x\" />\n {t('tree.filter.reset')}\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n )\n }\n\n const renderRow = (item: TreeItem, level: number) => {\n const row = rowOf(state, item, t)\n const add = model.addMenu(item)\n const filtered = row.hiddenKinds.length > 0\n const refused = row.drop && !row.drop.ok ? row.drop.reason : null\n const basket = itemBasket(item, state.baskets)\n return (\n <>\n <div\n role=\"treeitem\"\n tabIndex={0}\n aria-level={level + 1}\n aria-expanded={row.expandable ? row.open : undefined}\n aria-selected={row.active ? true : undefined}\n className={cn(\n 'group flex w-full cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-sm select-none outline-none hover:bg-muted/60 focus-visible:ring-1 focus-visible:ring-ring',\n row.active && 'bg-primary/10 font-medium text-primary',\n row.selected && 'bg-muted',\n row.drop?.ok && 'ring-1 ring-primary',\n refused && 'bg-destructive/10 ring-1 ring-destructive',\n row.dimmed && 'opacity-60',\n )}\n draggable={model.isDraggable(item)}\n onClick={() => model.activate(item)}\n onKeyDown={event => onRowKeyDown(event, item)}\n onDragStart={event => onDragStart(event, item)}\n onDragOver={event => onDragOver(event, item)}\n onDragLeave={event => onDragLeave(event, item)}\n onDrop={event => onDrop(event, item)}\n onDragEnd={() => model.dragEnd()}\n >\n {row.expandable\n ? (\n <span className=\"flex shrink-0\" onClick={event => onChevronClick(event, item)}>\n <Icon name=\"i-lucide-chevron-right\" className={cn('size-3.5 text-muted-foreground transition-transform', row.open && 'rotate-90')} />\n </span>\n )\n : isOutlineItem(item) && <span className=\"size-3.5 shrink-0\" />}\n <Icon name={item.icon} style={item.tone ? { color: item.tone } : undefined} />\n\n {row.renaming\n ? (\n <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <Input\n value={row.renaming.draft}\n className=\"h-6 min-w-0 px-2 text-xs md:text-xs\"\n autoFocus\n aria-label={t('tree.folder.name')}\n aria-invalid={!!row.renaming.error}\n onChange={event => model.setRenameDraft(event.target.value)}\n onFocus={event => event.currentTarget.select()}\n onClick={event => event.stopPropagation()}\n onKeyDown={(event) => {\n event.stopPropagation()\n if (event.key === 'Enter') void model.commitRename()\n else if (event.key === 'Escape') model.cancelRename()\n }}\n onBlur={() => void model.blurRename()}\n />\n {row.renaming.error && <p className=\"text-xs text-destructive\" role=\"alert\" onClick={event => event.stopPropagation()}>{row.renaming.error}</p>}\n </div>\n )\n : (\n <>\n {basket && (\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: basket.color }}\n title={basket.label}\n aria-label={basket.label}\n role=\"img\"\n data-basket-dot\n />\n )}\n <span className=\"min-w-0 flex-1 truncate\" title={item.label}><Label label={item.label} match={row.match} /></span>\n {item.hasSummary && <Icon name=\"i-lucide-text-quote\" className=\"size-3.5 text-muted-foreground\" />}\n <div className=\"flex shrink-0\" onClick={event => event.stopPropagation()}>\n {row.showFilter && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"icon-xs\"\n variant={filtered ? 'secondary' : 'ghost'}\n className={cn(!filtered && REVEAL_ON_HOVER)}\n title={t('tree.filter.title')}\n aria-label={t('tree.filter.title')}\n >\n <Icon name=\"i-lucide-filter\" />\n </Button>\n </DropdownMenuTrigger>\n {filterMenu(item)}\n </DropdownMenu>\n )}\n <div className=\"flex opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 has-data-[state=open]:opacity-100\">\n {item.type === 'composite' && item.blockId && (\n <Button size=\"icon-xs\" variant=\"ghost\" title={t('tree.focus.enter')} aria-label={t('tree.focus.enter')} onClick={() => model.focus(item.key)}>\n <Icon name=\"i-lucide-focus\" />\n </Button>\n )}\n {model.canMerge(item) && (\n <Button size=\"icon-xs\" variant=\"ghost\" title={t('tree.merge')} aria-label={t('tree.merge')} onClick={() => model.merge(item)}>\n <Icon name=\"i-lucide-merge\" />\n </Button>\n )}\n {add.length > 0 && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button size=\"icon-xs\" variant=\"ghost\" title={t('tree.add')} aria-label={t('tree.add')}>\n <Icon name=\"i-lucide-plus\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-auto\" onCloseAutoFocus={event => event.preventDefault()}>\n {add.map((group, index) => (\n <div key={index}>\n {index > 0 && <DropdownMenuSeparator />}\n {group.map(entry => (\n <DropdownMenuItem key={entry.label} onSelect={entry.run}>\n <Icon name={entry.icon} />\n {entry.label}\n </DropdownMenuItem>\n ))}\n </div>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n {item.type === 'document' && documentActions?.({ id: item.id!, title: item.label })}\n {(item.type === 'document' || item.type === 'folder') && (\n <Button\n size=\"icon-xs\"\n variant=\"ghost\"\n className=\"text-destructive hover:text-destructive\"\n aria-label={t('tree.delete')}\n disabled={row.removing}\n onClick={() => void model.remove(item)}\n >\n <Icon name={row.removing ? 'i-lucide-loader-circle' : 'i-lucide-trash-2'} className={cn(row.removing && 'animate-spin')} />\n </Button>\n )}\n </div>\n </div>\n </>\n )}\n </div>\n {refused && <p className=\"px-2 pt-0.5 text-xs text-destructive\" role=\"status\">{refused}</p>}\n </>\n )\n }\n\n const renderItems = (list: readonly TreeItem[], level: number): ReactNode => (\n <ul role={level === 0 ? 'tree' : 'group'} aria-label={level === 0 ? t('tree.aria') : undefined} ref={level === 0 ? treeElement : undefined} className={cn('m-0 list-none p-0', level > 0 && 'ml-3 border-l border-border pl-1')}>\n {list.map(item => (\n <li key={item.key} role=\"none\">\n <Collapsible open={rowOf(state, item, t).open}>\n {renderRow(item, level)}\n {item.children?.length ? <CollapsibleContent>{renderItems(item.children, level + 1)}</CollapsibleContent> : null}\n </Collapsible>\n </li>\n ))}\n </ul>\n )\n\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n <div className=\"flex items-center gap-1\">\n <div className=\"relative min-w-0 flex-1\">\n <Icon name=\"i-lucide-search\" className=\"pointer-events-none absolute top-1/2 left-2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={state.filterText}\n className=\"h-7 pr-7 pl-7 text-sm md:text-sm\"\n placeholder={t('tree.filterText.placeholder')}\n aria-label={t('tree.filterText.placeholder')}\n onChange={event => model.setFilterText(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') model.setFilterText('')\n }}\n />\n {state.filterText && (\n <Button\n size=\"icon-xs\"\n variant=\"ghost\"\n className=\"absolute top-1/2 right-1 -translate-y-1/2\"\n aria-label={t('tree.filterText.clear')}\n onClick={() => model.setFilterText('')}\n >\n <Icon name=\"i-lucide-x\" />\n </Button>\n )}\n </div>\n {showBasketFilter && (\n // A popover, not a dropdown menu: a menu item cannot show a dot in an arbitrary CSS colour.\n <Popover>\n <PopoverTrigger asChild>\n <Button\n size=\"icon-xs\"\n variant={shownBaskets.length ? 'secondary' : 'ghost'}\n title={t('tree.basketFilter.label')}\n aria-label={t('tree.basketFilter.label')}\n >\n <Icon name=\"i-lucide-paint-bucket\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent side=\"bottom\" align=\"end\" sideOffset={4} className=\"w-44 gap-0 p-1\" onCloseAutoFocus={event => event.preventDefault()}>\n <div role=\"menu\" aria-label={t('tree.basketFilter.label')}>\n {state.baskets.map((basket) => {\n const shown = shownBaskets.includes(basket.id)\n return (\n <button\n key={basket.id}\n type=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={shown}\n className={BASKET_OPTION}\n onClick={() => model.setBasketShown(basket.id, !shown)}\n >\n <span className=\"size-2.5 shrink-0 rounded-full\" style={{ backgroundColor: basket.color }} />\n <span className=\"truncate\">{basket.label}</span>\n {shown && <Icon name=\"i-lucide-check\" className=\"ml-auto size-3.5 shrink-0\" />}\n </button>\n )\n })}\n {shownBaskets.length > 0 && (\n <button type=\"button\" role=\"menuitem\" className={BASKET_OPTION} onClick={() => model.clearBasketFilter()}>\n <Icon name=\"i-lucide-filter-x\" className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{t('tree.basketFilter.reset')}</span>\n </button>\n )}\n </div>\n </PopoverContent>\n </Popover>\n )}\n </div>\n\n <div className=\"flex items-center justify-end\">\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n {/* A disabled button swallows pointer events, so the tooltip hangs on the wrapper. */}\n <span className=\"inline-flex\">\n <Button\n size=\"xs\"\n variant={state.virtual ? 'secondary' : 'ghost'}\n disabled={!canUseFileRoot}\n aria-pressed={state.virtual}\n onClick={() => update((draft) => { draft.blocks.treeRoot = draft.blocks.treeRoot === 'file' ? 'folders' : 'file' })}\n >\n <Icon name={state.virtual ? 'i-lucide-file-stack' : 'i-lucide-folder-tree'} />\n {t(state.virtual ? 'tree.root.file' : 'tree.root.folders')}\n </Button>\n </span>\n </TooltipTrigger>\n {!canUseFileRoot && <TooltipContent>{t('tree.root.unavailable')}</TooltipContent>}\n </Tooltip>\n </TooltipProvider>\n </div>\n\n {view.hasKindFilters && (\n <div className=\"flex items-center\">\n <Button size=\"xs\" variant=\"secondary\" onClick={() => model.clearAllFilters()}>\n <Icon name=\"i-lucide-filter-x\" />\n {t('tree.filter.reset')}\n </Button>\n </div>\n )}\n\n {creatingFolder && (\n <div className=\"flex flex-col gap-1\">\n <Input\n value={creatingFolder.draft}\n className=\"h-7 text-sm md:text-sm\"\n autoFocus\n placeholder={creatingFolder.parent ? t('tree.folder.placeholderIn', { parent: creatingFolder.parent }) : t('tree.folder.placeholder')}\n aria-label={t('tree.folder.name')}\n aria-invalid={!!creatingFolder.error}\n onChange={event => model.setFolderDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') void model.commitCreateFolder()\n else if (event.key === 'Escape') model.cancelCreateFolder()\n }}\n onBlur={() => model.cancelCreateFolder()}\n />\n {creatingFolder.error && <p className=\"px-0.5 text-xs text-destructive\" role=\"alert\">{creatingFolder.error}</p>}\n </div>\n )}\n\n {crumbs.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-0.5 text-xs\">\n <Button size=\"xs\" variant=\"ghost\" title={t('tree.focus.leave')} aria-label={t('tree.focus.leave')} onClick={() => model.defocus()}>\n <Icon name=\"i-lucide-corner-up-left\" />\n {focusDocument?.label ?? t('tree.focus.root')}\n </Button>\n {crumbs.map((crumb, index) => (\n <Fragment key={crumb.key}>\n <Icon name=\"i-lucide-chevron-right\" className=\"size-3 shrink-0 text-muted-foreground\" />\n {index === crumbs.length - 1\n ? <span className=\"min-w-0 truncate px-1.5 font-medium\" aria-current=\"location\">{crumb.label}</span>\n : <Button size=\"xs\" variant=\"ghost\" onClick={() => model.focus(crumb.key)}>{crumb.label}</Button>}\n </Fragment>\n ))}\n </div>\n )}\n\n {!state.tree && !state.virtual\n ? <p className=\"px-2.5 py-1.5 text-sm text-muted-foreground\">{state.tree === null ? t('tree.loadFailed') : t('tree.loading')}</p>\n : renderItems(view.items, 0)}\n\n {view.noMatches && <p className=\"px-2.5 py-1.5 text-sm text-muted-foreground\">{t('tree.noMatches')}</p>}\n {view.isEmpty && <p className=\"px-2.5 py-1.5 text-sm text-muted-foreground\">{t('tree.empty')}</p>}\n </div>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqCA,MAAM,gBAAgB;AAEtB,MAAM,kBAAkB;AACxB,MAAM,iBAAiB,SAAmB,KAAK,SAAS,eAAe,KAAK,SAAS;;AAGrF,SAAS,MAAM,EAAE,OAAO,SAAqE;CAC3F,IAAI,CAAC,OAAO,OAAO,oBAAA,YAAA,EAAA,UAAG,MAAQ,CAAA;CAC9B,MAAM,CAAC,IAAI,UAAU;CACrB,OACE,qBAAA,YAAA,EAAA,UAAA;EACG,MAAM,MAAM,GAAG,EAAE;EAClB,oBAAC,QAAD;GAAM,WAAU;GAAyC,UAAA,MAAM,MAAM,IAAI,KAAK,MAAM;EAAQ,CAAA;EAC3F,MAAM,MAAM,KAAK,MAAM;CACxB,EAAA,CAAA;AAEN;;AAGA,SAAgB,aAAa,EAAE,OAAO,QAAQ,gBAAgB,wBAAwB,iBAAiB,aAAgC;CACrI,MAAM,EAAE,MAAM,cAAc;CAC5B,MAAM,EAAE,WAAW,kBAAkB;CACrC,MAAM,UAAU,aAAa;EAAE;EAAO;EAAQ;EAAgB;CAAuB,CAAC;CACtF,MAAM,cAAc,OAAyB,IAAI;CACjD,IAAI,CAAC,SAAS,OAAO;CACrB,MAAM,EAAE,OAAO,UAAU;CAGzB,MAAM,iBAAiB,MAAM,aAAa,MAAM,cAAc;CAC9D,MAAM,EAAE,MAAM,mBAAmB;;CAGjC,MAAM,mBAAmB,MAAM,aAAa,MAAM,QAAQ,SAAS;;CAEnE,MAAM,eAAe,MAAM,aAAa,QAAO,OAAM,WAAW,MAAM,SAAS,EAAE,CAAC;;CAElF,MAAM,EAAE,UAAU,eAAe,WAAW,YAAY,MAAM,SAAS;CAIvE,SAAS,eAAe,OAAwC,MAAgB;EAC9E,IAAI,KAAK,SAAS,UAAU,KAAK,SAAS,UAAU;EACpD,MAAM,gBAAgB;EACtB,MAAM,OAAO,KAAK,GAAG;CACvB;CAEA,SAAS,aAAa,OAAsC,MAAgB;EAC1E,IAAI,MAAM,WAAW,MAAM,eAAe;EAC1C,MAAM,EAAE,YAAY,SAAS,MAAM,OAAO,MAAM,CAAC;EACjD,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK,MAAM,SAAS,IAAI;OAC9D,IAAI,MAAM,QAAQ,gBAAgB,cAAc,CAAC,MAAM,MAAM,QAAQ,KAAK,KAAK,IAAI;OACnF,IAAI,MAAM,QAAQ,eAAe,cAAc,MAAM,MAAM,QAAQ,KAAK,KAAK,KAAK;OAClF,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;GAC7D,MAAM,OAAO,CAAC,GAAI,YAAY,SAAS,iBAA8B,qBAAmB,KAAK,CAAC,CAAE;GAChG,KAAK,KAAK,QAAQ,MAAM,aAAa,KAAK,MAAM,QAAQ,cAAc,IAAI,IAAI,EAAE,MAAM;EACxF,OAAO;EACP,MAAM,eAAe;CACvB;CAIA,SAAS,YAAY,OAAkC,MAAgB;EACrE,MAAM,UAAU,MAAM,UAAU,IAAI;EACpC,IAAI,CAAC,SAAS,OAAO,MAAM,eAAe;EAC1C,MAAM,aAAa,QAAQ,WAAW,KAAK,UAAU,OAAO,CAAC;EAE7D,MAAM,QAAQ,QAAQ,SAAS,eAAe,UAAU,CAAC,OAAO,cAAc,cAAc,OAAO,MAAM,KAAK,QAAQ,OAAO,IAAI;EACjI,MAAM,WAAW,SAAS,SAAS,gBAAgB,QAAQ,MAAM,GAAG,IAAI;EACxE,IAAI,UAAU,mBAAmB,MAAM,cAAc,QAAQ;EAC7D,MAAM,aAAa,gBAAgB,WAAW,aAAa;CAC7D;;CAGA,MAAM,UAAU,CAAC,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS;CAE3D,SAAS,WAAW,OAAkC,MAAgB;EACpE,MAAM,UAAU,CAAC,WAAW,MAAM,aAAa,MAAM,SAAA,yBAAmB;EACxE,MAAM,UAAU,UAAU,MAAM,gBAAgB,IAAI,IAAI,MAAM,SAAS,IAAI;EAC3E,IAAI,CAAC,SAAS;EAEd,IAAI,QAAQ,IAAI,MAAM,eAAe;EACrC,MAAM,aAAa,aAAa,QAAQ,KAAM,UAAU,SAAS,SAAU;CAC7E;CAEA,SAAS,YAAY,OAAkC,MAAgB;EACrE,IAAI,CAAC,MAAM,cAAc,SAAS,MAAM,aAA4B,GAAG,MAAM,UAAU,IAAI;CAC7F;CAEA,SAAS,OAAO,OAAkC,MAAgB;EAChE,IAAI,SAAS;GACX,MAAM,eAAe;GACrB,MAAW,KAAK,IAAI;GACpB;EACF;EACA,MAAM,UAAU,kBAAkB,MAAM,YAAY;EACpD,IAAI,CAAC,SAAS;EACd,MAAM,eAAe;EACrB,MAAW,YAAY,MAAM,SAAS,MAAM,UAAU,MAAM,SAAS,MAAM,OAAO;CACpF;CAIA,MAAM,cAAc,SAAmB;EACrC,MAAM,EAAE,aAAa,gBAAgB,MAAM,OAAO,MAAM,CAAC;EACzD,OACE,qBAAC,qBAAD;GAAqB,OAAM;GAAQ,WAAU;GAA7C,UAAA;IACE,oBAAC,mBAAD,EAAA,UAAoB,EAAE,kBAAkB,EAAqB,CAAA;IAC5D,YAAY,KAAI,SACf,qBAAC,0BAAD;KAEE,SAAS,CAAC,YAAY,SAAS,KAAK,EAAE;KACtC,kBAAiB,YAAW,MAAM,cAAc,KAAK,KAAK,KAAK,IAAI,CAAC,OAAO;KAE3E,WAAU,UAAS,MAAM,eAAe;KAL1C,UAAA,CAOE,oBAAC,MAAD,EAAM,MAAM,KAAK,KAAO,CAAA,GACvB,KAAK,KACkB;IARnB,GAAA,KAAK,EAQc,CAC3B;IACA,YAAY,SAAS,KACpB,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,uBAAD,CAAwB,CAAA,GACxB,qBAAC,kBAAD;KAAkB,gBAAgB,MAAM,YAAY,KAAK,GAAG;KAA5D,UAAA,CACE,oBAAC,MAAD,EAAM,MAAK,oBAAqB,CAAA,GAC/B,EAAE,mBAAmB,CACN;IAClB,CAAA,CAAA,EAAA,CAAA;GAEe;;CAEzB;CAEA,MAAM,aAAa,MAAgB,UAAkB;EACnD,MAAM,MAAM,MAAM,OAAO,MAAM,CAAC;EAChC,MAAM,MAAM,MAAM,QAAQ,IAAI;EAC9B,MAAM,WAAW,IAAI,YAAY,SAAS;EAC1C,MAAM,UAAU,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,SAAS;EAC7D,MAAM,SAAS,WAAW,MAAM,MAAM,OAAO;EAC7C,OACE,qBAAA,YAAA,EAAA,UAAA,CACE,qBAAC,OAAD;GACE,MAAK;GACL,UAAU;GACV,cAAY,QAAQ;GACpB,iBAAe,IAAI,aAAa,IAAI,OAAO,KAAA;GAC3C,iBAAe,IAAI,SAAS,OAAO,KAAA;GACnC,WAAW,GACT,8KACA,IAAI,UAAU,0CACd,IAAI,YAAY,YAChB,IAAI,MAAM,MAAM,uBAChB,WAAW,6CACX,IAAI,UAAU,YAChB;GACA,WAAW,MAAM,YAAY,IAAI;GACjC,eAAe,MAAM,SAAS,IAAI;GAClC,YAAW,UAAS,aAAa,OAAO,IAAI;GAC5C,cAAa,UAAS,YAAY,OAAO,IAAI;GAC7C,aAAY,UAAS,WAAW,OAAO,IAAI;GAC3C,cAAa,UAAS,YAAY,OAAO,IAAI;GAC7C,SAAQ,UAAS,OAAO,OAAO,IAAI;GACnC,iBAAiB,MAAM,QAAQ;GArBjC,UAAA;IAuBG,IAAI,aAEC,oBAAC,QAAD;KAAM,WAAU;KAAgB,UAAS,UAAS,eAAe,OAAO,IAAI;KAC1E,UAAA,oBAAC,MAAD;MAAM,MAAK;MAAyB,WAAW,GAAG,uDAAuD,IAAI,QAAQ,WAAW;KAAI,CAAA;IAChI,CAAA,IAER,cAAc,IAAI,KAAK,oBAAC,QAAD,EAAM,WAAU,oBAAqB,CAAA;IAChE,oBAAC,MAAD;KAAM,MAAM,KAAK;KAAM,OAAO,KAAK,OAAO,EAAE,OAAO,KAAK,KAAK,IAAI,KAAA;IAAY,CAAA;IAE5E,IAAI,WAEC,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,OAAD;MACE,OAAO,IAAI,SAAS;MACpB,WAAU;MACV,WAAA;MACA,cAAY,EAAE,kBAAkB;MAChC,gBAAc,CAAC,CAAC,IAAI,SAAS;MAC7B,WAAU,UAAS,MAAM,eAAe,MAAM,OAAO,KAAK;MAC1D,UAAS,UAAS,MAAM,cAAc,OAAO;MAC7C,UAAS,UAAS,MAAM,gBAAgB;MACxC,YAAY,UAAU;OACpB,MAAM,gBAAgB;OACtB,IAAI,MAAM,QAAQ,SAAS,MAAW,aAAa;YAC9C,IAAI,MAAM,QAAQ,UAAU,MAAM,aAAa;MACtD;MACA,cAAc,KAAK,MAAM,WAAW;KACrC,CAAA,GACA,IAAI,SAAS,SAAS,oBAAC,KAAD;MAAG,WAAU;MAA2B,MAAK;MAAQ,UAAS,UAAS,MAAM,gBAAgB;MAAI,UAAA,IAAI,SAAS;KAAS,CAAA,CAC3I;IAGL,CAAA,IAAA,qBAAA,YAAA,EAAA,UAAA;KACG,UACC,oBAAC,QAAD;MACE,WAAU;MACV,OAAO,EAAE,iBAAiB,OAAO,MAAM;MACvC,OAAO,OAAO;MACd,cAAY,OAAO;MACnB,MAAK;MACL,mBAAA;KACD,CAAA;KAEH,oBAAC,QAAD;MAAM,WAAU;MAA0B,OAAO,KAAK;MAAO,UAAA,oBAAC,OAAD;OAAO,OAAO,KAAK;OAAO,OAAO,IAAI;MAAQ,CAAA;KAAO,CAAA;KAChH,KAAK,cAAc,oBAAC,MAAD;MAAM,MAAK;MAAsB,WAAU;KAAkC,CAAA;KACjG,qBAAC,OAAD;MAAK,WAAU;MAAgB,UAAS,UAAS,MAAM,gBAAgB;MAAvE,UAAA,CACG,IAAI,cACH,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,qBAAD;OAAqB,SAAA;OACnB,UAAA,oBAAC,QAAD;QACE,MAAK;QACL,SAAS,WAAW,cAAc;QAClC,WAAW,GAAG,CAAC,YAAY,eAAe;QAC1C,OAAO,EAAE,mBAAmB;QAC5B,cAAY,EAAE,mBAAmB;QAEjC,UAAA,oBAAC,MAAD,EAAM,MAAK,kBAAmB,CAAA;OACxB,CAAA;MACW,CAAA,GACpB,WAAW,IAAI,CACJ,EAAA,CAAA,GAEhB,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA;QACG,KAAK,SAAS,eAAe,KAAK,WACjC,oBAAC,QAAD;SAAQ,MAAK;SAAU,SAAQ;SAAQ,OAAO,EAAE,kBAAkB;SAAG,cAAY,EAAE,kBAAkB;SAAG,eAAe,MAAM,MAAM,KAAK,GAAG;SACzI,UAAA,oBAAC,MAAD,EAAM,MAAK,iBAAkB,CAAA;QACvB,CAAA;QAET,MAAM,SAAS,IAAI,KAClB,oBAAC,QAAD;SAAQ,MAAK;SAAU,SAAQ;SAAQ,OAAO,EAAE,YAAY;SAAG,cAAY,EAAE,YAAY;SAAG,eAAe,MAAM,MAAM,IAAI;SACzH,UAAA,oBAAC,MAAD,EAAM,MAAK,iBAAkB,CAAA;QACvB,CAAA;QAET,IAAI,SAAS,KACZ,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,qBAAD;SAAqB,SAAA;SACnB,UAAA,oBAAC,QAAD;UAAQ,MAAK;UAAU,SAAQ;UAAQ,OAAO,EAAE,UAAU;UAAG,cAAY,EAAE,UAAU;UACnF,UAAA,oBAAC,MAAD,EAAM,MAAK,gBAAiB,CAAA;SACtB,CAAA;QACW,CAAA,GACrB,oBAAC,qBAAD;SAAqB,OAAM;SAAQ,WAAU;SAAS,mBAAkB,UAAS,MAAM,eAAe;SACnG,UAAA,IAAI,KAAK,OAAO,UACf,qBAAC,OAAD,EAAA,UAAA,CACG,QAAQ,KAAK,oBAAC,uBAAD,CAAwB,CAAA,GACrC,MAAM,KAAI,UACT,qBAAC,kBAAD;UAAoC,UAAU,MAAM;UAApD,UAAA,CACE,oBAAC,MAAD,EAAM,MAAM,MAAM,KAAO,CAAA,GACxB,MAAM,KACS;SAHK,GAAA,MAAM,KAGX,CACnB,CACE,EAAA,GARK,KAQL,CACN;QACkB,CAAA,CACT,EAAA,CAAA;QAEf,KAAK,SAAS,cAAc,kBAAkB;SAAE,IAAI,KAAK;SAAK,OAAO,KAAK;QAAM,CAAC;SAChF,KAAK,SAAS,cAAc,KAAK,SAAS,aAC1C,oBAAC,QAAD;SACE,MAAK;SACL,SAAQ;SACR,WAAU;SACV,cAAY,EAAE,aAAa;SAC3B,UAAU,IAAI;SACd,eAAe,KAAK,MAAM,OAAO,IAAI;SAErC,UAAA,oBAAC,MAAD;UAAM,MAAM,IAAI,WAAW,2BAA2B;UAAoB,WAAW,GAAG,IAAI,YAAY,cAAc;SAAI,CAAA;QACpH,CAAA;OAEP;MACF,CAAA,CAAA;;IACL,EAAA,CAAA;GAEL;EACJ,CAAA,GAAA,WAAW,oBAAC,KAAD;GAAG,WAAU;GAAuC,MAAK;GAAU,UAAA;EAAW,CAAA,CAC1F,EAAA,CAAA;CAEN;CAEA,MAAM,eAAe,MAA2B,UAC9C,oBAAC,MAAD;EAAI,MAAM,UAAU,IAAI,SAAS;EAAS,cAAY,UAAU,IAAI,EAAE,WAAW,IAAI,KAAA;EAAW,KAAK,UAAU,IAAI,cAAc,KAAA;EAAW,WAAW,GAAG,qBAAqB,QAAQ,KAAK,kCAAkC;EAC3N,UAAA,KAAK,KAAI,SACR,oBAAC,MAAD;GAAmB,MAAK;GACtB,UAAA,qBAAC,aAAD;IAAa,MAAM,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC;IAAzC,UAAA,CACG,UAAU,MAAM,KAAK,GACrB,KAAK,UAAU,SAAS,oBAAC,oBAAD,EAAA,UAAqB,YAAY,KAAK,UAAU,QAAQ,CAAC,EAAsB,CAAA,IAAI,IACjG;;EACX,GALK,KAAK,GAKV,CACL;CACC,CAAA;CAGN,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,uBAAuB,SAAS;EAAnD,UAAA;GACE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,oBAAC,MAAD;OAAM,MAAK;OAAkB,WAAU;MAA+F,CAAA;MACtI,oBAAC,OAAD;OACE,OAAO,MAAM;OACb,WAAU;OACV,aAAa,EAAE,6BAA6B;OAC5C,cAAY,EAAE,6BAA6B;OAC3C,WAAU,UAAS,MAAM,cAAc,MAAM,OAAO,KAAK;OACzD,YAAY,UAAU;QACpB,IAAI,MAAM,QAAQ,UAAU,MAAM,cAAc,EAAE;OACpD;MACD,CAAA;MACA,MAAM,cACL,oBAAC,QAAD;OACE,MAAK;OACL,SAAQ;OACR,WAAU;OACV,cAAY,EAAE,uBAAuB;OACrC,eAAe,MAAM,cAAc,EAAE;OAErC,UAAA,oBAAC,MAAD,EAAM,MAAK,aAAc,CAAA;MACnB,CAAA;KAEP;IACJ,CAAA,GAAA,oBAEC,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,gBAAD;KAAgB,SAAA;KACd,UAAA,oBAAC,QAAD;MACE,MAAK;MACL,SAAS,aAAa,SAAS,cAAc;MAC7C,OAAO,EAAE,yBAAyB;MAClC,cAAY,EAAE,yBAAyB;MAEvC,UAAA,oBAAC,MAAD,EAAM,MAAK,wBAAyB,CAAA;KAC9B,CAAA;IACM,CAAA,GAChB,oBAAC,gBAAD;KAAgB,MAAK;KAAS,OAAM;KAAM,YAAY;KAAG,WAAU;KAAiB,mBAAkB,UAAS,MAAM,eAAe;KAClI,UAAA,qBAAC,OAAD;MAAK,MAAK;MAAO,cAAY,EAAE,yBAAyB;MAAxD,UAAA,CACG,MAAM,QAAQ,KAAK,WAAW;OAC7B,MAAM,QAAQ,aAAa,SAAS,OAAO,EAAE;OAC7C,OACE,qBAAC,UAAD;QAEE,MAAK;QACL,MAAK;QACL,gBAAc;QACd,WAAW;QACX,eAAe,MAAM,eAAe,OAAO,IAAI,CAAC,KAAK;QANvD,UAAA;SAQE,oBAAC,QAAD;UAAM,WAAU;UAAiC,OAAO,EAAE,iBAAiB,OAAO,MAAM;SAAI,CAAA;SAC5F,oBAAC,QAAD;UAAM,WAAU;UAAY,UAAA,OAAO;SAAY,CAAA;SAC9C,SAAS,oBAAC,MAAD;UAAM,MAAK;UAAiB,WAAU;SAA6B,CAAA;QACvE;OAVD,GAAA,OAAO,EAUN;MAEZ,CAAC,GACA,aAAa,SAAS,KACrB,qBAAC,UAAD;OAAQ,MAAK;OAAS,MAAK;OAAW,WAAW;OAAe,eAAe,MAAM,kBAAkB;OAAvG,UAAA,CACE,oBAAC,MAAD;QAAM,MAAK;QAAoB,WAAU;OAA2C,CAAA,GACpF,oBAAC,QAAD;QAAM,WAAU;QAAY,UAAA,EAAE,yBAAyB;OAAQ,CAAA,CACzD;MAEP,CAAA,CAAA;;IACS,CAAA,CACT,EAAA,CAAA,CAER;;GAEL,oBAAC,OAAD;IAAK,WAAU;IACb,UAAA,oBAAC,iBAAD,EAAA,UACE,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,gBAAD;KAAgB,SAAA;KAEd,UAAA,oBAAC,QAAD;MAAM,WAAU;MACd,UAAA,qBAAC,QAAD;OACE,MAAK;OACL,SAAS,MAAM,UAAU,cAAc;OACvC,UAAU,CAAC;OACX,gBAAc,MAAM;OACpB,eAAe,QAAQ,UAAU;QAAE,MAAM,OAAO,WAAW,MAAM,OAAO,aAAa,SAAS,YAAY;OAAO,CAAC;OALpH,UAAA,CAOE,oBAAC,MAAD,EAAM,MAAM,MAAM,UAAU,wBAAwB,uBAAyB,CAAA,GAC5E,EAAE,MAAM,UAAU,mBAAmB,mBAAmB,CACnD;;KACJ,CAAA;IACQ,CAAA,GACf,CAAC,kBAAkB,oBAAC,gBAAD,EAAA,UAAiB,EAAE,uBAAuB,EAAkB,CAAA,CACzE,EAAA,CAAA,EACM,CAAA;GACd,CAAA;GAEJ,KAAK,kBACJ,oBAAC,OAAD;IAAK,WAAU;IACb,UAAA,qBAAC,QAAD;KAAQ,MAAK;KAAK,SAAQ;KAAY,eAAe,MAAM,gBAAgB;KAA3E,UAAA,CACE,oBAAC,MAAD,EAAM,MAAK,oBAAqB,CAAA,GAC/B,EAAE,mBAAmB,CAChB;;GACL,CAAA;GAGN,kBACC,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,OAAD;KACE,OAAO,eAAe;KACtB,WAAU;KACV,WAAA;KACA,aAAa,eAAe,SAAS,EAAE,6BAA6B,EAAE,QAAQ,eAAe,OAAO,CAAC,IAAI,EAAE,yBAAyB;KACpI,cAAY,EAAE,kBAAkB;KAChC,gBAAc,CAAC,CAAC,eAAe;KAC/B,WAAU,UAAS,MAAM,eAAe,MAAM,OAAO,KAAK;KAC1D,YAAY,UAAU;MACpB,IAAI,MAAM,QAAQ,SAAS,MAAW,mBAAmB;WACpD,IAAI,MAAM,QAAQ,UAAU,MAAM,mBAAmB;KAC5D;KACA,cAAc,MAAM,mBAAmB;IACxC,CAAA,GACA,eAAe,SAAS,oBAAC,KAAD;KAAG,WAAU;KAAkC,MAAK;KAAS,UAAA,eAAe;IAAS,CAAA,CAC3G;;GAGN,OAAO,SAAS,KACf,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,QAAD;KAAQ,MAAK;KAAK,SAAQ;KAAQ,OAAO,EAAE,kBAAkB;KAAG,cAAY,EAAE,kBAAkB;KAAG,eAAe,MAAM,QAAQ;KAAhI,UAAA,CACE,oBAAC,MAAD,EAAM,MAAK,0BAA2B,CAAA,GACrC,eAAe,SAAS,EAAE,iBAAiB,CACtC;IACP,CAAA,GAAA,OAAO,KAAK,OAAO,UAClB,qBAAC,UAAD,EAAA,UAAA,CACE,oBAAC,MAAD;KAAM,MAAK;KAAyB,WAAU;IAAyC,CAAA,GACtF,UAAU,OAAO,SAAS,IACvB,oBAAC,QAAD;KAAM,WAAU;KAAsC,gBAAa;KAAY,UAAA,MAAM;IAAY,CAAA,IACjG,oBAAC,QAAD;KAAQ,MAAK;KAAK,SAAQ;KAAQ,eAAe,MAAM,MAAM,MAAM,GAAG;KAAI,UAAA,MAAM;IAAc,CAAA,CAC1F,EAAA,GALK,MAAM,GAKX,CACX,CACE;;GAGN,CAAC,MAAM,QAAQ,CAAC,MAAM,UACnB,oBAAC,KAAD;IAAG,WAAU;IAA+C,UAAA,MAAM,SAAS,OAAO,EAAE,iBAAiB,IAAI,EAAE,cAAc;GAAK,CAAA,IAC9H,YAAY,KAAK,OAAO,CAAC;GAE5B,KAAK,aAAa,oBAAC,KAAD;IAAG,WAAU;IAA+C,UAAA,EAAE,gBAAgB;GAAK,CAAA;GACrG,KAAK,WAAW,oBAAC,KAAD;IAAG,WAAU;IAA+C,UAAA,EAAE,YAAY;GAAK,CAAA;EAC7F;;AAET"}
|