mtrl 0.3.1 → 0.3.2

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 (159) hide show
  1. package/.env +15 -0
  2. package/CONTRIBUTING.md +8 -8
  3. package/DOCS.md +3 -3
  4. package/README.md +43 -20
  5. package/TESTING.md +128 -18
  6. package/dist/index.js +14865 -0
  7. package/git-user-stats.js +545 -0
  8. package/index.ts +9 -67
  9. package/package.json +8 -3
  10. package/src/components/badge/api.ts +15 -1
  11. package/src/components/badge/badge.ts +43 -4
  12. package/src/components/badge/config.ts +40 -8
  13. package/src/components/badge/index.ts +64 -3
  14. package/src/components/badge/types.ts +175 -33
  15. package/src/components/button/api.ts +63 -1
  16. package/src/components/button/button.ts +39 -3
  17. package/src/components/button/config.ts +21 -4
  18. package/src/components/button/index.ts +26 -1
  19. package/src/components/button/types.ts +7 -1
  20. package/src/components/card/api.ts +78 -9
  21. package/src/components/card/card.ts +58 -3
  22. package/src/components/card/config.ts +41 -11
  23. package/src/components/card/features.ts +39 -12
  24. package/src/components/card/index.ts +84 -19
  25. package/src/components/card/types.ts +218 -29
  26. package/src/components/carousel/carousel.ts +92 -28
  27. package/src/components/carousel/constants.ts +107 -21
  28. package/src/components/carousel/index.ts +31 -13
  29. package/src/components/checkbox/checkbox.ts +83 -16
  30. package/src/components/checkbox/index.ts +43 -1
  31. package/src/components/checkbox/types.ts +219 -32
  32. package/src/components/chips/api.ts +194 -0
  33. package/src/components/{chip → chips/chip}/api.ts +42 -2
  34. package/src/components/chips/chip/chip.ts +131 -0
  35. package/src/components/{chip → chips/chip}/config.ts +3 -3
  36. package/src/components/chips/chip/index.ts +3 -0
  37. package/src/components/chips/chips.md +481 -0
  38. package/src/components/chips/chips.ts +75 -0
  39. package/src/components/chips/config.ts +109 -0
  40. package/src/components/chips/constants.ts +61 -0
  41. package/src/components/chips/features/chip-items.ts +33 -0
  42. package/src/components/chips/features/container.ts +77 -0
  43. package/src/components/chips/features/controller.ts +448 -0
  44. package/src/components/chips/features/index.ts +5 -0
  45. package/src/components/chips/features/label.ts +108 -0
  46. package/src/components/chips/index.ts +11 -0
  47. package/src/components/chips/schema.ts +61 -0
  48. package/src/components/{chip → chips}/types.ts +203 -92
  49. package/src/components/dialog/dialog.ts +99 -16
  50. package/src/components/dialog/index.ts +97 -1
  51. package/src/components/dialog/types.ts +375 -69
  52. package/src/components/divider/config.ts +90 -6
  53. package/src/components/divider/divider.ts +32 -2
  54. package/src/components/divider/features.ts +26 -0
  55. package/src/components/divider/index.ts +30 -0
  56. package/src/components/divider/types.ts +86 -9
  57. package/src/components/extended-fab/api.ts +53 -1
  58. package/src/components/extended-fab/config.ts +29 -1
  59. package/src/components/extended-fab/extended-fab.ts +28 -0
  60. package/src/components/extended-fab/index.ts +36 -0
  61. package/src/components/extended-fab/types.ts +458 -13
  62. package/src/components/fab/api.ts +42 -2
  63. package/src/components/fab/config.ts +29 -1
  64. package/src/components/fab/fab.ts +16 -2
  65. package/src/components/fab/index.ts +35 -0
  66. package/src/components/fab/types.ts +374 -10
  67. package/src/components/list/api.ts +12 -2
  68. package/src/components/list/config.ts +21 -0
  69. package/src/components/list/features.ts +6 -0
  70. package/src/components/list/index.ts +56 -1
  71. package/src/components/list/list-item.ts +46 -2
  72. package/src/components/list/list.ts +73 -2
  73. package/src/components/list/types.ts +172 -0
  74. package/src/components/list/utils.ts +26 -2
  75. package/src/components/menu/api.ts +217 -20
  76. package/src/components/menu/config.ts +27 -0
  77. package/src/components/menu/features/visibility.ts +55 -6
  78. package/src/components/menu/index.ts +64 -0
  79. package/src/components/menu/menu-item.ts +46 -3
  80. package/src/components/menu/menu.ts +77 -1
  81. package/src/components/menu/types.ts +404 -39
  82. package/src/components/sheet/config.ts +1 -2
  83. package/src/components/sheet/features/gestures.ts +1 -1
  84. package/src/components/sheet/features/position.ts +1 -2
  85. package/src/components/sheet/features/state.ts +1 -1
  86. package/src/components/sheet/index.ts +10 -2
  87. package/src/components/sheet/sheet.ts +1 -2
  88. package/src/components/sheet/types.ts +29 -1
  89. package/src/components/slider/api.ts +1 -1
  90. package/src/components/slider/config.ts +1 -1
  91. package/src/components/slider/features/controller.ts +1 -1
  92. package/src/components/slider/features/handlers.ts +1 -1
  93. package/src/components/slider/features/states.ts +1 -1
  94. package/src/components/slider/index.ts +12 -5
  95. package/src/components/slider/schema.ts +1 -1
  96. package/src/components/slider/types.ts +31 -0
  97. package/src/components/tabs/tab-api.ts +1 -1
  98. package/src/components/tabs/types.ts +1 -1
  99. package/src/components/tooltip/api.ts +6 -2
  100. package/src/components/tooltip/config.ts +9 -28
  101. package/src/components/tooltip/index.ts +10 -1
  102. package/src/components/tooltip/types.ts +38 -3
  103. package/src/index.ts +129 -31
  104. package/src/styles/abstract/_mixins.scss +23 -9
  105. package/src/styles/abstract/_variables.scss +14 -4
  106. package/src/styles/components/_card.scss +1 -1
  107. package/src/styles/components/_chip.scss +323 -113
  108. package/src/styles/components/_tabs.scss +1 -1
  109. package/CLAUDE.md +0 -33
  110. package/src/components/checkbox/constants.ts +0 -37
  111. package/src/components/chip/chip-set.ts +0 -225
  112. package/src/components/chip/chip.ts +0 -118
  113. package/src/components/chip/constants.ts +0 -28
  114. package/src/components/chip/index.ts +0 -12
  115. package/src/components/list/constants.ts +0 -116
  116. package/src/components/sheet/constants.ts +0 -20
  117. package/src/components/slider/constants.ts +0 -32
  118. package/src/components/tooltip/constants.ts +0 -27
  119. package/test/components/badge.test.ts +0 -545
  120. package/test/components/bottom-app-bar.test.ts +0 -303
  121. package/test/components/button.test.ts +0 -233
  122. package/test/components/card.test.ts +0 -560
  123. package/test/components/carousel.test.ts +0 -951
  124. package/test/components/checkbox.test.ts +0 -462
  125. package/test/components/chip.test.ts +0 -692
  126. package/test/components/datepicker.test.ts +0 -1124
  127. package/test/components/dialog.test.ts +0 -990
  128. package/test/components/divider.test.ts +0 -412
  129. package/test/components/extended-fab.test.ts +0 -672
  130. package/test/components/fab.test.ts +0 -561
  131. package/test/components/list.test.ts +0 -365
  132. package/test/components/menu.test.ts +0 -718
  133. package/test/components/navigation.test.ts +0 -186
  134. package/test/components/progress.test.ts +0 -567
  135. package/test/components/radios.test.ts +0 -699
  136. package/test/components/search.test.ts +0 -1135
  137. package/test/components/segmented-button.test.ts +0 -732
  138. package/test/components/sheet.test.ts +0 -641
  139. package/test/components/slider.test.ts +0 -1220
  140. package/test/components/snackbar.test.ts +0 -461
  141. package/test/components/switch.test.ts +0 -452
  142. package/test/components/tabs.test.ts +0 -1369
  143. package/test/components/textfield.test.ts +0 -400
  144. package/test/components/timepicker.test.ts +0 -592
  145. package/test/components/tooltip.test.ts +0 -630
  146. package/test/components/top-app-bar.test.ts +0 -566
  147. package/test/core/dom.attributes.test.ts +0 -148
  148. package/test/core/dom.classes.test.ts +0 -152
  149. package/test/core/dom.events.test.ts +0 -243
  150. package/test/core/emitter.test.ts +0 -141
  151. package/test/core/ripple.test.ts +0 -99
  152. package/test/core/state.store.test.ts +0 -189
  153. package/test/core/utils.normalize.test.ts +0 -61
  154. package/test/core/utils.object.test.ts +0 -120
  155. package/test/setup.js +0 -371
  156. package/test/setup.ts +0 -451
  157. package/tsconfig.json +0 -22
  158. package/typedoc.json +0 -28
  159. package/typedoc.simple.json +0 -14
