diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 04b68f446c..ce29afebd4 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -59,7 +59,7 @@ }, "devDependencies": { "@babel/core": "^7.24.9", - "@eslint/js": "^9.7.0", + "@eslint/js": "^9.9.1", "@hey-api/openapi-ts": "^0.48.3", "@mdx-js/react": "^3.0.1", "@open-wc/testing": "^4.0.0", @@ -91,7 +91,7 @@ "eslint-plugin-lit": "^1.14.0", "eslint-plugin-local-rules": "^3.0.2", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-wc": "^2.1.0", + "eslint-plugin-wc": "^2.1.1", "glob": "^11.0.0", "globals": "^15.8.0", "lucide-static": "^0.424.0", @@ -2616,9 +2616,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", - "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", + "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -12770,9 +12770,9 @@ } }, "node_modules/eslint-plugin-wc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-2.1.0.tgz", - "integrity": "sha512-s/BGOtmpgQ2yifR6EC1OM9t0DwYLgg4ZAL07Kw4eXvBb5TYaPafI+65tswvnZvhH8FqcjERLbBZPPvYsvinkfg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-2.1.1.tgz", + "integrity": "sha512-GfJo05ZgWfwAFbW6Gkf+9CMOIU6fmbd3b4nm+PKESHgUdUTmi7vawlELCrzOhdiQjXUPZxDfFIVxYt9D/v/GdQ==", "dev": true, "dependencies": { "is-valid-element-name": "^1.0.0", @@ -12810,6 +12810,15 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", + "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 6c89efd83a..6566a38041 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -231,7 +231,7 @@ }, "devDependencies": { "@babel/core": "^7.24.9", - "@eslint/js": "^9.7.0", + "@eslint/js": "^9.9.1", "@hey-api/openapi-ts": "^0.48.3", "@mdx-js/react": "^3.0.1", "@open-wc/testing": "^4.0.0", @@ -263,7 +263,7 @@ "eslint-plugin-lit": "^1.14.0", "eslint-plugin-local-rules": "^3.0.2", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-wc": "^2.1.0", + "eslint-plugin-wc": "^2.1.1", "glob": "^11.0.0", "globals": "^15.8.0", "lucide-static": "^0.424.0", diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts index ae0236a47d..18575ba822 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts @@ -197,15 +197,17 @@ export class UmbInputDocumentElement extends UmbFormControlMixin= this.max) return; - return html` - = this.max) return nothing; + if (this.readonly && this.selection.length > 0) { + return nothing; + } else { + return html` - `; + ?disabled=${this.readonly}>`; + } } #renderItems() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts index c8135d7053..5d2b5bb964 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts @@ -1,4 +1,13 @@ -import { css, customElement, html, property, query, state, unsafeHTML } from '@umbraco-cms/backoffice/external/lit'; +import { + css, + customElement, + html, + nothing, + property, + query, + state, + unsafeHTML, +} from '@umbraco-cms/backoffice/external/lit'; import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; import { marked } from '@umbraco-cms/backoffice/external/marked'; import { monaco } from '@umbraco-cms/backoffice/external/monaco-editor'; @@ -34,6 +43,22 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, @property() overlaySize?: UUIModalSidebarSize; + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + public get readonly() { + return this.#readonly; + } + public set readonly(value) { + this.#readonly = value; + this.#editor?.monacoEditor?.updateOptions({ readOnly: this.#readonly }); + } + #readonly = false; + #editor?: UmbCodeEditorController; @query('umb-code-editor') @@ -50,6 +75,9 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, try { this.#editor = this._codeEditor?.editor; + // Set read only mode + this.#editor?.monacoEditor?.updateOptions({ readOnly: this.#readonly }); + // TODO: make all action into extensions this.observe(umbExtensionsRegistry.byType('monacoMarkdownEditorAction'), (manifests) => { manifests.forEach(async (manifest) => { @@ -416,6 +444,7 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, } #renderToolbar() { + if (this.readonly) return nothing; return html`
diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/manifests.ts index ee9dc738f5..bde0db6793 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/manifests.ts @@ -11,6 +11,7 @@ const manifest: ManifestPropertyEditorUi = { propertyEditorSchemaAlias: 'Umbraco.MarkdownEditor', icon: 'icon-code', group: 'richContent', + supportsReadOnly: true, settings: { properties: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.element.ts index e4d0e93692..8383d5f090 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.element.ts @@ -17,6 +17,15 @@ export class UmbPropertyEditorUIMarkdownEditorElement extends UmbLitElement impl @property() value = ''; + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + readonly = false; + @state() private _preview?: boolean; @@ -41,7 +50,8 @@ export class UmbPropertyEditorUIMarkdownEditorElement extends UmbLitElement impl value=${this.value} .overlaySize=${this._overlaySize} ?preview=${this._preview} - @change=${this.#onChange}> + @change=${this.#onChange} + ?readonly=${this.readonly}> `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts index e160890053..b6cbe7a4ef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts @@ -1,7 +1,16 @@ import type { UmbMediaCardItemModel } from '../../modals/index.js'; import type { UmbMediaItemModel } from '../../repository/index.js'; import { UmbMediaPickerInputContext } from './input-media.context.js'; -import { css, customElement, html, ifDefined, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { + css, + customElement, + html, + ifDefined, + nothing, + property, + repeat, + state, +} from '@umbraco-cms/backoffice/external/lit'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -13,7 +22,6 @@ import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import '@umbraco-cms/backoffice/imaging'; const elementName = 'umb-input-media'; - @customElement(elementName) export class UmbInputMediaElement extends UmbFormControlMixin(UmbLitElement) { #sorter = new UmbSorterController(this, { @@ -116,6 +124,27 @@ export class UmbInputMediaElement extends UmbFormControlMixin 0 ? this.selection.join(',') : undefined; } + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default + */ + @property({ type: Boolean, reflect: true }) + public get readonly() { + return this.#readonly; + } + public set readonly(value) { + this.#readonly = value; + + if (this.#readonly) { + this.#sorter.disable(); + } else { + this.#sorter.enable(); + } + } + #readonly = false; + @state() private _editMediaPath = ''; @@ -182,7 +211,7 @@ export class UmbInputMediaElement extends UmbFormControlMixin= this.max) return; - return html` - - - ${this.localize.term('general_choose')} - - `; + // TODO: Stop preventing adding more, instead implement proper validation for user feedback. [NL] + if (this._cards && this.max && this._cards.length >= this.max) return nothing; + if (this.readonly && this._cards.length > 0) { + return nothing; + } else { + return html` + + + ${this.localize.term('general_choose')} + + `; + } } #renderItem(item: UmbMediaCardItemModel) { + const href = this.readonly ? undefined : `${this._editMediaPath}edit/${item.unique}`; return html` + href="${ifDefined(href)}" + ?readonly=${this.readonly}> ${this.#renderIsTrashed(item)} - - this.#onRemove(item)}> - - - + ${this.#renderRemoveAction(item)} `; } + #renderRemoveAction(item: UmbMediaCardItemModel) { + if (this.readonly) return nothing; + return html` + this.#onRemove(item)}> + + + `; + } + #renderIsTrashed(item: UmbMediaCardItemModel) { - if (!item.isTrashed) return; + if (!item.isTrashed) return nothing; return html` Trashed diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-rich-media/input-rich-media.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-rich-media/input-rich-media.element.ts index 9b5cf80fef..1e705d6de7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-rich-media/input-rich-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-rich-media/input-rich-media.element.ts @@ -361,18 +361,23 @@ export class UmbInputRichMediaElement extends UUIFormControlMixin(UmbLitElement, } #renderAddButton() { + // TODO: Stop preventing adding more, instead implement proper validation for user feedback. [NL] if ((this._cards && this.max && this._cards.length >= this.max) || (this._cards.length && !this.multiple)) return; - return html` - - - ${this.localize.term('general_choose')} - - `; + if (this.readonly && this._cards.length > 0) { + return nothing; + } else { + return html` + + + ${this.localize.term('general_choose')} + + `; + } } #renderItem(item: UmbRichMediaCardModel) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/manifests.ts index 3b0bb49284..86bf37902e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/manifests.ts @@ -9,5 +9,6 @@ export const manifest: ManifestPropertyEditorUi = { label: 'Media Entity Picker', icon: 'icon-picture', group: 'pickers', + supportsReadOnly: true, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/property-editor-ui-media-entity-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/property-editor-ui-media-entity-picker.element.ts index c5426bfe0f..96827931d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/property-editor-ui-media-entity-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-entity-picker/property-editor-ui-media-entity-picker.element.ts @@ -19,6 +19,15 @@ export class UmbPropertyEditorUIMediaEntityPickerElement extends UmbLitElement i this._max = minMax?.max ?? Infinity; } + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + readonly = false; + @state() _min: number = 0; @@ -36,6 +45,7 @@ export class UmbPropertyEditorUIMediaEntityPickerElement extends UmbLitElement i .min=${this._min} .max=${this._max} .value=${this.value} + ?readonly=${this.readonly} @change=${this.#onChange}> `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts index fe25a89706..06e85a651a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/components/input-member-group/input-member-group.element.ts @@ -1,6 +1,6 @@ import type { UmbMemberGroupItemModel } from '../../repository/index.js'; import { UmbMemberGroupPickerInputContext } from './input-member-group.context.js'; -import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, property, state, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -100,6 +100,27 @@ export class UmbInputMemberGroupElement extends UmbFormControlMixin boolean = () => true; + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + public get readonly() { + return this.#readonly; + } + public set readonly(value) { + this.#readonly = value; + + if (this.#readonly) { + this.#sorter.disable(); + } else { + this.#sorter.enable(); + } + } + #readonly = false; + @state() private _editMemberGroupPath = ''; @@ -168,36 +189,38 @@ export class UmbInputMemberGroupElement extends UmbFormControlMixin= this.max) return; - return html``; + if (this.max === 1 && this.selection.length >= this.max) return nothing; + if (this.readonly && this.selection.length > 0) { + return nothing; + } else { + return html``; + } } #renderItem(item: UmbMemberGroupItemModel) { - if (!item.unique) return; + if (!item.unique) return nothing; return html` - - - ${this.#renderOpenButton(item)} - this.#removeItem(item)} label=${this.localize.term('general_remove')}> - + + ${this.#renderRemoveButton(item)} `; } - #renderOpenButton(item: UmbMemberGroupItemModel) { - if (!this.showOpenButton) return; - return html` - - ${this.localize.term('general_open')} - - `; + #renderRemoveButton(item: UmbMemberGroupItemModel) { + if (this.readonly) return nothing; + return html` this.#removeItem(item)} + label=${this.localize.term('general_remove')}>`; } static override styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/manifests.ts index 2ec8bcc4f2..77db474611 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/manifests.ts @@ -12,6 +12,7 @@ export const manifests: Array = [ propertyEditorSchemaAlias: 'Umbraco.MemberGroupPicker', icon: 'icon-users-alt', group: 'people', + supportsReadOnly: true, }, }, memberGroupSchemaManifest, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.element.ts index 680b011fa6..b26aeea41e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.element.ts @@ -22,6 +22,15 @@ export class UmbPropertyEditorUIMemberGroupPickerElement extends UmbLitElement i this._max = minMax?.max ?? Infinity; } + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + readonly = false; + @state() _min = 0; @@ -40,7 +49,8 @@ export class UmbPropertyEditorUIMemberGroupPickerElement extends UmbLitElement i .max=${this._max} .value=${this.value} ?showOpenButton=${true} - @change=${this.#onChange}> + @change=${this.#onChange} + ?readonly=${this.readonly}> `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts index 3c1983d5c9..b8ffac2d53 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts @@ -196,14 +196,18 @@ export class UmbInputMemberElement extends UmbFormControlMixin= this.max) return nothing; - return html` - - `; + if (this.readonly && this.selection.length > 0) { + return nothing; + } else { + return html` + + `; + } } #renderItem(item: UmbMemberItemModel) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.ts index 13be644661..67b398fbdc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.ts @@ -272,15 +272,19 @@ export class UmbInputMultiUrlElement extends UUIFormControlMixin(UmbLitElement, } #renderAddButton() { - if (this.max === 1 && this.urls && this.urls.length >= this.max) return; - return html` - - `; + if (this.max === 1 && this.urls && this.urls.length >= this.max) return nothing; + if (this.readonly && this.urls.length > 0) { + return nothing; + } else { + return html` + + `; + } } #renderItems() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts index b404d9a51e..3d1485052e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts @@ -8,7 +8,6 @@ import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; const elementName = 'umb-input-content'; - @customElement(elementName) export class UmbInputContentElement extends UmbFormControlMixin( UmbLitElement, @@ -79,6 +78,15 @@ export class UmbInputContentElement extends UmbFormControlMixin 0 ? this.#selection.join(',') : undefined; } + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + readonly = false; + #entityTypeLookup = { content: 'document', media: 'media', member: 'member' }; #selection: Array = []; @@ -117,6 +125,7 @@ export class UmbInputContentElement extends UmbFormControlMixin `; } @@ -131,6 +140,7 @@ export class UmbInputContentElement extends UmbFormControlMixin `; } @@ -145,6 +155,7 @@ export class UmbInputContentElement extends UmbFormControlMixin `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/manifests.ts index 98da3baee5..412adfacaf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/manifests.ts @@ -14,6 +14,7 @@ const manifest: ManifestPropertyEditorUi = { icon: 'icon-page-add', group: 'pickers', propertyEditorSchemaAlias: 'Umbraco.MultiNodeTreePicker', + supportsReadOnly: true, settings: { properties: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts index c40a756769..c6b35c9b2f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts @@ -37,6 +37,15 @@ export class UmbPropertyEditorUIContentPickerElement } #value?: UmbContentPickerValueType = []; + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + readonly = false; + @state() _type: UmbContentPickerSource['type'] = 'content'; @@ -150,6 +159,7 @@ export class UmbPropertyEditorUIContentPickerElement .startNode=${startNode} .allowedContentTypeIds=${this._allowedContentTypeUniques ?? ''} ?showOpenButton=${this._showOpenButton} + ?readonly=${this.readonly} @change=${this.#onChange}> `; }