@abraca/nuxt 2.0.11 → 2.4.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 (135) 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/AMedia.d.vue.ts +1 -1
  17. package/dist/runtime/components/aware/AMedia.vue.d.ts +1 -1
  18. package/dist/runtime/components/aware/APresenceBlobs.d.vue.ts +29 -1
  19. package/dist/runtime/components/aware/APresenceBlobs.vue +54 -8
  20. package/dist/runtime/components/aware/APresenceBlobs.vue.d.ts +29 -1
  21. package/dist/runtime/components/aware/APresenceCursors.d.vue.ts +11 -0
  22. package/dist/runtime/components/aware/APresenceCursors.vue +74 -9
  23. package/dist/runtime/components/aware/APresenceCursors.vue.d.ts +11 -0
  24. package/dist/runtime/components/aware/AToggleGroup.d.vue.ts +28 -13
  25. package/dist/runtime/components/aware/AToggleGroup.vue +56 -20
  26. package/dist/runtime/components/aware/AToggleGroup.vue.d.ts +28 -13
  27. package/dist/runtime/components/docs/ADocsNavigation.d.vue.ts +1 -1
  28. package/dist/runtime/components/docs/ADocsNavigation.vue.d.ts +1 -1
  29. package/dist/runtime/components/docs/ADocsSearch.d.vue.ts +1 -1
  30. package/dist/runtime/components/docs/ADocsSearch.vue.d.ts +1 -1
  31. package/dist/runtime/components/docs/ADocsSearchButton.d.vue.ts +1 -1
  32. package/dist/runtime/components/docs/ADocsSearchButton.vue.d.ts +1 -1
  33. package/dist/runtime/components/docs/ADocsToc.d.vue.ts +2 -2
  34. package/dist/runtime/components/docs/ADocsToc.vue.d.ts +2 -2
  35. package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +1 -1
  36. package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +1 -1
  37. package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +1 -1
  38. package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +1 -1
  39. package/dist/runtime/components/editor/AFileGlbViewer.vue +27 -10
  40. package/dist/runtime/components/editor/ANodeInlineLabel.d.vue.ts +1 -1
  41. package/dist/runtime/components/editor/ANodeInlineLabel.vue.d.ts +1 -1
  42. package/dist/runtime/components/registry/APluginBrowser.d.vue.ts +23 -0
  43. package/dist/runtime/components/registry/APluginBrowser.vue +155 -0
  44. package/dist/runtime/components/registry/APluginBrowser.vue.d.ts +23 -0
  45. package/dist/runtime/components/registry/APluginCapabilityDialog.d.vue.ts +17 -0
  46. package/dist/runtime/components/registry/APluginCapabilityDialog.vue +159 -0
  47. package/dist/runtime/components/registry/APluginCapabilityDialog.vue.d.ts +17 -0
  48. package/dist/runtime/components/registry/APluginCard.d.vue.ts +20 -0
  49. package/dist/runtime/components/registry/APluginCard.vue +91 -0
  50. package/dist/runtime/components/registry/APluginCard.vue.d.ts +20 -0
  51. package/dist/runtime/components/registry/APluginDetail.d.vue.ts +18 -0
  52. package/dist/runtime/components/registry/APluginDetail.vue +252 -0
  53. package/dist/runtime/components/registry/APluginDetail.vue.d.ts +18 -0
  54. package/dist/runtime/components/renderers/ACodeRenderer.d.vue.ts +15 -0
  55. package/dist/runtime/components/renderers/ACodeRenderer.vue +68 -0
  56. package/dist/runtime/components/renderers/ACodeRenderer.vue.d.ts +15 -0
  57. package/dist/runtime/components/renderers/AGraphRenderer.vue +416 -120
  58. package/dist/runtime/components/renderers/AProseRenderer.d.vue.ts +2 -2
  59. package/dist/runtime/components/renderers/AProseRenderer.vue.d.ts +2 -2
  60. package/dist/runtime/components/renderers/sheets/ASheetsToolbar.d.vue.ts +4 -4
  61. package/dist/runtime/components/renderers/sheets/ASheetsToolbar.vue.d.ts +4 -4
  62. package/dist/runtime/components/shell/ABreadcrumbForDoc.d.vue.ts +11 -0
  63. package/dist/runtime/components/shell/ABreadcrumbForDoc.vue +16 -0
  64. package/dist/runtime/components/shell/ABreadcrumbForDoc.vue.d.ts +11 -0
  65. package/dist/runtime/components/shell/ASettingsSection.d.vue.ts +35 -0
  66. package/dist/runtime/components/shell/ASettingsSection.vue +26 -0
  67. package/dist/runtime/components/shell/ASettingsSection.vue.d.ts +35 -0
  68. package/dist/runtime/components/shell/ASidebar.d.vue.ts +1 -1
  69. package/dist/runtime/components/shell/ASidebar.vue.d.ts +1 -1
  70. package/dist/runtime/components/shell/AUserMenu.d.vue.ts +3 -0
  71. package/dist/runtime/components/shell/AUserMenu.vue +4 -0
  72. package/dist/runtime/components/shell/AUserMenu.vue.d.ts +3 -0
  73. package/dist/runtime/composables/useAbracadabraSchema.d.ts +83 -0
  74. package/dist/runtime/composables/useAbracadabraSchema.js +52 -0
  75. package/dist/runtime/composables/useAggregatedPresence.d.ts +1 -6
  76. package/dist/runtime/composables/useCalendarView.d.ts +1 -1
  77. package/dist/runtime/composables/useChat.js +1 -0
  78. package/dist/runtime/composables/useDocBreadcrumb.d.ts +21 -0
  79. package/dist/runtime/composables/useDocBreadcrumb.js +33 -0
  80. package/dist/runtime/composables/useDocEntryTyped.d.ts +60 -0
  81. package/dist/runtime/composables/useDocEntryTyped.js +70 -0
  82. package/dist/runtime/composables/useEditorDragHandle.js +18 -0
  83. package/dist/runtime/composables/useEditorSuggestions.js +2 -1
  84. package/dist/runtime/composables/useInstalledPlugins.d.ts +3 -21
  85. package/dist/runtime/composables/useInstalledPlugins.js +2 -12
  86. package/dist/runtime/composables/useMetaMenuItems.d.ts +21 -0
  87. package/dist/runtime/composables/useMetaMenuItems.js +115 -0
  88. package/dist/runtime/composables/useMetaValidator.d.ts +27 -0
  89. package/dist/runtime/composables/useMetaValidator.js +10 -0
  90. package/dist/runtime/composables/usePluginCatalog.d.ts +161 -0
  91. package/dist/runtime/composables/usePluginCatalog.js +234 -0
  92. package/dist/runtime/composables/useQuery.d.ts +79 -0
  93. package/dist/runtime/composables/useQuery.js +97 -0
  94. package/dist/runtime/composables/useSpaces.js +4 -5
  95. package/dist/runtime/composables/useTableView.d.ts +3 -3
  96. package/dist/runtime/composables/useTypedDoc.d.ts +97 -0
  97. package/dist/runtime/composables/useTypedDoc.js +114 -0
  98. package/dist/runtime/composables/useWebRTC.js +44 -5
  99. package/dist/runtime/extensions/document-meta.js +5 -0
  100. package/dist/runtime/extensions/timeline.d.ts +11 -0
  101. package/dist/runtime/extensions/timeline.js +52 -0
  102. package/dist/runtime/extensions/views/DocumentMetaView.d.vue.ts +4 -0
  103. package/dist/runtime/extensions/views/DocumentMetaView.vue +63 -0
  104. package/dist/runtime/extensions/views/DocumentMetaView.vue.d.ts +4 -0
  105. package/dist/runtime/extensions/views/TimelineItemView.d.vue.ts +4 -0
  106. package/dist/runtime/extensions/views/TimelineItemView.vue +131 -0
  107. package/dist/runtime/extensions/views/TimelineItemView.vue.d.ts +4 -0
  108. package/dist/runtime/extensions/views/TimelineView.d.vue.ts +9 -0
  109. package/dist/runtime/extensions/views/TimelineView.vue +29 -0
  110. package/dist/runtime/extensions/views/TimelineView.vue.d.ts +9 -0
  111. package/dist/runtime/locale.d.ts +2 -0
  112. package/dist/runtime/locale.js +2 -0
  113. package/dist/runtime/plugin-abracadabra.client.js +107 -6
  114. package/dist/runtime/plugin-registry.d.ts +11 -30
  115. package/dist/runtime/plugin-registry.js +2 -82
  116. package/dist/runtime/plugins/core.plugin.js +10 -4
  117. package/dist/runtime/server/api/_abracadabra/spaces.get.d.ts +1 -1
  118. package/dist/runtime/server/plugins/abracadabra-service.js +28 -0
  119. package/dist/runtime/server/utils/docCache.js +24 -3
  120. package/dist/runtime/server/utils/schemaServerSupport.d.ts +52 -0
  121. package/dist/runtime/server/utils/schemaServerSupport.js +51 -0
  122. package/dist/runtime/types.d.ts +63 -46
  123. package/dist/runtime/utils/docTypes.d.ts +15 -0
  124. package/dist/runtime/utils/docTypes.js +20 -0
  125. package/dist/runtime/utils/loadCodeMirror.d.ts +32 -0
  126. package/dist/runtime/utils/loadCodeMirror.js +65 -0
  127. package/dist/runtime/utils/loadThree.d.ts +18 -0
  128. package/dist/runtime/utils/loadThree.js +46 -0
  129. package/dist/runtime/utils/markdownToYjs.d.ts +1 -23
  130. package/dist/runtime/utils/markdownToYjs.js +5 -440
  131. package/dist/runtime/utils/schemaSupport.d.ts +60 -0
  132. package/dist/runtime/utils/schemaSupport.js +40 -0
  133. package/dist/runtime/utils/yjsConvert.d.ts +1 -14
  134. package/dist/runtime/utils/yjsConvert.js +5 -331
  135. package/package.json +86 -21
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { ref, computed, nextTick, shallowRef, watch } from "vue";
2
+ import { ref, computed, nextTick, shallowRef, toRaw, watch } from "vue";
3
3
  import { useAbracadabra, useTrash, useChat, useVoice, useToast, useAppConfig, useSyncedMap, useDocImport, useDocExport, useWindowManager, useAwareness } from "#imports";
