Skip to content

Commit

Permalink
Tiptap RTE: Stylesheets (#18502)
Browse files Browse the repository at this point in the history
* Copies the "TinyMCE Stylesheets Property Editor UI" to the Templating/Stylesheet package

* Deprecates the "TinyMCE Stylesheets Property Editor UI"

as it may be used in 3rd party extensions.

TinyMCE will be removed in v16, but this deprecation notice in 15.4
will at least notify that the "Umb.PropertyEditorUi.StylesheetPicker"
UI can be used.

* Updates TinyMCE to use the Stylesheet Picker UI

* Prevent Stylesheet folders from being picked

+ UI tweaks

* Updates Stylesheet mock data

* Stylesheet Rule Input - removes Edit button

uses `@open` event for UI consistency with other pickers.

* Updates pangram

* Amending to be "header" instead of "heading"

* Adds "stylesheets" config to Tiptap data-type

* Updates RTE styles for Tiptap

Moves "StarterKit" styles to the RTE Essentials extension registration.

Scopes TinyMCE in "rte-content.css" (for now).
  • Loading branch information
leekelleher authored Feb 28, 2025
1 parent a20f11e commit 3ef9d64
Show file tree
Hide file tree
Showing 18 changed files with 281 additions and 146 deletions.
84 changes: 43 additions & 41 deletions src/Umbraco.Web.UI.Client/src/css/rte-content.css
Original file line number Diff line number Diff line change
@@ -1,49 +1,51 @@
.umb-macro-holder {
border: 3px dotted red;
padding: 7px;
margin: 3px;
display: block;
position: relative;
}
#tinymce {
.umb-macro-holder {
border: 3px dotted red;
padding: 7px;
margin: 3px;
display: block;
position: relative;
}

.umb-macro-holder::after {
content: 'Macros are no longer supported. Please use the block picker instead.';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
background-color: rgba(0, 0, 0, 0.7);
padding: 10px;
border-radius: 5px;
}
.umb-macro-holder::after {
content: 'Macros are no longer supported. Please use the block picker instead.';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
background-color: rgba(0, 0, 0, 0.7);
padding: 10px;
border-radius: 5px;
}

.umb-embed-holder {
position: relative;
}
.umb-embed-holder {
position: relative;
}

.umb-embed-holder > * {
user-select: none;
pointer-events: none;
}
.umb-embed-holder > * {
user-select: none;
pointer-events: none;
}

.umb-embed-holder[data-mce-selected] {
outline: 2px solid var(--uui-palette-spanish-pink-light);
}
.umb-embed-holder[data-mce-selected] {
outline: 2px solid var(--uui-palette-spanish-pink-light);
}

.umb-embed-holder::before {
z-index: 1000;
width: 100%;
height: 100%;
position: absolute;
content: ' ';
}
.umb-embed-holder::before {
z-index: 1000;
width: 100%;
height: 100%;
position: absolute;
content: ' ';
}

.umb-embed-holder[data-mce-selected]::before {
background: rgba(0, 0, 0, 0.025);
}
.umb-embed-holder[data-mce-selected]::before {
background: rgba(0, 0, 0, 0.025);
}

*[data-mce-selected='inline-boundary'] {
background: rgba(0, 0, 0, 0.025);
outline: 2px solid var(--uui-palette-spanish-pink-light);
*[data-mce-selected='inline-boundary'] {
background: rgba(0, 0, 0, 0.025);
outline: 2px solid var(--uui-palette-spanish-pink-light);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,7 @@ export const data: Array<UmbMockDataTypeModel> = [
],
],
},
{ alias: 'stylesheets', value: ['/rte-styles.css'] },
{ alias: 'dimensions', value: { height: 500 } },
{ alias: 'maxImageSize', value: 500 },
{ alias: 'ignoreUserStartNodes', value: false },
Expand Down Expand Up @@ -1105,7 +1106,7 @@ export const data: Array<UmbMockDataTypeModel> = [
'+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-s[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*],figure,figcaption,video[*],audio[*],picture[*],source[*],canvas[*]',
},
{ alias: 'invalidElements', value: 'font' },
{ alias: 'stylesheets', value: [] },
{ alias: 'stylesheets', value: ['/rte-styles.css'] },
{
alias: 'toolbar',
value: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,93 +10,89 @@ export type UmbMockStylesheetModel = StylesheetResponseModel &

export const data: Array<UmbMockStylesheetModel> = [
{
name: 'Stylesheet File 1.css',
path: '/Stylesheet File 1.css',
name: 'RTE Styles',
path: '/rte-styles.css',
parent: null,
isFolder: false,
hasChildren: false,
content: `
/** Stylesheet 1 */
/** RTE Stylesheet */
h1 {
color: blue;
#editor, #tinymce {
background-color: pink;
font-size: 1.5rem;
}
/**umb_name:bjjh*/
h1 {
color: blue;
/**umb_name:Page header*/
h2 {
color: red;
font-size: 2rem;
}
/**umb_name:comeone*/
h1 {
/**umb_name:Section header*/
h3 {
color: blue;
font-size: 1.75rem;
}
/**umb_name:lol*/
h1 {
color: blue;
/**umb_name:Paragraph header*/
h4 {
color: green;
font-size: 1.5rem;
}`,
},
{
name: 'Stylesheet File 2.css',
path: '/Stylesheet File 2.css',
name: 'RTE Styles 2',
path: '/rte-styles-2.css',
parent: null,
isFolder: false,
hasChildren: false,
content: `
/** Stylesheet 2 */
h1 {
color: green;
/** RTE Stylesheet 2 */
body {
font-family: cursive;
}
/**umb_name:HELLO*/
h1 {
color: green;
/**umb_name:Red*/
span {
color: red;
}
/**umb_name:SOMETHING*/
h1 {
color: green;
/**umb_name:Blue*/
span {
color: blue;
}
/**umb_name:NIOCE*/
h1 {
/**umb_name:Green*/
span {
color: green;
}`,
},
{
name: 'Folder 1',
path: '/Folder 1',
name: 'Folder for website',
path: '/folder-for-website',
parent: null,
isFolder: true,
hasChildren: true,
content: '',
},
{
name: 'Stylesheet File 3.css',
path: '/Folder 1/Stylesheet File 3.css',
name: 'Website Styles',
path: '/folder-for-website/website-styles.css',
parent: {
path: '/Folder 1',
path: '/folder-for-website',
},
hasChildren: false,
isFolder: false,
content: `h1 {
color: pink;
}
/**umb_name:ONE*/
h1 {
color: pink;
}
content: `
/** Website Stylesheet */
/**umb_name:TWO*/
h1 {
color: pink;
body {
background-color: #ffb7d3;
color: #b57790;
font-family: sans-serif;
}
/**umb_name:THREE*/
h1 {
color: pink;
}`,
`,
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -110,21 +110,22 @@ export class UmbStylesheetInputElement extends UUIFormControlMixin(UmbLitElement
<uui-button
id="btn-add"
look="placeholder"
@click=${() => this.#pickerContext.openPicker()}
@click=${() => this.#pickerContext.openPicker({ pickableFilter: (item) => !item.isFolder })}
label="Add stylesheet"></uui-button>
`;
}

#renderItem(item: UmbStylesheetItemModel) {
if (!item.unique) return;
return html`
<uui-ref-node-data-type name=${item.name}>
<uui-ref-node name=${item.name}>
<uui-icon slot="icon" name="icon-palette"></uui-icon>
<uui-action-bar slot="actions">
<uui-button
@click=${() => this.#pickerContext.requestRemoveItem(item.unique!)}
label=${this.localize.term('general_remove')}></uui-button>
</uui-action-bar>
</uui-ref-node-data-type>
</uui-ref-node>
`;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@ export class UmbStylesheetRuleInputElement extends UUIFormControlMixin(UmbLitEle
this.rules,
(rule, index) => rule.name + index,
(rule, index) => html`
<umb-stylesheet-rule-ref name=${rule.name} id=${rule.name} detail=${rule.selector}>
<umb-stylesheet-rule-ref
name=${rule.name}
id=${rule.name}
detail=${rule.selector}
@open=${() => this.#editRule(rule, index)}>
<uui-action-bar slot="actions">
<uui-button
label=${this.localize.term('general_edit')}
@click=${() => this.#editRule(rule, index)}></uui-button>
<uui-button
label=${this.localize.term('general_remove')}
@click=${() => this.#removeRule(rule)}></uui-button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default class UmbStylesheetRuleSettingsModalElement extends UmbModalBaseE
<br />
1 2 3 4 5 6 7 8 9 0 € £ $ % &amp; (.,;:'"!?)
<br />
Just keep examining every bid quoted for zinc etchings.
Amazingly few discotheques provide jukeboxes.
</div>
</uui-form-layout-item>
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { manifests as treeManifests } from './tree/manifests.js';
import { manifests as workspaceManifests } from './workspace/manifests.js';
import { manifests as entityActionManifests } from './entity-actions/manifests.js';
import { manifests as componentManifests } from './global-components/manifests.js';
import { manifests as propertyEditorsManifests } from './property-editors/manifests.js';

export const manifests: Array<UmbExtensionManifest> = [
...repositoryManifests,
Expand All @@ -12,4 +13,5 @@ export const manifests: Array<UmbExtensionManifest> = [
...workspaceManifests,
...entityActionManifests,
...componentManifests,
...propertyEditorsManifests,
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { manifest as stylesheetPickerManifest } from './stylesheet-picker/manifests.js';

export const manifests: Array<UmbExtensionManifest> = [stylesheetPickerManifest];
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/property-editor';

export const manifest: ManifestPropertyEditorUi = {
type: 'propertyEditorUi',
alias: 'Umb.PropertyEditorUi.StylesheetPicker',
name: 'Stylesheet Picker Property Editor UI',
js: () => import('./property-editor-ui-stylesheet-picker.element.js'),
meta: {
label: 'Stylesheet Picker',
icon: 'icon-document',
group: 'common',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor';
import { UmbServerFilePathUniqueSerializer } from '@umbraco-cms/backoffice/server-file-system';
import type {
UmbPropertyEditorConfigCollection,
UmbPropertyEditorUiElement,
} from '@umbraco-cms/backoffice/property-editor';
import type { UmbStylesheetInputElement } from '@umbraco-cms/backoffice/stylesheet';

@customElement('umb-property-editor-ui-stylesheet-picker')
export class UmbPropertyEditorUIStylesheetPickerElement extends UmbLitElement implements UmbPropertyEditorUiElement {
readonly #serverFilePathUniqueSerializer = new UmbServerFilePathUniqueSerializer();

@property({ type: Array })
public set value(value: Array<string>) {
if (!value) return;
this.#value = value.map((unique) => this.#serverFilePathUniqueSerializer.toUnique(unique));
}
public get value(): Array<string> {
if (!this.#value) return [];
return this.#value.map((unique) => this.#serverFilePathUniqueSerializer.toServerPath(unique)) as string[];
}
#value: Array<string> = [];

@property({ type: Object, attribute: false })
public config?: UmbPropertyEditorConfigCollection;

#onChange(event: CustomEvent) {
const target = event.target as UmbStylesheetInputElement;
this.#value = target.selection ?? [];
this.dispatchEvent(new UmbPropertyValueChangeEvent());
}

override render() {
return html`<umb-stylesheet-input @change=${this.#onChange} .selection=${this.#value}></umb-stylesheet-input>`;
}
}

export default UmbPropertyEditorUIStylesheetPickerElement;

declare global {
interface HTMLElementTagNameMap {
'umb-property-editor-ui-stylesheet-picker': UmbPropertyEditorUIStylesheetPickerElement;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { umbDataTypeMockDb } from '../../../../../mocks/data/data-type/data-type.db.js';
import { html } from '@umbraco-cms/backoffice/external/lit';
import type { Meta } from '@storybook/web-components';

import './property-editor-ui-tiny-mce-stylesheets-configuration.element.js';
import type { UmbDataTypeDetailModel } from '@umbraco-cms/backoffice/data-type';

const dataTypeData = umbDataTypeMockDb.read('dt-richTextEditor') as unknown as UmbDataTypeDetailModel;

export default {
title: 'Property Editor UIs/Stylesheet Picker',
component: 'umb-property-editor-ui-stylesheet-picker',
id: 'umb-property-editor-ui-sstylesheet-picker',
} as Meta;

export const AAAOverview = ({ value }: any) =>
html`<umb-property-editor-ui-stylesheet-picker .value=${value}></umb-property-editor-ui-stylesheet-picker>`;
AAAOverview.storyName = 'Overview';
AAAOverview.args = {
value: dataTypeData?.values?.find((x) => x.alias === 'stylesheets')?.value ?? [],
};
Loading

0 comments on commit 3ef9d64

Please sign in to comment.