@fps-games/editor 0.1.5-beta.1 → 0.1.5-beta.2

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 (40) hide show
  1. package/dist/build-info.json +13 -13
  2. package/dist/local-editor-harness.js +1 -1
  3. package/dist/local-editor-harness.js.map +1 -1
  4. package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
  5. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.d.ts +26 -0
  6. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.d.ts.map +1 -0
  7. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.js +312 -0
  8. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.js.map +1 -0
  9. package/node_modules/@fps-games/editor-babylon/dist/projection-selection-controller.d.ts.map +1 -1
  10. package/node_modules/@fps-games/editor-babylon/dist/projection-selection-controller.js +51 -29
  11. package/node_modules/@fps-games/editor-babylon/dist/projection-selection-controller.js.map +1 -1
  12. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
  13. package/node_modules/@fps-games/editor-babylon/dist/projection.js +4 -39
  14. package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
  15. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  16. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.d.ts +5 -0
  17. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.d.ts.map +1 -1
  18. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js +34 -1
  19. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js.map +1 -1
  20. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.d.ts +47 -0
  21. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.d.ts.map +1 -0
  22. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js +404 -0
  23. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js.map +1 -0
  24. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts.map +1 -1
  25. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js +59 -0
  26. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js.map +1 -1
  27. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.d.ts +1 -1
  28. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.d.ts.map +1 -1
  29. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.js +12 -6
  30. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.js.map +1 -1
  31. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +2 -0
  32. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  33. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +1 -0
  34. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  35. package/node_modules/@fps-games/editor-browser/package.json +3 -3
  36. package/node_modules/@fps-games/editor-core/package.json +2 -2
  37. package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
  38. package/node_modules/@fps-games/editor-playable-sdk/package.json +3 -3
  39. package/node_modules/@fps-games/editor-protocol/package.json +1 -1
  40. package/package.json +8 -8
