@lifecorner/angular-ui-kit 3.36.0 → 3.38.0
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/fesm2022/lifecorner-angular-ui-kit-card.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-card.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-hero.mjs +24 -3
- package/fesm2022/lifecorner-angular-ui-kit-hero.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-internal-chart.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-internal-chart.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs +10 -5
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs +15 -10
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-state-strip.mjs +27 -4
- package/fesm2022/lifecorner-angular-ui-kit-state-strip.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/_theme-light.scss +8 -1
- package/src/styles/theme-contrast.spec.ts +44 -0
- package/src/styles/theme-modes.spec.ts +20 -5
- package/types/lifecorner-angular-ui-kit-hero.d.ts +19 -1
- package/types/lifecorner-angular-ui-kit-internal-chart.d.ts +6 -0
- package/types/lifecorner-angular-ui-kit-list.d.ts +10 -0
- package/types/lifecorner-angular-ui-kit-select.d.ts +13 -1
- package/types/lifecorner-angular-ui-kit-state-strip.d.ts +20 -2
- package/types/lifecorner-angular-ui-kit-table.d.ts +9 -1
|
@@ -1003,7 +1003,7 @@ var TableComponent = class TableComponent {
|
|
|
1003
1003
|
isSignal: true
|
|
1004
1004
|
}],
|
|
1005
1005
|
ngImport: i0,
|
|
1006
|
-
template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n @if (caption()) {\n <!-- First child of the table, so it names the table (and the treegrid). -->\n <caption class=\"lc-table__caption\" [class.lc-table__caption--hidden]=\"!showCaption()\">{{ caption() }}</caption>\n }\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"filterPlaceholderLabel() + ' ' + column.label\"\n [ariaLabel]=\"filterAriaLabel() + ' ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <!-- The label's ::before covers the cell: a 44 px hit area (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (change)=\"toggleSelectAll()\"\n [attr.aria-label]=\"selectAllAriaLabel()\"\n />\n </label>\n </th>\n }\n @for (column of columns(); track column.key) {\n <!-- A sortable header is a keyboard stop too: Enter/Space sort like a click. -->\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [attr.tabindex]=\"column.sortable ? 0 : null\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\"\n (keydown)=\"column.sortable ? onHeaderKeydown($event, column.key) : null\">\n @if (column.align === 'end') {\n <!-- 3.17: the arrow is placed before the label (CSS), so the label stays\n flush with the figures; in the DOM it still follows the label. No\n whitespace between the label and the arrow. -->\n <span class=\"lc-table__sort-label\">{{ column.label }}@if (column.sortable && getSortState(column.key)) {<span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>}</span>\n } @else {\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>\n }\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.key) {\n <!-- In tree mode the rows form the treegrid's keyboard model: a roving\n tab stop plus Arrow/Home/End/Enter/Space handling (see the\n component). Flat mode keeps plain table rows. -->\n <tr\n #dataRow\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.row)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.tabindex]=\"rowTabindex(dr)\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n [attr.aria-selected]=\"treeMode() && selectable() ? isRowSelected(dr.row) : null\"\n (click)=\"onRowClick(dr.row, $event)\"\n (focus)=\"onRowFocus(dr)\"\n (keydown)=\"onRowKeydown($event, dr)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <!-- A click in the cell toggles the box, never the row (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.row)\"\n (change)=\"toggleRowSelect(dr.row)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"selectRowAriaLabel() + ' ' + (dr.absIndex + 1)\"\n />\n </label>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.row, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? collapseRowAriaLabel() : expandRowAriaLabel()) + ' ' + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"actionAriaLabel(action, dr.row, dr.absIndex)\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n @if (footerRow(); as footer) {\n <!-- 3.36: one footer row below every data row; never sorted, filtered,\n paged, selected or counted. Its first cell is the row header. -->\n <tfoot class=\"lc-table__footer\">\n <tr [attr.role]=\"treeMode() ? 'row' : null\">\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\"></td>\n }\n @for (column of columns(); track column.key; let first = $first) {\n @if (first) {\n <th\n scope=\"row\"\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'rowheader' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </th>\n } @else {\n <td\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </td>\n }\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n ></td>\n }\n </tr>\n </tfoot>\n }\n </table>\n</div>\n\n<!-- 3.36: a footer cell. In the tree column the label lines up with the level-0\n labels (an empty disclosure slot before it). Templates get `footer: true`. -->\n<ng-template #footerCell let-row=\"row\" let-column=\"column\">\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\"></span>\n <span class=\"lc-table__tree-content\">\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n </span>\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n }\n</ng-template>\n\n<ng-template #footerContent let-row=\"row\" let-column=\"column\">\n @if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row, footer: true }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, -1) }}\n }\n</ng-template>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(row, column.key)) {\n <input\n #editInput\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(row, column.key)\"\n (keydown)=\"onEditKeydown($event, row, column.key)\"\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div [class]=\"'lc-table-pagination lc-table-pagination--' + paginationSize()\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}–{{ paginationEnd }} {{ rangeOfLabel() }} {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"paginationSize()\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"rowsPerPageAriaLabel()\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <div class=\"lc-table-pagination__pager\">\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n [attr.aria-label]=\"previousPageAriaLabel()\"\n >‹</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n [attr.aria-label]=\"nextPageAriaLabel()\"\n >›</button>\n </div>\n </div>\n </div>\n}\n",
|
|
1006
|
+
template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n @if (caption()) {\n <!-- First child of the table, so it names the table (and the treegrid). -->\n <caption class=\"lc-table__caption\" [class.lc-table__caption--hidden]=\"!showCaption()\">{{ caption() }}</caption>\n }\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"filterPlaceholderLabel() + ' ' + column.label\"\n [ariaLabel]=\"filterAriaLabel() + ' ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <!-- The label's ::before covers the cell: a 44 px hit area (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (change)=\"toggleSelectAll()\"\n [attr.aria-label]=\"selectAllAriaLabel()\"\n />\n </label>\n </th>\n }\n @for (column of columns(); track column.key) {\n <!-- A sortable header is a keyboard stop too: Enter/Space sort like a click. -->\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [attr.tabindex]=\"column.sortable ? 0 : null\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\"\n (keydown)=\"column.sortable ? onHeaderKeydown($event, column.key) : null\">\n @if (column.align === 'end') {\n <!-- 3.17: the arrow is placed before the label (CSS), so the label stays\n flush with the figures; in the DOM it still follows the label. No\n whitespace between the label and the arrow. -->\n <span class=\"lc-table__sort-label\">{{ column.label }}@if (column.sortable && getSortState(column.key)) {<span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>}</span>\n } @else {\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>\n }\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.key) {\n <!-- In tree mode the rows form the treegrid's keyboard model: a roving\n tab stop plus Arrow/Home/End/Enter/Space handling (see the\n component). Flat mode keeps plain table rows. -->\n <tr\n #dataRow\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.row)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.tabindex]=\"rowTabindex(dr)\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n [attr.aria-selected]=\"treeMode() && selectable() ? isRowSelected(dr.row) : null\"\n (click)=\"onRowClick(dr.row, $event)\"\n (focus)=\"onRowFocus(dr)\"\n (keydown)=\"onRowKeydown($event, dr)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <!-- A click in the cell toggles the box, never the row (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.row)\"\n (change)=\"toggleRowSelect(dr.row)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"selectRowAriaLabel() + ' ' + (dr.absIndex + 1)\"\n />\n </label>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.row, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? collapseRowAriaLabel() : expandRowAriaLabel()) + ' ' + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n [size]=\"action.size ?? 'xs'\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"actionAriaLabel(action, dr.row, dr.absIndex)\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n @if (footerRow(); as footer) {\n <!-- 3.36: one footer row below every data row; never sorted, filtered,\n paged, selected or counted. Its first cell is the row header. -->\n <tfoot class=\"lc-table__footer\">\n <tr [attr.role]=\"treeMode() ? 'row' : null\">\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\"></td>\n }\n @for (column of columns(); track column.key; let first = $first) {\n @if (first) {\n <th\n scope=\"row\"\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'rowheader' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </th>\n } @else {\n <td\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </td>\n }\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n ></td>\n }\n </tr>\n </tfoot>\n }\n </table>\n</div>\n\n<!-- 3.36: a footer cell. In the tree column the label lines up with the level-0\n labels (an empty disclosure slot before it). Templates get `footer: true`. -->\n<ng-template #footerCell let-row=\"row\" let-column=\"column\">\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\"></span>\n <span class=\"lc-table__tree-content\">\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n </span>\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n }\n</ng-template>\n\n<ng-template #footerContent let-row=\"row\" let-column=\"column\">\n @if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row, footer: true }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, -1) }}\n }\n</ng-template>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(row, column.key)) {\n <input\n #editInput\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(row, column.key)\"\n (keydown)=\"onEditKeydown($event, row, column.key)\"\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div [class]=\"'lc-table-pagination lc-table-pagination--' + paginationSize()\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}–{{ paginationEnd }} {{ rangeOfLabel() }} {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"paginationSize()\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"rowsPerPageAriaLabel()\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <div class=\"lc-table-pagination__pager\">\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n [attr.aria-label]=\"previousPageAriaLabel()\"\n >‹</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n [attr.aria-label]=\"nextPageAriaLabel()\"\n >›</button>\n </div>\n </div>\n </div>\n}\n",
|
|
1007
1007
|
styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-surface);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface-2);border-bottom:2px solid var(--color-border-strong)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-table thead tr th.sortable:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4))}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-surface-2)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr,.lc-table--clickable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover,.lc-table--clickable tbody tr:hover{background-color:var(--color-surface-hover)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3))}.lc-table--sm thead tr th{font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5)}.lc-table--lg thead tr th{font-size:var(--typography-font-size-base)}:where(.lc-table tbody tr td){font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}:where(.lc-table--sm tbody tr td){font-size:var(--typography-font-size-xs)}:where(.lc-table--lg tbody tr td){font-size:var(--typography-font-size-base)}.lc-table thead tr th.lc-table__cell--end,.lc-table tbody tr td.lc-table__cell--end{text-align:end;font-variant-numeric:tabular-nums}.lc-table thead tr th.sortable.lc-table__cell--end{padding-inline-start:var(--spacing-8);padding-inline-end:var(--lc-density-padding-md, var(--spacing-4))}.lc-table thead tr th.sortable.lc-table__cell--end .sort-indicator{right:auto;inset-inline-end:calc(100% + var(--spacing-2))}.lc-table--sm thead tr th.sortable.lc-table__cell--end{padding-inline-end:var(--lc-density-padding-sm, var(--spacing-3))}.lc-table--lg thead tr th.sortable.lc-table__cell--end{padding-inline-end:var(--spacing-5)}.lc-table__sort-label{position:relative;display:inline-block}.lc-table__cell--end .lc-table__edit-input{text-align:end;font-variant-numeric:tabular-nums}.lc-table__caption{caption-side:top;padding:0 0 var(--spacing-3);text-align:start;font-family:var(--typography-font-family);font-size:var(--typography-font-size-base);font-weight:var(--typography-font-weight-semibold);line-height:var(--typography-line-height-normal);color:var(--color-text-primary)}.lc-table__caption--hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media(forced-colors:active){.lc-table tbody tr:focus-visible{outline:2px solid Highlight}}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-surface)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;display:block}.lc-table__filter-input .input-field{font-size:var(--typography-font-size-xs)}.lc-table__select-cell{position:relative;width:var(--size-min-touch-height, 2.75rem);text-align:center!important;padding:var(--spacing-2) calc((var(--size-min-touch-height, 2.75rem) - 1rem) / 2)!important}.lc-table__select-hit{cursor:pointer}.lc-table__select-hit:before{content:\"\";position:absolute;inset:0}.lc-table__checkbox{position:relative;width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary);display:block;margin:2.5px auto;margin:max(2.5px,(1lh - 16px) / 2) auto}.lc-table__checkbox:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-table__row--selected{background-color:var(--color-surface-selected)!important}.lc-table__actions-cell{white-space:nowrap}.lc-table thead tr th.lc-table__actions-cell--start,.lc-table tbody tr td.lc-table__actions-cell--start{text-align:left}.lc-table thead tr th.lc-table__actions-cell--center,.lc-table tbody tr td.lc-table__actions-cell--center{text-align:center}.lc-table thead tr th.lc-table__actions-cell--end,.lc-table tbody tr td.lc-table__actions-cell--end{text-align:right}.lc-table__actions{display:flex;align-items:center;gap:var(--spacing-2);justify-content:flex-start}.lc-table__actions-cell--center .lc-table__actions{justify-content:center}.lc-table__actions-cell--end .lc-table__actions{justify-content:flex-end}.lc-table__tree-cell{display:flex;align-items:center;min-width:0}.lc-table__tree-indent{flex:0 0 auto;align-self:stretch;position:relative}.lc-table__tree-indent:before{content:\"\";position:absolute;left:50%;top:0;bottom:0;width:1px;background-color:var(--color-border)}.lc-table__tree-chevron{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center}.lc-table__chevron-btn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--color-text-secondary);cursor:pointer;border-radius:var(--border-radius-sm);transition:transform .2s ease,background-color .15s ease,color .15s ease}.lc-table__chevron-btn:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table__chevron-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:1px}.lc-table__chevron-btn--expanded{transform:rotate(90deg)}.lc-table__tree-content{flex:1 1 auto;min-width:0}.lc-table__row--group .lc-table__tree-content{font-weight:var(--typography-font-weight-semibold)}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-surface-2);color:var(--color-text-primary);outline:none}.lc-table-pagination{--_lc-table-pagination-btn: var(--size-interactive-md-height);display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--spacing-2) var(--spacing-4);padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination--sm{--_lc-table-pagination-btn: var(--size-interactive-sm-height)}.lc-table-pagination--lg{--_lc-table-pagination-btn: var(--size-interactive-lg-height)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--spacing-2);margin-inline-start:auto}.lc-table-pagination__pager{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{--lc-select-clear-display: none;display:block;min-width:110px}.lc-table-pagination__btn{position:relative;appearance:none;border:1px solid var(--color-field-border);background-color:var(--color-surface-2);color:var(--color-text-primary);width:var(--_lc-table-pagination-btn);height:var(--_lc-table-pagination-btn);display:flex;align-items:center;justify-content:center;padding:0;border-radius:var(--border-radius-md);font-size:var(--typography-font-size-xl);line-height:1;cursor:pointer;transition:background-color .15s ease,border-color .15s ease}.lc-table-pagination__btn:before{content:\"\";position:absolute;inset:min(0px,(100% - var(--size-min-touch-height, 2.75rem)) / 2)}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-table-pagination__btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}@media(forced-colors:active){.lc-table__checkbox:focus-visible{outline-color:Highlight}}.lc-table tfoot tr{border-top:1px solid var(--color-field-border);border-bottom:3px double var(--color-field-border)}.lc-table tfoot tr th,.lc-table tfoot tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:start;font-weight:var(--typography-font-weight-semibold);font-variant-numeric:tabular-nums}.lc-table tfoot tr th.lc-table__cell--end,.lc-table tfoot tr td.lc-table__cell--end{text-align:end}.lc-table--sm tfoot tr th,.lc-table--sm tfoot tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3))}.lc-table--lg tfoot tr th,.lc-table--lg tfoot tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5)}.lc-table--bordered tfoot tr th,.lc-table--bordered tfoot tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered tfoot tr th:last-child,.lc-table--bordered tfoot tr td:last-child{border-right:none}:where(.lc-table tfoot tr th,.lc-table tfoot tr td){font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}:where(.lc-table--sm tfoot tr th,.lc-table--sm tfoot tr td){font-size:var(--typography-font-size-xs)}:where(.lc-table--lg tfoot tr th,.lc-table--lg tfoot tr td){font-size:var(--typography-font-size-base)}\n"],
|
|
1008
1008
|
dependencies: [
|
|
1009
1009
|
{
|
|
@@ -1179,7 +1179,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
1179
1179
|
],
|
|
1180
1180
|
viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_RIGHT])],
|
|
1181
1181
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1182
|
-
template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n @if (caption()) {\n <!-- First child of the table, so it names the table (and the treegrid). -->\n <caption class=\"lc-table__caption\" [class.lc-table__caption--hidden]=\"!showCaption()\">{{ caption() }}</caption>\n }\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"filterPlaceholderLabel() + ' ' + column.label\"\n [ariaLabel]=\"filterAriaLabel() + ' ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <!-- The label's ::before covers the cell: a 44 px hit area (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (change)=\"toggleSelectAll()\"\n [attr.aria-label]=\"selectAllAriaLabel()\"\n />\n </label>\n </th>\n }\n @for (column of columns(); track column.key) {\n <!-- A sortable header is a keyboard stop too: Enter/Space sort like a click. -->\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [attr.tabindex]=\"column.sortable ? 0 : null\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\"\n (keydown)=\"column.sortable ? onHeaderKeydown($event, column.key) : null\">\n @if (column.align === 'end') {\n <!-- 3.17: the arrow is placed before the label (CSS), so the label stays\n flush with the figures; in the DOM it still follows the label. No\n whitespace between the label and the arrow. -->\n <span class=\"lc-table__sort-label\">{{ column.label }}@if (column.sortable && getSortState(column.key)) {<span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>}</span>\n } @else {\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>\n }\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.key) {\n <!-- In tree mode the rows form the treegrid's keyboard model: a roving\n tab stop plus Arrow/Home/End/Enter/Space handling (see the\n component). Flat mode keeps plain table rows. -->\n <tr\n #dataRow\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.row)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.tabindex]=\"rowTabindex(dr)\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n [attr.aria-selected]=\"treeMode() && selectable() ? isRowSelected(dr.row) : null\"\n (click)=\"onRowClick(dr.row, $event)\"\n (focus)=\"onRowFocus(dr)\"\n (keydown)=\"onRowKeydown($event, dr)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <!-- A click in the cell toggles the box, never the row (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.row)\"\n (change)=\"toggleRowSelect(dr.row)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"selectRowAriaLabel() + ' ' + (dr.absIndex + 1)\"\n />\n </label>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.row, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? collapseRowAriaLabel() : expandRowAriaLabel()) + ' ' + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"actionAriaLabel(action, dr.row, dr.absIndex)\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n @if (footerRow(); as footer) {\n <!-- 3.36: one footer row below every data row; never sorted, filtered,\n paged, selected or counted. Its first cell is the row header. -->\n <tfoot class=\"lc-table__footer\">\n <tr [attr.role]=\"treeMode() ? 'row' : null\">\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\"></td>\n }\n @for (column of columns(); track column.key; let first = $first) {\n @if (first) {\n <th\n scope=\"row\"\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'rowheader' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </th>\n } @else {\n <td\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </td>\n }\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n ></td>\n }\n </tr>\n </tfoot>\n }\n </table>\n</div>\n\n<!-- 3.36: a footer cell. In the tree column the label lines up with the level-0\n labels (an empty disclosure slot before it). Templates get `footer: true`. -->\n<ng-template #footerCell let-row=\"row\" let-column=\"column\">\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\"></span>\n <span class=\"lc-table__tree-content\">\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n </span>\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n }\n</ng-template>\n\n<ng-template #footerContent let-row=\"row\" let-column=\"column\">\n @if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row, footer: true }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, -1) }}\n }\n</ng-template>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(row, column.key)) {\n <input\n #editInput\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(row, column.key)\"\n (keydown)=\"onEditKeydown($event, row, column.key)\"\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div [class]=\"'lc-table-pagination lc-table-pagination--' + paginationSize()\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}–{{ paginationEnd }} {{ rangeOfLabel() }} {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"paginationSize()\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"rowsPerPageAriaLabel()\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <div class=\"lc-table-pagination__pager\">\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n [attr.aria-label]=\"previousPageAriaLabel()\"\n >‹</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n [attr.aria-label]=\"nextPageAriaLabel()\"\n >›</button>\n </div>\n </div>\n </div>\n}\n",
|
|
1182
|
+
template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n @if (caption()) {\n <!-- First child of the table, so it names the table (and the treegrid). -->\n <caption class=\"lc-table__caption\" [class.lc-table__caption--hidden]=\"!showCaption()\">{{ caption() }}</caption>\n }\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"filterPlaceholderLabel() + ' ' + column.label\"\n [ariaLabel]=\"filterAriaLabel() + ' ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <!-- The label's ::before covers the cell: a 44 px hit area (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (change)=\"toggleSelectAll()\"\n [attr.aria-label]=\"selectAllAriaLabel()\"\n />\n </label>\n </th>\n }\n @for (column of columns(); track column.key) {\n <!-- A sortable header is a keyboard stop too: Enter/Space sort like a click. -->\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [attr.tabindex]=\"column.sortable ? 0 : null\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\"\n (keydown)=\"column.sortable ? onHeaderKeydown($event, column.key) : null\">\n @if (column.align === 'end') {\n <!-- 3.17: the arrow is placed before the label (CSS), so the label stays\n flush with the figures; in the DOM it still follows the label. No\n whitespace between the label and the arrow. -->\n <span class=\"lc-table__sort-label\">{{ column.label }}@if (column.sortable && getSortState(column.key)) {<span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>}</span>\n } @else {\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>\n }\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.key) {\n <!-- In tree mode the rows form the treegrid's keyboard model: a roving\n tab stop plus Arrow/Home/End/Enter/Space handling (see the\n component). Flat mode keeps plain table rows. -->\n <tr\n #dataRow\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.row)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.tabindex]=\"rowTabindex(dr)\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n [attr.aria-selected]=\"treeMode() && selectable() ? isRowSelected(dr.row) : null\"\n (click)=\"onRowClick(dr.row, $event)\"\n (focus)=\"onRowFocus(dr)\"\n (keydown)=\"onRowKeydown($event, dr)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <!-- A click in the cell toggles the box, never the row (request 043). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the click; the checkbox inside is the keyboard control -->\n <label class=\"lc-table__select-hit\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.row)\"\n (change)=\"toggleRowSelect(dr.row)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"selectRowAriaLabel() + ' ' + (dr.absIndex + 1)\"\n />\n </label>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.row, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? collapseRowAriaLabel() : expandRowAriaLabel()) + ' ' + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n [size]=\"action.size ?? 'xs'\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"actionAriaLabel(action, dr.row, dr.absIndex)\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n @if (footerRow(); as footer) {\n <!-- 3.36: one footer row below every data row; never sorted, filtered,\n paged, selected or counted. Its first cell is the row header. -->\n <tfoot class=\"lc-table__footer\">\n <tr [attr.role]=\"treeMode() ? 'row' : null\">\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\"></td>\n }\n @for (column of columns(); track column.key; let first = $first) {\n @if (first) {\n <th\n scope=\"row\"\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'rowheader' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </th>\n } @else {\n <td\n [class]=\"getCellClasses(footer, column, -1)\"\n [ngStyle]=\"getCellStyles(footer, column, -1)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n >\n <ng-container *ngTemplateOutlet=\"footerCell; context: { row: footer, column: column }\"></ng-container>\n </td>\n }\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n ></td>\n }\n </tr>\n </tfoot>\n }\n </table>\n</div>\n\n<!-- 3.36: a footer cell. In the tree column the label lines up with the level-0\n labels (an empty disclosure slot before it). Templates get `footer: true`. -->\n<ng-template #footerCell let-row=\"row\" let-column=\"column\">\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\"></span>\n <span class=\"lc-table__tree-content\">\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n </span>\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"footerContent; context: { row: row, column: column }\"></ng-container>\n }\n</ng-template>\n\n<ng-template #footerContent let-row=\"row\" let-column=\"column\">\n @if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row, footer: true }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, -1) }}\n }\n</ng-template>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(row, column.key)) {\n <input\n #editInput\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(row, column.key)\"\n (keydown)=\"onEditKeydown($event, row, column.key)\"\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div [class]=\"'lc-table-pagination lc-table-pagination--' + paginationSize()\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}–{{ paginationEnd }} {{ rangeOfLabel() }} {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"paginationSize()\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"rowsPerPageAriaLabel()\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <div class=\"lc-table-pagination__pager\">\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n [attr.aria-label]=\"previousPageAriaLabel()\"\n >‹</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n [attr.aria-label]=\"nextPageAriaLabel()\"\n >›</button>\n </div>\n </div>\n </div>\n}\n",
|
|
1183
1183
|
styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-surface);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface-2);border-bottom:2px solid var(--color-border-strong)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-table thead tr th.sortable:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4))}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-surface-2)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr,.lc-table--clickable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover,.lc-table--clickable tbody tr:hover{background-color:var(--color-surface-hover)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3))}.lc-table--sm thead tr th{font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5)}.lc-table--lg thead tr th{font-size:var(--typography-font-size-base)}:where(.lc-table tbody tr td){font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}:where(.lc-table--sm tbody tr td){font-size:var(--typography-font-size-xs)}:where(.lc-table--lg tbody tr td){font-size:var(--typography-font-size-base)}.lc-table thead tr th.lc-table__cell--end,.lc-table tbody tr td.lc-table__cell--end{text-align:end;font-variant-numeric:tabular-nums}.lc-table thead tr th.sortable.lc-table__cell--end{padding-inline-start:var(--spacing-8);padding-inline-end:var(--lc-density-padding-md, var(--spacing-4))}.lc-table thead tr th.sortable.lc-table__cell--end .sort-indicator{right:auto;inset-inline-end:calc(100% + var(--spacing-2))}.lc-table--sm thead tr th.sortable.lc-table__cell--end{padding-inline-end:var(--lc-density-padding-sm, var(--spacing-3))}.lc-table--lg thead tr th.sortable.lc-table__cell--end{padding-inline-end:var(--spacing-5)}.lc-table__sort-label{position:relative;display:inline-block}.lc-table__cell--end .lc-table__edit-input{text-align:end;font-variant-numeric:tabular-nums}.lc-table__caption{caption-side:top;padding:0 0 var(--spacing-3);text-align:start;font-family:var(--typography-font-family);font-size:var(--typography-font-size-base);font-weight:var(--typography-font-weight-semibold);line-height:var(--typography-line-height-normal);color:var(--color-text-primary)}.lc-table__caption--hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media(forced-colors:active){.lc-table tbody tr:focus-visible{outline:2px solid Highlight}}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-surface)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;display:block}.lc-table__filter-input .input-field{font-size:var(--typography-font-size-xs)}.lc-table__select-cell{position:relative;width:var(--size-min-touch-height, 2.75rem);text-align:center!important;padding:var(--spacing-2) calc((var(--size-min-touch-height, 2.75rem) - 1rem) / 2)!important}.lc-table__select-hit{cursor:pointer}.lc-table__select-hit:before{content:\"\";position:absolute;inset:0}.lc-table__checkbox{position:relative;width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary);display:block;margin:2.5px auto;margin:max(2.5px,(1lh - 16px) / 2) auto}.lc-table__checkbox:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-table__row--selected{background-color:var(--color-surface-selected)!important}.lc-table__actions-cell{white-space:nowrap}.lc-table thead tr th.lc-table__actions-cell--start,.lc-table tbody tr td.lc-table__actions-cell--start{text-align:left}.lc-table thead tr th.lc-table__actions-cell--center,.lc-table tbody tr td.lc-table__actions-cell--center{text-align:center}.lc-table thead tr th.lc-table__actions-cell--end,.lc-table tbody tr td.lc-table__actions-cell--end{text-align:right}.lc-table__actions{display:flex;align-items:center;gap:var(--spacing-2);justify-content:flex-start}.lc-table__actions-cell--center .lc-table__actions{justify-content:center}.lc-table__actions-cell--end .lc-table__actions{justify-content:flex-end}.lc-table__tree-cell{display:flex;align-items:center;min-width:0}.lc-table__tree-indent{flex:0 0 auto;align-self:stretch;position:relative}.lc-table__tree-indent:before{content:\"\";position:absolute;left:50%;top:0;bottom:0;width:1px;background-color:var(--color-border)}.lc-table__tree-chevron{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center}.lc-table__chevron-btn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--color-text-secondary);cursor:pointer;border-radius:var(--border-radius-sm);transition:transform .2s ease,background-color .15s ease,color .15s ease}.lc-table__chevron-btn:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-table__chevron-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:1px}.lc-table__chevron-btn--expanded{transform:rotate(90deg)}.lc-table__tree-content{flex:1 1 auto;min-width:0}.lc-table__row--group .lc-table__tree-content{font-weight:var(--typography-font-weight-semibold)}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-surface-2);color:var(--color-text-primary);outline:none}.lc-table-pagination{--_lc-table-pagination-btn: var(--size-interactive-md-height);display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--spacing-2) var(--spacing-4);padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination--sm{--_lc-table-pagination-btn: var(--size-interactive-sm-height)}.lc-table-pagination--lg{--_lc-table-pagination-btn: var(--size-interactive-lg-height)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--spacing-2);margin-inline-start:auto}.lc-table-pagination__pager{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{--lc-select-clear-display: none;display:block;min-width:110px}.lc-table-pagination__btn{position:relative;appearance:none;border:1px solid var(--color-field-border);background-color:var(--color-surface-2);color:var(--color-text-primary);width:var(--_lc-table-pagination-btn);height:var(--_lc-table-pagination-btn);display:flex;align-items:center;justify-content:center;padding:0;border-radius:var(--border-radius-md);font-size:var(--typography-font-size-xl);line-height:1;cursor:pointer;transition:background-color .15s ease,border-color .15s ease}.lc-table-pagination__btn:before{content:\"\";position:absolute;inset:min(0px,(100% - var(--size-min-touch-height, 2.75rem)) / 2)}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-table-pagination__btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}@media(forced-colors:active){.lc-table__checkbox:focus-visible{outline-color:Highlight}}.lc-table tfoot tr{border-top:1px solid var(--color-field-border);border-bottom:3px double var(--color-field-border)}.lc-table tfoot tr th,.lc-table tfoot tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:start;font-weight:var(--typography-font-weight-semibold);font-variant-numeric:tabular-nums}.lc-table tfoot tr th.lc-table__cell--end,.lc-table tfoot tr td.lc-table__cell--end{text-align:end}.lc-table--sm tfoot tr th,.lc-table--sm tfoot tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3))}.lc-table--lg tfoot tr th,.lc-table--lg tfoot tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5)}.lc-table--bordered tfoot tr th,.lc-table--bordered tfoot tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered tfoot tr th:last-child,.lc-table--bordered tfoot tr td:last-child{border-right:none}:where(.lc-table tfoot tr th,.lc-table tfoot tr td){font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}:where(.lc-table--sm tfoot tr th,.lc-table--sm tfoot tr td){font-size:var(--typography-font-size-xs)}:where(.lc-table--lg tfoot tr th,.lc-table--lg tfoot tr td){font-size:var(--typography-font-size-base)}\n"]
|
|
1184
1184
|
}]
|
|
1185
1185
|
}],
|