@designcrowd/library.brand-page 6.0.12 → 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 (109) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-BfQcnhof.js → CreatedOnBrandCrowd-de-de-CBjFFeBP.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-B86JfNzV.js → CreatedOnBrandCrowd-en-us-NuNXF81K.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-Dy70BV7X.js → CreatedOnBrandCrowd-es-es-BJG8nfug.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CQ8UhGRG.js → CreatedOnBrandCrowd-fr-ca-uX-nL53e.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CQ8UhGRG.js → CreatedOnBrandCrowd-fr-fr-uX-nL53e.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-c257u4q-.js → CreatedOnBrandCrowd-pt-br-DTrgFGQV.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-c257u4q-.js → CreatedOnBrandCrowd-pt-pt-DTrgFGQV.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-cRZ_Lx3_.js → CreatedOnDcom-de-de-DSfpxioT.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-CrfHKR-1.js → CreatedOnDcom-en-us-C7G4gKem.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-BFjhMPTR.js → CreatedOnDcom-es-es-DVckCaji.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-CZimjPcn.js → CreatedOnDcom-fr-ca-C5GDrm_C.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-V1z3-WzE.js → CreatedOnDcom-fr-fr-v5eMm-j2.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-NrmWKrvi.js → CreatedOnDcom-pt-br-Dq3-fPUc.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-CKLASXM9.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 +1 -1
  34. package/lib/src/{lib-CHfUKgt-.js → lib-BG-pyXi9.js} +19091 -18974
  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/utils/minify-brand-page-metadata.d.ts +2 -0
  64. package/lib/src/utils/minify-brand-page-metadata.js +8 -1
  65. package/package.json +1 -1
  66. package/src/brand-page/components/image-gallery/ImageGallery.stories.ts +3 -0
  67. package/src/brand-page/components/image-gallery/ImageGallery.test.ts +1 -0
  68. package/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.ts +2 -1
  69. package/src/brand-page/components/images-section/ImagesSection.stories.ts +2 -1
  70. package/src/brand-page/components/social-links/SocialLinks.stories.ts +3 -0
  71. package/src/brand-page/components/social-links/SocialLinks.vue.test.ts +5 -0
  72. package/src/brand-page/components/testimonial-section/__fixtures__/data.ts +3 -0
  73. package/src/brand-page/components/text/Text.stories.ts +2 -0
  74. package/src/brand-page/models/index.ts +17 -0
  75. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +23 -3
  76. package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +6 -0
  77. package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +12 -0
  78. package/src/brand-page/utils/migration/migration-01.ts +2 -0
  79. package/src/brand-page/utils/migration/migration-18.test.ts +131 -0
  80. package/src/brand-page/utils/migration/migration-18.ts +22 -0
  81. package/src/brand-page/utils/migration.util.ts +7 -0
  82. package/src/brand-page/utils/personalisation.util.test.ts +4 -0
  83. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +1 -0
  84. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -0
  85. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +6 -0
  86. package/src/brand-page-maker/constants/config-settings-constant.ts +4 -0
  87. package/src/brand-page-maker/models/content-settings.ts +4 -0
  88. package/src/metadata-builder/ai-metadata-executor.ts +31 -1
  89. package/src/metadata-builder/builders/footer-builder.test.ts +335 -28
  90. package/src/metadata-builder/builders/footer-builder.ts +40 -57
  91. package/src/metadata-builder/builders/item-id-utils.test.ts +184 -0
  92. package/src/metadata-builder/builders/item-id-utils.ts +117 -0
  93. package/src/metadata-builder/builders/move-page-builder.ts +227 -0
  94. package/src/metadata-builder/builders/nav-utils.ts +141 -0
  95. package/src/metadata-builder/builders/section-builders/image-gallery-builder.ts +62 -88
  96. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +66 -129
  97. package/src/metadata-builder/builders/section-builders/move-section-builder.ts +58 -35
  98. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +105 -160
  99. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +65 -20
  100. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +83 -146
  101. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +71 -122
  102. package/src/metadata-builder/builders/section-field-maps.ts +18 -0
  103. package/src/metadata-builder/builders/set-page-visibility-builder.ts +122 -0
  104. package/src/metadata-builder/metadata-executor.ts +4 -0
  105. package/src/metadata-builder/models.ts +2 -0
  106. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +32 -7
  107. package/src/metadata-builder/parsers/section-tool-arguments.ts +84 -48
  108. package/src/shared/content-settings/components/links-field/LinksField.mixin.ts +2 -0
  109. package/src/utils/minify-brand-page-metadata.ts +14 -2
