ai-progress-controls 0.1.0

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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +823 -0
  3. package/dist/ai-progress-controls.es.js +7191 -0
  4. package/dist/ai-progress-controls.es.js.map +1 -0
  5. package/dist/ai-progress-controls.umd.js +2 -0
  6. package/dist/ai-progress-controls.umd.js.map +1 -0
  7. package/dist/index.d.ts +2212 -0
  8. package/package.json +105 -0
  9. package/src/__tests__/setup.ts +93 -0
  10. package/src/core/base/AIControl.ts +230 -0
  11. package/src/core/base/index.ts +3 -0
  12. package/src/core/base/types.ts +77 -0
  13. package/src/core/base/utils.ts +168 -0
  14. package/src/core/batch-progress/BatchProgress.test.ts +458 -0
  15. package/src/core/batch-progress/BatchProgress.ts +760 -0
  16. package/src/core/batch-progress/index.ts +14 -0
  17. package/src/core/batch-progress/styles.ts +480 -0
  18. package/src/core/batch-progress/types.ts +169 -0
  19. package/src/core/model-loader/ModelLoader.test.ts +311 -0
  20. package/src/core/model-loader/ModelLoader.ts +673 -0
  21. package/src/core/model-loader/index.ts +2 -0
  22. package/src/core/model-loader/styles.ts +496 -0
  23. package/src/core/model-loader/types.ts +127 -0
  24. package/src/core/parameter-panel/ParameterPanel.test.ts +856 -0
  25. package/src/core/parameter-panel/ParameterPanel.ts +877 -0
  26. package/src/core/parameter-panel/index.ts +14 -0
  27. package/src/core/parameter-panel/styles.ts +323 -0
  28. package/src/core/parameter-panel/types.ts +278 -0
  29. package/src/core/parameter-slider/ParameterSlider.test.ts +299 -0
  30. package/src/core/parameter-slider/ParameterSlider.ts +653 -0
  31. package/src/core/parameter-slider/index.ts +8 -0
  32. package/src/core/parameter-slider/styles.ts +493 -0
  33. package/src/core/parameter-slider/types.ts +107 -0
  34. package/src/core/queue-progress/QueueProgress.test.ts +344 -0
  35. package/src/core/queue-progress/QueueProgress.ts +563 -0
  36. package/src/core/queue-progress/index.ts +5 -0
  37. package/src/core/queue-progress/styles.ts +469 -0
  38. package/src/core/queue-progress/types.ts +130 -0
  39. package/src/core/retry-progress/RetryProgress.test.ts +397 -0
  40. package/src/core/retry-progress/RetryProgress.ts +957 -0
  41. package/src/core/retry-progress/index.ts +6 -0
  42. package/src/core/retry-progress/styles.ts +530 -0
  43. package/src/core/retry-progress/types.ts +176 -0
  44. package/src/core/stream-progress/StreamProgress.test.ts +531 -0
  45. package/src/core/stream-progress/StreamProgress.ts +517 -0
  46. package/src/core/stream-progress/index.ts +2 -0
  47. package/src/core/stream-progress/styles.ts +349 -0
  48. package/src/core/stream-progress/types.ts +82 -0
  49. package/src/index.ts +19 -0
