@motionscript/ui 0.1.0-alpha.0 → 0.1.0-alpha.3

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 (46) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/browser/chunks/chunk-SFBJ6J3M.js +2 -0
  3. package/dist/browser/chunks/chunk-SFBJ6J3M.js.map +7 -0
  4. package/dist/browser/index.js +1 -1
  5. package/dist/browser/index.js.map +3 -3
  6. package/dist/browser/kit.js +1 -1
  7. package/dist/browser/manifest.json +2 -2
  8. package/dist/button/button.d.ts +6 -4
  9. package/dist/button/button.d.ts.map +1 -1
  10. package/dist/button/button.js +10 -10
  11. package/dist/button/button.js.map +1 -1
  12. package/dist/cursor/cursor.d.ts +1 -1
  13. package/dist/cursor/cursor.d.ts.map +1 -1
  14. package/dist/cursor/cursor.js +1 -1
  15. package/dist/cursor/cursor.js.map +1 -1
  16. package/dist/kit/control-icons.d.ts +1 -1
  17. package/dist/kit/control-icons.d.ts.map +1 -1
  18. package/dist/kit/control-icons.js +1 -1
  19. package/dist/kit/control-icons.js.map +1 -1
  20. package/dist/kit/control-node.d.ts +1 -1
  21. package/dist/kit/control-node.d.ts.map +1 -1
  22. package/dist/kit/control-node.js +1 -1
  23. package/dist/kit/control-node.js.map +1 -1
  24. package/dist/kit/cursor-outline.d.ts +1 -1
  25. package/dist/kit/cursor-outline.d.ts.map +1 -1
  26. package/dist/kit/cursor-outline.js +1 -1
  27. package/dist/kit/cursor-outline.js.map +1 -1
  28. package/dist/nodes.d.ts +1 -1
  29. package/dist/switch/switch.d.ts +1 -1
  30. package/dist/switch/switch.d.ts.map +1 -1
  31. package/dist/switch/switch.js +2 -2
  32. package/dist/switch/switch.js.map +1 -1
  33. package/dist/window/window.d.ts +1 -1
  34. package/dist/window/window.d.ts.map +1 -1
  35. package/dist/window/window.js +1 -1
  36. package/dist/window/window.js.map +1 -1
  37. package/package.json +4 -3
  38. package/src/button/button.ts +15 -12
  39. package/src/cursor/cursor.ts +1 -1
  40. package/src/kit/control-icons.ts +1 -1
  41. package/src/kit/control-node.ts +1 -1
  42. package/src/kit/cursor-outline.ts +1 -1
  43. package/src/switch/switch.ts +2 -2
  44. package/src/window/window.ts +1 -1
  45. package/dist/browser/chunks/chunk-W7G2N4A4.js +0 -2
  46. package/dist/browser/chunks/chunk-W7G2N4A4.js.map +0 -7
@@ -4,10 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { command, driveCommand, easeInOut, node, Graphics2D, property, } from "@motionscript/core";
7
+ import { clamp, command, driveCommand, node, Graphics2D, property, } from "@motionscript/sdk";
8
8
  import { CONTROL_ICONS, controlIconPixels, DEFAULT_CONTROL_ICON, } from "../kit/control-icons.js";
9
9
  import { buttonLook, CONTROL_STYLES, DEFAULT_CONTROL_STYLE, mixHex, readableInk, } from "../kit/control-style.js";
10
- import { pathOps } from "@motionscript/core";
10
+ import { pathOps } from "@motionscript/sdk";
11
11
  import { pressDepth } from "../kit/press.js";
12
12
  import { ControlNode } from "../kit/control-node.js";
13
13
  /**
@@ -47,20 +47,20 @@ let Button = class Button extends ControlNode {
47
47
  return false;
48
48
  }
49
49
  /**
50
- * Press and release the button — a pulse on `press`, not a state change, so
51
- * a document that only ever presses never leaves the button stuck down.
50
+ * Press and release the button: `press` climbs from the whole number it
51
+ * starts at to the next, and {@link pressDepth} draws that as one press. The
52
+ * phase only climbs, as `Cursor.click` writes it, so the row never undoes
53
+ * the count an earlier press left.
52
54
  *
53
55
  * Named `pulse` and published as `press` to avoid shadowing the `press` prop
54
56
  * this drives. Same split `Code.erase` makes to avoid shadowing `Node.remove`.
55
57
  */
56
58
  pulse(args) {
57
59
  const duration = args.duration && args.duration > 0 ? args.duration : this.pressDuration;
58
- const easing = args.easing ?? easeInOut();
59
- const DOWN = 0.35;
60
- return driveCommand(duration, (t) => {
61
- const phase = t < DOWN ? easing(t / DOWN) : 1 - easing((t - DOWN) / (1 - DOWN));
62
- this.set({ press: phase });
63
- });
60
+ const base = Math.floor(this.press);
61
+ return driveCommand(duration,
62
+ // Clamped so an overshooting easing cannot carry the phase into a second press.
63
+ (phase) => this.set({ press: base + clamp(phase, 0, 1) }), args.easing);
64
64
  }
65
65
  /** Every measurement the drawing needs, resolved once — see {@link Switch.metrics}. */
