@designcrowd/library.brand-page 6.0.6-undo-2 → 6.0.6-undo-3

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 (57) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-BSFTp6yl.js → CreatedOnBrandCrowd-de-de-x7BcD7Sj.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-rPQrOY1L.js → CreatedOnBrandCrowd-en-us-CG-ThD_q.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-awd8-QFa.js → CreatedOnBrandCrowd-es-es-aab4_Re2.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CwJ4J7Ow.js → CreatedOnBrandCrowd-fr-ca-Drl8X5uh.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CwJ4J7Ow.js → CreatedOnBrandCrowd-fr-fr-Drl8X5uh.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-BXYfTLlD.js → CreatedOnBrandCrowd-pt-br-8Ib7T70i.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-BXYfTLlD.js → CreatedOnBrandCrowd-pt-pt-8Ib7T70i.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-kX6u1lNK.js → CreatedOnDcom-de-de-FJtydzc5.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-Bkq5sgFs.js → CreatedOnDcom-en-us-BMiXru6P.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-zCAC9ujj.js → CreatedOnDcom-es-es-B8Srdnku.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-BYz6Wzg5.js → CreatedOnDcom-fr-ca-tcXGiBNt.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-CN-wAaSH.js → CreatedOnDcom-fr-fr-nE1cuUEU.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-BrK4Ngg-.js → CreatedOnDcom-pt-br-DxCCXCg8.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-AfI_g7xJ.js → CreatedOnDcom-pt-pt-Csabip9G.js} +1 -1
  15. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -1
  16. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +2 -2
  17. package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +1 -1
  18. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +1 -1
  19. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +17 -12
  20. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +1 -1
  21. package/lib/src/index.mjs +1 -1
  22. package/lib/src/{lib-BYFWAvIq.js → lib-C_UlYMJy.js} +15640 -15612
  23. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +5 -0
  24. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.js +29 -0
  25. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +2 -2
  26. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -1
  27. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +1 -1
  28. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +1 -1
  29. package/lib/src/shared/content-settings/components/email-field/EmailField.mixin.d.ts +5 -0
  30. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +1 -1
  31. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +0 -67
  32. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.js +4 -6
  33. package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +5 -0
  34. package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +5 -0
  35. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +2 -0
  36. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +19 -0
  37. package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +5 -0
  38. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +5 -0
  39. package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +5 -0
  40. package/lib/src/shared/content-settings/models.d.ts +11 -0
  41. package/lib/src/shared/content-settings/store/content-settings-store.d.ts +1 -1
  42. package/lib/src/shared/content-settings/store/content-settings-store.js +15 -1
  43. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
  44. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +1 -1
  45. package/package.json +1 -1
  46. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +18 -14
  47. package/src/shared/content-settings/components/GenericTextInput.mixin.test.ts +119 -0
  48. package/src/shared/content-settings/components/GenericTextInput.mixin.ts +34 -0
  49. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +10 -5
  50. package/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.ts +4 -7
  51. package/src/shared/content-settings/components/text-field/TextField.vue +2 -1
  52. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.test.ts +149 -0
  53. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +26 -0
  54. package/src/shared/content-settings/components/textarea-field/TextareaField.vue +2 -1
  55. package/src/shared/content-settings/models.ts +11 -0
  56. package/src/shared/content-settings/store/content-settings-store.test.ts +110 -0
  57. package/src/shared/content-settings/store/content-settings-store.ts +17 -0
@@ -84,6 +84,8 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
84
84
  isDirty: boolean;
85
85
  emitChangeDebounce: DebounceHandle | undefined;
86
86
  lengthError: boolean;