@@ -0,0 +1,47 @@
1
+ import { type LocalEditorThemeName } from './local-editor-ui-theme';
2
+ import type { LocalEditorHierarchyDropResolution, LocalEditorHierarchyTreeModel, LocalEditorHierarchyTreeNode } from './local-editor-ui-hierarchy-tree';
3
+ export interface LocalEditorHierarchyAttachTarget {
4
+ key: string;
5
+ targetId: string | null;
6
+ label: string;
7
+ role: LocalEditorHierarchyTreeNode['role'] | 'scene-root';
8
+ depth: number;
9
+ valid: boolean;
10
+ disabledReason?: string;
11
+ selected: boolean;
12
+ node?: LocalEditorHierarchyTreeNode;
13
+ resolution: LocalEditorHierarchyDropResolution;
14
+ }
15
+ export interface LocalEditorHierarchyAttachTargetSelection {
16
+ targetId: string | null;
17
+ placement: 'root' | 'inside';
18
+ label: string;
19
+ resolution: LocalEditorHierarchyDropResolution;
20
+ }
21
+ export interface LocalEditorHierarchyAttachTargetInput {
22
+ model: LocalEditorHierarchyTreeModel;
23
+ targetIds: readonly string[];
24
+ query?: string;
25
+ selectedTargetKey?: string | null;
26
+ }
27
+ export interface LocalEditorHierarchyAttachDialogOpenInput {
28
+ model: LocalEditorHierarchyTreeModel;
29
+ targetIds: readonly string[];
30
+ activeId: string | null;
31
+ }
32
+ export interface LocalEditorHierarchyAttachDialogOptions {
33
+ doc: Document;
34
+ getTheme?: () => LocalEditorThemeName | undefined;
35
+ onOpenChange?: (open: boolean) => void;
36
+ onConfirm?: (selection: LocalEditorHierarchyAttachTargetSelection) => void;
37
+ }
38
+ export interface LocalEditorHierarchyAttachDialogController {
39
+ isOpen(): boolean;
40
+ open(input: LocalEditorHierarchyAttachDialogOpenInput): void;
41
+ close(): void;
42
+ setTheme(theme: LocalEditorThemeName): void;
43
+ dispose(): void;
44
+ }
45
+ export declare function resolveLocalEditorHierarchyAttachTargets(input: LocalEditorHierarchyAttachTargetInput): LocalEditorHierarchyAttachTarget[];
46
+ export declare function createLocalEditorHierarchyAttachDialog(options: LocalEditorHierarchyAttachDialogOptions): LocalEditorHierarchyAttachDialogController;
47
+ //# sourceMappingURL=local-editor-ui-hierarchy-attach-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-editor-ui-hierarchy-attach-dialog.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-attach-dialog.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AAIjC,OAAO,KAAK,EACV,kCAAkC,EAClC,6BAA6B,EAC7B,4BAA4B,EAC7B,MAAM,kCAAkC,CAAC;AAU1C,MAAM,WAAW,gCAAgC;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,4BAA4B,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,4BAA4B,CAAC;IACpC,UAAU,EAAE,kCAAkC,CAAC;CAChD;AAED,MAAM,WAAW,yCAAyC;IACxD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,kCAAkC,CAAC;CAChD;AAED,MAAM,WAAW,qCAAqC;IACpD,KAAK,EAAE,6BAA6B,CAAC;IACrC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,yCAAyC;IACxD,KAAK,EAAE,6BAA6B,CAAC;IACrC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,uCAAuC;IACtD,GAAG,EAAE,QAAQ,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,oBAAoB,GAAG,SAAS,CAAC;IAClD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,yCAAyC,KAAK,IAAI,CAAC;CAC5E;AAED,MAAM,WAAW,0CAA0C;IACzD,MAAM,IAAI,OAAO,CAAC;IAClB,IAAI,CAAC,KAAK,EAAE,yCAAyC,GAAG,IAAI,CAAC;IAC7D,KAAK,IAAI,IAAI,CAAC;IACd,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC5C,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,wCAAwC,CACtD,KAAK,EAAE,qCAAqC,GAC3C,gCAAgC,EAAE,CA8BpC;AAED,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,uCAAuC,GAC/C,0CAA0C,CAuU5C"}
@@ -0,0 +1,404 @@
1
+ import { createButton } from './local-editor-ui-shared.js';
2
+ import { createEditorInputStyle, } from './local-editor-ui-primitives.js';
3
+ import { createLocalEditorIcon, isLocalEditorIconName, } from './local-editor-ui-icons.js';
4
+ import { applyLocalEditorTheme, LOCAL_EDITOR_THEME_CLASS, } from './local-editor-ui-theme.js';
5
+ import { resolveLocalEditorHierarchySearchRows, } from './local-editor-ui-hierarchy-view.js';
6
+ const ATTACH_TARGET_ROOT_KEY = '__fps_editor_scene_root__';
7
+ const ATTACH_ROLE_ICONS = {
8
+ root: 'root',
9
+ group: 'group',
10
+ object: 'object',
11
+ };
12
+ export function resolveLocalEditorHierarchyAttachTargets(input) {
13
+ const sourceIds = input.model.getTopLevelSelection(input.targetIds);
14
+ const rootResolution = input.model.resolveDrop({ draggedIds: sourceIds, placement: 'root' });
15
+ const targets = [{
16
+ key: ATTACH_TARGET_ROOT_KEY,
17
+ targetId: null,
18
+ label: 'Scene Root',
19
+ role: 'scene-root',
20
+ depth: 0,
21
+ valid: rootResolution.ok,
22
+ disabledReason: rootResolution.ok ? undefined : formatAttachDisabledReason(rootResolution.reason),
23
+ selected: input.selectedTargetKey === ATTACH_TARGET_ROOT_KEY,
24
+ resolution: rootResolution,
25
+ }];
26
+ for (const node of resolveLocalEditorHierarchySearchRows(input.model, input.query ?? '')) {
27
+ const resolution = resolveAttachTargetDrop(input.model, sourceIds, node.id);
28
+ targets.push({
29
+ key: node.id,
30
+ targetId: node.id,
31
+ label: node.label,
32
+ role: node.role,
33
+ depth: node.depth + 1,
34
+ valid: resolution.ok,
35
+ disabledReason: resolution.ok ? undefined : formatAttachDisabledReason(resolution.reason),
36
+ selected: input.selectedTargetKey === node.id,
37
+ node,
38
+ resolution,
39
+ });
40
+ }
41
+ return targets;
42
+ }
43
+ export function createLocalEditorHierarchyAttachDialog(options) {
44
+ const { doc } = options;
45
+ const root = doc.createElement('div');
46
+ root.classList.add(LOCAL_EDITOR_THEME_CLASS);
47
+ root.dataset.editorHierarchyAttachDialog = 'true';
48
+ root.dataset.editorWorkbenchRegion = 'modal';
49
+ root.style.cssText = [
50
+ 'position:fixed',
51
+ 'inset:0',
52
+ 'z-index:2147483642',
53
+ 'display:none',
54
+ 'align-items:center',
55
+ 'justify-content:center',
56
+ 'padding:32px',
57
+ 'background:rgba(0,0,0,0.45)',
58
+ 'font-family:var(--fps-editor-font)',
59
+ 'color:var(--fps-editor-text)',
60
+ 'pointer-events:auto',
61
+ ].join(';');
62
+ const dialog = doc.createElement('div');
63
+ dialog.setAttribute('role', 'dialog');
64
+ dialog.setAttribute('aria-modal', 'true');
65
+ dialog.setAttribute('aria-label', 'Attach selection to hierarchy target');
66
+ dialog.style.cssText = [
67
+ 'width:min(520px,calc(100vw - 64px))',
68
+ 'max-height:calc(100vh - 64px)',
69
+ 'display:flex',
70
+ 'flex-direction:column',
71
+ 'gap:10px',
72
+ 'padding:14px',
73
+ 'border:1px solid var(--fps-editor-border)',
74
+ 'border-radius:4px',
75
+ 'background:var(--fps-editor-panel)',
76
+ 'box-shadow:var(--fps-editor-shadow-modal)',
77
+ 'overflow:hidden',
78
+ ].join(';');
79
+ const header = doc.createElement('div');
80
+ header.style.cssText = 'display:flex;align-items:center;justify-content:space-between;gap:12px';
81
+ const title = doc.createElement('h2');
82
+ title.textContent = 'Attach To...';
83
+ title.style.cssText = [
84
+ 'min-width:0',
85
+ 'margin:0',
86
+ 'overflow:hidden',
87
+ 'text-overflow:ellipsis',
88
+ 'white-space:nowrap',
89
+ 'font-size:13px',
90
+ 'font-weight:900',
91
+ 'color:var(--fps-editor-text-strong)',
92
+ ].join(';');
93
+ const closeButton = createButton(doc, 'Cancel');
94
+ closeButton.dataset.editorHierarchyAttachCancel = 'true';
95
+ header.appendChild(title);
96
+ header.appendChild(closeButton);
97
+ const summary = doc.createElement('div');
98
+ summary.style.cssText = 'color:var(--fps-editor-muted);font-size:11px;font-weight:800;line-height:16px';
99
+ const search = doc.createElement('input');
100
+ search.type = 'search';
101
+ search.dataset.editorHierarchyAttachSearch = 'true';
102
+ search.placeholder = 'Search hierarchy target';
103
+ search.style.cssText = [
104
+ createEditorInputStyle(),
105
+ 'width:100%',
106
+ 'height:30px',
107
+ 'outline:none',
108
+ ].join(';');
109
+ const list = doc.createElement('div');
110
+ list.dataset.editorHierarchyAttachList = 'true';
111
+ list.style.cssText = [
112
+ 'min-height:180px',
113
+ 'max-height:min(430px,calc(100vh - 230px))',
114
+ 'overflow:auto',
115
+ 'display:flex',
116
+ 'flex-direction:column',
117
+ 'gap:2px',
118
+ 'padding:2px',
119
+ 'border:1px solid var(--fps-editor-border-soft)',
120
+ 'border-radius:3px',
121
+ 'background:var(--fps-editor-field)',
122
+ ].join(';');
123
+ const selectedSummary = doc.createElement('div');
124
+ selectedSummary.style.cssText = [
125
+ 'min-height:18px',
126
+ 'color:var(--fps-editor-muted-strong)',
127
+ 'font-size:11px',
128
+ 'font-weight:800',
129
+ 'line-height:16px',
130
+ ].join(';');
131
+ const footer = doc.createElement('div');
132
+ footer.style.cssText = 'display:flex;align-items:center;justify-content:flex-end;gap:8px';
133
+ const cancelButton = createButton(doc, 'Cancel');
134
+ cancelButton.dataset.editorHierarchyAttachCancel = 'true';
135
+ const confirmButton = createButton(doc, 'Attach', { icon: 'hierarchy' });
136
+ confirmButton.dataset.editorHierarchyAttachConfirm = 'true';
137
+ footer.appendChild(cancelButton);
138
+ footer.appendChild(confirmButton);
139
+ dialog.appendChild(header);
140
+ dialog.appendChild(summary);
141
+ dialog.appendChild(search);
142
+ dialog.appendChild(list);
143
+ dialog.appendChild(selectedSummary);
144
+ dialog.appendChild(footer);
145
+ root.appendChild(dialog);
146
+ doc.body.appendChild(root);
147
+ let openInput = null;
148
+ let query = '';
149
+ let selectedTargetKey = null;
150
+ let selectedTarget = null;
151
+ const close = () => {
152
+ if (!openInput)
153
+ return;
154
+ openInput = null;
155
+ query = '';
156
+ selectedTargetKey = null;
157
+ selectedTarget = null;
158
+ root.style.display = 'none';
159
+ search.value = '';
160
+ clearElement(list);
161
+ options.onOpenChange?.(false);
162
+ };
163
+ const render = () => {
164
+ if (!openInput) {
165
+ root.style.display = 'none';
166
+ return;
167
+ }
168
+ const targets = resolveLocalEditorHierarchyAttachTargets({
169
+ model: openInput.model,
170
+ targetIds: openInput.targetIds,
171
+ query,
172
+ selectedTargetKey,
173
+ });
174
+ const validSelection = targets.find(target => target.key === selectedTargetKey && target.valid) ?? null;
175
+ selectedTarget = validSelection;
176
+ if (!validSelection)
177
+ selectedTargetKey = null;
178
+ summary.textContent = `${openInput.targetIds.length} selected node${openInput.targetIds.length === 1 ? '' : 's'} will keep world transform.`;
179
+ search.value = query;
180
+ renderTargetList(targets);
181
+ renderSelectedSummary();
182
+ root.style.display = 'flex';
183
+ syncConfirmButton();
184
+ };
185
+ const renderTargetList = (targets) => {
186
+ clearElement(list);
187
+ const rootTarget = targets[0] ?? null;
188
+ if (rootTarget)
189
+ list.appendChild(createTargetButton(rootTarget));
190
+ const nodeTargets = targets.slice(1);
191
+ if (nodeTargets.length === 0) {
192
+ const empty = doc.createElement('div');
193
+ empty.textContent = query.trim() ? 'No matching GameObjects.' : 'No hierarchy nodes.';
194
+ empty.style.cssText = 'padding:8px;color:var(--fps-editor-muted);font-size:11px;font-weight:800';
195
+ list.appendChild(empty);
196
+ return;
197
+ }
198
+ for (const target of nodeTargets)
199
+ list.appendChild(createTargetButton(target));
200
+ };
201
+ const renderSelectedSummary = () => {
202
+ if (!selectedTarget) {
203
+ selectedSummary.textContent = 'Select a target, then confirm Attach.';
204
+ return;
205
+ }
206
+ const movingCount = selectedTarget.resolution.draggedIds.length;
207
+ selectedSummary.textContent = `Target: ${selectedTarget.label} · ${movingCount} node${movingCount === 1 ? '' : 's'} will move`;
208
+ };
209
+ const syncConfirmButton = () => {
210
+ confirmButton.disabled = !selectedTarget;
211
+ confirmButton.title = selectedTarget ? `Attach to ${selectedTarget.label}` : 'Select a valid target first.';
212
+ confirmButton.style.opacity = selectedTarget ? '1' : '0.55';
213
+ confirmButton.style.cursor = selectedTarget ? 'pointer' : 'not-allowed';
214
+ };
215
+ const createTargetButton = (target) => {
216
+ const button = doc.createElement('button');
217
+ button.type = 'button';
218
+ button.dataset.editorHierarchyAttachTarget = target.key;
219
+ button.disabled = !target.valid;
220
+ if (target.disabledReason)
221
+ button.title = target.disabledReason;
222
+ button.style.cssText = [
223
+ 'width:100%',
224
+ 'min-height:28px',
225
+ 'display:flex',
226
+ 'align-items:center',
227
+ 'gap:6px',
228
+ `padding:4px 8px 4px ${8 + Math.max(0, target.depth) * 14}px`,
229
+ `border:1px solid ${target.selected ? 'var(--fps-editor-accent-strong)' : 'transparent'}`,
230
+ 'border-radius:2px',
231
+ `background:${target.selected ? 'var(--fps-editor-row-active)' : 'transparent'}`,
232
+ `color:${target.valid ? target.selected ? 'var(--fps-editor-row-selected-text)' : 'var(--fps-editor-text)' : 'var(--fps-editor-muted)'}`,
233
+ 'font-size:12px',
234
+ 'font-weight:800',
235
+ 'text-align:left',
236
+ `cursor:${target.valid ? 'pointer' : 'not-allowed'}`,
237
+ `opacity:${target.valid ? '1' : '0.55'}`,
238
+ ].join(';');
239
+ button.appendChild(createTargetIcon(target));
240
+ const label = doc.createElement('span');
241
+ label.textContent = target.label;
242
+ label.style.cssText = 'min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap';
243
+ button.appendChild(label);
244
+ if (target.disabledReason) {
245
+ const reason = doc.createElement('span');
246
+ reason.textContent = target.disabledReason;
247
+ reason.style.cssText = 'max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--fps-editor-muted);font-size:10px;font-weight:800';
248
+ button.appendChild(reason);
249
+ }
250
+ return button;
251
+ };
252
+ const createTargetIcon = (target) => {
253
+ const rawIcon = target.node?.item.icon;
254
+ const iconName = target.role === 'scene-root'
255
+ ? 'root'
256
+ : isLocalEditorIconName(rawIcon)
257
+ ? rawIcon
258
+ : ATTACH_ROLE_ICONS[target.role];
259
+ const icon = doc.createElement('span');
260
+ icon.style.cssText = [
261
+ 'width:16px',
262
+ 'height:16px',
263
+ 'flex:0 0 16px',
264
+ 'display:inline-flex',
265
+ 'align-items:center',
266
+ 'justify-content:center',
267
+ 'color:var(--fps-editor-muted-strong)',
268
+ ].join(';');
269
+ icon.appendChild(createLocalEditorIcon(doc, iconName, { size: 13, strokeWidth: 2.3 }));
270
+ return icon;
271
+ };
272
+ const getSelectionForConfirm = () => {
273
+ if (!selectedTarget)
274
+ return null;
275
+ return {
276
+ targetId: selectedTarget.targetId,
277
+ placement: selectedTarget.targetId === null ? 'root' : 'inside',
278
+ label: selectedTarget.label,
279
+ resolution: selectedTarget.resolution,
280
+ };
281
+ };
282
+ const onClick = (event) => {
283
+ const target = event.target instanceof HTMLElement ? event.target : null;
284
+ if (!target)
285
+ return;
286
+ if (target.closest('[data-editor-hierarchy-attach-cancel]') || target === root) {
287
+ event.preventDefault();
288
+ close();
289
+ return;
290
+ }
291
+ const targetButton = target.closest('[data-editor-hierarchy-attach-target]');
292
+ if (targetButton) {
293
+ event.preventDefault();
294
+ if (targetButton.disabled)
295
+ return;
296
+ selectedTargetKey = targetButton.dataset.editorHierarchyAttachTarget ?? null;
297
+ render();
298
+ return;
299
+ }
300
+ if (target.closest('[data-editor-hierarchy-attach-confirm]')) {
301
+ event.preventDefault();
302
+ const selection = getSelectionForConfirm();
303
+ if (!selection)
304
+ return;
305
+ options.onConfirm?.(selection);
306
+ close();
307
+ }
308
+ };
309
+ const onInput = (event) => {
310
+ const input = event.target instanceof HTMLInputElement ? event.target : null;
311
+ if (input?.dataset.editorHierarchyAttachSearch == null)
312
+ return;
313
+ query = input.value;
314
+ render();
315
+ };
316
+ const onKeyDown = (event) => {
317
+ if (!openInput || event.key !== 'Escape')
318
+ return;
319
+ event.preventDefault();
320
+ event.stopPropagation();
321
+ close();
322
+ };
323
+ root.addEventListener('click', onClick);
324
+ root.addEventListener('input', onInput);
325
+ doc.addEventListener('keydown', onKeyDown, { capture: true });
326
+ return {
327
+ isOpen() {
328
+ return !!openInput;
329
+ },
330
+ open(input) {
331
+ openInput = {
332
+ model: input.model,
333
+ targetIds: input.model.getTopLevelSelection(input.targetIds),
334
+ activeId: input.activeId,
335
+ };
336
+ query = '';
337
+ selectedTargetKey = null;
338
+ selectedTarget = null;
339
+ applyLocalEditorTheme(root, options.getTheme?.());
340
+ options.onOpenChange?.(true);
341
+ render();
342
+ setTimeout(() => {
343
+ search.focus({ preventScroll: true });
344
+ search.select();
345
+ }, 0);
346
+ },
347
+ close,
348
+ setTheme(theme) {
349
+ applyLocalEditorTheme(root, theme);
350
+ },
351
+ dispose() {
352
+ close();
353
+ root.removeEventListener('click', onClick);
354
+ root.removeEventListener('input', onInput);
355
+ doc.removeEventListener('keydown', onKeyDown, { capture: true });
356
+ root.remove();
357
+ },
358
+ };
359
+ }
360
+ function resolveAttachTargetDrop(model, sourceIds, targetId) {
361
+ const resolution = model.resolveDrop({
362
+ draggedIds: sourceIds,
363
+ targetId,
364
+ placement: 'inside',
365
+ });
366
+ if (resolution.ok || !sourceIds.includes(targetId))
367
+ return resolution;
368
+ const remainingSourceIds = sourceIds.filter(id => id !== targetId);
369
+ if (remainingSourceIds.length === 0)
370
+ return resolution;
371
+ return model.resolveDrop({
372
+ draggedIds: remainingSourceIds,
373
+ targetId,
374
+ placement: 'inside',
375
+ });
376
+ }
377
+ function formatAttachDisabledReason(reason) {
378
+ if (!reason)
379
+ return undefined;
380
+ if (reason === 'empty-drag')
381
+ return 'Select one or more movable nodes first.';
382
+ if (reason === 'dragged-node-protected')
383
+ return 'Protected nodes cannot be attached.';
384
+ if (reason === 'missing-target')
385
+ return 'Target no longer exists.';
386
+ if (reason === 'cannot-drop-on-self')
387
+ return 'Cannot attach to itself.';
388
+ if (reason === 'cannot-drop-on-descendant')
389
+ return 'Cannot attach to selected descendants.';
390
+ if (reason === 'target-cannot-have-children')
391
+ return 'This node cannot contain children.';
392
+ if (reason === 'cannot-reorder-root')
393
+ return 'Root nodes cannot be reordered.';
394
+ if (reason === 'target-node-locked')
395
+ return 'Locked nodes cannot be used as targets.';
396
+ if (reason === 'target-parent-locked')
397
+ return 'The target parent is locked.';
398
+ return reason;
399
+ }
400
+ function clearElement(element) {
401
+ while (element.firstChild)
402
+ element.firstChild.remove();
403
+ }
404
+ //# sourceMappingURL=local-editor-ui-hierarchy-attach-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-editor-ui-hierarchy-attach-dialog.js","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-attach-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EACL,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GAEtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,wBAAwB,GAEzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qCAAqC,GACtC,MAAM,kCAAkC,CAAC;AAO1C,MAAM,sBAAsB,GAAG,2BAA2B,CAAC;AAE3D,MAAM,iBAAiB,GAAsE;IAC3F,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;CACjB,CAAC;AAkDF,MAAM,UAAU,wCAAwC,CACtD,KAA4C;IAE5C,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpE,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAuC,CAAC;YACnD,GAAG,EAAE,sBAAsB;YAC3B,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,cAAc,CAAC,EAAE;YACxB,cAAc,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,cAAc,CAAC,MAAM,CAAC;YACjG,QAAQ,EAAE,KAAK,CAAC,iBAAiB,KAAK,sBAAsB;YAC5D,UAAU,EAAE,cAAc;SAC3B,CAAC,CAAC;IACH,KAAK,MAAM,IAAI,IAAI,qCAAqC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACzF,MAAM,UAAU,GAAG,uBAAuB,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,EAAE;YACZ,QAAQ,EAAE,IAAI,CAAC,EAAE;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC;YACrB,KAAK,EAAE,UAAU,CAAC,EAAE;YACpB,cAAc,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,UAAU,CAAC,MAAM,CAAC;YACzF,QAAQ,EAAE,KAAK,CAAC,iBAAiB,KAAK,IAAI,CAAC,EAAE;YAC7C,IAAI;YACJ,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,sCAAsC,CACpD,OAAgD;IAEhD,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxB,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,CAAC,2BAA2B,GAAG,MAAM,CAAC;IAClD,IAAI,CAAC,OAAO,CAAC,qBAAqB,GAAG,OAAO,CAAC;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG;QACnB,gBAAgB;QAChB,SAAS;QACT,oBAAoB;QACpB,cAAc;QACd,oBAAoB;QACpB,wBAAwB;QACxB,cAAc;QACd,6BAA6B;QAC7B,oCAAoC;QACpC,8BAA8B;QAC9B,qBAAqB;KACtB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,sCAAsC,CAAC,CAAC;IAC1E,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG;QACrB,qCAAqC;QACrC,+BAA+B;QAC/B,cAAc;QACd,uBAAuB;QACvB,UAAU;QACV,cAAc;QACd,2CAA2C;QAC3C,mBAAmB;QACnB,oCAAoC;QACpC,2CAA2C;QAC3C,iBAAiB;KAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,wEAAwE,CAAC;IAChG,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACtC,KAAK,CAAC,WAAW,GAAG,cAAc,CAAC;IACnC,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG;QACpB,aAAa;QACb,UAAU;QACV,iBAAiB;QACjB,wBAAwB;QACxB,oBAAoB;QACpB,gBAAgB;QAChB,iBAAiB;QACjB,qCAAqC;KACtC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACZ,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAChD,WAAW,CAAC,OAAO,CAAC,2BAA2B,GAAG,MAAM,CAAC;IACzD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1B,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,+EAA+E,CAAC;IAExG,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;IACvB,MAAM,CAAC,OAAO,CAAC,2BAA2B,GAAG,MAAM,CAAC;IACpD,MAAM,CAAC,WAAW,GAAG,yBAAyB,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG;QACrB,sBAAsB,EAAE;QACxB,YAAY;QACZ,aAAa;QACb,cAAc;KACf,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,CAAC,yBAAyB,GAAG,MAAM,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG;QACnB,kBAAkB;QAClB,2CAA2C;QAC3C,eAAe;QACf,cAAc;QACd,uBAAuB;QACvB,SAAS;QACT,aAAa;QACb,gDAAgD;QAChD,mBAAmB;QACnB,oCAAoC;KACrC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,eAAe,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACjD,eAAe,CAAC,KAAK,CAAC,OAAO,GAAG;QAC9B,iBAAiB;QACjB,sCAAsC;QACtC,gBAAgB;QAChB,iBAAiB;QACjB,kBAAkB;KACnB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,kEAAkE,CAAC;IAC1F,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACjD,YAAY,CAAC,OAAO,CAAC,2BAA2B,GAAG,MAAM,CAAC;IAC1D,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IACzE,aAAa,CAAC,OAAO,CAAC,4BAA4B,GAAG,MAAM,CAAC;IAC5D,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IACjC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAElC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAE3B,IAAI,SAAS,GAAqD,IAAI,CAAC;IACvE,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,iBAAiB,GAAkB,IAAI,CAAC;IAC5C,IAAI,cAAc,GAA4C,IAAI,CAAC;IAEnE,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,CAAC,SAAS;YAAE,OAAO;QACvB,SAAS,GAAG,IAAI,CAAC;QACjB,KAAK,GAAG,EAAE,CAAC;QACX,iBAAiB,GAAG,IAAI,CAAC;QACzB,cAAc,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QAC5B,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;QAClB,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;YAC5B,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,wCAAwC,CAAC;YACvD,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,KAAK;YACL,iBAAiB;SAClB,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,iBAAiB,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;QACxG,cAAc,GAAG,cAAc,CAAC;QAChC,IAAI,CAAC,cAAc;YAAE,iBAAiB,GAAG,IAAI,CAAC;QAC9C,OAAO,CAAC,WAAW,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,iBAAiB,SAAS,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,6BAA6B,CAAC;QAC7I,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC1B,qBAAqB,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QAC5B,iBAAiB,EAAE,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,OAAoD,EAAQ,EAAE;QACtF,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACtC,IAAI,UAAU;YAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACvC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,qBAAqB,CAAC;YACtF,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,0EAA0E,CAAC;YACjG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,WAAW;YAAE,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC;IAEF,MAAM,qBAAqB,GAAG,GAAS,EAAE;QACvC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,eAAe,CAAC,WAAW,GAAG,uCAAuC,CAAC;YACtE,OAAO;QACT,CAAC;QACD,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC;QAChE,eAAe,CAAC,WAAW,GAAG,WAAW,cAAc,CAAC,KAAK,MAAM,WAAW,QAAQ,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;IACjI,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,GAAS,EAAE;QACnC,aAAa,CAAC,QAAQ,GAAG,CAAC,cAAc,CAAC;QACzC,aAAa,CAAC,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,aAAa,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,8BAA8B,CAAC;QAC5G,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5D,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;IAC1E,CAAC,CAAC;IAEF,MAAM,kBAAkB,GAAG,CAAC,MAAwC,EAAqB,EAAE;QACzF,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;QACvB,MAAM,CAAC,OAAO,CAAC,2BAA2B,GAAG,MAAM,CAAC,GAAG,CAAC;QACxD,MAAM,CAAC,QAAQ,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;QAChC,IAAI,MAAM,CAAC,cAAc;YAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC;QAChE,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG;YACrB,YAAY;YACZ,iBAAiB;YACjB,cAAc;YACd,oBAAoB;YACpB,SAAS;YACT,uBAAuB,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI;YAC7D,oBAAoB,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,aAAa,EAAE;YACzF,mBAAmB;YACnB,cAAc,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,aAAa,EAAE;YAChF,SAAS,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,yBAAyB,EAAE;YACxI,gBAAgB;YAChB,iBAAiB;YACjB,iBAAiB;YACjB,UAAU,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE;YACpD,WAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE;SACzC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACxC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;QACjC,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,8EAA8E,CAAC;QACrG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YACzC,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,wIAAwI,CAAC;YAChK,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,MAAwC,EAAe,EAAE;QACjF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,KAAK,YAAY;YAC3C,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,qBAAqB,CAAC,OAAO,CAAC;gBAC9B,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG;YACnB,YAAY;YACZ,aAAa;YACb,eAAe;YACf,qBAAqB;YACrB,oBAAoB;YACpB,wBAAwB;YACxB,sCAAsC;SACvC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACvF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,GAAqD,EAAE;QACpF,IAAI,CAAC,cAAc;YAAE,OAAO,IAAI,CAAC;QACjC,OAAO;YACL,QAAQ,EAAE,cAAc,CAAC,QAAQ;YACjC,SAAS,EAAE,cAAc,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;YAC/D,KAAK,EAAE,cAAc,CAAC,KAAK;YAC3B,UAAU,EAAE,cAAc,CAAC,UAAU;SACtC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,KAAiB,EAAQ,EAAE;QAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,MAAM,CAAC,OAAO,CAAC,uCAAuC,CAAC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAC/E,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,KAAK,EAAE,CAAC;YACR,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAoB,uCAAuC,CAAC,CAAC;QAChG,IAAI,YAAY,EAAE,CAAC;YACjB,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,YAAY,CAAC,QAAQ;gBAAE,OAAO;YAClC,iBAAiB,GAAG,YAAY,CAAC,OAAO,CAAC,2BAA2B,IAAI,IAAI,CAAC;YAC7E,MAAM,EAAE,CAAC;YACT,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,CAAC,wCAAwC,CAAC,EAAE,CAAC;YAC7D,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,sBAAsB,EAAE,CAAC;YAC3C,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,OAAO,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/B,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,KAAY,EAAQ,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,YAAY,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7E,IAAI,KAAK,EAAE,OAAO,CAAC,2BAA2B,IAAI,IAAI;YAAE,OAAO;QAC/D,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACpB,MAAM,EAAE,CAAC;IACX,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,KAAoB,EAAQ,EAAE;QAC/C,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;YAAE,OAAO;QACjD,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,KAAK,EAAE,CAAC;IACV,CAAC,CAAC;IAEF,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxC,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,OAAO;QACL,MAAM;YACJ,OAAO,CAAC,CAAC,SAAS,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,KAAK;YACR,SAAS,GAAG;gBACV,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,SAAS,CAAC;gBAC5D,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC;YACF,KAAK,GAAG,EAAE,CAAC;YACX,iBAAiB,GAAG,IAAI,CAAC;YACzB,cAAc,GAAG,IAAI,CAAC;YACtB,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAClD,OAAO,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC;YAC7B,MAAM,EAAE,CAAC;YACT,UAAU,CAAC,GAAG,EAAE;gBACd,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtC,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC;QACD,KAAK;QACL,QAAQ,CAAC,KAAK;YACZ,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,OAAO;YACL,KAAK,EAAE,CAAC;YACR,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC3C,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC3C,GAAG,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,KAAoC,EACpC,SAA4B,EAC5B,QAAgB;IAEhB,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;QACnC,UAAU,EAAE,SAAS;QACrB,QAAQ;QACR,SAAS,EAAE,QAAQ;KACpB,CAAC,CAAC;IACH,IAAI,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,UAAU,CAAC;IACtE,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IACnE,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IACvD,OAAO,KAAK,CAAC,WAAW,CAAC;QACvB,UAAU,EAAE,kBAAkB;QAC9B,QAAQ;QACR,SAAS,EAAE,QAAQ;KACpB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,0BAA0B,CAAC,MAA0B;IAC5D,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,MAAM,KAAK,YAAY;QAAE,OAAO,yCAAyC,CAAC;IAC9E,IAAI,MAAM,KAAK,wBAAwB;QAAE,OAAO,qCAAqC,CAAC;IACtF,IAAI,MAAM,KAAK,gBAAgB;QAAE,OAAO,0BAA0B,CAAC;IACnE,IAAI,MAAM,KAAK,qBAAqB;QAAE,OAAO,0BAA0B,CAAC;IACxE,IAAI,MAAM,KAAK,2BAA2B;QAAE,OAAO,wCAAwC,CAAC;IAC5F,IAAI,MAAM,KAAK,6BAA6B;QAAE,OAAO,oCAAoC,CAAC;IAC1F,IAAI,MAAM,KAAK,qBAAqB;QAAE,OAAO,iCAAiC,CAAC;IAC/E,IAAI,MAAM,KAAK,oBAAoB;QAAE,OAAO,yCAAyC,CAAC;IACtF,IAAI,MAAM,KAAK,sBAAsB;QAAE,OAAO,8BAA8B,CAAC;IAC7E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,OAAoB;IACxC,OAAO,OAAO,CAAC,UAAU;QAAE,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;AACzD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"local-editor-ui-hierarchy-controller.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-controller.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AACtF,OAAO,KAAK,EAGV,oDAAoD,EACpD,6BAA6B,EAC7B,yBAAyB,EAE1B,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,8BAA8B,CAAC,SAAS,GAAG,OAAO;IACjE,MAAM,CAAC,KAAK,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC1D,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAClD,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IACpD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,qCAAqC,CAAC,SAAS,GAAG,OAAO;IACxE,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,6BAA6B,CAAC;IACzC,WAAW,EAAE,+BAA+B,CAAC;IAC7C,WAAW,EAAE,gCAAgC,CAAC;IAC9C,QAAQ,EAAE,MAAM,yBAAyB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC5D,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,IAAI,CAAC;IACrC,cAAc,CAAC,EAAE,SAAS,oDAAoD,CAAC,SAAS,CAAC,EAAE,CAAC;CAC7F;AAED,wBAAgB,oCAAoC,CAAC,SAAS,GAAG,OAAO,EACtE,OAAO,EAAE,qCAAqC,CAAC,SAAS,CAAC,GACxD,8BAA8B,CAAC,SAAS,CAAC,CAm4B3C"}
1
+ {"version":3,"file":"local-editor-ui-hierarchy-controller.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-controller.ts"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AACtF,OAAO,KAAK,EAGV,oDAAoD,EACpD,6BAA6B,EAC7B,yBAAyB,EAE1B,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,8BAA8B,CAAC,SAAS,GAAG,OAAO;IACjE,MAAM,CAAC,KAAK,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC1D,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAClD,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IACpD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,qCAAqC,CAAC,SAAS,GAAG,OAAO;IACxE,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,6BAA6B,CAAC;IACzC,WAAW,EAAE,+BAA+B,CAAC;IAC7C,WAAW,EAAE,gCAAgC,CAAC;IAC9C,QAAQ,EAAE,MAAM,yBAAyB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC5D,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,IAAI,CAAC;IACrC,cAAc,CAAC,EAAE,SAAS,oDAAoD,CAAC,SAAS,CAAC,EAAE,CAAC;CAC7F;AAED,wBAAgB,oCAAoC,CAAC,SAAS,GAAG,OAAO,EACtE,OAAO,EAAE,qCAAqC,CAAC,SAAS,CAAC,GACxD,8BAA8B,CAAC,SAAS,CAAC,CA47B3C"}
@@ -5,6 +5,7 @@ import { resolveLocalEditorHierarchyAutoScroll, } from './local-editor-ui-hierar
5
5
  import { clearLocalEditorStructuredDragSession, createLocalEditorStructuredDragSession, hasLocalEditorStructuredDragSessionFeedback, } from './local-editor-ui-structured-drag-session.js';
6
6
  import { renderLocalEditorHierarchyPanel, syncLocalEditorHierarchyDropPreview, } from './local-editor-ui-hierarchy-view.js';
7
7
  import { createLocalEditorViewportRevealController, } from './local-editor-ui-dock-panel.js';
8
+ import { createLocalEditorHierarchyAttachDialog, } from './local-editor-ui-hierarchy-attach-dialog.js';
8
9
  const HIERARCHY_DRAG_INDENT_WIDTH = 16;
9
10
  export function createLocalEditorHierarchyController(options) {
10
11
  const { doc, panel, callbacks, inputRouter, contextMenu, getState, requestRender } = options;
@@ -22,6 +23,12 @@ export function createLocalEditorHierarchyController(options) {
22
23
  let lastRenderedActiveId;
23
24
  let pendingHierarchyScrollId = null;
24
25
  let hierarchySelectionAnchorId = null;
26
+ const attachDialog = createLocalEditorHierarchyAttachDialog({
27
+ doc,
28
+ getTheme: resolveActiveTheme,
29
+ onOpenChange: open => inputRouter.setModalOpen(open, 'hierarchy-attach'),
30
+ onConfirm: selection => submitAttachSelection(selection),
31
+ });
25
32
  const treeViewportReveal = createLocalEditorViewportRevealController({
26
33
  getViewport: findHierarchyTreeViewport,
27
34
  margin: 4,
@@ -355,6 +362,7 @@ export function createLocalEditorHierarchyController(options) {
355
362
  panel.removeEventListener('drop', onDrop);
356
363
  doc.removeEventListener('pointerdown', onDocumentPointerDown, { capture: true });
357
364
  doc.removeEventListener('focusin', onDocumentFocusIn, { capture: true });
365
+ attachDialog.dispose();
358
366
  },
359
367
  };
360
368
  function handleDeleteShortcut(event) {
@@ -730,6 +738,7 @@ export function createLocalEditorHierarchyController(options) {
730
738
  clipboardIds: hierarchyClipboard?.ids ?? null,
731
739
  clipboardActiveId: hierarchyClipboard?.activeId ?? null,
732
740
  hasDuplicateHandler: hasDuplicateHandler(),
741
+ hasMoveHandler: typeof callbacks.onSceneGraphMove === 'function',
733
742
  hasGroupSelectionHandler: typeof callbacks.onSceneGraphGroupSelection === 'function',
734
743
  contextActions: options.contextActions,
735
744
  })
@@ -739,6 +748,7 @@ export function createLocalEditorHierarchyController(options) {
739
748
  clipboardIds: hierarchyClipboard?.ids ?? null,
740
749
  clipboardActiveId: hierarchyClipboard?.activeId ?? null,
741
750
  hasDuplicateHandler: hasDuplicateHandler(),
751
+ hasMoveHandler: typeof callbacks.onSceneGraphMove === 'function',
742
752
  hasGroupSelectionHandler: typeof callbacks.onSceneGraphGroupSelection === 'function',
743
753
  contextActions: options.contextActions,
744
754
  });
@@ -773,6 +783,10 @@ export function createLocalEditorHierarchyController(options) {
773
783
  callbacks.onSceneGraphGroupSelection?.(action.intent);
774
784
  return;
775
785
  }
786
+ if (action.kind === 'open-attach-picker') {
787
+ openAttachPicker(action.targetIds, action.activeId);
788
+ return;
789
+ }
776
790
  if (action.kind === 'selection-command') {
777
791
  submitSelectionCommand(action.command);
778
792
  return;
@@ -782,6 +796,46 @@ export function createLocalEditorHierarchyController(options) {
782
796
  function submitSelectionCommand(command) {
783
797
  callbacks.onSelectionCommand?.(command);
784
798
  }
799
+ function openAttachPicker(targetIds, activeId) {
800
+ const state = getState();
801
+ if (!state || state.mode !== 'editor' || state.busy || targetIds.length === 0)
802
+ return;
803
+ attachDialog.open({
804
+ model: getModel(state),
805
+ targetIds,
806
+ activeId,
807
+ });
808
+ }
809
+ function submitAttachSelection(selection) {
810
+ const state = getState();
811
+ if (!state || state.mode !== 'editor' || state.busy)
812
+ return;
813
+ const ids = selection.resolution.draggedIds;
814
+ if (ids.length === 0)
815
+ return;
816
+ if (selection.placement === 'root') {
817
+ callbacks.onSceneGraphMove?.({
818
+ ids,
819
+ placement: 'root',
820
+ preserveWorldTransform: true,
821
+ });
822
+ requestRender();
823
+ return;
824
+ }
825
+ if (!selection.targetId)
826
+ return;
827
+ expandNode(selection.targetId);
828
+ callbacks.onSceneGraphMove?.({
829
+ ids,
830
+ targetId: selection.targetId,
831
+ placement: 'inside',
832
+ parentId: selection.resolution.parentId,
833
+ beforeId: selection.resolution.beforeId,
834
+ afterId: selection.resolution.afterId,
835
+ preserveWorldTransform: true,
836
+ });
837
+ requestRender();
838
+ }
785
839
  function shouldClearSelectionFromBlankClick(event, target) {
786
840
  if (event.button !== 0 || event.shiftKey || event.metaKey || event.ctrlKey || event.altKey)
787
841
  return false;
@@ -860,6 +914,11 @@ export function createLocalEditorHierarchyController(options) {
860
914
  function hasDuplicateHandler() {
861
915
  return typeof callbacks.onSceneGraphDuplicate === 'function';
862
916
  }
917
+ function resolveActiveTheme() {
918
+ const themed = panel.closest('.fps-editor-workbench[data-fps-editor-theme]');
919
+ const theme = themed?.dataset.fpsEditorTheme;
920
+ return theme === 'light' || theme === 'dark' ? theme : undefined;
921
+ }
863
922
  function beginHierarchyRename(id) {
864
923
  const state = getState();
865
924
  const model = state ? getModel(state) : null;