@abraca/nuxt 0.1.1 → 0.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 (154) hide show
  1. package/dist/module.d.mts +46 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +95 -2
  4. package/dist/runtime/assets/editor.css +1 -0
  5. package/dist/runtime/components/ACommandPalette.vue +4 -1
  6. package/dist/runtime/components/ADocRenderer.d.vue.ts +29 -0
  7. package/dist/runtime/components/ADocRenderer.vue +99 -0
  8. package/dist/runtime/components/ADocRenderer.vue.d.ts +29 -0
  9. package/dist/runtime/components/ADocTypeSelect.vue +4 -1
  10. package/dist/runtime/components/ADocumentTree.vue +78 -19
  11. package/dist/runtime/components/AEditor.d.vue.ts +9 -4
  12. package/dist/runtime/components/AEditor.vue +102 -7
  13. package/dist/runtime/components/AEditor.vue.d.ts +9 -4
  14. package/dist/runtime/components/AFloatingWindow.vue +1 -1
  15. package/dist/runtime/components/AIconPicker.vue +8 -2
  16. package/dist/runtime/components/ANodePanel.vue +100 -61
  17. package/dist/runtime/components/ANotifications.vue +35 -8
  18. package/dist/runtime/components/APermissionGuard.vue +3 -1
  19. package/dist/runtime/components/APresence.vue +14 -3
  20. package/dist/runtime/components/AProvider.vue +7 -1
  21. package/dist/runtime/components/AVoiceBar.vue +57 -15
  22. package/dist/runtime/components/AVoiceTile.vue +4 -1
  23. package/dist/runtime/components/AWindowLayer.vue +1 -1
  24. package/dist/runtime/components/aware/AArea.vue +1 -1
  25. package/dist/runtime/components/aware/AAvatar.vue +85 -16
  26. package/dist/runtime/components/aware/AButton.vue +5 -1
  27. package/dist/runtime/components/aware/ACursorLabel.vue +5 -1
  28. package/dist/runtime/components/aware/ADocBadge.vue +4 -1
  29. package/dist/runtime/components/aware/AFacepile.vue +13 -3
  30. package/dist/runtime/components/aware/AInput.vue +5 -1
  31. package/dist/runtime/components/aware/ATextarea.vue +5 -1
  32. package/dist/runtime/components/aware/AUserList.vue +8 -2
  33. package/dist/runtime/components/renderers/ACalendarRenderer.d.vue.ts +12 -1
  34. package/dist/runtime/components/renderers/ACalendarRenderer.vue +388 -114
  35. package/dist/runtime/components/renderers/ACalendarRenderer.vue.d.ts +12 -1
  36. package/dist/runtime/components/renderers/ACallRenderer.d.vue.ts +13 -0
  37. package/dist/runtime/components/renderers/ACallRenderer.vue +169 -0
  38. package/dist/runtime/components/renderers/ACallRenderer.vue.d.ts +13 -0
  39. package/dist/runtime/components/renderers/AChecklistRenderer.d.vue.ts +19 -0
  40. package/dist/runtime/components/renderers/AChecklistRenderer.vue +581 -0
  41. package/dist/runtime/components/renderers/AChecklistRenderer.vue.d.ts +19 -0
  42. package/dist/runtime/components/renderers/ADashboardRenderer.d.vue.ts +19 -0
  43. package/dist/runtime/components/renderers/ADashboardRenderer.vue +1372 -0
  44. package/dist/runtime/components/renderers/ADashboardRenderer.vue.d.ts +19 -0
  45. package/dist/runtime/components/renderers/AGalleryCoverImage.d.vue.ts +8 -0
  46. package/dist/runtime/components/renderers/AGalleryCoverImage.vue +60 -0
  47. package/dist/runtime/components/renderers/AGalleryCoverImage.vue.d.ts +8 -0
  48. package/dist/runtime/components/renderers/AGalleryRenderer.d.vue.ts +12 -1
  49. package/dist/runtime/components/renderers/AGalleryRenderer.vue +221 -55
  50. package/dist/runtime/components/renderers/AGalleryRenderer.vue.d.ts +12 -1
  51. package/dist/runtime/components/renderers/AGraphRenderer.d.vue.ts +19 -0
  52. package/dist/runtime/components/renderers/AGraphRenderer.vue +1027 -0
  53. package/dist/runtime/components/renderers/AGraphRenderer.vue.d.ts +19 -0
  54. package/dist/runtime/components/renderers/AKanbanRenderer.d.vue.ts +13 -1
  55. package/dist/runtime/components/renderers/AKanbanRenderer.vue +474 -140
  56. package/dist/runtime/components/renderers/AKanbanRenderer.vue.d.ts +13 -1
  57. package/dist/runtime/components/renderers/AMapRenderer.d.vue.ts +19 -0
  58. package/dist/runtime/components/renderers/AMapRenderer.vue +1622 -0
  59. package/dist/runtime/components/renderers/AMapRenderer.vue.d.ts +19 -0
  60. package/dist/runtime/components/renderers/AOutlineRenderer.d.vue.ts +12 -1
  61. package/dist/runtime/components/renderers/AOutlineRenderer.vue +294 -134
  62. package/dist/runtime/components/renderers/AOutlineRenderer.vue.d.ts +12 -1
  63. package/dist/runtime/components/renderers/ATableRenderer.d.vue.ts +12 -1
  64. package/dist/runtime/components/renderers/ATableRenderer.vue +437 -145
  65. package/dist/runtime/components/renderers/ATableRenderer.vue.d.ts +12 -1
  66. package/dist/runtime/components/renderers/ATimelineRenderer.d.vue.ts +19 -0
  67. package/dist/runtime/components/renderers/ATimelineRenderer.vue +446 -0
  68. package/dist/runtime/components/renderers/ATimelineRenderer.vue.d.ts +19 -0
  69. package/dist/runtime/composables/useAwareness.js +5 -0
  70. package/dist/runtime/composables/useBroadcastSync.d.ts +18 -0
  71. package/dist/runtime/composables/useBroadcastSync.js +26 -0
  72. package/dist/runtime/composables/useChat.js +4 -2
  73. package/dist/runtime/composables/useChatUsers.js +2 -1
  74. package/dist/runtime/composables/useCommandPalette.js +62 -3
  75. package/dist/runtime/composables/useConnectionStatus.js +7 -0
  76. package/dist/runtime/composables/useDevicePairing.d.ts +58 -0
  77. package/dist/runtime/composables/useDevicePairing.js +108 -0
  78. package/dist/runtime/composables/useDocExport.d.ts +5 -0
  79. package/dist/runtime/composables/useDocExport.js +2 -2
  80. package/dist/runtime/composables/useDocImport.js +4 -3
  81. package/dist/runtime/composables/useDocSeo.d.ts +20 -0
  82. package/dist/runtime/composables/useDocSeo.js +44 -0
  83. package/dist/runtime/composables/useDocSlugs.d.ts +7 -0
  84. package/dist/runtime/composables/useDocSlugs.js +20 -0
  85. package/dist/runtime/composables/useDocTree.d.ts +34 -0
  86. package/dist/runtime/composables/useDocTree.js +35 -0
  87. package/dist/runtime/composables/useEditorDragHandle.js +2 -1
  88. package/dist/runtime/composables/useEditorMentions.js +4 -2
  89. package/dist/runtime/composables/useEditorSuggestions.d.ts +1 -0
  90. package/dist/runtime/composables/useEditorSuggestions.js +9 -2
  91. package/dist/runtime/composables/useEditorToolbar.js +2 -1
  92. package/dist/runtime/composables/useFileIndex.js +2 -1
  93. package/dist/runtime/composables/useFileTransfer.d.ts +112 -0
  94. package/dist/runtime/composables/useFileTransfer.js +171 -0
  95. package/dist/runtime/composables/useFollowUser.js +2 -1
  96. package/dist/runtime/composables/useInvites.d.ts +56 -0
  97. package/dist/runtime/composables/useInvites.js +77 -0
  98. package/dist/runtime/composables/useNodePanel.d.ts +14 -0
  99. package/dist/runtime/composables/useNodePanel.js +52 -0
  100. package/dist/runtime/composables/useNotifications.js +4 -2
  101. package/dist/runtime/composables/usePasskeyAccounts.js +4 -2
  102. package/dist/runtime/composables/useSearchIndex.d.ts +1 -0
  103. package/dist/runtime/composables/useSearchIndex.js +13 -5
  104. package/dist/runtime/composables/useServerInfo.d.ts +31 -0
  105. package/dist/runtime/composables/useServerInfo.js +80 -0
  106. package/dist/runtime/composables/useSlugRoute.d.ts +6 -0
  107. package/dist/runtime/composables/useSlugRoute.js +19 -0
  108. package/dist/runtime/composables/useSpaces.d.ts +37 -0
  109. package/dist/runtime/composables/useSpaces.js +83 -0
  110. package/dist/runtime/composables/useTouchDrag.d.ts +34 -0
  111. package/dist/runtime/composables/useTouchDrag.js +191 -0
  112. package/dist/runtime/composables/useTrash.d.ts +1 -1
  113. package/dist/runtime/composables/useTrash.js +6 -3
  114. package/dist/runtime/composables/useWebRTC.d.ts +50 -0
  115. package/dist/runtime/composables/useWebRTC.js +177 -0
  116. package/dist/runtime/extensions/meta-field.d.ts +4 -1
  117. package/dist/runtime/extensions/steps.js +1 -1
  118. package/dist/runtime/extensions/views/AccordionItemView.vue +13 -3
  119. package/dist/runtime/extensions/views/AccordionView.vue +4 -1
  120. package/dist/runtime/extensions/views/BadgeView.vue +11 -2
  121. package/dist/runtime/extensions/views/CalloutView.vue +4 -1
  122. package/dist/runtime/extensions/views/CardGroupView.vue +4 -1
  123. package/dist/runtime/extensions/views/CardView.vue +17 -3
  124. package/dist/runtime/extensions/views/CodeGroupView.vue +4 -1
  125. package/dist/runtime/extensions/views/CollapsibleView.vue +8 -2
  126. package/dist/runtime/extensions/views/FileNodeView.vue +32 -8
  127. package/dist/runtime/extensions/views/KbdView.vue +8 -2
  128. package/dist/runtime/extensions/views/MetaFieldView.vue +208 -46
  129. package/dist/runtime/extensions/views/ProseIconView.vue +8 -2
  130. package/dist/runtime/extensions/views/TabsView.vue +17 -4
  131. package/dist/runtime/locale.d.ts +71 -0
  132. package/dist/runtime/locale.js +71 -0
  133. package/dist/runtime/plugin-abracadabra.client.js +29 -3
  134. package/dist/runtime/plugin-abracadabra.server.js +2 -0
  135. package/dist/runtime/server/api/_abracadabra/render/[docId].get.d.ts +1 -1
  136. package/dist/runtime/server/api/_abracadabra/render/[docId].get.js +29 -4
  137. package/dist/runtime/server/api/_abracadabra/resolve/[...slug].get.d.ts +2 -0
  138. package/dist/runtime/server/api/_abracadabra/resolve/[...slug].get.js +43 -0
  139. package/dist/runtime/server/api/_abracadabra/slugs.get.d.ts +2 -0
  140. package/dist/runtime/server/api/_abracadabra/slugs.get.js +7 -0
  141. package/dist/runtime/server/plugins/abracadabra-service.js +10 -5
  142. package/dist/runtime/server/runners/doc-tree-cache.js +4 -0
  143. package/dist/runtime/server/utils/slugMap.d.ts +32 -0
  144. package/dist/runtime/server/utils/slugMap.js +58 -0
  145. package/dist/runtime/types.d.ts +1 -0
  146. package/dist/runtime/utils/docTypes.d.ts +29 -1
  147. package/dist/runtime/utils/docTypes.js +129 -1
  148. package/dist/runtime/utils/markdownToYjs.js +2 -2
  149. package/dist/runtime/utils/sdkRef.d.ts +2 -0
  150. package/dist/runtime/utils/sdkRef.js +7 -0
  151. package/dist/runtime/utils/slugify.d.ts +40 -0
  152. package/dist/runtime/utils/slugify.js +36 -0
  153. package/dist/types.d.mts +6 -0
  154. package/package.json +32 -19
