Merge branch 'main' into bugfix/reintroduce-integer-deprecate-number

This commit is contained in:
Mads Rasmussen
2024-05-15 14:45:47 +02:00
34 changed files with 313 additions and 232 deletions

View File

@@ -23,6 +23,7 @@ const CORE_PACKAGES = [
import('../../packages/media/umbraco-package.js'),
import('../../packages/members/umbraco-package.js'),
import('../../packages/models-builder/umbraco-package.js'),
import('../../packages/multi-url-picker/umbraco-package.js'),
import('../../packages/packages/umbraco-package.js'),
import('../../packages/property-editors/umbraco-package.js'),
import('../../packages/relations/umbraco-package.js'),

View File

@@ -17,7 +17,6 @@ export * from './input-dropdown/index.js';
export * from './input-entity/index.js';
export * from './input-eye-dropper/index.js';
export * from './input-manifest/index.js';
export * from './input-multi-url/index.js';
export * from './input-number-range/index.js';
export * from './input-radio-button-list/index.js';
export * from './input-slider/index.js';

View File

@@ -1 +0,0 @@
export * from './input-multi-url.element.js';

View File

@@ -1,15 +0,0 @@
import type { Meta, StoryObj } from '@storybook/web-components';
import './input-multi-url.element.js';
import type { UmbInputMultiUrlElement } from './input-multi-url.element.js';
const meta: Meta<UmbInputMultiUrlElement> = {
title: 'Components/Inputs/Multi URL',
component: 'umb-input-multi-url',
};
export default meta;
type Story = StoryObj<UmbInputMultiUrlElement>;
export const Overview: Story = {
args: {},
};

View File

@@ -67,6 +67,7 @@ import type { ManifestSearchResultItem } from './search-result-item.model.js';
import type { ManifestAppEntryPoint } from './app-entry-point.model.js';
import type { ManifestBackofficeEntryPoint } from './backoffice-entry-point.model.js';
import type { ManifestEntryPoint } from './entry-point.model.js';
import type { ManifestMonacoMarkdownEditorAction } from './monaco-markdown-editor-action.model.js';
import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-cms/backoffice/extension-api';
export type * from './app-entry-point.model.js';
@@ -94,6 +95,7 @@ export type * from './menu-item.model.js';
export type * from './menu.model.js';
export type * from './mfa-login-provider.model.js';
export type * from './modal.model.js';
export type * from './monaco-markdown-editor-action.model.js';
export type * from './package-view.model.js';
export type * from './property-action.model.js';
export type * from './property-editor.model.js';
@@ -179,6 +181,7 @@ export type ManifestTypes =
| ManifestMenuItemTreeKind
| ManifestMfaLoginProvider
| ManifestModal
| ManifestMonacoMarkdownEditorAction
| ManifestPackageView
| ManifestPropertyActions
| ManifestPropertyEditorSchema

View File

@@ -0,0 +1,8 @@
import type { ManifestApi } from '@umbraco-cms/backoffice/extension-api';
export interface ManifestMonacoMarkdownEditorAction extends ManifestApi<any> {
type: 'monacoMarkdownEditorAction';
meta?: MetaMonacoMarkdownEditorAction;
}
export interface MetaMonacoMarkdownEditorAction {}

View File

@@ -13,12 +13,6 @@ const modals: Array<ManifestModal> = [
name: 'Icon Picker Modal',
element: () => import('./icon-picker/icon-picker-modal.element.js'),
},
{
type: 'modal',
alias: 'Umb.Modal.LinkPicker',
name: 'Link Picker Modal',
element: () => import('./link-picker/link-picker-modal.element.js'),
},
{
type: 'modal',
alias: 'Umb.Modal.CodeEditor',

View File

@@ -6,7 +6,6 @@ export * from './embedded-media-modal.token.js';
export * from './entity-user-permission-settings-modal.token.js';
export * from './icon-picker-modal.token.js';
export * from './item-picker-modal.token.js';
export * from './link-picker-modal.token.js';
export * from './modal-token.js';
export * from './property-editor-ui-picker-modal.token.js';
export * from './workspace-modal.token.js';

View File

@@ -1,4 +1,13 @@
import { css, html, customElement, query, property, unsafeHTML, when } from '@umbraco-cms/backoffice/external/lit';
import {
css,
html,
customElement,
query,
property,
unsafeHTML,
when,
state,
} from '@umbraco-cms/backoffice/external/lit';
import { DOMPurify } from '@umbraco-cms/backoffice/external/dompurify';
import { marked } from '@umbraco-cms/backoffice/external/marked';
import { monaco } from '@umbraco-cms/backoffice/external/monaco-editor';
@@ -7,12 +16,14 @@ import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app';
import { UMB_LINK_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UMB_MEDIA_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/media';
import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import type { UmbCodeEditorController, UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor';
import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api';
/**
* @element umb-input-markdown
@@ -39,6 +50,9 @@ export class UmbInputMarkdownElement extends UUIFormControlMixin(UmbLitElement,
@query('umb-code-editor')
_codeEditor?: UmbCodeEditorElement;
@state()
_actionExtensions: Array<monaco.editor.IActionDescriptor> = [];
private _modalContext?: UmbModalManagerContext;
private serverUrl?: string;
@@ -46,9 +60,11 @@ export class UmbInputMarkdownElement extends UUIFormControlMixin(UmbLitElement,
constructor() {
super();
this.#loadCodeEditor();
this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => {
this._modalContext = instance;
});
this.consumeContext(UMB_APP_CONTEXT, (instance) => {
this.serverUrl = instance.getServerUrl();
});
@@ -67,6 +83,23 @@ export class UmbInputMarkdownElement extends UUIFormControlMixin(UmbLitElement,
}); // Prefer to update options before showing the editor, to avoid seeing the changes in the UI.
this.#isCodeEditorReady.setValue(true);
// TODO: make all action into extensions
this.observe(umbExtensionsRegistry.byType('monacoMarkdownEditorAction'), (manifests) => {
manifests.forEach(async (manifest) => {
const api = await createExtensionApi(this, manifest, [this]);
const action: monaco.editor.IActionDescriptor = {
id: api.getUnique(),
label: api.getLabel(),
keybindings: api.getKeybindings(),
run: async () => await api.execute({ editor: this.#editor }),
};
this.#editor?.monacoEditor?.addAction(action);
this._actionExtensions.push(action);
this.requestUpdate('_actionExtensions');
});
});
this.#loadActions();
} catch (error) {
console.error(error);
@@ -157,12 +190,6 @@ export class UmbInputMarkdownElement extends UUIFormControlMixin(UmbLitElement,
id: 'line',
run: () => this._insertLine(),
});
this.#editor?.monacoEditor?.addAction({
label: 'Add Link',
id: 'link',
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK],
run: () => this._insertLink(),
});
this.#editor?.monacoEditor?.addAction({
label: 'Add Image',
id: 'image',
@@ -172,61 +199,18 @@ export class UmbInputMarkdownElement extends UUIFormControlMixin(UmbLitElement,
});
}
#onActionClick(event: any, action: monaco.editor.IActionDescriptor) {
event.stopPropagation();
const hasAction = this.#editor?.monacoEditor?.getAction(action.id);
if (!hasAction) throw new Error(`Action ${action.id} not found in the editor.`);
this.#editor?.monacoEditor?.getAction(action.id)?.run();
}
private _focusEditor(): void {
// If we press one of the action buttons manually (which is outside the editor), we need to focus the editor again.
this.#editor?.monacoEditor?.focus();
}
private _insertLink() {
const selection = this.#editor?.getSelections()[0];
if (!selection || !this._modalContext) return;
const selectedValue = this.#editor?.getValueInRange(selection);
this._focusEditor(); // Focus before opening modal
const modalContext = this._modalContext.open(this, UMB_LINK_PICKER_MODAL, {
modal: { size: this.overlaySize },
data: {
index: null,
config: {},
},
value: {
link: { name: selectedValue },
},
});
modalContext
?.onSubmit()
.then((value) => {
if (!value) return;
const name = this.localize.term('general_name');
const url = this.localize.term('general_url');
this.#editor?.monacoEditor?.executeEdits('', [
{ range: selection, text: `[${value.link.name || name}](${value.link.url || url})` },
]);
if (!value.link.name) {
this.#editor?.select({
startColumn: selection.startColumn + 1,
endColumn: selection.startColumn + 1 + name.length,
endLineNumber: selection.startLineNumber,
startLineNumber: selection.startLineNumber,
});
} else if (!value.link.url) {
this.#editor?.select({
startColumn: selection.startColumn + 3 + value.link.name.length,
endColumn: selection.startColumn + 3 + value.link.name.length + url.length,
endLineNumber: selection.startLineNumber,
startLineNumber: selection.startLineNumber,
});
}
})
.catch(() => undefined)
.finally(() => this._focusEditor());
}
private _insertMedia() {
const selection = this.#editor?.getSelections()[0];
if (!selection) return;
@@ -488,14 +472,6 @@ export class UmbInputMarkdownElement extends UUIFormControlMixin(UmbLitElement,
@click=${() => this.#editor?.monacoEditor?.getAction('line')?.run()}>
<uui-icon name="icon-width"></uui-icon>
</uui-button>
<uui-button
compact
look="secondary"
label="Link"
title="Link, &lt;Ctrl+K&gt;"
@click=${() => this.#editor?.monacoEditor?.getAction('link')?.run()}>
<uui-icon name="icon-link"></uui-icon>
</uui-button>
<uui-button
compact
look="secondary"
@@ -504,6 +480,18 @@ export class UmbInputMarkdownElement extends UUIFormControlMixin(UmbLitElement,
@click=${() => this.#editor?.monacoEditor?.getAction('image')?.run()}>
<uui-icon name="icon-picture"></uui-icon>
</uui-button>
${this._actionExtensions.map(
(action) => html`
<uui-button
compact
look="secondary"
label=${action.label}
@click=${(event: any) => this.#onActionClick(event, action)}>
<uui-icon name="icon-link"></uui-icon>
</uui-button>
`,
)}
</div>
<div>
<uui-button

View File

@@ -0,0 +1 @@
export const UMB_MULTI_URL_PICKER_MODAL_ALIAS = 'Umb.Modal.MultiUrlLinkPicker';

View File

@@ -1,13 +1,12 @@
import type { UmbLinkPickerLink, UmbLinkPickerLinkType } from './types.js';
import type {
UmbLinkPickerConfig,
UmbLinkPickerModalData,
UmbLinkPickerModalValue,
} from './link-picker-modal.token.js';
import type { UmbTreeElement, UmbTreeSelectionConfiguration } from '@umbraco-cms/backoffice/tree';
import { css, html, nothing, customElement, query, state, styleMap } from '@umbraco-cms/backoffice/external/lit';
import type { UUIBooleanInputEvent, UUIInputElement } from '@umbraco-cms/backoffice/external/uui';
import type {
UmbLinkPickerConfig,
UmbLinkPickerLink,
UmbLinkPickerLinkType,
UmbLinkPickerModalData,
UmbLinkPickerModalValue,
} from '@umbraco-cms/backoffice/modal';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { UMB_DOCUMENT_TREE_ALIAS } from '@umbraco-cms/backoffice/document';

View File

@@ -1,4 +1,4 @@
import '../../../components/body-layout/body-layout.element.js';
import '../../../core/components/body-layout/body-layout.element.js';
import './link-picker-modal.element.js';
import type { Meta, Story } from '@storybook/web-components';

View File

@@ -1,4 +1,6 @@
import { UmbModalToken } from './modal-token.js';
import { UMB_MULTI_URL_PICKER_MODAL_ALIAS } from './constants.js';
import type { UmbLinkPickerLink } from './types.js';
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
export interface UmbLinkPickerModalData {
config: UmbLinkPickerConfig;
@@ -7,20 +9,6 @@ export interface UmbLinkPickerModalData {
export type UmbLinkPickerModalValue = { link: UmbLinkPickerLink };
export interface UmbLinkPickerLink {
icon?: string | null;
name?: string | null;
published?: boolean | null;
queryString?: string | null;
target?: string | null;
trashed?: boolean | null;
type?: UmbLinkPickerLinkType | null;
unique?: string | null;
url?: string | null;
}
export type UmbLinkPickerLinkType = 'document' | 'external' | 'media';
// TODO: investigate: this looks more like a property editor configuration. Is this used in the correct way?
export interface UmbLinkPickerConfig {
hideAnchor?: boolean;
@@ -28,7 +16,7 @@ export interface UmbLinkPickerConfig {
}
export const UMB_LINK_PICKER_MODAL = new UmbModalToken<UmbLinkPickerModalData, UmbLinkPickerModalValue>(
'Umb.Modal.LinkPicker',
UMB_MULTI_URL_PICKER_MODAL_ALIAS,
{
modal: {
type: 'sidebar',

View File

@@ -0,0 +1,10 @@
import { UMB_MULTI_URL_PICKER_MODAL_ALIAS } from './constants.js';
export const manifests = [
{
type: 'modal',
alias: UMB_MULTI_URL_PICKER_MODAL_ALIAS,
name: 'Property Editor Multi Url Link Picker Modal',
element: () => import('./link-picker-modal.element.js'),
},
];

View File

@@ -0,0 +1,13 @@
export type UmbLinkPickerLinkType = 'document' | 'external' | 'media';
export interface UmbLinkPickerLink {
icon?: string | null;
name?: string | null;
published?: boolean | null;
queryString?: string | null;
target?: string | null;
trashed?: boolean | null;
type?: UmbLinkPickerLinkType | null;
unique?: string | null;
url?: string | null;
}

View File

@@ -0,0 +1,12 @@
import { manifests as modalManifests } from './link-picker-modal/manifests.js';
import { manifests as monacoMarkdownEditorManifests } from './monaco-markdown-editor-action/manifests.js';
import { manifests as propertyEditorManifests } from './property-editor/manifests.js';
import { manifests as tinyMceManifests } from './tiny-mce-plugin/manifests.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
export const manifests: Array<ManifestTypes> = [
...modalManifests,
...monacoMarkdownEditorManifests,
...propertyEditorManifests,
...tinyMceManifests,
];

View File

@@ -0,0 +1,8 @@
export const manifests = [
{
type: 'monacoMarkdownEditorAction',
alias: 'Umb.MonacoMarkdownEditorAction.MultiUrlPicker',
name: 'Multi Url Picker Monaco Markdown Editor Action',
js: () => import('./url-picker-monaco-markdown-editor-action.js'),
},
];

View File

@@ -0,0 +1,83 @@
import { UMB_LINK_PICKER_MODAL } from '../link-picker-modal/link-picker-modal.token.js';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { monaco } from '@umbraco-cms/backoffice/external/monaco-editor';
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
export class UmbUrlPickerMonacoMarkdownEditorAction extends UmbControllerBase {
#localize = new UmbLocalizationController(this);
constructor(host: UmbControllerHost) {
super(host);
}
getUnique() {
return 'Umb.MonacoMarkdownEditorAction.UrlPicker';
}
getLabel() {
return this.#localize.term('general_insertLink');
}
getKeybindings() {
return [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK];
}
async execute({ editor, overlaySize }: { editor: any; overlaySize: UUIModalSidebarSize }) {
if (!editor) throw new Error('Editor not found');
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
if (!modalManager) throw new Error('Modal manager not found');
const selection = editor?.getSelections()[0];
if (!selection) return;
const selectedValue = editor?.getValueInRange(selection);
editor.monacoEditor?.focus();
const modalContext = modalManager.open(this, UMB_LINK_PICKER_MODAL, {
modal: { size: overlaySize },
data: {
index: null,
config: {},
},
value: {
link: { name: selectedValue },
},
});
modalContext
?.onSubmit()
.then((value) => {
if (!value) return;
const name = this.#localize.term('general_name');
const url = this.#localize.term('general_url');
editor.monacoEditor?.executeEdits('', [
{ range: selection, text: `[${value.link.name || name}](${value.link.url || url})` },
]);
if (!value.link.name) {
editor.select({
startColumn: selection.startColumn + 1,
endColumn: selection.startColumn + 1 + name.length,
endLineNumber: selection.startLineNumber,
startLineNumber: selection.startLineNumber,
});
} else if (!value.link.url) {
editor.select({
startColumn: selection.startColumn + 3 + value.link.name.length,
endColumn: selection.startColumn + 3 + value.link.name.length + url.length,
endLineNumber: selection.startLineNumber,
startLineNumber: selection.startLineNumber,
});
}
})
.catch(() => undefined)
.finally(() => editor.monacoEditor?.focus());
}
}
export { UmbUrlPickerMonacoMarkdownEditorAction as api };

View File

@@ -0,0 +1 @@
export * from './multi-url-picker.element.js';

View File

@@ -1,15 +1,13 @@
import type { UmbLinkPickerLink } from '../link-picker-modal/types.js';
import { UMB_LINK_PICKER_MODAL } from '../link-picker-modal/link-picker-modal.token.js';
import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit';
import { simpleHashCode } from '@umbraco-cms/backoffice/observable-api';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import {
umbConfirmModal,
UmbModalRouteRegistrationController,
UMB_LINK_PICKER_MODAL,
} from '@umbraco-cms/backoffice/modal';
import { umbConfirmModal, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import type { UmbModalRouteBuilder, UmbLinkPickerLink } from '@umbraco-cms/backoffice/modal';
import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/modal';
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
@@ -19,8 +17,9 @@ import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
* @fires blur - when the input loses focus
* @fires focus - when the input gains focus
*/
@customElement('umb-input-multi-url')
export class UmbInputMultiUrlElement extends UUIFormControlMixin(UmbLitElement, '') {
const elementName = 'umb-multi-url-picker';
@customElement(elementName)
export class UmbMultiUrlPickerElement extends UUIFormControlMixin(UmbLitElement, '') {
#sorter = new UmbSorterController<UmbLinkPickerLink>(this, {
getUniqueOfElement: (element) => {
return element.id;
@@ -300,6 +299,6 @@ export class UmbInputMultiUrlElement extends UUIFormControlMixin(UmbLitElement,
declare global {
interface HTMLElementTagNameMap {
'umb-input-multi-url': UmbInputMultiUrlElement;
[elementName]: UmbMultiUrlPickerElement;
}
}

View File

@@ -0,0 +1,15 @@
import type { Meta, StoryObj } from '@storybook/web-components';
import './multi-url-picker.element.js';
import type { UmbMultiUrlPickerElement } from './multi-url-picker.element.js';
const meta: Meta<UmbMultiUrlPickerElement> = {
title: 'Components/Inputs/Multi URL',
component: 'umb-input-multi-url',
};
export default meta;
type Story = StoryObj<UmbMultiUrlPickerElement>;
export const Overview: Story = {
args: {},
};

View File

@@ -0,0 +1,33 @@
import { manifest as schemaManifest } from './Umbraco.MultiUrlPicker.js';
export const manifests = [
{
type: 'propertyEditorUi',
alias: 'Umb.PropertyEditorUi.MultiUrlPicker',
name: 'Multi URL Picker Property Editor UI',
element: () => import('./property-editor-ui-multi-url-picker.element.js'),
meta: {
label: 'Multi URL Picker',
propertyEditorSchemaAlias: 'Umbraco.MultiUrlPicker',
icon: 'icon-link',
group: 'pickers',
settings: {
properties: [
{
alias: 'overlaySize',
label: 'Overlay Size',
description: 'Select the width of the overlay.',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.OverlaySize',
},
{
alias: 'hideAnchor',
label: 'Hide anchor/query string input',
description: 'Selecting this hides the anchor/query string input field in the link picker overlay.',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.Toggle',
},
],
},
},
},
schemaManifest,
];

View File

@@ -1,13 +1,16 @@
import type { UmbLinkPickerLink } from '../link-picker-modal/types.js';
import type { UmbMultiUrlPickerElement } from '../multi-url-picker/multi-url-picker.element.js';
import { customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor';
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
import type { UmbInputMultiUrlElement } from '@umbraco-cms/backoffice/components';
import type { UmbLinkPickerLink } from '@umbraco-cms/backoffice/modal';
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui';
// import of local component
import '../multi-url-picker/multi-url-picker.element.js';
/**
* @element umb-property-editor-ui-multi-url-picker
*/
@@ -56,14 +59,14 @@ export class UmbPropertyEditorUIMultiUrlPickerElement extends UmbLitElement impl
});
}
#onChange(event: CustomEvent & { target: UmbInputMultiUrlElement }) {
#onChange(event: CustomEvent & { target: UmbMultiUrlPickerElement }) {
this.value = event.target.urls;
this.dispatchEvent(new UmbPropertyValueChangeEvent());
}
render() {
return html`
<umb-input-multi-url
<umb-multi-url-picker
.alias=${this._alias}
.ignoreUserStartNodes=${this._ignoreUserStartNodes}
.max=${this._maxNumber}
@@ -73,7 +76,7 @@ export class UmbPropertyEditorUIMultiUrlPickerElement extends UmbLitElement impl
.variantId=${this._variantId}
?hide-anchor=${this._hideAnchor}
@change=${this.#onChange}>
</umb-input-multi-url>
</umb-multi-url-picker>
`;
}
}

View File

@@ -0,0 +1,22 @@
export const manifests = [
{
type: 'tinyMcePlugin',
alias: 'Umb.TinyMcePlugin.MultiUrlPicker',
name: 'Multi Url Picker TinyMCE Plugin',
js: () => import('./tiny-mce-multi-url-picker.plugin.js'),
meta: {
toolbar: [
{
alias: 'link',
label: 'Insert/Edit link',
icon: 'link',
},
{
alias: 'unlink',
label: 'Remove link',
icon: 'unlink',
},
],
},
},
];

View File

@@ -1,6 +1,8 @@
import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '../components/input-tiny-mce/tiny-mce-plugin.js';
import type { UmbLinkPickerModalValue, UmbLinkPickerLink } from '@umbraco-cms/backoffice/modal';
import { UMB_LINK_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import type { UmbLinkPickerModalValue } from '../link-picker-modal/link-picker-modal.token.js';
import { UMB_LINK_PICKER_MODAL } from '../link-picker-modal/link-picker-modal.token.js';
import type { UmbLinkPickerLink } from '../link-picker-modal/types.js';
import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '@umbraco-cms/backoffice/tiny-mce';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
type AnchorElementAttributes = {
href?: string | null;
@@ -11,7 +13,7 @@ type AnchorElementAttributes = {
text?: string;
};
export default class UmbTinyMceLinkPickerPlugin extends UmbTinyMcePluginBase {
export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase {
#linkPickerData?: UmbLinkPickerModalValue;
#anchorElement?: HTMLAnchorElement;
@@ -72,7 +74,7 @@ export default class UmbTinyMceLinkPickerPlugin extends UmbTinyMcePluginBase {
if (this.#anchorElement.href.includes('localLink:')) {
const href = this.#anchorElement.getAttribute('href')!;
currentTarget.unique = href.substring(href.indexOf(":") + 1, href.indexOf("}"));
currentTarget.unique = href.substring(href.indexOf(':') + 1, href.indexOf('}'));
} else if (this.#anchorElement.host.length) {
currentTarget.url = this.#anchorElement.protocol ? this.#anchorElement.protocol + '//' : undefined;
currentTarget.url += this.#anchorElement.host + this.#anchorElement.pathname;
@@ -122,9 +124,10 @@ export default class UmbTinyMceLinkPickerPlugin extends UmbTinyMcePluginBase {
a.title = name;
}
if (this.#linkPickerData?.link.queryString?.startsWith('#') ||
this.#linkPickerData?.link.queryString?.startsWith('?'))
{
if (
this.#linkPickerData?.link.queryString?.startsWith('#') ||
this.#linkPickerData?.link.queryString?.startsWith('?')
) {
a['data-anchor'] = this.#linkPickerData?.link.queryString;
a.href += this.#linkPickerData?.link.queryString;
}

View File

@@ -0,0 +1,9 @@
export const name = 'Umbraco.Core.MultiUrlPicker';
export const extensions = [
{
name: 'Multi Url Picker Bundle',
alias: 'Umb.Bundle.MultiUrlPicker',
type: 'bundle',
js: () => import('./manifests.js'),
},
];

View File

@@ -1,24 +0,0 @@
import { UmbPropertyEditorUICollectionElement } from './property-editor-ui-collection.element.js';
import { customElement } from '@umbraco-cms/backoffice/external/lit';
/**
* @element umb-legacy-property-editor-ui-collection
* @deprecated Use "umb-property-editor-ui-collection" instead.
*/
@customElement('umb-legacy-property-editor-ui-collection')
export class UmbLegacyPropertyEditorUICollectionElement extends UmbPropertyEditorUICollectionElement {
constructor() {
super();
console.warn(
'The element "umb-legacy-property-editor-ui-collection" has been deprecated. Use "umb-property-editor-ui-collection" instead.',
);
}
}
export default UmbPropertyEditorUICollectionElement;
declare global {
interface HTMLElementTagNameMap {
'umb-legacy-property-editor-ui-collection': UmbPropertyEditorUICollectionElement;
}
}

View File

@@ -101,26 +101,11 @@ const propertyEditorUiManifest: ManifestPropertyEditorUi = {
},
};
/**
* Legacy property editor UI manifest for the collection view property editor.
* @deprecated Use the property editor UI alias of 'Umb.PropertyEditorUi.Collection' instead.
*/
const legacyPropertyEditorUiManifest: ManifestPropertyEditorUi = {
...propertyEditorUiManifest,
alias: 'Umb.PropertyEditorUi.CollectionView',
element: () => import('./legacy-property-editor-ui-collection.element.js'),
};
const config: Array<ManifestPropertyEditorUi> = [
export const manifests: Array<ManifestTypes> = [
propertyEditorUiManifest,
bulkActionPermissions,
columnConfiguration,
layoutConfiguration,
orderBy,
];
export const manifests: Array<ManifestTypes> = [
propertyEditorUiManifest,
legacyPropertyEditorUiManifest,
...config,
schema,
];

View File

@@ -13,7 +13,6 @@ import { manifests as eyeDropperManifests } from './eye-dropper/manifests.js';
import { manifests as iconPickerManifests } from './icon-picker/manifests.js';
import { manifests as labelManifests } from './label/manifests.js';
import { manifests as multipleTextStringManifests } from './multiple-text-string/manifests.js';
import { manifests as multiUrlPickerManifests } from './multi-url-picker/manifests.js';
import { manifests as numberManifests } from './number/manifests.js';
import { manifests as radioButtonListManifests } from './radio-button-list/manifests.js';
import { manifests as sliderManifests } from './slider/manifests.js';
@@ -34,7 +33,6 @@ export const manifests: Array<ManifestTypes> = [
...iconPickerManifests,
...labelManifests,
...multipleTextStringManifests,
...multiUrlPickerManifests,
...numberManifests,
...radioButtonListManifests,
...sliderManifests,

View File

@@ -1,33 +0,0 @@
import { manifest as schemaManifest } from './Umbraco.MultiUrlPicker.js';
import type { ManifestPropertyEditorUi, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
const manifest: ManifestPropertyEditorUi = {
type: 'propertyEditorUi',
alias: 'Umb.PropertyEditorUi.MultiUrlPicker',
name: 'Multi URL Picker Property Editor UI',
element: () => import('./property-editor-ui-multi-url-picker.element.js'),
meta: {
label: 'Multi URL Picker',
propertyEditorSchemaAlias: 'Umbraco.MultiUrlPicker',
icon: 'icon-link',
group: 'pickers',
settings: {
properties: [
{
alias: 'overlaySize',
label: 'Overlay Size',
description: 'Select the width of the overlay.',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.OverlaySize',
},
{
alias: 'hideAnchor',
label: 'Hide anchor/query string input',
description: 'Selecting this hides the anchor/query string input field in the link picker overlay.',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.Toggle',
},
],
},
},
};
export const manifests: Array<ManifestTypes> = [manifest, schemaManifest];

View File

@@ -16,26 +16,6 @@ export const manifests: Array<ManifestTinyMcePlugin> = [
],
},
},
{
type: 'tinyMcePlugin',
alias: 'Umb.TinyMcePlugin.LinkPicker',
name: 'Link Picker TinyMCE Plugin',
js: () => import('./tiny-mce-linkpicker.plugin.js'),
meta: {
toolbar: [
{
alias: 'link',
label: 'Insert/Edit link',
icon: 'link',
},
{
alias: 'unlink',
label: 'Remove link',
icon: 'unlink',
},
],
},
},
{
type: 'tinyMcePlugin',
alias: 'Umb.TinyMcePlugin.MediaPicker',