@field/cascade 0.2.22 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/AGENTS.md +47 -7
  2. package/ARCHITECTURE.md +30 -2
  3. package/CHANGELOG.md +89 -0
  4. package/DESIGN.md +10 -5
  5. package/README.md +103 -7
  6. package/dist/assets/CodeEditor-BADFbTJS.js +623 -0
  7. package/dist/assets/CodePanel-faK6PRfz.js +2 -0
  8. package/dist/assets/CustomNodeDialog-DhlKuviy.js +1 -0
  9. package/dist/assets/{ExportDialog-DWN4nhXI.js → ExportDialog-BJu2Bpvv.js} +2 -2
  10. package/dist/assets/ProjectSettings-D6a6kjqR.js +2 -0
  11. package/dist/assets/SettingsDialog-DJZdIvLC.js +1 -0
  12. package/dist/assets/VersionHistoryDialog-C1X3HOhc.js +3 -0
  13. package/dist/assets/{core-Bji4aZUU.js → core-CiuiuWZi.js} +29 -38
  14. package/dist/assets/{cssMode-B6Z_Q1Kh.js → cssMode-D-NwZSMJ.js} +1 -1
  15. package/dist/assets/{editor.api-jMoW_43X.js → editor.api-DT3WEvBd.js} +1 -1
  16. package/dist/assets/{freemarker2-DvvPV6m5.js → freemarker2-eKNYQaiz.js} +1 -1
  17. package/dist/assets/geo-DUvVbLnx.js +1 -0
  18. package/dist/assets/{handlebars-B8rfuSIa.js → handlebars-C2w1ggK2.js} +1 -1
  19. package/dist/assets/{html-DyHm6JCp.js → html-DQb41jyo.js} +1 -1
  20. package/dist/assets/{htmlMode-E9XLWE5u.js → htmlMode-IhNlh6Lv.js} +1 -1
  21. package/dist/assets/{image-BUcQC7PG.js → image-DMCXBY-_.js} +26 -40
  22. package/dist/assets/index-BDV5xGBZ.css +1 -0
  23. package/dist/assets/index-HTCN44kj.js +212 -0
  24. package/dist/assets/index-client-BoJgsN9M.js +1 -0
  25. package/dist/assets/{javascript-C_bM5PCN.js → javascript-BIT6jMLC.js} +1 -1
  26. package/dist/assets/{jsonMode-BdyVS7G4.js → jsonMode-CNfyB1ro.js} +1 -1
  27. package/dist/assets/{legacy-DIu3XRwl.js → legacy-CAj2_7QE.js} +2 -2
  28. package/dist/assets/{liquid-CDkn3spA.js → liquid-CmSmJmOG.js} +1 -1
  29. package/dist/assets/{lspLanguageFeatures-AB5DMAsr.js → lspLanguageFeatures-BqMm3uMP.js} +1 -1
  30. package/dist/assets/{mdx-BvH_NjDN.js → mdx-6r6YgOFw.js} +1 -1
  31. package/dist/assets/{nodeTypeUtils-CweA3NHd.js → nodeTypeUtils-BBA1JqHx.js} +1 -1
  32. package/dist/assets/{python-B7uii4fi.js → python-x1H0TQuI.js} +1 -1
  33. package/dist/assets/{razor-Z48fWdJc.js → razor-Dzl1vZFm.js} +1 -1
  34. package/dist/assets/{tsMode-BDgacVG4.js → tsMode-n6DMMe3a.js} +1 -1
  35. package/dist/assets/{typescript-Derb6Oqa.js → typescript-ziEz65xN.js} +1 -1
  36. package/dist/assets/{workers-BtoMX_pm.js → workers-D-qUdp-r.js} +1 -1
  37. package/dist/assets/{xml-B1CaFSrG.js → xml-DMZjt5lE.js} +1 -1
  38. package/dist/assets/{yaml-HmIeA0KH.js → yaml-DFe5qZSO.js} +1 -1
  39. package/dist/cli/index.js +16194 -10195
  40. package/dist/cli/runtime/io.ts +93 -7
  41. package/dist/contracts/animation.d.ts +40 -0
  42. package/dist/contracts/animation.js +14 -0
  43. package/dist/contracts/definition.d.ts +39 -1
  44. package/dist/contracts/document.d.ts +15 -0
  45. package/dist/contracts/index.d.ts +1 -0
  46. package/dist/contracts/index.js +1 -0
  47. package/dist/contracts/validate.d.ts +10 -1
  48. package/dist/contracts/validate.js +9 -1
  49. package/dist/graphs/default.cascade +1 -1
  50. package/dist/index.html +5 -5
  51. package/dist/io.d.ts +196 -0
  52. package/dist/io.js +303 -0
  53. package/dist/net.d.ts +1 -0
  54. package/dist/net.js +28 -0
  55. package/dist/runtime/animation/channel.d.ts +108 -0
  56. package/dist/runtime/animation/channel.js +204 -0
  57. package/dist/runtime/animation/frameRange.d.ts +78 -0
  58. package/dist/runtime/animation/frameRange.js +76 -0
  59. package/dist/runtime/animation/index.d.ts +10 -0
  60. package/dist/runtime/animation/index.js +8 -0
  61. package/dist/runtime/builtins/core/random.d.ts +1 -1
  62. package/dist/runtime/builtins/core/remap.d.ts +1 -1
  63. package/dist/runtime/builtins/geo/copyToPoints.d.ts +1 -1
  64. package/dist/runtime/builtins/geo/copyToPoints.js +1 -1
  65. package/dist/runtime/builtins/geo/generators.d.ts +1 -1
  66. package/dist/runtime/builtins/geo/merge.d.ts +1 -1
  67. package/dist/runtime/builtins/geo/svgExport.d.ts +1 -1
  68. package/dist/runtime/builtins/geo/svgExport.js +1 -1
  69. package/dist/runtime/builtins/geo/transform.d.ts +1 -1
  70. package/dist/runtime/builtins/geo/transform.js +1 -1
  71. package/dist/runtime/definition/architecture.d.ts +1 -1
  72. package/dist/runtime/definition/extract.d.ts +1 -1
  73. package/dist/runtime/definition/extract.js +1 -1
  74. package/dist/runtime/error.d.ts +1 -1
  75. package/dist/runtime/expressions/evaluator.d.ts +53 -0
  76. package/dist/runtime/expressions/evaluator.js +193 -0
  77. package/dist/runtime/expressions/index.d.ts +15 -0
  78. package/dist/runtime/expressions/index.js +12 -0
  79. package/dist/runtime/expressions/math.d.ts +75 -0
  80. package/dist/runtime/expressions/math.js +140 -0
  81. package/dist/runtime/expressions/preprocess.d.ts +33 -0
  82. package/dist/runtime/expressions/preprocess.js +102 -0
  83. package/dist/runtime/expressions/scope.d.ts +27 -0
  84. package/dist/runtime/expressions/scope.js +10 -0
  85. package/dist/runtime/expressions/time.d.ts +54 -0
  86. package/dist/runtime/expressions/time.js +71 -0
  87. package/dist/runtime/expressions/types.d.ts +66 -0
  88. package/dist/runtime/expressions/types.js +9 -0
  89. package/dist/runtime/geometry/attributes.d.ts +2 -2
  90. package/dist/runtime/geometry/attributes.js +1 -1
  91. package/dist/runtime/geometry/builder.d.ts +1 -1
  92. package/dist/runtime/geometry/builder.js +1 -1
  93. package/dist/runtime/geometry/copy.d.ts +1 -1
  94. package/dist/runtime/geometry/copy.js +1 -1
  95. package/dist/runtime/geometry/generate.d.ts +1 -1
  96. package/dist/runtime/geometry/groups.d.ts +1 -1
  97. package/dist/runtime/geometry/groups.js +1 -1
  98. package/dist/runtime/geometry/matrix.d.ts +1 -1
  99. package/dist/runtime/geometry/merge.d.ts +1 -1
  100. package/dist/runtime/geometry/merge.js +1 -1
  101. package/dist/runtime/geometry/primitives.d.ts +1 -1
  102. package/dist/runtime/geometry/primitives.js +1 -1
  103. package/dist/runtime/geometry/promote.d.ts +1 -1
  104. package/dist/runtime/geometry/promote.js +1 -1
  105. package/dist/runtime/geometry/resample.d.ts +1 -1
  106. package/dist/runtime/geometry/resample.js +1 -1
  107. package/dist/runtime/geometry/svg.d.ts +1 -1
  108. package/dist/runtime/geometry/svg.js +1 -1
  109. package/dist/runtime/geometry/transform.d.ts +1 -1
  110. package/dist/runtime/geometry/transform.js +1 -1
  111. package/dist/runtime/index.d.ts +4 -1
  112. package/dist/runtime/index.js +4 -1
  113. package/dist/runtime/params/animator.d.ts +74 -0
  114. package/dist/runtime/params/animator.js +137 -0
  115. package/dist/runtime/params/index.d.ts +11 -0
  116. package/dist/runtime/params/index.js +9 -0
  117. package/dist/runtime/params/resolve.d.ts +73 -0
  118. package/dist/runtime/params/resolve.js +62 -0
  119. package/dist/runtime/runtime.d.ts +22 -0
  120. package/dist/runtime/runtime.js +242 -14
  121. package/dist/runtime/types.d.ts +30 -4
  122. package/dist/shell.d.ts +3 -3
  123. package/doc/NODE_REFERENCE.md +395 -0
  124. package/doc/PROJECT_AUTHORING.md +148 -6
  125. package/package.json +26 -3
  126. package/dist/assets/CodeEditor-DoaNEUaM.js +0 -641
  127. package/dist/assets/CodePanel-B0_2XJ-t.js +0 -2
  128. package/dist/assets/CustomNodeDialog-026lzecD.js +0 -1
  129. package/dist/assets/ProjectSettings-BzT164Yx.js +0 -2
  130. package/dist/assets/SettingsDialog-DmHb1V0r.js +0 -1
  131. package/dist/assets/VersionHistoryDialog-hH6VsXLX.js +0 -3
  132. package/dist/assets/geo-CXmCtzMM.js +0 -2
  133. package/dist/assets/index-BXYXSdgh.js +0 -224
  134. package/dist/assets/index-CrNke7SW.css +0 -1
  135. package/dist/assets/index-client-DN_FvjN8.js +0 -1
  136. package/dist/assets/quill-DjZ69wL_.js +0 -121
  137. package/dist/cli/index.js.map +0 -7
  138. package/dist/contracts/capabilities.d.ts.map +0 -1
  139. package/dist/contracts/capabilities.js.map +0 -1
  140. package/dist/contracts/color.d.ts.map +0 -1
  141. package/dist/contracts/color.js.map +0 -1
  142. package/dist/contracts/definition.d.ts.map +0 -1
  143. package/dist/contracts/definition.js.map +0 -1
  144. package/dist/contracts/document.d.ts.map +0 -1
  145. package/dist/contracts/document.js.map +0 -1
  146. package/dist/contracts/geometry.d.ts.map +0 -1
  147. package/dist/contracts/geometry.js.map +0 -1
  148. package/dist/contracts/index.d.ts.map +0 -1
  149. package/dist/contracts/index.js.map +0 -1
  150. package/dist/contracts/schema.d.ts.map +0 -1
  151. package/dist/contracts/schema.js.map +0 -1
  152. package/dist/contracts/validate.d.ts.map +0 -1
  153. package/dist/contracts/validate.js.map +0 -1
  154. package/dist/contracts/values.d.ts.map +0 -1
  155. package/dist/contracts/values.js.map +0 -1
  156. package/dist/graphs/default-orig.cascade +0 -128
  157. package/dist/runtime/browser.d.ts.map +0 -1
  158. package/dist/runtime/browser.js.map +0 -1
  159. package/dist/runtime/builtins/core/index.d.ts.map +0 -1
  160. package/dist/runtime/builtins/core/index.js.map +0 -1
  161. package/dist/runtime/builtins/core/random.d.ts.map +0 -1
  162. package/dist/runtime/builtins/core/random.js.map +0 -1
  163. package/dist/runtime/builtins/core/remap.d.ts.map +0 -1
  164. package/dist/runtime/builtins/core/remap.js.map +0 -1
  165. package/dist/runtime/builtins/core/routing.d.ts.map +0 -1
  166. package/dist/runtime/builtins/core/routing.js.map +0 -1
  167. package/dist/runtime/builtins/core/structural.d.ts.map +0 -1
  168. package/dist/runtime/builtins/core/structural.js.map +0 -1
  169. package/dist/runtime/builtins/geo/copyToPoints.d.ts.map +0 -1
  170. package/dist/runtime/builtins/geo/copyToPoints.js.map +0 -1
  171. package/dist/runtime/builtins/geo/definitions.d.ts.map +0 -1
  172. package/dist/runtime/builtins/geo/definitions.js.map +0 -1
  173. package/dist/runtime/builtins/geo/generators.d.ts.map +0 -1
  174. package/dist/runtime/builtins/geo/generators.js.map +0 -1
  175. package/dist/runtime/builtins/geo/index.d.ts.map +0 -1
  176. package/dist/runtime/builtins/geo/index.js.map +0 -1
  177. package/dist/runtime/builtins/geo/merge.d.ts.map +0 -1
  178. package/dist/runtime/builtins/geo/merge.js.map +0 -1
  179. package/dist/runtime/builtins/geo/namespace.d.ts.map +0 -1
  180. package/dist/runtime/builtins/geo/namespace.js.map +0 -1
  181. package/dist/runtime/builtins/geo/svgExport.d.ts.map +0 -1
  182. package/dist/runtime/builtins/geo/svgExport.js.map +0 -1
  183. package/dist/runtime/builtins/geo/transform.d.ts.map +0 -1
  184. package/dist/runtime/builtins/geo/transform.js.map +0 -1
  185. package/dist/runtime/builtins/index.d.ts.map +0 -1
  186. package/dist/runtime/builtins/index.js.map +0 -1
  187. package/dist/runtime/definition/architecture.d.ts.map +0 -1
  188. package/dist/runtime/definition/architecture.js.map +0 -1
  189. package/dist/runtime/definition/extract.d.ts.map +0 -1
  190. package/dist/runtime/definition/extract.js.map +0 -1
  191. package/dist/runtime/error.d.ts.map +0 -1
  192. package/dist/runtime/error.js.map +0 -1
  193. package/dist/runtime/geometry/attributes.d.ts.map +0 -1
  194. package/dist/runtime/geometry/attributes.js.map +0 -1
  195. package/dist/runtime/geometry/builder.d.ts.map +0 -1
  196. package/dist/runtime/geometry/builder.js.map +0 -1
  197. package/dist/runtime/geometry/copy.d.ts.map +0 -1
  198. package/dist/runtime/geometry/copy.js.map +0 -1
  199. package/dist/runtime/geometry/generate.d.ts.map +0 -1
  200. package/dist/runtime/geometry/generate.js.map +0 -1
  201. package/dist/runtime/geometry/groups.d.ts.map +0 -1
  202. package/dist/runtime/geometry/groups.js.map +0 -1
  203. package/dist/runtime/geometry/index.d.ts.map +0 -1
  204. package/dist/runtime/geometry/index.js.map +0 -1
  205. package/dist/runtime/geometry/matrix.d.ts.map +0 -1
  206. package/dist/runtime/geometry/matrix.js.map +0 -1
  207. package/dist/runtime/geometry/merge.d.ts.map +0 -1
  208. package/dist/runtime/geometry/merge.js.map +0 -1
  209. package/dist/runtime/geometry/primitives.d.ts.map +0 -1
  210. package/dist/runtime/geometry/primitives.js.map +0 -1
  211. package/dist/runtime/geometry/promote.d.ts.map +0 -1
  212. package/dist/runtime/geometry/promote.js.map +0 -1
  213. package/dist/runtime/geometry/resample.d.ts.map +0 -1
  214. package/dist/runtime/geometry/resample.js.map +0 -1
  215. package/dist/runtime/geometry/svg.d.ts.map +0 -1
  216. package/dist/runtime/geometry/svg.js.map +0 -1
  217. package/dist/runtime/geometry/transform.d.ts.map +0 -1
  218. package/dist/runtime/geometry/transform.js.map +0 -1
  219. package/dist/runtime/index.d.ts.map +0 -1
  220. package/dist/runtime/index.js.map +0 -1
  221. package/dist/runtime/node.d.ts.map +0 -1
  222. package/dist/runtime/node.js.map +0 -1
  223. package/dist/runtime/runtime.d.ts.map +0 -1
  224. package/dist/runtime/runtime.js.map +0 -1
  225. package/dist/runtime/types.d.ts.map +0 -1
  226. package/dist/runtime/types.js.map +0 -1
  227. package/dist/shell.js.map +0 -7
  228. package/dist/stage.js.map +0 -7
