@mk-kit/ui 0.34.1 → 0.36.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.
@@ -67,6 +67,108 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
67
67
  }]
68
68
  }], propDecorators: { mkTableCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkTableCell", required: true }] }] } });
69
69
 
70
+ /**
71
+ * CSV export — turn rows into RFC 4180 text and hand it to the browser as a
72
+ * download. Framework-free so it also serves data that never touched a table.
73
+ */
74
+ const NEEDS_QUOTES = /["\r\n]/;
75
+ const FORMULA_LEAD = /^[=+\-@\t\r]/;
76
+ /** Escape one cell for CSV. */
77
+ function csvCell(value, delimiter, sanitize) {
78
+ if (value == null)
79
+ return '';
80
+ let text;
81
+ if (typeof value === 'string') {
82
+ text = sanitize && FORMULA_LEAD.test(value) ? `'${value}` : value;
83
+ }
84
+ else if (value instanceof Date) {
85
+ text = value.toISOString();
86
+ }
87
+ else if (typeof value === 'object') {
88
+ text = JSON.stringify(value);
89
+ }
90
+ else {
91
+ text = String(value);
92
+ }
93
+ return NEEDS_QUOTES.test(text) || text.includes(delimiter) || /^\s|\s$/.test(text)
94
+ ? `"${text.replace(/"/g, '""')}"`
95
+ : text;
96
+ }
97
+ /**
98
+ * Serialise `rows` as CSV text.
99
+ *
100
+ * Without `columns` every key of the first row is exported in its own order.
101
+ * Column formatters are applied, so what the user saw in the table is what
102
+ * lands in the file.
103
+ */
104
+ function mkToCsv(rows, columns, options = {}) {
105
+ const delimiter = options.delimiter ?? ',';
106
+ const newline = options.newline ?? '\r\n';
107
+ const sanitize = options.sanitize ?? true;
108
+ const cols = columns ??
109
+ Object.keys((rows[0] ?? {}))
110
+ .filter((key) => key !== options.childrenKey)
111
+ .map((key) => ({ key }));
112
+ const flat = [];
113
+ const walk = (list) => {
114
+ for (const row of list) {
115
+ flat.push(row);
116
+ const children = options.childrenKey
117
+ ? row[options.childrenKey]
118
+ : null;
119
+ if (Array.isArray(children))
120
+ walk(children);
121
+ }
122
+ };
123
+ walk(rows);
124
+ const lines = [];
125
+ if (options.header ?? true) {
126
+ lines.push(cols.map((c) => csvCell(c.header ?? c.key, delimiter, sanitize)).join(delimiter));
127
+ }
128
+ for (const row of flat) {
129
+ lines.push(cols
130
+ .map((c) => {
131
+ const raw = row[c.key];
132
+ const value = c.format ? c.format(raw, row) : raw;
133
+ return csvCell(value, delimiter, sanitize);
134
+ })
135
+ .join(delimiter));
136
+ }
137
+ return (options.bom ?? true ? '' : '') + lines.join(newline) + newline;
138
+ }
139
+ /**
140
+ * Trigger a browser download of `text` as a file. No-op outside a DOM
141
+ * (server-side rendering); returns whether a download was started.
142
+ */
143
+ function mkDownloadText(text, filename, type = 'text/csv;charset=utf-8') {
144
+ if (typeof document === 'undefined' || typeof URL?.createObjectURL !== 'function')
145
+ return false;
146
+ const url = URL.createObjectURL(new Blob([text], { type }));
147
+ const a = document.createElement('a');
148
+ a.href = url;
149
+ a.download = filename;
150
+ a.rel = 'noopener';
151
+ a.style.display = 'none';
152
+ document.body.appendChild(a);
153
+ a.click();
154
+ a.remove();
155
+ // Give the click a tick to grab the blob before the URL is released.
156
+ setTimeout(() => URL.revokeObjectURL(url), 0);
157
+ return true;
158
+ }
159
+ /**
160
+ * Serialise `rows` as CSV and download it. Returns the CSV text so callers
161
+ * can also keep it (tests, previews, uploads).
162
+ */
163
+ function mkExportCsv(rows, columns, options = {}) {
164
+ const csv = mkToCsv(rows, columns, options);
165
+ let filename = options.filename ?? 'export.csv';
166
+ if (!/\.csv$/i.test(filename))
167
+ filename += '.csv';
168
+ mkDownloadText(csv, filename);
169
+ return csv;
170
+ }
171
+
70
172
  /** Hard floor (px) for column resize when a column sets no `minWidth`. */
71
173
  const MIN_COL_WIDTH = 60;
72
174
  /** Upper bound advertised on resize separators (`aria-valuemax`). */
@@ -239,6 +341,16 @@ class MkTable {
239
341
  cellEdit = output();
240
342
  /** Emitted when a group header is expanded or collapsed. */
241
343
  groupToggle = output();
344
+ /**
345
+ * Tree rows: the property on each row holding its child rows (`T[]`). When
346
+ * set, the table renders a tree grid — child rows are indented under their
347
+ * parent behind an expand toggle in the first column, sorting applies per
348
+ * sibling group, and ArrowRight / ArrowLeft on a row open / close it.
349
+ */
350
+ childrenKey = input(null, /* @ts-ignore */
351
+ ...(ngDevMode ? [{ debugName: "childrenKey" }] : /* istanbul ignore next */ []));
352
+ /** Emitted when a parent row is expanded or collapsed (tree mode). */
353
+ treeToggle = output();
242
354
  /** User-set column widths (px), keyed by column key. */
243
355
  colWidths = signal({}, /* @ts-ignore */
244
356
  ...(ngDevMode ? [{ debugName: "colWidths" }] : /* istanbul ignore next */ []));
@@ -608,10 +720,12 @@ class MkTable {
608
720
  */
609
721
  static sortCollator = new Intl.Collator();
610
722
  /** Data sorted by the active column, or the input order when unsorted. */
611
- sortedData = computed(() => {
723
+ sortedData = computed(() => this.sortRows(this.data()), /* @ts-ignore */
724
+ ...(ngDevMode ? [{ debugName: "sortedData" }] : /* istanbul ignore next */ []));
725
+ /** Sort one sibling group by the active column (input order when unsorted). */
726
+ sortRows(rows) {
612
727
  const key = this.sortKey();
613
728
  const dir = this.sortDir();
614
- const rows = this.data();
615
729
  if (!key || !dir)
616
730
  return rows;
617
731
  const compare = (a, b) => {
@@ -630,8 +744,7 @@ class MkTable {
630
744
  // Negate the comparator for desc (instead of reversing) so the sort stays
631
745
  // stable and null ordering is consistent in both directions.
632
746
  return [...rows].sort(dir === 'desc' ? (a, b) => -compare(a, b) : compare);
633
- }, /* @ts-ignore */
634
- ...(ngDevMode ? [{ debugName: "sortedData" }] : /* istanbul ignore next */ []));
747
+ }
635
748
  /** `aria-sort` value for a header cell. */
636
749
  ariaSort(col) {
637
750
  if (!col.sortable)
@@ -685,8 +798,10 @@ class MkTable {
685
798
  if (this.clickableRows())
686
799
  this.rowClick.emit(row);
687
800
  }
688
- /** Keyboard activation for clickable rows (Enter / Space). */
801
+ /** Keyboard activation for clickable rows (Enter / Space) and tree keys. */
689
802
  onRowKeydown(event, row) {
803
+ if (this.onTreeKeydown(event, row))
804
+ return;
690
805
  if (!this.clickableRows())
691
806
  return;
692
807
  if (event.target !== event.currentTarget)
@@ -715,9 +830,28 @@ class MkTable {
715
830
  isSelected(row) {
716
831
  return this.selectedKeys().has(this.rowKey(row));
717
832
  }
833
+ /**
834
+ * Every data row, in display order, ignoring tree expansion — what
835
+ * "select all" and the header checkbox reason about. Equals `sortedData`
836
+ * for flat tables.
837
+ */
838
+ allRows = computed(() => {
839
+ if (!this.childrenKey())
840
+ return this.sortedData();
841
+ const out = [];
842
+ const walk = (rows) => {
843
+ for (const row of this.sortRows(rows)) {
844
+ out.push(row);
845
+ walk(this.childrenOf(row));
846
+ }
847
+ };
848
+ walk(this.data());
849
+ return out;
850
+ }, /* @ts-ignore */
851
+ ...(ngDevMode ? [{ debugName: "allRows" }] : /* istanbul ignore next */ []));
718
852
  /** True when every visible row is selected. */
719
853
  allSelected = computed(() => {
720
- const rows = this.sortedData();
854
+ const rows = this.allRows();
721
855
  const keys = this.selectedKeys();
722
856
  return rows.length > 0 && rows.every((row) => keys.has(this.rowKey(row)));
723
857
  }, /* @ts-ignore */
@@ -725,7 +859,7 @@ class MkTable {
725
859
  /** True when some — but not all — visible rows are selected. */
726
860
  someSelected = computed(() => {
727
861
  const keys = this.selectedKeys();
728
- return (this.sortedData().some((row) => keys.has(this.rowKey(row))) &&
862
+ return (this.allRows().some((row) => keys.has(this.rowKey(row))) &&
729
863
  !this.allSelected());
730
864
  }, /* @ts-ignore */
731
865
  ...(ngDevMode ? [{ debugName: "someSelected" }] : /* istanbul ignore next */ []));
@@ -742,9 +876,9 @@ class MkTable {
742
876
  : [...current, row];
743
877
  this.commitSelection(next);
744
878
  }
745
- /** Select or deselect all visible rows. */
879
+ /** Select or deselect all rows (every tree row, expanded or not). */
746
880
  toggleAll() {
747
- const rows = this.sortedData();
881
+ const rows = this.allRows();
748
882
  const current = this.selected();
749
883
  if (this.allSelected()) {
750
884
  const visible = new Set(rows.map((r) => this.rowKey(r)));
@@ -793,21 +927,139 @@ class MkTable {
793
927
  */
794
928
  displayItems = computed(() => {
795
929
  const groups = this.groups();
930
+ const items = [];
796
931
  if (!groups) {
797
- return this.sortedData().map((row) => ({ kind: 'row', row }));
932
+ this.pushRows(items, this.sortedData(), 0);
933
+ return items;
798
934
  }
799
935
  const collapsed = this.collapsedGroups();
800
- const items = [];
801
936
  for (const group of groups) {
802
937
  items.push({ kind: 'group', group });
803
- if (!collapsed.has(group.key)) {
804
- for (const row of group.rows)
805
- items.push({ kind: 'row', row });
806
- }
938
+ if (!collapsed.has(group.key))
939
+ this.pushRows(items, group.rows, 0);
807
940
  }
808
941
  return items;
809
942
  }, /* @ts-ignore */
810
943
  ...(ngDevMode ? [{ debugName: "displayItems" }] : /* istanbul ignore next */ []));
944
+ /**
945
+ * Append `rows` as render items. In tree mode each row is followed by its
946
+ * (sorted) children while it is expanded, one level deeper.
947
+ */
948
+ pushRows(items, rows, depth) {
949
+ const tree = !!this.childrenKey();
950
+ const expandedKeys = this.treeExpanded();
951
+ for (const row of rows) {
952
+ const children = tree ? this.childrenOf(row) : [];
953
+ const hasChildren = children.length > 0;
954
+ const expanded = hasChildren && expandedKeys.has(this.rowKey(row));
955
+ items.push({ kind: 'row', row, depth, hasChildren, expanded });
956
+ if (expanded)
957
+ this.pushRows(items, this.sortRows(children), depth + 1);
958
+ }
959
+ }
960
+ /** The child rows of `row` (tree mode), or an empty list. */
961
+ childrenOf(row) {
962
+ const key = this.childrenKey();
963
+ if (!key)
964
+ return [];
965
+ const value = row[key];
966
+ return Array.isArray(value) ? value : [];
967
+ }
968
+ // --- Tree rows ------------------------------------------------------------
969
+ /** Keys of parent rows whose children are shown. */
970
+ treeExpanded = signal(new Set(), /* @ts-ignore */
971
+ ...(ngDevMode ? [{ debugName: "treeExpanded" }] : /* istanbul ignore next */ []));
972
+ /** Whether a parent row's children are currently shown (tree mode). */
973
+ isTreeExpanded(row) {
974
+ return this.treeExpanded().has(this.rowKey(row));
975
+ }
976
+ /** Show or hide a parent row's children (tree mode). */
977
+ toggleTreeRow(row, event) {
978
+ event?.stopPropagation();
979
+ if (this.childrenOf(row).length === 0)
980
+ return;
981
+ this.setTreeExpanded(row, !this.isTreeExpanded(row));
982
+ }
983
+ /** Expand every parent row (tree mode). */
984
+ expandAllRows() {
985
+ const keys = new Set();
986
+ const walk = (rows) => {
987
+ for (const row of rows) {
988
+ const children = this.childrenOf(row);
989
+ if (children.length) {
990
+ keys.add(this.rowKey(row));
991
+ walk(children);
992
+ }
993
+ }
994
+ };
995
+ walk(this.data());
996
+ this.treeExpanded.set(keys);
997
+ }
998
+ /** Collapse every parent row (tree mode). */
999
+ collapseAllRows() {
1000
+ this.treeExpanded.set(new Set());
1001
+ }
1002
+ // --- Export -----------------------------------------------------------------
1003
+ /**
1004
+ * The table's rows as CSV: current column order, column formatters applied,
1005
+ * sorted the way they are shown, tree children flattened under their parent
1006
+ * whether or not they are expanded. Downloads the file (default name
1007
+ * `table.csv`) and returns the text.
1008
+ */
1009
+ exportCsv(options = {}) {
1010
+ let rows = this.allRows();
1011
+ if (options.selectedOnly) {
1012
+ const keys = this.selectedKeys();
1013
+ rows = rows.filter((r) => keys.has(this.rowKey(r)));
1014
+ }
1015
+ const only = options.columns ? new Set(options.columns) : null;
1016
+ const columns = this.orderedColumns()
1017
+ .filter((c) => !only || only.has(c.key))
1018
+ .map((c) => ({ key: c.key, header: c.header, format: c.format }));
1019
+ // `allRows` is already flat, so no childrenKey is passed through.
1020
+ const csv = mkToCsv(rows, columns, { ...options, childrenKey: undefined });
1021
+ if (options.download !== false) {
1022
+ let filename = options.filename ?? 'table.csv';
1023
+ if (!/\.csv$/i.test(filename))
1024
+ filename += '.csv';
1025
+ mkDownloadText(csv, filename);
1026
+ }
1027
+ return csv;
1028
+ }
1029
+ setTreeExpanded(row, expanded) {
1030
+ const rk = this.rowKey(row);
1031
+ if (this.treeExpanded().has(rk) === expanded)
1032
+ return;
1033
+ const next = new Set(this.treeExpanded());
1034
+ if (expanded)
1035
+ next.add(rk);
1036
+ else
1037
+ next.delete(rk);
1038
+ this.treeExpanded.set(next);
1039
+ this.treeToggle.emit({ row, expanded });
1040
+ }
1041
+ /**
1042
+ * ArrowRight opens and ArrowLeft closes a parent row's children (swapped in
1043
+ * RTL). Handled for keys pressed on the row itself or on its tree toggle.
1044
+ */
1045
+ onTreeKeydown(event, row) {
1046
+ if (!this.childrenKey() || this.childrenOf(row).length === 0)
1047
+ return false;
1048
+ const rtl = this.document.defaultView?.getComputedStyle(this.host.nativeElement).direction === 'rtl';
1049
+ const openKey = rtl ? 'ArrowLeft' : 'ArrowRight';
1050
+ const closeKey = rtl ? 'ArrowRight' : 'ArrowLeft';
1051
+ if (event.key === openKey && !this.isTreeExpanded(row)) {
1052
+ event.preventDefault();
1053
+ this.setTreeExpanded(row, true);
1054
+ return true;
1055
+ }
1056
+ if (event.key === closeKey && this.isTreeExpanded(row)) {
1057
+ event.preventDefault();
1058
+ this.setTreeExpanded(row, false);
1059
+ return true;
1060
+ }
1061
+ return false;
1062
+ }
811
1063
  /** `@for` identity: group headers by value, rows by {@link trackRow}. */
812
1064
  trackItem = (item) => item.kind === 'group' ? `mk-group:${String(item.group.key)}` : this.rowKey(item.row);
813
1065
  /** Whether a group is currently collapsed. */
@@ -860,7 +1112,7 @@ class MkTable {
860
1112
  this.expandedChange.emit(this.data().filter((r) => next.has(this.rowKey(r))));
861
1113
  }
862
1114
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
863
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkTable, isStandalone: true, selector: "mk-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, zebra: { classPropertyName: "zebra", publicName: "zebra", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stackAt: { classPropertyName: "stackAt", publicName: "stackAt", isSignal: true, isRequired: false, transformFunction: null }, clickableRows: { classPropertyName: "clickableRows", publicName: "clickableRows", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, trackKey: { classPropertyName: "trackKey", publicName: "trackKey", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, singleExpand: { classPropertyName: "singleExpand", publicName: "singleExpand", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, groupLabel: { classPropertyName: "groupLabel", publicName: "groupLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", sortChange: "sortChange", rowClick: "rowClick", selectionChange: "selectionChange", expandedChange: "expandedChange", columnResize: "columnResize", columnReorder: "columnReorder", cellEdit: "cellEdit", groupToggle: "groupToggle" }, host: { properties: { "class.mk-table--sticky": "stickyHeader()", "class.mk-table--zebra": "zebra()", "class.mk-table--hover": "hover()", "class.mk-table--compact": "density() === 'compact'", "class.mk-table--clickable": "clickableRows()", "class.mk-table--selectable": "selectable()", "class.mk-table--expandable": "expandable()", "class.mk-table--grouped": "groupBy() !== null", "class.mk-table--stacked": "stacked()" }, classAttribute: "mk-table" }, queries: [{ propertyName: "rowDetail", first: true, predicate: MkTableRowDetail, descendants: true, isSignal: true }, { propertyName: "cellTemplates", predicate: MkTableCell, isSignal: true }], viewQueries: [{ propertyName: "editInput", first: true, predicate: ["editInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"mk-table__scroll\">\n <!-- Explicit roles ONLY while stacked: `display: block` strips a table\n element of its implicit role, so without these a card layout stops\n being announced as tabular data at all. Redundant in the grid, so\n they are left off there rather than duplicating what the element\n already says. -->\n <table class=\"mk-table__table\" [attr.role]=\"stacked() ? 'table' : null\">\n <thead class=\"mk-table__head\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n <tr>\n @if (expandable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--expand\">\n <span class=\"mk-visually-hidden\">{{ i18n.expandHeader }}</span>\n </th>\n }\n @if (selectable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--select\">\n <mk-checkbox\n [aria-label]=\"i18n.selectAllRows\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of orderedColumns(); track col.key) {\n <th\n scope=\"col\"\n class=\"mk-table__th\"\n [class.mk-table__th--sortable]=\"col.sortable\"\n [class.mk-table__th--pinned]=\"col.pinned\"\n [class.mk-table__th--pinned-right]=\"col.pinned === 'right'\"\n [class.mk-table__th--dragging]=\"dragKey() === col.key\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"col.pinned === 'left' ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"col.pinned === 'right' ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.aria-sort]=\"ariaSort(col)\"\n [attr.draggable]=\"reorderableColumns() && !col.pinned ? true : null\"\n (dragstart)=\"onColDragStart($event, col)\"\n (dragover)=\"onColDragOver($event)\"\n (drop)=\"onColDrop($event, col)\"\n (dragend)=\"onColDragEnd()\"\n >\n @if (col.sortable || (reorderableColumns() && !col.pinned)) {\n <button\n type=\"button\"\n class=\"mk-table__th-button\"\n [class.mk-table__th-button--static]=\"!col.sortable\"\n (click)=\"onSort(col)\"\n (keydown)=\"onReorderKeydown($event, col)\"\n >\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n @if (col.sortable) {\n <span class=\"mk-table__sort\" aria-hidden=\"true\">{{ sortGlyph(col) }}</span>\n }\n </button>\n } @else {\n <span class=\"mk-table__th-inner\">\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n </span>\n }\n @if (resizableColumns() && col.resizable) {\n <span\n class=\"mk-table__resize\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"i18n.resizeColumn\"\n [attr.aria-valuemin]=\"resizeValueMin(col)\"\n [attr.aria-valuenow]=\"resizeValueNow(col)\"\n [attr.aria-valuemax]=\"resizeValueMax\"\n (pointerdown)=\"startResize($event, col)\"\n (keydown)=\"onResizeKeydown($event, col)\"\n (click)=\"$event.stopPropagation()\"\n ></span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"mk-table__body\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n @for (item of displayItems(); track trackItem(item); let i = $index) {\n @if (item.kind === 'group') {\n <tr class=\"mk-table__group-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <th\n class=\"mk-table__group\"\n scope=\"colgroup\"\n [attr.role]=\"stacked() ? 'rowheader' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__group-toggle\"\n [attr.aria-expanded]=\"!isGroupCollapsed(item.group.key)\"\n (click)=\"onGroupToggle(item.group)\"\n >\n <span\n class=\"mk-table__expander-icon\"\n [class.mk-table__expander-icon--open]=\"!isGroupCollapsed(item.group.key)\"\n aria-hidden=\"true\"\n >\u203A</span\n >\n <span class=\"mk-visually-hidden\">{{\n isGroupCollapsed(item.group.key) ? i18n.expandGroup : i18n.collapseGroup\n }}</span>\n <span class=\"mk-table__group-label\">{{ item.group.label }}</span>\n <span class=\"mk-table__group-count\">{{\n i18n.groupCount(item.group.rows.length)\n }}</span>\n </button>\n </th>\n </tr>\n } @else {\n <ng-container>\n <tr\n class=\"mk-table__row\"\n [attr.role]=\"stacked() ? 'row' : null\"\n [class]=\"rowClassFor(item.row)\"\n [class.mk-table__row--selected]=\"selectable() && isSelected(item.row)\"\n [class.mk-table__row--expanded]=\"expandable() && isExpanded(item.row)\"\n [attr.tabindex]=\"clickableRows() ? 0 : null\"\n (click)=\"onRowClick(item.row)\"\n (keydown)=\"onRowKeydown($event, item.row)\"\n >\n @if (expandable()) {\n <td\n class=\"mk-table__td mk-table__td--expand\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__expander\"\n [class.mk-table__expander--open]=\"isExpanded(item.row)\"\n [attr.aria-expanded]=\"isExpanded(item.row)\"\n [attr.aria-controls]=\"detailId(i)\"\n [attr.aria-label]=\"isExpanded(item.row) ? i18n.collapseRow : i18n.expandRow\"\n (click)=\"toggleExpand(item.row, $event)\"\n >\n <span class=\"mk-table__expander-icon\" aria-hidden=\"true\">\u203A</span>\n </button>\n </td>\n }\n @if (selectable()) {\n <td\n class=\"mk-table__td mk-table__td--select\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <mk-checkbox\n [aria-label]=\"i18n.selectRow(rowLabel(item.row))\"\n [checked]=\"isSelected(item.row)\"\n (checkedChange)=\"toggleRow(item.row)\"\n />\n </td>\n }\n @if (!stacked()) {\n @for (col of orderedColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: null }\"\n />\n }\n } @else {\n <!-- Card layout. Same <td> elements, restyled \u2014 keeping the table\n DOM means selection, expansion, inline edit and every cell\n template keep working, since all of them reach for a `td`. -->\n @for (col of stackTitleColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'title' }\"\n />\n }\n @for (col of stackFieldColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'field' }\"\n />\n }\n @for (col of stackFooterColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'footer' }\"\n />\n }\n }\n </tr>\n @if (expandable() && isExpanded(item.row) && rowDetail()) {\n <tr class=\"mk-table__detail-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__detail\"\n [id]=\"detailId(i)\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <div class=\"mk-table__detail-inner\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetail()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item.row }\"\n />\n </div>\n </td>\n </tr>\n }\n </ng-container>\n }\n } @empty {\n <tr class=\"mk-table__row mk-table__row--empty\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__empty\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <ng-content select=\"[mkTableEmpty]\">{{ emptyMessage() }}</ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n\n<!-- One cell, rendered by both layouts. `slot` is null in the grid and\n 'title' | 'field' | 'footer' in a card; everything else \u2014 the editor, the\n consumer's mkTableCell template, the formatted fallback \u2014 is identical, so\n a card can never drift from the grid it replaces. -->\n<ng-template #cellTpl let-col=\"col\" let-row=\"row\" let-i=\"i\" let-slot=\"slot\">\n <td\n class=\"mk-table__td\"\n [class.mk-table__td--pinned]=\"isPinned(col, 'left') || isPinned(col, 'right')\"\n [class.mk-table__td--pinned-right]=\"isPinned(col, 'right')\"\n [class.mk-table__td--editable]=\"col.editable\"\n [class.mk-table__td--stack-title]=\"slot === 'title'\"\n [class.mk-table__td--stack-field]=\"slot === 'field'\"\n [class.mk-table__td--stack-footer]=\"slot === 'footer'\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"isPinned(col, 'left') ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"isPinned(col, 'right') ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.tabindex]=\"col.editable ? 0 : null\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (dblclick)=\"startEdit(i, col, $event)\"\n (keydown)=\"onCellKeydown($event, i, col)\"\n >\n @if (slot === 'field' && hasStackLabel(col)) {\n <!-- The column header, moved beside the value. Not aria-hidden: the\n <thead> is display:none while stacked, so this label is the only\n thing naming the value for a screen reader. -->\n <span class=\"mk-table__cell-label\">{{ col.header }}</span>\n }\n <span class=\"mk-table__cell-value\">\n @if (isEditing(i, col)) {\n <input\n #editInput\n class=\"mk-table__cell-input\"\n [value]=\"cellText(row, col)\"\n [attr.aria-label]=\"col.header\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onEditKeydown($event, row, col)\"\n (blur)=\"commitEdit(row, col, $any($event.target).value)\"\n />\n } @else if (cellTemplateFor(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: cellValue(row, col), row }\"\n />\n } @else {\n {{ cellText(row, col) }}\n @if (col.editable) {\n <span class=\"mk-visually-hidden\">{{ i18n.editCell }}</span>\n }\n }\n </span>\n </td>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--_cell-pad-y: var(--mk-space-3);--_cell-pad-x: var(--mk-space-4);display:block;color:var(--mk-text)}:host(.mk-table--compact){--_cell-pad-y: var(--mk-space-2);--_cell-pad-x: var(--mk-space-3)}.mk-table__scroll{width:100%;overflow-x:auto;border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg)}.mk-table__table{width:100%;border-collapse:collapse;font-size:var(--mk-font-size-sm);background-color:var(--mk-surface)}.mk-table__th{padding:var(--_cell-pad-y) var(--_cell-pad-x);background-color:var(--mk-surface-2);color:var(--mk-text-muted);font-weight:var(--mk-font-weight-semibold);text-align:start;white-space:nowrap;border-bottom:var(--mk-border-width) solid var(--mk-border);vertical-align:middle}:host(.mk-table--sticky) .mk-table__head .mk-table__th{position:sticky;top:0;z-index:var(--mk-z-sticky)}.mk-table__th-inner{display:inline-flex;align-items:center;gap:var(--mk-space-1)}.mk-table__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.mk-table__th--sortable:hover{background-color:var(--mk-surface-3);color:var(--mk-text)}.mk-table__th-button{display:inline-flex;align-items:center;gap:var(--mk-space-1);width:100%;margin:calc(-1 * var(--_cell-pad-y)) calc(-1 * var(--_cell-pad-x));padding:var(--_cell-pad-y) var(--_cell-pad-x);font:inherit;font-weight:inherit;color:inherit;text-align:inherit;background:transparent;border:0;cursor:pointer}.mk-table__th-button--static{cursor:grab}.mk-table__th-button:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[data-align=center] .mk-table__th-button{justify-content:center}.mk-table__th[data-align=end] .mk-table__th-button{justify-content:flex-end}.mk-table__th[aria-sort=ascending],.mk-table__th[aria-sort=descending]{color:var(--mk-text)}.mk-table__sort{font-size:var(--mk-font-size-xs);opacity:.7;line-height:1}.mk-table__td{padding:var(--_cell-pad-y) var(--_cell-pad-x);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);vertical-align:middle}.mk-table__row:last-child .mk-table__td{border-bottom:0}.mk-table__th[data-align=center],.mk-table__td[data-align=center]{text-align:center}.mk-table__th[data-align=end],.mk-table__td[data-align=end]{text-align:right}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background-color:var(--mk-surface-2)}:host(.mk-table--hover) .mk-table__body .mk-table__row:not(.mk-table__row--empty):hover .mk-table__td{background-color:var(--mk-neutral-subtle)}:host(.mk-table--clickable) .mk-table__row:not(.mk-table__row--empty){cursor:pointer}:host(.mk-table--clickable) .mk-table__row:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th--select,.mk-table__td--select{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}:host .mk-table__body .mk-table__row--selected .mk-table__td,:host(.mk-table--zebra) .mk-table__body .mk-table__row--selected:nth-child(2n) .mk-table__td,:host(.mk-table--hover) .mk-table__body .mk-table__row--selected:hover .mk-table__td{background-color:var(--mk-selected-bg);color:var(--mk-selected-text)}.mk-table__th--expand,.mk-table__td--expand{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}.mk-table__expander{display:inline-grid;place-items:center;width:1.5rem;height:1.5rem;padding:0;color:var(--mk-text-muted);background:transparent;border:none;border-radius:var(--mk-radius-sm);cursor:pointer}.mk-table__expander:hover{background-color:var(--mk-hover-overlay);color:var(--mk-text)}.mk-table__expander:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__expander-icon{display:inline-block;font-size:var(--mk-font-size-lg);line-height:1;transition:transform var(--mk-transition-fast, .12s) ease}.mk-table__expander--open .mk-table__expander-icon,.mk-table__expander-icon--open{transform:rotate(90deg)}:host(:dir(rtl)) .mk-table__expander-icon{transform:scaleX(-1)}:host(:dir(rtl)) .mk-table__expander--open .mk-table__expander-icon,:host(:dir(rtl)) .mk-table__expander-icon--open{transform:scaleX(-1) rotate(-90deg)}.mk-table__detail{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle)}.mk-table__detail-inner{padding:var(--_cell-pad-y) var(--_cell-pad-x)}.mk-table__th{position:relative}.mk-table__resize{position:absolute;top:0;inset-inline-end:0;width:8px;height:100%;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}@media(pointer:coarse){.mk-table__resize:before{content:\"\";position:absolute;inset:min(0px,(100% - 24px) / 2)}}.mk-table__resize:after{content:\"\";position:absolute;top:25%;inset-inline-end:3px;width:2px;height:50%;background-color:var(--mk-border)}.mk-table__resize:hover:after,.mk-table__resize:focus-visible:after{background-color:var(--mk-primary)}.mk-table__resize:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[draggable=true]{cursor:grab}.mk-table__th--dragging{opacity:.5}.mk-table__th--pinned,.mk-table__td--pinned{position:sticky;z-index:1;background-color:var(--mk-surface)}.mk-table__th--pinned{z-index:2;background-color:var(--mk-surface-2)}.mk-table__th--pinned:not(.mk-table__th--pinned-right),.mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}.mk-table__th--pinned-right,.mk-table__td--pinned-right{box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned:not(.mk-table__th--pinned-right),:host(:dir(rtl)) .mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned-right,:host(:dir(rtl)) .mk-table__td--pinned-right{box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td--pinned{background-color:var(--mk-surface-2)}.mk-table__td--editable{cursor:text}.mk-table__td--editable:hover{background-color:var(--mk-hover-overlay)}.mk-table__td--editable:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__cell-input{width:100%;margin:calc(-1 * var(--mk-space-1)) 0;padding:var(--mk-space-1) var(--mk-space-2);font:inherit;color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-primary);border-radius:var(--mk-radius-sm);outline:none}.mk-table__empty{padding:var(--mk-space-8) var(--_cell-pad-x);text-align:center;color:var(--mk-text-subtle)}.mk-table__group{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);text-align:start}:host(.mk-table--grouped) .mk-table__group{position:sticky;top:var(--_group-top, 0px);z-index:calc(var(--mk-z-sticky) - 1)}.mk-table__group-toggle{display:flex;align-items:center;gap:var(--mk-space-2);width:100%;padding:var(--mk-space-2) var(--mk-space-3);border:none;background:none;color:var(--mk-text);font:inherit;font-weight:var(--mk-font-weight-semibold);cursor:pointer}.mk-table__group-toggle:hover{background-color:var(--mk-hover-overlay)}.mk-table__group-toggle:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__group-count{padding:0 var(--mk-space-2);border-radius:var(--mk-radius-full);background-color:var(--mk-surface-3);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-regular)}:host(.mk-table--stacked) .mk-table__scroll{overflow-x:visible;border:none;border-radius:0;background:none}:host(.mk-table--stacked) .mk-table__table,:host(.mk-table--stacked) .mk-table__body{display:block;background:none}:host(.mk-table--stacked) .mk-table__head{display:none}:host(.mk-table--stacked) .mk-table__row{display:grid;grid-template-columns:1fr;gap:var(--mk-space-1);padding:var(--mk-space-3);margin-bottom:var(--mk-space-3);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg);background-color:var(--mk-surface);box-shadow:var(--mk-shadow-xs)}:host(.mk-table--stacked) .mk-table__td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--mk-space-3);padding:var(--mk-space-1) 0;border:none;text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-title{justify-content:flex-start;padding-bottom:var(--mk-space-2);font-size:var(--mk-font-size-lg);font-weight:var(--mk-font-weight-semibold);color:var(--mk-text)}:host(.mk-table--stacked) .mk-table__td--stack-title~.mk-table__td--stack-title{justify-content:flex-end;margin-top:calc(-1 * var(--mk-space-2) - 1.5em);font-size:var(--mk-font-size-md)}:host(.mk-table--stacked) .mk-table__cell-label{flex:none;color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}:host(.mk-table--stacked) .mk-table__cell-value{min-width:0;text-align:end;overflow-wrap:anywhere}:host(.mk-table--stacked) .mk-table__td--stack-title .mk-table__cell-value,:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-footer{justify-content:flex-start;margin-top:var(--mk-space-2);padding-top:var(--mk-space-3);border-top:var(--mk-border-width) solid var(--mk-border-subtle)}:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{display:flex;flex-wrap:wrap;gap:var(--mk-space-2);width:100%}:host(.mk-table--stacked) .mk-table__td--select,:host(.mk-table--stacked) .mk-table__td--expand{width:auto;justify-content:flex-start}:host(.mk-table--stacked).mk-table--zebra .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background:none}:host(.mk-table--stacked) .mk-table__detail-row,:host(.mk-table--stacked) .mk-table__detail{display:block;padding:0}:host(.mk-table--stacked) .mk-table__detail-row{margin:calc(-1 * var(--mk-space-3)) 0 var(--mk-space-3)}:host(.mk-table--stacked) .mk-table__group-row,:host(.mk-table--stacked) .mk-table__group{display:block;top:0}:host(.mk-table--stacked) .mk-table__row--empty,:host(.mk-table--stacked) .mk-table__empty{display:block;border:none;box-shadow:none;background:none}@media(pointer:coarse){.mk-table__cell-input{font-size:max(var(--mk-font-size-md),16px)}}\n"], dependencies: [{ kind: "component", type: MkCheckbox, selector: "mk-checkbox", inputs: ["checked", "indeterminate", "disabled", "invalid", "required", "size", "tone", "aria-label"], outputs: ["checkedChange", "indeterminateChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1115
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkTable, isStandalone: true, selector: "mk-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, zebra: { classPropertyName: "zebra", publicName: "zebra", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stackAt: { classPropertyName: "stackAt", publicName: "stackAt", isSignal: true, isRequired: false, transformFunction: null }, clickableRows: { classPropertyName: "clickableRows", publicName: "clickableRows", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, trackKey: { classPropertyName: "trackKey", publicName: "trackKey", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, singleExpand: { classPropertyName: "singleExpand", publicName: "singleExpand", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, groupLabel: { classPropertyName: "groupLabel", publicName: "groupLabel", isSignal: true, isRequired: false, transformFunction: null }, childrenKey: { classPropertyName: "childrenKey", publicName: "childrenKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", sortChange: "sortChange", rowClick: "rowClick", selectionChange: "selectionChange", expandedChange: "expandedChange", columnResize: "columnResize", columnReorder: "columnReorder", cellEdit: "cellEdit", groupToggle: "groupToggle", treeToggle: "treeToggle" }, host: { properties: { "class.mk-table--sticky": "stickyHeader()", "class.mk-table--zebra": "zebra()", "class.mk-table--hover": "hover()", "class.mk-table--compact": "density() === 'compact'", "class.mk-table--clickable": "clickableRows()", "class.mk-table--selectable": "selectable()", "class.mk-table--expandable": "expandable()", "class.mk-table--grouped": "groupBy() !== null", "class.mk-table--stacked": "stacked()" }, classAttribute: "mk-table" }, queries: [{ propertyName: "rowDetail", first: true, predicate: MkTableRowDetail, descendants: true, isSignal: true }, { propertyName: "cellTemplates", predicate: MkTableCell, isSignal: true }], viewQueries: [{ propertyName: "editInput", first: true, predicate: ["editInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"mk-table__scroll\">\n <!-- Explicit roles ONLY while stacked: `display: block` strips a table\n element of its implicit role, so without these a card layout stops\n being announced as tabular data at all. Redundant in the grid, so\n they are left off there rather than duplicating what the element\n already says. -->\n <table\n class=\"mk-table__table\"\n [attr.role]=\"childrenKey() ? 'treegrid' : stacked() ? 'table' : null\"\n >\n <thead class=\"mk-table__head\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n <tr>\n @if (expandable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--expand\">\n <span class=\"mk-visually-hidden\">{{ i18n.expandHeader }}</span>\n </th>\n }\n @if (selectable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--select\">\n <mk-checkbox\n [aria-label]=\"i18n.selectAllRows\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of orderedColumns(); track col.key) {\n <th\n scope=\"col\"\n class=\"mk-table__th\"\n [class.mk-table__th--sortable]=\"col.sortable\"\n [class.mk-table__th--pinned]=\"col.pinned\"\n [class.mk-table__th--pinned-right]=\"col.pinned === 'right'\"\n [class.mk-table__th--dragging]=\"dragKey() === col.key\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"col.pinned === 'left' ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"col.pinned === 'right' ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.aria-sort]=\"ariaSort(col)\"\n [attr.draggable]=\"reorderableColumns() && !col.pinned ? true : null\"\n (dragstart)=\"onColDragStart($event, col)\"\n (dragover)=\"onColDragOver($event)\"\n (drop)=\"onColDrop($event, col)\"\n (dragend)=\"onColDragEnd()\"\n >\n @if (col.sortable || (reorderableColumns() && !col.pinned)) {\n <button\n type=\"button\"\n class=\"mk-table__th-button\"\n [class.mk-table__th-button--static]=\"!col.sortable\"\n (click)=\"onSort(col)\"\n (keydown)=\"onReorderKeydown($event, col)\"\n >\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n @if (col.sortable) {\n <span class=\"mk-table__sort\" aria-hidden=\"true\">{{ sortGlyph(col) }}</span>\n }\n </button>\n } @else {\n <span class=\"mk-table__th-inner\">\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n </span>\n }\n @if (resizableColumns() && col.resizable) {\n <span\n class=\"mk-table__resize\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"i18n.resizeColumn\"\n [attr.aria-valuemin]=\"resizeValueMin(col)\"\n [attr.aria-valuenow]=\"resizeValueNow(col)\"\n [attr.aria-valuemax]=\"resizeValueMax\"\n (pointerdown)=\"startResize($event, col)\"\n (keydown)=\"onResizeKeydown($event, col)\"\n (click)=\"$event.stopPropagation()\"\n ></span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"mk-table__body\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n @for (item of displayItems(); track trackItem(item); let i = $index) {\n @if (item.kind === 'group') {\n <tr class=\"mk-table__group-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <th\n class=\"mk-table__group\"\n scope=\"colgroup\"\n [attr.role]=\"stacked() ? 'rowheader' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__group-toggle\"\n [attr.aria-expanded]=\"!isGroupCollapsed(item.group.key)\"\n (click)=\"onGroupToggle(item.group)\"\n >\n <span\n class=\"mk-table__expander-icon\"\n [class.mk-table__expander-icon--open]=\"!isGroupCollapsed(item.group.key)\"\n aria-hidden=\"true\"\n >\u203A</span\n >\n <span class=\"mk-visually-hidden\">{{\n isGroupCollapsed(item.group.key) ? i18n.expandGroup : i18n.collapseGroup\n }}</span>\n <span class=\"mk-table__group-label\">{{ item.group.label }}</span>\n <span class=\"mk-table__group-count\">{{\n i18n.groupCount(item.group.rows.length)\n }}</span>\n </button>\n </th>\n </tr>\n } @else {\n <ng-container>\n <tr\n class=\"mk-table__row\"\n [attr.role]=\"stacked() || childrenKey() ? 'row' : null\"\n [class]=\"rowClassFor(item.row)\"\n [class.mk-table__row--selected]=\"selectable() && isSelected(item.row)\"\n [class.mk-table__row--expanded]=\"expandable() && isExpanded(item.row)\"\n [class.mk-table__row--parent]=\"item.hasChildren\"\n [style.--mk-tree-depth]=\"childrenKey() ? item.depth : null\"\n [style.margin-inline-start.px]=\"stacked() && item.depth ? item.depth * 16 : null\"\n [attr.aria-level]=\"childrenKey() ? item.depth + 1 : null\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [attr.tabindex]=\"clickableRows() ? 0 : null\"\n (click)=\"onRowClick(item.row)\"\n (keydown)=\"onRowKeydown($event, item.row)\"\n >\n @if (expandable()) {\n <td\n class=\"mk-table__td mk-table__td--expand\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__expander\"\n [class.mk-table__expander--open]=\"isExpanded(item.row)\"\n [attr.aria-expanded]=\"isExpanded(item.row)\"\n [attr.aria-controls]=\"detailId(i)\"\n [attr.aria-label]=\"isExpanded(item.row) ? i18n.collapseRow : i18n.expandRow\"\n (click)=\"toggleExpand(item.row, $event)\"\n >\n <span class=\"mk-table__expander-icon\" aria-hidden=\"true\">\u203A</span>\n </button>\n </td>\n }\n @if (selectable()) {\n <td\n class=\"mk-table__td mk-table__td--select\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <mk-checkbox\n [aria-label]=\"i18n.selectRow(rowLabel(item.row))\"\n [checked]=\"isSelected(item.row)\"\n (checkedChange)=\"toggleRow(item.row)\"\n />\n </td>\n }\n @if (!stacked()) {\n @for (col of orderedColumns(); track col.key; let first = $first) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: null, tree: first ? item : null }\"\n />\n }\n } @else {\n <!-- Card layout. Same <td> elements, restyled \u2014 keeping the table\n DOM means selection, expansion, inline edit and every cell\n template keep working, since all of them reach for a `td`. -->\n @for (col of stackTitleColumns(); track col.key; let first = $first) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'title', tree: first ? item : null }\"\n />\n }\n @for (col of stackFieldColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'field' }\"\n />\n }\n @for (col of stackFooterColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'footer' }\"\n />\n }\n }\n </tr>\n @if (expandable() && isExpanded(item.row) && rowDetail()) {\n <tr class=\"mk-table__detail-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__detail\"\n [id]=\"detailId(i)\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <div class=\"mk-table__detail-inner\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetail()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item.row }\"\n />\n </div>\n </td>\n </tr>\n }\n </ng-container>\n }\n } @empty {\n <tr class=\"mk-table__row mk-table__row--empty\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__empty\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <ng-content select=\"[mkTableEmpty]\">{{ emptyMessage() }}</ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n\n<!-- One cell, rendered by both layouts. `slot` is null in the grid and\n 'title' | 'field' | 'footer' in a card; everything else \u2014 the editor, the\n consumer's mkTableCell template, the formatted fallback \u2014 is identical, so\n a card can never drift from the grid it replaces. -->\n<ng-template #cellTpl let-col=\"col\" let-row=\"row\" let-i=\"i\" let-slot=\"slot\" let-tree=\"tree\">\n <td\n class=\"mk-table__td\"\n [class.mk-table__td--tree]=\"!!tree && !!childrenKey()\"\n [class.mk-table__td--pinned]=\"isPinned(col, 'left') || isPinned(col, 'right')\"\n [class.mk-table__td--pinned-right]=\"isPinned(col, 'right')\"\n [class.mk-table__td--editable]=\"col.editable\"\n [class.mk-table__td--stack-title]=\"slot === 'title'\"\n [class.mk-table__td--stack-field]=\"slot === 'field'\"\n [class.mk-table__td--stack-footer]=\"slot === 'footer'\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"isPinned(col, 'left') ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"isPinned(col, 'right') ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.tabindex]=\"col.editable ? 0 : null\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (dblclick)=\"startEdit(i, col, $event)\"\n (keydown)=\"onCellKeydown($event, i, col)\"\n >\n @if (slot === 'field' && hasStackLabel(col)) {\n <!-- The column header, moved beside the value. Not aria-hidden: the\n <thead> is display:none while stacked, so this label is the only\n thing naming the value for a screen reader. -->\n <span class=\"mk-table__cell-label\">{{ col.header }}</span>\n }\n @if (tree && childrenKey()) {\n <!-- Tree toggle (or a spacer on leaves) ahead of the first cell's value,\n so the indent and the caret read as one column. -->\n @if (tree.hasChildren) {\n <button\n type=\"button\"\n class=\"mk-table__tree-toggle\"\n [class.mk-table__tree-toggle--open]=\"tree.expanded\"\n [attr.aria-expanded]=\"tree.expanded\"\n [attr.aria-label]=\"tree.expanded ? i18n.collapseTreeRow : i18n.expandTreeRow\"\n (click)=\"toggleTreeRow(row, $event)\"\n >\n <span class=\"mk-table__expander-icon\" [class.mk-table__expander-icon--open]=\"tree.expanded\" aria-hidden=\"true\">\u203A</span>\n </button>\n } @else {\n <span class=\"mk-table__tree-spacer\" aria-hidden=\"true\"></span>\n }\n }\n <span class=\"mk-table__cell-value\">\n @if (isEditing(i, col)) {\n <input\n #editInput\n class=\"mk-table__cell-input\"\n [value]=\"cellText(row, col)\"\n [attr.aria-label]=\"col.header\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onEditKeydown($event, row, col)\"\n (blur)=\"commitEdit(row, col, $any($event.target).value)\"\n />\n } @else if (cellTemplateFor(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: cellValue(row, col), row }\"\n />\n } @else {\n {{ cellText(row, col) }}\n @if (col.editable) {\n <span class=\"mk-visually-hidden\">{{ i18n.editCell }}</span>\n }\n }\n </span>\n </td>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--_cell-pad-y: var(--mk-space-3);--_cell-pad-x: var(--mk-space-4);display:block;color:var(--mk-text)}:host(.mk-table--compact){--_cell-pad-y: var(--mk-space-2);--_cell-pad-x: var(--mk-space-3)}.mk-table__scroll{width:100%;overflow-x:auto;border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg)}.mk-table__table{width:100%;border-collapse:collapse;font-size:var(--mk-font-size-sm);background-color:var(--mk-surface)}.mk-table__th{padding:var(--_cell-pad-y) var(--_cell-pad-x);background-color:var(--mk-surface-2);color:var(--mk-text-muted);font-weight:var(--mk-font-weight-semibold);text-align:start;white-space:nowrap;border-bottom:var(--mk-border-width) solid var(--mk-border);vertical-align:middle}:host(.mk-table--sticky) .mk-table__head .mk-table__th{position:sticky;top:0;z-index:var(--mk-z-sticky)}.mk-table__th-inner{display:inline-flex;align-items:center;gap:var(--mk-space-1)}.mk-table__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.mk-table__th--sortable:hover{background-color:var(--mk-surface-3);color:var(--mk-text)}.mk-table__th-button{display:inline-flex;align-items:center;gap:var(--mk-space-1);width:100%;margin:calc(-1 * var(--_cell-pad-y)) calc(-1 * var(--_cell-pad-x));padding:var(--_cell-pad-y) var(--_cell-pad-x);font:inherit;font-weight:inherit;color:inherit;text-align:inherit;background:transparent;border:0;cursor:pointer}.mk-table__th-button--static{cursor:grab}.mk-table__th-button:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[data-align=center] .mk-table__th-button{justify-content:center}.mk-table__th[data-align=end] .mk-table__th-button{justify-content:flex-end}.mk-table__th[aria-sort=ascending],.mk-table__th[aria-sort=descending]{color:var(--mk-text)}.mk-table__sort{font-size:var(--mk-font-size-xs);opacity:.7;line-height:1}.mk-table__td{padding:var(--_cell-pad-y) var(--_cell-pad-x);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);vertical-align:middle}.mk-table__row:last-child .mk-table__td{border-bottom:0}.mk-table__th[data-align=center],.mk-table__td[data-align=center]{text-align:center}.mk-table__th[data-align=end],.mk-table__td[data-align=end]{text-align:right}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background-color:var(--mk-surface-2)}:host(.mk-table--hover) .mk-table__body .mk-table__row:not(.mk-table__row--empty):hover .mk-table__td{background-color:var(--mk-neutral-subtle)}:host(.mk-table--clickable) .mk-table__row:not(.mk-table__row--empty){cursor:pointer}:host(.mk-table--clickable) .mk-table__row:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th--select,.mk-table__td--select{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}:host .mk-table__body .mk-table__row--selected .mk-table__td,:host(.mk-table--zebra) .mk-table__body .mk-table__row--selected:nth-child(2n) .mk-table__td,:host(.mk-table--hover) .mk-table__body .mk-table__row--selected:hover .mk-table__td{background-color:var(--mk-selected-bg);color:var(--mk-selected-text)}.mk-table__th--expand,.mk-table__td--expand{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}.mk-table__expander{display:inline-grid;place-items:center;width:1.5rem;height:1.5rem;padding:0;color:var(--mk-text-muted);background:transparent;border:none;border-radius:var(--mk-radius-sm);cursor:pointer}.mk-table__expander:hover{background-color:var(--mk-hover-overlay);color:var(--mk-text)}.mk-table__expander:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__expander-icon{display:inline-block;font-size:var(--mk-font-size-lg);line-height:1;transition:transform var(--mk-transition-fast, .12s) ease}.mk-table__expander--open .mk-table__expander-icon,.mk-table__expander-icon--open{transform:rotate(90deg)}:host(:dir(rtl)) .mk-table__expander-icon{transform:scaleX(-1)}:host(:dir(rtl)) .mk-table__expander--open .mk-table__expander-icon,:host(:dir(rtl)) .mk-table__expander-icon--open{transform:scaleX(-1) rotate(-90deg)}.mk-table__detail{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle)}.mk-table__detail-inner{padding:var(--_cell-pad-y) var(--_cell-pad-x)}.mk-table__th{position:relative}.mk-table__resize{position:absolute;top:0;inset-inline-end:0;width:8px;height:100%;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}@media(pointer:coarse){.mk-table__resize:before{content:\"\";position:absolute;inset:min(0px,(100% - 24px) / 2)}}.mk-table__resize:after{content:\"\";position:absolute;top:25%;inset-inline-end:3px;width:2px;height:50%;background-color:var(--mk-border)}.mk-table__resize:hover:after,.mk-table__resize:focus-visible:after{background-color:var(--mk-primary)}.mk-table__resize:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[draggable=true]{cursor:grab}.mk-table__th--dragging{opacity:.5}.mk-table__th--pinned,.mk-table__td--pinned{position:sticky;z-index:1;background-color:var(--mk-surface)}.mk-table__th--pinned{z-index:2;background-color:var(--mk-surface-2)}.mk-table__th--pinned:not(.mk-table__th--pinned-right),.mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}.mk-table__th--pinned-right,.mk-table__td--pinned-right{box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned:not(.mk-table__th--pinned-right),:host(:dir(rtl)) .mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned-right,:host(:dir(rtl)) .mk-table__td--pinned-right{box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td--pinned{background-color:var(--mk-surface-2)}.mk-table__td--editable{cursor:text}.mk-table__td--editable:hover{background-color:var(--mk-hover-overlay)}.mk-table__td--editable:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__cell-input{width:100%;margin:calc(-1 * var(--mk-space-1)) 0;padding:var(--mk-space-1) var(--mk-space-2);font:inherit;color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-primary);border-radius:var(--mk-radius-sm);outline:none}.mk-table__empty{padding:var(--mk-space-8) var(--_cell-pad-x);text-align:center;color:var(--mk-text-subtle)}.mk-table__td--tree{padding-inline-start:calc(var(--_cell-pad-x) + var(--mk-tree-depth, 0) * 1.25rem);white-space:nowrap}.mk-table__tree-toggle,.mk-table__tree-spacer{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-inline-end:var(--mk-space-1);vertical-align:middle;flex:none}.mk-table__tree-toggle{padding:0;border:0;border-radius:var(--mk-radius-sm);background:transparent;color:var(--mk-text-muted);cursor:pointer}.mk-table__tree-toggle:hover{color:var(--mk-text);background:var(--mk-hover-overlay)}.mk-table__tree-toggle:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(var(--mk-focus-ring-offset) * -1)}.mk-table__td--tree .mk-table__cell-value{display:inline;vertical-align:middle}.mk-table__group{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);text-align:start}:host(.mk-table--grouped) .mk-table__group{position:sticky;top:var(--_group-top, 0px);z-index:calc(var(--mk-z-sticky) - 1)}.mk-table__group-toggle{display:flex;align-items:center;gap:var(--mk-space-2);width:100%;padding:var(--mk-space-2) var(--mk-space-3);border:none;background:none;color:var(--mk-text);font:inherit;font-weight:var(--mk-font-weight-semibold);cursor:pointer}.mk-table__group-toggle:hover{background-color:var(--mk-hover-overlay)}.mk-table__group-toggle:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__group-count{padding:0 var(--mk-space-2);border-radius:var(--mk-radius-full);background-color:var(--mk-surface-3);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-regular)}:host(.mk-table--stacked) .mk-table__scroll{overflow-x:visible;border:none;border-radius:0;background:none}:host(.mk-table--stacked) .mk-table__table,:host(.mk-table--stacked) .mk-table__body{display:block;background:none}:host(.mk-table--stacked) .mk-table__head{display:none}:host(.mk-table--stacked) .mk-table__row{display:grid;grid-template-columns:1fr;gap:var(--mk-space-1);padding:var(--mk-space-3);margin-bottom:var(--mk-space-3);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg);background-color:var(--mk-surface);box-shadow:var(--mk-shadow-xs)}:host(.mk-table--stacked) .mk-table__td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--mk-space-3);padding:var(--mk-space-1) 0;border:none;text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-title{justify-content:flex-start;padding-bottom:var(--mk-space-2);font-size:var(--mk-font-size-lg);font-weight:var(--mk-font-weight-semibold);color:var(--mk-text)}:host(.mk-table--stacked) .mk-table__td--stack-title~.mk-table__td--stack-title{justify-content:flex-end;margin-top:calc(-1 * var(--mk-space-2) - 1.5em);font-size:var(--mk-font-size-md)}:host(.mk-table--stacked) .mk-table__cell-label{flex:none;color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}:host(.mk-table--stacked) .mk-table__cell-value{min-width:0;text-align:end;overflow-wrap:anywhere}:host(.mk-table--stacked) .mk-table__td--stack-title .mk-table__cell-value,:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-footer{justify-content:flex-start;margin-top:var(--mk-space-2);padding-top:var(--mk-space-3);border-top:var(--mk-border-width) solid var(--mk-border-subtle)}:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{display:flex;flex-wrap:wrap;gap:var(--mk-space-2);width:100%}:host(.mk-table--stacked) .mk-table__td--select,:host(.mk-table--stacked) .mk-table__td--expand{width:auto;justify-content:flex-start}:host(.mk-table--stacked).mk-table--zebra .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background:none}:host(.mk-table--stacked) .mk-table__detail-row,:host(.mk-table--stacked) .mk-table__detail{display:block;padding:0}:host(.mk-table--stacked) .mk-table__detail-row{margin:calc(-1 * var(--mk-space-3)) 0 var(--mk-space-3)}:host(.mk-table--stacked) .mk-table__group-row,:host(.mk-table--stacked) .mk-table__group{display:block;top:0}:host(.mk-table--stacked) .mk-table__row--empty,:host(.mk-table--stacked) .mk-table__empty{display:block;border:none;box-shadow:none;background:none}@media(pointer:coarse){.mk-table__cell-input{font-size:max(var(--mk-font-size-md),16px)}}@media print{.mk-table__scroll{overflow:visible;border-radius:0}.mk-table__head{display:table-header-group}.mk-table__th,.mk-table__td{position:static;box-shadow:none;background-color:transparent!important;color:inherit!important;border-bottom:1px solid var(--mk-border)}.mk-table__row,.mk-table__group-row,.mk-table__detail-row{break-inside:avoid}.mk-table__sort,.mk-table__resize,.mk-table__th--select,.mk-table__td--select,.mk-table__th--expand,.mk-table__td--expand,.mk-table__tree-toggle .mk-table__expander-icon{display:none}.mk-table__th-button,.mk-table__tree-toggle,.mk-table__group-toggle{color:inherit;cursor:default}}\n"], dependencies: [{ kind: "component", type: MkCheckbox, selector: "mk-checkbox", inputs: ["checked", "indeterminate", "disabled", "invalid", "required", "size", "tone", "aria-label"], outputs: ["checkedChange", "indeterminateChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
864
1116
  }
865
1117
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkTable, decorators: [{
866
1118
  type: Component,
@@ -875,8 +1127,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
875
1127
  '[class.mk-table--expandable]': 'expandable()',
876
1128
  '[class.mk-table--grouped]': 'groupBy() !== null',
877
1129
  '[class.mk-table--stacked]': 'stacked()',
878
- }, template: "<div class=\"mk-table__scroll\">\n <!-- Explicit roles ONLY while stacked: `display: block` strips a table\n element of its implicit role, so without these a card layout stops\n being announced as tabular data at all. Redundant in the grid, so\n they are left off there rather than duplicating what the element\n already says. -->\n <table class=\"mk-table__table\" [attr.role]=\"stacked() ? 'table' : null\">\n <thead class=\"mk-table__head\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n <tr>\n @if (expandable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--expand\">\n <span class=\"mk-visually-hidden\">{{ i18n.expandHeader }}</span>\n </th>\n }\n @if (selectable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--select\">\n <mk-checkbox\n [aria-label]=\"i18n.selectAllRows\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of orderedColumns(); track col.key) {\n <th\n scope=\"col\"\n class=\"mk-table__th\"\n [class.mk-table__th--sortable]=\"col.sortable\"\n [class.mk-table__th--pinned]=\"col.pinned\"\n [class.mk-table__th--pinned-right]=\"col.pinned === 'right'\"\n [class.mk-table__th--dragging]=\"dragKey() === col.key\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"col.pinned === 'left' ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"col.pinned === 'right' ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.aria-sort]=\"ariaSort(col)\"\n [attr.draggable]=\"reorderableColumns() && !col.pinned ? true : null\"\n (dragstart)=\"onColDragStart($event, col)\"\n (dragover)=\"onColDragOver($event)\"\n (drop)=\"onColDrop($event, col)\"\n (dragend)=\"onColDragEnd()\"\n >\n @if (col.sortable || (reorderableColumns() && !col.pinned)) {\n <button\n type=\"button\"\n class=\"mk-table__th-button\"\n [class.mk-table__th-button--static]=\"!col.sortable\"\n (click)=\"onSort(col)\"\n (keydown)=\"onReorderKeydown($event, col)\"\n >\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n @if (col.sortable) {\n <span class=\"mk-table__sort\" aria-hidden=\"true\">{{ sortGlyph(col) }}</span>\n }\n </button>\n } @else {\n <span class=\"mk-table__th-inner\">\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n </span>\n }\n @if (resizableColumns() && col.resizable) {\n <span\n class=\"mk-table__resize\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"i18n.resizeColumn\"\n [attr.aria-valuemin]=\"resizeValueMin(col)\"\n [attr.aria-valuenow]=\"resizeValueNow(col)\"\n [attr.aria-valuemax]=\"resizeValueMax\"\n (pointerdown)=\"startResize($event, col)\"\n (keydown)=\"onResizeKeydown($event, col)\"\n (click)=\"$event.stopPropagation()\"\n ></span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"mk-table__body\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n @for (item of displayItems(); track trackItem(item); let i = $index) {\n @if (item.kind === 'group') {\n <tr class=\"mk-table__group-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <th\n class=\"mk-table__group\"\n scope=\"colgroup\"\n [attr.role]=\"stacked() ? 'rowheader' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__group-toggle\"\n [attr.aria-expanded]=\"!isGroupCollapsed(item.group.key)\"\n (click)=\"onGroupToggle(item.group)\"\n >\n <span\n class=\"mk-table__expander-icon\"\n [class.mk-table__expander-icon--open]=\"!isGroupCollapsed(item.group.key)\"\n aria-hidden=\"true\"\n >\u203A</span\n >\n <span class=\"mk-visually-hidden\">{{\n isGroupCollapsed(item.group.key) ? i18n.expandGroup : i18n.collapseGroup\n }}</span>\n <span class=\"mk-table__group-label\">{{ item.group.label }}</span>\n <span class=\"mk-table__group-count\">{{\n i18n.groupCount(item.group.rows.length)\n }}</span>\n </button>\n </th>\n </tr>\n } @else {\n <ng-container>\n <tr\n class=\"mk-table__row\"\n [attr.role]=\"stacked() ? 'row' : null\"\n [class]=\"rowClassFor(item.row)\"\n [class.mk-table__row--selected]=\"selectable() && isSelected(item.row)\"\n [class.mk-table__row--expanded]=\"expandable() && isExpanded(item.row)\"\n [attr.tabindex]=\"clickableRows() ? 0 : null\"\n (click)=\"onRowClick(item.row)\"\n (keydown)=\"onRowKeydown($event, item.row)\"\n >\n @if (expandable()) {\n <td\n class=\"mk-table__td mk-table__td--expand\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__expander\"\n [class.mk-table__expander--open]=\"isExpanded(item.row)\"\n [attr.aria-expanded]=\"isExpanded(item.row)\"\n [attr.aria-controls]=\"detailId(i)\"\n [attr.aria-label]=\"isExpanded(item.row) ? i18n.collapseRow : i18n.expandRow\"\n (click)=\"toggleExpand(item.row, $event)\"\n >\n <span class=\"mk-table__expander-icon\" aria-hidden=\"true\">\u203A</span>\n </button>\n </td>\n }\n @if (selectable()) {\n <td\n class=\"mk-table__td mk-table__td--select\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <mk-checkbox\n [aria-label]=\"i18n.selectRow(rowLabel(item.row))\"\n [checked]=\"isSelected(item.row)\"\n (checkedChange)=\"toggleRow(item.row)\"\n />\n </td>\n }\n @if (!stacked()) {\n @for (col of orderedColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: null }\"\n />\n }\n } @else {\n <!-- Card layout. Same <td> elements, restyled \u2014 keeping the table\n DOM means selection, expansion, inline edit and every cell\n template keep working, since all of them reach for a `td`. -->\n @for (col of stackTitleColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'title' }\"\n />\n }\n @for (col of stackFieldColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'field' }\"\n />\n }\n @for (col of stackFooterColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'footer' }\"\n />\n }\n }\n </tr>\n @if (expandable() && isExpanded(item.row) && rowDetail()) {\n <tr class=\"mk-table__detail-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__detail\"\n [id]=\"detailId(i)\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <div class=\"mk-table__detail-inner\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetail()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item.row }\"\n />\n </div>\n </td>\n </tr>\n }\n </ng-container>\n }\n } @empty {\n <tr class=\"mk-table__row mk-table__row--empty\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__empty\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <ng-content select=\"[mkTableEmpty]\">{{ emptyMessage() }}</ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n\n<!-- One cell, rendered by both layouts. `slot` is null in the grid and\n 'title' | 'field' | 'footer' in a card; everything else \u2014 the editor, the\n consumer's mkTableCell template, the formatted fallback \u2014 is identical, so\n a card can never drift from the grid it replaces. -->\n<ng-template #cellTpl let-col=\"col\" let-row=\"row\" let-i=\"i\" let-slot=\"slot\">\n <td\n class=\"mk-table__td\"\n [class.mk-table__td--pinned]=\"isPinned(col, 'left') || isPinned(col, 'right')\"\n [class.mk-table__td--pinned-right]=\"isPinned(col, 'right')\"\n [class.mk-table__td--editable]=\"col.editable\"\n [class.mk-table__td--stack-title]=\"slot === 'title'\"\n [class.mk-table__td--stack-field]=\"slot === 'field'\"\n [class.mk-table__td--stack-footer]=\"slot === 'footer'\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"isPinned(col, 'left') ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"isPinned(col, 'right') ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.tabindex]=\"col.editable ? 0 : null\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (dblclick)=\"startEdit(i, col, $event)\"\n (keydown)=\"onCellKeydown($event, i, col)\"\n >\n @if (slot === 'field' && hasStackLabel(col)) {\n <!-- The column header, moved beside the value. Not aria-hidden: the\n <thead> is display:none while stacked, so this label is the only\n thing naming the value for a screen reader. -->\n <span class=\"mk-table__cell-label\">{{ col.header }}</span>\n }\n <span class=\"mk-table__cell-value\">\n @if (isEditing(i, col)) {\n <input\n #editInput\n class=\"mk-table__cell-input\"\n [value]=\"cellText(row, col)\"\n [attr.aria-label]=\"col.header\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onEditKeydown($event, row, col)\"\n (blur)=\"commitEdit(row, col, $any($event.target).value)\"\n />\n } @else if (cellTemplateFor(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: cellValue(row, col), row }\"\n />\n } @else {\n {{ cellText(row, col) }}\n @if (col.editable) {\n <span class=\"mk-visually-hidden\">{{ i18n.editCell }}</span>\n }\n }\n </span>\n </td>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--_cell-pad-y: var(--mk-space-3);--_cell-pad-x: var(--mk-space-4);display:block;color:var(--mk-text)}:host(.mk-table--compact){--_cell-pad-y: var(--mk-space-2);--_cell-pad-x: var(--mk-space-3)}.mk-table__scroll{width:100%;overflow-x:auto;border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg)}.mk-table__table{width:100%;border-collapse:collapse;font-size:var(--mk-font-size-sm);background-color:var(--mk-surface)}.mk-table__th{padding:var(--_cell-pad-y) var(--_cell-pad-x);background-color:var(--mk-surface-2);color:var(--mk-text-muted);font-weight:var(--mk-font-weight-semibold);text-align:start;white-space:nowrap;border-bottom:var(--mk-border-width) solid var(--mk-border);vertical-align:middle}:host(.mk-table--sticky) .mk-table__head .mk-table__th{position:sticky;top:0;z-index:var(--mk-z-sticky)}.mk-table__th-inner{display:inline-flex;align-items:center;gap:var(--mk-space-1)}.mk-table__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.mk-table__th--sortable:hover{background-color:var(--mk-surface-3);color:var(--mk-text)}.mk-table__th-button{display:inline-flex;align-items:center;gap:var(--mk-space-1);width:100%;margin:calc(-1 * var(--_cell-pad-y)) calc(-1 * var(--_cell-pad-x));padding:var(--_cell-pad-y) var(--_cell-pad-x);font:inherit;font-weight:inherit;color:inherit;text-align:inherit;background:transparent;border:0;cursor:pointer}.mk-table__th-button--static{cursor:grab}.mk-table__th-button:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[data-align=center] .mk-table__th-button{justify-content:center}.mk-table__th[data-align=end] .mk-table__th-button{justify-content:flex-end}.mk-table__th[aria-sort=ascending],.mk-table__th[aria-sort=descending]{color:var(--mk-text)}.mk-table__sort{font-size:var(--mk-font-size-xs);opacity:.7;line-height:1}.mk-table__td{padding:var(--_cell-pad-y) var(--_cell-pad-x);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);vertical-align:middle}.mk-table__row:last-child .mk-table__td{border-bottom:0}.mk-table__th[data-align=center],.mk-table__td[data-align=center]{text-align:center}.mk-table__th[data-align=end],.mk-table__td[data-align=end]{text-align:right}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background-color:var(--mk-surface-2)}:host(.mk-table--hover) .mk-table__body .mk-table__row:not(.mk-table__row--empty):hover .mk-table__td{background-color:var(--mk-neutral-subtle)}:host(.mk-table--clickable) .mk-table__row:not(.mk-table__row--empty){cursor:pointer}:host(.mk-table--clickable) .mk-table__row:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th--select,.mk-table__td--select{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}:host .mk-table__body .mk-table__row--selected .mk-table__td,:host(.mk-table--zebra) .mk-table__body .mk-table__row--selected:nth-child(2n) .mk-table__td,:host(.mk-table--hover) .mk-table__body .mk-table__row--selected:hover .mk-table__td{background-color:var(--mk-selected-bg);color:var(--mk-selected-text)}.mk-table__th--expand,.mk-table__td--expand{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}.mk-table__expander{display:inline-grid;place-items:center;width:1.5rem;height:1.5rem;padding:0;color:var(--mk-text-muted);background:transparent;border:none;border-radius:var(--mk-radius-sm);cursor:pointer}.mk-table__expander:hover{background-color:var(--mk-hover-overlay);color:var(--mk-text)}.mk-table__expander:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__expander-icon{display:inline-block;font-size:var(--mk-font-size-lg);line-height:1;transition:transform var(--mk-transition-fast, .12s) ease}.mk-table__expander--open .mk-table__expander-icon,.mk-table__expander-icon--open{transform:rotate(90deg)}:host(:dir(rtl)) .mk-table__expander-icon{transform:scaleX(-1)}:host(:dir(rtl)) .mk-table__expander--open .mk-table__expander-icon,:host(:dir(rtl)) .mk-table__expander-icon--open{transform:scaleX(-1) rotate(-90deg)}.mk-table__detail{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle)}.mk-table__detail-inner{padding:var(--_cell-pad-y) var(--_cell-pad-x)}.mk-table__th{position:relative}.mk-table__resize{position:absolute;top:0;inset-inline-end:0;width:8px;height:100%;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}@media(pointer:coarse){.mk-table__resize:before{content:\"\";position:absolute;inset:min(0px,(100% - 24px) / 2)}}.mk-table__resize:after{content:\"\";position:absolute;top:25%;inset-inline-end:3px;width:2px;height:50%;background-color:var(--mk-border)}.mk-table__resize:hover:after,.mk-table__resize:focus-visible:after{background-color:var(--mk-primary)}.mk-table__resize:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[draggable=true]{cursor:grab}.mk-table__th--dragging{opacity:.5}.mk-table__th--pinned,.mk-table__td--pinned{position:sticky;z-index:1;background-color:var(--mk-surface)}.mk-table__th--pinned{z-index:2;background-color:var(--mk-surface-2)}.mk-table__th--pinned:not(.mk-table__th--pinned-right),.mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}.mk-table__th--pinned-right,.mk-table__td--pinned-right{box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned:not(.mk-table__th--pinned-right),:host(:dir(rtl)) .mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned-right,:host(:dir(rtl)) .mk-table__td--pinned-right{box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td--pinned{background-color:var(--mk-surface-2)}.mk-table__td--editable{cursor:text}.mk-table__td--editable:hover{background-color:var(--mk-hover-overlay)}.mk-table__td--editable:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__cell-input{width:100%;margin:calc(-1 * var(--mk-space-1)) 0;padding:var(--mk-space-1) var(--mk-space-2);font:inherit;color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-primary);border-radius:var(--mk-radius-sm);outline:none}.mk-table__empty{padding:var(--mk-space-8) var(--_cell-pad-x);text-align:center;color:var(--mk-text-subtle)}.mk-table__group{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);text-align:start}:host(.mk-table--grouped) .mk-table__group{position:sticky;top:var(--_group-top, 0px);z-index:calc(var(--mk-z-sticky) - 1)}.mk-table__group-toggle{display:flex;align-items:center;gap:var(--mk-space-2);width:100%;padding:var(--mk-space-2) var(--mk-space-3);border:none;background:none;color:var(--mk-text);font:inherit;font-weight:var(--mk-font-weight-semibold);cursor:pointer}.mk-table__group-toggle:hover{background-color:var(--mk-hover-overlay)}.mk-table__group-toggle:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__group-count{padding:0 var(--mk-space-2);border-radius:var(--mk-radius-full);background-color:var(--mk-surface-3);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-regular)}:host(.mk-table--stacked) .mk-table__scroll{overflow-x:visible;border:none;border-radius:0;background:none}:host(.mk-table--stacked) .mk-table__table,:host(.mk-table--stacked) .mk-table__body{display:block;background:none}:host(.mk-table--stacked) .mk-table__head{display:none}:host(.mk-table--stacked) .mk-table__row{display:grid;grid-template-columns:1fr;gap:var(--mk-space-1);padding:var(--mk-space-3);margin-bottom:var(--mk-space-3);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg);background-color:var(--mk-surface);box-shadow:var(--mk-shadow-xs)}:host(.mk-table--stacked) .mk-table__td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--mk-space-3);padding:var(--mk-space-1) 0;border:none;text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-title{justify-content:flex-start;padding-bottom:var(--mk-space-2);font-size:var(--mk-font-size-lg);font-weight:var(--mk-font-weight-semibold);color:var(--mk-text)}:host(.mk-table--stacked) .mk-table__td--stack-title~.mk-table__td--stack-title{justify-content:flex-end;margin-top:calc(-1 * var(--mk-space-2) - 1.5em);font-size:var(--mk-font-size-md)}:host(.mk-table--stacked) .mk-table__cell-label{flex:none;color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}:host(.mk-table--stacked) .mk-table__cell-value{min-width:0;text-align:end;overflow-wrap:anywhere}:host(.mk-table--stacked) .mk-table__td--stack-title .mk-table__cell-value,:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-footer{justify-content:flex-start;margin-top:var(--mk-space-2);padding-top:var(--mk-space-3);border-top:var(--mk-border-width) solid var(--mk-border-subtle)}:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{display:flex;flex-wrap:wrap;gap:var(--mk-space-2);width:100%}:host(.mk-table--stacked) .mk-table__td--select,:host(.mk-table--stacked) .mk-table__td--expand{width:auto;justify-content:flex-start}:host(.mk-table--stacked).mk-table--zebra .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background:none}:host(.mk-table--stacked) .mk-table__detail-row,:host(.mk-table--stacked) .mk-table__detail{display:block;padding:0}:host(.mk-table--stacked) .mk-table__detail-row{margin:calc(-1 * var(--mk-space-3)) 0 var(--mk-space-3)}:host(.mk-table--stacked) .mk-table__group-row,:host(.mk-table--stacked) .mk-table__group{display:block;top:0}:host(.mk-table--stacked) .mk-table__row--empty,:host(.mk-table--stacked) .mk-table__empty{display:block;border:none;box-shadow:none;background:none}@media(pointer:coarse){.mk-table__cell-input{font-size:max(var(--mk-font-size-md),16px)}}\n"] }]
879
- }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], zebra: [{ type: i0.Input, args: [{ isSignal: true, alias: "zebra", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], stackAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "stackAt", required: false }] }], clickableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickableRows", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], trackKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackKey", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], singleExpand: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleExpand", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], groupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupLabel", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], columnReorder: [{ type: i0.Output, args: ["columnReorder"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], groupToggle: [{ type: i0.Output, args: ["groupToggle"] }], editInput: [{ type: i0.ViewChild, args: ['editInput', { isSignal: true }] }], rowDetail: [{ type: i0.ContentChild, args: [i0.forwardRef(() => MkTableRowDetail), { isSignal: true }] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MkTableCell), { isSignal: true }] }] } });
1130
+ }, template: "<div class=\"mk-table__scroll\">\n <!-- Explicit roles ONLY while stacked: `display: block` strips a table\n element of its implicit role, so without these a card layout stops\n being announced as tabular data at all. Redundant in the grid, so\n they are left off there rather than duplicating what the element\n already says. -->\n <table\n class=\"mk-table__table\"\n [attr.role]=\"childrenKey() ? 'treegrid' : stacked() ? 'table' : null\"\n >\n <thead class=\"mk-table__head\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n <tr>\n @if (expandable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--expand\">\n <span class=\"mk-visually-hidden\">{{ i18n.expandHeader }}</span>\n </th>\n }\n @if (selectable()) {\n <th scope=\"col\" class=\"mk-table__th mk-table__th--select\">\n <mk-checkbox\n [aria-label]=\"i18n.selectAllRows\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of orderedColumns(); track col.key) {\n <th\n scope=\"col\"\n class=\"mk-table__th\"\n [class.mk-table__th--sortable]=\"col.sortable\"\n [class.mk-table__th--pinned]=\"col.pinned\"\n [class.mk-table__th--pinned-right]=\"col.pinned === 'right'\"\n [class.mk-table__th--dragging]=\"dragKey() === col.key\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"col.pinned === 'left' ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"col.pinned === 'right' ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.aria-sort]=\"ariaSort(col)\"\n [attr.draggable]=\"reorderableColumns() && !col.pinned ? true : null\"\n (dragstart)=\"onColDragStart($event, col)\"\n (dragover)=\"onColDragOver($event)\"\n (drop)=\"onColDrop($event, col)\"\n (dragend)=\"onColDragEnd()\"\n >\n @if (col.sortable || (reorderableColumns() && !col.pinned)) {\n <button\n type=\"button\"\n class=\"mk-table__th-button\"\n [class.mk-table__th-button--static]=\"!col.sortable\"\n (click)=\"onSort(col)\"\n (keydown)=\"onReorderKeydown($event, col)\"\n >\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n @if (col.sortable) {\n <span class=\"mk-table__sort\" aria-hidden=\"true\">{{ sortGlyph(col) }}</span>\n }\n </button>\n } @else {\n <span class=\"mk-table__th-inner\">\n <span class=\"mk-table__th-label\">{{ col.header }}</span>\n </span>\n }\n @if (resizableColumns() && col.resizable) {\n <span\n class=\"mk-table__resize\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"i18n.resizeColumn\"\n [attr.aria-valuemin]=\"resizeValueMin(col)\"\n [attr.aria-valuenow]=\"resizeValueNow(col)\"\n [attr.aria-valuemax]=\"resizeValueMax\"\n (pointerdown)=\"startResize($event, col)\"\n (keydown)=\"onResizeKeydown($event, col)\"\n (click)=\"$event.stopPropagation()\"\n ></span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"mk-table__body\" [attr.role]=\"stacked() ? 'rowgroup' : null\">\n @for (item of displayItems(); track trackItem(item); let i = $index) {\n @if (item.kind === 'group') {\n <tr class=\"mk-table__group-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <th\n class=\"mk-table__group\"\n scope=\"colgroup\"\n [attr.role]=\"stacked() ? 'rowheader' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__group-toggle\"\n [attr.aria-expanded]=\"!isGroupCollapsed(item.group.key)\"\n (click)=\"onGroupToggle(item.group)\"\n >\n <span\n class=\"mk-table__expander-icon\"\n [class.mk-table__expander-icon--open]=\"!isGroupCollapsed(item.group.key)\"\n aria-hidden=\"true\"\n >\u203A</span\n >\n <span class=\"mk-visually-hidden\">{{\n isGroupCollapsed(item.group.key) ? i18n.expandGroup : i18n.collapseGroup\n }}</span>\n <span class=\"mk-table__group-label\">{{ item.group.label }}</span>\n <span class=\"mk-table__group-count\">{{\n i18n.groupCount(item.group.rows.length)\n }}</span>\n </button>\n </th>\n </tr>\n } @else {\n <ng-container>\n <tr\n class=\"mk-table__row\"\n [attr.role]=\"stacked() || childrenKey() ? 'row' : null\"\n [class]=\"rowClassFor(item.row)\"\n [class.mk-table__row--selected]=\"selectable() && isSelected(item.row)\"\n [class.mk-table__row--expanded]=\"expandable() && isExpanded(item.row)\"\n [class.mk-table__row--parent]=\"item.hasChildren\"\n [style.--mk-tree-depth]=\"childrenKey() ? item.depth : null\"\n [style.margin-inline-start.px]=\"stacked() && item.depth ? item.depth * 16 : null\"\n [attr.aria-level]=\"childrenKey() ? item.depth + 1 : null\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [attr.tabindex]=\"clickableRows() ? 0 : null\"\n (click)=\"onRowClick(item.row)\"\n (keydown)=\"onRowKeydown($event, item.row)\"\n >\n @if (expandable()) {\n <td\n class=\"mk-table__td mk-table__td--expand\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <button\n type=\"button\"\n class=\"mk-table__expander\"\n [class.mk-table__expander--open]=\"isExpanded(item.row)\"\n [attr.aria-expanded]=\"isExpanded(item.row)\"\n [attr.aria-controls]=\"detailId(i)\"\n [attr.aria-label]=\"isExpanded(item.row) ? i18n.collapseRow : i18n.expandRow\"\n (click)=\"toggleExpand(item.row, $event)\"\n >\n <span class=\"mk-table__expander-icon\" aria-hidden=\"true\">\u203A</span>\n </button>\n </td>\n }\n @if (selectable()) {\n <td\n class=\"mk-table__td mk-table__td--select\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <mk-checkbox\n [aria-label]=\"i18n.selectRow(rowLabel(item.row))\"\n [checked]=\"isSelected(item.row)\"\n (checkedChange)=\"toggleRow(item.row)\"\n />\n </td>\n }\n @if (!stacked()) {\n @for (col of orderedColumns(); track col.key; let first = $first) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: null, tree: first ? item : null }\"\n />\n }\n } @else {\n <!-- Card layout. Same <td> elements, restyled \u2014 keeping the table\n DOM means selection, expansion, inline edit and every cell\n template keep working, since all of them reach for a `td`. -->\n @for (col of stackTitleColumns(); track col.key; let first = $first) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'title', tree: first ? item : null }\"\n />\n }\n @for (col of stackFieldColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'field' }\"\n />\n }\n @for (col of stackFooterColumns(); track col.key) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ col, row: item.row, i, slot: 'footer' }\"\n />\n }\n }\n </tr>\n @if (expandable() && isExpanded(item.row) && rowDetail()) {\n <tr class=\"mk-table__detail-row\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__detail\"\n [id]=\"detailId(i)\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <div class=\"mk-table__detail-inner\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetail()!.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item.row }\"\n />\n </div>\n </td>\n </tr>\n }\n </ng-container>\n }\n } @empty {\n <tr class=\"mk-table__row mk-table__row--empty\" [attr.role]=\"stacked() ? 'row' : null\">\n <td\n class=\"mk-table__empty\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n [attr.colspan]=\"totalColumns()\"\n >\n <ng-content select=\"[mkTableEmpty]\">{{ emptyMessage() }}</ng-content>\n </td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n\n<!-- One cell, rendered by both layouts. `slot` is null in the grid and\n 'title' | 'field' | 'footer' in a card; everything else \u2014 the editor, the\n consumer's mkTableCell template, the formatted fallback \u2014 is identical, so\n a card can never drift from the grid it replaces. -->\n<ng-template #cellTpl let-col=\"col\" let-row=\"row\" let-i=\"i\" let-slot=\"slot\" let-tree=\"tree\">\n <td\n class=\"mk-table__td\"\n [class.mk-table__td--tree]=\"!!tree && !!childrenKey()\"\n [class.mk-table__td--pinned]=\"isPinned(col, 'left') || isPinned(col, 'right')\"\n [class.mk-table__td--pinned-right]=\"isPinned(col, 'right')\"\n [class.mk-table__td--editable]=\"col.editable\"\n [class.mk-table__td--stack-title]=\"slot === 'title'\"\n [class.mk-table__td--stack-field]=\"slot === 'field'\"\n [class.mk-table__td--stack-footer]=\"slot === 'footer'\"\n [style.width]=\"colStyleWidth(col)\"\n [style.inset-inline-start.px]=\"isPinned(col, 'left') ? pinnedOffset(col) : null\"\n [style.inset-inline-end.px]=\"isPinned(col, 'right') ? pinnedOffset(col) : null\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [attr.tabindex]=\"col.editable ? 0 : null\"\n [attr.role]=\"stacked() ? 'cell' : null\"\n (dblclick)=\"startEdit(i, col, $event)\"\n (keydown)=\"onCellKeydown($event, i, col)\"\n >\n @if (slot === 'field' && hasStackLabel(col)) {\n <!-- The column header, moved beside the value. Not aria-hidden: the\n <thead> is display:none while stacked, so this label is the only\n thing naming the value for a screen reader. -->\n <span class=\"mk-table__cell-label\">{{ col.header }}</span>\n }\n @if (tree && childrenKey()) {\n <!-- Tree toggle (or a spacer on leaves) ahead of the first cell's value,\n so the indent and the caret read as one column. -->\n @if (tree.hasChildren) {\n <button\n type=\"button\"\n class=\"mk-table__tree-toggle\"\n [class.mk-table__tree-toggle--open]=\"tree.expanded\"\n [attr.aria-expanded]=\"tree.expanded\"\n [attr.aria-label]=\"tree.expanded ? i18n.collapseTreeRow : i18n.expandTreeRow\"\n (click)=\"toggleTreeRow(row, $event)\"\n >\n <span class=\"mk-table__expander-icon\" [class.mk-table__expander-icon--open]=\"tree.expanded\" aria-hidden=\"true\">\u203A</span>\n </button>\n } @else {\n <span class=\"mk-table__tree-spacer\" aria-hidden=\"true\"></span>\n }\n }\n <span class=\"mk-table__cell-value\">\n @if (isEditing(i, col)) {\n <input\n #editInput\n class=\"mk-table__cell-input\"\n [value]=\"cellText(row, col)\"\n [attr.aria-label]=\"col.header\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onEditKeydown($event, row, col)\"\n (blur)=\"commitEdit(row, col, $any($event.target).value)\"\n />\n } @else if (cellTemplateFor(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: cellValue(row, col), row }\"\n />\n } @else {\n {{ cellText(row, col) }}\n @if (col.editable) {\n <span class=\"mk-visually-hidden\">{{ i18n.editCell }}</span>\n }\n }\n </span>\n </td>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--_cell-pad-y: var(--mk-space-3);--_cell-pad-x: var(--mk-space-4);display:block;color:var(--mk-text)}:host(.mk-table--compact){--_cell-pad-y: var(--mk-space-2);--_cell-pad-x: var(--mk-space-3)}.mk-table__scroll{width:100%;overflow-x:auto;border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg)}.mk-table__table{width:100%;border-collapse:collapse;font-size:var(--mk-font-size-sm);background-color:var(--mk-surface)}.mk-table__th{padding:var(--_cell-pad-y) var(--_cell-pad-x);background-color:var(--mk-surface-2);color:var(--mk-text-muted);font-weight:var(--mk-font-weight-semibold);text-align:start;white-space:nowrap;border-bottom:var(--mk-border-width) solid var(--mk-border);vertical-align:middle}:host(.mk-table--sticky) .mk-table__head .mk-table__th{position:sticky;top:0;z-index:var(--mk-z-sticky)}.mk-table__th-inner{display:inline-flex;align-items:center;gap:var(--mk-space-1)}.mk-table__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.mk-table__th--sortable:hover{background-color:var(--mk-surface-3);color:var(--mk-text)}.mk-table__th-button{display:inline-flex;align-items:center;gap:var(--mk-space-1);width:100%;margin:calc(-1 * var(--_cell-pad-y)) calc(-1 * var(--_cell-pad-x));padding:var(--_cell-pad-y) var(--_cell-pad-x);font:inherit;font-weight:inherit;color:inherit;text-align:inherit;background:transparent;border:0;cursor:pointer}.mk-table__th-button--static{cursor:grab}.mk-table__th-button:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[data-align=center] .mk-table__th-button{justify-content:center}.mk-table__th[data-align=end] .mk-table__th-button{justify-content:flex-end}.mk-table__th[aria-sort=ascending],.mk-table__th[aria-sort=descending]{color:var(--mk-text)}.mk-table__sort{font-size:var(--mk-font-size-xs);opacity:.7;line-height:1}.mk-table__td{padding:var(--_cell-pad-y) var(--_cell-pad-x);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);vertical-align:middle}.mk-table__row:last-child .mk-table__td{border-bottom:0}.mk-table__th[data-align=center],.mk-table__td[data-align=center]{text-align:center}.mk-table__th[data-align=end],.mk-table__td[data-align=end]{text-align:right}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background-color:var(--mk-surface-2)}:host(.mk-table--hover) .mk-table__body .mk-table__row:not(.mk-table__row--empty):hover .mk-table__td{background-color:var(--mk-neutral-subtle)}:host(.mk-table--clickable) .mk-table__row:not(.mk-table__row--empty){cursor:pointer}:host(.mk-table--clickable) .mk-table__row:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th--select,.mk-table__td--select{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}:host .mk-table__body .mk-table__row--selected .mk-table__td,:host(.mk-table--zebra) .mk-table__body .mk-table__row--selected:nth-child(2n) .mk-table__td,:host(.mk-table--hover) .mk-table__body .mk-table__row--selected:hover .mk-table__td{background-color:var(--mk-selected-bg);color:var(--mk-selected-text)}.mk-table__th--expand,.mk-table__td--expand{width:1%;white-space:nowrap;text-align:center;vertical-align:middle}.mk-table__expander{display:inline-grid;place-items:center;width:1.5rem;height:1.5rem;padding:0;color:var(--mk-text-muted);background:transparent;border:none;border-radius:var(--mk-radius-sm);cursor:pointer}.mk-table__expander:hover{background-color:var(--mk-hover-overlay);color:var(--mk-text)}.mk-table__expander:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__expander-icon{display:inline-block;font-size:var(--mk-font-size-lg);line-height:1;transition:transform var(--mk-transition-fast, .12s) ease}.mk-table__expander--open .mk-table__expander-icon,.mk-table__expander-icon--open{transform:rotate(90deg)}:host(:dir(rtl)) .mk-table__expander-icon{transform:scaleX(-1)}:host(:dir(rtl)) .mk-table__expander--open .mk-table__expander-icon,:host(:dir(rtl)) .mk-table__expander-icon--open{transform:scaleX(-1) rotate(-90deg)}.mk-table__detail{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle)}.mk-table__detail-inner{padding:var(--_cell-pad-y) var(--_cell-pad-x)}.mk-table__th{position:relative}.mk-table__resize{position:absolute;top:0;inset-inline-end:0;width:8px;height:100%;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}@media(pointer:coarse){.mk-table__resize:before{content:\"\";position:absolute;inset:min(0px,(100% - 24px) / 2)}}.mk-table__resize:after{content:\"\";position:absolute;top:25%;inset-inline-end:3px;width:2px;height:50%;background-color:var(--mk-border)}.mk-table__resize:hover:after,.mk-table__resize:focus-visible:after{background-color:var(--mk-primary)}.mk-table__resize:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__th[draggable=true]{cursor:grab}.mk-table__th--dragging{opacity:.5}.mk-table__th--pinned,.mk-table__td--pinned{position:sticky;z-index:1;background-color:var(--mk-surface)}.mk-table__th--pinned{z-index:2;background-color:var(--mk-surface-2)}.mk-table__th--pinned:not(.mk-table__th--pinned-right),.mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}.mk-table__th--pinned-right,.mk-table__td--pinned-right{box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned:not(.mk-table__th--pinned-right),:host(:dir(rtl)) .mk-table__td--pinned:not(.mk-table__td--pinned-right){box-shadow:-2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(:dir(rtl)) .mk-table__th--pinned-right,:host(:dir(rtl)) .mk-table__td--pinned-right{box-shadow:2px 0 4px -2px var(--mk-shadow-color, rgba(0, 0, 0, .15))}:host(.mk-table--zebra) .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td--pinned{background-color:var(--mk-surface-2)}.mk-table__td--editable{cursor:text}.mk-table__td--editable:hover{background-color:var(--mk-hover-overlay)}.mk-table__td--editable:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__cell-input{width:100%;margin:calc(-1 * var(--mk-space-1)) 0;padding:var(--mk-space-1) var(--mk-space-2);font:inherit;color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-primary);border-radius:var(--mk-radius-sm);outline:none}.mk-table__empty{padding:var(--mk-space-8) var(--_cell-pad-x);text-align:center;color:var(--mk-text-subtle)}.mk-table__td--tree{padding-inline-start:calc(var(--_cell-pad-x) + var(--mk-tree-depth, 0) * 1.25rem);white-space:nowrap}.mk-table__tree-toggle,.mk-table__tree-spacer{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-inline-end:var(--mk-space-1);vertical-align:middle;flex:none}.mk-table__tree-toggle{padding:0;border:0;border-radius:var(--mk-radius-sm);background:transparent;color:var(--mk-text-muted);cursor:pointer}.mk-table__tree-toggle:hover{color:var(--mk-text);background:var(--mk-hover-overlay)}.mk-table__tree-toggle:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(var(--mk-focus-ring-offset) * -1)}.mk-table__td--tree .mk-table__cell-value{display:inline;vertical-align:middle}.mk-table__group{padding:0;background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);text-align:start}:host(.mk-table--grouped) .mk-table__group{position:sticky;top:var(--_group-top, 0px);z-index:calc(var(--mk-z-sticky) - 1)}.mk-table__group-toggle{display:flex;align-items:center;gap:var(--mk-space-2);width:100%;padding:var(--mk-space-2) var(--mk-space-3);border:none;background:none;color:var(--mk-text);font:inherit;font-weight:var(--mk-font-weight-semibold);cursor:pointer}.mk-table__group-toggle:hover{background-color:var(--mk-hover-overlay)}.mk-table__group-toggle:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-table__group-count{padding:0 var(--mk-space-2);border-radius:var(--mk-radius-full);background-color:var(--mk-surface-3);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-regular)}:host(.mk-table--stacked) .mk-table__scroll{overflow-x:visible;border:none;border-radius:0;background:none}:host(.mk-table--stacked) .mk-table__table,:host(.mk-table--stacked) .mk-table__body{display:block;background:none}:host(.mk-table--stacked) .mk-table__head{display:none}:host(.mk-table--stacked) .mk-table__row{display:grid;grid-template-columns:1fr;gap:var(--mk-space-1);padding:var(--mk-space-3);margin-bottom:var(--mk-space-3);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg);background-color:var(--mk-surface);box-shadow:var(--mk-shadow-xs)}:host(.mk-table--stacked) .mk-table__td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--mk-space-3);padding:var(--mk-space-1) 0;border:none;text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-title{justify-content:flex-start;padding-bottom:var(--mk-space-2);font-size:var(--mk-font-size-lg);font-weight:var(--mk-font-weight-semibold);color:var(--mk-text)}:host(.mk-table--stacked) .mk-table__td--stack-title~.mk-table__td--stack-title{justify-content:flex-end;margin-top:calc(-1 * var(--mk-space-2) - 1.5em);font-size:var(--mk-font-size-md)}:host(.mk-table--stacked) .mk-table__cell-label{flex:none;color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}:host(.mk-table--stacked) .mk-table__cell-value{min-width:0;text-align:end;overflow-wrap:anywhere}:host(.mk-table--stacked) .mk-table__td--stack-title .mk-table__cell-value,:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{text-align:start}:host(.mk-table--stacked) .mk-table__td--stack-footer{justify-content:flex-start;margin-top:var(--mk-space-2);padding-top:var(--mk-space-3);border-top:var(--mk-border-width) solid var(--mk-border-subtle)}:host(.mk-table--stacked) .mk-table__td--stack-footer .mk-table__cell-value{display:flex;flex-wrap:wrap;gap:var(--mk-space-2);width:100%}:host(.mk-table--stacked) .mk-table__td--select,:host(.mk-table--stacked) .mk-table__td--expand{width:auto;justify-content:flex-start}:host(.mk-table--stacked).mk-table--zebra .mk-table__body .mk-table__row:nth-child(2n) .mk-table__td{background:none}:host(.mk-table--stacked) .mk-table__detail-row,:host(.mk-table--stacked) .mk-table__detail{display:block;padding:0}:host(.mk-table--stacked) .mk-table__detail-row{margin:calc(-1 * var(--mk-space-3)) 0 var(--mk-space-3)}:host(.mk-table--stacked) .mk-table__group-row,:host(.mk-table--stacked) .mk-table__group{display:block;top:0}:host(.mk-table--stacked) .mk-table__row--empty,:host(.mk-table--stacked) .mk-table__empty{display:block;border:none;box-shadow:none;background:none}@media(pointer:coarse){.mk-table__cell-input{font-size:max(var(--mk-font-size-md),16px)}}@media print{.mk-table__scroll{overflow:visible;border-radius:0}.mk-table__head{display:table-header-group}.mk-table__th,.mk-table__td{position:static;box-shadow:none;background-color:transparent!important;color:inherit!important;border-bottom:1px solid var(--mk-border)}.mk-table__row,.mk-table__group-row,.mk-table__detail-row{break-inside:avoid}.mk-table__sort,.mk-table__resize,.mk-table__th--select,.mk-table__td--select,.mk-table__th--expand,.mk-table__td--expand,.mk-table__tree-toggle .mk-table__expander-icon{display:none}.mk-table__th-button,.mk-table__tree-toggle,.mk-table__group-toggle{color:inherit;cursor:default}}\n"] }]
1131
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], zebra: [{ type: i0.Input, args: [{ isSignal: true, alias: "zebra", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], stackAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "stackAt", required: false }] }], clickableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickableRows", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], trackKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackKey", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], singleExpand: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleExpand", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], groupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupLabel", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], columnReorder: [{ type: i0.Output, args: ["columnReorder"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], groupToggle: [{ type: i0.Output, args: ["groupToggle"] }], childrenKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "childrenKey", required: false }] }], treeToggle: [{ type: i0.Output, args: ["treeToggle"] }], editInput: [{ type: i0.ViewChild, args: ['editInput', { isSignal: true }] }], rowDetail: [{ type: i0.ContentChild, args: [i0.forwardRef(() => MkTableRowDetail), { isSignal: true }] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MkTableCell), { isSignal: true }] }] } });
880
1132
 
881
1133
  /**
882
1134
  * Sort coordinator — apply `mkSort` to a table (or any container) to track
@@ -1374,5 +1626,5 @@ class MkTableDataSource {
1374
1626
  * Generated bundle index. Do not edit.
1375
1627
  */
1376
1628
 
1377
- export { MkSort, MkSortHeader, MkTable, MkTableCell, MkTableDataSource, MkTableRowDetail };
1629
+ export { MkSort, MkSortHeader, MkTable, MkTableCell, MkTableDataSource, MkTableRowDetail, mkDownloadText, mkExportCsv, mkToCsv };
1378
1630
  //# sourceMappingURL=mk-kit-ui-table.mjs.map