@tailng-ui/primitives 0.1.0 → 0.12.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 (166) hide show
  1. package/README.md +97 -11
  2. package/package.json +9 -3
  3. package/src/index.d.ts +5 -0
  4. package/src/index.d.ts.map +1 -1
  5. package/src/index.js +5 -0
  6. package/src/index.js.map +1 -1
  7. package/src/lib/feedback/empty/tng-empty.d.ts.map +1 -1
  8. package/src/lib/feedback/empty/tng-empty.js +5 -0
  9. package/src/lib/feedback/empty/tng-empty.js.map +1 -1
  10. package/src/lib/feedback/progress-bar/tng-progress-bar.d.ts.map +1 -1
  11. package/src/lib/feedback/progress-bar/tng-progress-bar.js +4 -1
  12. package/src/lib/feedback/progress-bar/tng-progress-bar.js.map +1 -1
  13. package/src/lib/feedback/progress-spinner/tng-progress-spinner.d.ts.map +1 -1
  14. package/src/lib/feedback/progress-spinner/tng-progress-spinner.js +3 -1
  15. package/src/lib/feedback/progress-spinner/tng-progress-spinner.js.map +1 -1
  16. package/src/lib/feedback/skeleton/tng-skeleton.d.ts +1 -0
  17. package/src/lib/feedback/skeleton/tng-skeleton.d.ts.map +1 -1
  18. package/src/lib/feedback/skeleton/tng-skeleton.js +5 -0
  19. package/src/lib/feedback/skeleton/tng-skeleton.js.map +1 -1
  20. package/src/lib/feedback/toast/tng-toast.d.ts.map +1 -1
  21. package/src/lib/feedback/toast/tng-toast.js +2 -0
  22. package/src/lib/feedback/toast/tng-toast.js.map +1 -1
  23. package/src/lib/form/checkbox/tng-checkbox.d.ts.map +1 -1
  24. package/src/lib/form/checkbox/tng-checkbox.js +1 -0
  25. package/src/lib/form/checkbox/tng-checkbox.js.map +1 -1
  26. package/src/lib/form/chips/tng-chips.d.ts +53 -1
  27. package/src/lib/form/chips/tng-chips.d.ts.map +1 -1
  28. package/src/lib/form/chips/tng-chips.js +284 -1
  29. package/src/lib/form/chips/tng-chips.js.map +1 -1
  30. package/src/lib/form/combobox/tng-combobox.d.ts.map +1 -1
  31. package/src/lib/form/combobox/tng-combobox.js +1 -0
  32. package/src/lib/form/combobox/tng-combobox.js.map +1 -1
  33. package/src/lib/form/input-otp/tng-input-otp.d.ts +22 -0
  34. package/src/lib/form/input-otp/tng-input-otp.d.ts.map +1 -1
  35. package/src/lib/form/input-otp/tng-input-otp.js +106 -1
  36. package/src/lib/form/input-otp/tng-input-otp.js.map +1 -1
  37. package/src/lib/form/label/tng-label.d.ts +2 -0
  38. package/src/lib/form/label/tng-label.d.ts.map +1 -1
  39. package/src/lib/form/label/tng-label.js +10 -0
  40. package/src/lib/form/label/tng-label.js.map +1 -1
  41. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.trigger.d.ts +1 -0
  42. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.trigger.d.ts.map +1 -1
  43. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.trigger.js +26 -0
  44. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.trigger.js.map +1 -1
  45. package/src/lib/form/multiselect/tng-multiselect.d.ts.map +1 -1
  46. package/src/lib/form/multiselect/tng-multiselect.js +1 -0
  47. package/src/lib/form/multiselect/tng-multiselect.js.map +1 -1
  48. package/src/lib/form/radio/tng-radio.d.ts +26 -0
  49. package/src/lib/form/radio/tng-radio.d.ts.map +1 -1
  50. package/src/lib/form/radio/tng-radio.js +130 -1
  51. package/src/lib/form/radio/tng-radio.js.map +1 -1
  52. package/src/lib/form/slider/tng-slider.d.ts.map +1 -1
  53. package/src/lib/form/slider/tng-slider.js +1 -0
  54. package/src/lib/form/slider/tng-slider.js.map +1 -1
  55. package/src/lib/form/switch/tng-switch.d.ts.map +1 -1
  56. package/src/lib/form/switch/tng-switch.js +1 -0
  57. package/src/lib/form/switch/tng-switch.js.map +1 -1
  58. package/src/lib/form/textarea/tng-textarea.d.ts +6 -14
  59. package/src/lib/form/textarea/tng-textarea.d.ts.map +1 -1
  60. package/src/lib/form/textarea/tng-textarea.js +42 -85
  61. package/src/lib/form/textarea/tng-textarea.js.map +1 -1
  62. package/src/lib/form/toggle/tng-toggle.d.ts.map +1 -1
  63. package/src/lib/form/toggle/tng-toggle.js +1 -0
  64. package/src/lib/form/toggle/tng-toggle.js.map +1 -1
  65. package/src/lib/form/toggle-group/tng-toggle-group.d.ts.map +1 -1
  66. package/src/lib/form/toggle-group/tng-toggle-group.js +1 -0
  67. package/src/lib/form/toggle-group/tng-toggle-group.js.map +1 -1
  68. package/src/lib/layout/accordion/tng-accordion.d.ts +9 -0
  69. package/src/lib/layout/accordion/tng-accordion.d.ts.map +1 -1
  70. package/src/lib/layout/accordion/tng-accordion.js +113 -0
  71. package/src/lib/layout/accordion/tng-accordion.js.map +1 -1
  72. package/src/lib/layout/bottom-sheet/tng-bottom-sheet.d.ts.map +1 -1
  73. package/src/lib/layout/bottom-sheet/tng-bottom-sheet.js +1 -0
  74. package/src/lib/layout/bottom-sheet/tng-bottom-sheet.js.map +1 -1
  75. package/src/lib/layout/card/tng-card.d.ts.map +1 -1
  76. package/src/lib/layout/card/tng-card.js +10 -0
  77. package/src/lib/layout/card/tng-card.js.map +1 -1
  78. package/src/lib/layout/collapsible/tng-collapsible.d.ts.map +1 -1
  79. package/src/lib/layout/collapsible/tng-collapsible.js +3 -0
  80. package/src/lib/layout/collapsible/tng-collapsible.js.map +1 -1
  81. package/src/lib/layout/grid/tng-grid.d.ts.map +1 -1
  82. package/src/lib/layout/grid/tng-grid.js +1 -0
  83. package/src/lib/layout/grid/tng-grid.js.map +1 -1
  84. package/src/lib/layout/separator/tng-separator.d.ts.map +1 -1
  85. package/src/lib/layout/separator/tng-separator.js +1 -0
  86. package/src/lib/layout/separator/tng-separator.js.map +1 -1
  87. package/src/lib/layout/stepper/tng-stepper.d.ts.map +1 -1
  88. package/src/lib/layout/stepper/tng-stepper.js +1 -0
  89. package/src/lib/layout/stepper/tng-stepper.js.map +1 -1
  90. package/src/lib/layout/tree/__tests__/tng-tree.test-harness.d.ts +20 -0
  91. package/src/lib/layout/tree/__tests__/tng-tree.test-harness.d.ts.map +1 -0
  92. package/src/lib/layout/tree/__tests__/tng-tree.test-harness.js +106 -0
  93. package/src/lib/layout/tree/__tests__/tng-tree.test-harness.js.map +1 -0
  94. package/src/lib/layout/tree/index.d.ts +5 -0
  95. package/src/lib/layout/tree/index.d.ts.map +1 -0
  96. package/src/lib/layout/tree/index.js +5 -0
  97. package/src/lib/layout/tree/index.js.map +1 -0
  98. package/src/lib/layout/tree/tng-tree-group.d.ts +10 -0
  99. package/src/lib/layout/tree/tng-tree-group.d.ts.map +1 -0
  100. package/src/lib/layout/tree/tng-tree-group.js +29 -0
  101. package/src/lib/layout/tree/tng-tree-group.js.map +1 -0
  102. package/src/lib/layout/tree/tng-tree-indicator.d.ts +8 -0
  103. package/src/lib/layout/tree/tng-tree-indicator.d.ts.map +1 -0
  104. package/src/lib/layout/tree/tng-tree-indicator.js +36 -0
  105. package/src/lib/layout/tree/tng-tree-indicator.js.map +1 -0
  106. package/src/lib/layout/tree/tng-tree-item.d.ts +36 -0
  107. package/src/lib/layout/tree/tng-tree-item.d.ts.map +1 -0
  108. package/src/lib/layout/tree/tng-tree-item.js +139 -0
  109. package/src/lib/layout/tree/tng-tree-item.js.map +1 -0
  110. package/src/lib/layout/tree/tng-tree.d.ts +64 -1
  111. package/src/lib/layout/tree/tng-tree.d.ts.map +1 -1
  112. package/src/lib/layout/tree/tng-tree.js +536 -1
  113. package/src/lib/layout/tree/tng-tree.js.map +1 -1
  114. package/src/lib/layout/tree/tng-tree.transforms.d.ts +10 -0
  115. package/src/lib/layout/tree/tng-tree.transforms.d.ts.map +1 -0
  116. package/src/lib/layout/tree/tng-tree.transforms.js +46 -0
  117. package/src/lib/layout/tree/tng-tree.transforms.js.map +1 -0
  118. package/src/lib/navigation/breadcrumb/tng-breadcrumb.d.ts.map +1 -1
  119. package/src/lib/navigation/breadcrumb/tng-breadcrumb.js +5 -0
  120. package/src/lib/navigation/breadcrumb/tng-breadcrumb.js.map +1 -1
  121. package/src/lib/navigation/dropdown-menu/tng-dropdown-menu.d.ts.map +1 -1
  122. package/src/lib/navigation/dropdown-menu/tng-dropdown-menu.js +1 -0
  123. package/src/lib/navigation/dropdown-menu/tng-dropdown-menu.js.map +1 -1
  124. package/src/lib/navigation/navigation-menu/tng-navigation-menu.d.ts.map +1 -1
  125. package/src/lib/navigation/navigation-menu/tng-navigation-menu.js +1 -0
  126. package/src/lib/navigation/navigation-menu/tng-navigation-menu.js.map +1 -1
  127. package/src/lib/navigation/toolbar/tng-toolbar.d.ts.map +1 -1
  128. package/src/lib/navigation/toolbar/tng-toolbar.js +1 -0
  129. package/src/lib/navigation/toolbar/tng-toolbar.js.map +1 -1
  130. package/src/lib/overlay/dialog/tng-dialog.d.ts +158 -0
  131. package/src/lib/overlay/dialog/tng-dialog.d.ts.map +1 -0
  132. package/src/lib/overlay/dialog/tng-dialog.js +854 -0
  133. package/src/lib/overlay/dialog/tng-dialog.js.map +1 -0
  134. package/src/lib/overlay/popover/tng-popover.d.ts +121 -0
  135. package/src/lib/overlay/popover/tng-popover.d.ts.map +1 -0
  136. package/src/lib/overlay/popover/tng-popover.js +614 -0
  137. package/src/lib/overlay/popover/tng-popover.js.map +1 -0
  138. package/src/lib/overlay/tng-overlay-runtime.d.ts +11 -0
  139. package/src/lib/overlay/tng-overlay-runtime.d.ts.map +1 -0
  140. package/src/lib/overlay/tng-overlay-runtime.js +6 -0
  141. package/src/lib/overlay/tng-overlay-runtime.js.map +1 -0
  142. package/src/lib/overlay/tooltip/tng-tooltip.d.ts +92 -3
  143. package/src/lib/overlay/tooltip/tng-tooltip.d.ts.map +1 -1
  144. package/src/lib/overlay/tooltip/tng-tooltip.js +477 -3
  145. package/src/lib/overlay/tooltip/tng-tooltip.js.map +1 -1
  146. package/src/lib/utility/avatar/tng-avatar.d.ts.map +1 -1
  147. package/src/lib/utility/avatar/tng-avatar.js +3 -0
  148. package/src/lib/utility/avatar/tng-avatar.js.map +1 -1
  149. package/src/lib/utility/badge/tng-badge.d.ts +6 -0
  150. package/src/lib/utility/badge/tng-badge.d.ts.map +1 -1
  151. package/src/lib/utility/badge/tng-badge.js +66 -0
  152. package/src/lib/utility/badge/tng-badge.js.map +1 -1
  153. package/src/lib/utility/code-block/tng-code-block.d.ts.map +1 -1
  154. package/src/lib/utility/code-block/tng-code-block.js +5 -0
  155. package/src/lib/utility/code-block/tng-code-block.js.map +1 -1
  156. package/src/lib/utility/copy/tng-copy.d.ts +21 -10
  157. package/src/lib/utility/copy/tng-copy.d.ts.map +1 -1
  158. package/src/lib/utility/copy/tng-copy.js +118 -88
  159. package/src/lib/utility/copy/tng-copy.js.map +1 -1
  160. package/src/lib/utility/press/tng-press.d.ts.map +1 -1
  161. package/src/lib/utility/press/tng-press.js +1 -0
  162. package/src/lib/utility/press/tng-press.js.map +1 -1
  163. package/src/lib/utility/tag/tng-tag.d.ts +37 -0
  164. package/src/lib/utility/tag/tng-tag.d.ts.map +1 -1
  165. package/src/lib/utility/tag/tng-tag.js +198 -1
  166. package/src/lib/utility/tag/tng-tag.js.map +1 -1