66
66
  metrics() {
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/button/button.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n command,\n driveCommand,\n easeInOut,\n node,\n type Command,\n type CommandArgs,\n Graphics2D,\n property,\n type Node,\n type NodeConfig,\n type RenderContext2D,\n} from \"@motionscript/core\"\n\nimport {\n CONTROL_ICONS,\n controlIconPixels,\n DEFAULT_CONTROL_ICON,\n type ControlIcon,\n} from \"../kit/control-icons\"\nimport {\n buttonLook,\n CONTROL_STYLES,\n DEFAULT_CONTROL_STYLE,\n mixHex,\n readableInk,\n type ControlStyle,\n} from \"../kit/control-style\"\nimport { pathOps } from \"@motionscript/core\"\nimport { pressDepth } from \"../kit/press\"\nimport { ControlNode, type ControlNodeProps } from \"../kit/control-node\"\n\n/** A button's own props, over the box and the sound schedule every control has. */\nexport interface ButtonProps extends ControlNodeProps {\n /** Which design language to draw in — see {@link ControlStyle}. */\n style: ControlStyle\n /** The words on it. */\n label: string\n /** The face they are set in. Empty falls back to the built-in. */\n fontFamily: string\n /** The button's fill, and the colour the label is chosen to read against. */\n accent: string\n /** A mark before the label. `none` draws none and takes no room. */\n icon: ControlIcon\n /**\n * How many presses deep the chain is — a **monotonic phase**, not a depth.\n *\n * The one prop the Press command animates, and it climbs by exactly one per\n * press rather than going down and coming back: a tween can only run one way,\n * and a press is two. {@link pressDepth} turns the fractional part into the\n * down-and-up envelope, which is zero at both whole numbers — so a finished\n * press leaves the button at rest by arithmetic rather than by a reset the\n * builder would have to remember to write. See `nodes/ui-kit/commands.ts`.\n */\n press: number\n /**\n * The label's ink and the corner radius — honoured **only** in the `custom`\n * style, for the reason {@link SwitchProps.track} states. Empty ink means\n * \"work it out\", which is what every named style does.\n */\n ink: string\n radius: number\n /** Seconds a press runs for when its row states no duration. */\n pressDuration: number\n}\n\n/**\n * A **button**, as a node.\n *\n * The Switch's sibling and the other half of \"a video about an interface\": the\n * thing the cursor moves to before the switch flips. Same bargain — one style\n * question rather than thirty controls, an accent, a mark — and one difference\n * that runs all the way through it: a button's whole state is *transient*. A\n * switch is on or off between commands; a button is at rest, and a Press is a\n * moment rather than a change.\n *\n * ## The label's colour is not a control\n *\n * It is computed from the fill ({@link readableInk}), because it is not a\n * decision — it is a consequence, and the only decisions available are the\n * correct one and a mistake. The `custom` style exposes it for the case where\n * the fill is an image or the author is matching a real product's off-spec\n * button; every other style works it out and is right.\n *\n * ## The label is placed, not measured\n *\n * A `Graphics2D.text` hands back no metrics, so the icon-plus-label pair is\n * centred against an **estimate** of the label's width — the same trade the\n * grapher's axis labels already make (see `labelWidthEm`), and acceptable for\n * the same reason: being a few pixels off centre on a control the author is\n * sizing by eye is a smaller error than the alternatives, which are measuring\n * text in a package with no DOM or composing the button out of real nodes and\n * giving up the press animation.\n */\n@node({\n key: \"button\",\n parentKey: \"node\",\n forkable: true,\n layout: {\n children: \"freeform\",\n defaultWidthMode: \"fixed\",\n defaultHeightMode: \"fixed\",\n acceptsChildren: false,\n },\n seed: {\n width: 282,\n height: 88,\n },\n})\nexport class Button extends ControlNode<ButtonProps> {\n @property({ default: DEFAULT_CONTROL_STYLE, kind: \"enum\", options: CONTROL_STYLES })\n declare style: ControlStyle\n @property({ default: \"Button\" }) declare label: string\n @property({ default: \"\" }) declare fontFamily: string\n @property({ default: \"#007aff\", kind: \"color\" }) declare accent: string\n @property({ default: DEFAULT_CONTROL_ICON, kind: \"enum\", options: CONTROL_ICONS })\n declare icon: ControlIcon\n @property({ default: 0, min: 0 }) declare press: number\n @property({ default: \"\", kind: \"color\" }) declare ink: string\n @property({ default: 0.48, min: 0, max: 1, step: 0.01 }) declare radius: number\n @property({ default: 0.24, min: 0, step: 0.05, unit: \"s\" })\n declare pressDuration: number\n\n constructor(props: NodeConfig<Button, ButtonProps>) {\n super(props)\n }\n\n /** A button is a control, not a container — its label and mark are its own. */\n protected override acceptsChild(_child: Node): boolean {\n return false\n }\n\n /**\n * Press and release the button — a pulse on `press`, not a state change, so\n * a document that only ever presses never leaves the button stuck down.\n *\n * Named `pulse` and published as `press` to avoid shadowing the `press` prop\n * this drives. Same split `Code.erase` makes to avoid shadowing `Node.remove`.\n */\n @command({ key: \"press\" })\n pulse(args: CommandArgs<Record<string, never>> & { duration?: number }): Command<ButtonProps> {\n const duration = args.duration && args.duration > 0 ? args.duration : this.pressDuration\n const easing = args.easing ?? easeInOut()\n const DOWN = 0.35\n return driveCommand(duration, (t) => {\n const phase = t < DOWN ? easing(t / DOWN) : 1 - easing((t - DOWN) / (1 - DOWN))\n this.set({ press: phase } as Partial<ButtonProps>)\n }) as Command<ButtonProps>\n }\n\n /** Every measurement the drawing needs, resolved once — see {@link Switch.metrics}. */\n private metrics() {\n const bounds = this.layoutBounds\n const width = bounds?.width ?? 0\n const height = bounds?.height ?? 0\n const look = buttonLook(this.style)\n const custom = this.style === \"custom\"\n const depth = pressDepth(this.press)\n\n // The pressed fill, which the ink is then chosen against rather than against\n // the resting one: a button dark enough at rest to want white text is darker\n // still while held, so deriving from the resting colour would be deriving\n // from a frame that isn't on screen.\n const fill = mixHex(this.accent, \"#000000\", look.pressDim * depth)\n const fontSize = height * look.fontSize\n\n return {\n width,\n height,\n look,\n depth,\n fill,\n fontSize,\n scale: 1 - look.pressScale * depth,\n radius: (height / 2) * (custom ? this.radius : look.radius),\n ink: custom && this.ink !== \"\" ? this.ink : readableInk(fill),\n iconSize: this.icon === \"none\" ? 0 : fontSize * look.iconSize,\n gap: this.icon === \"none\" ? 0 : fontSize * look.iconGap,\n }\n }\n\n protected override renderSelf(ctx: RenderContext2D): void {\n const m = this.metrics()\n if (m.width <= 0 || m.height <= 0) return\n\n // The whole drawing shrinks about the node's own centre rather than each\n // part about its own bounding box, which is why the pivot is stated: three\n // separate draws each scaled about themselves would slide apart under the\n // press instead of settling together.\n const pivot = { x: 0, y: 0 }\n\n const face = new Graphics2D().rect({\n x: 0,\n y: 0,\n width: m.width,\n height: m.height,\n cornerRadius: m.radius,\n })\n face.fill(m.fill)\n if (m.look.outline > 0) {\n face.stroke({\n weight: m.height * m.look.outline,\n // A rim a shade darker than the face, which is what a hairline border\n // is on every filled control that has one — a *colour* here would be a\n // second accent nobody asked for.\n fill: mixHex(m.fill, \"#000000\", 0.18),\n align: \"inside\",\n })\n }\n if (m.look.shadow > 0) {\n face.shadow({\n blur: m.height * m.look.shadow,\n offset: { x: 0, y: -m.height * m.look.shadow * 0.3 },\n fill: \"rgba(0, 0, 0, 0.18)\",\n })\n }\n ctx.draw(face.scale(m.scale, pivot))\n\n // Where the icon-and-label pair sits. The pair is centred as a unit, so the\n // label shifts right by half the room the icon takes and the icon sits in\n // the gap that opens on the left.\n const labelWidth = estimateWidth(this.label, m.fontSize)\n const block = m.iconSize + m.gap\n const left = -(labelWidth + block) / 2\n\n if (m.iconSize > 0) {\n this.drawIcon(ctx, left + m.iconSize / 2, m.iconSize, m.ink, m.scale)\n }\n\n if (this.label !== \"\") {\n ctx.draw(\n new Graphics2D()\n .text({\n text: this.label,\n x: left + block + labelWidth / 2,\n // Centred on the baseline's own box rather than nudged: the text\n // descriptor centres its box on the point it is given, which is\n // already the vertical middle of the node.\n y: 0,\n width: labelWidth,\n fontSize: m.fontSize,\n // Already resolved: the props mapper fills an empty family in from\n // the host (see `nodes/kit/text-defaults`), so the node never has to\n // know which typeface this application ships.\n fontFamily: this.fontFamily,\n fontWeight: m.look.fontWeight,\n letterSpacing: m.fontSize * m.look.letterSpacing,\n textAlign: \"center\",\n wrap: false,\n })\n .fill(m.ink)\n .scale(m.scale, pivot)\n )\n }\n }\n\n /** The leading mark — see {@link Switch.drawIcon}, which this mirrors. */\n private drawIcon(\n ctx: RenderContext2D,\n x: number,\n size: number,\n color: string,\n scale: number\n ): void {\n const art = controlIconPixels(this.icon, size)\n const shift = (p: { x: number; y: number }) => ({ x: p.x + x, y: p.y })\n const pivot = { x: 0, y: 0 }\n\n if (art.fills.length > 0) {\n ctx.draw(\n new Graphics2D()\n .path({ data: pathOps.anchorCommands(art.fills, shift) })\n .fill(color)\n .scale(scale, pivot)\n )\n }\n if (art.strokes.length > 0) {\n ctx.draw(\n new Graphics2D()\n .path({ data: pathOps.anchorCommands(art.strokes, shift) })\n .stroke({\n weight: art.weight,\n fill: color,\n cap: \"round\",\n join: \"round\",\n align: \"center\",\n })\n .scale(scale, pivot)\n )\n }\n }\n\n}\n\n/**\n * How wide `label` comes out, in pixels, near enough to centre it by.\n *\n * A per-character average rather than a shaping pass, which this package has no\n * way to run — see the class note. `0.55em` is the mean advance of a UI sans at\n * mixed case; the error on a real label is a few percent, and it lands as a few\n * pixels of off-centre on a control whose text is centred inside its own box\n * anyway.\n *\n * The whole label rather than its longest line, because a button's label does\n * not wrap (`wrap: false` above) — a caption that needs two lines is a caption,\n * not a button.\n */\nfunction estimateWidth(label: string, fontSize: number): number {\n return label.length * fontSize * 0.55\n}\n"]}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/button/button.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n clamp,\n command,\n driveCommand,\n node,\n type Command,\n type CommandArgs,\n Graphics2D,\n property,\n type Node,\n type NodeConfig,\n type RenderContext2D,\n} from \"@motionscript/sdk\"\n\nimport {\n CONTROL_ICONS,\n controlIconPixels,\n DEFAULT_CONTROL_ICON,\n type ControlIcon,\n} from \"../kit/control-icons\"\nimport {\n buttonLook,\n CONTROL_STYLES,\n DEFAULT_CONTROL_STYLE,\n mixHex,\n readableInk,\n type ControlStyle,\n} from \"../kit/control-style\"\nimport { pathOps } from \"@motionscript/sdk\"\nimport { pressDepth } from \"../kit/press\"\nimport { ControlNode, type ControlNodeProps } from \"../kit/control-node\"\n\n/** A button's own props, over the box and the sound schedule every control has. */\nexport interface ButtonProps extends ControlNodeProps {\n /** Which design language to draw in — see {@link ControlStyle}. */\n style: ControlStyle\n /** The words on it. */\n label: string\n /** The face they are set in. Empty falls back to the built-in. */\n fontFamily: string\n /** The button's fill, and the colour the label is chosen to read against. */\n accent: string\n /** A mark before the label. `none` draws none and takes no room. */\n icon: ControlIcon\n /**\n * How many presses deep the chain is — a **monotonic phase**, not a depth.\n *\n * The one prop the Press command animates, and it climbs by exactly one per\n * press rather than going down and coming back: a tween can only run one way,\n * and a press is two. {@link pressDepth} turns the fractional part into the\n * down-and-up envelope, which is zero at both whole numbers — so a finished\n * press leaves the button at rest by arithmetic rather than by a reset the\n * builder would have to remember to write. See {@link Button.pulse}.\n */\n press: number\n /**\n * The label's ink and the corner radius — honoured **only** in the `custom`\n * style, for the reason {@link SwitchProps.track} states. Empty ink means\n * \"work it out\", which is what every named style does.\n */\n ink: string\n radius: number\n /** Seconds a press runs for when its row states no duration. */\n pressDuration: number\n}\n\n/**\n * A **button**, as a node.\n *\n * The Switch's sibling and the other half of \"a video about an interface\": the\n * thing the cursor moves to before the switch flips. Same bargain — one style\n * question rather than thirty controls, an accent, a mark — and one difference\n * that runs all the way through it: a button's whole state is *transient*. A\n * switch is on or off between commands; a button is at rest, and a Press is a\n * moment rather than a change.\n *\n * ## The label's colour is not a control\n *\n * It is computed from the fill ({@link readableInk}), because it is not a\n * decision — it is a consequence, and the only decisions available are the\n * correct one and a mistake. The `custom` style exposes it for the case where\n * the fill is an image or the author is matching a real product's off-spec\n * button; every other style works it out and is right.\n *\n * ## The label is placed, not measured\n *\n * A `Graphics2D.text` hands back no metrics, so the icon-plus-label pair is\n * centred against an **estimate** of the label's width — the same trade the\n * grapher's axis labels already make (see `labelWidthEm`), and acceptable for\n * the same reason: being a few pixels off centre on a control the author is\n * sizing by eye is a smaller error than the alternatives, which are measuring\n * text in a package with no DOM or composing the button out of real nodes and\n * giving up the press animation.\n */\n@node({\n key: \"button\",\n parentKey: \"node\",\n forkable: true,\n layout: {\n children: \"freeform\",\n defaultWidthMode: \"fixed\",\n defaultHeightMode: \"fixed\",\n acceptsChildren: false,\n },\n seed: {\n width: 282,\n height: 88,\n },\n})\nexport class Button extends ControlNode<ButtonProps> {\n @property({ default: DEFAULT_CONTROL_STYLE, kind: \"enum\", options: CONTROL_STYLES })\n declare style: ControlStyle\n @property({ default: \"Button\" }) declare label: string\n @property({ default: \"\" }) declare fontFamily: string\n @property({ default: \"#007aff\", kind: \"color\" }) declare accent: string\n @property({ default: DEFAULT_CONTROL_ICON, kind: \"enum\", options: CONTROL_ICONS })\n declare icon: ControlIcon\n @property({ default: 0, min: 0 }) declare press: number\n @property({ default: \"\", kind: \"color\" }) declare ink: string\n @property({ default: 0.48, min: 0, max: 1, step: 0.01 }) declare radius: number\n @property({ default: 0.24, min: 0, step: 0.05, unit: \"s\" })\n declare pressDuration: number\n\n constructor(props: NodeConfig<Button, ButtonProps>) {\n super(props)\n }\n\n /** A button is a control, not a container — its label and mark are its own. */\n protected override acceptsChild(_child: Node): boolean {\n return false\n }\n\n /**\n * Press and release the button: `press` climbs from the whole number it\n * starts at to the next, and {@link pressDepth} draws that as one press. The\n * phase only climbs, as `Cursor.click` writes it, so the row never undoes\n * the count an earlier press left.\n *\n * Named `pulse` and published as `press` to avoid shadowing the `press` prop\n * this drives. Same split `Code.erase` makes to avoid shadowing `Node.remove`.\n */\n @command({ key: \"press\" })\n pulse(args: CommandArgs<Record<string, never>> & { duration?: number }): Command<ButtonProps> {\n const duration = args.duration && args.duration > 0 ? args.duration : this.pressDuration\n const base = Math.floor(this.press)\n return driveCommand(\n duration,\n // Clamped so an overshooting easing cannot carry the phase into a second press.\n (phase) => this.set({ press: base + clamp(phase, 0, 1) } as Partial<ButtonProps>),\n args.easing\n ) as Command<ButtonProps>\n }\n\n /** Every measurement the drawing needs, resolved once — see {@link Switch.metrics}. */\n private metrics() {\n const bounds = this.layoutBounds\n const width = bounds?.width ?? 0\n const height = bounds?.height ?? 0\n const look = buttonLook(this.style)\n const custom = this.style === \"custom\"\n const depth = pressDepth(this.press)\n\n // The pressed fill, which the ink is then chosen against rather than against\n // the resting one: a button dark enough at rest to want white text is darker\n // still while held, so deriving from the resting colour would be deriving\n // from a frame that isn't on screen.\n const fill = mixHex(this.accent, \"#000000\", look.pressDim * depth)\n const fontSize = height * look.fontSize\n\n return {\n width,\n height,\n look,\n depth,\n fill,\n fontSize,\n scale: 1 - look.pressScale * depth,\n radius: (height / 2) * (custom ? this.radius : look.radius),\n ink: custom && this.ink !== \"\" ? this.ink : readableInk(fill),\n iconSize: this.icon === \"none\" ? 0 : fontSize * look.iconSize,\n gap: this.icon === \"none\" ? 0 : fontSize * look.iconGap,\n }\n }\n\n protected override renderSelf(ctx: RenderContext2D): void {\n const m = this.metrics()\n if (m.width <= 0 || m.height <= 0) return\n\n // The whole drawing shrinks about the node's own centre rather than each\n // part about its own bounding box, which is why the pivot is stated: three\n // separate draws each scaled about themselves would slide apart under the\n // press instead of settling together.\n const pivot = { x: 0, y: 0 }\n\n const face = new Graphics2D().rect({\n x: 0,\n y: 0,\n width: m.width,\n height: m.height,\n cornerRadius: m.radius,\n })\n face.fill(m.fill)\n if (m.look.outline > 0) {\n face.stroke({\n weight: m.height * m.look.outline,\n // A rim a shade darker than the face, which is what a hairline border\n // is on every filled control that has one — a *colour* here would be a\n // second accent nobody asked for.\n fill: mixHex(m.fill, \"#000000\", 0.18),\n align: \"inside\",\n })\n }\n if (m.look.shadow > 0) {\n face.shadow({\n blur: m.height * m.look.shadow,\n offset: { x: 0, y: -m.height * m.look.shadow * 0.3 },\n fill: \"rgba(0, 0, 0, 0.18)\",\n })\n }\n ctx.draw(face.scale(m.scale, pivot))\n\n // Where the icon-and-label pair sits. The pair is centred as a unit, so the\n // label shifts right by half the room the icon takes and the icon sits in\n // the gap that opens on the left.\n const labelWidth = estimateWidth(this.label, m.fontSize)\n const block = m.iconSize + m.gap\n const left = -(labelWidth + block) / 2\n\n if (m.iconSize > 0) {\n this.drawIcon(ctx, left + m.iconSize / 2, m.iconSize, m.ink, m.scale)\n }\n\n if (this.label !== \"\") {\n ctx.draw(\n new Graphics2D()\n .text({\n text: this.label,\n x: left + block + labelWidth / 2,\n // Centred on the baseline's own box rather than nudged: the text\n // descriptor centres its box on the point it is given, which is\n // already the vertical middle of the node.\n y: 0,\n width: labelWidth,\n fontSize: m.fontSize,\n // Already resolved: the props mapper fills an empty family in from\n // the host (see `nodes/kit/text-defaults`), so the node never has to\n // know which typeface this application ships.\n fontFamily: this.fontFamily,\n fontWeight: m.look.fontWeight,\n letterSpacing: m.fontSize * m.look.letterSpacing,\n textAlign: \"center\",\n wrap: false,\n })\n .fill(m.ink)\n .scale(m.scale, pivot)\n )\n }\n }\n\n /** The leading mark — see {@link Switch.drawIcon}, which this mirrors. */\n private drawIcon(\n ctx: RenderContext2D,\n x: number,\n size: number,\n color: string,\n scale: number\n ): void {\n const art = controlIconPixels(this.icon, size)\n const shift = (p: { x: number; y: number }) => ({ x: p.x + x, y: p.y })\n const pivot = { x: 0, y: 0 }\n\n if (art.fills.length > 0) {\n ctx.draw(\n new Graphics2D()\n .path({ data: pathOps.anchorCommands(art.fills, shift) })\n .fill(color)\n .scale(scale, pivot)\n )\n }\n if (art.strokes.length > 0) {\n ctx.draw(\n new Graphics2D()\n .path({ data: pathOps.anchorCommands(art.strokes, shift) })\n .stroke({\n weight: art.weight,\n fill: color,\n cap: \"round\",\n join: \"round\",\n align: \"center\",\n })\n .scale(scale, pivot)\n )\n }\n }\n\n}\n\n/**\n * How wide `label` comes out, in pixels, near enough to centre it by.\n *\n * A per-character average rather than a shaping pass, which this package has no\n * way to run — see the class note. `0.55em` is the mean advance of a UI sans at\n * mixed case; the error on a real label is a few percent, and it lands as a few\n * pixels of off-centre on a control whose text is centred inside its own box\n * anyway.\n *\n * The whole label rather than its longest line, because a button's label does\n * not wrap (`wrap: false` above) — a caption that needs two lines is a caption,\n * not a button.\n */\nfunction estimateWidth(label: string, fontSize: number): number {\n return label.length * fontSize * 0.55\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { Clip, type Command, type CommandArgs, Node2D, type Node2DProps, type Node, type NodeConfig, type RenderContext2D } from "@motionscript/core";
1
+ import { Clip, type Command, type CommandArgs, Node2D, type Node2DProps, type Node, type NodeConfig, type RenderContext2D } from "@motionscript/sdk";
2
2
  import { type CursorStyle, type CursorType } from "../kit/cursor-outline.js";
3
3
  import { type ClickArc } from "../kit/click-path.js";
