@star-ng/ui 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -2
  3. package/fesm2022/star-ng-ui-accordion.mjs +376 -0
  4. package/fesm2022/star-ng-ui-accordion.mjs.map +1 -0
  5. package/fesm2022/star-ng-ui-autocomplete.mjs +786 -0
  6. package/fesm2022/star-ng-ui-autocomplete.mjs.map +1 -0
  7. package/fesm2022/star-ng-ui-avatar.mjs +154 -0
  8. package/fesm2022/star-ng-ui-avatar.mjs.map +1 -0
  9. package/fesm2022/star-ng-ui-badge.mjs +153 -0
  10. package/fesm2022/star-ng-ui-badge.mjs.map +1 -0
  11. package/fesm2022/star-ng-ui-breadcrumb.mjs +199 -0
  12. package/fesm2022/star-ng-ui-breadcrumb.mjs.map +1 -0
  13. package/fesm2022/star-ng-ui-button.mjs +282 -0
  14. package/fesm2022/star-ng-ui-button.mjs.map +1 -0
  15. package/fesm2022/star-ng-ui-card.mjs +112 -0
  16. package/fesm2022/star-ng-ui-card.mjs.map +1 -0
  17. package/fesm2022/star-ng-ui-chart.mjs +1904 -0
  18. package/fesm2022/star-ng-ui-chart.mjs.map +1 -0
  19. package/fesm2022/star-ng-ui-checkbox.mjs +345 -0
  20. package/fesm2022/star-ng-ui-checkbox.mjs.map +1 -0
  21. package/fesm2022/star-ng-ui-core.mjs +484 -0
  22. package/fesm2022/star-ng-ui-core.mjs.map +1 -0
  23. package/fesm2022/star-ng-ui-data-display.mjs +1870 -0
  24. package/fesm2022/star-ng-ui-data-display.mjs.map +1 -0
  25. package/fesm2022/star-ng-ui-date-picker.mjs +2786 -0
  26. package/fesm2022/star-ng-ui-date-picker.mjs.map +1 -0
  27. package/fesm2022/star-ng-ui-dialog.mjs +948 -0
  28. package/fesm2022/star-ng-ui-dialog.mjs.map +1 -0
  29. package/fesm2022/star-ng-ui-drawer.mjs +158 -0
  30. package/fesm2022/star-ng-ui-drawer.mjs.map +1 -0
  31. package/fesm2022/star-ng-ui-editor.mjs +416 -0
  32. package/fesm2022/star-ng-ui-editor.mjs.map +1 -0
  33. package/fesm2022/star-ng-ui-field.mjs +378 -0
  34. package/fesm2022/star-ng-ui-field.mjs.map +1 -0
  35. package/fesm2022/star-ng-ui-file-upload.mjs +762 -0
  36. package/fesm2022/star-ng-ui-file-upload.mjs.map +1 -0
  37. package/fesm2022/star-ng-ui-i18n-de.mjs +179 -0
  38. package/fesm2022/star-ng-ui-i18n-de.mjs.map +1 -0
  39. package/fesm2022/star-ng-ui-i18n-es.mjs +179 -0
  40. package/fesm2022/star-ng-ui-i18n-es.mjs.map +1 -0
  41. package/fesm2022/star-ng-ui-input-group.mjs +188 -0
  42. package/fesm2022/star-ng-ui-input-group.mjs.map +1 -0
  43. package/fesm2022/star-ng-ui-input-mask.mjs +434 -0
  44. package/fesm2022/star-ng-ui-input-mask.mjs.map +1 -0
  45. package/fesm2022/star-ng-ui-input-number.mjs +691 -0
  46. package/fesm2022/star-ng-ui-input-number.mjs.map +1 -0
  47. package/fesm2022/star-ng-ui-input-otp.mjs +343 -0
  48. package/fesm2022/star-ng-ui-input-otp.mjs.map +1 -0
  49. package/fesm2022/star-ng-ui-input-tags.mjs +616 -0
  50. package/fesm2022/star-ng-ui-input-tags.mjs.map +1 -0
  51. package/fesm2022/star-ng-ui-knob.mjs +514 -0
  52. package/fesm2022/star-ng-ui-knob.mjs.map +1 -0
  53. package/fesm2022/star-ng-ui-layout.mjs +608 -0
  54. package/fesm2022/star-ng-ui-layout.mjs.map +1 -0
  55. package/fesm2022/star-ng-ui-listbox.mjs +886 -0
  56. package/fesm2022/star-ng-ui-listbox.mjs.map +1 -0
  57. package/fesm2022/star-ng-ui-media.mjs +833 -0
  58. package/fesm2022/star-ng-ui-media.mjs.map +1 -0
  59. package/fesm2022/star-ng-ui-menu.mjs +1840 -0
  60. package/fesm2022/star-ng-ui-menu.mjs.map +1 -0
  61. package/fesm2022/star-ng-ui-message.mjs +191 -0
  62. package/fesm2022/star-ng-ui-message.mjs.map +1 -0
  63. package/fesm2022/star-ng-ui-paginator.mjs +387 -0
  64. package/fesm2022/star-ng-ui-paginator.mjs.map +1 -0
  65. package/fesm2022/star-ng-ui-panel.mjs +324 -0
  66. package/fesm2022/star-ng-ui-panel.mjs.map +1 -0
  67. package/fesm2022/star-ng-ui-password.mjs +517 -0
  68. package/fesm2022/star-ng-ui-password.mjs.map +1 -0
  69. package/fesm2022/star-ng-ui-popover.mjs +241 -0
  70. package/fesm2022/star-ng-ui-popover.mjs.map +1 -0
  71. package/fesm2022/star-ng-ui-progress-bar.mjs +183 -0
  72. package/fesm2022/star-ng-ui-progress-bar.mjs.map +1 -0
  73. package/fesm2022/star-ng-ui-radio.mjs +411 -0
  74. package/fesm2022/star-ng-ui-radio.mjs.map +1 -0
  75. package/fesm2022/star-ng-ui-rating.mjs +211 -0
  76. package/fesm2022/star-ng-ui-rating.mjs.map +1 -0
  77. package/fesm2022/star-ng-ui-select-button.mjs +613 -0
  78. package/fesm2022/star-ng-ui-select-button.mjs.map +1 -0
  79. package/fesm2022/star-ng-ui-select.mjs +2547 -0
  80. package/fesm2022/star-ng-ui-select.mjs.map +1 -0
  81. package/fesm2022/star-ng-ui-skeleton.mjs +160 -0
  82. package/fesm2022/star-ng-ui-skeleton.mjs.map +1 -0
  83. package/fesm2022/star-ng-ui-slider.mjs +552 -0
  84. package/fesm2022/star-ng-ui-slider.mjs.map +1 -0
  85. package/fesm2022/star-ng-ui-spinner.mjs +148 -0
  86. package/fesm2022/star-ng-ui-spinner.mjs.map +1 -0
  87. package/fesm2022/star-ng-ui-stepper.mjs +360 -0
  88. package/fesm2022/star-ng-ui-stepper.mjs.map +1 -0
  89. package/fesm2022/star-ng-ui-table.mjs +3531 -0
  90. package/fesm2022/star-ng-ui-table.mjs.map +1 -0
  91. package/fesm2022/star-ng-ui-tabs.mjs +464 -0
  92. package/fesm2022/star-ng-ui-tabs.mjs.map +1 -0
  93. package/fesm2022/star-ng-ui-tag.mjs +129 -0
  94. package/fesm2022/star-ng-ui-tag.mjs.map +1 -0
  95. package/fesm2022/star-ng-ui-theme-switch.mjs +105 -0
  96. package/fesm2022/star-ng-ui-theme-switch.mjs.map +1 -0
  97. package/fesm2022/star-ng-ui-theme.mjs +98 -0
  98. package/fesm2022/star-ng-ui-theme.mjs.map +1 -0
  99. package/fesm2022/star-ng-ui-toast.mjs +298 -0
  100. package/fesm2022/star-ng-ui-toast.mjs.map +1 -0
  101. package/fesm2022/star-ng-ui-toggle-switch.mjs +316 -0
  102. package/fesm2022/star-ng-ui-toggle-switch.mjs.map +1 -0
  103. package/fesm2022/star-ng-ui-tooltip.mjs +297 -0
  104. package/fesm2022/star-ng-ui-tooltip.mjs.map +1 -0
  105. package/fesm2022/star-ng-ui-transloco.mjs +40 -0
  106. package/fesm2022/star-ng-ui-transloco.mjs.map +1 -0
  107. package/fesm2022/star-ng-ui-tree.mjs +1446 -0
  108. package/fesm2022/star-ng-ui-tree.mjs.map +1 -0
  109. package/fesm2022/star-ng-ui-utility.mjs +2134 -0
  110. package/fesm2022/star-ng-ui-utility.mjs.map +1 -0
  111. package/fesm2022/star-ng-ui.mjs +51 -0
  112. package/package.json +285 -3
  113. package/styles/_base.scss +70 -0
  114. package/styles/_shared.scss +2 -0
  115. package/styles/_tokens.scss +190 -0
  116. package/styles/controls/_accordion.scss +75 -0
  117. package/styles/controls/_autocomplete.scss +44 -0
  118. package/styles/controls/_avatar.scss +39 -0
  119. package/styles/controls/_breadcrumb.scss +45 -0
  120. package/styles/controls/_button.scss +137 -0
  121. package/styles/controls/_card.scss +38 -0
  122. package/styles/controls/_chart.scss +214 -0
  123. package/styles/controls/_chip.scss +51 -0
  124. package/styles/controls/_choice.scss +153 -0
  125. package/styles/controls/_data-display.scss +124 -0
  126. package/styles/controls/_date-picker.scss +300 -0
  127. package/styles/controls/_dialog.scss +123 -0
  128. package/styles/controls/_drawer.scss +118 -0
  129. package/styles/controls/_editor.scss +74 -0
  130. package/styles/controls/_field.scss +92 -0
  131. package/styles/controls/_file-upload.scss +136 -0
  132. package/styles/controls/_input-group.scss +104 -0
  133. package/styles/controls/_input-mask.scss +46 -0
  134. package/styles/controls/_input-number.scss +125 -0
  135. package/styles/controls/_knob.scss +76 -0
  136. package/styles/controls/_layout.scss +182 -0
  137. package/styles/controls/_listbox.scss +38 -0
  138. package/styles/controls/_media.scss +222 -0
  139. package/styles/controls/_menu.scss +254 -0
  140. package/styles/controls/_message.scss +48 -0
  141. package/styles/controls/_org-chart.scss +128 -0
  142. package/styles/controls/_paginator.scss +59 -0
  143. package/styles/controls/_panel.scss +83 -0
  144. package/styles/controls/_popover.scss +40 -0
  145. package/styles/controls/_progress-bar.scss +74 -0
  146. package/styles/controls/_select-button.scss +61 -0
  147. package/styles/controls/_select.scss +216 -0
  148. package/styles/controls/_skeleton.scss +43 -0
  149. package/styles/controls/_slider.scss +163 -0
  150. package/styles/controls/_spinner.scss +34 -0
  151. package/styles/controls/_stepper.scss +109 -0
  152. package/styles/controls/_table.scss +523 -0
  153. package/styles/controls/_tabs.scss +93 -0
  154. package/styles/controls/_tag.scss +84 -0
  155. package/styles/controls/_toast.scss +141 -0
  156. package/styles/controls/_tooltip.scss +14 -0
  157. package/styles/controls/_tree.scss +113 -0
  158. package/styles/controls/_utility.scss +654 -0
  159. package/styles/star-ng.css +5807 -0
  160. package/styles/star-ng.min.css +1 -0
  161. package/styles/star-ng.scss +50 -0
  162. package/theme/star-theme-first-paint.js +1 -0
  163. package/types/star-ng-ui-accordion.d.ts +82 -0
  164. package/types/star-ng-ui-autocomplete.d.ts +171 -0
  165. package/types/star-ng-ui-avatar.d.ts +43 -0
  166. package/types/star-ng-ui-badge.d.ts +46 -0
  167. package/types/star-ng-ui-breadcrumb.d.ts +39 -0
  168. package/types/star-ng-ui-button.d.ts +79 -0
  169. package/types/star-ng-ui-card.d.ts +29 -0
  170. package/types/star-ng-ui-chart.d.ts +337 -0
  171. package/types/star-ng-ui-checkbox.d.ts +92 -0
  172. package/types/star-ng-ui-core.d.ts +373 -0
  173. package/types/star-ng-ui-data-display.d.ts +438 -0
  174. package/types/star-ng-ui-date-picker.d.ts +701 -0
  175. package/types/star-ng-ui-dialog.d.ts +254 -0
  176. package/types/star-ng-ui-drawer.d.ts +29 -0
  177. package/types/star-ng-ui-editor.d.ts +96 -0
  178. package/types/star-ng-ui-field.d.ts +146 -0
  179. package/types/star-ng-ui-file-upload.d.ts +192 -0
  180. package/types/star-ng-ui-i18n-de.d.ts +7 -0
  181. package/types/star-ng-ui-i18n-es.d.ts +7 -0
  182. package/types/star-ng-ui-input-group.d.ts +58 -0
  183. package/types/star-ng-ui-input-mask.d.ts +126 -0
  184. package/types/star-ng-ui-input-number.d.ts +193 -0
  185. package/types/star-ng-ui-input-otp.d.ts +86 -0
  186. package/types/star-ng-ui-input-tags.d.ts +159 -0
  187. package/types/star-ng-ui-knob.d.ts +121 -0
  188. package/types/star-ng-ui-layout.d.ts +154 -0
  189. package/types/star-ng-ui-listbox.d.ts +170 -0
  190. package/types/star-ng-ui-media.d.ts +161 -0
  191. package/types/star-ng-ui-menu.d.ts +332 -0
  192. package/types/star-ng-ui-message.d.ts +52 -0
  193. package/types/star-ng-ui-paginator.d.ts +85 -0
  194. package/types/star-ng-ui-panel.d.ts +65 -0
  195. package/types/star-ng-ui-password.d.ts +129 -0
  196. package/types/star-ng-ui-popover.d.ts +57 -0
  197. package/types/star-ng-ui-progress-bar.d.ts +49 -0
  198. package/types/star-ng-ui-radio.d.ts +116 -0
  199. package/types/star-ng-ui-rating.d.ts +52 -0
  200. package/types/star-ng-ui-select-button.d.ts +169 -0
  201. package/types/star-ng-ui-select.d.ts +563 -0
  202. package/types/star-ng-ui-skeleton.d.ts +47 -0
  203. package/types/star-ng-ui-slider.d.ts +145 -0
  204. package/types/star-ng-ui-spinner.d.ts +29 -0
  205. package/types/star-ng-ui-stepper.d.ts +89 -0
  206. package/types/star-ng-ui-table.d.ts +885 -0
  207. package/types/star-ng-ui-tabs.d.ts +109 -0
  208. package/types/star-ng-ui-tag.d.ts +35 -0
  209. package/types/star-ng-ui-theme-switch.d.ts +36 -0
  210. package/types/star-ng-ui-theme.d.ts +95 -0
  211. package/types/star-ng-ui-toast.d.ts +84 -0
  212. package/types/star-ng-ui-toggle-switch.d.ts +81 -0
  213. package/types/star-ng-ui-tooltip.d.ts +66 -0
  214. package/types/star-ng-ui-transloco.d.ts +14 -0
  215. package/types/star-ng-ui-tree.d.ts +343 -0
  216. package/types/star-ng-ui-utility.d.ts +533 -0
  217. package/types/star-ng-ui.d.ts +51 -0
