@radix-ng/primitives 0.37.0 → 0.39.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 (78) hide show
  1. package/accordion/index.d.ts +3 -1
  2. package/accordion/src/accordion-content-presence.directive.d.ts +6 -0
  3. package/accordion/src/accordion-content.directive.d.ts +7 -8
  4. package/accordion/src/accordion-header.directive.d.ts +2 -2
  5. package/accordion/src/accordion-item.directive.d.ts +29 -77
  6. package/accordion/src/accordion-root.directive.d.ts +49 -78
  7. package/accordion/src/accordion-trigger.directive.d.ts +6 -11
  8. package/collapsible/index.d.ts +11 -0
  9. package/collapsible/src/collapsible-content-presence.directive.d.ts +6 -0
  10. package/collapsible/src/collapsible-content.directive.d.ts +13 -9
  11. package/collapsible/src/collapsible-root.directive.d.ts +19 -37
  12. package/collapsible/src/collapsible-trigger.directive.d.ts +1 -21
  13. package/core/index.d.ts +5 -0
  14. package/core/src/accessor/control-value-accessor.d.ts +67 -0
  15. package/core/src/create-context.d.ts +10 -0
  16. package/core/src/date-time/comparators.d.ts +7 -1
  17. package/core/src/date-time/useDateField.d.ts +2 -2
  18. package/core/src/types.d.ts +24 -0
  19. package/{stepper/src/utils → core/src}/useArrowNavigation.d.ts +2 -2
  20. package/core/src/useResizeObserver.d.ts +15 -0
  21. package/fesm2022/radix-ng-primitives-accordion.mjs +231 -398
  22. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-avatar.mjs +2 -10
  24. package/fesm2022/radix-ng-primitives-avatar.mjs.map +1 -1
  25. package/fesm2022/radix-ng-primitives-calendar.mjs +3 -14
  26. package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
  27. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-collapsible.mjs +151 -143
  29. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-core.mjs +248 -7
  31. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  32. package/fesm2022/radix-ng-primitives-hover-card.mjs +1 -3
  33. package/fesm2022/radix-ng-primitives-hover-card.mjs.map +1 -1
  34. package/fesm2022/radix-ng-primitives-menubar.mjs +1 -8
  35. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  36. package/fesm2022/radix-ng-primitives-pagination.mjs +2 -6
  37. package/fesm2022/radix-ng-primitives-pagination.mjs.map +1 -1
  38. package/fesm2022/radix-ng-primitives-popover.mjs +2 -6
  39. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  40. package/fesm2022/radix-ng-primitives-presence.mjs +34 -1
  41. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  42. package/fesm2022/radix-ng-primitives-progress.mjs +2 -7
  43. package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
  44. package/fesm2022/radix-ng-primitives-radio.mjs +1 -3
  45. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  46. package/fesm2022/radix-ng-primitives-select.mjs +75 -33
  47. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  48. package/fesm2022/radix-ng-primitives-stepper.mjs +1 -84
  49. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  50. package/fesm2022/radix-ng-primitives-switch.mjs +61 -97
  51. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  52. package/fesm2022/radix-ng-primitives-tabs.mjs +4 -19
  53. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  54. package/fesm2022/radix-ng-primitives-time-field.mjs +351 -0
  55. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -0
  56. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  57. package/fesm2022/radix-ng-primitives-toggle.mjs +1 -6
  58. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  59. package/fesm2022/radix-ng-primitives-tooltip.mjs +1 -3
  60. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  61. package/hover-card/src/hover-card-root.directive.d.ts +4 -4
  62. package/package.json +5 -1
  63. package/popover/src/popover-root.directive.d.ts +4 -4
  64. package/presence/index.d.ts +1 -0
  65. package/presence/src/presence.directive.d.ts +27 -0
  66. package/select/src/select-trigger.directive.d.ts +8 -2
  67. package/select/src/select.component.d.ts +23 -6
  68. package/switch/index.d.ts +0 -1
  69. package/switch/src/switch-input.directive.d.ts +1 -1
  70. package/switch/src/switch-root.directive.d.ts +23 -43
  71. package/switch/src/switch-thumb.directive.d.ts +1 -1
  72. package/time-field/README.md +1 -0
  73. package/time-field/index.d.ts +11 -0
  74. package/time-field/src/time-field-context.token.d.ts +19 -0
  75. package/time-field/src/time-field-input.directive.d.ts +53 -0
  76. package/time-field/src/time-field-root.directive.d.ts +125 -0
  77. package/tooltip/src/tooltip-root.directive.d.ts +4 -4
  78. package/collapsible/src/collapsible-content.token.d.ts +0 -3
