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,699 +0,0 @@
1
- // test/components/radios.test.ts
2
- import { describe, test, expect } from 'bun:test';
3
- import {
4
- type RadiosComponent,
5
- type RadiosConfig,
6
- type RadioOptionConfig,
7
- type RadioItem
8
- } from '../../src/components/radios/types';
9
-
10
- // Mock radios implementation
11
- const createMockRadios = (config: RadiosConfig): RadiosComponent => {
12
- // Create main container element
13
- const element = document.createElement('div');
14
- element.className = 'mtrl-radios';
15
-
16
- if (config.class) {
17
- const classes = config.class.split(' ');
18
- classes.forEach(className => element.classList.add(className));
19
- }
20
-
21
- if (config.disabled) {
22
- element.classList.add('mtrl-radios--disabled');
23
- }
24
-
25
- // Store settings
26
- const settings = {
27
- name: config.name,
28
- componentName: config.componentName || 'radios',
29
- prefix: config.prefix || 'mtrl',
30
- ripple: config.ripple !== undefined ? config.ripple : true,
31
- disabled: config.disabled || false,
32
- value: config.value || ''
33
- };
34
-
35
- // Create radio items
36
- const radios: RadioItem[] = [];
37
-
38
- // Track event handlers
39
- const eventHandlers: Record<string, Function[]> = {};
40
-
41
- // Emit an event
42
- const emit = (event: string, data?: any) => {
43
- if (eventHandlers[event]) {
44
- eventHandlers[event].forEach(handler => handler(data));
45
- }
46
- };
47
-
48
- // Helper function to create a radio item
49
- const createRadioItem = (option: RadioOptionConfig): RadioItem => {
50
- const radioElement = document.createElement('div');
51
- radioElement.className = 'mtrl-radio';
52
-
53
- const input = document.createElement('input');
54
- input.type = 'radio';
55
- input.name = settings.name;
56
- input.value = option.value;
57
- input.className = 'mtrl-radio__input';
58
- input.checked = option.value === settings.value;
59
-
60
- if (option.disabled || settings.disabled) {
61
- input.disabled = true;
62
- radioElement.classList.add('mtrl-radio--disabled');
63
- }
64
-
65
- const label = document.createElement('label');
66
- label.className = 'mtrl-radio__label';
67
- label.textContent = option.label;
68
- label.setAttribute('for', `${settings.name}-${option.value}`);
69
-
70
- if (option.labelBefore) {
71
- radioElement.classList.add('mtrl-radio--label-before');
72
- radioElement.appendChild(label);
73
- radioElement.appendChild(input);
74
- } else {
75
- radioElement.appendChild(input);
76
- radioElement.appendChild(label);
77
- }
78
-
79
- // Create ripple element if enabled
80
- if (settings.ripple) {
81
- const ripple = document.createElement('span');
82
- ripple.className = 'mtrl-radio__ripple';
83
- radioElement.appendChild(ripple);
84
- }
85
-
86
- // Handle change event
87
- const handleChange = () => {
88
- if (input.checked) {
89
- settings.value = option.value;
90
-
91
- // Update checked state of all radios
92
- radios.forEach(radio => {
93
- radio.input.checked = radio.input.value === settings.value;
94
- });
95
-
96
- emit('change', { value: settings.value });
97
- }
98
- };
99
-
100
- input.addEventListener('change', handleChange);
101
-
102
- const radioItem: RadioItem = {
103
- element: radioElement,
104
- input,
105
- label,
106
- config: { ...option },
107
- destroy: () => {
108
- input.removeEventListener('change', handleChange);
109
- if (radioElement.parentNode) {
110
- radioElement.parentNode.removeChild(radioElement);
111
- }
112
- }
113
- };
114
-
115
- return radioItem;
116
- };
117
-
118
- // Add initial options
119
- if (config.options) {
120
- config.options.forEach(option => {
121
- const radioItem = createRadioItem(option);
122
- radios.push(radioItem);
123
- element.appendChild(radioItem.element);
124
- });
125
- }
126
-
127
- // Create the radios component
128
- const radiosComponent: RadiosComponent = {
129
- element,
130
- radios,
131
-
132
- lifecycle: {
133
- destroy: () => {
134
- radiosComponent.destroy();
135
- }
136
- },
137
-
138
- getClass: (name: string) => {
139
- const prefix = settings.prefix;
140
- return name ? `${prefix}-${name}` : `${prefix}-radios`;
141
- },
142
-
143
- getValue: () => settings.value,
144
-
145
- setValue: (value: string) => {
146
- settings.value = value;
147
-
148
- // Update radio inputs
149
- radios.forEach(radio => {
150
- radio.input.checked = radio.config.value === value;
151
- });
152
-
153
- emit('change', { value });
154
-
155
- return radiosComponent;
156
- },
157
-
158
- getSelected: () => {
159
- const selectedRadio = radios.find(radio => radio.config.value === settings.value);
160
- return selectedRadio ? { ...selectedRadio.config } : null;
161
- },
162
-
163
- addOption: (option: RadioOptionConfig) => {
164
- // Check if option with this value already exists
165
- const existingIndex = radios.findIndex(radio => radio.config.value === option.value);
166
-
167
- if (existingIndex === -1) {
168
- const radioItem = createRadioItem(option);
169
- radios.push(radioItem);
170
- element.appendChild(radioItem.element);
171
- }
172
-
173
- return radiosComponent;
174
- },
175
-
176
- removeOption: (value: string) => {
177
- const index = radios.findIndex(radio => radio.config.value === value);
178
-
179
- if (index !== -1) {
180
- const radioItem = radios[index];
181
- radioItem.destroy();
182
- radios.splice(index, 1);
183
-
184
- // If we removed the selected option, clear the value
185
- if (settings.value === value) {
186
- settings.value = '';
187
- }
188
- }
189
-
190
- return radiosComponent;
191
- },
192
-
193
- enable: () => {
194
- settings.disabled = false;
195
- element.classList.remove('mtrl-radios--disabled');
196
-
197
- radios.forEach(radio => {
198
- if (!radio.config.disabled) {
199
- radio.input.disabled = false;
200
- radio.element.classList.remove('mtrl-radio--disabled');
201
- }
202
- });
203
-
204
- return radiosComponent;
205
- },
206
-
207
- disable: () => {
208
- settings.disabled = true;
209
- element.classList.add('mtrl-radios--disabled');
210
-
211
- radios.forEach(radio => {
212
- radio.input.disabled = true;
213
- radio.element.classList.add('mtrl-radio--disabled');
214
- });
215
-
216
- return radiosComponent;
217
- },
218
-
219
- enableOption: (value: string) => {
220
- const radio = radios.find(r => r.config.value === value);
221
-
222
- if (radio) {
223
- radio.config.disabled = false;
224
-
225
- if (!settings.disabled) {
226
- radio.input.disabled = false;
227
- radio.element.classList.remove('mtrl-radio--disabled');
228
- }
229
- }
230
-
231
- return radiosComponent;
232
- },
233
-
234
- disableOption: (value: string) => {
235
- const radio = radios.find(r => r.config.value === value);
236
-
237
- if (radio) {
238
- radio.config.disabled = true;
239
- radio.input.disabled = true;
240
- radio.element.classList.add('mtrl-radio--disabled');
241
- }
242
-
243
- return radiosComponent;
244
- },
245
-
246
- destroy: () => {
247
- // Clean up radio items
248
- radios.forEach(radio => radio.destroy());
249
- radios.length = 0;
250
-
251
- // Remove element from DOM if it has a parent
252
- if (element.parentNode) {
253
- element.parentNode.removeChild(element);
254
- }
255
-
256
- // Clear event handlers
257
- for (const event in eventHandlers) {
258
- eventHandlers[event] = [];
259
- }
260
- },
261
-
262
- on: (event: string, handler: Function) => {
263
- if (!eventHandlers[event]) {
264
- eventHandlers[event] = [];
265
- }
266
-
267
- eventHandlers[event].push(handler);
268
- return radiosComponent;
269
- },
270
-
271
- off: (event: string, handler: Function) => {
272
- if (eventHandlers[event]) {
273
- eventHandlers[event] = eventHandlers[event].filter(h => h !== handler);
274
- }
275
-
276
- return radiosComponent;
277
- }
278
- };
279
-
280
- return radiosComponent;
281
- };
282
-
283
- describe('Radios Component', () => {
284
- test('should create a radios component with options', () => {
285
- const options: RadioOptionConfig[] = [
286
- { value: 'option1', label: 'Option 1' },
287
- { value: 'option2', label: 'Option 2' },
288
- { value: 'option3', label: 'Option 3' }
289
- ];
290
-
291
- const radios = createMockRadios({
292
- name: 'test-radios',
293
- options
294
- });
295
-
296
- expect(radios.element).toBeDefined();
297
- expect(radios.element.tagName).toBe('DIV');
298
- expect(radios.element.className).toContain('mtrl-radios');
299
-
300
- expect(radios.radios.length).toBe(3);
301
-
302
- const radioElements = radios.element.querySelectorAll('.mtrl-radio');
303
- expect(radioElements.length).toBe(3);
304
-
305
- const inputs = radios.element.querySelectorAll('input[type="radio"]');
306
- expect(inputs.length).toBe(3);
307
-
308
- inputs.forEach((input: Element, index: number) => {
309
- expect((input as HTMLInputElement).name).toBe('test-radios');
310
- expect((input as HTMLInputElement).value).toBe(options[index].value);
311
-
312
- const label = input.parentElement?.querySelector('label');
313
- expect(label?.textContent).toBe(options[index].label);
314
- });
315
- });
316
-
317
- test('should set initial selected value', () => {
318
- const options: RadioOptionConfig[] = [
319
- { value: 'option1', label: 'Option 1' },
320
- { value: 'option2', label: 'Option 2' },
321
- { value: 'option3', label: 'Option 3' }
322
- ];
323
-
324
- const radios = createMockRadios({
325
- name: 'test-radios',
326
- options,
327
- value: 'option2'
328
- });
329
-
330
- expect(radios.getValue()).toBe('option2');
331
-
332
- const inputs = radios.element.querySelectorAll('input[type="radio"]');
333
- expect((inputs[0] as HTMLInputElement).checked).toBe(false);
334
- expect((inputs[1] as HTMLInputElement).checked).toBe(true);
335
- expect((inputs[2] as HTMLInputElement).checked).toBe(false);
336
- });
337
-
338
- test('should create with label before radio when configured', () => {
339
- const options: RadioOptionConfig[] = [
340
- { value: 'option1', label: 'Option 1', labelBefore: true }
341
- ];
342
-
343
- const radios = createMockRadios({
344
- name: 'test-radios',
345
- options
346
- });
347
-
348
- const radioElement = radios.element.querySelector('.mtrl-radio');
349
- expect(radioElement?.className).toContain('mtrl-radio--label-before');
350
-
351
- // First child should be label when labelBefore is true
352
- const firstChild = radioElement?.firstChild;
353
- expect(firstChild?.nodeName).toBe('LABEL');
354
- });
355
-
356
- test('should disable specific options', () => {
357
- const options: RadioOptionConfig[] = [
358
- { value: 'option1', label: 'Option 1' },
359
- { value: 'option2', label: 'Option 2', disabled: true },
360
- { value: 'option3', label: 'Option 3' }
361
- ];
362
-
363
- const radios = createMockRadios({
364
- name: 'test-radios',
365
- options
366
- });
367
-
368
- const inputs = radios.element.querySelectorAll('input[type="radio"]');
369
- expect((inputs[0] as HTMLInputElement).disabled).toBe(false);
370
- expect((inputs[1] as HTMLInputElement).disabled).toBe(true);
371
- expect((inputs[2] as HTMLInputElement).disabled).toBe(false);
372
-
373
- const radioElements = radios.element.querySelectorAll('.mtrl-radio');
374
- expect(radioElements[1].className).toContain('mtrl-radio--disabled');
375
- });
376
-
377
- test('should disable all options when component is disabled', () => {
378
- const options: RadioOptionConfig[] = [
379
- { value: 'option1', label: 'Option 1' },
380
- { value: 'option2', label: 'Option 2' },
381
- { value: 'option3', label: 'Option 3' }
382
- ];
383
-
384
- const radios = createMockRadios({
385
- name: 'test-radios',
386
- options,
387
- disabled: true
388
- });
389
-
390
- expect(radios.element.className).toContain('mtrl-radios--disabled');
391
-
392
- const inputs = radios.element.querySelectorAll('input[type="radio"]');
393
- inputs.forEach(input => {
394
- expect((input as HTMLInputElement).disabled).toBe(true);
395
- });
396
-
397
- const radioElements = radios.element.querySelectorAll('.mtrl-radio');
398
- radioElements.forEach(radio => {
399
- expect(radio.className).toContain('mtrl-radio--disabled');
400
- });
401
- });
402
-
403
- test('should create ripple effect by default', () => {
404
- const radios = createMockRadios({
405
- name: 'test-radios',
406
- options: [{ value: 'option1', label: 'Option 1' }]
407
- });
408
-
409
- const ripples = radios.element.querySelectorAll('.mtrl-radio__ripple');
410
- expect(ripples.length).toBe(1);
411
- });
412
-
413
- test('should not create ripple when disabled', () => {
414
- const radios = createMockRadios({
415
- name: 'test-radios',
416
- options: [{ value: 'option1', label: 'Option 1' }],
417
- ripple: false
418
- });
419
-
420
- const ripples = radios.element.querySelectorAll('.mtrl-radio__ripple');
421
- expect(ripples.length).toBe(0);
422
- });
423
-
424
- test('should change selected value', () => {
425
- const options: RadioOptionConfig[] = [
426
- { value: 'option1', label: 'Option 1' },
427
- { value: 'option2', label: 'Option 2' },
428
- { value: 'option3', label: 'Option 3' }
429
- ];
430
-
431
- const radios = createMockRadios({
432
- name: 'test-radios',
433
- options
434
- });
435
-
436
- expect(radios.getValue()).toBe('');
437
-
438
- radios.setValue('option2');
439
-
440
- expect(radios.getValue()).toBe('option2');
441
-
442
- const inputs = radios.element.querySelectorAll('input[type="radio"]');
443
- expect((inputs[0] as HTMLInputElement).checked).toBe(false);
444
- expect((inputs[1] as HTMLInputElement).checked).toBe(true);
445
- expect((inputs[2] as HTMLInputElement).checked).toBe(false);
446
- });
447
-
448
- test('should get selected option config', () => {
449
- const options: RadioOptionConfig[] = [
450
- { value: 'option1', label: 'Option 1' },
451
- { value: 'option2', label: 'Option 2' },
452
- { value: 'option3', label: 'Option 3' }
453
- ];
454
-
455
- const radios = createMockRadios({
456
- name: 'test-radios',
457
- options,
458
- value: 'option2'
459
- });
460
-
461
- const selected = radios.getSelected();
462
- expect(selected).toEqual(options[1]);
463
- });
464
-
465
- test('should add a new option', () => {
466
- const options: RadioOptionConfig[] = [
467
- { value: 'option1', label: 'Option 1' },
468
- { value: 'option2', label: 'Option 2' }
469
- ];
470
-
471
- const radios = createMockRadios({
472
- name: 'test-radios',
473
- options
474
- });
475
-
476
- expect(radios.radios.length).toBe(2);
477
-
478
- const newOption: RadioOptionConfig = {
479
- value: 'option3',
480
- label: 'Option 3'
481
- };
482
-
483
- radios.addOption(newOption);
484
-
485
- expect(radios.radios.length).toBe(3);
486
-
487
- const radioElements = radios.element.querySelectorAll('.mtrl-radio');
488
- expect(radioElements.length).toBe(3);
489
-
490
- const lastInput = radios.radios[2].input;
491
- expect(lastInput.value).toBe('option3');
492
-
493
- const lastLabel = radios.radios[2].label;
494
- expect(lastLabel.textContent).toBe('Option 3');
495
- });
496
-
497
- test('should remove an option', () => {
498
- const options: RadioOptionConfig[] = [
499
- { value: 'option1', label: 'Option 1' },
500
- { value: 'option2', label: 'Option 2' },
501
- { value: 'option3', label: 'Option 3' }
502
- ];
503
-
504
- const radios = createMockRadios({
505
- name: 'test-radios',
506
- options
507
- });
508
-
509
- expect(radios.radios.length).toBe(3);
510
-
511
- radios.removeOption('option2');
512
-
513
- expect(radios.radios.length).toBe(2);
514
-
515
- const radioElements = radios.element.querySelectorAll('.mtrl-radio');
516
- expect(radioElements.length).toBe(2);
517
-
518
- const remainingValues = radios.radios.map(radio => radio.config.value);
519
- expect(remainingValues).toEqual(['option1', 'option3']);
520
- });
521
-
522
- test('should clear value when selected option is removed', () => {
523
- const options: RadioOptionConfig[] = [
524
- { value: 'option1', label: 'Option 1' },
525
- { value: 'option2', label: 'Option 2' }
526
- ];
527
-
528
- const radios = createMockRadios({
529
- name: 'test-radios',
530
- options,
531
- value: 'option2'
532
- });
533
-
534
- expect(radios.getValue()).toBe('option2');
535
-
536
- radios.removeOption('option2');
537
-
538
- expect(radios.getValue()).toBe('');
539
- });
540
-
541
- test('should enable and disable the component', () => {
542
- const options: RadioOptionConfig[] = [
543
- { value: 'option1', label: 'Option 1' },
544
- { value: 'option2', label: 'Option 2' }
545
- ];
546
-
547
- const radios = createMockRadios({
548
- name: 'test-radios',
549
- options
550
- });
551
-
552
- expect(radios.element.className).not.toContain('mtrl-radios--disabled');
553
-
554
- radios.disable();
555
-
556
- expect(radios.element.className).toContain('mtrl-radios--disabled');
557
-
558
- const inputs = radios.element.querySelectorAll('input[type="radio"]');
559
- inputs.forEach(input => {
560
- expect((input as HTMLInputElement).disabled).toBe(true);
561
- });
562
-
563
- radios.enable();
564
-
565
- expect(radios.element.className).not.toContain('mtrl-radios--disabled');
566
-
567
- inputs.forEach(input => {
568
- expect((input as HTMLInputElement).disabled).toBe(false);
569
- });
570
- });
571
-
572
- test('should enable and disable specific options', () => {
573
- const options: RadioOptionConfig[] = [
574
- { value: 'option1', label: 'Option 1' },
575
- { value: 'option2', label: 'Option 2' }
576
- ];
577
-
578
- const radios = createMockRadios({
579
- name: 'test-radios',
580
- options
581
- });
582
-
583
- radios.disableOption('option1');
584
-
585
- const input1 = radios.radios[0].input;
586
- const input2 = radios.radios[1].input;
587
-
588
- expect(input1.disabled).toBe(true);
589
- expect(input2.disabled).toBe(false);
590
-
591
- expect(radios.radios[0].element.className).toContain('mtrl-radio--disabled');
592
- expect(radios.radios[1].element.className).not.toContain('mtrl-radio--disabled');
593
-
594
- radios.enableOption('option1');
595
-
596
- expect(input1.disabled).toBe(false);
597
- expect(radios.radios[0].element.className).not.toContain('mtrl-radio--disabled');
598
- });
599
-
600
- test('should emit change events', () => {
601
- const options: RadioOptionConfig[] = [
602
- { value: 'option1', label: 'Option 1' },
603
- { value: 'option2', label: 'Option 2' }
604
- ];
605
-
606
- const radios = createMockRadios({
607
- name: 'test-radios',
608
- options
609
- });
610
-
611
- let eventFired = false;
612
- let eventValue = '';
613
-
614
- radios.on('change', (data) => {
615
- eventFired = true;
616
- eventValue = data.value;
617
- });
618
-
619
- radios.setValue('option2');
620
-
621
- expect(eventFired).toBe(true);
622
- expect(eventValue).toBe('option2');
623
- });
624
-
625
- test('should handle input change events', () => {
626
- const options: RadioOptionConfig[] = [
627
- { value: 'option1', label: 'Option 1' },
628
- { value: 'option2', label: 'Option 2' }
629
- ];
630
-
631
- const radios = createMockRadios({
632
- name: 'test-radios',
633
- options
634
- });
635
-
636
- let eventFired = false;
637
- let eventValue = '';
638
-
639
- radios.on('change', (data) => {
640
- eventFired = true;
641
- eventValue = data.value;
642
- });
643
-
644
- // Simulate radio button change
645
- const input = radios.radios[1].input;
646
- input.checked = true;
647
- input.dispatchEvent(new Event('change'));
648
-
649
- expect(eventFired).toBe(true);
650
- expect(eventValue).toBe('option2');
651
- expect(radios.getValue()).toBe('option2');
652
- });
653
-
654
- test('should remove event listeners', () => {
655
- const radios = createMockRadios({
656
- name: 'test-radios',
657
- options: [
658
- { value: 'option1', label: 'Option 1' },
659
- { value: 'option2', label: 'Option 2' }
660
- ]
661
- });
662
-
663
- let eventCount = 0;
664
-
665
- const handler = () => {
666
- eventCount++;
667
- };
668
-
669
- radios.on('change', handler);
670
-
671
- radios.setValue('option1');
672
- expect(eventCount).toBe(1);
673
-
674
- radios.off('change', handler);
675
-
676
- radios.setValue('option2');
677
- expect(eventCount).toBe(1); // Count should not increase
678
- });
679
-
680
- test('should be properly destroyed', () => {
681
- const radios = createMockRadios({
682
- name: 'test-radios',
683
- options: [
684
- { value: 'option1', label: 'Option 1' },
685
- { value: 'option2', label: 'Option 2' }
686
- ]
687
- });
688
-
689
- document.body.appendChild(radios.element);
690
-
691
- expect(document.body.contains(radios.element)).toBe(true);
692
- expect(radios.radios.length).toBe(2);
693
-
694
- radios.destroy();
695
-
696
- expect(document.body.contains(radios.element)).toBe(false);
697
- expect(radios.radios.length).toBe(0);
698
- });
699
- });