@designcrowd/library.brand-page 5.19.1-id-based-items-2 → 5.19.2
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.
- package/lib/src/{CreatedOnBrandCrowd-de-de-Ruu5Az32.js → CreatedOnBrandCrowd-de-de-Ekmn0O3s.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-DGUJtvld.js → CreatedOnBrandCrowd-en-us-BjeXlKTS.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-Dg-1uOfV.js → CreatedOnBrandCrowd-es-es-rpNINAMY.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-CRKraZl8.js → CreatedOnBrandCrowd-fr-ca-BL4nSaLj.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-CRKraZl8.js → CreatedOnBrandCrowd-fr-fr-BL4nSaLj.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-bZ9VlEAu.js → CreatedOnBrandCrowd-pt-br-K0r4FyYq.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-bZ9VlEAu.js → CreatedOnBrandCrowd-pt-pt-K0r4FyYq.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-CJYfwZx8.js → CreatedOnDcom-de-de-0XYyEKYc.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-rzA1lVxH.js → CreatedOnDcom-en-us-E8hvwiMd.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-CNwGPjik.js → CreatedOnDcom-es-es-pRuCd7xX.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-DKw7OGIz.js → CreatedOnDcom-fr-ca-Bu4V3jpn.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-WzOEaAZG.js → CreatedOnDcom-fr-fr-CCcrGNz2.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-DkualVhm.js → CreatedOnDcom-pt-br-1GTvaLKd.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-w4Nnsdzq.js → CreatedOnDcom-pt-pt-CTIYW10X.js} +1 -1
- package/lib/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.d.ts +1 -1
- package/lib/src/brand-page/models/index.d.ts +1 -12
- package/lib/src/brand-page/models/index.js +3 -0
- package/lib/src/brand-page/utils/personalisation.util.js +72 -14
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/admin-background-settings/AdminBackgroundSettings.mixin.d.ts +6 -0
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +12 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +2 -0
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.js +1 -0
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +2 -3
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +16 -5
- package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +0 -5
- package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +6 -18
- package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +1 -0
- package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.js +3 -0
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +3 -1
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +5 -1
- package/lib/src/brand-page-maker/stores/ui/ui-store.d.ts +6 -0
- package/lib/src/brand-page-maker/stores/ui/ui-store.js +8 -0
- package/lib/src/clients/design-template-client.d.ts +3 -0
- package/lib/src/clients/models.d.ts +2 -0
- package/lib/src/css/library.brand-page-brandCrowd.min.css +19 -7
- package/lib/src/css/library.brand-page-brandPage.min.css +19 -7
- package/lib/src/css/library.brand-page-designCom.min.css +19 -7
- package/lib/src/css/library.brand-page-preview.min.css +19 -7
- package/lib/src/index.mjs +1 -1
- package/lib/src/{lib-Dy7MYyqz.js → lib-BfgUqu0B.js} +25060 -24791
- package/lib/src/metadata-builder/builders/footer-builder.js +44 -34
- package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.js +68 -57
- package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +93 -58
- package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +99 -66
- package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +17 -57
- package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +85 -51
- package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +74 -49
- package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +4 -13
- package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +48 -66
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +7 -1
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +9 -0
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +1 -1
- package/lib/src/shared/logo-versions/LogoVersions.mixin.d.ts +6 -0
- package/lib/src/shared/models.d.ts +2 -0
- package/lib/src/shared/my-designs/MyDesigns.mixin.d.ts +6 -0
- package/lib/src/shared/my-uploads/MyMedia.mixin.d.ts +6 -0
- package/lib/src/shared/my-uploads/MyUploads.mixin.d.ts +6 -0
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +7 -3
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +7 -3
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -1
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +7 -1
- package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +10 -439
- package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.js +2 -2
- package/lib/src/shared/template-settings/models.d.ts +1 -0
- package/lib/src/shared/template-settings/store/template-settings-store.d.ts +4 -0
- package/lib/src/shared/template-settings/store/template-settings-store.js +79 -11
- package/lib/src/shared/unsplash-library/UnsplashLibrary.mixin.d.ts +6 -0
- package/lib/src/utils/minify-brand-page-metadata.d.ts +0 -2
- package/lib/src/utils/minify-brand-page-metadata.js +1 -8
- package/package.json +1 -1
- package/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.ts +1 -2
- package/src/brand-page/models/index.ts +4 -12
- package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -0
- package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +1 -0
- package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +2 -0
- package/src/brand-page/utils/personalisation.util.test.ts +35 -0
- package/src/brand-page/utils/personalisation.util.ts +119 -23
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +4 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +1 -0
- package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +22 -8
- package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +5 -10
- package/src/brand-page-maker/components/template-preview/TemplatePreviewAiBadge.vue +12 -0
- package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +0 -6
- package/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.ts +5 -0
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +10 -0
- package/src/brand-page-maker/stores/ui/ui-store.ts +16 -0
- package/src/clients/design-template-client.ts +3 -0
- package/src/clients/models.ts +2 -0
- package/src/metadata-builder/builders/footer-builder.test.ts +0 -298
- package/src/metadata-builder/builders/footer-builder.ts +65 -56
- package/src/metadata-builder/builders/section-builders/image-gallery-builder.ts +88 -62
- package/src/metadata-builder/builders/section-builders/images-section-builder.ts +129 -66
- package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +160 -105
- package/src/metadata-builder/builders/section-builders/social-links-builder.ts +20 -65
- package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +146 -83
- package/src/metadata-builder/builders/section-builders/text-section-builder.ts +122 -70
- package/src/metadata-builder/parsers/ai-toolcall-parser.ts +4 -13
- package/src/metadata-builder/parsers/section-tool-arguments.ts +48 -66
- package/src/shared/models.ts +6 -0
- package/src/shared/template-settings/components/TemplatesSettings.mixin.ts +2 -2
- package/src/shared/template-settings/models.ts +1 -0
- package/src/shared/template-settings/store/template-settings-store.ts +105 -18
- package/src/utils/minify-brand-page-metadata.ts +2 -14
- package/lib/src/metadata-builder/builders/item-id-utils.d.ts +0 -54
- package/lib/src/metadata-builder/builders/item-id-utils.js +0 -96
- package/src/metadata-builder/builders/item-id-utils.test.ts +0 -184
- package/src/metadata-builder/builders/item-id-utils.ts +0 -117
|
@@ -142,15 +142,10 @@ export interface ProfileSectionArguments {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
export interface TextSectionItem {
|
|
145
|
-
/**
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
* move for existing ones). Use "__end__" for the end of the list. Omit to
|
|
150
|
-
* leave an existing item in place / append a new item. Mirrors the
|
|
151
|
-
* section-level move_before_content_id.
|
|
152
|
-
*/
|
|
153
|
-
move_before_item_id?: string;
|
|
145
|
+
/** 0-based index of existing item to update in-place */
|
|
146
|
+
item_index?: number;
|
|
147
|
+
/** 0-based position to insert a new item at */
|
|
148
|
+
insert_at?: number;
|
|
154
149
|
text?: RichTextField;
|
|
155
150
|
text_style?: TextStyleArguments;
|
|
156
151
|
}
|
|
@@ -164,8 +159,10 @@ export interface TextSectionArguments {
|
|
|
164
159
|
/** Multiple text items (BrandSite) */
|
|
165
160
|
items?: TextSectionItem[];
|
|
166
161
|
_replace_items?: boolean;
|
|
167
|
-
/**
|
|
168
|
-
|
|
162
|
+
/** 0-based indices of items to remove */
|
|
163
|
+
_remove_item_indices?: number[];
|
|
164
|
+
/** New order as array of current 0-based indices */
|
|
165
|
+
_reorder_items?: number[];
|
|
169
166
|
background_color?: string | null;
|
|
170
167
|
}
|
|
171
168
|
|
|
@@ -175,15 +172,10 @@ export interface ImageSectionArguments {
|
|
|
175
172
|
}
|
|
176
173
|
|
|
177
174
|
export interface ImageGalleryItem {
|
|
178
|
-
/**
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
|
|
182
|
-
* move for existing ones). Use "__end__" for the end of the list. Omit to
|
|
183
|
-
* leave an existing item in place / append a new item. Mirrors the
|
|
184
|
-
* section-level move_before_content_id.
|
|
185
|
-
*/
|
|
186
|
-
move_before_item_id?: string;
|
|
175
|
+
/** 0-based index of existing item to update in-place */
|
|
176
|
+
item_index?: number;
|
|
177
|
+
/** 0-based position to insert a new item at */
|
|
178
|
+
insert_at?: number;
|
|
187
179
|
image_url?: string;
|
|
188
180
|
caption?: string;
|
|
189
181
|
}
|
|
@@ -193,8 +185,10 @@ export interface ImageGallerySectionArguments {
|
|
|
193
185
|
gallery_type?: 'grid' | 'carousel' | 'masonry';
|
|
194
186
|
is_full_width?: boolean;
|
|
195
187
|
_replace_items?: boolean;
|
|
196
|
-
/**
|
|
197
|
-
|
|
188
|
+
/** 0-based indices of items to remove */
|
|
189
|
+
_remove_item_indices?: number[];
|
|
190
|
+
/** New order as array of current 0-based indices */
|
|
191
|
+
_reorder_items?: number[];
|
|
198
192
|
}
|
|
199
193
|
|
|
200
194
|
export interface GeneralLinkSectionArguments {
|
|
@@ -262,15 +256,10 @@ export interface TiktokSectionArguments {
|
|
|
262
256
|
}
|
|
263
257
|
|
|
264
258
|
export interface SocialLink {
|
|
265
|
-
/**
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
|
|
269
|
-
* move for existing ones). Use "__end__" for the end of the list. Omit to
|
|
270
|
-
* leave an existing item in place / append a new item. Mirrors the
|
|
271
|
-
* section-level move_before_content_id.
|
|
272
|
-
*/
|
|
273
|
-
move_before_item_id?: string;
|
|
259
|
+
/** 0-based index of existing item to update in-place */
|
|
260
|
+
item_index?: number;
|
|
261
|
+
/** 0-based position to insert a new item at */
|
|
262
|
+
insert_at?: number;
|
|
274
263
|
platform?:
|
|
275
264
|
| 'facebook'
|
|
276
265
|
| 'x'
|
|
@@ -291,8 +280,10 @@ export interface SocialLinksSectionArguments {
|
|
|
291
280
|
/** Style for the icon container background (used when icon_style is 'square' or 'circle'). */
|
|
292
281
|
icon_background_style?: TextStyleArguments;
|
|
293
282
|
_replace_items?: boolean;
|
|
294
|
-
/**
|
|
295
|
-
|
|
283
|
+
/** 0-based indices of items to remove */
|
|
284
|
+
_remove_item_indices?: number[];
|
|
285
|
+
/** New order as array of current 0-based indices */
|
|
286
|
+
_reorder_items?: number[];
|
|
296
287
|
}
|
|
297
288
|
|
|
298
289
|
export interface MailingListSectionArguments {
|
|
@@ -380,15 +371,10 @@ export interface AboutSectionArguments {
|
|
|
380
371
|
}
|
|
381
372
|
|
|
382
373
|
export interface ImagesSectionItem {
|
|
383
|
-
/**
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
|
|
387
|
-
* move for existing ones). Use "__end__" for the end of the list. Omit to
|
|
388
|
-
* leave an existing item in place / append a new item. Mirrors the
|
|
389
|
-
* section-level move_before_content_id.
|
|
390
|
-
*/
|
|
391
|
-
move_before_item_id?: string;
|
|
374
|
+
/** 0-based index of existing item to update in-place */
|
|
375
|
+
item_index?: number;
|
|
376
|
+
/** 0-based position to insert a new item at */
|
|
377
|
+
insert_at?: number;
|
|
392
378
|
image_url?: string;
|
|
393
379
|
heading?: string;
|
|
394
380
|
text?: string;
|
|
@@ -407,8 +393,10 @@ export interface ImagesSectionArguments {
|
|
|
407
393
|
| 'center-card-aligned-image'
|
|
408
394
|
| 'alternate-image';
|
|
409
395
|
_replace_items?: boolean;
|
|
410
|
-
/**
|
|
411
|
-
|
|
396
|
+
/** 0-based indices of items to remove */
|
|
397
|
+
_remove_item_indices?: number[];
|
|
398
|
+
/** New order as array of current 0-based indices */
|
|
399
|
+
_reorder_items?: number[];
|
|
412
400
|
title_style?: TextStyleArguments;
|
|
413
401
|
description_style?: TextStyleArguments;
|
|
414
402
|
heading_style?: TextStyleArguments;
|
|
@@ -421,15 +409,10 @@ export interface ImagesSectionArguments {
|
|
|
421
409
|
}
|
|
422
410
|
|
|
423
411
|
export interface TestimonialItem {
|
|
424
|
-
/**
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
|
|
428
|
-
* move for existing ones). Use "__end__" for the end of the list. Omit to
|
|
429
|
-
* leave an existing item in place / append a new item. Mirrors the
|
|
430
|
-
* section-level move_before_content_id.
|
|
431
|
-
*/
|
|
432
|
-
move_before_item_id?: string;
|
|
412
|
+
/** 0-based index of existing item to update in-place */
|
|
413
|
+
item_index?: number;
|
|
414
|
+
/** 0-based position to insert a new item at */
|
|
415
|
+
insert_at?: number;
|
|
433
416
|
testimonial?: string;
|
|
434
417
|
name?: string;
|
|
435
418
|
position?: string;
|
|
@@ -443,8 +426,10 @@ export interface TestimonialSectionArguments {
|
|
|
443
426
|
items?: TestimonialItem[];
|
|
444
427
|
display_style?: 'centered' | 'big-image' | 'columns';
|
|
445
428
|
_replace_items?: boolean;
|
|
446
|
-
/**
|
|
447
|
-
|
|
429
|
+
/** 0-based indices of items to remove */
|
|
430
|
+
_remove_item_indices?: number[];
|
|
431
|
+
/** New order as array of current 0-based indices */
|
|
432
|
+
_reorder_items?: number[];
|
|
448
433
|
title_style?: TextStyleArguments;
|
|
449
434
|
testimonial_style?: TextStyleArguments;
|
|
450
435
|
name_style?: TextStyleArguments;
|
|
@@ -454,15 +439,10 @@ export interface TestimonialSectionArguments {
|
|
|
454
439
|
}
|
|
455
440
|
|
|
456
441
|
export interface ShapesSectionItem {
|
|
457
|
-
/**
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
|
|
461
|
-
* move for existing ones). Use "__end__" for the end of the list. Omit to
|
|
462
|
-
* leave an existing item in place / append a new item. Mirrors the
|
|
463
|
-
* section-level move_before_content_id.
|
|
464
|
-
*/
|
|
465
|
-
move_before_item_id?: string;
|
|
442
|
+
/** 0-based index of existing item to update in-place */
|
|
443
|
+
item_index?: number;
|
|
444
|
+
/** 0-based position to insert a new item at */
|
|
445
|
+
insert_at?: number;
|
|
466
446
|
icon_image_url?: string;
|
|
467
447
|
shape_url?: string;
|
|
468
448
|
color_theme?: string;
|
|
@@ -482,8 +462,10 @@ export interface ShapesSectionArguments {
|
|
|
482
462
|
| 'center-card-aligned-image'
|
|
483
463
|
| 'alternate-image';
|
|
484
464
|
_replace_items?: boolean;
|
|
485
|
-
/**
|
|
486
|
-
|
|
465
|
+
/** 0-based indices of items to remove */
|
|
466
|
+
_remove_item_indices?: number[];
|
|
467
|
+
/** New order as array of current 0-based indices */
|
|
468
|
+
_reorder_items?: number[];
|
|
487
469
|
title_style?: TextStyleArguments;
|
|
488
470
|
description_style?: TextStyleArguments;
|
|
489
471
|
heading_style?: TextStyleArguments;
|
package/src/shared/models.ts
CHANGED
|
@@ -19,6 +19,12 @@ export interface UIRootState {
|
|
|
19
19
|
thirdPartySettings: UIRootStateThirdPartySettings;
|
|
20
20
|
personalisationData: UserPersonalisationContent[] | undefined;
|
|
21
21
|
isPersonalisationEnabled: boolean;
|
|
22
|
+
// Pre-purchase AI content key used to personalise AI template previews when
|
|
23
|
+
// there is no post-purchase personalisationData (bp-5742).
|
|
24
|
+
userPromptContentKey: string | undefined;
|
|
25
|
+
// Controls visibility of the dedicated AI templates tab. Decoupled from personalisationData
|
|
26
|
+
// so the slug flow can personalise previews/apply without surfacing the AI tab (bp-5742).
|
|
27
|
+
showAiTemplatesTab: boolean;
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
export interface Endpoints {
|
|
@@ -60,7 +60,7 @@ export default defineComponent({
|
|
|
60
60
|
templateCategories: computed(
|
|
61
61
|
() => templateSettingsStore.templateCategories,
|
|
62
62
|
),
|
|
63
|
-
|
|
63
|
+
showAiTemplatesTab: computed(() => uiStore.showAiTemplatesTab),
|
|
64
64
|
templateSettingsStore,
|
|
65
65
|
uiStore,
|
|
66
66
|
isDesignCom: computed(() => containerStore.isDesignCom),
|
|
@@ -155,7 +155,7 @@ export default defineComponent({
|
|
|
155
155
|
},
|
|
156
156
|
|
|
157
157
|
visibleTabs() {
|
|
158
|
-
return this.
|
|
158
|
+
return this.showAiTemplatesTab
|
|
159
159
|
? this.tabs
|
|
160
160
|
: [...this.tabs].splice(
|
|
161
161
|
0,
|
|
@@ -14,6 +14,7 @@ import * as DesignTemplateClient from '../../../clients/design-template-client';
|
|
|
14
14
|
import { type DesignTemplate } from '../../../clients/models';
|
|
15
15
|
import {
|
|
16
16
|
BP_DEFAULT_TEMPLATE_TYPE_NAME,
|
|
17
|
+
BP_BRAND_SITE_TEMPLATE_TYPE_NAME,
|
|
17
18
|
SIDE_BAR_TAB_NAMES,
|
|
18
19
|
} from '@brand-page-maker/constants';
|
|
19
20
|
import { defineStore, storeToRefs } from 'pinia';
|
|
@@ -32,6 +33,7 @@ import {
|
|
|
32
33
|
useUiEditableLogoStore,
|
|
33
34
|
useUiLogoSettingsStore,
|
|
34
35
|
} from '../../logo-settings/store';
|
|
36
|
+
import { useEventTracker } from '@brand-page-maker/composables/useEventTracker';
|
|
35
37
|
import {
|
|
36
38
|
templateSettingsTr,
|
|
37
39
|
getCurrentLocale,
|
|
@@ -39,6 +41,17 @@ import {
|
|
|
39
41
|
import { watch } from 'vue';
|
|
40
42
|
|
|
41
43
|
export const DEFAULT_PAGE_SIZE = 6;
|
|
44
|
+
|
|
45
|
+
const POST_PURCHASE_PAGE_SECTION_BY_TAB: Record<string, string> = {
|
|
46
|
+
[TEMPLATE_TABS.all]: 'MakerPostPurchaseSidebarTemplatesAllTab',
|
|
47
|
+
[TEMPLATE_TABS.AI]: 'MakerPostPurchaseSidebarTemplatesAiTab',
|
|
48
|
+
[TEMPLATE_TABS.categories]: 'MakerPostPurchaseSidebarTemplatesCategoryTab',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const PRE_PURCHASE_PAGE_SECTION_BY_TAB: Record<string, string> = {
|
|
52
|
+
[TEMPLATE_TABS.all]: 'MakerPrePurchaseSidebarTemplatesAllTab',
|
|
53
|
+
[TEMPLATE_TABS.categories]: 'MakerPrePurchaseSidebarTemplatesCategoryTab',
|
|
54
|
+
};
|
|
42
55
|
const LOAD_PAGE_RETRY_DELAY = 250;
|
|
43
56
|
|
|
44
57
|
type SelectedTabType = {
|
|
@@ -66,6 +79,7 @@ export interface TemplatesSettingState {
|
|
|
66
79
|
tabsWithTranslations: SelectedTabType[];
|
|
67
80
|
logoChangeWatcherInitialized: boolean;
|
|
68
81
|
initialSearchTerm: string | undefined;
|
|
82
|
+
aiTemplateKeywords: string | undefined;
|
|
69
83
|
onSearchTermChanged: OnSearchTermChangedCallback | undefined;
|
|
70
84
|
}
|
|
71
85
|
|
|
@@ -103,6 +117,7 @@ export const useUiTemplateSettingsStore = defineStore('uiTemplateSettings', {
|
|
|
103
117
|
cachedTemplates: {},
|
|
104
118
|
logoChangeWatcherInitialized: false,
|
|
105
119
|
initialSearchTerm: undefined,
|
|
120
|
+
aiTemplateKeywords: undefined,
|
|
106
121
|
onSearchTermChanged: undefined,
|
|
107
122
|
};
|
|
108
123
|
},
|
|
@@ -302,22 +317,60 @@ export const useUiTemplateSettingsStore = defineStore('uiTemplateSettings', {
|
|
|
302
317
|
const editableLogoVariation =
|
|
303
318
|
editableLogoStore.editableLogoVariations[logoVariation];
|
|
304
319
|
|
|
320
|
+
const isPrePurchase = brandPageContainerStore.isPrePurchase;
|
|
321
|
+
const isBrandSite =
|
|
322
|
+
this.templateType === BP_BRAND_SITE_TEMPLATE_TYPE_NAME;
|
|
323
|
+
|
|
324
|
+
// Pre-purchase has no logo draft for logo-based recommendation, so fall back to the seeded
|
|
325
|
+
// search term (the keyword from the URL/cookie - never the business name) so the All tab
|
|
326
|
+
// stays relevant instead of generic (bp-5454).
|
|
327
|
+
const effectiveSearchTerm =
|
|
328
|
+
!this.searchTerm &&
|
|
329
|
+
!this.selectedCategory &&
|
|
330
|
+
isPrePurchase &&
|
|
331
|
+
isBrandSite &&
|
|
332
|
+
this.selectedTab.key === TEMPLATE_TABS.all
|
|
333
|
+
? this.initialSearchTerm
|
|
334
|
+
: this.searchTerm;
|
|
335
|
+
|
|
336
|
+
const pageSection = isBrandSite
|
|
337
|
+
? (isPrePurchase
|
|
338
|
+
? PRE_PURCHASE_PAGE_SECTION_BY_TAB
|
|
339
|
+
: POST_PURCHASE_PAGE_SECTION_BY_TAB)[this.selectedTab.key]
|
|
340
|
+
: undefined;
|
|
341
|
+
|
|
342
|
+
const pageName = isBrandSite
|
|
343
|
+
? isPrePurchase
|
|
344
|
+
? 'maker-pre-purchase'
|
|
345
|
+
: 'maker'
|
|
346
|
+
: undefined;
|
|
347
|
+
|
|
348
|
+
const baseParams = {
|
|
349
|
+
page: pageNo,
|
|
350
|
+
categoryName: this.selectedCategory,
|
|
351
|
+
searchTerm: effectiveSearchTerm,
|
|
352
|
+
keywords: this.aiTemplateKeywords,
|
|
353
|
+
logoDraftToken: logoSettingsStore.selectedLogoImage.logoDraftToken,
|
|
354
|
+
logoVariation: logoSettingsStore.selectedLogoImage.logoVariation,
|
|
355
|
+
selectedTemplateToken: designTemplateToken,
|
|
356
|
+
locale: currentLocale,
|
|
357
|
+
logoS3Token: !isByo ? editableLogoVariation.s3Token : undefined,
|
|
358
|
+
logoTemplateToken: isByo ? logoTemplateToken : undefined,
|
|
359
|
+
useLogoForRecommendedTemplates:
|
|
360
|
+
isBrandSite && this.selectedTab.key === TEMPLATE_TABS.all,
|
|
361
|
+
pageSection,
|
|
362
|
+
pageName,
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
// AI templates are interleaved server-side for the Brand Site All tab
|
|
366
|
+
// (bp-5306); the frontend just renders the returned order.
|
|
305
367
|
const result =
|
|
306
368
|
await designTemplateClient.getTemplateItemsByTemplateType(
|
|
307
369
|
this.templateType,
|
|
308
370
|
{
|
|
309
|
-
|
|
371
|
+
...baseParams,
|
|
310
372
|
pageSize: DEFAULT_PAGE_SIZE,
|
|
311
|
-
categoryName: this.selectedCategory,
|
|
312
|
-
searchTerm: this.searchTerm,
|
|
313
|
-
logoDraftToken:
|
|
314
|
-
logoSettingsStore.selectedLogoImage.logoDraftToken,
|
|
315
|
-
logoVariation: logoSettingsStore.selectedLogoImage.logoVariation,
|
|
316
373
|
personalisable: this.selectedTab.key === TEMPLATE_TABS.AI,
|
|
317
|
-
selectedTemplateToken: designTemplateToken,
|
|
318
|
-
locale: currentLocale,
|
|
319
|
-
logoS3Token: !isByo ? editableLogoVariation.s3Token : undefined,
|
|
320
|
-
logoTemplateToken: isByo ? logoTemplateToken : undefined,
|
|
321
374
|
},
|
|
322
375
|
);
|
|
323
376
|
|
|
@@ -327,11 +380,27 @@ export const useUiTemplateSettingsStore = defineStore('uiTemplateSettings', {
|
|
|
327
380
|
|
|
328
381
|
this._setPageCount({ pageCount: result.pageCount });
|
|
329
382
|
|
|
383
|
+
if (
|
|
384
|
+
pageNo === 1 &&
|
|
385
|
+
result.abTestValuesToBePushed &&
|
|
386
|
+
Object.keys(result.abTestValuesToBePushed).length > 0
|
|
387
|
+
) {
|
|
388
|
+
const eventTracker = useEventTracker();
|
|
389
|
+
|
|
390
|
+
for (const [experimentName, experimentValue] of Object.entries(
|
|
391
|
+
result.abTestValuesToBePushed,
|
|
392
|
+
)) {
|
|
393
|
+
eventTracker.sendExperimentStartedEvent(
|
|
394
|
+
experimentName,
|
|
395
|
+
experimentValue,
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
330
400
|
const templates = await Promise.all(
|
|
331
401
|
result.paginatedItems.map(async (item) => {
|
|
332
402
|
try {
|
|
333
403
|
if (brandPageMakerUserStore.isAdmin) {
|
|
334
|
-
// Pre-purchase: full template with brandPageModel for live rendering
|
|
335
404
|
const template =
|
|
336
405
|
await designTemplateClient.getTemplateByTemplateToken(
|
|
337
406
|
item.designTemplateToken,
|
|
@@ -349,17 +418,24 @@ export const useUiTemplateSettingsStore = defineStore('uiTemplateSettings', {
|
|
|
349
418
|
uiStore.personalisationData.length,
|
|
350
419
|
);
|
|
351
420
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
421
|
+
contentKey =
|
|
422
|
+
uiStore.personalisationData[personalisationContentIndex]
|
|
423
|
+
.contentKey;
|
|
424
|
+
} else if (item.isPersonalisable) {
|
|
425
|
+
// Pre-purchase has no personalisationData; personalise AI
|
|
426
|
+
// template previews with the prompt content key (bp-5742).
|
|
427
|
+
contentKey = uiStore.userPromptContentKey;
|
|
358
428
|
}
|
|
359
429
|
|
|
360
430
|
return {
|
|
361
431
|
id: item.designTemplateToken,
|
|
432
|
+
isPersonalisable: item.isPersonalisable,
|
|
362
433
|
contentKey,
|
|
434
|
+
// A userPromptContentKey signals this design's real AI images live
|
|
435
|
+
// in the userPrompt bucket (post- or pre-purchase). The preview must
|
|
436
|
+
// then resolve via userPromptContentKey, not the regular bucket which
|
|
437
|
+
// holds placeholders post-purchase (bp-5454).
|
|
438
|
+
usesUserPromptContentKey: !!uiStore.userPromptContentKey,
|
|
363
439
|
previewImageUrl: item.previewImageUrl,
|
|
364
440
|
} as TemplateSettingsTemplate;
|
|
365
441
|
}
|
|
@@ -374,7 +450,15 @@ export const useUiTemplateSettingsStore = defineStore('uiTemplateSettings', {
|
|
|
374
450
|
(t): t is TemplateSettingsTemplate => t !== null,
|
|
375
451
|
);
|
|
376
452
|
|
|
377
|
-
|
|
453
|
+
// The Categories tab must never surface AI templates or the AI badge
|
|
454
|
+
// (bp-5454 scenario 5). The badge is driven purely by isPersonalisable,
|
|
455
|
+
// so clear it for category results regardless of the template's catalog flag.
|
|
456
|
+
const displayTemplates =
|
|
457
|
+
this.selectedTab.key === TEMPLATE_TABS.categories
|
|
458
|
+
? validTemplates.map((t) => ({ ...t, isPersonalisable: false }))
|
|
459
|
+
: validTemplates;
|
|
460
|
+
|
|
461
|
+
this._addTemplates({ templates: displayTemplates });
|
|
378
462
|
this._setPageNoLoaded({ pageNoLoaded: pageNo });
|
|
379
463
|
} finally {
|
|
380
464
|
this._setIsBusy({ isBusy: false });
|
|
@@ -496,6 +580,9 @@ export const useUiTemplateSettingsStore = defineStore('uiTemplateSettings', {
|
|
|
496
580
|
this.initialSearchTerm = payload.initialSearchTerm;
|
|
497
581
|
this.onSearchTermChanged = payload.onSearchTermChanged;
|
|
498
582
|
},
|
|
583
|
+
setAiTemplateKeywords(payload: { aiTemplateKeywords: string }) {
|
|
584
|
+
this.aiTemplateKeywords = payload.aiTemplateKeywords;
|
|
585
|
+
},
|
|
499
586
|
notifySearchTermChanged(searchTerm: string | undefined) {
|
|
500
587
|
this.onSearchTermChanged?.(searchTerm);
|
|
501
588
|
},
|
|
@@ -15,12 +15,7 @@ import { useExternalRichTextEditor } from '../brand-page-maker/composables/rich-
|
|
|
15
15
|
import type { Editor, JSONContent } from '@tiptap/vue-3';
|
|
16
16
|
import { type AssetEntry, resolveLogoData } from './build-asset-manifest';
|
|
17
17
|
|
|
18
|
-
type MinifiedFooterSocialLink = {
|
|
19
|
-
position: number;
|
|
20
|
-
id?: string;
|
|
21
|
-
imageUrl: string;
|
|
22
|
-
url: string;
|
|
23
|
-
};
|
|
18
|
+
type MinifiedFooterSocialLink = { imageUrl: string; url: string };
|
|
24
19
|
|
|
25
20
|
type MinifiedFooter = {
|
|
26
21
|
displayStyle?: string;
|
|
@@ -297,7 +292,6 @@ const minifyContent = (
|
|
|
297
292
|
...(Array.isArray(c.items) && {
|
|
298
293
|
items: c.items.map((item: any, index: number) => ({
|
|
299
294
|
position: index + 1,
|
|
300
|
-
...(item.id && { id: item.id }),
|
|
301
295
|
...st('name', item.name, editor),
|
|
302
296
|
...st('jobTitle', item.position, editor),
|
|
303
297
|
...st('testimonials', item.testimonials, editor),
|
|
@@ -326,7 +320,6 @@ const minifyContent = (
|
|
|
326
320
|
...(Array.isArray(c.items) && {
|
|
327
321
|
items: c.items.map((item: any, index: number) => ({
|
|
328
322
|
position: index + 1,
|
|
329
|
-
...(item.id && { id: item.id }),
|
|
330
323
|
...includeImageWithKey(item.imageUrl),
|
|
331
324
|
...st('title', item.title, editor),
|
|
332
325
|
...st('paragraph', item.paragraph, editor),
|
|
@@ -357,7 +350,6 @@ const minifyContent = (
|
|
|
357
350
|
...(Array.isArray(c.textItems) && {
|
|
358
351
|
textItems: c.textItems.map((item: any, index: number) => ({
|
|
359
352
|
position: index + 1,
|
|
360
|
-
...(item.id && { id: item.id }),
|
|
361
353
|
...st('text', item.text, editor),
|
|
362
354
|
...(includeStyle(item.textStyle) && { textStyle: item.textStyle }),
|
|
363
355
|
})),
|
|
@@ -447,7 +439,6 @@ const minifyContent = (
|
|
|
447
439
|
...(Array.isArray(c.links) && {
|
|
448
440
|
links: c.links.map((link: any, index: number) => ({
|
|
449
441
|
position: index + 1,
|
|
450
|
-
...(link.id && { id: link.id }),
|
|
451
442
|
...(includeString(link.url) && { url: link.url }),
|
|
452
443
|
...includeImageWithKey(link.imageUrl),
|
|
453
444
|
})),
|
|
@@ -491,7 +482,6 @@ const minifyContent = (
|
|
|
491
482
|
...(Array.isArray(c.images) && {
|
|
492
483
|
images: c.images.map((img: any, index: number) => ({
|
|
493
484
|
position: index + 1,
|
|
494
|
-
...(img.id && { id: img.id }),
|
|
495
485
|
...includeImageWithKey(img.imageUrl),
|
|
496
486
|
...st('imageTitle', img.imageTitle, editor),
|
|
497
487
|
})),
|
|
@@ -541,9 +531,7 @@ const minifyFooter = (
|
|
|
541
531
|
logoImageWidth: footer.logoImageWidth || undefined,
|
|
542
532
|
...(logoAssetKey && { logoAssetKey }),
|
|
543
533
|
socialLinks: footer.socialLinks?.length
|
|
544
|
-
? footer.socialLinks.map((l
|
|
545
|
-
position: index + 1,
|
|
546
|
-
...(l.id && { id: l.id }),
|
|
534
|
+
? footer.socialLinks.map((l) => ({
|
|
547
535
|
imageUrl: l.imageUrl || '',
|
|
548
536
|
url: l.url || '',
|
|
549
537
|
}))
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { BrandPageModel } from '../../brand-page/models';
|
|
2
|
-
/**
|
|
3
|
-
* Sentinel anchor meaning "the end of the list", mirroring the section-level
|
|
4
|
-
* `move_before_content_id: "__end__"` convention used in base-section-builder.
|
|
5
|
-
*/
|
|
6
|
-
export declare const END_ITEM_ANCHOR = "__end__";
|
|
7
|
-
/** Generate a stable item id. Mirrors section-level `uuid.v4()` id generation. */
|
|
8
|
-
export declare const generateItemId: () => string;
|
|
9
|
-
/**
|
|
10
|
-
* Walk an entire BrandPageModel and backfill a stable uuid `id` onto every
|
|
11
|
-
* nested array item that lacks one (gallery images, images/shapes/testimonial
|
|
12
|
-
* items, text items, social links, and footer social links).
|
|
13
|
-
*
|
|
14
|
-
* BP-5603: this must run BEFORE the model is minified for the AI, so the same
|
|
15
|
-
* id the AI is shown (and copies into `item_id`) is the one the executor later
|
|
16
|
-
* matches. The maker holds a single live model instance for both the minify
|
|
17
|
-
* and the apply step, so mutating it here makes the ids round-trip; they then
|
|
18
|
-
* persist on the next save. Idempotent — existing ids are preserved.
|
|
19
|
-
*/
|
|
20
|
-
export declare const ensureBrandPageItemIds: (model: BrandPageModel) => void;
|
|
21
|
-
/**
|
|
22
|
-
* Backfill ids onto any items missing one. Per BP-5603 this runs in the
|
|
23
|
-
* metadata builder when a section is processed, so the persisted metadata
|
|
24
|
-
* returned to the client gains stable ids that subsequent AI tool calls can
|
|
25
|
-
* reference. Mutates in place.
|
|
26
|
-
*/
|
|
27
|
-
export declare const ensureItemIds: <T extends {
|
|
28
|
-
id?: string | undefined;
|
|
29
|
-
}>(items: T[] | undefined) => void;
|
|
30
|
-
/**
|
|
31
|
-
* Remove items whose id appears in `ids`. Order-independent (no descending
|
|
32
|
-
* index sort needed) — the whole point of the id-based migration. Items
|
|
33
|
-
* without an id are never removed by id.
|
|
34
|
-
*/
|
|
35
|
-
export declare const removeItemsByIds: <T extends {
|
|
36
|
-
id?: string | undefined;
|
|
37
|
-
}>(items: T[] | undefined, ids: string[] | undefined) => T[];
|
|
38
|
-
/**
|
|
39
|
-
* Position `item` within `items` relative to an anchor id — the item-level
|
|
40
|
-
* mirror of base-section-builder's `moveContent`:
|
|
41
|
-
*
|
|
42
|
-
* - `moveBeforeItemId === undefined` → leave an existing item where it is;
|
|
43
|
-
* append a new (not-yet-present) item to the end.
|
|
44
|
-
* - `moveBeforeItemId === "__end__"` → move/insert at the very end.
|
|
45
|
-
* - anchor id found → insert immediately before it.
|
|
46
|
-
* - anchor id not found → fall through to the end (same
|
|
47
|
-
* forgiving behaviour as `moveContent`).
|
|
48
|
-
*
|
|
49
|
-
* Mutates `items` in place. `item` may be an existing element of `items`
|
|
50
|
-
* (a move) or a brand-new object (an insert).
|
|
51
|
-
*/
|
|
52
|
-
export declare const repositionItemByAnchor: <T extends {
|
|
53
|
-
id?: string | undefined;
|
|
54
|
-
}>(items: T[], item: T, moveBeforeItemId: string | undefined) => void;
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
-
/**
|
|
3
|
-
* Sentinel anchor meaning "the end of the list", mirroring the section-level
|
|
4
|
-
* `move_before_content_id: "__end__"` convention used in base-section-builder.
|
|
5
|
-
*/
|
|
6
|
-
export const END_ITEM_ANCHOR = '__end__';
|
|
7
|
-
/** Generate a stable item id. Mirrors section-level `uuid.v4()` id generation. */
|
|
8
|
-
export const generateItemId = () => uuidv4();
|
|
9
|
-
/**
|
|
10
|
-
* Walk an entire BrandPageModel and backfill a stable uuid `id` onto every
|
|
11
|
-
* nested array item that lacks one (gallery images, images/shapes/testimonial
|
|
12
|
-
* items, text items, social links, and footer social links).
|
|
13
|
-
*
|
|
14
|
-
* BP-5603: this must run BEFORE the model is minified for the AI, so the same
|
|
15
|
-
* id the AI is shown (and copies into `item_id`) is the one the executor later
|
|
16
|
-
* matches. The maker holds a single live model instance for both the minify
|
|
17
|
-
* and the apply step, so mutating it here makes the ids round-trip; they then
|
|
18
|
-
* persist on the next save. Idempotent — existing ids are preserved.
|
|
19
|
-
*/
|
|
20
|
-
export const ensureBrandPageItemIds = (model) => {
|
|
21
|
-
const ensureContentItemIds = (content) => {
|
|
22
|
-
// Every array field that the minifier surfaces as a list of items.
|
|
23
|
-
for (const field of ['images', 'items', 'textItems', 'links']) {
|
|
24
|
-
const arr = content[field];
|
|
25
|
-
if (Array.isArray(arr))
|
|
26
|
-
ensureItemIds(arr);
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
for (const page of model.pages ?? []) {
|
|
30
|
-
for (const content of page.contents ?? []) {
|
|
31
|
-
ensureContentItemIds(content);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
ensureItemIds(model.pageFooterDesktop?.socialLinks);
|
|
35
|
-
ensureItemIds(model.pageFooterMobile?.socialLinks);
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Backfill ids onto any items missing one. Per BP-5603 this runs in the
|
|
39
|
-
* metadata builder when a section is processed, so the persisted metadata
|
|
40
|
-
* returned to the client gains stable ids that subsequent AI tool calls can
|
|
41
|
-
* reference. Mutates in place.
|
|
42
|
-
*/
|
|
43
|
-
export const ensureItemIds = (items) => {
|
|
44
|
-
if (!items)
|
|
45
|
-
return;
|
|
46
|
-
for (const item of items) {
|
|
47
|
-
if (!item.id)
|
|
48
|
-
item.id = generateItemId();
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* Remove items whose id appears in `ids`. Order-independent (no descending
|
|
53
|
-
* index sort needed) — the whole point of the id-based migration. Items
|
|
54
|
-
* without an id are never removed by id.
|
|
55
|
-
*/
|
|
56
|
-
export const removeItemsByIds = (items, ids) => {
|
|
57
|
-
if (!items?.length)
|
|
58
|
-
return items ?? [];
|
|
59
|
-
if (!ids?.length)
|
|
60
|
-
return items;
|
|
61
|
-
const toRemove = new Set(ids);
|
|
62
|
-
return items.filter((item) => !item.id || !toRemove.has(item.id));
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Position `item` within `items` relative to an anchor id — the item-level
|
|
66
|
-
* mirror of base-section-builder's `moveContent`:
|
|
67
|
-
*
|
|
68
|
-
* - `moveBeforeItemId === undefined` → leave an existing item where it is;
|
|
69
|
-
* append a new (not-yet-present) item to the end.
|
|
70
|
-
* - `moveBeforeItemId === "__end__"` → move/insert at the very end.
|
|
71
|
-
* - anchor id found → insert immediately before it.
|
|
72
|
-
* - anchor id not found → fall through to the end (same
|
|
73
|
-
* forgiving behaviour as `moveContent`).
|
|
74
|
-
*
|
|
75
|
-
* Mutates `items` in place. `item` may be an existing element of `items`
|
|
76
|
-
* (a move) or a brand-new object (an insert).
|
|
77
|
-
*/
|
|
78
|
-
export const repositionItemByAnchor = (items, item, moveBeforeItemId) => {
|
|
79
|
-
const currentIndex = items.indexOf(item);
|
|
80
|
-
if (moveBeforeItemId === undefined) {
|
|
81
|
-
if (currentIndex === -1)
|
|
82
|
-
items.push(item);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (currentIndex !== -1)
|
|
86
|
-
items.splice(currentIndex, 1);
|
|
87
|
-
const anchorIndex = moveBeforeItemId === END_ITEM_ANCHOR
|
|
88
|
-
? -1
|
|
89
|
-
: items.findIndex((i) => i.id === moveBeforeItemId);
|
|
90
|
-
if (anchorIndex !== -1) {
|
|
91
|
-
items.splice(anchorIndex, 0, item);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
items.push(item);
|
|
95
|
-
}
|
|
96
|
-
};
|