@designcrowd/library.brand-page 5.17.6 → 5.17.7

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 (172) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-BI2KuOEF.js → CreatedOnBrandCrowd-de-de-BUQFMhZb.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-BYLJCjLJ.js → CreatedOnBrandCrowd-en-us-QS-5r4XI.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-Y_D6cuGE.js → CreatedOnBrandCrowd-es-es-CP2iH-n0.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CqCBRjYh.js → CreatedOnBrandCrowd-fr-ca-qfD4NmQZ.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CqCBRjYh.js → CreatedOnBrandCrowd-fr-fr-qfD4NmQZ.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-Bt0YF6DA.js → CreatedOnBrandCrowd-pt-br-CfmaB7zE.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-Bt0YF6DA.js → CreatedOnBrandCrowd-pt-pt-CfmaB7zE.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-CEk8FBEG.js → CreatedOnDcom-de-de-BxSUWfGN.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-DWw4Tm2L.js → CreatedOnDcom-en-us-CSeUdR6v.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-DpG-8o98.js → CreatedOnDcom-es-es-g7rCfAtP.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-CEla7RmR.js → CreatedOnDcom-fr-ca-Bh_BTb-O.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-DRXeVTlV.js → CreatedOnDcom-fr-fr-Clgd_Ujm.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-Bzu_phZc.js → CreatedOnDcom-pt-br-Dlgk0myX.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-DWax8Er7.js → CreatedOnDcom-pt-pt-B14APfrn.js} +1 -1
  15. package/lib/src/brand-page/models/brand-page-context.model.d.ts +2 -1
  16. package/lib/src/brand-page/models/brand-page-context.model.js +5 -0
  17. package/lib/src/brand-page/models/index.d.ts +1 -0
  18. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +62 -2
  19. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +1 -0
  20. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +60 -2
  21. package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +30 -1
  22. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +60 -2
  23. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +60 -2
  24. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +60 -2
  25. package/lib/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.mixin.d.ts +60 -2
  26. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +60 -2
  27. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +60 -2
  28. package/lib/src/brand-page-maker/composables/ai-chat/useAiChat.js +3 -1
  29. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +1 -1
  30. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.js +6 -6
  31. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.d.ts +2 -0
  32. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +258 -0
  33. package/lib/src/brand-page-maker/constants/sidebar-constant.d.ts +1 -0
  34. package/lib/src/brand-page-maker/constants/sidebar-constant.js +8 -0
  35. package/lib/src/brand-page-maker/stores/ai-thread/ai-website-builder-thread-store.d.ts +16 -0
  36. package/lib/src/brand-page-maker/stores/ai-thread/ai-website-builder-thread-store.js +14 -0
  37. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +62 -3
  38. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +2 -0
  39. package/lib/src/brand-page-maker/stores/index.d.ts +1 -0
  40. package/lib/src/brand-page-maker/stores/index.js +1 -0
  41. package/lib/src/brand-page-maker/stores/snapshot/snapshot-store.d.ts +2 -0
  42. package/lib/src/brand-page-maker/stores/snapshot/snapshot-store.js +9 -0
  43. package/lib/src/clients/ai-assistant-client.d.ts +8 -0
  44. package/lib/src/clients/ai-assistant-client.js +11 -1
  45. package/lib/src/composables/useSnapshot.js +33 -0
  46. package/lib/src/css/library.brand-page-brandCrowd.min.css +19 -6
  47. package/lib/src/css/library.brand-page-brandPage.min.css +19 -6
  48. package/lib/src/css/library.brand-page-designCom.min.css +19 -6
  49. package/lib/src/css/library.brand-page-preview.min.css +19 -6
  50. package/lib/src/index.d.ts +1 -0
  51. package/lib/src/index.mjs +42 -41
  52. package/lib/src/{lib-DODSa6QK.js → lib-pOkCQP0J.js} +28820 -26841
  53. package/lib/src/lib.js +1 -0
  54. package/lib/src/metadata-builder/ai-metadata-executor.d.ts +1 -1
  55. package/lib/src/metadata-builder/ai-metadata-executor.js +68 -7
  56. package/lib/src/metadata-builder/builders/add-page-builder.d.ts +14 -0
  57. package/lib/src/metadata-builder/builders/add-page-builder.js +66 -0
  58. package/lib/src/metadata-builder/builders/remove-page-builder.d.ts +13 -0
  59. package/lib/src/metadata-builder/builders/remove-page-builder.js +50 -0
  60. package/lib/src/metadata-builder/builders/section-builders/about-section-builder.d.ts +6 -0
  61. package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +17 -0
  62. package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.d.ts +6 -0
  63. package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +25 -0
  64. package/lib/src/metadata-builder/builders/section-builders/base-section-builder.d.ts +40 -0
  65. package/lib/src/metadata-builder/builders/section-builders/base-section-builder.js +108 -0
  66. package/lib/src/metadata-builder/builders/section-builders/button-section-builder.d.ts +6 -0
  67. package/lib/src/metadata-builder/builders/section-builders/button-section-builder.js +16 -0
  68. package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.d.ts +6 -0
  69. package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +27 -0
  70. package/lib/src/metadata-builder/builders/section-builders/delete-section-builder.d.ts +13 -0
  71. package/lib/src/metadata-builder/builders/section-builders/delete-section-builder.js +37 -0
  72. package/lib/src/metadata-builder/builders/section-builders/divider-section-builder.d.ts +6 -0
  73. package/lib/src/metadata-builder/builders/section-builders/divider-section-builder.js +16 -0
  74. package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.d.ts +6 -0
  75. package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.js +76 -0
  76. package/lib/src/metadata-builder/builders/section-builders/image-section-builder.d.ts +6 -0
  77. package/lib/src/metadata-builder/builders/section-builders/image-section-builder.js +16 -0
  78. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.d.ts +6 -0
  79. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +158 -0
  80. package/lib/src/metadata-builder/builders/section-builders/index.d.ts +17 -0
  81. package/lib/src/metadata-builder/builders/section-builders/index.js +17 -0
  82. package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.d.ts +6 -0
  83. package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +17 -0
  84. package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.d.ts +6 -0
  85. package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +16 -0
  86. package/lib/src/metadata-builder/builders/section-builders/move-section-builder.d.ts +15 -0
  87. package/lib/src/metadata-builder/builders/section-builders/move-section-builder.js +62 -0
  88. package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.d.ts +6 -0
  89. package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +16 -0
  90. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.d.ts +6 -0
  91. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +162 -0
  92. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.d.ts +6 -0
  93. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +50 -0
  94. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.d.ts +6 -0
  95. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +133 -0
  96. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.d.ts +6 -0
  97. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +154 -0
  98. package/lib/src/metadata-builder/builders/section-content-factory.d.ts +3 -0
  99. package/lib/src/metadata-builder/builders/section-content-factory.js +13 -0
  100. package/lib/src/metadata-builder/builders/section-field-maps.d.ts +12 -0
  101. package/lib/src/metadata-builder/builders/section-field-maps.js +180 -0
  102. package/lib/src/metadata-builder/builders/section-field-utils.d.ts +11 -0
  103. package/lib/src/metadata-builder/builders/section-field-utils.js +109 -0
  104. package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +6 -0
  105. package/lib/src/metadata-builder/helpers/rte.helpers.js +16 -1
  106. package/lib/src/metadata-builder/metadata-executor.js +71 -1
  107. package/lib/src/metadata-builder/models.d.ts +54 -0
  108. package/lib/src/metadata-builder/models.js +58 -0
  109. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +51 -3
  110. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.js +110 -13
  111. package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +285 -0
  112. package/lib/src/metadata-builder/parsers/section-tool-arguments.js +7 -0
  113. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +60 -2
  114. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +60 -2
  115. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +60 -2
  116. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +60 -2
  117. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +90 -3
  118. package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +61 -2
  119. package/lib/src/shared/side-bar/components/SideBar.mixin.js +6 -0
  120. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +60 -2
  121. package/lib/src/utils/minify-brand-page-metadata.d.ts +22 -0
  122. package/lib/src/utils/minify-brand-page-metadata.js +344 -0
  123. package/package.json +1 -1
  124. package/src/brand-page/models/brand-page-context.model.ts +12 -3
  125. package/src/brand-page/models/index.ts +1 -0
  126. package/src/brand-page-maker/components/ai-website-builder/AiWebsiteBuilder.vue +80 -0
  127. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +4 -0
  128. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +9 -2
  129. package/src/brand-page-maker/composables/ai-chat/useAiChat.ts +4 -1
  130. package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +6 -6
  131. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +363 -0
  132. package/src/brand-page-maker/constants/sidebar-constant.ts +8 -0
  133. package/src/brand-page-maker/stores/ai-thread/ai-website-builder-thread-store.ts +19 -0
  134. package/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.ts +3 -1
  135. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +4 -0
  136. package/src/brand-page-maker/stores/index.ts +1 -0
  137. package/src/brand-page-maker/stores/snapshot/snapshot-store.ts +12 -0
  138. package/src/clients/ai-assistant-client.ts +17 -1
  139. package/src/composables/useSnapshot.ts +47 -0
  140. package/src/lib.ts +4 -0
  141. package/src/metadata-builder/ai-metadata-executor.ts +116 -26
  142. package/src/metadata-builder/builders/add-page-builder.ts +98 -0
  143. package/src/metadata-builder/builders/remove-page-builder.ts +83 -0
  144. package/src/metadata-builder/builders/section-builders/about-section-builder.ts +28 -0
  145. package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +45 -0
  146. package/src/metadata-builder/builders/section-builders/base-section-builder.ts +160 -0
  147. package/src/metadata-builder/builders/section-builders/button-section-builder.ts +24 -0
  148. package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +43 -0
  149. package/src/metadata-builder/builders/section-builders/delete-section-builder.ts +63 -0
  150. package/src/metadata-builder/builders/section-builders/divider-section-builder.ts +27 -0
  151. package/src/metadata-builder/builders/section-builders/image-gallery-builder.ts +111 -0
  152. package/src/metadata-builder/builders/section-builders/image-section-builder.ts +24 -0
  153. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +223 -0
  154. package/src/metadata-builder/builders/section-builders/index.ts +21 -0
  155. package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +29 -0
  156. package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +27 -0
  157. package/src/metadata-builder/builders/section-builders/move-section-builder.ts +100 -0
  158. package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +27 -0
  159. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +231 -0
  160. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +79 -0
  161. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +194 -0
  162. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +234 -0
  163. package/src/metadata-builder/builders/section-content-factory.ts +20 -0
  164. package/src/metadata-builder/builders/section-field-maps.ts +235 -0
  165. package/src/metadata-builder/builders/section-field-utils.ts +157 -0
  166. package/src/metadata-builder/helpers/rte.helpers.ts +23 -1
  167. package/src/metadata-builder/metadata-executor.ts +96 -4
  168. package/src/metadata-builder/models.ts +62 -0
  169. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +141 -17
  170. package/src/metadata-builder/parsers/section-tool-arguments.ts +417 -0
  171. package/src/shared/side-bar/components/SideBar.mixin.ts +10 -0
  172. package/src/utils/minify-brand-page-metadata.ts +407 -0