@@ -0,0 +1,854 @@
1
+ import { __decorate } from "tslib";
2
+ import { Directive, ElementRef, HostBinding, HostListener, afterNextRender, booleanAttribute, effect, inject, Injector, input, output, signal, } from '@angular/core';
3
+ import { createOverlayFocusHandoffController, createModalIsolationManager, createOverlayScrollLockManager, resolveFirstFocusableElement, resolveFocusableElements, createTngIdFactory, } from '@tailng-ui/cdk';
4
+ import { tngPrimitiveOverlayRuntime } from '../tng-overlay-runtime';
5
+ const createDialogId = createTngIdFactory('tng-dialog');
6
+ const createDialogPanelId = createTngIdFactory('tng-dialog-panel');
7
+ const createDialogTitleId = createTngIdFactory('tng-dialog-title');
8
+ const createDialogDescriptionId = createTngIdFactory('tng-dialog-description');
9
+ const createDialogFocusableId = createTngIdFactory('tng-dialog-focusable');
10
+ function normalizeOptionalBooleanInput(value) {
11
+ if (value === null || value === undefined) {
12
+ return undefined;
13
+ }
14
+ return booleanAttribute(value);
15
+ }
16
+ function toScrollLockDocument(documentRef) {
17
+ if (!(documentRef instanceof Document)) {
18
+ return null;
19
+ }
20
+ return documentRef;
21
+ }
22
+ function toModalIsolationDocument(documentRef) {
23
+ if (!(documentRef instanceof Document)) {
24
+ return null;
25
+ }
26
+ return documentRef;
27
+ }
28
+ function toModalIsolationElement(elementRef) {
29
+ if (!(elementRef instanceof HTMLElement)) {
30
+ return null;
31
+ }
32
+ return elementRef;
33
+ }
34
+ function mapOverlayDismissReason(reason) {
35
+ if (reason === 'escape-key') {
36
+ return 'escape';
37
+ }
38
+ if (reason === 'outside-pointer') {
39
+ return 'backdrop';
40
+ }
41
+ return 'programmatic';
42
+ }
43
+ const dialogGlobalDocument = typeof document === 'undefined' ? null : document;
44
+ const dialogModalIsolation = createModalIsolationManager({
45
+ documentRef: toModalIsolationDocument(dialogGlobalDocument),
46
+ });
47
+ const dialogFocusHandoff = createOverlayFocusHandoffController();
48
+ export function resolveTngDialogActiveElement(documentRef) {
49
+ if (!(documentRef instanceof Document)) {
50
+ return null;
51
+ }
52
+ const activeElement = documentRef.activeElement;
53
+ return activeElement instanceof HTMLElement ? activeElement : null;
54
+ }
55
+ export function resolveTngDialogFocusableElements(container) {
56
+ return resolveFocusableElements(container);
57
+ }
58
+ export function resolveTngDialogMarkedInitialElement(container) {
59
+ if (!(container instanceof HTMLElement)) {
60
+ return null;
61
+ }
62
+ const markedInitial = container.querySelector('[data-tng-dialog-initial-focus]');
63
+ if (markedInitial === null) {
64
+ return null;
65
+ }
66
+ if (resolveTngDialogFocusableElements(container).includes(markedInitial)) {
67
+ return markedInitial;
68
+ }
69
+ return resolveTngDialogFocusableElements(markedInitial)[0] ?? null;
70
+ }
71
+ function readKeyboardEvent(event) {
72
+ return event instanceof KeyboardEvent ? event : null;
73
+ }
74
+ function resolveFirstFocusableWithin(container) {
75
+ return resolveFirstFocusableElement(container);
76
+ }
77
+ function isDialogCloseReason(value) {
78
+ return value === 'backdrop' || value === 'close-button' || value === 'escape' || value === 'programmatic';
79
+ }
80
+ let TngDialog = class TngDialog {
81
+ openInput = input(undefined, {
82
+ alias: 'open',
83
+ transform: normalizeOptionalBooleanInput,
84
+ });
85
+ defaultOpen = input(false, {
86
+ transform: booleanAttribute,
87
+ });
88
+ disabled = input(false, {
89
+ transform: booleanAttribute,
90
+ });
91
+ dismissible = input(true, {
92
+ transform: booleanAttribute,
93
+ });
94
+ closeOnBackdropClick = input(true, {
95
+ transform: booleanAttribute,
96
+ });
97
+ closeOnEscape = input(true, {
98
+ transform: booleanAttribute,
99
+ });
100
+ restoreFocus = input(true, {
101
+ transform: booleanAttribute,
102
+ });
103
+ autoFocus = input('first-focusable', {
104
+ transform: (value) => {
105
+ return value === 'none' || value === 'dialog' || value === 'first-focusable'
106
+ ? value
107
+ : 'first-focusable';
108
+ },
109
+ });
110
+ trapFocus = input(true, {
111
+ transform: booleanAttribute,
112
+ });
113
+ lockScroll = input(true, {
114
+ transform: booleanAttribute,
115
+ });
116
+ ariaLabel = input(null);
117
+ ariaLabelledby = input(null);
118
+ ariaDescribedby = input(null);
119
+ size = input('md');
120
+ openChange = output();
121
+ closed = output();
122
+ hostRef = inject(ElementRef);
123
+ documentRef = dialogGlobalDocument;
124
+ injector = inject(Injector);
125
+ instanceId = createDialogId();
126
+ scrollLock = createOverlayScrollLockManager({
127
+ documentRef: toScrollLockDocument(this.documentRef),
128
+ });
129
+ uncontrolledOpen = signal(false);
130
+ openStateEffect = effect(() => {
131
+ if (!this.initialized) {
132
+ return;
133
+ }
134
+ if (this.isOpen()) {
135
+ this.activateDialog();
136
+ return;
137
+ }
138
+ this.deactivateDialog();
139
+ });
140
+ initialized = false;
141
+ isActive = false;
142
+ isFocusLayerRegistered = false;
143
+ isOverlayLayerRegistered = false;
144
+ panelElement = null;
145
+ panelElementId = null;
146
+ registeredTitleId = null;
147
+ registeredDescriptionId = null;
148
+ dataSlot = 'dialog';
149
+ get dataOpenAttr() {
150
+ return this.isOpen() ? 'true' : 'false';
151
+ }
152
+ get dataStateAttr() {
153
+ return this.isOpen() ? 'open' : 'closed';
154
+ }
155
+ get dataDisabledAttr() {
156
+ return this.disabled() ? '' : null;
157
+ }
158
+ get dataSizeAttr() {
159
+ return this.size();
160
+ }
161
+ ngOnInit() {
162
+ if (!this.isControlled()) {
163
+ this.uncontrolledOpen.set(this.defaultOpen());
164
+ }
165
+ this.initialized = true;
166
+ if (this.isOpen()) {
167
+ this.activateDialog();
168
+ }
169
+ }
170
+ ngOnDestroy() {
171
+ this.openStateEffect.destroy();
172
+ this.deactivateDialog();
173
+ this.unregisterFocusLayer();
174
+ }
175
+ isOpen() {
176
+ return this.openInput() ?? this.uncontrolledOpen();
177
+ }
178
+ openDialog() {
179
+ if (this.disabled()) {
180
+ return;
181
+ }
182
+ this.setOpenState(true);
183
+ }
184
+ closeDialog(reason = 'programmatic') {
185
+ this.requestClose(reason);
186
+ }
187
+ toggleDialog(force) {
188
+ if (force !== undefined) {
189
+ if (force) {
190
+ this.openDialog();
191
+ return;
192
+ }
193
+ this.closeDialog('programmatic');
194
+ return;
195
+ }
196
+ if (this.isOpen()) {
197
+ this.closeDialog('programmatic');
198
+ return;
199
+ }
200
+ this.openDialog();
201
+ }
202
+ requestClose(reason) {
203
+ if (!this.isOpen()) {
204
+ return;
205
+ }
206
+ this.closed.emit(reason);
207
+ this.setOpenState(false);
208
+ }
209
+ registerPanel(panel, id) {
210
+ this.panelElement = panel;
211
+ this.panelElementId = id;
212
+ }
213
+ unregisterPanel(panel) {
214
+ if (this.panelElement === panel) {
215
+ this.panelElement = null;
216
+ this.panelElementId = null;
217
+ }
218
+ }
219
+ registerTitle(id) {
220
+ this.registeredTitleId = id;
221
+ }
222
+ unregisterTitle(id) {
223
+ if (this.registeredTitleId === id) {
224
+ this.registeredTitleId = null;
225
+ }
226
+ }
227
+ registerDescription(id) {
228
+ this.registeredDescriptionId = id;
229
+ }
230
+ unregisterDescription(id) {
231
+ if (this.registeredDescriptionId === id) {
232
+ this.registeredDescriptionId = null;
233
+ }
234
+ }
235
+ getPanelId() {
236
+ return this.panelElementId;
237
+ }
238
+ resolveAriaLabelledby() {
239
+ const explicit = this.ariaLabelledby()?.trim() ?? '';
240
+ if (explicit.length > 0) {
241
+ return explicit;
242
+ }
243
+ return this.registeredTitleId;
244
+ }
245
+ resolveAriaDescribedby() {
246
+ const explicit = this.ariaDescribedby()?.trim() ?? '';
247
+ if (explicit.length > 0) {
248
+ return explicit;
249
+ }
250
+ return this.registeredDescriptionId;
251
+ }
252
+ onBackdropPointerDown(event) {
253
+ if (!this.shouldCloseFromBackdrop()) {
254
+ return;
255
+ }
256
+ if (!(event.currentTarget instanceof HTMLElement)) {
257
+ return;
258
+ }
259
+ if (event.target !== event.currentTarget) {
260
+ return;
261
+ }
262
+ event.preventDefault();
263
+ this.requestClose('backdrop');
264
+ }
265
+ trapTabNavigation(event) {
266
+ if (!this.trapFocus()) {
267
+ return;
268
+ }
269
+ const keyboardEvent = readKeyboardEvent(event);
270
+ if (keyboardEvent === null || keyboardEvent.key !== 'Tab') {
271
+ return;
272
+ }
273
+ const panel = this.panelElement;
274
+ if (panel === null) {
275
+ return;
276
+ }
277
+ if (!dialogFocusHandoff.isTrapActive(this.instanceId)) {
278
+ return;
279
+ }
280
+ const focusableMemberIds = this.resolveFocusableMemberIds(panel);
281
+ const firstMemberId = focusableMemberIds[0];
282
+ if (firstMemberId === undefined) {
283
+ return;
284
+ }
285
+ const lastMemberId = focusableMemberIds[focusableMemberIds.length - 1] ?? firstMemberId;
286
+ const activeElement = resolveTngDialogActiveElement(this.documentRef);
287
+ const activeElementId = activeElement === null ? null : this.ensureElementId(activeElement);
288
+ let candidateId = null;
289
+ if (activeElement === null || !panel.contains(activeElement)) {
290
+ candidateId = keyboardEvent.shiftKey ? lastMemberId : firstMemberId;
291
+ }
292
+ else if (activeElementId === firstMemberId && keyboardEvent.shiftKey) {
293
+ candidateId = lastMemberId;
294
+ }
295
+ else if (activeElementId === lastMemberId && !keyboardEvent.shiftKey) {
296
+ candidateId = firstMemberId;
297
+ }
298
+ else {
299
+ if (activeElementId !== null) {
300
+ dialogFocusHandoff.recordFocus(this.instanceId, activeElementId);
301
+ }
302
+ return;
303
+ }
304
+ const resolvedId = dialogFocusHandoff.resolveFocusCandidate(this.instanceId, candidateId);
305
+ if (resolvedId === null) {
306
+ return;
307
+ }
308
+ const nextFocusTarget = this.resolveElementById(resolvedId);
309
+ if (nextFocusTarget === null) {
310
+ return;
311
+ }
312
+ keyboardEvent.preventDefault();
313
+ nextFocusTarget.focus();
314
+ dialogFocusHandoff.recordFocus(this.instanceId, resolvedId);
315
+ }
316
+ recordFocusedElement(target) {
317
+ if (!(target instanceof HTMLElement) || !this.isOpen()) {
318
+ return;
319
+ }
320
+ const panel = this.panelElement;
321
+ if (panel === null || !panel.contains(target)) {
322
+ return;
323
+ }
324
+ const targetId = this.ensureElementId(target);
325
+ dialogFocusHandoff.recordFocus(this.instanceId, targetId);
326
+ }
327
+ activateDialog() {
328
+ if (this.isActive) {
329
+ return;
330
+ }
331
+ this.isActive = true;
332
+ if (this.lockScroll()) {
333
+ this.scrollLock.acquire(this.instanceId);
334
+ }
335
+ this.registerFocusLayer();
336
+ this.activateFocusLayer();
337
+ this.registerOverlayLayer();
338
+ this.activateModalIsolation();
339
+ afterNextRender(() => {
340
+ this.focusInitialElement();
341
+ }, { injector: this.injector });
342
+ }
343
+ deactivateDialog() {
344
+ if (!this.isActive) {
345
+ return;
346
+ }
347
+ this.isActive = false;
348
+ if (this.lockScroll()) {
349
+ this.scrollLock.release(this.instanceId);
350
+ }
351
+ this.deactivateFocusLayer();
352
+ this.unregisterFocusLayer();
353
+ this.unregisterOverlayLayer();
354
+ this.deactivateModalIsolation();
355
+ }
356
+ focusInitialElement() {
357
+ if (!this.isOpen()) {
358
+ return;
359
+ }
360
+ const panel = this.panelElement;
361
+ if (panel === null) {
362
+ return;
363
+ }
364
+ if (this.autoFocus() === 'none') {
365
+ return;
366
+ }
367
+ if (this.autoFocus() === 'dialog') {
368
+ panel.focus();
369
+ return;
370
+ }
371
+ const markedInitial = resolveTngDialogMarkedInitialElement(panel);
372
+ if (markedInitial !== null) {
373
+ markedInitial.focus();
374
+ return;
375
+ }
376
+ const firstFocusable = resolveFirstFocusableWithin(panel);
377
+ if (firstFocusable !== null) {
378
+ firstFocusable.focus();
379
+ return;
380
+ }
381
+ panel.focus();
382
+ }
383
+ isControlled() {
384
+ return this.openInput() !== undefined;
385
+ }
386
+ setOpenState(nextOpen) {
387
+ if (nextOpen && this.disabled()) {
388
+ return;
389
+ }
390
+ if (this.isOpen() === nextOpen) {
391
+ return;
392
+ }
393
+ if (!this.isControlled()) {
394
+ this.uncontrolledOpen.set(nextOpen);
395
+ }
396
+ this.openChange.emit(nextOpen);
397
+ }
398
+ shouldCloseFromBackdrop() {
399
+ return this.isOpen() && this.dismissible() && this.closeOnBackdropClick();
400
+ }
401
+ shouldCloseFromEscape() {
402
+ return this.isOpen() && this.dismissible() && this.closeOnEscape();
403
+ }
404
+ activateModalIsolation() {
405
+ const hostElement = toModalIsolationElement(this.hostRef.nativeElement);
406
+ if (hostElement === null) {
407
+ return;
408
+ }
409
+ dialogModalIsolation.activate(this.instanceId, hostElement);
410
+ }
411
+ deactivateModalIsolation() {
412
+ dialogModalIsolation.deactivate(this.instanceId);
413
+ }
414
+ registerOverlayLayer() {
415
+ const hostElement = this.hostRef.nativeElement;
416
+ tngPrimitiveOverlayRuntime.registerLayer({
417
+ containsTarget: (target, path) => {
418
+ if (target instanceof Node && hostElement.contains(target)) {
419
+ return true;
420
+ }
421
+ return path.includes(hostElement);
422
+ },
423
+ dismissOnEscape: this.shouldCloseFromEscape(),
424
+ dismissOnOutsidePointer: false,
425
+ id: this.instanceId,
426
+ modal: true,
427
+ onDismiss: (reason) => {
428
+ if (reason === 'escape-key' && !this.shouldCloseFromEscape()) {
429
+ return;
430
+ }
431
+ if (reason === 'outside-pointer' && !this.shouldCloseFromBackdrop()) {
432
+ return;
433
+ }
434
+ this.requestClose(mapOverlayDismissReason(reason));
435
+ },
436
+ });
437
+ this.isOverlayLayerRegistered = true;
438
+ }
439
+ unregisterOverlayLayer() {
440
+ if (!this.isOverlayLayerRegistered) {
441
+ return;
442
+ }
443
+ tngPrimitiveOverlayRuntime.unregisterLayer(this.instanceId);
444
+ this.isOverlayLayerRegistered = false;
445
+ }
446
+ activateFocusLayer() {
447
+ const activeElement = resolveTngDialogActiveElement(this.documentRef);
448
+ const restoreFocusTargetId = activeElement === null ? null : this.ensureElementId(activeElement);
449
+ dialogFocusHandoff.activateLayer(this.instanceId, restoreFocusTargetId);
450
+ }
451
+ deactivateFocusLayer() {
452
+ const restoreFocusTargetId = dialogFocusHandoff.deactivateLayer(this.instanceId);
453
+ if (!this.restoreFocus() || restoreFocusTargetId === null) {
454
+ return;
455
+ }
456
+ const restoreFocusTarget = this.resolveElementById(restoreFocusTargetId);
457
+ restoreFocusTarget?.focus();
458
+ }
459
+ registerFocusLayer() {
460
+ if (this.isFocusLayerRegistered) {
461
+ return;
462
+ }
463
+ dialogFocusHandoff.registerLayer({
464
+ layerId: this.instanceId,
465
+ members: () => {
466
+ const panel = this.panelElement;
467
+ if (panel === null) {
468
+ return [];
469
+ }
470
+ return this.resolveFocusableMemberIds(panel);
471
+ },
472
+ restoreFocus: this.restoreFocus(),
473
+ trapFocus: this.trapFocus(),
474
+ });
475
+ this.isFocusLayerRegistered = true;
476
+ }
477
+ unregisterFocusLayer() {
478
+ if (!this.isFocusLayerRegistered) {
479
+ return;
480
+ }
481
+ dialogFocusHandoff.unregisterLayer(this.instanceId);
482
+ this.isFocusLayerRegistered = false;
483
+ }
484
+ resolveFocusableMemberIds(panel) {
485
+ const focusableElements = resolveTngDialogFocusableElements(panel);
486
+ if (focusableElements.length === 0) {
487
+ return [];
488
+ }
489
+ return focusableElements.map((element) => this.ensureElementId(element));
490
+ }
491
+ ensureElementId(element) {
492
+ const existingId = element.id.trim();
493
+ if (existingId.length > 0) {
494
+ return existingId;
495
+ }
496
+ const generatedId = createDialogFocusableId();
497
+ element.id = generatedId;
498
+ return generatedId;
499
+ }
500
+ resolveElementById(id) {
501
+ if (this.documentRef === null) {
502
+ return null;
503
+ }
504
+ const element = this.documentRef.getElementById(id);
505
+ return element instanceof HTMLElement ? element : null;
506
+ }
507
+ };
508
+ __decorate([
509
+ HostBinding('attr.data-slot')
510
+ ], TngDialog.prototype, "dataSlot", void 0);
511
+ __decorate([
512
+ HostBinding('attr.data-open')
513
+ ], TngDialog.prototype, "dataOpenAttr", null);
514
+ __decorate([
515
+ HostBinding('attr.data-state')
516
+ ], TngDialog.prototype, "dataStateAttr", null);
517
+ __decorate([
518
+ HostBinding('attr.data-disabled')
519
+ ], TngDialog.prototype, "dataDisabledAttr", null);
520
+ __decorate([
521
+ HostBinding('attr.data-size')
522
+ ], TngDialog.prototype, "dataSizeAttr", null);
523
+ TngDialog = __decorate([
524
+ Directive({
525
+ selector: '[tngDialog]',
526
+ exportAs: 'tngDialog',
527
+ standalone: true,
528
+ })
529
+ ], TngDialog);
530
+ export { TngDialog };
531
+ let TngDialogPanel = class TngDialogPanel {
532
+ dialog = inject(TngDialog);
533
+ hostRef = inject(ElementRef);
534
+ resolvedId = this.hostRef.nativeElement.id.trim().length > 0
535
+ ? this.hostRef.nativeElement.id
536
+ : createDialogPanelId();
537
+ dataSlot = 'dialog-panel';
538
+ get dataOpenAttr() {
539
+ return this.dialog.isOpen() ? 'true' : 'false';
540
+ }
541
+ get dataSizeAttr() {
542
+ return this.dialog.size();
543
+ }
544
+ get dataStateAttr() {
545
+ return this.dialog.isOpen() ? 'open' : 'closed';
546
+ }
547
+ get hiddenAttr() {
548
+ return this.dialog.isOpen() ? null : '';
549
+ }
550
+ get idAttr() {
551
+ return this.resolvedId;
552
+ }
553
+ roleAttr = 'dialog';
554
+ tabindexAttr = '-1';
555
+ get ariaDescribedByAttr() {
556
+ return this.dialog.resolveAriaDescribedby();
557
+ }
558
+ get ariaLabelAttr() {
559
+ const label = this.dialog.ariaLabel()?.trim() ?? '';
560
+ return label.length > 0 ? label : null;
561
+ }
562
+ get ariaLabelledByAttr() {
563
+ return this.dialog.resolveAriaLabelledby();
564
+ }
565
+ get ariaModalAttr() {
566
+ return this.dialog.isOpen() ? 'true' : null;
567
+ }
568
+ ngOnInit() {
569
+ this.dialog.registerPanel(this.hostRef.nativeElement, this.resolvedId);
570
+ }
571
+ ngOnDestroy() {
572
+ this.dialog.unregisterPanel(this.hostRef.nativeElement);
573
+ }
574
+ onKeydown(event) {
575
+ if (event.key === 'Tab') {
576
+ this.dialog.trapTabNavigation(event);
577
+ }
578
+ }
579
+ onFocusIn(target) {
580
+ this.dialog.recordFocusedElement(target);
581
+ }
582
+ };
583
+ __decorate([
584
+ HostBinding('attr.data-slot')
585
+ ], TngDialogPanel.prototype, "dataSlot", void 0);
586
+ __decorate([
587
+ HostBinding('attr.data-open')
588
+ ], TngDialogPanel.prototype, "dataOpenAttr", null);
589
+ __decorate([
590
+ HostBinding('attr.data-size')
591
+ ], TngDialogPanel.prototype, "dataSizeAttr", null);
592
+ __decorate([
593
+ HostBinding('attr.data-state')
594
+ ], TngDialogPanel.prototype, "dataStateAttr", null);
595
+ __decorate([
596
+ HostBinding('attr.hidden')
597
+ ], TngDialogPanel.prototype, "hiddenAttr", null);
598
+ __decorate([
599
+ HostBinding('attr.id')
600
+ ], TngDialogPanel.prototype, "idAttr", null);
601
+ __decorate([
602
+ HostBinding('attr.role')
603
+ ], TngDialogPanel.prototype, "roleAttr", void 0);
604
+ __decorate([
605
+ HostBinding('attr.tabindex')
606
+ ], TngDialogPanel.prototype, "tabindexAttr", void 0);
607
+ __decorate([
608
+ HostBinding('attr.aria-describedby')
609
+ ], TngDialogPanel.prototype, "ariaDescribedByAttr", null);
610
+ __decorate([
611
+ HostBinding('attr.aria-label')
612
+ ], TngDialogPanel.prototype, "ariaLabelAttr", null);
613
+ __decorate([
614
+ HostBinding('attr.aria-labelledby')
615
+ ], TngDialogPanel.prototype, "ariaLabelledByAttr", null);
616
+ __decorate([
617
+ HostBinding('attr.aria-modal')
618
+ ], TngDialogPanel.prototype, "ariaModalAttr", null);
619
+ __decorate([
620
+ HostListener('keydown', ['$event'])
621
+ ], TngDialogPanel.prototype, "onKeydown", null);
622
+ __decorate([
623
+ HostListener('focusin', ['$event.target'])
624
+ ], TngDialogPanel.prototype, "onFocusIn", null);
625
+ TngDialogPanel = __decorate([
626
+ Directive({
627
+ selector: '[tngDialogPanel]',
628
+ exportAs: 'tngDialogPanel',
629
+ standalone: true,
630
+ })
631
+ ], TngDialogPanel);
632
+ export { TngDialogPanel };
633
+ let TngDialogBackdrop = class TngDialogBackdrop {
634
+ dialog = inject(TngDialog);
635
+ dataSlot = 'dialog-backdrop';
636
+ get dataOpenAttr() {
637
+ return this.dialog.isOpen() ? 'true' : 'false';
638
+ }
639
+ get dataStateAttr() {
640
+ return this.dialog.isOpen() ? 'open' : 'closed';
641
+ }
642
+ get hiddenAttr() {
643
+ return this.dialog.isOpen() ? null : '';
644
+ }
645
+ onPointerDown(event) {
646
+ this.dialog.onBackdropPointerDown(event);
647
+ }
648
+ };
649
+ __decorate([
650
+ HostBinding('attr.data-slot')
651
+ ], TngDialogBackdrop.prototype, "dataSlot", void 0);
652
+ __decorate([
653
+ HostBinding('attr.data-open')
654
+ ], TngDialogBackdrop.prototype, "dataOpenAttr", null);
655
+ __decorate([
656
+ HostBinding('attr.data-state')
657
+ ], TngDialogBackdrop.prototype, "dataStateAttr", null);
658
+ __decorate([
659
+ HostBinding('attr.hidden')
660
+ ], TngDialogBackdrop.prototype, "hiddenAttr", null);
661
+ __decorate([
662
+ HostListener('pointerdown', ['$event'])
663
+ ], TngDialogBackdrop.prototype, "onPointerDown", null);
664
+ TngDialogBackdrop = __decorate([
665
+ Directive({
666
+ selector: '[tngDialogBackdrop]',
667
+ exportAs: 'tngDialogBackdrop',
668
+ standalone: true,
669
+ })
670
+ ], TngDialogBackdrop);
671
+ export { TngDialogBackdrop };
672
+ let TngDialogTrigger = class TngDialogTrigger {
673
+ parentDialog = inject(TngDialog, { optional: true });
674
+ dialogFor = input(null, {
675
+ alias: 'tngDialogTrigger',
676
+ });
677
+ ariaHasPopupAttr = 'dialog';
678
+ get ariaControlsAttr() {
679
+ return this.resolveDialog()?.getPanelId() ?? null;
680
+ }
681
+ get ariaExpandedAttr() {
682
+ return this.resolveDialog()?.isOpen() ? 'true' : 'false';
683
+ }
684
+ dataSlot = 'dialog-trigger';
685
+ get dataOpenAttr() {
686
+ return this.resolveDialog()?.isOpen() ? 'true' : 'false';
687
+ }
688
+ get dataStateAttr() {
689
+ return this.resolveDialog()?.isOpen() ? 'open' : 'closed';
690
+ }
691
+ get dataDisabledAttr() {
692
+ return this.resolveDialog()?.disabled() ? '' : null;
693
+ }
694
+ onClick() {
695
+ this.resolveDialog()?.openDialog();
696
+ }
697
+ resolveDialog() {
698
+ return this.dialogFor() ?? this.parentDialog;
699
+ }
700
+ };
701
+ __decorate([
702
+ HostBinding('attr.aria-haspopup')
703
+ ], TngDialogTrigger.prototype, "ariaHasPopupAttr", void 0);
704
+ __decorate([
705
+ HostBinding('attr.aria-controls')
706
+ ], TngDialogTrigger.prototype, "ariaControlsAttr", null);
707
+ __decorate([
708
+ HostBinding('attr.aria-expanded')
709
+ ], TngDialogTrigger.prototype, "ariaExpandedAttr", null);
710
+ __decorate([
711
+ HostBinding('attr.data-slot')
712
+ ], TngDialogTrigger.prototype, "dataSlot", void 0);
713
+ __decorate([
714
+ HostBinding('attr.data-open')
715
+ ], TngDialogTrigger.prototype, "dataOpenAttr", null);
716
+ __decorate([
717
+ HostBinding('attr.data-state')
718
+ ], TngDialogTrigger.prototype, "dataStateAttr", null);
719
+ __decorate([
720
+ HostBinding('attr.data-disabled')
721
+ ], TngDialogTrigger.prototype, "dataDisabledAttr", null);
722
+ __decorate([
723
+ HostListener('click')
724
+ ], TngDialogTrigger.prototype, "onClick", null);
725
+ TngDialogTrigger = __decorate([
726
+ Directive({
727
+ selector: '[tngDialogTrigger]',
728
+ exportAs: 'tngDialogTrigger',
729
+ standalone: true,
730
+ })
731
+ ], TngDialogTrigger);
732
+ export { TngDialogTrigger };
733
+ let TngDialogTitle = class TngDialogTitle {
734
+ dialog = inject(TngDialog);
735
+ hostRef = inject(ElementRef);
736
+ resolvedId = this.hostRef.nativeElement.id.trim().length > 0
737
+ ? this.hostRef.nativeElement.id
738
+ : createDialogTitleId();
739
+ dataSlot = 'dialog-title';
740
+ get idAttr() {
741
+ return this.resolvedId;
742
+ }
743
+ ngOnInit() {
744
+ this.dialog.registerTitle(this.resolvedId);
745
+ }
746
+ ngOnDestroy() {
747
+ this.dialog.unregisterTitle(this.resolvedId);
748
+ }
749
+ };
750
+ __decorate([
751
+ HostBinding('attr.data-slot')
752
+ ], TngDialogTitle.prototype, "dataSlot", void 0);
753
+ __decorate([
754
+ HostBinding('attr.id')
755
+ ], TngDialogTitle.prototype, "idAttr", null);
756
+ TngDialogTitle = __decorate([
757
+ Directive({
758
+ selector: '[tngDialogTitle]',
759
+ exportAs: 'tngDialogTitle',
760
+ standalone: true,
761
+ })
762
+ ], TngDialogTitle);
763
+ export { TngDialogTitle };
764
+ let TngDialogDescription = class TngDialogDescription {
765
+ dialog = inject(TngDialog);
766
+ hostRef = inject(ElementRef);
767
+ resolvedId = this.hostRef.nativeElement.id.trim().length > 0
768
+ ? this.hostRef.nativeElement.id
769
+ : createDialogDescriptionId();
770
+ dataSlot = 'dialog-description';
771
+ get idAttr() {
772
+ return this.resolvedId;
773
+ }
774
+ ngOnInit() {
775
+ this.dialog.registerDescription(this.resolvedId);
776
+ }
777
+ ngOnDestroy() {
778
+ this.dialog.unregisterDescription(this.resolvedId);
779
+ }
780
+ };
781
+ __decorate([
782
+ HostBinding('attr.data-slot')
783
+ ], TngDialogDescription.prototype, "dataSlot", void 0);
784
+ __decorate([
785
+ HostBinding('attr.id')
786
+ ], TngDialogDescription.prototype, "idAttr", null);
787
+ TngDialogDescription = __decorate([
788
+ Directive({
789
+ selector: '[tngDialogDescription]',
790
+ exportAs: 'tngDialogDescription',
791
+ standalone: true,
792
+ })
793
+ ], TngDialogDescription);
794
+ export { TngDialogDescription };
795
+ let TngDialogContent = class TngDialogContent {
796
+ dataSlot = 'dialog-content';
797
+ };
798
+ __decorate([
799
+ HostBinding('attr.data-slot')
800
+ ], TngDialogContent.prototype, "dataSlot", void 0);
801
+ TngDialogContent = __decorate([
802
+ Directive({
803
+ selector: '[tngDialogContent]',
804
+ exportAs: 'tngDialogContent',
805
+ standalone: true,
806
+ })
807
+ ], TngDialogContent);
808
+ export { TngDialogContent };
809
+ let TngDialogActions = class TngDialogActions {
810
+ dataSlot = 'dialog-actions';
811
+ };
812
+ __decorate([
813
+ HostBinding('attr.data-slot')
814
+ ], TngDialogActions.prototype, "dataSlot", void 0);
815
+ TngDialogActions = __decorate([
816
+ Directive({
817
+ selector: '[tngDialogActions]',
818
+ exportAs: 'tngDialogActions',
819
+ standalone: true,
820
+ })
821
+ ], TngDialogActions);
822
+ export { TngDialogActions };
823
+ let TngDialogClose = class TngDialogClose {
824
+ dialog = inject(TngDialog);
825
+ closeReason = input(null, {
826
+ alias: 'tngDialogClose',
827
+ });
828
+ dataSlot = 'dialog-close';
829
+ onClick() {
830
+ this.dialog.requestClose(this.resolveCloseReason());
831
+ }
832
+ resolveCloseReason() {
833
+ const raw = this.closeReason()?.trim();
834
+ if (raw === undefined || raw.length === 0) {
835
+ return 'close-button';
836
+ }
837
+ return isDialogCloseReason(raw) ? raw : 'close-button';
838
+ }
839
+ };
840
+ __decorate([
841
+ HostBinding('attr.data-slot')
842
+ ], TngDialogClose.prototype, "dataSlot", void 0);
843
+ __decorate([
844
+ HostListener('click')
845
+ ], TngDialogClose.prototype, "onClick", null);
846
+ TngDialogClose = __decorate([
847
+ Directive({
848
+ selector: '[tngDialogClose]',
849
+ exportAs: 'tngDialogClose',
850
+ standalone: true,
851
+ })
852
+ ], TngDialogClose);
853
+ export { TngDialogClose };
854
+ //# sourceMappingURL=tng-dialog.js.map