@@ -1,495 +1,326 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, EventEmitter, booleanAttribute, Output, Input, forwardRef, ContentChildren, Directive, ElementRef, ChangeDetectorRef, ContentChild, NgModule } from '@angular/core';
3
- import { UniqueSelectionDispatcher } from '@angular/cdk/collections';
4
- import { Subject, merge, Subscription } from 'rxjs';
5
- import { FocusKeyManager } from '@angular/cdk/a11y';
6
- import { Directionality } from '@angular/cdk/bidi';
7
- import { ENTER, SPACE, TAB } from '@angular/cdk/keycodes';
2
+ import { Directive, inject, ElementRef, input, booleanAttribute, model, output, computed, effect, NgModule } from '@angular/core';
3
+ import * as i1 from '@radix-ng/primitives/collapsible';
4
+ import { RdxCollapsibleContentPresenceDirective, injectCollapsibleRootContext, RdxCollapsibleRootDirective, RdxCollapsibleContentDirective, RdxCollapsibleTriggerDirective } from '@radix-ng/primitives/collapsible';
5
+ import { createContext, useArrowNavigation } from '@radix-ng/primitives/core';
6
+ import { _IdGenerator } from '@angular/cdk/a11y';
8
7
 
9
- const RdxAccordionRootToken = new InjectionToken('RdxAccordionRootDirective');
10
- let nextId$1 = 0;
8
+ class RdxAccordionContentPresenceDirective {
9
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionContentPresenceDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
10
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.4", type: RdxAccordionContentPresenceDirective, isStandalone: true, selector: "ng-template[rdxAccordionContentPresence]", hostDirectives: [{ directive: i1.RdxCollapsibleContentPresenceDirective }], ngImport: i0 }); }
11
+ }
12
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionContentPresenceDirective, decorators: [{
13
+ type: Directive,
14
+ args: [{
15
+ selector: 'ng-template[rdxAccordionContentPresence]',
16
+ hostDirectives: [RdxCollapsibleContentPresenceDirective]
17
+ }]
18
+ }] });
19
+
20
+ const [injectAccordionRootContext, provideAccordionRootContext] = createContext('AccordionRootContext');
21
+ const rootContext = () => {
22
+ const instance = inject(RdxAccordionRootDirective);
23
+ return {
24
+ disabled: instance.disabled,
25
+ direction: instance.dir,
26
+ collapsible: instance.collapsible,
27
+ orientation: instance.orientation,
28
+ elementRef: instance.elementRef,
29
+ value: instance.value,
30
+ isSingle: instance.isSingle,
31
+ changeModelValue: instance.changeModelValue
32
+ };
33
+ };
11
34
  /**
12
35
  * @group Components
13
36
  */
