Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ export class UmbTiptapToolbarElement extends UmbLitElement {
}

#renderActions(aliases: Array<string>) {
return repeat(aliases, (alias) => this.#lookup?.get(alias) ?? this.#renderActionPlaceholder());
return repeat(aliases, (alias) => this.#lookup?.get(alias) ?? this.#renderActionPlaceholder(alias));
}

#renderActionPlaceholder() {
return html`<span class="skeleton" role="none"></span>`;
#renderActionPlaceholder(alias: string) {
return html`<span class="skeleton" role="none" title="Loading '${alias}'"></span>`;
}

static override readonly styles = css`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const manifests: Array<UmbExtensionManifest> = [
alias: 'Umb.Tiptap.Toolbar.HorizontalRule',
name: 'Horizontal Rule Tiptap Toolbar Extension',
api: () => import('./horizontal-rule.tiptap-toolbar-api.js'),
forExtensions: ['Umb.Tiptap.HorizontalRule'],
meta: {
alias: 'horizontalRule',
icon: 'icon-horizontal-rule',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const manifests: Array<UmbExtensionManifest> = [
kind: 'styleMenu',
alias: 'Umb.Tiptap.Toolbar.StyleSelect',
name: 'Style Select Tiptap Extension',
forExtensions: ['Umb.Tiptap.Heading', 'Umb.Tiptap.Blockquote', 'Umb.Tiptap.CodeBlock'],
items: [
{
label: 'Headers',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
import {
css,
customElement,
html,
ifDefined,
nothing,
property,
state,
repeat,
when,
} from '@umbraco-cms/backoffice/external/lit';
import { css, customElement, html, nothing, property, state, repeat, when } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
Expand Down Expand Up @@ -166,7 +156,7 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement
${repeat(
group.extensions,
(item) => html`
<li title=${ifDefined(item.description)}>
<li title=${item.description ?? item.alias}>
<uui-checkbox
label=${this.localize.string(item.label)}
value=${item.alias}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export class UmbPropertyEditorUiTiptapStatusbarConfigurationElement
<uui-button
compact
class=${forbidden ? 'forbidden' : ''}
data-mark="tiptap-toolbar-item:${item.alias}"
data-mark="tiptap-statusbar-item:${item.alias}"
draggable="true"
label=${label}
look=${forbidden ? 'placeholder' : 'outline'}
Expand Down Expand Up @@ -212,30 +212,44 @@ export class UmbPropertyEditorUiTiptapStatusbarConfigurationElement

#renderItem(alias: string, areaIndex = 0, itemIndex = 0) {
const item = this.#context?.getExtensionByAlias(alias);
if (!item) return nothing;

const forbidden = !this.#context?.isExtensionEnabled(item.alias);
const label = this.localize.string(item.label);

return html`
<uui-button
compact
class=${forbidden ? 'forbidden' : ''}
data-mark="tiptap-toolbar-item:${item.alias}"
draggable="true"
label=${label}
look=${forbidden ? 'placeholder' : 'outline'}
title=${label}
?disabled=${forbidden}
@click=${() => this.#context.removeStatusbarItem([areaIndex, itemIndex])}
@dragend=${this.#onDragEnd}
@dragstart=${(e: DragEvent) => this.#onDragStart(e, alias, [areaIndex, itemIndex])}>
<div class="inner">
${when(item.icon, (icon) => html`<umb-icon .name=${icon}></umb-icon>`)}
<span>${label}</span>
</div>
</uui-button>
`;
switch (item.kind) {
case 'unknown':
return html`
<uui-button
compact
class="missing"
data-mark="tiptap-statusbar-item:${item.alias}"
color="danger"
look="placeholder"
label="Missing extension"
title="Missing extension: ${item.alias}"
@click=${() => this.#context.removeStatusbarItem([areaIndex, itemIndex])}></uui-button>
`;

default:
return html`
<uui-button
compact
class=${forbidden ? 'forbidden' : ''}
data-mark="tiptap-statusbar-item:${item.alias}"
draggable="true"
label=${label}
look=${forbidden ? 'placeholder' : 'outline'}
title=${label}
@click=${() => this.#context.removeStatusbarItem([areaIndex, itemIndex])}
@dragend=${this.#onDragEnd}
@dragstart=${(e: DragEvent) => this.#onDragStart(e, alias, [areaIndex, itemIndex])}>
<div class="inner">
${when(item.icon, (icon) => html`<umb-icon .name=${icon}></umb-icon>`)}
<span>${label}</span>
</div>
</uui-button>
`;
}
}

