@gravionlabs/helix-ui 22.2.7 → 22.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6199,6 +6199,11 @@ var HxDataTable = class HxDataTable {
6199
6199
  filterDisplay = input(...ngDevMode ? [void 0, { debugName: "filterDisplay" }] : /* istanbul ignore next */ []);
6200
6200
  filters = model({}, ...ngDevMode ? [{ debugName: "filters" }] : /* istanbul ignore next */ []);
6201
6201
  filterLabel = input("Filter {header}", ...ngDevMode ? [{ debugName: "filterLabel" }] : /* istanbul ignore next */ []);
6202
+ clearLabel = input("Clear", ...ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []);
6203
+ filterPopover = viewChild(HxPopover, ...ngDevMode ? [{ debugName: "filterPopover" }] : /* istanbul ignore next */ []);
6204
+ filterInput = viewChild("filterInput", ...ngDevMode ? [{ debugName: "filterInput" }] : /* istanbul ignore next */ []);
6205
+ activeFilterColumn = signal(null, ...ngDevMode ? [{ debugName: "activeFilterColumn" }] : /* istanbul ignore next */ []);
6206
+ injector = inject(Injector);
6202
6207
  expandedRowKeys = model({}, ...ngDevMode ? [{ debugName: "expandedRowKeys" }] : /* istanbul ignore next */ []);
6203
6208
  expandLabel = input("Expand row", ...ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []);
6204
6209
  collapseLabel = input("Collapse row", ...ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []);
@@ -6322,6 +6327,26 @@ var HxDataTable = class HxDataTable {
6322
6327
  this.first.set(0);
6323
6328
  if (this.lazy()) this.emitLazy();
6324
6329
  }
6330
+ openFilter(event, column) {
6331
+ const popover = this.filterPopover();
6332
+ if (!popover) return;
6333
+ if (popover.open() && this.activeFilterColumn()?.field === column.field) {
6334
+ popover.hide();
6335
+ return;
6336
+ }
6337
+ const switching = popover.open();
6338
+ popover.hide(false);
6339
+ this.activeFilterColumn.set(column);
6340
+ popover.show(event, event.currentTarget);
6341
+ if (switching) afterNextRender(() => this.filterInput()?.nativeElement.focus(), { injector: this.injector });
6342
+ }
6343
+ filterLabelFor(column) {
6344
+ return this.filterLabel().replace("{header}", column.header);
6345
+ }
6346
+ clearFilter(column) {
6347
+ this.setFilter(column, "");
6348
+ this.filterPopover()?.hide();
6349
+ }
6325
6350
  setFilter(column, text) {
6326
6351
  const next = { ...this.filters() };
6327
6352
  if (text) next[column.field] = text;
@@ -6695,6 +6720,13 @@ var HxDataTable = class HxDataTable {
6695
6720
  isRequired: false,
6696
6721
  transformFunction: null
6697
6722
  },
6723
+ clearLabel: {
6724
+ classPropertyName: "clearLabel",
6725
+ publicName: "clearLabel",
6726
+ isSignal: true,
6727
+ isRequired: false,
6728
+ transformFunction: null
6729
+ },
6698
6730
  expandedRowKeys: {
6699
6731
  classPropertyName: "expandedRowKeys",
6700
6732
  publicName: "expandedRowKeys",
@@ -6783,8 +6815,21 @@ var HxDataTable = class HxDataTable {
6783
6815
  isSignal: true
6784
6816
  }
6785
6817
  ],
6818
+ viewQueries: [{
6819
+ propertyName: "filterPopover",
6820
+ first: true,
6821
+ predicate: HxPopover,
6822
+ descendants: true,
6823
+ isSignal: true
6824
+ }, {
6825
+ propertyName: "filterInput",
6826
+ first: true,
6827
+ predicate: ["filterInput"],
6828
+ descendants: true,
6829
+ isSignal: true
6830
+ }],
6786
6831
  ngImport: i0,
6787
- template: "<div class=\"hx-data-table-frame\" [attr.aria-busy]=\"loading() ? 'true' : null\">\n <div\n class=\"hx-table-scroll hx-data-table-scroll\"\n [class.hx-data-table-scrolls]=\"scrolls()\"\n [style.max-height]=\"scrollHeight() ?? null\"\n [attr.role]=\"scrolls() ? 'region' : null\"\n [attr.aria-label]=\"scrolls() ? (ariaLabel() ?? caption() ?? null) : null\"\n [attr.tabindex]=\"scrolls() ? 0 : null\"\n >\n <table\n class=\"hx-table\"\n [class.hx-table-sm]=\"size() === 'small'\"\n [class.hx-table-lg]=\"size() === 'large'\"\n [class.hx-table-striped]=\"stripedRows()\"\n [class.hx-table-gridlines]=\"showGridlines()\"\n [class.hx-table-hoverable]=\"hoverRows()\"\n [class.hx-table-sticky]=\"!!scrollHeight()\"\n >\n @if (hasCaption()) {\n <caption [class.hx-data-table-caption-hidden]=\"captionHidden()\">\n @if (captionTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ caption() ?? ariaLabel() }}\n }\n </caption>\n }\n <thead>\n <tr>\n @if (expanderColumn()) {\n <th scope=\"col\" class=\"hx-data-table-expander-cell\"><span class=\"hx-data-table-caption-hidden\">Row details</span></th>\n }\n @if (checkboxColumn()) {\n <th scope=\"col\" class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectAllLabel()\" [checked]=\"allSelected()\" [indeterminate]=\"someSelected()\" (change)=\"toggleSelectAll($any($event.target).checked)\" />\n </th>\n }\n @if (headerTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <th\n scope=\"col\"\n [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\"\n [class.hx-data-table-sorted]=\"orderOf(column) !== 0\"\n [style.width]=\"column.width ?? null\"\n [attr.aria-sort]=\"ariaSort(column)\"\n [attr.title]=\"column.title ?? null\"\n >\n @if (columnHeaders().get(column.field); as extra) {\n <div class=\"hx-data-table-header-content\">\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n <ng-container [ngTemplateOutlet]=\"extra\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n }\n </th>\n }\n }\n </tr>\n @if (filterRow()) {\n <tr class=\"hx-data-table-filter-row\">\n @if (expanderColumn()) { <th></th> }\n @if (checkboxColumn()) { <th></th> }\n @for (column of columns(); track column.field) {\n <th>\n @if (column.filter) {\n <input type=\"text\" hx-input size=\"small\" fluid [attr.aria-label]=\"filterLabel().replace('{header}', column.header)\" [value]=\"filters()[column.field] ?? ''\" (input)=\"setFilter(column, $any($event.target).value)\" />\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @for (row of visibleRows(); track trackRow(row, $index); let i = $index) {\n <tr\n [class]=\"rowClassOf(row)\"\n [class.hx-data-table-selectable]=\"selectable()\"\n [attr.aria-selected]=\"selectionMode() ? (isSelected(row) ? 'true' : 'false') : null\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (click)=\"selectRow(row, $event)\"\n (keydown.enter)=\"onRowKey(row, $event)\"\n (keydown.space)=\"onRowKey(row, $event)\"\n >\n @if (expanderColumn()) {\n <td class=\"hx-data-table-expander-cell\">\n <button type=\"button\" class=\"hx-data-table-expander\" [class.hx-data-table-expander-open]=\"isExpanded(row, i)\" [attr.aria-expanded]=\"isExpanded(row, i)\" [attr.aria-label]=\"isExpanded(row, i) ? collapseLabel() : expandLabel()\" (click)=\"toggleExpansion(row, i)\"></button>\n </td>\n }\n @if (checkboxColumn()) {\n <td class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectRowLabel().replace('{row}', '' + (first() + i + 1))\" [checked]=\"isSelected(row)\" (change)=\"toggleRowCheckbox(row, $any($event.target).checked)\" />\n </td>\n }\n @if (bodyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <td [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\">\n @if (cells().get(column.field); as cell) {\n <ng-container [ngTemplateOutlet]=\"cell\" [ngTemplateOutletContext]=\"{ $implicit: row, value: valueOf(row, column), index: i }\" />\n } @else {\n {{ valueOf(row, column) ?? emptyValue() }}\n }\n </td>\n }\n }\n </tr>\n @if (expansionTemplate(); as tpl) {\n @if (isExpanded(row, i)) {\n <tr class=\"hx-data-table-expansion\">\n <td [attr.colspan]=\"colspan()\">\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n </td>\n </tr>\n }\n }\n } @empty {\n <tr class=\"hx-data-table-empty\">\n <td [attr.colspan]=\"colspan()\">\n @if (emptyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ emptyMessage() }}\n }\n </td>\n </tr>\n }\n </tbody>\n @if (footerTemplate(); as tpl) {\n <tfoot>\n <tr>\n @if (expanderColumn()) { <td></td> }\n @if (checkboxColumn()) { <td></td> }\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n </tr>\n </tfoot>\n }\n </table>\n </div>\n <span class=\"hx-data-table-caption-hidden\" aria-live=\"polite\">{{ announcement() }}</span>\n @if (loading()) {\n <div class=\"hx-data-table-loading\" role=\"status\">\n <hx-progress-spinner ariaLabel=\"Loading\" />\n </div>\n }\n @if (paginator()) {\n <hx-paginator\n class=\"hx-data-table-paginator\"\n [rows]=\"rows()\"\n [first]=\"first()\"\n [totalRecords]=\"total()\"\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\n [showAll]=\"showAll()\"\n (showAllChange)=\"showAll.set($event)\"\n [allLabel]=\"allLabel()\"\n [showCurrentPageReport]=\"showCurrentPageReport()\"\n (pageChange)=\"onPage($event)\"\n />\n }\n</div>\n\n<ng-template #label let-column>\n @if (column.sortable) {\n <button type=\"button\" class=\"hx-data-table-sort\" (click)=\"sort(column)\">\n <span>{{ column.header }}</span>\n <span class=\"hx-data-table-sort-icon\" [class.hx-data-table-sort-asc]=\"orderOf(column) === 1\" [class.hx-data-table-sort-desc]=\"orderOf(column) === -1\" aria-hidden=\"true\"></span>\n @if (sortRank(column); as rank) {\n <span class=\"hx-data-table-sort-rank\" aria-hidden=\"true\">{{ rank }}</span>\n }\n </button>\n } @else {\n {{ column.header }}\n }\n</ng-template>\n",
6832
+ template: "<div class=\"hx-data-table-frame\" [attr.aria-busy]=\"loading() ? 'true' : null\">\n <div\n class=\"hx-table-scroll hx-data-table-scroll\"\n [class.hx-data-table-scrolls]=\"scrolls()\"\n [style.max-height]=\"scrollHeight() ?? null\"\n [attr.role]=\"scrolls() ? 'region' : null\"\n [attr.aria-label]=\"scrolls() ? (ariaLabel() ?? caption() ?? null) : null\"\n [attr.tabindex]=\"scrolls() ? 0 : null\"\n >\n <table\n class=\"hx-table\"\n [class.hx-table-sm]=\"size() === 'small'\"\n [class.hx-table-lg]=\"size() === 'large'\"\n [class.hx-table-striped]=\"stripedRows()\"\n [class.hx-table-gridlines]=\"showGridlines()\"\n [class.hx-table-hoverable]=\"hoverRows()\"\n [class.hx-table-sticky]=\"!!scrollHeight()\"\n >\n @if (hasCaption()) {\n <caption [class.hx-data-table-caption-hidden]=\"captionHidden()\">\n @if (captionTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ caption() ?? ariaLabel() }}\n }\n </caption>\n }\n <thead>\n <tr>\n @if (expanderColumn()) {\n <th scope=\"col\" class=\"hx-data-table-expander-cell\"><span class=\"hx-data-table-caption-hidden\">Row details</span></th>\n }\n @if (checkboxColumn()) {\n <th scope=\"col\" class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectAllLabel()\" [checked]=\"allSelected()\" [indeterminate]=\"someSelected()\" (change)=\"toggleSelectAll($any($event.target).checked)\" />\n </th>\n }\n @if (headerTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <th\n scope=\"col\"\n [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\"\n [class.hx-data-table-sorted]=\"orderOf(column) !== 0\"\n [style.width]=\"column.width ?? null\"\n [attr.aria-sort]=\"ariaSort(column)\"\n [attr.title]=\"column.title ?? null\"\n >\n @let extra = columnHeaders().get(column.field);\n @let menu = filterDisplay() === 'menu' && column.filter;\n @if (extra || menu) {\n <div class=\"hx-data-table-header-content\">\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n @if (extra) {\n <ng-container [ngTemplateOutlet]=\"extra\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n }\n @if (menu) {\n <button\n type=\"button\"\n class=\"hx-data-table-filter-button\"\n [class.hx-data-table-filter-active]=\"!!filters()[column.field]\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"activeFilterColumn()?.field === column.field\"\n [attr.aria-label]=\"filterLabelFor(column)\"\n (click)=\"openFilter($event, column)\"\n >\n <span class=\"hx-data-table-filter-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n }\n </th>\n }\n }\n </tr>\n @if (filterRow()) {\n <tr class=\"hx-data-table-filter-row\">\n @if (expanderColumn()) { <th></th> }\n @if (checkboxColumn()) { <th></th> }\n @for (column of columns(); track column.field) {\n <th>\n @if (column.filter) {\n <input type=\"text\" hx-input size=\"small\" fluid [attr.aria-label]=\"filterLabelFor(column)\" [value]=\"filters()[column.field] ?? ''\" (input)=\"setFilter(column, $any($event.target).value)\" />\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @for (row of visibleRows(); track trackRow(row, $index); let i = $index) {\n <tr\n [class]=\"rowClassOf(row)\"\n [class.hx-data-table-selectable]=\"selectable()\"\n [attr.aria-selected]=\"selectionMode() ? (isSelected(row) ? 'true' : 'false') : null\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (click)=\"selectRow(row, $event)\"\n (keydown.enter)=\"onRowKey(row, $event)\"\n (keydown.space)=\"onRowKey(row, $event)\"\n >\n @if (expanderColumn()) {\n <td class=\"hx-data-table-expander-cell\">\n <button type=\"button\" class=\"hx-data-table-expander\" [class.hx-data-table-expander-open]=\"isExpanded(row, i)\" [attr.aria-expanded]=\"isExpanded(row, i)\" [attr.aria-label]=\"isExpanded(row, i) ? collapseLabel() : expandLabel()\" (click)=\"toggleExpansion(row, i)\"></button>\n </td>\n }\n @if (checkboxColumn()) {\n <td class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectRowLabel().replace('{row}', '' + (first() + i + 1))\" [checked]=\"isSelected(row)\" (change)=\"toggleRowCheckbox(row, $any($event.target).checked)\" />\n </td>\n }\n @if (bodyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <td [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\">\n @if (cells().get(column.field); as cell) {\n <ng-container [ngTemplateOutlet]=\"cell\" [ngTemplateOutletContext]=\"{ $implicit: row, value: valueOf(row, column), index: i }\" />\n } @else {\n {{ valueOf(row, column) ?? emptyValue() }}\n }\n </td>\n }\n }\n </tr>\n @if (expansionTemplate(); as tpl) {\n @if (isExpanded(row, i)) {\n <tr class=\"hx-data-table-expansion\">\n <td [attr.colspan]=\"colspan()\">\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n </td>\n </tr>\n }\n }\n } @empty {\n <tr class=\"hx-data-table-empty\">\n <td [attr.colspan]=\"colspan()\">\n @if (emptyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ emptyMessage() }}\n }\n </td>\n </tr>\n }\n </tbody>\n @if (footerTemplate(); as tpl) {\n <tfoot>\n <tr>\n @if (expanderColumn()) { <td></td> }\n @if (checkboxColumn()) { <td></td> }\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n </tr>\n </tfoot>\n }\n </table>\n </div>\n <span class=\"hx-data-table-caption-hidden\" aria-live=\"polite\">{{ announcement() }}</span>\n @if (loading()) {\n <div class=\"hx-data-table-loading\" role=\"status\">\n <hx-progress-spinner ariaLabel=\"Loading\" />\n </div>\n }\n @if (paginator()) {\n <hx-paginator\n class=\"hx-data-table-paginator\"\n [rows]=\"rows()\"\n [first]=\"first()\"\n [totalRecords]=\"total()\"\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\n [showAll]=\"showAll()\"\n (showAllChange)=\"showAll.set($event)\"\n [allLabel]=\"allLabel()\"\n [showCurrentPageReport]=\"showCurrentPageReport()\"\n (pageChange)=\"onPage($event)\"\n />\n }\n</div>\n\n@if (filterDisplay() === 'menu') {\n @let active = activeFilterColumn();\n <hx-popover panelClass=\"hx-data-table-filter-popover\" [ariaLabel]=\"active ? filterLabelFor(active) : undefined\" (hidden)=\"activeFilterColumn.set(null)\">\n @if (active) {\n <div class=\"hx-data-table-filter-menu\">\n <input #filterInput type=\"text\" hx-input size=\"small\" fluid [attr.aria-label]=\"filterLabelFor(active)\" [value]=\"filters()[active.field] ?? ''\" (input)=\"setFilter(active, $any($event.target).value)\" (keydown.enter)=\"filterPopover()?.hide()\" />\n <button hx-button type=\"button\" size=\"small\" variant=\"text\" class=\"hx-data-table-filter-clear\" (click)=\"clearFilter(active)\">{{ clearLabel() }}</button>\n </div>\n }\n </hx-popover>\n}\n\n<ng-template #label let-column>\n @if (column.sortable) {\n <button type=\"button\" class=\"hx-data-table-sort\" (click)=\"sort(column)\">\n <span>{{ column.header }}</span>\n <span class=\"hx-data-table-sort-icon\" [class.hx-data-table-sort-asc]=\"orderOf(column) === 1\" [class.hx-data-table-sort-desc]=\"orderOf(column) === -1\" aria-hidden=\"true\"></span>\n @if (sortRank(column); as rank) {\n <span class=\"hx-data-table-sort-rank\" aria-hidden=\"true\">{{ rank }}</span>\n }\n </button>\n } @else {\n {{ column.header }}\n }\n</ng-template>\n",
6788
6833
  dependencies: [
6789
6834
  {
6790
6835
  kind: "directive",
@@ -6854,6 +6899,37 @@ var HxDataTable = class HxDataTable {
6854
6899
  "autoResize"
6855
6900
  ],
6856
6901
  exportAs: ["hx-input"]
6902
+ },
6903
+ {
6904
+ kind: "directive",
6905
+ type: HxButton,
6906
+ selector: "button[hx-button], a[hx-button]",
6907
+ inputs: [
6908
+ "variant",
6909
+ "severity",
6910
+ "size",
6911
+ "rounded",
6912
+ "raised",
6913
+ "fluid",
6914
+ "iconOnly",
6915
+ "loading"
6916
+ ],
6917
+ exportAs: ["hx-button"]
6918
+ },
6919
+ {
6920
+ kind: "component",
6921
+ type: HxPopover,
6922
+ selector: "hx-popover",
6923
+ inputs: [
6924
+ "ariaLabel",
6925
+ "ariaLabelledBy",
6926
+ "ariaDescribedBy",
6927
+ "role",
6928
+ "panelClass",
6929
+ "dismissable",
6930
+ "closeOnEscape"
6931
+ ],
6932
+ outputs: ["shown", "hidden"]
6857
6933
  }
6858
6934
  ],
6859
6935
  changeDetection: i0.ChangeDetectionStrategy.OnPush
@@ -6873,11 +6949,13 @@ i0.ɵɵngDeclareClassMetadata({
6873
6949
  HxProgressSpinner,
6874
6950
  HxPaginator,
6875
6951
  HxCheckbox,
6876
- HxInput
6952
+ HxInput,
6953
+ HxButton,
6954
+ HxPopover
6877
6955
  ],
6878
6956
  changeDetection: ChangeDetectionStrategy.OnPush,
6879
6957
  host: { class: "hx-data-table" },
6880
- template: "<div class=\"hx-data-table-frame\" [attr.aria-busy]=\"loading() ? 'true' : null\">\n <div\n class=\"hx-table-scroll hx-data-table-scroll\"\n [class.hx-data-table-scrolls]=\"scrolls()\"\n [style.max-height]=\"scrollHeight() ?? null\"\n [attr.role]=\"scrolls() ? 'region' : null\"\n [attr.aria-label]=\"scrolls() ? (ariaLabel() ?? caption() ?? null) : null\"\n [attr.tabindex]=\"scrolls() ? 0 : null\"\n >\n <table\n class=\"hx-table\"\n [class.hx-table-sm]=\"size() === 'small'\"\n [class.hx-table-lg]=\"size() === 'large'\"\n [class.hx-table-striped]=\"stripedRows()\"\n [class.hx-table-gridlines]=\"showGridlines()\"\n [class.hx-table-hoverable]=\"hoverRows()\"\n [class.hx-table-sticky]=\"!!scrollHeight()\"\n >\n @if (hasCaption()) {\n <caption [class.hx-data-table-caption-hidden]=\"captionHidden()\">\n @if (captionTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ caption() ?? ariaLabel() }}\n }\n </caption>\n }\n <thead>\n <tr>\n @if (expanderColumn()) {\n <th scope=\"col\" class=\"hx-data-table-expander-cell\"><span class=\"hx-data-table-caption-hidden\">Row details</span></th>\n }\n @if (checkboxColumn()) {\n <th scope=\"col\" class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectAllLabel()\" [checked]=\"allSelected()\" [indeterminate]=\"someSelected()\" (change)=\"toggleSelectAll($any($event.target).checked)\" />\n </th>\n }\n @if (headerTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <th\n scope=\"col\"\n [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\"\n [class.hx-data-table-sorted]=\"orderOf(column) !== 0\"\n [style.width]=\"column.width ?? null\"\n [attr.aria-sort]=\"ariaSort(column)\"\n [attr.title]=\"column.title ?? null\"\n >\n @if (columnHeaders().get(column.field); as extra) {\n <div class=\"hx-data-table-header-content\">\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n <ng-container [ngTemplateOutlet]=\"extra\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n }\n </th>\n }\n }\n </tr>\n @if (filterRow()) {\n <tr class=\"hx-data-table-filter-row\">\n @if (expanderColumn()) { <th></th> }\n @if (checkboxColumn()) { <th></th> }\n @for (column of columns(); track column.field) {\n <th>\n @if (column.filter) {\n <input type=\"text\" hx-input size=\"small\" fluid [attr.aria-label]=\"filterLabel().replace('{header}', column.header)\" [value]=\"filters()[column.field] ?? ''\" (input)=\"setFilter(column, $any($event.target).value)\" />\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @for (row of visibleRows(); track trackRow(row, $index); let i = $index) {\n <tr\n [class]=\"rowClassOf(row)\"\n [class.hx-data-table-selectable]=\"selectable()\"\n [attr.aria-selected]=\"selectionMode() ? (isSelected(row) ? 'true' : 'false') : null\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (click)=\"selectRow(row, $event)\"\n (keydown.enter)=\"onRowKey(row, $event)\"\n (keydown.space)=\"onRowKey(row, $event)\"\n >\n @if (expanderColumn()) {\n <td class=\"hx-data-table-expander-cell\">\n <button type=\"button\" class=\"hx-data-table-expander\" [class.hx-data-table-expander-open]=\"isExpanded(row, i)\" [attr.aria-expanded]=\"isExpanded(row, i)\" [attr.aria-label]=\"isExpanded(row, i) ? collapseLabel() : expandLabel()\" (click)=\"toggleExpansion(row, i)\"></button>\n </td>\n }\n @if (checkboxColumn()) {\n <td class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectRowLabel().replace('{row}', '' + (first() + i + 1))\" [checked]=\"isSelected(row)\" (change)=\"toggleRowCheckbox(row, $any($event.target).checked)\" />\n </td>\n }\n @if (bodyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <td [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\">\n @if (cells().get(column.field); as cell) {\n <ng-container [ngTemplateOutlet]=\"cell\" [ngTemplateOutletContext]=\"{ $implicit: row, value: valueOf(row, column), index: i }\" />\n } @else {\n {{ valueOf(row, column) ?? emptyValue() }}\n }\n </td>\n }\n }\n </tr>\n @if (expansionTemplate(); as tpl) {\n @if (isExpanded(row, i)) {\n <tr class=\"hx-data-table-expansion\">\n <td [attr.colspan]=\"colspan()\">\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n </td>\n </tr>\n }\n }\n } @empty {\n <tr class=\"hx-data-table-empty\">\n <td [attr.colspan]=\"colspan()\">\n @if (emptyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ emptyMessage() }}\n }\n </td>\n </tr>\n }\n </tbody>\n @if (footerTemplate(); as tpl) {\n <tfoot>\n <tr>\n @if (expanderColumn()) { <td></td> }\n @if (checkboxColumn()) { <td></td> }\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n </tr>\n </tfoot>\n }\n </table>\n </div>\n <span class=\"hx-data-table-caption-hidden\" aria-live=\"polite\">{{ announcement() }}</span>\n @if (loading()) {\n <div class=\"hx-data-table-loading\" role=\"status\">\n <hx-progress-spinner ariaLabel=\"Loading\" />\n </div>\n }\n @if (paginator()) {\n <hx-paginator\n class=\"hx-data-table-paginator\"\n [rows]=\"rows()\"\n [first]=\"first()\"\n [totalRecords]=\"total()\"\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\n [showAll]=\"showAll()\"\n (showAllChange)=\"showAll.set($event)\"\n [allLabel]=\"allLabel()\"\n [showCurrentPageReport]=\"showCurrentPageReport()\"\n (pageChange)=\"onPage($event)\"\n />\n }\n</div>\n\n<ng-template #label let-column>\n @if (column.sortable) {\n <button type=\"button\" class=\"hx-data-table-sort\" (click)=\"sort(column)\">\n <span>{{ column.header }}</span>\n <span class=\"hx-data-table-sort-icon\" [class.hx-data-table-sort-asc]=\"orderOf(column) === 1\" [class.hx-data-table-sort-desc]=\"orderOf(column) === -1\" aria-hidden=\"true\"></span>\n @if (sortRank(column); as rank) {\n <span class=\"hx-data-table-sort-rank\" aria-hidden=\"true\">{{ rank }}</span>\n }\n </button>\n } @else {\n {{ column.header }}\n }\n</ng-template>\n"
6958
+ template: "<div class=\"hx-data-table-frame\" [attr.aria-busy]=\"loading() ? 'true' : null\">\n <div\n class=\"hx-table-scroll hx-data-table-scroll\"\n [class.hx-data-table-scrolls]=\"scrolls()\"\n [style.max-height]=\"scrollHeight() ?? null\"\n [attr.role]=\"scrolls() ? 'region' : null\"\n [attr.aria-label]=\"scrolls() ? (ariaLabel() ?? caption() ?? null) : null\"\n [attr.tabindex]=\"scrolls() ? 0 : null\"\n >\n <table\n class=\"hx-table\"\n [class.hx-table-sm]=\"size() === 'small'\"\n [class.hx-table-lg]=\"size() === 'large'\"\n [class.hx-table-striped]=\"stripedRows()\"\n [class.hx-table-gridlines]=\"showGridlines()\"\n [class.hx-table-hoverable]=\"hoverRows()\"\n [class.hx-table-sticky]=\"!!scrollHeight()\"\n >\n @if (hasCaption()) {\n <caption [class.hx-data-table-caption-hidden]=\"captionHidden()\">\n @if (captionTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ caption() ?? ariaLabel() }}\n }\n </caption>\n }\n <thead>\n <tr>\n @if (expanderColumn()) {\n <th scope=\"col\" class=\"hx-data-table-expander-cell\"><span class=\"hx-data-table-caption-hidden\">Row details</span></th>\n }\n @if (checkboxColumn()) {\n <th scope=\"col\" class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectAllLabel()\" [checked]=\"allSelected()\" [indeterminate]=\"someSelected()\" (change)=\"toggleSelectAll($any($event.target).checked)\" />\n </th>\n }\n @if (headerTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <th\n scope=\"col\"\n [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\"\n [class.hx-data-table-sorted]=\"orderOf(column) !== 0\"\n [style.width]=\"column.width ?? null\"\n [attr.aria-sort]=\"ariaSort(column)\"\n [attr.title]=\"column.title ?? null\"\n >\n @let extra = columnHeaders().get(column.field);\n @let menu = filterDisplay() === 'menu' && column.filter;\n @if (extra || menu) {\n <div class=\"hx-data-table-header-content\">\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n @if (extra) {\n <ng-container [ngTemplateOutlet]=\"extra\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n }\n @if (menu) {\n <button\n type=\"button\"\n class=\"hx-data-table-filter-button\"\n [class.hx-data-table-filter-active]=\"!!filters()[column.field]\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"activeFilterColumn()?.field === column.field\"\n [attr.aria-label]=\"filterLabelFor(column)\"\n (click)=\"openFilter($event, column)\"\n >\n <span class=\"hx-data-table-filter-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"label\" [ngTemplateOutletContext]=\"{ $implicit: column }\" />\n }\n </th>\n }\n }\n </tr>\n @if (filterRow()) {\n <tr class=\"hx-data-table-filter-row\">\n @if (expanderColumn()) { <th></th> }\n @if (checkboxColumn()) { <th></th> }\n @for (column of columns(); track column.field) {\n <th>\n @if (column.filter) {\n <input type=\"text\" hx-input size=\"small\" fluid [attr.aria-label]=\"filterLabelFor(column)\" [value]=\"filters()[column.field] ?? ''\" (input)=\"setFilter(column, $any($event.target).value)\" />\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @for (row of visibleRows(); track trackRow(row, $index); let i = $index) {\n <tr\n [class]=\"rowClassOf(row)\"\n [class.hx-data-table-selectable]=\"selectable()\"\n [attr.aria-selected]=\"selectionMode() ? (isSelected(row) ? 'true' : 'false') : null\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (click)=\"selectRow(row, $event)\"\n (keydown.enter)=\"onRowKey(row, $event)\"\n (keydown.space)=\"onRowKey(row, $event)\"\n >\n @if (expanderColumn()) {\n <td class=\"hx-data-table-expander-cell\">\n <button type=\"button\" class=\"hx-data-table-expander\" [class.hx-data-table-expander-open]=\"isExpanded(row, i)\" [attr.aria-expanded]=\"isExpanded(row, i)\" [attr.aria-label]=\"isExpanded(row, i) ? collapseLabel() : expandLabel()\" (click)=\"toggleExpansion(row, i)\"></button>\n </td>\n }\n @if (checkboxColumn()) {\n <td class=\"hx-data-table-select-cell\">\n <input type=\"checkbox\" hx-checkbox [attr.aria-label]=\"selectRowLabel().replace('{row}', '' + (first() + i + 1))\" [checked]=\"isSelected(row)\" (change)=\"toggleRowCheckbox(row, $any($event.target).checked)\" />\n </td>\n }\n @if (bodyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n } @else {\n @for (column of columns(); track column.field) {\n <td [class]=\"'hx-data-table-align-' + (column.align ?? 'left')\">\n @if (cells().get(column.field); as cell) {\n <ng-container [ngTemplateOutlet]=\"cell\" [ngTemplateOutletContext]=\"{ $implicit: row, value: valueOf(row, column), index: i }\" />\n } @else {\n {{ valueOf(row, column) ?? emptyValue() }}\n }\n </td>\n }\n }\n </tr>\n @if (expansionTemplate(); as tpl) {\n @if (isExpanded(row, i)) {\n <tr class=\"hx-data-table-expansion\">\n <td [attr.colspan]=\"colspan()\">\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: row, index: i, columns: columns() }\" />\n </td>\n </tr>\n }\n }\n } @empty {\n <tr class=\"hx-data-table-empty\">\n <td [attr.colspan]=\"colspan()\">\n @if (emptyTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl.template\" />\n } @else {\n {{ emptyMessage() }}\n }\n </td>\n </tr>\n }\n </tbody>\n @if (footerTemplate(); as tpl) {\n <tfoot>\n <tr>\n @if (expanderColumn()) { <td></td> }\n @if (checkboxColumn()) { <td></td> }\n <ng-container [ngTemplateOutlet]=\"tpl.template\" [ngTemplateOutletContext]=\"{ $implicit: columns() }\" />\n </tr>\n </tfoot>\n }\n </table>\n </div>\n <span class=\"hx-data-table-caption-hidden\" aria-live=\"polite\">{{ announcement() }}</span>\n @if (loading()) {\n <div class=\"hx-data-table-loading\" role=\"status\">\n <hx-progress-spinner ariaLabel=\"Loading\" />\n </div>\n }\n @if (paginator()) {\n <hx-paginator\n class=\"hx-data-table-paginator\"\n [rows]=\"rows()\"\n [first]=\"first()\"\n [totalRecords]=\"total()\"\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\n [showAll]=\"showAll()\"\n (showAllChange)=\"showAll.set($event)\"\n [allLabel]=\"allLabel()\"\n [showCurrentPageReport]=\"showCurrentPageReport()\"\n (pageChange)=\"onPage($event)\"\n />\n }\n</div>\n\n@if (filterDisplay() === 'menu') {\n @let active = activeFilterColumn();\n <hx-popover panelClass=\"hx-data-table-filter-popover\" [ariaLabel]=\"active ? filterLabelFor(active) : undefined\" (hidden)=\"activeFilterColumn.set(null)\">\n @if (active) {\n <div class=\"hx-data-table-filter-menu\">\n <input #filterInput type=\"text\" hx-input size=\"small\" fluid [attr.aria-label]=\"filterLabelFor(active)\" [value]=\"filters()[active.field] ?? ''\" (input)=\"setFilter(active, $any($event.target).value)\" (keydown.enter)=\"filterPopover()?.hide()\" />\n <button hx-button type=\"button\" size=\"small\" variant=\"text\" class=\"hx-data-table-filter-clear\" (click)=\"clearFilter(active)\">{{ clearLabel() }}</button>\n </div>\n }\n </hx-popover>\n}\n\n<ng-template #label let-column>\n @if (column.sortable) {\n <button type=\"button\" class=\"hx-data-table-sort\" (click)=\"sort(column)\">\n <span>{{ column.header }}</span>\n <span class=\"hx-data-table-sort-icon\" [class.hx-data-table-sort-asc]=\"orderOf(column) === 1\" [class.hx-data-table-sort-desc]=\"orderOf(column) === -1\" aria-hidden=\"true\"></span>\n @if (sortRank(column); as rank) {\n <span class=\"hx-data-table-sort-rank\" aria-hidden=\"true\">{{ rank }}</span>\n }\n </button>\n } @else {\n {{ column.header }}\n }\n</ng-template>\n"
6881
6959
  }]
6882
6960
  }],
6883
6961
  propDecorators: {
@@ -7218,6 +7296,22 @@ i0.ɵɵngDeclareClassMetadata({
7218
7296
  required: false
7219
7297
  }]
7220
7298
  }],
7299
+ clearLabel: [{
7300
+ type: i0.Input,
7301
+ args: [{
7302
+ isSignal: true,
7303
+ alias: "clearLabel",
7304
+ required: false
7305
+ }]
7306
+ }],
7307
+ filterPopover: [{
7308
+ type: i0.ViewChild,
7309
+ args: [i0.forwardRef(() => HxPopover), { isSignal: true }]
7310
+ }],
7311
+ filterInput: [{
7312
+ type: i0.ViewChild,
7313
+ args: ["filterInput", { isSignal: true }]
7314
+ }],
7221
7315
  expandedRowKeys: [{
7222
7316
  type: i0.Input,
7223
7317
  args: [{