Skip to content

Commit 9323d8b

Browse files
authored
Introduces getStyles() for Tiptap extensions (#18075)
1 parent 85a81b3 commit 9323d8b

File tree

6 files changed

+177
-131
lines changed

6 files changed

+177
-131
lines changed

src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts

Lines changed: 48 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import type { UmbTiptapExtensionApi } from '../../extensions/types.js';
22
import type { UmbTiptapToolbarValue } from '../types.js';
3-
import { css, customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit';
3+
import { css, customElement, html, property, state, unsafeCSS, when } from '@umbraco-cms/backoffice/external/lit';
44
import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api';
55
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
66
import { Editor } from '@umbraco-cms/backoffice/external/tiptap';
77
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
88
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
99
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
10+
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
11+
import type { Extensions } from '@umbraco-cms/backoffice/external/tiptap';
1012
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
1113

1214
import './tiptap-hover-menu.element.js';
@@ -45,6 +47,9 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
4547
@state()
4648
private readonly _extensions: Array<UmbTiptapExtensionApi> = [];
4749

50+
@state()
51+
private _styles: Array<CSSResultGroup> = [];
52+
4853
@state()
4954
_toolbar: UmbTiptapToolbarValue = [[[]]];
5055

@@ -100,14 +105,24 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
100105

101106
this._toolbar = this.configuration?.getValueByAlias<UmbTiptapToolbarValue>('toolbar') ?? [[[]]];
102107

103-
const extensions = this._extensions
104-
.map((ext) => ext.getTiptapExtensions({ configuration: this.configuration }))
105-
.flat();
108+
const tiptapExtensions: Extensions = [];
109+
110+
this._extensions.forEach((ext) => {
111+
const tiptapExt = ext.getTiptapExtensions({ configuration: this.configuration });
112+
if (tiptapExt?.length) {
113+
tiptapExtensions.push(...tiptapExt);
114+
}
115+
116+
const styles = ext.getStyles();
117+
if (styles) {
118+
this._styles.push(styles);
119+
}
120+
});
106121

107122
this._editor = new Editor({
108123
element: element,
109124
editable: !this.readonly,
110-
extensions: extensions,
125+
extensions: tiptapExtensions,
111126
content: this.#value,
112127
onBeforeCreate: ({ editor }) => {
113128
this._extensions.forEach((ext) => ext.setEditor(editor));
@@ -125,6 +140,7 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
125140
!this._editor && !this._extensions?.length,
126141
() => html`<div id="loader"><uui-loader></uui-loader></div>`,
127142
() => html`
143+
${this.#renderStyles()}
128144
<umb-tiptap-toolbar
129145
.toolbar=${this._toolbar}
130146
.editor=${this._editor}
@@ -136,6 +152,15 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
136152
`;
137153
}
138154

155+
#renderStyles() {
156+
if (!this._styles?.length) return;
157+
return html`
158+
<style>
159+
${this._styles.map((style) => unsafeCSS(style))}
160+
</style>
161+
`;
162+
}
163+
139164
static override readonly styles = [
140165
css`
141166
:host {
@@ -158,23 +183,6 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
158183
justify-content: center;
159184
}
160185
161-
.tiptap {
162-
height: 100%;
163-
width: 100%;
164-
outline: none;
165-
white-space: pre-wrap;
166-
min-width: 0;
167-
}
168-
169-
.tiptap .is-editor-empty:first-child::before {
170-
color: var(--uui-color-text);
171-
opacity: 0.55;
172-
content: attr(data-placeholder);
173-
float: left;
174-
height: 0;
175-
pointer-events: none;
176-
}
177-
178186
#editor {
179187
/* Required as overflow is set to auto, so that the scrollbars don't appear. */
180188
display: flex;
@@ -189,6 +197,24 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
189197
height: 100%;
190198
width: 100%;
191199
200+
.tiptap {
201+
height: 100%;
202+
width: 100%;
203+
outline: none;
204+
white-space: pre-wrap;
205+
min-width: 0;
206+
207+
.is-editor-empty:first-child::before {
208+
color: var(--uui-color-text);
209+
opacity: 0.55;
210+
content: attr(data-placeholder);
211+
float: left;
212+
height: 0;
213+
pointer-events: none;
214+
}
215+
}
216+
217+
/* The following styles are required for the "StarterKit" extension. */
192218
pre {
193219
background-color: var(--uui-color-surface-alt);
194220
padding: var(--uui-size-space-2) var(--uui-size-space-4);
@@ -220,118 +246,12 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
220246
margin-bottom: 0.5em;
221247
}
222248
223-
figure {
224-
> p,
225-
img {
226-
pointer-events: none;
227-
margin: 0;
228-
padding: 0;
229-
}
230-
231-
&.ProseMirror-selectednode {
232-
outline: 3px solid var(--uui-color-focus);
233-
}
234-
}
235-
236-
img {
237-
&.ProseMirror-selectednode {
238-
outline: 3px solid var(--uui-color-focus);
239-
}
240-
}
241-
242249
li {
243250
> p {
244251
margin: 0;
245252
padding: 0;
246253
}
247254
}
248-
249-
.umb-embed-holder {
250-
display: inline-block;
251-
position: relative;
252-
}
253-
254-
.umb-embed-holder > * {
255-
user-select: none;
256-
pointer-events: none;
257-
}
258-
259-
.umb-embed-holder.ProseMirror-selectednode {
260-
outline: 2px solid var(--uui-palette-spanish-pink-light);
261-
}
262-
263-
.umb-embed-holder::before {
264-
z-index: 1000;
265-
width: 100%;
266-
height: 100%;
267-
position: absolute;
268-
content: ' ';
269-
}
270-
271-
.umb-embed-holder.ProseMirror-selectednode::before {
272-
background: rgba(0, 0, 0, 0.025);
273-
}
274-
275-
/* Table-specific styling */
276-
.tableWrapper {
277-
margin: 1.5rem 0;
278-
overflow-x: auto;
279-
280-
table {
281-
border-collapse: collapse;
282-
margin: 0;
283-
overflow: hidden;
284-
table-layout: fixed;
285-
width: 100%;
286-
287-
td,
288-
th {
289-
border: 1px solid var(--uui-color-border);
290-
box-sizing: border-box;
291-
min-width: 1em;
292-
padding: 6px 8px;
293-
position: relative;
294-
vertical-align: top;
295-
296-
> * {
297-
margin-bottom: 0;
298-
}
299-
}
300-
301-
th {
302-
background-color: var(--uui-color-background);
303-
font-weight: bold;
304-
text-align: left;
305-
}
306-
307-
.selectedCell:after {
308-
background: var(--uui-color-surface-emphasis);
309-
content: '';
310-
left: 0;
311-
right: 0;
312-
top: 0;
313-
bottom: 0;
314-
pointer-events: none;
315-
position: absolute;
316-
z-index: 2;
317-
}
318-
319-
.column-resize-handle {
320-
background-color: var(--uui-color-default);
321-
bottom: -2px;
322-
pointer-events: none;
323-
position: absolute;
324-
right: -2px;
325-
top: 0;
326-
width: 3px;
327-
}
328-
}
329-
330-
.resize-cursor {
331-
cursor: ew-resize;
332-
cursor: col-resize;
333-
}
334-
}
335255
}
336256
`,
337257
];

src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
UmbTiptapToolbarElementApi,
77
} from './types.js';
88
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
9+
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
910
import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/external/tiptap';
1011
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
1112

@@ -27,6 +28,13 @@ export abstract class UmbTiptapExtensionApiBase extends UmbControllerBase implem
2728
this._editor = editor;
2829
}
2930

31+
/**
32+
* @inheritdoc
33+
*/
34+
getStyles(): CSSResultGroup | null | undefined {
35+
return null;
36+
}
37+
3038
/**
3139
* @inheritdoc
3240
*/
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
11
import { UmbTiptapExtensionApiBase } from '../base.js';
2+
import { css } from '@umbraco-cms/backoffice/external/lit';
23
import { umbEmbeddedMedia } from '@umbraco-cms/backoffice/external/tiptap';
34

45
export default class UmbTiptapEmbeddedMediaExtensionApi extends UmbTiptapExtensionApiBase {
56
getTiptapExtensions = () => [umbEmbeddedMedia.configure({ inline: true })];
7+
8+
override getStyles = () => css`
9+
.umb-embed-holder {
10+
display: inline-block;
11+
position: relative;
12+
}
13+
14+
.umb-embed-holder > * {
15+
user-select: none;
16+
pointer-events: none;
17+
}
18+
19+
.umb-embed-holder.ProseMirror-selectednode {
20+
outline: 2px solid var(--uui-palette-spanish-pink-light);
21+
}
22+
23+
.umb-embed-holder::before {
24+
z-index: 1000;
25+
width: 100%;
26+
height: 100%;
27+
position: absolute;
28+
content: ' ';
29+
}
30+
31+
.umb-embed-holder.ProseMirror-selectednode::before {
32+
background: rgba(0, 0, 0, 0.025);
33+
}
34+
`;
635
}
Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
11
import { UmbTiptapExtensionApiBase } from '../base.js';
2+
import { css } from '@umbraco-cms/backoffice/external/lit';
23
import { UmbImage } from '@umbraco-cms/backoffice/external/tiptap';
34

45
export default class UmbTiptapImageExtensionApi extends UmbTiptapExtensionApiBase {
5-
getTiptapExtensions() {
6-
return [UmbImage.configure({ inline: true })];
7-
}
6+
getTiptapExtensions = () => [UmbImage.configure({ inline: true })];
7+
8+
override getStyles = () => css`
9+
figure {
10+
> p,
11+
img {
12+
pointer-events: none;
13+
margin: 0;
14+
padding: 0;
15+
}
16+
17+
&.ProseMirror-selectednode {
18+
outline: 3px solid var(--uui-color-focus);
19+
}
20+
}
21+
22+
img {
23+
&.ProseMirror-selectednode {
24+
outline: 3px solid var(--uui-color-focus);
25+
}
26+
}
27+
`;
828
}

0 commit comments

Comments
 (0)