@pixel-point/toolcraft 0.0.16 → 0.0.18

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 (313) hide show
  1. package/package.json +1 -1
  2. package/src/generate-performance-iteration-execution.test.mjs +2 -2
  3. package/src/generate-test-demand-only-lifecycle.mjs +14 -3
  4. package/src/generate-test-dependency-sandbox.mjs +42 -5
  5. package/src/generate-test-doc-assertions.mjs +109 -69
  6. package/src/generate-test-doc-assertions.test.mjs +65 -0
  7. package/src/generate-test-doc-policy-assertions.mjs +92 -0
  8. package/src/generate-test-file-assertions.mjs +36 -118
  9. package/src/generate-test-output-assertions.mjs +95 -0
  10. package/src/generate-test-package-assertions.mjs +6 -0
  11. package/src/generate-test-performance-boundary-assertions.mjs +45 -0
  12. package/src/generate-test-product-fixture.mjs +1 -0
  13. package/src/generate-test-product-fixture.test.mjs +18 -0
  14. package/src/generate-test-product-iteration.mjs +1 -0
  15. package/src/generate-test-product-iteration.test.mjs +18 -0
  16. package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
  17. package/src/generate-test-standalone-assertions.mjs +10 -0
  18. package/src/generate-test-standalone-delivery-stages.mjs +14 -6
  19. package/src/generate.test.mjs +14 -0
  20. package/templates/runtime/contracts/component-contracts.choices.test.ts +59 -12
  21. package/templates/runtime/contracts/component-contracts.choices.ts +58 -12
  22. package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
  23. package/templates/runtime/contracts/component-contracts.inputs.ts +6 -6
  24. package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
  25. package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
  26. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +21 -6
  27. package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
  28. package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +4 -1
  29. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +4 -1
  30. package/templates/runtime/contracts/component-contracts.runtime.ts +15 -10
  31. package/templates/runtime/contracts/component-contracts.test.ts +2 -0
  32. package/templates/runtime/contracts/decision-contracts.test.ts +43 -4
  33. package/templates/runtime/contracts/decision-contracts.ts +10 -10
  34. package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
  35. package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
  36. package/templates/runtime/export/artifact-download.test.ts +71 -0
  37. package/templates/runtime/export/artifact-download.ts +80 -0
  38. package/templates/runtime/export/artifact-export-request.ts +23 -0
  39. package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
  40. package/templates/runtime/export/artifact-export-settings.ts +96 -0
  41. package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
  42. package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
  43. package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
  44. package/templates/runtime/export/artifact-frame-state.ts +44 -0
  45. package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
  46. package/templates/runtime/export/artifact-scene-frame.ts +118 -0
  47. package/templates/runtime/export/export-background.ts +46 -0
  48. package/templates/runtime/export/export-error.ts +43 -0
  49. package/templates/runtime/export/export.test.ts +49 -226
  50. package/templates/runtime/export/image-artifact-export.test.ts +111 -0
  51. package/templates/runtime/export/image-artifact-export.ts +145 -0
  52. package/templates/runtime/export/index.ts +44 -3
  53. package/templates/runtime/export/product-export-renderer.test.ts +77 -0
  54. package/templates/runtime/export/product-export-renderer.ts +63 -0
  55. package/templates/runtime/export/video-artifact-export.test.ts +166 -0
  56. package/templates/runtime/export/video-artifact-export.ts +164 -0
  57. package/templates/runtime/export/video-encoding-backend.ts +124 -0
  58. package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
  59. package/templates/runtime/export/video-encoding-policy.ts +86 -0
  60. package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
  61. package/templates/runtime/export/video-frame-schedule.ts +42 -0
  62. package/templates/runtime/index.ts +3 -0
  63. package/templates/runtime/model-import/model-import-limits.ts +15 -4
  64. package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
  65. package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
  66. package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +15 -304
  67. package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +41 -27
  68. package/templates/runtime/react/app-shell/toolcraft-app.tsx +39 -11
  69. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
  70. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
  71. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
  72. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
  73. package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
  74. package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
  75. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
  76. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
  77. package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +76 -0
  78. package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
  79. package/templates/runtime/react/canvas/canvas-shell.tsx +16 -1
  80. package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
  81. package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
  82. package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
  83. package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
  84. package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
  85. package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
  86. package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
  87. package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +18 -84
  88. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +62 -0
  89. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
  90. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +43 -87
  91. package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +68 -0
  92. package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
  93. package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
  94. package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +10 -8
  95. package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +3 -3
  96. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
  97. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
  98. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
  99. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
  100. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
  101. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
  102. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
  103. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
  104. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
  105. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
  106. package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
  107. package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
  108. package/templates/runtime/react/index.ts +4 -0
  109. package/templates/runtime/react/model-rendering/model-export.ts +1 -1
  110. package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
  111. package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
  112. package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
  113. package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
  114. package/templates/runtime/scene/scene-bounds.test.ts +23 -0
  115. package/templates/runtime/scene/scene-bounds.ts +32 -19
  116. package/templates/runtime/schema/app-capabilities.test.ts +4 -0
  117. package/templates/runtime/schema/canvas-render-scale.ts +62 -0
  118. package/templates/runtime/schema/collection-item-controls.ts +29 -0
  119. package/templates/runtime/schema/control-applicability.test.ts +127 -0
  120. package/templates/runtime/schema/control-applicability.ts +433 -0
  121. package/templates/runtime/schema/control-schema-normalization.ts +177 -11
  122. package/templates/runtime/schema/controls-panel-actions.ts +2 -2
  123. package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
  124. package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
  125. package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +62 -3
  126. package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
  127. package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
  128. package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
  129. package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
  130. package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
  131. package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
  132. package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
  133. package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
  134. package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
  135. package/templates/runtime/schema/define-toolcraft.ts +1 -1
  136. package/templates/runtime/schema/runtime-setup-section.ts +24 -5
  137. package/templates/runtime/schema/schema-resolvers.ts +0 -56
  138. package/templates/runtime/schema/types.ts +72 -17
  139. package/templates/runtime/state/canvas-background-state.ts +6 -0
  140. package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
  141. package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
  142. package/templates/starter/AGENTS.md +18 -15
  143. package/templates/starter/NOTICE.md +6 -0
  144. package/templates/starter/docs/toolcraft/README.md +2 -1
  145. package/templates/starter/docs/toolcraft/acceptance-testing.md +23 -35
  146. package/templates/starter/docs/toolcraft/agent-worklog.md +18 -3
  147. package/templates/starter/docs/toolcraft/assembly-workflow.md +13 -5
  148. package/templates/starter/docs/toolcraft/component-rules.md +8 -6
  149. package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
  150. package/templates/starter/docs/toolcraft/core/layout.md +7 -7
  151. package/templates/starter/docs/toolcraft/core/media-upload.md +4 -2
  152. package/templates/starter/docs/toolcraft/core/performance.md +14 -3
  153. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +16 -3
  154. package/templates/starter/docs/toolcraft/core/setup-export.md +49 -19
  155. package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
  156. package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
  157. package/templates/starter/docs/toolcraft/decision-contract.md +3 -1
  158. package/templates/starter/docs/toolcraft/performance.md +20 -6
  159. package/templates/starter/docs/toolcraft/renderer-technique.md +5 -1
  160. package/templates/starter/docs/toolcraft/schema-reference.md +23 -25
  161. package/templates/starter/docs/toolcraft/workflow.md +7 -2
  162. package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
  163. package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
  164. package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +50 -3
  165. package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
  166. package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
  167. package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
  168. package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
  169. package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
  170. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +5 -34
  171. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -16
  172. package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
  173. package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
  174. package/templates/starter/e2e/app-performance.spec.ts +16 -9
  175. package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
  176. package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
  177. package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +29 -341
  178. package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
  179. package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
  180. package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
  181. package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
  182. package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
  183. package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
  184. package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
  185. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +13 -3
  186. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +72 -35
  187. package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
  188. package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
  189. package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
  190. package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
  191. package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
  192. package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
  193. package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
  194. package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
  195. package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
  196. package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
  197. package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
  198. package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
  199. package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
  200. package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
  201. package/templates/starter/e2e/performance-path-helpers.ts +210 -91
  202. package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
  203. package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
  204. package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
  205. package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
  206. package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
  207. package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
  208. package/templates/starter/gitignore +1 -0
  209. package/templates/starter/package.json +1 -0
  210. package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
  211. package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
  212. package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
  213. package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
  214. package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
  215. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +95 -103
  216. package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
  217. package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
  218. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -26
  219. package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
  220. package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
  221. package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
  222. package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
  223. package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
  224. package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +157 -0
  225. package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
  226. package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
  227. package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
  228. package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
  229. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
  230. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +157 -206
  231. package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
  232. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
  233. package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
  234. package/templates/starter/src/app/acceptance/artifact-export-intent.ts +130 -0
  235. package/templates/starter/src/app/acceptance/conditions.ts +1 -1
  236. package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
  237. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -20
  238. package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
  239. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -13
  240. package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
  241. package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
  242. package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
  243. package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
  244. package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
  245. package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
  246. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +3 -10
  247. package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
  248. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
  249. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
  250. package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
  251. package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
  252. package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
  253. package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
  254. package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
  255. package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
  256. package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
  257. package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
  258. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +18 -10
  259. package/templates/starter/src/app/acceptance/output-export-model.ts +54 -11
  260. package/templates/starter/src/app/acceptance/output-export.ts +35 -12
  261. package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
  262. package/templates/starter/src/app/acceptance/types.ts +30 -8
  263. package/templates/starter/src/app/acceptance/validate-coverage.ts +20 -2
  264. package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +239 -0
  265. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +33 -0
  266. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +16 -1
  267. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +65 -0
  268. package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
  269. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +112 -16
  270. package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +224 -0
  271. package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
  272. package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
  273. package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
  274. package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
  275. package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
  276. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +22 -0
  277. package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +37 -9
  278. package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +12 -0
  279. package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
  280. package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
  281. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
  282. package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +384 -0
  283. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +46 -1
  284. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +112 -105
  285. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +12 -0
  286. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +1 -1
  287. package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
  288. package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
  289. package/templates/starter/src/app/starter-acceptance.ts +13 -2
  290. package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +336 -0
  291. package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +8 -0
  292. package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
  293. package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
  294. package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
  295. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +4 -2
  296. package/templates/starter/src/routes/index.tsx +2 -0
  297. package/templates/ui/components/composites/tabs.tsx +2 -2
  298. package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
  299. package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
  300. package/templates/ui/components/controls/collection-actions/index.ts +2 -0
  301. package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
  302. package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
  303. package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
  304. package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
  305. package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
  306. package/templates/ui/components/controls/file-drop/index.ts +1 -0
  307. package/templates/ui/components/controls/index.ts +3 -0
  308. package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
  309. package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
  310. package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
  311. package/templates/runtime/export/export.ts +0 -166
  312. package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
  313. package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
