@salsita-ai/sdk 0.50.0-develop.fbe43b9a2d → 0.50.0-develop.fda84314a5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/dist/application/index.d.ts +1 -0
  2. package/dist/application/index.js +1 -1
  3. package/dist/application/mount-application.d.ts +1 -1
  4. package/dist/application/mount-application.js +1 -1
  5. package/dist/application/mount-configurator.d.ts +19 -0
  6. package/dist/application/mount-configurator.js +1 -0
  7. package/dist/application/mounted-application-runtime.d.ts +4 -0
  8. package/dist/application/mounted-application-runtime.js +1 -0
  9. package/dist/application/register-web-component.d.ts +2 -0
  10. package/dist/application/register-web-component.js +1 -0
  11. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +11 -5
  12. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +1 -1
  13. package/dist/application-spec/generate-application/implementations/phx-application-types.d.ts +25 -0
  14. package/dist/application-spec/generate-application/implementations/phx-application-types.js +1 -0
  15. package/dist/application-spec/generate-application/implementations/phx-domain.d.ts +36 -0
  16. package/dist/application-spec/generate-application/implementations/phx-domain.js +1 -0
  17. package/dist/application-spec/generate-application/implementations/phx-model.d.ts +24 -0
  18. package/dist/application-spec/generate-application/implementations/phx-model.js +1 -0
  19. package/dist/application-spec/generate-application/implementations/phx.d.ts +22 -0
  20. package/dist/application-spec/generate-application/implementations/phx.js +1 -0
  21. package/dist/application-spec/generate-application/index.d.ts +2 -0
  22. package/dist/application-spec/generate-application/index.js +1 -1
  23. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-model-runtime.d.ts +3 -3
  24. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.d.ts +7 -4
  25. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.js +1 -1
  26. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-spec-runtime.d.ts +16 -0
  27. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-spec-runtime.js +1 -0
  28. package/dist/application-spec/generate-application/runtime/application-runtime.d.ts +17 -4
  29. package/dist/application-spec/generate-application/runtime/application-runtime.js +1 -1
  30. package/dist/application-spec/generate-application/runtime/application-spec-slice.d.ts +71 -0
  31. package/dist/application-spec/generate-application/runtime/application-spec-slice.js +1 -0
  32. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-model-runtime.d.ts +3 -3
  33. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.d.ts +7 -5
  34. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.js +1 -1
  35. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-spec-runtime.d.ts +16 -0
  36. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-spec-runtime.js +1 -0
  37. package/dist/application-spec/generate-application/runtime/create-application.d.ts +57 -0
  38. package/dist/application-spec/generate-application/runtime/create-application.js +1 -0
  39. package/dist/application-spec/generate-application/runtime/index.d.ts +8 -0
  40. package/dist/application-spec/generate-application/runtime/index.js +1 -0
  41. package/dist/application-spec/generate-application/runtime/sections/expression-runtime.d.ts +9 -3
  42. package/dist/application-spec/generate-application/runtime/sections/expression-runtime.js +1 -1
  43. package/dist/application-spec/generate-application/runtime/spec-runtime.d.ts +21 -0
  44. package/dist/application-spec/generate-application/runtime/spec-runtime.js +1 -0
  45. package/dist/application-spec/generate-application/runtime-spec/encoded-runtime-spec.d.ts +3 -2
  46. package/dist/application-spec/generate-application/runtime-spec/runtime-spec.d.ts +44 -9
  47. package/dist/application-spec/generate-application/runtime-spec/runtime-spec.js +1 -1
  48. package/dist/client/authorized-client.d.ts +3 -1
  49. package/dist/client/authorized-client.js +1 -1
  50. package/dist/client/contract.d.ts +17 -0
  51. package/dist/client/index.d.ts +1 -1
  52. package/dist/client/local-authorized-client.d.ts +3 -1
  53. package/dist/client/local-authorized-client.js +1 -1
  54. package/dist/client/memory-authorized-client.d.ts +4 -1
  55. package/dist/client/memory-authorized-client.js +1 -1
  56. package/dist/client/phoenix-api.d.ts +228 -0
  57. package/dist/configurator/ConfiguratorApp.js +1 -1
  58. package/dist/configurator/app-loader-content/index.d.ts +0 -1
  59. package/dist/configurator/app-loader-content/index.js +1 -1
  60. package/dist/configurator/application-runtime/extensions/selectors.js +1 -1
  61. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +17 -3
  62. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
  63. package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts +23 -6
  64. package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.js +1 -1
  65. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +15 -9
  66. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
  67. package/dist/configurator/common/configurator-interface.d.ts +8 -5
  68. package/dist/configurator/common/configurator-interface.js +1 -1
  69. package/dist/configurator/configuration-not-found-page/BuiltInConfigurationNotFoundPage.d.ts +5 -0
  70. package/dist/configurator/configuration-not-found-page/BuiltInConfigurationNotFoundPage.js +1 -0
  71. package/dist/configurator/configuration-not-found-page/ConfigurationNotFoundPageElement.d.ts +0 -6
  72. package/dist/configurator/configuration-not-found-page/ConfigurationNotFoundPageElement.js +1 -1
  73. package/dist/configurator/configuration-not-found-page/index.d.ts +2 -2
  74. package/dist/configurator/configuration-not-found-page/index.js +1 -1
  75. package/dist/configurator/configurator-context/ConfiguratorResponsiveProvider.d.ts +3 -3
  76. package/dist/configurator/configurator-context/ConfiguratorResponsiveProvider.js +1 -1
  77. package/dist/configurator/configurator-context/PreviewContextProvider.js +1 -1
  78. package/dist/configurator/configurator-error-page/BuiltInConfiguratorErrorPage.d.ts +3 -3
  79. package/dist/configurator/configurator-error-page/BuiltInConfiguratorErrorPage.js +1 -1
  80. package/dist/configurator/configurator-error-page/ConfiguratorErrorPageElement.d.ts +0 -5
  81. package/dist/configurator/configurator-error-page/ConfiguratorErrorPageElement.js +1 -1
  82. package/dist/configurator/configurator-error-page/index.d.ts +1 -2
  83. package/dist/configurator/configurator-error-page/index.js +1 -1
  84. package/dist/configurator/index.d.ts +9 -2
  85. package/dist/configurator/index.js +1 -1
  86. package/dist/configurator/pages/default-configurator-elements.js +1 -1
  87. package/dist/configurator/pages/error-boundaries/LoadingErrorBoundary.js +1 -1
  88. package/dist/configurator/ui/assistant/screenshots/ScreenshotThumbnails.d.ts +1 -1
  89. package/dist/configurator/ui/assistant/screenshots/ScreenshotThumbnails.js +1 -1
  90. package/dist/configurator/ui/assistant/screenshots/tool-screenshots.d.ts +12 -4
  91. package/dist/configurator/ui/assistant/screenshots/tool-screenshots.js +1 -1
  92. package/dist/configurator/ui/assistant/screenshots/use-screenshot-src.d.ts +8 -0
  93. package/dist/configurator/ui/assistant/screenshots/use-screenshot-src.js +1 -0
  94. package/dist/configurator/ui/configurator-layout/slots/canvas/LayoutCanvas.js +1 -1
  95. package/dist/configurator/ui/configurator-layout/slots/canvas/SharedCanvas.js +1 -1
  96. package/dist/configurator/ui/configurator-layout/universal/use-layout-scene-safe-area.js +1 -1
  97. package/dist/configurator/ui/legacy/layout/common/ReactiveInterfaceLayout.js +1 -1
  98. package/dist/configurator/ui/phoenix-layout-elements/AppLoader.d.ts +0 -7
  99. package/dist/configurator/ui/phoenix-layout-elements/AppLoader.js +2 -2
  100. package/dist/configurator/ui/phoenix-layout-elements/index.d.ts +8 -1
  101. package/dist/configurator/ui/phoenix-layout-elements/index.js +1 -1
  102. package/dist/configurator/ui/preset-layout/PresetUi.d.ts +0 -2
  103. package/dist/configurator/ui/preset-layout/PresetUi.js +1 -1
  104. package/dist/configurator/ui/preset-layout/index.d.ts +6 -1
  105. package/dist/configurator/ui/preset-layout/index.js +1 -1
  106. package/dist/configurator/ui/save-message-snackbars/SaveMessageSnackbars.js +1 -1
  107. package/dist/docs/index.json +34 -1
  108. package/dist/docs/integrations/webcomponent-api/basics.mdx +2 -0
  109. package/dist/docs/layouts/custom-layout.mdx +318 -158
  110. package/dist/docs/layouts/gallery/ardent-compressor.mdx +1 -0
  111. package/dist/docs/layouts/gallery/corvid-drone.mdx +3428 -0
  112. package/dist/docs/layouts/gallery/fenwick-window.mdx +198 -127
  113. package/dist/docs/layouts/gallery/nightjar-guitar.mdx +3698 -0
  114. package/dist/docs/layouts/gallery/sunfold-solar.mdx +16 -4
  115. package/dist/docs/layouts/gallery/tidepool-aquascape.mdx +5203 -0
  116. package/dist/docs/phoenix/configurator-interface.mdx +8 -6
  117. package/dist/docs/phoenix/sdk-builder-workflow.mdx +4 -2
  118. package/dist/docs/phoenix/sessions-and-access.mdx +2 -0
  119. package/dist/domain/application/assistant/build-assistant-manifest.js +1 -1
  120. package/dist/domain/application/assistant/generate-assistant-prompt.js +1 -1
  121. package/dist/domain/application/configurator-builder.d.ts +7 -1
  122. package/dist/domain/application/configurator-builder.js +1 -1
  123. package/dist/domain/application/index.d.ts +1 -1
  124. package/dist/domain/application/index.js +1 -1
  125. package/dist/domain/application/standard-properties.js +1 -1
  126. package/dist/domain/application/web-component-property.d.ts +3 -1
  127. package/dist/domain/application/web-component-property.js +1 -1
  128. package/dist/domain/domain-builder.d.ts +9 -3
  129. package/dist/domain/domain-builder.js +1 -1
  130. package/dist/domain/domain-runtime/application.d.ts +39 -0
  131. package/dist/domain/domain-runtime/application.js +1 -0
  132. package/dist/domain/domain-runtime/domain-context/selectors.d.ts +1 -0
  133. package/dist/domain/domain-runtime/domain-context/selectors.js +1 -1
  134. package/dist/domain/domain-runtime/domain-runtime.d.ts +40 -4
  135. package/dist/domain/domain-runtime/domain-runtime.js +1 -1
  136. package/dist/domain/domain-runtime/environment/initialize.d.ts +1 -1
  137. package/dist/domain/domain-runtime/errors/implementation-error-collector.d.ts +2 -0
  138. package/dist/domain/domain-runtime/errors/implementation-error-collector.js +1 -1
  139. package/dist/domain/domain-runtime/index.d.ts +2 -1
  140. package/dist/domain/domain-runtime/index.js +1 -1
  141. package/dist/domain/domain-runtime/spec/index.d.ts +1 -1
  142. package/dist/domain/domain-runtime/spec/index.js +1 -1
  143. package/dist/domain/domain-runtime/spec/module-checks/index.d.ts +1 -0
  144. package/dist/domain/domain-runtime/spec/module-checks/index.js +1 -1
  145. package/dist/domain/domain-runtime/spec/module-checks/merge-expression-modules.d.ts +23 -0
  146. package/dist/domain/domain-runtime/spec/module-checks/merge-expression-modules.js +1 -0
  147. package/dist/domain/domain-runtime/spec/module-checks/resolve-expression-modules.d.ts +3 -4
  148. package/dist/domain/domain-runtime/spec/module-checks/resolve-expression-modules.js +1 -1
  149. package/dist/domain/domain-runtime/web-component/actions.d.ts +3 -0
  150. package/dist/domain/domain-runtime/web-component/actions.js +1 -1
  151. package/dist/domain/domain-runtime/web-component/initialize.d.ts +1 -0
  152. package/dist/domain/domain-runtime/web-component/initialize.js +1 -1
  153. package/dist/domain/domain-runtime/web-component/selectors.d.ts +2 -0
  154. package/dist/domain/domain-runtime/web-component/selectors.js +1 -1
  155. package/dist/domain/domain-runtime/web-component/types.d.ts +6 -3
  156. package/dist/domain/mocks/create-mock-domain-runtime.d.ts +7 -0
  157. package/dist/editor/domain-editors/DomainSpecContext.js +1 -1
  158. package/dist/editor/domain-editors/apply-spec-update.d.ts +2 -1
  159. package/dist/editor/domain-editors/apply-spec-update.js +1 -1
  160. package/dist/editor/domain-editors/use-implementation-files.d.ts +6 -14
  161. package/dist/editor/domain-editors/use-implementation-files.js +1 -1
  162. package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
  163. package/dist/legacy/domain-cli/utils/cache.js +1 -1
  164. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/claude-md.d.ts +1 -1
  165. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/cursor-rules.d.ts +1 -1
  166. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.d.ts +1 -1
  167. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.js +11 -5
  168. package/dist/react-sdk/application-runtime/common-services/analytics/analytics-service.d.ts +1 -1
  169. package/dist/react-sdk/application-runtime/common-services/initialize.d.ts +2 -2
  170. package/dist/react-sdk/application-runtime/hooks/index.d.ts +2 -0
  171. package/dist/react-sdk/application-runtime/hooks/index.js +1 -1
  172. package/dist/react-sdk/application-runtime/hooks/loading/index.d.ts +5 -0
  173. package/dist/react-sdk/application-runtime/hooks/loading/index.js +1 -0
  174. package/dist/react-sdk/application-runtime/hooks/loading/loader-host-context.d.ts +11 -0
  175. package/dist/react-sdk/application-runtime/hooks/loading/loader-host-context.js +1 -0
  176. package/dist/react-sdk/application-runtime/hooks/loading/use-is-awaiting-loading-phase.d.ts +8 -0
  177. package/dist/react-sdk/application-runtime/hooks/loading/use-is-awaiting-loading-phase.js +1 -0
  178. package/dist/react-sdk/application-runtime/hooks/loading/use-is-loader-hosted.d.ts +7 -0
  179. package/dist/react-sdk/application-runtime/hooks/loading/use-is-loader-hosted.js +1 -0
  180. package/dist/react-sdk/application-runtime/hooks/loading/use-loading-actions.d.ts +9 -0
  181. package/dist/react-sdk/application-runtime/hooks/loading/use-loading-actions.js +1 -0
  182. package/dist/react-sdk/application-runtime/hooks/loading/use-loading-application.d.ts +24 -0
  183. package/dist/react-sdk/application-runtime/hooks/loading/use-loading-application.js +1 -0
  184. package/dist/react-sdk/application-runtime/hooks/responsive/index.d.ts +3 -0
  185. package/dist/react-sdk/application-runtime/hooks/responsive/index.js +1 -0
  186. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-actions.d.ts +9 -0
  187. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-actions.js +1 -0
  188. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-application.d.ts +26 -0
  189. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-application.js +1 -0
  190. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-state.d.ts +10 -0
  191. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-state.js +1 -0
  192. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-store.d.ts +24 -0
  193. package/dist/react-sdk/application-runtime/hooks/responsive/use-responsive-store.js +1 -0
  194. package/dist/react-sdk/application-runtime/hooks/use-access-service.d.ts +5 -0
  195. package/dist/react-sdk/application-runtime/hooks/use-access-service.js +1 -1
  196. package/dist/react-sdk/application-runtime/hooks/use-web-component-readonly-sync.d.ts +4 -11
  197. package/dist/react-sdk/application-runtime/hooks/use-web-component-readonly-sync.js +1 -1
  198. package/dist/react-sdk/application-runtime/hooks/use-web-component.d.ts +5 -0
  199. package/dist/react-sdk/application-runtime/hooks/use-web-component.js +1 -1
  200. package/dist/react-sdk/application-runtime/host-properties/actions.d.ts +15 -0
  201. package/dist/react-sdk/application-runtime/host-properties/actions.js +1 -0
  202. package/dist/react-sdk/application-runtime/host-properties/connect-host-properties.d.ts +30 -0
  203. package/dist/react-sdk/application-runtime/host-properties/connect-host-properties.js +1 -0
  204. package/dist/react-sdk/application-runtime/host-properties/domain-host-properties.d.ts +7 -0
  205. package/dist/react-sdk/application-runtime/host-properties/domain-host-properties.js +1 -0
  206. package/dist/react-sdk/application-runtime/host-properties/host-property-descriptors.d.ts +21 -0
  207. package/dist/react-sdk/application-runtime/host-properties/host-property-descriptors.js +1 -0
  208. package/dist/react-sdk/application-runtime/host-properties/host-property-scopes.d.ts +42 -0
  209. package/dist/react-sdk/application-runtime/host-properties/host-property-scopes.js +1 -0
  210. package/dist/react-sdk/application-runtime/host-properties/index.d.ts +8 -0
  211. package/dist/react-sdk/application-runtime/host-properties/index.js +1 -0
  212. package/dist/react-sdk/application-runtime/host-properties/initialize.d.ts +7 -0
  213. package/dist/react-sdk/application-runtime/host-properties/initialize.js +1 -0
  214. package/dist/react-sdk/application-runtime/host-properties/selectors.d.ts +54 -0
  215. package/dist/react-sdk/application-runtime/host-properties/selectors.js +1 -0
  216. package/dist/react-sdk/application-runtime/host-properties/types.d.ts +18 -0
  217. package/dist/react-sdk/application-runtime/index.d.ts +3 -0
  218. package/dist/react-sdk/application-runtime/loading/actions.d.ts +45 -0
  219. package/dist/react-sdk/application-runtime/loading/actions.js +1 -0
  220. package/dist/react-sdk/application-runtime/loading/index.d.ts +4 -0
  221. package/dist/react-sdk/application-runtime/loading/index.js +1 -0
  222. package/dist/react-sdk/application-runtime/loading/initialize.d.ts +3 -0
  223. package/dist/react-sdk/application-runtime/loading/initialize.js +1 -0
  224. package/dist/react-sdk/application-runtime/loading/selectors.d.ts +18 -0
  225. package/dist/react-sdk/application-runtime/loading/selectors.js +1 -0
  226. package/dist/react-sdk/application-runtime/loading/types.d.ts +59 -0
  227. package/dist/react-sdk/application-runtime/mocks/create-mock-application-runtime.js +1 -1
  228. package/dist/react-sdk/application-runtime/provider/ApplicationRuntime.d.ts +6 -0
  229. package/dist/react-sdk/application-runtime/provider/ApplicationRuntime.js +1 -1
  230. package/dist/react-sdk/application-runtime/provider/ApplicationType.d.ts +7 -0
  231. package/dist/react-sdk/application-runtime/provider/ApplicationType.js +1 -1
  232. package/dist/react-sdk/application-runtime/responsive/actions.d.ts +47 -0
  233. package/dist/react-sdk/application-runtime/responsive/actions.js +1 -0
  234. package/dist/react-sdk/application-runtime/responsive/index.d.ts +4 -0
  235. package/dist/react-sdk/application-runtime/responsive/index.js +1 -0
  236. package/dist/react-sdk/application-runtime/responsive/initialize.d.ts +3 -0
  237. package/dist/react-sdk/application-runtime/responsive/initialize.js +1 -0
  238. package/dist/react-sdk/application-runtime/responsive/selectors.d.ts +20 -0
  239. package/dist/react-sdk/application-runtime/responsive/selectors.js +1 -0
  240. package/dist/react-sdk/application-runtime/responsive/types.d.ts +104 -0
  241. package/dist/react-sdk/application-runtime/responsive/types.js +1 -0
  242. package/dist/react-sdk/application-runtime/runtime/create-application-runtime.d.ts +309 -8
  243. package/dist/react-sdk/application-runtime/runtime/create-application-runtime.js +1 -1
  244. package/dist/react-sdk/domain-application-context/BackendDataProvider.js +1 -1
  245. package/dist/react-sdk/domain-application-context/FrontendDataProvider.js +1 -1
  246. package/dist/react-sdk/domain-application-context/PublishedDataProvider.js +1 -1
  247. package/dist/react-sdk/domain-context/common-hooks/index.d.ts +1 -0
  248. package/dist/react-sdk/domain-context/common-hooks/index.js +1 -1
  249. package/dist/react-sdk/domain-context/common-hooks/use-configuration-save-state.d.ts +23 -0
  250. package/dist/react-sdk/domain-context/common-hooks/use-configuration-save-state.js +1 -0
  251. package/dist/react-sdk/domain-context/common-hooks/use-domain-context.d.ts +1 -0
  252. package/dist/react-sdk/domain-context/index.d.ts +1 -0
  253. package/dist/react-sdk/domain-context/index.js +1 -1
  254. package/dist/react-sdk/elements/index.d.ts +0 -1
  255. package/dist/react-sdk/index.d.ts +1 -1
  256. package/dist/react-sdk/index.js +1 -1
  257. package/dist/react-sdk/loading-state/LoaderHost.d.ts +20 -0
  258. package/dist/react-sdk/loading-state/LoaderHost.js +1 -0
  259. package/dist/react-sdk/loading-state/built-in-loading-phase.d.ts +9 -0
  260. package/dist/react-sdk/loading-state/built-in-loading-phase.js +1 -0
  261. package/dist/react-sdk/loading-state/create-app-loader.d.ts +18 -0
  262. package/dist/react-sdk/loading-state/create-app-loader.js +1 -0
  263. package/dist/react-sdk/loading-state/index.d.ts +4 -2
  264. package/dist/react-sdk/loading-state/index.js +1 -1
  265. package/dist/react-sdk/loading-state/{LoadingStateProvider.d.ts → loading-state-hooks.d.ts} +3 -12
  266. package/dist/react-sdk/loading-state/loading-state-hooks.js +1 -0
  267. package/dist/react-sdk/page-elements/ConfigurationNotFoundPagePropsProvider.d.ts +17 -0
  268. package/dist/react-sdk/page-elements/ConfigurationNotFoundPagePropsProvider.js +1 -0
  269. package/dist/react-sdk/page-elements/ConfiguratorErrorPagePropsProvider.d.ts +17 -0
  270. package/dist/react-sdk/page-elements/ConfiguratorErrorPagePropsProvider.js +1 -0
  271. package/dist/react-sdk/page-elements/configurator-error-page-props.js +1 -0
  272. package/dist/{configurator/configuration-not-found-page → react-sdk/page-elements}/create-configuration-not-found-page.d.ts +7 -1
  273. package/dist/react-sdk/page-elements/create-configuration-not-found-page.js +1 -0
  274. package/dist/{configurator/configurator-error-page → react-sdk/page-elements}/create-configurator-error-page.d.ts +6 -1
  275. package/dist/react-sdk/page-elements/create-configurator-error-page.js +1 -0
  276. package/dist/react-sdk/page-elements/create-preset-ui.d.ts +9 -0
  277. package/dist/react-sdk/page-elements/create-preset-ui.js +1 -0
  278. package/dist/react-sdk/page-elements/index.d.ts +6 -0
  279. package/dist/react-sdk/page-elements/index.js +1 -0
  280. package/dist/react-sdk/session/SessionServiceProvider.js +1 -1
  281. package/dist/react-sdk/web-component/create-web-component.js +1 -1
  282. package/dist/ui-sdk/responsive-application/ResponsiveApplicationProvider.d.ts +2 -2
  283. package/dist/ui-sdk/responsive-application/responsive-state-store.d.ts +11 -9
  284. package/dist/ui-sdk/responsive-application/use-store-responsive-info.js +1 -1
  285. package/package.json +3 -3
  286. package/dist/configurator/app-loader-content/app-loader-content-name.d.ts +0 -5
  287. package/dist/configurator/app-loader-content/app-loader-content-name.js +0 -1
  288. package/dist/configurator/configuration-not-found-page/create-configuration-not-found-page.js +0 -1
  289. package/dist/configurator/configurator-error-page/create-configurator-error-page.js +0 -1
  290. package/dist/react-sdk/loading-state/LoadingStateProvider.js +0 -1
  291. package/dist/react-sdk/loading-state/loading-state-manager.d.ts +0 -37
  292. package/dist/react-sdk/loading-state/loading-state-manager.js +0 -1
  293. package/dist/react-sdk/responsive-state/ResponsiveStateProvider.d.ts +0 -25
  294. package/dist/react-sdk/responsive-state/ResponsiveStateProvider.js +0 -1
  295. package/dist/react-sdk/responsive-state/canvas-padding.d.ts +0 -14
  296. package/dist/react-sdk/responsive-state/index.d.ts +0 -5
  297. package/dist/react-sdk/responsive-state/index.js +0 -1
  298. package/dist/react-sdk/responsive-state/responsive-state-manager.d.ts +0 -111
  299. package/dist/react-sdk/responsive-state/responsive-state-manager.js +0 -1
  300. package/dist/react-sdk/responsive-state/use-responsive-state-manager.d.ts +0 -10
  301. package/dist/react-sdk/responsive-state/use-responsive-state-manager.js +0 -1
  302. package/dist/react-sdk/responsive-state/use-responsive-state.d.ts +0 -11
  303. package/dist/react-sdk/responsive-state/use-responsive-state.js +0 -1
  304. /package/dist/react-sdk/{elements/configurator-error-page-props.js → application-runtime/host-properties/types.js} +0 -0
  305. /package/dist/react-sdk/{responsive-state/canvas-padding.js → application-runtime/loading/types.js} +0 -0
  306. /package/dist/react-sdk/{elements → page-elements}/configurator-error-page-props.d.ts +0 -0
