@star-ng/ui 0.0.0-stage → 0.1.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 +148 -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 +782 -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 +392 -0
  22. package/fesm2022/star-ng-ui-core.mjs.map +1 -0
  23. package/fesm2022/star-ng-ui-data-display.mjs +1556 -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 +978 -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 +2523 -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 +3477 -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 +281 -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 +118 -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 +5803 -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 +310 -0
  173. package/types/star-ng-ui-data-display.d.ts +339 -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 +197 -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 +540 -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 +829 -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 +310 -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,1446 @@
1
+ import { _IdGenerator } from "@angular/cdk/a11y";
2
+ import { CdkConnectedOverlay, CdkOverlayOrigin } from "@angular/cdk/overlay";
3
+ import { CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport } from "@angular/cdk/scrolling";
4
+ import { DOCUMENT, NgTemplateOutlet } from "@angular/common";
5
+ import * as i0 from "@angular/core";
6
+ import { ChangeDetectionStrategy, Component, ElementRef, afterEveryRender, afterRenderEffect, booleanAttribute, computed, effect, inject, input, linkedSignal, model, numberAttribute, output, signal, untracked, viewChild } from "@angular/core";
7
+ import { STAR_UI_TEXT, StarDirectionService, matchesFilter, starInlineKey } from "@star-ng/ui/core";
8
+ function flattenVisible(nodes, open, openAll = false) {
9
+ const rows = [];
10
+ const walk = (list, level, parentKey) => {
11
+ const setSize = list.length;
12
+ list.forEach((node, i) => {
13
+ rows.push({
14
+ node,
15
+ level,
16
+ setSize,
17
+ position: i + 1,
18
+ parentKey
19
+ });
20
+ if (node.children?.length && (openAll || open.has(node.key))) walk(node.children, level + 1, node.key);
21
+ });
22
+ };
23
+ walk(nodes, 1, null);
24
+ return rows;
25
+ }
26
+ function rowIndexOf(rows) {
27
+ const map = /* @__PURE__ */ new Map();
28
+ rows.forEach((row, i) => map.set(row.node.key, i));
29
+ return map;
30
+ }
31
+ function subtreeKeys(node) {
32
+ const keys = [];
33
+ const walk = (current) => {
34
+ keys.push(current.key);
35
+ current.children?.forEach(walk);
36
+ };
37
+ walk(node);
38
+ return keys;
39
+ }
40
+ function parentsOf(nodes) {
41
+ const map = /* @__PURE__ */ new Map();
42
+ const walk = (list, parent) => list.forEach((node) => {
43
+ map.set(node.key, parent);
44
+ if (node.children) walk(node.children, node.key);
45
+ });
46
+ walk(nodes, null);
47
+ return map;
48
+ }
49
+ function stillFocusable(previous, rowIndex, parents, firstKey) {
50
+ let key = previous ?? null;
51
+ while (key !== null) {
52
+ if (rowIndex.has(key)) return key;
53
+ key = parents.get(key) ?? null;
54
+ }
55
+ return firstKey;
56
+ }
57
+ function navigationTarget(rows, index, key, state) {
58
+ const row = rows[index];
59
+ if (!row) return null;
60
+ switch (key) {
61
+ case "ArrowDown": return rows[index + 1]?.node.key ?? null;
62
+ case "ArrowUp": return rows[index - 1]?.node.key ?? null;
63
+ case "Home": return rows[0]?.node.key ?? null;
64
+ case "End": return rows.at(-1)?.node.key ?? null;
65
+ case "ArrowRight": return state.hasChildren && state.expanded ? rows[index + 1]?.node.key ?? null : null;
66
+ case "ArrowLeft": return state.hasChildren && state.expanded ? null : row.parentKey;
67
+ default: return null;
68
+ }
69
+ }
70
+ function checkStates(nodes, selected, isLeaf) {
71
+ const states = /* @__PURE__ */ new Map();
72
+ const walk = (node) => {
73
+ if (!node.children?.length) {
74
+ states.set(node.key, selected.has(node.key));
75
+ const leaf = isLeaf(node.key);
76
+ return {
77
+ leaves: leaf ? 1 : 0,
78
+ checked: leaf && selected.has(node.key) ? 1 : 0
79
+ };
80
+ }
81
+ let leaves = 0;
82
+ let checked = 0;
83
+ for (const child of node.children) {
84
+ const part = walk(child);
85
+ leaves += part.leaves;
86
+ checked += part.checked;
87
+ }
88
+ states.set(node.key, checked === 0 ? false : checked === leaves ? true : "mixed");
89
+ return {
90
+ leaves,
91
+ checked
92
+ };
93
+ };
94
+ nodes.forEach(walk);
95
+ return states;
96
+ }
97
+ function scrollOffsetToReveal(index, itemSize, scrollOffset, viewportSize) {
98
+ const top = index * itemSize;
99
+ const bottom = top + itemSize;
100
+ if (top < scrollOffset) return top;
101
+ if (bottom > scrollOffset + viewportSize) return Math.max(0, bottom - viewportSize);
102
+ return null;
103
+ }
104
+ function filterNodes(nodes, query) {
105
+ if (!query) return [...nodes];
106
+ return nodes.flatMap((node) => {
107
+ const children = filterNodes(node.children ?? [], query);
108
+ return matchesFilter(node.label, query) || children.length ? [{
109
+ ...node,
110
+ children
111
+ }] : [];
112
+ });
113
+ }
114
+ var StarTree = class StarTree {
115
+ text = inject(STAR_UI_TEXT);
116
+ host = inject(ElementRef);
117
+ doc = inject(DOCUMENT);
118
+ value = model([], ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
119
+ nodes = input([], ...ngDevMode ? [{ debugName: "nodes" }] : /* istanbul ignore next */ []);
120
+ selectionMode = input(null, ...ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []);
121
+ expanded = model([], ...ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []);
122
+ filter = input(false, {
123
+ ...ngDevMode ? { debugName: "filter" } : /* istanbul ignore next */ {},
124
+ transform: booleanAttribute
125
+ });
126
+ scrollHeight = input(null, ...ngDevMode ? [{ debugName: "scrollHeight" }] : /* istanbul ignore next */ []);
127
+ virtualScroll = input(false, {
128
+ ...ngDevMode ? { debugName: "virtualScroll" } : /* istanbul ignore next */ {},
129
+ transform: booleanAttribute
130
+ });
131
+ virtualItemSize = input(34, {
132
+ ...ngDevMode ? { debugName: "virtualItemSize" } : /* istanbul ignore next */ {},
133
+ transform: numberAttribute
134
+ });
135
+ ariaLabel = input(null, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
136
+ disabled = input(false, {
137
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
138
+ transform: booleanAttribute
139
+ });
140
+ touch = output();
141
+ nodeSelect = output();
142
+ query = signal("", ...ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []);
143
+ viewport = viewChild(CdkVirtualScrollViewport, ...ngDevMode ? [{ debugName: "viewport" }] : /* istanbul ignore next */ []);
144
+ filtered = computed(() => filterNodes(this.nodes(), this.query()), ...ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []);
145
+ index = computed(() => {
146
+ const map = /* @__PURE__ */ new Map();
147
+ const walk = (nodes) => nodes.forEach((node) => {
148
+ map.set(node.key, node);
149
+ walk(node.children ?? []);
150
+ });
151
+ walk(this.nodes());
152
+ return map;
153
+ }, ...ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []);
154
+ parents = computed(() => parentsOf(this.nodes()), ...ngDevMode ? [{ debugName: "parents" }] : /* istanbul ignore next */ []);
155
+ openKeys = computed(() => new Set(this.expanded()), ...ngDevMode ? [{ debugName: "openKeys" }] : /* istanbul ignore next */ []);
156
+ selectedKeys = computed(() => new Set(this.value()), ...ngDevMode ? [{ debugName: "selectedKeys" }] : /* istanbul ignore next */ []);
157
+ visible = computed(() => flattenVisible(this.filtered(), this.openKeys(), !!this.query()), ...ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []);
158
+ rowIndex = computed(() => rowIndexOf(this.visible()), ...ngDevMode ? [{ debugName: "rowIndex" }] : /* istanbul ignore next */ []);
159
+ checkMap = computed(() => this.selectionMode() === "checkbox" ? checkStates(this.filtered(), this.selectedKeys(), (key) => this.isLeaf(key)) : /* @__PURE__ */ new Map(), ...ngDevMode ? [{ debugName: "checkMap" }] : /* istanbul ignore next */ []);
160
+ focusKey = linkedSignal({
161
+ ...ngDevMode ? { debugName: "focusKey" } : /* istanbul ignore next */ {},
162
+ source: this.visible,
163
+ computation: (rows, previous) => stillFocusable(previous?.value, this.rowIndex(), this.parents(), rows[0]?.node.key ?? null)
164
+ });
165
+ windowed = computed(() => this.virtualScroll() && !!this.scrollHeight() && this.virtualItemSize() > 0, ...ngDevMode ? [{ debugName: "windowed" }] : /* istanbul ignore next */ []);
166
+ showViewport = computed(() => this.windowed() && this.visible().length > 0, ...ngDevMode ? [{ debugName: "showViewport" }] : /* istanbul ignore next */ []);
167
+ viewportHeight = computed(() => `min(${this.visible().length * this.virtualItemSize()}px, ${this.scrollHeight()})`, ...ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []);
168
+ range = signal({
169
+ start: 0,
170
+ end: 0
171
+ }, ...ngDevMode ? [{ debugName: "range" }] : /* istanbul ignore next */ []);
172
+ activeRendered = computed(() => {
173
+ const index = this.rowIndex().get(this.focusKey() ?? "");
174
+ const { start, end } = this.range();
175
+ return index !== void 0 && index >= start && index < end;
176
+ }, ...ngDevMode ? [{ debugName: "activeRendered" }] : /* istanbul ignore next */ []);
177
+ multiselectable = computed(() => this.selectionMode() !== "single" && this.selectionMode() !== null ? true : null, ...ngDevMode ? [{ debugName: "multiselectable" }] : /* istanbul ignore next */ []);
178
+ pendingFocus = null;
179
+ parked = false;
180
+ trackRow = (_, row) => row.node.key;
181
+ constructor() {
182
+ effect((onCleanup) => {
183
+ const viewport = this.viewport();
184
+ if (!viewport) {
185
+ this.range.set({
186
+ start: 0,
187
+ end: 0
188
+ });
189
+ return;
190
+ }
191
+ this.range.set({ ...viewport.getRenderedRange() });
192
+ const subscription = viewport.renderedRangeStream.subscribe((range) => {
193
+ this.parkFocus(range);
194
+ this.range.set({ ...range });
195
+ });
196
+ onCleanup(() => subscription.unsubscribe());
197
+ });
198
+ effect(() => {
199
+ this.visible();
200
+ untracked(() => {
201
+ const viewport = this.viewport();
202
+ if (viewport) this.parkFocus(viewport.getRenderedRange());
203
+ });
204
+ });
205
+ afterRenderEffect(() => {
206
+ this.viewportHeight();
207
+ this.viewport()?.checkViewportSize();
208
+ });
209
+ afterEveryRender(() => {
210
+ this.applyPendingFocus();
211
+ if (this.parked) this.restoreParkedFocus();
212
+ });
213
+ }
214
+ isExpanded(node) {
215
+ return !!this.query() || this.openKeys().has(node.key);
216
+ }
217
+ toggle(node, open = !this.isExpanded(node)) {
218
+ this.expanded.update((keys) => {
219
+ if (!open) return keys.filter((k) => k !== node.key);
220
+ return keys.includes(node.key) ? keys : [...keys, node.key];
221
+ });
222
+ }
223
+ isSelected(node) {
224
+ return this.selectedKeys().has(node.key);
225
+ }
226
+ checkState(node) {
227
+ const known = this.checkMap().get(node.key);
228
+ if (known !== void 0) return known;
229
+ if (!node.children?.length) return this.isSelected(node);
230
+ return checkStates([node], this.selectedKeys(), (key) => this.isLeaf(key)).get(node.key) ?? false;
231
+ }
232
+ select(node) {
233
+ const mode = this.selectionMode();
234
+ if (!mode || this.disabled() || node.disabled || node.selectable === false) return;
235
+ if (mode === "single") this.value.set([node.key]);
236
+ else if (mode === "multiple") this.value.update((keys) => keys.includes(node.key) ? keys.filter((k) => k !== node.key) : [...keys, node.key]);
237
+ else {
238
+ const branch = subtreeKeys(node);
239
+ const inBranch = new Set(branch);
240
+ const on = this.checkState(node) !== true;
241
+ this.value.update((keys) => {
242
+ const rest = keys.filter((k) => !inBranch.has(k));
243
+ return on ? [...rest, ...branch.filter((key) => this.isLeaf(key))] : rest;
244
+ });
245
+ }
246
+ this.nodeSelect.emit(node);
247
+ }
248
+ onClick(node, event) {
249
+ this.focusKey.set(node.key);
250
+ event.currentTarget.focus();
251
+ if (this.selectionMode()) this.select(node);
252
+ else if (node.children?.length) this.toggle(node);
253
+ }
254
+ onRowFocus(key) {
255
+ this.focusKey.set(key);
256
+ this.pendingFocus = null;
257
+ this.parked = false;
258
+ }
259
+ focusRow(key) {
260
+ if (!key) return;
261
+ this.focusKey.set(key);
262
+ this.pendingFocus = key;
263
+ if (this.showViewport()) this.revealRow(key);
264
+ queueMicrotask(() => this.applyPendingFocus());
265
+ }
266
+ revealRow(key) {
267
+ const viewport = this.viewport();
268
+ const index = this.rowIndex().get(key);
269
+ if (!viewport || index === void 0) return;
270
+ const offset = scrollOffsetToReveal(index, this.virtualItemSize(), viewport.measureScrollOffset(), viewport.getViewportSize());
271
+ if (offset !== null) viewport.scrollToOffset(offset);
272
+ }
273
+ rowElement(key) {
274
+ return this.host.nativeElement.querySelector(`[data-key="${CSS.escape(key)}"]`);
275
+ }
276
+ applyPendingFocus() {
277
+ const key = this.pendingFocus;
278
+ if (key === null) return;
279
+ if (!this.rowIndex().has(key)) {
280
+ this.pendingFocus = null;
281
+ return;
282
+ }
283
+ const row = this.rowElement(key);
284
+ if (!row) return;
285
+ this.pendingFocus = null;
286
+ row.focus({ preventScroll: this.windowed() });
287
+ }
288
+ parkFocus(range) {
289
+ const viewport = this.viewport()?.elementRef.nativeElement;
290
+ const active = this.doc.activeElement;
291
+ if (!viewport || !active || active === viewport || !viewport.contains(active)) return;
292
+ const key = active.closest("[data-key]")?.dataset["key"];
293
+ const index = key === void 0 ? void 0 : this.rowIndex().get(key);
294
+ if (index !== void 0 && index >= range.start && index < range.end) return;
295
+ this.parked = true;
296
+ viewport.focus({ preventScroll: true });
297
+ }
298
+ restoreParkedFocus() {
299
+ const viewport = this.viewport()?.elementRef.nativeElement;
300
+ if (!viewport || this.doc.activeElement !== viewport) {
301
+ this.parked = false;
302
+ return;
303
+ }
304
+ const key = this.focusKey();
305
+ if (key === null) return;
306
+ this.rowElement(key)?.focus({ preventScroll: true });
307
+ }
308
+ onViewportFocus() {
309
+ if (!this.parked) this.focusRow(this.focusKey());
310
+ }
311
+ onViewportKeydown(event) {
312
+ if (event.target !== event.currentTarget) return;
313
+ const row = this.visible()[this.rowIndex().get(this.focusKey() ?? "") ?? -1];
314
+ if (row) this.onKeydown(event, row);
315
+ }
316
+ onKeydown(event, row) {
317
+ const rows = this.visible();
318
+ const item = this.pendingFocus === null ? row : rows[this.rowIndex().get(this.pendingFocus) ?? -1] ?? row;
319
+ const index = this.rowIndex().get(item.node.key) ?? -1;
320
+ const hasChildren = !!item.node.children?.length;
321
+ const expanded = hasChildren && this.isExpanded(item.node);
322
+ const key = starInlineKey(event);
323
+ const target = () => navigationTarget(rows, index, key, {
324
+ hasChildren,
325
+ expanded
326
+ });
327
+ const handled = () => event.preventDefault();
328
+ switch (key) {
329
+ case "ArrowDown":
330
+ case "ArrowUp":
331
+ case "Home":
332
+ case "End":
333
+ handled();
334
+ return this.focusRow(target());
335
+ case "ArrowRight":
336
+ handled();
337
+ if (hasChildren && !expanded) this.toggle(item.node, true);
338
+ else this.focusRow(target());
339
+ return;
340
+ case "ArrowLeft":
341
+ handled();
342
+ if (expanded) this.toggle(item.node, false);
343
+ else this.focusRow(target());
344
+ return;
345
+ case "Enter":
346
+ case " ":
347
+ handled();
348
+ if (this.selectionMode()) this.select(item.node);
349
+ else if (hasChildren) this.toggle(item.node);
350
+ return;
351
+ case "*": {
352
+ handled();
353
+ const siblings = rows.filter((r) => r.parentKey === item.parentKey && r.node.children?.length).map((r) => r.node.key);
354
+ this.expanded.update((keys) => {
355
+ const open = new Set(keys);
356
+ const added = siblings.filter((key) => !open.has(key));
357
+ return added.length ? [...keys, ...added] : keys;
358
+ });
359
+ return;
360
+ }
361
+ }
362
+ }
363
+ labelFor(key) {
364
+ return this.index().get(key)?.label ?? key;
365
+ }
366
+ isLeaf(key) {
367
+ return !this.index().get(key)?.children?.length;
368
+ }
369
+ focus() {
370
+ this.focusRow(this.focusKey());
371
+ }
372
+ static ɵfac = i0.ɵɵngDeclareFactory({
373
+ minVersion: "12.0.0",
374
+ version: "22.2.6",
375
+ ngImport: i0,
376
+ type: StarTree,
377
+ deps: [],
378
+ target: i0.ɵɵFactoryTarget.Component
379
+ });
380
+ static ɵcmp = i0.ɵɵngDeclareComponent({
381
+ minVersion: "17.0.0",
382
+ version: "22.2.6",
383
+ type: StarTree,
384
+ isStandalone: true,
385
+ selector: "star-tree",
386
+ inputs: {
387
+ value: {
388
+ classPropertyName: "value",
389
+ publicName: "value",
390
+ isSignal: true,
391
+ isRequired: false,
392
+ transformFunction: null
393
+ },
394
+ nodes: {
395
+ classPropertyName: "nodes",
396
+ publicName: "nodes",
397
+ isSignal: true,
398
+ isRequired: false,
399
+ transformFunction: null
400
+ },
401
+ selectionMode: {
402
+ classPropertyName: "selectionMode",
403
+ publicName: "selectionMode",
404
+ isSignal: true,
405
+ isRequired: false,
406
+ transformFunction: null
407
+ },
408
+ expanded: {
409
+ classPropertyName: "expanded",
410
+ publicName: "expanded",
411
+ isSignal: true,
412
+ isRequired: false,
413
+ transformFunction: null
414
+ },
415
+ filter: {
416
+ classPropertyName: "filter",
417
+ publicName: "filter",
418
+ isSignal: true,
419
+ isRequired: false,
420
+ transformFunction: null
421
+ },
422
+ scrollHeight: {
423
+ classPropertyName: "scrollHeight",
424
+ publicName: "scrollHeight",
425
+ isSignal: true,
426
+ isRequired: false,
427
+ transformFunction: null
428
+ },
429
+ virtualScroll: {
430
+ classPropertyName: "virtualScroll",
431
+ publicName: "virtualScroll",
432
+ isSignal: true,
433
+ isRequired: false,
434
+ transformFunction: null
435
+ },
436
+ virtualItemSize: {
437
+ classPropertyName: "virtualItemSize",
438
+ publicName: "virtualItemSize",
439
+ isSignal: true,
440
+ isRequired: false,
441
+ transformFunction: null
442
+ },
443
+ ariaLabel: {
444
+ classPropertyName: "ariaLabel",
445
+ publicName: "ariaLabel",
446
+ isSignal: true,
447
+ isRequired: false,
448
+ transformFunction: null
449
+ },
450
+ disabled: {
451
+ classPropertyName: "disabled",
452
+ publicName: "disabled",
453
+ isSignal: true,
454
+ isRequired: false,
455
+ transformFunction: null
456
+ }
457
+ },
458
+ outputs: {
459
+ value: "valueChange",
460
+ expanded: "expandedChange",
461
+ touch: "touch",
462
+ nodeSelect: "nodeSelect"
463
+ },
464
+ host: { classAttribute: "star-tree" },
465
+ viewQueries: [{
466
+ propertyName: "viewport",
467
+ first: true,
468
+ predicate: CdkVirtualScrollViewport,
469
+ descendants: true,
470
+ isSignal: true
471
+ }],
472
+ ngImport: i0,
473
+ template: `
474
+ @if (filter()) {
475
+ <div class="star-panel__filter">
476
+ <i class="ph-bold ph-magnifying-glass" aria-hidden="true"></i>
477
+ <input
478
+ #filterInput
479
+ type="search"
480
+ class="star-input star-input--sm"
481
+ autocomplete="off"
482
+ [attr.aria-label]="text.filterPlaceholder"
483
+ [placeholder]="text.filterPlaceholder"
484
+ [value]="query()"
485
+ (input)="query.set(filterInput.value)"
486
+ />
487
+ </div>
488
+ }
489
+ <ng-template #row let-item>
490
+ <li
491
+ class="star-tree__item"
492
+ role="treeitem"
493
+ [attr.data-key]="item.node.key"
494
+ [attr.aria-level]="item.level"
495
+ [attr.aria-setsize]="item.setSize"
496
+ [attr.aria-posinset]="item.position"
497
+ [attr.aria-expanded]="item.node.children?.length ? isExpanded(item.node) : null"
498
+ [attr.aria-selected]="
499
+ selectionMode() && selectionMode() !== 'checkbox' ? isSelected(item.node) : null
500
+ "
501
+ [attr.aria-checked]="selectionMode() === 'checkbox' ? checkState(item.node) : null"
502
+ [attr.aria-disabled]="item.node.disabled || null"
503
+ [attr.tabindex]="focusKey() === item.node.key ? 0 : -1"
504
+ [class.star-tree__item--selected]="isSelected(item.node)"
505
+ [style.--star-tree-level]="item.level - 1"
506
+ [style.height.px]="showViewport() ? virtualItemSize() : null"
507
+ (click)="onClick(item.node, $event)"
508
+ (keydown)="onKeydown($event, item)"
509
+ (focus)="onRowFocus(item.node.key)"
510
+ >
511
+ @if (item.node.children?.length) {
512
+ <span
513
+ class="star-tree__toggle"
514
+ aria-hidden="true"
515
+ (click)="$event.stopPropagation(); toggle(item.node)"
516
+ >
517
+ <i class="ph-bold ph-caret-right"></i>
518
+ </span>
519
+ } @else {
520
+ <span class="star-tree__toggle star-tree__toggle--leaf" aria-hidden="true"></span>
521
+ }
522
+ @if (selectionMode() === 'checkbox') {
523
+ <span
524
+ class="star-check__box star-tree__check"
525
+ aria-hidden="true"
526
+ [class.star-tree__check--on]="checkState(item.node) !== false"
527
+ >
528
+ @if (checkState(item.node) === 'mixed') {
529
+ <i class="ph-bold ph-minus"></i>
530
+ } @else if (checkState(item.node) === true) {
531
+ <i class="ph-bold ph-check"></i>
532
+ }
533
+ </span>
534
+ }
535
+ @if (item.node.icon) {
536
+ <i class="star-tree__icon" [class]="item.node.icon" aria-hidden="true"></i>
537
+ }
538
+ <span class="star-tree__label">{{ item.node.label }}</span>
539
+ </li>
540
+ </ng-template>
541
+ @if (showViewport()) {
542
+ <cdk-virtual-scroll-viewport
543
+ #viewport
544
+ class="star-tree__viewport"
545
+ role="tree"
546
+ [itemSize]="virtualItemSize()"
547
+ [attr.aria-label]="ariaLabel()"
548
+ [attr.aria-multiselectable]="multiselectable()"
549
+ [attr.tabindex]="activeRendered() ? -1 : 0"
550
+ [style.height]="viewportHeight()"
551
+ (focus)="onViewportFocus()"
552
+ (blur)="parked = false"
553
+ (keydown)="onViewportKeydown($event)"
554
+ >
555
+ <ng-template
556
+ cdkVirtualFor
557
+ let-item
558
+ [cdkVirtualForOf]="visible()"
559
+ [cdkVirtualForTrackBy]="trackRow"
560
+ >
561
+ <ng-container [ngTemplateOutlet]="row" [ngTemplateOutletContext]="{ $implicit: item }" />
562
+ </ng-template>
563
+ </cdk-virtual-scroll-viewport>
564
+ } @else {
565
+ <ul
566
+ #tree
567
+ class="star-tree__list"
568
+ role="tree"
569
+ [attr.aria-label]="ariaLabel()"
570
+ [attr.aria-multiselectable]="multiselectable()"
571
+ [style.max-height]="scrollHeight()"
572
+ >
573
+ @for (item of visible(); track item.node.key) {
574
+ <ng-container [ngTemplateOutlet]="row" [ngTemplateOutletContext]="{ $implicit: item }" />
575
+ } @empty {
576
+ <li class="star-listbox__empty" role="presentation">{{ text.emptyFilterMessage }}</li>
577
+ }
578
+ </ul>
579
+ }
580
+ `,
581
+ isInline: true,
582
+ dependencies: [
583
+ {
584
+ kind: "component",
585
+ type: CdkVirtualScrollViewport,
586
+ selector: "cdk-virtual-scroll-viewport",
587
+ inputs: ["orientation", "appendOnly"],
588
+ outputs: ["scrolledIndexChange"]
589
+ },
590
+ {
591
+ kind: "directive",
592
+ type: CdkFixedSizeVirtualScroll,
593
+ selector: "cdk-virtual-scroll-viewport[itemSize]",
594
+ inputs: [
595
+ "itemSize",
596
+ "minBufferPx",
597
+ "maxBufferPx"
598
+ ]
599
+ },
600
+ {
601
+ kind: "directive",
602
+ type: CdkVirtualForOf,
603
+ selector: "[cdkVirtualFor][cdkVirtualForOf]",
604
+ inputs: [
605
+ "cdkVirtualForOf",
606
+ "cdkVirtualForTrackBy",
607
+ "cdkVirtualForTemplate",
608
+ "cdkVirtualForTemplateCacheSize"
609
+ ]
610
+ },
611
+ {
612
+ kind: "directive",
613
+ type: NgTemplateOutlet,
614
+ selector: "[ngTemplateOutlet]",
615
+ inputs: [
616
+ "ngTemplateOutletContext",
617
+ "ngTemplateOutlet",
618
+ "ngTemplateOutletInjector"
619
+ ]
620
+ }
621
+ ],
622
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
623
+ });
624
+ };
625
+ i0.ɵɵngDeclareClassMetadata({
626
+ minVersion: "12.0.0",
627
+ version: "22.2.6",
628
+ ngImport: i0,
629
+ type: StarTree,
630
+ decorators: [{
631
+ type: Component,
632
+ args: [{
633
+ selector: "star-tree",
634
+ imports: [
635
+ CdkVirtualScrollViewport,
636
+ CdkFixedSizeVirtualScroll,
637
+ CdkVirtualForOf,
638
+ NgTemplateOutlet
639
+ ],
640
+ changeDetection: ChangeDetectionStrategy.OnPush,
641
+ host: { class: "star-tree" },
642
+ template: `
643
+ @if (filter()) {
644
+ <div class="star-panel__filter">
645
+ <i class="ph-bold ph-magnifying-glass" aria-hidden="true"></i>
646
+ <input
647
+ #filterInput
648
+ type="search"
649
+ class="star-input star-input--sm"
650
+ autocomplete="off"
651
+ [attr.aria-label]="text.filterPlaceholder"
652
+ [placeholder]="text.filterPlaceholder"
653
+ [value]="query()"
654
+ (input)="query.set(filterInput.value)"
655
+ />
656
+ </div>
657
+ }
658
+ <ng-template #row let-item>
659
+ <li
660
+ class="star-tree__item"
661
+ role="treeitem"
662
+ [attr.data-key]="item.node.key"
663
+ [attr.aria-level]="item.level"
664
+ [attr.aria-setsize]="item.setSize"
665
+ [attr.aria-posinset]="item.position"
666
+ [attr.aria-expanded]="item.node.children?.length ? isExpanded(item.node) : null"
667
+ [attr.aria-selected]="
668
+ selectionMode() && selectionMode() !== 'checkbox' ? isSelected(item.node) : null
669
+ "
670
+ [attr.aria-checked]="selectionMode() === 'checkbox' ? checkState(item.node) : null"
671
+ [attr.aria-disabled]="item.node.disabled || null"
672
+ [attr.tabindex]="focusKey() === item.node.key ? 0 : -1"
673
+ [class.star-tree__item--selected]="isSelected(item.node)"
674
+ [style.--star-tree-level]="item.level - 1"
675
+ [style.height.px]="showViewport() ? virtualItemSize() : null"
676
+ (click)="onClick(item.node, $event)"
677
+ (keydown)="onKeydown($event, item)"
678
+ (focus)="onRowFocus(item.node.key)"
679
+ >
680
+ @if (item.node.children?.length) {
681
+ <span
682
+ class="star-tree__toggle"
683
+ aria-hidden="true"
684
+ (click)="$event.stopPropagation(); toggle(item.node)"
685
+ >
686
+ <i class="ph-bold ph-caret-right"></i>
687
+ </span>
688
+ } @else {
689
+ <span class="star-tree__toggle star-tree__toggle--leaf" aria-hidden="true"></span>
690
+ }
691
+ @if (selectionMode() === 'checkbox') {
692
+ <span
693
+ class="star-check__box star-tree__check"
694
+ aria-hidden="true"
695
+ [class.star-tree__check--on]="checkState(item.node) !== false"
696
+ >
697
+ @if (checkState(item.node) === 'mixed') {
698
+ <i class="ph-bold ph-minus"></i>
699
+ } @else if (checkState(item.node) === true) {
700
+ <i class="ph-bold ph-check"></i>
701
+ }
702
+ </span>
703
+ }
704
+ @if (item.node.icon) {
705
+ <i class="star-tree__icon" [class]="item.node.icon" aria-hidden="true"></i>
706
+ }
707
+ <span class="star-tree__label">{{ item.node.label }}</span>
708
+ </li>
709
+ </ng-template>
710
+ @if (showViewport()) {
711
+ <cdk-virtual-scroll-viewport
712
+ #viewport
713
+ class="star-tree__viewport"
714
+ role="tree"
715
+ [itemSize]="virtualItemSize()"
716
+ [attr.aria-label]="ariaLabel()"
717
+ [attr.aria-multiselectable]="multiselectable()"
718
+ [attr.tabindex]="activeRendered() ? -1 : 0"
719
+ [style.height]="viewportHeight()"
720
+ (focus)="onViewportFocus()"
721
+ (blur)="parked = false"
722
+ (keydown)="onViewportKeydown($event)"
723
+ >
724
+ <ng-template
725
+ cdkVirtualFor
726
+ let-item
727
+ [cdkVirtualForOf]="visible()"
728
+ [cdkVirtualForTrackBy]="trackRow"
729
+ >
730
+ <ng-container [ngTemplateOutlet]="row" [ngTemplateOutletContext]="{ $implicit: item }" />
731
+ </ng-template>
732
+ </cdk-virtual-scroll-viewport>
733
+ } @else {
734
+ <ul
735
+ #tree
736
+ class="star-tree__list"
737
+ role="tree"
738
+ [attr.aria-label]="ariaLabel()"
739
+ [attr.aria-multiselectable]="multiselectable()"
740
+ [style.max-height]="scrollHeight()"
741
+ >
742
+ @for (item of visible(); track item.node.key) {
743
+ <ng-container [ngTemplateOutlet]="row" [ngTemplateOutletContext]="{ $implicit: item }" />
744
+ } @empty {
745
+ <li class="star-listbox__empty" role="presentation">{{ text.emptyFilterMessage }}</li>
746
+ }
747
+ </ul>
748
+ }
749
+ `
750
+ }]
751
+ }],
752
+ ctorParameters: () => [],
753
+ propDecorators: {
754
+ value: [{
755
+ type: i0.Input,
756
+ args: [{
757
+ isSignal: true,
758
+ alias: "value",
759
+ required: false
760
+ }]
761
+ }, {
762
+ type: i0.Output,
763
+ args: ["valueChange"]
764
+ }],
765
+ nodes: [{
766
+ type: i0.Input,
767
+ args: [{
768
+ isSignal: true,
769
+ alias: "nodes",
770
+ required: false
771
+ }]
772
+ }],
773
+ selectionMode: [{
774
+ type: i0.Input,
775
+ args: [{
776
+ isSignal: true,
777
+ alias: "selectionMode",
778
+ required: false
779
+ }]
780
+ }],
781
+ expanded: [{
782
+ type: i0.Input,
783
+ args: [{
784
+ isSignal: true,
785
+ alias: "expanded",
786
+ required: false
787
+ }]
788
+ }, {
789
+ type: i0.Output,
790
+ args: ["expandedChange"]
791
+ }],
792
+ filter: [{
793
+ type: i0.Input,
794
+ args: [{
795
+ isSignal: true,
796
+ alias: "filter",
797
+ required: false
798
+ }]
799
+ }],
800
+ scrollHeight: [{
801
+ type: i0.Input,
802
+ args: [{
803
+ isSignal: true,
804
+ alias: "scrollHeight",
805
+ required: false
806
+ }]
807
+ }],
808
+ virtualScroll: [{
809
+ type: i0.Input,
810
+ args: [{
811
+ isSignal: true,
812
+ alias: "virtualScroll",
813
+ required: false
814
+ }]
815
+ }],
816
+ virtualItemSize: [{
817
+ type: i0.Input,
818
+ args: [{
819
+ isSignal: true,
820
+ alias: "virtualItemSize",
821
+ required: false
822
+ }]
823
+ }],
824
+ ariaLabel: [{
825
+ type: i0.Input,
826
+ args: [{
827
+ isSignal: true,
828
+ alias: "ariaLabel",
829
+ required: false
830
+ }]
831
+ }],
832
+ disabled: [{
833
+ type: i0.Input,
834
+ args: [{
835
+ isSignal: true,
836
+ alias: "disabled",
837
+ required: false
838
+ }]
839
+ }],
840
+ touch: [{
841
+ type: i0.Output,
842
+ args: ["touch"]
843
+ }],
844
+ nodeSelect: [{
845
+ type: i0.Output,
846
+ args: ["nodeSelect"]
847
+ }],
848
+ viewport: [{
849
+ type: i0.ViewChild,
850
+ args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }]
851
+ }]
852
+ }
853
+ });
854
+ const POSITIONS = [{
855
+ originX: "start",
856
+ originY: "bottom",
857
+ overlayX: "start",
858
+ overlayY: "top",
859
+ offsetY: 6
860
+ }, {
861
+ originX: "start",
862
+ originY: "top",
863
+ overlayX: "start",
864
+ overlayY: "bottom",
865
+ offsetY: -6
866
+ }];
867
+ var StarTreeSelect = class StarTreeSelect {
868
+ directionSync = inject(StarDirectionService);
869
+ text = inject(STAR_UI_TEXT);
870
+ inputId = inject(_IdGenerator).getId("star-tree-select-");
871
+ positions = POSITIONS;
872
+ value = model([], ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
873
+ nodes = input([], ...ngDevMode ? [{ debugName: "nodes" }] : /* istanbul ignore next */ []);
874
+ selectionMode = input("single", ...ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []);
875
+ expanded = model([], ...ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []);
876
+ filter = input(false, {
877
+ ...ngDevMode ? { debugName: "filter" } : /* istanbul ignore next */ {},
878
+ transform: booleanAttribute
879
+ });
880
+ virtualScroll = input(false, {
881
+ ...ngDevMode ? { debugName: "virtualScroll" } : /* istanbul ignore next */ {},
882
+ transform: booleanAttribute
883
+ });
884
+ virtualItemSize = input(34, {
885
+ ...ngDevMode ? { debugName: "virtualItemSize" } : /* istanbul ignore next */ {},
886
+ transform: numberAttribute
887
+ });
888
+ showClear = input(false, {
889
+ ...ngDevMode ? { debugName: "showClear" } : /* istanbul ignore next */ {},
890
+ transform: booleanAttribute
891
+ });
892
+ placeholder = input(null, ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
893
+ ariaLabel = input(null, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
894
+ maxSelectedLabels = input(3, ...ngDevMode ? [{ debugName: "maxSelectedLabels" }] : /* istanbul ignore next */ []);
895
+ disabled = input(false, {
896
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
897
+ transform: booleanAttribute
898
+ });
899
+ invalid = input(false, {
900
+ ...ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {},
901
+ transform: booleanAttribute
902
+ });
903
+ touched = input(false, {
904
+ ...ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {},
905
+ transform: booleanAttribute
906
+ });
907
+ touch = output();
908
+ open = signal(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
909
+ panelTree = viewChild("panelTree", ...ngDevMode ? [{ debugName: "panelTree" }] : /* istanbul ignore next */ []);
910
+ trigger = viewChild.required("trigger", ...ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []);
911
+ labels = computed(() => {
912
+ const map = /* @__PURE__ */ new Map();
913
+ const walk = (nodes) => nodes.forEach((n) => {
914
+ map.set(n.key, n.label);
915
+ walk(n.children ?? []);
916
+ });
917
+ walk(this.nodes());
918
+ return map;
919
+ }, ...ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []);
920
+ summary = computed(() => {
921
+ const keys = this.value();
922
+ if (keys.length > this.maxSelectedLabels()) return this.text.selectedItems(keys.length);
923
+ return keys.map((key) => this.labels().get(key) ?? key).join(", ");
924
+ }, ...ngDevMode ? [{ debugName: "summary" }] : /* istanbul ignore next */ []);
925
+ triggerName = computed(() => {
926
+ const label = this.ariaLabel();
927
+ if (!label) return null;
928
+ return `${label}: ${this.summary() || (this.placeholder() ?? this.text.selectPlaceholder)}`;
929
+ }, ...ngDevMode ? [{ debugName: "triggerName" }] : /* istanbul ignore next */ []);
930
+ close(focus = false) {
931
+ if (!this.open()) return;
932
+ this.open.set(false);
933
+ if (focus) this.trigger().nativeElement.focus();
934
+ }
935
+ onOutside(event) {
936
+ if (this.trigger().nativeElement.contains(event.target)) return;
937
+ this.close();
938
+ this.touch.emit();
939
+ }
940
+ focus() {
941
+ this.trigger().nativeElement.focus();
942
+ }
943
+ static ɵfac = i0.ɵɵngDeclareFactory({
944
+ minVersion: "12.0.0",
945
+ version: "22.2.6",
946
+ ngImport: i0,
947
+ type: StarTreeSelect,
948
+ deps: [],
949
+ target: i0.ɵɵFactoryTarget.Component
950
+ });
951
+ static ɵcmp = i0.ɵɵngDeclareComponent({
952
+ minVersion: "17.0.0",
953
+ version: "22.2.6",
954
+ type: StarTreeSelect,
955
+ isStandalone: true,
956
+ selector: "star-tree-select",
957
+ inputs: {
958
+ value: {
959
+ classPropertyName: "value",
960
+ publicName: "value",
961
+ isSignal: true,
962
+ isRequired: false,
963
+ transformFunction: null
964
+ },
965
+ nodes: {
966
+ classPropertyName: "nodes",
967
+ publicName: "nodes",
968
+ isSignal: true,
969
+ isRequired: false,
970
+ transformFunction: null
971
+ },
972
+ selectionMode: {
973
+ classPropertyName: "selectionMode",
974
+ publicName: "selectionMode",
975
+ isSignal: true,
976
+ isRequired: false,
977
+ transformFunction: null
978
+ },
979
+ expanded: {
980
+ classPropertyName: "expanded",
981
+ publicName: "expanded",
982
+ isSignal: true,
983
+ isRequired: false,
984
+ transformFunction: null
985
+ },
986
+ filter: {
987
+ classPropertyName: "filter",
988
+ publicName: "filter",
989
+ isSignal: true,
990
+ isRequired: false,
991
+ transformFunction: null
992
+ },
993
+ virtualScroll: {
994
+ classPropertyName: "virtualScroll",
995
+ publicName: "virtualScroll",
996
+ isSignal: true,
997
+ isRequired: false,
998
+ transformFunction: null
999
+ },
1000
+ virtualItemSize: {
1001
+ classPropertyName: "virtualItemSize",
1002
+ publicName: "virtualItemSize",
1003
+ isSignal: true,
1004
+ isRequired: false,
1005
+ transformFunction: null
1006
+ },
1007
+ showClear: {
1008
+ classPropertyName: "showClear",
1009
+ publicName: "showClear",
1010
+ isSignal: true,
1011
+ isRequired: false,
1012
+ transformFunction: null
1013
+ },
1014
+ placeholder: {
1015
+ classPropertyName: "placeholder",
1016
+ publicName: "placeholder",
1017
+ isSignal: true,
1018
+ isRequired: false,
1019
+ transformFunction: null
1020
+ },
1021
+ ariaLabel: {
1022
+ classPropertyName: "ariaLabel",
1023
+ publicName: "ariaLabel",
1024
+ isSignal: true,
1025
+ isRequired: false,
1026
+ transformFunction: null
1027
+ },
1028
+ maxSelectedLabels: {
1029
+ classPropertyName: "maxSelectedLabels",
1030
+ publicName: "maxSelectedLabels",
1031
+ isSignal: true,
1032
+ isRequired: false,
1033
+ transformFunction: null
1034
+ },
1035
+ disabled: {
1036
+ classPropertyName: "disabled",
1037
+ publicName: "disabled",
1038
+ isSignal: true,
1039
+ isRequired: false,
1040
+ transformFunction: null
1041
+ },
1042
+ invalid: {
1043
+ classPropertyName: "invalid",
1044
+ publicName: "invalid",
1045
+ isSignal: true,
1046
+ isRequired: false,
1047
+ transformFunction: null
1048
+ },
1049
+ touched: {
1050
+ classPropertyName: "touched",
1051
+ publicName: "touched",
1052
+ isSignal: true,
1053
+ isRequired: false,
1054
+ transformFunction: null
1055
+ }
1056
+ },
1057
+ outputs: {
1058
+ value: "valueChange",
1059
+ expanded: "expandedChange",
1060
+ touch: "touch"
1061
+ },
1062
+ host: {
1063
+ properties: {
1064
+ "class.star-select--open": "open()",
1065
+ "class.star-select--disabled": "disabled()",
1066
+ "class.star-select--invalid": "invalid() && touched()"
1067
+ },
1068
+ classAttribute: "star-select star-tree-select"
1069
+ },
1070
+ viewQueries: [{
1071
+ propertyName: "panelTree",
1072
+ first: true,
1073
+ predicate: ["panelTree"],
1074
+ descendants: true,
1075
+ isSignal: true
1076
+ }, {
1077
+ propertyName: "trigger",
1078
+ first: true,
1079
+ predicate: ["trigger"],
1080
+ descendants: true,
1081
+ isSignal: true
1082
+ }],
1083
+ ngImport: i0,
1084
+ template: `
1085
+ <div class="star-select__control" cdkOverlayOrigin #origin="cdkOverlayOrigin">
1086
+ <button
1087
+ #trigger
1088
+ type="button"
1089
+ class="star-select__trigger star-tree-select__trigger"
1090
+ aria-haspopup="tree"
1091
+ [id]="inputId"
1092
+ [disabled]="disabled()"
1093
+ [attr.aria-expanded]="open()"
1094
+ [attr.aria-label]="triggerName()"
1095
+ (click)="open.set(!open())"
1096
+ (keydown.arrowdown)="$event.preventDefault(); open.set(true)"
1097
+ (blur)="!open() && touch.emit()"
1098
+ >
1099
+ @if (summary()) {
1100
+ <span class="star-select__value">{{ summary() }}</span>
1101
+ } @else {
1102
+ <span class="star-select__placeholder">{{
1103
+ placeholder() ?? text.selectPlaceholder
1104
+ }}</span>
1105
+ }
1106
+ </button>
1107
+ @if (showClear() && value().length && !disabled()) {
1108
+ <button
1109
+ type="button"
1110
+ class="star-select__icon-btn"
1111
+ [attr.aria-label]="text.clear"
1112
+ (click)="value.set([])"
1113
+ >
1114
+ <i class="ph-bold ph-x" aria-hidden="true"></i>
1115
+ </button>
1116
+ }
1117
+ <i class="ph-bold ph-caret-down star-select__caret" aria-hidden="true"></i>
1118
+ </div>
1119
+ <ng-template
1120
+ cdkConnectedOverlay
1121
+ cdkConnectedOverlayUsePopover="inline"
1122
+ [cdkConnectedOverlayMinWidth]="origin.elementRef.nativeElement.offsetWidth"
1123
+ [cdkConnectedOverlayOrigin]="origin"
1124
+ [cdkConnectedOverlayOpen]="open()"
1125
+ [cdkConnectedOverlayPositions]="positions"
1126
+ (attach)="panelTree()?.focus()"
1127
+ (detach)="close()"
1128
+ (overlayOutsideClick)="onOutside($event)"
1129
+ (overlayKeydown)="$event.key === 'Escape' && close(true)"
1130
+ >
1131
+ <div class="star-panel star-tree-select__panel">
1132
+ <star-tree
1133
+ #panelTree
1134
+ [nodes]="nodes()"
1135
+ [selectionMode]="selectionMode()"
1136
+ [(value)]="value"
1137
+ [(expanded)]="expanded"
1138
+ [filter]="filter()"
1139
+ scrollHeight="18rem"
1140
+ [virtualScroll]="virtualScroll()"
1141
+ [virtualItemSize]="virtualItemSize()"
1142
+ [ariaLabel]="ariaLabel()"
1143
+ (nodeSelect)="selectionMode() === 'single' && close(true)"
1144
+ />
1145
+ </div>
1146
+ </ng-template>
1147
+ `,
1148
+ isInline: true,
1149
+ dependencies: [
1150
+ {
1151
+ kind: "directive",
1152
+ type: CdkConnectedOverlay,
1153
+ selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]",
1154
+ inputs: [
1155
+ "cdkConnectedOverlayOrigin",
1156
+ "cdkConnectedOverlayPositions",
1157
+ "cdkConnectedOverlayPositionStrategy",
1158
+ "cdkConnectedOverlayOffsetX",
1159
+ "cdkConnectedOverlayOffsetY",
1160
+ "cdkConnectedOverlayWidth",
1161
+ "cdkConnectedOverlayHeight",
1162
+ "cdkConnectedOverlayMinWidth",
1163
+ "cdkConnectedOverlayMinHeight",
1164
+ "cdkConnectedOverlayBackdropClass",
1165
+ "cdkConnectedOverlayPanelClass",
1166
+ "cdkConnectedOverlayViewportMargin",
1167
+ "cdkConnectedOverlayScrollStrategy",
1168
+ "cdkConnectedOverlayOpen",
1169
+ "cdkConnectedOverlayDisableClose",
1170
+ "cdkConnectedOverlayTransformOriginOn",
1171
+ "cdkConnectedOverlayHasBackdrop",
1172
+ "cdkConnectedOverlayLockPosition",
1173
+ "cdkConnectedOverlayFlexibleDimensions",
1174
+ "cdkConnectedOverlayGrowAfterOpen",
1175
+ "cdkConnectedOverlayPush",
1176
+ "cdkConnectedOverlayDisposeOnNavigation",
1177
+ "cdkConnectedOverlayUsePopover",
1178
+ "cdkConnectedOverlayMatchWidth",
1179
+ "cdkConnectedOverlay"
1180
+ ],
1181
+ outputs: [
1182
+ "backdropClick",
1183
+ "positionChange",
1184
+ "attach",
1185
+ "detach",
1186
+ "overlayKeydown",
1187
+ "overlayOutsideClick"
1188
+ ],
1189
+ exportAs: ["cdkConnectedOverlay"]
1190
+ },
1191
+ {
1192
+ kind: "directive",
1193
+ type: CdkOverlayOrigin,
1194
+ selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]",
1195
+ exportAs: ["cdkOverlayOrigin"]
1196
+ },
1197
+ {
1198
+ kind: "component",
1199
+ type: StarTree,
1200
+ selector: "star-tree",
1201
+ inputs: [
1202
+ "value",
1203
+ "nodes",
1204
+ "selectionMode",
1205
+ "expanded",
1206
+ "filter",
1207
+ "scrollHeight",
1208
+ "virtualScroll",
1209
+ "virtualItemSize",
1210
+ "ariaLabel",
1211
+ "disabled"
1212
+ ],
1213
+ outputs: [
1214
+ "valueChange",
1215
+ "expandedChange",
1216
+ "touch",
1217
+ "nodeSelect"
1218
+ ]
1219
+ }
1220
+ ],
1221
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1222
+ });
1223
+ };
1224
+ i0.ɵɵngDeclareClassMetadata({
1225
+ minVersion: "12.0.0",
1226
+ version: "22.2.6",
1227
+ ngImport: i0,
1228
+ type: StarTreeSelect,
1229
+ decorators: [{
1230
+ type: Component,
1231
+ args: [{
1232
+ selector: "star-tree-select",
1233
+ imports: [
1234
+ CdkConnectedOverlay,
1235
+ CdkOverlayOrigin,
1236
+ StarTree
1237
+ ],
1238
+ changeDetection: ChangeDetectionStrategy.OnPush,
1239
+ host: {
1240
+ class: "star-select star-tree-select",
1241
+ "[class.star-select--open]": "open()",
1242
+ "[class.star-select--disabled]": "disabled()",
1243
+ "[class.star-select--invalid]": "invalid() && touched()"
1244
+ },
1245
+ template: `
1246
+ <div class="star-select__control" cdkOverlayOrigin #origin="cdkOverlayOrigin">
1247
+ <button
1248
+ #trigger
1249
+ type="button"
1250
+ class="star-select__trigger star-tree-select__trigger"
1251
+ aria-haspopup="tree"
1252
+ [id]="inputId"
1253
+ [disabled]="disabled()"
1254
+ [attr.aria-expanded]="open()"
1255
+ [attr.aria-label]="triggerName()"
1256
+ (click)="open.set(!open())"
1257
+ (keydown.arrowdown)="$event.preventDefault(); open.set(true)"
1258
+ (blur)="!open() && touch.emit()"
1259
+ >
1260
+ @if (summary()) {
1261
+ <span class="star-select__value">{{ summary() }}</span>
1262
+ } @else {
1263
+ <span class="star-select__placeholder">{{
1264
+ placeholder() ?? text.selectPlaceholder
1265
+ }}</span>
1266
+ }
1267
+ </button>
1268
+ @if (showClear() && value().length && !disabled()) {
1269
+ <button
1270
+ type="button"
1271
+ class="star-select__icon-btn"
1272
+ [attr.aria-label]="text.clear"
1273
+ (click)="value.set([])"
1274
+ >
1275
+ <i class="ph-bold ph-x" aria-hidden="true"></i>
1276
+ </button>
1277
+ }
1278
+ <i class="ph-bold ph-caret-down star-select__caret" aria-hidden="true"></i>
1279
+ </div>
1280
+ <ng-template
1281
+ cdkConnectedOverlay
1282
+ cdkConnectedOverlayUsePopover="inline"
1283
+ [cdkConnectedOverlayMinWidth]="origin.elementRef.nativeElement.offsetWidth"
1284
+ [cdkConnectedOverlayOrigin]="origin"
1285
+ [cdkConnectedOverlayOpen]="open()"
1286
+ [cdkConnectedOverlayPositions]="positions"
1287
+ (attach)="panelTree()?.focus()"
1288
+ (detach)="close()"
1289
+ (overlayOutsideClick)="onOutside($event)"
1290
+ (overlayKeydown)="$event.key === 'Escape' && close(true)"
1291
+ >
1292
+ <div class="star-panel star-tree-select__panel">
1293
+ <star-tree
1294
+ #panelTree
1295
+ [nodes]="nodes()"
1296
+ [selectionMode]="selectionMode()"
1297
+ [(value)]="value"
1298
+ [(expanded)]="expanded"
1299
+ [filter]="filter()"
1300
+ scrollHeight="18rem"
1301
+ [virtualScroll]="virtualScroll()"
1302
+ [virtualItemSize]="virtualItemSize()"
1303
+ [ariaLabel]="ariaLabel()"
1304
+ (nodeSelect)="selectionMode() === 'single' && close(true)"
1305
+ />
1306
+ </div>
1307
+ </ng-template>
1308
+ `
1309
+ }]
1310
+ }],
1311
+ propDecorators: {
1312
+ value: [{
1313
+ type: i0.Input,
1314
+ args: [{
1315
+ isSignal: true,
1316
+ alias: "value",
1317
+ required: false
1318
+ }]
1319
+ }, {
1320
+ type: i0.Output,
1321
+ args: ["valueChange"]
1322
+ }],
1323
+ nodes: [{
1324
+ type: i0.Input,
1325
+ args: [{
1326
+ isSignal: true,
1327
+ alias: "nodes",
1328
+ required: false
1329
+ }]
1330
+ }],
1331
+ selectionMode: [{
1332
+ type: i0.Input,
1333
+ args: [{
1334
+ isSignal: true,
1335
+ alias: "selectionMode",
1336
+ required: false
1337
+ }]
1338
+ }],
1339
+ expanded: [{
1340
+ type: i0.Input,
1341
+ args: [{
1342
+ isSignal: true,
1343
+ alias: "expanded",
1344
+ required: false
1345
+ }]
1346
+ }, {
1347
+ type: i0.Output,
1348
+ args: ["expandedChange"]
1349
+ }],
1350
+ filter: [{
1351
+ type: i0.Input,
1352
+ args: [{
1353
+ isSignal: true,
1354
+ alias: "filter",
1355
+ required: false
1356
+ }]
1357
+ }],
1358
+ virtualScroll: [{
1359
+ type: i0.Input,
1360
+ args: [{
1361
+ isSignal: true,
1362
+ alias: "virtualScroll",
1363
+ required: false
1364
+ }]
1365
+ }],
1366
+ virtualItemSize: [{
1367
+ type: i0.Input,
1368
+ args: [{
1369
+ isSignal: true,
1370
+ alias: "virtualItemSize",
1371
+ required: false
1372
+ }]
1373
+ }],
1374
+ showClear: [{
1375
+ type: i0.Input,
1376
+ args: [{
1377
+ isSignal: true,
1378
+ alias: "showClear",
1379
+ required: false
1380
+ }]
1381
+ }],
1382
+ placeholder: [{
1383
+ type: i0.Input,
1384
+ args: [{
1385
+ isSignal: true,
1386
+ alias: "placeholder",
1387
+ required: false
1388
+ }]
1389
+ }],
1390
+ ariaLabel: [{
1391
+ type: i0.Input,
1392
+ args: [{
1393
+ isSignal: true,
1394
+ alias: "ariaLabel",
1395
+ required: false
1396
+ }]
1397
+ }],
1398
+ maxSelectedLabels: [{
1399
+ type: i0.Input,
1400
+ args: [{
1401
+ isSignal: true,
1402
+ alias: "maxSelectedLabels",
1403
+ required: false
1404
+ }]
1405
+ }],
1406
+ disabled: [{
1407
+ type: i0.Input,
1408
+ args: [{
1409
+ isSignal: true,
1410
+ alias: "disabled",
1411
+ required: false
1412
+ }]
1413
+ }],
1414
+ invalid: [{
1415
+ type: i0.Input,
1416
+ args: [{
1417
+ isSignal: true,
1418
+ alias: "invalid",
1419
+ required: false
1420
+ }]
1421
+ }],
1422
+ touched: [{
1423
+ type: i0.Input,
1424
+ args: [{
1425
+ isSignal: true,
1426
+ alias: "touched",
1427
+ required: false
1428
+ }]
1429
+ }],
1430
+ touch: [{
1431
+ type: i0.Output,
1432
+ args: ["touch"]
1433
+ }],
1434
+ panelTree: [{
1435
+ type: i0.ViewChild,
1436
+ args: ["panelTree", { isSignal: true }]
1437
+ }],
1438
+ trigger: [{
1439
+ type: i0.ViewChild,
1440
+ args: ["trigger", { isSignal: true }]
1441
+ }]
1442
+ }
1443
+ });
1444
+ export { StarTree, StarTreeSelect };
1445
+
1446
+ //# sourceMappingURL=star-ng-ui-tree.mjs.map