@@ -90,6 +90,33 @@ describe("defineToolcraft fileDrop normalization", () => {
90
90
  expect(getSourceControl(app)?.hardMaxItems).toBe(0);
91
91
  });
92
92
 
93
+ it("accepts collection actions for a multiple file-kind fileDrop", () => {
94
+ const app = defineToolcraft(
95
+ createFileDropSchema({
96
+ assetKind: "file",
97
+ multiple: true,
98
+ variant: "collection-actions",
99
+ }),
100
+ );
101
+
102
+ expect(getSourceControl(app)?.variant).toBe("collection-actions");
103
+ });
104
+
105
+ it.each([
106
+ ["a single fileDrop", { assetKind: "file" }],
107
+ ["an image fileDrop", { assetKind: "image", multiple: true }],
108
+ ["a model fileDrop", { assetKind: "model", multiple: false }],
109
+ ])("rejects collection actions on %s", (_label, fields) => {
110
+ expect(() =>
111
+ defineToolcraft(
112
+ createFileDropSchema({
113
+ ...fields,
114
+ variant: "collection-actions",
115
+ }),
116
+ ),
117
+ ).toThrow(/\[filedrop-collection-actions\].*assetKind: "file".*multiple: true/u);
118
+ });
119
+
93
120
  it("accepts model fileDrops", () => {
94
121
  const createModelApp = () =>
95
122
  defineToolcraft(createFileDropSchema({ assetKind: "model" }));
@@ -1,5 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
+ import type { ToolcraftCollectionItemControlType } from "./collection-item-controls";
3
4
  import { defineToolcraft } from "./define-toolcraft";
4
5
  import type { ToolcraftControlSchema } from "./types";
5
6
 
@@ -39,8 +40,9 @@ function createModeControl(
39
40
  }
40
41
 
41
42
  function createCollectionModeControl(
42
- type: string,
43
+ type: ToolcraftCollectionItemControlType,
43
44
  labels: readonly string[],
45
+ parentType = "collectionActions",
44
46
  ): ToolcraftControlSchema {
45
47
  return {
46
48
  defaultValue: ["default"],
@@ -57,7 +59,7 @@ function createCollectionModeControl(
57
59
  label: "Modes",
58
60
  minItems: 1,
59
61
  target: "appearance.modes",
60
- type: "collectionActions",
62
+ type: parentType,
61
63
  };
62
64
  }
63
65
 
@@ -138,6 +140,22 @@ describe("defineToolcraft segmented control fit", () => {
138
140
  expect(control).toEqual(inputSnapshot);
139
141
  });
140
142
 
143
+ it("applies segmented item fit validation to sourceCollection", () => {
144
+ expect(() =>
145
+ defineToolcraft(
146
+ createAppSchema(
147
+ createCollectionModeControl(
148
+ "segmented",
149
+ SCREENSHOT_LABELS,
150
+ "sourceCollection",
151
+ ),
152
+ ),
153
+ ),
154
+ ).toThrow(
155
+ /Toolcraft control validation \[segmented-control-fit\] for target "appearance\.modes" itemControl: .*select dropdown/u,
156
+ );
157
+ });
158
+
141
159
  it.each(["type", "target"] as const)(
142
160
  "preserves required %s validation ownership",
143
161
  (fieldName) => {
@@ -118,7 +118,7 @@ describe("defineToolcraft runtime setup background controls", () => {
118
118
 
119
119
  it("keeps the normalized background pair when a resolved schema is defined again", () => {
120
120
  const first = defineToolcraft(createBackgroundSchema());
121
- const second = defineToolcraft(first);
121
+ const second = defineToolcraft(first as unknown as ToolcraftAppSchema);
122
122
  const setupSection = second.panels.controls?.sections[0];
123
123
 
124
124
  expect(second.panels.controls?.sections.map((section) => section.title)).toEqual([
@@ -32,6 +32,7 @@ describe("defineToolcraft runtime setup canvas controls", () => {
32
32
 
33
33
  expect(canvasSection?.title).toBe("Setup");
34
34
  expect(canvasSection?.controls.infinityCanvas).toMatchObject({
35
+ applicability: { mode: "always", origin: "explicit" },
35
36
  defaultValue: false,
36
37
  label: "Infinity canvas",
37
38
  target: "canvas.infinity",
@@ -52,7 +53,11 @@ describe("defineToolcraft runtime setup canvas controls", () => {
52
53
  performanceRole: "workload",
53
54
  target: "canvas.aspectRatio",
54
55
  type: "aspectRatio",
55
- visibleWhen: { equals: false, target: "canvas.infinity" },
56
+ applicability: {
57
+ all: [{ equals: false, target: "canvas.infinity" }],
58
+ mode: "conditional",
59
+ origin: "explicit",
60
+ },
56
61
  });
57
62
  expect(canvasSection?.controls.canvasWidth).toMatchObject({
58
63
  defaultValue: 1440,
@@ -60,7 +65,11 @@ describe("defineToolcraft runtime setup canvas controls", () => {
60
65
  performanceRole: "workload",
61
66
  target: "canvas.size.width",
62
67
  type: "text",
63
- visibleWhen: { equals: false, target: "canvas.infinity" },
68
+ applicability: {
69
+ all: [{ equals: false, target: "canvas.infinity" }],
70
+ mode: "conditional",
71
+ origin: "explicit",
72
+ },
64
73
  });
65
74
  expect(canvasSection?.controls.canvasHeight).toMatchObject({
66
75
  defaultValue: 900,
@@ -68,7 +77,11 @@ describe("defineToolcraft runtime setup canvas controls", () => {
68
77
  performanceRole: "workload",
69
78
  target: "canvas.size.height",
70
79
  type: "text",
71
- visibleWhen: { equals: false, target: "canvas.infinity" },
80
+ applicability: {
81
+ all: [{ equals: false, target: "canvas.infinity" }],
82
+ mode: "conditional",
83
+ origin: "explicit",
84
+ },
72
85
  });
73
86
  expect(canvasSection?.layoutGroups).toEqual([
74
87
  {
@@ -1,6 +1,40 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
3
  import { defineToolcraft } from "./define-toolcraft";
4
+ import type { ToolcraftCanvasRenderScaleSchema } from "./types";
5
+
6
+ const authoredRenderScaleStep: ToolcraftCanvasRenderScaleSchema = { step: 0.5 };
7
+ const authoredRenderScaleDefaultValue = { defaultValue: 1, step: 0.5 };
8
+ const authoredRenderScaleEnabled = { enabled: true, step: 0.5 };
9
+ const authoredRenderScaleMax = { max: 1, step: 0.5 };
10
+ const authoredRenderScaleMin = { min: 1, step: 0.5 };
11
+
12
+ // @ts-expect-error Authored render scale cannot select its resolved default value.
13
+ const authoredRenderScaleDefaultValueAssignment: ToolcraftCanvasRenderScaleSchema =
14
+ authoredRenderScaleDefaultValue;
15
+
16
+ // @ts-expect-error Authored render scale is always enabled when provided.
17
+ const authoredRenderScaleEnabledAssignment: ToolcraftCanvasRenderScaleSchema = {
18
+ ...authoredRenderScaleEnabled,
19
+ };
20
+
21
+ // @ts-expect-error Authored render scale cannot change the canonical maximum.
22
+ const authoredRenderScaleMaxAssignment: ToolcraftCanvasRenderScaleSchema = authoredRenderScaleMax;
23
+
24
+ // @ts-expect-error Authored render scale cannot change the canonical minimum.
25
+ const authoredRenderScaleMinAssignment: ToolcraftCanvasRenderScaleSchema = {
26
+ ...authoredRenderScaleMin,
27
+ };
28
+
29
+ void authoredRenderScaleStep;
30
+ void authoredRenderScaleDefaultValue;
31
+ void authoredRenderScaleEnabled;
32
+ void authoredRenderScaleMax;
33
+ void authoredRenderScaleMin;
34
+ void authoredRenderScaleDefaultValueAssignment;
35
+ void authoredRenderScaleEnabledAssignment;
36
+ void authoredRenderScaleMaxAssignment;
37
+ void authoredRenderScaleMinAssignment;
4
38
 
5
39
  describe("defineToolcraft runtime setup render scale and timeline controls", () => {
6
40
  it("appends raster render scale to the technical setup controls when enabled", () => {
@@ -95,11 +129,11 @@ describe("defineToolcraft runtime setup render scale and timeline controls", ()
95
129
  ]);
96
130
  });
97
131
 
98
- it("keeps timeline standalone with render scale for fixed output sizing", () => {
132
+ it("uses the canonical authored raster scale with a custom step", () => {
99
133
  const app = defineToolcraft({
100
134
  canvas: {
101
135
  enabled: true,
102
- renderScale: { defaultValue: 1.5 },
136
+ renderScale: { step: 0.5 },
103
137
  size: { height: 900, unit: "px", width: 1440 },
104
138
  sizing: { mode: "fixed-output" },
105
139
  },
@@ -120,10 +154,20 @@ describe("defineToolcraft runtime setup render scale and timeline controls", ()
120
154
  "timelineExtended",
121
155
  ]);
122
156
  expect(setupSection?.controls.canvasRenderScale).toMatchObject({
123
- defaultValue: 1.5,
157
+ defaultValue: 2,
158
+ max: 2,
159
+ min: 1,
160
+ step: 0.5,
124
161
  target: "canvas.renderScale",
125
162
  type: "slider",
126
163
  });
164
+ expect(app.canvas.renderScale).toEqual({
165
+ defaultValue: 2,
166
+ enabled: true,
167
+ max: 2,
168
+ min: 1,
169
+ step: 0.5,
170
+ });
127
171
  expect(setupSection?.controls.timelineExtended).toMatchObject({
128
172
  defaultValue: false,
129
173
  label: "Timeline",
@@ -133,4 +177,28 @@ describe("defineToolcraft runtime setup render scale and timeline controls", ()
133
177
  expect(setupSection?.controls.timelineExtended).not.toHaveProperty("description");
134
178
  expect(setupSection?.layoutGroups ?? []).toEqual([]);
135
179
  });
180
+
181
+ it("rejects an authored step that cannot reach the canonical maximum", () => {
182
+ expect(() =>
183
+ defineToolcraft({
184
+ canvas: {
185
+ enabled: true,
186
+ renderScale: { step: 0.3 },
187
+ },
188
+ panels: {},
189
+ }),
190
+ ).toThrow("Canvas render scale step must divide the canonical range exactly.");
191
+ });
192
+
193
+ it.each([0, Number.NaN])("rejects invalid authored step %s", (step) => {
194
+ expect(() =>
195
+ defineToolcraft({
196
+ canvas: {
197
+ enabled: true,
198
+ renderScale: { step },
199
+ },
200
+ panels: {},
201
+ }),
202
+ ).toThrow("Canvas render scale step must be a finite value between 0.01 and 1.");
203
+ });
136
204
  });
@@ -0,0 +1,79 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { defineToolcraft } from "./define-toolcraft";
4
+ import type { ToolcraftControlSchema } from "./types";
5
+
6
+ function createAppSchema(control: ToolcraftControlSchema) {
7
+ return {
8
+ canvas: { enabled: false },
9
+ panels: {
10
+ controls: {
11
+ sections: [
12
+ {
13
+ controls: { sections: control },
14
+ title: "Fill Sections",
15
+ },
16
+ ],
17
+ title: "Controls",
18
+ },
19
+ },
20
+ };
21
+ }
22
+
23
+ function createSourceCollection(
24
+ overrides: Record<string, unknown> = {},
25
+ ): ToolcraftControlSchema {
26
+ return {
27
+ defaultValue: [{ hex: "#DFFF1A" }],
28
+ itemControl: { label: false, type: "color" },
29
+ itemLabel: "Section",
30
+ label: "Sections",
31
+ target: "fills.sections",
32
+ type: "sourceCollection",
33
+ ...overrides,
34
+ } as ToolcraftControlSchema;
35
+ }
36
+
37
+ describe("defineToolcraft source collection", () => {
38
+ it("accepts a source-owned collection of built-in item controls", () => {
39
+ const app = defineToolcraft(createAppSchema(createSourceCollection()));
40
+ const control = app.panels.controls?.sections.find(
41
+ (section) => section.title === "Fill Sections",
42
+ )?.controls.sections;
43
+
44
+ expect(control?.type).toBe("sourceCollection");
45
+ expect(control?.itemControl?.type).toBe("color");
46
+ });
47
+
48
+ it("requires source collections to declare their built-in item control", () => {
49
+ expect(() =>
50
+ defineToolcraft(
51
+ createAppSchema(createSourceCollection({ itemControl: undefined })),
52
+ ),
53
+ ).toThrow(
54
+ /Toolcraft control validation \[source-collection-item-control\] for target "fills\.sections": itemControl is required/u,
55
+ );
56
+ });
57
+
58
+ it("rejects unsupported collection item controls", () => {
59
+ const control = createSourceCollection({
60
+ itemControl: { type: "imaginary" },
61
+ });
62
+
63
+ expect(() => defineToolcraft(createAppSchema(control))).toThrow(
64
+ /Toolcraft control validation \[collection-item-control\] for target "fills\.sections": unsupported collection item control "imaginary"/u,
65
+ );
66
+ });
67
+
68
+ it("rejects unsupported collectionActions item controls instead of falling back to text", () => {
69
+ const control = {
70
+ ...createSourceCollection(),
71
+ itemControl: { type: "imaginary" },
72
+ type: "collectionActions",
73
+ } as unknown as ToolcraftControlSchema;
74
+
75
+ expect(() => defineToolcraft(createAppSchema(control))).toThrow(
76
+ /Toolcraft control validation \[collection-item-control\] for target "fills\.sections": unsupported collection item control "imaginary"/u,
77
+ );
78
+ });
79
+ });
@@ -1,12 +1,12 @@
1
1
  import { createToolcraftAssemblyContract } from "./assembly-contract";
2
2
  import { resolveToolcraftAppCapabilities } from "./app-capabilities";
3
3
  import { resolveToolcraftAppIdentity } from "./app-identity";
4
+ import { resolveToolcraftCanvasRenderScale } from "./canvas-render-scale";
4
5
  import { normalizeToolcraftPanels } from "./panels-schema-normalization";
5
6
  import { resolveToolcraftPersistencePlan } from "./persistence-plan";
6
7
  import { resolveToolcraftSettingsTransfer } from "./runtime-setup-section";
7
8
  import {
8
9
  defaultToolcraftCanvasSize,
9
- resolveToolcraftCanvasRenderScale,
10
10
  resolveToolcraftCanvasSizing,
11
11
  resolveToolcraftExport,
12
12
  resolveToolcraftMedia,
@@ -38,6 +38,11 @@ const finiteCanvasCondition = Object.freeze({
38
38
  equals: false,
39
39
  target: toolcraftCanvasInfinityTarget,
40
40
  });
41
+ const alwaysApplicable = Object.freeze({ mode: "always" as const });
42
+ const finiteCanvasApplicability = Object.freeze({
43
+ all: [finiteCanvasCondition],
44
+ mode: "conditional" as const,
45
+ });
41
46
 
42
47
  type RuntimeSetupControlGroup = {
43
48
  controls: ToolcraftControlSectionSchema["controls"];
@@ -146,6 +151,7 @@ function createRenderScaleControl(
146
151
  }
147
152
 
148
153
  return {
154
+ applicability: alwaysApplicable,
149
155
  defaultValue: canvas.renderScale.defaultValue,
150
156
  description:
151
157
  "Increases raster canvas backing resolution without changing the visible output size.",
@@ -175,6 +181,7 @@ function createInfinityCanvasControl(
175
181
  }
176
182
 
177
183
  return {
184
+ applicability: alwaysApplicable,
178
185
  defaultValue: getToolcraftDefaultCanvasMode(canvas) === "infinite",
179
186
  ...(background
180
187
  ? {
@@ -199,6 +206,7 @@ function createTimelineExtendedControl(
199
206
  }
200
207
 
201
208
  return {
209
+ applicability: alwaysApplicable,
202
210
  defaultValue: false,
203
211
  label: "Timeline",
204
212
  target: toolcraftTimelinePanelExtendedTarget,
@@ -230,13 +238,23 @@ function createRuntimeSetupBackgroundControls({
230
238
  return {
231
239
  controls: {
232
240
  ...(includeBackgroundControl
233
- ? { includeBackground: includeBackgroundControl }
241
+ ? {
242
+ includeBackground: {
243
+ ...includeBackgroundControl,
244
+ applicability: alwaysApplicable,
245
+ },
246
+ }
234
247
  : {}),
235
248
  ...(infinityCanvasControl
236
249
  ? { infinityCanvas: infinityCanvasControl }
237
250
  : {}),
238
251
  ...(backgroundColorControl
239
- ? { background: backgroundColorControl }
252
+ ? {
253
+ background: {
254
+ ...backgroundColorControl,
255
+ applicability: alwaysApplicable,
256
+ },
257
+ }
240
258
  : {}),
241
259
  },
242
260
  layoutGroups:
@@ -262,6 +280,7 @@ function createFiniteCanvasControls(
262
280
  return {
263
281
  controls: {
264
282
  canvasAspectRatio: {
283
+ applicability: finiteCanvasApplicability,
265
284
  defaultValue: getCanvasAspectRatioDefaultValue(canvas.size),
266
285
  label: "Aspect ratio",
267
286
  orderRole: "input",
@@ -269,9 +288,9 @@ function createFiniteCanvasControls(
269
288
  performanceRole: "workload",
270
289
  target: canvasAspectRatioTarget,
271
290
  type: "aspectRatio",
272
- visibleWhen: finiteCanvasCondition,
273
291
  },
274
292
  canvasWidth: {
293
+ applicability: finiteCanvasApplicability,
275
294
  defaultValue: canvas.size.width,
276
295
  label: "Canvas width",
277
296
  orderRole: "input",
@@ -279,9 +298,9 @@ function createFiniteCanvasControls(
279
298
  performanceRole: "workload",
280
299
  target: canvasSizeControlTargets.width,
281
300
  type: "text",
282
- visibleWhen: finiteCanvasCondition,
283
301
  },
284
302
  canvasHeight: {
303
+ applicability: finiteCanvasApplicability,
285
304
  defaultValue: canvas.size.height,
286
305
  label: "Canvas height",
287
306
  orderRole: "input",
@@ -289,7 +308,6 @@ function createFiniteCanvasControls(
289
308
  performanceRole: "workload",
290
309
  target: canvasSizeControlTargets.height,
291
310
  type: "text",
292
- visibleWhen: finiteCanvasCondition,
293
311
  },
294
312
  },
295
313
  layoutGroups: [
@@ -325,6 +343,7 @@ export function createToolcraftRuntimeSetupSection({
325
343
  const section: ToolcraftControlSectionSchema & { id: string } = {
326
344
  controls: {
327
345
  settingsTransfer: {
346
+ applicability: alwaysApplicable,
328
347
  label: false,
329
348
  target: settingsTransferTarget,
330
349
  type: "settingsTransfer",
@@ -18,14 +18,6 @@ export const defaultToolcraftCanvasSize = {
18
18
  width: 1920,
19
19
  } satisfies ToolcraftCanvasSize;
20
20
 
21
- const defaultCanvasRenderScale = {
22
- defaultValue: 2,
23
- enabled: false,
24
- max: 2,
25
- min: 1,
26
- step: 0.25,
27
- } satisfies ResolvedToolcraftAppSchema["canvas"]["renderScale"];
28
-
29
21
  export function resolveToolcraftCanvasSizing(
30
22
  canvas: ToolcraftAppSchema["canvas"],
31
23
  ): ToolcraftCanvasSizingSchema {
@@ -44,54 +36,6 @@ export function resolveToolcraftCanvasSizing(
44
36
  return { mode: "intrinsic-media" };
45
37
  }
46
38
 
47
- function clampCanvasRenderScale(value: number | undefined, fallback: number): number {
48
- if (typeof value !== "number" || !Number.isFinite(value)) {
49
- return fallback;
50
- }
51
-
52
- return Math.max(1, Math.min(2, value));
53
- }
54
-
55
- export function resolveToolcraftCanvasRenderScale(
56
- renderScale: ToolcraftAppSchema["canvas"]["renderScale"],
57
- ): ResolvedToolcraftAppSchema["canvas"]["renderScale"] {
58
- if (renderScale === true) {
59
- return {
60
- ...defaultCanvasRenderScale,
61
- enabled: true,
62
- };
63
- }
64
-
65
- if (!renderScale) {
66
- return defaultCanvasRenderScale;
67
- }
68
-
69
- const min = clampCanvasRenderScale(renderScale.min, defaultCanvasRenderScale.min);
70
- const max = Math.max(
71
- min,
72
- clampCanvasRenderScale(renderScale.max, defaultCanvasRenderScale.max),
73
- );
74
- const step =
75
- typeof renderScale.step === "number" && Number.isFinite(renderScale.step)
76
- ? Math.max(0.01, Math.min(1, renderScale.step))
77
- : defaultCanvasRenderScale.step;
78
- const defaultValue = Math.max(
79
- min,
80
- Math.min(
81
- max,
82
- clampCanvasRenderScale(renderScale.defaultValue, defaultCanvasRenderScale.defaultValue),
83
- ),
84
- );
85
-
86
- return {
87
- defaultValue,
88
- enabled: renderScale.enabled ?? true,
89
- max,
90
- min,
91
- step,
92
- };
93
- }
94
-
95
39
  export function resolveToolcraftExport(
96
40
  exportSchema: ToolcraftAppSchema["export"],
97
41
  ): ResolvedToolcraftAppSchema["export"] {
@@ -3,6 +3,7 @@ import type {
3
3
  ToolcraftControlLayoutGroupLayout,
4
4
  ToolcraftSectionLayout,
5
5
  } from "../contracts/types";
6
+ import type { ToolcraftCollectionItemControlType } from "./collection-item-controls";
6
7
 
7
8
  export type ToolcraftCanvasSize = {
8
9
  height: number;
@@ -40,10 +41,10 @@ export type ToolcraftCanvasSizingSchema =
40
41
  export type ToolcraftCanvasRenderScaleSchema =
41
42
  | boolean
42
43
  | {
43
- defaultValue?: number;
44
- enabled?: boolean;
45
- max?: number;
46
- min?: number;
44
+ defaultValue?: never;
45
+ enabled?: never;
46
+ max?: never;
47
+ min?: never;
47
48
  step?: number;
48
49
  };
49
50
 
@@ -412,7 +413,7 @@ export type ResolvedToolcraftMediaSchema = {
412
413
  defaultAssets: readonly ToolcraftDefaultMediaAssetSchema[];
413
414
  };
414
415
 
415
- export type ToolcraftControlConditionSchema = {
416
+ export type ToolcraftControlPredicateSchema = Readonly<{
416
417
  equals?: unknown;
417
418
  greaterThan?: number;
418
419
  greaterThanOrEqual?: number;
@@ -422,7 +423,28 @@ export type ToolcraftControlConditionSchema = {
422
423
  notEquals?: unknown;
423
424
  oneOf?: readonly unknown[];
424
425
  target: string;
425
- };
426
+ }>;
427
+
428
+ export type ToolcraftControlConditionSchema =
429
+ ToolcraftControlPredicateSchema;
430
+
431
+ export type ToolcraftControlApplicabilitySchema =
432
+ | Readonly<{ mode: "always" }>
433
+ | Readonly<{
434
+ all: readonly ToolcraftControlPredicateSchema[];
435
+ mode: "conditional";
436
+ }>;
437
+
438
+ export type ToolcraftResolvedControlApplicabilitySchema =
439
+ | Readonly<{
440
+ mode: "always";
441
+ origin: "explicit" | "implicit";
442
+ }>
443
+ | Readonly<{
444
+ all: readonly ToolcraftControlPredicateSchema[];
445
+ mode: "conditional";
446
+ origin: "explicit" | "legacy";
447
+ }>;
426
448
 
427
449
  export type ToolcraftControlDisabledConditionSchema =
428
450
  ToolcraftControlConditionSchema;
@@ -434,18 +456,29 @@ export type ToolcraftColorOpacityValueSchema = {
434
456
 
435
457
  export type ToolcraftCollectionItemControlSchema = {
436
458
  commitMode?: "content" | "setting";
459
+ coordinateMode?: ToolcraftVectorCoordinateMode;
437
460
  defaultValue?: unknown;
461
+ description?: string;
438
462
  label?: boolean | string;
439
463
  markerCount?: number;
440
464
  max?: number;
441
465
  min?: number;
442
466
  options?: readonly { label: string; value: string }[];
467
+ performanceReason?: string;
468
+ performanceRole?: ToolcraftControlPerformanceRole;
469
+ sliderValueKind?: ToolcraftSliderValueKind;
443
470
  step?: number;
444
- type: string;
471
+ type: ToolcraftCollectionItemControlType;
445
472
  unit?: string;
446
473
  variant?: string;
474
+ xLabel?: string;
475
+ yLabel?: string;
447
476
  };
448
477
 
478
+ export type ToolcraftCollectionItemControlsSchema = Readonly<
479
+ Record<string, ToolcraftCollectionItemControlSchema>
480
+ >;
481
+
449
482
  export type ToolcraftFontPickerValueSchema = {
450
483
  color?: string;
451
484
  fontId: string;
@@ -461,7 +494,7 @@ export type ToolcraftCurveInterpolation = "monotone" | "smooth";
461
494
 
462
495
  export type ToolcraftVectorCoordinateMode = "cartesian" | "screen";
463
496
 
464
- export type ToolcraftControlSchemaBase = {
497
+ type ToolcraftControlSchemaFields = {
465
498
  accept?: string;
466
499
  actions?: readonly (ToolcraftActionSchema | string)[];
467
500
  addLabel?: string;
@@ -476,6 +509,7 @@ export type ToolcraftControlSchemaBase = {
476
509
  interpolation?: ToolcraftCurveInterpolation;
477
510
  items?: readonly ToolcraftImagePickerItemSchema[];
478
511
  itemControl?: ToolcraftCollectionItemControlSchema;
512
+ itemControls?: ToolcraftCollectionItemControlsSchema;
479
513
  itemDefaultValue?: unknown;
480
514
  itemLabel?: string;
481
515
  keyframeable?: boolean;
@@ -498,11 +532,16 @@ export type ToolcraftControlSchemaBase = {
498
532
  unit?: string;
499
533
  valueLabel?: string;
500
534
  variant?: string;
501
- visibleWhen?: ToolcraftControlConditionSchema;
502
535
  xLabel?: string;
503
536
  yLabel?: string;
504
537
  };
505
538
 
539
+ export type ToolcraftControlSchemaBase = ToolcraftControlSchemaFields & {
540
+ applicability?: ToolcraftControlApplicabilitySchema;
541
+ /** @deprecated Product controls use conditional applicability. */
542
+ visibleWhen?: ToolcraftControlPredicateSchema;
543
+ };
544
+
506
545
  export type ToolcraftNonModelControlSchema = ToolcraftControlSchemaBase & {
507
546
  assetKind?: ToolcraftMediaAssetKind;
508
547
  modelFormats?: never;
@@ -525,18 +564,34 @@ export type ToolcraftControlSchema =
525
564
  | ToolcraftNonModelControlSchema
526
565
  | ToolcraftModelFileDropSchema;
527
566
 
567
+ type ToolcraftResolvedControlApplicabilityFields = Readonly<{
568
+ applicability: ToolcraftResolvedControlApplicabilitySchema;
569
+ }>;
570
+
571
+ export type ResolvedToolcraftNonModelControlSchema = Omit<
572
+ ToolcraftNonModelControlSchema,
573
+ "applicability" | "visibleWhen"
574
+ > &
575
+ ToolcraftResolvedControlApplicabilityFields;
576
+
528
577
  export type ResolvedToolcraftModelFileDropSchema = Omit<
529
578
  ToolcraftModelFileDropSchema,
530
- "modelFormats" | "modelLimits" | "multiple" | "topologyProfile"
531
- > & {
532
- modelFormats: readonly ToolcraftModelFormat[];
533
- modelLimits: ToolcraftModelImportLimits;
534
- multiple: false;
535
- topologyProfile: ToolcraftModelTopologyProfile;
536
- };
579
+ | "applicability"
580
+ | "modelFormats"
581
+ | "modelLimits"
582
+ | "multiple"
583
+ | "topologyProfile"
584
+ | "visibleWhen"
585
+ > &
586
+ ToolcraftResolvedControlApplicabilityFields & {
587
+ modelFormats: readonly ToolcraftModelFormat[];
588
+ modelLimits: ToolcraftModelImportLimits;
589
+ multiple: false;
590
+ topologyProfile: ToolcraftModelTopologyProfile;
591
+ };
537
592
 
538
593
  export type ResolvedToolcraftControlSchema =
539
- | ToolcraftNonModelControlSchema
594
+ | ResolvedToolcraftNonModelControlSchema
540
595
  | ResolvedToolcraftModelFileDropSchema;
541
596
 
542
597
  export type ToolcraftControlLayoutGroupSchema = {