@weasel-js/core 0.5.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/CHANGELOG.md +381 -0
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/dist/DrawCommand-Dl0bXNfS.d.ts +500 -0
- package/dist/chunk-775XXAHR.js +216 -0
- package/dist/chunk-775XXAHR.js.map +1 -0
- package/dist/chunk-7V6JEOXE.js +27754 -0
- package/dist/chunk-7V6JEOXE.js.map +1 -0
- package/dist/chunk-AM6ARSPN.js +517 -0
- package/dist/chunk-AM6ARSPN.js.map +1 -0
- package/dist/chunk-BGGZ4CVF.js +248 -0
- package/dist/chunk-BGGZ4CVF.js.map +1 -0
- package/dist/chunk-BHVYVFGV.js +29 -0
- package/dist/chunk-BHVYVFGV.js.map +1 -0
- package/dist/chunk-CQNKCG34.js +831 -0
- package/dist/chunk-CQNKCG34.js.map +1 -0
- package/dist/chunk-GVCNT7UH.js +47 -0
- package/dist/chunk-GVCNT7UH.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +9 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-UGFFCMQP.js +28 -0
- package/dist/chunk-UGFFCMQP.js.map +1 -0
- package/dist/chunk-VOVKONXA.js +103 -0
- package/dist/chunk-VOVKONXA.js.map +1 -0
- package/dist/chunk-Y52N27PF.js +39 -0
- package/dist/chunk-Y52N27PF.js.map +1 -0
- package/dist/clipboard.d.ts +91 -0
- package/dist/clipboard.js +6 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/clone.d.ts +8 -0
- package/dist/clone.js +6 -0
- package/dist/clone.js.map +1 -0
- package/dist/fitViewToBounds-evGsnR8Q.d.ts +62 -0
- package/dist/grid-Cf87knjU.d.ts +153 -0
- package/dist/index-DZBYMsHI.d.ts +1555 -0
- package/dist/index.css +121 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +10200 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/insert.d.ts +33 -0
- package/dist/insert.js +81 -0
- package/dist/insert.js.map +1 -0
- package/dist/move.d.ts +69 -0
- package/dist/move.js +145 -0
- package/dist/move.js.map +1 -0
- package/dist/options-BPPBWMa7.d.ts +64 -0
- package/dist/patterns-builtin.d.ts +55 -0
- package/dist/patterns-builtin.js +100 -0
- package/dist/patterns-builtin.js.map +1 -0
- package/dist/pointSnapToGrid-D7s7QmOF.d.ts +185 -0
- package/dist/registerFont-CP-wCsrz.d.ts +109 -0
- package/dist/registerTexture-BzHTLhD9.d.ts +25 -0
- package/dist/renderer.css +121 -0
- package/dist/renderer.css.map +1 -0
- package/dist/renderer.d.ts +376 -0
- package/dist/renderer.js +13 -0
- package/dist/renderer.js.map +1 -0
- package/dist/resize.d.ts +78 -0
- package/dist/resize.js +5 -0
- package/dist/resize.js.map +1 -0
- package/dist/routing.css +35 -0
- package/dist/routing.css.map +1 -0
- package/dist/routing.d.ts +14 -0
- package/dist/routing.js +4 -0
- package/dist/routing.js.map +1 -0
- package/dist/types-B6MMiodD.d.ts +59 -0
- package/dist/types-BJ8_cyT7.d.ts +130 -0
- package/dist/types-B_-khFM0.d.ts +331 -0
- package/dist/types-BjUi2vA-.d.ts +355 -0
- package/dist/types-Cpb4hii1.d.ts +445 -0
- package/dist/types-D2tTKEU0.d.ts +18 -0
- package/dist/view-DSQgxBJB.d.ts +63 -0
- package/package.json +96 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { N as NodeId } from './types-Cpb4hii1.js';
|
|
2
|
+
import { C as ClipboardSnapshot, I as InsertAdapter } from './types-B_-khFM0.js';
|
|
3
|
+
import '@weasel-js/history';
|
|
4
|
+
import './types-B6MMiodD.js';
|
|
5
|
+
|
|
6
|
+
type Replacer$1 = (key: string, value: unknown) => unknown;
|
|
7
|
+
/** Options for `useClipboardOps`. */
|
|
8
|
+
interface UseClipboardOpsOptions {
|
|
9
|
+
/** How the hook reads "current selection" for copy. The kit doesn't assume
|
|
10
|
+
* a global selection store; each consumer wires this. */
|
|
11
|
+
getSelection: () => NodeId[];
|
|
12
|
+
/** Called after a successful paste with the ids of the newly inserted objects. */
|
|
13
|
+
onPaste?: (newIds: NodeId[]) => void;
|
|
14
|
+
/** Label for the history entry produced by paste. Default 'Paste'. */
|
|
15
|
+
pasteLabel?: string;
|
|
16
|
+
/** Pulled once per paste() call. When non-null, threaded to commitPaste
|
|
17
|
+
* as `ctx.dropPoint`; adapters typically use it as the cluster origin
|
|
18
|
+
* (ignoring `offset`). When null/undefined, the hook falls back to the
|
|
19
|
+
* existing cascade-offset behavior. */
|
|
20
|
+
getDropPoint?: () => {
|
|
21
|
+
worldX: number;
|
|
22
|
+
worldY: number;
|
|
23
|
+
} | null;
|
|
24
|
+
/** Produce the OS-clipboard flavor map for a copied snapshot. Keys are MIME
|
|
25
|
+
* types, values the serialized payload. The kit default emits
|
|
26
|
+
* `application/x-weasel-clipboard+json` plus `text/plain` carrying the
|
|
27
|
+
* same JSON. Apps override to add richer flavors (e.g. real SVG) or to
|
|
28
|
+
* replace the text flavor. Return an empty object to skip the OS write
|
|
29
|
+
* entirely. */
|
|
30
|
+
produceFlavors?: (snapshot: ClipboardSnapshot) => Record<string, string>;
|
|
31
|
+
/** Replacer for the kit-default JSON flavor (typed arrays etc.). Ignored
|
|
32
|
+
* when `produceFlavors` is supplied. */
|
|
33
|
+
jsonReplacer?: Replacer$1;
|
|
34
|
+
}
|
|
35
|
+
/** Return shape of `useClipboardOps`: imperative `copy`, `paste`, and `isEmpty` functions. */
|
|
36
|
+
interface UseClipboardOpsReturn {
|
|
37
|
+
copy(): void;
|
|
38
|
+
paste(): void;
|
|
39
|
+
isEmpty(): boolean;
|
|
40
|
+
}
|
|
41
|
+
/** In-memory copy/paste of selections via `InsertAdapter.snapshotSelection` / `commitPaste`. */
|
|
42
|
+
declare function useClipboardOps<TNode extends {
|
|
43
|
+
id: string;
|
|
44
|
+
}>(adapter: InsertAdapter<TNode>, options: UseClipboardOpsOptions): UseClipboardOpsReturn;
|
|
45
|
+
|
|
46
|
+
declare const WEASEL_CLIPBOARD_MIME = "application/x-weasel-clipboard+json";
|
|
47
|
+
/** Chromium's async-clipboard spelling for custom formats. */
|
|
48
|
+
declare const WEASEL_CLIPBOARD_MIME_WEB = "web application/x-weasel-clipboard+json";
|
|
49
|
+
type Replacer = (key: string, value: unknown) => unknown;
|
|
50
|
+
type Reviver = (key: string, value: unknown) => unknown;
|
|
51
|
+
/** Serialize snapshot items into the versioned wire text.
|
|
52
|
+
*
|
|
53
|
+
* Function-valued fields (e.g. a container's `clipFromPose`) are dropped by
|
|
54
|
+
* JSON serialization — OS-pasted clip containers arrive unclipped.
|
|
55
|
+
* Consumers who need clips to survive the OS round-trip can translate
|
|
56
|
+
* function ↔ registry key in their `jsonReplacer`/reviver pair (the
|
|
57
|
+
* scene-serialization `clipFromPoseKey` precedent). */
|
|
58
|
+
declare function buildWeaselClipboardText(items: unknown[], replacer?: Replacer): string;
|
|
59
|
+
/** Cheap check: could this text be a weasel clipboard payload? Substring
|
|
60
|
+
* pre-check, then a guarded parse + marker/version test. */
|
|
61
|
+
declare function sniffWeaselClipboardText(text: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Embed a weasel clipboard payload in an SVG document as a `<metadata>`
|
|
64
|
+
* child of the root — legal SVG 1.1, ignored by external tools — so one
|
|
65
|
+
* `text/plain` flavor serves both audiences: external tools parse the SVG,
|
|
66
|
+
* weasel extracts the JSON for full fidelity on draw→draw DOM paste.
|
|
67
|
+
*
|
|
68
|
+
* The payload rides in CDATA so JSON's `<` / `&` need no entity escaping; a
|
|
69
|
+
* literal `]]>` inside the payload is split across CDATA sections
|
|
70
|
+
* (`]]]]><![CDATA[>`), which {@link extractWeaselClipboardFromSvg} rejoins.
|
|
71
|
+
*
|
|
72
|
+
* Intended for OUR serializer's output only (`serializeSvg` — single
|
|
73
|
+
* `<svg ...>` open tag, XML-escaped attributes). When no open tag is found
|
|
74
|
+
* the input is returned unchanged with a debug warning.
|
|
75
|
+
*/
|
|
76
|
+
declare function embedWeaselMetadataInSvg(svgText: string, payloadText: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Recover an embedded weasel clipboard payload from SVG text: read the first
|
|
79
|
+
* `<metadata>` block, rejoin its CDATA sections (concatenation restores the
|
|
80
|
+
* `]]>` split by {@link embedWeaselMetadataInSvg}; plain non-CDATA content
|
|
81
|
+
* passes through as-is), and return the payload text iff it sniffs as the
|
|
82
|
+
* weasel wire format — else null (external/non-weasel metadata declines).
|
|
83
|
+
*
|
|
84
|
+
* A text scan, not an XML parse — the payload is small and ours.
|
|
85
|
+
*/
|
|
86
|
+
declare function extractWeaselClipboardFromSvg(svgText: string): string | null;
|
|
87
|
+
/** Parse wire text to snapshot items, or null when malformed/mismatched
|
|
88
|
+
* (callers decline to the next content handler). */
|
|
89
|
+
declare function parseWeaselClipboardText(text: string, reviver?: Reviver): unknown[] | null;
|
|
90
|
+
|
|
91
|
+
export { type UseClipboardOpsOptions, type UseClipboardOpsReturn, WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, buildWeaselClipboardText, embedWeaselMetadataInSvg, extractWeaselClipboardFromSvg, parseWeaselClipboardText, sniffWeaselClipboardText, useClipboardOps };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, buildWeaselClipboardText, embedWeaselMetadataInSvg, extractWeaselClipboardFromSvg, parseWeaselClipboardText, sniffWeaselClipboardText, useClipboardOps } from './chunk-775XXAHR.js';
|
|
2
|
+
import './chunk-BHVYVFGV.js';
|
|
3
|
+
import './chunk-GVCNT7UH.js';
|
|
4
|
+
import './chunk-PZ5AY32C.js';
|
|
5
|
+
//# sourceMappingURL=clipboard.js.map
|
|
6
|
+
//# sourceMappingURL=clipboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"clipboard.js"}
|
package/dist/clone.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { C as CloneBehavior } from './types-BjUi2vA-.js';
|
|
2
|
+
import '@weasel-js/history';
|
|
3
|
+
import './types-B_-khFM0.js';
|
|
4
|
+
|
|
5
|
+
/** Clone-on-alt-drag behavior for `useClone`; activates when Alt/Option is held at drag start. */
|
|
6
|
+
declare function cloneByAltDrag(): CloneBehavior;
|
|
7
|
+
|
|
8
|
+
export { cloneByAltDrag };
|
package/dist/clone.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"clone.js"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { V as View } from './view-DSQgxBJB.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Axis-aligned rectangle in world space. Kit-wide `Bounds` shape used by
|
|
5
|
+
* selection, group, and viewport helpers. The optional `rotation` field
|
|
6
|
+
* (radians, around the AABB center) lets selection chrome attach a rotated
|
|
7
|
+
* orientation to an otherwise axis-aligned rect without needing a parallel
|
|
8
|
+
* type.
|
|
9
|
+
*/
|
|
10
|
+
interface Bounds {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
rotation?: number;
|
|
16
|
+
}
|
|
17
|
+
/** Pixel dimensions of the canvas viewport. */
|
|
18
|
+
interface ViewportDims {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
}
|
|
22
|
+
/** Options for {@link fitViewToBounds}. */
|
|
23
|
+
interface FitViewToBoundsOptions {
|
|
24
|
+
/** Inset (in CSS px) around the bounds. Default 16. */
|
|
25
|
+
padding?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Override the kit's system max scale. Defaults to the kit-wide max zoom
|
|
28
|
+
* used by `computeWheelAction` / `useZoom` (currently `10`).
|
|
29
|
+
*/
|
|
30
|
+
maxScale?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Override the kit's system min scale. Defaults to the kit-wide min zoom
|
|
33
|
+
* used by `computeWheelAction` / `useZoom` (currently `0.1`).
|
|
34
|
+
*/
|
|
35
|
+
minScale?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Fit mode:
|
|
38
|
+
* - `'contain'` (default): uniform scale = `min(availW/w, availH/h)`. Bounds fit entirely; one axis has letterboxing.
|
|
39
|
+
* - `'fill'`: uniform scale = `max(...)`. Bounds overflow viewport on one axis.
|
|
40
|
+
* - `'stretch'`: per-axis scale. Bounds match viewport exactly; scale is non-uniform.
|
|
41
|
+
*/
|
|
42
|
+
mode?: 'contain' | 'fill' | 'stretch';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Compute the target {@link View} that fits `bounds` (world space) inside
|
|
46
|
+
* `viewportDims` (CSS px). The bounds are centered in the viewport with
|
|
47
|
+
* uniform padding on all sides; the resulting scale is clamped to the
|
|
48
|
+
* configured min/max.
|
|
49
|
+
*
|
|
50
|
+
* View semantics: `view.x` / `view.y` is the world point currently drawn at
|
|
51
|
+
* the canvas top-left, and `view.scale.{x,y}` is pixels per world unit on
|
|
52
|
+
* each axis (see `view.ts`). So:
|
|
53
|
+
* screenX = (worldX - view.x) * view.scale.x
|
|
54
|
+
* screenY = (worldY - view.y) * view.scale.y
|
|
55
|
+
*
|
|
56
|
+
* Empty / zero-sized bounds or viewports cannot be fit — in that case this
|
|
57
|
+
* returns `currentView` unchanged and logs a `console.warn`. Callers that
|
|
58
|
+
* want to no-op silently can detect zero area themselves before calling.
|
|
59
|
+
*/
|
|
60
|
+
declare function fitViewToBounds(bounds: Bounds, viewportDims: ViewportDims, currentView: View, opts?: FitViewToBoundsOptions): View;
|
|
61
|
+
|
|
62
|
+
export { type Bounds as B, type FitViewToBoundsOptions as F, type ViewportDims as V, fitViewToBounds as f };
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { a as MoveBehavior, S as SnapStrategy } from './types-BjUi2vA-.js';
|
|
2
|
+
import { D as DebugSink } from './types-BJ8_cyT7.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Units — a tiny customizable unit system for canvas-kit APIs.
|
|
6
|
+
*
|
|
7
|
+
* The kit stores all coordinates as bare numbers in a single base unit
|
|
8
|
+
* chosen by the consumer app. To make API call sites self-documenting,
|
|
9
|
+
* the public surface accepts `UnitValue` — either a bare number (interpreted
|
|
10
|
+
* as base units) or a `{ value, unit }` tag that's resolved against a
|
|
11
|
+
* `UnitSystem` at the API boundary. Internals never see units.
|
|
12
|
+
*
|
|
13
|
+
* Linear factors only. No per-axis units. No mixed-unit arithmetic.
|
|
14
|
+
*/
|
|
15
|
+
/** A unit name (e.g. `'in'`, `'ft'`, `'mm'`). Looked up in a `UnitSystem`. */
|
|
16
|
+
type Unit = string;
|
|
17
|
+
/** Conversion table mapping unit names to factors against a base unit. */
|
|
18
|
+
interface UnitSystem {
|
|
19
|
+
/** Name of the base unit, e.g. 'in'. All conversions resolve to this. */
|
|
20
|
+
base: Unit;
|
|
21
|
+
/** Factor to multiply a value in `unit` by to get base units. base unit's factor is 1. */
|
|
22
|
+
units: Record<Unit, number>;
|
|
23
|
+
}
|
|
24
|
+
/** Value at a unit-aware API boundary: bare number (in base units) or `{ value, unit }` tag. */
|
|
25
|
+
type UnitValue = number | {
|
|
26
|
+
value: number;
|
|
27
|
+
unit: Unit;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a UnitValue to a number in base units.
|
|
31
|
+
* - bare number: returned as-is (assumed base)
|
|
32
|
+
* - tagged: looks up factor; throws if unit not in unit system
|
|
33
|
+
*/
|
|
34
|
+
declare function resolveUnit(v: UnitValue, unitSystem?: UnitSystem): number;
|
|
35
|
+
/**
|
|
36
|
+
* Format a base-unit number as a string in the named display unit.
|
|
37
|
+
* e.g. formatUnit(36, 'ft', IMPERIAL_INCHES) => '3ft'
|
|
38
|
+
* Default precision: 2. Trailing zeros trimmed.
|
|
39
|
+
*/
|
|
40
|
+
declare function formatUnit(baseValue: number, displayUnit: Unit, unitSystem: UnitSystem, opts?: {
|
|
41
|
+
precision?: number;
|
|
42
|
+
suffix?: boolean;
|
|
43
|
+
}): string;
|
|
44
|
+
/** Imperial unit system with base 'in'. */
|
|
45
|
+
declare const IMPERIAL_INCHES: UnitSystem;
|
|
46
|
+
/** Metric unit system with base 'mm'. */
|
|
47
|
+
declare const METRIC_MM: UnitSystem;
|
|
48
|
+
/** Pixel unit system — sole unit is the base. */
|
|
49
|
+
declare const PIXELS: UnitSystem;
|
|
50
|
+
|
|
51
|
+
/** Option surface for the `move` action.
|
|
52
|
+
*
|
|
53
|
+
* Lives in a sibling file (not `move.ts`) so the type contract stays stable
|
|
54
|
+
* even after the legacy `useMove` hook is gone.
|
|
55
|
+
* Consumers should import from here directly; `move.ts` re-exports the
|
|
56
|
+
* same symbol for back-compat. */
|
|
57
|
+
|
|
58
|
+
interface UseMoveOptions<TPose> {
|
|
59
|
+
/** How to apply a `(dx, dy)` translation to a pose. Defaults to
|
|
60
|
+
* `translateRectPose`, which assumes the pose carries top-level
|
|
61
|
+
* `x`/`y` (the common rect-shaped case). Override for non-rect poses
|
|
62
|
+
* (e.g. `Path` → `translatePath`). */
|
|
63
|
+
translatePose?: (pose: TPose, dx: number, dy: number) => TPose;
|
|
64
|
+
behaviors?: MoveBehavior<TPose>[];
|
|
65
|
+
dragThresholdPx?: number;
|
|
66
|
+
moveLabel?: string;
|
|
67
|
+
/** Reserved for transient gestures (no history entry). Move is never transient
|
|
68
|
+
* in practice; accepted for API consistency but ignored. */
|
|
69
|
+
transient?: boolean;
|
|
70
|
+
onGestureStart?(ids: string[]): void;
|
|
71
|
+
onGestureEnd?(committed: boolean): void;
|
|
72
|
+
/** Optional: expand the incoming id list before pose lookups. Used for
|
|
73
|
+
* group expansion (groups have no pose; their leaves do).
|
|
74
|
+
* Called once at `start()`. The returned list flows through ctx,
|
|
75
|
+
* overlay (`overlay.draggedIds` is the **expanded** leaves), and op
|
|
76
|
+
* generation. Returning `[]` aborts the gesture cleanly.
|
|
77
|
+
* Default: identity. */
|
|
78
|
+
expandIds?: (ids: string[]) => string[];
|
|
79
|
+
/** Optional: lookup a world-space pose by id. When supplied alongside
|
|
80
|
+
* `adapter.getChildren`, the hook walks each dragged id's descendants and
|
|
81
|
+
* includes them in the live overlay (translated by the same drag delta
|
|
82
|
+
* and added to `overlay.hideIds`) so structurally-grouped children visually
|
|
83
|
+
* follow the parent during the gesture. No transform ops are generated
|
|
84
|
+
* for cascaded ids — under local-pose semantics, a child's local pose is
|
|
85
|
+
* unchanged when its parent's local pose moves, so the post-commit scene
|
|
86
|
+
* is already correct.
|
|
87
|
+
*
|
|
88
|
+
* Pair with `worldPoseLookup(adapter, composeRectPose)` from
|
|
89
|
+
* `@weasel-js/core/transforms` for the standard rect case. Returning
|
|
90
|
+
* `null` for an id (e.g., one removed mid-render) skips it. */
|
|
91
|
+
cascadeWorldPose?: (id: string) => TPose | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Projection used by `gridSnapStrategy` when `TPose` doesn't expose `{x,y}`
|
|
96
|
+
* directly (Path, polygon, etc.). The strategy reads the snap point via
|
|
97
|
+
* `getOrigin`, rounds it to the grid, then asks `translate` to move the
|
|
98
|
+
* pose by the resulting delta.
|
|
99
|
+
*/
|
|
100
|
+
interface OriginProjection<TPose> {
|
|
101
|
+
getOrigin(pose: TPose): {
|
|
102
|
+
x: number;
|
|
103
|
+
y: number;
|
|
104
|
+
};
|
|
105
|
+
translate(pose: TPose, dx: number, dy: number): TPose;
|
|
106
|
+
}
|
|
107
|
+
/** Identity projection for `TPose extends { x; y }`. */
|
|
108
|
+
declare const RECT_ORIGIN_PROJECTION: OriginProjection<{
|
|
109
|
+
x: number;
|
|
110
|
+
y: number;
|
|
111
|
+
}>;
|
|
112
|
+
/** Snap-strategy that rounds the pose's origin to the nearest multiple of
|
|
113
|
+
* `spacing` (resolved through `unitSystem`). For non-rect TPose pass an
|
|
114
|
+
* `OriginProjection` so the strategy knows how to read/write the origin. */
|
|
115
|
+
declare function gridSnapStrategy<TPose>(spacing: UnitValue, unitSystem?: UnitSystem): SnapStrategy<TPose>;
|
|
116
|
+
declare function gridSnapStrategy<TPose>(spacing: UnitValue, opts: {
|
|
117
|
+
unitSystem?: UnitSystem;
|
|
118
|
+
debug?: DebugSink;
|
|
119
|
+
}): SnapStrategy<TPose>;
|
|
120
|
+
declare function gridSnapStrategy<TPose>(spacing: UnitValue, opts: {
|
|
121
|
+
unitSystem?: UnitSystem;
|
|
122
|
+
origin: OriginProjection<TPose>;
|
|
123
|
+
debug?: DebugSink;
|
|
124
|
+
}): SnapStrategy<TPose>;
|
|
125
|
+
/**
|
|
126
|
+
* Compute the integer cell `{col, row}` that contains `point`, given a grid
|
|
127
|
+
* `spacing` and optional `origin` and `unitSystem`. Pair with
|
|
128
|
+
* `createCellHighlightLayer` (its `getCell` callback) to draw a snap-target
|
|
129
|
+
* preview that uses the same spacing as `gridSnapStrategy` — so the visual
|
|
130
|
+
* and behavioral grids stay in lockstep:
|
|
131
|
+
*
|
|
132
|
+
* const SPACING = 20;
|
|
133
|
+
* const snap = gridSnapStrategy(SPACING);
|
|
134
|
+
* // visual grid:
|
|
135
|
+
* createGridLayer({ spacing: SPACING, bounds: () => ... });
|
|
136
|
+
* // hover-preview overlay:
|
|
137
|
+
* createCellHighlightLayer({
|
|
138
|
+
* spacing: SPACING,
|
|
139
|
+
* getCell: () => hoverPoint && pointToGridCell(hoverPoint, SPACING),
|
|
140
|
+
* });
|
|
141
|
+
*/
|
|
142
|
+
declare function pointToGridCell(point: {
|
|
143
|
+
x: number;
|
|
144
|
+
y: number;
|
|
145
|
+
}, spacing: UnitValue, unitSystem?: UnitSystem, origin?: {
|
|
146
|
+
x: number;
|
|
147
|
+
y: number;
|
|
148
|
+
}): {
|
|
149
|
+
col: number;
|
|
150
|
+
row: number;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export { IMPERIAL_INCHES as I, METRIC_MM as M, type OriginProjection as O, PIXELS as P, RECT_ORIGIN_PROJECTION as R, type UseMoveOptions as U, type UnitValue as a, type UnitSystem as b, type Unit as c, formatUnit as f, gridSnapStrategy as g, pointToGridCell as p, resolveUnit as r };
|