Skip to content
Draft
Show file tree
Hide file tree
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
7 changes: 7 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,13 @@
"./components/hds/dropdown/toggle/button.js": "./dist/_app_/components/hds/dropdown/toggle/button.js",
"./components/hds/dropdown/toggle/chevron.js": "./dist/_app_/components/hds/dropdown/toggle/chevron.js",
"./components/hds/dropdown/toggle/icon.js": "./dist/_app_/components/hds/dropdown/toggle/icon.js",
"./components/hds/filter-bar/checkbox.js": "./dist/_app_/components/hds/filter-bar/checkbox.js",
"./components/hds/filter-bar/dropdown.js": "./dist/_app_/components/hds/filter-bar/dropdown.js",
"./components/hds/filter-bar/filters-checkbox.js": "./dist/_app_/components/hds/filter-bar/filters-checkbox.js",
"./components/hds/filter-bar/filters-dropdown.js": "./dist/_app_/components/hds/filter-bar/filters-dropdown.js",
"./components/hds/filter-bar.js": "./dist/_app_/components/hds/filter-bar.js",
"./components/hds/filter-bar/radio.js": "./dist/_app_/components/hds/filter-bar/radio.js",
"./components/hds/filter-bar/range.js": "./dist/_app_/components/hds/filter-bar/range.js",
"./components/hds/flyout/body.js": "./dist/_app_/components/hds/flyout/body.js",
"./components/hds/flyout/description.js": "./dist/_app_/components/hds/flyout/description.js",
"./components/hds/flyout/footer.js": "./dist/_app_/components/hds/flyout/footer.js",
Expand Down
10 changes: 10 additions & 0 deletions packages/components/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ export * from './components/hds/dropdown/list-item/types.ts';
export * from './components/hds/dropdown/toggle/types.ts';
export * from './components/hds/dropdown/types.ts';

// FilterBar
export { default as HdsFilterBar } from './components/hds/filter-bar/index.ts';
export { default as HdsFilterBarCheckbox } from './components/hds/filter-bar/checkbox.ts';
export { default as HdsFilterBarDropdown } from './components/hds/filter-bar/dropdown.ts';
export { default as HdsFilterBarFiltersCheckbox } from './components/hds/filter-bar/filters-checkbox.ts';
export { default as HdsFilterBarFiltersDropdown } from './components/hds/filter-bar/filters-dropdown.ts';
export { default as HdsFilterBarRadio } from './components/hds/filter-bar/radio.ts';
export { default as HdsFilterBarRange } from './components/hds/filter-bar/range.ts';
export * from './components/hds/filter-bar/types.ts';

// Flyout
export { default as HdsFlyout } from './components/hds/flyout/index.ts';
export * from './components/hds/flyout/types.ts';
Expand Down
148 changes: 87 additions & 61 deletions packages/components/src/components/hds/advanced-table/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
SPDX-License-Identifier: MPL-2.0
}}

