@abraca/nuxt 2.0.0 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/module.d.mts +18 -7
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +21 -5
  4. package/dist/runtime/assets/aware-tokens.css +1 -0
  5. package/dist/runtime/components/AAccountSwitcherModal.d.vue.ts +16 -1
  6. package/dist/runtime/components/AAccountSwitcherModal.vue +33 -4
  7. package/dist/runtime/components/AAccountSwitcherModal.vue.d.ts +16 -1
  8. package/dist/runtime/components/AAuthLinkLanding.d.vue.ts +3 -0
  9. package/dist/runtime/components/AAuthLinkLanding.vue +85 -0
  10. package/dist/runtime/components/AAuthLinkLanding.vue.d.ts +3 -0
  11. package/dist/runtime/components/AClaimAccountModal.d.vue.ts +7 -1
  12. package/dist/runtime/components/AClaimAccountModal.vue +28 -13
  13. package/dist/runtime/components/AClaimAccountModal.vue.d.ts +7 -1
  14. package/dist/runtime/components/AEditor.vue +5 -0
  15. package/dist/runtime/components/AEmailVerifyConfirmModal.d.vue.ts +30 -0
  16. package/dist/runtime/components/AEmailVerifyConfirmModal.vue +100 -0
  17. package/dist/runtime/components/AEmailVerifyConfirmModal.vue.d.ts +30 -0
  18. package/dist/runtime/components/AEmailVerifyRequestCard.d.vue.ts +22 -0
  19. package/dist/runtime/components/AEmailVerifyRequestCard.vue +65 -0
  20. package/dist/runtime/components/AEmailVerifyRequestCard.vue.d.ts +22 -0
  21. package/dist/runtime/components/AMnemonicLoginModal.d.vue.ts +1 -1
  22. package/dist/runtime/components/AMnemonicLoginModal.vue.d.ts +1 -1
  23. package/dist/runtime/components/ANodePanel.vue +2 -0
  24. package/dist/runtime/components/ANotificationBell.d.vue.ts +2 -2
  25. package/dist/runtime/components/ANotificationBell.vue.d.ts +2 -2
  26. package/dist/runtime/components/APasswordChangeModal.d.vue.ts +28 -0
  27. package/dist/runtime/components/APasswordChangeModal.vue +178 -0
  28. package/dist/runtime/components/APasswordChangeModal.vue.d.ts +28 -0
  29. package/dist/runtime/components/APasswordLoginModal.d.vue.ts +42 -0
  30. package/dist/runtime/components/APasswordLoginModal.vue +177 -0
  31. package/dist/runtime/components/APasswordLoginModal.vue.d.ts +42 -0
  32. package/dist/runtime/components/APasswordRegisterModal.d.vue.ts +49 -0
  33. package/dist/runtime/components/APasswordRegisterModal.vue +262 -0
  34. package/dist/runtime/components/APasswordRegisterModal.vue.d.ts +49 -0
  35. package/dist/runtime/components/APasswordResetConfirmModal.d.vue.ts +31 -0
  36. package/dist/runtime/components/APasswordResetConfirmModal.vue +154 -0
  37. package/dist/runtime/components/APasswordResetConfirmModal.vue.d.ts +31 -0
  38. package/dist/runtime/components/APasswordResetRequestModal.d.vue.ts +35 -0
  39. package/dist/runtime/components/APasswordResetRequestModal.vue +113 -0
  40. package/dist/runtime/components/APasswordResetRequestModal.vue.d.ts +35 -0
  41. package/dist/runtime/components/ASetPasswordCard.d.vue.ts +26 -0
  42. package/dist/runtime/components/ASetPasswordCard.vue +139 -0
  43. package/dist/runtime/components/ASetPasswordCard.vue.d.ts +26 -0
  44. package/dist/runtime/components/ASubPageList.d.vue.ts +66 -0
  45. package/dist/runtime/components/ASubPageList.vue +147 -0
  46. package/dist/runtime/components/ASubPageList.vue.d.ts +66 -0
  47. package/dist/runtime/components/aware/AAccordion.d.vue.ts +2 -0
  48. package/dist/runtime/components/aware/AAccordion.vue +11 -1
  49. package/dist/runtime/components/aware/AAccordion.vue.d.ts +2 -0
  50. package/dist/runtime/components/aware/AButton.vue +3 -3
  51. package/dist/runtime/components/aware/ACollapsible.d.vue.ts +2 -0
  52. package/dist/runtime/components/aware/ACollapsible.vue +9 -1
  53. package/dist/runtime/components/aware/ACollapsible.vue.d.ts +2 -0
  54. package/dist/runtime/components/aware/AGlobalFocusLayer.vue +1 -1
  55. package/dist/runtime/components/aware/AHoverItem.vue +28 -3
  56. package/dist/runtime/components/aware/AMedia.d.vue.ts +1 -1
  57. package/dist/runtime/components/aware/AMedia.vue.d.ts +1 -1
  58. package/dist/runtime/components/aware/AModal.d.vue.ts +2 -0
  59. package/dist/runtime/components/aware/AModal.vue +9 -1
  60. package/dist/runtime/components/aware/AModal.vue.d.ts +2 -0
  61. package/dist/runtime/components/aware/APresenceBlobs.vue +1 -1
  62. package/dist/runtime/components/aware/APresenceCursors.vue +1 -1
  63. package/dist/runtime/components/aware/AScroll.d.vue.ts +2 -0
  64. package/dist/runtime/components/aware/AScroll.vue +13 -3
  65. package/dist/runtime/components/aware/AScroll.vue.d.ts +2 -0
  66. package/dist/runtime/components/aware/ASlideover.d.vue.ts +2 -0
  67. package/dist/runtime/components/aware/ASlideover.vue +9 -1
  68. package/dist/runtime/components/aware/ASlideover.vue.d.ts +2 -0
  69. package/dist/runtime/components/aware/ASlider.vue +1 -0
  70. package/dist/runtime/components/aware/ATabs.d.vue.ts +2 -0
  71. package/dist/runtime/components/aware/ATabs.vue +9 -1
  72. package/dist/runtime/components/aware/ATabs.vue.d.ts +2 -0
  73. package/dist/runtime/components/chat/ANodeChatPanel.vue +1 -0
  74. package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +2 -2
  75. package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +2 -2
  76. package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +2 -2
  77. package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +2 -2
  78. package/dist/runtime/components/renderers/calendar/ACalendarToolbar.d.vue.ts +4 -4
  79. package/dist/runtime/components/renderers/calendar/ACalendarToolbar.vue.d.ts +4 -4
  80. package/dist/runtime/components/renderers/media/MediaTransportBar.d.vue.ts +2 -2
  81. package/dist/runtime/components/renderers/media/MediaTransportBar.vue.d.ts +2 -2
  82. package/dist/runtime/components/shell/AUserProfilePopover.d.vue.ts +1 -1
  83. package/dist/runtime/components/shell/AUserProfilePopover.vue.d.ts +1 -1
  84. package/dist/runtime/composables/useAAField.js +7 -4
  85. package/dist/runtime/composables/useAAFocus.js +10 -5
  86. package/dist/runtime/composables/useAAFollowAnchor.js +68 -34
  87. package/dist/runtime/composables/useAAFollowPeer.d.ts +7 -4
  88. package/dist/runtime/composables/useAAFollowPeer.js +60 -11
  89. package/dist/runtime/composables/useAAViewport.d.ts +1 -1
  90. package/dist/runtime/composables/useAbracadabraAuth.d.ts +2 -0
  91. package/dist/runtime/composables/useAbracadabraAuth.js +2 -0
  92. package/dist/runtime/composables/useEditorSuggestions.js +2 -1
  93. package/dist/runtime/composables/useEmailVerification.d.ts +40 -26
  94. package/dist/runtime/composables/useEmailVerification.js +95 -43
  95. package/dist/runtime/composables/usePasswordAuth.d.ts +64 -0
  96. package/dist/runtime/composables/usePasswordAuth.js +126 -0
  97. package/dist/runtime/composables/useTiptapHistory.d.ts +2 -2
  98. package/dist/runtime/composables/useTiptapHistory.js +5 -5
  99. package/dist/runtime/extensions/svg-embed.d.ts +23 -0
  100. package/dist/runtime/extensions/svg-embed.js +33 -0
  101. package/dist/runtime/extensions/views/MetaFieldView.vue +23 -6
  102. package/dist/runtime/extensions/views/SvgEmbedView.d.vue.ts +4 -0
  103. package/dist/runtime/extensions/views/SvgEmbedView.vue +120 -0
  104. package/dist/runtime/extensions/views/SvgEmbedView.vue.d.ts +4 -0
  105. package/dist/runtime/plugin-abracadabra.client.js +58 -9
  106. package/dist/runtime/plugin-abracadabra.server.js +2 -0
  107. package/dist/runtime/plugins/core.plugin.js +8 -4
  108. package/dist/runtime/server/plugins/abracadabra-service.js +102 -13
  109. package/dist/runtime/types.d.ts +11 -0
  110. package/dist/runtime/utils/awareRingStyle.js +1 -1
  111. package/dist/runtime/utils/sanitizeSvg.d.ts +19 -0
  112. package/dist/runtime/utils/sanitizeSvg.js +87 -0
  113. package/package.json +7 -8
  114. package/dist/runtime/components/renderers/ASpatialRenderer.d.vue.ts +0 -19
  115. package/dist/runtime/components/renderers/ASpatialRenderer.vue +0 -459
  116. package/dist/runtime/components/renderers/ASpatialRenderer.vue.d.ts +0 -19
  117. package/dist/runtime/components/renderers/spatial/SpatialGround.d.vue.ts +0 -20
  118. package/dist/runtime/components/renderers/spatial/SpatialGround.vue +0 -26
  119. package/dist/runtime/components/renderers/spatial/SpatialGround.vue.d.ts +0 -20
  120. package/dist/runtime/components/renderers/spatial/SpatialObject.d.vue.ts +0 -17
  121. package/dist/runtime/components/renderers/spatial/SpatialObject.vue +0 -257
  122. package/dist/runtime/components/renderers/spatial/SpatialObject.vue.d.ts +0 -17
  123. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.d.vue.ts +0 -15
  124. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue +0 -18
  125. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue.d.ts +0 -15
  126. package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.d.vue.ts +0 -16
  127. package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.vue +0 -66
  128. package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.vue.d.ts +0 -16
  129. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.d.vue.ts +0 -8
  130. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue +0 -53
  131. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue.d.ts +0 -8
  132. package/dist/runtime/composables/useSpatialCamera.d.ts +0 -16
  133. package/dist/runtime/composables/useSpatialCamera.js +0 -175
  134. package/dist/runtime/composables/useSpatialDrag.d.ts +0 -14
  135. package/dist/runtime/composables/useSpatialDrag.js +0 -137
