@radix-ng/primitives 0.10.0 → 0.11.1

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 (112) hide show
  1. package/accordion/src/accordion-content.directive.d.ts +8 -61
  2. package/accordion/src/accordion-header.directive.d.ts +2 -18
  3. package/accordion/src/accordion-item.directive.d.ts +54 -26
  4. package/accordion/src/accordion-root.directive.d.ts +41 -20
  5. package/accordion/src/accordion-trigger.directive.d.ts +6 -22
  6. package/collapsible/src/collapsible-content.directive.d.ts +8 -2
  7. package/collapsible/src/collapsible-content.token.d.ts +3 -0
  8. package/collapsible/src/collapsible-root.directive.d.ts +7 -4
  9. package/compodoc/documentation.json +11759 -0
  10. package/dialog/README.md +1 -0
  11. package/dialog/index.d.ts +1 -0
  12. package/esm2022/accordion/src/accordion-content.directive.mjs +29 -124
  13. package/esm2022/accordion/src/accordion-header.directive.mjs +10 -31
  14. package/esm2022/accordion/src/accordion-item.directive.mjs +149 -57
  15. package/esm2022/accordion/src/accordion-root.directive.mjs +103 -63
  16. package/esm2022/accordion/src/accordion-trigger.directive.mjs +22 -41
  17. package/esm2022/alert-dialog/src/alert-dialog-cancel.directive.mjs +3 -3
  18. package/esm2022/alert-dialog/src/alert-dialog-content.directive.mjs +3 -3
  19. package/esm2022/alert-dialog/src/alert-dialog-root.directive.mjs +3 -3
  20. package/esm2022/alert-dialog/src/alert-dialog-title.directive.mjs +3 -3
  21. package/esm2022/alert-dialog/src/alert-dialog-trigger.directive.mjs +3 -3
  22. package/esm2022/alert-dialog/src/alert-dialog.service.mjs +3 -3
  23. package/esm2022/avatar/src/avatar-fallback.directive.mjs +3 -3
  24. package/esm2022/avatar/src/avatar-image.directive.mjs +3 -3
  25. package/esm2022/avatar/src/avatar-root.directive.mjs +3 -3
  26. package/esm2022/checkbox/src/checkbox-button.directive.mjs +3 -3
  27. package/esm2022/checkbox/src/checkbox-indicator.directive.mjs +3 -3
  28. package/esm2022/checkbox/src/checkbox-input.directive.mjs +3 -3
  29. package/esm2022/checkbox/src/checkbox.directive.mjs +3 -3
  30. package/esm2022/collapsible/src/collapsible-content.directive.mjs +20 -7
  31. package/esm2022/collapsible/src/collapsible-content.token.mjs +3 -0
  32. package/esm2022/collapsible/src/collapsible-root.directive.mjs +17 -13
  33. package/esm2022/collapsible/src/collapsible-trigger.directive.mjs +3 -3
  34. package/esm2022/dialog/index.mjs +2 -0
  35. package/esm2022/dialog/radix-ng-primitives-dialog.mjs +5 -0
  36. package/esm2022/dropdown-menu/src/dropdown-menu-content.directive.mjs +3 -3
  37. package/esm2022/dropdown-menu/src/dropdown-menu-item-checkbox.directive.mjs +3 -3
  38. package/esm2022/dropdown-menu/src/dropdown-menu-item-indicator.directive.mjs +3 -3
  39. package/esm2022/dropdown-menu/src/dropdown-menu-item-radio-group.directive.mjs +3 -3
  40. package/esm2022/dropdown-menu/src/dropdown-menu-item-radio.directive.mjs +3 -3
  41. package/esm2022/dropdown-menu/src/dropdown-menu-item-selectable.mjs +3 -3
  42. package/esm2022/dropdown-menu/src/dropdown-menu-item.directive.mjs +3 -3
  43. package/esm2022/dropdown-menu/src/dropdown-menu-label.directive.mjs +3 -3
  44. package/esm2022/dropdown-menu/src/dropdown-menu-separator.directive.mjs +3 -3
  45. package/esm2022/dropdown-menu/src/dropdown-menu-trigger.directive.mjs +3 -3
  46. package/esm2022/label/src/label.directive.mjs +10 -5
  47. package/esm2022/menu/index.mjs +4 -4
  48. package/esm2022/menu/src/menu-content.directive.mjs +3 -3
  49. package/esm2022/menu/src/menu-directive.mjs +3 -3
  50. package/esm2022/menu/src/menu-group.directive.mjs +3 -3
  51. package/esm2022/menu/src/menu-item.directive.mjs +3 -3
  52. package/esm2022/menu/src/menu-label.directive.mjs +3 -3
  53. package/esm2022/menu/src/menu-separator.directive.mjs +3 -3
  54. package/esm2022/menubar/index.mjs +4 -4
  55. package/esm2022/menubar/src/menubar-content.directive.mjs +3 -3
  56. package/esm2022/menubar/src/menubar-item-checkbox.directive.mjs +3 -3
  57. package/esm2022/menubar/src/menubar-item-indicator.directive.mjs +3 -3
  58. package/esm2022/menubar/src/menubar-item-radio.directive.mjs +3 -3
  59. package/esm2022/menubar/src/menubar-item.directive.mjs +3 -3
  60. package/esm2022/menubar/src/menubar-radio-group.directive.mjs +3 -3
  61. package/esm2022/menubar/src/menubar-root.directive.mjs +3 -3
  62. package/esm2022/menubar/src/menubar-separator.directive.mjs +3 -3
  63. package/esm2022/menubar/src/menubar-trigger.directive.mjs +3 -3
  64. package/esm2022/progress/src/progress-indicator.directive.mjs +3 -3
  65. package/esm2022/progress/src/progress-root.directive.mjs +3 -3
  66. package/esm2022/radio/src/radio-indicator.directive.mjs +10 -10
  67. package/esm2022/radio/src/radio-item.directive.mjs +29 -18
  68. package/esm2022/radio/src/radio-root.directive.mjs +110 -16
  69. package/esm2022/radio/src/radio-tokens.mjs +3 -0
  70. package/esm2022/separator/src/separator.directive.mjs +3 -3
  71. package/esm2022/switch/index.mjs +4 -4
  72. package/esm2022/switch/src/switch-input.directive.mjs +3 -3
  73. package/esm2022/switch/src/switch-root.directive.mjs +3 -3
  74. package/esm2022/switch/src/switch-thumb.directive.mjs +3 -3
  75. package/esm2022/tabs/index.mjs +4 -4
  76. package/esm2022/tabs/src/tabs-content.directive.mjs +3 -3
  77. package/esm2022/tabs/src/tabs-context.service.mjs +3 -3
  78. package/esm2022/tabs/src/tabs-list.directive.mjs +3 -3
  79. package/esm2022/tabs/src/tabs-root.directive.mjs +3 -3
  80. package/esm2022/tabs/src/tabs-trigger.directive.mjs +3 -3
  81. package/esm2022/toggle/src/toggle.directive.mjs +3 -3
  82. package/esm2022/toggle-group/src/toggle-group-button.directive.mjs +3 -3
  83. package/esm2022/toggle-group/src/toggle-group-multi.directive.mjs +3 -3
  84. package/esm2022/toggle-group/src/toggle-group.directive.mjs +3 -3
  85. package/fesm2022/radix-ng-primitives-accordion.mjs +317 -323
  86. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  87. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +18 -18
  88. package/fesm2022/radix-ng-primitives-avatar.mjs +9 -9
  89. package/fesm2022/radix-ng-primitives-checkbox.mjs +12 -12
  90. package/fesm2022/radix-ng-primitives-collapsible.mjs +61 -44
  91. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  92. package/fesm2022/radix-ng-primitives-dialog.mjs +4 -0
  93. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -0
  94. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs +30 -30
  95. package/fesm2022/radix-ng-primitives-label.mjs +9 -4
  96. package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
  97. package/fesm2022/radix-ng-primitives-menu.mjs +22 -22
  98. package/fesm2022/radix-ng-primitives-menubar.mjs +31 -31
  99. package/fesm2022/radix-ng-primitives-progress.mjs +6 -6
  100. package/fesm2022/radix-ng-primitives-radio.mjs +182 -77
  101. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  102. package/fesm2022/radix-ng-primitives-separator.mjs +3 -3
  103. package/fesm2022/radix-ng-primitives-switch.mjs +13 -13
  104. package/fesm2022/radix-ng-primitives-tabs.mjs +19 -19
  105. package/fesm2022/radix-ng-primitives-toggle-group.mjs +9 -9
  106. package/fesm2022/radix-ng-primitives-toggle.mjs +3 -3
  107. package/label/src/label.directive.d.ts +9 -3
  108. package/package.json +7 -1
  109. package/radio/src/radio-indicator.directive.d.ts +4 -2
  110. package/radio/src/radio-item.directive.d.ts +10 -5
  111. package/radio/src/radio-root.directive.d.ts +19 -18
  112. package/radio/src/radio-tokens.d.ts +12 -0
