@nodetool-ai/node-sdk 0.8.4-a24.2 → 0.8.4

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 (256) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/_sandbox/README.md +176 -0
  3. package/dist/_sandbox/sandbox-aws/SKILL.md +98 -0
  4. package/dist/_sandbox/sandbox-aws/package.json +40 -0
  5. package/dist/_sandbox/sandbox-chrono/SKILL.md +39 -0
  6. package/dist/_sandbox/sandbox-chrono/package.json +40 -0
  7. package/dist/_sandbox/sandbox-color/SKILL.md +35 -0
  8. package/dist/_sandbox/sandbox-color/package.json +43 -0
  9. package/dist/_sandbox/sandbox-csv/SKILL.md +50 -0
  10. package/dist/_sandbox/sandbox-csv/package.json +39 -0
  11. package/dist/_sandbox/sandbox-dates/SKILL.md +47 -0
  12. package/dist/_sandbox/sandbox-dates/package.json +41 -0
  13. package/dist/_sandbox/sandbox-decimal/SKILL.md +36 -0
  14. package/dist/_sandbox/sandbox-decimal/package.json +43 -0
  15. package/dist/_sandbox/sandbox-diff/SKILL.md +36 -0
  16. package/dist/_sandbox/sandbox-diff/package.json +39 -0
  17. package/dist/_sandbox/sandbox-docx/SKILL.md +53 -0
  18. package/dist/_sandbox/sandbox-docx/package.json +40 -0
  19. package/dist/_sandbox/sandbox-dsl/SKILL.md +137 -0
  20. package/dist/_sandbox/sandbox-dsl/package.json +413 -0
  21. package/dist/_sandbox/sandbox-dsl/sandbox/authoring.js +382 -0
  22. package/dist/_sandbox/sandbox-dsl/sandbox/core.js +382 -0
  23. package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.audio.js +12 -0
  24. package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.image.js +8 -0
  25. package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.text.js +12 -0
  26. package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.video.js +12 -0
  27. package/dist/_sandbox/sandbox-dsl/sandbox/generated/index.js +149 -0
  28. package/dist/_sandbox/sandbox-dsl/sandbox/generated/kie.dynamic_schema.js +8 -0
  29. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.audio.js +68 -0
  30. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.browser.js +8 -0
  31. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.charts.js +8 -0
  32. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.comfy.js +16 -0
  33. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.grid.js +8 -0
  34. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.channel.js +12 -0
  35. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.color.js +32 -0
  36. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.color_grading.js +44 -0
  37. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.draw.js +36 -0
  38. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.effects.js +24 -0
  39. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.enhance.js +28 -0
  40. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.filter.js +64 -0
  41. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.js +8 -0
  42. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.keyer.js +12 -0
  43. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.mask.js +16 -0
  44. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.warp.js +36 -0
  45. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.pdf.js +32 -0
  46. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.sqlite.js +8 -0
  47. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.stable_diffusion_cpp.js +8 -0
  48. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.svg.js +12 -0
  49. package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.video.download.js +8 -0
  50. package/dist/_sandbox/sandbox-dsl/sandbox/generated/messaging.discord.js +8 -0
  51. package/dist/_sandbox/sandbox-dsl/sandbox/generated/messaging.telegram.js +8 -0
  52. package/dist/_sandbox/sandbox-dsl/sandbox/generated/mistral.embeddings.js +8 -0
  53. package/dist/_sandbox/sandbox-dsl/sandbox/generated/mistral.text.js +12 -0
  54. package/dist/_sandbox/sandbox-dsl/sandbox/generated/mistral.vision.js +12 -0
  55. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.agents.js +32 -0
  56. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.audio.js +104 -0
  57. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.audio.realtime.js +28 -0
  58. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.audio.synth.js +40 -0
  59. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.blender.js +28 -0
  60. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.code.js +8 -0
  61. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.compare.js +8 -0
  62. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.constant.js +132 -0
  63. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.control.js +96 -0
  64. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.creative.js +24 -0
  65. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.data.js +12 -0
  66. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.document.js +16 -0
  67. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.entity.js +16 -0
  68. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.fake.js +12 -0
  69. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.game.js +36 -0
  70. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.generators.js +24 -0
  71. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.image.js +120 -0
  72. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.input.js +140 -0
  73. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.manimgx.js +16 -0
  74. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.model3d.js +76 -0
  75. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.output.js +8 -0
  76. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.script.js +28 -0
  77. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.sketch.js +16 -0
  78. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.storyboard.js +32 -0
  79. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.text.js +56 -0
  80. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.timeline.js +24 -0
  81. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.triggers.js +24 -0
  82. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.variable.js +12 -0
  83. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.video.js +136 -0
  84. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.app_node.js +8 -0
  85. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.base_node.js +8 -0
  86. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.subgraph.js +8 -0
  87. package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.workflow_node.js +8 -0
  88. package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.agents.js +16 -0
  89. package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.audio.js +16 -0
  90. package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.image.js +16 -0
  91. package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.text.js +16 -0
  92. package/dist/_sandbox/sandbox-dsl/sandbox/generated/vector.js +56 -0
  93. package/dist/_sandbox/sandbox-dsl/sandbox/generated/whisper_cpp.js +8 -0
  94. package/dist/_sandbox/sandbox-dsl/sandbox/generated/xai.image.js +8 -0
  95. package/dist/_sandbox/sandbox-dsl/sandbox/generated/xai.text.js +12 -0
  96. package/dist/_sandbox/sandbox-dsl/sandbox/generated/xai.vision.js +8 -0
  97. package/dist/_sandbox/sandbox-dsl/sandbox/index.js +13 -0
  98. package/dist/_sandbox/sandbox-dsl/scripts/build.mjs +116 -0
  99. package/dist/_sandbox/sandbox-epub/SKILL.md +61 -0
  100. package/dist/_sandbox/sandbox-epub/package.json +40 -0
  101. package/dist/_sandbox/sandbox-exif/SKILL.md +30 -0
  102. package/dist/_sandbox/sandbox-exif/package.json +40 -0
  103. package/dist/_sandbox/sandbox-expr/SKILL.md +28 -0
  104. package/dist/_sandbox/sandbox-expr/package.json +40 -0
  105. package/dist/_sandbox/sandbox-fabric/SKILL.md +113 -0
  106. package/dist/_sandbox/sandbox-fabric/package.json +40 -0
  107. package/dist/_sandbox/sandbox-flow/SKILL.md +131 -0
  108. package/dist/_sandbox/sandbox-flow/package.json +411 -0
  109. package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.audio.js +12 -0
  110. package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.image.js +8 -0
  111. package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.text.js +12 -0
  112. package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.video.js +12 -0
  113. package/dist/_sandbox/sandbox-flow/sandbox/generated/kie.dynamic_schema.js +8 -0
  114. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.audio.js +68 -0
  115. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.browser.js +8 -0
  116. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.charts.js +8 -0
  117. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.comfy.js +25 -0
  118. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.grid.js +8 -0
  119. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.channel.js +12 -0
  120. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.color.js +32 -0
  121. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.color_grading.js +44 -0
  122. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.draw.js +36 -0
  123. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.effects.js +24 -0
  124. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.enhance.js +28 -0
  125. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.filter.js +64 -0
  126. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.js +8 -0
  127. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.keyer.js +12 -0
  128. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.mask.js +16 -0
  129. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.warp.js +36 -0
  130. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.pdf.js +32 -0
  131. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.sqlite.js +8 -0
  132. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.stable_diffusion_cpp.js +8 -0
  133. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.svg.js +12 -0
  134. package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.video.download.js +8 -0
  135. package/dist/_sandbox/sandbox-flow/sandbox/generated/messaging.discord.js +11 -0
  136. package/dist/_sandbox/sandbox-flow/sandbox/generated/messaging.telegram.js +11 -0
  137. package/dist/_sandbox/sandbox-flow/sandbox/generated/mistral.embeddings.js +8 -0
  138. package/dist/_sandbox/sandbox-flow/sandbox/generated/mistral.text.js +12 -0
  139. package/dist/_sandbox/sandbox-flow/sandbox/generated/mistral.vision.js +12 -0
  140. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.agents.js +41 -0
  141. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.audio.js +110 -0
  142. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.audio.realtime.js +46 -0
  143. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.audio.synth.js +67 -0
  144. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.blender.js +28 -0
  145. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.code.js +11 -0
  146. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.compare.js +8 -0
  147. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.constant.js +132 -0
  148. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.control.js +165 -0
  149. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.creative.js +27 -0
  150. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.data.js +18 -0
  151. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.document.js +19 -0
  152. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.entity.js +19 -0
  153. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.fake.js +12 -0
  154. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.game.js +39 -0
  155. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.generators.js +30 -0
  156. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.image.js +126 -0
  157. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.input.js +143 -0
  158. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.manimgx.js +16 -0
  159. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.model3d.js +76 -0
  160. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.output.js +11 -0
  161. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.script.js +28 -0
  162. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.sketch.js +16 -0
  163. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.storyboard.js +35 -0
  164. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.text.js +68 -0
  165. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.timeline.js +24 -0
  166. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.triggers.js +33 -0
  167. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.variable.js +15 -0
  168. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.video.js +145 -0
  169. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.app_node.js +11 -0
  170. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.base_node.js +8 -0
  171. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.subgraph.js +11 -0
  172. package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.workflow_node.js +11 -0
  173. package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.agents.js +25 -0
  174. package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.audio.js +16 -0
  175. package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.image.js +16 -0
  176. package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.text.js +16 -0
  177. package/dist/_sandbox/sandbox-flow/sandbox/generated/vector.js +56 -0
  178. package/dist/_sandbox/sandbox-flow/sandbox/generated/whisper_cpp.js +11 -0
  179. package/dist/_sandbox/sandbox-flow/sandbox/generated/xai.image.js +8 -0
  180. package/dist/_sandbox/sandbox-flow/sandbox/generated/xai.text.js +12 -0
  181. package/dist/_sandbox/sandbox-flow/sandbox/generated/xai.vision.js +8 -0
  182. package/dist/_sandbox/sandbox-flow/sandbox/guest-core.js +35 -0
  183. package/dist/_sandbox/sandbox-flow/sandbox/index.js +10 -0
  184. package/dist/_sandbox/sandbox-flow/scripts/build.mjs +120 -0
  185. package/dist/_sandbox/sandbox-game/SKILL.md +116 -0
  186. package/dist/_sandbox/sandbox-game/package.json +36 -0
  187. package/dist/_sandbox/sandbox-game/sandbox/index.js +208 -0
  188. package/dist/_sandbox/sandbox-gif/SKILL.md +36 -0
  189. package/dist/_sandbox/sandbox-gif/package.json +43 -0
  190. package/dist/_sandbox/sandbox-html/SKILL.md +107 -0
  191. package/dist/_sandbox/sandbox-html/package.json +40 -0
  192. package/dist/_sandbox/sandbox-ics/SKILL.md +41 -0
  193. package/dist/_sandbox/sandbox-ics/package.json +40 -0
  194. package/dist/_sandbox/sandbox-jmespath/SKILL.md +26 -0
  195. package/dist/_sandbox/sandbox-jmespath/package.json +43 -0
  196. package/dist/_sandbox/sandbox-mammoth/SKILL.md +46 -0
  197. package/dist/_sandbox/sandbox-mammoth/package.json +41 -0
  198. package/dist/_sandbox/sandbox-markdown/SKILL.md +123 -0
  199. package/dist/_sandbox/sandbox-markdown/package.json +41 -0
  200. package/dist/_sandbox/sandbox-notion/SKILL.md +101 -0
  201. package/dist/_sandbox/sandbox-notion/package.json +38 -0
  202. package/dist/_sandbox/sandbox-ocr/SKILL.md +47 -0
  203. package/dist/_sandbox/sandbox-ocr/package.json +40 -0
  204. package/dist/_sandbox/sandbox-pdf/SKILL.md +47 -0
  205. package/dist/_sandbox/sandbox-pdf/package.json +39 -0
  206. package/dist/_sandbox/sandbox-pdflib/SKILL.md +56 -0
  207. package/dist/_sandbox/sandbox-pdflib/package.json +38 -0
  208. package/dist/_sandbox/sandbox-pptx/SKILL.md +42 -0
  209. package/dist/_sandbox/sandbox-pptx/package.json +40 -0
  210. package/dist/_sandbox/sandbox-pptxgen/SKILL.md +49 -0
  211. package/dist/_sandbox/sandbox-pptxgen/package.json +38 -0
  212. package/dist/_sandbox/sandbox-qr/SKILL.md +43 -0
  213. package/dist/_sandbox/sandbox-qr/package.json +42 -0
  214. package/dist/_sandbox/sandbox-rrule/SKILL.md +37 -0
  215. package/dist/_sandbox/sandbox-rrule/package.json +43 -0
  216. package/dist/_sandbox/sandbox-stats/SKILL.md +42 -0
  217. package/dist/_sandbox/sandbox-stats/package.json +43 -0
  218. package/dist/_sandbox/sandbox-subtitle/SKILL.md +38 -0
  219. package/dist/_sandbox/sandbox-subtitle/package.json +41 -0
  220. package/dist/_sandbox/sandbox-supabase/SKILL.md +108 -0
  221. package/dist/_sandbox/sandbox-supabase/package.json +39 -0
  222. package/dist/_sandbox/sandbox-tfjs/SKILL.md +76 -0
  223. package/dist/_sandbox/sandbox-tfjs/package.json +42 -0
  224. package/dist/_sandbox/sandbox-timeline/SKILL.md +647 -0
  225. package/dist/_sandbox/sandbox-timeline/package.json +46 -0
  226. package/dist/_sandbox/sandbox-timeline/sandbox/charts.js +356 -0
  227. package/dist/_sandbox/sandbox-timeline/sandbox/components.js +171 -0
  228. package/dist/_sandbox/sandbox-timeline/sandbox/index.d.ts +700 -0
  229. package/dist/_sandbox/sandbox-timeline/sandbox/index.js +1658 -0
  230. package/dist/_sandbox/sandbox-tokens/SKILL.md +46 -0
  231. package/dist/_sandbox/sandbox-tokens/package.json +40 -0
  232. package/dist/_sandbox/sandbox-twilio/SKILL.md +93 -0
  233. package/dist/_sandbox/sandbox-twilio/package.json +39 -0
  234. package/dist/_sandbox/sandbox-xlsx/SKILL.md +74 -0
  235. package/dist/_sandbox/sandbox-xlsx/package.json +40 -0
  236. package/dist/_sandbox/sandbox-xml/SKILL.md +36 -0
  237. package/dist/_sandbox/sandbox-xml/package.json +40 -0
  238. package/dist/_sandbox/sandbox-yaml/SKILL.md +48 -0
  239. package/dist/_sandbox/sandbox-yaml/package.json +41 -0
  240. package/dist/_sandbox/sandbox-zip/SKILL.md +54 -0
  241. package/dist/_sandbox/sandbox-zip/package.json +40 -0
  242. package/dist/code-node-validation.d.ts +2 -0
  243. package/dist/code-node-validation.d.ts.map +1 -1
  244. package/dist/code-node-validation.js +1 -1
  245. package/dist/code-node-validation.js.map +1 -1
  246. package/dist/pack-loader.d.ts +1 -0
  247. package/dist/pack-loader.d.ts.map +1 -1
  248. package/dist/pack-loader.js +1 -0
  249. package/dist/pack-loader.js.map +1 -1
  250. package/dist/sandbox-catalog-host.js +1 -1
  251. package/dist/sandbox-catalog-host.js.map +1 -1
  252. package/dist/sandbox-pack-discovery.d.ts +3 -0
  253. package/dist/sandbox-pack-discovery.d.ts.map +1 -1
  254. package/dist/sandbox-pack-discovery.js +7 -3
  255. package/dist/sandbox-pack-discovery.js.map +1 -1
  256. package/package.json +5 -5
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@nodetool-ai/sandbox-timeline",
3
+ "version": "0.8.4",
4
+ "description": "Author a motion-graphics timeline as code: scenes of shapes, text and images, keyframed in frames, saved in one call",
5
+ "license": "MIT",
6
+ "types": "sandbox/index.d.ts",
7
+ "nodetool": {
8
+ "apiVersion": 1,
9
+ "recommended": true,
10
+ "sandboxModules": [
11
+ {
12
+ "name": ".",
13
+ "kind": "js",
14
+ "file": "sandbox/index.js"
15
+ }
16
+ ],
17
+ "internal": [
18
+ "sandbox/charts.js",
19
+ "sandbox/components.js"
20
+ ]
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/nodetool-ai/nodetool.git",
25
+ "directory": "packages/sandbox-packs/sandbox-timeline"
26
+ },
27
+ "homepage": "https://nodetool.ai",
28
+ "bugs": {
29
+ "url": "https://github.com/nodetool-ai/nodetool/issues"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "files": [
35
+ "SKILL.md",
36
+ "sandbox"
37
+ ],
38
+ "keywords": [
39
+ "nodetool",
40
+ "nodetool-sandbox-pack",
41
+ "sandbox",
42
+ "timeline",
43
+ "motion-graphics",
44
+ "animation"
45
+ ]
46
+ }
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Chart components for the timeline authoring API. Motion graphics are often
3
+ * data — a growth bar, a balance draining, a share of a whole — so a chart
4
+ * built from the same shapes and text everything else uses composes with the
5
+ * rest of a scene: parent it, stagger it, put a `kicker`/`pill` beside it.
6
+ *
7
+ * Pure functions over the public scene API (`s.rect`, `s.text`, `s.path`,
8
+ * `s.ellipse`, `s.group`) — no access to `index.js`'s own closures (`nid`,
9
+ * `msFor`, `W`/`H`), so a chart needs nothing from the entry module beyond
10
+ * `s` itself, and it composes with anything `s` can already do (parenting,
11
+ * layout containers once those land).
12
+ *
13
+ * Every chart returns `{ group, ...pieces }`. `group` is the container clip
14
+ * — move it, parent it, `beside()` it like any other clip. The pieces
15
+ * (`bars`, `line`, `dots`, `segments`, `label`, …) are the real shapes and
16
+ * text a caller might want to touch individually; they are already in the
17
+ * document (each was made through `s.rect`/`s.text`/`s.path`), so the
18
+ * returned object is bookkeeping, not something that itself gets saved.
19
+ */
20
+
21
+ const DEFAULT_COLOR = "#34d399";
22
+ const DEFAULT_DIM = "#8fb3a6";
23
+ const rad = (deg) => (deg * Math.PI) / 180;
24
+
25
+ function values(data) {
26
+ return data.map((d) => (typeof d === "number" ? d : d.value));
27
+ }
28
+ function labelsOf(data) {
29
+ return data.map((d) => (typeof d === "number" ? null : d.label ?? null));
30
+ }
31
+ function fmt(value, o = {}) {
32
+ const { decimals = 0, prefix = "", suffix = "" } = o;
33
+ const n = Number((value ?? 0).toFixed(decimals));
34
+ return `${prefix}${decimals > 0 ? n.toFixed(decimals) : Math.round(n)}${suffix}`;
35
+ }
36
+ /** `#rrggbb` + alpha -> `rgba(...)`, for a chart's own gradient fills. */
37
+ function hexA(hex, alpha) {
38
+ const h = hex.replace("#", "");
39
+ const n = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
40
+ const r = parseInt(n.slice(0, 2), 16), g = parseInt(n.slice(2, 4), 16), b = parseInt(n.slice(4, 6), 16);
41
+ return `rgba(${r},${g},${b},${alpha})`;
42
+ }
43
+ /** `[number, ...]` or `[{x, y}, ...]` into `{x?: 0..1, y}` points, evenly spaced when `x` is absent. */
44
+ function seriesPoints(series) {
45
+ return series.map((d, i) =>
46
+ typeof d === "number" ? { y: d } : d
47
+ ).map((p, i, arr) => ({
48
+ x: p.x !== undefined ? p.x : i / Math.max(1, arr.length - 1),
49
+ y: p.y
50
+ }));
51
+ }
52
+
53
+ /**
54
+ * `barChart(s, data, o)` — bars grow from the baseline (`scaleY`/`offsetY`,
55
+ * the same idiom every hand-authored growth bar in the shipped examples
56
+ * uses), staggered across the set, each with a value label that counts up
57
+ * and finishes inside its own bar's growth window — so a still taken any
58
+ * time after `at + i * stagger + dur` shows a settled bar and a settled
59
+ * number, never a mid-flight one.
60
+ *
61
+ * `data`: `[number, ...]` or `[{value, label}, ...]`.
62
+ * `o`: `w`, `h` (box size, px), `orientation` `"vertical"|"horizontal"`,
63
+ * `gap` (px between bars), `rounded` (corner radius), `labels` (value
64
+ * labels on/off, default true), `axisLabels` (the `label` strings on/off,
65
+ * default true), `stagger` (seconds between bars), `at`, `dur`, `ease`,
66
+ * `highlight` (index drawn in `color` instead of `palette`), `color`,
67
+ * `palette` (per-bar colors, cycled), `format` ({decimals, prefix,
68
+ * suffix}), `x`, `y`, `parent`.
69
+ */
70
+ export function barChart(s, data, o = {}) {
71
+ const {
72
+ w = 600,
73
+ h = 360,
74
+ gap = 16,
75
+ orientation = "vertical",
76
+ rounded = 8,
77
+ labels = true,
78
+ axisLabels = true,
79
+ stagger = 0.07,
80
+ at = 0,
81
+ dur = 0.5,
82
+ ease = "outExpo",
83
+ highlight,
84
+ color = DEFAULT_COLOR,
85
+ dim = DEFAULT_DIM,
86
+ palette = [],
87
+ format = {},
88
+ x = 0,
89
+ y = 0,
90
+ parent,
91
+ name = "barChart"
92
+ } = o;
93
+ const g = s.group({ name, x, y, parent });
94
+ const vals = values(data);
95
+ const labelStrs = labelsOf(data);
96
+ const n = vals.length;
97
+ const max = Math.max(...vals, 0.0001);
98
+ const vertical = orientation !== "horizontal";
99
+ const axisLen = vertical ? w : h;
100
+ const crossLen = vertical ? h : w;
101
+ const thickness = Math.max(1, (axisLen - gap * Math.max(0, n - 1)) / n);
102
+ const bars = [];
103
+ const valueLabels = [];
104
+ const dataLabels = [];
105
+ vals.forEach((value, i) => {
106
+ const frac = Math.max(0, value) / max;
107
+ const len = Math.max(1, crossLen * frac);
108
+ const isHi = i === highlight;
109
+ const barColor = isHi ? color : palette[i % Math.max(1, palette.length)] ?? dim;
110
+ const barAt = at + i * stagger;
111
+ let bar, labelX, labelY, labelAnchor;
112
+ if (vertical) {
113
+ const cx = -w / 2 + thickness / 2 + i * (thickness + gap);
114
+ const cy = h / 2 - len / 2;
115
+ bar = s.rect(thickness, len, barColor, { name: `bar-${i}`, parent: g.id, r: rounded, x: cx, y: cy });
116
+ bar.animate({ scaleY: [0, 1], offsetY: [len / 2, 0] }, { at: barAt, dur, ease });
117
+ labelX = cx;
118
+ labelY = h / 2 - len - 16;
119
+ labelAnchor = "center";
120
+ if (axisLabels && labelStrs[i] != null) {
121
+ const lbl = s.text(labelStrs[i], { parent: g.id, x: cx, y: h / 2 + 24, mw: 0.9, size: 22, weight: 600, color: dim });
122
+ lbl.enter({ from: { offsetY: 8, opacity: 0 }, at: barAt, dur: dur * 0.6 });
123
+ dataLabels.push(lbl);
124
+ }
125
+ } else {
126
+ const cy = -h / 2 + thickness / 2 + i * (thickness + gap);
127
+ const cx = -w / 2 + len / 2;
128
+ bar = s.rect(len, thickness, barColor, { name: `bar-${i}`, parent: g.id, r: rounded, x: cx, y: cy });
129
+ bar.animate({ scaleX: [0, 1], offsetX: [-len / 2, 0] }, { at: barAt, dur, ease });
130
+ labelX = -w / 2 + len + 16;
131
+ labelY = cy;
132
+ labelAnchor = "left";
133
+ if (axisLabels && labelStrs[i] != null) {
134
+ const lbl = s.text(labelStrs[i], { parent: g.id, x: -w / 2 - 12, y: cy, mw: 0.3, size: 22, weight: 600, color: dim, anchor: "right" });
135
+ lbl.enter({ from: { opacity: 0 }, at: barAt, dur: dur * 0.6 });
136
+ dataLabels.push(lbl);
137
+ }
138
+ }
139
+ bars.push(bar);
140
+ if (labels) {
141
+ const lbl = s.text(fmt(0, format), {
142
+ parent: g.id, x: labelX, y: labelY, mw: 0.9, size: 26, weight: 700,
143
+ color: isHi ? color : "#f4fbf8", anchor: labelAnchor
144
+ });
145
+ lbl.count({ from: 0, to: value, at: barAt, dur: dur * 0.85, ...format, ease: "outExpo" });
146
+ lbl.enter({ from: { opacity: 0 }, at: barAt, dur: 0.15 });
147
+ valueLabels.push(lbl);
148
+ }
149
+ });
150
+ return { group: g, bars, valueLabels, dataLabels };
151
+ }
152
+
153
+ /**
154
+ * `lineChart(s, series, o)` — one path that draws on (`trimEnd`, the same
155
+ * mechanism `el.draw()` wraps), points scaled into a `w`×`h` box, optional
156
+ * dot markers that pop in as the line reaches them, and an end-of-line
157
+ * value that counts from the first point to the last across the same
158
+ * window the line draws in.
159
+ *
160
+ * `series`: `[number, ...]` (evenly spaced x) or `[{x, y}, ...]` (`x` in
161
+ * 0..1 across the box).
162
+ * `o`: `w`, `h`, `dots` (default true), `highlight` (dot index), `color`,
163
+ * `sw` (stroke width), `dur`, `at`, `ease`, `endLabel` (default true),
164
+ * `format`, `x`, `y`, `parent`.
165
+ */
166
+ export function lineChart(s, series, o = {}) {
167
+ const {
168
+ w = 600,
169
+ h = 320,
170
+ dots = true,
171
+ highlight,
172
+ color = DEFAULT_COLOR,
173
+ sw = 4,
174
+ dur = 0.8,
175
+ at = 0,
176
+ ease = "outExpo",
177
+ endLabel = true,
178
+ format = {},
179
+ x = 0,
180
+ y = 0,
181
+ parent,
182
+ name = "lineChart"
183
+ } = o;
184
+ const g = s.group({ name, x, y, parent });
185
+ const pts = seriesPoints(series);
186
+ const ys = pts.map((p) => p.y);
187
+ const minY = Math.min(...ys), maxY = Math.max(...ys);
188
+ const span = maxY - minY || 1;
189
+ const coords = pts.map((p) => [-w / 2 + p.x * w, h / 2 - ((p.y - minY) / span) * h]);
190
+ const linePoints = coords.map(([px, py], i) => [i === 0 ? "M" : "L", px, py]);
191
+ const line = s.path(linePoints, { name: "line", parent: g.id, stroke: color, sw });
192
+ line.draw({ at, dur, ease });
193
+ const dotEls = [];
194
+ if (dots) {
195
+ coords.forEach(([px, py], i) => {
196
+ const isHi = i === highlight;
197
+ const dot = s.ellipse(isHi ? 16 : 10, isHi ? color : "#f4fbf8", { name: `dot-${i}`, parent: g.id, x: px, y: py });
198
+ dot.enter({ from: { scale: 0, opacity: 0 }, at: at + (dur * i) / Math.max(1, coords.length - 1), dur: 0.2, ease: "outExpo" });
199
+ dotEls.push(dot);
200
+ });
201
+ }
202
+ let label;
203
+ if (endLabel) {
204
+ const [lx, ly] = coords[coords.length - 1];
205
+ label = s.text(fmt(pts[0].y, format), { parent: g.id, x: lx, y: ly - 28, size: 26, weight: 700, color, mw: 0.4 });
206
+ label.count({ from: pts[0].y, to: pts[pts.length - 1].y, at, dur, ...format, ease });
207
+ label.enter({ from: { opacity: 0 }, at, dur: 0.2 });
208
+ }
209
+ return { group: g, line, dots: dotEls, label };
210
+ }
211
+
212
+ /**
213
+ * `areaChart(s, series, o)` — `lineChart`'s filled sibling. The same scaled
214
+ * points close into a baseline-filled shape that grows up from the bottom
215
+ * (the `barChart` baseline-grow idiom, applied to the whole fill), with an
216
+ * optional stroked line drawn on top over the same window.
217
+ *
218
+ * `series`/`o` match `lineChart`, plus `fill` (color or gradient stop list;
219
+ * default a soft top-to-bottom wash of `color`) and `line` (draw a stroked
220
+ * line on top, default true).
221
+ */
222
+ export function areaChart(s, series, o = {}) {
223
+ const {
224
+ w = 600,
225
+ h = 320,
226
+ color = DEFAULT_COLOR,
227
+ sw = 4,
228
+ dur = 0.6,
229
+ at = 0,
230
+ ease = "outExpo",
231
+ fill,
232
+ line: drawLine = true,
233
+ x = 0,
234
+ y = 0,
235
+ parent,
236
+ name = "areaChart"
237
+ } = o;
238
+ const g = s.group({ name, x, y, parent });
239
+ const pts = seriesPoints(series);
240
+ const ys = pts.map((p) => p.y);
241
+ const minY = Math.min(...ys), maxY = Math.max(...ys);
242
+ const span = maxY - minY || 1;
243
+ const coords = pts.map((p) => [-w / 2 + p.x * w, h / 2 - ((p.y - minY) / span) * h]);
244
+ const areaPoints = [
245
+ ["M", coords[0][0], h / 2],
246
+ ...coords.map(([px, py]) => ["L", px, py]),
247
+ ["L", coords[coords.length - 1][0], h / 2],
248
+ ["Z"]
249
+ ];
250
+ const fillStyle = fill ?? {
251
+ type: "linear",
252
+ angle: 90,
253
+ stops: [{ offset: 0, color: hexA(color, 0.55) }, { offset: 1, color: hexA(color, 0) }]
254
+ };
255
+ const area = s.path(areaPoints, { name: "area", parent: g.id, fill: fillStyle });
256
+ area.animate({ scaleY: [0, 1], offsetY: [h / 2, 0] }, { at, dur, ease });
257
+ let line;
258
+ if (drawLine) {
259
+ const linePoints = coords.map(([px, py], i) => [i === 0 ? "M" : "L", px, py]);
260
+ line = s.path(linePoints, { name: "line", parent: g.id, stroke: color, sw });
261
+ line.draw({ at, dur, ease });
262
+ }
263
+ return { group: g, area, line };
264
+ }
265
+
266
+ /**
267
+ * `donut(s, data, o)` — a ring, one stroked arc per datum (tessellated as a
268
+ * short M/L polyline, not an SVG `A` command — the renderer's path pipeline
269
+ * draws straight segments but drops a true arc), sweeping in clockwise from
270
+ * 12 o'clock and staggered via `trimEnd`; the arcs' `startDeg`/`endDeg`
271
+ * always sum their sweeps to 360 (minus the `gap` notches) regardless of
272
+ * `data`'s values, since each is `value / total * 360`.
273
+ *
274
+ * `data`: `[number, ...]` or `[{value, label}, ...]`.
275
+ * `o`: `d` (diameter), `thickness` (default `d * 0.22`), `gap` (degrees of
276
+ * notch between segments), `stagger`, `at`, `dur`, `ease`, `highlight`
277
+ * (index drawn in `color`), `color`, `palette` (cycled per segment),
278
+ * `centerLabel` (the total, counts up, default true), `format`, `x`, `y`,
279
+ * `parent`.
280
+ */
281
+ export function donut(s, data, o = {}) {
282
+ const {
283
+ d = 420,
284
+ thickness,
285
+ gap = 4,
286
+ stagger = 0.1,
287
+ at = 0,
288
+ dur = 0.6,
289
+ ease = "outExpo",
290
+ highlight,
291
+ color = DEFAULT_COLOR,
292
+ palette = [DEFAULT_COLOR, "#f4a340", "#5aa9e6", "#e6607a", "#8fb3a6"],
293
+ centerLabel = true,
294
+ format = {},
295
+ x = 0,
296
+ y = 0,
297
+ parent,
298
+ name = "donut"
299
+ } = o;
300
+ const g = s.group({ name, x, y, parent });
301
+ const r = d / 2;
302
+ const sw = thickness ?? d * 0.22;
303
+ const vals = values(data);
304
+ const labelStrs = labelsOf(data);
305
+ const total = vals.reduce((a, b) => a + Math.max(0, b), 0) || 1;
306
+ const segments = [];
307
+ let cursorDeg = -90;
308
+ vals.forEach((value, i) => {
309
+ const sweepDeg = Math.max(0, (Math.max(0, value) / total) * 360);
310
+ const startDeg = cursorDeg + gap / 2;
311
+ const endDeg = Math.max(startDeg, cursorDeg + sweepDeg - gap / 2);
312
+ cursorDeg += sweepDeg;
313
+ const isHi = i === highlight;
314
+ const segColor = isHi ? color : palette[i % Math.max(1, palette.length)];
315
+ // A tessellated M/L polyline, not a single SVG `A` arc command: the
316
+ // renderer's path pipeline (GPU, not Canvas 2D) draws straight segments
317
+ // but silently drops an arc command, leaving the ring invisible. ~6deg
318
+ // per segment is visually indistinguishable from a true arc at any size
319
+ // this chart renders at, and — being plain M/L — it also supports
320
+ // `el.draw()`'s `trimEnd` sweep, the same mechanism the line chart uses.
321
+ const steps = Math.max(2, Math.ceil((endDeg - startDeg) / 6));
322
+ const arcPoints = [];
323
+ for (let k = 0; k <= steps; k += 1) {
324
+ const deg = startDeg + ((endDeg - startDeg) * k) / steps;
325
+ const a = rad(deg);
326
+ arcPoints.push([k === 0 ? "M" : "L", r * Math.cos(a), r * Math.sin(a)]);
327
+ }
328
+ const arc = s.path(arcPoints, { name: `seg-${i}`, parent: g.id, stroke: segColor, sw });
329
+ arc.draw({ at: at + i * stagger, dur, ease });
330
+ segments.push({ clip: arc, value, startDeg, endDeg, label: labelStrs[i] });
331
+ });
332
+ let label;
333
+ if (centerLabel) {
334
+ const labelDur = Math.max(1, vals.length - 1) * stagger + dur;
335
+ label = s.text(fmt(0, format), { parent: g.id, size: d * 0.16, weight: 700, color: "#f4fbf8", mw: 0.6 });
336
+ label.count({ from: 0, to: total, at, dur: labelDur, ...format, ease: "outExpo" });
337
+ label.enter({ from: { opacity: 0 }, at, dur: 0.2 });
338
+ }
339
+ return { group: g, segments, label };
340
+ }
341
+
342
+ /**
343
+ * `statCounter(s, value, o)` — a single number that counts up: the building
344
+ * block `barChart`'s value labels use, on its own for a callout number
345
+ * that isn't part of a chart. `o`: `from` (default 0), `format`
346
+ * ({decimals, prefix, suffix, padTo, groupSeparator}), `at`, `dur`,
347
+ * `ease`, plus every `s.text` option (`size`, `weight`, `color`, `font`,
348
+ * `x`, `y`, `parent`).
349
+ */
350
+ export function statCounter(s, value, o = {}) {
351
+ const { from = 0, format = {}, at = 0, dur = 0.8, ease = "outExpo", ...textOpts } = o;
352
+ const el = s.text(fmt(from, format), { size: 64, weight: 700, color: "#f4fbf8", ...textOpts });
353
+ el.count({ from, to: value, at, dur, ...format, ease });
354
+ el.enter({ from: { opacity: 0 }, at, dur: 0.2 });
355
+ return el;
356
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * `component()` — a reusable timeline piece with typed props — and the
3
+ * marker-diff machinery `saveAsComposition` (in `index.js`, which owns
4
+ * `video()`) uses to map a prop onto the composition schema's JSON-pointer
5
+ * parameters (see `packages/timeline/src/composition.ts`).
6
+ *
7
+ * Kept as its own internal module so it can be edited without touching
8
+ * `index.js`'s `video()`/`scene()` core. Nothing here depends on a `video()`
9
+ * instance — `use()` and the probe builds that call `component()`'s `build`
10
+ * function live in `index.js`, which is the only place `video()` is in scope.
11
+ */
12
+
13
+ /** The value kinds a component prop carries — the same set a composition parameter allows. */
14
+ export const COMPONENT_PROP_TYPES = new Set(["string", "number", "color", "boolean"]);
15
+
16
+ const HEX_COLOR = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
17
+
18
+ /**
19
+ * Whether `value` matches a declared prop type. Mirrors
20
+ * `compositionValueMatchesType` in `packages/timeline/src/composition.ts` —
21
+ * the two must agree, or a prop that validates here fails validation once
22
+ * `saveAsComposition` turns it into a composition parameter.
23
+ */
24
+ export function componentValueMatchesType(type, value) {
25
+ switch (type) {
26
+ case "string": return typeof value === "string";
27
+ case "number": return typeof value === "number" && Number.isFinite(value);
28
+ case "boolean": return typeof value === "boolean";
29
+ case "color": return typeof value === "string" && HEX_COLOR.test(value);
30
+ default: return false;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * `component(name, {props, duration}, (s, props) => {...})` — a reusable
36
+ * scene piece. `props` maps a name to `{type, default, description?}`;
37
+ * `duration` (seconds) is the piece's own natural length, used by `use()`
38
+ * when the caller gives no `dur`. `build(s, props)` receives a scene
39
+ * authoring object exactly like a `scene()` builder, and adds its clips the
40
+ * same way — `use()` (in `index.js`) folds them into one group afterward.
41
+ */
42
+ export function component(name, spec = {}, build) {
43
+ if (typeof build !== "function") {
44
+ throw new Error(`component("${name}"): the third argument must be the build function (s, props) => {...}.`);
45
+ }
46
+ const props = spec.props ?? {};
47
+ for (const [propName, propSpec] of Object.entries(props)) {
48
+ if (!COMPONENT_PROP_TYPES.has(propSpec.type)) {
49
+ throw new Error(`component("${name}"): prop "${propName}" has type ${JSON.stringify(propSpec.type)}; expected one of ${[...COMPONENT_PROP_TYPES].join(", ")}.`);
50
+ }
51
+ if (!componentValueMatchesType(propSpec.type, propSpec.default)) {
52
+ throw new Error(`component("${name}"): prop "${propName}" is declared ${propSpec.type} but its default is ${JSON.stringify(propSpec.default)}.`);
53
+ }
54
+ }
55
+ return { __component: true, name, props, duration: spec.duration, build };
56
+ }
57
+
58
+ /** Fill `propsIn` against `Comp.props`: defaults, then a type check naming the offending prop. */
59
+ export function resolveComponentProps(Comp, propsIn = {}) {
60
+ const out = {};
61
+ for (const [name, spec] of Object.entries(Comp.props)) {
62
+ const has = Object.prototype.hasOwnProperty.call(propsIn, name);
63
+ const value = has ? propsIn[name] : spec.default;
64
+ if (!componentValueMatchesType(spec.type, value)) {
65
+ throw new Error(`${Comp.name}: prop "${name}" is declared ${spec.type} but got ${JSON.stringify(value)}.`);
66
+ }
67
+ out[name] = value;
68
+ }
69
+ for (const name of Object.keys(propsIn)) {
70
+ if (!Object.prototype.hasOwnProperty.call(Comp.props, name)) {
71
+ const known = Object.keys(Comp.props);
72
+ throw new Error(`${Comp.name} has no prop "${name}". ${known.length > 0 ? `Its props: ${known.join(", ")}.` : "It declares none."}`);
73
+ }
74
+ }
75
+ return out;
76
+ }
77
+
78
+ /** `{name: spec.default}` for every declared prop. */
79
+ export function defaultComponentProps(Comp) {
80
+ const out = {};
81
+ for (const [name, spec] of Object.entries(Comp.props)) out[name] = spec.default;
82
+ return out;
83
+ }
84
+
85
+ /**
86
+ * A value distinct from `current`, of the same declared type — used to probe
87
+ * which field a prop reaches by rebuilding the component with it and diffing
88
+ * the result against a baseline build. Assumes the prop passes through to its
89
+ * field largely intact; a build that heavily transforms it (rounds, clamps,
90
+ * hashes) may not register a diff, which `pointerForProp` then reports as
91
+ * unmapped rather than guessing.
92
+ */
93
+ export function markerPropValue(spec, current) {
94
+ switch (spec.type) {
95
+ case "boolean": return !current;
96
+ case "number": return Number.isFinite(current) ? current + 97 : 97;
97
+ case "string": return `${current}\u0000probe`;
98
+ case "color": return current === "#5a3cf4" ? "#f4c35a" : "#5a3cf4";
99
+ default: return current;
100
+ }
101
+ }
102
+
103
+ function escapePointer(key) {
104
+ return String(key).replace(/~/g, "~0").replace(/\//g, "~1");
105
+ }
106
+
107
+ /** Collect every leaf JSON-pointer path where `a` and `b` differ, stopping once more than one is found. */
108
+ function collectDiffs(a, b, prefix, out) {
109
+ if (out.length > 1) return;
110
+ if (a === b) return;
111
+ if (Array.isArray(a) && Array.isArray(b)) {
112
+ if (a.length !== b.length) { out.push(prefix); return; }
113
+ for (let i = 0; i < a.length; i++) collectDiffs(a[i], b[i], `${prefix}/${i}`, out);
114
+ return;
115
+ }
116
+ const aObj = a !== null && typeof a === "object" && !Array.isArray(a);
117
+ const bObj = b !== null && typeof b === "object" && !Array.isArray(b);
118
+ if (aObj && bObj) {
119
+ const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
120
+ for (const key of keys) collectDiffs(a[key], b[key], `${prefix}/${escapePointer(key)}`, out);
121
+ return;
122
+ }
123
+ out.push(prefix);
124
+ }
125
+
126
+ function unescapePointer(segment) {
127
+ return segment.replace(/~1/g, "/").replace(/~0/g, "~");
128
+ }
129
+
130
+ /** A deep clone of `children` with `path`'s target replaced by `value` — `instantiateComposition`'s own write, done locally to verify a candidate pointer. */
131
+ function withPointerValue(children, path, value) {
132
+ const clone = JSON.parse(JSON.stringify(children));
133
+ const segments = path.slice(1).split("/").map(unescapePointer);
134
+ const index = Number(segments[0]);
135
+ if (segments.length === 1) {
136
+ clone[index] = value;
137
+ return clone;
138
+ }
139
+ let cursor = clone[index];
140
+ for (let i = 1; i < segments.length - 1; i++) cursor = cursor[segments[i]];
141
+ cursor[segments[segments.length - 1]] = value;
142
+ return clone;
143
+ }
144
+
145
+ /**
146
+ * The one JSON pointer where `markedChildren` differs from `baseChildren` —
147
+ * two children arrays built with identical ids (same build call order, so
148
+ * only the probed prop's value moved) — or `undefined` when the prop reached
149
+ * no field, more than one field, or changed the children's shape, none of
150
+ * which a single composition-parameter pointer can express.
151
+ *
152
+ * The candidate is verified, not just located: writing `markerValue` to
153
+ * `baseChildren` at that pointer must reproduce `markedChildren` exactly. This
154
+ * catches a prop whose only visible effect is adding or removing a whole
155
+ * field (an `if (prop) el.enter(...)`, say) — the diff walk finds one path
156
+ * (the field's parent), but `instantiateComposition` would write the prop's
157
+ * scalar value there, not toggle the field's presence, so the pointer is
158
+ * rejected rather than shipped wrong.
159
+ */
160
+ export function pointerForProp(baseChildren, markedChildren, markerValue) {
161
+ if (baseChildren.length !== markedChildren.length) return undefined;
162
+ const diffs = [];
163
+ for (let i = 0; i < baseChildren.length; i++) {
164
+ collectDiffs(baseChildren[i], markedChildren[i], `/${i}`, diffs);
165
+ if (diffs.length > 1) return undefined;
166
+ }
167
+ const path = diffs.length === 1 ? diffs[0] : undefined;
168
+ if (path === undefined || markerValue === undefined) return path;
169
+ const patched = withPointerValue(baseChildren, path, markerValue);
170
+ return JSON.stringify(patched) === JSON.stringify(markedChildren) ? path : undefined;
171
+ }