@webiny/website-builder-sdk 0.0.0-unstable.7be00a75a9 → 0.0.0-unstable.7c2def32a7

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 (170) hide show
  1. package/BindingsResolver.d.ts +4 -1
  2. package/BindingsResolver.js.map +1 -1
  3. package/ComponentInputTraverser.js +4 -0
  4. package/ComponentInputTraverser.js.map +1 -1
  5. package/ComponentResolver.d.ts +6 -3
  6. package/ComponentResolver.js +9 -4
  7. package/ComponentResolver.js.map +1 -1
  8. package/ContentSdk.d.ts +67 -1
  9. package/ContentSdk.js +90 -8
  10. package/ContentSdk.js.map +1 -1
  11. package/DocumentStoreManager.d.ts +9 -2
  12. package/DocumentStoreManager.js +24 -5
  13. package/DocumentStoreManager.js.map +1 -1
  14. package/EditingSdk.d.ts +7 -1
  15. package/EditingSdk.js +5 -3
  16. package/EditingSdk.js.map +1 -1
  17. package/ElementFactory.js +7 -2
  18. package/ElementFactory.js.map +1 -1
  19. package/ElementFactory.test.js +102 -0
  20. package/ElementFactory.test.js.map +1 -1
  21. package/LiveSdk.d.ts +3 -1
  22. package/LiveSdk.js +3 -2
  23. package/LiveSdk.js.map +1 -1
  24. package/PreviewDocument.d.ts +3 -1
  25. package/PreviewDocument.js +5 -2
  26. package/PreviewDocument.js.map +1 -1
  27. package/PreviewSdk.d.ts +4 -1
  28. package/PreviewSdk.js +6 -2
  29. package/PreviewSdk.js.map +1 -1
  30. package/ResizeObserver.js +1 -1
  31. package/ResizeObserver.js.map +1 -1
  32. package/StylesBindingsProcessor.js +3 -2
  33. package/StylesBindingsProcessor.js.map +1 -1
  34. package/Theme.js +2 -1
  35. package/Theme.js.map +1 -1
  36. package/asset/deliveryUrl.d.ts +41 -0
  37. package/asset/deliveryUrl.js +34 -0
  38. package/asset/deliveryUrl.js.map +1 -0
  39. package/asset/deliveryUrl.test.d.ts +1 -0
  40. package/asset/deliveryUrl.test.js +127 -0
  41. package/asset/deliveryUrl.test.js.map +1 -0
  42. package/asset/geometry.d.ts +7 -0
  43. package/asset/geometry.js +10 -0
  44. package/asset/geometry.js.map +1 -0
  45. package/asset/imageSrcSet.d.ts +63 -0
  46. package/asset/imageSrcSet.js +98 -0
  47. package/asset/imageSrcSet.js.map +1 -0
  48. package/asset/imageSrcSet.test.d.ts +1 -0
  49. package/asset/imageSrcSet.test.js +103 -0
  50. package/asset/imageSrcSet.test.js.map +1 -0
  51. package/asset/index.d.ts +5 -0
  52. package/asset/index.js +5 -0
  53. package/asset/normalize.d.ts +24 -0
  54. package/asset/normalize.js +106 -0
  55. package/asset/normalize.js.map +1 -0
  56. package/asset/normalize.test.d.ts +1 -0
  57. package/asset/normalize.test.js +263 -0
  58. package/asset/normalize.test.js.map +1 -0
  59. package/asset/types.d.ts +2 -0
  60. package/asset/types.js +0 -0
  61. package/componentLoader/ComponentLoader.d.ts +16 -0
  62. package/componentLoader/ComponentLoader.js +0 -0
  63. package/componentLoader/RegistryOnlyComponentLoader.d.ts +9 -0
  64. package/componentLoader/RegistryOnlyComponentLoader.js +8 -0
  65. package/componentLoader/RegistryOnlyComponentLoader.js.map +1 -0
  66. package/componentLoader/createComponentLoader.d.ts +7 -0
  67. package/componentLoader/createComponentLoader.js +10 -0
  68. package/componentLoader/createComponentLoader.js.map +1 -0
  69. package/componentLoader/defaultComponentLoader.d.ts +7 -0
  70. package/componentLoader/defaultComponentLoader.js +8 -0
  71. package/componentLoader/defaultComponentLoader.js.map +1 -0
  72. package/componentLoader/index.d.ts +3 -0
  73. package/componentLoader/index.js +3 -0
  74. package/contentClientState.test.d.ts +1 -0
  75. package/contentClientState.test.js +384 -0
  76. package/contentClientState.test.js.map +1 -0
  77. package/contentEntry/ContentEntryBindingsResolver.d.ts +33 -0
  78. package/contentEntry/ContentEntryBindingsResolver.js +52 -0
  79. package/contentEntry/ContentEntryBindingsResolver.js.map +1 -0
  80. package/contentEntry/ContentEntryCache.d.ts +49 -0
  81. package/contentEntry/ContentEntryCache.js +51 -0
  82. package/contentEntry/ContentEntryCache.js.map +1 -0
  83. package/contentEntry/resolveContentEntry.d.ts +74 -0
  84. package/contentEntry/resolveContentEntry.js +53 -0
  85. package/contentEntry/resolveContentEntry.js.map +1 -0
  86. package/contentEntry/resolveContentEntry.test.d.ts +1 -0
  87. package/contentEntry/resolveContentEntry.test.js +213 -0
  88. package/contentEntry/resolveContentEntry.test.js.map +1 -0
  89. package/createComponent.d.ts +5 -0
  90. package/createComponent.js +32 -0
  91. package/createComponent.js.map +1 -0
  92. package/createContentClient.d.ts +17 -0
  93. package/createContentClient.js +16 -0
  94. package/createContentClient.js.map +1 -0
  95. package/createContentClient.test.d.ts +1 -0
  96. package/createContentClient.test.js +165 -0
  97. package/createContentClient.test.js.map +1 -0
  98. package/createInput.d.ts +10 -2
  99. package/createInput.js +8 -1
  100. package/createInput.js.map +1 -1
  101. package/dataProviders/ApiClient.d.ts +10 -5
  102. package/dataProviders/ApiClient.js +10 -10
  103. package/dataProviders/ApiClient.js.map +1 -1
  104. package/dataProviders/DefaultDataProvider.d.ts +4 -0
  105. package/dataProviders/DefaultDataProvider.js +35 -0
  106. package/dataProviders/DefaultDataProvider.js.map +1 -1
  107. package/dataProviders/GET_EXPERIMENT_PAUSED.d.ts +1 -0
  108. package/dataProviders/GET_EXPERIMENT_PAUSED.js +17 -0
  109. package/dataProviders/GET_EXPERIMENT_PAUSED.js.map +1 -0
  110. package/dataProviders/GET_PAGE_BY_ID.d.ts +1 -1
  111. package/dataProviders/GET_PAGE_BY_ID.js +2 -0
  112. package/dataProviders/GET_PAGE_BY_ID.js.map +1 -1
  113. package/dataProviders/GET_PAGE_BY_PATH.d.ts +1 -1
  114. package/dataProviders/GET_PAGE_BY_PATH.js +2 -0
  115. package/dataProviders/GET_PAGE_BY_PATH.js.map +1 -1
  116. package/dataProviders/GET_PAGE_EXPERIMENT.d.ts +1 -0
  117. package/dataProviders/GET_PAGE_EXPERIMENT.js +32 -0
  118. package/dataProviders/GET_PAGE_EXPERIMENT.js.map +1 -0
  119. package/dataProviders/GET_VARIANT_CONTENT.d.ts +1 -0
  120. package/dataProviders/GET_VARIANT_CONTENT.js +24 -0
  121. package/dataProviders/GET_VARIANT_CONTENT.js.map +1 -0
  122. package/dataProviders/NullDataProvider.d.ts +4 -0
  123. package/dataProviders/NullDataProvider.js +9 -0
  124. package/dataProviders/NullDataProvider.js.map +1 -1
  125. package/dataProviders/queries.test.d.ts +1 -0
  126. package/dataProviders/queries.test.js +45 -0
  127. package/dataProviders/queries.test.js.map +1 -0
  128. package/defaultBreakpoints.js +23 -3
  129. package/defaultBreakpoints.js.map +1 -1
  130. package/experiments/PostHogAnalyticsProvider.d.ts +31 -0
  131. package/experiments/PostHogAnalyticsProvider.js +28 -0
  132. package/experiments/PostHogAnalyticsProvider.js.map +1 -0
  133. package/experiments/analyticsProvider.d.ts +4 -0
  134. package/experiments/analyticsProvider.js +11 -0
  135. package/experiments/analyticsProvider.js.map +1 -0
  136. package/experiments/bucketing.d.ts +27 -0
  137. package/experiments/bucketing.js +91 -0
  138. package/experiments/bucketing.js.map +1 -0
  139. package/experiments/bucketing.test.d.ts +1 -0
  140. package/experiments/bucketing.test.js +183 -0
  141. package/experiments/bucketing.test.js.map +1 -0
  142. package/experiments/index.d.ts +5 -0
  143. package/experiments/index.js +5 -0
  144. package/experiments/render.d.ts +82 -0
  145. package/experiments/render.js +149 -0
  146. package/experiments/render.js.map +1 -0
  147. package/experiments/types.d.ts +108 -0
  148. package/experiments/types.js +4 -0
  149. package/experiments/types.js.map +1 -0
  150. package/headersProvider.d.ts +1 -2
  151. package/headersProvider.js.map +1 -1
  152. package/image/geometry.d.ts +54 -0
  153. package/image/geometry.js +112 -0
  154. package/image/geometry.js.map +1 -0
  155. package/image/geometry.test.d.ts +1 -0
  156. package/image/geometry.test.js +190 -0
  157. package/image/geometry.test.js.map +1 -0
  158. package/image/index.d.ts +3 -0
  159. package/image/index.js +3 -0
  160. package/image/presets.d.ts +6 -0
  161. package/image/presets.js +20 -0
  162. package/image/presets.js.map +1 -0
  163. package/image/types.d.ts +10 -0
  164. package/image/types.js +0 -0
  165. package/index.d.ts +12 -0
  166. package/index.js +12 -0
  167. package/jsonPatch.js +3 -3
  168. package/package.json +7 -6
  169. package/types/WebsiteBuilderTheme.d.ts +5 -0
  170. package/types.d.ts +75 -1
