@akcelik/strct 1.0.0 → 1.2.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.
@@ -7458,6 +7458,126 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
7458
7458
  }, styles: [".strct-table-host{display:block;overflow-x:auto}.strct-table{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-table th,.strct-table td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-table th{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2)}.strct-table td{color:var(--t1)}.strct-table tbody tr:last-child td{border-bottom:0}.strct-table-host--striped tbody tr:nth-child(2n) td{background:var(--bg-2)}.strct-table-host--hover tbody tr:hover td{background:var(--acc-s)}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-table__skeleton-block{height:12px;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-table__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-table__empty{text-align:center;color:var(--t3);padding:22px}\n"] }]
7459
7459
  }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }] } });
7460
7460
 
7461
+ /**
7462
+ * Minimal, dependency-free XLSX writer for the datagrid's Excel export.
7463
+ *
7464
+ * An .xlsx file is a ZIP of SpreadsheetML parts. This builds the five
7465
+ * required parts with inline strings and zips them with STORED (uncompressed)
7466
+ * entries — no runtime dependency, byte-accurate CRC32, opens in Excel,
7467
+ * LibreOffice and Google Sheets.
7468
+ */
7469
+ const CRC_TABLE = (() => {
7470
+ const t = new Uint32Array(256);
7471
+ for (let n = 0; n < 256; n++) {
7472
+ let c = n;
7473
+ for (let k = 0; k < 8; k++)
7474
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
7475
+ t[n] = c >>> 0;
7476
+ }
7477
+ return t;
7478
+ })();
7479
+ function crc32(data) {
7480
+ let c = 0xffffffff;
7481
+ for (const byte of data)
7482
+ c = CRC_TABLE[(c ^ byte) & 0xff] ^ (c >>> 8);
7483
+ return (c ^ 0xffffffff) >>> 0;
7484
+ }
7485
+ const enc = new TextEncoder();
7486
+ /** ZIP with STORED entries (no compression — spreadsheets are small). */
7487
+ function zip(entries) {
7488
+ const chunks = [];
7489
+ const central = [];
7490
+ let offset = 0;
7491
+ const u16 = (n) => new Uint8Array([n & 0xff, (n >> 8) & 0xff]);
7492
+ const u32 = (n) => new Uint8Array([n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]);
7493
+ const cat = (...parts) => {
7494
+ const total = parts.reduce((s, p) => s + p.length, 0);
7495
+ const out = new Uint8Array(total);
7496
+ let o = 0;
7497
+ for (const p of parts) {
7498
+ out.set(p, o);
7499
+ o += p.length;
7500
+ }
7501
+ return out;
7502
+ };
7503
+ for (const { name, data } of entries) {
7504
+ const nameBytes = enc.encode(name);
7505
+ const crc = crc32(data);
7506
+ const local = cat(u32(0x04034b50), u16(20), // version needed
7507
+ u16(0), // flags
7508
+ u16(0), // method: stored
7509
+ u16(0), u16(0), // mod time/date
7510
+ u32(crc), u32(data.length), u32(data.length), u16(nameBytes.length), u16(0), nameBytes, data);
7511
+ central.push(cat(u32(0x02014b50), u16(20), u16(20), u16(0), u16(0), u16(0), u16(0), u32(crc), u32(data.length), u32(data.length), u16(nameBytes.length), u16(0), u16(0), u16(0), u16(0), u32(0), u32(offset), nameBytes));
7512
+ chunks.push(local);
7513
+ offset += local.length;
7514
+ }
7515
+ const centralStart = offset;
7516
+ const centralBytes = cat(...central);
7517
+ const end = cat(u32(0x06054b50), u16(0), u16(0), u16(entries.length), u16(entries.length), u32(centralBytes.length), u32(centralStart), u16(0));
7518
+ return cat(...chunks, centralBytes, end);
7519
+ }
7520
+ const xml = (s) => String(s ?? '')
7521
+ .replace(/&/g, '&amp;')
7522
+ .replace(/</g, '&lt;')
7523
+ .replace(/>/g, '&gt;')
7524
+ .replace(/"/g, '&quot;');
7525
+ /** A1-style column ref: 0 → A, 26 → AA … */
7526
+ function colRef(i) {
7527
+ let s = '';
7528
+ for (let n = i; n >= 0; n = Math.floor(n / 26) - 1)
7529
+ s = String.fromCharCode(65 + (n % 26)) + s;
7530
+ return s;
7531
+ }
7532
+ /**
7533
+ * Build a single-sheet workbook: `header` as a bold-free first row, then
7534
+ * `rows`. Numbers stay numeric; everything else exports as inline strings.
7535
+ */
7536
+ function buildXlsx(header, rows, sheetName = 'Data') {
7537
+ const rowXml = (cells, r) => `<row r="${r}">` +
7538
+ cells
7539
+ .map((v, c) => {
7540
+ const ref = `${colRef(c)}${r}`;
7541
+ if (typeof v === 'number' && Number.isFinite(v)) {
7542
+ return `<c r="${ref}"><v>${v}</v></c>`;
7543
+ }
7544
+ return `<c r="${ref}" t="inlineStr"><is><t xml:space="preserve">${xml(v)}</t></is></c>`;
7545
+ })
7546
+ .join('') +
7547
+ '</row>';
7548
+ const sheet = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
7549
+ `<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>` +
7550
+ rowXml(header, 1) +
7551
+ rows.map((cells, i) => rowXml(cells, i + 2)).join('') +
7552
+ `</sheetData></worksheet>`;
7553
+ const workbook = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
7554
+ `<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" ` +
7555
+ `xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">` +
7556
+ `<sheets><sheet name="${xml(sheetName)}" sheetId="1" r:id="rId1"/></sheets></workbook>`;
7557
+ const workbookRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
7558
+ `<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">` +
7559
+ `<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>` +
7560
+ `</Relationships>`;
7561
+ const rootRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
7562
+ `<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">` +
7563
+ `<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>` +
7564
+ `</Relationships>`;
7565
+ const contentTypes = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
7566
+ `<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">` +
7567
+ `<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>` +
7568
+ `<Default Extension="xml" ContentType="application/xml"/>` +
7569
+ `<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>` +
7570
+ `<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>` +
7571
+ `</Types>`;
7572
+ return zip([
7573
+ { name: '[Content_Types].xml', data: enc.encode(contentTypes) },
7574
+ { name: '_rels/.rels', data: enc.encode(rootRels) },
7575
+ { name: 'xl/workbook.xml', data: enc.encode(workbook) },
7576
+ { name: 'xl/_rels/workbook.xml.rels', data: enc.encode(workbookRels) },
7577
+ { name: 'xl/worksheets/sheet1.xml', data: enc.encode(sheet) },
7578
+ ]);
7579
+ }
7580
+
7461
7581
  const DG_LABELS = {
7462
7582
  row: 'row',
7463
7583
  rows: 'rows',
@@ -7590,6 +7710,14 @@ class StrctDatagrid {
7590
7710
  stateKey = input(null, ...(ngDevMode ? [{ debugName: "stateKey" }] : /* istanbul ignore next */ []));
7591
7711
  /** User column preferences (two-way): widths from resize, hidden from the chooser. */
7592
7712
  columnState = model(null, ...(ngDevMode ? [{ debugName: "columnState" }] : /* istanbul ignore next */ []));
7713
+ /** Let the user reorder data columns by dragging their headers. */
7714
+ reorderable = input(false, { ...(ngDevMode ? { debugName: "reorderable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
7715
+ /**
7716
+ * Group rows by this column key: the grid renders a collapsible header row
7717
+ * per distinct value (with a count), respecting the current sort within
7718
+ * groups. Paging is bypassed while grouped; not combinable with `virtual`.
7719
+ */
7720
+ groupBy = input(null, ...(ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []));
7593
7721
  /** Emitted when the selection changes. */
7594
7722
  selectionChange = output();
7595
7723
  /** Emitted when the refresh button is clicked. */
@@ -7661,13 +7789,108 @@ class StrctDatagrid {
7661
7789
  paneOpen = computed(() => this.detailPane() && !!this.detailDef() && !!this.activeRow(), ...(ngDevMode ? [{ debugName: "paneOpen" }] : /* istanbul ignore next */ []));
7662
7790
  /** Whether to render the trailing row-actions (kebab) column. */
7663
7791
  canActions = computed(() => !!this.rowActions() && !this.paneOpen(), ...(ngDevMode ? [{ debugName: "canActions" }] : /* istanbul ignore next */ []));
7792
+ /** User-chosen column order (keys); unknown keys keep declared positions. */
7793
+ columnOrder = signal(null, ...(ngDevMode ? [{ debugName: "columnOrder" }] : /* istanbul ignore next */ []));
7794
+ /** Declared columns re-arranged by the user's drag order. */
7795
+ orderedColumns = computed(() => {
7796
+ const cols = this.columns();
7797
+ const order = this.columnOrder();
7798
+ if (!order?.length)
7799
+ return cols;
7800
+ const byKey = new Map(cols.map((c) => [c.key, c]));
7801
+ const out = [];
7802
+ for (const key of order) {
7803
+ const c = byKey.get(key);
7804
+ if (c) {
7805
+ out.push(c);
7806
+ byKey.delete(key);
7807
+ }
7808
+ }
7809
+ for (const c of cols)
7810
+ if (byKey.has(c.key))
7811
+ out.push(c);
7812
+ return out;
7813
+ }, ...(ngDevMode ? [{ debugName: "orderedColumns" }] : /* istanbul ignore next */ []));
7664
7814
  /** Only the first column is shown while the detail pane is open. */
7665
7815
  visibleColumns = computed(() => {
7666
7816
  if (this.paneOpen())
7667
- return this.columns().slice(0, 1);
7817
+ return this.orderedColumns().slice(0, 1);
7668
7818
  const hidden = this.hiddenColumns();
7669
- return this.columns().filter((c) => !hidden.has(c.key));
7819
+ return this.orderedColumns().filter((c) => !hidden.has(c.key));
7670
7820
  }, ...(ngDevMode ? [{ debugName: "visibleColumns" }] : /* istanbul ignore next */ []));
7821
+ // ── Column drag-reorder ────────────────────────────────────────
7822
+ dragKey = signal(null, ...(ngDevMode ? [{ debugName: "dragKey" }] : /* istanbul ignore next */ []));
7823
+ dropKey = signal(null, ...(ngDevMode ? [{ debugName: "dropKey" }] : /* istanbul ignore next */ []));
7824
+ onColDragStart(key, event) {
7825
+ if (!this.reorderable())
7826
+ return;
7827
+ this.dragKey.set(key);
7828
+ event.dataTransfer?.setData('text/plain', key);
7829
+ if (event.dataTransfer)
7830
+ event.dataTransfer.effectAllowed = 'move';
7831
+ }
7832
+ onColDragOver(key, event) {
7833
+ if (!this.reorderable() || !this.dragKey() || key === this.dragKey())
7834
+ return;
7835
+ event.preventDefault();
7836
+ this.dropKey.set(key);
7837
+ }
7838
+ onColDrop(key) {
7839
+ const from = this.dragKey();
7840
+ this.dragKey.set(null);
7841
+ this.dropKey.set(null);
7842
+ if (!from || from === key)
7843
+ return;
7844
+ const keys = this.orderedColumns().map((c) => c.key);
7845
+ const fromIdx = keys.indexOf(from);
7846
+ const toIdx = keys.indexOf(key);
7847
+ if (fromIdx < 0 || toIdx < 0)
7848
+ return;
7849
+ keys.splice(toIdx, 0, ...keys.splice(fromIdx, 1));
7850
+ this.columnOrder.set(keys);
7851
+ }
7852
+ onColDragEnd() {
7853
+ this.dragKey.set(null);
7854
+ this.dropKey.set(null);
7855
+ }
7856
+ // ── Row grouping ───────────────────────────────────────────────
7857
+ collapsedGroups = signal(new Set(), ...(ngDevMode ? [{ debugName: "collapsedGroups" }] : /* istanbul ignore next */ []));
7858
+ /** Collapse / expand one group header. */
7859
+ toggleGroup(key) {
7860
+ const next = new Set(this.collapsedGroups());
7861
+ if (next.has(key))
7862
+ next.delete(key);
7863
+ else
7864
+ next.add(key);
7865
+ this.collapsedGroups.set(next);
7866
+ }
7867
+ /** What tbody renders: plain (virtual/paged) rows, or groups + their rows. */
7868
+ displayItems = computed(() => {
7869
+ const g = this.groupBy();
7870
+ if (!g || this.virtual())
7871
+ return this.renderRows().map((row) => ({ row }));
7872
+ const map = new Map();
7873
+ for (const row of this.sorted()) {
7874
+ const key = row[g];
7875
+ const bucket = map.get(key);
7876
+ if (bucket)
7877
+ bucket.push(row);
7878
+ else
7879
+ map.set(key, [row]);
7880
+ }
7881
+ const out = [];
7882
+ for (const [key, rows] of map) {
7883
+ const collapsed = this.collapsedGroups().has(key);
7884
+ out.push({ group: { key, label: String(key ?? '—'), count: rows.length, collapsed } });
7885
+ if (!collapsed)
7886
+ for (const row of rows)
7887
+ out.push({ row });
7888
+ }
7889
+ return out;
7890
+ }, ...(ngDevMode ? [{ debugName: "displayItems" }] : /* istanbul ignore next */ []));
7891
+ itemKey(it) {
7892
+ return it.group ? `strct-group:${String(it.group.key)}` : this.rowKey(it.row);
7893
+ }
7671
7894
  sorted = computed(() => {
7672
7895
  // Server-side mode: rows arrive already ordered / sliced — never touch them.
7673
7896
  if (this.lazy())
@@ -7836,11 +8059,12 @@ class StrctDatagrid {
7836
8059
  this.applyColumnState(st);
7837
8060
  });
7838
8061
  });
7839
- // Push user changes (resize / chooser) outward + persist under stateKey.
8062
+ // Push user changes (resize / chooser / reorder) outward + persist under stateKey.
7840
8063
  effect(() => {
7841
8064
  const widths = Object.fromEntries(this.columnWidths());
7842
8065
  const hidden = [...this.hiddenColumns()];
7843
- const st = { widths, hidden };
8066
+ const order = this.columnOrder() ?? undefined;
8067
+ const st = { widths, hidden, order };
7844
8068
  const key = JSON.stringify(st);
7845
8069
  untracked(() => {
7846
8070
  if (key === this.lastStateKey)
@@ -7874,6 +8098,7 @@ class StrctDatagrid {
7874
8098
  applyColumnState(st) {
7875
8099
  this.columnWidths.set(new Map(Object.entries(st.widths ?? {}).map(([k, v]) => [k, Number(v)])));
7876
8100
  this.hiddenColumns.set(new Set(st.hidden ?? []));
8101
+ this.columnOrder.set(st.order?.length ? [...st.order] : null);
7877
8102
  }
7878
8103
  /**
7879
8104
  * The grid as CSV: header labels + every non-hidden column, all rows in the
@@ -7892,6 +8117,33 @@ class StrctDatagrid {
7892
8117
  ...data.map((r) => cols.map((c) => esc(r[c.key])).join(',')),
7893
8118
  ].join('\n');
7894
8119
  }
8120
+ /**
8121
+ * The grid as a real .xlsx workbook (dependency-free SpreadsheetML):
8122
+ * header labels + every non-hidden column in the current order, all rows in
8123
+ * the current sort; numeric cells stay numeric.
8124
+ */
8125
+ toXLSX() {
8126
+ const hidden = this.hiddenColumns();
8127
+ const cols = this.orderedColumns().filter((c) => !hidden.has(c.key));
8128
+ const data = this.lazy() ? this.rows() : this.sorted();
8129
+ return buildXlsx(cols.map((c) => c.label), data.map((r) => cols.map((c) => r[c.key])));
8130
+ }
8131
+ /** Download the grid as an .xlsx file. */
8132
+ downloadXLSX(filename = 'datagrid.xlsx') {
8133
+ if (typeof document === 'undefined')
8134
+ return;
8135
+ const bytes = this.toXLSX();
8136
+ const copy = new Uint8Array(bytes);
8137
+ const blob = new Blob([copy.buffer], {
8138
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
8139
+ });
8140
+ const url = URL.createObjectURL(blob);
8141
+ const a = document.createElement('a');
8142
+ a.href = url;
8143
+ a.download = filename;
8144
+ a.click();
8145
+ URL.revokeObjectURL(url);
8146
+ }
7895
8147
  /** Download the grid as a CSV file. */
7896
8148
  downloadCSV(filename = 'datagrid.csv') {
7897
8149
  if (typeof document === 'undefined')
@@ -8030,7 +8282,7 @@ class StrctDatagrid {
8030
8282
  return String(a ?? '').localeCompare(String(b ?? ''), undefined, { numeric: true });
8031
8283
  }
8032
8284
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDatagrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
8033
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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 }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPane: { classPropertyName: "detailPane", publicName: "detailPane", 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 }, sync: { classPropertyName: "sync", 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 }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, initialSelection: { classPropertyName: "initialSelection", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, virtual: { classPropertyName: "virtual", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, viewportHeight: { classPropertyName: "viewportHeight", publicName: "viewportHeight", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null }, columnState: { classPropertyName: "columnState", publicName: "columnState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { columnState: "columnStateChange", selectionChange: "selectionChange", syncChange: "syncChange", rowAction: "rowAction", lazyLoad: "lazyLoad" }, host: { properties: { "class.strct-dg-host--compact": "compact()", "class.strct-dg-host--singleline": "singleLine()", "class.strct-dg-host--virtual": "virtual()", "class.strct-dg-host--sticky": "stickyActive()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
8285
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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 }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPane: { classPropertyName: "detailPane", publicName: "detailPane", 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 }, sync: { classPropertyName: "sync", 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 }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, initialSelection: { classPropertyName: "initialSelection", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, virtual: { classPropertyName: "virtual", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, viewportHeight: { classPropertyName: "viewportHeight", publicName: "viewportHeight", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", 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 }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { columnState: "columnStateChange", selectionChange: "selectionChange", syncChange: "syncChange", rowAction: "rowAction", lazyLoad: "lazyLoad" }, host: { properties: { "class.strct-dg-host--compact": "compact()", "class.strct-dg-host--singleline": "singleLine()", "class.strct-dg-host--virtual": "virtual()", "class.strct-dg-host--sticky": "stickyActive()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
8034
8286
  @if (actionBarDef()) {
8035
8287
  <div class="strct-dg__toolbar"><ng-content select="[strctDatagridActionBar]" /></div>
8036
8288
  }
@@ -8080,11 +8332,17 @@ class StrctDatagrid {
8080
8332
  [style.text-align]="col.align ?? 'start'"
8081
8333
  [style.width]="colWidth(col.key) ?? col.width ?? null"
8082
8334
  [class.strct-dg__th--sortable]="col.sortable"
8335
+ [class.strct-dg__th--drop]="col.key === dropKey()"
8083
8336
  [class.strct-dg__cell--sticky]="isSticky(col)"
8084
8337
  [class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
8085
8338
  [style.insetInlineStart.px]="stickyLeft(col.key)"
8086
8339
  [attr.tabindex]="col.sortable ? 0 : null"
8087
8340
  [attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
8341
+ [attr.draggable]="reorderable() ? true : null"
8342
+ (dragstart)="onColDragStart(col.key, $event)"
8343
+ (dragover)="onColDragOver(col.key, $event)"
8344
+ (drop)="onColDrop(col.key)"
8345
+ (dragend)="onColDragEnd()"
8088
8346
  (click)="col.sortable && sortBy(col.key)"
8089
8347
  (keydown.enter)="col.sortable && sortBy(col.key)"
8090
8348
  (keydown.space)="col.sortable && onHeaderSpace($event, col.key)"
@@ -8141,105 +8399,129 @@ class StrctDatagrid {
8141
8399
  <td [attr.colspan]="colspan()" [style.height.px]="topPad()"></td>
8142
8400
  </tr>
8143
8401
  }
8144
- @for (row of renderRows(); track rowKey(row)) {
8145
- <tr
8146
- [class.strct-dg__row--selected]="isSelected(row)"
8147
- [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
8148
- >
8149
- @if (canDetail()) {
8150
- <td
8151
- class="strct-dg__expandcell"
8152
- [class.strct-dg__cell--sticky]="stickyActive()"
8153
- [style.insetInlineStart.px]="utilLeft('detail')"
8154
- >
8402
+ @for (it of displayItems(); track itemKey(it)) {
8403
+ @if (it.group; as grp) {
8404
+ <!-- Group header: distinct value + count, collapsible. -->
8405
+ <tr class="strct-dg__grouprow">
8406
+ <td [attr.colspan]="colspan()">
8155
8407
  <button
8156
8408
  type="button"
8157
- class="strct-dg__detailbtn"
8158
- [class.strct-dg__detailbtn--active]="row === activeRow()"
8159
- [attr.aria-expanded]="row === activeRow()"
8160
- [attr.aria-label]="L().openDetail"
8161
- (click)="openDetail(row)"
8409
+ class="strct-dg__groupbtn"
8410
+ [attr.aria-expanded]="!grp.collapsed"
8411
+ (click)="toggleGroup(grp.key)"
8162
8412
  >
8163
- <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
8413
+ <span
8414
+ class="strct-dg__groupchev"
8415
+ [class.strct-dg__groupchev--open]="!grp.collapsed"
8416
+ >
8417
+ <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
8418
+ </span>
8419
+ <span class="strct-dg__grouplabel">{{ grp.label }}</span>
8420
+ <span class="strct-dg__groupcount">{{ grp.count }}</span>
8164
8421
  </button>
8165
8422
  </td>
8166
- }
8167
- @if (canExpand()) {
8168
- <td
8169
- class="strct-dg__expandcell"
8170
- [class.strct-dg__cell--sticky]="stickyActive()"
8171
- [style.insetInlineStart.px]="utilLeft('expand')"
8172
- >
8173
- <button
8174
- type="button"
8175
- class="strct-dg__expandbtn"
8176
- [class.strct-dg__expandbtn--open]="isExpanded(row)"
8177
- [attr.aria-expanded]="isExpanded(row)"
8178
- [attr.aria-label]="L().toggleDetail"
8179
- (click)="toggleExpand(row)"
8423
+ </tr>
8424
+ } @else {
8425
+ @let row = it.row!;
8426
+ <tr
8427
+ [class.strct-dg__row--selected]="isSelected(row)"
8428
+ [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
8429
+ >
8430
+ @if (canDetail()) {
8431
+ <td
8432
+ class="strct-dg__expandcell"
8433
+ [class.strct-dg__cell--sticky]="stickyActive()"
8434
+ [style.insetInlineStart.px]="utilLeft('detail')"
8180
8435
  >
8181
- <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
8182
- </button>
8183
- </td>
8184
- }
8185
- @if (selectable()) {
8186
- <td
8187
- class="strct-dg__sel"
8188
- [class.strct-dg__cell--sticky]="stickyActive()"
8189
- [style.insetInlineStart.px]="utilLeft('sel')"
8190
- >
8191
- <strct-checkbox
8192
- [ariaLabel]="L().selectRow"
8193
- [checked]="isSelected(row)"
8194
- (checkedChange)="toggleRow(row)"
8195
- />
8196
- </td>
8197
- }
8198
- @for (col of visibleColumns(); track col.key) {
8199
- <td
8200
- [style.text-align]="col.align ?? 'start'"
8201
- [class.strct-dg__cell--sticky]="isSticky(col)"
8202
- [class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
8203
- [style.insetInlineStart.px]="stickyLeft(col.key)"
8204
- >
8205
- @if (cellTemplate(col.key); as tpl) {
8206
- <ng-container
8207
- [ngTemplateOutlet]="tpl"
8208
- [ngTemplateOutletContext]="{
8209
- $implicit: row,
8210
- value: row[col.key],
8211
- column: col,
8212
- }"
8213
- />
8214
- } @else {
8215
- {{ row[col.key] }}
8216
- }
8217
- </td>
8218
- }
8219
- @if (canActions()) {
8220
- <td class="strct-dg__actioncell">
8221
- <button
8222
- type="button"
8223
- class="strct-dg__kebab"
8224
- [attr.aria-label]="L().rowActions"
8225
- (click)="openRowMenu(row, $event)"
8436
+ <button
8437
+ type="button"
8438
+ class="strct-dg__detailbtn"
8439
+ [class.strct-dg__detailbtn--active]="row === activeRow()"
8440
+ [attr.aria-expanded]="row === activeRow()"
8441
+ [attr.aria-label]="L().openDetail"
8442
+ (click)="openDetail(row)"
8443
+ >
8444
+ <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
8445
+ </button>
8446
+ </td>
8447
+ }
8448
+ @if (canExpand()) {
8449
+ <td
8450
+ class="strct-dg__expandcell"
8451
+ [class.strct-dg__cell--sticky]="stickyActive()"
8452
+ [style.insetInlineStart.px]="utilLeft('expand')"
8226
8453
  >
8227
- <strct-icon name="dots" [size]="16" />
8228
- </button>
8229
- </td>
8230
- }
8231
- </tr>
8232
- @if (canExpand() && isExpanded(row)) {
8233
- <tr class="strct-dg__detailrow">
8234
- <td [attr.colspan]="colspan()">
8235
- <div class="strct-dg__detail">
8236
- <ng-container
8237
- [ngTemplateOutlet]="detailDef()!.template"
8238
- [ngTemplateOutletContext]="{ $implicit: row }"
8454
+ <button
8455
+ type="button"
8456
+ class="strct-dg__expandbtn"
8457
+ [class.strct-dg__expandbtn--open]="isExpanded(row)"
8458
+ [attr.aria-expanded]="isExpanded(row)"
8459
+ [attr.aria-label]="L().toggleDetail"
8460
+ (click)="toggleExpand(row)"
8461
+ >
8462
+ <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
8463
+ </button>
8464
+ </td>
8465
+ }
8466
+ @if (selectable()) {
8467
+ <td
8468
+ class="strct-dg__sel"
8469
+ [class.strct-dg__cell--sticky]="stickyActive()"
8470
+ [style.insetInlineStart.px]="utilLeft('sel')"
8471
+ >
8472
+ <strct-checkbox
8473
+ [ariaLabel]="L().selectRow"
8474
+ [checked]="isSelected(row)"
8475
+ (checkedChange)="toggleRow(row)"
8239
8476
  />
8240
- </div>
8241
- </td>
8477
+ </td>
8478
+ }
8479
+ @for (col of visibleColumns(); track col.key) {
8480
+ <td
8481
+ [style.text-align]="col.align ?? 'start'"
8482
+ [class.strct-dg__cell--sticky]="isSticky(col)"
8483
+ [class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
8484
+ [style.insetInlineStart.px]="stickyLeft(col.key)"
8485
+ >
8486
+ @if (cellTemplate(col.key); as tpl) {
8487
+ <ng-container
8488
+ [ngTemplateOutlet]="tpl"
8489
+ [ngTemplateOutletContext]="{
8490
+ $implicit: row,
8491
+ value: row[col.key],
8492
+ column: col,
8493
+ }"
8494
+ />
8495
+ } @else {
8496
+ {{ row[col.key] }}
8497
+ }
8498
+ </td>
8499
+ }
8500
+ @if (canActions()) {
8501
+ <td class="strct-dg__actioncell">
8502
+ <button
8503
+ type="button"
8504
+ class="strct-dg__kebab"
8505
+ [attr.aria-label]="L().rowActions"
8506
+ (click)="openRowMenu(row, $event)"
8507
+ >
8508
+ <strct-icon name="dots" [size]="16" />
8509
+ </button>
8510
+ </td>
8511
+ }
8242
8512
  </tr>
8513
+ @if (canExpand() && isExpanded(row)) {
8514
+ <tr class="strct-dg__detailrow">
8515
+ <td [attr.colspan]="colspan()">
8516
+ <div class="strct-dg__detail">
8517
+ <ng-container
8518
+ [ngTemplateOutlet]="detailDef()!.template"
8519
+ [ngTemplateOutletContext]="{ $implicit: row }"
8520
+ />
8521
+ </div>
8522
+ </td>
8523
+ </tr>
8524
+ }
8243
8525
  }
8244
8526
  } @empty {
8245
8527
  <tr>
@@ -8333,13 +8615,13 @@ class StrctDatagrid {
8333
8615
  </span>
8334
8616
  </div>
8335
8617
  <div class="strct-dg__foot-right">
8336
- @if (pageSize() > 0) {
8618
+ @if (pageSize() > 0 && !groupBy()) {
8337
8619
  <strct-pagination [total]="totalCount()" [pageSize]="pageSize()" [(page)]="page" />
8338
8620
  }
8339
8621
  </div>
8340
8622
  </div>
8341
8623
  }
8342
- `, isInline: true, styles: [".strct-dg-host{display:block;border:1px solid var(--b2);border-radius:10px;background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th{position:sticky;top:0;z-index:5}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .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:3}.strct-dg thead th.strct-dg__cell--sticky{z-index:6}.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:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.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__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:2}.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:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.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:5px;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{display:inline-flex;padding:3px;border:0;border-radius:4px;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:4px;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:260px;min-width:260px;max-width:260px}.strct-dg__layout--paned .strct-dg{width:260px;min-width:260px;max-width:260px;flex-shrink:0;border-top-right-radius:0;border-bottom-right-radius:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.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;right: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:0 8px 8px 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:4px;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;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.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);left:0;z-index:10;min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;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:6px;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)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["prevLabel", "nextLabel", "regionLabel", "total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StrctCheckbox, selector: "strct-checkbox", inputs: ["checked", "isDisabled", "disabled", "indeterminate", "ariaLabel"], outputs: ["checkedChange", "isDisabledChange"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }, { kind: "component", type: StrctButtonGroup, selector: "strct-button-group" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
8624
+ `, isInline: true, styles: [".strct-dg-host{display:block;border:1px solid var(--b2);border-radius:10px;background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th{position:sticky;top:0;z-index:5}.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:12.5px;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__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:9px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .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:3}.strct-dg thead th.strct-dg__cell--sticky{z-index:6}.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:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.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__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:2}.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:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.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:5px;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{display:inline-flex;padding:3px;border:0;border-radius:4px;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:4px;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:260px;min-width:260px;max-width:260px}.strct-dg__layout--paned .strct-dg{width:260px;min-width:260px;max-width:260px;flex-shrink:0;border-top-right-radius:0;border-bottom-right-radius:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.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;right: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:0 8px 8px 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:4px;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;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.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);left:0;z-index:10;min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;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:6px;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)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["prevLabel", "nextLabel", "regionLabel", "total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StrctCheckbox, selector: "strct-checkbox", inputs: ["checked", "isDisabled", "disabled", "indeterminate", "ariaLabel"], outputs: ["checkedChange", "isDisabledChange"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }, { kind: "component", type: StrctButtonGroup, selector: "strct-button-group" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
8343
8625
  }
8344
8626
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDatagrid, decorators: [{
8345
8627
  type: Component,
@@ -8400,11 +8682,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
8400
8682
  [style.text-align]="col.align ?? 'start'"
8401
8683
  [style.width]="colWidth(col.key) ?? col.width ?? null"
8402
8684
  [class.strct-dg__th--sortable]="col.sortable"
8685
+ [class.strct-dg__th--drop]="col.key === dropKey()"
8403
8686
  [class.strct-dg__cell--sticky]="isSticky(col)"
8404
8687
  [class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
8405
8688
  [style.insetInlineStart.px]="stickyLeft(col.key)"
8406
8689
  [attr.tabindex]="col.sortable ? 0 : null"
8407
8690
  [attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
8691
+ [attr.draggable]="reorderable() ? true : null"
8692
+ (dragstart)="onColDragStart(col.key, $event)"
8693
+ (dragover)="onColDragOver(col.key, $event)"
8694
+ (drop)="onColDrop(col.key)"
8695
+ (dragend)="onColDragEnd()"
8408
8696
  (click)="col.sortable && sortBy(col.key)"
8409
8697
  (keydown.enter)="col.sortable && sortBy(col.key)"
8410
8698
  (keydown.space)="col.sortable && onHeaderSpace($event, col.key)"
@@ -8461,105 +8749,129 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
8461
8749
  <td [attr.colspan]="colspan()" [style.height.px]="topPad()"></td>
8462
8750
  </tr>
8463
8751
  }
8464
- @for (row of renderRows(); track rowKey(row)) {
8465
- <tr
8466
- [class.strct-dg__row--selected]="isSelected(row)"
8467
- [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
8468
- >
8469
- @if (canDetail()) {
8470
- <td
8471
- class="strct-dg__expandcell"
8472
- [class.strct-dg__cell--sticky]="stickyActive()"
8473
- [style.insetInlineStart.px]="utilLeft('detail')"
8474
- >
8752
+ @for (it of displayItems(); track itemKey(it)) {
8753
+ @if (it.group; as grp) {
8754
+ <!-- Group header: distinct value + count, collapsible. -->
8755
+ <tr class="strct-dg__grouprow">
8756
+ <td [attr.colspan]="colspan()">
8475
8757
  <button
8476
8758
  type="button"
8477
- class="strct-dg__detailbtn"
8478
- [class.strct-dg__detailbtn--active]="row === activeRow()"
8479
- [attr.aria-expanded]="row === activeRow()"
8480
- [attr.aria-label]="L().openDetail"
8481
- (click)="openDetail(row)"
8759
+ class="strct-dg__groupbtn"
8760
+ [attr.aria-expanded]="!grp.collapsed"
8761
+ (click)="toggleGroup(grp.key)"
8482
8762
  >
8483
- <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
8763
+ <span
8764
+ class="strct-dg__groupchev"
8765
+ [class.strct-dg__groupchev--open]="!grp.collapsed"
8766
+ >
8767
+ <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
8768
+ </span>
8769
+ <span class="strct-dg__grouplabel">{{ grp.label }}</span>
8770
+ <span class="strct-dg__groupcount">{{ grp.count }}</span>
8484
8771
  </button>
8485
8772
  </td>
8486
- }
8487
- @if (canExpand()) {
8488
- <td
8489
- class="strct-dg__expandcell"
8490
- [class.strct-dg__cell--sticky]="stickyActive()"
8491
- [style.insetInlineStart.px]="utilLeft('expand')"
8492
- >
8493
- <button
8494
- type="button"
8495
- class="strct-dg__expandbtn"
8496
- [class.strct-dg__expandbtn--open]="isExpanded(row)"
8497
- [attr.aria-expanded]="isExpanded(row)"
8498
- [attr.aria-label]="L().toggleDetail"
8499
- (click)="toggleExpand(row)"
8773
+ </tr>
8774
+ } @else {
8775
+ @let row = it.row!;
8776
+ <tr
8777
+ [class.strct-dg__row--selected]="isSelected(row)"
8778
+ [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
8779
+ >
8780
+ @if (canDetail()) {
8781
+ <td
8782
+ class="strct-dg__expandcell"
8783
+ [class.strct-dg__cell--sticky]="stickyActive()"
8784
+ [style.insetInlineStart.px]="utilLeft('detail')"
8500
8785
  >
8501
- <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
8502
- </button>
8503
- </td>
8504
- }
8505
- @if (selectable()) {
8506
- <td
8507
- class="strct-dg__sel"
8508
- [class.strct-dg__cell--sticky]="stickyActive()"
8509
- [style.insetInlineStart.px]="utilLeft('sel')"
8510
- >
8511
- <strct-checkbox
8512
- [ariaLabel]="L().selectRow"
8513
- [checked]="isSelected(row)"
8514
- (checkedChange)="toggleRow(row)"
8515
- />
8516
- </td>
8517
- }
8518
- @for (col of visibleColumns(); track col.key) {
8519
- <td
8520
- [style.text-align]="col.align ?? 'start'"
8521
- [class.strct-dg__cell--sticky]="isSticky(col)"
8522
- [class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
8523
- [style.insetInlineStart.px]="stickyLeft(col.key)"
8524
- >
8525
- @if (cellTemplate(col.key); as tpl) {
8526
- <ng-container
8527
- [ngTemplateOutlet]="tpl"
8528
- [ngTemplateOutletContext]="{
8529
- $implicit: row,
8530
- value: row[col.key],
8531
- column: col,
8532
- }"
8533
- />
8534
- } @else {
8535
- {{ row[col.key] }}
8536
- }
8537
- </td>
8538
- }
8539
- @if (canActions()) {
8540
- <td class="strct-dg__actioncell">
8541
- <button
8542
- type="button"
8543
- class="strct-dg__kebab"
8544
- [attr.aria-label]="L().rowActions"
8545
- (click)="openRowMenu(row, $event)"
8786
+ <button
8787
+ type="button"
8788
+ class="strct-dg__detailbtn"
8789
+ [class.strct-dg__detailbtn--active]="row === activeRow()"
8790
+ [attr.aria-expanded]="row === activeRow()"
8791
+ [attr.aria-label]="L().openDetail"
8792
+ (click)="openDetail(row)"
8793
+ >
8794
+ <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
8795
+ </button>
8796
+ </td>
8797
+ }
8798
+ @if (canExpand()) {
8799
+ <td
8800
+ class="strct-dg__expandcell"
8801
+ [class.strct-dg__cell--sticky]="stickyActive()"
8802
+ [style.insetInlineStart.px]="utilLeft('expand')"
8546
8803
  >
8547
- <strct-icon name="dots" [size]="16" />
8548
- </button>
8549
- </td>
8550
- }
8551
- </tr>
8552
- @if (canExpand() && isExpanded(row)) {
8553
- <tr class="strct-dg__detailrow">
8554
- <td [attr.colspan]="colspan()">
8555
- <div class="strct-dg__detail">
8556
- <ng-container
8557
- [ngTemplateOutlet]="detailDef()!.template"
8558
- [ngTemplateOutletContext]="{ $implicit: row }"
8804
+ <button
8805
+ type="button"
8806
+ class="strct-dg__expandbtn"
8807
+ [class.strct-dg__expandbtn--open]="isExpanded(row)"
8808
+ [attr.aria-expanded]="isExpanded(row)"
8809
+ [attr.aria-label]="L().toggleDetail"
8810
+ (click)="toggleExpand(row)"
8811
+ >
8812
+ <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
8813
+ </button>
8814
+ </td>
8815
+ }
8816
+ @if (selectable()) {
8817
+ <td
8818
+ class="strct-dg__sel"
8819
+ [class.strct-dg__cell--sticky]="stickyActive()"
8820
+ [style.insetInlineStart.px]="utilLeft('sel')"
8821
+ >
8822
+ <strct-checkbox
8823
+ [ariaLabel]="L().selectRow"
8824
+ [checked]="isSelected(row)"
8825
+ (checkedChange)="toggleRow(row)"
8559
8826
  />
8560
- </div>
8561
- </td>
8827
+ </td>
8828
+ }
8829
+ @for (col of visibleColumns(); track col.key) {
8830
+ <td
8831
+ [style.text-align]="col.align ?? 'start'"
8832
+ [class.strct-dg__cell--sticky]="isSticky(col)"
8833
+ [class.strct-dg__cell--sticky-last]="col.key === lastStickyKey()"
8834
+ [style.insetInlineStart.px]="stickyLeft(col.key)"
8835
+ >
8836
+ @if (cellTemplate(col.key); as tpl) {
8837
+ <ng-container
8838
+ [ngTemplateOutlet]="tpl"
8839
+ [ngTemplateOutletContext]="{
8840
+ $implicit: row,
8841
+ value: row[col.key],
8842
+ column: col,
8843
+ }"
8844
+ />
8845
+ } @else {
8846
+ {{ row[col.key] }}
8847
+ }
8848
+ </td>
8849
+ }
8850
+ @if (canActions()) {
8851
+ <td class="strct-dg__actioncell">
8852
+ <button
8853
+ type="button"
8854
+ class="strct-dg__kebab"
8855
+ [attr.aria-label]="L().rowActions"
8856
+ (click)="openRowMenu(row, $event)"
8857
+ >
8858
+ <strct-icon name="dots" [size]="16" />
8859
+ </button>
8860
+ </td>
8861
+ }
8562
8862
  </tr>
8863
+ @if (canExpand() && isExpanded(row)) {
8864
+ <tr class="strct-dg__detailrow">
8865
+ <td [attr.colspan]="colspan()">
8866
+ <div class="strct-dg__detail">
8867
+ <ng-container
8868
+ [ngTemplateOutlet]="detailDef()!.template"
8869
+ [ngTemplateOutletContext]="{ $implicit: row }"
8870
+ />
8871
+ </div>
8872
+ </td>
8873
+ </tr>
8874
+ }
8563
8875
  }
8564
8876
  } @empty {
8565
8877
  <tr>
@@ -8653,7 +8965,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
8653
8965
  </span>
8654
8966
  </div>
8655
8967
  <div class="strct-dg__foot-right">
8656
- @if (pageSize() > 0) {
8968
+ @if (pageSize() > 0 && !groupBy()) {
8657
8969
  <strct-pagination [total]="totalCount()" [pageSize]="pageSize()" [(page)]="page" />
8658
8970
  }
8659
8971
  </div>
@@ -8665,8 +8977,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
8665
8977
  '[class.strct-dg-host--singleline]': 'singleLine()',
8666
8978
  '[class.strct-dg-host--virtual]': 'virtual()',
8667
8979
  '[class.strct-dg-host--sticky]': 'stickyActive()',
8668
- }, styles: [".strct-dg-host{display:block;border:1px solid var(--b2);border-radius:10px;background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th{position:sticky;top:0;z-index:5}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .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:3}.strct-dg thead th.strct-dg__cell--sticky{z-index:6}.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:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.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__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:2}.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:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.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:5px;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{display:inline-flex;padding:3px;border:0;border-radius:4px;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:4px;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:260px;min-width:260px;max-width:260px}.strct-dg__layout--paned .strct-dg{width:260px;min-width:260px;max-width:260px;flex-shrink:0;border-top-right-radius:0;border-bottom-right-radius:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.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;right: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:0 8px 8px 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:4px;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;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.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);left:0;z-index:10;min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;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:6px;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)}\n"] }]
8669
- }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], detailPane: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailPane", required: false }] }], 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 }] }], sync: [{ type: i0.Input, args: [{ isSignal: true, alias: "sync", required: false }] }], footerActionsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerActionsDisabled", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], initialSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSelection", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], virtual: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtual", required: false }] }], viewportHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewportHeight", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], columnState: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnState", required: false }] }, { type: i0.Output, args: ["columnStateChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], syncChange: [{ type: i0.Output, args: ["syncChange"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], detailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctRowDetailDef), { isSignal: true }] }], actionBarDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBar), { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }] } });
8980
+ }, styles: [".strct-dg-host{display:block;border:1px solid var(--b2);border-radius:10px;background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th{position:sticky;top:0;z-index:5}.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:12.5px;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__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:9px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .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:3}.strct-dg thead th.strct-dg__cell--sticky{z-index:6}.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:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.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__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:2}.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:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.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:5px;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{display:inline-flex;padding:3px;border:0;border-radius:4px;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:4px;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:260px;min-width:260px;max-width:260px}.strct-dg__layout--paned .strct-dg{width:260px;min-width:260px;max-width:260px;flex-shrink:0;border-top-right-radius:0;border-bottom-right-radius:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.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;right: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:0 8px 8px 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:4px;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;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.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);left:0;z-index:10;min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;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:6px;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)}\n"] }]
8981
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], detailPane: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailPane", required: false }] }], 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 }] }], sync: [{ type: i0.Input, args: [{ isSignal: true, alias: "sync", required: false }] }], footerActionsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerActionsDisabled", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], initialSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSelection", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], virtual: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtual", required: false }] }], viewportHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewportHeight", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], columnState: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnState", required: false }] }, { type: i0.Output, args: ["columnStateChange"] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], syncChange: [{ type: i0.Output, args: ["syncChange"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], detailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctRowDetailDef), { isSignal: true }] }], actionBarDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBar), { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }] } });
8670
8982
 
8671
8983
  /** Vertical timeline container. Wraps `<strct-timeline-item>` children. */
8672
8984
  class StrctTimeline {
@@ -9054,6 +9366,19 @@ class StrctChart {
9054
9366
  * Double-click, Escape or the reset chip zooms back out.
9055
9367
  */
9056
9368
  zoom = input(false, { ...(ngDevMode ? { debugName: "zoom" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
9369
+ /**
9370
+ * Stack multi-series values cumulatively: each series draws its line at the
9371
+ * running total and fills the band down to the series below (nulls break the
9372
+ * stack at that slot). Tooltips keep the original per-series values.
9373
+ */
9374
+ stacked = input(false, { ...(ngDevMode ? { debugName: "stacked" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
9375
+ /** Y-axis scale. `log` needs positive values; non-positives clamp to the floor. */
9376
+ scale = input('linear', ...(ngDevMode ? [{ debugName: "scale" }] : /* istanbul ignore next */ []));
9377
+ /**
9378
+ * Per-point timestamps (ms epoch or Date). When set, x positions map to real
9379
+ * time, so uneven sampling renders honestly instead of equally spaced.
9380
+ */
9381
+ times = input(null, ...(ngDevMode ? [{ debugName: "times" }] : /* istanbul ignore next */ []));
9057
9382
  /** Tooltip text for a gap (null) point. */
9058
9383
  gapText = input('no data', ...(ngDevMode ? [{ debugName: "gapText" }] : /* istanbul ignore next */ []));
9059
9384
  /** Accessible label of the reset-zoom chip (localizable). */
@@ -9176,7 +9501,8 @@ class StrctChart {
9176
9501
  const [s, e] = this.domain();
9177
9502
  return e > s ? this.chartW() / (e - s) : 0;
9178
9503
  }
9179
- /** Real values inside the visible window (multi-aware; bands included). */
9504
+ /** Real values inside the visible window (multi-aware; bands included;
9505
+ * per-slot totals when stacked). */
9180
9506
  visibleValues = computed(() => {
9181
9507
  const [s, e] = this.domain();
9182
9508
  const out = [];
@@ -9185,6 +9511,26 @@ class StrctChart {
9185
9511
  out.push(v);
9186
9512
  };
9187
9513
  const ser = this.seriesResolved();
9514
+ if (ser && this.stacked() && ser.length > 1) {
9515
+ const N = this.nx();
9516
+ const totals = new Array(N).fill(0);
9517
+ const has = new Array(N).fill(false);
9518
+ for (const x of ser) {
9519
+ const data = x.data ?? [];
9520
+ const offset = N - data.length;
9521
+ for (let li = 0; li < data.length; li++) {
9522
+ const v = data[li];
9523
+ if (isVal(v)) {
9524
+ totals[offset + li] += v;
9525
+ has[offset + li] = true;
9526
+ }
9527
+ }
9528
+ }
9529
+ for (let gi = s; gi <= Math.min(e, N - 1); gi++)
9530
+ if (has[gi])
9531
+ out.push(totals[gi]);
9532
+ return out;
9533
+ }
9188
9534
  if (ser) {
9189
9535
  const N = this.nx();
9190
9536
  for (const x of ser) {
@@ -9214,13 +9560,34 @@ class StrctChart {
9214
9560
  return m === 0 ? 1 : m * 1.1;
9215
9561
  }, ...(ngDevMode ? [{ debugName: "yMax" }] : /* istanbul ignore next */ []));
9216
9562
  yMin = computed(() => this.min() ?? 0, ...(ngDevMode ? [{ debugName: "yMin" }] : /* istanbul ignore next */ []));
9563
+ /** Smallest positive visible value — the floor of a log axis. */
9564
+ logFloor = computed(() => {
9565
+ const explicit = this.min();
9566
+ if (explicit != null && explicit > 0)
9567
+ return explicit;
9568
+ const positives = this.visibleValues().filter((v) => v > 0);
9569
+ return positives.length ? Math.min(...positives) : 1;
9570
+ }, ...(ngDevMode ? [{ debugName: "logFloor" }] : /* istanbul ignore next */ []));
9217
9571
  yOf(v) {
9572
+ if (this.scale() === 'log') {
9573
+ const lo = this.logFloor();
9574
+ const hi = Math.max(this.yMax(), lo * 10);
9575
+ const c = Math.max(lo, Math.min(hi, v));
9576
+ const span = Math.log10(hi) - Math.log10(lo) || 1;
9577
+ const f = (Math.log10(c) - Math.log10(lo)) / span;
9578
+ return PAD.t + (1 - f) * this.chartH();
9579
+ }
9218
9580
  const lo = this.yMin();
9219
9581
  const hi = this.yMax();
9220
9582
  const range = hi - lo || 1;
9221
9583
  const c = Math.max(lo, Math.min(hi, v));
9222
9584
  return PAD.t + (1 - (c - lo) / range) * this.chartH();
9223
9585
  }
9586
+ /** Timestamps normalized to ms (null when the axis is index-based). */
9587
+ timesMs = computed(() => {
9588
+ const t = this.times();
9589
+ return t?.length ? t.map((v) => +v) : null;
9590
+ }, ...(ngDevMode ? [{ debugName: "timesMs" }] : /* istanbul ignore next */ []));
9224
9591
  // ── Single-series geometry (gap-aware; null keeps its x-slot) ──
9225
9592
  points = computed(() => {
9226
9593
  const d = this.data();
@@ -9250,6 +9617,46 @@ class StrctChart {
9250
9617
  return [];
9251
9618
  const N = this.nx();
9252
9619
  const base = this.height() - PAD.b;
9620
+ // Stacked: each series rides on the running total of the ones before it,
9621
+ // filling the band down to that total; a null breaks the stack there.
9622
+ if (this.stacked() && s.length > 1) {
9623
+ const running = new Array(N).fill(0);
9624
+ return s.map((x) => {
9625
+ const data = x.data ?? [];
9626
+ const offset = N - data.length;
9627
+ const pts = [];
9628
+ const lowerPts = [];
9629
+ for (let li = 0; li < data.length; li++) {
9630
+ const v = data[li];
9631
+ const gi = offset + li;
9632
+ if (isVal(v)) {
9633
+ const lo = running[gi];
9634
+ const hi = lo + v;
9635
+ running[gi] = hi;
9636
+ const px = this.xOf(gi);
9637
+ lowerPts.push({ x: px, y: this.yOf(lo) });
9638
+ pts.push({ x: px, y: this.yOf(hi) });
9639
+ }
9640
+ else {
9641
+ lowerPts.push(null);
9642
+ pts.push(null);
9643
+ }
9644
+ }
9645
+ const curve = x.curve ?? this.curve();
9646
+ return {
9647
+ color: COLOR$1[x.status ?? this.status()],
9648
+ label: x.label ?? '',
9649
+ area: false,
9650
+ dash: x.dash ? (typeof x.dash === 'string' ? x.dash : '5 4') : null,
9651
+ pts,
9652
+ path: pathForSegs(pts, curve),
9653
+ areaPath: '',
9654
+ bandPath: bandPath(pts, lowerPts, curve),
9655
+ offset,
9656
+ data,
9657
+ };
9658
+ });
9659
+ }
9253
9660
  return s.map((x) => {
9254
9661
  const data = x.data ?? [];
9255
9662
  const offset = N - data.length; // right-align shorter series
@@ -9320,10 +9727,23 @@ class StrctChart {
9320
9727
  yAxisTicks = computed(() => {
9321
9728
  if (!this.yAxis())
9322
9729
  return [];
9730
+ const out = [];
9731
+ if (this.scale() === 'log') {
9732
+ // Decade ticks between the floor and the max, endpoints included.
9733
+ const lo = this.logFloor();
9734
+ const hi = Math.max(this.yMax(), lo * 10);
9735
+ const values = new Set([lo, hi]);
9736
+ for (let p = Math.ceil(Math.log10(lo)); p <= Math.floor(Math.log10(hi)); p++) {
9737
+ values.add(10 ** p);
9738
+ }
9739
+ for (const v of [...values].sort((a, b) => a - b)) {
9740
+ out.push({ value: v, y: this.yOf(v), text: this.fmtAxis(v) });
9741
+ }
9742
+ return out;
9743
+ }
9323
9744
  const n = Math.max(2, this.yTicks());
9324
9745
  const lo = this.yMin();
9325
9746
  const hi = this.yMax();
9326
- const out = [];
9327
9747
  for (let i = 0; i < n; i++) {
9328
9748
  const v = lo + (hi - lo) * (i / (n - 1));
9329
9749
  out.push({ value: v, y: this.yOf(v), text: this.fmtAxis(v) });
@@ -9535,9 +9955,17 @@ class StrctChart {
9535
9955
  const value = this.hoverGap() ? this.gapText() : this.hoverValueText();
9536
9956
  return `${meta ? meta + ': ' : ''}${value}`;
9537
9957
  }, ...(ngDevMode ? [{ debugName: "srText" }] : /* istanbul ignore next */ []));
9538
- /** Pixel x of a data index (shared by the plot, labels and annotations). */
9958
+ /** Pixel x of a data index (shared by the plot, labels and annotations).
9959
+ * With `times`, positions map to real timestamps — uneven sampling shows. */
9539
9960
  xOf(i) {
9540
- const [s] = this.domain();
9961
+ const [s, e] = this.domain();
9962
+ const t = this.timesMs();
9963
+ if (t && e > s) {
9964
+ const clamp = (k) => Math.min(Math.max(k, 0), t.length - 1);
9965
+ const t0 = t[clamp(s)];
9966
+ const span = t[clamp(e)] - t0 || 1;
9967
+ return this.pl() + ((t[clamp(i)] - t0) / span) * this.chartW();
9968
+ }
9541
9969
  return this.pl() + (i - s) * this.stepX();
9542
9970
  }
9543
9971
  /** Set the local hover index, emitting `hoverIndex` on change. */
@@ -9596,10 +10024,24 @@ class StrctChart {
9596
10024
  const rect = el.getBoundingClientRect();
9597
10025
  if (!rect.width)
9598
10026
  return null;
10027
+ const [s, e] = this.domain();
10028
+ if (this.timesMs()) {
10029
+ // Non-uniform x: nearest point by pixel distance.
10030
+ const svgX = ((event.clientX - rect.left) / rect.width) * this.width();
10031
+ let best = s;
10032
+ let bestDist = Infinity;
10033
+ for (let i = s; i <= e; i++) {
10034
+ const d = Math.abs(this.xOf(i) - svgX);
10035
+ if (d < bestDist) {
10036
+ bestDist = d;
10037
+ best = i;
10038
+ }
10039
+ }
10040
+ return best;
10041
+ }
9599
10042
  const plFrac = this.pl() / this.width();
9600
10043
  const rFrac = PAD.r / this.width();
9601
10044
  const fx = ((event.clientX - rect.left) / rect.width - plFrac) / (1 - plFrac - rFrac);
9602
- const [s, e] = this.domain();
9603
10045
  return Math.max(s, Math.min(e, s + Math.round(fx * (e - s))));
9604
10046
  }
9605
10047
  onDown(event) {
@@ -9746,7 +10188,7 @@ class StrctChart {
9746
10188
  });
9747
10189
  }
9748
10190
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
9749
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctChart, isStandalone: true, selector: "strct-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, curve: { classPropertyName: "curve", publicName: "curve", isSignal: true, isRequired: false, transformFunction: null }, area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, glow: { classPropertyName: "glow", publicName: "glow", isSignal: true, isRequired: false, transformFunction: null }, live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, grid: { classPropertyName: "grid", publicName: "grid", isSignal: true, isRequired: false, transformFunction: null }, dots: { classPropertyName: "dots", publicName: "dots", isSignal: true, isRequired: false, transformFunction: null }, legend: { classPropertyName: "legend", publicName: "legend", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, xTicks: { classPropertyName: "xTicks", publicName: "xTicks", isSignal: true, isRequired: false, transformFunction: null }, xFormat: { classPropertyName: "xFormat", publicName: "xFormat", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, yAxis: { classPropertyName: "yAxis", publicName: "yAxis", isSignal: true, isRequired: false, transformFunction: null }, yTicks: { classPropertyName: "yTicks", publicName: "yTicks", isSignal: true, isRequired: false, transformFunction: null }, axisFormat: { classPropertyName: "axisFormat", publicName: "axisFormat", isSignal: true, isRequired: false, transformFunction: null }, thresholds: { classPropertyName: "thresholds", publicName: "thresholds", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, agoFormat: { classPropertyName: "agoFormat", publicName: "agoFormat", isSignal: true, isRequired: false, transformFunction: null }, valueFormat: { classPropertyName: "valueFormat", publicName: "valueFormat", isSignal: true, isRequired: false, transformFunction: null }, annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, brush: { classPropertyName: "brush", publicName: "brush", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, gapText: { classPropertyName: "gapText", publicName: "gapText", isSignal: true, isRequired: false, transformFunction: null }, resetLabel: { classPropertyName: "resetLabel", publicName: "resetLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { hoverIndex: "hoverIndex", brushChange: "brushChange" }, host: { properties: { "class.strct-chart--glow": "glow()", "class.strct-chart--brush": "brush() || zoom()", "style.--strct-chart-c": "color()" }, classAttribute: "strct-chart" }, viewQueries: [{ propertyName: "svgRef", first: true, predicate: ["svg"], descendants: true, isSignal: true }], ngImport: i0, template: `
10191
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctChart, isStandalone: true, selector: "strct-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, curve: { classPropertyName: "curve", publicName: "curve", isSignal: true, isRequired: false, transformFunction: null }, area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, glow: { classPropertyName: "glow", publicName: "glow", isSignal: true, isRequired: false, transformFunction: null }, live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, grid: { classPropertyName: "grid", publicName: "grid", isSignal: true, isRequired: false, transformFunction: null }, dots: { classPropertyName: "dots", publicName: "dots", isSignal: true, isRequired: false, transformFunction: null }, legend: { classPropertyName: "legend", publicName: "legend", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, xTicks: { classPropertyName: "xTicks", publicName: "xTicks", isSignal: true, isRequired: false, transformFunction: null }, xFormat: { classPropertyName: "xFormat", publicName: "xFormat", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, yAxis: { classPropertyName: "yAxis", publicName: "yAxis", isSignal: true, isRequired: false, transformFunction: null }, yTicks: { classPropertyName: "yTicks", publicName: "yTicks", isSignal: true, isRequired: false, transformFunction: null }, axisFormat: { classPropertyName: "axisFormat", publicName: "axisFormat", isSignal: true, isRequired: false, transformFunction: null }, thresholds: { classPropertyName: "thresholds", publicName: "thresholds", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, agoFormat: { classPropertyName: "agoFormat", publicName: "agoFormat", isSignal: true, isRequired: false, transformFunction: null }, valueFormat: { classPropertyName: "valueFormat", publicName: "valueFormat", isSignal: true, isRequired: false, transformFunction: null }, annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, brush: { classPropertyName: "brush", publicName: "brush", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, times: { classPropertyName: "times", publicName: "times", isSignal: true, isRequired: false, transformFunction: null }, gapText: { classPropertyName: "gapText", publicName: "gapText", isSignal: true, isRequired: false, transformFunction: null }, resetLabel: { classPropertyName: "resetLabel", publicName: "resetLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { hoverIndex: "hoverIndex", brushChange: "brushChange" }, host: { properties: { "class.strct-chart--glow": "glow()", "class.strct-chart--brush": "brush() || zoom()", "style.--strct-chart-c": "color()" }, classAttribute: "strct-chart" }, viewQueries: [{ propertyName: "svgRef", first: true, predicate: ["svg"], descendants: true, isSignal: true }], ngImport: i0, template: `
9750
10192
  @if (isEmpty()) {
9751
10193
  <div class="strct-chart__empty" [style.height.px]="height()">{{ emptyText() }}</div>
9752
10194
  } @else {
@@ -9846,7 +10288,12 @@ class StrctChart {
9846
10288
  @if (isMulti()) {
9847
10289
  @for (s of multiSeries(); track $index) {
9848
10290
  @if (s.bandPath) {
9849
- <path class="strct-chart__band" [attr.d]="s.bandPath" [attr.fill]="s.color" />
10291
+ <path
10292
+ class="strct-chart__band"
10293
+ [class.strct-chart__band--stack]="stacked()"
10294
+ [attr.d]="s.bandPath"
10295
+ [attr.fill]="s.color"
10296
+ />
9850
10297
  }
9851
10298
  @if (s.area && s.areaPath) {
9852
10299
  <path
@@ -10065,7 +10512,7 @@ class StrctChart {
10065
10512
  </div>
10066
10513
  }
10067
10514
  }
10068
- `, isInline: true, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart__band{opacity:.13;stroke:none}.strct-chart__ann{stroke-width:1;opacity:.8;vector-effect:non-scaling-stroke}.strct-chart__ann--dashed{stroke-dasharray:4 3}.strct-chart__ann-label{position:absolute;top:0;transform:translate(-50%);pointer-events:none;font-size:12px;font-weight:600;background:var(--bg-1);padding:0 3px;border-radius:3px;white-space:nowrap}.strct-chart--brush .strct-chart__svg{cursor:crosshair}.strct-chart__brush{fill:var(--acc);opacity:.16;stroke:var(--acc50);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__reset{position:absolute;top:6px;right:8px;z-index:3;display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border:1px solid var(--b2);border-radius:99px;background:var(--bg-a);color:var(--t2);font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer}.strct-chart__reset:hover{color:var(--t1);border-color:var(--acc50)}.strct-chart__reset:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-chart__tip--gap{top:6px;transform:translate(-50%)}.strct-chart__tip-ann{font-size:12px;font-weight:600}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10515
+ `, isInline: true, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart__band{opacity:.13;stroke:none}.strct-chart__band--stack{opacity:.32}.strct-chart__ann{stroke-width:1;opacity:.8;vector-effect:non-scaling-stroke}.strct-chart__ann--dashed{stroke-dasharray:4 3}.strct-chart__ann-label{position:absolute;top:0;transform:translate(-50%);pointer-events:none;font-size:12px;font-weight:600;background:var(--bg-1);padding:0 3px;border-radius:3px;white-space:nowrap}.strct-chart--brush .strct-chart__svg{cursor:crosshair}.strct-chart__brush{fill:var(--acc);opacity:.16;stroke:var(--acc50);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__reset{position:absolute;top:6px;right:8px;z-index:3;display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border:1px solid var(--b2);border-radius:99px;background:var(--bg-a);color:var(--t2);font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer}.strct-chart__reset:hover{color:var(--t1);border-color:var(--acc50)}.strct-chart__reset:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-chart__tip--gap{top:6px;transform:translate(-50%)}.strct-chart__tip-ann{font-size:12px;font-weight:600}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10069
10516
  }
10070
10517
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctChart, decorators: [{
10071
10518
  type: Component,
@@ -10169,7 +10616,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
10169
10616
  @if (isMulti()) {
10170
10617
  @for (s of multiSeries(); track $index) {
10171
10618
  @if (s.bandPath) {
10172
- <path class="strct-chart__band" [attr.d]="s.bandPath" [attr.fill]="s.color" />
10619
+ <path
10620
+ class="strct-chart__band"
10621
+ [class.strct-chart__band--stack]="stacked()"
10622
+ [attr.d]="s.bandPath"
10623
+ [attr.fill]="s.color"
10624
+ />
10173
10625
  }
10174
10626
  @if (s.area && s.areaPath) {
10175
10627
  <path
@@ -10393,8 +10845,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
10393
10845
  '[class.strct-chart--glow]': 'glow()',
10394
10846
  '[class.strct-chart--brush]': 'brush() || zoom()',
10395
10847
  '[style.--strct-chart-c]': 'color()',
10396
- }, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart__band{opacity:.13;stroke:none}.strct-chart__ann{stroke-width:1;opacity:.8;vector-effect:non-scaling-stroke}.strct-chart__ann--dashed{stroke-dasharray:4 3}.strct-chart__ann-label{position:absolute;top:0;transform:translate(-50%);pointer-events:none;font-size:12px;font-weight:600;background:var(--bg-1);padding:0 3px;border-radius:3px;white-space:nowrap}.strct-chart--brush .strct-chart__svg{cursor:crosshair}.strct-chart__brush{fill:var(--acc);opacity:.16;stroke:var(--acc50);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__reset{position:absolute;top:6px;right:8px;z-index:3;display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border:1px solid var(--b2);border-radius:99px;background:var(--bg-a);color:var(--t2);font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer}.strct-chart__reset:hover{color:var(--t1);border-color:var(--acc50)}.strct-chart__reset:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-chart__tip--gap{top:6px;transform:translate(-50%)}.strct-chart__tip-ann{font-size:12px;font-weight:600}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"] }]
10397
- }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], curve: [{ type: i0.Input, args: [{ isSignal: true, alias: "curve", required: false }] }], area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], glow: [{ type: i0.Input, args: [{ isSignal: true, alias: "glow", required: false }] }], live: [{ type: i0.Input, args: [{ isSignal: true, alias: "live", required: false }] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: false }] }], dots: [{ type: i0.Input, args: [{ isSignal: true, alias: "dots", required: false }] }], legend: [{ type: i0.Input, args: [{ isSignal: true, alias: "legend", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], xTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "xTicks", required: false }] }], xFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "xFormat", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], yAxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "yAxis", required: false }] }], yTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "yTicks", required: false }] }], axisFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "axisFormat", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], agoFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "agoFormat", required: false }] }], valueFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormat", required: false }] }], annotations: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotations", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], brush: [{ type: i0.Input, args: [{ isSignal: true, alias: "brush", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], gapText: [{ type: i0.Input, args: [{ isSignal: true, alias: "gapText", required: false }] }], resetLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetLabel", required: false }] }], hoverIndex: [{ type: i0.Output, args: ["hoverIndex"] }], brushChange: [{ type: i0.Output, args: ["brushChange"] }], svgRef: [{ type: i0.ViewChild, args: ['svg', { isSignal: true }] }] } });
10848
+ }, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart__band{opacity:.13;stroke:none}.strct-chart__band--stack{opacity:.32}.strct-chart__ann{stroke-width:1;opacity:.8;vector-effect:non-scaling-stroke}.strct-chart__ann--dashed{stroke-dasharray:4 3}.strct-chart__ann-label{position:absolute;top:0;transform:translate(-50%);pointer-events:none;font-size:12px;font-weight:600;background:var(--bg-1);padding:0 3px;border-radius:3px;white-space:nowrap}.strct-chart--brush .strct-chart__svg{cursor:crosshair}.strct-chart__brush{fill:var(--acc);opacity:.16;stroke:var(--acc50);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__reset{position:absolute;top:6px;right:8px;z-index:3;display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border:1px solid var(--b2);border-radius:99px;background:var(--bg-a);color:var(--t2);font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer}.strct-chart__reset:hover{color:var(--t1);border-color:var(--acc50)}.strct-chart__reset:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-chart__tip--gap{top:6px;transform:translate(-50%)}.strct-chart__tip-ann{font-size:12px;font-weight:600}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"] }]
10849
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], curve: [{ type: i0.Input, args: [{ isSignal: true, alias: "curve", required: false }] }], area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], glow: [{ type: i0.Input, args: [{ isSignal: true, alias: "glow", required: false }] }], live: [{ type: i0.Input, args: [{ isSignal: true, alias: "live", required: false }] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: false }] }], dots: [{ type: i0.Input, args: [{ isSignal: true, alias: "dots", required: false }] }], legend: [{ type: i0.Input, args: [{ isSignal: true, alias: "legend", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], xTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "xTicks", required: false }] }], xFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "xFormat", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], yAxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "yAxis", required: false }] }], yTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "yTicks", required: false }] }], axisFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "axisFormat", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], agoFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "agoFormat", required: false }] }], valueFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormat", required: false }] }], annotations: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotations", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], brush: [{ type: i0.Input, args: [{ isSignal: true, alias: "brush", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], stacked: [{ type: i0.Input, args: [{ isSignal: true, alias: "stacked", required: false }] }], scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: false }] }], times: [{ type: i0.Input, args: [{ isSignal: true, alias: "times", required: false }] }], gapText: [{ type: i0.Input, args: [{ isSignal: true, alias: "gapText", required: false }] }], resetLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetLabel", required: false }] }], hoverIndex: [{ type: i0.Output, args: ["hoverIndex"] }], brushChange: [{ type: i0.Output, args: ["brushChange"] }], svgRef: [{ type: i0.ViewChild, args: ['svg', { isSignal: true }] }] } });
10398
10850
 
10399
10851
  const PALETTE = [
10400
10852
  'var(--acc)',