package/dist/module.d.mts CHANGED
@@ -3,6 +3,9 @@ import * as __runtime_types from '../dist/runtime/types.js';
3
3
  export { AbracadabraPlugin, AbracadabraState, CachedTreeNode, DocCacheAPI, DocPageMeta, RunnerCleanup, ServerRunnerContext, ServerRunnerDefinition, TreeEntry, UserMetaField } from '../dist/runtime/types.js';
4
4
  import { AbracadabraLocale } from '../dist/runtime/locale.js';
5
5
  export { AbracadabraLocale } from '../dist/runtime/locale.js';
6
+ export { DocTreeReturn } from '../dist/runtime/composables/useDocTree.js';
7
+ export { DocSeoOptions } from '../dist/runtime/composables/useDocSeo.js';
8
+ export { SlugMap, SlugMapEntry, buildSlugMap, isUUID, slugify } from '../dist/runtime/utils/slugify.js';
6
9
  export { avatarBorderStyle, avatarGradient, avatarStyleFromName } from '../dist/runtime/utils/avatarStyle.js';
7
10
  export { COLOR_PALETTES, ColorPalette, ColorShade, findPaletteByHex } from '../dist/runtime/utils/colorPalettes.js';
8
11
  export { META_FIELD_DEFINITIONS, MetaFieldDefinition } from '../dist/runtime/utils/metaFieldDefinitions.js';
