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.
Files changed (162) hide show
  1. package/.env +15 -0
  2. package/CONTRIBUTING.md +62 -23
  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/navigation/nav-item.ts +13 -2
  83. package/src/components/sheet/config.ts +1 -2
  84. package/src/components/sheet/features/gestures.ts +1 -1
  85. package/src/components/sheet/features/position.ts +1 -2
  86. package/src/components/sheet/features/state.ts +1 -1
  87. package/src/components/sheet/index.ts +10 -2
  88. package/src/components/sheet/sheet.ts +1 -2
  89. package/src/components/sheet/types.ts +29 -1
  90. package/src/components/slider/api.ts +1 -1
  91. package/src/components/slider/config.ts +1 -1
  92. package/src/components/slider/features/controller.ts +1 -1
  93. package/src/components/slider/features/handlers.ts +1 -1
  94. package/src/components/slider/features/states.ts +1 -1
  95. package/src/components/slider/index.ts +12 -5
  96. package/src/components/slider/schema.ts +1 -1
  97. package/src/components/slider/types.ts +31 -0
  98. package/src/components/tabs/tab-api.ts +1 -1
  99. package/src/components/tabs/types.ts +1 -1
  100. package/src/components/tooltip/api.ts +6 -2
  101. package/src/components/tooltip/config.ts +9 -28
  102. package/src/components/tooltip/index.ts +10 -1
  103. package/src/components/tooltip/types.ts +38 -3
  104. package/src/core/dom/create.ts +57 -51
  105. package/src/index.ts +129 -31
  106. package/src/styles/abstract/_mixins.scss +23 -9
  107. package/src/styles/abstract/_variables.scss +14 -4
  108. package/src/styles/components/_card.scss +1 -1
  109. package/src/styles/components/_chip.scss +323 -113
  110. package/src/styles/components/_tabs.scss +1 -1
  111. package/src/styles/themes/_autumn.scss +3 -0
  112. package/CLAUDE.md +0 -33
  113. package/src/components/checkbox/constants.ts +0 -37
  114. package/src/components/chip/chip-set.ts +0 -225
  115. package/src/components/chip/chip.ts +0 -118
  116. package/src/components/chip/constants.ts +0 -28
  117. package/src/components/chip/index.ts +0 -12
  118. package/src/components/list/constants.ts +0 -116
  119. package/src/components/sheet/constants.ts +0 -20
  120. package/src/components/slider/constants.ts +0 -32
  121. package/src/components/tooltip/constants.ts +0 -27
  122. package/test/components/badge.test.ts +0 -545
  123. package/test/components/bottom-app-bar.test.ts +0 -303
  124. package/test/components/button.test.ts +0 -233
  125. package/test/components/card.test.ts +0 -560
  126. package/test/components/carousel.test.ts +0 -951
  127. package/test/components/checkbox.test.ts +0 -462
  128. package/test/components/chip.test.ts +0 -692
  129. package/test/components/datepicker.test.ts +0 -1124
  130. package/test/components/dialog.test.ts +0 -990
  131. package/test/components/divider.test.ts +0 -412
  132. package/test/components/extended-fab.test.ts +0 -672
  133. package/test/components/fab.test.ts +0 -561
  134. package/test/components/list.test.ts +0 -365
  135. package/test/components/menu.test.ts +0 -718
  136. package/test/components/navigation.test.ts +0 -186
  137. package/test/components/progress.test.ts +0 -567
  138. package/test/components/radios.test.ts +0 -699
  139. package/test/components/search.test.ts +0 -1135
  140. package/test/components/segmented-button.test.ts +0 -732
  141. package/test/components/sheet.test.ts +0 -641
  142. package/test/components/slider.test.ts +0 -1220
  143. package/test/components/snackbar.test.ts +0 -461
  144. package/test/components/switch.test.ts +0 -452
  145. package/test/components/tabs.test.ts +0 -1369
  146. package/test/components/textfield.test.ts +0 -400
  147. package/test/components/timepicker.test.ts +0 -592
  148. package/test/components/tooltip.test.ts +0 -630
  149. package/test/components/top-app-bar.test.ts +0 -566
  150. package/test/core/dom.attributes.test.ts +0 -148
  151. package/test/core/dom.classes.test.ts +0 -152
  152. package/test/core/dom.events.test.ts +0 -243
  153. package/test/core/emitter.test.ts +0 -141
  154. package/test/core/ripple.test.ts +0 -99
  155. package/test/core/state.store.test.ts +0 -189
  156. package/test/core/utils.normalize.test.ts +0 -61
  157. package/test/core/utils.object.test.ts +0 -120
  158. package/test/setup.js +0 -371
  159. package/test/setup.ts +0 -451
  160. package/tsconfig.json +0 -22
  161. package/typedoc.json +0 -28
  162. package/typedoc.simple.json +0 -14
