@grafloria/element 0.4.34 → 0.4.35
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
|
@@ -1100,6 +1100,7 @@ export function createDashboardHandle(ctx) {
|
|
|
1100
1100
|
},
|
|
1101
1101
|
joinTargets: [...ctx.layoutOf.keys()].filter((id) => { var _a, _b; return id !== containerId && id !== pageId && ((_a = ctx.layoutOf.get(id)) !== null && _a !== void 0 ? _a : (_b = specById.get(id)) === null || _b === void 0 ? void 0 : _b.layout) === 'tabs' && !!model.getGroup(id) && !insidePage(id); }),
|
|
1102
1102
|
stripHeight: (targetId) => tabStripReserve(ctx.tabsOf.get(targetId), Math.max(1, liveCount(targetId))),
|
|
1103
|
+
ownBoards: [pageId, ...[...ctx.boardGroups.keys()].filter((id) => insidePage(id))],
|
|
1103
1104
|
stripIndex: (targetId, cx, cy) => {
|
|
1104
1105
|
const strip = ctx.tabStrips.get(targetId);
|
|
1105
1106
|
if (!strip)
|
|
@@ -569,6 +569,8 @@ export interface TearOutPlan {
|
|
|
569
569
|
stripIndex(targetId: string, clientX: number, clientY: number): number | null;
|
|
570
570
|
/** The strip's height on `targetId`, px — the band above its body. */
|
|
571
571
|
stripHeight(targetId: string): number;
|
|
572
|
+
/** The page itself and every board inside it — never a board the page can land on. */
|
|
573
|
+
ownBoards: string[];
|
|
572
574
|
/** The commands that REORDER the page to `index` along its own strip. Empty when nothing changes. */
|
|
573
575
|
reorder(index: number): Command[];
|
|
574
576
|
/**
|
|
@@ -661,6 +663,10 @@ interface AdoptedLeg {
|
|
|
661
663
|
}): boolean;
|
|
662
664
|
/** Every other tile's cell before the ghost entered — the layout a row insert translates. */
|
|
663
665
|
baseline(): Map<string, CellRect>;
|
|
666
|
+
/** Where the tile sits right now, or null while it is off the board. */
|
|
667
|
+
cell(): CellRect | null;
|
|
668
|
+
/** That cell in world space, by the adopting board's own geometry. */
|
|
669
|
+
rect(): WorldRect | null;
|
|
664
670
|
/** Undo the adoption: target board back to its pre-entry layout. */
|
|
665
671
|
abort(): void;
|
|
666
672
|
/**
|
|
@@ -1348,6 +1348,13 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
1348
1348
|
},
|
|
1349
1349
|
move: false,
|
|
1350
1350
|
};
|
|
1351
|
+
// A TOP or LEFT edge moves the slab's origin, and the engine refuses to
|
|
1352
|
+
// move a locked tile: the move never landed, only the resize did, and a
|
|
1353
|
+
// section pulled up by its caption grew DOWNWARD a row per pointer step
|
|
1354
|
+
// — 18 rows for a 2-row pull (identification round, F16). Unlocked for
|
|
1355
|
+
// its own gesture, as a move is; relocked on release.
|
|
1356
|
+
if (edges.n || edges.w)
|
|
1357
|
+
it.locked = false;
|
|
1351
1358
|
capturePointer(slabGesture.pointerId);
|
|
1352
1359
|
api.container.style.cursor = cursorFor(edges);
|
|
1353
1360
|
};
|
|
@@ -1388,6 +1395,29 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
1388
1395
|
if (it)
|
|
1389
1396
|
it.locked = true;
|
|
1390
1397
|
};
|
|
1398
|
+
/** The cell a slab move asked for and could not have — painted so the refusal is visible; null clears it. */
|
|
1399
|
+
let refusal = null;
|
|
1400
|
+
const showRefusal = (cell, w, h) => {
|
|
1401
|
+
const layer = htmlLayer();
|
|
1402
|
+
if (!cell || !layer) {
|
|
1403
|
+
refusal === null || refusal === void 0 ? void 0 : refusal.remove();
|
|
1404
|
+
refusal = null;
|
|
1405
|
+
api.container.style.cursor = slabGesture ? 'grabbing' : '';
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
if (!refusal || refusal.parentElement !== layer) {
|
|
1409
|
+
refusal === null || refusal === void 0 ? void 0 : refusal.remove();
|
|
1410
|
+
refusal = document.createElement('div');
|
|
1411
|
+
refusal.className = 'axdb-ph axdb-ph--no';
|
|
1412
|
+
layer.prepend(refusal);
|
|
1413
|
+
}
|
|
1414
|
+
const r = cellToRect({ x: cell.x, y: cell.y, w, h }, frame(), geom(), rows());
|
|
1415
|
+
refusal.style.left = `${r.x}px`;
|
|
1416
|
+
refusal.style.top = `${r.y}px`;
|
|
1417
|
+
refusal.style.width = `${r.width}px`;
|
|
1418
|
+
refusal.style.height = `${r.height}px`;
|
|
1419
|
+
api.container.style.cursor = 'not-allowed';
|
|
1420
|
+
};
|
|
1391
1421
|
const slabMove = (ev) => {
|
|
1392
1422
|
const g = slabGesture;
|
|
1393
1423
|
if (!g)
|
|
@@ -1406,8 +1436,26 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
1406
1436
|
if (g.move) {
|
|
1407
1437
|
// The section's top-left follows the pointer by the offset it was grabbed at.
|
|
1408
1438
|
const cell = pointToCell(ev.world.x + g.grab.dx, ev.world.y + g.grab.dy, f, gg, rows(), it.w);
|
|
1409
|
-
if (
|
|
1410
|
-
|
|
1439
|
+
if (cell.x !== it.x || cell.y !== it.y) {
|
|
1440
|
+
// The cell under the pointer, else the nearest legal one — a widget
|
|
1441
|
+
// slides along its row past a locked tile; a section grabbed 60 px
|
|
1442
|
+
// from its left edge used to have its right edge refused by the
|
|
1443
|
+
// locked panel at every cell and simply not move, with nothing on
|
|
1444
|
+
// screen to say why (identification round, D6/D7). When even that
|
|
1445
|
+
// fails the wanted cell is painted as refused.
|
|
1446
|
+
// Along its ROW only: a section dragged LEFT that wandered DOWN its
|
|
1447
|
+
// column (the row search) read as the wrong tile moving.
|
|
1448
|
+
const was = { x: it.x, y: it.y };
|
|
1449
|
+
const moved = engine.moveCheck(g.id, cell.x, cell.y, { gate: false }).changed || placeOnRow(g.id, cell.x, cell.y, it.w);
|
|
1450
|
+
if (moved)
|
|
1451
|
+
project();
|
|
1452
|
+
// STUCK: the pointer asks for another cell and the slab did not budge
|
|
1453
|
+
// (placeOnRow counts "already on a legal cell" as placed) — paint what
|
|
1454
|
+
// was asked for as refused.
|
|
1455
|
+
const now = engine.getItem(g.id);
|
|
1456
|
+
const stuck = !!now && now.x === was.x && now.y === was.y && (cell.x !== was.x || cell.y !== was.y);
|
|
1457
|
+
showRefusal(stuck ? cell : null, it.w, it.h);
|
|
1458
|
+
}
|
|
1411
1459
|
syncPlaceholder();
|
|
1412
1460
|
return;
|
|
1413
1461
|
}
|
|
@@ -1455,10 +1503,10 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
1455
1503
|
if (!g)
|
|
1456
1504
|
return;
|
|
1457
1505
|
slabGesture = null;
|
|
1506
|
+
showRefusal(null, 0, 0);
|
|
1458
1507
|
releasePointer(g.pointerId);
|
|
1459
1508
|
api.container.style.cursor = '';
|
|
1460
|
-
|
|
1461
|
-
relockSlab(g.id);
|
|
1509
|
+
relockSlab(g.id);
|
|
1462
1510
|
if (!g.started) {
|
|
1463
1511
|
engine.endGesture();
|
|
1464
1512
|
return;
|
|
@@ -1486,8 +1534,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
1486
1534
|
slabGesture = null;
|
|
1487
1535
|
releasePointer(g.pointerId);
|
|
1488
1536
|
api.container.style.cursor = '';
|
|
1489
|
-
|
|
1490
|
-
relockSlab(g.id);
|
|
1537
|
+
relockSlab(g.id);
|
|
1491
1538
|
if (g.started)
|
|
1492
1539
|
engine.cancelGesture();
|
|
1493
1540
|
else
|
|
@@ -2507,6 +2554,14 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2507
2554
|
return {
|
|
2508
2555
|
groupId: group.id,
|
|
2509
2556
|
baseline: () => startCells,
|
|
2557
|
+
cell: () => {
|
|
2558
|
+
const it = engine.getItem(node.id);
|
|
2559
|
+
return it ? { x: it.x, y: it.y, w: it.w, h: it.h } : null;
|
|
2560
|
+
},
|
|
2561
|
+
rect: () => {
|
|
2562
|
+
const it = engine.getItem(node.id);
|
|
2563
|
+
return it ? cellToRect(it, frame(), geom(), rows()) : null;
|
|
2564
|
+
},
|
|
2510
2565
|
place: (cell) => {
|
|
2511
2566
|
if (!engine.getItem(node.id) && !engine.add({ id: node.id, x: 0, y: engine.rows(), w: cell.w, h: cell.h }))
|
|
2512
2567
|
return false;
|
|
@@ -2737,23 +2792,37 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2737
2792
|
selfPeerRef = selfPeer;
|
|
2738
2793
|
// The board's gap, for chrome that must fit BETWEEN tiles (the outside grip tab).
|
|
2739
2794
|
api.container.style.setProperty('--axdb-gap', `${gap}px`);
|
|
2795
|
+
/** A press on one of our containers' strips, claimed so the renderer stays out of it. */
|
|
2796
|
+
let stripPress = false;
|
|
2740
2797
|
const tool = {
|
|
2741
2798
|
id: `dashboard-grid:${group.id}:${++binderSeq}`,
|
|
2742
2799
|
priority: 2, // point-specific claim — outranks mode-style tools (see ext/tools.ts)
|
|
2743
2800
|
hitTest(ev, hit) {
|
|
2744
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
2801
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
2745
2802
|
if (disposed)
|
|
2746
2803
|
return false;
|
|
2747
|
-
if (gesture || slabGesture || forwardSlab)
|
|
2804
|
+
if (gesture || slabGesture || forwardSlab || stripPress)
|
|
2748
2805
|
return true; // own the rest of an in-flight gesture
|
|
2806
|
+
// A press on one of OUR containers' TAB STRIPS is ours to CLAIM and then
|
|
2807
|
+
// leave alone: the strip's own listeners run the click, the tab drag and
|
|
2808
|
+
// the container move. Left unclaimed (ownsPress calls a strip "content")
|
|
2809
|
+
// the renderer's ladder cleared the selection and armed its empty-canvas
|
|
2810
|
+
// PAN, and the camera slid 10–20 px under every tab drag — the reorder
|
|
2811
|
+
// mark lost after a detour, a release outside the canvas that committed,
|
|
2812
|
+
// the strip end reading as the right band (identification round, 2026-09-09).
|
|
2813
|
+
const stripEl = (_d = (_c = (_b = (_a = ev.source) === null || _a === void 0 ? void 0 : _a.target) === null || _b === void 0 ? void 0 : _b.closest) === null || _c === void 0 ? void 0 : _c.call(_b, '.axdb-tabs')) !== null && _d !== void 0 ? _d : null;
|
|
2814
|
+
if (stripEl) {
|
|
2815
|
+
const cid = stripEl.getAttribute('data-tabs-id');
|
|
2816
|
+
return !!cid && ((_e = group.members) !== null && _e !== void 0 ? _e : new Set()).has(cid) && api.container.contains(stripEl);
|
|
2817
|
+
}
|
|
2749
2818
|
if (!ownsPress(api.container, diagram, ev, hit))
|
|
2750
2819
|
return false;
|
|
2751
2820
|
// A press on one of OUR sections' caption bands is ours by the DOM: a
|
|
2752
2821
|
// 'tab' band sits above the frame, over the gap or the tile above,
|
|
2753
2822
|
// where the geometry says otherwise.
|
|
2754
|
-
const chrome = (
|
|
2755
|
-
const chromeId = (
|
|
2756
|
-
const mine = !!chromeId && ((
|
|
2823
|
+
const chrome = (_h = (_g = (_f = ev.source) === null || _f === void 0 ? void 0 : _f.target) === null || _g === void 0 ? void 0 : _g.closest) === null || _h === void 0 ? void 0 : _h.call(_g, '.axdb-slab > .axdb-slab-h, .axdb-slab > .axdb-rs');
|
|
2824
|
+
const chromeId = (_j = chrome === null || chrome === void 0 ? void 0 : chrome.parentElement) === null || _j === void 0 ? void 0 : _j.getAttribute('data-slab-id');
|
|
2825
|
+
const mine = !!chromeId && ((_k = group.members) !== null && _k !== void 0 ? _k : new Set()).has(chromeId);
|
|
2757
2826
|
if (mine)
|
|
2758
2827
|
return true;
|
|
2759
2828
|
// Someone else's SECTION HANDLE is never ours to claim. A tab
|
|
@@ -2766,7 +2835,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2766
2835
|
if (chromeId && (chrome === null || chrome === void 0 ? void 0 : chrome.classList.contains('axdb-rs')))
|
|
2767
2836
|
return false;
|
|
2768
2837
|
if (hit.node) {
|
|
2769
|
-
if (((
|
|
2838
|
+
if (((_l = group.members) !== null && _l !== void 0 ? _l : new Set()).has(hit.node.id))
|
|
2770
2839
|
return true;
|
|
2771
2840
|
// A press on a tile that belongs to a NESTED board must reach that
|
|
2772
2841
|
// board's tool. The dead-zone claim below deadens the slab's EMPTY
|
|
@@ -2775,7 +2844,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2775
2844
|
// parent's tool won the registration-order tie and the child's resize
|
|
2776
2845
|
// never armed; grid-options binds parent-first and worked by
|
|
2777
2846
|
// accident).
|
|
2778
|
-
for (const p of (
|
|
2847
|
+
for (const p of (_m = BOARD_REGISTRY.get(api.container)) !== null && _m !== void 0 ? _m : []) {
|
|
2779
2848
|
if (p !== selfPeer && p.hasItem(hit.node.id))
|
|
2780
2849
|
return false;
|
|
2781
2850
|
}
|
|
@@ -2788,8 +2857,8 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2788
2857
|
// divider press in a split section (dead dividers) and, near the
|
|
2789
2858
|
// section's edge, turned it into a section resize (the width changed
|
|
2790
2859
|
// while a control's height was being dragged — Quantia, Groups page).
|
|
2791
|
-
for (const p of (
|
|
2792
|
-
if (p !== selfPeer && ((
|
|
2860
|
+
for (const p of (_o = BOARD_REGISTRY.get(api.container)) !== null && _o !== void 0 ? _o : []) {
|
|
2861
|
+
if (p !== selfPeer && ((_p = group.members) !== null && _p !== void 0 ? _p : new Set()).has(p.group.id) && p.containsWorld(ev.world.x, ev.world.y))
|
|
2793
2862
|
return false;
|
|
2794
2863
|
}
|
|
2795
2864
|
// Claim (and deaden) empty presses inside a member group's frame so the
|
|
@@ -2801,34 +2870,38 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2801
2870
|
return insideMemberGroupFrame(ev.world.x, ev.world.y) || worldInsideBoard(ev.world.x, ev.world.y);
|
|
2802
2871
|
},
|
|
2803
2872
|
onPointerDown(ev, hit) {
|
|
2804
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
|
2873
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
2805
2874
|
if (gesture)
|
|
2806
2875
|
return; // mid-palette
|
|
2807
2876
|
const target = ((_b = (_a = ev.source) === null || _a === void 0 ? void 0 : _a.target) !== null && _b !== void 0 ? _b : null);
|
|
2877
|
+
if ((_c = target === null || target === void 0 ? void 0 : target.closest) === null || _c === void 0 ? void 0 : _c.call(target, '.axdb-tabs')) {
|
|
2878
|
+
stripPress = true; // claimed for the strip: nothing of ours starts
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2808
2881
|
// A press on a painted grip names its widget by the DOM: an OUTSIDE tab
|
|
2809
2882
|
// sits above the card's box, where the hit test sees the gap or the
|
|
2810
2883
|
// neighbour above.
|
|
2811
2884
|
const gripHost = gripHostOf(target);
|
|
2812
|
-
const gripId = (
|
|
2813
|
-
const onGrip = !!gripId && ((
|
|
2885
|
+
const gripId = (_d = gripHost === null || gripHost === void 0 ? void 0 : gripHost.getAttribute('data-node-id')) !== null && _d !== void 0 ? _d : null;
|
|
2886
|
+
const onGrip = !!gripId && ((_e = group.members) !== null && _e !== void 0 ? _e : new Set()).has(gripId);
|
|
2814
2887
|
// A SECTION's corner handle sits on top of whatever tile shares that
|
|
2815
2888
|
// corner; the DOM target names the section, the hit test the tile.
|
|
2816
|
-
const sectionHandle = (
|
|
2889
|
+
const sectionHandle = (_f = target === null || target === void 0 ? void 0 : target.closest) === null || _f === void 0 ? void 0 : _f.call(target, '.axdb-slab > .axdb-rs');
|
|
2817
2890
|
// A SECTION's CAPTION BAND names its section the same way — a 'tab'
|
|
2818
2891
|
// band sits above the frame, over the gap or the tile above. An action
|
|
2819
2892
|
// button in it fires and does nothing else.
|
|
2820
|
-
const captionBand = (
|
|
2821
|
-
const captionId = (
|
|
2822
|
-
const ownCaption = !!captionId && ((
|
|
2893
|
+
const captionBand = (_g = target === null || target === void 0 ? void 0 : target.closest) === null || _g === void 0 ? void 0 : _g.call(target, '.axdb-slab > .axdb-slab-h');
|
|
2894
|
+
const captionId = (_j = (_h = captionBand === null || captionBand === void 0 ? void 0 : captionBand.parentElement) === null || _h === void 0 ? void 0 : _h.getAttribute('data-slab-id')) !== null && _j !== void 0 ? _j : null;
|
|
2895
|
+
const ownCaption = !!captionId && ((_k = group.members) !== null && _k !== void 0 ? _k : new Set()).has(captionId);
|
|
2823
2896
|
// (An action button never reaches here: it is pass-through, and its own
|
|
2824
2897
|
// `click` fires onCaptionAction — see captionPassThrough.)
|
|
2825
2898
|
if ((!hit.node && !onGrip) || sectionHandle || ownCaption) {
|
|
2826
2899
|
// A press on a SECTION — its empty band, its caption, its corner
|
|
2827
2900
|
// handle or its frame edge — selects the section; the handle or an
|
|
2828
2901
|
// edge resizes it.
|
|
2829
|
-
const slabHandle = (
|
|
2830
|
-
const slabId = (
|
|
2831
|
-
const grp = slabId && ((
|
|
2902
|
+
const slabHandle = (_l = target === null || target === void 0 ? void 0 : target.closest) === null || _l === void 0 ? void 0 : _l.call(target, '.axdb-slab > .axdb-rs');
|
|
2903
|
+
const slabId = (_p = (_o = (_m = slabHandle === null || slabHandle === void 0 ? void 0 : slabHandle.parentElement) === null || _m === void 0 ? void 0 : _m.getAttribute('data-slab-id')) !== null && _o !== void 0 ? _o : (ownCaption ? captionId : null)) !== null && _p !== void 0 ? _p : memberGroupAt(ev.world.x, ev.world.y);
|
|
2904
|
+
const grp = slabId && ((_q = group.members) !== null && _q !== void 0 ? _q : new Set()).has(slabId) ? diagram.getGroup(slabId) : undefined;
|
|
2832
2905
|
if (slabId && grp) {
|
|
2833
2906
|
selectWidget(slabId);
|
|
2834
2907
|
api.render();
|
|
@@ -2851,7 +2924,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2851
2924
|
// forwards the pointer sequence.
|
|
2852
2925
|
const parent = parentPeer();
|
|
2853
2926
|
if ((parent === null || parent === void 0 ? void 0 : parent.selectMember) && worldInsideBoard(ev.world.x, ev.world.y)) {
|
|
2854
|
-
const ownHandle = ((
|
|
2927
|
+
const ownHandle = ((_r = slabHandle === null || slabHandle === void 0 ? void 0 : slabHandle.parentElement) === null || _r === void 0 ? void 0 : _r.getAttribute('data-slab-id')) === group.id;
|
|
2855
2928
|
parent.selectMember(group.id);
|
|
2856
2929
|
if (!isStatic && parent.beginSlabResize) {
|
|
2857
2930
|
const edges = ownHandle
|
|
@@ -2859,14 +2932,14 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2859
2932
|
: slabEdgesNear(group, ev.world.x, ev.world.y);
|
|
2860
2933
|
if (anyEdge(edges) && parent.beginSlabResize(group.id, edges, ev))
|
|
2861
2934
|
forwardSlab = parent;
|
|
2862
|
-
else if (!anyEdge(edges) && captionId === group.id && ((
|
|
2935
|
+
else if (!anyEdge(edges) && captionId === group.id && ((_s = parent.beginSlabMove) === null || _s === void 0 ? void 0 : _s.call(parent, group.id, ev)))
|
|
2863
2936
|
forwardSlab = parent;
|
|
2864
2937
|
}
|
|
2865
2938
|
return;
|
|
2866
2939
|
}
|
|
2867
2940
|
// The board's own empty area: a void click. Nothing to drag, and the
|
|
2868
2941
|
// selection clears exactly as a click outside any board would.
|
|
2869
|
-
(
|
|
2942
|
+
(_u = (_t = diagram).clearSelection) === null || _u === void 0 ? void 0 : _u.call(_t);
|
|
2870
2943
|
selectWidget(undefined);
|
|
2871
2944
|
api.render();
|
|
2872
2945
|
return;
|
|
@@ -2875,17 +2948,17 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2875
2948
|
if (!node)
|
|
2876
2949
|
return;
|
|
2877
2950
|
selectWidget(node.id); // a press selects, whether or not it starts a gesture
|
|
2878
|
-
if (((
|
|
2951
|
+
if (((_v = node.state) === null || _v === void 0 ? void 0 : _v.locked) === true)
|
|
2879
2952
|
return; // pinned: refuse; click still focuses
|
|
2880
2953
|
if (isStatic)
|
|
2881
2954
|
return; // a static board: claimed and deadened, click still focuses
|
|
2882
2955
|
// Which edges did the press take? The corner handle names its own (s+e,
|
|
2883
2956
|
// or s+w on RTL); a bare press within EDGE_GRIP of the tile's border
|
|
2884
2957
|
// takes that border; anywhere else is a move. A grip press is a move.
|
|
2885
|
-
const onHandle = !!((
|
|
2958
|
+
const onHandle = !!((_w = target === null || target === void 0 ? void 0 : target.closest) === null || _w === void 0 ? void 0 : _w.call(target, '.axdb-rs'));
|
|
2886
2959
|
const hostEl = hostOf(node.id);
|
|
2887
|
-
const resizable = ((
|
|
2888
|
-
const movable = ((
|
|
2960
|
+
const resizable = ((_x = node.getMetadata) === null || _x === void 0 ? void 0 : _x.call(node, 'widgetResizable')) !== false;
|
|
2961
|
+
const movable = ((_y = node.getMetadata) === null || _y === void 0 ? void 0 : _y.call(node, 'widgetMovable')) !== false;
|
|
2889
2962
|
// `ev.screen` is ELEMENT-LOCAL px; host rects are in client px. Compare
|
|
2890
2963
|
// like with like — the source event's clientX/Y when there is one, else
|
|
2891
2964
|
// the container's origin plus the local offset.
|
|
@@ -2933,7 +3006,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2933
3006
|
startSize: { width: node.size.width, height: node.size.height },
|
|
2934
3007
|
startPos: { x: node.position.x, y: node.position.y },
|
|
2935
3008
|
edges,
|
|
2936
|
-
spans: { w: (
|
|
3009
|
+
spans: { w: (_z = it === null || it === void 0 ? void 0 : it.w) !== null && _z !== void 0 ? _z : 1, h: (_0 = it === null || it === void 0 ? void 0 : it.h) !== null && _0 !== void 0 ? _0 : 1 },
|
|
2937
3010
|
removedFromBoard: false,
|
|
2938
3011
|
leg: null,
|
|
2939
3012
|
strip: null,
|
|
@@ -2946,6 +3019,8 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2946
3019
|
},
|
|
2947
3020
|
onPointerMove(ev) {
|
|
2948
3021
|
var _a;
|
|
3022
|
+
if (stripPress)
|
|
3023
|
+
return;
|
|
2949
3024
|
if (forwardSlab)
|
|
2950
3025
|
(_a = forwardSlab.slabMove) === null || _a === void 0 ? void 0 : _a.call(forwardSlab, ev);
|
|
2951
3026
|
else if (slabGesture)
|
|
@@ -2954,20 +3029,38 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2954
3029
|
onToolMove(ev);
|
|
2955
3030
|
},
|
|
2956
3031
|
onPointerUp() {
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
3032
|
+
if (stripPress) {
|
|
3033
|
+
stripPress = false;
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
try {
|
|
3037
|
+
onPointerUpInner();
|
|
3038
|
+
}
|
|
3039
|
+
finally {
|
|
3040
|
+
flushDeferredRebuild();
|
|
2961
3041
|
}
|
|
2962
|
-
else if (slabGesture)
|
|
2963
|
-
slabUp();
|
|
2964
|
-
else
|
|
2965
|
-
onToolUp();
|
|
2966
3042
|
},
|
|
2967
3043
|
onCancel() {
|
|
2968
|
-
|
|
3044
|
+
stripPress = false;
|
|
3045
|
+
try {
|
|
3046
|
+
cancelActiveGesture();
|
|
3047
|
+
}
|
|
3048
|
+
finally {
|
|
3049
|
+
flushDeferredRebuild();
|
|
3050
|
+
}
|
|
2969
3051
|
},
|
|
2970
3052
|
};
|
|
3053
|
+
const onPointerUpInner = () => {
|
|
3054
|
+
var _a;
|
|
3055
|
+
if (forwardSlab) {
|
|
3056
|
+
(_a = forwardSlab.slabUp) === null || _a === void 0 ? void 0 : _a.call(forwardSlab);
|
|
3057
|
+
forwardSlab = null;
|
|
3058
|
+
}
|
|
3059
|
+
else if (slabGesture)
|
|
3060
|
+
slabUp();
|
|
3061
|
+
else
|
|
3062
|
+
onToolUp();
|
|
3063
|
+
};
|
|
2971
3064
|
const unregisterTool = registerTool(tool);
|
|
2972
3065
|
/**
|
|
2973
3066
|
* Edge affordance: the cursor says which border a press would take, the
|
|
@@ -3250,11 +3343,42 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3250
3343
|
// leaves whenever it is over a strip, a group or an edge. A full board that
|
|
3251
3344
|
// refuses the ghost still lets the page join, reorder or split.
|
|
3252
3345
|
let leg = null;
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3346
|
+
/** The board holding the leg: null = this one, else the foreign peer under the pointer. */
|
|
3347
|
+
let legPeer = null;
|
|
3348
|
+
const ensureLeg = (world, peer = null) => {
|
|
3349
|
+
// The page TRAVELS at most half the board tall (the dock's measure): at
|
|
3350
|
+
// its natural height — a page fills its container, eight rows on the
|
|
3351
|
+
// demo — the ghost crossing the KPI row tore the whole dashboard apart
|
|
3352
|
+
// on its way to a cell (identification round, D1 03–08).
|
|
3353
|
+
const capPx = dockSpan.h * (rowHeightFor(geom(), rows()) + gap) - gap;
|
|
3354
|
+
const size = { width: plan.size.width, height: Math.min(plan.size.height, capPx) };
|
|
3355
|
+
// A different board under the pointer takes the leg over, the old one
|
|
3356
|
+
// back to its pre-entry layout first. An INNER tab used to know only
|
|
3357
|
+
// the board owning its container — over the main board the chip dimmed
|
|
3358
|
+
// and the release did nothing (identification round, L2).
|
|
3359
|
+
if (leg && legPeer !== peer) {
|
|
3360
|
+
leg.abort();
|
|
3361
|
+
leg = null;
|
|
3362
|
+
}
|
|
3363
|
+
if (!leg) {
|
|
3364
|
+
leg = peer ? peer.adopt({ id: plan.arrivingId }, world, size, { fit: 'shrink', anchor: 'top' }) : adopt({ id: plan.arrivingId }, world, size, { fit: 'shrink', anchor: 'top' });
|
|
3365
|
+
legPeer = leg ? peer : null;
|
|
3366
|
+
}
|
|
3256
3367
|
return leg;
|
|
3257
3368
|
};
|
|
3369
|
+
/** The deepest OTHER board under the point that may take the page — never one of the page's own boards. */
|
|
3370
|
+
const foreignAt = (wx, wy) => {
|
|
3371
|
+
let best = null;
|
|
3372
|
+
for (const p of peersOnCanvas()) {
|
|
3373
|
+
if (p === selfPeer || plan.ownBoards.includes(p.group.id))
|
|
3374
|
+
continue;
|
|
3375
|
+
if (!p.containsWorld(wx, wy))
|
|
3376
|
+
continue;
|
|
3377
|
+
if (!best || p.frameArea() < best.frameArea())
|
|
3378
|
+
best = p;
|
|
3379
|
+
}
|
|
3380
|
+
return best;
|
|
3381
|
+
};
|
|
3258
3382
|
const naturalSpan = (() => {
|
|
3259
3383
|
const sp = sizeToSpan(plan.size.width, plan.size.height, frame(), geom(), rows());
|
|
3260
3384
|
return { w: Math.max(1, Math.min(columns, sp.w)), h: Math.max(TEAR_OUT_MIN_ROWS, sp.h) };
|
|
@@ -3337,13 +3461,60 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3337
3461
|
return { left, top, right, bottom }; // unlaid-out: nothing to clip to
|
|
3338
3462
|
return { left: Math.max(left, rect.left), top: Math.max(top, rect.top), right: Math.min(right, rect.right), bottom: Math.min(bottom, rect.bottom) };
|
|
3339
3463
|
};
|
|
3464
|
+
/** Inside the VISIBLE canvas plus the grace band, on the screen — a camera that moved must not turn a pointer outside the canvas into a world point inside the board. */
|
|
3465
|
+
const clientInsideCanvasGrace = (cx, cy) => {
|
|
3466
|
+
// The CANVAS, not this board's frame: a nested page's binder runs the
|
|
3467
|
+
// tear-out of the tabs inside it, and its pages must still land on the
|
|
3468
|
+
// boards around it. An unmeasurable container (no layout) is never off.
|
|
3469
|
+
const rect = api.container.getBoundingClientRect();
|
|
3470
|
+
if (rect.width <= 0 || rect.height <= 0)
|
|
3471
|
+
return true;
|
|
3472
|
+
return cx >= rect.left - EDGE_GRACE && cx <= rect.right + EDGE_GRACE && cy >= rect.top - EDGE_GRACE && cy <= rect.bottom + EDGE_GRACE;
|
|
3473
|
+
};
|
|
3474
|
+
/**
|
|
3475
|
+
* The board's rows for a dock: as they stood BEFORE the ghost entered.
|
|
3476
|
+
* Read live, the ghost's own pushing inflated them on every re-entry —
|
|
3477
|
+
* side docks 14, 21, 104 rows tall, a bottom dock landing at row 29.
|
|
3478
|
+
*/
|
|
3479
|
+
const baseRows = () => {
|
|
3480
|
+
const b = leg === null || leg === void 0 ? void 0 : leg.baseline();
|
|
3481
|
+
if (!b)
|
|
3482
|
+
return rowsWithout(plan.arrivingId);
|
|
3483
|
+
let r = 0;
|
|
3484
|
+
for (const c of b.values())
|
|
3485
|
+
r = Math.max(r, c.y + c.h);
|
|
3486
|
+
return r;
|
|
3487
|
+
};
|
|
3488
|
+
const worldToClient = (wx, wy) => {
|
|
3489
|
+
const rect = api.container.getBoundingClientRect();
|
|
3490
|
+
const o = toWorld(rect.left, rect.top);
|
|
3491
|
+
const u = toWorld(rect.left + 100, rect.top + 100);
|
|
3492
|
+
return { x: rect.left + (wx - o.x) * (100 / (u.x - o.x || 100)), y: rect.top + (wy - o.y) * (100 / (u.y - o.y || 100)) };
|
|
3493
|
+
};
|
|
3494
|
+
/**
|
|
3495
|
+
* Would the page land where the user cannot see it? A cell whose room
|
|
3496
|
+
* lies below the fold (the only cell left under a locked section — D1
|
|
3497
|
+
* hold3) used to take the drop a screen away. Hidden = not one pixel of
|
|
3498
|
+
* the cell inside the visible canvas: a landing whose top edge shows,
|
|
3499
|
+
* the rest below the fold of a small canvas, is a landing the user can
|
|
3500
|
+
* see and a grow board scrolls to (lab L61 dropped at the canvas foot).
|
|
3501
|
+
*/
|
|
3502
|
+
const landingHidden = () => {
|
|
3503
|
+
const r = leg === null || leg === void 0 ? void 0 : leg.rect();
|
|
3504
|
+
const rect = api.container.getBoundingClientRect();
|
|
3505
|
+
if (!r || rect.width <= 0 || rect.height <= 0)
|
|
3506
|
+
return false;
|
|
3507
|
+
const tl = worldToClient(r.x, r.y);
|
|
3508
|
+
const br = worldToClient(r.x + r.width, r.y + r.height);
|
|
3509
|
+
return tl.y >= rect.bottom || br.y <= rect.top || tl.x >= rect.right || br.x <= rect.left;
|
|
3510
|
+
};
|
|
3340
3511
|
const rootAt = (cx, cy) => {
|
|
3341
3512
|
// The bands reach a little OUTSIDE the frame too: a pointer that
|
|
3342
3513
|
// overshoots the board's top edge by a few pixels means "the top".
|
|
3343
3514
|
const v = visibleFrame();
|
|
3344
3515
|
if (cx < v.left - ROOT_SIDE || cx > v.right + ROOT_SIDE || cy < v.top - ROOT_TOP || cy > v.bottom + ROOT_BOTTOM)
|
|
3345
3516
|
return null;
|
|
3346
|
-
const rows = Math.max(TEAR_OUT_MIN_ROWS,
|
|
3517
|
+
const rows = Math.max(TEAR_OUT_MIN_ROWS, baseRows());
|
|
3347
3518
|
const w = dockSpan.w;
|
|
3348
3519
|
const h = dockSpan.h;
|
|
3349
3520
|
if (cy - v.top <= ROOT_TOP)
|
|
@@ -3390,6 +3561,11 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3390
3561
|
: { keep: { x: it.x, y: it.y + b, w: it.w, h: a }, born: { x: it.x, y: it.y, w: it.w, h: b } };
|
|
3391
3562
|
};
|
|
3392
3563
|
const zoneAt = (cx, cy, world) => {
|
|
3564
|
+
// A pointer OUTSIDE the visible canvas is off, full stop: a camera that
|
|
3565
|
+
// moved can map it to a world point inside a group, and that group
|
|
3566
|
+
// took a join or a split from a release in the page header.
|
|
3567
|
+
if (!clientInsideCanvasGrace(cx, cy))
|
|
3568
|
+
return { kind: 'off' };
|
|
3393
3569
|
const target = targetAt(world.x, world.y);
|
|
3394
3570
|
const home = !target && worldInsideGroup(from, world.x, world.y);
|
|
3395
3571
|
// A strip is the most precise target there is: anyone's wins outright.
|
|
@@ -3424,9 +3600,12 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3424
3600
|
}
|
|
3425
3601
|
if (home)
|
|
3426
3602
|
return { kind: 'home' };
|
|
3603
|
+
const foreign = foreignAt(world.x, world.y);
|
|
3604
|
+
if (foreign && (!worldInsideBoard(world.x, world.y) || foreign.frameArea() < boardArea()))
|
|
3605
|
+
return { kind: 'board', peer: foreign };
|
|
3427
3606
|
return { kind: 'board' };
|
|
3428
3607
|
};
|
|
3429
|
-
const zoneKey = (z) => JSON.stringify(z, (k, v) => (k === 'target' ? v.id : v));
|
|
3608
|
+
const zoneKey = (z) => JSON.stringify(z, (k, v) => (k === 'target' ? v.id : k === 'peer' ? v.group.id : v));
|
|
3430
3609
|
// DOCKING PUSHES SECTIONS. A section is a locked tile so that a widget
|
|
3431
3610
|
// never pushes it; a group docked against the board's edge is the one
|
|
3432
3611
|
// gesture that must — everything below the top band moves down. For the
|
|
@@ -3526,7 +3705,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3526
3705
|
};
|
|
3527
3706
|
const previewSplit = (z, world) => {
|
|
3528
3707
|
const it = engine.getItem(z.target.id);
|
|
3529
|
-
const l = ensureLeg(world);
|
|
3708
|
+
const l = ensureLeg(world, null);
|
|
3530
3709
|
if (!it || !l)
|
|
3531
3710
|
return false;
|
|
3532
3711
|
split = { id: z.target.id, before: { x: it.x, y: it.y, w: it.w, h: it.h }, frameBefore: frameOfGroup(z.target), keep: z.keep };
|
|
@@ -3545,14 +3724,14 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3545
3724
|
let zone = { kind: 'board' };
|
|
3546
3725
|
let key = zoneKey(zone);
|
|
3547
3726
|
const applyZone = (z, world) => {
|
|
3548
|
-
var _a;
|
|
3727
|
+
var _a, _b, _c;
|
|
3549
3728
|
const k = zoneKey(z);
|
|
3550
3729
|
const same = k === key;
|
|
3551
3730
|
key = k;
|
|
3552
3731
|
zone = z;
|
|
3553
3732
|
if (same) {
|
|
3554
3733
|
if (z.kind === 'board')
|
|
3555
|
-
(
|
|
3734
|
+
(_b = ensureLeg(world, (_a = z.peer) !== null && _a !== void 0 ? _a : null)) === null || _b === void 0 ? void 0 : _b.move(world);
|
|
3556
3735
|
return;
|
|
3557
3736
|
}
|
|
3558
3737
|
undoSplitPreview();
|
|
@@ -3583,7 +3762,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3583
3762
|
break;
|
|
3584
3763
|
}
|
|
3585
3764
|
case 'root': {
|
|
3586
|
-
const l = ensureLeg(world);
|
|
3765
|
+
const l = ensureLeg(world, null);
|
|
3587
3766
|
if (l) {
|
|
3588
3767
|
unlockGroups();
|
|
3589
3768
|
l.place(z.cell);
|
|
@@ -3600,10 +3779,11 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3600
3779
|
plan.markDrop(fromGroupId, z.index);
|
|
3601
3780
|
break;
|
|
3602
3781
|
case 'home':
|
|
3782
|
+
case 'off':
|
|
3603
3783
|
leg === null || leg === void 0 ? void 0 : leg.leave();
|
|
3604
3784
|
break;
|
|
3605
3785
|
case 'board': {
|
|
3606
|
-
const l = ensureLeg(world);
|
|
3786
|
+
const l = ensureLeg(world, (_c = z.peer) !== null && _c !== void 0 ? _c : null);
|
|
3607
3787
|
l === null || l === void 0 ? void 0 : l.enter(world);
|
|
3608
3788
|
break;
|
|
3609
3789
|
}
|
|
@@ -3626,7 +3806,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3626
3806
|
applyZone(z, world);
|
|
3627
3807
|
// Dimmed = a release here does nothing: home, off the board, or a board
|
|
3628
3808
|
// that refused the ghost (bounded and full).
|
|
3629
|
-
chip.classList.toggle('axdb-out', zone.kind === 'home' || (zone.kind === 'root' && !leg) || (zone.kind === 'board' && (!leg ||
|
|
3809
|
+
chip.classList.toggle('axdb-out', zone.kind === 'home' || zone.kind === 'off' || (zone.kind === 'root' && !leg) || (zone.kind === 'board' && (!leg || landingHidden())));
|
|
3630
3810
|
api.render();
|
|
3631
3811
|
};
|
|
3632
3812
|
const done = (changed, kind) => {
|
|
@@ -3638,7 +3818,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3638
3818
|
(_a = options.onGesture) === null || _a === void 0 ? void 0 : _a.call(options, { type: kind, kind: 'move', nodeId: pageId, changed });
|
|
3639
3819
|
};
|
|
3640
3820
|
const finish = (commit) => {
|
|
3641
|
-
var _a, _b;
|
|
3821
|
+
var _a, _b, _c, _d;
|
|
3642
3822
|
detach();
|
|
3643
3823
|
chip.remove();
|
|
3644
3824
|
hideOverlay();
|
|
@@ -3650,7 +3830,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3650
3830
|
const z = commit ? zoneAt(last.x, last.y, world) : { kind: 'home' };
|
|
3651
3831
|
if (z.kind !== 'root')
|
|
3652
3832
|
undoInsertRows();
|
|
3653
|
-
if (!commit || z.kind === 'home' || (z.kind === 'root' && !ensureLeg(world)) || (z.kind === 'board' && (!ensureLeg(world) ||
|
|
3833
|
+
if (!commit || z.kind === 'home' || z.kind === 'off' || (z.kind === 'root' && !ensureLeg(world, null)) || (z.kind === 'board' && (!ensureLeg(world, (_a = z.peer) !== null && _a !== void 0 ? _a : null) || landingHidden()))) {
|
|
3654
3834
|
undoSplitPreview();
|
|
3655
3835
|
leg === null || leg === void 0 ? void 0 : leg.abort();
|
|
3656
3836
|
relockGroups();
|
|
@@ -3680,7 +3860,9 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3680
3860
|
// other. The preview already holds both in the engine; commit them.
|
|
3681
3861
|
if (!split || split.id !== z.target.id || zoneKey(zone) !== zoneKey(z))
|
|
3682
3862
|
applyZone(z, world);
|
|
3683
|
-
|
|
3863
|
+
hideOverlay(); // a re-applied zone repaints its preview; the release is not a preview
|
|
3864
|
+
plan.markDrop(null, null);
|
|
3865
|
+
const fin = (_b = leg === null || leg === void 0 ? void 0 : leg.finalize()) !== null && _b !== void 0 ? _b : null;
|
|
3684
3866
|
const it = engine.getItem(z.target.id);
|
|
3685
3867
|
const before = split;
|
|
3686
3868
|
if (it)
|
|
@@ -3706,13 +3888,15 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3706
3888
|
// ROOT DOCK or a free cell on the board: the leg sits where it will land.
|
|
3707
3889
|
if (zoneKey(zone) !== zoneKey(z))
|
|
3708
3890
|
applyZone(z, world);
|
|
3709
|
-
|
|
3891
|
+
hideOverlay(); // a re-applied zone repaints its preview; the release is not a preview
|
|
3892
|
+
plan.markDrop(null, null);
|
|
3893
|
+
const fin = (_c = leg === null || leg === void 0 ? void 0 : leg.finalize()) !== null && _c !== void 0 ? _c : null;
|
|
3710
3894
|
relockGroups();
|
|
3711
3895
|
if (!fin) {
|
|
3712
3896
|
done(false, 'cancel');
|
|
3713
3897
|
return;
|
|
3714
3898
|
}
|
|
3715
|
-
const planned = plan.commands(fin.cell, fin.rect, group.id);
|
|
3899
|
+
const planned = plan.commands(fin.cell, fin.rect, (_d = leg === null || leg === void 0 ? void 0 : leg.groupId) !== null && _d !== void 0 ? _d : group.id);
|
|
3716
3900
|
done(execute(z.kind === 'root' ? 'Dock tab' : 'Move tab out', [...fin.commands, ...groupCommands(fin), ...planned.move, ...planned.collapse]), 'commit');
|
|
3717
3901
|
};
|
|
3718
3902
|
const onUp = () => finish(true);
|
|
@@ -3917,12 +4101,33 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3917
4101
|
});
|
|
3918
4102
|
/** Rebuild the engine from the members' persisted cells. `pack` runs gravity
|
|
3919
4103
|
* over the result (boot, float→off); a plain sync keeps the cells verbatim. */
|
|
4104
|
+
/**
|
|
4105
|
+
* A rebuild asked for while a gesture is live waits for the gesture. The
|
|
4106
|
+
* pointer's own crossing re-lays boards — adopting a widget into the Nested
|
|
4107
|
+
* page moved the inner tabs container, the tabs runtime re-placed its
|
|
4108
|
+
* pages, and the inner page's binder rebuilt from the model: its gesture
|
|
4109
|
+
* cancelled mid-drag, the dragged widget re-added, the ghost class gone
|
|
4110
|
+
* and the target's placeholder leaked through release and undo
|
|
4111
|
+
* (identification round, L5). The frame change itself is answered by
|
|
4112
|
+
* `onBoundsChanged` (a re-projection); the model is rebuilt afterwards.
|
|
4113
|
+
*/
|
|
4114
|
+
let rebuildDeferred = null;
|
|
4115
|
+
const flushDeferredRebuild = () => {
|
|
4116
|
+
if (!rebuildDeferred || gesture || slabGesture)
|
|
4117
|
+
return;
|
|
4118
|
+
const { pack } = rebuildDeferred;
|
|
4119
|
+
rebuildDeferred = null;
|
|
4120
|
+
rebuild(pack);
|
|
4121
|
+
};
|
|
3920
4122
|
const rebuild = (pack) => {
|
|
3921
4123
|
var _a, _b, _c, _d;
|
|
3922
4124
|
if (disposed)
|
|
3923
4125
|
return;
|
|
3924
|
-
if (gesture)
|
|
3925
|
-
|
|
4126
|
+
if (gesture || slabGesture) {
|
|
4127
|
+
rebuildDeferred = { pack: pack || (rebuildDeferred === null || rebuildDeferred === void 0 ? void 0 : rebuildDeferred.pack) === true };
|
|
4128
|
+
project();
|
|
4129
|
+
return;
|
|
4130
|
+
}
|
|
3926
4131
|
applyFluidFrame();
|
|
3927
4132
|
const items = [];
|
|
3928
4133
|
for (const id of (_a = group.members) !== null && _a !== void 0 ? _a : []) {
|
|
@@ -63,6 +63,9 @@ const CSS = `
|
|
|
63
63
|
z-index: 0;
|
|
64
64
|
transition: none;
|
|
65
65
|
}
|
|
66
|
+
/* A slab move asked for a cell it cannot have (a locked section in the way): the wanted cell in the danger tone. */
|
|
67
|
+
.grafloria-html-layer > .axdb-ph.axdb-ph--no { border-color: var(--axdb-danger, #b3123c); background: var(--axdb-danger-soft, rgba(179, 18, 60, .07)); }
|
|
68
|
+
|
|
66
69
|
@media (prefers-color-scheme: dark) {
|
|
67
70
|
.grafloria-html-layer > .axdb-ph { background: rgba(220, 225, 240, .12); border-color: rgba(220, 225, 240, .3); }
|
|
68
71
|
}
|