package/EditingSdk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"EditingSdk.js","sources":["../src/EditingSdk.ts"],"sourcesContent":["\"use client\";\nimport type {\n ComponentGroup,\n IContentSdk,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"./types.js\";\nimport { Messenger, MessageOrigin } from \"./messenger/index.js\";\nimport { logger } from \"./Logger.js\";\nimport { PreviewViewport } from \"./PreviewViewport.js\";\nimport { viewportManager } from \"./ViewportManager.js\";\nimport { componentRegistry } from \"./ComponentRegistry.js\";\nimport { functionConverter } from \"./FunctionConverter.js\";\nimport { documentStoreManager } from \"~/DocumentStoreManager.js\";\nimport type { DocumentStore } from \"~/DocumentStore.js\";\nimport { PreviewDocument } from \"./PreviewDocument.js\";\nimport { hashObject } from \"~/HashObject.js\";\nimport type { WebsiteBuilderTheme } from \"~/types/WebsiteBuilderTheme.js\";\n\nexport class EditingSdk implements IContentSdk {\n public readonly messenger: Messenger;\n private positionReportingEnabled = false;\n private previewViewport: PreviewViewport | null = null;\n private liveSdk: IContentSdk;\n private documentStore: DocumentStore<PublicPage>;\n private previewDocument: PreviewDocument;\n private lastBoxesHash = 0;\n\n constructor(liveSdk: IContentSdk, theme: WebsiteBuilderTheme) {\n this.liveSdk = liveSdk;\n\n const source = new MessageOrigin(() => window, window.location.origin);\n const target = new MessageOrigin(() => window.parent, this.getReferrerOrigin());\n\n this.previewDocument = PreviewDocument.createFromWindow();\n\n this.documentStore = documentStoreManager.getStore<PublicPage>(\n this.previewDocument.getId()\n );\n\n this.messenger = new Messenger(source, target, \"wb.editor.*\");\n\n componentRegistry.onRegister(reg => {\n this.messenger.send(\"preview.component.register\", reg.component.manifest);\n });\n\n this.setupListeners();\n\n this.messenger.send(\"preview.ready\", true);\n\n if (theme) {\n this.messenger.send(\"preview.theme\", { theme });\n }\n\n this.disableLinks();\n }\n\n public async getPage(path: string): Promise<PublicPage | null> {\n if (!this.previewDocument.matches({ type: \"page\", path })) {\n return this.liveSdk.getPage(path);\n }\n\n await this.documentStore.waitForDocument();\n return this.documentStore.getDocument();\n }\n\n public async listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.liveSdk.listPages(options);\n }\n\n registerComponentGroup(group: ComponentGroup) {\n this.messenger.send(\"preview.componentGroup.register\", {\n ...group,\n filter: group.filter ? functionConverter.serialize(group.filter) : undefined\n });\n }\n\n private getReferrerOrigin(): string {\n try {\n const searchParams = new URLSearchParams(window.location.search);\n return searchParams.get(\"wb.referrer\")!;\n } catch {\n return \"\";\n }\n }\n\n private setupListeners() {\n if (!this.messenger) {\n return;\n }\n\n this.messenger.on(\"document.set\", data => {\n this.documentStore.setDocument(data);\n\n if (!this.positionReportingEnabled) {\n // Initialize position reporting\n this.initPositionReporting();\n }\n });\n\n this.messenger.on(\"element.set\", data => {\n this.documentStore.updateElement(data.id, data.patch);\n });\n\n this.messenger.on(\"document.patch\", patch => {\n this.documentStore.applyPatch(patch);\n });\n }\n\n private initPositionReporting(): void {\n if (this.positionReportingEnabled) {\n return;\n }\n\n // Initialize element positions tracker\n this.previewViewport = new PreviewViewport();\n\n // Add event listeners\n viewportManager.onViewportChangeStart(() => {\n if (this.messenger) {\n this.messenger.send(\"preview.viewport.change.start\");\n }\n });\n\n viewportManager.onViewportChangeEnd(() => {\n if (this.messenger) {\n this.messenger.send(\"preview.viewport.change.end\");\n }\n });\n\n // Enable position reporting by default\n this.positionReportingEnabled = true;\n\n // Report positions periodically\n setInterval(() => this.reportBoxes(), 300);\n }\n\n private reportBoxes(): void {\n if (!this.messenger || !this.previewViewport) {\n logger.warn(\"No messenger or preview viewport. Skipping position reporting.\");\n return;\n }\n\n const newBoxes = this.previewViewport.getBoxes();\n const hash = hashObject.hash(newBoxes);\n if (hash === this.lastBoxesHash) {\n return;\n }\n\n this.lastBoxesHash = hash;\n // Send positions to the editor\n this.messenger.send(\"preview.viewport\", {\n boxes: this.previewViewport.getBoxes(),\n viewport: this.previewViewport.getViewport()\n });\n }\n\n private disableLinks() {\n // Intercept link clicks when we're in the editing mode (loaded via iframe from the editor).\n document.addEventListener(\n \"click\",\n event => {\n const target = event.target as HTMLElement;\n\n // Check if the clicked element or any of its ancestors is a link\n const anchor = target.closest(\"a\");\n\n if (anchor && anchor.href) {\n event.preventDefault();\n event.stopPropagation();\n }\n },\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture\n true\n );\n }\n}\n"],"names":["EditingSdk","liveSdk","theme","source","MessageOrigin","window","target","PreviewDocument","documentStoreManager","Messenger","componentRegistry","reg","path","options","group","functionConverter","undefined","searchParams","URLSearchParams","data","patch","PreviewViewport","viewportManager","setInterval","logger","newBoxes","hash","hashObject","document","event","anchor"],"mappings":"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"}
1
+ {"version":3,"file":"EditingSdk.js","sources":["../src/EditingSdk.ts"],"sourcesContent":["\"use client\";\nimport type {\n ComponentGroup,\n IContentSdk,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"./types.js\";\nimport { Messenger, MessageOrigin } from \"./messenger/index.js\";\nimport { logger } from \"./Logger.js\";\nimport { PreviewViewport } from \"./PreviewViewport.js\";\nimport { viewportManager } from \"./ViewportManager.js\";\nimport type { ComponentRegistry } from \"./ComponentRegistry.js\";\nimport { componentRegistry } from \"./ComponentRegistry.js\";\nimport { functionConverter } from \"./FunctionConverter.js\";\nimport type { DocumentStoreManager } from \"~/DocumentStoreManager.js\";\nimport { documentStoreManager } from \"~/DocumentStoreManager.js\";\nimport type { DocumentStore } from \"~/DocumentStore.js\";\nimport { PreviewDocument } from \"./PreviewDocument.js\";\nimport { hashObject } from \"~/HashObject.js\";\nimport type { WebsiteBuilderTheme } from \"~/types/WebsiteBuilderTheme.js\";\n\nexport type EditingSdkState = {\n componentRegistry?: ComponentRegistry;\n documentStoreManager?: DocumentStoreManager;\n};\n\nexport class EditingSdk implements IContentSdk {\n public readonly messenger: Messenger;\n private positionReportingEnabled = false;\n private previewViewport: PreviewViewport | null = null;\n private liveSdk: IContentSdk;\n private documentStore: DocumentStore<PublicPage>;\n private previewDocument: PreviewDocument;\n private lastBoxesHash = 0;\n\n constructor(liveSdk: IContentSdk, theme: WebsiteBuilderTheme, state: EditingSdkState = {}) {\n this.liveSdk = liveSdk;\n const registry = state.componentRegistry ?? componentRegistry;\n const stores = state.documentStoreManager ?? documentStoreManager;\n\n const source = new MessageOrigin(() => window, window.location.origin);\n const target = new MessageOrigin(() => window.parent, this.getReferrerOrigin());\n\n this.previewDocument = PreviewDocument.createFromWindow();\n\n this.documentStore = stores.getStore<PublicPage>(this.previewDocument.getId());\n\n this.messenger = new Messenger(source, target, \"wb.editor.*\");\n\n registry.onRegister(reg => {\n this.messenger.send(\"preview.component.register\", reg.component.manifest);\n });\n\n this.setupListeners();\n\n this.messenger.send(\"preview.ready\", true);\n\n if (theme) {\n this.messenger.send(\"preview.theme\", { theme });\n }\n\n this.disableLinks();\n }\n\n public async getPage(path: string): Promise<PublicPage | null> {\n if (!this.previewDocument.matches({ type: \"page\", path })) {\n return this.liveSdk.getPage(path);\n }\n\n await this.documentStore.waitForDocument();\n return this.documentStore.getDocument();\n }\n\n public async listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.liveSdk.listPages(options);\n }\n\n registerComponentGroup(group: ComponentGroup) {\n this.messenger.send(\"preview.componentGroup.register\", {\n ...group,\n filter: group.filter ? functionConverter.serialize(group.filter) : undefined\n });\n }\n\n private getReferrerOrigin(): string {\n try {\n const searchParams = new URLSearchParams(window.location.search);\n return searchParams.get(\"wb.referrer\")!;\n } catch {\n return \"\";\n }\n }\n\n private setupListeners() {\n if (!this.messenger) {\n return;\n }\n\n this.messenger.on(\"document.set\", data => {\n this.documentStore.setDocument(data);\n\n if (!this.positionReportingEnabled) {\n // Initialize position reporting\n this.initPositionReporting();\n }\n });\n\n this.messenger.on(\"element.set\", data => {\n this.documentStore.updateElement(data.id, data.patch);\n });\n\n this.messenger.on(\"document.patch\", patch => {\n this.documentStore.applyPatch(patch);\n });\n }\n\n private initPositionReporting(): void {\n if (this.positionReportingEnabled) {\n return;\n }\n\n // Initialize element positions tracker\n this.previewViewport = new PreviewViewport();\n\n // Add event listeners\n viewportManager.onViewportChangeStart(() => {\n if (this.messenger) {\n this.messenger.send(\"preview.viewport.change.start\");\n }\n });\n\n viewportManager.onViewportChangeEnd(() => {\n if (this.messenger) {\n this.messenger.send(\"preview.viewport.change.end\");\n }\n });\n\n // Enable position reporting by default\n this.positionReportingEnabled = true;\n\n // Report positions periodically\n setInterval(() => this.reportBoxes(), 300);\n }\n\n private reportBoxes(): void {\n if (!this.messenger || !this.previewViewport) {\n logger.warn(\"No messenger or preview viewport. Skipping position reporting.\");\n return;\n }\n\n const newBoxes = this.previewViewport.getBoxes();\n const hash = hashObject.hash(newBoxes);\n if (hash === this.lastBoxesHash) {\n return;\n }\n\n this.lastBoxesHash = hash;\n // Send positions to the editor\n this.messenger.send(\"preview.viewport\", {\n boxes: this.previewViewport.getBoxes(),\n viewport: this.previewViewport.getViewport()\n });\n }\n\n private disableLinks() {\n // Intercept link clicks when we're in the editing mode (loaded via iframe from the editor).\n document.addEventListener(\n \"click\",\n event => {\n const target = event.target as HTMLElement;\n\n // Check if the clicked element or any of its ancestors is a link\n const anchor = target.closest(\"a\");\n\n if (anchor && anchor.href) {\n event.preventDefault();\n event.stopPropagation();\n }\n },\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture\n true\n );\n }\n}\n"],"names":["EditingSdk","liveSdk","theme","state","registry","componentRegistry","stores","documentStoreManager","source","MessageOrigin","window","target","PreviewDocument","Messenger","reg","path","options","group","functionConverter","undefined","searchParams","URLSearchParams","data","patch","PreviewViewport","viewportManager","setInterval","logger","newBoxes","hash","hashObject","document","event","anchor"],"mappings":"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"}
package/ElementFactory.js CHANGED
@@ -26,12 +26,14 @@ class ElementFactory {
26
26
  defaultOperations.addElement(element),
27
27
  defaultOperations.addToParent(element, index)
28
28
  ];