@@ -1,430 +1,424 @@
1
- import * as i1 from '@angular/cdk/accordion';
2
- import { CdkAccordionItem, CdkAccordion } from '@angular/cdk/accordion';
3
1
  import * as i0 from '@angular/core';
4
- import { InjectionToken, inject, ElementRef, signal, input, effect, Directive, contentChild, Input, contentChildren } from '@angular/core';
5
- import { animationFrameScheduler } from 'rxjs';
2
+ import { InjectionToken, inject, EventEmitter, booleanAttribute, Directive, Input, ContentChildren, forwardRef, Output, ElementRef, ChangeDetectorRef, ContentChild } 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 } from '@angular/cdk/keycodes';
6
8
 
7
- const RdxAccordionContentToken = new InjectionToken('RdxAccordionContentToken');
8
- class RdxAccordionContentDirective {
9
+ const RdxAccordionRootToken = new InjectionToken('RdxAccordionRootDirective');
10
+ let nextId$1 = 0;
11
+ class RdxAccordionRootDirective {
9
12
  constructor() {
13
+ this.selectionDispatcher = inject(UniqueSelectionDispatcher);
14
+ this.dir = inject(Directionality, { optional: true });
15
+ this.id = `rdx-accordion-${nextId$1++}`;
16
+ this.openCloseAllActions = new Subject();
10
17
  /**
11
- * @ignore
12
- */
13
- this.elementRef = inject(ElementRef);
14
- /**
15
- * @ignore
18
+ * The orientation of the accordion.
16
19
  */
17
- this.initialized = signal(false);
18
- /**
19
- * Current item state
20
- */
21
- this.state = signal('closed');
22
- /**
23
- * When true, prevents the user from interacting with the accordion and all its items.
24
- */
25
- this.disabled = input(false);
20
+ this.orientation = 'vertical';
26
21
  /**
27
- * @ignore
22
+ * Determines whether one or multiple items can be opened at the same time.
28
23
  */
29
- this.accordionItem = inject(CdkAccordionItem);
24
+ this.type = 'single';
30
25
  /**
31
26
  * @ignore
32
27
  */
33
- this.orientation = 'vertical';
34
- effect(() => {
35
- if (this.state()) {
36
- this.setPresence();
37
- }
38
- });
28
+ this.collapsible = true;
29
+ this.onValueChange = new EventEmitter();
30
+ this._defaultValue = [];
39
31
  }
40
- /**
41
- * @ignore
42
- */
43
- ngOnInit() {
44
- this.togglePresence();
32
+ get isMultiple() {
33
+ return this.type === 'multiple';
45
34
  }
46
35
  /**
47
- * @ignore
36
+ * The value of the item to expand when initially rendered and type is "single". Use when you do not need to control the state of the items.
48
37
  */
49
- setOpen(state) {
50
- if (this.disabled()) {
51
- return;
52
- }
53
- if (state === undefined) {
54
- this.state.update(() => (this.state() === 'open' ? 'closed' : 'open'));
55
- }
56
- else {
57
- this.state.update(() => state);
38
+ set defaultValue(value) {
39
+ if (value !== this._defaultValue) {
40
+ this._defaultValue = Array.isArray(value) ? value : [value];
58
41
  }
59
42
  }
43
+ get defaultValue() {
44
+ return this.isMultiple ? this._defaultValue : this._defaultValue[0];
45
+ }
60
46
  /**
61
- * @ignore
47
+ * The controlled value of the item to expand
62
48
  */
63
- initialize() {
64
- if (!this.initialized()) {
65
- this.togglePresence();
66
- animationFrameScheduler.schedule(() => {
67
- this.elementRef.nativeElement.getAnimations().forEach((animation) => animation.cancel());
68
- this.initialized.set(true);
69
- });
49
+ set value(value) {
50
+ if (value !== this._value) {
51
+ this._value = Array.isArray(value) ? value : [value];
52
+ this.selectionDispatcher.notify(this.value, this.id);
70
53
  }
71
54
  }
72
- /**
73
- * @ignore
74
- */
75
- setPresence() {
76
- if (!this.initialized()) {
77
- this.initialize();
78
- return;
55
+ get value() {
56
+ if (this._value === undefined) {
57
+ return this.defaultValue;
79
58
  }
80
- animationFrameScheduler.schedule(() => {
81
- const animations = this.elementRef.nativeElement.getAnimations();
82
- const hidden = this.elementRef.nativeElement.hasAttribute('hidden');
83
- if (hidden) {
84
- this.show();
85
- const rect = this.elementRef.nativeElement.getBoundingClientRect();
86
- const height = `${this.elementRef.nativeElement.scrollHeight /*rect.height*/}px`;
87
- const width = `${rect.width}px`;
88
- this.elementRef.nativeElement.style.setProperty('--radix-accordion-content-height', height);
89
- this.elementRef.nativeElement.style.setProperty('--radix-accordion-content-width', width);
90
- this.hide();
91
- }
92
- Promise.all(animations.map((animation) => animation.finished)).then(() => {
93
- this.togglePresence();
94
- });
95
- });
59
+ return this.isMultiple ? this._value : this._value[0];
96
60
  }
97
61
  /**
98
62
  * @ignore
99
63
  */
100
- togglePresence() {
101
- if (this.state() === 'open') {
102
- this.show();
64
+ ngAfterContentInit() {
65
+ this.selectionDispatcher.notify((this._value ?? this._defaultValue), this.id);
66
+ this.keyManager = new FocusKeyManager(this.items).withHomeAndEnd();
67
+ if (this.orientation === 'horizontal') {
68
+ this.keyManager.withHorizontalOrientation(this.dir?.value || 'ltr');
103
69
  }
104
70
  else {
105
- this.hide();
71
+ this.keyManager.withVerticalOrientation();
106
72
  }
73
+ this.onValueChangeSubscription = merge(...this.items.map((item) => item.expandedChange)).subscribe(() => this.onValueChange.emit());
107
74
  }
108
75
  /**
109
76
  * @ignore
110
77
  */
111
- show() {
112
- this.elementRef.nativeElement.removeAttribute('hidden');
78
+ ngOnDestroy() {
79
+ this.openCloseAllActions.complete();
80
+ this.onValueChangeSubscription.unsubscribe();
113
81
  }
114
82
  /**
115
83
  * @ignore
116
84
  */
117
- hide() {
118
- this.elementRef.nativeElement.setAttribute('hidden', '');
119
- }
120
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
121
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.1.2", type: RdxAccordionContentDirective, isStandalone: true, selector: "[rdxAccordionContent]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-state": "state()", "attr.data-disabled": "disabled() ? \"\" : undefined", "attr.data-orientation": "orientation" } }, providers: [{ provide: RdxAccordionContentToken, useExisting: RdxAccordionContentDirective }], exportAs: ["rdxAccordionContent"], hostDirectives: [{ directive: i1.CdkAccordionItem }], ngImport: i0 }); }
122
- }
123
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionContentDirective, decorators: [{
124
- type: Directive,
125
- args: [{
126
- selector: '[rdxAccordionContent]',
127
- standalone: true,
128
- exportAs: 'rdxAccordionContent',
129
- providers: [{ provide: RdxAccordionContentToken, useExisting: RdxAccordionContentDirective }],
130
- host: {
131
- '[attr.data-state]': 'state()',
132
- '[attr.data-disabled]': 'disabled() ? "" : undefined',
133
- '[attr.data-orientation]': 'orientation'
134
- },
135
- hostDirectives: [CdkAccordionItem]
136
- }]
137
- }], ctorParameters: () => [] });
138
-
139
- const RdxAccordionItemToken = new InjectionToken('RdxAccordionItemToken');
140
- function injectAccordionItem() {
141
- return inject(RdxAccordionItemDirective);
142
- }
143
- class RdxAccordionItemDirective {
144
- constructor() {
145
- /**
146
- * @ignore
147
- */
148
- this.accordionContent = contentChild.required(RdxAccordionContentToken);
149
- /**
150
- * Current item state
151
- */
152
- this.state = signal('closed');
153
- /**
154
- * When true, prevents the user from interacting with the item.
155
- */
156
- this.disabled = input(false);
157
- /**
158
- * @ignore
159
- */
160
- this.orientation = 'vertical';
161
- }
162
- /**
163
- * Changes current item state
164
- */
165
- setOpen(state) {
166
- if (this.disabled()) {
167
- return;
85
+ handleKeydown(event) {
86
+ if (!this.keyManager.activeItem) {
87
+ this.keyManager.setFirstItemActive();
168
88
  }
169
- if (state === undefined) {
170
- this.state.update(() => (this.state() === 'open' ? 'closed' : 'open'));
89
+ const activeItem = this.keyManager.activeItem;
90
+ if ((event.keyCode === ENTER || event.keyCode === SPACE) &&
91
+ !this.keyManager.isTyping() &&
92
+ activeItem &&
93
+ !activeItem.disabled) {
94
+ event.preventDefault();
95
+ activeItem.toggle();
171
96
  }
172
97
  else {
173
- this.state.update(() => state);
98
+ this.keyManager.onKeydown(event);
99
+ }
100
+ }
101
+ /** Opens all enabled accordion items in an accordion where multi is enabled.
102
+ * @ignore
103
+ */
104
+ openAll() {
105
+ if (this.isMultiple) {
106
+ this.openCloseAllActions.next(true);
174
107
  }
175
- this.accordionContent().setOpen(this.state());
108
+ }
109
+ /** Closes all enabled accordion items.
110
+ * @ignore
111
+ */
112
+ closeAll() {
113
+ this.openCloseAllActions.next(false);
176
114
  }
177
115
  /**
178
116
  * @ignore
179
117
  */
180
- setOrientation(orientation) {
181
- this.orientation = orientation;
182
- this.accordionContent().orientation = orientation;
183
- }
184
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
185
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "18.1.2", type: RdxAccordionItemDirective, isStandalone: true, selector: "[rdxAccordionItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-state": "state()", "attr.data-disabled": "disabled() ? \"\" : undefined", "attr.data-orientation": "orientation" } }, providers: [
186
- {
187
- provide: RdxAccordionItemToken,
188
- useExisting: RdxAccordionItemDirective,
189
- multi: true
190
- }
191
- ], queries: [{ propertyName: "accordionContent", first: true, predicate: RdxAccordionContentToken, descendants: true, isSignal: true }], exportAs: ["rdxAccordionItem"], hostDirectives: [{ directive: i1.CdkAccordion }], ngImport: i0 }); }
118
+ setActiveItem(item) {
119
+ this.keyManager.setActiveItem(item);
120
+ }
121
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
122
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "18.2.1", 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: [
123
+ { provide: RdxAccordionRootToken, useExisting: RdxAccordionRootDirective },
124
+ { provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }
125
+ ], queries: [{ propertyName: "items", predicate: i0.forwardRef(() => RdxAccordionItemDirective), descendants: true }], ngImport: i0 }); }
192
126
  }
