@abraca/nuxt 2.0.10 → 2.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/dist/module.d.mts +68 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +99 -4
- package/dist/runtime/components/ACodeEditor.d.vue.ts +26 -0
- package/dist/runtime/components/ACodeEditor.vue +268 -0
- package/dist/runtime/components/ACodeEditor.vue.d.ts +26 -0
- package/dist/runtime/components/ADocumentTree.vue +52 -20
- package/dist/runtime/components/AEditor.d.vue.ts +20 -13
- package/dist/runtime/components/AEditor.vue +55 -2
- package/dist/runtime/components/AEditor.vue.d.ts +20 -13
- package/dist/runtime/components/ANodePanel.vue +64 -60
- package/dist/runtime/components/ANotificationBell.d.vue.ts +1 -1
- package/dist/runtime/components/ANotificationBell.vue.d.ts +1 -1
- package/dist/runtime/components/ASpaceFormModal.d.vue.ts +2 -2
- package/dist/runtime/components/ASpaceFormModal.vue.d.ts +2 -2
- package/dist/runtime/components/aware/APresenceBlobs.d.vue.ts +29 -1
- package/dist/runtime/components/aware/APresenceBlobs.vue +54 -8
- package/dist/runtime/components/aware/APresenceBlobs.vue.d.ts +29 -1
- package/dist/runtime/components/aware/APresenceCursors.d.vue.ts +11 -0
- package/dist/runtime/components/aware/APresenceCursors.vue +74 -9
- package/dist/runtime/components/aware/APresenceCursors.vue.d.ts +11 -0
- package/dist/runtime/components/aware/AToggleGroup.d.vue.ts +28 -13
- package/dist/runtime/components/aware/AToggleGroup.vue +56 -20
- package/dist/runtime/components/aware/AToggleGroup.vue.d.ts +28 -13
- package/dist/runtime/components/docs/ADocsNavigation.d.vue.ts +1 -1
- package/dist/runtime/components/docs/ADocsNavigation.vue.d.ts +1 -1
- package/dist/runtime/components/docs/ADocsSearchButton.d.vue.ts +1 -1
- package/dist/runtime/components/docs/ADocsSearchButton.vue.d.ts +1 -1
- package/dist/runtime/components/docs/ADocsToc.d.vue.ts +2 -2
- package/dist/runtime/components/docs/ADocsToc.vue.d.ts +2 -2
- package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +1 -1
- package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +1 -1
- package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +1 -1
- package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +1 -1
- package/dist/runtime/components/editor/ANodeInlineLabel.d.vue.ts +1 -1
- package/dist/runtime/components/editor/ANodeInlineLabel.vue.d.ts +1 -1
- package/dist/runtime/components/registry/APluginBrowser.d.vue.ts +23 -0
- package/dist/runtime/components/registry/APluginBrowser.vue +155 -0
- package/dist/runtime/components/registry/APluginBrowser.vue.d.ts +23 -0
- package/dist/runtime/components/registry/APluginCapabilityDialog.d.vue.ts +17 -0
- package/dist/runtime/components/registry/APluginCapabilityDialog.vue +159 -0
- package/dist/runtime/components/registry/APluginCapabilityDialog.vue.d.ts +17 -0
- package/dist/runtime/components/registry/APluginCard.d.vue.ts +20 -0
- package/dist/runtime/components/registry/APluginCard.vue +91 -0
- package/dist/runtime/components/registry/APluginCard.vue.d.ts +20 -0
- package/dist/runtime/components/registry/APluginDetail.d.vue.ts +18 -0
- package/dist/runtime/components/registry/APluginDetail.vue +252 -0
- package/dist/runtime/components/registry/APluginDetail.vue.d.ts +18 -0
- package/dist/runtime/components/renderers/ACodeRenderer.d.vue.ts +15 -0
- package/dist/runtime/components/renderers/ACodeRenderer.vue +68 -0
- package/dist/runtime/components/renderers/ACodeRenderer.vue.d.ts +15 -0
- package/dist/runtime/components/renderers/AGraphRenderer.vue +416 -120
- package/dist/runtime/components/renderers/AProseRenderer.d.vue.ts +2 -2
- package/dist/runtime/components/renderers/AProseRenderer.vue.d.ts +2 -2
- package/dist/runtime/components/shell/ABreadcrumbForDoc.d.vue.ts +11 -0
- package/dist/runtime/components/shell/ABreadcrumbForDoc.vue +16 -0
- package/dist/runtime/components/shell/ABreadcrumbForDoc.vue.d.ts +11 -0
- package/dist/runtime/components/shell/ASettingsSection.d.vue.ts +35 -0
- package/dist/runtime/components/shell/ASettingsSection.vue +26 -0
- package/dist/runtime/components/shell/ASettingsSection.vue.d.ts +35 -0
- package/dist/runtime/components/shell/ASidebar.d.vue.ts +1 -1
- package/dist/runtime/components/shell/ASidebar.vue.d.ts +1 -1
- package/dist/runtime/components/shell/AUserMenu.d.vue.ts +3 -0
- package/dist/runtime/components/shell/AUserMenu.vue +4 -0
- package/dist/runtime/components/shell/AUserMenu.vue.d.ts +3 -0
- package/dist/runtime/composables/useAbracadabraSchema.d.ts +83 -0
- package/dist/runtime/composables/useAbracadabraSchema.js +52 -0
- package/dist/runtime/composables/useAggregatedPresence.d.ts +1 -6
- package/dist/runtime/composables/useCalendarView.d.ts +1 -1
- package/dist/runtime/composables/useChat.js +1 -0
- package/dist/runtime/composables/useDocBreadcrumb.d.ts +21 -0
- package/dist/runtime/composables/useDocBreadcrumb.js +33 -0
- package/dist/runtime/composables/useDocEntryTyped.d.ts +60 -0
- package/dist/runtime/composables/useDocEntryTyped.js +70 -0
- package/dist/runtime/composables/useEditorDragHandle.js +18 -0
- package/dist/runtime/composables/useEditorSuggestions.js +2 -1
- package/dist/runtime/composables/useInstalledPlugins.d.ts +3 -21
- package/dist/runtime/composables/useInstalledPlugins.js +2 -12
- package/dist/runtime/composables/useMetaMenuItems.d.ts +21 -0
- package/dist/runtime/composables/useMetaMenuItems.js +115 -0
- package/dist/runtime/composables/useMetaValidator.d.ts +27 -0
- package/dist/runtime/composables/useMetaValidator.js +10 -0
- package/dist/runtime/composables/usePluginCatalog.d.ts +161 -0
- package/dist/runtime/composables/usePluginCatalog.js +234 -0
- package/dist/runtime/composables/useQuery.d.ts +79 -0
- package/dist/runtime/composables/useQuery.js +97 -0
- package/dist/runtime/composables/useSpaces.js +4 -5
- package/dist/runtime/composables/useTableView.d.ts +3 -3
- package/dist/runtime/composables/useTypedDoc.d.ts +97 -0
- package/dist/runtime/composables/useTypedDoc.js +114 -0
- package/dist/runtime/composables/useWebRTC.js +44 -5
- package/dist/runtime/extensions/document-meta.js +5 -0
- package/dist/runtime/extensions/timeline.d.ts +11 -0
- package/dist/runtime/extensions/timeline.js +52 -0
- package/dist/runtime/extensions/views/DocumentMetaView.d.vue.ts +4 -0
- package/dist/runtime/extensions/views/DocumentMetaView.vue +63 -0
- package/dist/runtime/extensions/views/DocumentMetaView.vue.d.ts +4 -0
- package/dist/runtime/extensions/views/TimelineItemView.d.vue.ts +4 -0
- package/dist/runtime/extensions/views/TimelineItemView.vue +131 -0
- package/dist/runtime/extensions/views/TimelineItemView.vue.d.ts +4 -0
- package/dist/runtime/extensions/views/TimelineView.d.vue.ts +9 -0
- package/dist/runtime/extensions/views/TimelineView.vue +29 -0
- package/dist/runtime/extensions/views/TimelineView.vue.d.ts +9 -0
- package/dist/runtime/locale.d.ts +2 -0
- package/dist/runtime/locale.js +2 -0
- package/dist/runtime/plugin-abracadabra.client.js +107 -6
- package/dist/runtime/plugin-registry.d.ts +11 -30
- package/dist/runtime/plugin-registry.js +2 -82
- package/dist/runtime/plugins/core.plugin.js +10 -4
- package/dist/runtime/server/api/_abracadabra/spaces.get.d.ts +1 -1
- package/dist/runtime/server/plugins/abracadabra-service.js +28 -0
- package/dist/runtime/server/utils/docCache.js +24 -3
- package/dist/runtime/server/utils/schemaServerSupport.d.ts +52 -0
- package/dist/runtime/server/utils/schemaServerSupport.js +51 -0
- package/dist/runtime/types.d.ts +63 -46
- package/dist/runtime/utils/docTypes.d.ts +15 -0
- package/dist/runtime/utils/docTypes.js +20 -0
- package/dist/runtime/utils/loadCodeMirror.d.ts +32 -0
- package/dist/runtime/utils/loadCodeMirror.js +65 -0
- package/dist/runtime/utils/markdownToYjs.d.ts +1 -23
- package/dist/runtime/utils/markdownToYjs.js +5 -440
- package/dist/runtime/utils/schemaSupport.d.ts +60 -0
- package/dist/runtime/utils/schemaSupport.js +40 -0
- package/dist/runtime/utils/yjsConvert.d.ts +1 -14
- package/dist/runtime/utils/yjsConvert.js +5 -331
- package/package.json +84 -23
|
@@ -10,14 +10,14 @@ type __VLS_Props = {
|
|
|
10
10
|
};
|
|
11
11
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, Record<PropertyKey, unknown>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
12
|
rename: (label: string) => any;
|
|
13
|
+
ready: () => any;
|
|
13
14
|
update: (content: any) => any;
|
|
14
15
|
updateMeta: (patch: Partial<DocPageMeta>) => any;
|
|
15
|
-
ready: () => any;
|
|
16
16
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
17
|
onRename?: ((label: string) => any) | undefined;
|
|
18
|
+
onReady?: (() => any) | undefined;
|
|
18
19
|
onUpdate?: ((content: any) => any) | undefined;
|
|
19
20
|
onUpdateMeta?: ((patch: Partial<DocPageMeta>) => any) | undefined;
|
|
20
|
-
onReady?: (() => any) | undefined;
|
|
21
21
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
22
|
declare const _default: typeof __VLS_export;
|
|
23
23
|
export default _default;
|
|
@@ -10,14 +10,14 @@ type __VLS_Props = {
|
|
|
10
10
|
};
|
|
11
11
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, Record<PropertyKey, unknown>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
12
|
rename: (label: string) => any;
|
|
13
|
+
ready: () => any;
|
|
13
14
|
update: (content: any) => any;
|
|
14
15
|
updateMeta: (patch: Partial<DocPageMeta>) => any;
|
|
15
|
-
ready: () => any;
|
|
16
16
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
17
|
onRename?: ((label: string) => any) | undefined;
|
|
18
|
+
onReady?: (() => any) | undefined;
|
|
18
19
|
onUpdate?: ((content: any) => any) | undefined;
|
|
19
20
|
onUpdateMeta?: ((patch: Partial<DocPageMeta>) => any) | undefined;
|
|
20
|
-
onReady?: (() => any) | undefined;
|
|
21
21
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
22
|
declare const _default: typeof __VLS_export;
|
|
23
23
|
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
/** Document ID at the leaf of the breadcrumb */
|
|
3
|
+
docId: string | null | undefined;
|
|
4
|
+
/** Maximum ancestors to walk (default 8) */
|
|
5
|
+
maxDepth?: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
8
|
+
maxDepth: number;
|
|
9
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useDocBreadcrumb } from "../../composables/useDocBreadcrumb";
|
|
3
|
+
const props = defineProps({
|
|
4
|
+
docId: { type: null, required: true },
|
|
5
|
+
maxDepth: { type: Number, required: false, default: 8 }
|
|
6
|
+
});
|
|
7
|
+
const { items } = useDocBreadcrumb(() => props.docId, { maxDepth: props.maxDepth });
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<UBreadcrumb
|
|
12
|
+
v-if="items.length > 0"
|
|
13
|
+
:items="items"
|
|
14
|
+
:ui="{ root: 'min-w-0', list: 'min-w-0 flex-nowrap', item: 'truncate', link: 'truncate' }"
|
|
15
|
+
/>
|
|
16
|
+
</template>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
/** Document ID at the leaf of the breadcrumb */
|
|
3
|
+
docId: string | null | undefined;
|
|
4
|
+
/** Maximum ancestors to walk (default 8) */
|
|
5
|
+
maxDepth?: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
8
|
+
maxDepth: number;
|
|
9
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings section primitive — heading + description + actions slot + content.
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent section pattern for settings pages and panels.
|
|
5
|
+
* Pairs with ASettingsPanel*'s row-style components but is also useful
|
|
6
|
+
* standalone for custom settings layouts.
|
|
7
|
+
*
|
|
8
|
+
* Slots:
|
|
9
|
+
* - `default`: section content
|
|
10
|
+
* - `description`: rich description (overrides `description` prop)
|
|
11
|
+
* - `actions`: top-right inline actions (button, switch, etc.)
|
|
12
|
+
*/
|
|
13
|
+
type __VLS_Props = {
|
|
14
|
+
/** Section title rendered as <h3> */
|
|
15
|
+
title: string;
|
|
16
|
+
/** Optional description rendered under the title */
|
|
17
|
+
description?: string;
|
|
18
|
+
};
|
|
19
|
+
declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {};
|
|
20
|
+
type __VLS_Slots = {} & {
|
|
21
|
+
actions?: (props: typeof __VLS_1) => any;
|
|
22
|
+
} & {
|
|
23
|
+
description?: (props: typeof __VLS_3) => any;
|
|
24
|
+
} & {
|
|
25
|
+
default?: (props: typeof __VLS_5) => any;
|
|
26
|
+
};
|
|
27
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
30
|
+
export default _default;
|
|
31
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
32
|
+
new (): {
|
|
33
|
+
$slots: S;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineProps({
|
|
3
|
+
title: { type: String, required: true },
|
|
4
|
+
description: { type: String, required: false }
|
|
5
|
+
});
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<section class="space-y-3">
|
|
10
|
+
<header class="space-y-1">
|
|
11
|
+
<div class="flex items-center justify-between gap-3">
|
|
12
|
+
<h3 class="text-sm font-semibold text-(--ui-text-highlighted)">
|
|
13
|
+
{{ title }}
|
|
14
|
+
</h3>
|
|
15
|
+
<slot name="actions" />
|
|
16
|
+
</div>
|
|
17
|
+
<p
|
|
18
|
+
v-if="description || $slots.description"
|
|
19
|
+
class="text-xs text-(--ui-text-muted)"
|
|
20
|
+
>
|
|
21
|
+
<slot name="description">{{ description }}</slot>
|
|
22
|
+
</p>
|
|
23
|
+
</header>
|
|
24
|
+
<slot />
|
|
25
|
+
</section>
|
|
26
|
+
</template>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings section primitive — heading + description + actions slot + content.
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent section pattern for settings pages and panels.
|
|
5
|
+
* Pairs with ASettingsPanel*'s row-style components but is also useful
|
|
6
|
+
* standalone for custom settings layouts.
|
|
7
|
+
*
|
|
8
|
+
* Slots:
|
|
9
|
+
* - `default`: section content
|
|
10
|
+
* - `description`: rich description (overrides `description` prop)
|
|
11
|
+
* - `actions`: top-right inline actions (button, switch, etc.)
|
|
12
|
+
*/
|
|
13
|
+
type __VLS_Props = {
|
|
14
|
+
/** Section title rendered as <h3> */
|
|
15
|
+
title: string;
|
|
16
|
+
/** Optional description rendered under the title */
|
|
17
|
+
description?: string;
|
|
18
|
+
};
|
|
19
|
+
declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {};
|
|
20
|
+
type __VLS_Slots = {} & {
|
|
21
|
+
actions?: (props: typeof __VLS_1) => any;
|
|
22
|
+
} & {
|
|
23
|
+
description?: (props: typeof __VLS_3) => any;
|
|
24
|
+
} & {
|
|
25
|
+
default?: (props: typeof __VLS_5) => any;
|
|
26
|
+
};
|
|
27
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
30
|
+
export default _default;
|
|
31
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
32
|
+
new (): {
|
|
33
|
+
$slots: S;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -39,8 +39,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
39
39
|
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
40
40
|
"onUpdate:collapsed"?: ((value: boolean) => any) | undefined;
|
|
41
41
|
}>, {
|
|
42
|
-
width: number;
|
|
43
42
|
open: boolean;
|
|
43
|
+
width: number;
|
|
44
44
|
collapsed: boolean;
|
|
45
45
|
collapsedWidth: number;
|
|
46
46
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -39,8 +39,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
39
39
|
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
40
40
|
"onUpdate:collapsed"?: ((value: boolean) => any) | undefined;
|
|
41
41
|
}>, {
|
|
42
|
-
width: number;
|
|
43
42
|
open: boolean;
|
|
43
|
+
width: number;
|
|
44
44
|
collapsed: boolean;
|
|
45
45
|
collapsedWidth: number;
|
|
46
46
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -8,6 +8,8 @@ type __VLS_Props = {
|
|
|
8
8
|
avatarStyle?: string;
|
|
9
9
|
/** Whether sidebar is collapsed */
|
|
10
10
|
collapsed?: boolean;
|
|
11
|
+
/** Optional secondary line under the name in the menu header (e.g. "Connected · 3 peers") */
|
|
12
|
+
statusLabel?: string;
|
|
11
13
|
/** Extra menu items prepended before default actions */
|
|
12
14
|
extraItems?: DropdownMenuItem[][];
|
|
13
15
|
};
|
|
@@ -23,6 +25,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
23
25
|
color: string;
|
|
24
26
|
collapsed: boolean;
|
|
25
27
|
avatarStyle: string;
|
|
28
|
+
statusLabel: string;
|
|
26
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
27
30
|
declare const _default: typeof __VLS_export;
|
|
28
31
|
export default _default;
|
|
@@ -5,6 +5,7 @@ const props = defineProps({
|
|
|
5
5
|
color: { type: String, required: false, default: "" },
|
|
6
6
|
avatarStyle: { type: String, required: false, default: "" },
|
|
7
7
|
collapsed: { type: Boolean, required: false, default: false },
|
|
8
|
+
statusLabel: { type: String, required: false, default: "" },
|
|
8
9
|
extraItems: { type: Array, required: false }
|
|
9
10
|
});
|
|
10
11
|
const emit = defineEmits(["open-settings", "open-account", "logout"]);
|
|
@@ -16,6 +17,9 @@ const items = computed(() => {
|
|
|
16
17
|
disabled: true
|
|
17
18
|
}
|
|
18
19
|
];
|
|
20
|
+
if (props.statusLabel) {
|
|
21
|
+
userGroup.push({ type: "label", label: props.statusLabel });
|
|
22
|
+
}
|
|
19
23
|
const actionGroup = [
|
|
20
24
|
{
|
|
21
25
|
label: "Account",
|
|
@@ -8,6 +8,8 @@ type __VLS_Props = {
|
|
|
8
8
|
avatarStyle?: string;
|
|
9
9
|
/** Whether sidebar is collapsed */
|
|
10
10
|
collapsed?: boolean;
|
|
11
|
+
/** Optional secondary line under the name in the menu header (e.g. "Connected · 3 peers") */
|
|
12
|
+
statusLabel?: string;
|
|
11
13
|
/** Extra menu items prepended before default actions */
|
|
12
14
|
extraItems?: DropdownMenuItem[][];
|
|
13
15
|
};
|
|
@@ -23,6 +25,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
23
25
|
color: string;
|
|
24
26
|
collapsed: boolean;
|
|
25
27
|
avatarStyle: string;
|
|
28
|
+
statusLabel: string;
|
|
26
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
27
30
|
declare const _default: typeof __VLS_export;
|
|
28
31
|
export default _default;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useAbracadabraSchema — registry handle + opt-in validator surface.
|
|
3
|
+
*
|
|
4
|
+
* Day 2 of the Phase 3 schema rollout. The Nuxt module never imports
|
|
5
|
+
* `@abraca/schema` statically — see `loadKatex.ts` / `schemaSupport.ts`
|
|
6
|
+
* for the rationale (Rule 1: core stays schema-free).
|
|
7
|
+
*
|
|
8
|
+
* Apps attach a `SchemaRegistry` (typically the result of
|
|
9
|
+
* `defineSchema({ types: [Kanban, Calendar, ...] })` from `@abraca/schema`,
|
|
10
|
+
* but any value satisfying `SchemaRegistryLike` works) via the Nuxt
|
|
11
|
+
* `abracadabra:before-boot` hook, e.g.:
|
|
12
|
+
*
|
|
13
|
+
* // app/plugins/abracadabra-schemas.client.ts
|
|
14
|
+
* import { defineSchema, Kanban, Calendar, Doc } from '@abraca/schema'
|
|
15
|
+
* export default defineNuxtPlugin(nuxtApp => {
|
|
16
|
+
* nuxtApp.hook('abracadabra:before-boot', (ctx) => {
|
|
17
|
+
* ctx.attachSchema(defineSchema({ types: [Kanban, Calendar, Doc] }))
|
|
18
|
+
* })
|
|
19
|
+
* })
|
|
20
|
+
*
|
|
21
|
+
* The first attached registry wins for type narrowing; subsequent
|
|
22
|
+
* registries are merged into the same validator-set so multiple
|
|
23
|
+
* boot-time plugins can each contribute their own schemas.
|
|
24
|
+
*/
|
|
25
|
+
import { type ComputedRef } from 'vue';
|
|
26
|
+
import { useNuxtApp } from '#imports';
|
|
27
|
+
import type { SchemaRegistryLike, ValidationResultLike } from '../utils/schemaSupport.js';
|
|
28
|
+
import type { AbracadabraPlugin } from '../types.js';
|
|
29
|
+
export type { SchemaRegistryLike, ValidationResultLike };
|
|
30
|
+
/**
|
|
31
|
+
* Hook payload for `abracadabra:before-boot`. Exposed so consumer
|
|
32
|
+
* plugins can declare their hook signatures with confidence.
|
|
33
|
+
*/
|
|
34
|
+
export interface BeforeBootCtx {
|
|
35
|
+
/** Attach a schema registry. Multiple calls accumulate. */
|
|
36
|
+
attachSchema: (registry: SchemaRegistryLike) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Attach an inline AbracadabraPlugin. Lets host apps contribute
|
|
39
|
+
* mention providers, extensions, suggestion items, etc. without
|
|
40
|
+
* the external-plugin URL-loader dance. Multiple calls accumulate.
|
|
41
|
+
*/
|
|
42
|
+
attachPlugin: (plugin: AbracadabraPlugin) => void;
|
|
43
|
+
}
|
|
44
|
+
declare module '#app' {
|
|
45
|
+
interface RuntimeNuxtHooks {
|
|
46
|
+
'abracadabra:before-boot': (ctx: BeforeBootCtx) => void | Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Internal: collect-and-store registries from the boot hook. Called once
|
|
51
|
+
* by `plugin-abracadabra.client.ts` before the provider is wired.
|
|
52
|
+
*
|
|
53
|
+
* Stored on `nuxtApp` (request-scoped) so multiple roots / SSR workers
|
|
54
|
+
* don't share state.
|
|
55
|
+
*/
|
|
56
|
+
export declare function _collectSchemaRegistries(nuxtApp: ReturnType<typeof useNuxtApp>): Promise<{
|
|
57
|
+
schemas: SchemaRegistryLike[];
|
|
58
|
+
plugins: AbracadabraPlugin[];
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Reactive handle to the registries the app attached at boot.
|
|
62
|
+
*
|
|
63
|
+
* The composable is safe to call before any registry is attached —
|
|
64
|
+
* it returns an empty list and a permissive validator (every meta
|
|
65
|
+
* passes) so renderer code can call it unconditionally.
|
|
66
|
+
*/
|
|
67
|
+
export declare function useAbracadabraSchema(): {
|
|
68
|
+
/** All registries attached at boot. Read-only — frozen after boot. */
|
|
69
|
+
registries: ComputedRef<readonly SchemaRegistryLike[]>;
|
|
70
|
+
/** True if at least one registry has been attached. */
|
|
71
|
+
hasSchema: ComputedRef<boolean>;
|
|
72
|
+
/**
|
|
73
|
+
* Validate `meta` against the first registry that recognises `typeName`.
|
|
74
|
+
* Returns `{ ok: true }` when no registry knows the type (Rule 4).
|
|
75
|
+
*/
|
|
76
|
+
validateMeta: (typeName: string, meta: unknown) => ValidationResultLike;
|
|
77
|
+
/**
|
|
78
|
+
* Run forward migrations on `meta` against the first registry that
|
|
79
|
+
* recognises `typeName`. Returns the input unchanged when no
|
|
80
|
+
* registry knows the type or `@abraca/schema` is not installed.
|
|
81
|
+
*/
|
|
82
|
+
runMigrations: (typeName: string, meta: unknown) => Promise<unknown>;
|
|
83
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { computed } from "vue";
|
|
2
|
+
import { useNuxtApp } from "#imports";
|
|
3
|
+
export async function _collectSchemaRegistries(nuxtApp) {
|
|
4
|
+
const collected = [];
|
|
5
|
+
const plugins = [];
|
|
6
|
+
const ctx = {
|
|
7
|
+
attachSchema: (registry) => {
|
|
8
|
+
if (!registry || typeof registry !== "object") return;
|
|
9
|
+
if (typeof registry.validateMeta !== "function") {
|
|
10
|
+
console.warn(
|
|
11
|
+
"[abracadabra] attachSchema received a value missing validateMeta() \u2014 expected a SchemaRegistry from `@abraca/schema` defineSchema(). Skipping."
|
|
12
|
+
);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
collected.push(registry);
|
|
16
|
+
},
|
|
17
|
+
attachPlugin: (plugin) => {
|
|
18
|
+
if (!plugin || typeof plugin !== "object" || typeof plugin.name !== "string") {
|
|
19
|
+
console.warn("[abracadabra] attachPlugin received an invalid plugin (missing name). Skipping.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
plugins.push(plugin);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
await nuxtApp.callHook("abracadabra:before-boot", ctx);
|
|
26
|
+
nuxtApp._abracadabraSchemas = collected;
|
|
27
|
+
return { schemas: collected, plugins };
|
|
28
|
+
}
|
|
29
|
+
export function useAbracadabraSchema() {
|
|
30
|
+
const nuxtApp = useNuxtApp();
|
|
31
|
+
const stored = nuxtApp._abracadabraSchemas;
|
|
32
|
+
const list = stored ?? [];
|
|
33
|
+
const registries = computed(() => list);
|
|
34
|
+
const hasSchema = computed(() => list.length > 0);
|
|
35
|
+
function validateMeta(typeName, meta) {
|
|
36
|
+
for (const r of list) {
|
|
37
|
+
if (r.types.has(typeName)) {
|
|
38
|
+
return r.validateMeta(typeName, meta);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { ok: true, value: meta };
|
|
42
|
+
}
|
|
43
|
+
async function runMigrations(typeName, meta) {
|
|
44
|
+
const reg = list.find((r) => r.types.has(typeName));
|
|
45
|
+
if (!reg) return meta;
|
|
46
|
+
const { tryLoadSchemaModule } = await import("../utils/schemaSupport.js");
|
|
47
|
+
const mod = await tryLoadSchemaModule();
|
|
48
|
+
if (!mod) return meta;
|
|
49
|
+
return mod.runMigrations(reg, typeName, meta);
|
|
50
|
+
}
|
|
51
|
+
return { registries, hasSchema, validateMeta, runMigrations };
|
|
52
|
+
}
|
|
@@ -71,7 +71,7 @@ export declare function useCalendarView(options: UseCalendarViewOptions): {
|
|
|
71
71
|
nextPeriod: () => void;
|
|
72
72
|
goToday: () => void;
|
|
73
73
|
goToMonth: (y: number, m: number) => void;
|
|
74
|
-
weekStartOffset: import("vue").ComputedRef<
|
|
74
|
+
weekStartOffset: import("vue").ComputedRef<0 | 1>;
|
|
75
75
|
weekDayHeaders: import("vue").ComputedRef<("Sun" | "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat")[]>;
|
|
76
76
|
weekViewDays: import("vue").ComputedRef<3 | 7>;
|
|
77
77
|
weeks: import("vue").ComputedRef<WeekRow[]>;
|
|
@@ -25,6 +25,7 @@ export function buildDmChannelId(a, b) {
|
|
|
25
25
|
return `dm:${[a, b].sort().join(":")}`;
|
|
26
26
|
}
|
|
27
27
|
function normalizeChannel(channelId) {
|
|
28
|
+
if (typeof channelId !== "string" || !channelId) return "";
|
|
28
29
|
return channelId.startsWith("group:") ? channelId.slice("group:".length) : channelId;
|
|
29
30
|
}
|
|
30
31
|
const messagesByChannel = ref({});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDocBreadcrumb — reactive parent chain for a document.
|
|
3
|
+
*
|
|
4
|
+
* Walks up the doc-tree from the given docId to the root, returning
|
|
5
|
+
* the breadcrumb trail as an array of items ready for UBreadcrumb.
|
|
6
|
+
* Caps depth at `maxDepth` (default 8) to handle malformed cycles
|
|
7
|
+
* defensively. The last item is the current doc and has no `to`.
|
|
8
|
+
*/
|
|
9
|
+
import { type ComputedRef, type MaybeRef } from 'vue';
|
|
10
|
+
export interface DocBreadcrumbItem {
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
icon: string;
|
|
14
|
+
/** Navigation target — undefined for the current doc */
|
|
15
|
+
to?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function useDocBreadcrumb(docId: MaybeRef<string | null | undefined>, options?: {
|
|
18
|
+
maxDepth?: number;
|
|
19
|
+
}): {
|
|
20
|
+
items: ComputedRef<DocBreadcrumbItem[]>;
|
|
21
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { computed, unref } from "vue";
|
|
2
|
+
import { resolveDocType } from "../utils/docTypes.js";
|
|
3
|
+
import { useRuntimeConfig } from "#imports";
|
|
4
|
+
import { useDocTree } from "./useDocTree.js";
|
|
5
|
+
export function useDocBreadcrumb(docId, options = {}) {
|
|
6
|
+
const maxDepth = options.maxDepth ?? 8;
|
|
7
|
+
const config = useRuntimeConfig();
|
|
8
|
+
const docBasePath = config.public?.abracadabra?.docBasePath ?? "/doc";
|
|
9
|
+
const tree = useDocTree();
|
|
10
|
+
const items = computed(() => {
|
|
11
|
+
const startId = unref(docId);
|
|
12
|
+
if (!startId) return [];
|
|
13
|
+
const trail = [];
|
|
14
|
+
let id = startId;
|
|
15
|
+
let safety = maxDepth;
|
|
16
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17
|
+
while (id && safety-- > 0 && !seen.has(id)) {
|
|
18
|
+
seen.add(id);
|
|
19
|
+
const entry = tree.getEntry(id);
|
|
20
|
+
if (!entry) break;
|
|
21
|
+
const isCurrent = id === startId;
|
|
22
|
+
trail.unshift({
|
|
23
|
+
id,
|
|
24
|
+
label: entry.label || "Untitled",
|
|
25
|
+
icon: resolveDocType(entry.type ?? "doc")?.icon ?? "i-lucide-file-text",
|
|
26
|
+
...isCurrent ? {} : { to: `${docBasePath}/${id}` }
|
|
27
|
+
});
|
|
28
|
+
id = entry.parentId ?? null;
|
|
29
|
+
}
|
|
30
|
+
return trail;
|
|
31
|
+
});
|
|
32
|
+
return { items };
|
|
33
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDocEntryTyped — reactive typed projection of a single doc-tree entry.
|
|
3
|
+
*
|
|
4
|
+
* Day 3 of the Phase 3 schema rollout. Pairs with `useTypedDoc` (which
|
|
5
|
+
* exposes write methods) — this composable is the renderer-side read
|
|
6
|
+
* surface, including optional auto-migrate-on-read.
|
|
7
|
+
*
|
|
8
|
+
* Behaviour:
|
|
9
|
+
* - Returns a `ComputedRef<TypedTreeEntry<M> | null>` that updates when
|
|
10
|
+
* the underlying Y.Map entry changes.
|
|
11
|
+
* - Returns `null` when the entry is missing OR its stored `type`
|
|
12
|
+
* doesn't match the requested `expectedType` (cross-schema reads
|
|
13
|
+
* return null — same contract as `useTypedDoc.get`).
|
|
14
|
+
* - When `options.migrate` (or module-config `schema.migrateOnRead`)
|
|
15
|
+
* is true, the composable lazy-loads `@abraca/schema` and runs
|
|
16
|
+
* forward migrations before returning. Until the schema module
|
|
17
|
+
* resolves, the composable returns the un-migrated projection so
|
|
18
|
+
* consumers never observe a flicker through `null`.
|
|
19
|
+
*
|
|
20
|
+
* Migrations are read-only — they don't write back to the doc-tree.
|
|
21
|
+
* Persistence happens on the next typed `update`/`set` call (consumers
|
|
22
|
+
* who want write-back should call `useTypedDoc(...).set(type, id, m)`
|
|
23
|
+
* with the migrated meta).
|
|
24
|
+
*/
|
|
25
|
+
import { type ComputedRef, type Ref } from 'vue';
|
|
26
|
+
import { type SchemaModule, type SchemaRegistryLike } from '../utils/schemaSupport.js';
|
|
27
|
+
type SchemaDocTypeName<S> = S extends {
|
|
28
|
+
__metaMap?: infer M;
|
|
29
|
+
} ? keyof M & string : string;
|
|
30
|
+
type SchemaMetaOf<S, N extends string> = S extends {
|
|
31
|
+
__metaMap?: infer M;
|
|
32
|
+
} ? N extends keyof M ? M[N] : Record<string, unknown> : Record<string, unknown>;
|
|
33
|
+
export interface TypedDocEntry<M> {
|
|
34
|
+
readonly id: string;
|
|
35
|
+
readonly type: string;
|
|
36
|
+
readonly label: string;
|
|
37
|
+
readonly parentId: string | null;
|
|
38
|
+
readonly order: number;
|
|
39
|
+
readonly meta: M | undefined;
|
|
40
|
+
readonly createdAt: number | undefined;
|
|
41
|
+
readonly updatedAt: number | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* True if `meta` was rewritten by `runMigrations`. Useful for
|
|
44
|
+
* renderer authors who want to flag stale storage in the UI.
|
|
45
|
+
*/
|
|
46
|
+
readonly migrated: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface UseDocEntryTypedOptions {
|
|
49
|
+
/**
|
|
50
|
+
* When true, run `@abraca/schema`'s `runMigrations` on the read meta.
|
|
51
|
+
* Defaults to module config `schema.migrateOnRead` (false unless set).
|
|
52
|
+
*/
|
|
53
|
+
migrate?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/** Test-only: reset the module cache so a fresh load runs next call. */
|
|
56
|
+
export declare function __resetUseDocEntryTypedCacheForTests(): void;
|
|
57
|
+
/** Test-only: inject a schema module synchronously (skips dynamic import). */
|
|
58
|
+
export declare function __setSchemaModuleForTests(mod: SchemaModule | null): void;
|
|
59
|
+
export declare function useDocEntryTyped<S extends SchemaRegistryLike>(docId: Ref<string | null | undefined> | string | null | undefined, schema: S, expectedType: SchemaDocTypeName<S>, options?: UseDocEntryTypedOptions): ComputedRef<TypedDocEntry<SchemaMetaOf<S, SchemaDocTypeName<S>>> | null>;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { computed, shallowRef, watch, isRef } from "vue";
|
|
2
|
+
import { useDocTree } from "./useDocTree.js";
|
|
3
|
+
import { useAbracadabraSchema } from "./useAbracadabraSchema.js";
|
|
4
|
+
import { tryLoadSchemaModule } from "../utils/schemaSupport.js";
|
|
5
|
+
import { useRuntimeConfig } from "#imports";
|
|
6
|
+
const _moduleRef = shallowRef(null);
|
|
7
|
+
let _moduleRequested = false;
|
|
8
|
+
function _ensureSchemaModule() {
|
|
9
|
+
if (_moduleRequested) return;
|
|
10
|
+
_moduleRequested = true;
|
|
11
|
+
void tryLoadSchemaModule().then((m) => {
|
|
12
|
+
_moduleRef.value = m;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export function __resetUseDocEntryTypedCacheForTests() {
|
|
16
|
+
_moduleRef.value = null;
|
|
17
|
+
_moduleRequested = false;
|
|
18
|
+
}
|
|
19
|
+
export function __setSchemaModuleForTests(mod) {
|
|
20
|
+
_moduleRef.value = mod;
|
|
21
|
+
_moduleRequested = true;
|
|
22
|
+
}
|
|
23
|
+
function projectEntry(entry, expectedType) {
|
|
24
|
+
if (!entry) return null;
|
|
25
|
+
if (entry.type !== expectedType) return null;
|
|
26
|
+
return {
|
|
27
|
+
id: entry.id,
|
|
28
|
+
type: expectedType,
|
|
29
|
+
label: entry.label,
|
|
30
|
+
parentId: entry.parentId,
|
|
31
|
+
order: entry.order,
|
|
32
|
+
meta: entry.meta,
|
|
33
|
+
createdAt: entry.createdAt,
|
|
34
|
+
updatedAt: entry.updatedAt
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function useDocEntryTyped(docId, schema, expectedType, options = {}) {
|
|
38
|
+
const tree = useDocTree();
|
|
39
|
+
const { runMigrations: _ } = useAbracadabraSchema();
|
|
40
|
+
void _;
|
|
41
|
+
const cfg = useRuntimeConfig().public.abracadabra?.schema;
|
|
42
|
+
const migrateOnRead = options.migrate ?? cfg?.migrateOnRead ?? false;
|
|
43
|
+
if (migrateOnRead) _ensureSchemaModule();
|
|
44
|
+
return computed(() => {
|
|
45
|
+
const id = isRef(docId) ? docId.value : docId;
|
|
46
|
+
if (!id) return null;
|
|
47
|
+
const entry = tree.getEntry(id);
|
|
48
|
+
const projected = projectEntry(entry, expectedType);
|
|
49
|
+
if (!projected) return null;
|
|
50
|
+
if (!migrateOnRead) {
|
|
51
|
+
return { ...projected, migrated: false };
|
|
52
|
+
}
|
|
53
|
+
const mod = _moduleRef.value;
|
|
54
|
+
if (!mod) {
|
|
55
|
+
return { ...projected, migrated: false };
|
|
56
|
+
}
|
|
57
|
+
const before = projected.meta;
|
|
58
|
+
if (before === void 0 || before === null) {
|
|
59
|
+
return { ...projected, migrated: false };
|
|
60
|
+
}
|
|
61
|
+
const after = mod.runMigrations(schema, expectedType, before);
|
|
62
|
+
const migrated = after !== before;
|
|
63
|
+
return {
|
|
64
|
+
...projected,
|
|
65
|
+
meta: migrated ? after : before,
|
|
66
|
+
migrated
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
watch(_moduleRef, () => void 0, { flush: "sync" });
|
|
@@ -73,6 +73,24 @@ export function useEditorDragHandle(pageConfig) {
|
|
|
73
73
|
{ label: "Download image", icon: "i-lucide-download", to: node?.attrs?.src, download: true }
|
|
74
74
|
];
|
|
75
75
|
}
|
|
76
|
+
if (nodeType === "timeline") {
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
label: "Add Event",
|
|
80
|
+
icon: "i-lucide-plus",
|
|
81
|
+
onSelect: () => {
|
|
82
|
+
if (pos === void 0) return;
|
|
83
|
+
const node = editor.state.doc.nodeAt(pos);
|
|
84
|
+
if (!node) return;
|
|
85
|
+
editor.chain().focus().insertContentAt(pos + node.nodeSize - 1, {
|
|
86
|
+
type: "timelineItem",
|
|
87
|
+
attrs: { date: "", label: `Event ${node.childCount + 1}`, icon: "" },
|
|
88
|
+
content: [{ type: "paragraph" }]
|
|
89
|
+
}).run();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
}
|
|
76
94
|
if (nodeType === "table") {
|
|
77
95
|
return [
|
|
78
96
|
{
|
|
@@ -73,7 +73,8 @@ export function useEditorSuggestions(options = {}) {
|
|
|
73
73
|
...extEnabled("mathBlock") ? [{ kind: "mathBlock", label: "Math (block)", icon: "i-lucide-square-sigma", description: "Display-mode LaTeX equation", keywords: ["katex", "latex", "equation", "formula", "math"] }] : [],
|
|
74
74
|
...extEnabled("mathInline") ? [{ kind: "mathInline", label: "Math (inline)", icon: "i-lucide-sigma", description: "Inline LaTeX expression", keywords: ["katex", "latex", "inline math"] }] : [],
|
|
75
75
|
...extEnabled("diff") ? [{ kind: "diff", label: "Diff", icon: "i-lucide-git-compare", description: "Side-by-side text diff", keywords: ["compare", "changes", "git"] }] : [],
|
|
76
|
-
...extEnabled("svgEmbed") ? [{ kind: "svgEmbed", label: "SVG embed", icon: "i-lucide-image", description: "Inline SVG (sanitized)", keywords: ["svg", "vector", "icon", "diagram"] }] : []
|
|
76
|
+
...extEnabled("svgEmbed") ? [{ kind: "svgEmbed", label: "SVG embed", icon: "i-lucide-image", description: "Inline SVG (sanitized)", keywords: ["svg", "vector", "icon", "diagram"] }] : [],
|
|
77
|
+
...extEnabled("timeline") ? [{ kind: "timeline", label: "Timeline", icon: "i-lucide-git-commit-vertical", description: "Vertical event timeline", keywords: ["events", "history", "milestones"] }] : []
|
|
77
78
|
]
|
|
78
79
|
];
|
|
79
80
|
try {
|