87
+ burstIsHydration: boolean | undefined;
88
+ pendingWriteIsHydration: boolean;
87
89
  }, {
88
90
  errorMessage(): string | undefined;
89
91
  isErrorVisible(): boolean;
@@ -96,6 +98,9 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
96
98
  }, {
97
99
  onFocus(): void;
98
100
  onBlur(): void;
101
+ onRteModelValue(newVal: string, meta?: {
102
+ isHydration?: boolean;
103
+ }): void;
99
104
  emitChange(): void;
100
105
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "on-toggle-state-change")[], "update:modelValue" | "on-toggle-state-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
101
106
  attrs: {
@@ -99,6 +99,13 @@ export default defineComponent({
99
99
  isDirty: false,
100
100
  emitChangeDebounce: undefined,
101
101
  lengthError: false,
102
+ // Whether every write in the current debounce burst was an RTE
103
+ // hydration write-back (see UpdateItemValuePayload.isHydrationWrite).
104
+ // undefined = no burst pending; any user write downgrades it to false.
105
+ burstIsHydration: undefined,
106
+ // One-shot channel from onRteModelValue into the `text` setter for
107
+ // the write currently being applied.
108
+ pendingWriteIsHydration: false,
102
109
  };
103
110
  },
104
111
  computed: {
@@ -128,6 +135,13 @@ export default defineComponent({
128
135
  return unescapeContentText(this.value);
129
136
  },
130
137
  set(newVal) {
138
+ // A burst is hydration only if EVERY write in it is hydration —
139
+ // one real keystroke downgrades the whole burst to a user edit
140
+ // (the canonicalisation then rides inside that legitimate entry).
141
+ const writeIsHydration = this.pendingWriteIsHydration;
142
+ this.pendingWriteIsHydration = false;
143
+ this.burstIsHydration =
144
+ this.burstIsHydration !== false && writeIsHydration;
131
145
  if (newVal === false) {
132
146
  this._value = false;
133
147
  }
@@ -162,11 +176,15 @@ export default defineComponent({
162
176
  this._oldValue = this._value || '';
163
177
  this._value = false;
164
178
  }
179
+ // Toggling is a user action — downgrade any pending hydration burst
180
+ // so this emit commits as a normal entry.
181
+ this.burstIsHydration = false;
165
182
  this.emitChange();
166
183
  },
167
184
  showRichTextEditor(newVal) {
168
185
  if (!newVal && this._value && typeof this._value === 'string') {
169
186
  this._value = encodeContentText(this._value);
187
+ this.burstIsHydration = false;
170
188
  this.emitChange();
171
189
  }
172
190
  },
@@ -186,11 +204,22 @@ export default defineComponent({
186
204
  onBlur() {
187
205
  this.isDirty = false;
188
206
  },
207
+ // RTE branch handler: receives the hydration meta the RichTextEditor
208
+ // attaches to its update:modelValue emits (a plain v-model binding
209
+ // would drop the second argument), records it for the `text` setter,
210
+ // then applies the write.
211
+ onRteModelValue(newVal, meta) {
212
+ this.pendingWriteIsHydration = meta?.isHydration === true;
213
+ this.text = newVal;
214
+ },
189
215
  emitChange() {
216
+ const isHydrationWrite = this.burstIsHydration === true;
217
+ this.burstIsHydration = undefined;
190
218
  this.$emit('update:modelValue', {
191
219
  id: this.id,
192
220
  name: this.name,
193
221
  value: this._value,
222
+ ...(isHydrationWrite ? { isHydrationWrite: true } : {}),
194
223
  });
195
224
  },
196
225
  },
@@ -549,7 +549,7 @@ declare const _default: import("vue").DefineComponent<{}, {
549
549
  pushMode(item: import("../../store").ContentSettingsModeStackItem): void;
550
550
  resetMode(): void;
551
551
  updateItemValue(payload: import("../../models").UpdateItemValuePayload<unknown>): void;
552
- updateMultipleItemValues({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
552
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
553
553
  updateTextStyleType({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
554
554
  updateTextStyles({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
555
555
  getTextStyles({ id, name }: {
@@ -924,7 +924,7 @@ declare const _default: import("vue").DefineComponent<{}, {
924
924
  reset: () => void;
925
925
  getCurrentSizeBytes: () => number;
926
926
  getCurrentEntryCount: () => number;
927
- }, "reset" | "undo" | "redo" | "captureBaseline" | "capture" | "captureTemplateSwitch" | "captureAiChangeset" | "mergeNextMutation" | "getCurrentSizeBytes" | "getCurrentEntryCount">>;
927
+ }, "reset" | "captureBaseline" | "capture" | "captureTemplateSwitch" | "captureAiChangeset" | "mergeNextMutation" | "undo" | "redo" | "getCurrentSizeBytes" | "getCurrentEntryCount">>;
928
928
  externalEditor: import("@tiptap/vue-3").Editor;
929
929
  }, {
930
930
  categoryTabs: CategoryTab[];
@@ -399,7 +399,7 @@ declare const _default: import("vue").DefineComponent<{}, {
399
399
  pushMode(item: import("../../store").ContentSettingsModeStackItem): void;
400
400
  resetMode(): void;
401
401
  updateItemValue(payload: import("../../models").UpdateItemValuePayload<unknown>): void;
402
- updateMultipleItemValues({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
402
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
403
403
  updateTextStyleType({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
404
404
  updateTextStyles({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
405
405
  getTextStyles({ id, name }: {
@@ -385,7 +385,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
385
385
  pushMode(item: import("../../store").ContentSettingsModeStackItem): void;
386
386
  resetMode(): void;
387
387
  updateItemValue(payload: UpdateItemValuePayload<unknown>): void;
388
- updateMultipleItemValues({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
388
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
389
389
  updateTextStyleType({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
390
390
  updateTextStyles({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
391
391
  getTextStyles({ id, name }: {
@@ -427,7 +427,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
427
427
  pushMode(item: import("../../store").ContentSettingsModeStackItem): void;
428
428
  resetMode(): void;
429
429
  updateItemValue(payload: UpdateItemValuePayload<unknown>): void;
430
- updateMultipleItemValues({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
430
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
431
431
  updateTextStyleType({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
432
432
  updateTextStyles({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
433
433
  getTextStyles({ id, name }: {
@@ -81,6 +81,8 @@ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import
81
81
  isDirty: boolean;
82
82
  emitChangeDebounce: import("lodash.debounce").DebounceHandle | undefined;
83
83
  lengthError: boolean;
84
+ burstIsHydration: boolean | undefined;
85
+ pendingWriteIsHydration: boolean;
84
86
  }, {
85
87
  errorMessage(): string | undefined;
86
88
  isErrorVisible(): boolean;
@@ -93,6 +95,9 @@ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import
93
95
  }, {
94
96
  onFocus(): void;
95
97
  onBlur(): void;
98
+ onRteModelValue(newVal: string, meta?: {
99
+ isHydration?: boolean;
100
+ }): void;
96
101
  emitChange(): void;
97
102
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "on-toggle-state-change")[], "update:modelValue" | "on-toggle-state-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
98
103
  attrs: {
@@ -378,7 +378,7 @@ declare const _default: import("vue").DefineComponent<{}, {
378
378
  pushMode(item: import("../../store").ContentSettingsModeStackItem): void;
379
379
  resetMode(): void;
380
380
  updateItemValue(payload: UpdateItemValuePayload<unknown>): void;
381
- updateMultipleItemValues({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
381
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
382
382
  updateTextStyleType({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
383
383
  updateTextStyles({ id, name, value, }: import("../../models").UpdateMultipleItemValuesPayload<any>): void;
384
384
  getTextStyles({ id, name }: {
@@ -483,73 +483,6 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
483
483
  collapseAllSections(): void;
484
484
  setPreviousSelectedDisplayStyle(viewport: string, displayStyle: string): void;
485
485
  }>;
486
- historyStore: import("pinia").Store<"history", Pick<{
487
- entries: import("vue").ShallowRef<import("@brand-page-maker/stores/history/history-store").HistoryEntry[], import("@brand-page-maker/stores/history/history-store").HistoryEntry[]>;
488
- currentIndex: import("vue").Ref<number, number>;
489
- isApplyingSnapshot: import("vue").Ref<boolean, boolean>;
490
- snapshotAppliedToken: import("vue").Ref<number, number>;
491
- baselineCaptured: import("vue").Ref<boolean, boolean>;
492
- canUndo: import("vue").ComputedRef<boolean>;
493
- canRedo: import("vue").ComputedRef<boolean>;
494
- captureBaseline: () => void;
495
- capture: (args: {
496
- source: import("@brand-page-maker/stores/history/history-store").HistoryEntry["source"];
497
- actor: import("@brand-page-maker/stores/history/history-store").HistoryEntry["actor"];
498
- label?: string;
499
- }) => "committed" | "oversized" | "noop" | "skipped";
500
- captureTemplateSwitch: (label?: string) => "committed" | "oversized" | "noop" | "skipped";
501
- captureAiChangeset: (label?: string) => "committed" | "oversized" | "noop" | "skipped";
502
- mergeNextMutation: () => void;
503
- undo: () => Promise<void>;
504
- redo: () => Promise<void>;
505
- reset: () => void;
506
- getCurrentSizeBytes: () => number;
507
- getCurrentEntryCount: () => number;
508
- }, "entries" | "currentIndex" | "isApplyingSnapshot" | "snapshotAppliedToken" | "baselineCaptured">, Pick<{
509
- entries: import("vue").ShallowRef<import("@brand-page-maker/stores/history/history-store").HistoryEntry[], import("@brand-page-maker/stores/history/history-store").HistoryEntry[]>;
510
- currentIndex: import("vue").Ref<number, number>;
511
- isApplyingSnapshot: import("vue").Ref<boolean, boolean>;
512
- snapshotAppliedToken: import("vue").Ref<number, number>;
513
- baselineCaptured: import("vue").Ref<boolean, boolean>;
514
- canUndo: import("vue").ComputedRef<boolean>;
515
- canRedo: import("vue").ComputedRef<boolean>;
516
- captureBaseline: () => void;
517
- capture: (args: {
518
- source: import("@brand-page-maker/stores/history/history-store").HistoryEntry["source"];
519
- actor: import("@brand-page-maker/stores/history/history-store").HistoryEntry["actor"];
520
- label?: string;
521
- }) => "committed" | "oversized" | "noop" | "skipped";
522
- captureTemplateSwitch: (label?: string) => "committed" | "oversized" | "noop" | "skipped";
523
- captureAiChangeset: (label?: string) => "committed" | "oversized" | "noop" | "skipped";
524
- mergeNextMutation: () => void;
525
- undo: () => Promise<void>;
526
- redo: () => Promise<void>;
527
- reset: () => void;
528
- getCurrentSizeBytes: () => number;
529
- getCurrentEntryCount: () => number;
530
- }, "canUndo" | "canRedo">, Pick<{
531
- entries: import("vue").ShallowRef<import("@brand-page-maker/stores/history/history-store").HistoryEntry[], import("@brand-page-maker/stores/history/history-store").HistoryEntry[]>;
532
- currentIndex: import("vue").Ref<number, number>;
533
- isApplyingSnapshot: import("vue").Ref<boolean, boolean>;
534
- snapshotAppliedToken: import("vue").Ref<number, number>;
535
- baselineCaptured: import("vue").Ref<boolean, boolean>;
536
- canUndo: import("vue").ComputedRef<boolean>;
537
- canRedo: import("vue").ComputedRef<boolean>;
538
- captureBaseline: () => void;
539
- capture: (args: {
540
- source: import("@brand-page-maker/stores/history/history-store").HistoryEntry["source"];
541
- actor: import("@brand-page-maker/stores/history/history-store").HistoryEntry["actor"];
542
- label?: string;
543
- }) => "committed" | "oversized" | "noop" | "skipped";
544
- captureTemplateSwitch: (label?: string) => "committed" | "oversized" | "noop" | "skipped";
545
- captureAiChangeset: (label?: string) => "committed" | "oversized" | "noop" | "skipped";
546
- mergeNextMutation: () => void;
547
- undo: () => Promise<void>;
548
- redo: () => Promise<void>;
549
- reset: () => void;
550
- getCurrentSizeBytes: () => number;
551
- getCurrentEntryCount: () => number;
552
- }, "reset" | "undo" | "redo" | "captureBaseline" | "capture" | "captureTemplateSwitch" | "captureAiChangeset" | "mergeNextMutation" | "getCurrentSizeBytes" | "getCurrentEntryCount">>;
553
486
  }, {
554
487
  selectedPaymentConfig: BrandPagePaymentConfig | undefined;
555
488
  isCurrencyUpdating: boolean;
@@ -4,7 +4,6 @@ import { useShopConfigStore } from '@shared/ecommerce-settings/store/shop-settin
4
4
  import { paymentConfigTr } from '@src/composables/useTranslate';
5
5
  import brandPageClient from '../../../../clients/brand-page-client';
6
6
  import { useUiPageSettingsStore } from '@shared/page-settings/store';
7
- import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
8
7
  export default defineComponent({
9
8
  props: {
10
9
  id: {
@@ -30,7 +29,6 @@ export default defineComponent({
30
29
  const uiPageSettingsStore = useUiPageSettingsStore();
31
30
  const eventManagerStore = useEventManagerStore();
32
31
  const shopConfigStore = useShopConfigStore();
33
- const historyStore = useHistoryStore();
34
32
  return {
35
33
  brandPageToken: computed(() => brandPageContainerStore.brandPageToken),
36
34
  isPaymentConfigSetupVisible: computed(() => !brandPageContainerStore.isPrePurchase),
@@ -38,7 +36,6 @@ export default defineComponent({
38
36
  eventManagerStore,
39
37
  shopConfigStore,
40
38
  uiPageSettingsStore,
41
- historyStore,
42
39
  };
43
40
  },
44
41
  emits: ['update:modelValue'],
@@ -97,14 +94,15 @@ export default defineComponent({
97
94
  ...this.value,
98
95
  paymentConfig: this.shopConfigStore.paymentConfig,
99
96
  };
97
+ // Lazy paymentConfig hydration — a hydration write, not a user edit.
98
+ // The flag makes the content-settings store fold it into the current
99
+ // undo head at write time (see UpdateItemValuePayload.isHydrationWrite).
100
100
  const payload = {
101
101
  id: this.id,
102
102
  name: this.name,
103
103
  value,
104
+ isHydrationWrite: true,
104
105
  };
105
- // Lazy paymentConfig hydration — fold into current head instead
106
- // of pushing a phantom entry.
107
- this.historyStore.mergeNextMutation();
108
106
  this.$emit('update:modelValue', payload);
109
107
  }
110
108
  },
@@ -81,6 +81,8 @@ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import
81
81
  isDirty: boolean;
82
82
  emitChangeDebounce: import("lodash.debounce").DebounceHandle | undefined;
83
83
  lengthError: boolean;
84
+ burstIsHydration: boolean | undefined;
85
+ pendingWriteIsHydration: boolean;
84
86
  }, {
85
87
  errorMessage(): string | undefined;
86
88
  isErrorVisible(): boolean;
@@ -93,6 +95,9 @@ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import
93
95
  }, {
94
96
  onFocus(): void;
95
97
  onBlur(): void;
98
+ onRteModelValue(newVal: string, meta?: {
99
+ isHydration?: boolean;
100
+ }): void;
96
101
  emitChange(): void;
97
102
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "on-toggle-state-change")[], "update:modelValue" | "on-toggle-state-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
98
103
  attrs: {
@@ -81,6 +81,8 @@ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import
81
81
  isDirty: boolean;
82
82
  emitChangeDebounce: import("lodash.debounce").DebounceHandle | undefined;
83
83
  lengthError: boolean;
84
+ burstIsHydration: boolean | undefined;
85
+ pendingWriteIsHydration: boolean;
84
86
  }, {
85
87
  errorMessage(): string | undefined;
86
88
  isErrorVisible(): boolean;
@@ -93,6 +95,9 @@ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import
93
95
  }, {
94
96
  onFocus(): void;
95
97
  onBlur(): void;
98
+ onRteModelValue(newVal: string, meta?: {
99
+ isHydration?: boolean;
100
+ }): void;
96
101
  emitChange(): void;
97
102
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "on-toggle-state-change")[], "update:modelValue" | "on-toggle-state-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
98
103
  attrs: {
@@ -53,6 +53,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
53
53
  textEmptyErrorMessage: any;
54
54
  textMaxLengthErrorMessage: any;
55
55
  isInternalWatchEnabled: boolean;
56
+ burstIsHydration: boolean | undefined;
56
57
  }, {}, {
57
58
  onDelete(index: number): void;
58
59
  onAddNewItem(): void;
@@ -64,6 +65,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
64
65
  id: string;
65
66
  name: string;
66
67
  value: string;
68
+ isHydrationWrite?: boolean;
67
69
  }, index: number): void;
68
70
  setTextStyleOption(payload: {
69
71
  id: string;
@@ -66,6 +66,11 @@ export default defineComponent({
66
66
  textEmptyErrorMessage: TEXT_EMPTY(),
67
67
  textMaxLengthErrorMessage: MAX_LENGTH_ERROR_MESSAGE(),
68
68
  isInternalWatchEnabled: true,
69
+ // Second burst layer on top of GenericTextInput's (this field re-wraps
70
+ // per-item TextareaField payloads into one textItems array payload
71
+ // behind its own debounce). Hydration only if EVERY write in the burst
72
+ // was hydration; any user action downgrades it. undefined = no burst.
73
+ burstIsHydration: undefined,
69
74
  }),
70
75
  async created() {
71
76
  this.options = cloneDeep(this.value);
@@ -77,6 +82,8 @@ export default defineComponent({
77
82
  methods: {
78
83
  onDelete(index) {
79
84
  this.options = this.options.filter((_o, i) => i !== index);
85
+ // Deleting is a user action — downgrade any pending hydration burst.
86
+ this.burstIsHydration = false;
80
87
  if (this.changeDebounce) {
81
88
  this.changeDebounce();
82
89
  }
@@ -86,6 +93,7 @@ export default defineComponent({
86
93
  this.addOption();
87
94
  },
88
95
  addOption() {
96
+ this.burstIsHydration = false;
89
97
  this.options.push({
90
98
  text: '',
91
99
  textStyle: {
@@ -107,14 +115,19 @@ export default defineComponent({
107
115
  return decodeHtmlEntities(text);
108
116
  },
109
117
  emitChange() {
118
+ const isHydrationWrite = this.burstIsHydration === true;
119
+ this.burstIsHydration = undefined;
110
120
  const payload = {
111
121
  id: this.id,
112
122
  name: this.name,
113
123
  value: this.options,
124
+ ...(isHydrationWrite ? { isHydrationWrite: true } : {}),
114
125
  };
115
126
  this.$emit('update:model-value', payload);
116
127
  },
117
128
  onItemsChange(items) {
129
+ // Reordering is a user action — downgrade any pending hydration burst.
130
+ this.burstIsHydration = false;
118
131
  const payload = {
119
132
  id: this.id,
120
133
  name: this.name,
@@ -128,11 +141,17 @@ export default defineComponent({
128
141
  this.$emit('update:model-value', payload);
129
142
  },
130
143
  onTextAreaTextChange(payload, index) {
144
+ // Carry the hydration flag from the per-item TextareaField burst into
145
+ // this field's own burst (AND rule — one user write downgrades it).
146
+ this.burstIsHydration =
147
+ this.burstIsHydration !== false && payload.isHydrationWrite === true;
131
148
  this.options[index].text = payload.value;
132
149
  this.isModified[index] = true;
133
150
  },
134
151
  setTextStyleOption(payload, index) {
135
152
  this.options[index].textStyle = payload.value;
153
+ // Style edits are user actions — downgrade any pending hydration burst.
154
+ this.burstIsHydration = false;
136
155
  this.emitChange();
137
156
  },
138
157
  onBlurOverride(value, index) {
@@ -95,6 +95,8 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
95
95
  isDirty: boolean;
96
96
  emitChangeDebounce: import("lodash.debounce").DebounceHandle | undefined;
97
97
  lengthError: boolean;
98
+ burstIsHydration: boolean | undefined;
99
+ pendingWriteIsHydration: boolean;
98
100
  }, {
99
101
  errorMessage(): string | undefined;
100
102
  isErrorVisible(): boolean;
@@ -107,6 +109,9 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
107
109
  }, {
108
110
  onFocus(): void;
109
111
  onBlur(): void;
112
+ onRteModelValue(newVal: string, meta?: {
113
+ isHydration?: boolean;
114
+ }): void;
110
115
  emitChange(): void;
111
116
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "on-toggle-state-change")[], "update:modelValue" | "on-toggle-state-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
112
117
  attrs: {
@@ -88,6 +88,8 @@ declare const _default: import("vue").DefineComponent<{}, {}, Record<string, any
88
88
  isDirty: boolean;
89
89
  emitChangeDebounce: import("lodash.debounce").DebounceHandle | undefined;
90
90
  lengthError: boolean;
91
+ burstIsHydration: boolean | undefined;
92
+ pendingWriteIsHydration: boolean;
91
93
  }, {
92
94
  errorMessage(): string | undefined;
93
95
  isErrorVisible(): boolean;
@@ -100,6 +102,9 @@ declare const _default: import("vue").DefineComponent<{}, {}, Record<string, any
100
102
  }, {
101
103
  onFocus(): void;
102
104
  onBlur(): void;
105
+ onRteModelValue(newVal: string, meta?: {
106
+ isHydration?: boolean;
107
+ }): void;
103
108
  emitChange(): void;
104
109
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "on-toggle-state-change")[], "update:modelValue" | "on-toggle-state-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
105
110
  attrs: {
@@ -84,6 +84,8 @@ declare const _default: import("vue").DefineComponent<{}, {}, Record<string, any
84
84
  isDirty: boolean;
85
85
  emitChangeDebounce: import("lodash.debounce").DebounceHandle | undefined;
86
86
  lengthError: boolean;
87
+ burstIsHydration: boolean | undefined;
88
+ pendingWriteIsHydration: boolean;
87
89
  }, {
88
90
  errorMessage(): string | undefined;
89
91
  isErrorVisible(): boolean;
@@ -96,6 +98,9 @@ declare const _default: import("vue").DefineComponent<{}, {}, Record<string, any
96
98
  }, {
97
99
  onFocus(): void;
98
100
  onBlur(): void;
101
+ onRteModelValue(newVal: string, meta?: {
102
+ isHydration?: boolean;
103
+ }): void;
99
104
  emitChange(): void;
100
105
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "on-toggle-state-change")[], "update:modelValue" | "on-toggle-state-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
101
106
  attrs: {
@@ -88,12 +88,23 @@ export interface UpdateItemValuePayload<T> {
88
88
  name: string;
89
89
  value: T;
90
90
  multipleValues?: boolean;
91
+ /**
92
+ * Marks this write as a hydration write-back (e.g. the RTE rewriting the
93
+ * model into canonical HTML on mount) rather than a user edit. The
94
+ * content-settings store arms the undo history's merge flag synchronously
95
+ * before applying a flagged write, so it folds into the current history
96
+ * head instead of pushing a phantom entry (BP-5810). The flag travels
97
+ * with the value so it survives the debounced field → store hops.
98
+ */
99
+ isHydrationWrite?: boolean;
91
100
  }
92
101
  export interface UpdateMultipleItemValuesPayload<T extends object> {
93
102
  id: string;
94
103
  name: string;
95
104
  value: T;
96
105
  index?: number;
106
+ /** See UpdateItemValuePayload.isHydrationWrite. */
107
+ isHydrationWrite?: boolean;
97
108
  }
98
109
  export interface ValidateItemPayload {
99
110
  id: string;
@@ -393,7 +393,7 @@ export declare const useUiContentSettingsStore: import("pinia").StoreDefinition<
393
393
  pushMode(item: ContentSettingsModeStackItem): void;
394
394
  resetMode(): void;
395
395
  updateItemValue(payload: UpdateItemValuePayload<unknown>): void;
396
- updateMultipleItemValues({ id, name, value, }: UpdateMultipleItemValuesPayload<any>): void;
396
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: UpdateMultipleItemValuesPayload<any>): void;
397
397
  updateTextStyleType({ id, name, value, }: UpdateMultipleItemValuesPayload<any>): void;
398
398
  updateTextStyles({ id, name, value, }: UpdateMultipleItemValuesPayload<any>): void;
399
399
  getTextStyles({ id, name }: {
@@ -4,6 +4,7 @@ import { RESERVED_FIELD_NAMES } from '../constants';
4
4
  import { UI_EVENT_SOURCES } from '../../models';
5
5
  import { CONTENT_SETTINGS_DISPLAY_MODES, ITEM_CATEGORIES, ITEM_CATEGORY_NAMES, } from '@brand-page-maker/models';
6
6
  import { useUiStore, useBrandPageMakerUserStore, useBrandPageMakerStore, useVideoStore, } from '@brand-page-maker/stores';
7
+ import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
7
8
  import { useUiSideBarStore } from '../../side-bar/store';
8
9
  import { createDefaultContentItemGroupState, createDefaultContentItemState, } from '../../navigation-style-settings/store';
9
10
  import { adminValidatorsDict, dummyValidator, validatorDict, } from '@brand-page-maker/validators';
@@ -210,6 +211,15 @@ export const useUiContentSettingsStore = defineStore('uiContentSettings', {
210
211
  if (!item) {
211
212
  return;
212
213
  }
214
+ // Hydration write-backs (RTE canonical HTML on mount, lazy config
215
+ // hydration, stale-id clears) fold into the current undo head instead
216
+ // of pushing an entry. Arming here — same tick as the write — is what
217
+ // makes the merge reliable: the flag travelled with the payload
218
+ // through the debounced field chain, so emit-time arming would lapse
219
+ // before the write lands (BP-5810).
220
+ if (payload.isHydrationWrite) {
221
+ useHistoryStore().mergeNextMutation();
222
+ }
213
223
  item.settings.content[payload.name] = payload.value;
214
224
  this.validateItem({
215
225
  id: payload.id,
@@ -217,11 +227,15 @@ export const useUiContentSettingsStore = defineStore('uiContentSettings', {
217
227
  });
218
228
  this.onContentChanged();
219
229
  },
220
- updateMultipleItemValues({ id, name, value, }) {
230
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }) {
221
231
  const item = this.items.find((i) => i.id === id);
222
232
  if (!item) {
223
233
  return;
224
234
  }
235
+ // Same hydration-write contract as updateItemValue.
236
+ if (isHydrationWrite) {
237
+ useHistoryStore().mergeNextMutation();
238
+ }
225
239
  item.settings.content = vueDeepMerge(item.settings.content, value);
226
240
  this.validateItem({ id, name });
227
241
  this.onContentChanged();
@@ -4411,7 +4411,7 @@ declare const _default: import("vue").DefineComponent<{}, {
4411
4411
  pushMode(item: import("../../../content-settings/store").ContentSettingsModeStackItem): void;
4412
4412
  resetMode(): void;
4413
4413
  updateItemValue(payload: import("../../../content-settings/models").UpdateItemValuePayload<unknown>): void;
4414
- updateMultipleItemValues({ id, name, value, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
4414
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
4415
4415
  updateTextStyleType({ id, name, value, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
4416
4416
  updateTextStyles({ id, name, value, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
4417
4417
  getTextStyles({ id, name }: {
@@ -3787,7 +3787,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
3787
3787
  pushMode(item: import("../../../content-settings/store").ContentSettingsModeStackItem): void;
3788
3788
  resetMode(): void;
3789
3789
  updateItemValue(payload: UpdateItemValuePayload<unknown>): void;
3790
- updateMultipleItemValues({ id, name, value, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
3790
+ updateMultipleItemValues({ id, name, value, isHydrationWrite, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
3791
3791
  updateTextStyleType({ id, name, value, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
3792
3792
  updateTextStyles({ id, name, value, }: import("../../../content-settings/models").UpdateMultipleItemValuesPayload<any>): void;
3793
3793
  getTextStyles({ id, name }: {
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.6-undo-2",
4
+ "version": "6.0.6-undo-3",
5
5
  "author": "Design.com Eng",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -211,10 +211,6 @@ export const useRichTextEditor = (
211
211
  ): UseRichTextEditorReturn => {
212
212
  const historyStore = useHistoryStore();
213
213
 
214
- // TipTap rehydrates and writes back canonical HTML on mount — fold
215
- // that into the current head instead of pushing a phantom entry.
216
- historyStore.mergeNextMutation();
217
-
218
214
  const editor = new Editor({
219
215
  content: model.value ?? '',
220
216
  editable: !props.readOnly,
@@ -492,6 +488,14 @@ export const useRichTextEditor = (
492
488
  );
493
489
 
494
490
  editor.on('transaction', ({ transaction }) => {
491
+ // Style detection only makes sense for user styling — an unfocused
492
+ // editor's transactions are mount rehydration / programmatic setContent
493
+ // churn, and clearing textStyleType from those would push a phantom
494
+ // style write into the model (BP-5810 family).
495
+ if (!editor.isFocused) {
496
+ return;
497
+ }
498
+
495
499
  if (isStyleChanged(transaction) && props.styles.textStyleType) {
496
500
  onSelectTextStyleType({
497
501
  label: 'None',
@@ -505,22 +509,22 @@ export const useRichTextEditor = (
505
509
 
506
510
  // An update fired while the editor is unfocused is TipTap rewriting the
507
511
  // model back into its canonical HTML during mount rehydration or a
508
- // programmatic setContent — not a user edit. Fold it into the current
509
- // head so merely selecting a section doesn't push a phantom undo entry
510
- // (BP-5810). The construction-time arm above lapses before this async
511
- // write-back fires, so re-arm here. Genuine edits happen while focused and
512
- // still push a new entry.
512
+ // programmatic setContent — not a user edit. Tag the emit so the write
513
+ // folds into the current undo head instead of pushing a phantom entry
514
+ // (BP-5810). The flag travels WITH the value through the debounced
515
+ // field → store chain and arms the history merge at the moment of the
516
+ // store write — arming here at emit time would lapse before the
517
+ // debounce fires. Genuine edits happen while focused and commit
518
+ // normally.
513
519
  //
514
520
  // Known limitation: a programmatic toolbar command run on an editor the
515
521
  // user hasn't focused yet would also merge (losing that undo step). Today
516
522
  // the RTE only mounts inside an already-open settings drawer and the user
517
523
  // focuses it before formatting, so this doesn't occur — revisit if a
518
524
  // consumer ever drives toolbar actions on an unfocused editor.
519
- if (!editor.isFocused && !historyStore.isApplyingSnapshot) {
520
- historyStore.mergeNextMutation();
521
- }
522
-
523
- emit('update:modelValue', sanitizedData.sanitizedHtml);
525
+ emit('update:modelValue', sanitizedData.sanitizedHtml, {
526
+ isHydration: !editor.isFocused,
527
+ });
524
528
  });
525
529
 
526
530
  editor.on('selectionUpdate', () => {