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,6 @@
1
+ /**
2
+ * RetryProgress module exports
3
+ */
4
+
5
+ export * from './types';
6
+ export { RetryProgress } from './RetryProgress';
@@ -0,0 +1,530 @@
1
+ /**
2
+ * Styles for RetryProgress component
3
+ */
4
+
5
+ export const styles = `
6
+ :host {
7
+ /* CSS variables inherit from document root with fallback defaults */
8
+ display: block;
9
+ font-family: var(--ai-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
10
+ font-size: var(--ai-font-size, 14px);
11
+ }
12
+
13
+ :host([style*="cursor: progress"]) .retry-container {
14
+ cursor: progress;
15
+ }
16
+
17
+ :host([style*="cursor: wait"]) .retry-container {
18
+ cursor: wait;
19
+ }
20
+
21
+ :host([style*="cursor: not-allowed"]) .retry-container {
22
+ cursor: not-allowed;
23
+ }
24
+
25
+ :host([style*="cursor: default"]) .retry-container {
26
+ cursor: default;
27
+ }
28
+
29
+ .retry-container {
30
+ background: var(--retry-background);
31
+ border-radius: 12px;
32
+ padding: 20px;
33
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
34
+ border: 1px solid var(--retry-border);
35
+ }
36
+
37
+ .retry-container.disabled {
38
+ opacity: 0.6;
39
+ pointer-events: none;
40
+ }
41
+
42
+ /* Header */
43
+ .retry-header {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 12px;
47
+ margin-bottom: 16px;
48
+ }
49
+
50
+ .retry-icon {
51
+ font-size: 32px;
52
+ animation: rotate 2s linear infinite;
53
+ }
54
+
55
+ .retry-icon.success {
56
+ animation: none;
57
+ }
58
+
59
+ .retry-icon.failed {
60
+ animation: shake 0.5s ease;
61
+ }
62
+
63
+ @keyframes rotate {
64
+ from { transform: rotate(0deg); }
65
+ to { transform: rotate(360deg); }
66
+ }
67
+
68
+ @keyframes shake {
69
+ 0%, 100% { transform: translateX(0); }
70
+ 25% { transform: translateX(-5px); }
71
+ 75% { transform: translateX(5px); }
72
+ }
73
+
74
+ .retry-info {
75
+ flex: 1;
76
+ }
77
+
78
+ .retry-title {
79
+ font-size: 16px;
80
+ font-weight: 600;
81
+ color: var(--retry-text);
82
+ margin: 0 0 4px 0;
83
+ }
84
+
85
+ .retry-message {
86
+ font-size: 14px;
87
+ color: var(--retry-text-secondary);
88
+ margin: 0;
89
+ }
90
+
91
+ /* Status Badge */
92
+ .status-badge {
93
+ display: inline-flex;
94
+ align-items: center;
95
+ gap: 6px;
96
+ padding: 4px 12px;
97
+ border-radius: 12px;
98
+ font-size: 12px;
99
+ font-weight: 600;
100
+ text-transform: uppercase;
101
+ letter-spacing: 0.5px;
102
+ }
103
+
104
+ .status-badge.idle {
105
+ background: #4b5563;
106
+ color: #d1d5db;
107
+ }
108
+
109
+ .status-badge.attempting {
110
+ background: #3b82f6;
111
+ color: white;
112
+ animation: pulse 2s infinite;
113
+ }
114
+
115
+ .status-badge.waiting {
116
+ background: var(--retry-primary);
117
+ color: white;
118
+ }
119
+
120
+ .status-badge.success {
121
+ background: var(--retry-success);
122
+ color: white;
123
+ }
124
+
125
+ .status-badge.failed {
126
+ background: var(--retry-error);
127
+ color: white;
128
+ }
129
+
130
+ .status-badge.cancelled {
131
+ background: #6b7280;
132
+ color: white;
133
+ }
134
+
135
+ @keyframes pulse {
136
+ 0%, 100% { opacity: 1; }
137
+ 50% { opacity: 0.7; }
138
+ }
139
+
140
+ /* Attempt Counter */
141
+ .attempt-counter {
142
+ text-align: center;
143
+ margin: 16px 0;
144
+ }
145
+
146
+ .attempt-number {
147
+ font-size: 48px;
148
+ font-weight: 700;
149
+ color: var(--retry-primary);
150
+ line-height: 1;
151
+ margin-bottom: 8px;
152
+ }
153
+
154
+ .attempt-number.success {
155
+ color: var(--retry-success);
156
+ }
157
+
158
+ .attempt-number.failed {
159
+ color: var(--retry-error);
160
+ }
161
+
162
+ .attempt-label {
163
+ font-size: 14px;
164
+ color: var(--retry-text-secondary);
165
+ text-transform: uppercase;
166
+ letter-spacing: 1px;
167
+ }
168
+
169
+ /* Metrics Grid */
170
+ .metrics-grid {
171
+ display: grid;
172
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
173
+ gap: 12px;
174
+ margin: 16px 0;
175
+ }
176
+
177
+ .metric {
178
+ background: rgba(0, 0, 0, 0.3);
179
+ border-radius: 8px;
180
+ padding: 12px;
181
+ text-align: center;
182
+ border: 1px solid rgba(255, 255, 255, 0.1);
183
+ }
184
+
185
+ .metric-value {
186
+ font-size: 20px;
187
+ font-weight: 600;
188
+ color: var(--retry-text);
189
+ margin-bottom: 4px;
190
+ }
191
+
192
+ .metric-label {
193
+ font-size: 11px;
194
+ color: var(--retry-text-secondary);
195
+ text-transform: uppercase;
196
+ letter-spacing: 0.5px;
197
+ }
198
+
199
+ /* Progress Bar */
200
+ .progress-bar-container {
201
+ margin: 16px 0;
202
+ }
203
+
204
+ .progress-label {
205
+ font-size: 12px;
206
+ color: var(--retry-text-secondary);
207
+ margin-bottom: 8px;
208
+ text-transform: uppercase;
209
+ letter-spacing: 0.5px;
210
+ }
211
+
212
+ .progress-bar {
213
+ height: 8px;
214
+ background: rgba(0, 0, 0, 0.3);
215
+ border-radius: 4px;
216
+ overflow: hidden;
217
+ position: relative;
218
+ }
219
+
220
+ .progress-fill {
221
+ height: 100%;
222
+ background: linear-gradient(90deg, var(--retry-primary), #fbbf24);
223
+ border-radius: 4px;
224
+ transition: width 0.3s ease;
225
+ position: relative;
226
+ }
227
+
228
+ .progress-fill::after {
229
+ content: '';
230
+ position: absolute;
231
+ top: 0;
232
+ left: 0;
233
+ right: 0;
234
+ bottom: 0;
235
+ background: linear-gradient(
236
+ 90deg,
237
+ transparent,
238
+ rgba(255, 255, 255, 0.3),
239
+ transparent
240
+ );
241
+ animation: shimmer 2s infinite;
242
+ }
243
+
244
+ @keyframes shimmer {
245
+ 0% { transform: translateX(-100%); }
246
+ 100% { transform: translateX(100%); }
247
+ }
248
+
249
+ /* Override default animation when animation attribute is set */
250
+ :host([animation]) .progress-fill::after {
251
+ animation: none !important;
252
+ }
253
+ font-size: 13px;
254
+ color: #fca5a5;
255
+ font-family: 'Monaco', 'Courier New', monospace;
256
+ word-break: break-word;
257
+ }
258
+
259
+ /* Action Buttons */
260
+ .actions {
261
+ display: flex;
262
+ gap: 8px;
263
+ margin-top: 16px;
264
+ }
265
+
266
+ .retry-button,
267
+ .cancel-button {
268
+ flex: 1;
269
+ padding: 10px 16px;
270
+ border: none;
271
+ border-radius: 8px;
272
+ font-size: 14px;
273
+ font-weight: 600;
274
+ cursor: pointer;
275
+ transition: all 0.2s;
276
+ }
277
+
278
+ .retry-button {
279
+ background: linear-gradient(135deg, var(--retry-primary), #fbbf24);
280
+ color: white;
281
+ }
282
+
283
+ .retry-button:hover:not(:disabled) {
284
+ transform: translateY(-2px);
285
+ box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4);
286
+ }
287
+
288
+ .retry-button:disabled {
289
+ opacity: 0.5;
290
+ cursor: not-allowed;
291
+ }
292
+
293
+ .cancel-button {
294
+ background: #4b5563;
295
+ color: white;
296
+ }
297
+
298
+ .cancel-button:hover:not(:disabled) {
299
+ background: #6b7280;
300
+ }
301
+
302
+ .cancel-button:disabled {
303
+ opacity: 0.5;
304
+ cursor: not-allowed;
305
+ }
306
+
307
+ /* Success State */
308
+ .success-message {
309
+ background: rgba(16, 185, 129, 0.1);
310
+ border: 1px solid var(--retry-success);
311
+ border-radius: 8px;
312
+ padding: 16px;
313
+ margin: 16px 0;
314
+ text-align: center;
315
+ }
316
+
317
+ .success-icon {
318
+ font-size: 48px;
319
+ margin-bottom: 8px;
320
+ }
321
+
322
+ .success-text {
323
+ font-size: 16px;
324
+ font-weight: 600;
325
+ color: var(--retry-success);
326
+ margin-bottom: 4px;
327
+ }
328
+
329
+ .success-details {
330
+ font-size: 13px;
331
+ color: var(--retry-text-secondary);
332
+ }
333
+
334
+ /* Visual Variants */
335
+
336
+ /* Minimal variant - clean, no shadows */
337
+ :host([variant="minimal"]) .retry-container {
338
+ box-shadow: none;
339
+ border: 1px solid var(--retry-border);
340
+ }
341
+
342
+ :host([variant="minimal"]) .progress-bar {
343
+ background: transparent;
344
+ border: 1px solid rgba(255, 255, 255, 0.1);
345
+ }
346
+
347
+ /* Gradient variant - colorful gradients */
348
+ :host([variant="gradient"]) .progress-fill {
349
+ background: linear-gradient(
350
+ 90deg,
351
+ var(--retry-primary),
352
+ #fbbf24,
353
+ var(--retry-primary)
354
+ );
355
+ background-size: 200% 100%;
356
+ animation: gradient-shift 3s ease-in-out infinite;
357
+ }
358
+
359
+ @keyframes gradient-shift {
360
+ 0%, 100% { background-position: 0% 50%; }
361
+ 50% { background-position: 100% 50%; }
362
+ }
363
+
364
+ /* Override gradient animation when custom animation is set */
365
+ :host([animation]:not([animation="none"])[variant="gradient"]) .progress-fill {
366
+ animation: none !important;
367
+ }
368
+
369
+ /* Override default animation when animation attribute is set */
370
+ :host([animation][variant="gradient"]) .progress-fill {
371
+ animation: none !important;
372
+ }
373
+
374
+ /* Glassmorphic variant - frosted glass effect */
375
+ :host([variant="glassmorphic"]) .retry-container {
376
+ background: rgba(var(--retry-background-rgb, 26, 26, 46), 0.6);
377
+ backdrop-filter: blur(10px);
378
+ -webkit-backdrop-filter: blur(10px);
379
+ border: 1px solid rgba(255, 255, 255, 0.1);
380
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
381
+ }
382
+
383
+ :host([variant="glassmorphic"]) .progress-bar {
384
+ background: rgba(0, 0, 0, 0.2);
385
+ }
386
+
387
+ :host([variant="glassmorphic"]) .progress-fill {
388
+ background: linear-gradient(
389
+ 90deg,
390
+ rgba(245, 158, 11, 0.8),
391
+ rgba(251, 191, 36, 0.8)
392
+ );
393
+ }
394
+
395
+ /* Animation Effects */
396
+
397
+ /* Striped animation */
398
+ :host([animation="striped"]) .progress-fill {
399
+ background-image:
400
+ linear-gradient(
401
+ 45deg,
402
+ rgba(255, 255, 255, 0.2) 25%,
403
+ transparent 25%,
404
+ transparent 50%,
405
+ rgba(255, 255, 255, 0.2) 50%,
406
+ rgba(255, 255, 255, 0.2) 75%,
407
+ transparent 75%,
408
+ transparent
409
+ ),
410
+ linear-gradient(to right, var(--retry-primary), var(--retry-primary)) !important;
411
+ background-size: 2rem 2rem, 100% 100% !important;
412
+ animation: progress-stripes 3s linear infinite !important;
413
+ }
414
+
415
+ @keyframes progress-stripes {
416
+ 0% { background-position: 0 0, 0 0; }
417
+ 100% { background-position: 2rem 0, 0 0; }
418
+ }
419
+
420
+ /* Pulse animation */
421
+ :host([animation="pulse"]) .progress-fill {
422
+ animation: progress-pulse 4s ease-in-out infinite !important;
423
+ }
424
+
425
+ @keyframes progress-pulse {
426
+ 0%, 100% { opacity: 1; }
427
+ 50% { opacity: 0.3; }
428
+ }
429
+
430
+ /* Glow animation */
431
+ :host([animation="glow"]) .progress-fill {
432
+ animation: progress-glow 4s ease-in-out infinite !important;
433
+ }
434
+
435
+ @keyframes progress-glow {
436
+ 0%, 100% {
437
+ box-shadow: 0 0 5px var(--retry-primary),
438
+ 0 0 10px var(--retry-primary);
439
+ }
440
+ 50% {
441
+ box-shadow: 0 0 20px var(--retry-primary),
442
+ 0 0 35px var(--retry-primary),
443
+ 0 0 50px var(--retry-primary);
444
+ }
445
+ }
446
+
447
+ /* Size variants */
448
+ :host([size="compact"]) .retry-container {
449
+ padding: 8px;
450
+ font-size: 12px;
451
+ }
452
+
453
+ :host([size="compact"]) .progress-bar {
454
+ height: 6px;
455
+ }
456
+
457
+ :host([size="compact"]) .retry-title {
458
+ font-size: 14px;
459
+ }
460
+
461
+ :host([size="compact"]) .retry-message {
462
+ font-size: 12px;
463
+ }
464
+
465
+ :host([size="compact"]) .attempt-number {
466
+ font-size: 40px;
467
+ }
468
+
469
+ :host([size="compact"]) .metric-value {
470
+ font-size: 20px;
471
+ }
472
+
473
+ :host([size="large"]) .retry-container {
474
+ padding: 16px;
475
+ font-size: 16px;
476
+ }
477
+
478
+ :host([size="large"]) .progress-bar {
479
+ height: 10px;
480
+ }
481
+
482
+ :host([size="large"]) .retry-title {
483
+ font-size: 18px;
484
+ }
485
+
486
+ :host([size="large"]) .retry-message {
487
+ font-size: 16px;
488
+ }
489
+
490
+ :host([size="large"]) .attempt-number {
491
+ font-size: 56px;
492
+ }
493
+
494
+ :host([size="large"]) .metric-value {
495
+ font-size: 28px;
496
+ }
497
+
498
+ /* Responsive */
499
+ @media (max-width: 480px) {
500
+ .retry-container {
501
+ padding: 16px;
502
+ }
503
+
504
+ .attempt-number {
505
+ font-size: 36px;
506
+ }
507
+
508
+ .metrics-grid {
509
+ grid-template-columns: repeat(2, 1fr);
510
+ }
511
+
512
+ .actions {
513
+ flex-direction: column;
514
+ }
515
+ }
516
+
517
+ /* Accessibility */
518
+ .retry-button:focus-visible,
519
+ .cancel-button:focus-visible {
520
+ outline: 2px solid var(--retry-primary);
521
+ outline-offset: 2px;
522
+ }
523
+
524
+ @media (prefers-reduced-motion: reduce) {
525
+ .retry-icon,
526
+ .progress-fill::after {
527
+ animation: none;
528
+ }
529
+ }
530
+ `;
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Types for RetryProgress component
3
+ */
4
+
5
+ /**
6
+ * Retry status
7
+ */
8
+ export type RetryStatus = 'idle' | 'attempting' | 'waiting' | 'success' | 'failed' | 'cancelled';
9
+
10
+ /**
11
+ * Retry strategy for backoff calculation
12
+ */
13
+ export type RetryStrategy = 'exponential' | 'linear' | 'fixed' | 'fibonacci';
14
+
15
+ /**
16
+ * Configuration for RetryProgress component
17
+ */
18
+ export interface RetryProgressConfig {
19
+ /** Current attempt number (1-indexed) */
20
+ attempt?: number;
21
+
22
+ /** Maximum number of retry attempts */
23
+ maxAttempts?: number;
24
+
25
+ /** Initial delay in milliseconds */
26
+ initialDelay?: number;
27
+
28
+ /** Maximum delay in milliseconds */
29
+ maxDelay?: number;
30
+
31
+ /** Backoff multiplier for exponential strategy */
32
+ backoffMultiplier?: number;
33
+
34
+ /** Retry strategy */
35
+ strategy?: RetryStrategy;
36
+
37
+ /** Operation message */
38
+ message?: string;
39
+
40
+ /** Show attempt count */
41
+ showAttemptCount?: boolean;
42
+
43
+ /** Show next retry time */
44
+ showNextRetry?: boolean;
45
+
46
+ /** Show progress bar for wait time */
47
+ showProgressBar?: boolean;
48
+
49
+ /** Show elapsed time */
50
+ showElapsedTime?: boolean;
51
+
52
+ /** Enable manual retry button */
53
+ allowManualRetry?: boolean;
54
+
55
+ /** Enable cancel button */
56
+ allowCancel?: boolean;
57
+
58
+ /** Enable animations */
59
+ animate?: boolean;
60
+
61
+ /** Enable automatic cursor state changes based on component state */
62
+ cursorFeedback?: boolean;
63
+
64
+ /** Component size variant */
65
+ size?: 'compact' | 'default' | 'large';
66
+
67
+ /** Visual style variant */
68
+ variant?: 'default' | 'minimal' | 'gradient' | 'glassmorphic';
69
+
70
+ /** Animation style */
71
+ animation?: 'none' | 'striped' | 'pulse' | 'glow';
72
+
73
+ /** Custom CSS class */
74
+ className?: string;
75
+
76
+ /** ARIA label for accessibility */
77
+ ariaLabel?: string;
78
+
79
+ /** Debug mode */
80
+ debug?: boolean;
81
+
82
+ /** Disabled state */
83
+ disabled?: boolean;
84
+ }
85
+
86
+ /**
87
+ * Internal state for RetryProgress
88
+ */
89
+ export interface RetryProgressState {
90
+ status: RetryStatus;
91
+ attempt: number;
92
+ maxAttempts: number;
93
+ currentDelay: number;
94
+ nextRetryTime: number;
95
+ startTime: number;
96
+ elapsedTime: number;
97
+ message: string;
98
+ errorMessage?: string;
99
+ lastError?: Error;
100
+ }
101
+
102
+ /**
103
+ * Data for retry attempt updates
104
+ */
105
+ export interface RetryAttemptUpdate {
106
+ /** New attempt number */
107
+ attempt?: number;
108
+
109
+ /** Operation message */
110
+ message?: string;
111
+
112
+ /** Error from last attempt */
113
+ error?: Error;
114
+
115
+ /** Override calculated delay (ms) */
116
+ delay?: number;
117
+ }
118
+
119
+ /**
120
+ * Event detail for retry attempt start
121
+ */
122
+ export interface RetryAttemptEvent {
123
+ attempt: number;
124
+ maxAttempts: number;
125
+ message: string;
126
+ timestamp: number;
127
+ }
128
+
129
+ /**
130
+ * Event detail for retry waiting period
131
+ */
132
+ export interface RetryWaitingEvent {
133
+ attempt: number;
134
+ delay: number;
135
+ nextRetryTime: number;
136
+ strategy: RetryStrategy;
137
+ timestamp: number;
138
+ }
139
+
140
+ /**
141
+ * Event detail for retry success
142
+ */
143
+ export interface RetrySuccessEvent {
144
+ attempt: number;
145
+ totalAttempts: number;
146
+ elapsedTime: number;
147
+ message: string;
148
+ timestamp: number;
149
+ }
150
+
151
+ /**
152
+ * Event detail for retry failure (max attempts reached)
153
+ */
154
+ export interface RetryFailureEvent {
155
+ totalAttempts: number;
156
+ lastError?: Error;
157
+ elapsedTime: number;
158
+ timestamp: number;
159
+ }
160
+
161
+ /**
162
+ * Event detail for retry cancellation
163
+ */
164
+ export interface RetryCancelEvent {
165
+ attempt: number;
166
+ reason?: string;
167
+ timestamp: number;
168
+ }
169
+
170
+ /**
171
+ * Event detail for manual retry trigger
172
+ */
173
+ export interface ManualRetryEvent {
174
+ attempt: number;
175
+ timestamp: number;
176
+ }