@abraca/nuxt 2.11.0 → 2.14.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 +15 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +9 -0
- package/dist/runtime/components/ACodeEditor.vue +123 -22
- 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/ADocViewToggle.d.vue.ts +40 -0
- package/dist/runtime/components/ADocViewToggle.vue +234 -0
- package/dist/runtime/components/ADocViewToggle.vue.d.ts +40 -0
- package/dist/runtime/components/ADocumentTree.vue +66 -1
- package/dist/runtime/components/AEditor.d.vue.ts +17 -10
- package/dist/runtime/components/AEditor.vue +403 -167
- package/dist/runtime/components/AEditor.vue.d.ts +17 -10
- package/dist/runtime/components/ANodePanel.d.vue.ts +9 -1
- package/dist/runtime/components/ANodePanel.vue +553 -481
- package/dist/runtime/components/ANodePanel.vue.d.ts +9 -1
- 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/ADocSuggestMenu.d.vue.ts +7 -0
- package/dist/runtime/components/editor/ADocSuggestMenu.vue +68 -0
- package/dist/runtime/components/editor/ADocSuggestMenu.vue.d.ts +7 -0
- 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/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/AUserMenu.d.vue.ts +2 -2
- package/dist/runtime/components/shell/AUserMenu.vue.d.ts +2 -2
- 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/useDocLinkPick.d.ts +9 -8
- package/dist/runtime/composables/useDocLinkPick.js +7 -18
- package/dist/runtime/composables/useDocSuggest.d.ts +34 -0
- package/dist/runtime/composables/useDocSuggest.js +56 -0
- package/dist/runtime/composables/useNodeContextMenu.d.ts +4 -0
- package/dist/runtime/composables/useNodeContextMenu.js +18 -0
- package/dist/runtime/composables/useSettingsModal.d.ts +1 -1
- package/dist/runtime/extensions/doc-link-drop.js +2 -2
- package/dist/runtime/extensions/doc-suggest.d.ts +28 -0
- package/dist/runtime/extensions/doc-suggest.js +85 -0
- package/dist/runtime/locale.d.ts +8 -0
- package/dist/runtime/locale.js +9 -1
- package/dist/runtime/utils/chatContent.d.ts +20 -2
- package/dist/runtime/utils/chatContent.js +20 -1
- package/dist/runtime/utils/codeHighlightStyle.d.ts +15 -0
- package/dist/runtime/utils/codeHighlightStyle.js +34 -0
- package/dist/runtime/utils/docTypes.js +43 -0
- package/dist/runtime/utils/loadCodeMirror.d.ts +1 -0
- package/dist/runtime/utils/loadCodeMirror.js +6 -3
- package/dist/runtime/utils/titleSync.d.ts +130 -0
- package/dist/runtime/utils/titleSync.js +53 -0
- package/package.json +12 -1
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, computed, onBeforeUnmount } from "vue";
|
|
3
|
+
import { useAbracadabra } from "../composables/useAbracadabra";
|
|
4
|
+
import { useSyncedMap } from "../composables/useYDoc";
|
|
5
|
+
import { useAbraLocale } from "../composables/useAbraLocale";
|
|
6
|
+
import { resolveDocType, getAvailableDocTypes } from "../utils/docTypes";
|
|
7
|
+
const props = defineProps({
|
|
8
|
+
modelValue: { type: [String, null], required: false, default: null },
|
|
9
|
+
docId: { type: String, required: true },
|
|
10
|
+
docType: { type: String, required: false },
|
|
11
|
+
chatUnread: { type: Number, required: false, default: 0 },
|
|
12
|
+
editorDisabled: { type: Boolean, required: false, default: false },
|
|
13
|
+
pageTypeDisabled: { type: Boolean, required: false, default: false },
|
|
14
|
+
canChangeType: { type: Boolean, required: false, default: true },
|
|
15
|
+
showChat: { type: Boolean, required: false, default: true },
|
|
16
|
+
showSettings: { type: Boolean, required: false, default: true },
|
|
17
|
+
disableTooltips: { type: Boolean, required: false, default: false },
|
|
18
|
+
size: { type: String, required: false, default: "md" }
|
|
19
|
+
});
|
|
20
|
+
const emit = defineEmits(["update:modelValue", "select"]);
|
|
21
|
+
const locale = computed(() => useAbraLocale("nodePanel"));
|
|
22
|
+
const { doc, registry } = useAbracadabra();
|
|
23
|
+
const treeMap = useSyncedMap(doc, "doc-tree");
|
|
24
|
+
const docTypeDef = computed(() => resolveDocType(props.docType, registry));
|
|
25
|
+
const hasPageType = computed(() => !!(props.docType && props.docType !== "doc"));
|
|
26
|
+
const docTypeItems = computed(
|
|
27
|
+
() => getAvailableDocTypes(registry).filter((dt) => dt.key !== props.docType).map((dt) => ({
|
|
28
|
+
label: dt.label,
|
|
29
|
+
icon: dt.icon,
|
|
30
|
+
onSelect() {
|
|
31
|
+
const entry = treeMap.get(props.docId);
|
|
32
|
+
if (!entry) return;
|
|
33
|
+
if (entry.type === dt.key) return;
|
|
34
|
+
treeMap.set(props.docId, { ...entry, type: dt.key, updatedAt: Date.now() });
|
|
35
|
+
}
|
|
36
|
+
}))
|
|
37
|
+
);
|
|
38
|
+
const visibleTabs = computed(() => {
|
|
39
|
+
const t = ["pageType", "editor"];
|
|
40
|
+
if (props.showChat) t.push("chat");
|
|
41
|
+
if (props.showSettings) t.push("settings");
|
|
42
|
+
return t;
|
|
43
|
+
});
|
|
44
|
+
function select(tab) {
|
|
45
|
+
emit("update:modelValue", tab);
|
|
46
|
+
emit("select", tab);
|
|
47
|
+
}
|
|
48
|
+
const typeMenuOpen = ref(false);
|
|
49
|
+
let pressTimer = null;
|
|
50
|
+
let longFired = false;
|
|
51
|
+
function onTypePointerDown() {
|
|
52
|
+
longFired = false;
|
|
53
|
+
cancelTypePress();
|
|
54
|
+
pressTimer = setTimeout(() => {
|
|
55
|
+
longFired = true;
|
|
56
|
+
typeMenuOpen.value = true;
|
|
57
|
+
}, 400);
|
|
58
|
+
}
|
|
59
|
+
function cancelTypePress() {
|
|
60
|
+
if (pressTimer) {
|
|
61
|
+
clearTimeout(pressTimer);
|
|
62
|
+
pressTimer = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function onTypeClick() {
|
|
66
|
+
cancelTypePress();
|
|
67
|
+
if (longFired) {
|
|
68
|
+
longFired = false;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
select("pageType");
|
|
72
|
+
}
|
|
73
|
+
onBeforeUnmount(cancelTypePress);
|
|
74
|
+
const activeIndex = computed(() => {
|
|
75
|
+
const v = props.modelValue;
|
|
76
|
+
if (!v) return -1;
|
|
77
|
+
if (v === "pageType" && !hasPageType.value) return -1;
|
|
78
|
+
return visibleTabs.value.indexOf(v);
|
|
79
|
+
});
|
|
80
|
+
const indicatorVisible = computed(() => activeIndex.value >= 0);
|
|
81
|
+
const segPx = computed(() => props.size === "sm" ? 24 : 28);
|
|
82
|
+
const iconClass = computed(() => props.size === "sm" ? "size-3" : "size-3.5");
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<template>
|
|
86
|
+
<div
|
|
87
|
+
class="dvt"
|
|
88
|
+
:class="`dvt-${size}`"
|
|
89
|
+
:style="{ '--dvt-seg': segPx + 'px' }"
|
|
90
|
+
>
|
|
91
|
+
<!-- Sliding active pill — like Nuxt UI tabs. Equal-width segments make the
|
|
92
|
+
offset a simple multiple of the segment size, no DOM measuring. -->
|
|
93
|
+
<span
|
|
94
|
+
class="dvt-indicator"
|
|
95
|
+
:class="{ 'dvt-indicator-hidden': !indicatorVisible }"
|
|
96
|
+
:style="{ transform: `translateX(${Math.max(activeIndex, 0) * 100}%)` }"
|
|
97
|
+
aria-hidden="true"
|
|
98
|
+
/>
|
|
99
|
+
|
|
100
|
+
<!-- Slot 1: page type (selectable tab) or + (assign-type dropdown) -->
|
|
101
|
+
<UDropdownMenu
|
|
102
|
+
v-if="!hasPageType"
|
|
103
|
+
:items="[docTypeItems]"
|
|
104
|
+
:disabled="!canChangeType"
|
|
105
|
+
>
|
|
106
|
+
<UTooltip
|
|
107
|
+
:text="locale.docType"
|
|
108
|
+
:content="{ side: 'bottom' }"
|
|
109
|
+
:disabled="disableTooltips"
|
|
110
|
+
>
|
|
111
|
+
<button
|
|
112
|
+
type="button"
|
|
113
|
+
class="dvt-seg"
|
|
114
|
+
:disabled="!canChangeType"
|
|
115
|
+
>
|
|
116
|
+
<UIcon
|
|
117
|
+
name="i-lucide-plus"
|
|
118
|
+
:class="iconClass"
|
|
119
|
+
/>
|
|
120
|
+
</button>
|
|
121
|
+
</UTooltip>
|
|
122
|
+
</UDropdownMenu>
|
|
123
|
+
<div
|
|
124
|
+
v-else
|
|
125
|
+
class="dvt-seg-host"
|
|
126
|
+
>
|
|
127
|
+
<UTooltip
|
|
128
|
+
:text="docTypeDef.label"
|
|
129
|
+
:content="{ side: 'bottom' }"
|
|
130
|
+
:disabled="disableTooltips || typeMenuOpen"
|
|
131
|
+
>
|
|
132
|
+
<button
|
|
133
|
+
type="button"
|
|
134
|
+
class="dvt-seg"
|
|
135
|
+
:class="{ active: modelValue === 'pageType' }"
|
|
136
|
+
:disabled="pageTypeDisabled"
|
|
137
|
+
@pointerdown="onTypePointerDown"
|
|
138
|
+
@pointerup="onTypeClick"
|
|
139
|
+
@pointerleave="cancelTypePress"
|
|
140
|
+
@pointercancel="cancelTypePress"
|
|
141
|
+
@contextmenu.prevent="canChangeType && (typeMenuOpen = true)"
|
|
142
|
+
>
|
|
143
|
+
<UIcon
|
|
144
|
+
:name="docTypeDef.icon"
|
|
145
|
+
:class="iconClass"
|
|
146
|
+
/>
|
|
147
|
+
</button>
|
|
148
|
+
</UTooltip>
|
|
149
|
+
<!-- Hidden anchor: the menu is opened programmatically by long-press so
|
|
150
|
+
the trigger never steals the click. -->
|
|
151
|
+
<UDropdownMenu
|
|
152
|
+
v-if="canChangeType"
|
|
153
|
+
v-model:open="typeMenuOpen"
|
|
154
|
+
:items="[docTypeItems]"
|
|
155
|
+
:content="{ side: 'bottom', align: 'center' }"
|
|
156
|
+
>
|
|
157
|
+
<span
|
|
158
|
+
class="dvt-anchor"
|
|
159
|
+
aria-hidden="true"
|
|
160
|
+
/>
|
|
161
|
+
</UDropdownMenu>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
<!-- Slot 2: editor -->
|
|
165
|
+
<UTooltip
|
|
166
|
+
:text="locale.editorTab"
|
|
167
|
+
:content="{ side: 'bottom' }"
|
|
168
|
+
:disabled="disableTooltips"
|
|
169
|
+
>
|
|
170
|
+
<button
|
|
171
|
+
type="button"
|
|
172
|
+
class="dvt-seg"
|
|
173
|
+
:class="{ active: modelValue === 'editor' }"
|
|
174
|
+
:disabled="editorDisabled"
|
|
175
|
+
@click="select('editor')"
|
|
176
|
+
>
|
|
177
|
+
<UIcon
|
|
178
|
+
name="i-lucide-text-cursor"
|
|
179
|
+
:class="iconClass"
|
|
180
|
+
/>
|
|
181
|
+
</button>
|
|
182
|
+
</UTooltip>
|
|
183
|
+
|
|
184
|
+
<!-- Slot 3: chat (with unread badge) -->
|
|
185
|
+
<UTooltip
|
|
186
|
+
v-if="showChat"
|
|
187
|
+
:text="locale.chatTab"
|
|
188
|
+
:content="{ side: 'bottom' }"
|
|
189
|
+
:disabled="disableTooltips"
|
|
190
|
+
>
|
|
191
|
+
<button
|
|
192
|
+
type="button"
|
|
193
|
+
class="dvt-seg"
|
|
194
|
+
:class="{ active: modelValue === 'chat' }"
|
|
195
|
+
@click="select('chat')"
|
|
196
|
+
>
|
|
197
|
+
<span class="relative inline-flex">
|
|
198
|
+
<UIcon
|
|
199
|
+
name="i-lucide-message-circle"
|
|
200
|
+
:class="iconClass"
|
|
201
|
+
/>
|
|
202
|
+
<span
|
|
203
|
+
v-if="chatUnread > 0 && modelValue !== 'chat'"
|
|
204
|
+
class="dvt-badge"
|
|
205
|
+
>{{ chatUnread > 99 ? "99+" : chatUnread }}</span>
|
|
206
|
+
</span>
|
|
207
|
+
</button>
|
|
208
|
+
</UTooltip>
|
|
209
|
+
|
|
210
|
+
<!-- Slot 4: settings -->
|
|
211
|
+
<UTooltip
|
|
212
|
+
v-if="showSettings"
|
|
213
|
+
:text="locale.settingsTab"
|
|
214
|
+
:content="{ side: 'bottom' }"
|
|
215
|
+
:disabled="disableTooltips"
|
|
216
|
+
>
|
|
217
|
+
<button
|
|
218
|
+
type="button"
|
|
219
|
+
class="dvt-seg"
|
|
220
|
+
:class="{ active: modelValue === 'settings' }"
|
|
221
|
+
@click="select('settings')"
|
|
222
|
+
>
|
|
223
|
+
<UIcon
|
|
224
|
+
name="i-lucide-settings-2"
|
|
225
|
+
:class="iconClass"
|
|
226
|
+
/>
|
|
227
|
+
</button>
|
|
228
|
+
</UTooltip>
|
|
229
|
+
</div>
|
|
230
|
+
</template>
|
|
231
|
+
|
|
232
|
+
<style scoped>
|
|
233
|
+
.dvt{align-items:center;background:var(--ui-bg-elevated);border-radius:calc(var(--ui-radius)*1.5);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ui-border-accented),#fff 25%);display:inline-flex;flex-shrink:0;padding:2px;position:relative}.dvt-indicator{background:var(--ui-bg);border-radius:var(--ui-radius);box-shadow:0 1px 2px rgba(0,0,0,.08),inset 0 0 0 1px var(--ui-border-accented);height:calc(100% - 4px);left:2px;pointer-events:none;position:absolute;top:2px;transition:transform .25s cubic-bezier(.4,0,.2,1),opacity .15s ease;width:var(--dvt-seg)}.dvt-indicator-hidden{opacity:0}.dvt-seg-host{display:flex;position:relative}.dvt-anchor{bottom:0;height:0;left:50%;position:absolute;width:0}.dvt-seg{align-items:center;border-radius:var(--ui-radius);color:var(--ui-text-muted);cursor:pointer;display:flex;height:var(--dvt-seg);justify-content:center;position:relative;transition:color .15s ease;width:var(--dvt-seg);z-index:1}.dvt-seg:hover:not(:disabled){color:var(--ui-text)}.dvt-seg.active{color:var(--ui-text-highlighted)}.dvt-seg:disabled{cursor:default;opacity:.4}.dvt-badge{background:var(--ui-color-error-500);border-radius:999px;color:#fff;font-size:9px;font-weight:700;height:15px;line-height:15px;min-width:15px;padding:0 3px;pointer-events:none;position:absolute;right:-7px;text-align:center;top:-6px}
|
|
234
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type DocViewTab = 'pageType' | 'editor' | 'chat' | 'settings';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
/** Active tab. `null` (or absent) = nothing highlighted (e.g. another tab is active). */
|
|
4
|
+
modelValue?: DocViewTab | null;
|
|
5
|
+
docId: string;
|
|
6
|
+
docType?: string;
|
|
7
|
+
chatUnread?: number;
|
|
8
|
+
/** Disable the editor segment (e.g. main view is already the editor). */
|
|
9
|
+
editorDisabled?: boolean;
|
|
10
|
+
/** Disable the page-type segment (e.g. provider not ready). */
|
|
11
|
+
pageTypeDisabled?: boolean;
|
|
12
|
+
/** Whether the user may assign/change the page type (gates the + dropdown). */
|
|
13
|
+
canChangeType?: boolean;
|
|
14
|
+
/** Render the chat slot. Off → omitted (e.g. features.chat disabled). */
|
|
15
|
+
showChat?: boolean;
|
|
16
|
+
/** Render the settings slot. Off → omitted. */
|
|
17
|
+
showSettings?: boolean;
|
|
18
|
+
/** Suppress tooltips (touch devices / during open animations). */
|
|
19
|
+
disableTooltips?: boolean;
|
|
20
|
+
size?: 'sm' | 'md';
|
|
21
|
+
};
|
|
22
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
23
|
+
select: (tab: DocViewTab) => any;
|
|
24
|
+
"update:modelValue": (tab: DocViewTab) => any;
|
|
25
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
26
|
+
onSelect?: ((tab: DocViewTab) => any) | undefined;
|
|
27
|
+
"onUpdate:modelValue"?: ((tab: DocViewTab) => any) | undefined;
|
|
28
|
+
}>, {
|
|
29
|
+
size: "sm" | "md";
|
|
30
|
+
modelValue: DocViewTab | null;
|
|
31
|
+
chatUnread: number;
|
|
32
|
+
editorDisabled: boolean;
|
|
33
|
+
pageTypeDisabled: boolean;
|
|
34
|
+
canChangeType: boolean;
|
|
35
|
+
showChat: boolean;
|
|
36
|
+
showSettings: boolean;
|
|
37
|
+
disableTooltips: boolean;
|
|
38
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
39
|
+
declare const _default: typeof __VLS_export;
|
|
40
|
+
export default _default;
|
|
@@ -298,6 +298,45 @@ function deleteDoc(docId) {
|
|
|
298
298
|
if (!docId || !isReady.value) return;
|
|
299
299
|
moveToTrash(docId, userName.value);
|
|
300
300
|
}
|
|
301
|
+
const moveTargetId = ref(null);
|
|
302
|
+
const movePickerOpen = ref(false);
|
|
303
|
+
function openMovePicker(docId) {
|
|
304
|
+
moveTargetId.value = docId;
|
|
305
|
+
movePickerOpen.value = true;
|
|
306
|
+
}
|
|
307
|
+
function performMove(newParentId) {
|
|
308
|
+
const id = moveTargetId.value;
|
|
309
|
+
if (!id || !isReady.value) return;
|
|
310
|
+
const entry = treeMap.data[id];
|
|
311
|
+
if (!entry) return;
|
|
312
|
+
if ((entry.parentId ?? null) === newParentId) return;
|
|
313
|
+
treeMap.set(id, { ...entry, parentId: newParentId, order: Date.now() });
|
|
314
|
+
if (newParentId) {
|
|
315
|
+
client.value?.createChild(newParentId, { child_id: id, kind: "page" }).catch(() => {
|
|
316
|
+
});
|
|
317
|
+
expandedIds.value.add(newParentId);
|
|
318
|
+
expandedIds.value = new Set(expandedIds.value);
|
|
319
|
+
}
|
|
320
|
+
emit("navigate", id);
|
|
321
|
+
}
|
|
322
|
+
const tagsTargetId = ref(null);
|
|
323
|
+
const tagsEditorOpen = ref(false);
|
|
324
|
+
function openTagsEditor(docId) {
|
|
325
|
+
tagsTargetId.value = docId;
|
|
326
|
+
tagsEditorOpen.value = true;
|
|
327
|
+
}
|
|
328
|
+
const tagsTargetTags = computed(() => {
|
|
329
|
+
const id = tagsTargetId.value;
|
|
330
|
+
if (!id) return [];
|
|
331
|
+
return treeMap.data[id]?.meta?.tags ?? [];
|
|
332
|
+
});
|
|
333
|
+
function saveTags(tags) {
|
|
334
|
+
const id = tagsTargetId.value;
|
|
335
|
+
if (!id || !isReady.value) return;
|
|
336
|
+
const entry = treeMap.data[id];
|
|
337
|
+
if (!entry) return;
|
|
338
|
+
treeMap.set(id, { ...entry, meta: { ...entry.meta ?? {}, tags } });
|
|
339
|
+
}
|
|
301
340
|
const renameId = ref(null);
|
|
302
341
|
const renameValue = ref("");
|
|
303
342
|
const renameInputRef = ref(null);
|
|
@@ -385,7 +424,7 @@ function onDragStart(e, item) {
|
|
|
385
424
|
if (!multiSelected.value.has(item.id)) multiSelected.value = /* @__PURE__ */ new Set();
|
|
386
425
|
dragId.value = item.id;
|
|
387
426
|
if (e.dataTransfer) {
|
|
388
|
-
e.dataTransfer.effectAllowed = "
|
|
427
|
+
e.dataTransfer.effectAllowed = "all";
|
|
389
428
|
e.dataTransfer.setData("text/plain", item.id);
|
|
390
429
|
e.dataTransfer.setData(DOC_DRAG_MIME, JSON.stringify({ id: item.id, label: item.name }));
|
|
391
430
|
}
|
|
@@ -770,6 +809,16 @@ function treeNodeMenuItems(item) {
|
|
|
770
809
|
label: "Add child page",
|
|
771
810
|
icon: "i-lucide-file-plus",
|
|
772
811
|
onSelect: () => createDirectly(item.id)
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
label: "Move to\u2026",
|
|
815
|
+
icon: "i-lucide-corner-down-right",
|
|
816
|
+
onSelect: () => openMovePicker(item.id)
|
|
817
|
+
},
|
|
818
|
+
{
|
|
819
|
+
label: "Edit tags\u2026",
|
|
820
|
+
icon: "i-lucide-tags",
|
|
821
|
+
onSelect: () => openTagsEditor(item.id)
|
|
773
822
|
}
|
|
774
823
|
],
|
|
775
824
|
[
|
|
@@ -1517,6 +1566,22 @@ defineExpose({
|
|
|
1517
1566
|
@close="closeOverlay"
|
|
1518
1567
|
/>
|
|
1519
1568
|
</div>
|
|
1569
|
+
|
|
1570
|
+
<!-- Move-to reparent picker -->
|
|
1571
|
+
<ADocPickerModal
|
|
1572
|
+
v-model:open="movePickerOpen"
|
|
1573
|
+
:exclude-id="moveTargetId"
|
|
1574
|
+
title="Move to…"
|
|
1575
|
+
confirm-label="Move here"
|
|
1576
|
+
@select="performMove"
|
|
1577
|
+
/>
|
|
1578
|
+
|
|
1579
|
+
<!-- Edit-tags editor -->
|
|
1580
|
+
<ATagsEditor
|
|
1581
|
+
v-model:open="tagsEditorOpen"
|
|
1582
|
+
:tags="tagsTargetTags"
|
|
1583
|
+
@save="saveTags"
|
|
1584
|
+
/>
|
|
1520
1585
|
</template>
|
|
1521
1586
|
|
|
1522
1587
|
<style scoped>
|
|
@@ -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,25 +55,25 @@ 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>;
|
|
@@ -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;
|