@@ -0,0 +1,3531 @@
1
+ import { DOCUMENT, NgTemplateOutlet } from "@angular/common";
2
+ import * as i0 from "@angular/core";
3
+ import { ApplicationRef, ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injector, TemplateRef, afterNextRender, afterRenderEffect, booleanAttribute, computed, contentChild, contentChildren, effect, inject, input, isDevMode, model, output, signal, untracked, viewChild } from "@angular/core";
4
+ import { StarButton } from "@star-ng/ui/button";
5
+ import { StarCheckbox } from "@star-ng/ui/checkbox";
6
+ import { STAR_UI_TEXT, compareValues, matchesFilter, readOption, starIsRtl } from "@star-ng/ui/core";
7
+ import { StarPaginator } from "@star-ng/ui/paginator";
8
+ import { StarPopover } from "@star-ng/ui/popover";
9
+ import { StarMultiSelect } from "@star-ng/ui/select";
10
+ import { StarSkeleton } from "@star-ng/ui/skeleton";
11
+ const encoder = new TextEncoder();
12
+ function escapeXml(text) {
13
+ return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g, "");
14
+ }
15
+ let crcTable = null;
16
+ function crc32(bytes) {
17
+ if (!crcTable) {
18
+ crcTable = /* @__PURE__ */ new Uint32Array(256);
19
+ for (let n = 0; n < 256; n++) {
20
+ let c = n;
21
+ for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
22
+ crcTable[n] = c >>> 0;
23
+ }
24
+ }
25
+ let crc = 4294967295;
26
+ for (const byte of bytes) crc = crcTable[(crc ^ byte) & 255] ^ crc >>> 8;
27
+ return (crc ^ 4294967295) >>> 0;
28
+ }
29
+ function zip(files) {
30
+ const chunks = [];
31
+ const central = [];
32
+ let offset = 0;
33
+ for (const file of files) {
34
+ const name = encoder.encode(file.name);
35
+ const data = encoder.encode(file.text);
36
+ const crc = crc32(data);
37
+ const local = /* @__PURE__ */ new DataView(/* @__PURE__ */ new ArrayBuffer(30));
38
+ local.setUint32(0, 67324752, true);
39
+ local.setUint16(4, 20, true);
40
+ local.setUint16(6, 2048, true);
41
+ local.setUint16(8, 0, true);
42
+ local.setUint32(14, crc, true);
43
+ local.setUint32(18, data.length, true);
44
+ local.setUint32(22, data.length, true);
45
+ local.setUint16(26, name.length, true);
46
+ const entry = /* @__PURE__ */ new DataView(/* @__PURE__ */ new ArrayBuffer(46));
47
+ entry.setUint32(0, 33639248, true);
48
+ entry.setUint16(4, 20, true);
49
+ entry.setUint16(6, 20, true);
50
+ entry.setUint16(8, 2048, true);
51
+ entry.setUint32(16, crc, true);
52
+ entry.setUint32(20, data.length, true);
53
+ entry.setUint32(24, data.length, true);
54
+ entry.setUint16(28, name.length, true);
55
+ entry.setUint32(42, offset, true);
56
+ chunks.push(new Uint8Array(local.buffer), name, data);
57
+ central.push(new Uint8Array(entry.buffer), name);
58
+ offset += 30 + name.length + data.length;
59
+ }
60
+ const centralSize = central.reduce((size, part) => size + part.length, 0);
61
+ const end = /* @__PURE__ */ new DataView(/* @__PURE__ */ new ArrayBuffer(22));
62
+ end.setUint32(0, 101010256, true);
63
+ end.setUint16(8, files.length, true);
64
+ end.setUint16(10, files.length, true);
65
+ end.setUint32(12, centralSize, true);
66
+ end.setUint32(16, offset, true);
67
+ const parts = [
68
+ ...chunks,
69
+ ...central,
70
+ new Uint8Array(end.buffer)
71
+ ];
72
+ const out = new Uint8Array(parts.reduce((size, part) => size + part.length, 0));
73
+ let position = 0;
74
+ for (const part of parts) {
75
+ out.set(part, position);
76
+ position += part.length;
77
+ }
78
+ return out;
79
+ }
80
+ function columnName(index) {
81
+ let name = "";
82
+ for (let n = index + 1; n > 0; n = Math.floor((n - 1) / 26)) name = String.fromCharCode(65 + (n - 1) % 26) + name;
83
+ return name;
84
+ }
85
+ function buildXlsx(headers, rows, sheetName = "Sheet1") {
86
+ const cell = (value, column, row, style = "") => {
87
+ const ref = `${columnName(column)}${row}`;
88
+ return typeof value === "number" && Number.isFinite(value) ? `<c r="${ref}"${style}><v>${value}</v></c>` : `<c r="${ref}"${style} t="inlineStr"><is><t xml:space="preserve">${escapeXml(String(value))}</t></is></c>`;
89
+ };
90
+ const sheetRows = [`<row r="1">${headers.map((header, i) => cell(header, i, 1, " s=\"1\"")).join("")}</row>`, ...rows.map((row, r) => `<row r="${r + 2}">${row.map((value, i) => cell(value, i, r + 2)).join("")}</row>`)];
91
+ const head = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
92
+ const main = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
93
+ const rel = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
94
+ const pkg = "http://schemas.openxmlformats.org/package/2006";
95
+ const type = "application/vnd.openxmlformats-officedocument.spreadsheetml";
96
+ const safeName = escapeXml(sheetName.replace(/[\\/?*[\]:]/g, " ").slice(0, 31) || "Sheet1");
97
+ return zip([
98
+ {
99
+ name: "[Content_Types].xml",
100
+ text: `${head}<Types xmlns="${pkg}/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="${type}.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="${type}.worksheet+xml"/><Override PartName="/xl/styles.xml" ContentType="${type}.styles+xml"/></Types>`
101
+ },
102
+ {
103
+ name: "_rels/.rels",
104
+ text: `${head}<Relationships xmlns="${pkg}/relationships"><Relationship Id="rId1" Type="${rel}/officeDocument" Target="xl/workbook.xml"/></Relationships>`
105
+ },
106
+ {
107
+ name: "xl/workbook.xml",
108
+ text: `${head}<workbook xmlns="${main}" xmlns:r="${rel}"><sheets><sheet name="${safeName}" sheetId="1" r:id="rId1"/></sheets></workbook>`
109
+ },
110
+ {
111
+ name: "xl/_rels/workbook.xml.rels",
112
+ text: `${head}<Relationships xmlns="${pkg}/relationships"><Relationship Id="rId1" Type="${rel}/worksheet" Target="worksheets/sheet1.xml"/><Relationship Id="rId2" Type="${rel}/styles" Target="styles.xml"/></Relationships>`
113
+ },
114
+ {
115
+ name: "xl/styles.xml",
116
+ text: `${head}<styleSheet xmlns="${main}"><fonts count="2"><font><sz val="11"/><name val="Calibri"/></font><font><b/><sz val="11"/><name val="Calibri"/></font></fonts><fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills><borders count="1"><border/></borders><cellStyleXfs count="1"><xf/></cellStyleXfs><cellXfs count="2"><xf/><xf fontId="1" applyFont="1"/></cellXfs></styleSheet>`
117
+ },
118
+ {
119
+ name: "xl/worksheets/sheet1.xml",
120
+ text: `${head}<worksheet xmlns="${main}"><sheetData>${sheetRows.join("")}</sheetData></worksheet>`
121
+ }
122
+ ]);
123
+ }
124
+ const LONG_WORD = 20;
125
+ const WORD_CHUNK = 12;
126
+ function printable(value) {
127
+ return String(value).split(/(\s+)/).map((word) => {
128
+ const letters = Array.from(word);
129
+ if (letters.length <= LONG_WORD) return escapeXml(word);
130
+ const chunks = [];
131
+ for (let start = 0; start < letters.length; start += WORD_CHUNK) chunks.push(escapeXml(letters.slice(start, start + WORD_CHUNK).join("")));
132
+ return chunks.join("<wbr>");
133
+ }).join("");
134
+ }
135
+ const PRINT_SIZE = 12;
136
+ const PRINT_FIT_STEPS = [
137
+ {
138
+ size: PRINT_SIZE,
139
+ wrap: false,
140
+ anywhere: false
141
+ },
142
+ {
143
+ size: PRINT_SIZE,
144
+ wrap: true,
145
+ anywhere: false
146
+ },
147
+ {
148
+ size: 11,
149
+ wrap: true,
150
+ anywhere: false
151
+ },
152
+ {
153
+ size: 10,
154
+ wrap: true,
155
+ anywhere: false
156
+ },
157
+ {
158
+ size: 9,
159
+ wrap: true,
160
+ anywhere: false
161
+ },
162
+ {
163
+ size: 8,
164
+ wrap: true,
165
+ anywhere: false
166
+ },
167
+ {
168
+ size: 8,
169
+ wrap: true,
170
+ anywhere: true
171
+ }
172
+ ];
173
+ const round = (value) => Math.round(value * 100) / 100;
174
+ function fitRules(step, scope, columns = []) {
175
+ const scale = step.size / PRINT_SIZE;
176
+ const total = columns.reduce((sum, width) => sum + width, 0);
177
+ return `${scope}{font-size:${step.size}px${step.anywhere && total ? ";table-layout:fixed" : ""}}${scope} th,${scope} td{padding:${round(4 * scale)}px ${round(8 * scale)}px${step.anywhere ? ";overflow-wrap:anywhere" : ""}}` + (step.wrap ? `${scope} td.s{white-space:normal}` : "") + (step.anywhere && total ? `${scope} th{box-sizing:border-box}` + columns.map((width, index) => `${scope} th:nth-child(${index + 1}){width:${Math.floor(width / total * 1e4) / 100}%}`).join("") : "");
178
+ }
179
+ function printFitStyle(widths, columns = []) {
180
+ let narrowest = widths[0] ?? 0;
181
+ let css = "";
182
+ for (let index = 1; index < widths.length && index < PRINT_FIT_STEPS.length; index++) {
183
+ if (widths[index] >= narrowest) continue;
184
+ css += `@container (width < ${narrowest}px){${fitRules(PRINT_FIT_STEPS[index], "table", columns)}}`;
185
+ narrowest = widths[index];
186
+ }
187
+ return css;
188
+ }
189
+ function addPrintStyle(doc, css = "") {
190
+ const Sheet = doc.defaultView?.CSSStyleSheet;
191
+ if (Sheet && "adoptedStyleSheets" in doc && typeof Sheet.prototype.replaceSync === "function") try {
192
+ const sheet = new Sheet();
193
+ sheet.replaceSync(css);
194
+ doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet];
195
+ return {
196
+ set: (text) => sheet.replaceSync(text),
197
+ remove: () => {
198
+ doc.adoptedStyleSheets = doc.adoptedStyleSheets.filter((other) => other !== sheet);
199
+ }
200
+ };
201
+ } catch {}
202
+ const element = doc.createElement("style");
203
+ element.textContent = css;
204
+ doc.head.append(element);
205
+ return {
206
+ set: (text) => {
207
+ element.textContent = text;
208
+ },
209
+ remove: () => element.remove()
210
+ };
211
+ }
212
+ function stylePrintDocument(doc) {
213
+ addPrintStyle(doc, PRINT_STYLE);
214
+ }
215
+ function fitPrintDocument(doc) {
216
+ const table = doc.querySelector("table");
217
+ if (!table) return {
218
+ widths: [],
219
+ columns: []
220
+ };
221
+ const probe = addPrintStyle(doc);
222
+ const lastWhole = PRINT_FIT_STEPS.findIndex((step) => step.anywhere) - 1;
223
+ let columns = [];
224
+ const widths = PRINT_FIT_STEPS.map((step, index) => {
225
+ probe.set(`table{width:1px}${fitRules(step, "table")}`);
226
+ if (index === lastWhole) columns = Array.from(table.querySelectorAll("thead th"), (cell) => Math.ceil(cell.getBoundingClientRect().width));
227
+ return Math.ceil(table.getBoundingClientRect().width);
228
+ });
229
+ probe.remove();
230
+ const css = printFitStyle(widths, columns);
231
+ if (css) addPrintStyle(doc, css);
232
+ return {
233
+ widths,
234
+ columns
235
+ };
236
+ }
237
+ function printColumnAlign(align, values) {
238
+ if (align) return align;
239
+ return values.length > 0 && values.every((value) => typeof value === "number") ? "end" : "start";
240
+ }
241
+ function printContext(host, doc) {
242
+ const find = (name, accept) => {
243
+ for (let node = host; node; node = node.parentElement) {
244
+ const value = node.getAttribute(name)?.trim();
245
+ if (value && accept(value)) return value;
246
+ }
247
+ const root = doc.documentElement.getAttribute(name)?.trim();
248
+ return root && accept(root) ? root : void 0;
249
+ };
250
+ const lang = find("lang", (value) => /^[A-Za-z0-9-]+$/.test(value));
251
+ const dir = find("dir", (value) => /^(ltr|rtl)$/i.test(value))?.toLowerCase();
252
+ return {
253
+ ...lang ? { lang } : {},
254
+ ...dir ? { dir } : {}
255
+ };
256
+ }
257
+ const PRINT_STYLE = `body{font:12px/1.4 system-ui,sans-serif;color:#000;margin:16px}
258
+ h1{font-size:16px;margin:0 0 12px;overflow-wrap:anywhere}
259
+ .fit{container-type:inline-size}
260
+ table{width:100%;border-collapse:collapse}
261
+ th,td{padding:4px 8px;border:1px solid #999;text-align:start;vertical-align:top;overflow-wrap:break-word}
262
+ th{background:#eee}
263
+ th.c,td.c{text-align:center}
264
+ th.e,td.e{text-align:end}
265
+ td.s{white-space:nowrap}
266
+ thead{display:table-header-group}
267
+ tr{break-inside:avoid}`;
268
+ function buildPrintDocument(title, headers, rows, options = {}) {
269
+ const escape = (value) => escapeXml(String(value));
270
+ const alignClass = (align) => align === "end" ? "e" : align === "center" ? "c" : "";
271
+ const cellClass = (value, index) => {
272
+ const text = String(value);
273
+ const column = options.align?.[index];
274
+ const classes = [column ? alignClass(column) : typeof value === "number" ? "e" : "", typeof value !== "number" && text.length <= LONG_WORD && !/\s/.test(text) ? "s" : ""].filter(Boolean);
275
+ return classes.length ? ` class="${classes.join(" ")}"` : "";
276
+ };
277
+ const numberColumn = (index) => rows.length > 0 && rows.every((row) => typeof row[index] === "number");
278
+ const headerClass = (index) => {
279
+ const align = options.align?.[index] ?? (numberColumn(index) ? "end" : "start");
280
+ return alignClass(align) ? ` class="${alignClass(align)}"` : "";
281
+ };
282
+ return `<!doctype html><html${(options.lang ? ` lang="${escapeXml(options.lang)}"` : "") + (options.dir ? ` dir="${options.dir === "rtl" ? "rtl" : "ltr"}"` : "")}><head><meta charset="utf-8"><title>${escape(title)}</title></head><body><h1>${escape(title)}</h1><div class="fit"><table><thead><tr>${headers.map((header, index) => `<th scope="col"${headerClass(index)}>${printable(header)}</th>`).join("")}</tr></thead><tbody>${rows.map((row) => `<tr>${row.map((value, index) => `<td${cellClass(value, index)}>${printable(value)}</td>`).join("")}</tr>`).join("")}</tbody></table></div></body></html>`;
283
+ }
284
+ var HeightTree = class {
285
+ heights;
286
+ sums;
287
+ topBit;
288
+ constructor(heights) {
289
+ const count = heights.length;
290
+ this.heights = new Float64Array(count);
291
+ this.sums = new Float64Array(count + 1);
292
+ for (let i = 0; i < count; i++) {
293
+ const height = Math.max(0, heights[i] || 0);
294
+ this.heights[i] = height;
295
+ this.sums[i + 1] += height;
296
+ const parent = i + 1 + (i + 1 & -(i + 1));
297
+ if (parent <= count) this.sums[parent] += this.sums[i + 1];
298
+ }
299
+ let bit = 1;
300
+ while (bit * 2 <= count) bit *= 2;
301
+ this.topBit = count ? bit : 0;
302
+ }
303
+ get size() {
304
+ return this.heights.length;
305
+ }
306
+ get total() {
307
+ return this.offsetOf(this.size);
308
+ }
309
+ get(index) {
310
+ return this.heights[index] ?? 0;
311
+ }
312
+ set(index, height) {
313
+ const delta = Math.max(0, height) - this.heights[index];
314
+ if (!delta) return 0;
315
+ this.heights[index] += delta;
316
+ for (let i = index + 1; i <= this.size; i += i & -i) this.sums[i] += delta;
317
+ return delta;
318
+ }
319
+ offsetOf(index) {
320
+ let sum = 0;
321
+ for (let i = Math.min(index, this.size); i > 0; i -= i & -i) sum += this.sums[i];
322
+ return sum;
323
+ }
324
+ indexAt(offset) {
325
+ if (!this.size) return -1;
326
+ let index = 0;
327
+ let rest = Math.max(0, offset);
328
+ for (let bit = this.topBit; bit > 0; bit >>= 1) {
329
+ const next = index + bit;
330
+ if (next <= this.size && this.sums[next] <= rest) {
331
+ index = next;
332
+ rest -= this.sums[next];
333
+ }
334
+ }
335
+ return Math.min(index, this.size - 1);
336
+ }
337
+ };
338
+ function variableRange(tree, top, viewport, buffer) {
339
+ const count = tree.size;
340
+ if (!count) return {
341
+ start: 0,
342
+ end: 0,
343
+ first: 0,
344
+ before: 0,
345
+ after: 0
346
+ };
347
+ const from = Math.max(0, top);
348
+ const first = tree.indexAt(from);
349
+ const last = tree.indexAt(from + Math.max(1, viewport) - 1);
350
+ const start = Math.max(0, first - buffer);
351
+ const end = Math.min(count, last + 1 + buffer);
352
+ return {
353
+ start,
354
+ end,
355
+ first,
356
+ before: tree.offsetOf(start),
357
+ after: tree.total - tree.offsetOf(end)
358
+ };
359
+ }
360
+ function anchorShift(changes, anchor) {
361
+ let shift = 0;
362
+ for (const change of changes) if (change.index < anchor) shift += change.to - change.from;
363
+ return shift;
364
+ }
365
+ function anchorOf(tree, top) {
366
+ const index = tree.indexAt(top);
367
+ if (index < 0) return null;
368
+ return {
369
+ index,
370
+ inside: Math.max(0, top) - tree.offsetOf(index)
371
+ };
372
+ }
373
+ function groupKey(label) {
374
+ return `\u0000group\u0000${label}`;
375
+ }
376
+ function buildVirtualLayout(rows, options) {
377
+ const items = [];
378
+ const counts = [];
379
+ let aria = 0;
380
+ let label = null;
381
+ let collapsed = false;
382
+ rows.forEach((row, index) => {
383
+ if (options.groupOf) {
384
+ const group = options.groupOf(row);
385
+ if (index === 0 || group !== label) {
386
+ label = group;
387
+ collapsed = options.isCollapsed(group);
388
+ counts.push(0);
389
+ items.push({
390
+ kind: "group",
391
+ key: groupKey(group),
392
+ label: group,
393
+ count: 0,
394
+ collapsed,
395
+ aria
396
+ });
397
+ aria++;
398
+ }
399
+ counts[counts.length - 1]++;
400
+ if (collapsed) return;
401
+ }
402
+ const expanded = options.isExpanded(row);
403
+ items.push({
404
+ kind: "row",
405
+ key: options.keyOf(row),
406
+ row,
407
+ index,
408
+ expanded,
409
+ aria
410
+ });
411
+ aria += expanded ? 2 : 1;
412
+ });
413
+ let group = 0;
414
+ const indexOfKey = /* @__PURE__ */ new Map();
415
+ const heights = new Float64Array(items.length);
416
+ items.forEach((item, index) => {
417
+ if (item.kind === "group") items[index] = {
418
+ ...item,
419
+ count: counts[group++]
420
+ };
421
+ indexOfKey.set(item.key, index);
422
+ heights[index] = options.heightOf(items[index]);
423
+ });
424
+ return {
425
+ items,
426
+ tree: new HeightTree(heights),
427
+ bodyRows: aria,
428
+ indexOfKey
429
+ };
430
+ }
431
+ function isRange(value) {
432
+ return typeof value === "object" && value !== null && !Array.isArray(value);
433
+ }
434
+ function hasBound(bound) {
435
+ return bound !== null && bound !== void 0 && bound !== "";
436
+ }
437
+ function isActiveFilter(value) {
438
+ if (isRange(value)) return hasBound(value.min) || hasBound(value.max);
439
+ return !!value && value.length > 0;
440
+ }
441
+ function dayKey(value) {
442
+ if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value)) return value.slice(0, 10);
443
+ const date = value instanceof Date ? value : new Date(value);
444
+ if (value === null || value === void 0 || Number.isNaN(date.getTime())) return "";
445
+ const pad = (part) => String(part).padStart(2, "0");
446
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
447
+ }
448
+ const VIRTUAL_BUFFER_ROWS = 5;
449
+ const VIRTUAL_FALLBACK_VIEWPORT = 480;
450
+ const MEASURE_TOLERANCE = .1;
451
+ const FOCUSABLE = "button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], [tabindex]:not([tabindex=\"-1\"])";
452
+ const MIN_COLUMN_WIDTH = 48;
453
+ const MAX_COLUMN_WIDTH_HINT = 2e3;
454
+ var StarCellTemplate = class StarCellTemplate {
455
+ starCell = input.required(...ngDevMode ? [{ debugName: "starCell" }] : /* istanbul ignore next */ []);
456
+ starCellOf = input(null, ...ngDevMode ? [{ debugName: "starCellOf" }] : /* istanbul ignore next */ []);
457
+ template = inject(TemplateRef);
458
+ static ngTemplateContextGuard(_dir, _ctx) {
459
+ return true;
460
+ }
461
+ static ɵfac = i0.ɵɵngDeclareFactory({
462
+ minVersion: "12.0.0",
463
+ version: "22.2.6",
464
+ ngImport: i0,
465
+ type: StarCellTemplate,
466
+ deps: [],
467
+ target: i0.ɵɵFactoryTarget.Directive
468
+ });
469
+ static ɵdir = i0.ɵɵngDeclareDirective({
470
+ minVersion: "17.1.0",
471
+ version: "22.2.6",
472
+ type: StarCellTemplate,
473
+ isStandalone: true,
474
+ selector: "ng-template[starCell]",
475
+ inputs: {
476
+ starCell: {
477
+ classPropertyName: "starCell",
478
+ publicName: "starCell",
479
+ isSignal: true,
480
+ isRequired: true,
481
+ transformFunction: null
482
+ },
483
+ starCellOf: {
484
+ classPropertyName: "starCellOf",
485
+ publicName: "starCellOf",
486
+ isSignal: true,
487
+ isRequired: false,
488
+ transformFunction: null
489
+ }
490
+ },
491
+ ngImport: i0
492
+ });
493
+ };
494
+ i0.ɵɵngDeclareClassMetadata({
495
+ minVersion: "12.0.0",
496
+ version: "22.2.6",
497
+ ngImport: i0,
498
+ type: StarCellTemplate,
499
+ decorators: [{
500
+ type: Directive,
501
+ args: [{ selector: "ng-template[starCell]" }]
502
+ }],
503
+ propDecorators: {
504
+ starCell: [{
505
+ type: i0.Input,
506
+ args: [{
507
+ isSignal: true,
508
+ alias: "starCell",
509
+ required: true
510
+ }]
511
+ }],
512
+ starCellOf: [{
513
+ type: i0.Input,
514
+ args: [{
515
+ isSignal: true,
516
+ alias: "starCellOf",
517
+ required: false
518
+ }]
519
+ }]
520
+ }
521
+ });
522
+ var StarRowExpansionTemplate = class StarRowExpansionTemplate {
523
+ starRowExpansionOf = input(null, ...ngDevMode ? [{ debugName: "starRowExpansionOf" }] : /* istanbul ignore next */ []);
524
+ template = inject(TemplateRef);
525
+ static ngTemplateContextGuard(_dir, _ctx) {
526
+ return true;
527
+ }
528
+ static ɵfac = i0.ɵɵngDeclareFactory({
529
+ minVersion: "12.0.0",
530
+ version: "22.2.6",
531
+ ngImport: i0,
532
+ type: StarRowExpansionTemplate,
533
+ deps: [],
534
+ target: i0.ɵɵFactoryTarget.Directive
535
+ });
536
+ static ɵdir = i0.ɵɵngDeclareDirective({
537
+ minVersion: "17.1.0",
538
+ version: "22.2.6",
539
+ type: StarRowExpansionTemplate,
540
+ isStandalone: true,
541
+ selector: "ng-template[starRowExpansion]",
542
+ inputs: { starRowExpansionOf: {
543
+ classPropertyName: "starRowExpansionOf",
544
+ publicName: "starRowExpansionOf",
545
+ isSignal: true,
546
+ isRequired: false,
547
+ transformFunction: null
548
+ } },
549
+ ngImport: i0
550
+ });
551
+ };
552
+ i0.ɵɵngDeclareClassMetadata({
553
+ minVersion: "12.0.0",
554
+ version: "22.2.6",
555
+ ngImport: i0,
556
+ type: StarRowExpansionTemplate,
557
+ decorators: [{
558
+ type: Directive,
559
+ args: [{ selector: "ng-template[starRowExpansion]" }]
560
+ }],
561
+ propDecorators: { starRowExpansionOf: [{
562
+ type: i0.Input,
563
+ args: [{
564
+ isSignal: true,
565
+ alias: "starRowExpansionOf",
566
+ required: false
567
+ }]
568
+ }] }
569
+ });
570
+ var StarTable = class StarTable {
571
+ text = inject(STAR_UI_TEXT);
572
+ document = inject(DOCUMENT);
573
+ host = inject(ElementRef);
574
+ injector = inject(Injector);
575
+ appRef = inject(ApplicationRef);
576
+ value = input.required(...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
577
+ columns = input.required(...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
578
+ dataKey = input(null, ...ngDevMode ? [{ debugName: "dataKey" }] : /* istanbul ignore next */ []);
579
+ loading = input(false, {
580
+ ...ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {},
581
+ transform: booleanAttribute
582
+ });
583
+ emptyMessage = input(null, ...ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []);
584
+ striped = input(false, {
585
+ ...ngDevMode ? { debugName: "striped" } : /* istanbul ignore next */ {},
586
+ transform: booleanAttribute
587
+ });
588
+ size = input("md", ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
589
+ stickyHeader = input(false, {
590
+ ...ngDevMode ? { debugName: "stickyHeader" } : /* istanbul ignore next */ {},
591
+ transform: booleanAttribute
592
+ });
593
+ scrollHeight = input(null, ...ngDevMode ? [{ debugName: "scrollHeight" }] : /* istanbul ignore next */ []);
594
+ responsiveLayout = input("scroll", ...ngDevMode ? [{ debugName: "responsiveLayout" }] : /* istanbul ignore next */ []);
595
+ virtualScroll = input(false, {
596
+ ...ngDevMode ? { debugName: "virtualScroll" } : /* istanbul ignore next */ {},
597
+ transform: booleanAttribute
598
+ });
599
+ virtualRowHeight = input(48, ...ngDevMode ? [{ debugName: "virtualRowHeight" }] : /* istanbul ignore next */ []);
600
+ virtualRowHeights = input("auto", ...ngDevMode ? [{ debugName: "virtualRowHeights" }] : /* istanbul ignore next */ []);
601
+ ariaLabel = input(null, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
602
+ paginator = input(false, {
603
+ ...ngDevMode ? { debugName: "paginator" } : /* istanbul ignore next */ {},
604
+ transform: booleanAttribute
605
+ });
606
+ first = model(0, ...ngDevMode ? [{ debugName: "first" }] : /* istanbul ignore next */ []);
607
+ rows = model(10, ...ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []);
608
+ rowsPerPageOptions = input([
609
+ 10,
610
+ 25,
611
+ 50
612
+ ], ...ngDevMode ? [{ debugName: "rowsPerPageOptions" }] : /* istanbul ignore next */ []);
613
+ sortField = model(null, ...ngDevMode ? [{ debugName: "sortField" }] : /* istanbul ignore next */ []);
614
+ sortOrder = model(1, ...ngDevMode ? [{ debugName: "sortOrder" }] : /* istanbul ignore next */ []);
615
+ globalFilter = input("", ...ngDevMode ? [{ debugName: "globalFilter" }] : /* istanbul ignore next */ []);
616
+ filters = model({}, ...ngDevMode ? [{ debugName: "filters" }] : /* istanbul ignore next */ []);
617
+ lazy = input(false, {
618
+ ...ngDevMode ? { debugName: "lazy" } : /* istanbul ignore next */ {},
619
+ transform: booleanAttribute
620
+ });
621
+ totalRecords = input(0, ...ngDevMode ? [{ debugName: "totalRecords" }] : /* istanbul ignore next */ []);
622
+ selectionMode = input(null, ...ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []);
623
+ selection = model([], ...ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []);
624
+ expandedKeys = model([], ...ngDevMode ? [{ debugName: "expandedKeys" }] : /* istanbul ignore next */ []);
625
+ rowExpandMode = input("multiple", ...ngDevMode ? [{ debugName: "rowExpandMode" }] : /* istanbul ignore next */ []);
626
+ columnToggle = input(false, {
627
+ ...ngDevMode ? { debugName: "columnToggle" } : /* istanbul ignore next */ {},
628
+ transform: booleanAttribute
629
+ });
630
+ reorderableColumns = input(false, {
631
+ ...ngDevMode ? { debugName: "reorderableColumns" } : /* istanbul ignore next */ {},
632
+ transform: booleanAttribute
633
+ });
634
+ resizableColumns = input(false, {
635
+ ...ngDevMode ? { debugName: "resizableColumns" } : /* istanbul ignore next */ {},
636
+ transform: booleanAttribute
637
+ });
638
+ columnOrder = model([], ...ngDevMode ? [{ debugName: "columnOrder" }] : /* istanbul ignore next */ []);
639
+ hiddenColumns = model([], ...ngDevMode ? [{ debugName: "hiddenColumns" }] : /* istanbul ignore next */ []);
640
+ columnWidths = model({}, ...ngDevMode ? [{ debugName: "columnWidths" }] : /* istanbul ignore next */ []);
641
+ multiSort = input(false, {
642
+ ...ngDevMode ? { debugName: "multiSort" } : /* istanbul ignore next */ {},
643
+ transform: booleanAttribute
644
+ });
645
+ sortMeta = model([], ...ngDevMode ? [{ debugName: "sortMeta" }] : /* istanbul ignore next */ []);
646
+ groupBy = input(null, ...ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []);
647
+ collapsedGroups = model([], ...ngDevMode ? [{ debugName: "collapsedGroups" }] : /* istanbul ignore next */ []);
648
+ reorderableRows = input(false, {
649
+ ...ngDevMode ? { debugName: "reorderableRows" } : /* istanbul ignore next */ {},
650
+ transform: booleanAttribute
651
+ });
652
+ stateKey = input(null, ...ngDevMode ? [{ debugName: "stateKey" }] : /* istanbul ignore next */ []);
653
+ stateStorage = input("local", ...ngDevMode ? [{ debugName: "stateStorage" }] : /* istanbul ignore next */ []);
654
+ rowClick = output();
655
+ rowReorder = output();
656
+ cellEdit = output();
657
+ lazyLoad = output();
658
+ editing = signal(null, ...ngDevMode ? [{ debugName: "editing" }] : /* istanbul ignore next */ []);
659
+ cellTemplates = contentChildren(StarCellTemplate, ...ngDevMode ? [{ debugName: "cellTemplates" }] : /* istanbul ignore next */ []);
660
+ expansion = contentChild(StarRowExpansionTemplate, ...ngDevMode ? [{ debugName: "expansion" }] : /* istanbul ignore next */ []);
661
+ expansionTemplate = computed(() => this.expansion()?.template ?? null, ...ngDevMode ? [{ debugName: "expansionTemplate" }] : /* istanbul ignore next */ []);
662
+ expandable = computed(() => !!this.expansion(), ...ngDevMode ? [{ debugName: "expandable" }] : /* istanbul ignore next */ []);
663
+ radioName = `star-table-${Math.random().toString(36).slice(2)}`;
664
+ clickable = computed(() => this.selectionMode() === "single", ...ngDevMode ? [{ debugName: "clickable" }] : /* istanbul ignore next */ []);
665
+ orderedColumns = computed(() => {
666
+ const order = this.columnOrder();
667
+ const rank = (column, index) => {
668
+ const position = order.indexOf(column.field);
669
+ return (column.frozen ? 0 : 1e6) + (position < 0 ? order.length + index : position);
670
+ };
671
+ return this.columns().map((column, index) => ({
672
+ column,
673
+ rank: rank(column, index)
674
+ })).sort((a, b) => a.rank - b.rank).map(({ column }) => column);
675
+ }, ...ngDevMode ? [{ debugName: "orderedColumns" }] : /* istanbul ignore next */ []);
676
+ visibleColumns = computed(() => {
677
+ const hidden = this.hiddenColumns();
678
+ return this.orderedColumns().filter((column) => !hidden.includes(column.field));
679
+ }, ...ngDevMode ? [{ debugName: "visibleColumns" }] : /* istanbul ignore next */ []);
680
+ dragField = signal(null, ...ngDevMode ? [{ debugName: "dragField" }] : /* istanbul ignore next */ []);
681
+ dropField = signal(null, ...ngDevMode ? [{ debugName: "dropField" }] : /* istanbul ignore next */ []);
682
+ resizing = false;
683
+ hasColumnFilters = computed(() => this.visibleColumns().some((column) => column.filter), ...ngDevMode ? [{ debugName: "hasColumnFilters" }] : /* istanbul ignore next */ []);
684
+ activeFilters = computed(() => {
685
+ const filters = this.filters();
686
+ return this.columns().flatMap((column) => {
687
+ const query = filters[column.field];
688
+ return column.filter && isActiveFilter(query) ? [{
689
+ column,
690
+ query
691
+ }] : [];
692
+ });
693
+ }, ...ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []);
694
+ filtered = computed(() => {
695
+ if (this.lazy()) return this.value();
696
+ const query = this.globalFilter();
697
+ const active = this.activeFilters();
698
+ if (!query && !active.length) return this.value();
699
+ return this.value().filter((row) => (!query || this.columns().some((column) => matchesFilter(this.cellText(row, column), query))) && active.every(({ column, query: value }) => this.matchesColumnFilter(row, column, value)));
700
+ }, ...ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []);
701
+ sorts = computed(() => {
702
+ const meta = this.sortMeta();
703
+ if (this.multiSort() && meta.length) return meta;
704
+ const field = this.sortField();
705
+ return field ? [{
706
+ field,
707
+ order: this.sortOrder()
708
+ }] : [];
709
+ }, ...ngDevMode ? [{ debugName: "sorts" }] : /* istanbul ignore next */ []);
710
+ sorted = computed(() => {
711
+ let rows = this.filtered();
712
+ if (this.lazy()) return rows;
713
+ const sorts = this.sorts().flatMap((sort) => {
714
+ const column = this.columns().find((c) => c.field === sort.field);
715
+ return column ? [{
716
+ column,
717
+ order: sort.order
718
+ }] : [];
719
+ });
720
+ if (sorts.length) rows = [...rows].sort((a, b) => {
721
+ for (const { column, order } of sorts) {
722
+ const result = compareValues(this.cellValue(a, column), this.cellValue(b, column));
723
+ if (result) return order * result;
724
+ }
725
+ return 0;
726
+ });
727
+ if (!this.groupBy()) return rows;
728
+ const rank = /* @__PURE__ */ new Map();
729
+ for (const row of rows) {
730
+ const group = this.groupOf(row);
731
+ if (!rank.has(group)) rank.set(group, rank.size);
732
+ }
733
+ return rows.map((row, index) => ({
734
+ row,
735
+ index,
736
+ rank: rank.get(this.groupOf(row)) ?? 0
737
+ })).sort((a, b) => a.rank - b.rank || a.index - b.index).map(({ row }) => row);
738
+ }, ...ngDevMode ? [{ debugName: "sorted" }] : /* istanbul ignore next */ []);
739
+ groupStarts = computed(() => {
740
+ const starts = /* @__PURE__ */ new Map();
741
+ if (!this.groupBy()) return starts;
742
+ let current = null;
743
+ this.pageRows().forEach((row, index) => {
744
+ const label = this.groupOf(row);
745
+ if (!current || current.label !== label) {
746
+ current = {
747
+ label,
748
+ count: 0
749
+ };
750
+ starts.set(index, current);
751
+ }
752
+ current.count++;
753
+ });
754
+ return starts;
755
+ }, ...ngDevMode ? [{ debugName: "groupStarts" }] : /* istanbul ignore next */ []);
756
+ hasFooter = computed(() => this.visibleColumns().some((column) => column.footer !== void 0), ...ngDevMode ? [{ debugName: "hasFooter" }] : /* istanbul ignore next */ []);
757
+ rowOrderIsOwn = computed(() => !this.lazy() && !this.sorts().length && !this.globalFilter() && !this.activeFilters().length && !this.groupBy(), ...ngDevMode ? [{ debugName: "rowOrderIsOwn" }] : /* istanbul ignore next */ []);
758
+ restoredKey = null;
759
+ total = computed(() => this.lazy() ? this.totalRecords() : this.filtered().length, ...ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []);
760
+ pageRows = computed(() => {
761
+ const rows = this.sorted();
762
+ if (this.lazy() || !this.paginator()) return rows;
763
+ return rows.slice(this.first(), this.first() + this.rows());
764
+ }, ...ngDevMode ? [{ debugName: "pageRows" }] : /* istanbul ignore next */ []);
765
+ scrollTop = signal(0, ...ngDevMode ? [{ debugName: "scrollTop" }] : /* istanbul ignore next */ []);
766
+ viewportHeight = signal(0, ...ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []);
767
+ scroller = viewChild("scroller", ...ngDevMode ? [{ debugName: "scroller" }] : /* istanbul ignore next */ []);
768
+ body = viewChild("body", ...ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []);
769
+ variableHeights = computed(() => this.virtualScroll() && (this.virtualRowHeights() === "variable" || this.expandable() || !!this.groupBy() || this.responsiveLayout() === "stack"), ...ngDevMode ? [{ debugName: "variableHeights" }] : /* istanbul ignore next */ []);
770
+ headerRows = computed(() => this.hasColumnFilters() ? 2 : 1, ...ngDevMode ? [{ debugName: "headerRows" }] : /* istanbul ignore next */ []);
771
+ ariaRowCount = computed(() => {
772
+ if (!this.virtualScroll()) return null;
773
+ const body = this.layout()?.bodyRows ?? this.pageRows().length;
774
+ return this.headerRows() + body + (this.hasFooter() ? 1 : 0);
775
+ }, ...ngDevMode ? [{ debugName: "ariaRowCount" }] : /* istanbul ignore next */ []);
776
+ expandedSet = computed(() => new Set(this.expandedKeys()), ...ngDevMode ? [{ debugName: "expandedSet" }] : /* istanbul ignore next */ []);
777
+ rowHeights = /* @__PURE__ */ new Map();
778
+ expandedHeights = /* @__PURE__ */ new Map();
779
+ measured = signal(0, ...ngDevMode ? [{ debugName: "measured" }] : /* istanbul ignore next */ []);
780
+ heightEpoch = signal(0, ...ngDevMode ? [{ debugName: "heightEpoch" }] : /* istanbul ignore next */ []);
781
+ bodyOffset = signal(0, ...ngDevMode ? [{ debugName: "bodyOffset" }] : /* istanbul ignore next */ []);
782
+ layout = computed(() => {
783
+ if (!this.variableHeights() || this.loading()) return null;
784
+ const rows = this.pageRows();
785
+ const grouped = !!this.groupBy();
786
+ const collapsed = new Set(this.collapsedGroups());
787
+ const expandable = this.expandable();
788
+ const expanded = this.expandedSet();
789
+ const estimate = Math.max(1, this.virtualRowHeight());
790
+ this.heightEpoch();
791
+ return untracked(() => {
792
+ if (this.rowHeights.size + this.expandedHeights.size > 4 * rows.length + 1e3) {
793
+ this.rowHeights.clear();
794
+ this.expandedHeights.clear();
795
+ }
796
+ return buildVirtualLayout(rows, {
797
+ groupOf: grouped ? (row) => this.groupOf(row) : null,
798
+ isCollapsed: (label) => collapsed.has(label),
799
+ isExpanded: (row) => expandable && expanded.has(this.trackKey(row)),
800
+ keyOf: (row) => this.trackKey(row),
801
+ heightOf: (item) => this.estimateOf(item, estimate)
802
+ });
803
+ });
804
+ }, ...ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []);
805
+ estimateOf(item, estimate) {
806
+ if (item.kind === "group") return this.rowHeights.get(item.key) ?? estimate;
807
+ if (!item.expanded) return this.rowHeights.get(item.key) ?? estimate;
808
+ return this.expandedHeights.get(item.key) ?? (this.rowHeights.get(item.key) ?? estimate) + estimate;
809
+ }
810
+ anchorMemo = null;
811
+ pendingScroll = null;
812
+ variableWindow = computed(() => {
813
+ const layout = this.layout();
814
+ if (!layout) return null;
815
+ this.measured();
816
+ const rows = this.pageRows();
817
+ let top = Math.max(0, this.scrollTop() - this.bodyOffset());
818
+ const memo = this.anchorMemo;
819
+ if (memo && memo.layout !== layout && memo.rows === rows && memo.top === top) {
820
+ const anchor = anchorOf(memo.layout.tree, top);
821
+ const key = anchor ? memo.layout.items[anchor.index]?.key : void 0;
822
+ const index = anchor ? layout.indexOfKey.get(key) : void 0;
823
+ if (anchor && index !== void 0) {
824
+ const kept = layout.tree.offsetOf(index) + anchor.inside;
825
+ if (Math.abs(kept - top) > .5) {
826
+ top = kept;
827
+ this.pendingScroll = kept + untracked(this.bodyOffset);
828
+ }
829
+ }
830
+ }
831
+ this.anchorMemo = {
832
+ layout,
833
+ rows,
834
+ top
835
+ };
836
+ const viewport = this.viewportHeight() || VIRTUAL_FALLBACK_VIEWPORT;
837
+ return {
838
+ layout,
839
+ ...variableRange(layout.tree, top, viewport, VIRTUAL_BUFFER_ROWS)
840
+ };
841
+ }, ...ngDevMode ? [{ debugName: "variableWindow" }] : /* istanbul ignore next */ []);
842
+ focusedKey = signal(null, ...ngDevMode ? [{ debugName: "focusedKey" }] : /* istanbul ignore next */ []);
843
+ focusedIndex = computed(() => {
844
+ const focused = this.focusedKey();
845
+ if (!focused || !this.virtualScroll()) return -1;
846
+ const layout = this.layout();
847
+ if (layout) return layout.indexOfKey.get(focused.key) ?? -1;
848
+ return this.pageRows().findIndex((row) => Object.is(this.trackKey(row), focused.key));
849
+ }, ...ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []);
850
+ bodyEntries = computed(() => {
851
+ const rows = this.pageRows();
852
+ if (!this.virtualScroll()) {
853
+ const entries = [];
854
+ const starts = this.groupStarts();
855
+ rows.forEach((row, index) => {
856
+ const group = starts.get(index);
857
+ if (group) entries.push({
858
+ kind: "group",
859
+ key: groupKey(group.label),
860
+ ...group,
861
+ aria: null,
862
+ item: null
863
+ });
864
+ entries.push({
865
+ kind: "row",
866
+ key: this.trackKey(row),
867
+ row,
868
+ index,
869
+ aria: null,
870
+ item: null
871
+ });
872
+ });
873
+ return entries;
874
+ }
875
+ const header = this.headerRows();
876
+ const focused = this.focusedIndex();
877
+ const variable = this.variableWindow();
878
+ if (variable) {
879
+ const { layout } = variable;
880
+ return this.windowEntries(variable, focused, layout.tree.total, (i) => layout.tree.offsetOf(i), (i) => {
881
+ const item = layout.items[i];
882
+ const aria = header + item.aria + 1;
883
+ return item.kind === "group" ? {
884
+ kind: "group",
885
+ key: item.key,
886
+ label: item.label,
887
+ count: item.count,
888
+ aria,
889
+ item: i
890
+ } : {
891
+ kind: "row",
892
+ key: item.key,
893
+ row: item.row,
894
+ index: item.index,
895
+ aria,
896
+ item: i
897
+ };
898
+ });
899
+ }
900
+ const height = Math.max(1, this.virtualRowHeight());
901
+ const window = this.virtualWindow();
902
+ return this.windowEntries(window, focused, rows.length * height, (i) => i * height, (i) => ({
903
+ kind: "row",
904
+ key: this.trackKey(rows[i]),
905
+ row: rows[i],
906
+ index: i,
907
+ aria: header + i + 1,
908
+ item: i
909
+ }));
910
+ }, ...ngDevMode ? [{ debugName: "bodyEntries" }] : /* istanbul ignore next */ []);
911
+ windowEntries(window, focused, total, offsetOf, entryAt) {
912
+ const indexes = [];
913
+ if (focused >= 0 && focused < window.start) indexes.push(focused);
914
+ for (let i = window.start; i < window.end; i++) indexes.push(i);
915
+ if (focused >= window.end) indexes.push(focused);
916
+ const entries = [];
917
+ let cursor = 0;
918
+ let spacers = 0;
919
+ const spacer = (height) => {
920
+ if (height > .01) entries.push({
921
+ kind: "spacer",
922
+ key: `\u0000spacer${spacers++}`,
923
+ height
924
+ });
925
+ };
926
+ for (const index of indexes) {
927
+ spacer(offsetOf(index) - offsetOf(cursor));
928
+ entries.push(entryAt(index));
929
+ cursor = index + 1;
930
+ }
931
+ if (indexes.length) spacer(total - offsetOf(cursor));
932
+ return entries;
933
+ }
934
+ virtualWindow = computed(() => {
935
+ const count = this.pageRows().length;
936
+ if (!this.virtualScroll() || this.loading() || this.variableHeights()) return {
937
+ start: 0,
938
+ end: count,
939
+ before: 0,
940
+ after: 0
941
+ };
942
+ const height = Math.max(1, this.virtualRowHeight());
943
+ const viewport = this.viewportHeight() || VIRTUAL_FALLBACK_VIEWPORT;
944
+ const visible = Math.ceil(viewport / height);
945
+ const first = Math.min(Math.floor(this.scrollTop() / height), Math.max(0, count - visible));
946
+ const start = Math.max(0, first - VIRTUAL_BUFFER_ROWS);
947
+ const end = Math.min(count, first + visible + VIRTUAL_BUFFER_ROWS);
948
+ return {
949
+ start,
950
+ end,
951
+ before: start * height,
952
+ after: (count - end) * height
953
+ };
954
+ }, ...ngDevMode ? [{ debugName: "virtualWindow" }] : /* istanbul ignore next */ []);
955
+ onScroll(event) {
956
+ if (!this.virtualScroll()) return;
957
+ const viewport = event.target;
958
+ this.scrollTop.set(viewport.scrollTop);
959
+ this.viewportHeight.set(viewport.clientHeight);
960
+ }
961
+ observedRows = /* @__PURE__ */ new Set();
962
+ rowObserver = null;
963
+ measureRendered() {
964
+ const layout = untracked(this.layout);
965
+ const scroller = this.scroller()?.nativeElement;
966
+ const body = this.body()?.nativeElement;
967
+ if (!layout || !scroller || !body || !scroller.isConnected || !scroller.clientHeight) return;
968
+ if (this.pendingScroll !== null) {
969
+ scroller.scrollTop = this.pendingScroll;
970
+ this.pendingScroll = null;
971
+ }
972
+ const area = scroller.getBoundingClientRect();
973
+ const offset = body.getBoundingClientRect().top - area.top - scroller.clientTop + scroller.scrollTop;
974
+ const heights = /* @__PURE__ */ new Map();
975
+ for (const row of Array.from(body.children)) {
976
+ const item = row.dataset["vi"];
977
+ if (item === void 0) continue;
978
+ heights.set(Number(item), (heights.get(Number(item)) ?? 0) + row.getBoundingClientRect().height);
979
+ }
980
+ const { tree, items } = layout;
981
+ const anchor = tree.indexAt(scroller.scrollTop - offset);
982
+ const changes = [];
983
+ for (const [index, height] of heights) {
984
+ const item = items[index];
985
+ if (!item || height <= 0) continue;
986
+ const from = tree.get(index);
987
+ if (Math.abs(height - from) < MEASURE_TOLERANCE) continue;
988
+ tree.set(index, height);
989
+ changes.push({
990
+ index,
991
+ from,
992
+ to: height
993
+ });
994
+ (item.kind === "row" && item.expanded ? this.expandedHeights : this.rowHeights).set(item.key, height);
995
+ }
996
+ const shift = anchorShift(changes, anchor);
997
+ if (Math.abs(shift) >= .5) scroller.scrollTop += shift;
998
+ this.bodyOffset.set(offset);
999
+ this.viewportHeight.set(scroller.clientHeight);
1000
+ this.scrollTop.set(scroller.scrollTop);
1001
+ if (changes.length) this.measured.update((count) => count + 1);
1002
+ this.observeRows(body);
1003
+ }
1004
+ observeRows(body) {
1005
+ if (typeof ResizeObserver === "undefined") return;
1006
+ this.rowObserver ??= new ResizeObserver(() => this.measureRendered());
1007
+ const rows = /* @__PURE__ */ new Set([body, ...Array.from(body.querySelectorAll(":scope > tr[data-vi]"))]);
1008
+ for (const row of this.observedRows) if (!rows.has(row)) {
1009
+ this.rowObserver.unobserve(row);
1010
+ this.observedRows.delete(row);
1011
+ }
1012
+ for (const row of rows) if (!this.observedRows.has(row)) {
1013
+ this.rowObserver.observe(row);
1014
+ this.observedRows.add(row);
1015
+ }
1016
+ }
1017
+ itemOf(element) {
1018
+ const row = element?.closest("tr[data-vi]");
1019
+ return row && this.body()?.nativeElement.contains(row) ? Number(row.dataset["vi"]) : -1;
1020
+ }
1021
+ keyOfItem(index) {
1022
+ const layout = this.layout();
1023
+ if (layout) return layout.items[index]?.key;
1024
+ const row = this.pageRows()[index];
1025
+ return row === void 0 ? void 0 : this.trackKey(row);
1026
+ }
1027
+ onBodyFocusIn(event) {
1028
+ if (!this.virtualScroll()) return;
1029
+ const index = this.itemOf(event.target);
1030
+ if (index < 0) return;
1031
+ const key = this.keyOfItem(index);
1032
+ if (!Object.is(this.focusedKey()?.key, key)) this.focusedKey.set({ key });
1033
+ const scroller = this.scroller()?.nativeElement;
1034
+ if (scroller) {
1035
+ this.scrollTop.set(scroller.scrollTop);
1036
+ if (scroller.clientHeight) this.viewportHeight.set(scroller.clientHeight);
1037
+ }
1038
+ }
1039
+ onBodyFocusOut(event) {
1040
+ if (!this.virtualScroll()) return;
1041
+ const body = this.body()?.nativeElement;
1042
+ const next = event.relatedTarget;
1043
+ if (!body || next && body.contains(next)) return;
1044
+ setTimeout(() => {
1045
+ if (!body.contains(this.document.activeElement)) this.focusedKey.set(null);
1046
+ });
1047
+ }
1048
+ onBodyKeydown(event) {
1049
+ if (event.key !== "Tab" || !this.virtualScroll() || event.defaultPrevented) return;
1050
+ const body = this.body()?.nativeElement;
1051
+ const index = this.itemOf(event.target);
1052
+ if (!body || index < 0) return;
1053
+ const step = event.shiftKey ? -1 : 1;
1054
+ const target = index + step;
1055
+ const count = this.layout()?.items.length ?? this.pageRows().length;
1056
+ if (target < 0 || target >= count || body.querySelector(`:scope > tr[data-vi="${target}"]`)) return;
1057
+ const own = this.focusablesOf(body, index);
1058
+ const position = own.indexOf(event.target);
1059
+ if (position < 0 || (step === 1 ? position < own.length - 1 : position > 0)) return;
1060
+ event.preventDefault();
1061
+ this.revealItem(target);
1062
+ afterNextRender(() => {
1063
+ for (let i = target; i >= 0 && i < count; i += step) {
1064
+ const controls = this.focusablesOf(body, i);
1065
+ if (!body.querySelector(`:scope > tr[data-vi="${i}"]`)) break;
1066
+ if (controls.length) {
1067
+ (step === 1 ? controls[0] : controls[controls.length - 1]).focus();
1068
+ return;
1069
+ }
1070
+ }
1071
+ }, { injector: this.injector });
1072
+ this.appRef.tick();
1073
+ }
1074
+ focusablesOf(body, index) {
1075
+ return Array.from(body.querySelectorAll(`:scope > tr[data-vi="${index}"]`)).flatMap((row) => Array.from(row.querySelectorAll(FOCUSABLE)));
1076
+ }
1077
+ revealItem(index) {
1078
+ const scroller = this.scroller()?.nativeElement;
1079
+ if (!scroller) return;
1080
+ const layout = this.layout();
1081
+ const offset = layout ? layout.tree.offsetOf(index) : index * Math.max(1, this.virtualRowHeight());
1082
+ scroller.scrollTop = Math.max(0, this.bodyOffset() + offset - scroller.clientHeight / 2);
1083
+ this.scrollTop.set(scroller.scrollTop);
1084
+ if (scroller.clientHeight) this.viewportHeight.set(scroller.clientHeight);
1085
+ }
1086
+ skeletonRows = computed(() => Array.from({ length: Math.min(this.rows(), 8) }, (_, i) => i), ...ngDevMode ? [{ debugName: "skeletonRows" }] : /* istanbul ignore next */ []);
1087
+ colspan = computed(() => this.visibleColumns().length + (this.selectionMode() ? 1 : 0) + (this.expandable() ? 1 : 0) + (this.reorderableRows() ? 1 : 0), ...ngDevMode ? [{ debugName: "colspan" }] : /* istanbul ignore next */ []);
1088
+ pageState = computed(() => {
1089
+ const rows = this.pageRows();
1090
+ const count = rows.filter((row) => this.isSelected(row)).length;
1091
+ if (!rows.length || count === 0) return false;
1092
+ return count === rows.length ? true : "mixed";
1093
+ }, ...ngDevMode ? [{ debugName: "pageState" }] : /* istanbul ignore next */ []);
1094
+ constructor() {
1095
+ effect(() => {
1096
+ this.globalFilter();
1097
+ this.filters();
1098
+ untracked(() => {
1099
+ this.first.set(0);
1100
+ this.emitLazy();
1101
+ });
1102
+ });
1103
+ afterRenderEffect({ read: () => this.measureFrozen() });
1104
+ afterRenderEffect(() => {
1105
+ this.bodyEntries();
1106
+ this.expandedKeys();
1107
+ if (this.variableHeights()) untracked(() => this.measureRendered());
1108
+ });
1109
+ const destroyRef = inject(DestroyRef);
1110
+ if (typeof ResizeObserver !== "undefined") {
1111
+ let width = null;
1112
+ const observer = new ResizeObserver((entries) => {
1113
+ this.resized.update((count) => count + 1);
1114
+ const next = Math.round(entries[entries.length - 1].contentRect.width);
1115
+ if (width !== null && next !== width && untracked(this.variableHeights)) {
1116
+ this.rowHeights.clear();
1117
+ this.expandedHeights.clear();
1118
+ this.heightEpoch.update((count) => count + 1);
1119
+ }
1120
+ width = next;
1121
+ });
1122
+ observer.observe(this.host.nativeElement);
1123
+ destroyRef.onDestroy(() => observer.disconnect());
1124
+ }
1125
+ destroyRef.onDestroy(() => this.rowObserver?.disconnect());
1126
+ if (isDevMode()) effect(() => {
1127
+ if (this.virtualScroll() && !this.scrollHeight()) console.warn("star-table: virtualScroll needs scrollHeight. Without it the table does not scroll inside its own area, and rows after the first window are not rendered.");
1128
+ if (this.virtualRowHeights() === "variable" && !this.virtualScroll()) console.warn("star-table: virtualRowHeights has no effect without virtualScroll.");
1129
+ });
1130
+ effect(() => {
1131
+ const key = this.stateKey();
1132
+ if (!key) return;
1133
+ if (this.restoredKey !== key) {
1134
+ this.restoredKey = key;
1135
+ untracked(() => this.restoreState(key));
1136
+ }
1137
+ const state = {
1138
+ sortField: this.sortField(),
1139
+ sortOrder: this.sortOrder(),
1140
+ sortMeta: this.sortMeta(),
1141
+ filters: this.filters(),
1142
+ columnOrder: this.columnOrder(),
1143
+ hiddenColumns: this.hiddenColumns(),
1144
+ columnWidths: this.columnWidths(),
1145
+ rows: this.rows(),
1146
+ collapsedGroups: this.collapsedGroups()
1147
+ };
1148
+ try {
1149
+ this.storage()?.setItem(key, JSON.stringify(state));
1150
+ } catch {}
1151
+ });
1152
+ }
1153
+ storage() {
1154
+ const view = this.document.defaultView;
1155
+ try {
1156
+ return (this.stateStorage() === "session" ? view?.sessionStorage : view?.localStorage) ?? null;
1157
+ } catch {
1158
+ return null;
1159
+ }
1160
+ }
1161
+ restoreState(key) {
1162
+ let state;
1163
+ try {
1164
+ state = JSON.parse(this.storage()?.getItem(key) ?? "null");
1165
+ } catch {
1166
+ return;
1167
+ }
1168
+ if (!state || typeof state !== "object") return;
1169
+ if (state.sortField !== void 0) this.sortField.set(state.sortField);
1170
+ if (state.sortOrder === 1 || state.sortOrder === -1) this.sortOrder.set(state.sortOrder);
1171
+ if (Array.isArray(state.sortMeta)) this.sortMeta.set(state.sortMeta);
1172
+ if (state.filters && typeof state.filters === "object") this.filters.set(state.filters);
1173
+ if (Array.isArray(state.columnOrder)) this.columnOrder.set(state.columnOrder);
1174
+ if (Array.isArray(state.hiddenColumns)) this.hiddenColumns.set(state.hiddenColumns);
1175
+ if (state.columnWidths && typeof state.columnWidths === "object") this.columnWidths.set(state.columnWidths);
1176
+ if (typeof state.rows === "number" && state.rows > 0) this.rows.set(state.rows);
1177
+ if (Array.isArray(state.collapsedGroups)) this.collapsedGroups.set(state.collapsedGroups);
1178
+ }
1179
+ clearState() {
1180
+ const key = this.stateKey();
1181
+ if (key) this.storage()?.removeItem(key);
1182
+ }
1183
+ groupOf(row) {
1184
+ const key = this.groupBy();
1185
+ const group = key ? readOption(row, key) : null;
1186
+ return group === null || group === void 0 ? "" : String(group);
1187
+ }
1188
+ isGroupCollapsed(label) {
1189
+ return this.collapsedGroups().includes(label);
1190
+ }
1191
+ isRowCollapsed(row) {
1192
+ return !!this.groupBy() && this.isGroupCollapsed(this.groupOf(row));
1193
+ }
1194
+ toggleGroup(label) {
1195
+ this.collapsedGroups.update((groups) => groups.includes(label) ? groups.filter((group) => group !== label) : [...groups, label]);
1196
+ }
1197
+ footerText(column) {
1198
+ const footer = column.footer;
1199
+ if (footer === void 0) return "";
1200
+ return typeof footer === "function" ? footer(this.sorted()) : footer;
1201
+ }
1202
+ canMoveRow(row, step) {
1203
+ if (!this.rowOrderIsOwn()) return false;
1204
+ const to = this.value().indexOf(row) + step;
1205
+ return to >= 0 && to < this.value().length;
1206
+ }
1207
+ moveRow(row, step) {
1208
+ if (!this.canMoveRow(row, step)) return;
1209
+ const from = this.value().indexOf(row);
1210
+ this.rowReorder.emit({
1211
+ row,
1212
+ from,
1213
+ to: from + step
1214
+ });
1215
+ }
1216
+ trackKey(row) {
1217
+ return readOption(row, this.dataKey());
1218
+ }
1219
+ cellTemplate(field) {
1220
+ return this.cellTemplates().find((t) => t.starCell() === field)?.template ?? null;
1221
+ }
1222
+ cellValue(row, column) {
1223
+ return column.value ? column.value(row) : row?.[column.field];
1224
+ }
1225
+ cellText(row, column) {
1226
+ if (column.format) return column.format(row);
1227
+ const value = this.cellValue(row, column);
1228
+ return value === null || value === void 0 ? "" : String(value);
1229
+ }
1230
+ isHidden(column) {
1231
+ return this.hiddenColumns().includes(column.field);
1232
+ }
1233
+ canHide(column) {
1234
+ if (column.hideable === false) return false;
1235
+ return this.isHidden(column) || this.visibleColumns().length > 1;
1236
+ }
1237
+ setColumnVisible(column, visible) {
1238
+ this.hiddenColumns.update((hidden) => visible ? hidden.filter((field) => field !== column.field) : [...hidden, column.field]);
1239
+ }
1240
+ moveColumn(field, targetField) {
1241
+ const fields = this.orderedColumns().map((column) => column.field);
1242
+ const from = fields.indexOf(field);
1243
+ const to = fields.indexOf(targetField);
1244
+ if (from < 0 || to < 0 || from === to) return;
1245
+ fields.splice(to, 0, ...fields.splice(from, 1));
1246
+ this.columnOrder.set(fields);
1247
+ }
1248
+ moveColumnBy(column, delta) {
1249
+ const fields = this.orderedColumns().map((item) => item.field);
1250
+ const target = fields[fields.indexOf(column.field) + delta];
1251
+ if (!target) return;
1252
+ this.moveColumn(column.field, target);
1253
+ this.focusMoveButton(column, delta);
1254
+ }
1255
+ moveKey(column, delta) {
1256
+ return `${this.radioName}|${column.field}|${delta}`;
1257
+ }
1258
+ focusMoveButton(column, delta) {
1259
+ afterNextRender(() => {
1260
+ const button = (step) => this.document.querySelector(`[data-move="${CSS.escape(this.moveKey(column, step))}"]`);
1261
+ const same = button(delta);
1262
+ (same && !same.disabled ? same : button(delta === 1 ? -1 : 1))?.focus();
1263
+ }, { injector: this.injector });
1264
+ }
1265
+ onDragStart(column, event) {
1266
+ if (this.resizing || !this.reorderableColumns()) {
1267
+ event.preventDefault();
1268
+ return;
1269
+ }
1270
+ this.dragField.set(column.field);
1271
+ event.dataTransfer?.setData("text/plain", column.field);
1272
+ if (event.dataTransfer) event.dataTransfer.effectAllowed = "move";
1273
+ }
1274
+ onDragOver(column, event) {
1275
+ const field = this.dragField();
1276
+ if (!field || field === column.field) return;
1277
+ event.preventDefault();
1278
+ this.dropField.set(column.field);
1279
+ }
1280
+ onDrop(column, event) {
1281
+ const field = this.dragField();
1282
+ if (!field) return;
1283
+ event.preventDefault();
1284
+ this.moveColumn(field, column.field);
1285
+ this.endDrag();
1286
+ }
1287
+ endDrag() {
1288
+ this.dragField.set(null);
1289
+ this.dropField.set(null);
1290
+ }
1291
+ widthOf(column) {
1292
+ return this.resizedWidth(column) ?? column.width ?? null;
1293
+ }
1294
+ resizedWidth(column) {
1295
+ const width = this.columnWidths()[column.field];
1296
+ return width ? `${width}px` : null;
1297
+ }
1298
+ frozenWidths = signal({}, ...ngDevMode ? [{ debugName: "frozenWidths" }] : /* istanbul ignore next */ []);
1299
+ headerWidths = signal({}, ...ngDevMode ? [{ debugName: "headerWidths" }] : /* istanbul ignore next */ []);
1300
+ scrollable = signal(false, ...ngDevMode ? [{ debugName: "scrollable" }] : /* istanbul ignore next */ []);
1301
+ minColumnWidth = MIN_COLUMN_WIDTH;
1302
+ resizeNow(column) {
1303
+ const width = this.columnWidths()[column.field] ?? this.headerWidths()[column.field];
1304
+ return width === void 0 ? null : Math.round(width);
1305
+ }
1306
+ resizeMax(column) {
1307
+ return Math.max(MAX_COLUMN_WIDTH_HINT, this.resizeNow(column) ?? 0);
1308
+ }
1309
+ resized = signal(0, ...ngDevMode ? [{ debugName: "resized" }] : /* istanbul ignore next */ []);
1310
+ measureFrozen() {
1311
+ const frozen = this.visibleColumns().filter((column) => column.frozen);
1312
+ this.columnWidths();
1313
+ this.value();
1314
+ this.size();
1315
+ this.resized();
1316
+ const scroller = this.scroller()?.nativeElement;
1317
+ if (scroller) this.scrollable.set(scroller.scrollWidth > scroller.clientWidth + 1 || scroller.scrollHeight > scroller.clientHeight + 1);
1318
+ const resizable = this.resizableColumns();
1319
+ if (!frozen.length && !resizable) return;
1320
+ const widths = {};
1321
+ const all = {};
1322
+ for (const cell of this.host.nativeElement.querySelectorAll("thead th[data-field]")) {
1323
+ const field = cell.dataset["field"];
1324
+ if (!field) continue;
1325
+ const width = cell.getBoundingClientRect().width;
1326
+ all[field] = width;
1327
+ if (frozen.some((column) => column.field === field)) widths[field] = width;
1328
+ }
1329
+ const sameWidths = (next, current) => Object.keys(next).length === Object.keys(current).length && Object.entries(next).every(([field, width]) => Math.abs((current[field] ?? -1) - width) < .5);
1330
+ if (!sameWidths(widths, untracked(this.frozenWidths))) this.frozenWidths.set(widths);
1331
+ if (resizable && !sameWidths(all, untracked(this.headerWidths))) this.headerWidths.set(all);
1332
+ }
1333
+ frozenOffset(column) {
1334
+ if (!column.frozen) return null;
1335
+ const measured = this.frozenWidths();
1336
+ const before = [];
1337
+ let pixels = 0;
1338
+ let allMeasured = true;
1339
+ for (const item of this.visibleColumns()) {
1340
+ if (item === column) break;
1341
+ if (!item.frozen) continue;
1342
+ before.push(this.widthOf(item) ?? "0px");
1343
+ const width = measured[item.field];
1344
+ if (width) pixels += width;
1345
+ else allMeasured = false;
1346
+ }
1347
+ if (!before.length) return "0px";
1348
+ return allMeasured ? `${Math.round(pixels * 100) / 100}px` : `calc(${before.join(" + ")})`;
1349
+ }
1350
+ setWidth(column, width) {
1351
+ const next = Math.max(MIN_COLUMN_WIDTH, Math.round(width));
1352
+ this.columnWidths.update((widths) => ({
1353
+ ...widths,
1354
+ [column.field]: next
1355
+ }));
1356
+ }
1357
+ startResize(column, event) {
1358
+ const handle = event.currentTarget;
1359
+ const header = handle.closest("th");
1360
+ if (!header) return;
1361
+ event.preventDefault();
1362
+ event.stopPropagation();
1363
+ this.resizing = true;
1364
+ const direction = starIsRtl(header) ? -1 : 1;
1365
+ const startWidth = header.offsetWidth;
1366
+ const startX = event.clientX;
1367
+ handle.setPointerCapture?.(event.pointerId);
1368
+ const move = (moveEvent) => this.setWidth(column, startWidth + direction * (moveEvent.clientX - startX));
1369
+ const stop = () => {
1370
+ this.resizing = false;
1371
+ handle.removeEventListener("pointermove", move);
1372
+ handle.removeEventListener("pointerup", stop);
1373
+ handle.removeEventListener("pointercancel", stop);
1374
+ };
1375
+ handle.addEventListener("pointermove", move);
1376
+ handle.addEventListener("pointerup", stop);
1377
+ handle.addEventListener("pointercancel", stop);
1378
+ }
1379
+ onResizeKey(column, event) {
1380
+ const step = event.key === "ArrowRight" ? 16 : event.key === "ArrowLeft" ? -16 : 0;
1381
+ if (!step) return;
1382
+ event.preventDefault();
1383
+ const header = event.currentTarget.closest("th");
1384
+ const direction = starIsRtl(header) ? -1 : 1;
1385
+ this.setWidth(column, (this.columnWidths()[column.field] ?? header?.offsetWidth ?? 0) + direction * step);
1386
+ }
1387
+ editKey(row, column) {
1388
+ return `${String(this.trackKey(row))}|${column.field}`;
1389
+ }
1390
+ isEditable(row, column) {
1391
+ return typeof column.editable === "function" ? column.editable(row) : !!column.editable;
1392
+ }
1393
+ isEditing(row, column) {
1394
+ return this.editing() === this.editKey(row, column);
1395
+ }
1396
+ editText(row, column) {
1397
+ const value = this.cellValue(row, column);
1398
+ return value === null || value === void 0 ? "" : String(value);
1399
+ }
1400
+ startEdit(row, column) {
1401
+ this.editing.set(this.editKey(row, column));
1402
+ this.focusAfterRender(".star-table__editor", true);
1403
+ }
1404
+ commitEdit(row, column, text) {
1405
+ if (!this.isEditing(row, column)) return;
1406
+ const previous = this.cellValue(row, column);
1407
+ const value = column.editor === "number" ? text.trim() === "" ? null : Number(text) : text;
1408
+ this.closeEditor(row, column);
1409
+ if (typeof value === "number" && Number.isNaN(value)) return;
1410
+ if (Object.is(value, previous) || value === "" && (previous ?? "") === "") return;
1411
+ this.cellEdit.emit({
1412
+ row,
1413
+ field: column.field,
1414
+ value,
1415
+ previous
1416
+ });
1417
+ }
1418
+ cancelEdit(event) {
1419
+ event.stopPropagation();
1420
+ const key = this.editing();
1421
+ this.editing.set(null);
1422
+ if (key) this.focusAfterRender(`[data-edit="${CSS.escape(key)}"]`);
1423
+ }
1424
+ closeEditor(row, column) {
1425
+ const key = this.editKey(row, column);
1426
+ this.editing.set(null);
1427
+ this.focusAfterRender(`[data-edit="${CSS.escape(key)}"]`);
1428
+ }
1429
+ focusAfterRender(selector, select = false) {
1430
+ afterNextRender(() => {
1431
+ const target = this.host.nativeElement.querySelector(selector);
1432
+ target?.focus();
1433
+ if (select && target instanceof HTMLInputElement && target.type === "text") target.select();
1434
+ }, { injector: this.injector });
1435
+ }
1436
+ isExpanded(row) {
1437
+ return this.expandedSet().has(this.trackKey(row));
1438
+ }
1439
+ detailId(index) {
1440
+ return `${this.radioName}-detail-${index}`;
1441
+ }
1442
+ toggleExpansion(row) {
1443
+ const key = this.trackKey(row);
1444
+ if (this.isExpanded(row)) this.expandedKeys.update((keys) => keys.filter((expanded) => !Object.is(expanded, key)));
1445
+ else this.expandedKeys.update((keys) => this.rowExpandMode() === "single" ? [key] : [...keys, key]);
1446
+ }
1447
+ expandAll() {
1448
+ this.expandedKeys.set(this.pageRows().map((row) => this.trackKey(row)));
1449
+ }
1450
+ collapseAll() {
1451
+ this.expandedKeys.set([]);
1452
+ }
1453
+ matchesColumnFilter(row, column, value) {
1454
+ if (isRange(value)) {
1455
+ const raw = this.cellValue(row, column);
1456
+ if (column.filter === "date") {
1457
+ const day = dayKey(raw);
1458
+ return !!day && (!hasBound(value.min) || day >= String(value.min)) && (!hasBound(value.max) || day <= String(value.max));
1459
+ }
1460
+ const amount = raw === null || raw === void 0 || raw === "" ? NaN : Number(raw);
1461
+ return !Number.isNaN(amount) && (!hasBound(value.min) || amount >= Number(value.min)) && (!hasBound(value.max) || amount <= Number(value.max));
1462
+ }
1463
+ const text = this.cellText(row, column);
1464
+ if (typeof value !== "string") return value.includes(text);
1465
+ return column.filter === "select" ? text === value : matchesFilter(text, value);
1466
+ }
1467
+ filterValue(field) {
1468
+ const value = this.filters()[field];
1469
+ return typeof value === "string" ? value : "";
1470
+ }
1471
+ filterList(field) {
1472
+ const value = this.filters()[field];
1473
+ return Array.isArray(value) ? value : [];
1474
+ }
1475
+ filterBound(field, bound) {
1476
+ const value = this.filters()[field];
1477
+ const side = isRange(value) ? value[bound] : null;
1478
+ return hasBound(side) ? String(side) : "";
1479
+ }
1480
+ setBound(column, bound, text) {
1481
+ const current = this.filters()[column.field];
1482
+ const side = text === "" ? null : column.filter === "number" ? Number(text) : text;
1483
+ this.setFilter(column.field, {
1484
+ ...isRange(current) ? current : {},
1485
+ [bound]: side
1486
+ });
1487
+ }
1488
+ filterChoices(column) {
1489
+ if (column.filterOptions) return column.filterOptions;
1490
+ const texts = new Set(this.value().map((row) => this.cellText(row, column)));
1491
+ texts.delete("");
1492
+ return [...texts].sort((a, b) => compareValues(a, b));
1493
+ }
1494
+ setFilter(field, value) {
1495
+ this.filters.update((filters) => ({
1496
+ ...filters,
1497
+ [field]: value
1498
+ }));
1499
+ }
1500
+ clearFilters() {
1501
+ this.filters.set({});
1502
+ }
1503
+ exportData(options) {
1504
+ return {
1505
+ columns: this.visibleColumns().filter((column) => column.exportable !== false),
1506
+ rows: options.rows ?? (options.selectionOnly ? this.selection() : this.sorted())
1507
+ };
1508
+ }
1509
+ exportText(row, column) {
1510
+ return column.exportValue ? String(column.exportValue(row) ?? "") : this.cellText(row, column);
1511
+ }
1512
+ exportCell(row, column) {
1513
+ const custom = column.exportValue?.(row);
1514
+ if (typeof custom === "number") return custom;
1515
+ const value = this.cellValue(row, column);
1516
+ return !column.exportValue && !column.format && typeof value === "number" ? value : this.exportText(row, column);
1517
+ }
1518
+ toCsv(options = {}) {
1519
+ const separator = options.separator ?? ",";
1520
+ const { columns, rows } = this.exportData(options);
1521
+ const escape = (text) => text.includes(separator) || /["\r\n]/.test(text) ? `"${text.replaceAll("\"", "\"\"")}"` : text;
1522
+ const cell = (row, column) => {
1523
+ const value = this.exportCell(row, column);
1524
+ const text = String(value);
1525
+ return escape(typeof value !== "number" && /^[=+\-@\t\r]/.test(text) ? `'${text}` : text);
1526
+ };
1527
+ return [columns.map((column) => escape(column.header)).join(separator), ...rows.map((row) => columns.map((column) => cell(row, column)).join(separator))].join("\r\n");
1528
+ }
1529
+ exportCsv(options = {}) {
1530
+ this.download(new Blob(["", this.toCsv(options)], { type: "text/csv;charset=utf-8" }), `${options.fileName ?? "export"}.csv`);
1531
+ }
1532
+ toXlsx(options = {}) {
1533
+ const { columns, rows } = this.exportData(options);
1534
+ return buildXlsx(columns.map((column) => column.header), rows.map((row) => columns.map((column) => this.exportCell(row, column))), options.title ?? this.ariaLabel() ?? void 0);
1535
+ }
1536
+ exportExcel(options = {}) {
1537
+ const bytes = this.toXlsx(options);
1538
+ this.download(new Blob([bytes.buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }), `${options.fileName ?? "export"}.xlsx`);
1539
+ }
1540
+ print(options = {}) {
1541
+ const { columns, rows } = this.exportData(options);
1542
+ const frame = this.document.createElement("iframe");
1543
+ frame.setAttribute("aria-hidden", "true");
1544
+ frame.style.cssText = "position:fixed;width:0;height:0;border:0;visibility:hidden";
1545
+ frame.srcdoc = buildPrintDocument(options.title ?? this.ariaLabel() ?? "", columns.map((column) => column.header), rows.map((row) => columns.map((column) => this.exportCell(row, column))), {
1546
+ align: columns.map((column) => printColumnAlign(column.align, rows.map((row) => {
1547
+ const cell = this.exportCell(row, column);
1548
+ return typeof cell === "number" ? cell : this.cellValue(row, column);
1549
+ }))),
1550
+ ...printContext(this.host.nativeElement, this.document)
1551
+ });
1552
+ frame.addEventListener("load", () => {
1553
+ const view = frame.contentWindow;
1554
+ if (!view) return;
1555
+ stylePrintDocument(view.document);
1556
+ fitPrintDocument(view.document);
1557
+ view.addEventListener("afterprint", () => frame.remove());
1558
+ view.focus();
1559
+ view.print();
1560
+ });
1561
+ this.document.body.append(frame);
1562
+ }
1563
+ download(blob, fileName) {
1564
+ const url = URL.createObjectURL(blob);
1565
+ const link = this.document.createElement("a");
1566
+ link.href = url;
1567
+ link.download = fileName;
1568
+ link.click();
1569
+ URL.revokeObjectURL(url);
1570
+ }
1571
+ sortBy(column, event) {
1572
+ const current = this.sorts().find((sort) => sort.field === column.field);
1573
+ const order = current ? current.order === 1 ? -1 : 1 : 1;
1574
+ if (this.multiSort() && event?.shiftKey) {
1575
+ const sorts = this.sorts();
1576
+ this.sortMeta.set(current ? sorts.map((sort) => sort.field === column.field ? {
1577
+ ...sort,
1578
+ order
1579
+ } : sort) : [...sorts, {
1580
+ field: column.field,
1581
+ order
1582
+ }]);
1583
+ } else this.sortMeta.set(this.multiSort() ? [{
1584
+ field: column.field,
1585
+ order
1586
+ }] : []);
1587
+ const first = this.multiSort() ? this.sortMeta()[0] : {
1588
+ field: column.field,
1589
+ order
1590
+ };
1591
+ this.sortField.set(first.field);
1592
+ this.sortOrder.set(first.order);
1593
+ this.first.set(0);
1594
+ this.emitLazy();
1595
+ }
1596
+ sortOf(column) {
1597
+ return this.sorts().find((sort) => sort.field === column.field);
1598
+ }
1599
+ ariaSort(column) {
1600
+ if (!column.sortable) return null;
1601
+ const first = this.sorts()[0];
1602
+ if (first?.field !== column.field) return "none";
1603
+ return first.order === 1 ? "ascending" : "descending";
1604
+ }
1605
+ sortIcon(column) {
1606
+ const sort = this.sortOf(column);
1607
+ if (!sort) return "ph-bold ph-arrows-down-up star-table__sort-idle";
1608
+ return sort.order === 1 ? "ph-bold ph-sort-ascending" : "ph-bold ph-sort-descending";
1609
+ }
1610
+ sortRank(column) {
1611
+ const sorts = this.sorts();
1612
+ if (sorts.length < 2) return null;
1613
+ const index = sorts.findIndex((sort) => sort.field === column.field);
1614
+ return index < 0 ? null : index + 1;
1615
+ }
1616
+ selectedKeys = computed(() => new Set(this.selection().map((row) => this.trackKey(row))), ...ngDevMode ? [{ debugName: "selectedKeys" }] : /* istanbul ignore next */ []);
1617
+ isSelected(row) {
1618
+ return this.selectedKeys().has(this.trackKey(row));
1619
+ }
1620
+ toggleRow(row) {
1621
+ const key = this.trackKey(row);
1622
+ this.selection.update((selection) => this.isSelected(row) ? selection.filter((selected) => !Object.is(this.trackKey(selected), key)) : [...selection, row]);
1623
+ }
1624
+ selectOnly(row) {
1625
+ this.selection.set([row]);
1626
+ }
1627
+ togglePage(checked) {
1628
+ const page = this.pageRows();
1629
+ const keys = new Set(page.map((row) => this.trackKey(row)));
1630
+ this.selection.update((selection) => {
1631
+ const others = selection.filter((row) => !keys.has(this.trackKey(row)));
1632
+ return checked ? [...others, ...page] : others;
1633
+ });
1634
+ }
1635
+ onRowClick(row, event) {
1636
+ if (event.target.closest("button, a, input, select, textarea")) return;
1637
+ if (this.selectionMode() === "single") this.selectOnly(row);
1638
+ this.rowClick.emit(row);
1639
+ }
1640
+ emitLazy() {
1641
+ if (!this.lazy()) return;
1642
+ this.lazyLoad.emit({
1643
+ first: this.first(),
1644
+ rows: this.rows(),
1645
+ field: this.sortField(),
1646
+ order: this.sortOrder(),
1647
+ filter: this.globalFilter(),
1648
+ filters: this.filters(),
1649
+ sorts: this.sorts()
1650
+ });
1651
+ }
1652
+ static ɵfac = i0.ɵɵngDeclareFactory({
1653
+ minVersion: "12.0.0",
1654
+ version: "22.2.6",
1655
+ ngImport: i0,
1656
+ type: StarTable,
1657
+ deps: [],
1658
+ target: i0.ɵɵFactoryTarget.Component
1659
+ });
1660
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1661
+ minVersion: "17.0.0",
1662
+ version: "22.2.6",
1663
+ type: StarTable,
1664
+ isStandalone: true,
1665
+ selector: "star-table",
1666
+ inputs: {
1667
+ value: {
1668
+ classPropertyName: "value",
1669
+ publicName: "value",
1670
+ isSignal: true,
1671
+ isRequired: true,
1672
+ transformFunction: null
1673
+ },
1674
+ columns: {
1675
+ classPropertyName: "columns",
1676
+ publicName: "columns",
1677
+ isSignal: true,
1678
+ isRequired: true,
1679
+ transformFunction: null
1680
+ },
1681
+ dataKey: {
1682
+ classPropertyName: "dataKey",
1683
+ publicName: "dataKey",
1684
+ isSignal: true,
1685
+ isRequired: false,
1686
+ transformFunction: null
1687
+ },
1688
+ loading: {
1689
+ classPropertyName: "loading",
1690
+ publicName: "loading",
1691
+ isSignal: true,
1692
+ isRequired: false,
1693
+ transformFunction: null
1694
+ },
1695
+ emptyMessage: {
1696
+ classPropertyName: "emptyMessage",
1697
+ publicName: "emptyMessage",
1698
+ isSignal: true,
1699
+ isRequired: false,
1700
+ transformFunction: null
1701
+ },
1702
+ striped: {
1703
+ classPropertyName: "striped",
1704
+ publicName: "striped",
1705
+ isSignal: true,
1706
+ isRequired: false,
1707
+ transformFunction: null
1708
+ },
1709
+ size: {
1710
+ classPropertyName: "size",
1711
+ publicName: "size",
1712
+ isSignal: true,
1713
+ isRequired: false,
1714
+ transformFunction: null
1715
+ },
1716
+ stickyHeader: {
1717
+ classPropertyName: "stickyHeader",
1718
+ publicName: "stickyHeader",
1719
+ isSignal: true,
1720
+ isRequired: false,
1721
+ transformFunction: null
1722
+ },
1723
+ scrollHeight: {
1724
+ classPropertyName: "scrollHeight",
1725
+ publicName: "scrollHeight",
1726
+ isSignal: true,
1727
+ isRequired: false,
1728
+ transformFunction: null
1729
+ },
1730
+ responsiveLayout: {
1731
+ classPropertyName: "responsiveLayout",
1732
+ publicName: "responsiveLayout",
1733
+ isSignal: true,
1734
+ isRequired: false,
1735
+ transformFunction: null
1736
+ },
1737
+ virtualScroll: {
1738
+ classPropertyName: "virtualScroll",
1739
+ publicName: "virtualScroll",
1740
+ isSignal: true,
1741
+ isRequired: false,
1742
+ transformFunction: null
1743
+ },
1744
+ virtualRowHeight: {
1745
+ classPropertyName: "virtualRowHeight",
1746
+ publicName: "virtualRowHeight",
1747
+ isSignal: true,
1748
+ isRequired: false,
1749
+ transformFunction: null
1750
+ },
1751
+ virtualRowHeights: {
1752
+ classPropertyName: "virtualRowHeights",
1753
+ publicName: "virtualRowHeights",
1754
+ isSignal: true,
1755
+ isRequired: false,
1756
+ transformFunction: null
1757
+ },
1758
+ ariaLabel: {
1759
+ classPropertyName: "ariaLabel",
1760
+ publicName: "ariaLabel",
1761
+ isSignal: true,
1762
+ isRequired: false,
1763
+ transformFunction: null
1764
+ },
1765
+ paginator: {
1766
+ classPropertyName: "paginator",
1767
+ publicName: "paginator",
1768
+ isSignal: true,
1769
+ isRequired: false,
1770
+ transformFunction: null
1771
+ },
1772
+ first: {
1773
+ classPropertyName: "first",
1774
+ publicName: "first",
1775
+ isSignal: true,
1776
+ isRequired: false,
1777
+ transformFunction: null
1778
+ },
1779
+ rows: {
1780
+ classPropertyName: "rows",
1781
+ publicName: "rows",
1782
+ isSignal: true,
1783
+ isRequired: false,
1784
+ transformFunction: null
1785
+ },
1786
+ rowsPerPageOptions: {
1787
+ classPropertyName: "rowsPerPageOptions",
1788
+ publicName: "rowsPerPageOptions",
1789
+ isSignal: true,
1790
+ isRequired: false,
1791
+ transformFunction: null
1792
+ },
1793
+ sortField: {
1794
+ classPropertyName: "sortField",
1795
+ publicName: "sortField",
1796
+ isSignal: true,
1797
+ isRequired: false,
1798
+ transformFunction: null
1799
+ },
1800
+ sortOrder: {
1801
+ classPropertyName: "sortOrder",
1802
+ publicName: "sortOrder",
1803
+ isSignal: true,
1804
+ isRequired: false,
1805
+ transformFunction: null
1806
+ },
1807
+ globalFilter: {
1808
+ classPropertyName: "globalFilter",
1809
+ publicName: "globalFilter",
1810
+ isSignal: true,
1811
+ isRequired: false,
1812
+ transformFunction: null
1813
+ },
1814
+ filters: {
1815
+ classPropertyName: "filters",
1816
+ publicName: "filters",
1817
+ isSignal: true,
1818
+ isRequired: false,
1819
+ transformFunction: null
1820
+ },
1821
+ lazy: {
1822
+ classPropertyName: "lazy",
1823
+ publicName: "lazy",
1824
+ isSignal: true,
1825
+ isRequired: false,
1826
+ transformFunction: null
1827
+ },
1828
+ totalRecords: {
1829
+ classPropertyName: "totalRecords",
1830
+ publicName: "totalRecords",
1831
+ isSignal: true,
1832
+ isRequired: false,
1833
+ transformFunction: null
1834
+ },
1835
+ selectionMode: {
1836
+ classPropertyName: "selectionMode",
1837
+ publicName: "selectionMode",
1838
+ isSignal: true,
1839
+ isRequired: false,
1840
+ transformFunction: null
1841
+ },
1842
+ selection: {
1843
+ classPropertyName: "selection",
1844
+ publicName: "selection",
1845
+ isSignal: true,
1846
+ isRequired: false,
1847
+ transformFunction: null
1848
+ },
1849
+ expandedKeys: {
1850
+ classPropertyName: "expandedKeys",
1851
+ publicName: "expandedKeys",
1852
+ isSignal: true,
1853
+ isRequired: false,
1854
+ transformFunction: null
1855
+ },
1856
+ rowExpandMode: {
1857
+ classPropertyName: "rowExpandMode",
1858
+ publicName: "rowExpandMode",
1859
+ isSignal: true,
1860
+ isRequired: false,
1861
+ transformFunction: null
1862
+ },
1863
+ columnToggle: {
1864
+ classPropertyName: "columnToggle",
1865
+ publicName: "columnToggle",
1866
+ isSignal: true,
1867
+ isRequired: false,
1868
+ transformFunction: null
1869
+ },
1870
+ reorderableColumns: {
1871
+ classPropertyName: "reorderableColumns",
1872
+ publicName: "reorderableColumns",
1873
+ isSignal: true,
1874
+ isRequired: false,
1875
+ transformFunction: null
1876
+ },
1877
+ resizableColumns: {
1878
+ classPropertyName: "resizableColumns",
1879
+ publicName: "resizableColumns",
1880
+ isSignal: true,
1881
+ isRequired: false,
1882
+ transformFunction: null
1883
+ },
1884
+ columnOrder: {
1885
+ classPropertyName: "columnOrder",
1886
+ publicName: "columnOrder",
1887
+ isSignal: true,
1888
+ isRequired: false,
1889
+ transformFunction: null
1890
+ },
1891
+ hiddenColumns: {
1892
+ classPropertyName: "hiddenColumns",
1893
+ publicName: "hiddenColumns",
1894
+ isSignal: true,
1895
+ isRequired: false,
1896
+ transformFunction: null
1897
+ },
1898
+ columnWidths: {
1899
+ classPropertyName: "columnWidths",
1900
+ publicName: "columnWidths",
1901
+ isSignal: true,
1902
+ isRequired: false,
1903
+ transformFunction: null
1904
+ },
1905
+ multiSort: {
1906
+ classPropertyName: "multiSort",
1907
+ publicName: "multiSort",
1908
+ isSignal: true,
1909
+ isRequired: false,
1910
+ transformFunction: null
1911
+ },
1912
+ sortMeta: {
1913
+ classPropertyName: "sortMeta",
1914
+ publicName: "sortMeta",
1915
+ isSignal: true,
1916
+ isRequired: false,
1917
+ transformFunction: null
1918
+ },
1919
+ groupBy: {
1920
+ classPropertyName: "groupBy",
1921
+ publicName: "groupBy",
1922
+ isSignal: true,
1923
+ isRequired: false,
1924
+ transformFunction: null
1925
+ },
1926
+ collapsedGroups: {
1927
+ classPropertyName: "collapsedGroups",
1928
+ publicName: "collapsedGroups",
1929
+ isSignal: true,
1930
+ isRequired: false,
1931
+ transformFunction: null
1932
+ },
1933
+ reorderableRows: {
1934
+ classPropertyName: "reorderableRows",
1935
+ publicName: "reorderableRows",
1936
+ isSignal: true,
1937
+ isRequired: false,
1938
+ transformFunction: null
1939
+ },
1940
+ stateKey: {
1941
+ classPropertyName: "stateKey",
1942
+ publicName: "stateKey",
1943
+ isSignal: true,
1944
+ isRequired: false,
1945
+ transformFunction: null
1946
+ },
1947
+ stateStorage: {
1948
+ classPropertyName: "stateStorage",
1949
+ publicName: "stateStorage",
1950
+ isSignal: true,
1951
+ isRequired: false,
1952
+ transformFunction: null
1953
+ }
1954
+ },
1955
+ outputs: {
1956
+ first: "firstChange",
1957
+ rows: "rowsChange",
1958
+ sortField: "sortFieldChange",
1959
+ sortOrder: "sortOrderChange",
1960
+ filters: "filtersChange",
1961
+ selection: "selectionChange",
1962
+ expandedKeys: "expandedKeysChange",
1963
+ columnOrder: "columnOrderChange",
1964
+ hiddenColumns: "hiddenColumnsChange",
1965
+ columnWidths: "columnWidthsChange",
1966
+ sortMeta: "sortMetaChange",
1967
+ collapsedGroups: "collapsedGroupsChange",
1968
+ rowClick: "rowClick",
1969
+ rowReorder: "rowReorder",
1970
+ cellEdit: "cellEdit",
1971
+ lazyLoad: "lazyLoad"
1972
+ },
1973
+ host: {
1974
+ listeners: {
1975
+ "focusin": "onBodyFocusIn($event)",
1976
+ "focusout": "onBodyFocusOut($event)",
1977
+ "keydown": "onBodyKeydown($event)"
1978
+ },
1979
+ properties: {
1980
+ "class.star-table--striped": "striped()",
1981
+ "class.star-table--sm": "size() === 'sm'",
1982
+ "class.star-table--sticky": "stickyHeader()",
1983
+ "class.star-table--virtual": "virtualScroll()",
1984
+ "class.star-table--variable": "variableHeights()",
1985
+ "class.star-table--stack": "responsiveLayout() === 'stack'",
1986
+ "style.--star-table-row-height.px": "virtualScroll() ? virtualRowHeight() : null"
1987
+ },
1988
+ classAttribute: "star-table"
1989
+ },
1990
+ queries: [{
1991
+ propertyName: "cellTemplates",
1992
+ predicate: StarCellTemplate,
1993
+ isSignal: true
1994
+ }, {
1995
+ propertyName: "expansion",
1996
+ first: true,
1997
+ predicate: StarRowExpansionTemplate,
1998
+ descendants: true,
1999
+ isSignal: true
2000
+ }],
2001
+ viewQueries: [{
2002
+ propertyName: "scroller",
2003
+ first: true,
2004
+ predicate: ["scroller"],
2005
+ descendants: true,
2006
+ isSignal: true
2007
+ }, {
2008
+ propertyName: "body",
2009
+ first: true,
2010
+ predicate: ["body"],
2011
+ descendants: true,
2012
+ isSignal: true
2013
+ }],
2014
+ ngImport: i0,
2015
+ template: `
2016
+ <ng-content select="[starTableCaption]" />
2017
+ @if (columnToggle()) {
2018
+ <div class="star-table__tools">
2019
+ <star-button
2020
+ size="sm"
2021
+ variant="secondary"
2022
+ leadingIcon="ph-bold ph-columns"
2023
+ (pressed)="columnsPanel.toggle($event)"
2024
+ >
2025
+ {{ text.columns }}
2026
+ </star-button>
2027
+ <star-popover #columnsPanel [ariaLabel]="text.columns">
2028
+ <ul class="star-table__columns">
2029
+ @for (
2030
+ column of orderedColumns();
2031
+ track column.field;
2032
+ let first = $first;
2033
+ let last = $last
2034
+ ) {
2035
+ <li>
2036
+ <star-checkbox
2037
+ [checked]="!isHidden(column)"
2038
+ [disabled]="!canHide(column)"
2039
+ (checkedChange)="setColumnVisible(column, $event)"
2040
+ >
2041
+ {{ column.header }}
2042
+ </star-checkbox>
2043
+ @if (reorderableColumns()) {
2044
+ <span class="star-table__columns-move">
2045
+ <button
2046
+ type="button"
2047
+ class="star-table__toggle"
2048
+ [disabled]="first"
2049
+ [attr.data-move]="moveKey(column, -1)"
2050
+ [attr.aria-label]="text.moveColumnEarlier(column.header)"
2051
+ (click)="moveColumnBy(column, -1)"
2052
+ >
2053
+ <i class="ph-bold ph-arrow-up" aria-hidden="true"></i>
2054
+ </button>
2055
+ <button
2056
+ type="button"
2057
+ class="star-table__toggle"
2058
+ [disabled]="last"
2059
+ [attr.data-move]="moveKey(column, 1)"
2060
+ [attr.aria-label]="text.moveColumnLater(column.header)"
2061
+ (click)="moveColumnBy(column, 1)"
2062
+ >
2063
+ <i class="ph-bold ph-arrow-down" aria-hidden="true"></i>
2064
+ </button>
2065
+ </span>
2066
+ }
2067
+ </li>
2068
+ }
2069
+ </ul>
2070
+ </star-popover>
2071
+ </div>
2072
+ }
2073
+ <div
2074
+ #scroller
2075
+ class="star-table__scroll"
2076
+ [attr.role]="scrollable() ? 'group' : null"
2077
+ [attr.aria-label]="scrollable() ? ariaLabel() : null"
2078
+ [attr.tabindex]="scrollable() ? 0 : null"
2079
+ [style.max-height]="scrollHeight()"
2080
+ (scroll)="onScroll($event)"
2081
+ >
2082
+ <table
2083
+ [attr.aria-label]="ariaLabel()"
2084
+ [attr.aria-busy]="loading() || null"
2085
+ [attr.aria-rowcount]="ariaRowCount()"
2086
+ >
2087
+ <thead>
2088
+ <tr [attr.aria-rowindex]="virtualScroll() ? 1 : null">
2089
+ @if (reorderableRows()) {
2090
+ <th class="star-table__reorder" scope="col">
2091
+ <span class="star-sr-only">{{ text.reorderRows }}</span>
2092
+ </th>
2093
+ }
2094
+ @if (expandable()) {
2095
+ <th class="star-table__expander" scope="col">
2096
+ <span class="star-sr-only">{{ text.rowDetails }}</span>
2097
+ </th>
2098
+ }
2099
+ @if (selectionMode() === 'multiple') {
2100
+ <th class="star-table__select" scope="col">
2101
+ <star-checkbox
2102
+ [checked]="pageState() === true"
2103
+ [indeterminate]="pageState() === 'mixed'"
2104
+ [ariaLabel]="text.selectAllRows"
2105
+ [disabled]="!pageRows().length"
2106
+ (checkedChange)="togglePage($event)"
2107
+ />
2108
+ </th>
2109
+ } @else if (selectionMode() === 'single') {
2110
+ <th class="star-table__select" scope="col">
2111
+ <span class="star-sr-only">{{ text.selectRow }}</span>
2112
+ </th>
2113
+ }
2114
+ @for (column of visibleColumns(); track column.field) {
2115
+ <th
2116
+ scope="col"
2117
+ [style.width]="widthOf(column)"
2118
+ [style.min-width]="resizedWidth(column)"
2119
+ [style.max-width]="resizedWidth(column)"
2120
+ [style.inset-inline-start]="frozenOffset(column)"
2121
+ [attr.data-field]="column.field"
2122
+ [class]="'star-table__th star-table__cell--' + (column.align ?? 'start')"
2123
+ [class.star-table__cell--frozen]="column.frozen"
2124
+ [class.star-table__th--drop]="dropField() === column.field"
2125
+ [attr.aria-sort]="ariaSort(column)"
2126
+ [attr.draggable]="reorderableColumns() ? 'true' : null"
2127
+ (dragstart)="onDragStart(column, $event)"
2128
+ (dragover)="onDragOver(column, $event)"
2129
+ (drop)="onDrop(column, $event)"
2130
+ (dragend)="endDrag()"
2131
+ >
2132
+ @if (column.sortable) {
2133
+ <button
2134
+ type="button"
2135
+ class="star-table__sort"
2136
+ [attr.title]="multiSort() ? text.sortMultiHint : null"
2137
+ (click)="sortBy(column, $event)"
2138
+ >
2139
+ {{ column.header }}
2140
+ <i [class]="sortIcon(column)" aria-hidden="true"></i>
2141
+ @if (sortRank(column); as rank) {
2142
+ <span class="star-table__sort-rank">{{ rank }}</span>
2143
+ }
2144
+ </button>
2145
+ } @else {
2146
+ {{ column.header }}
2147
+ }
2148
+ @if (resizableColumns()) {
2149
+ <span
2150
+ class="star-table__resizer"
2151
+ role="separator"
2152
+ aria-orientation="vertical"
2153
+ tabindex="0"
2154
+ [attr.aria-label]="text.resizeColumn(column.header)"
2155
+ [attr.aria-valuenow]="resizeNow(column)"
2156
+ [attr.aria-valuemin]="minColumnWidth"
2157
+ [attr.aria-valuemax]="resizeMax(column)"
2158
+ (pointerdown)="startResize(column, $event)"
2159
+ (keydown)="onResizeKey(column, $event)"
2160
+ ></span>
2161
+ }
2162
+ </th>
2163
+ }
2164
+ </tr>
2165
+ @if (hasColumnFilters()) {
2166
+ <tr class="star-table__filters" [attr.aria-rowindex]="virtualScroll() ? 2 : null">
2167
+ @if (reorderableRows()) {
2168
+ <td class="star-table__reorder"></td>
2169
+ }
2170
+ @if (expandable()) {
2171
+ <td class="star-table__expander"></td>
2172
+ }
2173
+ @if (selectionMode()) {
2174
+ <td class="star-table__select"></td>
2175
+ }
2176
+ @for (column of visibleColumns(); track column.field) {
2177
+ <td
2178
+ [class.star-table__cell--frozen]="column.frozen"
2179
+ [style.inset-inline-start]="frozenOffset(column)"
2180
+ [attr.data-label]="column.filter ? column.header : null"
2181
+ >
2182
+ @if (column.filter === 'select') {
2183
+ <select
2184
+ class="star-input star-input--sm star-table__filter"
2185
+ [attr.aria-label]="text.filterBy(column.header)"
2186
+ (change)="setFilter(column.field, $any($event.target).value)"
2187
+ >
2188
+ <option value="" [selected]="!filterValue(column.field)">
2189
+ {{ text.filterAll }}
2190
+ </option>
2191
+ @for (option of filterChoices(column); track option) {
2192
+ <option [value]="option" [selected]="option === filterValue(column.field)">
2193
+ {{ option }}
2194
+ </option>
2195
+ }
2196
+ </select>
2197
+ } @else if (column.filter === 'text') {
2198
+ <input
2199
+ type="search"
2200
+ class="star-input star-input--sm star-table__filter"
2201
+ [attr.aria-label]="text.filterBy(column.header)"
2202
+ [value]="filterValue(column.field)"
2203
+ (input)="setFilter(column.field, $any($event.target).value)"
2204
+ />
2205
+ } @else if (column.filter === 'multiselect') {
2206
+ <star-multi-select
2207
+ class="star-table__filter"
2208
+ size="sm"
2209
+ [options]="filterChoices(column)"
2210
+ [value]="filterList(column.field)"
2211
+ [placeholder]="text.filterAll"
2212
+ [ariaLabel]="text.filterBy(column.header)"
2213
+ (valueChange)="setFilter(column.field, $event)"
2214
+ />
2215
+ } @else if (column.filter === 'number' || column.filter === 'date') {
2216
+ <span class="star-table__filter-range">
2217
+ <input
2218
+ class="star-input star-input--sm star-table__filter"
2219
+ [type]="column.filter"
2220
+ [attr.aria-label]="text.filterMin(column.header)"
2221
+ [attr.placeholder]="column.filter === 'number' ? text.filterMinShort : null"
2222
+ [value]="filterBound(column.field, 'min')"
2223
+ (input)="setBound(column, 'min', $any($event.target).value)"
2224
+ />
2225
+ <input
2226
+ class="star-input star-input--sm star-table__filter"
2227
+ [type]="column.filter"
2228
+ [attr.aria-label]="text.filterMax(column.header)"
2229
+ [attr.placeholder]="column.filter === 'number' ? text.filterMaxShort : null"
2230
+ [value]="filterBound(column.field, 'max')"
2231
+ (input)="setBound(column, 'max', $any($event.target).value)"
2232
+ />
2233
+ </span>
2234
+ }
2235
+ </td>
2236
+ }
2237
+ </tr>
2238
+ }
2239
+ </thead>
2240
+ <tbody #body>
2241
+ @if (loading()) {
2242
+ @for (row of skeletonRows(); track row) {
2243
+ <tr class="star-table__row">
2244
+ @if (reorderableRows()) {
2245
+ <td class="star-table__reorder"></td>
2246
+ }
2247
+ @if (expandable()) {
2248
+ <td class="star-table__expander"></td>
2249
+ }
2250
+ @if (selectionMode()) {
2251
+ <td class="star-table__select"><star-skeleton size="1.25rem" /></td>
2252
+ }
2253
+ @for (column of visibleColumns(); track column.field) {
2254
+ <td><star-skeleton height="0.875rem" [width]="row % 2 ? '70%' : '90%'" /></td>
2255
+ }
2256
+ </tr>
2257
+ }
2258
+ } @else {
2259
+ @for (entry of bodyEntries(); track entry.key) {
2260
+ @if (entry.kind === 'spacer') {
2261
+ <tr class="star-table__spacer" aria-hidden="true">
2262
+ <td [attr.colspan]="colspan()" [style.height.px]="entry.height"></td>
2263
+ </tr>
2264
+ } @else if (entry.kind === 'group') {
2265
+ @let group = entry;
2266
+ <tr
2267
+ class="star-table__group"
2268
+ [attr.aria-rowindex]="group.aria"
2269
+ [attr.data-vi]="group.item"
2270
+ >
2271
+ <th [attr.colspan]="colspan()" scope="colgroup">
2272
+ <button
2273
+ type="button"
2274
+ class="star-table__group-toggle"
2275
+ [attr.aria-expanded]="!isGroupCollapsed(group.label)"
2276
+ (click)="toggleGroup(group.label)"
2277
+ >
2278
+ <i class="ph-bold ph-caret-down" aria-hidden="true"></i>
2279
+ {{ group.label }}
2280
+ <span class="star-table__group-count">{{ group.count }}</span>
2281
+ </button>
2282
+ </th>
2283
+ </tr>
2284
+ } @else {
2285
+ @let row = entry.row;
2286
+ @let i = entry.index;
2287
+ <tr
2288
+ [attr.aria-rowindex]="entry.aria"
2289
+ [attr.data-vi]="entry.item"
2290
+ [hidden]="isRowCollapsed(row)"
2291
+ class="star-table__row"
2292
+ [class.star-table__row--alt]="i % 2 === 1"
2293
+ [class.star-table__row--selected]="isSelected(row)"
2294
+ [class.star-table__row--clickable]="clickable()"
2295
+ [class.star-table__row--expanded]="expandable() && isExpanded(row)"
2296
+ [attr.aria-selected]="selectionMode() ? isSelected(row) : null"
2297
+ (click)="onRowClick(row, $event)"
2298
+ >
2299
+ @if (reorderableRows()) {
2300
+ <td class="star-table__reorder">
2301
+ <button
2302
+ type="button"
2303
+ class="star-table__toggle"
2304
+ [disabled]="!canMoveRow(row, -1)"
2305
+ [attr.aria-label]="text.moveUp"
2306
+ (click)="moveRow(row, -1)"
2307
+ >
2308
+ <i class="ph-bold ph-arrow-up" aria-hidden="true"></i>
2309
+ </button>
2310
+ <button
2311
+ type="button"
2312
+ class="star-table__toggle"
2313
+ [disabled]="!canMoveRow(row, 1)"
2314
+ [attr.aria-label]="text.moveDown"
2315
+ (click)="moveRow(row, 1)"
2316
+ >
2317
+ <i class="ph-bold ph-arrow-down" aria-hidden="true"></i>
2318
+ </button>
2319
+ </td>
2320
+ }
2321
+ @if (expandable()) {
2322
+ <td class="star-table__expander">
2323
+ <button
2324
+ type="button"
2325
+ class="star-table__toggle"
2326
+ [attr.aria-expanded]="isExpanded(row)"
2327
+ [attr.aria-controls]="isExpanded(row) ? detailId(i) : null"
2328
+ [attr.aria-label]="isExpanded(row) ? text.collapseRow : text.expandRow"
2329
+ (click)="toggleExpansion(row)"
2330
+ >
2331
+ <i class="ph-bold ph-caret-right" aria-hidden="true"></i>
2332
+ </button>
2333
+ </td>
2334
+ }
2335
+ @if (selectionMode() === 'multiple') {
2336
+ <td class="star-table__select">
2337
+ <star-checkbox
2338
+ [checked]="isSelected(row)"
2339
+ [ariaLabel]="text.selectRow"
2340
+ (checkedChange)="toggleRow(row)"
2341
+ (click)="$event.stopPropagation()"
2342
+ />
2343
+ </td>
2344
+ } @else if (selectionMode() === 'single') {
2345
+ <td class="star-table__select">
2346
+ <input
2347
+ type="radio"
2348
+ class="star-table__radio"
2349
+ [name]="radioName"
2350
+ [checked]="isSelected(row)"
2351
+ [attr.aria-label]="text.selectRow"
2352
+ (change)="selectOnly(row)"
2353
+ (click)="$event.stopPropagation()"
2354
+ />
2355
+ </td>
2356
+ }
2357
+ @for (column of visibleColumns(); track column.field) {
2358
+ <td
2359
+ [class]="'star-table__cell--' + (column.align ?? 'start')"
2360
+ [class.star-table__cell--frozen]="column.frozen"
2361
+ [style.inset-inline-start]="frozenOffset(column)"
2362
+ [attr.data-label]="column.header"
2363
+ >
2364
+ @if (isEditing(row, column)) {
2365
+ @if (column.editor === 'select') {
2366
+ <select
2367
+ class="star-input star-input--sm star-table__editor"
2368
+ [attr.aria-label]="text.editCell(column.header)"
2369
+ (change)="commitEdit(row, column, $any($event.target).value)"
2370
+ (blur)="commitEdit(row, column, $any($event.target).value)"
2371
+ (keydown.escape)="cancelEdit($event)"
2372
+ >
2373
+ @for (option of column.editOptions ?? []; track option) {
2374
+ <option
2375
+ [value]="option"
2376
+ [selected]="option === cellText(row, column)"
2377
+ >
2378
+ {{ option }}
2379
+ </option>
2380
+ }
2381
+ </select>
2382
+ } @else {
2383
+ <input
2384
+ class="star-input star-input--sm star-table__editor"
2385
+ [type]="column.editor === 'number' ? 'number' : 'text'"
2386
+ [attr.aria-label]="text.editCell(column.header)"
2387
+ [value]="editText(row, column)"
2388
+ (blur)="commitEdit(row, column, $any($event.target).value)"
2389
+ (keydown.enter)="commitEdit(row, column, $any($event.target).value)"
2390
+ (keydown.escape)="cancelEdit($event)"
2391
+ />
2392
+ }
2393
+ } @else if (isEditable(row, column)) {
2394
+ <button
2395
+ type="button"
2396
+ class="star-table__edit"
2397
+ [attr.data-edit]="editKey(row, column)"
2398
+ (click)="startEdit(row, column)"
2399
+ >
2400
+ <!-- The name is the action and the visible value (WCAG 2.5.3). -->
2401
+ <span class="star-sr-only">{{ text.editCell(column.header) }}: </span>
2402
+ <span class="star-table__edit-value">
2403
+ <ng-container
2404
+ *ngTemplateOutlet="
2405
+ cell;
2406
+ context: { $implicit: row, column, index: i }
2407
+ "
2408
+ />
2409
+ </span>
2410
+ <i class="ph-bold ph-pencil-simple" aria-hidden="true"></i>
2411
+ </button>
2412
+ } @else {
2413
+ <ng-container
2414
+ *ngTemplateOutlet="cell; context: { $implicit: row, column, index: i }"
2415
+ />
2416
+ }
2417
+ </td>
2418
+ }
2419
+ </tr>
2420
+ @if (expansionTemplate(); as detail) {
2421
+ @if (isExpanded(row) && !isRowCollapsed(row)) {
2422
+ <tr
2423
+ class="star-table__expansion"
2424
+ [id]="detailId(i)"
2425
+ [attr.aria-rowindex]="entry.aria === null ? null : entry.aria + 1"
2426
+ [attr.data-vi]="entry.item"
2427
+ >
2428
+ <td [attr.colspan]="colspan()">
2429
+ <ng-container
2430
+ *ngTemplateOutlet="detail; context: { $implicit: row, index: i }"
2431
+ />
2432
+ </td>
2433
+ </tr>
2434
+ }
2435
+ }
2436
+ }
2437
+ } @empty {
2438
+ <tr>
2439
+ <td class="star-table__empty" [attr.colspan]="colspan()">
2440
+ <i class="ph-bold ph-tray" aria-hidden="true"></i>
2441
+ {{ emptyMessage() ?? text.noData }}
2442
+ </td>
2443
+ </tr>
2444
+ }
2445
+ }
2446
+ </tbody>
2447
+ @if (hasFooter()) {
2448
+ <tfoot>
2449
+ <tr
2450
+ class="star-table__footer"
2451
+ [attr.aria-rowindex]="virtualScroll() ? ariaRowCount() : null"
2452
+ >
2453
+ @if (reorderableRows()) {
2454
+ <td class="star-table__reorder"></td>
2455
+ }
2456
+ @if (expandable()) {
2457
+ <td class="star-table__expander"></td>
2458
+ }
2459
+ @if (selectionMode()) {
2460
+ <td class="star-table__select"></td>
2461
+ }
2462
+ @for (column of visibleColumns(); track column.field) {
2463
+ <td
2464
+ [class]="'star-table__cell--' + (column.align ?? 'start')"
2465
+ [attr.data-label]="footerText(column) ? column.header : null"
2466
+ >
2467
+ {{ footerText(column) }}
2468
+ </td>
2469
+ }
2470
+ </tr>
2471
+ </tfoot>
2472
+ }
2473
+ </table>
2474
+ </div>
2475
+ <ng-template #cell let-row let-column="column" let-i="index">
2476
+ @if (cellTemplate(column.field); as custom) {
2477
+ <ng-container
2478
+ *ngTemplateOutlet="
2479
+ custom;
2480
+ context: { $implicit: row, value: cellValue(row, column), index: i }
2481
+ "
2482
+ />
2483
+ } @else {
2484
+ {{ cellText(row, column) }}
2485
+ }
2486
+ </ng-template>
2487
+ @if (paginator()) {
2488
+ <star-paginator
2489
+ [ariaLabel]="ariaLabel() ? text.pagination + ': ' + ariaLabel() : null"
2490
+ [totalRecords]="total()"
2491
+ [(first)]="first"
2492
+ [(rows)]="rows"
2493
+ [rowsPerPageOptions]="rowsPerPageOptions()"
2494
+ (pageChange)="emitLazy()"
2495
+ />
2496
+ }
2497
+ `,
2498
+ isInline: true,
2499
+ dependencies: [
2500
+ {
2501
+ kind: "directive",
2502
+ type: NgTemplateOutlet,
2503
+ selector: "[ngTemplateOutlet]",
2504
+ inputs: [
2505
+ "ngTemplateOutletContext",
2506
+ "ngTemplateOutlet",
2507
+ "ngTemplateOutletInjector"
2508
+ ]
2509
+ },
2510
+ {
2511
+ kind: "component",
2512
+ type: StarButton,
2513
+ selector: "star-button",
2514
+ inputs: [
2515
+ "variant",
2516
+ "size",
2517
+ "type",
2518
+ "disabled",
2519
+ "loading",
2520
+ "leadingIcon",
2521
+ "trailingIcon",
2522
+ "iconOnly",
2523
+ "fullWidth",
2524
+ "ariaLabel"
2525
+ ],
2526
+ outputs: ["pressed"]
2527
+ },
2528
+ {
2529
+ kind: "component",
2530
+ type: StarCheckbox,
2531
+ selector: "star-checkbox",
2532
+ inputs: [
2533
+ "checked",
2534
+ "indeterminate",
2535
+ "disabled",
2536
+ "readonly",
2537
+ "required",
2538
+ "invalid",
2539
+ "touched",
2540
+ "name",
2541
+ "inputId",
2542
+ "ariaLabel",
2543
+ "ariaDescribedBy"
2544
+ ],
2545
+ outputs: [
2546
+ "checkedChange",
2547
+ "indeterminateChange",
2548
+ "touch"
2549
+ ]
2550
+ },
2551
+ {
2552
+ kind: "component",
2553
+ type: StarMultiSelect,
2554
+ selector: "star-multi-select",
2555
+ inputs: [
2556
+ "value",
2557
+ "display",
2558
+ "maxSelectedLabels",
2559
+ "selectionLimit",
2560
+ "showToggleAll"
2561
+ ],
2562
+ outputs: ["valueChange"]
2563
+ },
2564
+ {
2565
+ kind: "component",
2566
+ type: StarPaginator,
2567
+ selector: "star-paginator",
2568
+ inputs: [
2569
+ "totalRecords",
2570
+ "first",
2571
+ "rows",
2572
+ "rowsPerPageOptions",
2573
+ "pageLinkSize",
2574
+ "showCurrentPageReport",
2575
+ "showFirstLast",
2576
+ "ariaLabel"
2577
+ ],
2578
+ outputs: [
2579
+ "firstChange",
2580
+ "rowsChange",
2581
+ "pageChange"
2582
+ ]
2583
+ },
2584
+ {
2585
+ kind: "component",
2586
+ type: StarPopover,
2587
+ selector: "star-popover",
2588
+ inputs: [
2589
+ "ariaLabel",
2590
+ "focusOnShow",
2591
+ "dismissable"
2592
+ ],
2593
+ outputs: ["shown", "hidden"]
2594
+ },
2595
+ {
2596
+ kind: "component",
2597
+ type: StarSkeleton,
2598
+ selector: "star-skeleton",
2599
+ inputs: [
2600
+ "shape",
2601
+ "width",
2602
+ "height",
2603
+ "size",
2604
+ "borderRadius",
2605
+ "animation"
2606
+ ]
2607
+ }
2608
+ ],
2609
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
2610
+ });
2611
+ };
2612
+ i0.ɵɵngDeclareClassMetadata({
2613
+ minVersion: "12.0.0",
2614
+ version: "22.2.6",
2615
+ ngImport: i0,
2616
+ type: StarTable,
2617
+ decorators: [{
2618
+ type: Component,
2619
+ args: [{
2620
+ selector: "star-table",
2621
+ imports: [
2622
+ NgTemplateOutlet,
2623
+ StarButton,
2624
+ StarCheckbox,
2625
+ StarMultiSelect,
2626
+ StarPaginator,
2627
+ StarPopover,
2628
+ StarSkeleton
2629
+ ],
2630
+ changeDetection: ChangeDetectionStrategy.OnPush,
2631
+ host: {
2632
+ class: "star-table",
2633
+ "[class.star-table--striped]": "striped()",
2634
+ "[class.star-table--sm]": "size() === 'sm'",
2635
+ "[class.star-table--sticky]": "stickyHeader()",
2636
+ "[class.star-table--virtual]": "virtualScroll()",
2637
+ "[class.star-table--variable]": "variableHeights()",
2638
+ "[class.star-table--stack]": "responsiveLayout() === 'stack'",
2639
+ "[style.--star-table-row-height.px]": "virtualScroll() ? virtualRowHeight() : null",
2640
+ "(focusin)": "onBodyFocusIn($event)",
2641
+ "(focusout)": "onBodyFocusOut($event)",
2642
+ "(keydown)": "onBodyKeydown($event)"
2643
+ },
2644
+ template: `
2645
+ <ng-content select="[starTableCaption]" />
2646
+ @if (columnToggle()) {
2647
+ <div class="star-table__tools">
2648
+ <star-button
2649
+ size="sm"
2650
+ variant="secondary"
2651
+ leadingIcon="ph-bold ph-columns"
2652
+ (pressed)="columnsPanel.toggle($event)"
2653
+ >
2654
+ {{ text.columns }}
2655
+ </star-button>
2656
+ <star-popover #columnsPanel [ariaLabel]="text.columns">
2657
+ <ul class="star-table__columns">
2658
+ @for (
2659
+ column of orderedColumns();
2660
+ track column.field;
2661
+ let first = $first;
2662
+ let last = $last
2663
+ ) {
2664
+ <li>
2665
+ <star-checkbox
2666
+ [checked]="!isHidden(column)"
2667
+ [disabled]="!canHide(column)"
2668
+ (checkedChange)="setColumnVisible(column, $event)"
2669
+ >
2670
+ {{ column.header }}
2671
+ </star-checkbox>
2672
+ @if (reorderableColumns()) {
2673
+ <span class="star-table__columns-move">
2674
+ <button
2675
+ type="button"
2676
+ class="star-table__toggle"
2677
+ [disabled]="first"
2678
+ [attr.data-move]="moveKey(column, -1)"
2679
+ [attr.aria-label]="text.moveColumnEarlier(column.header)"
2680
+ (click)="moveColumnBy(column, -1)"
2681
+ >
2682
+ <i class="ph-bold ph-arrow-up" aria-hidden="true"></i>
2683
+ </button>
2684
+ <button
2685
+ type="button"
2686
+ class="star-table__toggle"
2687
+ [disabled]="last"
2688
+ [attr.data-move]="moveKey(column, 1)"
2689
+ [attr.aria-label]="text.moveColumnLater(column.header)"
2690
+ (click)="moveColumnBy(column, 1)"
2691
+ >
2692
+ <i class="ph-bold ph-arrow-down" aria-hidden="true"></i>
2693
+ </button>
2694
+ </span>
2695
+ }
2696
+ </li>
2697
+ }
2698
+ </ul>
2699
+ </star-popover>
2700
+ </div>
2701
+ }
2702
+ <div
2703
+ #scroller
2704
+ class="star-table__scroll"
2705
+ [attr.role]="scrollable() ? 'group' : null"
2706
+ [attr.aria-label]="scrollable() ? ariaLabel() : null"
2707
+ [attr.tabindex]="scrollable() ? 0 : null"
2708
+ [style.max-height]="scrollHeight()"
2709
+ (scroll)="onScroll($event)"
2710
+ >
2711
+ <table
2712
+ [attr.aria-label]="ariaLabel()"
2713
+ [attr.aria-busy]="loading() || null"
2714
+ [attr.aria-rowcount]="ariaRowCount()"
2715
+ >
2716
+ <thead>
2717
+ <tr [attr.aria-rowindex]="virtualScroll() ? 1 : null">
2718
+ @if (reorderableRows()) {
2719
+ <th class="star-table__reorder" scope="col">
2720
+ <span class="star-sr-only">{{ text.reorderRows }}</span>
2721
+ </th>
2722
+ }
2723
+ @if (expandable()) {
2724
+ <th class="star-table__expander" scope="col">
2725
+ <span class="star-sr-only">{{ text.rowDetails }}</span>
2726
+ </th>
2727
+ }
2728
+ @if (selectionMode() === 'multiple') {
2729
+ <th class="star-table__select" scope="col">
2730
+ <star-checkbox
2731
+ [checked]="pageState() === true"
2732
+ [indeterminate]="pageState() === 'mixed'"
2733
+ [ariaLabel]="text.selectAllRows"
2734
+ [disabled]="!pageRows().length"
2735
+ (checkedChange)="togglePage($event)"
2736
+ />
2737
+ </th>
2738
+ } @else if (selectionMode() === 'single') {
2739
+ <th class="star-table__select" scope="col">
2740
+ <span class="star-sr-only">{{ text.selectRow }}</span>
2741
+ </th>
2742
+ }
2743
+ @for (column of visibleColumns(); track column.field) {
2744
+ <th
2745
+ scope="col"
2746
+ [style.width]="widthOf(column)"
2747
+ [style.min-width]="resizedWidth(column)"
2748
+ [style.max-width]="resizedWidth(column)"
2749
+ [style.inset-inline-start]="frozenOffset(column)"
2750
+ [attr.data-field]="column.field"
2751
+ [class]="'star-table__th star-table__cell--' + (column.align ?? 'start')"
2752
+ [class.star-table__cell--frozen]="column.frozen"
2753
+ [class.star-table__th--drop]="dropField() === column.field"
2754
+ [attr.aria-sort]="ariaSort(column)"
2755
+ [attr.draggable]="reorderableColumns() ? 'true' : null"
2756
+ (dragstart)="onDragStart(column, $event)"
2757
+ (dragover)="onDragOver(column, $event)"
2758
+ (drop)="onDrop(column, $event)"
2759
+ (dragend)="endDrag()"
2760
+ >
2761
+ @if (column.sortable) {
2762
+ <button
2763
+ type="button"
2764
+ class="star-table__sort"
2765
+ [attr.title]="multiSort() ? text.sortMultiHint : null"
2766
+ (click)="sortBy(column, $event)"
2767
+ >
2768
+ {{ column.header }}
2769
+ <i [class]="sortIcon(column)" aria-hidden="true"></i>
2770
+ @if (sortRank(column); as rank) {
2771
+ <span class="star-table__sort-rank">{{ rank }}</span>
2772
+ }
2773
+ </button>
2774
+ } @else {
2775
+ {{ column.header }}
2776
+ }
2777
+ @if (resizableColumns()) {
2778
+ <span
2779
+ class="star-table__resizer"
2780
+ role="separator"
2781
+ aria-orientation="vertical"
2782
+ tabindex="0"
2783
+ [attr.aria-label]="text.resizeColumn(column.header)"
2784
+ [attr.aria-valuenow]="resizeNow(column)"
2785
+ [attr.aria-valuemin]="minColumnWidth"
2786
+ [attr.aria-valuemax]="resizeMax(column)"
2787
+ (pointerdown)="startResize(column, $event)"
2788
+ (keydown)="onResizeKey(column, $event)"
2789
+ ></span>
2790
+ }
2791
+ </th>
2792
+ }
2793
+ </tr>
2794
+ @if (hasColumnFilters()) {
2795
+ <tr class="star-table__filters" [attr.aria-rowindex]="virtualScroll() ? 2 : null">
2796
+ @if (reorderableRows()) {
2797
+ <td class="star-table__reorder"></td>
2798
+ }
2799
+ @if (expandable()) {
2800
+ <td class="star-table__expander"></td>
2801
+ }
2802
+ @if (selectionMode()) {
2803
+ <td class="star-table__select"></td>
2804
+ }
2805
+ @for (column of visibleColumns(); track column.field) {
2806
+ <td
2807
+ [class.star-table__cell--frozen]="column.frozen"
2808
+ [style.inset-inline-start]="frozenOffset(column)"
2809
+ [attr.data-label]="column.filter ? column.header : null"
2810
+ >
2811
+ @if (column.filter === 'select') {
2812
+ <select
2813
+ class="star-input star-input--sm star-table__filter"
2814
+ [attr.aria-label]="text.filterBy(column.header)"
2815
+ (change)="setFilter(column.field, $any($event.target).value)"
2816
+ >
2817
+ <option value="" [selected]="!filterValue(column.field)">
2818
+ {{ text.filterAll }}
2819
+ </option>
2820
+ @for (option of filterChoices(column); track option) {
2821
+ <option [value]="option" [selected]="option === filterValue(column.field)">
2822
+ {{ option }}
2823
+ </option>
2824
+ }
2825
+ </select>
2826
+ } @else if (column.filter === 'text') {
2827
+ <input
2828
+ type="search"
2829
+ class="star-input star-input--sm star-table__filter"
2830
+ [attr.aria-label]="text.filterBy(column.header)"
2831
+ [value]="filterValue(column.field)"
2832
+ (input)="setFilter(column.field, $any($event.target).value)"
2833
+ />
2834
+ } @else if (column.filter === 'multiselect') {
2835
+ <star-multi-select
2836
+ class="star-table__filter"
2837
+ size="sm"
2838
+ [options]="filterChoices(column)"
2839
+ [value]="filterList(column.field)"
2840
+ [placeholder]="text.filterAll"
2841
+ [ariaLabel]="text.filterBy(column.header)"
2842
+ (valueChange)="setFilter(column.field, $event)"
2843
+ />
2844
+ } @else if (column.filter === 'number' || column.filter === 'date') {
2845
+ <span class="star-table__filter-range">
2846
+ <input
2847
+ class="star-input star-input--sm star-table__filter"
2848
+ [type]="column.filter"
2849
+ [attr.aria-label]="text.filterMin(column.header)"
2850
+ [attr.placeholder]="column.filter === 'number' ? text.filterMinShort : null"
2851
+ [value]="filterBound(column.field, 'min')"
2852
+ (input)="setBound(column, 'min', $any($event.target).value)"
2853
+ />
2854
+ <input
2855
+ class="star-input star-input--sm star-table__filter"
2856
+ [type]="column.filter"
2857
+ [attr.aria-label]="text.filterMax(column.header)"
2858
+ [attr.placeholder]="column.filter === 'number' ? text.filterMaxShort : null"
2859
+ [value]="filterBound(column.field, 'max')"
2860
+ (input)="setBound(column, 'max', $any($event.target).value)"
2861
+ />
2862
+ </span>
2863
+ }
2864
+ </td>
2865
+ }
2866
+ </tr>
2867
+ }
2868
+ </thead>
2869
+ <tbody #body>
2870
+ @if (loading()) {
2871
+ @for (row of skeletonRows(); track row) {
2872
+ <tr class="star-table__row">
2873
+ @if (reorderableRows()) {
2874
+ <td class="star-table__reorder"></td>
2875
+ }
2876
+ @if (expandable()) {
2877
+ <td class="star-table__expander"></td>
2878
+ }
2879
+ @if (selectionMode()) {
2880
+ <td class="star-table__select"><star-skeleton size="1.25rem" /></td>
2881
+ }
2882
+ @for (column of visibleColumns(); track column.field) {
2883
+ <td><star-skeleton height="0.875rem" [width]="row % 2 ? '70%' : '90%'" /></td>
2884
+ }
2885
+ </tr>
2886
+ }
2887
+ } @else {
2888
+ @for (entry of bodyEntries(); track entry.key) {
2889
+ @if (entry.kind === 'spacer') {
2890
+ <tr class="star-table__spacer" aria-hidden="true">
2891
+ <td [attr.colspan]="colspan()" [style.height.px]="entry.height"></td>
2892
+ </tr>
2893
+ } @else if (entry.kind === 'group') {
2894
+ @let group = entry;
2895
+ <tr
2896
+ class="star-table__group"
2897
+ [attr.aria-rowindex]="group.aria"
2898
+ [attr.data-vi]="group.item"
2899
+ >
2900
+ <th [attr.colspan]="colspan()" scope="colgroup">
2901
+ <button
2902
+ type="button"
2903
+ class="star-table__group-toggle"
2904
+ [attr.aria-expanded]="!isGroupCollapsed(group.label)"
2905
+ (click)="toggleGroup(group.label)"
2906
+ >
2907
+ <i class="ph-bold ph-caret-down" aria-hidden="true"></i>
2908
+ {{ group.label }}
2909
+ <span class="star-table__group-count">{{ group.count }}</span>
2910
+ </button>
2911
+ </th>
2912
+ </tr>
2913
+ } @else {
2914
+ @let row = entry.row;
2915
+ @let i = entry.index;
2916
+ <tr
2917
+ [attr.aria-rowindex]="entry.aria"
2918
+ [attr.data-vi]="entry.item"
2919
+ [hidden]="isRowCollapsed(row)"
2920
+ class="star-table__row"
2921
+ [class.star-table__row--alt]="i % 2 === 1"
2922
+ [class.star-table__row--selected]="isSelected(row)"
2923
+ [class.star-table__row--clickable]="clickable()"
2924
+ [class.star-table__row--expanded]="expandable() && isExpanded(row)"
2925
+ [attr.aria-selected]="selectionMode() ? isSelected(row) : null"
2926
+ (click)="onRowClick(row, $event)"
2927
+ >
2928
+ @if (reorderableRows()) {
2929
+ <td class="star-table__reorder">
2930
+ <button
2931
+ type="button"
2932
+ class="star-table__toggle"
2933
+ [disabled]="!canMoveRow(row, -1)"
2934
+ [attr.aria-label]="text.moveUp"
2935
+ (click)="moveRow(row, -1)"
2936
+ >
2937
+ <i class="ph-bold ph-arrow-up" aria-hidden="true"></i>
2938
+ </button>
2939
+ <button
2940
+ type="button"
2941
+ class="star-table__toggle"
2942
+ [disabled]="!canMoveRow(row, 1)"
2943
+ [attr.aria-label]="text.moveDown"
2944
+ (click)="moveRow(row, 1)"
2945
+ >
2946
+ <i class="ph-bold ph-arrow-down" aria-hidden="true"></i>
2947
+ </button>
2948
+ </td>
2949
+ }
2950
+ @if (expandable()) {
2951
+ <td class="star-table__expander">
2952
+ <button
2953
+ type="button"
2954
+ class="star-table__toggle"
2955
+ [attr.aria-expanded]="isExpanded(row)"
2956
+ [attr.aria-controls]="isExpanded(row) ? detailId(i) : null"
2957
+ [attr.aria-label]="isExpanded(row) ? text.collapseRow : text.expandRow"
2958
+ (click)="toggleExpansion(row)"
2959
+ >
2960
+ <i class="ph-bold ph-caret-right" aria-hidden="true"></i>
2961
+ </button>
2962
+ </td>
2963
+ }
2964
+ @if (selectionMode() === 'multiple') {
2965
+ <td class="star-table__select">
2966
+ <star-checkbox
2967
+ [checked]="isSelected(row)"
2968
+ [ariaLabel]="text.selectRow"
2969
+ (checkedChange)="toggleRow(row)"
2970
+ (click)="$event.stopPropagation()"
2971
+ />
2972
+ </td>
2973
+ } @else if (selectionMode() === 'single') {
2974
+ <td class="star-table__select">
2975
+ <input
2976
+ type="radio"
2977
+ class="star-table__radio"
2978
+ [name]="radioName"
2979
+ [checked]="isSelected(row)"
2980
+ [attr.aria-label]="text.selectRow"
2981
+ (change)="selectOnly(row)"
2982
+ (click)="$event.stopPropagation()"
2983
+ />
2984
+ </td>
2985
+ }
2986
+ @for (column of visibleColumns(); track column.field) {
2987
+ <td
2988
+ [class]="'star-table__cell--' + (column.align ?? 'start')"
2989
+ [class.star-table__cell--frozen]="column.frozen"
2990
+ [style.inset-inline-start]="frozenOffset(column)"
2991
+ [attr.data-label]="column.header"
2992
+ >
2993
+ @if (isEditing(row, column)) {
2994
+ @if (column.editor === 'select') {
2995
+ <select
2996
+ class="star-input star-input--sm star-table__editor"
2997
+ [attr.aria-label]="text.editCell(column.header)"
2998
+ (change)="commitEdit(row, column, $any($event.target).value)"
2999
+ (blur)="commitEdit(row, column, $any($event.target).value)"
3000
+ (keydown.escape)="cancelEdit($event)"
3001
+ >
3002
+ @for (option of column.editOptions ?? []; track option) {
3003
+ <option
3004
+ [value]="option"
3005
+ [selected]="option === cellText(row, column)"
3006
+ >
3007
+ {{ option }}
3008
+ </option>
3009
+ }
3010
+ </select>
3011
+ } @else {
3012
+ <input
3013
+ class="star-input star-input--sm star-table__editor"
3014
+ [type]="column.editor === 'number' ? 'number' : 'text'"
3015
+ [attr.aria-label]="text.editCell(column.header)"
3016
+ [value]="editText(row, column)"
3017
+ (blur)="commitEdit(row, column, $any($event.target).value)"
3018
+ (keydown.enter)="commitEdit(row, column, $any($event.target).value)"
3019
+ (keydown.escape)="cancelEdit($event)"
3020
+ />
3021
+ }
3022
+ } @else if (isEditable(row, column)) {
3023
+ <button
3024
+ type="button"
3025
+ class="star-table__edit"
3026
+ [attr.data-edit]="editKey(row, column)"
3027
+ (click)="startEdit(row, column)"
3028
+ >
3029
+ <!-- The name is the action and the visible value (WCAG 2.5.3). -->
3030
+ <span class="star-sr-only">{{ text.editCell(column.header) }}: </span>
3031
+ <span class="star-table__edit-value">
3032
+ <ng-container
3033
+ *ngTemplateOutlet="
3034
+ cell;
3035
+ context: { $implicit: row, column, index: i }
3036
+ "
3037
+ />
3038
+ </span>
3039
+ <i class="ph-bold ph-pencil-simple" aria-hidden="true"></i>
3040
+ </button>
3041
+ } @else {
3042
+ <ng-container
3043
+ *ngTemplateOutlet="cell; context: { $implicit: row, column, index: i }"
3044
+ />
3045
+ }
3046
+ </td>
3047
+ }
3048
+ </tr>
3049
+ @if (expansionTemplate(); as detail) {
3050
+ @if (isExpanded(row) && !isRowCollapsed(row)) {
3051
+ <tr
3052
+ class="star-table__expansion"
3053
+ [id]="detailId(i)"
3054
+ [attr.aria-rowindex]="entry.aria === null ? null : entry.aria + 1"
3055
+ [attr.data-vi]="entry.item"
3056
+ >
3057
+ <td [attr.colspan]="colspan()">
3058
+ <ng-container
3059
+ *ngTemplateOutlet="detail; context: { $implicit: row, index: i }"
3060
+ />
3061
+ </td>
3062
+ </tr>
3063
+ }
3064
+ }
3065
+ }
3066
+ } @empty {
3067
+ <tr>
3068
+ <td class="star-table__empty" [attr.colspan]="colspan()">
3069
+ <i class="ph-bold ph-tray" aria-hidden="true"></i>
3070
+ {{ emptyMessage() ?? text.noData }}
3071
+ </td>
3072
+ </tr>
3073
+ }
3074
+ }
3075
+ </tbody>
3076
+ @if (hasFooter()) {
3077
+ <tfoot>
3078
+ <tr
3079
+ class="star-table__footer"
3080
+ [attr.aria-rowindex]="virtualScroll() ? ariaRowCount() : null"
3081
+ >
3082
+ @if (reorderableRows()) {
3083
+ <td class="star-table__reorder"></td>
3084
+ }
3085
+ @if (expandable()) {
3086
+ <td class="star-table__expander"></td>
3087
+ }
3088
+ @if (selectionMode()) {
3089
+ <td class="star-table__select"></td>
3090
+ }
3091
+ @for (column of visibleColumns(); track column.field) {
3092
+ <td
3093
+ [class]="'star-table__cell--' + (column.align ?? 'start')"
3094
+ [attr.data-label]="footerText(column) ? column.header : null"
3095
+ >
3096
+ {{ footerText(column) }}
3097
+ </td>
3098
+ }
3099
+ </tr>
3100
+ </tfoot>
3101
+ }
3102
+ </table>
3103
+ </div>
3104
+ <ng-template #cell let-row let-column="column" let-i="index">
3105
+ @if (cellTemplate(column.field); as custom) {
3106
+ <ng-container
3107
+ *ngTemplateOutlet="
3108
+ custom;
3109
+ context: { $implicit: row, value: cellValue(row, column), index: i }
3110
+ "
3111
+ />
3112
+ } @else {
3113
+ {{ cellText(row, column) }}
3114
+ }
3115
+ </ng-template>
3116
+ @if (paginator()) {
3117
+ <star-paginator
3118
+ [ariaLabel]="ariaLabel() ? text.pagination + ': ' + ariaLabel() : null"
3119
+ [totalRecords]="total()"
3120
+ [(first)]="first"
3121
+ [(rows)]="rows"
3122
+ [rowsPerPageOptions]="rowsPerPageOptions()"
3123
+ (pageChange)="emitLazy()"
3124
+ />
3125
+ }
3126
+ `
3127
+ }]
3128
+ }],
3129
+ ctorParameters: () => [],
3130
+ propDecorators: {
3131
+ value: [{
3132
+ type: i0.Input,
3133
+ args: [{
3134
+ isSignal: true,
3135
+ alias: "value",
3136
+ required: true
3137
+ }]
3138
+ }],
3139
+ columns: [{
3140
+ type: i0.Input,
3141
+ args: [{
3142
+ isSignal: true,
3143
+ alias: "columns",
3144
+ required: true
3145
+ }]
3146
+ }],
3147
+ dataKey: [{
3148
+ type: i0.Input,
3149
+ args: [{
3150
+ isSignal: true,
3151
+ alias: "dataKey",
3152
+ required: false
3153
+ }]
3154
+ }],
3155
+ loading: [{
3156
+ type: i0.Input,
3157
+ args: [{
3158
+ isSignal: true,
3159
+ alias: "loading",
3160
+ required: false
3161
+ }]
3162
+ }],
3163
+ emptyMessage: [{
3164
+ type: i0.Input,
3165
+ args: [{
3166
+ isSignal: true,
3167
+ alias: "emptyMessage",
3168
+ required: false
3169
+ }]
3170
+ }],
3171
+ striped: [{
3172
+ type: i0.Input,
3173
+ args: [{
3174
+ isSignal: true,
3175
+ alias: "striped",
3176
+ required: false
3177
+ }]
3178
+ }],
3179
+ size: [{
3180
+ type: i0.Input,
3181
+ args: [{
3182
+ isSignal: true,
3183
+ alias: "size",
3184
+ required: false
3185
+ }]
3186
+ }],
3187
+ stickyHeader: [{
3188
+ type: i0.Input,
3189
+ args: [{
3190
+ isSignal: true,
3191
+ alias: "stickyHeader",
3192
+ required: false
3193
+ }]
3194
+ }],
3195
+ scrollHeight: [{
3196
+ type: i0.Input,
3197
+ args: [{
3198
+ isSignal: true,
3199
+ alias: "scrollHeight",
3200
+ required: false
3201
+ }]
3202
+ }],
3203
+ responsiveLayout: [{
3204
+ type: i0.Input,
3205
+ args: [{
3206
+ isSignal: true,
3207
+ alias: "responsiveLayout",
3208
+ required: false
3209
+ }]
3210
+ }],
3211
+ virtualScroll: [{
3212
+ type: i0.Input,
3213
+ args: [{
3214
+ isSignal: true,
3215
+ alias: "virtualScroll",
3216
+ required: false
3217
+ }]
3218
+ }],
3219
+ virtualRowHeight: [{
3220
+ type: i0.Input,
3221
+ args: [{
3222
+ isSignal: true,
3223
+ alias: "virtualRowHeight",
3224
+ required: false
3225
+ }]
3226
+ }],
3227
+ virtualRowHeights: [{
3228
+ type: i0.Input,
3229
+ args: [{
3230
+ isSignal: true,
3231
+ alias: "virtualRowHeights",
3232
+ required: false
3233
+ }]
3234
+ }],
3235
+ ariaLabel: [{
3236
+ type: i0.Input,
3237
+ args: [{
3238
+ isSignal: true,
3239
+ alias: "ariaLabel",
3240
+ required: false
3241
+ }]
3242
+ }],
3243
+ paginator: [{
3244
+ type: i0.Input,
3245
+ args: [{
3246
+ isSignal: true,
3247
+ alias: "paginator",
3248
+ required: false
3249
+ }]
3250
+ }],
3251
+ first: [{
3252
+ type: i0.Input,
3253
+ args: [{
3254
+ isSignal: true,
3255
+ alias: "first",
3256
+ required: false
3257
+ }]
3258
+ }, {
3259
+ type: i0.Output,
3260
+ args: ["firstChange"]
3261
+ }],
3262
+ rows: [{
3263
+ type: i0.Input,
3264
+ args: [{
3265
+ isSignal: true,
3266
+ alias: "rows",
3267
+ required: false
3268
+ }]
3269
+ }, {
3270
+ type: i0.Output,
3271
+ args: ["rowsChange"]
3272
+ }],
3273
+ rowsPerPageOptions: [{
3274
+ type: i0.Input,
3275
+ args: [{
3276
+ isSignal: true,
3277
+ alias: "rowsPerPageOptions",
3278
+ required: false
3279
+ }]
3280
+ }],
3281
+ sortField: [{
3282
+ type: i0.Input,
3283
+ args: [{
3284
+ isSignal: true,
3285
+ alias: "sortField",
3286
+ required: false
3287
+ }]
3288
+ }, {
3289
+ type: i0.Output,
3290
+ args: ["sortFieldChange"]
3291
+ }],
3292
+ sortOrder: [{
3293
+ type: i0.Input,
3294
+ args: [{
3295
+ isSignal: true,
3296
+ alias: "sortOrder",
3297
+ required: false
3298
+ }]
3299
+ }, {
3300
+ type: i0.Output,
3301
+ args: ["sortOrderChange"]
3302
+ }],
3303
+ globalFilter: [{
3304
+ type: i0.Input,
3305
+ args: [{
3306
+ isSignal: true,
3307
+ alias: "globalFilter",
3308
+ required: false
3309
+ }]
3310
+ }],
3311
+ filters: [{
3312
+ type: i0.Input,
3313
+ args: [{
3314
+ isSignal: true,
3315
+ alias: "filters",
3316
+ required: false
3317
+ }]
3318
+ }, {
3319
+ type: i0.Output,
3320
+ args: ["filtersChange"]
3321
+ }],
3322
+ lazy: [{
3323
+ type: i0.Input,
3324
+ args: [{
3325
+ isSignal: true,
3326
+ alias: "lazy",
3327
+ required: false
3328
+ }]
3329
+ }],
3330
+ totalRecords: [{
3331
+ type: i0.Input,
3332
+ args: [{
3333
+ isSignal: true,
3334
+ alias: "totalRecords",
3335
+ required: false
3336
+ }]
3337
+ }],
3338
+ selectionMode: [{
3339
+ type: i0.Input,
3340
+ args: [{
3341
+ isSignal: true,
3342
+ alias: "selectionMode",
3343
+ required: false
3344
+ }]
3345
+ }],
3346
+ selection: [{
3347
+ type: i0.Input,
3348
+ args: [{
3349
+ isSignal: true,
3350
+ alias: "selection",
3351
+ required: false
3352
+ }]
3353
+ }, {
3354
+ type: i0.Output,
3355
+ args: ["selectionChange"]
3356
+ }],
3357
+ expandedKeys: [{
3358
+ type: i0.Input,
3359
+ args: [{
3360
+ isSignal: true,
3361
+ alias: "expandedKeys",
3362
+ required: false
3363
+ }]
3364
+ }, {
3365
+ type: i0.Output,
3366
+ args: ["expandedKeysChange"]
3367
+ }],
3368
+ rowExpandMode: [{
3369
+ type: i0.Input,
3370
+ args: [{
3371
+ isSignal: true,
3372
+ alias: "rowExpandMode",
3373
+ required: false
3374
+ }]
3375
+ }],
3376
+ columnToggle: [{
3377
+ type: i0.Input,
3378
+ args: [{
3379
+ isSignal: true,
3380
+ alias: "columnToggle",
3381
+ required: false
3382
+ }]
3383
+ }],
3384
+ reorderableColumns: [{
3385
+ type: i0.Input,
3386
+ args: [{
3387
+ isSignal: true,
3388
+ alias: "reorderableColumns",
3389
+ required: false
3390
+ }]
3391
+ }],
3392
+ resizableColumns: [{
3393
+ type: i0.Input,
3394
+ args: [{
3395
+ isSignal: true,
3396
+ alias: "resizableColumns",
3397
+ required: false
3398
+ }]
3399
+ }],
3400
+ columnOrder: [{
3401
+ type: i0.Input,
3402
+ args: [{
3403
+ isSignal: true,
3404
+ alias: "columnOrder",
3405
+ required: false
3406
+ }]
3407
+ }, {
3408
+ type: i0.Output,
3409
+ args: ["columnOrderChange"]
3410
+ }],
3411
+ hiddenColumns: [{
3412
+ type: i0.Input,
3413
+ args: [{
3414
+ isSignal: true,
3415
+ alias: "hiddenColumns",
3416
+ required: false
3417
+ }]
3418
+ }, {
3419
+ type: i0.Output,
3420
+ args: ["hiddenColumnsChange"]
3421
+ }],
3422
+ columnWidths: [{
3423
+ type: i0.Input,
3424
+ args: [{
3425
+ isSignal: true,
3426
+ alias: "columnWidths",
3427
+ required: false
3428
+ }]
3429
+ }, {
3430
+ type: i0.Output,
3431
+ args: ["columnWidthsChange"]
3432
+ }],
3433
+ multiSort: [{
3434
+ type: i0.Input,
3435
+ args: [{
3436
+ isSignal: true,
3437
+ alias: "multiSort",
3438
+ required: false
3439
+ }]
3440
+ }],
3441
+ sortMeta: [{
3442
+ type: i0.Input,
3443
+ args: [{
3444
+ isSignal: true,
3445
+ alias: "sortMeta",
3446
+ required: false
3447
+ }]
3448
+ }, {
3449
+ type: i0.Output,
3450
+ args: ["sortMetaChange"]
3451
+ }],
3452
+ groupBy: [{
3453
+ type: i0.Input,
3454
+ args: [{
3455
+ isSignal: true,
3456
+ alias: "groupBy",
3457
+ required: false
3458
+ }]
3459
+ }],
3460
+ collapsedGroups: [{
3461
+ type: i0.Input,
3462
+ args: [{
3463
+ isSignal: true,
3464
+ alias: "collapsedGroups",
3465
+ required: false
3466
+ }]
3467
+ }, {
3468
+ type: i0.Output,
3469
+ args: ["collapsedGroupsChange"]
3470
+ }],
3471
+ reorderableRows: [{
3472
+ type: i0.Input,
3473
+ args: [{
3474
+ isSignal: true,
3475
+ alias: "reorderableRows",
3476
+ required: false
3477
+ }]
3478
+ }],
3479
+ stateKey: [{
3480
+ type: i0.Input,
3481
+ args: [{
3482
+ isSignal: true,
3483
+ alias: "stateKey",
3484
+ required: false
3485
+ }]
3486
+ }],
3487
+ stateStorage: [{
3488
+ type: i0.Input,
3489
+ args: [{
3490
+ isSignal: true,
3491
+ alias: "stateStorage",
3492
+ required: false
3493
+ }]
3494
+ }],
3495
+ rowClick: [{
3496
+ type: i0.Output,
3497
+ args: ["rowClick"]
3498
+ }],
3499
+ rowReorder: [{
3500
+ type: i0.Output,
3501
+ args: ["rowReorder"]
3502
+ }],
3503
+ cellEdit: [{
3504
+ type: i0.Output,
3505
+ args: ["cellEdit"]
3506
+ }],
3507
+ lazyLoad: [{
3508
+ type: i0.Output,
3509
+ args: ["lazyLoad"]
3510
+ }],
3511
+ cellTemplates: [{
3512
+ type: i0.ContentChildren,
3513
+ args: [i0.forwardRef(() => StarCellTemplate), { isSignal: true }]
3514
+ }],
3515
+ expansion: [{
3516
+ type: i0.ContentChild,
3517
+ args: [i0.forwardRef(() => StarRowExpansionTemplate), { isSignal: true }]
3518
+ }],
3519
+ scroller: [{
3520
+ type: i0.ViewChild,
3521
+ args: ["scroller", { isSignal: true }]
3522
+ }],
3523
+ body: [{
3524
+ type: i0.ViewChild,
3525
+ args: ["body", { isSignal: true }]
3526
+ }]
3527
+ }
3528
+ });
3529
+ export { PRINT_FIT_STEPS, PRINT_STYLE, StarCellTemplate, StarRowExpansionTemplate, StarTable, addPrintStyle, buildPrintDocument, buildXlsx, fitPrintDocument, printColumnAlign, printContext, printFitStyle, stylePrintDocument };
3530
+
3531
+ //# sourceMappingURL=star-ng-ui-table.mjs.map