@@ -0,0 +1,76 @@
1
+ import { applyScalarFields } from '../section-field-utils';
2
+ import { BaseSectionBuilder } from './base-section-builder';
3
+ const applyGalleryType = (content, galleryType) => {
4
+ content.galleryStyles = {
5
+ ...(content.galleryStyles || {}),
6
+ galleryType: galleryType,
7
+ };
8
+ };
9
+ const applyGalleryImages = (content, images) => {
10
+ content.images = images
11
+ .filter((img) => !!img.image_url)
12
+ .map((img) => ({
13
+ imageUrl: img.image_url || '',
14
+ imageTitle: img.caption || '',
15
+ width: 0,
16
+ height: 0,
17
+ mediaType: 'image',
18
+ imageLink: '',
19
+ }));
20
+ };
21
+ const mergeGalleryImages = (content, images, replaceAll) => {
22
+ const updatedImages = images
23
+ .map((img, index) => {
24
+ const existing = content.images?.[index];
25
+ const imageUrl = img.image_url ?? existing?.imageUrl ?? '';
26
+ return {
27
+ ...(existing || {}),
28
+ imageUrl,
29
+ imageTitle: img.caption ?? existing?.imageTitle ?? '',
30
+ width: existing?.width ?? 0,
31
+ height: existing?.height ?? 0,
32
+ mediaType: existing?.mediaType ?? 'image',
33
+ imageLink: existing?.imageLink ?? '',
34
+ };
35
+ })
36
+ .filter((item) => !!item.imageUrl);
37
+ if (!replaceAll && content.images && content.images.length > images.length) {
38
+ const extras = content.images.slice(images.length).map((img) => ({
39
+ imageUrl: img.imageUrl ?? '',
40
+ imageTitle: img.imageTitle ?? '',
41
+ width: img.width ?? 0,
42
+ height: img.height ?? 0,
43
+ mediaType: img.mediaType ?? 'image',
44
+ imageLink: img.imageLink ?? '',
45
+ }));
46
+ updatedImages.push(...extras);
47
+ }
48
+ content.images = updatedImages;
49
+ };
50
+ export class ImageGalleryBuilder extends BaseSectionBuilder {
51
+ async buildAsync(model) {
52
+ this.log('Build called');
53
+ const validation = await this.validateAsync();
54
+ if (validation.errors.length) {
55
+ return { request: this.request, model, errors: validation.errors };
56
+ }
57
+ const resolved = this.resolveContent(model);
58
+ if ('error' in resolved)
59
+ return resolved.error;
60
+ const content = resolved.content;
61
+ applyScalarFields(content, this.args, this.sectionType);
62
+ const args = this.args;
63
+ if (args.gallery_type) {
64
+ applyGalleryType(content, args.gallery_type);
65
+ }
66
+ if (args.images && Array.isArray(args.images)) {
67
+ if (this.mode === 'create') {
68
+ applyGalleryImages(content, args.images);
69
+ }
70
+ else {
71
+ mergeGalleryImages(content, args.images, !!args._replace_items);
72
+ }
73
+ }
74
+ return { request: this.request, model };
75
+ }
76
+ }
@@ -0,0 +1,6 @@
1
+ import type { ImageContent, BrandPageModel } from '../../../brand-page/models';
2
+ import type { BuilderResult } from '../../models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ export declare class ImageSectionBuilder extends BaseSectionBuilder<ImageContent> {
5
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
+ }
@@ -0,0 +1,16 @@
1
+ import { applyScalarFields } from '../section-field-utils';
2
+ import { BaseSectionBuilder } from './base-section-builder';
3
+ export class ImageSectionBuilder extends BaseSectionBuilder {
4
+ async buildAsync(model) {
5
+ this.log('Build called');
6
+ const validation = await this.validateAsync();
7
+ if (validation.errors.length) {
8
+ return { request: this.request, model, errors: validation.errors };
9
+ }
10
+ const resolved = this.resolveContent(model);
11
+ if ('error' in resolved)
12
+ return resolved.error;
13
+ applyScalarFields(resolved.content, this.args, this.sectionType);
14
+ return { request: this.request, model };
15
+ }
16
+ }
@@ -0,0 +1,6 @@
1
+ import type { ImagesSectionContent, BrandPageModel } from '../../../brand-page/models';
2
+ import type { BuilderResult } from '../../models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ export declare class ImagesSectionBuilder extends BaseSectionBuilder<ImagesSectionContent> {
5
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
+ }
@@ -0,0 +1,158 @@
1
+ import { applyScalarFields, applyStyleFields, applyRTEStyles, } from '../section-field-utils';
2
+ import { BaseSectionBuilder } from './base-section-builder';
3
+ const applyImageItems = (content, items) => {
4
+ content.items = items
5
+ .filter((item) => !!item.image_url)
6
+ .map((item, index) => ({
7
+ imageUrl: item.image_url || '',
8
+ imageTitle: '',
9
+ width: 0,
10
+ height: 0,
11
+ mediaType: 'image',
12
+ imageLink: '',
13
+ title: item.heading || '',
14
+ paragraph: item.text || '',
15
+ itemsId: index,
16
+ colorReplacements: [],
17
+ }));
18
+ };
19
+ const mergeImageItems = (content, items, replaceAll) => {
20
+ const hasIndexedItems = items.some((item) => item.item_index !== undefined);
21
+ if (hasIndexedItems) {
22
+ for (const item of items) {
23
+ const targetIndex = item.item_index;
24
+ if (targetIndex === undefined ||
25
+ targetIndex < 0 ||
26
+ !content.items?.[targetIndex])
27
+ continue;
28
+ const existing = content.items[targetIndex];
29
+ if (item.image_url !== undefined)
30
+ existing.imageUrl = item.image_url;
31
+ if (item.heading !== undefined)
32
+ existing.title = item.heading;
33
+ if (item.text !== undefined)
34
+ existing.paragraph = item.text;
35
+ }
36
+ return;
37
+ }
38
+ const updatedItems = items
39
+ .map((item, index) => {
40
+ const existing = content.items?.[index];
41
+ return {
42
+ ...(existing || {}),
43
+ imageUrl: item.image_url ?? existing?.imageUrl ?? '',
44
+ imageTitle: existing?.imageTitle ?? '',
45
+ width: existing?.width ?? 0,
46
+ height: existing?.height ?? 0,
47
+ mediaType: existing?.mediaType ?? 'image',
48
+ imageLink: existing?.imageLink ?? '',
49
+ title: item.heading ?? existing?.title ?? '',
50
+ paragraph: item.text ?? existing?.paragraph ?? '',
51
+ itemsId: existing?.itemsId ?? index,
52
+ colorReplacements: existing?.colorReplacements ?? [],
53
+ };
54
+ })
55
+ .filter((item) => !!item.imageUrl);
56
+ if (!replaceAll && content.items && content.items.length > items.length) {
57
+ const remaining = content.items.slice(items.length);
58
+ updatedItems.push(...remaining);
59
+ }
60
+ content.items = updatedItems;
61
+ };
62
+ export class ImagesSectionBuilder extends BaseSectionBuilder {
63
+ async buildAsync(model) {
64
+ this.log('Build called');
65
+ const validation = await this.validateAsync();
66
+ if (validation.errors.length) {
67
+ return { request: this.request, model, errors: validation.errors };
68
+ }
69
+ const resolved = this.resolveContent(model);
70
+ if ('error' in resolved)
71
+ return resolved.error;
72
+ const content = resolved.content;
73
+ applyScalarFields(content, this.args, this.sectionType);
74
+ applyStyleFields(content, this.args, this.sectionType);
75
+ applyRTEStyles(content, this.args, this.sectionType);
76
+ const args = this.args;
77
+ if (args.background_style && typeof args.background_style === 'object') {
78
+ const existing = content.backgroundStyle || {};
79
+ content.backgroundStyle = {
80
+ ...existing,
81
+ ...Object.fromEntries(Object.entries(args.background_style).map(([k, v]) => [
82
+ k,
83
+ v === null ? '' : v,
84
+ ])),
85
+ };
86
+ }
87
+ if (args.card_style && typeof args.card_style === 'object') {
88
+ const existing = content.cardStyle || {};
89
+ content.cardStyle = {
90
+ ...existing,
91
+ ...Object.fromEntries(Object.entries(args.card_style).map(([k, v]) => [
92
+ k,
93
+ v === null ? '' : v,
94
+ ])),
95
+ };
96
+ }
97
+ if (args.items && Array.isArray(args.items)) {
98
+ if (this.mode === 'create') {
99
+ applyImageItems(content, args.items);
100
+ }
101
+ else {
102
+ mergeImageItems(content, args.items, !!args._replace_items);
103
+ }
104
+ }
105
+ // Phase 2: Item operations (remove, insert, reorder)
106
+ if (args._remove_item_indices?.length && content.items) {
107
+ const sorted = [...args._remove_item_indices].sort((a, b) => b - a);
108
+ for (const idx of sorted) {
109
+ if (idx >= 0 && idx < content.items.length) {
110
+ content.items.splice(idx, 1);
111
+ }
112
+ }
113
+ }
114
+ if (args.items && Array.isArray(args.items)) {
115
+ const insertItems = args.items.filter((item) => item.insert_at !== undefined && item.item_index === undefined);
116
+ // Process inserts in reverse order of insert_at to preserve indices
117
+ const sortedInserts = [...insertItems].sort((a, b) => (b.insert_at ?? 0) - (a.insert_at ?? 0));
118
+ for (const item of sortedInserts) {
119
+ if (!item.image_url)
120
+ continue;
121
+ const pos = Math.max(0, Math.min(item.insert_at ?? 0, content.items?.length ?? 0));
122
+ const newItem = {
123
+ imageUrl: item.image_url,
124
+ imageTitle: '',
125
+ width: 0,
126
+ height: 0,
127
+ mediaType: 'image',
128
+ imageLink: '',
129
+ title: item.heading ?? '',
130
+ paragraph: item.text ?? '',
131
+ itemsId: pos,
132
+ colorReplacements: [],
133
+ };
134
+ content.items = content.items ?? [];
135
+ content.items.splice(pos, 0, newItem);
136
+ }
137
+ }
138
+ if (args._reorder_items?.length && content.items) {
139
+ const newOrder = args._reorder_items;
140
+ const unique = new Set(newOrder);
141
+ if (unique.size === newOrder.length) {
142
+ const reordered = newOrder
143
+ .filter((idx) => idx >= 0 && idx < content.items.length)
144
+ .map((idx) => content.items[idx]);
145
+ if (reordered.length === content.items.length) {
146
+ content.items = reordered;
147
+ }
148
+ }
149
+ }
150
+ // Re-index itemsId after any item operations
151
+ if (content.items) {
152
+ content.items.forEach((item, i) => {
153
+ item.itemsId = i;
154
+ });
155
+ }
156
+ return { request: this.request, model };
157
+ }
158
+ }
@@ -0,0 +1,17 @@
1
+ export { BaseSectionBuilder, type SectionBuilderPayload, } from './base-section-builder';
2
+ export { BannerSectionBuilder } from './banner-section-builder';
3
+ export { AboutSectionBuilder } from './about-section-builder';
4
+ export { ContactFormBuilder } from './contact-form-builder';
5
+ export { DividerSectionBuilder } from './divider-section-builder';
6
+ export { TextSectionBuilder } from './text-section-builder';
7
+ export { TestimonialSectionBuilder } from './testimonial-section-builder';
8
+ export { ImagesSectionBuilder } from './images-section-builder';
9
+ export { ShapesSectionBuilder } from './shapes-section-builder';
10
+ export { SocialLinksBuilder } from './social-links-builder';
11
+ export { ImageGalleryBuilder } from './image-gallery-builder';
12
+ export { ProfileSectionBuilder } from './profile-section-builder';
13
+ export { MailingListSectionBuilder } from './mailing-list-section-builder';
14
+ export { ImageSectionBuilder } from './image-section-builder';
15
+ export { ButtonSectionBuilder } from './button-section-builder';
16
+ export { DeleteSectionBuilder } from './delete-section-builder';
17
+ export { MoveSectionBuilder } from './move-section-builder';
@@ -0,0 +1,17 @@
1
+ export { BaseSectionBuilder, } from './base-section-builder';
2
+ export { BannerSectionBuilder } from './banner-section-builder';
3
+ export { AboutSectionBuilder } from './about-section-builder';
4
+ export { ContactFormBuilder } from './contact-form-builder';
5
+ export { DividerSectionBuilder } from './divider-section-builder';
6
+ export { TextSectionBuilder } from './text-section-builder';
7
+ export { TestimonialSectionBuilder } from './testimonial-section-builder';
8
+ export { ImagesSectionBuilder } from './images-section-builder';
9
+ export { ShapesSectionBuilder } from './shapes-section-builder';
10
+ export { SocialLinksBuilder } from './social-links-builder';
11
+ export { ImageGalleryBuilder } from './image-gallery-builder';
12
+ export { ProfileSectionBuilder } from './profile-section-builder';
13
+ export { MailingListSectionBuilder } from './mailing-list-section-builder';
14
+ export { ImageSectionBuilder } from './image-section-builder';
15
+ export { ButtonSectionBuilder } from './button-section-builder';
16
+ export { DeleteSectionBuilder } from './delete-section-builder';
17
+ export { MoveSectionBuilder } from './move-section-builder';
@@ -0,0 +1,6 @@
1
+ import type { BuilderResult } from '@src/metadata-builder/models';
2
+ import type { BrandPageModel, MailingListContent } from '../../../brand-page/models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ export declare class MailingListBuilder extends BaseSectionBuilder<MailingListContent> {
5
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
+ }
@@ -0,0 +1,17 @@
1
+ import { applyScalarFields } from '../section-field-utils';
2
+ import { BaseSectionBuilder } from './base-section-builder';
3
+ export class MailingListBuilder extends BaseSectionBuilder {
4
+ async buildAsync(model) {
5
+ this.log('Build called');
6
+ const validation = await this.validateAsync();
7
+ if (validation.errors.length) {
8
+ return { request: this.request, model, errors: validation.errors };
9
+ }
10
+ const resolved = this.resolveContent(model);
11
+ if ('error' in resolved)
12
+ return resolved.error;
13
+ const content = resolved.content;
14
+ applyScalarFields(content, this.args, this.sectionType);
15
+ return { request: this.request, model };
16
+ }
17
+ }
@@ -0,0 +1,6 @@
1
+ import type { MailingListContent, BrandPageModel } from '../../../brand-page/models';
2
+ import type { BuilderResult } from '../../models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ export declare class MailingListSectionBuilder extends BaseSectionBuilder<MailingListContent> {
5
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
+ }
@@ -0,0 +1,16 @@
1
+ import { applyScalarFields } from '../section-field-utils';
2
+ import { BaseSectionBuilder } from './base-section-builder';
3
+ export class MailingListSectionBuilder extends BaseSectionBuilder {
4
+ async buildAsync(model) {
5
+ this.log('Build called');
6
+ const validation = await this.validateAsync();
7
+ if (validation.errors.length) {
8
+ return { request: this.request, model, errors: validation.errors };
9
+ }
10
+ const resolved = this.resolveContent(model);
11
+ if ('error' in resolved)
12
+ return resolved.error;
13
+ applyScalarFields(resolved.content, this.args, this.sectionType);
14
+ return { request: this.request, model };
15
+ }
16
+ }
@@ -0,0 +1,15 @@
1
+ import type { BrandPageModel } from '../../../brand-page/models';
2
+ import { BaseMetadataBuilder, type BuilderResult, type MetadataBuilderRequest } from '../../models';
3
+ import type { Logger } from '../../logger';
4
+ export interface MoveSectionPayload {
5
+ contentId: string;
6
+ position: number;
7
+ targetPageId?: string;
8
+ }
9
+ export declare class MoveSectionBuilder extends BaseMetadataBuilder<MoveSectionPayload> {
10
+ constructor(request: MetadataBuilderRequest<MoveSectionPayload>, logger?: Logger);
11
+ validateAsync(): Promise<{
12
+ errors: string[];
13
+ }>;
14
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
15
+ }
@@ -0,0 +1,62 @@
1
+ import { BaseMetadataBuilder, } from '../../models';
2
+ export class MoveSectionBuilder extends BaseMetadataBuilder {
3
+ constructor(request, logger) {
4
+ super(request, logger);
5
+ }
6
+ async validateAsync() {
7
+ const errors = [];
8
+ const payload = this.request.payload;
9
+ if (!payload?.contentId) {
10
+ errors.push('contentId is required for move_section');
11
+ }
12
+ if (payload?.position === undefined || payload.position < 0) {
13
+ errors.push('position must be a non-negative integer');
14
+ }
15
+ return { errors };
16
+ }
17
+ async buildAsync(model) {
18
+ this.log('Build called');
19
+ const validation = await this.validateAsync();
20
+ if (validation.errors.length) {
21
+ return { request: this.request, model, errors: validation.errors };
22
+ }
23
+ const { contentId, position, targetPageId } = this.request.payload;
24
+ for (const page of model.pages) {
25
+ const currentIndex = page.contents.findIndex((c) => c.id === contentId);
26
+ if (currentIndex !== -1) {
27
+ const [section] = page.contents.splice(currentIndex, 1);
28
+ // Cross-page move: insert into target page
29
+ if (targetPageId && targetPageId !== page.id) {
30
+ const targetPage = model.pages.find((p) => p.id === targetPageId);
31
+ if (!targetPage) {
32
+ // Undo the splice and return an error
33
+ page.contents.splice(currentIndex, 0, section);
34
+ return {
35
+ request: this.request,
36
+ model,
37
+ errors: [`Target page with ID "${targetPageId}" not found`],
38
+ };
39
+ }
40
+ const targetIndex = Math.min(position, targetPage.contents.length);
41
+ targetPage.contents.splice(targetIndex, 0, section);
42
+ this.log({
43
+ message: `Moved section ${contentId} from page ${page.id} index ${currentIndex} to page ${targetPageId} index ${targetIndex}`,
44
+ });
45
+ return { request: this.request, model };
46
+ }
47
+ // Within-page reorder
48
+ const targetIndex = Math.min(position, page.contents.length);
49
+ page.contents.splice(targetIndex, 0, section);
50
+ this.log({
51
+ message: `Moved section ${contentId} from index ${currentIndex} to ${targetIndex} on page ${page.id}`,
52
+ });
53
+ return { request: this.request, model };
54
+ }
55
+ }
56
+ return {
57
+ request: this.request,
58
+ model,
59
+ errors: [`Section with ID "${contentId}" not found`],
60
+ };
61
+ }
62
+ }
@@ -0,0 +1,6 @@
1
+ import type { ProfileContent, BrandPageModel } from '../../../brand-page/models';
2
+ import type { BuilderResult } from '../../models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ export declare class ProfileSectionBuilder extends BaseSectionBuilder<ProfileContent> {
5
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
+ }
@@ -0,0 +1,16 @@
1
+ import { applyScalarFields } from '../section-field-utils';
2
+ import { BaseSectionBuilder } from './base-section-builder';
3
+ export class ProfileSectionBuilder extends BaseSectionBuilder {
4
+ async buildAsync(model) {
5
+ this.log('Build called');
6
+ const validation = await this.validateAsync();
7
+ if (validation.errors.length) {
8
+ return { request: this.request, model, errors: validation.errors };
9
+ }
10
+ const resolved = this.resolveContent(model);
11
+ if ('error' in resolved)
12
+ return resolved.error;
13
+ applyScalarFields(resolved.content, this.args, this.sectionType);
14
+ return { request: this.request, model };
15
+ }
16
+ }
@@ -0,0 +1,6 @@
1
+ import type { ShapesSectionContent, BrandPageModel } from '../../../brand-page/models';
2
+ import type { BuilderResult } from '../../models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ export declare class ShapesSectionBuilder extends BaseSectionBuilder<ShapesSectionContent> {
5
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
+ }
@@ -0,0 +1,162 @@
1
+ import { applyScalarFields, applyStyleFields, applyRTEStyles, } from '../section-field-utils';
2
+ import { BaseSectionBuilder } from './base-section-builder';
3
+ const applyShapeItems = (content, items) => {
4
+ content.items = items.map((item, index) => ({
5
+ imageUrl: item.shape_url || item.icon_image_url || '',
6
+ imageTitle: '',
7
+ width: 0,
8
+ height: 0,
9
+ mediaType: 'shape',
10
+ imageLink: '',
11
+ title: item.heading || '',
12
+ paragraph: item.text || '',
13
+ itemsId: index,
14
+ colorReplacements: [],
15
+ keepColor: item.keep_color ?? false,
16
+ }));
17
+ };
18
+ const mergeShapeItems = (content, items, replaceAll) => {
19
+ const hasIndexedItems = items.some((item) => item.item_index !== undefined);
20
+ if (hasIndexedItems) {
21
+ for (const item of items) {
22
+ const targetIndex = item.item_index;
23
+ if (targetIndex === undefined ||
24
+ targetIndex < 0 ||
25
+ !content.items?.[targetIndex])
26
+ continue;
27
+ const existing = content.items[targetIndex];
28
+ if (item.shape_url !== undefined || item.icon_image_url !== undefined) {
29
+ existing.imageUrl =
30
+ item.shape_url ?? item.icon_image_url ?? existing.imageUrl;
31
+ }
32
+ if (item.heading !== undefined)
33
+ existing.title = item.heading;
34
+ if (item.text !== undefined)
35
+ existing.paragraph = item.text;
36
+ if (item.keep_color !== undefined) {
37
+ existing.keepColor = item.keep_color;
38
+ }
39
+ }
40
+ return;
41
+ }
42
+ const updatedItems = items.map((item, index) => {
43
+ const existing = content.items?.[index];
44
+ const imageUrl = item.shape_url ?? item.icon_image_url ?? existing?.imageUrl ?? '';
45
+ return {
46
+ ...(existing || {}),
47
+ imageUrl,
48
+ imageTitle: existing?.imageTitle ?? '',
49
+ width: existing?.width ?? 0,
50
+ height: existing?.height ?? 0,
51
+ mediaType: existing?.mediaType ?? 'shape',
52
+ imageLink: existing?.imageLink ?? '',
53
+ title: item.heading ?? existing?.title ?? '',
54
+ paragraph: item.text ?? existing?.paragraph ?? '',
55
+ itemsId: existing?.itemsId ?? index,
56
+ colorReplacements: existing?.colorReplacements ?? [],
57
+ keepColor: item.keep_color ??
58
+ (existing && 'keepColor' in existing ? existing.keepColor : false),
59
+ };
60
+ });
61
+ if (!replaceAll && content.items && content.items.length > items.length) {
62
+ const remaining = content.items.slice(items.length);
63
+ updatedItems.push(...remaining);
64
+ }
65
+ content.items = updatedItems;
66
+ };
67
+ export class ShapesSectionBuilder extends BaseSectionBuilder {
68
+ async buildAsync(model) {
69
+ this.log('Build called');
70
+ const validation = await this.validateAsync();
71
+ if (validation.errors.length) {
72
+ return { request: this.request, model, errors: validation.errors };
73
+ }
74
+ const resolved = this.resolveContent(model);
75
+ if ('error' in resolved)
76
+ return resolved.error;
77
+ const content = resolved.content;
78
+ applyScalarFields(content, this.args, this.sectionType);
79
+ applyStyleFields(content, this.args, this.sectionType);
80
+ applyRTEStyles(content, this.args, this.sectionType);
81
+ const args = this.args;
82
+ if (args.background_style && typeof args.background_style === 'object') {
83
+ const existing = content.backgroundStyle || {};
84
+ content.backgroundStyle = {
85
+ ...existing,
86
+ ...Object.fromEntries(Object.entries(args.background_style).map(([k, v]) => [
87
+ k,
88
+ v === null ? '' : v,
89
+ ])),
90
+ };
91
+ }
92
+ if (args.card_style && typeof args.card_style === 'object') {
93
+ const existing = content.cardStyle || {};
94
+ content.cardStyle = {
95
+ ...existing,
96
+ ...Object.fromEntries(Object.entries(args.card_style).map(([k, v]) => [
97
+ k,
98
+ v === null ? '' : v,
99
+ ])),
100
+ };
101
+ }
102
+ if (args.items && Array.isArray(args.items)) {
103
+ if (this.mode === 'create') {
104
+ applyShapeItems(content, args.items);
105
+ }
106
+ else {
107
+ mergeShapeItems(content, args.items, !!args._replace_items);
108
+ }
109
+ }
110
+ // Phase 2: Item operations (remove, insert, reorder)
111
+ if (args._remove_item_indices?.length && content.items) {
112
+ const sorted = [...args._remove_item_indices].sort((a, b) => b - a);
113
+ for (const idx of sorted) {
114
+ if (idx >= 0 && idx < content.items.length) {
115
+ content.items.splice(idx, 1);
116
+ }
117
+ }
118
+ }
119
+ if (args.items && Array.isArray(args.items)) {
120
+ const insertItems = args.items.filter((item) => item.insert_at !== undefined && item.item_index === undefined);
121
+ // Process inserts in reverse order of insert_at to preserve indices
122
+ const sortedInserts = [...insertItems].sort((a, b) => (b.insert_at ?? 0) - (a.insert_at ?? 0));
123
+ for (const item of sortedInserts) {
124
+ const pos = Math.max(0, Math.min(item.insert_at ?? 0, content.items?.length ?? 0));
125
+ const newItem = {
126
+ imageUrl: item.shape_url ?? item.icon_image_url ?? '',
127
+ imageTitle: '',
128
+ width: 0,
129
+ height: 0,
130
+ mediaType: 'shape',
131
+ imageLink: '',
132
+ title: item.heading ?? '',
133
+ paragraph: item.text ?? '',
134
+ itemsId: pos,
135
+ colorReplacements: [],
136
+ keepColor: item.keep_color ?? false,
137
+ };
138
+ content.items = content.items ?? [];
139
+ content.items.splice(pos, 0, newItem);
140
+ }
141
+ }
142
+ if (args._reorder_items?.length && content.items) {
143
+ const newOrder = args._reorder_items;
144
+ const unique = new Set(newOrder);
145
+ if (unique.size === newOrder.length) {
146
+ const reordered = newOrder
147
+ .filter((idx) => idx >= 0 && idx < content.items.length)
148
+ .map((idx) => content.items[idx]);
149
+ if (reordered.length === content.items.length) {
150
+ content.items = reordered;
151
+ }
152
+ }
153
+ }
154
+ // Re-index itemsId after any item operations
155
+ if (content.items) {
156
+ content.items.forEach((item, i) => {
157
+ item.itemsId = i;
158
+ });
159
+ }
160
+ return { request: this.request, model };
161
+ }
162
+ }
@@ -0,0 +1,6 @@
1
+ import type { SocialLinksContent, BrandPageModel } from '../../../brand-page/models';
2
+ import type { BuilderResult } from '../../models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ export declare class SocialLinksBuilder extends BaseSectionBuilder<SocialLinksContent> {
5
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
+ }