Skip to content

Commit

Permalink
Refactor table components to enforce min-width type will be required (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
deleonio authored Feb 14, 2025
2 parents 32eea84 + ccbcc1c commit f71d262
Show file tree
Hide file tree
Showing 27 changed files with 122 additions and 59 deletions.
3 changes: 2 additions & 1 deletion packages/components/src/components/modal/shadow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { setState, validateLabel, watchString } from '../../schema';
import type { JSX } from '@stencil/core';
import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core';
import { dispatchDomEvent, KolEvent } from '../../utils/events';
import { ModalVariantPropType, validateModalVariant } from '../../schema/props/variant/modal';
import type { ModalVariantPropType } from '../../schema/props/variant/modal';
import { validateModalVariant } from '../../schema/props/variant/modal';
import { KolButtonWcTag } from '../../core/component-names';
import { translate } from '../../i18n';
import clsx from 'clsx';
Expand Down
17 changes: 9 additions & 8 deletions packages/components/src/components/table-stateful/shadow.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
import type { JSX } from '@stencil/core';
import { Component, Element, h, Host, Method, Prop, State, Watch } from '@stencil/core';
import { KolPaginationTag, KolTableStatelessWcTag } from '../../core/component-names';
import { translate } from '../../i18n';
import type {
KoliBriDataCompareFn,
KoliBriPaginationButtonCallbacks,
Expand Down Expand Up @@ -34,13 +38,9 @@ import {
watchString,
watchValidator,
} from '../../schema';
import type { JSX } from '@stencil/core';
import { Component, Element, h, Host, Method, Prop, State, Watch } from '@stencil/core';

import { translate } from '../../i18n';
import { KolPaginationTag, KolTableStatelessWcTag } from '../../core/component-names';
import { dispatchDomEvent, KolEvent } from '../../utils/events';
import { Callback } from '../../schema/enums';
import type { MinWidthPropType } from '../../schema/props/min-width';
import { dispatchDomEvent, KolEvent } from '../../utils/events';

const PAGINATION_OPTIONS = [10, 20, 50, 100];

Expand Down Expand Up @@ -100,9 +100,9 @@ export class KolTableStateful implements TableAPI {
@Prop() public _label!: string;

/**
* Defines the table min-width.
* Defines the table min-width (CSS width values).
*/
@Prop() public _minWidth?: string;
@Prop() public _minWidth!: MinWidthPropType;

/**
* Defines whether to show the data distributed over multiple pages.
Expand Down Expand Up @@ -130,6 +130,7 @@ export class KolTableStateful implements TableAPI {
vertical: [],
},
_label: '', // ⚠ required
_minWidth: 'auto',
_pagination: {
_page: 1,
_pageSize: 10,
Expand Down
18 changes: 9 additions & 9 deletions packages/components/src/components/table-stateless/component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { JSX } from '@stencil/core';
import { Component, Element, Fragment, h, Listen, Prop, State, Watch } from '@stencil/core';

import clsx from 'clsx';
import { KolButtonWcTag, KolIconTag, KolTooltipWcTag } from '../../core/component-names';
import type { TranslationKey } from '../../i18n';
import { translate } from '../../i18n';
Expand Down Expand Up @@ -28,12 +29,12 @@ import {
validateTableDataFoot,
validateTableHeaderCells,
validateTableSelection,
watchString,
} from '../../schema';
import { Callback } from '../../schema/enums';
import type { MinWidthPropType } from '../../schema/props/min-width';
import { validateMinWidth } from '../../schema/props/min-width';
import { nonce } from '../../utils/dev.utils';
import { dispatchDomEvent, KolEvent } from '../../utils/events';
import clsx from 'clsx';

/**
* @internal
Expand All @@ -47,11 +48,12 @@ export class KolTableStateless implements TableStatelessAPI {

@State() public state: TableStatelessStates = {
_data: [],
_label: '',
_headerCells: {
horizontal: [],
vertical: [],
},
_label: '',
_minWidth: 'auto',
};

private tableDivElement?: HTMLDivElement;
Expand Down Expand Up @@ -86,9 +88,9 @@ export class KolTableStateless implements TableStatelessAPI {
@Prop() public _label!: string;

/**
* Defines the table min-width.
* Defines the table min-width (CSS width values).
*/
@Prop() public _minWidth?: string;
@Prop() public _minWidth!: MinWidthPropType;

/**
* Defines the callback functions for table events.
Expand Down Expand Up @@ -127,10 +129,8 @@ export class KolTableStateless implements TableStatelessAPI {
}

@Watch('_minWidth')
public validateMinWidth(value?: string): void {
watchString(this, '_minWidth', value, {
defaultValue: undefined,
});
public validateMinWidth(value?: MinWidthPropType): void {
validateMinWidth(this, value);
}

@Watch('_on')
Expand Down
10 changes: 5 additions & 5 deletions packages/components/src/components/table-stateless/shadow.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { JSX } from '@stencil/core';
import { Component, h, Prop } from '@stencil/core';

import { KolTableStatelessWcTag } from '../../core/component-names';
import type {
TableCallbacksPropType,
TableDataFootPropType,
TableDataPropType,
TableHeaderCellsPropType,
TableStatelessProps,
TableCallbacksPropType,
TableSelectionPropType,
TableStatelessProps,
} from '../../schema';
import type { MinWidthPropType } from '../../schema/props/min-width';

@Component({
tag: 'kol-table-stateless',
Expand Down Expand Up @@ -40,9 +40,9 @@ export class KolTableStateless implements TableStatelessProps {
@Prop() public _label!: string;

/**
* Defines the table min-width.
* Defines the table min-width (CSS width values).
*/
@Prop() public _minWidth?: string;
@Prop() public _minWidth!: MinWidthPropType;

/**
* Defines the callback functions for table events.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`kol-table-stateless-wc should render with _label="Table with horizontal and vertical headers" _headerCells={"horizontal":[[{"key":"header1","label":"Header1","textAlign":"left"},{"key":"header2","label":"Header2","textAlign":"center"},{"key":"header3","label":"Header3","textAlign":"right"}]],"vertical":[[{"key":"row1","label":"Row 1","textAlign":"left"},{"key":"row2","label":"Row 2","textAlign":"center"},{"key":"row3","label":"Row 3","textAlign":"right"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2","header3":"Cell 1.3"},{"header1":"Cell 2.1","header2":"Cell 2.2","header3":"Cell 2.3"},{"header1":"Cell 3.1","header2":"Cell 3.2","header3":"Cell 3.3"}] 1`] = `
exports[`kol-table-stateless-wc should render with _label="Table with horizontal and vertical headers" _minWidth="400px" _headerCells={"horizontal":[[{"key":"header1","label":"Header1","textAlign":"left"},{"key":"header2","label":"Header2","textAlign":"center"},{"key":"header3","label":"Header3","textAlign":"right"}]],"vertical":[[{"key":"row1","label":"Row 1","textAlign":"left"},{"key":"row2","label":"Row 2","textAlign":"center"},{"key":"row3","label":"Row 3","textAlign":"right"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2","header3":"Cell 1.3"},{"header1":"Cell 2.1","header2":"Cell 2.2","header3":"Cell 2.3"},{"header1":"Cell 3.1","header2":"Cell 3.2","header3":"Cell 3.3"}] 1`] = `
<kol-table-stateless-wc>
<div class="kol-table">
<table class="kol-table__table">
<table class="kol-table__table" style="min-width: 400px;">
<div aria-describedby="caption" class="kol-table__focus-element"></div>
<caption class="kol-table__caption" id="caption">
Table with horizontal and vertical headers
Expand Down Expand Up @@ -74,10 +74,10 @@ exports[`kol-table-stateless-wc should render with _label="Table with horizontal
</kol-table-stateless-wc>
`;

exports[`kol-table-stateless-wc should render with _label="Table with only horizontal headers" _headerCells={"horizontal":[[{"key":"header1","label":"Header 1","textAlign":"left"},{"key":"header2","label":"Header 2","textAlign":"center"}]],"vertical":[]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
exports[`kol-table-stateless-wc should render with _label="Table with only horizontal headers" _minWidth="400px" _headerCells={"horizontal":[[{"key":"header1","label":"Header 1","textAlign":"left"},{"key":"header2","label":"Header 2","textAlign":"center"}]],"vertical":[]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
<kol-table-stateless-wc>
<div class="kol-table">
<table class="kol-table__table">
<table class="kol-table__table" style="min-width: 400px;">
<div aria-describedby="caption" class="kol-table__focus-element"></div>
<caption class="kol-table__caption" id="caption">
Table with only horizontal headers
Expand Down Expand Up @@ -118,10 +118,10 @@ exports[`kol-table-stateless-wc should render with _label="Table with only horiz
</kol-table-stateless-wc>
`;

exports[`kol-table-stateless-wc should render with _label="Table with two horizontal header rows" _headerCells={"horizontal":[[{"label":"Header 1","textAlign":"left"},{"label":"Header 2","textAlign":"center"}],[{"key":"header1","label":"Sub Header 1","textAlign":"left"},{"key":"header2","label":"Sub Header 2","textAlign":"center"}]],"vertical":[[{"key":"row-1","label":"Row 1","textAlign":"left"},{"key":"row-2","label":"Row 2","textAlign":"center"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
exports[`kol-table-stateless-wc should render with _label="Table with two horizontal header rows" _minWidth="400px" _headerCells={"horizontal":[[{"label":"Header 1","textAlign":"left"},{"label":"Header 2","textAlign":"center"}],[{"key":"header1","label":"Sub Header 1","textAlign":"left"},{"key":"header2","label":"Sub Header 2","textAlign":"center"}]],"vertical":[[{"key":"row-1","label":"Row 1","textAlign":"left"},{"key":"row-2","label":"Row 2","textAlign":"center"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
<kol-table-stateless-wc>
<div class="kol-table">
<table class="kol-table__table">
<table class="kol-table__table" style="min-width: 400px;">
<div aria-describedby="caption" class="kol-table__focus-element"></div>
<caption class="kol-table__caption" id="caption">
Table with two horizontal header rows
Expand Down Expand Up @@ -177,10 +177,10 @@ exports[`kol-table-stateless-wc should render with _label="Table with two horizo
</kol-table-stateless-wc>
`;

exports[`kol-table-stateless-wc should render with _label="Table with two spanned horizontal and vertical headers" _headerCells={"horizontal":[[{"label":"H-Header","colSpan":2}],[{"key":"header1","label":"Sub H-Header 1"},{"key":"header2","label":"Sub H-Header 2"}]],"vertical":[[{"label":"V-Header","rowSpan":2}],[{"label":"Sub V-Header 1"},{"label":"Sub V-Header 2"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
exports[`kol-table-stateless-wc should render with _label="Table with two spanned horizontal and vertical headers" _minWidth="400px" _headerCells={"horizontal":[[{"label":"H-Header","colSpan":2}],[{"key":"header1","label":"Sub H-Header 1"},{"key":"header2","label":"Sub H-Header 2"}]],"vertical":[[{"label":"V-Header","rowSpan":2}],[{"label":"Sub V-Header 1"},{"label":"Sub V-Header 2"}]]} _data=[{"header1":"Cell 1.1","header2":"Cell 1.2"},{"header1":"Cell 2.1","header2":"Cell 2.2"}] 1`] = `
<kol-table-stateless-wc>
<div class="kol-table">
<table class="kol-table__table">
<table class="kol-table__table" style="min-width: 400px;">
<div aria-describedby="caption" class="kol-table__focus-element"></div>
<caption class="kol-table__caption" id="caption">
Table with two spanned horizontal and vertical headers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ executeSnapshotTests<TableStatelessProps>(
[
{
_label: 'Table with horizontal and vertical headers',
_minWidth: '400px',
_headerCells: {
horizontal: [
[
Expand All @@ -34,6 +35,7 @@ executeSnapshotTests<TableStatelessProps>(
},
{
_label: 'Table with only horizontal headers',
_minWidth: '400px',
_headerCells: {
horizontal: [
[
Expand All @@ -50,6 +52,7 @@ executeSnapshotTests<TableStatelessProps>(
},
{
_label: 'Table with two horizontal header rows',
_minWidth: '400px',
_headerCells: {
horizontal: [
[
Expand All @@ -75,6 +78,7 @@ executeSnapshotTests<TableStatelessProps>(
},
{
_label: 'Table with two spanned horizontal and vertical headers',
_minWidth: '400px',
_headerCells: {
horizontal: [
[{ label: 'H-Header', colSpan: 2 }],
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/schema/components/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Generic } from 'adopted-style-sheets';

import type { PropLabel } from '../props';
import type { KoliBriModalEventCallbacks } from '../types';
import { PropModalVariant } from '../props/variant/modal';
import type { PropModalVariant } from '../props/variant/modal';

type RequiredProps = PropLabel;
type OptionalProps = {
Expand Down
15 changes: 8 additions & 7 deletions packages/components/src/schema/components/table.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { Generic } from 'adopted-style-sheets';

import type { PropLabel, StatefulPropTableCallbacks, PropTableData, PropTableDataFoot, PropTableSelection } from '../props';
import type { KoliBriTableDataType, KoliBriTableHeaderCell, Stringified, KoliBriSortDirection, KoliBriTableSelection } from '../types';
import type { KoliBriPaginationProps } from './pagination';
import type { PropLabel, PropTableData, PropTableDataFoot, PropTableSelection, StatefulPropTableCallbacks } from '../props';
import type { PropMinWidth } from '../props/min-width';
import type { PropPaginationPosition } from '../props/pagination-position';
import type { KoliBriSortDirection, KoliBriTableDataType, KoliBriTableHeaderCell, KoliBriTableSelection, Stringified } from '../types';
import type { KoliBriPaginationProps } from './pagination';

export type KoliBriDataCompareFn = (a: KoliBriTableDataType, b: KoliBriTableDataType) => number;

Expand Down Expand Up @@ -34,11 +35,11 @@ type KoliBriTablePaginationStates = Generic.Element.Members<

type RequiredProps = {
headers: Stringified<KoliBriTableHeaders>;
} & PropTableData &
PropLabel;
} & PropLabel &
PropMinWidth &
PropTableData;
type OptionalProps = {
allowMultiSort: boolean;
minWidth: string;
pagination: boolean | Stringified<KoliBriTablePaginationProps>;
} & PropTableDataFoot &
PropPaginationPosition &
Expand All @@ -53,9 +54,9 @@ type RequiredStates = {
pagination: KoliBriTablePaginationStates;
sortedData: KoliBriTableDataType[];
} & PropLabel &
PropMinWidth &
PropPaginationPosition;
type OptionalStates = {
minWidth: string;
sortDirection: KoliBriSortDirection;
selection: KoliBriTableSelection;
} & StatefulPropTableCallbacks;
Expand Down
16 changes: 6 additions & 10 deletions packages/components/src/schema/components/tableStateless.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import type { Generic } from 'adopted-style-sheets';

import type { PropLabel, PropTableCallbacks, PropTableData, PropTableDataFoot, PropTableSelection, TableHeaderCells } from '../props';
import type { KoliBriTableDataType, KoliBriTableSelection } from '../types';
import type { PropMinWidth } from '../props/min-width';
import type { PropTableHeaderCells } from '../props/table-header-cells';
import type { KoliBriTableDataType, KoliBriTableSelection } from '../types';

type RequiredProps = PropLabel & PropTableData & PropTableHeaderCells;
type RequiredProps = PropLabel & PropMinWidth & PropTableData & PropTableHeaderCells;

type OptionalProps = {
minWidth: string;
} & PropTableCallbacks &
PropTableDataFoot &
PropTableSelection;
type OptionalProps = PropTableCallbacks & PropTableDataFoot & PropTableSelection;

type RequiredStates = {
headerCells: TableHeaderCells;
data: KoliBriTableDataType[];
} & PropLabel;
} & PropLabel &
PropMinWidth;

type OptionalStates = {
minWidth: string;
dataFoot: KoliBriTableDataType[];
selection: KoliBriTableSelection;
} & PropTableCallbacks;
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/schema/props/error-list.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Generic } from 'adopted-style-sheets';
import { EventCallback } from '../types';
import type { EventCallback } from '../types';
import { watchValidator } from '../utils';

/* types */
Expand Down
31 changes: 31 additions & 0 deletions packages/components/src/schema/props/min-width.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Generic } from 'adopted-style-sheets';
import type { WatchStringOptions } from '../utils';
import { watchValidator } from '../utils';

/* types */
export type MinWidthPropType = string;

/**
* Defines the technical name of an input field.
*/
export type PropMinWidth = {
minWidth: MinWidthPropType;
};

/* constants */
/**
* Regular expression to validate the width of a header cell.
*/
const HEADER_CELL_WIDTH_VALIDATOR = /^\d+(\.\d+)?([a-z]+|%)?$/;

/* validator */
export const validateMinWidth = (component: Generic.Element.Component, value?: MinWidthPropType, options?: WatchStringOptions): void => {
watchValidator<MinWidthPropType>(
component,
'_minWidth',
(v) => typeof v === 'string' && HEADER_CELL_WIDTH_VALIDATOR.test(v),
new Set(['String', '/^\\d+(\\.\\d+)?([a-z]+|%)?$/']),
value,
options,
);
};
19 changes: 15 additions & 4 deletions packages/components/src/schema/props/table-header-cells.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Generic } from 'adopted-style-sheets';
import { emptyStringByArrayHandler, objectObjectHandler, parseJson, watchValidator } from '../utils';
import type { KoliBriTableHeaderCell, Stringified } from '../types';
import { emptyStringByArrayHandler, objectObjectHandler, parseJson, watchValidator } from '../utils';

/* types */
export type TableHeaderCells = {
Expand All @@ -23,11 +23,22 @@ export const validateTableHeaderCells = (component: Generic.Element.Component, v
objectObjectHandler(value, () => {
try {
value = parseJson<TableHeaderCells>(value);
// eslint-disable-next-line no-empty
} catch (e) {
// value keeps the original data
void e;
}
watchValidator(component, '_headerCells', (value): boolean => typeof value === 'object' && value !== null, new Set(['TableHeaderCellsPropType']), value);
watchValidator(
component,
'_headerCells',
(value): boolean =>
typeof value === 'object' &&
value !== null &&
(value.horizontal === undefined ||
(Array.isArray(value.horizontal) && value.horizontal.find((headerRow) => !Array.isArray(headerRow)) === undefined)) &&
(value.vertical === undefined || (Array.isArray(value.vertical) && value.vertical.find((headerCol) => !Array.isArray(headerCol)) === undefined)) &&
true,
new Set(['TableHeaderCellsPropType']),
value,
);
});
});
};
2 changes: 1 addition & 1 deletion packages/samples/react/src/components/handout/basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ export const HandoutBasic: FC = () => {
</KolCard>
<KolCard className="col-span-6 sm:col-span-6 md:col-span-4 xl:col-span-5" _label="Table with Pagination" _level={2}>
<div slot="" className="grid gap-2 p-2">
<KolTableStateful _label="Table" _headers={TABLE_HEADERS} _data={TABLE_DATA} _pagination></KolTableStateful>
<KolTableStateful _label="Table" _minWidth="auto" _headers={TABLE_HEADERS} _data={TABLE_DATA} _pagination></KolTableStateful>
</div>
</KolCard>
</div>
Expand Down
Loading

0 comments on commit f71d262

Please sign in to comment.