@aglyn/besigner 1.0.0-beta.143

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 (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +48 -0
  4. package/src/besigner.d.ts +28 -0
  5. package/src/besigner.js +59 -0
  6. package/src/besigner.js.map +1 -0
  7. package/src/index.d.ts +17 -0
  8. package/src/index.js +18 -0
  9. package/src/index.js.map +1 -0
  10. package/src/lib/api/app.api.d.ts +22 -0
  11. package/src/lib/api/app.api.js +59 -0
  12. package/src/lib/api/app.api.js.map +1 -0
  13. package/src/lib/api/besigner.api.d.ts +24 -0
  14. package/src/lib/api/besigner.api.js +39 -0
  15. package/src/lib/api/besigner.api.js.map +1 -0
  16. package/src/lib/clipboard-manager/clipboard-manager.d.ts +89 -0
  17. package/src/lib/clipboard-manager/clipboard-manager.js +241 -0
  18. package/src/lib/clipboard-manager/clipboard-manager.js.map +1 -0
  19. package/src/lib/clipboard-manager/clipboard-mirror.d.ts +52 -0
  20. package/src/lib/clipboard-manager/clipboard-mirror.js +75 -0
  21. package/src/lib/clipboard-manager/clipboard-mirror.js.map +1 -0
  22. package/src/lib/clipboard-manager/index.d.ts +20 -0
  23. package/src/lib/clipboard-manager/index.js +23 -0
  24. package/src/lib/clipboard-manager/index.js.map +1 -0
  25. package/src/lib/clipboard-manager/style-clipboard.d.ts +77 -0
  26. package/src/lib/clipboard-manager/style-clipboard.js +173 -0
  27. package/src/lib/clipboard-manager/style-clipboard.js.map +1 -0
  28. package/src/lib/constants/_internal.d.ts +20 -0
  29. package/src/lib/constants/_internal.js +19 -0
  30. package/src/lib/constants/_internal.js.map +1 -0
  31. package/src/lib/constants/besigner.d.ts +78 -0
  32. package/src/lib/constants/besigner.js +69 -0
  33. package/src/lib/constants/besigner.js.map +1 -0
  34. package/src/lib/controllers/besigner-app.controller.d.ts +33 -0
  35. package/src/lib/controllers/besigner-app.controller.js +57 -0
  36. package/src/lib/controllers/besigner-app.controller.js.map +1 -0
  37. package/src/lib/controllers/besigner-interface.controller.d.ts +44 -0
  38. package/src/lib/controllers/besigner-interface.controller.js +130 -0
  39. package/src/lib/controllers/besigner-interface.controller.js.map +1 -0
  40. package/src/lib/definitions/besigner-app.types.d.ts +41 -0
  41. package/src/lib/definitions/besigner-app.types.js +18 -0
  42. package/src/lib/definitions/besigner-app.types.js.map +1 -0
  43. package/src/lib/definitions/besigner-interface.types.d.ts +106 -0
  44. package/src/lib/definitions/besigner-interface.types.js +18 -0
  45. package/src/lib/definitions/besigner-interface.types.js.map +1 -0
  46. package/src/lib/definitions/emitter.types.d.ts +33 -0
  47. package/src/lib/definitions/emitter.types.js +18 -0
  48. package/src/lib/definitions/emitter.types.js.map +1 -0
  49. package/src/lib/device-preview-width.d.ts +39 -0
  50. package/src/lib/device-preview-width.js +57 -0
  51. package/src/lib/device-preview-width.js.map +1 -0
  52. package/src/lib/dnd-manager/confirm-valid-lineal-relationship.d.ts +54 -0
  53. package/src/lib/dnd-manager/confirm-valid-lineal-relationship.js +109 -0
  54. package/src/lib/dnd-manager/confirm-valid-lineal-relationship.js.map +1 -0
  55. package/src/lib/dnd-manager/dnd-manager.d.ts +75 -0
  56. package/src/lib/dnd-manager/dnd-manager.js +337 -0
  57. package/src/lib/dnd-manager/dnd-manager.js.map +1 -0
  58. package/src/lib/dnd-manager/droppable-region-utils.d.ts +72 -0
  59. package/src/lib/dnd-manager/droppable-region-utils.js +115 -0
  60. package/src/lib/dnd-manager/droppable-region-utils.js.map +1 -0
  61. package/src/lib/dnd-manager/index.d.ts +20 -0
  62. package/src/lib/dnd-manager/index.js +21 -0
  63. package/src/lib/dnd-manager/index.js.map +1 -0
  64. package/src/lib/focus-manager/focus-manager.d.ts +104 -0
  65. package/src/lib/focus-manager/focus-manager.js +353 -0
  66. package/src/lib/focus-manager/focus-manager.js.map +1 -0
  67. package/src/lib/focus-manager/index.d.ts +18 -0
  68. package/src/lib/focus-manager/index.js +19 -0
  69. package/src/lib/focus-manager/index.js.map +1 -0
  70. package/src/lib/is-root-element-id.d.ts +19 -0
  71. package/src/lib/is-root-element-id.js +22 -0
  72. package/src/lib/is-root-element-id.js.map +1 -0
  73. package/src/lib/managers.d.ts +25 -0
  74. package/src/lib/managers.js +26 -0
  75. package/src/lib/managers.js.map +1 -0
  76. package/src/lib/node-move/index.d.ts +17 -0
  77. package/src/lib/node-move/index.js +18 -0
  78. package/src/lib/node-move/index.js.map +1 -0
  79. package/src/lib/node-move/node-move.d.ts +80 -0
  80. package/src/lib/node-move/node-move.js +134 -0
  81. package/src/lib/node-move/node-move.js.map +1 -0
  82. package/src/lib/node-refs/index.d.ts +1 -0
  83. package/src/lib/node-refs/index.js +3 -0
  84. package/src/lib/node-refs/index.js.map +1 -0
  85. package/src/lib/node-refs/node-refs.d.ts +24 -0
  86. package/src/lib/node-refs/node-refs.js +30 -0
  87. package/src/lib/node-refs/node-refs.js.map +1 -0
  88. package/src/lib/pick-manager/index.d.ts +18 -0
  89. package/src/lib/pick-manager/index.js +20 -0
  90. package/src/lib/pick-manager/index.js.map +1 -0
  91. package/src/lib/pick-manager/pick-manager.d.ts +64 -0
  92. package/src/lib/pick-manager/pick-manager.js +116 -0
  93. package/src/lib/pick-manager/pick-manager.js.map +1 -0
  94. package/src/lib/text-entry/index.d.ts +17 -0
  95. package/src/lib/text-entry/index.js +18 -0
  96. package/src/lib/text-entry/index.js.map +1 -0
  97. package/src/lib/text-entry/text-entry.d.ts +71 -0
  98. package/src/lib/text-entry/text-entry.js +103 -0
  99. package/src/lib/text-entry/text-entry.js.map +1 -0
@@ -0,0 +1,353 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2024 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { canvas } from "@aglyn/aglyn";
17
+ import { observable, runInAction } from "mobx";
18
+ // The leaf module, not the 68 KB package bundle — see the note there.
19
+ import { computedFn } from "@aglyn/shared-util-vendor/mobx-computed-fn";
20
+ const state = observable({
21
+ hovered: null,
22
+ selected: [],
23
+ expanded: [],
24
+ manuallyCollapsed: [],
25
+ get allExpanded () {
26
+ return [
27
+ ...this.expanded,
28
+ ...this.selected
29
+ ];
30
+ },
31
+ get lastSelected () {
32
+ return this.selected[this.selected.length - 1];
33
+ },
34
+ get selectionCount () {
35
+ return this.selected.length;
36
+ },
37
+ get hasMultipleSelected () {
38
+ return this.selected.length > 1;
39
+ },
40
+ isNodeSelected: computedFn((node)=>{
41
+ if (!node) return false;
42
+ return state.selected.some((i)=>(i == null ? void 0 : i.$id) === (node == null ? void 0 : node.$id));
43
+ }),
44
+ isNodeOrDescendantSelected: computedFn((node)=>{
45
+ if (!node) return false;
46
+ // A node's breadcrumbPath is [root, ...ancestors, self], so a
47
+ // selected node whose path contains this id makes this node the
48
+ // selection itself or one of its ancestors — i.e. the selection is
49
+ // within this node's subtree.
50
+ return state.selected.some((selectedNode)=>{
51
+ var _selectedNode_breadcrumbPath;
52
+ return (selectedNode == null ? void 0 : selectedNode.$id) === node.$id || (selectedNode == null ? void 0 : (_selectedNode_breadcrumbPath = selectedNode.breadcrumbPath) == null ? void 0 : _selectedNode_breadcrumbPath.includes(node.$id));
53
+ });
54
+ }),
55
+ isNodeHovered: computedFn((node)=>{
56
+ var _state_hovered;
57
+ if (!node) return false;
58
+ return ((_state_hovered = state.hovered) == null ? void 0 : _state_hovered.$id) === (node == null ? void 0 : node.$id);
59
+ }),
60
+ isNodeExpanded: computedFn((node)=>{
61
+ if (!node) return false;
62
+ return state.expanded.some((i)=>(i == null ? void 0 : i.$id) === (node == null ? void 0 : node.$id));
63
+ }),
64
+ isNodeEffectivelyExpanded: computedFn((node)=>{
65
+ if (!node) return false;
66
+ // Manually expanded always wins
67
+ if (state.expanded.some((i)=>(i == null ? void 0 : i.$id) === (node == null ? void 0 : node.$id))) return true;
68
+ // If the user explicitly collapsed this node, treat it as collapsed
69
+ if (state.manuallyCollapsed.includes(node.$id)) return false;
70
+ // Auto-expanded: this node is an ancestor of a manually expanded node
71
+ // (mirrors the view's allExpanded breadcrumb-path logic exactly)
72
+ if (state.expanded.some((n)=>{
73
+ var _n_breadcrumbPath;
74
+ return n == null ? void 0 : (_n_breadcrumbPath = n.breadcrumbPath) == null ? void 0 : _n_breadcrumbPath.includes(node.$id);
75
+ })) return true;
76
+ // Auto-expanded: this node is an ancestor of a selected node
77
+ return state.selected.some((selectedNode)=>{
78
+ var _selectedNode_breadcrumbPath;
79
+ return selectedNode == null ? void 0 : (_selectedNode_breadcrumbPath = selectedNode.breadcrumbPath) == null ? void 0 : _selectedNode_breadcrumbPath.includes(node.$id);
80
+ });
81
+ })
82
+ });
83
+ export function getLastSelected() {
84
+ return state.lastSelected;
85
+ }
86
+ export function selectionCount() {
87
+ return state.selectionCount;
88
+ }
89
+ export function hasMultipleSelected() {
90
+ return state.hasMultipleSelected;
91
+ }
92
+ export function getHovered() {
93
+ return state.hovered;
94
+ }
95
+ export function getSelected() {
96
+ return state.selected;
97
+ }
98
+ export function getAllExpanded() {
99
+ return state.allExpanded;
100
+ }
101
+ export function getManuallyCollapsed() {
102
+ return state.manuallyCollapsed;
103
+ }
104
+ export function isNodeSelected(node) {
105
+ return state.isNodeSelected(node);
106
+ }
107
+ export function isNodeOrDescendantSelected(node) {
108
+ return state.isNodeOrDescendantSelected(node);
109
+ }
110
+ export function isNodeHovered(node) {
111
+ return state.isNodeHovered(node);
112
+ }
113
+ export function isNodeExpanded(node) {
114
+ return state.isNodeExpanded(node);
115
+ }
116
+ export function isNodeEffectivelyExpanded(node) {
117
+ return state.isNodeEffectivelyExpanded(node);
118
+ }
119
+ export function clearFocusStatus() {
120
+ runInAction(()=>{
121
+ state.selected = [];
122
+ state.hovered = null;
123
+ });
124
+ }
125
+ export function clearSelection() {
126
+ runInAction(()=>{
127
+ state.selected = [];
128
+ });
129
+ }
130
+ export function clearHover() {
131
+ runInAction(()=>{
132
+ state.hovered = null;
133
+ });
134
+ }
135
+ export function expandNode(node) {
136
+ if (!node) return;
137
+ runInAction(()=>{
138
+ // Clear any manual-collapse override so the node stays open
139
+ const mcIndex = state.manuallyCollapsed.indexOf(node.$id);
140
+ if (mcIndex !== -1) state.manuallyCollapsed.splice(mcIndex, 1);
141
+ if (!state.expanded.some((i)=>(i == null ? void 0 : i.$id) === (node == null ? void 0 : node.$id))) {
142
+ state.expanded.push(node);
143
+ }
144
+ });
145
+ }
146
+ export function collapseNode(node) {
147
+ if (!node) return;
148
+ runInAction(()=>{
149
+ // Remove from manually-expanded if present
150
+ const index = state.expanded.findIndex((i)=>(i == null ? void 0 : i.$id) === (node == null ? void 0 : node.$id));
151
+ if (index !== -1) state.expanded.splice(index, 1);
152
+ // After removal, check if the node is still visually open because it is an
153
+ // ancestor of another expanded node or of a selected node. If so, record a
154
+ // manual-collapse override so those auto-expansion sources are suppressed.
155
+ const stillEffectivelyExpanded = state.expanded.some((n)=>{
156
+ var _n_breadcrumbPath;
157
+ return n == null ? void 0 : (_n_breadcrumbPath = n.breadcrumbPath) == null ? void 0 : _n_breadcrumbPath.includes(node.$id);
158
+ }) || state.selected.some((s)=>{
159
+ var _s_breadcrumbPath;
160
+ return s == null ? void 0 : (_s_breadcrumbPath = s.breadcrumbPath) == null ? void 0 : _s_breadcrumbPath.includes(node.$id);
161
+ });
162
+ if (stillEffectivelyExpanded && !state.manuallyCollapsed.includes(node.$id)) {
163
+ state.manuallyCollapsed.push(node.$id);
164
+ }
165
+ });
166
+ }
167
+ export function toggleNodeExpansion(node) {
168
+ if (!node) return;
169
+ // Use effective expansion so auto-expanded nodes can also be toggled closed
170
+ if (isNodeEffectivelyExpanded(node)) return collapseNode(node);
171
+ return expandNode(node);
172
+ }
173
+ /**
174
+ * What a click on a node means, in the hierarchy and on the canvas alike.
175
+ *
176
+ * Toggling belongs to Cmd/Ctrl-click — which is exactly what
177
+ * `multiSelection` means at both call sites, and what both of their comments
178
+ * already claimed. A PLAIN click always selects (AGL-2486): it used to
179
+ * toggle, so clicking the row of a node that was already selected DESELECTED
180
+ * it, and since the hierarchy's expansion is derived from the selection
181
+ * (`allExpanded`), the tree then collapsed to the document root and the row
182
+ * vanished from under the pointer. Every way of putting a new element on the
183
+ * canvas leaves it selected, so "add an element, then click it in the
184
+ * hierarchy" hit this every time.
185
+ */ export function handleNodeSelection(node, multiSelection = false) {
186
+ if (multiSelection && isNodeSelected(node)) {
187
+ deselectNode(node, multiSelection);
188
+ return;
189
+ }
190
+ setSelectedNode(node, multiSelection);
191
+ }
192
+ export function deselectNode(node, multiSelection = false) {
193
+ if (!isNodeSelected(node)) return;
194
+ runInAction(()=>{
195
+ if (multiSelection) {
196
+ const selectIndex = state.selected.indexOf(node);
197
+ state.selected.splice(selectIndex, 1);
198
+ } else {
199
+ state.selected = [];
200
+ }
201
+ });
202
+ }
203
+ export function setSelectedNode(node, multiSelection = false) {
204
+ // Already the sole selection, or already a member of a multi-selection
205
+ // being added to: nothing to do. A plain (single) select of a node that is
206
+ // one of SEVERAL still has work — it collapses the selection down to that
207
+ // node — so it deliberately falls through.
208
+ if (isNodeSelected(node) && (multiSelection || state.selected.length === 1)) {
209
+ return;
210
+ }
211
+ runInAction(()=>{
212
+ var _ref;
213
+ if (multiSelection) state.selected.push(node);
214
+ else state.selected = [
215
+ node
216
+ ];
217
+ // Clear manual-collapse overrides for ancestors of the newly selected node
218
+ // so the hierarchy always opens up to reveal it
219
+ const ancestorIds = new Set((_ref = node == null ? void 0 : node.breadcrumbPath) != null ? _ref : []);
220
+ state.manuallyCollapsed = state.manuallyCollapsed.filter((id)=>!ancestorIds.has(id));
221
+ });
222
+ }
223
+ /**
224
+ * Where the selection should land once `nodes` are deleted, best first
225
+ * (AGL-2553).
226
+ *
227
+ * Deleting used to clear the selection outright, and the hierarchy collapsing
228
+ * was the consequence: the tree only holds a branch open to reveal what is
229
+ * selected, so with nothing selected a subtree the author had navigated into
230
+ * snapped shut on every delete.
231
+ *
232
+ * Order is next sibling, then previous, then the parent. NEXT first because
233
+ * it slides into the deleted node's slot — the highlight stays where the
234
+ * author's eye already is, rather than stepping backwards. Previous covers
235
+ * deleting the last child, and the parent covers an only child, where keeping
236
+ * the branch open one level up is still better than closing it.
237
+ *
238
+ * ⚑ Returns CANDIDATES rather than a node, because it must be called BEFORE
239
+ * the delete — sibling indices shift once it runs — and the caller selects the
240
+ * first that survives. That ordering is what makes multi-selection safe
241
+ * without walking ancestors: a sibling that was itself doomed, or that hung
242
+ * off a doomed node, is simply absent from the map afterwards and the next
243
+ * candidate wins.
244
+ */ export function resolveSelectionAfterDeletion(nodes) {
245
+ var _parent_nodes;
246
+ const anchor = nodes.find((node)=>(node == null ? void 0 : node.$id) && (node == null ? void 0 : node.parentId));
247
+ if (!anchor) return [];
248
+ const parent = canvas.getNode(anchor.parentId);
249
+ if (!parent) return [];
250
+ const siblings = (_parent_nodes = parent.nodes) != null ? _parent_nodes : [];
251
+ const index = siblings.indexOf(anchor.$id);
252
+ const candidates = [];
253
+ if (index > -1) {
254
+ for(let i = index + 1; i < siblings.length; i += 1){
255
+ const sibling = canvas.getNode(siblings[i]);
256
+ if (sibling) candidates.push(sibling);
257
+ }
258
+ for(let i = index - 1; i >= 0; i -= 1){
259
+ const sibling = canvas.getNode(siblings[i]);
260
+ if (sibling) candidates.push(sibling);
261
+ }
262
+ }
263
+ candidates.push(parent);
264
+ return candidates;
265
+ }
266
+ /**
267
+ * Selects the first of `candidates` that still exists, or clears the
268
+ * selection when none do. The other half of
269
+ * {@link resolveSelectionAfterDeletion}; call it AFTER the delete.
270
+ */ export function selectFirstSurviving(candidates) {
271
+ const survivor = candidates.find((node)=>!!canvas.getNode(node.$id));
272
+ if (survivor) setSelectedNode(survivor);
273
+ else clearSelection();
274
+ }
275
+ /**
276
+ * Flat, depth-first list of the nodes currently visible in the hierarchy —
277
+ * children of collapsed nodes are skipped (AGL-6). Range selection resolves
278
+ * its slice against this order.
279
+ */ export function getVisibleNodeOrder() {
280
+ const result = [];
281
+ const root = canvas.rootNode;
282
+ if (!root) return result;
283
+ const walk = (node)=>{
284
+ var _node_nodes;
285
+ result.push(node);
286
+ if (node.$id !== root.$id && !state.isNodeEffectivelyExpanded(node)) return;
287
+ for (const id of (_node_nodes = node.nodes) != null ? _node_nodes : []){
288
+ const child = canvas.getNode(id);
289
+ if (child) walk(child);
290
+ }
291
+ };
292
+ walk(root);
293
+ return result;
294
+ }
295
+ /**
296
+ * Shift+Click range selection (AGL-7): selects every visible node between
297
+ * the current anchor (`lastSelected`) and the target, in document order.
298
+ * Without an anchor it falls back to single selection.
299
+ */ export function rangeSelectNode(node) {
300
+ if (!node) return;
301
+ const anchor = state.lastSelected;
302
+ if (!anchor || anchor.$id === node.$id) return setSelectedNode(node, false);
303
+ const visibleNodes = getVisibleNodeOrder();
304
+ const anchorIndex = visibleNodes.findIndex((n)=>n.$id === anchor.$id);
305
+ const targetIndex = visibleNodes.findIndex((n)=>n.$id === node.$id);
306
+ if (anchorIndex === -1 || targetIndex === -1) {
307
+ return setSelectedNode(node, false);
308
+ }
309
+ const [from, to] = anchorIndex < targetIndex ? [
310
+ anchorIndex,
311
+ targetIndex
312
+ ] : [
313
+ targetIndex,
314
+ anchorIndex
315
+ ];
316
+ runInAction(()=>{
317
+ state.selected = visibleNodes.slice(from, to + 1);
318
+ });
319
+ }
320
+ /**
321
+ * Cmd/Ctrl+A helper (AGL-7): selects every visible node at the same tree
322
+ * depth as the current selection anchor (siblings-and-cousins). No-ops
323
+ * without an anchor.
324
+ */ export function selectAllAtDepth() {
325
+ var _ref;
326
+ var _anchor_breadcrumbPath;
327
+ const anchor = state.lastSelected;
328
+ if (!anchor) return;
329
+ const depth = (_ref = (_anchor_breadcrumbPath = anchor.breadcrumbPath) == null ? void 0 : _anchor_breadcrumbPath.length) != null ? _ref : 0;
330
+ const peers = getVisibleNodeOrder().filter((node)=>{
331
+ var _ref;
332
+ var _node_breadcrumbPath;
333
+ return ((_ref = (_node_breadcrumbPath = node.breadcrumbPath) == null ? void 0 : _node_breadcrumbPath.length) != null ? _ref : 0) === depth;
334
+ });
335
+ if (!peers.length) return;
336
+ runInAction(()=>{
337
+ state.selected = peers;
338
+ });
339
+ }
340
+ export function setHoveredNode(node) {
341
+ if (isNodeHovered(node)) return;
342
+ runInAction(()=>{
343
+ state.hovered = node;
344
+ });
345
+ }
346
+ export function dehoverNode(node) {
347
+ if (!isNodeHovered(node)) return;
348
+ runInAction(()=>{
349
+ state.hovered = null;
350
+ });
351
+ }
352
+
353
+ //# sourceMappingURL=focus-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/focus-manager/focus-manager.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2024 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type * as Aglyn from '@aglyn/aglyn'\nimport { canvas } from '@aglyn/aglyn'\nimport { observable, runInAction } from 'mobx'\n// The leaf module, not the 68 KB package bundle — see the note there.\nimport { computedFn } from '@aglyn/shared-util-vendor/mobx-computed-fn'\n\nexport type HoveredNode = Aglyn.NodeSchema<any> | null\nexport type SelectedNodes = Aglyn.NodeSchema<any>[]\nexport type ExpandedNodes = Aglyn.NodeSchema<any>[]\nexport type LastSelectedNode = Aglyn.NodeSchema<any> | undefined\n\ninterface FocusState {\n /**\n * The current hovered node\n */\n hovered?: HoveredNode\n /**\n * The current selected node\n */\n selected: SelectedNodes\n /**\n * Nodes the user has manually expanded via the tree toggle\n */\n expanded: ExpandedNodes\n /**\n * Node IDs that the user has explicitly collapsed, overriding auto-expansion\n * from selection. Cleared for a node's ancestors whenever a new node is selected.\n */\n manuallyCollapsed: Aglyn.NodeId[]\n allExpanded: ExpandedNodes & SelectedNodes\n /**\n * The computed last selected node\n */\n readonly lastSelected: LastSelectedNode\n /** Number of currently selected nodes (AGL-5). */\n readonly selectionCount: number\n /** True when more than one node is selected (AGL-5). */\n readonly hasMultipleSelected: boolean\n\n readonly isNodeSelected: (node: Aglyn.NodeSchema) => boolean\n /**\n * Whether the current selection lives inside this node's subtree — the\n * node itself or any of its descendants is selected. Canvas chrome uses\n * this to expand collapsed containers (menus, drawers) only while they\n * are being authored (AGL-571).\n */\n readonly isNodeOrDescendantSelected: (node: Aglyn.NodeSchema) => boolean\n readonly isNodeHovered: (node: Aglyn.NodeSchema) => boolean\n readonly isNodeExpanded: (node: Aglyn.NodeSchema) => boolean\n /**\n * Whether a node is currently visually open in the tree — either because the\n * user manually expanded it, or because it is an auto-expanded ancestor of a\n * selected node that has not been manually collapsed.\n */\n readonly isNodeEffectivelyExpanded: (node: Aglyn.NodeSchema) => boolean\n}\n\nconst state = observable<FocusState>({\n hovered: null,\n selected: [],\n expanded: [],\n manuallyCollapsed: [],\n\n get allExpanded(): Aglyn.NodeSchema<any>[] {\n return [...this.expanded, ...this.selected]\n },\n get lastSelected(): Aglyn.NodeSchema<any> | undefined {\n return this.selected[this.selected.length - 1]\n },\n get selectionCount(): number {\n return this.selected.length\n },\n get hasMultipleSelected(): boolean {\n return this.selected.length > 1\n },\n\n isNodeSelected: computedFn((node: Aglyn.NodeSchema<any>): boolean => {\n if (!node) return false\n return state.selected.some((i) => i?.$id === node?.$id)\n }),\n isNodeOrDescendantSelected: computedFn(\n (node: Aglyn.NodeSchema<any>): boolean => {\n if (!node) return false\n // A node's breadcrumbPath is [root, ...ancestors, self], so a\n // selected node whose path contains this id makes this node the\n // selection itself or one of its ancestors — i.e. the selection is\n // within this node's subtree.\n return state.selected.some(\n (selectedNode) =>\n selectedNode?.$id === node.$id ||\n selectedNode?.breadcrumbPath?.includes(node.$id),\n )\n },\n ),\n isNodeHovered: computedFn((node: Aglyn.NodeSchema<any>): boolean => {\n if (!node) return false\n return state.hovered?.$id === node?.$id\n }),\n isNodeExpanded: computedFn((node: Aglyn.NodeSchema<any>): boolean => {\n if (!node) return false\n return state.expanded.some((i) => i?.$id === node?.$id)\n }),\n isNodeEffectivelyExpanded: computedFn((node: Aglyn.NodeSchema<any>): boolean => {\n if (!node) return false\n // Manually expanded always wins\n if (state.expanded.some((i) => i?.$id === node?.$id)) return true\n // If the user explicitly collapsed this node, treat it as collapsed\n if (state.manuallyCollapsed.includes(node.$id)) return false\n // Auto-expanded: this node is an ancestor of a manually expanded node\n // (mirrors the view's allExpanded breadcrumb-path logic exactly)\n if (state.expanded.some((n) => n?.breadcrumbPath?.includes(node.$id))) return true\n // Auto-expanded: this node is an ancestor of a selected node\n return state.selected.some((selectedNode) =>\n selectedNode?.breadcrumbPath?.includes(node.$id),\n )\n }),\n})\n\nexport function getLastSelected(): LastSelectedNode {\n return state.lastSelected\n}\n\nexport function selectionCount(): number {\n return state.selectionCount\n}\n\nexport function hasMultipleSelected(): boolean {\n return state.hasMultipleSelected\n}\n\nexport function getHovered(): HoveredNode | undefined {\n return state.hovered\n}\n\nexport function getSelected(): SelectedNodes {\n return state.selected\n}\n\nexport function getAllExpanded(): ExpandedNodes & SelectedNodes {\n return state.allExpanded\n}\n\nexport function getManuallyCollapsed(): Aglyn.NodeId[] {\n return state.manuallyCollapsed\n}\n\nexport function isNodeSelected(node: Aglyn.NodeSchema<any>) {\n return state.isNodeSelected(node)\n}\n\nexport function isNodeOrDescendantSelected(node: Aglyn.NodeSchema<any>) {\n return state.isNodeOrDescendantSelected(node)\n}\n\nexport function isNodeHovered(node: Aglyn.NodeSchema<any>) {\n return state.isNodeHovered(node)\n}\n\nexport function isNodeExpanded(node: Aglyn.NodeSchema<any>) {\n return state.isNodeExpanded(node)\n}\n\nexport function isNodeEffectivelyExpanded(node: Aglyn.NodeSchema<any>) {\n return state.isNodeEffectivelyExpanded(node)\n}\n\nexport function clearFocusStatus() {\n runInAction(() => {\n state.selected = []\n state.hovered = null\n })\n}\n\nexport function clearSelection() {\n runInAction(() => {\n state.selected = []\n })\n}\n\nexport function clearHover() {\n runInAction(() => {\n state.hovered = null\n })\n}\n\nexport function expandNode(node: Aglyn.NodeSchema<any>) {\n if (!node) return\n runInAction(() => {\n // Clear any manual-collapse override so the node stays open\n const mcIndex = state.manuallyCollapsed.indexOf(node.$id)\n if (mcIndex !== -1) state.manuallyCollapsed.splice(mcIndex, 1)\n\n if (!state.expanded.some((i) => i?.$id === node?.$id)) {\n state.expanded.push(node)\n }\n })\n}\n\nexport function collapseNode(node: Aglyn.NodeSchema<any>) {\n if (!node) return\n runInAction(() => {\n // Remove from manually-expanded if present\n const index = state.expanded.findIndex((i) => i?.$id === node?.$id)\n if (index !== -1) state.expanded.splice(index, 1)\n\n // After removal, check if the node is still visually open because it is an\n // ancestor of another expanded node or of a selected node. If so, record a\n // manual-collapse override so those auto-expansion sources are suppressed.\n const stillEffectivelyExpanded =\n state.expanded.some((n) => n?.breadcrumbPath?.includes(node.$id)) ||\n state.selected.some((s) => s?.breadcrumbPath?.includes(node.$id))\n\n if (stillEffectivelyExpanded && !state.manuallyCollapsed.includes(node.$id)) {\n state.manuallyCollapsed.push(node.$id)\n }\n })\n}\n\nexport function toggleNodeExpansion(node: Aglyn.NodeSchema<any>) {\n if (!node) return\n // Use effective expansion so auto-expanded nodes can also be toggled closed\n if (isNodeEffectivelyExpanded(node)) return collapseNode(node)\n return expandNode(node)\n}\n\n/**\n * What a click on a node means, in the hierarchy and on the canvas alike.\n *\n * Toggling belongs to Cmd/Ctrl-click — which is exactly what\n * `multiSelection` means at both call sites, and what both of their comments\n * already claimed. A PLAIN click always selects (AGL-2486): it used to\n * toggle, so clicking the row of a node that was already selected DESELECTED\n * it, and since the hierarchy's expansion is derived from the selection\n * (`allExpanded`), the tree then collapsed to the document root and the row\n * vanished from under the pointer. Every way of putting a new element on the\n * canvas leaves it selected, so \"add an element, then click it in the\n * hierarchy\" hit this every time.\n */\nexport function handleNodeSelection(\n node: Aglyn.NodeSchema<any>,\n multiSelection = false,\n) {\n if (multiSelection && isNodeSelected(node)) {\n deselectNode(node, multiSelection)\n return\n }\n setSelectedNode(node, multiSelection)\n}\n\nexport function deselectNode(\n node: Aglyn.NodeSchema<any>,\n multiSelection = false,\n) {\n if (!isNodeSelected(node)) return\n runInAction(() => {\n if (multiSelection) {\n const selectIndex = state.selected.indexOf(node)\n state.selected.splice(selectIndex, 1)\n } else {\n state.selected = []\n }\n })\n}\n\nexport function setSelectedNode(\n node: Aglyn.NodeSchema<any>,\n multiSelection = false,\n) {\n // Already the sole selection, or already a member of a multi-selection\n // being added to: nothing to do. A plain (single) select of a node that is\n // one of SEVERAL still has work — it collapses the selection down to that\n // node — so it deliberately falls through.\n if (isNodeSelected(node) && (multiSelection || state.selected.length === 1)) {\n return\n }\n runInAction(() => {\n if (multiSelection) state.selected.push(node)\n else state.selected = [node]\n\n // Clear manual-collapse overrides for ancestors of the newly selected node\n // so the hierarchy always opens up to reveal it\n const ancestorIds = new Set<Aglyn.NodeId>(node?.breadcrumbPath ?? [])\n state.manuallyCollapsed = state.manuallyCollapsed.filter(\n (id) => !ancestorIds.has(id),\n )\n })\n}\n\n/**\n * Where the selection should land once `nodes` are deleted, best first\n * (AGL-2553).\n *\n * Deleting used to clear the selection outright, and the hierarchy collapsing\n * was the consequence: the tree only holds a branch open to reveal what is\n * selected, so with nothing selected a subtree the author had navigated into\n * snapped shut on every delete.\n *\n * Order is next sibling, then previous, then the parent. NEXT first because\n * it slides into the deleted node's slot — the highlight stays where the\n * author's eye already is, rather than stepping backwards. Previous covers\n * deleting the last child, and the parent covers an only child, where keeping\n * the branch open one level up is still better than closing it.\n *\n * ⚑ Returns CANDIDATES rather than a node, because it must be called BEFORE\n * the delete — sibling indices shift once it runs — and the caller selects the\n * first that survives. That ordering is what makes multi-selection safe\n * without walking ancestors: a sibling that was itself doomed, or that hung\n * off a doomed node, is simply absent from the map afterwards and the next\n * candidate wins.\n */\nexport function resolveSelectionAfterDeletion(\n nodes: readonly Aglyn.NodeSchema<any>[],\n): Aglyn.NodeSchema<any>[] {\n const anchor = nodes.find((node) => node?.$id && node?.parentId)\n if (!anchor) return []\n const parent = canvas.getNode(anchor.parentId!)\n if (!parent) return []\n\n const siblings = parent.nodes ?? []\n const index = siblings.indexOf(anchor.$id)\n const candidates: Aglyn.NodeSchema<any>[] = []\n if (index > -1) {\n for (let i = index + 1; i < siblings.length; i += 1) {\n const sibling = canvas.getNode(siblings[i])\n if (sibling) candidates.push(sibling)\n }\n for (let i = index - 1; i >= 0; i -= 1) {\n const sibling = canvas.getNode(siblings[i])\n if (sibling) candidates.push(sibling)\n }\n }\n candidates.push(parent)\n return candidates\n}\n\n/**\n * Selects the first of `candidates` that still exists, or clears the\n * selection when none do. The other half of\n * {@link resolveSelectionAfterDeletion}; call it AFTER the delete.\n */\nexport function selectFirstSurviving(\n candidates: readonly Aglyn.NodeSchema<any>[],\n): void {\n const survivor = candidates.find((node) => !!canvas.getNode(node.$id))\n if (survivor) setSelectedNode(survivor)\n else clearSelection()\n}\n\n/**\n * Flat, depth-first list of the nodes currently visible in the hierarchy —\n * children of collapsed nodes are skipped (AGL-6). Range selection resolves\n * its slice against this order.\n */\nexport function getVisibleNodeOrder(): Aglyn.NodeSchema<any>[] {\n const result: Aglyn.NodeSchema<any>[] = []\n const root = canvas.rootNode\n if (!root) return result\n const walk = (node: Aglyn.NodeSchema<any>) => {\n result.push(node)\n if (node.$id !== root.$id && !state.isNodeEffectivelyExpanded(node)) return\n for (const id of node.nodes ?? []) {\n const child = canvas.getNode(id)\n if (child) walk(child)\n }\n }\n walk(root)\n return result\n}\n\n/**\n * Shift+Click range selection (AGL-7): selects every visible node between\n * the current anchor (`lastSelected`) and the target, in document order.\n * Without an anchor it falls back to single selection.\n */\nexport function rangeSelectNode(node: Aglyn.NodeSchema<any>) {\n if (!node) return\n const anchor = state.lastSelected\n if (!anchor || anchor.$id === node.$id) return setSelectedNode(node, false)\n\n const visibleNodes = getVisibleNodeOrder()\n const anchorIndex = visibleNodes.findIndex((n) => n.$id === anchor.$id)\n const targetIndex = visibleNodes.findIndex((n) => n.$id === node.$id)\n if (anchorIndex === -1 || targetIndex === -1) {\n return setSelectedNode(node, false)\n }\n const [from, to] =\n anchorIndex < targetIndex\n ? [anchorIndex, targetIndex]\n : [targetIndex, anchorIndex]\n runInAction(() => {\n state.selected = visibleNodes.slice(from, to + 1)\n })\n}\n\n/**\n * Cmd/Ctrl+A helper (AGL-7): selects every visible node at the same tree\n * depth as the current selection anchor (siblings-and-cousins). No-ops\n * without an anchor.\n */\nexport function selectAllAtDepth() {\n const anchor = state.lastSelected\n if (!anchor) return\n const depth = anchor.breadcrumbPath?.length ?? 0\n const peers = getVisibleNodeOrder().filter(\n (node) => (node.breadcrumbPath?.length ?? 0) === depth,\n )\n if (!peers.length) return\n runInAction(() => {\n state.selected = peers\n })\n}\n\nexport function setHoveredNode(node: Aglyn.NodeSchema<any>) {\n if (isNodeHovered(node)) return\n runInAction(() => {\n state.hovered = node\n })\n}\n\nexport function dehoverNode(node: Aglyn.NodeSchema<any>) {\n if (!isNodeHovered(node)) return\n runInAction(() => {\n state.hovered = null\n })\n}\n"],"names":["canvas","observable","runInAction","computedFn","state","hovered","selected","expanded","manuallyCollapsed","allExpanded","lastSelected","length","selectionCount","hasMultipleSelected","isNodeSelected","node","some","i","$id","isNodeOrDescendantSelected","selectedNode","breadcrumbPath","includes","isNodeHovered","isNodeExpanded","isNodeEffectivelyExpanded","n","getLastSelected","getHovered","getSelected","getAllExpanded","getManuallyCollapsed","clearFocusStatus","clearSelection","clearHover","expandNode","mcIndex","indexOf","splice","push","collapseNode","index","findIndex","stillEffectivelyExpanded","s","toggleNodeExpansion","handleNodeSelection","multiSelection","deselectNode","setSelectedNode","selectIndex","ancestorIds","Set","filter","id","has","resolveSelectionAfterDeletion","nodes","parent","anchor","find","parentId","getNode","siblings","candidates","sibling","selectFirstSurviving","survivor","getVisibleNodeOrder","result","root","rootNode","walk","child","rangeSelectNode","visibleNodes","anchorIndex","targetIndex","from","to","slice","selectAllAtDepth","depth","peers","setHoveredNode","dehoverNode"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export * as focus from './focus-manager';
18
+ export { type HoveredNode, type SelectedNodes, type ExpandedNodes, type LastSelectedNode, } from './focus-manager';
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import * as _focus from "./focus-manager.js";
17
+ export { _focus as focus };
18
+
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/focus-manager/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * as focus from './focus-manager'\nexport {\n type HoveredNode,\n type SelectedNodes,\n type ExpandedNodes,\n type LastSelectedNode,\n} from './focus-manager'\n"],"names":["focus"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,wBAAuB,qBAAiB;AAAxC,SAAO,UAAKA,KAAK,GAAuB"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { CANVAS_ROOT_ELEMENT_ID, NodeId } from '@aglyn/aglyn';
18
+ export declare const isRootElementId: ($id: NodeId) => $id is CANVAS_ROOT_ELEMENT_ID;
19
+ export default isRootElementId;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { CANVAS_ROOT_ELEMENT_ID } from "@aglyn/aglyn";
17
+ export const isRootElementId = ($id)=>{
18
+ return $id === CANVAS_ROOT_ELEMENT_ID;
19
+ };
20
+ export default isRootElementId;
21
+
22
+ //# sourceMappingURL=is-root-element-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/besigner/core/src/lib/is-root-element-id.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CANVAS_ROOT_ELEMENT_ID, NodeId } from '@aglyn/aglyn'\n\nexport const isRootElementId = ($id: NodeId): $id is CANVAS_ROOT_ELEMENT_ID => {\n return $id === CANVAS_ROOT_ELEMENT_ID\n}\n\nexport default isRootElementId\n"],"names":["CANVAS_ROOT_ELEMENT_ID","isRootElementId","$id"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD,SAASA,sBAAsB,QAAgB,eAAc;AAE7D,OAAO,MAAMC,kBAAkB,CAACC;IAC9B,OAAOA,QAAQF;AACjB,EAAC;AAED,eAAeC,gBAAe"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { DndManager } from './dnd-manager';
18
+ export * from './node-refs';
19
+ export * from './clipboard-manager';
20
+ export * from './dnd-manager';
21
+ export * from './focus-manager';
22
+ export * from './node-move';
23
+ export * from './pick-manager';
24
+ export * from './text-entry';
25
+ export declare const dnd: DndManager;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { DndManager } from "./dnd-manager/index.js";
17
+ export * from "./node-refs/index.js";
18
+ export * from "./clipboard-manager/index.js";
19
+ export * from "./dnd-manager/index.js";
20
+ export * from "./focus-manager/index.js";
21
+ export * from "./node-move/index.js";
22
+ export * from "./pick-manager/index.js";
23
+ export * from "./text-entry/index.js";
24
+ export const dnd = new DndManager();
25
+
26
+ //# sourceMappingURL=managers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/besigner/core/src/lib/managers.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DndManager } from './dnd-manager'\n\nexport * from './node-refs'\nexport * from './clipboard-manager'\nexport * from './dnd-manager'\nexport * from './focus-manager'\nexport * from './node-move'\nexport * from './pick-manager'\nexport * from './text-entry'\n\nexport const dnd = new DndManager()\n"],"names":["DndManager","dnd"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,UAAU,QAAQ,yBAAe;AAE1C,cAAc,uBAAa;AAC3B,cAAc,+BAAqB;AACnC,cAAc,yBAAe;AAC7B,cAAc,2BAAiB;AAC/B,cAAc,uBAAa;AAC3B,cAAc,0BAAgB;AAC9B,cAAc,wBAAc;AAE5B,OAAO,MAAMC,MAAM,IAAID,aAAY"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export { canMoveNodeIn, canMoveNodeOut, type MoveResult, moveNodeIn, moveNodeOut, resolveMoveIn, resolveMoveOut, } from './node-move';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ export { canMoveNodeIn, canMoveNodeOut, moveNodeIn, moveNodeOut, resolveMoveIn, resolveMoveOut } from "./node-move.js";
17
+
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/node-move/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport {\n canMoveNodeIn,\n canMoveNodeOut,\n type MoveResult,\n moveNodeIn,\n moveNodeOut,\n resolveMoveIn,\n resolveMoveOut,\n} from './node-move'\n"],"names":["canMoveNodeIn","canMoveNodeOut","moveNodeIn","moveNodeOut","resolveMoveIn","resolveMoveOut"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,aAAa,EACbC,cAAc,EAEdC,UAAU,EACVC,WAAW,EACXC,aAAa,EACbC,cAAc,QACT,iBAAa"}