4
4
  /** A cursor's own props, over the box every node has. */
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,IAAI,EACJ,KAAK,OAAO,EACZ,KAAK,WAAW,EAEhB,MAAM,EACN,KAAK,WAAW,EAGhB,KAAK,IAAI,EACT,KAAK,UAAU,EAGf,KAAK,eAAe,EAErB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAOL,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAGL,KAAK,QAAQ,EAEd,MAAM,mBAAmB,CAAA;AAG1B,yDAAyD;AACzD,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,oDAAoD;IACpD,MAAM,EAAE,UAAU,CAAA;IAClB,0DAA0D;IAC1D,KAAK,EAAE,WAAW,CAAA;IAClB;;;;;;;;;;OAUG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAA;CACtB;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,qBAea,MAAO,SAAQ,MAAM,CAAC,WAAW,CAAC;IAErC,MAAM,EAAE,UAAU,CAAA;IAGlB,KAAK,EAAE,WAAW,CAAA;IAEgB,KAAK,EAAE,MAAM,CAAA;IAG/C,aAAa,EAAE,MAAM,CAAA;gBAEjB,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC;IAIlD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IAeH,KAAK,CACH,IAAI,EAAE,WAAW,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9B,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GACzB,OAAO,CAAC,WAAW,CAAC;IAuBvB;;;;;;;;;;OAUG;cACgB,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAkBzD,0DAA0D;cACvC,YAAY,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO;IAItD;;;;;;;;;OASG;cACgB,QAAQ,IAAI,IAAI;IAOnC;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAwBnB,oEAAoE;IACpE,OAAO,CAAC,QAAQ;IAIhB;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM;IAQd,oEAAoE;IACpE,OAAO,CAAC,aAAa;IAOrB;;;;;;OAMG;IACH,OAAO,CAAC,OAAO;IAYf;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;CAUrB"}
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,IAAI,EACJ,KAAK,OAAO,EACZ,KAAK,WAAW,EAEhB,MAAM,EACN,KAAK,WAAW,EAGhB,KAAK,IAAI,EACT,KAAK,UAAU,EAGf,KAAK,eAAe,EAErB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAOL,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAGL,KAAK,QAAQ,EAEd,MAAM,mBAAmB,CAAA;AAG1B,yDAAyD;AACzD,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,oDAAoD;IACpD,MAAM,EAAE,UAAU,CAAA;IAClB,0DAA0D;IAC1D,KAAK,EAAE,WAAW,CAAA;IAClB;;;;;;;;;;OAUG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAA;CACtB;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,qBAea,MAAO,SAAQ,MAAM,CAAC,WAAW,CAAC;IAErC,MAAM,EAAE,UAAU,CAAA;IAGlB,KAAK,EAAE,WAAW,CAAA;IAEgB,KAAK,EAAE,MAAM,CAAA;IAG/C,aAAa,EAAE,MAAM,CAAA;gBAEjB,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC;IAIlD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IAeH,KAAK,CACH,IAAI,EAAE,WAAW,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9B,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GACzB,OAAO,CAAC,WAAW,CAAC;IAuBvB;;;;;;;;;;OAUG;cACgB,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAkBzD,0DAA0D;cACvC,YAAY,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO;IAItD;;;;;;;;;OASG;cACgB,QAAQ,IAAI,IAAI;IAOnC;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAwBnB,oEAAoE;IACpE,OAAO,CAAC,QAAQ;IAIhB;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM;IAQd,oEAAoE;IACpE,OAAO,CAAC,aAAa;IAOrB;;;;;;OAMG;IACH,OAAO,CAAC,OAAO;IAYf;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;CAUrB"}
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { command, driveCommand, easeInOut, node, Clip, Graphics2D, Node2D, pathOps, property, } from "@motionscript/core";
7
+ import { command, driveCommand, easeInOut, node, Clip, Graphics2D, Node2D, pathOps, property, } from "@motionscript/sdk";
8
8
  import { cursorArtworkPixels, cursorLook, CURSOR_STYLES, CURSOR_TYPES, DEFAULT_CURSOR_STYLE, DEFAULT_CURSOR_TYPE, } from "../kit/cursor-outline.js";
9
9
  import { arcPointAt, resolveClickArc, } from "../kit/click-path.js";