@@ -57,6 +57,7 @@ exports[`migration.util > Banner Contents - text Align and Font Family should no
57
57
  "socialLinks": [
58
58
  {
59
59
  "height": 0,
60
+ "id": "00000000-0000-4000-8000-000000000004",
60
61
  "imageLink": "",
61
62
  "imageTitle": "",
62
63
  "imageUrl": "facebook",
@@ -66,6 +67,7 @@ exports[`migration.util > Banner Contents - text Align and Font Family should no
66
67
  },
67
68
  {
68
69
  "height": 0,
70
+ "id": "00000000-0000-4000-8000-000000000005",
69
71
  "imageLink": "",
70
72
  "imageTitle": "",
71
73
  "imageUrl": "instagram",
@@ -75,6 +77,7 @@ exports[`migration.util > Banner Contents - text Align and Font Family should no
75
77
  },
76
78
  {
77
79
  "height": 0,
80
+ "id": "00000000-0000-4000-8000-000000000006",
78
81
  "imageLink": "",
79
82
  "imageTitle": "",
80
83
  "imageUrl": "x",
@@ -112,6 +115,7 @@ exports[`migration.util > Banner Contents - text Align and Font Family should no
112
115
  "socialLinks": [
113
116
  {
114
117
  "height": 0,
118
+ "id": "00000000-0000-4000-8000-000000000001",
115
119
  "imageLink": "",
116
120
  "imageTitle": "",
117
121
  "imageUrl": "facebook",
@@ -121,6 +125,7 @@ exports[`migration.util > Banner Contents - text Align and Font Family should no
121
125
  },
122
126
  {
123
127
  "height": 0,
128
+ "id": "00000000-0000-4000-8000-000000000002",
124
129
  "imageLink": "",
125
130
  "imageTitle": "",
126
131
  "imageUrl": "instagram",
@@ -130,6 +135,7 @@ exports[`migration.util > Banner Contents - text Align and Font Family should no
130
135
  },
131
136
  {
132
137
  "height": 0,
138
+ "id": "00000000-0000-4000-8000-000000000003",
133
139
  "imageLink": "",
134
140
  "imageTitle": "",
135
141
  "imageUrl": "x",
@@ -457,7 +463,7 @@ exports[`migration.util > Banner Contents - text Align and Font Family should no
457
463
  },
458
464
  },
459
465
  "userPromptContentKey": undefined,
460
- "v": 17,
466
+ "v": 18,
461
467
  },
462
468
  "useOldLogoRenderSize": true,
463
469
  }
@@ -520,6 +526,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
520
526
  "socialLinks": [
521
527
  {
522
528
  "height": 0,
529
+ "id": "00000000-0000-4000-8000-000000000004",
523
530
  "imageLink": "",
524
531
  "imageTitle": "",
525
532
  "imageUrl": "facebook",
@@ -529,6 +536,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
529
536
  },
530
537
  {
531
538
  "height": 0,
539
+ "id": "00000000-0000-4000-8000-000000000005",
532
540
  "imageLink": "",
533
541
  "imageTitle": "",
534
542
  "imageUrl": "instagram",
@@ -538,6 +546,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
538
546
  },
539
547
  {
540
548
  "height": 0,
549
+ "id": "00000000-0000-4000-8000-000000000006",
541
550
  "imageLink": "",
542
551
  "imageTitle": "",
543
552
  "imageUrl": "x",
@@ -575,6 +584,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
575
584
  "socialLinks": [
576
585
  {
577
586
  "height": 0,
587
+ "id": "00000000-0000-4000-8000-000000000001",
578
588
  "imageLink": "",
579
589
  "imageTitle": "",
580
590
  "imageUrl": "facebook",
@@ -584,6 +594,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
584
594
  },
585
595
  {
586
596
  "height": 0,
597
+ "id": "00000000-0000-4000-8000-000000000002",
587
598
  "imageLink": "",
588
599
  "imageTitle": "",
589
600
  "imageUrl": "instagram",
@@ -593,6 +604,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
593
604
  },
594
605
  {
595
606
  "height": 0,
607
+ "id": "00000000-0000-4000-8000-000000000003",
596
608
  "imageLink": "",
597
609
  "imageTitle": "",
598
610
  "imageUrl": "x",
@@ -760,6 +772,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
760
772
  "textColor": {},
761
773
  "textItems": [
762
774
  {
775
+ "id": "00000000-0000-4000-8000-000000000007",
763
776
  "text": "Christmas",
764
777
  "textStyle": {
765
778
  "applyAutoScale": true,
@@ -903,7 +916,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
903
916
  },
904
917
  },
905
918
  "userPromptContentKey": undefined,
906
- "v": 17,
919
+ "v": 18,
907
920
  },
908
921
  "useOldLogoRenderSize": true,
909
922
  }
@@ -966,6 +979,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
966
979
  "socialLinks": [
967
980
  {
968
981
  "height": 0,
982
+ "id": "00000000-0000-4000-8000-000000000004",
969
983
  "imageLink": "",
970
984
  "imageTitle": "",
971
985
  "imageUrl": "facebook",
@@ -975,6 +989,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
975
989
  },
976
990
  {
977
991
  "height": 0,
992
+ "id": "00000000-0000-4000-8000-000000000005",
978
993
  "imageLink": "",
979
994
  "imageTitle": "",
980
995
  "imageUrl": "instagram",
@@ -984,6 +999,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
984
999
  },
985
1000
  {
986
1001
  "height": 0,
1002
+ "id": "00000000-0000-4000-8000-000000000006",
987
1003
  "imageLink": "",
988
1004
  "imageTitle": "",
989
1005
  "imageUrl": "x",
@@ -1021,6 +1037,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
1021
1037
  "socialLinks": [
1022
1038
  {
1023
1039
  "height": 0,
1040
+ "id": "00000000-0000-4000-8000-000000000001",
1024
1041
  "imageLink": "",
1025
1042
  "imageTitle": "",
1026
1043
  "imageUrl": "facebook",
@@ -1030,6 +1047,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
1030
1047
  },
1031
1048
  {
1032
1049
  "height": 0,
1050
+ "id": "00000000-0000-4000-8000-000000000002",
1033
1051
  "imageLink": "",
1034
1052
  "imageTitle": "",
1035
1053
  "imageUrl": "instagram",
@@ -1039,6 +1057,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
1039
1057
  },
1040
1058
  {
1041
1059
  "height": 0,
1060
+ "id": "00000000-0000-4000-8000-000000000003",
1042
1061
  "imageLink": "",
1043
1062
  "imageTitle": "",
1044
1063
  "imageUrl": "x",
@@ -1206,6 +1225,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
1206
1225
  "textColor": {},
1207
1226
  "textItems": [
1208
1227
  {
1228
+ "id": "00000000-0000-4000-8000-000000000007",
1209
1229
  "text": "Christmas",
1210
1230
  "textStyle": {
1211
1231
  "applyAutoScale": true,
@@ -1356,7 +1376,7 @@ exports[`migration.util > migrateBrandPageModel should return brand page model w
1356
1376
  },
1357
1377
  },
1358
1378
  "userPromptContentKey": undefined,
1359
- "v": 17,
1379
+ "v": 18,
1360
1380
  },
1361
1381
  "useOldLogoRenderSize": true,
1362
1382
  }
@@ -45,6 +45,7 @@ exports[`migration02.ts > migration02 should return converted letterspacing 1`]
45
45
  "socialLinks": [
46
46
  {
47
47
  "height": 0,
48
+ "id": "00000000-0000-4000-8000-000000000004",
48
49
  "imageLink": "",
49
50
  "imageTitle": "",
50
51
  "imageUrl": "facebook",
@@ -54,6 +55,7 @@ exports[`migration02.ts > migration02 should return converted letterspacing 1`]
54
55
  },
55
56
  {
56
57
  "height": 0,
58
+ "id": "00000000-0000-4000-8000-000000000005",
57
59
  "imageLink": "",
58
60
  "imageTitle": "",
59
61
  "imageUrl": "instagram",
@@ -63,6 +65,7 @@ exports[`migration02.ts > migration02 should return converted letterspacing 1`]
63
65
  },
64
66
  {
65
67
  "height": 0,
68
+ "id": "00000000-0000-4000-8000-000000000006",
66
69
  "imageLink": "",
67
70
  "imageTitle": "",
68
71
  "imageUrl": "x",
@@ -101,6 +104,7 @@ exports[`migration02.ts > migration02 should return converted letterspacing 1`]
101
104
  "socialLinks": [
102
105
  {
103
106
  "height": 0,
107
+ "id": "00000000-0000-4000-8000-000000000001",
104
108
  "imageLink": "",
105
109
  "imageTitle": "",
106
110
  "imageUrl": "facebook",
@@ -110,6 +114,7 @@ exports[`migration02.ts > migration02 should return converted letterspacing 1`]
110
114
  },
111
115
  {
112
116
  "height": 0,
117
+ "id": "00000000-0000-4000-8000-000000000002",
113
118
  "imageLink": "",
114
119
  "imageTitle": "",
115
120
  "imageUrl": "instagram",
@@ -119,6 +124,7 @@ exports[`migration02.ts > migration02 should return converted letterspacing 1`]
119
124
  },
120
125
  {
121
126
  "height": 0,
127
+ "id": "00000000-0000-4000-8000-000000000003",
122
128
  "imageLink": "",
123
129
  "imageTitle": "",
124
130
  "imageUrl": "x",
@@ -44,6 +44,7 @@ BrandPageModel {
44
44
  "socialLinks": [
45
45
  {
46
46
  "height": 0,
47
+ "id": "00000000-0000-4000-8000-000000000004",
47
48
  "imageLink": "",
48
49
  "imageTitle": "",
49
50
  "imageUrl": "facebook",
@@ -53,6 +54,7 @@ BrandPageModel {
53
54
  },
54
55
  {
55
56
  "height": 0,
57
+ "id": "00000000-0000-4000-8000-000000000005",
56
58
  "imageLink": "",
57
59
  "imageTitle": "",
58
60
  "imageUrl": "instagram",
@@ -62,6 +64,7 @@ BrandPageModel {
62
64
  },
63
65
  {
64
66
  "height": 0,
67
+ "id": "00000000-0000-4000-8000-000000000006",
65
68
  "imageLink": "",
66
69
  "imageTitle": "",
67
70
  "imageUrl": "x",
@@ -100,6 +103,7 @@ BrandPageModel {
100
103
  "socialLinks": [
101
104
  {
102
105
  "height": 0,
106
+ "id": "00000000-0000-4000-8000-000000000001",
103
107
  "imageLink": "",
104
108
  "imageTitle": "",
105
109
  "imageUrl": "facebook",
@@ -109,6 +113,7 @@ BrandPageModel {
109
113
  },
110
114
  {
111
115
  "height": 0,
116
+ "id": "00000000-0000-4000-8000-000000000002",
112
117
  "imageLink": "",
113
118
  "imageTitle": "",
114
119
  "imageUrl": "instagram",
@@ -118,6 +123,7 @@ BrandPageModel {
118
123
  },
119
124
  {
120
125
  "height": 0,
126
+ "id": "00000000-0000-4000-8000-000000000003",
121
127
  "imageLink": "",
122
128
  "imageTitle": "",
123
129
  "imageUrl": "x",
@@ -495,6 +501,7 @@ BrandPageModel {
495
501
  "socialLinks": [
496
502
  {
497
503
  "height": 0,
504
+ "id": "00000000-0000-4000-8000-000000000004",
498
505
  "imageLink": "",
499
506
  "imageTitle": "",
500
507
  "imageUrl": "facebook",
@@ -504,6 +511,7 @@ BrandPageModel {
504
511
  },
505
512
  {
506
513
  "height": 0,
514
+ "id": "00000000-0000-4000-8000-000000000005",
507
515
  "imageLink": "",
508
516
  "imageTitle": "",
509
517
  "imageUrl": "instagram",
@@ -513,6 +521,7 @@ BrandPageModel {
513
521
  },
514
522
  {
515
523
  "height": 0,
524
+ "id": "00000000-0000-4000-8000-000000000006",
516
525
  "imageLink": "",
517
526
  "imageTitle": "",
518
527
  "imageUrl": "x",
@@ -551,6 +560,7 @@ BrandPageModel {
551
560
  "socialLinks": [
552
561
  {
553
562
  "height": 0,
563
+ "id": "00000000-0000-4000-8000-000000000001",
554
564
  "imageLink": "",
555
565
  "imageTitle": "",
556
566
  "imageUrl": "facebook",
@@ -560,6 +570,7 @@ BrandPageModel {
560
570
  },
561
571
  {
562
572
  "height": 0,
573
+ "id": "00000000-0000-4000-8000-000000000002",
563
574
  "imageLink": "",
564
575
  "imageTitle": "",
565
576
  "imageUrl": "instagram",
@@ -569,6 +580,7 @@ BrandPageModel {
569
580
  },
570
581
  {
571
582
  "height": 0,
583
+ "id": "00000000-0000-4000-8000-000000000003",
572
584
  "imageLink": "",
573
585
  "imageTitle": "",
574
586
  "imageUrl": "x",
@@ -1,3 +1,4 @@
1
+ import * as uuid from 'uuid';
1
2
  import {
2
3
  getLogoVariationIndexFromLogoImageUrl,
3
4
  getLogoDraftTokenFromLogoImageUrl,
@@ -101,6 +102,7 @@ export const applyTextContentTextToTextItemsMigration = (
101
102
  }
102
103
 
103
104
  const textItem: TextItem = {
105
+ id: uuid.v4(),
104
106
  text: item.text,
105
107
  textStyle,
106
108
  };
@@ -0,0 +1,131 @@
1
+ import { describe, test, expect } from 'vitest';
2
+ import { migration18 } from './migration-18';
3
+ import type { MigrationData } from '../migration.util';
4
+
5
+ const createMigrationData = (brandPageModel: any): MigrationData => ({
6
+ brandPageModel,
7
+ useOldLogoRenderSize: false,
8
+ });
9
+
10
+ const createModel = (overrides: any = {}) => ({
11
+ v: 17,
12
+ pages: [
13
+ {
14
+ title: 'Home',
15
+ slug: 'home',
16
+ contents: [
17
+ {
18
+ id: 'gallery-1',
19
+ type: 'image-gallery',
20
+ images: [
21
+ { imageUrl: 'a.jpg', imageTitle: 'A' },
22
+ { imageUrl: 'b.jpg', imageTitle: 'B' },
23
+ ],
24
+ },
25
+ {
26
+ id: 'testimonials-1',
27
+ type: 'testimonial-section',
28
+ items: [
29
+ { name: 'Ada', testimonials: 'Great' },
30
+ { name: 'Grace', testimonials: 'Superb' },
31
+ ],
32
+ },
33
+ {
34
+ id: 'text-1',
35
+ type: 'text',
36
+ textItems: [{ text: 'Hello' }, { text: 'World' }],
37
+ },
38
+ {
39
+ id: 'social-1',
40
+ type: 'social-links',
41
+ links: [
42
+ { imageUrl: 'facebook', url: 'https://facebook.com' },
43
+ { imageUrl: 'x', url: 'https://x.com' },
44
+ ],
45
+ },
46
+ ],
47
+ },
48
+ ],
49
+ pageFooterDesktop: {
50
+ socialLinks: [
51
+ { imageUrl: 'facebook', url: 'https://facebook.com' },
52
+ { imageUrl: 'instagram', url: 'https://instagram.com' },
53
+ ],
54
+ },
55
+ pageFooterMobile: {
56
+ socialLinks: [{ imageUrl: 'x', url: 'https://x.com' }],
57
+ },
58
+ ...overrides,
59
+ });
60
+
61
+ const allNestedItems = (model: any): any[] => {
62
+ const [gallery, testimonials, text, social] = model.pages[0].contents;
63
+
64
+ return [
65
+ ...gallery.images,
66
+ ...testimonials.items,
67
+ ...text.textItems,
68
+ ...social.links,
69
+ ...model.pageFooterDesktop.socialLinks,
70
+ ...model.pageFooterMobile.socialLinks,
71
+ ];
72
+ };
73
+
74
+ describe('migration18', () => {
75
+ test('backfills a stable id onto every nested item that lacks one', async () => {
76
+ const model = createModel();
77
+
78
+ const result = await migration18(createMigrationData(model));
79
+
80
+ const items = allNestedItems(result.brandPageModel);
81
+
82
+ expect(items).toHaveLength(11);
83
+ items.forEach((item) => expect(item.id).toBeTruthy());
84
+ });
85
+
86
+ test('generates unique ids across all nested items', async () => {
87
+ const model = createModel();
88
+
89
+ const result = await migration18(createMigrationData(model));
90
+
91
+ const ids = allNestedItems(result.brandPageModel).map((i) => i.id);
92
+
93
+ expect(new Set(ids).size).toBe(ids.length);
94
+ });
95
+
96
+ test('preserves ids that already exist', async () => {
97
+ const model = createModel();
98
+
99
+ model.pages[0].contents[0].images[0].id = 'keep-me';
100
+ model.pageFooterMobile.socialLinks[0].id = 'keep-footer';
101
+
102
+ // migration mutates in place, so assert against the same (any-typed) model.
103
+ await migration18(createMigrationData(model));
104
+
105
+ expect(model.pages[0].contents[0].images[0].id).toBe('keep-me');
106
+ expect(model.pageFooterMobile.socialLinks[0].id).toBe('keep-footer');
107
+ });
108
+
109
+ test('is idempotent — a second run does not change any id', async () => {
110
+ const model = createModel();
111
+
112
+ await migration18(createMigrationData(model));
113
+ const firstPass = allNestedItems(model).map((i) => i.id);
114
+
115
+ await migration18(createMigrationData(model));
116
+ const secondPass = allNestedItems(model).map((i) => i.id);
117
+
118
+ expect(secondPass).toEqual(firstPass);
119
+ });
120
+
121
+ test('handles a model with no footers and empty pages without throwing', async () => {
122
+ const model = {
123
+ v: 17,
124
+ pages: [{ title: 'Home', slug: 'home', contents: [] }],
125
+ };
126
+
127
+ const result = await migration18(createMigrationData(model));
128
+
129
+ expect(result.brandPageModel).toBe(model);
130
+ });
131
+ });
@@ -0,0 +1,22 @@
1
+ import type { MigrationData } from '../migration.util';
2
+ import { ensureBrandPageItemIds } from '../../../metadata-builder/builders/item-id-utils';
3
+
4
+ /**
5
+ * BP-5603: backfill a stable uuid `id` onto every nested item (gallery images,
6
+ * images/shapes/testimonial items, text items, section + footer social links)
7
+ * that predates the id-based edit model.
8
+ *
9
+ * The item `id` field is now non-nullable in the model, so every load path must
10
+ * guarantee it — not just the AI chat flow, which already stamps ids before
11
+ * minifying (see ensureBrandPageItemIds in useAiWebsiteBuilderChat). This
12
+ * migration is that guarantee for persisted data. Idempotent — existing ids are
13
+ * preserved, so re-running (e.g. render-only sites that never re-save) is a
14
+ * no-op beyond generating ids for items that still lack one.
15
+ */
16
+ export const migration18 = async (
17
+ migrationResult: MigrationData,
18
+ ): Promise<MigrationData> => {
19
+ ensureBrandPageItemIds(migrationResult.brandPageModel);
20
+
21
+ return migrationResult;
22
+ };
@@ -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
 
24
25
  export interface MigrationData {
25
26
  brandPageModel: BrandPageModel;
@@ -160,6 +161,12 @@ const MIGRATION_TABLE = [
160
161
  description:
161
162
  '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)',
162
163
  },
164
+ {
165
+ version: 18,
166
+ migrateFn: migration18,
167
+ description:
168
+ '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',
169
+ },
163
170
  ] as MigrationTableItem[];
164
171
 
165
172
  export const GetLatestModelVersion = () =>
@@ -432,6 +432,7 @@ describe('personalisation.util', async () => {
432
432
  personalisationRole: 'profile',
433
433
  items: [
434
434
  {
435
+ id: 'shapes-item-1',
435
436
  colorReplacements: [],
436
437
  height: -1,
437
438
  imageUrl: 'shape-1.svg',
@@ -986,6 +987,7 @@ describe('personalisation.util', async () => {
986
987
  personalisationRole: 'media',
987
988
  items: [
988
989
  {
990
+ id: 'shapes-item-1',
989
991
  colorReplacements: [],
990
992
  height: -1,
991
993
  imageUrl: 'shape-1.svg',
@@ -1052,6 +1054,7 @@ describe('personalisation.util', async () => {
1052
1054
  personalisationRole: 'media',
1053
1055
  items: [
1054
1056
  {
1057
+ id: 'shapes-item-1',
1055
1058
  colorReplacements: [],
1056
1059
  height: -1,
1057
1060
  imageUrl: 'https://bcassetcdn.com/shapes/prod/original-shape.svg',
@@ -1141,6 +1144,7 @@ describe('personalisation.util', async () => {
1141
1144
  personalisationRole: 'media',
1142
1145
  items: [
1143
1146
  {
1147
+ id: 'shapes-item-1',
1144
1148
  colorReplacements: [],
1145
1149
  height: -1,
1146
1150
  imageUrl: 'https://bcassetcdn.com/shapes/prod/original-shape.svg',
@@ -1498,6 +1498,7 @@ export const SampleImageGallery = (): any => {
1498
1498
  const width = 300;
1499
1499
  const height = 300;
1500
1500
  imageGalleryContent.images!.push({
1501
+ id: `gallery-item-${i}`,
1501
1502
  width,
1502
1503
  height,
1503
1504
  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`,
@@ -2314,6 +2314,7 @@ export const BRAND_PAGE_PERSONALISED: BrandPageData = {
2314
2314
  displayStyle: 'centered',
2315
2315
  items: [
2316
2316
  {
2317
+ id: 'shapes-section-item-1',
2317
2318
  colorReplacements: [],
2318
2319
  height: -1,
2319
2320
  imageUrl:
@@ -18,6 +18,7 @@ import {
18
18
  type PlanItem,
19
19
  } from '../../../clients/websocket-gateway-client';
20
20
  import { minifyBrandPageMetadata } from '../../../utils/minify-brand-page-metadata';
21
+ import { ensureBrandPageItemIds } from '../../../metadata-builder/builders/item-id-utils';
21
22
  import { buildAssetManifest } from '../../../utils/build-asset-manifest';
22
23
  import cloneDeep from 'lodash.clonedeep';
23
24
  import { usePageNavigationStore } from '../../../shared/page-navigation/store/page-navigation-store';
@@ -259,6 +260,11 @@ export function useAiWebsiteBuilderChat(): UseAiChatResult {
259
260
 
260
261
  const buildMessagePayload = async (userPrompt: string) => {
261
262
  const brandPageData = brandPageMakerStore.brandPageData;
263
+
264
+ // BP-5603: stamp stable uuid ids onto every nested item BEFORE minifying,
265
+ // so the id the AI is shown (and returns as `item_id`) is the exact id the
266
+ // executor matches when applying tool calls to this same live model.
267
+ ensureBrandPageItemIds(brandPageData);
262
268
  const headerLogoDraftToken =
263
269
  brandPageData.pageHeaderDesktop?.logoImage?.logoDraftToken ??
264
270
  uiStore.logoDraftToken;
@@ -85,6 +85,7 @@ import {
85
85
  createInitialShopContent,
86
86
  createInitialBookingSectionContent,
87
87
  } from '../models';
88
+ import * as uuid from 'uuid';
88
89
  import type {
89
90
  ContentReplaceImageSettings,
90
91
  SetContentMediaPayload,
@@ -353,6 +354,7 @@ const imageGalleryReplaceImageSettings =
353
354
  }
354
355
 
355
356
  content.images.push({
357
+ id: uuid.v4(),
356
358
  imageUrl: value.imageUrl,
357
359
  imageTitle: value.imageTitle,
358
360
  height: value.height!,
@@ -614,6 +616,7 @@ const shapesImageReplaceImageSettings =
614
616
  ) => {
615
617
  if (index === undefined || index === null) {
616
618
  content.items?.push({
619
+ id: uuid.v4(),
617
620
  imageUrl: value.imageUrl,
618
621
  imageTitle: '',
619
622
  paragraph: '',
@@ -652,6 +655,7 @@ const textImageReplaceImageSettings =
652
655
  ) => {
653
656
  if (index === undefined || index === null) {
654
657
  content.items?.push({
658
+ id: uuid.v4(),
655
659
  imageUrl: value.imageUrl,
656
660
  imageTitle: value.imageTitle,
657
661
  paragraph: '',
@@ -233,6 +233,7 @@ export const createInitialTextContent = (
233
233
  options?.brandPageType === 'brandSite'
234
234
  ? [
235
235
  {
236
+ id: uuid.v4(),
236
237
  text: contentSettingsTr(`defaultTextValue`),
237
238
  textStyle: {
238
239
  applyAutoScale:
@@ -835,6 +836,7 @@ export const createInitialSocialLinksContent = (
835
836
  title: contentSettingsTr(`followUsOnTitle`),
836
837
  links: [
837
838
  {
839
+ id: uuid.v4(),
838
840
  imageUrl: 'facebook',
839
841
  url: 'https://www.facebook.com',
840
842
  imageTitle: '',
@@ -845,6 +847,7 @@ export const createInitialSocialLinksContent = (
845
847
  imageLink: '',
846
848
  },
847
849
  {
850
+ id: uuid.v4(),
848
851
  imageUrl: 'instagram',
849
852
  url: 'https://www.instagram.com',
850
853
  imageTitle: '',
@@ -855,6 +858,7 @@ export const createInitialSocialLinksContent = (
855
858
  imageLink: '',
856
859
  },
857
860
  {
861
+ id: uuid.v4(),
858
862
  imageUrl: 'x',
859
863
  url: 'https://www.x.com',
860
864
  imageTitle: '',