@fps-games/editor 0.2.0-beta.3 → 0.2.0-beta.4

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 (116) hide show
  1. package/dist/agent-bridge/capabilities/editor-state.d.ts.map +1 -1
  2. package/dist/agent-bridge/capabilities/editor-state.js +26 -17
  3. package/dist/agent-bridge/capabilities/editor-state.js.map +1 -1
  4. package/dist/agent-bridge/capabilities/prefabs.d.ts.map +1 -1
  5. package/dist/agent-bridge/capabilities/prefabs.js +61 -13
  6. package/dist/agent-bridge/capabilities/prefabs.js.map +1 -1
  7. package/dist/agent-bridge/capabilities/scene-objects.d.ts +1 -1
  8. package/dist/agent-bridge/capabilities/scene-objects.d.ts.map +1 -1
  9. package/dist/agent-bridge/capabilities/scene-objects.js +110 -25
  10. package/dist/agent-bridge/capabilities/scene-objects.js.map +1 -1
  11. package/dist/agent-bridge/capabilities/selection.d.ts.map +1 -1
  12. package/dist/agent-bridge/capabilities/selection.js +8 -5
  13. package/dist/agent-bridge/capabilities/selection.js.map +1 -1
  14. package/dist/agent-bridge/capabilities/shadows.d.ts.map +1 -1
  15. package/dist/agent-bridge/capabilities/shadows.js +11 -2
  16. package/dist/agent-bridge/capabilities/shadows.js.map +1 -1
  17. package/dist/agent-bridge/capabilities/transform.d.ts.map +1 -1
  18. package/dist/agent-bridge/capabilities/transform.js +6 -4
  19. package/dist/agent-bridge/capabilities/transform.js.map +1 -1
  20. package/dist/agent-bridge/capabilities/viewport.d.ts.map +1 -1
  21. package/dist/agent-bridge/capabilities/viewport.js +79 -47
  22. package/dist/agent-bridge/capabilities/viewport.js.map +1 -1
  23. package/dist/agent-bridge/shared.d.ts +8 -3
  24. package/dist/agent-bridge/shared.d.ts.map +1 -1
  25. package/dist/agent-bridge/shared.js +32 -0
  26. package/dist/agent-bridge/shared.js.map +1 -1
  27. package/dist/build-info.json +34 -34
  28. package/dist/local-editor-agent-actions.d.ts.map +1 -1
  29. package/dist/local-editor-agent-actions.js +9 -5
  30. package/dist/local-editor-agent-actions.js.map +1 -1
  31. package/dist/local-editor-harness.d.ts.map +1 -1
  32. package/dist/local-editor-harness.js +264 -41
  33. package/dist/local-editor-harness.js.map +1 -1
  34. package/node_modules/@fps-games/babylon-renderer/package.json +7 -7
  35. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  36. package/node_modules/@fps-games/editor-browser/dist/index.d.ts +3 -1
  37. package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
  38. package/node_modules/@fps-games/editor-browser/dist/index.js +2 -0
  39. package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
  40. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts +2 -1
  41. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts.map +1 -1
  42. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js +260 -94
  43. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js.map +1 -1
  44. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-projection.d.ts +7 -0
  45. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-projection.d.ts.map +1 -0
  46. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-projection.js +186 -0
  47. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-projection.js.map +1 -0
  48. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.d.ts +2 -2
  49. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.d.ts.map +1 -1
  50. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.js +14 -8
  51. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.js.map +1 -1
  52. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
  53. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js +23 -7
  54. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js.map +1 -1
  55. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
  56. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
  57. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +6 -0
  58. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
  59. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.d.ts +3 -0
  60. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.d.ts.map +1 -1
  61. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.js +60 -13
  62. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-input-router.js.map +1 -1
  63. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-status-diagnostics.d.ts +24 -0
  64. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-status-diagnostics.d.ts.map +1 -0
  65. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-status-diagnostics.js +69 -0
  66. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-status-diagnostics.js.map +1 -0
  67. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +58 -14
  68. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
  69. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.js.map +1 -1
  70. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +1 -1
  71. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  72. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +196 -11
  73. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  74. package/node_modules/@fps-games/editor-browser/package.json +4 -4
  75. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +3 -0
  76. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
  77. package/node_modules/@fps-games/editor-core/dist/editor-session.js +9 -0
  78. package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
  79. package/node_modules/@fps-games/editor-core/package.json +6 -6
  80. package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
  81. package/node_modules/@fps-games/editor-playable-sdk/package.json +6 -6
  82. package/node_modules/@fps-games/editor-protocol/package.json +2 -2
  83. package/node_modules/@fps-games/editor-tooling/package.json +3 -3
  84. package/node_modules/@fps-games/playable-assets/package.json +1 -1
  85. package/node_modules/@fps-games/playable-contracts/package.json +1 -1
  86. package/node_modules/@fps-games/playable-rendering/package.json +2 -2
  87. package/node_modules/@fps-games/playable-runtime/package.json +12 -12
  88. package/node_modules/@fps-games/playable-runtime-data/package.json +4 -4
  89. package/node_modules/@fps-games/playable-scene/package.json +2 -2
  90. package/node_modules/@fps-games/plugin-api/package.json +1 -1
  91. package/node_modules/@fps-games/plugin-assets/dist/version.d.ts +1 -1
  92. package/node_modules/@fps-games/plugin-assets/dist/version.js +1 -1
  93. package/node_modules/@fps-games/plugin-assets/dist/version.js.map +1 -1
  94. package/node_modules/@fps-games/plugin-assets/package.json +5 -5
  95. package/node_modules/@fps-games/plugin-host/package.json +2 -2
  96. package/node_modules/@fps-games/plugin-markers/dist/version.d.ts +1 -1
  97. package/node_modules/@fps-games/plugin-markers/dist/version.js +1 -1
  98. package/node_modules/@fps-games/plugin-markers/dist/version.js.map +1 -1
  99. package/node_modules/@fps-games/plugin-markers/package.json +5 -5
  100. package/node_modules/@fps-games/plugin-materials/dist/version.d.ts +1 -1
  101. package/node_modules/@fps-games/plugin-materials/dist/version.js +1 -1
  102. package/node_modules/@fps-games/plugin-materials/dist/version.js.map +1 -1
  103. package/node_modules/@fps-games/plugin-materials/package.json +5 -5
  104. package/node_modules/@fps-games/plugin-rendering/dist/version.d.ts +1 -1
  105. package/node_modules/@fps-games/plugin-rendering/dist/version.js +1 -1
  106. package/node_modules/@fps-games/plugin-rendering/dist/version.js.map +1 -1
  107. package/node_modules/@fps-games/plugin-rendering/package.json +5 -5
  108. package/node_modules/@fps-games/plugin-scene/dist/version.d.ts +1 -1
  109. package/node_modules/@fps-games/plugin-scene/dist/version.js +1 -1
  110. package/node_modules/@fps-games/plugin-scene/dist/version.js.map +1 -1
  111. package/node_modules/@fps-games/plugin-scene/package.json +5 -5
  112. package/node_modules/@fps-games/plugin-shadows/dist/version.d.ts +1 -1
  113. package/node_modules/@fps-games/plugin-shadows/dist/version.js +1 -1
  114. package/node_modules/@fps-games/plugin-shadows/dist/version.js.map +1 -1
  115. package/node_modules/@fps-games/plugin-shadows/package.json +7 -7
  116. package/package.json +19 -19
