@ngneers/controls 0.0.1-pre1 → 0.0.1-pre3

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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/fesm2022/ngneers-controls-accordion.mjs +194 -0
  3. package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
  4. package/fesm2022/ngneers-controls-api-ng.mjs +668 -0
  5. package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
  6. package/fesm2022/ngneers-controls-api.mjs +256 -227
  7. package/fesm2022/ngneers-controls-api.mjs.map +1 -1
  8. package/fesm2022/ngneers-controls-avatar.mjs +70 -0
  9. package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
  10. package/fesm2022/ngneers-controls-base.mjs +397 -0
  11. package/fesm2022/ngneers-controls-base.mjs.map +1 -0
  12. package/fesm2022/ngneers-controls-breadcrumb.mjs +74 -0
  13. package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
  14. package/fesm2022/ngneers-controls-button-group.mjs +51 -0
  15. package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
  16. package/fesm2022/ngneers-controls-button.mjs +62 -0
  17. package/fesm2022/ngneers-controls-button.mjs.map +1 -0
  18. package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs +63 -0
  19. package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs.map +1 -0
  20. package/fesm2022/ngneers-controls-calendar.mjs +468 -0
  21. package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
  22. package/fesm2022/ngneers-controls-checkbox.mjs +58 -0
  23. package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
  24. package/fesm2022/ngneers-controls-chip.mjs +52 -0
  25. package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
  26. package/fesm2022/ngneers-controls-defer.mjs +43 -0
  27. package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
  28. package/fesm2022/ngneers-controls-dialog.mjs +329 -33
  29. package/fesm2022/ngneers-controls-dialog.mjs.map +1 -1
  30. package/fesm2022/ngneers-controls-directives.mjs +443 -0
  31. package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
  32. package/fesm2022/ngneers-controls-drawer.mjs +232 -0
  33. package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
  34. package/fesm2022/ngneers-controls-edit-inplace.mjs +120 -0
  35. package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
  36. package/fesm2022/ngneers-controls-filter.mjs +516 -0
  37. package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
  38. package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs +87 -0
  39. package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs.map +1 -0
  40. package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs +87 -0
  41. package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs.map +1 -0
  42. package/fesm2022/ngneers-controls-i18n.mjs +57 -0
  43. package/fesm2022/ngneers-controls-i18n.mjs.map +1 -0
  44. package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs +4 -0
  45. package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs.map +1 -0
  46. package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs +4 -0
  47. package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs.map +1 -0
  48. package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs +4 -0
  49. package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs.map +1 -0
  50. package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs +4 -0
  51. package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs.map +1 -0
  52. package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs +4 -0
  53. package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs.map +1 -0
  54. package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs +4 -0
  55. package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs.map +1 -0
  56. package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs +4 -0
  57. package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs.map +1 -0
  58. package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs +4 -0
  59. package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs.map +1 -0
  60. package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs +4 -0
  61. package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs.map +1 -0
  62. package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs +4 -0
  63. package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs.map +1 -0
  64. package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs +4 -0
  65. package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs.map +1 -0
  66. package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs +4 -0
  67. package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs.map +1 -0
  68. package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs +4 -0
  69. package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs.map +1 -0
  70. package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs +4 -0
  71. package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs.map +1 -0
  72. package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs +4 -0
  73. package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs.map +1 -0
  74. package/fesm2022/ngneers-controls-icon.mjs +60 -18
  75. package/fesm2022/ngneers-controls-icon.mjs.map +1 -1
  76. package/fesm2022/ngneers-controls-inplace.mjs +107 -0
  77. package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
  78. package/fesm2022/ngneers-controls-input-field.mjs +141 -0
  79. package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
  80. package/fesm2022/ngneers-controls-input-mask.mjs +282 -0
  81. package/fesm2022/ngneers-controls-input-mask.mjs.map +1 -0
  82. package/fesm2022/ngneers-controls-input.mjs +69 -0
  83. package/fesm2022/ngneers-controls-input.mjs.map +1 -0
  84. package/fesm2022/ngneers-controls-item-view.mjs +441 -0
  85. package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
  86. package/fesm2022/ngneers-controls-list-box.mjs +157 -53
  87. package/fesm2022/ngneers-controls-list-box.mjs.map +1 -1
  88. package/fesm2022/ngneers-controls-menu.mjs +332 -0
  89. package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
  90. package/fesm2022/ngneers-controls-message.mjs +29 -0
  91. package/fesm2022/ngneers-controls-message.mjs.map +1 -0
  92. package/fesm2022/ngneers-controls-paginator.mjs +111 -0
  93. package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
  94. package/fesm2022/ngneers-controls-popover.mjs +129 -40
  95. package/fesm2022/ngneers-controls-popover.mjs.map +1 -1
  96. package/fesm2022/ngneers-controls-progress.mjs +82 -0
  97. package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
  98. package/fesm2022/ngneers-controls-scroller.mjs +162 -78
  99. package/fesm2022/ngneers-controls-scroller.mjs.map +1 -1
  100. package/fesm2022/ngneers-controls-select-button.mjs +55 -0
  101. package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
  102. package/fesm2022/ngneers-controls-select.mjs +313 -103
  103. package/fesm2022/ngneers-controls-select.mjs.map +1 -1
  104. package/fesm2022/ngneers-controls-slider.mjs +155 -0
  105. package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
  106. package/fesm2022/ngneers-controls-spinner.mjs +169 -0
  107. package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
  108. package/fesm2022/ngneers-controls-splitter.mjs +717 -0
  109. package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
  110. package/fesm2022/ngneers-controls-switch.mjs +39 -0
  111. package/fesm2022/ngneers-controls-switch.mjs.map +1 -0
  112. package/fesm2022/ngneers-controls-table.mjs +379 -0
  113. package/fesm2022/ngneers-controls-table.mjs.map +1 -0
  114. package/fesm2022/ngneers-controls-tabs.mjs +287 -0
  115. package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
  116. package/fesm2022/ngneers-controls-tag.mjs +29 -0
  117. package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
  118. package/fesm2022/ngneers-controls-toast.mjs +184 -0
  119. package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
  120. package/fesm2022/ngneers-controls-toggle-button.mjs +65 -0
  121. package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
  122. package/fesm2022/ngneers-controls-tooltip.mjs +454 -0
  123. package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
  124. package/fesm2022/ngneers-controls-utils-ng.mjs +227 -0
  125. package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
  126. package/fesm2022/ngneers-controls-utils.mjs +217 -60
  127. package/fesm2022/ngneers-controls-utils.mjs.map +1 -1
  128. package/fesm2022/ngneers-controls.mjs.map +1 -1
  129. package/package.json +167 -32
  130. package/types/ngneers-controls-accordion.d.ts +114 -0
  131. package/types/ngneers-controls-api-ng.d.ts +291 -0
  132. package/types/ngneers-controls-api.d.ts +99 -0
  133. package/types/ngneers-controls-avatar.d.ts +50 -0
  134. package/types/ngneers-controls-base.d.ts +166 -0
  135. package/types/ngneers-controls-breadcrumb.d.ts +86 -0
  136. package/types/ngneers-controls-button-group.d.ts +30 -0
  137. package/types/ngneers-controls-button.d.ts +34 -0
  138. package/types/ngneers-controls-calendar.d.ts +275 -0
  139. package/types/ngneers-controls-checkbox.d.ts +38 -0
  140. package/types/ngneers-controls-chip.d.ts +37 -0
  141. package/types/ngneers-controls-defer.d.ts +22 -0
  142. package/types/ngneers-controls-dialog.d.ts +218 -0
  143. package/types/ngneers-controls-directives.d.ts +146 -0
  144. package/types/ngneers-controls-drawer.d.ts +220 -0
  145. package/types/ngneers-controls-edit-inplace.d.ts +182 -0
  146. package/types/ngneers-controls-filter.d.ts +304 -0
  147. package/types/ngneers-controls-i18n.d.ts +108 -0
  148. package/types/ngneers-controls-icon.d.ts +74 -0
  149. package/types/ngneers-controls-inplace.d.ts +95 -0
  150. package/types/ngneers-controls-input-field.d.ts +159 -0
  151. package/types/ngneers-controls-input-mask.d.ts +83 -0
  152. package/types/ngneers-controls-input.d.ts +27 -0
  153. package/types/ngneers-controls-item-view.d.ts +211 -0
  154. package/types/ngneers-controls-list-box.d.ts +216 -0
  155. package/types/ngneers-controls-menu.d.ts +178 -0
  156. package/types/ngneers-controls-message.d.ts +19 -0
  157. package/types/ngneers-controls-paginator.d.ts +162 -0
  158. package/types/ngneers-controls-popover.d.ts +101 -0
  159. package/types/ngneers-controls-progress.d.ts +44 -0
  160. package/types/ngneers-controls-scroller.d.ts +137 -0
  161. package/types/ngneers-controls-select-button.d.ts +37 -0
  162. package/types/ngneers-controls-select.d.ts +314 -0
  163. package/types/ngneers-controls-slider.d.ts +53 -0
  164. package/types/ngneers-controls-spinner.d.ts +105 -0
  165. package/types/ngneers-controls-splitter.d.ts +391 -0
  166. package/types/ngneers-controls-switch.d.ts +18 -0
  167. package/types/ngneers-controls-table.d.ts +157 -0
  168. package/types/ngneers-controls-tabs.d.ts +106 -0
  169. package/types/ngneers-controls-tag.d.ts +19 -0
  170. package/types/ngneers-controls-toast.d.ts +70 -0
  171. package/types/ngneers-controls-toggle-button.d.ts +46 -0
  172. package/types/ngneers-controls-tooltip.d.ts +188 -0
  173. package/types/ngneers-controls-utils-ng.d.ts +57 -0
  174. package/types/ngneers-controls-utils.d.ts +130 -0
  175. package/api/index.d.ts +0 -134
  176. package/custom-types/index.d.ts +0 -7
  177. package/dialog/index.d.ts +0 -43
  178. package/fesm2022/ngneers-controls-custom-types.mjs +0 -4
  179. package/fesm2022/ngneers-controls-custom-types.mjs.map +0 -1
  180. package/fesm2022/ngneers-controls-form-field.mjs +0 -33
  181. package/fesm2022/ngneers-controls-form-field.mjs.map +0 -1
  182. package/fesm2022/ngneers-controls-lazy-cacher.mjs +0 -30
  183. package/fesm2022/ngneers-controls-lazy-cacher.mjs.map +0 -1
  184. package/fesm2022/ngneers-controls-text-field.mjs +0 -23
  185. package/fesm2022/ngneers-controls-text-field.mjs.map +0 -1
  186. package/form-field/index.d.ts +0 -19
  187. package/icon/index.d.ts +0 -30
  188. package/lazy-cacher/index.d.ts +0 -14
  189. package/list-box/index.d.ts +0 -58
  190. package/popover/index.d.ts +0 -41
  191. package/scroller/index.d.ts +0 -95
  192. package/select/index.d.ts +0 -86
  193. package/text-field/index.d.ts +0 -10
  194. package/utils/index.d.ts +0 -36
  195. /package/{index.d.ts → types/ngneers-controls.d.ts} +0 -0