14
37
  class RdxAccordionRootDirective {
15
38
  constructor() {
39
+ this.elementRef = inject(ElementRef);
40
+ this.id = input(inject(_IdGenerator).getId('rdx-accordion-'));
16
41
  /**
17
- * @ignore
42
+ * The reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode.
43
+ *
44
+ * @group Props
18
45
  */
19
- this.selectionDispatcher = inject(UniqueSelectionDispatcher);
20
- /**
21
- * @ignore
46
+ this.dir = input('ltr');
47
+ /** Whether the Accordion is disabled.
48
+ * @defaultValue false
49
+ * @group Props
22
50
  */
23
- this.dir = inject(Directionality, { optional: true });
51
+ this.disabled = input(false, { transform: booleanAttribute });
24
52
  /**
25
- * @ignore
53
+ * The orientation of the accordion.
54
+ *
55
+ * @defaultValue 'vertical'
56
+ * @group Props
26
57
  */
27
- this.id = `rdx-accordion-${nextId$1++}`;
58
+ this.orientation = input('vertical');
28
59
  /**
29
- * @ignore
60
+ * The default active value of the item(s).
61
+ *
62
+ * Use when you do not need to control the state of the item(s).
63
+ * @group Props
30
64
  */
31
- this.openCloseAllActions = new Subject();
65
+ this.defaultValue = input();
32
66
  /**
33
- * The orientation of the accordion.
67
+ * The controlled value of the item to expand.
34
68
  *
35
- * @defaultValue 'vertical'
36
69
  * @group Props
37
70
  */
38
- this.orientation = 'vertical';
71
+ this.value = model();
39
72
  /**
40
- * Determines whether one or multiple items can be opened at the same time.
73
+ * When type is "single", allows closing content when clicking trigger for an open item.
74
+ * When type is "multiple", this prop has no effect.
75
+ *
76
+ * @defaultValue false
41
77
  * @group Props
42
- * @defaultValue 'single'
43
78
  */
44
- this.type = 'single';
79
+ this.collapsible = input(false, { transform: booleanAttribute });
45
80
  /**
46
- * @ignore
81
+ * Determines whether a "single" or "multiple" items can be selected at a time.
82
+ *
83
+ * @defaultValue 'single'
84
+ * @group Props
47
85
  */
48
- this.collapsible = true;
86
+ this.type = input('single');
49
87
  /**
50
88
  * Event handler called when the expanded state of an item changes and type is "multiple".
51
89
  * @group Emits
52
90
  */
53
- this.onValueChange = new EventEmitter();
54
- this._defaultValue = [];
55
- }
56
- get isMultiple() {
57
- return this.type === 'multiple';
58
- }
59
- /**
60
- * The value of the item to expand when initially rendered and type is "single".
61
- * Use when you do not need to control the state of the items.
62
- * @group Props
63
- */
64
- set defaultValue(value) {
65
- if (value !== this._defaultValue) {
66
- this._defaultValue = Array.isArray(value) ? value : [value];
67
- }
68
- }
69
- get defaultValue() {
70
- return this.isMultiple ? this._defaultValue : this._defaultValue[0];
71
- }
72
- /**
73
- * The controlled value of the item to expand.
74
- *
75
- * @group Props
76
- */
77
- set value(value) {
78
- if (value !== this._value) {
79
- this._value = Array.isArray(value) ? value : [value];
80
- this.selectionDispatcher.notify(this.value, this.id);
81
- }
82
- }
83
- get value() {
84
- if (this._value === undefined) {
85
- return this.defaultValue;
86
- }
87
- return this.isMultiple ? this._value : this._value[0];
88
- }
89
- /**
90
- * @ignore
91
- */
92
- ngAfterContentInit() {
93
- this.selectionDispatcher.notify((this._value ?? this._defaultValue), this.id);
94
- this.keyManager = new FocusKeyManager(this.items).withHomeAndEnd();
95
- if (this.orientation === 'horizontal') {
96
- this.keyManager.withHorizontalOrientation(this.dir?.value || 'ltr');
97
- }
98
- else {
99
- this.keyManager.withVerticalOrientation();
100
- }
101
- this.onValueChangeSubscription = merge(...this.items.map((item) => item.expandedChange)).subscribe(() => this.onValueChange.emit());
102
- }
103
- /**
104
- * @ignore
105
- */
106
- ngOnDestroy() {
107
- this.openCloseAllActions.complete();
108
- this.onValueChangeSubscription.unsubscribe();
109
- }
110
- /**
111
- * @ignore
112
- */
113
- handleKeydown(event) {
114
- if (!this.keyManager.activeItem) {
115
- this.keyManager.setFirstItemActive();
116
- }
117
- const activeItem = this.keyManager.activeItem;
118
- if ((event.keyCode === ENTER || event.keyCode === SPACE) &&
119
- !this.keyManager.isTyping() &&
120
- activeItem &&
121
- !activeItem.disabled) {
122
- event.preventDefault();
123
- activeItem.toggle();
124
- }
125
- else if (event.keyCode === TAB && event.shiftKey) {
126
- if (this.keyManager.activeItemIndex === 0)
127
- return;
128
- this.keyManager.setPreviousItemActive();
129
- event.preventDefault();
130
- }
131
- else if (event.keyCode === TAB) {
132
- if (this.keyManager.activeItemIndex === this.items.length - 1)
133
- return;
134
- this.keyManager.setNextItemActive();
135
- event.preventDefault();
136
- }
137
- else {
138
- this.keyManager.onKeydown(event);
139
- }
140
- }
141
- /** Opens all enabled accordion items in an accordion where multi is enabled.
142
- * @ignore
143
- */
144
- openAll() {
145
- if (this.isMultiple) {
146
- this.openCloseAllActions.next(true);
147
- }
91
+ this.onValueChange = output();
92
+ this.isSingle = computed(() => this.type() === 'single');
93
+ this.changeModelValue = (newValue) => {
94
+ if (this.type() === 'single') {
95
+ this.value.set(this.isEqual(newValue, this.value()) ? undefined : newValue);
96
+ }
97
+ else {
98
+ const currentValue = this.value();
99
+ let modelValueArray = [];
100
+ if (Array.isArray(currentValue)) {
101
+ modelValueArray = [...currentValue];
102
+ }
103
+ else if (currentValue !== undefined && currentValue !== null) {
104
+ modelValueArray = [currentValue];
105
+ }
106
+ if (this.isValueEqualOrExist(modelValueArray, newValue)) {
107
+ const index = modelValueArray.findIndex((item) => this.isEqual(item, newValue));
108
+ if (index !== -1) {
109
+ modelValueArray.splice(index, 1);
110
+ }
111
+ }
112
+ else {
113
+ modelValueArray.push(newValue);
114
+ }
115
+ this.value.set(modelValueArray);
116
+ }
117
+ };
118
+ effect(() => {
119
+ if (this.defaultValue() !== undefined) {
120
+ this.value.set(this.defaultValue());
121
+ }
122
+ });
148
123
  }
149
- /** Closes all enabled accordion items.
150
- * @ignore
151
- */
152
- closeAll() {
153
- this.openCloseAllActions.next(false);
124
+ isValueEqualOrExist(arr, value) {
125
+ return arr.some((item) => this.isEqual(item, value));
154
126
  }
155
- /**
156
- * @ignore
157
- */
158
- setActiveItem(item) {
159
- this.keyManager.setActiveItem(item);
127
+ isEqual(a, b) {
128
+ return JSON.stringify(a) === JSON.stringify(b);
160
129
  }
161
130
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
162
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.4", type: RdxAccordionRootDirective, isStandalone: true, selector: "[rdxAccordionRoot]", inputs: { disabled: ["disabled", "disabled", booleanAttribute], orientation: "orientation", defaultValue: "defaultValue", type: "type", collapsible: "collapsible", value: "value" }, outputs: { onValueChange: "onValueChange" }, host: { listeners: { "keydown": "handleKeydown($event)" }, properties: { "attr.data-orientation": "orientation" } }, providers: [
163
- { provide: RdxAccordionRootToken, useExisting: RdxAccordionRootDirective },
164
- { provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }
165
- ], queries: [{ propertyName: "items", predicate: i0.forwardRef(() => RdxAccordionItemDirective), descendants: true }], ngImport: i0 }); }
131
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.4", type: RdxAccordionRootDirective, isStandalone: true, selector: "[rdxAccordionRoot]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onValueChange: "onValueChange" }, host: { properties: { "attr.data-orientation": "orientation()" } }, providers: [provideAccordionRootContext(rootContext)], exportAs: ["rdxAccordionRoot"], ngImport: i0 }); }
166
132
  }