29
+ const baseStyles = bindings?.styles ?? componentManifest.defaults?.styles ?? {};
30
+ const resolvedStyles = false === componentManifest.applyDefaultStyles ? baseStyles : withDefaultStyles(baseStyles);
29
31
  documentOps.push(...this.generateOperations({
30
32
  element,
31
33
  inputsAst,
32
34
  bindings: {
33
35
  inputs: bindings?.inputs ?? componentManifest.defaults?.inputs ?? {},
34
- styles: withDefaultStyles(bindings?.styles ?? componentManifest.defaults?.styles ?? {}),
36
+ styles: resolvedStyles,
35
37
  overrides: bindings?.overrides ?? {}
36
38
  },
37
39
  operations: defaultOperations
@@ -115,7 +117,10 @@ class ElementFactory {
115
117
  }
116
118
  getComponentManifest(componentName) {
117
119
  const manifest = this.components[componentName];
118
- if (!manifest) throw new Error(`Component "${componentName}" not registered.`);
120
+ if (!manifest) {
121
+ const registered = Object.keys(this.components).join(", ");
122
+ throw new Error(`Component "${componentName}" not registered. Registered components: ${registered}`);
123
+ }
119
124
  return manifest;
120
125
  }
121
126
  createElement(componentName, parentId, slot) {
@@ -1 +1 @@
1
- {"version":3,"file":"ElementFactory.js","sources":["../src/ElementFactory.ts"],"sourcesContent":["import { generateElementId } from \"./generateElementId.js\";\nimport type {\n DocumentElement,\n ComponentManifest,\n InputValueBinding,\n StyleValueBinding,\n CssProperties\n} from \"~/types.js\";\nimport { type IDocumentOperation, DocumentOperations } from \"./documentOperations/index.js\";\nimport {\n ComponentManifestToAstConverter,\n type InputAstNode\n} from \"./ComponentManifestToAstConverter.js\";\nimport { ComponentInputTraverser } from \"./ComponentInputTraverser.js\";\n\nconst defaultStyles = {\n display: \"flex\",\n flexDirection: \"column\"\n};\n\nconst withDefaultStyles = (styles: CssProperties) => {\n return { ...defaultStyles, ...styles };\n};\n\nexport interface ElementFactoryCreateElementParams {\n componentName: string;\n parentId: string;\n slot: string;\n index?: number;\n bindings?: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n overrides?: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsParams {\n element: DocumentElement;\n inputsAst: InputAstNode[];\n operations: ElementFactoryOperations;\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n overrides: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsFromBindingsParams {\n elementId: string;\n inputsAst: InputAstNode[];\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n };\n operations: ElementFactoryOperations;\n ignoreDefaultValues: boolean;\n}\n\ntype ElementFactoryOperations = {\n addElement: (element: DocumentElement) => IDocumentOperation;\n addToParent: (element: DocumentElement, index?: number) => IDocumentOperation;\n setInputBinding: (\n elementId: string,\n bindingPath: string,\n binding: InputValueBinding\n ) => IDocumentOperation;\n setStyleBinding: (\n elementId: string,\n bindingPath: string,\n binding: StyleValueBinding\n ) => IDocumentOperation;\n};\n\nconst defaultOperations: ElementFactoryOperations = {\n addElement: (element: DocumentElement) => {\n return new DocumentOperations.AddElement(element);\n },\n addToParent: (element: DocumentElement, index?: number) => {\n return new DocumentOperations.AddToParent(element, index);\n },\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalInputBinding(elementId, bindingPath, binding);\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalStyleBinding(elementId, bindingPath, binding);\n }\n};\n\nexport class ElementFactory {\n constructor(private components: Record<string, ComponentManifest>) {}\n\n public createElementFromComponent({\n componentName,\n parentId,\n slot,\n index,\n bindings\n }: ElementFactoryCreateElementParams) {\n const { element, componentManifest, inputsAst } = this.createElement(\n componentName,\n parentId,\n slot\n );\n\n const documentOps: IDocumentOperation[] = [\n defaultOperations.addElement(element),\n defaultOperations.addToParent(element, index)\n ];\n\n documentOps.push(\n ...this.generateOperations({\n element,\n inputsAst,\n bindings: {\n inputs: bindings?.inputs ?? componentManifest.defaults?.inputs ?? {},\n styles: withDefaultStyles(\n bindings?.styles ?? componentManifest.defaults?.styles ?? {}\n ),\n overrides: bindings?.overrides ?? {}\n },\n operations: defaultOperations\n })\n );\n\n return { element, operations: documentOps };\n }\n\n public generateOperations({\n element,\n inputsAst,\n bindings,\n operations\n }: GenerateOperationsParams): IDocumentOperation[] {\n const ops = this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues: false\n });\n\n if (bindings.overrides) {\n for (const [breakpoint, overrides] of Object.entries(bindings.overrides)) {\n ops.push(\n ...this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings: {\n inputs: overrides.inputs ?? {},\n styles: overrides.styles ?? {}\n },\n operations: {\n ...operations,\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetInputBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetStyleBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n }\n },\n ignoreDefaultValues: true\n })\n );\n }\n }\n\n return ops;\n }\n\n private generateOperationsFromBindings({\n elementId,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues\n }: GenerateOperationsFromBindingsParams): IDocumentOperation[] {\n const inputData = bindings.inputs;\n const traverser = new ComponentInputTraverser(inputsAst);\n\n const ops: IDocumentOperation[] = [];\n\n traverser.traverse(inputData, (node, path, value) => {\n const isCreateElement = value?.action === \"CreateElement\";\n const isList = node.list;\n const isObject = node.type === \"object\";\n\n if (isCreateElement) {\n const factory = new ElementFactory(this.components);\n const newElement = factory.createElementFromComponent({\n componentName: value.params.component,\n // undefined index = append to end of the slot array\n index: isList ? undefined : 0,\n slot: path,\n parentId: elementId,\n bindings: value.params\n });\n\n const newElementId = newElement.element.id;\n\n ops.push(...newElement.operations);\n\n if (isList) {\n // For list slots, AddToParent already manages the static array.\n // We only set metadata here.\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: newElementId,\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n }\n } else if (isObject && isList) {\n return;\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: ignoreDefaultValues\n ? undefined\n : (value ?? node.input.defaultValue),\n type: node.type,\n list: node.list,\n translatable: node.input.translatable\n })\n );\n }\n });\n\n // Process styles\n for (const key in bindings.styles) {\n ops.push(\n operations.setStyleBinding(elementId, key, {\n static: bindings.styles[key]\n })\n );\n }\n\n return ops;\n }\n\n private getComponentManifest(componentName: string): ComponentManifest {\n const manifest = this.components[componentName];\n if (!manifest) {\n throw new Error(`Component \"${componentName}\" not registered.`);\n }\n\n return manifest;\n }\n\n private createElement(componentName: string, parentId: string, slot: string) {\n const element: DocumentElement = {\n type: \"Webiny/Element\",\n id: generateElementId(),\n parent: { id: parentId, slot },\n component: { name: componentName }\n };\n\n const componentManifest = this.getComponentManifest(componentName);\n const inputsAst = ComponentManifestToAstConverter.convert(componentManifest.inputs ?? []);\n\n return {\n element,\n inputsAst,\n componentManifest\n };\n }\n}\n"],"names":["defaultStyles","withDefaultStyles","styles","defaultOperations","element","DocumentOperations","index","elementId","bindingPath","binding","ElementFactory","components","componentName","parentId","slot","bindings","componentManifest","inputsAst","documentOps","operations","ops","breakpoint","overrides","Object","ignoreDefaultValues","inputData","traverser","ComponentInputTraverser","node","path","value","isCreateElement","isList","isObject","factory","newElement","undefined","newElementId","generateElementId","key","manifest","Error","ComponentManifestToAstConverter"],"mappings":"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"}
1
+ {"version":3,"file":"ElementFactory.js","sources":["../src/ElementFactory.ts"],"sourcesContent":["import { generateElementId } from \"./generateElementId.js\";\nimport type {\n DocumentElement,\n ComponentManifest,\n InputValueBinding,\n StyleValueBinding,\n CssProperties\n} from \"~/types.js\";\nimport { type IDocumentOperation, DocumentOperations } from \"./documentOperations/index.js\";\nimport {\n ComponentManifestToAstConverter,\n type InputAstNode\n} from \"./ComponentManifestToAstConverter.js\";\nimport { ComponentInputTraverser } from \"./ComponentInputTraverser.js\";\n\nconst defaultStyles = {\n display: \"flex\",\n flexDirection: \"column\"\n};\n\nconst withDefaultStyles = (styles: CssProperties) => {\n return { ...defaultStyles, ...styles };\n};\n\nexport interface ElementFactoryCreateElementParams {\n componentName: string;\n parentId: string;\n slot: string;\n index?: number;\n bindings?: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n overrides?: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsParams {\n element: DocumentElement;\n inputsAst: InputAstNode[];\n operations: ElementFactoryOperations;\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n overrides: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsFromBindingsParams {\n elementId: string;\n inputsAst: InputAstNode[];\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n };\n operations: ElementFactoryOperations;\n ignoreDefaultValues: boolean;\n}\n\ntype ElementFactoryOperations = {\n addElement: (element: DocumentElement) => IDocumentOperation;\n addToParent: (element: DocumentElement, index?: number) => IDocumentOperation;\n setInputBinding: (\n elementId: string,\n bindingPath: string,\n binding: InputValueBinding\n ) => IDocumentOperation;\n setStyleBinding: (\n elementId: string,\n bindingPath: string,\n binding: StyleValueBinding\n ) => IDocumentOperation;\n};\n\nconst defaultOperations: ElementFactoryOperations = {\n addElement: (element: DocumentElement) => {\n return new DocumentOperations.AddElement(element);\n },\n addToParent: (element: DocumentElement, index?: number) => {\n return new DocumentOperations.AddToParent(element, index);\n },\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalInputBinding(elementId, bindingPath, binding);\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalStyleBinding(elementId, bindingPath, binding);\n }\n};\n\nexport class ElementFactory {\n constructor(private components: Record<string, ComponentManifest>) {}\n\n public createElementFromComponent({\n componentName,\n parentId,\n slot,\n index,\n bindings\n }: ElementFactoryCreateElementParams) {\n const { element, componentManifest, inputsAst } = this.createElement(\n componentName,\n parentId,\n slot\n );\n\n const documentOps: IDocumentOperation[] = [\n defaultOperations.addElement(element),\n defaultOperations.addToParent(element, index)\n ];\n\n const baseStyles = bindings?.styles ?? componentManifest.defaults?.styles ?? {};\n const resolvedStyles =\n componentManifest.applyDefaultStyles === false\n ? baseStyles\n : withDefaultStyles(baseStyles);\n\n documentOps.push(\n ...this.generateOperations({\n element,\n inputsAst,\n bindings: {\n inputs: bindings?.inputs ?? componentManifest.defaults?.inputs ?? {},\n styles: resolvedStyles,\n overrides: bindings?.overrides ?? {}\n },\n operations: defaultOperations\n })\n );\n\n return { element, operations: documentOps };\n }\n\n public generateOperations({\n element,\n inputsAst,\n bindings,\n operations\n }: GenerateOperationsParams): IDocumentOperation[] {\n const ops = this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues: false\n });\n\n if (bindings.overrides) {\n for (const [breakpoint, overrides] of Object.entries(bindings.overrides)) {\n ops.push(\n ...this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings: {\n inputs: overrides.inputs ?? {},\n styles: overrides.styles ?? {}\n },\n operations: {\n ...operations,\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetInputBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetStyleBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n }\n },\n ignoreDefaultValues: true\n })\n );\n }\n }\n\n return ops;\n }\n\n private generateOperationsFromBindings({\n elementId,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues\n }: GenerateOperationsFromBindingsParams): IDocumentOperation[] {\n const inputData = bindings.inputs;\n const traverser = new ComponentInputTraverser(inputsAst);\n\n const ops: IDocumentOperation[] = [];\n\n traverser.traverse(inputData, (node, path, value) => {\n const isCreateElement = value?.action === \"CreateElement\";\n const isList = node.list;\n const isObject = node.type === \"object\";\n\n if (isCreateElement) {\n const factory = new ElementFactory(this.components);\n const newElement = factory.createElementFromComponent({\n componentName: value.params.component,\n // undefined index = append to end of the slot array\n index: isList ? undefined : 0,\n slot: path,\n parentId: elementId,\n bindings: value.params\n });\n\n const newElementId = newElement.element.id;\n\n ops.push(...newElement.operations);\n\n if (isList) {\n // For list slots, AddToParent already manages the static array.\n // We only set metadata here.\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: newElementId,\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n }\n } else if (isObject && isList) {\n return;\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: ignoreDefaultValues\n ? undefined\n : (value ?? node.input.defaultValue),\n type: node.type,\n list: node.list,\n translatable: node.input.translatable\n })\n );\n }\n });\n\n // Process styles\n for (const key in bindings.styles) {\n ops.push(\n operations.setStyleBinding(elementId, key, {\n static: bindings.styles[key]\n })\n );\n }\n\n return ops;\n }\n\n private getComponentManifest(componentName: string): ComponentManifest {\n const manifest = this.components[componentName];\n if (!manifest) {\n const registered = Object.keys(this.components).join(\", \");\n throw new Error(\n `Component \"${componentName}\" not registered. Registered components: ${registered}`\n );\n }\n\n return manifest;\n }\n\n private createElement(componentName: string, parentId: string, slot: string) {\n const element: DocumentElement = {\n type: \"Webiny/Element\",\n id: generateElementId(),\n parent: { id: parentId, slot },\n component: { name: componentName }\n };\n\n const componentManifest = this.getComponentManifest(componentName);\n const inputsAst = ComponentManifestToAstConverter.convert(componentManifest.inputs ?? []);\n\n return {\n element,\n inputsAst,\n componentManifest\n };\n }\n}\n"],"names":["defaultStyles","withDefaultStyles","styles","defaultOperations","element","DocumentOperations","index","elementId","bindingPath","binding","ElementFactory","components","componentName","parentId","slot","bindings","componentManifest","inputsAst","documentOps","baseStyles","resolvedStyles","operations","ops","breakpoint","overrides","Object","ignoreDefaultValues","inputData","traverser","ComponentInputTraverser","node","path","value","isCreateElement","isList","isObject","factory","newElement","undefined","newElementId","generateElementId","key","manifest","registered","Error","ComponentManifestToAstConverter"],"mappings":"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"}
@@ -246,6 +246,108 @@ describe("ElementFactory", ()=>{
246
246
  step2.id
247
247
  ]);
248
248
  });
249
+ it("should keep every item of a primitive list (tags) from the component defaults", ()=>{
250
+ const pricing = {
251
+ name: "Custom/PricingPlans",
252
+ label: "Pricing Plans",
253
+ tags: [],
254
+ inputs: [
255
+ {
256
+ type: "text",
257
+ list: true,
258
+ renderer: "Webiny/Tags",
259
+ name: "highlights",
260
+ defaultValue: [
261
+ "Default"
262
+ ]
263
+ },
264
+ {
265
+ type: "object",
266
+ list: true,
267
+ renderer: "Webiny/Object",
268
+ name: "plans",
269
+ fields: [
270
+ {
271
+ type: "text",
272
+ renderer: "Webiny/Input",
273
+ name: "name"
274
+ },
275
+ {
276
+ type: "text",
277
+ list: true,
278
+ renderer: "Webiny/Tags",
279
+ name: "features",
280
+ defaultValue: [
281
+ "Feature one",
282
+ "Feature two"
283
+ ]
284
+ }
285
+ ]
286
+ }
287
+ ],
288
+ defaults: {
289
+ inputs: {
290
+ highlights: [
291
+ "Fast",
292
+ "Cheap"
293
+ ],
294
+ plans: [
295
+ {
296
+ name: "Hobby",
297
+ features: [
298
+ "Autocomplete",
299
+ "Limited AI integration"
300
+ ]
301
+ },
302
+ {
303
+ name: "Enterprise",
304
+ features: [
305
+ "Everything in Hobby",
306
+ "24/7 Support"
307
+ ]
308
+ }
309
+ ]
310
+ }
311
+ }
312
+ };
313
+ const factory = new ElementFactory({
314
+ ...components,
315
+ [pricing.name]: pricing
316
+ });
317
+ const result = factory.createElementFromComponent({
318
+ componentName: pricing.name,
319
+ parentId: "root",
320
+ slot: "children"
321
+ });
322
+ const document = {
323
+ state: {},
324
+ elements: {
325
+ root: {
326
+ type: "Webiny/Element",
327
+ id: "root",
328
+ component: {
329
+ name: "Webiny/Root"
330
+ }
331
+ }
332
+ },
333
+ bindings: {}
334
+ };
335
+ for (const op of result.operations)op.apply(document);
336
+ const inputs = document.bindings[result.element.id].inputs;
337
+ expect(inputs["highlights"]?.static).toEqual([
338
+ "Fast",
339
+ "Cheap"
340
+ ]);
341
+ expect(inputs["plans/0/name"]?.static).toBe("Hobby");
342
+ expect(inputs["plans/0/features"]?.static).toEqual([
343
+ "Autocomplete",
344
+ "Limited AI integration"
345
+ ]);
346
+ expect(inputs["plans/1/features"]?.static).toEqual([
347
+ "Everything in Hobby",
348
+ "24/7 Support"
349
+ ]);
350
+ });
249
351
  });
250
352
 