@@ -0,0 +1,186 @@
1
+ export function isLocalEditorHierarchyCommandPreconditionCurrent(precondition, expected) {
2
+ return precondition.scopeId === expected.scopeId
3
+ && precondition.documentRevision === expected.documentRevision
4
+ && precondition.projectionRevision === expected.projectionRevision;
5
+ }
6
+ export function isLocalEditorHierarchyProjectionCurrent(projection, scope) {
7
+ return projection?.scopeId === scope.scopeId
8
+ && projection.documentRevision === scope.documentRevision
9
+ && projection.projectionRevision === scope.projectionRevision;
10
+ }
11
+ export function createLocalEditorHierarchyProjection(scope) {
12
+ const diagnostics = [];
13
+ const rowsById = new Map();
14
+ const duplicateRowIds = new Set();
15
+ for (const node of scope.nodes) {
16
+ if (rowsById.has(node.id)) {
17
+ duplicateRowIds.add(node.id);
18
+ diagnostics.push(createDiagnostic(scope, {
19
+ code: 'hierarchy-row-id-duplicate',
20
+ severity: 'error',
21
+ message: `Hierarchy row ID is duplicated: ${node.id}`,
22
+ rowId: node.id,
23
+ }));
24
+ continue;
25
+ }
26
+ rowsById.set(node.id, node);
27
+ }
28
+ const invalidIds = new Set(duplicateRowIds);
29
+ for (const duplicateRowId of duplicateRowIds)
30
+ rowsById.delete(duplicateRowId);
31
+ for (const node of scope.nodes) {
32
+ if (invalidIds.has(node.id))
33
+ continue;
34
+ if (node.parentId != null && !rowsById.has(node.parentId)) {
35
+ invalidIds.add(node.id);
36
+ diagnostics.push(createDiagnostic(scope, {
37
+ code: 'hierarchy-parent-missing',
38
+ severity: 'error',
39
+ message: `Hierarchy row ${node.id} references missing parent ${node.parentId}.`,
40
+ rowId: node.id,
41
+ targetId: node.parentId,
42
+ }));
43
+ }
44
+ }
45
+ for (const node of scope.nodes) {
46
+ const path = new Set();
47
+ let cursor = node;
48
+ while (cursor?.parentId != null) {
49
+ if (path.has(cursor.id)) {
50
+ for (const id of path)
51
+ invalidIds.add(id);
52
+ diagnostics.push(createDiagnostic(scope, {
53
+ code: 'hierarchy-parent-cycle',
54
+ severity: 'error',
55
+ message: `Hierarchy parent cycle includes row ${cursor.id}.`,
56
+ rowId: cursor.id,
57
+ }));
58
+ break;
59
+ }
60
+ path.add(cursor.id);
61
+ cursor = rowsById.get(cursor.parentId);
62
+ }
63
+ }
64
+ propagateInvalidDescendants(scope.nodes, invalidIds);
65
+ const targets = [];
66
+ const targetRows = new Map();
67
+ for (const node of scope.nodes) {
68
+ if (invalidIds.has(node.id))
69
+ continue;
70
+ const targetId = node.commandTargetId?.trim();
71
+ if (!targetId) {
72
+ if (node.commandable === false)
73
+ continue;
74
+ invalidIds.add(node.id);
75
+ diagnostics.push(createDiagnostic(scope, {
76
+ code: 'hierarchy-command-target-missing',
77
+ severity: 'error',
78
+ message: `Hierarchy row ${node.id} has no command target.`,
79
+ rowId: node.id,
80
+ }));
81
+ continue;
82
+ }
83
+ const rows = targetRows.get(targetId) ?? [];
84
+ rows.push(node.id);
85
+ targetRows.set(targetId, rows);
86
+ targets.push({
87
+ rowId: node.id,
88
+ targetId,
89
+ targetKind: node.sourceKind ?? node.role ?? 'object',
90
+ });
91
+ }
92
+ for (const [targetId, rowIds] of targetRows) {
93
+ if (rowIds.length < 2)
94
+ continue;
95
+ for (const rowId of rowIds)
96
+ invalidIds.add(rowId);
97
+ diagnostics.push(createDiagnostic(scope, {
98
+ code: 'hierarchy-command-target-duplicate',
99
+ severity: 'error',
100
+ message: `Hierarchy command target ${targetId} is shared by rows: ${rowIds.join(', ')}.`,
101
+ targetId,
102
+ details: { rowIds },
103
+ }));
104
+ }
105
+ propagateInvalidDescendants(scope.nodes, invalidIds);
106
+ const nodes = scope.nodes.filter(node => !invalidIds.has(node.id));
107
+ const nodeIds = new Set(nodes.map(node => node.id));
108
+ const selectedIds = scope.selectedIds.filter(id => nodeIds.has(id));
109
+ const activeId = scope.activeId && selectedIds.includes(scope.activeId)
110
+ ? scope.activeId
111
+ : selectedIds[selectedIds.length - 1] ?? null;
112
+ const staleSelectionIds = scope.selectedIds.filter(id => !nodeIds.has(id));
113
+ if (staleSelectionIds.length > 0 || scope.activeId !== activeId) {
114
+ diagnostics.push(createDiagnostic(scope, {
115
+ code: 'hierarchy-selection-stale',
116
+ severity: 'warning',
117
+ message: `Hierarchy selection referenced unavailable rows: ${staleSelectionIds.join(', ') || scope.activeId}.`,
118
+ details: { selectedIds: scope.selectedIds, activeId: scope.activeId },
119
+ }));
120
+ }
121
+ return createProjectionResult(scope, nodes, targets.filter(target => nodeIds.has(target.rowId)), diagnostics, true, selectedIds, activeId);
122
+ }
123
+ export function formatLocalEditorStatusDiagnostic(diagnostic) {
124
+ const location = [diagnostic.scopeId, diagnostic.rowId, diagnostic.targetId]
125
+ .filter(Boolean)
126
+ .join(' / ');
127
+ return [
128
+ `[${diagnostic.severity.toUpperCase()}] ${diagnostic.code}`,
129
+ diagnostic.message,
130
+ `Source: ${diagnostic.source}`,
131
+ location ? `Location: ${location}` : '',
132
+ diagnostic.documentRevision != null ? `Document revision: ${diagnostic.documentRevision}` : '',
133
+ diagnostic.projectionRevision != null ? `Projection revision: ${diagnostic.projectionRevision}` : '',
134
+ diagnostic.details ? `Details: ${formatLocalEditorStatusDiagnosticDetails(diagnostic.details)}` : '',
135
+ ].filter(Boolean).join('\n');
136
+ }
137
+ export function formatLocalEditorStatusDiagnosticDetails(details) {
138
+ try {
139
+ return JSON.stringify(details);
140
+ }
141
+ catch {
142
+ return '[unserializable details]';
143
+ }
144
+ }
145
+ function createProjectionResult(scope, nodes, targets, diagnostics, interactive, selectedIds = [], activeId = null) {
146
+ const health = diagnostics.some(item => item.severity === 'error')
147
+ ? 'error'
148
+ : diagnostics.length > 0
149
+ ? 'warning'
150
+ : 'healthy';
151
+ return {
152
+ scopeId: scope.scopeId,
153
+ scopeKind: scope.kind,
154
+ documentRevision: scope.documentRevision,
155
+ projectionRevision: scope.projectionRevision,
156
+ health,
157
+ interactive: interactive && (health !== 'error' || nodes.length > 0),
158
+ nodes,
159
+ selectedIds,
160
+ activeId,
161
+ targets,
162
+ diagnostics,
163
+ };
164
+ }
165
+ function createDiagnostic(scope, input) {
166
+ return {
167
+ ...input,
168
+ source: 'hierarchy-projection',
169
+ scopeId: scope.scopeId,
170
+ documentRevision: scope.documentRevision,
171
+ projectionRevision: scope.projectionRevision,
172
+ };
173
+ }
174
+ function propagateInvalidDescendants(nodes, invalidIds) {
175
+ let changed = true;
176
+ while (changed) {
177
+ changed = false;
178
+ for (const node of nodes) {
179
+ if (invalidIds.has(node.id) || !node.parentId || !invalidIds.has(node.parentId))
180
+ continue;
181
+ invalidIds.add(node.id);
182
+ changed = true;
183
+ }
184
+ }
185
+ }
186
+ //# sourceMappingURL=local-editor-ui-hierarchy-projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-editor-ui-hierarchy-projection.js","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-projection.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n LocalEditorBrowserHierarchyCommandPrecondition,\n LocalEditorBrowserHierarchyProjectionState,\n LocalEditorBrowserHierarchyProjectionTarget,\n LocalEditorBrowserHierarchyScope,\n LocalEditorBrowserHierarchyScopeNode,\n LocalEditorBrowserStatusDiagnostic,\n} from './local-editor-ui-types';\n\nexport function isLocalEditorHierarchyCommandPreconditionCurrent(\n precondition: LocalEditorBrowserHierarchyCommandPrecondition,\n expected: LocalEditorBrowserHierarchyCommandPrecondition,\n): boolean {\n return precondition.scopeId === expected.scopeId\n && precondition.documentRevision === expected.documentRevision\n && precondition.projectionRevision === expected.projectionRevision;\n}\n\nexport function isLocalEditorHierarchyProjectionCurrent(\n projection: LocalEditorBrowserHierarchyProjectionState | null | undefined,\n scope: LocalEditorBrowserHierarchyScope,\n): projection is LocalEditorBrowserHierarchyProjectionState {\n return projection?.scopeId === scope.scopeId\n && projection.documentRevision === scope.documentRevision\n && projection.projectionRevision === scope.projectionRevision;\n}\n\nexport function createLocalEditorHierarchyProjection(\n scope: LocalEditorBrowserHierarchyScope,\n): LocalEditorBrowserHierarchyProjectionState {\n const diagnostics: LocalEditorBrowserStatusDiagnostic[] = [];\n const rowsById = new Map<string, LocalEditorBrowserHierarchyScopeNode>();\n const duplicateRowIds = new Set<string>();\n\n for (const node of scope.nodes) {\n if (rowsById.has(node.id)) {\n duplicateRowIds.add(node.id);\n diagnostics.push(createDiagnostic(scope, {\n code: 'hierarchy-row-id-duplicate',\n severity: 'error',\n message: `Hierarchy row ID is duplicated: ${node.id}`,\n rowId: node.id,\n }));\n continue;\n }\n rowsById.set(node.id, node);\n }\n\n const invalidIds = new Set<string>(duplicateRowIds);\n for (const duplicateRowId of duplicateRowIds) rowsById.delete(duplicateRowId);\n for (const node of scope.nodes) {\n if (invalidIds.has(node.id)) continue;\n if (node.parentId != null && !rowsById.has(node.parentId)) {\n invalidIds.add(node.id);\n diagnostics.push(createDiagnostic(scope, {\n code: 'hierarchy-parent-missing',\n severity: 'error',\n message: `Hierarchy row ${node.id} references missing parent ${node.parentId}.`,\n rowId: node.id,\n targetId: node.parentId,\n }));\n }\n }\n\n for (const node of scope.nodes) {\n const path = new Set<string>();\n let cursor: LocalEditorBrowserHierarchyScopeNode | undefined = node;\n while (cursor?.parentId != null) {\n if (path.has(cursor.id)) {\n for (const id of path) invalidIds.add(id);\n diagnostics.push(createDiagnostic(scope, {\n code: 'hierarchy-parent-cycle',\n severity: 'error',\n message: `Hierarchy parent cycle includes row ${cursor.id}.`,\n rowId: cursor.id,\n }));\n break;\n }\n path.add(cursor.id);\n cursor = rowsById.get(cursor.parentId);\n }\n }\n\n propagateInvalidDescendants(scope.nodes, invalidIds);\n\n const targets: LocalEditorBrowserHierarchyProjectionTarget[] = [];\n const targetRows = new Map<string, string[]>();\n for (const node of scope.nodes) {\n if (invalidIds.has(node.id)) continue;\n const targetId = node.commandTargetId?.trim();\n if (!targetId) {\n if (node.commandable === false) continue;\n invalidIds.add(node.id);\n diagnostics.push(createDiagnostic(scope, {\n code: 'hierarchy-command-target-missing',\n severity: 'error',\n message: `Hierarchy row ${node.id} has no command target.`,\n rowId: node.id,\n }));\n continue;\n }\n const rows = targetRows.get(targetId) ?? [];\n rows.push(node.id);\n targetRows.set(targetId, rows);\n targets.push({\n rowId: node.id,\n targetId,\n targetKind: node.sourceKind ?? node.role ?? 'object',\n });\n }\n\n for (const [targetId, rowIds] of targetRows) {\n if (rowIds.length < 2) continue;\n for (const rowId of rowIds) invalidIds.add(rowId);\n diagnostics.push(createDiagnostic(scope, {\n code: 'hierarchy-command-target-duplicate',\n severity: 'error',\n message: `Hierarchy command target ${targetId} is shared by rows: ${rowIds.join(', ')}.`,\n targetId,\n details: { rowIds },\n }));\n }\n\n propagateInvalidDescendants(scope.nodes, invalidIds);\n const nodes = scope.nodes.filter(node => !invalidIds.has(node.id));\n const nodeIds = new Set(nodes.map(node => node.id));\n const selectedIds = scope.selectedIds.filter(id => nodeIds.has(id));\n const activeId = scope.activeId && selectedIds.includes(scope.activeId)\n ? scope.activeId\n : selectedIds[selectedIds.length - 1] ?? null;\n const staleSelectionIds = scope.selectedIds.filter(id => !nodeIds.has(id));\n if (staleSelectionIds.length > 0 || scope.activeId !== activeId) {\n diagnostics.push(createDiagnostic(scope, {\n code: 'hierarchy-selection-stale',\n severity: 'warning',\n message: `Hierarchy selection referenced unavailable rows: ${staleSelectionIds.join(', ') || scope.activeId}.`,\n details: { selectedIds: scope.selectedIds, activeId: scope.activeId },\n }));\n }\n\n return createProjectionResult(\n scope,\n nodes,\n targets.filter(target => nodeIds.has(target.rowId)),\n diagnostics,\n true,\n selectedIds,\n activeId,\n );\n}\n\nexport function formatLocalEditorStatusDiagnostic(\n diagnostic: LocalEditorBrowserStatusDiagnostic,\n): string {\n const location = [diagnostic.scopeId, diagnostic.rowId, diagnostic.targetId]\n .filter(Boolean)\n .join(' / ');\n return [\n `[${diagnostic.severity.toUpperCase()}] ${diagnostic.code}`,\n diagnostic.message,\n `Source: ${diagnostic.source}`,\n location ? `Location: ${location}` : '',\n diagnostic.documentRevision != null ? `Document revision: ${diagnostic.documentRevision}` : '',\n diagnostic.projectionRevision != null ? `Projection revision: ${diagnostic.projectionRevision}` : '',\n diagnostic.details ? `Details: ${formatLocalEditorStatusDiagnosticDetails(diagnostic.details)}` : '',\n ].filter(Boolean).join('\\n');\n}\n\nexport function formatLocalEditorStatusDiagnosticDetails(details: Record<string, unknown>): string {\n try {\n return JSON.stringify(details);\n } catch {\n return '[unserializable details]';\n }\n}\n\nfunction createProjectionResult(\n scope: LocalEditorBrowserHierarchyScope,\n nodes: LocalEditorBrowserHierarchyScopeNode[],\n targets: LocalEditorBrowserHierarchyProjectionTarget[],\n diagnostics: LocalEditorBrowserStatusDiagnostic[],\n interactive: boolean,\n selectedIds: string[] = [],\n activeId: string | null = null,\n): LocalEditorBrowserHierarchyProjectionState {\n const health = diagnostics.some(item => item.severity === 'error')\n ? 'error'\n : diagnostics.length > 0\n ? 'warning'\n : 'healthy';\n return {\n scopeId: scope.scopeId,\n scopeKind: scope.kind,\n documentRevision: scope.documentRevision,\n projectionRevision: scope.projectionRevision,\n health,\n interactive: interactive && (health !== 'error' || nodes.length > 0),\n nodes,\n selectedIds,\n activeId,\n targets,\n diagnostics,\n };\n}\n\nfunction createDiagnostic(\n scope: LocalEditorBrowserHierarchyScope,\n input: Omit<LocalEditorBrowserStatusDiagnostic, 'source' | 'scopeId' | 'documentRevision' | 'projectionRevision'>,\n): LocalEditorBrowserStatusDiagnostic {\n return {\n ...input,\n source: 'hierarchy-projection',\n scopeId: scope.scopeId,\n documentRevision: scope.documentRevision,\n projectionRevision: scope.projectionRevision,\n };\n}\n\nfunction propagateInvalidDescendants(\n nodes: readonly LocalEditorBrowserHierarchyScopeNode[],\n invalidIds: Set<string>,\n): void {\n let changed = true;\n while (changed) {\n changed = false;\n for (const node of nodes) {\n if (invalidIds.has(node.id) || !node.parentId || !invalidIds.has(node.parentId)) continue;\n invalidIds.add(node.id);\n changed = true;\n }\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { LocalEditorBrowserHierarchyScope, LocalEditorBrowserPrefabStageState, LocalEditorBrowserUiState } from './local-editor-ui-types';
2
- export declare function createLocalEditorSceneHierarchyScope<TDocument>(state: Pick<LocalEditorBrowserUiState<TDocument>, 'hierarchy' | 'selectedIds' | 'activeId'>): LocalEditorBrowserHierarchyScope;
3
- export declare function createLocalEditorPrefabStageHierarchyScope<TDocument>(stage: LocalEditorBrowserPrefabStageState<TDocument>): LocalEditorBrowserHierarchyScope;
2
+ export declare function createLocalEditorSceneHierarchyScope<TDocument>(state: Pick<LocalEditorBrowserUiState<TDocument>, 'hierarchy' | 'selectedIds' | 'activeId' | 'documentRevision' | 'hierarchyProjectionRevision'>): LocalEditorBrowserHierarchyScope;
3
+ export declare function createLocalEditorPrefabStageHierarchyScope<TDocument>(stage: LocalEditorBrowserPrefabStageState<TDocument>, documentRevision?: number, projectionRevision?: number): LocalEditorBrowserHierarchyScope;
4
4
  export declare function createLocalEditorActiveHierarchyScope<TDocument>(state: LocalEditorBrowserUiState<TDocument>): LocalEditorBrowserHierarchyScope;