@@ -1,111 +1,296 @@
1
1
  // src/components/checkbox/types.ts
2
2
 
3
3
  /**
4
- * Checkbox variant types
4
+ * Visual variants for checkbox styling
5
+ *
6
+ * Material Design 3 checkboxes can use different visual styles
7
+ * while maintaining the same functionality.
8
+ *
9
+ * @category Components
10
+ */
11
+ export const CHECKBOX_VARIANTS = {
12
+ /** Checkbox with filled background when checked */
13
+ FILLED: 'filled',
14
+ /** Checkbox with outlined style (less prominent) */
15
+ OUTLINED: 'outlined'
16
+ } as const;
17
+
18
+ /**
19
+ * Label position options for the checkbox
20
+ *
21
+ * Controls whether the label appears before or after the checkbox.
22
+ *
23
+ * @category Components
24
+ */
25
+ export const CHECKBOX_LABEL_POSITION = {
26
+ /** Label appears before (to the left of) the checkbox */
27
+ START: 'start',
28
+ /** Label appears after (to the right of) the checkbox (default) */
29
+ END: 'end'
30
+ } as const;
31
+
32
+ /**
33
+ * Checkbox state classes
34
+ *
35
+ * These classes are applied to the checkbox element to reflect its current state.
36
+ * They can be used for styling or for selection in tests.
37
+ *
38
+ * @category Components
39
+ */
40
+ export const CHECKBOX_STATES = {
41
+ /** Applied when the checkbox is checked */
42
+ CHECKED: 'checked',
43
+ /** Applied when the checkbox is in indeterminate state */
44
+ INDETERMINATE: 'indeterminate',
45
+ /** Applied when the checkbox is disabled */
46
+ DISABLED: 'disabled',
47
+ /** Applied when the checkbox has focus */
48
+ FOCUSED: 'focused'
49
+ } as const;
50
+
51
+ /**
52
+ * Checkbox element classes
53
+ *
54
+ * These classes are applied to different parts of the checkbox component.
55
+ * They follow the BEM naming convention used throughout the library.
56
+ *
57
+ * @category Components
58
+ */
59
+ export const CHECKBOX_CLASSES = {
60
+ /** The main checkbox container element */
61
+ ROOT: 'checkbox',
62
+ /** The actual input element (usually hidden) */
63
+ INPUT: 'checkbox-input',
64
+ /** The visual checkbox icon */
65
+ ICON: 'checkbox-icon',
66
+ /** The text label associated with the checkbox */
67
+ LABEL: 'checkbox-label'
68
+ } as const;
69
+
70
+ /**
71
+ * Checkbox variant types - controls the visual style of the checkbox
72
+ *
73
+ * @category Components
74
+ * @remarks
75
+ * - filled: Checkbox with filled background when checked (default)
76
+ * - outlined: Checkbox with outline only, for less visual emphasis
5
77
  */
