@grafloria/element 0.4.20 → 0.4.21

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": "@grafloria/element",
3
- "version": "0.4.20",
3
+ "version": "0.4.21",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
@@ -513,14 +513,19 @@ interface AdoptedLeg {
513
513
  * unregister. A split board adopts nothing and grows no slab: its `adopt`
514
514
  * answers null and `resizeMemberBy` answers unchanged.
515
515
  */
516
+ /** The board on the canvas that holds `groupId` as a member — a nested board's parent. */
517
+ export declare function parentPeerOf(container: HTMLElement, groupId: string): BinderPeer | null;
516
518
  /** Clear the selection on every OTHER board of the canvas — one selection per canvas. */
517
519
  export declare function clearOtherSelections(container: HTMLElement, self: BinderPeer | null): void;
518
520
  export declare function registerBoardPeer(container: HTMLElement, peer: BinderPeer): () => void;
519
521
  export type { BinderPeer };
520
- interface ResizeEdges {
522
+ /** A press this close (CSS px) to a tile's border takes that edge for a resize. */
523
+ export declare const EDGE_GRIP = 7;
524
+ export interface ResizeEdges {
521
525
  n: boolean;
522
526
  e: boolean;
523
527
  s: boolean;
524
528
  w: boolean;
525
529
  }
530
+ export declare const anyEdge: (E: ResizeEdges) => boolean;
526
531
  export declare function bindDashboardGrid(api: DashboardGridApi, group: GroupModel, options?: DashboardGridOptions): DashboardGridHandle;
@@ -153,6 +153,14 @@ const BOARD_REGISTRY = new WeakMap();
153
153
  * unregister. A split board adopts nothing and grows no slab: its `adopt`
154
154
  * answers null and `resizeMemberBy` answers unchanged.
155
155
  */
156
+ /** The board on the canvas that holds `groupId` as a member — a nested board's parent. */
157
+ export function parentPeerOf(container, groupId) {
158
+ var _a;
159
+ for (const p of (_a = BOARD_REGISTRY.get(container)) !== null && _a !== void 0 ? _a : [])
160
+ if (p.group.id !== groupId && p.hasItem(groupId))
161
+ return p;
162
+ return null;
163
+ }
156
164
  /** Clear the selection on every OTHER board of the canvas — one selection per canvas. */
157
165
  export function clearOtherSelections(container, self) {
158
166
  var _a, _b;
@@ -241,7 +249,7 @@ class SetGroupCellCommand extends Command {
241
249
  const DRAG_THRESHOLD = 4;
242
250
  const GLIDE_OFF_DELAY = 400;
243
251
  /** A press this close (CSS px) to a tile's border takes that edge for a resize. */
244
- const EDGE_GRIP = 7;
252
+ export const EDGE_GRIP = 7;
245
253
  const NO_EDGES = { n: false, e: false, s: false, w: false };
246
254
  /** Which of a host's edges a client point is within EDGE_GRIP of (none when outside). */
247
255
  function edgesNear(host, cx, cy) {
@@ -255,7 +263,7 @@ function edgesNear(host, cx, cy) {
255
263
  e: r.right - cx <= EDGE_GRIP,
256
264
  };
257
265
  }
258
- const anyEdge = (E) => E.n || E.e || E.s || E.w;
266
+ export const anyEdge = (E) => E.n || E.e || E.s || E.w;
259
267
  /** The resize cursor for a set of edges ('' when none). */
260
268
  function cursorFor(E) {
261
269
  const v = E.n || E.s;
@@ -2127,7 +2135,7 @@ export function bindDashboardGrid(api, group, options = {}) {
2127
2135
  id: `dashboard-grid:${group.id}:${++binderSeq}`,
2128
2136
  priority: 2, // point-specific claim — outranks mode-style tools (see ext/tools.ts)
2129
2137
  hitTest(ev, hit) {
2130
- var _a, _b;
2138
+ var _a, _b, _c, _d;
2131
2139
  if (disposed)
2132
2140
  return false;
2133
2141
  if (gesture || slabGesture || forwardSlab)
@@ -2150,6 +2158,17 @@ export function bindDashboardGrid(api, group, options = {}) {
2150
2158
  }
2151
2159
  return insideMemberGroupFrame(ev.world.x, ev.world.y);
2152
2160
  }
2161
+ // An EMPTY press inside a NESTED board's frame is that board's: its
2162
+ // dividers, its band, its own section press (which it hands back up).
2163
+ // Ties went to the first registered tool, and a section re-bound by a
2164
+ // layout switch registers AFTER its parent — so the parent took every
2165
+ // divider press in a split section (dead dividers) and, near the
2166
+ // section's edge, turned it into a section resize (the width changed
2167
+ // while a control's height was being dragged — Quantia, Groups page).
2168
+ for (const p of (_c = BOARD_REGISTRY.get(api.container)) !== null && _c !== void 0 ? _c : []) {
2169
+ if (p !== selfPeer && ((_d = group.members) !== null && _d !== void 0 ? _d : new Set()).has(p.group.id) && p.containsWorld(ev.world.x, ev.world.y))
2170
+ return false;
2171
+ }
2153
2172
  // Claim (and deaden) empty presses inside a member group's frame so the
2154
2173
  // built-in group-drag cannot fight the pack layout for the KPI slab —
2155
2174
  // and empty presses on the BOARD itself: its group is a layout
@@ -25,7 +25,7 @@
25
25
  import { __awaiter } from "tslib";
26
26
  import { Command } from '@grafloria/engine';
27
27
  import { LiveRegionController, registerTool } from '@grafloria/renderer';
28
- import { clearOtherSelections, dragHandleSelector, gripHostOf, gripOf, normalizeDragHandle, ownsPress, pressOnDragHandle, registerBoardPeer, syncGrip, DRAG_HANDLE_CLASS } from './grid-binder.js';
28
+ import { anyEdge, clearOtherSelections, dragHandleSelector, gripHostOf, gripOf, normalizeDragHandle, ownsPress, parentPeerOf, pressOnDragHandle, registerBoardPeer, syncGrip, DRAG_HANDLE_CLASS, EDGE_GRIP } from './grid-binder.js';
29
29
  import { cellFromGridItem } from './grid-mapping.js';
30
30
  import { addSplitLeaf, cellsFromSplit, cloneSplit, dividersOf, groupRectsOf, insertSplitLeaf, moveSplitDivider, normalizeSplit, pathToLeaf, projectSplit, removeSplitLeaf, splitFromCells, splitLeaves, } from './split-layout.js';
31
31
  import { ensureDashboardKitStyles } from './styles.js';
@@ -99,6 +99,8 @@ export function bindDashboardSplit(api, group, options = {}) {
99
99
  let designW = (_k = (_j = group.size) === null || _j === void 0 ? void 0 : _j.width) !== null && _k !== void 0 ? _k : 0;
100
100
  let disposed = false;
101
101
  let gesture = null;
102
+ /** The PARENT running a resize of OUR section from a press this tool claimed. */
103
+ let forwardSlab = null;
102
104
  let focusedId;
103
105
  const live = liveRegionFor(api.container);
104
106
  // -- geometry ---------------------------------------------------------------
@@ -634,7 +636,7 @@ export function bindDashboardSplit(api, group, options = {}) {
634
636
  var _a;
635
637
  if (disposed)
636
638
  return false;
637
- if (gesture)
639
+ if (gesture || forwardSlab)
638
640
  return true;
639
641
  if (!ownsPress(api.container, diagram, ev, hit))
640
642
  return false;
@@ -643,7 +645,7 @@ export function bindDashboardSplit(api, group, options = {}) {
643
645
  return worldInsideBoard(ev.world.x, ev.world.y);
644
646
  },
645
647
  onPointerDown(ev, hit) {
646
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
648
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
647
649
  if (gesture)
648
650
  return;
649
651
  const target = ((_b = (_a = ev.source) === null || _a === void 0 ? void 0 : _a.target) !== null && _b !== void 0 ? _b : null);
@@ -678,8 +680,27 @@ export function bindDashboardSplit(api, group, options = {}) {
678
680
  // sits above the card's box) — see grid-binder.
679
681
  const gripId = (_e = (_d = gripHostOf(target)) === null || _d === void 0 ? void 0 : _d.getAttribute('data-node-id')) !== null && _e !== void 0 ? _e : null;
680
682
  const onGrip = !!gripId && ((_f = group.members) !== null && _f !== void 0 ? _f : new Set()).has(gripId);
681
- if (!hit.node && !onGrip) {
682
- (_h = (_g = diagram).clearSelection) === null || _h === void 0 ? void 0 : _h.call(_g);
683
+ const sectionHandle = (_g = target === null || target === void 0 ? void 0 : target.closest) === null || _g === void 0 ? void 0 : _g.call(target, '.axdb-slab > .axdb-rs');
684
+ if ((!hit.node && !onGrip) || sectionHandle) {
685
+ // OUR OWN empty band or corner handle, and we are a section of a
686
+ // parent board: select the section there; an edge or the handle
687
+ // starts the section resize, which the parent runs while this tool
688
+ // forwards the pointer sequence (the grid binder does the same).
689
+ const parent = parentPeerOf(api.container, group.id);
690
+ if ((parent === null || parent === void 0 ? void 0 : parent.selectMember) && (sectionHandle || worldInsideBoard(ev.world.x, ev.world.y))) {
691
+ const own = ((_h = sectionHandle === null || sectionHandle === void 0 ? void 0 : sectionHandle.parentElement) === null || _h === void 0 ? void 0 : _h.getAttribute('data-slab-id')) === group.id;
692
+ parent.selectMember(group.id);
693
+ if (!isStatic && parent.beginSlabResize) {
694
+ const f = frame();
695
+ const edges = own
696
+ ? rtl ? { n: false, e: false, s: true, w: true } : { n: false, e: true, s: true, w: false }
697
+ : { n: ev.world.y - f.y <= EDGE_GRIP, s: f.y + f.height - ev.world.y <= EDGE_GRIP, w: ev.world.x - f.x <= EDGE_GRIP, e: f.x + f.width - ev.world.x <= EDGE_GRIP };
698
+ if (anyEdge(edges) && parent.beginSlabResize(group.id, edges, ev))
699
+ forwardSlab = parent;
700
+ }
701
+ return;
702
+ }
703
+ (_k = (_j = diagram).clearSelection) === null || _k === void 0 ? void 0 : _k.call(_j);
683
704
  selectWidget(undefined);
684
705
  api.render();
685
706
  return;
@@ -688,9 +709,9 @@ export function bindDashboardSplit(api, group, options = {}) {
688
709
  if (!node)
689
710
  return;
690
711
  selectWidget(node.id); // a press selects, whether or not it starts a gesture
691
- if (((_j = node.state) === null || _j === void 0 ? void 0 : _j.locked) === true || isStatic)
712
+ if (((_l = node.state) === null || _l === void 0 ? void 0 : _l.locked) === true || isStatic)
692
713
  return;
693
- if (((_k = node.getMetadata) === null || _k === void 0 ? void 0 : _k.call(node, 'widgetMovable')) === false)
714
+ if (((_m = node.getMetadata) === null || _m === void 0 ? void 0 : _m.call(node, 'widgetMovable')) === false)
694
715
  return;
695
716
  // Drag-handle mode: only the handle (the caption strip, a custom element
696
717
  // or the painted grip) lifts a widget out — see pressOnDragHandle.
@@ -723,12 +744,27 @@ export function bindDashboardSplit(api, group, options = {}) {
723
744
  };
724
745
  },
725
746
  onPointerMove(ev) {
726
- onToolMove(ev);
747
+ var _a;
748
+ if (forwardSlab)
749
+ (_a = forwardSlab.slabMove) === null || _a === void 0 ? void 0 : _a.call(forwardSlab, ev);
750
+ else
751
+ onToolMove(ev);
727
752
  },
728
753
  onPointerUp() {
729
- onToolUp();
754
+ var _a;
755
+ if (forwardSlab) {
756
+ (_a = forwardSlab.slabUp) === null || _a === void 0 ? void 0 : _a.call(forwardSlab);
757
+ forwardSlab = null;
758
+ }
759
+ else
760
+ onToolUp();
730
761
  },
731
762
  onCancel() {
763
+ var _a;
764
+ if (forwardSlab) {
765
+ (_a = forwardSlab.slabCancel) === null || _a === void 0 ? void 0 : _a.call(forwardSlab);
766
+ forwardSlab = null;
767
+ }
732
768
  cancelActiveGesture();
733
769
  },
734
770
  };