@@ -413,8 +413,19 @@ const useSize = () => {
413
413
  return { ref, size }
414
414
  }
415
415
 
416
+ // A rectangle moved in by `by` on every side. A size the spec allows can leave no room, for example three panes across
417
+ // a 500 mm window, so the size never drops below zero; what has no size is not drawn.
416
418
  const inset = (rect: { x: number; y: number; width: number; height: number }, by: number) => {
417
- return { x: rect.x + by, y: rect.y + by, width: rect.width - 2 * by, height: rect.height - 2 * by }
419
+ return {
420
+ x: rect.x + by,
421
+ y: rect.y + by,
422
+ width: Math.max(0, rect.width - 2 * by),
423
+ height: Math.max(0, rect.height - 2 * by),
424
+ }
425
+ }
426
+
427
+ const hasSize = (rect: { width: number; height: number }) => {
428
+ return rect.width > 0 && rect.height > 0
418
429
  }
419
430
 
420
431
  // The elevation of the window as configured, drawn in millimetres from the spec's `$panes` expression. The drawing is
@@ -426,8 +437,14 @@ export const ShopDrawing = () => {
426
437
  const { width: W, height: H, $panes: panes, $mullionWidth: mullion } = casement
427
438
  const mainPanes = panes.filter(pane => pane.key.startsWith('P'))
428
439
  const topLight = panes.find(pane => pane.key === 'T1')
429
- const left = (topLight ? 2 : 1) * TIER + 18
430
- const bottom = (mainPanes.length > 1 ? 2 : 1) * TIER + 14
440
+ const transom = topLight ? topLight.y + topLight.height + mullion / 2 : null
441
+ // A tall top light can leave the main panes no height. They are not drawn then, so neither is a height split
442
+ // over them nor the chain of their widths
443
+ const mainPanesDrawn = mainPanes.some(hasSize)
444
+ const split = mainPanesDrawn ? transom : null
445
+ const chained = mainPanesDrawn && mainPanes.length > 1
446
+ const left = (split !== null ? 2 : 1) * TIER + 18
447
+ const bottom = (chained ? 2 : 1) * TIER + 14
431
448
  const timber = SHEET.timber[casement.finish]
432
449
 
433
450
  // Pixels per millimetre: the window and its margins fill the box in its tighter direction
@@ -439,7 +456,6 @@ export const ShopDrawing = () => {
439
456
  const viewBox = [-left * px, -MARGIN.top * px, W + (left + MARGIN.right) * px, H + (MARGIN.top + bottom) * px]
440
457
  // The chain of pane widths along the bottom, measured to the centres of the mullions
441
458
  const chain = [0, ...mainPanes.slice(0, -1).map(pane => pane.x + pane.width + mullion / 2), W]
442
- const split = topLight ? topLight.y + topLight.height + mullion / 2 : null
443
459
 
444
460
  return (
445
461
  <Box component="div" ref={ref} sx={{ position: 'absolute', inset: 0 }}>
@@ -457,51 +473,60 @@ export const ShopDrawing = () => {
457
473
 
458
474
  {panes.map(pane => {
459
475
  const isSash = pane.opening !== 'Fixed'
476
+ const opening = inset(pane, 0)
460
477
  const glass = inset(pane, isSash ? SASH : BEAD)
461
478
  const outline = pane.oversize ? SHEET.attention : SHEET.ink
462
479
 
480
+ // A top light can leave the main panes no height at all; the spec's warning says so
481
+ if (!hasSize(opening)) {
482
+ return null
483
+ }
484
+
463
485
  return (
464
486
  <g key={pane.key}>
465
- <rect
466
- x={pane.x}
467
- y={pane.y}
468
- width={pane.width}
469
- height={pane.height}
470
- fill={isSash ? timber : SHEET.glass}
471
- stroke={SHEET.ink}
472
- strokeWidth={1.2 * px}
473
- />
474
- <rect {...glass} fill={SHEET.glass} stroke={SHEET.glassStroke} strokeWidth={px} />
475
- {/* Two short strokes in a corner, the drafting sign for glass */}
476
- <polyline
477
- points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.28} ${glass.x + glass.width * 0.28},${glass.y + glass.height * 0.1}`}
478
- stroke={SHEET.glassStroke}
479
- strokeWidth={1.2 * px}
480
- fill="none"
481
- />
482
- <polyline
483
- points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.4} ${glass.x + glass.width * 0.4},${glass.y + glass.height * 0.1}`}
484
- stroke={SHEET.glassStroke}
485
- strokeWidth={1.2 * px}
486
- fill="none"
487
- />
488
- {casement.glazingBars && (
489
- <g fill={timber} stroke={SHEET.ink} strokeWidth={px}>
490
- <rect
491
- x={glass.x + glass.width / 2 - GLAZING_BAR / 2}
492
- y={glass.y}
493
- width={GLAZING_BAR}
494
- height={glass.height}
487
+ <rect {...opening} fill={isSash ? timber : SHEET.glass} stroke={SHEET.ink} strokeWidth={1.2 * px} />
488
+ {hasSize(glass) && (
489
+ <>
490
+ <rect {...glass} fill={SHEET.glass} stroke={SHEET.glassStroke} strokeWidth={px} />
491
+ {/* Two short strokes in a corner, the drafting sign for glass */}
492
+ <polyline
493
+ points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.28} ${glass.x + glass.width * 0.28},${glass.y + glass.height * 0.1}`}
494
+ stroke={SHEET.glassStroke}
495
+ strokeWidth={1.2 * px}
496
+ fill="none"
495
497
  />
496
- <rect
497
- x={glass.x}
498
- y={glass.y + glass.height / 2 - GLAZING_BAR / 2}
499
- width={glass.width}
500
- height={GLAZING_BAR}
498
+ <polyline
499
+ points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.4} ${glass.x + glass.width * 0.4},${glass.y + glass.height * 0.1}`}
500
+ stroke={SHEET.glassStroke}
501
+ strokeWidth={1.2 * px}
502
+ fill="none"
501
503
  />
502
- </g>
504
+ {casement.glazingBars && (
505
+ <g fill={timber} stroke={SHEET.ink} strokeWidth={px}>
506
+ <rect
507
+ x={glass.x + glass.width / 2 - GLAZING_BAR / 2}
508
+ y={glass.y}
509
+ width={GLAZING_BAR}
510
+ height={glass.height}
511
+ />
512
+ <rect
513
+ x={glass.x}
514
+ y={glass.y + glass.height / 2 - GLAZING_BAR / 2}
515
+ width={glass.width}
516
+ height={GLAZING_BAR}
517
+ />
518
+ </g>
519
+ )}
520
+ <OpeningSymbol
521
+ opening={pane.opening}
522
+ glass={glass}
523
+ sash={opening}
524
+ stile={SASH}
525
+ px={px}
526
+ color={outline}
527
+ />
528
+ </>
503
529
  )}
504
- <OpeningSymbol opening={pane.opening} glass={glass} sash={pane} stile={SASH} px={px} color={outline} />
505
530
  {pane.oversize && (
506
531
  <>
507
532
  <rect
@@ -529,7 +554,7 @@ export const ShopDrawing = () => {
529
554
  )
530
555
  })}
531
556
 
532
- {mainPanes.length > 1 &&
557
+ {chained &&
533
558
  chain
534
559
  .slice(1)
535
560
  .map((end, index) => (
@@ -543,14 +568,7 @@ export const ShopDrawing = () => {
543
568
  px={px}
544
569
  />
545
570
  ))}
546
- <DimensionLine
547
- from={0}
548
- to={W}
549
- at={H + (mainPanes.length > 1 ? 2 : 1) * TIER * px}
550
- origin={H}
551
- axis="horizontal"
552
- px={px}
553
- />
571
+ <DimensionLine from={0} to={W} at={H + (chained ? 2 : 1) * TIER * px} origin={H} axis="horizontal" px={px} />
554
572
 
555
573
  {split !== null && (
556
574
  <>
@@ -670,7 +688,7 @@ components:
670
688
 
671
689
  ## Rules the drawing shows
672
690
 
673
- A sash wider than its hinges carry would sag, and a top light can leave too little window below it. Both rules are `warning` invariants: the change is kept, so the drawing shows the problem, the inputs say how to fix it, and the window cannot be ordered until it is fixed.
691
+ A sash wider than its hinges carry would sag, a sash narrower than its two stiles has no room for glass, and a top light can leave too little window below it. All three rules are `warning` invariants: the change is kept, so the drawing shows the problem, the inputs say how to fix it, and the window cannot be ordered until it is fixed. The drawing never draws a negative size: a sash with no room for glass is drawn without glass or symbol, and main panes with no height are left out.
674
692
 
675
693
  ```yaml
676
694
  invariants:
@@ -678,6 +696,7 @@ invariants:
678
696
  sashSize:
679
697
  types:
680
698
  - sashTooWide
699
+ - sashTooNarrow
681
700
  topLightTooTall:
682
701
  type: topLightTooTall
683
702
  severity: warning
@@ -690,26 +709,40 @@ import { phx } from '../../.phoenix/phx.js'
690
709
  const MAX_SASH_WIDTH = { Fixed: Infinity, SideHung: 900, TiltTurn: 1300, TopHung: 1600 }
691
710
  const OPENING_LABEL = { Fixed: 'fixed', SideHung: 'side-hung', TiltTurn: 'tilt and turn', TopHung: 'top-hung' }
692
711
  const MIN_MAIN_HEIGHT = 500
712
+ // A sash's two stiles are 56 mm each, so a narrower opening leaves no room for glass
713
+ const MIN_SASH_WIDTH = 2 * 56
693
714
 
694
715
  // Both rules are warnings: the drawing keeps the change and marks the problem, and the window cannot be ordered until
695
716
  // it is resolved
696
717
  export default phx.domain.implementCustomInvariants({
697
718
  Window: {
698
- // A sash wider than its hinges carry would sag; the message names the limit of the chosen opening
719
+ // A sash wider than its hinges carry would sag, and one narrower than its two stiles has no room for glass; the
720
+ // messages name the limit
699
721
  sashSize: s => {
700
722
  const oversize = s.$panes.find(pane => pane.oversize)
723
+ const undersize = s.$panes.find(pane => pane.opening !== 'Fixed' && pane.width < MIN_SASH_WIDTH)
724
+
725
+ if (oversize !== undefined) {
726
+ return [
727
+ {
728
+ type: 'sashTooWide',
729
+ severity: 'warning',
730
+ message: `A ${OPENING_LABEL[s.opening]} sash can be at most ${MAX_SASH_WIDTH[s.opening].toLocaleString('en-GB')} mm wide, and these are ${Math.round(oversize.width).toLocaleString('en-GB')} mm. Add a pane across or make the window narrower.`,
731
+ },
732
+ ]
733
+ }
701
734
 
702
- if (oversize === undefined) {
703
- return []
735
+ if (undersize !== undefined) {
736
+ return [
737
+ {
738
+ type: 'sashTooNarrow',
739
+ severity: 'warning',
740
+ message: `A sash needs at least ${MIN_SASH_WIDTH} mm for its stiles, and these are ${Math.round(undersize.width)} mm. Use fewer panes across or make the window wider.`,
741
+ },
742
+ ]
704
743
  }
705
744
 
706
- return [
707
- {
708
- type: 'sashTooWide',
709
- severity: 'warning',
710
- message: `A ${OPENING_LABEL[s.opening]} sash can be at most ${MAX_SASH_WIDTH[s.opening].toLocaleString('en-GB')} mm wide, and these are ${Math.round(oversize.width).toLocaleString('en-GB')} mm. Add a pane across or make the window narrower.`,
711
- },
712
- ]
745
+ return []
713
746
  },
714
747
  topLightTooTall: s => {
715
748
  return !s.topLight || s.height - 2 * s.$frameWidth - s.topLightHeight - s.$mullionWidth >= MIN_MAIN_HEIGHT
@@ -852,12 +885,14 @@ The same layout in a frame 390 pixels wide: the drawing keeps the top of the scr
852
885
  - The page opens on a 1400 × 1250 mm two-light window with side-hung sashes hinged at the outer edges: two dashed symbols with their apexes at the outer sides, the handles on the meeting stiles, the pane widths 700 and 700 below, 1400 overall and 1250 at the side. The title block shows Uw 1.30 W/m²K and 50 kg, and the price is **£1,276.00**.
853
886
  - A width of 2100 mm outlines both sashes in red with "SASH TOO WIDE", shows "A side-hung sash can be at most 900 mm wide, and these are 944 mm. …" under **Overall size**, and disables **Add to order**.
854
887
  - Three panes across clear the warning: the middle pane reads "FIXED", the outer two open, and the chain reads 710, 680 and 710.
888
+ - Three panes across a 500 mm window show "A sash needs at least 112 mm for its stiles, and these are 71 mm. …" under **Overall size**; the outer sashes are drawn without glass or symbol.
889
+ - A 500 mm high window with the 400 mm top light shows the top light warning, and the drawing keeps the top light and leaves out the main panes.
855
890
  - **Top light** adds a fixed pane above a transom, the **Top light height** input, and a second tier on the left with the two heights. A top light of 600 mm in a 1250 mm window shows the top light warning under **Panes**; 380 mm clears it.
856
891
  - One pane with **Tilt and turn** shows the **Hinged on the** question; **Right** puts the symbol's apex on the right and the handle on the left, with a second pair of lines pointing down for the tilt.
857
892
  - **Top-hung** removes the hinge question and points the symbol's apex to the top, with the handle on the bottom rail.
858
893
  - An 800 × 1800 mm window draws tall and narrow, with its lettering at the same size as the wide one's.
859
894
  - **Triple** glazing lowers the U-value in the title block and raises the price; **Glazing bars** draws a cross of bars in every pane; **Natural oak** tints the frame and changes the title block's finish.
860
- - The **−** and **+** buttons change a size by 10 mm, and a typed size is clamped to the input's range.
895
+ - The **−** and **+** buttons change a size by 10 mm, a typed size is clamped to the input's range, and a size cleared and left empty gets its value back.
861
896
  - **Add to order** shows a spinner and "Adding…", then "Added to your order" with the size and the price; the inputs are locked until **Draw another**.
862
897
  - In the **Phone** story the drawing stays at the top while the inputs scroll, the same warning and drawing changes appear, and **Add to order** confirms the order in the bottom bar.
863
898
  - The browser console shows no errors, the page has no `canvas` element, and no model or texture is requested.
@@ -1019,6 +1054,7 @@ invariants:
1019
1054
  sashSize:
1020
1055
  types:
1021
1056
  - sashTooWide
1057
+ - sashTooNarrow
1022
1058
  topLightTooTall:
1023
1059
  type: topLightTooTall
1024
1060
  severity: warning
@@ -1322,8 +1358,8 @@ export const OpeningSymbol = ({ opening, glass, sash, stile, px, color }: Openin
1322
1358
  const midX = x + width / 2
1323
1359
  const midY = y + height / 2
1324
1360
  const dash = `${8 * px} ${5 * px}`
1325
- const handleLength = Math.min(120, height / 3)
1326
- const handleWidth = Math.min(16, stile / 2)
1361
+ const handleLength = Math.max(0, Math.min(120, height / 3))
1362
+ const handleWidth = Math.max(0, Math.min(16, stile / 2))
1327
1363
 
1328
1364
  if (opening === 'Fixed') {
1329
1365
  return (
@@ -1373,7 +1409,9 @@ export const OpeningSymbol = ({ opening, glass, sash, stile, px, color }: Openin
1373
1409
  {tiltLines && (
1374
1410
  <polyline points={tiltLines} fill="none" stroke={color} strokeWidth={1.2 * px} strokeDasharray={dash} />
1375
1411
  )}
1376
- <rect {...handle} rx={handleWidth / 2} fill={SHEET.paper} stroke={SHEET.ink} strokeWidth={1.4 * px} />
1412
+ {handleLength > 0 && (
1413
+ <rect {...handle} rx={handleWidth / 2} fill={SHEET.paper} stroke={SHEET.ink} strokeWidth={1.4 * px} />
1414
+ )}
1377
1415
  </g>
1378
1416
  )
1379
1417
  }
@@ -1428,8 +1466,19 @@ const useSize = () => {
1428
1466
  return { ref, size }
1429
1467
  }
1430
1468
 
1469
+ // A rectangle moved in by `by` on every side. A size the spec allows can leave no room, for example three panes across
1470
+ // a 500 mm window, so the size never drops below zero; what has no size is not drawn.
1431
1471
  const inset = (rect: { x: number; y: number; width: number; height: number }, by: number) => {
1432
- return { x: rect.x + by, y: rect.y + by, width: rect.width - 2 * by, height: rect.height - 2 * by }
1472
+ return {
1473
+ x: rect.x + by,
1474
+ y: rect.y + by,
1475
+ width: Math.max(0, rect.width - 2 * by),
1476
+ height: Math.max(0, rect.height - 2 * by),
1477
+ }
1478
+ }
1479
+
1480
+ const hasSize = (rect: { width: number; height: number }) => {
1481
+ return rect.width > 0 && rect.height > 0
1433
1482
  }
1434
1483
 
1435
1484
  // The elevation of the window as configured, drawn in millimetres from the spec's `$panes` expression. The drawing is
@@ -1441,8 +1490,14 @@ export const ShopDrawing = () => {
1441
1490
  const { width: W, height: H, $panes: panes, $mullionWidth: mullion } = casement
1442
1491
  const mainPanes = panes.filter(pane => pane.key.startsWith('P'))
1443
1492
  const topLight = panes.find(pane => pane.key === 'T1')
1444
- const left = (topLight ? 2 : 1) * TIER + 18
1445
- const bottom = (mainPanes.length > 1 ? 2 : 1) * TIER + 14
1493
+ const transom = topLight ? topLight.y + topLight.height + mullion / 2 : null
1494
+ // A tall top light can leave the main panes no height. They are not drawn then, so neither is a height split
1495
+ // over them nor the chain of their widths
1496
+ const mainPanesDrawn = mainPanes.some(hasSize)
1497
+ const split = mainPanesDrawn ? transom : null
1498
+ const chained = mainPanesDrawn && mainPanes.length > 1
1499
+ const left = (split !== null ? 2 : 1) * TIER + 18
1500
+ const bottom = (chained ? 2 : 1) * TIER + 14
1446
1501
  const timber = SHEET.timber[casement.finish]
1447
1502
 
1448
1503
  // Pixels per millimetre: the window and its margins fill the box in its tighter direction
@@ -1454,7 +1509,6 @@ export const ShopDrawing = () => {
1454
1509
  const viewBox = [-left * px, -MARGIN.top * px, W + (left + MARGIN.right) * px, H + (MARGIN.top + bottom) * px]
1455
1510
  // The chain of pane widths along the bottom, measured to the centres of the mullions
1456
1511
  const chain = [0, ...mainPanes.slice(0, -1).map(pane => pane.x + pane.width + mullion / 2), W]
1457
- const split = topLight ? topLight.y + topLight.height + mullion / 2 : null
1458
1512
 
1459
1513
  return (
1460
1514
  <Box component="div" ref={ref} sx={{ position: 'absolute', inset: 0 }}>
@@ -1472,51 +1526,60 @@ export const ShopDrawing = () => {
1472
1526
 
1473
1527
  {panes.map(pane => {
1474
1528
  const isSash = pane.opening !== 'Fixed'
1529
+ const opening = inset(pane, 0)
1475
1530
  const glass = inset(pane, isSash ? SASH : BEAD)
1476
1531
  const outline = pane.oversize ? SHEET.attention : SHEET.ink
1477
1532
 
1533
+ // A top light can leave the main panes no height at all; the spec's warning says so
1534
+ if (!hasSize(opening)) {
1535
+ return null
1536
+ }
1537
+
1478
1538
  return (
1479
1539
  <g key={pane.key}>
1480
- <rect
1481
- x={pane.x}
1482
- y={pane.y}
1483
- width={pane.width}
1484
- height={pane.height}
1485
- fill={isSash ? timber : SHEET.glass}
1486
- stroke={SHEET.ink}
1487
- strokeWidth={1.2 * px}
1488
- />
1489
- <rect {...glass} fill={SHEET.glass} stroke={SHEET.glassStroke} strokeWidth={px} />
1490
- {/* Two short strokes in a corner, the drafting sign for glass */}
1491
- <polyline
1492
- points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.28} ${glass.x + glass.width * 0.28},${glass.y + glass.height * 0.1}`}
1493
- stroke={SHEET.glassStroke}
1494
- strokeWidth={1.2 * px}
1495
- fill="none"
1496
- />
1497
- <polyline
1498
- points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.4} ${glass.x + glass.width * 0.4},${glass.y + glass.height * 0.1}`}
1499
- stroke={SHEET.glassStroke}
1500
- strokeWidth={1.2 * px}
1501
- fill="none"
1502
- />
1503
- {casement.glazingBars && (
1504
- <g fill={timber} stroke={SHEET.ink} strokeWidth={px}>
1505
- <rect
1506
- x={glass.x + glass.width / 2 - GLAZING_BAR / 2}
1507
- y={glass.y}
1508
- width={GLAZING_BAR}
1509
- height={glass.height}
1540
+ <rect {...opening} fill={isSash ? timber : SHEET.glass} stroke={SHEET.ink} strokeWidth={1.2 * px} />
1541
+ {hasSize(glass) && (
1542
+ <>
1543
+ <rect {...glass} fill={SHEET.glass} stroke={SHEET.glassStroke} strokeWidth={px} />
1544
+ {/* Two short strokes in a corner, the drafting sign for glass */}
1545
+ <polyline
1546
+ points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.28} ${glass.x + glass.width * 0.28},${glass.y + glass.height * 0.1}`}
1547
+ stroke={SHEET.glassStroke}
1548
+ strokeWidth={1.2 * px}
1549
+ fill="none"
1510
1550
  />
1511
- <rect
1512
- x={glass.x}
1513
- y={glass.y + glass.height / 2 - GLAZING_BAR / 2}
1514
- width={glass.width}
1515
- height={GLAZING_BAR}
1551
+ <polyline
1552
+ points={`${glass.x + glass.width * 0.1},${glass.y + glass.height * 0.4} ${glass.x + glass.width * 0.4},${glass.y + glass.height * 0.1}`}
1553
+ stroke={SHEET.glassStroke}
1554
+ strokeWidth={1.2 * px}
1555
+ fill="none"
1556
+ />
1557
+ {casement.glazingBars && (
1558
+ <g fill={timber} stroke={SHEET.ink} strokeWidth={px}>
1559
+ <rect
1560
+ x={glass.x + glass.width / 2 - GLAZING_BAR / 2}
1561
+ y={glass.y}
1562
+ width={GLAZING_BAR}
1563
+ height={glass.height}
1564
+ />
1565
+ <rect
1566
+ x={glass.x}
1567
+ y={glass.y + glass.height / 2 - GLAZING_BAR / 2}
1568
+ width={glass.width}
1569
+ height={GLAZING_BAR}
1570
+ />
1571
+ </g>
1572
+ )}
1573
+ <OpeningSymbol
1574
+ opening={pane.opening}
1575
+ glass={glass}
1576
+ sash={opening}
1577
+ stile={SASH}
1578
+ px={px}
1579
+ color={outline}
1516
1580
  />
1517
- </g>
1581
+ </>
1518
1582
  )}
1519
- <OpeningSymbol opening={pane.opening} glass={glass} sash={pane} stile={SASH} px={px} color={outline} />
1520
1583
  {pane.oversize && (
1521
1584
  <>
1522
1585
  <rect
@@ -1544,7 +1607,7 @@ export const ShopDrawing = () => {
1544
1607
  )
1545
1608
  })}
1546
1609
 
1547
- {mainPanes.length > 1 &&
1610
+ {chained &&
1548
1611
  chain
1549
1612
  .slice(1)
1550
1613
  .map((end, index) => (
@@ -1558,14 +1621,7 @@ export const ShopDrawing = () => {
1558
1621
  px={px}
1559
1622
  />
1560
1623
  ))}
1561
- <DimensionLine
1562
- from={0}
1563
- to={W}
1564
- at={H + (mainPanes.length > 1 ? 2 : 1) * TIER * px}
1565
- origin={H}
1566
- axis="horizontal"
1567
- px={px}
1568
- />
1624
+ <DimensionLine from={0} to={W} at={H + (chained ? 2 : 1) * TIER * px} origin={H} axis="horizontal" px={px} />
1569
1625
 
1570
1626
  {split !== null && (
1571
1627
  <>
@@ -1891,7 +1947,8 @@ const MillimetreInput = ({ instanceName, label, readOnly }: MillimetreFieldProps
1891
1947
  const commitDraft = () => {
1892
1948
  const parsed = Number(draft)
1893
1949
 
1894
- if (Number.isFinite(parsed)) {
1950
+ // `Number('')` is 0, so a cleared field would become the minimum; it gets the stored value back instead
1951
+ if (draft.trim() !== '' && Number.isFinite(parsed)) {
1895
1952
  commit(parsed)
1896
1953
  } else {
1897
1954
  setDraft(String(dimension.value))
@@ -2435,7 +2492,7 @@ interface WindowInputsProps {
2435
2492
  export const WindowInputs = ({ readOnly }: WindowInputsProps) => {
2436
2493
  return (
2437
2494
  <Box component="div" sx={{ display: 'grid' }}>
2438
- <Section title="Overall size" warningTypes={['sashTooWide']}>
2495
+ <Section title="Overall size" warningTypes={['sashTooWide', 'sashTooNarrow']}>
2439
2496
  <MillimetreField instanceName="width" label="Width" readOnly={readOnly} />
2440
2497
  <MillimetreField instanceName="height" label="Height" readOnly={readOnly} />
2441
2498
  </Section>
@@ -2701,26 +2758,40 @@ import { phx } from '../../.phoenix/phx.js'
2701
2758
  const MAX_SASH_WIDTH = { Fixed: Infinity, SideHung: 900, TiltTurn: 1300, TopHung: 1600 }
2702
2759
  const OPENING_LABEL = { Fixed: 'fixed', SideHung: 'side-hung', TiltTurn: 'tilt and turn', TopHung: 'top-hung' }
2703
2760
  const MIN_MAIN_HEIGHT = 500
2761
+ // A sash's two stiles are 56 mm each, so a narrower opening leaves no room for glass
2762
+ const MIN_SASH_WIDTH = 2 * 56
2704
2763
 
2705
2764
  // Both rules are warnings: the drawing keeps the change and marks the problem, and the window cannot be ordered until
2706
2765
  // it is resolved
2707
2766
  export default phx.domain.implementCustomInvariants({
2708
2767
  Window: {
2709
- // A sash wider than its hinges carry would sag; the message names the limit of the chosen opening
2768
+ // A sash wider than its hinges carry would sag, and one narrower than its two stiles has no room for glass; the
2769
+ // messages name the limit
2710
2770
  sashSize: s => {
2711
2771
  const oversize = s.$panes.find(pane => pane.oversize)
2772
+ const undersize = s.$panes.find(pane => pane.opening !== 'Fixed' && pane.width < MIN_SASH_WIDTH)
2773
+
2774
+ if (oversize !== undefined) {
2775
+ return [
2776
+ {
2777
+ type: 'sashTooWide',
2778
+ severity: 'warning',
2779
+ message: `A ${OPENING_LABEL[s.opening]} sash can be at most ${MAX_SASH_WIDTH[s.opening].toLocaleString('en-GB')} mm wide, and these are ${Math.round(oversize.width).toLocaleString('en-GB')} mm. Add a pane across or make the window narrower.`,
2780
+ },
2781
+ ]
2782
+ }
2712
2783
 
2713
- if (oversize === undefined) {
2714
- return []
2784
+ if (undersize !== undefined) {
2785
+ return [
2786
+ {
2787
+ type: 'sashTooNarrow',
2788
+ severity: 'warning',
2789
+ message: `A sash needs at least ${MIN_SASH_WIDTH} mm for its stiles, and these are ${Math.round(undersize.width)} mm. Use fewer panes across or make the window wider.`,
2790
+ },
2791
+ ]
2715
2792
  }
2716
2793
 
2717
- return [
2718
- {
2719
- type: 'sashTooWide',
2720
- severity: 'warning',
2721
- message: `A ${OPENING_LABEL[s.opening]} sash can be at most ${MAX_SASH_WIDTH[s.opening].toLocaleString('en-GB')} mm wide, and these are ${Math.round(oversize.width).toLocaleString('en-GB')} mm. Add a pane across or make the window narrower.`,
2722
- },
2723
- ]
2794
+ return []
2724
2795
  },
2725
2796
  topLightTooTall: s => {
2726
2797
  return !s.topLight || s.height - 2 * s.$frameWidth - s.topLightHeight - s.$mullionWidth >= MIN_MAIN_HEIGHT