5
5
  //# sourceMappingURL=local-editor-ui-hierarchy-scope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-editor-ui-hierarchy-scope.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gCAAgC,EAEhC,kCAAkC,EAGlC,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,oCAAoC,CAAC,SAAS,EAC5D,KAAK,EAAE,IAAI,CAAC,yBAAyB,CAAC,SAAS,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC,GAC1F,gCAAgC,CAYlC;AAaD,wBAAgB,0CAA0C,CAAC,SAAS,EAClE,KAAK,EAAE,kCAAkC,CAAC,SAAS,CAAC,GACnD,gCAAgC,CAiBlC;AAED,wBAAgB,qCAAqC,CAAC,SAAS,EAC7D,KAAK,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC1C,gCAAgC,CAIlC"}
1
+ {"version":3,"file":"local-editor-ui-hierarchy-scope.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gCAAgC,EAEhC,kCAAkC,EAGlC,yBAAyB,EAC1B,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,oCAAoC,CAAC,SAAS,EAC5D,KAAK,EAAE,IAAI,CAAC,yBAAyB,CAAC,SAAS,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,UAAU,GAAG,kBAAkB,GAAG,6BAA6B,CAAC,GAC/I,gCAAgC,CAgBlC;AAcD,wBAAgB,0CAA0C,CAAC,SAAS,EAClE,KAAK,EAAE,kCAAkC,CAAC,SAAS,CAAC,EACpD,gBAAgB,SAAI,EACpB,kBAAkB,SAAmB,GACpC,gCAAgC,CAiBlC;AAED,wBAAgB,qCAAqC,CAAC,SAAS,EAC7D,KAAK,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC1C,gCAAgC,CAQlC"}
@@ -1,4 +1,6 @@
1
1
  export function createLocalEditorSceneHierarchyScope(state) {
2
+ const revision = state.documentRevision ?? 0;
3
+ const projectionRevision = state.hierarchyProjectionRevision ?? revision;
2
4
  return {
3
5
  scopeId: 'scene',
4
6
  kind: 'scene',
@@ -9,25 +11,26 @@ export function createLocalEditorSceneHierarchyScope(state) {
9
11
  activeId: state.activeId,
10
12
  readonly: false,
11
13
  commandSurface: 'scene-graph',
14
+ documentRevision: revision,
15
+ projectionRevision,
12
16
  };
13
17
  }
14
18
  function mapSceneHierarchyItemToScopeNode(item) {
15
19
  if (item.protected !== true)
16
- return { ...item, scopeId: 'scene' };
20
+ return { ...item, scopeId: 'scene', commandTargetId: item.id };
17
21
  return {
18
22
  ...item,
19
23
  scopeId: 'scene',
20
24
  renamable: item.renamable ?? false,
21
25
  deletable: item.deletable ?? false,
22
26
  draggable: item.draggable ?? false,
27
+ commandTargetId: item.id,
23
28
  };
24
29
  }
25
- export function createLocalEditorPrefabStageHierarchyScope(stage) {
30
+ export function createLocalEditorPrefabStageHierarchyScope(stage, documentRevision = 0, projectionRevision = documentRevision) {
26
31
  const scopeId = `prefab-stage:${stage.assetId}`;
27
32
  const nodes = flattenPrefabStageStructureItems(stage.structureItems, scopeId, null, stage.readonly === true);
28
- const selectedIds = stage.selectedItemId && nodes.some(node => node.id === stage.selectedItemId)
29
- ? [stage.selectedItemId]
30
- : [];
33
+ const selectedIds = stage.selectedItemId ? [stage.selectedItemId] : [];
31
34
  return {
32
35
  scopeId,
33
36
  kind: 'prefab-stage',
@@ -38,11 +41,13 @@ export function createLocalEditorPrefabStageHierarchyScope(stage) {
38
41
  activeId: selectedIds[0] ?? null,
39
42
  readonly: stage.readonly === true,
40
43
  commandSurface: stage.readonly === true ? 'readonly' : 'prefab-composition',
44
+ documentRevision,
45
+ projectionRevision,
41
46
  };
42
47
  }
43
48
  export function createLocalEditorActiveHierarchyScope(state) {
44
49
  return state.prefabStage
45
- ? createLocalEditorPrefabStageHierarchyScope(state.prefabStage)
50
+ ? createLocalEditorPrefabStageHierarchyScope(state.prefabStage, state.documentRevision ?? 0, state.hierarchyProjectionRevision ?? state.documentRevision ?? 0)
46
51
  : createLocalEditorSceneHierarchyScope(state);
47
52
  }
48
53
  function flattenPrefabStageStructureItems(items, scopeId, parentId, stageReadonly) {
@@ -72,11 +77,12 @@ function mapPrefabStageStructureItemToHierarchyNode(item, scopeId, parentId, sta
72
77
  icon: item.icon,
73
78
  scopeId,
74
79
  sourceKind: item.kind,
75
- commandTargetId: item.nodeId,
80
+ commandTargetId: isRoot ? undefined : item.nodeId ?? item.id,
81
+ commandable: !isRoot,
76
82
  selectable: true,
77
83
  protected: false,
78
84
  locked: false,
79
- canHaveChildren: !readonly,
85
+ canHaveChildren: !readonly && !isRoot,
80
86
  renamable: canEdit,
81
87
  deletable: canEdit,
82
88
  draggable: canEdit,
@@ -1 +1 @@
1
- {"version":3,"file":"local-editor-ui-hierarchy-scope.js","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-scope.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n LocalEditorBrowserHierarchyScope,\n LocalEditorBrowserHierarchyScopeNode,\n LocalEditorBrowserPrefabStageState,\n LocalEditorBrowserPrefabStageStructureItem,\n LocalEditorBrowserUiHierarchyItem,\n LocalEditorBrowserUiState,\n} from './local-editor-ui-types';\n\nexport function createLocalEditorSceneHierarchyScope<TDocument>(\n state: Pick<LocalEditorBrowserUiState<TDocument>, 'hierarchy' | 'selectedIds' | 'activeId'>,\n): LocalEditorBrowserHierarchyScope {\n return {\n scopeId: 'scene',\n kind: 'scene',\n title: 'Hierarchy',\n searchPlaceholder: '搜索 GameObject 名称',\n nodes: state.hierarchy.map(mapSceneHierarchyItemToScopeNode),\n selectedIds: [...state.selectedIds],\n activeId: state.activeId,\n readonly: false,\n commandSurface: 'scene-graph',\n };\n}\n\nfunction mapSceneHierarchyItemToScopeNode(item: LocalEditorBrowserUiHierarchyItem): LocalEditorBrowserHierarchyScopeNode {\n if (item.protected !== true) return { ...item, scopeId: 'scene' };\n return {\n ...item,\n scopeId: 'scene',\n renamable: item.renamable ?? false,\n deletable: item.deletable ?? false,\n draggable: item.draggable ?? false,\n };\n}\n\nexport function createLocalEditorPrefabStageHierarchyScope<TDocument>(\n stage: LocalEditorBrowserPrefabStageState<TDocument>,\n): LocalEditorBrowserHierarchyScope {\n const scopeId = `prefab-stage:${stage.assetId}`;\n const nodes = flattenPrefabStageStructureItems(stage.structureItems, scopeId, null, stage.readonly === true);\n const selectedIds = stage.selectedItemId && nodes.some(node => node.id === stage.selectedItemId)\n ? [stage.selectedItemId]\n : [];\n return {\n scopeId,\n kind: 'prefab-stage',\n title: `Hierarchy / Prefab: ${stage.label}`,\n searchPlaceholder: 'Filter prefab nodes',\n nodes,\n selectedIds,\n activeId: selectedIds[0] ?? null,\n readonly: stage.readonly === true,\n commandSurface: stage.readonly === true ? 'readonly' : 'prefab-composition',\n };\n}\n\nexport function createLocalEditorActiveHierarchyScope<TDocument>(\n state: LocalEditorBrowserUiState<TDocument>,\n): LocalEditorBrowserHierarchyScope {\n return state.prefabStage\n ? createLocalEditorPrefabStageHierarchyScope(state.prefabStage)\n : createLocalEditorSceneHierarchyScope(state);\n}\n\nfunction flattenPrefabStageStructureItems(\n items: readonly LocalEditorBrowserPrefabStageStructureItem[],\n scopeId: string,\n parentId: string | null,\n stageReadonly: boolean,\n): LocalEditorBrowserHierarchyScopeNode[] {\n const nodes: LocalEditorBrowserHierarchyScopeNode[] = [];\n for (const item of items) {\n const includeItem = isPrefabStageHierarchyItem(item);\n const nextParentId = includeItem ? item.id : parentId;\n if (includeItem) {\n nodes.push(mapPrefabStageStructureItemToHierarchyNode(item, scopeId, parentId, stageReadonly));\n }\n nodes.push(...flattenPrefabStageStructureItems(item.children ?? [], scopeId, nextParentId, stageReadonly));\n }\n return nodes;\n}\n\nfunction isPrefabStageHierarchyItem(item: LocalEditorBrowserPrefabStageStructureItem): boolean {\n return item.kind === 'root' || item.itemType === 'prefab-node';\n}\n\nfunction mapPrefabStageStructureItemToHierarchyNode(\n item: LocalEditorBrowserPrefabStageStructureItem,\n scopeId: string,\n parentId: string | null,\n stageReadonly: boolean,\n): LocalEditorBrowserHierarchyScopeNode {\n const readonly = stageReadonly || item.readonly === true;\n const isRoot = item.kind === 'root';\n const canEdit = !readonly && !isRoot;\n return {\n id: item.id,\n label: item.label,\n parentId,\n role: mapPrefabStageStructureKindToHierarchyRole(item.kind),\n icon: item.icon,\n scopeId,\n sourceKind: item.kind,\n commandTargetId: item.nodeId,\n selectable: true,\n protected: false,\n locked: false,\n canHaveChildren: !readonly,\n renamable: canEdit,\n deletable: canEdit,\n draggable: canEdit,\n };\n}\n\nfunction mapPrefabStageStructureKindToHierarchyRole(\n kind: LocalEditorBrowserPrefabStageStructureItem['kind'],\n): LocalEditorBrowserUiHierarchyItem['role'] {\n if (kind === 'root') return 'root';\n if (kind === 'group') return 'group';\n return 'object';\n}\n"]}
1
+ {"version":3,"file":"local-editor-ui-hierarchy-scope.js","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-scope.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n LocalEditorBrowserHierarchyScope,\n LocalEditorBrowserHierarchyScopeNode,\n LocalEditorBrowserPrefabStageState,\n LocalEditorBrowserPrefabStageStructureItem,\n LocalEditorBrowserUiHierarchyItem,\n LocalEditorBrowserUiState,\n} from './local-editor-ui-types';\n\nexport function createLocalEditorSceneHierarchyScope<TDocument>(\n state: Pick<LocalEditorBrowserUiState<TDocument>, 'hierarchy' | 'selectedIds' | 'activeId' | 'documentRevision' | 'hierarchyProjectionRevision'>,\n): LocalEditorBrowserHierarchyScope {\n const revision = state.documentRevision ?? 0;\n const projectionRevision = state.hierarchyProjectionRevision ?? revision;\n return {\n scopeId: 'scene',\n kind: 'scene',\n title: 'Hierarchy',\n searchPlaceholder: '搜索 GameObject 名称',\n nodes: state.hierarchy.map(mapSceneHierarchyItemToScopeNode),\n selectedIds: [...state.selectedIds],\n activeId: state.activeId,\n readonly: false,\n commandSurface: 'scene-graph',\n documentRevision: revision,\n projectionRevision,\n };\n}\n\nfunction mapSceneHierarchyItemToScopeNode(item: LocalEditorBrowserUiHierarchyItem): LocalEditorBrowserHierarchyScopeNode {\n if (item.protected !== true) return { ...item, scopeId: 'scene', commandTargetId: item.id };\n return {\n ...item,\n scopeId: 'scene',\n renamable: item.renamable ?? false,\n deletable: item.deletable ?? false,\n draggable: item.draggable ?? false,\n commandTargetId: item.id,\n };\n}\n\nexport function createLocalEditorPrefabStageHierarchyScope<TDocument>(\n stage: LocalEditorBrowserPrefabStageState<TDocument>,\n documentRevision = 0,\n projectionRevision = documentRevision,\n): LocalEditorBrowserHierarchyScope {\n const scopeId = `prefab-stage:${stage.assetId}`;\n const nodes = flattenPrefabStageStructureItems(stage.structureItems, scopeId, null, stage.readonly === true);\n const selectedIds = stage.selectedItemId ? [stage.selectedItemId] : [];\n return {\n scopeId,\n kind: 'prefab-stage',\n title: `Hierarchy / Prefab: ${stage.label}`,\n searchPlaceholder: 'Filter prefab nodes',\n nodes,\n selectedIds,\n activeId: selectedIds[0] ?? null,\n readonly: stage.readonly === true,\n commandSurface: stage.readonly === true ? 'readonly' : 'prefab-composition',\n documentRevision,\n projectionRevision,\n };\n}\n\nexport function createLocalEditorActiveHierarchyScope<TDocument>(\n state: LocalEditorBrowserUiState<TDocument>,\n): LocalEditorBrowserHierarchyScope {\n return state.prefabStage\n ? createLocalEditorPrefabStageHierarchyScope(\n state.prefabStage,\n state.documentRevision ?? 0,\n state.hierarchyProjectionRevision ?? state.documentRevision ?? 0,\n )\n : createLocalEditorSceneHierarchyScope(state);\n}\n\nfunction flattenPrefabStageStructureItems(\n items: readonly LocalEditorBrowserPrefabStageStructureItem[],\n scopeId: string,\n parentId: string | null,\n stageReadonly: boolean,\n): LocalEditorBrowserHierarchyScopeNode[] {\n const nodes: LocalEditorBrowserHierarchyScopeNode[] = [];\n for (const item of items) {\n const includeItem = isPrefabStageHierarchyItem(item);\n const nextParentId = includeItem ? item.id : parentId;\n if (includeItem) {\n nodes.push(mapPrefabStageStructureItemToHierarchyNode(item, scopeId, parentId, stageReadonly));\n }\n nodes.push(...flattenPrefabStageStructureItems(item.children ?? [], scopeId, nextParentId, stageReadonly));\n }\n return nodes;\n}\n\nfunction isPrefabStageHierarchyItem(item: LocalEditorBrowserPrefabStageStructureItem): boolean {\n return item.kind === 'root' || item.itemType === 'prefab-node';\n}\n\nfunction mapPrefabStageStructureItemToHierarchyNode(\n item: LocalEditorBrowserPrefabStageStructureItem,\n scopeId: string,\n parentId: string | null,\n stageReadonly: boolean,\n): LocalEditorBrowserHierarchyScopeNode {\n const readonly = stageReadonly || item.readonly === true;\n const isRoot = item.kind === 'root';\n const canEdit = !readonly && !isRoot;\n return {\n id: item.id,\n label: item.label,\n parentId,\n role: mapPrefabStageStructureKindToHierarchyRole(item.kind),\n icon: item.icon,\n scopeId,\n sourceKind: item.kind,\n commandTargetId: isRoot ? undefined : item.nodeId ?? item.id,\n commandable: !isRoot,\n selectable: true,\n protected: false,\n locked: false,\n canHaveChildren: !readonly && !isRoot,\n renamable: canEdit,\n deletable: canEdit,\n draggable: canEdit,\n };\n}\n\nfunction mapPrefabStageStructureKindToHierarchyRole(\n kind: LocalEditorBrowserPrefabStageStructureItem['kind'],\n): LocalEditorBrowserUiHierarchyItem['role'] {\n if (kind === 'root') return 'root';\n if (kind === 'group') return 'group';\n return 'object';\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"local-editor-ui-hierarchy-tree.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-tree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local-editor-ui-hierarchy-tree.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-tree.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  export function createLocalEditorHierarchyTreeModel(items, selectedIds = [], activeId = null, options = {}) {
2
+ assertHierarchyTreeInput(items);
2
3
  const selected = new Set(selectedIds);
3
4
  const byRawId = new Map(items.map((item, inputIndex) => [item.id, { item, inputIndex }]));
4
5
  const childrenByParentId = new Map();
5
6
  const provisionalNodes = new Map();
6
7
  for (const { item, inputIndex } of byRawId.values()) {
7
- const parentId = item.parentId && byRawId.has(item.parentId) ? item.parentId : null;
8
+ const parentId = item.parentId ?? null;
8
9
  const role = resolveHierarchyNodeRole(item);
9
10
  provisionalNodes.set(item.id, {
10
11
  id: item.id,
@@ -67,12 +68,6 @@ export function createLocalEditorHierarchyTreeModel(items, selectedIds = [], act
67
68
  const rootIds = [...(childrenByParentId.get(null) ?? [])];
68
69
  for (const rootId of rootIds)
69
70
  appendNode(rootId, 0, true);
70
- for (const id of provisionalNodes.keys()) {
71
- if (visited.has(id))
72
- continue;
73
- rootIds.push(id);
74
- appendNode(id, 0, true);
75
- }
76
71
  const nodes = [...nodesById.values()].sort((a, b) => a.inputIndex - b.inputIndex);
77
72
  return {
78
73
  nodes,
@@ -140,6 +135,27 @@ export function createLocalEditorHierarchyTreeModel(items, selectedIds = [], act
140
135
  },
141
136
  };
142
137
  }
138
+ function assertHierarchyTreeInput(items) {
139
+ const ids = new Set();
140
+ for (const item of items) {
141
+ if (ids.has(item.id))
142
+ throw new Error(`hierarchy-row-id-duplicate:${item.id}`);
143
+ ids.add(item.id);
144
+ }
145
+ for (const item of items) {
146
+ if (item.parentId != null && !ids.has(item.parentId)) {
147
+ throw new Error(`hierarchy-parent-missing:${item.id}:${item.parentId}`);
148
+ }
149
+ const path = new Set();
150
+ let cursor = item;
151
+ while (cursor?.parentId != null) {
152
+ if (path.has(cursor.id))
153
+ throw new Error(`hierarchy-parent-cycle:${cursor.id}`);
154
+ path.add(cursor.id);
155
+ cursor = items.find(candidate => candidate.id === cursor?.parentId);
156
+ }
157
+ }
158
+ }
143
159
  export function isLocalEditorHierarchyNodeSelectable(node) {
144
160
  return !!node
145
161
  && node.item.selectable !== false
@@ -1 +1 @@
1
- {"version":3,"file":"local-editor-ui-hierarchy-tree.js","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-tree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LocalEditorBrowserUiHierarchyItem } from './local-editor-ui-types';\n\nexport type LocalEditorHierarchyNodeRole = 'root' | 'group' | 'object' | 'marker';\nexport type LocalEditorHierarchyDropPlacement = 'inside' | 'before' | 'after' | 'root';\n\nexport interface LocalEditorHierarchyTreeOptions {\n expandedIds?: ReadonlySet<string> | readonly string[];\n collapsedIds?: ReadonlySet<string> | readonly string[];\n defaultExpanded?: boolean;\n}\n\nexport interface LocalEditorHierarchyTreeNode {\n id: string;\n label: string;\n item: LocalEditorBrowserUiHierarchyItem;\n parentId: string | null;\n childIds: string[];\n depth: number;\n siblingIndex: number;\n inputIndex: number;\n role: LocalEditorHierarchyNodeRole;\n protected: boolean;\n selected: boolean;\n active: boolean;\n expanded: boolean;\n visible: boolean;\n}\n\nexport interface LocalEditorHierarchyDropResolution {\n ok: boolean;\n reason?: string;\n placement: LocalEditorHierarchyDropPlacement;\n draggedIds: string[];\n targetId: string | null;\n parentId: string | null;\n beforeId: string | null;\n afterId: string | null;\n}\n\nexport interface LocalEditorHierarchyDropInput {\n draggedIds: readonly string[];\n targetId?: string | null;\n placement: LocalEditorHierarchyDropPlacement;\n}\n\nexport interface LocalEditorHierarchyTreeModel {\n readonly nodes: LocalEditorHierarchyTreeNode[];\n readonly visibleRows: LocalEditorHierarchyTreeNode[];\n readonly rootIds: string[];\n readonly byId: ReadonlyMap<string, LocalEditorHierarchyTreeNode>;\n readonly childrenByParentId: ReadonlyMap<string | null, string[]>;\n getNode(id: string | null | undefined): LocalEditorHierarchyTreeNode | null;\n getChildren(parentId: string | null | undefined): LocalEditorHierarchyTreeNode[];\n getAncestors(id: string | null | undefined): LocalEditorHierarchyTreeNode[];\n isDescendant(candidateId: string, ancestorId: string): boolean;\n getSelectableChildren(id: string | null | undefined): string[];\n getSelectableDescendants(id: string | null | undefined): string[];\n getTopLevelSelection(ids: readonly string[]): string[];\n getVisibleRangeSelection(anchorId: string | null | undefined, targetId: string | null | undefined): string[];\n resolveDrop(input: LocalEditorHierarchyDropInput): LocalEditorHierarchyDropResolution;\n}\n\nexport function createLocalEditorHierarchyTreeModel(\n items: readonly LocalEditorBrowserUiHierarchyItem[],\n selectedIds: readonly string[] = [],\n activeId: string | null = null,\n options: LocalEditorHierarchyTreeOptions = {},\n): LocalEditorHierarchyTreeModel {\n const selected = new Set(selectedIds);\n const byRawId = new Map(items.map((item, inputIndex) => [item.id, { item, inputIndex }]));\n const childrenByParentId = new Map<string | null, string[]>();\n const provisionalNodes = new Map<string, Omit<LocalEditorHierarchyTreeNode, 'childIds' | 'depth' | 'siblingIndex' | 'expanded' | 'visible'>>();\n\n for (const { item, inputIndex } of byRawId.values()) {\n const parentId = item.parentId && byRawId.has(item.parentId) ? item.parentId : null;\n const role = resolveHierarchyNodeRole(item);\n provisionalNodes.set(item.id, {\n id: item.id,\n label: item.label,\n item,\n parentId,\n inputIndex,\n role,\n protected: item.protected === true,\n selected: selected.has(item.id),\n active: activeId === item.id,\n });\n const children = childrenByParentId.get(parentId) ?? [];\n children.push(item.id);\n childrenByParentId.set(parentId, children);\n }\n\n for (const childIds of childrenByParentId.values()) {\n childIds.sort((a, b) => {\n const left = provisionalNodes.get(a);\n const right = provisionalNodes.get(b);\n return (left?.inputIndex ?? 0) - (right?.inputIndex ?? 0);\n });\n }\n const siblingIndexById = new Map<string, number>();\n for (const childIds of childrenByParentId.values()) {\n childIds.forEach((id, index) => {\n siblingIndexById.set(id, index);\n });\n }\n\n const expanded = normalizeIdSet(options.expandedIds);\n const collapsed = normalizeIdSet(options.collapsedIds);\n const defaultExpanded = options.defaultExpanded ?? true;\n const nodesById = new Map<string, LocalEditorHierarchyTreeNode>();\n const visibleRows: LocalEditorHierarchyTreeNode[] = [];\n const visited = new Set<string>();\n\n const appendNode = (id: string, depth: number, visible: boolean): void => {\n if (visited.has(id)) return;\n const provisional = provisionalNodes.get(id);\n if (!provisional) return;\n visited.add(id);\n const childIds = childrenByParentId.get(id) ?? [];\n const parentChildren = childrenByParentId.get(provisional.parentId) ?? [];\n const nodeExpanded = childIds.length > 0 && (expanded.has(id) || (defaultExpanded && !collapsed.has(id)));\n const node: LocalEditorHierarchyTreeNode = {\n ...provisional,\n childIds: [...childIds],\n depth,\n siblingIndex: siblingIndexById.get(id) ?? Math.max(0, parentChildren.indexOf(id)),\n expanded: nodeExpanded,\n visible,\n };\n nodesById.set(id, node);\n if (visible) visibleRows.push(node);\n for (const childId of childIds) appendNode(childId, depth + 1, visible && nodeExpanded);\n };\n\n const rootIds = [...(childrenByParentId.get(null) ?? [])];\n for (const rootId of rootIds) appendNode(rootId, 0, true);\n for (const id of provisionalNodes.keys()) {\n if (visited.has(id)) continue;\n rootIds.push(id);\n appendNode(id, 0, true);\n }\n\n const nodes = [...nodesById.values()].sort((a, b) => a.inputIndex - b.inputIndex);\n return {\n nodes,\n visibleRows,\n rootIds,\n byId: nodesById,\n childrenByParentId,\n getNode(id) {\n return id ? nodesById.get(id) ?? null : null;\n },\n getChildren(parentId) {\n return (childrenByParentId.get(parentId ?? null) ?? [])\n .map(id => nodesById.get(id) ?? null)\n .filter((node): node is LocalEditorHierarchyTreeNode => !!node);\n },\n getAncestors(id) {\n const ancestors: LocalEditorHierarchyTreeNode[] = [];\n const seen = new Set<string>();\n let cursor = id ? nodesById.get(id) ?? null : null;\n while (cursor?.parentId && !seen.has(cursor.parentId)) {\n seen.add(cursor.parentId);\n cursor = nodesById.get(cursor.parentId) ?? null;\n if (cursor) ancestors.push(cursor);\n }\n return ancestors;\n },\n isDescendant(candidateId, ancestorId) {\n if (candidateId === ancestorId) return false;\n return this.getAncestors(candidateId).some(ancestor => ancestor.id === ancestorId);\n },\n getSelectableChildren(id) {\n return this.getChildren(id)\n .filter(isLocalEditorHierarchyNodeSelectable)\n .map(node => node.id);\n },\n getSelectableDescendants(id) {\n return collectSelectableDescendantIds(id, childrenByParentId, nodesById);\n },\n getTopLevelSelection(ids) {\n const selectedIds = new Set(ids.filter(id => nodesById.has(id)));\n const seen = new Set<string>();\n return ids.filter((id, index) => {\n if (!selectedIds.has(id) || seen.has(id)) return false;\n seen.add(id);\n return !this.getAncestors(id).some(ancestor => selectedIds.has(ancestor.id));\n });\n },\n getVisibleRangeSelection(anchorId, targetId) {\n const anchorIndex = findVisibleRowIndex(visibleRows, anchorId);\n const targetIndex = findVisibleRowIndex(visibleRows, targetId);\n if (anchorIndex < 0 || targetIndex < 0) return [];\n const start = Math.min(anchorIndex, targetIndex);\n const end = Math.max(anchorIndex, targetIndex);\n return visibleRows\n .slice(start, end + 1)\n .filter(isLocalEditorHierarchyNodeSelectable)\n .map(node => node.id);\n },\n resolveDrop(input) {\n return resolveHierarchyDrop(nodesById, childrenByParentId, input, this.getTopLevelSelection.bind(this), this.isDescendant.bind(this));\n },\n };\n}\n\nexport function isLocalEditorHierarchyNodeSelectable(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.selectable !== false\n && node.item.locked !== true;\n}\n\nexport function isLocalEditorHierarchyNodeMovable(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.locked !== true\n && node.item.draggable !== false;\n}\n\nexport function canLocalEditorHierarchyNodeHaveChildren(node: LocalEditorHierarchyTreeNode | null): boolean {\n if (!node) return false;\n if (node.item.locked === true) return false;\n return node.item.canHaveChildren === true;\n}\n\nexport function canLocalEditorHierarchyNodeRename(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.locked !== true\n && node.item.renamable !== false;\n}\n\nexport function canLocalEditorHierarchyNodeDelete(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.locked !== true\n && node.item.deletable !== false;\n}\n\nexport function canLocalEditorHierarchyNodeToggleEnabled(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && typeof node.item.enabled === 'boolean'\n && node.item.canToggleEnabled !== false\n && node.item.locked !== true\n && node.protected !== true;\n}\n\nfunction resolveHierarchyNodeRole(item: LocalEditorBrowserUiHierarchyItem): LocalEditorHierarchyNodeRole {\n if (item.role) return item.role;\n if (item.parentId == null && item.selectable === false) return 'root';\n return 'object';\n}\n\nfunction normalizeIdSet(value: ReadonlySet<string> | readonly string[] | undefined): ReadonlySet<string> {\n if (!value) return new Set<string>();\n return value instanceof Set ? value : new Set(value);\n}\n\nfunction findVisibleRowIndex(rows: readonly LocalEditorHierarchyTreeNode[], id: string | null | undefined): number {\n if (!id) return -1;\n return rows.findIndex(row => row.id === id);\n}\n\nfunction collectSelectableDescendantIds(\n id: string | null | undefined,\n childrenByParentId: ReadonlyMap<string | null, string[]>,\n nodesById: ReadonlyMap<string, LocalEditorHierarchyTreeNode>,\n): string[] {\n if (!id || !nodesById.has(id)) return [];\n const selectedIds: string[] = [];\n const visit = (parentId: string): void => {\n for (const childId of childrenByParentId.get(parentId) ?? []) {\n const child = nodesById.get(childId) ?? null;\n if (!child) continue;\n if (isLocalEditorHierarchyNodeSelectable(child)) selectedIds.push(child.id);\n visit(child.id);\n }\n };\n visit(id);\n return selectedIds;\n}\n\nfunction resolveHierarchyDrop(\n nodesById: ReadonlyMap<string, LocalEditorHierarchyTreeNode>,\n childrenByParentId: ReadonlyMap<string | null, string[]>,\n input: LocalEditorHierarchyDropInput,\n getTopLevelSelection: (ids: readonly string[]) => string[],\n isDescendant: (candidateId: string, ancestorId: string) => boolean,\n): LocalEditorHierarchyDropResolution {\n const draggedIds = getTopLevelSelection(input.draggedIds);\n if (draggedIds.length === 0) return invalidDrop(input, 'empty-drag');\n for (const id of draggedIds) {\n if (!isLocalEditorHierarchyNodeMovable(nodesById.get(id) ?? null)) return invalidDrop(input, 'dragged-node-not-movable');\n }\n if (input.placement === 'root') {\n return {\n ok: true,\n placement: 'root',\n draggedIds,\n targetId: null,\n parentId: null,\n beforeId: null,\n afterId: null,\n };\n }\n\n const targetId = input.targetId ?? null;\n const target = targetId ? nodesById.get(targetId) ?? null : null;\n if (!target) return invalidDrop(input, 'missing-target');\n if (draggedIds.includes(target.id)) return invalidDrop(input, 'cannot-drop-on-self');\n if (draggedIds.some(id => isDescendant(target.id, id))) return invalidDrop(input, 'cannot-drop-on-descendant');\n\n if (input.placement === 'inside') {\n if (!canLocalEditorHierarchyNodeHaveChildren(target)) return invalidDrop(input, 'target-cannot-have-children');\n const draggedSet = new Set(draggedIds);\n const children = (childrenByParentId.get(target.id) ?? []).filter(id => !draggedSet.has(id));\n return {\n ok: true,\n placement: 'inside',\n draggedIds,\n targetId: target.id,\n parentId: target.id,\n beforeId: null,\n afterId: children[children.length - 1] ?? null,\n };\n }\n\n if (target.role === 'root') return invalidDrop(input, 'cannot-reorder-root');\n if (target.item.locked === true) return invalidDrop(input, 'target-node-locked');\n const parent = target.parentId ? nodesById.get(target.parentId) ?? null : null;\n if (parent?.item.locked === true) return invalidDrop(input, 'target-parent-locked');\n const draggedSet = new Set(draggedIds);\n const siblings = (childrenByParentId.get(target.parentId) ?? []).filter(id => !draggedSet.has(id));\n const targetIndex = siblings.indexOf(target.id);\n return {\n ok: true,\n placement: input.placement,\n draggedIds,\n targetId: target.id,\n parentId: target.parentId,\n beforeId: input.placement === 'before' ? target.id : siblings[targetIndex + 1] ?? null,\n afterId: input.placement === 'after' ? target.id : siblings[targetIndex - 1] ?? null,\n };\n}\n\nfunction invalidDrop(\n input: LocalEditorHierarchyDropInput,\n reason: string,\n): LocalEditorHierarchyDropResolution {\n return {\n ok: false,\n reason,\n placement: input.placement,\n draggedIds: [],\n targetId: input.targetId ?? null,\n parentId: null,\n beforeId: null,\n afterId: null,\n };\n}\n"]}
1
+ {"version":3,"file":"local-editor-ui-hierarchy-tree.js","sourceRoot":"","sources":["../src/local-editor-ui-hierarchy-tree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LocalEditorBrowserUiHierarchyItem } from './local-editor-ui-types';\n\nexport type LocalEditorHierarchyNodeRole = 'root' | 'group' | 'object' | 'marker';\nexport type LocalEditorHierarchyDropPlacement = 'inside' | 'before' | 'after' | 'root';\n\nexport interface LocalEditorHierarchyTreeOptions {\n expandedIds?: ReadonlySet<string> | readonly string[];\n collapsedIds?: ReadonlySet<string> | readonly string[];\n defaultExpanded?: boolean;\n}\n\nexport interface LocalEditorHierarchyTreeNode {\n id: string;\n label: string;\n item: LocalEditorBrowserUiHierarchyItem;\n parentId: string | null;\n childIds: string[];\n depth: number;\n siblingIndex: number;\n inputIndex: number;\n role: LocalEditorHierarchyNodeRole;\n protected: boolean;\n selected: boolean;\n active: boolean;\n expanded: boolean;\n visible: boolean;\n}\n\nexport interface LocalEditorHierarchyDropResolution {\n ok: boolean;\n reason?: string;\n placement: LocalEditorHierarchyDropPlacement;\n draggedIds: string[];\n targetId: string | null;\n parentId: string | null;\n beforeId: string | null;\n afterId: string | null;\n}\n\nexport interface LocalEditorHierarchyDropInput {\n draggedIds: readonly string[];\n targetId?: string | null;\n placement: LocalEditorHierarchyDropPlacement;\n}\n\nexport interface LocalEditorHierarchyTreeModel {\n readonly nodes: LocalEditorHierarchyTreeNode[];\n readonly visibleRows: LocalEditorHierarchyTreeNode[];\n readonly rootIds: string[];\n readonly byId: ReadonlyMap<string, LocalEditorHierarchyTreeNode>;\n readonly childrenByParentId: ReadonlyMap<string | null, string[]>;\n getNode(id: string | null | undefined): LocalEditorHierarchyTreeNode | null;\n getChildren(parentId: string | null | undefined): LocalEditorHierarchyTreeNode[];\n getAncestors(id: string | null | undefined): LocalEditorHierarchyTreeNode[];\n isDescendant(candidateId: string, ancestorId: string): boolean;\n getSelectableChildren(id: string | null | undefined): string[];\n getSelectableDescendants(id: string | null | undefined): string[];\n getTopLevelSelection(ids: readonly string[]): string[];\n getVisibleRangeSelection(anchorId: string | null | undefined, targetId: string | null | undefined): string[];\n resolveDrop(input: LocalEditorHierarchyDropInput): LocalEditorHierarchyDropResolution;\n}\n\nexport function createLocalEditorHierarchyTreeModel(\n items: readonly LocalEditorBrowserUiHierarchyItem[],\n selectedIds: readonly string[] = [],\n activeId: string | null = null,\n options: LocalEditorHierarchyTreeOptions = {},\n): LocalEditorHierarchyTreeModel {\n assertHierarchyTreeInput(items);\n const selected = new Set(selectedIds);\n const byRawId = new Map(items.map((item, inputIndex) => [item.id, { item, inputIndex }]));\n const childrenByParentId = new Map<string | null, string[]>();\n const provisionalNodes = new Map<string, Omit<LocalEditorHierarchyTreeNode, 'childIds' | 'depth' | 'siblingIndex' | 'expanded' | 'visible'>>();\n\n for (const { item, inputIndex } of byRawId.values()) {\n const parentId = item.parentId ?? null;\n const role = resolveHierarchyNodeRole(item);\n provisionalNodes.set(item.id, {\n id: item.id,\n label: item.label,\n item,\n parentId,\n inputIndex,\n role,\n protected: item.protected === true,\n selected: selected.has(item.id),\n active: activeId === item.id,\n });\n const children = childrenByParentId.get(parentId) ?? [];\n children.push(item.id);\n childrenByParentId.set(parentId, children);\n }\n\n for (const childIds of childrenByParentId.values()) {\n childIds.sort((a, b) => {\n const left = provisionalNodes.get(a);\n const right = provisionalNodes.get(b);\n return (left?.inputIndex ?? 0) - (right?.inputIndex ?? 0);\n });\n }\n const siblingIndexById = new Map<string, number>();\n for (const childIds of childrenByParentId.values()) {\n childIds.forEach((id, index) => {\n siblingIndexById.set(id, index);\n });\n }\n\n const expanded = normalizeIdSet(options.expandedIds);\n const collapsed = normalizeIdSet(options.collapsedIds);\n const defaultExpanded = options.defaultExpanded ?? true;\n const nodesById = new Map<string, LocalEditorHierarchyTreeNode>();\n const visibleRows: LocalEditorHierarchyTreeNode[] = [];\n const visited = new Set<string>();\n\n const appendNode = (id: string, depth: number, visible: boolean): void => {\n if (visited.has(id)) return;\n const provisional = provisionalNodes.get(id);\n if (!provisional) return;\n visited.add(id);\n const childIds = childrenByParentId.get(id) ?? [];\n const parentChildren = childrenByParentId.get(provisional.parentId) ?? [];\n const nodeExpanded = childIds.length > 0 && (expanded.has(id) || (defaultExpanded && !collapsed.has(id)));\n const node: LocalEditorHierarchyTreeNode = {\n ...provisional,\n childIds: [...childIds],\n depth,\n siblingIndex: siblingIndexById.get(id) ?? Math.max(0, parentChildren.indexOf(id)),\n expanded: nodeExpanded,\n visible,\n };\n nodesById.set(id, node);\n if (visible) visibleRows.push(node);\n for (const childId of childIds) appendNode(childId, depth + 1, visible && nodeExpanded);\n };\n\n const rootIds = [...(childrenByParentId.get(null) ?? [])];\n for (const rootId of rootIds) appendNode(rootId, 0, true);\n\n const nodes = [...nodesById.values()].sort((a, b) => a.inputIndex - b.inputIndex);\n return {\n nodes,\n visibleRows,\n rootIds,\n byId: nodesById,\n childrenByParentId,\n getNode(id) {\n return id ? nodesById.get(id) ?? null : null;\n },\n getChildren(parentId) {\n return (childrenByParentId.get(parentId ?? null) ?? [])\n .map(id => nodesById.get(id) ?? null)\n .filter((node): node is LocalEditorHierarchyTreeNode => !!node);\n },\n getAncestors(id) {\n const ancestors: LocalEditorHierarchyTreeNode[] = [];\n const seen = new Set<string>();\n let cursor = id ? nodesById.get(id) ?? null : null;\n while (cursor?.parentId && !seen.has(cursor.parentId)) {\n seen.add(cursor.parentId);\n cursor = nodesById.get(cursor.parentId) ?? null;\n if (cursor) ancestors.push(cursor);\n }\n return ancestors;\n },\n isDescendant(candidateId, ancestorId) {\n if (candidateId === ancestorId) return false;\n return this.getAncestors(candidateId).some(ancestor => ancestor.id === ancestorId);\n },\n getSelectableChildren(id) {\n return this.getChildren(id)\n .filter(isLocalEditorHierarchyNodeSelectable)\n .map(node => node.id);\n },\n getSelectableDescendants(id) {\n return collectSelectableDescendantIds(id, childrenByParentId, nodesById);\n },\n getTopLevelSelection(ids) {\n const selectedIds = new Set(ids.filter(id => nodesById.has(id)));\n const seen = new Set<string>();\n return ids.filter((id, index) => {\n if (!selectedIds.has(id) || seen.has(id)) return false;\n seen.add(id);\n return !this.getAncestors(id).some(ancestor => selectedIds.has(ancestor.id));\n });\n },\n getVisibleRangeSelection(anchorId, targetId) {\n const anchorIndex = findVisibleRowIndex(visibleRows, anchorId);\n const targetIndex = findVisibleRowIndex(visibleRows, targetId);\n if (anchorIndex < 0 || targetIndex < 0) return [];\n const start = Math.min(anchorIndex, targetIndex);\n const end = Math.max(anchorIndex, targetIndex);\n return visibleRows\n .slice(start, end + 1)\n .filter(isLocalEditorHierarchyNodeSelectable)\n .map(node => node.id);\n },\n resolveDrop(input) {\n return resolveHierarchyDrop(nodesById, childrenByParentId, input, this.getTopLevelSelection.bind(this), this.isDescendant.bind(this));\n },\n };\n}\n\nfunction assertHierarchyTreeInput(items: readonly LocalEditorBrowserUiHierarchyItem[]): void {\n const ids = new Set<string>();\n for (const item of items) {\n if (ids.has(item.id)) throw new Error(`hierarchy-row-id-duplicate:${item.id}`);\n ids.add(item.id);\n }\n for (const item of items) {\n if (item.parentId != null && !ids.has(item.parentId)) {\n throw new Error(`hierarchy-parent-missing:${item.id}:${item.parentId}`);\n }\n const path = new Set<string>();\n let cursor: LocalEditorBrowserUiHierarchyItem | undefined = item;\n while (cursor?.parentId != null) {\n if (path.has(cursor.id)) throw new Error(`hierarchy-parent-cycle:${cursor.id}`);\n path.add(cursor.id);\n cursor = items.find(candidate => candidate.id === cursor?.parentId);\n }\n }\n}\n\nexport function isLocalEditorHierarchyNodeSelectable(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.selectable !== false\n && node.item.locked !== true;\n}\n\nexport function isLocalEditorHierarchyNodeMovable(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.locked !== true\n && node.item.draggable !== false;\n}\n\nexport function canLocalEditorHierarchyNodeHaveChildren(node: LocalEditorHierarchyTreeNode | null): boolean {\n if (!node) return false;\n if (node.item.locked === true) return false;\n return node.item.canHaveChildren === true;\n}\n\nexport function canLocalEditorHierarchyNodeRename(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.locked !== true\n && node.item.renamable !== false;\n}\n\nexport function canLocalEditorHierarchyNodeDelete(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && node.item.locked !== true\n && node.item.deletable !== false;\n}\n\nexport function canLocalEditorHierarchyNodeToggleEnabled(node: LocalEditorHierarchyTreeNode | null): boolean {\n return !!node\n && typeof node.item.enabled === 'boolean'\n && node.item.canToggleEnabled !== false\n && node.item.locked !== true\n && node.protected !== true;\n}\n\nfunction resolveHierarchyNodeRole(item: LocalEditorBrowserUiHierarchyItem): LocalEditorHierarchyNodeRole {\n if (item.role) return item.role;\n if (item.parentId == null && item.selectable === false) return 'root';\n return 'object';\n}\n\nfunction normalizeIdSet(value: ReadonlySet<string> | readonly string[] | undefined): ReadonlySet<string> {\n if (!value) return new Set<string>();\n return value instanceof Set ? value : new Set(value);\n}\n\nfunction findVisibleRowIndex(rows: readonly LocalEditorHierarchyTreeNode[], id: string | null | undefined): number {\n if (!id) return -1;\n return rows.findIndex(row => row.id === id);\n}\n\nfunction collectSelectableDescendantIds(\n id: string | null | undefined,\n childrenByParentId: ReadonlyMap<string | null, string[]>,\n nodesById: ReadonlyMap<string, LocalEditorHierarchyTreeNode>,\n): string[] {\n if (!id || !nodesById.has(id)) return [];\n const selectedIds: string[] = [];\n const visit = (parentId: string): void => {\n for (const childId of childrenByParentId.get(parentId) ?? []) {\n const child = nodesById.get(childId) ?? null;\n if (!child) continue;\n if (isLocalEditorHierarchyNodeSelectable(child)) selectedIds.push(child.id);\n visit(child.id);\n }\n };\n visit(id);\n return selectedIds;\n}\n\nfunction resolveHierarchyDrop(\n nodesById: ReadonlyMap<string, LocalEditorHierarchyTreeNode>,\n childrenByParentId: ReadonlyMap<string | null, string[]>,\n input: LocalEditorHierarchyDropInput,\n getTopLevelSelection: (ids: readonly string[]) => string[],\n isDescendant: (candidateId: string, ancestorId: string) => boolean,\n): LocalEditorHierarchyDropResolution {\n const draggedIds = getTopLevelSelection(input.draggedIds);\n if (draggedIds.length === 0) return invalidDrop(input, 'empty-drag');\n for (const id of draggedIds) {\n if (!isLocalEditorHierarchyNodeMovable(nodesById.get(id) ?? null)) return invalidDrop(input, 'dragged-node-not-movable');\n }\n if (input.placement === 'root') {\n return {\n ok: true,\n placement: 'root',\n draggedIds,\n targetId: null,\n parentId: null,\n beforeId: null,\n afterId: null,\n };\n }\n\n const targetId = input.targetId ?? null;\n const target = targetId ? nodesById.get(targetId) ?? null : null;\n if (!target) return invalidDrop(input, 'missing-target');\n if (draggedIds.includes(target.id)) return invalidDrop(input, 'cannot-drop-on-self');\n if (draggedIds.some(id => isDescendant(target.id, id))) return invalidDrop(input, 'cannot-drop-on-descendant');\n\n if (input.placement === 'inside') {\n if (!canLocalEditorHierarchyNodeHaveChildren(target)) return invalidDrop(input, 'target-cannot-have-children');\n const draggedSet = new Set(draggedIds);\n const children = (childrenByParentId.get(target.id) ?? []).filter(id => !draggedSet.has(id));\n return {\n ok: true,\n placement: 'inside',\n draggedIds,\n targetId: target.id,\n parentId: target.id,\n beforeId: null,\n afterId: children[children.length - 1] ?? null,\n };\n }\n\n if (target.role === 'root') return invalidDrop(input, 'cannot-reorder-root');\n if (target.item.locked === true) return invalidDrop(input, 'target-node-locked');\n const parent = target.parentId ? nodesById.get(target.parentId) ?? null : null;\n if (parent?.item.locked === true) return invalidDrop(input, 'target-parent-locked');\n const draggedSet = new Set(draggedIds);\n const siblings = (childrenByParentId.get(target.parentId) ?? []).filter(id => !draggedSet.has(id));\n const targetIndex = siblings.indexOf(target.id);\n return {\n ok: true,\n placement: input.placement,\n draggedIds,\n targetId: target.id,\n parentId: target.parentId,\n beforeId: input.placement === 'before' ? target.id : siblings[targetIndex + 1] ?? null,\n afterId: input.placement === 'after' ? target.id : siblings[targetIndex - 1] ?? null,\n };\n}\n\nfunction invalidDrop(\n input: LocalEditorHierarchyDropInput,\n reason: string,\n): LocalEditorHierarchyDropResolution {\n return {\n ok: false,\n reason,\n placement: input.placement,\n draggedIds: [],\n targetId: input.targetId ?? null,\n parentId: null,\n beforeId: null,\n afterId: null,\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- export declare const LOCAL_EDITOR_ICON_NAMES: readonly ["asset", "arrange", "camera", "chevron-down", "chevron-right", "copy", "discard", "execute", "eye", "eye-off", "group", "grid", "help", "hierarchy", "history", "inspector", "local", "lock", "material-slot", "move", "object", "performance", "prefab", "place-ground", "place-off", "place-surface", "projection-ortho", "projection-perspective", "plus", "redo", "root", "rotate", "save", "scale", "select", "snap", "status", "theme", "trash", "undo", "view-front", "view-overlay", "view-perspective", "view-right", "view-top", "measure", "world"];
1
+ export declare const LOCAL_EDITOR_ICON_NAMES: readonly ["asset", "arrange", "camera", "chevron-down", "chevron-right", "copy", "discard", "execute", "eye", "eye-off", "group", "grid", "help", "hierarchy", "history", "inspector", "local", "lock", "material-slot", "move", "object", "performance", "prefab", "place-ground", "place-off", "place-surface", "projection-ortho", "projection-perspective", "plus", "redo", "root", "rotate", "save", "scale", "select", "snap", "status", "theme", "trash", "undo", "view-front", "view-overlay", "view-perspective", "view-right", "view-top", "warning", "measure", "world"];
2
2
  export type LocalEditorIconName = typeof LOCAL_EDITOR_ICON_NAMES[number];
3
3
  export interface LocalEditorIconOptions {
4
4
  size?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"local-editor-ui-icons.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-icons.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,0iBAgD1B,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2ND,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAElF;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,mBAA8B,GACvC,mBAAmB,CAErB;AAED,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,mBAAmB,EACzB,OAAO,GAAE,sBAA2B,GACnC,eAAe,CAuCjB"}
1
+ {"version":3,"file":"local-editor-ui-icons.d.ts","sourceRoot":"","sources":["../src/local-editor-ui-icons.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,qjBAiD1B,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAgOD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAElF;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,mBAA8B,GACvC,mBAAmB,CAErB;AAED,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,mBAAmB,EACzB,OAAO,GAAE,sBAA2B,GACnC,eAAe,CAuCjB"}
@@ -44,6 +44,7 @@ export const LOCAL_EDITOR_ICON_NAMES = [
44
44
  'view-perspective',
45
45
  'view-right',
46
46
  'view-top',
47
+ 'warning',
47
48
  'measure',
48
49
  'world',
49
50
  ];
@@ -210,6 +211,11 @@ const LOCAL_EDITOR_ICON_DEFINITIONS = {
210
211
  { tag: 'path', attrs: { d: 'M12 8v5' } },
211
212
  { tag: 'line', attrs: { x1: '12', y1: '16', x2: '12.01', y2: '16' } },
212
213
  ],
214
+ warning: [
215
+ { tag: 'path', attrs: { d: 'M12 3L2.8 20h18.4z' } },
216
+ { tag: 'path', attrs: { d: 'M12 9v5' } },
217
+ { tag: 'line', attrs: { x1: '12', y1: '17', x2: '12.01', y2: '17' } },
218
+ ],
213
219
  theme: [
214
220
  { tag: 'circle', attrs: { cx: '12', cy: '12', r: '9' } },
215
221
  { tag: 'path', attrs: { d: 'M12 3v18' } },