@@ -26,6 +29,8 @@ declare module '@nuxt/schema' {
26
29
  backgroundSync?: boolean;
27
30
  renderers?: boolean;
28
31
  serverCache?: boolean;
32
+ broadcastSync?: boolean;
33
+ webrtc?: boolean;
29
34
  };
30
35
  locale: AbracadabraLocale;
31
36
  auth: {
@@ -43,6 +48,15 @@ declare module '@nuxt/schema' {
43
48
  adjectives: string[];
44
49
  nouns: string[];
45
50
  };
51
+ webrtc: {
52
+ iceServers: Array<{
53
+ urls: string | string[];
54
+ username?: string;
55
+ credential?: string;
56
+ }>;
57
+ e2ee: boolean;
58
+ fileTransfer: boolean;
59
+ };
46
60
  };
47
61
  }
48
62
  interface RuntimeConfig {
@@ -109,6 +123,18 @@ interface ModuleOptions {
109
123
  * Default: true.
110
124
  */
111
125
  serverCache?: boolean;
126
+ /**
127
+ * Enable BroadcastChannel cross-tab sync for Y.js documents.
128
+ * Automatically syncs the root doc across browser tabs on the same origin.
129
+ * Zero config, no server needed. Default: true.
130
+ */
131
+ broadcastSync?: boolean;
132
+ /**
133
+ * Enable WebRTC P2P sync composables (useWebRTC, useDevicePairing).
134
+ * Opt-in — requires ICE server config and UI integration.
135
+ * Default: false.
136
+ */
137
+ webrtc?: boolean;
112
138
  };
113
139
  /**
114
140
  * Automatically add Vite resolve.dedupe entries for ProseMirror, TipTap, and Yjs.
@@ -164,6 +190,11 @@ interface ModuleOptions {
164
190
  * docBasePath: '' → /{docId}
165
191
  */
166
192
  docBasePath?: string;
193
+ /**
194
+ * Mapbox GL access token for the Map renderer.
195
+ * Can be overridden at runtime via NUXT_PUBLIC_ABRACADABRA_MAPBOX_TOKEN.
196
+ */
197
+ mapboxToken?: string;
167
198
  /**
168
199
  * Word lists for generating random guest display names.
169
200
  * Defaults to a fantasy-theme set ('Swift-Wizard', 'Bright-Mage', etc.).
@@ -173,6 +204,21 @@ interface ModuleOptions {
173
204
  adjectives?: string[];
174
205
  nouns?: string[];
175
206
  };
207
+ /**
208
+ * WebRTC P2P configuration. Only used when features.webrtc is true.
209
+ */
210
+ webrtc?: {
211
+ /** ICE servers for WebRTC connections. Default: Google STUN server. */
212
+ iceServers?: Array<{
213
+ urls: string | string[];
214
+ username?: string;
215
+ credential?: string;
216
+ }>;
217
+ /** Enable E2EE on WebRTC data channels. Requires claimed passkey identity. Default: false. */
218
+ e2ee?: boolean;
219
+ /** Enable file transfer over WebRTC data channels. Default: false. */
220
+ fileTransfer?: boolean;
221
+ };
176
222
  /**
177
223
  * Service-role provider configuration for server-side background runners.
178
224
  * When publicKey + privateKey are set, a Nitro plugin connects to the
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=4.0.0"
6
6
  },
7
- "version": "0.1.1",
7
+ "version": "0.3.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { defineNuxtModule, createResolver, addPlugin, addImportsDir, addComponentsDir, addServerHandler, addRouteMiddleware, addServerPlugin, addServerImportsDir } from '@nuxt/kit';
1
+ import { defineNuxtModule, createResolver, addPlugin, addImportsDir, addImports, addComponentsDir, addServerHandler, addRouteMiddleware, addServerPlugin, addServerImportsDir } from '@nuxt/kit';
2
2
  import { defu } from 'defu';
3
+ export { buildSlugMap, isUUID, slugify } from '../dist/runtime/utils/slugify.js';
3
4
  export { avatarBorderStyle, avatarGradient, avatarStyleFromName } from '../dist/runtime/utils/avatarStyle.js';
4
5
  export { COLOR_PALETTES, findPaletteByHex } from '../dist/runtime/utils/colorPalettes.js';
5
6
  export { META_FIELD_DEFINITIONS } from '../dist/runtime/utils/metaFieldDefinitions.js';
@@ -20,7 +21,9 @@ const module$1 = defineNuxtModule({
20
21
  search: true,
21
22
  backgroundSync: true,
22
23
  renderers: true,
23
- serverCache: true
24
+ serverCache: true,
25
+ broadcastSync: true,
26
+ webrtc: false
24
27
  },
25
28
  addViteDedupe: true,
26
29
  prefix: "",
@@ -37,6 +40,11 @@ const module$1 = defineNuxtModule({
37
40
  debug: false,
38
41
  docBasePath: "/doc",
39
42
  guestName: {},
43
+ webrtc: {
44
+ iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
45
+ e2ee: false,
46
+ fileTransfer: false
47
+ },
40
48
  service: {
41
49
  disabled: false
42
50
  }
@@ -58,9 +66,15 @@ const module$1 = defineNuxtModule({
58
66
  server: options.server ?? {},
59
67
  debug: options.debug ?? false,
60
68
  docBasePath: options.docBasePath ?? "/doc",
69
+ mapboxToken: options.mapboxToken ?? "",
61
70
  guestName: {
62
71
  adjectives: options.guestName?.adjectives ?? [],
63
72
  nouns: options.guestName?.nouns ?? []
73
+ },
74
+ webrtc: {
75
+ iceServers: options.webrtc?.iceServers ?? [{ urls: "stun:stun.l.google.com:19302" }],
76
+ e2ee: options.webrtc?.e2ee ?? false,
77
+ fileTransfer: options.webrtc?.fileTransfer ?? false
64
78
  }
65
79
  }
66
80
  }
@@ -73,6 +87,14 @@ const module$1 = defineNuxtModule({
73
87
  serviceDisabled: options.service?.disabled ?? false
74
88
  }
75
89
  });
90
+ nuxt.options.nitro = defu(nuxt.options.nitro, {
91
+ storage: {
92
+ "doc-cache": {
93
+ driver: "fs",
94
+ base: ".data/abracadabra-cache"
95
+ }
96
+ }
97
+ });
76
98
  if (options.addViteDedupe) {
77
99
  const dedupePackages = [
78
100
  "prosemirror-view",
@@ -84,6 +106,8 @@ const module$1 = defineNuxtModule({
84
106
  "prosemirror-inputrules",
85
107
  "prosemirror-history",
86
108
  "prosemirror-gapcursor",
109
+ "prosemirror-tables",
110
+ "prosemirror-schema-list",
87
111
  "yjs",
88
112
  "@tiptap/core",
89
113
  "@tiptap/pm",
@@ -95,6 +119,29 @@ const module$1 = defineNuxtModule({
95
119
  nuxt.options.vite.resolve.dedupe = [
96
120
  .../* @__PURE__ */ new Set([...existing, ...dedupePackages])
97
121
  ];
