@aspect-ops/exon-ui 0.0.3 → 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 (65) hide show
  1. package/README.md +793 -43
  2. package/dist/components/Accordion/Accordion.svelte +79 -0
  3. package/dist/components/Accordion/Accordion.svelte.d.ts +10 -0
  4. package/dist/components/Accordion/AccordionItem.svelte +198 -0
  5. package/dist/components/Accordion/AccordionItem.svelte.d.ts +10 -0
  6. package/dist/components/Accordion/index.d.ts +2 -0
  7. package/dist/components/Accordion/index.js +2 -0
  8. package/dist/components/Carousel/Carousel.svelte +454 -0
  9. package/dist/components/Carousel/Carousel.svelte.d.ts +14 -0
  10. package/dist/components/Carousel/CarouselSlide.svelte +22 -0
  11. package/dist/components/Carousel/CarouselSlide.svelte.d.ts +7 -0
  12. package/dist/components/Carousel/index.d.ts +2 -0
  13. package/dist/components/Carousel/index.js +2 -0
  14. package/dist/components/Chip/Chip.svelte +461 -0
  15. package/dist/components/Chip/Chip.svelte.d.ts +17 -0
  16. package/dist/components/Chip/ChipGroup.svelte +76 -0
  17. package/dist/components/Chip/ChipGroup.svelte.d.ts +9 -0
  18. package/dist/components/Chip/index.d.ts +2 -0
  19. package/dist/components/Chip/index.js +2 -0
  20. package/dist/components/DatePicker/DatePicker.svelte +746 -0
  21. package/dist/components/DatePicker/DatePicker.svelte.d.ts +19 -0
  22. package/dist/components/DatePicker/index.d.ts +1 -0
  23. package/dist/components/DatePicker/index.js +1 -0
  24. package/dist/components/FileUpload/FileUpload.svelte +484 -0
  25. package/dist/components/FileUpload/FileUpload.svelte.d.ts +16 -0
  26. package/dist/components/FileUpload/index.d.ts +1 -0
  27. package/dist/components/FileUpload/index.js +1 -0
  28. package/dist/components/Image/Image.svelte +223 -0
  29. package/dist/components/Image/Image.svelte.d.ts +19 -0
  30. package/dist/components/Image/index.d.ts +1 -0
  31. package/dist/components/Image/index.js +1 -0
  32. package/dist/components/OTPInput/OTPInput.svelte +312 -0
  33. package/dist/components/OTPInput/OTPInput.svelte.d.ts +57 -0
  34. package/dist/components/OTPInput/index.d.ts +1 -0
  35. package/dist/components/OTPInput/index.js +1 -0
  36. package/dist/components/Rating/Rating.svelte +316 -0
  37. package/dist/components/Rating/Rating.svelte.d.ts +16 -0
  38. package/dist/components/Rating/index.d.ts +1 -0
  39. package/dist/components/Rating/index.js +1 -0
  40. package/dist/components/SearchInput/SearchInput.svelte +480 -0
  41. package/dist/components/SearchInput/SearchInput.svelte.d.ts +22 -0
  42. package/dist/components/SearchInput/index.d.ts +1 -0
  43. package/dist/components/SearchInput/index.js +1 -0
  44. package/dist/components/Slider/Slider.svelte +324 -0
  45. package/dist/components/Slider/Slider.svelte.d.ts +14 -0
  46. package/dist/components/Slider/index.d.ts +1 -0
  47. package/dist/components/Slider/index.js +1 -0
  48. package/dist/components/Stepper/Stepper.svelte +100 -0
  49. package/dist/components/Stepper/Stepper.svelte.d.ts +11 -0
  50. package/dist/components/Stepper/StepperStep.svelte +391 -0
  51. package/dist/components/Stepper/StepperStep.svelte.d.ts +13 -0
  52. package/dist/components/Stepper/index.d.ts +2 -0
  53. package/dist/components/Stepper/index.js +2 -0
  54. package/dist/components/TimePicker/TimePicker.svelte +803 -0
  55. package/dist/components/TimePicker/TimePicker.svelte.d.ts +17 -0
  56. package/dist/components/TimePicker/index.d.ts +1 -0
  57. package/dist/components/TimePicker/index.js +1 -0
  58. package/dist/index.d.ts +10 -1
  59. package/dist/index.js +9 -0
  60. package/dist/types/data-display.d.ts +68 -0
  61. package/dist/types/index.d.ts +3 -2
  62. package/dist/types/input.d.ts +67 -0
  63. package/dist/types/input.js +2 -0
  64. package/dist/types/navigation.d.ts +15 -0
  65. package/package.json +1 -1