167
133
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionRootDirective, decorators: [{
168
134
  type: Directive,
169
135
  args: [{
170
136
  selector: '[rdxAccordionRoot]',
171
- standalone: true,
172
- providers: [
173
- { provide: RdxAccordionRootToken, useExisting: RdxAccordionRootDirective },
174
- { provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }
175
- ],
137
+ exportAs: 'rdxAccordionRoot',
138
+ providers: [provideAccordionRootContext(rootContext)],
176
139
  host: {
177
- '[attr.data-orientation]': 'orientation',
178
- '(keydown)': 'handleKeydown($event)'
140
+ '[attr.data-orientation]': 'orientation()'
179
141
  }
180
142
  }]
181
- }], propDecorators: { disabled: [{
182
- type: Input,
183
- args: [{ transform: booleanAttribute }]
184
- }], orientation: [{
185
- type: Input
186
- }], items: [{
187
- type: ContentChildren,
188
- args: [forwardRef(() => RdxAccordionItemDirective), { descendants: true }]
189
- }], defaultValue: [{
190
- type: Input
191
- }], type: [{
192
- type: Input
193
- }], collapsible: [{
194
- type: Input
195
- }], value: [{
196
- type: Input
197
- }], onValueChange: [{
198
- type: Output
199
- }] } });
143
+ }], ctorParameters: () => [] });
200
144
 
201
- class RdxAccordionTriggerDirective {
202
- constructor() {
203
- this.nativeElement = inject(ElementRef).nativeElement;
204
- this.accordionRoot = inject(RdxAccordionRootDirective);
205
- this.item = inject(RdxAccordionItemDirective);
206
- }
207
- /**
208
- * Fires when trigger clicked
209
- */
210
- onClick() {
211
- if (!this.accordionRoot.collapsible && this.item.expanded)
212
- return;
213
- this.item.toggle();
214
- this.accordionRoot.setActiveItem(this.item);
215
- }
216
- focus() {
217
- this.nativeElement.focus();
218
- }
219
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
220
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.4", type: RdxAccordionTriggerDirective, isStandalone: true, selector: "[rdxAccordionTrigger]", host: { listeners: { "click": "onClick()" }, properties: { "attr.role": "\"button\"", "attr.aria-expanded": "item.expanded", "attr.data-state": "item.dataState", "attr.data-disabled": "item.disabled", "attr.disabled": "item.disabled ? \"\" : null", "attr.data-orientation": "item.orientation" } }, ngImport: i0 }); }
221
- }
222
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionTriggerDirective, decorators: [{
223
- type: Directive,
224
- args: [{
225
- selector: '[rdxAccordionTrigger]',
226
- standalone: true,
227
- host: {
228
- '[attr.role]': '"button"',
229
- '[attr.aria-expanded]': 'item.expanded',
230
- '[attr.data-state]': 'item.dataState',
231
- '[attr.data-disabled]': 'item.disabled',
232
- '[attr.disabled]': 'item.disabled ? "" : null',
233
- '[attr.data-orientation]': 'item.orientation',
234
- '(click)': 'onClick()'
235
- }
236
- }]
237
- }] });
238
-
239
- let nextId = 0;
145
+ const [injectAccordionItemContext, provideAccordionItemContext] = createContext('AccordionItemContext');
146
+ const itemContext = () => {
147
+ const instance = inject(RdxAccordionItemDirective);
148
+ return {
149
+ open: instance.open,
150
+ dataState: instance.dataState,
151
+ disabled: instance.disabled,
152
+ dataDisabled: instance.isDisabled,
153
+ triggerId: '',
154
+ currentElement: instance.elementRef,
155
+ value: computed(() => instance.value()),
156
+ updateOpen: instance.updateOpen
157
+ };
158
+ };
240
159
  /**
241
160
  * @group Components
242
161
  */
