@pixel-point/toolcraft 0.0.14 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -2
- package/package.json +1 -1
- package/scripts/prepare-pack.mjs +2 -28
- package/src/cli-io.mjs +174 -0
- package/src/cli-package-manager-flow.test.mjs +206 -0
- package/src/cli.mjs +7 -495
- package/src/cli.test.mjs +34 -177
- package/src/create-command.mjs +152 -0
- package/src/create-options.mjs +194 -0
- package/src/generate-test-assertions.mjs +27 -0
- package/src/generate-test-doc-assertions.mjs +162 -0
- package/src/generate-test-file-assertions.mjs +251 -0
- package/src/generate-test-fs-utils.mjs +59 -0
- package/src/generate-test-integrity-assertions.mjs +30 -0
- package/src/generate-test-integrity-framework-assertions.mjs +222 -0
- package/src/generate-test-integrity-manifest-assertions.mjs +150 -0
- package/src/generate-test-integrity-ownership-assertions.mjs +127 -0
- package/src/generate-test-integrity-test-utils.mjs +102 -0
- package/src/generate-test-package-assertions.mjs +75 -0
- package/src/generate-test-product-fixture.mjs +84 -0
- package/src/generate-test-product-fixture.test.mjs +73 -0
- package/src/generate-test-standalone-assertions.mjs +209 -0
- package/src/generate-transactional.test.mjs +151 -0
- package/src/generate.mjs +182 -102
- package/src/generate.test.mjs +242 -338
- package/src/generated-integrity-manifest.mjs +127 -0
- package/src/generated-integrity-manifest.test.mjs +151 -0
- package/src/generated-source-policy.mjs +22 -0
- package/src/generated-source-policy.test.mjs +35 -0
- package/src/generated-target-policy.mjs +55 -0
- package/src/generation-transaction.mjs +135 -0
- package/src/generation-transaction.test.mjs +74 -0
- package/src/package-json.mjs +18 -1
- package/src/package-json.test.mjs +38 -5
- package/src/package-manager.mjs +2 -0
- package/src/package-manager.test.mjs +5 -1
- package/src/packaged-template-fallback.test.mjs +126 -0
- package/src/prepare-pack-templates.mjs +34 -0
- package/templates/runtime/contracts/component-contract-builders.ts +95 -0
- package/templates/runtime/contracts/component-contracts.choices.test.ts +293 -0
- package/templates/runtime/contracts/component-contracts.choices.ts +322 -0
- package/templates/runtime/contracts/component-contracts.inputs.test.ts +210 -0
- package/templates/runtime/contracts/component-contracts.inputs.ts +252 -0
- package/templates/runtime/contracts/component-contracts.media-custom.test.ts +116 -0
- package/templates/runtime/contracts/component-contracts.media-custom.ts +144 -0
- package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +229 -0
- package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +76 -0
- package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +135 -0
- package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +148 -0
- package/templates/runtime/contracts/component-contracts.runtime.ts +361 -0
- package/templates/runtime/contracts/component-contracts.test.ts +39 -1458
- package/templates/runtime/contracts/component-contracts.ts +44 -1505
- package/templates/runtime/contracts/component-contracts.visual.test.ts +316 -0
- package/templates/runtime/contracts/component-contracts.visual.ts +385 -0
- package/templates/runtime/contracts/contract-manifest.test.ts +64 -0
- package/templates/runtime/contracts/decision-contracts.test.ts +29 -4
- package/templates/runtime/contracts/decision-contracts.ts +38 -1
- package/templates/runtime/index.ts +1 -0
- package/templates/runtime/react/{runtime-public-api.test.tsx → app-shell/runtime-public-api.test.tsx} +29 -7
- package/templates/runtime/react/{settings-transfer.test.ts → app-shell/settings-transfer.test.ts} +4 -4
- package/templates/runtime/react/{settings-transfer.ts → app-shell/settings-transfer.ts} +3 -3
- package/templates/runtime/react/{toolbar-panel.test.tsx → app-shell/toolbar-panel.test.tsx} +2 -2
- package/templates/runtime/react/{toolbar-panel.tsx → app-shell/toolbar-panel.tsx} +3 -3
- package/templates/runtime/react/{toolcraft-app.integration.test.tsx → app-shell/toolcraft-app.integration.test.tsx} +6 -6
- package/templates/runtime/react/{toolcraft-app.test.tsx → app-shell/toolcraft-app.test.tsx} +3 -3
- package/templates/runtime/react/{toolcraft-app.tsx → app-shell/toolcraft-app.tsx} +11 -8
- package/templates/runtime/react/{toolcraft-root.test.tsx → app-shell/toolcraft-root.test.tsx} +1 -1
- package/templates/runtime/react/{toolcraft-root.tsx → app-shell/toolcraft-root.tsx} +5 -5
- package/templates/runtime/react/{use-toolcraft.ts → app-shell/use-toolcraft.ts} +1 -1
- package/templates/runtime/react/canvas/canvas-default-media-layer.tsx +81 -0
- package/templates/runtime/react/canvas/canvas-media-transform.ts +33 -0
- package/templates/runtime/react/canvas/canvas-shell-interactions.test.tsx +156 -0
- package/templates/runtime/react/canvas/canvas-shell-media-rendering.test.tsx +87 -0
- package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +102 -0
- package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +108 -0
- package/templates/runtime/react/canvas/canvas-shell-upload.test.tsx +106 -0
- package/templates/runtime/react/canvas/canvas-shell.tsx +146 -0
- package/templates/runtime/react/canvas/canvas-upload-routing.ts +84 -0
- package/templates/runtime/react/{media-file.ts → canvas/media-file.ts} +1 -1
- package/templates/runtime/react/canvas/use-canvas-drop-import.ts +145 -0
- package/templates/runtime/react/canvas/use-canvas-viewport-interactions.ts +227 -0
- package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +89 -0
- package/templates/runtime/react/{controls-panel-filedrop-reorder.test.tsx → controls-panel/__tests__/controls-panel-filedrop-reorder.test.tsx} +4 -4
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.actions-layout.test.tsx +91 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +213 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-layout.test.tsx +366 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-picker-models.test.tsx +169 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.compound-layout.test.tsx +160 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +352 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.curves.test.tsx +226 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.floating-shell.test.tsx +13 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.font-picker.test.tsx +302 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +401 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.gradient-control.test.tsx +139 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.help-policy.test.tsx +103 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.image-picker.test.tsx +16 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.inline-layout.test.tsx +290 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.keyframes.test.tsx +175 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.media-upload-files.test.tsx +121 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.media-upload-image.test.tsx +363 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.media-upload-multi-image.test.tsx +105 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.range-slider-editing.test.tsx +149 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.section-shell.test.tsx +138 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.select-layout.test.tsx +148 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.setup-controls.test.tsx +189 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.slider-rendering.test.tsx +317 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.state-reset.test.tsx +137 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.structure.test.tsx +66 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.text-input.test.tsx +205 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.vector-interaction.test.tsx +388 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.vector-layout.test.tsx +155 -0
- package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +172 -0
- package/templates/runtime/react/{control-conditions.ts → controls-panel/conditions/control-conditions.ts} +26 -3
- package/templates/runtime/react/{control-renderers.ts → controls-panel/control-renderers.ts} +2 -2
- package/templates/runtime/react/controls-panel/controls-panel.tsx +250 -0
- package/templates/runtime/react/controls-panel/keyframes/controls-panel-keyframes.tsx +265 -0
- package/templates/runtime/react/controls-panel/layout/controls-panel-collapse-storage.ts +131 -0
- package/templates/runtime/react/controls-panel/layout/controls-panel-help.tsx +132 -0
- package/templates/runtime/react/controls-panel/layout/controls-panel-inline-layout.tsx +311 -0
- package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +216 -0
- package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +401 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-action-renderer.tsx +137 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-basic-renderers.tsx +421 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +286 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-compound-renderers.tsx +366 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +173 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +23 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +55 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-settings-transfer-renderer.tsx +45 -0
- package/templates/runtime/react/controls-panel/testing/controls-panel-test-utils.tsx +300 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-aspect-ratio-values.ts +94 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +87 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-color-values.ts +82 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-font-values.ts +69 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-spatial-values.ts +64 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +93 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-value-primitives.ts +30 -0
- package/templates/runtime/react/controls-panel/values/controls-panel-values.ts +7 -0
- package/templates/runtime/react/index.ts +13 -13
- package/templates/runtime/react/{layer-tree.ts → layers/layer-tree.ts} +1 -1
- package/templates/runtime/react/layers/layers-panel-drag-drop.test.tsx +190 -0
- package/templates/runtime/react/layers/layers-panel-editing.test.tsx +41 -0
- package/templates/runtime/react/layers/layers-panel-insert-targets.test.ts +87 -0
- package/templates/runtime/react/layers/layers-panel-insert-targets.ts +254 -0
- package/templates/runtime/react/layers/layers-panel-model.ts +15 -0
- package/templates/runtime/react/layers/layers-panel-rendering.test.tsx +43 -0
- package/templates/runtime/react/layers/layers-panel-reorder.ts +148 -0
- package/templates/runtime/react/layers/layers-panel-row.tsx +475 -0
- package/templates/runtime/react/layers/layers-panel-test-utils.tsx +135 -0
- package/templates/runtime/react/layers/layers-panel-visibility.test.tsx +126 -0
- package/templates/runtime/react/layers/layers-panel.tsx +349 -0
- package/templates/runtime/react/layers/use-layers-panel-drag-controller.ts +327 -0
- package/templates/runtime/react/{panel-host-types.ts → panel-host/panel-host-types.ts} +2 -2
- package/templates/runtime/react/{panel-host.test.tsx → panel-host/panel-host.test.tsx} +3 -3
- package/templates/runtime/react/{panel-host.tsx → panel-host/panel-host.tsx} +1 -1
- package/templates/runtime/react/timeline/timeline-easing-editor.tsx +409 -0
- package/templates/runtime/react/timeline/timeline-easing-geometry.ts +42 -0
- package/templates/runtime/react/timeline/timeline-easing-icons.tsx +135 -0
- package/templates/runtime/react/timeline/timeline-easing-model.test.ts +87 -0
- package/templates/runtime/react/timeline/timeline-easing-model.ts +271 -0
- package/templates/runtime/react/timeline/timeline-easing-popover-content.tsx +227 -0
- package/templates/runtime/react/timeline/timeline-easing-popover-layout.ts +69 -0
- package/templates/runtime/react/timeline/timeline-easing-popover.tsx +60 -0
- package/templates/runtime/react/timeline/timeline-event-targets.ts +19 -0
- package/templates/runtime/react/timeline/timeline-expanded-content.tsx +299 -0
- package/templates/runtime/react/timeline/timeline-icon-button.tsx +51 -0
- package/templates/runtime/react/timeline/timeline-keyframe-row.tsx +360 -0
- package/templates/runtime/react/timeline/timeline-keyframes.ts +23 -0
- package/templates/runtime/react/timeline/timeline-panel-floating-layout.test.tsx +328 -0
- package/templates/runtime/react/timeline/timeline-panel-header.tsx +404 -0
- package/templates/runtime/react/timeline/timeline-panel-keyframes.test.tsx +90 -0
- package/templates/runtime/react/timeline/timeline-panel-layout.ts +30 -0
- package/templates/runtime/react/timeline/timeline-panel-responsive-layout.ts +182 -0
- package/templates/runtime/react/timeline/timeline-panel-test-utils.tsx +88 -0
- package/templates/runtime/react/timeline/timeline-panel-transport.test.tsx +202 -0
- package/templates/runtime/react/timeline/timeline-panel-upload.test.tsx +53 -0
- package/templates/runtime/react/timeline/timeline-panel.tsx +449 -0
- package/templates/runtime/react/timeline/timeline-playback-hooks.ts +254 -0
- package/templates/runtime/schema/assembly-contract.ts +271 -0
- package/templates/runtime/schema/control-schema-normalization.ts +55 -0
- package/templates/runtime/schema/controls-panel-actions.ts +141 -0
- package/templates/runtime/schema/controls-panel-layout-groups.ts +144 -0
- package/templates/runtime/schema/controls-panel-normalization.ts +19 -0
- package/templates/runtime/schema/controls-panel-section-layout.ts +140 -0
- package/templates/runtime/schema/controls-panel-section-titles.ts +161 -0
- package/templates/runtime/schema/define-toolcraft-test-utils.ts +18 -0
- package/templates/runtime/schema/define-toolcraft.actions.test.ts +182 -0
- package/templates/runtime/schema/define-toolcraft.assembly.test.ts +246 -0
- package/templates/runtime/schema/define-toolcraft.canvas.test.ts +150 -0
- package/templates/runtime/schema/define-toolcraft.control-layout.test.ts +345 -0
- package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +304 -0
- package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +69 -0
- package/templates/runtime/schema/define-toolcraft.setup-persistence.test.ts +66 -0
- package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +116 -0
- package/templates/runtime/schema/define-toolcraft.setup-settings-transfer.test.ts +291 -0
- package/templates/runtime/schema/define-toolcraft.ts +24 -1449
- package/templates/runtime/schema/panels-schema-normalization.ts +49 -0
- package/templates/runtime/schema/runtime-section-titles.ts +1 -0
- package/templates/runtime/schema/runtime-setup-section.ts +282 -0
- package/templates/runtime/schema/schema-resolvers.ts +168 -0
- package/templates/runtime/schema/types.ts +17 -0
- package/templates/runtime/state/canvas-reducer.ts +106 -0
- package/templates/runtime/state/canvas-state.ts +209 -0
- package/templates/runtime/state/controls-reducer.ts +277 -0
- package/templates/runtime/state/history-patches.ts +174 -0
- package/templates/runtime/state/layer-state.ts +12 -0
- package/templates/runtime/state/layers-reducer.ts +318 -0
- package/templates/runtime/state/media-reducer.ts +283 -0
- package/templates/runtime/state/media-state.ts +105 -0
- package/templates/runtime/state/panels-reducer.ts +58 -0
- package/templates/runtime/state/persistence-merge.ts +53 -0
- package/templates/runtime/state/persistence-reader-canvas.ts +27 -0
- package/templates/runtime/state/persistence-reader-layers.ts +73 -0
- package/templates/runtime/state/persistence-reader-media.ts +82 -0
- package/templates/runtime/state/persistence-reader-panels.ts +56 -0
- package/templates/runtime/state/persistence-reader-primitives.ts +27 -0
- package/templates/runtime/state/persistence-reader-timeline.ts +145 -0
- package/templates/runtime/state/persistence-reader-values.ts +40 -0
- package/templates/runtime/state/persistence-readers.ts +72 -0
- package/templates/runtime/state/persistence-shared.ts +23 -0
- package/templates/runtime/state/persistence-snapshot.ts +57 -0
- package/templates/runtime/state/persistence.ts +16 -581
- package/templates/runtime/state/reducer-canvas-panels.test.ts +324 -0
- package/templates/runtime/state/reducer-controls.test.ts +158 -0
- package/templates/runtime/state/reducer-layers.test.ts +306 -0
- package/templates/runtime/state/reducer-media-import-sizing.test.ts +197 -0
- package/templates/runtime/state/reducer-media-reorder-history.test.ts +116 -0
- package/templates/runtime/state/reducer-media-reset.test.ts +249 -0
- package/templates/runtime/state/reducer-media-test-utils.ts +40 -0
- package/templates/runtime/state/reducer-media-transform.test.ts +52 -0
- package/templates/runtime/state/reducer-test-utils.ts +30 -0
- package/templates/runtime/state/reducer-timeline.test.ts +242 -0
- package/templates/runtime/state/reducer.ts +57 -1785
- package/templates/runtime/state/timeline-reducer.ts +412 -0
- package/templates/runtime/state/timeline-values.test.ts +45 -0
- package/templates/runtime/state/timeline-values.ts +45 -0
- package/templates/runtime/testing/performance-browser-policy.test.ts +81 -0
- package/templates/runtime/testing/performance-browser-policy.ts +102 -0
- package/templates/runtime/testing/performance-budget-validation.ts +84 -0
- package/templates/runtime/testing/performance-control-classification.test.ts +106 -0
- package/templates/runtime/testing/performance-control-classification.ts +101 -0
- package/templates/runtime/testing/performance-coverage-context.ts +44 -0
- package/templates/runtime/testing/performance-coverage-renderer-policy.ts +221 -0
- package/templates/runtime/testing/performance-coverage-scenario-policy.ts +147 -0
- package/templates/runtime/testing/performance-coverage-target-policy.ts +121 -0
- package/templates/runtime/testing/performance-coverage-validator.ts +34 -0
- package/templates/runtime/testing/performance-export-coverage.test.ts +234 -0
- package/templates/runtime/testing/performance-fixture-load-profile.test.ts +360 -0
- package/templates/runtime/testing/performance-fixture-media.test.ts +80 -0
- package/templates/runtime/testing/performance-fixture-stress.test.ts +314 -0
- package/templates/runtime/testing/performance-fixture-validation.ts +255 -0
- package/templates/runtime/testing/performance-fixture-values.ts +275 -0
- package/templates/runtime/testing/performance-fixture-workload.test.ts +140 -0
- package/templates/runtime/testing/performance-load-profile-validation.ts +467 -0
- package/templates/runtime/testing/performance-renderer-coverage.test.ts +325 -0
- package/templates/runtime/testing/performance-renderer-pipeline-coverage.test.ts +115 -0
- package/templates/runtime/testing/performance-renderer-pipeline-interactions.test.ts +201 -0
- package/templates/runtime/testing/performance-renderer-pipeline-passes.test.ts +247 -0
- package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +360 -0
- package/templates/runtime/testing/performance-renderer-technique-validation.ts +329 -0
- package/templates/runtime/testing/performance-renderer-technique.test.ts +275 -0
- package/templates/runtime/testing/performance-renderer-validation.ts +2 -0
- package/templates/runtime/testing/performance-scenario-coverage.test.ts +303 -0
- package/templates/runtime/testing/performance-scenario-validation.ts +49 -0
- package/templates/runtime/testing/performance-schema-derived-workloads.test.ts +231 -0
- package/templates/runtime/testing/performance-schema-queries.ts +181 -0
- package/templates/runtime/testing/performance-test-fixtures/index.ts +4 -0
- package/templates/runtime/testing/performance-test-fixtures/renderer-pipelines.ts +322 -0
- package/templates/runtime/testing/performance-test-fixtures/scenarios.ts +172 -0
- package/templates/runtime/testing/performance-test-fixtures/schemas.ts +151 -0
- package/templates/runtime/testing/performance-test-fixtures/stress-fixtures.ts +133 -0
- package/templates/runtime/testing/performance-test-fixtures.ts +1 -0
- package/templates/runtime/testing/performance-types.ts +338 -0
- package/templates/runtime/testing/performance.ts +15 -2485
- package/templates/starter/AGENTS.md +41 -26
- package/templates/starter/LICENSE.md +18 -95
- package/templates/starter/NOTICE.md +3 -3
- package/templates/starter/docs/toolcraft/README.md +5 -5
- package/templates/starter/docs/toolcraft/acceptance-testing.md +36 -8
- package/templates/starter/docs/toolcraft/assembly-workflow.md +12 -15
- package/templates/starter/docs/toolcraft/component-rules.md +6 -2
- package/templates/starter/docs/toolcraft/core/layout.md +1 -0
- package/templates/starter/docs/toolcraft/core/performance.md +7 -4
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +11 -4
- package/templates/starter/docs/toolcraft/core/timeline-animation.md +1 -0
- package/templates/starter/docs/toolcraft/custom-controls.md +8 -1
- package/templates/starter/docs/toolcraft/decision-contract.md +26 -22
- package/templates/starter/docs/toolcraft/performance.md +42 -16
- package/templates/starter/docs/toolcraft/schema-reference.md +34 -23
- package/templates/starter/docs/toolcraft/workflow.md +25 -17
- package/templates/starter/e2e/app-browser-acceptance-evidence.spec.ts +111 -0
- package/templates/starter/e2e/app-browser-control-coverage.spec.ts +118 -0
- package/templates/starter/e2e/app-browser-performance-evidence.spec.ts +217 -0
- package/templates/starter/e2e/app-browser-performance-probe.spec.ts +322 -0
- package/templates/starter/e2e/app-browser-proof-session.spec.ts +196 -0
- package/templates/starter/e2e/app-browser-runtime-evidence.spec.ts +9 -0
- package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +240 -0
- package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +180 -0
- package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +310 -0
- package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +432 -0
- package/templates/starter/e2e/app-browser-shell.spec.ts +171 -0
- package/templates/starter/e2e/app-browser-timeline-layers-reference.spec.ts +70 -0
- package/templates/starter/e2e/app-performance.spec.ts +0 -491
- package/templates/starter/e2e/browser-acceptance-outcome-helpers.ts +97 -0
- package/templates/starter/e2e/browser-acceptance-transition-helpers.ts +74 -0
- package/templates/starter/e2e/browser-conditional-output-evidence-helpers.ts +230 -0
- package/templates/starter/e2e/browser-control-target-helpers.ts +109 -0
- package/templates/starter/e2e/browser-layer-evidence-helpers.ts +229 -0
- package/templates/starter/e2e/browser-proof-session.ts +392 -0
- package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +136 -0
- package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +290 -0
- package/templates/starter/e2e/browser-runtime-evidence.ts +27 -0
- package/templates/starter/e2e/browser-state-evidence-helpers.ts +205 -0
- package/templates/starter/e2e/browser-timeline-evidence-helpers.ts +319 -0
- package/templates/starter/e2e/canvas-handle-helpers.ts +86 -4
- package/templates/starter/e2e/export-artifact-helpers.ts +132 -0
- package/templates/starter/e2e/performance-budget-helpers.ts +159 -0
- package/templates/starter/e2e/performance-canvas-helpers.ts +123 -0
- package/templates/starter/e2e/performance-control-helpers.ts +3 -0
- package/templates/starter/e2e/performance-control-layout-helpers.ts +161 -0
- package/templates/starter/e2e/performance-fixture-helpers.ts +217 -0
- package/templates/starter/e2e/performance-frame-probe.ts +247 -0
- package/templates/starter/e2e/performance-helpers.ts +6 -854
- package/templates/starter/e2e/performance-interaction-measurement.ts +251 -0
- package/templates/starter/e2e/performance-measurement-evidence.ts +72 -0
- package/templates/starter/e2e/performance-output-action-helpers.spec.ts +43 -0
- package/templates/starter/e2e/performance-output-action-helpers.ts +109 -0
- package/templates/starter/e2e/performance-probe-helpers.ts +12 -0
- package/templates/starter/e2e/performance-render-scale-helpers.ts +55 -0
- package/templates/starter/e2e/performance-slider-helpers.ts +271 -0
- package/templates/starter/e2e/product-observable-helpers.ts +72 -17
- package/templates/starter/e2e/stable-outcome-helpers.ts +208 -0
- package/templates/starter/package.json +10 -5
- package/templates/starter/playwright.config.ts +5 -2
- package/templates/starter/scripts/check-ai-skills.mjs +14 -8
- package/templates/starter/scripts/check-ai-skills.test.mjs +64 -0
- package/templates/starter/scripts/check-toolcraft-code-health.mjs +108 -0
- package/templates/starter/scripts/check-toolcraft-code-health.test.mjs +213 -0
- package/templates/starter/scripts/check-toolcraft-docs.mjs +47 -34
- package/templates/starter/scripts/check-toolcraft-integrity.mjs +141 -144
- package/templates/starter/scripts/run-browser-performance.mjs +118 -0
- package/templates/starter/scripts/run-browser-performance.test.mjs +53 -0
- package/templates/starter/scripts/toolcraft-code-health-core.mjs +297 -0
- package/templates/starter/scripts/toolcraft-contract-doc-integrity.mjs +77 -0
- package/templates/starter/scripts/toolcraft-contract-doc-integrity.test.mjs +81 -0
- package/templates/starter/scripts/toolcraft-contract-manifest.json +113 -0
- package/templates/starter/scripts/toolcraft-contract-manifest.mjs +128 -0
- package/templates/starter/scripts/toolcraft-contract-manifest.test.mjs +72 -0
- package/templates/starter/scripts/toolcraft-integrity-manifest.mjs +172 -0
- package/templates/starter/scripts/toolcraft-integrity-policy.mjs +60 -0
- package/templates/starter/scripts/toolcraft-product-boundary-ast-utils.mjs +23 -0
- package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +264 -0
- package/templates/starter/scripts/toolcraft-product-boundary-test-fixtures.mjs +16 -0
- package/templates/starter/scripts/toolcraft-product-boundary.mjs +243 -0
- package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +289 -0
- package/templates/starter/scripts/toolcraft-product-dependency-graph.mjs +176 -0
- package/templates/starter/scripts/toolcraft-product-dependency-graph.test.mjs +196 -0
- package/templates/starter/scripts/toolcraft-product-dependency-resolution.mjs +279 -0
- package/templates/starter/scripts/toolcraft-product-evidence-boundary-ast.mjs +91 -0
- package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +138 -0
- package/templates/starter/scripts/toolcraft-product-style-boundary.mjs +219 -0
- package/templates/starter/scripts/toolcraft-source-inventory.d.mts +46 -0
- package/templates/starter/scripts/toolcraft-source-inventory.mjs +187 -0
- package/templates/starter/scripts/toolcraft-source-inventory.test.mjs +132 -0
- package/templates/starter/scripts/toolcraft-source-ownership.mjs +167 -0
- package/templates/starter/scripts/toolcraft-source-ownership.test.mjs +113 -0
- package/templates/starter/scripts/toolcraft-static-string.mjs +104 -0
- package/templates/starter/scripts/toolcraft-verification-inventory.mjs +123 -0
- package/templates/starter/scripts/toolcraft-verification-receipt.d.mts +19 -0
- package/templates/starter/scripts/toolcraft-verification-receipt.mjs +284 -0
- package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +282 -0
- package/templates/starter/scripts/toolcraft-vitest-runtime-contract.d.mts +32 -0
- package/templates/starter/scripts/toolcraft-vitest-runtime-contract.mjs +88 -0
- package/templates/starter/scripts/toolcraft-vitest-runtime-contract.test.mjs +87 -0
- package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.mjs +109 -0
- package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.test.mjs +111 -0
- package/templates/starter/scripts/toolcraft-workflow-routes.mjs +314 -0
- package/templates/starter/scripts/toolcraft-workflow-routes.test.mjs +204 -0
- package/templates/starter/src/app/acceptance/actions.ts +30 -0
- package/templates/starter/src/app/acceptance/animation-intent.ts +184 -0
- package/templates/starter/src/app/acceptance/canvas-handle-acceptance.ts +70 -0
- package/templates/starter/src/app/acceptance/color-bank-labels.ts +164 -0
- package/templates/starter/src/app/acceptance/conditions.ts +80 -0
- package/templates/starter/src/app/acceptance/control-acceptance-context.ts +70 -0
- package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +271 -0
- package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +149 -0
- package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +189 -0
- package/templates/starter/src/app/acceptance/control-acceptance.ts +70 -0
- package/templates/starter/src/app/acceptance/control-component-rules.ts +277 -0
- package/templates/starter/src/app/acceptance/control-labels.ts +223 -0
- package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +107 -0
- package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +104 -0
- package/templates/starter/src/app/acceptance/control-layout-model.ts +159 -0
- package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +164 -0
- package/templates/starter/src/app/acceptance/control-layout.ts +45 -0
- package/templates/starter/src/app/acceptance/control-order.ts +123 -0
- package/templates/starter/src/app/acceptance/control-parts.ts +47 -0
- package/templates/starter/src/app/acceptance/control-section-inventory.ts +183 -0
- package/templates/starter/src/app/acceptance/controls.ts +27 -0
- package/templates/starter/src/app/acceptance/coverage.ts +81 -0
- package/templates/starter/src/app/acceptance/custom-controls.ts +140 -0
- package/templates/starter/src/app/acceptance/inline-layout.ts +192 -0
- package/templates/starter/src/app/acceptance/media-upload.ts +55 -0
- package/templates/starter/src/app/acceptance/output-background-rules.ts +135 -0
- package/templates/starter/src/app/acceptance/output-export-actions.test.ts +76 -0
- package/templates/starter/src/app/acceptance/output-export-actions.ts +34 -0
- package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +46 -0
- package/templates/starter/src/app/acceptance/output-export-model.ts +146 -0
- package/templates/starter/src/app/acceptance/output-export.ts +45 -0
- package/templates/starter/src/app/acceptance/output-image-export-rules.ts +87 -0
- package/templates/starter/src/app/acceptance/reference-runtime-coverage.ts +96 -0
- package/templates/starter/src/app/acceptance/reference-runtime-feature-inventory.ts +171 -0
- package/templates/starter/src/app/acceptance/reference-runtime-study.ts +73 -0
- package/templates/starter/src/app/acceptance/reference-runtime-timeline.ts +291 -0
- package/templates/starter/src/app/acceptance/reference-runtime.ts +99 -0
- package/templates/starter/src/app/acceptance/runtime-coverage.ts +290 -0
- package/templates/starter/src/app/acceptance/runtime-setup.ts +117 -0
- package/templates/starter/src/app/acceptance/section-title-rules.ts +8 -0
- package/templates/starter/src/app/acceptance/sections.ts +6 -0
- package/templates/starter/src/app/acceptance/semantic.ts +63 -0
- package/templates/starter/src/app/acceptance/timeline-loop.ts +21 -0
- package/templates/starter/src/app/acceptance/types.ts +363 -0
- package/templates/starter/src/app/acceptance/validate-coverage.ts +217 -0
- package/templates/starter/src/app/acceptance/validation-pipeline.test.ts +56 -0
- package/templates/starter/src/app/acceptance/validation-pipeline.ts +60 -0
- package/templates/starter/src/app/acceptance/video-reference-study.ts +217 -0
- package/templates/starter/src/app/starter-acceptance-data.ts +21 -0
- package/templates/starter/src/app/starter-acceptance.animation-intent.test.ts +383 -0
- package/templates/starter/src/app/starter-acceptance.background-export.test.ts +349 -0
- package/templates/starter/src/app/starter-acceptance.base-coverage.test.ts +47 -0
- package/templates/starter/src/app/starter-acceptance.canvas-handles.test.ts +71 -0
- package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +199 -0
- package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +244 -0
- package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +63 -0
- package/templates/starter/src/app/starter-acceptance.control-label-context.test.ts +172 -0
- package/templates/starter/src/app/starter-acceptance.control-labels.test.ts +387 -0
- package/templates/starter/src/app/starter-acceptance.control-naming-rules.test.ts +215 -0
- package/templates/starter/src/app/starter-acceptance.control-order.test.ts +274 -0
- package/templates/starter/src/app/starter-acceptance.control-state.test.ts +275 -0
- package/templates/starter/src/app/starter-acceptance.curves-rules.test.ts +184 -0
- package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +200 -0
- package/templates/starter/src/app/starter-acceptance.custom-control-coverage.test.ts +111 -0
- package/templates/starter/src/app/starter-acceptance.custom-control-fit-check.test.ts +135 -0
- package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +74 -0
- package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +107 -0
- package/templates/starter/src/app/starter-acceptance.framework-boundary.test.ts +327 -0
- package/templates/starter/src/app/starter-acceptance.image-video-export-settings.test.ts +328 -0
- package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +242 -0
- package/templates/starter/src/app/starter-acceptance.layers.test.ts +203 -0
- package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +110 -0
- package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +153 -0
- package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +97 -0
- package/templates/starter/src/app/starter-acceptance.persistence-coverage.test.ts +134 -0
- package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +202 -0
- package/templates/starter/src/app/starter-acceptance.product-readiness-rules.test.ts +14 -0
- package/templates/starter/src/app/starter-acceptance.product-readiness-test-utils.ts +25 -0
- package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +50 -0
- package/templates/starter/src/app/starter-acceptance.product-worklog.test.ts +27 -0
- package/templates/starter/src/app/starter-acceptance.range-slider-rules.test.ts +147 -0
- package/templates/starter/src/app/starter-acceptance.reference-custom-timeline.test.ts +197 -0
- package/templates/starter/src/app/starter-acceptance.reference-foundation.test.ts +304 -0
- package/templates/starter/src/app/starter-acceptance.reference-test-utils.ts +102 -0
- package/templates/starter/src/app/starter-acceptance.reference-timeline.test.ts +267 -0
- package/templates/starter/src/app/starter-acceptance.schema-test-utils.ts +116 -0
- package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +373 -0
- package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +260 -0
- package/templates/starter/src/app/starter-acceptance.section-titles.test.ts +180 -0
- package/templates/starter/src/app/starter-acceptance.setup-readiness.test.ts +205 -0
- package/templates/starter/src/app/starter-acceptance.slider-rules.test.ts +470 -0
- package/templates/starter/src/app/starter-acceptance.slider-unit-rules.test.ts +61 -0
- package/templates/starter/src/app/starter-acceptance.source-test-utils.ts +43 -0
- package/templates/starter/src/app/starter-acceptance.test-utils.ts +21 -0
- package/templates/starter/src/app/starter-acceptance.text-control-kind.test.ts +89 -0
- package/templates/starter/src/app/starter-acceptance.timeline-playback.test.ts +264 -0
- package/templates/starter/src/app/starter-acceptance.timeline-test-utils.ts +56 -0
- package/templates/starter/src/app/starter-acceptance.toggle-pair-layout.test.ts +200 -0
- package/templates/starter/src/app/starter-acceptance.toggle-parameter-layout.test.ts +277 -0
- package/templates/starter/src/app/starter-acceptance.ts +151 -4576
- package/templates/starter/src/app/starter-acceptance.video-export-test-utils.ts +37 -0
- package/templates/starter/src/app/starter-acceptance.video-reference-study.test.ts +262 -0
- package/templates/starter/src/app/starter-acceptance.worklog-test-utils.ts +428 -0
- package/templates/starter/src/app/starter-acceptance.worklog.test.ts +283 -0
- package/templates/starter/src/app/starter-automated-runtime-evidence.test.ts +34 -0
- package/templates/starter/src/app/starter-composition.tsx +7 -0
- package/templates/starter/src/app/starter-performance-test-utils.ts +275 -0
- package/templates/starter/src/app/starter-performance.budgets.test.ts +374 -0
- package/templates/starter/src/app/starter-performance.gates.test.ts +128 -0
- package/templates/starter/src/app/starter-performance.renderer-source.test.ts +136 -0
- package/templates/starter/src/app/starter-performance.renderer-technique.test.ts +291 -0
- package/templates/starter/src/app/starter-performance.scenarios.test.ts +355 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.test.ts +253 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +243 -0
- package/templates/starter/src/routes/index.tsx +11 -2
- package/templates/starter/vite.config.ts +8 -0
- package/templates/ui/components/controls/color/color-control-types.ts +38 -0
- package/templates/ui/components/controls/color/color-control.tsx +19 -437
- package/templates/ui/components/controls/color/color-footer.tsx +272 -0
- package/templates/ui/components/controls/color/color-model-slider.tsx +271 -0
- package/templates/ui/components/controls/color/color-opacity-input.tsx +94 -0
- package/templates/ui/components/controls/color/color-surface.tsx +194 -0
- package/templates/ui/components/controls/color/color-value-control.tsx +159 -0
- package/templates/ui/components/controls/color/color-value-utils.ts +170 -0
- package/templates/ui/components/controls/color/index.ts +10 -3
- package/templates/ui/components/controls/color/palette-control-controller.ts +407 -0
- package/templates/ui/components/controls/color/palette-control-layout.ts +14 -0
- package/templates/ui/components/controls/color/palette-control-types.ts +50 -0
- package/templates/ui/components/controls/color/palette-control-view.tsx +174 -0
- package/templates/ui/components/controls/color/palette-control.tsx +6 -544
- package/templates/ui/components/controls/color/style-guide-color-picker-color-utils.ts +39 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-controller.ts +370 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-hue-handlers.ts +66 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-interaction-state.ts +49 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-interactions.ts +2 -2
- package/templates/ui/components/controls/color/style-guide-color-picker-model.ts +125 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-parts.tsx +10 -707
- package/templates/ui/components/controls/color/style-guide-color-picker-surface-drag.ts +93 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-surface-geometry.ts +114 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-surface-preview.ts +45 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-types.ts +84 -0
- package/templates/ui/components/controls/color/style-guide-color-picker-view.tsx +69 -0
- package/templates/ui/components/controls/color/style-guide-color-picker.tsx +6 -495
- package/templates/ui/components/controls/curves/curves-control.tsx +4 -3
- package/templates/ui/components/controls/file-drop/file-drop-control.tsx +39 -515
- package/templates/ui/components/controls/file-drop/file-drop-empty-state.tsx +35 -0
- package/templates/ui/components/controls/file-drop/file-drop-file-list.tsx +160 -0
- package/templates/ui/components/controls/file-drop/file-drop-image-grid.tsx +175 -0
- package/templates/ui/components/controls/file-drop/file-drop-model.tsx +170 -0
- package/templates/ui/components/controls/file-drop/file-drop-single-preview.tsx +63 -0
- package/templates/ui/components/controls/file-drop/file-drop-types.ts +48 -0
- package/templates/ui/components/controls/file-drop/index.ts +2 -2
- package/templates/ui/components/controls/font-picker/font-picker-control.tsx +133 -906
- package/templates/ui/components/controls/font-picker/font-picker-footer.tsx +116 -0
- package/templates/ui/components/controls/font-picker/font-picker-list.tsx +194 -0
- package/templates/ui/components/controls/font-picker/font-picker-popover-content.tsx +191 -0
- package/templates/ui/components/controls/font-picker/font-picker-value.ts +222 -0
- package/templates/ui/components/controls/font-picker/index.ts +4 -1
- package/templates/ui/components/controls/font-picker/use-font-picker-preview-pipeline.ts +163 -0
- package/templates/ui/components/controls/font-picker/use-font-picker-virtual-list.ts +293 -0
- package/templates/ui/components/controls/gradient/gradient-control-utils.ts +2 -25
- package/templates/ui/components/controls/gradient/gradient-control.tsx +4 -464
- package/templates/ui/components/controls/gradient/gradient-stops-controller.ts +332 -0
- package/templates/ui/components/controls/gradient/gradient-stops-track.tsx +159 -0
- package/templates/ui/components/controls/vector/vector-control-types.ts +26 -0
- package/templates/ui/components/controls/vector/vector-control.tsx +10 -486
- package/templates/ui/components/controls/vector/vector-pad-field.tsx +211 -0
- package/templates/ui/components/controls/vector/vector-pad-geometry.ts +61 -0
- package/templates/ui/components/controls/vector/vector-pad-parts.tsx +72 -0
- package/templates/ui/components/controls/vector/vector-pad-variants.ts +20 -0
- package/templates/ui/components/controls/vector/vector-size-field.tsx +104 -0
- package/templates/ui/components/controls/vector/vector-value.ts +46 -0
- package/templates/ui/components/primitives/slider/slider-discrete-state.ts +181 -0
- package/templates/ui/components/primitives/slider/slider-marker-policy.ts +52 -0
- package/templates/ui/components/primitives/slider/slider-pointer-dragging.ts +87 -0
- package/templates/ui/components/primitives/slider/slider-runtime.ts +109 -0
- package/templates/ui/components/primitives/slider/slider-types.ts +21 -0
- package/templates/ui/components/primitives/slider/slider.tsx +2 -403
- package/templates/runtime/react/canvas-shell.test.tsx +0 -554
- package/templates/runtime/react/canvas-shell.tsx +0 -585
- package/templates/runtime/react/controls-panel.test.tsx +0 -5446
- package/templates/runtime/react/controls-panel.tsx +0 -3220
- package/templates/runtime/react/layers-panel.test.tsx +0 -487
- package/templates/runtime/react/layers-panel.tsx +0 -1348
- package/templates/runtime/react/timeline-panel.test.tsx +0 -751
- package/templates/runtime/react/timeline-panel.tsx +0 -3078
- package/templates/runtime/schema/define-toolcraft.test.ts +0 -1742
- package/templates/runtime/state/reducer.test.ts +0 -1703
- package/templates/runtime/testing/performance.test.ts +0 -3081
- package/templates/starter/e2e/app-browser-acceptance.spec.ts +0 -785
- package/templates/starter/src/app/starter-acceptance.test.ts +0 -10068
- package/templates/starter/src/app/starter-performance.test.ts +0 -1583
- package/templates/ui/components/controls/color/style-guide-color-picker-logic.ts +0 -490
- /package/templates/runtime/react/{storage-key-migration.ts → app-shell/storage-key-migration.ts} +0 -0
- /package/templates/runtime/react/{theme-runtime.tsx → app-shell/theme-runtime.tsx} +0 -0
- /package/templates/runtime/react/{curve-geometry.test.ts → controls-panel/__tests__/curve-geometry.test.ts} +0 -0
- /package/templates/runtime/react/{panel-host-config.ts → panel-host/panel-host-config.ts} +0 -0
- /package/templates/runtime/react/{panel-host-geometry.test.ts → panel-host/panel-host-geometry.test.ts} +0 -0
- /package/templates/runtime/react/{panel-host-geometry.ts → panel-host/panel-host-geometry.ts} +0 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { getToolcraftComponentContract } from "./component-contracts";
|
|
4
|
+
|
|
5
|
+
describe("Toolcraft template component contracts: choices and actions", () => {
|
|
6
|
+
it("documents select as the fallback for segmented controls that exceed compact limits", () => {
|
|
7
|
+
const segmented = getToolcraftComponentContract("segmented").decisionCatalog;
|
|
8
|
+
const select = getToolcraftComponentContract("select").decisionCatalog;
|
|
9
|
+
|
|
10
|
+
expect(segmented?.strictness).toBe("best-fit");
|
|
11
|
+
expect(segmented?.acceptableAlternatives?.join(" ")).toMatch(/Select/i);
|
|
12
|
+
expect(segmented?.layoutConstraints).toContain(
|
|
13
|
+
"Segmented controls are full-width controls and must not be placed in two-column inline or half-width layout groups.",
|
|
14
|
+
);
|
|
15
|
+
expect(getToolcraftComponentContract("segmented").aiUsageRules).toContain(
|
|
16
|
+
"Do not place Segmented beside Switch, Color, Select, or another control in an inline row; use Select when a finite choice must occupy a half-width column.",
|
|
17
|
+
);
|
|
18
|
+
expect(select?.useWhen.join(" ")).toMatch(/long labels|many options/i);
|
|
19
|
+
expect(select?.useWhen).toContain(
|
|
20
|
+
"Use Select when a dropdown choice is more readable than a row of segmented cells.",
|
|
21
|
+
);
|
|
22
|
+
expect(select?.layoutConstraints).toContain(
|
|
23
|
+
"Standalone Select controls render stacked full-width with the label above the dropdown; do not use the compact side-label row with label left and dropdown right.",
|
|
24
|
+
);
|
|
25
|
+
expect(select?.layoutConstraints).toContain(
|
|
26
|
+
"Prefer compact two-column inline layout only for related short Select pairs that tune one workflow or entity.",
|
|
27
|
+
);
|
|
28
|
+
expect(select?.layoutConstraints).toContain(
|
|
29
|
+
"Use vertical one-select-per-row layout for single Select controls and as the fallback when a Select pair label, selected value, or option text would clip, truncate, or lose internal padding in the compact row.",
|
|
30
|
+
);
|
|
31
|
+
expect(select?.layoutConstraints).toContain(
|
|
32
|
+
"If a compact Select pair falls back to vertical layout, record the fit reason in the spec or worklog.",
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("documents context-only labels for binary controls", () => {
|
|
37
|
+
const switchContract = getToolcraftComponentContract("switch");
|
|
38
|
+
const checkboxContract = getToolcraftComponentContract("checkbox");
|
|
39
|
+
|
|
40
|
+
expect(switchContract.aiUsageRules).toContain(
|
|
41
|
+
'Switch labels name the setting context only; do not prefix labels with "Enable" or "Disable" because the switch already communicates on/off behavior.',
|
|
42
|
+
);
|
|
43
|
+
expect(switchContract.aiUsageRules).toContain(
|
|
44
|
+
'Use labels such as "CRT", "Background", "Glow", or "Loop" instead of "Enable CRT" or "Disable background".',
|
|
45
|
+
);
|
|
46
|
+
expect(switchContract.aiUsageRules).toContain(
|
|
47
|
+
"Two adjacent Switch controls for the same product entity must share one inline row when every visible label fits without truncation. Keep paired labels to short one- or two-word names; the runtime auto-pairs safe adjacent switches by target entity, and generated schemas should stack switches only when any label would truncate.",
|
|
48
|
+
);
|
|
49
|
+
expect(switchContract.aiUsageRules).toContain(
|
|
50
|
+
"When the nearest section title already names the switch context, do not duplicate that title as the visible switch label. Use label false for a visual-only toggle and keep the meaning in target/description.",
|
|
51
|
+
);
|
|
52
|
+
expect(switchContract.aiUsageRules).toContain(
|
|
53
|
+
'A Switch may share an inline row with one related parameter control when the visible switch label is short enough to fit. That row uses equal-width columns and the same horizontal column gap as paired Select controls; never shrink the switch column to intrinsic width. The non-switch parameter uses label false in that row; if its label is needed, stack the controls instead. In section-owned rows, use a short visible switch label such as "Include" instead of repeating the section title, such as "Include background" inside Background.',
|
|
54
|
+
);
|
|
55
|
+
expect(checkboxContract.aiUsageRules).toContain(
|
|
56
|
+
'Checkbox labels name the setting context only; do not prefix labels with "Enable" or "Disable" because the checkbox already communicates enabled/selected state.',
|
|
57
|
+
);
|
|
58
|
+
expect(checkboxContract.aiUsageRules).toContain(
|
|
59
|
+
'Use labels such as "Transparent background", "Guides", or "Loop" instead of "Enable transparent background".',
|
|
60
|
+
);
|
|
61
|
+
expect(checkboxContract.aiUsageRules).toContain(
|
|
62
|
+
"When the nearest section title already names the checkbox context, do not duplicate that title as the visible checkbox label. Use label false for a visual-only checkbox and keep the meaning in target/description.",
|
|
63
|
+
);
|
|
64
|
+
expect(checkboxContract.aiUsageRules).toContain(
|
|
65
|
+
"Two adjacent Checkbox controls for the same product entity must share one inline row when every visible label fits without truncation. Keep paired labels to short one- or two-word names; the runtime auto-pairs safe adjacent checkboxes by target entity, and generated schemas should stack checkboxes only when any label would truncate.",
|
|
66
|
+
);
|
|
67
|
+
expect(checkboxContract.aiUsageRules).toContain(
|
|
68
|
+
"A Checkbox may share an inline row with one related parameter control when the visible checkbox label is short enough to fit. That row uses equal-width columns and the same horizontal column gap as paired Select controls; never shrink the checkbox column to intrinsic width. The non-checkbox parameter uses label false in that row; if its label is needed, stack the controls instead. Hide the checkbox label when the section title provides the visible context.",
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("documents Actions as local section command groups", () => {
|
|
73
|
+
const contract = getToolcraftComponentContract("actions");
|
|
74
|
+
|
|
75
|
+
expect(contract.stateMode).toBe("command-only");
|
|
76
|
+
expect(contract.decisionCatalog?.ownsValueModel).toContain(
|
|
77
|
+
"entity-scoped command group",
|
|
78
|
+
);
|
|
79
|
+
expect(contract.decisionCatalog?.useWhen).toContain(
|
|
80
|
+
"Use Actions for section-scoped commands such as Randomize palette, Normalize weights, Sort glyphs, Clear selection, Duplicate item, or Reset current entity.",
|
|
81
|
+
);
|
|
82
|
+
expect(contract.aiUsageRules).toContain(
|
|
83
|
+
"Use Actions for local commands inside the current section when the command affects only the nearby entity or workflow step.",
|
|
84
|
+
);
|
|
85
|
+
expect(contract.aiUsageRules).toContain(
|
|
86
|
+
"Good Actions examples: Randomize palette, Normalize weights, Sort glyphs, Clear selection, Duplicate item, Reset current layer, Reset current stop, or Shuffle shades.",
|
|
87
|
+
);
|
|
88
|
+
expect(contract.aiUsageRules).toContain(
|
|
89
|
+
"Do not use Actions for final product delivery actions; use sticky panelActions for Export, Copy, Download, Generate, or Apply.",
|
|
90
|
+
);
|
|
91
|
+
expect(contract.aiUsageRules).toContain(
|
|
92
|
+
"Do not use Actions for animation transport; Play, Pause, Resume, Restart, and Scrub belong to the top timeline when timeline behavior exists.",
|
|
93
|
+
);
|
|
94
|
+
expect(contract.decisionCatalog?.layoutConstraints).toContain(
|
|
95
|
+
"Do not set an Actions control label to the exact same visible text as its only button; use a short one- or two-word context label such as Ink wash, Palette action, or Current layer while the button keeps the command verb.",
|
|
96
|
+
);
|
|
97
|
+
expect(contract.decisionCatalog?.layoutConstraints).toContain(
|
|
98
|
+
"Actions never use a side-label layout. If a visible label exists, it sits above the buttons.",
|
|
99
|
+
);
|
|
100
|
+
expect(contract.decisionCatalog?.layoutConstraints).toContain(
|
|
101
|
+
"Actions buttons render as a two-column grid. One visible button occupies the left half of the section; two buttons occupy one half each; more than two buttons wrap into additional 50% cells.",
|
|
102
|
+
);
|
|
103
|
+
expect(contract.decisionCatalog?.layoutConstraints).toContain(
|
|
104
|
+
"Do not center or right-align a partial final Actions row; an odd trailing button stays in the left 50% cell.",
|
|
105
|
+
);
|
|
106
|
+
expect(contract.aiUsageRules).toContain(
|
|
107
|
+
"For a single visible Actions button, the control label and button label must not be identical; make the control label a concise context and the button label the command.",
|
|
108
|
+
);
|
|
109
|
+
expect(contract.aiUsageRules).toContain(
|
|
110
|
+
"Render the Actions label above the buttons; do not put the label on the left with buttons on the right.",
|
|
111
|
+
);
|
|
112
|
+
expect(contract.aiUsageRules).toContain(
|
|
113
|
+
"Render Actions buttons in 50% cells: one button uses the left half, two buttons fill one row, and larger groups continue in two columns.",
|
|
114
|
+
);
|
|
115
|
+
expect(contract.aiUsageRules).toContain(
|
|
116
|
+
"Do not stretch an odd trailing Actions button full-width.",
|
|
117
|
+
);
|
|
118
|
+
expect(contract.aiUsageRules).toContain(
|
|
119
|
+
'For local reset-like actions, use product-specific values such as "reset-current-layer" or "reset-palette" and handle them through ToolcraftApp onPanelAction; do not use a bare "reset" value unless the action intentionally runs controls.reset.',
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("documents CollectionActions as canvas-backed add/remove controls", () => {
|
|
124
|
+
const contract = getToolcraftComponentContract("collectionActions");
|
|
125
|
+
|
|
126
|
+
expect(contract.stateMode).toBe("controlled");
|
|
127
|
+
expect(contract.decisionCatalog?.strictness).toBe("exact-owner");
|
|
128
|
+
expect(contract.decisionCatalog?.ownsValueModel).toContain(
|
|
129
|
+
"repeatable product entity collection",
|
|
130
|
+
);
|
|
131
|
+
expect(contract.decisionCatalog?.useWhen).toContain(
|
|
132
|
+
"Use CollectionActions instead of a count Slider when the user edits the actual set of items rather than only a numeric amount.",
|
|
133
|
+
);
|
|
134
|
+
expect(contract.decisionCatalog?.doNotReplaceWith).toContain(
|
|
135
|
+
"Do not use Slider to add or remove real collection items.",
|
|
136
|
+
);
|
|
137
|
+
expect(contract.decisionCatalog?.layoutConstraints).toContain(
|
|
138
|
+
"recommendedMaxItems is an agent/layout/performance hint, not a hard add limit; hardMaxItems is allowed only for real algorithm, format, API, export, or proven performance limits.",
|
|
139
|
+
);
|
|
140
|
+
expect(contract.decisionCatalog?.requiredAcceptance.join(" ")).toMatch(
|
|
141
|
+
/canvas preview and export/i,
|
|
142
|
+
);
|
|
143
|
+
expect(contract.aiUsageRules).toContain(
|
|
144
|
+
"Adding or removing collection items must update the runtime target array consumed by the renderer and export; do not add panel-only items.",
|
|
145
|
+
);
|
|
146
|
+
expect(contract.aiUsageRules).toContain(
|
|
147
|
+
"recommendedMaxItems is advisory only and must not disable the plus button. Use hardMaxItems only when a real product, algorithm, API, export, or measured performance limit requires it.",
|
|
148
|
+
);
|
|
149
|
+
expect(contract.aiUsageRules.join(" ")).toMatch(/TextInput/);
|
|
150
|
+
expect(contract.aiUsageRules.join(" ")).toMatch(/FontPicker/);
|
|
151
|
+
expect(contract.aiUsageRules).toContain(
|
|
152
|
+
"Use FontPicker as the collection item control when each repeated item is a typography/text-style entity; do not split its font, color, opacity, size, case, letter-spacing, or line-height into sibling collection fields.",
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("documents segmented controls as compact selector-only choices", () => {
|
|
157
|
+
const segmented = getToolcraftComponentContract("segmented");
|
|
158
|
+
|
|
159
|
+
expect(segmented.aiUsageRules).toContain(
|
|
160
|
+
"Use Segmented only for compact mode choices where every cell keeps its internal padding.",
|
|
161
|
+
);
|
|
162
|
+
expect(segmented.aiUsageRules).toContain(
|
|
163
|
+
"If a segmented control is too wide, first shorten option labels; if the compact labels still exceed the width budget, use Select because it has the same selection mechanics without broken cells.",
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("keeps panel actions documented as sticky footer command controls", () => {
|
|
168
|
+
const contract = getToolcraftComponentContract("panelActions");
|
|
169
|
+
|
|
170
|
+
expect(contract.stateMode).toBe("command-only");
|
|
171
|
+
expect(contract.commands).toEqual(["controls.apply"]);
|
|
172
|
+
expect(contract.aiUsageRules).toContain(
|
|
173
|
+
"Do not use panelActions for resetting controls; the controls panel header owns Reset controls.",
|
|
174
|
+
);
|
|
175
|
+
expect(contract.aiUsageRules).toContain(
|
|
176
|
+
"Handle product-specific panelActions through ToolcraftApp onPanelAction.",
|
|
177
|
+
);
|
|
178
|
+
expect(contract.aiUsageRules).toContain(
|
|
179
|
+
"Async product actions such as Export, Download, Copy, Generate, or Apply must return the real Promise from onPanelAction and report progress through the onPanelAction reportProgress callback.",
|
|
180
|
+
);
|
|
181
|
+
expect(contract.aiUsageRules).toContain(
|
|
182
|
+
"The sticky footer top accent indicator is determinate when reportProgress receives 0..1 values and falls back to pending state only when progress is unavailable.",
|
|
183
|
+
);
|
|
184
|
+
expect(contract.aiUsageRules).toContain(
|
|
185
|
+
"defineToolcraft hoists panelActions into the controls panel sticky footer automatically.",
|
|
186
|
+
);
|
|
187
|
+
expect(contract.aiUsageRules).toContain(
|
|
188
|
+
"Product-output apps must always include export in panelActions.",
|
|
189
|
+
);
|
|
190
|
+
expect(contract.aiUsageRules).toContain(
|
|
191
|
+
'Export-labeled panelActions use icon "upload-simple", matching the Setup "Export Settings" action; do not use "download", "download-simple", or "export" icons for Export PNG or Export Video.',
|
|
192
|
+
);
|
|
193
|
+
expect(contract.aiUsageRules).toContain(
|
|
194
|
+
"Static or still-output apps include Export PNG as the primary footer action.",
|
|
195
|
+
);
|
|
196
|
+
expect(contract.aiUsageRules).toContain(
|
|
197
|
+
'Every app with Export PNG must expose a separate "Image Export" controls section.',
|
|
198
|
+
);
|
|
199
|
+
expect(contract.aiUsageRules).toContain(
|
|
200
|
+
'The Image Export section must include "export.image.format" as a Select control with PNG and JPG choices, defaulting to "png".',
|
|
201
|
+
);
|
|
202
|
+
expect(contract.aiUsageRules).toContain(
|
|
203
|
+
'The Image Export section must include "export.image.resolution" as a Select control with 2K, 4K, and 8K choices, defaulting to "4k".',
|
|
204
|
+
);
|
|
205
|
+
expect(contract.aiUsageRules).toContain(
|
|
206
|
+
"Image Export format and resolution render as one compact two-column inline Select pair, matching the Video Export settings structure.",
|
|
207
|
+
);
|
|
208
|
+
expect(contract.aiUsageRules).toContain(
|
|
209
|
+
"Image Export resolution controls the actual exported image long edge: 2K = 2048px, 4K = 4096px, 8K = 8192px. Pass the selected runtime value to createToolcraftPngExportCanvas resolution and prove decoded image width/height in browser acceptance.",
|
|
210
|
+
);
|
|
211
|
+
expect(contract.aiUsageRules).toContain(
|
|
212
|
+
"Animated apps include Export Video as the primary footer action and Export PNG as a secondary footer action.",
|
|
213
|
+
);
|
|
214
|
+
expect(contract.aiUsageRules).toContain(
|
|
215
|
+
"Any app with Export Video must enable the top Toolcraft timeline; video duration, loop, and rendered timestamps come from runtime timeline state.",
|
|
216
|
+
);
|
|
217
|
+
expect(contract.aiUsageRules).toContain(
|
|
218
|
+
'Animated apps with Export Video must expose a separate "Video Export" controls section.',
|
|
219
|
+
);
|
|
220
|
+
expect(contract.aiUsageRules).toContain(
|
|
221
|
+
'Animated apps with both Export PNG and Export Video must expose both "Image Export" and "Video Export"; Image Export sits immediately before Video Export.',
|
|
222
|
+
);
|
|
223
|
+
expect(contract.aiUsageRules).toContain(
|
|
224
|
+
'The Video Export section must include format and resolution controls such as targets "export.video.format" and "export.video.resolution".',
|
|
225
|
+
);
|
|
226
|
+
expect(contract.aiUsageRules).toContain(
|
|
227
|
+
"Use Select controls for Video Export format and resolution; do not use Segmented unless the product has a deliberately tiny fixed output menu and browser tests prove every cell keeps padding.",
|
|
228
|
+
);
|
|
229
|
+
expect(contract.aiUsageRules).toContain(
|
|
230
|
+
"Place the Video Export section as the final controls section directly above sticky footer panelActions.",
|
|
231
|
+
);
|
|
232
|
+
expect(contract.aiUsageRules).toContain(
|
|
233
|
+
'Video Export format defaults to "mp4"; keep "webm" available as the baseline alternate unless the prompt/reference requires another default.',
|
|
234
|
+
);
|
|
235
|
+
expect(contract.aiUsageRules).toContain(
|
|
236
|
+
'Video Export resolution defaults to "current"; keep "4k" available as the high-resolution alternate.',
|
|
237
|
+
);
|
|
238
|
+
expect(contract.aiUsageRules).toContain(
|
|
239
|
+
"Video Export format and resolution are a compact semantic pair and should use a two-column inline layout by default; use stacked rows only when labels or selected values do not fit without clipping.",
|
|
240
|
+
);
|
|
241
|
+
expect(contract.aiUsageRules).toContain(
|
|
242
|
+
'Baseline browser video formats are "mp4" and "webm"; MOV or ProRes require an explicit custom encoder/transcoder and dedicated acceptance plus performance coverage.',
|
|
243
|
+
);
|
|
244
|
+
expect(contract.aiUsageRules).toContain(
|
|
245
|
+
"Video export code must choose the actual MIME/container through MediaRecorder.isTypeSupported or an equivalent encoder capability check, then fall back safely.",
|
|
246
|
+
);
|
|
247
|
+
expect(contract.aiUsageRules).toContain(
|
|
248
|
+
"Video export must use getToolcraftVideoExportSize for current and 4K dimensions. Current video export uses the current canvas/output size with even encoder-safe rounding; 4K video fits inside an encoder-safe 3840x2160 box, preserves canvas aspect ratio, and uses even pixel dimensions. Do not hand-roll 4096px long-edge video sizing.",
|
|
249
|
+
);
|
|
250
|
+
expect(contract.aiUsageRules).toContain(
|
|
251
|
+
"Video export must set recording canvas dimensions before captureStream, MediaRecorder, VideoEncoder, or equivalent encoder setup, and must reject recorder/encoder errors instead of returning corrupt blobs.",
|
|
252
|
+
);
|
|
253
|
+
expect(contract.aiUsageRules).toContain(
|
|
254
|
+
"Offline video export duration must be encoded from runtime timeline timestamps. Do not rely on canvas.captureStream plus MediaRecorder wall-clock recording time as the only duration mechanism for rendered-frame export.",
|
|
255
|
+
);
|
|
256
|
+
expect(contract.aiUsageRules).toContain(
|
|
257
|
+
'Video resolution must control exported dimensions. Use "current" output size by default; "4K" is an export resolution target, not a hardcoded 3840x2160 canvas lock.',
|
|
258
|
+
);
|
|
259
|
+
expect(contract.aiUsageRules).toContain(
|
|
260
|
+
"Video export browser coverage must load the exported blob metadata and prove video.duration matches the edited runtime timeline duration; blobSize/blobType checks alone are not enough.",
|
|
261
|
+
);
|
|
262
|
+
expect(contract.aiUsageRules).toContain(
|
|
263
|
+
"Video export must report frame-based progress through reportProgress during render/encode steps. PNG export should report phase progress for render, blob, and handoff when those phases are asynchronous.",
|
|
264
|
+
);
|
|
265
|
+
expect(contract.aiUsageRules).toContain(
|
|
266
|
+
'Product-output apps must expose a dedicated "Background" section directly before the first export settings section. With PNG export that first section is Image Export; with video-only export it is Video Export.',
|
|
267
|
+
);
|
|
268
|
+
expect(contract.aiUsageRules).toContain(
|
|
269
|
+
"Product-output apps must pass the includeBackground runtime value to createToolcraftPngExportCanvas for PNG alpha and call shouldIncludeToolcraftPreviewBackground(state) for live preview product background.",
|
|
270
|
+
);
|
|
271
|
+
expect(contract.aiUsageRules).toContain(
|
|
272
|
+
"PNG export must use createToolcraftPngExportCanvas so background transparency and selected image dimensions or retina fallback are applied consistently; turning Include off makes preview product background and PNG alpha transparent without hiding the Toolcraft canvas backing or video background.",
|
|
273
|
+
);
|
|
274
|
+
expect(contract.aiUsageRules).toContain(
|
|
275
|
+
"Video export must keep product background and use getToolcraftVideoExportSize for current/4K output dimensions.",
|
|
276
|
+
);
|
|
277
|
+
expect(contract.aiUsageRules).toContain(
|
|
278
|
+
"Copy PNG can be a secondary action when clipboard output is useful, but copy does not replace export.",
|
|
279
|
+
);
|
|
280
|
+
expect(contract.aiUsageRules).toContain(
|
|
281
|
+
"Add Copy PNG as a secondary action only when the prompt/reference includes clipboard output or the product clearly benefits from paste/share workflows.",
|
|
282
|
+
);
|
|
283
|
+
expect(contract.aiUsageRules).toContain(
|
|
284
|
+
"Footer actions must be one compact horizontal group; do not split them into stacked full-width sections.",
|
|
285
|
+
);
|
|
286
|
+
expect(contract.aiUsageRules).toContain(
|
|
287
|
+
"If two footer actions are needed, render secondary/outline on the left and primary on the right.",
|
|
288
|
+
);
|
|
289
|
+
expect(contract.aiUsageRules).toContain(
|
|
290
|
+
"When an odd number of footer actions renders in two columns, the final unpaired action spans the full row width.",
|
|
291
|
+
);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { control, decisionCatalog } from "./component-contract-builders";
|
|
2
|
+
import type { ToolcraftComponentContract } from "./types";
|
|
3
|
+
export const TOOLCRAFT_CHOICE_COMPONENT_CONTRACTS = {
|
|
4
|
+
select: {
|
|
5
|
+
...control("select", "Select", "grouped", "required"),
|
|
6
|
+
decisionCatalog: decisionCatalog({
|
|
7
|
+
strictness: "best-fit",
|
|
8
|
+
ownsValueModel: [
|
|
9
|
+
"finite single selection",
|
|
10
|
+
"long option labels",
|
|
11
|
+
"many options",
|
|
12
|
+
"segmented fallback",
|
|
13
|
+
],
|
|
14
|
+
useWhen: [
|
|
15
|
+
"Use Select for finite choices with long labels, many options, or values that would not fit in Segmented.",
|
|
16
|
+
"Use Select when a dropdown choice is more readable than a row of segmented cells.",
|
|
17
|
+
],
|
|
18
|
+
doNotReplaceWith: [
|
|
19
|
+
"Do not use Select to recreate FontPicker, Gradient, ImagePicker, FileDrop, Curves, Vector, or Palette value models.",
|
|
20
|
+
],
|
|
21
|
+
acceptableAlternatives: [
|
|
22
|
+
"Use Segmented for two to four short closely related options that fit without clipping.",
|
|
23
|
+
],
|
|
24
|
+
layoutConstraints: [
|
|
25
|
+
"Standalone Select controls render stacked full-width with the label above the dropdown; do not use the compact side-label row with label left and dropdown right.",
|
|
26
|
+
"Prefer compact two-column inline layout only for related short Select pairs that tune one workflow or entity.",
|
|
27
|
+
"Use vertical one-select-per-row layout for single Select controls and as the fallback when a Select pair label, selected value, or option text would clip, truncate, or lose internal padding in the compact row.",
|
|
28
|
+
"If a compact Select pair falls back to vertical layout, record the fit reason in the spec or worklog.",
|
|
29
|
+
],
|
|
30
|
+
requiredAcceptance: [
|
|
31
|
+
"Prove every visible option or representative option set changes product output or interpreted product state.",
|
|
32
|
+
],
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
segmented: {
|
|
36
|
+
...control("segmented", "Segmented", "grouped", "required"),
|
|
37
|
+
decisionCatalog: decisionCatalog({
|
|
38
|
+
strictness: "best-fit",
|
|
39
|
+
ownsValueModel: [
|
|
40
|
+
"compact finite mode choice",
|
|
41
|
+
"two to four short related options",
|
|
42
|
+
"single-row mode toggle",
|
|
43
|
+
],
|
|
44
|
+
useWhen: [
|
|
45
|
+
"Use Segmented for compact mode choices where every cell keeps internal padding.",
|
|
46
|
+
"Use Segmented when the options are short, closely related, and easier to compare side by side.",
|
|
47
|
+
],
|
|
48
|
+
doNotReplaceWith: [
|
|
49
|
+
"Do not use Segmented for long labels, many options, or values that clip.",
|
|
50
|
+
"Do not use Segmented for actions; use buttons or panelActions.",
|
|
51
|
+
],
|
|
52
|
+
acceptableAlternatives: [
|
|
53
|
+
"Use Select when options are long, numerous, or break segmented cell padding.",
|
|
54
|
+
],
|
|
55
|
+
layoutConstraints: [
|
|
56
|
+
"Keep text segmented controls to at most four options and compact labels.",
|
|
57
|
+
"Segmented controls are full-width controls and must not be placed in two-column inline or half-width layout groups.",
|
|
58
|
+
"Fallback to Select when cells collide, clip, or lose padding.",
|
|
59
|
+
],
|
|
60
|
+
requiredAcceptance: [
|
|
61
|
+
"Prove every visible segment changes the relevant product mode or output.",
|
|
62
|
+
"Browser verification must treat clipped or paddingless cells as broken.",
|
|
63
|
+
],
|
|
64
|
+
}),
|
|
65
|
+
aiUsageRules: [
|
|
66
|
+
"Use Segmented only for compact mode choices where every cell keeps its internal padding.",
|
|
67
|
+
"Do not place Segmented beside Switch, Color, Select, or another control in an inline row; use Select when a finite choice must occupy a half-width column.",
|
|
68
|
+
"If a segmented control is too wide, first shorten option labels; if the compact labels still exceed the width budget, use Select because it has the same selection mechanics without broken cells.",
|
|
69
|
+
"Generated schemas should keep text segmented controls to at most four options, no option label longer than nine characters, and no more than twenty-four total option-label characters.",
|
|
70
|
+
"Browser verification must treat collided, clipped, or paddingless segmented cells as a broken component and switch to shorter labels or Select.",
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
switch: {
|
|
74
|
+
...control("switch", "Switch", "grouped", "required"),
|
|
75
|
+
decisionCatalog: decisionCatalog({
|
|
76
|
+
strictness: "best-fit",
|
|
77
|
+
ownsValueModel: [
|
|
78
|
+
"immediate binary setting",
|
|
79
|
+
"on/off product behavior",
|
|
80
|
+
"enabled/disabled runtime option",
|
|
81
|
+
],
|
|
82
|
+
useWhen: [
|
|
83
|
+
"Use Switch for a binary setting that applies immediately.",
|
|
84
|
+
"Use Switch for options such as Glow, Loop, CRT, Background, or Guides.",
|
|
85
|
+
],
|
|
86
|
+
doNotReplaceWith: [
|
|
87
|
+
"Do not use Switch for more than two options.",
|
|
88
|
+
"Do not use Switch for destructive actions or commands that need confirmation.",
|
|
89
|
+
],
|
|
90
|
+
acceptableAlternatives: [
|
|
91
|
+
"Use Checkbox when the option is an explicit inclusion flag.",
|
|
92
|
+
"Use Select or Segmented for more than two options.",
|
|
93
|
+
],
|
|
94
|
+
layoutConstraints: [
|
|
95
|
+
"Two adjacent Switch controls for the same product entity must share one inline row when both labels fit; the runtime auto-pairs safe adjacent switches by target entity when no explicit layout group is needed.",
|
|
96
|
+
],
|
|
97
|
+
requiredAcceptance: [
|
|
98
|
+
"Prove toggling the switch changes the product output or runtime behavior.",
|
|
99
|
+
],
|
|
100
|
+
}),
|
|
101
|
+
aiUsageRules: [
|
|
102
|
+
'Switch labels name the setting context only; do not prefix labels with "Enable" or "Disable" because the switch already communicates on/off behavior.',
|
|
103
|
+
'Use labels such as "CRT", "Background", "Glow", or "Loop" instead of "Enable CRT" or "Disable background".',
|
|
104
|
+
"Two adjacent Switch controls for the same product entity must share one inline row when every visible label fits without truncation. Keep paired labels to short one- or two-word names; the runtime auto-pairs safe adjacent switches by target entity, and generated schemas should stack switches only when any label would truncate.",
|
|
105
|
+
"When the nearest section title already names the switch context, do not duplicate that title as the visible switch label. Use label false for a visual-only toggle and keep the meaning in target/description.",
|
|
106
|
+
'A Switch may share an inline row with one related parameter control when the visible switch label is short enough to fit. That row uses equal-width columns and the same horizontal column gap as paired Select controls; never shrink the switch column to intrinsic width. The non-switch parameter uses label false in that row; if its label is needed, stack the controls instead. In section-owned rows, use a short visible switch label such as "Include" instead of repeating the section title, such as "Include background" inside Background.',
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
checkbox: {
|
|
110
|
+
...control("checkbox", "Checkbox", "grouped", "required"),
|
|
111
|
+
decisionCatalog: decisionCatalog({
|
|
112
|
+
strictness: "best-fit",
|
|
113
|
+
ownsValueModel: [
|
|
114
|
+
"explicit optional flag",
|
|
115
|
+
"included/excluded choice",
|
|
116
|
+
"binary checklist state",
|
|
117
|
+
],
|
|
118
|
+
useWhen: [
|
|
119
|
+
"Use Checkbox when the product meaning is an explicit optional flag or inclusion choice.",
|
|
120
|
+
],
|
|
121
|
+
doNotReplaceWith: [
|
|
122
|
+
"Do not use Checkbox for immediate setting toggles that read more naturally as Switch.",
|
|
123
|
+
"Do not use Checkbox for commands.",
|
|
124
|
+
],
|
|
125
|
+
acceptableAlternatives: [
|
|
126
|
+
"Use Switch for immediate on/off settings.",
|
|
127
|
+
"Use Select or Segmented for more than two options.",
|
|
128
|
+
],
|
|
129
|
+
layoutConstraints: [
|
|
130
|
+
"Two adjacent Checkbox controls for the same product entity must share one inline row when both labels fit; the runtime auto-pairs safe adjacent checkboxes by target entity when no explicit layout group is needed.",
|
|
131
|
+
],
|
|
132
|
+
requiredAcceptance: [
|
|
133
|
+
"Prove checking and unchecking changes product output or runtime behavior.",
|
|
134
|
+
],
|
|
135
|
+
}),
|
|
136
|
+
aiUsageRules: [
|
|
137
|
+
'Checkbox labels name the setting context only; do not prefix labels with "Enable" or "Disable" because the checkbox already communicates enabled/selected state.',
|
|
138
|
+
'Use labels such as "Transparent background", "Guides", or "Loop" instead of "Enable transparent background".',
|
|
139
|
+
"When the nearest section title already names the checkbox context, do not duplicate that title as the visible checkbox label. Use label false for a visual-only checkbox and keep the meaning in target/description.",
|
|
140
|
+
"Two adjacent Checkbox controls for the same product entity must share one inline row when every visible label fits without truncation. Keep paired labels to short one- or two-word names; the runtime auto-pairs safe adjacent checkboxes by target entity, and generated schemas should stack checkboxes only when any label would truncate.",
|
|
141
|
+
"A Checkbox may share an inline row with one related parameter control when the visible checkbox label is short enough to fit. That row uses equal-width columns and the same horizontal column gap as paired Select controls; never shrink the checkbox column to intrinsic width. The non-checkbox parameter uses label false in that row; if its label is needed, stack the controls instead. Hide the checkbox label when the section title provides the visible context.",
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
actions: {
|
|
145
|
+
...control("actions", "Actions", "grouped", "required"),
|
|
146
|
+
decisionCatalog: decisionCatalog({
|
|
147
|
+
strictness: "best-fit",
|
|
148
|
+
ownsValueModel: [
|
|
149
|
+
"local section action",
|
|
150
|
+
"small contextual command",
|
|
151
|
+
"non-sticky workflow command",
|
|
152
|
+
"entity-scoped command group",
|
|
153
|
+
],
|
|
154
|
+
useWhen: [
|
|
155
|
+
"Use Actions for local commands inside a control section that affect the nearby entity.",
|
|
156
|
+
"Use Actions for section-scoped commands such as Randomize palette, Normalize weights, Sort glyphs, Clear selection, Duplicate item, or Reset current entity.",
|
|
157
|
+
],
|
|
158
|
+
doNotReplaceWith: [
|
|
159
|
+
"Do not use Actions for final product export, copy, generate, apply, or download actions.",
|
|
160
|
+
"Do not use Actions for global reset; the panel header owns reset.",
|
|
161
|
+
"Do not use Actions for timeline transport such as Play, Pause, Resume, Restart, or Scrub.",
|
|
162
|
+
],
|
|
163
|
+
acceptableAlternatives: [
|
|
164
|
+
"Use panelActions for sticky product delivery actions.",
|
|
165
|
+
"Use item-level icon buttons inside custom controls for local item remove/reorder commands.",
|
|
166
|
+
"Use the top TimelinePanel for animation transport commands.",
|
|
167
|
+
],
|
|
168
|
+
layoutConstraints: [
|
|
169
|
+
"Keep local actions close to the entity they affect.",
|
|
170
|
+
"Keep action labels short and scoped by the section title; prefer Randomize, Clear, Sort, Normalize, Duplicate, or Reset when the section already names the target.",
|
|
171
|
+
"Do not set an Actions control label to the exact same visible text as its only button; use a short one- or two-word context label such as Ink wash, Palette action, or Current layer while the button keeps the command verb.",
|
|
172
|
+
"Actions never use a side-label layout. If a visible label exists, it sits above the buttons.",
|
|
173
|
+
"Actions buttons render as a two-column grid. One visible button occupies the left half of the section; two buttons occupy one half each; more than two buttons wrap into additional 50% cells.",
|
|
174
|
+
"Do not center or right-align a partial final Actions row; an odd trailing button stays in the left 50% cell.",
|
|
175
|
+
],
|
|
176
|
+
requiredAcceptance: [
|
|
177
|
+
"Prove each action dispatches the intended command or product side effect for the nearby entity only.",
|
|
178
|
+
],
|
|
179
|
+
}),
|
|
180
|
+
commands: ["controls.reset", "controls.apply"],
|
|
181
|
+
stateMode: "command-only",
|
|
182
|
+
aiUsageRules: [
|
|
183
|
+
"Use Actions for local commands inside the current section when the command affects only the nearby entity or workflow step.",
|
|
184
|
+
"Good Actions examples: Randomize palette, Normalize weights, Sort glyphs, Clear selection, Duplicate item, Reset current layer, Reset current stop, or Shuffle shades.",
|
|
185
|
+
"Do not use Actions for final product delivery actions; use sticky panelActions for Export, Copy, Download, Generate, or Apply.",
|
|
186
|
+
"Do not use Actions for global reset; the controls panel header owns global reset.",
|
|
187
|
+
"Do not use Actions for animation transport; Play, Pause, Resume, Restart, and Scrub belong to the top timeline when timeline behavior exists.",
|
|
188
|
+
"For a single visible Actions button, the control label and button label must not be identical; make the control label a concise context and the button label the command.",
|
|
189
|
+
"Render the Actions label above the buttons; do not put the label on the left with buttons on the right.",
|
|
190
|
+
"Render Actions buttons in 50% cells: one button uses the left half, two buttons fill one row, and larger groups continue in two columns.",
|
|
191
|
+
"Do not stretch an odd trailing Actions button full-width.",
|
|
192
|
+
'For local reset-like actions, use product-specific values such as "reset-current-layer" or "reset-palette" and handle them through ToolcraftApp onPanelAction; do not use a bare "reset" value unless the action intentionally runs controls.reset.',
|
|
193
|
+
"Acceptance and browser tests must click each Actions button and prove the product output or runtime state for the nearby entity changed.",
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
collectionActions: {
|
|
197
|
+
...control("collectionActions", "CollectionActions", "standalone", "component-owned"),
|
|
198
|
+
decisionCatalog: decisionCatalog({
|
|
199
|
+
strictness: "exact-owner",
|
|
200
|
+
ownsValueModel: [
|
|
201
|
+
"repeatable product entity collection",
|
|
202
|
+
"add/remove product items",
|
|
203
|
+
"dynamic list of visible controls",
|
|
204
|
+
"canvas-backed collection size",
|
|
205
|
+
],
|
|
206
|
+
useWhen: [
|
|
207
|
+
"Use CollectionActions when users can add or remove repeated product entities such as colors, glyphs, symbols, points, rules, variants, or object entries.",
|
|
208
|
+
"Use CollectionActions instead of a count Slider when the user edits the actual set of items rather than only a numeric amount.",
|
|
209
|
+
],
|
|
210
|
+
doNotReplaceWith: [
|
|
211
|
+
"Do not use Slider to add or remove real collection items.",
|
|
212
|
+
"Do not use plain Actions for add/remove collection ownership; Actions are local commands, not collection state owners.",
|
|
213
|
+
"Do not use CollectionActions for panel-only lists that do not affect canvas preview or export.",
|
|
214
|
+
],
|
|
215
|
+
acceptableAlternatives: [
|
|
216
|
+
"Use fileDrop multiple when the repeated entities are uploaded images.",
|
|
217
|
+
"Use Gradient when the repeated entities are gradient stops inside an adjustable gradient.",
|
|
218
|
+
"Use customControl only when the repeated entity needs interactions no built-in collection item control can express.",
|
|
219
|
+
],
|
|
220
|
+
layoutConstraints: [
|
|
221
|
+
"CollectionActions sits at the start of its section, renders the collection label on the left, and keeps remove/add icon buttons together on the right.",
|
|
222
|
+
"Homogeneous repeated item controls do not render visible per-item labels when the collection label already names the group.",
|
|
223
|
+
"Collection item controls follow normal density rules: plain color items use equal 50% columns when they fit, while color+opacity items stay stacked.",
|
|
224
|
+
"CollectionActions is a compound control and follows content-width compound divider rules when sharing a section with sibling controls.",
|
|
225
|
+
"recommendedMaxItems is an agent/layout/performance hint, not a hard add limit; hardMaxItems is allowed only for real algorithm, format, API, export, or proven performance limits.",
|
|
226
|
+
],
|
|
227
|
+
requiredAcceptance: [
|
|
228
|
+
"Prove plus adds a runtime item and that the new item appears in or affects canvas preview and export.",
|
|
229
|
+
"Prove minus removes a runtime item and that the removed item disappears from or stops affecting canvas preview and export.",
|
|
230
|
+
"Prove minItems prevents deleting below the minimum and recommendedMaxItems does not silently block adding more items.",
|
|
231
|
+
],
|
|
232
|
+
}),
|
|
233
|
+
stateMode: "controlled",
|
|
234
|
+
aiUsageRules: [
|
|
235
|
+
"Use CollectionActions for repeatable product entities whose actual item list can grow or shrink.",
|
|
236
|
+
"Adding or removing collection items must update the runtime target array consumed by the renderer and export; do not add panel-only items.",
|
|
237
|
+
"Do not model add/remove item behavior with a Slider count when users need to edit the actual items.",
|
|
238
|
+
"recommendedMaxItems is advisory only and must not disable the plus button. Use hardMaxItems only when a real product, algorithm, API, export, or measured performance limit requires it.",
|
|
239
|
+
"CollectionActions item controls use built-in controls whenever possible, such as Color, ColorOpacity, TextInput, Select, Segmented, Slider, Switch, Checkbox, RangeInput, or FontPicker.",
|
|
240
|
+
"Use FontPicker as the collection item control when each repeated item is a typography/text-style entity; do not split its font, color, opacity, size, case, letter-spacing, or line-height into sibling collection fields.",
|
|
241
|
+
"Do not add visible labels like Color 1, Color 2, Item 1, or Item 2 for homogeneous collection items when the collection label already explains the group.",
|
|
242
|
+
"Use compact half-width item layout whenever the child control is allowed to fit in a half row; color items without opacity are the default two-column case.",
|
|
243
|
+
"Acceptance must add and remove items through the browser UI and prove canvas/export output follows the changed collection.",
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
panelActions: {
|
|
247
|
+
...control("panelActions", "PanelActions", "standalone", "component-owned"),
|
|
248
|
+
decisionCatalog: decisionCatalog({
|
|
249
|
+
strictness: "exact-owner",
|
|
250
|
+
ownsValueModel: [
|
|
251
|
+
"sticky final product action",
|
|
252
|
+
"export action",
|
|
253
|
+
"copy action",
|
|
254
|
+
"generate action",
|
|
255
|
+
"apply action",
|
|
256
|
+
],
|
|
257
|
+
useWhen: [
|
|
258
|
+
"Use panelActions for final product actions such as Export, Copy, Generate, Apply, or Download.",
|
|
259
|
+
],
|
|
260
|
+
doNotReplaceWith: [
|
|
261
|
+
"Do not place final product action buttons on the canvas.",
|
|
262
|
+
"Do not use regular section Actions for final sticky export or generate actions.",
|
|
263
|
+
"Do not duplicate global Reset in panelActions.",
|
|
264
|
+
],
|
|
265
|
+
acceptableAlternatives: [
|
|
266
|
+
"Use Actions only for local section commands.",
|
|
267
|
+
],
|
|
268
|
+
layoutConstraints: [
|
|
269
|
+
"Footer actions are one compact sticky group with secondary on the left and primary on the right.",
|
|
270
|
+
],
|
|
271
|
+
requiredAcceptance: [
|
|
272
|
+
"Prove panel actions execute real product side effects such as exported bytes, clipboard payload, or generated output.",
|
|
273
|
+
"For async panelActions, prove the sticky footer top accent indicator is visible while the returned Promise is pending, advances when reportProgress is called, and hides after it settles.",
|
|
274
|
+
],
|
|
275
|
+
}),
|
|
276
|
+
aiUsageRules: [
|
|
277
|
+
"Use panelActions only for sticky footer product actions such as Generate, Export, Copy, or Download.",
|
|
278
|
+
"Do not use panelActions for resetting controls; the controls panel header owns Reset controls.",
|
|
279
|
+
"Handle product-specific panelActions through ToolcraftApp onPanelAction.",
|
|
280
|
+
"Async product actions such as Export, Download, Copy, Generate, or Apply must return the real Promise from onPanelAction and report progress through the onPanelAction reportProgress callback.",
|
|
281
|
+
"The sticky footer top accent indicator is determinate when reportProgress receives 0..1 values and falls back to pending state only when progress is unavailable.",
|
|
282
|
+
"defineToolcraft hoists panelActions into the controls panel sticky footer automatically.",
|
|
283
|
+
"Product-output apps must always include export in panelActions.",
|
|
284
|
+
'Export-labeled panelActions use icon "upload-simple", matching the Setup "Export Settings" action; do not use "download", "download-simple", or "export" icons for Export PNG or Export Video.',
|
|
285
|
+
"Static or still-output apps include Export PNG as the primary footer action.",
|
|
286
|
+
'Every app with Export PNG must expose a separate "Image Export" controls section.',
|
|
287
|
+
'The Image Export section must include "export.image.format" as a Select control with PNG and JPG choices, defaulting to "png".',
|
|
288
|
+
'The Image Export section must include "export.image.resolution" as a Select control with 2K, 4K, and 8K choices, defaulting to "4k".',
|
|
289
|
+
"Image Export format and resolution render as one compact two-column inline Select pair, matching the Video Export settings structure.",
|
|
290
|
+
"Image Export resolution controls the actual exported image long edge: 2K = 2048px, 4K = 4096px, 8K = 8192px. Pass the selected runtime value to createToolcraftPngExportCanvas resolution and prove decoded image width/height in browser acceptance.",
|
|
291
|
+
"Animated apps include Export Video as the primary footer action and Export PNG as a secondary footer action.",
|
|
292
|
+
"Any app with Export Video must enable the top Toolcraft timeline; video duration, loop, and rendered timestamps come from runtime timeline state.",
|
|
293
|
+
'Animated apps with Export Video must expose a separate "Video Export" controls section.',
|
|
294
|
+
'Animated apps with both Export PNG and Export Video must expose both "Image Export" and "Video Export"; Image Export sits immediately before Video Export.',
|
|
295
|
+
'The Video Export section must include format and resolution controls such as targets "export.video.format" and "export.video.resolution".',
|
|
296
|
+
"Use Select controls for Video Export format and resolution; do not use Segmented unless the product has a deliberately tiny fixed output menu and browser tests prove every cell keeps padding.",
|
|
297
|
+
'Place the Video Export section as the final controls section directly above sticky footer panelActions.',
|
|
298
|
+
'Video Export format defaults to "mp4"; keep "webm" available as the baseline alternate unless the prompt/reference requires another default.',
|
|
299
|
+
'Video Export resolution defaults to "current"; keep "4k" available as the high-resolution alternate.',
|
|
300
|
+
"Video Export format and resolution are a compact semantic pair and should use a two-column inline layout by default; use stacked rows only when labels or selected values do not fit without clipping.",
|
|
301
|
+
'Baseline browser video formats are "mp4" and "webm"; MOV or ProRes require an explicit custom encoder/transcoder and dedicated acceptance plus performance coverage.',
|
|
302
|
+
"Video export code must choose the actual MIME/container through MediaRecorder.isTypeSupported or an equivalent encoder capability check, then fall back safely.",
|
|
303
|
+
"Video export must use getToolcraftVideoExportSize for current and 4K dimensions. Current video export uses the current canvas/output size with even encoder-safe rounding; 4K video fits inside an encoder-safe 3840x2160 box, preserves canvas aspect ratio, and uses even pixel dimensions. Do not hand-roll 4096px long-edge video sizing.",
|
|
304
|
+
"Video export must set recording canvas dimensions before captureStream, MediaRecorder, VideoEncoder, or equivalent encoder setup, and must reject recorder/encoder errors instead of returning corrupt blobs.",
|
|
305
|
+
"Offline video export duration must be encoded from runtime timeline timestamps. Do not rely on canvas.captureStream plus MediaRecorder wall-clock recording time as the only duration mechanism for rendered-frame export.",
|
|
306
|
+
'Video resolution must control exported dimensions. Use "current" output size by default; "4K" is an export resolution target, not a hardcoded 3840x2160 canvas lock.',
|
|
307
|
+
"Video export browser coverage must load the exported blob metadata and prove video.duration matches the edited runtime timeline duration; blobSize/blobType checks alone are not enough.",
|
|
308
|
+
"Video export must report frame-based progress through reportProgress during render/encode steps. PNG export should report phase progress for render, blob, and handoff when those phases are asynchronous.",
|
|
309
|
+
'Product-output apps must expose a dedicated "Background" section directly before the first export settings section. With PNG export that first section is Image Export; with video-only export it is Video Export.',
|
|
310
|
+
"Product-output apps must pass the includeBackground runtime value to createToolcraftPngExportCanvas for PNG alpha and call shouldIncludeToolcraftPreviewBackground(state) for live preview product background.",
|
|
311
|
+
"PNG export must use createToolcraftPngExportCanvas so background transparency and selected image dimensions or retina fallback are applied consistently; turning Include off makes preview product background and PNG alpha transparent without hiding the Toolcraft canvas backing or video background.",
|
|
312
|
+
"Video export must keep product background and use getToolcraftVideoExportSize for current/4K output dimensions.",
|
|
313
|
+
"Copy PNG can be a secondary action when clipboard output is useful, but copy does not replace export.",
|
|
314
|
+
"Add Copy PNG as a secondary action only when the prompt/reference includes clipboard output or the product clearly benefits from paste/share workflows.",
|
|
315
|
+
"Footer actions must be one compact horizontal group; do not split them into stacked full-width sections.",
|
|
316
|
+
"If two footer actions are needed, render secondary/outline on the left and primary on the right.",
|
|
317
|
+
"When an odd number of footer actions renders in two columns, the final unpaired action spans the full row width.",
|
|
318
|
+
],
|
|
319
|
+
commands: ["controls.apply"],
|
|
320
|
+
stateMode: "command-only",
|
|
321
|
+
},
|
|
322
|
+
} as const satisfies Record<string, ToolcraftComponentContract>;
|