@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.
Files changed (126) hide show
  1. package/dist/module.d.mts +68 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +99 -4
  4. package/dist/runtime/components/ACodeEditor.d.vue.ts +26 -0
  5. package/dist/runtime/components/ACodeEditor.vue +268 -0
  6. package/dist/runtime/components/ACodeEditor.vue.d.ts +26 -0
  7. package/dist/runtime/components/ADocumentTree.vue +52 -20
  8. package/dist/runtime/components/AEditor.d.vue.ts +20 -13
  9. package/dist/runtime/components/AEditor.vue +55 -2
  10. package/dist/runtime/components/AEditor.vue.d.ts +20 -13
  11. package/dist/runtime/components/ANodePanel.vue +64 -60
  12. package/dist/runtime/components/ANotificationBell.d.vue.ts +1 -1
  13. package/dist/runtime/components/ANotificationBell.vue.d.ts +1 -1
  14. package/dist/runtime/components/ASpaceFormModal.d.vue.ts +2 -2
  15. package/dist/runtime/components/ASpaceFormModal.vue.d.ts +2 -2
  16. package/dist/runtime/components/aware/APresenceBlobs.d.vue.ts +29 -1
  17. package/dist/runtime/components/aware/APresenceBlobs.vue +54 -8
  18. package/dist/runtime/components/aware/APresenceBlobs.vue.d.ts +29 -1
  19. package/dist/runtime/components/aware/APresenceCursors.d.vue.ts +11 -0
  20. package/dist/runtime/components/aware/APresenceCursors.vue +74 -9
  21. package/dist/runtime/components/aware/APresenceCursors.vue.d.ts +11 -0
  22. package/dist/runtime/components/aware/AToggleGroup.d.vue.ts +28 -13
  23. package/dist/runtime/components/aware/AToggleGroup.vue +56 -20
  24. package/dist/runtime/components/aware/AToggleGroup.vue.d.ts +28 -13
  25. package/dist/runtime/components/docs/ADocsNavigation.d.vue.ts +1 -1
  26. package/dist/runtime/components/docs/ADocsNavigation.vue.d.ts +1 -1
  27. package/dist/runtime/components/docs/ADocsSearchButton.d.vue.ts +1 -1
  28. package/dist/runtime/components/docs/ADocsSearchButton.vue.d.ts +1 -1
  29. package/dist/runtime/components/docs/ADocsToc.d.vue.ts +2 -2
  30. package/dist/runtime/components/docs/ADocsToc.vue.d.ts +2 -2
  31. package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +1 -1
  32. package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +1 -1
  33. package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +1 -1
  34. package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +1 -1
  35. package/dist/runtime/components/editor/ANodeInlineLabel.d.vue.ts +1 -1
  36. package/dist/runtime/components/editor/ANodeInlineLabel.vue.d.ts +1 -1
  37. package/dist/runtime/components/registry/APluginBrowser.d.vue.ts +23 -0
  38. package/dist/runtime/components/registry/APluginBrowser.vue +155 -0
  39. package/dist/runtime/components/registry/APluginBrowser.vue.d.ts +23 -0
  40. package/dist/runtime/components/registry/APluginCapabilityDialog.d.vue.ts +17 -0
  41. package/dist/runtime/components/registry/APluginCapabilityDialog.vue +159 -0
  42. package/dist/runtime/components/registry/APluginCapabilityDialog.vue.d.ts +17 -0
  43. package/dist/runtime/components/registry/APluginCard.d.vue.ts +20 -0
  44. package/dist/runtime/components/registry/APluginCard.vue +91 -0
  45. package/dist/runtime/components/registry/APluginCard.vue.d.ts +20 -0
  46. package/dist/runtime/components/registry/APluginDetail.d.vue.ts +18 -0
  47. package/dist/runtime/components/registry/APluginDetail.vue +252 -0
  48. package/dist/runtime/components/registry/APluginDetail.vue.d.ts +18 -0
  49. package/dist/runtime/components/renderers/ACodeRenderer.d.vue.ts +15 -0
  50. package/dist/runtime/components/renderers/ACodeRenderer.vue +68 -0
  51. package/dist/runtime/components/renderers/ACodeRenderer.vue.d.ts +15 -0
  52. package/dist/runtime/components/renderers/AGraphRenderer.vue +416 -120
  53. package/dist/runtime/components/renderers/AProseRenderer.d.vue.ts +2 -2
  54. package/dist/runtime/components/renderers/AProseRenderer.vue.d.ts +2 -2
  55. package/dist/runtime/components/shell/ABreadcrumbForDoc.d.vue.ts +11 -0
  56. package/dist/runtime/components/shell/ABreadcrumbForDoc.vue +16 -0
  57. package/dist/runtime/components/shell/ABreadcrumbForDoc.vue.d.ts +11 -0
  58. package/dist/runtime/components/shell/ASettingsSection.d.vue.ts +35 -0
  59. package/dist/runtime/components/shell/ASettingsSection.vue +26 -0
  60. package/dist/runtime/components/shell/ASettingsSection.vue.d.ts +35 -0
  61. package/dist/runtime/components/shell/ASidebar.d.vue.ts +1 -1
  62. package/dist/runtime/components/shell/ASidebar.vue.d.ts +1 -1
  63. package/dist/runtime/components/shell/AUserMenu.d.vue.ts +3 -0
  64. package/dist/runtime/components/shell/AUserMenu.vue +4 -0
  65. package/dist/runtime/components/shell/AUserMenu.vue.d.ts +3 -0
  66. package/dist/runtime/composables/useAbracadabraSchema.d.ts +83 -0
  67. package/dist/runtime/composables/useAbracadabraSchema.js +52 -0
  68. package/dist/runtime/composables/useAggregatedPresence.d.ts +1 -6
  69. package/dist/runtime/composables/useCalendarView.d.ts +1 -1
  70. package/dist/runtime/composables/useChat.js +1 -0
  71. package/dist/runtime/composables/useDocBreadcrumb.d.ts +21 -0
  72. package/dist/runtime/composables/useDocBreadcrumb.js +33 -0
  73. package/dist/runtime/composables/useDocEntryTyped.d.ts +60 -0
  74. package/dist/runtime/composables/useDocEntryTyped.js +70 -0
  75. package/dist/runtime/composables/useEditorDragHandle.js +18 -0
  76. package/dist/runtime/composables/useEditorSuggestions.js +2 -1
  77. package/dist/runtime/composables/useInstalledPlugins.d.ts +3 -21
  78. package/dist/runtime/composables/useInstalledPlugins.js +2 -12
  79. package/dist/runtime/composables/useMetaMenuItems.d.ts +21 -0
  80. package/dist/runtime/composables/useMetaMenuItems.js +115 -0
  81. package/dist/runtime/composables/useMetaValidator.d.ts +27 -0
  82. package/dist/runtime/composables/useMetaValidator.js +10 -0
  83. package/dist/runtime/composables/usePluginCatalog.d.ts +161 -0
  84. package/dist/runtime/composables/usePluginCatalog.js +234 -0
  85. package/dist/runtime/composables/useQuery.d.ts +79 -0
  86. package/dist/runtime/composables/useQuery.js +97 -0
  87. package/dist/runtime/composables/useSpaces.js +4 -5
  88. package/dist/runtime/composables/useTableView.d.ts +3 -3
  89. package/dist/runtime/composables/useTypedDoc.d.ts +97 -0
  90. package/dist/runtime/composables/useTypedDoc.js +114 -0
  91. package/dist/runtime/composables/useWebRTC.js +44 -5
  92. package/dist/runtime/extensions/document-meta.js +5 -0
  93. package/dist/runtime/extensions/timeline.d.ts +11 -0
  94. package/dist/runtime/extensions/timeline.js +52 -0
  95. package/dist/runtime/extensions/views/DocumentMetaView.d.vue.ts +4 -0
  96. package/dist/runtime/extensions/views/DocumentMetaView.vue +63 -0
  97. package/dist/runtime/extensions/views/DocumentMetaView.vue.d.ts +4 -0
  98. package/dist/runtime/extensions/views/TimelineItemView.d.vue.ts +4 -0
  99. package/dist/runtime/extensions/views/TimelineItemView.vue +131 -0
  100. package/dist/runtime/extensions/views/TimelineItemView.vue.d.ts +4 -0
  101. package/dist/runtime/extensions/views/TimelineView.d.vue.ts +9 -0
  102. package/dist/runtime/extensions/views/TimelineView.vue +29 -0
  103. package/dist/runtime/extensions/views/TimelineView.vue.d.ts +9 -0
  104. package/dist/runtime/locale.d.ts +2 -0
  105. package/dist/runtime/locale.js +2 -0
  106. package/dist/runtime/plugin-abracadabra.client.js +107 -6
  107. package/dist/runtime/plugin-registry.d.ts +11 -30
  108. package/dist/runtime/plugin-registry.js +2 -82
  109. package/dist/runtime/plugins/core.plugin.js +10 -4
  110. package/dist/runtime/server/api/_abracadabra/spaces.get.d.ts +1 -1
  111. package/dist/runtime/server/plugins/abracadabra-service.js +28 -0
  112. package/dist/runtime/server/utils/docCache.js +24 -3
  113. package/dist/runtime/server/utils/schemaServerSupport.d.ts +52 -0
  114. package/dist/runtime/server/utils/schemaServerSupport.js +51 -0
  115. package/dist/runtime/types.d.ts +63 -46
  116. package/dist/runtime/utils/docTypes.d.ts +15 -0
  117. package/dist/runtime/utils/docTypes.js +20 -0
  118. package/dist/runtime/utils/loadCodeMirror.d.ts +32 -0
  119. package/dist/runtime/utils/loadCodeMirror.js +65 -0
  120. package/dist/runtime/utils/markdownToYjs.d.ts +1 -23
  121. package/dist/runtime/utils/markdownToYjs.js +5 -440
  122. package/dist/runtime/utils/schemaSupport.d.ts +60 -0
  123. package/dist/runtime/utils/schemaSupport.js +40 -0
  124. package/dist/runtime/utils/yjsConvert.d.ts +1 -14
  125. package/dist/runtime/utils/yjsConvert.js +5 -331
  126. 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
+ }
@@ -1,9 +1,4 @@
1
- export interface PresenceUser {
2
- name: string;
3
- color: string;
4
- publicKey?: string;
5
- clientId: number;
6
- }
1
+ import type { PresenceUser } from './useItemPresence.js';
7
2
  interface AwarenessState {
8
3
  user?: {
9
4
  name?: string;
@@ -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<1 | 0>;
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 {