@weasel-js/core 1.7.3 → 1.8.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 +47 -0
- package/dist/animation/colorHelpers.js +58 -58
- package/dist/animation/colorHelpers.js.map +1 -1
- package/dist/animation/engine/axes.js +36 -0
- package/dist/animation/engine/axes.js.map +1 -0
- package/dist/animation/engine/codec.js +170 -0
- package/dist/animation/engine/codec.js.map +1 -0
- package/dist/animation/engine/integrator.js +12 -0
- package/dist/animation/engine/integrator.js.map +1 -0
- package/dist/animation/useAnimator.js +199 -157
- package/dist/animation/useAnimator.js.map +1 -1
- package/dist/{builtins-C-gRyVRx.d.ts → builtins-BW32dOXy.d.ts} +74 -8
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +12 -12
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/pickWalk.js +2 -2
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/sceneSlotWiring.js +1 -1
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +1 -1
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/core/scene/effectivePose.js +1 -1
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/poseOverrides.js +42 -22
- package/dist/core/scene/poseOverrides.js.map +1 -1
- package/dist/core/scene/types.js.map +1 -1
- package/dist/index.d.ts +28 -18
- package/dist/renderer/WeaselRenderer.js +4 -1
- package/dist/renderer/WeaselRenderer.js.map +1 -1
- package/dist/renderer/batchClip.js +46 -0
- package/dist/renderer/batchClip.js.map +1 -0
- package/dist/renderer/draw.js +367 -294
- package/dist/renderer/draw.js.map +1 -1
- package/dist/renderer/drawBatch.js +75 -45
- package/dist/renderer/drawBatch.js.map +1 -1
- package/dist/renderer.d.ts +1 -1
- package/dist/tools/builtin/text/useTextTool.js +8 -8
- package/dist/tools/builtin/text/useTextTool.js.map +1 -1
- package/dist/tools/prefs.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +16 -15
package/dist/tools/prefs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefs.js","names":["prefUnit","self","unitScale","system","display","scale","opts","suffix","accepts","name","other","factor","offset","shown","stored","formatUnit","TOOL_PREF_KINDS","isBuiltinToolPref","leaf"],"sources":["../../src/tools/prefs.ts"],"sourcesContent":["// src/tools/prefs.ts\n//\n// Minimal pref descriptor for tools that want to expose user-facing\n// settings (commit-on-close, snap thresholds, etc.). Host apps compose\n// these into their own preferences registry; the kit ships no storage\n// or UI of its own. The shape is intentionally narrow — number,\n// boolean, string, enum, plus rendering hints — so it's a clean\n// structural subset of whatever a host app already has.\n\nimport { formatUnit, unitScale } from '@weasel-js/quantity';\nimport type { Display, Unit, UnitEntry, UnitScale, UnitSystem } from '@weasel-js/quantity';\n\n/** The value types a built-in pref leaf can hold. */\nexport type ToolPrefKind =\n | 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint' | 'object';\n\n/** The fields every leaf pref shares, keyed by its `kind` and typed by its stored value. */\nexport interface ToolPrefBase<K extends string, Value> {\n kind: K;\n /** Human-readable label. */\n name: string;\n /** Longer help text — shown in tooltips / a settings pane. */\n description: string;\n /** Fallback when nothing is persisted. */\n default: Value;\n /** Hide from a host app's settings UI by default. */\n hidden?: boolean;\n /** Render full-width with no label row in schema-driven settings UIs\n * (weasel-ui `PrefsForm` honors this for leaves whose control brings\n * its own chrome). */\n block?: boolean;\n /** Glyph naming this leaf in a host UI's icon set (weasel-ui resolves it\n * against `ICON_PATHS`). A plain string because core ships no icon set and\n * cannot depend on one. Read where a leaf's `name` has nowhere to go — a\n * `pair`ed row is labeled by the pair, so its fields have only the glyph\n * to tell them apart. */\n icon?: string;\n /** Row-pairing hint for compact property UIs (weasel-ui\n * `SelectionPanel`): leaves sharing a `pair` id render side-by-side\n * on one row labeled with the `pair` string (e.g. `'Position'` for\n * `pose.x` / `pose.y`). Purely presentational. */\n pair?: string;\n /** The label a surface with no room for `name` shows instead — a strip of\n * controls on one line, or a segment in a `pair`ed row. `name` stays the\n * accessible name, so this abbreviates without costing anything. */\n short?: string;\n}\n\n/** How a schema-driven UI should present a number pref. */\nexport type ToolPrefNumberControl = 'input' | 'slider';\n/** How a schema-driven UI should present a boolean pref. */\nexport type ToolPrefBooleanControl = 'checkbox' | 'switch' | 'toggle';\n/** How a schema-driven UI should present a string pref. */\nexport type ToolPrefStringControl = 'input' | 'textarea';\n/** How a schema-driven UI should present an enum pref. */\nexport type ToolPrefEnumControl = 'select' | 'radio' | 'toggle';\n\n/** Display-unit conversion for number leaves whose stored value uses a\n * canonical unit the user shouldn't see (e.g. radians stored, degrees\n * shown). The stored value stays canonical; UIs convert at the edge. */\nexport interface ToolPrefNumberUnit {\n toDisplay: (stored: number) => number;\n fromDisplay: (display: number) => number;\n /** Shown after the input, e.g. `'°'`. */\n suffix?: string;\n /** Suffixes a person may type, each mapped to the scale that turns a\n * number in that unit into a display number: `{ mm: 0.1, cm: 1 }` for a\n * field showing centimeters. A unit that disagrees with the display unit\n * about zero carries an `offset` as well. */\n accepts?: Readonly<Record<string, UnitEntry>>;\n /** The stored value as display text, suffix included. */\n format?: (stored: number) => string;\n}\n\n/**\n * A display unit built from a {@link UnitSystem}: values are stored in the\n * system's base and shown in `display`, rounded to `precision` places when\n * given, and every unit in the system is accepted as typed text. `suffix`\n * defaults to the unit's name and is accepted too.\n */\nexport function prefUnit(\n system: UnitSystem,\n display: Unit,\n opts?: { precision?: number; suffix?: string },\n): ToolPrefNumberUnit {\n let self: Required<UnitScale>;\n try {\n self = unitScale(system, display);\n } catch (e) {\n throw new Error(`prefUnit: ${e instanceof Error ? e.message : String(e)}`);\n }\n const scale = opts?.precision === undefined ? undefined : 10 ** opts.precision;\n const suffix = opts?.suffix ?? display;\n const accepts: Record<string, UnitEntry> = { [suffix]: 1 };\n for (const name of Object.keys(system.units)) {\n const other = unitScale(system, name);\n // A number typed in `name` reaches display units through base:\n // `(n * factor + offset - self.offset) / self.factor`.\n const factor = other.factor / self.factor;\n const offset = (other.offset - self.offset) / self.factor;\n accepts[name] = offset === 0 ? factor : { factor, offset };\n }\n const toDisplay = (stored: number) => {\n const shown = (stored - self.offset) / self.factor;\n return scale === undefined ? shown : Math.round(shown * scale) / scale;\n };\n return {\n toDisplay,\n fromDisplay: (shown) => shown * self.factor + self.offset,\n suffix,\n accepts,\n format: (stored) =>\n `${formatUnit(stored, display, system, {\n precision: opts?.precision ?? 2,\n suffix: false,\n })}${suffix}`,\n };\n}\n\n/** A numeric pref, optionally bounded and stepped, and optionally stored in a\n * different unit from the one shown. */\nexport interface ToolPrefNumber extends ToolPrefBase<'number', number> {\n min?: number;\n max?: number;\n step?: number;\n control?: ToolPrefNumberControl;\n /** How the value shows, speaks and reads back when typed — `compact()`\n * reads `2.00M`. Presentation only: the stored value stays a number. */\n display?: Display;\n unit?: ToolPrefNumberUnit;\n}\n/**\n * Stored-value bridge for a boolean leaf whose field is not a boolean — the\n * flag counterpart of {@link ToolPrefEnumEncoding}. `TextStyle.fontStyle` is\n * the case: it stores `'italic'`, and the control is an Italic toggle.\n */\nexport interface ToolPrefBooleanEncoding {\n /** Whether `stored` reads as on. */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => boolean;\n /** What to store for `on`. `undefined` removes the field. */\n write: (on: boolean, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** An on/off pref. */\nexport interface ToolPrefBoolean extends ToolPrefBase<'boolean', boolean> {\n control?: ToolPrefBooleanControl;\n encoding?: ToolPrefBooleanEncoding;\n}\n/** A free-text pref. */\nexport interface ToolPrefString extends ToolPrefBase<'string', string> {\n control?: ToolPrefStringControl;\n}\n/**\n * Stored-value bridge for an enum leaf whose value is not the option string —\n * the counterpart of {@link ToolPrefNumberUnit}, which does the same for a\n * number stored in a canonical unit.\n *\n * A dash array is the case that needs it: `Stroke.dash` stores lengths, and\n * the thing a person chooses is a style. The presets scale by the stroke's\n * width, so both directions are given the object's other fields — a style is\n * meaningless without the width it is a multiple of.\n */\nexport interface ToolPrefEnumEncoding<T extends string = string> {\n /**\n * The option `stored` reads as, or `undefined` for none — which a UI shows\n * the way it shows a mixed selection, by selecting nothing.\n *\n * `siblings` is the object the leaf is a field of, or `undefined` when the\n * node does not hold that object (and for a top-level leaf, which has none).\n */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => T | undefined;\n /** What to store for `option`. `undefined` removes the field. */\n write: (option: T, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** A pref with a fixed set of labeled choices. `default` is `undefined` only\n * for a {@link ToolPrefEnum.clearable} leaf, whose absence is a value. */\nexport interface ToolPrefEnum<T extends string = string>\n extends ToolPrefBase<'enum', T | undefined> {\n /**\n * The field may hold none of the options, and that absence is a state of\n * its own rather than a missing value — a script that is neither super nor\n * sub. A toggle control then lets the chosen segment be clicked off, which\n * removes the field.\n */\n clearable?: boolean;\n /** `short` is the label a segmented control uses when a full one would not\n * fit — a capital or two. `icon` names a glyph in the host UI's set\n * (weasel-ui resolves it against `ICON_PATHS`) and outranks `short` where\n * it resolves. It is a plain string because core ships no icon set and\n * cannot depend on one. The full `label` stays the accessible name, so\n * neither the abbreviation nor the glyph becomes the only thing naming\n * the option.\n *\n * `disabled` marks an option a control reports but cannot author — the\n * value a stored form reads as when it matches nothing offered. Dropping it\n * from the list instead would leave the control selecting nothing and\n * claiming the field is unset. */\n options: readonly {\n value: T;\n label: string;\n short?: string;\n icon?: string;\n disabled?: boolean;\n }[];\n control?: ToolPrefEnumControl;\n encoding?: ToolPrefEnumEncoding<T>;\n}\n\n/** A single color, stored as a hex string. For a value that may also be a\n * gradient or a pattern, use {@link ToolPrefPaint} instead. */\nexport interface ToolPrefColor extends ToolPrefBase<'color', string> {\n /** Value is `#rrggbb`, or `#rrggbbaa` when `alpha` is set (UIs then\n * offer an opacity control). */\n alpha?: boolean;\n}\n\n/**\n * Open leaf: any node with a `kind` outside the built-ins. Schema-driven\n * UIs (weasel-ui `PrefsForm` / `SelectionPanel`) dispatch it to an\n * app-supplied renderer. Deliberately NOT index-signatured so concrete\n * app interfaces stay assignable. Mirrors weasel-ui's `PrefCustom`.\n */\nexport type ToolPrefCustom = ToolPrefBase<string, unknown>;\n\n/**\n * A whole `FillStyle`, not a color inside one. Use it wherever the value is\n * the tagged paint union — a solid color, a pattern, a gradient — rather\n * than a hex string.\n *\n * Addressing `…fill.color` instead reads `undefined` off a gradient (so the\n * control shows its default and claims the text is black) and writes a\n * hybrid `{ fill: 'gradient', stops, color }` that the renderer's structural\n * `'color' in paint` checks then paint flat solid. The union has to be\n * edited as a union.\n */\nexport interface ToolPrefPaint extends ToolPrefBase<'paint', unknown> {\n /** Offer an opacity control alongside the color. */\n alpha?: boolean;\n}\n\n/**\n * A leaf whose value is one object, with its own fields hanging off it.\n *\n * A compound value — a stroke, a shadow, a pattern spec — could be described\n * as several sibling leaves addressing into it (`data.stroke.width`,\n * `data.stroke.cap`). It shouldn't be: each control would then write one field\n * of a value it can only half see, and writing into something that is not an\n * object yet corrupts it. Here the fields are `children` of one leaf, and\n * every edit commits the parent object whole.\n *\n * `children` paths are relative to the object. They are ordinary leaves, so a\n * field that is itself a union (a stroke's `paint`) declares the kind that\n * edits that union. A child may also be a {@link ToolPrefGroup}, which\n * organises the fields under a heading without contributing to the path —\n * the same rule group keys follow at the top level. A `TextStyle` needs it:\n * its character and paragraph fields belong to one value but read as two\n * lists.\n */\nexport interface ToolPrefObject extends ToolPrefBase<'object', unknown> {\n children: Record<string, ToolPrefLeaf | ToolPrefGroup>;\n /**\n * Lift a non-object value into the object form, for a consumer field that\n * may also be held as a scalar. Called before a child edit is applied;\n * without it a scalar-valued leaf shows its children empty and refuses the\n * edit.\n */\n fromScalar?: (value: unknown) => Record<string, unknown>;\n}\n\n/** One built-in pref leaf. `ToolPrefLeaf` widens this to include\n * app-defined kinds. */\nexport type ToolPref =\n | ToolPrefNumber\n | ToolPrefBoolean\n | ToolPrefString\n | ToolPrefEnum\n | ToolPrefColor\n | ToolPrefPaint\n | ToolPrefObject;\n\n// Compile-time tie: every built-in leaf kind must appear in ToolPrefKind\n// and vice versa (ToolPrefBase's K is open for ToolPrefCustom's sake, so\n// the union no longer enforces it).\ntype _BuiltinKindsExact = [ToolPref['kind']] extends [ToolPrefKind]\n ? [ToolPrefKind] extends [ToolPref['kind']] ? true : never\n : never;\nconst _builtinKindsExact: _BuiltinKindsExact = true;\nvoid _builtinKindsExact;\n\n/**\n * The built-in kinds, as a table. A kind added to {@link ToolPrefKind} is a\n * compile error here, and from here it is one in every renderer's `never`\n * guard — the only thing standing between a new kind and rendering as\n * nothing in four places at once.\n */\nexport const TOOL_PREF_KINDS: Record<ToolPrefKind, true> = {\n number: true,\n boolean: true,\n string: true,\n enum: true,\n color: true,\n paint: true,\n object: true,\n};\n\n/**\n * Narrows a leaf to the built-in union, so a renderer's switch discriminates\n * on {@link ToolPrefKind} instead of the open `string` that\n * {@link ToolPrefCustom} widens `kind` to. An app-defined kind answers false\n * and belongs to the renderer's custom-renderer path.\n */\nexport function isBuiltinToolPref(leaf: ToolPrefLeaf): leaf is ToolPref {\n return Object.hasOwn(TOOL_PREF_KINDS, leaf.kind);\n}\n\n/** Built-in or app-defined leaf. */\nexport type ToolPrefLeaf = ToolPref | ToolPrefCustom;\n\n/** Nestable group: branch nodes a tool can use to organize its prefs. */\nexport interface ToolPrefGroup {\n /** Heading for the group's rows. **Empty means no heading** — for a group\n * that exists to organise, not to name: one whose children are themselves\n * groups carrying the labels a reader needs. Give it a name whenever the\n * name is the referent (a `Border` group over `Top` / `Right` / `Bottom`\n * reads as nothing without it). */\n name: string;\n description?: string;\n children: Record<string, ToolPrefLeaf | ToolPrefGroup>;\n}\n"],"mappings":";;AAgFA,SAAgBA,EACd,GACA,GACA,GACoB;CACpB,IAAIC;CACJ,IAAI;EACF,IAAOC,EAAUC,GAAQC,CAAO;CAClC,SAAS,GAAG;EACV,MAAU,MAAM,aAAa,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG;CAC3E;CACA,IAAMC,IAAQC,GAAM,cAAc,KAAA,IAAY,KAAA,IAAY,MAAMA,EAAK,WAC/DC,IAASD,GAAM,UAAUF,GACzBI,IAAqC,GAAGD,IAAS,EAAE;CACzD,KAAK,IAAME,KAAQ,OAAO,KAAKN,EAAO,KAAK,GAAG;EAC5C,IAAMO,IAAQR,EAAUC,GAAQM,CAAI,GAG9BE,IAASD,EAAM,SAAST,EAAK,QAC7BW,KAAUF,EAAM,SAAST,EAAK,UAAUA,EAAK;EACnD,EAAQQ,KAAQG,MAAW,IAAID,IAAS;GAAE;GAAQ;EAAO;CAC3D;CAKA,OAAO;EACL,YALiB,MAAmB;GACpC,IAAME,KAASC,IAASb,EAAK,UAAUA,EAAK;GAC5C,OAAOI,MAAU,KAAA,IAAYQ,IAAQ,KAAK,MAAMA,IAAQR,CAAK,IAAIA;EACnE;EAGE,cAAc,MAAUQ,IAAQZ,EAAK,SAASA,EAAK;EACnD;EACA;EACA,SAAS,MACP,GAAGc,EAAWD,GAAQV,GAASD,GAAQ;GACrC,WAAWG,GAAM,aAAa;GAC9B,QAAQ;EACV,CAAC,IAAIC;CACT;AACF;AAmLA,IAAaS,IAA8C;CACzD,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,MAAM;CACN,OAAO;CACP,OAAO;CACP,QAAQ;AACV;AAQA,SAAgBC,EAAkB,GAAsC;CACtE,OAAO,OAAO,OAAOD,GAAiBE,EAAK,IAAI;AACjD"}
|
|
1
|
+
{"version":3,"file":"prefs.js","names":["prefUnit","self","unitScale","system","display","scale","opts","suffix","accepts","name","other","factor","offset","shown","stored","formatUnit","TOOL_PREF_KINDS","isBuiltinToolPref","leaf"],"sources":["../../src/tools/prefs.ts"],"sourcesContent":["// src/tools/prefs.ts\n//\n// Minimal pref descriptor for tools that want to expose user-facing\n// settings (commit-on-close, snap thresholds, etc.). Host apps compose\n// these into their own preferences registry; the kit ships no storage\n// or UI of its own. The shape is intentionally narrow — number,\n// boolean, string, enum, plus rendering hints — so it's a clean\n// structural subset of whatever a host app already has.\n\nimport { formatUnit, unitScale } from '@weasel-js/quantity';\nimport type { Display, InfinityText, Unit, UnitEntry, UnitScale, UnitSystem } from '@weasel-js/quantity';\n\n/** The value types a built-in pref leaf can hold. */\nexport type ToolPrefKind =\n | 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint' | 'object';\n\n/** The fields every leaf pref shares, keyed by its `kind` and typed by its stored value. */\nexport interface ToolPrefBase<K extends string, Value> {\n kind: K;\n /** Human-readable label. */\n name: string;\n /** Longer help text — shown in tooltips / a settings pane. */\n description: string;\n /** Fallback when nothing is persisted. */\n default: Value;\n /** Hide from a host app's settings UI by default. */\n hidden?: boolean;\n /** Render full-width with no label row in schema-driven settings UIs\n * (weasel-ui `PrefsForm` honors this for leaves whose control brings\n * its own chrome). */\n block?: boolean;\n /** Glyph naming this leaf in a host UI's icon set (weasel-ui resolves it\n * against `ICON_PATHS`). A plain string because core ships no icon set and\n * cannot depend on one. Read where a leaf's `name` has nowhere to go — a\n * `pair`ed row is labeled by the pair, so its fields have only the glyph\n * to tell them apart. */\n icon?: string;\n /** Row-pairing hint for compact property UIs (weasel-ui\n * `SelectionPanel`): leaves sharing a `pair` id render side-by-side\n * on one row labeled with the `pair` string (e.g. `'Position'` for\n * `pose.x` / `pose.y`). Purely presentational. */\n pair?: string;\n /** Shorter forms of `name`, longest first. A surface short of room for\n * `name` — a strip of controls on one line, a segment in a `pair`ed row —\n * shows the longest of them that fits. `name` stays the accessible name, so\n * these abbreviate without costing anything. */\n short?: readonly string[];\n}\n\n/** How a schema-driven UI should present a number pref. */\nexport type ToolPrefNumberControl = 'input' | 'slider';\n/** How a schema-driven UI should present a boolean pref. */\nexport type ToolPrefBooleanControl = 'checkbox' | 'switch' | 'toggle';\n/** How a schema-driven UI should present a string pref. */\nexport type ToolPrefStringControl = 'input' | 'textarea';\n/** How a schema-driven UI should present an enum pref. */\nexport type ToolPrefEnumControl = 'select' | 'radio' | 'toggle';\n\n/** Display-unit conversion for number leaves whose stored value uses a\n * canonical unit the user shouldn't see (e.g. radians stored, degrees\n * shown). The stored value stays canonical; UIs convert at the edge. */\nexport interface ToolPrefNumberUnit {\n toDisplay: (stored: number) => number;\n fromDisplay: (display: number) => number;\n /** Shown after the input, e.g. `'°'`. */\n suffix?: string;\n /** Suffixes a person may type, each mapped to the scale that turns a\n * number in that unit into a display number: `{ mm: 0.1, cm: 1 }` for a\n * field showing centimeters. A unit that disagrees with the display unit\n * about zero carries an `offset` as well. */\n accepts?: Readonly<Record<string, UnitEntry>>;\n /** The stored value as display text, suffix included. */\n format?: (stored: number) => string;\n}\n\n/**\n * A display unit built from a {@link UnitSystem}: values are stored in the\n * system's base and shown in `display`, rounded to `precision` places when\n * given, and every unit in the system is accepted as typed text. `suffix`\n * defaults to the unit's name and is accepted too.\n */\nexport function prefUnit(\n system: UnitSystem,\n display: Unit,\n opts?: { precision?: number; suffix?: string },\n): ToolPrefNumberUnit {\n let self: Required<UnitScale>;\n try {\n self = unitScale(system, display);\n } catch (e) {\n throw new Error(`prefUnit: ${e instanceof Error ? e.message : String(e)}`);\n }\n const scale = opts?.precision === undefined ? undefined : 10 ** opts.precision;\n const suffix = opts?.suffix ?? display;\n const accepts: Record<string, UnitEntry> = { [suffix]: 1 };\n for (const name of Object.keys(system.units)) {\n const other = unitScale(system, name);\n // A number typed in `name` reaches display units through base:\n // `(n * factor + offset - self.offset) / self.factor`.\n const factor = other.factor / self.factor;\n const offset = (other.offset - self.offset) / self.factor;\n accepts[name] = offset === 0 ? factor : { factor, offset };\n }\n const toDisplay = (stored: number) => {\n const shown = (stored - self.offset) / self.factor;\n return scale === undefined ? shown : Math.round(shown * scale) / scale;\n };\n return {\n toDisplay,\n fromDisplay: (shown) => shown * self.factor + self.offset,\n suffix,\n accepts,\n format: (stored) =>\n `${formatUnit(stored, display, system, {\n precision: opts?.precision ?? 2,\n suffix: false,\n })}${suffix}`,\n };\n}\n\n/** A numeric pref, optionally bounded and stepped, and optionally stored in a\n * different unit from the one shown. */\nexport interface ToolPrefNumber extends ToolPrefBase<'number', number> {\n min?: number;\n max?: number;\n step?: number;\n control?: ToolPrefNumberControl;\n /** How the value shows, speaks and reads back when typed — `compact()`\n * reads `2.00M`. Presentation only: the stored value stays a number. */\n display?: Display;\n unit?: ToolPrefNumberUnit;\n /** Which end of a slider stands for infinity: the value there is ±Infinity. */\n endless?: 'min' | 'max' | 'both';\n /** The word infinity shows as — `'never'`, `'uncapped'`. Default `∞`. */\n infinity?: InfinityText;\n}\n/**\n * Stored-value bridge for a boolean leaf whose field is not a boolean — the\n * flag counterpart of {@link ToolPrefEnumEncoding}. `TextStyle.fontStyle` is\n * the case: it stores `'italic'`, and the control is an Italic toggle.\n */\nexport interface ToolPrefBooleanEncoding {\n /** Whether `stored` reads as on. */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => boolean;\n /** What to store for `on`. `undefined` removes the field. */\n write: (on: boolean, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** An on/off pref. */\nexport interface ToolPrefBoolean extends ToolPrefBase<'boolean', boolean> {\n control?: ToolPrefBooleanControl;\n encoding?: ToolPrefBooleanEncoding;\n}\n/** A free-text pref. */\nexport interface ToolPrefString extends ToolPrefBase<'string', string> {\n control?: ToolPrefStringControl;\n}\n/**\n * Stored-value bridge for an enum leaf whose value is not the option string —\n * the counterpart of {@link ToolPrefNumberUnit}, which does the same for a\n * number stored in a canonical unit.\n *\n * A dash array is the case that needs it: `Stroke.dash` stores lengths, and\n * the thing a person chooses is a style. The presets scale by the stroke's\n * width, so both directions are given the object's other fields — a style is\n * meaningless without the width it is a multiple of.\n */\nexport interface ToolPrefEnumEncoding<T extends string = string> {\n /**\n * The option `stored` reads as, or `undefined` for none — which a UI shows\n * the way it shows a mixed selection, by selecting nothing.\n *\n * `siblings` is the object the leaf is a field of, or `undefined` when the\n * node does not hold that object (and for a top-level leaf, which has none).\n */\n read: (stored: unknown, siblings: Record<string, unknown> | undefined) => T | undefined;\n /** What to store for `option`. `undefined` removes the field. */\n write: (option: T, siblings: Record<string, unknown> | undefined) => unknown;\n}\n\n/** A pref with a fixed set of labeled choices. `default` is `undefined` only\n * for a {@link ToolPrefEnum.clearable} leaf, whose absence is a value. */\nexport interface ToolPrefEnum<T extends string = string>\n extends ToolPrefBase<'enum', T | undefined> {\n /**\n * The field may hold none of the options, and that absence is a state of\n * its own rather than a missing value — a script that is neither super nor\n * sub. A toggle control then lets the chosen segment be clicked off, which\n * removes the field.\n */\n clearable?: boolean;\n /** `short` holds shorter forms of `label`, longest first, for a segmented\n * control too narrow for the full one — down to a capital or two. `icon`\n * names a glyph in the host UI's set (weasel-ui resolves it against\n * `ICON_PATHS`), drawn in place of any text form where it resolves. It is\n * a plain string because core ships no icon set and cannot depend on one.\n * The full `label` stays the accessible name, so\n * neither the abbreviation nor the glyph becomes the only thing naming\n * the option.\n *\n * `disabled` marks an option a control reports but cannot author — the\n * value a stored form reads as when it matches nothing offered. Dropping it\n * from the list instead would leave the control selecting nothing and\n * claiming the field is unset. */\n options: readonly {\n value: T;\n label: string;\n short?: readonly string[];\n icon?: string;\n disabled?: boolean;\n }[];\n control?: ToolPrefEnumControl;\n encoding?: ToolPrefEnumEncoding<T>;\n}\n\n/** A single color, stored as a hex string. For a value that may also be a\n * gradient or a pattern, use {@link ToolPrefPaint} instead. */\nexport interface ToolPrefColor extends ToolPrefBase<'color', string> {\n /** Value is `#rrggbb`, or `#rrggbbaa` when `alpha` is set (UIs then\n * offer an opacity control). */\n alpha?: boolean;\n}\n\n/**\n * Open leaf: any node with a `kind` outside the built-ins. Schema-driven\n * UIs (weasel-ui `PrefsForm` / `SelectionPanel`) dispatch it to an\n * app-supplied renderer. Deliberately NOT index-signatured so concrete\n * app interfaces stay assignable. Mirrors weasel-ui's `PrefCustom`.\n */\nexport type ToolPrefCustom = ToolPrefBase<string, unknown>;\n\n/**\n * A whole `FillStyle`, not a color inside one. Use it wherever the value is\n * the tagged paint union — a solid color, a pattern, a gradient — rather\n * than a hex string.\n *\n * Addressing `…fill.color` instead reads `undefined` off a gradient (so the\n * control shows its default and claims the text is black) and writes a\n * hybrid `{ fill: 'gradient', stops, color }` that the renderer's structural\n * `'color' in paint` checks then paint flat solid. The union has to be\n * edited as a union.\n */\nexport interface ToolPrefPaint extends ToolPrefBase<'paint', unknown> {\n /** Offer an opacity control alongside the color. */\n alpha?: boolean;\n}\n\n/**\n * A leaf whose value is one object, with its own fields hanging off it.\n *\n * A compound value — a stroke, a shadow, a pattern spec — could be described\n * as several sibling leaves addressing into it (`data.stroke.width`,\n * `data.stroke.cap`). It shouldn't be: each control would then write one field\n * of a value it can only half see, and writing into something that is not an\n * object yet corrupts it. Here the fields are `children` of one leaf, and\n * every edit commits the parent object whole.\n *\n * `children` paths are relative to the object. They are ordinary leaves, so a\n * field that is itself a union (a stroke's `paint`) declares the kind that\n * edits that union. A child may also be a {@link ToolPrefGroup}, which\n * organises the fields under a heading without contributing to the path —\n * the same rule group keys follow at the top level. A `TextStyle` needs it:\n * its character and paragraph fields belong to one value but read as two\n * lists.\n */\nexport interface ToolPrefObject extends ToolPrefBase<'object', unknown> {\n children: Record<string, ToolPrefLeaf | ToolPrefGroup>;\n /**\n * Lift a non-object value into the object form, for a consumer field that\n * may also be held as a scalar. Called before a child edit is applied;\n * without it a scalar-valued leaf shows its children empty and refuses the\n * edit.\n */\n fromScalar?: (value: unknown) => Record<string, unknown>;\n}\n\n/** One built-in pref leaf. `ToolPrefLeaf` widens this to include\n * app-defined kinds. */\nexport type ToolPref =\n | ToolPrefNumber\n | ToolPrefBoolean\n | ToolPrefString\n | ToolPrefEnum\n | ToolPrefColor\n | ToolPrefPaint\n | ToolPrefObject;\n\n// Compile-time tie: every built-in leaf kind must appear in ToolPrefKind\n// and vice versa (ToolPrefBase's K is open for ToolPrefCustom's sake, so\n// the union no longer enforces it).\ntype _BuiltinKindsExact = [ToolPref['kind']] extends [ToolPrefKind]\n ? [ToolPrefKind] extends [ToolPref['kind']] ? true : never\n : never;\nconst _builtinKindsExact: _BuiltinKindsExact = true;\nvoid _builtinKindsExact;\n\n/**\n * The built-in kinds, as a table. A kind added to {@link ToolPrefKind} is a\n * compile error here, and from here it is one in every renderer's `never`\n * guard — the only thing standing between a new kind and rendering as\n * nothing in four places at once.\n */\nexport const TOOL_PREF_KINDS: Record<ToolPrefKind, true> = {\n number: true,\n boolean: true,\n string: true,\n enum: true,\n color: true,\n paint: true,\n object: true,\n};\n\n/**\n * Narrows a leaf to the built-in union, so a renderer's switch discriminates\n * on {@link ToolPrefKind} instead of the open `string` that\n * {@link ToolPrefCustom} widens `kind` to. An app-defined kind answers false\n * and belongs to the renderer's custom-renderer path.\n */\nexport function isBuiltinToolPref(leaf: ToolPrefLeaf): leaf is ToolPref {\n return Object.hasOwn(TOOL_PREF_KINDS, leaf.kind);\n}\n\n/** Built-in or app-defined leaf. */\nexport type ToolPrefLeaf = ToolPref | ToolPrefCustom;\n\n/** Nestable group: branch nodes a tool can use to organize its prefs. */\nexport interface ToolPrefGroup {\n /** Heading for the group's rows. **Empty means no heading** — for a group\n * that exists to organise, not to name: one whose children are themselves\n * groups carrying the labels a reader needs. Give it a name whenever the\n * name is the referent (a `Border` group over `Top` / `Right` / `Bottom`\n * reads as nothing without it). */\n name: string;\n description?: string;\n children: Record<string, ToolPrefLeaf | ToolPrefGroup>;\n}\n"],"mappings":";;AAiFA,SAAgBA,EACd,GACA,GACA,GACoB;CACpB,IAAIC;CACJ,IAAI;EACF,IAAOC,EAAUC,GAAQC,CAAO;CAClC,SAAS,GAAG;EACV,MAAU,MAAM,aAAa,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG;CAC3E;CACA,IAAMC,IAAQC,GAAM,cAAc,KAAA,IAAY,KAAA,IAAY,MAAMA,EAAK,WAC/DC,IAASD,GAAM,UAAUF,GACzBI,IAAqC,GAAGD,IAAS,EAAE;CACzD,KAAK,IAAME,KAAQ,OAAO,KAAKN,EAAO,KAAK,GAAG;EAC5C,IAAMO,IAAQR,EAAUC,GAAQM,CAAI,GAG9BE,IAASD,EAAM,SAAST,EAAK,QAC7BW,KAAUF,EAAM,SAAST,EAAK,UAAUA,EAAK;EACnD,EAAQQ,KAAQG,MAAW,IAAID,IAAS;GAAE;GAAQ;EAAO;CAC3D;CAKA,OAAO;EACL,YALiB,MAAmB;GACpC,IAAME,KAASC,IAASb,EAAK,UAAUA,EAAK;GAC5C,OAAOI,MAAU,KAAA,IAAYQ,IAAQ,KAAK,MAAMA,IAAQR,CAAK,IAAIA;EACnE;EAGE,cAAc,MAAUQ,IAAQZ,EAAK,SAASA,EAAK;EACnD;EACA;EACA,SAAS,MACP,GAAGc,EAAWD,GAAQV,GAASD,GAAQ;GACrC,WAAWG,GAAM,aAAa;GAC9B,QAAQ;EACV,CAAC,IAAIC;CACT;AACF;AAwLA,IAAaS,IAA8C;CACzD,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,MAAM;CACN,OAAO;CACP,OAAO;CACP,QAAQ;AACV;AAQA,SAAgBC,EAAkB,GAAsC;CACtE,OAAO,OAAO,OAAOD,GAAiBE,EAAK,IAAI;AACjD"}
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Domain-agnostic 2D scene graph primitives for React: viewport math, drag/resize/insert/clone interactions, layered canvas rendering.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "orochi235",
|
|
@@ -85,21 +85,22 @@
|
|
|
85
85
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
86
86
|
},
|
|
87
87
|
"peerDependencies": {
|
|
88
|
-
"@weasel-js/font": "1.
|
|
88
|
+
"@weasel-js/font": "1.8.0",
|
|
89
89
|
"react": ">=18"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@
|
|
93
|
-
"@weasel-js/
|
|
94
|
-
"@weasel-js/
|
|
95
|
-
"@weasel-js/
|
|
96
|
-
"@weasel-js/
|
|
97
|
-
"@weasel-js/
|
|
98
|
-
"@weasel-js/
|
|
99
|
-
"@weasel-js/
|
|
100
|
-
"@weasel-js/
|
|
101
|
-
"@weasel-js/
|
|
102
|
-
"@weasel-js/
|
|
92
|
+
"@msb235/blits": "0.4.0",
|
|
93
|
+
"@weasel-js/cursor": "1.8.0",
|
|
94
|
+
"@weasel-js/geom": "1.8.0",
|
|
95
|
+
"@weasel-js/gestures": "1.8.0",
|
|
96
|
+
"@weasel-js/history": "1.8.0",
|
|
97
|
+
"@weasel-js/modes": "1.8.0",
|
|
98
|
+
"@weasel-js/quantity": "1.8.0",
|
|
99
|
+
"@weasel-js/paint": "1.8.0",
|
|
100
|
+
"@weasel-js/react": "1.8.0",
|
|
101
|
+
"@weasel-js/registry": "1.8.0",
|
|
102
|
+
"@weasel-js/routing": "1.8.0",
|
|
103
|
+
"@weasel-js/text": "1.8.0",
|
|
103
104
|
"earcut": "3.2.3",
|
|
104
105
|
"polygon-clipping": "^0.15.7"
|
|
105
106
|
},
|
|
@@ -117,7 +118,7 @@
|
|
|
117
118
|
"2d"
|
|
118
119
|
],
|
|
119
120
|
"devDependencies": {
|
|
120
|
-
"@weasel-js/modes": "1.
|
|
121
|
-
"@weasel-js/theme": "1.
|
|
121
|
+
"@weasel-js/modes": "1.8.0",
|
|
122
|
+
"@weasel-js/theme": "1.8.0"
|
|
122
123
|
}
|
|
123
124
|
}
|