243
162
  class RdxAccordionItemDirective {
244
- get dataState() {
245
- return this.expanded ? 'open' : 'closed';
246
- }
247
- get orientation() {
248
- return this.accordion.orientation;
249
- }
250
- /**
251
- * @defaultValue false
252
- * @group Props
253
- */
254
- set expanded(expanded) {
255
- // Only emit events and update the internal value if the value changes.
256
- if (this._expanded !== expanded) {
257
- this._expanded = expanded;
258
- this.expandedChange.emit(expanded);
259
- if (expanded) {
260
- this.opened.emit();
261
- /**
262
- * In the unique selection dispatcher, the id parameter is the id of the CdkAccordionItem,
263
- * the name value is the id of the accordion.
264
- */
265
- const accordionId = this.accordion ? this.accordion.id : this.value;
266
- this.expansionDispatcher.notify(this.value, accordionId);
267
- }
268
- else {
269
- this.closed.emit();
270
- }
271
- // Ensures that the animation will run when the value is set outside of an `@Input`.
272
- // This includes cases like the open, close and toggle methods.
273
- this.changeDetectorRef.markForCheck();
274
- }
275
- }
276
- get expanded() {
277
- return this._expanded;
278
- }
279
- /**
280
- * Accordion value.
281
- *
282
- * @group Props
283
- */
284
- set value(value) {
285
- this._value = value;
286
- }
287
- get value() {
288
- return this._value || this.id;
289
- }
290
- /**
291
- * Whether the AccordionItem is disabled.
292
- *
293
- * @defaultValue false
294
- * @group Props
295
- */
296
- set disabled(value) {
297
- this._disabled = value;
298
- }
299
- get disabled() {
300
- return this.accordion.disabled ?? this._disabled;
301
- }
302
163
  constructor() {
303
- this.accordion = inject(RdxAccordionRootToken, { skipSelf: true });
304
- this.changeDetectorRef = inject(ChangeDetectorRef);
305
- this.expansionDispatcher = inject(UniqueSelectionDispatcher);
306
- /**
307
- * The unique AccordionItem id.
308
- * @ignore
309
- */
310
- this.id = `rdx-accordion-item-${nextId++}`;
311
- this._expanded = false;
312
- this._disabled = false;
313
- /**
314
- * Event emitted every time the AccordionItem is closed.
315
- */
316
- this.closed = new EventEmitter();
317
- /** Event emitted every time the AccordionItem is opened. */
318
- this.opened = new EventEmitter();
164
+ this.elementRef = inject(ElementRef);
165
+ this.collapsibleContext = injectCollapsibleRootContext();
166
+ this.rootContext = injectAccordionRootContext();
319
167
  /**
320
- * Event emitted when the AccordionItem is destroyed.
321
- * @ignore
168
+ * A string value for the accordion item. All items within an accordion should use a unique value.
169
+ * @group Props
322
170
  */
323
- this.destroyed = new EventEmitter();
171
+ this.value = input();
324
172
  /**
325
- * Emits whenever the expanded state of the accordion changes.
326
- * Primarily used to facilitate two-way binding.
327
- * @group Emits
173
+ * Whether or not an accordion item is disabled from user interaction.
174
+ * When `true`, prevents the user from interacting with the item.
175
+ * @group Props
328
176
  */
329
- this.expandedChange = new EventEmitter();
330
- /** Subscription to openAll/closeAll events. */
331
- this.openCloseAllSubscription = Subscription.EMPTY;
332
- this.removeUniqueSelectionListener = this.expansionDispatcher.listen((id, accordionId) => {
333
- if (this.accordion.isMultiple) {
334
- if (this.accordion.id === accordionId && id.includes(this.value)) {
335
- this.expanded = true;
336
- }
337
- }
338
- else {
339
- this.expanded = this.accordion.id === accordionId && id.includes(this.value);
340
- }
177
+ this.disabled = input(false, { transform: booleanAttribute });
178
+ this.isDisabled = computed(() => {
179
+ return this.rootContext.disabled() || this.disabled();
180
+ });
181
+ this.open = computed(() => this.rootContext.isSingle()
182
+ ? this.value() === this.rootContext.value()
183
+ : Array.isArray(this.rootContext.value()) && this.rootContext.value().includes(this.value()));
184
+ this.dataState = computed(() => (this.open() ? 'open' : 'closed'));
185
+ this.updateOpen = () => {
186
+ this.collapsibleContext.open.set(this.open());
187
+ };
188
+ effect(() => {
189
+ this.updateOpen();
341
190
  });
342
- // When an accordion item is hosted in an accordion, subscribe to open/close events.
343
- if (this.accordion) {
344
- this.openCloseAllSubscription = this.subscribeToOpenCloseAllActions();
345
- }
346
- }
347
- /** Emits an event for the accordion item being destroyed. */
348
- ngOnDestroy() {
349
- this.opened.complete();
350
- this.closed.complete();
351
- this.destroyed.emit();
352
- this.destroyed.complete();
353
- this.removeUniqueSelectionListener();
354
- this.openCloseAllSubscription.unsubscribe();
355
- }
356
- focus() {
357
- this.trigger.focus();
358
- }
359
- /** Toggles the expanded state of the accordion item. */
360
- toggle() {
361
- if (!this.disabled) {
362
- this.content.onToggle();
363
- this.expanded = !this.expanded;
364
- }
365
- }
366
- /** Sets the expanded state of the accordion item to false. */
367
- close() {
368
- if (!this.disabled) {
369
- this.expanded = false;
370
- }
371
- }
372
- /** Sets the expanded state of the accordion item to true. */
373
- open() {
374
- if (!this.disabled) {
375
- this.expanded = true;
376
- }
377
191
  }
378
- subscribeToOpenCloseAllActions() {
379
- return this.accordion.openCloseAllActions.subscribe((expanded) => {
380
- // Only change expanded state if item is enabled
381
- if (!this.disabled) {
382
- this.expanded = expanded;
383
- }
192
+ handleArrowKey(event) {
193
+ const target = event.target;
194
+ const allCollectionItems = Array.from(this.rootContext.elementRef.nativeElement?.querySelectorAll('[data-rdx-collection-item]') ?? []);
195
+ const collectionItemIndex = allCollectionItems.findIndex((item) => item === target);
196
+ if (collectionItemIndex === -1)
197
+ return;
198
+ useArrowNavigation(event, this.elementRef.nativeElement.querySelector('[data-rdx-collection-item]'), this.rootContext.elementRef.nativeElement, {
199
+ arrowKeyOptions: this.rootContext.orientation(),
200
+ dir: this.rootContext.direction(),
201
+ focus: true
384
202
  });
385
203
  }
386
204
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
387
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.4", type: RdxAccordionItemDirective, isStandalone: true, selector: "[rdxAccordionItem]", inputs: { expanded: ["expanded", "expanded", booleanAttribute], value: "value", disabled: ["disabled", "disabled", booleanAttribute] }, outputs: { closed: "closed", opened: "opened", expandedChange: "expandedChange" }, host: { properties: { "attr.data-state": "dataState", "attr.data-disabled": "disabled", "attr.data-orientation": "orientation" } }, providers: [
388
- { provide: RdxAccordionRootToken, useValue: undefined }
389
- ], queries: [{ propertyName: "trigger", first: true, predicate: RdxAccordionTriggerDirective, descendants: true }, { propertyName: "content", first: true, predicate: i0.forwardRef(() => RdxAccordionContentDirective), descendants: true }], exportAs: ["rdxAccordionItem"], ngImport: i0 }); }
205
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.4", type: RdxAccordionItemDirective, isStandalone: true, selector: "[rdxAccordionItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown.arrowDown": "handleArrowKey($event)", "keydown.arrowUp": "handleArrowKey($event)", "keydown.arrowLeft": "handleArrowKey($event)", "keydown.arrowRight": "handleArrowKey($event)", "keydown.home": "handleArrowKey($event)", "keydown.end": "handleArrowKey($event)" }, properties: { "attr.data-orientation": "rootContext.orientation()", "attr.data-disabled": "disabled() ? \"\" : undefined", "attr.data-state": "dataState()" } }, providers: [provideAccordionItemContext(itemContext)], exportAs: ["rdxAccordionItem"], hostDirectives: [{ directive: i1.RdxCollapsibleRootDirective, inputs: ["disabled", "disabled", "open", "open"] }], ngImport: i0 }); }
390
206
  }