@@ -1,4 +1,4 @@
1
- import { Color, isStringAttribute, } from "cascade/contracts";
1
+ import { Color, isStringAttribute, } from "@field/cascade/contracts";
2
2
  import { geometryError, numericAttribute, positionAttribute, readComponent, } from "./attributes.js";
3
3
  import { groupNames } from "./groups.js";
4
4
  import { bezierSegments, geometryBounds, isBezier, isClosed, loosePointMask, primitivePoints, } from "./primitives.js";
@@ -1,4 +1,4 @@
1
- import { type Geometry, type Mat3, type Mat4 } from "cascade/contracts";
1
+ import { type Geometry, type Mat3, type Mat4 } from "@field/cascade/contracts";
2
2
  /**
3
3
  * Transform `P`. Matrices are column-major, as the `mat3` and `mat4` types are
4
4
  * already documented to be, so a `mat3`'s third column carries the 2D
@@ -1,4 +1,4 @@
1
- import { POSITION_ATTRIBUTE, } from "cascade/contracts";
1
+ import { POSITION_ATTRIBUTE, } from "@field/cascade/contracts";
2
2
  import { attributeSet, copyAttributeArray, geometryError, positionAttribute, withAttributeSet, } from "./attributes.js";
3
3
  /**
4
4
  * Transform `P`. Matrices are column-major, as the `mat3` and `mat4` types are
@@ -1,5 +1,8 @@
1
1
  export { CascadeRuntimeError } from "./error.js";
2
+ export * from "./animation/index.js";
3
+ export * from "./expressions/index.js";
2
4
  export * from "./geometry/index.js";
3
- export { createRuntime } from "./runtime.js";
5
+ export * from "./params/index.js";
6
+ export { createRuntime, PREFLIGHT_WARNING_CODES } from "./runtime.js";
4
7
  export type * from "./types.js";
5
8
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,7 @@
1
1
  export { CascadeRuntimeError } from "./error.js";
2
+ export * from "./animation/index.js";
3
+ export * from "./expressions/index.js";
2
4
  export * from "./geometry/index.js";
3
- export { createRuntime } from "./runtime.js";
5
+ export * from "./params/index.js";
6
+ export { createRuntime, PREFLIGHT_WARNING_CODES } from "./runtime.js";
4
7
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Resolving a graph's bound parameters at a frame.
3
+ *
4
+ * `resolvePropBinding` answers "what is this one parameter worth" and owns the
5
+ * order. This is the layer above it: a graph's worth of parameters, an
6
+ * expression engine bound to that graph, and the frame they are all resolved
7
+ * at. The deterministic runtime had neither half — it read `saved.value` and
8
+ * stopped — so a definition-v1 prop carrying `$T` or a drawn curve rendered as
9
+ * a constant offline while the same document animated in Studio.
10
+ *
11
+ * It is generic over the node rather than importing the runtime's own, so this
12
+ * file has no dependency on `runtime.ts` and can be exercised on its own.
13
+ *
14
+ * Resolution is LAZY and cycle-guarded, which is not a detail: `ch('../a/x')`
15
+ * may name a parameter that is itself an expression, and resolving in node
16
+ * order would hand out last frame's value for half the graph depending on
17
+ * where the reference pointed. Pulling on demand gives the same answer
18
+ * whatever order the nodes are in, which is the whole promise of the word
19
+ * deterministic.
20
+ */
21
+ import type { PropBinding } from "./resolve.js";
22
+ /** The minimum a node must be for its parameters to be resolvable. */
23
+ export interface AnimatableNode {
24
+ readonly id: string;
25
+ /** Resolved values, written by `resolveAll`. */
26
+ readonly props: Record<string, unknown>;
27
+ readonly inputs: Record<string, unknown>;
28
+ /** Only the props that carry an expression or a channel. */
29
+ readonly bindings: Record<string, PropBinding>;
30
+ }
31
+ export interface PropAnimatorTopology<TNode extends AnimatableNode> {
32
+ readonly nodes: readonly TNode[];
33
+ node(id: string): TNode | undefined;
34
+ /** The node feeding `node`'s data input at `index`, for `opinput()`. */
35
+ inputNode(node: TNode, index: number): TNode | null;
36
+ /** A failed expression. The parameter has already fallen back to its stored
37
+ * value; this is so the host can say so rather than render a wrong number
38
+ * in silence. */
39
+ report?(nodeId: string, propName: string, error: string): void;
40
+ }
41
+ export declare class PropAnimator<TNode extends AnimatableNode> {
42
+ private readonly topology;
43
+ private readonly evaluator;
44
+ private readonly resolving;
45
+ constructor(topology: PropAnimatorTopology<TNode>);
46
+ /** True when any parameter in the graph is bound at all — so a host can skip
47
+ * the whole pass, and a graph with no animation costs nothing. */
48
+ get animated(): boolean;
49
+ setFrame(frame: number): void;
50
+ setFps(fps: number): void;
51
+ /** Write every bound parameter's value at the current frame into `props`. */
52
+ resolveAll(): void;
53
+ /**
54
+ * One parameter, at the current frame.
55
+ *
56
+ * Re-entry returns the stored value rather than throwing: a parameter whose
57
+ * expression refers back to itself is an author's mistake, and the render
58
+ * that names it is more use than the one that dies.
59
+ */
60
+ private resolve;
61
+ /**
62
+ * The host binding the expression engine reads through.
63
+ *
64
+ * A path names a parameter — `./radius`, `../blur1/amount`,
65
+ * `/root/blur1/amount` — and the last segment is always the parameter, the
66
+ * one before it the node. Anything a graph does not have resolves to null,
67
+ * which the engine turns into 0 / '' / [] per accessor rather than an
68
+ * exception: one broken reference must not take a render down.
69
+ */
70
+ private scope;
71
+ /** The node a path's leading segments name, or `from` when they name none. */
72
+ private owner;
73
+ }
74
+ //# sourceMappingURL=animator.d.ts.map
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Resolving a graph's bound parameters at a frame.
3
+ *
4
+ * `resolvePropBinding` answers "what is this one parameter worth" and owns the
5
+ * order. This is the layer above it: a graph's worth of parameters, an
6
+ * expression engine bound to that graph, and the frame they are all resolved
7
+ * at. The deterministic runtime had neither half — it read `saved.value` and
8
+ * stopped — so a definition-v1 prop carrying `$T` or a drawn curve rendered as
9
+ * a constant offline while the same document animated in Studio.
10
+ *
11
+ * It is generic over the node rather than importing the runtime's own, so this
12
+ * file has no dependency on `runtime.ts` and can be exercised on its own.
13
+ *
14
+ * Resolution is LAZY and cycle-guarded, which is not a detail: `ch('../a/x')`
15
+ * may name a parameter that is itself an expression, and resolving in node
16
+ * order would hand out last frame's value for half the graph depending on
17
+ * where the reference pointed. Pulling on demand gives the same answer
18
+ * whatever order the nodes are in, which is the whole promise of the word
19
+ * deterministic.
20
+ */
21
+ import { ExpressionEvaluator } from "../expressions/evaluator.js";
22
+ import { isBoundProp, resolvePropBinding } from "./resolve.js";
23
+ export class PropAnimator {
24
+ topology;
25
+ evaluator;
26
+ resolving = new Set();
27
+ constructor(topology) {
28
+ this.topology = topology;
29
+ this.evaluator = new ExpressionEvaluator(this.scope());
30
+ }
31
+ /** True when any parameter in the graph is bound at all — so a host can skip
32
+ * the whole pass, and a graph with no animation costs nothing. */
33
+ get animated() {
34
+ return this.topology.nodes.some((node) => Object.values(node.bindings).some((binding) => isBoundProp(binding)));
35
+ }
36
+ setFrame(frame) {
37
+ this.evaluator.setFrame(frame);
38
+ }
39
+ setFps(fps) {
40
+ this.evaluator.setFps(fps);
41
+ }
42
+ /** Write every bound parameter's value at the current frame into `props`. */
43
+ resolveAll() {
44
+ for (const node of this.topology.nodes)
45
+ for (const name of Object.keys(node.bindings))
46
+ this.resolve(node, name);
47
+ }
48
+ /**
49
+ * One parameter, at the current frame.
50
+ *
51
+ * Re-entry returns the stored value rather than throwing: a parameter whose
52
+ * expression refers back to itself is an author's mistake, and the render
53
+ * that names it is more use than the one that dies.
54
+ */
55
+ resolve(node, name) {
56
+ const binding = node.bindings[name];
57
+ if (!binding)
58
+ return node.props[name];
59
+ const key = `${node.id}.${name}`;
60
+ if (this.resolving.has(key))
61
+ return binding.value;
62
+ this.resolving.add(key);
63
+ try {
64
+ const resolved = resolvePropBinding(binding, {
65
+ frame: this.evaluator.fframe,
66
+ evaluateExpression: (expression) => this.evaluator.evaluate(expression, node),
67
+ });
68
+ if (resolved.error)
69
+ this.topology.report?.(node.id, name, resolved.error);
70
+ node.props[name] = resolved.value;
71
+ return resolved.value;
72
+ }
73
+ finally {
74
+ this.resolving.delete(key);
75
+ }
76
+ }
77
+ /**
78
+ * The host binding the expression engine reads through.
79
+ *
80
+ * A path names a parameter — `./radius`, `../blur1/amount`,
81
+ * `/root/blur1/amount` — and the last segment is always the parameter, the
82
+ * one before it the node. Anything a graph does not have resolves to null,
83
+ * which the engine turns into 0 / '' / [] per accessor rather than an
84
+ * exception: one broken reference must not take a render down.
85
+ */
86
+ scope() {
87
+ return {
88
+ resolveParam: (from, path) => {
89
+ const segments = split(path);
90
+ if (!segments.length)
91
+ return null;
92
+ const name = segments[segments.length - 1];
93
+ const owner = this.owner(from, segments.slice(0, -1));
94
+ if (!owner)
95
+ return null;
96
+ // Through `resolve`, so a reference to a keyed or expressed parameter
97
+ // reads what it is worth at this frame rather than what it was saved
98
+ // as. Reading the stored value here is the bug that makes `ch()` look
99
+ // like it works until somebody keys the parameter it points at.
100
+ if (owner.bindings[name])
101
+ return { value: this.resolve(owner, name) };
102
+ if (name in owner.props)
103
+ return { value: owner.props[name] };
104
+ if (name in owner.inputs)
105
+ return { value: owner.inputs[name] };
106
+ return null;
107
+ },
108
+ nodeExists: (from, path) => {
109
+ const segments = split(path);
110
+ if (!segments.length)
111
+ return false;
112
+ const last = segments[segments.length - 1];
113
+ if (last === "..")
114
+ return true;
115
+ return last === from.id || !!this.topology.node(last);
116
+ },
117
+ inputNode: (from, index) => this.topology.inputNode(from, index),
118
+ };
119
+ }
120
+ /** The node a path's leading segments name, or `from` when they name none. */
121
+ owner(from, segments) {
122
+ for (let i = segments.length - 1; i >= 0; i--) {
123
+ if (segments[i] === "..")
124
+ continue;
125
+ return this.topology.node(segments[i]);
126
+ }
127
+ return from;
128
+ }
129
+ }
130
+ /** Path segments, with the no-ops (`.`, empty, a trailing root slash) dropped
131
+ * but `..` kept, because it is the one that means something. */
132
+ function split(path) {
133
+ return String(path ?? "")
134
+ .split("/")
135
+ .filter((segment) => segment.length > 0 && segment !== ".");
136
+ }
137
+ //# sourceMappingURL=animator.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Parameter resolution: the order in which a parameter becomes a value.
3
+ *
4
+ * One module, one order, both hosts. See ./resolve.ts for why evaluation
5
+ * itself is a callback rather than a dependency.
6
+ */
7
+ export { PropAnimator } from "./animator.js";
8
+ export type { AnimatableNode, PropAnimatorTopology } from "./animator.js";
9
+ export { isBoundProp, resolvePropBinding, } from "./resolve.js";
10
+ export type { PropBinding, PropBindingSource, PropResolutionContext, ResolvedProp, } from "./resolve.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Parameter resolution: the order in which a parameter becomes a value.
3
+ *
4
+ * One module, one order, both hosts. See ./resolve.ts for why evaluation
5
+ * itself is a callback rather than a dependency.
6
+ */
7
+ export { PropAnimator } from "./animator.js";
8
+ export { isBoundProp, resolvePropBinding, } from "./resolve.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The one place a parameter becomes a value.
3
+ *
4
+ * Three bindings, in one order: a keyframe channel, an expression, the stored
5
+ * value. That order was implemented once, in Studio's `Node.evalParm`, which
6
+ * meant the deterministic runtime had no answer at all — a definition-v1 prop
7
+ * carrying `$T` or a drawn curve rendered as a static number offline. Copying
8
+ * `evalParm` into the runtime would have produced a second answer to the same
9
+ * question, which is exactly the two-parameter-stores mistake this codebase
10
+ * has already paid for once. So the order moved here, into the neutral
11
+ * runtime, and both hosts call it.
12
+ *
13
+ * What it deliberately does NOT own: the expression *engine*. Evaluation is
14
+ * passed in as a callback, because each host has its own scope (Studio's
15
+ * `ExpressionEngine` reaches into the compatibility graph; the runtime binds
16
+ * its own node map) and its own error bookkeeping (Studio stores the message
17
+ * on the prop for the Inspector to show). Keeping evaluation out is also what
18
+ * keeps this module dependent on nothing but the channel sampler — no cycle
19
+ * between `animation` and `expressions`, and no clock anywhere: the frame is a
20
+ * value the caller hands in, which is what keeps a cook deterministic.
21
+ */
22
+ import type { Channel } from "../animation/channel.js";
23
+ /**
24
+ * A parameter and everything bound to it. Structurally what Studio's `Prop`
25
+ * already is, and what `CascadeSerializedProp` deserialises to, so neither
26
+ * host has to build an adapter object to ask this question.
27
+ */
28
+ export interface PropBinding {
29
+ /** The stored value — what the author typed, and what the file records. */
30
+ readonly value: unknown;
31
+ readonly expression?: string | undefined;
32
+ readonly channel?: Channel | null | undefined;
33
+ }
34
+ /** Which of the three bindings actually produced the value. */
35
+ export type PropBindingSource = "channel" | "expression" | "value";
36
+ export interface ResolvedProp {
37
+ readonly value: unknown;
38
+ readonly source: PropBindingSource;
39
+ /** An expression that failed. The value has fallen back to the stored one. */
40
+ readonly error?: string;
41
+ }
42
+ export interface PropResolutionContext {
43
+ /** Fractional frame — a channel is sampled at it, and it is what the host's
44
+ * expression engine should already be set to. */
45
+ readonly frame: number;
46
+ /**
47
+ * Evaluate one expression. Omitted by a caller with no engine (a static
48
+ * inspection), in which case an expression is skipped rather than guessed
49
+ * at and the stored value stands.
50
+ */
51
+ readonly evaluateExpression?: (expression: string) => {
52
+ value: unknown;
53
+ error?: string;
54
+ } | undefined;
55
+ }
56
+ /** True when a parameter carries something beyond its stored value, and so has
57
+ * to be resolved per frame rather than read once. */
58
+ export declare function isBoundProp(binding: PropBinding | null | undefined): boolean;
59
+ /**
60
+ * Resolve a parameter at a frame.
61
+ *
62
+ * A parameter may carry both a channel and an expression, and the channel
63
+ * wins. The expression is kept, inert, and comes back when the channel is
64
+ * deleted: silently discarding what an author wrote is the worse of the two
65
+ * failures. `contracts/animation.ts` states the same rule for the document, so
66
+ * the file format and the resolver agree by construction.
67
+ *
68
+ * An empty channel resolves to nothing rather than to zero, so a parameter
69
+ * whose last key was deleted falls through to its expression or its value
70
+ * instead of snapping to the origin.
71
+ */
72
+ export declare function resolvePropBinding(binding: PropBinding, context: PropResolutionContext): ResolvedProp;
73
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The one place a parameter becomes a value.
3
+ *
4
+ * Three bindings, in one order: a keyframe channel, an expression, the stored
5
+ * value. That order was implemented once, in Studio's `Node.evalParm`, which
6
+ * meant the deterministic runtime had no answer at all — a definition-v1 prop
7
+ * carrying `$T` or a drawn curve rendered as a static number offline. Copying
8
+ * `evalParm` into the runtime would have produced a second answer to the same
9
+ * question, which is exactly the two-parameter-stores mistake this codebase
10
+ * has already paid for once. So the order moved here, into the neutral
11
+ * runtime, and both hosts call it.
12
+ *
13
+ * What it deliberately does NOT own: the expression *engine*. Evaluation is
14
+ * passed in as a callback, because each host has its own scope (Studio's
15
+ * `ExpressionEngine` reaches into the compatibility graph; the runtime binds
16
+ * its own node map) and its own error bookkeeping (Studio stores the message
17
+ * on the prop for the Inspector to show). Keeping evaluation out is also what
18
+ * keeps this module dependent on nothing but the channel sampler — no cycle
19
+ * between `animation` and `expressions`, and no clock anywhere: the frame is a
20
+ * value the caller hands in, which is what keeps a cook deterministic.
21
+ */
22
+ import { isEmptyChannel, sampleChannel } from "../animation/channel.js";
23
+ /** True when a parameter carries something beyond its stored value, and so has
24
+ * to be resolved per frame rather than read once. */
25
+ export function isBoundProp(binding) {
26
+ if (!binding)
27
+ return false;
28
+ return !!binding.expression || !isEmptyChannel(binding.channel);
29
+ }
30
+ /**
31
+ * Resolve a parameter at a frame.
32
+ *
33
+ * A parameter may carry both a channel and an expression, and the channel
34
+ * wins. The expression is kept, inert, and comes back when the channel is
35
+ * deleted: silently discarding what an author wrote is the worse of the two
36
+ * failures. `contracts/animation.ts` states the same rule for the document, so
37
+ * the file format and the resolver agree by construction.
38
+ *
39
+ * An empty channel resolves to nothing rather than to zero, so a parameter
40
+ * whose last key was deleted falls through to its expression or its value
41
+ * instead of snapping to the origin.
42
+ */
43
+ export function resolvePropBinding(binding, context) {
44
+ if (!isEmptyChannel(binding.channel)) {
45
+ const sampled = sampleChannel(binding.channel, context.frame);
46
+ if (sampled !== undefined)
47
+ return { value: sampled, source: "channel" };
48
+ }
49
+ if (binding.expression && context.evaluateExpression) {
50
+ const result = context.evaluateExpression(binding.expression);
51
+ // A failed expression falls back to the stored value and reports why. The
52
+ // alternative — a hole in the middle of a render — is the one outcome
53
+ // nobody can act on.
54
+ if (result?.error) {
55
+ return { value: binding.value, source: "value", error: result.error };
56
+ }
57
+ if (result)
58
+ return { value: result.value, source: "expression" };
59
+ }
60
+ return { value: binding.value, source: "value" };
61
+ }
62
+ //# sourceMappingURL=resolve.js.map
@@ -1,3 +1,25 @@
1
1
  import type { CascadeRuntime, CreateRuntimeOptions } from "./types.js";