6
78
  export type CheckboxVariant = 'filled' | 'outlined';
7
79
 
8
80
  /**
9
- * Checkbox label position types
81
+ * Checkbox label position types - controls where the label appears
82
+ *
83
+ * @category Components
84
+ * @remarks
85
+ * - start: Label appears before (to the left of) the checkbox
86
+ * - end: Label appears after (to the right of) the checkbox (default)
10
87
  */
11
88
  export type CheckboxLabelPosition = 'start' | 'end';
12
89
 
13
90
  /**
14
91
  * Configuration interface for the Checkbox component
92
+ *
93
+ * @category Components
94
+ * @description
95
+ * Defines the appearance and behavior of a checkbox component.
96
+ * All properties are optional with sensible defaults.
15
97
  */
16
98
  export interface CheckboxConfig {
17
- /** Input name attribute */
99
+ /**
100
+ * Input name attribute, used for form submission
101
+ * @example "accept-terms"
102
+ */
18
103
  name?: string;
19
104
 
20
- /** Initial checked state */
105
+ /**
106
+ * Initial checked state
107
+ * @default false
108
+ */
21
109
  checked?: boolean;
22
110
 
23
- /** Initial indeterminate state */
111
+ /**
112
+ * Initial indeterminate state (partially checked)
113
+ * Used when a checkbox represents a mixed selection state
114
+ * @default false
115
+ */
24
116
  indeterminate?: boolean;
25
117
 
26
- /** Whether input is required */
118
+ /**
119
+ * Whether input is required for form validation
120
+ * @default false
121
+ */
27
122
  required?: boolean;
28
123
 
29
- /** Whether checkbox is disabled */
124
+ /**
125
+ * Whether checkbox is disabled (non-interactive)
126
+ * @default false
127
+ */
30
128
  disabled?: boolean;
31
129
 
32
- /** Input value attribute */
130
+ /**
131
+ * Input value attribute, used for form submission
132
+ * @example "true" | "selected" | "1"
133
+ */
33
134
  value?: string;
34
135
 
35
- /** Label text */
136
+ /**
137
+ * Label text displayed next to the checkbox
138
+ * @example "Accept terms and conditions"
139
+ */
36
140
  label?: string;
37
141
 
38
- /** Label position (start/end) */
142
+ /**
143
+ * Label position (start/end)
144
+ * Controls whether the label appears before or after the checkbox
145
+ * @default "end"
146
+ */
39
147
  labelPosition?: CheckboxLabelPosition | string;
40
148
 
41
- /** Visual variant */
149
+ /**
150
+ * Visual variant (filled/outlined)
151
+ * @default "filled"
152
+ */
42
153
  variant?: CheckboxVariant | string;
43
154
 
44
- /** Additional CSS classes */
155
+ /**
156
+ * Additional CSS classes to apply to the checkbox
157
+ * @example "terms-checkbox primary-checkbox"
158
+ */
45
159
  class?: string;
46
160
 
47
- /** Prefix for class names */
161
+ /**
162
+ * CSS class prefix for all checkbox classes
163
+ * @default "mtrl"
164
+ */
48
165
  prefix?: string;
49
166
 
50
- /** Component name */
167
+ /**
168
+ * Component name used in CSS class generation
169
+ * @default "checkbox"
170
+ * @internal
171
+ */
51
172
  componentName?: string;
52
173
  }
