Skip to content

Commit

Permalink
Expansion table selection (#6634)
Browse files Browse the repository at this point in the history
  • Loading branch information
deleonio authored Jul 19, 2024
2 parents 3eedec5 + 7de96dd commit fbb5fbd
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 43 deletions.
112 changes: 70 additions & 42 deletions packages/components/src/components/table-stateless/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
watchString,
} from '../../schema';
import { KolButtonWcTag, KolInputCheckboxTag } from '../../core/component-names';
import type { TranslationKey } from '../../i18n';
import { translate } from '../../i18n';
import { tryToDispatchKoliBriEvent } from '../../utils/events';
import { Events } from '../../schema/enums';
Expand Down Expand Up @@ -378,43 +379,36 @@ export class KolTableStateless implements TableStatelessAPI {
}

private renderSelectionCell(row: (KoliBriTableCell & KoliBriTableDataType)[], rowIndex: number): JSX.Element {
if (this.state._selection) {
const keyPropertyName = this.state._selection.keyPropertyName ?? 'id';
const keyCell = row.find((cell) => cell.key === keyPropertyName);

if (keyCell) {
const keyProperty = (keyCell?.data as KoliBriTableDataType)[keyPropertyName] as string;
const selected = this.state._selection?.selectedKeys?.includes(keyProperty);
const label = this.state._selection.label(keyCell.data as KoliBriTableDataType);

return (
<td key={`tbody-${rowIndex}-selection`} class="selection-cell">
<KolInputCheckboxTag
_label={label}
_hideLabel
_checked={selected}
_tooltipAlign="right"
_on={{
onInput: (event: Event, value) => {
if (this.state._selection?.selectedKeys) {
const updatedSelectedKeys = value
? [...this.state._selection.selectedKeys, keyProperty]
: this.state._selection.selectedKeys.filter((key) => key !== keyProperty);

tryToDispatchKoliBriEvent('selection-change', this.host, updatedSelectedKeys);
if (typeof this.state._on?.[Events.onSelectionChange] === 'function') {
this.state._on[Events.onSelectionChange](event, updatedSelectedKeys);
}
}
},
}}
/>
</td>
);
}
}
if (!this.state._selection) return '';
const keyPropertyName = this.state._selection.keyPropertyName ?? 'id';
const keyCell = row.find((cell) => cell.key === keyPropertyName);

if (!keyCell) return '';
const keyProperty = (keyCell?.data as KoliBriTableDataType)[keyPropertyName] as string;
const selected = this.state._selection?.selectedKeys?.includes(keyProperty);
const label = this.state._selection.label(keyCell.data as KoliBriTableDataType);

return '';
return (
<td key={`tbody-${rowIndex}-selection`} class="selection-cell">
<KolInputCheckboxTag
_label={label}
_hideLabel
_checked={selected}
_tooltipAlign="right"
_on={{
onInput: (event: Event, value) => {
const updatedSelectedKeys = value
? [...(this.state._selection?.selectedKeys ?? []), keyProperty]
: this.state._selection?.selectedKeys?.filter((key) => key !== keyProperty);
tryToDispatchKoliBriEvent('selection-change', this.host, updatedSelectedKeys);
if (typeof this.state._on?.[Events.onSelectionChange] === 'function') {
this.state._on[Events.onSelectionChange](event, updatedSelectedKeys ?? []);
}
},
}}
/>
</td>
);
}

