@akcelik/strct 5.30.0 → 5.32.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/akcelik-strct.mjs +19 -1582
- package/fesm2022/akcelik-strct.mjs.map +1 -1
- package/package.json +1 -1
- package/types/akcelik-strct.d.ts +23 -13
|
@@ -15243,6 +15243,21 @@ const DG_LABELS = {
|
|
|
15243
15243
|
pageOf: (page, pages) => `Page ${page} of ${pages}`,
|
|
15244
15244
|
rowsMatch: (shown, total) => `${shown} of ${total} rows match`,
|
|
15245
15245
|
};
|
|
15246
|
+
|
|
15247
|
+
/*
|
|
15248
|
+
* ── The grid's features, as objects (5.30.0) ──────────────────────────────
|
|
15249
|
+
*
|
|
15250
|
+
* The component grew to 54 inputs, which is more than a template can read.
|
|
15251
|
+
* Each cluster of them becomes one object; the flat inputs keep working
|
|
15252
|
+
* through 5.x and dev mode says which object each has moved into, so a
|
|
15253
|
+
* consumer upgrades a screen at a time. They are removed in 6.0.
|
|
15254
|
+
*
|
|
15255
|
+
* What stays flat on purpose: the two-way state (`selectedIds`, `filters`,
|
|
15256
|
+
* `columnState`, `collapsedGroups`, `quickFilter`, `activeRowId`,
|
|
15257
|
+
* `selectedId`), because `[(…)]` cannot bind through a property of an
|
|
15258
|
+
* object; and the grid's core (`columns`, `rows`, `rowId`, `labels`) with the
|
|
15259
|
+
* handful of look flags.
|
|
15260
|
+
*/
|
|
15246
15261
|
/** Flat inputs already named in a deprecation warning, per app run. */
|
|
15247
15262
|
const warnedFlatInputs = new Set();
|
|
15248
15263
|
const pendingFlatInputWarnings = new Set();
|
|
@@ -17803,796 +17818,7 @@ class StrctDatagrid {
|
|
|
17803
17818
|
return String(a ?? '').localeCompare(String(b ?? ''), undefined, { numeric: true });
|
|
17804
17819
|
}
|
|
17805
17820
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDatagrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
17806
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDatagrid, isStandalone: true, selector: "strct-datagrid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, pageSizeFlat: { classPropertyName: "pageSizeFlat", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectableFlat: { classPropertyName: "selectableFlat", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPaneFlat: { classPropertyName: "detailPaneFlat", publicName: "detailPane", isSignal: true, isRequired: false, transformFunction: null }, paneListWidthFlat: { classPropertyName: "paneListWidthFlat", publicName: "paneListWidth", isSignal: true, isRequired: false, transformFunction: null }, paneTakeoverWidthFlat: { classPropertyName: "paneTakeoverWidthFlat", publicName: "paneTakeoverWidth", isSignal: true, isRequired: false, transformFunction: null }, activeRowId: { classPropertyName: "activeRowId", publicName: "activeRowId", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, singleLine: { classPropertyName: "singleLine", publicName: "singleLine", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, columnChooser: { classPropertyName: "columnChooser", publicName: "columnChooser", isSignal: true, isRequired: false, transformFunction: null }, syncFlat: { classPropertyName: "syncFlat", publicName: "sync", isSignal: true, isRequired: false, transformFunction: null }, footerActionsDisabled: { classPropertyName: "footerActionsDisabled", publicName: "footerActionsDisabled", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null }, selectionModeFlat: { classPropertyName: "selectionModeFlat", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, rowSelectableFlat: { classPropertyName: "rowSelectableFlat", publicName: "rowSelectable", isSignal: true, isRequired: false, transformFunction: null }, flush: { classPropertyName: "flush", publicName: "flush", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, hasMoreFlat: { classPropertyName: "hasMoreFlat", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, loadingMoreFlat: { classPropertyName: "loadingMoreFlat", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, moreTotalFlat: { classPropertyName: "moreTotalFlat", publicName: "moreTotal", isSignal: true, isRequired: false, transformFunction: null }, groupSelectFlat: { classPropertyName: "groupSelectFlat", publicName: "groupSelect", isSignal: true, isRequired: false, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, initialSelectionFlat: { classPropertyName: "initialSelectionFlat", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, viewportHeightFlat: { classPropertyName: "viewportHeightFlat", publicName: "viewportHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeightFlat: { classPropertyName: "maxHeightFlat", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, editHint: { classPropertyName: "editHint", publicName: "editHint", isSignal: true, isRequired: false, transformFunction: null }, rowHeightFlat: { classPropertyName: "rowHeightFlat", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, lazyFlat: { classPropertyName: "lazyFlat", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, totalFlat: { classPropertyName: "totalFlat", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, stateKeyFlat: { classPropertyName: "stateKeyFlat", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null }, columnState: { classPropertyName: "columnState", publicName: "columnState", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, groupByFlat: { classPropertyName: "groupByFlat", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, groupsFlat: { classPropertyName: "groupsFlat", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, showEmptyGroupsFlat: { classPropertyName: "showEmptyGroupsFlat", publicName: "showEmptyGroups", isSignal: true, isRequired: false, transformFunction: null }, collapsedGroups: { classPropertyName: "collapsedGroups", publicName: "collapsedGroups", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, quickFilter: { classPropertyName: "quickFilter", publicName: "quickFilter", isSignal: true, isRequired: false, transformFunction: null }, quickFilterFieldsFlat: { classPropertyName: "quickFilterFieldsFlat", publicName: "quickFilterFields", isSignal: true, isRequired: false, transformFunction: null }, quickFilterableFlat: { classPropertyName: "quickFilterableFlat", publicName: "quickFilterable", isSignal: true, isRequired: false, transformFunction: null }, quickFilterAlignFlat: { classPropertyName: "quickFilterAlignFlat", publicName: "quickFilterAlign", isSignal: true, isRequired: false, transformFunction: null }, childrenKeyFlat: { classPropertyName: "childrenKeyFlat", publicName: "childrenKey", isSignal: true, isRequired: false, transformFunction: null }, interactionMode: { classPropertyName: "interactionMode", publicName: "interactionMode", isSignal: true, isRequired: false, transformFunction: null }, selectionColumnFlat: { classPropertyName: "selectionColumnFlat", publicName: "selectionColumn", isSignal: true, isRequired: false, transformFunction: null }, selectionCfg: { classPropertyName: "selectionCfg", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, paneFlat: { classPropertyName: "paneFlat", publicName: "pane", isSignal: true, isRequired: false, transformFunction: null }, pagingFlat: { classPropertyName: "pagingFlat", publicName: "paging", isSignal: true, isRequired: false, transformFunction: null }, virtualFlat: { classPropertyName: "virtualFlat", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, groupingCfg: { classPropertyName: "groupingCfg", publicName: "grouping", isSignal: true, isRequired: false, transformFunction: null }, filteringCfg: { classPropertyName: "filteringCfg", publicName: "filtering", isSignal: true, isRequired: false, transformFunction: null }, stateCfg: { classPropertyName: "stateCfg", publicName: "state", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeRowId: "activeRowIdChange", selectedId: "selectedIdChange", loadMore: "loadMore", selectedIds: "selectedIdsChange", columnState: "columnStateChange", collapsedGroups: "collapsedGroupsChange", filters: "filtersChange", quickFilter: "quickFilterChange", rowActivate: "rowActivate", selectionChange: "selectionChange", syncChange: "syncChange", rowAction: "rowAction", lazyLoad: "lazyLoad", cellEdit: "cellEdit" }, host: { listeners: { "document:click": "onDocClickOverlays($event)", "document:keydown.escape": "onEscapeOverlays($event)" }, properties: { "attr.aria-busy": "loading() || loadingMore() ? \"true\" : null", "class.strct-dg-host--compact": "compact()", "class.strct-dg-host--singleline": "singleLine()", "class.strct-dg-host--virtual": "virtual()", "class.strct-dg-host--bounded": "!virtual() && maxHeight() !== null", "class.strct-dg-host--sticky": "stickyActive()", "class.strct-dg-host--flush": "flush()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "groupHeaderDef", first: true, predicate: StrctGroupHeaderDef, descendants: true, isSignal: true }, { propertyName: "paneTitleDef", first: true, predicate: StrctDetailPaneTitle, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "actionBarCaptionDef", first: true, predicate: StrctDatagridActionBarCaption, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
|
|
17807
|
-
<!-- One polite region for everything the grid does to itself: sorting,
|
|
17808
|
-
paging and filtering all change the rows without saying so. -->
|
|
17809
|
-
<span class="strct-dg__announcer" role="status" aria-live="polite">{{ announcement() }}</span>
|
|
17810
|
-
@if (actionBarDef() || quickFilterable() || actionBarCaptionDef()) {
|
|
17811
|
-
<div class="strct-dg__toolbar">
|
|
17812
|
-
@if (quickFilterable()) {
|
|
17813
|
-
<strct-searchbox
|
|
17814
|
-
class="strct-dg__quickfilter"
|
|
17815
|
-
[class.strct-dg__quickfilter--end]="quickFilterAlign() === 'end'"
|
|
17816
|
-
[placeholder]="L().quickFilter"
|
|
17817
|
-
[ariaLabel]="L().quickFilter"
|
|
17818
|
-
[value]="quickFilter()"
|
|
17819
|
-
(valueChange)="quickFilter.set($event)"
|
|
17820
|
-
/>
|
|
17821
|
-
@if (filterNote(); as note) {
|
|
17822
|
-
<span
|
|
17823
|
-
class="strct-dg__filternote"
|
|
17824
|
-
[class.strct-dg__filternote--end]="quickFilterAlign() === 'end'"
|
|
17825
|
-
>{{ note }}</span
|
|
17826
|
-
>
|
|
17827
|
-
}
|
|
17828
|
-
}
|
|
17829
|
-
<span class="strct-dg__actioncaption">
|
|
17830
|
-
<ng-content select="[strctDatagridActionBarCaption]" />
|
|
17831
|
-
</span>
|
|
17832
|
-
<ng-content select="[strctDatagridActionBar]" />
|
|
17833
|
-
</div>
|
|
17834
|
-
}
|
|
17835
|
-
|
|
17836
|
-
@if (hasEditableColumn()) {
|
|
17837
|
-
<!-- What the editable cells point at with aria-describedby: a keyboard
|
|
17838
|
-
user is told the cell can be edited, and how. -->
|
|
17839
|
-
<!-- In flow, not absolutely positioned: an out-of-flow box whose
|
|
17840
|
-
containing block is the page extends the document's scrollable area
|
|
17841
|
-
from wherever the grid happens to sit. 1x1 and clipped is enough. -->
|
|
17842
|
-
<span
|
|
17843
|
-
class="strct-sr-only"
|
|
17844
|
-
style="display: inline-block; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap"
|
|
17845
|
-
[id]="editHintId"
|
|
17846
|
-
>{{ L().editCellInstructions }}</span
|
|
17847
|
-
>
|
|
17848
|
-
}
|
|
17849
|
-
|
|
17850
|
-
@if (bulkHint(); as hint) {
|
|
17851
|
-
<!-- Selecting the page is not selecting the set. Say which one happened,
|
|
17852
|
-
and offer the other. -->
|
|
17853
|
-
<div class="strct-dg__bulk" role="status">
|
|
17854
|
-
<span>{{ hint.text }}</span>
|
|
17855
|
-
<button strct-button variant="flat" size="sm" (click)="hint.run()">
|
|
17856
|
-
{{ hint.action }}
|
|
17857
|
-
</button>
|
|
17858
|
-
</div>
|
|
17859
|
-
}
|
|
17860
|
-
<div
|
|
17861
|
-
class="strct-dg__layout"
|
|
17862
|
-
[class.strct-dg__layout--paned]="paneOpen()"
|
|
17863
|
-
[class.strct-dg__layout--panetakeover]="paneOpen() && narrowPane()"
|
|
17864
|
-
[style.--strct-dg-pane-list-w]="paneListWidth()"
|
|
17865
|
-
>
|
|
17866
|
-
<div
|
|
17867
|
-
class="strct-dg__scroll"
|
|
17868
|
-
tabindex="0"
|
|
17869
|
-
role="region"
|
|
17870
|
-
[attr.aria-label]="L().rows"
|
|
17871
|
-
[style.max-height.px]="virtual() ? viewportHeight() : maxHeight()"
|
|
17872
|
-
(scroll)="virtual() && onScroll($event)"
|
|
17873
|
-
>
|
|
17874
|
-
<table
|
|
17875
|
-
class="strct-dg"
|
|
17876
|
-
[attr.role]="childrenKey() ? 'treegrid' : gridMode() ? 'grid' : null"
|
|
17877
|
-
[attr.aria-rowcount]="ariaRowCount()"
|
|
17878
|
-
[attr.aria-labelledby]="caption() ? captionId : null"
|
|
17879
|
-
>
|
|
17880
|
-
@if (caption()) {
|
|
17881
|
-
<caption class="strct-dg__caption" [id]="captionId">
|
|
17882
|
-
{{
|
|
17883
|
-
caption()
|
|
17884
|
-
}}
|
|
17885
|
-
</caption>
|
|
17886
|
-
}
|
|
17887
|
-
<thead>
|
|
17888
|
-
<tr>
|
|
17889
|
-
<!-- A utility column is still a column: axe reports every empty
|
|
17890
|
-
header, and a screen-reader user hears nothing where the
|
|
17891
|
-
detail, expand and select controls are. The name is hidden,
|
|
17892
|
-
not absent. -->
|
|
17893
|
-
@if (canDetail()) {
|
|
17894
|
-
<th
|
|
17895
|
-
class="strct-dg__expandcol"
|
|
17896
|
-
scope="col"
|
|
17897
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
17898
|
-
[style.insetInlineStart.px]="utilLeft('detail')"
|
|
17899
|
-
>
|
|
17900
|
-
<span class="strct-sr-only">{{ L().detailColumn }}</span>
|
|
17901
|
-
</th>
|
|
17902
|
-
}
|
|
17903
|
-
@if (canExpand()) {
|
|
17904
|
-
<th
|
|
17905
|
-
class="strct-dg__expandcol"
|
|
17906
|
-
scope="col"
|
|
17907
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
17908
|
-
[style.insetInlineStart.px]="utilLeft('expand')"
|
|
17909
|
-
>
|
|
17910
|
-
<span class="strct-sr-only">{{ L().expandColumn }}</span>
|
|
17911
|
-
</th>
|
|
17912
|
-
}
|
|
17913
|
-
@if (hasSelectionColumn()) {
|
|
17914
|
-
<th
|
|
17915
|
-
class="strct-dg__sel"
|
|
17916
|
-
scope="col"
|
|
17917
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
17918
|
-
[style.insetInlineStart.px]="utilLeft('sel')"
|
|
17919
|
-
>
|
|
17920
|
-
@if (mode() === 'multiple') {
|
|
17921
|
-
<strct-checkbox
|
|
17922
|
-
[ariaLabel]="L().selectAll"
|
|
17923
|
-
[checked]="allPageSelected()"
|
|
17924
|
-
[indeterminate]="somePageSelected()"
|
|
17925
|
-
(checkedChange)="toggleAll()"
|
|
17926
|
-
/>
|
|
17927
|
-
} @else {
|
|
17928
|
-
<span class="strct-sr-only">{{ L().selectColumn }}</span>
|
|
17929
|
-
}
|
|
17930
|
-
</th>
|
|
17931
|
-
}
|
|
17932
|
-
@for (col of visibleColumns(); track col.key) {
|
|
17933
|
-
<th
|
|
17934
|
-
scope="col"
|
|
17935
|
-
[style.text-align]="col.align ?? (col.numeric ? 'end' : 'start')"
|
|
17936
|
-
[style.width]="colWidth(col.key) ?? col.width ?? null"
|
|
17937
|
-
[class.strct-dg__th--sortable]="col.sortable"
|
|
17938
|
-
[class.strct-dg__th--drop]="col.key === dropKey()"
|
|
17939
|
-
[class.strct-dg__cell--sticky]="isSticky(col)"
|
|
17940
|
-
[class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
|
|
17941
|
-
[style.insetInlineStart.px]="stickyLeft(col.key)"
|
|
17942
|
-
[attr.data-col]="col.key"
|
|
17943
|
-
[attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
|
|
17944
|
-
[attr.draggable]="reorderable() ? true : null"
|
|
17945
|
-
(dragstart)="onColDragStart(col.key, $event)"
|
|
17946
|
-
(dragover)="onColDragOver(col.key, $event)"
|
|
17947
|
-
(drop)="onColDrop(col.key)"
|
|
17948
|
-
(dragend)="onColDragEnd()"
|
|
17949
|
-
>
|
|
17950
|
-
<span class="strct-dg__hd">
|
|
17951
|
-
<!-- A header that sorts is a button: a th with tabindex is
|
|
17952
|
-
read as "column header, focusable" and never says it
|
|
17953
|
-
can be activated. aria-sort stays on the th, which is
|
|
17954
|
-
what carries the column's sorted state. -->
|
|
17955
|
-
@if (col.sortable) {
|
|
17956
|
-
<!-- The button covers most of the header, so it carries
|
|
17957
|
-
the drag source too: a reorderable column has to be
|
|
17958
|
-
grabbable where the pointer actually lands. The
|
|
17959
|
-
event bubbles to the th's own handlers. -->
|
|
17960
|
-
<button
|
|
17961
|
-
type="button"
|
|
17962
|
-
class="strct-dg__sortbtn"
|
|
17963
|
-
[attr.draggable]="reorderable() ? true : null"
|
|
17964
|
-
(click)="sortBy(col.key)"
|
|
17965
|
-
>
|
|
17966
|
-
{{ col.label }}
|
|
17967
|
-
<strct-icon
|
|
17968
|
-
class="strct-dg__sorticon"
|
|
17969
|
-
[name]="sortIcon(col.key)"
|
|
17970
|
-
[size]="13"
|
|
17971
|
-
/>
|
|
17972
|
-
</button>
|
|
17973
|
-
} @else {
|
|
17974
|
-
{{ col.label }}
|
|
17975
|
-
}
|
|
17976
|
-
@if (col.filterable || col.filterOptions) {
|
|
17977
|
-
<button
|
|
17978
|
-
#fbtn
|
|
17979
|
-
type="button"
|
|
17980
|
-
class="strct-dg__filterbtn"
|
|
17981
|
-
[class.strct-dg__filterbtn--active]="hasFilter(col.key)"
|
|
17982
|
-
[attr.aria-expanded]="filterOpenKey() === col.key"
|
|
17983
|
-
[attr.aria-label]="L().filterColumn + ': ' + col.label"
|
|
17984
|
-
(click)="toggleFilterPanel(col.key, $event)"
|
|
17985
|
-
(keydown.enter)="$event.stopPropagation()"
|
|
17986
|
-
(keydown.space)="$event.stopPropagation()"
|
|
17987
|
-
>
|
|
17988
|
-
<strct-icon name="filter" [size]="12" />
|
|
17989
|
-
</button>
|
|
17990
|
-
@if (filterOpenKey() === col.key) {
|
|
17991
|
-
<div
|
|
17992
|
-
class="strct-dg__filterpanel"
|
|
17993
|
-
role="dialog"
|
|
17994
|
-
[attr.aria-label]="L().filterColumn + ': ' + col.label"
|
|
17995
|
-
[strctOverlay]="fbtn"
|
|
17996
|
-
strctOverlayPlacement="bottom-start"
|
|
17997
|
-
(click)="$event.stopPropagation()"
|
|
17998
|
-
(keydown.enter)="$event.stopPropagation()"
|
|
17999
|
-
(keydown.space)="$event.stopPropagation()"
|
|
18000
|
-
>
|
|
18001
|
-
@if (col.filterOptions; as opts) {
|
|
18002
|
-
@for (opt of opts; track $index) {
|
|
18003
|
-
<label class="strct-dg__filteropt">
|
|
18004
|
-
<input
|
|
18005
|
-
type="checkbox"
|
|
18006
|
-
[checked]="optionChecked(col.key, opt)"
|
|
18007
|
-
(change)="toggleFilterOption(col.key, opt)"
|
|
18008
|
-
/>
|
|
18009
|
-
<span>{{ opt }}</span>
|
|
18010
|
-
</label>
|
|
18011
|
-
}
|
|
18012
|
-
} @else {
|
|
18013
|
-
<input
|
|
18014
|
-
class="strct-dg__filterinput"
|
|
18015
|
-
type="text"
|
|
18016
|
-
[attr.placeholder]="L().filterPlaceholder"
|
|
18017
|
-
[attr.aria-label]="L().filterColumn + ': ' + col.label"
|
|
18018
|
-
[value]="textFilter(col.key)"
|
|
18019
|
-
(input)="setTextFilter(col.key, $any($event.target).value)"
|
|
18020
|
-
/>
|
|
18021
|
-
}
|
|
18022
|
-
<button
|
|
18023
|
-
type="button"
|
|
18024
|
-
class="strct-dg__filterclear"
|
|
18025
|
-
[disabled]="!hasFilter(col.key)"
|
|
18026
|
-
(click)="clearFilter(col.key)"
|
|
18027
|
-
>
|
|
18028
|
-
{{ L().clearFilter }}
|
|
18029
|
-
</button>
|
|
18030
|
-
</div>
|
|
18031
|
-
}
|
|
18032
|
-
}
|
|
18033
|
-
</span>
|
|
18034
|
-
@if (resizable() && col.resizable !== false) {
|
|
18035
|
-
<!-- A separator, not a bare div: a column could only be
|
|
18036
|
-
resized with a mouse, which is the one input a
|
|
18037
|
-
console cannot assume. -->
|
|
18038
|
-
<div
|
|
18039
|
-
class="strct-dg__resize"
|
|
18040
|
-
role="separator"
|
|
18041
|
-
aria-orientation="vertical"
|
|
18042
|
-
tabindex="0"
|
|
18043
|
-
[attr.aria-label]="L().resizeColumn(col.label)"
|
|
18044
|
-
[attr.aria-valuenow]="separatorValue(col.key)"
|
|
18045
|
-
[attr.aria-valuemin]="40"
|
|
18046
|
-
(mousedown)="onResizeStart($event, col.key)"
|
|
18047
|
-
(keydown)="onResizeKey($event, col.key)"
|
|
18048
|
-
(dblclick)="resetWidth(col.key)"
|
|
18049
|
-
></div>
|
|
18050
|
-
}
|
|
18051
|
-
</th>
|
|
18052
|
-
}
|
|
18053
|
-
@if (canActions()) {
|
|
18054
|
-
<th class="strct-dg__actioncol" scope="col" [attr.aria-label]="L().actions"></th>
|
|
18055
|
-
}
|
|
18056
|
-
</tr>
|
|
18057
|
-
</thead>
|
|
18058
|
-
<!--
|
|
18059
|
-
focusin is the real keyboard path (focus does not bubble from cells);
|
|
18060
|
-
the plain focus binding exists to satisfy mouse-events-have-key-events.
|
|
18061
|
-
-->
|
|
18062
|
-
<tbody
|
|
18063
|
-
(mouseover)="revealIfClipped($event)"
|
|
18064
|
-
(focusin)="revealIfClipped($event)"
|
|
18065
|
-
(focus)="revealIfClipped($event)"
|
|
18066
|
-
>
|
|
18067
|
-
@if (loading()) {
|
|
18068
|
-
@for (_ of [1, 2, 3, 4, 5]; track $index) {
|
|
18069
|
-
<tr class="strct-dg__skeleton-row">
|
|
18070
|
-
@if (canDetail()) {
|
|
18071
|
-
<td class="strct-dg__expandcell"></td>
|
|
18072
|
-
}
|
|
18073
|
-
@if (canExpand()) {
|
|
18074
|
-
<td class="strct-dg__expandcell"></td>
|
|
18075
|
-
}
|
|
18076
|
-
@if (hasSelectionColumn()) {
|
|
18077
|
-
<td class="strct-dg__sel"></td>
|
|
18078
|
-
}
|
|
18079
|
-
@for (col of visibleColumns(); track col.key) {
|
|
18080
|
-
<td [style.text-align]="col.align ?? 'start'">
|
|
18081
|
-
<div class="strct-dg__skeleton-block"></div>
|
|
18082
|
-
</td>
|
|
18083
|
-
}
|
|
18084
|
-
@if (canActions()) {
|
|
18085
|
-
<td class="strct-dg__actioncell"></td>
|
|
18086
|
-
}
|
|
18087
|
-
</tr>
|
|
18088
|
-
}
|
|
18089
|
-
} @else {
|
|
18090
|
-
@if (virtual() && topPad() > 0) {
|
|
18091
|
-
<tr class="strct-dg__vspacer" aria-hidden="true">
|
|
18092
|
-
<td [attr.colspan]="colspan()" [style.height.px]="topPad()"></td>
|
|
18093
|
-
</tr>
|
|
18094
|
-
}
|
|
18095
|
-
@for (it of displayItems(); track itemKey(it)) {
|
|
18096
|
-
@if (it.group; as grp) {
|
|
18097
|
-
<!-- Group header: distinct value + count, collapsible. -->
|
|
18098
|
-
<tr class="strct-dg__grouprow">
|
|
18099
|
-
@if (groupSelect() && mode() === 'multiple') {
|
|
18100
|
-
<td class="strct-dg__sel">
|
|
18101
|
-
<strct-checkbox
|
|
18102
|
-
[ariaLabel]="L().selectAllInGroup(grp.label)"
|
|
18103
|
-
[checked]="groupAllSelected(grp.key)"
|
|
18104
|
-
[indeterminate]="groupSomeSelected(grp.key)"
|
|
18105
|
-
(checkedChange)="toggleGroupSelection(grp.key)"
|
|
18106
|
-
/>
|
|
18107
|
-
</td>
|
|
18108
|
-
}
|
|
18109
|
-
<td
|
|
18110
|
-
[attr.colspan]="
|
|
18111
|
-
groupSelect() && mode() === 'multiple' ? colspan() - 1 : colspan()
|
|
18112
|
-
"
|
|
18113
|
-
>
|
|
18114
|
-
<button
|
|
18115
|
-
type="button"
|
|
18116
|
-
class="strct-dg__groupbtn"
|
|
18117
|
-
[attr.aria-expanded]="!grp.collapsed"
|
|
18118
|
-
(click)="toggleGroup(grp.key)"
|
|
18119
|
-
>
|
|
18120
|
-
<span
|
|
18121
|
-
class="strct-dg__groupchev"
|
|
18122
|
-
[class.strct-dg__groupchev--open]="!grp.collapsed"
|
|
18123
|
-
>
|
|
18124
|
-
<strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
|
|
18125
|
-
</span>
|
|
18126
|
-
@if (groupHeaderDef(); as tpl) {
|
|
18127
|
-
<!-- The consumer draws the row; the button, its
|
|
18128
|
-
aria-expanded and the keyboard stay ours. -->
|
|
18129
|
-
<ng-container
|
|
18130
|
-
[ngTemplateOutlet]="tpl.template"
|
|
18131
|
-
[ngTemplateOutletContext]="{
|
|
18132
|
-
$implicit: grp,
|
|
18133
|
-
group: grp,
|
|
18134
|
-
count: grp.count,
|
|
18135
|
-
}"
|
|
18136
|
-
/>
|
|
18137
|
-
} @else {
|
|
18138
|
-
<span
|
|
18139
|
-
class="strct-dg__grouplabel strct-dg__grouplabel--{{
|
|
18140
|
-
grp.status ?? 'none'
|
|
18141
|
-
}}"
|
|
18142
|
-
>{{ grp.label }}</span
|
|
18143
|
-
>
|
|
18144
|
-
<!-- The three spans run together in the button's
|
|
18145
|
-
name ("Needs your decision1Blocks the join…");
|
|
18146
|
-
the separators are read, not seen. -->
|
|
18147
|
-
<span class="strct-dg__announcer">, </span>
|
|
18148
|
-
<span
|
|
18149
|
-
class="strct-dg__groupcount strct-dg__groupcount--{{
|
|
18150
|
-
grp.status ?? 'none'
|
|
18151
|
-
}}"
|
|
18152
|
-
>{{ grp.count }}</span
|
|
18153
|
-
>
|
|
18154
|
-
<!-- Seen: the chip's number. Heard: the number with
|
|
18155
|
-
the grid's noun, because "Inconclusive, 3" does
|
|
18156
|
-
not say three of what. -->
|
|
18157
|
-
<span class="strct-dg__announcer"> {{ countNoun(grp.count) }}</span>
|
|
18158
|
-
@if (grp.note) {
|
|
18159
|
-
<span class="strct-dg__announcer">. </span>
|
|
18160
|
-
<span class="strct-dg__groupnote">{{ grp.note }}</span>
|
|
18161
|
-
}
|
|
18162
|
-
}
|
|
18163
|
-
</button>
|
|
18164
|
-
</td>
|
|
18165
|
-
</tr>
|
|
18166
|
-
} @else {
|
|
18167
|
-
@let row = it.row!;
|
|
18168
|
-
<tr
|
|
18169
|
-
[attr.aria-rowindex]="ariaRowIndex(row)"
|
|
18170
|
-
[class.strct-dg__row--selected]="isSelected(row)"
|
|
18171
|
-
[class.strct-dg__row--locked]="lockedReason(row) !== null"
|
|
18172
|
-
[attr.aria-selected]="mode() === 'none' ? null : isSelected(row)"
|
|
18173
|
-
[attr.aria-disabled]="lockedReason(row) !== null ? 'true' : null"
|
|
18174
|
-
[attr.title]="lockedReason(row) || null"
|
|
18175
|
-
(click)="onRowPick(row)"
|
|
18176
|
-
[class.strct-dg__row--active]="paneOpen() && row === activeRow()"
|
|
18177
|
-
[attr.aria-level]="childrenKey() ? treeDepth(row) + 1 : null"
|
|
18178
|
-
[attr.aria-expanded]="
|
|
18179
|
-
childrenKey() && treeHasChildren(row) ? treeExpanded(row) : null
|
|
18180
|
-
"
|
|
18181
|
-
[attr.tabindex]="
|
|
18182
|
-
childrenKey()
|
|
18183
|
-
? treeRowTabindex(row)
|
|
18184
|
-
: gridMode()
|
|
18185
|
-
? gridRowTabindex(row)
|
|
18186
|
-
: canDetail()
|
|
18187
|
-
? paneRowTabindex(row)
|
|
18188
|
-
: null
|
|
18189
|
-
"
|
|
18190
|
-
(keydown)="
|
|
18191
|
-
childrenKey()
|
|
18192
|
-
? onTreeRowKeydown(row, $event)
|
|
18193
|
-
: gridMode()
|
|
18194
|
-
? onGridRowKeydown(row, $event)
|
|
18195
|
-
: onPaneRowKeydown(row, $event)
|
|
18196
|
-
"
|
|
18197
|
-
(dblclick)="onRowActivate(row)"
|
|
18198
|
-
>
|
|
18199
|
-
@if (canDetail()) {
|
|
18200
|
-
<td
|
|
18201
|
-
class="strct-dg__expandcell"
|
|
18202
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
18203
|
-
[style.insetInlineStart.px]="utilLeft('detail')"
|
|
18204
|
-
>
|
|
18205
|
-
<button
|
|
18206
|
-
type="button"
|
|
18207
|
-
[attr.tabindex]="ctlTabindex()"
|
|
18208
|
-
class="strct-dg__detailbtn"
|
|
18209
|
-
[class.strct-dg__detailbtn--active]="row === activeRow()"
|
|
18210
|
-
[attr.aria-expanded]="row === activeRow()"
|
|
18211
|
-
[attr.aria-label]="L().openDetail"
|
|
18212
|
-
(click)="openDetail(row)"
|
|
18213
|
-
>
|
|
18214
|
-
<strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
|
|
18215
|
-
</button>
|
|
18216
|
-
</td>
|
|
18217
|
-
}
|
|
18218
|
-
@if (canExpand()) {
|
|
18219
|
-
<td
|
|
18220
|
-
class="strct-dg__expandcell"
|
|
18221
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
18222
|
-
[style.insetInlineStart.px]="utilLeft('expand')"
|
|
18223
|
-
>
|
|
18224
|
-
<button
|
|
18225
|
-
type="button"
|
|
18226
|
-
[attr.tabindex]="ctlTabindex()"
|
|
18227
|
-
class="strct-dg__expandbtn"
|
|
18228
|
-
[class.strct-dg__expandbtn--open]="isExpanded(row)"
|
|
18229
|
-
[attr.aria-expanded]="isExpanded(row)"
|
|
18230
|
-
[attr.aria-label]="L().toggleDetail"
|
|
18231
|
-
(click)="toggleExpand(row)"
|
|
18232
|
-
>
|
|
18233
|
-
<strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
|
|
18234
|
-
</button>
|
|
18235
|
-
</td>
|
|
18236
|
-
}
|
|
18237
|
-
@if (hasSelectionColumn()) {
|
|
18238
|
-
<td
|
|
18239
|
-
class="strct-dg__sel"
|
|
18240
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
18241
|
-
[style.insetInlineStart.px]="utilLeft('sel')"
|
|
18242
|
-
>
|
|
18243
|
-
@if (mode() === 'single') {
|
|
18244
|
-
<!-- A native radio group: one name per grid, so the
|
|
18245
|
-
arrow keys move between rows and Space picks,
|
|
18246
|
-
without the grid inventing its own keyboarding. -->
|
|
18247
|
-
<input
|
|
18248
|
-
type="radio"
|
|
18249
|
-
class="strct-dg__radio"
|
|
18250
|
-
[name]="radioName"
|
|
18251
|
-
[attr.aria-label]="selectRowLabel(row)"
|
|
18252
|
-
[attr.aria-description]="lockedReason(row) || null"
|
|
18253
|
-
[checked]="isSelected(row)"
|
|
18254
|
-
[disabled]="lockedReason(row) !== null"
|
|
18255
|
-
[attr.tabindex]="ctlTabindex()"
|
|
18256
|
-
(change)="selectSingle(row)"
|
|
18257
|
-
(click)="$event.stopPropagation()"
|
|
18258
|
-
/>
|
|
18259
|
-
} @else {
|
|
18260
|
-
<!-- click fires (and bubbles) before the input's change,
|
|
18261
|
-
so the modifier is recorded by the time toggleRow runs. -->
|
|
18262
|
-
<strct-checkbox
|
|
18263
|
-
[ariaLabel]="selectRowLabel(row)"
|
|
18264
|
-
[attr.aria-description]="lockedReason(row) || null"
|
|
18265
|
-
[checked]="isSelected(row)"
|
|
18266
|
-
[disabled]="lockedReason(row) !== null"
|
|
18267
|
-
[tabIndex]="ctlTabindex()"
|
|
18268
|
-
(click)="noteRangeIntent($event); $event.stopPropagation()"
|
|
18269
|
-
(checkedChange)="toggleRow(row)"
|
|
18270
|
-
/>
|
|
18271
|
-
}
|
|
18272
|
-
</td>
|
|
18273
|
-
}
|
|
18274
|
-
@for (col of visibleColumns(); track col.key; let colIdx = $index) {
|
|
18275
|
-
<td
|
|
18276
|
-
[style.text-align]="col.align ?? (col.numeric ? 'end' : 'start')"
|
|
18277
|
-
[class.strct-dg__cell--mono]="col.mono"
|
|
18278
|
-
[class.strct-dg__cell--muted]="col.muted"
|
|
18279
|
-
[class.strct-dg__cell--numeric]="col.numeric"
|
|
18280
|
-
[class.strct-dg__cell--sticky]="isSticky(col)"
|
|
18281
|
-
[class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
|
|
18282
|
-
[class.strct-dg__cell--editable]="col.editable"
|
|
18283
|
-
[style.insetInlineStart.px]="stickyLeft(col.key)"
|
|
18284
|
-
[attr.data-edit]="col.editable ? '' : null"
|
|
18285
|
-
[attr.tabindex]="col.editable ? editCellTabindex(row, col) : null"
|
|
18286
|
-
[attr.aria-describedby]="col.editable ? editHintId : null"
|
|
18287
|
-
(dblclick)="col.editable && startEdit(row, col)"
|
|
18288
|
-
(focus)="col.editable && onEditCellFocus(row, col)"
|
|
18289
|
-
(keydown)="col.editable && onEditCellKeydown(row, col, $event)"
|
|
18290
|
-
>
|
|
18291
|
-
@if (childrenKey() && colIdx === 0) {
|
|
18292
|
-
<span
|
|
18293
|
-
class="strct-dg__treepad"
|
|
18294
|
-
[style.width.px]="treeDepth(row) * 18"
|
|
18295
|
-
aria-hidden="true"
|
|
18296
|
-
></span>
|
|
18297
|
-
@if (treeHasChildren(row)) {
|
|
18298
|
-
<button
|
|
18299
|
-
type="button"
|
|
18300
|
-
class="strct-dg__treebtn"
|
|
18301
|
-
[class.strct-dg__treebtn--open]="treeExpanded(row)"
|
|
18302
|
-
[attr.aria-expanded]="treeExpanded(row)"
|
|
18303
|
-
[attr.aria-label]="L().toggleChildren"
|
|
18304
|
-
(click)="toggleTreeRow(row)"
|
|
18305
|
-
>
|
|
18306
|
-
<strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
|
|
18307
|
-
</button>
|
|
18308
|
-
} @else {
|
|
18309
|
-
<span
|
|
18310
|
-
class="strct-dg__treebtn strct-dg__treebtn--leaf"
|
|
18311
|
-
aria-hidden="true"
|
|
18312
|
-
></span>
|
|
18313
|
-
}
|
|
18314
|
-
}
|
|
18315
|
-
@if (isEditingCell(row, col)) {
|
|
18316
|
-
@switch (col.editor ?? 'text') {
|
|
18317
|
-
@case ('select') {
|
|
18318
|
-
<!-- Choosing is the commit: there is nothing to
|
|
18319
|
-
confirm with Enter once an option is picked. -->
|
|
18320
|
-
<strct-select
|
|
18321
|
-
class="strct-dg__editselect"
|
|
18322
|
-
[options]="editorOptionsFor(row, col)"
|
|
18323
|
-
[listLabel]="L().editCell + ': ' + col.label"
|
|
18324
|
-
[ngModel]="row[col.key]"
|
|
18325
|
-
(ngModelChange)="commitValue(row, col, $event)"
|
|
18326
|
-
(keydown.escape)="cancelEdit($event)"
|
|
18327
|
-
(click)="$event.stopPropagation()"
|
|
18328
|
-
/>
|
|
18329
|
-
}
|
|
18330
|
-
@case ('number') {
|
|
18331
|
-
<strct-number
|
|
18332
|
-
class="strct-dg__editnumber"
|
|
18333
|
-
[ariaLabel]="L().editCell + ': ' + col.label"
|
|
18334
|
-
[min]="col.editorMin ?? null"
|
|
18335
|
-
[max]="col.editorMax ?? null"
|
|
18336
|
-
[step]="col.editorStep ?? 1"
|
|
18337
|
-
[ngModel]="row[col.key]"
|
|
18338
|
-
(ngModelChange)="editDraft.set($event)"
|
|
18339
|
-
(keydown.enter)="commitDraft(row, col, $event)"
|
|
18340
|
-
(keydown.escape)="cancelEdit($event)"
|
|
18341
|
-
(focusout)="commitOnLeave(row, col, $event)"
|
|
18342
|
-
(click)="$event.stopPropagation()"
|
|
18343
|
-
/>
|
|
18344
|
-
}
|
|
18345
|
-
@default {
|
|
18346
|
-
<input
|
|
18347
|
-
class="strct-dg__editinput"
|
|
18348
|
-
type="text"
|
|
18349
|
-
[value]="row[col.key] ?? ''"
|
|
18350
|
-
[attr.aria-label]="L().editCell + ': ' + col.label"
|
|
18351
|
-
(keydown.enter)="commitEdit(row, col, $event)"
|
|
18352
|
-
(keydown.escape)="cancelEdit($event)"
|
|
18353
|
-
(blur)="commitEdit(row, col, $event)"
|
|
18354
|
-
(click)="$event.stopPropagation()"
|
|
18355
|
-
/>
|
|
18356
|
-
}
|
|
18357
|
-
}
|
|
18358
|
-
} @else if (cellTemplate(col.key); as tpl) {
|
|
18359
|
-
<ng-container
|
|
18360
|
-
[ngTemplateOutlet]="tpl"
|
|
18361
|
-
[ngTemplateOutletContext]="{
|
|
18362
|
-
$implicit: row,
|
|
18363
|
-
row,
|
|
18364
|
-
value: row[col.key],
|
|
18365
|
-
column: col,
|
|
18366
|
-
}"
|
|
18367
|
-
/>
|
|
18368
|
-
} @else if (isBlank(row, col)) {
|
|
18369
|
-
<span
|
|
18370
|
-
class="strct-dg__empty"
|
|
18371
|
-
[attr.aria-label]="col.emptyLabel || null"
|
|
18372
|
-
>{{ col.emptyText }}</span
|
|
18373
|
-
>
|
|
18374
|
-
} @else {
|
|
18375
|
-
{{ displayValue(row, col) }}
|
|
18376
|
-
@if (col.descriptionKey && row[col.descriptionKey]) {
|
|
18377
|
-
<span class="strct-dg__celldesc">{{ row[col.descriptionKey] }}</span>
|
|
18378
|
-
}
|
|
18379
|
-
}
|
|
18380
|
-
<!-- The affordance a mouse never needed: a cell that
|
|
18381
|
-
can be edited says so on hover and on focus. -->
|
|
18382
|
-
@if (col.editable && editHint() && !isEditingCell(row, col)) {
|
|
18383
|
-
<strct-icon
|
|
18384
|
-
class="strct-dg__editpencil"
|
|
18385
|
-
name="pencil"
|
|
18386
|
-
[size]="12"
|
|
18387
|
-
[strokeWidth]="1.6"
|
|
18388
|
-
aria-hidden="true"
|
|
18389
|
-
/>
|
|
18390
|
-
}
|
|
18391
|
-
</td>
|
|
18392
|
-
}
|
|
18393
|
-
@if (canActions()) {
|
|
18394
|
-
<td class="strct-dg__actioncell">
|
|
18395
|
-
<button
|
|
18396
|
-
type="button"
|
|
18397
|
-
[attr.tabindex]="ctlTabindex()"
|
|
18398
|
-
class="strct-dg__kebab"
|
|
18399
|
-
[attr.aria-label]="L().rowActions"
|
|
18400
|
-
(click)="openRowMenu(row, $event)"
|
|
18401
|
-
>
|
|
18402
|
-
<strct-icon name="dots" [size]="16" />
|
|
18403
|
-
</button>
|
|
18404
|
-
</td>
|
|
18405
|
-
}
|
|
18406
|
-
</tr>
|
|
18407
|
-
@if (canExpand() && isExpanded(row)) {
|
|
18408
|
-
<tr class="strct-dg__detailrow">
|
|
18409
|
-
<td [attr.colspan]="colspan()">
|
|
18410
|
-
<div class="strct-dg__detail">
|
|
18411
|
-
<ng-container
|
|
18412
|
-
[ngTemplateOutlet]="detailDef()!.template"
|
|
18413
|
-
[ngTemplateOutletContext]="{ $implicit: row, row }"
|
|
18414
|
-
/>
|
|
18415
|
-
</div>
|
|
18416
|
-
</td>
|
|
18417
|
-
</tr>
|
|
18418
|
-
}
|
|
18419
|
-
}
|
|
18420
|
-
} @empty {
|
|
18421
|
-
<!-- "Nothing here" and "nothing matches what you typed" are
|
|
18422
|
-
different states: the second one can be undone, and
|
|
18423
|
-
saying so is the whole point. -->
|
|
18424
|
-
<tr>
|
|
18425
|
-
<td class="strct-dg__emptyrow" [attr.colspan]="colspan()">
|
|
18426
|
-
@if (filteredAway()) {
|
|
18427
|
-
<strct-empty-state
|
|
18428
|
-
size="sm"
|
|
18429
|
-
[titleLevel]="null"
|
|
18430
|
-
[title]="L().noMatches"
|
|
18431
|
-
[description]="noMatchesDescription()"
|
|
18432
|
-
>
|
|
18433
|
-
<button strct-button variant="flat" size="sm" (click)="clearAllFilters()">
|
|
18434
|
-
{{ L().clearFilters }}
|
|
18435
|
-
</button>
|
|
18436
|
-
</strct-empty-state>
|
|
18437
|
-
} @else {
|
|
18438
|
-
<!-- Not a heading: a grid is a region of a page, and an
|
|
18439
|
-
empty one used to put an <h3> in its outline. -->
|
|
18440
|
-
<strct-empty-state size="sm" [titleLevel]="null" [title]="emptyText()" />
|
|
18441
|
-
}
|
|
18442
|
-
</td>
|
|
18443
|
-
</tr>
|
|
18444
|
-
}
|
|
18445
|
-
@if (virtual() && bottomPad() > 0) {
|
|
18446
|
-
<tr class="strct-dg__vspacer" aria-hidden="true">
|
|
18447
|
-
<td [attr.colspan]="colspan()" [style.height.px]="bottomPad()"></td>
|
|
18448
|
-
</tr>
|
|
18449
|
-
}
|
|
18450
|
-
}
|
|
18451
|
-
</tbody>
|
|
18452
|
-
</table>
|
|
18453
|
-
</div>
|
|
18454
|
-
|
|
18455
|
-
@if (paneOpen()) {
|
|
18456
|
-
<aside class="strct-dg__pane">
|
|
18457
|
-
<div class="strct-dg__pane-head">
|
|
18458
|
-
@if (narrowPane()) {
|
|
18459
|
-
<!-- The pane has taken the list's place, so there is a way back. -->
|
|
18460
|
-
<button
|
|
18461
|
-
type="button"
|
|
18462
|
-
class="strct-dg__pane-back"
|
|
18463
|
-
[attr.aria-label]="L().backToList"
|
|
18464
|
-
(click)="closePane()"
|
|
18465
|
-
>
|
|
18466
|
-
<strct-icon name="chevronLeft" [size]="13" />
|
|
18467
|
-
</button>
|
|
18468
|
-
}
|
|
18469
|
-
<span class="strct-dg__pane-title">
|
|
18470
|
-
<ng-content select="[strctDetailPaneTitle]" />
|
|
18471
|
-
@if (!paneTitleDef()) {
|
|
18472
|
-
{{ activeRow()![columns()[0].key] }}
|
|
18473
|
-
}
|
|
18474
|
-
</span>
|
|
18475
|
-
<span class="strct-dg__pane-meta">
|
|
18476
|
-
<ng-content select="[strctDetailPaneMeta]" />
|
|
18477
|
-
</span>
|
|
18478
|
-
<span class="strct-dg__pane-actions">
|
|
18479
|
-
<ng-content select="[strctDetailPaneActions]" />
|
|
18480
|
-
</span>
|
|
18481
|
-
<button
|
|
18482
|
-
type="button"
|
|
18483
|
-
class="strct-dg__pane-close"
|
|
18484
|
-
[attr.aria-label]="L().closeDetail"
|
|
18485
|
-
(click)="closePane()"
|
|
18486
|
-
>
|
|
18487
|
-
<strct-icon name="close" [size]="13" />
|
|
18488
|
-
</button>
|
|
18489
|
-
</div>
|
|
18490
|
-
<div class="strct-dg__pane-body">
|
|
18491
|
-
<ng-container
|
|
18492
|
-
[ngTemplateOutlet]="detailDef()!.template"
|
|
18493
|
-
[ngTemplateOutletContext]="{ $implicit: activeRow(), row: activeRow() }"
|
|
18494
|
-
/>
|
|
18495
|
-
</div>
|
|
18496
|
-
</aside>
|
|
18497
|
-
}
|
|
18498
|
-
</div>
|
|
18499
|
-
|
|
18500
|
-
@if (showFooter()) {
|
|
18501
|
-
<div class="strct-dg__foot">
|
|
18502
|
-
<div class="strct-dg__foot-left">
|
|
18503
|
-
@if (columnChooser() || sync()) {
|
|
18504
|
-
<div class="strct-dg__actions">
|
|
18505
|
-
<strct-button-group>
|
|
18506
|
-
@if (columnChooser()) {
|
|
18507
|
-
<button
|
|
18508
|
-
strct-button
|
|
18509
|
-
size="sm"
|
|
18510
|
-
[class.is-open]="chooserOpen()"
|
|
18511
|
-
[disabled]="footerActionsDisabled()"
|
|
18512
|
-
[attr.aria-label]="L().chooseColumns"
|
|
18513
|
-
(click)="toggleChooser($event)"
|
|
18514
|
-
>
|
|
18515
|
-
<strct-icon name="settings" [size]="16" />
|
|
18516
|
-
</button>
|
|
18517
|
-
}
|
|
18518
|
-
@if (sync()) {
|
|
18519
|
-
<button
|
|
18520
|
-
strct-button
|
|
18521
|
-
size="sm"
|
|
18522
|
-
[disabled]="footerActionsDisabled()"
|
|
18523
|
-
[attr.aria-label]="L().refresh"
|
|
18524
|
-
(click)="syncChange.emit()"
|
|
18525
|
-
>
|
|
18526
|
-
<strct-icon name="refresh" [size]="16" />
|
|
18527
|
-
</button>
|
|
18528
|
-
}
|
|
18529
|
-
</strct-button-group>
|
|
18530
|
-
@if (columnChooser() && chooserOpen()) {
|
|
18531
|
-
<div class="strct-dg__chooser-menu">
|
|
18532
|
-
@for (col of columns(); track col.key) {
|
|
18533
|
-
<!-- The whole row toggles; the checkbox's own click must not
|
|
18534
|
-
reach the row or the column would flip twice. -->
|
|
18535
|
-
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
18536
|
-
<div
|
|
18537
|
-
class="strct-dg__chooser-item"
|
|
18538
|
-
(click)="toggleColumn(col.key, hiddenColumns().has(col.key))"
|
|
18539
|
-
>
|
|
18540
|
-
<strct-checkbox
|
|
18541
|
-
[checked]="!hiddenColumns().has(col.key)"
|
|
18542
|
-
(checkedChange)="toggleColumn(col.key, $event)"
|
|
18543
|
-
(click)="$event.stopPropagation()"
|
|
18544
|
-
/>
|
|
18545
|
-
<span>{{ col.label }}</span>
|
|
18546
|
-
</div>
|
|
18547
|
-
}
|
|
18548
|
-
</div>
|
|
18549
|
-
}
|
|
18550
|
-
</div>
|
|
18551
|
-
}
|
|
18552
|
-
<span class="strct-dg__count">
|
|
18553
|
-
@if (paging() === 'more') {
|
|
18554
|
-
{{ L().showing(rows().length, moreTotal() ?? undefined) }}
|
|
18555
|
-
} @else {
|
|
18556
|
-
{{ totalCount() }} {{ totalCount() === 1 ? L().row : L().rows }}
|
|
18557
|
-
}
|
|
18558
|
-
@if (selectedCount() && mode() !== 'single') {
|
|
18559
|
-
<span class="strct-dg__count-sep">|</span>
|
|
18560
|
-
<span class="strct-dg__count-sel">{{ selectedCount() }} {{ L().selected }}</span>
|
|
18561
|
-
}
|
|
18562
|
-
</span>
|
|
18563
|
-
</div>
|
|
18564
|
-
<div class="strct-dg__foot-right">
|
|
18565
|
-
<!-- A feed that pages by cursor loads more at the end: page numbers
|
|
18566
|
-
are something a cursor API cannot answer. It takes the pager's
|
|
18567
|
-
place — the column chooser, the sync button and the count are
|
|
18568
|
-
the footer's, not the pager's. -->
|
|
18569
|
-
@if (paging() === 'more') {
|
|
18570
|
-
@if (hasMore()) {
|
|
18571
|
-
<button
|
|
18572
|
-
strct-button
|
|
18573
|
-
size="sm"
|
|
18574
|
-
class="strct-dg__more"
|
|
18575
|
-
[disabled]="loadingMore()"
|
|
18576
|
-
(click)="loadMore.emit()"
|
|
18577
|
-
>
|
|
18578
|
-
@if (loadingMore()) {
|
|
18579
|
-
<strct-spinner size="sm" />
|
|
18580
|
-
}
|
|
18581
|
-
{{ L().loadMore }}
|
|
18582
|
-
</button>
|
|
18583
|
-
}
|
|
18584
|
-
} @else if (pageSize() > 0 && !groupBy()) {
|
|
18585
|
-
<strct-pagination
|
|
18586
|
-
[total]="totalCount()"
|
|
18587
|
-
[pageSize]="pageSize()"
|
|
18588
|
-
[page]="page()"
|
|
18589
|
-
(pageChange)="goToPage($event)"
|
|
18590
|
-
/>
|
|
18591
|
-
}
|
|
18592
|
-
</div>
|
|
18593
|
-
</div>
|
|
18594
|
-
}
|
|
18595
|
-
`, isInline: true, styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t2)}.strct-dg__bulk{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px 10px;padding:7px 12px;border-bottom:1px solid var(--b2);background:var(--acc-s);color:var(--t2);font-size:var(--text-md)}.strct-dg__announcer{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t2)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t2)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t2);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:var(--text-sm);font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__grouplabel--critical{color:var(--critical)}.strct-dg__grouplabel--warning{color:var(--warning)}.strct-dg__grouplabel--success{color:var(--success)}.strct-dg__grouplabel--accent{color:var(--acc)}.strct-dg__grouplabel--neutral,.strct-dg__grouplabel--none{color:var(--t1)}.strct-dg__groupnote{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);font-weight:400;color:var(--t2)}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:4px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg__groupcount--critical{background:var(--critical-bg);color:var(--critical)}.strct-dg__groupcount--warning{background:var(--warning-bg);color:var(--warning)}.strct-dg__groupcount--success{background:var(--success-bg);color:var(--success)}.strct-dg__groupcount--neutral,.strct-dg__groupcount--none{background:var(--bg-3);color:var(--t2)}.strct-dg-host--singleline .strct-dg{border-collapse:separate;border-spacing:0}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:4px;border-start-end-radius:4px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:4px;border-end-end-radius:4px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__sortbtn{display:inline-flex;align-items:center;gap:inherit;padding:0;border:0;background:none;color:inherit;font:inherit;text-transform:inherit;letter-spacing:inherit;text-align:inherit;cursor:pointer}.strct-dg__sortbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel .strct-cb,.strct-dg__sel .strct-dg__radio,.strct-dg__expandbtn{position:relative}.strct-dg__sel .strct-cb:after,.strct-dg__sel .strct-dg__radio:after,.strct-dg__expandbtn:after{content:\"\";position:absolute;inset:-11px -13px;min-width:24px;min-height:24px}.strct-dg-host--compact .strct-dg__sel .strct-cb:after,.strct-dg-host--compact .strct-dg__sel .strct-dg__radio:after,.strct-dg-host--compact .strct-dg__expandbtn:after{inset:-7px -11px}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned>.strct-dg__scroll{flex:0 0 auto;width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px)}.strct-dg__layout--paned>.strct-dg__scroll>.strct-dg{width:100%;min-width:0;max-width:none;flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__layout--panetakeover>.strct-dg__scroll{display:none}.strct-dg__layout--panetakeover>.strct-dg__pane{flex:1;min-width:0}.strct-dg__pane-meta,.strct-dg__pane-actions{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-dg__pane-meta:empty,.strct-dg__pane-actions:empty{display:none}.strct-dg__pane-actions{margin-inline-start:auto}.strct-dg__pane-back{display:inline-flex;align-items:center;border:0;background:none;color:var(--t2);cursor:pointer;padding:2px;border-radius:var(--radius-sm)}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:4px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t2);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:var(--text-sm);color:var(--t2);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:4px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:3px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:3px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{padding:5px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:var(--bg-2);color:var(--t1);font-family:var(--font);font-size:12px}.strct-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:var(--text-sm);cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "mode", "modeLabel", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["prevLabel", "nextLabel", "regionLabel", "pageLabel", "total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StrctCheckbox, selector: "strct-checkbox", inputs: ["checked", "disabled", "indeterminate", "ariaLabel", "description", "tabIndex"], outputs: ["checkedChange"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly", "disabled", "disabledReason", "disabledReasonPosition"] }, { kind: "component", type: StrctButtonGroup, selector: "strct-button-group" }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }, { kind: "component", type: StrctSearchbox, selector: "strct-searchbox", inputs: ["placeholder", "hint", "trigger", "clearable", "ariaLabel", "clearLabel", "value"], outputs: ["valueChange", "search", "activated"] }, { kind: "component", type: StrctSelect, selector: "strct-select", inputs: ["options", "placeholder", "ariaLabel", "listLabel", "emptyText", "disabled", "compareWith"] }, { kind: "component", type: StrctNumber, selector: "strct-number", inputs: ["min", "max", "step", "placeholder", "ariaLabel", "incrementLabel", "decrementLabel", "disabled"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }, { kind: "component", type: StrctEmptyState, selector: "strct-empty-state", inputs: ["variant", "icon", "tone", "title", "titleLevel", "size", "description"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
17821
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDatagrid, isStandalone: true, selector: "strct-datagrid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, pageSizeFlat: { classPropertyName: "pageSizeFlat", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectableFlat: { classPropertyName: "selectableFlat", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPaneFlat: { classPropertyName: "detailPaneFlat", publicName: "detailPane", isSignal: true, isRequired: false, transformFunction: null }, paneListWidthFlat: { classPropertyName: "paneListWidthFlat", publicName: "paneListWidth", isSignal: true, isRequired: false, transformFunction: null }, paneTakeoverWidthFlat: { classPropertyName: "paneTakeoverWidthFlat", publicName: "paneTakeoverWidth", isSignal: true, isRequired: false, transformFunction: null }, activeRowId: { classPropertyName: "activeRowId", publicName: "activeRowId", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, singleLine: { classPropertyName: "singleLine", publicName: "singleLine", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, columnChooser: { classPropertyName: "columnChooser", publicName: "columnChooser", isSignal: true, isRequired: false, transformFunction: null }, syncFlat: { classPropertyName: "syncFlat", publicName: "sync", isSignal: true, isRequired: false, transformFunction: null }, footerActionsDisabled: { classPropertyName: "footerActionsDisabled", publicName: "footerActionsDisabled", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null }, selectionModeFlat: { classPropertyName: "selectionModeFlat", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, rowSelectableFlat: { classPropertyName: "rowSelectableFlat", publicName: "rowSelectable", isSignal: true, isRequired: false, transformFunction: null }, flush: { classPropertyName: "flush", publicName: "flush", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, hasMoreFlat: { classPropertyName: "hasMoreFlat", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, loadingMoreFlat: { classPropertyName: "loadingMoreFlat", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, moreTotalFlat: { classPropertyName: "moreTotalFlat", publicName: "moreTotal", isSignal: true, isRequired: false, transformFunction: null }, groupSelectFlat: { classPropertyName: "groupSelectFlat", publicName: "groupSelect", isSignal: true, isRequired: false, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, initialSelectionFlat: { classPropertyName: "initialSelectionFlat", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, viewportHeightFlat: { classPropertyName: "viewportHeightFlat", publicName: "viewportHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeightFlat: { classPropertyName: "maxHeightFlat", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, editHint: { classPropertyName: "editHint", publicName: "editHint", isSignal: true, isRequired: false, transformFunction: null }, rowHeightFlat: { classPropertyName: "rowHeightFlat", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, lazyFlat: { classPropertyName: "lazyFlat", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, totalFlat: { classPropertyName: "totalFlat", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, stateKeyFlat: { classPropertyName: "stateKeyFlat", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null }, columnState: { classPropertyName: "columnState", publicName: "columnState", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, groupByFlat: { classPropertyName: "groupByFlat", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, groupsFlat: { classPropertyName: "groupsFlat", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, showEmptyGroupsFlat: { classPropertyName: "showEmptyGroupsFlat", publicName: "showEmptyGroups", isSignal: true, isRequired: false, transformFunction: null }, collapsedGroups: { classPropertyName: "collapsedGroups", publicName: "collapsedGroups", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, quickFilter: { classPropertyName: "quickFilter", publicName: "quickFilter", isSignal: true, isRequired: false, transformFunction: null }, quickFilterFieldsFlat: { classPropertyName: "quickFilterFieldsFlat", publicName: "quickFilterFields", isSignal: true, isRequired: false, transformFunction: null }, quickFilterableFlat: { classPropertyName: "quickFilterableFlat", publicName: "quickFilterable", isSignal: true, isRequired: false, transformFunction: null }, quickFilterAlignFlat: { classPropertyName: "quickFilterAlignFlat", publicName: "quickFilterAlign", isSignal: true, isRequired: false, transformFunction: null }, childrenKeyFlat: { classPropertyName: "childrenKeyFlat", publicName: "childrenKey", isSignal: true, isRequired: false, transformFunction: null }, interactionMode: { classPropertyName: "interactionMode", publicName: "interactionMode", isSignal: true, isRequired: false, transformFunction: null }, selectionColumnFlat: { classPropertyName: "selectionColumnFlat", publicName: "selectionColumn", isSignal: true, isRequired: false, transformFunction: null }, selectionCfg: { classPropertyName: "selectionCfg", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, paneFlat: { classPropertyName: "paneFlat", publicName: "pane", isSignal: true, isRequired: false, transformFunction: null }, pagingFlat: { classPropertyName: "pagingFlat", publicName: "paging", isSignal: true, isRequired: false, transformFunction: null }, virtualFlat: { classPropertyName: "virtualFlat", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, groupingCfg: { classPropertyName: "groupingCfg", publicName: "grouping", isSignal: true, isRequired: false, transformFunction: null }, filteringCfg: { classPropertyName: "filteringCfg", publicName: "filtering", isSignal: true, isRequired: false, transformFunction: null }, stateCfg: { classPropertyName: "stateCfg", publicName: "state", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeRowId: "activeRowIdChange", selectedId: "selectedIdChange", loadMore: "loadMore", selectedIds: "selectedIdsChange", columnState: "columnStateChange", collapsedGroups: "collapsedGroupsChange", filters: "filtersChange", quickFilter: "quickFilterChange", rowActivate: "rowActivate", selectionChange: "selectionChange", syncChange: "syncChange", rowAction: "rowAction", lazyLoad: "lazyLoad", cellEdit: "cellEdit" }, host: { listeners: { "document:click": "onDocClickOverlays($event)", "document:keydown.escape": "onEscapeOverlays($event)" }, properties: { "attr.aria-busy": "loading() || loadingMore() ? \"true\" : null", "class.strct-dg-host--compact": "compact()", "class.strct-dg-host--singleline": "singleLine()", "class.strct-dg-host--virtual": "virtual()", "class.strct-dg-host--bounded": "!virtual() && maxHeight() !== null", "class.strct-dg-host--sticky": "stickyActive()", "class.strct-dg-host--flush": "flush()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "groupHeaderDef", first: true, predicate: StrctGroupHeaderDef, descendants: true, isSignal: true }, { propertyName: "paneTitleDef", first: true, predicate: StrctDetailPaneTitle, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "actionBarCaptionDef", first: true, predicate: StrctDatagridActionBarCaption, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: "<!-- One polite region for everything the grid does to itself: sorting,\n paging and filtering all change the rows without saying so. -->\n<span class=\"strct-dg__announcer\" role=\"status\" aria-live=\"polite\">{{ announcement() }}</span>\n@if (actionBarDef() || quickFilterable() || actionBarCaptionDef()) {\n <div class=\"strct-dg__toolbar\">\n @if (quickFilterable()) {\n <strct-searchbox\n class=\"strct-dg__quickfilter\"\n [class.strct-dg__quickfilter--end]=\"quickFilterAlign() === 'end'\"\n [placeholder]=\"L().quickFilter\"\n [ariaLabel]=\"L().quickFilter\"\n [value]=\"quickFilter()\"\n (valueChange)=\"quickFilter.set($event)\"\n />\n @if (filterNote(); as note) {\n <span\n class=\"strct-dg__filternote\"\n [class.strct-dg__filternote--end]=\"quickFilterAlign() === 'end'\"\n >{{ note }}</span\n >\n }\n }\n <span class=\"strct-dg__actioncaption\">\n <ng-content select=\"[strctDatagridActionBarCaption]\" />\n </span>\n <ng-content select=\"[strctDatagridActionBar]\" />\n </div>\n}\n\n@if (hasEditableColumn()) {\n <!-- What the editable cells point at with aria-describedby: a keyboard\n user is told the cell can be edited, and how. -->\n <!-- In flow, not absolutely positioned: an out-of-flow box whose\n containing block is the page extends the document's scrollable area\n from wherever the grid happens to sit. 1x1 and clipped is enough. -->\n <span\n class=\"strct-sr-only\"\n style=\"\n display: inline-block;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n \"\n [id]=\"editHintId\"\n >{{ L().editCellInstructions }}</span\n >\n}\n\n@if (bulkHint(); as hint) {\n <!-- Selecting the page is not selecting the set. Say which one happened,\n and offer the other. -->\n <div class=\"strct-dg__bulk\" role=\"status\">\n <span>{{ hint.text }}</span>\n <button strct-button variant=\"flat\" size=\"sm\" (click)=\"hint.run()\">\n {{ hint.action }}\n </button>\n </div>\n}\n<div\n class=\"strct-dg__layout\"\n [class.strct-dg__layout--paned]=\"paneOpen()\"\n [class.strct-dg__layout--panetakeover]=\"paneOpen() && narrowPane()\"\n [style.--strct-dg-pane-list-w]=\"paneListWidth()\"\n>\n <div\n class=\"strct-dg__scroll\"\n tabindex=\"0\"\n role=\"region\"\n [attr.aria-label]=\"L().rows\"\n [style.max-height.px]=\"virtual() ? viewportHeight() : maxHeight()\"\n (scroll)=\"virtual() && onScroll($event)\"\n >\n <table\n class=\"strct-dg\"\n [attr.role]=\"childrenKey() ? 'treegrid' : gridMode() ? 'grid' : null\"\n [attr.aria-rowcount]=\"ariaRowCount()\"\n [attr.aria-labelledby]=\"caption() ? captionId : null\"\n >\n @if (caption()) {\n <caption class=\"strct-dg__caption\" [id]=\"captionId\">\n {{\n caption()\n }}\n </caption>\n }\n <thead>\n <tr>\n <!-- A utility column is still a column: axe reports every empty\n header, and a screen-reader user hears nothing where the\n detail, expand and select controls are. The name is hidden,\n not absent. -->\n @if (canDetail()) {\n <th\n class=\"strct-dg__expandcol\"\n scope=\"col\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('detail')\"\n >\n <span class=\"strct-sr-only\">{{ L().detailColumn }}</span>\n </th>\n }\n @if (canExpand()) {\n <th\n class=\"strct-dg__expandcol\"\n scope=\"col\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('expand')\"\n >\n <span class=\"strct-sr-only\">{{ L().expandColumn }}</span>\n </th>\n }\n @if (hasSelectionColumn()) {\n <th\n class=\"strct-dg__sel\"\n scope=\"col\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('sel')\"\n >\n @if (mode() === 'multiple') {\n <strct-checkbox\n [ariaLabel]=\"L().selectAll\"\n [checked]=\"allPageSelected()\"\n [indeterminate]=\"somePageSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n } @else {\n <span class=\"strct-sr-only\">{{ L().selectColumn }}</span>\n }\n </th>\n }\n @for (col of visibleColumns(); track col.key) {\n <th\n scope=\"col\"\n [style.text-align]=\"col.align ?? (col.numeric ? 'end' : 'start')\"\n [style.width]=\"colWidth(col.key) ?? col.width ?? null\"\n [class.strct-dg__th--sortable]=\"col.sortable\"\n [class.strct-dg__th--drop]=\"col.key === dropKey()\"\n [class.strct-dg__cell--sticky]=\"isSticky(col)\"\n [class.strct-dg__cell--sticky-last]=\"col.key === lastStickyKey()\"\n [style.insetInlineStart.px]=\"stickyLeft(col.key)\"\n [attr.data-col]=\"col.key\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n [attr.draggable]=\"reorderable() ? true : null\"\n (dragstart)=\"onColDragStart(col.key, $event)\"\n (dragover)=\"onColDragOver(col.key, $event)\"\n (drop)=\"onColDrop(col.key)\"\n (dragend)=\"onColDragEnd()\"\n >\n <span class=\"strct-dg__hd\">\n <!-- A header that sorts is a button: a th with tabindex is\n read as \"column header, focusable\" and never says it\n can be activated. aria-sort stays on the th, which is\n what carries the column's sorted state. -->\n @if (col.sortable) {\n <!-- The button covers most of the header, so it carries\n the drag source too: a reorderable column has to be\n grabbable where the pointer actually lands. The\n event bubbles to the th's own handlers. -->\n <button\n type=\"button\"\n class=\"strct-dg__sortbtn\"\n [attr.draggable]=\"reorderable() ? true : null\"\n (click)=\"sortBy(col.key)\"\n >\n {{ col.label }}\n <strct-icon class=\"strct-dg__sorticon\" [name]=\"sortIcon(col.key)\" [size]=\"13\" />\n </button>\n } @else {\n {{ col.label }}\n }\n @if (col.filterable || col.filterOptions) {\n <button\n #fbtn\n type=\"button\"\n class=\"strct-dg__filterbtn\"\n [class.strct-dg__filterbtn--active]=\"hasFilter(col.key)\"\n [attr.aria-expanded]=\"filterOpenKey() === col.key\"\n [attr.aria-label]=\"L().filterColumn + ': ' + col.label\"\n (click)=\"toggleFilterPanel(col.key, $event)\"\n (keydown.enter)=\"$event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n >\n <strct-icon name=\"filter\" [size]=\"12\" />\n </button>\n @if (filterOpenKey() === col.key) {\n <div\n class=\"strct-dg__filterpanel\"\n role=\"dialog\"\n [attr.aria-label]=\"L().filterColumn + ': ' + col.label\"\n [strctOverlay]=\"fbtn\"\n strctOverlayPlacement=\"bottom-start\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n >\n @if (col.filterOptions; as opts) {\n @for (opt of opts; track $index) {\n <label class=\"strct-dg__filteropt\">\n <input\n type=\"checkbox\"\n [checked]=\"optionChecked(col.key, opt)\"\n (change)=\"toggleFilterOption(col.key, opt)\"\n />\n <span>{{ opt }}</span>\n </label>\n }\n } @else {\n <input\n class=\"strct-dg__filterinput\"\n type=\"text\"\n [attr.placeholder]=\"L().filterPlaceholder\"\n [attr.aria-label]=\"L().filterColumn + ': ' + col.label\"\n [value]=\"textFilter(col.key)\"\n (input)=\"setTextFilter(col.key, $any($event.target).value)\"\n />\n }\n <button\n type=\"button\"\n class=\"strct-dg__filterclear\"\n [disabled]=\"!hasFilter(col.key)\"\n (click)=\"clearFilter(col.key)\"\n >\n {{ L().clearFilter }}\n </button>\n </div>\n }\n }\n </span>\n @if (resizable() && col.resizable !== false) {\n <!-- A separator, not a bare div: a column could only be\n resized with a mouse, which is the one input a\n console cannot assume. -->\n <div\n class=\"strct-dg__resize\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"L().resizeColumn(col.label)\"\n [attr.aria-valuenow]=\"separatorValue(col.key)\"\n [attr.aria-valuemin]=\"40\"\n (mousedown)=\"onResizeStart($event, col.key)\"\n (keydown)=\"onResizeKey($event, col.key)\"\n (dblclick)=\"resetWidth(col.key)\"\n ></div>\n }\n </th>\n }\n @if (canActions()) {\n <th class=\"strct-dg__actioncol\" scope=\"col\" [attr.aria-label]=\"L().actions\"></th>\n }\n </tr>\n </thead>\n <!--\n focusin is the real keyboard path (focus does not bubble from cells);\n the plain focus binding exists to satisfy mouse-events-have-key-events.\n -->\n <tbody\n (mouseover)=\"revealIfClipped($event)\"\n (focusin)=\"revealIfClipped($event)\"\n (focus)=\"revealIfClipped($event)\"\n >\n @if (loading()) {\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\n <tr class=\"strct-dg__skeleton-row\">\n @if (canDetail()) {\n <td class=\"strct-dg__expandcell\"></td>\n }\n @if (canExpand()) {\n <td class=\"strct-dg__expandcell\"></td>\n }\n @if (hasSelectionColumn()) {\n <td class=\"strct-dg__sel\"></td>\n }\n @for (col of visibleColumns(); track col.key) {\n <td [style.text-align]=\"col.align ?? 'start'\">\n <div class=\"strct-dg__skeleton-block\"></div>\n </td>\n }\n @if (canActions()) {\n <td class=\"strct-dg__actioncell\"></td>\n }\n </tr>\n }\n } @else {\n @if (virtual() && topPad() > 0) {\n <tr class=\"strct-dg__vspacer\" aria-hidden=\"true\">\n <td [attr.colspan]=\"colspan()\" [style.height.px]=\"topPad()\"></td>\n </tr>\n }\n @for (it of displayItems(); track itemKey(it)) {\n @if (it.group; as grp) {\n <!-- Group header: distinct value + count, collapsible. -->\n <tr class=\"strct-dg__grouprow\">\n @if (groupSelect() && mode() === 'multiple') {\n <td class=\"strct-dg__sel\">\n <strct-checkbox\n [ariaLabel]=\"L().selectAllInGroup(grp.label)\"\n [checked]=\"groupAllSelected(grp.key)\"\n [indeterminate]=\"groupSomeSelected(grp.key)\"\n (checkedChange)=\"toggleGroupSelection(grp.key)\"\n />\n </td>\n }\n <td\n [attr.colspan]=\"\n groupSelect() && mode() === 'multiple' ? colspan() - 1 : colspan()\n \"\n >\n <button\n type=\"button\"\n class=\"strct-dg__groupbtn\"\n [attr.aria-expanded]=\"!grp.collapsed\"\n (click)=\"toggleGroup(grp.key)\"\n >\n <span\n class=\"strct-dg__groupchev\"\n [class.strct-dg__groupchev--open]=\"!grp.collapsed\"\n >\n <strct-icon name=\"chevronRight\" [size]=\"12\" [strokeWidth]=\"1.7\" />\n </span>\n @if (groupHeaderDef(); as tpl) {\n <!-- The consumer draws the row; the button, its\n aria-expanded and the keyboard stay ours. -->\n <ng-container\n [ngTemplateOutlet]=\"tpl.template\"\n [ngTemplateOutletContext]=\"{\n $implicit: grp,\n group: grp,\n count: grp.count,\n }\"\n />\n } @else {\n <span\n class=\"strct-dg__grouplabel strct-dg__grouplabel--{{\n grp.status ?? 'none'\n }}\"\n >{{ grp.label }}</span\n >\n <!-- The three spans run together in the button's\n name (\"Needs your decision1Blocks the join\u2026\");\n the separators are read, not seen. -->\n <span class=\"strct-dg__announcer\">, </span>\n <span\n class=\"strct-dg__groupcount strct-dg__groupcount--{{\n grp.status ?? 'none'\n }}\"\n >{{ grp.count }}</span\n >\n <!-- Seen: the chip's number. Heard: the number with\n the grid's noun, because \"Inconclusive, 3\" does\n not say three of what. -->\n <span class=\"strct-dg__announcer\"> {{ countNoun(grp.count) }}</span>\n @if (grp.note) {\n <span class=\"strct-dg__announcer\">. </span>\n <span class=\"strct-dg__groupnote\">{{ grp.note }}</span>\n }\n }\n </button>\n </td>\n </tr>\n } @else {\n @let row = it.row!;\n <tr\n [attr.aria-rowindex]=\"ariaRowIndex(row)\"\n [class.strct-dg__row--selected]=\"isSelected(row)\"\n [class.strct-dg__row--locked]=\"lockedReason(row) !== null\"\n [attr.aria-selected]=\"mode() === 'none' ? null : isSelected(row)\"\n [attr.aria-disabled]=\"lockedReason(row) !== null ? 'true' : null\"\n [attr.title]=\"lockedReason(row) || null\"\n (click)=\"onRowPick(row)\"\n [class.strct-dg__row--active]=\"paneOpen() && row === activeRow()\"\n [attr.aria-level]=\"childrenKey() ? treeDepth(row) + 1 : null\"\n [attr.aria-expanded]=\"\n childrenKey() && treeHasChildren(row) ? treeExpanded(row) : null\n \"\n [attr.tabindex]=\"\n childrenKey()\n ? treeRowTabindex(row)\n : gridMode()\n ? gridRowTabindex(row)\n : canDetail()\n ? paneRowTabindex(row)\n : null\n \"\n (keydown)=\"\n childrenKey()\n ? onTreeRowKeydown(row, $event)\n : gridMode()\n ? onGridRowKeydown(row, $event)\n : onPaneRowKeydown(row, $event)\n \"\n (dblclick)=\"onRowActivate(row)\"\n >\n @if (canDetail()) {\n <td\n class=\"strct-dg__expandcell\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('detail')\"\n >\n <button\n type=\"button\"\n [attr.tabindex]=\"ctlTabindex()\"\n class=\"strct-dg__detailbtn\"\n [class.strct-dg__detailbtn--active]=\"row === activeRow()\"\n [attr.aria-expanded]=\"row === activeRow()\"\n [attr.aria-label]=\"L().openDetail\"\n (click)=\"openDetail(row)\"\n >\n <strct-icon name=\"chevronDoubleRight\" [size]=\"13\" [strokeWidth]=\"1.6\" />\n </button>\n </td>\n }\n @if (canExpand()) {\n <td\n class=\"strct-dg__expandcell\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('expand')\"\n >\n <button\n type=\"button\"\n [attr.tabindex]=\"ctlTabindex()\"\n class=\"strct-dg__expandbtn\"\n [class.strct-dg__expandbtn--open]=\"isExpanded(row)\"\n [attr.aria-expanded]=\"isExpanded(row)\"\n [attr.aria-label]=\"L().toggleDetail\"\n (click)=\"toggleExpand(row)\"\n >\n <strct-icon name=\"chevronRight\" [size]=\"12\" [strokeWidth]=\"1.7\" />\n </button>\n </td>\n }\n @if (hasSelectionColumn()) {\n <td\n class=\"strct-dg__sel\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('sel')\"\n >\n @if (mode() === 'single') {\n <!-- A native radio group: one name per grid, so the\n arrow keys move between rows and Space picks,\n without the grid inventing its own keyboarding. -->\n <input\n type=\"radio\"\n class=\"strct-dg__radio\"\n [name]=\"radioName\"\n [attr.aria-label]=\"selectRowLabel(row)\"\n [attr.aria-description]=\"lockedReason(row) || null\"\n [checked]=\"isSelected(row)\"\n [disabled]=\"lockedReason(row) !== null\"\n [attr.tabindex]=\"ctlTabindex()\"\n (change)=\"selectSingle(row)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else {\n <!-- click fires (and bubbles) before the input's change,\n so the modifier is recorded by the time toggleRow runs. -->\n <strct-checkbox\n [ariaLabel]=\"selectRowLabel(row)\"\n [attr.aria-description]=\"lockedReason(row) || null\"\n [checked]=\"isSelected(row)\"\n [disabled]=\"lockedReason(row) !== null\"\n [tabIndex]=\"ctlTabindex()\"\n (click)=\"noteRangeIntent($event); $event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row)\"\n />\n }\n </td>\n }\n @for (col of visibleColumns(); track col.key; let colIdx = $index) {\n <td\n [style.text-align]=\"col.align ?? (col.numeric ? 'end' : 'start')\"\n [class.strct-dg__cell--mono]=\"col.mono\"\n [class.strct-dg__cell--muted]=\"col.muted\"\n [class.strct-dg__cell--numeric]=\"col.numeric\"\n [class.strct-dg__cell--sticky]=\"isSticky(col)\"\n [class.strct-dg__cell--sticky-last]=\"col.key === lastStickyKey()\"\n [class.strct-dg__cell--editable]=\"col.editable\"\n [style.insetInlineStart.px]=\"stickyLeft(col.key)\"\n [attr.data-edit]=\"col.editable ? '' : null\"\n [attr.tabindex]=\"col.editable ? editCellTabindex(row, col) : null\"\n [attr.aria-describedby]=\"col.editable ? editHintId : null\"\n (dblclick)=\"col.editable && startEdit(row, col)\"\n (focus)=\"col.editable && onEditCellFocus(row, col)\"\n (keydown)=\"col.editable && onEditCellKeydown(row, col, $event)\"\n >\n @if (childrenKey() && colIdx === 0) {\n <span\n class=\"strct-dg__treepad\"\n [style.width.px]=\"treeDepth(row) * 18\"\n aria-hidden=\"true\"\n ></span>\n @if (treeHasChildren(row)) {\n <button\n type=\"button\"\n class=\"strct-dg__treebtn\"\n [class.strct-dg__treebtn--open]=\"treeExpanded(row)\"\n [attr.aria-expanded]=\"treeExpanded(row)\"\n [attr.aria-label]=\"L().toggleChildren\"\n (click)=\"toggleTreeRow(row)\"\n >\n <strct-icon name=\"chevronRight\" [size]=\"12\" [strokeWidth]=\"1.7\" />\n </button>\n } @else {\n <span\n class=\"strct-dg__treebtn strct-dg__treebtn--leaf\"\n aria-hidden=\"true\"\n ></span>\n }\n }\n @if (isEditingCell(row, col)) {\n @switch (col.editor ?? 'text') {\n @case ('select') {\n <!-- Choosing is the commit: there is nothing to\n confirm with Enter once an option is picked. -->\n <strct-select\n class=\"strct-dg__editselect\"\n [options]=\"editorOptionsFor(row, col)\"\n [listLabel]=\"L().editCell + ': ' + col.label\"\n [ngModel]=\"row[col.key]\"\n (ngModelChange)=\"commitValue(row, col, $event)\"\n (keydown.escape)=\"cancelEdit($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n @case ('number') {\n <strct-number\n class=\"strct-dg__editnumber\"\n [ariaLabel]=\"L().editCell + ': ' + col.label\"\n [min]=\"col.editorMin ?? null\"\n [max]=\"col.editorMax ?? null\"\n [step]=\"col.editorStep ?? 1\"\n [ngModel]=\"row[col.key]\"\n (ngModelChange)=\"editDraft.set($event)\"\n (keydown.enter)=\"commitDraft(row, col, $event)\"\n (keydown.escape)=\"cancelEdit($event)\"\n (focusout)=\"commitOnLeave(row, col, $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n @default {\n <input\n class=\"strct-dg__editinput\"\n type=\"text\"\n [value]=\"row[col.key] ?? ''\"\n [attr.aria-label]=\"L().editCell + ': ' + col.label\"\n (keydown.enter)=\"commitEdit(row, col, $event)\"\n (keydown.escape)=\"cancelEdit($event)\"\n (blur)=\"commitEdit(row, col, $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n }\n } @else if (cellTemplate(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n row,\n value: row[col.key],\n column: col,\n }\"\n />\n } @else if (isBlank(row, col)) {\n <span class=\"strct-dg__empty\" [attr.aria-label]=\"col.emptyLabel || null\">{{\n col.emptyText\n }}</span>\n } @else {\n {{ displayValue(row, col) }}\n @if (col.descriptionKey && row[col.descriptionKey]) {\n <span class=\"strct-dg__celldesc\">{{ row[col.descriptionKey] }}</span>\n }\n }\n <!-- The affordance a mouse never needed: a cell that\n can be edited says so on hover and on focus. -->\n @if (col.editable && editHint() && !isEditingCell(row, col)) {\n <strct-icon\n class=\"strct-dg__editpencil\"\n name=\"pencil\"\n [size]=\"12\"\n [strokeWidth]=\"1.6\"\n aria-hidden=\"true\"\n />\n }\n </td>\n }\n @if (canActions()) {\n <td class=\"strct-dg__actioncell\">\n <button\n type=\"button\"\n [attr.tabindex]=\"ctlTabindex()\"\n class=\"strct-dg__kebab\"\n [attr.aria-label]=\"L().rowActions\"\n (click)=\"openRowMenu(row, $event)\"\n >\n <strct-icon name=\"dots\" [size]=\"16\" />\n </button>\n </td>\n }\n </tr>\n @if (canExpand() && isExpanded(row)) {\n <tr class=\"strct-dg__detailrow\">\n <td [attr.colspan]=\"colspan()\">\n <div class=\"strct-dg__detail\">\n <ng-container\n [ngTemplateOutlet]=\"detailDef()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: row, row }\"\n />\n </div>\n </td>\n </tr>\n }\n }\n } @empty {\n <!-- \"Nothing here\" and \"nothing matches what you typed\" are\n different states: the second one can be undone, and\n saying so is the whole point. -->\n <tr>\n <td class=\"strct-dg__emptyrow\" [attr.colspan]=\"colspan()\">\n @if (filteredAway()) {\n <strct-empty-state\n size=\"sm\"\n [titleLevel]=\"null\"\n [title]=\"L().noMatches\"\n [description]=\"noMatchesDescription()\"\n >\n <button strct-button variant=\"flat\" size=\"sm\" (click)=\"clearAllFilters()\">\n {{ L().clearFilters }}\n </button>\n </strct-empty-state>\n } @else {\n <!-- Not a heading: a grid is a region of a page, and an\n empty one used to put an <h3> in its outline. -->\n <strct-empty-state size=\"sm\" [titleLevel]=\"null\" [title]=\"emptyText()\" />\n }\n </td>\n </tr>\n }\n @if (virtual() && bottomPad() > 0) {\n <tr class=\"strct-dg__vspacer\" aria-hidden=\"true\">\n <td [attr.colspan]=\"colspan()\" [style.height.px]=\"bottomPad()\"></td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (paneOpen()) {\n <aside class=\"strct-dg__pane\">\n <div class=\"strct-dg__pane-head\">\n @if (narrowPane()) {\n <!-- The pane has taken the list's place, so there is a way back. -->\n <button\n type=\"button\"\n class=\"strct-dg__pane-back\"\n [attr.aria-label]=\"L().backToList\"\n (click)=\"closePane()\"\n >\n <strct-icon name=\"chevronLeft\" [size]=\"13\" />\n </button>\n }\n <span class=\"strct-dg__pane-title\">\n <ng-content select=\"[strctDetailPaneTitle]\" />\n @if (!paneTitleDef()) {\n {{ activeRow()![columns()[0].key] }}\n }\n </span>\n <span class=\"strct-dg__pane-meta\">\n <ng-content select=\"[strctDetailPaneMeta]\" />\n </span>\n <span class=\"strct-dg__pane-actions\">\n <ng-content select=\"[strctDetailPaneActions]\" />\n </span>\n <button\n type=\"button\"\n class=\"strct-dg__pane-close\"\n [attr.aria-label]=\"L().closeDetail\"\n (click)=\"closePane()\"\n >\n <strct-icon name=\"close\" [size]=\"13\" />\n </button>\n </div>\n <div class=\"strct-dg__pane-body\">\n <ng-container\n [ngTemplateOutlet]=\"detailDef()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: activeRow(), row: activeRow() }\"\n />\n </div>\n </aside>\n }\n</div>\n\n@if (showFooter()) {\n <div class=\"strct-dg__foot\">\n <div class=\"strct-dg__foot-left\">\n @if (columnChooser() || sync()) {\n <div class=\"strct-dg__actions\">\n <strct-button-group>\n @if (columnChooser()) {\n <button\n strct-button\n size=\"sm\"\n [class.is-open]=\"chooserOpen()\"\n [disabled]=\"footerActionsDisabled()\"\n [attr.aria-label]=\"L().chooseColumns\"\n (click)=\"toggleChooser($event)\"\n >\n <strct-icon name=\"settings\" [size]=\"16\" />\n </button>\n }\n @if (sync()) {\n <button\n strct-button\n size=\"sm\"\n [disabled]=\"footerActionsDisabled()\"\n [attr.aria-label]=\"L().refresh\"\n (click)=\"syncChange.emit()\"\n >\n <strct-icon name=\"refresh\" [size]=\"16\" />\n </button>\n }\n </strct-button-group>\n @if (columnChooser() && chooserOpen()) {\n <div class=\"strct-dg__chooser-menu\">\n @for (col of columns(); track col.key) {\n <!-- The whole row toggles; the checkbox's own click must not\n reach the row or the column would flip twice. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"strct-dg__chooser-item\"\n (click)=\"toggleColumn(col.key, hiddenColumns().has(col.key))\"\n >\n <strct-checkbox\n [checked]=\"!hiddenColumns().has(col.key)\"\n (checkedChange)=\"toggleColumn(col.key, $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n <span>{{ col.label }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n <span class=\"strct-dg__count\">\n @if (paging() === 'more') {\n {{ L().showing(rows().length, moreTotal() ?? undefined) }}\n } @else {\n {{ totalCount() }} {{ totalCount() === 1 ? L().row : L().rows }}\n }\n @if (selectedCount() && mode() !== 'single') {\n <span class=\"strct-dg__count-sep\">|</span>\n <span class=\"strct-dg__count-sel\">{{ selectedCount() }} {{ L().selected }}</span>\n }\n </span>\n </div>\n <div class=\"strct-dg__foot-right\">\n <!-- A feed that pages by cursor loads more at the end: page numbers\n are something a cursor API cannot answer. It takes the pager's\n place \u2014 the column chooser, the sync button and the count are\n the footer's, not the pager's. -->\n @if (paging() === 'more') {\n @if (hasMore()) {\n <button\n strct-button\n size=\"sm\"\n class=\"strct-dg__more\"\n [disabled]=\"loadingMore()\"\n (click)=\"loadMore.emit()\"\n >\n @if (loadingMore()) {\n <strct-spinner size=\"sm\" />\n }\n {{ L().loadMore }}\n </button>\n }\n } @else if (pageSize() > 0 && !groupBy()) {\n <strct-pagination\n [total]=\"totalCount()\"\n [pageSize]=\"pageSize()\"\n [page]=\"page()\"\n (pageChange)=\"goToPage($event)\"\n />\n }\n </div>\n </div>\n}\n", styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t2)}.strct-dg__bulk{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px 10px;padding:7px 12px;border-bottom:1px solid var(--b2);background:var(--acc-s);color:var(--t2);font-size:var(--text-md)}.strct-dg__announcer{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t2)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t2)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t2);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:var(--text-sm);font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__grouplabel--critical{color:var(--critical)}.strct-dg__grouplabel--warning{color:var(--warning)}.strct-dg__grouplabel--success{color:var(--success)}.strct-dg__grouplabel--accent{color:var(--acc)}.strct-dg__grouplabel--neutral,.strct-dg__grouplabel--none{color:var(--t1)}.strct-dg__groupnote{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);font-weight:400;color:var(--t2)}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:4px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg__groupcount--critical{background:var(--critical-bg);color:var(--critical)}.strct-dg__groupcount--warning{background:var(--warning-bg);color:var(--warning)}.strct-dg__groupcount--success{background:var(--success-bg);color:var(--success)}.strct-dg__groupcount--neutral,.strct-dg__groupcount--none{background:var(--bg-3);color:var(--t2)}.strct-dg-host--singleline .strct-dg{border-collapse:separate;border-spacing:0}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:4px;border-start-end-radius:4px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:4px;border-end-end-radius:4px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__sortbtn{display:inline-flex;align-items:center;gap:inherit;padding:0;border:0;background:none;color:inherit;font:inherit;text-transform:inherit;letter-spacing:inherit;text-align:inherit;cursor:pointer}.strct-dg__sortbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel .strct-cb,.strct-dg__sel .strct-dg__radio,.strct-dg__expandbtn{position:relative}.strct-dg__sel .strct-cb:after,.strct-dg__sel .strct-dg__radio:after,.strct-dg__expandbtn:after{content:\"\";position:absolute;inset:-11px -13px;min-width:24px;min-height:24px}.strct-dg-host--compact .strct-dg__sel .strct-cb:after,.strct-dg-host--compact .strct-dg__sel .strct-dg__radio:after,.strct-dg-host--compact .strct-dg__expandbtn:after{inset:-7px -11px}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned>.strct-dg__scroll{flex:0 0 auto;width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px)}.strct-dg__layout--paned>.strct-dg__scroll>.strct-dg{width:100%;min-width:0;max-width:none;flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__layout--panetakeover>.strct-dg__scroll{display:none}.strct-dg__layout--panetakeover>.strct-dg__pane{flex:1;min-width:0}.strct-dg__pane-meta,.strct-dg__pane-actions{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-dg__pane-meta:empty,.strct-dg__pane-actions:empty{display:none}.strct-dg__pane-actions{margin-inline-start:auto}.strct-dg__pane-back{display:inline-flex;align-items:center;border:0;background:none;color:var(--t2);cursor:pointer;padding:2px;border-radius:var(--radius-sm)}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:4px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t2);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:var(--text-sm);color:var(--t2);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:4px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:3px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:3px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{padding:5px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:var(--bg-2);color:var(--t1);font-family:var(--font);font-size:12px}.strct-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:var(--text-sm);cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "mode", "modeLabel", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["prevLabel", "nextLabel", "regionLabel", "pageLabel", "total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StrctCheckbox, selector: "strct-checkbox", inputs: ["checked", "disabled", "indeterminate", "ariaLabel", "description", "tabIndex"], outputs: ["checkedChange"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly", "disabled", "disabledReason", "disabledReasonPosition"] }, { kind: "component", type: StrctButtonGroup, selector: "strct-button-group" }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }, { kind: "component", type: StrctSearchbox, selector: "strct-searchbox", inputs: ["placeholder", "hint", "trigger", "clearable", "ariaLabel", "clearLabel", "value"], outputs: ["valueChange", "search", "activated"] }, { kind: "component", type: StrctSelect, selector: "strct-select", inputs: ["options", "placeholder", "ariaLabel", "listLabel", "emptyText", "disabled", "compareWith"] }, { kind: "component", type: StrctNumber, selector: "strct-number", inputs: ["min", "max", "step", "placeholder", "ariaLabel", "incrementLabel", "decrementLabel", "disabled"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }, { kind: "component", type: StrctEmptyState, selector: "strct-empty-state", inputs: ["variant", "icon", "tone", "title", "titleLevel", "size", "description"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
18596
17822
|
}
|
|
18597
17823
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDatagrid, decorators: [{
|
|
18598
17824
|
type: Component,
|
|
@@ -18610,796 +17836,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18610
17836
|
StrctSpinner,
|
|
18611
17837
|
StrctEmptyState,
|
|
18612
17838
|
FormsModule,
|
|
18613
|
-
],
|
|
18614
|
-
<!-- One polite region for everything the grid does to itself: sorting,
|
|
18615
|
-
paging and filtering all change the rows without saying so. -->
|
|
18616
|
-
<span class="strct-dg__announcer" role="status" aria-live="polite">{{ announcement() }}</span>
|
|
18617
|
-
@if (actionBarDef() || quickFilterable() || actionBarCaptionDef()) {
|
|
18618
|
-
<div class="strct-dg__toolbar">
|
|
18619
|
-
@if (quickFilterable()) {
|
|
18620
|
-
<strct-searchbox
|
|
18621
|
-
class="strct-dg__quickfilter"
|
|
18622
|
-
[class.strct-dg__quickfilter--end]="quickFilterAlign() === 'end'"
|
|
18623
|
-
[placeholder]="L().quickFilter"
|
|
18624
|
-
[ariaLabel]="L().quickFilter"
|
|
18625
|
-
[value]="quickFilter()"
|
|
18626
|
-
(valueChange)="quickFilter.set($event)"
|
|
18627
|
-
/>
|
|
18628
|
-
@if (filterNote(); as note) {
|
|
18629
|
-
<span
|
|
18630
|
-
class="strct-dg__filternote"
|
|
18631
|
-
[class.strct-dg__filternote--end]="quickFilterAlign() === 'end'"
|
|
18632
|
-
>{{ note }}</span
|
|
18633
|
-
>
|
|
18634
|
-
}
|
|
18635
|
-
}
|
|
18636
|
-
<span class="strct-dg__actioncaption">
|
|
18637
|
-
<ng-content select="[strctDatagridActionBarCaption]" />
|
|
18638
|
-
</span>
|
|
18639
|
-
<ng-content select="[strctDatagridActionBar]" />
|
|
18640
|
-
</div>
|
|
18641
|
-
}
|
|
18642
|
-
|
|
18643
|
-
@if (hasEditableColumn()) {
|
|
18644
|
-
<!-- What the editable cells point at with aria-describedby: a keyboard
|
|
18645
|
-
user is told the cell can be edited, and how. -->
|
|
18646
|
-
<!-- In flow, not absolutely positioned: an out-of-flow box whose
|
|
18647
|
-
containing block is the page extends the document's scrollable area
|
|
18648
|
-
from wherever the grid happens to sit. 1x1 and clipped is enough. -->
|
|
18649
|
-
<span
|
|
18650
|
-
class="strct-sr-only"
|
|
18651
|
-
style="display: inline-block; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap"
|
|
18652
|
-
[id]="editHintId"
|
|
18653
|
-
>{{ L().editCellInstructions }}</span
|
|
18654
|
-
>
|
|
18655
|
-
}
|
|
18656
|
-
|
|
18657
|
-
@if (bulkHint(); as hint) {
|
|
18658
|
-
<!-- Selecting the page is not selecting the set. Say which one happened,
|
|
18659
|
-
and offer the other. -->
|
|
18660
|
-
<div class="strct-dg__bulk" role="status">
|
|
18661
|
-
<span>{{ hint.text }}</span>
|
|
18662
|
-
<button strct-button variant="flat" size="sm" (click)="hint.run()">
|
|
18663
|
-
{{ hint.action }}
|
|
18664
|
-
</button>
|
|
18665
|
-
</div>
|
|
18666
|
-
}
|
|
18667
|
-
<div
|
|
18668
|
-
class="strct-dg__layout"
|
|
18669
|
-
[class.strct-dg__layout--paned]="paneOpen()"
|
|
18670
|
-
[class.strct-dg__layout--panetakeover]="paneOpen() && narrowPane()"
|
|
18671
|
-
[style.--strct-dg-pane-list-w]="paneListWidth()"
|
|
18672
|
-
>
|
|
18673
|
-
<div
|
|
18674
|
-
class="strct-dg__scroll"
|
|
18675
|
-
tabindex="0"
|
|
18676
|
-
role="region"
|
|
18677
|
-
[attr.aria-label]="L().rows"
|
|
18678
|
-
[style.max-height.px]="virtual() ? viewportHeight() : maxHeight()"
|
|
18679
|
-
(scroll)="virtual() && onScroll($event)"
|
|
18680
|
-
>
|
|
18681
|
-
<table
|
|
18682
|
-
class="strct-dg"
|
|
18683
|
-
[attr.role]="childrenKey() ? 'treegrid' : gridMode() ? 'grid' : null"
|
|
18684
|
-
[attr.aria-rowcount]="ariaRowCount()"
|
|
18685
|
-
[attr.aria-labelledby]="caption() ? captionId : null"
|
|
18686
|
-
>
|
|
18687
|
-
@if (caption()) {
|
|
18688
|
-
<caption class="strct-dg__caption" [id]="captionId">
|
|
18689
|
-
{{
|
|
18690
|
-
caption()
|
|
18691
|
-
}}
|
|
18692
|
-
</caption>
|
|
18693
|
-
}
|
|
18694
|
-
<thead>
|
|
18695
|
-
<tr>
|
|
18696
|
-
<!-- A utility column is still a column: axe reports every empty
|
|
18697
|
-
header, and a screen-reader user hears nothing where the
|
|
18698
|
-
detail, expand and select controls are. The name is hidden,
|
|
18699
|
-
not absent. -->
|
|
18700
|
-
@if (canDetail()) {
|
|
18701
|
-
<th
|
|
18702
|
-
class="strct-dg__expandcol"
|
|
18703
|
-
scope="col"
|
|
18704
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
18705
|
-
[style.insetInlineStart.px]="utilLeft('detail')"
|
|
18706
|
-
>
|
|
18707
|
-
<span class="strct-sr-only">{{ L().detailColumn }}</span>
|
|
18708
|
-
</th>
|
|
18709
|
-
}
|
|
18710
|
-
@if (canExpand()) {
|
|
18711
|
-
<th
|
|
18712
|
-
class="strct-dg__expandcol"
|
|
18713
|
-
scope="col"
|
|
18714
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
18715
|
-
[style.insetInlineStart.px]="utilLeft('expand')"
|
|
18716
|
-
>
|
|
18717
|
-
<span class="strct-sr-only">{{ L().expandColumn }}</span>
|
|
18718
|
-
</th>
|
|
18719
|
-
}
|
|
18720
|
-
@if (hasSelectionColumn()) {
|
|
18721
|
-
<th
|
|
18722
|
-
class="strct-dg__sel"
|
|
18723
|
-
scope="col"
|
|
18724
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
18725
|
-
[style.insetInlineStart.px]="utilLeft('sel')"
|
|
18726
|
-
>
|
|
18727
|
-
@if (mode() === 'multiple') {
|
|
18728
|
-
<strct-checkbox
|
|
18729
|
-
[ariaLabel]="L().selectAll"
|
|
18730
|
-
[checked]="allPageSelected()"
|
|
18731
|
-
[indeterminate]="somePageSelected()"
|
|
18732
|
-
(checkedChange)="toggleAll()"
|
|
18733
|
-
/>
|
|
18734
|
-
} @else {
|
|
18735
|
-
<span class="strct-sr-only">{{ L().selectColumn }}</span>
|
|
18736
|
-
}
|
|
18737
|
-
</th>
|
|
18738
|
-
}
|
|
18739
|
-
@for (col of visibleColumns(); track col.key) {
|
|
18740
|
-
<th
|
|
18741
|
-
scope="col"
|
|
18742
|
-
[style.text-align]="col.align ?? (col.numeric ? 'end' : 'start')"
|
|
18743
|
-
[style.width]="colWidth(col.key) ?? col.width ?? null"
|
|
18744
|
-
[class.strct-dg__th--sortable]="col.sortable"
|
|
18745
|
-
[class.strct-dg__th--drop]="col.key === dropKey()"
|
|
18746
|
-
[class.strct-dg__cell--sticky]="isSticky(col)"
|
|
18747
|
-
[class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
|
|
18748
|
-
[style.insetInlineStart.px]="stickyLeft(col.key)"
|
|
18749
|
-
[attr.data-col]="col.key"
|
|
18750
|
-
[attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
|
|
18751
|
-
[attr.draggable]="reorderable() ? true : null"
|
|
18752
|
-
(dragstart)="onColDragStart(col.key, $event)"
|
|
18753
|
-
(dragover)="onColDragOver(col.key, $event)"
|
|
18754
|
-
(drop)="onColDrop(col.key)"
|
|
18755
|
-
(dragend)="onColDragEnd()"
|
|
18756
|
-
>
|
|
18757
|
-
<span class="strct-dg__hd">
|
|
18758
|
-
<!-- A header that sorts is a button: a th with tabindex is
|
|
18759
|
-
read as "column header, focusable" and never says it
|
|
18760
|
-
can be activated. aria-sort stays on the th, which is
|
|
18761
|
-
what carries the column's sorted state. -->
|
|
18762
|
-
@if (col.sortable) {
|
|
18763
|
-
<!-- The button covers most of the header, so it carries
|
|
18764
|
-
the drag source too: a reorderable column has to be
|
|
18765
|
-
grabbable where the pointer actually lands. The
|
|
18766
|
-
event bubbles to the th's own handlers. -->
|
|
18767
|
-
<button
|
|
18768
|
-
type="button"
|
|
18769
|
-
class="strct-dg__sortbtn"
|
|
18770
|
-
[attr.draggable]="reorderable() ? true : null"
|
|
18771
|
-
(click)="sortBy(col.key)"
|
|
18772
|
-
>
|
|
18773
|
-
{{ col.label }}
|
|
18774
|
-
<strct-icon
|
|
18775
|
-
class="strct-dg__sorticon"
|
|
18776
|
-
[name]="sortIcon(col.key)"
|
|
18777
|
-
[size]="13"
|
|
18778
|
-
/>
|
|
18779
|
-
</button>
|
|
18780
|
-
} @else {
|
|
18781
|
-
{{ col.label }}
|
|
18782
|
-
}
|
|
18783
|
-
@if (col.filterable || col.filterOptions) {
|
|
18784
|
-
<button
|
|
18785
|
-
#fbtn
|
|
18786
|
-
type="button"
|
|
18787
|
-
class="strct-dg__filterbtn"
|
|
18788
|
-
[class.strct-dg__filterbtn--active]="hasFilter(col.key)"
|
|
18789
|
-
[attr.aria-expanded]="filterOpenKey() === col.key"
|
|
18790
|
-
[attr.aria-label]="L().filterColumn + ': ' + col.label"
|
|
18791
|
-
(click)="toggleFilterPanel(col.key, $event)"
|
|
18792
|
-
(keydown.enter)="$event.stopPropagation()"
|
|
18793
|
-
(keydown.space)="$event.stopPropagation()"
|
|
18794
|
-
>
|
|
18795
|
-
<strct-icon name="filter" [size]="12" />
|
|
18796
|
-
</button>
|
|
18797
|
-
@if (filterOpenKey() === col.key) {
|
|
18798
|
-
<div
|
|
18799
|
-
class="strct-dg__filterpanel"
|
|
18800
|
-
role="dialog"
|
|
18801
|
-
[attr.aria-label]="L().filterColumn + ': ' + col.label"
|
|
18802
|
-
[strctOverlay]="fbtn"
|
|
18803
|
-
strctOverlayPlacement="bottom-start"
|
|
18804
|
-
(click)="$event.stopPropagation()"
|
|
18805
|
-
(keydown.enter)="$event.stopPropagation()"
|
|
18806
|
-
(keydown.space)="$event.stopPropagation()"
|
|
18807
|
-
>
|
|
18808
|
-
@if (col.filterOptions; as opts) {
|
|
18809
|
-
@for (opt of opts; track $index) {
|
|
18810
|
-
<label class="strct-dg__filteropt">
|
|
18811
|
-
<input
|
|
18812
|
-
type="checkbox"
|
|
18813
|
-
[checked]="optionChecked(col.key, opt)"
|
|
18814
|
-
(change)="toggleFilterOption(col.key, opt)"
|
|
18815
|
-
/>
|
|
18816
|
-
<span>{{ opt }}</span>
|
|
18817
|
-
</label>
|
|
18818
|
-
}
|
|
18819
|
-
} @else {
|
|
18820
|
-
<input
|
|
18821
|
-
class="strct-dg__filterinput"
|
|
18822
|
-
type="text"
|
|
18823
|
-
[attr.placeholder]="L().filterPlaceholder"
|
|
18824
|
-
[attr.aria-label]="L().filterColumn + ': ' + col.label"
|
|
18825
|
-
[value]="textFilter(col.key)"
|
|
18826
|
-
(input)="setTextFilter(col.key, $any($event.target).value)"
|
|
18827
|
-
/>
|
|
18828
|
-
}
|
|
18829
|
-
<button
|
|
18830
|
-
type="button"
|
|
18831
|
-
class="strct-dg__filterclear"
|
|
18832
|
-
[disabled]="!hasFilter(col.key)"
|
|
18833
|
-
(click)="clearFilter(col.key)"
|
|
18834
|
-
>
|
|
18835
|
-
{{ L().clearFilter }}
|
|
18836
|
-
</button>
|
|
18837
|
-
</div>
|
|
18838
|
-
}
|
|
18839
|
-
}
|
|
18840
|
-
</span>
|
|
18841
|
-
@if (resizable() && col.resizable !== false) {
|
|
18842
|
-
<!-- A separator, not a bare div: a column could only be
|
|
18843
|
-
resized with a mouse, which is the one input a
|
|
18844
|
-
console cannot assume. -->
|
|
18845
|
-
<div
|
|
18846
|
-
class="strct-dg__resize"
|
|
18847
|
-
role="separator"
|
|
18848
|
-
aria-orientation="vertical"
|
|
18849
|
-
tabindex="0"
|
|
18850
|
-
[attr.aria-label]="L().resizeColumn(col.label)"
|
|
18851
|
-
[attr.aria-valuenow]="separatorValue(col.key)"
|
|
18852
|
-
[attr.aria-valuemin]="40"
|
|
18853
|
-
(mousedown)="onResizeStart($event, col.key)"
|
|
18854
|
-
(keydown)="onResizeKey($event, col.key)"
|
|
18855
|
-
(dblclick)="resetWidth(col.key)"
|
|
18856
|
-
></div>
|
|
18857
|
-
}
|
|
18858
|
-
</th>
|
|
18859
|
-
}
|
|
18860
|
-
@if (canActions()) {
|
|
18861
|
-
<th class="strct-dg__actioncol" scope="col" [attr.aria-label]="L().actions"></th>
|
|
18862
|
-
}
|
|
18863
|
-
</tr>
|
|
18864
|
-
</thead>
|
|
18865
|
-
<!--
|
|
18866
|
-
focusin is the real keyboard path (focus does not bubble from cells);
|
|
18867
|
-
the plain focus binding exists to satisfy mouse-events-have-key-events.
|
|
18868
|
-
-->
|
|
18869
|
-
<tbody
|
|
18870
|
-
(mouseover)="revealIfClipped($event)"
|
|
18871
|
-
(focusin)="revealIfClipped($event)"
|
|
18872
|
-
(focus)="revealIfClipped($event)"
|
|
18873
|
-
>
|
|
18874
|
-
@if (loading()) {
|
|
18875
|
-
@for (_ of [1, 2, 3, 4, 5]; track $index) {
|
|
18876
|
-
<tr class="strct-dg__skeleton-row">
|
|
18877
|
-
@if (canDetail()) {
|
|
18878
|
-
<td class="strct-dg__expandcell"></td>
|
|
18879
|
-
}
|
|
18880
|
-
@if (canExpand()) {
|
|
18881
|
-
<td class="strct-dg__expandcell"></td>
|
|
18882
|
-
}
|
|
18883
|
-
@if (hasSelectionColumn()) {
|
|
18884
|
-
<td class="strct-dg__sel"></td>
|
|
18885
|
-
}
|
|
18886
|
-
@for (col of visibleColumns(); track col.key) {
|
|
18887
|
-
<td [style.text-align]="col.align ?? 'start'">
|
|
18888
|
-
<div class="strct-dg__skeleton-block"></div>
|
|
18889
|
-
</td>
|
|
18890
|
-
}
|
|
18891
|
-
@if (canActions()) {
|
|
18892
|
-
<td class="strct-dg__actioncell"></td>
|
|
18893
|
-
}
|
|
18894
|
-
</tr>
|
|
18895
|
-
}
|
|
18896
|
-
} @else {
|
|
18897
|
-
@if (virtual() && topPad() > 0) {
|
|
18898
|
-
<tr class="strct-dg__vspacer" aria-hidden="true">
|
|
18899
|
-
<td [attr.colspan]="colspan()" [style.height.px]="topPad()"></td>
|
|
18900
|
-
</tr>
|
|
18901
|
-
}
|
|
18902
|
-
@for (it of displayItems(); track itemKey(it)) {
|
|
18903
|
-
@if (it.group; as grp) {
|
|
18904
|
-
<!-- Group header: distinct value + count, collapsible. -->
|
|
18905
|
-
<tr class="strct-dg__grouprow">
|
|
18906
|
-
@if (groupSelect() && mode() === 'multiple') {
|
|
18907
|
-
<td class="strct-dg__sel">
|
|
18908
|
-
<strct-checkbox
|
|
18909
|
-
[ariaLabel]="L().selectAllInGroup(grp.label)"
|
|
18910
|
-
[checked]="groupAllSelected(grp.key)"
|
|
18911
|
-
[indeterminate]="groupSomeSelected(grp.key)"
|
|
18912
|
-
(checkedChange)="toggleGroupSelection(grp.key)"
|
|
18913
|
-
/>
|
|
18914
|
-
</td>
|
|
18915
|
-
}
|
|
18916
|
-
<td
|
|
18917
|
-
[attr.colspan]="
|
|
18918
|
-
groupSelect() && mode() === 'multiple' ? colspan() - 1 : colspan()
|
|
18919
|
-
"
|
|
18920
|
-
>
|
|
18921
|
-
<button
|
|
18922
|
-
type="button"
|
|
18923
|
-
class="strct-dg__groupbtn"
|
|
18924
|
-
[attr.aria-expanded]="!grp.collapsed"
|
|
18925
|
-
(click)="toggleGroup(grp.key)"
|
|
18926
|
-
>
|
|
18927
|
-
<span
|
|
18928
|
-
class="strct-dg__groupchev"
|
|
18929
|
-
[class.strct-dg__groupchev--open]="!grp.collapsed"
|
|
18930
|
-
>
|
|
18931
|
-
<strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
|
|
18932
|
-
</span>
|
|
18933
|
-
@if (groupHeaderDef(); as tpl) {
|
|
18934
|
-
<!-- The consumer draws the row; the button, its
|
|
18935
|
-
aria-expanded and the keyboard stay ours. -->
|
|
18936
|
-
<ng-container
|
|
18937
|
-
[ngTemplateOutlet]="tpl.template"
|
|
18938
|
-
[ngTemplateOutletContext]="{
|
|
18939
|
-
$implicit: grp,
|
|
18940
|
-
group: grp,
|
|
18941
|
-
count: grp.count,
|
|
18942
|
-
}"
|
|
18943
|
-
/>
|
|
18944
|
-
} @else {
|
|
18945
|
-
<span
|
|
18946
|
-
class="strct-dg__grouplabel strct-dg__grouplabel--{{
|
|
18947
|
-
grp.status ?? 'none'
|
|
18948
|
-
}}"
|
|
18949
|
-
>{{ grp.label }}</span
|
|
18950
|
-
>
|
|
18951
|
-
<!-- The three spans run together in the button's
|
|
18952
|
-
name ("Needs your decision1Blocks the join…");
|
|
18953
|
-
the separators are read, not seen. -->
|
|
18954
|
-
<span class="strct-dg__announcer">, </span>
|
|
18955
|
-
<span
|
|
18956
|
-
class="strct-dg__groupcount strct-dg__groupcount--{{
|
|
18957
|
-
grp.status ?? 'none'
|
|
18958
|
-
}}"
|
|
18959
|
-
>{{ grp.count }}</span
|
|
18960
|
-
>
|
|
18961
|
-
<!-- Seen: the chip's number. Heard: the number with
|
|
18962
|
-
the grid's noun, because "Inconclusive, 3" does
|
|
18963
|
-
not say three of what. -->
|
|
18964
|
-
<span class="strct-dg__announcer"> {{ countNoun(grp.count) }}</span>
|
|
18965
|
-
@if (grp.note) {
|
|
18966
|
-
<span class="strct-dg__announcer">. </span>
|
|
18967
|
-
<span class="strct-dg__groupnote">{{ grp.note }}</span>
|
|
18968
|
-
}
|
|
18969
|
-
}
|
|
18970
|
-
</button>
|
|
18971
|
-
</td>
|
|
18972
|
-
</tr>
|
|
18973
|
-
} @else {
|
|
18974
|
-
@let row = it.row!;
|
|
18975
|
-
<tr
|
|
18976
|
-
[attr.aria-rowindex]="ariaRowIndex(row)"
|
|
18977
|
-
[class.strct-dg__row--selected]="isSelected(row)"
|
|
18978
|
-
[class.strct-dg__row--locked]="lockedReason(row) !== null"
|
|
18979
|
-
[attr.aria-selected]="mode() === 'none' ? null : isSelected(row)"
|
|
18980
|
-
[attr.aria-disabled]="lockedReason(row) !== null ? 'true' : null"
|
|
18981
|
-
[attr.title]="lockedReason(row) || null"
|
|
18982
|
-
(click)="onRowPick(row)"
|
|
18983
|
-
[class.strct-dg__row--active]="paneOpen() && row === activeRow()"
|
|
18984
|
-
[attr.aria-level]="childrenKey() ? treeDepth(row) + 1 : null"
|
|
18985
|
-
[attr.aria-expanded]="
|
|
18986
|
-
childrenKey() && treeHasChildren(row) ? treeExpanded(row) : null
|
|
18987
|
-
"
|
|
18988
|
-
[attr.tabindex]="
|
|
18989
|
-
childrenKey()
|
|
18990
|
-
? treeRowTabindex(row)
|
|
18991
|
-
: gridMode()
|
|
18992
|
-
? gridRowTabindex(row)
|
|
18993
|
-
: canDetail()
|
|
18994
|
-
? paneRowTabindex(row)
|
|
18995
|
-
: null
|
|
18996
|
-
"
|
|
18997
|
-
(keydown)="
|
|
18998
|
-
childrenKey()
|
|
18999
|
-
? onTreeRowKeydown(row, $event)
|
|
19000
|
-
: gridMode()
|
|
19001
|
-
? onGridRowKeydown(row, $event)
|
|
19002
|
-
: onPaneRowKeydown(row, $event)
|
|
19003
|
-
"
|
|
19004
|
-
(dblclick)="onRowActivate(row)"
|
|
19005
|
-
>
|
|
19006
|
-
@if (canDetail()) {
|
|
19007
|
-
<td
|
|
19008
|
-
class="strct-dg__expandcell"
|
|
19009
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
19010
|
-
[style.insetInlineStart.px]="utilLeft('detail')"
|
|
19011
|
-
>
|
|
19012
|
-
<button
|
|
19013
|
-
type="button"
|
|
19014
|
-
[attr.tabindex]="ctlTabindex()"
|
|
19015
|
-
class="strct-dg__detailbtn"
|
|
19016
|
-
[class.strct-dg__detailbtn--active]="row === activeRow()"
|
|
19017
|
-
[attr.aria-expanded]="row === activeRow()"
|
|
19018
|
-
[attr.aria-label]="L().openDetail"
|
|
19019
|
-
(click)="openDetail(row)"
|
|
19020
|
-
>
|
|
19021
|
-
<strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
|
|
19022
|
-
</button>
|
|
19023
|
-
</td>
|
|
19024
|
-
}
|
|
19025
|
-
@if (canExpand()) {
|
|
19026
|
-
<td
|
|
19027
|
-
class="strct-dg__expandcell"
|
|
19028
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
19029
|
-
[style.insetInlineStart.px]="utilLeft('expand')"
|
|
19030
|
-
>
|
|
19031
|
-
<button
|
|
19032
|
-
type="button"
|
|
19033
|
-
[attr.tabindex]="ctlTabindex()"
|
|
19034
|
-
class="strct-dg__expandbtn"
|
|
19035
|
-
[class.strct-dg__expandbtn--open]="isExpanded(row)"
|
|
19036
|
-
[attr.aria-expanded]="isExpanded(row)"
|
|
19037
|
-
[attr.aria-label]="L().toggleDetail"
|
|
19038
|
-
(click)="toggleExpand(row)"
|
|
19039
|
-
>
|
|
19040
|
-
<strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
|
|
19041
|
-
</button>
|
|
19042
|
-
</td>
|
|
19043
|
-
}
|
|
19044
|
-
@if (hasSelectionColumn()) {
|
|
19045
|
-
<td
|
|
19046
|
-
class="strct-dg__sel"
|
|
19047
|
-
[class.strct-dg__cell--sticky]="stickyActive()"
|
|
19048
|
-
[style.insetInlineStart.px]="utilLeft('sel')"
|
|
19049
|
-
>
|
|
19050
|
-
@if (mode() === 'single') {
|
|
19051
|
-
<!-- A native radio group: one name per grid, so the
|
|
19052
|
-
arrow keys move between rows and Space picks,
|
|
19053
|
-
without the grid inventing its own keyboarding. -->
|
|
19054
|
-
<input
|
|
19055
|
-
type="radio"
|
|
19056
|
-
class="strct-dg__radio"
|
|
19057
|
-
[name]="radioName"
|
|
19058
|
-
[attr.aria-label]="selectRowLabel(row)"
|
|
19059
|
-
[attr.aria-description]="lockedReason(row) || null"
|
|
19060
|
-
[checked]="isSelected(row)"
|
|
19061
|
-
[disabled]="lockedReason(row) !== null"
|
|
19062
|
-
[attr.tabindex]="ctlTabindex()"
|
|
19063
|
-
(change)="selectSingle(row)"
|
|
19064
|
-
(click)="$event.stopPropagation()"
|
|
19065
|
-
/>
|
|
19066
|
-
} @else {
|
|
19067
|
-
<!-- click fires (and bubbles) before the input's change,
|
|
19068
|
-
so the modifier is recorded by the time toggleRow runs. -->
|
|
19069
|
-
<strct-checkbox
|
|
19070
|
-
[ariaLabel]="selectRowLabel(row)"
|
|
19071
|
-
[attr.aria-description]="lockedReason(row) || null"
|
|
19072
|
-
[checked]="isSelected(row)"
|
|
19073
|
-
[disabled]="lockedReason(row) !== null"
|
|
19074
|
-
[tabIndex]="ctlTabindex()"
|
|
19075
|
-
(click)="noteRangeIntent($event); $event.stopPropagation()"
|
|
19076
|
-
(checkedChange)="toggleRow(row)"
|
|
19077
|
-
/>
|
|
19078
|
-
}
|
|
19079
|
-
</td>
|
|
19080
|
-
}
|
|
19081
|
-
@for (col of visibleColumns(); track col.key; let colIdx = $index) {
|
|
19082
|
-
<td
|
|
19083
|
-
[style.text-align]="col.align ?? (col.numeric ? 'end' : 'start')"
|
|
19084
|
-
[class.strct-dg__cell--mono]="col.mono"
|
|
19085
|
-
[class.strct-dg__cell--muted]="col.muted"
|
|
19086
|
-
[class.strct-dg__cell--numeric]="col.numeric"
|
|
19087
|
-
[class.strct-dg__cell--sticky]="isSticky(col)"
|
|
19088
|
-
[class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
|
|
19089
|
-
[class.strct-dg__cell--editable]="col.editable"
|
|
19090
|
-
[style.insetInlineStart.px]="stickyLeft(col.key)"
|
|
19091
|
-
[attr.data-edit]="col.editable ? '' : null"
|
|
19092
|
-
[attr.tabindex]="col.editable ? editCellTabindex(row, col) : null"
|
|
19093
|
-
[attr.aria-describedby]="col.editable ? editHintId : null"
|
|
19094
|
-
(dblclick)="col.editable && startEdit(row, col)"
|
|
19095
|
-
(focus)="col.editable && onEditCellFocus(row, col)"
|
|
19096
|
-
(keydown)="col.editable && onEditCellKeydown(row, col, $event)"
|
|
19097
|
-
>
|
|
19098
|
-
@if (childrenKey() && colIdx === 0) {
|
|
19099
|
-
<span
|
|
19100
|
-
class="strct-dg__treepad"
|
|
19101
|
-
[style.width.px]="treeDepth(row) * 18"
|
|
19102
|
-
aria-hidden="true"
|
|
19103
|
-
></span>
|
|
19104
|
-
@if (treeHasChildren(row)) {
|
|
19105
|
-
<button
|
|
19106
|
-
type="button"
|
|
19107
|
-
class="strct-dg__treebtn"
|
|
19108
|
-
[class.strct-dg__treebtn--open]="treeExpanded(row)"
|
|
19109
|
-
[attr.aria-expanded]="treeExpanded(row)"
|
|
19110
|
-
[attr.aria-label]="L().toggleChildren"
|
|
19111
|
-
(click)="toggleTreeRow(row)"
|
|
19112
|
-
>
|
|
19113
|
-
<strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
|
|
19114
|
-
</button>
|
|
19115
|
-
} @else {
|
|
19116
|
-
<span
|
|
19117
|
-
class="strct-dg__treebtn strct-dg__treebtn--leaf"
|
|
19118
|
-
aria-hidden="true"
|
|
19119
|
-
></span>
|
|
19120
|
-
}
|
|
19121
|
-
}
|
|
19122
|
-
@if (isEditingCell(row, col)) {
|
|
19123
|
-
@switch (col.editor ?? 'text') {
|
|
19124
|
-
@case ('select') {
|
|
19125
|
-
<!-- Choosing is the commit: there is nothing to
|
|
19126
|
-
confirm with Enter once an option is picked. -->
|
|
19127
|
-
<strct-select
|
|
19128
|
-
class="strct-dg__editselect"
|
|
19129
|
-
[options]="editorOptionsFor(row, col)"
|
|
19130
|
-
[listLabel]="L().editCell + ': ' + col.label"
|
|
19131
|
-
[ngModel]="row[col.key]"
|
|
19132
|
-
(ngModelChange)="commitValue(row, col, $event)"
|
|
19133
|
-
(keydown.escape)="cancelEdit($event)"
|
|
19134
|
-
(click)="$event.stopPropagation()"
|
|
19135
|
-
/>
|
|
19136
|
-
}
|
|
19137
|
-
@case ('number') {
|
|
19138
|
-
<strct-number
|
|
19139
|
-
class="strct-dg__editnumber"
|
|
19140
|
-
[ariaLabel]="L().editCell + ': ' + col.label"
|
|
19141
|
-
[min]="col.editorMin ?? null"
|
|
19142
|
-
[max]="col.editorMax ?? null"
|
|
19143
|
-
[step]="col.editorStep ?? 1"
|
|
19144
|
-
[ngModel]="row[col.key]"
|
|
19145
|
-
(ngModelChange)="editDraft.set($event)"
|
|
19146
|
-
(keydown.enter)="commitDraft(row, col, $event)"
|
|
19147
|
-
(keydown.escape)="cancelEdit($event)"
|
|
19148
|
-
(focusout)="commitOnLeave(row, col, $event)"
|
|
19149
|
-
(click)="$event.stopPropagation()"
|
|
19150
|
-
/>
|
|
19151
|
-
}
|
|
19152
|
-
@default {
|
|
19153
|
-
<input
|
|
19154
|
-
class="strct-dg__editinput"
|
|
19155
|
-
type="text"
|
|
19156
|
-
[value]="row[col.key] ?? ''"
|
|
19157
|
-
[attr.aria-label]="L().editCell + ': ' + col.label"
|
|
19158
|
-
(keydown.enter)="commitEdit(row, col, $event)"
|
|
19159
|
-
(keydown.escape)="cancelEdit($event)"
|
|
19160
|
-
(blur)="commitEdit(row, col, $event)"
|
|
19161
|
-
(click)="$event.stopPropagation()"
|
|
19162
|
-
/>
|
|
19163
|
-
}
|
|
19164
|
-
}
|
|
19165
|
-
} @else if (cellTemplate(col.key); as tpl) {
|
|
19166
|
-
<ng-container
|
|
19167
|
-
[ngTemplateOutlet]="tpl"
|
|
19168
|
-
[ngTemplateOutletContext]="{
|
|
19169
|
-
$implicit: row,
|
|
19170
|
-
row,
|
|
19171
|
-
value: row[col.key],
|
|
19172
|
-
column: col,
|
|
19173
|
-
}"
|
|
19174
|
-
/>
|
|
19175
|
-
} @else if (isBlank(row, col)) {
|
|
19176
|
-
<span
|
|
19177
|
-
class="strct-dg__empty"
|
|
19178
|
-
[attr.aria-label]="col.emptyLabel || null"
|
|
19179
|
-
>{{ col.emptyText }}</span
|
|
19180
|
-
>
|
|
19181
|
-
} @else {
|
|
19182
|
-
{{ displayValue(row, col) }}
|
|
19183
|
-
@if (col.descriptionKey && row[col.descriptionKey]) {
|
|
19184
|
-
<span class="strct-dg__celldesc">{{ row[col.descriptionKey] }}</span>
|
|
19185
|
-
}
|
|
19186
|
-
}
|
|
19187
|
-
<!-- The affordance a mouse never needed: a cell that
|
|
19188
|
-
can be edited says so on hover and on focus. -->
|
|
19189
|
-
@if (col.editable && editHint() && !isEditingCell(row, col)) {
|
|
19190
|
-
<strct-icon
|
|
19191
|
-
class="strct-dg__editpencil"
|
|
19192
|
-
name="pencil"
|
|
19193
|
-
[size]="12"
|
|
19194
|
-
[strokeWidth]="1.6"
|
|
19195
|
-
aria-hidden="true"
|
|
19196
|
-
/>
|
|
19197
|
-
}
|
|
19198
|
-
</td>
|
|
19199
|
-
}
|
|
19200
|
-
@if (canActions()) {
|
|
19201
|
-
<td class="strct-dg__actioncell">
|
|
19202
|
-
<button
|
|
19203
|
-
type="button"
|
|
19204
|
-
[attr.tabindex]="ctlTabindex()"
|
|
19205
|
-
class="strct-dg__kebab"
|
|
19206
|
-
[attr.aria-label]="L().rowActions"
|
|
19207
|
-
(click)="openRowMenu(row, $event)"
|
|
19208
|
-
>
|
|
19209
|
-
<strct-icon name="dots" [size]="16" />
|
|
19210
|
-
</button>
|
|
19211
|
-
</td>
|
|
19212
|
-
}
|
|
19213
|
-
</tr>
|
|
19214
|
-
@if (canExpand() && isExpanded(row)) {
|
|
19215
|
-
<tr class="strct-dg__detailrow">
|
|
19216
|
-
<td [attr.colspan]="colspan()">
|
|
19217
|
-
<div class="strct-dg__detail">
|
|
19218
|
-
<ng-container
|
|
19219
|
-
[ngTemplateOutlet]="detailDef()!.template"
|
|
19220
|
-
[ngTemplateOutletContext]="{ $implicit: row, row }"
|
|
19221
|
-
/>
|
|
19222
|
-
</div>
|
|
19223
|
-
</td>
|
|
19224
|
-
</tr>
|
|
19225
|
-
}
|
|
19226
|
-
}
|
|
19227
|
-
} @empty {
|
|
19228
|
-
<!-- "Nothing here" and "nothing matches what you typed" are
|
|
19229
|
-
different states: the second one can be undone, and
|
|
19230
|
-
saying so is the whole point. -->
|
|
19231
|
-
<tr>
|
|
19232
|
-
<td class="strct-dg__emptyrow" [attr.colspan]="colspan()">
|
|
19233
|
-
@if (filteredAway()) {
|
|
19234
|
-
<strct-empty-state
|
|
19235
|
-
size="sm"
|
|
19236
|
-
[titleLevel]="null"
|
|
19237
|
-
[title]="L().noMatches"
|
|
19238
|
-
[description]="noMatchesDescription()"
|
|
19239
|
-
>
|
|
19240
|
-
<button strct-button variant="flat" size="sm" (click)="clearAllFilters()">
|
|
19241
|
-
{{ L().clearFilters }}
|
|
19242
|
-
</button>
|
|
19243
|
-
</strct-empty-state>
|
|
19244
|
-
} @else {
|
|
19245
|
-
<!-- Not a heading: a grid is a region of a page, and an
|
|
19246
|
-
empty one used to put an <h3> in its outline. -->
|
|
19247
|
-
<strct-empty-state size="sm" [titleLevel]="null" [title]="emptyText()" />
|
|
19248
|
-
}
|
|
19249
|
-
</td>
|
|
19250
|
-
</tr>
|
|
19251
|
-
}
|
|
19252
|
-
@if (virtual() && bottomPad() > 0) {
|
|
19253
|
-
<tr class="strct-dg__vspacer" aria-hidden="true">
|
|
19254
|
-
<td [attr.colspan]="colspan()" [style.height.px]="bottomPad()"></td>
|
|
19255
|
-
</tr>
|
|
19256
|
-
}
|
|
19257
|
-
}
|
|
19258
|
-
</tbody>
|
|
19259
|
-
</table>
|
|
19260
|
-
</div>
|
|
19261
|
-
|
|
19262
|
-
@if (paneOpen()) {
|
|
19263
|
-
<aside class="strct-dg__pane">
|
|
19264
|
-
<div class="strct-dg__pane-head">
|
|
19265
|
-
@if (narrowPane()) {
|
|
19266
|
-
<!-- The pane has taken the list's place, so there is a way back. -->
|
|
19267
|
-
<button
|
|
19268
|
-
type="button"
|
|
19269
|
-
class="strct-dg__pane-back"
|
|
19270
|
-
[attr.aria-label]="L().backToList"
|
|
19271
|
-
(click)="closePane()"
|
|
19272
|
-
>
|
|
19273
|
-
<strct-icon name="chevronLeft" [size]="13" />
|
|
19274
|
-
</button>
|
|
19275
|
-
}
|
|
19276
|
-
<span class="strct-dg__pane-title">
|
|
19277
|
-
<ng-content select="[strctDetailPaneTitle]" />
|
|
19278
|
-
@if (!paneTitleDef()) {
|
|
19279
|
-
{{ activeRow()![columns()[0].key] }}
|
|
19280
|
-
}
|
|
19281
|
-
</span>
|
|
19282
|
-
<span class="strct-dg__pane-meta">
|
|
19283
|
-
<ng-content select="[strctDetailPaneMeta]" />
|
|
19284
|
-
</span>
|
|
19285
|
-
<span class="strct-dg__pane-actions">
|
|
19286
|
-
<ng-content select="[strctDetailPaneActions]" />
|
|
19287
|
-
</span>
|
|
19288
|
-
<button
|
|
19289
|
-
type="button"
|
|
19290
|
-
class="strct-dg__pane-close"
|
|
19291
|
-
[attr.aria-label]="L().closeDetail"
|
|
19292
|
-
(click)="closePane()"
|
|
19293
|
-
>
|
|
19294
|
-
<strct-icon name="close" [size]="13" />
|
|
19295
|
-
</button>
|
|
19296
|
-
</div>
|
|
19297
|
-
<div class="strct-dg__pane-body">
|
|
19298
|
-
<ng-container
|
|
19299
|
-
[ngTemplateOutlet]="detailDef()!.template"
|
|
19300
|
-
[ngTemplateOutletContext]="{ $implicit: activeRow(), row: activeRow() }"
|
|
19301
|
-
/>
|
|
19302
|
-
</div>
|
|
19303
|
-
</aside>
|
|
19304
|
-
}
|
|
19305
|
-
</div>
|
|
19306
|
-
|
|
19307
|
-
@if (showFooter()) {
|
|
19308
|
-
<div class="strct-dg__foot">
|
|
19309
|
-
<div class="strct-dg__foot-left">
|
|
19310
|
-
@if (columnChooser() || sync()) {
|
|
19311
|
-
<div class="strct-dg__actions">
|
|
19312
|
-
<strct-button-group>
|
|
19313
|
-
@if (columnChooser()) {
|
|
19314
|
-
<button
|
|
19315
|
-
strct-button
|
|
19316
|
-
size="sm"
|
|
19317
|
-
[class.is-open]="chooserOpen()"
|
|
19318
|
-
[disabled]="footerActionsDisabled()"
|
|
19319
|
-
[attr.aria-label]="L().chooseColumns"
|
|
19320
|
-
(click)="toggleChooser($event)"
|
|
19321
|
-
>
|
|
19322
|
-
<strct-icon name="settings" [size]="16" />
|
|
19323
|
-
</button>
|
|
19324
|
-
}
|
|
19325
|
-
@if (sync()) {
|
|
19326
|
-
<button
|
|
19327
|
-
strct-button
|
|
19328
|
-
size="sm"
|
|
19329
|
-
[disabled]="footerActionsDisabled()"
|
|
19330
|
-
[attr.aria-label]="L().refresh"
|
|
19331
|
-
(click)="syncChange.emit()"
|
|
19332
|
-
>
|
|
19333
|
-
<strct-icon name="refresh" [size]="16" />
|
|
19334
|
-
</button>
|
|
19335
|
-
}
|
|
19336
|
-
</strct-button-group>
|
|
19337
|
-
@if (columnChooser() && chooserOpen()) {
|
|
19338
|
-
<div class="strct-dg__chooser-menu">
|
|
19339
|
-
@for (col of columns(); track col.key) {
|
|
19340
|
-
<!-- The whole row toggles; the checkbox's own click must not
|
|
19341
|
-
reach the row or the column would flip twice. -->
|
|
19342
|
-
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
19343
|
-
<div
|
|
19344
|
-
class="strct-dg__chooser-item"
|
|
19345
|
-
(click)="toggleColumn(col.key, hiddenColumns().has(col.key))"
|
|
19346
|
-
>
|
|
19347
|
-
<strct-checkbox
|
|
19348
|
-
[checked]="!hiddenColumns().has(col.key)"
|
|
19349
|
-
(checkedChange)="toggleColumn(col.key, $event)"
|
|
19350
|
-
(click)="$event.stopPropagation()"
|
|
19351
|
-
/>
|
|
19352
|
-
<span>{{ col.label }}</span>
|
|
19353
|
-
</div>
|
|
19354
|
-
}
|
|
19355
|
-
</div>
|
|
19356
|
-
}
|
|
19357
|
-
</div>
|
|
19358
|
-
}
|
|
19359
|
-
<span class="strct-dg__count">
|
|
19360
|
-
@if (paging() === 'more') {
|
|
19361
|
-
{{ L().showing(rows().length, moreTotal() ?? undefined) }}
|
|
19362
|
-
} @else {
|
|
19363
|
-
{{ totalCount() }} {{ totalCount() === 1 ? L().row : L().rows }}
|
|
19364
|
-
}
|
|
19365
|
-
@if (selectedCount() && mode() !== 'single') {
|
|
19366
|
-
<span class="strct-dg__count-sep">|</span>
|
|
19367
|
-
<span class="strct-dg__count-sel">{{ selectedCount() }} {{ L().selected }}</span>
|
|
19368
|
-
}
|
|
19369
|
-
</span>
|
|
19370
|
-
</div>
|
|
19371
|
-
<div class="strct-dg__foot-right">
|
|
19372
|
-
<!-- A feed that pages by cursor loads more at the end: page numbers
|
|
19373
|
-
are something a cursor API cannot answer. It takes the pager's
|
|
19374
|
-
place — the column chooser, the sync button and the count are
|
|
19375
|
-
the footer's, not the pager's. -->
|
|
19376
|
-
@if (paging() === 'more') {
|
|
19377
|
-
@if (hasMore()) {
|
|
19378
|
-
<button
|
|
19379
|
-
strct-button
|
|
19380
|
-
size="sm"
|
|
19381
|
-
class="strct-dg__more"
|
|
19382
|
-
[disabled]="loadingMore()"
|
|
19383
|
-
(click)="loadMore.emit()"
|
|
19384
|
-
>
|
|
19385
|
-
@if (loadingMore()) {
|
|
19386
|
-
<strct-spinner size="sm" />
|
|
19387
|
-
}
|
|
19388
|
-
{{ L().loadMore }}
|
|
19389
|
-
</button>
|
|
19390
|
-
}
|
|
19391
|
-
} @else if (pageSize() > 0 && !groupBy()) {
|
|
19392
|
-
<strct-pagination
|
|
19393
|
-
[total]="totalCount()"
|
|
19394
|
-
[pageSize]="pageSize()"
|
|
19395
|
-
[page]="page()"
|
|
19396
|
-
(pageChange)="goToPage($event)"
|
|
19397
|
-
/>
|
|
19398
|
-
}
|
|
19399
|
-
</div>
|
|
19400
|
-
</div>
|
|
19401
|
-
}
|
|
19402
|
-
`, host: {
|
|
17839
|
+
], host: {
|
|
19403
17840
|
class: 'strct-dg-host',
|
|
19404
17841
|
// The skeleton rows say "updating" to the eye; this says it to everyone else.
|
|
19405
17842
|
'[attr.aria-busy]': 'loading() || loadingMore() ? "true" : null',
|
|
@@ -19409,7 +17846,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
19409
17846
|
'[class.strct-dg-host--bounded]': '!virtual() && maxHeight() !== null',
|
|
19410
17847
|
'[class.strct-dg-host--sticky]': 'stickyActive()',
|
|
19411
17848
|
'[class.strct-dg-host--flush]': 'flush()',
|
|
19412
|
-
}, styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t2)}.strct-dg__bulk{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px 10px;padding:7px 12px;border-bottom:1px solid var(--b2);background:var(--acc-s);color:var(--t2);font-size:var(--text-md)}.strct-dg__announcer{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t2)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t2)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t2);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:var(--text-sm);font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__grouplabel--critical{color:var(--critical)}.strct-dg__grouplabel--warning{color:var(--warning)}.strct-dg__grouplabel--success{color:var(--success)}.strct-dg__grouplabel--accent{color:var(--acc)}.strct-dg__grouplabel--neutral,.strct-dg__grouplabel--none{color:var(--t1)}.strct-dg__groupnote{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);font-weight:400;color:var(--t2)}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:4px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg__groupcount--critical{background:var(--critical-bg);color:var(--critical)}.strct-dg__groupcount--warning{background:var(--warning-bg);color:var(--warning)}.strct-dg__groupcount--success{background:var(--success-bg);color:var(--success)}.strct-dg__groupcount--neutral,.strct-dg__groupcount--none{background:var(--bg-3);color:var(--t2)}.strct-dg-host--singleline .strct-dg{border-collapse:separate;border-spacing:0}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:4px;border-start-end-radius:4px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:4px;border-end-end-radius:4px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__sortbtn{display:inline-flex;align-items:center;gap:inherit;padding:0;border:0;background:none;color:inherit;font:inherit;text-transform:inherit;letter-spacing:inherit;text-align:inherit;cursor:pointer}.strct-dg__sortbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel .strct-cb,.strct-dg__sel .strct-dg__radio,.strct-dg__expandbtn{position:relative}.strct-dg__sel .strct-cb:after,.strct-dg__sel .strct-dg__radio:after,.strct-dg__expandbtn:after{content:\"\";position:absolute;inset:-11px -13px;min-width:24px;min-height:24px}.strct-dg-host--compact .strct-dg__sel .strct-cb:after,.strct-dg-host--compact .strct-dg__sel .strct-dg__radio:after,.strct-dg-host--compact .strct-dg__expandbtn:after{inset:-7px -11px}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned>.strct-dg__scroll{flex:0 0 auto;width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px)}.strct-dg__layout--paned>.strct-dg__scroll>.strct-dg{width:100%;min-width:0;max-width:none;flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__layout--panetakeover>.strct-dg__scroll{display:none}.strct-dg__layout--panetakeover>.strct-dg__pane{flex:1;min-width:0}.strct-dg__pane-meta,.strct-dg__pane-actions{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-dg__pane-meta:empty,.strct-dg__pane-actions:empty{display:none}.strct-dg__pane-actions{margin-inline-start:auto}.strct-dg__pane-back{display:inline-flex;align-items:center;border:0;background:none;color:var(--t2);cursor:pointer;padding:2px;border-radius:var(--radius-sm)}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:4px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t2);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:var(--text-sm);color:var(--t2);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:4px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:3px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:3px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{padding:5px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:var(--bg-2);color:var(--t1);font-family:var(--font);font-size:12px}.strct-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:var(--text-sm);cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"] }]
|
|
17849
|
+
}, template: "<!-- One polite region for everything the grid does to itself: sorting,\n paging and filtering all change the rows without saying so. -->\n<span class=\"strct-dg__announcer\" role=\"status\" aria-live=\"polite\">{{ announcement() }}</span>\n@if (actionBarDef() || quickFilterable() || actionBarCaptionDef()) {\n <div class=\"strct-dg__toolbar\">\n @if (quickFilterable()) {\n <strct-searchbox\n class=\"strct-dg__quickfilter\"\n [class.strct-dg__quickfilter--end]=\"quickFilterAlign() === 'end'\"\n [placeholder]=\"L().quickFilter\"\n [ariaLabel]=\"L().quickFilter\"\n [value]=\"quickFilter()\"\n (valueChange)=\"quickFilter.set($event)\"\n />\n @if (filterNote(); as note) {\n <span\n class=\"strct-dg__filternote\"\n [class.strct-dg__filternote--end]=\"quickFilterAlign() === 'end'\"\n >{{ note }}</span\n >\n }\n }\n <span class=\"strct-dg__actioncaption\">\n <ng-content select=\"[strctDatagridActionBarCaption]\" />\n </span>\n <ng-content select=\"[strctDatagridActionBar]\" />\n </div>\n}\n\n@if (hasEditableColumn()) {\n <!-- What the editable cells point at with aria-describedby: a keyboard\n user is told the cell can be edited, and how. -->\n <!-- In flow, not absolutely positioned: an out-of-flow box whose\n containing block is the page extends the document's scrollable area\n from wherever the grid happens to sit. 1x1 and clipped is enough. -->\n <span\n class=\"strct-sr-only\"\n style=\"\n display: inline-block;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n \"\n [id]=\"editHintId\"\n >{{ L().editCellInstructions }}</span\n >\n}\n\n@if (bulkHint(); as hint) {\n <!-- Selecting the page is not selecting the set. Say which one happened,\n and offer the other. -->\n <div class=\"strct-dg__bulk\" role=\"status\">\n <span>{{ hint.text }}</span>\n <button strct-button variant=\"flat\" size=\"sm\" (click)=\"hint.run()\">\n {{ hint.action }}\n </button>\n </div>\n}\n<div\n class=\"strct-dg__layout\"\n [class.strct-dg__layout--paned]=\"paneOpen()\"\n [class.strct-dg__layout--panetakeover]=\"paneOpen() && narrowPane()\"\n [style.--strct-dg-pane-list-w]=\"paneListWidth()\"\n>\n <div\n class=\"strct-dg__scroll\"\n tabindex=\"0\"\n role=\"region\"\n [attr.aria-label]=\"L().rows\"\n [style.max-height.px]=\"virtual() ? viewportHeight() : maxHeight()\"\n (scroll)=\"virtual() && onScroll($event)\"\n >\n <table\n class=\"strct-dg\"\n [attr.role]=\"childrenKey() ? 'treegrid' : gridMode() ? 'grid' : null\"\n [attr.aria-rowcount]=\"ariaRowCount()\"\n [attr.aria-labelledby]=\"caption() ? captionId : null\"\n >\n @if (caption()) {\n <caption class=\"strct-dg__caption\" [id]=\"captionId\">\n {{\n caption()\n }}\n </caption>\n }\n <thead>\n <tr>\n <!-- A utility column is still a column: axe reports every empty\n header, and a screen-reader user hears nothing where the\n detail, expand and select controls are. The name is hidden,\n not absent. -->\n @if (canDetail()) {\n <th\n class=\"strct-dg__expandcol\"\n scope=\"col\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('detail')\"\n >\n <span class=\"strct-sr-only\">{{ L().detailColumn }}</span>\n </th>\n }\n @if (canExpand()) {\n <th\n class=\"strct-dg__expandcol\"\n scope=\"col\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('expand')\"\n >\n <span class=\"strct-sr-only\">{{ L().expandColumn }}</span>\n </th>\n }\n @if (hasSelectionColumn()) {\n <th\n class=\"strct-dg__sel\"\n scope=\"col\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('sel')\"\n >\n @if (mode() === 'multiple') {\n <strct-checkbox\n [ariaLabel]=\"L().selectAll\"\n [checked]=\"allPageSelected()\"\n [indeterminate]=\"somePageSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n } @else {\n <span class=\"strct-sr-only\">{{ L().selectColumn }}</span>\n }\n </th>\n }\n @for (col of visibleColumns(); track col.key) {\n <th\n scope=\"col\"\n [style.text-align]=\"col.align ?? (col.numeric ? 'end' : 'start')\"\n [style.width]=\"colWidth(col.key) ?? col.width ?? null\"\n [class.strct-dg__th--sortable]=\"col.sortable\"\n [class.strct-dg__th--drop]=\"col.key === dropKey()\"\n [class.strct-dg__cell--sticky]=\"isSticky(col)\"\n [class.strct-dg__cell--sticky-last]=\"col.key === lastStickyKey()\"\n [style.insetInlineStart.px]=\"stickyLeft(col.key)\"\n [attr.data-col]=\"col.key\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n [attr.draggable]=\"reorderable() ? true : null\"\n (dragstart)=\"onColDragStart(col.key, $event)\"\n (dragover)=\"onColDragOver(col.key, $event)\"\n (drop)=\"onColDrop(col.key)\"\n (dragend)=\"onColDragEnd()\"\n >\n <span class=\"strct-dg__hd\">\n <!-- A header that sorts is a button: a th with tabindex is\n read as \"column header, focusable\" and never says it\n can be activated. aria-sort stays on the th, which is\n what carries the column's sorted state. -->\n @if (col.sortable) {\n <!-- The button covers most of the header, so it carries\n the drag source too: a reorderable column has to be\n grabbable where the pointer actually lands. The\n event bubbles to the th's own handlers. -->\n <button\n type=\"button\"\n class=\"strct-dg__sortbtn\"\n [attr.draggable]=\"reorderable() ? true : null\"\n (click)=\"sortBy(col.key)\"\n >\n {{ col.label }}\n <strct-icon class=\"strct-dg__sorticon\" [name]=\"sortIcon(col.key)\" [size]=\"13\" />\n </button>\n } @else {\n {{ col.label }}\n }\n @if (col.filterable || col.filterOptions) {\n <button\n #fbtn\n type=\"button\"\n class=\"strct-dg__filterbtn\"\n [class.strct-dg__filterbtn--active]=\"hasFilter(col.key)\"\n [attr.aria-expanded]=\"filterOpenKey() === col.key\"\n [attr.aria-label]=\"L().filterColumn + ': ' + col.label\"\n (click)=\"toggleFilterPanel(col.key, $event)\"\n (keydown.enter)=\"$event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n >\n <strct-icon name=\"filter\" [size]=\"12\" />\n </button>\n @if (filterOpenKey() === col.key) {\n <div\n class=\"strct-dg__filterpanel\"\n role=\"dialog\"\n [attr.aria-label]=\"L().filterColumn + ': ' + col.label\"\n [strctOverlay]=\"fbtn\"\n strctOverlayPlacement=\"bottom-start\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n >\n @if (col.filterOptions; as opts) {\n @for (opt of opts; track $index) {\n <label class=\"strct-dg__filteropt\">\n <input\n type=\"checkbox\"\n [checked]=\"optionChecked(col.key, opt)\"\n (change)=\"toggleFilterOption(col.key, opt)\"\n />\n <span>{{ opt }}</span>\n </label>\n }\n } @else {\n <input\n class=\"strct-dg__filterinput\"\n type=\"text\"\n [attr.placeholder]=\"L().filterPlaceholder\"\n [attr.aria-label]=\"L().filterColumn + ': ' + col.label\"\n [value]=\"textFilter(col.key)\"\n (input)=\"setTextFilter(col.key, $any($event.target).value)\"\n />\n }\n <button\n type=\"button\"\n class=\"strct-dg__filterclear\"\n [disabled]=\"!hasFilter(col.key)\"\n (click)=\"clearFilter(col.key)\"\n >\n {{ L().clearFilter }}\n </button>\n </div>\n }\n }\n </span>\n @if (resizable() && col.resizable !== false) {\n <!-- A separator, not a bare div: a column could only be\n resized with a mouse, which is the one input a\n console cannot assume. -->\n <div\n class=\"strct-dg__resize\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"L().resizeColumn(col.label)\"\n [attr.aria-valuenow]=\"separatorValue(col.key)\"\n [attr.aria-valuemin]=\"40\"\n (mousedown)=\"onResizeStart($event, col.key)\"\n (keydown)=\"onResizeKey($event, col.key)\"\n (dblclick)=\"resetWidth(col.key)\"\n ></div>\n }\n </th>\n }\n @if (canActions()) {\n <th class=\"strct-dg__actioncol\" scope=\"col\" [attr.aria-label]=\"L().actions\"></th>\n }\n </tr>\n </thead>\n <!--\n focusin is the real keyboard path (focus does not bubble from cells);\n the plain focus binding exists to satisfy mouse-events-have-key-events.\n -->\n <tbody\n (mouseover)=\"revealIfClipped($event)\"\n (focusin)=\"revealIfClipped($event)\"\n (focus)=\"revealIfClipped($event)\"\n >\n @if (loading()) {\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\n <tr class=\"strct-dg__skeleton-row\">\n @if (canDetail()) {\n <td class=\"strct-dg__expandcell\"></td>\n }\n @if (canExpand()) {\n <td class=\"strct-dg__expandcell\"></td>\n }\n @if (hasSelectionColumn()) {\n <td class=\"strct-dg__sel\"></td>\n }\n @for (col of visibleColumns(); track col.key) {\n <td [style.text-align]=\"col.align ?? 'start'\">\n <div class=\"strct-dg__skeleton-block\"></div>\n </td>\n }\n @if (canActions()) {\n <td class=\"strct-dg__actioncell\"></td>\n }\n </tr>\n }\n } @else {\n @if (virtual() && topPad() > 0) {\n <tr class=\"strct-dg__vspacer\" aria-hidden=\"true\">\n <td [attr.colspan]=\"colspan()\" [style.height.px]=\"topPad()\"></td>\n </tr>\n }\n @for (it of displayItems(); track itemKey(it)) {\n @if (it.group; as grp) {\n <!-- Group header: distinct value + count, collapsible. -->\n <tr class=\"strct-dg__grouprow\">\n @if (groupSelect() && mode() === 'multiple') {\n <td class=\"strct-dg__sel\">\n <strct-checkbox\n [ariaLabel]=\"L().selectAllInGroup(grp.label)\"\n [checked]=\"groupAllSelected(grp.key)\"\n [indeterminate]=\"groupSomeSelected(grp.key)\"\n (checkedChange)=\"toggleGroupSelection(grp.key)\"\n />\n </td>\n }\n <td\n [attr.colspan]=\"\n groupSelect() && mode() === 'multiple' ? colspan() - 1 : colspan()\n \"\n >\n <button\n type=\"button\"\n class=\"strct-dg__groupbtn\"\n [attr.aria-expanded]=\"!grp.collapsed\"\n (click)=\"toggleGroup(grp.key)\"\n >\n <span\n class=\"strct-dg__groupchev\"\n [class.strct-dg__groupchev--open]=\"!grp.collapsed\"\n >\n <strct-icon name=\"chevronRight\" [size]=\"12\" [strokeWidth]=\"1.7\" />\n </span>\n @if (groupHeaderDef(); as tpl) {\n <!-- The consumer draws the row; the button, its\n aria-expanded and the keyboard stay ours. -->\n <ng-container\n [ngTemplateOutlet]=\"tpl.template\"\n [ngTemplateOutletContext]=\"{\n $implicit: grp,\n group: grp,\n count: grp.count,\n }\"\n />\n } @else {\n <span\n class=\"strct-dg__grouplabel strct-dg__grouplabel--{{\n grp.status ?? 'none'\n }}\"\n >{{ grp.label }}</span\n >\n <!-- The three spans run together in the button's\n name (\"Needs your decision1Blocks the join\u2026\");\n the separators are read, not seen. -->\n <span class=\"strct-dg__announcer\">, </span>\n <span\n class=\"strct-dg__groupcount strct-dg__groupcount--{{\n grp.status ?? 'none'\n }}\"\n >{{ grp.count }}</span\n >\n <!-- Seen: the chip's number. Heard: the number with\n the grid's noun, because \"Inconclusive, 3\" does\n not say three of what. -->\n <span class=\"strct-dg__announcer\"> {{ countNoun(grp.count) }}</span>\n @if (grp.note) {\n <span class=\"strct-dg__announcer\">. </span>\n <span class=\"strct-dg__groupnote\">{{ grp.note }}</span>\n }\n }\n </button>\n </td>\n </tr>\n } @else {\n @let row = it.row!;\n <tr\n [attr.aria-rowindex]=\"ariaRowIndex(row)\"\n [class.strct-dg__row--selected]=\"isSelected(row)\"\n [class.strct-dg__row--locked]=\"lockedReason(row) !== null\"\n [attr.aria-selected]=\"mode() === 'none' ? null : isSelected(row)\"\n [attr.aria-disabled]=\"lockedReason(row) !== null ? 'true' : null\"\n [attr.title]=\"lockedReason(row) || null\"\n (click)=\"onRowPick(row)\"\n [class.strct-dg__row--active]=\"paneOpen() && row === activeRow()\"\n [attr.aria-level]=\"childrenKey() ? treeDepth(row) + 1 : null\"\n [attr.aria-expanded]=\"\n childrenKey() && treeHasChildren(row) ? treeExpanded(row) : null\n \"\n [attr.tabindex]=\"\n childrenKey()\n ? treeRowTabindex(row)\n : gridMode()\n ? gridRowTabindex(row)\n : canDetail()\n ? paneRowTabindex(row)\n : null\n \"\n (keydown)=\"\n childrenKey()\n ? onTreeRowKeydown(row, $event)\n : gridMode()\n ? onGridRowKeydown(row, $event)\n : onPaneRowKeydown(row, $event)\n \"\n (dblclick)=\"onRowActivate(row)\"\n >\n @if (canDetail()) {\n <td\n class=\"strct-dg__expandcell\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('detail')\"\n >\n <button\n type=\"button\"\n [attr.tabindex]=\"ctlTabindex()\"\n class=\"strct-dg__detailbtn\"\n [class.strct-dg__detailbtn--active]=\"row === activeRow()\"\n [attr.aria-expanded]=\"row === activeRow()\"\n [attr.aria-label]=\"L().openDetail\"\n (click)=\"openDetail(row)\"\n >\n <strct-icon name=\"chevronDoubleRight\" [size]=\"13\" [strokeWidth]=\"1.6\" />\n </button>\n </td>\n }\n @if (canExpand()) {\n <td\n class=\"strct-dg__expandcell\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('expand')\"\n >\n <button\n type=\"button\"\n [attr.tabindex]=\"ctlTabindex()\"\n class=\"strct-dg__expandbtn\"\n [class.strct-dg__expandbtn--open]=\"isExpanded(row)\"\n [attr.aria-expanded]=\"isExpanded(row)\"\n [attr.aria-label]=\"L().toggleDetail\"\n (click)=\"toggleExpand(row)\"\n >\n <strct-icon name=\"chevronRight\" [size]=\"12\" [strokeWidth]=\"1.7\" />\n </button>\n </td>\n }\n @if (hasSelectionColumn()) {\n <td\n class=\"strct-dg__sel\"\n [class.strct-dg__cell--sticky]=\"stickyActive()\"\n [style.insetInlineStart.px]=\"utilLeft('sel')\"\n >\n @if (mode() === 'single') {\n <!-- A native radio group: one name per grid, so the\n arrow keys move between rows and Space picks,\n without the grid inventing its own keyboarding. -->\n <input\n type=\"radio\"\n class=\"strct-dg__radio\"\n [name]=\"radioName\"\n [attr.aria-label]=\"selectRowLabel(row)\"\n [attr.aria-description]=\"lockedReason(row) || null\"\n [checked]=\"isSelected(row)\"\n [disabled]=\"lockedReason(row) !== null\"\n [attr.tabindex]=\"ctlTabindex()\"\n (change)=\"selectSingle(row)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else {\n <!-- click fires (and bubbles) before the input's change,\n so the modifier is recorded by the time toggleRow runs. -->\n <strct-checkbox\n [ariaLabel]=\"selectRowLabel(row)\"\n [attr.aria-description]=\"lockedReason(row) || null\"\n [checked]=\"isSelected(row)\"\n [disabled]=\"lockedReason(row) !== null\"\n [tabIndex]=\"ctlTabindex()\"\n (click)=\"noteRangeIntent($event); $event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row)\"\n />\n }\n </td>\n }\n @for (col of visibleColumns(); track col.key; let colIdx = $index) {\n <td\n [style.text-align]=\"col.align ?? (col.numeric ? 'end' : 'start')\"\n [class.strct-dg__cell--mono]=\"col.mono\"\n [class.strct-dg__cell--muted]=\"col.muted\"\n [class.strct-dg__cell--numeric]=\"col.numeric\"\n [class.strct-dg__cell--sticky]=\"isSticky(col)\"\n [class.strct-dg__cell--sticky-last]=\"col.key === lastStickyKey()\"\n [class.strct-dg__cell--editable]=\"col.editable\"\n [style.insetInlineStart.px]=\"stickyLeft(col.key)\"\n [attr.data-edit]=\"col.editable ? '' : null\"\n [attr.tabindex]=\"col.editable ? editCellTabindex(row, col) : null\"\n [attr.aria-describedby]=\"col.editable ? editHintId : null\"\n (dblclick)=\"col.editable && startEdit(row, col)\"\n (focus)=\"col.editable && onEditCellFocus(row, col)\"\n (keydown)=\"col.editable && onEditCellKeydown(row, col, $event)\"\n >\n @if (childrenKey() && colIdx === 0) {\n <span\n class=\"strct-dg__treepad\"\n [style.width.px]=\"treeDepth(row) * 18\"\n aria-hidden=\"true\"\n ></span>\n @if (treeHasChildren(row)) {\n <button\n type=\"button\"\n class=\"strct-dg__treebtn\"\n [class.strct-dg__treebtn--open]=\"treeExpanded(row)\"\n [attr.aria-expanded]=\"treeExpanded(row)\"\n [attr.aria-label]=\"L().toggleChildren\"\n (click)=\"toggleTreeRow(row)\"\n >\n <strct-icon name=\"chevronRight\" [size]=\"12\" [strokeWidth]=\"1.7\" />\n </button>\n } @else {\n <span\n class=\"strct-dg__treebtn strct-dg__treebtn--leaf\"\n aria-hidden=\"true\"\n ></span>\n }\n }\n @if (isEditingCell(row, col)) {\n @switch (col.editor ?? 'text') {\n @case ('select') {\n <!-- Choosing is the commit: there is nothing to\n confirm with Enter once an option is picked. -->\n <strct-select\n class=\"strct-dg__editselect\"\n [options]=\"editorOptionsFor(row, col)\"\n [listLabel]=\"L().editCell + ': ' + col.label\"\n [ngModel]=\"row[col.key]\"\n (ngModelChange)=\"commitValue(row, col, $event)\"\n (keydown.escape)=\"cancelEdit($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n @case ('number') {\n <strct-number\n class=\"strct-dg__editnumber\"\n [ariaLabel]=\"L().editCell + ': ' + col.label\"\n [min]=\"col.editorMin ?? null\"\n [max]=\"col.editorMax ?? null\"\n [step]=\"col.editorStep ?? 1\"\n [ngModel]=\"row[col.key]\"\n (ngModelChange)=\"editDraft.set($event)\"\n (keydown.enter)=\"commitDraft(row, col, $event)\"\n (keydown.escape)=\"cancelEdit($event)\"\n (focusout)=\"commitOnLeave(row, col, $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n @default {\n <input\n class=\"strct-dg__editinput\"\n type=\"text\"\n [value]=\"row[col.key] ?? ''\"\n [attr.aria-label]=\"L().editCell + ': ' + col.label\"\n (keydown.enter)=\"commitEdit(row, col, $event)\"\n (keydown.escape)=\"cancelEdit($event)\"\n (blur)=\"commitEdit(row, col, $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n }\n } @else if (cellTemplate(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n row,\n value: row[col.key],\n column: col,\n }\"\n />\n } @else if (isBlank(row, col)) {\n <span class=\"strct-dg__empty\" [attr.aria-label]=\"col.emptyLabel || null\">{{\n col.emptyText\n }}</span>\n } @else {\n {{ displayValue(row, col) }}\n @if (col.descriptionKey && row[col.descriptionKey]) {\n <span class=\"strct-dg__celldesc\">{{ row[col.descriptionKey] }}</span>\n }\n }\n <!-- The affordance a mouse never needed: a cell that\n can be edited says so on hover and on focus. -->\n @if (col.editable && editHint() && !isEditingCell(row, col)) {\n <strct-icon\n class=\"strct-dg__editpencil\"\n name=\"pencil\"\n [size]=\"12\"\n [strokeWidth]=\"1.6\"\n aria-hidden=\"true\"\n />\n }\n </td>\n }\n @if (canActions()) {\n <td class=\"strct-dg__actioncell\">\n <button\n type=\"button\"\n [attr.tabindex]=\"ctlTabindex()\"\n class=\"strct-dg__kebab\"\n [attr.aria-label]=\"L().rowActions\"\n (click)=\"openRowMenu(row, $event)\"\n >\n <strct-icon name=\"dots\" [size]=\"16\" />\n </button>\n </td>\n }\n </tr>\n @if (canExpand() && isExpanded(row)) {\n <tr class=\"strct-dg__detailrow\">\n <td [attr.colspan]=\"colspan()\">\n <div class=\"strct-dg__detail\">\n <ng-container\n [ngTemplateOutlet]=\"detailDef()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: row, row }\"\n />\n </div>\n </td>\n </tr>\n }\n }\n } @empty {\n <!-- \"Nothing here\" and \"nothing matches what you typed\" are\n different states: the second one can be undone, and\n saying so is the whole point. -->\n <tr>\n <td class=\"strct-dg__emptyrow\" [attr.colspan]=\"colspan()\">\n @if (filteredAway()) {\n <strct-empty-state\n size=\"sm\"\n [titleLevel]=\"null\"\n [title]=\"L().noMatches\"\n [description]=\"noMatchesDescription()\"\n >\n <button strct-button variant=\"flat\" size=\"sm\" (click)=\"clearAllFilters()\">\n {{ L().clearFilters }}\n </button>\n </strct-empty-state>\n } @else {\n <!-- Not a heading: a grid is a region of a page, and an\n empty one used to put an <h3> in its outline. -->\n <strct-empty-state size=\"sm\" [titleLevel]=\"null\" [title]=\"emptyText()\" />\n }\n </td>\n </tr>\n }\n @if (virtual() && bottomPad() > 0) {\n <tr class=\"strct-dg__vspacer\" aria-hidden=\"true\">\n <td [attr.colspan]=\"colspan()\" [style.height.px]=\"bottomPad()\"></td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (paneOpen()) {\n <aside class=\"strct-dg__pane\">\n <div class=\"strct-dg__pane-head\">\n @if (narrowPane()) {\n <!-- The pane has taken the list's place, so there is a way back. -->\n <button\n type=\"button\"\n class=\"strct-dg__pane-back\"\n [attr.aria-label]=\"L().backToList\"\n (click)=\"closePane()\"\n >\n <strct-icon name=\"chevronLeft\" [size]=\"13\" />\n </button>\n }\n <span class=\"strct-dg__pane-title\">\n <ng-content select=\"[strctDetailPaneTitle]\" />\n @if (!paneTitleDef()) {\n {{ activeRow()![columns()[0].key] }}\n }\n </span>\n <span class=\"strct-dg__pane-meta\">\n <ng-content select=\"[strctDetailPaneMeta]\" />\n </span>\n <span class=\"strct-dg__pane-actions\">\n <ng-content select=\"[strctDetailPaneActions]\" />\n </span>\n <button\n type=\"button\"\n class=\"strct-dg__pane-close\"\n [attr.aria-label]=\"L().closeDetail\"\n (click)=\"closePane()\"\n >\n <strct-icon name=\"close\" [size]=\"13\" />\n </button>\n </div>\n <div class=\"strct-dg__pane-body\">\n <ng-container\n [ngTemplateOutlet]=\"detailDef()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: activeRow(), row: activeRow() }\"\n />\n </div>\n </aside>\n }\n</div>\n\n@if (showFooter()) {\n <div class=\"strct-dg__foot\">\n <div class=\"strct-dg__foot-left\">\n @if (columnChooser() || sync()) {\n <div class=\"strct-dg__actions\">\n <strct-button-group>\n @if (columnChooser()) {\n <button\n strct-button\n size=\"sm\"\n [class.is-open]=\"chooserOpen()\"\n [disabled]=\"footerActionsDisabled()\"\n [attr.aria-label]=\"L().chooseColumns\"\n (click)=\"toggleChooser($event)\"\n >\n <strct-icon name=\"settings\" [size]=\"16\" />\n </button>\n }\n @if (sync()) {\n <button\n strct-button\n size=\"sm\"\n [disabled]=\"footerActionsDisabled()\"\n [attr.aria-label]=\"L().refresh\"\n (click)=\"syncChange.emit()\"\n >\n <strct-icon name=\"refresh\" [size]=\"16\" />\n </button>\n }\n </strct-button-group>\n @if (columnChooser() && chooserOpen()) {\n <div class=\"strct-dg__chooser-menu\">\n @for (col of columns(); track col.key) {\n <!-- The whole row toggles; the checkbox's own click must not\n reach the row or the column would flip twice. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"strct-dg__chooser-item\"\n (click)=\"toggleColumn(col.key, hiddenColumns().has(col.key))\"\n >\n <strct-checkbox\n [checked]=\"!hiddenColumns().has(col.key)\"\n (checkedChange)=\"toggleColumn(col.key, $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n <span>{{ col.label }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n <span class=\"strct-dg__count\">\n @if (paging() === 'more') {\n {{ L().showing(rows().length, moreTotal() ?? undefined) }}\n } @else {\n {{ totalCount() }} {{ totalCount() === 1 ? L().row : L().rows }}\n }\n @if (selectedCount() && mode() !== 'single') {\n <span class=\"strct-dg__count-sep\">|</span>\n <span class=\"strct-dg__count-sel\">{{ selectedCount() }} {{ L().selected }}</span>\n }\n </span>\n </div>\n <div class=\"strct-dg__foot-right\">\n <!-- A feed that pages by cursor loads more at the end: page numbers\n are something a cursor API cannot answer. It takes the pager's\n place \u2014 the column chooser, the sync button and the count are\n the footer's, not the pager's. -->\n @if (paging() === 'more') {\n @if (hasMore()) {\n <button\n strct-button\n size=\"sm\"\n class=\"strct-dg__more\"\n [disabled]=\"loadingMore()\"\n (click)=\"loadMore.emit()\"\n >\n @if (loadingMore()) {\n <strct-spinner size=\"sm\" />\n }\n {{ L().loadMore }}\n </button>\n }\n } @else if (pageSize() > 0 && !groupBy()) {\n <strct-pagination\n [total]=\"totalCount()\"\n [pageSize]=\"pageSize()\"\n [page]=\"page()\"\n (pageChange)=\"goToPage($event)\"\n />\n }\n </div>\n </div>\n}\n", styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t2)}.strct-dg__bulk{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px 10px;padding:7px 12px;border-bottom:1px solid var(--b2);background:var(--acc-s);color:var(--t2);font-size:var(--text-md)}.strct-dg__announcer{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t2)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t2)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t2);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:var(--text-sm);font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__grouplabel--critical{color:var(--critical)}.strct-dg__grouplabel--warning{color:var(--warning)}.strct-dg__grouplabel--success{color:var(--success)}.strct-dg__grouplabel--accent{color:var(--acc)}.strct-dg__grouplabel--neutral,.strct-dg__grouplabel--none{color:var(--t1)}.strct-dg__groupnote{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);font-weight:400;color:var(--t2)}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:4px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg__groupcount--critical{background:var(--critical-bg);color:var(--critical)}.strct-dg__groupcount--warning{background:var(--warning-bg);color:var(--warning)}.strct-dg__groupcount--success{background:var(--success-bg);color:var(--success)}.strct-dg__groupcount--neutral,.strct-dg__groupcount--none{background:var(--bg-3);color:var(--t2)}.strct-dg-host--singleline .strct-dg{border-collapse:separate;border-spacing:0}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:4px;border-start-end-radius:4px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:4px;border-end-end-radius:4px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__sortbtn{display:inline-flex;align-items:center;gap:inherit;padding:0;border:0;background:none;color:inherit;font:inherit;text-transform:inherit;letter-spacing:inherit;text-align:inherit;cursor:pointer}.strct-dg__sortbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--selected td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody tr.strct-dg__row--selected:hover td{background:linear-gradient(var(--acc-s),var(--acc-s)),linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel .strct-cb,.strct-dg__sel .strct-dg__radio,.strct-dg__expandbtn{position:relative}.strct-dg__sel .strct-cb:after,.strct-dg__sel .strct-dg__radio:after,.strct-dg__expandbtn:after{content:\"\";position:absolute;inset:-11px -13px;min-width:24px;min-height:24px}.strct-dg-host--compact .strct-dg__sel .strct-cb:after,.strct-dg-host--compact .strct-dg__sel .strct-dg__radio:after,.strct-dg-host--compact .strct-dg__expandbtn:after{inset:-7px -11px}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned>.strct-dg__scroll{flex:0 0 auto;width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px)}.strct-dg__layout--paned>.strct-dg__scroll>.strct-dg{width:100%;min-width:0;max-width:none;flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__layout--panetakeover>.strct-dg__scroll{display:none}.strct-dg__layout--panetakeover>.strct-dg__pane{flex:1;min-width:0}.strct-dg__pane-meta,.strct-dg__pane-actions{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-dg__pane-meta:empty,.strct-dg__pane-actions:empty{display:none}.strct-dg__pane-actions{margin-inline-start:auto}.strct-dg__pane-back{display:inline-flex;align-items:center;border:0;background:none;color:var(--t2);cursor:pointer;padding:2px;border-radius:var(--radius-sm)}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg tbody .strct-dg__row--active td{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:4px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t2);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:var(--text-sm);color:var(--t2);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:4px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:3px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:3px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{padding:5px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:var(--bg-2);color:var(--t1);font-family:var(--font);font-size:12px}.strct-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:var(--text-sm);cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:2px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"] }]
|
|
19413
17850
|
}], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], pageSizeFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], selectableFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], detailPaneFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailPane", required: false }] }], paneListWidthFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "paneListWidth", required: false }] }], paneTakeoverWidthFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "paneTakeoverWidth", required: false }] }], activeRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeRowId", required: false }] }, { type: i0.Output, args: ["activeRowIdChange"] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], singleLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleLine", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], columnChooser: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnChooser", required: false }] }], syncFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "sync", required: false }] }], footerActionsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerActionsDisabled", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], selectionModeFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }, { type: i0.Output, args: ["selectedIdChange"] }], rowSelectableFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowSelectable", required: false }] }], flush: [{ type: i0.Input, args: [{ isSignal: true, alias: "flush", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], hasMoreFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], loadingMoreFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMore", required: false }] }], moreTotalFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreTotal", required: false }] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], groupSelectFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupSelect", required: false }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], initialSelectionFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSelection", required: false }] }], selectedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIds", required: false }] }, { type: i0.Output, args: ["selectedIdsChange"] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], viewportHeightFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewportHeight", required: false }] }], maxHeightFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], editHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "editHint", required: false }] }], rowHeightFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], lazyFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], stateKeyFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], columnState: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnState", required: false }] }, { type: i0.Output, args: ["columnStateChange"] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], groupByFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], groupsFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], showEmptyGroupsFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEmptyGroups", required: false }] }], collapsedGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedGroups", required: false }] }, { type: i0.Output, args: ["collapsedGroupsChange"] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], quickFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilter", required: false }] }, { type: i0.Output, args: ["quickFilterChange"] }], quickFilterFieldsFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterFields", required: false }] }], quickFilterableFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterable", required: false }] }], quickFilterAlignFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterAlign", required: false }] }], childrenKeyFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "childrenKey", required: false }] }], interactionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactionMode", required: false }] }], selectionColumnFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionColumn", required: false }] }], rowActivate: [{ type: i0.Output, args: ["rowActivate"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], syncChange: [{ type: i0.Output, args: ["syncChange"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], selectionCfg: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], paneFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "pane", required: false }] }], pagingFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "paging", required: false }] }], virtualFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtual", required: false }] }], groupingCfg: [{ type: i0.Input, args: [{ isSignal: true, alias: "grouping", required: false }] }], filteringCfg: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtering", required: false }] }], stateCfg: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], detailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctRowDetailDef), { isSignal: true }] }], groupHeaderDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctGroupHeaderDef), { isSignal: true }] }], paneTitleDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDetailPaneTitle), { isSignal: true }] }], actionBarDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBar), { isSignal: true }] }], actionBarCaptionDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBarCaption), { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }], onDocClickOverlays: [{
|
|
19414
17851
|
type: HostListener,
|
|
19415
17852
|
args: ['document:click', ['$event']]
|
|
@@ -32185,5 +30622,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
32185
30622
|
* Generated bundle index. Do not edit.
|
|
32186
30623
|
*/
|
|
32187
30624
|
|
|
32188
|
-
export { FOCUSABLE_SELECTOR, STRCT_DP_DOW, STRCT_DP_DOW_FULL, STRCT_DP_MONTHS, STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_ICON_NAMES, STRCT_MASKS, STRCT_MD_LIMITS, STRCT_NOTIFICATION_HISTORY_LIMIT, STRCT_PALETTES, STRCT_RAW_ICONS, STRCT_TIME_RANGE_PRESETS, STRCT_WIZARD_DEFAULTS, StrctAccordion, StrctAccordionPanel, StrctAccordionPanelMeta, StrctAlert, StrctAlertActions, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCardHeaderActions, StrctCardHeaderLeading, StrctCardHeaderMeta, StrctCardHeaderNote, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChange, StrctChart, StrctChatAttachment, StrctChatComposer, StrctChatMessage, StrctChatMessageActions, StrctChatThread, StrctCheckbox, StrctChips, StrctCode, StrctCodeInline, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctConfirmOutlet, StrctConfirmService, StrctContextMenu, StrctContextMenuTrigger, StrctControlDescription, StrctCopy, StrctDatagrid, StrctDatagridActionBar, StrctDatagridActionBarCaption, StrctDatepicker, StrctDatetimePicker, StrctDesc, StrctDescriptionList, StrctDetailPaneActions, StrctDetailPaneMeta, StrctDetailPaneTitle, StrctDiff, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownGroup, StrctDropdownItem, StrctDropdownItemAction, StrctDropdownItemDescription, StrctDropdownItemIcon, StrctDropdownItemLabel, StrctDropdownTrigger, StrctDurationPipe, StrctEmptyState, StrctField, StrctFieldGroup, StrctFieldHint, StrctFieldPrefix, StrctFieldSuffix, StrctFieldValue, StrctFile, StrctFilterBar, StrctFlow, StrctFlowNodeTemplate, StrctFooter, StrctGauge, StrctGroupHeaderDef, StrctHeader, StrctHeaderAction, StrctHeatmap, StrctHero, StrctHotkeysHelp, StrctHotkeysService, StrctIcon, StrctInlineEdit, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLegend, StrctList, StrctListItem, StrctListItemDescription, StrctListItemLeading, StrctListItemMeta, StrctListItemTrailing, StrctLiveIndicator, StrctLogViewer, StrctLogin, StrctMarkdown, StrctMarkdownToken, StrctMediaFrame, StrctMenuPanel, StrctMenuService, StrctMenubar, StrctMetricTile, StrctModal, StrctModalContent, StrctNav, StrctNavItem, StrctNotificationCenter, StrctNumber, StrctOverlay, StrctPageHeader, StrctPageHeaderActions, StrctPageHeaderCrumbs, StrctPageHeaderTitleMeta, StrctPagination, StrctPassword, StrctPopover, StrctPopoverTrigger, StrctProductSwitcher, StrctProgress, StrctQr, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRatePipe, StrctRating, StrctReorder, StrctReorderGroup, StrctReorderHandle, StrctReorderItem, StrctResizeHandle, StrctRowDetailDef, StrctSearchbox, StrctSectionHeader, StrctSectionHeaderActions, StrctSectionHeaderMeta, StrctSectionMenu, StrctSegmented, StrctSelect, StrctShell, StrctShellService, StrctSiPipe, StrctSignpost, StrctSignpostTrigger, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctSplitButton, StrctSplitter, StrctStack, StrctStackItem, StrctStatusDot, StrctStep, StrctStepAction, StrctSteps, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctTagLeading, StrctThemeService, StrctThemeSwitcher, StrctTimeRangePicker, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctToolbar, StrctToolbarCaption, StrctToolbarSpacer, StrctTooltip, StrctTour, StrctTransfer, StrctTree, StrctTreeNode, StrctTreeSelect, StrctVerticalNav, StrctWatermark, StrctWindow, StrctWindowDock, StrctWindowDockItem, StrctWindowService, StrctWizard, StrctWizardAside, __qrInternals, defaultStateWords, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, parseInlines, placeTooltip, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctCheckHostDisplay, strctCheckHostInputs, strctClassifyHref, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctParseMarkdown, strctQrMatrix, strctShowTooltip, strctValidationIcon, strctValidationTone, unlockBodyScroll };
|
|
30625
|
+
export { DG_LABELS, FOCUSABLE_SELECTOR, STRCT_DP_DOW, STRCT_DP_DOW_FULL, STRCT_DP_MONTHS, STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_ICON_NAMES, STRCT_MASKS, STRCT_MD_LIMITS, STRCT_NOTIFICATION_HISTORY_LIMIT, STRCT_PALETTES, STRCT_RAW_ICONS, STRCT_TIME_RANGE_PRESETS, STRCT_WIZARD_DEFAULTS, StrctAccordion, StrctAccordionPanel, StrctAccordionPanelMeta, StrctAlert, StrctAlertActions, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCardHeaderActions, StrctCardHeaderLeading, StrctCardHeaderMeta, StrctCardHeaderNote, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChange, StrctChart, StrctChatAttachment, StrctChatComposer, StrctChatMessage, StrctChatMessageActions, StrctChatThread, StrctCheckbox, StrctChips, StrctCode, StrctCodeInline, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctConfirmOutlet, StrctConfirmService, StrctContextMenu, StrctContextMenuTrigger, StrctControlDescription, StrctCopy, StrctDatagrid, StrctDatagridActionBar, StrctDatagridActionBarCaption, StrctDatepicker, StrctDatetimePicker, StrctDesc, StrctDescriptionList, StrctDetailPaneActions, StrctDetailPaneMeta, StrctDetailPaneTitle, StrctDiff, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownGroup, StrctDropdownItem, StrctDropdownItemAction, StrctDropdownItemDescription, StrctDropdownItemIcon, StrctDropdownItemLabel, StrctDropdownTrigger, StrctDurationPipe, StrctEmptyState, StrctField, StrctFieldGroup, StrctFieldHint, StrctFieldPrefix, StrctFieldSuffix, StrctFieldValue, StrctFile, StrctFilterBar, StrctFlow, StrctFlowNodeTemplate, StrctFooter, StrctGauge, StrctGroupHeaderDef, StrctHeader, StrctHeaderAction, StrctHeatmap, StrctHero, StrctHotkeysHelp, StrctHotkeysService, StrctIcon, StrctInlineEdit, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLegend, StrctList, StrctListItem, StrctListItemDescription, StrctListItemLeading, StrctListItemMeta, StrctListItemTrailing, StrctLiveIndicator, StrctLogViewer, StrctLogin, StrctMarkdown, StrctMarkdownToken, StrctMediaFrame, StrctMenuPanel, StrctMenuService, StrctMenubar, StrctMetricTile, StrctModal, StrctModalContent, StrctNav, StrctNavItem, StrctNotificationCenter, StrctNumber, StrctOverlay, StrctPageHeader, StrctPageHeaderActions, StrctPageHeaderCrumbs, StrctPageHeaderTitleMeta, StrctPagination, StrctPassword, StrctPopover, StrctPopoverTrigger, StrctProductSwitcher, StrctProgress, StrctQr, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRatePipe, StrctRating, StrctReorder, StrctReorderGroup, StrctReorderHandle, StrctReorderItem, StrctResizeHandle, StrctRowDetailDef, StrctSearchbox, StrctSectionHeader, StrctSectionHeaderActions, StrctSectionHeaderMeta, StrctSectionMenu, StrctSegmented, StrctSelect, StrctShell, StrctShellService, StrctSiPipe, StrctSignpost, StrctSignpostTrigger, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctSplitButton, StrctSplitter, StrctStack, StrctStackItem, StrctStatusDot, StrctStep, StrctStepAction, StrctSteps, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctTagLeading, StrctThemeService, StrctThemeSwitcher, StrctTimeRangePicker, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctToolbar, StrctToolbarCaption, StrctToolbarSpacer, StrctTooltip, StrctTour, StrctTransfer, StrctTree, StrctTreeNode, StrctTreeSelect, StrctVerticalNav, StrctWatermark, StrctWindow, StrctWindowDock, StrctWindowDockItem, StrctWindowService, StrctWizard, StrctWizardAside, __qrInternals, defaultStateWords, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, parseInlines, placeTooltip, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctCheckHostDisplay, strctCheckHostInputs, strctClassifyHref, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctParseMarkdown, strctQrMatrix, strctShowTooltip, strctValidationIcon, strctValidationTone, unlockBodyScroll };
|
|
32189
30626
|
//# sourceMappingURL=akcelik-strct.mjs.map
|