@aglyn/besigner 1.0.0-beta.273 → 1.0.0-beta.277

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/besigner",
3
- "version": "1.0.0-beta.273",
3
+ "version": "1.0.0-beta.277",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,11 +25,11 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.0.0-beta.273",
29
- "@aglyn/shared-data-types": "1.0.0-beta.273",
30
- "@aglyn/shared-util-logger": "1.0.0-beta.273",
31
- "@aglyn/shared-util-tools": "1.0.0-beta.273",
32
- "@aglyn/shared-util-vendor": "1.0.0-beta.273",
28
+ "@aglyn/aglyn": "1.0.0-beta.277",
29
+ "@aglyn/shared-data-types": "1.0.0-beta.277",
30
+ "@aglyn/shared-util-logger": "1.0.0-beta.277",
31
+ "@aglyn/shared-util-tools": "1.0.0-beta.277",
32
+ "@aglyn/shared-util-vendor": "1.0.0-beta.277",
33
33
  "@swc/helpers": "0.5.23",
34
34
  "lodash-es": "^4.18.1",
35
35
  "mobx": "^7.0.5",
@@ -71,5 +71,7 @@ export declare class DndManager {
71
71
  setDropNode(node: DraggableNode): this;
72
72
  setDropRegion(region: DropRegion): this;
73
73
  onDragEnd(): void;
74
+ /** Commits the pending drop, or does nothing when it would be refused. */
75
+ private landDrop;
74
76
  }
75
77
  export default DndManager;
@@ -50,6 +50,8 @@ export class DndManager {
50
50
  return 0x2;
51
51
  }
52
52
  get computedDrop() {
53
+ var _ref;
54
+ var _canvas_getNode;
53
55
  if (!this.drop) return this.drop;
54
56
  if (canvas.isRootNode(this.drop)) return this.drop;
55
57
  if (!this.dropRegion) return this.drop;
@@ -63,7 +65,10 @@ export class DndManager {
63
65
  if (node && !canvas.nodeAcceptsChildren(node)) return node.parent;
64
66
  return this.drop;
65
67
  }
66
- return canvas.getNode(this.drop.$id).parent;
68
+ // The target can be gone by the time this is read — undone, or removed
69
+ // by a co-editor mid-drag. Nothing to resolve against, rather than a
70
+ // throw out of the drag's end that would leave its state painted.
71
+ return (_ref = (_canvas_getNode = canvas.getNode(this.drop.$id)) == null ? void 0 : _canvas_getNode.parent) != null ? _ref : null;
67
72
  }
