@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.
Files changed (74) hide show
  1. package/CHANGELOG.md +381 -0
  2. package/LICENSE +21 -0
  3. package/README.md +144 -0
  4. package/dist/DrawCommand-Dl0bXNfS.d.ts +500 -0
  5. package/dist/chunk-775XXAHR.js +216 -0
  6. package/dist/chunk-775XXAHR.js.map +1 -0
  7. package/dist/chunk-7V6JEOXE.js +27754 -0
  8. package/dist/chunk-7V6JEOXE.js.map +1 -0
  9. package/dist/chunk-AM6ARSPN.js +517 -0
  10. package/dist/chunk-AM6ARSPN.js.map +1 -0
  11. package/dist/chunk-BGGZ4CVF.js +248 -0
  12. package/dist/chunk-BGGZ4CVF.js.map +1 -0
  13. package/dist/chunk-BHVYVFGV.js +29 -0
  14. package/dist/chunk-BHVYVFGV.js.map +1 -0
  15. package/dist/chunk-CQNKCG34.js +831 -0
  16. package/dist/chunk-CQNKCG34.js.map +1 -0
  17. package/dist/chunk-GVCNT7UH.js +47 -0
  18. package/dist/chunk-GVCNT7UH.js.map +1 -0
  19. package/dist/chunk-PZ5AY32C.js +9 -0
  20. package/dist/chunk-PZ5AY32C.js.map +1 -0
  21. package/dist/chunk-UGFFCMQP.js +28 -0
  22. package/dist/chunk-UGFFCMQP.js.map +1 -0
  23. package/dist/chunk-VOVKONXA.js +103 -0
  24. package/dist/chunk-VOVKONXA.js.map +1 -0
  25. package/dist/chunk-Y52N27PF.js +39 -0
  26. package/dist/chunk-Y52N27PF.js.map +1 -0
  27. package/dist/clipboard.d.ts +91 -0
  28. package/dist/clipboard.js +6 -0
  29. package/dist/clipboard.js.map +1 -0
  30. package/dist/clone.d.ts +8 -0
  31. package/dist/clone.js +6 -0
  32. package/dist/clone.js.map +1 -0
  33. package/dist/fitViewToBounds-evGsnR8Q.d.ts +62 -0
  34. package/dist/grid-Cf87knjU.d.ts +153 -0
  35. package/dist/index-DZBYMsHI.d.ts +1555 -0
  36. package/dist/index.css +121 -0
  37. package/dist/index.css.map +1 -0
  38. package/dist/index.d.ts +10200 -0
  39. package/dist/index.js +13 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/insert.d.ts +33 -0
  42. package/dist/insert.js +81 -0
  43. package/dist/insert.js.map +1 -0
  44. package/dist/move.d.ts +69 -0
  45. package/dist/move.js +145 -0
  46. package/dist/move.js.map +1 -0
  47. package/dist/options-BPPBWMa7.d.ts +64 -0
  48. package/dist/patterns-builtin.d.ts +55 -0
  49. package/dist/patterns-builtin.js +100 -0
  50. package/dist/patterns-builtin.js.map +1 -0
  51. package/dist/pointSnapToGrid-D7s7QmOF.d.ts +185 -0
  52. package/dist/registerFont-CP-wCsrz.d.ts +109 -0
  53. package/dist/registerTexture-BzHTLhD9.d.ts +25 -0
  54. package/dist/renderer.css +121 -0
  55. package/dist/renderer.css.map +1 -0
  56. package/dist/renderer.d.ts +376 -0
  57. package/dist/renderer.js +13 -0
  58. package/dist/renderer.js.map +1 -0
  59. package/dist/resize.d.ts +78 -0
  60. package/dist/resize.js +5 -0
  61. package/dist/resize.js.map +1 -0
  62. package/dist/routing.css +35 -0
  63. package/dist/routing.css.map +1 -0
  64. package/dist/routing.d.ts +14 -0
  65. package/dist/routing.js +4 -0
  66. package/dist/routing.js.map +1 -0
  67. package/dist/types-B6MMiodD.d.ts +59 -0
  68. package/dist/types-BJ8_cyT7.d.ts +130 -0
  69. package/dist/types-B_-khFM0.d.ts +331 -0
  70. package/dist/types-BjUi2vA-.d.ts +355 -0
  71. package/dist/types-Cpb4hii1.d.ts +445 -0
  72. package/dist/types-D2tTKEU0.d.ts +18 -0
  73. package/dist/view-DSQgxBJB.d.ts +63 -0
  74. 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"}
@@ -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,6 @@
1
+ export { cloneByAltDrag } from './chunk-UGFFCMQP.js';
2
+ import './chunk-BHVYVFGV.js';
3
+ import './chunk-GVCNT7UH.js';
4
+ import './chunk-PZ5AY32C.js';
5
+ //# sourceMappingURL=clone.js.map
6
+ //# sourceMappingURL=clone.js.map
@@ -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 };