Skip to content

Commit 2fc9940

Browse files
authored
Merge pull request #2374 from umbraco/v15/feature/rte/tiptap/render-toolbar
Tiptap: Render toolbar with row and group configuration
2 parents 093b6b6 + da4134e commit 2fc9940

File tree

4 files changed

+88
-36
lines changed

4 files changed

+88
-36
lines changed

src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { UmbTiptapExtensionApi } from '../../extensions/types.js';
1+
import type { UmbTiptapExtensionApi, UmbTiptapToolbarValue } from '../../extensions/types.js';
22
import { css, customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit';
33
import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api';
44
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
@@ -75,7 +75,7 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
7575
private _editor!: Editor;
7676

7777
@state()
78-
_toolbar: string[][][] = [[[]]];
78+
_toolbar: UmbTiptapToolbarValue = [[[]]];
7979

8080
protected override async firstUpdated() {
8181
await Promise.all([await this.#loadExtensions(), await this.#loadEditor()]);
@@ -110,7 +110,7 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
110110
if (maxWidth) this.setAttribute('style', `max-width: ${maxWidth}px;`);
111111
if (maxHeight) element.setAttribute('style', `max-height: ${maxHeight}px;`);
112112

113-
this._toolbar = this.configuration?.getValueByAlias<string[][][]>('toolbar') ?? [[[]]];
113+
this._toolbar = this.configuration?.getValueByAlias<UmbTiptapToolbarValue>('toolbar') ?? [[[]]];
114114

115115
const extensions = this._extensions
116116
.map((ext) => ext.getTiptapExtensions({ configuration: this.configuration }))

src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import type { ManifestTiptapToolbarExtension } from '../../extensions/tiptap-toolbar-extension.js';
2-
import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit';
1+
import type { UmbTiptapToolbarValue } from '../../extensions/types.js';
2+
import { css, customElement, html, map, property, state } from '@umbraco-cms/backoffice/external/lit';
3+
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
4+
import { UmbExtensionsElementAndApiInitializer } from '@umbraco-cms/backoffice/extension-api';
35
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
46
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
57
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
@@ -10,6 +12,12 @@ const elementName = 'umb-tiptap-fixed-menu';
1012

1113
@customElement(elementName)
1214
export class UmbTiptapFixedMenuElement extends UmbLitElement {
15+
#attached = false;
16+
#extensionsController?: UmbExtensionsElementAndApiInitializer;
17+
18+
@state()
19+
private _lookup?: Map<string, unknown>;
20+
1321
@property({ type: Boolean, reflect: true })
1422
readonly = false;
1523

@@ -20,21 +28,61 @@ export class UmbTiptapFixedMenuElement extends UmbLitElement {
2028
configuration?: UmbPropertyEditorConfigCollection;
2129

2230
@property({ attribute: false })
23-
toolbar: string[][][] = [[[]]];
31+
toolbar: UmbTiptapToolbarValue = [[[]]];
32+
33+
override connectedCallback(): void {
34+
super.connectedCallback();
35+
this.#attached = true;
36+
this.#observeExtensions();
37+
}
38+
override disconnectedCallback(): void {
39+
this.#attached = false;
40+
this.#extensionsController?.destroy();
41+
this.#extensionsController = undefined;
42+
super.disconnectedCallback();
43+
}
44+
45+
#observeExtensions(): void {
46+
if (!this.#attached) return;
47+
this.#extensionsController?.destroy();
48+
49+
this.#extensionsController = new UmbExtensionsElementAndApiInitializer(
50+
this,
51+
umbExtensionsRegistry,
52+
'tiptapToolbarExtension',
53+
[],
54+
(manifest) => this.toolbar.flat(2).includes(manifest.alias),
55+
(extensionControllers) => {
56+
this._lookup = new Map(extensionControllers.map((ext) => [ext.alias, ext.component]));
57+
},
58+
);
59+
60+
this.#extensionsController.apiProperties = { configuration: this.configuration };
61+
this.#extensionsController.elementProperties = { editor: this.editor, configuration: this.configuration };
62+
}
2463

2564
override render() {
26-
return html`
27-
<umb-extension-with-api-slot
28-
type="tiptapToolbarExtension"
29-
.filter=${(ext: ManifestTiptapToolbarExtension) =>
30-
this.toolbar.flat(2).includes(ext.alias) && (!!ext.kind || !!ext.element)}
31-
.elementProps=${{ editor: this.editor, configuration: this.configuration }}
32-
.apiProps=${{ configuration: this.configuration }}>
33-
</umb-extension-with-api-slot>
34-
`;
65+
return html`${map(this.toolbar, (row, rowIndex) =>
66+
map(
67+
row,
68+
(group, groupIndex) =>
69+
html`${map(group, (alias, aliasIndex) => {
70+
const newRow = rowIndex !== 0 && groupIndex === 0 && aliasIndex === 0;
71+
return html`<div class="item" ?data-new-row=${newRow} style="${newRow ? 'grid-column: 1 / span 3' : ''}">
72+
${this._lookup?.get(alias)}
73+
</div>`;
74+
})}
75+
<div class="separator"></div> `,
76+
),
77+
)} `;
3578
}
3679

3780
static override readonly styles = css`
81+
:host([readonly]) {
82+
pointer-events: none;
83+
background-color: var(--uui-color-surface-alt);
84+
}
85+
3886
:host {
3987
border-radius: var(--uui-border-radius);
4088
border: 1px solid var(--uui-color-border);
@@ -43,20 +91,29 @@ export class UmbTiptapFixedMenuElement extends UmbLitElement {
4391
background-color: var(--uui-color-surface);
4492
color: var(--color-text);
4593
display: grid;
46-
grid-template-columns: repeat(auto-fill, minmax(24px, 1fr));
47-
gap: var(--uui-size-space-1);
94+
grid-template-columns: repeat(auto-fill, minmax(10px, 1fr));
95+
grid-auto-flow: row;
4896
position: sticky;
4997
top: -25px;
5098
left: 0px;
5199
right: 0px;
52100
padding: var(--uui-size-space-3);
53-
align-items: center;
54101
z-index: 9999999;
55102
}
56103
57-
:host([readonly]) {
58-
pointer-events: none;
59-
background-color: var(--uui-color-surface-alt);
104+
.item {
105+
grid-column: span 3;
106+
}
107+
108+
.separator {
109+
background-color: var(--uui-color-border);
110+
width: 1px;
111+
place-self: center;
112+
height: 22px;
113+
}
114+
.separator:last-child,
115+
.separator:has(+ [data-new-row]) {
116+
display: none;
60117
}
61118
`;
62119
}

src/packages/rte/tiptap/extensions/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,5 @@ export abstract class UmbTiptapToolbarElementApiBase extends UmbControllerBase i
9898
return editor && this.manifest?.meta.alias ? editor?.isActive(this.manifest.meta.alias) : false;
9999
}
100100
}
101+
102+
export type UmbTiptapToolbarValue = Array<Array<Array<string>>>;

src/packages/rte/tiptap/property-editors/property-editor-ui-tiptap-toolbar-configuration.element.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
1-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
2-
import {
3-
customElement,
4-
css,
5-
html,
6-
property,
7-
state,
8-
repeat,
9-
nothing,
10-
type PropertyValueMap,
11-
} from '@umbraco-cms/backoffice/external/lit';
12-
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
1+
import type { UmbTiptapToolbarValue } from '../extensions/types.js';
2+
import { customElement, css, html, property, state, repeat, nothing } from '@umbraco-cms/backoffice/external/lit';
133
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
4+
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
5+
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
146
import { UmbPropertyValueChangeEvent, type UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor';
7+
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
158

169
type Extension = {
1710
alias: string;
@@ -25,7 +18,7 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement
2518
implements UmbPropertyEditorUiElement
2619
{
2720
@property({ attribute: false })
28-
set value(value: string[][][] | undefined) {
21+
set value(value: UmbTiptapToolbarValue | undefined) {
2922
if (!value) {
3023
this.#useDefault = true;
3124
this.#value = [[[]]];
@@ -36,14 +29,14 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement
3629
this.#value = value.map((rows) => rows.map((groups) => [...groups]));
3730
}
3831

39-
get value(): string[][][] {
32+
get value(): UmbTiptapToolbarValue {
4033
// TODO: This can be optimized with cashing;
4134
return this.#value.map((rows) => rows.map((groups) => [...groups]));
4235
}
4336

4437
#useDefault = false;
4538

46-
#value: string[][][] = [[[]]];
39+
#value: UmbTiptapToolbarValue = [[[]]];
4740

4841
@state()
4942
_extensions: Extension[] = [];

0 commit comments

Comments
 (0)