Merge branch 'main' into bugfix/reintroduce-integer-deprecate-number
This commit is contained in:
@@ -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'),
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from './input-multi-url.element.js';
|
||||
@@ -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: {},
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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 {}
|
||||
@@ -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',
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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, <Ctrl+K>"
|
||||
@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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const UMB_MULTI_URL_PICKER_MODAL_ALIAS = 'Umb.Modal.MultiUrlLinkPicker';
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
@@ -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',
|
||||
@@ -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'),
|
||||
},
|
||||
];
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
];
|
||||
@@ -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'),
|
||||
},
|
||||
];
|
||||
@@ -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 };
|
||||
@@ -0,0 +1 @@
|
||||
export * from './multi-url-picker.element.js';
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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: {},
|
||||
};
|
||||
@@ -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,
|
||||
];
|
||||
@@ -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>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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'),
|
||||
},
|
||||
];
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user