@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
@@ -92,10 +92,15 @@ export interface ProfileSectionArguments {
92
92
  background_color?: string | null;
93
93
  }
94
94
  export interface TextSectionItem {
95
- /** 0-based index of existing item to update in-place */
96
- item_index?: number;
97
- /** 0-based position to insert a new item at */
98
- insert_at?: number;
95
+ /** Stable id of the existing item to update or move. Omit to ADD a new item. */
96
+ item_id?: string;
97
+ /**
98
+ * Id of an existing item to position this item before (insert for new items,
99
+ * move for existing ones). Use "__end__" for the end of the list. Omit to
100
+ * leave an existing item in place / append a new item. Mirrors the
101
+ * section-level move_before_content_id.
102
+ */
103
+ move_before_item_id?: string;
99
104
  text?: RichTextField;
100
105
  text_style?: TextStyleArguments;
101
106
  }
@@ -108,21 +113,26 @@ export interface TextSectionArguments {
108
113
  /** Multiple text items (BrandSite) */
109
114
  items?: TextSectionItem[];
110
115
  _replace_items?: boolean;
111
- /** 0-based indices of items to remove */
112
- _remove_item_indices?: number[];
113
- /** New order as array of current 0-based indices */
114
- _reorder_items?: number[];
116
+ /** Stable ids of items to remove. Order-independent (no index shifting). */
117
+ _remove_item_ids?: string[];
115
118
  background_color?: string | null;
119
+ padding_top?: number;
120
+ padding_bottom?: number;
116
121
  }
117
122
  export interface ImageSectionArguments {
118
123
  image_url?: string;
119
124
  image_title?: string;
120
125
  }
121
126
  export interface ImageGalleryItem {
122
- /** 0-based index of existing item to update in-place */
123
- item_index?: number;
124
- /** 0-based position to insert a new item at */
125
- insert_at?: number;
127
+ /** Stable id of the existing item to update or move. Omit to ADD a new item. */
128
+ item_id?: string;
129
+ /**
130
+ * Id of an existing item to position this item before (insert for new items,
131
+ * move for existing ones). Use "__end__" for the end of the list. Omit to
132
+ * leave an existing item in place / append a new item. Mirrors the
133
+ * section-level move_before_content_id.
134
+ */
135
+ move_before_item_id?: string;
126
136
  image_url?: string;
127
137
  caption?: string;
128
138
  }
@@ -131,10 +141,10 @@ export interface ImageGallerySectionArguments {
131
141
  gallery_type?: 'grid' | 'carousel' | 'masonry';
132
142
  is_full_width?: boolean;
133
143
  _replace_items?: boolean;
134
- /** 0-based indices of items to remove */
135
- _remove_item_indices?: number[];
136
- /** New order as array of current 0-based indices */
137
- _reorder_items?: number[];
144
+ /** Stable ids of items to remove. Order-independent (no index shifting). */
145
+ _remove_item_ids?: string[];
146
+ padding_top?: number;
147
+ padding_bottom?: number;
138
148
  }
