@ngneers/controls 0.0.1-next.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 (186) hide show
  1. package/fesm2022/ngneers-controls-accordion.mjs +234 -0
  2. package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
  3. package/fesm2022/ngneers-controls-api-ng.mjs +959 -0
  4. package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
  5. package/fesm2022/ngneers-controls-api-resize.mjs +712 -0
  6. package/fesm2022/ngneers-controls-api-resize.mjs.map +1 -0
  7. package/fesm2022/ngneers-controls-api.mjs +347 -0
  8. package/fesm2022/ngneers-controls-api.mjs.map +1 -0
  9. package/fesm2022/ngneers-controls-avatar.mjs +77 -0
  10. package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
  11. package/fesm2022/ngneers-controls-base.mjs +620 -0
  12. package/fesm2022/ngneers-controls-base.mjs.map +1 -0
  13. package/fesm2022/ngneers-controls-breadcrumb.mjs +100 -0
  14. package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
  15. package/fesm2022/ngneers-controls-button-group.mjs +110 -0
  16. package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
  17. package/fesm2022/ngneers-controls-button.mjs +83 -0
  18. package/fesm2022/ngneers-controls-button.mjs.map +1 -0
  19. package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs +74 -0
  20. package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs.map +1 -0
  21. package/fesm2022/ngneers-controls-calendar.mjs +801 -0
  22. package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
  23. package/fesm2022/ngneers-controls-checkbox.mjs +63 -0
  24. package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
  25. package/fesm2022/ngneers-controls-chip.mjs +55 -0
  26. package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
  27. package/fesm2022/ngneers-controls-default-icons.mjs +82 -0
  28. package/fesm2022/ngneers-controls-default-icons.mjs.map +1 -0
  29. package/fesm2022/ngneers-controls-defer.mjs +72 -0
  30. package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
  31. package/fesm2022/ngneers-controls-dialog.mjs +407 -0
  32. package/fesm2022/ngneers-controls-dialog.mjs.map +1 -0
  33. package/fesm2022/ngneers-controls-directives.mjs +498 -0
  34. package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
  35. package/fesm2022/ngneers-controls-drawer.mjs +271 -0
  36. package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
  37. package/fesm2022/ngneers-controls-edit-inplace.mjs +127 -0
  38. package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
  39. package/fesm2022/ngneers-controls-errors.mjs +329 -0
  40. package/fesm2022/ngneers-controls-errors.mjs.map +1 -0
  41. package/fesm2022/ngneers-controls-filter.mjs +708 -0
  42. package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
  43. package/fesm2022/ngneers-controls-hint.mjs +153 -0
  44. package/fesm2022/ngneers-controls-hint.mjs.map +1 -0
  45. package/fesm2022/ngneers-controls-i18n-translations-de.mjs +170 -0
  46. package/fesm2022/ngneers-controls-i18n-translations-de.mjs.map +1 -0
  47. package/fesm2022/ngneers-controls-i18n-translations-en.mjs +170 -0
  48. package/fesm2022/ngneers-controls-i18n-translations-en.mjs.map +1 -0
  49. package/fesm2022/ngneers-controls-i18n.mjs +57 -0
  50. package/fesm2022/ngneers-controls-i18n.mjs.map +1 -0
  51. package/fesm2022/ngneers-controls-icon.mjs +195 -0
  52. package/fesm2022/ngneers-controls-icon.mjs.map +1 -0
  53. package/fesm2022/ngneers-controls-inplace.mjs +150 -0
  54. package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
  55. package/fesm2022/ngneers-controls-input-field.mjs +165 -0
  56. package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
  57. package/fesm2022/ngneers-controls-input.mjs +72 -0
  58. package/fesm2022/ngneers-controls-input.mjs.map +1 -0
  59. package/fesm2022/ngneers-controls-item-view.mjs +473 -0
  60. package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
  61. package/fesm2022/ngneers-controls-list-box.mjs +281 -0
  62. package/fesm2022/ngneers-controls-list-box.mjs.map +1 -0
  63. package/fesm2022/ngneers-controls-mask-input.mjs +888 -0
  64. package/fesm2022/ngneers-controls-mask-input.mjs.map +1 -0
  65. package/fesm2022/ngneers-controls-menu.mjs +371 -0
  66. package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
  67. package/fesm2022/ngneers-controls-message.mjs +30 -0
  68. package/fesm2022/ngneers-controls-message.mjs.map +1 -0
  69. package/fesm2022/ngneers-controls-number-input.mjs +366 -0
  70. package/fesm2022/ngneers-controls-number-input.mjs.map +1 -0
  71. package/fesm2022/ngneers-controls-paginator.mjs +129 -0
  72. package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
  73. package/fesm2022/ngneers-controls-popover.mjs +215 -0
  74. package/fesm2022/ngneers-controls-popover.mjs.map +1 -0
  75. package/fesm2022/ngneers-controls-progress.mjs +98 -0
  76. package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
  77. package/fesm2022/ngneers-controls-radio.mjs +152 -0
  78. package/fesm2022/ngneers-controls-radio.mjs.map +1 -0
  79. package/fesm2022/ngneers-controls-roving-focus.mjs +323 -0
  80. package/fesm2022/ngneers-controls-roving-focus.mjs.map +1 -0
  81. package/fesm2022/ngneers-controls-scroll-shadow.mjs +65 -0
  82. package/fesm2022/ngneers-controls-scroll-shadow.mjs.map +1 -0
  83. package/fesm2022/ngneers-controls-scroller.mjs +308 -0
  84. package/fesm2022/ngneers-controls-scroller.mjs.map +1 -0
  85. package/fesm2022/ngneers-controls-select-button.mjs +58 -0
  86. package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
  87. package/fesm2022/ngneers-controls-select.mjs +417 -0
  88. package/fesm2022/ngneers-controls-select.mjs.map +1 -0
  89. package/fesm2022/ngneers-controls-slider.mjs +167 -0
  90. package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
  91. package/fesm2022/ngneers-controls-snackbar.mjs +414 -0
  92. package/fesm2022/ngneers-controls-snackbar.mjs.map +1 -0
  93. package/fesm2022/ngneers-controls-spin-buttons.mjs +126 -0
  94. package/fesm2022/ngneers-controls-spin-buttons.mjs.map +1 -0
  95. package/fesm2022/ngneers-controls-spinner.mjs +184 -0
  96. package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
  97. package/fesm2022/ngneers-controls-splitter.mjs +604 -0
  98. package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
  99. package/fesm2022/ngneers-controls-state.mjs +185 -0
  100. package/fesm2022/ngneers-controls-state.mjs.map +1 -0
  101. package/fesm2022/ngneers-controls-switch.mjs +39 -0
  102. package/fesm2022/ngneers-controls-switch.mjs.map +1 -0
  103. package/fesm2022/ngneers-controls-table.mjs +2634 -0
  104. package/fesm2022/ngneers-controls-table.mjs.map +1 -0
  105. package/fesm2022/ngneers-controls-tabs.mjs +336 -0
  106. package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
  107. package/fesm2022/ngneers-controls-tag.mjs +30 -0
  108. package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
  109. package/fesm2022/ngneers-controls-toast.mjs +350 -0
  110. package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
  111. package/fesm2022/ngneers-controls-toggle-button.mjs +70 -0
  112. package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
  113. package/fesm2022/ngneers-controls-tooltip.mjs +506 -0
  114. package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
  115. package/fesm2022/ngneers-controls-tree.mjs +599 -0
  116. package/fesm2022/ngneers-controls-tree.mjs.map +1 -0
  117. package/fesm2022/ngneers-controls-upload.mjs +377 -0
  118. package/fesm2022/ngneers-controls-upload.mjs.map +1 -0
  119. package/fesm2022/ngneers-controls-utils-ng.mjs +411 -0
  120. package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
  121. package/fesm2022/ngneers-controls-utils.mjs +261 -0
  122. package/fesm2022/ngneers-controls-utils.mjs.map +1 -0
  123. package/fesm2022/ngneers-controls.mjs +6 -0
  124. package/fesm2022/ngneers-controls.mjs.map +1 -0
  125. package/package.json +302 -0
  126. package/types/ngneers-controls-accordion.d.ts +139 -0
  127. package/types/ngneers-controls-api-ng.d.ts +364 -0
  128. package/types/ngneers-controls-api-resize.d.ts +318 -0
  129. package/types/ngneers-controls-api.d.ts +145 -0
  130. package/types/ngneers-controls-avatar.d.ts +54 -0
  131. package/types/ngneers-controls-base.d.ts +277 -0
  132. package/types/ngneers-controls-breadcrumb.d.ts +272 -0
  133. package/types/ngneers-controls-button-group.d.ts +46 -0
  134. package/types/ngneers-controls-button.d.ts +48 -0
  135. package/types/ngneers-controls-calendar.d.ts +466 -0
  136. package/types/ngneers-controls-checkbox.d.ts +40 -0
  137. package/types/ngneers-controls-chip.d.ts +202 -0
  138. package/types/ngneers-controls-default-icons.d.ts +5 -0
  139. package/types/ngneers-controls-defer.d.ts +48 -0
  140. package/types/ngneers-controls-dialog.d.ts +399 -0
  141. package/types/ngneers-controls-directives.d.ts +171 -0
  142. package/types/ngneers-controls-drawer.d.ts +308 -0
  143. package/types/ngneers-controls-edit-inplace.d.ts +263 -0
  144. package/types/ngneers-controls-errors.d.ts +155 -0
  145. package/types/ngneers-controls-filter.d.ts +609 -0
  146. package/types/ngneers-controls-hint.d.ts +88 -0
  147. package/types/ngneers-controls-i18n-translations-de.d.ts +164 -0
  148. package/types/ngneers-controls-i18n-translations-en.d.ts +164 -0
  149. package/types/ngneers-controls-i18n.d.ts +186 -0
  150. package/types/ngneers-controls-icon.d.ts +68 -0
  151. package/types/ngneers-controls-inplace.d.ts +98 -0
  152. package/types/ngneers-controls-input-field.d.ts +248 -0
  153. package/types/ngneers-controls-input.d.ts +30 -0
  154. package/types/ngneers-controls-item-view.d.ts +215 -0
  155. package/types/ngneers-controls-list-box.d.ts +334 -0
  156. package/types/ngneers-controls-mask-input.d.ts +434 -0
  157. package/types/ngneers-controls-menu.d.ts +192 -0
  158. package/types/ngneers-controls-message.d.ts +21 -0
  159. package/types/ngneers-controls-number-input.d.ts +146 -0
  160. package/types/ngneers-controls-paginator.d.ts +255 -0
  161. package/types/ngneers-controls-popover.d.ts +116 -0
  162. package/types/ngneers-controls-progress.d.ts +49 -0
  163. package/types/ngneers-controls-radio.d.ts +91 -0
  164. package/types/ngneers-controls-roving-focus.d.ts +107 -0
  165. package/types/ngneers-controls-scroll-shadow.d.ts +25 -0
  166. package/types/ngneers-controls-scroller.d.ts +151 -0
  167. package/types/ngneers-controls-select-button.d.ts +51 -0
  168. package/types/ngneers-controls-select.d.ts +409 -0
  169. package/types/ngneers-controls-slider.d.ts +57 -0
  170. package/types/ngneers-controls-snackbar.d.ts +330 -0
  171. package/types/ngneers-controls-spin-buttons.d.ts +69 -0
  172. package/types/ngneers-controls-spinner.d.ts +117 -0
  173. package/types/ngneers-controls-splitter.d.ts +465 -0
  174. package/types/ngneers-controls-state.d.ts +102 -0
  175. package/types/ngneers-controls-switch.d.ts +18 -0
  176. package/types/ngneers-controls-table.d.ts +3127 -0
  177. package/types/ngneers-controls-tabs.d.ts +118 -0
  178. package/types/ngneers-controls-tag.d.ts +21 -0
  179. package/types/ngneers-controls-toast.d.ts +298 -0
  180. package/types/ngneers-controls-toggle-button.d.ts +48 -0
  181. package/types/ngneers-controls-tooltip.d.ts +189 -0
  182. package/types/ngneers-controls-tree.d.ts +409 -0
  183. package/types/ngneers-controls-upload.d.ts +347 -0
  184. package/types/ngneers-controls-utils-ng.d.ts +129 -0
  185. package/types/ngneers-controls-utils.d.ts +130 -0
  186. package/types/ngneers-controls.d.ts +2 -0