251
353
  //# sourceMappingURL=ElementFactory.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ElementFactory.test.js","sources":["../src/ElementFactory.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { ElementFactory } from \"./ElementFactory.js\";\nimport { DocumentOperations } from \"./documentOperations/index.js\";\nimport type { ComponentManifest, Document } from \"~/types.js\";\n\nconst components: Record<string, ComponentManifest> = {\n \"Webiny/Root\": {\n name: \"Webiny/Root\",\n label: \"Main Content\",\n tags: [],\n inputs: [\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n },\n \"FunnelBuilder/Funnel\": {\n name: \"FunnelBuilder/Funnel\",\n label: \"Funnel\",\n tags: [],\n inputs: [\n {\n type: \"object\",\n renderer: \"Webiny/Object\",\n name: \"fields\",\n list: true,\n fields: [],\n defaultValue: []\n },\n {\n type: \"number\",\n renderer: \"Webiny/Number\",\n name: \"activeStep\",\n label: \"Active Step\",\n defaultValue: 0\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"steps\"\n },\n {\n type: \"object\",\n renderer: \"FunnelBuilder/ConditionRulesRenderer\",\n name: \"conditionRules\",\n list: true,\n fields: []\n }\n ]\n },\n \"FunnelBuilder/Step\": {\n name: \"FunnelBuilder/Step\",\n label: \"Funnel Step\",\n tags: [],\n inputs: [\n {\n type: \"text\",\n renderer: \"Webiny/Input\",\n name: \"label\",\n label: \"Label\"\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n }\n};\n\n/**\n * Extract private fields from operation instances for assertion.\n */\nfunction serializeOp(op: any) {\n if (op instanceof DocumentOperations.AddElement) {\n return { type: \"AddElement\", element: op[\"element\"] };\n }\n if (op instanceof DocumentOperations.AddToParent) {\n return { type: \"AddToParent\", element: op[\"element\"], index: op[\"index\"] };\n }\n if (op instanceof DocumentOperations.SetGlobalInputBinding) {\n return {\n type: \"SetGlobalInputBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n if (op instanceof DocumentOperations.SetGlobalStyleBinding) {\n return {\n type: \"SetGlobalStyleBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n return op;\n}\n\ndescribe(\"ElementFactory\", () => {\n it(\"should produce correct operation sequence for a Funnel with two Steps\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const ops = result.operations.map(serializeOp);\n const funnelId = result.element.id;\n\n // 0: AddElement — Funnel\n expect(ops[0].type).toBe(\"AddElement\");\n expect(ops[0].element.component.name).toBe(\"FunnelBuilder/Funnel\");\n\n // 1: AddToParent — Funnel → root/children at index 0\n expect(ops[1].type).toBe(\"AddToParent\");\n expect(ops[1].element.id).toBe(funnelId);\n expect(ops[1].index).toBe(0);\n\n // 2: SetGlobalInputBinding — activeStep = 0\n expect(ops[2].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[2].elementId).toBe(funnelId);\n expect(ops[2].bindingPath).toBe(\"activeStep\");\n expect(ops[2].binding.static).toBe(0);\n\n // 3: AddElement — Step 1\n const step1Id = ops[3].element.id;\n expect(ops[3].type).toBe(\"AddElement\");\n expect(ops[3].element.component.name).toBe(\"FunnelBuilder/Step\");\n expect(ops[3].element.parent).toEqual({ id: funnelId, slot: \"steps\" });\n\n // 4: AddToParent — Step 1 (undefined = append)\n expect(ops[4].type).toBe(\"AddToParent\");\n expect(ops[4].element.id).toBe(step1Id);\n expect(ops[4].index).toBeUndefined();\n\n // 5: Step 1 label binding\n expect(ops[5].bindingPath).toBe(\"label\");\n expect(ops[5].binding.static).toBe(\"Step 1\");\n\n // 6: Step 1 children binding\n expect(ops[6].bindingPath).toBe(\"children\");\n expect(ops[6].binding.static).toEqual([]);\n\n // 7-8: Step 1 style bindings\n expect(ops[7].bindingPath).toBe(\"display\");\n expect(ops[8].bindingPath).toBe(\"flexDirection\");\n\n // 9: SetGlobalInputBinding — steps slot metadata (no static, AddToParent handles it)\n expect(ops[9].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[9].elementId).toBe(funnelId);\n expect(ops[9].bindingPath).toBe(\"steps\");\n expect(ops[9].binding.static).toBeUndefined();\n expect(ops[9].binding.type).toBe(\"slot\");\n expect(ops[9].binding.list).toBe(true);\n\n // 10: AddElement — Step 2\n expect(ops[10].element.component.name).toBe(\"FunnelBuilder/Step\");\n\n // 11: AddToParent — Step 2 (undefined = append)\n expect(ops[11].index).toBeUndefined();\n\n // 12-15: Step 2 bindings + styles\n expect(ops[12].binding.static).toBe(\"Final Step\");\n expect(ops[13].binding.static).toEqual([]);\n\n // 16: SetGlobalInputBinding — steps slot metadata (no static)\n expect(ops[16].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[16].elementId).toBe(funnelId);\n expect(ops[16].bindingPath).toBe(\"steps\");\n expect(ops[16].binding.static).toBeUndefined();\n\n // 17-18: Funnel style bindings\n expect(ops[17].bindingPath).toBe(\"display\");\n expect(ops[18].bindingPath).toBe(\"flexDirection\");\n\n expect(ops).toHaveLength(19);\n });\n\n it(\"should produce correct document after applying all operations\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const document = {\n state: {},\n elements: {\n root: {\n type: \"Webiny/Element\",\n id: \"root\",\n component: { name: \"Webiny/Root\" }\n }\n },\n bindings: {}\n } as unknown as Document;\n\n for (const op of result.operations) {\n op.apply(document);\n }\n\n const funnelId = result.element.id;\n\n // Both step elements exist in the document.\n const stepElements = Object.values(document.elements).filter(\n el => el.component.name === \"FunnelBuilder/Step\"\n );\n expect(stepElements).toHaveLength(2);\n\n // Both steps have their correct labels.\n const labels = stepElements.map(el => document.bindings[el.id]?.inputs?.label?.static);\n expect(labels).toContain(\"Step 1\");\n expect(labels).toContain(\"Final Step\");\n\n // The steps binding contains both step IDs in order.\n const stepsBinding = document.bindings[funnelId]?.inputs?.steps;\n expect(stepsBinding?.list).toBe(true);\n expect(stepsBinding?.type).toBe(\"slot\");\n expect(stepsBinding?.static).toHaveLength(2);\n\n const step1 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Step 1\"\n )!;\n const step2 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Final Step\"\n )!;\n expect(stepsBinding?.static).toEqual([step1.id, step2.id]);\n });\n});\n"],"names":["components","serializeOp","op","DocumentOperations","describe","it","factory","ElementFactory","result","ops","funnelId","expect","step1Id","document","stepElements","Object","el","labels","stepsBinding","step1","step2"],"mappings":";;;AAKA,MAAMA,aAAgD;IAClD,eAAe;QACX,MAAM;QACN,OAAO;QACP,MAAM,EAAE;QACR,QAAQ;YACJ;gBACI,MAAM;gBACN,MAAM;gBACN,UAAU;gBACV,cAAc,EAAE;gBAChB,MAAM;YACV;SACH;IACL;IACA,wBAAwB;QACpB,MAAM;QACN,OAAO;QACP,MAAM,EAAE;QACR,QAAQ;YACJ;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,MAAM;gBACN,QAAQ,EAAE;gBACV,cAAc,EAAE;YACpB;YACA;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,OAAO;gBACP,cAAc;YAClB;YACA;gBACI,MAAM;gBACN,MAAM;gBACN,UAAU;gBACV,cAAc,EAAE;gBAChB,MAAM;YACV;YACA;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,MAAM;gBACN,QAAQ,EAAE;YACd;SACH;IACL;IACA,sBAAsB;QAClB,MAAM;QACN,OAAO;QACP,MAAM,EAAE;QACR,QAAQ;YACJ;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,OAAO;YACX;YACA;gBACI,MAAM;gBACN,MAAM;gBACN,UAAU;gBACV,cAAc,EAAE;gBAChB,MAAM;YACV;SACH;IACL;AACJ;AAKA,SAASC,YAAYC,EAAO;IACxB,IAAIA,cAAcC,mBAAmB,UAAU,EAC3C,OAAO;QAAE,MAAM;QAAc,SAASD,EAAE,CAAC,UAAU;IAAC;IAExD,IAAIA,cAAcC,mBAAmB,WAAW,EAC5C,OAAO;QAAE,MAAM;QAAe,SAASD,EAAE,CAAC,UAAU;QAAE,OAAOA,EAAE,CAAC,QAAQ;IAAC;IAE7E,IAAIA,cAAcC,mBAAmB,qBAAqB,EACtD,OAAO;QACH,MAAM;QACN,WAAWD,EAAE,CAAC,YAAY;QAC1B,aAAaA,EAAE,CAAC,cAAc;QAC9B,SAASA,EAAE,CAAC,UAAU;IAC1B;IAEJ,IAAIA,cAAcC,mBAAmB,qBAAqB,EACtD,OAAO;QACH,MAAM;QACN,WAAWD,EAAE,CAAC,YAAY;QAC1B,aAAaA,EAAE,CAAC,cAAc;QAC9B,SAASA,EAAE,CAAC,UAAU;IAC1B;IAEJ,OAAOA;AACX;AAEAE,SAAS,kBAAkB;IACvBC,GAAG,yEAAyE;QACxE,MAAMC,UAAU,IAAIC,eAAeP;QACnC,MAAMQ,SAASF,QAAQ,0BAA0B,CAAC;YAC9C,eAAe;YACf,UAAU;YACV,MAAM;YACN,OAAO;YACP,UAAU;gBACN,QAAQ;oBACJ,QAAQ,EAAE;oBACV,YAAY;oBACZ,OAAO;wBACH;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAU,UAAU,EAAE;gCAAC;4BAC5C;wBACJ;wBACA;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAc,UAAU,EAAE;gCAAC;4BAChD;wBACJ;qBACH;gBACL;YACJ;QACJ;QAEA,MAAMG,MAAMD,OAAO,UAAU,CAAC,GAAG,CAACP;QAClC,MAAMS,WAAWF,OAAO,OAAO,CAAC,EAAE;QAGlCG,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;QAG3CE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAACC;QAC/BC,OAAOF,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;QAG1BE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAACC;QAC9BC,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;QAGnC,MAAMG,UAAUH,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE;QACjCE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;QAC3CE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;YAAE,IAAIC;YAAU,MAAM;QAAQ;QAGpEC,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAACG;QAC/BD,OAAOF,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa;QAGlCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;QAGnCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;QAGxCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAGhCE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAACC;QAC9BC,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa;QAC3CE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;QACjCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;QAGjCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;QAG5CE,OAAOF,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa;QAGnCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;QACpCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;QAGzCE,OAAOF,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC;QAC1BE,OAAOF,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAACC;QAC/BC,OAAOF,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC;QACjCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa;QAG5CE,OAAOF,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC;QACjCE,OAAOF,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC;QAEjCE,OAAOF,KAAK,YAAY,CAAC;IAC7B;IAEAJ,GAAG,iEAAiE;QAChE,MAAMC,UAAU,IAAIC,eAAeP;QACnC,MAAMQ,SAASF,QAAQ,0BAA0B,CAAC;YAC9C,eAAe;YACf,UAAU;YACV,MAAM;YACN,OAAO;YACP,UAAU;gBACN,QAAQ;oBACJ,QAAQ,EAAE;oBACV,YAAY;oBACZ,OAAO;wBACH;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAU,UAAU,EAAE;gCAAC;4BAC5C;wBACJ;wBACA;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAc,UAAU,EAAE;gCAAC;4BAChD;wBACJ;qBACH;gBACL;YACJ;QACJ;QAEA,MAAMO,WAAW;YACb,OAAO,CAAC;YACR,UAAU;gBACN,MAAM;oBACF,MAAM;oBACN,IAAI;oBACJ,WAAW;wBAAE,MAAM;oBAAc;gBACrC;YACJ;YACA,UAAU,CAAC;QACf;QAEA,KAAK,MAAMX,MAAMM,OAAO,UAAU,CAC9BN,GAAG,KAAK,CAACW;QAGb,MAAMH,WAAWF,OAAO,OAAO,CAAC,EAAE;QAGlC,MAAMM,eAAeC,OAAO,MAAM,CAACF,SAAS,QAAQ,EAAE,MAAM,CACxDG,CAAAA,KAAMA,AAAsB,yBAAtBA,GAAG,SAAS,CAAC,IAAI;QAE3BL,OAAOG,cAAc,YAAY,CAAC;QAGlC,MAAMG,SAASH,aAAa,GAAG,CAACE,CAAAA,KAAMH,SAAS,QAAQ,CAACG,GAAG,EAAE,CAAC,EAAE,QAAQ,OAAO;QAC/EL,OAAOM,QAAQ,SAAS,CAAC;QACzBN,OAAOM,QAAQ,SAAS,CAAC;QAGzB,MAAMC,eAAeL,SAAS,QAAQ,CAACH,SAAS,EAAE,QAAQ;QAC1DC,OAAOO,cAAc,MAAM,IAAI,CAAC;QAChCP,OAAOO,cAAc,MAAM,IAAI,CAAC;QAChCP,OAAOO,cAAc,QAAQ,YAAY,CAAC;QAE1C,MAAMC,QAAQL,aAAa,IAAI,CAC3BE,CAAAA,KAAMH,SAAS,QAAQ,CAACG,GAAG,EAAE,CAAC,EAAE,QAAQ,OAAO,WAAW;QAE9D,MAAMI,QAAQN,aAAa,IAAI,CAC3BE,CAAAA,KAAMH,SAAS,QAAQ,CAACG,GAAG,EAAE,CAAC,EAAE,QAAQ,OAAO,WAAW;QAE9DL,OAAOO,cAAc,QAAQ,OAAO,CAAC;YAACC,MAAM,EAAE;YAAEC,MAAM,EAAE;SAAC;IAC7D;AACJ"}