391
207
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionItemDirective, decorators: [{
392
208
  type: Directive,
393
209
  args: [{
394
210
  selector: '[rdxAccordionItem]',
395
- standalone: true,
396
211
  exportAs: 'rdxAccordionItem',
212
+ providers: [provideAccordionItemContext(itemContext)],
213
+ hostDirectives: [
214
+ {
215
+ directive: RdxCollapsibleRootDirective,
216
+ inputs: ['disabled: disabled', 'open: open']
217
+ }
218
+ ],
397
219
  host: {
398
- '[attr.data-state]': 'dataState',
399
- '[attr.data-disabled]': 'disabled',
400
- '[attr.data-orientation]': 'orientation'
401
- },
402
- providers: [
403
- { provide: RdxAccordionRootToken, useValue: undefined }
404
- ]
220
+ '[attr.data-orientation]': 'rootContext.orientation()',
221
+ '[attr.data-disabled]': 'disabled() ? "" : undefined',
222
+ '[attr.data-state]': 'dataState()',
223
+ '(keydown.arrowDown)': 'handleArrowKey($event)',
224
+ '(keydown.arrowUp)': 'handleArrowKey($event)',
225
+ '(keydown.arrowLeft)': 'handleArrowKey($event)',
226
+ '(keydown.arrowRight)': 'handleArrowKey($event)',
227
+ '(keydown.home)': 'handleArrowKey($event)',
228
+ '(keydown.end)': 'handleArrowKey($event)'
229
+ }
405
230
  }]
406
- }], ctorParameters: () => [], propDecorators: { trigger: [{
407
- type: ContentChild,
408
- args: [RdxAccordionTriggerDirective, { descendants: true }]
409
- }], content: [{
410
- type: ContentChild,
411
- args: [forwardRef(() => RdxAccordionContentDirective), { descendants: true }]
412
- }], expanded: [{
413
- type: Input,
414
- args: [{ transform: booleanAttribute }]
415
- }], value: [{
416
- type: Input
417
- }], disabled: [{
418
- type: Input,
419
- args: [{ transform: booleanAttribute }]
420
- }], closed: [{
421
- type: Output
422
- }], opened: [{
423
- type: Output
424
- }], expandedChange: [{
425
- type: Output
426
- }] } });
231
+ }], ctorParameters: () => [] });
427
232
 
