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.
- package/.env +15 -0
- package/CONTRIBUTING.md +8 -8
- package/DOCS.md +3 -3
- package/README.md +43 -20
- package/TESTING.md +128 -18
- package/dist/index.js +14865 -0
- package/git-user-stats.js +545 -0
- package/index.ts +9 -67
- package/package.json +8 -3
- package/src/components/badge/api.ts +15 -1
- package/src/components/badge/badge.ts +43 -4
- package/src/components/badge/config.ts +40 -8
- package/src/components/badge/index.ts +64 -3
- package/src/components/badge/types.ts +175 -33
- package/src/components/button/api.ts +63 -1
- package/src/components/button/button.ts +39 -3
- package/src/components/button/config.ts +21 -4
- package/src/components/button/index.ts +26 -1
- package/src/components/button/types.ts +7 -1
- package/src/components/card/api.ts +78 -9
- package/src/components/card/card.ts +58 -3
- package/src/components/card/config.ts +41 -11
- package/src/components/card/features.ts +39 -12
- package/src/components/card/index.ts +84 -19
- package/src/components/card/types.ts +218 -29
- package/src/components/carousel/carousel.ts +92 -28
- package/src/components/carousel/constants.ts +107 -21
- package/src/components/carousel/index.ts +31 -13
- package/src/components/checkbox/checkbox.ts +83 -16
- package/src/components/checkbox/index.ts +43 -1
- package/src/components/checkbox/types.ts +219 -32
- package/src/components/chips/api.ts +194 -0
- package/src/components/{chip → chips/chip}/api.ts +42 -2
- package/src/components/chips/chip/chip.ts +131 -0
- package/src/components/{chip → chips/chip}/config.ts +3 -3
- package/src/components/chips/chip/index.ts +3 -0
- package/src/components/chips/chips.md +481 -0
- package/src/components/chips/chips.ts +75 -0
- package/src/components/chips/config.ts +109 -0
- package/src/components/chips/constants.ts +61 -0
- package/src/components/chips/features/chip-items.ts +33 -0
- package/src/components/chips/features/container.ts +77 -0
- package/src/components/chips/features/controller.ts +448 -0
- package/src/components/chips/features/index.ts +5 -0
- package/src/components/chips/features/label.ts +108 -0
- package/src/components/chips/index.ts +11 -0
- package/src/components/chips/schema.ts +61 -0
- package/src/components/{chip → chips}/types.ts +203 -92
- package/src/components/dialog/dialog.ts +99 -16
- package/src/components/dialog/index.ts +97 -1
- package/src/components/dialog/types.ts +375 -69
- package/src/components/divider/config.ts +90 -6
- package/src/components/divider/divider.ts +32 -2
- package/src/components/divider/features.ts +26 -0
- package/src/components/divider/index.ts +30 -0
- package/src/components/divider/types.ts +86 -9
- package/src/components/extended-fab/api.ts +53 -1
- package/src/components/extended-fab/config.ts +29 -1
- package/src/components/extended-fab/extended-fab.ts +28 -0
- package/src/components/extended-fab/index.ts +36 -0
- package/src/components/extended-fab/types.ts +458 -13
- package/src/components/fab/api.ts +42 -2
- package/src/components/fab/config.ts +29 -1
- package/src/components/fab/fab.ts +16 -2
- package/src/components/fab/index.ts +35 -0
- package/src/components/fab/types.ts +374 -10
- package/src/components/list/api.ts +12 -2
- package/src/components/list/config.ts +21 -0
- package/src/components/list/features.ts +6 -0
- package/src/components/list/index.ts +56 -1
- package/src/components/list/list-item.ts +46 -2
- package/src/components/list/list.ts +73 -2
- package/src/components/list/types.ts +172 -0
- package/src/components/list/utils.ts +26 -2
- package/src/components/menu/api.ts +217 -20
- package/src/components/menu/config.ts +27 -0
- package/src/components/menu/features/visibility.ts +55 -6
- package/src/components/menu/index.ts +64 -0
- package/src/components/menu/menu-item.ts +46 -3
- package/src/components/menu/menu.ts +77 -1
- package/src/components/menu/types.ts +404 -39
- package/src/components/sheet/config.ts +1 -2
- package/src/components/sheet/features/gestures.ts +1 -1
- package/src/components/sheet/features/position.ts +1 -2
- package/src/components/sheet/features/state.ts +1 -1
- package/src/components/sheet/index.ts +10 -2
- package/src/components/sheet/sheet.ts +1 -2
- package/src/components/sheet/types.ts +29 -1
- package/src/components/slider/api.ts +1 -1
- package/src/components/slider/config.ts +1 -1
- package/src/components/slider/features/controller.ts +1 -1
- package/src/components/slider/features/handlers.ts +1 -1
- package/src/components/slider/features/states.ts +1 -1
- package/src/components/slider/index.ts +12 -5
- package/src/components/slider/schema.ts +1 -1
- package/src/components/slider/types.ts +31 -0
- package/src/components/tabs/tab-api.ts +1 -1
- package/src/components/tabs/types.ts +1 -1
- package/src/components/tooltip/api.ts +6 -2
- package/src/components/tooltip/config.ts +9 -28
- package/src/components/tooltip/index.ts +10 -1
- package/src/components/tooltip/types.ts +38 -3
- package/src/index.ts +129 -31
- package/src/styles/abstract/_mixins.scss +23 -9
- package/src/styles/abstract/_variables.scss +14 -4
- package/src/styles/components/_card.scss +1 -1
- package/src/styles/components/_chip.scss +323 -113
- package/src/styles/components/_tabs.scss +1 -1
- package/CLAUDE.md +0 -33
- package/src/components/checkbox/constants.ts +0 -37
- package/src/components/chip/chip-set.ts +0 -225
- package/src/components/chip/chip.ts +0 -118
- package/src/components/chip/constants.ts +0 -28
- package/src/components/chip/index.ts +0 -12
- package/src/components/list/constants.ts +0 -116
- package/src/components/sheet/constants.ts +0 -20
- package/src/components/slider/constants.ts +0 -32
- package/src/components/tooltip/constants.ts +0 -27
- package/test/components/badge.test.ts +0 -545
- package/test/components/bottom-app-bar.test.ts +0 -303
- package/test/components/button.test.ts +0 -233
- package/test/components/card.test.ts +0 -560
- package/test/components/carousel.test.ts +0 -951
- package/test/components/checkbox.test.ts +0 -462
- package/test/components/chip.test.ts +0 -692
- package/test/components/datepicker.test.ts +0 -1124
- package/test/components/dialog.test.ts +0 -990
- package/test/components/divider.test.ts +0 -412
- package/test/components/extended-fab.test.ts +0 -672
- package/test/components/fab.test.ts +0 -561
- package/test/components/list.test.ts +0 -365
- package/test/components/menu.test.ts +0 -718
- package/test/components/navigation.test.ts +0 -186
- package/test/components/progress.test.ts +0 -567
- package/test/components/radios.test.ts +0 -699
- package/test/components/search.test.ts +0 -1135
- package/test/components/segmented-button.test.ts +0 -732
- package/test/components/sheet.test.ts +0 -641
- package/test/components/slider.test.ts +0 -1220
- package/test/components/snackbar.test.ts +0 -461
- package/test/components/switch.test.ts +0 -452
- package/test/components/tabs.test.ts +0 -1369
- package/test/components/textfield.test.ts +0 -400
- package/test/components/timepicker.test.ts +0 -592
- package/test/components/tooltip.test.ts +0 -630
- package/test/components/top-app-bar.test.ts +0 -566
- package/test/core/dom.attributes.test.ts +0 -148
- package/test/core/dom.classes.test.ts +0 -152
- package/test/core/dom.events.test.ts +0 -243
- package/test/core/emitter.test.ts +0 -141
- package/test/core/ripple.test.ts +0 -99
- package/test/core/state.store.test.ts +0 -189
- package/test/core/utils.normalize.test.ts +0 -61
- package/test/core/utils.object.test.ts +0 -120
- package/test/setup.js +0 -371
- package/test/setup.ts +0 -451
- package/tsconfig.json +0 -22
- package/typedoc.json +0 -28
- 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
|
-
});
|