mtrl 0.3.1 → 0.3.3
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 +62 -23
- 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/navigation/nav-item.ts +13 -2
- 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/core/dom/create.ts +57 -51
- 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/src/styles/themes/_autumn.scss +3 -0
- 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,692 +0,0 @@
|
|
|
1
|
-
// test/components/chip.test.ts
|
|
2
|
-
import { describe, test, expect } from 'bun:test';
|
|
3
|
-
import {
|
|
4
|
-
type ChipComponent,
|
|
5
|
-
type ChipConfig,
|
|
6
|
-
type ChipVariant
|
|
7
|
-
} from '../../src/components/chip/types';
|
|
8
|
-
|
|
9
|
-
// Constants for chip variants
|
|
10
|
-
const CHIP_VARIANTS = {
|
|
11
|
-
FILLED: 'filled',
|
|
12
|
-
OUTLINED: 'outlined',
|
|
13
|
-
ELEVATED: 'elevated',
|
|
14
|
-
ASSIST: 'assist',
|
|
15
|
-
FILTER: 'filter',
|
|
16
|
-
INPUT: 'input',
|
|
17
|
-
SUGGESTION: 'suggestion'
|
|
18
|
-
} as const;
|
|
19
|
-
|
|
20
|
-
// Mock chip implementation
|
|
21
|
-
const createMockChip = (config: ChipConfig = {}): ChipComponent => {
|
|
22
|
-
// Create the main element
|
|
23
|
-
const element = document.createElement('div');
|
|
24
|
-
element.className = 'mtrl-chip';
|
|
25
|
-
|
|
26
|
-
// Set default configuration
|
|
27
|
-
const componentConfig = {
|
|
28
|
-
componentName: 'chip',
|
|
29
|
-
prefix: config.prefix || 'mtrl',
|
|
30
|
-
variant: config.variant || CHIP_VARIANTS.FILLED,
|
|
31
|
-
disabled: config.disabled || false,
|
|
32
|
-
selected: config.selected || false,
|
|
33
|
-
ripple: config.ripple !== undefined ? config.ripple : true
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Apply variant class
|
|
37
|
-
if (componentConfig.variant) {
|
|
38
|
-
element.classList.add(`mtrl-chip--${componentConfig.variant}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Apply disabled state
|
|
42
|
-
if (componentConfig.disabled) {
|
|
43
|
-
element.classList.add('mtrl-chip--disabled');
|
|
44
|
-
element.setAttribute('aria-disabled', 'true');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Apply selected state
|
|
48
|
-
if (componentConfig.selected) {
|
|
49
|
-
element.classList.add('mtrl-chip--selected');
|
|
50
|
-
element.setAttribute('aria-selected', 'true');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Apply value if provided
|
|
54
|
-
if (config.value) {
|
|
55
|
-
element.setAttribute('data-value', config.value);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Apply additional classes
|
|
59
|
-
if (config.class) {
|
|
60
|
-
const classes = config.class.split(' ');
|
|
61
|
-
classes.forEach(className => element.classList.add(className));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Create ripple element if enabled
|
|
65
|
-
if (componentConfig.ripple) {
|
|
66
|
-
const ripple = document.createElement('span');
|
|
67
|
-
ripple.className = 'mtrl-chip__ripple';
|
|
68
|
-
element.appendChild(ripple);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Create text element
|
|
72
|
-
const textElement = document.createElement('span');
|
|
73
|
-
textElement.className = 'mtrl-chip__text';
|
|
74
|
-
if (config.text) {
|
|
75
|
-
textElement.textContent = config.text;
|
|
76
|
-
}
|
|
77
|
-
element.appendChild(textElement);
|
|
78
|
-
|
|
79
|
-
// Create leading icon element if provided
|
|
80
|
-
let leadingIconElement: HTMLElement | null = null;
|
|
81
|
-
if (config.leadingIcon || config.icon) {
|
|
82
|
-
leadingIconElement = document.createElement('span');
|
|
83
|
-
leadingIconElement.className = 'mtrl-chip__icon mtrl-chip__icon--leading';
|
|
84
|
-
leadingIconElement.innerHTML = config.leadingIcon || config.icon || '';
|
|
85
|
-
element.insertBefore(leadingIconElement, textElement);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Create trailing icon element if provided
|
|
89
|
-
let trailingIconElement: HTMLElement | null = null;
|
|
90
|
-
if (config.trailingIcon) {
|
|
91
|
-
trailingIconElement = document.createElement('span');
|
|
92
|
-
trailingIconElement.className = 'mtrl-chip__icon mtrl-chip__icon--trailing';
|
|
93
|
-
trailingIconElement.innerHTML = config.trailingIcon;
|
|
94
|
-
element.appendChild(trailingIconElement);
|
|
95
|
-
|
|
96
|
-
// Add click handler if provided
|
|
97
|
-
if (config.onTrailingIconClick) {
|
|
98
|
-
trailingIconElement.addEventListener('click', (e) => {
|
|
99
|
-
e.stopPropagation();
|
|
100
|
-
if (config.onTrailingIconClick) {
|
|
101
|
-
config.onTrailingIconClick(chip);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Set up event handlers
|
|
108
|
-
const eventHandlers: Record<string, Function[]> = {};
|
|
109
|
-
|
|
110
|
-
const emit = (event: string, data?: any) => {
|
|
111
|
-
if (eventHandlers[event]) {
|
|
112
|
-
eventHandlers[event].forEach(handler => handler(data));
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// Click handler to toggle selected state if selectable
|
|
117
|
-
const handleClick = () => {
|
|
118
|
-
if (componentConfig.disabled) return;
|
|
119
|
-
|
|
120
|
-
if (config.selectable ||
|
|
121
|
-
componentConfig.variant === CHIP_VARIANTS.FILTER ||
|
|
122
|
-
componentConfig.variant === CHIP_VARIANTS.INPUT) {
|
|
123
|
-
chip.toggleSelected();
|
|
124
|
-
|
|
125
|
-
if (config.onChange) {
|
|
126
|
-
config.onChange(chip);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
emit('change', { selected: chip.isSelected() });
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
emit('click');
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
// Add click handler to the element
|
|
136
|
-
element.addEventListener('click', handleClick);
|
|
137
|
-
|
|
138
|
-
// Initialize text API
|
|
139
|
-
const textAPI = {
|
|
140
|
-
setText: (content: string) => {
|
|
141
|
-
textElement.textContent = content;
|
|
142
|
-
return textAPI;
|
|
143
|
-
},
|
|
144
|
-
getText: () => textElement.textContent || '',
|
|
145
|
-
getElement: () => textElement
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
// Initialize icon API
|
|
149
|
-
const iconAPI = {
|
|
150
|
-
setIcon: (html: string) => {
|
|
151
|
-
if (!leadingIconElement) {
|
|
152
|
-
leadingIconElement = document.createElement('span');
|
|
153
|
-
leadingIconElement.className = 'mtrl-chip__icon mtrl-chip__icon--leading';
|
|
154
|
-
element.insertBefore(leadingIconElement, textElement);
|
|
155
|
-
}
|
|
156
|
-
leadingIconElement.innerHTML = html;
|
|
157
|
-
return iconAPI;
|
|
158
|
-
},
|
|
159
|
-
getIcon: () => leadingIconElement ? leadingIconElement.innerHTML : '',
|
|
160
|
-
getElement: () => leadingIconElement
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
// Create the chip component
|
|
164
|
-
const chip: ChipComponent = {
|
|
165
|
-
element,
|
|
166
|
-
text: textAPI,
|
|
167
|
-
icon: iconAPI,
|
|
168
|
-
|
|
169
|
-
disabled: {
|
|
170
|
-
enable: () => {
|
|
171
|
-
element.classList.remove('mtrl-chip--disabled');
|
|
172
|
-
element.removeAttribute('aria-disabled');
|
|
173
|
-
},
|
|
174
|
-
disable: () => {
|
|
175
|
-
element.classList.add('mtrl-chip--disabled');
|
|
176
|
-
element.setAttribute('aria-disabled', 'true');
|
|
177
|
-
},
|
|
178
|
-
isDisabled: () => element.classList.contains('mtrl-chip--disabled')
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
lifecycle: {
|
|
182
|
-
destroy: () => {
|
|
183
|
-
chip.destroy();
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
|
|
187
|
-
getClass: (name: string) => {
|
|
188
|
-
const prefix = componentConfig.prefix;
|
|
189
|
-
return name ? `${prefix}-${name}` : `${prefix}-chip`;
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
getValue: () => element.getAttribute('data-value'),
|
|
193
|
-
|
|
194
|
-
setValue: (value: string) => {
|
|
195
|
-
element.setAttribute('data-value', value);
|
|
196
|
-
return chip;
|
|
197
|
-
},
|
|
198
|
-
|
|
199
|
-
enable: () => {
|
|
200
|
-
chip.disabled.enable();
|
|
201
|
-
return chip;
|
|
202
|
-
},
|
|
203
|
-
|
|
204
|
-
disable: () => {
|
|
205
|
-
chip.disabled.disable();
|
|
206
|
-
return chip;
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
isDisabled: () => chip.disabled.isDisabled(),
|
|
210
|
-
|
|
211
|
-
setText: (content: string) => {
|
|
212
|
-
textAPI.setText(content);
|
|
213
|
-
return chip;
|
|
214
|
-
},
|
|
215
|
-
|
|
216
|
-
getText: () => textAPI.getText(),
|
|
217
|
-
|
|
218
|
-
setIcon: (icon: string) => {
|
|
219
|
-
iconAPI.setIcon(icon);
|
|
220
|
-
return chip;
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
getIcon: () => iconAPI.getIcon(),
|
|
224
|
-
|
|
225
|
-
setLeadingIcon: (icon: string) => {
|
|
226
|
-
iconAPI.setIcon(icon);
|
|
227
|
-
return chip;
|
|
228
|
-
},
|
|
229
|
-
|
|
230
|
-
setTrailingIcon: (icon: string, onClick?: (chip: ChipComponent) => void) => {
|
|
231
|
-
if (!trailingIconElement) {
|
|
232
|
-
trailingIconElement = document.createElement('span');
|
|
233
|
-
trailingIconElement.className = 'mtrl-chip__icon mtrl-chip__icon--trailing';
|
|
234
|
-
element.appendChild(trailingIconElement);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
trailingIconElement.innerHTML = icon;
|
|
238
|
-
|
|
239
|
-
// Clear previous handlers and add new one if provided
|
|
240
|
-
const newTrailingElement = trailingIconElement.cloneNode(true);
|
|
241
|
-
trailingIconElement.parentNode?.replaceChild(newTrailingElement, trailingIconElement);
|
|
242
|
-
trailingIconElement = newTrailingElement as HTMLElement;
|
|
243
|
-
|
|
244
|
-
if (onClick) {
|
|
245
|
-
trailingIconElement.addEventListener('click', (e) => {
|
|
246
|
-
e.stopPropagation();
|
|
247
|
-
onClick(chip);
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return chip;
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
isSelected: () => element.classList.contains('mtrl-chip--selected'),
|
|
255
|
-
|
|
256
|
-
setSelected: (selected: boolean) => {
|
|
257
|
-
if (selected) {
|
|
258
|
-
element.classList.add('mtrl-chip--selected');
|
|
259
|
-
element.setAttribute('aria-selected', 'true');
|
|
260
|
-
|
|
261
|
-
if (config.onSelect) {
|
|
262
|
-
config.onSelect(chip);
|
|
263
|
-
}
|
|
264
|
-
} else {
|
|
265
|
-
element.classList.remove('mtrl-chip--selected');
|
|
266
|
-
element.removeAttribute('aria-selected');
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return chip;
|
|
270
|
-
},
|
|
271
|
-
|
|
272
|
-
toggleSelected: () => {
|
|
273
|
-
const newSelectedState = !chip.isSelected();
|
|
274
|
-
chip.setSelected(newSelectedState);
|
|
275
|
-
return chip;
|
|
276
|
-
},
|
|
277
|
-
|
|
278
|
-
destroy: () => {
|
|
279
|
-
// Remove event listeners
|
|
280
|
-
element.removeEventListener('click', handleClick);
|
|
281
|
-
|
|
282
|
-
// Remove element from DOM if it has a parent
|
|
283
|
-
if (element.parentNode) {
|
|
284
|
-
element.parentNode.removeChild(element);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Clear event handlers
|
|
288
|
-
for (const event in eventHandlers) {
|
|
289
|
-
eventHandlers[event] = [];
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
|
|
293
|
-
on: (event: string, handler: Function) => {
|
|
294
|
-
if (!eventHandlers[event]) {
|
|
295
|
-
eventHandlers[event] = [];
|
|
296
|
-
}
|
|
297
|
-
eventHandlers[event].push(handler);
|
|
298
|
-
return chip;
|
|
299
|
-
},
|
|
300
|
-
|
|
301
|
-
off: (event: string, handler: Function) => {
|
|
302
|
-
if (eventHandlers[event]) {
|
|
303
|
-
eventHandlers[event] = eventHandlers[event].filter(h => h !== handler);
|
|
304
|
-
}
|
|
305
|
-
return chip;
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
addClass: (...classes: string[]) => {
|
|
309
|
-
classes.forEach(className => element.classList.add(className));
|
|
310
|
-
return chip;
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
return chip;
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
describe('Chip Component', () => {
|
|
318
|
-
test('should create a chip element', () => {
|
|
319
|
-
const chip = createMockChip();
|
|
320
|
-
expect(chip.element).toBeDefined();
|
|
321
|
-
expect(chip.element.tagName).toBe('DIV');
|
|
322
|
-
expect(chip.element.className).toContain('mtrl-chip');
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
test('should apply variant classes', () => {
|
|
326
|
-
const variants: ChipVariant[] = [
|
|
327
|
-
CHIP_VARIANTS.FILLED,
|
|
328
|
-
CHIP_VARIANTS.OUTLINED,
|
|
329
|
-
CHIP_VARIANTS.ELEVATED,
|
|
330
|
-
CHIP_VARIANTS.ASSIST,
|
|
331
|
-
CHIP_VARIANTS.FILTER,
|
|
332
|
-
CHIP_VARIANTS.INPUT,
|
|
333
|
-
CHIP_VARIANTS.SUGGESTION
|
|
334
|
-
];
|
|
335
|
-
|
|
336
|
-
variants.forEach(variant => {
|
|
337
|
-
const chip = createMockChip({ variant });
|
|
338
|
-
expect(chip.element.className).toContain(`mtrl-chip--${variant}`);
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
test('should set initial text content', () => {
|
|
343
|
-
const chip = createMockChip({ text: 'Test Chip' });
|
|
344
|
-
|
|
345
|
-
const textElement = chip.element.querySelector('.mtrl-chip__text');
|
|
346
|
-
expect(textElement).toBeDefined();
|
|
347
|
-
expect(textElement?.textContent).toBe('Test Chip');
|
|
348
|
-
expect(chip.getText()).toBe('Test Chip');
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
test('should set initial leading icon', () => {
|
|
352
|
-
const iconHtml = '<svg><path></path></svg>';
|
|
353
|
-
const chip = createMockChip({ leadingIcon: iconHtml });
|
|
354
|
-
|
|
355
|
-
const iconElement = chip.element.querySelector('.mtrl-chip__icon--leading');
|
|
356
|
-
expect(iconElement).toBeDefined();
|
|
357
|
-
expect(iconElement?.innerHTML).toBe(iconHtml);
|
|
358
|
-
expect(chip.getIcon()).toBe(iconHtml);
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
test('should use icon as alias for leadingIcon', () => {
|
|
362
|
-
const iconHtml = '<svg><path></path></svg>';
|
|
363
|
-
const chip = createMockChip({ icon: iconHtml });
|
|
364
|
-
|
|
365
|
-
const iconElement = chip.element.querySelector('.mtrl-chip__icon--leading');
|
|
366
|
-
expect(iconElement).toBeDefined();
|
|
367
|
-
expect(iconElement?.innerHTML).toBe(iconHtml);
|
|
368
|
-
expect(chip.getIcon()).toBe(iconHtml);
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
test('should set initial trailing icon', () => {
|
|
372
|
-
const iconHtml = '<svg><path></path></svg>';
|
|
373
|
-
const chip = createMockChip({ trailingIcon: iconHtml });
|
|
374
|
-
|
|
375
|
-
const iconElement = chip.element.querySelector('.mtrl-chip__icon--trailing');
|
|
376
|
-
expect(iconElement).toBeDefined();
|
|
377
|
-
expect(iconElement?.innerHTML).toBe(iconHtml);
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
test('should set value attribute', () => {
|
|
381
|
-
const chip = createMockChip({ value: 'chip-123' });
|
|
382
|
-
|
|
383
|
-
expect(chip.element.getAttribute('data-value')).toBe('chip-123');
|
|
384
|
-
expect(chip.getValue()).toBe('chip-123');
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
test('should create ripple element by default', () => {
|
|
388
|
-
const chip = createMockChip();
|
|
389
|
-
|
|
390
|
-
const rippleElement = chip.element.querySelector('.mtrl-chip__ripple');
|
|
391
|
-
expect(rippleElement).toBeDefined();
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
test('should not create ripple element when disabled', () => {
|
|
395
|
-
const chip = createMockChip({ ripple: false });
|
|
396
|
-
|
|
397
|
-
const rippleElement = chip.element.querySelector('.mtrl-chip__ripple');
|
|
398
|
-
expect(rippleElement).toBeNull();
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
test('should apply disabled state', () => {
|
|
402
|
-
const chip = createMockChip({ disabled: true });
|
|
403
|
-
|
|
404
|
-
expect(chip.element.className).toContain('mtrl-chip--disabled');
|
|
405
|
-
expect(chip.element.getAttribute('aria-disabled')).toBe('true');
|
|
406
|
-
expect(chip.isDisabled()).toBe(true);
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
test('should apply selected state', () => {
|
|
410
|
-
const chip = createMockChip({ selected: true });
|
|
411
|
-
|
|
412
|
-
expect(chip.element.className).toContain('mtrl-chip--selected');
|
|
413
|
-
expect(chip.element.getAttribute('aria-selected')).toBe('true');
|
|
414
|
-
expect(chip.isSelected()).toBe(true);
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
test('should be able to change text content', () => {
|
|
418
|
-
const chip = createMockChip({ text: 'Initial Text' });
|
|
419
|
-
|
|
420
|
-
expect(chip.getText()).toBe('Initial Text');
|
|
421
|
-
|
|
422
|
-
chip.setText('Updated Text');
|
|
423
|
-
|
|
424
|
-
expect(chip.getText()).toBe('Updated Text');
|
|
425
|
-
|
|
426
|
-
const textElement = chip.element.querySelector('.mtrl-chip__text');
|
|
427
|
-
expect(textElement?.textContent).toBe('Updated Text');
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
test('should be able to change leading icon', () => {
|
|
431
|
-
const chip = createMockChip();
|
|
432
|
-
|
|
433
|
-
const initialIconElement = chip.element.querySelector('.mtrl-chip__icon--leading');
|
|
434
|
-
expect(initialIconElement).toBeNull();
|
|
435
|
-
|
|
436
|
-
const iconHtml = '<svg><path></path></svg>';
|
|
437
|
-
chip.setIcon(iconHtml);
|
|
438
|
-
|
|
439
|
-
const updatedIconElement = chip.element.querySelector('.mtrl-chip__icon--leading');
|
|
440
|
-
expect(updatedIconElement).toBeDefined();
|
|
441
|
-
expect(updatedIconElement?.innerHTML).toBe(iconHtml);
|
|
442
|
-
expect(chip.getIcon()).toBe(iconHtml);
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
test('should be able to change trailing icon', () => {
|
|
446
|
-
const chip = createMockChip();
|
|
447
|
-
|
|
448
|
-
const initialIconElement = chip.element.querySelector('.mtrl-chip__icon--trailing');
|
|
449
|
-
expect(initialIconElement).toBeNull();
|
|
450
|
-
|
|
451
|
-
const iconHtml = '<svg><path></path></svg>';
|
|
452
|
-
chip.setTrailingIcon(iconHtml);
|
|
453
|
-
|
|
454
|
-
const updatedIconElement = chip.element.querySelector('.mtrl-chip__icon--trailing');
|
|
455
|
-
expect(updatedIconElement).toBeDefined();
|
|
456
|
-
expect(updatedIconElement?.innerHTML).toBe(iconHtml);
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
test('should handle trailing icon click events', () => {
|
|
460
|
-
let clickHandled = false;
|
|
461
|
-
|
|
462
|
-
const chip = createMockChip({
|
|
463
|
-
trailingIcon: '<svg></svg>',
|
|
464
|
-
onTrailingIconClick: () => {
|
|
465
|
-
clickHandled = true;
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
const trailingIcon = chip.element.querySelector('.mtrl-chip__icon--trailing');
|
|
470
|
-
expect(trailingIcon).toBeDefined();
|
|
471
|
-
|
|
472
|
-
const clickEvent = new Event('click');
|
|
473
|
-
clickEvent.stopPropagation = () => {};
|
|
474
|
-
trailingIcon?.dispatchEvent(clickEvent);
|
|
475
|
-
|
|
476
|
-
expect(clickHandled).toBe(true);
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
test('should be able to change selected state', () => {
|
|
480
|
-
const chip = createMockChip();
|
|
481
|
-
|
|
482
|
-
expect(chip.isSelected()).toBe(false);
|
|
483
|
-
|
|
484
|
-
chip.setSelected(true);
|
|
485
|
-
|
|
486
|
-
expect(chip.isSelected()).toBe(true);
|
|
487
|
-
expect(chip.element.className).toContain('mtrl-chip--selected');
|
|
488
|
-
expect(chip.element.getAttribute('aria-selected')).toBe('true');
|
|
489
|
-
|
|
490
|
-
chip.setSelected(false);
|
|
491
|
-
|
|
492
|
-
expect(chip.isSelected()).toBe(false);
|
|
493
|
-
expect(chip.element.className).not.toContain('mtrl-chip--selected');
|
|
494
|
-
expect(chip.element.getAttribute('aria-selected')).toBeNull();
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
test('should be able to toggle selected state', () => {
|
|
498
|
-
const chip = createMockChip();
|
|
499
|
-
|
|
500
|
-
expect(chip.isSelected()).toBe(false);
|
|
501
|
-
|
|
502
|
-
chip.toggleSelected();
|
|
503
|
-
|
|
504
|
-
expect(chip.isSelected()).toBe(true);
|
|
505
|
-
|
|
506
|
-
chip.toggleSelected();
|
|
507
|
-
|
|
508
|
-
expect(chip.isSelected()).toBe(false);
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
test('should be able to change disabled state', () => {
|
|
512
|
-
const chip = createMockChip();
|
|
513
|
-
|
|
514
|
-
expect(chip.isDisabled()).toBe(false);
|
|
515
|
-
|
|
516
|
-
chip.disable();
|
|
517
|
-
|
|
518
|
-
expect(chip.isDisabled()).toBe(true);
|
|
519
|
-
expect(chip.element.className).toContain('mtrl-chip--disabled');
|
|
520
|
-
expect(chip.element.getAttribute('aria-disabled')).toBe('true');
|
|
521
|
-
|
|
522
|
-
chip.enable();
|
|
523
|
-
|
|
524
|
-
expect(chip.isDisabled()).toBe(false);
|
|
525
|
-
expect(chip.element.className).not.toContain('mtrl-chip--disabled');
|
|
526
|
-
expect(chip.element.getAttribute('aria-disabled')).toBeNull();
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
test('should be able to change value', () => {
|
|
530
|
-
const chip = createMockChip();
|
|
531
|
-
|
|
532
|
-
expect(chip.getValue()).toBeNull();
|
|
533
|
-
|
|
534
|
-
chip.setValue('new-value');
|
|
535
|
-
|
|
536
|
-
expect(chip.getValue()).toBe('new-value');
|
|
537
|
-
expect(chip.element.getAttribute('data-value')).toBe('new-value');
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
test('should add event listeners', () => {
|
|
541
|
-
const chip = createMockChip();
|
|
542
|
-
let eventFired = false;
|
|
543
|
-
|
|
544
|
-
chip.on('click', () => {
|
|
545
|
-
eventFired = true;
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
// Simulate click
|
|
549
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
550
|
-
|
|
551
|
-
expect(eventFired).toBe(true);
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
test('should remove event listeners', () => {
|
|
555
|
-
const chip = createMockChip();
|
|
556
|
-
let count = 0;
|
|
557
|
-
|
|
558
|
-
const handler = () => {
|
|
559
|
-
count++;
|
|
560
|
-
};
|
|
561
|
-
|
|
562
|
-
chip.on('click', handler);
|
|
563
|
-
|
|
564
|
-
// First click
|
|
565
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
566
|
-
expect(count).toBe(1);
|
|
567
|
-
|
|
568
|
-
// Remove listener
|
|
569
|
-
chip.off('click', handler);
|
|
570
|
-
|
|
571
|
-
// Second click
|
|
572
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
573
|
-
expect(count).toBe(1); // Count should not increase
|
|
574
|
-
});
|
|
575
|
-
|
|
576
|
-
test('should add CSS classes', () => {
|
|
577
|
-
const chip = createMockChip();
|
|
578
|
-
|
|
579
|
-
chip.addClass('custom-class', 'special-chip');
|
|
580
|
-
|
|
581
|
-
expect(chip.element.className).toContain('custom-class');
|
|
582
|
-
expect(chip.element.className).toContain('special-chip');
|
|
583
|
-
});
|
|
584
|
-
|
|
585
|
-
test('should toggle selected state when clicked for filter chips', () => {
|
|
586
|
-
const chip = createMockChip({ variant: CHIP_VARIANTS.FILTER });
|
|
587
|
-
|
|
588
|
-
expect(chip.isSelected()).toBe(false);
|
|
589
|
-
|
|
590
|
-
// Simulate click
|
|
591
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
592
|
-
|
|
593
|
-
expect(chip.isSelected()).toBe(true);
|
|
594
|
-
|
|
595
|
-
// Click again
|
|
596
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
597
|
-
|
|
598
|
-
expect(chip.isSelected()).toBe(false);
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
test('should call onChange when selection changes', () => {
|
|
602
|
-
let changeHandled = false;
|
|
603
|
-
let selectedState = false;
|
|
604
|
-
|
|
605
|
-
const chip = createMockChip({
|
|
606
|
-
variant: CHIP_VARIANTS.FILTER,
|
|
607
|
-
onChange: (c) => {
|
|
608
|
-
changeHandled = true;
|
|
609
|
-
selectedState = c.isSelected();
|
|
610
|
-
}
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
// Simulate click
|
|
614
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
615
|
-
|
|
616
|
-
expect(changeHandled).toBe(true);
|
|
617
|
-
expect(selectedState).toBe(true);
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
test('should call onSelect when selected', () => {
|
|
621
|
-
let selectHandled = false;
|
|
622
|
-
|
|
623
|
-
const chip = createMockChip({
|
|
624
|
-
onSelect: () => {
|
|
625
|
-
selectHandled = true;
|
|
626
|
-
}
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
chip.setSelected(true);
|
|
630
|
-
|
|
631
|
-
expect(selectHandled).toBe(true);
|
|
632
|
-
});
|
|
633
|
-
|
|
634
|
-
test('should make any chip variant selectable with selectable flag', () => {
|
|
635
|
-
const chip = createMockChip({
|
|
636
|
-
variant: CHIP_VARIANTS.FILLED,
|
|
637
|
-
selectable: true
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
expect(chip.isSelected()).toBe(false);
|
|
641
|
-
|
|
642
|
-
// Simulate click
|
|
643
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
644
|
-
|
|
645
|
-
expect(chip.isSelected()).toBe(true);
|
|
646
|
-
});
|
|
647
|
-
|
|
648
|
-
test('should not toggle selection when disabled', () => {
|
|
649
|
-
const chip = createMockChip({
|
|
650
|
-
variant: CHIP_VARIANTS.FILTER,
|
|
651
|
-
disabled: true
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
expect(chip.isSelected()).toBe(false);
|
|
655
|
-
|
|
656
|
-
// Simulate click
|
|
657
|
-
chip.element.dispatchEvent(new Event('click'));
|
|
658
|
-
|
|
659
|
-
expect(chip.isSelected()).toBe(false);
|
|
660
|
-
});
|
|
661
|
-
|
|
662
|
-
test('should be properly destroyed', () => {
|
|
663
|
-
const chip = createMockChip();
|
|
664
|
-
document.body.appendChild(chip.element);
|
|
665
|
-
|
|
666
|
-
expect(document.body.contains(chip.element)).toBe(true);
|
|
667
|
-
|
|
668
|
-
chip.destroy();
|
|
669
|
-
|
|
670
|
-
expect(document.body.contains(chip.element)).toBe(false);
|
|
671
|
-
});
|
|
672
|
-
|
|
673
|
-
test('should handle basic chip set creation', () => {
|
|
674
|
-
// Create a chip set container
|
|
675
|
-
const chipSetElement = document.createElement('div');
|
|
676
|
-
chipSetElement.className = 'mtrl-chip-set';
|
|
677
|
-
|
|
678
|
-
// Add chips to the set
|
|
679
|
-
const chip1 = createMockChip({ text: 'Chip 1' });
|
|
680
|
-
const chip2 = createMockChip({ text: 'Chip 2', selected: true });
|
|
681
|
-
const chip3 = createMockChip({ text: 'Chip 3' });
|
|
682
|
-
|
|
683
|
-
chipSetElement.appendChild(chip1.element);
|
|
684
|
-
chipSetElement.appendChild(chip2.element);
|
|
685
|
-
chipSetElement.appendChild(chip3.element);
|
|
686
|
-
|
|
687
|
-
// Check if all chips are in the set
|
|
688
|
-
expect(chipSetElement.children.length).toBe(3);
|
|
689
|
-
expect(chipSetElement.children[0].className).toContain('mtrl-chip');
|
|
690
|
-
expect(chipSetElement.children[1].className).toContain('mtrl-chip--selected');
|
|
691
|
-
});
|
|
692
|
-
});
|