68
73
  get hasDragTarget() {
69
74
  return Boolean(this.drag);
@@ -240,9 +245,21 @@ export class DndManager {
240
245
  return this;
241
246
  }
242
247
  onDragEnd() {
243
- if (!this.drop || !this.drag) return;
244
- if (this.dropIsInsideDrag) return;
245
- if (!this.isValidLinealRelationship) return;
248
+ // Every drag ends by clearing, landed, refused or thrown. A drag that
249
+ // left its state set kept painting it — the dragged node's wash, the
250
+ // ring on the target and every ancestor of it, the hierarchy row that
251
+ // stops taking drops while it is dragged — until the next drag began.
252
+ try {
253
+ this.landDrop();
254
+ } finally{
255
+ this.clearDndStatus();
256
+ }
257
+ }
258
+ /** Commits the pending drop, or does nothing when it would be refused. */ landDrop() {
259
+ if (!this.drop || !this.drag || // Gone since the pointer got there: there is no slot left to name.
260
+ !canvas.getNode(this.drop.$id) || this.dropIsInsideDrag || !this.isValidLinealRelationship) {
261
+ return;
262
+ }
246
263
  const dragNode = this.drag;
247
264
  const dropNode = this.drop;
248
265
  const region = this.dropRegion;
@@ -274,10 +291,7 @@ export class DndManager {
274
291
  // it would deepen the same hole. `reparentNode` refuses this outright
275
292
  // now (AGL-1405); catch it here so a drag ends quietly instead of
276
293
  // throwing out of the pointer handler.
277
- if (!parent || !canvas.nodeAcceptsChildren(parent)) {
278
- this.clearDndStatus();
279
- return;
280
- }
294
+ if (!parent || !canvas.nodeAcceptsChildren(parent)) return;
281
295
  if (dragNode.type === NodeType.PRESET) {
282
296
  canvas.addNodeFromPreset(dragNode, parent, position);
283
297
  // Besigner.focus.setSelectedNode(newNode)
@@ -323,7 +337,6 @@ export class DndManager {
323
337
  if (!Number.isNaN(position)) position += 1;
324
338
  }
325
339
  }
326
- this.clearDndStatus();
327
340
  }
328
341
  constructor(){
329
342
  this.drag = null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/dnd-manager/dnd-manager.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 type * as Aglyn from '@aglyn/aglyn'\nimport { canvas, components, isFeatureEnabled, NodeType } from '@aglyn/aglyn'\nimport {\n confirmValidLinealRelationship,\n type ConfirmValidLinealRelationshipResponse,\n describeInvalidLinealRelationship,\n type InvalidLinealRelationFlag,\n type LinealItem,\n} from './confirm-valid-lineal-relationship'\nimport { makeAutoObservable } from 'mobx'\nimport { getSelected, isNodeSelected } from '../focus-manager/focus-manager'\n\nexport enum DragType {\n CANVAS = 'canvas',\n PRESET = 'preset',\n TREE = 'tree',\n}\n\nexport enum DropAreaType {\n BEFORE = 0x1,\n INSIDE = 0x2,\n AFTER = 0x3,\n}\n\nexport enum DropRegion {\n CHILDREN = 'children',\n TOP = 'top',\n RIGHT = 'right',\n BOTTOM = 'bottom',\n LEFT = 'left',\n}\n\nexport type DraggableNode = Aglyn.NodeSchema<any> | Aglyn.PresetSchema<any>\n\nexport class DndManager {\n drag?: DraggableNode = null\n drop?: DraggableNode = null\n dropRegion?: DropRegion | null = null\n public get intoArea(): DropAreaType {\n switch (this.dropRegion) {\n case DropRegion.TOP:\n case DropRegion.LEFT:\n return DropAreaType.BEFORE\n case DropRegion.RIGHT:\n case DropRegion.BOTTOM:\n return DropAreaType.AFTER\n }\n\n return DropAreaType.INSIDE\n }\n\n public get computedDrop() {\n if (!this.drop) return this.drop\n if (canvas.isRootNode(this.drop)) return this.drop\n if (!this.dropRegion) return this.drop\n if (this.dropRegion === DropRegion.CHILDREN) {\n // A leaf (self-closing / text-editable) has no slot for node children,\n // so a center/CHILDREN drop resolves against its PARENT and lands as a\n // sibling — mirroring the Insert menu's leaf handling (AGL-575). This\n // also makes the lineal check validate against the real parent instead\n // of the leaf, which (declaring no restrictChildren) would wrongly pass.\n const node = canvas.getNode(this.drop.$id)\n if (node && !canvas.nodeAcceptsChildren(node)) return node.parent\n return this.drop\n }\n return canvas.getNode(this.drop.$id).parent\n }\n\n public get hasDragTarget(): boolean {\n return Boolean(this.drag)\n }\n public get hasDropTarget(): boolean {\n return Boolean(this.drop)\n }\n public get dragBreadcrumbs(): Aglyn.NodeBreadcrumbPath | false {\n if (!this.hasDragTarget) return false\n return this.drag?.breadcrumbPath\n }\n public get dropBreadcrumbs(): Aglyn.NodeBreadcrumbPath | false {\n if (!this.hasDropTarget) return false\n return this.drop?.breadcrumbPath\n }\n public get dropIsInsideDrag() {\n return Boolean(\n this.computedDrop?.breadcrumbPath?.some((i) => i === this.drag?.$id),\n )\n }\n /**\n * Multi-drag (AGL-13): when the dragged node is part of the current\n * multi-selection, every draggable selected node moves; otherwise just\n * the dragged node. Presets never join a selection.\n */\n public get dragNodes(): DraggableNode[] {\n if (\n this.drag &&\n this.drag.type === NodeType.NODE &&\n isNodeSelected(this.drag as Aglyn.NodeSchema<any>)\n ) {\n const selected = getSelected().filter((node) => this.canDragNode(node))\n if (selected.length > 1) {\n // Document order (not selection order) so relative positions\n // survive the move: compare breadcrumb paths by sibling index.\n const orderKey = (node: Aglyn.NodeSchema<any>): number[] =>\n (node.breadcrumbPath ?? []).map((id) => {\n try {\n return canvas.getNodeIndex(canvas.getNode(id))\n } catch {\n return 0\n }\n })\n return [...selected].sort((a, b) => {\n const left = orderKey(a)\n const right = orderKey(b)\n for (let i = 0; i < Math.max(left.length, right.length); i += 1) {\n const diff = (left[i] ?? -1) - (right[i] ?? -1)\n if (diff !== 0) return diff\n }\n return 0\n })\n }\n if (selected.length === 1) return selected\n }\n return this.drag ? [this.drag] : []\n }\n /** Item/parent descriptors for the pending drop, or null without targets. */\n private get dropRelationshipActors(): {\n item: LinealItem\n parent: LinealItem\n } | null {\n if (!this.hasDragTarget || !this.hasDropTarget) return null\n const parent: LinealItem = {\n pluginId: this.computedDrop?.pluginId,\n componentId: this.computedDrop?.componentId,\n restrictChildren: this.computedDrop?.componentSchema?.restrictChildren,\n restrictParent: this.computedDrop?.componentSchema?.restrictParent,\n }\n\n if (this.drag?.type === NodeType.PRESET) {\n const preset = this.drag as Aglyn.PresetSchema<any>\n const itemNode = preset.data\n const itemSchema = components.getSchema(itemNode?.componentId)\n return {\n item: {\n pluginId: preset.data?.pluginId,\n componentId: itemNode?.componentId,\n restrictChildren: itemSchema?.restrictChildren,\n restrictParent: itemSchema?.restrictParent,\n },\n parent,\n }\n }\n return {\n item: {\n pluginId: this.drag?.pluginId,\n componentId: this.drag?.componentId,\n restrictChildren: this.drag?.componentSchema?.restrictChildren,\n restrictParent: this.drag?.componentSchema?.restrictParent,\n },\n parent,\n }\n }\n\n public get linealValidation(): ConfirmValidLinealRelationshipResponse {\n const actors = this.dropRelationshipActors\n if (!actors) return [false, 0 as InvalidLinealRelationFlag]\n return confirmValidLinealRelationship(actors.item, actors.parent)\n }\n\n public get isValidLinealRelationship(): boolean {\n return this.linealValidation[0]\n }\n\n /**\n * Human-readable reason the pending drop would be rejected, or null when\n * the drop is valid (or there is nothing to validate). Read this before\n * onDragEnd — completing the drag clears the dnd state.\n */\n public describeDropRejection(): string | null {\n const actors = this.dropRelationshipActors\n if (!actors) return null\n if (this.dropIsInsideDrag) {\n return \"An element can't be moved inside itself\"\n }\n // Says out loud what `onDragEnd` refuses silently: the resolved parent\n // has no slot a child could render into (AGL-1405).\n const into = this.computedDrop as Aglyn.NodeSchema<any>\n if (into && !canvas.nodeAcceptsChildren(into)) {\n return `${into.labelShort || 'That element'} can't hold other elements`\n }\n const [valid, reason] = confirmValidLinealRelationship(\n actors.item,\n actors.parent,\n )\n if (valid) return null\n return describeInvalidLinealRelationship(actors.item, actors.parent, reason)\n }\n\n constructor() {\n makeAutoObservable(this)\n }\n\n public isDraggingNode(node: DraggableNode): boolean {\n if (!node) return false\n return node?.$id === this.drag?.$id\n }\n public isDraggingDropNode(node: DraggableNode): boolean {\n if (!node) return false\n return node?.$id === this.drop?.$id\n }\n public isDraggingOverDropNode(node: DraggableNode): boolean {\n if (!node) return false\n const breadcrumbs = this.dropBreadcrumbs\n return Array.isArray(breadcrumbs) && breadcrumbs.indexOf(node?.$id) >= 0\n }\n canDragNode(node: DraggableNode): boolean {\n if (!node) throw new Error('Invalid node')\n switch (true) {\n case canvas.isRootNode(node):\n return false\n case node?.type === NodeType.PRESET:\n return true\n case node?.type === NodeType.NODE:\n return isFeatureEnabled(\n (node as Aglyn.NodeSchema<any>)?.componentSchema?.flags?.dragging,\n )\n default:\n return false\n }\n }\n\n public clearDndStatus() {\n this.drag = null\n this.drop = null\n this.dropRegion = null\n return this\n }\n\n public setDragNode(node: DraggableNode) {\n this.drag = node || null\n return this\n }\n public setDropNode(node: DraggableNode) {\n this.drop = node || null\n return this\n }\n public setDropRegion(region: DropRegion) {\n this.dropRegion = region || null\n return this\n }\n public onDragEnd() {\n if (!this.drop || !this.drag) return\n if (this.dropIsInsideDrag) return\n if (!this.isValidLinealRelationship) return\n\n const dragNode = this.drag\n const dropNode = this.drop\n const region = this.dropRegion\n const before = region === DropRegion.TOP || region === DropRegion.LEFT\n const after = region === DropRegion.RIGHT || region === DropRegion.BOTTOM\n let position = NaN\n let parent\n\n if (before || after) {\n parent = canvas.getNode(dropNode.parentId)\n position = canvas.getNodeIndex(dropNode)\n if (after) position = position + 1\n } else {\n const dropTarget = canvas.getNode(dropNode.$id)\n // Leaf redirect (AGL-575 parallel): a self-closing / text-editable\n // target has no children slot, so a center drop becomes a sibling right\n // after it rather than a nested child. Non-leaf containers still nest.\n if (\n dropTarget &&\n dropNode.parentId &&\n !canvas.nodeAcceptsChildren(dropTarget)\n ) {\n const leafIndex = canvas.getNodeIndex(dropTarget)\n parent = canvas.getNode(dropNode.parentId)\n if (leafIndex > -1) position = leafIndex + 1\n } else {\n parent = dropTarget\n }\n }\n\n // The redirect above only rescues a drop aimed AT a leaf. An edge drop\n // resolves to the drop node's existing parent, and that parent may itself\n // be unable to hold children — a node already trapped under a `markdown`\n // block (AGL-1388) has exactly that shape, so dropping a sibling next to\n // it would deepen the same hole. `reparentNode` refuses this outright\n // now (AGL-1405); catch it here so a drag ends quietly instead of\n // throwing out of the pointer handler.\n if (!parent || !canvas.nodeAcceptsChildren(parent)) {\n this.clearDndStatus()\n return\n }\n\n if (dragNode.type === NodeType.PRESET) {\n canvas.addNodeFromPreset(dragNode as Aglyn.PresetSchema<any>, parent, position)\n // Besigner.focus.setSelectedNode(newNode)\n } else {\n // Multi-drag (AGL-13): move the whole selection when the dragged\n // node is selected. Per-node guards mirror the single-node checks —\n // nodes that contain the drop target or fail the lineal rules are\n // skipped rather than failing the whole move. Sequential inserts\n // with an advancing position preserve document order (CANVAS and\n // TREE drags both land here).\n const parentSchema = components.getSchema(parent?.componentId)\n for (const node of this.dragNodes) {\n if (node.type !== NodeType.NODE) continue\n const containsDrop = Boolean(\n this.computedDrop?.breadcrumbPath?.some((id) => id === node.$id),\n )\n if (containsDrop) continue\n const [valid] = confirmValidLinealRelationship(\n {\n pluginId: node.pluginId,\n componentId: node.componentId,\n restrictChildren: (node as Aglyn.NodeSchema<any>)\n ?.componentSchema?.restrictChildren,\n restrictParent: (node as Aglyn.NodeSchema<any>)?.componentSchema\n ?.restrictParent,\n },\n {\n pluginId: parent?.pluginId,\n componentId: parent?.componentId,\n restrictChildren: parentSchema?.restrictChildren,\n restrictParent: parentSchema?.restrictParent,\n },\n )\n if (!valid) continue\n\n // An edge drop names a GAP in the sibling list as it stands now —\n // \"before whatever is at index 2\". `reparentNode` indexes the list it\n // is left with, after this node has been spliced out of it. Those\n // agree for a drop into a different parent; among the node's OWN\n // siblings every slot past it shifts down by one, so without this the\n // drag lands one place late — and dropping a node just above itself\n // resolves to the slot it is already in, which is what made the\n // hierarchy drag look inert (AGL-1405).\n let at = position\n if (!Number.isNaN(at) && node.parentId === parent?.$id) {\n const from = canvas.getNodeIndex(node)\n if (from > -1 && from < at) at -= 1\n }\n canvas.reparentNode(node, parent, at)\n if (!Number.isNaN(position)) position += 1\n }\n }\n\n this.clearDndStatus()\n }\n}\n\nexport default DndManager\n"],"names":["canvas","components","isFeatureEnabled","NodeType","confirmValidLinealRelationship","describeInvalidLinealRelationship","makeAutoObservable","getSelected","isNodeSelected","DragType","DropAreaType","DropRegion","DndManager","intoArea","dropRegion","computedDrop","drop","isRootNode","node","getNode","$id","nodeAcceptsChildren","parent","hasDragTarget","Boolean","drag","hasDropTarget","dragBreadcrumbs","breadcrumbPath","dropBreadcrumbs","dropIsInsideDrag","some","i","dragNodes","type","NODE","selected","filter","canDragNode","length","orderKey","map","id","getNodeIndex","sort","a","b","left","right","Math","max","diff","dropRelationshipActors","pluginId","componentId","restrictChildren","componentSchema","restrictParent","PRESET","preset","itemNode","data","itemSchema","getSchema","item","linealValidation","actors","isValidLinealRelationship","describeDropRejection","into","labelShort","valid","reason","isDraggingNode","isDraggingDropNode","isDraggingOverDropNode","breadcrumbs","Array","isArray","indexOf","Error","flags","dragging","clearDndStatus","setDragNode","setDropNode","setDropRegion","region","onDragEnd","dragNode","dropNode","before","after","position","NaN","parentId","dropTarget","leafIndex","addNodeFromPreset","parentSchema","containsDrop","at","Number","isNaN","from","reparentNode"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/dnd-manager/dnd-manager.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 type * as Aglyn from '@aglyn/aglyn'\nimport { canvas, components, isFeatureEnabled, NodeType } from '@aglyn/aglyn'\nimport {\n confirmValidLinealRelationship,\n type ConfirmValidLinealRelationshipResponse,\n describeInvalidLinealRelationship,\n type InvalidLinealRelationFlag,\n type LinealItem,\n} from './confirm-valid-lineal-relationship'\nimport { makeAutoObservable } from 'mobx'\nimport { getSelected, isNodeSelected } from '../focus-manager/focus-manager'\n\nexport enum DragType {\n CANVAS = 'canvas',\n PRESET = 'preset',\n TREE = 'tree',\n}\n\nexport enum DropAreaType {\n BEFORE = 0x1,\n INSIDE = 0x2,\n AFTER = 0x3,\n}\n\nexport enum DropRegion {\n CHILDREN = 'children',\n TOP = 'top',\n RIGHT = 'right',\n BOTTOM = 'bottom',\n LEFT = 'left',\n}\n\nexport type DraggableNode = Aglyn.NodeSchema<any> | Aglyn.PresetSchema<any>\n\nexport class DndManager {\n drag?: DraggableNode = null\n drop?: DraggableNode = null\n dropRegion?: DropRegion | null = null\n public get intoArea(): DropAreaType {\n switch (this.dropRegion) {\n case DropRegion.TOP:\n case DropRegion.LEFT:\n return DropAreaType.BEFORE\n case DropRegion.RIGHT:\n case DropRegion.BOTTOM:\n return DropAreaType.AFTER\n }\n\n return DropAreaType.INSIDE\n }\n\n public get computedDrop() {\n if (!this.drop) return this.drop\n if (canvas.isRootNode(this.drop)) return this.drop\n if (!this.dropRegion) return this.drop\n if (this.dropRegion === DropRegion.CHILDREN) {\n // A leaf (self-closing / text-editable) has no slot for node children,\n // so a center/CHILDREN drop resolves against its PARENT and lands as a\n // sibling — mirroring the Insert menu's leaf handling (AGL-575). This\n // also makes the lineal check validate against the real parent instead\n // of the leaf, which (declaring no restrictChildren) would wrongly pass.\n const node = canvas.getNode(this.drop.$id)\n if (node && !canvas.nodeAcceptsChildren(node)) return node.parent\n return this.drop\n }\n // The target can be gone by the time this is read — undone, or removed\n // by a co-editor mid-drag. Nothing to resolve against, rather than a\n // throw out of the drag's end that would leave its state painted.\n return canvas.getNode(this.drop.$id)?.parent ?? null\n }\n\n public get hasDragTarget(): boolean {\n return Boolean(this.drag)\n }\n public get hasDropTarget(): boolean {\n return Boolean(this.drop)\n }\n public get dragBreadcrumbs(): Aglyn.NodeBreadcrumbPath | false {\n if (!this.hasDragTarget) return false\n return this.drag?.breadcrumbPath\n }\n public get dropBreadcrumbs(): Aglyn.NodeBreadcrumbPath | false {\n if (!this.hasDropTarget) return false\n return this.drop?.breadcrumbPath\n }\n public get dropIsInsideDrag() {\n return Boolean(\n this.computedDrop?.breadcrumbPath?.some((i) => i === this.drag?.$id),\n )\n }\n /**\n * Multi-drag (AGL-13): when the dragged node is part of the current\n * multi-selection, every draggable selected node moves; otherwise just\n * the dragged node. Presets never join a selection.\n */\n public get dragNodes(): DraggableNode[] {\n if (\n this.drag &&\n this.drag.type === NodeType.NODE &&\n isNodeSelected(this.drag as Aglyn.NodeSchema<any>)\n ) {\n const selected = getSelected().filter((node) => this.canDragNode(node))\n if (selected.length > 1) {\n // Document order (not selection order) so relative positions\n // survive the move: compare breadcrumb paths by sibling index.\n const orderKey = (node: Aglyn.NodeSchema<any>): number[] =>\n (node.breadcrumbPath ?? []).map((id) => {\n try {\n return canvas.getNodeIndex(canvas.getNode(id))\n } catch {\n return 0\n }\n })\n return [...selected].sort((a, b) => {\n const left = orderKey(a)\n const right = orderKey(b)\n for (let i = 0; i < Math.max(left.length, right.length); i += 1) {\n const diff = (left[i] ?? -1) - (right[i] ?? -1)\n if (diff !== 0) return diff\n }\n return 0\n })\n }\n if (selected.length === 1) return selected\n }\n return this.drag ? [this.drag] : []\n }\n /** Item/parent descriptors for the pending drop, or null without targets. */\n private get dropRelationshipActors(): {\n item: LinealItem\n parent: LinealItem\n } | null {\n if (!this.hasDragTarget || !this.hasDropTarget) return null\n const parent: LinealItem = {\n pluginId: this.computedDrop?.pluginId,\n componentId: this.computedDrop?.componentId,\n restrictChildren: this.computedDrop?.componentSchema?.restrictChildren,\n restrictParent: this.computedDrop?.componentSchema?.restrictParent,\n }\n\n if (this.drag?.type === NodeType.PRESET) {\n const preset = this.drag as Aglyn.PresetSchema<any>\n const itemNode = preset.data\n const itemSchema = components.getSchema(itemNode?.componentId)\n return {\n item: {\n pluginId: preset.data?.pluginId,\n componentId: itemNode?.componentId,\n restrictChildren: itemSchema?.restrictChildren,\n restrictParent: itemSchema?.restrictParent,\n },\n parent,\n }\n }\n return {\n item: {\n pluginId: this.drag?.pluginId,\n componentId: this.drag?.componentId,\n restrictChildren: this.drag?.componentSchema?.restrictChildren,\n restrictParent: this.drag?.componentSchema?.restrictParent,\n },\n parent,\n }\n }\n\n public get linealValidation(): ConfirmValidLinealRelationshipResponse {\n const actors = this.dropRelationshipActors\n if (!actors) return [false, 0 as InvalidLinealRelationFlag]\n return confirmValidLinealRelationship(actors.item, actors.parent)\n }\n\n public get isValidLinealRelationship(): boolean {\n return this.linealValidation[0]\n }\n\n /**\n * Human-readable reason the pending drop would be rejected, or null when\n * the drop is valid (or there is nothing to validate). Read this before\n * onDragEnd — completing the drag clears the dnd state.\n */\n public describeDropRejection(): string | null {\n const actors = this.dropRelationshipActors\n if (!actors) return null\n if (this.dropIsInsideDrag) {\n return \"An element can't be moved inside itself\"\n }\n // Says out loud what `onDragEnd` refuses silently: the resolved parent\n // has no slot a child could render into (AGL-1405).\n const into = this.computedDrop as Aglyn.NodeSchema<any>\n if (into && !canvas.nodeAcceptsChildren(into)) {\n return `${into.labelShort || 'That element'} can't hold other elements`\n }\n const [valid, reason] = confirmValidLinealRelationship(\n actors.item,\n actors.parent,\n )\n if (valid) return null\n return describeInvalidLinealRelationship(actors.item, actors.parent, reason)\n }\n\n constructor() {\n makeAutoObservable(this)\n }\n\n public isDraggingNode(node: DraggableNode): boolean {\n if (!node) return false\n return node?.$id === this.drag?.$id\n }\n public isDraggingDropNode(node: DraggableNode): boolean {\n if (!node) return false\n return node?.$id === this.drop?.$id\n }\n public isDraggingOverDropNode(node: DraggableNode): boolean {\n if (!node) return false\n const breadcrumbs = this.dropBreadcrumbs\n return Array.isArray(breadcrumbs) && breadcrumbs.indexOf(node?.$id) >= 0\n }\n canDragNode(node: DraggableNode): boolean {\n if (!node) throw new Error('Invalid node')\n switch (true) {\n case canvas.isRootNode(node):\n return false\n case node?.type === NodeType.PRESET:\n return true\n case node?.type === NodeType.NODE:\n return isFeatureEnabled(\n (node as Aglyn.NodeSchema<any>)?.componentSchema?.flags?.dragging,\n )\n default:\n return false\n }\n }\n\n public clearDndStatus() {\n this.drag = null\n this.drop = null\n this.dropRegion = null\n return this\n }\n\n public setDragNode(node: DraggableNode) {\n this.drag = node || null\n return this\n }\n public setDropNode(node: DraggableNode) {\n this.drop = node || null\n return this\n }\n public setDropRegion(region: DropRegion) {\n this.dropRegion = region || null\n return this\n }\n public onDragEnd() {\n // Every drag ends by clearing, landed, refused or thrown. A drag that\n // left its state set kept painting it — the dragged node's wash, the\n // ring on the target and every ancestor of it, the hierarchy row that\n // stops taking drops while it is dragged — until the next drag began.\n try {\n this.landDrop()\n } finally {\n this.clearDndStatus()\n }\n }\n\n /** Commits the pending drop, or does nothing when it would be refused. */\n private landDrop() {\n if (\n !this.drop ||\n !this.drag ||\n // Gone since the pointer got there: there is no slot left to name.\n !canvas.getNode(this.drop.$id) ||\n this.dropIsInsideDrag ||\n !this.isValidLinealRelationship\n ) {\n return\n }\n\n const dragNode = this.drag\n const dropNode = this.drop\n const region = this.dropRegion\n const before = region === DropRegion.TOP || region === DropRegion.LEFT\n const after = region === DropRegion.RIGHT || region === DropRegion.BOTTOM\n let position = NaN\n let parent\n\n if (before || after) {\n parent = canvas.getNode(dropNode.parentId)\n position = canvas.getNodeIndex(dropNode)\n if (after) position = position + 1\n } else {\n const dropTarget = canvas.getNode(dropNode.$id)\n // Leaf redirect (AGL-575 parallel): a self-closing / text-editable\n // target has no children slot, so a center drop becomes a sibling right\n // after it rather than a nested child. Non-leaf containers still nest.\n if (\n dropTarget &&\n dropNode.parentId &&\n !canvas.nodeAcceptsChildren(dropTarget)\n ) {\n const leafIndex = canvas.getNodeIndex(dropTarget)\n parent = canvas.getNode(dropNode.parentId)\n if (leafIndex > -1) position = leafIndex + 1\n } else {\n parent = dropTarget\n }\n }\n\n // The redirect above only rescues a drop aimed AT a leaf. An edge drop\n // resolves to the drop node's existing parent, and that parent may itself\n // be unable to hold children — a node already trapped under a `markdown`\n // block (AGL-1388) has exactly that shape, so dropping a sibling next to\n // it would deepen the same hole. `reparentNode` refuses this outright\n // now (AGL-1405); catch it here so a drag ends quietly instead of\n // throwing out of the pointer handler.\n if (!parent || !canvas.nodeAcceptsChildren(parent)) return\n\n if (dragNode.type === NodeType.PRESET) {\n canvas.addNodeFromPreset(dragNode as Aglyn.PresetSchema<any>, parent, position)\n // Besigner.focus.setSelectedNode(newNode)\n } else {\n // Multi-drag (AGL-13): move the whole selection when the dragged\n // node is selected. Per-node guards mirror the single-node checks —\n // nodes that contain the drop target or fail the lineal rules are\n // skipped rather than failing the whole move. Sequential inserts\n // with an advancing position preserve document order (CANVAS and\n // TREE drags both land here).\n const parentSchema = components.getSchema(parent?.componentId)\n for (const node of this.dragNodes) {\n if (node.type !== NodeType.NODE) continue\n const containsDrop = Boolean(\n this.computedDrop?.breadcrumbPath?.some((id) => id === node.$id),\n )\n if (containsDrop) continue\n const [valid] = confirmValidLinealRelationship(\n {\n pluginId: node.pluginId,\n componentId: node.componentId,\n restrictChildren: (node as Aglyn.NodeSchema<any>)\n ?.componentSchema?.restrictChildren,\n restrictParent: (node as Aglyn.NodeSchema<any>)?.componentSchema\n ?.restrictParent,\n },\n {\n pluginId: parent?.pluginId,\n componentId: parent?.componentId,\n restrictChildren: parentSchema?.restrictChildren,\n restrictParent: parentSchema?.restrictParent,\n },\n )\n if (!valid) continue\n\n // An edge drop names a GAP in the sibling list as it stands now —\n // \"before whatever is at index 2\". `reparentNode` indexes the list it\n // is left with, after this node has been spliced out of it. Those\n // agree for a drop into a different parent; among the node's OWN\n // siblings every slot past it shifts down by one, so without this the\n // drag lands one place late — and dropping a node just above itself\n // resolves to the slot it is already in, which is what made the\n // hierarchy drag look inert (AGL-1405).\n let at = position\n if (!Number.isNaN(at) && node.parentId === parent?.$id) {\n const from = canvas.getNodeIndex(node)\n if (from > -1 && from < at) at -= 1\n }\n canvas.reparentNode(node, parent, at)\n if (!Number.isNaN(position)) position += 1\n }\n }\n }\n}\n\nexport default DndManager\n"],"names":["canvas","components","isFeatureEnabled","NodeType","confirmValidLinealRelationship","describeInvalidLinealRelationship","makeAutoObservable","getSelected","isNodeSelected","DragType","DropAreaType","DropRegion","DndManager","intoArea","dropRegion","computedDrop","drop","isRootNode","node","getNode","$id","nodeAcceptsChildren","parent","hasDragTarget","Boolean","drag","hasDropTarget","dragBreadcrumbs","breadcrumbPath","dropBreadcrumbs","dropIsInsideDrag","some","i","dragNodes","type","NODE","selected","filter","canDragNode","length","orderKey","map","id","getNodeIndex","sort","a","b","left","right","Math","max","diff","dropRelationshipActors","pluginId","componentId","restrictChildren","componentSchema","restrictParent","PRESET","preset","itemNode","data","itemSchema","getSchema","item","linealValidation","actors","isValidLinealRelationship","describeDropRejection","into","labelShort","valid","reason","isDraggingNode","isDraggingDropNode","isDraggingOverDropNode","breadcrumbs","Array","isArray","indexOf","Error","flags","dragging","clearDndStatus","setDragNode","setDropNode","setDropRegion","region","onDragEnd","landDrop","dragNode","dropNode","before","after","position","NaN","parentId","dropTarget","leafIndex","addNodeFromPreset","parentSchema","containsDrop","at","Number","isNaN","from","reparentNode"],"mappings":"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"}
@@ -69,4 +69,52 @@ export declare function withinRegion(rect: {
69
69
  * never reads as a nest.
70
70
  */
71
71
  export declare function determineSiblingRegion(rect: DroppableClientRect, x: number, y: number): DropRegion.TOP | DropRegion.RIGHT | DropRegion.BOTTOM | DropRegion.LEFT;
72
+ /**
73
+ * The direction a target's siblings run in. It decides which two edges of the
74
+ * target mean "before" and "after": in a column those are its top and bottom,
75
+ * in a row its left and right. The other two edges mean nothing — dropping on
76
+ * the left edge of a card in a column still lands above or below it.
77
+ */
78
+ export type DropAxis = 'vertical' | 'horizontal';
79
+ /** The widest an edge band of a container gets, in px. The rest is inside. */
80
+ export declare const DROP_EDGE_BAND_MAX = 12;
81
+ /**
82
+ * How far past its boundary the pointer has to go before a before/after
83
+ * region it was already in lets go, in px (a leaf's halves hold the same
84
+ * way). Without it, a pointer resting on the line between two regions flips
85
+ * between them on every pixel of hand tremor.
86
+ */
87
+ export declare const DROP_REGION_HYSTERESIS = 4;
88
+ export interface ResolveDropRegionOptions {
89
+ rect: DroppableClientRect;
90
+ x: number;
91
+ y: number;
92
+ /** The way the target's siblings run. A column unless said otherwise. */
93
+ axis?: DropAxis;
94
+ /**
95
+ * False for a leaf (self-closing / text-editable): it has no inside, so it
96
+ * splits into a before half and an after half (AGL-575 parallel).
97
+ */
98
+ acceptsChildren?: boolean;
99
+ /** False for the document root: it has no siblings, so all of it is inside. */
100
+ acceptsSiblings?: boolean;
101
+ /**
102
+ * False where the after edge would be drawn somewhere the drop does not
103
+ * land. An expanded container in the hierarchy is the case: its bottom edge
104
+ * is the top of its first child's row, while "after it" is past its whole
105
+ * subtree. That space is inside instead.
106
+ */
107
+ allowAfter?: boolean;
108
+ /** Where the same target resolved last time, which it holds onto. */
109
+ previous?: DropRegion | null;
110
+ }
111
+ /**
112
+ * The region a point over a drop target names, for a target whose siblings
113
+ * run along `axis`.
114
+ *
115
+ * A container has a thin before band and a thin after band along that axis
116
+ * (a quarter of its length, at most {@link DROP_EDGE_BAND_MAX}) and is inside
117
+ * everywhere else. A leaf is all before and after, split at its middle.
118
+ */
119
+ export declare function resolveDropRegion(options: ResolveDropRegionOptions): DropRegion;
72
120
  export declare function determineDropRegion(clientRect: DroppableClientRect, x: number, y: number, acceptsChildren?: boolean, regions?: ReturnType<typeof buildDroppableRects>): DropRegion;
@@ -89,6 +89,46 @@ export function withinRegion(rect, x, y) {
89
89
  }
90
90
  return y < top + height / 2 ? DropRegion.TOP : DropRegion.BOTTOM;
91
91
  }
92
+ /** The widest an edge band of a container gets, in px. The rest is inside. */ export const DROP_EDGE_BAND_MAX = 12;
93
+ /**
94
+ * How far past its boundary the pointer has to go before a before/after
95
+ * region it was already in lets go, in px (a leaf's halves hold the same
96
+ * way). Without it, a pointer resting on the line between two regions flips
97
+ * between them on every pixel of hand tremor.
98
+ */ export const DROP_REGION_HYSTERESIS = 4;
99
+ /**
100
+ * The region a point over a drop target names, for a target whose siblings
101
+ * run along `axis`.
102
+ *
103
+ * A container has a thin before band and a thin after band along that axis
104
+ * (a quarter of its length, at most {@link DROP_EDGE_BAND_MAX}) and is inside
105
+ * everywhere else. A leaf is all before and after, split at its middle.
106
+ */ export function resolveDropRegion(options) {
107
+ const { rect, x, y, axis = 'vertical', acceptsChildren = true, acceptsSiblings = true, allowAfter = true, previous = null } = options;
108
+ if (!acceptsSiblings) return DropRegion.CHILDREN;
109
+ const horizontal = axis === 'horizontal';
110
+ const before = horizontal ? DropRegion.LEFT : DropRegion.TOP;
111
+ const after = horizontal ? DropRegion.RIGHT : DropRegion.BOTTOM;
112
+ const start = (horizontal ? rect == null ? void 0 : rect.left : rect == null ? void 0 : rect.top) || 0;
113
+ const size = Math.max(0, (horizontal ? rect == null ? void 0 : rect.width : rect == null ? void 0 : rect.height) || 0);
114
+ const at = (horizontal ? x : y) - start;
115
+ if (!acceptsChildren) {
116
+ const stick = Math.min(DROP_REGION_HYSTERESIS, size / 4);
117
+ let middle = size / 2;
118
+ if (previous === before) middle += stick;
119
+ if (previous === after) middle -= stick;
120
+ return at < middle ? before : after;
121
+ }
122
+ const band = Math.min(size / 4, DROP_EDGE_BAND_MAX);
123
+ // An edge band holds on once the pointer is in it, but never shrinks to
124
+ // hold inside: in a 28px hierarchy row it is only 7px to begin with, and
125
+ // halving it on the way in made "above this row" a target few could hit.
126
+ const stick = Math.min(DROP_REGION_HYSTERESIS, band / 2);
127
+ const held = (region)=>previous === region ? stick : 0;
128
+ if (at < band + held(before)) return before;
129
+ if (allowAfter && at > size - band - held(after)) return after;
130
+ return DropRegion.CHILDREN;
131
+ }
92
132
  export function determineDropRegion(clientRect, x, y, acceptsChildren = true, regions) {
93
133
  const _regions = regions || buildDroppableRects(clientRect);
94
134
  switch(true){
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/dnd-manager/droppable-region-utils.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 */\nimport { DropRegion } from './dnd-manager'\n\n// Structural rect type: dnd-kit passes a ClientRect that lacks DOMRect's\n// x/y/toJSON, and x/y are defaulted below anyway.\nexport type DroppableClientRect = Pick<\n DOMRect,\n 'width' | 'height' | 'top' | 'right' | 'bottom' | 'left'\n> &\n Partial<Pick<DOMRect, 'x' | 'y'>>\n\nexport function buildDroppableRects(rect: DroppableClientRect) {\n const {\n width = 0,\n height = 0,\n top = 0,\n right = 0,\n bottom = 0,\n left = 0,\n x = 0,\n y = 0,\n } = rect || {}\n const isHorz = (width || 0) >= (height || 0)\n\n const vertWRaw = width / 6\n const vertWidth = vertWRaw > 12 ? 12 : vertWRaw\n const vertHeight = height\n\n const horzHRaw = height / 4\n const horzWidth = width\n const horzHeight = horzHRaw > 12 ? 12 : horzHRaw\n\n const _top = {\n width: horzWidth,\n height: horzHeight,\n top: top,\n left: left,\n }\n const _bottom = {\n width: horzWidth,\n height: horzHeight,\n top: top + vertHeight - horzHeight,\n left: left,\n }\n const _left = {\n width: vertWidth,\n height: vertHeight,\n top: top,\n left: left,\n }\n const _right = {\n width: vertWidth,\n height: vertHeight,\n top: top,\n left: left + horzWidth - vertWidth,\n }\n const _children = {\n width: _top.width - vertWidth * 2,\n height: height - (_top.height + _bottom.height),\n top: top + _top.height,\n left: left + _left.width,\n }\n const _full = {\n x,\n y,\n left: _left.left,\n width: _left.width + _children.width + _right.width,\n top: _top.top,\n height: _top.height + _children.height + _bottom.height,\n }\n\n return {\n children: _children,\n top: _top,\n right: _right,\n bottom: _bottom,\n left: _left,\n full: _full,\n }\n}\n\nexport function withinRegion(rect: { left: number; top: number; width: number; height: number }, x: number, y: number) {\n const { left, top } = rect\n const { width, height } = rect\n const xis = x >= left && x <= left + width\n const yis = y >= top && y <= top + height\n return xis && yis\n}\n\n/**\n * Before/after sibling region for a point over a leaf element, split on the\n * element's dominant axis: wide elements divide left/right, tall ones divide\n * top/bottom. Used when the target can't hold node children so its center\n * never reads as a nest.\n */\nexport function determineSiblingRegion(rect: DroppableClientRect, x: number, y: number) {\n const { width = 0, height = 0, top = 0, left = 0 } = rect || {}\n if (width >= height) {\n return x < left + width / 2 ? DropRegion.LEFT : DropRegion.RIGHT\n }\n return y < top + height / 2 ? DropRegion.TOP : DropRegion.BOTTOM\n}\n\nexport function determineDropRegion(\n clientRect: DroppableClientRect,\n x: number,\n y: number,\n acceptsChildren = true,\n regions?: ReturnType<typeof buildDroppableRects>,\n) {\n const _regions = regions || buildDroppableRects(clientRect)\n switch (true) {\n case withinRegion(_regions.top, x, y):\n return DropRegion.TOP\n case withinRegion(_regions.right, x, y):\n return DropRegion.RIGHT\n case withinRegion(_regions.bottom, x, y):\n return DropRegion.BOTTOM\n case withinRegion(_regions.left, x, y):\n return DropRegion.LEFT\n case !acceptsChildren:\n // Leaf targets (self-closing / text-editable) have no children slot, so\n // the center resolves to a sibling insert rather than a nest — keeping\n // the drop indicator and the committed placement in agreement\n // (AGL-575 parallel for drag-and-drop).\n return determineSiblingRegion(clientRect, x, y)\n case withinRegion(_regions.children, x, y):\n default:\n return DropRegion.CHILDREN\n }\n}\n"],"names":["DropRegion","buildDroppableRects","rect","width","height","top","right","bottom","left","x","y","isHorz","vertWRaw","vertWidth","vertHeight","horzHRaw","horzWidth","horzHeight","_top","_bottom","_left","_right","_children","_full","children","full","withinRegion","xis","yis","determineSiblingRegion","LEFT","RIGHT","TOP","BOTTOM","determineDropRegion","clientRect","acceptsChildren","regions","_regions","CHILDREN"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/dnd-manager/droppable-region-utils.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 */\nimport { DropRegion } from './dnd-manager'\n\n// Structural rect type: dnd-kit passes a ClientRect that lacks DOMRect's\n// x/y/toJSON, and x/y are defaulted below anyway.\nexport type DroppableClientRect = Pick<\n DOMRect,\n 'width' | 'height' | 'top' | 'right' | 'bottom' | 'left'\n> &\n Partial<Pick<DOMRect, 'x' | 'y'>>\n\nexport function buildDroppableRects(rect: DroppableClientRect) {\n const {\n width = 0,\n height = 0,\n top = 0,\n right = 0,\n bottom = 0,\n left = 0,\n x = 0,\n y = 0,\n } = rect || {}\n const isHorz = (width || 0) >= (height || 0)\n\n const vertWRaw = width / 6\n const vertWidth = vertWRaw > 12 ? 12 : vertWRaw\n const vertHeight = height\n\n const horzHRaw = height / 4\n const horzWidth = width\n const horzHeight = horzHRaw > 12 ? 12 : horzHRaw\n\n const _top = {\n width: horzWidth,\n height: horzHeight,\n top: top,\n left: left,\n }\n const _bottom = {\n width: horzWidth,\n height: horzHeight,\n top: top + vertHeight - horzHeight,\n left: left,\n }\n const _left = {\n width: vertWidth,\n height: vertHeight,\n top: top,\n left: left,\n }\n const _right = {\n width: vertWidth,\n height: vertHeight,\n top: top,\n left: left + horzWidth - vertWidth,\n }\n const _children = {\n width: _top.width - vertWidth * 2,\n height: height - (_top.height + _bottom.height),\n top: top + _top.height,\n left: left + _left.width,\n }\n const _full = {\n x,\n y,\n left: _left.left,\n width: _left.width + _children.width + _right.width,\n top: _top.top,\n height: _top.height + _children.height + _bottom.height,\n }\n\n return {\n children: _children,\n top: _top,\n right: _right,\n bottom: _bottom,\n left: _left,\n full: _full,\n }\n}\n\nexport function withinRegion(rect: { left: number; top: number; width: number; height: number }, x: number, y: number) {\n const { left, top } = rect\n const { width, height } = rect\n const xis = x >= left && x <= left + width\n const yis = y >= top && y <= top + height\n return xis && yis\n}\n\n/**\n * Before/after sibling region for a point over a leaf element, split on the\n * element's dominant axis: wide elements divide left/right, tall ones divide\n * top/bottom. Used when the target can't hold node children so its center\n * never reads as a nest.\n */\nexport function determineSiblingRegion(rect: DroppableClientRect, x: number, y: number) {\n const { width = 0, height = 0, top = 0, left = 0 } = rect || {}\n if (width >= height) {\n return x < left + width / 2 ? DropRegion.LEFT : DropRegion.RIGHT\n }\n return y < top + height / 2 ? DropRegion.TOP : DropRegion.BOTTOM\n}\n\n/**\n * The direction a target's siblings run in. It decides which two edges of the\n * target mean \"before\" and \"after\": in a column those are its top and bottom,\n * in a row its left and right. The other two edges mean nothing — dropping on\n * the left edge of a card in a column still lands above or below it.\n */\nexport type DropAxis = 'vertical' | 'horizontal'\n\n/** The widest an edge band of a container gets, in px. The rest is inside. */\nexport const DROP_EDGE_BAND_MAX = 12\n\n/**\n * How far past its boundary the pointer has to go before a before/after\n * region it was already in lets go, in px (a leaf's halves hold the same\n * way). Without it, a pointer resting on the line between two regions flips\n * between them on every pixel of hand tremor.\n */\nexport const DROP_REGION_HYSTERESIS = 4\n\nexport interface ResolveDropRegionOptions {\n rect: DroppableClientRect\n x: number\n y: number\n /** The way the target's siblings run. A column unless said otherwise. */\n axis?: DropAxis\n /**\n * False for a leaf (self-closing / text-editable): it has no inside, so it\n * splits into a before half and an after half (AGL-575 parallel).\n */\n acceptsChildren?: boolean\n /** False for the document root: it has no siblings, so all of it is inside. */\n acceptsSiblings?: boolean\n /**\n * False where the after edge would be drawn somewhere the drop does not\n * land. An expanded container in the hierarchy is the case: its bottom edge\n * is the top of its first child's row, while \"after it\" is past its whole\n * subtree. That space is inside instead.\n */\n allowAfter?: boolean\n /** Where the same target resolved last time, which it holds onto. */\n previous?: DropRegion | null\n}\n\n/**\n * The region a point over a drop target names, for a target whose siblings\n * run along `axis`.\n *\n * A container has a thin before band and a thin after band along that axis\n * (a quarter of its length, at most {@link DROP_EDGE_BAND_MAX}) and is inside\n * everywhere else. A leaf is all before and after, split at its middle.\n */\nexport function resolveDropRegion(options: ResolveDropRegionOptions): DropRegion {\n const {\n rect,\n x,\n y,\n axis = 'vertical',\n acceptsChildren = true,\n acceptsSiblings = true,\n allowAfter = true,\n previous = null,\n } = options\n if (!acceptsSiblings) return DropRegion.CHILDREN\n\n const horizontal = axis === 'horizontal'\n const before = horizontal ? DropRegion.LEFT : DropRegion.TOP\n const after = horizontal ? DropRegion.RIGHT : DropRegion.BOTTOM\n const start = (horizontal ? rect?.left : rect?.top) || 0\n const size = Math.max(0, (horizontal ? rect?.width : rect?.height) || 0)\n const at = (horizontal ? x : y) - start\n\n if (!acceptsChildren) {\n const stick = Math.min(DROP_REGION_HYSTERESIS, size / 4)\n let middle = size / 2\n if (previous === before) middle += stick\n if (previous === after) middle -= stick\n return at < middle ? before : after\n }\n\n const band = Math.min(size / 4, DROP_EDGE_BAND_MAX)\n // An edge band holds on once the pointer is in it, but never shrinks to\n // hold inside: in a 28px hierarchy row it is only 7px to begin with, and\n // halving it on the way in made \"above this row\" a target few could hit.\n const stick = Math.min(DROP_REGION_HYSTERESIS, band / 2)\n const held = (region: DropRegion) => (previous === region ? stick : 0)\n if (at < band + held(before)) return before\n if (allowAfter && at > size - band - held(after)) return after\n return DropRegion.CHILDREN\n}\n\nexport function determineDropRegion(\n clientRect: DroppableClientRect,\n x: number,\n y: number,\n acceptsChildren = true,\n regions?: ReturnType<typeof buildDroppableRects>,\n) {\n const _regions = regions || buildDroppableRects(clientRect)\n switch (true) {\n case withinRegion(_regions.top, x, y):\n return DropRegion.TOP\n case withinRegion(_regions.right, x, y):\n return DropRegion.RIGHT\n case withinRegion(_regions.bottom, x, y):\n return DropRegion.BOTTOM\n case withinRegion(_regions.left, x, y):\n return DropRegion.LEFT\n case !acceptsChildren:\n // Leaf targets (self-closing / text-editable) have no children slot, so\n // the center resolves to a sibling insert rather than a nest — keeping\n // the drop indicator and the committed placement in agreement\n // (AGL-575 parallel for drag-and-drop).\n return determineSiblingRegion(clientRect, x, y)\n case withinRegion(_regions.children, x, y):\n default:\n return DropRegion.CHILDREN\n }\n}\n"],"names":["DropRegion","buildDroppableRects","rect","width","height","top","right","bottom","left","x","y","isHorz","vertWRaw","vertWidth","vertHeight","horzHRaw","horzWidth","horzHeight","_top","_bottom","_left","_right","_children","_full","children","full","withinRegion","xis","yis","determineSiblingRegion","LEFT","RIGHT","TOP","BOTTOM","DROP_EDGE_BAND_MAX","DROP_REGION_HYSTERESIS","resolveDropRegion","options","axis","acceptsChildren","acceptsSiblings","allowAfter","previous","CHILDREN","horizontal","before","after","start","size","Math","max","at","stick","min","middle","band","held","region","determineDropRegion","clientRect","regions","_regions"],"mappings":"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"}