@abraca/nuxt 2.10.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.d.mts +14 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +9 -0
- package/dist/runtime/assets/editor.css +1 -1
- package/dist/runtime/components/AConnectionBadge.d.vue.ts +29 -0
- package/dist/runtime/components/AConnectionBadge.vue +79 -0
- package/dist/runtime/components/AConnectionBadge.vue.d.ts +29 -0
- package/dist/runtime/components/ADocPickerModal.d.vue.ts +31 -0
- package/dist/runtime/components/ADocPickerModal.vue +191 -0
- package/dist/runtime/components/ADocPickerModal.vue.d.ts +31 -0
- package/dist/runtime/components/ADocumentTree.vue +65 -0
- package/dist/runtime/components/AEditor.d.vue.ts +19 -12
- package/dist/runtime/components/AEditor.vue +243 -165
- package/dist/runtime/components/AEditor.vue.d.ts +19 -12
- package/dist/runtime/components/AEncryptionModePicker.d.vue.ts +33 -0
- package/dist/runtime/components/AEncryptionModePicker.vue +211 -0
- package/dist/runtime/components/AEncryptionModePicker.vue.d.ts +33 -0
- package/dist/runtime/components/AModalShell.d.vue.ts +48 -0
- package/dist/runtime/components/AModalShell.vue +105 -0
- package/dist/runtime/components/AModalShell.vue.d.ts +48 -0
- package/dist/runtime/components/ANodePanel.d.vue.ts +17 -7
- package/dist/runtime/components/ANodePanel.vue +550 -451
- package/dist/runtime/components/ANodePanel.vue.d.ts +17 -7
- package/dist/runtime/components/ANodePanelHeader.d.vue.ts +20 -10
- package/dist/runtime/components/ANodePanelHeader.vue +17 -3
- package/dist/runtime/components/ANodePanelHeader.vue.d.ts +20 -10
- package/dist/runtime/components/ANodeSettingsPanel.d.vue.ts +2 -0
- package/dist/runtime/components/ANodeSettingsPanel.vue +21 -1
- package/dist/runtime/components/ANodeSettingsPanel.vue.d.ts +2 -0
- package/dist/runtime/components/ASnapshotPreviewModal.d.vue.ts +33 -0
- package/dist/runtime/components/ASnapshotPreviewModal.vue +430 -0
- package/dist/runtime/components/ASnapshotPreviewModal.vue.d.ts +33 -0
- package/dist/runtime/components/ATagsEditor.d.vue.ts +19 -0
- package/dist/runtime/components/ATagsEditor.vue +60 -0
- package/dist/runtime/components/ATagsEditor.vue.d.ts +19 -0
- package/dist/runtime/components/aware/AMedia.d.vue.ts +1 -1
- package/dist/runtime/components/aware/AMedia.vue.d.ts +1 -1
- package/dist/runtime/components/chat/AChatInput.d.vue.ts +11 -6
- package/dist/runtime/components/chat/AChatInput.vue +33 -2
- package/dist/runtime/components/chat/AChatInput.vue.d.ts +11 -6
- package/dist/runtime/components/chat/AChatList.d.vue.ts +12 -0
- package/dist/runtime/components/chat/AChatList.vue +76 -32
- package/dist/runtime/components/chat/AChatList.vue.d.ts +12 -0
- package/dist/runtime/components/chat/AChatMessages.d.vue.ts +4 -0
- package/dist/runtime/components/chat/AChatMessages.vue +57 -4
- package/dist/runtime/components/chat/AChatMessages.vue.d.ts +4 -0
- package/dist/runtime/components/chat/AChatPanel.d.vue.ts +6 -2
- package/dist/runtime/components/chat/AChatPanel.vue +17 -1
- package/dist/runtime/components/chat/AChatPanel.vue.d.ts +6 -2
- package/dist/runtime/components/chat/ANodeChatPanel.vue +1 -1
- package/dist/runtime/components/docs/ADocsSearch.d.vue.ts +1 -1
- package/dist/runtime/components/docs/ADocsSearch.vue.d.ts +1 -1
- package/dist/runtime/components/editor/ALocationPickerPopover.vue +28 -7
- package/dist/runtime/components/registry/APluginDetail.d.vue.ts +2 -2
- package/dist/runtime/components/registry/APluginDetail.vue.d.ts +2 -2
- package/dist/runtime/components/renderers/AChartRenderer.client.d.vue.ts +17 -0
- package/dist/runtime/components/renderers/AChartRenderer.client.vue +622 -0
- package/dist/runtime/components/renderers/AChartRenderer.client.vue.d.ts +17 -0
- package/dist/runtime/components/renderers/AGraphRenderer.vue +64 -15
- package/dist/runtime/components/renderers/AProseRenderer.d.vue.ts +2 -2
- package/dist/runtime/components/renderers/AProseRenderer.vue.d.ts +2 -2
- package/dist/runtime/components/renderers/calendar/ACalendarToolbar.d.vue.ts +2 -2
- package/dist/runtime/components/renderers/calendar/ACalendarToolbar.vue.d.ts +2 -2
- package/dist/runtime/components/renderers/media/MediaTransportBar.d.vue.ts +2 -2
- package/dist/runtime/components/renderers/media/MediaTransportBar.vue.d.ts +2 -2
- package/dist/runtime/components/renderers/sheets/ASheetsGrid.d.vue.ts +2 -2
- package/dist/runtime/components/renderers/sheets/ASheetsGrid.vue.d.ts +2 -2
- package/dist/runtime/components/settings/ASettingsAppearancePanel.d.vue.ts +3 -0
- package/dist/runtime/components/settings/ASettingsAppearancePanel.vue +67 -0
- package/dist/runtime/components/settings/ASettingsAppearancePanel.vue.d.ts +3 -0
- package/dist/runtime/components/settings/ASettingsGroup.d.vue.ts +24 -0
- package/dist/runtime/components/settings/ASettingsGroup.vue +31 -0
- package/dist/runtime/components/settings/ASettingsGroup.vue.d.ts +24 -0
- package/dist/runtime/components/settings/ASettingsModal.vue +84 -53
- package/dist/runtime/components/settings/ASettingsPlaceholder.d.vue.ts +20 -0
- package/dist/runtime/components/settings/ASettingsPlaceholder.vue +32 -0
- package/dist/runtime/components/settings/ASettingsPlaceholder.vue.d.ts +20 -0
- package/dist/runtime/components/settings/ASettingsRow.d.vue.ts +34 -0
- package/dist/runtime/components/settings/ASettingsRow.vue +34 -0
- package/dist/runtime/components/settings/ASettingsRow.vue.d.ts +34 -0
- package/dist/runtime/components/settings/sections.d.ts +37 -0
- package/dist/runtime/components/settings/sections.js +45 -0
- package/dist/runtime/components/shell/ABreadcrumbForDoc.d.vue.ts +6 -0
- package/dist/runtime/components/shell/ABreadcrumbForDoc.vue +75 -3
- package/dist/runtime/components/shell/ABreadcrumbForDoc.vue.d.ts +6 -0
- package/dist/runtime/components/shell/ADocPanelServerSettings.d.vue.ts +17 -0
- package/dist/runtime/components/shell/ADocPanelServerSettings.vue +253 -0
- package/dist/runtime/components/shell/ADocPanelServerSettings.vue.d.ts +17 -0
- package/dist/runtime/components/shell/ADocPanelSettings.d.vue.ts +2 -0
- package/dist/runtime/components/shell/ADocPanelSettings.vue +15 -4
- package/dist/runtime/components/shell/ADocPanelSettings.vue.d.ts +2 -0
- package/dist/runtime/components/shell/AUserProfilePopover.d.vue.ts +1 -1
- package/dist/runtime/components/shell/AUserProfilePopover.vue.d.ts +1 -1
- package/dist/runtime/composables/useChat.d.ts +22 -1
- package/dist/runtime/composables/useChat.js +79 -8
- package/dist/runtime/composables/useDocBreadcrumb.d.ts +17 -2
- package/dist/runtime/composables/useDocBreadcrumb.js +17 -3
- package/dist/runtime/composables/useDocSnapshots.d.ts +2 -1
- package/dist/runtime/composables/useDocSnapshots.js +5 -0
- package/dist/runtime/composables/useEditor.d.ts +1 -1
- package/dist/runtime/composables/useEditor.js +120 -0
- package/dist/runtime/composables/useEditorToolbar.d.ts +12 -4
- package/dist/runtime/composables/useEditorToolbar.js +78 -56
- package/dist/runtime/composables/useNodeContextMenu.d.ts +14 -0
- package/dist/runtime/composables/useNodeContextMenu.js +59 -1
- package/dist/runtime/composables/useSettingsModal.d.ts +1 -1
- package/dist/runtime/composables/useSwipeGesture.d.ts +48 -0
- package/dist/runtime/composables/useSwipeGesture.js +140 -0
- package/dist/runtime/extensions/document-header.js +16 -6
- package/dist/runtime/extensions/document-meta.js +344 -19
- package/dist/runtime/extensions/meta-field.js +42 -0
- package/dist/runtime/extensions/views/DocumentMetaView.vue +33 -7
- package/dist/runtime/extensions/views/FieldView.vue +51 -19
- package/dist/runtime/extensions/views/MetaFieldView.vue +30 -4
- package/dist/runtime/locale.d.ts +8 -0
- package/dist/runtime/locale.js +9 -1
- package/dist/runtime/middleware/abracadabra-auth.d.ts +1 -1
- package/dist/runtime/plugin-abracadabra.client.d.ts +1 -1
- package/dist/runtime/plugin-abracadabra.client.js +12 -2
- package/dist/runtime/plugin-abracadabra.server.d.ts +1 -1
- package/dist/runtime/plugin-shared-globals.client.d.ts +1 -1
- package/dist/runtime/utils/chatContent.d.ts +20 -2
- package/dist/runtime/utils/chatContent.js +20 -1
- package/dist/runtime/utils/docTypes.js +43 -0
- package/dist/runtime/utils/titleSync.d.ts +130 -0
- package/dist/runtime/utils/titleSync.js +53 -0
- package/package.json +11 -4
|
@@ -5,7 +5,11 @@ import { Fragment } from "@tiptap/pm/model";
|
|
|
5
5
|
import { useSyncedMap } from "../composables/useYDoc";
|
|
6
6
|
import { resolveDocType, GEO_TYPE_META_SCHEMAS } from "../utils/docTypes";
|
|
7
7
|
import { schemaFieldToAttrs, userFieldToAttrs } from "../extensions/meta-field";
|
|
8
|
+
import { decideTitleSync, setHeaderText as applyHeaderText, UNTITLED } from "../utils/titleSync";
|
|
8
9
|
import { useEditor } from "../composables/useEditor";
|
|
10
|
+
import { useDocTree } from "../composables/useDocTree";
|
|
11
|
+
import { useDocBreadcrumb } from "../composables/useDocBreadcrumb";
|
|
12
|
+
import { useDocSlugs } from "../composables/useDocSlugs";
|
|
9
13
|
import { useEditorToolbar } from "../composables/useEditorToolbar";
|
|
10
14
|
import { useEditorSuggestions } from "../composables/useEditorSuggestions";
|
|
11
15
|
import { useEditorDragHandle } from "../composables/useEditorDragHandle";
|
|
@@ -27,7 +31,8 @@ const props = defineProps({
|
|
|
27
31
|
parentType: { type: String, required: false },
|
|
28
32
|
metaSchema: { type: Array, required: false },
|
|
29
33
|
variant: { type: String, required: false, default: "doc" },
|
|
30
|
-
showSourceToggle: { type: Boolean, required: false, default: false }
|
|
34
|
+
showSourceToggle: { type: Boolean, required: false, default: false },
|
|
35
|
+
showBreadcrumb: { type: Boolean, required: false, default: true }
|
|
31
36
|
});
|
|
32
37
|
const viewMode = ref("rich");
|
|
33
38
|
const emit = defineEmits(["ready", "update", "rename", "updateMeta"]);
|
|
@@ -57,12 +62,21 @@ watch(ready, (val) => {
|
|
|
57
62
|
const editorRef = ref(null);
|
|
58
63
|
const tiptapEditor = computed(() => editorRef.value?.editor ?? null);
|
|
59
64
|
defineExpose({ editor: tiptapEditor });
|
|
60
|
-
const {
|
|
65
|
+
const { bubbleItems: toolbarItems } = useEditorToolbar({ docId: props.docId });
|
|
66
|
+
const docTree = useDocTree();
|
|
61
67
|
const resolvedMetaSchema = computed(() => {
|
|
62
68
|
if (props.metaSchema) return props.metaSchema;
|
|
63
69
|
const geoType = props.docMeta?.geoType;
|
|
64
70
|
if (geoType && geoType in GEO_TYPE_META_SCHEMAS)
|
|
65
71
|
return GEO_TYPE_META_SCHEMAS[geoType];
|
|
72
|
+
let pid = docTree.getEntry(props.docId)?.parentId ?? void 0;
|
|
73
|
+
while (pid) {
|
|
74
|
+
const entry = docTree.getEntry(pid);
|
|
75
|
+
if (!entry) break;
|
|
76
|
+
const schema = resolveDocType(entry.type, registry).metaSchema;
|
|
77
|
+
if (schema && schema.length > 0) return schema;
|
|
78
|
+
pid = entry.parentId ?? void 0;
|
|
79
|
+
}
|
|
66
80
|
return resolveDocType(props.parentType, registry).metaSchema ?? [];
|
|
67
81
|
});
|
|
68
82
|
const { items: allSuggestionItems, propertiesOnlyItems } = useEditorSuggestions({ docId: props.docId });
|
|
@@ -157,79 +171,93 @@ function initDocumentMeta(ed) {
|
|
|
157
171
|
metaInitDone = true;
|
|
158
172
|
}
|
|
159
173
|
let syncingFromEditor = false;
|
|
160
|
-
|
|
174
|
+
let lastSyncedLabel = null;
|
|
161
175
|
function getHeaderText(ed) {
|
|
162
176
|
const first = ed.state.doc.firstChild;
|
|
163
177
|
if (!first || first.type.name !== "documentHeader") return "";
|
|
164
178
|
return first.textContent;
|
|
165
179
|
}
|
|
166
|
-
function
|
|
167
|
-
|
|
168
|
-
if (!first || first.type.name !== "documentHeader") return;
|
|
169
|
-
if (first.textContent === text) return;
|
|
170
|
-
const { tr, schema } = ed.state;
|
|
171
|
-
const to = 1 + first.content.size;
|
|
172
|
-
if (text) {
|
|
173
|
-
tr.replaceWith(1, to, schema.text(text));
|
|
174
|
-
} else {
|
|
175
|
-
tr.delete(1, to);
|
|
176
|
-
}
|
|
177
|
-
ed.view.dispatch(tr);
|
|
180
|
+
function currentTreeLabel() {
|
|
181
|
+
return _treeMap.data[props.docId]?.label ?? props.docLabel ?? "";
|
|
178
182
|
}
|
|
179
|
-
function
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
function writeTreeLabel(label) {
|
|
184
|
+
const e = _treeMap.data[props.docId];
|
|
185
|
+
const next = label || UNTITLED;
|
|
186
|
+
if (!e || e.label === next) return;
|
|
183
187
|
syncingFromEditor = true;
|
|
184
|
-
|
|
188
|
+
lastSyncedLabel = next;
|
|
189
|
+
_treeMap.set(props.docId, { ...e, label: next, updatedAt: Date.now() });
|
|
190
|
+
emit("rename", next);
|
|
185
191
|
nextTick(() => {
|
|
186
192
|
syncingFromEditor = false;
|
|
187
193
|
});
|
|
188
194
|
}
|
|
195
|
+
function syncHeader(ed, isRemoteUpdate, initialSyncDone) {
|
|
196
|
+
const action = decideTitleSync({
|
|
197
|
+
headerText: getHeaderText(ed),
|
|
198
|
+
treeLabel: currentTreeLabel(),
|
|
199
|
+
isRemoteUpdate,
|
|
200
|
+
initialSyncDone
|
|
201
|
+
});
|
|
202
|
+
if (action.kind === "noop") return;
|
|
203
|
+
if (action.kind === "header-from-tree") {
|
|
204
|
+
applyHeaderText(ed, action.text);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
writeTreeLabel(action.label);
|
|
208
|
+
}
|
|
189
209
|
watchEffect((onCleanup) => {
|
|
190
210
|
const ed = editorRef.value?.editor;
|
|
191
211
|
if (!ed || !ready.value) return;
|
|
192
212
|
let initialSyncDone = false;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
213
|
+
let headerTimer = null;
|
|
214
|
+
const runSync = (isRemote) => {
|
|
215
|
+
const wasInitial = !initialSyncDone;
|
|
216
|
+
if (wasInitial) initialSyncDone = true;
|
|
217
|
+
syncHeader(ed, isRemote, !wasInitial);
|
|
218
|
+
};
|
|
219
|
+
function onUpdate({ transaction }) {
|
|
220
|
+
const isRemote = !!transaction?.getMeta?.("y-sync$")?.isChangeOrigin;
|
|
221
|
+
initDocumentMeta(ed);
|
|
222
|
+
if (isRemote || !initialSyncDone) {
|
|
223
|
+
if (headerTimer) {
|
|
224
|
+
clearTimeout(headerTimer);
|
|
225
|
+
headerTimer = null;
|
|
205
226
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
227
|
+
runSync(isRemote);
|
|
228
|
+
} else {
|
|
229
|
+
if (headerTimer) clearTimeout(headerTimer);
|
|
230
|
+
headerTimer = setTimeout(() => {
|
|
231
|
+
headerTimer = null;
|
|
232
|
+
runSync(false);
|
|
233
|
+
}, 200);
|
|
212
234
|
}
|
|
213
235
|
}
|
|
214
|
-
function onUpdate() {
|
|
215
|
-
syncHeaderToTree(ed);
|
|
216
|
-
initDocumentMeta(ed);
|
|
217
|
-
}
|
|
218
236
|
nextTick(() => {
|
|
219
|
-
|
|
237
|
+
runSync(false);
|
|
220
238
|
initDocumentMeta(ed);
|
|
221
239
|
});
|
|
222
240
|
ed.on("update", onUpdate);
|
|
223
|
-
onCleanup(() =>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (newLabel === _lastEmittedHeader.value) return;
|
|
228
|
-
if (!_treeMap.lastUpdateLocal.value) return;
|
|
229
|
-
const ed = editorRef.value?.editor;
|
|
230
|
-
if (!ed || !ready.value) return;
|
|
231
|
-
setHeaderText(ed, newLabel || "");
|
|
241
|
+
onCleanup(() => {
|
|
242
|
+
if (headerTimer) clearTimeout(headerTimer);
|
|
243
|
+
ed.off("update", onUpdate);
|
|
244
|
+
});
|
|
232
245
|
});
|
|
246
|
+
watch(
|
|
247
|
+
() => _treeMap.data[props.docId]?.label ?? props.docLabel,
|
|
248
|
+
(newLabel) => {
|
|
249
|
+
if (syncingFromEditor) return;
|
|
250
|
+
if (lastSyncedLabel !== null && newLabel === lastSyncedLabel) {
|
|
251
|
+
lastSyncedLabel = null;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
lastSyncedLabel = null;
|
|
255
|
+
if (newLabel === void 0 || newLabel === "" || newLabel === UNTITLED) return;
|
|
256
|
+
const ed = editorRef.value?.editor;
|
|
257
|
+
if (!ed || !ready.value) return;
|
|
258
|
+
applyHeaderText(ed, newLabel);
|
|
259
|
+
}
|
|
260
|
+
);
|
|
233
261
|
function insertNode(editor, type, attrs, content) {
|
|
234
262
|
const node = { type, attrs };
|
|
235
263
|
if (content) node.content = content;
|
|
@@ -347,6 +375,11 @@ const editorHandlers = {
|
|
|
347
375
|
const _mentionItems = computed(
|
|
348
376
|
() => registry.getAllMentionProviders().flatMap((p) => p.label ? [p] : [])
|
|
349
377
|
);
|
|
378
|
+
const { items: _breadcrumbItems } = useDocBreadcrumb(() => props.docId);
|
|
379
|
+
const { getDocUrl } = useDocSlugs();
|
|
380
|
+
const ancestorChain = computed(
|
|
381
|
+
() => _breadcrumbItems.value.slice(0, -1).map((a) => ({ ...a, to: getDocUrl(a.id) }))
|
|
382
|
+
);
|
|
350
383
|
function onPlusClick(e, onClick) {
|
|
351
384
|
e.stopPropagation();
|
|
352
385
|
onClick();
|
|
@@ -377,7 +410,10 @@ function onPlusClick(e, onClick) {
|
|
|
377
410
|
>
|
|
378
411
|
<div class="aeditor-source-toolbar">
|
|
379
412
|
<span class="aeditor-source-toolbar__label">
|
|
380
|
-
<UIcon
|
|
413
|
+
<UIcon
|
|
414
|
+
name="i-lucide-code-xml"
|
|
415
|
+
class="size-3.5"
|
|
416
|
+
/>
|
|
381
417
|
XML source — read-only mirror of <code>getXmlFragment('default')</code>
|
|
382
418
|
</span>
|
|
383
419
|
<UButton
|
|
@@ -398,136 +434,178 @@ function onPlusClick(e, onClick) {
|
|
|
398
434
|
/>
|
|
399
435
|
</div>
|
|
400
436
|
|
|
401
|
-
|
|
437
|
+
<!-- Editor canvas: ancestor breadcrumb (cou-sh parity) + the TipTap editor,
|
|
438
|
+
stacked in one scroll container (the parent's overflow class falls
|
|
439
|
+
through to this wrapper). -->
|
|
440
|
+
<div
|
|
402
441
|
v-else
|
|
403
|
-
|
|
404
|
-
ref="editorRef"
|
|
405
|
-
v-slot="{ editor }"
|
|
406
|
-
v-model="model"
|
|
407
|
-
:content-type="contentType"
|
|
408
|
-
:editable="editable"
|
|
409
|
-
:extensions="extensions"
|
|
410
|
-
:starter-kit="{ undoRedo: false, codeBlock: false, document: false }"
|
|
411
|
-
:handlers="editorHandlers"
|
|
412
|
-
:placeholder="placeholder"
|
|
413
|
-
@update:model-value="emit('update', $event)"
|
|
442
|
+
class="aeditor-canvas"
|
|
414
443
|
>
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
class="aeditor-
|
|
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
|
-
/>
|
|
426
|
-
<!-- Default slot: app can override entire editor content -->
|
|
427
|
-
<slot
|
|
428
|
-
:editor="editor"
|
|
429
|
-
:connected-users="connectedUsers"
|
|
430
|
-
:ready="ready"
|
|
444
|
+
<nav
|
|
445
|
+
v-if="showBreadcrumb && ancestorChain.length"
|
|
446
|
+
aria-label="Breadcrumb"
|
|
447
|
+
class="aeditor-breadcrumb"
|
|
431
448
|
>
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
layout="bubble"
|
|
441
|
-
:should-show="({ view, state }) => view.hasFocus() && !state.selection.empty"
|
|
442
|
-
>
|
|
443
|
-
<template #link>
|
|
444
|
-
<slot
|
|
445
|
-
name="link"
|
|
446
|
-
:editor="editor"
|
|
447
|
-
>
|
|
448
|
-
<ALinkPopover :editor="editor" />
|
|
449
|
-
</slot>
|
|
450
|
-
</template>
|
|
451
|
-
<template #doc-link>
|
|
452
|
-
<slot
|
|
453
|
-
name="doc-link"
|
|
454
|
-
:editor="editor"
|
|
449
|
+
<ol class="flex items-center gap-0.5 min-w-0">
|
|
450
|
+
<template
|
|
451
|
+
v-for="(ancestor, idx) in ancestorChain"
|
|
452
|
+
:key="ancestor.id"
|
|
453
|
+
>
|
|
454
|
+
<li
|
|
455
|
+
v-if="idx > 0"
|
|
456
|
+
class="flex shrink-0"
|
|
455
457
|
>
|
|
456
|
-
<
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
458
|
+
<UIcon
|
|
459
|
+
name="i-lucide-chevron-right"
|
|
460
|
+
class="size-4 text-(--ui-text-dimmed)"
|
|
461
|
+
/>
|
|
462
|
+
</li>
|
|
463
|
+
<li class="flex min-w-0">
|
|
464
|
+
<ULink
|
|
465
|
+
:to="ancestor.to"
|
|
466
|
+
class="flex items-center gap-1.5 px-1.5 py-0.5 rounded-md text-sm text-(--ui-text-muted) font-medium hover:bg-(--ui-bg-elevated)/60 hover:text-(--ui-text) transition-colors min-w-0 select-none"
|
|
467
|
+
>
|
|
468
|
+
<UIcon
|
|
469
|
+
:name="ancestor.icon"
|
|
470
|
+
class="size-4 shrink-0"
|
|
471
|
+
/>
|
|
472
|
+
<span class="truncate">{{ ancestor.label }}</span>
|
|
473
|
+
</ULink>
|
|
474
|
+
</li>
|
|
464
475
|
</template>
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
name="send-to-chat"
|
|
468
|
-
:editor="editor"
|
|
469
|
-
/>
|
|
470
|
-
</template>
|
|
471
|
-
</UEditorToolbar>
|
|
476
|
+
</ol>
|
|
477
|
+
</nav>
|
|
472
478
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
479
|
+
<UEditor
|
|
480
|
+
ref="editorRef"
|
|
481
|
+
v-slot="{ editor }"
|
|
482
|
+
v-model="model"
|
|
483
|
+
:class="{ 'prose-variant': variant === 'prose' }"
|
|
484
|
+
:content-type="contentType"
|
|
485
|
+
:editable="editable"
|
|
486
|
+
:extensions="extensions"
|
|
487
|
+
:starter-kit="{ undoRedo: false, codeBlock: false, document: false }"
|
|
488
|
+
:handlers="editorHandlers"
|
|
489
|
+
:placeholder="placeholder"
|
|
490
|
+
@update:model-value="emit('update', $event)"
|
|
491
|
+
>
|
|
492
|
+
<!-- Floating source-view toggle (opt-in via :show-source-toggle="true") -->
|
|
493
|
+
<UButton
|
|
494
|
+
v-if="showSourceToggle"
|
|
495
|
+
class="aeditor-source-toggle"
|
|
496
|
+
icon="i-lucide-code-xml"
|
|
497
|
+
size="xs"
|
|
498
|
+
variant="ghost"
|
|
499
|
+
color="neutral"
|
|
500
|
+
:title="'View XML source'"
|
|
501
|
+
@click="viewMode = 'source'"
|
|
478
502
|
/>
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
<UEditorEmojiMenu
|
|
503
|
+
<!-- Default slot: app can override entire editor content -->
|
|
504
|
+
<slot
|
|
482
505
|
:editor="editor"
|
|
483
|
-
:
|
|
484
|
-
|
|
506
|
+
:connected-users="connectedUsers"
|
|
507
|
+
:ready="ready"
|
|
508
|
+
>
|
|
509
|
+
<!-- ── Bubble toolbar (appears when text is selected) ─────────────── -->
|
|
510
|
+
<!-- 4 named slots are forwarded to consumers:
|
|
511
|
+
#link / #doc-link — defaulted to ALinkPopover / ADocLinkPopover
|
|
512
|
+
#create-child-doc / #send-to-chat — empty by default; app-defined -->
|
|
513
|
+
<UEditorToolbar
|
|
514
|
+
v-if="showToolbar"
|
|
515
|
+
:editor="editor"
|
|
516
|
+
:items="toolbarItems"
|
|
517
|
+
layout="bubble"
|
|
518
|
+
:should-show="({ view, state }) => view.hasFocus() && !state.selection.empty"
|
|
519
|
+
>
|
|
520
|
+
<template #link>
|
|
521
|
+
<slot
|
|
522
|
+
name="link"
|
|
523
|
+
:editor="editor"
|
|
524
|
+
>
|
|
525
|
+
<ALinkPopover :editor="editor" />
|
|
526
|
+
</slot>
|
|
527
|
+
</template>
|
|
528
|
+
<template #doc-link>
|
|
529
|
+
<slot
|
|
530
|
+
name="doc-link"
|
|
531
|
+
:editor="editor"
|
|
532
|
+
>
|
|
533
|
+
<ADocLinkPopover :editor="editor" />
|
|
534
|
+
</slot>
|
|
535
|
+
</template>
|
|
536
|
+
<template #create-child-doc>
|
|
537
|
+
<slot
|
|
538
|
+
name="create-child-doc"
|
|
539
|
+
:editor="editor"
|
|
540
|
+
/>
|
|
541
|
+
</template>
|
|
542
|
+
<template #send-to-chat>
|
|
543
|
+
<slot
|
|
544
|
+
name="send-to-chat"
|
|
545
|
+
:editor="editor"
|
|
546
|
+
/>
|
|
547
|
+
</template>
|
|
548
|
+
</UEditorToolbar>
|
|
485
549
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
550
|
+
<!-- ── Slash command menu ──────────────────────────────────────────── -->
|
|
551
|
+
<UEditorSuggestionMenu
|
|
552
|
+
v-if="showSuggestionMenu"
|
|
553
|
+
:editor="editor"
|
|
554
|
+
:items="suggestionItems"
|
|
555
|
+
/>
|
|
491
556
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
color="neutral"
|
|
503
|
-
variant="ghost"
|
|
504
|
-
size="sm"
|
|
505
|
-
:class="ui.handle()"
|
|
506
|
-
@click="(e) => onPlusClick(e, onClick)"
|
|
557
|
+
<!-- ── Emoji menu (`:` trigger) ───────────────────────────────────── -->
|
|
558
|
+
<UEditorEmojiMenu
|
|
559
|
+
:editor="editor"
|
|
560
|
+
:items="emojiItems"
|
|
561
|
+
/>
|
|
562
|
+
|
|
563
|
+
<!-- ── Mention menu (`@` trigger) — users + docs + plugin providers ── -->
|
|
564
|
+
<UEditorMentionMenu
|
|
565
|
+
:editor="editor"
|
|
566
|
+
:items="mentionItems"
|
|
507
567
|
/>
|
|
508
568
|
|
|
509
|
-
<!--
|
|
510
|
-
<
|
|
511
|
-
v-
|
|
512
|
-
|
|
513
|
-
:
|
|
514
|
-
|
|
515
|
-
:ui="{ content: 'w-48', label: 'text-xs' }"
|
|
516
|
-
@update:open="(v) => editor.chain().setMeta('lockDragHandle', v).run()"
|
|
569
|
+
<!-- ── Drag handle — plus button + grip dropdown ───────────────────── -->
|
|
570
|
+
<UEditorDragHandle
|
|
571
|
+
v-if="showDragHandle"
|
|
572
|
+
v-slot="{ ui, onClick }"
|
|
573
|
+
:editor="editor"
|
|
574
|
+
@node-change="dragHandle.onNodeChange"
|
|
517
575
|
>
|
|
576
|
+
<!-- Plus: insert block via slash menu -->
|
|
518
577
|
<UButton
|
|
578
|
+
icon="i-lucide-plus"
|
|
519
579
|
color="neutral"
|
|
520
580
|
variant="ghost"
|
|
521
|
-
:active-variant="'soft'"
|
|
522
581
|
size="sm"
|
|
523
|
-
icon="i-lucide-grip-vertical"
|
|
524
|
-
:active="open"
|
|
525
582
|
:class="ui.handle()"
|
|
583
|
+
@click="(e) => onPlusClick(e, onClick)"
|
|
526
584
|
/>
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
585
|
+
|
|
586
|
+
<!-- Grip: block context menu -->
|
|
587
|
+
<UDropdownMenu
|
|
588
|
+
v-slot="{ open }"
|
|
589
|
+
:modal="false"
|
|
590
|
+
:items="dragHandle.getItems(editor)"
|
|
591
|
+
:content="{ side: 'left' }"
|
|
592
|
+
:ui="{ content: 'w-48', label: 'text-xs' }"
|
|
593
|
+
@update:open="(v) => editor.chain().setMeta('lockDragHandle', v).run()"
|
|
594
|
+
>
|
|
595
|
+
<UButton
|
|
596
|
+
color="neutral"
|
|
597
|
+
variant="ghost"
|
|
598
|
+
:active-variant="'soft'"
|
|
599
|
+
size="sm"
|
|
600
|
+
icon="i-lucide-grip-vertical"
|
|
601
|
+
:active="open"
|
|
602
|
+
:class="ui.handle()"
|
|
603
|
+
/>
|
|
604
|
+
</UDropdownMenu>
|
|
605
|
+
</UEditorDragHandle>
|
|
606
|
+
</slot>
|
|
607
|
+
</UEditor>
|
|
608
|
+
</div>
|
|
531
609
|
|
|
532
610
|
<template #fallback>
|
|
533
611
|
<div
|
|
@@ -543,5 +621,5 @@ function onPlusClick(e, onClick) {
|
|
|
543
621
|
</template>
|
|
544
622
|
|
|
545
623
|
<style scoped>
|
|
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}
|
|
624
|
+
.aeditor-canvas{display:flex;flex-direction:column;min-height:0}.aeditor-breadcrumb{flex-shrink:0;padding:.75rem 1rem 0}@media (min-width:640px){.aeditor-breadcrumb{padding-left:1.5rem;padding-right:1.5rem}}.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}
|
|
547
625
|
</style>
|
|
@@ -35,12 +35,18 @@ type __VLS_Props = {
|
|
|
35
35
|
* Useful for inspecting CRDT state during development. Default: false.
|
|
36
36
|
*/
|
|
37
37
|
showSourceToggle?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Show the in-canvas ancestor breadcrumb above the document (matching
|
|
40
|
+
* cou-sh's DocRenderer). Only renders when the doc actually has ancestors,
|
|
41
|
+
* so root/space docs show nothing. Set false for embeds/previews.
|
|
42
|
+
*/
|
|
43
|
+
showBreadcrumb?: boolean;
|
|
38
44
|
};
|
|
39
45
|
type __VLS_ModelProps = {
|
|
40
46
|
modelValue?: any;
|
|
41
47
|
};
|
|
42
48
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
43
|
-
declare var
|
|
49
|
+
declare var __VLS_58: {
|
|
44
50
|
editor: any;
|
|
45
51
|
connectedUsers: {
|
|
46
52
|
name: string;
|
|
@@ -49,40 +55,40 @@ declare var __VLS_42: {
|
|
|
49
55
|
docId?: string | undefined;
|
|
50
56
|
}[];
|
|
51
57
|
ready: boolean;
|
|
52
|
-
},
|
|
58
|
+
}, __VLS_67: {
|
|
53
59
|
editor: any;
|
|
54
|
-
},
|
|
60
|
+
}, __VLS_75: {
|
|
55
61
|
editor: any;
|
|
56
|
-
},
|
|
62
|
+
}, __VLS_83: {
|
|
57
63
|
editor: any;
|
|
58
|
-
},
|
|
64
|
+
}, __VLS_86: {
|
|
59
65
|
editor: any;
|
|
60
66
|
};
|
|
61
67
|
type __VLS_Slots = {} & {
|
|
62
|
-
default?: (props: typeof
|
|
68
|
+
default?: (props: typeof __VLS_58) => any;
|
|
63
69
|
} & {
|
|
64
|
-
link?: (props: typeof
|
|
70
|
+
link?: (props: typeof __VLS_67) => any;
|
|
65
71
|
} & {
|
|
66
|
-
'doc-link'?: (props: typeof
|
|
72
|
+
'doc-link'?: (props: typeof __VLS_75) => any;
|
|
67
73
|
} & {
|
|
68
|
-
'create-child-doc'?: (props: typeof
|
|
74
|
+
'create-child-doc'?: (props: typeof __VLS_83) => any;
|
|
69
75
|
} & {
|
|
70
|
-
'send-to-chat'?: (props: typeof
|
|
76
|
+
'send-to-chat'?: (props: typeof __VLS_86) => any;
|
|
71
77
|
};
|
|
72
78
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
73
79
|
editor: import("vue").ComputedRef<any>;
|
|
74
80
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
75
81
|
rename: (label: string) => any;
|
|
82
|
+
ready: () => any;
|
|
76
83
|
update: (content: any) => any;
|
|
77
84
|
"update:modelValue": (value: any) => any;
|
|
78
85
|
updateMeta: (patch: Partial<DocPageMeta>) => any;
|
|
79
|
-
ready: () => any;
|
|
80
86
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
81
87
|
onRename?: ((label: string) => any) | undefined;
|
|
88
|
+
onReady?: (() => any) | undefined;
|
|
82
89
|
onUpdate?: ((content: any) => any) | undefined;
|
|
83
90
|
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
84
91
|
onUpdateMeta?: ((patch: Partial<DocPageMeta>) => any) | undefined;
|
|
85
|
-
onReady?: (() => any) | undefined;
|
|
86
92
|
}>, {
|
|
87
93
|
contentType: "json" | "html" | "markdown";
|
|
88
94
|
editable: boolean;
|
|
@@ -91,6 +97,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
91
97
|
showDragHandle: boolean;
|
|
92
98
|
variant: "doc" | "prose";
|
|
93
99
|
showSourceToggle: boolean;
|
|
100
|
+
showBreadcrumb: boolean;
|
|
94
101
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
95
102
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
96
103
|
declare const _default: typeof __VLS_export;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { DocEncryptionInfo } from '@abraca/dabra';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
docId: string;
|
|
4
|
+
/** Override any displayed string. */
|
|
5
|
+
labels?: Partial<typeof DEFAULTS>;
|
|
6
|
+
};
|
|
7
|
+
declare const DEFAULTS: {
|
|
8
|
+
noneTitle: string;
|
|
9
|
+
noneDesc: string;
|
|
10
|
+
cseTitle: string;
|
|
11
|
+
cseDesc: string;
|
|
12
|
+
e2eTitle: string;
|
|
13
|
+
e2eDesc: string;
|
|
14
|
+
cannotDowngrade: string;
|
|
15
|
+
loadFailed: string;
|
|
16
|
+
retry: string;
|
|
17
|
+
enableE2ETitle: string;
|
|
18
|
+
cannotBeUndone: string;
|
|
19
|
+
warningServerCantRead: string;
|
|
20
|
+
warningNoSearch: string;
|
|
21
|
+
warningNoOffline: string;
|
|
22
|
+
warningKeysRequired: string;
|
|
23
|
+
warningCannotUndo: string;
|
|
24
|
+
cancel: string;
|
|
25
|
+
enableE2E: string;
|
|
26
|
+
};
|
|
27
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
28
|
+
updated: (args_0: DocEncryptionInfo) => any;
|
|
29
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
30
|
+
onUpdated?: ((args_0: DocEncryptionInfo) => any) | undefined;
|
|
31
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
32
|
+
declare const _default: typeof __VLS_export;
|
|
33
|
+
export default _default;
|