10
10
  import { pressDepth } from "../kit/press.js";
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n command,\n driveCommand,\n easeInOut,\n node,\n Clip,\n type Command,\n type CommandArgs,\n Graphics2D,\n Node2D,\n type Node2DProps,\n pathOps,\n property,\n type Node,\n type NodeConfig,\n type PathBounds,\n type PathCommand,\n type RenderContext2D,\n type VectorPath,\n} from \"@motionscript/core\"\n\nimport {\n cursorArtworkPixels,\n cursorLook,\n CURSOR_STYLES,\n CURSOR_TYPES,\n DEFAULT_CURSOR_STYLE,\n DEFAULT_CURSOR_TYPE,\n type CursorStyle,\n type CursorType,\n} from \"../kit/cursor-outline\"\nimport {\n arcPointAt,\n resolveClickArc,\n type ClickArc,\n type ClickPoint,\n} from \"../kit/click-path\"\nimport { pressDepth } from \"../kit/press\"\n\n/** A cursor's own props, over the box every node has. */\nexport interface CursorProps extends Node2DProps {\n /** Which glyph to draw — see {@link CursorType}. */\n cursor: CursorType\n /** Which look to draw it in — see {@link CursorStyle}. */\n style: CursorStyle\n /**\n * How many clicks deep the chain is — a **monotonic phase**, not a depth.\n *\n * The one prop {@link Cursor.click} animates, and it climbs by exactly one\n * per click rather than going down and coming back: a tween can only run one\n * way, and a click is two. `pressDepth` turns the fractional part into the\n * down-and-up envelope, which is zero at both whole numbers — so a finished\n * click leaves the pointer at rest by arithmetic rather than by a reset the\n * command would have to remember to write. Exactly `Button.press`, and the\n * same function drives both.\n */\n press: number\n /** Seconds a {@link Cursor.click} runs for when its row states no duration. */\n clickDuration: number\n}\n\n/** How far the glyph shrinks at the bottom of a press. */\nconst PRESS_DIP = 0.12\n/** The ring's radius at the end of a click, as a fraction of the glyph's box. */\nconst RIPPLE_REACH = 1.4\nconst RIPPLE_OPACITY = 0.5\n\n/**\n * A mouse cursor, as a node.\n *\n * The one thing a screen recording has that a motion-graphics scene doesn't:\n * something on screen standing in for the person. Every explainer that shows an\n * interface needs one, and the alternatives are all worse — a screenshot of a\n * cursor pastes in at one size, and a hand-drawn path is a shape nobody can\n * change their mind about.\n *\n * Which pointer, whose, and how far through a click it is. Where it sits and\n * how big it is are the transform every node has; the contours and both colours\n * come out of the first two (see `kit/cursor-outline`, which holds the artwork\n * and the reasoning).\n *\n * ## A `Node2D`, and a leaf\n *\n * Not a `ShapeNode`, on the reasoning `Code` records in its own changeset: the\n * paint slots a shape carries are a surface this node cannot honour. A cursor's\n * colours are not a matter of taste — the Windows arrow is white with a black\n * keyline — so an author asked to set them by hand would be re-deriving a fact\n * rather than making a choice, and a cursor with the wrong two colours is not a\n * stylized cursor, it is a mistake. Declaring `fill`/`overlay`/`stroke`/\n * `shadow` and then ignoring them was a surface a host had no way to know was\n * inert; not declaring them is one it cannot offer.\n *\n * It refuses children for the same kind of reason. Nothing goes *inside* a\n * pointer, and a drop target on one is a place to lose a node.\n *\n * ## Why it paints itself, in two passes\n *\n * The keyline and the body, in that order: the outer contour filled black, then\n * the inner one filled white over it, leaving the keyline showing as the gap\n * between them. Not a fill with a stroke round it, because a stroke's weight is\n * a pixel count and this glyph is stretched onto whatever box the node has —\n * see the module note on `kit/cursor-outline`.\n *\n * ## The hotspot is the box's top-left\n *\n * Both the click ripple and the press dip are anchored there rather than at the\n * node's centre, because that is where a pointer actually points. A dip about\n * the centre would walk the tip half a pixel down and right at the bottom of\n * every press, which reads as the cursor sliding rather than pressing.\n *\n * ## Animating one\n *\n * `cursor` and `style` are ordinary props, so a `to` command can change either.\n * Neither has a tween function, and motion-script's fallback for a value it\n * can't interpolate is to hold the old one until the command ends and then\n * snap — which is exactly right here: there is no halfway between an arrow and\n * a pointing hand, and a cursor that changes shape *at the moment it reaches\n * the link* is what the author is after. A zero-duration `to` is the instant\n * switch.\n */\n@node({\n key: \"cursor\",\n parentKey: \"node\",\n forkable: true,\n layout: {\n children: \"freeform\",\n defaultWidthMode: \"fixed\",\n defaultHeightMode: \"fixed\",\n acceptsChildren: false,\n },\n seed: {\n width: 32,\n height: 32,\n },\n})\nexport class Cursor extends Node2D<CursorProps> {\n @property({ default: DEFAULT_CURSOR_TYPE, kind: \"enum\", options: CURSOR_TYPES })\n declare cursor: CursorType\n\n @property({ default: DEFAULT_CURSOR_STYLE, kind: \"enum\", options: CURSOR_STYLES })\n declare style: CursorStyle\n\n @property({ default: 0, min: 0 }) declare press: number\n\n @property({ default: 0.5, min: 0, step: 0.05, unit: \"s\" })\n declare clickDuration: number\n\n constructor(props: NodeConfig<Cursor, CursorProps>) {\n super(props as NodeConfig<Node2D, Node2DProps>)\n }\n\n /**\n * Travel to a control, press it, and let go — the whole gesture as one row.\n *\n * **`target` is a node id, and it is resolved when the command is built.**\n * That is the point of the command: the destination and the curve to it are\n * derived from where the control *currently* is, so moving a switch on the\n * canvas re-aims the animation with nothing to re-author. A baked path is\n * correct only for the two points it was baked against, which is what made\n * this a chore worth removing. An id rather than a `key` because `NodeSpec.key`\n * is optional and never generated, so it is not a handle every node has; an\n * expression is not an option either, since a command that does not `bind`\n * refuses one outright (`SceneTimeline._assertNoExpressions`).\n *\n * Naming nothing — or naming a node absent at this moment — clicks in place,\n * which is the same answer the document's own node references give for\n * something not there. A click is a legitimate beat over a rectangle or an\n * image, so refusing would cost more than it caught.\n *\n * `activate` drives the control itself: a switch throws, a button takes a\n * press. Both are written straight to the other node, which the timeline\n * restores along with this one because it records what a command writes\n * rather than what it targets.\n */\n @command({\n args: [\n { key: \"target\", kind: \"nodeRef\" },\n {\n key: \"clickShape\",\n kind: \"arc\",\n properties: {\n bow: { kind: \"number\", min: -1, max: 1, step: 0.01 },\n lean: { kind: \"number\", min: 0, max: 1, step: 0.01 },\n },\n },\n { key: \"activate\", kind: \"boolean\", default: true },\n ],\n })\n click(\n args: CommandArgs<{\n target?: string\n clickShape?: Partial<ClickArc>\n activate?: boolean\n }> & { duration?: number },\n ): Command<CursorProps> {\n const duration = args.duration && args.duration > 0 ? args.duration : this.clickDuration\n const easing = args.easing ?? easeInOut()\n const arc = resolveClickArc(args.data?.clickShape)\n const target = this._controlNamed(args.data?.target)\n\n const from: ClickPoint = { x: this.x, y: this.y }\n const to = target ? this._reach(target) : from\n const press = Math.floor(this.press)\n const activated =\n args.data?.activate === false ? null : target && activateOf(target)\n\n return driveCommand(duration, (t) => {\n // Travel over the lead-in, then hold still while the click happens: a\n // pointer that is still moving as it presses reads as a drag.\n const travel = easing(Math.min(1, t / TRAVEL))\n const at = arcPointAt(from, to, arc, travel)\n const phase = t <= TRAVEL ? 0 : (t - TRAVEL) / (1 - TRAVEL)\n this.set({ x: at.x, y: at.y, press: press + phase } as Partial<CursorProps>)\n activated?.(phase)\n }) as unknown as Command<CursorProps>\n }\n\n /**\n * Keyline, then body — the two-tone cursor, in the style's own colours, with\n * the click ripple behind them.\n *\n * The glyph is one `Graphics2D` with two shape groups rather than two\n * submissions: `fill()` scopes to the shapes declared since the last one, so\n * the second `path()` starts a group of its own and the two paint in order.\n * The ripple is a submission of its own because it carries a group opacity,\n * and `Graphics2D.opacity` composites the whole list — chaining it would fade\n * the pointer along with the ring.\n */\n protected override renderSelf(ctx: RenderContext2D): void {\n const depth = pressDepth(this.press)\n this._drawRipple(ctx, depth)\n\n const scale = 1 - PRESS_DIP * depth\n const { keyline, body } = this.artwork(scale)\n if (keyline.length === 0) return\n const look = cursorLook(this.style)\n const centerBounds = this.centerBounds(scale)\n ctx.draw(\n new Graphics2D()\n .path({ data: keyline, centerBounds })\n .fill(look.keyline)\n .path({ data: body, centerBounds })\n .fill(look.body)\n )\n }\n\n /** Nothing goes inside a pointer — see the class note. */\n protected override acceptsChild(_child: Node): boolean {\n return false\n }\n\n /**\n * The node's laid-out rect as a clip outline, so `clip` and any backdrop\n * effect are confined to the box rather than to nothing.\n *\n * Picking needs no help here: `Node2D` already grabs on the layout box, which\n * is the answer a cursor wants. An arrow occupies about a third of its box,\n * so picking on the silhouette would mean clicking one required hitting the\n * arrow itself — which on a node whose whole job is to be small on screen\n * reads as the app ignoring you.\n */\n protected override clipSelf(): Clip {\n return new Clip().rect({\n width: this.layoutBounds.width,\n height: this.layoutBounds.height,\n })\n }\n\n /**\n * The expanding ring a click leaves, centred on the hotspot.\n *\n * Drawn from the press envelope rather than from a phase of its own, so it\n * cannot drift out of step with the dip — and so a cursor at rest draws\n * nothing at all, which is the common case on every frame.\n */\n private _drawRipple(ctx: RenderContext2D, depth: number): void {\n if (depth <= 0) return\n const { width, height } = this.layoutBounds\n const span = Math.max(width, height)\n if (span <= 0) return\n const tip = this._hotspot()\n const radius = span * RIPPLE_REACH * depth\n ctx.draw(\n new Graphics2D()\n .ellipse({\n x: tip.x,\n y: tip.y,\n width: radius * 2,\n height: radius * 2,\n })\n .stroke({\n weight: Math.max(1, span * 0.06 * (1 - depth)),\n fill: cursorLook(this.style).keyline,\n align: \"center\",\n })\n .opacity(RIPPLE_OPACITY * (1 - depth))\n )\n }\n\n /** Where the pointer points, in the node's own y-up local space. */\n private _hotspot(): ClickPoint {\n return { x: -this.layoutBounds.width / 2, y: this.layoutBounds.height / 2 }\n }\n\n /**\n * Where this cursor has to sit for its hotspot to land on `target`'s centre,\n * in this node's **parent** space.\n *\n * `global` is world-space and `x`/`y` are parent-relative, so the parent's own\n * world contribution comes back off — the conversion `Node2D.global` documents.\n * The half-box offset is what makes the tip, rather than the cursor's centre,\n * the thing that arrives.\n */\n private _reach(target: Node2D): ClickPoint {\n const parent = this.parent2D\n const origin = parent ? parent.global : { x: 0, y: 0 }\n const at = target.global\n const tip = this._hotspot()\n return { x: at.x - origin.x - tip.x, y: at.y - origin.y - tip.y }\n }\n\n /** The node `id` names, from the root of this cursor's own tree. */\n private _controlNamed(id: string | undefined): Node2D | undefined {\n if (id === undefined || id === \"\") return undefined\n let root: Node = this\n while (root.parent) root = root.parent\n return findNode(root, id)\n }\n\n /**\n * The glyph's two contours in the renderer's local space.\n *\n * `cursorArtworkPixels` works y-**down** (the convention the author box and a\n * stored `d` string share), and a node's own space is y-up — hence the flip,\n * which is the whole of the difference between the two.\n */\n private artwork(scale = 1): { keyline: PathCommand[]; body: PathCommand[] } {\n const flip = (p: { x: number; y: number }) => ({ x: p.x, y: -p.y })\n const pixels = cursorArtworkPixels(\n this.cursor,\n this.style,\n this.layoutBounds.width * scale,\n this.layoutBounds.height * scale\n )\n const commands = (path: VectorPath) => pathOps.anchorCommands(path, flip)\n return { keyline: commands(pixels.keyline), body: commands(pixels.body) }\n }\n\n /**\n * The frame both contours are centred against: the node's own box, or the\n * dipped box pinned to the hotspot while a press is under way.\n *\n * Stated rather than left to the descriptor's default, which centres a path\n * on *its own* bounding box. Here that default would break the drawing\n * outright — the body is smaller than the keyline, so each would be centred\n * on a different rectangle and the two would come apart.\n */\n private centerBounds(scale = 1): PathBounds {\n const w = (this.layoutBounds.width * scale) / 2\n const h = (this.layoutBounds.height * scale) / 2\n const tip = this._hotspot()\n // Pinned to the tip, so the dip shrinks the glyph in place rather than\n // walking it down and to the right.\n const cx = tip.x + w\n const cy = tip.y - h\n return [cx - w, cy - h, cx + w, cy + h]\n }\n}\n\n/** The fraction of a click spent travelling, before the press itself. */\nconst TRAVEL = 0.62\n\n/** Depth-first by document id; `undefined` for a node not in this tree. */\nfunction findNode(at: Node, id: string): Node2D | undefined {\n if (at.id === id) return at as Node2D\n for (const child of at._allChildren) {\n const found = findNode(child, id)\n if (found) return found\n }\n return undefined\n}\n\n/**\n * How `target` answers a click, as a function of the press phase — or `null`\n * for a node that has no answer, which is every type but the two controls.\n *\n * Duck-typed on the prop rather than on the class, because a **forked**\n * component is a different class carrying the same source and an `instanceof`\n * against the original is false for it. That is the same argument\n * `Registry.nodeCommand` makes for dispatching on the method name.\n */\nfunction activateOf(target: Node2D): ((phase: number) => void) | null {\n const props = target as unknown as Record<string, unknown>\n\n if (typeof props.progress === \"number\" && \"accent\" in props) {\n // A switch throws once, at the bottom of the press, and stays thrown —\n // read when the command is *built*, matching the timeline's own order, so\n // two clicks at the same `at` agree rather than alternating.\n const from = props.progress\n const to = from > 0.5 ? 0 : 1\n return (phase) => {\n const t = Math.min(1, Math.max(0, (phase - PRESS_DOWN) / (1 - PRESS_DOWN)))\n target.set({ progress: from + (to - from) * t } as never)\n }\n }\n\n if (typeof props.press === \"number\" && \"label\" in props) {\n // A button takes the pointer's own envelope, one whole press per click.\n const base = Math.floor(props.press)\n return (phase) => target.set({ press: base + phase } as never)\n }\n\n return null\n}\n\n/** Where in the press the control actually reacts — the bottom of the travel. */\nconst PRESS_DOWN = 1 / 3\n"]}
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n command,\n driveCommand,\n easeInOut,\n node,\n Clip,\n type Command,\n type CommandArgs,\n Graphics2D,\n Node2D,\n type Node2DProps,\n pathOps,\n property,\n type Node,\n type NodeConfig,\n type PathBounds,\n type PathCommand,\n type RenderContext2D,\n type VectorPath,\n} from \"@motionscript/sdk\"\n\nimport {\n cursorArtworkPixels,\n cursorLook,\n CURSOR_STYLES,\n CURSOR_TYPES,\n DEFAULT_CURSOR_STYLE,\n DEFAULT_CURSOR_TYPE,\n type CursorStyle,\n type CursorType,\n} from \"../kit/cursor-outline\"\nimport {\n arcPointAt,\n resolveClickArc,\n type ClickArc,\n type ClickPoint,\n} from \"../kit/click-path\"\nimport { pressDepth } from \"../kit/press\"\n\n/** A cursor's own props, over the box every node has. */\nexport interface CursorProps extends Node2DProps {\n /** Which glyph to draw — see {@link CursorType}. */\n cursor: CursorType\n /** Which look to draw it in — see {@link CursorStyle}. */\n style: CursorStyle\n /**\n * How many clicks deep the chain is — a **monotonic phase**, not a depth.\n *\n * The one prop {@link Cursor.click} animates, and it climbs by exactly one\n * per click rather than going down and coming back: a tween can only run one\n * way, and a click is two. `pressDepth` turns the fractional part into the\n * down-and-up envelope, which is zero at both whole numbers — so a finished\n * click leaves the pointer at rest by arithmetic rather than by a reset the\n * command would have to remember to write. Exactly `Button.press`, and the\n * same function drives both.\n */\n press: number\n /** Seconds a {@link Cursor.click} runs for when its row states no duration. */\n clickDuration: number\n}\n\n/** How far the glyph shrinks at the bottom of a press. */\nconst PRESS_DIP = 0.12\n/** The ring's radius at the end of a click, as a fraction of the glyph's box. */\nconst RIPPLE_REACH = 1.4\nconst RIPPLE_OPACITY = 0.5\n\n/**\n * A mouse cursor, as a node.\n *\n * The one thing a screen recording has that a motion-graphics scene doesn't:\n * something on screen standing in for the person. Every explainer that shows an\n * interface needs one, and the alternatives are all worse — a screenshot of a\n * cursor pastes in at one size, and a hand-drawn path is a shape nobody can\n * change their mind about.\n *\n * Which pointer, whose, and how far through a click it is. Where it sits and\n * how big it is are the transform every node has; the contours and both colours\n * come out of the first two (see `kit/cursor-outline`, which holds the artwork\n * and the reasoning).\n *\n * ## A `Node2D`, and a leaf\n *\n * Not a `ShapeNode`, on the reasoning `Code` records in its own changeset: the\n * paint slots a shape carries are a surface this node cannot honour. A cursor's\n * colours are not a matter of taste — the Windows arrow is white with a black\n * keyline — so an author asked to set them by hand would be re-deriving a fact\n * rather than making a choice, and a cursor with the wrong two colours is not a\n * stylized cursor, it is a mistake. Declaring `fill`/`overlay`/`stroke`/\n * `shadow` and then ignoring them was a surface a host had no way to know was\n * inert; not declaring them is one it cannot offer.\n *\n * It refuses children for the same kind of reason. Nothing goes *inside* a\n * pointer, and a drop target on one is a place to lose a node.\n *\n * ## Why it paints itself, in two passes\n *\n * The keyline and the body, in that order: the outer contour filled black, then\n * the inner one filled white over it, leaving the keyline showing as the gap\n * between them. Not a fill with a stroke round it, because a stroke's weight is\n * a pixel count and this glyph is stretched onto whatever box the node has —\n * see the module note on `kit/cursor-outline`.\n *\n * ## The hotspot is the box's top-left\n *\n * Both the click ripple and the press dip are anchored there rather than at the\n * node's centre, because that is where a pointer actually points. A dip about\n * the centre would walk the tip half a pixel down and right at the bottom of\n * every press, which reads as the cursor sliding rather than pressing.\n *\n * ## Animating one\n *\n * `cursor` and `style` are ordinary props, so a `to` command can change either.\n * Neither has a tween function, and motion-script's fallback for a value it\n * can't interpolate is to hold the old one until the command ends and then\n * snap — which is exactly right here: there is no halfway between an arrow and\n * a pointing hand, and a cursor that changes shape *at the moment it reaches\n * the link* is what the author is after. A zero-duration `to` is the instant\n * switch.\n */\n@node({\n key: \"cursor\",\n parentKey: \"node\",\n forkable: true,\n layout: {\n children: \"freeform\",\n defaultWidthMode: \"fixed\",\n defaultHeightMode: \"fixed\",\n acceptsChildren: false,\n },\n seed: {\n width: 32,\n height: 32,\n },\n})\nexport class Cursor extends Node2D<CursorProps> {\n @property({ default: DEFAULT_CURSOR_TYPE, kind: \"enum\", options: CURSOR_TYPES })\n declare cursor: CursorType\n\n @property({ default: DEFAULT_CURSOR_STYLE, kind: \"enum\", options: CURSOR_STYLES })\n declare style: CursorStyle\n\n @property({ default: 0, min: 0 }) declare press: number\n\n @property({ default: 0.5, min: 0, step: 0.05, unit: \"s\" })\n declare clickDuration: number\n\n constructor(props: NodeConfig<Cursor, CursorProps>) {\n super(props as NodeConfig<Node2D, Node2DProps>)\n }\n\n /**\n * Travel to a control, press it, and let go — the whole gesture as one row.\n *\n * **`target` is a node id, and it is resolved when the command is built.**\n * That is the point of the command: the destination and the curve to it are\n * derived from where the control *currently* is, so moving a switch on the\n * canvas re-aims the animation with nothing to re-author. A baked path is\n * correct only for the two points it was baked against, which is what made\n * this a chore worth removing. An id rather than a `key` because `NodeSpec.key`\n * is optional and never generated, so it is not a handle every node has; an\n * expression is not an option either, since a command that does not `bind`\n * refuses one outright (`SceneTimeline._assertNoExpressions`).\n *\n * Naming nothing — or naming a node absent at this moment — clicks in place,\n * which is the same answer the document's own node references give for\n * something not there. A click is a legitimate beat over a rectangle or an\n * image, so refusing would cost more than it caught.\n *\n * `activate` drives the control itself: a switch throws, a button takes a\n * press. Both are written straight to the other node, which the timeline\n * restores along with this one because it records what a command writes\n * rather than what it targets.\n */\n @command({\n args: [\n { key: \"target\", kind: \"nodeRef\" },\n {\n key: \"clickShape\",\n kind: \"arc\",\n properties: {\n bow: { kind: \"number\", min: -1, max: 1, step: 0.01 },\n lean: { kind: \"number\", min: 0, max: 1, step: 0.01 },\n },\n },\n { key: \"activate\", kind: \"boolean\", default: true },\n ],\n })\n click(\n args: CommandArgs<{\n target?: string\n clickShape?: Partial<ClickArc>\n activate?: boolean\n }> & { duration?: number },\n ): Command<CursorProps> {\n const duration = args.duration && args.duration > 0 ? args.duration : this.clickDuration\n const easing = args.easing ?? easeInOut()\n const arc = resolveClickArc(args.data?.clickShape)\n const target = this._controlNamed(args.data?.target)\n\n const from: ClickPoint = { x: this.x, y: this.y }\n const to = target ? this._reach(target) : from\n const press = Math.floor(this.press)\n const activated =\n args.data?.activate === false ? null : target && activateOf(target)\n\n return driveCommand(duration, (t) => {\n // Travel over the lead-in, then hold still while the click happens: a\n // pointer that is still moving as it presses reads as a drag.\n const travel = easing(Math.min(1, t / TRAVEL))\n const at = arcPointAt(from, to, arc, travel)\n const phase = t <= TRAVEL ? 0 : (t - TRAVEL) / (1 - TRAVEL)\n this.set({ x: at.x, y: at.y, press: press + phase } as Partial<CursorProps>)\n activated?.(phase)\n }) as unknown as Command<CursorProps>\n }\n\n /**\n * Keyline, then body — the two-tone cursor, in the style's own colours, with\n * the click ripple behind them.\n *\n * The glyph is one `Graphics2D` with two shape groups rather than two\n * submissions: `fill()` scopes to the shapes declared since the last one, so\n * the second `path()` starts a group of its own and the two paint in order.\n * The ripple is a submission of its own because it carries a group opacity,\n * and `Graphics2D.opacity` composites the whole list — chaining it would fade\n * the pointer along with the ring.\n */\n protected override renderSelf(ctx: RenderContext2D): void {\n const depth = pressDepth(this.press)\n this._drawRipple(ctx, depth)\n\n const scale = 1 - PRESS_DIP * depth\n const { keyline, body } = this.artwork(scale)\n if (keyline.length === 0) return\n const look = cursorLook(this.style)\n const centerBounds = this.centerBounds(scale)\n ctx.draw(\n new Graphics2D()\n .path({ data: keyline, centerBounds })\n .fill(look.keyline)\n .path({ data: body, centerBounds })\n .fill(look.body)\n )\n }\n\n /** Nothing goes inside a pointer — see the class note. */\n protected override acceptsChild(_child: Node): boolean {\n return false\n }\n\n /**\n * The node's laid-out rect as a clip outline, so `clip` and any backdrop\n * effect are confined to the box rather than to nothing.\n *\n * Picking needs no help here: `Node2D` already grabs on the layout box, which\n * is the answer a cursor wants. An arrow occupies about a third of its box,\n * so picking on the silhouette would mean clicking one required hitting the\n * arrow itself — which on a node whose whole job is to be small on screen\n * reads as the app ignoring you.\n */\n protected override clipSelf(): Clip {\n return new Clip().rect({\n width: this.layoutBounds.width,\n height: this.layoutBounds.height,\n })\n }\n\n /**\n * The expanding ring a click leaves, centred on the hotspot.\n *\n * Drawn from the press envelope rather than from a phase of its own, so it\n * cannot drift out of step with the dip — and so a cursor at rest draws\n * nothing at all, which is the common case on every frame.\n */\n private _drawRipple(ctx: RenderContext2D, depth: number): void {\n if (depth <= 0) return\n const { width, height } = this.layoutBounds\n const span = Math.max(width, height)\n if (span <= 0) return\n const tip = this._hotspot()\n const radius = span * RIPPLE_REACH * depth\n ctx.draw(\n new Graphics2D()\n .ellipse({\n x: tip.x,\n y: tip.y,\n width: radius * 2,\n height: radius * 2,\n })\n .stroke({\n weight: Math.max(1, span * 0.06 * (1 - depth)),\n fill: cursorLook(this.style).keyline,\n align: \"center\",\n })\n .opacity(RIPPLE_OPACITY * (1 - depth))\n )\n }\n\n /** Where the pointer points, in the node's own y-up local space. */\n private _hotspot(): ClickPoint {\n return { x: -this.layoutBounds.width / 2, y: this.layoutBounds.height / 2 }\n }\n\n /**\n * Where this cursor has to sit for its hotspot to land on `target`'s centre,\n * in this node's **parent** space.\n *\n * `global` is world-space and `x`/`y` are parent-relative, so the parent's own\n * world contribution comes back off — the conversion `Node2D.global` documents.\n * The half-box offset is what makes the tip, rather than the cursor's centre,\n * the thing that arrives.\n */\n private _reach(target: Node2D): ClickPoint {\n const parent = this.parent2D\n const origin = parent ? parent.global : { x: 0, y: 0 }\n const at = target.global\n const tip = this._hotspot()\n return { x: at.x - origin.x - tip.x, y: at.y - origin.y - tip.y }\n }\n\n /** The node `id` names, from the root of this cursor's own tree. */\n private _controlNamed(id: string | undefined): Node2D | undefined {\n if (id === undefined || id === \"\") return undefined\n let root: Node = this\n while (root.parent) root = root.parent\n return findNode(root, id)\n }\n\n /**\n * The glyph's two contours in the renderer's local space.\n *\n * `cursorArtworkPixels` works y-**down** (the convention the author box and a\n * stored `d` string share), and a node's own space is y-up — hence the flip,\n * which is the whole of the difference between the two.\n */\n private artwork(scale = 1): { keyline: PathCommand[]; body: PathCommand[] } {\n const flip = (p: { x: number; y: number }) => ({ x: p.x, y: -p.y })\n const pixels = cursorArtworkPixels(\n this.cursor,\n this.style,\n this.layoutBounds.width * scale,\n this.layoutBounds.height * scale\n )\n const commands = (path: VectorPath) => pathOps.anchorCommands(path, flip)\n return { keyline: commands(pixels.keyline), body: commands(pixels.body) }\n }\n\n /**\n * The frame both contours are centred against: the node's own box, or the\n * dipped box pinned to the hotspot while a press is under way.\n *\n * Stated rather than left to the descriptor's default, which centres a path\n * on *its own* bounding box. Here that default would break the drawing\n * outright — the body is smaller than the keyline, so each would be centred\n * on a different rectangle and the two would come apart.\n */\n private centerBounds(scale = 1): PathBounds {\n const w = (this.layoutBounds.width * scale) / 2\n const h = (this.layoutBounds.height * scale) / 2\n const tip = this._hotspot()\n // Pinned to the tip, so the dip shrinks the glyph in place rather than\n // walking it down and to the right.\n const cx = tip.x + w\n const cy = tip.y - h\n return [cx - w, cy - h, cx + w, cy + h]\n }\n}\n\n/** The fraction of a click spent travelling, before the press itself. */\nconst TRAVEL = 0.62\n\n/** Depth-first by document id; `undefined` for a node not in this tree. */\nfunction findNode(at: Node, id: string): Node2D | undefined {\n if (at.id === id) return at as Node2D\n for (const child of at._allChildren) {\n const found = findNode(child, id)\n if (found) return found\n }\n return undefined\n}\n\n/**\n * How `target` answers a click, as a function of the press phase — or `null`\n * for a node that has no answer, which is every type but the two controls.\n *\n * Duck-typed on the prop rather than on the class, because a **forked**\n * component is a different class carrying the same source and an `instanceof`\n * against the original is false for it. That is the same argument\n * `Registry.nodeCommand` makes for dispatching on the method name.\n */\nfunction activateOf(target: Node2D): ((phase: number) => void) | null {\n const props = target as unknown as Record<string, unknown>\n\n if (typeof props.progress === \"number\" && \"accent\" in props) {\n // A switch throws once, at the bottom of the press, and stays thrown —\n // read when the command is *built*, matching the timeline's own order, so\n // two clicks at the same `at` agree rather than alternating.\n const from = props.progress\n const to = from > 0.5 ? 0 : 1\n return (phase) => {\n const t = Math.min(1, Math.max(0, (phase - PRESS_DOWN) / (1 - PRESS_DOWN)))\n target.set({ progress: from + (to - from) * t } as never)\n }\n }\n\n if (typeof props.press === \"number\" && \"label\" in props) {\n // A button takes the pointer's own envelope, one whole press per click.\n const base = Math.floor(props.press)\n return (phase) => target.set({ press: base + phase } as never)\n }\n\n return null\n}\n\n/** Where in the press the control actually reacts — the bottom of the travel. */\nconst PRESS_DOWN = 1 / 3\n"]}
@@ -38,7 +38,7 @@
38
38
  * glyph exactly as the cursor's keyline does — a pixel weight would be a
