@edv4h/usketch-plugin-dashboard 0.2.0
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/LICENSE +21 -0
- package/README.md +52 -0
- package/dist/config-ops.d.ts +48 -0
- package/dist/config-ops.d.ts.map +1 -0
- package/dist/config-ops.js +101 -0
- package/dist/config-ops.js.map +1 -0
- package/dist/dashboard-config-shape-def.d.ts +4 -0
- package/dist/dashboard-config-shape-def.d.ts.map +1 -0
- package/dist/dashboard-config-shape-def.js +33 -0
- package/dist/dashboard-config-shape-def.js.map +1 -0
- package/dist/dashboard-config-shape.d.ts +71 -0
- package/dist/dashboard-config-shape.d.ts.map +1 -0
- package/dist/dashboard-config-shape.js +51 -0
- package/dist/dashboard-config-shape.js.map +1 -0
- package/dist/dashboard-runtime.d.ts +23 -0
- package/dist/dashboard-runtime.d.ts.map +1 -0
- package/dist/dashboard-runtime.js +726 -0
- package/dist/dashboard-runtime.js.map +1 -0
- package/dist/dashboard-service.d.ts +76 -0
- package/dist/dashboard-service.d.ts.map +1 -0
- package/dist/dashboard-service.js +287 -0
- package/dist/dashboard-service.js.map +1 -0
- package/dist/drag-target-store.d.ts +11 -0
- package/dist/drag-target-store.d.ts.map +1 -0
- package/dist/drag-target-store.js +33 -0
- package/dist/drag-target-store.js.map +1 -0
- package/dist/grid-overlay.d.ts +16 -0
- package/dist/grid-overlay.d.ts.map +1 -0
- package/dist/grid-overlay.js +111 -0
- package/dist/grid-overlay.js.map +1 -0
- package/dist/grid.d.ts +110 -0
- package/dist/grid.d.ts.map +1 -0
- package/dist/grid.js +214 -0
- package/dist/grid.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/items.d.ts +25 -0
- package/dist/items.d.ts.map +1 -0
- package/dist/items.js +59 -0
- package/dist/items.js.map +1 -0
- package/dist/order.d.ts +10 -0
- package/dist/order.d.ts.map +1 -0
- package/dist/order.js +15 -0
- package/dist/order.js.map +1 -0
- package/dist/plugin.d.ts +12 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +59 -0
- package/dist/plugin.js.map +1 -0
- package/dist/register-dashboard-hud.d.ts +5 -0
- package/dist/register-dashboard-hud.d.ts.map +1 -0
- package/dist/register-dashboard-hud.js +173 -0
- package/dist/register-dashboard-hud.js.map +1 -0
- package/dist/slide-animation.d.ts +10 -0
- package/dist/slide-animation.d.ts.map +1 -0
- package/dist/slide-animation.js +67 -0
- package/dist/slide-animation.js.map +1 -0
- package/dist/viewport-lock.d.ts +4 -0
- package/dist/viewport-lock.d.ts.map +1 -0
- package/dist/viewport-lock.js +172 -0
- package/dist/viewport-lock.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useSyncExternalStore } from "react";
|
|
3
|
+
import { isDashboardConfig } from "./dashboard-config-shape.js";
|
|
4
|
+
import { getDragTarget, subscribeDragTarget } from "./drag-target-store.js";
|
|
5
|
+
import { cellTopLeft } from "./grid.js";
|
|
6
|
+
export const GRID_OVERLAY_LAYER_ID = "usketch-plugin-dashboard:grid-overlay";
|
|
7
|
+
// ── Shared visibility state (module-scoped, app-local; toggled from the HUD) ──
|
|
8
|
+
let visible = true;
|
|
9
|
+
const listeners = new Set();
|
|
10
|
+
/** Show/hide the grid overlay. */
|
|
11
|
+
export function setGridOverlayVisible(next) {
|
|
12
|
+
if (next === visible)
|
|
13
|
+
return;
|
|
14
|
+
visible = next;
|
|
15
|
+
for (const fn of listeners)
|
|
16
|
+
fn();
|
|
17
|
+
}
|
|
18
|
+
export function isGridOverlayVisible() {
|
|
19
|
+
return visible;
|
|
20
|
+
}
|
|
21
|
+
/** Reset to the default (visible) — call on plugin setup so a remount starts fresh. */
|
|
22
|
+
export function resetGridOverlayVisible() {
|
|
23
|
+
setGridOverlayVisible(true);
|
|
24
|
+
}
|
|
25
|
+
function subscribe(cb) {
|
|
26
|
+
listeners.add(cb);
|
|
27
|
+
return () => listeners.delete(cb);
|
|
28
|
+
}
|
|
29
|
+
/** Smallest-id config → GridSpec (matches getDashboardConfig's deterministic pick). */
|
|
30
|
+
function specFromShapes(shapes) {
|
|
31
|
+
let chosen = null;
|
|
32
|
+
for (const shape of shapes.values()) {
|
|
33
|
+
if (isDashboardConfig(shape) && (chosen === null || shape.id < chosen.id))
|
|
34
|
+
chosen = shape;
|
|
35
|
+
}
|
|
36
|
+
if (!chosen)
|
|
37
|
+
return null;
|
|
38
|
+
const c = chosen;
|
|
39
|
+
return {
|
|
40
|
+
columns: c.columns,
|
|
41
|
+
cellW: c.cellW,
|
|
42
|
+
cellH: c.cellH,
|
|
43
|
+
gap: c.gap,
|
|
44
|
+
padding: c.padding,
|
|
45
|
+
originX: c.originX,
|
|
46
|
+
originY: c.originY,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** How many rows the current top-level items actually occupy, from their bottom
|
|
50
|
+
* edges — so a spanning item (which covers several cells) extends the drawn grid
|
|
51
|
+
* rather than being under-counted as a single cell. Own-flag locked/hidden only
|
|
52
|
+
* (ancestor checks need the store, but overlay sizing needn't be exact). */
|
|
53
|
+
function usedRows(shapes, spec) {
|
|
54
|
+
const stepY = spec.cellH + spec.gap;
|
|
55
|
+
if (stepY <= 0)
|
|
56
|
+
return 1;
|
|
57
|
+
let maxRow = 0;
|
|
58
|
+
let any = false;
|
|
59
|
+
for (const s of shapes.values()) {
|
|
60
|
+
if (isDashboardConfig(s))
|
|
61
|
+
continue;
|
|
62
|
+
if (typeof s.parentId === "string")
|
|
63
|
+
continue;
|
|
64
|
+
if (s.width <= 0 || s.height <= 0)
|
|
65
|
+
continue;
|
|
66
|
+
if (s.locked || s.hidden)
|
|
67
|
+
continue;
|
|
68
|
+
any = true;
|
|
69
|
+
const bottomRow = Math.ceil((s.y + s.height - spec.originY - spec.padding) / stepY);
|
|
70
|
+
if (bottomRow > maxRow)
|
|
71
|
+
maxRow = bottomRow;
|
|
72
|
+
}
|
|
73
|
+
return any ? maxRow : 1;
|
|
74
|
+
}
|
|
75
|
+
function GridOverlay({ viewport, shapes }) {
|
|
76
|
+
const show = useSyncExternalStore(subscribe, isGridOverlayVisible, isGridOverlayVisible);
|
|
77
|
+
const dragTarget = useSyncExternalStore(subscribeDragTarget, getDragTarget, getDragTarget);
|
|
78
|
+
const spec = specFromShapes(shapes);
|
|
79
|
+
if (!spec)
|
|
80
|
+
return null; // not a dashboard board
|
|
81
|
+
if (!show && !dragTarget)
|
|
82
|
+
return null; // nothing to draw
|
|
83
|
+
const z = viewport.zoom;
|
|
84
|
+
const cells = [];
|
|
85
|
+
if (show) {
|
|
86
|
+
const cols = Math.max(1, Math.floor(spec.columns));
|
|
87
|
+
// Cover all items' actual footprints (span-aware) plus one spare row for the
|
|
88
|
+
// next drop (min 2 rows), capped so a huge board can't explode the cell count.
|
|
89
|
+
const rows = Math.max(2, usedRows(shapes, spec) + 1);
|
|
90
|
+
const cellCount = Math.min(cols * rows, 300);
|
|
91
|
+
const w = spec.cellW * z;
|
|
92
|
+
const h = spec.cellH * z;
|
|
93
|
+
for (let i = 0; i < cellCount; i++) {
|
|
94
|
+
const tl = cellTopLeft(i, spec);
|
|
95
|
+
cells.push(_jsx("rect", { x: viewport.x + tl.x * z, y: viewport.y + tl.y * z, width: w, height: h, rx: 4, fill: "rgba(99,102,241,0.06)", stroke: "rgba(99,102,241,0.55)", strokeWidth: 1, strokeDasharray: "6 4" }, i));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// The drop-target cell: highlighted (brighter, solid) so it's obvious where the
|
|
99
|
+
// dragged item will land — including over empty space, where nothing else moves.
|
|
100
|
+
const highlight = dragTarget ? (_jsx("rect", { x: viewport.x + dragTarget.x * z, y: viewport.y + dragTarget.y * z, width: dragTarget.width * z, height: dragTarget.height * z, rx: 4, fill: "rgba(99,102,241,0.18)", stroke: "rgba(99,102,241,0.95)", strokeWidth: 2 })) : null;
|
|
101
|
+
return (_jsx("div", { style: { position: "absolute", inset: 0, pointerEvents: "none" }, children: _jsxs("svg", { width: "100%", height: "100%", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("title", { children: "Dashboard grid" }), cells, highlight] }) }));
|
|
102
|
+
}
|
|
103
|
+
/** The overlay layer descriptor. Registered in the plugin's setup. */
|
|
104
|
+
export const gridOverlayLayer = {
|
|
105
|
+
id: GRID_OVERLAY_LAYER_ID,
|
|
106
|
+
order: 20,
|
|
107
|
+
avoidCollision: true,
|
|
108
|
+
fixed: true,
|
|
109
|
+
render: (ctx) => _jsx(GridOverlay, { viewport: ctx.viewport, shapes: ctx.shapes }),
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=grid-overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid-overlay.js","sourceRoot":"","sources":["../src/grid-overlay.tsx"],"names":[],"mappings":"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"}
|
package/dist/grid.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/** Fixed-cell flow-grid geometry. `originX`/`originY` is the world anchor of the
|
|
2
|
+
* first cell's outer corner; `padding` insets the first cell from that anchor. */
|
|
3
|
+
export interface GridSpec {
|
|
4
|
+
/** Number of columns before wrapping to the next row (>= 1). */
|
|
5
|
+
columns: number;
|
|
6
|
+
/** Base cell width in world units. */
|
|
7
|
+
cellW: number;
|
|
8
|
+
/** Base cell height in world units. */
|
|
9
|
+
cellH: number;
|
|
10
|
+
/** Gap between adjacent cells (both axes). */
|
|
11
|
+
gap: number;
|
|
12
|
+
/** Inset from the origin anchor to the first cell. */
|
|
13
|
+
padding: number;
|
|
14
|
+
/** World X anchor of the grid's outer corner. */
|
|
15
|
+
originX: number;
|
|
16
|
+
/** World Y anchor of the grid's outer corner. */
|
|
17
|
+
originY: number;
|
|
18
|
+
}
|
|
19
|
+
/** A resolved top-left position for one item. The dashboard never writes size. */
|
|
20
|
+
export interface Placement {
|
|
21
|
+
id: string;
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
}
|
|
25
|
+
/** An item to place, with the size that determines its cell footprint. */
|
|
26
|
+
export interface ItemSize {
|
|
27
|
+
id: string;
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
}
|
|
31
|
+
/** How many cells an item occupies, per axis (>= 1). */
|
|
32
|
+
export interface Span {
|
|
33
|
+
cols: number;
|
|
34
|
+
rows: number;
|
|
35
|
+
}
|
|
36
|
+
/** World top-left of the cell at grid coordinate (`col`, `row`). */
|
|
37
|
+
export declare function cellXY(col: number, row: number, spec: GridSpec): {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* World top-left of the cell at flow `index` (row-major, single-cell items). Used
|
|
43
|
+
* by the grid overlay to draw the base cells; item placement uses {@link packSpans}.
|
|
44
|
+
*/
|
|
45
|
+
export declare function cellTopLeft(index: number, spec: GridSpec): {
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* How many cells a `width × height` item spans. A size that fits within one cell
|
|
51
|
+
* spans 1; every extra `cellW + gap` (resp. `cellH + gap`) of size adds a cell.
|
|
52
|
+
* Column span is clamped to the grid width; row span has no upper bound.
|
|
53
|
+
*/
|
|
54
|
+
export declare function spanOf(width: number, height: number, spec: GridSpec): Span;
|
|
55
|
+
/**
|
|
56
|
+
* Snap a size to the NEAREST whole-cell footprint: width → the closest N-column
|
|
57
|
+
* span (`N*cellW + (N-1)*gap`), height → the closest M-row span. Columns are
|
|
58
|
+
* clamped to the grid width; rows have no upper bound. Used by the "fit to grid"
|
|
59
|
+
* option so resizing snaps a shape to exact cell dimensions.
|
|
60
|
+
*/
|
|
61
|
+
export declare function fitSize(width: number, height: number, spec: GridSpec): {
|
|
62
|
+
width: number;
|
|
63
|
+
height: number;
|
|
64
|
+
};
|
|
65
|
+
/** Nearest cell (col/row) a world top-left point rounds to. */
|
|
66
|
+
export declare function cellOfPoint(x: number, y: number, spec: GridSpec): {
|
|
67
|
+
col: number;
|
|
68
|
+
row: number;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* ABSOLUTE placement: each item is snapped to the cell nearest its OWN position
|
|
72
|
+
* (gaps are preserved — items don't compact). Items are processed in the given
|
|
73
|
+
* order; if an item's desired footprint is already taken, it takes the next free
|
|
74
|
+
* one scanning forward (row-major), so earlier items in `items` win a contested
|
|
75
|
+
* cell. Returns each item's top-left in the SAME order as `items`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function packAbsolute(items: readonly PlacedBox[], spec: GridSpec): Placement[];
|
|
78
|
+
/** A placed item with its footprint, used to compute a drop index. */
|
|
79
|
+
export interface PlacedBox {
|
|
80
|
+
id: string;
|
|
81
|
+
x: number;
|
|
82
|
+
y: number;
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Insertion index for a dragged item whose centre is at `point`, given the OTHER
|
|
88
|
+
* items in reading order with their (compact) placed footprints. An item counts
|
|
89
|
+
* as "before" the point when it's on an earlier row band, or the same band and the
|
|
90
|
+
* point is at/past the item's RIGHT edge. Using the right edge (rather than the
|
|
91
|
+
* centre) means the drop point only has to be anywhere over a cell to claim that
|
|
92
|
+
* cell — so an item dropped onto the leftmost cell reliably becomes first, instead
|
|
93
|
+
* of having to cross that item's centre (a half-cell knife-edge right at the grid's
|
|
94
|
+
* left edge, made worse because the live reflow recompacts the leftmost item to
|
|
95
|
+
* exactly where the drop lands). Since `boxesInOrder` is row-major, the first
|
|
96
|
+
* not-before item ends the count — a clean `[0, boxesInOrder.length]` index.
|
|
97
|
+
*/
|
|
98
|
+
export declare function targetIndexFromPoint(point: {
|
|
99
|
+
x: number;
|
|
100
|
+
y: number;
|
|
101
|
+
}, boxesInOrder: readonly PlacedBox[], spec: GridSpec): number;
|
|
102
|
+
/**
|
|
103
|
+
* Pack sized items into the grid in order, first-fit / non-dense: each item is
|
|
104
|
+
* placed at the first free footprint at or after the previous item's start (so
|
|
105
|
+
* order is preserved and earlier holes are not back-filled), wrapping to the next
|
|
106
|
+
* row when it doesn't fit the remaining columns. Returns each item's top-left
|
|
107
|
+
* world position in the SAME order as `items`.
|
|
108
|
+
*/
|
|
109
|
+
export declare function packSpans(items: readonly ItemSize[], spec: GridSpec): Placement[];
|
|
110
|
+
//# sourceMappingURL=grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"AAUA;mFACmF;AACnF,MAAM,WAAW,QAAQ;IACxB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,kFAAkF;AAClF,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AAED,0EAA0E;AAC1E,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED,wDAAwD;AACxD,MAAM,WAAW,IAAI;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAaD,oEAAoE;AACpE,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAKzF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAInF;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAS1E;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,GACZ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CASnC;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAO9F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,CAwCrF;AAED,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/B,YAAY,EAAE,SAAS,SAAS,EAAE,EAClC,IAAI,EAAE,QAAQ,GACZ,MAAM,CAaR;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,CAiDjF"}
|
package/dist/grid.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Pure grid geometry for the dashboard: a fixed-cell flow grid anchored at a world
|
|
2
|
+
// origin, where each item occupies a whole-number block of cells (`cols × rows`)
|
|
3
|
+
// sized from its own width/height — like a real dashboard's tiles (Grafana,
|
|
4
|
+
// react-grid-layout). Items flow left→right, top→bottom and pack around each
|
|
5
|
+
// other; a wider/taller item simply takes more cells. Only the top-LEFT of each
|
|
6
|
+
// item is snapped (its footprint is measured in cells, but it is never resized).
|
|
7
|
+
//
|
|
8
|
+
// All functions here are pure and side-effect free, so they can be unit-tested in
|
|
9
|
+
// isolation and reused by both the runtime and the service `repack()` path.
|
|
10
|
+
function clamp(n, min, max) {
|
|
11
|
+
if (n < min)
|
|
12
|
+
return min;
|
|
13
|
+
if (n > max)
|
|
14
|
+
return max;
|
|
15
|
+
return n;
|
|
16
|
+
}
|
|
17
|
+
/** Normalize a spec's column count to a positive integer. */
|
|
18
|
+
function colsOf(spec) {
|
|
19
|
+
return Math.max(1, Math.floor(spec.columns));
|
|
20
|
+
}
|
|
21
|
+
/** World top-left of the cell at grid coordinate (`col`, `row`). */
|
|
22
|
+
export function cellXY(col, row, spec) {
|
|
23
|
+
return {
|
|
24
|
+
x: spec.originX + spec.padding + col * (spec.cellW + spec.gap),
|
|
25
|
+
y: spec.originY + spec.padding + row * (spec.cellH + spec.gap),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* World top-left of the cell at flow `index` (row-major, single-cell items). Used
|
|
30
|
+
* by the grid overlay to draw the base cells; item placement uses {@link packSpans}.
|
|
31
|
+
*/
|
|
32
|
+
export function cellTopLeft(index, spec) {
|
|
33
|
+
const cols = colsOf(spec);
|
|
34
|
+
const i = Math.max(0, Math.floor(index));
|
|
35
|
+
return cellXY(i % cols, Math.floor(i / cols), spec);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* How many cells a `width × height` item spans. A size that fits within one cell
|
|
39
|
+
* spans 1; every extra `cellW + gap` (resp. `cellH + gap`) of size adds a cell.
|
|
40
|
+
* Column span is clamped to the grid width; row span has no upper bound.
|
|
41
|
+
*/
|
|
42
|
+
export function spanOf(width, height, spec) {
|
|
43
|
+
const stepX = spec.cellW + spec.gap;
|
|
44
|
+
const stepY = spec.cellH + spec.gap;
|
|
45
|
+
const cols = stepX > 0 ? Math.ceil((width + spec.gap) / stepX) : 1;
|
|
46
|
+
const rows = stepY > 0 ? Math.ceil((height + spec.gap) / stepY) : 1;
|
|
47
|
+
return {
|
|
48
|
+
cols: clamp(cols, 1, colsOf(spec)),
|
|
49
|
+
rows: Math.max(1, rows),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Snap a size to the NEAREST whole-cell footprint: width → the closest N-column
|
|
54
|
+
* span (`N*cellW + (N-1)*gap`), height → the closest M-row span. Columns are
|
|
55
|
+
* clamped to the grid width; rows have no upper bound. Used by the "fit to grid"
|
|
56
|
+
* option so resizing snaps a shape to exact cell dimensions.
|
|
57
|
+
*/
|
|
58
|
+
export function fitSize(width, height, spec) {
|
|
59
|
+
const stepX = spec.cellW + spec.gap;
|
|
60
|
+
const stepY = spec.cellH + spec.gap;
|
|
61
|
+
const cols = clamp(stepX > 0 ? Math.round((width + spec.gap) / stepX) : 1, 1, colsOf(spec));
|
|
62
|
+
const rows = Math.max(1, stepY > 0 ? Math.round((height + spec.gap) / stepY) : 1);
|
|
63
|
+
return {
|
|
64
|
+
width: cols * spec.cellW + (cols - 1) * spec.gap,
|
|
65
|
+
height: rows * spec.cellH + (rows - 1) * spec.gap,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Nearest cell (col/row) a world top-left point rounds to. */
|
|
69
|
+
export function cellOfPoint(x, y, spec) {
|
|
70
|
+
const stepX = spec.cellW + spec.gap;
|
|
71
|
+
const stepY = spec.cellH + spec.gap;
|
|
72
|
+
return {
|
|
73
|
+
col: stepX > 0 ? Math.round((x - spec.originX - spec.padding) / stepX) : 0,
|
|
74
|
+
row: stepY > 0 ? Math.round((y - spec.originY - spec.padding) / stepY) : 0,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* ABSOLUTE placement: each item is snapped to the cell nearest its OWN position
|
|
79
|
+
* (gaps are preserved — items don't compact). Items are processed in the given
|
|
80
|
+
* order; if an item's desired footprint is already taken, it takes the next free
|
|
81
|
+
* one scanning forward (row-major), so earlier items in `items` win a contested
|
|
82
|
+
* cell. Returns each item's top-left in the SAME order as `items`.
|
|
83
|
+
*/
|
|
84
|
+
export function packAbsolute(items, spec) {
|
|
85
|
+
const cols = colsOf(spec);
|
|
86
|
+
const occupied = new Set();
|
|
87
|
+
const key = (r, c) => `${r},${c}`;
|
|
88
|
+
const fits = (r, c, sr, sc) => {
|
|
89
|
+
if (r < 0 || c < 0 || c + sc > cols)
|
|
90
|
+
return false;
|
|
91
|
+
for (let dr = 0; dr < sr; dr++) {
|
|
92
|
+
for (let dc = 0; dc < sc; dc++) {
|
|
93
|
+
if (occupied.has(key(r + dr, c + dc)))
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
};
|
|
99
|
+
const mark = (r, c, sr, sc) => {
|
|
100
|
+
for (let dr = 0; dr < sr; dr++) {
|
|
101
|
+
for (let dc = 0; dc < sc; dc++)
|
|
102
|
+
occupied.add(key(r + dr, c + dc));
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const out = [];
|
|
106
|
+
for (const item of items) {
|
|
107
|
+
const span = spanOf(item.width, item.height, spec);
|
|
108
|
+
const sc = span.cols;
|
|
109
|
+
const sr = span.rows;
|
|
110
|
+
const desired = cellOfPoint(item.x, item.y, spec);
|
|
111
|
+
let r = Math.max(0, desired.row);
|
|
112
|
+
let c = clamp(desired.col, 0, cols - sc);
|
|
113
|
+
while (true) {
|
|
114
|
+
if (c + sc > cols) {
|
|
115
|
+
c = 0;
|
|
116
|
+
r++;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (fits(r, c, sr, sc))
|
|
120
|
+
break;
|
|
121
|
+
c++;
|
|
122
|
+
}
|
|
123
|
+
mark(r, c, sr, sc);
|
|
124
|
+
out.push({ id: item.id, ...cellXY(c, r, spec) });
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Insertion index for a dragged item whose centre is at `point`, given the OTHER
|
|
130
|
+
* items in reading order with their (compact) placed footprints. An item counts
|
|
131
|
+
* as "before" the point when it's on an earlier row band, or the same band and the
|
|
132
|
+
* point is at/past the item's RIGHT edge. Using the right edge (rather than the
|
|
133
|
+
* centre) means the drop point only has to be anywhere over a cell to claim that
|
|
134
|
+
* cell — so an item dropped onto the leftmost cell reliably becomes first, instead
|
|
135
|
+
* of having to cross that item's centre (a half-cell knife-edge right at the grid's
|
|
136
|
+
* left edge, made worse because the live reflow recompacts the leftmost item to
|
|
137
|
+
* exactly where the drop lands). Since `boxesInOrder` is row-major, the first
|
|
138
|
+
* not-before item ends the count — a clean `[0, boxesInOrder.length]` index.
|
|
139
|
+
*/
|
|
140
|
+
export function targetIndexFromPoint(point, boxesInOrder, spec) {
|
|
141
|
+
const rowStep = spec.cellH + spec.gap;
|
|
142
|
+
const band = (y) => rowStep > 0 ? Math.round((y - spec.originY - spec.padding) / rowStep) : 0;
|
|
143
|
+
const pointerBand = band(point.y);
|
|
144
|
+
let index = 0;
|
|
145
|
+
for (const box of boxesInOrder) {
|
|
146
|
+
const b = band(box.y + box.height / 2);
|
|
147
|
+
const before = b < pointerBand || (b === pointerBand && point.x >= box.x + box.width);
|
|
148
|
+
if (!before)
|
|
149
|
+
break;
|
|
150
|
+
index++;
|
|
151
|
+
}
|
|
152
|
+
return index;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Pack sized items into the grid in order, first-fit / non-dense: each item is
|
|
156
|
+
* placed at the first free footprint at or after the previous item's start (so
|
|
157
|
+
* order is preserved and earlier holes are not back-filled), wrapping to the next
|
|
158
|
+
* row when it doesn't fit the remaining columns. Returns each item's top-left
|
|
159
|
+
* world position in the SAME order as `items`.
|
|
160
|
+
*/
|
|
161
|
+
export function packSpans(items, spec) {
|
|
162
|
+
const cols = colsOf(spec);
|
|
163
|
+
const occupied = new Set();
|
|
164
|
+
const key = (r, c) => `${r},${c}`;
|
|
165
|
+
const fits = (r, c, sr, sc) => {
|
|
166
|
+
if (c + sc > cols)
|
|
167
|
+
return false;
|
|
168
|
+
for (let dr = 0; dr < sr; dr++) {
|
|
169
|
+
for (let dc = 0; dc < sc; dc++) {
|
|
170
|
+
if (occupied.has(key(r + dr, c + dc)))
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return true;
|
|
175
|
+
};
|
|
176
|
+
const mark = (r, c, sr, sc) => {
|
|
177
|
+
for (let dr = 0; dr < sr; dr++) {
|
|
178
|
+
for (let dc = 0; dc < sc; dc++)
|
|
179
|
+
occupied.add(key(r + dr, c + dc));
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const out = [];
|
|
183
|
+
let curR = 0;
|
|
184
|
+
let curC = 0;
|
|
185
|
+
for (const item of items) {
|
|
186
|
+
const span = spanOf(item.width, item.height, spec);
|
|
187
|
+
const sc = span.cols;
|
|
188
|
+
const sr = span.rows;
|
|
189
|
+
let r = curR;
|
|
190
|
+
let c = curC;
|
|
191
|
+
// Forward scan from the cursor for the first fitting footprint.
|
|
192
|
+
while (true) {
|
|
193
|
+
if (c + sc > cols) {
|
|
194
|
+
c = 0;
|
|
195
|
+
r++;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (fits(r, c, sr, sc))
|
|
199
|
+
break;
|
|
200
|
+
c++;
|
|
201
|
+
}
|
|
202
|
+
mark(r, c, sr, sc);
|
|
203
|
+
out.push({ id: item.id, ...cellXY(c, r, spec) });
|
|
204
|
+
// Advance the cursor past this item's leading cell.
|
|
205
|
+
curR = r;
|
|
206
|
+
curC = c + sc;
|
|
207
|
+
if (curC >= cols) {
|
|
208
|
+
curC = 0;
|
|
209
|
+
curR = r + 1;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return out;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=grid.js.map
|
package/dist/grid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { type DashboardConfigPatch, ensureDashboardConfig, fitToGridOf, freeOutOfRangeOf, getDashboardConfig, gridSpecFromConfig, modeOf, setConfig, viewportLockOf, } from "./config-ops.js";
|
|
2
|
+
export { DASHBOARD_CONFIG_TYPE, DASHBOARD_DEFAULTS, type DashboardConfigData, type DashboardDefaults, type DashboardMode, isDashboardConfig, makeDashboardConfig, type ViewportLock, } from "./dashboard-config-shape.js";
|
|
3
|
+
export { createDashboardConfigShapeDefinition } from "./dashboard-config-shape-def.js";
|
|
4
|
+
export { repackBoard, setupDashboard } from "./dashboard-runtime.js";
|
|
5
|
+
export { createDashboardApi, type DashboardApi, dashboardService, getDashboardApi, } from "./dashboard-service.js";
|
|
6
|
+
export { cellOfPoint, cellTopLeft, cellXY, fitSize, type GridSpec, type ItemSize, type PlacedBox, type Placement, packAbsolute, packSpans, type Span, spanOf, targetIndexFromPoint, } from "./grid.js";
|
|
7
|
+
export { GRID_OVERLAY_LAYER_ID, gridOverlayLayer, isGridOverlayVisible, setGridOverlayVisible, } from "./grid-overlay.js";
|
|
8
|
+
export { allDashboardItems, dashboardItems, isDashboardItem, isGridItem, isWithinGrid, } from "./items.js";
|
|
9
|
+
export { readingOrder } from "./order.js";
|
|
10
|
+
export { createDashboardPlugin, type DashboardPluginOptions } from "./plugin.js";
|
|
11
|
+
export { registerDashboardHud } from "./register-dashboard-hud.js";
|
|
12
|
+
export { setupViewportLock } from "./viewport-lock.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,MAAM,EACN,SAAS,EACT,cAAc,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,YAAY,GACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,oCAAoC,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EACN,kBAAkB,EAClB,KAAK,YAAY,EACjB,gBAAgB,EAChB,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,WAAW,EACX,WAAW,EACX,MAAM,EACN,OAAO,EACP,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,SAAS,EACd,YAAY,EACZ,SAAS,EACT,KAAK,IAAI,EACT,MAAM,EACN,oBAAoB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { ensureDashboardConfig, fitToGridOf, freeOutOfRangeOf, getDashboardConfig, gridSpecFromConfig, modeOf, setConfig, viewportLockOf, } from "./config-ops.js";
|
|
2
|
+
export { DASHBOARD_CONFIG_TYPE, DASHBOARD_DEFAULTS, isDashboardConfig, makeDashboardConfig, } from "./dashboard-config-shape.js";
|
|
3
|
+
export { createDashboardConfigShapeDefinition } from "./dashboard-config-shape-def.js";
|
|
4
|
+
export { repackBoard, setupDashboard } from "./dashboard-runtime.js";
|
|
5
|
+
export { createDashboardApi, dashboardService, getDashboardApi, } from "./dashboard-service.js";
|
|
6
|
+
export { cellOfPoint, cellTopLeft, cellXY, fitSize, packAbsolute, packSpans, spanOf, targetIndexFromPoint, } from "./grid.js";
|
|
7
|
+
export { GRID_OVERLAY_LAYER_ID, gridOverlayLayer, isGridOverlayVisible, setGridOverlayVisible, } from "./grid-overlay.js";
|
|
8
|
+
export { allDashboardItems, dashboardItems, isDashboardItem, isGridItem, isWithinGrid, } from "./items.js";
|
|
9
|
+
export { readingOrder } from "./order.js";
|
|
10
|
+
export { createDashboardPlugin } from "./plugin.js";
|
|
11
|
+
export { registerDashboardHud } from "./register-dashboard-hud.js";
|
|
12
|
+
export { setupViewportLock } from "./viewport-lock.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,MAAM,EACN,SAAS,EACT,cAAc,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,qBAAqB,EACrB,kBAAkB,EAIlB,iBAAiB,EACjB,mBAAmB,GAEnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,oCAAoC,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EACN,kBAAkB,EAElB,gBAAgB,EAChB,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,WAAW,EACX,WAAW,EACX,MAAM,EACN,OAAO,EAKP,YAAY,EACZ,SAAS,EAET,MAAM,EACN,oBAAoB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,UAAU,EACV,YAAY,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAA+B,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/items.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { BoardStore, ShapeData } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { GridSpec } from "./grid.js";
|
|
3
|
+
/** True if `shape` passes the base (position-agnostic) grid-item checks: top-level,
|
|
4
|
+
* not the config substrate, has area, not locked/hidden. */
|
|
5
|
+
export declare function isDashboardItem(store: BoardStore, shape: ShapeData): boolean;
|
|
6
|
+
/** Whether a shape sits within the grid's range, judged by the shape's CENTRE
|
|
7
|
+
* against the grid's world rectangle (not a rounded cell index). Left of the grid
|
|
8
|
+
* is deliberately NOT out of range — it maps to the first column, so an item
|
|
9
|
+
* dragged in FRONT of the leftmost cell becomes first instead of being freed
|
|
10
|
+
* (dragging left past the origin is how you reorder to the front, not how you
|
|
11
|
+
* escape the grid). Only past the RIGHT edge (beyond the columns) or ABOVE the top
|
|
12
|
+
* row frees a shape. The grid grows downward without bound, so any row ≥ 0 is in. */
|
|
13
|
+
export declare function isWithinGrid(shape: ShapeData, spec: GridSpec): boolean;
|
|
14
|
+
/** True if `shape` is a MANAGED grid item on this board: base checks, plus (when
|
|
15
|
+
* `freeOutOfRange` is on) within the grid range. */
|
|
16
|
+
export declare function isGridItem(store: BoardStore, shape: ShapeData): boolean;
|
|
17
|
+
/** The board's current managed grid items, unordered — callers derive order from
|
|
18
|
+
* geometry. Used by the live drag/reflow. When `freeOutOfRange` is on, shapes
|
|
19
|
+
* outside the grid's column range are excluded (left free). */
|
|
20
|
+
export declare function dashboardItems(store: BoardStore): ShapeData[];
|
|
21
|
+
/** Every top-level dashboard item, IGNORING the grid range — used by `enable` and
|
|
22
|
+
* the "整列" action, which deliberately gather all shapes into the grid (bringing
|
|
23
|
+
* out-of-range ones back in). */
|
|
24
|
+
export declare function allDashboardItems(store: BoardStore): ShapeData[];
|
|
25
|
+
//# sourceMappingURL=items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../src/items.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAInE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;6DAC6D;AAC7D,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAO5E;AAED;;;;;;sFAMsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAQtE;AAED;qDACqD;AACrD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAKvE;AAED;;gEAEgE;AAChE,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,CAM7D;AAED;;kCAEkC;AAClC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,CAEhE"}
|
package/dist/items.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getTopLevelShapes, isEffectivelyHidden, isEffectivelyLocked } from "@edv4h/usketch-store";
|
|
2
|
+
import { freeOutOfRangeOf, getDashboardConfig, gridSpecFromConfig } from "./config-ops.js";
|
|
3
|
+
import { isDashboardConfig } from "./dashboard-config-shape.js";
|
|
4
|
+
/** True if `shape` passes the base (position-agnostic) grid-item checks: top-level,
|
|
5
|
+
* not the config substrate, has area, not locked/hidden. */
|
|
6
|
+
export function isDashboardItem(store, shape) {
|
|
7
|
+
if (typeof shape.parentId === "string")
|
|
8
|
+
return false; // nested → not a grid item
|
|
9
|
+
if (isDashboardConfig(shape))
|
|
10
|
+
return false;
|
|
11
|
+
if (shape.width <= 0 || shape.height <= 0)
|
|
12
|
+
return false; // substrate / zero-area
|
|
13
|
+
if (isEffectivelyLocked(store, shape))
|
|
14
|
+
return false;
|
|
15
|
+
if (isEffectivelyHidden(store, shape))
|
|
16
|
+
return false;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
/** Whether a shape sits within the grid's range, judged by the shape's CENTRE
|
|
20
|
+
* against the grid's world rectangle (not a rounded cell index). Left of the grid
|
|
21
|
+
* is deliberately NOT out of range — it maps to the first column, so an item
|
|
22
|
+
* dragged in FRONT of the leftmost cell becomes first instead of being freed
|
|
23
|
+
* (dragging left past the origin is how you reorder to the front, not how you
|
|
24
|
+
* escape the grid). Only past the RIGHT edge (beyond the columns) or ABOVE the top
|
|
25
|
+
* row frees a shape. The grid grows downward without bound, so any row ≥ 0 is in. */
|
|
26
|
+
export function isWithinGrid(shape, spec) {
|
|
27
|
+
const cols = Math.max(1, Math.floor(spec.columns));
|
|
28
|
+
const left = spec.originX + spec.padding;
|
|
29
|
+
const top = spec.originY + spec.padding;
|
|
30
|
+
const right = left + cols * spec.cellW + (cols - 1) * spec.gap; // last cell's right edge
|
|
31
|
+
const cx = shape.x + shape.width / 2;
|
|
32
|
+
const cy = shape.y + shape.height / 2;
|
|
33
|
+
return cx < right && cy >= top;
|
|
34
|
+
}
|
|
35
|
+
/** True if `shape` is a MANAGED grid item on this board: base checks, plus (when
|
|
36
|
+
* `freeOutOfRange` is on) within the grid range. */
|
|
37
|
+
export function isGridItem(store, shape) {
|
|
38
|
+
if (!isDashboardItem(store, shape))
|
|
39
|
+
return false;
|
|
40
|
+
const config = getDashboardConfig(store);
|
|
41
|
+
if (!config || !freeOutOfRangeOf(store))
|
|
42
|
+
return true;
|
|
43
|
+
return isWithinGrid(shape, gridSpecFromConfig(config));
|
|
44
|
+
}
|
|
45
|
+
/** The board's current managed grid items, unordered — callers derive order from
|
|
46
|
+
* geometry. Used by the live drag/reflow. When `freeOutOfRange` is on, shapes
|
|
47
|
+
* outside the grid's column range are excluded (left free). */
|
|
48
|
+
export function dashboardItems(store) {
|
|
49
|
+
const config = getDashboardConfig(store);
|
|
50
|
+
const spec = config && freeOutOfRangeOf(store) ? gridSpecFromConfig(config) : null;
|
|
51
|
+
return getTopLevelShapes(store).filter((s) => isDashboardItem(store, s) && (spec === null || isWithinGrid(s, spec)));
|
|
52
|
+
}
|
|
53
|
+
/** Every top-level dashboard item, IGNORING the grid range — used by `enable` and
|
|
54
|
+
* the "整列" action, which deliberately gather all shapes into the grid (bringing
|
|
55
|
+
* out-of-range ones back in). */
|
|
56
|
+
export function allDashboardItems(store) {
|
|
57
|
+
return getTopLevelShapes(store).filter((s) => isDashboardItem(store, s));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=items.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"items.js","sourceRoot":"","sources":["../src/items.ts"],"names":[],"mappings":"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"}
|
package/dist/order.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ShapeData } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { GridSpec } from "./grid.js";
|
|
3
|
+
/**
|
|
4
|
+
* Row-major reading order of `items` given the grid geometry. Items are bucketed
|
|
5
|
+
* into rows by their Y (tolerant of sub-cell jitter, since a whole row shares a
|
|
6
|
+
* band), then sorted left-to-right within each row. Ties are broken by original
|
|
7
|
+
* array order so the result is stable across calls with equal positions.
|
|
8
|
+
*/
|
|
9
|
+
export declare function readingOrder(items: readonly ShapeData[], spec: GridSpec): string[];
|
|
10
|
+
//# sourceMappingURL=order.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order.d.ts","sourceRoot":"","sources":["../src/order.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CASlF"}
|
package/dist/order.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row-major reading order of `items` given the grid geometry. Items are bucketed
|
|
3
|
+
* into rows by their Y (tolerant of sub-cell jitter, since a whole row shares a
|
|
4
|
+
* band), then sorted left-to-right within each row. Ties are broken by original
|
|
5
|
+
* array order so the result is stable across calls with equal positions.
|
|
6
|
+
*/
|
|
7
|
+
export function readingOrder(items, spec) {
|
|
8
|
+
const rowStep = spec.cellH + spec.gap;
|
|
9
|
+
const rowBucket = (y) => rowStep > 0 ? Math.round((y - spec.originY - spec.padding) / rowStep) : 0;
|
|
10
|
+
return items
|
|
11
|
+
.map((s, i) => ({ id: s.id, row: rowBucket(s.y), x: s.x, i }))
|
|
12
|
+
.sort((a, b) => a.row - b.row || a.x - b.x || a.i - b.i)
|
|
13
|
+
.map((e) => e.id);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order.js","sourceRoot":"","sources":["../src/order.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAA2B,EAAE,IAAc;IACvE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC;IACtC,MAAM,SAAS,GAAG,CAAC,CAAS,EAAU,EAAE,CACvC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3E,OAAO,KAAK;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SAC7D,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACvD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC"}
|