122
+ const pmMapping = {
123
+ "@tiptap/pm/state": "prosemirror-state",
124
+ "@tiptap/pm/view": "prosemirror-view",
125
+ "@tiptap/pm/model": "prosemirror-model",
126
+ "@tiptap/pm/transform": "prosemirror-transform",
127
+ "@tiptap/pm/keymap": "prosemirror-keymap",
128
+ "@tiptap/pm/inputrules": "prosemirror-inputrules",
129
+ "@tiptap/pm/history": "prosemirror-history",
130
+ "@tiptap/pm/gapcursor": "prosemirror-gapcursor",
131
+ "@tiptap/pm/schema-list": "prosemirror-schema-list",
132
+ "@tiptap/pm/tables": "prosemirror-tables"
133
+ };
134
+ nuxt.hook("vite:extendConfig", (config) => {
135
+ config.resolve ??= {};
136
+ config.resolve.alias ??= {};
137
+ if (Array.isArray(config.resolve.alias)) {
138
+ for (const [find, replacement] of Object.entries(pmMapping)) {
139
+ config.resolve.alias.push({ find, replacement });
140
+ }
141
+ } else {
142
+ Object.assign(config.resolve.alias, pmMapping);
143
+ }
144
+ });
98
145
  }
99
146
  nuxt.options.vite.optimizeDeps = defu(nuxt.options.vite.optimizeDeps, { include: [] });
100
147
  const includeList = nuxt.options.vite.optimizeDeps.include ?? [];