193
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionItemDirective, decorators: [{
127
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionRootDirective, decorators: [{
194
128
  type: Directive,
195
129
  args: [{
196
- selector: '[rdxAccordionItem]',
130
+ selector: '[rdxAccordionRoot]',
197
131
  standalone: true,
198
- exportAs: 'rdxAccordionItem',
199
132
  providers: [
200
- {
201
- provide: RdxAccordionItemToken,
202
- useExisting: RdxAccordionItemDirective,
203
- multi: true
204
- }
133
+ { provide: RdxAccordionRootToken, useExisting: RdxAccordionRootDirective },
134
+ { provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }
205
135
  ],
206
136
  host: {
207
- '[attr.data-state]': 'state()',
208
- '[attr.data-disabled]': 'disabled() ? "" : undefined',
209
- '[attr.data-orientation]': 'orientation'
210
- },
211
- hostDirectives: [CdkAccordion]
137
+ '[attr.data-orientation]': 'orientation',
138
+ '(keydown)': 'handleKeydown($event)'
139
+ }
212
140
  }]
213
- }], propDecorators: { value: [{
141
+ }], propDecorators: { disabled: [{
142
+ type: Input,
143
+ args: [{ transform: booleanAttribute }]
144
+ }], orientation: [{
145
+ type: Input
146
+ }], items: [{
147
+ type: ContentChildren,
148
+ args: [forwardRef(() => RdxAccordionItemDirective), { descendants: true }]
149
+ }], defaultValue: [{
214
150
  type: Input
151
+ }], type: [{
152
+ type: Input
153
+ }], collapsible: [{
154
+ type: Input
155
+ }], value: [{
156
+ type: Input
157
+ }], onValueChange: [{
158
+ type: Output
215
159
  }] } });