1
+ {"version":3,"file":"ElementFactory.test.js","sources":["../src/ElementFactory.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { ElementFactory } from \"./ElementFactory.js\";\nimport { DocumentOperations } from \"./documentOperations/index.js\";\nimport type { ComponentManifest, Document } from \"~/types.js\";\n\nconst components: Record<string, ComponentManifest> = {\n \"Webiny/Root\": {\n name: \"Webiny/Root\",\n label: \"Main Content\",\n tags: [],\n inputs: [\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n },\n \"FunnelBuilder/Funnel\": {\n name: \"FunnelBuilder/Funnel\",\n label: \"Funnel\",\n tags: [],\n inputs: [\n {\n type: \"object\",\n renderer: \"Webiny/Object\",\n name: \"fields\",\n list: true,\n fields: [],\n defaultValue: []\n },\n {\n type: \"number\",\n renderer: \"Webiny/Number\",\n name: \"activeStep\",\n label: \"Active Step\",\n defaultValue: 0\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"steps\"\n },\n {\n type: \"object\",\n renderer: \"FunnelBuilder/ConditionRulesRenderer\",\n name: \"conditionRules\",\n list: true,\n fields: []\n }\n ]\n },\n \"FunnelBuilder/Step\": {\n name: \"FunnelBuilder/Step\",\n label: \"Funnel Step\",\n tags: [],\n inputs: [\n {\n type: \"text\",\n renderer: \"Webiny/Input\",\n name: \"label\",\n label: \"Label\"\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n }\n};\n\n/**\n * Extract private fields from operation instances for assertion.\n */\nfunction serializeOp(op: any) {\n if (op instanceof DocumentOperations.AddElement) {\n return { type: \"AddElement\", element: op[\"element\"] };\n }\n if (op instanceof DocumentOperations.AddToParent) {\n return { type: \"AddToParent\", element: op[\"element\"], index: op[\"index\"] };\n }\n if (op instanceof DocumentOperations.SetGlobalInputBinding) {\n return {\n type: \"SetGlobalInputBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n if (op instanceof DocumentOperations.SetGlobalStyleBinding) {\n return {\n type: \"SetGlobalStyleBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n return op;\n}\n\ndescribe(\"ElementFactory\", () => {\n it(\"should produce correct operation sequence for a Funnel with two Steps\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const ops = result.operations.map(serializeOp);\n const funnelId = result.element.id;\n\n // 0: AddElement — Funnel\n expect(ops[0].type).toBe(\"AddElement\");\n expect(ops[0].element.component.name).toBe(\"FunnelBuilder/Funnel\");\n\n // 1: AddToParent — Funnel → root/children at index 0\n expect(ops[1].type).toBe(\"AddToParent\");\n expect(ops[1].element.id).toBe(funnelId);\n expect(ops[1].index).toBe(0);\n\n // 2: SetGlobalInputBinding — activeStep = 0\n expect(ops[2].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[2].elementId).toBe(funnelId);\n expect(ops[2].bindingPath).toBe(\"activeStep\");\n expect(ops[2].binding.static).toBe(0);\n\n // 3: AddElement — Step 1\n const step1Id = ops[3].element.id;\n expect(ops[3].type).toBe(\"AddElement\");\n expect(ops[3].element.component.name).toBe(\"FunnelBuilder/Step\");\n expect(ops[3].element.parent).toEqual({ id: funnelId, slot: \"steps\" });\n\n // 4: AddToParent — Step 1 (undefined = append)\n expect(ops[4].type).toBe(\"AddToParent\");\n expect(ops[4].element.id).toBe(step1Id);\n expect(ops[4].index).toBeUndefined();\n\n // 5: Step 1 label binding\n expect(ops[5].bindingPath).toBe(\"label\");\n expect(ops[5].binding.static).toBe(\"Step 1\");\n\n // 6: Step 1 children binding\n expect(ops[6].bindingPath).toBe(\"children\");\n expect(ops[6].binding.static).toEqual([]);\n\n // 7-8: Step 1 style bindings\n expect(ops[7].bindingPath).toBe(\"display\");\n expect(ops[8].bindingPath).toBe(\"flexDirection\");\n\n // 9: SetGlobalInputBinding — steps slot metadata (no static, AddToParent handles it)\n expect(ops[9].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[9].elementId).toBe(funnelId);\n expect(ops[9].bindingPath).toBe(\"steps\");\n expect(ops[9].binding.static).toBeUndefined();\n expect(ops[9].binding.type).toBe(\"slot\");\n expect(ops[9].binding.list).toBe(true);\n\n // 10: AddElement — Step 2\n expect(ops[10].element.component.name).toBe(\"FunnelBuilder/Step\");\n\n // 11: AddToParent — Step 2 (undefined = append)\n expect(ops[11].index).toBeUndefined();\n\n // 12-15: Step 2 bindings + styles\n expect(ops[12].binding.static).toBe(\"Final Step\");\n expect(ops[13].binding.static).toEqual([]);\n\n // 16: SetGlobalInputBinding — steps slot metadata (no static)\n expect(ops[16].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[16].elementId).toBe(funnelId);\n expect(ops[16].bindingPath).toBe(\"steps\");\n expect(ops[16].binding.static).toBeUndefined();\n\n // 17-18: Funnel style bindings\n expect(ops[17].bindingPath).toBe(\"display\");\n expect(ops[18].bindingPath).toBe(\"flexDirection\");\n\n expect(ops).toHaveLength(19);\n });\n\n it(\"should produce correct document after applying all operations\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const document = {\n state: {},\n elements: {\n root: {\n type: \"Webiny/Element\",\n id: \"root\",\n component: { name: \"Webiny/Root\" }\n }\n },\n bindings: {}\n } as unknown as Document;\n\n for (const op of result.operations) {\n op.apply(document);\n }\n\n const funnelId = result.element.id;\n\n // Both step elements exist in the document.\n const stepElements = Object.values(document.elements).filter(\n el => el.component.name === \"FunnelBuilder/Step\"\n );\n expect(stepElements).toHaveLength(2);\n\n // Both steps have their correct labels.\n const labels = stepElements.map(el => document.bindings[el.id]?.inputs?.label?.static);\n expect(labels).toContain(\"Step 1\");\n expect(labels).toContain(\"Final Step\");\n\n // The steps binding contains both step IDs in order.\n const stepsBinding = document.bindings[funnelId]?.inputs?.steps;\n expect(stepsBinding?.list).toBe(true);\n expect(stepsBinding?.type).toBe(\"slot\");\n expect(stepsBinding?.static).toHaveLength(2);\n\n const step1 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Step 1\"\n )!;\n const step2 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Final Step\"\n )!;\n expect(stepsBinding?.static).toEqual([step1.id, step2.id]);\n });\n it(\"should keep every item of a primitive list (tags) from the component defaults\", () => {\n const pricing: ComponentManifest = {\n name: \"Custom/PricingPlans\",\n label: \"Pricing Plans\",\n tags: [],\n inputs: [\n {\n type: \"text\",\n list: true,\n renderer: \"Webiny/Tags\",\n name: \"highlights\",\n defaultValue: [\"Default\"]\n },\n {\n type: \"object\",\n list: true,\n renderer: \"Webiny/Object\",\n name: \"plans\",\n fields: [\n { type: \"text\", renderer: \"Webiny/Input\", name: \"name\" },\n {\n type: \"text\",\n list: true,\n renderer: \"Webiny/Tags\",\n name: \"features\",\n defaultValue: [\"Feature one\", \"Feature two\"]\n }\n ]\n }\n ],\n defaults: {\n inputs: {\n highlights: [\"Fast\", \"Cheap\"],\n plans: [\n { name: \"Hobby\", features: [\"Autocomplete\", \"Limited AI integration\"] },\n { name: \"Enterprise\", features: [\"Everything in Hobby\", \"24/7 Support\"] }\n ]\n }\n }\n };\n\n const factory = new ElementFactory({ ...components, [pricing.name]: pricing });\n const result = factory.createElementFromComponent({\n componentName: pricing.name,\n parentId: \"root\",\n slot: \"children\"\n });\n\n const document = {\n state: {},\n elements: {\n root: {\n type: \"Webiny/Element\",\n id: \"root\",\n component: { name: \"Webiny/Root\" }\n }\n },\n bindings: {}\n } as unknown as Document;\n\n for (const op of result.operations) {\n op.apply(document);\n }\n\n const inputs = document.bindings[result.element.id]!.inputs!;\n expect(inputs[\"highlights\"]?.static).toEqual([\"Fast\", \"Cheap\"]);\n expect(inputs[\"plans/0/name\"]?.static).toBe(\"Hobby\");\n expect(inputs[\"plans/0/features\"]?.static).toEqual([\n \"Autocomplete\",\n \"Limited AI integration\"\n ]);\n expect(inputs[\"plans/1/features\"]?.static).toEqual([\"Everything in Hobby\", \"24/7 Support\"]);\n });\n});\n"],"names":["components","serializeOp","op","DocumentOperations","describe","it","factory","ElementFactory","result","ops","funnelId","expect","step1Id","document","stepElements","Object","el","labels","stepsBinding","step1","step2","pricing","inputs"],"mappings":"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"}
package/LiveSdk.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { GetPageOptions, IContentSdk, IDataProvider, ListPagesOptions, ListPagesResult, PublicPage } from "./types.js";
2
+ import type { DocumentStoreManager } from "./DocumentStoreManager.js";
2
3
  export declare class LiveSdk implements IContentSdk {
3
4
  private dataProvider;
4
- constructor(dataProvider: IDataProvider);
5
+ private documentStoreManager;
6
+ constructor(dataProvider: IDataProvider, stores?: DocumentStoreManager);
5
7
  getPage(path: string, options?: GetPageOptions): Promise<PublicPage | null>;
6
8
  listPages(options?: ListPagesOptions): Promise<ListPagesResult>;
7
9
  }
package/LiveSdk.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { documentStoreManager } from "./DocumentStoreManager.js";
2
2
  class LiveSdk {
3
- constructor(dataProvider){
3
+ constructor(dataProvider, stores = documentStoreManager){
4
4
  this.dataProvider = dataProvider;
5
+ this.documentStoreManager = stores;
5
6
  }
6
7
  async getPage(path, options) {
7
8
  const page = await this.dataProvider.getPageByPath(path, options);
8
- if (page) documentStoreManager.getStore(page.properties.id).setDocument(page);
9
+ if (page) this.documentStoreManager.getStore(page.properties.id).setDocument(page);
9
10
  return page;
10
11
  }
11
12
  listPages(options) {
package/LiveSdk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"LiveSdk.js","sources":["../src/LiveSdk.ts"],"sourcesContent":["import type {\n GetPageOptions,\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport { documentStoreManager } from \"~/DocumentStoreManager.js\";\n\nexport class LiveSdk implements IContentSdk {\n private dataProvider: IDataProvider;\n\n constructor(dataProvider: IDataProvider) {\n this.dataProvider = dataProvider;\n }\n\n async getPage(path: string, options?: GetPageOptions): Promise<PublicPage | null> {\n const page = await this.dataProvider.getPageByPath(path, options);\n if (page) {\n documentStoreManager.getStore<PublicPage>(page.properties.id).setDocument(page);\n }\n return page;\n }\n\n listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.dataProvider.listPages(options);\n }\n}\n"],"names":["LiveSdk","dataProvider","path","options","page","documentStoreManager"],"mappings":";AAUO,MAAMA;IAGT,YAAYC,YAA2B,CAAE;QACrC,IAAI,CAAC,YAAY,GAAGA;IACxB;IAEA,MAAM,QAAQC,IAAY,EAAEC,OAAwB,EAA8B;QAC9E,MAAMC,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAACF,MAAMC;QACzD,IAAIC,MACAC,qBAAqB,QAAQ,CAAaD,KAAK,UAAU,CAAC,EAAE,EAAE,WAAW,CAACA;QAE9E,OAAOA;IACX;IAEA,UAAUD,OAA0B,EAA4B;QAC5D,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAACA;IACvC;AACJ"}
1
+ {"version":3,"file":"LiveSdk.js","sources":["../src/LiveSdk.ts"],"sourcesContent":["import type {\n GetPageOptions,\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport type { DocumentStoreManager } from \"~/DocumentStoreManager.js\";\nimport { documentStoreManager } from \"~/DocumentStoreManager.js\";\n\nexport class LiveSdk implements IContentSdk {\n private dataProvider: IDataProvider;\n private documentStoreManager: DocumentStoreManager;\n\n constructor(dataProvider: IDataProvider, stores: DocumentStoreManager = documentStoreManager) {\n this.dataProvider = dataProvider;\n this.documentStoreManager = stores;\n }\n\n async getPage(path: string, options?: GetPageOptions): Promise<PublicPage | null> {\n const page = await this.dataProvider.getPageByPath(path, options);\n if (page) {\n this.documentStoreManager.getStore<PublicPage>(page.properties.id).setDocument(page);\n }\n return page;\n }\n\n listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.dataProvider.listPages(options);\n }\n}\n"],"names":["LiveSdk","dataProvider","stores","documentStoreManager","path","options","page"],"mappings":";AAWO,MAAMA;IAIT,YAAYC,YAA2B,EAAEC,SAA+BC,oBAAoB,CAAE;QAC1F,IAAI,CAAC,YAAY,GAAGF;QACpB,IAAI,CAAC,oBAAoB,GAAGC;IAChC;IAEA,MAAM,QAAQE,IAAY,EAAEC,OAAwB,EAA8B;QAC9E,MAAMC,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAACF,MAAMC;QACzD,IAAIC,MACA,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAaA,KAAK,UAAU,CAAC,EAAE,EAAE,WAAW,CAACA;QAEnF,OAAOA;IACX;IAEA,UAAUD,OAA0B,EAA4B;QAC5D,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAACA;IACvC;AACJ"}
@@ -1,8 +1,10 @@
1
+ import type { HeadersProvider } from "./headersProvider.js";
1
2
  export declare class PreviewDocument {
2
3
  readonly props: Record<string, string>;
3
4
  private constructor();
5
+ static createFromParams(params: string): PreviewDocument;
4
6
  static createFromWindow(): PreviewDocument;
5
- static createFromHeaders(): Promise<PreviewDocument>;
7
+ static createFromHeaders(provider?: HeadersProvider): Promise<PreviewDocument>;
6
8
  matches(params: Record<string, string>): boolean;
7
9
  getId(): string;
8
10
  }
@@ -9,12 +9,15 @@ class PreviewDocument {
9
9
  }
10
10
  });
11
11
  }
12
+ static createFromParams(params) {
13
+ return new PreviewDocument("wb", new URLSearchParams(params));
14
+ }
12
15
  static createFromWindow() {
13
16
  const query = new URLSearchParams(window.location.search);
14
17
  return new PreviewDocument("wb", query);
15
18
  }
