@cute-widgets/base 20.0.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 (183) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +191 -0
  3. package/README.md +190 -0
  4. package/abstract/index.d.ts +327 -0
  5. package/alert/index.d.ts +68 -0
  6. package/autocomplete/index.d.ts +442 -0
  7. package/badge/index.d.ts +26 -0
  8. package/bottom-sheet/index.d.ts +231 -0
  9. package/button/index.d.ts +182 -0
  10. package/button-toggle/index.d.ts +225 -0
  11. package/card/index.d.ts +163 -0
  12. package/checkbox/index.d.ts +174 -0
  13. package/chips/index.d.ts +963 -0
  14. package/collapse/index.d.ts +97 -0
  15. package/core/animation/index.d.ts +43 -0
  16. package/core/datetime/index.d.ts +404 -0
  17. package/core/directives/index.d.ts +168 -0
  18. package/core/error/index.d.ts +74 -0
  19. package/core/index.d.ts +1039 -0
  20. package/core/interfaces/index.d.ts +114 -0
  21. package/core/layout/index.d.ts +53 -0
  22. package/core/line/index.d.ts +37 -0
  23. package/core/nav/index.d.ts +321 -0
  24. package/core/observers/index.d.ts +124 -0
  25. package/core/option/index.d.ts +185 -0
  26. package/core/pipes/index.d.ts +53 -0
  27. package/core/ripple/index.d.ts +66 -0
  28. package/core/testing/index.d.ts +154 -0
  29. package/core/theming/index.d.ts +118 -0
  30. package/core/types/index.d.ts +53 -0
  31. package/core/utils/index.d.ts +129 -0
  32. package/cute-widgets-base-20.0.1.tgz +0 -0
  33. package/datepicker/index.d.ts +1817 -0
  34. package/dialog/index.d.ts +484 -0
  35. package/divider/index.d.ts +24 -0
  36. package/expansion/README.md +8 -0
  37. package/expansion/index.d.ts +308 -0
  38. package/fesm2022/cute-widgets-base-abstract.mjs +547 -0
  39. package/fesm2022/cute-widgets-base-abstract.mjs.map +1 -0
  40. package/fesm2022/cute-widgets-base-alert.mjs +198 -0
  41. package/fesm2022/cute-widgets-base-alert.mjs.map +1 -0
  42. package/fesm2022/cute-widgets-base-autocomplete.mjs +1217 -0
  43. package/fesm2022/cute-widgets-base-autocomplete.mjs.map +1 -0
  44. package/fesm2022/cute-widgets-base-badge.mjs +75 -0
  45. package/fesm2022/cute-widgets-base-badge.mjs.map +1 -0
  46. package/fesm2022/cute-widgets-base-bottom-sheet.mjs +416 -0
  47. package/fesm2022/cute-widgets-base-bottom-sheet.mjs.map +1 -0
  48. package/fesm2022/cute-widgets-base-button-toggle.mjs +640 -0
  49. package/fesm2022/cute-widgets-base-button-toggle.mjs.map +1 -0
  50. package/fesm2022/cute-widgets-base-button.mjs +546 -0
  51. package/fesm2022/cute-widgets-base-button.mjs.map +1 -0
  52. package/fesm2022/cute-widgets-base-card.mjs +471 -0
  53. package/fesm2022/cute-widgets-base-card.mjs.map +1 -0
  54. package/fesm2022/cute-widgets-base-checkbox.mjs +390 -0
  55. package/fesm2022/cute-widgets-base-checkbox.mjs.map +1 -0
  56. package/fesm2022/cute-widgets-base-chips.mjs +2360 -0
  57. package/fesm2022/cute-widgets-base-chips.mjs.map +1 -0
  58. package/fesm2022/cute-widgets-base-collapse.mjs +259 -0
  59. package/fesm2022/cute-widgets-base-collapse.mjs.map +1 -0
  60. package/fesm2022/cute-widgets-base-core-animation.mjs +53 -0
  61. package/fesm2022/cute-widgets-base-core-animation.mjs.map +1 -0
  62. package/fesm2022/cute-widgets-base-core-datetime.mjs +568 -0
  63. package/fesm2022/cute-widgets-base-core-datetime.mjs.map +1 -0
  64. package/fesm2022/cute-widgets-base-core-directives.mjs +404 -0
  65. package/fesm2022/cute-widgets-base-core-directives.mjs.map +1 -0
  66. package/fesm2022/cute-widgets-base-core-error.mjs +105 -0
  67. package/fesm2022/cute-widgets-base-core-error.mjs.map +1 -0
  68. package/fesm2022/cute-widgets-base-core-interfaces.mjs +22 -0
  69. package/fesm2022/cute-widgets-base-core-interfaces.mjs.map +1 -0
  70. package/fesm2022/cute-widgets-base-core-layout.mjs +74 -0
  71. package/fesm2022/cute-widgets-base-core-layout.mjs.map +1 -0
  72. package/fesm2022/cute-widgets-base-core-line.mjs +87 -0
  73. package/fesm2022/cute-widgets-base-core-line.mjs.map +1 -0
  74. package/fesm2022/cute-widgets-base-core-nav.mjs +863 -0
  75. package/fesm2022/cute-widgets-base-core-nav.mjs.map +1 -0
  76. package/fesm2022/cute-widgets-base-core-observers.mjs +304 -0
  77. package/fesm2022/cute-widgets-base-core-observers.mjs.map +1 -0
  78. package/fesm2022/cute-widgets-base-core-option.mjs +373 -0
  79. package/fesm2022/cute-widgets-base-core-option.mjs.map +1 -0
  80. package/fesm2022/cute-widgets-base-core-pipes.mjs +97 -0
  81. package/fesm2022/cute-widgets-base-core-pipes.mjs.map +1 -0
  82. package/fesm2022/cute-widgets-base-core-ripple.mjs +172 -0
  83. package/fesm2022/cute-widgets-base-core-ripple.mjs.map +1 -0
  84. package/fesm2022/cute-widgets-base-core-testing.mjs +210 -0
  85. package/fesm2022/cute-widgets-base-core-testing.mjs.map +1 -0
  86. package/fesm2022/cute-widgets-base-core-theming.mjs +314 -0
  87. package/fesm2022/cute-widgets-base-core-theming.mjs.map +1 -0
  88. package/fesm2022/cute-widgets-base-core-types.mjs +22 -0
  89. package/fesm2022/cute-widgets-base-core-types.mjs.map +1 -0
  90. package/fesm2022/cute-widgets-base-core-utils.mjs +257 -0
  91. package/fesm2022/cute-widgets-base-core-utils.mjs.map +1 -0
  92. package/fesm2022/cute-widgets-base-core.mjs +1600 -0
  93. package/fesm2022/cute-widgets-base-core.mjs.map +1 -0
  94. package/fesm2022/cute-widgets-base-datepicker.mjs +4827 -0
  95. package/fesm2022/cute-widgets-base-datepicker.mjs.map +1 -0
  96. package/fesm2022/cute-widgets-base-dialog.mjs +1046 -0
  97. package/fesm2022/cute-widgets-base-dialog.mjs.map +1 -0
  98. package/fesm2022/cute-widgets-base-divider.mjs +86 -0
  99. package/fesm2022/cute-widgets-base-divider.mjs.map +1 -0
  100. package/fesm2022/cute-widgets-base-expansion.mjs +623 -0
  101. package/fesm2022/cute-widgets-base-expansion.mjs.map +1 -0
  102. package/fesm2022/cute-widgets-base-form-field.mjs +969 -0
  103. package/fesm2022/cute-widgets-base-form-field.mjs.map +1 -0
  104. package/fesm2022/cute-widgets-base-grid-list.mjs +715 -0
  105. package/fesm2022/cute-widgets-base-grid-list.mjs.map +1 -0
  106. package/fesm2022/cute-widgets-base-icon.mjs +1105 -0
  107. package/fesm2022/cute-widgets-base-icon.mjs.map +1 -0
  108. package/fesm2022/cute-widgets-base-input.mjs +726 -0
  109. package/fesm2022/cute-widgets-base-input.mjs.map +1 -0
  110. package/fesm2022/cute-widgets-base-layout-container.mjs +95 -0
  111. package/fesm2022/cute-widgets-base-layout-container.mjs.map +1 -0
  112. package/fesm2022/cute-widgets-base-layout-stack.mjs +166 -0
  113. package/fesm2022/cute-widgets-base-layout-stack.mjs.map +1 -0
  114. package/fesm2022/cute-widgets-base-layout.mjs +250 -0
  115. package/fesm2022/cute-widgets-base-layout.mjs.map +1 -0
  116. package/fesm2022/cute-widgets-base-list.mjs +1557 -0
  117. package/fesm2022/cute-widgets-base-list.mjs.map +1 -0
  118. package/fesm2022/cute-widgets-base-menu.mjs +1283 -0
  119. package/fesm2022/cute-widgets-base-menu.mjs.map +1 -0
  120. package/fesm2022/cute-widgets-base-navbar.mjs +359 -0
  121. package/fesm2022/cute-widgets-base-navbar.mjs.map +1 -0
  122. package/fesm2022/cute-widgets-base-paginator.mjs +485 -0
  123. package/fesm2022/cute-widgets-base-paginator.mjs.map +1 -0
  124. package/fesm2022/cute-widgets-base-progress.mjs +321 -0
  125. package/fesm2022/cute-widgets-base-progress.mjs.map +1 -0
  126. package/fesm2022/cute-widgets-base-radio.mjs +637 -0
  127. package/fesm2022/cute-widgets-base-radio.mjs.map +1 -0
  128. package/fesm2022/cute-widgets-base-select.mjs +1208 -0
  129. package/fesm2022/cute-widgets-base-select.mjs.map +1 -0
  130. package/fesm2022/cute-widgets-base-sidenav.mjs +1095 -0
  131. package/fesm2022/cute-widgets-base-sidenav.mjs.map +1 -0
  132. package/fesm2022/cute-widgets-base-slider.mjs +99 -0
  133. package/fesm2022/cute-widgets-base-slider.mjs.map +1 -0
  134. package/fesm2022/cute-widgets-base-snack-bar.mjs +897 -0
  135. package/fesm2022/cute-widgets-base-snack-bar.mjs.map +1 -0
  136. package/fesm2022/cute-widgets-base-sort.mjs +639 -0
  137. package/fesm2022/cute-widgets-base-sort.mjs.map +1 -0
  138. package/fesm2022/cute-widgets-base-spinner.mjs +154 -0
  139. package/fesm2022/cute-widgets-base-spinner.mjs.map +1 -0
  140. package/fesm2022/cute-widgets-base-stepper.mjs +673 -0
  141. package/fesm2022/cute-widgets-base-stepper.mjs.map +1 -0
  142. package/fesm2022/cute-widgets-base-table.mjs +1023 -0
  143. package/fesm2022/cute-widgets-base-table.mjs.map +1 -0
  144. package/fesm2022/cute-widgets-base-tabs.mjs +729 -0
  145. package/fesm2022/cute-widgets-base-tabs.mjs.map +1 -0
  146. package/fesm2022/cute-widgets-base-timepicker.mjs +965 -0
  147. package/fesm2022/cute-widgets-base-timepicker.mjs.map +1 -0
  148. package/fesm2022/cute-widgets-base-toolbar.mjs +120 -0
  149. package/fesm2022/cute-widgets-base-toolbar.mjs.map +1 -0
  150. package/fesm2022/cute-widgets-base-tooltip.mjs +947 -0
  151. package/fesm2022/cute-widgets-base-tooltip.mjs.map +1 -0
  152. package/fesm2022/cute-widgets-base-tree.mjs +598 -0
  153. package/fesm2022/cute-widgets-base-tree.mjs.map +1 -0
  154. package/fesm2022/cute-widgets-base.mjs +68 -0
  155. package/fesm2022/cute-widgets-base.mjs.map +1 -0
  156. package/form-field/index.d.ts +401 -0
  157. package/grid-list/index.d.ts +361 -0
  158. package/icon/index.d.ts +477 -0
  159. package/index.d.ts +3 -0
  160. package/input/index.d.ts +256 -0
  161. package/layout/container/index.d.ts +31 -0
  162. package/layout/index.d.ts +78 -0
  163. package/layout/stack/index.d.ts +52 -0
  164. package/list/index.d.ts +659 -0
  165. package/menu/index.d.ts +497 -0
  166. package/navbar/index.d.ts +91 -0
  167. package/package.json +279 -0
  168. package/paginator/index.d.ts +216 -0
  169. package/progress/index.d.ts +130 -0
  170. package/radio/index.d.ts +259 -0
  171. package/select/index.d.ts +426 -0
  172. package/sidenav/index.d.ts +369 -0
  173. package/slider/index.d.ts +48 -0
  174. package/snack-bar/index.d.ts +374 -0
  175. package/sort/index.d.ts +334 -0
  176. package/spinner/index.d.ts +70 -0
  177. package/stepper/index.d.ts +295 -0
  178. package/table/index.d.ts +395 -0
  179. package/tabs/index.d.ts +307 -0
  180. package/timepicker/index.d.ts +350 -0
  181. package/toolbar/index.d.ts +36 -0
  182. package/tooltip/index.d.ts +299 -0
  183. package/tree/index.d.ts +314 -0