static override readonly styles = [
Expand Down Expand Up @@ -303,8 +317,8 @@ export class UmbPropertyEditorUiTiptapStatusbarConfigurationElement
--color-standalone: var(--uui-color-danger-standalone);
--color-emphasis: var(--uui-color-danger-emphasis);
--color-contrast: var(--uui-color-danger);
--uui-button-contrast-disabled: var(--uui-color-danger);
--uui-button-border-color-disabled: var(--uui-color-danger);
--uui-button-contrast: var(--uui-color-danger);
--uui-button-border-color: var(--uui-color-danger);
}

div {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class UmbTiptapStatusbarConfigurationContext extends UmbContextBase {
const _extensions = extensions
.sort((a, b) => a.alias.localeCompare(b.alias))
.map((ext) => ({
kind: 'default',
alias: ext.alias,
label: ext.meta.label,
icon: ext.meta.icon,
Expand Down Expand Up @@ -75,8 +76,8 @@ export class UmbTiptapStatusbarConfigurationContext extends UmbContextBase {
.filter((ext) => ext.alias?.toLowerCase().includes(query) || ext.label?.toLowerCase().includes(query));
}

public getExtensionByAlias(alias: string): UmbTiptapStatusbarExtension | undefined {
return this.#lookup?.get(alias);
public getExtensionByAlias(alias: string): UmbTiptapStatusbarExtension {
return this.#lookup?.get(alias) ?? { label: '', alias, icon: '', kind: 'unknown' };
}

public isExtensionEnabled(alias: string): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,7 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement
#renderGroup(group?: UmbTiptapToolbarGroupViewModel, rowIndex = 0, groupIndex = 0) {
if (!group) return nothing;
const showActionBar = this._toolbar[rowIndex].data.length > 1 && group.data.length === 0;
const items: UmbTiptapToolbarExtension[] = group!.data
.map((alias) => this.#context?.getExtensionByAlias(alias))
.filter((item): item is UmbTiptapToolbarExtension => !!item);
const items = group!.data.map((alias) => this.#context?.getExtensionByAlias(alias));
return html`
<div
class="group"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ export class UmbTiptapToolbarConfigurationContext extends UmbContextBase {
.filter((ext) => ext.alias?.toLowerCase().includes(query) || ext.label?.toLowerCase().includes(query));
}

public getExtensionByAlias(alias: string): UmbTiptapToolbarExtension | undefined {
return this.#lookup?.get(alias);
public getExtensionByAlias(alias: string): UmbTiptapToolbarExtension {
return this.#lookup?.get(alias) ?? { label: '', alias, icon: '', kind: 'unknown' };
}

public isExtensionEnabled(alias: string): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export class UmbTiptapToolbarGroupConfigurationElement<
TiptapToolbarItem extends UmbTiptapToolbarExtension = UmbTiptapToolbarExtension,
> extends UmbLitElement {
#sorter = new UmbSorterController<TiptapToolbarItem, HTMLElement>(this, {
getUniqueOfElement: (element) => element.getAttribute('tiptap-toolbar-alias'),
getUniqueOfModel: (modelEntry) => modelEntry.alias!,
itemSelector: 'uui-button',
getUniqueOfElement: (element) => element.dataset.mark,
getUniqueOfModel: (modelEntry) => `tiptap-toolbar-item:${modelEntry.alias}`,
itemSelector: '.draggable',
identifier: 'umb-tiptap-toolbar-sorter',
containerSelector: '.items',
resolvePlacement: UmbSorterResolvePlacementAsGrid,
Expand Down Expand Up @@ -71,7 +71,7 @@ export class UmbTiptapToolbarGroupConfigurationElement<
}

#renderItem(item: TiptapToolbarItem, index = 0) {
const label = this.localize.string(item.label);
const label = this.localize.string(item.label) || item.alias;
const forbidden = !this.#context?.isExtensionEnabled(item.alias);

switch (item.kind) {
Expand All @@ -80,13 +80,11 @@ export class UmbTiptapToolbarGroupConfigurationElement<
return html`
<uui-button
compact
class=${forbidden ? 'forbidden' : ''}
class="draggable ${forbidden ? 'forbidden' : ''}"
data-mark="tiptap-toolbar-item:${item.alias}"
look=${forbidden ? 'placeholder' : 'outline'}
label=${label}
title=${label}
?disabled=${forbidden}
tiptap-toolbar-alias=${item.alias}
@click=${() => this.#onRequestRemove(item, index)}>
<div class="inner">
<span>${label}</span>
Expand All @@ -95,18 +93,29 @@ export class UmbTiptapToolbarGroupConfigurationElement<
</uui-button>
`;

case 'unknown':
return html`
<uui-button
compact
data-mark="tiptap-toolbar-item:${item.alias}"
color="danger"
look="placeholder"
label="Missing extension"
title="Missing extension: ${item.alias}"
@click=${() => this.#onRequestRemove(item, index)}></uui-button>
`;

case 'button':
case 'colorPickerButton':
default:
return html`
<uui-button
compact
class=${forbidden ? 'forbidden' : ''}
class="draggable ${forbidden ? 'forbidden' : ''}"
data-mark="tiptap-toolbar-item:${item.alias}"
look=${forbidden ? 'placeholder' : 'outline'}
label=${label}
title=${label}
?disabled=${forbidden}
tiptap-toolbar-alias=${item.alias}
@click=${() => this.#onRequestRemove(item, index)}>
<div class="inner">
${when(
Expand All @@ -131,23 +140,18 @@ export class UmbTiptapToolbarGroupConfigurationElement<
uui-button {
--uui-button-font-weight: normal;

&[draggable='true'],
&[draggable='true'] > .inner {
&.draggable,
&.draggable > .inner {
cursor: move;
}

&[disabled],
&[disabled] > .inner {
cursor: not-allowed;
}

&.forbidden {
--color: var(--uui-color-danger);
--color-standalone: var(--uui-color-danger-standalone);
--color-emphasis: var(--uui-color-danger-emphasis);
--color-contrast: var(--uui-color-danger);
--uui-button-contrast-disabled: var(--uui-color-danger);
--uui-button-border-color-disabled: var(--uui-color-danger);
--uui-button-contrast: var(--uui-color-danger);
--uui-button-border-color: var(--uui-color-danger);
}

div {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
export type UmbTiptapSortableViewModel<T> = { unique: string; data: T };

export type UmbTiptapStatusbarExtension = {
export type UmbTiptapExtensionBase = {
kind?: string;
alias: string;
label: string;
icon: string;
dependencies?: Array<string>;
};

export type UmbTiptapStatusbarExtension = UmbTiptapExtensionBase;

export type UmbTiptapStatusbarViewModel = UmbTiptapSortableViewModel<Array<string>>;

export type UmbTiptapToolbarExtension = UmbTiptapStatusbarExtension & {
kind?: string;
};
export type UmbTiptapToolbarExtension = UmbTiptapExtensionBase;

export type UmbTiptapToolbarRowViewModel = UmbTiptapSortableViewModel<Array<UmbTiptapToolbarGroupViewModel>>;
export type UmbTiptapToolbarGroupViewModel = UmbTiptapSortableViewModel<Array<string>>;
Expand Down
Loading