From 6b1d80cedea6fda3822e60527adf4ef740aa4e91 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 26 Sep 2024 13:58:47 +0200
Subject: [PATCH 1/4] feat: add support for providing preconfigured altText and
caption to media-caption modal
---
.../media-caption-alt-text-modal.element.ts | 22 +++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-caption-alt-text/media-caption-alt-text-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-caption-alt-text/media-caption-alt-text-modal.element.ts
index adb87d2e7d..40581dd0a5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-caption-alt-text/media-caption-alt-text-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-caption-alt-text/media-caption-alt-text-modal.element.ts
@@ -27,7 +27,7 @@ export class UmbMediaCaptionAltTextModalElement extends UmbModalBaseElement<
const { data } = await this.#mediaDetailRepository.requestByUnique(this.#mediaUnique);
if (!data) return;
- this.value = { altText: data.variants[0].name, caption: undefined, url: data.urls[0]?.url ?? '' };
+ this.value = { ...this.value, altText: this.value.altText ?? data.variants[0].name, url: data.urls[0]?.url ?? '' };
}
override render() {
@@ -46,11 +46,14 @@ export class UmbMediaCaptionAltTextModalElement extends UmbModalBaseElement<
(this.value = { ...this.value, caption: e.target.value as string })}>
-
- ${this.value?.caption ?? ''}
+
+
+ ${this.value?.caption ?? ''}
+
@@ -64,7 +67,7 @@ export class UmbMediaCaptionAltTextModalElement extends UmbModalBaseElement<
`;
}
- static override styles = [
+ static override readonly styles = [
css`
uui-input {
margin-bottom: var(--uui-size-layout-1);
@@ -74,6 +77,17 @@ export class UmbMediaCaptionAltTextModalElement extends UmbModalBaseElement<
display: flex;
flex-direction: column;
}
+
+ #mainobject {
+ display: flex;
+ flex-direction: column;
+ max-width: 100%;
+
+ img {
+ max-width: 100%;
+ height: auto;
+ }
+ }
`,
];
}
From 422b89c0e7d6bac9652c8926831fb1341f8fb137 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 26 Sep 2024 13:59:33 +0200
Subject: [PATCH 2/4] feat: adds support for figure and figcaption
---
.../extensions/tiptap-figcaption.extension.ts | 40 ++++++++++++++
.../extensions/tiptap-figure.extension.ts | 52 +++++++++++++++++++
.../src/external/tiptap/index.ts | 2 +
.../extensions/core/figure.extension.ts | 6 +++
.../rte/tiptap/extensions/core/manifests.ts | 12 +++++
5 files changed, 112 insertions(+)
create mode 100644 src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figcaption.extension.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figure.extension.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/figure.extension.ts
diff --git a/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figcaption.extension.ts b/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figcaption.extension.ts
new file mode 100644
index 0000000000..23b188b7bf
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figcaption.extension.ts
@@ -0,0 +1,40 @@
+import { Node } from '@tiptap/core';
+
+export interface FigcaptionOptions {
+ /**
+ * HTML attributes to add to the image element.
+ * @default {}
+ * @example { class: 'foo' }
+ */
+ HTMLAttributes: Record
;
+}
+
+export const Figcaption = Node.create({
+ name: 'figcaption',
+
+ addOptions() {
+ return {
+ HTMLAttributes: {},
+ };
+ },
+
+ group: 'block',
+
+ content: 'inline*',
+
+ selectable: false,
+
+ draggable: false,
+
+ parseHTML() {
+ return [
+ {
+ tag: 'figcaption',
+ },
+ ];
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return [this.name, HTMLAttributes, 0];
+ },
+});
diff --git a/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figure.extension.ts b/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figure.extension.ts
new file mode 100644
index 0000000000..0cae9f7b47
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figure.extension.ts
@@ -0,0 +1,52 @@
+import { mergeAttributes, Node } from '@tiptap/core';
+
+export interface FigureOptions {
+ /**
+ * HTML attributes to add to the image element.
+ * @default {}
+ * @example { class: 'foo' }
+ */
+ HTMLAttributes: Record;
+}
+
+export const Figure = Node.create({
+ name: 'figure',
+ group: 'block',
+ content: 'block+',
+ draggable: true,
+ selectable: true,
+ isolating: true,
+ atom: true,
+
+ addAttributes() {
+ return {
+ figcaption: {
+ default: '',
+ },
+ };
+ },
+
+ addOptions() {
+ return {
+ HTMLAttributes: {},
+ };
+ },
+
+ parseHTML() {
+ return [
+ {
+ tag: 'figure',
+ getAttrs: (dom) => {
+ const figcaption = dom.querySelector('figcaption');
+ return {
+ figcaption: figcaption?.textContent || '',
+ };
+ },
+ },
+ ];
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return [this.name, mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
+ },
+});
diff --git a/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts b/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts
index 5c6fabf333..a2c146f446 100644
--- a/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts
@@ -24,4 +24,6 @@ export { TextAlign } from '@tiptap/extension-text-align';
export { Underline } from '@tiptap/extension-underline';
export { Image } from '@tiptap/extension-image';
// CUSTOM EXTENSIONS
+export * from './extensions/tiptap-figcaption.extension.js';
+export * from './extensions/tiptap-figure.extension.js';
export * from './extensions/tiptap-umb-image.extension.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/figure.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/figure.extension.ts
new file mode 100644
index 0000000000..1da6bdec35
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/figure.extension.ts
@@ -0,0 +1,6 @@
+import { UmbTiptapExtensionApiBase } from '../types.js';
+import { Figure, Figcaption } from '@umbraco-cms/backoffice/external/tiptap';
+
+export default class UmbTiptapFigureExtensionApi extends UmbTiptapExtensionApiBase {
+ getTiptapExtensions = () => [Figcaption, Figure];
+}
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
index 9ef58cd081..b4c0961f2b 100644
--- 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
@@ -53,6 +53,18 @@ export const manifests: Array import('./figure.extension.js'),
+ weight: 955,
+ meta: {
+ alias: 'figure',
+ icon: 'icon-frame',
+ label: 'Figure',
+ },
+ },
{
type: 'tiptapExtension',
kind: 'button',
From 72d7093fbf7322c5844bb305388a5710d82a281d Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 26 Sep 2024 14:00:03 +0200
Subject: [PATCH 3/4] chore: rename umbImage to image
---
.../extensions/tiptap-umb-image.extension.ts | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-umb-image.extension.ts b/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-umb-image.extension.ts
index fb3d645b4e..81807bc9ad 100644
--- a/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-umb-image.extension.ts
+++ b/src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-umb-image.extension.ts
@@ -1,7 +1,19 @@
import Image from '@tiptap/extension-image';
+export interface UmbImageAttributes {
+ src: string;
+ alt?: string;
+ title?: string;
+ width?: string;
+ height?: string;
+ loading?: string;
+ srcset?: string;
+ sizes?: string;
+ 'data-tmpimg'?: string;
+ 'data-udi'?: string;
+}
+
export const UmbImage = Image.extend({
- name: 'umbImage',
addAttributes() {
return {
...this.parent?.(),
@@ -22,7 +34,6 @@ export const UmbImage = Image.extend({
},
'data-tmpimg': { default: null },
'data-udi': { default: null },
- 'data-caption': { default: null },
};
},
});
@@ -38,19 +49,7 @@ declare module '@tiptap/core' {
* .commands
* .setImage({ src: 'https://tiptap.dev/logo.png', alt: 'tiptap', title: 'tiptap logo' })
*/
- setImage: (options: {
- src: string;
- alt?: string;
- title?: string;
- width?: string;
- height?: string;
- loading?: string;
- srcset?: string;
- sizes?: string;
- 'data-tmpimg'?: string;
- 'data-udi'?: string;
- 'data-caption'?: string;
- }) => ReturnType;
+ setImage: (options: UmbImageAttributes) => ReturnType;
};
}
}
From a7e93e82bb6df7e0d2ec2e6ed8ee1e2749ffa7cf Mon Sep 17 00:00:00 2001
From: leekelleher
Date: Thu, 26 Sep 2024 10:23:29 +0100
Subject: [PATCH 4/4] Tiptap extension: Table
---
src/Umbraco.Web.UI.Client/package-lock.json | 53 ++++++++++++++++
src/Umbraco.Web.UI.Client/package.json | 4 ++
.../src/external/tiptap/index.ts | 12 +++-
.../core/icon-registry/icon-dictionary.json | 4 ++
.../src/packages/core/icon-registry/icons.ts | 4 ++
.../core/icon-registry/icons/icon-table.ts | 17 ++++++
.../input-tiptap/input-tiptap.element.ts | 61 +++++++++++++++++++
.../rte/tiptap/extensions/core/manifests.ts | 13 ++++
.../tiptap/extensions/core/table.extension.ts | 11 ++++
9 files changed, 176 insertions(+), 3 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-table.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/table.extension.ts
diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json
index 24c064470c..d1233645ab 100644
--- a/src/Umbraco.Web.UI.Client/package-lock.json
+++ b/src/Umbraco.Web.UI.Client/package-lock.json
@@ -32,6 +32,10 @@
"@tiptap/extension-ordered-list": "^2.7.0",
"@tiptap/extension-paragraph": "^2.7.0",
"@tiptap/extension-strike": "^2.7.0",
+ "@tiptap/extension-table": "^2.7.3",
+ "@tiptap/extension-table-cell": "^2.7.3",
+ "@tiptap/extension-table-header": "^2.7.3",
+ "@tiptap/extension-table-row": "^2.7.3",
"@tiptap/extension-text": "^2.7.0",
"@tiptap/extension-text-align": "^2.6.6",
"@tiptap/extension-underline": "^2.6.6",
@@ -6731,6 +6735,55 @@
"@tiptap/core": "^2.7.0-pre.0"
}
},
+ "node_modules/@tiptap/extension-table": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-2.7.3.tgz",
+ "integrity": "sha512-zv1SGgVywTY3vs+9EIMdYS7jZMovlfsraZ3Qdz1YkqN3dNZBUukXrfpZaJqzVwUvRehCVvjA+HG7zH12RU/XYQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.7.0",
+ "@tiptap/pm": "^2.7.0"
+ }
+ },
+ "node_modules/@tiptap/extension-table-cell": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table-cell/-/extension-table-cell-2.7.3.tgz",
+ "integrity": "sha512-C6f2dAcatk/XROZ2Q1owv4DBrTyfVzfsK1Jh7rk3mkpEa8oh/lPKR8thYjmaLC/BlPYjtVuIbMIqp9lz6U/Ufw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.7.0"
+ }
+ },
+ "node_modules/@tiptap/extension-table-header": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table-header/-/extension-table-header-2.7.3.tgz",
+ "integrity": "sha512-eL1FVn+GBf0dRYmsE88QeJa3azwVKhyYDAFTmoGIwilHsjbNzb4ptUGi+ko2XpxLHvY+XfGLe3+UEZbQ3FDOIA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.7.0"
+ }
+ },
+ "node_modules/@tiptap/extension-table-row": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table-row/-/extension-table-row-2.7.3.tgz",
+ "integrity": "sha512-gB6gXYVCGWn6IDb/oV3ds1LI0yLLIwymcvcu1MWnT9p8qClZPaId/J6/+mQbSGCEc8G1SzYYUhnu2dsaVIsFsw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.7.0"
+ }
+ },
"node_modules/@tiptap/extension-text": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.7.0.tgz",
diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json
index d058a21df1..d50b98524f 100644
--- a/src/Umbraco.Web.UI.Client/package.json
+++ b/src/Umbraco.Web.UI.Client/package.json
@@ -212,6 +212,10 @@
"@tiptap/extension-ordered-list": "^2.7.0",
"@tiptap/extension-paragraph": "^2.7.0",
"@tiptap/extension-strike": "^2.7.0",
+ "@tiptap/extension-table": "^2.7.3",
+ "@tiptap/extension-table-cell": "^2.7.3",
+ "@tiptap/extension-table-header": "^2.7.3",
+ "@tiptap/extension-table-row": "^2.7.3",
"@tiptap/extension-text": "^2.7.0",
"@tiptap/extension-text-align": "^2.6.6",
"@tiptap/extension-underline": "^2.6.6",
diff --git a/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts b/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts
index a2c146f446..e186f0ccf3 100644
--- a/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/external/tiptap/index.ts
@@ -1,4 +1,4 @@
-// REQUIRED EXTENSIONS START
+// REQUIRED EXTENSIONS
export * from '@tiptap/core';
export { Document } from '@tiptap/extension-document';
export { Dropcursor } from '@tiptap/extension-dropcursor';
@@ -7,7 +7,8 @@ export { HardBreak } from '@tiptap/extension-hard-break';
export { History } from '@tiptap/extension-history';
export { Paragraph } from '@tiptap/extension-paragraph';
export { Text } from '@tiptap/extension-text';
-// REQUIRED EXTENSIONS END
+
+// OPTIONAL EXTENSIONS
export { Blockquote } from '@tiptap/extension-blockquote';
export { Bold } from '@tiptap/extension-bold';
export { BulletList } from '@tiptap/extension-bullet-list';
@@ -15,14 +16,19 @@ export { Code } from '@tiptap/extension-code';
export { CodeBlock } from '@tiptap/extension-code-block';
export { Heading } from '@tiptap/extension-heading';
export { HorizontalRule } from '@tiptap/extension-horizontal-rule';
+export { Image } from '@tiptap/extension-image';
export { Italic } from '@tiptap/extension-italic';
export { Link } from '@tiptap/extension-link';
export { ListItem } from '@tiptap/extension-list-item';
export { OrderedList } from '@tiptap/extension-ordered-list';
export { Strike } from '@tiptap/extension-strike';
+export { Table } from '@tiptap/extension-table';
+export { TableCell } from '@tiptap/extension-table-cell';
+export { TableHeader } from '@tiptap/extension-table-header';
+export { TableRow } from '@tiptap/extension-table-row';
export { TextAlign } from '@tiptap/extension-text-align';
export { Underline } from '@tiptap/extension-underline';
-export { Image } from '@tiptap/extension-image';
+
// CUSTOM EXTENSIONS
export * from './extensions/tiptap-figcaption.extension.js';
export * from './extensions/tiptap-figure.extension.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json
index 4d592bfb10..9c53e18410 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json
@@ -1982,6 +1982,10 @@
"name": "icon-tab-key",
"file": "arrow-right-to-line.svg"
},
+ {
+ "name": "icon-table",
+ "file": "table.svg"
+ },
{
"name": "icon-tag",
"file": "tag.svg"
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts
index 3139743a15..1f55c16a7f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts
@@ -1867,6 +1867,10 @@ name: "icon-tab-key",
path: () => import("./icons/icon-tab-key.js"),
},{
+name: "icon-table",
+
+path: () => import("./icons/icon-table.js"),
+},{
name: "icon-tag",
path: () => import("./icons/icon-tag.js"),
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-table.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-table.ts
new file mode 100644
index 0000000000..283a8a901c
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-table.ts
@@ -0,0 +1,17 @@
+export default `
+
+`;
\ No newline at end of file
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 85e18d8a67..d6e9872427 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
@@ -180,6 +180,67 @@ export class UmbInputTiptapElement extends UmbFormControlMixin * {
+ margin-bottom: 0;
+ }
+ }
+
+ th {
+ background-color: var(--uui-color-background);
+ font-weight: bold;
+ text-align: left;
+ }
+
+ .selectedCell:after {
+ background: var(--uui-color-surface-emphasis);
+ content: '';
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ pointer-events: none;
+ position: absolute;
+ z-index: 2;
+ }
+
+ .column-resize-handle {
+ background-color: var(--uui-color-default);
+ bottom: -2px;
+ pointer-events: none;
+ position: absolute;
+ right: -2px;
+ top: 0;
+ width: 3px;
+ }
+ }
+ }
+
+ .resize-cursor {
+ cursor: ew-resize;
+ cursor: col-resize;
+ }
}
`,
];
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
index b4c0961f2b..309598a14f 100644
--- 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
@@ -165,6 +165,19 @@ export const manifests: Array import('./table.extension.js'),
+ weight: 909,
+ meta: {
+ alias: 'table',
+ icon: 'icon-table',
+ label: 'Table',
+ },
+ },
{
type: 'tiptapExtension',
kind: 'button',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/table.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/table.extension.ts
new file mode 100644
index 0000000000..ae2d71fa73
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/extensions/core/table.extension.ts
@@ -0,0 +1,11 @@
+import { UmbTiptapToolbarElementApiBase } from '../types.js';
+import { Table, TableHeader, TableRow, TableCell } from '@umbraco-cms/backoffice/external/tiptap';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+export default class UmbTiptapTableExtensionApi extends UmbTiptapToolbarElementApiBase {
+ getTiptapExtensions = () => [Table.configure({ resizable: true }), TableHeader, TableRow, TableCell];
+
+ override execute(editor?: Editor) {
+ editor?.commands.insertTable({ rows: 3, cols: 3, withHeaderRow: true });
+ }
+}