@salsita-ai/sdk 0.50.0-develop.8c8c362f86 → 0.50.0-develop.8e3768cb11
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/dist/application-spec/core/components/component-filter.d.ts +53 -0
- package/dist/application-spec/core/components/component-filter.js +1 -0
- package/dist/application-spec/core/components/index.d.ts +2 -0
- package/dist/application-spec/core/components/index.js +1 -0
- package/dist/application-spec/core/components/sdk-code-ref.d.ts +9 -0
- package/dist/application-spec/core/components/sdk-code-ref.js +1 -0
- package/dist/application-spec/core/enhanced-json-value.d.ts +0 -68
- package/dist/application-spec/core/enhanced-json-value.js +1 -1
- package/dist/application-spec/core/expressions/index.d.ts +2 -0
- package/dist/application-spec/core/expressions/index.js +1 -0
- package/dist/application-spec/core/expressions/relation-expression-params.d.ts +11 -0
- package/dist/application-spec/core/expressions/relation-expression-params.js +1 -0
- package/dist/application-spec/core/expressions/sdk-expression-implementation.d.ts +24 -0
- package/dist/application-spec/core/expressions/sdk-expression-implementation.js +1 -0
- package/dist/application-spec/core/index.d.ts +2 -0
- package/dist/application-spec/core/index.js +1 -1
- package/dist/application-spec/core/json-value.d.ts +1 -1
- package/dist/application-spec/{core → enhanced-json}/eval-to-constant.d.ts +1 -1
- package/dist/application-spec/enhanced-json/index.d.ts +4 -0
- package/dist/application-spec/enhanced-json/index.js +1 -0
- package/dist/application-spec/enhanced-json/is-enhanced-json-array.d.ts +2 -0
- package/dist/application-spec/enhanced-json/is-enhanced-json-array.js +1 -0
- package/dist/application-spec/enhanced-json/resolve-enhanced-json-value.d.ts +18 -0
- package/dist/application-spec/enhanced-json/resolve-enhanced-json-value.js +1 -0
- package/dist/application-spec/enhanced-json/schema-from-value.d.ts +24 -0
- package/dist/application-spec/enhanced-json/schema-from-value.js +1 -0
- package/dist/application-spec/enhanced-json/stringify-enhanced-json-value.d.ts +14 -0
- package/dist/application-spec/enhanced-json/stringify-enhanced-json-value.js +1 -0
- package/dist/application-spec/enhanced-json/validate-enhanced-json-value-caps.d.ts +12 -0
- package/dist/application-spec/enhanced-json/validate-enhanced-json-value-caps.js +1 -0
- package/dist/application-spec/enhanced-json/validate-no-legacy-code-ref.d.ts +13 -0
- package/dist/application-spec/enhanced-json/validate-no-legacy-code-ref.js +1 -0
- package/dist/application-spec/generate-application/code/generate-application-code.d.ts +3 -2
- package/dist/application-spec/generate-application/code/generate-application-code.js +1 -1
- package/dist/application-spec/generate-application/code/project-scaffolding.d.ts +9 -4
- package/dist/application-spec/generate-application/code/project-scaffolding.js +2 -2
- package/dist/application-spec/generate-application/code/standalone-app-files.d.ts +2 -2
- package/dist/application-spec/generate-application/code/standalone-app-files.js +1 -1
- package/dist/application-spec/generate-application/code/templates/configurator-config.js +6 -4
- package/dist/application-spec/generate-application/code/templates/domain-spec/generate-component-optics.js +4 -4
- package/dist/application-spec/generate-application/code/templates/domain-spec/generate-defaults.js +1 -1
- package/dist/application-spec/generate-application/code/templates/gitignore.js +1 -2
- package/dist/application-spec/generate-application/code/templates/index.d.ts +1 -1
- package/dist/application-spec/generate-application/code/templates/index.js +1 -1
- package/dist/application-spec/generate-application/code/templates/package-json.js +1 -1
- package/dist/application-spec/generate-application/code/templates/root-tsconfig.d.ts +6 -0
- package/dist/application-spec/generate-application/code/templates/root-tsconfig.js +2 -0
- package/dist/application-spec/generate-application/code/templates/skills/phoenix-review-skill.js +1 -1
- package/dist/application-spec/generate-application/code/templates/skills/phoenix-skill.js +1 -1
- package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +10 -4
- package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +2 -2
- package/dist/application-spec/generate-application/code/templates/tsconfig.d.ts +5 -0
- package/dist/application-spec/generate-application/code/templates/tsconfig.js +1 -1
- package/dist/application-spec/generate-application/code/templates/webhook-index.d.ts +6 -1
- package/dist/application-spec/generate-application/code/templates/webhook-index.js +10 -1
- package/dist/application-spec/generate-application/index.d.ts +2 -0
- package/dist/application-spec/generate-application/index.js +1 -1
- package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.d.ts +6 -2
- package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.js +1 -1
- package/dist/application-spec/generate-application/runtime/application-runtime.d.ts +8 -1
- package/dist/application-spec/generate-application/runtime/application-runtime.js +1 -1
- package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.d.ts +5 -1
- package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.js +1 -1
- package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.d.ts +43 -0
- package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.js +1 -0
- package/dist/application-spec/generate-application/runtime/factory-data/index.d.ts +3 -0
- package/dist/application-spec/generate-application/runtime/factory-data/index.js +1 -0
- package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.d.ts +13 -0
- package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.js +1 -0
- package/dist/application-spec/generate-application/runtime/factory-data/static-violations.d.ts +16 -0
- package/dist/application-spec/generate-application/runtime/factory-data/static-violations.js +1 -0
- package/dist/application-spec/generate-application/runtime/migrations/index.d.ts +1 -0
- package/dist/application-spec/generate-application/runtime/migrations/index.js +1 -0
- package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.d.ts +53 -0
- package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.js +1 -0
- package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.d.ts +1 -1
- package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.js +1 -1
- package/dist/application-spec/generate-application/runtime/sections/expression-runtime.js +1 -1
- package/dist/application-spec/index.d.ts +1 -0
- package/dist/application-spec/index.js +1 -1
- package/dist/application-spec/parse-application-files/categorize/categorize-files.d.ts +16 -0
- package/dist/application-spec/parse-application-files/categorize/categorize-files.js +1 -1
- package/dist/application-spec/parse-application-files/categorize/earlier-generated-tsconfig.d.ts +9 -0
- package/dist/application-spec/parse-application-files/categorize/earlier-generated-tsconfig.js +1 -0
- package/dist/application-spec/parse-application-files/raw-spec/raw-spec-file.js +1 -1
- package/dist/application-spec/parse-application-files/spec/components/component-entry.d.ts +1 -9
- package/dist/application-spec/parse-application-files/spec/components/component-entry.js +1 -1
- package/dist/application-spec/parse-application-files/spec/components/component-filter.d.ts +1 -54
- package/dist/application-spec/parse-application-files/spec/components/component-filter.js +1 -1
- package/dist/application-spec/parse-application-files/spec/components/index.d.ts +1 -1
- package/dist/application-spec/parse-application-files/spec/components/index.js +1 -1
- package/dist/application-spec/parse-application-files/spec/expressions/expression.d.ts +1 -28
- package/dist/application-spec/parse-application-files/spec/expressions/expression.js +1 -1
- package/dist/application-spec/parse-application-files/spec/expressions/expressions.d.ts +1 -1
- package/dist/application-spec/parse-application-files/spec/expressions/expressions.js +1 -1
- package/dist/application-spec/parse-application-files/spec/expressions/index.d.ts +0 -1
- package/dist/application-spec/parse-application-files/spec/expressions/index.js +1 -1
- package/dist/application-spec/parse-application-files/spec/expressions/memo-eval-plan.js +1 -1
- package/dist/application-spec/parse-application-files/spec/expressions/user-expressions.js +1 -1
- package/dist/application-spec/parse-application-files/spec/model/defaults.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +29 -0
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts +7 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/drag-and-drop-system/drag-and-drop-system.d.ts +3 -3
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +6 -0
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/layout-system/layout-system.d.ts +2 -2
- package/dist/configurator/common/configurator-interface.d.ts +22 -1
- package/dist/configurator/common/configurator-interface.js +1 -1
- package/dist/configurator/common/frontend-analytics.d.ts +2 -0
- package/dist/configurator/common/frontend-analytics.js +1 -1
- package/dist/configurator/common/index.d.ts +2 -0
- package/dist/configurator/common/index.js +1 -1
- package/dist/configurator/common/use-finalize-action.d.ts +31 -0
- package/dist/configurator/common/use-finalize-action.js +1 -0
- package/dist/configurator/common/use-reset-camera.d.ts +6 -0
- package/dist/configurator/common/use-reset-camera.js +1 -0
- package/dist/configurator/configurator-context/configurator-hooks/layout-hooks.d.ts +1 -1
- package/dist/configurator/pages/DefaultConfiguratorLayout.d.ts +2 -2
- package/dist/configurator/pages/LoadedConfiguratorDetailPage.js +1 -1
- package/dist/configurator/pages/configurator-layout-name.d.ts +2 -0
- package/dist/configurator/pages/configurator-layout-name.js +1 -0
- package/dist/configurator/pages/default-configurator-elements.d.ts +7 -0
- package/dist/configurator/pages/default-configurator-elements.js +1 -0
- package/dist/configurator/pages/index.d.ts +1 -0
- package/dist/configurator/pages/index.js +1 -1
- package/dist/configurator/scene/scene-controls/hotspot-drag-handle/HotspotDragHandle.d.ts +1 -1
- package/dist/configurator/scene/scene-controls/hotspot-drag-handle/HotspotDragSceneHandle.d.ts +1 -1
- package/dist/configurator/scene/scene-entity/dimension-indicators/DimensionIndicator.d.ts +1 -1
- package/dist/configurator/scene/scene-entity/dimension-indicators/DimensionIndicatorInternal.d.ts +1 -1
- package/dist/configurator/scene/scene-entity/drag-and-drop/shared.d.ts +2 -2
- package/dist/configurator/scene/scene-entity/drag-and-drop/use-drag-object.d.ts +1 -1
- package/dist/configurator/scene/scene-entity/materials/RemoteReplacedMaterial.js +1 -1
- package/dist/configurator/scene/scene-entity/objects/SceneEntityObjectTextDecal.d.ts +1 -1
- package/dist/configurator/ui/assistant/AssistantChips.d.ts +8 -2
- package/dist/configurator/ui/assistant/AssistantChips.js +1 -1
- package/dist/configurator/ui/assistant/AssistantMarkdown.d.ts +1 -1
- package/dist/configurator/ui/assistant/AssistantMarkdown.js +1 -1
- package/dist/configurator/ui/assistant/AssistantThread.js +1 -1
- package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.d.ts +13 -0
- package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.js +1 -0
- package/dist/configurator/ui/assistant/entity-link/entity-link-selection.d.ts +22 -0
- package/dist/configurator/ui/assistant/entity-link/entity-link-selection.js +1 -0
- package/dist/configurator/ui/assistant/entity-link/entity-link-state.d.ts +27 -0
- package/dist/configurator/ui/assistant/entity-link/entity-link-state.js +1 -0
- package/dist/configurator/ui/assistant/entity-link/entity-link-target.d.ts +5 -0
- package/dist/configurator/ui/assistant/entity-link/entity-link-target.js +1 -0
- package/dist/configurator/ui/assistant/entity-link/index.d.ts +3 -0
- package/dist/configurator/ui/assistant/entity-link/index.js +1 -0
- package/dist/configurator/ui/configurator-layout/slots/services/InvariantViolations.d.ts +4 -4
- package/dist/configurator/ui/configurator-layout/slots/services/InvariantViolations.js +1 -1
- package/dist/configurator/ui/configurator-layout/slots/services/SideEffects.d.ts +3 -6
- package/dist/configurator/ui/configurator-layout/slots/services/SideEffects.js +1 -1
- package/dist/configurator/ui/legacy/layout/steps/StepsNavigation.d.ts +2 -2
- package/dist/configurator/ui/phoenix-layout-elements/header/common/step-navigation/StepsNavigation.d.ts +2 -2
- package/dist/docs/dimensions/3d-scene-integration/dimension-indicators.mdx +2 -2
- package/dist/docs/dimensions/3d-scene-integration/editable-angle-indicator.mdx +1 -1
- package/dist/docs/dimensions/3d-scene-integration/editable-distance-dimension-indicator.mdx +1 -1
- package/dist/docs/dimensions/3d-scene-integration/list-selector-dimension-indicator.mdx +1 -1
- package/dist/docs/drag-and-drop/drag-handle.mdx +1 -1
- package/dist/docs/drag-and-drop/hotspot-handle.mdx +1 -1
- package/dist/docs/drag-and-drop/planes.mdx +1 -1
- package/dist/docs/drag-and-drop/rotatable.mdx +2 -2
- package/dist/docs/index.json +11 -1
- package/dist/docs/layouts/custom-layout.mdx +1323 -179
- package/dist/docs/layouts/header/fixed.mdx +2 -2
- package/dist/docs/layouts/header/floating.mdx +2 -2
- package/dist/docs/layouts/sidebar/in-a-custom-layout.mdx +2 -2
- package/dist/docs/layouts/sidebar-footer/basic.mdx +32 -77
- package/dist/docs/other-features/client-side-rendering/declarative.mdx +1 -1
- package/dist/docs/phoenix/application-states.mdx +9 -7
- package/dist/docs/phoenix/configurator-interface.mdx +134 -18
- package/dist/docs/phoenix/finalization.mdx +1 -1
- package/dist/docs/phoenix/layout-slots.mdx +116 -0
- package/dist/docs/phoenix/migration-guide.mdx +19 -8
- package/dist/docs/phoenix/phoenix-cli.mdx +26 -8
- package/dist/docs/phoenix/project-structure.mdx +20 -5
- package/dist/docs/phoenix/sdk-builder-workflow.mdx +2 -2
- package/dist/docs/phoenix/webhooks.mdx +17 -0
- package/dist/domain/application/application-config.d.ts +3 -1
- package/dist/domain/application/assistant/generate-assistant-prompt.js +1 -1
- package/dist/domain/application/configurator-builder.d.ts +4 -1
- package/dist/domain/application/configurator-builder.js +1 -1
- package/dist/domain/core/invariant/violation.d.ts +50 -2
- package/dist/domain/core/invariant/violation.js +1 -1
- package/dist/domain/core/model/model.d.ts +1 -1
- package/dist/domain/domain-context/index.d.ts +1 -1
- package/dist/domain/domain-context/undo-system.d.ts +28 -1
- package/dist/domain/domain-context/undo-system.js +1 -1
- package/dist/domain/domain-runtime/spec/initialize.js +1 -1
- package/dist/domain/domain-runtime/spec/selectors.js +1 -1
- package/dist/domain/domain-runtime/spec/types.d.ts +2 -0
- package/dist/domain/extensions/attribute-switch.d.ts +1 -1
- package/dist/domain/extensions/attribute-switch.js +1 -1
- package/dist/domain/extensions/canvas-config.d.ts +1 -1
- package/dist/domain/extensions/client-side-image.d.ts +2 -2
- package/dist/domain/extensions/client-side-image.js +1 -1
- package/dist/domain/extensions/common/angle-indicator-schema.d.ts +2 -2
- package/dist/domain/extensions/common/dimension-indicator-schema.d.ts +2 -2
- package/dist/domain/extensions/editable-angle-indicator.d.ts +1 -1
- package/dist/domain/extensions/editable-distance-dimension-indicator.d.ts +1 -1
- package/dist/domain/extensions/editable-offset-indicator.d.ts +1 -1
- package/dist/domain/extensions/editable-offset-indicator.js +1 -1
- package/dist/domain/extensions/fit-selection-orthographic-camera-component.js +1 -1
- package/dist/domain/extensions/fit-selection-perspective-camera-component.js +1 -1
- package/dist/domain/extensions/horizontal-tabs.d.ts +2 -2
- package/dist/domain/extensions/list-selector-dimension-indicator.d.ts +1 -1
- package/dist/domain/extensions/navigation-steps.d.ts +2 -2
- package/dist/domain/extensions/offset-indicator.js +1 -1
- package/dist/domain/extensions/rotation-handle.d.ts +2 -2
- package/dist/domain/extensions/save-template-thumbnail.d.ts +2 -2
- package/dist/domain/extensions/save-template-thumbnail.js +1 -1
- package/dist/domain/extensions/scene-entity-animation.js +1 -1
- package/dist/domain/system-components/application-config.d.ts +2 -2
- package/dist/domain/system-components/child-entity-selection.js +1 -1
- package/dist/domain/system-components/collision-box-geometry.d.ts +4 -2
- package/dist/domain/system-components/collision-geometry.d.ts +4 -2
- package/dist/domain/system-components/collision-point-geometry.d.ts +4 -2
- package/dist/domain/system-components/common/material-override-schema.d.ts +2 -2
- package/dist/domain/system-components/common/recipes.d.ts +21 -3
- package/dist/domain/system-components/common/recipes.js +1 -1
- package/dist/domain/system-components/constraint.d.ts +10 -23
- package/dist/domain/system-components/drag-handle.d.ts +1 -1
- package/dist/domain/system-components/drag-handle.js +1 -1
- package/dist/domain/system-components/fit-entity-orthographic-camera-component.js +1 -1
- package/dist/domain/system-components/fit-entity-perspective-camera-component.js +1 -1
- package/dist/domain/system-components/fit-root-orthographic-camera-component.js +1 -1
- package/dist/domain/system-components/fit-root-perspective-camera-component.js +1 -1
- package/dist/domain/system-components/hotspot-drag-handle.d.ts +1 -1
- package/dist/domain/system-components/hotspot-drag-handle.js +1 -1
- package/dist/domain/system-components/material-swatch.js +1 -1
- package/dist/domain/system-components/scene-entity-material-override.d.ts +1 -1
- package/dist/domain/system-components/scene-entity-object-material-override.d.ts +1 -1
- package/dist/domain/system-components/scene-entity-object-text-decal.d.ts +1 -1
- package/dist/domain/system-components/scene-entity-object-transimissive-material-override.d.ts +1 -1
- package/dist/domain/system-components/scene-entity-transimissive-material-override.d.ts +1 -1
- package/dist/domain/system-components/static-orthographic-camera-component.js +1 -1
- package/dist/domain/system-components/static-perspective-camera-component.js +1 -1
- package/dist/i18n/locales/cs/messages.js +1 -1
- package/dist/i18n/locales/da/messages.js +1 -1
- package/dist/i18n/locales/de/messages.js +1 -1
- package/dist/i18n/locales/de-AT/messages.js +1 -1
- package/dist/i18n/locales/en/messages.js +1 -1
- package/dist/i18n/locales/en-AU/messages.js +1 -1
- package/dist/i18n/locales/en-GB/messages.js +1 -1
- package/dist/i18n/locales/es/messages.js +1 -1
- package/dist/i18n/locales/fr/messages.js +1 -1
- package/dist/i18n/locales/hu/messages.js +1 -1
- package/dist/i18n/locales/it/messages.js +1 -1
- package/dist/i18n/locales/nl/messages.js +1 -1
- package/dist/i18n/locales/pl/messages.js +1 -1
- package/dist/i18n/locales/pt/messages.js +1 -1
- package/dist/i18n/locales/ro/messages.js +1 -1
- package/dist/i18n/locales/sk/messages.js +1 -1
- package/dist/i18n/locales/tr/messages.js +1 -1
- package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
- package/dist/legacy/domain-cli/utils/cache.js +1 -1
- package/dist/legacy/domain-spec/__generated/domain-schema.d.ts +81 -68
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/claude-md.d.ts +1 -1
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/cursor-rules.d.ts +1 -1
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.d.ts +1 -1
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.js +7 -1
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-admin.js +18 -16
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-configurator.js +14 -12
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-admin.js +13 -11
- package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-configurator.js +13 -11
- package/dist/phoenix/application-spec/application-spec-builder.js +1 -1
- package/dist/phoenix/application-spec/project-files.js +1 -1
- package/dist/phoenix/commands/check.js +1 -1
- package/dist/phoenix/commands/deploy.js +1 -1
- package/dist/phoenix/commands/dev.js +5 -5
- package/dist/phoenix/commands/fix.js +1 -1
- package/dist/phoenix/services/application-spec-project-watcher.d.ts +2 -0
- package/dist/phoenix/services/application-spec-project-watcher.js +3 -3
- package/dist/phoenix/services/source-archive.d.ts +1 -0
- package/dist/phoenix/services/source-archive.js +1 -1
- package/dist/phoenix/services/swc.js +1 -1
- package/dist/react-sdk/domain-context/common-hooks/use-configurator-messages.d.ts +30 -0
- package/dist/react-sdk/domain-context/common-hooks/use-configurator-messages.js +1 -0
- package/dist/react-sdk/domain-context/index.d.ts +2 -1
- package/dist/react-sdk/domain-context/index.js +1 -1
- package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.d.ts +5 -0
- package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.js +1 -1
- package/dist/react-sdk/domain-controls/hooks/use-angle-dimension.d.ts +1 -1
- package/dist/ui-sdk/theme/types.d.ts +1 -1
- package/package.json +33 -29
- package/schema/domain-spec.json +1115 -209
- package/dist/application-spec/generate-application/code/templates/webhook-implementation.d.ts +0 -1
- package/dist/application-spec/generate-application/code/templates/webhook-implementation.js +0 -7
- /package/dist/application-spec/{core → enhanced-json}/eval-code-uses-self.d.ts +0 -0
- /package/dist/application-spec/{core → enhanced-json}/eval-code-uses-self.js +0 -0
- /package/dist/application-spec/{core → enhanced-json}/eval-to-constant.js +0 -0
|
@@ -145,7 +145,7 @@ interface HorizontalTab {
|
|
|
145
145
|
/**
|
|
146
146
|
* List of navigation states when the tab is active. First one will be used for activation.
|
|
147
147
|
*/
|
|
148
|
-
readonly navigationStates: string[]
|
|
148
|
+
readonly navigationStates: readonly string[]
|
|
149
149
|
}
|
|
150
150
|
```
|
|
151
151
|
|
|
@@ -158,7 +158,7 @@ type HorizontalTabsComponentState = {
|
|
|
158
158
|
/**
|
|
159
159
|
* List of tabs in the horizontal tabs.
|
|
160
160
|
*/
|
|
161
|
-
readonly tabs: HorizontalTab[]
|
|
161
|
+
readonly tabs: readonly HorizontalTab[]
|
|
162
162
|
}
|
|
163
163
|
```
|
|
164
164
|
|
|
@@ -110,11 +110,11 @@ The configuration uses these component types:
|
|
|
110
110
|
```typescript
|
|
111
111
|
export interface NavigationStep {
|
|
112
112
|
readonly label: Localizable
|
|
113
|
-
readonly navigationStates: string[]
|
|
113
|
+
readonly navigationStates: readonly string[]
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
export type NavigationStepsComponentState = {
|
|
117
|
-
readonly steps: NavigationStep[]
|
|
117
|
+
readonly steps: readonly NavigationStep[]
|
|
118
118
|
}
|
|
119
119
|
```
|
|
120
120
|
|
|
@@ -90,8 +90,8 @@ The spec is a table with one property, its edge finish, on a **Design** tab and
|
|
|
90
90
|
|
|
91
91
|
## Known gaps
|
|
92
92
|
|
|
93
|
-
- The finalize button is disabled unless the spec configures `finalizeButton` or `finalizePage
|
|
94
|
-
- `LayoutSlots.DesktopSidebar` is the desktop sidebar. At phone width a project layout needs its own arrangement, for example the `Mobile*` members of `LayoutSlots
|
|
93
|
+
- The footer is the basic sidebar footer, as in the built-in layout when the spec configures none. Its finalize button is disabled unless the spec configures the legacy `finalizeButton` or `finalizePage` components, which are declared only in TypeScript, and a project layout shows a `finalizePage` only if it renders it. New projects finalize over `finalizeAction` components, which the universal sidebar footer offers when the spec configures `universalSidebarFooter`.
|
|
94
|
+
- `LayoutSlots.DesktopSidebar` is the desktop sidebar. At phone width a project layout needs its own arrangement, for example the `Mobile*` members of `LayoutSlots`, listed in [Layout Slots](?path=/docs/phoenix-layout-slots--docs#phone-layout), in a drawer.
|
|
95
95
|
- The tabs overlap the scene beside the sidebar; the safe area in this example does not leave room for them.
|
|
96
96
|
- `miniSidebar` does not shrink the sidebar: the built-in layout does that, and here the sidebar fills its container. A layout that honours it reads `LayoutSlots.useSidebarContent().hasMiniSidebar` and gives the container no fixed height, anchored at the bottom for example, so the sidebar takes its content's height.
|
|
97
97
|
|
|
@@ -41,11 +41,11 @@ The basic sidebar footer adapts its layout based on what's available. The finali
|
|
|
41
41
|
|
|
42
42
|
For more control over the sidebar footer, see these related examples:
|
|
43
43
|
|
|
44
|
-
- **[Phoenix Handlers](
|
|
45
|
-
- **[Read Sidebar Footer](
|
|
46
|
-
- **[Universal Sidebar Footer](
|
|
47
|
-
- **[Custom Sidebar Footer](
|
|
48
|
-
- **[Hidden Sidebar Footer](
|
|
44
|
+
- **[Phoenix Handlers](?path=/docs/layouts-phoenix-handlers--docs)**: Learn how to create custom action handlers for sidebar footer buttons
|
|
45
|
+
- **[Read Sidebar Footer](?path=/docs/layouts-sidebar-footer-read--docs)**: Display price in read-only mode without action buttons
|
|
46
|
+
- **[Universal Sidebar Footer](?path=/docs/layouts-sidebar-footer-universal--docs)**: Add custom text and multiple action buttons while keeping the standard layout
|
|
47
|
+
- **[Custom Sidebar Footer](?path=/docs/layouts-sidebar-footer-custom--docs)**: Replace the sidebar footer with your own React components for complete control
|
|
48
|
+
- **[Hidden Sidebar Footer](?path=/docs/layouts-sidebar-footer-hidden--docs)**: Remove the sidebar footer entirely for embedded or immersive experiences
|
|
49
49
|
|
|
50
50
|
## Guide
|
|
51
51
|
|
|
@@ -98,84 +98,39 @@ This configuration gives you a fully functional sidebar footer with price displa
|
|
|
98
98
|
|
|
99
99
|
### Customizing finalize behavior
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
New projects finalize with `finalizeAction` components and the [Universal Sidebar Footer](?path=/docs/layouts-sidebar-footer-universal--docs), which runs the action's handler. The basic sidebar footer's own customization, the `finalizeButton` and `finalizePage` components, is legacy: the spec parser rejects both in YAML, so a project that keeps them declares them in TypeScript.
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
The basic sidebar footer checks for them in this order:
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
1. **finalizeButton**: if configured, its `button` React node is rendered instead of the finalize button, and implements the finalization and the disabled state itself
|
|
106
|
+
2. **finalizePage**: if no custom button exists, a default button navigates to the first of the component's `finalizeNavigationStates`, and the built-in layout shows its `page` in a dialog while one of those states is active
|
|
107
|
+
3. **No-op fallback**: if neither component is configured, a disabled button appears with the hint "Finalize feature is not configured"
|
|
106
108
|
|
|
107
|
-
|
|
108
|
-
components:
|
|
109
|
-
Scene:
|
|
110
|
-
finalizeButton:
|
|
111
|
-
customFinalize:
|
|
112
|
-
button: <CustomFinalizeButtonComponent />
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**TypeScript Interface**:
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
/**
|
|
119
|
-
* State for a custom finalize button component.
|
|
120
|
-
*/
|
|
121
|
-
interface FinalizeButtonComponentState {
|
|
122
|
-
/**
|
|
123
|
-
* Custom React node to render as the finalize button.
|
|
124
|
-
* This completely replaces the default finalize button.
|
|
125
|
-
*/
|
|
126
|
-
readonly button: ReactNode
|
|
127
|
-
}
|
|
128
|
-
```
|
|
109
|
+
A legacy `finalizePage` is attached in TypeScript, as the [Universal](?path=/docs/layouts-universal--docs) example does in `src/components/components.tsx`:
|
|
129
110
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
#### Using finalizePage component
|
|
133
|
-
|
|
134
|
-
The `finalizePage` component opens a modal page when the user clicks finalize. This is useful for multi-step checkout flows, order forms, or any scenario where you need to collect additional information before completing the order.
|
|
135
|
-
|
|
136
|
-
```yaml
|
|
137
|
-
components:
|
|
138
|
-
Scene:
|
|
139
|
-
finalizePage:
|
|
140
|
-
checkoutFlow:
|
|
141
|
-
finalizeNavigationStates: ['checkout', 'payment', 'confirmation']
|
|
142
|
-
page: <CheckoutFormComponent />
|
|
143
|
-
```
|
|
111
|
+
```tsx
|
|
112
|
+
import { finalizePageComponent, memoEval } from '@salsita-ai/sdk/domain'
|
|
144
113
|
|
|
145
|
-
|
|
114
|
+
// CheckoutPage is the project's own React component
|
|
115
|
+
import { CheckoutPage } from '../_shared/CheckoutPage.js'
|
|
146
116
|
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* State for a finalize page component that opens a modal.
|
|
150
|
-
*/
|
|
151
|
-
interface FinalizePageComponentState {
|
|
152
|
-
/**
|
|
153
|
-
* The navigation states that are active when finalization is in progress.
|
|
154
|
-
* The first state in this array is used for initial navigation when the
|
|
155
|
-
* finalize button is clicked.
|
|
156
|
-
*/
|
|
157
|
-
readonly finalizeNavigationStates: string[]
|
|
117
|
+
// `phx` is a global in an application project; a Storybook example imports it from '../../.phoenix/phx.js'
|
|
158
118
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
119
|
+
export default phx.domain.attachComponent
|
|
120
|
+
.withComponent(finalizePageComponent, 'default')
|
|
121
|
+
.withEntity('Scene')
|
|
122
|
+
.attach(
|
|
123
|
+
memoEval(
|
|
124
|
+
() => [],
|
|
125
|
+
() => ({
|
|
126
|
+
finalizeNavigationStates: [phx.applicationTypes.NavigationState.finalize],
|
|
127
|
+
page: <CheckoutPage />,
|
|
128
|
+
})
|
|
129
|
+
)
|
|
130
|
+
)
|
|
164
131
|
```
|
|
165
132
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
#### Priority and fallback behavior
|
|
169
|
-
|
|
170
|
-
The sidebar footer checks for finalize components in this order:
|
|
171
|
-
|
|
172
|
-
1. **finalizeButton**: If configured, this component is rendered as-is with no modifications
|
|
173
|
-
2. **finalizePage**: If no custom button exists, a default button is shown that opens the specified page
|
|
174
|
-
3. **No-op fallback**: If neither component is configured, a disabled button appears with the hint "Finalize feature is not configured"
|
|
175
|
-
|
|
176
|
-
This priority system lets you customize either the button appearance or the finalization flow, but not both simultaneously. If you need both, use `finalizeButton` and implement the page navigation logic within your custom component.
|
|
177
|
-
|
|
178
|
-
See the [Finalize Page Layout](../?path=/docs/layouts-simple-layout-finalize-page) example for a complete implementation of the finalize page pattern.
|
|
133
|
+
The states in `finalizeNavigationStates` must be listed in the spec's `navigationStates`. The universal sidebar footer never opens a `finalizePage`.
|
|
179
134
|
|
|
180
135
|
### Navigation steps influence
|
|
181
136
|
|
|
@@ -278,7 +233,7 @@ Use `simpleSummary` for basic summaries that just need to display a list of conf
|
|
|
278
233
|
|
|
279
234
|
Both component types require a `summaryNavigationState` that must exist in your navigation configuration. The sidebar footer checks the current navigation state against this property to determine whether the summary is currently active.
|
|
280
235
|
|
|
281
|
-
See the [Summary
|
|
236
|
+
See the [Sidebar Summary](?path=/docs/layouts-sidebar-summary--docs) example for a complete summary implementation.
|
|
282
237
|
|
|
283
238
|
### Custom price sidebar footer
|
|
284
239
|
|
|
@@ -317,11 +272,11 @@ When `customPriceSidebarFooter` is configured:
|
|
|
317
272
|
- The sidebar footer layout remains unchanged - only the price display is replaced
|
|
318
273
|
- Action buttons (finalize, next/previous, etc.) are not affected
|
|
319
274
|
|
|
320
|
-
This component affects **only** the price display, not the overall sidebar footer structure. If you need to change the entire sidebar footer layout, use the [Universal Sidebar Footer](
|
|
275
|
+
This component affects **only** the price display, not the overall sidebar footer structure. If you need to change the entire sidebar footer layout, use the [Universal Sidebar Footer](?path=/docs/layouts-sidebar-footer-universal--docs) or [Custom Sidebar Footer](?path=/docs/layouts-sidebar-footer-custom--docs) instead.
|
|
321
276
|
|
|
322
277
|
The custom price node receives no special props. You must access price data yourself through the configurator hooks like `useRootEntityPrice()` or by reading entity attributes directly.
|
|
323
278
|
|
|
324
|
-
See the [Custom Price Sidebar Footer](
|
|
279
|
+
See the [Custom Price Sidebar Footer](?path=/docs/layouts-custom-price--docs) example for implementation details and best practices.
|
|
325
280
|
|
|
326
281
|
## Example
|
|
327
282
|
|
|
@@ -229,7 +229,7 @@ export type ClientSideImageComponentState = {
|
|
|
229
229
|
/** Output format: PNG (with transparency) or JPEG */
|
|
230
230
|
readonly fileFormat: 'PNG' | 'JPEG'
|
|
231
231
|
/** Optional background color (hex string) */
|
|
232
|
-
readonly backgroundColor?:
|
|
232
|
+
readonly backgroundColor?: HexColor
|
|
233
233
|
|
|
234
234
|
/** Tool state the image is rendered in (pins component filters keyed on tool state) */
|
|
235
235
|
readonly toolState: string
|
|
@@ -223,22 +223,24 @@ components:
|
|
|
223
223
|
|
|
224
224
|
staticPerspectiveCamera:
|
|
225
225
|
overview:
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
distance: 14
|
|
227
|
+
polarAngle: 0.8
|
|
228
|
+
azimuthAngle: 0
|
|
228
229
|
$filter:
|
|
229
230
|
viewStates: ['overview']
|
|
230
231
|
|
|
231
232
|
detail:
|
|
232
|
-
|
|
233
|
-
|
|
233
|
+
distance: 3.5
|
|
234
|
+
polarAngle: 0.95
|
|
235
|
+
azimuthAngle: 0.8
|
|
234
236
|
$filter:
|
|
235
237
|
viewStates: ['closeup']
|
|
236
238
|
|
|
237
239
|
staticOrthographicCamera:
|
|
238
240
|
blueprint:
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
241
|
+
distance: 20
|
|
242
|
+
polarAngle: 0
|
|
243
|
+
frustumSize: 12
|
|
242
244
|
$filter:
|
|
243
245
|
viewStates: ['blueprint']
|
|
244
246
|
|
|
@@ -158,30 +158,35 @@ const viewState = phx.frontend.useActiveViewState()
|
|
|
158
158
|
const toolState = phx.frontend.useActiveToolState()
|
|
159
159
|
|
|
160
160
|
// Navigation actions
|
|
161
|
-
const navigate = phx.frontend.useNavigate()
|
|
162
|
-
const pushNavigate = phx.frontend.usePushNavigate()
|
|
163
|
-
const popNavigate = phx.frontend.usePopNavigate()
|
|
161
|
+
const navigate = phx.frontend.useNavigate() // navigate(state) replaces the active state and clears the history
|
|
162
|
+
const pushNavigate = phx.frontend.usePushNavigate() // pushNavigate(state) remembers the active state for popNavigate
|
|
163
|
+
const popNavigate = phx.frontend.usePopNavigate() // popNavigate() returns to the remembered state, if there is one
|
|
164
164
|
|
|
165
165
|
// Fullscreen: a flag in the configurator's state that the layout honours; it does not put the browser into fullscreen
|
|
166
166
|
const isFullscreen = phx.frontend.useIsFullscreenActive()
|
|
167
167
|
const setFullscreen = phx.frontend.useSetFullscreen() // setFullscreen(true) or setFullscreen(false)
|
|
168
|
+
|
|
169
|
+
// View state and camera
|
|
170
|
+
const setViewState = phx.frontend.useSetViewState() // setViewState(state) makes one of the spec's viewStates active
|
|
171
|
+
const resetCamera = phx.frontend.useResetCamera() // resetCamera() undoes the user's orbit, pan and zoom
|
|
168
172
|
```
|
|
169
173
|
|
|
170
174
|
### Controls
|
|
171
175
|
|
|
172
176
|
```typescript
|
|
173
|
-
// Control hooks for UI inputs
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
const
|
|
177
|
+
// Control hooks for UI inputs: the entity id and the instance name of the control component on it
|
|
178
|
+
// useSwatchSelection requires its third argument, the fixable violation types
|
|
179
|
+
const swatchSelection = phx.frontend.useSwatchSelection(entityId, instanceName, [])
|
|
180
|
+
const textValue = phx.frontend.useTextValue(entityId, instanceName)
|
|
181
|
+
const attributeSelection = phx.frontend.useAttributeSelection(entityId, instanceName)
|
|
182
|
+
const attributeSwitch = phx.frontend.useAttributeSwitch(entityId, instanceName)
|
|
183
|
+
const distanceDimension = phx.frontend.useDistanceDimension(entityId, instanceName)
|
|
184
|
+
const angleDimension = phx.frontend.useAngleDimension(entityId, instanceName)
|
|
185
|
+
const genericDimension = phx.frontend.useGenericDimension(entityId, instanceName)
|
|
181
186
|
|
|
182
187
|
// Update control
|
|
183
188
|
const updateControl = phx.frontend.useUpdateControl()
|
|
184
|
-
const updatedControl = phx.frontend.useUpdatedControl(
|
|
189
|
+
const updatedControl = phx.frontend.useUpdatedControl(updates)
|
|
185
190
|
```
|
|
186
191
|
|
|
187
192
|
### Recipes & Entity Creation
|
|
@@ -207,15 +212,19 @@ const deletedEntity = phx.frontend.useDeletedEntity()
|
|
|
207
212
|
### Validation & Violations
|
|
208
213
|
|
|
209
214
|
```typescript
|
|
210
|
-
//
|
|
215
|
+
// Validity of the last committed state; a rejected change never becomes committed, so it is not seen here
|
|
211
216
|
const validity = phx.frontend.useStateValidity()
|
|
212
217
|
|
|
213
|
-
// Control violations
|
|
214
|
-
|
|
218
|
+
// Control violations: takes the violation types to ignore and returns a function that maps a prepared
|
|
219
|
+
// state emission to { disabled, hints, violations }
|
|
220
|
+
const controlViolations = phx.frontend.useControlViolations([])
|
|
215
221
|
|
|
216
222
|
// Finalize violations
|
|
217
223
|
const { disabled, hints } = phx.frontend.useFinalizeViolations()
|
|
218
224
|
|
|
225
|
+
// Messages for the user: violations of a rejected change, side-effect hints and errors, one call each
|
|
226
|
+
phx.frontend.useConfiguratorMessages(message => showToast(message.text))
|
|
227
|
+
|
|
219
228
|
// Map violations to hints
|
|
220
229
|
const mapViolationHints = phx.frontend.useMapViolationHints()
|
|
221
230
|
```
|
|
@@ -420,12 +429,119 @@ export default phx.frontend.createCustomPhoenixLayoutElement('ConfiguratorLayout
|
|
|
420
429
|
- `LayoutSlots.SharedCanvas` renders the scene. It is absolutely positioned and fills its nearest positioned ancestor, so the layout's root is positioned and covers the page. The layout positions its own UI above the canvas and after it in the markup, as the `aside` does; unpositioned content is painted under the canvas.
|
|
421
430
|
- `useSceneSafeArea()`, called without arguments, tells the camera which part of the canvas the UI leaves free. Attach `containerRef` to the element that covers the whole canvas and `safeAreaRef` to the region the scene should stay visible in: the hook measures the gap between the two and the camera frames the scene inside the safe area. Without it the scene is framed in the whole canvas. The safe-area element lies over the canvas, so it sets `pointerEvents: 'none'` to leave orbiting and clicking to the scene. A `canvasPadding` component in the spec scales the measured gaps, see [Canvas Padding](?path=/docs/layouts-canvas-padding--docs).
|
|
422
431
|
- The layout has to mount `LayoutSlots.SharedCanvas`, or the project sets `appLoader: legacy`. Otherwise the app loader stays on screen.
|
|
423
|
-
- The layout composes the rest from what `@salsita-ai/sdk/configurator` exports: `LayoutSlots.Services` and the other members of `LayoutSlots
|
|
432
|
+
- The layout composes the rest from what `@salsita-ai/sdk/configurator` exports: `LayoutSlots.Services` and the other members of `LayoutSlots`, which [Layout Slots](?path=/docs/phoenix-layout-slots--docs) lists with what each shows, what feeds it, what it renders when the spec configures nothing for it and what it does in read mode.
|
|
424
433
|
- `LayoutSlots.DesktopSidebar` is the built-in desktop sidebar as one piece: the spec's tabs, back button, property pages and sidebar footer with their spacing, scrolling and empty states, and the assistant panel. Use it when the spec's property pages are what the customer should see and only their place changes, for example a sidebar on the left; build the controls yourself when they have to look like the brand's own. Without `width` it fills its container, so the layout positions and sizes that container; `miniSidebar` does not shrink it, so a layout that honours it reads `LayoutSlots.useSidebarContent().hasMiniSidebar` and lets the container take the sidebar's height. Its tabs sit outside it on the left; `side="start"` puts them on its right, for a sidebar on the left. In fullscreen it stays in place, transparent and inert, so a layout that wants the space back removes it while `phx.frontend.useIsFullscreenActive()` is set. See [Sidebar in a Custom Layout](?path=/docs/layouts-sidebar-in-a-custom-layout--docs).
|
|
425
|
-
- Nothing of the built-in layouts is rendered for it.
|
|
426
|
-
- The layout reads the state it has to react to from hooks
|
|
434
|
+
- Nothing of the built-in layouts is rendered for it. A project layout finalizes over the spec's `finalizeAction` components, see the finalize paragraph of [Hooks for a Project Layout](#hooks-for-a-project-layout). The `finalizePage` and `finalizeButton` components are legacy: they cannot be declared in YAML, only in TypeScript, and `Legacy.CommonFinalizePage`, which is deprecated, shows a `finalizePage` for projects that still have one. `LayoutDialog` renders only what the project registers with `createLayoutDialog` and is not part of the finalize flow. The preview start screen is `DesktopPreview` or `MobilePreview`, which the layout shows while `usePreview().isPreview` is set. Both previews frame the scene themselves, so the layout renders the component that calls `useSceneSafeArea()` only while `isPreview` is not set; it then measures when it mounts after the preview. The assistant panel is available to a project layout only inside `LayoutSlots.DesktopSidebar`.
|
|
435
|
+
- The layout reads the state it has to react to from hooks, listed with what each returns in [Hooks for a Project Layout](#hooks-for-a-project-layout).
|
|
436
|
+
- Messages for the user come one of two ways. `LayoutSlots.Services` shows violations of a rejected change, side-effect hints and errors as the built-in snackbars, which render into `LayoutSlots.DesktopSnackbarsRoot` or `LayoutSlots.MobileSnackbarsRoot` wherever the layout mounts it. `phx.frontend.useConfiguratorMessages(onMessage)` hands the same messages to the layout's own UI instead, with their text resolved, as the toast in [Custom Layout](?path=/docs/layouts-custom-layout--docs#show-messages) does; mount one of the two, not both, or every message is shown twice. Some messages stay snackbars either way: a failure to save the configuration and an error of the built-in finalize and other actions. They render into the snackbar root, so a layout that mounts none shows them outside the configurator, in the page's `body`. An error while a preset is applied appears on the preset screen, outside the layout. A finalize action the layout runs with `phx.frontend.useFinalizeAction` reports its error as that hook's `error` instead, neither as a message nor as a snackbar.
|
|
427
437
|
- Any project layout element named `ConfiguratorLayout` takes over the page.
|
|
428
438
|
|
|
439
|
+
`defaultConfiguratorElements`, exported from `@salsita-ai/sdk/configurator`, holds the built-in UI as a `ConfiguratorLayout` registration that renders the layout the spec selects. Generated code registers these defaults with `withDefaultElements`, apart from the project's elements, so the built-in UI is a registration like any other; a project element registered under the same name wins over a default.
|
|
440
|
+
|
|
441
|
+
#### Hooks for a Project Layout
|
|
442
|
+
|
|
443
|
+
A project layout reads the product and the configurator's state through hooks, and changes them through the functions the hooks return. Each row names where its hook comes from; the `phx.frontend` hooks in these tables are also exported from `@salsita-ai/sdk/react` under the same name. No hook looks at read mode: the control hooks and the navigation and fullscreen setters keep working while `accessInfo.viewMode` is `true`, so the layout decides what a viewer can change.
|
|
444
|
+
|
|
445
|
+
**The product**
|
|
446
|
+
|
|
447
|
+
| Hook | Returns |
|
|
448
|
+
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
449
|
+
| `phx.frontend.useRootEntityId()` | The id of the root entity, which the control hooks take. |
|
|
450
|
+
| `phx.frontend.useSelectedDomainEntityId()` | The id of the selected entity, or the root entity's id while nothing is selected. |
|
|
451
|
+
| `phx.frontend.useFirstRootComponent(componentType)` | The first component of that type on the root entity as `{ componentInstance, state }`, or `null` without one. It takes a component type such as `detailComponent` from `@salsita-ai/sdk/domain`, or an array of them. The `detail` component's `state` is `{ title, subtitle, description, thumbnailUrl? }`, all `Localizable`. |
|
|
452
|
+
| `phx.frontend.useComponents({ componentTypes, entityIds?, instanceNames? })` | Every matching component on any entity, as `{ componentInstance, state }[]`. Its type on `phx.frontend` includes `null`, but it returns an empty array when nothing matches. |
|
|
453
|
+
| `phx.frontend.useRootEntityPrice()` and `phx.frontend.useEntityPrice(entityId)` | The value of the entity's `price` component formatted as currency for the current locale, in the component's `currency` or `USD`, or `null` without a `price` component. |
|
|
454
|
+
|
|
455
|
+
**Controls**
|
|
456
|
+
|
|
457
|
+
| Hook | Returns |
|
|
458
|
+
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
459
|
+
| `phx.frontend.useAttributeSelection(entityId, instanceName)` | `{ value, options }`. Each option has `title` and `description` (`Localizable`, the spec's `label` and `description`), `value`, `imageSrc` (the spec's `img`), `disabled`, `error`, `hint` (a `string` saying why it is disabled, or `undefined`) and `onSelect()`, which writes the option; the selected option's `onSelect` does nothing. It throws when the entity has no `attributeSelection` component named `instanceName`. |
|
|
460
|
+
| `phx.frontend.useAttributeSwitch(entityId, instanceName)` | `{ state, onChange, disabled, error, hint }`: `state.value` is the boolean and `onChange()` writes its opposite. It throws without the component. |
|
|
461
|
+
|
|
462
|
+
The other control hooks in [Controls](#controls) take the same two arguments, `useSwatchSelection` a required third. `useSwatchSelection` returns `{ value, options }`, where `value` is the selected swatch key and each option is `{ swatchName, onClick, swatchKey, selected, thumbnailUrl, disabled, color, hint?, trace? }`; `useTextValue` and the dimension hooks return `{ value, hints, hasErrors, update, resolve, trace }` instead, where `update(value)` stages a value the scene shows at once (`useTextValue`'s is an `onChange` handler, `update(event, value)`) and `resolve()` commits it, or rolls it back when it breaks an invariant. Their TypeScript types give the exact shapes, and [Custom Controls](?path=/docs/controls-custom--docs) lists them.
|
|
463
|
+
|
|
464
|
+
**Texts**
|
|
465
|
+
|
|
466
|
+
Texts from the spec, such as option titles and the `detail` fields, are `Localizable`, not `string`. `useResolveLocalizable()` from `@salsita-ai/sdk/react` returns a function that turns one into a string in the current language, which suits a list; `useLocalizable(text)` and `<LocalizableMessage>` resolve a single text, see [Localization](?path=/docs/phoenix-localization--docs).
|
|
467
|
+
|
|
468
|
+
**Mode, fullscreen, preview and navigation**
|
|
469
|
+
|
|
470
|
+
| Hook | Returns |
|
|
471
|
+
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
472
|
+
| `phx.frontend.useAccessService()` | `{ configurationId, accessInfo }`. `accessInfo.viewMode` is `true` while a configuration shared for viewing is open, and also while the host sets the `readonly` property. |
|
|
473
|
+
| `phx.frontend.useIsFullscreenActive()` and `phx.frontend.useSetFullscreen()` | The fullscreen flag, a `boolean`, and a function `(enabled: boolean) => void` that sets it. |
|
|
474
|
+
| `usePreview()` from `@salsita-ai/sdk/configurator` | `{ isPreview, isExpanded, isPreviewEnabled, isHidden, enter, leave }`. The layout shows a preview start screen while `isPreview` is `true`. |
|
|
475
|
+
| `phx.frontend.useActiveNavigationState()` | The active navigation state, one of the spec's `navigationStates`. |
|
|
476
|
+
| `phx.frontend.usePushNavigate()` and `phx.frontend.usePopNavigate()` | `(state) => void`, which enters a state and remembers the active one, and `() => void`, which returns to the remembered state and does nothing when there is none. `phx.frontend.useNavigate()` returns `(state) => void`, which enters a state and forgets the history. |
|
|
477
|
+
| `phx.frontend.useActiveViewState()` and `phx.frontend.useActiveToolState()` | The active view state and tool state. |
|
|
478
|
+
| `phx.frontend.useSetViewState()` | `(state) => void`, which makes the given view state, one of the spec's `viewStates`, the active one; setting the active state again keeps it. Cameras and components filtered by `viewStates` follow the change. |
|
|
479
|
+
| `phx.frontend.useResetCamera()` | `() => void`, which moves the camera back to the framing of the active camera configuration, undoing the user's orbit, pan and zoom, as the toolbar's reset button does. Besides `phx.frontend`, `@salsita-ai/sdk/configurator` exports it, not `@salsita-ai/sdk/react`. |
|
|
480
|
+
| `useActiveViewports()` from `@salsita-ai/sdk/react` | The responsive breakpoints the configurator's container satisfies, as `Viewport[]`, or `null` before it is measured. It follows the container, not the window, so it is the switch between a desktop and a phone layout. `desktop` is a container wider than 768 pixels and `mobile` one at most 768 pixels wide; `phone` is narrower than 480 and `tablet` between 480 and 1024 pixels; `landscape` and `portrait` follow the browser window's orientation. The built-in layout uses its phone arrangement unless `desktop` is active. |
|
|
481
|
+
|
|
482
|
+
**Violations**
|
|
483
|
+
|
|
484
|
+
| Hook | Returns |
|
|
485
|
+
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
486
|
+
| `phx.frontend.useStateValidity()` | The validity of the last committed state: `{ valid: true, severity: null }`, or `{ valid: true, severity: 'notice' \| 'warning', entityViolations }`. A change that leaves a `fixable` or `fatal` violation is rejected and never committed, and neither is a change during which an error was thrown, so neither is seen here. |
|
|
487
|
+
| `phx.frontend.useFinalizeViolations()` | `{ disabled, hints, violations }`. `disabled` is `true` while a `warning`, `fixable` or `fatal` violation holds or the configuration failed to save; `hints` is the violations' text, or `undefined`. |
|
|
488
|
+
| `phx.frontend.useConfiguratorMessages(onMessage)` | Nothing. It calls `onMessage(message)` once per message: `{ kind: 'violation', entityId, violation, text }` for each violation of the rejected state, including notices and warnings already present, so `violation.severity` tells the reason for the rejection (`fixable` or `fatal`) from them, `{ kind: 'sideEffect', text }` for each hint of a committed update, and `{ kind: 'error', error, text }` when an error is thrown while a change is validated, with `text` the generic "Oops, something went wrong". `text` is resolved to the current language; a violation's is its `message`, or its `type` without one, and the built-in snackbar prefixes it with `entityId`. Hints committed before the layout mounted are not delivered; when the most recent change was rejected or threw, its messages are delivered again when the hook mounts. `onMessage` may be a new function on every render. On `phx.frontend` the message is typed by the project, so `violation.type` narrows to its violation types; from `@salsita-ai/sdk/react` the type is `ConfiguratorMessage`. |
|
|
489
|
+
| `phx.frontend.useFinalizeAction(handler)` | `{ run, isPending, error, disabled, hints }` for the `finalizeAction` whose `handler` it is given; see the Finalize paragraph below for how to call it. `run()` records the finalize-button click for analytics and runs the project's handler, and does nothing while `disabled` or `isPending`; `error` is what the handler's last run rejected with, or `null`; `disabled` and `hints` are those of `useFinalizeViolations()`. The type of the result is `UseFinalizeActionResult` from `@salsita-ai/sdk/configurator`, which also exports the hook. |
|
|
490
|
+
|
|
491
|
+
`LayoutSlots.Services` shows the messages of `useConfiguratorMessages` as snackbars; see the messages paragraph of [Loaded Configuration UI](#loaded-configuration-ui) for choosing between the two and for the messages that stay snackbars.
|
|
492
|
+
|
|
493
|
+
**Finalize**
|
|
494
|
+
|
|
495
|
+
A project layout finalizes over the spec's `finalizeAction` components. `phx.frontend.useComponents({ componentTypes: [finalizeActionComponent] })`, with `finalizeActionComponent` from `@salsita-ai/sdk/domain`, lists them; each `state` is `{ variant, label, title, icon, handler }`, where `variant` is `'primary'` or `'secondary'` and `handler` names the project's handler registered with `phx.frontend.createPhoenixHandler`. The built-in footer offers the first `'primary'` action, or else the first action, as its button and the others in a menu; a project layout follows the same rule when it offers one action.
|
|
496
|
+
|
|
497
|
+
Each action gets a component of its own that calls `phx.frontend.useFinalizeAction(action.state.handler)` once, never in a loop or conditionally, because the hook runs the project's handler factory, which calls hooks. The layout wraps that component in `<PhoenixHandlerBoundary name={action.state.handler}>` from `@salsita-ai/sdk/react`, so an edited handler takes effect without a reload. The hook returns:
|
|
498
|
+
|
|
499
|
+
- `run()`, which records the finalize-button click for analytics and then runs the handler. It does nothing while `disabled` or `isPending`.
|
|
500
|
+
- `isPending`, `true` while the handler runs.
|
|
501
|
+
- `error`, what the handler's last run rejected with, or `null`; a rejection that is not an `Error` is wrapped in one, with the value as its `cause`. It is cleared when the action runs again. No snackbar is raised; the layout shows the error its own way.
|
|
502
|
+
- `disabled` and `hints`, those of `useFinalizeViolations()`: finalizing is not possible while a `warning`, `fixable` or `fatal` violation holds or the configuration failed to save, and `hints` says why.
|
|
503
|
+
|
|
504
|
+
`isPending` and `error` belong to the mounted component: when it unmounts during a run, the handler keeps running, and a component mounted afterwards starts with `isPending` false and no `error`.
|
|
505
|
+
|
|
506
|
+
```tsx
|
|
507
|
+
import { finalizeActionComponent } from '@salsita-ai/sdk/domain'
|
|
508
|
+
import { PhoenixHandlerBoundary, useResolveLocalizable } from '@salsita-ai/sdk/react'
|
|
509
|
+
|
|
510
|
+
const FinalizeButton = ({ handler, label }: { handler: string; label: string }) => {
|
|
511
|
+
const { run, isPending, error, disabled, hints } = phx.frontend.useFinalizeAction(handler)
|
|
512
|
+
|
|
513
|
+
return (
|
|
514
|
+
<div>
|
|
515
|
+
<button type="button" disabled={disabled || isPending} onClick={run} title={hints}>
|
|
516
|
+
{isPending ? 'Sending…' : label}
|
|
517
|
+
</button>
|
|
518
|
+
{error && <p role="alert">{error.message}</p>}
|
|
519
|
+
</div>
|
|
520
|
+
)
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export const Finalize = () => {
|
|
524
|
+
const { accessInfo } = phx.frontend.useAccessService()
|
|
525
|
+
const resolve = useResolveLocalizable()
|
|
526
|
+
const actions = phx.frontend.useComponents({ componentTypes: [finalizeActionComponent] }) ?? []
|
|
527
|
+
const primary = actions.find(action => action.state.variant === 'primary') ?? actions[0]
|
|
528
|
+
|
|
529
|
+
if (accessInfo.viewMode || !primary) {
|
|
530
|
+
return null
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return (
|
|
534
|
+
<PhoenixHandlerBoundary name={primary.state.handler}>
|
|
535
|
+
<FinalizeButton handler={primary.state.handler} label={resolve(primary.state.label)} />
|
|
536
|
+
</PhoenixHandlerBoundary>
|
|
537
|
+
)
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
The hook does not check read mode, so the layout hides finalizing while `accessInfo.viewMode` is `true`, as above. [Custom Layout](?path=/docs/layouts-custom-layout--docs#request-a-quote) runs a finalize action this way from its review step.
|
|
542
|
+
|
|
543
|
+
Instead of its own buttons, a project layout can mount `<FinalizeActions />` from `@salsita-ai/sdk/configurator`: the built-in footer's finalize buttons, the primary action plus a menu of the others, disabled with the hints of `useFinalizeViolations()`, with a spinner while the handler runs and a snackbar when it fails. It renders nothing without a `finalizeAction`, and it does not check read mode either.
|
|
544
|
+
|
|
429
545
|
## TransformerBuilder
|
|
430
546
|
|
|
431
547
|
Use `transformerBuilder` to create entity transformers:
|
|
@@ -15,7 +15,7 @@ Finalization is Phoenix's system for completing configurator sessions and proces
|
|
|
15
15
|
|
|
16
16
|
> For integration-specific finalization flows — how host-specific data is passed in and how the host is notified on completion (event dispatch in `headless`, redirect in `handoff`) — see [Finalization (Internal)](?path=/docs/phoenix-integration-finalization-internal--docs) and [Finalization (External)](?path=/docs/phoenix-integration-finalization-external--docs).
|
|
17
17
|
|
|
18
|
-
Phoenix selects one primary footer action and places additional finalization actions in its menu.
|
|
18
|
+
The universal sidebar footer offers the spec's `finalizeAction` components: Phoenix selects one primary footer action and places additional finalization actions in its menu. It never opens a `finalizePage`; the `finalizePage` and `finalizeButton` components are legacy, declared only in TypeScript, and used by the basic sidebar footer and the legacy layouts. Built-in finalization actions use configuration validity to disable the footer action and provide pending and generic error states, including for add-to-cart handlers. See [Universal Sidebar Footer](?path=/docs/layouts-sidebar-footer-universal--docs) for the layout behavior. A project layout (`ConfiguratorLayout`) offers the same actions with its own buttons through `phx.frontend.useFinalizeAction`, which runs an action's handler and returns its pending state, its error and the disabled state with hints; see the Finalize paragraph of [Configurator Interface → Hooks for a Project Layout](?path=/docs/phoenix-configurator-interface--docs#hooks-for-a-project-layout).
|
|
19
19
|
|
|
20
20
|
## How Finalization Works
|
|
21
21
|
|