@@ -0,0 +1,299 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { ParameterSlider } from './ParameterSlider';
3
+ import { waitForElement, waitForNextTick } from '../../__tests__/setup';
4
+
5
+ describe('ParameterSlider Component', () => {
6
+ let slider: ParameterSlider;
7
+
8
+ beforeEach(() => {
9
+ slider = new ParameterSlider();
10
+ document.body.appendChild(slider);
11
+ });
12
+
13
+ afterEach(() => {
14
+ if (slider.parentNode) {
15
+ slider.remove();
16
+ }
17
+ });
18
+
19
+ describe('Constructor & Configuration', () => {
20
+ it('should create instance with default config', () => {
21
+ expect(slider).toBeInstanceOf(ParameterSlider);
22
+ expect(slider.tagName.toLowerCase()).toBe('parameter-slider');
23
+ });
24
+
25
+ it('should accept custom configuration', () => {
26
+ const customSlider = new ParameterSlider({
27
+ label: 'Temperature',
28
+ min: 0,
29
+ max: 2,
30
+ value: 0.7,
31
+ step: 0.1,
32
+ });
33
+
34
+ const config = customSlider.getConfig();
35
+ expect(config.label).toBe('Temperature');
36
+ expect(config.min).toBe(0);
37
+ expect(config.max).toBe(2);
38
+ customSlider.remove();
39
+ });
40
+
41
+ it('should have shadow root', async () => {
42
+ await waitForElement(slider);
43
+ expect(slider.shadowRoot).toBeTruthy();
44
+ });
45
+ });
46
+
47
+ describe('State Management', () => {
48
+ it('should initialize with default value', () => {
49
+ const state = slider.getState();
50
+ expect(state.currentValue).toBeDefined();
51
+ expect(typeof state.currentValue).toBe('number');
52
+ });
53
+
54
+ it('should track value changes', () => {
55
+ const initialValue = slider.getValue();
56
+ slider.setValue(0.8);
57
+
58
+ expect(slider.getValue()).toBe(0.8);
59
+ expect(slider.getValue()).not.toBe(initialValue);
60
+ });
61
+ });
62
+
63
+ describe('Methods', () => {
64
+ describe('getValue()', () => {
65
+ it('should return current value', () => {
66
+ const value = slider.getValue();
67
+ expect(typeof value).toBe('number');
68
+ });
69
+
70
+ it('should return updated value after setValue', () => {
71
+ slider.setValue(0.5);
72
+ expect(slider.getValue()).toBe(0.5);
73
+ });
74
+ });
75
+
76
+ describe('setValue()', () => {
77
+ it('should update slider value', () => {
78
+ slider.setValue(0.9);
79
+ expect(slider.getValue()).toBe(0.9);
80
+ });
81
+
82
+ it('should emit valuechange event', async () => {
83
+ const spy = vi.fn();
84
+ slider.addEventListener('valuechange', spy);
85
+
86
+ slider.setValue(0.6);
87
+ await waitForNextTick();
88
+
89
+ expect(spy).toHaveBeenCalled();
90
+ });
91
+
92
+ it('should clamp value to min/max', () => {
93
+ const config = slider.getConfig();
94
+
95
+ slider.setValue(config.max + 1);
96
+ expect(slider.getValue()).toBeLessThanOrEqual(config.max);
97
+
98
+ slider.setValue(config.min - 1);
99
+ expect(slider.getValue()).toBeGreaterThanOrEqual(config.min);
100
+ });
101
+ });
102
+
103
+ describe('reset()', () => {
104
+ it('should reset to default value', () => {
105
+ const config = slider.getConfig();
106
+ const defaultValue = config.defaultValue;
107
+
108
+ slider.setValue(0.9);
109
+ slider.reset();
110
+
111
+ expect(slider.getValue()).toBe(defaultValue);
112
+ });
113
+
114
+ it('should emit valuechange event on reset', async () => {
115
+ const spy = vi.fn();
116
+ slider.addEventListener('valuechange', spy);
117
+
118
+ slider.setValue(0.9);
119
+ slider.reset();
120
+ await waitForNextTick();
121
+
122
+ expect(spy).toHaveBeenCalled();
123
+ });
124
+ });
125
+
126
+ describe('selectPreset()', () => {
127
+ it('should select preset if available', () => {
128
+ const customSlider = new ParameterSlider({
129
+ label: 'Temperature',
130
+ presets: [
131
+ { value: 0.3, label: 'Conservative' },
132
+ { value: 0.7, label: 'Balanced' },
133
+ ],
134
+ });
135
+ document.body.appendChild(customSlider);
136
+
137
+ customSlider.selectPreset({ value: 0.3, label: 'Conservative' });
138
+ expect(customSlider.getValue()).toBe(0.3);
139
+
140
+ customSlider.remove();
141
+ });
142
+ });
143
+ });
144
+
145
+ describe('Properties', () => {
146
+ it('should get/set disabled state', () => {
147
+ expect(slider.disabled).toBe(false);
148
+
149
+ slider.disabled = true;
150
+ expect(slider.disabled).toBe(true);
151
+ });
152
+
153
+ it('should get/set value property', () => {
154
+ slider.value = 0.75;
155
+ expect(slider.value).toBe(0.75);
156
+ });
157
+ });
158
+
159
+ describe('Rendering', () => {
160
+ it('should render in shadow DOM', async () => {
161
+ await waitForElement(slider);
162
+ expect(slider.shadowRoot?.querySelector('.parameter-slider')).toBeTruthy();
163
+ });
164
+
165
+ it('should render slider controls', async () => {
166
+ await waitForElement(slider);
167
+ const track = slider.shadowRoot?.querySelector('.slider-track');
168
+ expect(track).toBeTruthy();
169
+ });
170
+ });
171
+
172
+ describe('Accessibility', () => {
173
+ it('should have proper ARIA attributes', async () => {
174
+ await waitForElement(slider);
175
+ const thumb = slider.shadowRoot?.querySelector('.slider-thumb');
176
+
177
+ expect(thumb?.getAttribute('role')).toBe('slider');
178
+ expect(thumb?.hasAttribute('tabindex')).toBe(true);
179
+ });
180
+
181
+ it('should be keyboard accessible', async () => {
182
+ await waitForElement(slider);
183
+ const thumb = slider.shadowRoot?.querySelector('.slider-thumb') as HTMLElement;
184
+
185
+ expect(thumb.tabIndex).toBeGreaterThanOrEqual(0);
186
+ });
187
+ });
188
+
189
+ describe('Edge Cases', () => {
190
+ it('should handle zero value', () => {
191
+ slider.setValue(0);
192
+ expect(slider.getValue()).toBe(0);
193
+ });
194
+
195
+ it('should handle max value', () => {
196
+ const config = slider.getConfig();
197
+ slider.setValue(config.max);
198
+ expect(slider.getValue()).toBe(config.max);
199
+ });
200
+
201
+ it('should handle rapid value changes', async () => {
202
+ const values = [0.1, 0.2, 0.3, 0.4, 0.5];
203
+
204
+ for (const val of values) {
205
+ slider.setValue(val);
206
+ await waitForNextTick();
207
+ }
208
+
209
+ expect(slider.getValue()).toBe(0.5);
210
+ });
211
+ });
212
+
213
+ describe('Size Variants', () => {
214
+ it('should default to default size', () => {
215
+ expect(slider['config'].size).toBe('default');
216
+ });
217
+
218
+ it('should accept size in constructor', () => {
219
+ const compact = new ParameterSlider({ size: 'compact' });
220
+ expect(compact['config'].size).toBe('compact');
221
+ compact.remove();
222
+
223
+ const large = new ParameterSlider({ size: 'large' });
224
+ expect(large['config'].size).toBe('large');
225
+ large.remove();
226
+ });
227
+
228
+ it('should update size via attribute', async () => {
229
+ await waitForElement(slider);
230
+
231
+ slider.setAttribute('size', 'compact');
232
+ await waitForNextTick();
233
+ expect(slider['config'].size).toBe('compact');
234
+ expect(slider.getAttribute('size')).toBe('compact');
235
+
236
+ slider.setAttribute('size', 'large');
237
+ await waitForNextTick();
238
+ expect(slider['config'].size).toBe('large');
239
+ expect(slider.getAttribute('size')).toBe('large');
240
+ });
241
+
242
+ it('should apply size attribute to host element', async () => {
243
+ await waitForElement(slider);
244
+
245
+ slider.setAttribute('size', 'compact');
246
+ await waitForNextTick();
247
+ expect(slider.hasAttribute('size')).toBe(true);
248
+ expect(slider.getAttribute('size')).toBe('compact');
249
+ });
250
+ });
251
+
252
+ describe('Visual Variants', () => {
253
+ it('should apply default variant by default', () => {
254
+ expect(slider['config'].variant).toBe('default');
255
+ });
256
+
257
+ it('should apply minimal variant', () => {
258
+ const minimal = new ParameterSlider({ variant: 'minimal' });
259
+ expect(minimal['config'].variant).toBe('minimal');
260
+ minimal.remove();
261
+ });
262
+
263
+ it('should apply gradient variant', () => {
264
+ const gradient = new ParameterSlider({ variant: 'gradient' });
265
+ expect(gradient['config'].variant).toBe('gradient');
266
+ gradient.remove();
267
+ });
268
+
269
+ it('should apply glassmorphic variant', () => {
270
+ const glassmorphic = new ParameterSlider({ variant: 'glassmorphic' });
271
+ expect(glassmorphic['config'].variant).toBe('glassmorphic');
272
+ glassmorphic.remove();
273
+ });
274
+ });
275
+
276
+ describe('Animation Effects', () => {
277
+ it('should apply none animation by default', () => {
278
+ expect(slider['config'].animation).toBe('none');
279
+ });
280
+
281
+ it('should apply striped animation', () => {
282
+ const striped = new ParameterSlider({ animation: 'striped' });
283
+ expect(striped['config'].animation).toBe('striped');
284
+ striped.remove();
285
+ });
286
+
287
+ it('should apply pulse animation', () => {
288
+ const pulse = new ParameterSlider({ animation: 'pulse' });
289
+ expect(pulse['config'].animation).toBe('pulse');
290
+ pulse.remove();
291
+ });
292
+
293
+ it('should apply glow animation', () => {
294
+ const glow = new ParameterSlider({ animation: 'glow' });
295
+ expect(glow['config'].animation).toBe('glow');
296
+ glow.remove();
297
+ });
298
+ });
299
+ });