Merge remote-tracking branch 'origin/v15/feature/tiptap' into v15/feature/rte/tiptap/ext/embed
This commit is contained in:
53
src/Umbraco.Web.UI.Client/package-lock.json
generated
53
src/Umbraco.Web.UI.Client/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
40
src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figcaption.extension.ts
vendored
Normal file
40
src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figcaption.extension.ts
vendored
Normal file
@@ -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<string, any>;
|
||||
}
|
||||
|
||||
export const Figcaption = Node.create<FigcaptionOptions>({
|
||||
name: 'figcaption',
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
HTMLAttributes: {},
|
||||
};
|
||||
},
|
||||
|
||||
group: 'block',
|
||||
|
||||
content: 'inline*',
|
||||
|
||||
selectable: false,
|
||||
|
||||
draggable: false,
|
||||
|
||||
parseHTML() {
|
||||
return [
|
||||
{
|
||||
tag: 'figcaption',
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return [this.name, HTMLAttributes, 0];
|
||||
},
|
||||
});
|
||||
52
src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figure.extension.ts
vendored
Normal file
52
src/Umbraco.Web.UI.Client/src/external/tiptap/extensions/tiptap-figure.extension.ts
vendored
Normal file
@@ -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<string, any>;
|
||||
}
|
||||
|
||||
export const Figure = Node.create<FigureOptions>({
|
||||
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];
|
||||
},
|
||||
});
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,21 @@ 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-umb-embedded-media.extension.js';
|
||||
export * from './extensions/tiptap-figcaption.extension.js';
|
||||
export * from './extensions/tiptap-figure.extension.js';
|
||||
export * from './extensions/tiptap-umb-image.extension.js';
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export default `<!-- @license lucide-static v0.446.0 - ISC -->
|
||||
<svg
|
||||
class="lucide lucide-table"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.75"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M12 3v18" />
|
||||
<rect width="18" height="18" x="3" y="3" rx="2" />
|
||||
<path d="M3 9h18" />
|
||||
<path d="M3 15h18" />
|
||||
</svg>
|
||||
`;
|
||||
@@ -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<
|
||||
<uui-input
|
||||
id="caption"
|
||||
label="caption"
|
||||
.value=${this.value?.caption ?? ''}
|
||||
@input=${(e: UUIInputEvent) =>
|
||||
(this.value = { ...this.value, caption: e.target.value as string })}></uui-input>
|
||||
|
||||
<img src=${this.value?.url ?? ''} alt=${this.value?.altText ?? ''} />
|
||||
${this.value?.caption ?? ''}
|
||||
<figure id="mainobject">
|
||||
<img src=${this.value?.url ?? ''} alt=${this.value?.altText ?? ''} />
|
||||
<figcaption>${this.value?.caption ?? ''}</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div slot="actions">
|
||||
<uui-button label=${this.localize.term('general_close')} @click=${this._rejectModal}></uui-button>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -205,6 +205,65 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
|
||||
|
||||
.umb-embed-holder.ProseMirror-selectednode::before {
|
||||
background: rgba(0, 0, 0, 0.025);
|
||||
/* Table-specific styling */
|
||||
.tableWrapper {
|
||||
margin: 1.5rem 0;
|
||||
overflow-x: auto;
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
|
||||
td,
|
||||
th {
|
||||
border: 1px solid var(--uui-color-border);
|
||||
box-sizing: border-box;
|
||||
min-width: 1em;
|
||||
padding: 6px 8px;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
|
||||
> * {
|
||||
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;
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -53,6 +53,18 @@ export const manifests: Array<ManifestTiptapExtension | ManifestTiptapExtensionB
|
||||
label: 'Code Block',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'tiptapExtension',
|
||||
alias: 'Umb.Tiptap.Figure',
|
||||
name: 'Figure Tiptap Extension',
|
||||
api: () => import('./figure.extension.js'),
|
||||
weight: 955,
|
||||
meta: {
|
||||
alias: 'figure',
|
||||
icon: 'icon-frame',
|
||||
label: 'Figure',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'tiptapExtension',
|
||||
kind: 'button',
|
||||
@@ -153,6 +165,19 @@ export const manifests: Array<ManifestTiptapExtension | ManifestTiptapExtensionB
|
||||
label: 'Strike',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'tiptapExtension',
|
||||
kind: 'button',
|
||||
alias: 'Umb.Tiptap.Table',
|
||||
name: 'Table Tiptap Extension',
|
||||
api: () => import('./table.extension.js'),
|
||||
weight: 909,
|
||||
meta: {
|
||||
alias: 'table',
|
||||
icon: 'icon-table',
|
||||
label: 'Table',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'tiptapExtension',
|
||||
kind: 'button',
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user