@pixel-point/toolcraft 0.0.17 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/generate-test-doc-assertions.mjs +58 -68
- package/src/generate-test-doc-assertions.test.mjs +43 -0
- package/src/generate-test-doc-policy-assertions.mjs +92 -0
- package/src/generate-test-file-assertions.mjs +26 -75
- package/src/generate-test-product-iteration.test.mjs +17 -0
- package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
- package/src/generate-test-standalone-assertions.mjs +10 -0
- package/templates/runtime/contracts/component-contracts.choices.test.ts +47 -3
- package/templates/runtime/contracts/component-contracts.choices.ts +48 -3
- package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
- package/templates/runtime/contracts/component-contracts.inputs.ts +6 -6
- package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
- package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
- package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +4 -4
- package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
- package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +3 -0
- package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +3 -0
- package/templates/runtime/contracts/component-contracts.runtime.ts +12 -8
- package/templates/runtime/contracts/component-contracts.test.ts +2 -0
- package/templates/runtime/contracts/decision-contracts.test.ts +18 -0
- package/templates/runtime/contracts/decision-contracts.ts +10 -10
- package/templates/runtime/export/export-background.ts +0 -19
- package/templates/runtime/export/export.test.ts +45 -42
- package/templates/runtime/export/index.ts +44 -16
- package/templates/runtime/index.ts +2 -0
- package/templates/runtime/model-import/model-import-limits.ts +15 -4
- package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +11 -1
- package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +29 -0
- package/templates/runtime/react/app-shell/toolcraft-app.tsx +18 -8
- package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +76 -0
- package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
- package/templates/runtime/react/canvas/canvas-shell.tsx +16 -1
- package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
- package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
- package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
- package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +1 -1
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +62 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
- package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +2 -4
- package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +10 -4
- package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
- package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
- package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +10 -8
- package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +3 -3
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
- package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
- package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
- package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
- package/templates/runtime/react/index.ts +4 -0
- package/templates/runtime/react/model-rendering/model-export.ts +1 -1
- package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
- package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
- package/templates/runtime/scene/scene-bounds.test.ts +23 -0
- package/templates/runtime/scene/scene-bounds.ts +31 -17
- package/templates/runtime/schema/app-capabilities.test.ts +4 -0
- package/templates/runtime/schema/collection-item-controls.ts +29 -0
- package/templates/runtime/schema/control-applicability.test.ts +127 -0
- package/templates/runtime/schema/control-applicability.ts +433 -0
- package/templates/runtime/schema/control-schema-normalization.ts +177 -11
- package/templates/runtime/schema/controls-panel-actions.ts +2 -2
- package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
- package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +59 -0
- package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
- package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
- package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
- package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
- package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
- package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
- package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
- package/templates/runtime/schema/runtime-setup-section.ts +24 -5
- package/templates/runtime/schema/types.ts +68 -13
- package/templates/starter/AGENTS.md +12 -10
- package/templates/starter/docs/toolcraft/acceptance-testing.md +17 -31
- package/templates/starter/docs/toolcraft/agent-worklog.md +15 -0
- package/templates/starter/docs/toolcraft/assembly-workflow.md +10 -3
- package/templates/starter/docs/toolcraft/component-rules.md +8 -6
- package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
- package/templates/starter/docs/toolcraft/core/layout.md +7 -7
- package/templates/starter/docs/toolcraft/core/media-upload.md +2 -0
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +13 -2
- package/templates/starter/docs/toolcraft/core/setup-export.md +33 -7
- package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
- package/templates/starter/docs/toolcraft/decision-contract.md +3 -1
- package/templates/starter/docs/toolcraft/renderer-technique.md +4 -0
- package/templates/starter/docs/toolcraft/schema-reference.md +21 -19
- package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
- package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +7 -2
- package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
- package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +1 -33
- package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -15
- package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
- package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
- package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +20 -11
- package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
- package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
- package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
- package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +9 -2
- package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +29 -26
- package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
- package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
- package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +85 -115
- package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
- package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -72
- package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
- package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
- package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +6 -17
- package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
- package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
- package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +2 -0
- package/templates/starter/src/app/acceptance/artifact-export-intent.ts +130 -0
- package/templates/starter/src/app/acceptance/conditions.ts +1 -1
- package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
- package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -20
- package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
- package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -13
- package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
- package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
- package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
- package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
- package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
- package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
- package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +3 -10
- package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
- package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
- package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
- package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
- package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
- package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
- package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
- package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
- package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
- package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
- package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +18 -10
- package/templates/starter/src/app/acceptance/output-export-model.ts +54 -11
- package/templates/starter/src/app/acceptance/output-export.ts +22 -10
- package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
- package/templates/starter/src/app/acceptance/types.ts +23 -8
- package/templates/starter/src/app/acceptance/validate-coverage.ts +19 -2
- package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +239 -0
- package/templates/starter/src/app/starter-acceptance.background-export.test.ts +33 -0
- package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +16 -1
- package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +65 -0
- package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
- package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +112 -16
- package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +224 -0
- package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
- package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
- package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
- package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
- package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +22 -0
- package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +37 -9
- package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +12 -0
- package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
- package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
- package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +384 -0
- package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +4 -0
- package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +112 -105
- package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +12 -0
- package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +1 -1
- package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
- package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
- package/templates/starter/src/app/starter-acceptance.ts +11 -2
- package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +336 -0
- package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +8 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +2 -2
- package/templates/starter/src/routes/index.tsx +1 -0
- package/templates/ui/components/composites/tabs.tsx +2 -2
- package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
- package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
- package/templates/ui/components/controls/collection-actions/index.ts +2 -0
- package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
- package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
- package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
- package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
- package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
- package/templates/ui/components/controls/file-drop/index.ts +1 -0
- package/templates/ui/components/controls/index.ts +3 -0
- package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
- package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
- package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
- package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
- package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
+
import type { ToolcraftCollectionItemControlType } from "./collection-item-controls";
|
|
3
4
|
import { defineToolcraft } from "./define-toolcraft";
|
|
4
5
|
import type { ToolcraftControlSchema } from "./types";
|
|
5
6
|
|
|
@@ -39,8 +40,9 @@ function createModeControl(
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
function createCollectionModeControl(
|
|
42
|
-
type:
|
|
43
|
+
type: ToolcraftCollectionItemControlType,
|
|
43
44
|
labels: readonly string[],
|
|
45
|
+
parentType = "collectionActions",
|
|
44
46
|
): ToolcraftControlSchema {
|
|
45
47
|
return {
|
|
46
48
|
defaultValue: ["default"],
|
|
@@ -57,7 +59,7 @@ function createCollectionModeControl(
|
|
|
57
59
|
label: "Modes",
|
|
58
60
|
minItems: 1,
|
|
59
61
|
target: "appearance.modes",
|
|
60
|
-
type:
|
|
62
|
+
type: parentType,
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -138,6 +140,22 @@ describe("defineToolcraft segmented control fit", () => {
|
|
|
138
140
|
expect(control).toEqual(inputSnapshot);
|
|
139
141
|
});
|
|
140
142
|
|
|
143
|
+
it("applies segmented item fit validation to sourceCollection", () => {
|
|
144
|
+
expect(() =>
|
|
145
|
+
defineToolcraft(
|
|
146
|
+
createAppSchema(
|
|
147
|
+
createCollectionModeControl(
|
|
148
|
+
"segmented",
|
|
149
|
+
SCREENSHOT_LABELS,
|
|
150
|
+
"sourceCollection",
|
|
151
|
+
),
|
|
152
|
+
),
|
|
153
|
+
),
|
|
154
|
+
).toThrow(
|
|
155
|
+
/Toolcraft control validation \[segmented-control-fit\] for target "appearance\.modes" itemControl: .*select dropdown/u,
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
141
159
|
it.each(["type", "target"] as const)(
|
|
142
160
|
"preserves required %s validation ownership",
|
|
143
161
|
(fieldName) => {
|
|
@@ -32,6 +32,7 @@ describe("defineToolcraft runtime setup canvas controls", () => {
|
|
|
32
32
|
|
|
33
33
|
expect(canvasSection?.title).toBe("Setup");
|
|
34
34
|
expect(canvasSection?.controls.infinityCanvas).toMatchObject({
|
|
35
|
+
applicability: { mode: "always", origin: "explicit" },
|
|
35
36
|
defaultValue: false,
|
|
36
37
|
label: "Infinity canvas",
|
|
37
38
|
target: "canvas.infinity",
|
|
@@ -52,7 +53,11 @@ describe("defineToolcraft runtime setup canvas controls", () => {
|
|
|
52
53
|
performanceRole: "workload",
|
|
53
54
|
target: "canvas.aspectRatio",
|
|
54
55
|
type: "aspectRatio",
|
|
55
|
-
|
|
56
|
+
applicability: {
|
|
57
|
+
all: [{ equals: false, target: "canvas.infinity" }],
|
|
58
|
+
mode: "conditional",
|
|
59
|
+
origin: "explicit",
|
|
60
|
+
},
|
|
56
61
|
});
|
|
57
62
|
expect(canvasSection?.controls.canvasWidth).toMatchObject({
|
|
58
63
|
defaultValue: 1440,
|
|
@@ -60,7 +65,11 @@ describe("defineToolcraft runtime setup canvas controls", () => {
|
|
|
60
65
|
performanceRole: "workload",
|
|
61
66
|
target: "canvas.size.width",
|
|
62
67
|
type: "text",
|
|
63
|
-
|
|
68
|
+
applicability: {
|
|
69
|
+
all: [{ equals: false, target: "canvas.infinity" }],
|
|
70
|
+
mode: "conditional",
|
|
71
|
+
origin: "explicit",
|
|
72
|
+
},
|
|
64
73
|
});
|
|
65
74
|
expect(canvasSection?.controls.canvasHeight).toMatchObject({
|
|
66
75
|
defaultValue: 900,
|
|
@@ -68,7 +77,11 @@ describe("defineToolcraft runtime setup canvas controls", () => {
|
|
|
68
77
|
performanceRole: "workload",
|
|
69
78
|
target: "canvas.size.height",
|
|
70
79
|
type: "text",
|
|
71
|
-
|
|
80
|
+
applicability: {
|
|
81
|
+
all: [{ equals: false, target: "canvas.infinity" }],
|
|
82
|
+
mode: "conditional",
|
|
83
|
+
origin: "explicit",
|
|
84
|
+
},
|
|
72
85
|
});
|
|
73
86
|
expect(canvasSection?.layoutGroups).toEqual([
|
|
74
87
|
{
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { defineToolcraft } from "./define-toolcraft";
|
|
4
|
+
import type { ToolcraftControlSchema } from "./types";
|
|
5
|
+
|
|
6
|
+
function createAppSchema(control: ToolcraftControlSchema) {
|
|
7
|
+
return {
|
|
8
|
+
canvas: { enabled: false },
|
|
9
|
+
panels: {
|
|
10
|
+
controls: {
|
|
11
|
+
sections: [
|
|
12
|
+
{
|
|
13
|
+
controls: { sections: control },
|
|
14
|
+
title: "Fill Sections",
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
title: "Controls",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createSourceCollection(
|
|
24
|
+
overrides: Record<string, unknown> = {},
|
|
25
|
+
): ToolcraftControlSchema {
|
|
26
|
+
return {
|
|
27
|
+
defaultValue: [{ hex: "#DFFF1A" }],
|
|
28
|
+
itemControl: { label: false, type: "color" },
|
|
29
|
+
itemLabel: "Section",
|
|
30
|
+
label: "Sections",
|
|
31
|
+
target: "fills.sections",
|
|
32
|
+
type: "sourceCollection",
|
|
33
|
+
...overrides,
|
|
34
|
+
} as ToolcraftControlSchema;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("defineToolcraft source collection", () => {
|
|
38
|
+
it("accepts a source-owned collection of built-in item controls", () => {
|
|
39
|
+
const app = defineToolcraft(createAppSchema(createSourceCollection()));
|
|
40
|
+
const control = app.panels.controls?.sections.find(
|
|
41
|
+
(section) => section.title === "Fill Sections",
|
|
42
|
+
)?.controls.sections;
|
|
43
|
+
|
|
44
|
+
expect(control?.type).toBe("sourceCollection");
|
|
45
|
+
expect(control?.itemControl?.type).toBe("color");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("requires source collections to declare their built-in item control", () => {
|
|
49
|
+
expect(() =>
|
|
50
|
+
defineToolcraft(
|
|
51
|
+
createAppSchema(createSourceCollection({ itemControl: undefined })),
|
|
52
|
+
),
|
|
53
|
+
).toThrow(
|
|
54
|
+
/Toolcraft control validation \[source-collection-item-control\] for target "fills\.sections": itemControl is required/u,
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("rejects unsupported collection item controls", () => {
|
|
59
|
+
const control = createSourceCollection({
|
|
60
|
+
itemControl: { type: "imaginary" },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
expect(() => defineToolcraft(createAppSchema(control))).toThrow(
|
|
64
|
+
/Toolcraft control validation \[collection-item-control\] for target "fills\.sections": unsupported collection item control "imaginary"/u,
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("rejects unsupported collectionActions item controls instead of falling back to text", () => {
|
|
69
|
+
const control = {
|
|
70
|
+
...createSourceCollection(),
|
|
71
|
+
itemControl: { type: "imaginary" },
|
|
72
|
+
type: "collectionActions",
|
|
73
|
+
} as unknown as ToolcraftControlSchema;
|
|
74
|
+
|
|
75
|
+
expect(() => defineToolcraft(createAppSchema(control))).toThrow(
|
|
76
|
+
/Toolcraft control validation \[collection-item-control\] for target "fills\.sections": unsupported collection item control "imaginary"/u,
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -38,6 +38,11 @@ const finiteCanvasCondition = Object.freeze({
|
|
|
38
38
|
equals: false,
|
|
39
39
|
target: toolcraftCanvasInfinityTarget,
|
|
40
40
|
});
|
|
41
|
+
const alwaysApplicable = Object.freeze({ mode: "always" as const });
|
|
42
|
+
const finiteCanvasApplicability = Object.freeze({
|
|
43
|
+
all: [finiteCanvasCondition],
|
|
44
|
+
mode: "conditional" as const,
|
|
45
|
+
});
|
|
41
46
|
|
|
42
47
|
type RuntimeSetupControlGroup = {
|
|
43
48
|
controls: ToolcraftControlSectionSchema["controls"];
|
|
@@ -146,6 +151,7 @@ function createRenderScaleControl(
|
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
return {
|
|
154
|
+
applicability: alwaysApplicable,
|
|
149
155
|
defaultValue: canvas.renderScale.defaultValue,
|
|
150
156
|
description:
|
|
151
157
|
"Increases raster canvas backing resolution without changing the visible output size.",
|
|
@@ -175,6 +181,7 @@ function createInfinityCanvasControl(
|
|
|
175
181
|
}
|
|
176
182
|
|
|
177
183
|
return {
|
|
184
|
+
applicability: alwaysApplicable,
|
|
178
185
|
defaultValue: getToolcraftDefaultCanvasMode(canvas) === "infinite",
|
|
179
186
|
...(background
|
|
180
187
|
? {
|
|
@@ -199,6 +206,7 @@ function createTimelineExtendedControl(
|
|
|
199
206
|
}
|
|
200
207
|
|
|
201
208
|
return {
|
|
209
|
+
applicability: alwaysApplicable,
|
|
202
210
|
defaultValue: false,
|
|
203
211
|
label: "Timeline",
|
|
204
212
|
target: toolcraftTimelinePanelExtendedTarget,
|
|
@@ -230,13 +238,23 @@ function createRuntimeSetupBackgroundControls({
|
|
|
230
238
|
return {
|
|
231
239
|
controls: {
|
|
232
240
|
...(includeBackgroundControl
|
|
233
|
-
? {
|
|
241
|
+
? {
|
|
242
|
+
includeBackground: {
|
|
243
|
+
...includeBackgroundControl,
|
|
244
|
+
applicability: alwaysApplicable,
|
|
245
|
+
},
|
|
246
|
+
}
|
|
234
247
|
: {}),
|
|
235
248
|
...(infinityCanvasControl
|
|
236
249
|
? { infinityCanvas: infinityCanvasControl }
|
|
237
250
|
: {}),
|
|
238
251
|
...(backgroundColorControl
|
|
239
|
-
? {
|
|
252
|
+
? {
|
|
253
|
+
background: {
|
|
254
|
+
...backgroundColorControl,
|
|
255
|
+
applicability: alwaysApplicable,
|
|
256
|
+
},
|
|
257
|
+
}
|
|
240
258
|
: {}),
|
|
241
259
|
},
|
|
242
260
|
layoutGroups:
|
|
@@ -262,6 +280,7 @@ function createFiniteCanvasControls(
|
|
|
262
280
|
return {
|
|
263
281
|
controls: {
|
|
264
282
|
canvasAspectRatio: {
|
|
283
|
+
applicability: finiteCanvasApplicability,
|
|
265
284
|
defaultValue: getCanvasAspectRatioDefaultValue(canvas.size),
|
|
266
285
|
label: "Aspect ratio",
|
|
267
286
|
orderRole: "input",
|
|
@@ -269,9 +288,9 @@ function createFiniteCanvasControls(
|
|
|
269
288
|
performanceRole: "workload",
|
|
270
289
|
target: canvasAspectRatioTarget,
|
|
271
290
|
type: "aspectRatio",
|
|
272
|
-
visibleWhen: finiteCanvasCondition,
|
|
273
291
|
},
|
|
274
292
|
canvasWidth: {
|
|
293
|
+
applicability: finiteCanvasApplicability,
|
|
275
294
|
defaultValue: canvas.size.width,
|
|
276
295
|
label: "Canvas width",
|
|
277
296
|
orderRole: "input",
|
|
@@ -279,9 +298,9 @@ function createFiniteCanvasControls(
|
|
|
279
298
|
performanceRole: "workload",
|
|
280
299
|
target: canvasSizeControlTargets.width,
|
|
281
300
|
type: "text",
|
|
282
|
-
visibleWhen: finiteCanvasCondition,
|
|
283
301
|
},
|
|
284
302
|
canvasHeight: {
|
|
303
|
+
applicability: finiteCanvasApplicability,
|
|
285
304
|
defaultValue: canvas.size.height,
|
|
286
305
|
label: "Canvas height",
|
|
287
306
|
orderRole: "input",
|
|
@@ -289,7 +308,6 @@ function createFiniteCanvasControls(
|
|
|
289
308
|
performanceRole: "workload",
|
|
290
309
|
target: canvasSizeControlTargets.height,
|
|
291
310
|
type: "text",
|
|
292
|
-
visibleWhen: finiteCanvasCondition,
|
|
293
311
|
},
|
|
294
312
|
},
|
|
295
313
|
layoutGroups: [
|
|
@@ -325,6 +343,7 @@ export function createToolcraftRuntimeSetupSection({
|
|
|
325
343
|
const section: ToolcraftControlSectionSchema & { id: string } = {
|
|
326
344
|
controls: {
|
|
327
345
|
settingsTransfer: {
|
|
346
|
+
applicability: alwaysApplicable,
|
|
328
347
|
label: false,
|
|
329
348
|
target: settingsTransferTarget,
|
|
330
349
|
type: "settingsTransfer",
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ToolcraftControlLayoutGroupLayout,
|
|
4
4
|
ToolcraftSectionLayout,
|
|
5
5
|
} from "../contracts/types";
|
|
6
|
+
import type { ToolcraftCollectionItemControlType } from "./collection-item-controls";
|
|
6
7
|
|
|
7
8
|
export type ToolcraftCanvasSize = {
|
|
8
9
|
height: number;
|
|
@@ -412,7 +413,7 @@ export type ResolvedToolcraftMediaSchema = {
|
|
|
412
413
|
defaultAssets: readonly ToolcraftDefaultMediaAssetSchema[];
|
|
413
414
|
};
|
|
414
415
|
|
|
415
|
-
export type
|
|
416
|
+
export type ToolcraftControlPredicateSchema = Readonly<{
|
|
416
417
|
equals?: unknown;
|
|
417
418
|
greaterThan?: number;
|
|
418
419
|
greaterThanOrEqual?: number;
|
|
@@ -422,7 +423,28 @@ export type ToolcraftControlConditionSchema = {
|
|
|
422
423
|
notEquals?: unknown;
|
|
423
424
|
oneOf?: readonly unknown[];
|
|
424
425
|
target: string;
|
|
425
|
-
}
|
|
426
|
+
}>;
|
|
427
|
+
|
|
428
|
+
export type ToolcraftControlConditionSchema =
|
|
429
|
+
ToolcraftControlPredicateSchema;
|
|
430
|
+
|
|
431
|
+
export type ToolcraftControlApplicabilitySchema =
|
|
432
|
+
| Readonly<{ mode: "always" }>
|
|
433
|
+
| Readonly<{
|
|
434
|
+
all: readonly ToolcraftControlPredicateSchema[];
|
|
435
|
+
mode: "conditional";
|
|
436
|
+
}>;
|
|
437
|
+
|
|
438
|
+
export type ToolcraftResolvedControlApplicabilitySchema =
|
|
439
|
+
| Readonly<{
|
|
440
|
+
mode: "always";
|
|
441
|
+
origin: "explicit" | "implicit";
|
|
442
|
+
}>
|
|
443
|
+
| Readonly<{
|
|
444
|
+
all: readonly ToolcraftControlPredicateSchema[];
|
|
445
|
+
mode: "conditional";
|
|
446
|
+
origin: "explicit" | "legacy";
|
|
447
|
+
}>;
|
|
426
448
|
|
|
427
449
|
export type ToolcraftControlDisabledConditionSchema =
|
|
428
450
|
ToolcraftControlConditionSchema;
|
|
@@ -434,18 +456,29 @@ export type ToolcraftColorOpacityValueSchema = {
|
|
|
434
456
|
|
|
435
457
|
export type ToolcraftCollectionItemControlSchema = {
|
|
436
458
|
commitMode?: "content" | "setting";
|
|
459
|
+
coordinateMode?: ToolcraftVectorCoordinateMode;
|
|
437
460
|
defaultValue?: unknown;
|
|
461
|
+
description?: string;
|
|
438
462
|
label?: boolean | string;
|
|
439
463
|
markerCount?: number;
|
|
440
464
|
max?: number;
|
|
441
465
|
min?: number;
|
|
442
466
|
options?: readonly { label: string; value: string }[];
|
|
467
|
+
performanceReason?: string;
|
|
468
|
+
performanceRole?: ToolcraftControlPerformanceRole;
|
|
469
|
+
sliderValueKind?: ToolcraftSliderValueKind;
|
|
443
470
|
step?: number;
|
|
444
|
-
type:
|
|
471
|
+
type: ToolcraftCollectionItemControlType;
|
|
445
472
|
unit?: string;
|
|
446
473
|
variant?: string;
|
|
474
|
+
xLabel?: string;
|
|
475
|
+
yLabel?: string;
|
|
447
476
|
};
|
|
448
477
|
|
|
478
|
+
export type ToolcraftCollectionItemControlsSchema = Readonly<
|
|
479
|
+
Record<string, ToolcraftCollectionItemControlSchema>
|
|
480
|
+
>;
|
|
481
|
+
|
|
449
482
|
export type ToolcraftFontPickerValueSchema = {
|
|
450
483
|
color?: string;
|
|
451
484
|
fontId: string;
|
|
@@ -461,7 +494,7 @@ export type ToolcraftCurveInterpolation = "monotone" | "smooth";
|
|
|
461
494
|
|
|
462
495
|
export type ToolcraftVectorCoordinateMode = "cartesian" | "screen";
|
|
463
496
|
|
|
464
|
-
|
|
497
|
+
type ToolcraftControlSchemaFields = {
|
|
465
498
|
accept?: string;
|
|
466
499
|
actions?: readonly (ToolcraftActionSchema | string)[];
|
|
467
500
|
addLabel?: string;
|
|
@@ -476,6 +509,7 @@ export type ToolcraftControlSchemaBase = {
|
|
|
476
509
|
interpolation?: ToolcraftCurveInterpolation;
|
|
477
510
|
items?: readonly ToolcraftImagePickerItemSchema[];
|
|
478
511
|
itemControl?: ToolcraftCollectionItemControlSchema;
|
|
512
|
+
itemControls?: ToolcraftCollectionItemControlsSchema;
|
|
479
513
|
itemDefaultValue?: unknown;
|
|
480
514
|
itemLabel?: string;
|
|
481
515
|
keyframeable?: boolean;
|
|
@@ -498,11 +532,16 @@ export type ToolcraftControlSchemaBase = {
|
|
|
498
532
|
unit?: string;
|
|
499
533
|
valueLabel?: string;
|
|
500
534
|
variant?: string;
|
|
501
|
-
visibleWhen?: ToolcraftControlConditionSchema;
|
|
502
535
|
xLabel?: string;
|
|
503
536
|
yLabel?: string;
|
|
504
537
|
};
|
|
505
538
|
|
|
539
|
+
export type ToolcraftControlSchemaBase = ToolcraftControlSchemaFields & {
|
|
540
|
+
applicability?: ToolcraftControlApplicabilitySchema;
|
|
541
|
+
/** @deprecated Product controls use conditional applicability. */
|
|
542
|
+
visibleWhen?: ToolcraftControlPredicateSchema;
|
|
543
|
+
};
|
|
544
|
+
|
|
506
545
|
export type ToolcraftNonModelControlSchema = ToolcraftControlSchemaBase & {
|
|
507
546
|
assetKind?: ToolcraftMediaAssetKind;
|
|
508
547
|
modelFormats?: never;
|
|
@@ -525,18 +564,34 @@ export type ToolcraftControlSchema =
|
|
|
525
564
|
| ToolcraftNonModelControlSchema
|
|
526
565
|
| ToolcraftModelFileDropSchema;
|
|
527
566
|
|
|
567
|
+
type ToolcraftResolvedControlApplicabilityFields = Readonly<{
|
|
568
|
+
applicability: ToolcraftResolvedControlApplicabilitySchema;
|
|
569
|
+
}>;
|
|
570
|
+
|
|
571
|
+
export type ResolvedToolcraftNonModelControlSchema = Omit<
|
|
572
|
+
ToolcraftNonModelControlSchema,
|
|
573
|
+
"applicability" | "visibleWhen"
|
|
574
|
+
> &
|
|
575
|
+
ToolcraftResolvedControlApplicabilityFields;
|
|
576
|
+
|
|
528
577
|
export type ResolvedToolcraftModelFileDropSchema = Omit<
|
|
529
578
|
ToolcraftModelFileDropSchema,
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
579
|
+
| "applicability"
|
|
580
|
+
| "modelFormats"
|
|
581
|
+
| "modelLimits"
|
|
582
|
+
| "multiple"
|
|
583
|
+
| "topologyProfile"
|
|
584
|
+
| "visibleWhen"
|
|
585
|
+
> &
|
|
586
|
+
ToolcraftResolvedControlApplicabilityFields & {
|
|
587
|
+
modelFormats: readonly ToolcraftModelFormat[];
|
|
588
|
+
modelLimits: ToolcraftModelImportLimits;
|
|
589
|
+
multiple: false;
|
|
590
|
+
topologyProfile: ToolcraftModelTopologyProfile;
|
|
591
|
+
};
|
|
537
592
|
|
|
538
593
|
export type ResolvedToolcraftControlSchema =
|
|
539
|
-
|
|
|
594
|
+
| ResolvedToolcraftNonModelControlSchema
|
|
540
595
|
| ResolvedToolcraftModelFileDropSchema;
|
|
541
596
|
|
|
542
597
|
export type ToolcraftControlLayoutGroupSchema = {
|
|
@@ -20,10 +20,10 @@ Process matching routes sequentially within the current phase and skip repeated
|
|
|
20
20
|
|
|
21
21
|
1. Build through `defineToolcraft` and `ToolcraftApp`.
|
|
22
22
|
2. Keep app state in Toolcraft runtime schema and commands.
|
|
23
|
-
3. Keep product output in `canvasContent`; never render app UI there. The signed host owns `ToolcraftApp`, bootstrap, routes,
|
|
24
|
-
4. Use built-in Toolcraft controls before custom controls. Before controls or canvas interactions, declare typed `interactionOwnership`: user request, inspected reference, or product usability selects one primary surface for each operation; complementary operations may share related state, but canvas and panel must not mirror the same operation. Every product also declares typed `viewInteraction` before renderer code; a visible editable spatial scene defaults to `orbit` and uses schema `orientationGizmo` plus runtime model-orbit interaction. Fixed or timeline-owned cameras require an explicit user request or inspected-reference evidence.
|
|
25
|
-
5. Do not hand-compose runtime surfaces or render built-in control components directly in app code; use `ToolcraftApp`, schema controls, `canvasContent`, `controlRenderers`, `onPanelAction`, and runtime commands.
|
|
26
|
-
6. Before writing controls,
|
|
23
|
+
3. Keep product output in `canvasContent`; never render app UI there. The signed host owns `ToolcraftApp`, bootstrap, routes, global runtime styles, and the finite/infinite product scene surface; product code supplies only `ToolcraftAppComposition`. Infinite custom raster/WebGL output declares `sceneBoundsProvider` and consumes `useToolcraftProductSceneFrame` instead of dormant finite `canvas.size`. A preview-only environment that must fill the complete Infinity viewport uses `infiniteCanvasContent`; it remains pointer-transparent and outside world transforms, scene bounds, and export. Model upload preserves supported authored appearance from standalone files, folders, and bounded ZIP packages; declare typed `modelPresentation`, using runtime presentation by default and checked consumers for custom presentation. `renderDefaultCanvasMedia={false}` never hides runtime model layers. If upload/import is part of the source-material flow, do not invent canvas placeholder artwork, CTA copy, helper text, fake sample output, or preset source designs before real content exists.
|
|
24
|
+
4. Use built-in Toolcraft controls before custom controls. Use `sourceCollection` when a source/runtime workflow owns array cardinality and users edit existing built-in item values; use `collectionActions` when users own add/remove cardinality. Before controls or canvas interactions, declare typed `interactionOwnership`: user request, inspected reference, or product usability selects one primary surface for each operation; complementary operations may share related state, but canvas and panel must not mirror the same operation. Every product also declares typed `viewInteraction` before renderer code; a visible editable spatial scene defaults to `orbit` and uses schema `orientationGizmo` plus runtime model-orbit interaction. Fixed or timeline-owned cameras require an explicit user request or inspected-reference evidence.
|
|
25
|
+
5. Do not hand-compose runtime surfaces or render built-in control components directly in app code; use `ToolcraftApp`, schema controls, `canvasContent`, `controlRenderers`, `onPanelAction`, and runtime commands. Product code never imports modules below `src/toolcraft/ui/components/controls/**` or substitutes native `color`, `range`, `file`, `checkbox`, `radio`, `select`, or `textarea` value models for schema controls. Product artifact surfaces must correspond exactly to required `productReadiness.exportIntent`; use `docs/toolcraft/core/setup-export.md` for the canonical export decision sequence.
|
|
26
|
+
6. Before writing controls, export `starterControlSectionInventory`. Every product section declares stable `entityId`, human-readable `entity`, exact targets, and `groupingReason`. Every product control explicitly declares `applicability` as `always` or `conditional`; inactive branches are absent, and every visible finite sibling branch must prove the control's accepted product outcome. Keep one entity in one section through ten controls; sections with eight to ten controls declare `semanticGroup` on every control. Entities above ten controls split into balanced two-to-ten-control workflow stages that keep the same entity identity and declare unique `workflowStage` plus `splitReason`. Group by product meaning, never by UI component type or target namespace.
|
|
27
27
|
7. Keep control `label` short but semantically sufficient with the nearest visible section/group context, and put product-specific behavior help in schema `description`; runtime renders the label help tooltip only when that description adds meaning beyond the label.
|
|
28
28
|
8. Enable layers and timeline only when product behavior requires them, then test the real UI. Product animation loops are seamless forward-only by default: first and last frames stitch, direction does not reverse, and mirror/yoyo/ping-pong behavior requires explicit user intent.
|
|
29
29
|
9. Animated preview renderers suspend or coalesce non-essential animation work during canvas drag, pan, pinch, zoom, and radar/center interactions, then resume without changing user playback state.
|
|
@@ -33,7 +33,7 @@ Process matching routes sequentially within the current phase and skip repeated
|
|
|
33
33
|
13. Generated apps follow the mandatory runtime Setup, Infinity canvas/finite canvas sizing, render scale, Timeline switch, Background, Image Export, Video Export, and sticky action rules in `docs/toolcraft/core/setup-export.md`. Do not duplicate or reinterpret those controls in app-authored sections.
|
|
34
34
|
14. Media uploads, image/file mode, source images, multi-upload sorting, default assets, and image transform actions follow `docs/toolcraft/core/media-upload.md`.
|
|
35
35
|
15. Keep `docs/toolcraft/agent-worklog.md` current with a decision trail, product decisions, explicit reference inputs, evidence, verification, and risks. Reference-runtime-clone apps also declare `referenceStudy` plus `referenceFeatureInventory` so every inspected reference feature has feature-level behavior evidence and maps to Toolcraft implementation and acceptance coverage.
|
|
36
|
-
16. Prove every visible entity through acceptance, browser, and performance coverage. Browser acceptance and performance pass only when protected helpers emit matching runtime evidence after successful assertions; source-code spelling and acceptance prose are not outcome authority.
|
|
36
|
+
16. Prove every visible entity through acceptance, browser, and performance coverage. Browser acceptance and performance pass only when protected helpers emit matching runtime evidence after successful assertions; source-code spelling and acceptance prose are not outcome authority. Control applicability derives case-scoped presence/absence and product-outcome evidence from semantic section peers; background output keeps its fixed typed recipe. Raster products with `canvas.renderScale` declare `renderScaleCoverage` for interaction and steady state, plus playback when timeline is enabled, and prove real backing pixels with `canvas-render-scale-backing`; clamping quality is a functional failure without measured performance. Every measured path in a render-scale-enabled raster product proves actual CSS × devicePixelRatio × 2 backing after each measured phase. Generic acceptance outcomes prove command side effects only; use the fixed media, persistence, viewport, compound-control, layer, and timeline semantic recipes for specialized evidence.
|
|
37
37
|
17. Performance planning follows one sequence: reachable controls and inputs; workload dimensions and enforced boundaries; pass cost, frequency, lifecycle, and invalidation; render-plan assessment and protected kernel benchmark when required; derived paths and combined fixtures; targeted functional/browser development checks; lifecycle-appropriate delivery proof. Keep `src/app/app-verification-impact.json` complete so later functional changes derive exact verification scope. Only exact request authority may create a measured targeted performance iteration. Details live in `docs/toolcraft/core/performance.md` and `docs/toolcraft/performance.md`.
|
|
38
38
|
18. Custom renderer apps compile one canonical `rendererPipelineRegistration`, supply it through `ToolcraftAppComposition`, reuse that registration as `rendererPipeline` in performance assessment, and derive paths and fixtures from it. The neutral starter has no registration, runtime provider, or fixture adapters.
|
|
39
39
|
19. Classify each coherent user-visible delivery batch with a verification tier before editing. Steering and fixes inside the same request stay in that batch. Use targeted checks for development feedback, then run the protected delivery gate once when the batch is ready.
|
|
@@ -42,7 +42,7 @@ Process matching routes sequentially within the current phase and skip repeated
|
|
|
42
42
|
|
|
43
43
|
The generated folder starts as a neutral Toolcraft shell: canvas upload plus toolbar. It intentionally does not include demo controls, prompt fields, layers, or timeline. Do not treat test fixtures or documentation examples as product requirements. Add controls, timeline, layers, sticky actions, and custom renderers only after the requested product or reference app requires them; base workspace persistence already exists.
|
|
44
44
|
|
|
45
|
-
When the folder becomes a real product, update `src/app/app-acceptance-data.ts` from `appProductReadiness.mode: "starter"` to `mode: "product"` and fill `productName`, `productSummary`, `requestedBehavior`, typed `interactionOwnership`, and typed `viewInteraction`. Compare canvas and panel for each operation that could plausibly live on either surface. A visible editable 3D scene uses `orbit`; `fixed-camera` and `timeline-camera` require explicit request/reference evidence. Renamed product folders are not allowed to keep neutral starter readiness.
|
|
45
|
+
When the folder becomes a real product, update `src/app/app-acceptance-data.ts` from `appProductReadiness.mode: "starter"` to `mode: "product"` and fill `productName`, `productSummary`, `requestedBehavior`, required typed `exportIntent`, typed `interactionOwnership`, and typed `viewInteraction`. Compare canvas and panel for each operation that could plausibly live on either surface. A visible editable 3D scene uses `orbit`; `fixed-camera` and `timeline-camera` require explicit request/reference evidence. Renamed product folders are not allowed to keep neutral starter readiness.
|
|
46
46
|
|
|
47
47
|
## License
|
|
48
48
|
|
|
@@ -119,9 +119,10 @@ These ids mirror `TOOLCRAFT_DECISION_CONTRACT` in `@/toolcraft/runtime`. Keep th
|
|
|
119
119
|
|
|
120
120
|
- Use `defineToolcraft` from `@/toolcraft/runtime`.
|
|
121
121
|
- Export an `appComposition` satisfying `ToolcraftAppComposition` from `src/app/app-composition.tsx`.
|
|
122
|
-
- Keep product composition limited to `schema`, `canvasContent`, `controlRenderers`, `exportRenderer`, `modelPresentation`, `onPanelAction`, `renderDefaultCanvasMedia`, and optional `rendererPipelineRegistration`; host `className` and `style` are not product extension points.
|
|
122
|
+
- Keep product composition limited to `schema`, `canvasContent`, `infiniteCanvasContent`, `controlRenderers`, `exportRenderer`, `sceneBoundsProvider`, `modelPresentation`, `onPanelAction`, `renderDefaultCanvasMedia`, and optional `rendererPipelineRegistration`; host `className` and `style` are not product extension points.
|
|
123
|
+
- Infinite product output fills the runtime-owned scene surface derived from `sceneBoundsProvider`. Raster/WebGL renderers call `useToolcraftProductSceneFrame` for backing size and coordinate translation; they never position a second bounds wrapper or use dormant finite `canvas.size` while infinite.
|
|
123
124
|
- Custom renderers use one compiled `rendererPipelineRegistration` as the canonical declaration for runtime execution and new-envelope performance assessment. Product code receives only the disposal-free pipeline client through hooks and panel action context.
|
|
124
|
-
- Do not import `ToolcraftApp`, low-level runtime surfaces,
|
|
125
|
+
- Do not import `ToolcraftApp`, low-level runtime surfaces, built-in controls, or modules below `src/toolcraft/ui/components/controls/**` into product modules. Do not recreate schema control value models with native form elements. The signed host renders the shell; product modules use schema controls and supported composition fields.
|
|
125
126
|
- Use `renderDefaultCanvasMedia={false}` when a custom renderer replaces generic image/file preview. This flag does not suppress runtime model layers; use typed `modelPresentation` custom mode with checked consumers for declared model targets.
|
|
126
127
|
- Use `ToolcraftApp onPanelAction` for non-export sticky footer product actions such as Generate, Apply, Copy, or Download. Typed `export-image` and `export-video` actions are executed by the runtime from the shared `ToolcraftAppComposition.exportRenderer`.
|
|
127
128
|
- Product export renderers draw one deterministic scene-coordinate frame and return/await their real work. Product modules never allocate export canvases, choose encoders, encode blobs, create download URLs, or duplicate image/video composition.
|
|
@@ -203,10 +204,11 @@ The app is complete only when:
|
|
|
203
204
|
- the Toolcraft runtime shell is present;
|
|
204
205
|
- `canvasContent` contains product output only;
|
|
205
206
|
- the runtime canvas backing remains visible behind product output;
|
|
206
|
-
-
|
|
207
|
+
- infinite product output uses the runtime-owned product scene surface, exact provider bounds, and real edge-pixel proof without clipping to dormant finite `canvas.size`;
|
|
208
|
+
- every product control declares explicit applicability, every non-matching finite branch hides it, and every visible finite branch proves product output or the accepted command side effect;
|
|
207
209
|
- reset returns schema controls to `defaultValue`;
|
|
208
210
|
- sticky footer export actions operate on final product output at `state.canvas.size`;
|
|
209
|
-
-
|
|
211
|
+
- artifact actions and settings correspond exactly to `productReadiness.exportIntent`; image export is the product default, video requires explicit user-request evidence, and image removal requires explicit user-removal evidence;
|
|
210
212
|
- PNG export uses the background controls normalized into runtime Setup: `Background` beside `Infinity canvas`, then `Background color`; live preview hides product background when Background is off, and video keeps background;
|
|
211
213
|
- every PNG export includes `Image Export` format/resolution `select` controls; runtime resolves the selected settings and exact output size;
|
|
212
214
|
- products with both PNG and video export place `Image Export` immediately before `Video Export`;
|