39
39
  * hairline on a large switch and a blob on a small one.
40
40
  */
41
- import { type VectorPath } from "@motionscript/core";
41
+ import { type VectorPath } from "@motionscript/sdk";
42
42
  /**
43
43
  * The marks a control can wear, in the order the dropdown offers them.
44
44
  *
@@ -1 +1 @@
1
- {"version":3,"file":"control-icons.d.ts","sourceRoot":"","sources":["../../src/kit/control-icons.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAA6B,KAAK,UAAU,EAAgB,MAAM,oBAAoB,CAAA;AAE7F;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,qJAiBhB,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,EAAE,WAAoB,CAAA;AAEvD,sFAAsF;AACtF,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,OAAO,EAAE,UAAU,CAAA;IACnB,qCAAqC;IACrC,KAAK,EAAE,UAAU,CAAA;IACjB,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;CACf;AA8ZD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,GACX;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAa5D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG;IAClD,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAOA;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAKlE"}
1
+ {"version":3,"file":"control-icons.d.ts","sourceRoot":"","sources":["../../src/kit/control-icons.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAA6B,KAAK,UAAU,EAAgB,MAAM,mBAAmB,CAAA;AAE5F;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,qJAiBhB,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,EAAE,WAAoB,CAAA;AAEvD,sFAAsF;AACtF,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,OAAO,EAAE,UAAU,CAAA;IACnB,qCAAqC;IACrC,KAAK,EAAE,UAAU,CAAA;IACjB,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;CACf;AA8ZD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,GACX;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAa5D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG;IAClD,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAOA;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAKlE"}
@@ -38,7 +38,7 @@
38
38
  * glyph exactly as the cursor's keyline does — a pixel weight would be a
39
39
  * hairline on a large switch and a blob on a small one.
40
40
  */