@@ -1,459 +0,0 @@
1
- <script setup>
2
- import { ref, computed, watch, onMounted, onBeforeUnmount } from "vue";
3
- import { useRuntimeConfig } from "#imports";
4
- import { useRendererBase } from "../../composables/useRendererBase";
5
- import { useNodePanel } from "../../composables/useNodePanel";
6
- import { useSpatialCamera } from "../../composables/useSpatialCamera";
7
- import { useSpatialDrag } from "../../composables/useSpatialDrag";
8
- import SpatialTransformInputs from "./spatial/SpatialTransformInputs.vue";
9
- const props = defineProps({
10
- docId: { type: String, required: true },
11
- childProvider: { type: null, required: true },
12
- docLabel: { type: String, required: true },
13
- pageTypes: { type: Array, required: false },
14
- labels: { type: Object, required: false },
15
- editable: { type: Boolean, required: false, default: true }
16
- });
17
- const config = useRuntimeConfig();
18
- const _locale = config.public;
19
- const { tree, childProviderRef, states, setLocalState, connectedUsers } = useRendererBase(props);
20
- const {
21
- openNodeId,
22
- openNodeLabel,
23
- openNodeProvider,
24
- openNode,
25
- closePanel
26
- } = useNodePanel(childProviderRef);
27
- const gridVisible = ref(true);
28
- function toggleGrid() {
29
- gridVisible.value = !gridVisible.value;
30
- }
31
- const {
32
- cameraRef,
33
- cameraPosition,
34
- cameraTarget,
35
- controlMode,
36
- focusOn,
37
- onCanvasPointerDown: camPointerDown,
38
- onCanvasPointerMove: camPointerMove,
39
- onCanvasPointerUp: camPointerUp,
40
- onCanvasWheel
41
- } = useSpatialCamera(setLocalState);
42
- const selectedIds = ref(/* @__PURE__ */ new Set());
43
- const selectedEntry = computed(() => {
44
- if (selectedIds.value.size !== 1) return null;
45
- const id = [...selectedIds.value][0];
46
- return tree.entries.value.find((e) => e.id === id) ?? null;
47
- });
48
- watch(selectedIds, (ids) => {
49
- setLocalState({ spatial: { selectedIds: [...ids] } });
50
- }, { deep: true });
51
- const sceneSettings = { data: {} };
52
- const {
53
- draggingId,
54
- bindScene,
55
- onPointerDown: dragPointerDown,
56
- onPointerMove: dragPointerMove,
57
- onPointerUp: dragPointerUp
58
- } = useSpatialDrag(tree, selectedIds, cameraRef, setLocalState, sceneSettings);
59
- const topLevelEntries = computed(() => tree.childrenOf(null));
60
- const myClientId = computed(() => props.childProvider?.awareness?.clientID ?? 0);
61
- const remoteUsers3D = computed(
62
- () => states.value.filter((s) => s.clientId !== myClientId.value && s.spatial?.camera).map((s) => ({
63
- clientId: s.clientId,
64
- name: s.user?.name ?? "?",
65
- color: s.user?.color ?? "#888",
66
- position: s.spatial.camera.position,
67
- selectedIds: s.spatial?.selectedIds ?? []
68
- }))
69
- );
70
- const remoteSelectionMap = computed(() => {
71
- const map = /* @__PURE__ */ new Map();
72
- for (const u of remoteUsers3D.value) {
73
- for (const id of u.selectedIds) {
74
- if (!map.has(id)) map.set(id, []);
75
- map.get(id).push({ color: u.color, name: u.name });
76
- }
77
- }
78
- return map;
79
- });
80
- const shapes = ["box", "sphere", "cylinder", "cone", "plane", "torus"];
81
- const shapeIcons = {
82
- box: "i-lucide-box",
83
- sphere: "i-lucide-circle",
84
- cylinder: "i-lucide-cylinder",
85
- cone: "i-lucide-triangle",
86
- plane: "i-lucide-square",
87
- torus: "i-lucide-donut",
88
- glb: "i-lucide-package"
89
- };
90
- function addObject(shape = "box") {
91
- if (!props.editable) return;
92
- const label = shape.charAt(0).toUpperCase() + shape.slice(1);
93
- const offset = topLevelEntries.value.length * 1.5;
94
- const id = tree.createChild(null, label);
95
- tree.updateMeta(id, {
96
- spShape: shape,
97
- spX: offset,
98
- spY: shape === "plane" ? 0 : 0.5,
99
- spZ: 0,
100
- spSX: 1,
101
- spSY: 1,
102
- spSZ: 1,
103
- color: "#6366f1"
104
- });
105
- selectedIds.value = /* @__PURE__ */ new Set([id]);
106
- }
107
- function deleteSelected() {
108
- if (!props.editable) return;
109
- for (const id of selectedIds.value) tree.deleteEntry(id);
110
- selectedIds.value = /* @__PURE__ */ new Set();
111
- }
112
- function duplicateSelected() {
113
- if (!props.editable || !selectedEntry.value) return;
114
- const newId = tree.duplicateEntry(selectedEntry.value.id);
115
- const entry = tree.entries.value.find((e) => e.id === newId);
116
- if (entry) tree.updateMeta(newId, { spX: (entry.meta?.spX ?? 0) + 1.5 });
117
- selectedIds.value = /* @__PURE__ */ new Set([newId]);
118
- }
119
- const shapeMenuItems = computed(() => [
120
- shapes.map((s) => ({
121
- label: s.charAt(0).toUpperCase() + s.slice(1),
122
- icon: shapeIcons[s] ?? "i-lucide-box",
123
- onSelect: () => addObject(s)
124
- }))
125
- ]);
126
- function shapeIcon(shape) {
127
- return shapeIcons[shape ?? "box"] ?? "i-lucide-box";
128
- }
129
- const contextMenuItems = computed(() => {
130
- const items = [];
131
- if (selectedEntry.value) {
132
- items.push([
133
- { label: "Open", icon: "i-lucide-external-link", onSelect: () => openNode(selectedEntry.value.id, selectedEntry.value.label) },
134
- { label: "Duplicate", icon: "i-lucide-copy", onSelect: duplicateSelected }
135
- ]);
136
- }
137
- if (selectedIds.value.size > 0) {
138
- items.push([{ label: "Delete", icon: "i-lucide-trash-2", color: "error", onSelect: deleteSelected }]);
139
- }
140
- items.push(shapes.map((s) => ({
141
- label: `Add ${s.charAt(0).toUpperCase() + s.slice(1)}`,
142
- icon: "i-lucide-plus",
143
- onSelect: () => addObject(s)
144
- })));
145
- return items;
146
- });
147
- let pointerDownHitId = null;
148
- let pointerDownTime = 0;
149
- let isPointerActive = false;
150
- function onCanvasPointerDown(ev) {
151
- isPointerActive = true;
152
- if (ev.button !== 0) {
153
- camPointerDown(ev);
154
- return;
155
- }
156
- pointerDownTime = performance.now();
157
- pointerDownHitId = dragPointerDown(ev);
158
- if (pointerDownHitId && !props.editable) {
159
- pointerDownHitId = null;
160
- camPointerDown(ev);
161
- return;
162
- }
163
- if (pointerDownHitId) {
164
- if (ev.shiftKey) {
165
- const next = new Set(selectedIds.value);
166
- if (next.has(pointerDownHitId)) next.delete(pointerDownHitId);
167
- else next.add(pointerDownHitId);
168
- selectedIds.value = next;
169
- } else if (!selectedIds.value.has(pointerDownHitId)) {
170
- selectedIds.value = /* @__PURE__ */ new Set([pointerDownHitId]);
171
- }
172
- } else {
173
- camPointerDown(ev);
174
- }
175
- }
176
- function onWindowPointerMove(ev) {
177
- if (!isPointerActive) return;
178
- if (draggingId.value) dragPointerMove(ev);
179
- else camPointerMove(ev);
180
- }
181
- function onWindowPointerUp(ev) {
182
- if (!isPointerActive) return;
183
- isPointerActive = false;
184
- if (draggingId.value) {
185
- dragPointerUp(ev);
186
- } else {
187
- camPointerUp();
188
- const elapsed = performance.now() - pointerDownTime;
189
- if (!pointerDownHitId && ev.button === 0 && !ev.shiftKey && elapsed < 300) {
190
- selectedIds.value = /* @__PURE__ */ new Set();
191
- }
192
- }
193
- pointerDownHitId = null;
194
- }
195
- function onCanvasDblClick(ev) {
196
- const hitId = dragPointerDown(ev);
197
- dragPointerUp(ev);
198
- if (hitId) {
199
- const entry = tree.entries.value.find((e) => e.id === hitId);
200
- if (entry) {
201
- focusOn([entry.meta?.spX ?? 0, entry.meta?.spY ?? 0, entry.meta?.spZ ?? 0]);
202
- }
203
- }
204
- }
205
- function onKeyDown(ev) {
206
- if (ev.target?.tagName === "INPUT") return;
207
- if ((ev.key === "Delete" || ev.key === "Backspace") && props.editable && selectedIds.value.size > 0) {
208
- ev.preventDefault();
209
- deleteSelected();
210
- }
211
- if (ev.key === "d" && (ev.metaKey || ev.ctrlKey) && props.editable && selectedEntry.value) {
212
- ev.preventDefault();
213
- duplicateSelected();
214
- }
215
- if (ev.key === "Escape") selectedIds.value = /* @__PURE__ */ new Set();
216
- }
217
- onMounted(() => {
218
- window.addEventListener("keydown", onKeyDown);
219
- window.addEventListener("pointermove", onWindowPointerMove);
220
- window.addEventListener("pointerup", onWindowPointerUp);
221
- });
222
- onBeforeUnmount(() => {
223
- window.removeEventListener("keydown", onKeyDown);
224
- window.removeEventListener("pointermove", onWindowPointerMove);
225
- window.removeEventListener("pointerup", onWindowPointerUp);
226
- });
227
- const isDark = computed(() => typeof document !== "undefined" && document.documentElement.classList.contains("dark"));
228
- const clearColor = computed(() => isDark.value ? "#111118" : "#f0f0f4");
229
- const gridColor1 = computed(() => isDark.value ? "#555" : "#ccc");
230
- const gridColor2 = computed(() => isDark.value ? "#333" : "#ddd");
231
- const groundColor = computed(() => isDark.value ? "#111118" : "#f0f0f4");
232
- function onSceneReady({ scene: s, camera: c, canvas: cvs }) {
233
- if (cvs && s && c) bindScene(cvs, s, c);
234
- }
235
- defineExpose({ connectedUsers });
236
- </script>
237
-
238
- <template>
239
- <div class="spatial-container">
240
- <ClientOnly>
241
- <UContextMenu
242
- :items="editable ? contextMenuItems : []"
243
- class="absolute inset-0"
244
- >
245
- <div
246
- class="spatial-canvas-wrap"
247
- data-swipe-ignore
248
- @pointerdown="onCanvasPointerDown"
249
- @wheel.prevent="onCanvasWheel"
250
- @dblclick="onCanvasDblClick"
251
- >
252
- <TresCanvas
253
- shadows
254
- :clear-color="clearColor"
255
- >
256
- <SpatialSceneBridge @ready="onSceneReady" />
257
- <TresPerspectiveCamera
258
- ref="cameraRef"
259
- :position="cameraPosition"
260
- :look-at="cameraTarget"
261
- :fov="60"
262
- :near="0.1"
263
- :far="1e3"
264
- />
265
-
266
- <TresAmbientLight :intensity="isDark ? 0.5 : 0.8" />
267
- <TresDirectionalLight
268
- :position="[15, 25, 15]"
269
- :intensity="isDark ? 1.2 : 1"
270
- cast-shadow
271
- />
272
- <TresDirectionalLight
273
- :position="[-10, 10, -10]"
274
- :intensity="isDark ? 0.3 : 0.5"
275
- />
276
-
277
- <SpatialGround
278
- v-if="gridVisible"
279
- :color1="gridColor1"
280
- :color2="gridColor2"
281
- :ground-color="groundColor"
282
- />
283
-
284
- <SpatialObject
285
- v-for="entry in topLevelEntries"
286
- :key="entry.id"
287
- :entry="entry"
288
- :tree="tree"
289
- :selected-ids="selectedIds"
290
- :remote-selections="remoteSelectionMap"
291
- :dragging-id="draggingId"
292
- />
293
-
294
- <SpatialUserAvatar
295
- v-for="u in remoteUsers3D"
296
- :key="u.clientId"
297
- :position="u.position"
298
- :color="u.color"
299
- :name="u.name"
300
- />
301
- </TresCanvas>
302
- </div>
303
-
304
- <!-- Toolbar -->
305
- <div class="spatial-toolbar">
306
- <template v-if="editable">
307
- <div class="toolbar-group">
308
- <UDropdownMenu :items="shapeMenuItems">
309
- <UButton
310
- icon="i-lucide-plus"
311
- size="sm"
312
- variant="ghost"
313
- color="neutral"
314
- />
315
- </UDropdownMenu>
316
- </div>
317
- <div class="toolbar-divider" />
318
- </template>
319
- <div class="toolbar-group">
320
- <UButton
321
- icon="i-lucide-rotate-3d"
322
- size="sm"
323
- :color="controlMode === 'orbit' ? 'primary' : 'neutral'"
324
- :variant="controlMode === 'orbit' ? 'soft' : 'ghost'"
325
- @click="controlMode = 'orbit'"
326
- />
327
- <UButton
328
- icon="i-lucide-move-3d"
329
- size="sm"
330
- :color="controlMode === 'fly' ? 'primary' : 'neutral'"
331
- :variant="controlMode === 'fly' ? 'soft' : 'ghost'"
332
- @click="controlMode = 'fly'"
333
- />
334
- </div>
335
- <div class="toolbar-divider" />
336
- <UButton
337
- v-if="editable"
338
- icon="i-lucide-grid-3x3"
339
- size="sm"
340
- :color="gridVisible ? 'primary' : 'neutral'"
341
- :variant="gridVisible ? 'soft' : 'ghost'"
342
- :class="{ 'opacity-40': !gridVisible }"
343
- @click="toggleGrid"
344
- />
345
- </div>
346
-
347
- <!-- Properties panel -->
348
- <div
349
- v-if="selectedEntry"
350
- class="spatial-properties"
351
- >
352
- <div class="sp-prop-header">
353
- <UIcon
354
- :name="shapeIcon(selectedEntry.meta?.spShape)"
355
- class="size-4 shrink-0 text-(--ui-text-muted)"
356
- />
357
- <span class="sp-prop-name">{{ selectedEntry.label }}</span>
358
- <UButton
359
- icon="i-lucide-external-link"
360
- size="xs"
361
- variant="ghost"
362
- color="neutral"
363
- @click="openNode(selectedEntry.id, selectedEntry.label)"
364
- />
365
- <UButton
366
- v-if="editable"
367
- icon="i-lucide-trash-2"
368
- size="xs"
369
- variant="ghost"
370
- color="error"
371
- @click="deleteSelected"
372
- />
373
- </div>
374
-
375
- <!-- Shape selector (hide for GLB — shape comes from the file) -->
376
- <div
377
- v-if="editable && selectedEntry.meta?.spShape !== 'glb'"
378
- class="sp-prop-row"
379
- >
380
- <span class="sp-prop-label">Shape</span>
381
- <USelectMenu
382
- :model-value="selectedEntry.meta?.spShape ?? 'box'"
383
- :items="shapes"
384
- size="xs"
385
- class="flex-1"
386
- @update:model-value="tree.updateMeta(selectedEntry.id, { spShape: $event })"
387
- />
388
- </div>
389
-
390
- <div
391
- v-if="editable && selectedEntry.meta?.spShape !== 'glb'"
392
- class="sp-prop-row"
393
- >
394
- <span class="sp-prop-label">Color</span>
395
- <div class="flex gap-1 flex-wrap">
396
- <button
397
- v-for="c in ['#6366f1', '#ef4444', '#22c55e', '#3b82f6', '#f97316', '#a855f7', '#ec4899', '#14b8a6']"
398
- :key="c"
399
- class="size-5 rounded-full cursor-pointer border-2 transition-transform hover:scale-110"
400
- :class="selectedEntry.meta?.color === c ? 'border-(--ui-text)' : 'border-transparent'"
401
- :style="{ background: c }"
402
- @click="tree.updateMeta(selectedEntry.id, { color: c })"
403
- />
404
- </div>
405
- </div>
406
-
407
- <div
408
- v-if="editable && selectedEntry.meta?.spShape !== 'glb'"
409
- class="sp-prop-row"
410
- >
411
- <span class="sp-prop-label">Opacity</span>
412
- <input
413
- type="range"
414
- min="0"
415
- max="100"
416
- :value="selectedEntry.meta?.spOpacity ?? 100"
417
- class="flex-1 h-1.5 accent-(--color-primary-500)"
418
- @input="tree.updateMeta(selectedEntry.id, { spOpacity: Number($event.target.value) })"
419
- >
420
- <span class="text-[10px] w-7 text-right text-(--ui-text-dimmed)">{{ selectedEntry.meta?.spOpacity ?? 100 }}%</span>
421
- </div>
422
-
423
- <!-- Transform inputs (Pos / Rot / Scale) -->
424
- <SpatialTransformInputs
425
- v-if="editable"
426
- :entry="selectedEntry"
427
- :tree="tree"
428
- />
429
- </div>
430
-
431
- <!-- Connected users -->
432
- <div
433
- v-if="connectedUsers.length > 1"
434
- class="spatial-presence"
435
- >
436
- <UAvatar
437
- v-for="u in connectedUsers"
438
- :key="u.clientId"
439
- :alt="u.name"
440
- size="xs"
441
- :style="{ border: `2px solid ${u.color}`, borderRadius: '50%' }"
442
- />
443
- </div>
444
- </UContextMenu>
445
- </ClientOnly>
446
-
447
- <!-- Node panel -->
448
- <ANodePanel
449
- :node-id="openNodeId"
450
- :node-label="openNodeLabel"
451
- :child-provider="openNodeProvider"
452
- @close="closePanel"
453
- />
454
- </div>
455
- </template>
456
-
457
- <style scoped>
458
- .spatial-container{flex:1;height:100%;min-height:0;overflow:hidden;position:relative;width:100%}.spatial-canvas-wrap{inset:0;position:absolute;touch-action:none}.spatial-toolbar{align-items:center;backdrop-filter:blur(8px);background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:10px;bottom:2rem;display:flex;gap:3px;left:50%;padding:3px;position:absolute;transform:translateX(-50%);z-index:20}.toolbar-group{align-items:center;display:flex;gap:1px}.toolbar-divider{background:var(--ui-border);flex-shrink:0;height:20px;margin:0 2px;width:1px}.spatial-properties{background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:8px;display:flex;flex-direction:column;gap:6px;max-height:calc(100% - 24px);overflow-y:auto;padding:10px;position:absolute;right:12px;top:12px;width:260px;z-index:10}.sp-prop-header{align-items:center;display:flex;gap:6px}.sp-prop-name{flex:1;font-size:.8rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sp-prop-row{align-items:center;display:flex;gap:6px}.sp-prop-label{color:var(--ui-text-dimmed);flex-shrink:0;font-size:.7rem;font-weight:500;width:48px}.spatial-presence{bottom:12px;display:flex;gap:4px;left:12px;position:absolute;z-index:10}
459
- </style>
@@ -1,19 +0,0 @@
1
- import { type RendererBaseProps } from '../../composables/useRendererBase.js';
2
- import type { AbracadabraLocale } from '../../locale.js';
3
- type __VLS_Props = RendererBaseProps & {
4
- labels?: Partial<AbracadabraLocale['renderers']>;
5
- editable?: boolean;
6
- };
7
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
8
- connectedUsers: import("vue").ComputedRef<{
9
- clientId: number;
10
- name: string;
11
- color: string;
12
- avatar: string | undefined;
13
- publicKey: any;
14
- }[]>;
15
- }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
16
- editable: boolean;
17
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
- declare const _default: typeof __VLS_export;
19
- export default _default;
@@ -1,20 +0,0 @@
1
- /**
2
- * Ground plane with grid helper and shadow-receiving surface.
3
- * Ported from cou-sh/app/components/spatial/SpatialGround.vue
4
- */
5
- type __VLS_Props = {
6
- gridSize?: number;
7
- gridDivisions?: number;
8
- color1?: string;
9
- color2?: string;
10
- groundColor?: string;
11
- };
12
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
13
- groundColor: string;
14
- gridSize: number;
15
- gridDivisions: number;
16
- color1: string;
17
- color2: string;
18
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
- declare const _default: typeof __VLS_export;
20
- export default _default;
@@ -1,26 +0,0 @@
1
- <script setup>
2
- defineProps({
3
- gridSize: { type: Number, required: false, default: 100 },
4
- gridDivisions: { type: Number, required: false, default: 100 },
5
- color1: { type: String, required: false, default: "#555" },
6
- color2: { type: String, required: false, default: "#333" },
7
- groundColor: { type: String, required: false, default: "#111118" }
8
- });
9
- const HALF_PI = -Math.PI / 2;
10
- </script>
11
-
12
- <template>
13
- <TresGridHelper :args="[gridSize, gridDivisions, color1, color2]" />
14
- <TresMesh
15
- :rotation-x="HALF_PI"
16
- :position-y="-5e-3"
17
- receive-shadow
18
- >
19
- <TresPlaneGeometry :args="[gridSize, gridSize]" />
20
- <TresMeshStandardMaterial
21
- :color="groundColor"
22
- :opacity="0.3"
23
- :transparent="true"
24
- />
25
- </TresMesh>
26
- </template>
@@ -1,20 +0,0 @@
1
- /**
2
- * Ground plane with grid helper and shadow-receiving surface.
3
- * Ported from cou-sh/app/components/spatial/SpatialGround.vue
4
- */
5
- type __VLS_Props = {
6
- gridSize?: number;
7
- gridDivisions?: number;
8
- color1?: string;
9
- color2?: string;
10
- groundColor?: string;
11
- };
12
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
13
- groundColor: string;
14
- gridSize: number;
15
- gridDivisions: number;
16
- color1: string;
17
- color2: string;
18
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
- declare const _default: typeof __VLS_export;
20
- export default _default;
@@ -1,17 +0,0 @@
1
- import type { TreeEntry } from '../../../types.js';
2
- type __VLS_Props = {
3
- entry: TreeEntry;
4
- tree: {
5
- childrenOf: (parentId: string | null) => TreeEntry[];
6
- updateMeta: (id: string, meta: Record<string, unknown>) => void;
7
- };
8
- selectedIds: Set<string>;
9
- remoteSelections: Map<string, {
10
- color: string;
11
- name: string;
12
- }[]>;
13
- draggingId: string | null;
14
- };
15
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
- declare const _default: typeof __VLS_export;
17
- export default _default;