@@ -1,567 +0,0 @@
1
- // test/components/progress.test.ts
2
- import { describe, test, expect } from 'bun:test';
3
- import {
4
- type ProgressComponent,
5
- type ProgressConfig,
6
- type ProgressVariant,
7
- type ProgressEvent
8
- } from '../../src/components/progress/types';
9
-
10
- // Constants for progress variants
11
- const PROGRESS_VARIANTS = {
12
- LINEAR: 'linear',
13
- CIRCULAR: 'circular'
14
- } as const;
15
-
16
- // Constants for progress events
17
- const PROGRESS_EVENTS = {
18
- CHANGE: 'change',
19
- COMPLETE: 'complete'
20
- } as const;
21
-
22
- // Mock progress component implementation
23
- const createMockProgress = (config: ProgressConfig = {}): ProgressComponent => {
24
- // Create main elements
25
- const element = document.createElement('div');
26
- element.className = 'mtrl-progress';
27
-
28
- const trackElement = document.createElement('div');
29
- trackElement.className = 'mtrl-progress-track';
30
-
31
- const indicatorElement = document.createElement('div');
32
- indicatorElement.className = 'mtrl-progress-indicator';
33
-
34
- // Default settings
35
- const settings = {
36
- variant: config.variant || PROGRESS_VARIANTS.LINEAR,
37
- value: config.value !== undefined ? config.value : 0,
38
- max: config.max !== undefined ? config.max : 100,
39
- buffer: config.buffer !== undefined ? config.buffer : 0,
40
- disabled: config.disabled || false,
41
- indeterminate: config.indeterminate || false,
42
- showLabel: config.showLabel || false,
43
- labelFormatter: config.labelFormatter || ((value, max) => `${Math.round((value/max) * 100)}%`),
44
- componentName: 'progress',
45
- prefix: config.prefix || 'mtrl'
46
- };
47
-
48
- // Apply variant class
49
- element.classList.add(`mtrl-progress--${settings.variant}`);
50
-
51
- // Apply disabled state
52
- if (settings.disabled) {
53
- element.classList.add('mtrl-progress--disabled');
54
- }
55
-
56
- // Apply indeterminate state
57
- if (settings.indeterminate) {
58
- element.classList.add('mtrl-progress--indeterminate');
59
- }
60
-
61
- // Apply additional classes
62
- if (config.class) {
63
- const classes = config.class.split(' ');
64
- classes.forEach(className => element.classList.add(className));
65
- }
66
-
67
- // Create buffer element for linear variant
68
- let bufferElement: HTMLElement | undefined;
69
- if (settings.variant === PROGRESS_VARIANTS.LINEAR) {
70
- bufferElement = document.createElement('div');
71
- bufferElement.className = 'mtrl-progress-buffer';
72
- trackElement.appendChild(bufferElement);
73
- }
74
-
75
- // Create label element if enabled
76
- let labelElement: HTMLElement | undefined;
77
- if (settings.showLabel) {
78
- labelElement = document.createElement('div');
79
- labelElement.className = 'mtrl-progress-label';
80
- labelElement.textContent = settings.labelFormatter(settings.value, settings.max);
81
- }
82
-
83
- // Assemble elements
84
- trackElement.appendChild(indicatorElement);
85
- element.appendChild(trackElement);
86
-
87
- if (labelElement) {
88
- element.appendChild(labelElement);
89
- }
90
-
91
- // Track event handlers
92
- const eventHandlers: Record<string, Function[]> = {};
93
-
94
- // Update visuals based on current value
95
- const updateVisuals = () => {
96
- if (!settings.indeterminate) {
97
- const percentage = (settings.value / settings.max) * 100;
98
-
99
- if (settings.variant === PROGRESS_VARIANTS.LINEAR) {
100
- indicatorElement.style.width = `${percentage}%`;
101
-
102
- if (bufferElement) {
103
- const bufferPercentage = (settings.buffer / settings.max) * 100;
104
- bufferElement.style.width = `${bufferPercentage}%`;
105
- }
106
- } else if (settings.variant === PROGRESS_VARIANTS.CIRCULAR) {
107
- // For circular progress, update stroke-dashoffset or similar property
108
- const circumference = 100; // Simplified for testing
109
- const offset = circumference - (percentage / 100 * circumference);
110
- indicatorElement.style.setProperty('--progress-offset', `${offset}`);
111
- }
112
-
113
- // Update label if present
114
- if (labelElement) {
115
- labelElement.textContent = settings.labelFormatter(settings.value, settings.max);
116
- }
117
- }
118
- };
119
-
120
- // Initialize visuals
121
- updateVisuals();
122
-
123
- // Emit an event
124
- const emit = (event: string, data?: any) => {
125
- if (eventHandlers[event]) {
126
- eventHandlers[event].forEach(handler => handler(data));
127
- }
128
- };
129
-
130
- // Create the progress component
131
- const progress: ProgressComponent = {
132
- element,
133
- trackElement,
134
- indicatorElement,
135
- bufferElement,
136
- labelElement,
137
-
138
- getClass: (name: string) => {
139
- const prefix = settings.prefix;
140
- return name ? `${prefix}-${name}` : `${prefix}-progress`;
141
- },
142
-
143
- setValue: (value: number) => {
144
- // Ensure value is within bounds
145
- value = Math.max(0, Math.min(value, settings.max));
146
-
147
- const oldValue = settings.value;
148
- settings.value = value;
149
-
150
- // Update visuals
151
- updateVisuals();
152
-
153
- // Emit change event
154
- emit(PROGRESS_EVENTS.CHANGE, { value, oldValue });
155
-
156
- // Emit complete event if reached 100%
157
- if (value === settings.max && oldValue !== settings.max) {
158
- emit(PROGRESS_EVENTS.COMPLETE, { value });
159
- }
160
-
161
- return progress;
162
- },
163
-
164
- getValue: () => settings.value,
165
-
166
- setBuffer: (value: number) => {
167
- // Ensure buffer is within bounds
168
- value = Math.max(0, Math.min(value, settings.max));
169
- settings.buffer = value;
170
-
171
- // Update visuals
172
- updateVisuals();
173
-
174
- return progress;
175
- },
176
-
177
- getBuffer: () => settings.buffer,
178
-
179
- enable: () => {
180
- progress.disabled.enable();
181
- return progress;
182
- },
183
-
184
- disable: () => {
185
- progress.disabled.disable();
186
- return progress;
187
- },
188
-
189
- isDisabled: () => progress.disabled.isDisabled(),
190
-
191
- showLabel: () => {
192
- settings.showLabel = true;
193
-
194
- if (!labelElement) {
195
- labelElement = document.createElement('div');
196
- labelElement.className = 'mtrl-progress-label';
197
- labelElement.textContent = settings.labelFormatter(settings.value, settings.max);
198
- element.appendChild(labelElement);
199
- progress.labelElement = labelElement;
200
- }
201
-
202
- return progress;
203
- },
204
-
205
- hideLabel: () => {
206
- settings.showLabel = false;
207
-
208
- if (labelElement) {
209
- element.removeChild(labelElement);
210
- labelElement = undefined;
211
- progress.labelElement = undefined;
212
- }
213
-
214
- return progress;
215
- },
216
-
217
- setLabelFormatter: (formatter: (value: number, max: number) => string) => {
218
- settings.labelFormatter = formatter;
219
-
220
- if (labelElement) {
221
- labelElement.textContent = formatter(settings.value, settings.max);
222
- }
223
-
224
- return progress;
225
- },
226
-
227
- setIndeterminate: (indeterminate: boolean) => {
228
- settings.indeterminate = indeterminate;
229
-
230
- if (indeterminate) {
231
- element.classList.add('mtrl-progress--indeterminate');
232
- } else {
233
- element.classList.remove('mtrl-progress--indeterminate');
234
- updateVisuals();
235
- }
236
-
237
- return progress;
238
- },
239
-
240
- isIndeterminate: () => settings.indeterminate,
241
-
242
- on: (event: string, handler: Function) => {
243
- if (!eventHandlers[event]) {
244
- eventHandlers[event] = [];
245
- }
246
-
247
- eventHandlers[event].push(handler);
248
- return progress;
249
- },
250
-
251
- off: (event: string, handler: Function) => {
252
- if (eventHandlers[event]) {
253
- eventHandlers[event] = eventHandlers[event].filter(h => h !== handler);
254
- }
255
-
256
- return progress;
257
- },
258
-
259
- destroy: () => {
260
- // Remove element from DOM if it has a parent
261
- if (element.parentNode) {
262
- element.parentNode.removeChild(element);
263
- }
264
-
265
- // Clear event handlers
266
- for (const event in eventHandlers) {
267
- eventHandlers[event] = [];
268
- }
269
- },
270
-
271
- addClass: (...classes: string[]) => {
272
- classes.forEach(className => element.classList.add(className));
273
- return progress;
274
- },
275
-
276
- disabled: {
277
- enable: () => {
278
- settings.disabled = false;
279
- element.classList.remove('mtrl-progress--disabled');
280
- },
281
-
282
- disable: () => {
283
- settings.disabled = true;
284
- element.classList.add('mtrl-progress--disabled');
285
- },
286
-
287
- isDisabled: () => settings.disabled
288
- },
289
-
290
- lifecycle: {
291
- destroy: () => {
292
- progress.destroy();
293
- }
294
- }
295
- };
296
-
297
- return progress;
298
- };
299
-
300
- describe('Progress Component', () => {
301
- test('should create a progress element', () => {
302
- const progress = createMockProgress();
303
-
304
- expect(progress.element).toBeDefined();
305
- expect(progress.element.tagName).toBe('DIV');
306
- expect(progress.element.className).toContain('mtrl-progress');
307
-
308
- expect(progress.trackElement).toBeDefined();
309
- expect(progress.trackElement.className).toContain('mtrl-progress-track');
310
-
311
- expect(progress.indicatorElement).toBeDefined();
312
- expect(progress.indicatorElement.className).toContain('mtrl-progress-indicator');
313
- });
314
-
315
- test('should apply linear variant by default', () => {
316
- const progress = createMockProgress();
317
-
318
- expect(progress.element.className).toContain('mtrl-progress--linear');
319
- expect(progress.bufferElement).toBeDefined();
320
- });
321
-
322
- test('should apply circular variant when specified', () => {
323
- const progress = createMockProgress({
324
- variant: PROGRESS_VARIANTS.CIRCULAR
325
- });
326
-
327
- expect(progress.element.className).toContain('mtrl-progress--circular');
328
- expect(progress.bufferElement).toBeUndefined();
329
- });
330
-
331
- test('should set initial value', () => {
332
- const progress = createMockProgress({
333
- value: 25
334
- });
335
-
336
- expect(progress.getValue()).toBe(25);
337
- expect(progress.indicatorElement.style.width).toBe('25%');
338
- });
339
-
340
- test('should set initial buffer value', () => {
341
- const progress = createMockProgress({
342
- buffer: 50
343
- });
344
-
345
- expect(progress.getBuffer()).toBe(50);
346
- expect(progress.bufferElement?.style.width).toBe('50%');
347
- });
348
-
349
- test('should apply disabled state', () => {
350
- const progress = createMockProgress({
351
- disabled: true
352
- });
353
-
354
- expect(progress.element.className).toContain('mtrl-progress--disabled');
355
- expect(progress.isDisabled()).toBe(true);
356
- });
357
-
358
- test('should apply indeterminate state', () => {
359
- const progress = createMockProgress({
360
- indeterminate: true
361
- });
362
-
363
- expect(progress.element.className).toContain('mtrl-progress--indeterminate');
364
- expect(progress.isIndeterminate()).toBe(true);
365
- });
366
-
367
- test('should show label when configured', () => {
368
- const progress = createMockProgress({
369
- showLabel: true,
370
- value: 75
371
- });
372
-
373
- expect(progress.labelElement).toBeDefined();
374
- expect(progress.labelElement?.textContent).toBe('75%');
375
- });
376
-
377
- test('should use custom label formatter', () => {
378
- const formatter = (value: number, max: number) => `${value} of ${max}`;
379
-
380
- const progress = createMockProgress({
381
- showLabel: true,
382
- value: 50,
383
- max: 200,
384
- labelFormatter: formatter
385
- });
386
-
387
- expect(progress.labelElement?.textContent).toBe('50 of 200');
388
- });
389
-
390
- test('should update value and appearance', () => {
391
- const progress = createMockProgress({
392
- value: 0
393
- });
394
-
395
- expect(progress.getValue()).toBe(0);
396
- expect(progress.indicatorElement.style.width).toBe('0%');
397
-
398
- progress.setValue(60);
399
-
400
- expect(progress.getValue()).toBe(60);
401
- expect(progress.indicatorElement.style.width).toBe('60%');
402
- });
403
-
404
- test('should update buffer value', () => {
405
- const progress = createMockProgress();
406
-
407
- expect(progress.getBuffer()).toBe(0);
408
-
409
- progress.setBuffer(75);
410
-
411
- expect(progress.getBuffer()).toBe(75);
412
- expect(progress.bufferElement?.style.width).toBe('75%');
413
- });
414
-
415
- test('should constrain values within bounds', () => {
416
- const progress = createMockProgress({
417
- max: 100
418
- });
419
-
420
- progress.setValue(-10);
421
- expect(progress.getValue()).toBe(0);
422
-
423
- progress.setValue(150);
424
- expect(progress.getValue()).toBe(100);
425
-
426
- progress.setBuffer(-20);
427
- expect(progress.getBuffer()).toBe(0);
428
-
429
- progress.setBuffer(200);
430
- expect(progress.getBuffer()).toBe(100);
431
- });
432
-
433
- test('should toggle disabled state', () => {
434
- const progress = createMockProgress();
435
-
436
- expect(progress.isDisabled()).toBe(false);
437
-
438
- progress.disable();
439
-
440
- expect(progress.isDisabled()).toBe(true);
441
- expect(progress.element.className).toContain('mtrl-progress--disabled');
442
-
443
- progress.enable();
444
-
445
- expect(progress.isDisabled()).toBe(false);
446
- expect(progress.element.className).not.toContain('mtrl-progress--disabled');
447
- });
448
-
449
- test('should toggle indeterminate state', () => {
450
- const progress = createMockProgress();
451
-
452
- expect(progress.isIndeterminate()).toBe(false);
453
-
454
- progress.setIndeterminate(true);
455
-
456
- expect(progress.isIndeterminate()).toBe(true);
457
- expect(progress.element.className).toContain('mtrl-progress--indeterminate');
458
-
459
- progress.setIndeterminate(false);
460
-
461
- expect(progress.isIndeterminate()).toBe(false);
462
- expect(progress.element.className).not.toContain('mtrl-progress--indeterminate');
463
- });
464
-
465
- test('should show and hide label', () => {
466
- const progress = createMockProgress();
467
-
468
- expect(progress.labelElement).toBeUndefined();
469
-
470
- progress.showLabel();
471
-
472
- expect(progress.labelElement).toBeDefined();
473
- expect(progress.element.contains(progress.labelElement)).toBe(true);
474
-
475
- progress.hideLabel();
476
-
477
- expect(progress.labelElement).toBeUndefined();
478
- expect(progress.element.querySelector('.mtrl-progress-label')).toBeNull();
479
- });
480
-
481
- test('should update label formatter', () => {
482
- const progress = createMockProgress({
483
- showLabel: true,
484
- value: 50
485
- });
486
-
487
- expect(progress.labelElement?.textContent).toBe('50%');
488
-
489
- progress.setLabelFormatter((value) => `${value} units`);
490
-
491
- expect(progress.labelElement?.textContent).toBe('50 units');
492
- });
493
-
494
- test('should emit change event when value changes', () => {
495
- const progress = createMockProgress();
496
- let changeEventFired = false;
497
- let eventData = null;
498
-
499
- progress.on(PROGRESS_EVENTS.CHANGE, (data) => {
500
- changeEventFired = true;
501
- eventData = data;
502
- });
503
-
504
- progress.setValue(50);
505
-
506
- expect(changeEventFired).toBe(true);
507
- expect(eventData).toEqual({ value: 50, oldValue: 0 });
508
- });
509
-
510
- test('should emit complete event when reaching max', () => {
511
- const progress = createMockProgress({
512
- value: 50,
513
- max: 100
514
- });
515
-
516
- let completeEventFired = false;
517
-
518
- progress.on(PROGRESS_EVENTS.COMPLETE, () => {
519
- completeEventFired = true;
520
- });
521
-
522
- progress.setValue(99);
523
- expect(completeEventFired).toBe(false);
524
-
525
- progress.setValue(100);
526
- expect(completeEventFired).toBe(true);
527
- });
528
-
529
- test('should remove event listeners', () => {
530
- const progress = createMockProgress();
531
- let eventCount = 0;
532
-
533
- const handler = () => {
534
- eventCount++;
535
- };
536
-
537
- progress.on(PROGRESS_EVENTS.CHANGE, handler);
538
-
539
- progress.setValue(10);
540
- expect(eventCount).toBe(1);
541
-
542
- progress.off(PROGRESS_EVENTS.CHANGE, handler);
543
-
544
- progress.setValue(20);
545
- expect(eventCount).toBe(1); // Count should not increase
546
- });
547
-
548
- test('should add CSS classes', () => {
549
- const progress = createMockProgress();
550
-
551
- progress.addClass('custom-class', 'special-progress');
552
-
553
- expect(progress.element.className).toContain('custom-class');
554
- expect(progress.element.className).toContain('special-progress');
555
- });
556
-
557
- test('should be properly destroyed', () => {
558
- const progress = createMockProgress();
559
- document.body.appendChild(progress.element);
560
-
561
- expect(document.body.contains(progress.element)).toBe(true);
562
-
563
- progress.destroy();
564
-
565
- expect(document.body.contains(progress.element)).toBe(false);
566
- });
567
- });