53
174
 
54
175
  /**
55
176
  * Checkbox component interface
177
+ *
178
+ * Provides methods for controlling a Material Design 3 checkbox
179
+ *
180
+ * @category Components
56
181
  */
57
182
  export interface CheckboxComponent {
58
- /** The root element of the checkbox */
183
+ /**
184
+ * The checkbox's root DOM element (container)
185
+ */
59
186
  element: HTMLElement;
60
187
 
61
- /** The input element */
188
+ /**
189
+ * The actual input element (native checkbox)
190
+ */
62
191
  input: HTMLInputElement;
63
192
 
64
- /** Gets the checkbox's value */
193
+ /**
194
+ * Gets the checkbox's current value attribute
195
+ * @returns Current value of the checkbox
196
+ */
65
197
  getValue: () => string;
66
198
 
67
- /** Sets the checkbox's value */
199
+ /**
200
+ * Sets the checkbox's value attribute
201
+ * @param value - New value to set
202
+ * @returns Checkbox component for method chaining
203
+ */
68
204
  setValue: (value: string) => CheckboxComponent;
69
205
 
70
- /** Checks the checkbox */
206
+ /**
207
+ * Checks the checkbox (sets checked=true)
208
+ * @returns Checkbox component for method chaining
209
+ */
71
210
  check: () => CheckboxComponent;
72
211
 
73
- /** Unchecks the checkbox */
212
+ /**
213
+ * Unchecks the checkbox (sets checked=false)
214
+ * @returns Checkbox component for method chaining
215
+ */
74
216
  uncheck: () => CheckboxComponent;
75
217
 
76
- /** Toggles the checkbox's checked state */
218
+ /**
219
+ * Toggles the checkbox's checked state
220
+ * @returns Checkbox component for method chaining
221
+ */
77
222
  toggle: () => CheckboxComponent;
78
223
 
79
- /** Returns whether the checkbox is checked */
224
+ /**
225
+ * Checks if the checkbox is currently checked
226
+ * @returns True if checkbox is checked, false otherwise
227
+ */
80
228
  isChecked: () => boolean;
81
229
 
82
- /** Sets the checkbox's indeterminate state */
230
+ /**
231
+ * Sets the checkbox's indeterminate state
232
+ * An indeterminate checkbox appears partially checked
233
+ * and is used to represent a mixed selection state
234
+ *
235
+ * @param state - Whether to set indeterminate state
236
+ * @returns Checkbox component for method chaining
237
+ */
83
238
  setIndeterminate: (state: boolean) => CheckboxComponent;
84
239
 
85
- /** Sets the checkbox's label text */
240
+ /**
241
+ * Sets the checkbox's label text
242
+ * @param text - New label text
243
+ * @returns Checkbox component for method chaining
244
+ */
86
245
  setLabel: (text: string) => CheckboxComponent;
87
246
 
88
- /** Gets the checkbox's label text */
247
+ /**
248
+ * Gets the checkbox's current label text
249
+ * @returns Current label text
250
+ */
89
251
  getLabel: () => string;
90
252
 
91
- /** Adds event listener */
253
+ /**
254
+ * Adds an event listener to the checkbox
255
+ * @param event - Event name ('change', 'click', etc.)
256
+ * @param handler - Event handler function
257
+ * @returns Checkbox component for method chaining
258
+ * @example
259
+ * checkbox.on('change', (e) => console.log('Checkbox state:', e.target.checked));
260
+ */
92
261
  on: (event: string, handler: Function) => CheckboxComponent;
93
262
 
94
- /** Removes event listener */
263
+ /**
264
+ * Removes an event listener from the checkbox
265
+ * @param event - Event name
266
+ * @param handler - Event handler function
267
+ * @returns Checkbox component for method chaining
268
+ */
95
269
  off: (event: string, handler: Function) => CheckboxComponent;
96
270
 
97
- /** Enables the checkbox */
271
+ /**
272
+ * Enables the checkbox, making it interactive
273
+ * @returns Checkbox component for method chaining
274
+ */
98
275
  enable: () => CheckboxComponent;
99
276
 
100
- /** Disables the checkbox */
277
+ /**
278
+ * Disables the checkbox, making it non-interactive
279
+ * @returns Checkbox component for method chaining
280
+ */
101
281
  disable: () => CheckboxComponent;
102
282
 
103
- /** Destroys the checkbox component and cleans up resources */
283
+ /**
284
+ * Destroys the checkbox component and cleans up resources
285
+ * Removes event listeners and DOM references
286
+ */
104
287
  destroy: () => void;
105
288
  }
