@designcrowd/library.brand-page 6.2.2 → 6.2.3-ast-faq
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-7P2gNr-R.js → CreatedOnBrandCrowd-de-de-BRisMzFY.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-Dl7BymW6.js → CreatedOnBrandCrowd-en-us-CDDsL9GX.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-CO4FvWVw.js → CreatedOnBrandCrowd-es-es-BkZrEo4j.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-DHNqakQu.js → CreatedOnBrandCrowd-fr-ca-sx_ury7R.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-DHNqakQu.js → CreatedOnBrandCrowd-fr-fr-sx_ury7R.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-CGUC-ZbP.js → CreatedOnBrandCrowd-pt-br-DCWiAfkU.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-CGUC-ZbP.js → CreatedOnBrandCrowd-pt-pt-DCWiAfkU.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-Dvds-Vmy.js → CreatedOnDcom-de-de-C1S7f22L.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-fd3C-8Tp.js → CreatedOnDcom-en-us-DgTlWaXE.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-DTXZW35-.js → CreatedOnDcom-es-es-CxSQJe_V.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-DRCYOKPs.js → CreatedOnDcom-fr-ca-Bbam2tt6.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-DpIB8x2x.js → CreatedOnDcom-fr-fr-Cb0XDRPL.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-Esnxy8wX.js → CreatedOnDcom-pt-br-BjdX3-E3.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-CaiVHFXR.js → CreatedOnDcom-pt-pt-BXpbfopB.js} +1 -1
- package/lib/src/brand-page/constants/misc.constants.d.ts +8 -0
- package/lib/src/brand-page/constants/misc.constants.js +7 -0
- package/lib/src/brand-page/constants/styles.constants.d.ts +2 -0
- package/lib/src/brand-page/constants/styles.constants.js +2 -0
- package/lib/src/brand-page/models/brand-page-context.model.d.ts +0 -2
- package/lib/src/brand-page/models/brand-page-context.model.js +0 -12
- package/lib/src/brand-page/models/content.model.d.ts +1 -0
- package/lib/src/brand-page/models/content.model.js +1 -0
- package/lib/src/brand-page/models/index.d.ts +19 -0
- package/lib/src/brand-page/utils/content-callback-util.d.ts +2 -1
- package/lib/src/brand-page/utils/content-callback-util.js +3 -0
- package/lib/src/brand-page/utils/model.util.d.ts +2 -1
- package/lib/src/brand-page/utils/model.util.js +3 -0
- package/lib/src/brand-page/utils/view-model.util.d.ts +2 -0
- package/lib/src/brand-page/utils/view-model.util.js +24 -0
- package/lib/src/brand-page/view-models.d.ts +9 -2
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +0 -1
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.js +0 -9
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +10 -42
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +10 -42
- package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +0 -14
- package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +0 -42
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +0 -42
- package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +0 -42
- package/lib/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.mixin.d.ts +0 -42
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +0 -42
- package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +0 -42
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +13 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +64 -30
- package/lib/src/brand-page-maker/constants/config-settings-constant.d.ts +2 -1
- package/lib/src/brand-page-maker/constants/config-settings-constant.js +101 -2
- package/lib/src/brand-page-maker/convertors/faq-display-style.convertor.d.ts +3 -0
- package/lib/src/brand-page-maker/convertors/faq-display-style.convertor.js +47 -0
- package/lib/src/brand-page-maker/models/content-settings-configs.d.ts +22 -1
- package/lib/src/brand-page-maker/models/content-settings-configs.js +1 -0
- package/lib/src/brand-page-maker/models/content-settings.d.ts +4 -1
- package/lib/src/brand-page-maker/models/content-settings.js +45 -1
- package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +0 -42
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +1 -0
- package/lib/src/brand-page-maker/utils/apply-color-strategy.js +47 -17
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +6 -0
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +24 -1
- package/lib/src/brand-page-maker/validators/field.validator.js +2 -0
- package/lib/src/bundled-translations-DY9YvuL-.js +179 -0
- package/lib/src/bundles/bundled-translations.json +20 -2
- package/lib/src/composables/useTranslate.d.ts +1 -1
- package/lib/src/composables/useTranslate.js +1 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +143 -36
- package/lib/src/css/library.brand-page-brandPage.min.css +143 -36
- package/lib/src/css/library.brand-page-designCom.min.css +143 -36
- package/lib/src/css/library.brand-page-preview.min.css +143 -36
- package/lib/src/index.mjs +159 -158
- package/lib/src/{lib-V7aqfuiB.js → lib-DwpSAbLZ.js} +26889 -26178
- package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +1 -1
- package/lib/src/shared/color-strategies/color-strategies.js +4 -0
- package/lib/src/shared/color-strategies/rte-field-pairs.d.ts +12 -0
- package/lib/src/shared/color-strategies/rte-field-pairs.js +10 -0
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +10 -0
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +11 -1
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +10 -0
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +10 -0
- package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +10 -0
- package/lib/src/shared/content-settings/components/items-field/ItemsField.mixin.d.ts +14 -1
- package/lib/src/shared/content-settings/components/items-field/ItemsField.mixin.js +11 -1
- package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +0 -42
- package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +12 -0
- package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.js +5 -0
- package/lib/src/shared/content-settings/models.d.ts +6 -0
- package/lib/src/shared/content-settings/store/content-settings-store.d.ts +14 -1
- package/lib/src/shared/content-settings/store/content-settings-store.js +24 -2
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +0 -42
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +10 -42
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +10 -42
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +0 -56
- package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +0 -42
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +0 -42
- package/package.json +2 -2
- package/src/brand-page/components/faq-section/FaqSection.test.ts +292 -0
- package/src/brand-page/components/faq-section/FaqSection.vue +299 -0
- package/src/brand-page/components/page/PageComponent.vue +2 -0
- package/src/brand-page/components/section-heading/SectionHeading.vue +52 -0
- package/src/brand-page/components/text-wrapper/TextWrapper.test.ts +33 -0
- package/src/brand-page/constants/misc.constants.ts +12 -0
- package/src/brand-page/constants/styles.constants.ts +2 -0
- package/src/brand-page/models/brand-page-context.model.ts +0 -23
- package/src/brand-page/models/content.model.ts +1 -0
- package/src/brand-page/models/index.ts +21 -0
- package/src/brand-page/utils/content-callback-util.ts +5 -0
- package/src/brand-page/utils/model.util.ts +7 -0
- package/src/brand-page/utils/view-model.util.test.ts +96 -0
- package/src/brand-page/utils/view-model.util.ts +49 -0
- package/src/brand-page/view-models.ts +12 -1
- package/src/brand-page-maker/components/action-bar/ActionBar.mixin.ts +0 -10
- package/src/brand-page-maker/components/action-bar/ActionBarNavigation.test.ts +8 -49
- package/src/brand-page-maker/components/action-bar/ActionBarNavigation.vue +1 -1
- package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.test.ts +165 -0
- package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +37 -49
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +87 -30
- package/src/brand-page-maker/constants/config-settings-constant.ts +108 -0
- package/src/brand-page-maker/constants/faq-section-config.test.ts +151 -0
- package/src/brand-page-maker/convertors/faq-display-style.convertor.ts +59 -0
- package/src/brand-page-maker/convertors/i18n/converter.json +4 -1
- package/src/brand-page-maker/models/content-settings-configs.ts +24 -0
- package/src/brand-page-maker/models/content-settings.ts +57 -0
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +2 -0
- package/src/brand-page-maker/utils/__snapshots__/apply-color-strategy.golden.test.ts.snap +4063 -895
- package/src/brand-page-maker/utils/apply-color-strategy.test.ts +104 -2
- package/src/brand-page-maker/utils/apply-color-strategy.ts +77 -19
- package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +110 -0
- package/src/brand-page-maker/utils/rich-text-editor.util.ts +66 -0
- package/src/brand-page-maker/validators/field.validator.ts +2 -0
- package/src/bundles/bundled-translations.json +20 -2
- package/src/composables/useTranslate.ts +2 -1
- package/src/metadata-builder/builders/item-id-utils.test.ts +24 -0
- package/src/metadata-builder/parsers/section-tool-arguments.ts +2 -1
- package/src/metadata-builder/parsers/section-tool-map.test.ts +12 -0
- package/src/shared/color-strategies/color-strategies.ts +4 -0
- package/src/shared/color-strategies/rte-field-pairs.ts +23 -0
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.json +17 -1
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.vue +3 -0
- package/src/shared/content-settings/components/items-field/ItemsField.mixin.ts +11 -1
- package/src/shared/content-settings/components/items-field/ItemsField.vue +8 -2
- package/src/shared/content-settings/components/list-items-field/ListItemsField.test.ts +429 -0
- package/src/shared/content-settings/components/list-items-field/ListItemsField.vue +262 -0
- package/src/shared/content-settings/components/textarea-field/TextareaField.mixin.ts +6 -0
- package/src/shared/content-settings/components/textarea-field/TextareaField.vue +1 -0
- package/src/shared/content-settings/models.ts +7 -0
- package/src/shared/content-settings/store/content-settings-store.test.ts +70 -0
- package/src/shared/content-settings/store/content-settings-store.ts +37 -3
- package/src/shared/ecommerce-settings/util/refreshDuplicatedMetadata.test.ts +19 -0
- package/src/shared/page-settings/store/page-settings-store.test.ts +0 -71
- package/src/utils/minify-brand-page-metadata.test.ts +35 -0
- package/lib/src/bundled-translations-BYUfWBT3.js +0 -179
|
@@ -24,6 +24,24 @@ export const useExternalRichTextEditor = () => {
|
|
|
24
24
|
externalEditor,
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* An editor bound to a list item (`itemStyleTarget`) writes its toolbar styles to that
|
|
29
|
+
* item's own style field instead of the section-level `${name}Style`. Returns false when
|
|
30
|
+
* the editor has no item target, so the caller falls through to its section-level write.
|
|
31
|
+
*/
|
|
32
|
+
export const writeListItemStyles = (store, props, value, isHydrationWrite) => {
|
|
33
|
+
if (!props.itemStyleTarget) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
store.updateListItemTextStyles({
|
|
37
|
+
id: props.rawId,
|
|
38
|
+
name: props.name,
|
|
39
|
+
value,
|
|
40
|
+
target: props.itemStyleTarget,
|
|
41
|
+
isHydrationWrite,
|
|
42
|
+
});
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
27
45
|
export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDropdownRef,
|
|
28
46
|
// One entry of `textStyleOptions`; `undefined` when the selection is "none".
|
|
29
47
|
selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyleTypeOptions, markedText, isHyperlinkPopupOpen, selectedLinkTypeValue) => {
|
|
@@ -204,6 +222,21 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
204
222
|
});
|
|
205
223
|
}
|
|
206
224
|
});
|
|
225
|
+
// Set while a toolbar command runs. The toolbar has taken focus by then, so
|
|
226
|
+
// `isFocused` alone would tag the command's write as hydration and fold it into
|
|
227
|
+
// the previous undo entry — hidden only when a style write rides along and opens
|
|
228
|
+
// an entry of its own. Synchronous commands only: the spacing sliders dispatch
|
|
229
|
+
// after a debounce and are not covered.
|
|
230
|
+
let isRunningToolbarCommand = false;
|
|
231
|
+
const runAsToolbarCommand = (command) => {
|
|
232
|
+
isRunningToolbarCommand = true;
|
|
233
|
+
try {
|
|
234
|
+
return command();
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
isRunningToolbarCommand = false;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
207
240
|
// Update model when editor content changes. RTE content is stored as Tiptap
|
|
208
241
|
// JSON (BP-5787). getJSON() is already in hand (the editor holds the doc) and
|
|
209
242
|
// is sanitised natively — no getHTML(), no DOMPurify, no extra editor — so
|
|
@@ -217,15 +250,9 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
217
250
|
// field → store chain and arms the history merge at the moment of the
|
|
218
251
|
// store write — arming here at emit time would lapse before the
|
|
219
252
|
// debounce fires. Genuine edits happen while focused and commit
|
|
220
|
-
// normally.
|
|
221
|
-
//
|
|
222
|
-
// Known limitation: a programmatic toolbar command run on an editor the
|
|
223
|
-
// user hasn't focused yet would also merge (losing that undo step). Today
|
|
224
|
-
// the RTE only mounts inside an already-open settings drawer and the user
|
|
225
|
-
// focuses it before formatting, so this doesn't occur — revisit if a
|
|
226
|
-
// consumer ever drives toolbar actions on an unfocused editor.
|
|
253
|
+
// normally, and so do synchronous toolbar commands (isRunningToolbarCommand).
|
|
227
254
|
emit('update:modelValue', sanitizeRteJson(editor.getJSON()), {
|
|
228
|
-
isHydrationWrite: !editor.isFocused,
|
|
255
|
+
isHydrationWrite: !editor.isFocused && !isRunningToolbarCommand,
|
|
229
256
|
});
|
|
230
257
|
});
|
|
231
258
|
editor.on('selectionUpdate', () => {
|
|
@@ -303,26 +330,30 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
303
330
|
// write lands ~100ms BEFORE the editor's canonical text write-back, and
|
|
304
331
|
// an unflagged write here would open a plain capture burst that
|
|
305
332
|
// swallows the flagged text write into a phantom entry (BP-5810).
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
333
|
+
const syncedStyles = {
|
|
334
|
+
fontSize: globalStyles.fontSize,
|
|
335
|
+
fontFamily: globalStyles.fontFamily,
|
|
336
|
+
fontWeight: globalStyles.fontWeight,
|
|
337
|
+
fontStyle: globalStyles.fontStyle,
|
|
338
|
+
textDecoration: globalStyles.textDecoration,
|
|
339
|
+
// Keep an element colour override (a creation-time contrast bake, or a
|
|
340
|
+
// colour picked while linked) — only fall back to the global style's colour
|
|
341
|
+
// when the element has none, mirroring `resolveTextColor`'s element-first
|
|
342
|
+
// cascade. Blindly taking `globalStyles.color` here re-derived the linked
|
|
343
|
+
// colour on every RTE mount and clobbered the override.
|
|
344
|
+
color: props.styles?.color || globalStyles.color,
|
|
345
|
+
lineHeight: globalStyles.lineHeight,
|
|
346
|
+
letterSpacing: globalStyles.letterSpacing,
|
|
347
|
+
};
|
|
348
|
+
const isHydrationWrite = !editor.isFocused;
|
|
349
|
+
if (!writeListItemStyles(contentSettingStore, props, syncedStyles, isHydrationWrite)) {
|
|
350
|
+
contentSettingStore.updateTextStyles({
|
|
351
|
+
id: props.rawId,
|
|
352
|
+
name: props.name,
|
|
353
|
+
value: syncedStyles,
|
|
354
|
+
isHydrationWrite,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
326
357
|
// sync toolbar editor styles
|
|
327
358
|
fontSettings.selectedFont = globalStyles?.fontFamily ?? 'Lato';
|
|
328
359
|
fontSettings.selectedFontSize = globalStyles?.fontSize ?? '2.25em';
|
|
@@ -476,6 +507,9 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
476
507
|
syncContentSettings(fontStyleChanges);
|
|
477
508
|
};
|
|
478
509
|
const syncContentSettings = (fontStyleChanges) => {
|
|
510
|
+
if (writeListItemStyles(contentSettingStore, props, fontStyleChanges)) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
479
513
|
if (props.name === 'textItems') {
|
|
480
514
|
contentSettingStore.updateTextItemTextStyleTypeWithStyles({
|
|
481
515
|
id: props.rawId,
|
|
@@ -584,7 +618,7 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
584
618
|
editor,
|
|
585
619
|
onFocus,
|
|
586
620
|
onBlur,
|
|
587
|
-
triggerEditorStyleChange,
|
|
621
|
+
triggerEditorStyleChange: (editorOption) => runAsToolbarCommand(() => triggerEditorStyleChange(editorOption)),
|
|
588
622
|
toggleBold,
|
|
589
623
|
toggleItalic,
|
|
590
624
|
toggleUnderline,
|
|
@@ -601,7 +635,7 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
601
635
|
setInitialStyleSettings,
|
|
602
636
|
copyGlobalStyleSettings,
|
|
603
637
|
unsetAllMarks,
|
|
604
|
-
handleHyperlink,
|
|
638
|
+
handleHyperlink: (...args) => runAsToolbarCommand(() => handleHyperlink(...args)),
|
|
605
639
|
hyperlinkValue,
|
|
606
640
|
setHyperlinkUrlValue,
|
|
607
641
|
shouldShow,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LogoContent, FacebookContent, GeneralLinkContent, PhoneContent, EmailContent, ImageContent, InstagramContent, LinkedInContent, PinterestContent, ProfileContent, TextContent, TiktokContent, TwitchContent, XContent, VideoContent, WebsiteContent, YoutubeContent, ContentType, MapContent, ImageGalleryContent, MailingListContent, RequestPaymentContent, SupportMeContent, ContactFormContent, BannerSectionContent, SocialLinksContent, ImagesSectionContent, TestimonialSectionContent, AboutSectionContent, DividerSectionContent, ShapesSectionContent, ShopContent, BookingSectionContent } from '@brand-page';
|
|
1
|
+
import type { LogoContent, FacebookContent, GeneralLinkContent, PhoneContent, EmailContent, ImageContent, InstagramContent, LinkedInContent, PinterestContent, ProfileContent, TextContent, TiktokContent, TwitchContent, XContent, VideoContent, WebsiteContent, YoutubeContent, ContentType, MapContent, ImageGalleryContent, MailingListContent, RequestPaymentContent, SupportMeContent, ContactFormContent, BannerSectionContent, SocialLinksContent, ImagesSectionContent, TestimonialSectionContent, AboutSectionContent, DividerSectionContent, ShapesSectionContent, ShopContent, BookingSectionContent, FaqSectionContent } from '@brand-page';
|
|
2
2
|
import type { ContentSettingsConfig, ContentSettingsField, ContentSettingsMultiField } from '../models';
|
|
3
3
|
export declare const LOGO_SETTINGS_CONFIG: () => ContentSettingsConfig<Omit<LogoContent, "version" | "logoVariation" | "logoImageHeight" | "logoImageWidth" | "logoLastUpdate" | "logoImageBase64Url">>;
|
|
4
4
|
export declare const GENERAL_LINK_CONTENT_SETTINGS_CONFIG: () => ContentSettingsConfig<GeneralLinkContent>;
|
|
@@ -51,4 +51,5 @@ export declare const SHOP_SECTION_SETTINGS_CONFIG: () => ContentSettingsConfig<S
|
|
|
51
51
|
isShippingEnabled: boolean;
|
|
52
52
|
}>;
|
|
53
53
|
export declare const BOOKING_SECTION_SETTINGS_CONFIG: () => ContentSettingsConfig<BookingSectionContent>;
|
|
54
|
+
export declare const FAQ_SECTION_SETTINGS_CONFIG: () => ContentSettingsConfig<FaqSectionContent>;
|
|
54
55
|
export declare const CONTENT_SETTINGS_CONFIGS: () => Record<ContentType, ContentSettingsConfig<any>>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SOCIAL_LINKS_ICON_DISPLAY_STYLES, BRAND_PAGE_TYPES, DIVIDER_STYLES, MEDIA_TYPES, BUTTON_LINK_TYPE, FONT_SIZE_BODY, LINE_HEIGHT_BODY, MIN_TEXT_SIZE_PX, MAX_TEXT_SIZE_PX, TEXT_COLUMNS, DEFAULT_SHAPE_SIZE, PAYMENT_OPTION_DISPLAY_TYPES, PAYMENT_OPTION_IMAGE_TYPES, GettyVideoMedia, } from '@brand-page';
|
|
2
|
-
import { createInitialButtonContent, createInitialImageContent, createInitialProfileContent, createInitialTextContent, createInitialVideoContent, createInitialLogoContent, createInitialMapContent, createInitialImageGalleryContent, createInitialGeneralLinkContent, createInitialMailingListContent, createInitialRequestPaymentContent, createInitialSupportMeContent, createInitialContactFormContent, CONTENT_SETTINGS_DISPLAY_MODES, createInitialBannerSectionContent, createInitialSocialLinksContent, createInitialImagesSectionContent, createInitialTestimonialSectionContent, createInitialAboutSectionContent, createInitialDividerSectionContent, createInitialShapesSectionContent, VARIANT_DISPLAY_MODES, createInitialShopContent, createInitialBookingSectionContent, } from '../models';
|
|
1
|
+
import { FAQ_DISPLAY_STYLES, FAQ_MAX_ITEMS, SOCIAL_LINKS_ICON_DISPLAY_STYLES, BRAND_PAGE_TYPES, DIVIDER_STYLES, MEDIA_TYPES, BUTTON_LINK_TYPE, FONT_SIZE_BODY, LINE_HEIGHT_BODY, MIN_TEXT_SIZE_PX, MAX_TEXT_SIZE_PX, TEXT_COLUMNS, DEFAULT_SHAPE_SIZE, PAYMENT_OPTION_DISPLAY_TYPES, PAYMENT_OPTION_IMAGE_TYPES, GettyVideoMedia, } from '@brand-page';
|
|
2
|
+
import { createInitialButtonContent, createInitialImageContent, createInitialProfileContent, createInitialTextContent, createInitialVideoContent, createInitialLogoContent, createInitialMapContent, createInitialImageGalleryContent, createInitialGeneralLinkContent, createInitialMailingListContent, createInitialRequestPaymentContent, createInitialSupportMeContent, createInitialContactFormContent, CONTENT_SETTINGS_DISPLAY_MODES, createInitialBannerSectionContent, createInitialSocialLinksContent, createInitialImagesSectionContent, createInitialTestimonialSectionContent, createInitialAboutSectionContent, createInitialDividerSectionContent, createInitialShapesSectionContent, VARIANT_DISPLAY_MODES, createInitialShopContent, createInitialBookingSectionContent, createInitialFaqSectionContent, createInitialFaqQuestionStyle, createInitialFaqAnswerStyle, } from '../models';
|
|
3
3
|
import * as uuid from 'uuid';
|
|
4
4
|
import { colorConvertor, backgroundColorConvertor, borderColorConvertor, displayStyleConvertor, galleryTypeConvertor, imageAspectRatioConvertor, textAlignmentOptionsConvertor, videoContentStateConvertor, fillColorConvertor, bannerAlignDisplayStyleConvertor, aboutDisplayStyleConvertor, dividerStyleConvertor, shapeSizeOptionsConvertor, buttonLinkStyleConvertor, textSizeValueConvertor, textColumnStyleConvertor, contactLayoutStyleConvertor, paymentLinkDisplayStyleConvertor, shopDisplayConvertor, shopAspectRatioConvertor, } from '../convertors';
|
|
5
5
|
import { ALIGN_CENTERED, DISPLAY_STYLE_COLLAPSED, DISPLAY_STYLE_PREVIEW, } from '@brand-page';
|
|
@@ -8,6 +8,7 @@ import { contactFormCardColorDefaultGetter, paymentFillColorFieldDefaultGetter,
|
|
|
8
8
|
import { socialLinksIconDisplayStyleConvertor } from '../convertors/social-links-icon-display-style.convertor';
|
|
9
9
|
import { getTextMediaOptionsConverterByMediaType } from '../convertors/text-image-display-style.convertor';
|
|
10
10
|
import { testimonialDisplayStyleConvertor } from '../convertors/testimonial-display-style-convertor';
|
|
11
|
+
import { faqDisplayStyleConvertor } from '../convertors/faq-display-style.convertor';
|
|
11
12
|
import { pageValidator, urlValidator } from '../validators';
|
|
12
13
|
import { imagesSectionAspectRatioVisibilityAssessor } from '../assessors/images-section-aspect-ratio-visibility.assessor';
|
|
13
14
|
import { bannerLinkTypeVisibilityAssessor, bannerSectionPageVisibilityAssessor, bannerSectionUrlVisibilityAssessor, bannerDisplayTypeVisibilityAssessor, bannerOverlayOptionsVisibilityAssessor, } from '../assessors/banner-section-description-visibility.assessor';
|
|
@@ -2807,6 +2808,103 @@ export const BOOKING_SECTION_SETTINGS_CONFIG = () => ({
|
|
|
2807
2808
|
isEnabled: true,
|
|
2808
2809
|
isLocked: false,
|
|
2809
2810
|
});
|
|
2811
|
+
const FAQ_FIELD_GROUP_IDS = {
|
|
2812
|
+
settings: 'settings',
|
|
2813
|
+
items: 'items',
|
|
2814
|
+
style: 'style',
|
|
2815
|
+
};
|
|
2816
|
+
export const FAQ_SECTION_SETTINGS_CONFIG = () => ({
|
|
2817
|
+
type: 'faq-section',
|
|
2818
|
+
category: 'general',
|
|
2819
|
+
createInitialContent: createInitialFaqSectionContent,
|
|
2820
|
+
displayMode: CONTENT_SETTINGS_DISPLAY_MODES.focused,
|
|
2821
|
+
defaultIconName: 'question-circle-filled',
|
|
2822
|
+
displayName: contentSettingsTr(`faqSectionDisplayName`),
|
|
2823
|
+
fieldGroups: [
|
|
2824
|
+
{
|
|
2825
|
+
id: FAQ_FIELD_GROUP_IDS.settings,
|
|
2826
|
+
displayName: contentSettingsTr(`settingsDisplayName`),
|
|
2827
|
+
isCollapsed: false,
|
|
2828
|
+
},
|
|
2829
|
+
{
|
|
2830
|
+
id: FAQ_FIELD_GROUP_IDS.items,
|
|
2831
|
+
displayName: contentSettingsTr(`faqItemsDisplayName`),
|
|
2832
|
+
isCollapsed: false,
|
|
2833
|
+
},
|
|
2834
|
+
{
|
|
2835
|
+
id: FAQ_FIELD_GROUP_IDS.style,
|
|
2836
|
+
displayName: contentSettingsTr(`styleDisplayName`),
|
|
2837
|
+
isCollapsed: true,
|
|
2838
|
+
},
|
|
2839
|
+
],
|
|
2840
|
+
fields: {
|
|
2841
|
+
titleStyle: DEFAULT_TITLE_STYLE_SETTINGS_FILED_WITH_TITLE(),
|
|
2842
|
+
descriptionStyle: DEFAULT_DESCRIPTION_STYLE_FILED(),
|
|
2843
|
+
title: {
|
|
2844
|
+
type: 'text',
|
|
2845
|
+
placeholder: contentSettingsTr(`titlePlaceholder`),
|
|
2846
|
+
title: contentSettingsTr(`titleTitle`),
|
|
2847
|
+
groupId: FAQ_FIELD_GROUP_IDS.settings,
|
|
2848
|
+
maxLength: 200,
|
|
2849
|
+
},
|
|
2850
|
+
description: {
|
|
2851
|
+
type: 'textarea',
|
|
2852
|
+
placeholder: contentSettingsTr(`descriptionPlaceholder`),
|
|
2853
|
+
title: contentSettingsTr(`descriptionTitle`),
|
|
2854
|
+
groupId: FAQ_FIELD_GROUP_IDS.settings,
|
|
2855
|
+
maxLength: 1000,
|
|
2856
|
+
},
|
|
2857
|
+
items: {
|
|
2858
|
+
type: 'list-items',
|
|
2859
|
+
defaultValue: [],
|
|
2860
|
+
groupId: FAQ_FIELD_GROUP_IDS.items,
|
|
2861
|
+
maxLength: FAQ_MAX_ITEMS,
|
|
2862
|
+
itemFields: [
|
|
2863
|
+
{
|
|
2864
|
+
key: 'question',
|
|
2865
|
+
kind: 'text',
|
|
2866
|
+
styleKey: 'questionStyle',
|
|
2867
|
+
defaultStyle: () => createInitialFaqQuestionStyle(),
|
|
2868
|
+
maxLength: 200,
|
|
2869
|
+
title: contentSettingsTr(`faqQuestionTitle`),
|
|
2870
|
+
placeholder: contentSettingsTr(`faqQuestionPlaceholder`),
|
|
2871
|
+
defaultValue: () => contentSettingsTr(`faqNewQuestion`),
|
|
2872
|
+
},
|
|
2873
|
+
{
|
|
2874
|
+
key: 'answer',
|
|
2875
|
+
kind: 'textarea',
|
|
2876
|
+
styleKey: 'answerStyle',
|
|
2877
|
+
defaultStyle: () => createInitialFaqAnswerStyle(),
|
|
2878
|
+
maxLength: 1000,
|
|
2879
|
+
title: contentSettingsTr(`faqAnswerTitle`),
|
|
2880
|
+
placeholder: contentSettingsTr(`faqAnswerPlaceholder`),
|
|
2881
|
+
defaultValue: () => contentSettingsTr(`faqNewAnswer`),
|
|
2882
|
+
},
|
|
2883
|
+
],
|
|
2884
|
+
},
|
|
2885
|
+
displayStyle: {
|
|
2886
|
+
type: 'radio',
|
|
2887
|
+
role: 'multi',
|
|
2888
|
+
defaultValue: FAQ_DISPLAY_STYLES.centered,
|
|
2889
|
+
title: contentSettingsTr(`displayStyleTitle`),
|
|
2890
|
+
optionsConvertor: faqDisplayStyleConvertor,
|
|
2891
|
+
groupId: FAQ_FIELD_GROUP_IDS.style,
|
|
2892
|
+
variant: 'icon',
|
|
2893
|
+
},
|
|
2894
|
+
...PADDING_CONTROL_FIELDS(FAQ_FIELD_GROUP_IDS.style),
|
|
2895
|
+
backgroundStyle: {
|
|
2896
|
+
type: 'color',
|
|
2897
|
+
groupId: FAQ_FIELD_GROUP_IDS.style,
|
|
2898
|
+
defaultValue: {},
|
|
2899
|
+
isInline: true,
|
|
2900
|
+
showToggle: false,
|
|
2901
|
+
title: contentSettingsTr(`backgroundColorTitle`),
|
|
2902
|
+
valueConvertor: backgroundColorConvertor,
|
|
2903
|
+
},
|
|
2904
|
+
},
|
|
2905
|
+
isEnabled: true,
|
|
2906
|
+
isLocked: false,
|
|
2907
|
+
});
|
|
2810
2908
|
export const CONTENT_SETTINGS_CONFIGS = () => ({
|
|
2811
2909
|
logo: LOGO_SETTINGS_CONFIG(),
|
|
2812
2910
|
'general-link': GENERAL_LINK_CONTENT_SETTINGS_CONFIG(),
|
|
@@ -2840,4 +2938,5 @@ export const CONTENT_SETTINGS_CONFIGS = () => ({
|
|
|
2840
2938
|
'shapes-section': SHAPES_SECTION_SETTINGS_CONFIG(),
|
|
2841
2939
|
'shop-section': SHOP_SECTION_SETTINGS_CONFIG(),
|
|
2842
2940
|
'booking-section': BOOKING_SECTION_SETTINGS_CONFIG(),
|
|
2941
|
+
'faq-section': FAQ_SECTION_SETTINGS_CONFIG(),
|
|
2843
2942
|
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { FAQ_DISPLAY_STYLES } from '@brand-page/constants';
|
|
2
|
+
import { converterTr } from '@src/composables/useTranslate';
|
|
3
|
+
const ICON_VIEW_BOX = '0 0 96 56';
|
|
4
|
+
export const faqDisplayStyleConvertor = {
|
|
5
|
+
convertBackToMultipleValues: true,
|
|
6
|
+
convert(value) {
|
|
7
|
+
return {
|
|
8
|
+
options: [
|
|
9
|
+
{
|
|
10
|
+
title: converterTr(`faqCenteredAccordion`),
|
|
11
|
+
value: FAQ_DISPLAY_STYLES.centered,
|
|
12
|
+
isSelected: value === FAQ_DISPLAY_STYLES.centered,
|
|
13
|
+
iconName: 'display-style-faq-1',
|
|
14
|
+
iconViewBox: ICON_VIEW_BOX,
|
|
15
|
+
dataAttribute: 'data-test-btn-faq-centered',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
title: converterTr(`faqSplitAccordion`),
|
|
19
|
+
value: FAQ_DISPLAY_STYLES.split,
|
|
20
|
+
isSelected: value === FAQ_DISPLAY_STYLES.split,
|
|
21
|
+
iconName: 'display-style-faq-2',
|
|
22
|
+
iconViewBox: ICON_VIEW_BOX,
|
|
23
|
+
dataAttribute: 'data-test-btn-faq-split',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
title: converterTr(`faqGrid`),
|
|
27
|
+
value: FAQ_DISPLAY_STYLES.grid,
|
|
28
|
+
isSelected: value === FAQ_DISPLAY_STYLES.grid,
|
|
29
|
+
iconName: 'display-style-faq-3',
|
|
30
|
+
iconViewBox: ICON_VIEW_BOX,
|
|
31
|
+
dataAttribute: 'data-test-btn-faq-grid',
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
// The heading sits left beside the accordion in split, centred above it otherwise.
|
|
37
|
+
convertBack(config) {
|
|
38
|
+
const displayStyle = config.options.find((v) => v.isSelected)?.value ??
|
|
39
|
+
FAQ_DISPLAY_STYLES.centered;
|
|
40
|
+
const textAlign = displayStyle === FAQ_DISPLAY_STYLES.split ? 'left' : 'center';
|
|
41
|
+
return {
|
|
42
|
+
displayStyle,
|
|
43
|
+
titleStyle: { textAlign },
|
|
44
|
+
descriptionStyle: { textAlign },
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BrandPageContext, BrandPageType, Content, ContentType } from '@brand-page';
|
|
1
|
+
import type { BrandPageContext, BrandPageType, Content, ContentType, TextStyleDeclaration } from '@brand-page';
|
|
2
2
|
import type { ContentReplaceImageSettings } from '@shared/content-settings/models';
|
|
3
3
|
import type { UIUserFeatures } from '@src/constants/ui';
|
|
4
4
|
import type { OptionsConvertor, ValueConvertor } from './convertor.model';
|
|
@@ -52,6 +52,7 @@ export declare const ITEM_FIELD_TYPES: {
|
|
|
52
52
|
readonly 'color-replacements': "color-replacements";
|
|
53
53
|
readonly 'testimonial-items': "testimonial-items";
|
|
54
54
|
readonly 'text-items': "text-items";
|
|
55
|
+
readonly 'list-items': "list-items";
|
|
55
56
|
readonly 'page-dropdown': "page-dropdown";
|
|
56
57
|
readonly 'personalisation-override': "personalisation-override";
|
|
57
58
|
};
|
|
@@ -104,6 +105,26 @@ export interface ContentSettingsField<TContent> {
|
|
|
104
105
|
* Defaults to `${fieldName}Style` when not specified.
|
|
105
106
|
*/
|
|
106
107
|
styleName?: string;
|
|
108
|
+
/** `list-items` only: the per-item inputs, in order. The first `text` input labels the row. */
|
|
109
|
+
itemFields?: ListItemFieldSchema[];
|
|
110
|
+
}
|
|
111
|
+
export interface ListItemFieldSchema {
|
|
112
|
+
key: string;
|
|
113
|
+
/** The plain input used when the rich-text editor is unavailable. */
|
|
114
|
+
kind: 'text' | 'textarea';
|
|
115
|
+
title: string;
|
|
116
|
+
placeholder?: string;
|
|
117
|
+
maxLength?: number;
|
|
118
|
+
/**
|
|
119
|
+
* The item field that holds this text's style. Set it to make the text rich text —
|
|
120
|
+
* the same editor as a section title, writing this item's own style — whenever the
|
|
121
|
+
* section allows rich text. Without rich text, a font-style control edits it instead.
|
|
122
|
+
*/
|
|
123
|
+
styleKey?: string;
|
|
124
|
+
/** Style a first item starts with; later items copy the last item's style. */
|
|
125
|
+
defaultStyle?: () => TextStyleDeclaration;
|
|
126
|
+
/** Value a newly added item starts with. */
|
|
127
|
+
defaultValue?: () => string;
|
|
107
128
|
}
|
|
108
129
|
export interface ContentSettingsMultiField<TContent, TField> extends Omit<ContentSettingsField<TContent>, 'type' | 'role'> {
|
|
109
130
|
type: ItemMultiFieldType;
|
|
@@ -55,6 +55,7 @@ export const ITEM_FIELD_TYPES = {
|
|
|
55
55
|
'color-replacements': 'color-replacements',
|
|
56
56
|
'testimonial-items': 'testimonial-items',
|
|
57
57
|
'text-items': 'text-items',
|
|
58
|
+
'list-items': 'list-items',
|
|
58
59
|
'page-dropdown': 'page-dropdown',
|
|
59
60
|
'personalisation-override': 'personalisation-override',
|
|
60
61
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BrandPageModel } from '@brand-page';
|
|
2
|
-
import type { ButtonContent, ContentType, ImageContent, ProfileContent, TextContent, VideoContent, LogoContent, LogoTheme, MapContent, ImageGalleryContent, GeneralLinkContent, MailingListContent, RequestPaymentContent, ContactFormContent, BannerSectionContent, SocialLinksContent, ImagesSectionContent, TestimonialSectionContent, AboutSectionContent, DividerSectionContent, ShapesSectionContent, BrandPageType, SupportMeContent, ShopContent, BookingSectionContent } from '@brand-page';
|
|
2
|
+
import type { ButtonContent, ContentType, ImageContent, ProfileContent, TextContent, VideoContent, LogoContent, LogoTheme, MapContent, ImageGalleryContent, GeneralLinkContent, MailingListContent, RequestPaymentContent, ContactFormContent, BannerSectionContent, SocialLinksContent, ImagesSectionContent, TestimonialSectionContent, AboutSectionContent, DividerSectionContent, ShapesSectionContent, BrandPageType, SupportMeContent, ShopContent, BookingSectionContent, TextStyleDeclaration, FaqSectionContent } from '@brand-page';
|
|
3
3
|
import type { CreateInitialContentFunction } from './content-settings-configs';
|
|
4
4
|
import type { CreateInitialContentOptions } from '@shared/content-settings/models';
|
|
5
5
|
export declare const createInitialButtonContent: (type: ContentType, iconUrl: string, options?: CreateInitialContentOptions) => () => ButtonContent;
|
|
@@ -18,6 +18,9 @@ export declare const createInitialSupportMeContent: (options?: CreateInitialCont
|
|
|
18
18
|
export declare const createInitialContactFormContent: CreateInitialContentFunction<ContactFormContent>;
|
|
19
19
|
export declare const createInitialBannerSectionContent: CreateInitialContentFunction<BannerSectionContent>;
|
|
20
20
|
export declare const createInitialBookingSectionContent: CreateInitialContentFunction<BookingSectionContent>;
|
|
21
|
+
export declare const createInitialFaqQuestionStyle: (applyAutoScale?: boolean) => TextStyleDeclaration;
|
|
22
|
+
export declare const createInitialFaqAnswerStyle: (applyAutoScale?: boolean) => TextStyleDeclaration;
|
|
23
|
+
export declare const createInitialFaqSectionContent: CreateInitialContentFunction<FaqSectionContent>;
|
|
21
24
|
export declare const createInitialImagesSectionContent: CreateInitialContentFunction<ImagesSectionContent>;
|
|
22
25
|
export declare const createInitialTestimonialSectionContent: CreateInitialContentFunction<TestimonialSectionContent>;
|
|
23
26
|
export declare const createInitialAboutSectionContent: CreateInitialContentFunction<AboutSectionContent>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BrandPageModel, PageStyles, FORM_FIELD_IDS, PAYMENT_OPTION_DISPLAY_TYPES, PAYMENT_OPTION_IMAGE_TYPES, SOCIAL_LINKS_ICON_DISPLAY_STYLES, PageHeaderMobile, PageHeaderDesktop, PageFooterMobile, PageFooterDesktop, MEDIA_TYPES, BUTTON_LINK_TYPE, DISPLAY_STYLE_PREVIEW, SUPPORT_ME_CUSTOM_PRODUCT_NAME, DEFAULT_LOGO_HEIGHT, DEFAULT_LOGO_WIDTH, FONT_SIZE_BODY, LINE_HEIGHT_BODY, TEXT_STYLE_TYPES, TEXT_COLUMNS, DEFAULT_LOGO_BACKGROUND_COLOR_RGB, DEFAULT_LOGO_TEXT_COLOR_RGB, EMPTY_LOGO_IMAGE_MODEL, BRAND_PAGE_TYPES, SENSITIVE_CONTENT_TYPES, CONTACT_FORM_LAYOUT_DEFAULT_PADDING, TESTIMONIAL_DEFAULT_PADDING, } from '@brand-page';
|
|
1
|
+
import { BrandPageModel, PageStyles, FORM_FIELD_IDS, PAYMENT_OPTION_DISPLAY_TYPES, PAYMENT_OPTION_IMAGE_TYPES, SOCIAL_LINKS_ICON_DISPLAY_STYLES, PageHeaderMobile, PageHeaderDesktop, PageFooterMobile, PageFooterDesktop, MEDIA_TYPES, BUTTON_LINK_TYPE, DISPLAY_STYLE_PREVIEW, SUPPORT_ME_CUSTOM_PRODUCT_NAME, DEFAULT_LOGO_HEIGHT, DEFAULT_LOGO_WIDTH, FONT_SIZE_BODY, LINE_HEIGHT_BODY, TEXT_STYLE_TYPES, TEXT_COLUMNS, DEFAULT_LOGO_BACKGROUND_COLOR_RGB, DEFAULT_LOGO_TEXT_COLOR_RGB, EMPTY_LOGO_IMAGE_MODEL, BRAND_PAGE_TYPES, SENSITIVE_CONTENT_TYPES, CONTACT_FORM_LAYOUT_DEFAULT_PADDING, TESTIMONIAL_DEFAULT_PADDING, FAQ_DISPLAY_STYLES, } from '@brand-page';
|
|
2
2
|
import * as uuid from 'uuid';
|
|
3
3
|
import { getColorShades, DEFAULT_CARD_SURFACE_REFERENCE, } from '@brand-page/utils';
|
|
4
4
|
import { contentSettingsTr } from '@src/composables/useTranslate';
|
|
@@ -556,6 +556,50 @@ export const createInitialBookingSectionContent = (options) => {
|
|
|
556
556
|
},
|
|
557
557
|
};
|
|
558
558
|
};
|
|
559
|
+
// Questions follow the Headings role, answers the Paragraphs role.
|
|
560
|
+
export const createInitialFaqQuestionStyle = (applyAutoScale = false) => ({
|
|
561
|
+
applyAutoScale,
|
|
562
|
+
textStyleType: TEXT_STYLE_TYPES.headings,
|
|
563
|
+
textAlign: 'left',
|
|
564
|
+
});
|
|
565
|
+
export const createInitialFaqAnswerStyle = (applyAutoScale = false) => ({
|
|
566
|
+
applyAutoScale,
|
|
567
|
+
textStyleType: TEXT_STYLE_TYPES.paragraphs,
|
|
568
|
+
textAlign: 'left',
|
|
569
|
+
});
|
|
570
|
+
export const createInitialFaqSectionContent = (options) => {
|
|
571
|
+
const applyAutoScale = options?.brandPageType === BRAND_PAGE_TYPES.brandSite;
|
|
572
|
+
return {
|
|
573
|
+
id: uuid.v4(),
|
|
574
|
+
type: 'faq-section',
|
|
575
|
+
title: contentSettingsTr(`defaultFaqTitle`),
|
|
576
|
+
description: contentSettingsTr(`defaultFaqDescription`),
|
|
577
|
+
displayStyle: FAQ_DISPLAY_STYLES.centered,
|
|
578
|
+
topPadding: 32,
|
|
579
|
+
bottomPadding: 32,
|
|
580
|
+
// One sample item; the design's four are only there to show a longer list.
|
|
581
|
+
items: [
|
|
582
|
+
{
|
|
583
|
+
id: uuid.v4(),
|
|
584
|
+
question: contentSettingsTr(`defaultFaqQuestion`),
|
|
585
|
+
questionStyle: createInitialFaqQuestionStyle(applyAutoScale),
|
|
586
|
+
answer: contentSettingsTr(`defaultFaqAnswer`),
|
|
587
|
+
answerStyle: createInitialFaqAnswerStyle(applyAutoScale),
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
titleStyle: {
|
|
591
|
+
applyAutoScale,
|
|
592
|
+
textStyleType: TEXT_STYLE_TYPES.titles,
|
|
593
|
+
textAlign: 'center',
|
|
594
|
+
},
|
|
595
|
+
descriptionStyle: {
|
|
596
|
+
applyAutoScale,
|
|
597
|
+
textStyleType: TEXT_STYLE_TYPES.paragraphs,
|
|
598
|
+
textAlign: 'center',
|
|
599
|
+
},
|
|
600
|
+
backgroundStyle: {},
|
|
601
|
+
};
|
|
602
|
+
};
|
|
559
603
|
export const createInitialImagesSectionContent = (options) => {
|
|
560
604
|
return {
|
|
561
605
|
id: uuid.v4(),
|
|
@@ -158,20 +158,6 @@ export declare const useBrandPageContainerStore: import("pinia").StoreDefinition
|
|
|
158
158
|
isVariation: boolean;
|
|
159
159
|
isExcluded: boolean;
|
|
160
160
|
} | undefined;
|
|
161
|
-
bp_5873_live_preview_prepurchase?: {
|
|
162
|
-
key: string;
|
|
163
|
-
value: string;
|
|
164
|
-
isControl: boolean;
|
|
165
|
-
isVariation: boolean;
|
|
166
|
-
isExcluded: boolean;
|
|
167
|
-
} | undefined;
|
|
168
|
-
bp_5873_live_preview_postpurchase?: {
|
|
169
|
-
key: string;
|
|
170
|
-
value: string;
|
|
171
|
-
isControl: boolean;
|
|
172
|
-
isVariation: boolean;
|
|
173
|
-
isExcluded: boolean;
|
|
174
|
-
} | undefined;
|
|
175
161
|
};
|
|
176
162
|
isSubsequentPublish: boolean;
|
|
177
163
|
isContextualUpgradeModalVisible: boolean;
|
|
@@ -247,20 +233,6 @@ export declare const useBrandPageContainerStore: import("pinia").StoreDefinition
|
|
|
247
233
|
isVariation: boolean;
|
|
248
234
|
isExcluded: boolean;
|
|
249
235
|
} | undefined;
|
|
250
|
-
bp_5873_live_preview_prepurchase?: {
|
|
251
|
-
key: string;
|
|
252
|
-
value: string;
|
|
253
|
-
isControl: boolean;
|
|
254
|
-
isVariation: boolean;
|
|
255
|
-
isExcluded: boolean;
|
|
256
|
-
} | undefined;
|
|
257
|
-
bp_5873_live_preview_postpurchase?: {
|
|
258
|
-
key: string;
|
|
259
|
-
value: string;
|
|
260
|
-
isControl: boolean;
|
|
261
|
-
isVariation: boolean;
|
|
262
|
-
isExcluded: boolean;
|
|
263
|
-
} | undefined;
|
|
264
236
|
};
|
|
265
237
|
isSubsequentPublish: boolean;
|
|
266
238
|
isContextualUpgradeModalVisible: boolean;
|
|
@@ -336,20 +308,6 @@ export declare const useBrandPageContainerStore: import("pinia").StoreDefinition
|
|
|
336
308
|
isVariation: boolean;
|
|
337
309
|
isExcluded: boolean;
|
|
338
310
|
} | undefined;
|
|
339
|
-
bp_5873_live_preview_prepurchase?: {
|
|
340
|
-
key: string;
|
|
341
|
-
value: string;
|
|
342
|
-
isControl: boolean;
|
|
343
|
-
isVariation: boolean;
|
|
344
|
-
isExcluded: boolean;
|
|
345
|
-
} | undefined;
|
|
346
|
-
bp_5873_live_preview_postpurchase?: {
|
|
347
|
-
key: string;
|
|
348
|
-
value: string;
|
|
349
|
-
isControl: boolean;
|
|
350
|
-
isVariation: boolean;
|
|
351
|
-
isExcluded: boolean;
|
|
352
|
-
} | undefined;
|
|
353
311
|
};
|
|
354
312
|
isSubsequentPublish: boolean;
|
|
355
313
|
isContextualUpgradeModalVisible: boolean;
|
|
@@ -1477,6 +1477,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
1477
1477
|
setVideoUrlsWithToken: videoStore.setVideoUrlsWithToken,
|
|
1478
1478
|
isCustomDomain: false,
|
|
1479
1479
|
brandPageSlug: brandPageContainerStore.brandPageSlug,
|
|
1480
|
+
activeItemIdByContentId: useUiContentSettingsStore().activeItemIdByContentId,
|
|
1480
1481
|
});
|
|
1481
1482
|
},
|
|
1482
1483
|
gettyVideoIds() {
|
|
@@ -2,7 +2,7 @@ import { BRAND_PAGE_TYPES } from '@brand-page';
|
|
|
2
2
|
import { FIELD_SLOT_MAP, raisedLayerFor, strategyRoleRefForField, } from '@shared/color-strategies/color-strategies';
|
|
3
3
|
import { isTransparentDisabled, } from '@shared/content-settings/disable-transparent.util';
|
|
4
4
|
import { setRteTextColor } from '@shared/color-strategies/rte-color';
|
|
5
|
-
import { pairedRteTextField } from '@shared/color-strategies/rte-field-pairs';
|
|
5
|
+
import { pairedRteTextField, RTE_ITEM_FIELD_PAIRS, } from '@shared/color-strategies/rte-field-pairs';
|
|
6
6
|
/**
|
|
7
7
|
* Field types a strategy can assign. `color` fields hold nothing but a colour and are
|
|
8
8
|
* REPLACED via their `valueConvertor`; `text-style` fields hold typography *and* a
|
|
@@ -62,6 +62,17 @@ const sectionLayers = (assignable, content, context) => {
|
|
|
62
62
|
surfaceFields.every(([, field]) => !isTransparentDisabled(field.disableTransparent, context?.brandPageType ?? BRAND_PAGE_TYPES.default)),
|
|
63
63
|
};
|
|
64
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* The strategy's text treatment for one text-style field: `color` set, text background
|
|
67
|
+
* cleared (matching the highlight strip in `setRteTextColor` — the toolbar writes both).
|
|
68
|
+
* The key is deleted rather than set undefined so `'backgroundColor' in style` checks
|
|
69
|
+
* downstream stay honest.
|
|
70
|
+
*/
|
|
71
|
+
const withStrategyTextStyle = (current, ref) => {
|
|
72
|
+
const nextStyle = { ...(current ?? {}), color: ref };
|
|
73
|
+
delete nextStyle.backgroundColor;
|
|
74
|
+
return nextStyle;
|
|
75
|
+
};
|
|
65
76
|
/**
|
|
66
77
|
* Build the per-field colour writes a strategy stamps onto a section. Pure — reads the
|
|
67
78
|
* section config + current content and returns a `{ fieldName: value }` partial. Each
|
|
@@ -97,16 +108,7 @@ export const buildColorStrategyValues = (config, content, strategyId, context, a
|
|
|
97
108
|
}
|
|
98
109
|
if (field.type === 'text-style') {
|
|
99
110
|
const current = contentRecord[name];
|
|
100
|
-
|
|
101
|
-
...(current ?? {}),
|
|
102
|
-
color: ref,
|
|
103
|
-
};
|
|
104
|
-
// A strategy owns the text treatment, so it clears the text background colour
|
|
105
|
-
// too — matching the highlight strip in `setRteTextColor` (the toolbar writes
|
|
106
|
-
// both). Delete the key rather than set it undefined so `'backgroundColor' in
|
|
107
|
-
// style` checks downstream stay honest.
|
|
108
|
-
delete nextStyle.backgroundColor;
|
|
109
|
-
values[name] = nextStyle;
|
|
111
|
+
values[name] = withStrategyTextStyle(current, ref);
|
|
110
112
|
// Also stamp the colour into the paired RTE document, if this field drives one.
|
|
111
113
|
// `setRteTextColor` returns undefined for a plain string or legacy HTML RTE, so
|
|
112
114
|
// that doubles as the "nothing to do" test — no separate type guard here.
|
|
@@ -133,8 +135,33 @@ export const buildColorStrategyValues = (config, content, strategyId, context, a
|
|
|
133
135
|
}
|
|
134
136
|
values[name] = field.valueConvertor.convertBack(ref);
|
|
135
137
|
});
|
|
138
|
+
// Item-level RTE fields (each FAQ question) carry their own style and document, so
|
|
139
|
+
// the section's field loop above never sees them. Same two halves, per item, written
|
|
140
|
+
// back as one new list.
|
|
141
|
+
const itemPairs = typeof contentRecord.type === 'string'
|
|
142
|
+
? (RTE_ITEM_FIELD_PAIRS[contentRecord.type] ?? [])
|
|
143
|
+
: [];
|
|
144
|
+
itemPairs.forEach((pair) => {
|
|
145
|
+
const ref = strategyRoleRefForField(strategyId, pair.styleField, content, context, layers, anchors);
|
|
146
|
+
const items = (values[pair.itemsField] ??
|
|
147
|
+
contentRecord[pair.itemsField]);
|
|
148
|
+
if (!ref || !Array.isArray(items)) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
values[pair.itemsField] = items.map((item) => {
|
|
152
|
+
const nextDoc = setRteTextColor(item[pair.textField], ref);
|
|
153
|
+
return {
|
|
154
|
+
...item,
|
|
155
|
+
[pair.styleField]: withStrategyTextStyle(item[pair.styleField], ref),
|
|
156
|
+
...(nextDoc ? { [pair.textField]: nextDoc } : {}),
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
});
|
|
136
160
|
return values;
|
|
137
161
|
};
|
|
162
|
+
const isRteDoc = (value) => typeof value === 'object' &&
|
|
163
|
+
value !== null &&
|
|
164
|
+
value.type === 'doc';
|
|
138
165
|
/**
|
|
139
166
|
* Apply a strategy to one content item. Shared by both settings surfaces — the focused
|
|
140
167
|
* section panel and the inline list item (divider) — so the write semantics can't drift.
|
|
@@ -147,12 +174,15 @@ export const applyColorStrategyToItem = (store, { id, config, content, strategyI
|
|
|
147
174
|
Object.entries(values).forEach(([name, value]) => {
|
|
148
175
|
store.updateItemValue({ id, name, value });
|
|
149
176
|
});
|
|
150
|
-
// A recoloured RTE field is emitted as a whole Tiptap document
|
|
151
|
-
//
|
|
152
|
-
// to re-seed, so signal it just
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
value
|
|
177
|
+
// A recoloured RTE field is emitted as a whole Tiptap document (at the top level,
|
|
178
|
+
// or inside a rewritten item list); the paired style-object writes are plain
|
|
179
|
+
// objects. Only the former needs the live editor to re-seed, so signal it just
|
|
180
|
+
// when a doc was among the writes.
|
|
181
|
+
const replacedRteDoc = Object.values(values).some((value) => isRteDoc(value) ||
|
|
182
|
+
(Array.isArray(value) &&
|
|
183
|
+
value.some((item) => typeof item === 'object' &&
|
|
184
|
+
item !== null &&
|
|
185
|
+
Object.values(item).some(isRteDoc))));
|
|
156
186
|
if (replacedRteDoc) {
|
|
157
187
|
markRteResync?.();
|
|
158
188
|
}
|