@akcelik/strct 5.33.0 → 6.0.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 +71 -427
- package/fesm2022/akcelik-strct.mjs.map +1 -1
- package/package.json +1 -1
- package/types/akcelik-strct.d.ts +38 -152
|
@@ -640,8 +640,7 @@ class StrctIcon {
|
|
|
640
640
|
...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
|
|
641
641
|
/**
|
|
642
642
|
* A mode the operator chose, drawn in its own (top-end) corner so it never
|
|
643
|
-
* displaces the health badge.
|
|
644
|
-
* `mode="maintenance"`, which is where it belongs; it is deprecated.
|
|
643
|
+
* displaces the health badge.
|
|
645
644
|
*/
|
|
646
645
|
mode = input('none', /* @ts-ignore */
|
|
647
646
|
...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
@@ -686,19 +685,11 @@ class StrctIcon {
|
|
|
686
685
|
/** 1.2em of the icon size, floored at 14px, as the badge's box. */
|
|
687
686
|
countFontSize = computed(() => Math.max(9, Math.round(this.size() * 0.58)), /* @ts-ignore */
|
|
688
687
|
...(ngDevMode ? [{ debugName: "countFontSize" }] : /* istanbul ignore next */ []));
|
|
689
|
-
/**
|
|
690
|
-
|
|
691
|
-
* there was a mode (back-compat — the amber disc read as `paused` at 16px).
|
|
692
|
-
*/
|
|
693
|
-
shownMode = computed(() => {
|
|
694
|
-
const mode = this.mode();
|
|
695
|
-
if (mode !== 'none')
|
|
696
|
-
return mode;
|
|
697
|
-
return this.badge() === 'maintenance' ? 'maintenance' : 'none';
|
|
698
|
-
}, /* @ts-ignore */
|
|
688
|
+
/** The mode as drawn. */
|
|
689
|
+
shownMode = computed(() => this.mode(), /* @ts-ignore */
|
|
699
690
|
...(ngDevMode ? [{ debugName: "shownMode" }] : /* istanbul ignore next */ []));
|
|
700
|
-
/** The badge as drawn
|
|
701
|
-
shownBadge = computed(() => this.badge()
|
|
691
|
+
/** The badge as drawn. */
|
|
692
|
+
shownBadge = computed(() => this.badge(), /* @ts-ignore */
|
|
702
693
|
...(ngDevMode ? [{ debugName: "shownBadge" }] : /* istanbul ignore next */ []));
|
|
703
694
|
/** The label the glyph carries: its own, plus the count and the mode. */
|
|
704
695
|
accessibleLabel = computed(() => {
|
|
@@ -3619,7 +3610,7 @@ class StrctBadge {
|
|
|
3619
3610
|
/** Opt-in filled style instead of the default outlined style. */
|
|
3620
3611
|
solid = input(false, { ...(ngDevMode ? { debugName: "solid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3621
3612
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3622
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctBadge, isStandalone: true, selector: "strct-badge", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-badge--accent": "status() === 'accent'", "class.strct-badge--success": "status() === 'success'", "class.strct-badge--warning": "status() === 'warning'", "class.strct-badge--
|
|
3613
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctBadge, isStandalone: true, selector: "strct-badge", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-badge--accent": "status() === 'accent'", "class.strct-badge--success": "status() === 'success'", "class.strct-badge--warning": "status() === 'warning'", "class.strct-badge--critical": "status() === 'critical'", "class.strct-badge--solid": "solid()", "class.strct-badge--tone": "tone()", "style.--strct-badge-fg": "tone() || null" }, classAttribute: "strct-badge" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:500;line-height:1;letter-spacing:.2px;padding:0 8px 0 0;border:0;border-radius:0;white-space:nowrap;color:var(--t2);background:transparent}.strct-badge:before{content:\"\";flex:none;width:6px;height:6px;border-radius:50%;background:var(--strct-badge-dot, var(--t3))}.strct-badge:has(>strct-icon,>.strct-icon,>svg,>strct-status-dot):before{display:none}.strct-badge--accent{--strct-badge-dot: var(--acc)}.strct-badge--success{--strct-badge-dot: var(--success)}.strct-badge--warning{--strct-badge-dot: var(--warning)}.strct-badge--critical{--strct-badge-dot: var(--critical)}.strct-badge--tone{--strct-badge-dot: var(--strct-badge-fg, var(--t3))}.strct-badge--solid{gap:4px;padding:3px 8px;border-radius:var(--radius-sm);font-weight:600;color:var(--t1);background:var(--bg-a)}.strct-badge--solid:before{display:none}.strct-badge--solid.strct-badge--accent{background:var(--acc);color:var(--inv)}.strct-badge--solid.strct-badge--success{background:var(--success);color:var(--inv)}.strct-badge--solid.strct-badge--warning{background:var(--warning);color:var(--inv)}.strct-badge--solid.strct-badge--critical{background:var(--critical);color:var(--inv)}.strct-badge--solid.strct-badge--tone{background:var(--strct-badge-fg, var(--bg-a));color:var(--strct-badge-on, var(--inv))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3623
3614
|
}
|
|
3624
3615
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctBadge, decorators: [{
|
|
3625
3616
|
type: Component,
|
|
@@ -3628,8 +3619,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
3628
3619
|
'[class.strct-badge--accent]': "status() === 'accent'",
|
|
3629
3620
|
'[class.strct-badge--success]': "status() === 'success'",
|
|
3630
3621
|
'[class.strct-badge--warning]': "status() === 'warning'",
|
|
3631
|
-
// Deprecated alias of --warning (original typo), kept so consumer CSS keeps matching.
|
|
3632
|
-
'[class.strct-badge--warninging]': "status() === 'warning'",
|
|
3633
3622
|
'[class.strct-badge--critical]': "status() === 'critical'",
|
|
3634
3623
|
'[class.strct-badge--solid]': 'solid()',
|
|
3635
3624
|
'[class.strct-badge--tone]': 'tone()',
|
|
@@ -5614,11 +5603,9 @@ class StrctTreeNode {
|
|
|
5614
5603
|
const parts = [];
|
|
5615
5604
|
const mode = this.displayMode();
|
|
5616
5605
|
const badge = this.displayBadge();
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
if (
|
|
5620
|
-
parts.push(words[effectiveMode] ?? '');
|
|
5621
|
-
if (badge !== 'none' && badge !== 'maintenance')
|
|
5606
|
+
if (mode !== 'none')
|
|
5607
|
+
parts.push(words[mode] ?? '');
|
|
5608
|
+
if (badge !== 'none')
|
|
5622
5609
|
parts.push(words[badge] ?? '');
|
|
5623
5610
|
return parts.filter(Boolean).join(', ');
|
|
5624
5611
|
}, /* @ts-ignore */
|
|
@@ -7056,230 +7043,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
7056
7043
|
}, styles: [".strct-drawer__backdrop{position:fixed;inset:0;z-index:var(--z-overlay);background:var(--backdrop);-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px);animation:strct-drawer-fade .16s ease}.strct-drawer__backdrop--bare{background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;pointer-events:none}.strct-drawer{position:fixed;z-index:calc(var(--z-overlay) + 1);display:flex;flex-direction:column;background:var(--bg-1);box-shadow:var(--shh)}.strct-drawer--start,.strct-drawer--end{top:0;bottom:0;border-radius:0}.strct-drawer--start{inset-inline-start:0;border-inline-end:1px solid var(--b2);animation:strct-drawer-in-start .18s ease}.strct-drawer--end{inset-inline-end:0;border-inline-start:1px solid var(--b2);animation:strct-drawer-in-end .18s ease}[dir=rtl] .strct-drawer--start{animation-name:strct-drawer-in-end}[dir=rtl] .strct-drawer--end{animation-name:strct-drawer-in-start}.strct-drawer--top,.strct-drawer--bottom{left:0;right:0}.strct-drawer--top{top:0;border-bottom:1px solid var(--b2);animation:strct-drawer-in-top .18s ease}.strct-drawer--bottom{bottom:0;border-top:1px solid var(--b2);animation:strct-drawer-in-bottom .18s ease}.strct-drawer--start.strct-drawer--sm,.strct-drawer--end.strct-drawer--sm{width:300px}.strct-drawer--start.strct-drawer--md,.strct-drawer--end.strct-drawer--md{width:420px}.strct-drawer--start.strct-drawer--lg,.strct-drawer--end.strct-drawer--lg{width:600px}.strct-drawer--top.strct-drawer--sm,.strct-drawer--bottom.strct-drawer--sm{height:220px}.strct-drawer--top.strct-drawer--md,.strct-drawer--bottom.strct-drawer--md{height:340px}.strct-drawer--top.strct-drawer--lg,.strct-drawer--bottom.strct-drawer--lg{height:480px}.strct-drawer{max-width:100vw;max-height:100vh}.strct-drawer__head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--b1);flex-shrink:0}.strct-drawer__title{font-size:15px;font-weight:600;color:var(--t1)}.strct-drawer__close{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-drawer__close:hover{color:var(--t1);background:var(--bg-3)}.strct-drawer__body{flex:1;min-height:0;overflow-y:auto;padding:16px 18px;font-size:13px;color:var(--t1)}.strct-drawer__foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 18px;border-top:1px solid var(--b1);flex-shrink:0}@keyframes strct-drawer-fade{0%{opacity:0}}@keyframes strct-drawer-in-start{0%{transform:translate(-100%)}}@keyframes strct-drawer-in-end{0%{transform:translate(100%)}}@keyframes strct-drawer-in-top{0%{transform:translateY(-100%)}}@keyframes strct-drawer-in-bottom{0%{transform:translateY(100%)}}@media(prefers-reduced-motion:reduce){.strct-drawer__backdrop,.strct-drawer{animation:none}}\n"] }]
|
|
7057
7044
|
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], dismissable: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissable", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], footerDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDrawerFooter), { isSignal: true }] }] } });
|
|
7058
7045
|
|
|
7059
|
-
/**
|
|
7060
|
-
* Right-click (context) menu. Wraps a trigger area and shows a menu at the
|
|
7061
|
-
* cursor. Reuse `strct-dropdown-item` for the entries:
|
|
7062
|
-
* <strct-context-menu>
|
|
7063
|
-
* <div>Right-click here</div>
|
|
7064
|
-
* <ng-container strctContextMenuItems>
|
|
7065
|
-
* <strct-dropdown-item>Open</strct-dropdown-item>
|
|
7066
|
-
* <strct-dropdown-item critical>Delete</strct-dropdown-item>
|
|
7067
|
-
* </ng-container>
|
|
7068
|
-
* </strct-context-menu>
|
|
7069
|
-
*
|
|
7070
|
-
* Keyboard model mirrors `StrctMenuPanel` (menu.ts): focus moves into the
|
|
7071
|
-
* menu on open, Arrow/Home/End roam it, Enter/Space picks the active item,
|
|
7072
|
-
* Escape closes with stopPropagation, and focus returns to the trigger.
|
|
7073
|
-
*
|
|
7074
|
-
* @deprecated Prefer the data-driven `[strctContextMenu]` directive backed by
|
|
7075
|
-
* `StrctMenuService` (menu.ts) for new code — same visual menu, portaled into
|
|
7076
|
-
* `<body>`, with submenus and item actions.
|
|
7077
|
-
*/
|
|
7078
|
-
class StrctContextMenu {
|
|
7079
|
-
open = signal(false, /* @ts-ignore */
|
|
7080
|
-
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
7081
|
-
x = signal(0, /* @ts-ignore */
|
|
7082
|
-
...(ngDevMode ? [{ debugName: "x" }] : /* istanbul ignore next */ []));
|
|
7083
|
-
y = signal(0, /* @ts-ignore */
|
|
7084
|
-
...(ngDevMode ? [{ debugName: "y" }] : /* istanbul ignore next */ []));
|
|
7085
|
-
menuEl = viewChild('menu', /* @ts-ignore */
|
|
7086
|
-
...(ngDevMode ? [{ debugName: "menuEl" }] : /* istanbul ignore next */ []));
|
|
7087
|
-
/** Index within the navigable (non-disabled) items. */
|
|
7088
|
-
activeIndex = signal(0, /* @ts-ignore */
|
|
7089
|
-
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
7090
|
-
/** Element focused before opening — focus returns here on close. */
|
|
7091
|
-
restoreTo = null;
|
|
7092
|
-
onContextMenu(event) {
|
|
7093
|
-
event.preventDefault();
|
|
7094
|
-
this.restoreTo = saveFocusedElement();
|
|
7095
|
-
this.x.set(event.clientX);
|
|
7096
|
-
this.y.set(event.clientY);
|
|
7097
|
-
this.activeIndex.set(0);
|
|
7098
|
-
this.open.set(true);
|
|
7099
|
-
// Defer past the render so clamping measures the real menu box (not a
|
|
7100
|
-
// guessed size) and focus can land on the first item.
|
|
7101
|
-
setTimeout(() => {
|
|
7102
|
-
this.clampToViewport();
|
|
7103
|
-
// Land on the first entry that can act, not a disabled-but-hinted one.
|
|
7104
|
-
const first = this.navItems().findIndex((i) => i.getAttribute('aria-disabled') !== 'true');
|
|
7105
|
-
this.focusItem(Math.max(first, 0));
|
|
7106
|
-
});
|
|
7107
|
-
}
|
|
7108
|
-
close() {
|
|
7109
|
-
if (!this.open())
|
|
7110
|
-
return;
|
|
7111
|
-
this.open.set(false);
|
|
7112
|
-
// Hand focus back to the trigger (selection, Escape, Tab, outside click).
|
|
7113
|
-
restoreFocus(this.restoreTo);
|
|
7114
|
-
this.restoreTo = null;
|
|
7115
|
-
}
|
|
7116
|
-
/** Keyboard-reachable `strct-dropdown-item` elements in DOM order: enabled
|
|
7117
|
-
* ones, plus disabled ones that carry a hint (so the reason can be read). */
|
|
7118
|
-
navItems() {
|
|
7119
|
-
const el = this.menuEl()?.nativeElement;
|
|
7120
|
-
if (!el)
|
|
7121
|
-
return [];
|
|
7122
|
-
return Array.from(el.querySelectorAll('.strct-dd__item')).filter((i) => i.getAttribute('aria-disabled') !== 'true' ||
|
|
7123
|
-
i.classList.contains('strct-dd__item--hinted'));
|
|
7124
|
-
}
|
|
7125
|
-
/**
|
|
7126
|
-
* Focus-based roving: items keep the `tabindex="-1"` their host binding
|
|
7127
|
-
* sets (so Tab never stops mid-menu), the active element moves instead.
|
|
7128
|
-
*/
|
|
7129
|
-
focusItem(i) {
|
|
7130
|
-
const items = this.navItems();
|
|
7131
|
-
if (!items.length)
|
|
7132
|
-
return;
|
|
7133
|
-
const next = ((i % items.length) + items.length) % items.length;
|
|
7134
|
-
this.activeIndex.set(next);
|
|
7135
|
-
items[next].focus();
|
|
7136
|
-
}
|
|
7137
|
-
/** Re-position with the measured box so the menu stays inside the viewport. */
|
|
7138
|
-
clampToViewport() {
|
|
7139
|
-
const el = this.menuEl()?.nativeElement;
|
|
7140
|
-
if (!el)
|
|
7141
|
-
return;
|
|
7142
|
-
const w = el.offsetWidth;
|
|
7143
|
-
const h = el.offsetHeight;
|
|
7144
|
-
const m = 6;
|
|
7145
|
-
const nx = Math.max(m, Math.min(this.x(), window.innerWidth - w - m));
|
|
7146
|
-
const ny = Math.max(m, Math.min(this.y(), window.innerHeight - h - m));
|
|
7147
|
-
this.x.set(nx);
|
|
7148
|
-
this.y.set(ny);
|
|
7149
|
-
}
|
|
7150
|
-
/** Close on a real item pick only — padding / divider misclicks keep the menu open. */
|
|
7151
|
-
onMenuClick(event) {
|
|
7152
|
-
if (event.target.closest('.strct-dd__item'))
|
|
7153
|
-
this.close();
|
|
7154
|
-
}
|
|
7155
|
-
/** Keep the arrow-key anchor in sync with the hovered item. */
|
|
7156
|
-
onMenuMouseOver(event) {
|
|
7157
|
-
const item = event.target.closest('.strct-dd__item');
|
|
7158
|
-
if (!item)
|
|
7159
|
-
return;
|
|
7160
|
-
const i = this.navItems().indexOf(item);
|
|
7161
|
-
if (i >= 0)
|
|
7162
|
-
this.activeIndex.set(i);
|
|
7163
|
-
}
|
|
7164
|
-
onMenuKeydown(event) {
|
|
7165
|
-
const items = this.navItems();
|
|
7166
|
-
switch (event.key) {
|
|
7167
|
-
case 'ArrowDown':
|
|
7168
|
-
event.preventDefault();
|
|
7169
|
-
event.stopPropagation();
|
|
7170
|
-
this.focusItem(this.activeIndex() + 1);
|
|
7171
|
-
break;
|
|
7172
|
-
case 'ArrowUp':
|
|
7173
|
-
event.preventDefault();
|
|
7174
|
-
event.stopPropagation();
|
|
7175
|
-
this.focusItem(this.activeIndex() - 1);
|
|
7176
|
-
break;
|
|
7177
|
-
case 'Home':
|
|
7178
|
-
event.preventDefault();
|
|
7179
|
-
event.stopPropagation();
|
|
7180
|
-
this.focusItem(0);
|
|
7181
|
-
break;
|
|
7182
|
-
case 'End':
|
|
7183
|
-
event.preventDefault();
|
|
7184
|
-
event.stopPropagation();
|
|
7185
|
-
this.focusItem(items.length - 1);
|
|
7186
|
-
break;
|
|
7187
|
-
case 'Enter':
|
|
7188
|
-
case ' ':
|
|
7189
|
-
event.preventDefault();
|
|
7190
|
-
event.stopPropagation();
|
|
7191
|
-
// Runs the item's own (click) wiring; onMenuClick then closes.
|
|
7192
|
-
items[this.activeIndex()]?.click();
|
|
7193
|
-
break;
|
|
7194
|
-
case 'Escape':
|
|
7195
|
-
event.preventDefault();
|
|
7196
|
-
event.stopPropagation();
|
|
7197
|
-
this.close();
|
|
7198
|
-
break;
|
|
7199
|
-
case 'Tab':
|
|
7200
|
-
// APG: Tab closes the menu — no preventDefault, so focus moves on
|
|
7201
|
-
// naturally once the panel (and the focus inside it) is gone.
|
|
7202
|
-
this.close();
|
|
7203
|
-
break;
|
|
7204
|
-
}
|
|
7205
|
-
}
|
|
7206
|
-
onDocClick(event) {
|
|
7207
|
-
if (!this.open())
|
|
7208
|
-
return;
|
|
7209
|
-
const el = this.menuEl()?.nativeElement;
|
|
7210
|
-
// Clicks inside the menu are handled (or deliberately ignored) by onMenuClick.
|
|
7211
|
-
if (el && !el.contains(event.target))
|
|
7212
|
-
this.close();
|
|
7213
|
-
}
|
|
7214
|
-
/** Fallback for focus landing outside the panel; in-panel Escape stops first. */
|
|
7215
|
-
onEscape(event) {
|
|
7216
|
-
if (!this.open())
|
|
7217
|
-
return;
|
|
7218
|
-
event.stopPropagation();
|
|
7219
|
-
this.close();
|
|
7220
|
-
}
|
|
7221
|
-
onResize() {
|
|
7222
|
-
this.close();
|
|
7223
|
-
}
|
|
7224
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctContextMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7225
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctContextMenu, isStandalone: true, selector: "strct-context-menu", host: { listeners: { "document:click": "onDocClick($event)", "document:keydown.escape": "onEscape($event)", "window:resize": "onResize()" }, classAttribute: "strct-ctx" }, viewQueries: [{ propertyName: "menuEl", first: true, predicate: ["menu"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
7226
|
-
<div class="strct-ctx__trigger" (contextmenu)="onContextMenu($event)">
|
|
7227
|
-
<ng-content />
|
|
7228
|
-
</div>
|
|
7229
|
-
@if (open()) {
|
|
7230
|
-
<!-- eslint-disable-next-line @angular-eslint/template/mouse-events-have-key-events -- hover only syncs the arrow anchor; keyboard roves focus directly. -->
|
|
7231
|
-
<div
|
|
7232
|
-
#menu
|
|
7233
|
-
class="strct-ctx__menu"
|
|
7234
|
-
role="menu"
|
|
7235
|
-
tabindex="-1"
|
|
7236
|
-
[style.left.px]="x()"
|
|
7237
|
-
[style.top.px]="y()"
|
|
7238
|
-
(click)="onMenuClick($event)"
|
|
7239
|
-
(contextmenu)="$event.preventDefault(); close()"
|
|
7240
|
-
(keydown)="onMenuKeydown($event)"
|
|
7241
|
-
(mouseover)="onMenuMouseOver($event)"
|
|
7242
|
-
>
|
|
7243
|
-
<ng-content select="[strctContextMenuItems]" />
|
|
7244
|
-
</div>
|
|
7245
|
-
}
|
|
7246
|
-
`, isInline: true, styles: [".strct-ctx{display:block}.strct-ctx__menu{position:fixed;z-index:var(--z-overlay);min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);animation:strct-ctx-in .1s ease}@keyframes strct-ctx-in{0%{opacity:0;transform:scale(.97)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
7247
|
-
}
|
|
7248
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctContextMenu, decorators: [{
|
|
7249
|
-
type: Component,
|
|
7250
|
-
args: [{ selector: 'strct-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
|
|
7251
|
-
<div class="strct-ctx__trigger" (contextmenu)="onContextMenu($event)">
|
|
7252
|
-
<ng-content />
|
|
7253
|
-
</div>
|
|
7254
|
-
@if (open()) {
|
|
7255
|
-
<!-- eslint-disable-next-line @angular-eslint/template/mouse-events-have-key-events -- hover only syncs the arrow anchor; keyboard roves focus directly. -->
|
|
7256
|
-
<div
|
|
7257
|
-
#menu
|
|
7258
|
-
class="strct-ctx__menu"
|
|
7259
|
-
role="menu"
|
|
7260
|
-
tabindex="-1"
|
|
7261
|
-
[style.left.px]="x()"
|
|
7262
|
-
[style.top.px]="y()"
|
|
7263
|
-
(click)="onMenuClick($event)"
|
|
7264
|
-
(contextmenu)="$event.preventDefault(); close()"
|
|
7265
|
-
(keydown)="onMenuKeydown($event)"
|
|
7266
|
-
(mouseover)="onMenuMouseOver($event)"
|
|
7267
|
-
>
|
|
7268
|
-
<ng-content select="[strctContextMenuItems]" />
|
|
7269
|
-
</div>
|
|
7270
|
-
}
|
|
7271
|
-
`, host: { class: 'strct-ctx' }, styles: [".strct-ctx{display:block}.strct-ctx__menu{position:fixed;z-index:var(--z-overlay);min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);animation:strct-ctx-in .1s ease}@keyframes strct-ctx-in{0%{opacity:0;transform:scale(.97)}}\n"] }]
|
|
7272
|
-
}], propDecorators: { menuEl: [{ type: i0.ViewChild, args: ['menu', { isSignal: true }] }], onDocClick: [{
|
|
7273
|
-
type: HostListener,
|
|
7274
|
-
args: ['document:click', ['$event']]
|
|
7275
|
-
}], onEscape: [{
|
|
7276
|
-
type: HostListener,
|
|
7277
|
-
args: ['document:keydown.escape', ['$event']]
|
|
7278
|
-
}], onResize: [{
|
|
7279
|
-
type: HostListener,
|
|
7280
|
-
args: ['window:resize']
|
|
7281
|
-
}] } });
|
|
7282
|
-
|
|
7283
7046
|
/**
|
|
7284
7047
|
* A nested fly-out inside a `strct-context-menu` or `strct-dropdown`. Opens on
|
|
7285
7048
|
* hover, click/tap, or the keyboard (Enter / Space / → — focus then moves into
|
|
@@ -15258,14 +15021,6 @@ const DG_LABELS = {
|
|
|
15258
15021
|
* object; and the grid's core (`columns`, `rows`, `rowId`, `labels`) with the
|
|
15259
15022
|
* handful of look flags.
|
|
15260
15023
|
*/
|
|
15261
|
-
/** Flat inputs already named in a deprecation warning, per app run. */
|
|
15262
|
-
const warnedFlatInputs = new Set();
|
|
15263
|
-
const pendingFlatInputWarnings = new Set();
|
|
15264
|
-
let flatInputWarningQueued = false;
|
|
15265
|
-
strctOnDevWarnReset(() => {
|
|
15266
|
-
warnedFlatInputs.clear();
|
|
15267
|
-
pendingFlatInputWarnings.clear();
|
|
15268
|
-
});
|
|
15269
15024
|
/**
|
|
15270
15025
|
* `virtual` and `pane` take the flag they always took — including the bare
|
|
15271
15026
|
* attribute, which arrives as `''` — or the object that replaced their
|
|
@@ -15357,7 +15112,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
15357
15112
|
* Interactive data table: sortable columns, row selection (Shift-click a row
|
|
15358
15113
|
* checkbox to carry its new state across a whole block), expandable detail
|
|
15359
15114
|
* rows, a batch action bar and built-in paging.
|
|
15360
|
-
* <strct-datagrid [columns]="cols" [rows]="data"
|
|
15115
|
+
* <strct-datagrid [columns]="cols" [rows]="data" [selection]="{ enabled: true }" [paging]="{ pageSize: 10 }" expandable>
|
|
15361
15116
|
* <button strct-button strctDatagridActions size="sm">Migrate</button>
|
|
15362
15117
|
* <ng-template strctRowDetail let-row> … </ng-template>
|
|
15363
15118
|
* </strct-datagrid>
|
|
@@ -15369,26 +15124,19 @@ class StrctDatagrid {
|
|
|
15369
15124
|
/** Data rows. */
|
|
15370
15125
|
rows = input.required(/* @ts-ignore */
|
|
15371
15126
|
...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
15372
|
-
/** Rows per page (0 disables paging). */
|
|
15373
|
-
pageSizeFlat = input(0, { ...(ngDevMode ? { debugName: "pageSizeFlat" } : /* istanbul ignore next */ {}), alias: 'pageSize' });
|
|
15374
|
-
/** Enable row selection. */
|
|
15375
|
-
selectableFlat = input(false, { ...(ngDevMode ? { debugName: "selectableFlat" } : /* istanbul ignore next */ {}), alias: 'selectable', transform: booleanAttribute });
|
|
15376
15127
|
/** Expand a row in place to reveal its detail template below it. */
|
|
15377
15128
|
expandable = input(false, { ...(ngDevMode ? { debugName: "expandable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
15378
15129
|
/** Collapse the grid to a single column and open a side detail pane for the
|
|
15379
15130
|
* clicked row (distinct from {@link expandable}). */
|
|
15380
|
-
detailPaneFlat = input(false, { ...(ngDevMode ? { debugName: "detailPaneFlat" } : /* istanbul ignore next */ {}), alias: 'detailPane', transform: booleanAttribute });
|
|
15381
15131
|
/**
|
|
15382
15132
|
* How wide the list column is while the pane is open — px or any CSS width.
|
|
15383
15133
|
* 260px cuts a test name like "Validate Switch Enabled Teaming
|
|
15384
15134
|
* Configurations" in half and hides its status.
|
|
15385
15135
|
*/
|
|
15386
|
-
paneListWidthFlat = input('260px', { ...(ngDevMode ? { debugName: "paneListWidthFlat" } : /* istanbul ignore next */ {}), alias: 'paneListWidth' });
|
|
15387
15136
|
/**
|
|
15388
15137
|
* Below this container width (px) the pane takes the list's place, with a
|
|
15389
15138
|
* way back in its header, rather than squeezing both into a phone.
|
|
15390
15139
|
*/
|
|
15391
|
-
paneTakeoverWidthFlat = input(900, { ...(ngDevMode ? { debugName: "paneTakeoverWidthFlat" } : /* istanbul ignore next */ {}), alias: 'paneTakeoverWidth' });
|
|
15392
15140
|
/**
|
|
15393
15141
|
* The row whose pane is open, two-way: a "what to do next" chip opens the
|
|
15394
15142
|
* finding it settles, a URL fragment deep-links to a test, `null` closes it.
|
|
@@ -15411,8 +15159,6 @@ class StrctDatagrid {
|
|
|
15411
15159
|
resizable = input(false, { ...(ngDevMode ? { debugName: "resizable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
15412
15160
|
/** Show a column-chooser dropdown in the footer. */
|
|
15413
15161
|
columnChooser = input(false, { ...(ngDevMode ? { debugName: "columnChooser" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
15414
|
-
/** Show a refresh button in the footer. */
|
|
15415
|
-
syncFlat = input(false, { ...(ngDevMode ? { debugName: "syncFlat" } : /* istanbul ignore next */ {}), alias: 'sync', transform: booleanAttribute });
|
|
15416
15162
|
/** Disable all footer action buttons (sync, column chooser, etc.). */
|
|
15417
15163
|
footerActionsDisabled = input(false, { ...(ngDevMode ? { debugName: "footerActionsDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
15418
15164
|
/**
|
|
@@ -15428,7 +15174,6 @@ class StrctDatagrid {
|
|
|
15428
15174
|
* exactly one row is grid behaviour rather than a column of radios the
|
|
15429
15175
|
* consumer builds and wires by hand.
|
|
15430
15176
|
*/
|
|
15431
|
-
selectionModeFlat = input('none', { ...(ngDevMode ? { debugName: "selectionModeFlat" } : /* istanbul ignore next */ {}), alias: 'selectionMode' });
|
|
15432
15177
|
/** Two-way single selection: the row id (per `rowId`), or null. */
|
|
15433
15178
|
selectedId = model(null, /* @ts-ignore */
|
|
15434
15179
|
...(ngDevMode ? [{ debugName: "selectedId" }] : /* istanbul ignore next */ []));
|
|
@@ -15437,22 +15182,13 @@ class StrctDatagrid {
|
|
|
15437
15182
|
* it AND say why — shown as the row's tooltip and given to assistive tech as
|
|
15438
15183
|
* the control's description, following the `hint` convention.
|
|
15439
15184
|
*/
|
|
15440
|
-
rowSelectableFlat = input(null, { ...(ngDevMode ? { debugName: "rowSelectableFlat" } : /* istanbul ignore next */ {}), alias: 'rowSelectable' });
|
|
15441
15185
|
/** No outer border, radius or shadow — for a grid inside a bordered panel. */
|
|
15442
15186
|
flush = input(false, { ...(ngDevMode ? { debugName: "flush" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
15443
15187
|
/** The grid's title, rendered above the header and used as its accessible name. */
|
|
15444
15188
|
caption = input('', /* @ts-ignore */
|
|
15445
15189
|
...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
|
|
15446
|
-
/** Whether there is another slice to ask for. */
|
|
15447
|
-
hasMoreFlat = input(false, { ...(ngDevMode ? { debugName: "hasMoreFlat" } : /* istanbul ignore next */ {}), alias: 'hasMore', transform: booleanAttribute });
|
|
15448
|
-
/** A slice is on its way: the button waits with a spinner. */
|
|
15449
|
-
loadingMoreFlat = input(false, { ...(ngDevMode ? { debugName: "loadingMoreFlat" } : /* istanbul ignore next */ {}), alias: 'loadingMore', transform: booleanAttribute });
|
|
15450
|
-
/** The grand total, when the API knows it — "Showing the latest 50 of 812". */
|
|
15451
|
-
moreTotalFlat = input(null, { ...(ngDevMode ? { debugName: "moreTotalFlat" } : /* istanbul ignore next */ {}), alias: 'moreTotal' });
|
|
15452
15190
|
/** The user asked for the next slice. */
|
|
15453
15191
|
loadMore = output();
|
|
15454
|
-
/** With `groupBy` and multiple selection: a tri-state checkbox per group. */
|
|
15455
|
-
groupSelectFlat = input(false, { ...(ngDevMode ? { debugName: "groupSelectFlat" } : /* istanbul ignore next */ {}), alias: 'groupSelect', transform: booleanAttribute });
|
|
15456
15192
|
/**
|
|
15457
15193
|
* Per-row action menu resolver. When set, each row gets a trailing actions
|
|
15458
15194
|
* column with a vertical-dots (kebab) button that opens this row's menu.
|
|
@@ -15466,7 +15202,6 @@ class StrctDatagrid {
|
|
|
15466
15202
|
* `selectable`. Assigning a new array (e.g. when opening a dialog) re-seeds the
|
|
15467
15203
|
* selection; the user's subsequent toggles are preserved until the next change.
|
|
15468
15204
|
*/
|
|
15469
|
-
initialSelectionFlat = input(null, { ...(ngDevMode ? { debugName: "initialSelectionFlat" } : /* istanbul ignore next */ {}), alias: 'initialSelection' });
|
|
15470
15205
|
/**
|
|
15471
15206
|
* The selection itself, two-way, for `selectionMode="multiple"` — what
|
|
15472
15207
|
* `selectedId` is for single mode. Write it and the grid checks those rows
|
|
@@ -15482,30 +15217,22 @@ class StrctDatagrid {
|
|
|
15482
15217
|
/** Effective labels (defaults + overrides). */
|
|
15483
15218
|
L = computed(() => ({ ...DG_LABELS, ...this.labels() }), /* @ts-ignore */
|
|
15484
15219
|
...(ngDevMode ? [{ debugName: "L" }] : /* istanbul ignore next */ []));
|
|
15485
|
-
/** Scroll viewport height in px (virtual mode). */
|
|
15486
|
-
viewportHeightFlat = input(360, { ...(ngDevMode ? { debugName: "viewportHeightFlat" } : /* istanbul ignore next */ {}), alias: 'viewportHeight' });
|
|
15487
15220
|
/**
|
|
15488
15221
|
* Show a pencil on an editable cell when it is hovered or focused. A mouse
|
|
15489
15222
|
* user finds an editable cell by double-clicking one; nothing said so.
|
|
15490
15223
|
*/
|
|
15491
15224
|
editHint = input(false, { ...(ngDevMode ? { debugName: "editHint" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
15492
|
-
/** Uniform row height in px (virtual mode; tune when `compact`). */
|
|
15493
|
-
rowHeightFlat = input(38, { ...(ngDevMode ? { debugName: "rowHeightFlat" } : /* istanbul ignore next */ {}), alias: 'rowHeight' });
|
|
15494
15225
|
/**
|
|
15495
15226
|
* Server-side mode: the grid never sorts or slices `rows` itself — it shows
|
|
15496
15227
|
* them as given and emits `(lazyLoad)` with `{ page, pageSize, sortKey,
|
|
15497
15228
|
* sortDir }` whenever the user pages or sorts (and once on init). Provide
|
|
15498
15229
|
* `total` so the pager and count reflect the full server-side set.
|
|
15499
15230
|
*/
|
|
15500
|
-
lazyFlat = input(false, { ...(ngDevMode ? { debugName: "lazyFlat" } : /* istanbul ignore next */ {}), alias: 'lazy', transform: booleanAttribute });
|
|
15501
|
-
/** Total row count on the server (lazy mode). */
|
|
15502
|
-
totalFlat = input(null, { ...(ngDevMode ? { debugName: "totalFlat" } : /* istanbul ignore next */ {}), alias: 'total' });
|
|
15503
15231
|
/**
|
|
15504
15232
|
* Persist the user's column widths + hidden columns under this key in
|
|
15505
15233
|
* localStorage (`strct-dg:<key>`), restoring them on init. For full control
|
|
15506
15234
|
* use the two-way `columnState` instead (both may be combined).
|
|
15507
15235
|
*/
|
|
15508
|
-
stateKeyFlat = input(null, { ...(ngDevMode ? { debugName: "stateKeyFlat" } : /* istanbul ignore next */ {}), alias: 'stateKey' });
|
|
15509
15236
|
/** User column preferences (two-way): widths from resize, hidden from the chooser. */
|
|
15510
15237
|
columnState = model(null, /* @ts-ignore */
|
|
15511
15238
|
...(ngDevMode ? [{ debugName: "columnState" }] : /* istanbul ignore next */ []));
|
|
@@ -15516,16 +15243,11 @@ class StrctDatagrid {
|
|
|
15516
15243
|
* per distinct value (with a count), respecting the current sort within
|
|
15517
15244
|
* groups. Paging is bypassed while grouped; not combinable with `virtual`.
|
|
15518
15245
|
*/
|
|
15519
|
-
groupByFlat = input(null, { ...(ngDevMode ? { debugName: "groupByFlat" } : /* istanbul ignore next */ {}), alias: 'groupBy' });
|
|
15520
15246
|
/**
|
|
15521
15247
|
* The groups themselves, beside `groupBy`: their order, their labels, a
|
|
15522
15248
|
* tone, a note, whether they start folded and a count of the consumer's
|
|
15523
15249
|
* own. Values no group mentions follow, in the order the rows arrived.
|
|
15524
15250
|
*/
|
|
15525
|
-
groupsFlat = input(null, { ...(ngDevMode ? { debugName: "groupsFlat" } : /* istanbul ignore next */ {}), alias: 'groups' });
|
|
15526
|
-
/** Keep a declared group that holds no rows, rather than dropping it. */
|
|
15527
|
-
showEmptyGroupsFlat = input(false, { ...(ngDevMode ? { debugName: "showEmptyGroupsFlat" } : /* istanbul ignore next */ {}), alias: 'showEmptyGroups',
|
|
15528
|
-
transform: booleanAttribute });
|
|
15529
15251
|
/**
|
|
15530
15252
|
* Which groups are folded, two-way — so a summary counter elsewhere on the
|
|
15531
15253
|
* page can open the group it counts.
|
|
@@ -15547,18 +15269,12 @@ class StrctDatagrid {
|
|
|
15547
15269
|
*/
|
|
15548
15270
|
quickFilter = model('', /* @ts-ignore */
|
|
15549
15271
|
...(ngDevMode ? [{ debugName: "quickFilter" }] : /* istanbul ignore next */ []));
|
|
15550
|
-
/** Columns the quick term scans. Defaults to every column's `key`. */
|
|
15551
|
-
quickFilterFieldsFlat = input(null, { ...(ngDevMode ? { debugName: "quickFilterFieldsFlat" } : /* istanbul ignore next */ {}), alias: 'quickFilterFields' });
|
|
15552
|
-
/** Render the built-in quick-filter searchbox in the toolbar. */
|
|
15553
|
-
quickFilterableFlat = input(false, { ...(ngDevMode ? { debugName: "quickFilterableFlat" } : /* istanbul ignore next */ {}), alias: 'quickFilterable',
|
|
15554
|
-
transform: booleanAttribute });
|
|
15555
15272
|
/**
|
|
15556
15273
|
* Where the built-in box sits in the toolbar. `'end'` (default) follows the
|
|
15557
15274
|
* console convention: action verbs lead on the left, view controls sit at
|
|
15558
15275
|
* the far right — and the box keeps a stable position across grids whose
|
|
15559
15276
|
* button sets differ.
|
|
15560
15277
|
*/
|
|
15561
|
-
quickFilterAlignFlat = input('end', { ...(ngDevMode ? { debugName: "quickFilterAlignFlat" } : /* istanbul ignore next */ {}), alias: 'quickFilterAlign' });
|
|
15562
15278
|
/**
|
|
15563
15279
|
* Tree-grid: the row property holding a row's children array. Rows render
|
|
15564
15280
|
* hierarchically with indent + carets; sorting applies per sibling level;
|
|
@@ -15571,7 +15287,6 @@ class StrctDatagrid {
|
|
|
15571
15287
|
* ArrowLeft collapses an expanded one. There is no cell-level navigation —
|
|
15572
15288
|
* Tab walks the interactive elements inside each row as usual.
|
|
15573
15289
|
*/
|
|
15574
|
-
childrenKeyFlat = input(null, { ...(ngDevMode ? { debugName: "childrenKeyFlat" } : /* istanbul ignore next */ {}), alias: 'childrenKey' });
|
|
15575
15290
|
/**
|
|
15576
15291
|
* `'table'` (the default) is what the grid has always been: a table whose
|
|
15577
15292
|
* controls each take a tab stop. `'grid'` is the APG grid: the table claims
|
|
@@ -15590,7 +15305,6 @@ class StrctDatagrid {
|
|
|
15590
15305
|
* file list selects by clicking the row, not a control in it. The row is
|
|
15591
15306
|
* then the control, so pair it with `interactionMode="grid"`.
|
|
15592
15307
|
*/
|
|
15593
|
-
selectionColumnFlat = input('auto', { ...(ngDevMode ? { debugName: "selectionColumnFlat" } : /* istanbul ignore next */ {}), alias: 'selectionColumn' });
|
|
15594
15308
|
/**
|
|
15595
15309
|
* The row was opened: a double-click, or Enter on the focused row in grid
|
|
15596
15310
|
* mode. Selection is "which rows do I mean"; activation is "go".
|
|
@@ -15625,17 +15339,17 @@ class StrctDatagrid {
|
|
|
15625
15339
|
/** How rows are picked — replaces six flat inputs. */
|
|
15626
15340
|
selectionCfg = input({}, { ...(ngDevMode ? { debugName: "selectionCfg" } : /* istanbul ignore next */ {}), alias: 'selection' });
|
|
15627
15341
|
/** The detail pane — replaces three. `[pane]` on its own turns it on. */
|
|
15628
|
-
|
|
15342
|
+
paneInput = input(false, { ...(ngDevMode ? { debugName: "paneInput" } : /* istanbul ignore next */ {}), alias: 'pane',
|
|
15629
15343
|
transform: objectOrBoolean });
|
|
15630
15344
|
paneCfg = computed(() => {
|
|
15631
|
-
const v = this.
|
|
15345
|
+
const v = this.paneInput();
|
|
15632
15346
|
return typeof v === 'boolean' ? (v ? { enabled: true } : {}) : { enabled: true, ...v };
|
|
15633
15347
|
}, /* @ts-ignore */
|
|
15634
15348
|
...(ngDevMode ? [{ debugName: "paneCfg" }] : /* istanbul ignore next */ []));
|
|
15635
15349
|
/** How rows are paged. Takes the mode on its own, as before, or the object. */
|
|
15636
|
-
|
|
15350
|
+
pagingInput = input('pages', { ...(ngDevMode ? { debugName: "pagingInput" } : /* istanbul ignore next */ {}), alias: 'paging' });
|
|
15637
15351
|
pagingCfg = computed(() => {
|
|
15638
|
-
const v = this.
|
|
15352
|
+
const v = this.pagingInput();
|
|
15639
15353
|
return typeof v === 'string' ? { mode: v } : v;
|
|
15640
15354
|
}, /* @ts-ignore */
|
|
15641
15355
|
...(ngDevMode ? [{ debugName: "pagingCfg" }] : /* istanbul ignore next */ []));
|
|
@@ -15643,9 +15357,9 @@ class StrctDatagrid {
|
|
|
15643
15357
|
paging = computed(() => this.pagingCfg().mode ?? 'pages', /* @ts-ignore */
|
|
15644
15358
|
...(ngDevMode ? [{ debugName: "paging" }] : /* istanbul ignore next */ []));
|
|
15645
15359
|
/** Virtual scrolling. Takes the flag on its own, as before, or the object. */
|
|
15646
|
-
|
|
15360
|
+
virtualInput = input(false, { ...(ngDevMode ? { debugName: "virtualInput" } : /* istanbul ignore next */ {}), alias: 'virtual', transform: objectOrBoolean });
|
|
15647
15361
|
virtualCfg = computed(() => {
|
|
15648
|
-
const v = this.
|
|
15362
|
+
const v = this.virtualInput();
|
|
15649
15363
|
return typeof v === 'boolean' ? (v ? { enabled: true } : {}) : { enabled: true, ...v };
|
|
15650
15364
|
}, /* @ts-ignore */
|
|
15651
15365
|
...(ngDevMode ? [{ debugName: "virtualCfg" }] : /* istanbul ignore next */ []));
|
|
@@ -15658,147 +15372,83 @@ class StrctDatagrid {
|
|
|
15658
15372
|
filteringCfg = input({}, { ...(ngDevMode ? { debugName: "filteringCfg" } : /* istanbul ignore next */ {}), alias: 'filtering' });
|
|
15659
15373
|
/** Remembered state — replaces `stateKey` and `sync`. */
|
|
15660
15374
|
stateCfg = input({}, { ...(ngDevMode ? { debugName: "stateCfg" } : /* istanbul ignore next */ {}), alias: 'state' });
|
|
15661
|
-
/**
|
|
15662
|
-
|
|
15663
|
-
* moved into. "Given" is read as "not its default", which is what a
|
|
15664
|
-
* template can be checked against from inside the component.
|
|
15665
|
-
*/
|
|
15666
|
-
flatInputsInUse = [
|
|
15667
|
-
['pageSize', () => this.pageSizeFlat() !== 0, '[paging].pageSize'],
|
|
15668
|
-
['selectable', () => this.selectableFlat(), '[selection].enabled'],
|
|
15669
|
-
['detailPane', () => this.detailPaneFlat(), '[pane].enabled'],
|
|
15670
|
-
['paneListWidth', () => this.paneListWidthFlat() !== '260px', '[pane].listWidth'],
|
|
15671
|
-
['paneTakeoverWidth', () => this.paneTakeoverWidthFlat() !== 900, '[pane].takeoverWidth'],
|
|
15672
|
-
['sync', () => this.syncFlat(), '[state].sync'],
|
|
15673
|
-
['selectionMode', () => this.selectionModeFlat() !== 'none', '[selection].mode'],
|
|
15674
|
-
['rowSelectable', () => this.rowSelectableFlat() !== null, '[selection].rowSelectable'],
|
|
15675
|
-
['hasMore', () => this.hasMoreFlat(), '[paging].hasMore'],
|
|
15676
|
-
['loadingMore', () => this.loadingMoreFlat(), '[paging].loadingMore'],
|
|
15677
|
-
['moreTotal', () => this.moreTotalFlat() !== null, '[paging].moreTotal'],
|
|
15678
|
-
['groupSelect', () => this.groupSelectFlat(), '[selection].groupSelect'],
|
|
15679
|
-
['initialSelection', () => this.initialSelectionFlat() !== null, '[selection].initial'],
|
|
15680
|
-
['viewportHeight', () => this.viewportHeightFlat() !== 360, '[virtual].viewportHeight'],
|
|
15681
|
-
['rowHeight', () => this.rowHeightFlat() !== 38, '[virtual].rowHeight'],
|
|
15682
|
-
['lazy', () => this.lazyFlat(), '[paging].lazy'],
|
|
15683
|
-
['total', () => this.totalFlat() !== null, '[paging].total'],
|
|
15684
|
-
['stateKey', () => this.stateKeyFlat() !== null, '[state].key'],
|
|
15685
|
-
['groupBy', () => this.groupByFlat() !== null, '[grouping].by'],
|
|
15686
|
-
['groups', () => this.groupsFlat() !== null, '[grouping].groups'],
|
|
15687
|
-
['showEmptyGroups', () => this.showEmptyGroupsFlat(), '[grouping].showEmpty'],
|
|
15688
|
-
['quickFilterFields', () => this.quickFilterFieldsFlat() !== null, '[filtering].fields'],
|
|
15689
|
-
['quickFilterable', () => this.quickFilterableFlat(), '[filtering].quick'],
|
|
15690
|
-
['quickFilterAlign', () => this.quickFilterAlignFlat() !== 'end', '[filtering].align'],
|
|
15691
|
-
['childrenKey', () => this.childrenKeyFlat() !== null, '[grouping].childrenKey'],
|
|
15692
|
-
['selectionColumn', () => this.selectionColumnFlat() !== 'auto', '[selection].column'],
|
|
15693
|
-
];
|
|
15694
|
-
/**
|
|
15695
|
-
* Dev mode says, once per app run, which flat inputs have moved — a
|
|
15696
|
-
* console line per name would be a wall in a screen with four grids, so
|
|
15697
|
-
* the names are collected and reported together.
|
|
15698
|
-
*/
|
|
15699
|
-
reportFlatInputs() {
|
|
15700
|
-
const fresh = this.flatInputsInUse
|
|
15701
|
-
.filter(([name, given]) => given() && !warnedFlatInputs.has(name))
|
|
15702
|
-
.map(([name, , to]) => {
|
|
15703
|
-
warnedFlatInputs.add(name);
|
|
15704
|
-
return ` ${name} → ${to}`;
|
|
15705
|
-
});
|
|
15706
|
-
if (!fresh.length)
|
|
15707
|
-
return;
|
|
15708
|
-
for (const line of fresh)
|
|
15709
|
-
pendingFlatInputWarnings.add(line);
|
|
15710
|
-
if (flatInputWarningQueued)
|
|
15711
|
-
return;
|
|
15712
|
-
flatInputWarningQueued = true;
|
|
15713
|
-
setTimeout(() => {
|
|
15714
|
-
flatInputWarningQueued = false;
|
|
15715
|
-
const lines = [...pendingFlatInputWarnings].sort();
|
|
15716
|
-
pendingFlatInputWarnings.clear();
|
|
15717
|
-
console.warn(`[strct-datagrid] ${lines.length} input(s) have moved into a feature ` +
|
|
15718
|
-
`object and are removed in 6.0. They keep working through 5.x:\n` +
|
|
15719
|
-
lines.join('\n') +
|
|
15720
|
-
`\nThe objects are [selection], [paging], [pane], [virtual], ` +
|
|
15721
|
-
`[grouping], [filtering] and [state]; two-way state ` +
|
|
15722
|
-
`(selectedIds, filters, columnState, …) stays where it is.`);
|
|
15723
|
-
});
|
|
15724
|
-
}
|
|
15725
|
-
/** `[paging].pageSize` when it is set, else the flat `pageSize` (deprecated). */
|
|
15726
|
-
pageSize = computed(() => this.pagingCfg().pageSize ?? this.pageSizeFlat(), /* @ts-ignore */
|
|
15375
|
+
/** From `[paging].pageSize`. */
|
|
15376
|
+
pageSize = computed(() => this.pagingCfg().pageSize ?? 0, /* @ts-ignore */
|
|
15727
15377
|
...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
|
|
15728
|
-
/** `[selection].enabled
|
|
15729
|
-
selectable = computed(() => this.selectionCfg().enabled ??
|
|
15378
|
+
/** From `[selection].enabled`. */
|
|
15379
|
+
selectable = computed(() => this.selectionCfg().enabled ?? false, /* @ts-ignore */
|
|
15730
15380
|
...(ngDevMode ? [{ debugName: "selectable" }] : /* istanbul ignore next */ []));
|
|
15731
|
-
/** `[pane].enabled
|
|
15732
|
-
detailPane = computed(() => this.paneCfg().enabled ??
|
|
15381
|
+
/** From `[pane].enabled`. */
|
|
15382
|
+
detailPane = computed(() => this.paneCfg().enabled ?? false, /* @ts-ignore */
|
|
15733
15383
|
...(ngDevMode ? [{ debugName: "detailPane" }] : /* istanbul ignore next */ []));
|
|
15734
|
-
/** `[pane].listWidth
|
|
15735
|
-
paneListWidth = computed(() => this.paneCfg().listWidth ??
|
|
15384
|
+
/** From `[pane].listWidth`. */
|
|
15385
|
+
paneListWidth = computed(() => this.paneCfg().listWidth ?? '260px', /* @ts-ignore */
|
|
15736
15386
|
...(ngDevMode ? [{ debugName: "paneListWidth" }] : /* istanbul ignore next */ []));
|
|
15737
|
-
/** `[pane].takeoverWidth
|
|
15738
|
-
paneTakeoverWidth = computed(() => this.paneCfg().takeoverWidth ??
|
|
15387
|
+
/** From `[pane].takeoverWidth`. */
|
|
15388
|
+
paneTakeoverWidth = computed(() => this.paneCfg().takeoverWidth ?? 900, /* @ts-ignore */
|
|
15739
15389
|
...(ngDevMode ? [{ debugName: "paneTakeoverWidth" }] : /* istanbul ignore next */ []));
|
|
15740
|
-
/** `[state].sync
|
|
15741
|
-
sync = computed(() => this.stateCfg().sync ??
|
|
15390
|
+
/** From `[state].sync`. */
|
|
15391
|
+
sync = computed(() => this.stateCfg().sync ?? false, /* @ts-ignore */
|
|
15742
15392
|
...(ngDevMode ? [{ debugName: "sync" }] : /* istanbul ignore next */ []));
|
|
15743
|
-
/** `[selection].mode
|
|
15744
|
-
selectionMode = computed(() => this.selectionCfg().mode ??
|
|
15393
|
+
/** From `[selection].mode`. */
|
|
15394
|
+
selectionMode = computed(() => this.selectionCfg().mode ?? 'none', /* @ts-ignore */
|
|
15745
15395
|
...(ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []));
|
|
15746
|
-
/** `[selection].rowSelectable
|
|
15747
|
-
rowSelectable = computed(() => this.selectionCfg().rowSelectable ??
|
|
15396
|
+
/** From `[selection].rowSelectable`. */
|
|
15397
|
+
rowSelectable = computed(() => this.selectionCfg().rowSelectable ?? null, /* @ts-ignore */
|
|
15748
15398
|
...(ngDevMode ? [{ debugName: "rowSelectable" }] : /* istanbul ignore next */ []));
|
|
15749
|
-
/** `[paging].hasMore
|
|
15750
|
-
hasMore = computed(() => this.pagingCfg().hasMore ??
|
|
15399
|
+
/** From `[paging].hasMore`. */
|
|
15400
|
+
hasMore = computed(() => this.pagingCfg().hasMore ?? false, /* @ts-ignore */
|
|
15751
15401
|
...(ngDevMode ? [{ debugName: "hasMore" }] : /* istanbul ignore next */ []));
|
|
15752
|
-
/** `[paging].loadingMore
|
|
15753
|
-
loadingMore = computed(() => this.pagingCfg().loadingMore ??
|
|
15402
|
+
/** From `[paging].loadingMore`. */
|
|
15403
|
+
loadingMore = computed(() => this.pagingCfg().loadingMore ?? false, /* @ts-ignore */
|
|
15754
15404
|
...(ngDevMode ? [{ debugName: "loadingMore" }] : /* istanbul ignore next */ []));
|
|
15755
|
-
/** `[paging].moreTotal
|
|
15756
|
-
moreTotal = computed(() => this.pagingCfg().moreTotal ??
|
|
15405
|
+
/** From `[paging].moreTotal`. */
|
|
15406
|
+
moreTotal = computed(() => this.pagingCfg().moreTotal ?? null, /* @ts-ignore */
|
|
15757
15407
|
...(ngDevMode ? [{ debugName: "moreTotal" }] : /* istanbul ignore next */ []));
|
|
15758
|
-
/** `[selection].groupSelect
|
|
15759
|
-
groupSelect = computed(() => this.selectionCfg().groupSelect ??
|
|
15408
|
+
/** From `[selection].groupSelect`. */
|
|
15409
|
+
groupSelect = computed(() => this.selectionCfg().groupSelect ?? false, /* @ts-ignore */
|
|
15760
15410
|
...(ngDevMode ? [{ debugName: "groupSelect" }] : /* istanbul ignore next */ []));
|
|
15761
|
-
/** `[selection].initial
|
|
15762
|
-
initialSelection = computed(() => this.selectionCfg().initial ??
|
|
15411
|
+
/** From `[selection].initial`. */
|
|
15412
|
+
initialSelection = computed(() => this.selectionCfg().initial ?? null, /* @ts-ignore */
|
|
15763
15413
|
...(ngDevMode ? [{ debugName: "initialSelection" }] : /* istanbul ignore next */ []));
|
|
15764
|
-
/** `[virtual].viewportHeight
|
|
15765
|
-
viewportHeight = computed(() => this.virtualCfg().viewportHeight ??
|
|
15414
|
+
/** From `[virtual].viewportHeight`. */
|
|
15415
|
+
viewportHeight = computed(() => this.virtualCfg().viewportHeight ?? 360, /* @ts-ignore */
|
|
15766
15416
|
...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
|
|
15767
|
-
/** `[virtual].rowHeight
|
|
15768
|
-
rowHeight = computed(() => this.virtualCfg().rowHeight ??
|
|
15417
|
+
/** From `[virtual].rowHeight`. */
|
|
15418
|
+
rowHeight = computed(() => this.virtualCfg().rowHeight ?? 38, /* @ts-ignore */
|
|
15769
15419
|
...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
|
|
15770
|
-
/** `[paging].lazy
|
|
15771
|
-
lazy = computed(() => this.pagingCfg().lazy ??
|
|
15420
|
+
/** From `[paging].lazy`. */
|
|
15421
|
+
lazy = computed(() => this.pagingCfg().lazy ?? false, /* @ts-ignore */
|
|
15772
15422
|
...(ngDevMode ? [{ debugName: "lazy" }] : /* istanbul ignore next */ []));
|
|
15773
|
-
/** `[paging].total
|
|
15774
|
-
total = computed(() => this.pagingCfg().total ??
|
|
15423
|
+
/** From `[paging].total`. */
|
|
15424
|
+
total = computed(() => this.pagingCfg().total ?? null, /* @ts-ignore */
|
|
15775
15425
|
...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
|
|
15776
|
-
/** `[state].key
|
|
15777
|
-
stateKey = computed(() => this.stateCfg().key ??
|
|
15426
|
+
/** From `[state].key`. */
|
|
15427
|
+
stateKey = computed(() => this.stateCfg().key ?? null, /* @ts-ignore */
|
|
15778
15428
|
...(ngDevMode ? [{ debugName: "stateKey" }] : /* istanbul ignore next */ []));
|
|
15779
|
-
/** `[grouping].by
|
|
15780
|
-
groupBy = computed(() => this.groupingCfg().by ??
|
|
15429
|
+
/** From `[grouping].by`. */
|
|
15430
|
+
groupBy = computed(() => this.groupingCfg().by ?? null, /* @ts-ignore */
|
|
15781
15431
|
...(ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []));
|
|
15782
|
-
/** `[grouping].groups
|
|
15783
|
-
groups = computed(() => this.groupingCfg().groups ??
|
|
15432
|
+
/** From `[grouping].groups`. */
|
|
15433
|
+
groups = computed(() => this.groupingCfg().groups ?? null, /* @ts-ignore */
|
|
15784
15434
|
...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
15785
|
-
/** `[grouping].showEmpty
|
|
15786
|
-
showEmptyGroups = computed(() => this.groupingCfg().showEmpty ??
|
|
15435
|
+
/** From `[grouping].showEmpty`. */
|
|
15436
|
+
showEmptyGroups = computed(() => this.groupingCfg().showEmpty ?? false, /* @ts-ignore */
|
|
15787
15437
|
...(ngDevMode ? [{ debugName: "showEmptyGroups" }] : /* istanbul ignore next */ []));
|
|
15788
|
-
/** `[filtering].fields
|
|
15789
|
-
quickFilterFields = computed(() => this.filteringCfg().fields ??
|
|
15438
|
+
/** From `[filtering].fields`. */
|
|
15439
|
+
quickFilterFields = computed(() => this.filteringCfg().fields ?? null, /* @ts-ignore */
|
|
15790
15440
|
...(ngDevMode ? [{ debugName: "quickFilterFields" }] : /* istanbul ignore next */ []));
|
|
15791
|
-
/** `[filtering].quick
|
|
15792
|
-
quickFilterable = computed(() => this.filteringCfg().quick ??
|
|
15441
|
+
/** From `[filtering].quick`. */
|
|
15442
|
+
quickFilterable = computed(() => this.filteringCfg().quick ?? false, /* @ts-ignore */
|
|
15793
15443
|
...(ngDevMode ? [{ debugName: "quickFilterable" }] : /* istanbul ignore next */ []));
|
|
15794
|
-
/** `[filtering].align
|
|
15795
|
-
quickFilterAlign = computed(() => this.filteringCfg().align ??
|
|
15444
|
+
/** From `[filtering].align`. */
|
|
15445
|
+
quickFilterAlign = computed(() => this.filteringCfg().align ?? 'end', /* @ts-ignore */
|
|
15796
15446
|
...(ngDevMode ? [{ debugName: "quickFilterAlign" }] : /* istanbul ignore next */ []));
|
|
15797
|
-
/** `[grouping].childrenKey
|
|
15798
|
-
childrenKey = computed(() => this.groupingCfg().childrenKey ??
|
|
15447
|
+
/** From `[grouping].childrenKey`. */
|
|
15448
|
+
childrenKey = computed(() => this.groupingCfg().childrenKey ?? null, /* @ts-ignore */
|
|
15799
15449
|
...(ngDevMode ? [{ debugName: "childrenKey" }] : /* istanbul ignore next */ []));
|
|
15800
|
-
/** `[selection].column
|
|
15801
|
-
selectionColumn = computed(() => this.selectionCfg().column ??
|
|
15450
|
+
/** From `[selection].column`. */
|
|
15451
|
+
selectionColumn = computed(() => this.selectionCfg().column ?? 'auto', /* @ts-ignore */
|
|
15802
15452
|
...(ngDevMode ? [{ debugName: "selectionColumn" }] : /* istanbul ignore next */ []));
|
|
15803
15453
|
menu = inject(StrctMenuService);
|
|
15804
15454
|
detailDef = contentChild(StrctRowDetailDef, /* @ts-ignore */
|
|
@@ -17316,12 +16966,6 @@ class StrctDatagrid {
|
|
|
17316
16966
|
this.lazyLoad.emit(state);
|
|
17317
16967
|
});
|
|
17318
16968
|
});
|
|
17319
|
-
// The inputs are bound by the first render, so this is where they can be
|
|
17320
|
-
// read and reported.
|
|
17321
|
-
afterNextRender(() => {
|
|
17322
|
-
if (typeof ngDevMode !== 'undefined' && ngDevMode)
|
|
17323
|
-
this.reportFlatInputs();
|
|
17324
|
-
});
|
|
17325
16969
|
// Below `paneTakeoverWidth` the pane replaces the list. The grid's own
|
|
17326
16970
|
// width decides, not the viewport: the same grid is wide in a page and
|
|
17327
16971
|
// narrow in a drawer.
|
|
@@ -17826,7 +17470,7 @@ class StrctDatagrid {
|
|
|
17826
17470
|
return String(a ?? '').localeCompare(String(b ?? ''), undefined, { numeric: true });
|
|
17827
17471
|
}
|
|
17828
17472
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDatagrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
17829
|
-
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 }, 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 }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", 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 });
|
|
17473
|
+
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 }, expandable: { classPropertyName: "expandable", publicName: "expandable", 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 }, footerActionsDisabled: { classPropertyName: "footerActionsDisabled", publicName: "footerActionsDisabled", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", 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 }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", 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 }, editHint: { classPropertyName: "editHint", publicName: "editHint", 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 }, 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 }, interactionMode: { classPropertyName: "interactionMode", publicName: "interactionMode", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, selectionCfg: { classPropertyName: "selectionCfg", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, paneInput: { classPropertyName: "paneInput", publicName: "pane", isSignal: true, isRequired: false, transformFunction: null }, pagingInput: { classPropertyName: "pagingInput", publicName: "paging", isSignal: true, isRequired: false, transformFunction: null }, virtualInput: { classPropertyName: "virtualInput", 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 });
|
|
17830
17474
|
}
|
|
17831
17475
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDatagrid, decorators: [{
|
|
17832
17476
|
type: Component,
|
|
@@ -17855,7 +17499,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
17855
17499
|
'[class.strct-dg-host--sticky]': 'stickyActive()',
|
|
17856
17500
|
'[class.strct-dg-host--flush]': 'flush()',
|
|
17857
17501
|
}, 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"] }]
|
|
17858
|
-
}], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }],
|
|
17502
|
+
}], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", 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 }] }], footerActionsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerActionsDisabled", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }, { type: i0.Output, args: ["selectedIdChange"] }], flush: [{ type: i0.Input, args: [{ isSignal: true, alias: "flush", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", 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 }] }], editHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "editHint", 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 }] }], 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"] }], interactionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactionMode", 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"] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], selectionCfg: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], paneInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "pane", required: false }] }], pagingInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "paging", required: false }] }], virtualInput: [{ 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: [{
|
|
17859
17503
|
type: HostListener,
|
|
17860
17504
|
args: ['document:click', ['$event']]
|
|
17861
17505
|
}], onEscapeOverlays: [{
|
|
@@ -30630,5 +30274,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
30630
30274
|
* Generated bundle index. Do not edit.
|
|
30631
30275
|
*/
|
|
30632
30276
|
|
|
30633
|
-
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,
|
|
30277
|
+
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, 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 };
|
|
30634
30278
|
//# sourceMappingURL=akcelik-strct.mjs.map
|