@weasel-js/guides 1.9.4 → 1.10.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/README.md +1 -1
- package/dist/{chunk-NIEZTECL.js → chunk-LOFNN7EQ.js} +2 -2
- package/dist/{chunk-NIEZTECL.js.map → chunk-LOFNN7EQ.js.map} +1 -1
- package/dist/{chunk-JETW4ZA3.js → chunk-TLFMAZ6M.js} +11 -11
- package/dist/chunk-TLFMAZ6M.js.map +1 -0
- package/dist/index.d.ts +249 -59
- package/dist/index.js +441 -35
- package/dist/index.js.map +1 -1
- package/dist/insert.d.ts +1 -1
- package/dist/insert.js +1 -1
- package/dist/move.d.ts +1 -1
- package/dist/move.js +2 -2
- package/dist/resize.d.ts +1 -1
- package/dist/resize.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-JETW4ZA3.js.map +0 -1
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ import { snapToGrid } from '@weasel-js/guides/insert';
|
|
|
52
52
|
|---|---|
|
|
53
53
|
| Grid | `createGridLayer`, `createCellHighlightLayer`, `useGridCellHover`, `gridSnapStrategy`, `pointToGridCell`, `pointSnapToGrid`, `roundToCell` |
|
|
54
54
|
| Guides | `useGuides`, `createGuidesLayer`, `guideSnapStrategy`, `deriveAlignmentGuides`, `matchAlignment`, `alignMoveBehavior`, `alignResizeBehavior`, `alignInsertBehavior` |
|
|
55
|
-
| Layout | `freeform`, `tileGrid`, `snapPoint`, and the drop-target pickers `none`, `nearest`, `nearestWithin`, `containedThenNearest`, `cellAt` |
|
|
55
|
+
| Layout | `freeform`, `tileGrid`, `snapPoint`, `slots` (with the `rowSlots`, `gridSlots`, and `ringSlots` arrangements), `pack`, `quadtree`, `perContainer` for a strategy that keeps state, and the drop-target pickers `none`, `nearest`, `nearestWithin`, `containedThenNearest`, `cellAt` |
|
|
56
56
|
|
|
57
57
|
## License
|
|
58
58
|
|
|
@@ -41,5 +41,5 @@ function guideSnapStrategy(getGuides, options = {}) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export { DEFAULT_GUIDE_TOLERANCE_PX, guideOffsetOn, guideSnapStrategy, nearestGuideDelta, roundToGridOn };
|
|
44
|
-
//# sourceMappingURL=chunk-
|
|
45
|
-
//# sourceMappingURL=chunk-
|
|
44
|
+
//# sourceMappingURL=chunk-LOFNN7EQ.js.map
|
|
45
|
+
//# sourceMappingURL=chunk-LOFNN7EQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/strategies/onPlane.ts","../src/strategies/guides.ts"],"names":[],"mappings":";;;;;AAQO,SAAS,aAAA,CAAc,GAAU,KAAA,EAAsB;AAC5D,EAAA,OAAO,KAAA,GAAQ,CAAA,CAAE,MAAA,GAAS,KAAA,CAAM,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAE,IAAI,IAAI,CAAA,CAAE,MAAA;AAC3E;AAGO,SAAS,iBAAA,CACd,MAAA,EACA,IAAA,EACA,KAAA,EACA,KACA,KAAA,EACe;AACf,EAAA,IAAI,IAAA,GAAsB,IAAA;AAC1B,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,IAAI,CAAA,CAAE,SAAS,IAAA,EAAM;AACrB,IAAA,MAAM,CAAA,GAAI,aAAA,CAAc,CAAA,EAAG,KAAK,CAAA,GAAI,KAAA;AACpC,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,IAAK,QAAQ,IAAA,KAAS,IAAA,IAAQ,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAI,IAAI,IAAA,GAAO,CAAA;AAAA,EACpF;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,aAAA,CAAc,KAAA,EAAe,IAAA,EAAY,OAAA,EAAiB,KAAA,EAAsB;AAC9F,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,KAAK,KAAA,CAAM,KAAA,GAAQ,OAAO,CAAA,GAAI,OAAA;AACjD,EAAA,MAAM,MAAA,GAAA,CAAU,QAAQ,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA,IAAK,KAAA,CAAM,MAAM,IAAI,CAAA;AAC9D,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,OAAO,CAAA,GAAI,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,GAAI,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AACvF;;;ACxBO,IAAM,0BAAA,GAA6B;
|
|
1
|
+
{"version":3,"sources":["../src/strategies/onPlane.ts","../src/strategies/guides.ts"],"names":[],"mappings":";;;;;AAQO,SAAS,aAAA,CAAc,GAAU,KAAA,EAAsB;AAC5D,EAAA,OAAO,KAAA,GAAQ,CAAA,CAAE,MAAA,GAAS,KAAA,CAAM,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAE,IAAI,IAAI,CAAA,CAAE,MAAA;AAC3E;AAGO,SAAS,iBAAA,CACd,MAAA,EACA,IAAA,EACA,KAAA,EACA,KACA,KAAA,EACe;AACf,EAAA,IAAI,IAAA,GAAsB,IAAA;AAC1B,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,IAAI,CAAA,CAAE,SAAS,IAAA,EAAM;AACrB,IAAA,MAAM,CAAA,GAAI,aAAA,CAAc,CAAA,EAAG,KAAK,CAAA,GAAI,KAAA;AACpC,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,IAAK,QAAQ,IAAA,KAAS,IAAA,IAAQ,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAI,IAAI,IAAA,GAAO,CAAA;AAAA,EACpF;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,aAAA,CAAc,KAAA,EAAe,IAAA,EAAY,OAAA,EAAiB,KAAA,EAAsB;AAC9F,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,KAAK,KAAA,CAAM,KAAA,GAAQ,OAAO,CAAA,GAAI,OAAA;AACjD,EAAA,MAAM,MAAA,GAAA,CAAU,QAAQ,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA,IAAK,KAAA,CAAM,MAAM,IAAI,CAAA;AAC9D,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,OAAO,CAAA,GAAI,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,GAAI,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AACvF;;;ACxBO,IAAM,0BAAA,GAA6B;AAuCnC,SAAS,iBAAA,CACd,SAAA,EACA,OAAA,GAAmC,EAAC,EACf;AACrB,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,0BAAA;AACvC,EAAA,MAAM,IAAA,GACJ,QAAQ,MAAA,IAAW,sBAAA;AAErB,EAAA,OAAO;AAAA,IACL,IAAA,CAAK,MAAM,GAAA,EAAK;AACd,MAAA,MAAM,SAAS,SAAA,EAAU;AACzB,MAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAIhC,MAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,SAAA,EAAW,GAAG,CAAA;AAE1C,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAC7B,MAAA,MAAM,EAAA,GAAK,iBAAA,CAAkB,MAAA,EAAQ,GAAA,EAAK,CAAA,CAAE,GAAG,GAAA,CAAI,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,IAAK,CAAA;AACpE,MAAA,MAAM,EAAA,GAAK,iBAAA,CAAkB,MAAA,EAAQ,GAAA,EAAK,CAAA,CAAE,GAAG,GAAA,CAAI,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,IAAK,CAAA;AACpE,MAAA,IAAI,EAAA,KAAO,CAAA,IAAK,EAAA,KAAO,CAAA,EAAG,OAAO,IAAA;AACjC,MAAA,OAAO,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,EAAA,EAAI,EAAE,CAAA;AAAA,IACpC;AAAA,GACF;AACF","file":"chunk-LOFNN7EQ.js","sourcesContent":["import type { GestureContext } from '@weasel-js/core';\nimport type { Guide } from '../guides/types';\n\n/** A gesture's `plane`: how the camera's world maps into the world its poses are in. */\ntype Plane = GestureContext<unknown>['plane'];\ntype Axis = 'x' | 'y';\n\n/** Where a guide the camera draws lies along its own axis in the world a gesture's poses are in. */\nexport function guideOffsetOn(g: Guide, plane: Plane): number {\n return plane ? g.offset * plane.scale[g.axis] + plane.offset[g.axis] : g.offset;\n}\n\n/** The signed distance from `value` to the nearest guide on `axis` within `tol`, or null when none is. */\nexport function nearestGuideDelta(\n guides: readonly Guide[],\n axis: Axis,\n value: number,\n tol: number,\n plane: Plane,\n): number | null {\n let best: number | null = null;\n for (const g of guides) {\n if (g.axis !== axis) continue;\n const d = guideOffsetOn(g, plane) - value;\n if (Math.abs(d) <= tol && (best === null || Math.abs(d) < Math.abs(best))) best = d;\n }\n return best;\n}\n\n/** `value` on `axis` moved to the nearest line of the camera's grid, in the world a gesture's poses are in. */\nexport function roundToGridOn(value: number, axis: Axis, spacing: number, plane: Plane): number {\n if (!plane) return Math.round(value / spacing) * spacing;\n const camera = (value - plane.offset[axis]) / plane.scale[axis];\n return Math.round(camera / spacing) * spacing * plane.scale[axis] + plane.offset[axis];\n}\n","import {\n type SnapStrategy,\n screenTolerance,\n type OriginProjection,\n AUTO_ORIGIN_PROJECTION,\n} from '@weasel-js/core';\nimport type { Guide } from '../guides/types';\nimport { nearestGuideDelta } from './onPlane';\n\n/** Default snap tolerance (screen pixels). */\nexport const DEFAULT_GUIDE_TOLERANCE_PX = 6;\n\n/** Options for `guideSnapStrategy`. */\nexport interface GuideSnapOptions<TPose> {\n /**\n * Tolerance in screen pixels, divided by the gesture view's scale so the\n * trigger zone stays the same on screen at every zoom. Defaults to\n * `DEFAULT_GUIDE_TOLERANCE_PX`.\n */\n tolerance?: number;\n /**\n * Projection used when `TPose` doesn't expose `{x, y}` directly (Path,\n * polygon, etc.) — same contract as `gridSnapStrategy`. Defaults to the\n * rect-pose identity projection.\n */\n origin?: OriginProjection<TPose>;\n}\n\n/**\n * Snap-strategy that snaps the pose's origin to the nearest guide line on\n * each axis when within tolerance. Each axis is considered independently:\n * a vertical guide (`axis: 'x'`) constrains X, a horizontal guide\n * (`axis: 'y'`) constrains Y. When multiple guides are within range on the\n * same axis, the closest wins.\n *\n * Pair with `useGuides` for storage and `createGuidesLayer` for rendering.\n * Combining with `gridSnapStrategy` is left to the consumer.\n */\nexport function guideSnapStrategy<TPose extends { x: number; y: number }>(\n getGuides: () => readonly Guide[],\n options?: Omit<GuideSnapOptions<TPose>, 'origin'>,\n): SnapStrategy<TPose>;\n/** As above, for a `TPose` that is not a rect: `origin` tells the strategy how\n * to read and write the pose's origin. */\nexport function guideSnapStrategy<TPose>(\n getGuides: () => readonly Guide[],\n options: GuideSnapOptions<TPose> & { origin: OriginProjection<TPose> },\n): SnapStrategy<TPose>;\n/** Snap a pose's origin to the nearest guide line within tolerance, per axis. */\nexport function guideSnapStrategy<TPose>(\n getGuides: () => readonly Guide[],\n options: GuideSnapOptions<TPose> = {},\n): SnapStrategy<TPose> {\n const tolerance = options.tolerance ?? DEFAULT_GUIDE_TOLERANCE_PX;\n const proj: OriginProjection<TPose> =\n options.origin ?? (AUTO_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n\n return {\n snap(pose, ctx) {\n const guides = getGuides();\n if (guides.length === 0) return null;\n\n // Per axis: a guide on the x axis is matched by a horizontal distance,\n // so it answers to `scale.x` alone.\n const tol = screenTolerance(tolerance, ctx);\n\n const o = proj.getOrigin(pose);\n const dx = nearestGuideDelta(guides, 'x', o.x, tol.x, ctx.plane) ?? 0;\n const dy = nearestGuideDelta(guides, 'y', o.y, tol.y, ctx.plane) ?? 0;\n if (dx === 0 && dy === 0) return null;\n return proj.translate(pose, dx, dy);\n },\n };\n}\n"]}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { roundToGridOn } from './chunk-
|
|
2
|
-
import { AUTO_ORIGIN_PROJECTION,
|
|
1
|
+
import { roundToGridOn } from './chunk-LOFNN7EQ.js';
|
|
2
|
+
import { AUTO_ORIGIN_PROJECTION, resolveAxes } from '@weasel-js/core';
|
|
3
3
|
|
|
4
4
|
function gridSnapStrategy(spacing, arg) {
|
|
5
|
-
const isOpts = typeof arg === "object" && arg !== null && ("origin" in arg || "debug" in arg || "unitSystem" in arg) && !("base" in arg);
|
|
5
|
+
const isOpts = typeof arg === "object" && arg !== null && ("origin" in arg || "debug" in arg || "unitSystem" in arg) && !("base" in arg) && !("x" in arg);
|
|
6
6
|
const optsArg = isOpts ? arg : null;
|
|
7
7
|
const unitSystem = optsArg ? optsArg.unitSystem : arg;
|
|
8
8
|
const proj = optsArg && optsArg.origin ? optsArg.origin : AUTO_ORIGIN_PROJECTION;
|
|
9
9
|
const debug = optsArg ? optsArg.debug : void 0;
|
|
10
|
-
const c =
|
|
10
|
+
const c = resolveAxes(spacing, unitSystem);
|
|
11
11
|
return {
|
|
12
12
|
snap(pose, ctx) {
|
|
13
13
|
const o = proj.getOrigin(pose);
|
|
14
|
-
const sx = roundToGridOn(o.x, "x", c, ctx?.plane);
|
|
15
|
-
const sy = roundToGridOn(o.y, "y", c, ctx?.plane);
|
|
14
|
+
const sx = roundToGridOn(o.x, "x", c.x, ctx?.plane);
|
|
15
|
+
const sy = roundToGridOn(o.y, "y", c.y, ctx?.plane);
|
|
16
16
|
debug?.recordSnapCandidate({ x: sx, y: sy }, true);
|
|
17
17
|
return proj.translate(pose, sx - o.x, sy - o.y);
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
function pointToGridCell(point, spacing, unitSystem, origin = { x: 0, y: 0 }) {
|
|
22
|
-
const s =
|
|
22
|
+
const s = resolveAxes(spacing, unitSystem);
|
|
23
23
|
return {
|
|
24
|
-
col: Math.floor((point.x - origin.x) / s),
|
|
25
|
-
row: Math.floor((point.y - origin.y) / s)
|
|
24
|
+
col: Math.floor((point.x - origin.x) / s.x),
|
|
25
|
+
row: Math.floor((point.y - origin.y) / s.y)
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export { gridSnapStrategy, pointToGridCell };
|
|
30
|
-
//# sourceMappingURL=chunk-
|
|
31
|
-
//# sourceMappingURL=chunk-
|
|
30
|
+
//# sourceMappingURL=chunk-TLFMAZ6M.js.map
|
|
31
|
+
//# sourceMappingURL=chunk-TLFMAZ6M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/strategies/grid.ts"],"names":[],"mappings":";;;AAkCO,SAAS,gBAAA,CACd,SACA,GAAA,EACqB;AACrB,EAAA,MAAM,SACJ,OAAO,GAAA,KAAQ,QAAA,IACf,GAAA,KAAQ,SACP,QAAA,IAAY,GAAA,IAAO,OAAA,IAAW,GAAA,IAAO,gBAAgB,GAAA,CAAA,IACtD,EAAE,MAAA,IAAU,GAAA,CAAA,IACZ,EAAE,GAAA,IAAO,GAAA,CAAA;AACX,EAAA,MAAM,OAAA,GAAU,SACX,GAAA,GACD,IAAA;AACJ,EAAA,MAAM,UAAA,GAAa,OAAA,GAAU,OAAA,CAAQ,UAAA,GAAc,GAAA;AACnD,EAAA,MAAM,IAAA,GAAgC,OAAA,IAAW,OAAA,CAAQ,MAAA,GACrD,QAAQ,MAAA,GACP,sBAAA;AACL,EAAA,MAAM,KAAA,GAA+B,OAAA,GAAU,OAAA,CAAQ,KAAA,GAAQ,MAAA;AAC/D,EAAA,MAAM,CAAA,GAAI,WAAA,CAAY,OAAA,EAAS,UAAU,CAAA;AACzC,EAAA,OAAO;AAAA,IACL,IAAA,CAAK,MAAM,GAAA,EAAK;AACd,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAC7B,MAAA,MAAM,EAAA,GAAK,cAAc,CAAA,CAAE,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA,EAAG,KAAK,KAAK,CAAA;AAClD,MAAA,MAAM,EAAA,GAAK,cAAc,CAAA,CAAE,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA,EAAG,KAAK,KAAK,CAAA;AAClD,MAAA,KAAA,EAAO,oBAAoB,EAAE,CAAA,EAAG,IAAI,CAAA,EAAG,EAAA,IAAM,IAAI,CAAA;AACjD,MAAA,OAAO,IAAA,CAAK,UAAU,IAAA,EAAM,EAAA,GAAK,EAAE,CAAA,EAAG,EAAA,GAAK,EAAE,CAAC,CAAA;AAAA,IAChD;AAAA,GACF;AACF;AAOO,SAAS,eAAA,CACd,KAAA,EACA,OAAA,EACA,UAAA,EACA,MAAA,GAAmC,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE,EAClB;AAC9B,EAAA,MAAM,CAAA,GAAI,WAAA,CAAY,OAAA,EAAS,UAAU,CAAA;AACzC,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,KAAK,KAAA,CAAA,CAAO,KAAA,CAAM,IAAI,MAAA,CAAO,CAAA,IAAK,EAAE,CAAC,CAAA;AAAA,IAC1C,GAAA,EAAK,KAAK,KAAA,CAAA,CAAO,KAAA,CAAM,IAAI,MAAA,CAAO,CAAA,IAAK,EAAE,CAAC;AAAA,GAC5C;AACF","file":"chunk-TLFMAZ6M.js","sourcesContent":["import {\n AUTO_ORIGIN_PROJECTION,\n resolveAxes,\n type DebugSink,\n type OriginProjection,\n type SnapStrategy,\n type PlaneUnits,\n type PlaneValue,\n} from '@weasel-js/core';\nimport { roundToGridOn } from './onPlane';\n\n/** Snap-strategy that rounds the pose's origin to the nearest multiple of\n * `spacing` (resolved through `unitSystem`). Either may be per axis —\n * `{ x, y }` — for a grid whose axes have different pitches or units. For\n * non-rect TPose pass an `OriginProjection` so the strategy knows how to\n * read/write the origin. */\nexport function gridSnapStrategy<TPose>(\n spacing: PlaneValue,\n unitSystem?: PlaneUnits,\n): SnapStrategy<TPose>;\n/** As above, additionally reporting each candidate to a debug sink. */\nexport function gridSnapStrategy<TPose>(\n spacing: PlaneValue,\n opts: { unitSystem?: PlaneUnits; debug?: DebugSink },\n): SnapStrategy<TPose>;\n/** As above, for a `TPose` that is not a rect: `origin` tells the strategy how\n * to read and write the pose's origin. */\nexport function gridSnapStrategy<TPose>(\n spacing: PlaneValue,\n opts: { unitSystem?: PlaneUnits; origin: OriginProjection<TPose>; debug?: DebugSink },\n): SnapStrategy<TPose>;\n/** Snap-strategy that rounds the pose's origin to the nearest multiple of\n * `spacing` (resolved through `unitSystem`). For non-rect TPose pass an\n * `OriginProjection` so the strategy knows how to read/write the origin. */\nexport function gridSnapStrategy<TPose>(\n spacing: PlaneValue,\n arg?: PlaneUnits | { unitSystem?: PlaneUnits; origin?: OriginProjection<TPose>; debug?: DebugSink },\n): SnapStrategy<TPose> {\n const isOpts =\n typeof arg === 'object' &&\n arg !== null &&\n ('origin' in arg || 'debug' in arg || 'unitSystem' in arg) &&\n !('base' in arg) &&\n !('x' in arg);\n const optsArg = isOpts\n ? (arg as { unitSystem?: PlaneUnits; origin?: OriginProjection<TPose>; debug?: DebugSink })\n : null;\n const unitSystem = optsArg ? optsArg.unitSystem : (arg as PlaneUnits | undefined);\n const proj: OriginProjection<TPose> = optsArg && optsArg.origin\n ? optsArg.origin\n : (AUTO_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n const debug: DebugSink | undefined = optsArg ? optsArg.debug : undefined;\n const c = resolveAxes(spacing, unitSystem);\n return {\n snap(pose, ctx) {\n const o = proj.getOrigin(pose);\n const sx = roundToGridOn(o.x, 'x', c.x, ctx?.plane);\n const sy = roundToGridOn(o.y, 'y', c.y, ctx?.plane);\n debug?.recordSnapCandidate({ x: sx, y: sy }, true);\n return proj.translate(pose, sx - o.x, sy - o.y);\n },\n };\n}\n\n/**\n * The integer cell `{col, row}` that contains `point`. Pair with\n * `createCellHighlightLayer` (its `getCell` callback) to draw a snap-target\n * preview that uses the same spacing as `gridSnapStrategy`.\n */\nexport function pointToGridCell(\n point: { x: number; y: number },\n spacing: PlaneValue,\n unitSystem?: PlaneUnits,\n origin: { x: number; y: number } = { x: 0, y: 0 },\n): { col: number; row: number } {\n const s = resolveAxes(spacing, unitSystem);\n return {\n col: Math.floor((point.x - origin.x) / s.x),\n row: Math.floor((point.y - origin.y) / s.y),\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
|
-
import { ViewTransform,
|
|
2
|
+
import { ViewTransform, PlaneValue, PlaneUnits, CommandStroke, RenderLayer, CommandFill, SnapStrategy, DebugSink, OriginProjection, ModifierState, Bounds, PlaneMap, PoseDescriptor, InsertBehavior, MoveBehavior, BoundsConstraint, LayoutSnap, LayoutStrategy, LayoutContainer, Vec2, ContainerBounds, LayoutChild } from '@weasel-js/core';
|
|
3
3
|
export { p as pointSnapToGrid } from './pointSnapToGrid-BaVEjV23.js';
|
|
4
4
|
import { G as Guide, S as SpacingGap } from './types-DRSPiXfk.js';
|
|
5
|
+
import { Rect } from '@weasel-js/geom';
|
|
5
6
|
|
|
6
7
|
/** Round `value` to the nearest multiple of `cellSize`. Returns 0 when the result would be -0. */
|
|
7
8
|
declare function roundToCell(value: number, cellSize: number): number;
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Pointer-tracking glue that turns hover position into a grid cell, suitable
|
|
11
|
-
* for dropping straight into `createCellHighlightLayer({ getCell })`.
|
|
12
|
-
* with `gridSnapStrategy` / `createGridLayer` so the visual hover preview
|
|
13
|
-
* uses the exact same spacing as the snap behavior.
|
|
14
|
-
*
|
|
15
|
-
* Wires three things you'd otherwise glue by hand:
|
|
16
|
-
* 1. pointermove on a target element → client coords
|
|
17
|
-
* 2. client coords → world coords via your `ViewTransform`
|
|
18
|
-
* 3. world coords → integer `{col, row}` via `pointToGridCell`
|
|
12
|
+
* for dropping straight into `createCellHighlightLayer({ getCell })`.
|
|
19
13
|
*
|
|
20
14
|
* State updates only fire when the cell actually changes (not on every
|
|
21
15
|
* pointer tick). Pass `onChange` to trigger a canvas redraw on each transition.
|
|
@@ -30,9 +24,9 @@ interface UseGridCellHoverOptions {
|
|
|
30
24
|
view: () => ViewTransform;
|
|
31
25
|
/** Cell spacing in world units. Same value you pass to `createGridLayer`
|
|
32
26
|
* and `createCellHighlightLayer`. */
|
|
33
|
-
spacing:
|
|
27
|
+
spacing: PlaneValue;
|
|
34
28
|
/** Required if `spacing` is tagged (e.g. `{ value: 1, unit: 'ft' }`). */
|
|
35
|
-
unitSystem?:
|
|
29
|
+
unitSystem?: PlaneUnits;
|
|
36
30
|
/** Origin the cell grid is anchored to, in world units. Default `(0, 0)`. */
|
|
37
31
|
origin?: {
|
|
38
32
|
x: number;
|
|
@@ -80,10 +74,11 @@ interface GridLayerOpts {
|
|
|
80
74
|
* Distance between adjacent grid lines (also known as grid pitch),
|
|
81
75
|
* in world (base) units. Accepts a bare number or a tagged
|
|
82
76
|
* `{ value, unit }`. Tagged values require `unitSystem` to be supplied.
|
|
77
|
+
* Either may be per axis — `{ x, y }`.
|
|
83
78
|
*/
|
|
84
|
-
spacing:
|
|
79
|
+
spacing: PlaneValue;
|
|
85
80
|
/** Optional unit system for resolving tagged `spacing` values. */
|
|
86
|
-
unitSystem?:
|
|
81
|
+
unitSystem?: PlaneUnits;
|
|
87
82
|
/** Bounds of the area to cover, in world units. */
|
|
88
83
|
bounds: () => {
|
|
89
84
|
x: number;
|
|
@@ -95,7 +90,7 @@ interface GridLayerOpts {
|
|
|
95
90
|
accentEvery?: number;
|
|
96
91
|
/** Optional finer subdivisions per cell. e.g. 4 -> 4 sub-lines per cell. */
|
|
97
92
|
subdivisions?: number;
|
|
98
|
-
/** Per-band stroke styles. Each is a
|
|
93
|
+
/** Per-band stroke styles. Each is a Paint+width (etc.) — see `Stroke`. */
|
|
99
94
|
style?: {
|
|
100
95
|
line?: CommandStroke;
|
|
101
96
|
accent?: CommandStroke;
|
|
@@ -114,9 +109,9 @@ declare function createGridLayer(opts: GridLayerOpts): RenderLayer<unknown>;
|
|
|
114
109
|
/** Options for `createCellHighlightLayer`. */
|
|
115
110
|
interface CellHighlightLayerOpts {
|
|
116
111
|
/** Cell size in world units (matches the grid's `spacing`). */
|
|
117
|
-
spacing:
|
|
112
|
+
spacing: PlaneValue;
|
|
118
113
|
/** Optional unit system for resolving tagged `spacing` values. */
|
|
119
|
-
unitSystem?:
|
|
114
|
+
unitSystem?: PlaneUnits;
|
|
120
115
|
/** Origin the cell grid is anchored to, in world units. Defaults to (0,0). */
|
|
121
116
|
origin?: () => {
|
|
122
117
|
x: number;
|
|
@@ -127,49 +122,39 @@ interface CellHighlightLayerOpts {
|
|
|
127
122
|
col: number;
|
|
128
123
|
row: number;
|
|
129
124
|
} | null;
|
|
130
|
-
/**
|
|
125
|
+
/** Fill for the highlighted cell. Defaults to a soft green. */
|
|
131
126
|
fill?: CommandFill;
|
|
132
127
|
}
|
|
133
128
|
/** Build a `RenderLayer` that fills a single grid cell — typically a snap-target preview. */
|
|
134
129
|
declare function createCellHighlightLayer(opts: CellHighlightLayerOpts): RenderLayer<unknown>;
|
|
135
130
|
|
|
136
131
|
/** Snap-strategy that rounds the pose's origin to the nearest multiple of
|
|
137
|
-
* `spacing` (resolved through `unitSystem`).
|
|
138
|
-
* `
|
|
139
|
-
|
|
132
|
+
* `spacing` (resolved through `unitSystem`). Either may be per axis —
|
|
133
|
+
* `{ x, y }` — for a grid whose axes have different pitches or units. For
|
|
134
|
+
* non-rect TPose pass an `OriginProjection` so the strategy knows how to
|
|
135
|
+
* read/write the origin. */
|
|
136
|
+
declare function gridSnapStrategy<TPose>(spacing: PlaneValue, unitSystem?: PlaneUnits): SnapStrategy<TPose>;
|
|
140
137
|
/** As above, additionally reporting each candidate to a debug sink. */
|
|
141
|
-
declare function gridSnapStrategy<TPose>(spacing:
|
|
142
|
-
unitSystem?:
|
|
138
|
+
declare function gridSnapStrategy<TPose>(spacing: PlaneValue, opts: {
|
|
139
|
+
unitSystem?: PlaneUnits;
|
|
143
140
|
debug?: DebugSink;
|
|
144
141
|
}): SnapStrategy<TPose>;
|
|
145
142
|
/** As above, for a `TPose` that is not a rect: `origin` tells the strategy how
|
|
146
143
|
* to read and write the pose's origin. */
|
|
147
|
-
declare function gridSnapStrategy<TPose>(spacing:
|
|
148
|
-
unitSystem?:
|
|
144
|
+
declare function gridSnapStrategy<TPose>(spacing: PlaneValue, opts: {
|
|
145
|
+
unitSystem?: PlaneUnits;
|
|
149
146
|
origin: OriginProjection<TPose>;
|
|
150
147
|
debug?: DebugSink;
|
|
151
148
|
}): SnapStrategy<TPose>;
|
|
152
149
|
/**
|
|
153
|
-
*
|
|
154
|
-
* `spacing` and optional `origin` and `unitSystem`. Pair with
|
|
150
|
+
* The integer cell `{col, row}` that contains `point`. Pair with
|
|
155
151
|
* `createCellHighlightLayer` (its `getCell` callback) to draw a snap-target
|
|
156
|
-
* preview that uses the same spacing as `gridSnapStrategy
|
|
157
|
-
* and behavioral grids stay in lockstep:
|
|
158
|
-
*
|
|
159
|
-
* const SPACING = 20;
|
|
160
|
-
* const snap = gridSnapStrategy(SPACING);
|
|
161
|
-
* // visual grid:
|
|
162
|
-
* createGridLayer({ spacing: SPACING, bounds: () => ... });
|
|
163
|
-
* // hover-preview overlay:
|
|
164
|
-
* createCellHighlightLayer({
|
|
165
|
-
* spacing: SPACING,
|
|
166
|
-
* getCell: () => hoverPoint && pointToGridCell(hoverPoint, SPACING),
|
|
167
|
-
* });
|
|
152
|
+
* preview that uses the same spacing as `gridSnapStrategy`.
|
|
168
153
|
*/
|
|
169
154
|
declare function pointToGridCell(point: {
|
|
170
155
|
x: number;
|
|
171
156
|
y: number;
|
|
172
|
-
}, spacing:
|
|
157
|
+
}, spacing: PlaneValue, unitSystem?: PlaneUnits, origin?: {
|
|
173
158
|
x: number;
|
|
174
159
|
y: number;
|
|
175
160
|
}): {
|
|
@@ -344,9 +329,8 @@ declare const MOVE_ANCHORS: {
|
|
|
344
329
|
* from the aligned siblings to the box being dragged.
|
|
345
330
|
*
|
|
346
331
|
* `worldTolerance` is per axis because a screen-pixel tolerance is not one
|
|
347
|
-
* world distance under non-uniform zoom
|
|
348
|
-
*
|
|
349
|
-
* approximation. Pass the same number twice for a world-space tolerance.
|
|
332
|
+
* world distance under non-uniform zoom. Pass the same number twice for a
|
|
333
|
+
* world-space tolerance.
|
|
350
334
|
*/
|
|
351
335
|
declare function matchAlignment(bounds: Bounds, candidates: readonly Guide[], worldTolerance: {
|
|
352
336
|
x: number;
|
|
@@ -356,14 +340,13 @@ declare function matchAlignment(bounds: Bounds, candidates: readonly Guide[], wo
|
|
|
356
340
|
y: readonly AlignAnchor[];
|
|
357
341
|
}): AlignMatchResult;
|
|
358
342
|
|
|
359
|
-
type Axis = 'x' | 'y';
|
|
360
343
|
/**
|
|
361
344
|
* The visible gaps between neighboring boxes along `axis`: for `'x'`, each box
|
|
362
345
|
* and the nearest box to its right that shares some of its vertical range, as
|
|
363
346
|
* long as no third box stands in the strip between them. These are the gaps an
|
|
364
347
|
* equal-spacing snap can reproduce.
|
|
365
348
|
*/
|
|
366
|
-
declare function measureGaps(targets: readonly Bounds[], axis:
|
|
349
|
+
declare function measureGaps(targets: readonly Bounds[], axis: 'x' | 'y'): SpacingGap[];
|
|
367
350
|
/**
|
|
368
351
|
* Match a box against the gaps between `targets`, Figma's "equal spacing":
|
|
369
352
|
* on each axis, find where the box's gap to a neighbor equals a gap that
|
|
@@ -432,10 +415,7 @@ interface GuideSnapOptions<TPose> {
|
|
|
432
415
|
* same axis, the closest wins.
|
|
433
416
|
*
|
|
434
417
|
* Pair with `useGuides` for storage and `createGuidesLayer` for rendering.
|
|
435
|
-
*
|
|
436
|
-
* **Composition:** combining with `gridSnapStrategy` is left to the
|
|
437
|
-
* consumer in v1 — typically by picking one based on a modifier key, or
|
|
438
|
-
* by stacking two move/resize/insert behaviors in priority order.
|
|
418
|
+
* Combining with `gridSnapStrategy` is left to the consumer.
|
|
439
419
|
*/
|
|
440
420
|
declare function guideSnapStrategy<TPose extends {
|
|
441
421
|
x: number;
|
|
@@ -476,6 +456,34 @@ declare function containedThenNearest<TPose>(): LayoutSnap<TPose>;
|
|
|
476
456
|
*/
|
|
477
457
|
declare function cellAt<TPose>(): LayoutSnap<TPose>;
|
|
478
458
|
|
|
459
|
+
/** Options for `perContainer`. */
|
|
460
|
+
interface PerContainerOptions<TPose> {
|
|
461
|
+
/** The snap every container shares: a strategy's `snap` is read with no
|
|
462
|
+
* container in hand, so it cannot come from the one the factory builds. */
|
|
463
|
+
snap: LayoutSnap<TPose>;
|
|
464
|
+
/** Shared for the same reason. Absent, a container's body is its bounds. */
|
|
465
|
+
contains?: LayoutStrategy<TPose>['contains'];
|
|
466
|
+
/** How many containers' strategies to keep. Past it, the one used longest
|
|
467
|
+
* ago is dropped and built again when next asked for. Default 256. */
|
|
468
|
+
max?: number;
|
|
469
|
+
}
|
|
470
|
+
/** A strategy `perContainer` built, and the way to drop one container's state. */
|
|
471
|
+
type PerContainerStrategy<TPose> = LayoutStrategy<TPose> & {
|
|
472
|
+
/** Drop what was built for `containerId`: for a container that is gone, or
|
|
473
|
+
* whose cached state no longer describes it. */
|
|
474
|
+
forget(containerId: string): void;
|
|
475
|
+
};
|
|
476
|
+
/**
|
|
477
|
+
* A layout strategy that keeps state, as one strategy value: `factory` runs
|
|
478
|
+
* once for each container the layout is asked about, and what it returns
|
|
479
|
+
* serves that container from then on, closing over whatever it caches — a
|
|
480
|
+
* spatial index, the last arrangement, a solver's warm start.
|
|
481
|
+
*
|
|
482
|
+
* Declare the result on as many containers as you like. A method the built
|
|
483
|
+
* strategy leaves out behaves as its absence would.
|
|
484
|
+
*/
|
|
485
|
+
declare function perContainer<TPose>(factory: (container: LayoutContainer) => LayoutStrategy<TPose>, opts: PerContainerOptions<TPose>): PerContainerStrategy<TPose>;
|
|
486
|
+
|
|
479
487
|
/** Options for `freeform`. */
|
|
480
488
|
interface FreeformOptions<TPose> {
|
|
481
489
|
snap?: LayoutSnap<TPose>;
|
|
@@ -488,12 +496,6 @@ interface FreeformOptions<TPose> {
|
|
|
488
496
|
*/
|
|
489
497
|
declare function freeform<TPose>(opts?: FreeformOptions<TPose>): LayoutStrategy<TPose>;
|
|
490
498
|
|
|
491
|
-
type Rect = {
|
|
492
|
-
x: number;
|
|
493
|
-
y: number;
|
|
494
|
-
width: number;
|
|
495
|
-
height: number;
|
|
496
|
-
};
|
|
497
499
|
/**
|
|
498
500
|
* What a `tileGrid` does with a child past its `cols × rows` cells.
|
|
499
501
|
*
|
|
@@ -524,10 +526,8 @@ interface TileGridOptions<TPose> {
|
|
|
524
526
|
snap?: LayoutSnap<TPose>;
|
|
525
527
|
/** Optional: map a cell rect + the dragged pose to the new pose. Default
|
|
526
528
|
* writes `{ x, y, width, height }` into the dragged pose (assumes
|
|
527
|
-
* `RectPose`).
|
|
528
|
-
*
|
|
529
|
-
* use it to preserve fields the cell rect doesn't carry (e.g. rotation,
|
|
530
|
-
* domain metadata). */
|
|
529
|
+
* `RectPose`). `dragged` is the pre-drop pose of the child being placed —
|
|
530
|
+
* use it to preserve fields the cell rect doesn't carry (e.g. rotation). */
|
|
531
531
|
cellToPose?(cellRect: Rect, dragged: TPose): TPose;
|
|
532
532
|
/** Optional: the point that decides which cell a child occupies — a child
|
|
533
533
|
* occupies the cell containing it. Default reads `x`/`y` plus half of
|
|
@@ -566,4 +566,194 @@ interface SnapPointOptions<TPose> {
|
|
|
566
566
|
* child to land on. */
|
|
567
567
|
declare function snapPoint<TPose extends Vec2>(opts: SnapPointOptions<TPose>): LayoutStrategy<TPose>;
|
|
568
568
|
|
|
569
|
-
|
|
569
|
+
/** One place a child's center goes. */
|
|
570
|
+
interface Slot {
|
|
571
|
+
x: number;
|
|
572
|
+
y: number;
|
|
573
|
+
/** The direction the slot faces, in radians, where the arrangement has one
|
|
574
|
+
* — outward from the center on a ring. `slotToPose` decides what to do
|
|
575
|
+
* with it; the default ignores it. */
|
|
576
|
+
angle?: number;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Where a container's slots are when it holds `count` children, in fill
|
|
580
|
+
* order. Returning fewer than `count` caps the container: `slots` refuses
|
|
581
|
+
* whatever would not fit.
|
|
582
|
+
*/
|
|
583
|
+
type Arrangement = (bounds: ContainerBounds, count: number) => Slot[];
|
|
584
|
+
/** Options for `rowSlots`. */
|
|
585
|
+
interface RowSlotsOptions {
|
|
586
|
+
/** The axis the row runs along. Default `'x'`. */
|
|
587
|
+
axis?: 'x' | 'y';
|
|
588
|
+
/** Distance between neighboring slots, in world units, the row centered in
|
|
589
|
+
* the container. Absent, the slots divide the container's length evenly. */
|
|
590
|
+
pitch?: number;
|
|
591
|
+
}
|
|
592
|
+
/** Slots in a line, centered across the container. */
|
|
593
|
+
declare function rowSlots(opts?: RowSlotsOptions): Arrangement;
|
|
594
|
+
/** Options for `gridSlots`. */
|
|
595
|
+
interface GridSlotsOptions {
|
|
596
|
+
cols: number;
|
|
597
|
+
/** Rows the grid has before any child needs one. Default 1. */
|
|
598
|
+
rows?: number;
|
|
599
|
+
}
|
|
600
|
+
/** Slots at the centers of a grid that fills row by row, adding a row when the
|
|
601
|
+
* last fills; the rows always divide the container's height. */
|
|
602
|
+
declare function gridSlots(opts: GridSlotsOptions): Arrangement;
|
|
603
|
+
/** Options for `ringSlots`. */
|
|
604
|
+
interface RingSlotsOptions {
|
|
605
|
+
/** Angle of the first slot, in radians, 0 pointing along +x and positive
|
|
606
|
+
* turning toward +y. Default −π/2: the top, on a y-down canvas. */
|
|
607
|
+
start?: number;
|
|
608
|
+
/** How far round the slots run. Default a full turn, which spaces them
|
|
609
|
+
* evenly; anything less puts a slot on each end of the arc. */
|
|
610
|
+
sweep?: number;
|
|
611
|
+
/** Distance to pull the ring in from the container's edges. Default 0. */
|
|
612
|
+
inset?: number;
|
|
613
|
+
}
|
|
614
|
+
/** Slots around the ellipse inscribed in the container, each facing outward. */
|
|
615
|
+
declare function ringSlots(opts?: RingSlotsOptions): Arrangement;
|
|
616
|
+
|
|
617
|
+
/** Options for `slots`. */
|
|
618
|
+
interface SlotsOptions<TPose> {
|
|
619
|
+
/** Where the slots are for a given child count: `rowSlots`, `gridSlots`,
|
|
620
|
+
* `ringSlots`, or a function of your own. */
|
|
621
|
+
arrangement: Arrangement;
|
|
622
|
+
/** Which slot a drag means. Default `nearest()`. */
|
|
623
|
+
snap?: LayoutSnap<TPose>;
|
|
624
|
+
/** The pose a child takes in a slot. Default centers the child's own
|
|
625
|
+
* `width`/`height` on the slot and keeps every other field. */
|
|
626
|
+
slotToPose?(slot: Slot, pose: TPose): TPose;
|
|
627
|
+
/** The point that decides which slot a child sits in. Default is the
|
|
628
|
+
* center of a `RectPose`, and the point itself for a point pose. */
|
|
629
|
+
centerOf?(pose: TPose): {
|
|
630
|
+
x: number;
|
|
631
|
+
y: number;
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Layout strategy that keeps its children in a sequence of slots — a row, a
|
|
636
|
+
* grid, a ring — whose positions depend on how many children there are, so
|
|
637
|
+
* the arrangement re-spaces itself as children come and go.
|
|
638
|
+
*
|
|
639
|
+
* A child's place in the sequence is the slot it sits nearest. Dropping a
|
|
640
|
+
* drag on a slot inserts it there and shifts the children between; a drag
|
|
641
|
+
* from outside is offered one slot more than the container holds. An insert
|
|
642
|
+
* or reparent lands at the slot nearest where the child was put.
|
|
643
|
+
*/
|
|
644
|
+
declare function slots<TPose>(opts: SlotsOptions<TPose>): LayoutStrategy<TPose>;
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* What `pack` does when its shelves run past the container's height.
|
|
648
|
+
*
|
|
649
|
+
* - `'reject'` (default) — refuse the child that would not fit, by any route.
|
|
650
|
+
* - `'grow'` — the container's height follows its content, never below
|
|
651
|
+
* `minHeight`.
|
|
652
|
+
* - `'scroll'` — the container keeps its size and the shelves run on below
|
|
653
|
+
* it; `contentExtent` reports the region they cover.
|
|
654
|
+
*/
|
|
655
|
+
type PackOverflow = 'reject' | 'grow' | 'scroll';
|
|
656
|
+
/** Options for `pack`. */
|
|
657
|
+
interface PackOptions<TPose> {
|
|
658
|
+
/** Space between neighbors on a shelf and between shelves, in world units. Default 0. */
|
|
659
|
+
gap?: number;
|
|
660
|
+
/** What happens past the container's height. Default `'reject'`. */
|
|
661
|
+
overflow?: PackOverflow;
|
|
662
|
+
/** The least height a `'grow'` container shrinks to. Default 0. */
|
|
663
|
+
minHeight?: number;
|
|
664
|
+
/** Which index a drag means. Default `nearest()`. */
|
|
665
|
+
snap?: LayoutSnap<TPose>;
|
|
666
|
+
/** A child's box. Default reads `x`, `y`, `width`, and `height` off the pose. */
|
|
667
|
+
rectOf?(pose: TPose): Rect;
|
|
668
|
+
/** `pose` with its box's top-left at `at`. Default writes `x` and `y`. */
|
|
669
|
+
moveTo?(pose: TPose, at: {
|
|
670
|
+
x: number;
|
|
671
|
+
y: number;
|
|
672
|
+
}): TPose;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Layout strategy that packs children of any size onto shelves: left to
|
|
676
|
+
* right at their own sizes, wrapping at the container's width, each shelf as
|
|
677
|
+
* tall as its tallest child. A child wider than the container is refused.
|
|
678
|
+
*
|
|
679
|
+
* The children's order is the order they read in — shelf by shelf, left to
|
|
680
|
+
* right. A drop inserts at the index nearest the pointer and everything after
|
|
681
|
+
* it reflows.
|
|
682
|
+
*/
|
|
683
|
+
declare function pack<TPose>(opts?: PackOptions<TPose>): LayoutStrategy<TPose>;
|
|
684
|
+
|
|
685
|
+
/** Options for `quadtree`. */
|
|
686
|
+
interface QuadtreeOptions<TPose> {
|
|
687
|
+
/** How many times the container may be quartered. Default 4, a 16 × 16 grid at its finest. */
|
|
688
|
+
maxDepth?: number;
|
|
689
|
+
/** Which free cell a drag means. Default `containedThenNearest()`. */
|
|
690
|
+
snap?: LayoutSnap<TPose>;
|
|
691
|
+
/** The length a cell's shorter side must reach to hold the child. Default
|
|
692
|
+
* is the larger of the pose's `width` and `height`. */
|
|
693
|
+
sizeOf?(pose: TPose): number;
|
|
694
|
+
/** The pose a child takes in a cell. Default centers the child's own size
|
|
695
|
+
* in the cell and keeps every other field. */
|
|
696
|
+
cellToPose?(cell: Rect, pose: TPose): TPose;
|
|
697
|
+
/** The point that decides which cell a child sits in. Default is the
|
|
698
|
+
* center of a `RectPose`, and the point itself for a point pose. */
|
|
699
|
+
centerOf?(pose: TPose): {
|
|
700
|
+
x: number;
|
|
701
|
+
y: number;
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
/** One cell a child holds: {@link QuadtreeStrategy.cells}. */
|
|
705
|
+
interface QuadtreeCell {
|
|
706
|
+
id: string;
|
|
707
|
+
/** How many times the container was quartered to reach the cell. */
|
|
708
|
+
depth: number;
|
|
709
|
+
rect: Rect;
|
|
710
|
+
}
|
|
711
|
+
/** A `quadtree` layout, which also reports the cells it has given out. */
|
|
712
|
+
interface QuadtreeStrategy<TPose> extends LayoutStrategy<TPose> {
|
|
713
|
+
/** The cell each child holds, largest first: what a debug overlay draws. */
|
|
714
|
+
cells(container: LayoutContainer, children: ReadonlyArray<LayoutChild<TPose>>): QuadtreeCell[];
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Layout strategy that quarters its container as far as each child needs: a
|
|
718
|
+
* child holds the smallest cell that fits it, so large and small children
|
|
719
|
+
* share one container without a fixed grid. A cell is free while it, the
|
|
720
|
+
* cells it sits inside, and the cells inside it hold nobody.
|
|
721
|
+
*
|
|
722
|
+
* A drag is offered the free cells of its own size. Children never move to
|
|
723
|
+
* make room: a child that finds its cell covered goes to the nearest free
|
|
724
|
+
* one, and an arrival with no free cell of its size is refused.
|
|
725
|
+
*/
|
|
726
|
+
declare function quadtree<TPose>(opts?: QuadtreeOptions<TPose>): QuadtreeStrategy<TPose>;
|
|
727
|
+
|
|
728
|
+
/** What makes a sequence layout a row of slots or a shelf-packed flow. */
|
|
729
|
+
interface Sequencer<TPose> {
|
|
730
|
+
/** `children` in sequence, read off the poses they were given when the
|
|
731
|
+
* container was last arranged for `count` children. */
|
|
732
|
+
order(container: LayoutContainer, children: ReadonlyArray<LayoutChild<TPose>>, count: number): LayoutChild<TPose>[];
|
|
733
|
+
/** A pose for every child of `sequence`, or `null` when the container
|
|
734
|
+
* cannot hold them all. */
|
|
735
|
+
place(container: LayoutContainer, sequence: ReadonlyArray<LayoutChild<TPose>>): Map<string, TPose> | null;
|
|
736
|
+
/** The bounds the container takes to hold `sequence`, for one that sizes
|
|
737
|
+
* itself to its children. */
|
|
738
|
+
resize?(container: LayoutContainer, sequence: ReadonlyArray<LayoutChild<TPose>>): ContainerBounds | undefined;
|
|
739
|
+
centerOf(pose: TPose): {
|
|
740
|
+
x: number;
|
|
741
|
+
y: number;
|
|
742
|
+
};
|
|
743
|
+
snap: LayoutSnap<TPose>;
|
|
744
|
+
/** Labels for the two kinds of op a drop writes. */
|
|
745
|
+
labels: {
|
|
746
|
+
drop: string;
|
|
747
|
+
shift: string;
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* The behavior every layout that keeps its children in one ordered sequence
|
|
752
|
+
* shares: a drop inserts at an index and shifts the children after it, an
|
|
753
|
+
* arrival goes in at the index that lands it nearest where it was put, and a
|
|
754
|
+
* departure closes the gap. The `Sequencer` says what the order is and where
|
|
755
|
+
* a sequence sits.
|
|
756
|
+
*/
|
|
757
|
+
declare function sequenceLayout<TPose>(seq: Sequencer<TPose>): LayoutStrategy<TPose>;
|
|
758
|
+
|
|
759
|
+
export { type AlignAnchor, type AlignMatchResult, type AlignMoveArgs, type AlignmentBehaviorBase, type Arrangement, type CellHighlightLayerOpts, DEFAULT_GUIDE_TOLERANCE_PX, type DeriveAlignmentGuidesOptions, type FreeformOptions, type GridLayerOpts, type GridSlotsOptions, Guide, type GuideSnapOptions, type GuidesLayerOpts, MOVE_ANCHORS, type PackOptions, type PackOverflow, type PerContainerOptions, type PerContainerStrategy, type QuadtreeCell, type QuadtreeOptions, type QuadtreeStrategy, type RingSlotsOptions, type RowSlotsOptions, type Sequencer, type Slot, type SlotsOptions, type SnapPattern, type SnapPointOptions, type SpacingEdge, SpacingGap, type SpacingMatchResult, type TileGridOptions, type TileGridOverflow, type UseGridCellHoverOptions, type UseGridCellHoverReturn, type UseGuidesReturn, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, cellAt, containedThenNearest, createCellHighlightLayer, createGridLayer, createGuidesLayer, deriveAlignmentGuides, freeform, gridSlots, gridSnapStrategy, guideSnapStrategy, matchAlignment, matchSpacing, measureGaps, nearest, nearestWithin, none, pack, perContainer, pointToGridCell, quadtree, ringSlots, roundToCell, rowSlots, sequenceLayout, slots, snapPoint, tileGrid, useGridCellHover, useGuides };
|