diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts index b6e7a4f42a..60f61c75b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts @@ -10,9 +10,11 @@ import type { import { UmbBlockRteEntriesContext, UmbBlockRteManagerContext, + type UmbBlockRteLayoutModel, type UmbBlockRteTypeModel, } from '@umbraco-cms/backoffice/block-rte'; import { UMB_PROPERTY_CONTEXT, UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block'; // eslint-disable-next-line local-rules/enforce-element-suffix-on-element-class-name export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement implements UmbPropertyEditorUiElement { @@ -35,6 +37,16 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im }, }) public set value(value: UmbPropertyEditorUiValueType | undefined) { + if (!value) { + this._value = undefined; + this._markup = ''; + this.#managerContext.setLayouts([]); + this.#managerContext.setContents([]); + this.#managerContext.setSettings([]); + this.#managerContext.setExposes([]); + return; + } + const buildUpValue: Partial = value ? { ...value } : {}; buildUpValue.markup ??= ''; buildUpValue.blocks ??= { layout: {}, contentData: [], settingsData: [], expose: [] }; @@ -69,10 +81,7 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im protected _config?: UmbPropertyEditorConfigCollection; @state() - protected _value: UmbPropertyEditorUiValueType = { - markup: '', - blocks: { layout: {}, contentData: [], settingsData: [], expose: [] }, - }; + protected _value?: UmbPropertyEditorUiValueType | undefined; /** * Separate state for markup, to avoid re-rendering/re-setting the value of the Tiptap editor when the value does not really change. @@ -127,49 +136,30 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im // Observe the value of the property and update the editor value. this.observe(this.#managerContext.layouts, (layouts) => { - this._value = { - ...this._value, - blocks: { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts } }, - }; - this._fireChangeEvent(); + const blocksValue = + this._value && layouts?.length > 0 + ? { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts } } + : undefined; + + this.#setBlocksValue(blocksValue); }); + this.observe(this.#managerContext.contents, (contents) => { - this._value = { ...this._value, blocks: { ...this._value.blocks, contentData: contents } }; - this._fireChangeEvent(); + const blocksValue = this._value ? { ...this._value.blocks, contentData: contents } : undefined; + this.#setBlocksValue(blocksValue); }); + this.observe(this.#managerContext.settings, (settings) => { - this._value = { ...this._value, blocks: { ...this._value.blocks, settingsData: settings } }; - this._fireChangeEvent(); + const blocksValue = this._value ? { ...this._value.blocks, settingsData: settings } : undefined; + this.#setBlocksValue(blocksValue); }); + this.observe(this.#managerContext.exposes, (exposes) => { - this._value = { ...this._value, blocks: { ...this._value.blocks, expose: exposes } }; - this._fireChangeEvent(); + const blocksValue = this._value ? { ...this._value.blocks, expose: exposes } : undefined; + this.#setBlocksValue(blocksValue); }); - - // The above could potentially be replaced with a single observeMultiple call, but it is not done for now to avoid potential issues with the order of the updates. - /*this.observe( - observeMultiple([ - this.#managerContext.layouts, - this.#managerContext.contents, - this.#managerContext.settings, - this.#managerContext.exposes, - ]).pipe(debounceTime(20)), - ([layouts, contents, settings, exposes]) => { - this._value = { - ...this._value, - blocks: { - layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts }, - contentData: contents, - settingsData: settings, - expose: exposes, - }, - }; - - this._fireChangeEvent(); - }, - 'motherObserver', - );*/ }); + this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (context) => { this.#managerContext.setVariantId(context.getVariantId()); }); @@ -191,6 +181,19 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im }); } + #setBlocksValue(blocksValue?: UmbBlockValueType) { + if (!blocksValue || !this._value) { + return; + } + + this._value = { + ...this._value, + blocks: blocksValue, + }; + + this._fireChangeEvent(); + } + protected _fireChangeEvent() { this.dispatchEvent(new UmbPropertyValueChangeEvent()); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts index 6033e78ead..b10349366c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts @@ -12,6 +12,13 @@ export class UmbPropertyEditorUITinyMceElement extends UmbPropertyEditorUiRteEle #onChange(event: CustomEvent & { target: UmbInputTinyMceElement }) { const value = typeof event.target.value === 'string' ? event.target.value : ''; + // If we don't get any markup clear the property editor value. + if (value === '') { + this.value = undefined; + this._fireChangeEvent(); + return; + } + // Clone the DOM, to remove the classes and attributes on the original: const div = document.createElement('div'); div.innerHTML = value; @@ -38,10 +45,12 @@ export class UmbPropertyEditorUITinyMceElement extends UmbPropertyEditorUiRteEle this._latestMarkup = markup; - this._value = { - ...this._value, - markup: markup, - }; + this._value = this._value + ? { + ...this._value, + markup: markup, + } + : undefined; this._fireChangeEvent(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts index 130d8aee6f..4743f758d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts @@ -67,6 +67,14 @@ export class UmbInputTiptapElement extends UmbFormControlMixin((resolve) => { this.observe(umbExtensionsRegistry.byType('tiptapExtension'), async (manifests) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts index d0340572ff..5cd865f02c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts @@ -12,7 +12,15 @@ const elementName = 'umb-property-editor-ui-tiptap'; @customElement(elementName) export class UmbPropertyEditorUiTiptapElement extends UmbPropertyEditorUiRteElementBase { #onChange(event: CustomEvent & { target: UmbInputTiptapElement }) { - const value = event.target.value; + const tipTapElement = event.target; + const value = tipTapElement.value; + + // If we don't get any markup clear the property editor value. + if (tipTapElement.isEmpty()) { + this.value = undefined; + this._fireChangeEvent(); + return; + } // Remove unused Blocks of Blocks Layout. Leaving only the Blocks that are present in Markup. const usedContentKeys: string[] = []; @@ -32,10 +40,12 @@ export class UmbPropertyEditorUiTiptapElement extends UmbPropertyEditorUiRteElem this._latestMarkup = value; - this._value = { - ...this._value, - markup: this._latestMarkup, - }; + this._value = this._value + ? { + ...this._value, + markup: this._latestMarkup, + } + : undefined; this._fireChangeEvent(); }