Merge remote-tracking branch 'origin/v15/feature/tiptap' into tiptap/feat/toolbar
This commit is contained in:
@@ -42,6 +42,7 @@ import type { ManifestSectionView } from './section-view.model.js';
|
||||
import type { ManifestStore, ManifestTreeStore, ManifestItemStore } from './store.model.js';
|
||||
import type { ManifestTheme } from './theme.model.js';
|
||||
import type { ManifestTinyMcePlugin } from './tinymce-plugin.model.js';
|
||||
import type { ManifestTiptapExtension } from './tiptap-extension.model.js';
|
||||
import type { ManifestTree } from './tree.model.js';
|
||||
import type { ManifestTreeItem } from './tree-item.model.js';
|
||||
import type { ManifestUfmComponent } from './ufm-component.model.js';
|
||||
@@ -113,6 +114,7 @@ export type * from './section.model.js';
|
||||
export type * from './store.model.js';
|
||||
export type * from './theme.model.js';
|
||||
export type * from './tinymce-plugin.model.js';
|
||||
export type * from './tiptap-extension.model.js';
|
||||
export type * from './tree-item.model.js';
|
||||
export type * from './tree.model.js';
|
||||
export type * from './ufm-component.model.js';
|
||||
@@ -206,6 +208,7 @@ export type ManifestTypes =
|
||||
| ManifestStore
|
||||
| ManifestTheme
|
||||
| ManifestTinyMcePlugin
|
||||
| ManifestTiptapExtension
|
||||
| ManifestTree
|
||||
| ManifestTreeItem
|
||||
| ManifestTreeStore
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { UmbTiptapExtensionBase } from '@umbraco-cms/backoffice/tiptap';
|
||||
import type { ManifestApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestTiptapExtension extends ManifestApi<UmbTiptapExtensionBase> {
|
||||
type: 'tiptapExtension';
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { manifests as tiptapManifests } from './tiptap/manifests.js';
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests = [...tiptapManifests];
|
||||
export const manifests: Array<ManifestTypes> = [...tiptapManifests];
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './input-tiptap.element.js';
|
||||
export * from './tiptap-extension.js';
|
||||
|
||||
@@ -1,41 +1,65 @@
|
||||
import type { UmbTiptapFixedMenuElement } from './tiptap-fixed-menu.element.js';
|
||||
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { css, customElement, html, property, query, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbTiptapExtensionBase } from './tiptap-extension.js';
|
||||
import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { Editor, Link, StarterKit, TextAlign, Underline } from '@umbraco-cms/backoffice/external/tiptap';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
|
||||
import './tiptap-fixed-menu.element.js';
|
||||
import './tiptap-hover-menu.element.js';
|
||||
import { Editor, Link, StarterKit, TextAlign, Underline } from '@umbraco-cms/backoffice/external/tiptap';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
|
||||
@customElement('umb-input-tiptap')
|
||||
export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, '') {
|
||||
@query('umb-tiptap-fixed-menu') _fixedMenuElement!: UmbTiptapFixedMenuElement;
|
||||
export class UmbInputTiptapElement extends UmbFormControlMixin(UmbLitElement, '') {
|
||||
@state()
|
||||
private _extensions: Array<UmbTiptapExtensionBase> = [];
|
||||
|
||||
@property({ attribute: false })
|
||||
configuration?: UmbPropertyEditorConfigCollection;
|
||||
|
||||
@state()
|
||||
_editor!: Editor;
|
||||
private _editor!: Editor;
|
||||
|
||||
protected override firstUpdated(): void {
|
||||
const editor = this.shadowRoot?.querySelector('#editor');
|
||||
protected override async firstUpdated() {
|
||||
await Promise.all([await this.#loadExtensions(), await this.#loadEditor()]);
|
||||
}
|
||||
|
||||
if (!editor) return;
|
||||
async #loadExtensions() {
|
||||
await new Promise<void>((resolve) => {
|
||||
this.observe(umbExtensionsRegistry.byType('tiptapExtension'), async (manifests) => {
|
||||
this._extensions = [];
|
||||
|
||||
for (const manifest of manifests) {
|
||||
if (manifest.api) {
|
||||
const extension = await loadManifestApi(manifest.api);
|
||||
if (extension) {
|
||||
this._extensions.push(new extension(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.requestUpdate('_extensions');
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async #loadEditor() {
|
||||
const element = this.shadowRoot?.querySelector('#editor');
|
||||
if (!element) return;
|
||||
|
||||
const toolbar = this.configuration?.getValueByAlias<string[]>('toolbar');
|
||||
const maxWidth = this.configuration?.getValueByAlias<number>('maxWidth');
|
||||
const maxHeight = this.configuration?.getValueByAlias<number>('maxHeight');
|
||||
const mode = this.configuration?.getValueByAlias<string>('mode');
|
||||
|
||||
this.setAttribute('style', `max-width: ${maxWidth}px;`);
|
||||
editor.setAttribute('style', `max-height: ${maxHeight}px;`);
|
||||
element.setAttribute('style', `max-height: ${maxHeight}px;`);
|
||||
|
||||
if (!editor) return;
|
||||
const extensions = this._extensions.map((ext) => ext.getExtensions()).flat();
|
||||
|
||||
this._editor = new Editor({
|
||||
element: editor,
|
||||
element: element,
|
||||
extensions: [
|
||||
StarterKit,
|
||||
TextAlign.configure({
|
||||
@@ -43,6 +67,7 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
|
||||
}),
|
||||
Link.configure({ openOnClick: false }),
|
||||
Underline,
|
||||
...extensions,
|
||||
],
|
||||
content: this.value.toString(),
|
||||
onUpdate: ({ editor }) => {
|
||||
@@ -52,13 +77,10 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
|
||||
});
|
||||
}
|
||||
|
||||
protected getFormElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (!this._extensions?.length) return html`<uui-loader></uui-loader>`;
|
||||
return html`
|
||||
<umb-tiptap-fixed-menu .editor=${this._editor}></umb-tiptap-fixed-menu>
|
||||
<umb-tiptap-fixed-menu .editor=${this._editor} .extensions=${this._extensions}></umb-tiptap-fixed-menu>
|
||||
<div id="editor"></div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/external/tiptap';
|
||||
import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export abstract class UmbTiptapExtensionBase extends UmbControllerBase implements UmbApi {
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host);
|
||||
}
|
||||
|
||||
abstract getExtensions(): Array<Extension | Mark | Node>;
|
||||
|
||||
abstract getToolbarButtons(): Array<UmbTiptapToolbarButton>;
|
||||
}
|
||||
|
||||
export interface UmbTiptapToolbarButton {
|
||||
name: string;
|
||||
icon: string | TemplateResult;
|
||||
isActive: (editor?: Editor) => boolean | undefined;
|
||||
command: (editor?: Editor) => boolean | undefined | void | Promise<boolean> | Promise<undefined> | Promise<void>;
|
||||
}
|
||||
@@ -1,29 +1,13 @@
|
||||
import {
|
||||
alignCenter,
|
||||
alignJustify,
|
||||
alignLeft,
|
||||
alignRight,
|
||||
blockquote,
|
||||
bold,
|
||||
bulletList,
|
||||
code,
|
||||
heading1,
|
||||
heading2,
|
||||
heading3,
|
||||
horizontalRule,
|
||||
italic,
|
||||
link,
|
||||
orderedList,
|
||||
strikethrough,
|
||||
underline,
|
||||
} from './icons.js';
|
||||
import { LitElement, css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import * as icons from './icons.js';
|
||||
import type { UmbTiptapExtensionBase, UmbTiptapToolbarButton } from './tiptap-extension.js';
|
||||
import { css, customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
|
||||
|
||||
@customElement('umb-tiptap-fixed-menu')
|
||||
export class UmbTiptapFixedMenuElement extends LitElement {
|
||||
export class UmbTiptapFixedMenuElement extends UmbLitElement {
|
||||
@state()
|
||||
actions = [
|
||||
actions: Array<UmbTiptapToolbarButton> = [
|
||||
// TODO: I don't think we need a paragraph button. It's the default state.
|
||||
// {
|
||||
// name: 'paragraph',
|
||||
@@ -31,107 +15,108 @@ export class UmbTiptapFixedMenuElement extends LitElement {
|
||||
// <path fill="none" d="M0 0h24v24H0z" />
|
||||
// <path d="M12 6v15h-2v-5a6 6 0 1 1 0-12h10v2h-3v15h-2V6h-3zm-2 0a4 4 0 1 0 0 8V6z" fill="currentColor" />
|
||||
// </svg>`,
|
||||
// command: () => this.editor?.chain().focus().setParagraph().run(),
|
||||
// command: (editor) => editor?.chain().focus().setParagraph().run(),
|
||||
// },
|
||||
{
|
||||
name: 'bold',
|
||||
icon: bold,
|
||||
isActive: () => this.editor?.isActive('bold'),
|
||||
command: () => this.editor?.chain().focus().toggleBold().run(),
|
||||
icon: icons.bold,
|
||||
isActive: (editor) => editor?.isActive('bold'),
|
||||
command: (editor) => editor?.chain().focus().toggleBold().run(),
|
||||
},
|
||||
{
|
||||
name: 'italic',
|
||||
icon: italic,
|
||||
isActive: () => this.editor?.isActive('italic'),
|
||||
command: () => this.editor?.chain().focus().toggleItalic().run(),
|
||||
icon: icons.italic,
|
||||
isActive: (editor) => editor?.isActive('italic'),
|
||||
command: (editor) => editor?.chain().focus().toggleItalic().run(),
|
||||
},
|
||||
{
|
||||
name: 'underline',
|
||||
icon: underline,
|
||||
isActive: () => this.editor?.isActive('underline'),
|
||||
command: () => this.editor?.chain().focus().toggleUnderline().run(),
|
||||
icon: icons.underline,
|
||||
isActive: (editor) => editor?.isActive('underline'),
|
||||
command: (editor) => editor?.chain().focus().toggleUnderline().run(),
|
||||
},
|
||||
{
|
||||
name: 'strikethrough',
|
||||
icon: strikethrough,
|
||||
isActive: () => this.editor?.isActive('strike'),
|
||||
command: () => this.editor?.chain().focus().toggleStrike().run(),
|
||||
icon: icons.strikethrough,
|
||||
isActive: (editor) => editor?.isActive('strike'),
|
||||
command: (editor) => editor?.chain().focus().toggleStrike().run(),
|
||||
},
|
||||
{
|
||||
name: 'h1',
|
||||
icon: heading1,
|
||||
isActive: () => this.editor?.isActive('heading', { level: 1 }),
|
||||
command: () => this.editor?.chain().focus().toggleHeading({ level: 1 }).run(),
|
||||
icon: icons.heading1,
|
||||
isActive: (editor) => editor?.isActive('heading', { level: 1 }),
|
||||
command: (editor) => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
|
||||
},
|
||||
{
|
||||
name: 'h2',
|
||||
icon: heading2,
|
||||
isActive: () => this.editor?.isActive('heading', { level: 2 }),
|
||||
command: () => this.editor?.chain().focus().toggleHeading({ level: 2 }).run(),
|
||||
icon: icons.heading2,
|
||||
isActive: (editor) => editor?.isActive('heading', { level: 2 }),
|
||||
command: (editor) => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
|
||||
},
|
||||
{
|
||||
name: 'h3',
|
||||
icon: heading3,
|
||||
isActive: () => this.editor?.isActive('heading', { level: 3 }),
|
||||
command: () => this.editor?.chain().focus().toggleHeading({ level: 3 }).run(),
|
||||
icon: icons.heading3,
|
||||
isActive: (editor) => editor?.isActive('heading', { level: 3 }),
|
||||
command: (editor) => editor?.chain().focus().toggleHeading({ level: 3 }).run(),
|
||||
},
|
||||
{
|
||||
name: 'blockquote',
|
||||
icon: blockquote,
|
||||
isActive: () => this.editor?.isActive('blockquote'),
|
||||
command: () => this.editor?.chain().focus().toggleBlockquote().run(),
|
||||
icon: icons.blockquote,
|
||||
isActive: (editor) => editor?.isActive('blockquote'),
|
||||
command: (editor) => editor?.chain().focus().toggleBlockquote().run(),
|
||||
},
|
||||
{
|
||||
name: 'code',
|
||||
icon: code,
|
||||
isActive: () => this.editor?.isActive('codeBlock'),
|
||||
command: () => this.editor?.chain().focus().toggleCodeBlock().run(),
|
||||
icon: icons.code,
|
||||
isActive: (editor) => editor?.isActive('codeBlock'),
|
||||
command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),
|
||||
},
|
||||
{
|
||||
name: 'bullet-list',
|
||||
icon: bulletList,
|
||||
isActive: () => this.editor?.isActive('bulletList'),
|
||||
command: () => this.editor?.chain().focus().toggleBulletList().run(),
|
||||
icon: icons.bulletList,
|
||||
isActive: (editor) => editor?.isActive('bulletList'),
|
||||
command: (editor) => editor?.chain().focus().toggleBulletList().run(),
|
||||
},
|
||||
{
|
||||
name: 'ordered-list',
|
||||
icon: orderedList,
|
||||
isActive: () => this.editor?.isActive('orderedList'),
|
||||
command: () => this.editor?.chain().focus().toggleOrderedList().run(),
|
||||
icon: icons.orderedList,
|
||||
isActive: (editor) => editor?.isActive('orderedList'),
|
||||
command: (editor) => editor?.chain().focus().toggleOrderedList().run(),
|
||||
},
|
||||
{
|
||||
name: 'horizontal-rule',
|
||||
icon: horizontalRule,
|
||||
isActive: () => this.editor?.isActive('horizontalRule'),
|
||||
command: () => this.editor?.chain().focus().setHorizontalRule().run(),
|
||||
icon: icons.horizontalRule,
|
||||
isActive: (editor) => editor?.isActive('horizontalRule'),
|
||||
command: (editor) => editor?.chain().focus().setHorizontalRule().run(),
|
||||
},
|
||||
{
|
||||
name: 'align-left',
|
||||
icon: alignLeft,
|
||||
isActive: () => this.editor?.isActive({ textAlign: 'left' }),
|
||||
command: () => this.editor?.chain().focus().setTextAlign('left').run(),
|
||||
icon: icons.alignLeft,
|
||||
isActive: (editor) => editor?.isActive({ textAlign: 'left' }),
|
||||
command: (editor) => editor?.chain().focus().setTextAlign('left').run(),
|
||||
},
|
||||
{
|
||||
name: 'align-center',
|
||||
icon: alignCenter,
|
||||
isActive: () => this.editor?.isActive({ textAlign: 'center' }),
|
||||
command: () => this.editor?.chain().focus().setTextAlign('center').run(),
|
||||
icon: icons.alignCenter,
|
||||
isActive: (editor) => editor?.isActive({ textAlign: 'center' }),
|
||||
command: (editor) => editor?.chain().focus().setTextAlign('center').run(),
|
||||
},
|
||||
{
|
||||
name: 'align-right',
|
||||
icon: alignRight,
|
||||
isActive: () => this.editor?.isActive({ textAlign: 'right' }),
|
||||
command: () => this.editor?.chain().focus().setTextAlign('right').run(),
|
||||
icon: icons.alignRight,
|
||||
isActive: (editor) => editor?.isActive({ textAlign: 'right' }),
|
||||
command: (editor) => editor?.chain().focus().setTextAlign('right').run(),
|
||||
},
|
||||
{
|
||||
name: 'align-justify',
|
||||
icon: alignJustify,
|
||||
isActive: () => this.editor?.isActive({ textAlign: 'justify' }),
|
||||
command: () => this.editor?.chain().focus().setTextAlign('justify').run(),
|
||||
icon: icons.alignJustify,
|
||||
isActive: (editor) => editor?.isActive({ textAlign: 'justify' }),
|
||||
command: (editor) => editor?.chain().focus().setTextAlign('justify').run(),
|
||||
},
|
||||
{
|
||||
name: 'link',
|
||||
icon: link,
|
||||
icon: icons.link,
|
||||
isActive: (editor) => editor?.isActive('link'),
|
||||
command: () => {
|
||||
const text = prompt('Enter the text');
|
||||
const url = prompt('Enter the URL');
|
||||
@@ -151,9 +136,6 @@ export class UmbTiptapFixedMenuElement extends LitElement {
|
||||
];
|
||||
|
||||
@property({ attribute: false })
|
||||
get editor() {
|
||||
return this.#editor;
|
||||
}
|
||||
set editor(value) {
|
||||
const oldValue = this.#editor;
|
||||
if (value === oldValue) {
|
||||
@@ -163,18 +145,36 @@ export class UmbTiptapFixedMenuElement extends LitElement {
|
||||
this.#editor?.on('selectionUpdate', this.#onUpdate);
|
||||
this.#editor?.on('update', this.#onUpdate);
|
||||
}
|
||||
get editor() {
|
||||
return this.#editor;
|
||||
}
|
||||
#editor?: Editor;
|
||||
|
||||
@property({ attribute: false })
|
||||
extensions: Array<UmbTiptapExtensionBase> = [];
|
||||
|
||||
#onUpdate = () => {
|
||||
this.requestUpdate();
|
||||
};
|
||||
|
||||
protected override firstUpdated() {
|
||||
const buttons = this.extensions.flatMap((ext) => ext.getToolbarButtons());
|
||||
this.actions.push(...buttons);
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
${this.actions.map(
|
||||
(action) => html`
|
||||
<button class=${action.isActive?.() ? 'active' : ''} @click=${action.command} title=${action.name}>
|
||||
${action.icon}
|
||||
<button
|
||||
class=${action.isActive?.(this.editor) ? 'active' : ''}
|
||||
title=${action.name}
|
||||
@click=${() => action.command(this.editor)}>
|
||||
${when(
|
||||
typeof action.icon === 'string',
|
||||
() => html`<umb-icon name=${action.icon}></umb-icon>`,
|
||||
() => action.icon,
|
||||
)}
|
||||
</button>
|
||||
`,
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { ManifestTiptapExtension } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<ManifestTiptapExtension> = [
|
||||
{
|
||||
type: 'tiptapExtension',
|
||||
alias: 'Umb.Tiptap.MediaPicker',
|
||||
name: 'Media Picker Tiptap Extension',
|
||||
api: () => import('./tiptap-mediapicker.extension.js'),
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,68 @@
|
||||
import { UmbTiptapExtensionBase } from '../components/input-tiptap/tiptap-extension.js';
|
||||
import { mergeAttributes, Node } from '@umbraco-cms/backoffice/external/tiptap';
|
||||
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
|
||||
import { UMB_MEDIA_PICKER_MODAL } from '@umbraco-cms/backoffice/media';
|
||||
|
||||
export default class UmbTiptapMediaPickerPlugin extends UmbTiptapExtensionBase {
|
||||
getExtensions() {
|
||||
return [
|
||||
Node.create({
|
||||
name: 'umbMediaPicker',
|
||||
group: 'block',
|
||||
marks: '',
|
||||
draggable: true,
|
||||
addNodeView() {
|
||||
return () => {
|
||||
//console.log('umb-media.addNodeView');
|
||||
const dom = document.createElement('umb-debug');
|
||||
dom.attributes.setNamedItem(document.createAttribute('visible'));
|
||||
dom.attributes.setNamedItem(document.createAttribute('dialog'));
|
||||
return { dom };
|
||||
};
|
||||
},
|
||||
parseHTML() {
|
||||
//console.log('umb-media.parseHTML');
|
||||
return [{ tag: 'umb-media' }];
|
||||
},
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
//console.log('umb-media.renderHTML');
|
||||
return ['umb-media', mergeAttributes(HTMLAttributes)];
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
getToolbarButtons() {
|
||||
return [
|
||||
{
|
||||
name: 'umb-media',
|
||||
icon: 'icon-picture',
|
||||
isActive: (editor?: Editor) => editor?.isActive('umbMediaPicker'),
|
||||
command: async (editor?: Editor) => {
|
||||
//console.log('umb-media.command', editor);
|
||||
|
||||
const selection = await this.#openMediaPicker();
|
||||
if (!selection || !selection.length) return;
|
||||
|
||||
editor?.chain().focus().insertContent(`<umb-media>${selection}</umb-media>`).run();
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async #openMediaPicker() {
|
||||
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
|
||||
const modalHandler = modalManager?.open(this, UMB_MEDIA_PICKER_MODAL, {
|
||||
data: { multiple: false },
|
||||
value: { selection: [] },
|
||||
});
|
||||
|
||||
if (!modalHandler) return;
|
||||
|
||||
const { selection } = await modalHandler.onSubmit().catch(() => ({ selection: undefined }));
|
||||
|
||||
//console.log('umb-media.selection', selection);
|
||||
return selection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './components/index.js';
|
||||
@@ -1,4 +1,5 @@
|
||||
import { manifests as extensions } from './extensions/manifests.js';
|
||||
import { manifests as propertyEditors } from './property-editors/manifests.js';
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<ManifestTypes> = [...propertyEditors];
|
||||
export const manifests: Array<ManifestTypes> = [...extensions, ...propertyEditors];
|
||||
|
||||
@@ -4,13 +4,13 @@ export const manifests: Array<ManifestTypes> = [
|
||||
{
|
||||
type: 'propertyEditorUi',
|
||||
alias: 'Umb.PropertyEditorUi.Tiptap',
|
||||
name: 'Tiptap Property Editor UI',
|
||||
name: 'Rich Text Editor [Tiptap] Property Editor UI',
|
||||
element: () => import('./property-editor-ui-tiptap.element.js'),
|
||||
meta: {
|
||||
label: 'Tiptap Editor',
|
||||
propertyEditorSchemaAlias: 'Umbraco.Plain.Json',
|
||||
icon: 'icon-document',
|
||||
group: 'richText',
|
||||
label: 'Rich Text Editor [Tiptap]',
|
||||
propertyEditorSchemaAlias: 'Umbraco.RichText',
|
||||
icon: 'icon-browser-window',
|
||||
group: 'richContent',
|
||||
settings: {
|
||||
properties: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user