@@ -0,0 +1,411 @@
1
+ import { toggleClass, globalPropertyName, throwExp } from '@ngneers/controls/utils';
2
+ import * as i0 from '@angular/core';
3
+ import { computed, effect, untracked, afterRenderEffect, signal, inject, DOCUMENT, Injectable, DestroyRef } from '@angular/core';
4
+ import { SIGNAL } from '@angular/core/primitives/signals';
5
+
6
+ function signalWithPrevious(signal, previous) {
7
+ let current = previous;
8
+ return computed(() => {
9
+ const prev = current;
10
+ current = signal();
11
+ return { current, previous: prev };
12
+ });
13
+ }
14
+ function computedWithPrevious(computeFn, previous) {
15
+ let current = previous;
16
+ return computed(() => {
17
+ const prev = current;
18
+ current = computeFn(prev);
19
+ return current;
20
+ });
21
+ }
22
+ function effectWithPrevious(signal, effectFn) {
23
+ const sig = signalWithPrevious(signal);
24
+ return effect(() => {
25
+ const { current, previous } = sig();
26
+ effectFn(current, previous);
27
+ });
28
+ }
29
+ function explicitEffectBase(usedEffectFn, signals, effectFn) {
30
+ return usedEffectFn(() => {
31
+ const values = signals.map(sig => sig());
32
+ untracked(() => {
33
+ effectFn(values);
34
+ });
35
+ });
36
+ }
37
+ function explicitEffect(signals, effectFn) {
38
+ return explicitEffectBase(effect, signals, effectFn);
39
+ }
40
+ function explicitAfterRenderEffect(signals, effectFn) {
41
+ return explicitEffectBase(afterRenderEffect, signals, effectFn);
42
+ }
43
+ function asyncComputed(computeFn, initial) {
44
+ let latestId = 0;
45
+ let latestCompletedId = 0;
46
+ const isRunningSignal = signal(false, /* @ts-ignore */
47
+ ...(ngDevMode ? [{ debugName: "isRunningSignal" }] : /* istanbul ignore next */ []));
48
+ const firstRunCompleted = signal(false, /* @ts-ignore */
49
+ ...(ngDevMode ? [{ debugName: "firstRunCompleted" }] : /* istanbul ignore next */ []));
50
+ const returnSignal = signal(initial, /* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "returnSignal" }] : /* istanbul ignore next */ []));
52
+ effect(() => {
53
+ const currentId = ++latestId;
54
+ isRunningSignal.set(true);
55
+ computeFn()
56
+ .then(value => {
57
+ // Only update the signal if this is the latest call
58
+ if (currentId <= latestCompletedId) {
59
+ console.debug('asyncComputed: ignoring stale value update');
60
+ return;
61
+ }
62
+ latestCompletedId = currentId;
63
+ returnSignal.set(value);
64
+ firstRunCompleted.set(true);
65
+ // Set isRunning to false if this is the latest operation
66
+ if (currentId === latestId) {
67
+ isRunningSignal.set(false);
68
+ }
69
+ })
70
+ .catch(error => {
71
+ // Also check if this is the latest operation on error
72
+ if (currentId === latestId) {
73
+ isRunningSignal.set(false);
74
+ }
75
+ console.error('Error in asyncComputed:', error);
76
+ });
77
+ });
78
+ const returnFn = returnSignal;
79
+ returnFn.isRunning = isRunningSignal.asReadonly();
80
+ returnFn.firstRunCompleted = firstRunCompleted;
81
+ return returnFn;
82
+ }
83
+ function setInputSignalValue(input, value) {
84
+ input[SIGNAL].applyValueToInputSignal(input[SIGNAL], value);
85
+ }
86
+ function afterRenderComputed(computeFn, defaultValue) {
87
+ const value = signal(defaultValue, /* @ts-ignore */
88
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
89
+ afterRenderEffect(() => {
90
+ value.set(computeFn());
91
+ });
92
+ return value.asReadonly();
93
+ }
94
+ function debounceSignal(input, delayMs) {
95
+ const delayFn = typeof delayMs === 'function' ? delayMs : () => delayMs;
96
+ const debounced = signal(input(), /* @ts-ignore */
97
+ ...(ngDevMode ? [{ debugName: "debounced" }] : /* istanbul ignore next */ []));
98
+ let timeoutId;
99
+ effect(onCleanup => {
100
+ const value = input();
101
+ const delay = delayFn();
102
+ // Clear any pending timeout
103
+ if (timeoutId !== undefined) {
104
+ clearTimeout(timeoutId);
105
+ }
106
+ // Set new timeout
107
+ timeoutId = setTimeout(() => {
108
+ debounced.set(value);
109
+ timeoutId = undefined;
110
+ }, delay);
111
+ // Cleanup function to clear timeout when effect is destroyed or re-run
112
+ onCleanup(() => {
113
+ if (timeoutId !== undefined) {
114
+ clearTimeout(timeoutId);
115
+ timeoutId = undefined;
116
+ }
117
+ });
118
+ });
119
+ return debounced.asReadonly();
120
+ }
121
+
122
+ function classSignal(element, klass) {
123
+ effectWithPrevious(klass, (current, previous) => {
124
+ if (previous) {
125
+ toggleClass(element, previous, false);
126
+ }
127
+ if (current) {
128
+ toggleClass(element, current, true);
129
+ }
130
+ });
131
+ }
132
+
133
+ const FOCUSABLE_SELECTOR = [
134
+ 'a[href]',
135
+ 'button:not([disabled])',
136
+ 'input:not([disabled])',
137
+ 'select:not([disabled])',
138
+ 'textarea:not([disabled])',
139
+ '[tabindex]:not([tabindex="-1"])',
140
+ '[contenteditable="true"]',
141
+ ].join(',');
142
+ /** Visible, focusable descendants of `container`, in DOM order. */
143
+ function getFocusable(container) {
144
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter(el => el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0);
145
+ }
146
+ /**
147
+ * Keeps keyboard focus inside a single container for the duration a modal
148
+ * overlay is open. On {@link activate} it remembers what was focused, moves
149
+ * focus into the container, and wraps `Tab`/`Shift+Tab` at the edges;
150
+ * {@link deactivate} tears the listener down and restores the prior focus.
151
+ *
152
+ * The container itself is focused as a fallback when it has no focusable
153
+ * children, so focus never escapes to the (inert) background.
154
+ */
155
+ class FocusTrap {
156
+ container;
157
+ _previouslyFocused = null;
158
+ _active = false;
159
+ constructor(container) {
160
+ this.container = container;
161
+ }
162
+ activate() {
163
+ if (this._active)
164
+ return;
165
+ this._active = true;
166
+ this._previouslyFocused = document.activeElement;
167
+ this.container.addEventListener('keydown', this._onKeydown);
168
+ const focusable = getFocusable(this.container);
169
+ const target = focusable[0] ?? this.container;
170
+ if (target === this.container && !this.container.hasAttribute('tabindex')) {
171
+ this.container.tabIndex = -1;
172
+ }
173
+ target.focus();
174
+ }
175
+ deactivate() {
176
+ if (!this._active)
177
+ return;
178
+ this._active = false;
179
+ this.container.removeEventListener('keydown', this._onKeydown);
180
+ // Restore focus only if it is still inside the trap — otherwise the user
181
+ // has already moved on and we must not yank it back.
182
+ if (this.container.contains(document.activeElement)) {
183
+ this._previouslyFocused?.focus?.();
184
+ }
185
+ this._previouslyFocused = null;
186
+ }
187
+ _onKeydown = (event) => {
188
+ if (event.key !== 'Tab')
189
+ return;
190
+ const focusable = getFocusable(this.container);
191
+ if (focusable.length === 0) {
192
+ // Nothing to move to — keep focus pinned to the container.
193
+ event.preventDefault();
194
+ this.container.focus();
195
+ return;
196
+ }
197
+ const first = focusable[0];
198
+ const last = focusable[focusable.length - 1];
199
+ const active = document.activeElement;
200
+ if (event.shiftKey && active === first) {
201
+ event.preventDefault();
202
+ last.focus();
203
+ }
204
+ else if (!event.shiftKey && active === last) {
205
+ event.preventDefault();
206
+ first.focus();
207
+ }
208
+ };
209
+ }
210
+
211
+ class NgnGlobal {
212
+ _window = inject(DOCUMENT).defaultView || window;
213
+ constructor() {
214
+ this._window[globalPropertyName] ??= {
215
+ nextElementId: 1,
216
+ fancyLogging: true,
217
+ };
218
+ }
219
+ get nextElementId() {
220
+ return this._window[globalPropertyName].nextElementId;
221
+ }
222
+ set nextElementId(value) {
223
+ this._window[globalPropertyName].nextElementId = value;
224
+ }
225
+ get fancyLogging() {
226
+ return this._window[globalPropertyName].fancyLogging;
227
+ }
228
+ set fancyLogging(value) {
229
+ this._window[globalPropertyName].fancyLogging = value;
230
+ }
231
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnGlobal, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
232
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnGlobal });
233
+ }
234
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnGlobal, decorators: [{
235
+ type: Injectable
236
+ }], ctorParameters: () => [] });
237
+
238
+ const idPrefix = 'ngn-id-';
239
+ function generateElementId() {
240
+ return idPrefix + inject(NgnGlobal).nextElementId++;
241
+ }
242
+
243
+ function injectOrThrow(token, moduleName, errorMsg) {
244
+ return inject(token, { optional: true }) ?? throwExp(moduleName, errorMsg);
245
+ }
246
+
247
+ /**
248
+ * Keyboard-accessibility controller for a stack of transient notifications
249
+ * (snackbars / toasts) rendered inside a single host region.
250
+ *
251
+ * Implements the WAI-ARIA APG guidance for toasts: focus is never stolen when a
252
+ * notification appears, but a global hotkey (`F6`) lets the user jump into the
253
+ * region on demand. Within the region, a roving-tabindex model exposes exactly one
254
+ * item to the Tab sequence while `ArrowUp`/`ArrowDown`/`Home`/`End` move between
255
+ * items. Whenever the region holds focus, every timer in it is paused so nothing
256
+ * disappears mid-read.
257
+ *
258
+ * The host component owns the wiring: it forwards its events to the handlers here
259
+ * and binds {@link tabbableIndex} to each item's `tabindex`.
260
+ */
261
+ class NotificationRegionController {
262
+ host;
263
+ items;
264
+ /** The item index currently exposed to the Tab sequence (roving tabindex). */
265
+ activeIndex = signal(0, /* @ts-ignore */
266
+ ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
267
+ _regionFocused = false;
268
+ /**
269
+ * @param host The region's root element, used to scope focus containment checks.
270
+ * @param items A getter returning the live, ordered list of items (oldest first).
271
+ */
272
+ constructor(host, items) {
273
+ this.host = host;
274
+ this.items = items;
275
+ }
276
+ /**
277
+ * The roving tabindex target, clamped to the current item count so the region
278
+ * always has exactly one tabbable entry point even after items are removed.
279
+ */
280
+ tabbableIndex() {
281
+ const count = this.items().length;
282
+ return count === 0 ? -1 : Math.min(this.activeIndex(), count - 1);
283
+ }
284
+ /** Document-level handler: `F6` moves focus to the newest notification. */
285
+ handleGlobalKeydown(event) {
286
+ if (event.key !== 'F6') {
287
+ return;
288
+ }
289
+ const items = this.items();
290
+ if (items.length === 0) {
291
+ return;
292
+ }
293
+ event.preventDefault();
294
+ this.focusIndex(items.length - 1);
295
+ }
296
+ /** Region-level handler: arrow / Home / End roving between notifications. */
297
+ handleKeydown(event) {
298
+ const items = this.items();
299
+ if (items.length === 0) {
300
+ return;
301
+ }
302
+ const current = Math.min(this.activeIndex(), items.length - 1);
303
+ let next;
304
+ switch (event.key) {
305
+ case 'ArrowDown':
306
+ next = Math.min(current + 1, items.length - 1);
307
+ break;
308
+ case 'ArrowUp':
309
+ next = Math.max(current - 1, 0);
310
+ break;
311
+ case 'Home':
312
+ next = 0;
313
+ break;
314
+ case 'End':
315
+ next = items.length - 1;
316
+ break;
317
+ default:
318
+ return;
319
+ }
320
+ event.preventDefault();
321
+ this.focusIndex(next);
322
+ }
323
+ /** Region gained focus (via hotkey, Tab, or click) — pause every timer in it. */
324
+ handleFocusIn() {
325
+ this._regionFocused = true;
326
+ for (const item of this.items()) {
327
+ item.regionPause();
328
+ }
329
+ }
330
+ /** Region lost focus to something outside it — resume every timer. */
331
+ handleFocusOut(event) {
332
+ const next = event.relatedTarget;
333
+ if (next && this.host.contains(next)) {
334
+ return;
335
+ }
336
+ this._regionFocused = false;
337
+ for (const item of this.items()) {
338
+ item.regionResume();
339
+ }
340
+ }
341
+ focusIndex(index) {
342
+ this.activeIndex.set(index);
343
+ this.items()[index]?.focus();
344
+ }
345
+ }
346
+
347
+ function loadState(storage, key) {
348
+ const storageType = storage === 'local' ? localStorage : sessionStorage;
349
+ const state = storageType.getItem(key);
350
+ return state ? JSON.parse(state) : null;
351
+ }
352
+ function saveState(storage, key, state) {
353
+ const storageType = storage === 'local' ? localStorage : sessionStorage;
354
+ if (state === null) {
355
+ storageType.removeItem(key);
356
+ return;
357
+ }
358
+ storageType.setItem(key, JSON.stringify(state));
359
+ }
360
+ function registerState(options) {
361
+ const { storage, key, valueFn, onLoad, debounce } = options;
362
+ const destroyRef = options?.injector?.get(DestroyRef) ?? inject(DestroyRef);
363
+ const document = options?.injector?.get(DOCUMENT) ?? inject(DOCUMENT);
364
+ const load = () => {
365
+ const k = key();
366
+ return k ? loadState(storage(), k) : null;
367
+ };
368
+ const stateSignal = signal(undefined, /* @ts-ignore */
369
+ ...(ngDevMode ? [{ debugName: "stateSignal" }] : /* istanbul ignore next */ []));
370
+ let timer = undefined;
371
+ const save = () => {
372
+ const k = key();
373
+ const s = stateSignal();
374
+ if (k && s !== undefined)
375
+ saveState(storage(), k, s);
376
+ };
377
+ afterRenderEffect(() => {
378
+ let state = load();
379
+ if (onLoad) {
380
+ state = untracked(() => onLoad(state));
381
+ }
382
+ stateSignal.set(state);
383
+ }, options);
384
+ afterRenderEffect(() => {
385
+ stateSignal.set(valueFn(untracked(() => stateSignal() ?? null)));
386
+ }, options);
387
+ effect(() => {
388
+ stateSignal();
389
+ if (debounce === 0) {
390
+ save();
391
+ }
392
+ else {
393
+ clearTimeout(timer);
394
+ timer = setTimeout(save, debounce);
395
+ }
396
+ }, options);
397
+ // Ensure saving happens on destroy and unload
398
+ document.defaultView?.addEventListener('beforeunload', save);
399
+ destroyRef.onDestroy(() => {
400
+ clearTimeout(timer);
401
+ document.defaultView?.removeEventListener('beforeunload', save);
402
+ save();
403
+ });
404
+ }
405
+
406
+ /**
407
+ * Generated bundle index. Do not edit.
408
+ */
409
+
410
+ export { FocusTrap, NgnGlobal, NotificationRegionController, afterRenderComputed, asyncComputed, classSignal, computedWithPrevious, debounceSignal, effectWithPrevious, explicitAfterRenderEffect, explicitEffect, generateElementId, injectOrThrow, loadState, registerState, saveState, setInputSignalValue, signalWithPrevious };
411
+ //# sourceMappingURL=ngneers-controls-utils-ng.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-utils-ng.mjs","sources":["../../src/utils-ng/signals.ts","../../src/utils-ng/dom.ts","../../src/utils-ng/focus-trap.ts","../../src/utils-ng/globals.ts","../../src/utils-ng/generate-id.ts","../../src/utils-ng/inject.ts","../../src/utils-ng/notification-region.ts","../../src/utils-ng/state.ts","../../src/utils-ng/ngneers-controls-utils-ng.ts"],"sourcesContent":["import {\n afterRenderEffect,\n computed,\n effect,\n type EffectRef,\n type InputSignal,\n type InputSignalWithTransform,\n signal,\n type Signal,\n untracked,\n} from '@angular/core';\nimport { SIGNAL } from '@angular/core/primitives/signals';\n\nexport function signalWithPrevious<T>(\n signal: Signal<T>,\n previous?: T\n): Signal<{ current: T; previous: T | undefined }> {\n let current = previous;\n\n return computed(() => {\n const prev = current;\n current = signal();\n return { current, previous: prev };\n });\n}\n\nexport function computedWithPrevious<T>(computeFn: (prev?: T) => T, previous?: T): Signal<T> {\n let current = previous;\n\n return computed<T>(() => {\n const prev = current;\n current = computeFn(prev);\n return current;\n });\n}\n\nexport function effectWithPrevious<T>(\n signal: Signal<T>,\n effectFn: (current: T, previous: T | undefined) => void\n): EffectRef {\n const sig = signalWithPrevious(signal);\n return effect(() => {\n const { current, previous } = sig();\n effectFn(current, previous);\n });\n}\nfunction explicitEffectBase<T extends readonly Signal<any>[]>(\n usedEffectFn: (fn: () => void) => EffectRef,\n signals: [...T],\n effectFn: (values: { [K in keyof T]: T[K] extends Signal<infer U> ? U : never }) => void\n): EffectRef {\n return usedEffectFn(() => {\n const values = signals.map(sig => sig()) as {\n [K in keyof T]: T[K] extends Signal<infer U> ? U : never;\n };\n untracked(() => {\n effectFn(values);\n });\n });\n}\n\nexport function explicitEffect<T extends readonly Signal<any>[]>(\n signals: [...T],\n effectFn: (values: { [K in keyof T]: T[K] extends Signal<infer U> ? U : never }) => void\n): EffectRef {\n return explicitEffectBase(effect, signals, effectFn);\n}\n\nexport function explicitAfterRenderEffect<T extends readonly Signal<any>[]>(\n signals: [...T],\n effectFn: (values: { [K in keyof T]: T[K] extends Signal<infer U> ? U : never }) => void\n): EffectRef {\n return explicitEffectBase(afterRenderEffect, signals, effectFn);\n}\n\nexport function asyncComputed<T>(\n computeFn: () => Promise<T>,\n initial: T\n): { (): T; isRunning: Signal<boolean>; firstRunCompleted: Signal<boolean> } {\n let latestId = 0;\n let latestCompletedId = 0;\n const isRunningSignal = signal(false);\n const firstRunCompleted = signal(false);\n const returnSignal = signal<T>(initial);\n\n effect(() => {\n const currentId = ++latestId;\n isRunningSignal.set(true);\n\n computeFn()\n .then(value => {\n // Only update the signal if this is the latest call\n if (currentId <= latestCompletedId) {\n console.debug('asyncComputed: ignoring stale value update');\n return;\n }\n latestCompletedId = currentId;\n returnSignal.set(value);\n firstRunCompleted.set(true);\n\n // Set isRunning to false if this is the latest operation\n if (currentId === latestId) {\n isRunningSignal.set(false);\n }\n })\n .catch(error => {\n // Also check if this is the latest operation on error\n if (currentId === latestId) {\n isRunningSignal.set(false);\n }\n console.error('Error in asyncComputed:', error);\n });\n });\n\n const returnFn = returnSignal as unknown as {\n (): T;\n isRunning: Signal<boolean>;\n firstRunCompleted: Signal<boolean>;\n };\n returnFn.isRunning = isRunningSignal.asReadonly();\n returnFn.firstRunCompleted = firstRunCompleted;\n return returnFn;\n}\n\nexport function setInputSignalValue<T>(\n input: InputSignal<T> | InputSignalWithTransform<T, unknown>,\n value: T\n): void {\n input[SIGNAL].applyValueToInputSignal(input[SIGNAL], value);\n}\n\nexport function afterRenderComputed<T>(computeFn: () => T, defaultValue: T): () => T {\n const value = signal(defaultValue);\n afterRenderEffect(() => {\n value.set(computeFn());\n });\n return value.asReadonly();\n}\n\nexport function debounceSignal<T>(input: Signal<T>, delayMs: (() => number) | number): Signal<T> {\n const delayFn = typeof delayMs === 'function' ? delayMs : () => delayMs;\n const debounced = signal(input());\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n effect(onCleanup => {\n const value = input();\n const delay = delayFn();\n\n // Clear any pending timeout\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n\n // Set new timeout\n timeoutId = setTimeout(() => {\n debounced.set(value);\n timeoutId = undefined;\n }, delay);\n\n // Cleanup function to clear timeout when effect is destroyed or re-run\n onCleanup(() => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n timeoutId = undefined;\n }\n });\n });\n\n return debounced.asReadonly();\n}\n","import { toggleClass } from '@ngneers/controls/utils';\n\nimport { effectWithPrevious } from './signals';\n\nimport type { Signal } from '@angular/core';\n\nexport function classSignal(element: HTMLElement, klass: Signal<string | string[]>) {\n effectWithPrevious(klass, (current, previous) => {\n if (previous) {\n toggleClass(element, previous, false);\n }\n if (current) {\n toggleClass(element, current, true);\n }\n });\n}\n","const FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n].join(',');\n\n/** Visible, focusable descendants of `container`, in DOM order. */\nfunction getFocusable(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n el => el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0\n );\n}\n\n/**\n * Keeps keyboard focus inside a single container for the duration a modal\n * overlay is open. On {@link activate} it remembers what was focused, moves\n * focus into the container, and wraps `Tab`/`Shift+Tab` at the edges;\n * {@link deactivate} tears the listener down and restores the prior focus.\n *\n * The container itself is focused as a fallback when it has no focusable\n * children, so focus never escapes to the (inert) background.\n */\nexport class FocusTrap {\n private _previouslyFocused: HTMLElement | null = null;\n private _active = false;\n\n constructor(private readonly container: HTMLElement) {}\n\n public activate(): void {\n if (this._active) return;\n this._active = true;\n this._previouslyFocused = document.activeElement as HTMLElement | null;\n this.container.addEventListener('keydown', this._onKeydown);\n\n const focusable = getFocusable(this.container);\n const target = focusable[0] ?? this.container;\n if (target === this.container && !this.container.hasAttribute('tabindex')) {\n this.container.tabIndex = -1;\n }\n target.focus();\n }\n\n public deactivate(): void {\n if (!this._active) return;\n this._active = false;\n this.container.removeEventListener('keydown', this._onKeydown);\n // Restore focus only if it is still inside the trap — otherwise the user\n // has already moved on and we must not yank it back.\n if (this.container.contains(document.activeElement)) {\n this._previouslyFocused?.focus?.();\n }\n this._previouslyFocused = null;\n }\n\n private readonly _onKeydown = (event: KeyboardEvent): void => {\n if (event.key !== 'Tab') return;\n const focusable = getFocusable(this.container);\n if (focusable.length === 0) {\n // Nothing to move to — keep focus pinned to the container.\n event.preventDefault();\n this.container.focus();\n return;\n }\n const first = focusable[0]!;\n const last = focusable[focusable.length - 1]!;\n const active = document.activeElement;\n if (event.shiftKey && active === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && active === last) {\n event.preventDefault();\n first.focus();\n }\n };\n}\n","import { DOCUMENT, inject, Injectable } from '@angular/core';\nimport { globalPropertyName, type NgnGlobalType } from '@ngneers/controls/utils';\n\n@Injectable()\nexport class NgnGlobal implements NgnGlobalType {\n private readonly _window = inject(DOCUMENT).defaultView || window;\n constructor() {\n this._window[globalPropertyName] ??= {\n nextElementId: 1,\n fancyLogging: true,\n };\n }\n\n public get nextElementId(): number {\n return this._window[globalPropertyName].nextElementId;\n }\n public set nextElementId(value: number) {\n this._window[globalPropertyName].nextElementId = value;\n }\n\n public get fancyLogging(): boolean {\n return this._window[globalPropertyName].fancyLogging;\n }\n public set fancyLogging(value: boolean) {\n this._window[globalPropertyName].fancyLogging = value;\n }\n}\n","import { inject } from '@angular/core';\n\nimport { NgnGlobal } from './globals';\n\nconst idPrefix = 'ngn-id-';\n\nexport function generateElementId() {\n return idPrefix + inject(NgnGlobal).nextElementId++;\n}\n","import { inject, type ProviderToken } from '@angular/core';\nimport { throwExp } from '@ngneers/controls/utils';\n\nexport function injectOrThrow<T>(token: ProviderToken<T>, moduleName: string, errorMsg: string): T {\n return inject(token, { optional: true }) ?? throwExp(moduleName, errorMsg);\n}\n","import { signal } from '@angular/core';\n\n/**\n * An item managed by a {@link NotificationRegionController} — a single snackbar or\n * toast. The controller drives focus and timer state through this narrow contract.\n */\nexport interface NotificationRegionItem {\n /** Move DOM focus to this item's root element. */\n focus(): void;\n /** Freeze the auto-hide timer because the region as a whole holds focus. */\n regionPause(): void;\n /** Release the region-level freeze; the item resumes unless still hovered/focused. */\n regionResume(): void;\n}\n\n/**\n * Keyboard-accessibility controller for a stack of transient notifications\n * (snackbars / toasts) rendered inside a single host region.\n *\n * Implements the WAI-ARIA APG guidance for toasts: focus is never stolen when a\n * notification appears, but a global hotkey (`F6`) lets the user jump into the\n * region on demand. Within the region, a roving-tabindex model exposes exactly one\n * item to the Tab sequence while `ArrowUp`/`ArrowDown`/`Home`/`End` move between\n * items. Whenever the region holds focus, every timer in it is paused so nothing\n * disappears mid-read.\n *\n * The host component owns the wiring: it forwards its events to the handlers here\n * and binds {@link tabbableIndex} to each item's `tabindex`.\n */\nexport class NotificationRegionController<T extends NotificationRegionItem> {\n /** The item index currently exposed to the Tab sequence (roving tabindex). */\n public readonly activeIndex = signal(0);\n\n private _regionFocused = false;\n\n /**\n * @param host The region's root element, used to scope focus containment checks.\n * @param items A getter returning the live, ordered list of items (oldest first).\n */\n constructor(\n private readonly host: HTMLElement,\n private readonly items: () => readonly T[]\n ) {}\n\n /**\n * The roving tabindex target, clamped to the current item count so the region\n * always has exactly one tabbable entry point even after items are removed.\n */\n public tabbableIndex(): number {\n const count = this.items().length;\n return count === 0 ? -1 : Math.min(this.activeIndex(), count - 1);\n }\n\n /** Document-level handler: `F6` moves focus to the newest notification. */\n public handleGlobalKeydown(event: KeyboardEvent): void {\n if (event.key !== 'F6') {\n return;\n }\n const items = this.items();\n if (items.length === 0) {\n return;\n }\n event.preventDefault();\n this.focusIndex(items.length - 1);\n }\n\n /** Region-level handler: arrow / Home / End roving between notifications. */\n public handleKeydown(event: KeyboardEvent): void {\n const items = this.items();\n if (items.length === 0) {\n return;\n }\n const current = Math.min(this.activeIndex(), items.length - 1);\n let next: number;\n switch (event.key) {\n case 'ArrowDown':\n next = Math.min(current + 1, items.length - 1);\n break;\n case 'ArrowUp':\n next = Math.max(current - 1, 0);\n break;\n case 'Home':\n next = 0;\n break;\n case 'End':\n next = items.length - 1;\n break;\n default:\n return;\n }\n event.preventDefault();\n this.focusIndex(next);\n }\n\n /** Region gained focus (via hotkey, Tab, or click) — pause every timer in it. */\n public handleFocusIn(): void {\n this._regionFocused = true;\n for (const item of this.items()) {\n item.regionPause();\n }\n }\n\n /** Region lost focus to something outside it — resume every timer. */\n public handleFocusOut(event: FocusEvent): void {\n const next = event.relatedTarget as Node | null;\n if (next && this.host.contains(next)) {\n return;\n }\n this._regionFocused = false;\n for (const item of this.items()) {\n item.regionResume();\n }\n }\n\n private focusIndex(index: number): void {\n this.activeIndex.set(index);\n this.items()[index]?.focus();\n }\n}\n","import {\n Injector,\n DestroyRef,\n inject,\n DOCUMENT,\n signal,\n afterRenderEffect,\n untracked,\n effect,\n} from '@angular/core';\n\nexport type NgnStateStorage = 'local' | 'session';\n\nexport function loadState<T>(storage: NgnStateStorage, key: string) {\n const storageType = storage === 'local' ? localStorage : sessionStorage;\n const state = storageType.getItem(key);\n return state ? (JSON.parse(state) as T) : null;\n}\n\nexport function saveState<T>(storage: NgnStateStorage, key: string, state: T | null) {\n const storageType = storage === 'local' ? localStorage : sessionStorage;\n if (state === null) {\n storageType.removeItem(key);\n return;\n }\n storageType.setItem(key, JSON.stringify(state));\n}\n\nexport type RegisterStateOptions<T> = {\n storage: () => NgnStateStorage;\n key: () => string | null | undefined;\n valueFn: (previousState: T | null) => T | null;\n onLoad: (state: T | null) => T | null;\n debounce?: number;\n injector?: Injector;\n};\nexport function registerState<T>(options: RegisterStateOptions<T>) {\n const { storage, key, valueFn, onLoad, debounce } = options;\n const destroyRef = options?.injector?.get(DestroyRef) ?? inject(DestroyRef);\n const document = options?.injector?.get<Document>(DOCUMENT) ?? inject(DOCUMENT);\n\n const load = () => {\n const k = key();\n return k ? loadState<T>(storage(), k) : null;\n };\n\n const stateSignal = signal<T | null | undefined>(undefined);\n\n let timer: ReturnType<typeof setTimeout> | undefined = undefined;\n const save = () => {\n const k = key();\n const s = stateSignal();\n if (k && s !== undefined) saveState(storage(), k, s);\n };\n\n afterRenderEffect(() => {\n let state = load();\n if (onLoad) {\n state = untracked(() => onLoad(state));\n }\n stateSignal.set(state);\n }, options);\n afterRenderEffect(() => {\n stateSignal.set(valueFn(untracked(() => stateSignal() ?? null)));\n }, options);\n effect(() => {\n stateSignal();\n if (debounce === 0) {\n save();\n } else {\n clearTimeout(timer);\n timer = setTimeout(save, debounce);\n }\n }, options);\n\n // Ensure saving happens on destroy and unload\n document.defaultView?.addEventListener('beforeunload', save);\n destroyRef.onDestroy(() => {\n clearTimeout(timer);\n document.defaultView?.removeEventListener('beforeunload', save);\n save();\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}