Skip to content

SPIKE - Do not merge - Resizable column exploration #2828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
@@ -134,12 +134,14 @@
"./components/hds/accordion/item/index.js": "./dist/_app_/components/hds/accordion/item/index.js",
"./components/hds/advanced-table/expandable-tr-group.js": "./dist/_app_/components/hds/advanced-table/expandable-tr-group.js",
"./components/hds/advanced-table/index.js": "./dist/_app_/components/hds/advanced-table/index.js",
"./components/hds/advanced-table/models/column.js": "./dist/_app_/components/hds/advanced-table/models/column.js",
"./components/hds/advanced-table/models/row.js": "./dist/_app_/components/hds/advanced-table/models/row.js",
"./components/hds/advanced-table/models/table.js": "./dist/_app_/components/hds/advanced-table/models/table.js",
"./components/hds/advanced-table/td.js": "./dist/_app_/components/hds/advanced-table/td.js",
"./components/hds/advanced-table/th-button-expand.js": "./dist/_app_/components/hds/advanced-table/th-button-expand.js",
"./components/hds/advanced-table/th-button-sort.js": "./dist/_app_/components/hds/advanced-table/th-button-sort.js",
"./components/hds/advanced-table/th-button-tooltip.js": "./dist/_app_/components/hds/advanced-table/th-button-tooltip.js",
"./components/hds/advanced-table/th-resize-handle.js": "./dist/_app_/components/hds/advanced-table/th-resize-handle.js",
"./components/hds/advanced-table/th-selectable.js": "./dist/_app_/components/hds/advanced-table/th-selectable.js",
"./components/hds/advanced-table/th-sort.js": "./dist/_app_/components/hds/advanced-table/th-sort.js",
"./components/hds/advanced-table/th.js": "./dist/_app_/components/hds/advanced-table/th.js",
17 changes: 11 additions & 6 deletions packages/components/src/components/hds/advanced-table/index.hbs
Original file line number Diff line number Diff line change
@@ -38,11 +38,11 @@
@hasStickyColumn={{@hasStickyFirstColumn}}
@isStickyColumnPinned={{this.isStickyColumnPinned}}
>
{{#each @columns as |column index|}}
{{#each this._tableModel.orderedColumns as |column index|}}
{{#if column.isSortable}}
<Hds::AdvancedTable::ThSort
@sortOrder={{if (eq column.key this._sortBy) this._sortOrder}}
@onClickSort={{fn this.setSortBy column.key}}
@onClickSort={{if column.key (fn this.setSortBy column.key)}}
@align={{column.align}}
@tooltip={{column.tooltip}}
@isStickyColumn={{if (and (eq index 0) @hasStickyFirstColumn) true}}
@@ -53,6 +53,7 @@
{{else}}
<Hds::AdvancedTable::Th
@align={{column.align}}
@column={{column}}
@tooltip={{column.tooltip}}
@isVisuallyHidden={{column.isVisuallyHidden}}
@isExpandable={{column.isExpandable}}
@@ -61,6 +62,8 @@
@hasExpandAllButton={{this._tableModel.hasRowsWithChildren}}
@isStickyColumn={{if (and (eq index 0) @hasStickyFirstColumn) true}}
@isStickyColumnPinned={{this.isStickyColumnPinned}}
@onReorderDragStart={{fn (mut this._tableModel.reorderDraggedColumn)}}
@onReorderDrop={{this._tableModel.reorderColumn}}
>
{{column.label}}
</Hds::AdvancedTable::Th>
@@ -92,6 +95,7 @@
isParentRow=T.isExpandable
depth=T.depth
displayRow=T.shouldDisplayChildRows
data=T.data
)
Th=(component
"hds/advanced-table/th"
@@ -105,17 +109,16 @@
)
Td=(component "hds/advanced-table/td" align=@align)
data=T.data
columns=@columns
isOpen=T.isExpanded
rowIndex=T.rowIndex
)
to="body"
}}
</Hds::AdvancedTable::ExpandableTrGroup>
{{else}}
{{yield
(hash
Tr=(component
"hds/advanced-table/tr"
{{! @glint-ignore: Temporarily ignore deep type instantiation error }}
{{yield (hash Tr=(component "hds/advanced-table/tr"
selectionScope="row"
isLastRow=(eq this._tableModel.lastVisibleRow.id record.id)
isSelectable=this.isSelectable
@@ -125,6 +128,7 @@
selectionAriaLabelSuffix=@selectionAriaLabelSuffix
hasStickyColumn=@hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
data=record
)
Th=(component
"hds/advanced-table/th"
@@ -134,6 +138,7 @@
)
Td=(component "hds/advanced-table/td" align=@align)
data=record
columns=@columns
rowIndex=index
)
to="body"
65 changes: 21 additions & 44 deletions packages/components/src/components/hds/advanced-table/index.ts
Original file line number Diff line number Diff line change
@@ -114,8 +114,10 @@ export interface HdsAdvancedTableSignature {
align?: HdsAdvancedTableHorizontalAlignment;
caption?: string;
columns: HdsAdvancedTableColumn[];
columnOrder?: string[];
density?: HdsAdvancedTableDensities;
identityKey?: string;
isResizable?: boolean;
isSelectable?: boolean;
isStriped?: boolean;
model: HdsAdvancedTableModel;
@@ -132,13 +134,15 @@ export interface HdsAdvancedTableSignature {
hasStickyHeader?: boolean;
hasStickyFirstColumn?: boolean;
childrenKey?: string;
onReorder?: (columnOrder: string[]) => void;
};
Blocks: {
body?: [
{
Td?: ComponentLike<HdsAdvancedTableTdSignature>;
Tr?: ComponentLike<HdsAdvancedTableTrSignature>;
Th?: ComponentLike<HdsAdvancedTableThSignature>;
columns: HdsAdvancedTableColumn[];
data?: Record<string, unknown>;
rowIndex?: number | string;
isOpen?: HdsAdvancedTableExpandState;
@@ -158,10 +162,10 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
@tracked private _isSelectAllCheckboxSelected?: boolean = undefined;
private _selectableRows: HdsAdvancedTableSelectableRow[] = [];
private _captionId = 'caption-' + guidFor(this);
private _tableModel!: HdsAdvancedTableTableModel;
private _scrollHandler!: (event: Event) => void;
private _resizeObserver!: ResizeObserver;
private _theadElement!: HTMLDivElement;
private _tableModel: HdsAdvancedTableTableModel;

@tracked scrollIndicatorDimensions = DEFAULT_SCROLL_DIMENSIONS;
@tracked isStickyColumnPinned = false;
@@ -175,29 +179,17 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
constructor(owner: Owner, args: HdsAdvancedTableSignature['Args']) {
super(owner, args);

const { model, childrenKey, columns, hasStickyFirstColumn } = args;
const { model, childrenKey, columns, columnOrder, hasStickyFirstColumn, isSelectable, onReorder } = this.args;

this._tableModel = new HdsAdvancedTableTableModel({
model,
childrenKey,
columns,
columnOrder,
hasStickyFirstColumn,
isSelectable,
onReorder,
});

if (this._tableModel.hasRowsWithChildren) {
const sortableColumns = columns.filter((column) => column.isSortable);
const sortableColumnLabels = sortableColumns.map(
(column) => column.label
);

assert(
`Cannot have sortable columns if there are nested rows. Sortable columns are ${sortableColumnLabels.toString()}`,
sortableColumns.length === 0
);

assert(
'Cannot have a sticky first column if there are nested rows.',
!hasStickyFirstColumn
);
}
}

get getSortCriteria(): string | HdsAdvancedTableSortingFunction<unknown> {
@@ -218,24 +210,6 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
}
}

get columnWidths(): string[] | undefined {
const { columns } = this.args;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const widths: string[] = new Array(columns.length);
let hasCustomColumnWidth = false;

for (let i = 0; i < columns.length; i++) {
const column = columns[i];

if (column?.['width']) {
widths[i] = column.width;
if (!hasCustomColumnWidth) hasCustomColumnWidth = true;
}
}

return hasCustomColumnWidth ? widths : undefined;
}

get identityKey(): string | undefined {
// we have to provide a way for the consumer to pass undefined because Ember tries to interpret undefined as missing an arg and therefore falls back to the default
if (this.args.identityKey === 'none') {
@@ -326,21 +300,24 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur

// returns the grid-template-columns CSS attribute for the grid
get gridTemplateColumns(): string {
const { isSelectable, columns } = this.args;
const { isSelectable } = this.args;
const { orderedColumns } = this._tableModel;

const DEFAULT_COLUMN_WIDTH = '1fr';

// if there is a select checkbox, the first column has a 'min-content' width to hug the checkbox content
let style = isSelectable ? 'min-content ' : '';

if (!this.columnWidths) {
// if there are no custom column widths, each column is the same width and they take up the available space
style += `repeat(${columns.length}, ${DEFAULT_COLUMN_WIDTH})`;
} else {
const hasCustomColumnWidths = orderedColumns.some(column => column.width !== undefined);

if (hasCustomColumnWidths) {
// check the custom column widths, if the current column has a custom width use the custom width. otherwise take the available space.
for (let i = 0; i < this.columnWidths.length; i++) {
style += ` ${this.columnWidths[i] ? this.columnWidths[i] : DEFAULT_COLUMN_WIDTH}`;
for (let i = 0; i < orderedColumns.length; i++) {
style += ` ${orderedColumns[i]?.width ?? DEFAULT_COLUMN_WIDTH}`;
}
} else {
// if there are no custom column widths, each column is the same width and they take up the available space
style += `repeat(${orderedColumns.length}, ${DEFAULT_COLUMN_WIDTH})`;
}

return style;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { tracked } from '@glimmer/tracking';

import type { HdsAdvancedTableHorizontalAlignment } from "../types";

export default class HdsAdvancedTableColumn {
@tracked label: string = '';

@tracked align?: HdsAdvancedTableHorizontalAlignment = 'left';
@tracked isExpandable?: boolean = false;
@tracked isReorderable?: boolean = false;
@tracked isResizable?: boolean = false;
@tracked isSortable?: boolean = false;
@tracked isVisuallyHidden?: boolean = false;
@tracked key?: string = undefined;
@tracked sortingFunction?: (a: unknown, b: unknown) => number = undefined;
@tracked tooltip?: string = undefined;
@tracked width?: string = undefined;

constructor(args: HdsAdvancedTableColumn) {
this.label = args.label;

this.align = args.align ?? 'left';
this.isExpandable = args.isExpandable ?? false;
this.isReorderable = args.isReorderable ?? false;
this.isResizable = args.isResizable ?? false;
this.isSortable = args.isSortable ?? false;
this.isVisuallyHidden = args.isVisuallyHidden ?? false;
this.key = args.key;
this.sortingFunction = args.sortingFunction;
this.tooltip = args.tooltip;
this.width = args.width;
}
}
Original file line number Diff line number Diff line change
@@ -7,10 +7,14 @@ import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { guidFor } from '@ember/object/internals';

import type { HdsAdvancedTableColumn, HdsAdvancedTableCell } from '../types';

interface HdsAdvancedTableRowArgs {
[key: string]: unknown;
columns: HdsAdvancedTableColumn[];
id?: string;
childrenKey?: string;
columnOrder?: string[];
}

export default class HdsAdvancedTableRow {
@@ -20,6 +24,21 @@ export default class HdsAdvancedTableRow {
[key: string]: unknown;

@tracked isOpen: boolean = false;
@tracked cells: HdsAdvancedTableCell[] = [];
@tracked columnOrder: string[] = [];

get orderedCells() {
return this.columnOrder.reduce((acc, key) => {
const cell = this.cells.find((cell) => cell.columnKey === key);

if (cell) {
acc.push(cell);
}

return acc;
}
, [] as HdsAdvancedTableCell[]);
}

children: HdsAdvancedTableRow[] = [];
childrenKey: string;
@@ -33,6 +52,18 @@ export default class HdsAdvancedTableRow {
}

constructor(args: HdsAdvancedTableRowArgs) {
const { columns } = args;

this.cells = columns.map((column) => {
const cell = args[column.key ?? ''];

return {
columnKey: column.key ?? '',
value: cell,
};
});
this.columnOrder = args.columnOrder ?? this.cells.map((cell) => cell.columnKey);

// set row data
Object.assign(this, args);

@@ -48,6 +79,15 @@ export default class HdsAdvancedTableRow {
}
}

@action
updateColumnOrder(columnOrder: string[]) {
this.columnOrder = columnOrder;

for (const child of this.children) {
child.updateColumnOrder(columnOrder);
}
}

@action
openAll() {
this.isOpen = true;
Loading
Loading