4
4
  import { resolveDocType, getAvailableDocTypes } from "../utils/docTypes";
5
5
  import { avatarBorderStyle } from "../utils/avatarStyle";
@@ -29,24 +29,56 @@ const toast = useToast();
29
29
  const appConfig = useAppConfig();
30
30
  const presenceNeutral = computed(() => appConfig.ui?.colors?.neutral ?? "zinc");
31
31
  const treeMap = useSyncedMap(doc, "doc-tree");
32
- function buildTree(parentId = null, depth = 0) {
33
- return Object.entries(treeMap.data).filter(([id, v]) => {
34
- if (id === spaceDocId.value) return false;
35
- const pid = v.parentId ?? null;
36
- if (parentId === null) return pid === null || pid === spaceDocId.value;
37
- return pid === parentId;
38
- }).sort(([, a], [, b]) => (a.order ?? 0) - (b.order ?? 0)).map(([id, v]) => ({
39
- id,
40
- label: v.label || "Untitled",
41
- parentId: v.parentId,
42
- order: v.order ?? 0,
43
- type: v.type,
44
- meta: v.meta,
45
- children: buildTree(id, depth + 1),
46
- depth
47
- }));
48
- }
49
- const treeItems = computed(() => buildTree(null));
32
+ const structureHash = computed(() => {
33
+ let h = 0;
34
+ const data = treeMap.data;
35
+ let count = 0;
36
+ for (const id in data) {
37
+ const v = data[id];
38
+ const pid = v.parentId ?? "";
39
+ const ord = v.order ?? 0;
40
+ for (let i = 0; i < id.length; i++)
41
+ h = (h << 5) + h + id.charCodeAt(i) | 0;
42
+ for (let i = 0; i < pid.length; i++)
43
+ h = (h << 5) + h + pid.charCodeAt(i) | 0;
44
+ h = (h << 5) + h + ord | 0;
45
+ count++;
46
+ }
47
+ return (h << 5) + h + count | 0;
48
+ });
49
+ const treeItems = computed(() => {
50
+ void structureHash.value;
51
+ const sid = spaceDocId.value;
52
+ const raw = toRaw(treeMap.data);
53
+ const ROOT = "@root";
54
+ const childrenByParent = /* @__PURE__ */ new Map();
55
+ for (const id in raw) {
56
+ if (id === sid) continue;
57
+ const v = raw[id];
58
+ const rawPid = v.parentId ?? null;
59
+ const pid = rawPid == null || rawPid === sid ? ROOT : rawPid;
60
+ const bucket = childrenByParent.get(pid);
61
+ if (bucket) bucket.push([id, v]);
62
+ else childrenByParent.set(pid, [[id, v]]);
63
+ }
64
+ for (const list of childrenByParent.values())
65
+ list.sort((a, b) => (a[1].order ?? 0) - (b[1].order ?? 0));
66
+ function build(parentKey, depth) {
67
+ const bucket = childrenByParent.get(parentKey);
68
+ if (!bucket) return [];
69
+ return bucket.map(([id, v]) => ({
70
+ id,
71
+ label: v.label || "Untitled",
72
+ parentId: v.parentId,
73
+ order: v.order ?? 0,
74
+ type: v.type,
75
+ meta: v.meta,
76
+ children: build(id, depth + 1),
77
+ depth
78
+ }));
79
+ }
80
+ return build(ROOT, 0);
81
+ });
50
82
  const nodeMap = computed(() => {
51
83
  const map = /* @__PURE__ */ new Map();
52
84
  function walk(nodes) {
@@ -58,7 +90,7 @@ const nodeMap = computed(() => {
58
90
  walk(treeItems.value);
59
91
  return map;
60
92
  });
61
- const expandedIds = ref(/* @__PURE__ */ new Set());
93
+ const expandedIds = shallowRef(/* @__PURE__ */ new Set());
62
94
  const {
63
95
  externalDragActive,
64
96
  onDragEnter: onImportDragEnter,
@@ -29,12 +29,18 @@ type __VLS_Props = {
29
29
  * for long-form writing. Same TipTap engine and extensions.
30
30
  */
31
31
  variant?: 'doc' | 'prose';
32
+ /**
33
+ * Show a floating toggle that swaps the TipTap canvas for a read-only
34
+ * CodeMirror view of the document's underlying Y.XmlFragment XML.
35
+ * Useful for inspecting CRDT state during development. Default: false.
36
+ */
37
+ showSourceToggle?: boolean;
32
38
  };
33
39
  type __VLS_ModelProps = {
34
40
  modelValue?: any;
35
41
  };
36
42
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
37
- declare var __VLS_18: {
43
+ declare var __VLS_42: {
38
44
  editor: any;
39
45
  connectedUsers: {
40
46
  name: string;
@@ -43,47 +49,48 @@ declare var __VLS_18: {
43
49
  docId?: string | undefined;
44
50
  }[];
45
51
  ready: boolean;
46
- }, __VLS_27: {
52
+ }, __VLS_51: {
47
53
  editor: any;
48
- }, __VLS_35: {
54
+ }, __VLS_59: {
49
55
  editor: any;
50
- }, __VLS_43: {
56
+ }, __VLS_67: {
51
57
  editor: any;
52
- }, __VLS_46: {
58
+ }, __VLS_70: {
53
59
  editor: any;
54
60
  };
55
61
  type __VLS_Slots = {} & {
56
- default?: (props: typeof __VLS_18) => any;
62
+ default?: (props: typeof __VLS_42) => any;
57
63
  } & {
58
- link?: (props: typeof __VLS_27) => any;
64
+ link?: (props: typeof __VLS_51) => any;
59
65
  } & {
60
- 'doc-link'?: (props: typeof __VLS_35) => any;
66
+ 'doc-link'?: (props: typeof __VLS_59) => any;
61
67
  } & {
62
- 'create-child-doc'?: (props: typeof __VLS_43) => any;
68
+ 'create-child-doc'?: (props: typeof __VLS_67) => any;
63
69
  } & {
64
- 'send-to-chat'?: (props: typeof __VLS_46) => any;
70
+ 'send-to-chat'?: (props: typeof __VLS_70) => any;
65
71
  };
66
72
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
67
73
  editor: import("vue").ComputedRef<any>;
68
74
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
69
75
  rename: (label: string) => any;
76
+ ready: () => any;
70
77
  update: (content: any) => any;
71
78
  "update:modelValue": (value: any) => any;
72
79
  updateMeta: (patch: Partial<DocPageMeta>) => any;
73
- ready: () => any;
74
80
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
75
81
  onRename?: ((label: string) => any) | undefined;
82
+ onReady?: (() => any) | undefined;
76
83
  onUpdate?: ((content: any) => any) | undefined;
77
84
  "onUpdate:modelValue"?: ((value: any) => any) | undefined;
78
85
  onUpdateMeta?: ((patch: Partial<DocPageMeta>) => any) | undefined;
79
- onReady?: (() => any) | undefined;
80
86
  }>, {
81
- variant: "doc" | "prose";
82
87
  contentType: "json" | "html" | "markdown";
83
88
  editable: boolean;
84
89
  showToolbar: boolean;
85
90
  showSuggestionMenu: boolean;
86
91
  showDragHandle: boolean;
92
+ variant: "doc" | "prose";
93
+ showSourceToggle: boolean;
87
94
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
88
95
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
89
96
  declare const _default: typeof __VLS_export;
@@ -13,6 +13,7 @@ import { useEditorEmojis } from "../composables/useEditorEmojis";
13
13
  import { useEditorMentions } from "../composables/useEditorMentions";
14
14
  import ALinkPopover from "./editor/ALinkPopover.vue";
15
15
  import ADocLinkPopover from "./editor/ADocLinkPopover.vue";
16
+ import ACodeEditor from "./ACodeEditor.vue";
16
17
  const props = defineProps({
17
18
  docId: { type: String, required: true },
18
19
  docLabel: { type: String, required: false },
@@ -25,8 +26,10 @@ const props = defineProps({
25
26
  docMeta: { type: Object, required: false },
26
27
  parentType: { type: String, required: false },
27
28
  metaSchema: { type: Array, required: false },
28
- variant: { type: String, required: false, default: "doc" }
29
+ variant: { type: String, required: false, default: "doc" },
30
+ showSourceToggle: { type: Boolean, required: false, default: false }
29
31
  });
32
+ const viewMode = ref("rich");
30
33
  const emit = defineEmits(["ready", "update", "rename", "updateMeta"]);
31
34
  const model = defineModel({ type: null });
32
35
  const { doc, provider, registry } = useNuxtApp().$abracadabra;
@@ -328,6 +331,17 @@ const editorHandlers = {
328
331
  canExecute: () => true,
329
332
  execute: (editor) => insertNode(editor, "svgEmbed", { svg: "", title: "", width: null, height: null }),
330
333
  isActive: (editor) => editor.isActive("svgEmbed")
334
+ },
335
+ timeline: {
336
+ canExecute: () => true,
337
+ execute: (editor) => insertNode(editor, "timeline", {}, [
338
+ {
339
+ type: "timelineItem",
340
+ attrs: { date: "", label: "Event", icon: "" },
341
+ content: [{ type: "paragraph" }]
342
+ }
343
+ ]),
344
+ isActive: (editor) => editor.isActive("timeline")
331
345
  }
332
346
  };
333
347
  const _mentionItems = computed(
@@ -356,6 +370,34 @@ function onPlusClick(e, onClick) {
356
370
  <div class="h-4 w-5/6 animate-pulse rounded bg-elevated" />
357
371
  </div>
358
372
 
373
+ <!-- Source view: read-only CodeMirror over getXmlFragment('default').toString() -->
374
+ <div
375
+ v-else-if="viewMode === 'source'"
376
+ class="aeditor-source-wrap"
377
+ >
378
+ <div class="aeditor-source-toolbar">
379
+ <span class="aeditor-source-toolbar__label">
380
+ <UIcon name="i-lucide-code-xml" class="size-3.5" />
381
+ XML source — read-only mirror of <code>getXmlFragment('default')</code>
382
+ </span>
383
+ <UButton
384
+ icon="i-lucide-file-text"
385
+ size="xs"
386
+ variant="ghost"
387
+ color="neutral"
388
+ label="Rich text"
389
+ @click="viewMode = 'rich'"
390
+ />
391
+ </div>
392
+ <ACodeEditor
393
+ :provider="childProvider"
394
+ field-name="default"
395
+ language="plain"
396
+ :read-only="true"
397
+ :as-xml-fragment="true"
398
+ />
399
+ </div>
400
+
359
401
  <UEditor
360
402
  v-else
361
403
  :class="{ 'prose-variant': variant === 'prose' }"
@@ -370,6 +412,17 @@ function onPlusClick(e, onClick) {
370
412
  :placeholder="placeholder"
371
413
  @update:model-value="emit('update', $event)"
372
414
  >
415
+ <!-- Floating source-view toggle (opt-in via :show-source-toggle="true") -->
416
+ <UButton
417
+ v-if="showSourceToggle"
418
+ class="aeditor-source-toggle"
419
+ icon="i-lucide-code-xml"
420
+ size="xs"
421
+ variant="ghost"
422
+ color="neutral"
423
+ :title="'View XML source'"
424
+ @click="viewMode = 'source'"
425
+ />
373
426
  <!-- Default slot: app can override entire editor content -->
374
427
  <slot
375
428
  :editor="editor"
@@ -490,5 +543,5 @@ function onPlusClick(e, onClick) {
490
543
  </template>
491
544
 
492
545
  <style scoped>
493
- .prose-variant :deep(.tiptap){color:var(--ui-text);font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif;font-size:1.0625rem;line-height:1.75}.prose-variant :deep(.tiptap p){margin-bottom:1em;margin-top:0}.prose-variant :deep(.tiptap h1),.prose-variant :deep(.tiptap h2),.prose-variant :deep(.tiptap h3),.prose-variant :deep(.tiptap h4){font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif;letter-spacing:-.01em;line-height:1.25;margin-bottom:.5em;margin-top:1.75em}.prose-variant :deep(.tiptap h1){font-size:2rem;font-weight:700}.prose-variant :deep(.tiptap h2){font-size:1.5rem;font-weight:700}.prose-variant :deep(.tiptap h3){font-size:1.25rem;font-weight:600}.prose-variant :deep(.tiptap blockquote){border-left:3px solid var(--ui-border);color:var(--ui-text-muted);font-style:italic;margin-left:0;padding-left:1em}.prose-variant :deep(.tiptap ol),.prose-variant :deep(.tiptap ul){margin-bottom:1em;padding-left:1.5em}.prose-variant :deep(.tiptap .document-header){font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif;font-size:2.75rem;font-weight:700;letter-spacing:-.02em;line-height:1.15;margin-bottom:1.5rem}
546
+ .prose-variant :deep(.tiptap){color:var(--ui-text);font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif;font-size:1.0625rem;line-height:1.75}.prose-variant :deep(.tiptap p){margin-bottom:1em;margin-top:0}.prose-variant :deep(.tiptap h1),.prose-variant :deep(.tiptap h2),.prose-variant :deep(.tiptap h3),.prose-variant :deep(.tiptap h4){font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif;letter-spacing:-.01em;line-height:1.25;margin-bottom:.5em;margin-top:1.75em}.prose-variant :deep(.tiptap h1){font-size:2rem;font-weight:700}.prose-variant :deep(.tiptap h2){font-size:1.5rem;font-weight:700}.prose-variant :deep(.tiptap h3){font-size:1.25rem;font-weight:600}.prose-variant :deep(.tiptap blockquote){border-left:3px solid var(--ui-border);color:var(--ui-text-muted);font-style:italic;margin-left:0;padding-left:1em}.prose-variant :deep(.tiptap ol),.prose-variant :deep(.tiptap ul){margin-bottom:1em;padding-left:1.5em}.prose-variant :deep(.tiptap .document-header){font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif;font-size:2.75rem;font-weight:700;letter-spacing:-.02em;line-height:1.15;margin-bottom:1.5rem}.aeditor-source-wrap{display:flex;flex:1 1 0;flex-direction:column;min-height:0}.aeditor-source-toolbar{align-items:center;background:var(--ui-bg);border-bottom:1px solid var(--ui-border);display:flex;flex-shrink:0;justify-content:space-between;padding:.375rem .75rem}.aeditor-source-toolbar__label{align-items:center;color:var(--ui-text-muted);display:inline-flex;font-size:.75rem;gap:.375rem}.aeditor-source-toolbar__label code{background:var(--ui-bg-elevated);border:1px solid var(--ui-border);border-radius:var(--ui-radius);font-family:ui-monospace,SF Mono,Menlo,Monaco,Consolas,monospace;font-size:.7rem;padding:.05rem .3rem}.aeditor-source-toggle{opacity:.6;position:absolute;right:.375rem;top:.375rem;transition:opacity .12s ease;z-index:5}.aeditor-source-toggle:hover{opacity:1}
494
547
  </style>
@@ -29,12 +29,18 @@ type __VLS_Props = {
29
29
  * for long-form writing. Same TipTap engine and extensions.
30
30
  */
31
31
  variant?: 'doc' | 'prose';
32
+ /**
33
+ * Show a floating toggle that swaps the TipTap canvas for a read-only
34
+ * CodeMirror view of the document's underlying Y.XmlFragment XML.
35
+ * Useful for inspecting CRDT state during development. Default: false.
36
+ */
37
+ showSourceToggle?: boolean;
32
38
  };
33
39
  type __VLS_ModelProps = {
34
40
  modelValue?: any;
35
41
  };
36
42
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
37
- declare var __VLS_18: {
43
+ declare var __VLS_42: {
38
44
  editor: any;
39
45
  connectedUsers: {
40
46
  name: string;
@@ -43,47 +49,48 @@ declare var __VLS_18: {
43
49
  docId?: string | undefined;
44
50
  }[];
45
51
  ready: boolean;
46
- }, __VLS_27: {
52
+ }, __VLS_51: {
47
53
  editor: any;
48
- }, __VLS_35: {
54
+ }, __VLS_59: {
49
55
  editor: any;
50
- }, __VLS_43: {
56
+ }, __VLS_67: {
51
57
  editor: any;
52
- }, __VLS_46: {
58
+ }, __VLS_70: {
53
59
  editor: any;
54
60
  };
55
61
  type __VLS_Slots = {} & {
56
- default?: (props: typeof __VLS_18) => any;
62
+ default?: (props: typeof __VLS_42) => any;
57
63
  } & {
58
- link?: (props: typeof __VLS_27) => any;
64
+ link?: (props: typeof __VLS_51) => any;
59
65
  } & {
60
- 'doc-link'?: (props: typeof __VLS_35) => any;
66
+ 'doc-link'?: (props: typeof __VLS_59) => any;
61
67
  } & {
62
- 'create-child-doc'?: (props: typeof __VLS_43) => any;
68
+ 'create-child-doc'?: (props: typeof __VLS_67) => any;
63
69
  } & {
64
- 'send-to-chat'?: (props: typeof __VLS_46) => any;
70
+ 'send-to-chat'?: (props: typeof __VLS_70) => any;
65
71
  };
66
72
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
67
73
  editor: import("vue").ComputedRef<any>;
68
74
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
69
75
  rename: (label: string) => any;
76
+ ready: () => any;
70
77
  update: (content: any) => any;
71
78
  "update:modelValue": (value: any) => any;
72
79
  updateMeta: (patch: Partial<DocPageMeta>) => any;
73
- ready: () => any;
74
80
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
75
81
  onRename?: ((label: string) => any) | undefined;
82
+ onReady?: (() => any) | undefined;
76
83
  onUpdate?: ((content: any) => any) | undefined;
77
84
  "onUpdate:modelValue"?: ((value: any) => any) | undefined;
78
85
  onUpdateMeta?: ((patch: Partial<DocPageMeta>) => any) | undefined;
79
- onReady?: (() => any) | undefined;
80
86
  }>, {
81
- variant: "doc" | "prose";
82
87
  contentType: "json" | "html" | "markdown";
83
88
  editable: boolean;
84
89
  showToolbar: boolean;
85
90
  showSuggestionMenu: boolean;
86
91
  showDragHandle: boolean;
92
+ variant: "doc" | "prose";
93
+ showSourceToggle: boolean;
87
94
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
88
95
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
89
96
  declare const _default: typeof __VLS_export;
@@ -183,6 +183,7 @@ const addFieldMenuItems = computed(
183
183
  side="right"
184
184
  :title="nodeLabel || 'Document'"
185
185
  :content="{ style: resize.style.value }"
186
+ :ui="{ body: 'p-0' }"
186
187
  @update:open="(v) => !v && emit('close')"
187
188
  >
188
189
  <template #header>
@@ -205,7 +206,69 @@ const addFieldMenuItems = computed(
205
206
  :icon-color="meta.color"
206
207
  :editor="activeTab === 'editor' && !usesPageRenderer ? tiptapEditor : null"
207
208
  @expand="navigateTo(`/app/${nodeId}`)"
208
- />
209
+ >
210
+ <!-- Tabs inline with the title — single-row header layout.
211
+ Built-in tabs honour the `tabs` prop; plugin-registered tabs
212
+ always render. -->
213
+ <template #actions-left>
214
+ <div class="flex items-center gap-1 ml-2">
215
+ <UButton
216
+ v-if="showEditorTab"
217
+ icon="i-lucide-file-text"
218
+ :label="locale.editorTab"
219
+ size="xs"
220
+ :color="activeTab === 'editor' ? 'primary' : 'neutral'"
221
+ :variant="activeTab === 'editor' ? 'soft' : 'ghost'"
222
+ @click="activeTab = 'editor'"
223
+ />
224
+ <UButton
225
+ v-if="showPropertiesTab"
226
+ icon="i-lucide-sliders-horizontal"
227
+ :label="locale.propertiesTab"
228
+ size="xs"
229
+ :color="activeTab === 'properties' ? 'primary' : 'neutral'"
230
+ :variant="activeTab === 'properties' ? 'soft' : 'ghost'"
231
+ @click="activeTab = 'properties'"
232
+ />
233
+ <UChip
234
+ v-if="showChatTab"
235
+ :text="chatUnread > 0 && activeTab !== 'chat' ? String(chatUnread) : void 0"
236
+ color="error"
237
+ size="lg"
238
+ :show="chatUnread > 0 && activeTab !== 'chat'"
239
+ :inset="true"
240
+ >
241
+ <UButton
242
+ icon="i-lucide-message-circle"
243
+ label="Chat"
244
+ size="xs"
245
+ :color="activeTab === 'chat' ? 'primary' : 'neutral'"
246
+ :variant="activeTab === 'chat' ? 'soft' : 'ghost'"
247
+ @click="activeTab = 'chat'"
248
+ />
249
+ </UChip>
250
+ <UButton
251
+ v-if="showSettingsTab"
252
+ icon="i-lucide-settings-2"
253
+ label="Settings"
254
+ size="xs"
255
+ :color="activeTab === 'settings' ? 'primary' : 'neutral'"
256
+ :variant="activeTab === 'settings' ? 'soft' : 'ghost'"
257
+ @click="activeTab = 'settings'"
258
+ />
259
+ <UButton
260
+ v-for="slot in pluginSlots"
261
+ :key="slot.id"
262
+ :icon="slot.icon"
263
+ :label="slot.label"
264
+ size="xs"
265
+ :color="activeTab === slot.id ? 'primary' : 'neutral'"
266
+ :variant="activeTab === slot.id ? 'soft' : 'ghost'"
267
+ @click="activeTab = slot.id"
268
+ />
269
+ </div>
270
+ </template>
271
+ </ANodePanelHeader>
209
272
  </slot>
210
273
  </template>
211
274
 
@@ -219,65 +282,6 @@ const addFieldMenuItems = computed(
219
282
  @dblclick="resize.onDoubleClick"
220
283
  />
221
284
 
222
- <!-- Tab bar — built-in tabs are individually toggleable via the
223
- `tabs` prop; plugin-registered tabs always render. -->
224
- <div class="flex items-center gap-1 border-b border-(--ui-border) mb-4 -mt-2">
225
- <UButton
226
- v-if="showEditorTab"
227
- icon="i-lucide-file-text"
228
- :label="locale.editorTab"
229
- size="sm"
230
- :color="activeTab === 'editor' ? 'primary' : 'neutral'"
231
- :variant="activeTab === 'editor' ? 'soft' : 'ghost'"
232
- @click="activeTab = 'editor'"
233
- />
234
- <UButton
235
- v-if="showPropertiesTab"
236
- icon="i-lucide-sliders-horizontal"
237
- :label="locale.propertiesTab"
238
- size="sm"
239
- :color="activeTab === 'properties' ? 'primary' : 'neutral'"
240
- :variant="activeTab === 'properties' ? 'soft' : 'ghost'"
241
- @click="activeTab = 'properties'"
242
- />
243
- <UChip
244
- v-if="showChatTab"
245
- :text="chatUnread > 0 && activeTab !== 'chat' ? String(chatUnread) : void 0"
246
- color="error"
247
- size="lg"
248
- :show="chatUnread > 0 && activeTab !== 'chat'"
249
- :inset="true"
250
- >
251
- <UButton
252
- icon="i-lucide-message-circle"
253
- label="Chat"
254
- size="sm"
255
- :color="activeTab === 'chat' ? 'primary' : 'neutral'"
256
- :variant="activeTab === 'chat' ? 'soft' : 'ghost'"
257
- @click="activeTab = 'chat'"
258
- />
259
- </UChip>
260
- <UButton
261
- v-if="showSettingsTab"
262
- icon="i-lucide-settings-2"
263
- label="Settings"
264
- size="sm"
265
- :color="activeTab === 'settings' ? 'primary' : 'neutral'"
266
- :variant="activeTab === 'settings' ? 'soft' : 'ghost'"
267
- @click="activeTab = 'settings'"
268
- />
269
- <UButton
270
- v-for="slot in pluginSlots"
271
- :key="slot.id"
272
- :icon="slot.icon"
273
- :label="slot.label"
274
- size="sm"
275
- :color="activeTab === slot.id ? 'primary' : 'neutral'"
276
- :variant="activeTab === slot.id ? 'soft' : 'ghost'"
277
- @click="activeTab = slot.id"
278
- />
279
- </div>
280
-
281
285
  <!-- Editor tab — swaps to the registered page-type renderer when the
282
286
  doc has a non-'doc' type (kanban / table / calendar / etc.). -->
283
287
  <div
@@ -15,8 +15,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
15
15
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
16
16
  onClick?: ((event: MouseEvent) => any) | undefined;
17
17
  }>, {
18
- color: "neutral" | "primary" | "secondary" | "error" | "warning" | "success" | "info";
19
18
  icon: string;
19
+ color: "neutral" | "primary" | "secondary" | "error" | "warning" | "success" | "info";
20
20
  size: "xs" | "sm" | "md" | "lg" | "xl";
21
21
  variant: "ghost" | "soft" | "outline" | "solid" | "subtle" | "link";
22
22
  tooltip: string;
@@ -15,8 +15,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
15
15
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
16
16
  onClick?: ((event: MouseEvent) => any) | undefined;
17
17
  }>, {
18
- color: "neutral" | "primary" | "secondary" | "error" | "warning" | "success" | "info";
19
18
  icon: string;
19
+ color: "neutral" | "primary" | "secondary" | "error" | "warning" | "success" | "info";
20
20
  size: "xs" | "sm" | "md" | "lg" | "xl";
21
21
  variant: "ghost" | "soft" | "outline" | "solid" | "subtle" | "link";
22
22
  tooltip: string;
@@ -2,15 +2,15 @@ type __VLS_Props = {
2
2
  open: boolean;
3
3
  };
4
4
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ "update:open": (v: boolean) => any;
5
6
  created: (args_0: {
6
7
  id: string;
7
8
  }) => any;
8
- "update:open": (v: boolean) => any;
9
9
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
10
11
  onCreated?: ((args_0: {
11
12
  id: string;
12
13
  }) => any) | undefined;
13
- "onUpdate:open"?: ((v: boolean) => any) | undefined;
14
14
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
15
  declare const _default: typeof __VLS_export;
16
16
  export default _default;
@@ -2,15 +2,15 @@ type __VLS_Props = {
2
2
  open: boolean;
3
3
  };
4
4
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ "update:open": (v: boolean) => any;
5
6
  created: (args_0: {
6
7
  id: string;
7
8
  }) => any;
8
- "update:open": (v: boolean) => any;
9
9
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
10
11
  onCreated?: ((args_0: {
11
12
  id: string;
12
13
  }) => any) | undefined;
13
- "onUpdate:open"?: ((v: boolean) => any) | undefined;
14
14
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
15
  declare const _default: typeof __VLS_export;
16
16
  export default _default;
@@ -12,8 +12,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
12
12
  awareness: boolean;
13
13
  tag: "video" | "audio";
14
14
  live: boolean;
15
- total: boolean;
16
15
  controls: boolean;
16
+ total: boolean;
17
17
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
18
  declare const _default: typeof __VLS_export;
19
19
  export default _default;
@@ -12,8 +12,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
12
12
  awareness: boolean;
13
13
  tag: "video" | "audio";
14
14
  live: boolean;
15
- total: boolean;
16
15
  controls: boolean;
16
+ total: boolean;
17
17
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
18
  declare const _default: typeof __VLS_export;
19
19
  export default _default;
@@ -1,3 +1,31 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ type __VLS_Props = {
2
+ /**
3
+ * Coordinate space the blob positions live in.
4
+ * - `viewport` (default): element-anchored peer pointer from `aa:focus`.
5
+ * - `world`: absolute world coords from `state[worldChannel]`, projected
6
+ * into the local viewport via `toScreen`.
7
+ */
8
+ coords?: 'viewport' | 'world';
9
+ /**
10
+ * Awareness state field carrying world coords `{x, y}` per peer. Only used
11
+ * in `coords="world"` mode. Defaults to `'cursor-pos'` to match the
12
+ * playground's map page broadcast.
13
+ */
14
+ worldChannel?: string;
15
+ /**
16
+ * Project a peer's world coordinates into local viewport CSS pixels.
17
+ * Required when `coords="world"`. Return `null` to drop a peer (e.g.
18
+ * because the point falls outside the visible region or the local
19
+ * camera isn't ready yet).
20
+ */
21
+ toScreen?: (worldX: number, worldY: number) => {
22
+ x: number;
23
+ y: number;
24
+ } | null;
25
+ };
26
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
27
+ coords: "viewport" | "world";
28
+ worldChannel: string;
29
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
2
30
  declare const _default: typeof __VLS_export;
3
31
  export default _default;