@@ -0,0 +1,324 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ value?: number;
4
+ min?: number;
5
+ max?: number;
6
+ step?: number;
7
+ disabled?: boolean;
8
+ showValue?: boolean;
9
+ showTicks?: boolean;
10
+ class?: string;
11
+ onchange?: (value: number) => void;
12
+ }
13
+
14
+ let {
15
+ value = $bindable(0),
16
+ min = 0,
17
+ max = 100,
18
+ step = 1,
19
+ disabled = false,
20
+ showValue = false,
21
+ showTicks = false,
22
+ class: className = '',
23
+ onchange
24
+ }: Props = $props();
25
+
26
+ let sliderRef: HTMLDivElement | null = $state(null);
27
+ let isDragging = $state(false);
28
+ let thumbRef: HTMLDivElement | null = $state(null);
29
+
30
+ // Calculate percentage for positioning
31
+ const percentage = $derived(((value - min) / (max - min)) * 100);
32
+
33
+ // Snap to nearest step
34
+ function snapToStep(val: number): number {
35
+ const snapped = Math.round(val / step) * step;
36
+ return Math.max(min, Math.min(max, snapped));
37
+ }
38
+
39
+ // Update value from position
40
+ function updateValueFromPosition(clientX: number) {
41
+ if (disabled || !sliderRef) return;
42
+
43
+ const rect = sliderRef.getBoundingClientRect();
44
+ const position = (clientX - rect.left) / rect.width;
45
+ const rawValue = position * (max - min) + min;
46
+ const newValue = snapToStep(rawValue);
47
+
48
+ if (newValue !== value) {
49
+ value = newValue;
50
+ onchange?.(newValue);
51
+ }
52
+ }
53
+
54
+ // Mouse/Touch handlers
55
+ function handlePointerDown(e: PointerEvent) {
56
+ if (disabled) return;
57
+ e.preventDefault();
58
+ isDragging = true;
59
+ updateValueFromPosition(e.clientX);
60
+
61
+ // Capture pointer for smooth dragging
62
+ (e.target as HTMLElement).setPointerCapture(e.pointerId);
63
+ }
64
+
65
+ function handlePointerMove(e: PointerEvent) {
66
+ if (!isDragging || disabled) return;
67
+ e.preventDefault();
68
+ updateValueFromPosition(e.clientX);
69
+ }
70
+
71
+ function handlePointerUp(e: PointerEvent) {
72
+ if (isDragging) {
73
+ isDragging = false;
74
+ (e.target as HTMLElement).releasePointerCapture(e.pointerId);
75
+ }
76
+ }
77
+
78
+ // Track click handler
79
+ function handleTrackClick(e: MouseEvent) {
80
+ if (disabled) return;
81
+ // Only update if clicking on track, not thumb
82
+ if (e.target === thumbRef) return;
83
+ updateValueFromPosition(e.clientX);
84
+ }
85
+
86
+ // Keyboard navigation
87
+ function handleKeyDown(e: KeyboardEvent) {
88
+ if (disabled) return;
89
+
90
+ let newValue = value;
91
+ const largeStep = (max - min) * 0.1; // 10% for Page Up/Down
92
+
93
+ switch (e.key) {
94
+ case 'ArrowRight':
95
+ case 'ArrowUp':
96
+ e.preventDefault();
97
+ newValue = Math.min(max, value + step);
98
+ break;
99
+ case 'ArrowLeft':
100
+ case 'ArrowDown':
101
+ e.preventDefault();
102
+ newValue = Math.max(min, value - step);
103
+ break;
104
+ case 'PageUp':
105
+ e.preventDefault();
106
+ newValue = Math.min(max, value + largeStep);
107
+ break;
108
+ case 'PageDown':
109
+ e.preventDefault();
110
+ newValue = Math.max(min, value - largeStep);
111
+ break;
112
+ case 'Home':
113
+ e.preventDefault();
114
+ newValue = min;
115
+ break;
116
+ case 'End':
117
+ e.preventDefault();
118
+ newValue = max;
119
+ break;
120
+ default:
121
+ return;
122
+ }
123
+
124
+ newValue = snapToStep(newValue);
125
+ if (newValue !== value) {
126
+ value = newValue;
127
+ onchange?.(newValue);
128
+ }
129
+ }
130
+
131
+ // Generate tick marks
132
+ function generateTicks(): number[] {
133
+ const ticks: number[] = [];
134
+ for (let i = min; i <= max; i += step) {
135
+ ticks.push(i);
136
+ }
137
+ return ticks;
138
+ }
139
+
140
+ const ticks = $derived(showTicks ? generateTicks() : []);
141
+ </script>
142
+
143
+ <div class="slider-container {className}">
144
+ <div
145
+ bind:this={sliderRef}
146
+ class="slider-track"
147
+ class:slider-track--disabled={disabled}
148
+ onclick={handleTrackClick}
149
+ role="presentation"
150
+ >
151
+ <!-- Filled portion of track -->
152
+ <div class="slider-track-fill" style="width: {percentage}%"></div>
153
+
154
+ <!-- Tick marks -->
155
+ {#if showTicks}
156
+ <div class="slider-ticks">
157
+ {#each ticks as tick}
158
+ <div class="slider-tick" style="left: {((tick - min) / (max - min)) * 100}%"></div>
159
+ {/each}
160
+ </div>
161
+ {/if}
162
+
163
+ <!-- Draggable thumb -->
164
+ <div
165
+ bind:this={thumbRef}
166
+ class="slider-thumb"
167
+ class:slider-thumb--dragging={isDragging}
168
+ class:slider-thumb--disabled={disabled}
169
+ style="left: {percentage}%"
170
+ role="slider"
171
+ aria-valuemin={min}
172
+ aria-valuemax={max}
173
+ aria-valuenow={value}
174
+ aria-orientation="horizontal"
175
+ aria-disabled={disabled}
176
+ tabindex={disabled ? -1 : 0}
177
+ onpointerdown={handlePointerDown}
178
+ onpointermove={handlePointerMove}
179
+ onpointerup={handlePointerUp}
180
+ onkeydown={handleKeyDown}
181
+ >
182
+ {#if showValue}
183
+ <div class="slider-value-tooltip">{value}</div>
184
+ {/if}
185
+ </div>
186
+ </div>
187
+ </div>
188
+
189
+ <style>
190
+ .slider-container {
191
+ position: relative;
192
+ width: 100%;
193
+ padding: var(--space-md, 1rem) 0;
194
+ }
195
+
196
+ .slider-track {
197
+ position: relative;
198
+ width: 100%;
199
+ height: 6px;
200
+ background: var(--color-bg-subtle, #f0f0f0);
201
+ border-radius: var(--radius-full, 9999px);
202
+ cursor: pointer;
203
+ touch-action: none;
204
+ -webkit-tap-highlight-color: transparent;
205
+ }
206
+
207
+ .slider-track--disabled {
208
+ cursor: not-allowed;
209
+ opacity: 0.5;
210
+ }
211
+
212
+ .slider-track-fill {
213
+ position: absolute;
214
+ top: 0;
215
+ left: 0;
216
+ height: 100%;
217
+ background: var(--color-primary, #0090ff);
218
+ border-radius: var(--radius-full, 9999px);
219
+ transition: width var(--transition-fast, 150ms ease);
220
+ pointer-events: none;
221
+ }
222
+
223
+ .slider-ticks {
224
+ position: absolute;
225
+ top: 0;
226
+ left: 0;
227
+ width: 100%;
228
+ height: 100%;
229
+ pointer-events: none;
230
+ }
231
+
232
+ .slider-tick {
233
+ position: absolute;
234
+ top: 50%;
235
+ width: 2px;
236
+ height: 8px;
237
+ background: var(--color-border, #d9d9d9);
238
+ transform: translate(-50%, -50%);
239
+ border-radius: var(--radius-sm, 0.25rem);
240
+ }
241
+
242
+ .slider-thumb {
243
+ position: absolute;
244
+ top: 50%;
245
+ width: 20px;
246
+ height: 20px;
247
+ background: var(--color-bg-elevated, #ffffff);
248
+ border: 2px solid var(--color-primary, #0090ff);
249
+ border-radius: 50%;
250
+ box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));
251
+ transform: translate(-50%, -50%);
252
+ cursor: grab;
253
+ transition:
254
+ left var(--transition-fast, 150ms ease),
255
+ box-shadow var(--transition-fast, 150ms ease),
256
+ transform var(--transition-fast, 150ms ease);
257
+ touch-action: none;
258
+ -webkit-tap-highlight-color: transparent;
259
+
260
+ /* Ensure 44px touch target */
261
+ min-width: var(--touch-target-min, 44px);
262
+ min-height: var(--touch-target-min, 44px);
263
+ }
264
+
265
+ .slider-thumb::before {
266
+ content: '';
267
+ position: absolute;
268
+ top: 50%;
269
+ left: 50%;
270
+ width: var(--touch-target-min, 44px);
271
+ height: var(--touch-target-min, 44px);
272
+ transform: translate(-50%, -50%);
273
+ border-radius: 50%;
274
+ }
275
+
276
+ .slider-thumb:hover:not(.slider-thumb--disabled) {
277
+ box-shadow: var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1));
278
+ transform: translate(-50%, -50%) scale(1.1);
279
+ }
280
+
281
+ .slider-thumb:focus-visible {
282
+ outline: none;
283
+ box-shadow:
284
+ var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1)),
285
+ 0 0 0 3px var(--color-primary-bg, rgba(0, 144, 255, 0.2));
286
+ }
287
+
288
+ .slider-thumb--dragging {
289
+ cursor: grabbing;
290
+ box-shadow: var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1));
291
+ transform: translate(-50%, -50%) scale(1.15);
292
+ }
293
+
294
+ .slider-thumb--disabled {
295
+ cursor: not-allowed;
296
+ opacity: 0.5;
297
+ }
298
+
299
+ .slider-value-tooltip {
300
+ position: absolute;
301
+ bottom: calc(100% + 8px);
302
+ left: 50%;
303
+ transform: translateX(-50%);
304
+ padding: var(--space-xs, 0.25rem) var(--space-sm, 0.5rem);
305
+ background: var(--color-text, #202020);
306
+ color: var(--color-text-inverse, #ffffff);
307
+ font-size: var(--text-xs, 0.75rem);
308
+ font-weight: var(--font-medium, 500);
309
+ border-radius: var(--radius-md, 0.375rem);
310
+ white-space: nowrap;
311
+ pointer-events: none;
312
+ box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));
313
+ }
314
+
315
+ .slider-value-tooltip::after {
316
+ content: '';
317
+ position: absolute;
318
+ top: 100%;
319
+ left: 50%;
320
+ transform: translateX(-50%);
321
+ border: 4px solid transparent;
322
+ border-top-color: var(--color-text, #202020);
323
+ }
324
+ </style>
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ value?: number;
3
+ min?: number;
4
+ max?: number;
5
+ step?: number;
6
+ disabled?: boolean;
7
+ showValue?: boolean;
8
+ showTicks?: boolean;
9
+ class?: string;
10
+ onchange?: (value: number) => void;
11
+ }
12
+ declare const Slider: import("svelte").Component<Props, {}, "value">;
13
+ type Slider = ReturnType<typeof Slider>;
14
+ export default Slider;
@@ -0,0 +1 @@
1
+ export { default as Slider } from './Slider.svelte';
@@ -0,0 +1 @@
1
+ export { default as Slider } from './Slider.svelte';
@@ -0,0 +1,100 @@
1
+ <script lang="ts">
2
+ import { setContext } from 'svelte';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ activeStep?: number;
7
+ orientation?: 'horizontal' | 'vertical';
8
+ linear?: boolean;
9
+ class?: string;
10
+ children?: Snippet;
11
+ }
12
+
13
+ let {
14
+ activeStep = $bindable(0),
15
+ orientation = 'horizontal',
16
+ linear = true,
17
+ class: className = '',
18
+ children
19
+ }: Props = $props();
20
+
21
+ // Track completed steps
22
+ let completedSteps = $state<Set<number>>(new Set());
23
+
24
+ // Track total steps
25
+ let totalSteps = $state(0);
26
+
27
+ // Context for child steps
28
+ const stepperContext = {
29
+ get activeStep() {
30
+ return activeStep;
31
+ },
32
+ get orientation() {
33
+ return orientation;
34
+ },
35
+ get linear() {
36
+ return linear;
37
+ },
38
+ get totalSteps() {
39
+ return totalSteps;
40
+ },
41
+ get completedSteps() {
42
+ return completedSteps;
43
+ },
44
+ registerStep: () => {
45
+ const stepIndex = totalSteps;
46
+ totalSteps++;
47
+ return stepIndex;
48
+ },
49
+ setActiveStep: (index: number) => {
50
+ if (!linear || completedSteps.has(index) || index <= activeStep) {
51
+ // Mark previous steps as completed
52
+ for (let i = 0; i < index; i++) {
53
+ completedSteps.add(i);
54
+ }
55
+ activeStep = index;
56
+ }
57
+ },
58
+ completeStep: (index: number) => {
59
+ completedSteps.add(index);
60
+ }
61
+ };
62
+
63
+ setContext('stepper', stepperContext);
64
+ </script>
65
+
66
+ <nav class="stepper stepper--{orientation} {className}" aria-label="Progress">
67
+ <ol class="stepper__list" role="list">
68
+ {#if children}
69
+ {@render children()}
70
+ {/if}
71
+ </ol>
72
+ </nav>
73
+
74
+ <style>
75
+ .stepper {
76
+ font-family: inherit;
77
+ width: 100%;
78
+ }
79
+
80
+ .stepper__list {
81
+ list-style: none;
82
+ margin: 0;
83
+ padding: 0;
84
+ display: flex;
85
+ }
86
+
87
+ /* Horizontal Layout */
88
+ .stepper--horizontal .stepper__list {
89
+ flex-direction: row;
90
+ align-items: flex-start;
91
+ gap: var(--space-sm, 0.5rem);
92
+ }
93
+
94
+ /* Vertical Layout */
95
+ .stepper--vertical .stepper__list {
96
+ flex-direction: column;
97
+ align-items: stretch;
98
+ gap: var(--space-xs, 0.25rem);
99
+ }
100
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ activeStep?: number;
4
+ orientation?: 'horizontal' | 'vertical';
5
+ linear?: boolean;
6
+ class?: string;
7
+ children?: Snippet;
8
+ }
9
+ declare const Stepper: import("svelte").Component<Props, {}, "activeStep">;
10
+ type Stepper = ReturnType<typeof Stepper>;
11
+ export default Stepper;