@@ -0,0 +1,2360 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, inject, ElementRef, numberAttribute, booleanAttribute, Input, Directive, ChangeDetectorRef, NgZone, HOST_TAG_NAME, DOCUMENT, EventEmitter, Injector, ANIMATION_MODULE_TYPE, ViewChild, ContentChild, Output, ContentChildren, ChangeDetectionStrategy, ViewEncapsulation, Component, QueryList, isDevMode, forwardRef, NgModule } from '@angular/core';
3
+ import { ENTER, SPACE, BACKSPACE, DELETE, TAB, hasModifierKey } from '@angular/cdk/keycodes';
4
+ import { Subject, merge, EMPTY } from 'rxjs';
5
+ import { CuteFocusableControl } from '@cute-widgets/base/abstract';
6
+ import { Validators, NgControl, NgForm, FormGroupDirective, NG_VALUE_ACCESSOR } from '@angular/forms';
7
+ import { ErrorStateMatcher, _ErrorStateTracker } from '@cute-widgets/base/core/error';
8
+ import { CuteFormFieldControl, CUTE_FORM_FIELD } from '@cute-widgets/base/form-field';
9
+ import { takeUntil, startWith, switchMap } from 'rxjs/operators';
10
+ import { FocusKeyManager } from '@angular/cdk/a11y';
11
+ import { Directionality } from '@angular/cdk/bidi';
12
+ import { CuteButton } from '@cute-widgets/base/button';
13
+ import { CommonModule } from '@angular/common';
14
+
15
+ /**
16
+ * @license Apache-2.0
17
+ *
18
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
19
+ *
20
+ * You may not use this file except in compliance with the License
21
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
22
+ *
23
+ * This code is a modification of the `@angular/material` original
24
+ * code licensed under MIT-style License (https://angular.dev/license).
25
+ */
26
+ /** Injection token to be used to override the default options for the chips module. */
27
+ const CUTE_CHIPS_DEFAULT_OPTIONS = new InjectionToken('cute-chips-default-options', {
28
+ providedIn: 'root',
29
+ factory: () => ({
30
+ separatorKeyCodes: [ENTER],
31
+ }),
32
+ });
33
+ /**
34
+ * Injection token that can be used to reference instances of `CuteChipAvatar`. It serves as
35
+ * an alternative token to the actual `CuteChipAvatar` class which could cause unnecessary
36
+ * retention of the class and its directive metadata.
37
+ */
38
+ const CUTE_CHIP_AVATAR = new InjectionToken('CuteChipAvatar');
39
+ /**
40
+ * Injection token that can be used to reference instances of `CuteChipTrailingIcon`. It serves as
41
+ * an alternative token to the actual `CuteChipTrailingIcon` class, which could cause unnecessary
42
+ * retention of the class and its directive metadata.
43
+ */
44
+ const CUTE_CHIP_TRAILING_ICON = new InjectionToken('CuteChipTrailingIcon');
45
+ /**
46
+ * Injection token that can be used to reference instances of `CuteChipEdit`. It serves as
47
+ * alternative token to the actual `CuteChipEdit` class which could cause unnecessary
48
+ * retention of the class and its directive metadata.
49
+ */
50
+ const CUTE_CHIP_EDIT = new InjectionToken('CuteChipEdit');
51
+ /**
52
+ * Injection token that can be used to reference instances of `CuteChipRemove`. It serves as
53
+ * an alternative token to the actual `CuteChipRemove` class, which could cause unnecessary
54
+ * retention of the class and its directive metadata.
55
+ */
56
+ const CUTE_CHIP_REMOVE = new InjectionToken('CuteChipRemove');
57
+ /**
58
+ * Injection token used to avoid a circular dependency between the `CuteChip` and `CuteChipAction`.
59
+ */
60
+ const CUTE_CHIP = new InjectionToken('CuteChip');
61
+
62
+ /**
63
+ * @license Apache-2.0
64
+ *
65
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
66
+ *
67
+ * You may not use this file except in compliance with the License
68
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
69
+ *
70
+ * This code is a modification of the `@angular/material` original
71
+ * code licensed under MIT-style License (https://angular.dev/license).
72
+ */
73
+ /**
74
+ * Section within a chip.
75
+ * @docs-private
76
+ */
77
+ class CuteChipAction {
78
+ /** Whether the action is disabled. */
79
+ get disabled() { return this._disabled || this._parentChip.disabled; }
80
+ set disabled(value) { this._disabled = value; }
81
+ /**
82
+ * Determine the value of the disabled attribute for this chip action.
83
+ */
84
+ _getDisabledAttribute() {
85
+ // When this chip action is disabled and focusing disabled chips is not permitted, return empty
86
+ // string to indicate that disabled attribute should be included.
87
+ return this.disabled && !this._allowFocusWhenDisabled ? '' : null;
88
+ }
89
+ /**
90
+ * Determine the value of the tabindex attribute for this chip action.
91
+ */
92
+ _getTabindex() {
93
+ return (this.disabled && !this._allowFocusWhenDisabled) || !this.isInteractive
94
+ ? null
95
+ : this.tabIndex.toString();
96
+ }
97
+ constructor() {
98
+ this._elementRef = inject(ElementRef);
99
+ this._parentChip = inject(CUTE_CHIP);
100
+ /** Whether the action is interactive. */
101
+ this.isInteractive = true;
102
+ /** Whether this is the primary action in the chip. */
103
+ this._isPrimary = true;
104
+ /** Whether this is the leading action in the chip. */
105
+ this._isLeading = false; // TODO(adolgachev): consolidate usage to secondary css class
106
+ this._disabled = false;
107
+ /** Tab index of the action. */
108
+ this.tabIndex = -1;
109
+ /**
110
+ * Private API to allow focusing this chip when it is disabled.
111
+ */
112
+ this._allowFocusWhenDisabled = false;
113
+ if (this._elementRef.nativeElement.nodeName === 'BUTTON') {
114
+ this._elementRef.nativeElement.setAttribute('type', 'button');
115
+ }
116
+ }
117
+ focus() {
118
+ this._elementRef.nativeElement.focus();
119
+ }
120
+ _handleClick(event) {
121
+ if (!this.disabled && this.isInteractive && this._isPrimary) {
122
+ event.preventDefault();
123
+ this._parentChip._handlePrimaryActionInteraction();
124
+ }
125
+ }
126
+ _handleKeydown(event) {
127
+ if ((event.keyCode === ENTER || event.keyCode === SPACE) &&
128
+ !this.disabled &&
129
+ this.isInteractive &&
130
+ this._isPrimary &&
131
+ !this._parentChip._isEditing) {
132
+ event.preventDefault();
133
+ this._parentChip._handlePrimaryActionInteraction();
134
+ }
135
+ }
136
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipAction, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
137
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.15", type: CuteChipAction, isStandalone: true, selector: "[cuteChipAction]", inputs: { isInteractive: "isInteractive", disabled: ["disabled", "disabled", booleanAttribute], tabIndex: ["tabIndex", "tabIndex", (value) => (value == null ? -1 : numberAttribute(value))], _allowFocusWhenDisabled: "_allowFocusWhenDisabled" }, host: { listeners: { "click": "_handleClick($event)", "keydown": "_handleKeydown($event)" }, properties: { "class.cute-chip__action--primary": "_isPrimary", "class.cute-chip__action--presentational": "!isInteractive", "class.cute-chip__action--secondary": "!_isPrimary", "class.cute-chip__action--trailing": "!_isPrimary && !_isLeading", "attr.tabindex": "_getTabindex()", "attr.disabled": "_getDisabledAttribute()", "attr.aria-disabled": "disabled" }, classAttribute: "cute-chip__action cute-chip-action" }, ngImport: i0 }); }
138
+ }
139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipAction, decorators: [{
140
+ type: Directive,
141
+ args: [{
142
+ selector: '[cuteChipAction]',
143
+ host: {
144
+ 'class': 'cute-chip__action cute-chip-action',
145
+ '[class.cute-chip__action--primary]': '_isPrimary',
146
+ '[class.cute-chip__action--presentational]': '!isInteractive',
147
+ '[class.cute-chip__action--secondary]': '!_isPrimary',
148
+ '[class.cute-chip__action--trailing]': '!_isPrimary && !_isLeading',
149
+ '[attr.tabindex]': '_getTabindex()',
150
+ '[attr.disabled]': '_getDisabledAttribute()',
151
+ '[attr.aria-disabled]': 'disabled',
152
+ '(click)': '_handleClick($event)',
153
+ '(keydown)': '_handleKeydown($event)',
154
+ },
155
+ standalone: true,
156
+ }]
157
+ }], ctorParameters: () => [], propDecorators: { isInteractive: [{
158
+ type: Input
159
+ }], disabled: [{
160
+ type: Input,
161
+ args: [{ transform: booleanAttribute }]
162
+ }], tabIndex: [{
163
+ type: Input,
164
+ args: [{
165
+ transform: (value) => (value == null ? -1 : numberAttribute(value)),
166
+ }]
167
+ }], _allowFocusWhenDisabled: [{
168
+ type: Input
169
+ }] } });
170
+
171
+ /**
172
+ * @license Apache-2.0
173
+ *
174
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
175
+ *
176
+ * You may not use this file except in compliance with the License
177
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
178
+ *
179
+ * This code is a modification of the `@angular/material` original
180
+ * code licensed under MIT-style License (https://angular.dev/license).
181
+ */
182
+ let uid = 0;
183
+ /**
184
+ * A Chip base component used inside the `CuteChipSet` component.
185
+ * Extended by `CuteChipOption` and `CuteChipRow` for different interaction patterns.
186
+ */
187
+ class CuteChip extends CuteFocusableControl {
188
+ _hasFocus() {
189
+ return this._hasFocusInternal;
190
+ }
191
+ /** A unique id for the chip. If none is supplied, it will be auto-generated. */
192
+ generateId() {
193
+ return `cute-chip-${uid++}`;
194
+ }
195
+ /**
196
+ * The value of the chip. Defaults to the content inside
197
+ * the `cute-chip-action-label` element.
198
+ */
199
+ get value() {
200
+ return this._value !== undefined ? this._value : this._textElement?.textContent.trim();
201
+ }
202
+ set value(value) {
203
+ this._value = value;
204
+ }
205
+ /**
206
+ * Handles the lazy creation of the CuteChip ripple.
207
+ * Used to improve initial load time of large applications.
208
+ */
209
+ //_rippleLoader: MatRippleLoader = inject(MatRippleLoader);
210
+ getDisabledState() {
211
+ return super.getDisabledState() || this._chipListDisabled;
212
+ }
213
+ constructor() {
214
+ super();
215
+ this._changeDetectorRef = inject(ChangeDetectorRef);
216
+ this._ngZone = inject(NgZone);
217
+ this._tagName = inject(HOST_TAG_NAME);
218
+ //private _globalRippleOptions = inject<RippleGlobalOptions>(MAT_RIPPLE_GLOBAL_OPTIONS, {
219
+ // optional: true,
220
+ //});
221
+ this._document = inject(DOCUMENT);
222
+ /** Emits when the chip is focused. */
223
+ this._onFocus = new Subject();
224
+ /** Emits when the chip is blurred. */
225
+ this._onBlur = new Subject();
226
+ /** Whether the chip has focus. */
227
+ this._hasFocusInternal = false;
228
+ /** The `id` of a span that contains this chip's aria description. */
229
+ this._ariaDescriptionId = `${this.id}-aria-description`;
230
+ /** Whether the chip list is disabled. */
231
+ this._chipListDisabled = false;
232
+ /** Whether the chip was focused when it was removed. */
233
+ this._hadFocusOnRemove = false;
234
+ /**
235
+ * Determines whether the chip displays the remove styling and emits (removed) events.
236
+ */
237
+ this.removable = true;
238
+ /**
239
+ * Colors the chip for emphasis as if it were selected.
240
+ */
241
+ this.highlighted = false;
242
+ /** Whether the ripple effect is disabled or not. */
243
+ this.disableRipple = false;
244
+ /** Emitted when a chip is to be removed. */
245
+ this.removed = new EventEmitter();
246
+ /** Emitted when the chip is destroyed. */
247
+ this.destroyed = new EventEmitter();
248
+ /** The unstyled chip selector for this component. */
249
+ this.basicChipAttrName = 'cute-basic-chip';
250
+ this._injector = inject(Injector);
251
+ const animationMode = inject(ANIMATION_MODULE_TYPE, { optional: true });
252
+ this._animationsDisabled = animationMode === 'NoopAnimations';
253
+ const tabIndex = this.getAttribute("tabindex");
254
+ if (tabIndex) {
255
+ this.tabIndex = parseInt(tabIndex) ?? -1;
256
+ }
257
+ else {
258
+ this.tabIndex = undefined;
259
+ }
260
+ this._monitorFocus();
261
+ }
262
+ ngOnInit() {
263
+ super.ngOnInit();
264
+ // This check needs to happen in `ngOnInit` so the overridden value of
265
+ // `basicChipAttrName` coming from base classes can be picked up.
266
+ const element = this._elementRef.nativeElement;
267
+ this._isBasicChip =
268
+ element.hasAttribute(this.basicChipAttrName) ||
269
+ element.tagName.toLowerCase() === this.basicChipAttrName;
270
+ this._isStandardStaticChip = !this._isBasicChip &&
271
+ (element.tagName.toLowerCase() === "cute-chip" ||
272
+ element.tagName.toLowerCase() === "cute-chip-row");
273
+ }
274
+ ngAfterViewInit() {
275
+ super.ngAfterViewInit();
276
+ this._textElement = this._elementRef.nativeElement.querySelector('.cute-chip-action-label');
277
+ if (this._pendingFocus) {
278
+ this._pendingFocus = false;
279
+ this.focus();
280
+ }
281
+ }
282
+ ngAfterContentInit() {
283
+ super.ngAfterContentInit();
284
+ // Since the styling depends on the presence of some
285
+ // actions, we have to mark for check on changes.
286
+ this._actionChanges = merge(this._allLeadingIcons?.changes, this._allTrailingIcons?.changes, this._allEditIcons?.changes, this._allRemoveIcons?.changes).subscribe(() => this._changeDetectorRef.markForCheck());
287
+ }
288
+ ngDoCheck() {
289
+ //this._rippleLoader.setDisabled(this._elementRef.nativeElement, this._isRippleDisabled());
290
+ }
291
+ ngOnDestroy() {
292
+ super.ngOnDestroy();
293
+ this._actionChanges?.unsubscribe();
294
+ this.destroyed.emit({ chip: this });
295
+ this.destroyed.complete();
296
+ }
297
+ /**
298
+ * Allows for programmatic removal of the chip.
299
+ *
300
+ * Informs any listeners of the removal request. Does not remove the chip from the DOM.
301
+ */
302
+ remove() {
303
+ if (this.removable) {
304
+ this._hadFocusOnRemove = this._hasFocus();
305
+ this.removed.emit({ chip: this });
306
+ }
307
+ }
308
+ /** Whether the ripple should be disabled. */
309
+ /*
310
+ _isRippleDisabled(): boolean {
311
+ return (
312
+ this.disabled ||
313
+ this.disableRipple ||
314
+ this._animationsDisabled ||
315
+ this._isBasicChip ||
316
+ !!this._globalRippleOptions?.disabled
317
+ );
318
+ }
319
+ */
320
+ /** Returns whether the chip has a trailing icon. */
321
+ _hasTrailingIcon() {
322
+ return !!(this.trailingIcon || this.removeIcon);
323
+ }
324
+ /** Handles keyboard events on the chip. */
325
+ _handleKeydown(event) {
326
+ // Ignore backspace events where the user is holding down the key
327
+ // so that we don't accidentally remove too many chips.
328
+ if ((event.keyCode === BACKSPACE && !event.repeat) || event.keyCode === DELETE) {
329
+ event.preventDefault();
330
+ this.remove();
331
+ }
332
+ }
333
+ /** Allows for programmatic focusing of the chip. */
334
+ focus() {
335
+ super.focus();
336
+ if (!this.disabled) {
337
+ // If `focus` is called before `ngAfterViewInit`, we won't have access to the primary action.
338
+ // This can happen if the consumer tries to focus a chip immediately after it is added.
339
+ // Queue the method to be called again on init.
340
+ if (this.primaryAction) {
341
+ this.primaryAction.focus();
342
+ }
343
+ else {
344
+ this._pendingFocus = true;
345
+ }
346
+ }
347
+ }
348
+ /** Gets the action that contains a specific target node. */
349
+ _getSourceAction(target) {
350
+ return this._getActions().find(action => {
351
+ const element = action._elementRef.nativeElement;
352
+ return element === target || element.contains(target);
353
+ });
354
+ }
355
+ /** Gets all the actions within the chip. */
356
+ _getActions() {
357
+ const result = [];
358
+ if (this.editIcon) {
359
+ result.push(this.editIcon);
360
+ }
361
+ if (this.primaryAction) {
362
+ result.push(this.primaryAction);
363
+ }
364
+ if (this.removeIcon) {
365
+ result.push(this.removeIcon);
366
+ }
367
+ if (this.trailingIcon) {
368
+ result.push(this.trailingIcon);
369
+ }
370
+ return result;
371
+ }
372
+ /** Handles interactions with the primary action of the chip. */
373
+ _handlePrimaryActionInteraction() {
374
+ // Empty here, but is overwritten in child classes.
375
+ }
376
+ /** Handles interactions with the edit action of the chip. */
377
+ _edit(event) {
378
+ // Empty here, but is overwritten in child classes.
379
+ }
380
+ /** Gets the tabindex of the chip. */
381
+ _getTabIndex() {
382
+ if (!this.role) {
383
+ return null;
384
+ }
385
+ return this.disabled ? -1 : this.tabIndex;
386
+ }
387
+ /** Starts the focus monitoring process on the chip. */
388
+ _monitorFocus() {
389
+ this._focusMonitor.monitor(this._elementRef, true).subscribe(origin => {
390
+ const hasFocus = origin !== null;
391
+ if (hasFocus !== this._hasFocusInternal) {
392
+ this._hasFocusInternal = hasFocus;
393
+ if (hasFocus) {
394
+ this._onFocus.next({ chip: this });
395
+ }
396
+ else {
397
+ // When animations are enabled, Angular may end up removing the chip from the DOM a little
398
+ // earlier than usual, causing it to be blurred and throwing off the logic in the chip list
399
+ // that moves focus not the next item. To work around the issue, we defer marking the chip
400
+ // as not focused until after the next render.
401
+ this.markForCheck();
402
+ setTimeout(() => this._ngZone.run(() => this._onBlur.next({ chip: this })));
403
+ }
404
+ }
405
+ });
406
+ }
407
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChip, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
408
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: CuteChip, isStandalone: true, selector: "cute-basic-chip, [cute-basic-chip], cute-chip, [cute-chip]", inputs: { value: "value", removable: ["removable", "removable", booleanAttribute], highlighted: ["highlighted", "highlighted", booleanAttribute], disableRipple: ["disableRipple", "disableRipple", booleanAttribute] }, outputs: { removed: "removed", destroyed: "destroyed" }, host: { listeners: { "keydown": "_handleKeydown($event)" }, properties: { "class.btn": "_isStandardStaticChip", "class.btn-sm": "_isStandardStaticChip", "class.border": "_isStandardStaticChip", "class.rounded-pill": "_isStandardStaticChip", "class.cute-static-chip": "_isStandardStaticChip", "class.cute-chip-with-avatar": "leadingIcon", "class.cute-chip-highlighted": "highlighted", "class.disabled": "_isStandardStaticChip && disabled", "class.cute-basic-chip": "_isBasicChip", "class.cute-standard-chip": "!_isBasicChip", "class.cute-chip-with-trailing-icon": "_hasTrailingIcon()", "class._cute-animation-noopable": "_animationsDisabled", "id": "id", "attr.role": "role", "attr.tabindex": "_getTabIndex()", "attr.aria-label": "ariaLabel" }, classAttribute: "cute-chip" }, providers: [{ provide: CUTE_CHIP, useExisting: CuteChip }], queries: [{ propertyName: "leadingIcon", first: true, predicate: CUTE_CHIP_AVATAR, descendants: true }, { propertyName: "editIcon", first: true, predicate: CUTE_CHIP_EDIT, descendants: true }, { propertyName: "trailingIcon", first: true, predicate: CUTE_CHIP_TRAILING_ICON, descendants: true }, { propertyName: "removeIcon", first: true, predicate: CUTE_CHIP_REMOVE, descendants: true }, { propertyName: "_allLeadingIcons", predicate: CUTE_CHIP_AVATAR, descendants: true }, { propertyName: "_allTrailingIcons", predicate: CUTE_CHIP_TRAILING_ICON, descendants: true }, { propertyName: "_allEditIcons", predicate: CUTE_CHIP_EDIT, descendants: true }, { propertyName: "_allRemoveIcons", predicate: CUTE_CHIP_REMOVE, descendants: true }], viewQueries: [{ propertyName: "primaryAction", first: true, predicate: CuteChipAction, descendants: true }], exportAs: ["cuteChip"], usesInheritance: true, ngImport: i0, template: "<span class=\"cute-chip-focus-overlay\"></span>\r\n\r\n<span class=\"cute-chip__cell cute-chip__cell--primary\">\r\n <span cuteChipAction [isInteractive]=\"false\">\r\n @if (leadingIcon) {\r\n <span class=\"cute-chip__graphic cute-chip-graphic\">\r\n <ng-content select=\"cute-avatar, cute-chip-avatar, [cuteChipAvatar]\"></ng-content>\r\n </span>\r\n }\r\n <span class=\"cute-chip__text-label cute-chip-action-label\">\r\n <ng-content></ng-content>\r\n <span class=\"cute-chip-primary-focus-indicator cute-focus-indicator\"></span>\r\n </span>\r\n </span>\r\n</span>\r\n\r\n@if (_hasTrailingIcon()) {\r\n <span class=\"cute-chip__cell cute-chip__cell--trailing\">\r\n <ng-content select=\"cute-chip-trailing-icon,[cuteChipRemove],[cuteChipTrailingIcon]\"></ng-content>\r\n </span>\r\n}\r\n", styles: [".cute-chip,.cute-chip-option,cute-chip-row{position:relative;display:inline-flex;align-items:center}.cute-chip.cute-static-chip,.cute-chip-option.cute-static-chip,cute-chip-row.cute-static-chip{--bs-btn-bg: rgba(var(--bs-body-color-rgb), .06);cursor:auto}.cute-chip:hover,.cute-chip-option:hover,cute-chip-row:hover{--bs-btn-hover-bg: rgba(var(--bs-body-color-rgb), .1)}.cute-chip:active,.cute-chip-option:active,cute-chip-row:active{--bs-btn-active-bg: rgba(var(--bs-body-color-rgb), .14)}.cute-chip__cell [cuteChipAction],.cute-chip__cell .cute-chip-action{display:inline-flex;align-items:center;cursor:pointer;outline:none}.cute-chip__cell [cuteChipAction].cute-chip__action--presentational,.cute-chip__cell .cute-chip-action.cute-chip__action--presentational{cursor:auto}.cute-chip__cell [cuteChipAction]:not(button),.cute-chip__cell .cute-chip-action:not(button){gap:.5rem}.cute-chip__cell [cuteChipAction] .cute-chip__graphic,.cute-chip__cell .cute-chip-action .cute-chip__graphic{align-items:center;display:inline-flex;justify-content:center;overflow:hidden;pointer-events:none;position:relative}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark{padding-left:2px;padding-right:4px}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{width:1.2rem}[dir=rtl] .cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,[dir=rtl] .cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{transform:rotateY(180deg)}.cute-chip__cell [cuteChipAction].disabled,.cute-chip__cell .cute-chip-action.disabled{cursor:auto}.cute-chip__cell [cuteChipAction].cute-chip__icon--trailing,.cute-chip__cell .cute-chip-action.cute-chip__icon--trailing{padding-left:4px;padding-right:4px;border:none;background:none}.cute-standard-chip{-webkit-tap-highlight-color:transparent}@media (forced-colors: active){.cute-standard-chip{outline:solid 1px}.cute-standard-chip .cute-chip__checkmark-path{stroke:CanvasText!important}}.cute-standard-chip .cute-chip__icon--primary{--size: 18px;height:var(--size);width:var(--size);font-size:var(--size);border-radius:calc(var(--size) * 1.3);min-height:fit-content;background:none}.cute-standard-chip .cute-chip__cell--primary{display:flex}.cute-standard-chip .cute-chip__cell--trailing{display:inline-flex;background-color:transparent;padding-left:.5rem;padding-right:0}[dir=rtl] .cute-standard-chip .cute-chip__cell--trailing{padding-left:0;padding-right:.5rem}.cute-standard-chip._cute-animation-noopable,.cute-standard-chip._cute-animation-noopable .cute-chip__graphic,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark-path{transition-duration:1ms;animation-duration:1ms}.cute-chip-focus-overlay{inset:0;position:absolute;pointer-events:none;opacity:0;border-radius:inherit;transition:opacity .15s linear}._cute-animation-noopable .cute-chip-focus-overlay{transition:none}.cute-basic-chip .cute-chip-focus-overlay{display:none}.cute-chip-action-label{text-align:left;white-space:nowrap}[dir=rtl] .cute-chip-action-label{text-align:right}.cute-chip-primary-focus-indicator{position:absolute;inset:0;pointer-events:none}.cute-chip-edit-input{cursor:text;display:inline-block;color:inherit;outline:0}@media (forced-colors: active){.cute-chip-selected:not(.cute-chip-multiple){outline-width:3px}}\n"], dependencies: [{ kind: "directive", type: CuteChipAction, selector: "[cuteChipAction]", inputs: ["isInteractive", "disabled", "tabIndex", "_allowFocusWhenDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
409
+ }
410
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChip, decorators: [{
411
+ type: Component,
412
+ args: [{ selector: 'cute-basic-chip, [cute-basic-chip], cute-chip, [cute-chip]', exportAs: 'cuteChip', host: {
413
+ 'class': 'cute-chip',
414
+ '[class.btn]': '_isStandardStaticChip',
415
+ '[class.btn-sm]': '_isStandardStaticChip',
416
+ '[class.border]': '_isStandardStaticChip',
417
+ '[class.rounded-pill]': '_isStandardStaticChip',
418
+ '[class.cute-static-chip]': '_isStandardStaticChip',
419
+ /*
420
+ '[class]': '"text-bg-"+color||"tertiary"',
421
+ '[class.mdc-evolution-chip]': '!_isBasicChip',
422
+ '[class.mdc-evolution-chip--disabled]': 'disabled',
423
+ '[class.mdc-evolution-chip--with-trailing-action]': '_hasTrailingIcon()',
424
+ '[class.mdc-evolution-chip--with-primary-graphic]': 'leadingIcon',
425
+ '[class.mdc-evolution-chip--with-primary-icon]': 'leadingIcon',
426
+ '[class.mdc-evolution-chip--with-avatar]': 'leadingIcon',
427
+ */
428
+ '[class.cute-chip-with-avatar]': 'leadingIcon',
429
+ '[class.cute-chip-highlighted]': 'highlighted',
430
+ '[class.disabled]': '_isStandardStaticChip && disabled',
431
+ '[class.cute-basic-chip]': '_isBasicChip',
432
+ '[class.cute-standard-chip]': '!_isBasicChip',
433
+ '[class.cute-chip-with-trailing-icon]': '_hasTrailingIcon()',
434
+ '[class._cute-animation-noopable]': '_animationsDisabled',
435
+ '[id]': 'id',
436
+ '[attr.role]': 'role',
437
+ '[attr.tabindex]': '_getTabIndex()',
438
+ '[attr.aria-label]': 'ariaLabel',
439
+ '(keydown)': '_handleKeydown($event)',
440
+ }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: CUTE_CHIP, useExisting: CuteChip }], imports: [CuteChipAction], template: "<span class=\"cute-chip-focus-overlay\"></span>\r\n\r\n<span class=\"cute-chip__cell cute-chip__cell--primary\">\r\n <span cuteChipAction [isInteractive]=\"false\">\r\n @if (leadingIcon) {\r\n <span class=\"cute-chip__graphic cute-chip-graphic\">\r\n <ng-content select=\"cute-avatar, cute-chip-avatar, [cuteChipAvatar]\"></ng-content>\r\n </span>\r\n }\r\n <span class=\"cute-chip__text-label cute-chip-action-label\">\r\n <ng-content></ng-content>\r\n <span class=\"cute-chip-primary-focus-indicator cute-focus-indicator\"></span>\r\n </span>\r\n </span>\r\n</span>\r\n\r\n@if (_hasTrailingIcon()) {\r\n <span class=\"cute-chip__cell cute-chip__cell--trailing\">\r\n <ng-content select=\"cute-chip-trailing-icon,[cuteChipRemove],[cuteChipTrailingIcon]\"></ng-content>\r\n </span>\r\n}\r\n", styles: [".cute-chip,.cute-chip-option,cute-chip-row{position:relative;display:inline-flex;align-items:center}.cute-chip.cute-static-chip,.cute-chip-option.cute-static-chip,cute-chip-row.cute-static-chip{--bs-btn-bg: rgba(var(--bs-body-color-rgb), .06);cursor:auto}.cute-chip:hover,.cute-chip-option:hover,cute-chip-row:hover{--bs-btn-hover-bg: rgba(var(--bs-body-color-rgb), .1)}.cute-chip:active,.cute-chip-option:active,cute-chip-row:active{--bs-btn-active-bg: rgba(var(--bs-body-color-rgb), .14)}.cute-chip__cell [cuteChipAction],.cute-chip__cell .cute-chip-action{display:inline-flex;align-items:center;cursor:pointer;outline:none}.cute-chip__cell [cuteChipAction].cute-chip__action--presentational,.cute-chip__cell .cute-chip-action.cute-chip__action--presentational{cursor:auto}.cute-chip__cell [cuteChipAction]:not(button),.cute-chip__cell .cute-chip-action:not(button){gap:.5rem}.cute-chip__cell [cuteChipAction] .cute-chip__graphic,.cute-chip__cell .cute-chip-action .cute-chip__graphic{align-items:center;display:inline-flex;justify-content:center;overflow:hidden;pointer-events:none;position:relative}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark{padding-left:2px;padding-right:4px}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{width:1.2rem}[dir=rtl] .cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,[dir=rtl] .cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{transform:rotateY(180deg)}.cute-chip__cell [cuteChipAction].disabled,.cute-chip__cell .cute-chip-action.disabled{cursor:auto}.cute-chip__cell [cuteChipAction].cute-chip__icon--trailing,.cute-chip__cell .cute-chip-action.cute-chip__icon--trailing{padding-left:4px;padding-right:4px;border:none;background:none}.cute-standard-chip{-webkit-tap-highlight-color:transparent}@media (forced-colors: active){.cute-standard-chip{outline:solid 1px}.cute-standard-chip .cute-chip__checkmark-path{stroke:CanvasText!important}}.cute-standard-chip .cute-chip__icon--primary{--size: 18px;height:var(--size);width:var(--size);font-size:var(--size);border-radius:calc(var(--size) * 1.3);min-height:fit-content;background:none}.cute-standard-chip .cute-chip__cell--primary{display:flex}.cute-standard-chip .cute-chip__cell--trailing{display:inline-flex;background-color:transparent;padding-left:.5rem;padding-right:0}[dir=rtl] .cute-standard-chip .cute-chip__cell--trailing{padding-left:0;padding-right:.5rem}.cute-standard-chip._cute-animation-noopable,.cute-standard-chip._cute-animation-noopable .cute-chip__graphic,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark-path{transition-duration:1ms;animation-duration:1ms}.cute-chip-focus-overlay{inset:0;position:absolute;pointer-events:none;opacity:0;border-radius:inherit;transition:opacity .15s linear}._cute-animation-noopable .cute-chip-focus-overlay{transition:none}.cute-basic-chip .cute-chip-focus-overlay{display:none}.cute-chip-action-label{text-align:left;white-space:nowrap}[dir=rtl] .cute-chip-action-label{text-align:right}.cute-chip-primary-focus-indicator{position:absolute;inset:0;pointer-events:none}.cute-chip-edit-input{cursor:text;display:inline-block;color:inherit;outline:0}@media (forced-colors: active){.cute-chip-selected:not(.cute-chip-multiple){outline-width:3px}}\n"] }]
441
+ }], ctorParameters: () => [], propDecorators: { _allLeadingIcons: [{
442
+ type: ContentChildren,
443
+ args: [CUTE_CHIP_AVATAR, { descendants: true }]
444
+ }], _allTrailingIcons: [{
445
+ type: ContentChildren,
446
+ args: [CUTE_CHIP_TRAILING_ICON, { descendants: true }]
447
+ }], _allEditIcons: [{
448
+ type: ContentChildren,
449
+ args: [CUTE_CHIP_EDIT, { descendants: true }]
450
+ }], _allRemoveIcons: [{
451
+ type: ContentChildren,
452
+ args: [CUTE_CHIP_REMOVE, { descendants: true }]
453
+ }], value: [{
454
+ type: Input
455
+ }], removable: [{
456
+ type: Input,
457
+ args: [{ transform: booleanAttribute }]
458
+ }], highlighted: [{
459
+ type: Input,
460
+ args: [{ transform: booleanAttribute }]
461
+ }], disableRipple: [{
462
+ type: Input,
463
+ args: [{ transform: booleanAttribute }]
464
+ }], removed: [{
465
+ type: Output
466
+ }], destroyed: [{
467
+ type: Output
468
+ }], leadingIcon: [{
469
+ type: ContentChild,
470
+ args: [CUTE_CHIP_AVATAR]
471
+ }], editIcon: [{
472
+ type: ContentChild,
473
+ args: [CUTE_CHIP_EDIT]
474
+ }], trailingIcon: [{
475
+ type: ContentChild,
476
+ args: [CUTE_CHIP_TRAILING_ICON]
477
+ }], removeIcon: [{
478
+ type: ContentChild,
479
+ args: [CUTE_CHIP_REMOVE]
480
+ }], primaryAction: [{
481
+ type: ViewChild,
482
+ args: [CuteChipAction]
483
+ }] } });
484
+
485
+ /**
486
+ * @license Apache-2.0
487
+ *
488
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
489
+ *
490
+ * You may not use this file except in compliance with the License
491
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
492
+ *
493
+ * This code is a modification of the `@angular/material` original
494
+ * code licensed under MIT-style License (https://angular.dev/license).
495
+ */
496
+ /**
497
+ * A directive that makes a <span> editable and exposes functions to modify and retrieve the
498
+ * element's contents.
499
+ */
500
+ class CuteChipEditInput {
501
+ constructor() {
502
+ this._elementRef = inject(ElementRef);
503
+ this._document = inject(DOCUMENT);
504
+ }
505
+ initialize(initialValue) {
506
+ this.getNativeElement().focus();
507
+ this.setValue(initialValue);
508
+ }
509
+ getNativeElement() {
510
+ return this._elementRef.nativeElement;
511
+ }
512
+ setValue(value) {
513
+ this.getNativeElement().textContent = value;
514
+ this._moveCursorToEndOfInput();
515
+ }
516
+ getValue() {
517
+ return this.getNativeElement().textContent || '';
518
+ }
519
+ _moveCursorToEndOfInput() {
520
+ const range = this._document.createRange();
521
+ range.selectNodeContents(this.getNativeElement());
522
+ range.collapse(false);
523
+ const sel = window.getSelection();
524
+ sel.removeAllRanges();
525
+ sel.addRange(range);
526
+ }
527
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipEditInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
528
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: CuteChipEditInput, isStandalone: true, selector: "span[cuteChipEditInput]", host: { attributes: { "role": "textbox", "tabindex": "-1", "contenteditable": "true" }, classAttribute: "cute-chip-edit-input" }, ngImport: i0 }); }
529
+ }
530
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipEditInput, decorators: [{
531
+ type: Directive,
532
+ args: [{
533
+ selector: 'span[cuteChipEditInput]',
534
+ host: {
535
+ 'class': 'cute-chip-edit-input',
536
+ 'role': 'textbox',
537
+ 'tabindex': '-1',
538
+ 'contenteditable': 'true',
539
+ },
540
+ standalone: true,
541
+ }]
542
+ }], ctorParameters: () => [] });
543
+
544
+ /**
545
+ * @license Apache-2.0
546
+ *
547
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
548
+ *
549
+ * You may not use this file except in compliance with the License
550
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
551
+ *
552
+ * This code is a modification of the `@angular/material` original
553
+ * code licensed under MIT-style License (https://angular.dev/license).
554
+ */
555
+ /**
556
+ * An extension of the CuteChip component used with CuteChipGrid and
557
+ * the cuteChipInputFor directive.
558
+ */
559
+ class CuteChipRow extends CuteChip {
560
+ constructor() {
561
+ super();
562
+ this.basicChipAttrName = 'cute-basic-chip-row';
563
+ /**
564
+ * The editing action has to be triggered in a timeout. While we're waiting on it, a blur
565
+ * event might occur which will interrupt the editing. This flag is used to avoid interruptions
566
+ * while the editing action is being initialized.
567
+ */
568
+ this._editStartPending = false;
569
+ this.editable = false;
570
+ /** Emitted when the chip is edited. */
571
+ this.edited = new EventEmitter();
572
+ this._isEditing = false;
573
+ this.role = 'row';
574
+ this._onBlur.pipe(takeUntil(this.destroyed)).subscribe(() => {
575
+ if (this._isEditing && !this._editStartPending) {
576
+ this._onEditFinish();
577
+ }
578
+ });
579
+ }
580
+ _hasTrailingIcon() {
581
+ // The trailing icon is hidden while editing.
582
+ return !this._isEditing && super._hasTrailingIcon();
583
+ }
584
+ /** Sends focus to the first gridcell when the user clicks anywhere inside the chip. */
585
+ _handleFocus() {
586
+ if (!this._isEditing && !this.disabled) {
587
+ this.focus();
588
+ }
589
+ }
590
+ _handleKeydown(event) {
591
+ if (event.keyCode === ENTER && !this.disabled) {
592
+ if (this._isEditing) {
593
+ event.preventDefault();
594
+ this._onEditFinish();
595
+ }
596
+ else if (this.editable) {
597
+ this._startEditing(event);
598
+ }
599
+ }
600
+ else if (this._isEditing) {
601
+ // Stop the event from reaching the chip set in order to avoid navigating.
602
+ event.stopPropagation();
603
+ }
604
+ else {
605
+ super._handleKeydown(event);
606
+ }
607
+ }
608
+ _handleDoubleclick(event) {
609
+ if (!this.disabled && this.editable) {
610
+ this._startEditing(event);
611
+ }
612
+ }
613
+ _startEditing(event) {
614
+ if (!this.primaryAction ||
615
+ (this.removeIcon && this._getSourceAction(event.target) === this.removeIcon)) {
616
+ return;
617
+ }
618
+ // The value depends on the DOM so we need to extract it before we flip the flag.
619
+ const value = this.value;
620
+ this._isEditing = this._editStartPending = true;
621
+ // Starting the editing sequence below depends on the edit input
622
+ // query resolving on time. Trigger a synchronous change detection to
623
+ // ensure that it happens by the time we hit the timeout below.
624
+ this._changeDetectorRef.detectChanges();
625
+ // TODO(crisbeto): this timeout shouldn't be necessary given the `detectChange` call above.
626
+ // Defer initializing the input so it has time to be added to the DOM.
627
+ setTimeout(() => {
628
+ this._getEditInput().initialize(value);
629
+ this._editStartPending = false;
630
+ });
631
+ }
632
+ _onEditFinish() {
633
+ this._isEditing = this._editStartPending = false;
634
+ this.edited.emit({ chip: this, value: this._getEditInput().getValue() });
635
+ // If the edit input is still focused or focus was returned to the body after it was destroyed,
636
+ // return focus to the chip contents.
637
+ if (this._document.activeElement === this._getEditInput().getNativeElement() ||
638
+ this._document.activeElement === this._document.body) {
639
+ this.primaryAction?.focus();
640
+ }
641
+ }
642
+ /*
643
+ override _isRippleDisabled(): boolean {
644
+ return super._isRippleDisabled() || this._isEditing;
645
+ }
646
+ */
647
+ /**
648
+ * Gets the projected chip edit input, or the default input if none is projected in. One of these
649
+ * two values is guaranteed to be defined.
650
+ */
651
+ _getEditInput() {
652
+ return this.contentEditInput || this.defaultEditInput;
653
+ }
654
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipRow, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
655
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: CuteChipRow, isStandalone: true, selector: "cute-chip-row, [cute-chip-row], cute-basic-chip-row, [cute-basic-chip-row]", inputs: { editable: "editable" }, outputs: { edited: "edited" }, host: { listeners: { "focus": "_handleFocus($event)", "dblclick": "_handleDoubleclick($event)" }, properties: { "class.cute-chip-with-avatar": "leadingIcon", "class.cute-chip-disabled": "disabled", "class.cute-chip-editing": "_isEditing", "class.cute-chip-editable": "editable", "class.cute-chip-highlighted": "highlighted", "class.cute-chip-with-trailing-icon": "_hasTrailingIcon()", "id": "id", "attr.tabindex": "disabled ? null : -1", "attr.aria-label": "null", "attr.aria-description": "null", "attr.role": "role" }, classAttribute: "cute-chip-row" }, providers: [
656
+ { provide: CuteChip, useExisting: CuteChipRow },
657
+ { provide: CUTE_CHIP, useExisting: CuteChipRow },
658
+ ], queries: [{ propertyName: "contentEditInput", first: true, predicate: CuteChipEditInput, descendants: true }], viewQueries: [{ propertyName: "defaultEditInput", first: true, predicate: CuteChipEditInput, descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (!_isEditing) {\r\n <span class=\"cute-chip-focus-overlay\"></span>\r\n}\r\n\r\n<span class=\"cute-chip__cell cute-chip__cell--primary\">\r\n <span class=\"cute-chip-action\" role=\"gridcell\"\r\n cuteChipAction\r\n [tabIndex]=\"tabIndex\"\r\n [disabled]=\"disabled\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"_ariaDescriptionId\">\r\n @if (leadingIcon) {\r\n <span class=\"cute-chip-graphic\">\r\n <ng-content select=\"cute-avatar, cute-chip-avatar, [cuteChipAvatar]\"></ng-content>\r\n </span>\r\n }\r\n\r\n <span class=\"cute-chip__text-label cute-chip-action-label\">\r\n @if (_isEditing) {\r\n @if (contentEditInput) {\r\n <ng-content select=\"[cuteChipEditInput]\"></ng-content>\r\n } @else {\r\n <span cuteChipEditInput></span>\r\n }\r\n } @else {\r\n <ng-content></ng-content>\r\n }\r\n\r\n <span class=\"cute-chip-primary-focus-indicator cute-focus-indicator\" aria-hidden=\"true\"></span>\r\n </span>\r\n </span>\r\n</span>\r\n\r\n@if (_hasTrailingIcon()) {\r\n <span\r\n class=\"cute-chip__cell cute-chip__cell--trailing\"\r\n role=\"gridcell\">\r\n <ng-content select=\"cute-chip-trailing-icon,[cuteChipRemove],[cuteChipTrailingIcon]\"></ng-content>\r\n </span>\r\n}\r\n\r\n<span class=\"visually-hidden\" [id]=\"_ariaDescriptionId\">{{ariaDescription}}</span>\r\n", styles: [".cute-chip,.cute-chip-option,cute-chip-row{position:relative;display:inline-flex;align-items:center}.cute-chip.cute-static-chip,.cute-chip-option.cute-static-chip,cute-chip-row.cute-static-chip{--bs-btn-bg: rgba(var(--bs-body-color-rgb), .06);cursor:auto}.cute-chip:hover,.cute-chip-option:hover,cute-chip-row:hover{--bs-btn-hover-bg: rgba(var(--bs-body-color-rgb), .1)}.cute-chip:active,.cute-chip-option:active,cute-chip-row:active{--bs-btn-active-bg: rgba(var(--bs-body-color-rgb), .14)}.cute-chip__cell [cuteChipAction],.cute-chip__cell .cute-chip-action{display:inline-flex;align-items:center;cursor:pointer;outline:none}.cute-chip__cell [cuteChipAction].cute-chip__action--presentational,.cute-chip__cell .cute-chip-action.cute-chip__action--presentational{cursor:auto}.cute-chip__cell [cuteChipAction]:not(button),.cute-chip__cell .cute-chip-action:not(button){gap:.5rem}.cute-chip__cell [cuteChipAction] .cute-chip__graphic,.cute-chip__cell .cute-chip-action .cute-chip__graphic{align-items:center;display:inline-flex;justify-content:center;overflow:hidden;pointer-events:none;position:relative}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark{padding-left:2px;padding-right:4px}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{width:1.2rem}[dir=rtl] .cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,[dir=rtl] .cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{transform:rotateY(180deg)}.cute-chip__cell [cuteChipAction].disabled,.cute-chip__cell .cute-chip-action.disabled{cursor:auto}.cute-chip__cell [cuteChipAction].cute-chip__icon--trailing,.cute-chip__cell .cute-chip-action.cute-chip__icon--trailing{padding-left:4px;padding-right:4px;border:none;background:none}.cute-standard-chip{-webkit-tap-highlight-color:transparent}@media (forced-colors: active){.cute-standard-chip{outline:solid 1px}.cute-standard-chip .cute-chip__checkmark-path{stroke:CanvasText!important}}.cute-standard-chip .cute-chip__icon--primary{--size: 18px;height:var(--size);width:var(--size);font-size:var(--size);border-radius:calc(var(--size) * 1.3);min-height:fit-content;background:none}.cute-standard-chip .cute-chip__cell--primary{display:flex}.cute-standard-chip .cute-chip__cell--trailing{display:inline-flex;background-color:transparent;padding-left:.5rem;padding-right:0}[dir=rtl] .cute-standard-chip .cute-chip__cell--trailing{padding-left:0;padding-right:.5rem}.cute-standard-chip._cute-animation-noopable,.cute-standard-chip._cute-animation-noopable .cute-chip__graphic,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark-path{transition-duration:1ms;animation-duration:1ms}.cute-chip-focus-overlay{inset:0;position:absolute;pointer-events:none;opacity:0;border-radius:inherit;transition:opacity .15s linear}._cute-animation-noopable .cute-chip-focus-overlay{transition:none}.cute-basic-chip .cute-chip-focus-overlay{display:none}.cute-chip-action-label{text-align:left;white-space:nowrap}[dir=rtl] .cute-chip-action-label{text-align:right}.cute-chip-primary-focus-indicator{position:absolute;inset:0;pointer-events:none}.cute-chip-edit-input{cursor:text;display:inline-block;color:inherit;outline:0}@media (forced-colors: active){.cute-chip-selected:not(.cute-chip-multiple){outline-width:3px}}\n"], dependencies: [{ kind: "directive", type: CuteChipAction, selector: "[cuteChipAction]", inputs: ["isInteractive", "disabled", "tabIndex", "_allowFocusWhenDisabled"] }, { kind: "directive", type: CuteChipEditInput, selector: "span[cuteChipEditInput]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
659
+ }
660
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipRow, decorators: [{
661
+ type: Component,
662
+ args: [{ selector: 'cute-chip-row, [cute-chip-row], cute-basic-chip-row, [cute-basic-chip-row]', host: {
663
+ 'class': 'cute-chip-row',
664
+ '[class.cute-chip-with-avatar]': 'leadingIcon',
665
+ '[class.cute-chip-disabled]': 'disabled',
666
+ '[class.cute-chip-editing]': '_isEditing',
667
+ '[class.cute-chip-editable]': 'editable',
668
+ '[class.cute-chip-highlighted]': 'highlighted',
669
+ '[class.cute-chip-with-trailing-icon]': '_hasTrailingIcon()',
670
+ /*
671
+ '[class.mdc-evolution-chip--disabled]': 'disabled',
672
+ '[class.mdc-evolution-chip--with-trailing-action]': '_hasTrailingIcon()',
673
+ '[class.mdc-evolution-chip--with-primary-graphic]': 'leadingIcon',
674
+ '[class.mdc-evolution-chip--with-primary-icon]': 'leadingIcon',
675
+ '[class.mdc-evolution-chip--with-avatar]': 'leadingIcon',
676
+ */
677
+ '[id]': 'id',
678
+ // Has to have a negative tabindex to capture
679
+ // focus and redirect it to the primary action.
680
+ '[attr.tabindex]': 'disabled ? null : -1',
681
+ '[attr.aria-label]': 'null',
682
+ '[attr.aria-description]': 'null',
683
+ '[attr.role]': 'role',
684
+ '(focus)': '_handleFocus($event)',
685
+ '(dblclick)': '_handleDoubleclick($event)',
686
+ }, providers: [
687
+ { provide: CuteChip, useExisting: CuteChipRow },
688
+ { provide: CUTE_CHIP, useExisting: CuteChipRow },
689
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CuteChipAction, CuteChipEditInput], template: "@if (!_isEditing) {\r\n <span class=\"cute-chip-focus-overlay\"></span>\r\n}\r\n\r\n<span class=\"cute-chip__cell cute-chip__cell--primary\">\r\n <span class=\"cute-chip-action\" role=\"gridcell\"\r\n cuteChipAction\r\n [tabIndex]=\"tabIndex\"\r\n [disabled]=\"disabled\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"_ariaDescriptionId\">\r\n @if (leadingIcon) {\r\n <span class=\"cute-chip-graphic\">\r\n <ng-content select=\"cute-avatar, cute-chip-avatar, [cuteChipAvatar]\"></ng-content>\r\n </span>\r\n }\r\n\r\n <span class=\"cute-chip__text-label cute-chip-action-label\">\r\n @if (_isEditing) {\r\n @if (contentEditInput) {\r\n <ng-content select=\"[cuteChipEditInput]\"></ng-content>\r\n } @else {\r\n <span cuteChipEditInput></span>\r\n }\r\n } @else {\r\n <ng-content></ng-content>\r\n }\r\n\r\n <span class=\"cute-chip-primary-focus-indicator cute-focus-indicator\" aria-hidden=\"true\"></span>\r\n </span>\r\n </span>\r\n</span>\r\n\r\n@if (_hasTrailingIcon()) {\r\n <span\r\n class=\"cute-chip__cell cute-chip__cell--trailing\"\r\n role=\"gridcell\">\r\n <ng-content select=\"cute-chip-trailing-icon,[cuteChipRemove],[cuteChipTrailingIcon]\"></ng-content>\r\n </span>\r\n}\r\n\r\n<span class=\"visually-hidden\" [id]=\"_ariaDescriptionId\">{{ariaDescription}}</span>\r\n", styles: [".cute-chip,.cute-chip-option,cute-chip-row{position:relative;display:inline-flex;align-items:center}.cute-chip.cute-static-chip,.cute-chip-option.cute-static-chip,cute-chip-row.cute-static-chip{--bs-btn-bg: rgba(var(--bs-body-color-rgb), .06);cursor:auto}.cute-chip:hover,.cute-chip-option:hover,cute-chip-row:hover{--bs-btn-hover-bg: rgba(var(--bs-body-color-rgb), .1)}.cute-chip:active,.cute-chip-option:active,cute-chip-row:active{--bs-btn-active-bg: rgba(var(--bs-body-color-rgb), .14)}.cute-chip__cell [cuteChipAction],.cute-chip__cell .cute-chip-action{display:inline-flex;align-items:center;cursor:pointer;outline:none}.cute-chip__cell [cuteChipAction].cute-chip__action--presentational,.cute-chip__cell .cute-chip-action.cute-chip__action--presentational{cursor:auto}.cute-chip__cell [cuteChipAction]:not(button),.cute-chip__cell .cute-chip-action:not(button){gap:.5rem}.cute-chip__cell [cuteChipAction] .cute-chip__graphic,.cute-chip__cell .cute-chip-action .cute-chip__graphic{align-items:center;display:inline-flex;justify-content:center;overflow:hidden;pointer-events:none;position:relative}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark{padding-left:2px;padding-right:4px}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{width:1.2rem}[dir=rtl] .cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,[dir=rtl] .cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{transform:rotateY(180deg)}.cute-chip__cell [cuteChipAction].disabled,.cute-chip__cell .cute-chip-action.disabled{cursor:auto}.cute-chip__cell [cuteChipAction].cute-chip__icon--trailing,.cute-chip__cell .cute-chip-action.cute-chip__icon--trailing{padding-left:4px;padding-right:4px;border:none;background:none}.cute-standard-chip{-webkit-tap-highlight-color:transparent}@media (forced-colors: active){.cute-standard-chip{outline:solid 1px}.cute-standard-chip .cute-chip__checkmark-path{stroke:CanvasText!important}}.cute-standard-chip .cute-chip__icon--primary{--size: 18px;height:var(--size);width:var(--size);font-size:var(--size);border-radius:calc(var(--size) * 1.3);min-height:fit-content;background:none}.cute-standard-chip .cute-chip__cell--primary{display:flex}.cute-standard-chip .cute-chip__cell--trailing{display:inline-flex;background-color:transparent;padding-left:.5rem;padding-right:0}[dir=rtl] .cute-standard-chip .cute-chip__cell--trailing{padding-left:0;padding-right:.5rem}.cute-standard-chip._cute-animation-noopable,.cute-standard-chip._cute-animation-noopable .cute-chip__graphic,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark-path{transition-duration:1ms;animation-duration:1ms}.cute-chip-focus-overlay{inset:0;position:absolute;pointer-events:none;opacity:0;border-radius:inherit;transition:opacity .15s linear}._cute-animation-noopable .cute-chip-focus-overlay{transition:none}.cute-basic-chip .cute-chip-focus-overlay{display:none}.cute-chip-action-label{text-align:left;white-space:nowrap}[dir=rtl] .cute-chip-action-label{text-align:right}.cute-chip-primary-focus-indicator{position:absolute;inset:0;pointer-events:none}.cute-chip-edit-input{cursor:text;display:inline-block;color:inherit;outline:0}@media (forced-colors: active){.cute-chip-selected:not(.cute-chip-multiple){outline-width:3px}}\n"] }]
690
+ }], ctorParameters: () => [], propDecorators: { editable: [{
691
+ type: Input
692
+ }], edited: [{
693
+ type: Output
694
+ }], defaultEditInput: [{
695
+ type: ViewChild,
696
+ args: [CuteChipEditInput]
697
+ }], contentEditInput: [{
698
+ type: ContentChild,
699
+ args: [CuteChipEditInput]
700
+ }] } });
701
+
702
+ /**
703
+ * @license Apache-2.0
704
+ *
705
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
706
+ *
707
+ * You may not use this file except in compliance with the License
708
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
709
+ *
710
+ * This code is a modification of the `@angular/material` original
711
+ * code licensed under MIT-style License (https://angular.dev/license).
712
+ */
713
+ /**
714
+ * Basic container component for the `CuteChip` component.
715
+ * Extended by `CuteChipListbox` and `CuteChipGrid` for different interaction patterns.
716
+ */
717
+ class CuteChipSet {
718
+ /** Combined stream of all the child chips' focus events. */
719
+ get chipFocusChanges() {
720
+ return this._getChipStream(chip => chip._onFocus);
721
+ }
722
+ /** Combined stream of all the child chips' destroy events. */
723
+ get chipDestroyedChanges() {
724
+ return this._getChipStream(chip => chip.destroyed);
725
+ }
726
+ /** Combined stream of all the child chips' remove events. */
727
+ get chipRemovedChanges() {
728
+ return this._getChipStream(chip => chip.removed);
729
+ }
730
+ /** Whether the chip set is disabled. */
731
+ get disabled() { return this._disabled; }
732
+ set disabled(value) {
733
+ this._disabled = value;
734
+ this._syncChipsState();
735
+ }
736
+ /** Whether the chip list contains chips or not. */
737
+ get empty() {
738
+ return !this._chips || this._chips.length === 0;
739
+ }
740
+ /** The ARIA role applied to the chip set. */
741
+ get role() {
742
+ if (this._explicitRole) {
743
+ return this._explicitRole;
744
+ }
745
+ return this.empty ? null : this._defaultRole;
746
+ }
747
+ set role(value) {
748
+ this._explicitRole = value;
749
+ }
750
+ /** Whether any of the chips inside this chip-set has focus. */
751
+ get focused() {
752
+ return this._hasFocusedChip();
753
+ }
754
+ constructor() {
755
+ this._elementRef = inject(ElementRef);
756
+ this._changeDetectorRef = inject(ChangeDetectorRef);
757
+ this._dir = inject(Directionality, { optional: true });
758
+ /** Index of the last destroyed chip that had focus. */
759
+ this._lastDestroyedFocusedChipIndex = null;
760
+ /** Subject that emits when the component has been destroyed. */
761
+ this._destroyed = new Subject();
762
+ /** Role to use if it hasn't been overwritten by the user. */
763
+ this._defaultRole = 'presentation';
764
+ this._disabled = false;
765
+ this._explicitRole = null;
766
+ /** Tabindex of the chip set. */
767
+ this.tabIndex = 0;
768
+ /** Flat list of all the actions contained within the chips. */
769
+ this._chipActions = new QueryList();
770
+ }
771
+ ngAfterViewInit() {
772
+ this._setUpFocusManagement();
773
+ this._trackChipSetChanges();
774
+ this._trackDestroyedFocusedChip();
775
+ }
776
+ ngOnDestroy() {
777
+ this._keyManager?.destroy();
778
+ this._chipActions.destroy();
779
+ this._destroyed.next();
780
+ this._destroyed.complete();
781
+ }
782
+ /** Checks whether any of the chips is focused. */
783
+ _hasFocusedChip() {
784
+ return (this._chips && this._chips.some(chip => chip._hasFocus())) || false;
785
+ }
786
+ /** Syncs the chip-set's state with the individual chips. */
787
+ _syncChipsState() {
788
+ if (this._chips) {
789
+ this._chips.forEach(chip => {
790
+ chip._chipListDisabled = this._disabled;
791
+ chip._changeDetectorRef.markForCheck();
792
+ });
793
+ }
794
+ }
795
+ /** The dummy method for subclasses to override. Base chip set cannot be focused. */
796
+ focus() { }
797
+ /** Handles keyboard events on the chip set. */
798
+ _handleKeydown(event) {
799
+ if (this._originatesFromChip(event)) {
800
+ this._keyManager?.onKeydown(event);
801
+ }
802
+ }
803
+ /**
804
+ * Utility to ensure all indexes are valid.
805
+ *
806
+ * @param index The index to be checked.
807
+ * @returns True if the index is valid for our list of chips.
808
+ */
809
+ _isValidIndex(index) {
810
+ if (this._chips) {
811
+ return index >= 0 && index < this._chips.length;
812
+ }
813
+ return false;
814
+ }
815
+ /**
816
+ * Removes the `tabindex` from the chip set and resets it back afterward, allowing the
817
+ * user to tab out of it. This prevents the set from capturing focus and redirecting
818
+ * it back to the first chip, creating a focus trap if its user tries to tab away.
819
+ */
820
+ _allowFocusEscape() {
821
+ const previous = this._elementRef.nativeElement.tabIndex;
822
+ if (previous !== -1) {
823
+ // Set the tabindex directly on the element, instead of going through
824
+ // the data binding, because we aren't guaranteed that change detection
825
+ // will run quickly enough to allow focus to escape.
826
+ this._elementRef.nativeElement.tabIndex = -1;
827
+ // Note that this needs to be a `setTimeout`, because a `Promise.resolve`
828
+ // doesn't allow enough time for the focus to escape.
829
+ setTimeout(() => (this._elementRef.nativeElement.tabIndex = previous));
830
+ }
831
+ }
832
+ /**
833
+ * Gets a stream of events from all the chips within the set.
834
+ * The stream will automatically incorporate any newly added chips.
835
+ */
836
+ _getChipStream(mappingFunction) {
837
+ if (this._chips) {
838
+ return this._chips.changes.pipe(startWith(null), switchMap(() => merge(...this._chips.map(mappingFunction))));
839
+ }
840
+ return EMPTY;
841
+ }
842
+ /** Checks whether an event comes from inside a chip element. */
843
+ _originatesFromChip(event) {
844
+ let currentElement = event.target;
845
+ while (currentElement && currentElement !== this._elementRef.nativeElement) {
846
+ if (currentElement.classList.contains('cute-chip')) {
847
+ return true;
848
+ }
849
+ currentElement = currentElement.parentElement;
850
+ }
851
+ return false;
852
+ }
853
+ /** Sets up the chip set's focus management logic. */
854
+ _setUpFocusManagement() {
855
+ // Create a flat `QueryList` containing the actions of all the chips.
856
+ // This allows us to navigate both within the chip and move to the next/previous
857
+ // one using the existing `ListKeyManager`.
858
+ this._chips?.changes.pipe(startWith(this._chips)).subscribe((chips) => {
859
+ const actions = [];
860
+ chips.forEach(chip => chip._getActions().forEach(action => actions.push(action)));
861
+ this._chipActions.reset(actions);
862
+ this._chipActions.notifyOnChanges();
863
+ });
864
+ this._keyManager = new FocusKeyManager(this._chipActions)
865
+ .withVerticalOrientation()
866
+ .withHorizontalOrientation(this._dir ? this._dir.value : 'ltr')
867
+ .withHomeAndEnd()
868
+ .skipPredicate(action => this._skipPredicate(action));
869
+ // Keep the manager active index in sync so that navigation picks
870
+ // up from the current chip if the user clicks into the list directly.
871
+ this.chipFocusChanges.pipe(takeUntil(this._destroyed)).subscribe(({ chip }) => {
872
+ const action = chip._getSourceAction(document.activeElement);
873
+ if (action) {
874
+ this._keyManager?.updateActiveItem(action);
875
+ }
876
+ });
877
+ this._dir?.change
878
+ .pipe(takeUntil(this._destroyed))
879
+ .subscribe(direction => this._keyManager?.withHorizontalOrientation(direction));
880
+ }
881
+ /**
882
+ * Determines if key manager should avoid putting a given chip action in the tab index. Skip
883
+ * non-interactive and disabled actions since the user can't do anything with them.
884
+ */
885
+ _skipPredicate(action) {
886
+ // Skip chips that the user cannot interact with.
887
+ // The `cute-chip-set` does not permit focusing on disabled chips.
888
+ return !action.isInteractive || action.disabled;
889
+ }
890
+ /** Listens to changes in the chip set and syncs up the state of the individual chips. */
891
+ _trackChipSetChanges() {
892
+ this._chips?.changes.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
893
+ if (this.disabled) {
894
+ // Since this happens after the content has been
895
+ // checked, we need to defer it to the next tick.
896
+ Promise.resolve().then(() => this._syncChipsState());
897
+ }
898
+ this._redirectDestroyedChipFocus();
899
+ });
900
+ }
901
+ /** Starts tracking the destroyed chips to capture the focused one. */
902
+ _trackDestroyedFocusedChip() {
903
+ this.chipDestroyedChanges.pipe(takeUntil(this._destroyed)).subscribe((event) => {
904
+ // If the focused chip is destroyed, save its index so that we can move focus to the next
905
+ // chip. We only save the index here, rather than move the focus immediately, because we want
906
+ // to wait until the chip is removed from the chip list before focusing the next one. This
907
+ // allows us to keep focus on the same index if the chip gets swapped out.
908
+ const chipArray = this._chips?.toArray() || [];
909
+ const chipIndex = chipArray.indexOf(event.chip);
910
+ const hasFocus = event.chip._hasFocus();
911
+ const wasLastFocused = event.chip._hadFocusOnRemove &&
912
+ this._keyManager?.activeItem &&
913
+ event.chip._getActions().includes(this._keyManager.activeItem);
914
+ // Note that depending on the timing, the chip might've already lost focus by the
915
+ // time we check this. We need the `wasLastFocused` as a fallback to detect such cases.
916
+ // In `wasLastFocused` we also need to ensure that the chip actually had focus when it was
917
+ // deleted so that we don't steal away the user's focus after they've moved on from the chip.
918
+ const shouldMoveFocus = hasFocus || wasLastFocused;
919
+ if (this._isValidIndex(chipIndex) && shouldMoveFocus) {
920
+ this._lastDestroyedFocusedChipIndex = chipIndex;
921
+ }
922
+ });
923
+ }
924
+ /**
925
+ * Finds the next appropriate chip to move focus to
926
+ * if the currently focused chip is destroyed.
927
+ */
928
+ _redirectDestroyedChipFocus() {
929
+ if (this._lastDestroyedFocusedChipIndex == null) {
930
+ return;
931
+ }
932
+ if (this._chips && this._chips.length) {
933
+ const newIndex = Math.min(this._lastDestroyedFocusedChipIndex, this._chips.length - 1);
934
+ const chipToFocus = this._chips.toArray()[newIndex];
935
+ if (chipToFocus.disabled) {
936
+ // If we're down to one disabled chip, move focus back to the set.
937
+ if (this._chips.length === 1) {
938
+ this.focus();
939
+ }
940
+ else {
941
+ this._keyManager?.setPreviousItemActive();
942
+ }
943
+ }
944
+ else {
945
+ chipToFocus.focus();
946
+ }
947
+ }
948
+ else {
949
+ this.focus();
950
+ }
951
+ this._lastDestroyedFocusedChipIndex = null;
952
+ }
953
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipSet, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
954
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.3.15", type: CuteChipSet, isStandalone: true, selector: "cute-chip-set", inputs: { disabled: ["disabled", "disabled", booleanAttribute], role: "role", tabIndex: ["tabIndex", "tabIndex", (value) => (value == null ? 0 : numberAttribute(value))] }, host: { listeners: { "keydown": "_handleKeydown($event)" }, properties: { "attr.role": "role" }, classAttribute: "cute-chip-set" }, queries: [{ propertyName: "_chips", predicate: CuteChip, descendants: true }], ngImport: i0, template: `
955
+ <div class="cute-chip-set__chips" role="presentation">
956
+ <ng-content></ng-content>
957
+ </div>
958
+ `, isInline: true, styles: [".cute-chip-listbox,.cute-chip-grid,.cute-chip-set{display:flex;width:100%;background-color:var(--bs-body-bg)}.cute-chip-listbox .cute-chip-set__chips,.cute-chip-grid .cute-chip-set__chips,.cute-chip-set .cute-chip-set__chips{display:flex;flex-flow:wrap;gap:.375rem;min-width:100%}.cute-form-field .cute-chip-listbox,.cute-form-field .cute-chip-grid,.cute-form-field .cute-chip-set{min-height:58px}.cute-chip-grid-focused{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.cute-chip-set-stacked .cute-chip-set__chips{flex-direction:column;align-items:flex-start}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip{display:block;width:100%}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__graphic{flex-grow:0}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip-action,.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__action--primary{flex-basis:100%;justify-content:start;width:100%}input.cute-chip-input{flex:1 0 150px;margin-left:.25rem;border:none;outline:none;background:none;transition:opacity .15s 0ms cubic-bezier(.4,0,.2,1)}input.cute-chip-input:not(:focus){opacity:.75}[dir=rtl] input.cute-chip-input{margin-left:0;margin-right:.25rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
959
+ }
960
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipSet, decorators: [{
961
+ type: Component,
962
+ args: [{ selector: 'cute-chip-set', template: `
963
+ <div class="cute-chip-set__chips" role="presentation">
964
+ <ng-content></ng-content>
965
+ </div>
966
+ `, host: {
967
+ 'class': 'cute-chip-set',
968
+ '(keydown)': '_handleKeydown($event)',
969
+ '[attr.role]': 'role',
970
+ }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [".cute-chip-listbox,.cute-chip-grid,.cute-chip-set{display:flex;width:100%;background-color:var(--bs-body-bg)}.cute-chip-listbox .cute-chip-set__chips,.cute-chip-grid .cute-chip-set__chips,.cute-chip-set .cute-chip-set__chips{display:flex;flex-flow:wrap;gap:.375rem;min-width:100%}.cute-form-field .cute-chip-listbox,.cute-form-field .cute-chip-grid,.cute-form-field .cute-chip-set{min-height:58px}.cute-chip-grid-focused{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.cute-chip-set-stacked .cute-chip-set__chips{flex-direction:column;align-items:flex-start}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip{display:block;width:100%}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__graphic{flex-grow:0}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip-action,.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__action--primary{flex-basis:100%;justify-content:start;width:100%}input.cute-chip-input{flex:1 0 150px;margin-left:.25rem;border:none;outline:none;background:none;transition:opacity .15s 0ms cubic-bezier(.4,0,.2,1)}input.cute-chip-input:not(:focus){opacity:.75}[dir=rtl] input.cute-chip-input{margin-left:0;margin-right:.25rem}\n"] }]
971
+ }], ctorParameters: () => [], propDecorators: { disabled: [{
972
+ type: Input,
973
+ args: [{ transform: booleanAttribute }]
974
+ }], role: [{
975
+ type: Input
976
+ }], tabIndex: [{
977
+ type: Input,
978
+ args: [{
979
+ transform: (value) => (value == null ? 0 : numberAttribute(value)),
980
+ }]
981
+ }], _chips: [{
982
+ type: ContentChildren,
983
+ args: [CuteChip, {
984
+ // We need to use `descendants: true`, because Ivy will no longer match
985
+ // indirect descendants if it's left as false.
986
+ descendants: true,
987
+ }]
988
+ }] } });
989
+
990
+ /**
991
+ * @license Apache-2.0
992
+ *
993
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
994
+ *
995
+ * You may not use this file except in compliance with the License
996
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
997
+ *
998
+ * This code is a modification of the `@angular/material` original
999
+ * code licensed under MIT-style License (https://angular.dev/license).
1000
+ */
1001
+ /** Change event object that is emitted when the chip grid value has changed. */
1002
+ class CuteChipGridChange {
1003
+ constructor(
1004
+ /** Chip grid that emitted the event. */
1005
+ source,
1006
+ /** Value of the chip grid when the event was emitted. */
1007
+ value) {
1008
+ this.source = source;
1009
+ this.value = value;
1010
+ }
1011
+ }
1012
+ /**
1013
+ * An extension of the CuteChipSet component used with CuteChipRow chips and
1014
+ * the cuteChipInputFor directive.
1015
+ */
1016
+ class CuteChipGrid extends CuteChipSet {
1017
+ /**
1018
+ * Implemented as part of CuteFormFieldControl.
1019
+ * @docs-private
1020
+ */
1021
+ get disabled() {
1022
+ return this.ngControl ? !!this.ngControl.disabled : this._disabled;
1023
+ }
1024
+ set disabled(value) {
1025
+ this._disabled = value;
1026
+ this._syncChipsState();
1027
+ }
1028
+ /**
1029
+ * Implemented as part of CuteFormFieldControl.
1030
+ * @docs-private
1031
+ */
1032
+ get id() {
1033
+ return this._chipInput?.id || "";
1034
+ }
1035
+ /**
1036
+ * Implemented as part of CuteFormFieldControl.
1037
+ * @docs-private
1038
+ */
1039
+ get empty() {
1040
+ return ((!this._chipInput || this._chipInput.empty) && (!this._chips || this._chips.length === 0));
1041
+ }
1042
+ /**
1043
+ * Implemented as part of CuteFormFieldControl.
1044
+ * @docs-private
1045
+ */
1046
+ get placeholder() {
1047
+ return (this._chipInput ? this._chipInput.placeholder : this._placeholder) || "";
1048
+ }
1049
+ set placeholder(value) {
1050
+ this._placeholder = value;
1051
+ this.stateChanges.next();
1052
+ }
1053
+ /** Whether any chips or the `cuteChipInput` inside this <chip-grid> has focus. */
1054
+ get focused() {
1055
+ return this._chipInput?.focused || this._hasFocusedChip();
1056
+ }
1057
+ /**
1058
+ * Implemented as part of CuteFormFieldControl.
1059
+ * @docs-private
1060
+ */
1061
+ get required() {
1062
+ return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;
1063
+ }
1064
+ set required(value) {
1065
+ this._required = value;
1066
+ this.stateChanges.next();
1067
+ }
1068
+ /**
1069
+ * Implemented as part of CuteFormFieldControl.
1070
+ * @docs-private
1071
+ */
1072
+ get shouldLabelFloat() {
1073
+ return !this.empty || this.focused;
1074
+ }
1075
+ /**
1076
+ * Implemented as part of CuteFormFieldControl.
1077
+ * @docs-private
1078
+ */
1079
+ get value() { return this._value; }
1080
+ set value(value) { this._value = value; }
1081
+ /** An object used to control when error messages are shown. */
1082
+ get errorStateMatcher() { return this._errorStateTracker.matcher; }
1083
+ set errorStateMatcher(value) {
1084
+ this._errorStateTracker.matcher = value;
1085
+ }
1086
+ /** Combined stream of all of the child chips' blur events. */
1087
+ get chipBlurChanges() {
1088
+ return this._getChipStream(chip => chip._onBlur);
1089
+ }
1090
+ /** Whether the chip grid is in an error state. */
1091
+ get errorState() { return this._errorStateTracker.errorState; }
1092
+ set errorState(value) {
1093
+ this._errorStateTracker.errorState = value;
1094
+ }
1095
+ get controlElementRef() {
1096
+ return this._elementRef;
1097
+ }
1098
+ constructor() {
1099
+ super();
1100
+ this.ngControl = inject(NgControl, { optional: true, self: true });
1101
+ /**
1102
+ * Implemented as part of CuteFormFieldControl.
1103
+ * @docs-private
1104
+ */
1105
+ this.controlType = 'cute-chip-grid';
1106
+ this._defaultRole = 'grid';
1107
+ /**
1108
+ * List of element ids to propagate to the chipInput's `aria-describedby` attribute.
1109
+ */
1110
+ this._ariaDescribedbyIds = [];
1111
+ /**
1112
+ * Function when touched. Set as part of ControlValueAccessor implementation.
1113
+ * @docs-private
1114
+ */
1115
+ this._onTouched = () => { };
1116
+ /**
1117
+ * Function when changed. Set as part of ControlValueAccessor implementation.
1118
+ * @docs-private
1119
+ */
1120
+ this._onChange = () => { };
1121
+ this._value = [];
1122
+ /** Emits when the user has changed the chip grid value. */
1123
+ this.change = new EventEmitter();
1124
+ /**
1125
+ * Emits whenever the raw value of the <chip-grid> changes. This is here primarily
1126
+ * to facilitate the two-way binding for the `value` input.
1127
+ */
1128
+ this.valueChange = new EventEmitter();
1129
+ this._chips = undefined;
1130
+ /**
1131
+ * Emits whenever the component state changes and should cause the parent
1132
+ * form-field to update. Implemented as part of `CuteFormFieldControl`.
1133
+ */
1134
+ this.stateChanges = new Subject();
1135
+ const parentForm = inject(NgForm, { optional: true });
1136
+ const parentFormGroup = inject(FormGroupDirective, { optional: true });
1137
+ const defaultErrorStateMatcher = inject(ErrorStateMatcher);
1138
+ if (this.ngControl) {
1139
+ this.ngControl.valueAccessor = this;
1140
+ }
1141
+ this._errorStateTracker = new _ErrorStateTracker(defaultErrorStateMatcher, this.ngControl, parentFormGroup, parentForm, this.stateChanges);
1142
+ }
1143
+ ngAfterContentInit() {
1144
+ this.chipBlurChanges.pipe(takeUntil(this._destroyed)).subscribe(() => {
1145
+ this._blur();
1146
+ this.stateChanges.next();
1147
+ });
1148
+ merge(this.chipFocusChanges, this._chips.changes)
1149
+ .pipe(takeUntil(this._destroyed))
1150
+ .subscribe(() => this.stateChanges.next());
1151
+ }
1152
+ ngAfterViewInit() {
1153
+ super.ngAfterViewInit();
1154
+ if (!this._chipInput && isDevMode()) {
1155
+ throw Error('cute-chip-grid must be used in combination with cuteChipInputFor.');
1156
+ }
1157
+ }
1158
+ ngDoCheck() {
1159
+ if (this.ngControl) {
1160
+ // We need to re-evaluate this on every change detection cycle, because there are some
1161
+ // error triggers that we can't subscribe to (e.g. parent form submissions). This means
1162
+ // that whatever logic is in here has to be super lean, or we risk destroying the performance.
1163
+ this.updateErrorState();
1164
+ }
1165
+ }
1166
+ ngOnDestroy() {
1167
+ super.ngOnDestroy();
1168
+ this.stateChanges.complete();
1169
+ }
1170
+ /** Associates an HTML input element with this chip grid. */
1171
+ registerInput(inputElement) {
1172
+ this._chipInput = inputElement;
1173
+ this._chipInput.setDescribedByIds(this._ariaDescribedbyIds);
1174
+ }
1175
+ /**
1176
+ * Implemented as part of CuteFormFieldControl.
1177
+ */
1178
+ onContainerClick(event) {
1179
+ if (!this.disabled && !this._originatesFromChip(event)) {
1180
+ this.focus();
1181
+ }
1182
+ }
1183
+ _toggleFocusedStyle(force) {
1184
+ if (this._elementRef.nativeElement.classList.contains("input-group-text")) {
1185
+ this._elementRef.nativeElement.classList.toggle("cute-chip-grid-focused", force);
1186
+ }
1187
+ }
1188
+ /**
1189
+ * Focuses the first chip in this chip grid, or the associated input when there
1190
+ * are no eligible chips.
1191
+ */
1192
+ focus() {
1193
+ if (this.disabled || this._chipInput?.focused) {
1194
+ return;
1195
+ }
1196
+ if (!this._chips.length || this._chips.first.disabled) {
1197
+ // Delay until the next tick, because this can cause a "changed after checked"
1198
+ // error if the input does something on focus (e.g., opens an autocomplete).
1199
+ Promise.resolve().then(() => this._chipInput?.focus());
1200
+ }
1201
+ else {
1202
+ const activeItem = this._keyManager?.activeItem;
1203
+ if (activeItem) {
1204
+ activeItem.focus();
1205
+ }
1206
+ else {
1207
+ this._keyManager?.setFirstItemActive();
1208
+ }
1209
+ }
1210
+ this.stateChanges.next();
1211
+ }
1212
+ /**
1213
+ * Implemented as part of CuteFormFieldControl.
1214
+ */
1215
+ setDescribedByIds(ids) {
1216
+ // We must keep this up to date to handle the case where ids are set
1217
+ // before the chip input is registered.
1218
+ this._ariaDescribedbyIds = ids;
1219
+ this._chipInput?.setDescribedByIds(ids);
1220
+ }
1221
+ /**
1222
+ * Implemented as part of ControlValueAccessor.
1223
+ */
1224
+ writeValue(value) {
1225
+ // The user is responsible for creating the child chips, so we just store the value.
1226
+ this._value = value;
1227
+ }
1228
+ /**
1229
+ * Implemented as part of ControlValueAccessor.
1230
+ */
1231
+ registerOnChange(fn) {
1232
+ this._onChange = fn;
1233
+ }
1234
+ /**
1235
+ * Implemented as part of ControlValueAccessor.
1236
+ */
1237
+ registerOnTouched(fn) {
1238
+ this._onTouched = fn;
1239
+ }
1240
+ /**
1241
+ * Implemented as part of ControlValueAccessor.
1242
+ */
1243
+ setDisabledState(isDisabled) {
1244
+ this.disabled = isDisabled;
1245
+ this.stateChanges.next();
1246
+ }
1247
+ /** Refreshes the error state of the chip grid. */
1248
+ updateErrorState() {
1249
+ this._errorStateTracker.updateErrorState();
1250
+ }
1251
+ /** When blurred, mark the field as touched when focus moved outside the chip grid. */
1252
+ _blur() {
1253
+ if (!this.disabled) {
1254
+ this._toggleFocusedStyle(false);
1255
+ // Check whether the focus moved to chip input.
1256
+ // If the focus is not moved to chip input, mark the field as touched. If the focus moved
1257
+ // to chip input, do nothing.
1258
+ // Timeout is needed to wait for the focus() event trigger on chip input.
1259
+ setTimeout(() => {
1260
+ if (!this.focused) {
1261
+ this._propagateChanges();
1262
+ this._markAsTouched();
1263
+ }
1264
+ });
1265
+ }
1266
+ }
1267
+ /**
1268
+ * Removes the `tabindex` from the chip grid and resets it back afterward, allowing the
1269
+ * user to tab out of it. This prevents the grid from capturing focus and redirecting
1270
+ * it back to the first chip, creating a focus trap if its user tries to tab away.
1271
+ */
1272
+ _allowFocusEscape() {
1273
+ if (!this._chipInput?.focused) {
1274
+ super._allowFocusEscape();
1275
+ }
1276
+ }
1277
+ /** Handles custom keyboard events. */
1278
+ _handleKeydown(event) {
1279
+ if (event.keyCode === TAB) {
1280
+ if (this._chipInput?.focused &&
1281
+ hasModifierKey(event, 'shiftKey') &&
1282
+ this._chips.length &&
1283
+ !this._chips.last.disabled) {
1284
+ event.preventDefault();
1285
+ if (this._keyManager?.activeItem) {
1286
+ this._keyManager?.setActiveItem(this._keyManager.activeItem);
1287
+ }
1288
+ else {
1289
+ this._focusLastChip();
1290
+ }
1291
+ }
1292
+ else {
1293
+ // Use the super method here since it doesn't check for the input
1294
+ // focused state. This allows focus to escape if there's only one
1295
+ // disabled chip left in the list.
1296
+ super._allowFocusEscape();
1297
+ }
1298
+ }
1299
+ else if (!this._chipInput?.focused) {
1300
+ super._handleKeydown(event);
1301
+ }
1302
+ this.stateChanges.next();
1303
+ }
1304
+ _focusLastChip() {
1305
+ if (this._chips.length) {
1306
+ this._chips.last.focus();
1307
+ }
1308
+ }
1309
+ /** Emits change event to set the model value. */
1310
+ _propagateChanges() {
1311
+ const valueToEmit = this._chips.length ? this._chips.toArray().map(chip => chip.value) : [];
1312
+ this._value = valueToEmit;
1313
+ this.change.emit(new CuteChipGridChange(this, valueToEmit));
1314
+ this.valueChange.emit(valueToEmit);
1315
+ this._onChange(valueToEmit);
1316
+ this._changeDetectorRef.markForCheck();
1317
+ }
1318
+ /** Mark the field as touched */
1319
+ _markAsTouched() {
1320
+ this._onTouched();
1321
+ this._changeDetectorRef.markForCheck();
1322
+ this.stateChanges.next();
1323
+ }
1324
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipGrid, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1325
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.3.15", type: CuteChipGrid, isStandalone: true, selector: "cute-chip-grid", inputs: { disabled: ["disabled", "disabled", booleanAttribute], placeholder: "placeholder", required: ["required", "required", booleanAttribute], value: "value", errorStateMatcher: "errorStateMatcher" }, outputs: { change: "change", valueChange: "valueChange" }, host: { listeners: { "focus": "focus()", "blur": "_blur()" }, properties: { "attr.role": "role", "attr.tabindex": "(disabled || (_chips && _chips.length === 0)) ? -1 : tabIndex", "attr.aria-disabled": "disabled", "attr.aria-invalid": "errorState", "class.cute-chip-list-disabled": "disabled", "class.cute-chip-list-invalid": "errorState", "class.cute-chip-list-required": "required" }, classAttribute: "cute-chip-grid input-group-text" }, providers: [{ provide: CuteFormFieldControl, useExisting: CuteChipGrid }], queries: [{ propertyName: "_chips", predicate: CuteChipRow, descendants: true }], usesInheritance: true, ngImport: i0, template: `
1326
+ <div class="cute-chip-set__chips" role="presentation">
1327
+ <ng-content></ng-content>
1328
+ </div>
1329
+ `, isInline: true, styles: [".cute-chip-listbox,.cute-chip-grid,.cute-chip-set{display:flex;width:100%;background-color:var(--bs-body-bg)}.cute-chip-listbox .cute-chip-set__chips,.cute-chip-grid .cute-chip-set__chips,.cute-chip-set .cute-chip-set__chips{display:flex;flex-flow:wrap;gap:.375rem;min-width:100%}.cute-form-field .cute-chip-listbox,.cute-form-field .cute-chip-grid,.cute-form-field .cute-chip-set{min-height:58px}.cute-chip-grid-focused{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.cute-chip-set-stacked .cute-chip-set__chips{flex-direction:column;align-items:flex-start}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip{display:block;width:100%}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__graphic{flex-grow:0}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip-action,.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__action--primary{flex-basis:100%;justify-content:start;width:100%}input.cute-chip-input{flex:1 0 150px;margin-left:.25rem;border:none;outline:none;background:none;transition:opacity .15s 0ms cubic-bezier(.4,0,.2,1)}input.cute-chip-input:not(:focus){opacity:.75}[dir=rtl] input.cute-chip-input{margin-left:0;margin-right:.25rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1330
+ }
1331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipGrid, decorators: [{
1332
+ type: Component,
1333
+ args: [{ selector: 'cute-chip-grid', template: `
1334
+ <div class="cute-chip-set__chips" role="presentation">
1335
+ <ng-content></ng-content>
1336
+ </div>
1337
+ `, host: {
1338
+ 'class': 'cute-chip-grid input-group-text',
1339
+ '[attr.role]': 'role',
1340
+ '[attr.tabindex]': '(disabled || (_chips && _chips.length === 0)) ? -1 : tabIndex',
1341
+ '[attr.aria-disabled]': 'disabled',
1342
+ '[attr.aria-invalid]': 'errorState',
1343
+ '[class.cute-chip-list-disabled]': 'disabled',
1344
+ '[class.cute-chip-list-invalid]': 'errorState',
1345
+ '[class.cute-chip-list-required]': 'required',
1346
+ '(focus)': 'focus()',
1347
+ '(blur)': '_blur()',
1348
+ }, providers: [{ provide: CuteFormFieldControl, useExisting: CuteChipGrid }], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [".cute-chip-listbox,.cute-chip-grid,.cute-chip-set{display:flex;width:100%;background-color:var(--bs-body-bg)}.cute-chip-listbox .cute-chip-set__chips,.cute-chip-grid .cute-chip-set__chips,.cute-chip-set .cute-chip-set__chips{display:flex;flex-flow:wrap;gap:.375rem;min-width:100%}.cute-form-field .cute-chip-listbox,.cute-form-field .cute-chip-grid,.cute-form-field .cute-chip-set{min-height:58px}.cute-chip-grid-focused{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.cute-chip-set-stacked .cute-chip-set__chips{flex-direction:column;align-items:flex-start}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip{display:block;width:100%}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__graphic{flex-grow:0}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip-action,.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__action--primary{flex-basis:100%;justify-content:start;width:100%}input.cute-chip-input{flex:1 0 150px;margin-left:.25rem;border:none;outline:none;background:none;transition:opacity .15s 0ms cubic-bezier(.4,0,.2,1)}input.cute-chip-input:not(:focus){opacity:.75}[dir=rtl] input.cute-chip-input{margin-left:0;margin-right:.25rem}\n"] }]
1349
+ }], ctorParameters: () => [], propDecorators: { disabled: [{
1350
+ type: Input,
1351
+ args: [{ transform: booleanAttribute }]
1352
+ }], placeholder: [{
1353
+ type: Input
1354
+ }], required: [{
1355
+ type: Input,
1356
+ args: [{ transform: booleanAttribute }]
1357
+ }], value: [{
1358
+ type: Input
1359
+ }], errorStateMatcher: [{
1360
+ type: Input
1361
+ }], change: [{
1362
+ type: Output
1363
+ }], valueChange: [{
1364
+ type: Output
1365
+ }], _chips: [{
1366
+ type: ContentChildren,
1367
+ args: [CuteChipRow, {
1368
+ // We need to use `descendants: true`, because Ivy will no longer match
1369
+ // indirect descendants if it's left as false.
1370
+ descendants: true,
1371
+ }]
1372
+ }] } });
1373
+
1374
+ /**
1375
+ * @license Apache-2.0
1376
+ *
1377
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
1378
+ *
1379
+ * You may not use this file except in compliance with the License
1380
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
1381
+ *
1382
+ * This code is a modification of the `@angular/material` original
1383
+ * code licensed under MIT-style License (https://angular.dev/license).
1384
+ */
1385
+ /** Avatar image within a chip. */
1386
+ class CuteChipAvatar {
1387
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipAvatar, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1388
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: CuteChipAvatar, isStandalone: true, selector: "cute-chip-avatar, [cuteChipAvatar]", host: { attributes: { "role": "img" }, classAttribute: "cute-chip-avatar cute-chip__icon cute-chip__icon--primary" }, providers: [{ provide: CUTE_CHIP_AVATAR, useExisting: CuteChipAvatar }], ngImport: i0 }); }
1389
+ }
1390
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipAvatar, decorators: [{
1391
+ type: Directive,
1392
+ args: [{
1393
+ selector: 'cute-chip-avatar, [cuteChipAvatar]',
1394
+ host: {
1395
+ 'class': 'cute-chip-avatar cute-chip__icon cute-chip__icon--primary',
1396
+ 'role': 'img',
1397
+ },
1398
+ providers: [{ provide: CUTE_CHIP_AVATAR, useExisting: CuteChipAvatar }],
1399
+ standalone: true,
1400
+ }]
1401
+ }] });
1402
+ /** Non-interactive trailing icon in a chip. */
1403
+ class CuteChipTrailingIcon extends CuteChipAction {
1404
+ constructor() {
1405
+ super(...arguments);
1406
+ /**
1407
+ * MDC considers all trailing actions as a remove icon,
1408
+ * but we support non-interactive trailing icons.
1409
+ */
1410
+ this.isInteractive = false;
1411
+ this._isPrimary = false;
1412
+ }
1413
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipTrailingIcon, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1414
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: CuteChipTrailingIcon, isStandalone: true, selector: "cute-chip-trailing-icon, [cuteChipTrailingIcon]", host: { attributes: { "aria-hidden": "true" }, classAttribute: "cute-chip-trailing-icon cute-chip__icon cute-chip__icon--trailing" }, providers: [{ provide: CUTE_CHIP_TRAILING_ICON, useExisting: CuteChipTrailingIcon }], usesInheritance: true, ngImport: i0 }); }
1415
+ }
1416
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipTrailingIcon, decorators: [{
1417
+ type: Directive,
1418
+ args: [{
1419
+ selector: 'cute-chip-trailing-icon, [cuteChipTrailingIcon]',
1420
+ host: {
1421
+ 'class': 'cute-chip-trailing-icon cute-chip__icon cute-chip__icon--trailing',
1422
+ 'aria-hidden': 'true',
1423
+ },
1424
+ providers: [{ provide: CUTE_CHIP_TRAILING_ICON, useExisting: CuteChipTrailingIcon }],
1425
+ standalone: true,
1426
+ }]
1427
+ }] });
1428
+ /**
1429
+ * Directive to edit the parent chip when the leading action icon is clicked or
1430
+ * when the ENTER key is pressed on it.
1431
+ *
1432
+ * Recommended for use with the Material Design "edit" icon
1433
+ * available at https://material.io/icons/#ic_edit.
1434
+ *
1435
+ * Example:
1436
+ *
1437
+ * ```
1438
+ * <cute-chip>
1439
+ * <button cuteChipEdit aria-label="Edit">
1440
+ * <cute-icon>edit</cute-icon>
1441
+ * </button>
1442
+ * </cute-chip>
1443
+ * ```
1444
+ */
1445
+ class CuteChipEdit extends CuteChipAction {
1446
+ constructor() {
1447
+ super(...arguments);
1448
+ this._isPrimary = false;
1449
+ this._isLeading = true;
1450
+ }
1451
+ _handleClick(event) {
1452
+ if (!this.disabled) {
1453
+ event.stopPropagation();
1454
+ event.preventDefault();
1455
+ this._parentChip._edit();
1456
+ }
1457
+ }
1458
+ _handleKeydown(event) {
1459
+ if ((event.keyCode === ENTER || event.keyCode === SPACE) && !this.disabled) {
1460
+ event.stopPropagation();
1461
+ event.preventDefault();
1462
+ this._parentChip._edit();
1463
+ }
1464
+ }
1465
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipEdit, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1466
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: CuteChipEdit, isStandalone: true, selector: "[cuteChipEdit]", host: { attributes: { "role": "button" }, properties: { "attr.aria-hidden": "null" }, classAttribute: "cute-chip-edit cute-chip-avatar cute-focus-indicator cute-chip__icon cute-chip__icon--primary" }, providers: [{ provide: CUTE_CHIP_EDIT, useExisting: CuteChipEdit }], usesInheritance: true, ngImport: i0 }); }
1467
+ }
1468
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipEdit, decorators: [{
1469
+ type: Directive,
1470
+ args: [{
1471
+ selector: '[cuteChipEdit]',
1472
+ host: {
1473
+ 'class': 'cute-chip-edit cute-chip-avatar cute-focus-indicator ' +
1474
+ 'cute-chip__icon cute-chip__icon--primary',
1475
+ 'role': 'button',
1476
+ '[attr.aria-hidden]': 'null',
1477
+ },
1478
+ providers: [{ provide: CUTE_CHIP_EDIT, useExisting: CuteChipEdit }],
1479
+ }]
1480
+ }] });
1481
+ /**
1482
+ * Directive to remove the parent chip when the trailing icon is clicked or
1483
+ * when the ENTER key is pressed on it.
1484
+ *
1485
+ * Recommended for use with the Material Design "cancel" icon
1486
+ * available at https://material.io/icons/#ic_cancel.
1487
+ *
1488
+ * Example:
1489
+ *
1490
+ * ```
1491
+ * <cute-chip>
1492
+ * <cute-icon cuteChipRemove>cancel</cute-icon>
1493
+ * </cute-chip>
1494
+ * ```
1495
+ */
1496
+ class CuteChipRemove extends CuteChipAction {
1497
+ constructor() {
1498
+ super(...arguments);
1499
+ this._isPrimary = false;
1500
+ }
1501
+ _handleClick(event) {
1502
+ if (!this.disabled) {
1503
+ event.stopPropagation();
1504
+ event.preventDefault();
1505
+ this._parentChip.remove();
1506
+ }
1507
+ }
1508
+ _handleKeydown(event) {
1509
+ if ((event.keyCode === ENTER || event.keyCode === SPACE) && !this.disabled) {
1510
+ event.stopPropagation();
1511
+ event.preventDefault();
1512
+ this._parentChip.remove();
1513
+ }
1514
+ }
1515
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipRemove, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1516
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: CuteChipRemove, isStandalone: true, selector: "[cuteChipRemove]", host: { attributes: { "role": "button" }, properties: { "attr.aria-hidden": "null" }, classAttribute: "cute-chip-remove cute-chip-trailing-icon cute-focus-indicator cute-chip__icon cute-chip__icon--trailing cute-chip__action" }, providers: [{ provide: CUTE_CHIP_REMOVE, useExisting: CuteChipRemove }], usesInheritance: true, ngImport: i0 }); }
1517
+ }
1518
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipRemove, decorators: [{
1519
+ type: Directive,
1520
+ args: [{
1521
+ selector: '[cuteChipRemove]',
1522
+ host: {
1523
+ 'class': 'cute-chip-remove cute-chip-trailing-icon cute-focus-indicator ' +
1524
+ 'cute-chip__icon cute-chip__icon--trailing cute-chip__action',
1525
+ 'role': 'button',
1526
+ '[attr.aria-hidden]': 'null',
1527
+ },
1528
+ providers: [{ provide: CUTE_CHIP_REMOVE, useExisting: CuteChipRemove }],
1529
+ standalone: true,
1530
+ }]
1531
+ }] });
1532
+
1533
+ /**
1534
+ * @license Apache-2.0
1535
+ *
1536
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
1537
+ *
1538
+ * You may not use this file except in compliance with the License
1539
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
1540
+ *
1541
+ * This code is a modification of the `@angular/material` original
1542
+ * code licensed under MIT-style License (https://angular.dev/license).
1543
+ */
1544
+ // Increasing integer for generating unique ids.
1545
+ let nextUniqueId = 0;
1546
+ /**
1547
+ * Directive that adds chip-specific behaviors to an input element inside `<cute-form-field>`.
1548
+ * May be placed inside or outside a `<cute-chip-grid>`.
1549
+ */
1550
+ class CuteChipInput {
1551
+ /** Register input for a chip list */
1552
+ get chipGrid() { return this._chipGrid; }
1553
+ set chipGrid(value) {
1554
+ if (value) {
1555
+ this._chipGrid = value;
1556
+ this._chipGrid.registerInput(this);
1557
+ }
1558
+ }
1559
+ /** Whether the input is disabled. */
1560
+ get disabled() {
1561
+ return (this._disabled || (this._chipGrid && this._chipGrid.disabled)) ?? false;
1562
+ }
1563
+ set disabled(value) {
1564
+ this._disabled = value;
1565
+ }
1566
+ /** Whether the input is empty. */
1567
+ get empty() {
1568
+ return !this.inputElement.value;
1569
+ }
1570
+ constructor() {
1571
+ this._elementRef = inject(ElementRef);
1572
+ /** Used to prevent focus moving to chips while user is holding backspace */
1573
+ this._focusLastChipOnBackspace = false;
1574
+ /** Whether the control is focused. */
1575
+ this.focused = false;
1576
+ /**
1577
+ * Whether the `chipEnd` event will be emitted when the input is blurred.
1578
+ */
1579
+ this.addOnBlur = false;
1580
+ /** Emitted when a chip is to be added. */
1581
+ this.chipEnd = new EventEmitter();
1582
+ /** The input's placeholder text. */
1583
+ this.placeholder = '';
1584
+ /** Unique id for the input. */
1585
+ this.id = `cute-chip-list-input-${nextUniqueId++}`;
1586
+ this._disabled = false;
1587
+ /** Whether the input is readonly. */
1588
+ this.readonly = false;
1589
+ /** Whether the input should remain interactive when it is disabled. */
1590
+ this.disabledInteractive = false;
1591
+ const defaultOptions = inject(CUTE_CHIPS_DEFAULT_OPTIONS);
1592
+ const formField = inject(CUTE_FORM_FIELD, { optional: true });
1593
+ this.inputElement = this._elementRef.nativeElement;
1594
+ this.separatorKeyCodes = defaultOptions.separatorKeyCodes;
1595
+ this.disabledInteractive = defaultOptions.inputDisabledInteractive ?? false;
1596
+ if (formField) {
1597
+ this.inputElement.classList.add('cute-form-field-input-control');
1598
+ }
1599
+ }
1600
+ ngOnChanges() {
1601
+ this._chipGrid?.stateChanges.next();
1602
+ }
1603
+ ngOnDestroy() {
1604
+ this.chipEnd.complete();
1605
+ }
1606
+ /** Utility method to make host definition/tests more clear. */
1607
+ _keydown(event) {
1608
+ if (this.empty && event.keyCode === BACKSPACE) {
1609
+ // Ignore events where the user is holding down backspace
1610
+ // so that we don't accidentally remove too many chips.
1611
+ if (!event.repeat) {
1612
+ this._chipGrid?._focusLastChip();
1613
+ }
1614
+ event.preventDefault();
1615
+ }
1616
+ else {
1617
+ this._emitChipEnd(event);
1618
+ }
1619
+ }
1620
+ /** Checks to see if the blur should emit the (chipEnd) event. */
1621
+ _blur() {
1622
+ if (this.addOnBlur) {
1623
+ this._emitChipEnd();
1624
+ }
1625
+ this.focused = false;
1626
+ // Blur the chip list if it is not focused
1627
+ if (this._chipGrid) {
1628
+ if (!this._chipGrid.focused) {
1629
+ this._chipGrid._blur();
1630
+ }
1631
+ this._chipGrid.stateChanges.next();
1632
+ }
1633
+ }
1634
+ _focus() {
1635
+ this.focused = true;
1636
+ this._focusLastChipOnBackspace = this.empty;
1637
+ this._chipGrid?._toggleFocusedStyle(true);
1638
+ this._chipGrid?.stateChanges.next();
1639
+ }
1640
+ /** Checks to see if the (chipEnd) event needs to be emitted. */
1641
+ _emitChipEnd(event) {
1642
+ if (!event || this._isSeparatorKey(event)) {
1643
+ this.chipEnd.emit({
1644
+ input: this.inputElement,
1645
+ value: this.inputElement.value,
1646
+ chipInput: this,
1647
+ });
1648
+ event?.preventDefault();
1649
+ }
1650
+ }
1651
+ _onInput() {
1652
+ // Let the chip list know whenever the value changes.
1653
+ this._chipGrid?.stateChanges.next();
1654
+ }
1655
+ /** Focuses the input. */
1656
+ focus() {
1657
+ this.inputElement.focus();
1658
+ }
1659
+ /** Clears the input */
1660
+ clear() {
1661
+ this.inputElement.value = '';
1662
+ this._focusLastChipOnBackspace = true;
1663
+ }
1664
+ setDescribedByIds(ids) {
1665
+ const element = this._elementRef.nativeElement;
1666
+ // Set the value directly in the DOM since this binding
1667
+ // is prone to "changed after checked" errors.
1668
+ if (ids.length) {
1669
+ element.setAttribute('aria-describedby', ids.join(' '));
1670
+ }
1671
+ else {
1672
+ element.removeAttribute('aria-describedby');
1673
+ }
1674
+ }
1675
+ /** Checks whether a keycode is one of the configured separators. */
1676
+ _isSeparatorKey(event) {
1677
+ return !hasModifierKey(event) && new Set(this.separatorKeyCodes).has(event.keyCode);
1678
+ }
1679
+ /** Gets the value to set on the `readonly` attribute. */
1680
+ _getReadonlyAttribute() {
1681
+ return this.readonly || (this.disabled && this.disabledInteractive) ? 'true' : null;
1682
+ }
1683
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1684
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.15", type: CuteChipInput, isStandalone: true, selector: "input[cuteChipInputFor]", inputs: { chipGrid: ["cuteChipInputFor", "chipGrid"], addOnBlur: ["cuteChipInputAddOnBlur", "addOnBlur", booleanAttribute], separatorKeyCodes: ["cuteChipInputSeparatorKeyCodes", "separatorKeyCodes"], placeholder: "placeholder", id: "id", disabled: ["disabled", "disabled", booleanAttribute], readonly: ["readonly", "readonly", booleanAttribute], disabledInteractive: ["cuteChipInputDisabledInteractive", "disabledInteractive", booleanAttribute] }, outputs: { chipEnd: "cuteChipInputTokenEnd" }, host: { listeners: { "keydown": "_keydown($event)", "blur": "_blur()", "focus": "_focus()", "input": "_onInput()" }, properties: { "id": "id", "attr.disabled": "disabled && !disabledInteractive ? \"\" : null", "attr.placeholder": "placeholder || null", "attr.aria-invalid": "chipGrid && chipGrid.ngControl ? chipGrid.ngControl.invalid : null", "attr.aria-required": "(chipGrid && chipGrid.required) || null", "attr.aria-disabled": "disabled && disabledInteractive ? \"true\" : null", "attr.readonly": "_getReadonlyAttribute()", "attr.required": "(chipGrid && chipGrid.required) || null" }, classAttribute: "cute-chip-input" }, exportAs: ["cuteChipInput", "cuteChipInputFor"], usesOnChanges: true, ngImport: i0 }); }
1685
+ }
1686
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipInput, decorators: [{
1687
+ type: Directive,
1688
+ args: [{
1689
+ selector: 'input[cuteChipInputFor]',
1690
+ exportAs: 'cuteChipInput, cuteChipInputFor',
1691
+ host: {
1692
+ 'class': 'cute-chip-input',
1693
+ '(keydown)': '_keydown($event)',
1694
+ '(blur)': '_blur()',
1695
+ '(focus)': '_focus()',
1696
+ '(input)': '_onInput()',
1697
+ '[id]': 'id',
1698
+ '[attr.disabled]': 'disabled && !disabledInteractive ? "" : null',
1699
+ '[attr.placeholder]': 'placeholder || null',
1700
+ '[attr.aria-invalid]': 'chipGrid && chipGrid.ngControl ? chipGrid.ngControl.invalid : null',
1701
+ '[attr.aria-required]': '(chipGrid && chipGrid.required) || null',
1702
+ '[attr.aria-disabled]': 'disabled && disabledInteractive ? "true" : null',
1703
+ '[attr.readonly]': '_getReadonlyAttribute()',
1704
+ '[attr.required]': '(chipGrid && chipGrid.required) || null',
1705
+ },
1706
+ standalone: true,
1707
+ }]
1708
+ }], ctorParameters: () => [], propDecorators: { chipGrid: [{
1709
+ type: Input,
1710
+ args: ['cuteChipInputFor']
1711
+ }], addOnBlur: [{
1712
+ type: Input,
1713
+ args: [{ alias: 'cuteChipInputAddOnBlur', transform: booleanAttribute }]
1714
+ }], separatorKeyCodes: [{
1715
+ type: Input,
1716
+ args: ['cuteChipInputSeparatorKeyCodes']
1717
+ }], chipEnd: [{
1718
+ type: Output,
1719
+ args: ['cuteChipInputTokenEnd']
1720
+ }], placeholder: [{
1721
+ type: Input
1722
+ }], id: [{
1723
+ type: Input
1724
+ }], disabled: [{
1725
+ type: Input,
1726
+ args: [{ transform: booleanAttribute }]
1727
+ }], readonly: [{
1728
+ type: Input,
1729
+ args: [{ transform: booleanAttribute }]
1730
+ }], disabledInteractive: [{
1731
+ type: Input,
1732
+ args: [{ alias: 'cuteChipInputDisabledInteractive', transform: booleanAttribute }]
1733
+ }] } });
1734
+
1735
+ /**
1736
+ * @license Apache-2.0
1737
+ *
1738
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
1739
+ *
1740
+ * You may not use this file except in compliance with the License
1741
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
1742
+ *
1743
+ * This code is a modification of the `@angular/material` original
1744
+ * code licensed under MIT-style License (https://angular.dev/license).
1745
+ */
1746
+ /** Event object emitted by CuteChipOption when selected or deselected. */
1747
+ class CuteChipSelectionChange {
1748
+ constructor(
1749
+ /** Reference to the chip that emitted the event. */
1750
+ source,
1751
+ /** Whether the chip that emitted the event is selected. */
1752
+ selected,
1753
+ /** Whether the selection change was a result of a user interaction. */
1754
+ isUserInput = false) {
1755
+ this.source = source;
1756
+ this.selected = selected;
1757
+ this.isUserInput = isUserInput;
1758
+ }
1759
+ }
1760
+ /**
1761
+ * An extension of the CuteChip component that supports chip selection. Used with CuteChipListbox.
1762
+ *
1763
+ * Unlike other chips, the user can focus on disabled chip options inside a CuteChipListbox. The
1764
+ * user cannot click disabled chips.
1765
+ */
1766
+ class CuteChipOption extends CuteChip {
1767
+ constructor() {
1768
+ super(...arguments);
1769
+ /** Default chip options. */
1770
+ this._defaultOptions = inject(CUTE_CHIPS_DEFAULT_OPTIONS, { optional: true });
1771
+ /** Whether the chip list is selectable. */
1772
+ this.chipListSelectable = true;
1773
+ /** Whether the chip list is in multi-selection mode. */
1774
+ this._chipListMultiple = false;
1775
+ /** Whether the chip list hides single-selection indicator. */
1776
+ this._chipListHideSingleSelectionIndicator = this._defaultOptions?.hideSingleSelectionIndicator ?? false;
1777
+ this._selectable = true;
1778
+ this._selected = false;
1779
+ /** The unstyled chip selector for this component. */
1780
+ this.basicChipAttrName = 'cute-basic-chip-option';
1781
+ /** Emitted when the chip is selected or deselected. */
1782
+ this.selectionChange = new EventEmitter();
1783
+ }
1784
+ /**
1785
+ * Whether the chip is selectable.
1786
+ *
1787
+ * When a chip is not selectable, changes to its selected state are always
1788
+ * ignored. By default, an option chip is selectable, and it becomes
1789
+ * non-selectable if its parent chip list is not selectable.
1790
+ */
1791
+ get selectable() { return this._selectable && this.chipListSelectable; }
1792
+ set selectable(value) {
1793
+ this._selectable = value;
1794
+ this.markForCheck();
1795
+ }
1796
+ /** Whether the chip is selected. */
1797
+ get selected() { return this._selected; }
1798
+ set selected(value) { this._setSelectedState(value, false, true); }
1799
+ /**
1800
+ * The ARIA selected applied to the chip. Conforms to WAI ARIA best practices for listbox
1801
+ * interaction patterns.
1802
+ *
1803
+ * From [WAI ARIA Listbox authoring practices guide](
1804
+ * https://www.w3.org/WAI/ARIA/apg/patterns/listbox/):
1805
+ * "If any options are selected, each selected option has either aria-selected or aria-checked
1806
+ * set to true. All options that are selectable but not selected have either aria-selected or
1807
+ * aria-checked set to false."
1808
+ *
1809
+ * Set `aria-selected="false"` on not-selected listbox options that are selectable to fix
1810
+ * VoiceOver reading every option as "selected" (#25736).
1811
+ */
1812
+ get ariaSelected() {
1813
+ return this.selectable ? this.selected.toString() : null;
1814
+ }
1815
+ ngOnInit() {
1816
+ super.ngOnInit();
1817
+ this.role = 'presentation';
1818
+ }
1819
+ /** Selects the chip. */
1820
+ select() { this._setSelectedState(true, false, true); }
1821
+ /** Deselects the chip. */
1822
+ deselect() { this._setSelectedState(false, false, true); }
1823
+ /** Selects this chip and emits userInputSelection event */
1824
+ selectViaInteraction() { this._setSelectedState(true, true, true); }
1825
+ /** Toggles the current selected state of this chip. */
1826
+ toggleSelected(isUserInput = false) {
1827
+ this._setSelectedState(!this.selected, isUserInput, true);
1828
+ return this.selected;
1829
+ }
1830
+ _handlePrimaryActionInteraction() {
1831
+ if (!this.disabled) {
1832
+ // Interacting with the primary action implies that the chip already has focus, however,
1833
+ // there's a bug in Safari where focus ends up lingering on the previous chip (see #27544).
1834
+ // We work around it by explicitly focusing the primary action of the current chip.
1835
+ this.focus();
1836
+ if (this.selectable) {
1837
+ this.toggleSelected(true);
1838
+ }
1839
+ }
1840
+ }
1841
+ _hasLeadingGraphic() {
1842
+ if (this.leadingIcon) {
1843
+ return true;
1844
+ }
1845
+ // The checkmark graphic communicates selected state for both single-select and multi-select.
1846
+ // Include checkmark in single-select to fix a11y issue where the selected state is communicated
1847
+ // visually only using color (#25886).
1848
+ return !this._chipListHideSingleSelectionIndicator || this._chipListMultiple;
1849
+ }
1850
+ _setSelectedState(isSelected, isUserInput, emitEvent) {
1851
+ if (isSelected !== this.selected) {
1852
+ this._selected = isSelected;
1853
+ if (emitEvent) {
1854
+ this.selectionChange.emit({
1855
+ source: this,
1856
+ isUserInput,
1857
+ selected: this.selected,
1858
+ });
1859
+ }
1860
+ this.markForCheck();
1861
+ }
1862
+ }
1863
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipOption, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1864
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: CuteChipOption, isStandalone: true, selector: "cute-basic-chip-option, [cute-basic-chip-option], cute-chip-option, [cute-chip-option]", inputs: { selectable: ["selectable", "selectable", booleanAttribute], selected: ["selected", "selected", booleanAttribute] }, outputs: { selectionChange: "selectionChange" }, host: { properties: { "class.cute-chip-disabled": "disabled", "class.cute-chip-highlighted": "highlighted", "class.cute-chip-with-trailing-icon": "_hasTrailingIcon()", "class.cute-chip-selected": "selected", "class.cute-chip-multiple": "_chipListMultiple", "class.cute-chip-with-avatar": "leadingIcon", "attr.tabindex": "null", "attr.aria-label": "null", "attr.aria-description": "null", "attr.role": "role", "id": "id" }, classAttribute: "cute-chip-option" }, providers: [
1865
+ { provide: CuteChip, useExisting: CuteChipOption },
1866
+ { provide: CUTE_CHIP, useExisting: CuteChipOption },
1867
+ ], usesInheritance: true, ngImport: i0, template: "<span class=\"cute-chip-focus-overlay\"></span>\r\n\r\n<span class=\"cute-chip__cell cute-chip__cell--primary\">\r\n <button\r\n cuteButton=\"outline-button\"\r\n class=\"cute-chip-action rounded-pill text-nowrap\"\r\n [class.active]=\"selected\"\r\n magnitude=\"small\"\r\n [color]=\"color\"\r\n [tabIndex]=\"tabIndex\"\r\n [disabled]=\"disabled\"\r\n [attr.aria-selected]=\"ariaSelected\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"_ariaDescriptionId\"\r\n data-bs-toggle=\"button\"\r\n role=\"option\"\r\n (click)=\"_handlePrimaryActionInteraction()\">\r\n @if (_hasLeadingGraphic()) {\r\n <span cuteButtonIcon class=\"cute-chip-graphic cute-chip__graphic\">\r\n <ng-content select=\"cute-avatar, cute-chip-avatar, [cuteChipAvatar]\"></ng-content>\r\n @if (selected && !leadingIcon ) {\r\n <span class=\"cute-chip__checkmark\">\r\n <svg\r\n class=\"cute-chip__checkmark-svg\"\r\n viewBox=\"-2 2 24 24\"\r\n focusable=\"false\"\r\n aria-hidden=\"true\">\r\n <path class=\"cute-chip__checkmark-path\"\r\n fill=\"none\" stroke=\"currentColor\" d=\"M1.73,12.91 8.1,19.28 22.79,4.59\" />\r\n </svg>\r\n </span>\r\n }\r\n </span>\r\n }\r\n <span class=\"cute-chip__text-label cute-chip-action-label\">\r\n <ng-content></ng-content>\r\n <span class=\"cute-chip-primary-focus-indicator\"></span>\r\n </span>\r\n </button>\r\n</span>\r\n\r\n@if (_hasTrailingIcon()) {\r\n <span class=\"cute-chip__cell cute-chip__cell--trailing\">\r\n <ng-content select=\"cute-chip-trailing-icon,[cuteChipRemove],[cuteChipTrailingIcon]\"></ng-content>\r\n </span>\r\n}\r\n\r\n<span class=\"visually-hidden\" [id]=\"_ariaDescriptionId\">{{ariaDescription}}</span>\r\n", styles: [".cute-chip,.cute-chip-option,cute-chip-row{position:relative;display:inline-flex;align-items:center}.cute-chip.cute-static-chip,.cute-chip-option.cute-static-chip,cute-chip-row.cute-static-chip{--bs-btn-bg: rgba(var(--bs-body-color-rgb), .06);cursor:auto}.cute-chip:hover,.cute-chip-option:hover,cute-chip-row:hover{--bs-btn-hover-bg: rgba(var(--bs-body-color-rgb), .1)}.cute-chip:active,.cute-chip-option:active,cute-chip-row:active{--bs-btn-active-bg: rgba(var(--bs-body-color-rgb), .14)}.cute-chip__cell [cuteChipAction],.cute-chip__cell .cute-chip-action{display:inline-flex;align-items:center;cursor:pointer;outline:none}.cute-chip__cell [cuteChipAction].cute-chip__action--presentational,.cute-chip__cell .cute-chip-action.cute-chip__action--presentational{cursor:auto}.cute-chip__cell [cuteChipAction]:not(button),.cute-chip__cell .cute-chip-action:not(button){gap:.5rem}.cute-chip__cell [cuteChipAction] .cute-chip__graphic,.cute-chip__cell .cute-chip-action .cute-chip__graphic{align-items:center;display:inline-flex;justify-content:center;overflow:hidden;pointer-events:none;position:relative}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark{padding-left:2px;padding-right:4px}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{width:1.2rem}[dir=rtl] .cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,[dir=rtl] .cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{transform:rotateY(180deg)}.cute-chip__cell [cuteChipAction].disabled,.cute-chip__cell .cute-chip-action.disabled{cursor:auto}.cute-chip__cell [cuteChipAction].cute-chip__icon--trailing,.cute-chip__cell .cute-chip-action.cute-chip__icon--trailing{padding-left:4px;padding-right:4px;border:none;background:none}.cute-standard-chip{-webkit-tap-highlight-color:transparent}@media (forced-colors: active){.cute-standard-chip{outline:solid 1px}.cute-standard-chip .cute-chip__checkmark-path{stroke:CanvasText!important}}.cute-standard-chip .cute-chip__icon--primary{--size: 18px;height:var(--size);width:var(--size);font-size:var(--size);border-radius:calc(var(--size) * 1.3);min-height:fit-content;background:none}.cute-standard-chip .cute-chip__cell--primary{display:flex}.cute-standard-chip .cute-chip__cell--trailing{display:inline-flex;background-color:transparent;padding-left:.5rem;padding-right:0}[dir=rtl] .cute-standard-chip .cute-chip__cell--trailing{padding-left:0;padding-right:.5rem}.cute-standard-chip._cute-animation-noopable,.cute-standard-chip._cute-animation-noopable .cute-chip__graphic,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark-path{transition-duration:1ms;animation-duration:1ms}.cute-chip-focus-overlay{inset:0;position:absolute;pointer-events:none;opacity:0;border-radius:inherit;transition:opacity .15s linear}._cute-animation-noopable .cute-chip-focus-overlay{transition:none}.cute-basic-chip .cute-chip-focus-overlay{display:none}.cute-chip-action-label{text-align:left;white-space:nowrap}[dir=rtl] .cute-chip-action-label{text-align:right}.cute-chip-primary-focus-indicator{position:absolute;inset:0;pointer-events:none}.cute-chip-edit-input{cursor:text;display:inline-block;color:inherit;outline:0}@media (forced-colors: active){.cute-chip-selected:not(.cute-chip-multiple){outline-width:3px}}\n"], dependencies: [{ kind: "component", type: CuteButton, selector: "button[cuteButton], button[cute-button], a[cuteButton], a[cute-button], ", exportAs: ["cuteButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1868
+ }
1869
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipOption, decorators: [{
1870
+ type: Component,
1871
+ args: [{ selector: 'cute-basic-chip-option, [cute-basic-chip-option], cute-chip-option, [cute-chip-option]', host: {
1872
+ 'class': 'cute-chip-option',
1873
+ '[class.cute-chip-disabled]': 'disabled',
1874
+ '[class.cute-chip-highlighted]': 'highlighted',
1875
+ '[class.cute-chip-with-trailing-icon]': '_hasTrailingIcon()',
1876
+ '[class.cute-chip-selected]': 'selected',
1877
+ '[class.cute-chip-multiple]': '_chipListMultiple',
1878
+ '[class.cute-chip-with-avatar]': 'leadingIcon',
1879
+ /*
1880
+ '[class.mdc-evolution-chip]': '!_isBasicChip',
1881
+ '[class.mdc-evolution-chip--filter]': '!_isBasicChip',
1882
+ '[class.mdc-evolution-chip--selectable]': '!_isBasicChip',
1883
+ '[class.mdc-evolution-chip--disabled]': 'disabled',
1884
+ '[class.mdc-evolution-chip--selected]': 'selected',
1885
+ // This class enables the transition on the checkmark. Usually MDC adds it when selection
1886
+ // starts and removes it once the animation is finished. We don't need to go through all
1887
+ // the trouble, because we only care about the selection animation. MDC needs to do it,
1888
+ // because they also have an exit animation that we don't care about.
1889
+ '[class.mdc-evolution-chip--selecting]': '!_animationsDisabled',
1890
+ '[class.mdc-evolution-chip--with-trailing-action]': '_hasTrailingIcon()',
1891
+ '[class.mdc-evolution-chip--with-primary-icon]': 'leadingIcon',
1892
+ '[class.mdc-evolution-chip--with-primary-graphic]': '_hasLeadingGraphic()',
1893
+ '[class.mdc-evolution-chip--with-avatar]': 'leadingIcon',
1894
+ */
1895
+ '[attr.tabindex]': 'null',
1896
+ '[attr.aria-label]': 'null',
1897
+ '[attr.aria-description]': 'null',
1898
+ '[attr.role]': 'role',
1899
+ '[id]': 'id',
1900
+ }, providers: [
1901
+ { provide: CuteChip, useExisting: CuteChipOption },
1902
+ { provide: CUTE_CHIP, useExisting: CuteChipOption },
1903
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CuteChipAction, CuteButton], template: "<span class=\"cute-chip-focus-overlay\"></span>\r\n\r\n<span class=\"cute-chip__cell cute-chip__cell--primary\">\r\n <button\r\n cuteButton=\"outline-button\"\r\n class=\"cute-chip-action rounded-pill text-nowrap\"\r\n [class.active]=\"selected\"\r\n magnitude=\"small\"\r\n [color]=\"color\"\r\n [tabIndex]=\"tabIndex\"\r\n [disabled]=\"disabled\"\r\n [attr.aria-selected]=\"ariaSelected\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"_ariaDescriptionId\"\r\n data-bs-toggle=\"button\"\r\n role=\"option\"\r\n (click)=\"_handlePrimaryActionInteraction()\">\r\n @if (_hasLeadingGraphic()) {\r\n <span cuteButtonIcon class=\"cute-chip-graphic cute-chip__graphic\">\r\n <ng-content select=\"cute-avatar, cute-chip-avatar, [cuteChipAvatar]\"></ng-content>\r\n @if (selected && !leadingIcon ) {\r\n <span class=\"cute-chip__checkmark\">\r\n <svg\r\n class=\"cute-chip__checkmark-svg\"\r\n viewBox=\"-2 2 24 24\"\r\n focusable=\"false\"\r\n aria-hidden=\"true\">\r\n <path class=\"cute-chip__checkmark-path\"\r\n fill=\"none\" stroke=\"currentColor\" d=\"M1.73,12.91 8.1,19.28 22.79,4.59\" />\r\n </svg>\r\n </span>\r\n }\r\n </span>\r\n }\r\n <span class=\"cute-chip__text-label cute-chip-action-label\">\r\n <ng-content></ng-content>\r\n <span class=\"cute-chip-primary-focus-indicator\"></span>\r\n </span>\r\n </button>\r\n</span>\r\n\r\n@if (_hasTrailingIcon()) {\r\n <span class=\"cute-chip__cell cute-chip__cell--trailing\">\r\n <ng-content select=\"cute-chip-trailing-icon,[cuteChipRemove],[cuteChipTrailingIcon]\"></ng-content>\r\n </span>\r\n}\r\n\r\n<span class=\"visually-hidden\" [id]=\"_ariaDescriptionId\">{{ariaDescription}}</span>\r\n", styles: [".cute-chip,.cute-chip-option,cute-chip-row{position:relative;display:inline-flex;align-items:center}.cute-chip.cute-static-chip,.cute-chip-option.cute-static-chip,cute-chip-row.cute-static-chip{--bs-btn-bg: rgba(var(--bs-body-color-rgb), .06);cursor:auto}.cute-chip:hover,.cute-chip-option:hover,cute-chip-row:hover{--bs-btn-hover-bg: rgba(var(--bs-body-color-rgb), .1)}.cute-chip:active,.cute-chip-option:active,cute-chip-row:active{--bs-btn-active-bg: rgba(var(--bs-body-color-rgb), .14)}.cute-chip__cell [cuteChipAction],.cute-chip__cell .cute-chip-action{display:inline-flex;align-items:center;cursor:pointer;outline:none}.cute-chip__cell [cuteChipAction].cute-chip__action--presentational,.cute-chip__cell .cute-chip-action.cute-chip__action--presentational{cursor:auto}.cute-chip__cell [cuteChipAction]:not(button),.cute-chip__cell .cute-chip-action:not(button){gap:.5rem}.cute-chip__cell [cuteChipAction] .cute-chip__graphic,.cute-chip__cell .cute-chip-action .cute-chip__graphic{align-items:center;display:inline-flex;justify-content:center;overflow:hidden;pointer-events:none;position:relative}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark{padding-left:2px;padding-right:4px}.cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,.cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{width:1.2rem}[dir=rtl] .cute-chip__cell [cuteChipAction] .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg,[dir=rtl] .cute-chip__cell .cute-chip-action .cute-chip__graphic .cute-chip__checkmark .cute-chip__checkmark-svg{transform:rotateY(180deg)}.cute-chip__cell [cuteChipAction].disabled,.cute-chip__cell .cute-chip-action.disabled{cursor:auto}.cute-chip__cell [cuteChipAction].cute-chip__icon--trailing,.cute-chip__cell .cute-chip-action.cute-chip__icon--trailing{padding-left:4px;padding-right:4px;border:none;background:none}.cute-standard-chip{-webkit-tap-highlight-color:transparent}@media (forced-colors: active){.cute-standard-chip{outline:solid 1px}.cute-standard-chip .cute-chip__checkmark-path{stroke:CanvasText!important}}.cute-standard-chip .cute-chip__icon--primary{--size: 18px;height:var(--size);width:var(--size);font-size:var(--size);border-radius:calc(var(--size) * 1.3);min-height:fit-content;background:none}.cute-standard-chip .cute-chip__cell--primary{display:flex}.cute-standard-chip .cute-chip__cell--trailing{display:inline-flex;background-color:transparent;padding-left:.5rem;padding-right:0}[dir=rtl] .cute-standard-chip .cute-chip__cell--trailing{padding-left:0;padding-right:.5rem}.cute-standard-chip._cute-animation-noopable,.cute-standard-chip._cute-animation-noopable .cute-chip__graphic,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark,.cute-standard-chip._cute-animation-noopable .cute-chip__checkmark-path{transition-duration:1ms;animation-duration:1ms}.cute-chip-focus-overlay{inset:0;position:absolute;pointer-events:none;opacity:0;border-radius:inherit;transition:opacity .15s linear}._cute-animation-noopable .cute-chip-focus-overlay{transition:none}.cute-basic-chip .cute-chip-focus-overlay{display:none}.cute-chip-action-label{text-align:left;white-space:nowrap}[dir=rtl] .cute-chip-action-label{text-align:right}.cute-chip-primary-focus-indicator{position:absolute;inset:0;pointer-events:none}.cute-chip-edit-input{cursor:text;display:inline-block;color:inherit;outline:0}@media (forced-colors: active){.cute-chip-selected:not(.cute-chip-multiple){outline-width:3px}}\n"] }]
1904
+ }], propDecorators: { selectable: [{
1905
+ type: Input,
1906
+ args: [{ transform: booleanAttribute }]
1907
+ }], selected: [{
1908
+ type: Input,
1909
+ args: [{ transform: booleanAttribute }]
1910
+ }], selectionChange: [{
1911
+ type: Output
1912
+ }] } });
1913
+
1914
+ /**
1915
+ * @license Apache-2.0
1916
+ *
1917
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
1918
+ *
1919
+ * You may not use this file except in compliance with the License
1920
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
1921
+ *
1922
+ * This code is a modification of the `@angular/material` original
1923
+ * code licensed under MIT-style License (https://angular.dev/license).
1924
+ */
1925
+ /** Change event object that is emitted when the chip listbox value has changed. */
1926
+ class CuteChipListboxChange {
1927
+ constructor(
1928
+ /** Chip listbox that emitted the event. */
1929
+ source,
1930
+ /** Value of the chip listbox when the event was emitted. */
1931
+ value) {
1932
+ this.source = source;
1933
+ this.value = value;
1934
+ }
1935
+ }
1936
+ /**
1937
+ * Provider Expression that allows cute-chip-listbox to register as a ControlValueAccessor.
1938
+ * This allows it to support [(ngModel)].
1939
+ * @docs-private
1940
+ */
1941
+ const CUTE_CHIP_LISTBOX_CONTROL_VALUE_ACCESSOR = {
1942
+ provide: NG_VALUE_ACCESSOR,
1943
+ useExisting: forwardRef(() => CuteChipListbox),
1944
+ multi: true,
1945
+ };
1946
+ /**
1947
+ * An extension of the CuteChipSet component that supports chip selection.
1948
+ * Used with CuteChipOption chips.
1949
+ */
1950
+ class CuteChipListbox extends CuteChipSet {
1951
+ constructor() {
1952
+ super(...arguments);
1953
+ /**
1954
+ * Function when touched. Set as part of ControlValueAccessor implementation.
1955
+ * @docs-private
1956
+ */
1957
+ this._onTouched = () => { };
1958
+ /**
1959
+ * Function when changed. Set as part of ControlValueAccessor implementation.
1960
+ * @docs-private
1961
+ */
1962
+ this._onChange = () => { };
1963
+ // TODO: MDC uses `grid` here
1964
+ this._defaultRole = 'listbox';
1965
+ /** Default chip options. */
1966
+ this._defaultOptions = inject(CUTE_CHIPS_DEFAULT_OPTIONS, { optional: true });
1967
+ this._multiple = false;
1968
+ /** Orientation of the chip list. */
1969
+ this.ariaOrientation = 'horizontal';
1970
+ this._selectable = true;
1971
+ /**
1972
+ * A function to compare the option values with the selected values. The first argument
1973
+ * is a value from an option. The second is a value from the selection. A boolean
1974
+ * should be returned.
1975
+ */
1976
+ this.compareWith = (o1, o2) => o1 === o2;
1977
+ /** Whether this chip listbox is required. */
1978
+ this.required = false;
1979
+ this._hideSingleSelectionIndicator = this._defaultOptions?.hideSingleSelectionIndicator ?? false;
1980
+ /** Event emitted when the user has changed the selected chip listbox value. */
1981
+ this.change = new EventEmitter();
1982
+ this._chips = undefined;
1983
+ }
1984
+ /** Whether the user should be allowed to select multiple chips. */
1985
+ get multiple() { return this._multiple; }
1986
+ set multiple(value) {
1987
+ this._multiple = value;
1988
+ this._syncListboxProperties();
1989
+ }
1990
+ /** The array of selected chips inside the chip listbox. */
1991
+ get selected() {
1992
+ const selectedChips = this._chips.toArray().filter(chip => chip.selected);
1993
+ return this.multiple ? selectedChips : selectedChips[0];
1994
+ }
1995
+ /**
1996
+ * Whether this chip listbox is selectable.
1997
+ *
1998
+ * When a chip listbox is not selectable, the selected states for all
1999
+ * the chips inside the chip listbox are always ignored.
2000
+ */
2001
+ get selectable() { return this._selectable; }
2002
+ set selectable(value) {
2003
+ this._selectable = value;
2004
+ this._syncListboxProperties();
2005
+ }
2006
+ /** Whether the checkmark indicator for single-selection options is hidden. */
2007
+ get hideSingleSelectionIndicator() { return this._hideSingleSelectionIndicator; }
2008
+ set hideSingleSelectionIndicator(value) {
2009
+ this._hideSingleSelectionIndicator = value;
2010
+ this._syncListboxProperties();
2011
+ }
2012
+ /** The combined stream of all of the child chips' selection change events. */
2013
+ get chipSelectionChanges() {
2014
+ return this._getChipStream(chip => chip.selectionChange);
2015
+ }
2016
+ /** Combined stream of all of the child chips' blur events. */
2017
+ get chipBlurChanges() {
2018
+ return this._getChipStream(chip => chip._onBlur);
2019
+ }
2020
+ /** The value of the listbox, which is the combined value of the selected chips. */
2021
+ get value() { return this._value; }
2022
+ set value(value) {
2023
+ this.writeValue(value);
2024
+ this._value = value;
2025
+ }
2026
+ ngAfterContentInit() {
2027
+ if (this._pendingInitialValue !== undefined) {
2028
+ Promise.resolve().then(() => {
2029
+ this._setSelectionByValue(this._pendingInitialValue, false);
2030
+ this._pendingInitialValue = undefined;
2031
+ });
2032
+ }
2033
+ this._chips.changes.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
2034
+ // Update listbox selectable/multiple properties on chips
2035
+ this._syncListboxProperties();
2036
+ });
2037
+ this.chipBlurChanges.pipe(takeUntil(this._destroyed)).subscribe(() => this._blur());
2038
+ this.chipSelectionChanges.pipe(takeUntil(this._destroyed)).subscribe(event => {
2039
+ if (!this.multiple) {
2040
+ this._chips.forEach(chip => {
2041
+ if (chip !== event.source) {
2042
+ chip._setSelectedState(false, false, false);
2043
+ }
2044
+ });
2045
+ }
2046
+ if (event.isUserInput) {
2047
+ this._propagateChanges();
2048
+ }
2049
+ });
2050
+ }
2051
+ /**
2052
+ * Focuses the first selected chip in this chip listbox, or the first non-disabled chip when there
2053
+ * are no selected chips.
2054
+ */
2055
+ focus() {
2056
+ if (this.disabled) {
2057
+ return;
2058
+ }
2059
+ const firstSelectedChip = this._getFirstSelectedChip();
2060
+ if (firstSelectedChip && !firstSelectedChip.disabled) {
2061
+ firstSelectedChip.focus();
2062
+ }
2063
+ else if (this._chips.length > 0) {
2064
+ this._keyManager?.setFirstItemActive();
2065
+ }
2066
+ else {
2067
+ this._elementRef.nativeElement.focus();
2068
+ }
2069
+ }
2070
+ /**
2071
+ * Implemented as part of ControlValueAccessor.
2072
+ * @docs-private
2073
+ */
2074
+ writeValue(value) {
2075
+ if (this._chips) {
2076
+ this._setSelectionByValue(value, false);
2077
+ }
2078
+ else if (value != null) {
2079
+ this._pendingInitialValue = value;
2080
+ }
2081
+ }
2082
+ /**
2083
+ * Implemented as part of ControlValueAccessor.
2084
+ * @docs-private
2085
+ */
2086
+ registerOnChange(fn) {
2087
+ this._onChange = fn;
2088
+ }
2089
+ /**
2090
+ * Implemented as part of ControlValueAccessor.
2091
+ * @docs-private
2092
+ */
2093
+ registerOnTouched(fn) {
2094
+ this._onTouched = fn;
2095
+ }
2096
+ /**
2097
+ * Implemented as part of ControlValueAccessor.
2098
+ * @docs-private
2099
+ */
2100
+ setDisabledState(isDisabled) {
2101
+ this.disabled = isDisabled;
2102
+ }
2103
+ /** Selects all chips with value. */
2104
+ _setSelectionByValue(value, isUserInput = true) {
2105
+ this._clearSelection();
2106
+ if (Array.isArray(value)) {
2107
+ value.forEach(currentValue => this._selectValue(currentValue, isUserInput));
2108
+ }
2109
+ else {
2110
+ this._selectValue(value, isUserInput);
2111
+ }
2112
+ }
2113
+ /** When blurred, marks the field as touched when focus moved outside the chip listbox. */
2114
+ _blur() {
2115
+ if (!this.disabled) {
2116
+ // Wait to see if focus moves to an individual chip.
2117
+ setTimeout(() => {
2118
+ if (!this.focused) {
2119
+ this._markAsTouched();
2120
+ }
2121
+ });
2122
+ }
2123
+ }
2124
+ _keydown(event) {
2125
+ if (event.keyCode === TAB) {
2126
+ super._allowFocusEscape();
2127
+ }
2128
+ }
2129
+ /** Marks the field as touched */
2130
+ _markAsTouched() {
2131
+ this._onTouched();
2132
+ this._changeDetectorRef.markForCheck();
2133
+ }
2134
+ /** Emits change event to set the model value. */
2135
+ _propagateChanges() {
2136
+ let valueToEmit = null;
2137
+ if (Array.isArray(this.selected)) {
2138
+ valueToEmit = this.selected.map(chip => chip.value);
2139
+ }
2140
+ else {
2141
+ valueToEmit = this.selected ? this.selected.value : undefined;
2142
+ }
2143
+ this._value = valueToEmit;
2144
+ this.change.emit(new CuteChipListboxChange(this, valueToEmit));
2145
+ this._onChange(valueToEmit);
2146
+ this._changeDetectorRef.markForCheck();
2147
+ }
2148
+ /**
2149
+ * Deselects every chip in the listbox.
2150
+ * @param skip Chip that should not be deselected.
2151
+ */
2152
+ _clearSelection(skip) {
2153
+ this._chips.forEach(chip => {
2154
+ if (chip !== skip) {
2155
+ chip.deselect();
2156
+ }
2157
+ });
2158
+ }
2159
+ /**
2160
+ * Finds and selects the chip based on its value.
2161
+ * @returns Chip that has the corresponding value.
2162
+ */
2163
+ _selectValue(value, isUserInput) {
2164
+ const correspondingChip = this._chips.find(chip => {
2165
+ return chip.value != null && this.compareWith(chip.value, value);
2166
+ });
2167
+ if (correspondingChip) {
2168
+ isUserInput ? correspondingChip.selectViaInteraction() : correspondingChip.select();
2169
+ }
2170
+ return correspondingChip;
2171
+ }
2172
+ /** Syncs the chip-listbox selection state with the individual chips. */
2173
+ _syncListboxProperties() {
2174
+ if (this._chips) {
2175
+ // Defers setting the value to avoid the "Expression
2176
+ // has changed after it was checked" errors from Angular.
2177
+ Promise.resolve().then(() => {
2178
+ this._chips.forEach(chip => {
2179
+ chip._chipListMultiple = this.multiple;
2180
+ chip.chipListSelectable = this._selectable;
2181
+ chip._chipListHideSingleSelectionIndicator = this.hideSingleSelectionIndicator;
2182
+ chip._changeDetectorRef.markForCheck();
2183
+ });
2184
+ });
2185
+ }
2186
+ }
2187
+ /** Returns the first selected chip in this listbox, or undefined if no chips are selected. */
2188
+ _getFirstSelectedChip() {
2189
+ if (Array.isArray(this.selected)) {
2190
+ return this.selected.length ? this.selected[0] : undefined;
2191
+ }
2192
+ else {
2193
+ return this.selected;
2194
+ }
2195
+ }
2196
+ /**
2197
+ * Determines if key manager should avoid putting a given chip action in the tab index. Skip
2198
+ * non-interactive actions since the user can't do anything with them.
2199
+ */
2200
+ _skipPredicate(action) {
2201
+ // Override the skip predicate in the base class to avoid skipping disabled chips. Allow
2202
+ // disabled chip options to receive focus to align with WAI ARIA recommendation. Normally WAI
2203
+ // ARIA's instructions are to exclude disabled items from the tab order, but it makes a few
2204
+ // exceptions for compound widgets.
2205
+ //
2206
+ // From [Developing a Keyboard Interface](
2207
+ // https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/):
2208
+ // "For the following composite widget elements, keep them focusable when disabled: Options in a
2209
+ // Listbox..."
2210
+ return !action.isInteractive;
2211
+ }
2212
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipListbox, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2213
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.3.15", type: CuteChipListbox, isStandalone: true, selector: "cute-chip-listbox", inputs: { multiple: ["multiple", "multiple", booleanAttribute], ariaOrientation: ["aria-orientation", "ariaOrientation"], selectable: ["selectable", "selectable", booleanAttribute], compareWith: "compareWith", required: ["required", "required", booleanAttribute], hideSingleSelectionIndicator: ["hideSingleSelectionIndicator", "hideSingleSelectionIndicator", booleanAttribute], value: "value" }, outputs: { change: "change" }, host: { listeners: { "focus": "focus()", "blur": "_blur()", "keydown": "_keydown($event)" }, properties: { "attr.role": "role", "tabIndex": "(disabled || empty) ? -1 : tabIndex", "attr.aria-required": "role ? required : null", "attr.aria-disabled": "disabled", "attr.aria-multiselectable": "multiple", "attr.aria-orientation": "ariaOrientation", "class.cute-chip-list-disabled": "disabled", "class.cute-chip-list-required": "required" }, classAttribute: "cute-chip-listbox" }, providers: [CUTE_CHIP_LISTBOX_CONTROL_VALUE_ACCESSOR], queries: [{ propertyName: "_chips", predicate: CuteChipOption, descendants: true }], usesInheritance: true, ngImport: i0, template: `
2214
+ <div class="cute-chip-set__chips" role="presentation">
2215
+ <ng-content></ng-content>
2216
+ </div>
2217
+ `, isInline: true, styles: [".cute-chip-listbox,.cute-chip-grid,.cute-chip-set{display:flex;width:100%;background-color:var(--bs-body-bg)}.cute-chip-listbox .cute-chip-set__chips,.cute-chip-grid .cute-chip-set__chips,.cute-chip-set .cute-chip-set__chips{display:flex;flex-flow:wrap;gap:.375rem;min-width:100%}.cute-form-field .cute-chip-listbox,.cute-form-field .cute-chip-grid,.cute-form-field .cute-chip-set{min-height:58px}.cute-chip-grid-focused{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.cute-chip-set-stacked .cute-chip-set__chips{flex-direction:column;align-items:flex-start}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip{display:block;width:100%}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__graphic{flex-grow:0}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip-action,.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__action--primary{flex-basis:100%;justify-content:start;width:100%}input.cute-chip-input{flex:1 0 150px;margin-left:.25rem;border:none;outline:none;background:none;transition:opacity .15s 0ms cubic-bezier(.4,0,.2,1)}input.cute-chip-input:not(:focus){opacity:.75}[dir=rtl] input.cute-chip-input{margin-left:0;margin-right:.25rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
2218
+ }
2219
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipListbox, decorators: [{
2220
+ type: Component,
2221
+ args: [{ selector: 'cute-chip-listbox', template: `
2222
+ <div class="cute-chip-set__chips" role="presentation">
2223
+ <ng-content></ng-content>
2224
+ </div>
2225
+ `, host: {
2226
+ 'class': 'cute-chip-listbox',
2227
+ '[attr.role]': 'role',
2228
+ '[tabIndex]': '(disabled || empty) ? -1 : tabIndex',
2229
+ // TODO: replace this binding with use of AriaDescriber
2230
+ //'[attr.aria-describedby]': '_ariaDescribedby || null',
2231
+ '[attr.aria-required]': 'role ? required : null',
2232
+ '[attr.aria-disabled]': 'disabled',
2233
+ '[attr.aria-multiselectable]': 'multiple',
2234
+ '[attr.aria-orientation]': 'ariaOrientation',
2235
+ '[class.cute-chip-list-disabled]': 'disabled',
2236
+ '[class.cute-chip-list-required]': 'required',
2237
+ '(focus)': 'focus()',
2238
+ '(blur)': '_blur()',
2239
+ '(keydown)': '_keydown($event)',
2240
+ }, providers: [CUTE_CHIP_LISTBOX_CONTROL_VALUE_ACCESSOR], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [".cute-chip-listbox,.cute-chip-grid,.cute-chip-set{display:flex;width:100%;background-color:var(--bs-body-bg)}.cute-chip-listbox .cute-chip-set__chips,.cute-chip-grid .cute-chip-set__chips,.cute-chip-set .cute-chip-set__chips{display:flex;flex-flow:wrap;gap:.375rem;min-width:100%}.cute-form-field .cute-chip-listbox,.cute-form-field .cute-chip-grid,.cute-form-field .cute-chip-set{min-height:58px}.cute-chip-grid-focused{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.cute-chip-set-stacked .cute-chip-set__chips{flex-direction:column;align-items:flex-start}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip{display:block;width:100%}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__graphic{flex-grow:0}.cute-chip-set-stacked .cute-chip-set__chips .cute-chip-action,.cute-chip-set-stacked .cute-chip-set__chips .cute-chip__action--primary{flex-basis:100%;justify-content:start;width:100%}input.cute-chip-input{flex:1 0 150px;margin-left:.25rem;border:none;outline:none;background:none;transition:opacity .15s 0ms cubic-bezier(.4,0,.2,1)}input.cute-chip-input:not(:focus){opacity:.75}[dir=rtl] input.cute-chip-input{margin-left:0;margin-right:.25rem}\n"] }]
2241
+ }], propDecorators: { multiple: [{
2242
+ type: Input,
2243
+ args: [{ transform: booleanAttribute }]
2244
+ }], ariaOrientation: [{
2245
+ type: Input,
2246
+ args: ['aria-orientation']
2247
+ }], selectable: [{
2248
+ type: Input,
2249
+ args: [{ transform: booleanAttribute }]
2250
+ }], compareWith: [{
2251
+ type: Input
2252
+ }], required: [{
2253
+ type: Input,
2254
+ args: [{ transform: booleanAttribute }]
2255
+ }], hideSingleSelectionIndicator: [{
2256
+ type: Input,
2257
+ args: [{ transform: booleanAttribute }]
2258
+ }], value: [{
2259
+ type: Input
2260
+ }], change: [{
2261
+ type: Output
2262
+ }], _chips: [{
2263
+ type: ContentChildren,
2264
+ args: [CuteChipOption, {
2265
+ // We need to use `descendants: true`, because Ivy will no longer match
2266
+ // indirect descendants if it's left as false.
2267
+ descendants: true,
2268
+ }]
2269
+ }] } });
2270
+
2271
+ /**
2272
+ * @license Apache-2.0
2273
+ *
2274
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
2275
+ *
2276
+ * You may not use this file except in compliance with the License
2277
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
2278
+ *
2279
+ * This code is a modification of the `@angular/material` original
2280
+ * code licensed under MIT-style License (https://angular.dev/license).
2281
+ */
2282
+
2283
+ /**
2284
+ * @license Apache-2.0
2285
+ *
2286
+ * Copyright (c) 2025 CuteWidgets Team. All Rights Reserved.
2287
+ *
2288
+ * You may not use this file except in compliance with the License
2289
+ * that can be found at http://www.apache.org/licenses/LICENSE-2.0
2290
+ */
2291
+ const TYPES = [
2292
+ CuteChip,
2293
+ CuteChipAvatar,
2294
+ CuteChipEditInput,
2295
+ CuteChipGrid,
2296
+ CuteChipInput,
2297
+ CuteChipListbox,
2298
+ CuteChipOption,
2299
+ CuteChipRemove,
2300
+ CuteChipRow,
2301
+ CuteChipSet,
2302
+ CuteChipTrailingIcon,
2303
+ ];
2304
+ class CuteChipsModule {
2305
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2306
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: CuteChipsModule, imports: [CommonModule, CuteChip,
2307
+ CuteChipAvatar,
2308
+ CuteChipEditInput,
2309
+ CuteChipGrid,
2310
+ CuteChipInput,
2311
+ CuteChipListbox,
2312
+ CuteChipOption,
2313
+ CuteChipRemove,
2314
+ CuteChipRow,
2315
+ CuteChipSet,
2316
+ CuteChipTrailingIcon], exports: [CuteChip,
2317
+ CuteChipAvatar,
2318
+ CuteChipEditInput,
2319
+ CuteChipGrid,
2320
+ CuteChipInput,
2321
+ CuteChipListbox,
2322
+ CuteChipOption,
2323
+ CuteChipRemove,
2324
+ CuteChipRow,
2325
+ CuteChipSet,
2326
+ CuteChipTrailingIcon] }); }
2327
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipsModule, providers: [
2328
+ ErrorStateMatcher,
2329
+ {
2330
+ provide: CUTE_CHIPS_DEFAULT_OPTIONS,
2331
+ useValue: {
2332
+ separatorKeyCodes: [ENTER],
2333
+ },
2334
+ },
2335
+ ], imports: [CommonModule, CuteChipOption] }); }
2336
+ }
2337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CuteChipsModule, decorators: [{
2338
+ type: NgModule,
2339
+ args: [{
2340
+ imports: [CommonModule, ...TYPES],
2341
+ exports: TYPES,
2342
+ declarations: [],
2343
+ providers: [
2344
+ ErrorStateMatcher,
2345
+ {
2346
+ provide: CUTE_CHIPS_DEFAULT_OPTIONS,
2347
+ useValue: {
2348
+ separatorKeyCodes: [ENTER],
2349
+ },
2350
+ },
2351
+ ],
2352
+ }]
2353
+ }] });
2354
+
2355
+ /**
2356
+ * Generated bundle index. Do not edit.
2357
+ */
2358
+
2359
+ export { CUTE_CHIP_LISTBOX_CONTROL_VALUE_ACCESSOR, CuteChip, CuteChipAvatar, CuteChipEdit, CuteChipEditInput, CuteChipGrid, CuteChipGridChange, CuteChipInput, CuteChipListbox, CuteChipListboxChange, CuteChipOption, CuteChipRemove, CuteChipRow, CuteChipSelectionChange, CuteChipSet, CuteChipTrailingIcon, CuteChipsModule };
2360
+ //# sourceMappingURL=cute-widgets-base-chips.mjs.map