428
233
  class RdxAccordionContentDirective {
429
234
  constructor() {
430
- this.item = inject(RdxAccordionItemDirective);
431
- this.nativeElement = inject(ElementRef).nativeElement;
432
- this.hidden = false;
433
- }
434
- onAnimationEnd() {
435
- this.hidden = !this.item.expanded;
436
- const { height, width } = this.nativeElement.getBoundingClientRect();
437
- this.nativeElement.style.setProperty('--radix-collapsible-content-height', `${height}px`);
438
- this.nativeElement.style.setProperty('--radix-collapsible-content-width', `${width}px`);
439
- this.nativeElement.style.setProperty('--radix-accordion-content-height', 'var(--radix-collapsible-content-height)');
440
- this.nativeElement.style.setProperty('--radix-accordion-content-width', 'var(--radix-collapsible-content-width)');
235
+ this.rootContext = injectAccordionRootContext();
236
+ this.itemContext = injectAccordionItemContext();
441
237
  }
442
- onToggle() {
443
- if (!this.item.expanded) {
444
- this.hidden = false;
445
- }
238
+ ngOnInit() {
239
+ this.rootContext.changeModelValue(this.itemContext.value());
446
240
  }
447
241
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
448
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.4", type: RdxAccordionContentDirective, isStandalone: true, selector: "[rdxAccordionContent]", host: { listeners: { "animationend": "onAnimationEnd()" }, properties: { "attr.role": "\"region\"", "style.display": "hidden ? \"none\" : \"\"", "attr.data-state": "item.dataState", "attr.data-disabled": "item.disabled", "attr.data-orientation": "item.orientation" } }, exportAs: ["rdxAccordionContent"], ngImport: i0 }); }
242
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.4", type: RdxAccordionContentDirective, isStandalone: true, selector: "[rdxAccordionContent]", host: { attributes: { "role": "region" }, properties: { "attr.aria-labelledby": "itemContext.triggerId", "attr.data-state": "itemContext.dataState()", "attr.data-disabled": "itemContext.dataDisabled()", "attr.data-orientation": "rootContext.orientation()", "style": "{\n '--radix-accordion-content-height': 'var(--radix-collapsible-content-height)',\n '--radix-accordion-content-width': 'var(--radix-collapsible-content-width)',\n }" } }, hostDirectives: [{ directive: i1.RdxCollapsibleContentDirective }], ngImport: i0 }); }
449
243
  }
450
244
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionContentDirective, decorators: [{
451
245
  type: Directive,
452
246
  args: [{
453
247
  selector: '[rdxAccordionContent]',
454
- standalone: true,
455
- exportAs: 'rdxAccordionContent',
248
+ hostDirectives: [RdxCollapsibleContentDirective],
456
249
  host: {
457
- '[attr.role]': '"region"',
458
- '[style.display]': 'hidden ? "none" : ""',
459
- '[attr.data-state]': 'item.dataState',
460
- '[attr.data-disabled]': 'item.disabled',
461
- '[attr.data-orientation]': 'item.orientation',
462
- '(animationend)': 'onAnimationEnd()'
250
+ role: 'region',
251
+ '[attr.aria-labelledby]': 'itemContext.triggerId',
252
+ '[attr.data-state]': 'itemContext.dataState()',
253
+ '[attr.data-disabled]': 'itemContext.dataDisabled()',
254
+ '[attr.data-orientation]': 'rootContext.orientation()',
255
+ '[style]': `{
256
+ '--radix-accordion-content-height': 'var(--radix-collapsible-content-height)',
257
+ '--radix-accordion-content-width': 'var(--radix-collapsible-content-width)',
258
+ }`
463
259
  }
464
260
  }]
465
261
  }] });
466
262
 
467
263
  class RdxAccordionHeaderDirective {
468
264
  constructor() {
469
- this.item = inject(RdxAccordionItemDirective);
265
+ this.rootContext = injectAccordionRootContext();
266
+ this.itemContext = injectAccordionItemContext();
470
267
  }
471
268
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
472
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.4", type: RdxAccordionHeaderDirective, isStandalone: true, selector: "[rdxAccordionHeader]", host: { properties: { "attr.data-state": "item.dataState", "attr.data-disabled": "item.disabled", "attr.data-orientation": "item.orientation" } }, ngImport: i0 }); }
269
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.4", type: RdxAccordionHeaderDirective, isStandalone: true, selector: "[rdxAccordionHeader]", host: { properties: { "attr.data-state": "itemContext.dataState()", "attr.data-disabled": "itemContext.dataDisabled()", "attr.data-orientation": "rootContext.orientation()" } }, ngImport: i0 }); }
473
270
  }
