@designcrowd/library.brand-page 6.0.11 → 6.0.13

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 (117) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DopPc6g2.js → CreatedOnBrandCrowd-de-de-CBjFFeBP.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-CSHmaAWm.js → CreatedOnBrandCrowd-en-us-NuNXF81K.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-C4vM0p2e.js → CreatedOnBrandCrowd-es-es-BJG8nfug.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-ArpBbnxm.js → CreatedOnBrandCrowd-fr-ca-uX-nL53e.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-ArpBbnxm.js → CreatedOnBrandCrowd-fr-fr-uX-nL53e.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-CGAQLXiX.js → CreatedOnBrandCrowd-pt-br-DTrgFGQV.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-CGAQLXiX.js → CreatedOnBrandCrowd-pt-pt-DTrgFGQV.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-3WVSgB6t.js → CreatedOnDcom-de-de-DSfpxioT.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-Dx-RHXrH.js → CreatedOnDcom-en-us-C7G4gKem.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-CfnEYFMA.js → CreatedOnDcom-es-es-DVckCaji.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-BSHZTiUO.js → CreatedOnDcom-fr-ca-C5GDrm_C.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-DtHssrQb.js → CreatedOnDcom-fr-fr-v5eMm-j2.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-CdX1aRI8.js → CreatedOnDcom-pt-br-Dq3-fPUc.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-jy044FNL.js → CreatedOnDcom-pt-pt-DFsncYax.js} +1 -1
  15. package/lib/src/brand-page/components/image-gallery/ImageGallery.stories.js +3 -0
  16. package/lib/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.d.ts +1 -1
  17. package/lib/src/brand-page/components/images-section/ImagesSection.stories.js +2 -1
  18. package/lib/src/brand-page/components/social-links/SocialLinks.stories.js +3 -0
  19. package/lib/src/brand-page/components/testimonial-section/__fixtures__/data.js +3 -0
  20. package/lib/src/brand-page/components/text/Text.stories.js +2 -0
  21. package/lib/src/brand-page/models/index.d.ts +13 -0
  22. package/lib/src/brand-page/models/index.js +4 -0
  23. package/lib/src/brand-page/utils/migration/migration-01.js +2 -0
  24. package/lib/src/brand-page/utils/migration/migration-18.d.ts +14 -0
  25. package/lib/src/brand-page/utils/migration/migration-18.js +17 -0
  26. package/lib/src/brand-page/utils/migration.util.js +6 -0
  27. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.js +1 -0
  28. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -0
  29. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +5 -0
  30. package/lib/src/brand-page-maker/constants/config-settings-constant.js +4 -0
  31. package/lib/src/brand-page-maker/models/content-settings.js +4 -0
  32. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +18 -0
  33. package/lib/src/index.mjs +84 -83
  34. package/lib/src/{lib-Bx7xK4dn.js → lib-BG-pyXi9.js} +19585 -19807
  35. package/lib/src/metadata-builder/ai-metadata-executor.js +24 -1
  36. package/lib/src/metadata-builder/builders/footer-builder.js +32 -41
  37. package/lib/src/metadata-builder/builders/item-id-utils.d.ts +54 -0
  38. package/lib/src/metadata-builder/builders/item-id-utils.js +96 -0
  39. package/lib/src/metadata-builder/builders/move-page-builder.d.ts +32 -0
  40. package/lib/src/metadata-builder/builders/move-page-builder.js +137 -0
  41. package/lib/src/metadata-builder/builders/nav-utils.d.ts +26 -0
  42. package/lib/src/metadata-builder/builders/nav-utils.js +95 -0
  43. package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.js +57 -68
  44. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +58 -93
  45. package/lib/src/metadata-builder/builders/section-builders/move-section-builder.d.ts +13 -1
  46. package/lib/src/metadata-builder/builders/section-builders/move-section-builder.js +40 -30
  47. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +66 -99
  48. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +57 -17
  49. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +51 -85
  50. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +50 -74
  51. package/lib/src/metadata-builder/builders/section-field-maps.js +17 -0
  52. package/lib/src/metadata-builder/builders/set-page-visibility-builder.d.ts +23 -0
  53. package/lib/src/metadata-builder/builders/set-page-visibility-builder.js +83 -0
  54. package/lib/src/metadata-builder/metadata-executor.js +4 -0
  55. package/lib/src/metadata-builder/models.d.ts +2 -0
  56. package/lib/src/metadata-builder/models.js +2 -0
  57. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +31 -7
  58. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.js +2 -0
  59. package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +84 -48
  60. package/lib/src/shared/content-settings/components/links-field/LinksField.mixin.js +2 -0
  61. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +2 -0
  62. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +2 -0
  63. package/lib/src/tracker.d.ts +2 -0
  64. package/lib/src/tracker.js +12 -0
  65. package/lib/src/tracker.mjs +12 -0
  66. package/lib/src/useEventTracker-DmQ6AkNn.js +356 -0
  67. package/lib/src/utils/minify-brand-page-metadata.d.ts +2 -0
  68. package/lib/src/utils/minify-brand-page-metadata.js +8 -1
  69. package/package.json +16 -1
  70. package/src/brand-page/components/image-gallery/ImageGallery.stories.ts +3 -0
  71. package/src/brand-page/components/image-gallery/ImageGallery.test.ts +1 -0
  72. package/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.ts +2 -1
  73. package/src/brand-page/components/images-section/ImagesSection.stories.ts +2 -1
  74. package/src/brand-page/components/social-links/SocialLinks.stories.ts +3 -0
  75. package/src/brand-page/components/social-links/SocialLinks.vue.test.ts +5 -0
  76. package/src/brand-page/components/testimonial-section/__fixtures__/data.ts +3 -0
  77. package/src/brand-page/components/text/Text.stories.ts +2 -0
  78. package/src/brand-page/models/index.ts +17 -0
  79. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +23 -3
  80. package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +6 -0
  81. package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +12 -0
  82. package/src/brand-page/utils/migration/migration-01.ts +2 -0
  83. package/src/brand-page/utils/migration/migration-18.test.ts +131 -0
  84. package/src/brand-page/utils/migration/migration-18.ts +22 -0
  85. package/src/brand-page/utils/migration.util.ts +7 -0
  86. package/src/brand-page/utils/personalisation.util.test.ts +4 -0
  87. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +1 -0
  88. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -0
  89. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +6 -0
  90. package/src/brand-page-maker/constants/config-settings-constant.ts +4 -0
  91. package/src/brand-page-maker/models/content-settings.ts +4 -0
  92. package/src/metadata-builder/ai-metadata-executor.ts +31 -1
  93. package/src/metadata-builder/builders/footer-builder.test.ts +335 -28
  94. package/src/metadata-builder/builders/footer-builder.ts +40 -57
  95. package/src/metadata-builder/builders/item-id-utils.test.ts +184 -0
  96. package/src/metadata-builder/builders/item-id-utils.ts +117 -0
  97. package/src/metadata-builder/builders/move-page-builder.ts +227 -0
  98. package/src/metadata-builder/builders/nav-utils.ts +141 -0
  99. package/src/metadata-builder/builders/section-builders/image-gallery-builder.ts +62 -88
  100. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +66 -129
  101. package/src/metadata-builder/builders/section-builders/move-section-builder.ts +58 -35
  102. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +105 -160
  103. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +65 -20
  104. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +83 -146
  105. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +71 -122
  106. package/src/metadata-builder/builders/section-field-maps.ts +18 -0
  107. package/src/metadata-builder/builders/set-page-visibility-builder.ts +122 -0
  108. package/src/metadata-builder/metadata-executor.ts +4 -0
  109. package/src/metadata-builder/models.ts +2 -0
  110. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +32 -7
  111. package/src/metadata-builder/parsers/section-tool-arguments.ts +84 -48
  112. package/src/shared/content-settings/components/links-field/LinksField.mixin.ts +2 -0
  113. package/src/tracker.ts +28 -0
  114. package/src/utils/minify-brand-page-metadata.ts +14 -2
  115. package/lib/src/metadata-builder/builders/reorder-pages-builder.d.ts +0 -13
  116. package/lib/src/metadata-builder/builders/reorder-pages-builder.js +0 -49
  117. package/src/metadata-builder/builders/reorder-pages-builder.ts +0 -80
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bx7xK4dn.js";
2
+ import { _ as t } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, h = {
4
4
  width: "275",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bx7xK4dn.js";
2
+ import { _ as t } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, h = {
4
4
  width: "251",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bx7xK4dn.js";
2
+ import { _ as t } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, h = {
4
4
  width: "250",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bx7xK4dn.js";
2
+ import { _ as t } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bx7xK4dn.js";
2
+ import { _ as t } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bx7xK4dn.js";
2
+ import { _ as t } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-Bx7xK4dn.js";
2
+ import { _ as t } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bx7xK4dn.js";
2
+ import { _ as e } from "./lib-BG-pyXi9.js";
3
3
  const M = {}, Z = {
4
4
  width: "242",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bx7xK4dn.js";
2
+ import { _ as e } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, M = {
4
4
  width: "231",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bx7xK4dn.js";
2
+ import { _ as e } from "./lib-BG-pyXi9.js";
3
3
  const M = {}, Z = {
4
4
  width: "230",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bx7xK4dn.js";
2
+ import { _ as e } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-Bx7xK4dn.js";
2
+ import { _ as e } from "./lib-BG-pyXi9.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-Bx7xK4dn.js";
2
+ import { _ as M } from "./lib-BG-pyXi9.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-Bx7xK4dn.js";
2
+ import { _ as M } from "./lib-BG-pyXi9.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -44,6 +44,7 @@ export const Carousel = () => {
44
44
  content.galleryStyles = undefined;
45
45
  content.images = new Array(10).fill(0).map((_, i) => {
46
46
  return {
47
+ id: `gallery-carousel-item-${i}`,
47
48
  imageUrl: `https://picsum.photos/${300 * ((i + 1) / 4)}/${300 * ((i + 1) / 4)}?random=${i}`,
48
49
  width: 300,
49
50
  height: 300,
@@ -71,6 +72,7 @@ export const Masonry = () => {
71
72
  const content = createInitialImageGalleryContent();
72
73
  content.images = new Array(10).fill(0).map((_, i) => {
73
74
  return {
75
+ id: `gallery-masonry-item-${i}`,
74
76
  imageUrl: `https://picsum.photos/${300 * ((i + 1) / 4)}/${300 * ((i + 1) / 4)}?random=${i}`,
75
77
  width: 564,
76
78
  height: 416,
@@ -98,6 +100,7 @@ export const Grid = () => {
98
100
  const content = createInitialImageGalleryContent();
99
101
  content.images = new Array(10).fill(0).map((_, i) => {
100
102
  return {
103
+ id: `gallery-grid-item-${i}`,
101
104
  imageUrl: `https://picsum.photos/${300 * ((i + 1) / 4)}/${300 * ((i + 1) / 4)}?random=${i}`,
102
105
  width: 564,
103
106
  height: 416,
@@ -2,7 +2,7 @@ import type { PropType } from 'vue';
2
2
  import type { ImageGalleryViewModel } from '../../../view-models';
3
3
  import type { DebounceHandle } from 'lodash.debounce';
4
4
  import type { BrandPageContext, ImageGalleryItem } from '../../../models';
5
- interface IndexedImageGalleryItem extends ImageGalleryItem {
5
+ interface IndexedImageGalleryItem extends Omit<ImageGalleryItem, 'id'> {
6
6
  id: number;
7
7
  }
8
8
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
@@ -41,8 +41,9 @@ export const Images = () => {
41
41
  },
42
42
  data() {
43
43
  const content = createInitialImagesSectionContent();
44
- content.items = new Array(2).fill(0).map(() => {
44
+ content.items = new Array(2).fill(0).map((_, i) => {
45
45
  return {
46
+ id: `images-section-item-${i}`,
46
47
  imageUrl: 'https://bc-user-uploads.brandcrowd.com/public/media-int/6b3a4d19-e95c-4d59-aa22-ac033a2cec2f/1116870a-c672-4306-b515-32f8d5d6e10c',
47
48
  width: 564,
48
49
  height: 416,
@@ -11,6 +11,7 @@ const viewModel = {
11
11
  title: 'Follow us on',
12
12
  links: [
13
13
  {
14
+ id: 'social-link-facebook',
14
15
  imageUrl: 'facebook',
15
16
  url: '',
16
17
  imageTitle: '',
@@ -21,6 +22,7 @@ const viewModel = {
21
22
  imageLink: '',
22
23
  },
23
24
  {
25
+ id: 'social-link-instagram',
24
26
  imageUrl: 'instagram',
25
27
  url: 'https://www.instagram.com',
26
28
  imageTitle: '',
@@ -31,6 +33,7 @@ const viewModel = {
31
33
  imageLink: '',
32
34
  },
33
35
  {
36
+ id: 'social-link-empty',
34
37
  imageUrl: '',
35
38
  url: '',
36
39
  imageTitle: '',
@@ -9,6 +9,7 @@ export const viewModel = {
9
9
  displayStyle: 'centered',
10
10
  items: [
11
11
  {
12
+ id: 'testimonial-1',
12
13
  testimonials: faker.lorem.paragraphs(1),
13
14
  imageUrl: unsplashImage,
14
15
  name: '1',
@@ -17,6 +18,7 @@ export const viewModel = {
17
18
  colorReplacements: [],
18
19
  },
19
20
  {
21
+ id: 'testimonial-2',
20
22
  testimonials: faker.lorem.paragraphs(3),
21
23
  imageUrl: unsplashImage,
22
24
  name: '2',
@@ -25,6 +27,7 @@ export const viewModel = {
25
27
  colorReplacements: [],
26
28
  },
27
29
  {
30
+ id: 'testimonial-3',
28
31
  testimonials: faker.lorem.paragraphs(5),
29
32
  imageUrl: 'https://source.unsplash.com/random/200x200?3',
30
33
  name: '3',
@@ -31,6 +31,7 @@ const BSviewModel = {
31
31
  text: 'asdasjdlkasjmdlkmsad',
32
32
  textItems: [
33
33
  {
34
+ id: 'text-item-1',
34
35
  text: 'lorem ipsum',
35
36
  textStyle: {
36
37
  fontSize: '1rem',
@@ -39,6 +40,7 @@ const BSviewModel = {
39
40
  },
40
41
  },
41
42
  {
43
+ id: 'text-item-2',
42
44
  text: 'lorem ipsum',
43
45
  textStyle: {
44
46
  fontSize: '1rem',
@@ -110,6 +110,13 @@ export interface ImageContent extends Content {
110
110
  height?: number;
111
111
  }
112
112
  export interface ImageItem {
113
+ /**
114
+ * Stable per-item identifier. Mirrors the section-level `Content.id` one
115
+ * level deeper so AI tool calls can reference items by id rather than by
116
+ * positional index. Backfilled on load for persisted data that predates
117
+ * item ids (see ensureItemIds), so it is always present at runtime.
118
+ */
119
+ id: string;
113
120
  imageUrl: string;
114
121
  imageTitle: string;
115
122
  width: number;
@@ -311,6 +318,8 @@ export interface ShapeItem extends ImageItem {
311
318
  paragraphOverride?: string;
312
319
  }
313
320
  export interface TestimonialItems {
321
+ /** Stable per-item identifier. See ImageItem.id. */
322
+ id: string;
314
323
  imageUrl: string;
315
324
  name: string;
316
325
  position: string;
@@ -325,6 +334,8 @@ export interface TestimonialItems {
325
334
  positionOverride?: string;
326
335
  }
327
336
  export interface TextItem {
337
+ /** Stable per-item identifier. See ImageItem.id. */
338
+ id: string;
328
339
  text: string;
329
340
  textStyle: TextStyleDeclaration;
330
341
  textOverride?: string;
@@ -385,6 +396,8 @@ export interface AboutSectionContent extends Content {
385
396
  size?: string;
386
397
  }
387
398
  export interface LinksItem {
399
+ /** Stable per-item identifier. See ImageItem.id. */
400
+ id: string;
388
401
  imageUrl: string;
389
402
  url: string;
390
403
  size?: string;
@@ -11,6 +11,7 @@ import { NavigationDesktop, NavigationMobile } from './navigation-styles.model';
11
11
  import { TEXT_STYLE_TYPES, TextStyles } from './styles.model';
12
12
  import { EMPTY_LOGO_IMAGE_MODEL, LogoStyles } from './logo.model';
13
13
  import cloneDeep from 'lodash.clonedeep';
14
+ import * as uuid from 'uuid';
14
15
  export * from './brand-page-context.model';
15
16
  export * from './payment.model';
16
17
  export * from './content.model';
@@ -331,6 +332,7 @@ export class AbstractPageFooterStyles {
331
332
  this.logoImageWidth = options.logoImageWidth || DEFAULT_LOGO_WIDTH;
332
333
  this.socialLinks = options.socialLinks || [
333
334
  {
335
+ id: uuid.v4(),
334
336
  width: 0,
335
337
  height: 0,
336
338
  imageUrl: 'facebook',
@@ -340,6 +342,7 @@ export class AbstractPageFooterStyles {
340
342
  imageLink: '',
341
343
  },
342
344
  {
345
+ id: uuid.v4(),
343
346
  width: 0,
344
347
  height: 0,
345
348
  imageUrl: 'instagram',
@@ -349,6 +352,7 @@ export class AbstractPageFooterStyles {
349
352
  imageLink: '',
350
353
  },
351
354
  {
355
+ id: uuid.v4(),
352
356
  width: 0,
353
357
  height: 0,
354
358
  imageUrl: 'x',
@@ -1,3 +1,4 @@
1
+ import * as uuid from 'uuid';
1
2
  import { getLogoVariationIndexFromLogoImageUrl, getLogoDraftTokenFromLogoImageUrl, safeGetLogoImageFromLogoImageUrl, } from '../logo.util';
2
3
  import { DEFAULT_LETTER_SPACING, FOOTER_DISPLAY, NavigationDesktop, NavigationMobile, PageFooterDesktop, PageFooterMobile, PageHeaderDesktop, PageHeaderMobile, } from '../../';
3
4
  import { ALIGN_CARD_CENTER_IMAGE, ALIGN_CARD_LEFT_IMAGE, ALIGN_CENTERED, ALIGN_LEFT_BIG_IMAGE, BIG_IMAGE, BRAND_PAGE_TYPES, DEFAULT_FONT_FAMILY_KEY, DEFAULT_LOGO_HEIGHT, DEFAULT_LOGO_WIDTH, DEFAULT_TEXT_ALIGN, FONT_FAMILY_CONFIGS, HEADER_DISPLAY, NAVIGATION_DISPLAY, LINE_HEIGHT_BODY, LINE_HEIGHT_HEADINGS, LINE_HEIGHT_TITLE, PAYMENT_OPTION_DISPLAY_TYPES, } from '../../';
@@ -25,6 +26,7 @@ export const applyTextContentTextToTextItemsMigration = (brandPageModel) => {
25
26
  };
26
27
  }
27
28
  const textItem = {
29
+ id: uuid.v4(),
28
30
  text: item.text,
29
31
  textStyle,
30
32
  };
@@ -0,0 +1,14 @@
1
+ import type { MigrationData } from '../migration.util';
2
+ /**
3
+ * BP-5603: backfill a stable uuid `id` onto every nested item (gallery images,
4
+ * images/shapes/testimonial items, text items, section + footer social links)
5
+ * that predates the id-based edit model.
6
+ *
7
+ * The item `id` field is now non-nullable in the model, so every load path must
8
+ * guarantee it — not just the AI chat flow, which already stamps ids before
9
+ * minifying (see ensureBrandPageItemIds in useAiWebsiteBuilderChat). This
10
+ * migration is that guarantee for persisted data. Idempotent — existing ids are
11
+ * preserved, so re-running (e.g. render-only sites that never re-save) is a
12
+ * no-op beyond generating ids for items that still lack one.
13
+ */
14
+ export declare const migration18: (migrationResult: MigrationData) => Promise<MigrationData>;
@@ -0,0 +1,17 @@
1
+ import { ensureBrandPageItemIds } from '../../../metadata-builder/builders/item-id-utils';
2
+ /**
3
+ * BP-5603: backfill a stable uuid `id` onto every nested item (gallery images,
4
+ * images/shapes/testimonial items, text items, section + footer social links)
5
+ * that predates the id-based edit model.
6
+ *
7
+ * The item `id` field is now non-nullable in the model, so every load path must
8
+ * guarantee it — not just the AI chat flow, which already stamps ids before
9
+ * minifying (see ensureBrandPageItemIds in useAiWebsiteBuilderChat). This
10
+ * migration is that guarantee for persisted data. Idempotent — existing ids are
11
+ * preserved, so re-running (e.g. render-only sites that never re-save) is a
12
+ * no-op beyond generating ids for items that still lack one.
13
+ */
14
+ export const migration18 = async (migrationResult) => {
15
+ ensureBrandPageItemIds(migrationResult.brandPageModel);
16
+ return migrationResult;
17
+ };
@@ -20,6 +20,7 @@ import { migration14 } from './migration/migration-14';
20
20
  import { migration15 } from './migration/migration-15';
21
21
  import { migration16 } from './migration/migration-16';
22
22
  import { migration17 } from './migration/migration-17';
23
+ import { migration18 } from './migration/migration-18';
23
24
  const MIGRATION_TABLE = [
24
25
  {
25
26
  version: 1,
@@ -132,6 +133,11 @@ const MIGRATION_TABLE = [
132
133
  runAlways: true,
133
134
  description: 'Padding Control backfill (BP-5699 Tier 2 + BP-5700 Store): backfill existing top/bottom spacing as explicit padding for text (12px), images/social links/shapes/booking (32px), store (16px), contact form (per layout), banner and about (per display style)',
134
135
  },
136
+ {
137
+ version: 18,
138
+ migrateFn: migration18,
139
+ description: 'BP-5603: backfill stable item ids on all nested items (gallery/section/testimonial/text items, section + footer social links) — the item id is now non-nullable',
140
+ },
135
141
  ];
136
142
  export const GetLatestModelVersion = () => Math.max(...MIGRATION_TABLE.map((x) => x.version));
137
143
  export const migrateBrandPageModel = async (brandPageModel, options) => {
@@ -1281,6 +1281,7 @@ export const SampleImageGallery = () => {
1281
1281
  const width = 300;
1282
1282
  const height = 300;
1283
1283
  imageGalleryContent.images.push({
1284
+ id: `gallery-item-${i}`,
1284
1285
  width,
1285
1286
  height,
1286
1287
  imageUrl: `https://images.unsplash.com/photo-1659535915214-e7cbac112038?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMjQzOTV8MXwxfHNlYXJjaHw4fHxnYW1pbmd8ZW58MHx8fHwxNjY5MDc4ODE1&ixlib=rb-4.0.3&q=80&w=1080`,
@@ -2212,6 +2212,7 @@ export const BRAND_PAGE_PERSONALISED = {
2212
2212
  displayStyle: 'centered',
2213
2213
  items: [
2214
2214
  {
2215
+ id: 'shapes-section-item-1',
2215
2216
  colorReplacements: [],
2216
2217
  height: -1,
2217
2218
  imageUrl: 'https://bcassetcdn.com/shapes/prod/00019160-9144-4bb3-af48-394a52845c37.svg',
@@ -5,6 +5,7 @@ import { parseLogoThemeToCssStyles } from '../../../brand-page/utils/style.util'
5
5
  import { AI_ASSISTANT_TOOL_NAMES } from '../../../metadata-builder/parsers/ai-toolcall-parser';
6
6
  import { WebSocketGatewayClient, } from '../../../clients/websocket-gateway-client';
7
7
  import { minifyBrandPageMetadata } from '../../../utils/minify-brand-page-metadata';
8
+ import { ensureBrandPageItemIds } from '../../../metadata-builder/builders/item-id-utils';
8
9
  import { buildAssetManifest } from '../../../utils/build-asset-manifest';
9
10
  import cloneDeep from 'lodash.clonedeep';
10
11
  import { usePageNavigationStore } from '../../../shared/page-navigation/store/page-navigation-store';
@@ -179,6 +180,10 @@ export function useAiWebsiteBuilderChat() {
179
180
  };
180
181
  const buildMessagePayload = async (userPrompt) => {
181
182
  const brandPageData = brandPageMakerStore.brandPageData;
183
+ // BP-5603: stamp stable uuid ids onto every nested item BEFORE minifying,
184
+ // so the id the AI is shown (and returns as `item_id`) is the exact id the
185
+ // executor matches when applying tool calls to this same live model.
186
+ ensureBrandPageItemIds(brandPageData);
182
187
  const headerLogoDraftToken = brandPageData.pageHeaderDesktop?.logoImage?.logoDraftToken ??
183
188
  uiStore.logoDraftToken;
184
189
  const [assets, logoContext] = await Promise.all([
@@ -1,5 +1,6 @@
1
1
  import { SOCIAL_LINKS_ICON_DISPLAY_STYLES, BRAND_PAGE_TYPES, DIVIDER_STYLES, MEDIA_TYPES, BUTTON_LINK_TYPE, FONT_SIZE_BODY, LINE_HEIGHT_BODY, MIN_TEXT_SIZE_PX, MAX_TEXT_SIZE_PX, TEXT_COLUMNS, DEFAULT_SHAPE_SIZE, PAYMENT_OPTION_DISPLAY_TYPES, PAYMENT_OPTION_IMAGE_TYPES, GettyVideoMedia, } from '@brand-page';
2
2
  import { createInitialButtonContent, createInitialImageContent, createInitialProfileContent, createInitialTextContent, createInitialVideoContent, createInitialLogoContent, createInitialMapContent, createInitialImageGalleryContent, createInitialGeneralLinkContent, createInitialMailingListContent, createInitialRequestPaymentContent, createInitialSupportMeContent, createInitialContactFormContent, CONTENT_SETTINGS_DISPLAY_MODES, createInitialBannerSectionContent, createInitialSocialLinksContent, createInitialImagesSectionContent, createInitialTestimonialSectionContent, createInitialAboutSectionContent, createInitialDividerSectionContent, createInitialShapesSectionContent, VARIANT_DISPLAY_MODES, createInitialShopContent, createInitialBookingSectionContent, } from '../models';
3
+ import * as uuid from 'uuid';
3
4
  import { colorConvertor, backgroundColorConvertor, borderColorConvertor, displayStyleConvertor, galleryTypeConvertor, imageAspectRatioConvertor, textAlignmentOptionsConvertor, videoContentStateConvertor, fillColorConvertor, bannerAlignDisplayStyleConvertor, aboutDisplayStyleConvertor, dividerStyleConvertor, shapeSizeOptionsConvertor, buttonLinkStyleConvertor, textSizeValueConvertor, textColumnStyleConvertor, contactLayoutStyleConvertor, paymentLinkDisplayStyleConvertor, shopDisplayConvertor, shopAspectRatioConvertor, } from '../convertors';
4
5
  import { ALIGN_CENTERED, DISPLAY_STYLE_COLLAPSED, DISPLAY_STYLE_PREVIEW, } from '@brand-page';
5
6
  import { imageFieldVisibilityAssessor, imageOptionVisibilityAssessor, imageGalleryFieldVisibilityAssessor, cardFillVisibilityAssessor, mediaSectionItemsFieldTypeAssessor, dividerToggleFieldVisibilityAssessor, shapeSectionItemsFieldTypeAssessor, colorReplacementVisibilityTypeAssessor, colorReplacementProfileVisibilityTypeAssessor, colorReplacementIconVisibilityTypeAssessor, imagesSectionCardStyleVisibilityAssessor, contactCardDisplayTypeVisibilityAssessor, imageUrlVisibilityAssessor, displayTypeVisibilityAssessor, logoFieldVisibilityAssessor, shapesSectionCardStyleVisibilityAssessor, shopImageOptionVisibilityAssessor, shopItemColorVisibility, personalisationOverrideVisibility, } from '../assessors';
@@ -167,6 +168,7 @@ const imageGalleryReplaceImageSettings = () => ({
167
168
  content.images = [];
168
169
  }
169
170
  content.images.push({
171
+ id: uuid.v4(),
170
172
  imageUrl: value.imageUrl,
171
173
  imageTitle: value.imageTitle,
172
174
  height: value.height,
@@ -372,6 +374,7 @@ const shapesImageReplaceImageSettings = () => ({
372
374
  setContentMedia: (content, value, index) => {
373
375
  if (index === undefined || index === null) {
374
376
  content.items?.push({
377
+ id: uuid.v4(),
375
378
  imageUrl: value.imageUrl,
376
379
  imageTitle: '',
377
380
  paragraph: '',
@@ -402,6 +405,7 @@ const textImageReplaceImageSettings = () => ({
402
405
  setContentMedia: (content, value, index) => {
403
406
  if (index === undefined || index === null) {
404
407
  content.items?.push({
408
+ id: uuid.v4(),
405
409
  imageUrl: value.imageUrl,
406
410
  imageTitle: value.imageTitle,
407
411
  paragraph: '',
@@ -153,6 +153,7 @@ export const createInitialTextContent = (options) => {
153
153
  textItems: options?.brandPageType === 'brandSite'
154
154
  ? [
155
155
  {
156
+ id: uuid.v4(),
156
157
  text: contentSettingsTr(`defaultTextValue`),
157
158
  textStyle: {
158
159
  applyAutoScale: options?.brandPageType === BRAND_PAGE_TYPES.brandSite,
@@ -706,6 +707,7 @@ export const createInitialSocialLinksContent = (options) => {
706
707
  title: contentSettingsTr(`followUsOnTitle`),
707
708
  links: [
708
709
  {
710
+ id: uuid.v4(),
709
711
  imageUrl: 'facebook',
710
712
  url: 'https://www.facebook.com',
711
713
  imageTitle: '',
@@ -716,6 +718,7 @@ export const createInitialSocialLinksContent = (options) => {
716
718
  imageLink: '',
717
719
  },
718
720
  {
721
+ id: uuid.v4(),
719
722
  imageUrl: 'instagram',
720
723
  url: 'https://www.instagram.com',
721
724
  imageTitle: '',
@@ -726,6 +729,7 @@ export const createInitialSocialLinksContent = (options) => {
726
729
  imageLink: '',
727
730
  },
728
731
  {
732
+ id: uuid.v4(),
729
733
  imageUrl: 'x',
730
734
  url: 'https://www.x.com',
731
735
  imageTitle: '',
@@ -4581,6 +4581,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
4581
4581
  logoImageBase64Url?: string | undefined;
4582
4582
  socialLinks: {
4583
4583
  url: string;
4584
+ id: string;
4584
4585
  imageUrl: string;
4585
4586
  size?: string | undefined;
4586
4587
  imageTitle: string;
@@ -4805,6 +4806,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
4805
4806
  logoImageBase64Url?: string | undefined;
4806
4807
  socialLinks: {
4807
4808
  url: string;
4809
+ id: string;
4808
4810
  imageUrl: string;
4809
4811
  size?: string | undefined;
4810
4812
  imageTitle: string;
@@ -5029,6 +5031,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
5029
5031
  logoImageBase64Url?: string | undefined;
5030
5032
  socialLinks: {
5031
5033
  url: string;
5034
+ id: string;
5032
5035
  imageUrl: string;
5033
5036
  size?: string | undefined;
5034
5037
  imageTitle: string;
@@ -9690,6 +9693,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
9690
9693
  logoImageBase64Url?: string | undefined;
9691
9694
  socialLinks: {
9692
9695
  url: string;
9696
+ id: string;
9693
9697
  imageUrl: string;
9694
9698
  size?: string | undefined;
9695
9699
  imageTitle: string;
@@ -9914,6 +9918,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
9914
9918
  logoImageBase64Url?: string | undefined;
9915
9919
  socialLinks: {
9916
9920
  url: string;
9921
+ id: string;
9917
9922
  imageUrl: string;
9918
9923
  size?: string | undefined;
9919
9924
  imageTitle: string;
@@ -10138,6 +10143,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
10138
10143
  logoImageBase64Url?: string | undefined;
10139
10144
  socialLinks: {
10140
10145
  url: string;
10146
+ id: string;
10141
10147
  imageUrl: string;
10142
10148
  size?: string | undefined;
10143
10149
  imageTitle: string;
@@ -14805,6 +14811,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
14805
14811
  logoImageBase64Url?: string | undefined;
14806
14812
  socialLinks: {
14807
14813
  url: string;
14814
+ id: string;
14808
14815
  imageUrl: string;
14809
14816
  size?: string | undefined;
14810
14817
  imageTitle: string;
@@ -15029,6 +15036,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
15029
15036
  logoImageBase64Url?: string | undefined;
15030
15037
  socialLinks: {
15031
15038
  url: string;
15039
+ id: string;
15032
15040
  imageUrl: string;
15033
15041
  size?: string | undefined;
15034
15042
  imageTitle: string;
@@ -15253,6 +15261,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
15253
15261
  logoImageBase64Url?: string | undefined;
15254
15262
  socialLinks: {
15255
15263
  url: string;
15264
+ id: string;
15256
15265
  imageUrl: string;
15257
15266
  size?: string | undefined;
15258
15267
  imageTitle: string;
@@ -19914,6 +19923,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
19914
19923
  logoImageBase64Url?: string | undefined;
19915
19924
  socialLinks: {
19916
19925
  url: string;
19926
+ id: string;
19917
19927
  imageUrl: string;
19918
19928
  size?: string | undefined;
19919
19929
  imageTitle: string;
@@ -20138,6 +20148,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
20138
20148
  logoImageBase64Url?: string | undefined;
20139
20149
  socialLinks: {
20140
20150
  url: string;
20151
+ id: string;
20141
20152
  imageUrl: string;
20142
20153
  size?: string | undefined;
20143
20154
  imageTitle: string;
@@ -20362,6 +20373,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
20362
20373
  logoImageBase64Url?: string | undefined;
20363
20374
  socialLinks: {
20364
20375
  url: string;
20376
+ id: string;
20365
20377
  imageUrl: string;
20366
20378
  size?: string | undefined;
20367
20379
  imageTitle: string;
@@ -25029,6 +25041,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
25029
25041
  logoImageBase64Url?: string | undefined;
25030
25042
  socialLinks: {
25031
25043
  url: string;
25044
+ id: string;
25032
25045
  imageUrl: string;
25033
25046
  size?: string | undefined;
25034
25047
  imageTitle: string;
@@ -25253,6 +25266,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
25253
25266
  logoImageBase64Url?: string | undefined;
25254
25267
  socialLinks: {
25255
25268
  url: string;
25269
+ id: string;
25256
25270
  imageUrl: string;
25257
25271
  size?: string | undefined;
25258
25272
  imageTitle: string;
@@ -25477,6 +25491,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
25477
25491
  logoImageBase64Url?: string | undefined;
25478
25492
  socialLinks: {
25479
25493
  url: string;
25494
+ id: string;
25480
25495
  imageUrl: string;
25481
25496
  size?: string | undefined;
25482
25497
  imageTitle: string;
@@ -30138,6 +30153,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
30138
30153
  logoImageBase64Url?: string | undefined;
30139
30154
  socialLinks: {
30140
30155
  url: string;
30156
+ id: string;
30141
30157
  imageUrl: string;
30142
30158
  size?: string | undefined;
30143
30159
  imageTitle: string;
@@ -30362,6 +30378,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
30362
30378
  logoImageBase64Url?: string | undefined;
30363
30379
  socialLinks: {
30364
30380
  url: string;
30381
+ id: string;
30365
30382
  imageUrl: string;
30366
30383
  size?: string | undefined;
30367
30384
  imageTitle: string;
@@ -30586,6 +30603,7 @@ export declare const useAiCheckpointStore: import("pinia").StoreDefinition<"aiCh
30586
30603
  logoImageBase64Url?: string | undefined;
30587
30604
  socialLinks: {
30588
30605
  url: string;
30606
+ id: string;
30589
30607
  imageUrl: string;
30590
30608
  size?: string | undefined;
30591
30609
  imageTitle: string;