@@ -0,0 +1,668 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, provideAppInitializer, inject, ElementRef, computed, signal, afterRenderEffect, DestroyRef, Injector, runInInjectionContext, effect, PLATFORM_ID, DOCUMENT, Injectable, untracked, input, Directive } from '@angular/core';
3
+ import { registerCustomLanguages, I18n } from '@ngneers/controls/i18n';
4
+ import { Logger, deepCopy } from '@ngneers/controls/utils';
5
+ import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
6
+ import { signalWithPrevious, NgnGlobal } from '@ngneers/controls/utils-ng';
7
+ import { Subject, fromEvent, skip } from 'rxjs';
8
+ import { isPlatformBrowser } from '@angular/common';
9
+ import { flip, shift, computePosition, offset, size, autoUpdate } from '@floating-ui/dom';
10
+ import { getClassName, applyTheme, applyGlobalStyles } from '@ngneers/controls-themes';
11
+ import { globalStyles } from '@ngneers/controls-themes/base/global';
12
+
13
+ const NGN_CONFIG = new InjectionToken('NGN_CONFIG');
14
+ const defaultNgnConfig = {
15
+ logLevel: 'info',
16
+ disableAnimations: false,
17
+ theme: {
18
+ preset: null,
19
+ lazyLoaded: false,
20
+ styleScope: null,
21
+ cssLayer: 'ngn-controls',
22
+ namePrefix: 'ngn-',
23
+ },
24
+ defaults: {
25
+ stateStorage: 'session',
26
+ splitter: {
27
+ stateStorage: 'session',
28
+ },
29
+ tooltip: {
30
+ placement: 'bottom',
31
+ offset: 4,
32
+ showDelay: '0.5s',
33
+ hideDelay: '0.1s',
34
+ showArrow: true,
35
+ showOnHover: true,
36
+ showOnFocus: true,
37
+ hideOnTooltipHover: false,
38
+ hideOnClick: true,
39
+ },
40
+ },
41
+ };
42
+ function provideNgnConfig(config) {
43
+ return [
44
+ {
45
+ provide: NGN_CONFIG,
46
+ useValue: {
47
+ logLevel: config?.logLevel ?? defaultNgnConfig.logLevel,
48
+ customTranslations: config?.customTranslations,
49
+ disableAnimations: config?.disableAnimations ?? defaultNgnConfig.disableAnimations,
50
+ theme: {
51
+ preset: config?.theme?.preset ?? defaultNgnConfig.theme.preset,
52
+ lazyLoaded: config?.theme?.lazyLoaded ?? defaultNgnConfig.theme.lazyLoaded,
53
+ styleScope: config?.theme?.styleScope ?? defaultNgnConfig.theme.styleScope,
54
+ cssLayer: config?.theme?.cssLayer === undefined
55
+ ? defaultNgnConfig.theme.cssLayer
56
+ : config?.theme?.cssLayer,
57
+ namePrefix: config?.theme?.namePrefix ?? defaultNgnConfig.theme.namePrefix,
58
+ },
59
+ defaults: {
60
+ stateStorage: config?.defaults?.stateStorage ?? defaultNgnConfig.defaults.stateStorage,
61
+ splitter: {
62
+ stateStorage: config?.defaults?.splitter?.stateStorage ??
63
+ config?.defaults?.stateStorage ??
64
+ defaultNgnConfig.defaults.splitter.stateStorage,
65
+ },
66
+ tooltip: {
67
+ placement: config?.defaults?.tooltip?.placement ?? defaultNgnConfig.defaults.tooltip.placement,
68
+ offset: config?.defaults?.tooltip?.offset ?? defaultNgnConfig.defaults.tooltip.offset,
69
+ showDelay: config?.defaults?.tooltip?.showDelay ?? defaultNgnConfig.defaults.tooltip.showDelay,
70
+ hideDelay: config?.defaults?.tooltip?.hideDelay ?? defaultNgnConfig.defaults.tooltip.hideDelay,
71
+ showArrow: config?.defaults?.tooltip?.showArrow ?? defaultNgnConfig.defaults.tooltip.showArrow,
72
+ showOnHover: config?.defaults?.tooltip?.showOnHover ??
73
+ defaultNgnConfig.defaults.tooltip.showOnHover,
74
+ showOnFocus: config?.defaults?.tooltip?.showOnFocus ??
75
+ defaultNgnConfig.defaults.tooltip.showOnFocus,
76
+ hideOnTooltipHover: config?.defaults?.tooltip?.hideOnTooltipHover ??
77
+ defaultNgnConfig.defaults.tooltip.hideOnTooltipHover,
78
+ hideOnClick: config?.defaults?.tooltip?.hideOnClick ??
79
+ defaultNgnConfig.defaults.tooltip.hideOnClick,
80
+ },
81
+ },
82
+ },
83
+ },
84
+ provideAppInitializer(() => {
85
+ const config = inject(NGN_CONFIG);
86
+ if (config?.customTranslations) {
87
+ registerCustomLanguages(config.customTranslations);
88
+ }
89
+ Logger.logLevel = config.logLevel ?? Logger.logLevel;
90
+ }),
91
+ ];
92
+ }
93
+
94
+ function toPopoverCloseBy(closeBy) {
95
+ switch (closeBy) {
96
+ case 'any':
97
+ return 'auto';
98
+ case 'escape':
99
+ case 'none':
100
+ return 'manual';
101
+ }
102
+ }
103
+ function toModalCloseBy(closeBy) {
104
+ switch (closeBy) {
105
+ case 'any':
106
+ return 'any';
107
+ case 'escape':
108
+ return 'closerequest';
109
+ case 'none':
110
+ return 'none';
111
+ }
112
+ }
113
+
114
+ function setComponentInput(componentRef, inputName, value) {
115
+ componentRef.setInput(inputName, value);
116
+ }
117
+
118
+ function getElement(el) {
119
+ const rawElement = typeof el === 'function' ? el() : el;
120
+ const element = rawElement instanceof ElementRef ? rawElement.nativeElement : rawElement;
121
+ return element;
122
+ }
123
+ function elementSizeSignal(element, active) {
124
+ const val = elementsSizesSignalInt(element, active);
125
+ return computed(() => val()[0] ?? { width: 0, height: 0 });
126
+ }
127
+ function elementsSizesSignal(element, active) {
128
+ return elementsSizesSignalInt(element, active);
129
+ }
130
+ function elementsSizesSignalInt(element, active) {
131
+ const sizeSignal = signal([], { ...(ngDevMode ? { debugName: "sizeSignal" } : {}), equal: (a, b) => JSON.stringify(a) === JSON.stringify(b) });
132
+ let elements;
133
+ afterRenderEffect(() => {
134
+ resizeObserver.disconnect();
135
+ if (active && !active()) {
136
+ return;
137
+ }
138
+ const rawElement = typeof element === 'function' ? element() : element;
139
+ const arrayElement = Array.isArray(rawElement) ? rawElement : rawElement ? [rawElement] : [];
140
+ elements = arrayElement.map(el => (el instanceof ElementRef ? el.nativeElement : el));
141
+ if (!elements.length) {
142
+ return;
143
+ }
144
+ sizeSignal.set(elements.map(el => {
145
+ const rect = el.getBoundingClientRect();
146
+ return {
147
+ width: rect.width,
148
+ height: rect.height,
149
+ };
150
+ }));
151
+ elements.forEach(el => {
152
+ resizeObserver.observe(el, { box: 'border-box' });
153
+ });
154
+ });
155
+ const destroyRef = inject(DestroyRef);
156
+ if (typeof ResizeObserver === 'undefined') {
157
+ return sizeSignal; // ResizeObserver is not supported, return initial size
158
+ }
159
+ const resizeObserver = new ResizeObserver(entries => {
160
+ entries.forEach(entry => {
161
+ const index = elements.findIndex(el => el === entry.target);
162
+ sizeSignal.update(s => {
163
+ const copy = deepCopy(s);
164
+ const borderBoxSize = entry.borderBoxSize[0];
165
+ if (!borderBoxSize) {
166
+ return s;
167
+ }
168
+ copy[index] = {
169
+ width: borderBoxSize.inlineSize,
170
+ height: borderBoxSize.blockSize,
171
+ };
172
+ return copy;
173
+ });
174
+ });
175
+ });
176
+ destroyRef.onDestroy(() => {
177
+ resizeObserver.disconnect();
178
+ });
179
+ return sizeSignal;
180
+ }
181
+ const ABORT_SIGNAL_SYMBOL = Symbol('AbortSignal');
182
+ function abortSignalOnDestroy(options) {
183
+ const destroyRef = options?.injector?.get(DestroyRef) ?? inject(DestroyRef);
184
+ if (ABORT_SIGNAL_SYMBOL in destroyRef) {
185
+ return destroyRef[ABORT_SIGNAL_SYMBOL];
186
+ }
187
+ const abortController = new AbortController();
188
+ destroyRef.onDestroy(() => {
189
+ abortController.abort();
190
+ });
191
+ destroyRef[ABORT_SIGNAL_SYMBOL] = abortController.signal;
192
+ return abortController.signal;
193
+ }
194
+ /**
195
+ * Creates an Observable that emits the latest event of the specified type from the given DOM element.
196
+ *
197
+ * ⚠️ Cannot be used to cancel or call preventDefault on the event, as the event is emitted after the event handler phase.
198
+ * @param element The target DOM element or ElementRef. Either can be provided directly or via a Signal.
199
+ * @param eventName The name of the event to listen for.
200
+ * @param injector Optional injector to use for lifecycle management. If not provided, the current injector is used.
201
+ * @returns An Observable that emits the latest event of the specified type. Does not complete until the injector is destroyed.
202
+ */
203
+ function domEventObservable(element, eventName, injector) {
204
+ const inj = injector ?? inject(Injector);
205
+ const result = new Subject();
206
+ const destroyRef = inj.get(DestroyRef);
207
+ let subscription;
208
+ runInInjectionContext(inj, () => {
209
+ afterRenderEffect(() => {
210
+ subscription?.unsubscribe();
211
+ const el = getElement(element);
212
+ if (!el) {
213
+ return;
214
+ }
215
+ subscription = fromEvent(el, eventName)
216
+ .pipe(takeUntilDestroyed(destroyRef))
217
+ .subscribe(e => result.next(e));
218
+ });
219
+ });
220
+ return result.asObservable().pipe(takeUntilDestroyed(destroyRef));
221
+ }
222
+ /**
223
+ * Creates a Signal that emits the latest event of the specified type from the given DOM element.
224
+ *
225
+ * ⚠️ Cannot be used to cancel or call preventDefault on the event, as the event is emitted after the event handler phase.
226
+ * @param element The target DOM element or ElementRef. Either can be provided directly or via a Signal.
227
+ * @param eventName The name of the event to listen for.
228
+ * @param injector Optional injector to use for lifecycle management. If not provided, the current injector is used.
229
+ * @returns A Signal that emits the latest event of the specified type or null if no event has occurred.
230
+ */
231
+ function domEventSignal(element, eventName, injector) {
232
+ const inj = injector ?? inject(Injector);
233
+ const res = runInInjectionContext(inj, () => {
234
+ const sig = signal(null, ...(ngDevMode ? [{ debugName: "sig" }] : []));
235
+ domEventObservable(element, eventName, inj).subscribe(value => {
236
+ sig.set(value);
237
+ });
238
+ return sig;
239
+ });
240
+ return res;
241
+ }
242
+ /**
243
+ * Attaches an event handler to a DOM element that is automatically removed when the injector is destroyed.
244
+ * @param element The target DOM element or ElementRef. Either can be provided directly or via a Signal.
245
+ * @param eventName The name of the event to listen for.
246
+ * @param handler The function to handle the event.
247
+ * @param injector Optional injector to use for lifecycle management. If not provided, the current injector is used.
248
+ */
249
+ function domEventHandler(element, eventName, handler, injector) {
250
+ const inj = injector ?? inject(Injector);
251
+ const destroyRef = inj.get(DestroyRef);
252
+ runInInjectionContext(inj, () => {
253
+ const destroyed = signal(false, ...(ngDevMode ? [{ debugName: "destroyed" }] : []));
254
+ destroyRef.onDestroy(() => {
255
+ destroyed.set(true);
256
+ });
257
+ const elSig = computed(() => (destroyed() ? null : getElement(element)), ...(ngDevMode ? [{ debugName: "elSig" }] : []));
258
+ const elSigWithPrev = signalWithPrevious(elSig);
259
+ effect(() => {
260
+ const element = elSigWithPrev();
261
+ const previousElement = element.previous;
262
+ if (previousElement) {
263
+ previousElement.removeEventListener(eventName, handler);
264
+ }
265
+ if (element.current) {
266
+ element.current.addEventListener(eventName, handler);
267
+ }
268
+ });
269
+ });
270
+ }
271
+
272
+ /**
273
+ * Retrieves the available kinds for a given control from the theme configuration.
274
+ * Does **not** return custom kinds defined by the user in `NgnCustomTypes`.
275
+ * @param controlName The name of the control to get kinds for.
276
+ * @returns A tuple of available kinds for the specified control.
277
+ * @todo make reactive (signal)
278
+ */
279
+ function injectThemeControlKinds(controlName) {
280
+ const val = inject(NGN_CONFIG).theme.preset?.meta.kinds?.[controlName] ?? [];
281
+ return val;
282
+ }
283
+ /**
284
+ * Retrieves the available colors from the theme configuration.
285
+ * Does **not** return custom colors defined by the user in `NgnCustomTypes`.
286
+ * @returns A tuple of available colors.
287
+ * @todo make reactive (signal)
288
+ */
289
+ function injectThemeColors(controlName) {
290
+ const theme = inject(NGN_CONFIG).theme;
291
+ if (controlName) {
292
+ const classNames = theme.preset?.parts.find(x => x.scope === controlName)?.controlTemplate
293
+ ?.classNames;
294
+ const hasColor = classNames?.includes('color-*');
295
+ if (!hasColor) {
296
+ return [];
297
+ }
298
+ }
299
+ const val = theme.preset?.meta.colors ?? [];
300
+ return val;
301
+ }
302
+
303
+ class Platform {
304
+ _deviceType = signal('desktop', ...(ngDevMode ? [{ debugName: "_deviceType" }] : []));
305
+ isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
306
+ windowSize = this.isBrowser
307
+ ? elementSizeSignal(document.body)
308
+ : signal({ width: 0, height: 0 });
309
+ width = computed(() => this.windowSize().width, ...(ngDevMode ? [{ debugName: "width" }] : []));
310
+ height = computed(() => this.windowSize().height, ...(ngDevMode ? [{ debugName: "height" }] : []));
311
+ constructor() {
312
+ const doc = inject(DOCUMENT);
313
+ const win = doc.defaultView;
314
+ if (!win) {
315
+ return;
316
+ }
317
+ if (typeof win.matchMedia !== 'function') {
318
+ return;
319
+ }
320
+ const hasMouse = win.matchMedia('(any-hover: hover)').matches;
321
+ if (hasMouse) {
322
+ this._deviceType.set('desktop');
323
+ return;
324
+ }
325
+ const isSmallScreen = window.matchMedia('(max-width: 768px)').matches ||
326
+ window.matchMedia('(max-height: 768px)').matches;
327
+ if (isSmallScreen) {
328
+ this._deviceType.set('mobile');
329
+ }
330
+ else {
331
+ this._deviceType.set('tablet');
332
+ }
333
+ }
334
+ isTouchDevice = computed(() => {
335
+ return this._deviceType() === 'mobile' || this._deviceType() === 'tablet';
336
+ }, ...(ngDevMode ? [{ debugName: "isTouchDevice" }] : []));
337
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Platform, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
338
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Platform });
339
+ }
340
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Platform, decorators: [{
341
+ type: Injectable
342
+ }], ctorParameters: () => [] });
343
+
344
+ function filterNonNullishKeys(obj) {
345
+ return Object.fromEntries(Object.entries(obj).filter(([, value]) => value != null));
346
+ }
347
+ function mergeWithDefaults(options) {
348
+ return {
349
+ placement: 'bottom',
350
+ flip: true,
351
+ resize: true,
352
+ shift: true,
353
+ offset: 4,
354
+ stopped: false,
355
+ ...filterNonNullishKeys(options),
356
+ };
357
+ }
358
+ function positionElement(anchor, floatingEl, options = {}) {
359
+ options = mergeWithDefaults(options);
360
+ const referenceElement = toReferenceElement(anchor);
361
+ const flipMiddleware = options.flip
362
+ ? flip(options.shift ? { crossAxis: 'alignment', fallbackAxisSideDirection: 'end' } : undefined)
363
+ : undefined;
364
+ const shiftMiddleware = options.shift ? shift() : undefined;
365
+ if (options.sizeConstraints) {
366
+ if (options.sizeConstraints.width || options.sizeConstraints.maxWidth) {
367
+ const refWidth = referenceElement.getBoundingClientRect().width;
368
+ if (options.sizeConstraints.width) {
369
+ if (typeof options.sizeConstraints.width === 'string') {
370
+ floatingEl.style.width = options.sizeConstraints.width;
371
+ }
372
+ else {
373
+ const widthConstraints = options.sizeConstraints.width * refWidth;
374
+ floatingEl.style.width = `min(100%, ${widthConstraints}px)`;
375
+ }
376
+ }
377
+ if (options.sizeConstraints.maxWidth) {
378
+ if (typeof options.sizeConstraints.maxWidth === 'string') {
379
+ floatingEl.style.maxWidth = options.sizeConstraints.maxWidth;
380
+ }
381
+ else {
382
+ const maxWidthConstraints = options.sizeConstraints.maxWidth * refWidth;
383
+ floatingEl.style.maxWidth = `min(100%, ${maxWidthConstraints}px)`;
384
+ }
385
+ }
386
+ }
387
+ if (options.sizeConstraints.height || options.sizeConstraints.maxHeight) {
388
+ if (options.sizeConstraints.height) {
389
+ floatingEl.style.height = options.sizeConstraints.height;
390
+ }
391
+ if (options.sizeConstraints.maxHeight) {
392
+ floatingEl.style.maxHeight = options.sizeConstraints.maxHeight;
393
+ }
394
+ }
395
+ if (options.sizeConstraints.minWidth) {
396
+ floatingEl.style.minWidth = options.sizeConstraints.minWidth;
397
+ }
398
+ }
399
+ computePosition(referenceElement, floatingEl, {
400
+ placement: options.placement,
401
+ strategy: options.strategy,
402
+ middleware: [
403
+ options.offset ? offset(options.offset) : undefined,
404
+ options.resize
405
+ ? size({
406
+ apply({ availableHeight }) {
407
+ const maxHeightConstraint = options.sizeConstraints?.maxHeight;
408
+ const maxHeightInPx = maxHeightConstraint?.replace(/px$/, '');
409
+ const maxHeight = maxHeightInPx
410
+ ? Math.min(availableHeight, parseInt(maxHeightInPx))
411
+ : availableHeight;
412
+ if (options.hasShrinkableContent) {
413
+ Object.assign(floatingEl.style, {
414
+ height: `${maxHeight - 1}px`,
415
+ });
416
+ }
417
+ },
418
+ })
419
+ : undefined,
420
+ ...(options.placement?.includes('-')
421
+ ? [flipMiddleware, shiftMiddleware]
422
+ : [shiftMiddleware, flipMiddleware]),
423
+ ...(options.middleware || []),
424
+ ].filter(Boolean),
425
+ }).then(pos => {
426
+ if (!options.disableSettingStyles) {
427
+ const flipped = pos.middlewareData.flip?.index;
428
+ const flippedToLREnd = flipped &&
429
+ (pos.placement.startsWith('left-') || pos.placement.startsWith('right-')) &&
430
+ pos.placement.endsWith('-end');
431
+ const flippedToTop = flipped && pos.placement.startsWith('top');
432
+ Object.assign(floatingEl.style, {
433
+ left: `${pos.x}px`,
434
+ top: `${pos.y}px`,
435
+ justifyContent: flippedToLREnd || flippedToTop ? 'flex-end' : 'flex-start',
436
+ });
437
+ }
438
+ options.onPositionChange?.(pos);
439
+ });
440
+ }
441
+ function toReferenceElement(anchor) {
442
+ const referenceElement = anchor instanceof HTMLElement
443
+ ? anchor
444
+ : {
445
+ getBoundingClientRect: () => ({
446
+ x: anchor.x,
447
+ y: anchor.y,
448
+ width: 1,
449
+ height: 1,
450
+ top: anchor.y,
451
+ right: anchor.x + 1,
452
+ bottom: anchor.y + 1,
453
+ left: anchor.x,
454
+ }),
455
+ };
456
+ return referenceElement;
457
+ }
458
+ function autoPositionElement(anchor, floatingEl, options = {}) {
459
+ options = mergeWithDefaults(options);
460
+ let cleanup;
461
+ const destroyRef = options.injector?.get(DestroyRef) ?? inject(DestroyRef);
462
+ function startAutoUpdate() {
463
+ cleanup = autoUpdate(toReferenceElement(anchor), floatingEl, () => {
464
+ positionElement(anchor, floatingEl, options);
465
+ });
466
+ return cleanup;
467
+ }
468
+ destroyRef.onDestroy(() => {
469
+ cleanup?.();
470
+ cleanup = undefined;
471
+ });
472
+ return {
473
+ start: () => {
474
+ cleanup?.();
475
+ startAutoUpdate();
476
+ },
477
+ stop: () => {
478
+ cleanup?.();
479
+ cleanup = undefined;
480
+ },
481
+ isRunning: () => !!cleanup,
482
+ };
483
+ }
484
+ function splitPlacement(placement) {
485
+ return placement.split('-');
486
+ }
487
+
488
+ function themeTemplateToTemplateInfo(config, template, options) {
489
+ return {
490
+ scope: template.scope,
491
+ class: (className) => getClassName(config.theme.namePrefix, template.scope, className, options?.unstyled?.()),
492
+ classes: (classes) => {
493
+ let result = '';
494
+ for (const className in classes) {
495
+ if (classes[className]) {
496
+ if (result)
497
+ result += ' ';
498
+ result += getClassName(config.theme.namePrefix, template.scope, className, options?.unstyled?.());
499
+ }
500
+ }
501
+ return result;
502
+ },
503
+ };
504
+ }
505
+ function injectThemeTemplate(template, options) {
506
+ const config = options?.injector?.get(NGN_CONFIG) ?? inject(NGN_CONFIG);
507
+ const themeService = options?.injector?.get(ThemeService) ?? inject(ThemeService);
508
+ themeService.loadScope(template.scope);
509
+ return themeTemplateToTemplateInfo(config, template, { unstyled: options?.unstyled });
510
+ }
511
+ function injectTheme(controlName, options) {
512
+ const themeService = options?.injector?.get(ThemeService) ?? inject(ThemeService);
513
+ const theme = themeService.activeTheme();
514
+ if (!theme) {
515
+ throw new Error(`No active theme is set. Cannot inject theme for control "${controlName}". Please provide a theme in the configuration or set lazyLoaded to true if you plan to load themes dynamically.`);
516
+ }
517
+ const template = theme.parts.find(part => part.scope === controlName)?.controlTemplate;
518
+ if (!template) {
519
+ throw new Error(`The active theme "${theme.name}" does not contain a template for control "${controlName}".`);
520
+ }
521
+ return template;
522
+ }
523
+ function getAppliedClasses(klass, themeTemplateInfo) {
524
+ function suffixes() {
525
+ if (typeof klass === 'string') {
526
+ return [klass];
527
+ }
528
+ else if (typeof klass === 'object' && klass !== null) {
529
+ return Object.entries(klass)
530
+ .filter(([_, value]) => (typeof value === 'function' ? value() : value))
531
+ .map(([key, _]) => key);
532
+ }
533
+ return [];
534
+ }
535
+ const classes = suffixes().map(suffix => ({
536
+ class: themeTemplateInfo.class(suffix),
537
+ name: suffix,
538
+ }));
539
+ return classes;
540
+ }
541
+ class ThemeService {
542
+ _config = inject(NGN_CONFIG);
543
+ _loadedScopes = new Set();
544
+ _document = inject(DOCUMENT);
545
+ activeTheme = signal(this._config.theme?.preset, ...(ngDevMode ? [{ debugName: "activeTheme" }] : []));
546
+ constructor() {
547
+ if (!this._config.theme?.preset && !this._config.theme?.lazyLoaded) {
548
+ console.warn('No active theme found. Please provide a theme in the configuration or set lazyLoaded to true if you plan to load themes dynamically.');
549
+ }
550
+ if (this._config.disableAnimations) {
551
+ const style = this._document.createElement('style');
552
+ style.setAttribute('ngn-style', '');
553
+ // we set the durations instead of setting animation/transition to none,
554
+ // so that the animation starts/ends are still applied & the events are still fired
555
+ style.innerHTML = `.ngn-control, .ngn-control * {
556
+ animation-duration: 0s !important;
557
+ transition-duration: 0s !important;
558
+ }`;
559
+ this._document.head.appendChild(style);
560
+ Logger.debug('Animations have been disabled via configuration.');
561
+ }
562
+ toObservable(this.activeTheme)
563
+ .pipe(takeUntilDestroyed(), skip(1))
564
+ .subscribe(this.onThemeChange.bind(this));
565
+ }
566
+ loadScope(scope) {
567
+ if (this._loadedScopes.has(scope)) {
568
+ Logger.debug(`Theme scope "${scope}" is already loaded.`);
569
+ return;
570
+ }
571
+ const activeTheme = untracked(() => this.activeTheme());
572
+ if (!activeTheme) {
573
+ Logger.debug(`No active theme set. Cannot load theme scope "${scope}". Scope will be loaded when the theme is set.`);
574
+ return;
575
+ }
576
+ else {
577
+ Logger.debug(`Loading theme scope "${scope}" for active theme "${activeTheme.name}".`);
578
+ this.applyTheme(activeTheme, [scope]);
579
+ }
580
+ this._loadedScopes.add(scope);
581
+ }
582
+ ngOnDestroy() {
583
+ Logger.debug('ThemeService is being destroyed. Unloading all theme scopes...');
584
+ this.unloadAllScopes();
585
+ this._loadedScopes.clear();
586
+ }
587
+ onThemeChange(newTheme) {
588
+ if (!newTheme) {
589
+ Logger.warn('The active theme has been set to null.');
590
+ this.unloadAllScopes();
591
+ return;
592
+ }
593
+ Logger.debug(`Active theme changed to "${newTheme.name}". Reloading scopes...`);
594
+ this._loadedScopes.forEach(scope => {
595
+ Logger.debug(`Reloading theme scope "${scope}" for active theme "${newTheme.name}".`);
596
+ this.applyTheme(newTheme, [scope]);
597
+ });
598
+ }
599
+ unloadAllScopes() {
600
+ Logger.warn('Unloading all theme scopes is not implemented yet. This is a placeholder method.');
601
+ }
602
+ applyTheme(theme, scopes) {
603
+ applyTheme(theme, scopes, {
604
+ document: this._document,
605
+ layer: this._config.theme.cssLayer ?? undefined,
606
+ styleScope: this._config.theme.styleScope ?? undefined,
607
+ namePrefix: this._config.theme.namePrefix,
608
+ });
609
+ applyGlobalStyles(globalStyles, {
610
+ document: this._document,
611
+ layer: this._config.theme.cssLayer ?? undefined,
612
+ styleScope: this._config.theme.styleScope ?? undefined,
613
+ namePrefix: this._config.theme.namePrefix,
614
+ });
615
+ }
616
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
617
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeService });
618
+ }
619
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeService, decorators: [{
620
+ type: Injectable
621
+ }], ctorParameters: () => [] });
622
+
623
+ function provideNgnControls(config, ...features) {
624
+ return [
625
+ NgnGlobal,
626
+ ThemeService,
627
+ I18n,
628
+ Platform,
629
+ provideNgnConfig(config),
630
+ ...features.map(f => f.providers).flat(),
631
+ ];
632
+ }
633
+
634
+ class NgnTemplate {
635
+ ngnTemplate = input.required(...(ngDevMode ? [{ debugName: "ngnTemplate" }] : []));
636
+ static ngTemplateContextGuard(dir, ctx) {
637
+ return true;
638
+ }
639
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnTemplate, deps: [], target: i0.ɵɵFactoryTarget.Directive });
640
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: NgnTemplate, isStandalone: true, selector: "ng-template[ngnTemplate]", inputs: { ngnTemplate: { classPropertyName: "ngnTemplate", publicName: "ngnTemplate", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
641
+ }
642
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnTemplate, decorators: [{
643
+ type: Directive,
644
+ args: [{
645
+ selector: 'ng-template[ngnTemplate]',
646
+ }]
647
+ }], propDecorators: { ngnTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngnTemplate", required: true }] }] } });
648
+ /**
649
+ * A noop with return type T.
650
+ * This function is used to define typed properties to use in a template.
651
+ */
652
+ function templateTypesFn() {
653
+ return {};
654
+ }
655
+ /**
656
+ * A noop with return type `{ $implicit: Implicit } & Named`.
657
+ * This function is used to define a typed property to use in a template.
658
+ */
659
+ function templateTypeFn() {
660
+ return {};
661
+ }
662
+
663
+ /**
664
+ * Generated bundle index. Do not edit.
665
+ */
666
+
667
+ export { NGN_CONFIG, NgnTemplate, Platform, ThemeService, abortSignalOnDestroy, autoPositionElement, defaultNgnConfig, domEventHandler, domEventObservable, domEventSignal, elementSizeSignal, elementsSizesSignal, getAppliedClasses, injectTheme, injectThemeColors, injectThemeControlKinds, injectThemeTemplate, positionElement, provideNgnConfig, provideNgnControls, setComponentInput, splitPlacement, templateTypeFn, templateTypesFn, themeTemplateToTemplateInfo, toModalCloseBy, toPopoverCloseBy };
668
+ //# sourceMappingURL=ngneers-controls-api-ng.mjs.map