474
271
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionHeaderDirective, decorators: [{
475
272
  type: Directive,
476
273
  args: [{
477
274
  selector: '[rdxAccordionHeader]',
478
- standalone: true,
479
275
  host: {
480
- '[attr.data-state]': 'item.dataState',
481
- '[attr.data-disabled]': 'item.disabled',
482
- '[attr.data-orientation]': 'item.orientation'
276
+ '[attr.data-state]': 'itemContext.dataState()',
277
+ '[attr.data-disabled]': 'itemContext.dataDisabled()',
278
+ '[attr.data-orientation]': 'rootContext.orientation()'
483
279
  }
484
280
  }]
485
281
  }] });
486
282
 
283
+ class RdxAccordionTriggerDirective {
284
+ constructor() {
285
+ this.rootContext = injectAccordionRootContext();
286
+ this.itemContext = injectAccordionItemContext();
287
+ this.itemContext.triggerId = inject(_IdGenerator).getId('rdx-accordion-trigger-');
288
+ }
289
+ changeItem() {
290
+ const triggerDisabled = this.rootContext.isSingle() && this.itemContext.open() && !this.rootContext.collapsible();
291
+ if (this.itemContext.disabled() || triggerDisabled) {
292
+ this.itemContext.updateOpen();
293
+ return;
294
+ }
295
+ this.rootContext.changeModelValue(this.itemContext.value());
296
+ }
297
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
298
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.4", type: RdxAccordionTriggerDirective, isStandalone: true, selector: "[rdxAccordionTrigger]", host: { listeners: { "click": "changeItem()" }, properties: { "id": "itemContext.triggerId", "attr.data-rdx-collection-item": "\"\"", "attr.role": "\"button\"", "attr.aria-disabled": "itemContext.open() && !rootContext.collapsible() ? \"true\" : undefined", "attr.data-orientation": "rootContext.orientation()", "disabled": "itemContext.disabled()" } }, hostDirectives: [{ directive: i1.RdxCollapsibleTriggerDirective }], ngImport: i0 }); }
299
+ }
300
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionTriggerDirective, decorators: [{
301
+ type: Directive,
302
+ args: [{
303
+ selector: '[rdxAccordionTrigger]',
304
+ hostDirectives: [RdxCollapsibleTriggerDirective],
305
+ host: {
306
+ '[id]': 'itemContext.triggerId',
307
+ '[attr.data-rdx-collection-item]': '""',
308
+ '[attr.role]': '"button"',
309
+ '[attr.aria-disabled]': 'itemContext.open() && !rootContext.collapsible() ? "true" : undefined',
310
+ '[attr.data-orientation]': 'rootContext.orientation()',
311
+ '[disabled]': 'itemContext.disabled()',
312
+ '(click)': 'changeItem()'
313
+ }
314
+ }]
315
+ }], ctorParameters: () => [] });
316
+
487
317
  const _imports = [
488
318
  RdxAccordionContentDirective,
489
319
  RdxAccordionHeaderDirective,
490
320
  RdxAccordionItemDirective,
491
321
  RdxAccordionRootDirective,
492
- RdxAccordionTriggerDirective
322
+ RdxAccordionTriggerDirective,
323
+ RdxAccordionContentPresenceDirective
493
324
  ];
494
325
  class RdxAccordionModule {
495
326
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
@@ -497,11 +328,13 @@ class RdxAccordionModule {
497
328
  RdxAccordionHeaderDirective,
498
329
  RdxAccordionItemDirective,
499
330
  RdxAccordionRootDirective,
500
- RdxAccordionTriggerDirective], exports: [RdxAccordionContentDirective,
331
+ RdxAccordionTriggerDirective,
332
+ RdxAccordionContentPresenceDirective], exports: [RdxAccordionContentDirective,
501
333
  RdxAccordionHeaderDirective,
502
334
  RdxAccordionItemDirective,
503
335
  RdxAccordionRootDirective,
504
- RdxAccordionTriggerDirective] }); }
336
+ RdxAccordionTriggerDirective,
337
+ RdxAccordionContentPresenceDirective] }); }
505
338
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionModule }); }
506
339
  }
507
340
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxAccordionModule, decorators: [{
@@ -516,5 +349,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
516
349
  * Generated bundle index. Do not edit.
517
350
  */
518
351
 
519
- export { RdxAccordionContentDirective, RdxAccordionHeaderDirective, RdxAccordionItemDirective, RdxAccordionModule, RdxAccordionRootDirective, RdxAccordionRootToken, RdxAccordionTriggerDirective };
352
+ export { RdxAccordionContentDirective, RdxAccordionContentPresenceDirective, RdxAccordionHeaderDirective, RdxAccordionItemDirective, RdxAccordionModule, RdxAccordionRootDirective, RdxAccordionTriggerDirective, injectAccordionItemContext, injectAccordionRootContext, provideAccordionItemContext, provideAccordionRootContext };
520
353
  //# sourceMappingURL=radix-ng-primitives-accordion.mjs.map