diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/icon.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/icon.registry.ts
new file mode 100644
index 0000000000..996fc4482b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/icon.registry.ts
@@ -0,0 +1,81 @@
+import { UmbIconRegistry } from '@umbraco-cms/backoffice/icon';
+
+export class UmbTiptapIconRegistry extends UmbIconRegistry {
+ constructor() {
+ super();
+
+ this.defineIcon(
+ 'bold',
+ ``,
+ );
+
+ this.defineIcon(
+ 'italic',
+ ``,
+ );
+ this.defineIcon(
+ 'underline',
+ ``,
+ );
+ this.defineIcon(
+ 'strike',
+ ``,
+ );
+ this.defineIcon(
+ 'heading1',
+ ``,
+ );
+ this.defineIcon(
+ 'heading2',
+ ``,
+ );
+ this.defineIcon(
+ 'heading3',
+ ``,
+ );
+ this.defineIcon(
+ 'blockquote',
+ ``,
+ );
+ this.defineIcon(
+ 'code-block',
+ ``,
+ );
+ this.defineIcon(
+ 'bullet-list',
+ ``,
+ );
+ this.defineIcon(
+ 'ordered-list',
+ ``,
+ );
+ this.defineIcon(
+ 'horizontal-rule',
+ ``,
+ );
+ this.defineIcon(
+ 'text-align-left',
+ ``,
+ );
+ this.defineIcon(
+ 'text-align-center',
+ ``,
+ );
+ this.defineIcon(
+ 'text-align-right',
+ ``,
+ );
+ this.defineIcon(
+ 'text-align-justify',
+ ``,
+ );
+ this.defineIcon(
+ 'link',
+ ``,
+ );
+ this.defineIcon(
+ 'umbraco',
+ ``,
+ );
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/icons.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/icons.ts
deleted file mode 100644
index 2676404411..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/icons.ts
+++ /dev/null
@@ -1,268 +0,0 @@
-import { html } from '@umbraco-cms/backoffice/external/lit';
-
-const iconSize = '16px';
-export const bold = html``;
-
-export const italic = html``;
-
-export const underline = html``;
-
-export const strikethrough = html``;
-export const heading1 = html``;
-export const heading2 = html``;
-export const heading3 = html``;
-export const blockquote = html``;
-export const code = html``;
-export const bulletList = html``;
-export const orderedList = html``;
-export const horizontalRule = html``;
-export const alignLeft = html``;
-export const alignCenter = html``;
-export const alignRight = html``;
-export const alignJustify = html``;
-
-export const link = html``;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
index 4bb0a53188..095567fd41 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
@@ -3,28 +3,14 @@ import { css, customElement, html, property, state, when } from '@umbraco-cms/ba
import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import {
- Blockquote,
- Bold,
- BulletList,
- Code,
- CodeBlock,
Document,
Dropcursor,
Editor,
Gapcursor,
HardBreak,
- Heading,
History,
- HorizontalRule,
- Italic,
- Link,
- ListItem,
- OrderedList,
Paragraph,
- Strike,
Text,
- TextAlign,
- Underline,
} from '@umbraco-cms/backoffice/external/tiptap';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
@@ -83,26 +69,7 @@ export class UmbInputTiptapElement extends UmbFormControlMixin {
this.value = editor.getHTML();
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
index 1567febabb..39e75dc1b8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
@@ -1,7 +1,6 @@
-import type { UmbTiptapToolbarButton } from '../../extensions/types.js';
import type { ManifestTiptapExtension } from '../../extensions/tiptap-extension.js';
-import * as icons from './icons.js';
-import { css, customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit';
+import { UmbTiptapIconRegistry } from './icon.registry.js';
+import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
@@ -10,135 +9,6 @@ export class UmbTiptapFixedMenuElement extends UmbLitElement {
@property({ type: Boolean, reflect: true })
readonly = false;
- @state()
- actions: Array = [
- // TODO: I don't think we need a paragraph button. It's the default state.
- // {
- // name: 'paragraph',
- // icon: html``,
- // command: (editor) => editor?.chain().focus().setParagraph().run(),
- // },
- {
- name: 'bold',
- icon: icons.bold,
- isActive: (editor) => editor?.isActive('bold'),
- command: (editor) => editor?.chain().focus().toggleBold().run(),
- },
- {
- name: 'italic',
- icon: icons.italic,
- isActive: (editor) => editor?.isActive('italic'),
- command: (editor) => editor?.chain().focus().toggleItalic().run(),
- },
- {
- name: 'underline',
- icon: icons.underline,
- isActive: (editor) => editor?.isActive('underline'),
- command: (editor) => editor?.chain().focus().toggleUnderline().run(),
- },
- {
- name: 'strikethrough',
- icon: icons.strikethrough,
- isActive: (editor) => editor?.isActive('strike'),
- command: (editor) => editor?.chain().focus().toggleStrike().run(),
- },
- {
- name: 'h1',
- icon: icons.heading1,
- isActive: (editor) => editor?.isActive('heading', { level: 1 }),
- command: (editor) => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
- },
- {
- name: 'h2',
- icon: icons.heading2,
- isActive: (editor) => editor?.isActive('heading', { level: 2 }),
- command: (editor) => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
- },
- {
- name: 'h3',
- icon: icons.heading3,
- isActive: (editor) => editor?.isActive('heading', { level: 3 }),
- command: (editor) => editor?.chain().focus().toggleHeading({ level: 3 }).run(),
- },
- {
- name: 'blockquote',
- icon: icons.blockquote,
- isActive: (editor) => editor?.isActive('blockquote'),
- command: (editor) => editor?.chain().focus().toggleBlockquote().run(),
- },
- {
- name: 'code',
- icon: icons.code,
- isActive: (editor) => editor?.isActive('codeBlock'),
- command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),
- },
- {
- name: 'bullet-list',
- icon: icons.bulletList,
- isActive: (editor) => editor?.isActive('bulletList'),
- command: (editor) => editor?.chain().focus().toggleBulletList().run(),
- },
- {
- name: 'ordered-list',
- icon: icons.orderedList,
- isActive: (editor) => editor?.isActive('orderedList'),
- command: (editor) => editor?.chain().focus().toggleOrderedList().run(),
- },
- {
- name: 'horizontal-rule',
- icon: icons.horizontalRule,
- isActive: (editor) => editor?.isActive('horizontalRule'),
- command: (editor) => editor?.chain().focus().setHorizontalRule().run(),
- },
- {
- name: 'align-left',
- icon: icons.alignLeft,
- isActive: (editor) => editor?.isActive({ textAlign: 'left' }),
- command: (editor) => editor?.chain().focus().setTextAlign('left').run(),
- },
- {
- name: 'align-center',
- icon: icons.alignCenter,
- isActive: (editor) => editor?.isActive({ textAlign: 'center' }),
- command: (editor) => editor?.chain().focus().setTextAlign('center').run(),
- },
- {
- name: 'align-right',
- icon: icons.alignRight,
- isActive: (editor) => editor?.isActive({ textAlign: 'right' }),
- command: (editor) => editor?.chain().focus().setTextAlign('right').run(),
- },
- {
- name: 'align-justify',
- icon: icons.alignJustify,
- isActive: (editor) => editor?.isActive({ textAlign: 'justify' }),
- command: (editor) => editor?.chain().focus().setTextAlign('justify').run(),
- },
- {
- name: 'link',
- icon: icons.link,
- isActive: (editor) => editor?.isActive('link'),
- command: () => {
- const text = prompt('Enter the text');
- const url = prompt('Enter the URL');
-
- if (url && text && this.editor) {
- const { from } = this.editor.state.selection;
- this.editor
- .chain()
- .focus()
- .insertContent(text)
- .setTextSelection({ from: from, to: from + text.length })
- .setLink({ href: url, target: '_blank' })
- .run();
- }
- },
- },
- ];
-
@property({ attribute: false })
set editor(value) {
const oldValue = this.#editor;
@@ -158,22 +28,15 @@ export class UmbTiptapFixedMenuElement extends UmbLitElement {
this.requestUpdate();
};
+ #registry = new UmbTiptapIconRegistry();
+
+ constructor() {
+ super();
+ this.#registry.attach(this);
+ }
+
override render() {
return html`
- ${this.actions.map(
- (action) => html`
-
- `,
- )}
!!ext.kind || !!ext.element}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts
index 28c9feb62e..30f1458cb7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts
@@ -24,7 +24,6 @@ export class UmbTiptapHoverMenuElement extends LitElement {
}
#onUpdate = () => {
- console.log('LINK ACTIVE');
if (this.editor?.isActive('link')) {
// show the popover
this.showPopover();
@@ -34,7 +33,6 @@ export class UmbTiptapHoverMenuElement extends LitElement {
};
override render() {
- console.log('RENDER HOVER MENU');
return html``;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/blockquote.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/blockquote.extension.ts
new file mode 100644
index 0000000000..101299b5fb
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/blockquote.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Blockquote } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Blockquote',
+ name: 'Blockquote Tiptap Extension',
+ api: () => import('./blockquote.extension.js'),
+ weight: 995,
+ meta: {
+ alias: 'blockquote',
+ icon: 'blockquote',
+ label: 'Blockquote',
+ },
+};
+
+export default class UmbTiptapBlockquotePlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Blockquote];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleBlockquote().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/bold.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/bold.extension.ts
new file mode 100644
index 0000000000..6524e15b04
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/bold.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Bold } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Bold',
+ name: 'Bold Tiptap Extension',
+ api: () => import('./bold.extension.js'),
+ weight: 999,
+ meta: {
+ alias: 'bold',
+ icon: 'bold',
+ label: 'Bold',
+ },
+};
+
+export default class UmbTiptapBoldPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Bold];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleBold().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/bullet-list.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/bullet-list.extension.ts
new file mode 100644
index 0000000000..853cbb202f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/bullet-list.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { BulletList, ListItem } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.BulletList',
+ name: 'Bullet List Tiptap Extension',
+ api: () => import('./bullet-list.extension.js'),
+ weight: 993,
+ meta: {
+ alias: 'bullet-list',
+ icon: 'bullet-list',
+ label: 'Bullet List',
+ },
+};
+
+export default class UmbTiptapBulletListPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [BulletList, ListItem];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleBulletList().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/code-block.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/code-block.extension.ts
new file mode 100644
index 0000000000..42dea9c02f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/code-block.extension.ts
@@ -0,0 +1,27 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Code, CodeBlock } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.CodeBlock',
+ name: 'Code Block Tiptap Extension',
+ api: () => import('./code-block.extension.js'),
+ weight: 994,
+ meta: {
+ alias: 'code-block',
+ icon: 'code-block',
+ label: 'Code Block',
+ },
+};
+
+export default class UmbTiptapCodePlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Code, CodeBlock];
+
+ override execute(editor?: Editor) {
+ // editor.chain().focus().toggleCode().run();
+ editor?.chain().focus().toggleCodeBlock().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading1.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading1.extension.ts
new file mode 100644
index 0000000000..6f1ac09400
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading1.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Heading } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Heading1',
+ name: 'Heading 1 Tiptap Extension',
+ api: () => import('./heading1.extension.js'),
+ weight: 949,
+ meta: {
+ alias: 'heading1',
+ icon: 'heading1',
+ label: 'Heading 1',
+ },
+};
+
+export default class UmbTiptapHeading1Plugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Heading];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleHeading({ level: 1 }).run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading2.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading2.extension.ts
new file mode 100644
index 0000000000..8f7ad839b2
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading2.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Heading } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Heading2',
+ name: 'Heading 2 Tiptap Extension',
+ api: () => import('./heading2.extension.js'),
+ weight: 948,
+ meta: {
+ alias: 'heading2',
+ icon: 'heading2',
+ label: 'Heading 2',
+ },
+};
+
+export default class UmbTiptapHeading1Plugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Heading];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleHeading({ level: 2 }).run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading3.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading3.extension.ts
new file mode 100644
index 0000000000..f1d11a912e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/heading3.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Heading } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Heading3',
+ name: 'Heading 3 Tiptap Extension',
+ api: () => import('./heading3.extension.js'),
+ weight: 947,
+ meta: {
+ alias: 'heading3',
+ icon: 'heading3',
+ label: 'Heading 3',
+ },
+};
+
+export default class UmbTiptapHeading1Plugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Heading];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleHeading({ level: 3 }).run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/horizontal-rule.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/horizontal-rule.extension.ts
new file mode 100644
index 0000000000..4e29557f2a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/horizontal-rule.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { HorizontalRule } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.HorizontalRule',
+ name: 'Horizontal Rule Tiptap Extension',
+ api: () => import('./horizontal-rule.extension.js'),
+ weight: 991,
+ meta: {
+ alias: 'horizontal-rule',
+ icon: 'horizontal-rule',
+ label: 'Horizontal Rule',
+ },
+};
+
+export default class UmbTiptapHorizontalRulePlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [HorizontalRule];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().setHorizontalRule().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/image.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/image.extension.ts
new file mode 100644
index 0000000000..1bd069617f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/image.extension.ts
@@ -0,0 +1,17 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { UmbImage } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ alias: 'Umb.Tiptap.Image',
+ name: 'Image Tiptap Extension',
+ api: () => import('./image.extension.js'),
+ meta: {},
+};
+
+export default class UmbTiptapImageExtension extends UmbTiptapExtensionApi {
+ getTiptapExtensions() {
+ return [UmbImage.configure({ inline: true })];
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/italic.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/italic.extension.ts
new file mode 100644
index 0000000000..2343355c08
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/italic.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Italic } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Italic',
+ name: 'Italic Tiptap Extension',
+ api: () => import('./italic.extension.js'),
+ weight: 998,
+ meta: {
+ alias: 'italic',
+ icon: 'italic',
+ label: 'Italic',
+ },
+};
+
+export default class UmbTiptapItalicPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Italic];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleItalic().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/manifests.ts
new file mode 100644
index 0000000000..f45ce80e1b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/manifests.ts
@@ -0,0 +1,38 @@
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { manifest as blockquote } from './blockquote.extension.js';
+import { manifest as bold } from './bold.extension.js';
+import { manifest as bulletList } from './bullet-list.extension.js';
+import { manifest as codeBlock } from './code-block.extension.js';
+import { manifest as image } from './image.extension.js';
+import { manifest as italic } from './italic.extension.js';
+import { manifest as heading1 } from './heading1.extension.js';
+import { manifest as heading2 } from './heading2.extension.js';
+import { manifest as heading3 } from './heading3.extension.js';
+import { manifest as horizontalRule } from './horizontal-rule.extension.js';
+import { manifest as orderedList } from './ordered-list.extension.js';
+import { manifest as strike } from './strike.extension.js';
+import { manifest as textAlignLeft } from './text-align-left.extension.js';
+import { manifest as textAlignCenter } from './text-align-center.extension.js';
+import { manifest as textAlignRight } from './text-align-right.extension.js';
+import { manifest as textAlignJustify } from './text-align-justify.extension.js';
+import { manifest as underline } from './underline.extension.js';
+
+export const manifests: Array = [
+ blockquote,
+ bold,
+ bulletList,
+ codeBlock,
+ image,
+ italic,
+ heading1,
+ heading2,
+ heading3,
+ horizontalRule,
+ orderedList,
+ strike,
+ textAlignLeft,
+ textAlignCenter,
+ textAlignRight,
+ textAlignJustify,
+ underline,
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/ordered-list.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/ordered-list.extension.ts
new file mode 100644
index 0000000000..85e650e273
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/ordered-list.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { OrderedList, ListItem } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.OrderedList',
+ name: 'Ordered List Tiptap Extension',
+ api: () => import('./ordered-list.extension.js'),
+ weight: 992,
+ meta: {
+ alias: 'ordered-list',
+ icon: 'ordered-list',
+ label: 'Ordered List',
+ },
+};
+
+export default class UmbTiptapOrderedListPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [OrderedList, ListItem];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleOrderedList().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/strike.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/strike.extension.ts
new file mode 100644
index 0000000000..a3e5feb0a9
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/strike.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Strike } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Strike',
+ name: 'Strike Tiptap Extension',
+ api: () => import('./strike.extension.js'),
+ weight: 996,
+ meta: {
+ alias: 'strike',
+ icon: 'strike',
+ label: 'Strike',
+ },
+};
+
+export default class UmbTiptapStrikePlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Strike];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleStrike().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-center.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-center.extension.ts
new file mode 100644
index 0000000000..5e6caad8cd
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-center.extension.ts
@@ -0,0 +1,30 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { TextAlign } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.TextAlignCenter',
+ name: 'Text Align Center Tiptap Extension',
+ api: () => import('./text-align-center.extension.js'),
+ weight: 918,
+ meta: {
+ alias: 'text-align-center',
+ icon: 'text-align-center',
+ label: 'Text Align Center',
+ },
+};
+
+export default class UmbTiptapTextAlignCenterPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [
+ TextAlign.configure({
+ types: ['heading', 'paragraph', 'blockquote', 'orderedList', 'bulletList', 'codeBlock'],
+ }),
+ ];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().setTextAlign('center').run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-justify.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-justify.extension.ts
new file mode 100644
index 0000000000..0c021383b5
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-justify.extension.ts
@@ -0,0 +1,30 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { TextAlign } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.TextAlignJustify',
+ name: 'Text Align Justify Tiptap Extension',
+ api: () => import('./text-align-justify.extension.js'),
+ weight: 916,
+ meta: {
+ alias: 'text-align-justify',
+ icon: 'text-align-justify',
+ label: 'Text Align Justify',
+ },
+};
+
+export default class UmbTiptapTextAlignJustifyPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [
+ TextAlign.configure({
+ types: ['heading', 'paragraph', 'blockquote', 'orderedList', 'bulletList', 'codeBlock'],
+ }),
+ ];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().setTextAlign('justify').run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-left.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-left.extension.ts
new file mode 100644
index 0000000000..aedfbc2d85
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-left.extension.ts
@@ -0,0 +1,30 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { TextAlign } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.TextAlignLeft',
+ name: 'Text Align Left Tiptap Extension',
+ api: () => import('./text-align-left.extension.js'),
+ weight: 919,
+ meta: {
+ alias: 'text-align-left',
+ icon: 'text-align-left',
+ label: 'Text Align Left',
+ },
+};
+
+export default class UmbTiptapTextAlignLeftPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [
+ TextAlign.configure({
+ types: ['heading', 'paragraph', 'blockquote', 'orderedList', 'bulletList', 'codeBlock'],
+ }),
+ ];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().setTextAlign('left').run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-right.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-right.extension.ts
new file mode 100644
index 0000000000..049781dd1e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/text-align-right.extension.ts
@@ -0,0 +1,30 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { TextAlign } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.TextAlignRight',
+ name: 'Text Align Right Tiptap Extension',
+ api: () => import('./text-align-right.extension.js'),
+ weight: 917,
+ meta: {
+ alias: 'text-align-right',
+ icon: 'text-align-right',
+ label: 'Text Align Right',
+ },
+};
+
+export default class UmbTiptapTextAlignRightPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [
+ TextAlign.configure({
+ types: ['heading', 'paragraph', 'blockquote', 'orderedList', 'bulletList', 'codeBlock'],
+ }),
+ ];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().setTextAlign('right').run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/underline.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/underline.extension.ts
new file mode 100644
index 0000000000..52387b9b62
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/underline.extension.ts
@@ -0,0 +1,26 @@
+import { UmbTiptapExtensionApi } from '../types.js';
+import type { ManifestTiptapExtension } from '../tiptap-extension.js';
+import { Underline } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Underline',
+ name: 'Underline Tiptap Extension',
+ api: () => import('./underline.extension.js'),
+ weight: 997,
+ meta: {
+ alias: 'underline',
+ icon: 'underline',
+ label: 'Underline',
+ },
+};
+
+export default class UmbTiptapItalicPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [Underline];
+
+ override execute(editor?: Editor) {
+ editor?.chain().focus().toggleUnderline().run();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/embed.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/embed.extension.ts
new file mode 100644
index 0000000000..4967051267
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/embed.extension.ts
@@ -0,0 +1,25 @@
+import { UmbTiptapExtensionApi } from './types.js';
+import type { ManifestTiptapExtension } from './tiptap-extension.js';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.Embed',
+ name: 'Embed Tiptap Extension',
+ api: () => import('./embed.extension.js'),
+ meta: {
+ alias: 'umb-embed',
+ icon: 'umbraco',
+ label: 'Embed',
+ },
+};
+
+export default class UmbTiptapEmbedPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions = () => [];
+
+ override async execute(editor?: Editor) {
+ console.log('umb-embed.execute', editor);
+ // Research: https://github.com/ueberdosis/tiptap/tree/main/packages/extension-youtube
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/manifests.ts
index 8afb03e629..754fb3dcf1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/manifests.ts
@@ -1,4 +1,8 @@
import type { ManifestTiptapExtension } from './tiptap-extension.js';
+import { manifests as core } from './core/manifests.js';
+import { manifest as embed } from './embed.extension.js';
+import { manifest as mediaPicker } from './mediapicker.extension.js';
+import { manifest as urlPicker } from './urlpicker.extension.js';
import type { ManifestTypes, UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
const kinds: Array = [
@@ -13,28 +17,6 @@ const kinds: Array = [
},
];
-const extensions: Array = [
- {
- type: 'tiptapExtension',
- alias: 'Umb.Tiptap.Image',
- name: 'Image Tiptap Extension',
- weight: 1000,
- api: () => import('./tiptap-image.extension.js'),
- meta: {},
- },
- {
- type: 'tiptapExtension',
- kind: 'button',
- alias: 'Umb.Tiptap.MediaPicker',
- name: 'Media Picker Tiptap Extension',
- weight: 900,
- api: () => import('./tiptap-mediapicker.extension.js'),
- meta: {
- alias: 'umb-media',
- icon: 'icon-picture',
- label: 'Media picker',
- },
- },
-];
+const extensions: Array = [...core, embed, mediaPicker, urlPicker];
export const manifests: Array = [...kinds, ...extensions];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/tiptap-mediapicker.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/mediapicker.extension.ts
similarity index 83%
rename from src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/tiptap-mediapicker.extension.ts
rename to src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/mediapicker.extension.ts
index 7d96091761..ee3923cfa9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/tiptap-mediapicker.extension.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/mediapicker.extension.ts
@@ -1,9 +1,23 @@
import { UmbTiptapExtensionApi } from './types.js';
+import type { ManifestTiptapExtension } from './tiptap-extension.js';
import { mergeAttributes, Node } from '@umbraco-cms/backoffice/external/tiptap';
import { UMB_MEDIA_PICKER_MODAL } from '@umbraco-cms/backoffice/media';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.MediaPicker',
+ name: 'Media Picker Tiptap Extension',
+ api: () => import('./mediapicker.extension.js'),
+ meta: {
+ alias: 'umb-media',
+ icon: 'umbraco',
+ label: 'Media picker',
+ },
+};
+
export default class UmbTiptapMediaPickerPlugin extends UmbTiptapExtensionApi {
getTiptapExtensions() {
return [
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/tiptap-image.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/tiptap-image.extension.ts
deleted file mode 100644
index f6d64e11a2..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/tiptap-image.extension.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { UmbTiptapExtensionApi } from './types.js';
-import { UmbImage } from '@umbraco-cms/backoffice/external/tiptap';
-
-export default class UmbTiptapImageExtension extends UmbTiptapExtensionApi {
- getTiptapExtensions() {
- return [UmbImage.configure({ inline: true })];
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/urlpicker.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/urlpicker.extension.ts
new file mode 100644
index 0000000000..6f01aa8bcd
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/urlpicker.extension.ts
@@ -0,0 +1,41 @@
+import { UmbTiptapExtensionApi } from './types.js';
+import type { ManifestTiptapExtension } from './tiptap-extension.js';
+import { Link } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export const manifest: ManifestTiptapExtension = {
+ type: 'tiptapExtension',
+ kind: 'button',
+ alias: 'Umb.Tiptap.UrlPicker',
+ name: 'URL Picker Tiptap Extension',
+ api: () => import('./urlpicker.extension.js'),
+ meta: {
+ alias: 'umb-link',
+ icon: 'umbraco',
+ label: 'URL picker',
+ },
+};
+
+export default class UmbTiptapUrlPickerPlugin extends UmbTiptapExtensionApi {
+ getTiptapExtensions() {
+ return [Link.extend({ openOnClick: false })];
+ }
+
+ override async execute(editor?: Editor) {
+ console.log('umb-link.execute', editor);
+
+ const text = prompt('Enter the text');
+ const url = prompt('Enter the URL');
+
+ if (url && text && editor) {
+ const { from } = editor.state.selection;
+ editor
+ .chain()
+ .focus()
+ .insertContent(text)
+ .setTextSelection({ from: from, to: from + text.length })
+ .setLink({ href: url, target: '_blank' })
+ .run();
+ }
+ }
+}