16
- static async createFromHeaders() {
17
- const headersProvider = getHeadersProvider();
19
+ static async createFromHeaders(provider) {
20
+ const headersProvider = provider ?? getHeadersProvider();
18
21
  const headers = await headersProvider();
19
22
  const previewFromHeaders = headers.get("X-Preview-Params");
20
23
  return new PreviewDocument("wb", new URLSearchParams(previewFromHeaders ?? ""));
@@ -1 +1 @@
1
- {"version":3,"file":"PreviewDocument.js","sources":["../src/PreviewDocument.ts"],"sourcesContent":["import { getHeadersProvider } from \"./headersProvider.js\";\n\nexport class PreviewDocument {\n public readonly props: Record<string, string>;\n\n private constructor(prefix: string, query: URLSearchParams) {\n this.props = {};\n query.forEach((value, key) => {\n if (key.startsWith(prefix + \".\")) {\n const strippedKey = key.slice(prefix.length + 1); // +1 for the dot\n this.props[strippedKey] = value as string;\n }\n });\n }\n\n static createFromWindow(): PreviewDocument {\n const query = new URLSearchParams(window.location.search);\n return new PreviewDocument(\"wb\", query);\n }\n\n static async createFromHeaders(): Promise<PreviewDocument> {\n const headersProvider = getHeadersProvider();\n const headers = await headersProvider();\n const previewFromHeaders = headers.get(\"X-Preview-Params\");\n\n return new PreviewDocument(\"wb\", new URLSearchParams(previewFromHeaders ?? \"\"));\n }\n\n matches(params: Record<string, string>) {\n for (const [key, value] of Object.entries(params)) {\n if (this.props[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n getId() {\n return this.props.id;\n }\n}\n"],"names":["PreviewDocument","prefix","query","value","key","strippedKey","URLSearchParams","window","headersProvider","getHeadersProvider","headers","previewFromHeaders","params","Object"],"mappings":";AAEO,MAAMA;IAGT,YAAoBC,MAAc,EAAEC,KAAsB,CAAE;QACxD,IAAI,CAAC,KAAK,GAAG,CAAC;QACdA,MAAM,OAAO,CAAC,CAACC,OAAOC;YAClB,IAAIA,IAAI,UAAU,CAACH,SAAS,MAAM;gBAC9B,MAAMI,cAAcD,IAAI,KAAK,CAACH,OAAO,MAAM,GAAG;gBAC9C,IAAI,CAAC,KAAK,CAACI,YAAY,GAAGF;YAC9B;QACJ;IACJ;IAEA,OAAO,mBAAoC;QACvC,MAAMD,QAAQ,IAAII,gBAAgBC,OAAO,QAAQ,CAAC,MAAM;QACxD,OAAO,IAAIP,gBAAgB,MAAME;IACrC;IAEA,aAAa,oBAA8C;QACvD,MAAMM,kBAAkBC;QACxB,MAAMC,UAAU,MAAMF;QACtB,MAAMG,qBAAqBD,QAAQ,GAAG,CAAC;QAEvC,OAAO,IAAIV,gBAAgB,MAAM,IAAIM,gBAAgBK,sBAAsB;IAC/E;IAEA,QAAQC,MAA8B,EAAE;QACpC,KAAK,MAAM,CAACR,KAAKD,MAAM,IAAIU,OAAO,OAAO,CAACD,QACtC,IAAI,IAAI,CAAC,KAAK,CAACR,IAAI,KAAKD,OACpB,OAAO;QAGf,OAAO;IACX;IAEA,QAAQ;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE;IACxB;AACJ"}
1
+ {"version":3,"file":"PreviewDocument.js","sources":["../src/PreviewDocument.ts"],"sourcesContent":["import type { HeadersProvider } from \"./headersProvider.js\";\nimport { getHeadersProvider } from \"./headersProvider.js\";\n\nexport class PreviewDocument {\n public readonly props: Record<string, string>;\n\n private constructor(prefix: string, query: URLSearchParams) {\n this.props = {};\n query.forEach((value, key) => {\n if (key.startsWith(prefix + \".\")) {\n const strippedKey = key.slice(prefix.length + 1); // +1 for the dot\n this.props[strippedKey] = value as string;\n }\n });\n }\n\n static createFromParams(params: string): PreviewDocument {\n return new PreviewDocument(\"wb\", new URLSearchParams(params));\n }\n\n static createFromWindow(): PreviewDocument {\n const query = new URLSearchParams(window.location.search);\n return new PreviewDocument(\"wb\", query);\n }\n\n static async createFromHeaders(provider?: HeadersProvider): Promise<PreviewDocument> {\n const headersProvider = provider ?? getHeadersProvider();\n const headers = await headersProvider();\n const previewFromHeaders = headers.get(\"X-Preview-Params\");\n\n return new PreviewDocument(\"wb\", new URLSearchParams(previewFromHeaders ?? \"\"));\n }\n\n matches(params: Record<string, string>) {\n for (const [key, value] of Object.entries(params)) {\n if (this.props[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n getId() {\n return this.props.id;\n }\n}\n"],"names":["PreviewDocument","prefix","query","value","key","strippedKey","params","URLSearchParams","window","provider","headersProvider","getHeadersProvider","headers","previewFromHeaders","Object"],"mappings":";AAGO,MAAMA;IAGT,YAAoBC,MAAc,EAAEC,KAAsB,CAAE;QACxD,IAAI,CAAC,KAAK,GAAG,CAAC;QACdA,MAAM,OAAO,CAAC,CAACC,OAAOC;YAClB,IAAIA,IAAI,UAAU,CAACH,SAAS,MAAM;gBAC9B,MAAMI,cAAcD,IAAI,KAAK,CAACH,OAAO,MAAM,GAAG;gBAC9C,IAAI,CAAC,KAAK,CAACI,YAAY,GAAGF;YAC9B;QACJ;IACJ;IAEA,OAAO,iBAAiBG,MAAc,EAAmB;QACrD,OAAO,IAAIN,gBAAgB,MAAM,IAAIO,gBAAgBD;IACzD;IAEA,OAAO,mBAAoC;QACvC,MAAMJ,QAAQ,IAAIK,gBAAgBC,OAAO,QAAQ,CAAC,MAAM;QACxD,OAAO,IAAIR,gBAAgB,MAAME;IACrC;IAEA,aAAa,kBAAkBO,QAA0B,EAA4B;QACjF,MAAMC,kBAAkBD,YAAYE;QACpC,MAAMC,UAAU,MAAMF;QACtB,MAAMG,qBAAqBD,QAAQ,GAAG,CAAC;QAEvC,OAAO,IAAIZ,gBAAgB,MAAM,IAAIO,gBAAgBM,sBAAsB;IAC/E;IAEA,QAAQP,MAA8B,EAAE;QACpC,KAAK,MAAM,CAACF,KAAKD,MAAM,IAAIW,OAAO,OAAO,CAACR,QACtC,IAAI,IAAI,CAAC,KAAK,CAACF,IAAI,KAAKD,OACpB,OAAO;QAGf,OAAO;IACX;IAEA,QAAQ;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE;IACxB;AACJ"}
package/PreviewSdk.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import type { IContentSdk, IDataProvider, ListPagesOptions, ListPagesResult, PublicPage } from "./types.js";
2
+ import type { HeadersProvider } from "./headersProvider.js";
2
3
  export declare class PreviewSdk implements IContentSdk {
3
4
  private liveSdk;
4
5
  private dataProvider;
5
- constructor(dataProvider: IDataProvider, liveSdk: IContentSdk);
6
+ private previewParams;
7
+ private headersProvider;
8
+ constructor(dataProvider: IDataProvider, liveSdk: IContentSdk, previewParams?: string, headersProvider?: HeadersProvider);
6
9
  getPage(path: string): Promise<PublicPage | null>;
7
10
  listPages(options?: ListPagesOptions): Promise<ListPagesResult>;
8
11
  }
package/PreviewSdk.js CHANGED
@@ -1,11 +1,15 @@
1
1
  import { PreviewDocument } from "./PreviewDocument.js";
2
+ import { environment } from "./Environment.js";
2
3
  class PreviewSdk {
3
- constructor(dataProvider, liveSdk){
4
+ constructor(dataProvider, liveSdk, previewParams, headersProvider){
4
5
  this.liveSdk = liveSdk;
5
6
  this.dataProvider = dataProvider;
7
+ this.previewParams = previewParams;
8
+ this.headersProvider = headersProvider;
6
9
  }
7
10
  async getPage(path) {
8
- const previewDocument = await PreviewDocument.createFromHeaders();
11
+ let previewDocument;
12
+ previewDocument = this.previewParams ? PreviewDocument.createFromParams(this.previewParams) : environment.isClient() ? PreviewDocument.createFromWindow() : await PreviewDocument.createFromHeaders(this.headersProvider);
9
13
  if (!previewDocument.matches({
10
14
  type: "page",
11
15
  path
package/PreviewSdk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"PreviewSdk.js","sources":["../src/PreviewSdk.ts"],"sourcesContent":["import type {\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport { PreviewDocument } from \"~/PreviewDocument.js\";\n\nexport class PreviewSdk implements IContentSdk {\n private liveSdk: IContentSdk;\n private dataProvider: IDataProvider;\n\n constructor(dataProvider: IDataProvider, liveSdk: IContentSdk) {\n this.liveSdk = liveSdk;\n this.dataProvider = dataProvider;\n }\n\n async getPage(path: string): Promise<PublicPage | null> {\n const previewDocument = await PreviewDocument.createFromHeaders();\n if (!previewDocument.matches({ type: \"page\", path })) {\n return this.liveSdk.getPage(path);\n }\n return this.dataProvider.getPageById(previewDocument.getId());\n }\n\n async listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.liveSdk.listPages(options);\n }\n}\n"],"names":["PreviewSdk","dataProvider","liveSdk","path","previewDocument","PreviewDocument","options"],"mappings":";AASO,MAAMA;IAIT,YAAYC,YAA2B,EAAEC,OAAoB,CAAE;QAC3D,IAAI,CAAC,OAAO,GAAGA;QACf,IAAI,CAAC,YAAY,GAAGD;IACxB;IAEA,MAAM,QAAQE,IAAY,EAA8B;QACpD,MAAMC,kBAAkB,MAAMC,gBAAgB,iBAAiB;QAC/D,IAAI,CAACD,gBAAgB,OAAO,CAAC;YAAE,MAAM;YAAQD;QAAK,IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAACA;QAEhC,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAACC,gBAAgB,KAAK;IAC9D;IAEA,MAAM,UAAUE,OAA0B,EAA4B;QAClE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAACA;IAClC;AACJ"}
1
+ {"version":3,"file":"PreviewSdk.js","sources":["../src/PreviewSdk.ts"],"sourcesContent":["import type {\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport { PreviewDocument } from \"~/PreviewDocument.js\";\nimport { environment } from \"./Environment.js\";\nimport type { HeadersProvider } from \"./headersProvider.js\";\n\nexport class PreviewSdk implements IContentSdk {\n private liveSdk: IContentSdk;\n private dataProvider: IDataProvider;\n private previewParams: string | undefined;\n private headersProvider: HeadersProvider | undefined;\n\n constructor(\n dataProvider: IDataProvider,\n liveSdk: IContentSdk,\n previewParams?: string,\n headersProvider?: HeadersProvider\n ) {\n this.liveSdk = liveSdk;\n this.dataProvider = dataProvider;\n this.previewParams = previewParams;\n this.headersProvider = headersProvider;\n }\n\n async getPage(path: string): Promise<PublicPage | null> {\n let previewDocument: PreviewDocument;\n\n if (this.previewParams) {\n // Params were passed directly via init config (server-side SSR path).\n previewDocument = PreviewDocument.createFromParams(this.previewParams);\n } else if (environment.isClient()) {\n previewDocument = PreviewDocument.createFromWindow();\n } else {\n previewDocument = await PreviewDocument.createFromHeaders(this.headersProvider);\n }\n\n if (!previewDocument.matches({ type: \"page\", path })) {\n return this.liveSdk.getPage(path);\n }\n return this.dataProvider.getPageById(previewDocument.getId());\n }\n\n async listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.liveSdk.listPages(options);\n }\n}\n"],"names":["PreviewSdk","dataProvider","liveSdk","previewParams","headersProvider","path","previewDocument","PreviewDocument","environment","options"],"mappings":";;AAWO,MAAMA;IAMT,YACIC,YAA2B,EAC3BC,OAAoB,EACpBC,aAAsB,EACtBC,eAAiC,CACnC;QACE,IAAI,CAAC,OAAO,GAAGF;QACf,IAAI,CAAC,YAAY,GAAGD;QACpB,IAAI,CAAC,aAAa,GAAGE;QACrB,IAAI,CAAC,eAAe,GAAGC;IAC3B;IAEA,MAAM,QAAQC,IAAY,EAA8B;QACpD,IAAIC;QAIAA,kBAFA,IAAI,CAAC,aAAa,GAEAC,gBAAgB,gBAAgB,CAAC,IAAI,CAAC,aAAa,IAC9DC,YAAY,QAAQ,KACTD,gBAAgB,gBAAgB,KAEhC,MAAMA,gBAAgB,iBAAiB,CAAC,IAAI,CAAC,eAAe;QAGlF,IAAI,CAACD,gBAAgB,OAAO,CAAC;YAAE,MAAM;YAAQD;QAAK,IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAACA;QAEhC,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAACC,gBAAgB,KAAK;IAC9D;IAEA,MAAM,UAAUG,OAA0B,EAA4B;QAClE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAACA;IAClC;AACJ"}
package/ResizeObserver.js CHANGED
@@ -7,7 +7,7 @@ const flushResizeQueue = ()=>{
7
7
  resizeQueue = {};
8
8
  };
9
9
  let observer;
10
- observer = "u" < typeof window ? {
10
+ observer = "u" < typeof ResizeObserver ? {
11
11
  observe: ()=>{},
12
12
  unobserve: ()=>{}
13
13
  } : new ResizeObserver((entries)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"ResizeObserver.js","sources":["../src/ResizeObserver.ts"],"sourcesContent":["let resizeQueue: Record<string, DOMRect> = {};\nconst onChangeListeners: Array<() => void> = [];\n\nconst flushResizeQueue = () => {\n if (Object.entries(resizeQueue).length > 0) {\n onChangeListeners.forEach(entry => {\n entry();\n });\n }\n resizeQueue = {};\n};\n\nlet observer: any;\n\nif (typeof window === \"undefined\") {\n observer = {\n observe: () => {},\n unobserve: () => {}\n };\n} else {\n observer = new ResizeObserver(entries => {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const id = el.getAttribute(\"data-element-id\");\n if (id) {\n resizeQueue[id] = el.getBoundingClientRect();\n }\n }\n requestAnimationFrame(flushResizeQueue);\n });\n}\n\nexport const resizeObserver = {\n observe: (element: HTMLElement) => {\n observer.observe(element);\n },\n unobserve: (element: HTMLElement) => {\n observer.unobserve(element);\n },\n onChange: (cb: () => void) => {\n onChangeListeners.push(cb);\n }\n};\n"],"names":["resizeQueue","onChangeListeners","flushResizeQueue","Object","entry","observer","window","ResizeObserver","entries","el","id","requestAnimationFrame","resizeObserver","element","cb"],"mappings":"AAAA,IAAIA,cAAuC,CAAC;AAC5C,MAAMC,oBAAuC,EAAE;AAE/C,MAAMC,mBAAmB;IACrB,IAAIC,OAAO,OAAO,CAACH,aAAa,MAAM,GAAG,GACrCC,kBAAkB,OAAO,CAACG,CAAAA;QACtBA;IACJ;IAEJJ,cAAc,CAAC;AACnB;AAEA,IAAIK;AAGAA,WADA,AAAkB,MAAlB,OAAOC,SACI;IACP,SAAS,KAAO;IAChB,WAAW,KAAO;AACtB,IAEW,IAAIC,eAAeC,CAAAA;IAC1B,KAAK,MAAMJ,SAASI,QAAS;QACzB,MAAMC,KAAKL,MAAM,MAAM;QACvB,MAAMM,KAAKD,GAAG,YAAY,CAAC;QAC3B,IAAIC,IACAV,WAAW,CAACU,GAAG,GAAGD,GAAG,qBAAqB;IAElD;IACAE,sBAAsBT;AAC1B;AAGG,MAAMU,iBAAiB;IAC1B,SAAS,CAACC;QACNR,SAAS,OAAO,CAACQ;IACrB;IACA,WAAW,CAACA;QACRR,SAAS,SAAS,CAACQ;IACvB;IACA,UAAU,CAACC;QACPb,kBAAkB,IAAI,CAACa;IAC3B;AACJ"}
1
+ {"version":3,"file":"ResizeObserver.js","sources":["../src/ResizeObserver.ts"],"sourcesContent":["let resizeQueue: Record<string, DOMRect> = {};\nconst onChangeListeners: Array<() => void> = [];\n\nconst flushResizeQueue = () => {\n if (Object.entries(resizeQueue).length > 0) {\n onChangeListeners.forEach(entry => {\n entry();\n });\n }\n resizeQueue = {};\n};\n\nlet observer: any;\n\nif (typeof ResizeObserver === \"undefined\") {\n observer = {\n observe: () => {},\n unobserve: () => {}\n };\n} else {\n observer = new ResizeObserver(entries => {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const id = el.getAttribute(\"data-element-id\");\n if (id) {\n resizeQueue[id] = el.getBoundingClientRect();\n }\n }\n requestAnimationFrame(flushResizeQueue);\n });\n}\n\nexport const resizeObserver = {\n observe: (element: HTMLElement) => {\n observer.observe(element);\n },\n unobserve: (element: HTMLElement) => {\n observer.unobserve(element);\n },\n onChange: (cb: () => void) => {\n onChangeListeners.push(cb);\n }\n};\n"],"names":["resizeQueue","onChangeListeners","flushResizeQueue","Object","entry","observer","ResizeObserver","entries","el","id","requestAnimationFrame","resizeObserver","element","cb"],"mappings":"AAAA,IAAIA,cAAuC,CAAC;AAC5C,MAAMC,oBAAuC,EAAE;AAE/C,MAAMC,mBAAmB;IACrB,IAAIC,OAAO,OAAO,CAACH,aAAa,MAAM,GAAG,GACrCC,kBAAkB,OAAO,CAACG,CAAAA;QACtBA;IACJ;IAEJJ,cAAc,CAAC;AACnB;AAEA,IAAIK;AAGAA,WADA,AAA0B,MAA1B,OAAOC,iBACI;IACP,SAAS,KAAO;IAChB,WAAW,KAAO;AACtB,IAEW,IAAIA,eAAeC,CAAAA;IAC1B,KAAK,MAAMH,SAASG,QAAS;QACzB,MAAMC,KAAKJ,MAAM,MAAM;QACvB,MAAMK,KAAKD,GAAG,YAAY,CAAC;QAC3B,IAAIC,IACAT,WAAW,CAACS,GAAG,GAAGD,GAAG,qBAAqB;IAElD;IACAE,sBAAsBR;AAC1B;AAGG,MAAMS,iBAAiB;IAC1B,SAAS,CAACC;QACNP,SAAS,OAAO,CAACO;IACrB;IACA,WAAW,CAACA;QACRP,SAAS,SAAS,CAACO;IACvB;IACA,UAAU,CAACC;QACPZ,kBAAkB,IAAI,CAACY;IAC3B;AACJ"}
@@ -1,5 +1,6 @@
1
1
  import set from "lodash/set.js";
2
2
  import unset from "lodash/unset.js";
3
+ import { toJS } from "mobx";
3
4
  import { InheritedValueResolver } from "./InheritedValueResolver.js";
4
5
  import { StylesUpdater } from "./StylesUpdater.js";
5
6
  class StylesBindingsProcessor {
@@ -35,11 +36,11 @@ class StylesBindingsProcessor {
35
36
  }
36
37
  getBaseStyles() {
37
38
  const baseStyles = {
38
- styles: structuredClone(this.rawBindings.styles) ?? {},
39
+ styles: structuredClone(toJS(this.rawBindings.styles)) ?? {},
39
40
  overrides: {}
40
41
  };
41
42
  if (this.rawBindings.overrides) {
42
- for (const [bp, overrides] of Object.entries(this.rawBindings.overrides))if (overrides.styles) set(baseStyles, `overrides.${bp}.styles`, structuredClone(this.rawBindings.overrides[bp].styles));
43
+ for (const [bp, overrides] of Object.entries(this.rawBindings.overrides))if (overrides.styles) set(baseStyles, `overrides.${bp}.styles`, structuredClone(toJS(this.rawBindings.overrides[bp].styles)));
43
44
  }
44
45
  return baseStyles;
45
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"StylesBindingsProcessor.js","sources":["../src/StylesBindingsProcessor.ts"],"sourcesContent":["import set from \"lodash/set.js\";\nimport unset from \"lodash/unset.js\";\nimport type { DocumentElementBindings, DocumentElementStyleBindings } from \"~/types.js\";\nimport { InheritedValueResolver } from \"~/InheritedValueResolver.js\";\nimport { StylesUpdater } from \"./StylesUpdater.js\";\n\ntype DeepBindings = Record<string, any>;\n\nexport type ElementStylesBindings = {\n styles: DocumentElementStyleBindings;\n overrides: {\n [breakpoint: string]: {\n styles: DocumentElementStyleBindings;\n };\n };\n};\n\n/**\n * Handles deep-to-flat and flat-to-deep conversion of style bindings,\n * with breakpoint inheritance awareness.\n */\nexport class StylesBindingsProcessor {\n private breakpoints: string[];\n private rawBindings: DocumentElementBindings;\n private elementId: string;\n\n constructor(elementId: string, breakpoints: string[], rawBindings: DocumentElementBindings) {\n this.elementId = elementId;\n this.breakpoints = breakpoints;\n this.rawBindings = rawBindings;\n }\n\n /**\n * Converts flat style bindings into deep styles object (removes `.static`).\n */\n public toDeepStyles(styles: DocumentElementBindings[\"styles\"] = {}): DeepBindings {\n const result: DeepBindings = {};\n Object.keys(styles).forEach(key => {\n // @ts-expect-error Style keys cannot be indexed with a string.\n result[key] = styles[key].static;\n });\n return result;\n }\n\n /**\n * Flattens deep styles object into flat bindings with `.static` wrappers.\n * Skips overrides where the value matches inherited parent breakpoint.\n */\n public createUpdate(styles: DeepBindings, currentBreakpoint: string) {\n const rebuilt = this.getBaseStyles();\n const valueResolver = new InheritedValueResolver(this.breakpoints, breakpoint => {\n if (this.isBaseBreakpoint(breakpoint)) {\n return this.rawBindings.styles;\n }\n return this.rawBindings?.overrides?.[breakpoint]?.styles;\n });\n\n // Collect original keys for the breakpoint\n const originalStyles = this.isBaseBreakpoint(currentBreakpoint)\n ? this.rawBindings.styles || {}\n : this.rawBindings?.overrides?.[currentBreakpoint]?.styles || {};\n\n const newKeys = new Set(Object.keys(styles));\n const originalKeys = Object.keys(originalStyles);\n\n // Remove keys that no longer exist\n for (const key of originalKeys) {\n if (!newKeys.has(key)) {\n if (this.isBaseBreakpoint(currentBreakpoint)) {\n unset(rebuilt, `styles.${key}`);\n } else {\n unset(rebuilt, `overrides.${currentBreakpoint}.styles.${key}`);\n }\n }\n }\n\n for (const [key, value] of Object.entries(styles)) {\n if (this.isBaseBreakpoint(currentBreakpoint)) {\n set(rebuilt, `styles.${key}.static`, value);\n } else {\n const inheritedValue = valueResolver.getInheritedValue(key, currentBreakpoint);\n\n if (value !== inheritedValue) {\n set(rebuilt, `overrides.${currentBreakpoint}.styles.${key}.static`, value);\n } else {\n unset(rebuilt, `overrides.${currentBreakpoint}.styles.${key}`);\n }\n }\n }\n\n return new StylesUpdater(this.elementId, rebuilt);\n }\n\n private getBaseStyles(): ElementStylesBindings {\n const baseStyles: ElementStylesBindings = {\n styles: structuredClone(this.rawBindings.styles) ?? {},\n overrides: {}\n };\n\n // Clone existing overrides if present, to avoid losing breakpoint overrides\n if (this.rawBindings.overrides) {\n for (const [bp, overrides] of Object.entries(this.rawBindings.overrides)) {\n if (overrides.styles) {\n set(\n baseStyles,\n `overrides.${bp}.styles`,\n structuredClone(this.rawBindings.overrides[bp].styles)\n );\n }\n }\n }\n\n return baseStyles;\n }\n\n private isBaseBreakpoint(name: string): boolean {\n return this.breakpoints.indexOf(name) === 0;\n }\n}\n"],"names":["StylesBindingsProcessor","elementId","breakpoints","rawBindings","styles","result","Object","key","currentBreakpoint","rebuilt","valueResolver","InheritedValueResolver","breakpoint","originalStyles","newKeys","Set","originalKeys","unset","value","set","inheritedValue","StylesUpdater","baseStyles","structuredClone","bp","overrides","name"],"mappings":";;;;AAqBO,MAAMA;IAKT,YAAYC,SAAiB,EAAEC,WAAqB,EAAEC,WAAoC,CAAE;QACxF,IAAI,CAAC,SAAS,GAAGF;QACjB,IAAI,CAAC,WAAW,GAAGC;QACnB,IAAI,CAAC,WAAW,GAAGC;IACvB;IAKO,aAAaC,SAA4C,CAAC,CAAC,EAAgB;QAC9E,MAAMC,SAAuB,CAAC;QAC9BC,OAAO,IAAI,CAACF,QAAQ,OAAO,CAACG,CAAAA;YAExBF,MAAM,CAACE,IAAI,GAAGH,MAAM,CAACG,IAAI,CAAC,MAAM;QACpC;QACA,OAAOF;IACX;IAMO,aAAaD,MAAoB,EAAEI,iBAAyB,EAAE;QACjE,MAAMC,UAAU,IAAI,CAAC,aAAa;QAClC,MAAMC,gBAAgB,IAAIC,uBAAuB,IAAI,CAAC,WAAW,EAAEC,CAAAA;YAC/D,IAAI,IAAI,CAAC,gBAAgB,CAACA,aACtB,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM;YAElC,OAAO,IAAI,CAAC,WAAW,EAAE,WAAW,CAACA,WAAW,EAAE;QACtD;QAGA,MAAMC,iBAAiB,IAAI,CAAC,gBAAgB,CAACL,qBACvC,IAAI,CAAC,WAAW,CAAC,MAAM,IAAI,CAAC,IAC5B,IAAI,CAAC,WAAW,EAAE,WAAW,CAACA,kBAAkB,EAAE,UAAU,CAAC;QAEnE,MAAMM,UAAU,IAAIC,IAAIT,OAAO,IAAI,CAACF;QACpC,MAAMY,eAAeV,OAAO,IAAI,CAACO;QAGjC,KAAK,MAAMN,OAAOS,aACd,IAAI,CAACF,QAAQ,GAAG,CAACP,MACT,IAAI,CAAC,gBAAgB,CAACC,qBACtBS,MAAMR,SAAS,CAAC,OAAO,EAAEF,KAAK,IAE9BU,MAAMR,SAAS,CAAC,UAAU,EAAED,kBAAkB,QAAQ,EAAED,KAAK;QAKzE,KAAK,MAAM,CAACA,KAAKW,MAAM,IAAIZ,OAAO,OAAO,CAACF,QACtC,IAAI,IAAI,CAAC,gBAAgB,CAACI,oBACtBW,IAAIV,SAAS,CAAC,OAAO,EAAEF,IAAI,OAAO,CAAC,EAAEW;aAClC;YACH,MAAME,iBAAiBV,cAAc,iBAAiB,CAACH,KAAKC;YAE5D,IAAIU,UAAUE,gBACVD,IAAIV,SAAS,CAAC,UAAU,EAAED,kBAAkB,QAAQ,EAAED,IAAI,OAAO,CAAC,EAAEW;iBAEpED,MAAMR,SAAS,CAAC,UAAU,EAAED,kBAAkB,QAAQ,EAAED,KAAK;QAErE;QAGJ,OAAO,IAAIc,cAAc,IAAI,CAAC,SAAS,EAAEZ;IAC7C;IAEQ,gBAAuC;QAC3C,MAAMa,aAAoC;YACtC,QAAQC,gBAAgB,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;YACrD,WAAW,CAAC;QAChB;QAGA,IAAI,IAAI,CAAC,WAAW,CAAC,SAAS,EAC1B;YAAA,KAAK,MAAM,CAACC,IAAIC,UAAU,IAAInB,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EACnE,IAAImB,UAAU,MAAM,EAChBN,IACIG,YACA,CAAC,UAAU,EAAEE,GAAG,OAAO,CAAC,EACxBD,gBAAgB,IAAI,CAAC,WAAW,CAAC,SAAS,CAACC,GAAG,CAAC,MAAM;QAGjE;QAGJ,OAAOF;IACX;IAEQ,iBAAiBI,IAAY,EAAW;QAC5C,OAAO,AAAmC,MAAnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAACA;IACpC;AACJ"}
1
+ {"version":3,"file":"StylesBindingsProcessor.js","sources":["../src/StylesBindingsProcessor.ts"],"sourcesContent":["import set from \"lodash/set.js\";\nimport unset from \"lodash/unset.js\";\nimport { toJS } from \"mobx\";\nimport type { DocumentElementBindings, DocumentElementStyleBindings } from \"~/types.js\";\nimport { InheritedValueResolver } from \"~/InheritedValueResolver.js\";\nimport { StylesUpdater } from \"./StylesUpdater.js\";\n\ntype DeepBindings = Record<string, any>;\n\nexport type ElementStylesBindings = {\n styles: DocumentElementStyleBindings;\n overrides: {\n [breakpoint: string]: {\n styles: DocumentElementStyleBindings;\n };\n };\n};\n\n/**\n * Handles deep-to-flat and flat-to-deep conversion of style bindings,\n * with breakpoint inheritance awareness.\n */\nexport class StylesBindingsProcessor {\n private breakpoints: string[];\n private rawBindings: DocumentElementBindings;\n private elementId: string;\n\n constructor(elementId: string, breakpoints: string[], rawBindings: DocumentElementBindings) {\n this.elementId = elementId;\n this.breakpoints = breakpoints;\n this.rawBindings = rawBindings;\n }\n\n /**\n * Converts flat style bindings into deep styles object (removes `.static`).\n */\n public toDeepStyles(styles: DocumentElementBindings[\"styles\"] = {}): DeepBindings {\n const result: DeepBindings = {};\n Object.keys(styles).forEach(key => {\n // @ts-expect-error Style keys cannot be indexed with a string.\n result[key] = styles[key].static;\n });\n return result;\n }\n\n /**\n * Flattens deep styles object into flat bindings with `.static` wrappers.\n * Skips overrides where the value matches inherited parent breakpoint.\n */\n public createUpdate(styles: DeepBindings, currentBreakpoint: string) {\n const rebuilt = this.getBaseStyles();\n const valueResolver = new InheritedValueResolver(this.breakpoints, breakpoint => {\n if (this.isBaseBreakpoint(breakpoint)) {\n return this.rawBindings.styles;\n }\n return this.rawBindings?.overrides?.[breakpoint]?.styles;\n });\n\n // Collect original keys for the breakpoint\n const originalStyles = this.isBaseBreakpoint(currentBreakpoint)\n ? this.rawBindings.styles || {}\n : this.rawBindings?.overrides?.[currentBreakpoint]?.styles || {};\n\n const newKeys = new Set(Object.keys(styles));\n const originalKeys = Object.keys(originalStyles);\n\n // Remove keys that no longer exist\n for (const key of originalKeys) {\n if (!newKeys.has(key)) {\n if (this.isBaseBreakpoint(currentBreakpoint)) {\n unset(rebuilt, `styles.${key}`);\n } else {\n unset(rebuilt, `overrides.${currentBreakpoint}.styles.${key}`);\n }\n }\n }\n\n for (const [key, value] of Object.entries(styles)) {\n if (this.isBaseBreakpoint(currentBreakpoint)) {\n set(rebuilt, `styles.${key}.static`, value);\n } else {\n const inheritedValue = valueResolver.getInheritedValue(key, currentBreakpoint);\n\n if (value !== inheritedValue) {\n set(rebuilt, `overrides.${currentBreakpoint}.styles.${key}.static`, value);\n } else {\n unset(rebuilt, `overrides.${currentBreakpoint}.styles.${key}`);\n }\n }\n }\n\n return new StylesUpdater(this.elementId, rebuilt);\n }\n\n private getBaseStyles(): ElementStylesBindings {\n const baseStyles: ElementStylesBindings = {\n styles: structuredClone(toJS(this.rawBindings.styles)) ?? {},\n overrides: {}\n };\n\n // Clone existing overrides if present, to avoid losing breakpoint overrides\n if (this.rawBindings.overrides) {\n for (const [bp, overrides] of Object.entries(this.rawBindings.overrides)) {\n if (overrides.styles) {\n set(\n baseStyles,\n `overrides.${bp}.styles`,\n structuredClone(toJS(this.rawBindings.overrides[bp].styles))\n );\n }\n }\n }\n\n return baseStyles;\n }\n\n private isBaseBreakpoint(name: string): boolean {\n return this.breakpoints.indexOf(name) === 0;\n }\n}\n"],"names":["StylesBindingsProcessor","elementId","breakpoints","rawBindings","styles","result","Object","key","currentBreakpoint","rebuilt","valueResolver","InheritedValueResolver","breakpoint","originalStyles","newKeys","Set","originalKeys","unset","value","set","inheritedValue","StylesUpdater","baseStyles","structuredClone","toJS","bp","overrides","name"],"mappings":";;;;;AAsBO,MAAMA;IAKT,YAAYC,SAAiB,EAAEC,WAAqB,EAAEC,WAAoC,CAAE;QACxF,IAAI,CAAC,SAAS,GAAGF;QACjB,IAAI,CAAC,WAAW,GAAGC;QACnB,IAAI,CAAC,WAAW,GAAGC;IACvB;IAKO,aAAaC,SAA4C,CAAC,CAAC,EAAgB;QAC9E,MAAMC,SAAuB,CAAC;QAC9BC,OAAO,IAAI,CAACF,QAAQ,OAAO,CAACG,CAAAA;YAExBF,MAAM,CAACE,IAAI,GAAGH,MAAM,CAACG,IAAI,CAAC,MAAM;QACpC;QACA,OAAOF;IACX;IAMO,aAAaD,MAAoB,EAAEI,iBAAyB,EAAE;QACjE,MAAMC,UAAU,IAAI,CAAC,aAAa;QAClC,MAAMC,gBAAgB,IAAIC,uBAAuB,IAAI,CAAC,WAAW,EAAEC,CAAAA;YAC/D,IAAI,IAAI,CAAC,gBAAgB,CAACA,aACtB,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM;YAElC,OAAO,IAAI,CAAC,WAAW,EAAE,WAAW,CAACA,WAAW,EAAE;QACtD;QAGA,MAAMC,iBAAiB,IAAI,CAAC,gBAAgB,CAACL,qBACvC,IAAI,CAAC,WAAW,CAAC,MAAM,IAAI,CAAC,IAC5B,IAAI,CAAC,WAAW,EAAE,WAAW,CAACA,kBAAkB,EAAE,UAAU,CAAC;QAEnE,MAAMM,UAAU,IAAIC,IAAIT,OAAO,IAAI,CAACF;QACpC,MAAMY,eAAeV,OAAO,IAAI,CAACO;QAGjC,KAAK,MAAMN,OAAOS,aACd,IAAI,CAACF,QAAQ,GAAG,CAACP,MACT,IAAI,CAAC,gBAAgB,CAACC,qBACtBS,MAAMR,SAAS,CAAC,OAAO,EAAEF,KAAK,IAE9BU,MAAMR,SAAS,CAAC,UAAU,EAAED,kBAAkB,QAAQ,EAAED,KAAK;QAKzE,KAAK,MAAM,CAACA,KAAKW,MAAM,IAAIZ,OAAO,OAAO,CAACF,QACtC,IAAI,IAAI,CAAC,gBAAgB,CAACI,oBACtBW,IAAIV,SAAS,CAAC,OAAO,EAAEF,IAAI,OAAO,CAAC,EAAEW;aAClC;YACH,MAAME,iBAAiBV,cAAc,iBAAiB,CAACH,KAAKC;YAE5D,IAAIU,UAAUE,gBACVD,IAAIV,SAAS,CAAC,UAAU,EAAED,kBAAkB,QAAQ,EAAED,IAAI,OAAO,CAAC,EAAEW;iBAEpED,MAAMR,SAAS,CAAC,UAAU,EAAED,kBAAkB,QAAQ,EAAED,KAAK;QAErE;QAGJ,OAAO,IAAIc,cAAc,IAAI,CAAC,SAAS,EAAEZ;IAC7C;IAEQ,gBAAuC;QAC3C,MAAMa,aAAoC;YACtC,QAAQC,gBAAgBC,KAAK,IAAI,CAAC,WAAW,CAAC,MAAM,MAAM,CAAC;YAC3D,WAAW,CAAC;QAChB;QAGA,IAAI,IAAI,CAAC,WAAW,CAAC,SAAS,EAC1B;YAAA,KAAK,MAAM,CAACC,IAAIC,UAAU,IAAIpB,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EACnE,IAAIoB,UAAU,MAAM,EAChBP,IACIG,YACA,CAAC,UAAU,EAAEG,GAAG,OAAO,CAAC,EACxBF,gBAAgBC,KAAK,IAAI,CAAC,WAAW,CAAC,SAAS,CAACC,GAAG,CAAC,MAAM;QAGtE;QAGJ,OAAOH;IACX;IAEQ,iBAAiBK,IAAY,EAAW;QAC5C,OAAO,AAAmC,MAAnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAACA;IACpC;AACJ"}
package/Theme.js CHANGED
@@ -24,7 +24,8 @@ class Theme {
24
24
  colors: input?.colors ?? [],
25
25
  typography: {
26
26
  ...input?.typography
27
- }
27
+ },
28
+ allowCustomColors: input.allowCustomColors
28
29
  };
29
30
  }
30
31
  }
package/Theme.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Theme.js","sources":["../src/Theme.ts"],"sourcesContent":["import deepMerge from \"deepmerge\";\nimport type {\n Breakpoint,\n WebsiteBuilderTheme,\n WebsiteBuilderThemeInput\n} from \"~/types/WebsiteBuilderTheme.js\";\nimport { defaultBreakpoints } from \"~/defaultBreakpoints.js\";\n\nexport class Theme {\n static from(input: WebsiteBuilderThemeInput): WebsiteBuilderTheme {\n const { custom = {}, ...builtInOverrides } = input?.breakpoints ?? {};\n\n const mergedBreakpoints = deepMerge.all([\n {},\n defaultBreakpoints,\n builtInOverrides,\n custom\n ]) as WebsiteBuilderThemeInput[\"breakpoints\"];\n\n const breakpoints: Breakpoint[] = [];\n Object.entries(mergedBreakpoints ?? {}).forEach(([name, breakpoint]) => {\n breakpoints.push({\n name,\n ...(breakpoint as Omit<Breakpoint, \"name\">)\n });\n });\n\n return {\n css: input.css,\n fonts: input.fonts,\n fontSizes: input.fontSizes,\n breakpoints: breakpoints.sort((a, b) => b.maxWidth - a.maxWidth),\n colors: input?.colors ?? [],\n typography: {\n ...input?.typography\n }\n };\n }\n}\n"],"names":["Theme","input","custom","builtInOverrides","mergedBreakpoints","deepMerge","defaultBreakpoints","breakpoints","Object","name","breakpoint","a","b"],"mappings":";;AAQO,MAAMA;IACT,OAAO,KAAKC,KAA+B,EAAuB;QAC9D,MAAM,EAAEC,SAAS,CAAC,CAAC,EAAE,GAAGC,kBAAkB,GAAGF,OAAO,eAAe,CAAC;QAEpE,MAAMG,oBAAoBC,UAAAA,GAAa,CAAC;YACpC,CAAC;YACDC;YACAH;YACAD;SACH;QAED,MAAMK,cAA4B,EAAE;QACpCC,OAAO,OAAO,CAACJ,qBAAqB,CAAC,GAAG,OAAO,CAAC,CAAC,CAACK,MAAMC,WAAW;YAC/DH,YAAY,IAAI,CAAC;gBACbE;gBACA,GAAIC,UAAU;YAClB;QACJ;QAEA,OAAO;YACH,KAAKT,MAAM,GAAG;YACd,OAAOA,MAAM,KAAK;YAClB,WAAWA,MAAM,SAAS;YAC1B,aAAaM,YAAY,IAAI,CAAC,CAACI,GAAGC,IAAMA,EAAE,QAAQ,GAAGD,EAAE,QAAQ;YAC/D,QAAQV,OAAO,UAAU,EAAE;YAC3B,YAAY;gBACR,GAAGA,OAAO,UAAU;YACxB;QACJ;IACJ;AACJ"}
1
+ {"version":3,"file":"Theme.js","sources":["../src/Theme.ts"],"sourcesContent":["import deepMerge from \"deepmerge\";\nimport type {\n Breakpoint,\n WebsiteBuilderTheme,\n WebsiteBuilderThemeInput\n} from \"~/types/WebsiteBuilderTheme.js\";\nimport { defaultBreakpoints } from \"~/defaultBreakpoints.js\";\n\nexport class Theme {\n static from(input: WebsiteBuilderThemeInput): WebsiteBuilderTheme {\n const { custom = {}, ...builtInOverrides } = input?.breakpoints ?? {};\n\n const mergedBreakpoints = deepMerge.all([\n {},\n defaultBreakpoints,\n builtInOverrides,\n custom\n ]) as WebsiteBuilderThemeInput[\"breakpoints\"];\n\n const breakpoints: Breakpoint[] = [];\n Object.entries(mergedBreakpoints ?? {}).forEach(([name, breakpoint]) => {\n breakpoints.push({\n name,\n ...(breakpoint as Omit<Breakpoint, \"name\">)\n });\n });\n\n return {\n css: input.css,\n fonts: input.fonts,\n fontSizes: input.fontSizes,\n breakpoints: breakpoints.sort((a, b) => b.maxWidth - a.maxWidth),\n colors: input?.colors ?? [],\n typography: {\n ...input?.typography\n },\n allowCustomColors: input.allowCustomColors\n };\n }\n}\n"],"names":["Theme","input","custom","builtInOverrides","mergedBreakpoints","deepMerge","defaultBreakpoints","breakpoints","Object","name","breakpoint","a","b"],"mappings":";;AAQO,MAAMA;IACT,OAAO,KAAKC,KAA+B,EAAuB;QAC9D,MAAM,EAAEC,SAAS,CAAC,CAAC,EAAE,GAAGC,kBAAkB,GAAGF,OAAO,eAAe,CAAC;QAEpE,MAAMG,oBAAoBC,UAAAA,GAAa,CAAC;YACpC,CAAC;YACDC;YACAH;YACAD;SACH;QAED,MAAMK,cAA4B,EAAE;QACpCC,OAAO,OAAO,CAACJ,qBAAqB,CAAC,GAAG,OAAO,CAAC,CAAC,CAACK,MAAMC,WAAW;YAC/DH,YAAY,IAAI,CAAC;gBACbE;gBACA,GAAIC,UAAU;YAClB;QACJ;QAEA,OAAO;YACH,KAAKT,MAAM,GAAG;YACd,OAAOA,MAAM,KAAK;YAClB,WAAWA,MAAM,SAAS;YAC1B,aAAaM,YAAY,IAAI,CAAC,CAACI,GAAGC,IAAMA,EAAE,QAAQ,GAAGD,EAAE,QAAQ;YAC/D,QAAQV,OAAO,UAAU,EAAE;YAC3B,YAAY;gBACR,GAAGA,OAAO,UAAU;YACxB;YACA,mBAAmBA,MAAM,iBAAiB;QAC9C;IACJ;AACJ"}