private readonly renderTableRow = (row: (KoliBriTableCell & KoliBriTableDataType)[], rowIndex: number): JSX.Element => {
Expand All @@ -435,11 +429,7 @@ export class KolTableStateless implements TableStatelessAPI {
let key = `${rowIndex}-${colIndex}-${cell.label}`;
if (cell.data) {
const dataKey = this.getDataKey(cell.data);
if (this.horizontal) {
key = dataKey ? `${dataKey}-${colIndex}` : key;
} else {
key = dataKey ? `${dataKey}-${rowIndex}` : key;
}
key = dataKey ? `${dataKey}-${this.horizontal ? colIndex : rowIndex}` : key;
}

if (cell.asTd === false) {
Expand Down Expand Up @@ -471,6 +461,44 @@ export class KolTableStateless implements TableStatelessAPI {
}
};

private renderHeadingSelectionCell(): JSX.Element {
if (!this.state._selection) return '';
const selectedKeyLength = this.state._selection.selectedKeys?.length;
const dataLength = this.state._data.length;
const isChecked = selectedKeyLength === dataLength;
const intermediate = selectedKeyLength !== 0 && !isChecked;
let translationKey = 'kol-table-selection-intermediate' as TranslationKey;
if (isChecked && !intermediate) {
translationKey = 'kol-table-selection-none';
}
if (selectedKeyLength === 0) {
translationKey = 'kol-table-selection-all';
}
return (
<th key={`thead-0-selection`} class="selection-cell selection-control">
<KolInputCheckboxTag
_label={translate(translationKey)}
_hideLabel
_checked={isChecked && !intermediate}
_indeterminate={intermediate}
_tooltipAlign="right"
_on={{
onInput: (event: Event, value) => {
let selections = [] as KoliBriTableDataType[];
if (value || !isChecked) {
selections = this.state._data;
}
tryToDispatchKoliBriEvent('selection-change', this.host, selections);
if (typeof this.state._on?.[Events.onSelectionChange] === 'function') {
this.state._on[Events.onSelectionChange](event, selections.map((el) => el?.id) as string[]);
}
},
}}
/>
</th>
);
}

private renderHeadingCell(cell: KoliBriTableHeaderCell, rowIndex: number, colIndex: number): JSX.Element {
let ariaSort = undefined;
let sortButtonIcon = 'codicon codicon-fold';
Expand Down Expand Up @@ -565,7 +593,7 @@ export class KolTableStateless implements TableStatelessAPI {
<thead>
{this.state._headerCells.horizontal.map((cols, rowIndex) => (
<tr key={`thead-${rowIndex}`}>
{this.state._selection && <td key="thead-selection" class="selection-header-cell"></td>}
{this.state._selection && this.renderHeadingSelectionCell()}
{cols.map((cell, colIndex) => {
if (cell.asTd === true) {
return (
Expand Down
4 changes: 3 additions & 1 deletion packages/components/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ type Options = {
placeholders?: { [K: string]: string };
};

export let translate = (key: `${Lowercase<ResourcePrefix>}-${Lowercase<ComponentKeys>}`, options?: Options) => {
export type TranslationKey = `${Lowercase<ResourcePrefix>}-${Lowercase<ComponentKeys>}`;

export let translate = (key: TranslationKey, options?: Options) => {
const i18n = getI18nInstance() ?? initializeI18n('de');
return i18n.translate(key, options);
};
Expand Down
3 changes: 3 additions & 0 deletions packages/components/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export default {
'error-list-message': 'Bitte korrigieren Sie folgende Fehler:',
version: 'Versionsnummer',
'table-visible-range': 'Einträge {{start}} bis {{end}} von {{total}}',
'table-selection-all': 'Alle auswählen',
'table-selection-none': 'Alle abwählen',
'table-selection-intermediate': 'Alle auswählen bei teilweiser Auswahl',
dropdown: 'Auswahlliste',
'nav-label-open': 'Untermenü zu {{label}} öffnen',
'nav-label-close': 'Untermenü zu {{label}} schließen',
Expand Down
3 changes: 3 additions & 0 deletions packages/components/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export default {
'error-list-message': 'Please correct the following errors',
version: 'Version number',
'table-visible-range': 'Entries {{start}} to {{end}} of {{total}}',
'table-selection-all': 'Select all',
'table-selection-none': 'Deselect all',
'table-selection-intermediate': 'Select all with partial selection',
dropdown: 'Dropdown',
'nav-label-open': 'Submenu for {{label}} open',
'nav-label-close': 'Submenu for {{label}} close',
Expand Down

0 comments on commit fbb5fbd

Please sign in to comment.