106
289
 
107
290
  /**
108
- * API options interface
291
+ * API options interface for internal use
292
+ * @category Components
293
+ * @internal
109
294
  */
110
295
  export interface ApiOptions {
111
296
  disabled: {
@@ -124,7 +309,9 @@ export interface ApiOptions {
124
309
  }
125
310
 
126
311
  /**
127
- * Base component interface
312
+ * Base component interface for internal composition
313
+ * @category Components
314
+ * @internal
128
315
  */
129
316
  export interface BaseComponent {
130
317
  element: HTMLElement;
@@ -0,0 +1,194 @@
1
+ // src/components/chips/api.ts
2
+ import { ChipsComponent, ChipComponent } from './types';
3
+
4
+ /**
5
+ * API options interface - structured by feature area
6
+ */
7
+ interface ApiOptions {
8
+ chips: {
9
+ addChip: (chipConfig: any) => ChipComponent;
10
+ removeChip: (chipOrIndex: ChipComponent | number) => void;
11
+ getChips: () => ChipComponent[];
12
+ getSelectedChips: () => ChipComponent[];
13
+ getSelectedValues: () => (string | null)[];
14
+ selectByValue: (values: string | string[], triggerEvent?: boolean) => void;
15
+ clearSelection: () => void;
16
+ scrollToChip: (chipOrIndex: ChipComponent | number) => void;
17
+ };
18
+ layout: {
19
+ setScrollable: (isScrollable: boolean) => any;
20
+ isScrollable: () => boolean;
21
+ setVertical: (isVertical: boolean) => any;
22
+ isVertical: () => boolean;
23
+ };
24
+ label: {
25
+ setText: (text: string) => any;
26
+ getText: () => string;
27
+ setPosition: (position: 'start' | 'end') => any;
28
+ getPosition: () => string;
29
+ };
30
+ keyboard: {
31
+ enableKeyboardNavigation: () => void;
32
+ disableKeyboardNavigation: () => void;
33
+ };
34
+ events: {
35
+ on: (event: string, handler: Function) => void;
36
+ off: (event: string, handler: Function) => void;
37
+ };
38
+ lifecycle: {
39
+ destroy: () => void;
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Enhances a chips component with a streamlined API
45
+ * @param {ApiOptions} options - API configuration options
46
+ * @returns {Function} Higher-order function that adds API methods to component
47
+ * @internal This is an internal utility for the Chips component
48
+ */
49
+ export const withAPI = (options: ApiOptions) =>
50
+ (component: { element: HTMLElement }): ChipsComponent => {
51
+ return {
52
+ ...component as any,
53
+
54
+ // Element access
55
+ element: component.element,
56
+
57
+ // Chip management
58
+ addChip(chipConfig) {
59
+ if (options.chips && typeof options.chips.addChip === 'function') {
60
+ options.chips.addChip(chipConfig);
61
+ }
62
+ return this;
63
+ },
64
+
65
+ removeChip(chipOrIndex) {
66
+ if (options.chips && typeof options.chips.removeChip === 'function') {
67
+ options.chips.removeChip(chipOrIndex);
68
+ }
69
+ return this;
70
+ },
71
+
72
+ getChips() {
73
+ if (options.chips && typeof options.chips.getChips === 'function') {
74
+ return options.chips.getChips();
75
+ }
76
+ return [];
77
+ },
78
+
79
+ getSelectedChips() {
80
+ if (options.chips && typeof options.chips.getSelectedChips === 'function') {
81
+ return options.chips.getSelectedChips();
82
+ }
83
+ return [];
84
+ },
85
+
86
+ getSelectedValues() {
87
+ if (options.chips && typeof options.chips.getSelectedValues === 'function') {
88
+ return options.chips.getSelectedValues();
89
+ }
90
+ return [];
91
+ },
92
+
93
+ /**
94
+ * Selects chips by their values
95
+ * @param values - Value or array of values to select
96
+ * @param triggerEvent - Whether to trigger change event (default: true)
97
+ * @returns The chips instance for chaining
98
+ */
99
+ selectByValue(values, triggerEvent = true) {
100
+ if (options.chips && typeof options.chips.selectByValue === 'function') {
101
+ options.chips.selectByValue(values, triggerEvent);
102
+ }
103
+ return this;
104
+ },
105
+
106
+ clearSelection() {
107
+ if (options.chips && typeof options.chips.clearSelection === 'function') {
108
+ options.chips.clearSelection();
109
+ }
110
+ return this;
111
+ },
112
+
113
+ // Layout management
114
+ setScrollable(isScrollable) {
115
+ if (options.layout && typeof options.layout.setScrollable === 'function') {
116
+ options.layout.setScrollable(isScrollable);
117
+ }
118
+ return this;
119
+ },
120
+
121
+ setVertical(isVertical) {
122
+ if (options.layout && typeof options.layout.setVertical === 'function') {
123
+ options.layout.setVertical(isVertical);
124
+ }
125
+ return this;
126
+ },
127
+
128
+ // Label management
129
+ setLabel(text) {
130
+ if (options.label && typeof options.label.setText === 'function') {
131
+ options.label.setText(text);
132
+ }
133
+ return this;
134
+ },
135
+
136
+ getLabel() {
137
+ if (options.label && typeof options.label.getText === 'function') {
138
+ return options.label.getText();
139
+ }
140
+ return '';
141
+ },
142
+
143
+ setLabelPosition(position) {
144
+ if (options.label && typeof options.label.setPosition === 'function') {
145
+ options.label.setPosition(position);
146
+ }
147
+ return this;
148
+ },
149
+
150
+ getLabelPosition() {
151
+ if (options.label && typeof options.label.getPosition === 'function') {
152
+ return options.label.getPosition();
153
+ }
154
+ return 'start';
155
+ },
156
+
157
+ // Navigation
158
+ scrollToChip(chipOrIndex) {
159
+ if (options.chips && typeof options.chips.scrollToChip === 'function') {
160
+ options.chips.scrollToChip(chipOrIndex);
161
+ }
162
+ return this;
163
+ },
164
+
165
+ enableKeyboardNavigation() {
166
+ if (options.keyboard && typeof options.keyboard.enableKeyboardNavigation === 'function') {
167
+ options.keyboard.enableKeyboardNavigation();
168
+ }
169
+ return this;
170
+ },
171
+
172
+ // Event management
173
+ on(event, handler) {
174
+ if (options.events && typeof options.events.on === 'function') {
175
+ options.events.on(event, handler);
176
+ }
177
+ return this;
178
+ },
179
+
180
+ off(event, handler) {
181
+ if (options.events && typeof options.events.off === 'function') {
182
+ options.events.off(event, handler);
183
+ }
184
+ return this;
185
+ },
186
+
187
+ // Lifecycle management
188
+ destroy() {
189
+ if (options.lifecycle && typeof options.lifecycle.destroy === 'function') {
190
+ options.lifecycle.destroy();
191
+ }
192
+ }
193
+ };
194
+ };
@@ -27,16 +27,56 @@ export const withAPI = ({ disabled, lifecycle }: ApiOptions) =>
27
27
  // Track selected state internally
28
28
  let isSelected = component.element.classList.contains(`${component.getClass('chip')}--selected`);
29
29
 
30
+ // Store the value internally as well to ensure reliability
31
+ let chipValue = component.element.getAttribute('data-value') || null;
32
+
30
33
  return {
31
34
  ...component as any,
32
35
  element: component.element,
33
36
 
34
37
  getValue() {
35
- return component.element.getAttribute('data-value') || null;
38
+ // First try to get from the element's attribute
39
+ const attrValue = component.element.getAttribute('data-value');
40
+
41
+ // If we have an attribute value, update our internal value and return it
42
+ if (attrValue !== null) {
43
+ chipValue = attrValue;
44
+ return attrValue;
45
+ }
46
+
47
+ // If we have an internal value, set it on the element and return it
48
+ if (chipValue !== null) {
49
+ component.element.setAttribute('data-value', chipValue);
50
+ return chipValue;
51
+ }
52
+
53
+ // If we have text content, derive a value from it
54
+ const textElement = component.element.querySelector(`.${component.getClass('chip')}-text`);
55
+ if (textElement && textElement.textContent) {
56
+ // Convert text like "Ocean Theme" to "ocean"
57
+ const text = textElement.textContent;
58
+ if (text.includes(' Theme')) {
59
+ chipValue = text.replace(' Theme', '').toLowerCase();
60
+ } else {
61
+ chipValue = text.toLowerCase().replace(/\s+/g, '-');
62
+ }
63
+
64
+ // Set the derived value on the element
65
+ component.element.setAttribute('data-value', chipValue);
66
+ return chipValue;
67
+ }
68
+
69
+ return null;
36
70
  },
37
71
 
38
72
  setValue(value: string) {
39
- component.element.setAttribute('data-value', value || '');
73
+ if (value !== null && value !== undefined) {
74
+ chipValue = value;
75
+ component.element.setAttribute('data-value', value);
76
+ } else {
77
+ chipValue = null;
78
+ component.element.removeAttribute('data-value');
79
+ }
40
80
  return this;
41
81
  },
42
82