diff --git a/docs/BREAKING_CHANGES.v3.md b/docs/BREAKING_CHANGES.v3.md index 05b261a5dc..568f82465e 100644 --- a/docs/BREAKING_CHANGES.v3.md +++ b/docs/BREAKING_CHANGES.v3.md @@ -23,6 +23,14 @@ The following components have been removed: - Visually, the tooltip has been replaced by a simple label shown in parentheses after the abbreviation. - The property `_tooltipAlign` has been removed. +### kol-modal + +- The property `_activeElement` has been removed. Use the methods `openModal` and `closeModal` instead. + +### kol-table-stateful + +- The table header property `sort` has been removed. Use `compareFn` instead. + ### kol-input-file - The property `_value` has been removed as it never served a purpose. Use the `getValue()` method instead to access the FileList. @@ -44,6 +52,10 @@ The public `focus`-methods have been removed from all components. Use `kolFocus` - The property `_alert` has been removed. It's now being handled automatically based on `_msg` and the touched state. See #6138. - The property `_error` has been removed. Use `_msg_` instead. +## Toaster + +- The toast default `alertVariant` and options property `defaultAlertVariant` have been removed. Use `variant` and `defaultVariant` instead. + ## Themes ### BMF-Theme (Bundesministerium der Finanzen) diff --git a/packages/components/src/components/modal/modal.e2e.ts b/packages/components/src/components/modal/modal.e2e.ts index 86a905a156..7f4102bcc1 100644 --- a/packages/components/src/components/modal/modal.e2e.ts +++ b/packages/components/src/components/modal/modal.e2e.ts @@ -29,25 +29,7 @@ test.describe('kol-modal', () => { }); }); - test.describe('legacy attribute API', () => { - test('it opens and closes the dialog', async ({ page }) => { - await page.setContent('Modal content'); - const kolModal = page.locator('kol-modal'); - const dialog = page.locator('dialog'); - - await expect(dialog).toBeHidden(); - await kolModal.evaluate((element: HTMLKolModalElement) => { - element._activeElement = document.createElement('button'); - }); - await expect(dialog).toBeVisible(); - await kolModal.evaluate((element: HTMLKolModalElement) => { - element._activeElement = null; - }); - await expect(dialog).toBeHidden(); - }); - }); - - test.describe('Callbacks', () => { + test.describe('events', () => { test('it calls the onClose callback when the closeModal-method has been called', async ({ page }) => { await page.setContent('Modal content'); const kolModal = page.locator('kol-modal'); diff --git a/packages/components/src/components/modal/shadow.tsx b/packages/components/src/components/modal/shadow.tsx index a73cf3c2ad..a57fb50fc6 100644 --- a/packages/components/src/components/modal/shadow.tsx +++ b/packages/components/src/components/modal/shadow.tsx @@ -1,8 +1,7 @@ import type { KoliBriModalEventCallbacks, LabelPropType, ModalAPI, ModalStates } from '../../schema'; -import { setState, validateLabel, watchString, watchValidator } from '../../schema'; +import { setState, validateLabel, watchString } from '../../schema'; import type { JSX } from '@stencil/core'; -import { Method } from '@stencil/core'; -import { Component, Element, h, Prop, State, Watch } from '@stencil/core'; +import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core'; import { dispatchDomEvent, KolEvent } from '../../utils/events'; /** @@ -21,12 +20,6 @@ export class KolModal implements ModalAPI { @Element() private readonly host?: HTMLKolModalElement; private refDialog?: HTMLDialogElement; - public componentDidRender(): void { - if (this.state._activeElement) { - this.refDialog?.showModal(); - } - } - public disconnectedCallback(): void { void this.closeModal(); } @@ -47,8 +40,6 @@ export class KolModal implements ModalAPI { @Method() // eslint-disable-next-line @typescript-eslint/require-await public async closeModal() { - this._activeElement = null; - /* The optional chaining for the `close` method is not strictly necessary, but a simple/lazy workaround for HTMLDialog not being implemented in jsdom, causing Jest tests to fail. It may be removed in the future. */ this.refDialog?.close?.(); } @@ -74,12 +65,6 @@ export class KolModal implements ModalAPI { ); } - /** - * Legacy property - while set to an HTMLElement, the modal is open. - * @deprecated Use methode `openModal` and `closeModal` instead. - */ - @Prop({ mutable: true }) public _activeElement?: HTMLElement | null; - /** * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). */ @@ -96,27 +81,10 @@ export class KolModal implements ModalAPI { @Prop() public _width?: string = '100%'; @State() public state: ModalStates = { - _activeElement: null, _label: '', // ⚠ required _width: '100%', }; - @Watch('_activeElement') - public validateActiveElement(value?: HTMLElement | null): void { - watchValidator(this, '_activeElement', (value): boolean => typeof value === 'object' || value === null, new Set(['HTMLElement', 'null']), value, { - defaultValue: null, - hooks: { - afterPatch: () => { - if (this.state._activeElement) { - void this.openModal(); - } else { - void this.closeModal(); - } - }, - }, - }); - } - @Watch('_label') public validateLabel(value?: LabelPropType): void { validateLabel(this, value, { @@ -143,7 +111,6 @@ export class KolModal implements ModalAPI { } public componentWillLoad(): void { - this.validateActiveElement(this._activeElement); this.validateLabel(this._label); this.validateOn(this._on); this.validateWidth(this._width); diff --git a/packages/components/src/components/table-stateful/shadow.tsx b/packages/components/src/components/table-stateful/shadow.tsx index 0f0f738a30..f10805b687 100644 --- a/packages/components/src/components/table-stateful/shadow.tsx +++ b/packages/components/src/components/table-stateful/shadow.tsx @@ -3,12 +3,10 @@ import type { KoliBriDataCompareFn, KoliBriPaginationButtonCallbacks, KoliBriSortDirection, - KoliBriSortFunction, KoliBriTableDataType, KoliBriTableHeaderCellWithLogic, KoliBriTableHeaders, KoliBriTablePaginationProps, - KoliBriTableSelectedHead, LabelPropType, PaginationPositionPropType, SortEventPayload, @@ -70,25 +68,12 @@ export class KolTableStateful implements TableAPI { this.tableWcRef = ref; }; - /** - * @deprecated only for backward compatibility - */ - private sortFunction?: KoliBriSortFunction; - /** - * @deprecated only for backward compatibility - */ - private sortDirections: Map = new Map(); private sortData: SortData[] = []; private showPagination = false; private pageStartSlice = 0; private pageEndSlice = 10; private disableSort = false; - /** - * @deprecated only for backward compatibility - */ - private sortedColumnHead: KoliBriTableSelectedHead = { label: '', key: '', sortDirection: 'NOS' }; - /** * Defines whether to allow multi sort. */ @@ -185,29 +170,11 @@ export class KolTableStateful implements TableAPI { validatePaginationPosition(this, value); } - /** - * @deprecated only for backward compatibility - */ - private setSortDirection = (sort: KoliBriSortFunction, direction: KoliBriSortDirection) => { - /** - * Durch des Clearen, ist es nicht möglich eine Mehr-Spalten-Sortierung - * darzustellen. Das wäre der Fall, wenn man ggf. Daten in außerhalb der - * Komponente sortiert und diese sortiert von außen rein gibt und der - * Sortierungsalgorithmus mehrere Spalten zusammen sortierte. - * - * Beachte auch col.sort !== this.sortFunction - */ - this.sortDirections.clear(); - this.sortDirections.set(sort, direction); - this.sortFunction = sort; - }; - /** * Handles sorting logic for table columns. * If multi-sort is enabled (`_allowMultiSort`), multiple columns can be sorted at once. * Otherwise, sorting is cleared when switching between columns. */ - private changeCellSort(headerCell: KoliBriTableHeaderCellWithLogic) { if (typeof headerCell.compareFn === 'function') { if (!this.state._allowMultiSort && headerCell.key != this.sortData[0]?.key) { @@ -238,20 +205,7 @@ export class KolTableStateful implements TableAPI { }); } - this.updateSortedData(headerCell as KoliBriTableSelectedHead); - } else if (typeof headerCell.sort === 'function') { - this.sortFunction = headerCell.sort; - switch (this.sortDirections.get(this.sortFunction)) { - case 'ASC': - this.setSortDirection(this.sortFunction, 'DESC'); - break; - case 'DESC': - this.setSortDirection(this.sortFunction, 'NOS'); - break; - default: - this.setSortDirection(this.sortFunction, 'ASC'); - } - this.updateSortedData(headerCell as KoliBriTableSelectedHead); + this.updateSortedData(); } } @@ -292,9 +246,6 @@ export class KolTableStateful implements TableAPI { this.sortData.push({ label: cell.label, key, compareFn: cell.compareFn, direction: sortDirection }); } hasSortedCells = true; - } else if (typeof cell.sort === 'function') { - this.setSortDirection(cell.sort, sortDirection); - setTimeout(() => this.updateSortedData({ key, label: cell.label, sortDirection })); } } }); @@ -439,11 +390,7 @@ export class KolTableStateful implements TableAPI { } } - /** - * - * @param cell only used for old single sort. Can be removed when sort is removed. - */ - private updateSortedData = (cell: KoliBriTableSelectedHead = this.sortedColumnHead) => { + private updateSortedData = () => { if (this.disableSort) { setState(this, '_sortedData', this.state._data); return; @@ -461,21 +408,6 @@ export class KolTableStateful implements TableAPI { } return 0; }); - } else if (typeof this.sortFunction === 'function') { - switch (this.sortDirections.get(this.sortFunction)) { - case 'ASC': - sortedData = this.sortFunction([...this.state._data]); - this.sortedColumnHead = { label: cell.label, key: cell.key, sortDirection: 'ASC' }; - break; - case 'DESC': - sortedData = this.sortFunction([...this.state._data]).reverse(); - this.sortedColumnHead = { label: cell.label, key: cell.key, sortDirection: 'DESC' }; - break; - case 'NOS': - default: - sortedData = [...this.state._data]; - this.sortedColumnHead = { label: '', key: '', sortDirection: 'NOS' }; - } } setState(this, '_sortedData', sortedData); }; @@ -522,10 +454,7 @@ export class KolTableStateful implements TableAPI { } private getHeaderCellSortState(headerCell: KoliBriTableHeaderCellWithLogic): KoliBriSortDirection | undefined { - if (!this.disableSort && (typeof headerCell.compareFn === 'function' || typeof headerCell.sort === 'function')) { - if (headerCell.key === this.sortedColumnHead.key) { - return this.sortedColumnHead.sortDirection; - } + if (!this.disableSort && typeof headerCell.compareFn === 'function') { if (headerCell.key) { const data = this.sortData.find((value) => value.key === headerCell.key); if (data?.direction) { diff --git a/packages/components/src/components/toaster/toaster.tsx b/packages/components/src/components/toaster/toaster.tsx index 88351a6152..ff54de9213 100644 --- a/packages/components/src/components/toaster/toaster.tsx +++ b/packages/components/src/components/toaster/toaster.tsx @@ -48,12 +48,7 @@ export class ToasterService { * so we can't enqueue toasts. */ if (this.toastContainerElement && typeof this.toastContainerElement.enqueue === 'function') { - const defaultVariant = this.options?.defaultVariant ?? undefined; - const defaultAlertVariant = this.options?.defaultAlertVariant ?? undefined; - if (!toast.alertVariant && !toast.variant && this.options) { - toast.variant = defaultAlertVariant ?? defaultVariant; - } - + toast.variant ??= this.options?.defaultVariant; return this.toastContainerElement.enqueue(toast); } } diff --git a/packages/components/src/functional-components/ToastItem/ToastItem.tsx b/packages/components/src/functional-components/ToastItem/ToastItem.tsx index f6cf34c522..0fdead44f9 100644 --- a/packages/components/src/functional-components/ToastItem/ToastItem.tsx +++ b/packages/components/src/functional-components/ToastItem/ToastItem.tsx @@ -12,7 +12,7 @@ type ToastItemProps = JSXBase.HTMLAttributes & { }; const ToastItemFc: FC = ({ status, toast, onClose, ...other }) => { - const { type, label, description, variant, alertVariant } = toast; + const { type, label, description, variant } = toast; return (
@@ -23,7 +23,7 @@ const ToastItemFc: FC = ({ status, toast, onClose, ...other }) = level={0} hasCloser={true} type={type} - variant={alertVariant || variant || 'card'} + variant={variant || 'card'} onCloserClick={onClose} >
{description}
diff --git a/packages/components/src/schema/components/modal.ts b/packages/components/src/schema/components/modal.ts index b048f1d5d4..5129757356 100644 --- a/packages/components/src/schema/components/modal.ts +++ b/packages/components/src/schema/components/modal.ts @@ -5,12 +5,10 @@ import type { KoliBriModalEventCallbacks } from '../types'; type RequiredProps = PropLabel; type OptionalProps = { - activeElement: HTMLElement | null; on: KoliBriModalEventCallbacks; width: string; }; type RequiredStates = { - activeElement: HTMLElement | null; width: string; } & PropLabel; type OptionalStates = { diff --git a/packages/components/src/schema/components/table.ts b/packages/components/src/schema/components/table.ts index 6d5cbc57d2..ff6dc07def 100644 --- a/packages/components/src/schema/components/table.ts +++ b/packages/components/src/schema/components/table.ts @@ -5,19 +5,10 @@ import type { KoliBriTableDataType, KoliBriTableHeaderCell, Stringified, KoliBri import type { KoliBriPaginationProps } from './pagination'; import type { PropPaginationPosition } from '../props/pagination-position'; -export type KoliBriTableSelectedHead = { key: string; label: string; sortDirection: KoliBriSortDirection }; - -type KoliBriTableSort = (data: T[]) => T[]; - -export type KoliBriSortFunction = (data: KoliBriTableDataType[]) => KoliBriTableDataType[]; export type KoliBriDataCompareFn = (a: KoliBriTableDataType, b: KoliBriTableDataType) => number; export type KoliBriTableHeaderCellWithLogic = KoliBriTableHeaderCell & { compareFn?: KoliBriDataCompareFn; - /** - * @deprecated use `compareFn` instead - */ - sort?: KoliBriTableSort; sortDirection?: KoliBriSortDirection; }; diff --git a/packages/components/src/schema/components/toaster.ts b/packages/components/src/schema/components/toaster.ts index 35f23c464d..1667c6e0eb 100644 --- a/packages/components/src/schema/components/toaster.ts +++ b/packages/components/src/schema/components/toaster.ts @@ -13,10 +13,6 @@ export type Toast = { render?: ToastRenderFunction; label: LabelPropType; type: AlertType; - /** - * @deprecated Use variant instead - */ - alertVariant?: AlertVariant; variant?: AlertVariant; }; @@ -27,10 +23,6 @@ export type ToastState = { }; export type ToasterOptions = { - /** - * @deprecated Use defaultVariant instead - */ - defaultAlertVariant: AlertVariant; defaultVariant: AlertVariant; }; diff --git a/packages/samples/react/src/components/handout/basic.tsx b/packages/samples/react/src/components/handout/basic.tsx index 3699d4e8f8..3a939583b1 100644 --- a/packages/samples/react/src/components/handout/basic.tsx +++ b/packages/samples/react/src/components/handout/basic.tsx @@ -73,16 +73,14 @@ const TABLE_HEADERS: KoliBriTableHeaders = { el.appendChild(renderElement); getRoot(renderElement).render(); }, - sort: (data) => { - return data.sort((first, second) => { - if ((first as TableDataType).monday < (second as TableDataType).monday) { - return -1; - } - if ((first as TableDataType).monday > (second as TableDataType).monday) { - return 1; - } - return 0; - }); + compareFn: (first, second) => { + if ((first as TableDataType).monday < (second as TableDataType).monday) { + return -1; + } + if ((first as TableDataType).monday > (second as TableDataType).monday) { + return 1; + } + return 0; }, sortDirection: 'ASC', textAlign: 'right', @@ -97,16 +95,14 @@ const TABLE_HEADERS: KoliBriTableHeaders = { el.appendChild(renderElement); getRoot(renderElement).render(); }, - sort: (data) => { - return data.sort((first, second) => { - if ((first as TableDataType).tuesday < (second as TableDataType).tuesday) { - return -1; - } - if ((first as TableDataType).tuesday > (second as TableDataType).tuesday) { - return 1; - } - return 0; - }); + compareFn: (first, second) => { + if ((first as TableDataType).tuesday < (second as TableDataType).tuesday) { + return -1; + } + if ((first as TableDataType).tuesday > (second as TableDataType).tuesday) { + return 1; + } + return 0; }, sortDirection: 'DESC', }, diff --git a/packages/samples/react/src/components/table/column-alignment.tsx b/packages/samples/react/src/components/table/column-alignment.tsx index 1b8cb70117..ac8367ba39 100644 --- a/packages/samples/react/src/components/table/column-alignment.tsx +++ b/packages/samples/react/src/components/table/column-alignment.tsx @@ -6,7 +6,7 @@ import { KolHeading, KolTableStateful } from '@public-ui/react'; import { SampleDescription } from '../SampleDescription'; const DATA = [{ left: 'Left Example', center: 'Center Example', right: 'Right Example' }]; -const genericNonSorter = (data: T): T => data; +const genericNonSorter = () => 0; export const TableColumnAlignment: FC = () => ( <> @@ -38,9 +38,9 @@ export const TableColumnAlignment: FC = () => ( _headers={{ horizontal: [ [ - { label: 'left', key: 'left', textAlign: 'left', sort: genericNonSorter }, - { label: 'center', key: 'center', textAlign: 'center', sort: genericNonSorter }, - { label: 'right', key: 'right', textAlign: 'right', sort: genericNonSorter }, + { label: 'left', key: 'left', textAlign: 'left', compareFn: genericNonSorter }, + { label: 'center', key: 'center', textAlign: 'center', compareFn: genericNonSorter }, + { label: 'right', key: 'right', textAlign: 'right', compareFn: genericNonSorter }, ], ], }} @@ -55,8 +55,8 @@ export const TableColumnAlignment: FC = () => ( _headers={{ horizontal: [ [ - { label: 'left', key: 'left', textAlign: 'left', sort: genericNonSorter }, - { label: 'center', key: 'center', textAlign: 'center', sort: genericNonSorter }, + { label: 'left', key: 'left', textAlign: 'left', compareFn: genericNonSorter }, + { label: 'center', key: 'center', textAlign: 'center', compareFn: genericNonSorter }, { label: 'right', key: 'right', textAlign: 'right' }, ], ], diff --git a/packages/samples/react/src/components/table/render-cell.tsx b/packages/samples/react/src/components/table/render-cell.tsx index ed6d2b9573..f570a61f26 100644 --- a/packages/samples/react/src/components/table/render-cell.tsx +++ b/packages/samples/react/src/components/table/render-cell.tsx @@ -80,7 +80,7 @@ const HEADERS: KoliBriTableHeaders = { render: (el, cell) => { el.innerHTML = `${DATE_FORMATTER.format(cell.label as unknown as Date)}`; }, - sort: (data) => data.sort((data0, data1) => (data0 as Data).date.getTime() - (data1 as Data).date.getTime()), + compareFn: (data0, data1) => (data0 as Data).date.getTime() - (data1 as Data).date.getTime(), }, { label: 'Action (react)', diff --git a/packages/samples/react/src/components/table/sort-data.tsx b/packages/samples/react/src/components/table/sort-data.tsx index 648cff1259..8ddf37ff07 100644 --- a/packages/samples/react/src/components/table/sort-data.tsx +++ b/packages/samples/react/src/components/table/sort-data.tsx @@ -22,12 +22,11 @@ const HEADERS_HORIZONTAL: KoliBriTableHeaders = { key: 'date', textAlign: 'center', render: (_el, _cell, tupel) => DATE_FORMATTER.format((tupel as Data).date), - sort: (data) => - data.sort((data0, data1) => { - if ((data0 as Data).date < (data1 as Data).date) return -1; - else if ((data1 as Data).date < (data0 as Data).date) return 1; - else return 0; - }), + compareFn: (data0, data1) => { + if ((data0 as Data).date < (data1 as Data).date) return -1; + else if ((data1 as Data).date < (data0 as Data).date) return 1; + else return 0; + }, }, ], ], @@ -42,12 +41,11 @@ const HEADERS_VERTICAL: KoliBriTableHeaders = { key: 'date', textAlign: 'center', render: (_el, _cell, tupel) => DATE_FORMATTER.format((tupel as Data).date), - sort: (data) => - data.sort((data0, data1) => { - if ((data0 as Data).date < (data1 as Data).date) return -1; - else if ((data1 as Data).date < (data0 as Data).date) return 1; - else return 0; - }), + compareFn: (data0, data1) => { + if ((data0 as Data).date < (data1 as Data).date) return -1; + else if ((data1 as Data).date < (data0 as Data).date) return 1; + else return 0; + }, }, ], ],