2
+ /**
3
+ * Preflight codes that describe something other than "this graph cannot run
4
+ * here", so `run` proceeds and a checker reports them as warnings.
5
+ *
6
+ * False positives are worse than blindness: a validator that cries wolf gets
7
+ * ignored, and then it is no better than the one that saw nothing. So the line
8
+ * is drawn at what the diagnostic is about.
9
+ *
10
+ * `preflight-environment` is about the checker's reach — a node saying
11
+ * `runsOn: 'browser'` claims nothing about the CLI and is not defective
12
+ * because somebody validated it from a terminal.
13
+ *
14
+ * `stray-params` is about the document — values were lost on the way in, which
15
+ * is worth saying loudly and is not a reason to refuse to run: a graph with a
16
+ * leftover `params` array runs perfectly well on its defaults, which is
17
+ * precisely the problem.
18
+ *
19
+ * This set lives here rather than in the CLI because the run path and the
20
+ * check path both need it, and it was a duplicated rule that let `validate`
21
+ * and `check` pass graphs `run` then rejected.
22
+ */
23
+ export declare const PREFLIGHT_WARNING_CODES: ReadonlySet<string>;
2
24
  export declare function createRuntime(options: CreateRuntimeOptions): CascadeRuntime;
3
25
  //# sourceMappingURL=runtime.d.ts.map