From 2fa21b889586ae650f377f25ebbf8b8dfd4c7d47 Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:27:15 +0200 Subject: [PATCH] cleanup --- ...ui-tiptap-toolbar-configuration.element.ts | 8 +- ...ap-toolbar-groups-configuration.element.ts | 390 +++++++++++------- ...p-toolbar-groups-configuration2.element.ts | 340 --------------- 3 files changed, 246 insertions(+), 492 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration2.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/property-editor-ui-tiptap-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/property-editor-ui-tiptap-toolbar-configuration.element.ts index 91d1a11c51..4ecf695b94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/property-editor-ui-tiptap-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/property-editor-ui-tiptap-toolbar-configuration.element.ts @@ -1,4 +1,4 @@ -import type UmbTiptapToolbarGroupsConfiguration2Element from './tiptap-toolbar-groups-configuration2.element.js'; +import type UmbTiptapToolbarGroupsConfigurationElement from './tiptap-toolbar-groups-configuration.element.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; import { customElement, css, html, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; @@ -9,7 +9,7 @@ import { type UmbPropertyEditorConfigCollection, } from '@umbraco-cms/backoffice/property-editor'; -import './tiptap-toolbar-groups-configuration2.element.js'; +import './tiptap-toolbar-groups-configuration.element.js'; // If an extension does not have a position, it is considered hidden in the toolbar type TestServerValue = Array<{ @@ -119,7 +119,7 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement } #onChange(event: CustomEvent) { - this.value = (event.target as UmbTiptapToolbarGroupsConfiguration2Element).value; + this.value = (event.target as UmbTiptapToolbarGroupsConfigurationElement).value; // update the selected state of the extensions // TODO this should be done in a more efficient way @@ -134,7 +134,7 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement override render() { return html` - +
${repeat( this._extensionCategories, diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration.element.ts index 8c9051ef06..9a04507cb3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration.element.ts @@ -1,7 +1,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { customElement, css, html, property, repeat, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { Observable, UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; type Extension = { alias: string; @@ -9,163 +9,165 @@ type Extension = { icon?: string; }; +type TestServerValue = Array<{ + alias: string; + position?: [number, number, number]; +}>; + @customElement('umb-tiptap-toolbar-groups-configuration') export class UmbTiptapToolbarGroupsConfigurationElement extends UmbLitElement { @property({ attribute: false }) - availableExtensions: Array = []; - - @state() - private _toolbar: string[][][] = [[[]]]; - - #toolbarLayout: UmbArrayState | undefined; - - #testData: TestServerValue = [ - { - alias: 'bold', - position: [0, 0, 0], - }, - { - alias: 'italic', - position: [0, 0, 1], - }, - { - alias: 'undo', - position: [0, 1, 0], - }, - { - alias: 'redo', - position: [0, 1, 1], - }, - { - alias: 'copy', - position: [1, 0, 0], - }, - { - alias: 'paste', - position: [1, 2, 0], - }, - ]; - - toStructuredData = (data: any): string[][][] => { - const structuredData: string[][][] = []; - - data.forEach(({ alias, position }) => { - const [rowIndex, groupIndex, aliasIndex] = position; - - // Ensure the row exists up to rowIndex - while (structuredData.length <= rowIndex) { - structuredData.push([]); - } - - const currentRow = structuredData[rowIndex]; - - // Ensure the group exists up to groupIndex within the row - while (currentRow.length <= groupIndex) { - currentRow.push([]); - } - - const currentGroup = currentRow[groupIndex]; - - // Ensure the alias is placed at the correct position in the group - currentGroup[aliasIndex] = alias; - }); - - return structuredData; - }; - - constructor() { - super(); - - this.consumeContext( - 'umb-tiptap-toolbar-context', - (instance: { state: UmbArrayState; observable: Observable }) => { - this.#toolbarLayout = instance.state; - - this.observe(instance.observable, (value) => { - this._toolbar = value.map((rows) => rows.map((groups) => [...groups])); - }); - }, - ); - - setTimeout(() => { - this._toolbar = this.toStructuredData(this.#testData); - }, 2000); + set value(value: TestServerValue) { + // if (this.#originalFormat === value) return; + // TODO: also check if the added values have positions, if not, there's no need to update the structured data. + this.#originalFormat = value; + this._structuredData = this.toStructuredData(value); } - private moveItem = (from: [number, number, number], to: [number, number, number]) => { - const [fromRow, fromGroup, fromItem] = from; - const [toRow, toGroup, toItem] = to; + get value(): TestServerValue { + return this.#originalFormat; + } - // Get the item to move from the 'from' position - const itemToMove = this._toolbar[fromRow][fromGroup][fromItem]; + @property({ attribute: false }) + extensionConfigs: Extension[] = []; - // Remove the item from the original position - this._toolbar[fromRow][fromGroup].splice(fromItem, 1); + //TODO: Use the context again so that we can remove items from the extensions list from here. - // Insert the item into the new position - this._toolbar[toRow][toGroup].splice(toItem, 0, itemToMove); + @state() + _structuredData: string[][][] = [[[]]]; - this.#toolbarLayout?.setValue(this._toolbar); - }; + #originalFormat: TestServerValue = []; - #addGroup = (rowIndex: number, groupIndex: number) => { - this._toolbar[rowIndex].splice(groupIndex, 0, []); - this.#toolbarLayout?.setValue(this._toolbar); - }; + #currentDragAlias?: string; - #removeGroup = (rowIndex: number, groupIndex: number) => { - this._toolbar[rowIndex].splice(groupIndex, 1); - this.#toolbarLayout?.setValue(this._toolbar); - }; - - #addRow = (rowIndex: number) => { - this._toolbar.splice(rowIndex, 0, [[]]); - this.#toolbarLayout?.setValue(this._toolbar); - }; - - #removeRow = (rowIndex: number) => { - this._toolbar.splice(rowIndex, 1); - this.#toolbarLayout?.setValue(this._toolbar); - }; - - #onDragStart = (event: DragEvent, pos: [number, number, number]) => { - event.dataTransfer!.setData('application/json', JSON.stringify(pos)); - event.dataTransfer!.dropEffect = 'move'; + #onDragStart = (event: DragEvent, alias: string) => { + this.#currentDragAlias = alias; + event.dataTransfer!.effectAllowed = 'move'; }; #onDragOver = (event: DragEvent) => { event.preventDefault(); + event.dataTransfer!.dropEffect = 'move'; + }; + + #onDragEnd = (event: DragEvent) => { + event.preventDefault(); + if (event.dataTransfer?.dropEffect === 'none') { + const fromPos = this.#originalFormat.find((item) => item.alias === this.#currentDragAlias)?.position; + if (!fromPos) return; + + this.removeItem(fromPos); + } }; #onDrop = (event: DragEvent, toPos: [number, number, number]) => { event.preventDefault(); + const fromPos = this.#originalFormat.find((item) => item.alias === this.#currentDragAlias)?.position; - const fromPos: [number, number, number] = JSON.parse(event.dataTransfer!.getData('application/json') ?? '[0,0,0]'); - this.moveItem(fromPos, toPos); + if (fromPos) { + this.moveItem(fromPos, toPos); + } else if (this.#currentDragAlias) { + this.insertItem(this.#currentDragAlias, toPos); + } }; - private renderItem(alias: string, rowIndex: number, groupIndex: number, itemIndex: number) { - const extension = this.availableExtensions.find((ext) => ext.alias === alias); - if (!extension) return nothing; + private moveItem = (from: [number, number, number], to: [number, number, number]) => { + const [rowIndex, groupIndex, itemIndex] = from; + // Get the item to move from the 'from' position + const itemToMove = this._structuredData[rowIndex][groupIndex][itemIndex]; + + // Remove the item from the original position + this._structuredData[rowIndex][groupIndex].splice(itemIndex, 1); + + this.insertItem(itemToMove, to); + }; + + private insertItem = (alias: string, toPos: [number, number, number]) => { + const [rowIndex, groupIndex, itemIndex] = toPos; + // Insert the item into the new position + this._structuredData[rowIndex][groupIndex].splice(itemIndex, 0, alias); + this.#updateOriginalFormat(); + + this.requestUpdate('_structuredData'); + this.dispatchEvent(new UmbChangeEvent()); + }; + + private removeItem(from: [number, number, number]) { + const [rowIndex, groupIndex, itemIndex] = from; + this._structuredData[rowIndex][groupIndex].splice(itemIndex, 1); + + this.#updateOriginalFormat(); + + this.requestUpdate('_structuredData'); + this.dispatchEvent(new UmbChangeEvent()); + } + + #addGroup = (rowIndex: number, groupIndex: number) => { + this._structuredData[rowIndex].splice(groupIndex, 0, []); + this.requestUpdate('_structuredData'); + }; + + #removeGroup = (rowIndex: number, groupIndex: number) => { + if (rowIndex === 0 && groupIndex === 0) { + // Prevent removing the last group + this._structuredData[rowIndex][groupIndex] = []; + } else { + this._structuredData[rowIndex].splice(groupIndex, 1); + } + this.requestUpdate('_structuredData'); + this.#updateOriginalFormat(); + }; + + #addRow = (rowIndex: number) => { + this._structuredData.splice(rowIndex, 0, [[]]); + this.requestUpdate('_structuredData'); + }; + + #removeRow = (rowIndex: number) => { + if (rowIndex === 0) { + // Prevent removing the last row + this._structuredData[rowIndex] = [[]]; + } else { + this._structuredData.splice(rowIndex, 1); + } + this.requestUpdate('_structuredData'); + this.#updateOriginalFormat(); + }; + + #updateOriginalFormat() { + this.#originalFormat = this.toOriginalFormat(this._structuredData); + this.dispatchEvent(new UmbChangeEvent()); + } + + private renderItem(alias: string) { + const extension = this.extensionConfigs.find((ext) => ext.alias === alias); + if (!extension) return nothing; return html`
this.#onDragStart(e, [rowIndex, groupIndex, itemIndex])}> - ${extension.label} + @dragend=${this.#onDragEnd} + @dragstart=${(e: DragEvent) => this.#onDragStart(e, alias)}> +
`; } private renderGroup(group: string[], rowIndex: number, groupIndex: number) { - console.log('group', group); return html`
this.#onDrop(e, [rowIndex, groupIndex, 0])}> - ${group.map((alias, itemIndex) => this.renderItem(alias, rowIndex, groupIndex, itemIndex))} - + @drop=${(e: DragEvent) => this.#onDrop(e, [rowIndex, groupIndex, group.length])}> + ${group.map((alias) => this.renderItem(alias))} + this.#removeGroup(rowIndex, groupIndex)}> + +
`; } @@ -174,17 +176,101 @@ export class UmbTiptapToolbarGroupsConfigurationElement extends UmbLitElement { return html`
${repeat(row, (group, groupIndex) => this.renderGroup(group, rowIndex, groupIndex))} - - + this.#addGroup(rowIndex, row.length)}>+ + this.#removeRow(rowIndex)}> + +
`; } override render() { - return html`${repeat(this._toolbar, (row, rowIndex) => this.renderRow(row, rowIndex))} - `; + return html` +

+ WIP Feature Rows, groups, and item order have no effect yet.
+ However, adding and removing items from the toolbar is functional. Additionally, hiding items from the toolbar + while retaining their functionality by excluding them from the toolbar layout is also functional. +

+ ${repeat(this._structuredData, (row, rowIndex) => this.renderRow(row, rowIndex))} + this.#addRow(this._structuredData.length)}>+ + +

Extensions hidden from the toolbar

+
+ ${this.#originalFormat?.filter((item) => !item.position).map((item) => this.renderItem(item.alias))} +
+ `; } + toStructuredData = (data: TestServerValue) => { + if (!data?.length) return [[[]]]; + + const structuredData: string[][][] = [[[]]]; + data.forEach(({ alias, position }) => { + if (!position) return; + + const [rowIndex, groupIndex, aliasIndex] = position; + + while (structuredData.length <= rowIndex) { + structuredData.push([]); + } + + const currentRow = structuredData[rowIndex]; + + while (currentRow.length <= groupIndex) { + currentRow.push([]); + } + + const currentGroup = currentRow[groupIndex]; + + currentGroup[aliasIndex] = alias; + }); + + return structuredData; + }; + + toOriginalFormat = (structuredData: string[][][]) => { + const originalData: TestServerValue = []; + + structuredData.forEach((row, rowIndex) => { + row.forEach((group, groupIndex) => { + group.forEach((alias, aliasIndex) => { + if (alias) { + originalData.push({ + alias, + position: [rowIndex, groupIndex, aliasIndex], + }); + } + }); + }); + }); + + // add items from this.#originalFormat only if they are not already in the structured data. and if they have a position property set, unset it. + this.#originalFormat.forEach((item) => { + if (!originalData.some((i) => i.alias === item.alias)) { + originalData.push({ + alias: item.alias, + }); + } + }); + + // TODO: this code removes the items completely, while the one above just puts them back into the hidden extensions list. Which one do we prefer? + // this.#originalFormat.forEach((item) => { + // if (!item.position) { + // const exists = originalData.find((i) => i.alias === item.alias); + // if (!exists) { + // originalData.push(item); + // } + // } + // }); + + return originalData; + }; + static override styles = [ UmbTextStyles, css` @@ -193,6 +279,13 @@ export class UmbTiptapToolbarGroupsConfigurationElement extends UmbLitElement { flex-direction: column; gap: 6px; } + .hidden-extensions { + display: flex; + gap: 6px; + } + .hidden-extensions-header { + margin-bottom: 3px; + } .row { position: relative; display: flex; @@ -202,36 +295,37 @@ export class UmbTiptapToolbarGroupsConfigurationElement extends UmbLitElement { position: relative; display: flex; gap: 3px; - border: 1px solid #ccc; + border-radius: var(--uui-border-radius); + background-color: var(--uui-color-surface-alt); padding: 6px; - min-height: 24px; - min-width: 24px; + min-height: 30px; + min-width: 30px; } .item { - padding: 3px; - border: 1px solid #ccc; - border-radius: 3px; - background-color: #f9f9f9; + padding: var(--uui-size-space-2); + border: 1px solid var(--uui-color-border); + border-radius: var(--uui-border-radius); + background-color: var(--uui-color-surface); + cursor: move; + display: flex; + align-items: baseline; } + .remove-row-button, + .remove-group-button { + display: none; + } .remove-group-button { position: absolute; - top: -4px; - right: -4px; - display: none; - } - .group:hover .remove-group-button { - display: block; + top: -26px; + left: 50%; + transform: translateX(-50%); + z-index: 1; } - .remove-row-button { - position: absolute; - left: -25px; - top: 8px; - display: none; - } - .row:hover .remove-row-button { - display: block; + .row:hover .remove-row-button:not(.hidden), + .group:hover .remove-group-button:not(.hidden) { + display: flex; } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration2.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration2.element.ts deleted file mode 100644 index b978935be1..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/tiptap/property-editors/tiptap-toolbar-groups-configuration2.element.ts +++ /dev/null @@ -1,340 +0,0 @@ -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { customElement, css, html, property, repeat, nothing, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; - -type Extension = { - alias: string; - label: string; - icon?: string; -}; - -type TestServerValue = Array<{ - alias: string; - position?: [number, number, number]; -}>; - -@customElement('umb-tiptap-toolbar-groups-configuration2') -export class UmbTiptapToolbarGroupsConfiguration2Element extends UmbLitElement { - @property({ attribute: false }) - set value(value: TestServerValue) { - // if (this.#originalFormat === value) return; - // TODO: also check if the added values have positions, if not, there's no need to update the structured data. - this.#originalFormat = value; - this._structuredData = this.toStructuredData(value); - } - - get value(): TestServerValue { - return this.#originalFormat; - } - - @property({ attribute: false }) - extensionConfigs: Extension[] = []; - - //TODO: Use the context again so that we can remove items from the extensions list from here. - - @state() - _structuredData: string[][][] = [[[]]]; - - #originalFormat: TestServerValue = []; - - #currentDragAlias?: string; - - #onDragStart = (event: DragEvent, alias: string) => { - this.#currentDragAlias = alias; - event.dataTransfer!.effectAllowed = 'move'; - }; - - #onDragOver = (event: DragEvent) => { - event.preventDefault(); - event.dataTransfer!.dropEffect = 'move'; - }; - - #onDragEnd = (event: DragEvent) => { - event.preventDefault(); - if (event.dataTransfer?.dropEffect === 'none') { - const fromPos = this.#originalFormat.find((item) => item.alias === this.#currentDragAlias)?.position; - if (!fromPos) return; - - this.removeItem(fromPos); - } - }; - - #onDrop = (event: DragEvent, toPos: [number, number, number]) => { - event.preventDefault(); - const fromPos = this.#originalFormat.find((item) => item.alias === this.#currentDragAlias)?.position; - - if (fromPos) { - this.moveItem(fromPos, toPos); - } else if (this.#currentDragAlias) { - this.insertItem(this.#currentDragAlias, toPos); - } - }; - - private moveItem = (from: [number, number, number], to: [number, number, number]) => { - const [rowIndex, groupIndex, itemIndex] = from; - - // Get the item to move from the 'from' position - const itemToMove = this._structuredData[rowIndex][groupIndex][itemIndex]; - - // Remove the item from the original position - this._structuredData[rowIndex][groupIndex].splice(itemIndex, 1); - - this.insertItem(itemToMove, to); - }; - - private insertItem = (alias: string, toPos: [number, number, number]) => { - const [rowIndex, groupIndex, itemIndex] = toPos; - // Insert the item into the new position - this._structuredData[rowIndex][groupIndex].splice(itemIndex, 0, alias); - this.#updateOriginalFormat(); - - this.requestUpdate('_structuredData'); - this.dispatchEvent(new UmbChangeEvent()); - }; - - private removeItem(from: [number, number, number]) { - const [rowIndex, groupIndex, itemIndex] = from; - this._structuredData[rowIndex][groupIndex].splice(itemIndex, 1); - - this.#updateOriginalFormat(); - - this.requestUpdate('_structuredData'); - this.dispatchEvent(new UmbChangeEvent()); - } - - #addGroup = (rowIndex: number, groupIndex: number) => { - this._structuredData[rowIndex].splice(groupIndex, 0, []); - this.requestUpdate('_structuredData'); - }; - - #removeGroup = (rowIndex: number, groupIndex: number) => { - if (rowIndex === 0 && groupIndex === 0) { - // Prevent removing the last group - this._structuredData[rowIndex][groupIndex] = []; - } else { - this._structuredData[rowIndex].splice(groupIndex, 1); - } - this.requestUpdate('_structuredData'); - this.#updateOriginalFormat(); - }; - - #addRow = (rowIndex: number) => { - this._structuredData.splice(rowIndex, 0, [[]]); - this.requestUpdate('_structuredData'); - }; - - #removeRow = (rowIndex: number) => { - if (rowIndex === 0) { - // Prevent removing the last row - this._structuredData[rowIndex] = [[]]; - } else { - this._structuredData.splice(rowIndex, 1); - } - this.requestUpdate('_structuredData'); - this.#updateOriginalFormat(); - }; - - #updateOriginalFormat() { - this.#originalFormat = this.toOriginalFormat(this._structuredData); - this.dispatchEvent(new UmbChangeEvent()); - } - - private renderItem(alias: string) { - const extension = this.extensionConfigs.find((ext) => ext.alias === alias); - if (!extension) return nothing; - return html`
this.#onDragStart(e, alias)}> - -
`; - } - - private renderGroup(group: string[], rowIndex: number, groupIndex: number) { - return html` -
this.#onDrop(e, [rowIndex, groupIndex, group.length])}> - ${group.map((alias) => this.renderItem(alias))} - this.#removeGroup(rowIndex, groupIndex)}> - - -
- `; - } - - private renderRow(row: string[][], rowIndex: number) { - return html` -
- ${repeat(row, (group, groupIndex) => this.renderGroup(group, rowIndex, groupIndex))} - this.#addGroup(rowIndex, row.length)}>+ - this.#removeRow(rowIndex)}> - - -
- `; - } - - override render() { - return html` -

- WIP Feature Rows, groups, and item order have no effect yet.
- However, adding and removing items from the toolbar is functional. Additionally, hiding items from the toolbar - while retaining their functionality by excluding them from the toolbar layout is also functional. -

- ${repeat(this._structuredData, (row, rowIndex) => this.renderRow(row, rowIndex))} - this.#addRow(this._structuredData.length)}>+ - -

Extensions hidden from the toolbar

-
- ${this.#originalFormat?.filter((item) => !item.position).map((item) => this.renderItem(item.alias))} -
- `; - } - - toStructuredData = (data: TestServerValue) => { - if (!data?.length) return [[[]]]; - - const structuredData: string[][][] = [[[]]]; - data.forEach(({ alias, position }) => { - if (!position) return; - - const [rowIndex, groupIndex, aliasIndex] = position; - - while (structuredData.length <= rowIndex) { - structuredData.push([]); - } - - const currentRow = structuredData[rowIndex]; - - while (currentRow.length <= groupIndex) { - currentRow.push([]); - } - - const currentGroup = currentRow[groupIndex]; - - currentGroup[aliasIndex] = alias; - }); - - return structuredData; - }; - - toOriginalFormat = (structuredData: string[][][]) => { - const originalData: TestServerValue = []; - - structuredData.forEach((row, rowIndex) => { - row.forEach((group, groupIndex) => { - group.forEach((alias, aliasIndex) => { - if (alias) { - originalData.push({ - alias, - position: [rowIndex, groupIndex, aliasIndex], - }); - } - }); - }); - }); - - // add items from this.#originalFormat only if they are not already in the structured data. and if they have a position property set, unset it. - this.#originalFormat.forEach((item) => { - if (!originalData.some((i) => i.alias === item.alias)) { - originalData.push({ - alias: item.alias, - }); - } - }); - - // TODO: this code removes the items completely, while the one above just puts them back into the hidden extensions list. Which one do we prefer? - // this.#originalFormat.forEach((item) => { - // if (!item.position) { - // const exists = originalData.find((i) => i.alias === item.alias); - // if (!exists) { - // originalData.push(item); - // } - // } - // }); - - return originalData; - }; - - static override styles = [ - UmbTextStyles, - css` - :host { - display: flex; - flex-direction: column; - gap: 6px; - } - .hidden-extensions { - display: flex; - gap: 6px; - } - .hidden-extensions-header { - margin-bottom: 3px; - } - .row { - position: relative; - display: flex; - gap: 12px; - } - .group { - position: relative; - display: flex; - gap: 3px; - border-radius: var(--uui-border-radius); - background-color: var(--uui-color-surface-alt); - padding: 6px; - min-height: 30px; - min-width: 30px; - } - .item { - padding: var(--uui-size-space-2); - border: 1px solid var(--uui-color-border); - border-radius: var(--uui-border-radius); - background-color: var(--uui-color-surface); - cursor: move; - display: flex; - align-items: baseline; - } - - .remove-row-button, - .remove-group-button { - display: none; - } - .remove-group-button { - position: absolute; - top: -26px; - left: 50%; - transform: translateX(-50%); - z-index: 1; - } - - .row:hover .remove-row-button:not(.hidden), - .group:hover .remove-group-button:not(.hidden) { - display: flex; - } - `, - ]; -} - -export default UmbTiptapToolbarGroupsConfiguration2Element; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tiptap-toolbar-groups-configuration2': UmbTiptapToolbarGroupsConfiguration2Element; - } -}