{{#if (has-block "actions")}}
<div class="hds-advanced-table__actions">
{{yield (hash FilterBar=(component "hds/filter-bar")) to="actions"}}
</div>
{{/if}}
<div
class="hds-advanced-table__container
{{(if this.isStickyHeaderPinned 'hds-advanced-table__container--header-is-pinned')}}"
Expand Down Expand Up @@ -107,79 +112,81 @@
</div>

{{! Body }}
<div class="hds-advanced-table__tbody" role="rowgroup">
{{! ----------------------------------------------------------------------------------------
{{#unless this.isEmpty}}
<div class="hds-advanced-table__tbody" role="rowgroup">
{{! ----------------------------------------------------------------------------------------
IMPORTANT: we loop on the `model` array and for each record
we yield the Tr/Td/Th elements _and_ the record itself as `data`
this means the consumer will *have to* use the `data` key to access it in their template
-------------------------------------------------------------------------------------------- }}
{{#each this._tableModel.sortedRows key=this.identityKey as |record index|}}
{{#if this._tableModel.hasRowsWithChildren}}
<Hds::AdvancedTable::ExpandableTrGroup
@record={{record}}
@rowIndex={{index}}
@onClickToggle={{record.onClickToggle}}
as |T|
>
{{#each this._tableModel.sortedRows key=this.identityKey as |record index|}}
{{#if this._tableModel.hasRowsWithChildren}}
<Hds::AdvancedTable::ExpandableTrGroup
@record={{record}}
@rowIndex={{index}}
@onClickToggle={{record.onClickToggle}}
as |T|
>
{{yield
(hash
Tr=(component
"hds/advanced-table/tr"
isLastRow=(eq this._tableModel.lastVisibleRow.id T.data.id)
isParentRow=T.isExpandable
depth=T.depth
displayRow=T.shouldDisplayChildRows
data=T.data
)
Th=(component
"hds/advanced-table/th"
depth=T.depth
isExpandable=T.isExpandable
isExpanded=T.isExpanded
newLabel=T.id
parentId=T.parentId
scope="row"
onClickToggle=T.onClickToggle
)
Td=(component "hds/advanced-table/td" align=@align)
data=T.data
isOpen=T.isExpanded
rowIndex=T.rowIndex
)
to="body"
}}
</Hds::AdvancedTable::ExpandableTrGroup>
{{else}}
{{yield
(hash
Tr=(component
"hds/advanced-table/tr"
isLastRow=(eq this._tableModel.lastVisibleRow.id T.data.id)
isParentRow=T.isExpandable
depth=T.depth
displayRow=T.shouldDisplayChildRows
data=T.data
selectionScope="row"
isLastRow=(eq this._tableModel.lastVisibleRow.id record.id)
isSelectable=this.isSelectable
onSelectionChange=this.onSelectionRowChange
didInsert=this.didInsertRowCheckbox
willDestroy=this.willDestroyRowCheckbox
selectionAriaLabelSuffix=@selectionAriaLabelSuffix
hasStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
data=record
)
Th=(component
"hds/advanced-table/th"
depth=T.depth
isExpandable=T.isExpandable
isExpanded=T.isExpanded
newLabel=T.id
parentId=T.parentId
scope="row"
onClickToggle=T.onClickToggle
isStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
)
Td=(component "hds/advanced-table/td" align=@align)
data=T.data
isOpen=T.isExpanded
rowIndex=T.rowIndex
data=record
rowIndex=index
)
to="body"
}}
</Hds::AdvancedTable::ExpandableTrGroup>
{{else}}
{{yield
(hash
Tr=(component
"hds/advanced-table/tr"
selectionScope="row"
isLastRow=(eq this._tableModel.lastVisibleRow.id record.id)
isSelectable=this.isSelectable
onSelectionChange=this.onSelectionRowChange
didInsert=this.didInsertRowCheckbox
willDestroy=this.willDestroyRowCheckbox
selectionAriaLabelSuffix=@selectionAriaLabelSuffix
hasStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
data=record
)
Th=(component
"hds/advanced-table/th"
scope="row"
isStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
)
Td=(component "hds/advanced-table/td" align=@align)
data=record
rowIndex=index
)
to="body"
}}
{{/if}}
{{/each}}
</div>
{{/if}}
{{/each}}
</div>
{{/unless}}
</div>

{{#if this.showScrollIndicatorLeft}}
Expand All @@ -196,10 +203,29 @@
/>
{{/if}}

{{#if this.showScrollIndicatorBottom}}
<div
class="hds-advanced-table__scroll-indicator hds-advanced-table__scroll-indicator-bottom"
{{style bottom=this.scrollIndicatorDimensions.bottom width=this.scrollIndicatorDimensions.width}}
/>
{{#unless this.isEmpty}}
{{#if this.showScrollIndicatorBottom}}
<div
class="hds-advanced-table__scroll-indicator hds-advanced-table__scroll-indicator-bottom"
{{style bottom=this.scrollIndicatorDimensions.bottom width=this.scrollIndicatorDimensions.width}}
/>
{{/if}}
{{/unless}}

{{#if this.isEmpty}}
<div class="hds-advanced-table__empty-state">
<div class="hds-advanced-table__empty-state__content">
{{#if (has-block "emptyState")}}
{{yield to="emptyState"}}
{{else}}
<Hds::Layout::Flex @direction="column" @gap="8">
<Hds::Text::Display @tag="h3" @size="300">No data to display</Hds::Text::Display>
<Hds::Text::Body>
No data is available in the table to display.
</Hds::Text::Body>
</Hds::Layout::Flex>
{{/if}}
</div>
</div>
{{/if}}
</div>
17 changes: 17 additions & 0 deletions packages/components/src/components/hds/advanced-table/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import HdsAdvancedTableTableModel from './models/table.ts';

import type Owner from '@ember/owner';
import type { WithBoundArgs } from '@glint/template';
import type { ComponentLike } from '@glint/template';
import {
HdsAdvancedTableDensityValues,
HdsAdvancedTableVerticalAlignmentValues,
Expand All @@ -30,6 +31,7 @@ import type {
HdsAdvancedTableExpandState,
HdsAdvancedTableColumnReorderCallback,
} from './types.ts';
import type { HdsFilterBarSignature } from '../filter-bar/index.ts';
import type HdsAdvancedTableColumnType from './models/column.ts';
import type { HdsFormCheckboxBaseSignature } from '../form/checkbox/base.ts';
import type HdsAdvancedTableTd from './td.ts';
Expand Down Expand Up @@ -149,6 +151,7 @@ export interface HdsAdvancedTableSignature {
hasStickyFirstColumn?: boolean;
childrenKey?: string;
maxHeight?: string;
isEmpty?: boolean;
onColumnReorder?: HdsAdvancedTableColumnReorderCallback;
onColumnResize?: (columnKey: string, newWidth?: string) => void;
onSelectionChange?: (
Expand All @@ -157,6 +160,11 @@ export interface HdsAdvancedTableSignature {
onSort?: (sortBy: string, sortOrder: HdsAdvancedTableThSortOrder) => void;
};
Blocks: {
actions?: [
{
FilterBar?: ComponentLike<HdsFilterBarSignature>;
},
];
body?: [
{
Td?: WithBoundArgs<typeof HdsAdvancedTableTd, 'align'>;
Expand Down Expand Up @@ -192,6 +200,7 @@ export interface HdsAdvancedTableSignature {
isOpen?: HdsAdvancedTableExpandState;
},
];
emptyState?: [];
};
Element: HTMLDivElement;
}
Expand Down Expand Up @@ -259,6 +268,14 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
}
}

get isEmpty(): boolean {
const { isEmpty } = this.args;
if (isEmpty !== undefined) {
return isEmpty;
}
return false;
}

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') {
Expand Down
16 changes: 15 additions & 1 deletion packages/components/src/components/hds/dropdown/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
SPDX-License-Identifier: MPL-2.0
}}
<Hds::PopoverPrimitive @isOpen={{@isOpen}} @onClose={{@onClose}} @enableClickEvents={{true}} as |PP|>
<div class={{this.classNames}} ...attributes {{PP.setupPrimitiveContainer}}>
<div class={{this.classNames}} ...attributes {{PP.setupPrimitiveContainer}} {{this._setUpDropdown}}>
{{#if this.onDismiss}}
<button class="hds-dropdown__dismiss" type="button" {{on "click" this.onDismiss}}>
<Hds::Icon class="hds-tag__dismiss-icon" @name="x" @size="16" />
</button>
{{/if}}
{{yield
(hash
ToggleButton=(component
Expand All @@ -21,6 +26,15 @@
>
{{#if (or PP.isOpen @preserveContentInDom)}}
{{yield (hash Header=(component "hds/dropdown/header") close=PP.hidePopover)}}
{{#if @searchEnabled}}
<div class="hds-dropdown__search">
<Hds::Form::TextInput::Base
@type="search"
placeholder={{if @searchPlaceholder @searchPlaceholder "Search"}}
{{on "input" this.onSearch}}
/>
</div>
{{/if}}
<ul class="hds-dropdown__list" {{did-insert this.didInsertList}}>
{{yield
(hash
Expand Down
44 changes: 44 additions & 0 deletions packages/components/src/components/hds/dropdown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { assert } from '@ember/debug';
import { modifier } from 'ember-modifier';

import {
// map Dropdown's `listPosition` values to PopoverPrimitive's `placement` values
Expand Down Expand Up @@ -48,6 +49,10 @@ export interface HdsDropdownSignature {
enableCollisionDetection?: HdsAnchoredPositionOptions['enableCollisionDetection'];
preserveContentInDom?: boolean;
matchToggleWidth?: boolean;
searchEnabled?: boolean;
searchPlaceholder?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onDismiss?: (event: MouseEvent, ...args: any[]) => void;
};
Blocks: {
default: [
Expand All @@ -73,6 +78,14 @@ export interface HdsDropdownSignature {
}

export default class HdsDropdown extends Component<HdsDropdownSignature> {
private _element!: HTMLDivElement;

private _setUpDropdown = modifier((element: HTMLDivElement) => {
this._element = element;

return () => {};
});

/**
* @param listPosition
* @type {string}
Expand Down Expand Up @@ -116,6 +129,17 @@ export default class HdsDropdown extends Component<HdsDropdownSignature> {
};
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
get onDismiss(): ((event: MouseEvent, ...args: any[]) => void) | false {
const { onDismiss } = this.args;

if (typeof onDismiss === 'function') {
return onDismiss;
} else {
return false;
}
}

/**
* Get the class names to apply to the element
* @method classNames
Expand All @@ -129,6 +153,10 @@ export default class HdsDropdown extends Component<HdsDropdownSignature> {
classes.push('hds-dropdown--is-inline');
}

if (this.args.onDismiss) {
classes.push('hds-dropdown--has-dismiss');
}

return classes.join(' ');
}

Expand Down Expand Up @@ -169,4 +197,20 @@ export default class HdsDropdown extends Component<HdsDropdownSignature> {
}
}
}

onSearch = (event: Event) => {
const listItems = this._element.querySelectorAll('.hds-dropdown-list-item') as NodeListOf<HTMLLIElement>;
const input = event.target as HTMLInputElement;
listItems.forEach((item) => {
if (item.textContent) {
const text = item.textContent.toLowerCase();
const searchText = input.value.toLowerCase();
if (text.includes(searchText)) {
item.style.display = '';
} else {
item.style.display = 'none';
}
}
});
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{#let @checkbox as |Checkbox|}}
<Checkbox checked={{this.isChecked}} @value={{@value}} {{on "change" this.onChange}}>
{{yield}}
</Checkbox>
{{/let}}
Loading
Loading