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,311 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { ModelLoader } from './ModelLoader';
3
+ import { waitForElement, waitForNextTick } from '../../__tests__/setup';
4
+
5
+ describe('ModelLoader Component', () => {
6
+ let loader: ModelLoader;
7
+
8
+ beforeEach(() => {
9
+ loader = new ModelLoader();
10
+ document.body.appendChild(loader);
11
+ });
12
+
13
+ afterEach(() => {
14
+ if (loader.parentNode) {
15
+ loader.remove();
16
+ }
17
+ });
18
+
19
+ describe('Constructor & Configuration', () => {
20
+ it('should create instance with default config', () => {
21
+ expect(loader).toBeInstanceOf(ModelLoader);
22
+ expect(loader.tagName.toLowerCase()).toBe('model-loader');
23
+ });
24
+
25
+ it('should accept custom configuration', () => {
26
+ const customLoader = new ModelLoader({
27
+ modelName: 'Custom Model',
28
+ showBytes: true,
29
+ showMemoryUsage: true,
30
+ });
31
+
32
+ const config = customLoader.getConfig();
33
+ expect(config.modelName).toBe('Custom Model');
34
+ expect(config.showBytes).toBe(true);
35
+ customLoader.remove();
36
+ });
37
+
38
+ it('should have shadow root', async () => {
39
+ await waitForElement(loader);
40
+ expect(loader.shadowRoot).toBeTruthy();
41
+ });
42
+ });
43
+
44
+ describe('State Management', () => {
45
+ it('should initialize with idle state', () => {
46
+ const state = loader.getState();
47
+ expect(state.isLoading).toBe(false);
48
+ expect(state.currentStage).toBe('download'); // First stage by default
49
+ });
50
+
51
+ it('should update state when started', () => {
52
+ loader.start('Loading model...');
53
+ const state = loader.getState();
54
+
55
+ expect(state.isLoading).toBe(true);
56
+ expect(state.currentStage).toBe('download');
57
+ });
58
+ });
59
+
60
+ describe('Methods', () => {
61
+ describe('start()', () => {
62
+ it('should start loading process', () => {
63
+ loader.start('Loading...');
64
+ const state = loader.getState();
65
+
66
+ expect(state.isLoading).toBe(true);
67
+ expect(state.currentStage).toBe('download');
68
+ });
69
+
70
+ it('should emit loadstart event', async () => {
71
+ const spy = vi.fn();
72
+ loader.addEventListener('loadstart', spy);
73
+
74
+ loader.start();
75
+ await waitForNextTick();
76
+
77
+ expect(spy).toHaveBeenCalled();
78
+ });
79
+ });
80
+
81
+ describe('updateStage()', () => {
82
+ beforeEach(() => {
83
+ loader.start();
84
+ });
85
+
86
+ it('should update stage progress', () => {
87
+ loader.updateStage('download', { progress: 50 });
88
+ const state = loader.getState();
89
+
90
+ expect(state.stages.download.progress).toBe(50);
91
+ });
92
+
93
+ it('should emit stageupdate event', async () => {
94
+ const spy = vi.fn();
95
+ loader.addEventListener('stageupdate', spy);
96
+
97
+ loader.updateStage('download', { progress: 75 });
98
+ await waitForNextTick();
99
+
100
+ expect(spy).toHaveBeenCalled();
101
+ });
102
+ });
103
+
104
+ describe('setStage()', () => {
105
+ beforeEach(() => {
106
+ loader.start();
107
+ });
108
+
109
+ it('should change current stage', () => {
110
+ loader.setStage('load');
111
+ const state = loader.getState();
112
+
113
+ expect(state.currentStage).toBe('load');
114
+ });
115
+ });
116
+
117
+ describe('completeStage()', () => {
118
+ beforeEach(() => {
119
+ loader.start();
120
+ });
121
+
122
+ it('should mark current stage as complete', () => {
123
+ loader.setStage('download');
124
+ loader.updateStage('download', { progress: 100 });
125
+ loader.completeStage();
126
+
127
+ const state = loader.getState();
128
+ expect(state.stages.download.status).toBe('completed');
129
+ });
130
+
131
+ it('should advance to next stage', () => {
132
+ loader.setStage('download');
133
+ loader.completeStage();
134
+
135
+ const state = loader.getState();
136
+ expect(state.currentStage).toBe('load');
137
+ });
138
+ });
139
+
140
+ describe('complete()', () => {
141
+ beforeEach(() => {
142
+ loader.start();
143
+ });
144
+
145
+ it('should complete loading process', () => {
146
+ loader.complete();
147
+ const state = loader.getState();
148
+
149
+ expect(state.isLoading).toBe(false);
150
+ expect(state.currentStage).toBe('ready');
151
+ });
152
+
153
+ it('should emit loadcomplete event', async () => {
154
+ const spy = vi.fn();
155
+ loader.addEventListener('loadcomplete', spy);
156
+
157
+ loader.complete();
158
+ await waitForNextTick();
159
+
160
+ expect(spy).toHaveBeenCalled();
161
+ });
162
+ });
163
+
164
+ describe('error()', () => {
165
+ beforeEach(() => {
166
+ loader.start();
167
+ });
168
+
169
+ it('should handle error', () => {
170
+ loader.error('Failed to load');
171
+ const state = loader.getState();
172
+
173
+ expect(state.isLoading).toBe(false);
174
+ expect(state.hasError).toBe(true);
175
+ });
176
+
177
+ it('should emit loaderror event', async () => {
178
+ const spy = vi.fn();
179
+ loader.addEventListener('loaderror', spy);
180
+
181
+ loader.error('Test error');
182
+ await waitForNextTick();
183
+
184
+ expect(spy).toHaveBeenCalled();
185
+ });
186
+ });
187
+
188
+ describe('reset()', () => {
189
+ it('should reset to initial state', () => {
190
+ loader.start();
191
+ loader.updateStage('download', { progress: 50 });
192
+ loader.reset();
193
+
194
+ const state = loader.getState();
195
+ expect(state.isLoading).toBe(false);
196
+ expect(state.currentStage).toBe('download');
197
+ });
198
+ });
199
+ });
200
+
201
+ describe('Properties', () => {
202
+ it('should get/set disabled state', () => {
203
+ expect(loader.disabled).toBe(false);
204
+
205
+ loader.disabled = true;
206
+ expect(loader.disabled).toBe(true);
207
+ });
208
+ });
209
+
210
+ describe('Rendering', () => {
211
+ it('should render in shadow DOM', async () => {
212
+ await waitForElement(loader);
213
+ expect(loader.shadowRoot?.querySelector('.model-loader')).toBeTruthy();
214
+ });
215
+ });
216
+
217
+ describe('Accessibility', () => {
218
+ it('should have proper ARIA role', async () => {
219
+ await waitForElement(loader);
220
+ const role = loader.getAttribute('role');
221
+ expect(role).toBe('progressbar');
222
+ });
223
+ });
224
+
225
+ describe('Size Variants', () => {
226
+ it('should default to default size', () => {
227
+ expect(loader['config'].size).toBe('default');
228
+ });
229
+
230
+ it('should accept size in constructor', () => {
231
+ const compact = new ModelLoader({ size: 'compact' });
232
+ expect(compact['config'].size).toBe('compact');
233
+ compact.remove();
234
+
235
+ const large = new ModelLoader({ size: 'large' });
236
+ expect(large['config'].size).toBe('large');
237
+ large.remove();
238
+ });
239
+
240
+ it('should update size via attribute', async () => {
241
+ await waitForElement(loader);
242
+
243
+ loader.setAttribute('size', 'compact');
244
+ await waitForNextTick();
245
+ expect(loader['config'].size).toBe('compact');
246
+ expect(loader.getAttribute('size')).toBe('compact');
247
+
248
+ loader.setAttribute('size', 'large');
249
+ await waitForNextTick();
250
+ expect(loader['config'].size).toBe('large');
251
+ expect(loader.getAttribute('size')).toBe('large');
252
+ });
253
+
254
+ it('should apply size attribute to host element', async () => {
255
+ await waitForElement(loader);
256
+
257
+ loader.setAttribute('size', 'compact');
258
+ await waitForNextTick();
259
+ expect(loader.hasAttribute('size')).toBe(true);
260
+ expect(loader.getAttribute('size')).toBe('compact');
261
+ });
262
+ });
263
+
264
+ describe('Visual Variants', () => {
265
+ it('should apply default variant by default', () => {
266
+ expect(loader['config'].variant).toBe('default');
267
+ });
268
+
269
+ it('should apply minimal variant', () => {
270
+ const minimal = new ModelLoader({ variant: 'minimal' });
271
+ expect(minimal['config'].variant).toBe('minimal');
272
+ minimal.remove();
273
+ });
274
+
275
+ it('should apply gradient variant', () => {
276
+ const gradient = new ModelLoader({ variant: 'gradient' });
277
+ expect(gradient['config'].variant).toBe('gradient');
278
+ gradient.remove();
279
+ });
280
+
281
+ it('should apply glassmorphic variant', () => {
282
+ const glassmorphic = new ModelLoader({ variant: 'glassmorphic' });
283
+ expect(glassmorphic['config'].variant).toBe('glassmorphic');
284
+ glassmorphic.remove();
285
+ });
286
+ });
287
+
288
+ describe('Animation Effects', () => {
289
+ it('should apply none animation by default', () => {
290
+ expect(loader['config'].animation).toBe('none');
291
+ });
292
+
293
+ it('should apply striped animation', () => {
294
+ const striped = new ModelLoader({ animation: 'striped' });
295
+ expect(striped['config'].animation).toBe('striped');
296
+ striped.remove();
297
+ });
298
+
299
+ it('should apply pulse animation', () => {
300
+ const pulse = new ModelLoader({ animation: 'pulse' });
301
+ expect(pulse['config'].animation).toBe('pulse');
302
+ pulse.remove();
303
+ });
304
+
305
+ it('should apply glow animation', () => {
306
+ const glow = new ModelLoader({ animation: 'glow' });
307
+ expect(glow['config'].animation).toBe('glow');
308
+ glow.remove();
309
+ });
310
+ });
311
+ });