41
- import { pathOps } from "@motionscript/core";
41
+ import { pathOps } from "@motionscript/sdk";
42
42
  /**
43
43
  * The marks a control can wear, in the order the dropdown offers them.
44
44
  *
@@ -1 +1 @@
1
- {"version":3,"file":"control-icons.js","sourceRoot":"","sources":["../../src/kit/control-icons.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The glyph catalogue the UI-control nodes draw inside themselves — the mark a\n * Switch wears in its knob, and the one a Button wears beside its label.\n *\n * ## Why a catalogue rather than an asset field\n *\n * The obvious alternative is to let an author point each slot at an image in the\n * library, and it is the wrong shape twice over. A control's icon is drawn at\n * twelve pixels inside a moving knob, so it has to be a *line* that thickens\n * with the control rather than a bitmap that blurs; and the icons people\n * actually want here — a tick, a cross, a power symbol — are the same dozen in\n * every product ever shipped, so asking someone to find and upload one is asking\n * them to do work whose only possible answer is already known.\n *\n * The same argument `model/cursor-outline` makes for the pointer, and this\n * module is deliberately its sibling: fixed artwork, normalized once into an\n * author box, handed out mapped onto whatever box the node has.\n *\n * ## Built rather than pasted\n *\n * Unlike the cursor's, these contours are **constructed** — {@link circle},\n * {@link arc} and {@link polyline} rather than verbatim `d` strings. Two\n * reasons, and the second is the load-bearing one:\n *\n * - Half of them are circles and arcs, and `parseVectorPath` deliberately\n * understands no `A` command (see its `COMMAND_LETTERS`), so a pasted circle\n * would have arrived as somebody's hand-expanded cubics anyway.\n * - A glyph built from named geometry is one somebody can *correct*. \"The power\n * ring opens 60° at the top\" is a line of code; the same fact spelled as eight\n * control points is a drawing nobody will ever touch again.\n *\n * ## Two kinds of contour\n *\n * A glyph carries a stroked list and a filled list, and most carry only one. It\n * is not a stylistic choice: a tick has no interior and a play triangle has\n * nothing else, so drawing either the other way round is drawing a different\n * mark. {@link ControlIconArtwork.weight} is in box units, so it scales with the\n * glyph exactly as the cursor's keyline does — a pixel weight would be a\n * hairline on a large switch and a blob on a small one.\n */\n\nimport { pathOps, type PathSubpath, type VectorPath, type Vector2 } from \"@motionscript/core\"\n\n/**\n * The marks a control can wear, in the order the dropdown offers them.\n *\n * `none` leads and is the default for both slots, because the commonest switch\n * in the world has no icon in it at all — the position *is* the state. What the\n * rest are for is the switch whose two states are not obviously opposite (\"mic\n * live / mic muted\"), where the mark is what saves a caption.\n *\n * Ordered by what they answer rather than alphabetically: the yes/no pair, the\n * arithmetic pair, the transport pair, then the ones that name a *thing* being\n * switched — power, light, sound, security.\n */\nexport const CONTROL_ICONS = [\n \"none\",\n \"check\",\n \"close\",\n \"dot\",\n \"plus\",\n \"minus\",\n \"play\",\n \"pause\",\n \"power\",\n \"sun\",\n \"moon\",\n \"star\",\n \"heart\",\n \"lock\",\n \"bolt\",\n \"arrowRight\",\n] as const\n\nexport type ControlIcon = (typeof CONTROL_ICONS)[number]\n\n/** What both icon slots open on: nothing. See {@link CONTROL_ICONS}. */\nexport const DEFAULT_CONTROL_ICON: ControlIcon = \"none\"\n\n/** The side of the square box every glyph is authored in, y-down, origin top-left. */\nexport const CONTROL_ICON_UNITS = 24\n\n/** One glyph: what to stroke, what to fill, and how thick the stroke is. */\nexport interface ControlIconArtwork {\n /** Open (or closed) contours drawn as lines. */\n strokes: VectorPath\n /** Closed contours painted solid. */\n fills: VectorPath\n /** Stroke weight, in units of the {@link CONTROL_ICON_UNITS} box. */\n weight: number\n}\n\n/** The empty glyph — what `none` resolves to, and the fallback for a bad key. */\nconst EMPTY_ARTWORK: ControlIconArtwork = {\n strokes: [],\n fills: [],\n weight: 0,\n}\n\n// --- Construction helpers --------------------------------------------------\n\nfunction point(x: number, y: number): Vector2 {\n return { x, y }\n}\n\n/** A run of straight segments through `points`, optionally closed. */\nfunction polyline(points: Vector2[], closed = false): PathSubpath {\n return {\n anchors: points.map((p) => ({ point: p, inHandle: null, outHandle: null })),\n closed,\n }\n}\n\n/**\n * A circular arc as cubics, swept **clockwise** in the y-down box from `from`\n * degrees to `to` degrees (0° is due east, 90° due south).\n *\n * Split so no segment spans more than a quarter turn, which is the point past\n * which a single cubic's error stops being invisible. The handle length is the\n * standard `(4/3)·tan(Δ/4)·r`, exact at the endpoints and within a thousandth of\n * the radius in between — far below the half-pixel anyone could see at the size\n * these are drawn.\n */\nfunction arc(\n cx: number,\n cy: number,\n radius: number,\n from: number,\n to: number,\n closed = false\n): PathSubpath {\n const start = (from * Math.PI) / 180\n const end = (to * Math.PI) / 180\n const sweep = end - start\n const steps = Math.max(1, Math.ceil(Math.abs(sweep) / (Math.PI / 2)))\n const step = sweep / steps\n const handle = (4 / 3) * Math.tan(step / 4) * radius\n\n const at = (angle: number): Vector2 =>\n point(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle))\n /** The unit tangent in the direction of increasing angle. */\n const tangent = (angle: number): Vector2 =>\n point(-Math.sin(angle), Math.cos(angle))\n\n const anchors = []\n for (let i = 0; i <= steps; i++) {\n const angle = start + step * i\n const p = at(angle)\n const t = tangent(angle)\n anchors.push({\n point: p,\n // The first anchor has nothing arriving at it and the last nothing\n // leaving, which is what makes this an arc rather than a closed ring.\n inHandle: i === 0 ? null : point(p.x - t.x * handle, p.y - t.y * handle),\n outHandle:\n i === steps ? null : point(p.x + t.x * handle, p.y + t.y * handle),\n })\n }\n return { anchors, closed }\n}\n\n/** A full ring, as the closed four-segment arc. */\nfunction circle(cx: number, cy: number, radius: number): PathSubpath {\n const ring = arc(cx, cy, radius, 0, 360, true)\n // The sweep lands exactly back on the first anchor, so the last one is that\n // same point twice — dropped, with its incoming handle moved onto the anchor\n // it duplicates, which is what closes the ring smoothly rather than with a\n // corner.\n const anchors = ring.anchors.slice(0, -1)\n const last = ring.anchors[ring.anchors.length - 1]\n anchors[0] = { ...anchors[0], inHandle: last.inHandle }\n return { anchors, closed: true }\n}\n\n/**\n * Two arcs welded end to end into one contour.\n *\n * The second's first anchor is the same *point* as the first's last — that is\n * what makes the pair a shape rather than two curves — so it is dropped and its\n * outgoing handle moved onto the anchor it duplicated. Leaving it in would put a\n * zero-length segment at the seam, which strokes as a dot and fills as nothing.\n */\nfunction joinArcs(first: PathSubpath, second: PathSubpath): PathSubpath {\n const head = first.anchors.slice(0, -1)\n const seam = first.anchors[first.anchors.length - 1]\n const [start, ...rest] = second.anchors\n return {\n anchors: [...head, { ...seam, outHandle: start.outHandle }, ...rest],\n closed: true,\n }\n}\n\n/** A regular star, `points` long, alternating between the two radii. */\nfunction star(\n cx: number,\n cy: number,\n outer: number,\n inner: number,\n points: number\n): PathSubpath {\n const vertices: Vector2[] = []\n for (let i = 0; i < points * 2; i++) {\n // Starts at due north, which is the only orientation anyone pictures.\n const angle = (Math.PI * i) / points - Math.PI / 2\n const radius = i % 2 === 0 ? outer : inner\n vertices.push(\n point(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle))\n )\n }\n return polyline(vertices, true)\n}\n\n/**\n * The crescent's outline: the fat edge of one circle, bitten by another.\n *\n * The two **tips** are chosen first — at −60° and 150° on the outer ring, which\n * is the tilt every moon glyph is drawn at — and the biting circle is then\n * derived from them: its centre is the point on their perpendicular bisector\n * that sits {@link BITE} away from their midpoint, on the side the bite comes\n * from. So the two arcs meet exactly, by construction rather than by adjustment,\n * and moving the tips or deepening the bite keeps them meeting.\n */\nfunction crescent(): PathSubpath {\n const cx = 12\n const cy = 12\n const radius = 8.5\n /** How far the biting circle's centre sits off the chord's midpoint. */\n const BITE = 3.5\n\n const tip = (degrees: number): Vector2 => {\n const angle = (degrees * Math.PI) / 180\n return point(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle))\n }\n const first = tip(-60)\n const second = tip(150)\n\n // The chord's midpoint, pushed along its own perpendicular toward the\n // up-and-left, which is where a crescent's bite comes from.\n const midX = (first.x + second.x) / 2\n const midY = (first.y + second.y) / 2\n const span = Math.hypot(second.x - first.x, second.y - first.y)\n const normalX = -(second.y - first.y) / span\n const normalY = (second.x - first.x) / span\n const biteX = midX + normalX * BITE\n const biteY = midY + normalY * BITE\n const biteRadius = Math.hypot(first.x - biteX, first.y - biteY)\n const angleOf = (p: Vector2): number =>\n (Math.atan2(p.y - biteY, p.x - biteX) * 180) / Math.PI\n\n return joinArcs(\n // The outer edge: the long way round, through the east and the south.\n arc(cx, cy, radius, -60, 150),\n // …and back through the biting circle's own east and south, which lies\n // inside the ring above and is therefore the concave side.\n arc(biteX, biteY, biteRadius, angleOf(second), angleOf(first))\n )\n}\n\n// --- The catalogue ---------------------------------------------------------\n\n/** The default stroke weight: two units of twenty-four, as lucide draws. */\nconst WEIGHT = 2.2\n\n/**\n * Every glyph, in the 24-unit author box.\n *\n * Built at module load rather than per draw, exactly as the cursor's artwork is:\n * these are fixed drawings with nothing to recompute, so re-deriving a few dozen\n * control points every frame would buy nothing.\n */\nconst ARTWORK: Record<ControlIcon, ControlIconArtwork> = {\n none: EMPTY_ARTWORK,\n\n check: {\n strokes: [polyline([point(5, 12.5), point(9.75, 17.5), point(19, 6.5)])],\n fills: [],\n weight: WEIGHT,\n },\n\n close: {\n strokes: [\n polyline([point(6.5, 6.5), point(17.5, 17.5)]),\n polyline([point(17.5, 6.5), point(6.5, 17.5)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n // A filled disc — the mark for a switch whose states are \"armed\" and \"not\",\n // where a tick would claim something was completed.\n dot: { strokes: [], fills: [circle(12, 12, 4.5)], weight: 0 },\n\n plus: {\n strokes: [\n polyline([point(12, 5.5), point(12, 18.5)]),\n polyline([point(5.5, 12), point(18.5, 12)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n minus: {\n strokes: [polyline([point(5.5, 12), point(18.5, 12)])],\n fills: [],\n weight: WEIGHT,\n },\n\n // Filled, because a play triangle has no interior to leave empty — an\n // outlined one reads as a \"next\" chevron rather than as play.\n play: {\n strokes: [],\n fills: [polyline([point(7.5, 5), point(19, 12), point(7.5, 19)], true)],\n weight: 0,\n },\n\n pause: {\n strokes: [],\n fills: [\n polyline(\n [point(8, 5.5), point(11, 5.5), point(11, 18.5), point(8, 18.5)],\n true\n ),\n polyline(\n [point(13, 5.5), point(16, 5.5), point(16, 18.5), point(13, 18.5)],\n true\n ),\n ],\n weight: 0,\n },\n\n // The ring opens 60° at the top, centred on the stem — the IEC 5009 symbol\n // every device on earth wears, and the reason the gap is stated in degrees\n // rather than drawn: it is a fact about the symbol, not about this drawing.\n power: {\n strokes: [\n arc(12, 12.5, 7, -60, 240),\n polyline([point(12, 3.5), point(12, 11.5)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n sun: {\n strokes: [\n circle(12, 12, 4.5),\n ...Array.from({ length: 8 }, (_, i) => {\n const angle = (Math.PI * i) / 4\n const cos = Math.cos(angle)\n const sin = Math.sin(angle)\n return polyline([\n point(12 + cos * 7.5, 12 + sin * 7.5),\n point(12 + cos * 9.75, 12 + sin * 9.75),\n ])\n }),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n // A crescent as two arcs of two different circles rather than one circle cut\n // out of another: a cut needs an even-odd fill the renderer would have to be\n // told about, and the outline is the same shape either way.\n //\n // The second circle is *derived* from where the two tips sit rather than\n // eyeballed, which is the only way the two arcs meet exactly — a crescent\n // whose halves miss each other by a unit closes with a straight nick across\n // its own point. See {@link crescent}.\n moon: { strokes: [], fills: [crescent()], weight: 0 },\n\n star: { strokes: [], fills: [star(12, 12, 8.5, 3.6, 5)], weight: 0 },\n\n // Two lobes meeting at a point. Written as one closed contour of four cubics\n // because a heart is a *shape*, and splitting it into halves would leave a\n // seam down the middle of any stroke drawn on it.\n heart: {\n strokes: [],\n fills: [\n {\n anchors: [\n {\n point: point(12, 20),\n inHandle: point(15.6, 17),\n outHandle: point(8.4, 17),\n },\n {\n point: point(4, 11.6),\n inHandle: point(5.4, 15.4),\n outHandle: point(2.2, 9.6),\n },\n {\n point: point(7.8, 5.5),\n inHandle: point(4.2, 5.5),\n outHandle: point(10.4, 5.5),\n },\n {\n point: point(12, 8.6),\n inHandle: point(11.2, 6.6),\n outHandle: point(12.8, 6.6),\n },\n {\n point: point(16.2, 5.5),\n inHandle: point(13.6, 5.5),\n outHandle: point(19.8, 5.5),\n },\n {\n point: point(20, 11.6),\n inHandle: point(21.8, 9.6),\n outHandle: point(18.6, 15.4),\n },\n ],\n closed: true,\n },\n ],\n weight: 0,\n },\n\n lock: {\n strokes: [\n // The shackle: a half turn, open at the bottom where it meets the body.\n arc(12, 10, 4, 180, 360),\n // The body, as a rounded box drawn from its four corners.\n {\n anchors: [\n {\n point: point(6.25, 10.5),\n inHandle: point(6.25, 10.9),\n outHandle: null,\n },\n {\n point: point(17.75, 10.5),\n inHandle: null,\n outHandle: point(18.5, 10.5),\n },\n {\n point: point(18.5, 11.25),\n inHandle: point(18.5, 10.85),\n outHandle: null,\n },\n {\n point: point(18.5, 18.75),\n inHandle: null,\n outHandle: point(18.5, 19.5),\n },\n {\n point: point(17.75, 19.5),\n inHandle: point(18.15, 19.5),\n outHandle: null,\n },\n {\n point: point(6.25, 19.5),\n inHandle: null,\n outHandle: point(5.5, 19.5),\n },\n {\n point: point(5.5, 18.75),\n inHandle: point(5.5, 19.15),\n outHandle: null,\n },\n {\n point: point(5.5, 11.25),\n inHandle: null,\n outHandle: point(5.5, 10.5),\n },\n ],\n closed: true,\n },\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n bolt: {\n strokes: [],\n fills: [\n polyline(\n [\n point(13.5, 2.5),\n point(5, 13.5),\n point(11, 13.5),\n point(10.5, 21.5),\n point(19, 10.5),\n point(13, 10.5),\n ],\n true\n ),\n ],\n weight: 0,\n },\n\n arrowRight: {\n strokes: [\n polyline([point(4.5, 12), point(19, 12)]),\n polyline([point(13, 6), point(19, 12), point(13, 18)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n}\n\n/** The glyph a key names, or the empty one for a key this build doesn't know. */\nfunction artworkFor(icon: ControlIcon): ControlIconArtwork {\n return ARTWORK[icon] ?? EMPTY_ARTWORK\n}\n\n/**\n * The glyph mapped onto a `size` × `size` box **centred on the origin and\n * y-up** — the space a node draws in.\n *\n * The flip is the whole of the difference between the author box and the\n * renderer's, exactly as it is for the cursor: glyphs are drawn y-down because\n * that is what every SVG box and every icon set uses, and a node's own space\n * counts upward.\n *\n * The weight comes back in pixels so the caller can hand it straight to a\n * stroke. It scales with the glyph, which is the point: an icon in a switch knob\n * is drawn at whatever size the knob came out, and a fixed pixel weight would be\n * a hairline on a big control and a smudge on a small one.\n */\nexport function controlIconPixels(\n icon: ControlIcon,\n size: number\n): { strokes: VectorPath; fills: VectorPath; weight: number } {\n const artwork = artworkFor(icon)\n if (!(size > 0)) return { strokes: [], fills: [], weight: 0 }\n const scale = size / CONTROL_ICON_UNITS\n const onto = (p: Vector2): Vector2 => ({\n x: p.x * scale - size / 2,\n y: size / 2 - p.y * scale,\n })\n return {\n strokes: pathOps.map(artwork.strokes, onto),\n fills: pathOps.map(artwork.fills, onto),\n weight: artwork.weight * scale,\n }\n}\n\n/**\n * The glyph as SVG `d` strings in the 24-unit box, for the studio's own chrome.\n *\n * What the icon dropdown draws its options with, so a mark corrected here is\n * corrected in the panel too — the same bargain `cursorArtworkData` strikes, and\n * for the same reason: a hand-drawn approximation in the picker is a picture of\n * an icon the node does not draw.\n */\nexport function controlIconData(icon: ControlIcon): {\n strokes: string\n fills: string\n weight: number\n} {\n const artwork = artworkFor(icon)\n return {\n strokes: pathOps.fromAnchors(artwork.strokes),\n fills: pathOps.fromAnchors(artwork.fills),\n weight: artwork.weight,\n }\n}\n\n/** Whether a stored value names a glyph this build can draw. */\nexport function isControlIcon(value: unknown): value is ControlIcon {\n return (\n typeof value === \"string\" &&\n (CONTROL_ICONS as readonly string[]).includes(value)\n )\n}\n"]}
1
+ {"version":3,"file":"control-icons.js","sourceRoot":"","sources":["../../src/kit/control-icons.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The glyph catalogue the UI-control nodes draw inside themselves — the mark a\n * Switch wears in its knob, and the one a Button wears beside its label.\n *\n * ## Why a catalogue rather than an asset field\n *\n * The obvious alternative is to let an author point each slot at an image in the\n * library, and it is the wrong shape twice over. A control's icon is drawn at\n * twelve pixels inside a moving knob, so it has to be a *line* that thickens\n * with the control rather than a bitmap that blurs; and the icons people\n * actually want here — a tick, a cross, a power symbol — are the same dozen in\n * every product ever shipped, so asking someone to find and upload one is asking\n * them to do work whose only possible answer is already known.\n *\n * The same argument `model/cursor-outline` makes for the pointer, and this\n * module is deliberately its sibling: fixed artwork, normalized once into an\n * author box, handed out mapped onto whatever box the node has.\n *\n * ## Built rather than pasted\n *\n * Unlike the cursor's, these contours are **constructed** — {@link circle},\n * {@link arc} and {@link polyline} rather than verbatim `d` strings. Two\n * reasons, and the second is the load-bearing one:\n *\n * - Half of them are circles and arcs, and `parseVectorPath` deliberately\n * understands no `A` command (see its `COMMAND_LETTERS`), so a pasted circle\n * would have arrived as somebody's hand-expanded cubics anyway.\n * - A glyph built from named geometry is one somebody can *correct*. \"The power\n * ring opens 60° at the top\" is a line of code; the same fact spelled as eight\n * control points is a drawing nobody will ever touch again.\n *\n * ## Two kinds of contour\n *\n * A glyph carries a stroked list and a filled list, and most carry only one. It\n * is not a stylistic choice: a tick has no interior and a play triangle has\n * nothing else, so drawing either the other way round is drawing a different\n * mark. {@link ControlIconArtwork.weight} is in box units, so it scales with the\n * glyph exactly as the cursor's keyline does — a pixel weight would be a\n * hairline on a large switch and a blob on a small one.\n */\n\nimport { pathOps, type PathSubpath, type VectorPath, type Vector2 } from \"@motionscript/sdk\"\n\n/**\n * The marks a control can wear, in the order the dropdown offers them.\n *\n * `none` leads and is the default for both slots, because the commonest switch\n * in the world has no icon in it at all — the position *is* the state. What the\n * rest are for is the switch whose two states are not obviously opposite (\"mic\n * live / mic muted\"), where the mark is what saves a caption.\n *\n * Ordered by what they answer rather than alphabetically: the yes/no pair, the\n * arithmetic pair, the transport pair, then the ones that name a *thing* being\n * switched — power, light, sound, security.\n */\nexport const CONTROL_ICONS = [\n \"none\",\n \"check\",\n \"close\",\n \"dot\",\n \"plus\",\n \"minus\",\n \"play\",\n \"pause\",\n \"power\",\n \"sun\",\n \"moon\",\n \"star\",\n \"heart\",\n \"lock\",\n \"bolt\",\n \"arrowRight\",\n] as const\n\nexport type ControlIcon = (typeof CONTROL_ICONS)[number]\n\n/** What both icon slots open on: nothing. See {@link CONTROL_ICONS}. */\nexport const DEFAULT_CONTROL_ICON: ControlIcon = \"none\"\n\n/** The side of the square box every glyph is authored in, y-down, origin top-left. */\nexport const CONTROL_ICON_UNITS = 24\n\n/** One glyph: what to stroke, what to fill, and how thick the stroke is. */\nexport interface ControlIconArtwork {\n /** Open (or closed) contours drawn as lines. */\n strokes: VectorPath\n /** Closed contours painted solid. */\n fills: VectorPath\n /** Stroke weight, in units of the {@link CONTROL_ICON_UNITS} box. */\n weight: number\n}\n\n/** The empty glyph — what `none` resolves to, and the fallback for a bad key. */\nconst EMPTY_ARTWORK: ControlIconArtwork = {\n strokes: [],\n fills: [],\n weight: 0,\n}\n\n// --- Construction helpers --------------------------------------------------\n\nfunction point(x: number, y: number): Vector2 {\n return { x, y }\n}\n\n/** A run of straight segments through `points`, optionally closed. */\nfunction polyline(points: Vector2[], closed = false): PathSubpath {\n return {\n anchors: points.map((p) => ({ point: p, inHandle: null, outHandle: null })),\n closed,\n }\n}\n\n/**\n * A circular arc as cubics, swept **clockwise** in the y-down box from `from`\n * degrees to `to` degrees (0° is due east, 90° due south).\n *\n * Split so no segment spans more than a quarter turn, which is the point past\n * which a single cubic's error stops being invisible. The handle length is the\n * standard `(4/3)·tan(Δ/4)·r`, exact at the endpoints and within a thousandth of\n * the radius in between — far below the half-pixel anyone could see at the size\n * these are drawn.\n */\nfunction arc(\n cx: number,\n cy: number,\n radius: number,\n from: number,\n to: number,\n closed = false\n): PathSubpath {\n const start = (from * Math.PI) / 180\n const end = (to * Math.PI) / 180\n const sweep = end - start\n const steps = Math.max(1, Math.ceil(Math.abs(sweep) / (Math.PI / 2)))\n const step = sweep / steps\n const handle = (4 / 3) * Math.tan(step / 4) * radius\n\n const at = (angle: number): Vector2 =>\n point(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle))\n /** The unit tangent in the direction of increasing angle. */\n const tangent = (angle: number): Vector2 =>\n point(-Math.sin(angle), Math.cos(angle))\n\n const anchors = []\n for (let i = 0; i <= steps; i++) {\n const angle = start + step * i\n const p = at(angle)\n const t = tangent(angle)\n anchors.push({\n point: p,\n // The first anchor has nothing arriving at it and the last nothing\n // leaving, which is what makes this an arc rather than a closed ring.\n inHandle: i === 0 ? null : point(p.x - t.x * handle, p.y - t.y * handle),\n outHandle:\n i === steps ? null : point(p.x + t.x * handle, p.y + t.y * handle),\n })\n }\n return { anchors, closed }\n}\n\n/** A full ring, as the closed four-segment arc. */\nfunction circle(cx: number, cy: number, radius: number): PathSubpath {\n const ring = arc(cx, cy, radius, 0, 360, true)\n // The sweep lands exactly back on the first anchor, so the last one is that\n // same point twice — dropped, with its incoming handle moved onto the anchor\n // it duplicates, which is what closes the ring smoothly rather than with a\n // corner.\n const anchors = ring.anchors.slice(0, -1)\n const last = ring.anchors[ring.anchors.length - 1]\n anchors[0] = { ...anchors[0], inHandle: last.inHandle }\n return { anchors, closed: true }\n}\n\n/**\n * Two arcs welded end to end into one contour.\n *\n * The second's first anchor is the same *point* as the first's last — that is\n * what makes the pair a shape rather than two curves — so it is dropped and its\n * outgoing handle moved onto the anchor it duplicated. Leaving it in would put a\n * zero-length segment at the seam, which strokes as a dot and fills as nothing.\n */\nfunction joinArcs(first: PathSubpath, second: PathSubpath): PathSubpath {\n const head = first.anchors.slice(0, -1)\n const seam = first.anchors[first.anchors.length - 1]\n const [start, ...rest] = second.anchors\n return {\n anchors: [...head, { ...seam, outHandle: start.outHandle }, ...rest],\n closed: true,\n }\n}\n\n/** A regular star, `points` long, alternating between the two radii. */\nfunction star(\n cx: number,\n cy: number,\n outer: number,\n inner: number,\n points: number\n): PathSubpath {\n const vertices: Vector2[] = []\n for (let i = 0; i < points * 2; i++) {\n // Starts at due north, which is the only orientation anyone pictures.\n const angle = (Math.PI * i) / points - Math.PI / 2\n const radius = i % 2 === 0 ? outer : inner\n vertices.push(\n point(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle))\n )\n }\n return polyline(vertices, true)\n}\n\n/**\n * The crescent's outline: the fat edge of one circle, bitten by another.\n *\n * The two **tips** are chosen first — at −60° and 150° on the outer ring, which\n * is the tilt every moon glyph is drawn at — and the biting circle is then\n * derived from them: its centre is the point on their perpendicular bisector\n * that sits {@link BITE} away from their midpoint, on the side the bite comes\n * from. So the two arcs meet exactly, by construction rather than by adjustment,\n * and moving the tips or deepening the bite keeps them meeting.\n */\nfunction crescent(): PathSubpath {\n const cx = 12\n const cy = 12\n const radius = 8.5\n /** How far the biting circle's centre sits off the chord's midpoint. */\n const BITE = 3.5\n\n const tip = (degrees: number): Vector2 => {\n const angle = (degrees * Math.PI) / 180\n return point(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle))\n }\n const first = tip(-60)\n const second = tip(150)\n\n // The chord's midpoint, pushed along its own perpendicular toward the\n // up-and-left, which is where a crescent's bite comes from.\n const midX = (first.x + second.x) / 2\n const midY = (first.y + second.y) / 2\n const span = Math.hypot(second.x - first.x, second.y - first.y)\n const normalX = -(second.y - first.y) / span\n const normalY = (second.x - first.x) / span\n const biteX = midX + normalX * BITE\n const biteY = midY + normalY * BITE\n const biteRadius = Math.hypot(first.x - biteX, first.y - biteY)\n const angleOf = (p: Vector2): number =>\n (Math.atan2(p.y - biteY, p.x - biteX) * 180) / Math.PI\n\n return joinArcs(\n // The outer edge: the long way round, through the east and the south.\n arc(cx, cy, radius, -60, 150),\n // …and back through the biting circle's own east and south, which lies\n // inside the ring above and is therefore the concave side.\n arc(biteX, biteY, biteRadius, angleOf(second), angleOf(first))\n )\n}\n\n// --- The catalogue ---------------------------------------------------------\n\n/** The default stroke weight: two units of twenty-four, as lucide draws. */\nconst WEIGHT = 2.2\n\n/**\n * Every glyph, in the 24-unit author box.\n *\n * Built at module load rather than per draw, exactly as the cursor's artwork is:\n * these are fixed drawings with nothing to recompute, so re-deriving a few dozen\n * control points every frame would buy nothing.\n */\nconst ARTWORK: Record<ControlIcon, ControlIconArtwork> = {\n none: EMPTY_ARTWORK,\n\n check: {\n strokes: [polyline([point(5, 12.5), point(9.75, 17.5), point(19, 6.5)])],\n fills: [],\n weight: WEIGHT,\n },\n\n close: {\n strokes: [\n polyline([point(6.5, 6.5), point(17.5, 17.5)]),\n polyline([point(17.5, 6.5), point(6.5, 17.5)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n // A filled disc — the mark for a switch whose states are \"armed\" and \"not\",\n // where a tick would claim something was completed.\n dot: { strokes: [], fills: [circle(12, 12, 4.5)], weight: 0 },\n\n plus: {\n strokes: [\n polyline([point(12, 5.5), point(12, 18.5)]),\n polyline([point(5.5, 12), point(18.5, 12)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n minus: {\n strokes: [polyline([point(5.5, 12), point(18.5, 12)])],\n fills: [],\n weight: WEIGHT,\n },\n\n // Filled, because a play triangle has no interior to leave empty — an\n // outlined one reads as a \"next\" chevron rather than as play.\n play: {\n strokes: [],\n fills: [polyline([point(7.5, 5), point(19, 12), point(7.5, 19)], true)],\n weight: 0,\n },\n\n pause: {\n strokes: [],\n fills: [\n polyline(\n [point(8, 5.5), point(11, 5.5), point(11, 18.5), point(8, 18.5)],\n true\n ),\n polyline(\n [point(13, 5.5), point(16, 5.5), point(16, 18.5), point(13, 18.5)],\n true\n ),\n ],\n weight: 0,\n },\n\n // The ring opens 60° at the top, centred on the stem — the IEC 5009 symbol\n // every device on earth wears, and the reason the gap is stated in degrees\n // rather than drawn: it is a fact about the symbol, not about this drawing.\n power: {\n strokes: [\n arc(12, 12.5, 7, -60, 240),\n polyline([point(12, 3.5), point(12, 11.5)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n sun: {\n strokes: [\n circle(12, 12, 4.5),\n ...Array.from({ length: 8 }, (_, i) => {\n const angle = (Math.PI * i) / 4\n const cos = Math.cos(angle)\n const sin = Math.sin(angle)\n return polyline([\n point(12 + cos * 7.5, 12 + sin * 7.5),\n point(12 + cos * 9.75, 12 + sin * 9.75),\n ])\n }),\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n // A crescent as two arcs of two different circles rather than one circle cut\n // out of another: a cut needs an even-odd fill the renderer would have to be\n // told about, and the outline is the same shape either way.\n //\n // The second circle is *derived* from where the two tips sit rather than\n // eyeballed, which is the only way the two arcs meet exactly — a crescent\n // whose halves miss each other by a unit closes with a straight nick across\n // its own point. See {@link crescent}.\n moon: { strokes: [], fills: [crescent()], weight: 0 },\n\n star: { strokes: [], fills: [star(12, 12, 8.5, 3.6, 5)], weight: 0 },\n\n // Two lobes meeting at a point. Written as one closed contour of four cubics\n // because a heart is a *shape*, and splitting it into halves would leave a\n // seam down the middle of any stroke drawn on it.\n heart: {\n strokes: [],\n fills: [\n {\n anchors: [\n {\n point: point(12, 20),\n inHandle: point(15.6, 17),\n outHandle: point(8.4, 17),\n },\n {\n point: point(4, 11.6),\n inHandle: point(5.4, 15.4),\n outHandle: point(2.2, 9.6),\n },\n {\n point: point(7.8, 5.5),\n inHandle: point(4.2, 5.5),\n outHandle: point(10.4, 5.5),\n },\n {\n point: point(12, 8.6),\n inHandle: point(11.2, 6.6),\n outHandle: point(12.8, 6.6),\n },\n {\n point: point(16.2, 5.5),\n inHandle: point(13.6, 5.5),\n outHandle: point(19.8, 5.5),\n },\n {\n point: point(20, 11.6),\n inHandle: point(21.8, 9.6),\n outHandle: point(18.6, 15.4),\n },\n ],\n closed: true,\n },\n ],\n weight: 0,\n },\n\n lock: {\n strokes: [\n // The shackle: a half turn, open at the bottom where it meets the body.\n arc(12, 10, 4, 180, 360),\n // The body, as a rounded box drawn from its four corners.\n {\n anchors: [\n {\n point: point(6.25, 10.5),\n inHandle: point(6.25, 10.9),\n outHandle: null,\n },\n {\n point: point(17.75, 10.5),\n inHandle: null,\n outHandle: point(18.5, 10.5),\n },\n {\n point: point(18.5, 11.25),\n inHandle: point(18.5, 10.85),\n outHandle: null,\n },\n {\n point: point(18.5, 18.75),\n inHandle: null,\n outHandle: point(18.5, 19.5),\n },\n {\n point: point(17.75, 19.5),\n inHandle: point(18.15, 19.5),\n outHandle: null,\n },\n {\n point: point(6.25, 19.5),\n inHandle: null,\n outHandle: point(5.5, 19.5),\n },\n {\n point: point(5.5, 18.75),\n inHandle: point(5.5, 19.15),\n outHandle: null,\n },\n {\n point: point(5.5, 11.25),\n inHandle: null,\n outHandle: point(5.5, 10.5),\n },\n ],\n closed: true,\n },\n ],\n fills: [],\n weight: WEIGHT,\n },\n\n bolt: {\n strokes: [],\n fills: [\n polyline(\n [\n point(13.5, 2.5),\n point(5, 13.5),\n point(11, 13.5),\n point(10.5, 21.5),\n point(19, 10.5),\n point(13, 10.5),\n ],\n true\n ),\n ],\n weight: 0,\n },\n\n arrowRight: {\n strokes: [\n polyline([point(4.5, 12), point(19, 12)]),\n polyline([point(13, 6), point(19, 12), point(13, 18)]),\n ],\n fills: [],\n weight: WEIGHT,\n },\n}\n\n/** The glyph a key names, or the empty one for a key this build doesn't know. */\nfunction artworkFor(icon: ControlIcon): ControlIconArtwork {\n return ARTWORK[icon] ?? EMPTY_ARTWORK\n}\n\n/**\n * The glyph mapped onto a `size` × `size` box **centred on the origin and\n * y-up** — the space a node draws in.\n *\n * The flip is the whole of the difference between the author box and the\n * renderer's, exactly as it is for the cursor: glyphs are drawn y-down because\n * that is what every SVG box and every icon set uses, and a node's own space\n * counts upward.\n *\n * The weight comes back in pixels so the caller can hand it straight to a\n * stroke. It scales with the glyph, which is the point: an icon in a switch knob\n * is drawn at whatever size the knob came out, and a fixed pixel weight would be\n * a hairline on a big control and a smudge on a small one.\n */\nexport function controlIconPixels(\n icon: ControlIcon,\n size: number\n): { strokes: VectorPath; fills: VectorPath; weight: number } {\n const artwork = artworkFor(icon)\n if (!(size > 0)) return { strokes: [], fills: [], weight: 0 }\n const scale = size / CONTROL_ICON_UNITS\n const onto = (p: Vector2): Vector2 => ({\n x: p.x * scale - size / 2,\n y: size / 2 - p.y * scale,\n })\n return {\n strokes: pathOps.map(artwork.strokes, onto),\n fills: pathOps.map(artwork.fills, onto),\n weight: artwork.weight * scale,\n }\n}\n\n/**\n * The glyph as SVG `d` strings in the 24-unit box, for the studio's own chrome.\n *\n * What the icon dropdown draws its options with, so a mark corrected here is\n * corrected in the panel too — the same bargain `cursorArtworkData` strikes, and\n * for the same reason: a hand-drawn approximation in the picker is a picture of\n * an icon the node does not draw.\n */\nexport function controlIconData(icon: ControlIcon): {\n strokes: string\n fills: string\n weight: number\n} {\n const artwork = artworkFor(icon)\n return {\n strokes: pathOps.fromAnchors(artwork.strokes),\n fills: pathOps.fromAnchors(artwork.fills),\n weight: artwork.weight,\n }\n}\n\n/** Whether a stored value names a glyph this build can draw. */\nexport function isControlIcon(value: unknown): value is ControlIcon {\n return (\n typeof value === \"string\" &&\n (CONTROL_ICONS as readonly string[]).includes(value)\n )\n}\n"]}
@@ -21,7 +21,7 @@
21
21
  * button — so the alternative is the same code twice. What they genuinely share