139
149
  export interface GeneralLinkSectionArguments {
140
150
  title?: string;
@@ -189,10 +199,15 @@ export interface TiktokSectionArguments {
189
199
  url?: string;
190
200
  }
191
201
  export interface SocialLink {
192
- /** 0-based index of existing item to update in-place */
193
- item_index?: number;
194
- /** 0-based position to insert a new item at */
195
- insert_at?: number;
202
+ /** Stable id of the existing item to update or move. Omit to ADD a new item. */
203
+ item_id?: string;
204
+ /**
205
+ * Id of an existing item to position this item before (insert for new items,
206
+ * move for existing ones). Use "__end__" for the end of the list. Omit to
207
+ * leave an existing item in place / append a new item. Mirrors the
208
+ * section-level move_before_content_id.
209
+ */
210
+ move_before_item_id?: string;
196
211
  platform?: 'facebook' | 'x' | 'instagram' | 'youtube' | 'linkedin' | 'pinterest' | 'twitch' | 'tiktok';
197
212
  url?: string;
198
213
  }
@@ -204,10 +219,10 @@ export interface SocialLinksSectionArguments {
204
219
  /** Style for the icon container background (used when icon_style is 'square' or 'circle'). */
205
220
  icon_background_style?: TextStyleArguments;
206
221
  _replace_items?: boolean;
207
- /** 0-based indices of items to remove */
208
- _remove_item_indices?: number[];
209
- /** New order as array of current 0-based indices */
210
- _reorder_items?: number[];
222
+ /** Stable ids of items to remove. Order-independent (no index shifting). */
223
+ _remove_item_ids?: string[];
224
+ padding_top?: number;
225
+ padding_bottom?: number;
211
226
  }
212
227
  export interface MailingListSectionArguments {
213
228
  title?: RichTextField;
@@ -215,6 +230,8 @@ export interface MailingListSectionArguments {
215
230
  accepted_fields?: 'emailOnly' | 'nameAndEmail';
216
231
  title_style?: TextStyleArguments;
217
232
  button_text_style?: ButtonTextStyleArguments;
233
+ padding_top?: number;
234
+ padding_bottom?: number;
218
235
  }
219
236
  export interface ContactFormFieldToggle {
220
237
  /** Field ID matching FORM_FIELD_IDS (e.g., 'firstName', 'lastName', 'phoneNumber', 'message') */
@@ -239,6 +256,8 @@ export interface ContactFormSectionArguments {
239
256
  fields?: ContactFormFieldToggle[];
240
257
  background_color?: string | null;
241
258
  card_style?: CardStyleArguments;
259
+ padding_top?: number;
260
+ padding_bottom?: number;
242
261
  }
243
262
  export interface BannerSectionArguments {
244
263
  title?: RichTextField;
@@ -255,6 +274,8 @@ export interface BannerSectionArguments {
255
274
  button_text_style?: ButtonTextStyleArguments;
256
275
  background_color?: string | null;
257
276
  card_style?: CardStyleArguments;
277
+ padding_top?: number;
278
+ padding_bottom?: number;
258
279
  }
259
280
  export interface AboutSectionArguments {
260
281
  title?: RichTextField;
@@ -266,12 +287,19 @@ export interface AboutSectionArguments {
266
287
  title_style?: TextStyleArguments;
267
288
  paragraph_style?: TextStyleArguments;
268
289
  background_color?: string | null;
290
+ padding_top?: number;
291
+ padding_bottom?: number;
269
292
  }
270
293
  export interface ImagesSectionItem {
271
- /** 0-based index of existing item to update in-place */
272
- item_index?: number;
273
- /** 0-based position to insert a new item at */
274
- insert_at?: number;
294
+ /** Stable id of the existing item to update or move. Omit to ADD a new item. */
295
+ item_id?: string;
296
+ /**
297
+ * Id of an existing item to position this item before (insert for new items,
298
+ * move for existing ones). Use "__end__" for the end of the list. Omit to
299
+ * leave an existing item in place / append a new item. Mirrors the
300
+ * section-level move_before_content_id.
301
+ */
302
+ move_before_item_id?: string;
275
303
  image_url?: string;
276
304
  heading?: string;
277
305
  text?: string;
@@ -283,10 +311,8 @@ export interface ImagesSectionArguments {
283
311
  items?: ImagesSectionItem[];
284
312
  display_style?: 'left-aligned' | 'right-aligned' | 'centered' | 'media-only' | 'center-card-aligned-image' | 'alternate-image';
285
313
  _replace_items?: boolean;
286
- /** 0-based indices of items to remove */
287
- _remove_item_indices?: number[];
288
- /** New order as array of current 0-based indices */
289
- _reorder_items?: number[];
314
+ /** Stable ids of items to remove. Order-independent (no index shifting). */
315
+ _remove_item_ids?: string[];
290
316
  title_style?: TextStyleArguments;
291
317
  description_style?: TextStyleArguments;
292
318
  heading_style?: TextStyleArguments;
@@ -298,10 +324,15 @@ export interface ImagesSectionArguments {
298
324
  card_style?: CardStyleArguments;
299
325
  }
300
326
  export interface TestimonialItem {
301
- /** 0-based index of existing item to update in-place */
302
- item_index?: number;
303
- /** 0-based position to insert a new item at */
304
- insert_at?: number;
327
+ /** Stable id of the existing item to update or move. Omit to ADD a new item. */
328
+ item_id?: string;
329
+ /**
330
+ * Id of an existing item to position this item before (insert for new items,
331
+ * move for existing ones). Use "__end__" for the end of the list. Omit to
332
+ * leave an existing item in place / append a new item. Mirrors the
333
+ * section-level move_before_content_id.
334
+ */
335
+ move_before_item_id?: string;
305
336
  testimonial?: string;
306
337
  name?: string;
307
338
  position?: string;
@@ -314,22 +345,27 @@ export interface TestimonialSectionArguments {
314
345
  items?: TestimonialItem[];
315
346
  display_style?: 'centered' | 'big-image' | 'columns';
316
347
  _replace_items?: boolean;
317
- /** 0-based indices of items to remove */
318
- _remove_item_indices?: number[];
319
- /** New order as array of current 0-based indices */
320
- _reorder_items?: number[];
348
+ /** Stable ids of items to remove. Order-independent (no index shifting). */
349
+ _remove_item_ids?: string[];
321
350
  title_style?: TextStyleArguments;
322
351
  testimonial_style?: TextStyleArguments;
323
352
  name_style?: TextStyleArguments;
324
353
  position_style?: TextStyleArguments;
325
354
  background_style?: BackgroundStyleArguments;
326
355
  card_style?: CardStyleArguments;
356
+ padding_top?: number;
357
+ padding_bottom?: number;
327
358
  }
328
359
  export interface ShapesSectionItem {
329
- /** 0-based index of existing item to update in-place */
330
- item_index?: number;
331
- /** 0-based position to insert a new item at */
332
- insert_at?: number;
360
+ /** Stable id of the existing item to update or move. Omit to ADD a new item. */
361
+ item_id?: string;
362
+ /**
363
+ * Id of an existing item to position this item before (insert for new items,
364
+ * move for existing ones). Use "__end__" for the end of the list. Omit to
365
+ * leave an existing item in place / append a new item. Mirrors the
366
+ * section-level move_before_content_id.
367
+ */
368
+ move_before_item_id?: string;
333
369
  icon_image_url?: string;
334
370
  shape_url?: string;
335
371
  color_theme?: string;
@@ -342,10 +378,8 @@ export interface ShapesSectionArguments {
342
378
  items?: ShapesSectionItem[];
343
379
  display_style?: 'left-aligned' | 'right-aligned' | 'centered' | 'media-only' | 'center-card-aligned-image' | 'alternate-image';
344
380
  _replace_items?: boolean;
345
- /** 0-based indices of items to remove */
346
- _remove_item_indices?: number[];
347
- /** New order as array of current 0-based indices */
348
- _reorder_items?: number[];
381
+ /** Stable ids of items to remove. Order-independent (no index shifting). */
382
+ _remove_item_ids?: string[];
349
383
  title_style?: TextStyleArguments;
350
384
  description_style?: TextStyleArguments;
351
385
  heading_style?: TextStyleArguments;
@@ -364,6 +398,8 @@ export interface BookingSectionArguments {
364
398
  description_style?: TextStyleArguments;
365
399
  button_text_style?: ButtonTextStyleArguments;
366
400
  background_color?: string | null;
401
+ padding_top?: number;
402
+ padding_bottom?: number;
367
403
  }
368
404
  export interface DividerSectionArguments {
369
405
  divider_style?: 'none' | 'thin' | 'thick';
@@ -1,5 +1,6 @@
1
1
  import { defineComponent } from 'vue';
2
2
  import cloneDeep from 'lodash.clonedeep';
3
+ import * as uuid from 'uuid';
3
4
  const ACCEPTED_MIME_TYPES = 'image/png, image/jpeg, image/svg+xml';
4
5
  export default defineComponent({
5
6
  props: {
@@ -75,6 +76,7 @@ export default defineComponent({
75
76
  },
76
77
  addNewItem() {
77
78
  const newItem = {
79
+ id: uuid.v4(),
78
80
  height: 0,
79
81
  imageTitle: '',
80
82
  width: 0,
@@ -2871,6 +2871,7 @@ declare const _default: import("vue").DefineComponent<{}, {
2871
2871
  logoImageBase64Url?: string | undefined;
2872
2872
  socialLinks: {
2873
2873
  url: string;
2874
+ id: string;
2874
2875
  imageUrl: string;
2875
2876
  size?: string | undefined;
2876
2877
  imageTitle: string;
@@ -3095,6 +3096,7 @@ declare const _default: import("vue").DefineComponent<{}, {
3095
3096
  logoImageBase64Url?: string | undefined;
3096
3097
  socialLinks: {
3097
3098
  url: string;
3099
+ id: string;
3098
3100
  imageUrl: string;
3099
3101
  size?: string | undefined;
3100
3102
  imageTitle: string;
@@ -2824,6 +2824,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
2824
2824
  logoImageBase64Url?: string | undefined;
2825
2825
  socialLinks: {
2826
2826
  url: string;
2827
+ id: string;
2827
2828
  imageUrl: string;
2828
2829
  size?: string | undefined;
2829
2830
  imageTitle: string;
@@ -3048,6 +3049,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
3048
3049
  logoImageBase64Url?: string | undefined;
3049
3050
  socialLinks: {
3050
3051
  url: string;
3052
+ id: string;
3051
3053
  imageUrl: string;
3052
3054
  size?: string | undefined;
3053
3055
  imageTitle: string;
@@ -2,6 +2,8 @@ import { type BrandPageModel, type BrandPageType, type NavModel, type PageStyles
2
2
  import type { ContentType } from '../brand-page/models/content.model';
3
3
  import { type AssetEntry } from './build-asset-manifest';
4
4
  type MinifiedFooterSocialLink = {
5
+ position: number;
6
+ id?: string;
5
7
  imageUrl: string;
6
8
  url: string;
7
9
  };
@@ -156,6 +156,7 @@ const minifyContent = (content, editor, assets) => {
156
156
  ...(Array.isArray(c.items) && {
157
157
  items: c.items.map((item, index) => ({
158
158
  position: index + 1,
159
+ ...(item.id && { id: item.id }),
159
160
  ...st('name', item.name, editor),
160
161
  ...st('jobTitle', item.position, editor),
161
162
  ...st('testimonials', item.testimonials, editor),
@@ -183,6 +184,7 @@ const minifyContent = (content, editor, assets) => {
183
184
  ...(Array.isArray(c.items) && {
184
185
  items: c.items.map((item, index) => ({
185
186
  position: index + 1,
187
+ ...(item.id && { id: item.id }),
186
188
  ...includeImageWithKey(item.imageUrl),
187
189
  ...st('title', item.title, editor),
188
190
  ...st('paragraph', item.paragraph, editor),
@@ -212,6 +214,7 @@ const minifyContent = (content, editor, assets) => {
212
214
  ...(Array.isArray(c.textItems) && {
213
215
  textItems: c.textItems.map((item, index) => ({
214
216
  position: index + 1,
217
+ ...(item.id && { id: item.id }),
215
218
  ...st('text', item.text, editor),
216
219
  ...(includeStyle(item.textStyle) && { textStyle: item.textStyle }),
217
220
  })),
@@ -292,6 +295,7 @@ const minifyContent = (content, editor, assets) => {
292
295
  ...(Array.isArray(c.links) && {
293
296
  links: c.links.map((link, index) => ({
294
297
  position: index + 1,
298
+ ...(link.id && { id: link.id }),
295
299
  ...(includeString(link.url) && { url: link.url }),
296
300
  ...includeImageWithKey(link.imageUrl),
297
301
  })),
@@ -331,6 +335,7 @@ const minifyContent = (content, editor, assets) => {
331
335
  ...(Array.isArray(c.images) && {
332
336
  images: c.images.map((img, index) => ({
333
337
  position: index + 1,
338
+ ...(img.id && { id: img.id }),
334
339
  ...includeImageWithKey(img.imageUrl),
335
340
  ...st('imageTitle', img.imageTitle, editor),
336
341
  })),
@@ -371,7 +376,9 @@ const minifyFooter = (footer, logoAssetKey) => {
371
376
  logoImageWidth: footer.logoImageWidth || undefined,
372
377
  ...(logoAssetKey && { logoAssetKey }),
373
378
  socialLinks: footer.socialLinks?.length
374
- ? footer.socialLinks.map((l) => ({
379
+ ? footer.socialLinks.map((l, index) => ({
380
+ position: index + 1,
381
+ ...(l.id && { id: l.id }),
375
382
  imageUrl: l.imageUrl || '',
376
383
  url: l.url || '',
377
384
  }))
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@designcrowd/library.brand-page",
3
3
  "description": "A collection of Maker/Designer applications",
4
- "version": "6.0.12",
4
+ "version": "6.0.13",
5
5
  "author": "Design.com Eng",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -52,6 +52,7 @@ export const Carousel = () => {
52
52
 
53
53
  content.images = new Array(10).fill(0).map((_, i) => {
54
54
  return {
55
+ id: `gallery-carousel-item-${i}`,
55
56
  imageUrl: `https://picsum.photos/${300 * ((i + 1) / 4)}/${300 * ((i + 1) / 4)}?random=${i}`,
56
57
  width: 300,
57
58
  height: 300,
@@ -83,6 +84,7 @@ export const Masonry = () => {
83
84
 
84
85
  content.images = new Array(10).fill(0).map((_, i) => {
85
86
  return {
87
+ id: `gallery-masonry-item-${i}`,
86
88
  imageUrl: `https://picsum.photos/${300 * ((i + 1) / 4)}/${300 * ((i + 1) / 4)}?random=${i}`,
87
89
  width: 564,
88
90
  height: 416,
@@ -114,6 +116,7 @@ export const Grid = () => {
114
116
 
115
117
  content.images = new Array(10).fill(0).map((_, i) => {
116
118
  return {
119
+ id: `gallery-grid-item-${i}`,
117
120
  imageUrl: `https://picsum.photos/${300 * ((i + 1) / 4)}/${300 * ((i + 1) / 4)}?random=${i}`,
118
121
  width: 564,
119
122
  height: 416,
@@ -47,6 +47,7 @@ const createTestImageGalleryViewModel = (
47
47
  role: 'image-gallery',
48
48
  images: [
49
49
  {
50
+ id: 'gallery-item-1',
50
51
  imageUrl: faker.internet.url(),
51
52
  width: faker.datatype.number(1000),
52
53
  height: faker.datatype.number(1000),
@@ -7,7 +7,8 @@ import type { ImageGalleryImageClickPayload } from '../models';
7
7
  import type { BrandPageContext, ImageGalleryItem } from '../../../models';
8
8
  import { getImageAltText } from '../../../utils';
9
9
 
10
- interface IndexedImageGalleryItem extends ImageGalleryItem {
10
+ interface IndexedImageGalleryItem extends Omit<ImageGalleryItem, 'id'> {
11
+ // Local rendering index, distinct from the stable string `id` on ImageItem.
11
12
  id: number;
12
13
  }
13
14
 
@@ -50,8 +50,9 @@ export const Images = () => {
50
50
  data() {
51
51
  const content = createInitialImagesSectionContent();
52
52
 
53
- content.items = new Array(2).fill(0).map(() => {
53
+ content.items = new Array(2).fill(0).map((_, i) => {
54
54
  return {
55
+ id: `images-section-item-${i}`,
55
56
  imageUrl:
56
57
  'https://bc-user-uploads.brandcrowd.com/public/media-int/6b3a4d19-e95c-4d59-aa22-ac033a2cec2f/1116870a-c672-4306-b515-32f8d5d6e10c',
57
58
  width: 564,
@@ -14,6 +14,7 @@ const viewModel: SocialLinksViewModel = {
14
14
  title: 'Follow us on',
15
15
  links: [
16
16
  {
17
+ id: 'social-link-facebook',
17
18
  imageUrl: 'facebook',
18
19
  url: '',
19
20
  imageTitle: '',
@@ -24,6 +25,7 @@ const viewModel: SocialLinksViewModel = {
24
25
  imageLink: '',
25
26
  },
26
27
  {
28
+ id: 'social-link-instagram',
27
29
  imageUrl: 'instagram',
28
30
  url: 'https://www.instagram.com',
29
31
  imageTitle: '',
@@ -34,6 +36,7 @@ const viewModel: SocialLinksViewModel = {
34
36
  imageLink: '',
35
37
  },
36
38
  {
39
+ id: 'social-link-empty',
37
40
  imageUrl: '',
38
41
  url: '',
39
42
  imageTitle: '',
@@ -53,6 +53,7 @@ const createTestSocialLinksViewModel = (): SocialLinksViewModel => ({
53
53
  isFullWidth: false,
54
54
  links: [
55
55
  {
56
+ id: 'social-link-facebook',
56
57
  imageUrl: 'facebook',
57
58
  url: 'https://www.facebook.com',
58
59
  imageTitle: '',
@@ -63,6 +64,7 @@ const createTestSocialLinksViewModel = (): SocialLinksViewModel => ({
63
64
  imageLink: '',
64
65
  },
65
66
  {
67
+ id: 'social-link-instagram',
66
68
  imageUrl: 'instagram',
67
69
  url: 'https://www.instagram.com',
68
70
  imageTitle: '',
@@ -73,6 +75,7 @@ const createTestSocialLinksViewModel = (): SocialLinksViewModel => ({
73
75
  imageLink: '',
74
76
  },
75
77
  {
78
+ id: 'social-link-twitter',
76
79
  imageUrl: 'twitter',
77
80
  url: 'https://www.twitter.com',
78
81
  imageTitle: '',
@@ -115,6 +118,7 @@ describe('Social Links', () => {
115
118
  isPreview: false,
116
119
  links: [
117
120
  {
121
+ id: 'social-link-facebook',
118
122
  imageUrl: 'facebook',
119
123
  url: '',
120
124
  imageTitle: '',
@@ -145,6 +149,7 @@ describe('Social Links', () => {
145
149
  isPreview: false,
146
150
  links: [
147
151
  {
152
+ id: 'social-link-facebook',
148
153
  imageUrl: 'facebook',
149
154
  url: 'https://www.fb.com',
150
155
  imageTitle: '',
@@ -14,6 +14,7 @@ export const viewModel: TestimonialSectionViewModel = {
14
14
  displayStyle: 'centered',
15
15
  items: [
16
16
  {
17
+ id: 'testimonial-1',
17
18
  testimonials: faker.lorem.paragraphs(1),
18
19
  imageUrl: unsplashImage,
19
20
  name: '1',
@@ -22,6 +23,7 @@ export const viewModel: TestimonialSectionViewModel = {
22
23
  colorReplacements: [],
23
24
  },
24
25
  {
26
+ id: 'testimonial-2',
25
27
  testimonials: faker.lorem.paragraphs(3),
26
28
  imageUrl: unsplashImage,
27
29
  name: '2',
@@ -30,6 +32,7 @@ export const viewModel: TestimonialSectionViewModel = {
30
32
  colorReplacements: [],
31
33
  },
32
34
  {
35
+ id: 'testimonial-3',
33
36
  testimonials: faker.lorem.paragraphs(5),
34
37
  imageUrl: 'https://source.unsplash.com/random/200x200?3',
35
38
  name: '3',
@@ -34,6 +34,7 @@ const BSviewModel: TextViewModel = {
34
34
  text: 'asdasjdlkasjmdlkmsad',
35
35
  textItems: [
36
36
  {
37
+ id: 'text-item-1',
37
38
  text: 'lorem ipsum',
38
39
  textStyle: {
39
40
  fontSize: '1rem',
@@ -42,6 +43,7 @@ const BSviewModel: TextViewModel = {
42
43
  },
43
44
  },
44
45
  {
46
+ id: 'text-item-2',
45
47
  text: 'lorem ipsum',
46
48
  textStyle: {
47
49
  fontSize: '1rem',
@@ -28,6 +28,7 @@ import { TEXT_STYLE_TYPES, TextStyles } from './styles.model';
28
28
  import { EMPTY_LOGO_IMAGE_MODEL, LogoStyles } from './logo.model';
29
29
  import type { LogoImageModel, LogoTemplateImageModel } from './logo.model';
30
30
  import cloneDeep from 'lodash.clonedeep';
31
+ import * as uuid from 'uuid';
31
32
  import type { BrandPagePaymentConfig } from './payment.model';
32
33
 
33
34
  export * from './brand-page-context.model';
@@ -234,6 +235,13 @@ export interface ImageContent extends Content {
234
235
  }
235
236
 
236
237
  export interface ImageItem {
238
+ /**
239
+ * Stable per-item identifier. Mirrors the section-level `Content.id` one
240
+ * level deeper so AI tool calls can reference items by id rather than by
241
+ * positional index. Backfilled on load for persisted data that predates
242
+ * item ids (see ensureItemIds), so it is always present at runtime.
243
+ */
244
+ id: string;
237
245
  imageUrl: string;
238
246
  imageTitle: string;
239
247
  width: number;
@@ -466,6 +474,8 @@ export interface ShapeItem extends ImageItem {
466
474
  }
467
475
 
468
476
  export interface TestimonialItems {
477
+ /** Stable per-item identifier. See ImageItem.id. */
478
+ id: string;
469
479
  imageUrl: string;
470
480
  name: string;
471
481
  position: string;
@@ -483,6 +493,8 @@ export interface TestimonialItems {
483
493
  }
484
494
 
485
495
  export interface TextItem {
496
+ /** Stable per-item identifier. See ImageItem.id. */
497
+ id: string;
486
498
  text: string;
487
499
  textStyle: TextStyleDeclaration;
488
500
 
@@ -552,6 +564,8 @@ export interface AboutSectionContent extends Content {
552
564
  }
553
565
 
554
566
  export interface LinksItem {
567
+ /** Stable per-item identifier. See ImageItem.id. */
568
+ id: string;
555
569
  imageUrl: string;
556
570
  url: string;
557
571
  size?: string;
@@ -828,6 +842,7 @@ export abstract class AbstractPageFooterStyles {
828
842
  this.logoImageWidth = options.logoImageWidth || DEFAULT_LOGO_WIDTH;
829
843
  this.socialLinks = options.socialLinks || [
830
844
  {
845
+ id: uuid.v4(),
831
846
  width: 0,
832
847
  height: 0,
833
848
  imageUrl: 'facebook',
@@ -837,6 +852,7 @@ export abstract class AbstractPageFooterStyles {
837
852
  imageLink: '',
838
853
  },
839
854
  {
855
+ id: uuid.v4(),
840
856
  width: 0,
841
857
  height: 0,
842
858
  imageUrl: 'instagram',
@@ -846,6 +862,7 @@ export abstract class AbstractPageFooterStyles {
846
862
  imageLink: '',
847
863
  },
848
864
  {
865
+ id: uuid.v4(),
849
866
  width: 0,
850
867
  height: 0,
851
868
  imageUrl: 'x',