@area8975/ui 0.2.2-dev.36 → 0.2.2-dev.37
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.
- package/CHANGELOG.md +5 -0
- package/fesm2022/area8975-ui.mjs +17 -3
- package/fesm2022/area8975-ui.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,11 @@ All notable changes to this project will be documented in this file. See [commit
|
|
|
9
9
|
* add ui-disclosure, a trigger that shows and hides a panel, with section and whole-row triggers and a turning chevron
|
|
10
10
|
* add `visibleOptions` to ui-table-filters options groups, showing the rest behind a "Show N more" toggle
|
|
11
11
|
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* ui-table row actions and sortable headers now shade on hover and keyboard focus in consuming apps. They used a `hocus:` variant that only the library's own stylesheets define, so apps generated nothing for them. Row actions now use `bg-surface-hover`, so they still show on a shaded row
|
|
15
|
+
* ui-table row actions show their label in a ui-tooltip instead of the browser's native title, including on disabled actions
|
|
16
|
+
|
|
12
17
|
## [0.2.1](https://gitea.cor.bz/corbz/ui-library/compare/v0.2.0...v0.2.1) (2026-10-17)
|
|
13
18
|
|
|
14
19
|
### Features
|
package/fesm2022/area8975-ui.mjs
CHANGED
|
@@ -10234,7 +10234,7 @@ var UiTableComponent = class UiTableComponent {
|
|
|
10234
10234
|
heroBars2
|
|
10235
10235
|
})],
|
|
10236
10236
|
ngImport: i0,
|
|
10237
|
-
template: "@if (searchable() || hasFilterableColumns() || toggleableColumns()) {\n <div class=\"ui-table-toolbar\">\n @if (searchable()) {\n <ui-input\n [value]=\"query()\"\n (valueChange)=\"onQueryChange($event)\"\n [placeholder]=\"searchPlaceholder()\"\n class=\"max-w-xs\"\n >\n <ng-template #leading>\n <ng-icon\n name=\"heroMagnifyingGlass\"\n class=\"ms-3 size-4 text-muted-foreground-1\"\n />\n </ng-template>\n </ui-input>\n }\n\n @if (hasFilterableColumns()) {\n <ui-dropdown\n [isOpen]=\"filterMenuOpen\"\n placement=\"bottom-start\"\n closeBehaviour=\"whenClickOutside\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"filterMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroFunnel\" class=\"size-4\" />\n Filters\n @if (activeFilterCount()) {\n <span class=\"ui-table-filter-count ui-text-caption\">\n {{ activeFilterCount() }}\n </span>\n }\n </ui-button>\n\n @if (filterMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"ui-table-filter-menu\">\n @for (column of filterableColumns(); track column.id) {\n <div class=\"flex flex-col gap-1\">\n <span\n class=\"text-muted-foreground-1 ui-text-caption\"\n >\n {{ column.header }}\n </span>\n\n @if (column.filterOptions) {\n <ui-select\n [dataSource]=\"filterDataSource(column)\"\n [selectedItem]=\"selectedFilterOption(column)\"\n (selectionChange)=\"onFilterSelect(column.id, $event)\"\n [displayWith]=\"column.sensitive ? sensitiveFilterOptionLabel : filterOptionLabel\"\n [clearable]=\"true\"\n clearLabel=\"All\"\n placeholder=\"All\"\n />\n } @else {\n <ui-input\n [value]=\"filterValue(column.id)\"\n (valueChange)=\"onFilterInput(column.id, $event)\"\n placeholder=\"Filter...\"\n [ariaLabel]=\"'Filter ' + column.header\"\n />\n }\n </div>\n }\n\n @if (activeFilterCount()) {\n <ui-button\n appearance=\"link\"\n intent=\"secondary\"\n class=\"text-end\"\n classes=\"self-end p-0! text-sm\"\n (click)=\"clearFilters()\"\n >\n Clear filters\n </ui-button>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n\n @if (toggleableColumns()) {\n <ui-dropdown\n [isOpen]=\"columnMenuOpen\"\n placement=\"bottom-end\"\n closeBehaviour=\"whenClickOutside\"\n class=\"ms-auto\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"columnMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroViewColumns\" class=\"size-4\" />\n Columns\n </ui-button>\n\n @if (columnMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"bg-layer shadow-xs py-1 border border-dropdown-divider rounded-lg min-w-40\">\n @for (column of hideableColumns(); track column.id) {\n <label\n class=\"flex items-center gap-2 hover:bg-dropdown-item-hover px-3 py-2 ui-text-body-alt cursor-pointer\"\n >\n <ui-checkbox\n [value]=\"isColumnVisible(column)\"\n (valueChange)=\"toggleColumnVisibility(column)\"\n />\n {{ column.header }}\n </label>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n </div>\n}\n\n<div class=\"ui-table-scroll\">\n <table [class]=\"generatedClasses()\" [style.width.px]=\"fixedWidth()\">\n <colgroup>\n @if (selectable()) {\n <col [style.width.px]=\"44\" />\n }\n\n @for (column of renderColumns(); track column.id) {\n <col [style.width.px]=\"columnWidth(column)\" />\n }\n\n @if (hasActions()) {\n <col [style.width.px]=\"actionsColumnWidth()\" />\n }\n </colgroup>\n\n <thead [class.ui-table-sticky]=\"stickyHeader()\">\n <tr>\n @if (selectable()) {\n <th class=\"text-center! ui-table-select-cell\">\n <ui-checkbox\n [value]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (valueChange)=\"toggleSelectAll()\"\n />\n </th>\n }\n\n @for (column of renderColumns(); track column.id) {\n <th\n scope=\"col\"\n [attr.data-column-id]=\"column.id\"\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [class.ui-table-column-dragging]=\"draggedColumnId() === column.id\"\n [class.ui-table-column-drag-over]=\"dragOverColumnId() === column.id\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n <div class=\"ui-table-th-content\">\n @if (reorderableColumns() && column.reorderable !== false) {\n <ng-icon\n name=\"heroBars2\"\n class=\"ui-table-drag-handle\"\n (pointerdown)=\"onColumnDragStart($event, column)\"\n />\n }\n\n @if (column.sortable) {\n <ui-button\n appearance=\"none\"\n classes=\"flex items-center gap-1 p-0! border-transparent! rounded-none! cursor-pointer hocus:text-foreground\"\n (click)=\"toggleSort(column)\"\n >\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n <svg\n viewBox=\"0 0 8 13\"\n aria-hidden=\"true\"\n class=\"ui-table-sort\"\n [attr.data-direction]=\"sortDirection(column)\"\n >\n <path class=\"ui-table-sort-asc\" d=\"M4 0 8 5H0z\" />\n <path class=\"ui-table-sort-desc\" d=\"M4 13 0 8h8z\" />\n </svg>\n </ui-button>\n } @else {\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n }\n </div>\n\n @if (column.resizable) {\n <span\n class=\"ui-table-resize-handle\"\n (pointerdown)=\"startResize($event, column)\"\n ></span>\n }\n </th>\n }\n\n @if (hasActions()) {\n <th class=\"ui-table-actions-cell\"></th>\n }\n </tr>\n </thead>\n\n <tbody class=\"ui-text-body-alt\">\n @if (loading()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n <ui-loading type=\"loading-dots\" />\n </td>\n </tr>\n } @else if (error()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status ui-table-status-error\"\n >\n {{ errorMessage() }}\n <ui-button\n appearance=\"link\"\n intent=\"danger\"\n classes=\"ms-1 p-0! text-sm underline\"\n (click)=\"reload()\"\n >\n Retry\n </ui-button>\n </td>\n </tr>\n } @else if (isEmpty()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n {{ emptyMessage() }}\n </td>\n </tr>\n } @else {\n @for (row of rows(); track rowId()(row, $index); let i = $index) {\n <tr\n [class.ui-table-row-selected]=\"isRowSelected(row, i)\"\n [class.ui-table-row-dragging]=\"draggedRowIndex() === i\"\n [draggable]=\"canReorderRows()\"\n (dragstart)=\"onRowDragStart($event, i)\"\n (dragover)=\"onRowDragOver($event)\"\n (drop)=\"onRowDrop($event, i)\"\n >\n @if (selectable()) {\n <td class=\"ui-table-select-cell\">\n <ui-checkbox\n [value]=\"isRowSelected(row, i)\"\n (valueChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n\n @for (column of renderColumns(); track column.id) {\n <td\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n @if (column.displayType === 'icon') {\n <ng-icon\n [name]=\"cellIconValue(column, row)\"\n class=\"size-4\"\n />\n } @else if (column.displayType === 'currency') {\n <ui-money\n [value]=\"moneyCellValue(column, row)\"\n [currency]=\"column.currency ?? uiFormat.currency\"\n placeholder=\"\"\n />\n } @else if (column.sensitive) {\n <ui-private [text]=\"formattedCellValue(column, row)\" />\n } @else {\n {{ formattedCellValue(column, row) }}\n }\n </td>\n }\n\n @if (hasActions()) {\n <td class=\"ui-table-actions-cell\">\n @for (action of actions(); track action.id) {\n <ui-button\n appearance=\"none\"\n classes=\"p-1.5! border-transparent! rounded-md! text-muted-foreground-1 cursor-pointer hocus:bg-surface hocus:text-foreground disabled:opacity-40! disabled:cursor-not-allowed\"\n [disabled]=\"!!action.disabled?.(row)\"\n [ariaLabel]=\"action.label\"\n [title]=\"action.label\"\n (click)=\"action.onClick(row)\"\n >\n <ng-icon\n [name]=\"action.icon\"\n class=\"size-4\"\n />\n </ui-button>\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (dragPreview(); as preview) {\n <div\n class=\"ui-table-drag-preview ui-text-body-alt\"\n [style.left.px]=\"preview.x\"\n [style.top.px]=\"preview.y\"\n [style.width.px]=\"preview.width\"\n [style.height.px]=\"preview.height\"\n >\n <ng-icon name=\"heroBars2\" class=\"ui-table-drag-preview-icon\" />\n <span class=\"truncate\">{{ preview.label }}</span>\n </div>\n}\n\n@if (paginated()) {\n <div class=\"ui-table-footer\">\n <span class=\"text-muted-foreground-1 ui-text-caption\">{{\n resultsLabel()\n }}</span>\n\n <div class=\"ui-table-pagination\">\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n >\n Prev\n </ui-button>\n\n <span class=\"ui-text-body-alt\">Page {{ currentPage() + 1 }} of {{\n totalPages()\n }}</span>\n\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() + 1 >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n >\n Next\n </ui-button>\n </div>\n </div>\n}\n",
|
|
10237
|
+
template: "@if (searchable() || hasFilterableColumns() || toggleableColumns()) {\n <div class=\"ui-table-toolbar\">\n @if (searchable()) {\n <ui-input\n [value]=\"query()\"\n (valueChange)=\"onQueryChange($event)\"\n [placeholder]=\"searchPlaceholder()\"\n class=\"max-w-xs\"\n >\n <ng-template #leading>\n <ng-icon\n name=\"heroMagnifyingGlass\"\n class=\"ms-3 size-4 text-muted-foreground-1\"\n />\n </ng-template>\n </ui-input>\n }\n\n @if (hasFilterableColumns()) {\n <ui-dropdown\n [isOpen]=\"filterMenuOpen\"\n placement=\"bottom-start\"\n closeBehaviour=\"whenClickOutside\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"filterMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroFunnel\" class=\"size-4\" />\n Filters\n @if (activeFilterCount()) {\n <span class=\"ui-table-filter-count ui-text-caption\">\n {{ activeFilterCount() }}\n </span>\n }\n </ui-button>\n\n @if (filterMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"ui-table-filter-menu\">\n @for (column of filterableColumns(); track column.id) {\n <div class=\"flex flex-col gap-1\">\n <span\n class=\"text-muted-foreground-1 ui-text-caption\"\n >\n {{ column.header }}\n </span>\n\n @if (column.filterOptions) {\n <ui-select\n [dataSource]=\"filterDataSource(column)\"\n [selectedItem]=\"selectedFilterOption(column)\"\n (selectionChange)=\"onFilterSelect(column.id, $event)\"\n [displayWith]=\"column.sensitive ? sensitiveFilterOptionLabel : filterOptionLabel\"\n [clearable]=\"true\"\n clearLabel=\"All\"\n placeholder=\"All\"\n />\n } @else {\n <ui-input\n [value]=\"filterValue(column.id)\"\n (valueChange)=\"onFilterInput(column.id, $event)\"\n placeholder=\"Filter...\"\n [ariaLabel]=\"'Filter ' + column.header\"\n />\n }\n </div>\n }\n\n @if (activeFilterCount()) {\n <ui-button\n appearance=\"link\"\n intent=\"secondary\"\n class=\"text-end\"\n classes=\"self-end p-0! text-sm\"\n (click)=\"clearFilters()\"\n >\n Clear filters\n </ui-button>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n\n @if (toggleableColumns()) {\n <ui-dropdown\n [isOpen]=\"columnMenuOpen\"\n placement=\"bottom-end\"\n closeBehaviour=\"whenClickOutside\"\n class=\"ms-auto\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"columnMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroViewColumns\" class=\"size-4\" />\n Columns\n </ui-button>\n\n @if (columnMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"bg-layer shadow-xs py-1 border border-dropdown-divider rounded-lg min-w-40\">\n @for (column of hideableColumns(); track column.id) {\n <label\n class=\"flex items-center gap-2 hover:bg-dropdown-item-hover px-3 py-2 ui-text-body-alt cursor-pointer\"\n >\n <ui-checkbox\n [value]=\"isColumnVisible(column)\"\n (valueChange)=\"toggleColumnVisibility(column)\"\n />\n {{ column.header }}\n </label>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n </div>\n}\n\n<div class=\"ui-table-scroll\">\n <table [class]=\"generatedClasses()\" [style.width.px]=\"fixedWidth()\">\n <colgroup>\n @if (selectable()) {\n <col [style.width.px]=\"44\" />\n }\n\n @for (column of renderColumns(); track column.id) {\n <col [style.width.px]=\"columnWidth(column)\" />\n }\n\n @if (hasActions()) {\n <col [style.width.px]=\"actionsColumnWidth()\" />\n }\n </colgroup>\n\n <thead [class.ui-table-sticky]=\"stickyHeader()\">\n <tr>\n @if (selectable()) {\n <th class=\"text-center! ui-table-select-cell\">\n <ui-checkbox\n [value]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (valueChange)=\"toggleSelectAll()\"\n />\n </th>\n }\n\n @for (column of renderColumns(); track column.id) {\n <th\n scope=\"col\"\n [attr.data-column-id]=\"column.id\"\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [class.ui-table-column-dragging]=\"draggedColumnId() === column.id\"\n [class.ui-table-column-drag-over]=\"dragOverColumnId() === column.id\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n <div class=\"ui-table-th-content\">\n @if (reorderableColumns() && column.reorderable !== false) {\n <ng-icon\n name=\"heroBars2\"\n class=\"ui-table-drag-handle\"\n (pointerdown)=\"onColumnDragStart($event, column)\"\n />\n }\n\n @if (column.sortable) {\n <ui-button\n appearance=\"none\"\n classes=\"flex items-center gap-1 p-0! border-transparent! rounded-none! cursor-pointer hover:text-foreground focus-visible:text-foreground\"\n (click)=\"toggleSort(column)\"\n >\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n <svg\n viewBox=\"0 0 8 13\"\n aria-hidden=\"true\"\n class=\"ui-table-sort\"\n [attr.data-direction]=\"sortDirection(column)\"\n >\n <path class=\"ui-table-sort-asc\" d=\"M4 0 8 5H0z\" />\n <path class=\"ui-table-sort-desc\" d=\"M4 13 0 8h8z\" />\n </svg>\n </ui-button>\n } @else {\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n }\n </div>\n\n @if (column.resizable) {\n <span\n class=\"ui-table-resize-handle\"\n (pointerdown)=\"startResize($event, column)\"\n ></span>\n }\n </th>\n }\n\n @if (hasActions()) {\n <th class=\"ui-table-actions-cell\"></th>\n }\n </tr>\n </thead>\n\n <tbody class=\"ui-text-body-alt\">\n @if (loading()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n <ui-loading type=\"loading-dots\" />\n </td>\n </tr>\n } @else if (error()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status ui-table-status-error\"\n >\n {{ errorMessage() }}\n <ui-button\n appearance=\"link\"\n intent=\"danger\"\n classes=\"ms-1 p-0! text-sm underline\"\n (click)=\"reload()\"\n >\n Retry\n </ui-button>\n </td>\n </tr>\n } @else if (isEmpty()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n {{ emptyMessage() }}\n </td>\n </tr>\n } @else {\n @for (row of rows(); track rowId()(row, $index); let i = $index) {\n <tr\n [class.ui-table-row-selected]=\"isRowSelected(row, i)\"\n [class.ui-table-row-dragging]=\"draggedRowIndex() === i\"\n [draggable]=\"canReorderRows()\"\n (dragstart)=\"onRowDragStart($event, i)\"\n (dragover)=\"onRowDragOver($event)\"\n (drop)=\"onRowDrop($event, i)\"\n >\n @if (selectable()) {\n <td class=\"ui-table-select-cell\">\n <ui-checkbox\n [value]=\"isRowSelected(row, i)\"\n (valueChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n\n @for (column of renderColumns(); track column.id) {\n <td\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n @if (column.displayType === 'icon') {\n <ng-icon\n [name]=\"cellIconValue(column, row)\"\n class=\"size-4\"\n />\n } @else if (column.displayType === 'currency') {\n <ui-money\n [value]=\"moneyCellValue(column, row)\"\n [currency]=\"column.currency ?? uiFormat.currency\"\n placeholder=\"\"\n />\n } @else if (column.sensitive) {\n <ui-private [text]=\"formattedCellValue(column, row)\" />\n } @else {\n {{ formattedCellValue(column, row) }}\n }\n </td>\n }\n\n @if (hasActions()) {\n <td class=\"ui-table-actions-cell\">\n @for (action of actions(); track action.id) {\n <ui-tooltip [text]=\"action.label\">\n <ui-button\n appearance=\"none\"\n classes=\"p-1.5! border-transparent! rounded-md! text-muted-foreground-1 cursor-pointer hover:bg-surface-hover hover:text-foreground focus-visible:bg-surface-hover focus-visible:text-foreground disabled:opacity-40! disabled:cursor-not-allowed\"\n [disabled]=\"!!action.disabled?.(row)\"\n [ariaLabel]=\"action.label\"\n (click)=\"action.onClick(row)\"\n >\n <ng-icon\n [name]=\"action.icon\"\n class=\"size-4\"\n />\n </ui-button>\n </ui-tooltip>\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (dragPreview(); as preview) {\n <div\n class=\"ui-table-drag-preview ui-text-body-alt\"\n [style.left.px]=\"preview.x\"\n [style.top.px]=\"preview.y\"\n [style.width.px]=\"preview.width\"\n [style.height.px]=\"preview.height\"\n >\n <ng-icon name=\"heroBars2\" class=\"ui-table-drag-preview-icon\" />\n <span class=\"truncate\">{{ preview.label }}</span>\n </div>\n}\n\n@if (paginated()) {\n <div class=\"ui-table-footer\">\n <span class=\"text-muted-foreground-1 ui-text-caption\">{{\n resultsLabel()\n }}</span>\n\n <div class=\"ui-table-pagination\">\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n >\n Prev\n </ui-button>\n\n <span class=\"ui-text-body-alt\">Page {{ currentPage() + 1 }} of {{\n totalPages()\n }}</span>\n\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() + 1 >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n >\n Next\n </ui-button>\n </div>\n </div>\n}\n",
|
|
10238
10238
|
styles: ["@layer properties;:host{min-width:100%}.ui-table-toolbar{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.ui-table-scroll{overflow-x:auto;border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--table-line)}.ui-table-scroll::-webkit-scrollbar{height:calc(var(--spacing, .25rem) * 2)}.ui-table-scroll::-webkit-scrollbar-thumb{border-radius:0}.ui-table-scroll::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb)}.ui-table-scroll::-webkit-scrollbar-track{background-color:var(--scrollbar-track)}.ui-table-scroll:has(.ui-table-sticky){max-height:480px}.ui-table{min-width:100%}.ui-table--fixed{table-layout:fixed}.ui-table thead{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--table-line);background-color:var(--muted)}.ui-table thead:where(.dark,.dark *){background-color:var(--color-neutral-700, oklch(37.1% 0 none))}.ui-table thead.ui-table-sticky{position:sticky;top:0;z-index:20}.ui-table th{padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 3);text-align:start}.ui-table td{overflow:hidden;text-overflow:ellipsis;padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 4);white-space:nowrap}.ui-table tbody{background-color:var(--layer)}:where(.ui-table tbody>:not(:last-child)){--tw-divide-y-reverse: 0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.ui-table tbody>:not(:last-child)){border-color:var(--table-line)}.ui-table tbody tr:last-child{border-bottom-style:var(--tw-border-style)!important;border-bottom-width:0px!important}.ui-table tbody tr:hover{background-color:var(--muted)}.ui-table-row-selected{background-color:var(--color-primary-50, var(--color-blue-50))}.ui-table-row-dragging{opacity:40%}.ui-table-pinned{position:sticky;z-index:10;background-color:var(--layer)}.ui-table-row-selected .ui-table-pinned{background-color:var(--color-primary-50, var(--color-blue-50))}.ui-table th.ui-table-pinned{position:sticky;z-index:30;background-color:var(--muted)}.ui-table th.ui-table-pinned:where(.dark,.dark *){background-color:var(--color-neutral-700, oklch(37.1% 0 none))}.ui-table [data-pin=left]{border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--border-line-2)}.ui-table [data-pin=right]{border-left-style:var(--tw-border-style);border-left-width:1px;border-color:var(--border-line-2)}.ui-table-th-content{display:flex;align-items:center;gap:var(--spacing, .25rem)}.ui-table-sort{height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 2);flex-shrink:0;fill:currentcolor;color:var(--muted-foreground-1)}.ui-table-sort path{opacity:30%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s))}.ui-table-sort[data-direction]{color:var(--color-primary-500, var(--color-blue-500))}.ui-table-sort[data-direction=asc] .ui-table-sort-asc,.ui-table-sort[data-direction=desc] .ui-table-sort-desc{opacity:100%}.ui-table-drag-handle{width:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 4);flex-shrink:0;cursor:grab;color:var(--muted-foreground-1)}.ui-table-column-dragging{opacity:40%}.ui-table-column-drag-over{background-color:var(--color-primary-50, var(--color-blue-50))}.ui-table-drag-preview{pointer-events:none;position:fixed;z-index:50;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border-line-2);background-color:var(--layer);padding-right:calc(var(--spacing, .25rem) * 3);padding-left:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground);--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ui-table-drag-preview-icon{width:calc(var(--spacing, .25rem) * 3.5);height:calc(var(--spacing, .25rem) * 3.5);flex-shrink:0;color:var(--color-primary-500, var(--color-blue-500))}.ui-table-resize-handle{position:absolute;top:0;right:0;height:100%;width:calc(var(--spacing, .25rem) * 1.5);cursor:col-resize}.ui-table-resize-handle:hover,.ui-table-resize-handle:focus-visible{background-color:var(--color-primary-300, var(--color-blue-300))}.ui-table-filter-menu{display:flex;width:calc(var(--spacing, .25rem) * 64);flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--dropdown-divider);background-color:var(--layer);padding:calc(var(--spacing, .25rem) * 3);--tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, rgb(0 0 0 / .05));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ui-table-filter-count{display:inline-flex;height:calc(var(--spacing, .25rem) * 5);min-width:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;border-radius:var(--radius-full, calc(infinity * 1px));background-color:var(--color-primary-50, var(--color-blue-50));padding-inline:var(--spacing, .25rem);color:var(--color-primary-600, var(--color-blue-600))}.ui-table-select-cell,.ui-table-actions-cell{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);text-align:center}.ui-table-actions-cell{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing, .25rem)}.ui-table-status{padding-block:calc(var(--spacing, .25rem) * 8);text-align:center;color:var(--muted-foreground-1)}.ui-table-status-error{color:var(--color-danger-500, var(--color-red-500))}.ui-table-footer{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.ui-table-pagination{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-divide-y-reverse{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-divide-y-reverse: 0;--tw-font-weight: initial;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
|
|
10239
10239
|
dependencies: [
|
|
10240
10240
|
{
|
|
@@ -10406,6 +10406,19 @@ var UiTableComponent = class UiTableComponent {
|
|
|
10406
10406
|
type: UiPrivateComponent,
|
|
10407
10407
|
selector: "ui-private",
|
|
10408
10408
|
inputs: ["text"]
|
|
10409
|
+
},
|
|
10410
|
+
{
|
|
10411
|
+
kind: "component",
|
|
10412
|
+
type: UiTooltipComponent,
|
|
10413
|
+
selector: "ui-tooltip",
|
|
10414
|
+
inputs: [
|
|
10415
|
+
"text",
|
|
10416
|
+
"placement",
|
|
10417
|
+
"trigger",
|
|
10418
|
+
"classes",
|
|
10419
|
+
"isOpen"
|
|
10420
|
+
],
|
|
10421
|
+
exportAs: ["uiTooltip"]
|
|
10409
10422
|
}
|
|
10410
10423
|
]
|
|
10411
10424
|
});
|
|
@@ -10429,7 +10442,8 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
10429
10442
|
UiSelectComponent,
|
|
10430
10443
|
UiLoadingComponent,
|
|
10431
10444
|
UiMoneyComponent,
|
|
10432
|
-
UiPrivateComponent
|
|
10445
|
+
UiPrivateComponent,
|
|
10446
|
+
UiTooltipComponent
|
|
10433
10447
|
],
|
|
10434
10448
|
host: { class: "block" },
|
|
10435
10449
|
providers: [provideIcons({
|
|
@@ -10438,7 +10452,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
10438
10452
|
heroViewColumns,
|
|
10439
10453
|
heroBars2
|
|
10440
10454
|
})],
|
|
10441
|
-
template: "@if (searchable() || hasFilterableColumns() || toggleableColumns()) {\n <div class=\"ui-table-toolbar\">\n @if (searchable()) {\n <ui-input\n [value]=\"query()\"\n (valueChange)=\"onQueryChange($event)\"\n [placeholder]=\"searchPlaceholder()\"\n class=\"max-w-xs\"\n >\n <ng-template #leading>\n <ng-icon\n name=\"heroMagnifyingGlass\"\n class=\"ms-3 size-4 text-muted-foreground-1\"\n />\n </ng-template>\n </ui-input>\n }\n\n @if (hasFilterableColumns()) {\n <ui-dropdown\n [isOpen]=\"filterMenuOpen\"\n placement=\"bottom-start\"\n closeBehaviour=\"whenClickOutside\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"filterMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroFunnel\" class=\"size-4\" />\n Filters\n @if (activeFilterCount()) {\n <span class=\"ui-table-filter-count ui-text-caption\">\n {{ activeFilterCount() }}\n </span>\n }\n </ui-button>\n\n @if (filterMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"ui-table-filter-menu\">\n @for (column of filterableColumns(); track column.id) {\n <div class=\"flex flex-col gap-1\">\n <span\n class=\"text-muted-foreground-1 ui-text-caption\"\n >\n {{ column.header }}\n </span>\n\n @if (column.filterOptions) {\n <ui-select\n [dataSource]=\"filterDataSource(column)\"\n [selectedItem]=\"selectedFilterOption(column)\"\n (selectionChange)=\"onFilterSelect(column.id, $event)\"\n [displayWith]=\"column.sensitive ? sensitiveFilterOptionLabel : filterOptionLabel\"\n [clearable]=\"true\"\n clearLabel=\"All\"\n placeholder=\"All\"\n />\n } @else {\n <ui-input\n [value]=\"filterValue(column.id)\"\n (valueChange)=\"onFilterInput(column.id, $event)\"\n placeholder=\"Filter...\"\n [ariaLabel]=\"'Filter ' + column.header\"\n />\n }\n </div>\n }\n\n @if (activeFilterCount()) {\n <ui-button\n appearance=\"link\"\n intent=\"secondary\"\n class=\"text-end\"\n classes=\"self-end p-0! text-sm\"\n (click)=\"clearFilters()\"\n >\n Clear filters\n </ui-button>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n\n @if (toggleableColumns()) {\n <ui-dropdown\n [isOpen]=\"columnMenuOpen\"\n placement=\"bottom-end\"\n closeBehaviour=\"whenClickOutside\"\n class=\"ms-auto\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"columnMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroViewColumns\" class=\"size-4\" />\n Columns\n </ui-button>\n\n @if (columnMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"bg-layer shadow-xs py-1 border border-dropdown-divider rounded-lg min-w-40\">\n @for (column of hideableColumns(); track column.id) {\n <label\n class=\"flex items-center gap-2 hover:bg-dropdown-item-hover px-3 py-2 ui-text-body-alt cursor-pointer\"\n >\n <ui-checkbox\n [value]=\"isColumnVisible(column)\"\n (valueChange)=\"toggleColumnVisibility(column)\"\n />\n {{ column.header }}\n </label>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n </div>\n}\n\n<div class=\"ui-table-scroll\">\n <table [class]=\"generatedClasses()\" [style.width.px]=\"fixedWidth()\">\n <colgroup>\n @if (selectable()) {\n <col [style.width.px]=\"44\" />\n }\n\n @for (column of renderColumns(); track column.id) {\n <col [style.width.px]=\"columnWidth(column)\" />\n }\n\n @if (hasActions()) {\n <col [style.width.px]=\"actionsColumnWidth()\" />\n }\n </colgroup>\n\n <thead [class.ui-table-sticky]=\"stickyHeader()\">\n <tr>\n @if (selectable()) {\n <th class=\"text-center! ui-table-select-cell\">\n <ui-checkbox\n [value]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (valueChange)=\"toggleSelectAll()\"\n />\n </th>\n }\n\n @for (column of renderColumns(); track column.id) {\n <th\n scope=\"col\"\n [attr.data-column-id]=\"column.id\"\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [class.ui-table-column-dragging]=\"draggedColumnId() === column.id\"\n [class.ui-table-column-drag-over]=\"dragOverColumnId() === column.id\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n <div class=\"ui-table-th-content\">\n @if (reorderableColumns() && column.reorderable !== false) {\n <ng-icon\n name=\"heroBars2\"\n class=\"ui-table-drag-handle\"\n (pointerdown)=\"onColumnDragStart($event, column)\"\n />\n }\n\n @if (column.sortable) {\n <ui-button\n appearance=\"none\"\n classes=\"flex items-center gap-1 p-0! border-transparent! rounded-none! cursor-pointer hocus:text-foreground\"\n (click)=\"toggleSort(column)\"\n >\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n <svg\n viewBox=\"0 0 8 13\"\n aria-hidden=\"true\"\n class=\"ui-table-sort\"\n [attr.data-direction]=\"sortDirection(column)\"\n >\n <path class=\"ui-table-sort-asc\" d=\"M4 0 8 5H0z\" />\n <path class=\"ui-table-sort-desc\" d=\"M4 13 0 8h8z\" />\n </svg>\n </ui-button>\n } @else {\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n }\n </div>\n\n @if (column.resizable) {\n <span\n class=\"ui-table-resize-handle\"\n (pointerdown)=\"startResize($event, column)\"\n ></span>\n }\n </th>\n }\n\n @if (hasActions()) {\n <th class=\"ui-table-actions-cell\"></th>\n }\n </tr>\n </thead>\n\n <tbody class=\"ui-text-body-alt\">\n @if (loading()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n <ui-loading type=\"loading-dots\" />\n </td>\n </tr>\n } @else if (error()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status ui-table-status-error\"\n >\n {{ errorMessage() }}\n <ui-button\n appearance=\"link\"\n intent=\"danger\"\n classes=\"ms-1 p-0! text-sm underline\"\n (click)=\"reload()\"\n >\n Retry\n </ui-button>\n </td>\n </tr>\n } @else if (isEmpty()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n {{ emptyMessage() }}\n </td>\n </tr>\n } @else {\n @for (row of rows(); track rowId()(row, $index); let i = $index) {\n <tr\n [class.ui-table-row-selected]=\"isRowSelected(row, i)\"\n [class.ui-table-row-dragging]=\"draggedRowIndex() === i\"\n [draggable]=\"canReorderRows()\"\n (dragstart)=\"onRowDragStart($event, i)\"\n (dragover)=\"onRowDragOver($event)\"\n (drop)=\"onRowDrop($event, i)\"\n >\n @if (selectable()) {\n <td class=\"ui-table-select-cell\">\n <ui-checkbox\n [value]=\"isRowSelected(row, i)\"\n (valueChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n\n @for (column of renderColumns(); track column.id) {\n <td\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n @if (column.displayType === 'icon') {\n <ng-icon\n [name]=\"cellIconValue(column, row)\"\n class=\"size-4\"\n />\n } @else if (column.displayType === 'currency') {\n <ui-money\n [value]=\"moneyCellValue(column, row)\"\n [currency]=\"column.currency ?? uiFormat.currency\"\n placeholder=\"\"\n />\n } @else if (column.sensitive) {\n <ui-private [text]=\"formattedCellValue(column, row)\" />\n } @else {\n {{ formattedCellValue(column, row) }}\n }\n </td>\n }\n\n @if (hasActions()) {\n <td class=\"ui-table-actions-cell\">\n @for (action of actions(); track action.id) {\n <ui-button\n appearance=\"none\"\n classes=\"p-1.5! border-transparent! rounded-md! text-muted-foreground-1 cursor-pointer hocus:bg-surface hocus:text-foreground disabled:opacity-40! disabled:cursor-not-allowed\"\n [disabled]=\"!!action.disabled?.(row)\"\n [ariaLabel]=\"action.label\"\n [title]=\"action.label\"\n (click)=\"action.onClick(row)\"\n >\n <ng-icon\n [name]=\"action.icon\"\n class=\"size-4\"\n />\n </ui-button>\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (dragPreview(); as preview) {\n <div\n class=\"ui-table-drag-preview ui-text-body-alt\"\n [style.left.px]=\"preview.x\"\n [style.top.px]=\"preview.y\"\n [style.width.px]=\"preview.width\"\n [style.height.px]=\"preview.height\"\n >\n <ng-icon name=\"heroBars2\" class=\"ui-table-drag-preview-icon\" />\n <span class=\"truncate\">{{ preview.label }}</span>\n </div>\n}\n\n@if (paginated()) {\n <div class=\"ui-table-footer\">\n <span class=\"text-muted-foreground-1 ui-text-caption\">{{\n resultsLabel()\n }}</span>\n\n <div class=\"ui-table-pagination\">\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n >\n Prev\n </ui-button>\n\n <span class=\"ui-text-body-alt\">Page {{ currentPage() + 1 }} of {{\n totalPages()\n }}</span>\n\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() + 1 >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n >\n Next\n </ui-button>\n </div>\n </div>\n}\n",
|
|
10455
|
+
template: "@if (searchable() || hasFilterableColumns() || toggleableColumns()) {\n <div class=\"ui-table-toolbar\">\n @if (searchable()) {\n <ui-input\n [value]=\"query()\"\n (valueChange)=\"onQueryChange($event)\"\n [placeholder]=\"searchPlaceholder()\"\n class=\"max-w-xs\"\n >\n <ng-template #leading>\n <ng-icon\n name=\"heroMagnifyingGlass\"\n class=\"ms-3 size-4 text-muted-foreground-1\"\n />\n </ng-template>\n </ui-input>\n }\n\n @if (hasFilterableColumns()) {\n <ui-dropdown\n [isOpen]=\"filterMenuOpen\"\n placement=\"bottom-start\"\n closeBehaviour=\"whenClickOutside\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"filterMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroFunnel\" class=\"size-4\" />\n Filters\n @if (activeFilterCount()) {\n <span class=\"ui-table-filter-count ui-text-caption\">\n {{ activeFilterCount() }}\n </span>\n }\n </ui-button>\n\n @if (filterMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"ui-table-filter-menu\">\n @for (column of filterableColumns(); track column.id) {\n <div class=\"flex flex-col gap-1\">\n <span\n class=\"text-muted-foreground-1 ui-text-caption\"\n >\n {{ column.header }}\n </span>\n\n @if (column.filterOptions) {\n <ui-select\n [dataSource]=\"filterDataSource(column)\"\n [selectedItem]=\"selectedFilterOption(column)\"\n (selectionChange)=\"onFilterSelect(column.id, $event)\"\n [displayWith]=\"column.sensitive ? sensitiveFilterOptionLabel : filterOptionLabel\"\n [clearable]=\"true\"\n clearLabel=\"All\"\n placeholder=\"All\"\n />\n } @else {\n <ui-input\n [value]=\"filterValue(column.id)\"\n (valueChange)=\"onFilterInput(column.id, $event)\"\n placeholder=\"Filter...\"\n [ariaLabel]=\"'Filter ' + column.header\"\n />\n }\n </div>\n }\n\n @if (activeFilterCount()) {\n <ui-button\n appearance=\"link\"\n intent=\"secondary\"\n class=\"text-end\"\n classes=\"self-end p-0! text-sm\"\n (click)=\"clearFilters()\"\n >\n Clear filters\n </ui-button>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n\n @if (toggleableColumns()) {\n <ui-dropdown\n [isOpen]=\"columnMenuOpen\"\n placement=\"bottom-end\"\n closeBehaviour=\"whenClickOutside\"\n class=\"ms-auto\"\n >\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n (click)=\"columnMenuOpen.update(open => !open)\"\n >\n <ng-icon name=\"heroViewColumns\" class=\"size-4\" />\n Columns\n </ui-button>\n\n @if (columnMenuOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <div class=\"bg-layer shadow-xs py-1 border border-dropdown-divider rounded-lg min-w-40\">\n @for (column of hideableColumns(); track column.id) {\n <label\n class=\"flex items-center gap-2 hover:bg-dropdown-item-hover px-3 py-2 ui-text-body-alt cursor-pointer\"\n >\n <ui-checkbox\n [value]=\"isColumnVisible(column)\"\n (valueChange)=\"toggleColumnVisibility(column)\"\n />\n {{ column.header }}\n </label>\n }\n </div>\n </div>\n }\n </ui-dropdown>\n }\n </div>\n}\n\n<div class=\"ui-table-scroll\">\n <table [class]=\"generatedClasses()\" [style.width.px]=\"fixedWidth()\">\n <colgroup>\n @if (selectable()) {\n <col [style.width.px]=\"44\" />\n }\n\n @for (column of renderColumns(); track column.id) {\n <col [style.width.px]=\"columnWidth(column)\" />\n }\n\n @if (hasActions()) {\n <col [style.width.px]=\"actionsColumnWidth()\" />\n }\n </colgroup>\n\n <thead [class.ui-table-sticky]=\"stickyHeader()\">\n <tr>\n @if (selectable()) {\n <th class=\"text-center! ui-table-select-cell\">\n <ui-checkbox\n [value]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (valueChange)=\"toggleSelectAll()\"\n />\n </th>\n }\n\n @for (column of renderColumns(); track column.id) {\n <th\n scope=\"col\"\n [attr.data-column-id]=\"column.id\"\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [class.ui-table-column-dragging]=\"draggedColumnId() === column.id\"\n [class.ui-table-column-drag-over]=\"dragOverColumnId() === column.id\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n <div class=\"ui-table-th-content\">\n @if (reorderableColumns() && column.reorderable !== false) {\n <ng-icon\n name=\"heroBars2\"\n class=\"ui-table-drag-handle\"\n (pointerdown)=\"onColumnDragStart($event, column)\"\n />\n }\n\n @if (column.sortable) {\n <ui-button\n appearance=\"none\"\n classes=\"flex items-center gap-1 p-0! border-transparent! rounded-none! cursor-pointer hover:text-foreground focus-visible:text-foreground\"\n (click)=\"toggleSort(column)\"\n >\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n <svg\n viewBox=\"0 0 8 13\"\n aria-hidden=\"true\"\n class=\"ui-table-sort\"\n [attr.data-direction]=\"sortDirection(column)\"\n >\n <path class=\"ui-table-sort-asc\" d=\"M4 0 8 5H0z\" />\n <path class=\"ui-table-sort-desc\" d=\"M4 13 0 8h8z\" />\n </svg>\n </ui-button>\n } @else {\n <span\n class=\"font-medium text-muted-foreground-1 ui-text-caption ui-text-caption uppercase\"\n >\n {{ column.header }}\n </span>\n }\n </div>\n\n @if (column.resizable) {\n <span\n class=\"ui-table-resize-handle\"\n (pointerdown)=\"startResize($event, column)\"\n ></span>\n }\n </th>\n }\n\n @if (hasActions()) {\n <th class=\"ui-table-actions-cell\"></th>\n }\n </tr>\n </thead>\n\n <tbody class=\"ui-text-body-alt\">\n @if (loading()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n <ui-loading type=\"loading-dots\" />\n </td>\n </tr>\n } @else if (error()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status ui-table-status-error\"\n >\n {{ errorMessage() }}\n <ui-button\n appearance=\"link\"\n intent=\"danger\"\n classes=\"ms-1 p-0! text-sm underline\"\n (click)=\"reload()\"\n >\n Retry\n </ui-button>\n </td>\n </tr>\n } @else if (isEmpty()) {\n <tr>\n <td\n [attr.colspan]=\"renderColumns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\"\n class=\"ui-table-status\"\n >\n {{ emptyMessage() }}\n </td>\n </tr>\n } @else {\n @for (row of rows(); track rowId()(row, $index); let i = $index) {\n <tr\n [class.ui-table-row-selected]=\"isRowSelected(row, i)\"\n [class.ui-table-row-dragging]=\"draggedRowIndex() === i\"\n [draggable]=\"canReorderRows()\"\n (dragstart)=\"onRowDragStart($event, i)\"\n (dragover)=\"onRowDragOver($event)\"\n (drop)=\"onRowDrop($event, i)\"\n >\n @if (selectable()) {\n <td class=\"ui-table-select-cell\">\n <ui-checkbox\n [value]=\"isRowSelected(row, i)\"\n (valueChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n\n @for (column of renderColumns(); track column.id) {\n <td\n [class.ui-table-pinned]=\"isPinned(column)\"\n [attr.data-pin]=\"column.pin || null\"\n [style.left.px]=\"leftOffset(column)\"\n [style.right.px]=\"rightOffset(column)\"\n >\n @if (column.displayType === 'icon') {\n <ng-icon\n [name]=\"cellIconValue(column, row)\"\n class=\"size-4\"\n />\n } @else if (column.displayType === 'currency') {\n <ui-money\n [value]=\"moneyCellValue(column, row)\"\n [currency]=\"column.currency ?? uiFormat.currency\"\n placeholder=\"\"\n />\n } @else if (column.sensitive) {\n <ui-private [text]=\"formattedCellValue(column, row)\" />\n } @else {\n {{ formattedCellValue(column, row) }}\n }\n </td>\n }\n\n @if (hasActions()) {\n <td class=\"ui-table-actions-cell\">\n @for (action of actions(); track action.id) {\n <ui-tooltip [text]=\"action.label\">\n <ui-button\n appearance=\"none\"\n classes=\"p-1.5! border-transparent! rounded-md! text-muted-foreground-1 cursor-pointer hover:bg-surface-hover hover:text-foreground focus-visible:bg-surface-hover focus-visible:text-foreground disabled:opacity-40! disabled:cursor-not-allowed\"\n [disabled]=\"!!action.disabled?.(row)\"\n [ariaLabel]=\"action.label\"\n (click)=\"action.onClick(row)\"\n >\n <ng-icon\n [name]=\"action.icon\"\n class=\"size-4\"\n />\n </ui-button>\n </ui-tooltip>\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (dragPreview(); as preview) {\n <div\n class=\"ui-table-drag-preview ui-text-body-alt\"\n [style.left.px]=\"preview.x\"\n [style.top.px]=\"preview.y\"\n [style.width.px]=\"preview.width\"\n [style.height.px]=\"preview.height\"\n >\n <ng-icon name=\"heroBars2\" class=\"ui-table-drag-preview-icon\" />\n <span class=\"truncate\">{{ preview.label }}</span>\n </div>\n}\n\n@if (paginated()) {\n <div class=\"ui-table-footer\">\n <span class=\"text-muted-foreground-1 ui-text-caption\">{{\n resultsLabel()\n }}</span>\n\n <div class=\"ui-table-pagination\">\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n >\n Prev\n </ui-button>\n\n <span class=\"ui-text-body-alt\">Page {{ currentPage() + 1 }} of {{\n totalPages()\n }}</span>\n\n <ui-button\n size=\"sm\"\n appearance=\"white\"\n intent=\"secondary\"\n [disabled]=\"currentPage() + 1 >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n >\n Next\n </ui-button>\n </div>\n </div>\n}\n",
|
|
10442
10456
|
styles: ["@layer properties;:host{min-width:100%}.ui-table-toolbar{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.ui-table-scroll{overflow-x:auto;border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--table-line)}.ui-table-scroll::-webkit-scrollbar{height:calc(var(--spacing, .25rem) * 2)}.ui-table-scroll::-webkit-scrollbar-thumb{border-radius:0}.ui-table-scroll::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb)}.ui-table-scroll::-webkit-scrollbar-track{background-color:var(--scrollbar-track)}.ui-table-scroll:has(.ui-table-sticky){max-height:480px}.ui-table{min-width:100%}.ui-table--fixed{table-layout:fixed}.ui-table thead{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--table-line);background-color:var(--muted)}.ui-table thead:where(.dark,.dark *){background-color:var(--color-neutral-700, oklch(37.1% 0 none))}.ui-table thead.ui-table-sticky{position:sticky;top:0;z-index:20}.ui-table th{padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 3);text-align:start}.ui-table td{overflow:hidden;text-overflow:ellipsis;padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 4);white-space:nowrap}.ui-table tbody{background-color:var(--layer)}:where(.ui-table tbody>:not(:last-child)){--tw-divide-y-reverse: 0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.ui-table tbody>:not(:last-child)){border-color:var(--table-line)}.ui-table tbody tr:last-child{border-bottom-style:var(--tw-border-style)!important;border-bottom-width:0px!important}.ui-table tbody tr:hover{background-color:var(--muted)}.ui-table-row-selected{background-color:var(--color-primary-50, var(--color-blue-50))}.ui-table-row-dragging{opacity:40%}.ui-table-pinned{position:sticky;z-index:10;background-color:var(--layer)}.ui-table-row-selected .ui-table-pinned{background-color:var(--color-primary-50, var(--color-blue-50))}.ui-table th.ui-table-pinned{position:sticky;z-index:30;background-color:var(--muted)}.ui-table th.ui-table-pinned:where(.dark,.dark *){background-color:var(--color-neutral-700, oklch(37.1% 0 none))}.ui-table [data-pin=left]{border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--border-line-2)}.ui-table [data-pin=right]{border-left-style:var(--tw-border-style);border-left-width:1px;border-color:var(--border-line-2)}.ui-table-th-content{display:flex;align-items:center;gap:var(--spacing, .25rem)}.ui-table-sort{height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 2);flex-shrink:0;fill:currentcolor;color:var(--muted-foreground-1)}.ui-table-sort path{opacity:30%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s))}.ui-table-sort[data-direction]{color:var(--color-primary-500, var(--color-blue-500))}.ui-table-sort[data-direction=asc] .ui-table-sort-asc,.ui-table-sort[data-direction=desc] .ui-table-sort-desc{opacity:100%}.ui-table-drag-handle{width:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 4);flex-shrink:0;cursor:grab;color:var(--muted-foreground-1)}.ui-table-column-dragging{opacity:40%}.ui-table-column-drag-over{background-color:var(--color-primary-50, var(--color-blue-50))}.ui-table-drag-preview{pointer-events:none;position:fixed;z-index:50;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--border-line-2);background-color:var(--layer);padding-right:calc(var(--spacing, .25rem) * 3);padding-left:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:var(--foreground);--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ui-table-drag-preview-icon{width:calc(var(--spacing, .25rem) * 3.5);height:calc(var(--spacing, .25rem) * 3.5);flex-shrink:0;color:var(--color-primary-500, var(--color-blue-500))}.ui-table-resize-handle{position:absolute;top:0;right:0;height:100%;width:calc(var(--spacing, .25rem) * 1.5);cursor:col-resize}.ui-table-resize-handle:hover,.ui-table-resize-handle:focus-visible{background-color:var(--color-primary-300, var(--color-blue-300))}.ui-table-filter-menu{display:flex;width:calc(var(--spacing, .25rem) * 64);flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:var(--dropdown-divider);background-color:var(--layer);padding:calc(var(--spacing, .25rem) * 3);--tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, rgb(0 0 0 / .05));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ui-table-filter-count{display:inline-flex;height:calc(var(--spacing, .25rem) * 5);min-width:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;border-radius:var(--radius-full, calc(infinity * 1px));background-color:var(--color-primary-50, var(--color-blue-50));padding-inline:var(--spacing, .25rem);color:var(--color-primary-600, var(--color-blue-600))}.ui-table-select-cell,.ui-table-actions-cell{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);text-align:center}.ui-table-actions-cell{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing, .25rem)}.ui-table-status{padding-block:calc(var(--spacing, .25rem) * 8);text-align:center;color:var(--muted-foreground-1)}.ui-table-status-error{color:var(--color-danger-500, var(--color-red-500))}.ui-table-footer{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.ui-table-pagination{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-divide-y-reverse{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-divide-y-reverse: 0;--tw-font-weight: initial;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
|
|
10443
10457
|
}]
|
|
10444
10458
|
}],
|