22
22
  * is exactly this: a box, a style, and a schedule of sounds.
23
23
  */
24
- import { Node2D, type AudioScope, type Node2DProps } from "@motionscript/core";
24
+ import { Node2D, type AudioScope, type Node2DProps } from "@motionscript/sdk";
25
25
  /**
26
26
  * One sound a node's chain fires: a moment, a file, and the window of it played.
27
27
  *
@@ -1 +1 @@
1
- {"version":3,"file":"control-node.d.ts","sourceRoot":"","sources":["../../src/kit/control-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EACL,MAAM,EAEN,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAA;AAE3B;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAA;IACV,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAA;IACX,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,8DAA8D;IAC9D,MAAM,EAAE,QAAQ,EAAE,CAAA;CACnB;AAED;;;GAGG;AACH,8BAAsB,WAAW,CAC/B,CAAC,SAAS,gBAAgB,CAC1B,SAAQ,MAAM,CAAC,CAAC,CAAC;IACkB,MAAM,EAAE,QAAQ,EAAE,CAAA;IAE5C,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;CAiB/C"}
1
+ {"version":3,"file":"control-node.d.ts","sourceRoot":"","sources":["../../src/kit/control-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EACL,MAAM,EAEN,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAA;AAE1B;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAA;IACV,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAA;IACX,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,8DAA8D;IAC9D,MAAM,EAAE,QAAQ,EAAE,CAAA;CACnB;AAED;;;GAGG;AACH,8BAAsB,WAAW,CAC/B,CAAC,SAAS,gBAAgB,CAC1B,SAAQ,MAAM,CAAC,CAAC,CAAC;IACkB,MAAM,EAAE,QAAQ,EAAE,CAAA;IAE5C,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;CAiB/C"}
@@ -27,7 +27,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
27
27
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
28
28
  return c > 3 && r && Object.defineProperty(target, key, r), r;
29
29
  };
30
- import { Node2D, property, } from "@motionscript/core";
30
+ import { Node2D, property, } from "@motionscript/sdk";
31
31
  /**
32
32
  * A node with a sound schedule. Abstract: what it *draws* is its subclass's
33
33
  * business, and there is no sensible drawing for "a control".
@@ -1 +1 @@
1
- {"version":3,"file":"control-node.js","sourceRoot":"","sources":["../../src/kit/control-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;AAEH,OAAO,EACL,MAAM,EACN,QAAQ,GAGT,MAAM,oBAAoB,CAAA;AA+B3B;;;GAGG;AACH,MAAM,OAAgB,WAEpB,SAAQ,MAAS;IAGR,YAAY,CAAC,KAAiB;QACrC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,GAAG;gBAAE,SAAQ;YACtB,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAA;YAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC9E,KAAK,CAAC,IAAI,CAAC;gBACT,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,6CAA6C;gBAC7C,KAAK,EAAE,QAAQ;gBACf,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,yEAAyE;gBACzE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF;AAnBoC;IAAlC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;2CAA2B","sourcesContent":["/**\n * The base the two UI controls share: a node that can **make a noise when a\n * command runs**.\n *\n * ## Declared, not fired\n *\n * Playing the sound from the command's own step cannot work: a seek jumps\n * straight to a frame without running the steps before it, and an export renders\n * the same frame many times, so a step that started a clip would play the click\n * zero times, once, or forty times depending on how the playhead arrived. So a\n * node is handed its whole schedule at construction — \"at this second of the\n * clip, play this file\" — and declares it, which keeps the mix a pure function\n * of the document.\n *\n * The cues are built by the builder rather than here, because only it holds the\n * resolved asset URLs and the node's spawn time (see `nodes/ui-kit/sound-cues.ts`).\n *\n * ## Why the base class exists at all\n *\n * Two nodes need this and neither is a kind of the other — a switch is not a\n * button — so the alternative is the same code twice. What they genuinely share\n * is exactly this: a box, a style, and a schedule of sounds.\n */\n\nimport {\n Node2D,\n property,\n type AudioScope,\n type Node2DProps,\n} from \"@motionscript/core\"\n\n/**\n * One sound a node's chain fires: a moment, a file, and the window of it played.\n *\n * `at` is a second of the **clip's** clock rather than of the node's own, because\n * that is what an `AudioRequest.startAt` is. The builder adds the node's spawn\n * delay for exactly this reason.\n */\nexport interface SoundCue {\n /** Second of the clip's clock the effect fires at. */\n at: number\n /** The resolved source URL. Never an asset id: the node cannot resolve one. */\n src: string\n /** In-point inside the source, in seconds. */\n trimStart: number\n /**\n * Out-point, or `0` for \"to the end of the source\" — the same sentinel\n * {@link CommandSound.trimEnd} carries, passed through unresolved because the\n * length is a fact only the asset catalog holds.\n */\n trimEnd: number\n /** Linear gain, `0`–`1`. */\n volume: number\n}\n\nexport interface ControlNodeProps extends Node2DProps {\n /** The node's whole audio schedule — see {@link SoundCue}. */\n sounds: SoundCue[]\n}\n\n/**\n * A node with a sound schedule. Abstract: what it *draws* is its subclass's\n * business, and there is no sensible drawing for \"a control\".\n */\nexport abstract class ControlNode<\n P extends ControlNodeProps,\n> extends Node2D<P> {\n @property({ default: [] }) declare sounds: SoundCue[]\n\n override declareAudio(audio: AudioScope): void {\n for (const cue of this.sounds) {\n if (!cue.src) continue\n const trimmed = Number.isFinite(cue.trimEnd) && cue.trimEnd > 0\n const length = trimmed ? cue.trimEnd : audio.catalog.getMediaDuration(cue.src)\n audio.clip({\n src: cue.src,\n at: cue.at,\n // A click outlives the control that made it.\n until: Infinity,\n volume: cue.volume,\n trimStart: cue.trimStart,\n // An unknown length leaves the clip open rather than pinning it to zero.\n ...(Number.isFinite(length) && length > 0 ? { trimEnd: length } : {}),\n })\n }\n }\n}\n"]}
1
+ {"version":3,"file":"control-node.js","sourceRoot":"","sources":["../../src/kit/control-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;AAEH,OAAO,EACL,MAAM,EACN,QAAQ,GAGT,MAAM,mBAAmB,CAAA;AA+B1B;;;GAGG;AACH,MAAM,OAAgB,WAEpB,SAAQ,MAAS;IAGR,YAAY,CAAC,KAAiB;QACrC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,GAAG;gBAAE,SAAQ;YACtB,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAA;YAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC9E,KAAK,CAAC,IAAI,CAAC;gBACT,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,6CAA6C;gBAC7C,KAAK,EAAE,QAAQ;gBACf,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,yEAAyE;gBACzE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF;AAnBoC;IAAlC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;2CAA2B","sourcesContent":["/**\n * The base the two UI controls share: a node that can **make a noise when a\n * command runs**.\n *\n * ## Declared, not fired\n *\n * Playing the sound from the command's own step cannot work: a seek jumps\n * straight to a frame without running the steps before it, and an export renders\n * the same frame many times, so a step that started a clip would play the click\n * zero times, once, or forty times depending on how the playhead arrived. So a\n * node is handed its whole schedule at construction — \"at this second of the\n * clip, play this file\" — and declares it, which keeps the mix a pure function\n * of the document.\n *\n * The cues are built by the builder rather than here, because only it holds the\n * resolved asset URLs and the node's spawn time (see `nodes/ui-kit/sound-cues.ts`).\n *\n * ## Why the base class exists at all\n *\n * Two nodes need this and neither is a kind of the other — a switch is not a\n * button — so the alternative is the same code twice. What they genuinely share\n * is exactly this: a box, a style, and a schedule of sounds.\n */\n\nimport {\n Node2D,\n property,\n type AudioScope,\n type Node2DProps,\n} from \"@motionscript/sdk\"\n\n/**\n * One sound a node's chain fires: a moment, a file, and the window of it played.\n *\n * `at` is a second of the **clip's** clock rather than of the node's own, because\n * that is what an `AudioRequest.startAt` is. The builder adds the node's spawn\n * delay for exactly this reason.\n */\nexport interface SoundCue {\n /** Second of the clip's clock the effect fires at. */\n at: number\n /** The resolved source URL. Never an asset id: the node cannot resolve one. */\n src: string\n /** In-point inside the source, in seconds. */\n trimStart: number\n /**\n * Out-point, or `0` for \"to the end of the source\" — the same sentinel\n * {@link CommandSound.trimEnd} carries, passed through unresolved because the\n * length is a fact only the asset catalog holds.\n */\n trimEnd: number\n /** Linear gain, `0`–`1`. */\n volume: number\n}\n\nexport interface ControlNodeProps extends Node2DProps {\n /** The node's whole audio schedule — see {@link SoundCue}. */\n sounds: SoundCue[]\n}\n\n/**\n * A node with a sound schedule. Abstract: what it *draws* is its subclass's\n * business, and there is no sensible drawing for \"a control\".\n */\nexport abstract class ControlNode<\n P extends ControlNodeProps,\n> extends Node2D<P> {\n @property({ default: [] }) declare sounds: SoundCue[]\n\n override declareAudio(audio: AudioScope): void {\n for (const cue of this.sounds) {\n if (!cue.src) continue\n const trimmed = Number.isFinite(cue.trimEnd) && cue.trimEnd > 0\n const length = trimmed ? cue.trimEnd : audio.catalog.getMediaDuration(cue.src)\n audio.clip({\n src: cue.src,\n at: cue.at,\n // A click outlives the control that made it.\n until: Infinity,\n volume: cue.volume,\n trimStart: cue.trimStart,\n // An unknown length leaves the clip open rather than pinning it to zero.\n ...(Number.isFinite(length) && length > 0 ? { trimEnd: length } : {}),\n })\n }\n }\n}\n"]}
@@ -36,7 +36,7 @@
36
36
  * *verbatim* — they are the artwork as drawn, in their own viewBoxes, and
37
37
  * nobody has to re-derive a coordinate to move one into this module.
38
38
  */
39
- import { type VectorPath } from "@motionscript/core";
39
+ import { type VectorPath } from "@motionscript/sdk";
40
40
  /**
41
41
  * The pointers, in the order the dropdown offers them.
42
42
  *
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-outline.d.ts","sourceRoot":"","sources":["../../src/kit/cursor-outline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAW,KAAK,UAAU,EAAgB,MAAM,oBAAoB,CAAA;AAE3E;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,iCAAkC,CAAA;AAE3D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,sBAAuB,CAAA;AAEjD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,UAAsB,CAAA;AAExD,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,EAAE,WAAuB,CAAA;AAE1D,kEAAkE;AAClE,eAAO,MAAM,YAAY,KAAK,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,KAAK,CAAA;AAE7B,iDAAiD;AACjD,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,CAExD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,CAEzD;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,OAAO,EAAE,UAAU,CAAA;IACnB,sEAAsE;IACtE,IAAI,EAAE,UAAU,CAAA;CACjB;AA2FD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,aAAa,CAgBf;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,WAAW,GACjB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAMnC;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAKhE;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAKlE"}
1
+ {"version":3,"file":"cursor-outline.d.ts","sourceRoot":"","sources":["../../src/kit/cursor-outline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAW,KAAK,UAAU,EAAgB,MAAM,mBAAmB,CAAA;AAE1E;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,iCAAkC,CAAA;AAE3D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,sBAAuB,CAAA;AAEjD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,UAAsB,CAAA;AAExD,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,EAAE,WAAuB,CAAA;AAE1D,kEAAkE;AAClE,eAAO,MAAM,YAAY,KAAK,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,KAAK,CAAA;AAE7B,iDAAiD;AACjD,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,CAExD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,CAEzD;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,OAAO,EAAE,UAAU,CAAA;IACnB,sEAAsE;IACtE,IAAI,EAAE,UAAU,CAAA;CACjB;AA2FD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,aAAa,CAgBf;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,WAAW,GACjB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAMnC;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAKhE;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAKlE"}
@@ -36,7 +36,7 @@
36
36
  * *verbatim* — they are the artwork as drawn, in their own viewBoxes, and
37
37
  * nobody has to re-derive a coordinate to move one into this module.
38
38
  */
39
- import { pathOps } from "@motionscript/core";
39
+ import { pathOps } from "@motionscript/sdk";
40
40
  /**
41
41
  * The pointers, in the order the dropdown offers them.
42
42
  *