@@ -104,6 +151,11 @@ const module$1 = defineNuxtModule({
104
151
  "prosemirror-model",
105
152
  "prosemirror-transform",
106
153
  "prosemirror-tables",
154
+ "prosemirror-gapcursor",
155
+ "prosemirror-keymap",
156
+ "prosemirror-inputrules",
157
+ "prosemirror-history",
158
+ "prosemirror-schema-list",
107
159
  "@tiptap/extension-table",
108
160
  "@tiptap/extension-table-row",
109
161
  "@tiptap/extension-table-header",
@@ -113,6 +165,34 @@ const module$1 = defineNuxtModule({
113
165
  nuxt.options.vite.optimizeDeps.include = [
114
166
  .../* @__PURE__ */ new Set([...includeList, ...prosemirrorDeps])
115
167
  ];
168
+ if (options.features?.editor !== false) {
169
+ nuxt.options.css.push(resolver.resolve("./runtime/assets/editor.css"));
170
+ }
171
+ nuxt.hook("app:resolve", (app) => {
172
+ const appConfig = app.config ?? {};
173
+ appConfig.ui = appConfig.ui ?? {};
174
+ appConfig.ui.editor = defu(appConfig.ui.editor ?? {}, {
175
+ slots: {
176
+ base: [
177
+ // Tables
178
+ "[&_table]:w-full [&_table]:border-separate [&_table]:border-spacing-0 [&_table]:rounded-md",
179
+ "[&_th]:py-3 [&_th]:px-4 [&_th]:font-semibold [&_th]:text-sm [&_th]:text-left [&_th]:bg-muted/50 [&_th]:border-t [&_th]:border-b [&_th]:border-e [&_th]:first:border-s [&_th]:border-muted",
180
+ "[&_th_p]:my-0 [&_th_p]:leading-5",
181
+ "[&_td]:py-3 [&_td]:px-4 [&_td]:text-sm [&_td]:text-left [&_td]:border-b [&_td]:border-e [&_td]:first:border-s [&_td]:border-muted",
182
+ "[&_td_p]:my-0 [&_td_p]:leading-5 [&_td_code]:text-xs/5 [&_td_ul]:my-0 [&_td_ol]:my-0 [&_td_ul]:ps-4.5 [&_td_ol]:ps-4.5 [&_td_li]:leading-6 [&_td_li]:my-0.5",
183
+ "[&_tr:first-child_th:first-child]:rounded-tl-md [&_tr:first-child_th:last-child]:rounded-tr-md [&_tr:last-child_td:first-child]:rounded-bl-md [&_tr:last-child_td:last-child]:rounded-br-md",
184
+ "[&_.selectedCell]:bg-primary/10 [&_.selectedCell]:ring-2 [&_.selectedCell]:ring-primary [&_.selectedCell]:ring-inset",
185
+ // Task lists
186
+ "[&_ul[data-type=taskList]]:list-none [&_ul[data-type=taskList]]:ps-1",
187
+ "[&_ul[data-type=taskList]_li]:flex [&_ul[data-type=taskList]_li]:items-center [&_ul[data-type=taskList]_li]:ps-0",
188
+ "[&_ul[data-type=taskList]_li_label]:inline-flex [&_ul[data-type=taskList]_li_label]:pr-2.5",
189
+ "[&_ul[data-type=taskList]_li_label_input]:appearance-none [&_ul[data-type=taskList]_li_label_input]:size-4 [&_ul[data-type=taskList]_li_label_input]:rounded-sm [&_ul[data-type=taskList]_li_label_input]:ring [&_ul[data-type=taskList]_li_label_input]:ring-inset [&_ul[data-type=taskList]_li_label_input]:ring-accented [&_ul[data-type=taskList]_li_label_input]:bg-center",
190
+ "[&_ul[data-type=taskList]_li_label_input:checked]:bg-primary [&_ul[data-type=taskList]_li_label_input:checked]:ring-primary [&_ul[data-type=taskList]_li_label_input:checked]:bg-[url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTIwIDZMOSAxN2wtNS01Ii8+PC9zdmc+)] dark:[&_ul[data-type=taskList]_li_label_input:checked]:bg-[url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTIwIDZMOSAxN2wtNS01Ii8+PC9zdmc+)]",
191
+ "[&_ul[data-type=taskList]_li[data-checked=true]>div>p]:line-through [&_ul[data-type=taskList]_li[data-checked=true]>div>p]:opacity-50"
192
+ ]
193
+ }
194
+ });
195
+ });
116
196
  addPlugin({
117
197
  src: resolver.resolve("./runtime/plugin-abracadabra.server"),
118
198
  mode: "server"
@@ -126,6 +206,11 @@ const module$1 = defineNuxtModule({
126
206
  mode: "client"
127
207
  });
128
208
  addImportsDir(resolver.resolve("./runtime/composables"));
209
+ addImports([
210
+ { name: "slugify", from: resolver.resolve("./runtime/utils/slugify") },
211
+ { name: "buildSlugMap", from: resolver.resolve("./runtime/utils/slugify") },
212
+ { name: "isUUID", from: resolver.resolve("./runtime/utils/slugify") }
213
+ ]);
129
214
  addComponentsDir({
130
215
  path: resolver.resolve("./runtime/components/aware"),
131
216
  prefix: options.prefix ?? "",
@@ -151,6 +236,14 @@ const module$1 = defineNuxtModule({
151
236
  route: "/api/_abracadabra/spaces",
152
237
  handler: resolver.resolve("./runtime/server/api/_abracadabra/spaces.get")
153
238
  });
239
+ addServerHandler({
240
+ route: "/api/_abracadabra/resolve/**",
241
+ handler: resolver.resolve("./runtime/server/api/_abracadabra/resolve/[...slug].get")
242
+ });
243
+ addServerHandler({
244
+ route: "/api/_abracadabra/slugs",
245
+ handler: resolver.resolve("./runtime/server/api/_abracadabra/slugs.get")
246
+ });
154
247
  }
155
248
  if (options.auth?.middleware) {
156
249
  addRouteMiddleware({
@@ -0,0 +1 @@
1
+ html.dark .tiptap .shiki,html.dark .tiptap .shiki span{background-color:var(--ui-bg-muted)!important;color:var(--shiki-dark)!important}.collaboration-carets__caret{border-left:1px solid #0d0d0d;border-right:1px solid #0d0d0d;margin-left:-1px;margin-right:-1px;opacity:0;pointer-events:none;position:relative;transition:opacity .3s ease;word-break:normal}.collaboration-carets__caret.is-hidden{display:none}.collaboration-carets__caret.is-active{opacity:1}.collaboration-carets__label{border-radius:3px 3px 3px 0;color:#0d0d0d;font-size:12px;font-style:normal;font-weight:600;left:-1px;line-height:normal;padding:.1rem .3rem;position:absolute;top:-1.4em;-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.ProseMirror-yjs-selection,.collaboration-carets__selection{background-color:var(--collaboration-selection-color)!important;pointer-events:none}.search-highlight{background-color:color-mix(in srgb,var(--color-primary-400) 35%,transparent);border-radius:2px;padding:0 1px}.doc-passage-highlight{background-color:color-mix(in srgb,var(--color-success-400) 35%,transparent);border-radius:2px;padding:0 1px}
@@ -17,7 +17,10 @@ defineShortcuts({ meta_k: toggle });
17
17
 
18
18
  <template>
19
19
  <ClientOnly>
20
- <UModal v-model:open="isOpen" :ui="{ content: 'p-0' }">
20
+ <UModal
21
+ v-model:open="isOpen"
22
+ :ui="{ content: 'p-0' }"
23
+ >
21
24
  <template #content>
22
25
  <UCommandPalette
23
26
  v-model="searchTerm"
@@ -0,0 +1,29 @@
1
+ type __VLS_Props = {
2
+ /** Document ID to render */
3
+ docId: string;
4
+ /** Whether the document is editable. Default: true */
5
+ editable?: boolean;
6
+ /** CSS class applied to editor-type documents (doc, or hasEditor: true) */
7
+ editorClass?: string;
8
+ /** CSS class applied to structured renderers (kanban, table, etc.) */
9
+ rendererClass?: string;
10
+ };
11
+ declare var __VLS_1: {}, __VLS_23: {
12
+ error: any;
13
+ };
14
+ type __VLS_Slots = {} & {
15
+ loading?: (props: typeof __VLS_1) => any;
16
+ } & {
17
+ error?: (props: typeof __VLS_23) => any;
18
+ };
19
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
20
+ editable: boolean;
21
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
23
+ declare const _default: typeof __VLS_export;
24
+ export default _default;
25
+ type __VLS_WithSlots<T, S> = T & {
26
+ new (): {
27
+ $slots: S;
28
+ };
29
+ };
@@ -0,0 +1,99 @@
1
+ <script setup>
2
+ import { computed, watch, shallowRef } from "vue";
3
+ import { resolveDocType } from "../utils/docTypes";
4
+ const props = defineProps({
5
+ docId: { type: String, required: true },
6
+ editable: { type: Boolean, required: false, default: true },
7
+ editorClass: { type: String, required: false },
8
+ rendererClass: { type: String, required: false }
9
+ });
10
+ const abra = useAbracadabra();
11
+ const treeMap = useSyncedMap(abra.doc, "doc-tree");
12
+ const docEntry = computed(() => treeMap.data[props.docId]);
13
+ const docTitle = computed(() => docEntry.value?.label ?? "Untitled");
14
+ const docType = computed(() => docEntry.value?.type ?? "doc");
15
+ const docMeta = computed(() => docEntry.value?.meta ?? {});
16
+ const registry = usePluginRegistry();
17
+ const docTypeDef = computed(() => resolveDocType(docType.value, registry));
18
+ const childProvider = shallowRef(null);
19
+ async function loadChildProvider(id) {
20
+ childProvider.value = null;
21
+ if (!abra.provider.value) return;
22
+ try {
23
+ const prov = await abra.provider.value.loadChild(id);
24
+ if (!prov.isSynced) {
25
+ await new Promise((resolve) => {
26
+ const done = () => {
27
+ prov.off("synced", done);
28
+ resolve();
29
+ };
30
+ prov.on("synced", done);
31
+ setTimeout(resolve, 6e3);
32
+ });
33
+ }
34
+ childProvider.value = prov;
35
+ } catch (e) {
36
+ console.error("[ADocRenderer] Failed to load child provider:", e);
37
+ }
38
+ }
39
+ watch([() => abra.isReady.value, () => props.docId], ([ready, id]) => {
40
+ if (ready && id) loadChildProvider(id);
41
+ }, { immediate: true });
42
+ const { data: ssrContent } = useFetch(
43
+ () => `/api/_abracadabra/render/${props.docId}`,
44
+ { key: `render-${props.docId}`, server: true, lazy: true }
45
+ );
46
+ const resolvedClass = computed(
47
+ () => docTypeDef.value.hasEditor ? props.editorClass ?? void 0 : props.rendererClass ?? void 0
48
+ );
49
+ </script>
50
+
51
+ <template>
52
+ <!-- Loading state -->
53
+ <div v-if="!abra.isReady.value">
54
+ <!-- SSR: show pre-rendered HTML while client hydrates -->
55
+ <div
56
+ v-if="ssrContent?.html"
57
+ class="prose dark:prose-invert max-w-none"
58
+ v-html="ssrContent.html"
59
+ />
60
+ <slot
61
+ v-else
62
+ name="loading"
63
+ >
64
+ <div class="p-8 space-y-3">
65
+ <USkeleton class="h-8 w-48" />
66
+ <USkeleton class="h-4 w-full" />
67
+ <USkeleton class="h-4 w-3/4" />
68
+ <USkeleton class="h-4 w-5/6" />
69
+ </div>
70
+ </slot>
71
+ </div>
72
+
73
+ <!-- Connection error -->
74
+ <slot
75
+ v-else-if="abra.connectionError.value && !abra.synced.value"
76
+ name="error"
77
+ :error="abra.connectionError.value"
78
+ >
79
+ <UAlert
80
+ class="m-8"
81
+ color="error"
82
+ icon="i-lucide-wifi-off"
83
+ :title="abra.connectionError.value"
84
+ description="Unable to connect to the server."
85
+ />
86
+ </slot>
87
+
88
+ <!-- Resolved renderer -->
89
+ <component
90
+ :is="docTypeDef.component"
91
+ v-else
92
+ :doc-id="docId"
93
+ :doc-label="docTitle"
94
+ :doc-meta="docMeta"
95
+ :child-provider="childProvider"
96
+ :editable="editable"
97
+ :class="resolvedClass"
98
+ />
99
+ </template>
@@ -0,0 +1,29 @@
1
+ type __VLS_Props = {
2
+ /** Document ID to render */
3
+ docId: string;
4
+ /** Whether the document is editable. Default: true */
5
+ editable?: boolean;
6
+ /** CSS class applied to editor-type documents (doc, or hasEditor: true) */
7
+ editorClass?: string;
8
+ /** CSS class applied to structured renderers (kanban, table, etc.) */
9
+ rendererClass?: string;
10
+ };
11
+ declare var __VLS_1: {}, __VLS_23: {
12
+ error: any;
13
+ };
14
+ type __VLS_Slots = {} & {
15
+ loading?: (props: typeof __VLS_1) => any;
16
+ } & {
17
+ error?: (props: typeof __VLS_23) => any;
18
+ };
19
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
20
+ editable: boolean;
21
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
23
+ declare const _default: typeof __VLS_export;
24
+ export default _default;
25
+ type __VLS_WithSlots<T, S> = T & {
26
+ new (): {
27
+ $slots: S;
28
+ };
29
+ };
@@ -28,7 +28,10 @@ const current = computed(() => types.find((t) => t.type === props.modelValue));
28
28
  class="size-4 text-muted shrink-0"
29
29
  />
30
30
  <span class="text-sm flex-1 text-left truncate">{{ current?.label ?? modelValue }}</span>
31
- <UIcon name="i-lucide-chevron-down" class="size-3 text-muted shrink-0" />
31
+ <UIcon
32
+ name="i-lucide-chevron-down"
33
+ class="size-3 text-muted shrink-0"
34
+ />
32
35
  </button>
33
36
  </UDropdownMenu>
34
37
  </template>
@@ -881,9 +881,18 @@ defineExpose({
881
881
  v-if="collapsed && ancestorChain.length"
882
882
  class="flex flex-col items-center gap-0.5 py-1.5"
883
883
  >
884
- <template v-for="(node, i) in ancestorChain" :key="node.id">
885
- <div v-if="i > 0" class="h-2 w-px bg-(--ui-border)" />
886
- <UTooltip :text="node.label" :content="{ side: 'right' }">
884
+ <template
885
+ v-for="(node, i) in ancestorChain"
886
+ :key="node.id"
887
+ >
888
+ <div
889
+ v-if="i > 0"
890
+ class="h-2 w-px bg-(--ui-border)"
891
+ />
892
+ <UTooltip
893
+ :text="node.label"
894
+ :content="{ side: 'right' }"
895
+ >
887
896
  <UButton
888
897
  :icon="getItemIcon(nodeToFlatItem(node))"
889
898
  size="xs"
@@ -896,9 +905,20 @@ defineExpose({
896
905
  </template>
897
906
 
898
907
  <!-- Collapsed trash icon -->
899
- <div v-if="trashedCount > 0" class="mt-auto pt-2">
900
- <UChip :text="trashedCount" color="neutral" size="sm" inset>
901
- <UTooltip text="Trash" :content="{ side: 'right' }">
908
+ <div
909
+ v-if="trashedCount > 0"
910
+ class="mt-auto pt-2"
911
+ >
912
+ <UChip
913
+ :text="trashedCount"
914
+ color="neutral"
915
+ size="sm"
916
+ inset
917
+ >
918
+ <UTooltip
919
+ text="Trash"
920
+ :content="{ side: 'right' }"
921
+ >
902
922
  <UButton
903
923
  icon="i-lucide-trash-2"
904
924
  size="xs"
@@ -1025,7 +1045,10 @@ defineExpose({
1025
1045
  class="size-3.5"
1026
1046
  />
1027
1047
  </span>
1028
- <UIcon name="i-lucide-trash-2" class="size-4 shrink-0" />
1048
+ <UIcon
1049
+ name="i-lucide-trash-2"
1050
+ class="size-4 shrink-0"
1051
+ />
1029
1052
  <span class="truncate flex-1 min-w-0 text-left">Trash</span>
1030
1053
  <UBadge
1031
1054
  v-if="trashedCount > 0"
@@ -1060,9 +1083,15 @@ defineExpose({
1060
1083
  class="size-3.5"
1061
1084
  />
1062
1085
  </span>
1063
- <span v-else class="size-5 shrink-0" />
1086
+ <span
1087
+ v-else
1088
+ class="size-5 shrink-0"
1089
+ />
1064
1090
 
1065
- <UIcon :name="getItemIcon(item)" class="size-4 shrink-0 text-(--ui-text-muted)" />
1091
+ <UIcon
1092
+ :name="getItemIcon(item)"
1093
+ class="size-4 shrink-0 text-(--ui-text-muted)"
1094
+ />
1066
1095
  <span class="truncate flex-1 min-w-0 text-left">{{ item.name }}</span>
1067
1096
  </button>
1068
1097
  </UContextMenu>
@@ -1095,7 +1124,10 @@ defineExpose({
1095
1124
  class="size-3.5"
1096
1125
  />
1097
1126
  </span>
1098
- <span v-else class="size-5 shrink-0" />
1127
+ <span
1128
+ v-else
1129
+ class="size-5 shrink-0"
1130
+ />
1099
1131
 
1100
1132
  <UIcon
1101
1133
  :name="getItemIcon(item)"
@@ -1116,7 +1148,10 @@ defineExpose({
1116
1148
  @blur="commitRename"
1117
1149
  @click.stop
1118
1150
  />
1119
- <span v-else class="truncate flex-1 min-w-0 text-left">{{ item.name }}</span>
1151
+ <span
1152
+ v-else
1153
+ class="truncate flex-1 min-w-0 text-left"
1154
+ >{{ item.name }}</span>
1120
1155
 
1121
1156
  <!-- Unread chat badge -->
1122
1157
  <UBadge
@@ -1149,7 +1184,6 @@ defineExpose({
1149
1184
  +{{ docPresence.get(item.id).length - MAX_PRESENCE }}
1150
1185
  </div>
1151
1186
  </div>
1152
-
1153
1187
  </button>
1154
1188
  </UContextMenu>
1155
1189
 
@@ -1178,7 +1212,10 @@ defineExpose({
1178
1212
  class="size-3.5"
1179
1213
  />
1180
1214
  </span>
1181
- <span v-else class="size-5 shrink-0" />
1215
+ <span
1216
+ v-else
1217
+ class="size-5 shrink-0"
1218
+ />
1182
1219
 
1183
1220
  <UIcon
1184
1221
  :name="getItemIcon(item)"
@@ -1239,8 +1276,16 @@ defineExpose({
1239
1276
  @click="onRestoreItem(item)"
1240
1277
  />
1241
1278
  </UTooltip>
1242
- <UDropdownMenu :items="trashNodeMenuItems(item)" :content="{ align: 'start' }">
1243
- <UButton icon="i-lucide-ellipsis" size="xs" variant="ghost" color="neutral" />
1279
+ <UDropdownMenu
1280
+ :items="trashNodeMenuItems(item)"
1281
+ :content="{ align: 'start' }"
1282
+ >
1283
+ <UButton
1284
+ icon="i-lucide-ellipsis"
1285
+ size="xs"
1286
+ variant="ghost"
1287
+ color="neutral"
1288
+ />
1244
1289
  </UDropdownMenu>
1245
1290
  </div>
1246
1291
  <!-- Editable item actions -->
@@ -1258,7 +1303,10 @@ defineExpose({
1258
1303
  variant="ghost"
1259
1304
  @click="isInThisCall(item) ? leaveRoom() : joinRoom(item.id)"
1260
1305
  />
1261
- <UTooltip v-if="!isCallDoc(item)" text="Add child page">
1306
+ <UTooltip
1307
+ v-if="!isCallDoc(item)"
1308
+ text="Add child page"
1309
+ >
1262
1310
  <UButton
1263
1311
  icon="i-lucide-plus"
1264
1312
  size="xs"
@@ -1267,8 +1315,16 @@ defineExpose({
1267
1315
  @click="createDirectly(item.id)"
1268
1316
  />
1269
1317
  </UTooltip>
1270
- <UDropdownMenu :items="treeNodeMenuItems(item)" :content="{ align: 'start' }">
1271
- <UButton icon="i-lucide-ellipsis" size="xs" variant="ghost" color="neutral" />
1318
+ <UDropdownMenu
1319
+ :items="treeNodeMenuItems(item)"
1320
+ :content="{ align: 'start' }"
1321
+ >
1322
+ <UButton
1323
+ icon="i-lucide-ellipsis"
1324
+ size="xs"
1325
+ variant="ghost"
1326
+ color="neutral"
1327
+ />
1272
1328
  </UDropdownMenu>
1273
1329
  </div>
1274
1330
  </div>
@@ -1291,7 +1347,10 @@ defineExpose({
1291
1347
  Drop into
1292
1348
  <span class="font-medium text-(--ui-text-highlighted)">{{ nodeMap.get(dropIndicator.targetId)?.label }}</span>
1293
1349
  </span>
1294
- <span v-else class="text-xs text-(--ui-text-muted)">
1350
+ <span
1351
+ v-else
1352
+ class="text-xs text-(--ui-text-muted)"
1353
+ >
1295
1354
  Drop to import — docs, images, or any file
1296
1355
  </span>
1297
1356
  </div>
@@ -1,4 +1,5 @@
1
1
  import type { DocPageMeta } from '../types.js';
2
+ import type { MetaField } from '../utils/docTypes.js';
2
3
  type __VLS_Props = {
3
4
  /** Y.Doc ID to load as a child document */
4
5
  docId: string;
@@ -18,6 +19,10 @@ type __VLS_Props = {
18
19
  showDragHandle?: boolean;
19
20
  /** Current document metadata from the doc-tree — written into MetaField storage */
20
21
  docMeta?: DocPageMeta;
22
+ /** Parent document's type key — used to resolve metaSchema for auto-inserting chips */
23
+ parentType?: string;
24
+ /** Override metaSchema directly instead of resolving from parentType */
25
+ metaSchema?: MetaField[];
21
26
  };
22
27
  type __VLS_ModelProps = {
23
28
  modelValue?: any;
@@ -39,15 +44,15 @@ type __VLS_Slots = {} & {
39
44
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
40
45
  "update:modelValue": (value: any) => any;
41
46
  rename: (label: string) => any;
42
- ready: () => any;
43
- update: (content: any) => any;
44
47
  updateMeta: (patch: Partial<DocPageMeta>) => any;
48
+ update: (content: any) => any;
49
+ ready: () => any;
45
50
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
46
51
  "onUpdate:modelValue"?: ((value: any) => any) | undefined;
47
52
  onRename?: ((label: string) => any) | undefined;
48
- onReady?: (() => any) | undefined;
49
- onUpdate?: ((content: any) => any) | undefined;
50
53
  onUpdateMeta?: ((patch: Partial<DocPageMeta>) => any) | undefined;
54
+ onUpdate?: ((content: any) => any) | undefined;
55
+ onReady?: (() => any) | undefined;
51
56
  }>, {
52
57
  contentType: "json" | "html" | "markdown";
53
58
  editable: boolean;