216
160
 
217
- class RdxAccordionHeaderDirective {
161
+ class RdxAccordionTriggerDirective {
218
162
  constructor() {
219
- /**
220
- * @ignore
221
- */
222
- this.accordionItem = injectAccordionItem();
223
- }
224
- /**
225
- * @ignore
226
- */
227
- getState() {
228
- return this.accordionItem.state();
163
+ this.nativeElement = inject(ElementRef).nativeElement;
164
+ this.accordionRoot = inject(RdxAccordionRootDirective);
165
+ this.item = inject(RdxAccordionItemDirective);
229
166
  }
230
167
  /**
231
- * @ignore
168
+ * Fires when trigger clicked
232
169
  */
233
- getDisabled() {
234
- return this.accordionItem.disabled() ? '' : undefined;
170
+ onClick() {
171
+ if (!this.accordionRoot.collapsible && this.item.expanded)
172
+ return;
173
+ this.item.toggle();
174
+ this.accordionRoot.setActiveItem(this.item);
235
175
  }
236
- /**
237
- * @ignore
238
- */
239
- getOrientation() {
240
- return this.accordionItem.orientation;
176
+ focus() {
177
+ this.nativeElement.focus();
241
178
  }
242
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
243
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.1.2", type: RdxAccordionHeaderDirective, isStandalone: true, selector: "[rdxAccordionHeader]", host: { properties: { "attr.data-state": "getState()", "attr.data-disabled": "getDisabled()", "attr.data-orientation": "getOrientation()" } }, ngImport: i0 }); }
179
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
180
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.1", 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 }); }
244
181
  }
245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionHeaderDirective, decorators: [{
182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionTriggerDirective, decorators: [{
246
183
  type: Directive,
247
184
  args: [{
248
- selector: '[rdxAccordionHeader]',
185
+ selector: '[rdxAccordionTrigger]',
249
186
  standalone: true,
250
187
  host: {
251
- '[attr.data-state]': 'getState()',
252
- '[attr.data-disabled]': 'getDisabled()',
253
- '[attr.data-orientation]': 'getOrientation()'
188
+ '[attr.role]': '"button"',
189
+ '[attr.aria-expanded]': 'item.expanded',
190
+ '[attr.data-state]': 'item.dataState',
191
+ '[attr.data-disabled]': 'item.disabled',
192
+ '[attr.disabled]': 'item.disabled ? "" : null',
193
+ '[attr.data-orientation]': 'item.orientation',
194
+ '(click)': 'onClick()'
254
195
  }
255
196
  }]
256
197
  }] });
257
198
 
258
- const RdxAccordionRootToken = new InjectionToken('RdxAccordionRootDirective');
259
- function injectAccordionRoot() {
260
- return inject(RdxAccordionRootDirective);
261
- }
262
- class RdxAccordionRootDirective {
199
+ let nextId = 0;
200
+ class RdxAccordionItemDirective {
201
+ get dataState() {
202
+ return this.expanded ? 'open' : 'closed';
203
+ }
204
+ get orientation() {
205
+ return this.accordion.orientation;
206
+ }
207
+ /** Whether the AccordionItem is expanded. */
208
+ set expanded(expanded) {
209
+ // Only emit events and update the internal value if the value changes.
210
+ if (this._expanded !== expanded) {
211
+ this._expanded = expanded;
212
+ this.expandedChange.emit(expanded);
213
+ if (expanded) {
214
+ this.opened.emit();
215
+ /**
216
+ * In the unique selection dispatcher, the id parameter is the id of the CdkAccordionItem,
217
+ * the name value is the id of the accordion.
218
+ */
219
+ const accordionId = this.accordion ? this.accordion.id : this.value;
220
+ this.expansionDispatcher.notify(this.value, accordionId);
221
+ }
222
+ else {
223
+ this.closed.emit();
224
+ }
225
+ // Ensures that the animation will run when the value is set outside of an `@Input`.
226
+ // This includes cases like the open, close and toggle methods.
227
+ this.changeDetectorRef.markForCheck();
228
+ }
229
+ }
230
+ get expanded() {
231
+ return this._expanded;
232
+ }
233
+ set value(value) {
234
+ this._value = value;
235
+ }
236
+ get value() {
237
+ return this._value || this.id;
238
+ }
239
+ /** Whether the AccordionItem is disabled. */
240
+ set disabled(value) {
241
+ this._disabled = value;
242
+ }
243
+ get disabled() {
244
+ return this.accordion.disabled ?? this._disabled;
245
+ }
263
246
  constructor() {
247
+ this.accordion = inject(RdxAccordionRootToken, { skipSelf: true });
248
+ this.changeDetectorRef = inject(ChangeDetectorRef);
249
+ this.expansionDispatcher = inject(UniqueSelectionDispatcher);
264
250
  /**
265
- * @private
266
- * @ignore
267
- */
268
- this.accordionItems = contentChildren(RdxAccordionItemToken);
269
- /**
270
- * @private
271
- * @ignore
272
- */
273
- this._orientation = 'vertical';
274
- /**
275
- * @private
251
+ * The unique AccordionItem id.
276
252
  * @ignore
277
253
  */
278
- this._value = [];
279
- /**
280
- * The value of the item to expand when initially rendered and type is "single". Use when you do not need to control the state of the items.
281
- */
282
- this.defaultValue = [];
283
- /**
284
- * Determines whether one or multiple items can be opened at the same time.
285
- */
286
- this.type = 'single';
254
+ this.id = `rdx-accordion-item-${nextId++}`;
255
+ this._expanded = false;
256
+ this._disabled = false;
257
+ /** Event emitted every time the AccordionItem is closed. */
258
+ this.closed = new EventEmitter();
259
+ /** Event emitted every time the AccordionItem is opened. */
260
+ this.opened = new EventEmitter();
261
+ /** Event emitted when the AccordionItem is destroyed. */
262
+ this.destroyed = new EventEmitter();
287
263
  /**
288
- * @ignore
264
+ * Emits whenever the expanded state of the accordion changes.
265
+ * Primarily used to facilitate two-way binding.
266
+ * @docs-private
289
267
  */
290
- this.collapsible = true;
291
- }
292
- /**
293
- * The controlled value of the item to expand
294
- */
295
- set value(value) {
296
- if (value !== undefined) {
297
- this._value = Array.isArray(value) ? value : [value];
298
- }
299
- else {
300
- this._value = [];
268
+ this.expandedChange = new EventEmitter();
269
+ /** Subscription to openAll/closeAll events. */
270
+ this.openCloseAllSubscription = Subscription.EMPTY;
271
+ this.removeUniqueSelectionListener = this.expansionDispatcher.listen((id, accordionId) => {
272
+ if (this.accordion.isMultiple) {
273
+ if (this.accordion.id === accordionId && id.includes(this.value)) {
274
+ this.expanded = true;
275
+ }
276
+ }
277
+ else {
278
+ this.expanded = this.accordion.id === accordionId && id.includes(this.value);
279
+ }
280
+ });
281
+ // When an accordion item is hosted in an accordion, subscribe to open/close events.
282
+ if (this.accordion) {
283
+ this.openCloseAllSubscription = this.subscribeToOpenCloseAllActions();
301
284
  }
302
- this.onValueChange(this._value);
303
285
  }
304
- /**
305
- * The orientation of the accordion.
306
- */
307
- set orientation(orientation) {
308
- this._orientation = orientation ?? 'vertical';
309
- this.accordionItems().forEach((accordionItem) => accordionItem.setOrientation(this._orientation));
286
+ /** Emits an event for the accordion item being destroyed. */
287
+ ngOnDestroy() {
288
+ this.opened.complete();
289
+ this.closed.complete();
290
+ this.destroyed.emit();
291
+ this.destroyed.complete();
292
+ this.removeUniqueSelectionListener();
293
+ this.openCloseAllSubscription.unsubscribe();
310
294
  }
311
- /**
312
- * @ignore
313
- */
314
- ngOnInit() {
315
- if (this.defaultValue) {
316
- this.value = this.defaultValue;
295
+ focus() {
296
+ this.trigger.focus();
297
+ }
298
+ /** Toggles the expanded state of the accordion item. */
299
+ toggle() {
300
+ if (!this.disabled) {
301
+ this.content.onToggle();
302
+ this.expanded = !this.expanded;
317
303
  }
318
304
  }
319
- /**
320
- * @ignore
321
- */
322
- onValueChange(value) {
323
- if (this.type === 'single') {
324
- const currentValue = value.length > 0 ? value[0] : undefined;
325
- this.accordionItems().forEach((accordionItem) => {
326
- if (accordionItem.value === currentValue) {
327
- accordionItem.setOpen();
328
- }
329
- else {
330
- accordionItem.setOpen('closed');
331
- }
332
- });
305
+ /** Sets the expanded state of the accordion item to false. */
306
+ close() {
307
+ if (!this.disabled) {
308
+ this.expanded = false;
333
309
  }
334
- else {
335
- value.forEach((valueItem) => {
336
- this.accordionItems().forEach((accordionItem) => {
337
- if (accordionItem.value === valueItem) {
338
- accordionItem.setOpen();
339
- }
340
- });
341
- });
310
+ }
311
+ /** Sets the expanded state of the accordion item to true. */
312
+ open() {
313
+ if (!this.disabled) {
314
+ this.expanded = true;
342
315
  }
343
316
  }
344
- /**
345
- * @ignore
346
- */
347
- getOrientation() {
348
- return this._orientation;
317
+ subscribeToOpenCloseAllActions() {
318
+ return this.accordion.openCloseAllActions.subscribe((expanded) => {
319
+ // Only change expanded state if item is enabled
320
+ if (!this.disabled) {
321
+ this.expanded = expanded;
322
+ }
323
+ });
349
324
  }
350
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
351
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "18.1.2", type: RdxAccordionRootDirective, isStandalone: true, selector: "[rdxAccordionRoot]", inputs: { defaultValue: "defaultValue", type: "type", collapsible: "collapsible", value: "value", orientation: "orientation" }, host: { properties: { "attr.data-orientation": "getOrientation()" } }, providers: [{ provide: RdxAccordionRootToken, useExisting: RdxAccordionRootDirective }], queries: [{ propertyName: "accordionItems", predicate: RdxAccordionItemToken, isSignal: true }], ngImport: i0 }); }
325
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
326
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "18.2.1", 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: [
327
+ { provide: RdxAccordionRootToken, useValue: undefined }
328
+ ], queries: [{ propertyName: "trigger", first: true, predicate: RdxAccordionTriggerDirective, descendants: true }, { propertyName: "content", first: true, predicate: i0.forwardRef(() => RdxAccordionContentDirective), descendants: true }], exportAs: ["rdxAccordionItem"], ngImport: i0 }); }
352
329
  }
353
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionRootDirective, decorators: [{
330
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionItemDirective, decorators: [{
354
331
  type: Directive,
355
332
  args: [{
356
- selector: '[rdxAccordionRoot]',
333
+ selector: '[rdxAccordionItem]',
357
334
  standalone: true,
358
- providers: [{ provide: RdxAccordionRootToken, useExisting: RdxAccordionRootDirective }],
335
+ exportAs: 'rdxAccordionItem',
359
336
  host: {
360
- '[attr.data-orientation]': 'getOrientation()'
361
- }
337
+ '[attr.data-state]': 'dataState',
338
+ '[attr.data-disabled]': 'disabled',
339
+ '[attr.data-orientation]': 'orientation'
340
+ },
341
+ providers: [
342
+ { provide: RdxAccordionRootToken, useValue: undefined }
343
+ ]
362
344
  }]
363
- }], propDecorators: { defaultValue: [{
364
- type: Input
365
- }], type: [{
366
- type: Input
367
- }], collapsible: [{
368
- type: Input
345
+ }], ctorParameters: () => [], propDecorators: { trigger: [{
346
+ type: ContentChild,
347
+ args: [RdxAccordionTriggerDirective, { descendants: true }]
348
+ }], content: [{
349
+ type: ContentChild,
350
+ args: [forwardRef(() => RdxAccordionContentDirective), { descendants: true }]
351
+ }], expanded: [{
352
+ type: Input,
353
+ args: [{ transform: booleanAttribute }]
369
354
  }], value: [{
370
355
  type: Input
371
- }], orientation: [{
372
- type: Input
356
+ }], disabled: [{
357
+ type: Input,
358
+ args: [{ transform: booleanAttribute }]
359
+ }], closed: [{
360
+ type: Output
361
+ }], opened: [{
362
+ type: Output
363
+ }], expandedChange: [{
364
+ type: Output
373
365
  }] } });
374
366
 
375
- class RdxAccordionTriggerDirective {
367
+ class RdxAccordionContentDirective {
376
368
  constructor() {
377
- /**
378
- * @ignore
379
- */
380
- this.accordionRoot = injectAccordionRoot();
381
- /**
382
- * @ignore
383
- */
384
- this.accordionItem = injectAccordionItem();
385
- }
386
- /**
387
- * Fires when trigger clicked
388
- */
389
- onClick() {
390
- if (!this.accordionRoot.collapsible) {
391
- return;
392
- }
393
- if (this.accordionItem.value) {
394
- this.accordionRoot.value = [this.accordionItem.value];
395
- }
369
+ this.item = inject(RdxAccordionItemDirective);
370
+ this.nativeElement = inject(ElementRef).nativeElement;
371
+ this.hidden = false;
396
372
  }
397
- /**
398
- * @ignore
399
- */
400
- getState() {
401
- return this.accordionItem.state();
373
+ onAnimationEnd() {
374
+ this.hidden = !this.item.expanded;
375
+ const { height, width } = this.nativeElement.getBoundingClientRect();
376
+ this.nativeElement.style.setProperty('--radix-collapsible-content-height', `${height}px`);
377
+ this.nativeElement.style.setProperty('--radix-collapsible-content-width', `${width}px`);
378
+ this.nativeElement.style.setProperty('--radix-accordion-content-height', 'var(--radix-collapsible-content-height)');
379
+ this.nativeElement.style.setProperty('--radix-accordion-content-width', 'var(--radix-collapsible-content-width)');
402
380
  }
403
- /**
404
- * @ignore
405
- */
406
- getDisabled() {
407
- return this.accordionItem.disabled() || undefined;
381
+ onToggle() {
382
+ if (!this.item.expanded) {
383
+ this.hidden = false;
384
+ }
408
385
  }
409
- /**
410
- * @ignore
411
- */
412
- getOrientation() {
413
- return this.accordionRoot.getOrientation();
386
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
387
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.1", 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 }); }
388
+ }
389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionContentDirective, decorators: [{
390
+ type: Directive,
391
+ args: [{
392
+ selector: '[rdxAccordionContent]',
393
+ standalone: true,
394
+ exportAs: 'rdxAccordionContent',
395
+ host: {
396
+ '[attr.role]': '"region"',
397
+ '[style.display]': 'hidden ? "none" : ""',
398
+ '[attr.data-state]': 'item.dataState',
399
+ '[attr.data-disabled]': 'item.disabled',
400
+ '[attr.data-orientation]': 'item.orientation',
401
+ '(animationend)': 'onAnimationEnd()'
402
+ }
403
+ }]
404
+ }] });
405
+
406
+ class RdxAccordionHeaderDirective {
407
+ constructor() {
408
+ this.item = inject(RdxAccordionItemDirective);
414
409
  }
415
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
416
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.1.2", type: RdxAccordionTriggerDirective, isStandalone: true, selector: "[rdxAccordionTrigger]", host: { listeners: { "click": "onClick()" }, properties: { "attr.data-state": "getState()", "attr.data-disabled": "getDisabled()", "attr.data-orientation": "getOrientation()" } }, ngImport: i0 }); }
410
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
411
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.1", 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 }); }
417
412
  }
418
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RdxAccordionTriggerDirective, decorators: [{
413
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: RdxAccordionHeaderDirective, decorators: [{
419
414
  type: Directive,
420
415
  args: [{
421
- selector: '[rdxAccordionTrigger]',
416
+ selector: '[rdxAccordionHeader]',
422
417
  standalone: true,
423
418
  host: {
424
- '(click)': 'onClick()',
425
- '[attr.data-state]': 'getState()',
426
- '[attr.data-disabled]': 'getDisabled()',
427
- '[attr.data-orientation]': 'getOrientation()'
419
+ '[attr.data-state]': 'item.dataState',
420
+ '[attr.data-disabled]': 'item.disabled',
421
+ '[attr.data-orientation]': 'item.orientation'
428
422
  }
429
423
  }]
430
424
  }] });
@@ -433,5 +427,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImpor
433
427
  * Generated bundle index. Do not edit.
434
428
  */
435
429
 
436
- export { RdxAccordionContentDirective, RdxAccordionContentToken, RdxAccordionHeaderDirective, RdxAccordionItemDirective, RdxAccordionItemToken, RdxAccordionRootDirective, RdxAccordionRootToken, RdxAccordionTriggerDirective, injectAccordionItem, injectAccordionRoot };
430
+ export { RdxAccordionContentDirective, RdxAccordionHeaderDirective, RdxAccordionItemDirective, RdxAccordionRootDirective, RdxAccordionRootToken, RdxAccordionTriggerDirective };
437
431
  //# sourceMappingURL=radix-ng-primitives-accordion.mjs.map