@aspect-ops/exon-ui 0.0.1 → 0.0.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 (178) hide show
  1. package/README.md +438 -0
  2. package/dist/components/ActionSheet/ActionSheet.svelte +270 -0
  3. package/dist/components/ActionSheet/ActionSheet.svelte.d.ts +12 -0
  4. package/dist/components/ActionSheet/ActionSheetItem.svelte +151 -0
  5. package/dist/components/ActionSheet/ActionSheetItem.svelte.d.ts +10 -0
  6. package/dist/components/ActionSheet/index.d.ts +3 -0
  7. package/dist/components/ActionSheet/index.js +2 -0
  8. package/dist/components/Alert/Alert.svelte +165 -0
  9. package/dist/components/Alert/Alert.svelte.d.ts +11 -0
  10. package/dist/components/Alert/index.d.ts +1 -0
  11. package/dist/components/Alert/index.js +1 -0
  12. package/dist/components/AspectRatio/AspectRatio.svelte +42 -0
  13. package/dist/components/AspectRatio/AspectRatio.svelte.d.ts +9 -0
  14. package/dist/components/AspectRatio/index.d.ts +1 -0
  15. package/dist/components/AspectRatio/index.js +1 -0
  16. package/dist/components/Avatar/Avatar.svelte +147 -0
  17. package/dist/components/Avatar/Avatar.svelte.d.ts +12 -0
  18. package/dist/components/Avatar/AvatarGroup.svelte +153 -0
  19. package/dist/components/Avatar/AvatarGroup.svelte.d.ts +12 -0
  20. package/dist/components/Avatar/index.d.ts +2 -0
  21. package/dist/components/Avatar/index.js +2 -0
  22. package/dist/components/BottomSheet/BottomSheet.svelte +230 -0
  23. package/dist/components/BottomSheet/BottomSheet.svelte.d.ts +7 -0
  24. package/dist/components/BottomSheet/BottomSheetBody.svelte +20 -0
  25. package/dist/components/BottomSheet/BottomSheetBody.svelte.d.ts +7 -0
  26. package/dist/components/BottomSheet/BottomSheetHeader.svelte +27 -0
  27. package/dist/components/BottomSheet/BottomSheetHeader.svelte.d.ts +7 -0
  28. package/dist/components/BottomSheet/index.d.ts +3 -0
  29. package/dist/components/BottomSheet/index.js +3 -0
  30. package/dist/components/Box/Box.svelte +41 -0
  31. package/dist/components/Box/Box.svelte.d.ts +7 -0
  32. package/dist/components/Box/index.d.ts +1 -0
  33. package/dist/components/Box/index.js +1 -0
  34. package/dist/components/Card/Card.svelte +95 -0
  35. package/dist/components/Card/Card.svelte.d.ts +10 -0
  36. package/dist/components/Card/CardBody.svelte +32 -0
  37. package/dist/components/Card/CardBody.svelte.d.ts +7 -0
  38. package/dist/components/Card/CardFooter.svelte +34 -0
  39. package/dist/components/Card/CardFooter.svelte.d.ts +7 -0
  40. package/dist/components/Card/CardHeader.svelte +67 -0
  41. package/dist/components/Card/CardHeader.svelte.d.ts +9 -0
  42. package/dist/components/Card/index.d.ts +4 -0
  43. package/dist/components/Card/index.js +4 -0
  44. package/dist/components/Center/Center.svelte +28 -0
  45. package/dist/components/Center/Center.svelte.d.ts +8 -0
  46. package/dist/components/Center/index.d.ts +1 -0
  47. package/dist/components/Center/index.js +1 -0
  48. package/dist/components/Container/Container.svelte +58 -0
  49. package/dist/components/Container/Container.svelte.d.ts +10 -0
  50. package/dist/components/Container/index.d.ts +1 -0
  51. package/dist/components/Container/index.js +1 -0
  52. package/dist/components/Divider/Divider.svelte +38 -0
  53. package/dist/components/Divider/Divider.svelte.d.ts +9 -0
  54. package/dist/components/Divider/index.d.ts +1 -0
  55. package/dist/components/Divider/index.js +1 -0
  56. package/dist/components/EmptyState/EmptyState.svelte +164 -0
  57. package/dist/components/EmptyState/EmptyState.svelte.d.ts +12 -0
  58. package/dist/components/EmptyState/index.d.ts +1 -0
  59. package/dist/components/EmptyState/index.js +1 -0
  60. package/dist/components/FAB/FAB.svelte +242 -0
  61. package/dist/components/FAB/FAB.svelte.d.ts +9 -0
  62. package/dist/components/FAB/FABGroup.svelte +449 -0
  63. package/dist/components/FAB/FABGroup.svelte.d.ts +9 -0
  64. package/dist/components/FAB/index.d.ts +3 -0
  65. package/dist/components/FAB/index.js +2 -0
  66. package/dist/components/Grid/Grid.svelte +136 -0
  67. package/dist/components/Grid/Grid.svelte.d.ts +12 -0
  68. package/dist/components/Grid/GridItem.svelte +21 -0
  69. package/dist/components/Grid/GridItem.svelte.d.ts +7 -0
  70. package/dist/components/Grid/index.d.ts +2 -0
  71. package/dist/components/Grid/index.js +2 -0
  72. package/dist/components/List/List.svelte +42 -0
  73. package/dist/components/List/List.svelte.d.ts +18 -0
  74. package/dist/components/List/ListItem.svelte +139 -0
  75. package/dist/components/List/ListItem.svelte.d.ts +36 -0
  76. package/dist/components/List/index.d.ts +2 -0
  77. package/dist/components/List/index.js +2 -0
  78. package/dist/components/Modal/Modal.svelte +204 -0
  79. package/dist/components/Modal/Modal.svelte.d.ts +7 -0
  80. package/dist/components/Modal/ModalBody.svelte +50 -0
  81. package/dist/components/Modal/ModalBody.svelte.d.ts +7 -0
  82. package/dist/components/Modal/ModalFooter.svelte +37 -0
  83. package/dist/components/Modal/ModalFooter.svelte.d.ts +7 -0
  84. package/dist/components/Modal/ModalHeader.svelte +73 -0
  85. package/dist/components/Modal/ModalHeader.svelte.d.ts +7 -0
  86. package/dist/components/Modal/index.d.ts +4 -0
  87. package/dist/components/Modal/index.js +4 -0
  88. package/dist/components/Popover/Popover.svelte +14 -0
  89. package/dist/components/Popover/Popover.svelte.d.ts +7 -0
  90. package/dist/components/Popover/PopoverContent.svelte +63 -0
  91. package/dist/components/Popover/PopoverContent.svelte.d.ts +7 -0
  92. package/dist/components/Popover/PopoverTrigger.svelte +14 -0
  93. package/dist/components/Popover/PopoverTrigger.svelte.d.ts +7 -0
  94. package/dist/components/Popover/index.d.ts +3 -0
  95. package/dist/components/Popover/index.js +3 -0
  96. package/dist/components/Progress/ProgressBar.svelte +86 -0
  97. package/dist/components/Progress/ProgressBar.svelte.d.ts +11 -0
  98. package/dist/components/Progress/ProgressCircle.svelte +134 -0
  99. package/dist/components/Progress/ProgressCircle.svelte.d.ts +12 -0
  100. package/dist/components/Progress/Spinner.svelte +68 -0
  101. package/dist/components/Progress/Spinner.svelte.d.ts +8 -0
  102. package/dist/components/Progress/index.d.ts +3 -0
  103. package/dist/components/Progress/index.js +3 -0
  104. package/dist/components/PullToRefresh/PullToRefresh.svelte +304 -0
  105. package/dist/components/PullToRefresh/PullToRefresh.svelte.d.ts +20 -0
  106. package/dist/components/PullToRefresh/index.d.ts +1 -0
  107. package/dist/components/PullToRefresh/index.js +1 -0
  108. package/dist/components/SafeArea/SafeArea.svelte +33 -0
  109. package/dist/components/SafeArea/SafeArea.svelte.d.ts +7 -0
  110. package/dist/components/Select/Select.svelte +55 -12
  111. package/dist/components/Skeleton/Skeleton.svelte +59 -0
  112. package/dist/components/Skeleton/Skeleton.svelte.d.ts +10 -0
  113. package/dist/components/Skeleton/index.d.ts +1 -0
  114. package/dist/components/Skeleton/index.js +1 -0
  115. package/dist/components/Spacer/Spacer.svelte +56 -0
  116. package/dist/components/Spacer/Spacer.svelte.d.ts +6 -0
  117. package/dist/components/Spacer/index.d.ts +1 -0
  118. package/dist/components/Spacer/index.js +1 -0
  119. package/dist/components/Stack/Stack.svelte +117 -0
  120. package/dist/components/Stack/Stack.svelte.d.ts +13 -0
  121. package/dist/components/Stack/index.d.ts +1 -0
  122. package/dist/components/Stack/index.js +1 -0
  123. package/dist/components/SwipeActions/SwipeAction.svelte +43 -0
  124. package/dist/components/SwipeActions/SwipeAction.svelte.d.ts +8 -0
  125. package/dist/components/SwipeActions/SwipeActions.svelte +193 -0
  126. package/dist/components/SwipeActions/SwipeActions.svelte.d.ts +9 -0
  127. package/dist/components/SwipeActions/index.d.ts +2 -0
  128. package/dist/components/SwipeActions/index.js +2 -0
  129. package/dist/components/Switch/Switch.svelte +29 -9
  130. package/dist/components/Table/Table.svelte +175 -0
  131. package/dist/components/Table/Table.svelte.d.ts +38 -0
  132. package/dist/components/Table/TableBody.svelte +26 -0
  133. package/dist/components/Table/TableBody.svelte.d.ts +13 -0
  134. package/dist/components/Table/TableCell.svelte +85 -0
  135. package/dist/components/Table/TableCell.svelte.d.ts +28 -0
  136. package/dist/components/Table/TableHead.svelte +36 -0
  137. package/dist/components/Table/TableHead.svelte.d.ts +13 -0
  138. package/dist/components/Table/TableHeader.svelte +217 -0
  139. package/dist/components/Table/TableHeader.svelte.d.ts +32 -0
  140. package/dist/components/Table/TableRow.svelte +92 -0
  141. package/dist/components/Table/TableRow.svelte.d.ts +28 -0
  142. package/dist/components/Table/index.d.ts +6 -0
  143. package/dist/components/Table/index.js +6 -0
  144. package/dist/components/Tag/Tag.svelte +189 -0
  145. package/dist/components/Tag/Tag.svelte.d.ts +13 -0
  146. package/dist/components/Tag/index.d.ts +1 -0
  147. package/dist/components/Tag/index.js +1 -0
  148. package/dist/components/Toast/Toast.svelte +241 -0
  149. package/dist/components/Toast/Toast.svelte.d.ts +18 -0
  150. package/dist/components/Toast/ToastContainer.svelte +110 -0
  151. package/dist/components/Toast/ToastContainer.svelte.d.ts +8 -0
  152. package/dist/components/Toast/index.d.ts +3 -0
  153. package/dist/components/Toast/index.js +3 -0
  154. package/dist/components/Toast/toast.d.ts +13 -0
  155. package/dist/components/Toast/toast.js +55 -0
  156. package/dist/components/Tooltip/Tooltip.svelte +71 -0
  157. package/dist/components/Tooltip/Tooltip.svelte.d.ts +7 -0
  158. package/dist/components/Tooltip/index.d.ts +2 -0
  159. package/dist/components/Tooltip/index.js +1 -0
  160. package/dist/index.d.ts +29 -1
  161. package/dist/index.js +32 -0
  162. package/dist/styles/tokens.css +5 -0
  163. package/dist/types/data-display.d.ts +93 -0
  164. package/dist/types/data-display.js +1 -0
  165. package/dist/types/feedback.d.ts +92 -0
  166. package/dist/types/feedback.js +1 -0
  167. package/dist/types/index.d.ts +4 -0
  168. package/dist/types/layout.d.ts +57 -0
  169. package/dist/types/layout.js +1 -0
  170. package/dist/types/mobile.d.ts +91 -0
  171. package/dist/types/mobile.js +1 -0
  172. package/dist/utils/gestures.d.ts +219 -0
  173. package/dist/utils/gestures.js +492 -0
  174. package/dist/utils/haptics.d.ts +89 -0
  175. package/dist/utils/haptics.js +198 -0
  176. package/dist/utils/platform.d.ts +47 -0
  177. package/dist/utils/platform.js +156 -0
  178. package/package.json +1 -1
@@ -0,0 +1,304 @@
1
+ <script lang="ts">
2
+ import type { PullToRefreshProps } from '../../types/index.js';
3
+ import { hapticImpact } from '../../utils/haptics.js';
4
+
5
+ interface Props extends PullToRefreshProps {
6
+ /** Controlled loading state (bindable) */
7
+ refreshing?: boolean;
8
+ /** Pull distance in pixels to trigger refresh (default: 80) */
9
+ threshold?: number;
10
+ /** Maximum pull distance in pixels (default: 150) */
11
+ maxPull?: number;
12
+ /** Disable pull-to-refresh functionality */
13
+ disabled?: boolean;
14
+ /** Additional CSS class */
15
+ class?: string;
16
+ /** Called when threshold reached and released */
17
+ onrefresh?: () => void;
18
+ /** Content to render inside */
19
+ children?: import('svelte').Snippet;
20
+ }
21
+
22
+ let {
23
+ refreshing = $bindable(false),
24
+ threshold = 80,
25
+ maxPull = 150,
26
+ disabled = false,
27
+ class: className = '',
28
+ onrefresh,
29
+ children
30
+ }: Props = $props();
31
+
32
+ // Touch tracking state
33
+ let pullDistance = $state(0);
34
+ let isPulling = $state(false);
35
+ let startY = $state(0);
36
+ let currentY = $state(0);
37
+ let containerEl: HTMLDivElement | undefined = $state();
38
+ let contentEl: HTMLDivElement | undefined = $state();
39
+
40
+ // Calculated values
41
+ const progress = $derived(Math.min(pullDistance / threshold, 1));
42
+ const indicatorRotation = $derived(progress * 360);
43
+ const indicatorY = $derived(Math.min(pullDistance, maxPull) - 40);
44
+ const indicatorOpacity = $derived(Math.min(progress, 1));
45
+ const isThresholdReached = $derived(pullDistance >= threshold);
46
+
47
+ /**
48
+ * Check if content is scrolled to the top
49
+ */
50
+ function isAtScrollTop(): boolean {
51
+ if (!contentEl) return true;
52
+ return contentEl.scrollTop <= 0;
53
+ }
54
+
55
+ /**
56
+ * Apply resistance to pull distance for natural feel
57
+ */
58
+ function applyResistance(distance: number): number {
59
+ if (distance <= 0) return 0;
60
+ // Diminishing returns after threshold
61
+ const resistance = distance > threshold ? 0.4 : 0.6;
62
+ return Math.min(distance * resistance, maxPull);
63
+ }
64
+
65
+ /**
66
+ * Handle touch start
67
+ */
68
+ function handleTouchStart(e: TouchEvent) {
69
+ if (disabled || refreshing) return;
70
+ if (!isAtScrollTop()) return;
71
+ if (e.touches.length !== 1) return;
72
+
73
+ startY = e.touches[0].clientY;
74
+ currentY = startY;
75
+ isPulling = false;
76
+ }
77
+
78
+ /**
79
+ * Handle touch move
80
+ */
81
+ function handleTouchMove(e: TouchEvent) {
82
+ if (disabled || refreshing) return;
83
+ if (e.touches.length !== 1) return;
84
+
85
+ const touchY = e.touches[0].clientY;
86
+ const rawDistance = touchY - startY;
87
+
88
+ // Only start pulling if we're at scroll top and pulling down
89
+ if (!isPulling) {
90
+ if (rawDistance > 0 && isAtScrollTop()) {
91
+ isPulling = true;
92
+ startY = touchY; // Reset start position when pull begins
93
+ } else {
94
+ return;
95
+ }
96
+ }
97
+
98
+ // Calculate pull distance with resistance
99
+ currentY = touchY;
100
+ const actualDistance = currentY - startY;
101
+
102
+ if (actualDistance > 0) {
103
+ pullDistance = applyResistance(actualDistance);
104
+ // Prevent scroll while pulling
105
+ e.preventDefault();
106
+ } else {
107
+ // Reset if user pushes back up
108
+ pullDistance = 0;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Handle touch end
114
+ */
115
+ async function handleTouchEnd() {
116
+ if (disabled) return;
117
+
118
+ if (isPulling && isThresholdReached && !refreshing) {
119
+ // Trigger haptic feedback
120
+ await hapticImpact('medium');
121
+
122
+ // Trigger refresh
123
+ refreshing = true;
124
+ onrefresh?.();
125
+ }
126
+
127
+ // Animate back
128
+ isPulling = false;
129
+
130
+ if (!refreshing) {
131
+ pullDistance = 0;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Handle touch cancel
137
+ */
138
+ function handleTouchCancel() {
139
+ isPulling = false;
140
+ if (!refreshing) {
141
+ pullDistance = 0;
142
+ }
143
+ }
144
+
145
+ // Watch for refreshing state changes to reset pull distance
146
+ $effect(() => {
147
+ if (!refreshing && pullDistance > 0) {
148
+ pullDistance = 0;
149
+ }
150
+ });
151
+ </script>
152
+
153
+ <div
154
+ bind:this={containerEl}
155
+ class="ptr-container {className}"
156
+ class:ptr-container--pulling={isPulling}
157
+ class:ptr-container--refreshing={refreshing}
158
+ class:ptr-container--disabled={disabled}
159
+ ontouchstart={handleTouchStart}
160
+ ontouchmove={handleTouchMove}
161
+ ontouchend={handleTouchEnd}
162
+ ontouchcancel={handleTouchCancel}
163
+ >
164
+ <!-- Pull indicator -->
165
+ <div
166
+ class="ptr-indicator"
167
+ class:ptr-indicator--visible={pullDistance > 0 || refreshing}
168
+ class:ptr-indicator--threshold-reached={isThresholdReached}
169
+ class:ptr-indicator--refreshing={refreshing}
170
+ style="transform: translateY({refreshing ? 20 : indicatorY}px); opacity: {refreshing
171
+ ? 1
172
+ : indicatorOpacity};"
173
+ aria-hidden="true"
174
+ >
175
+ <div
176
+ class="ptr-spinner"
177
+ class:ptr-spinner--spinning={refreshing}
178
+ style="transform: rotate({refreshing ? 0 : indicatorRotation}deg);"
179
+ >
180
+ <svg viewBox="0 0 24 24" class="ptr-spinner__icon">
181
+ <path
182
+ d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46A7.93 7.93 0 0020 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74A7.93 7.93 0 004 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"
183
+ fill="currentColor"
184
+ />
185
+ </svg>
186
+ </div>
187
+ </div>
188
+
189
+ <!-- Content wrapper -->
190
+ <div
191
+ bind:this={contentEl}
192
+ class="ptr-content"
193
+ style="transform: translateY({refreshing ? threshold * 0.5 : pullDistance}px);"
194
+ >
195
+ {#if children}
196
+ {@render children()}
197
+ {/if}
198
+ </div>
199
+ </div>
200
+
201
+ <style>
202
+ .ptr-container {
203
+ position: relative;
204
+ width: 100%;
205
+ height: 100%;
206
+ overflow: hidden;
207
+ touch-action: pan-y;
208
+ -webkit-overflow-scrolling: touch;
209
+ }
210
+
211
+ .ptr-container--disabled {
212
+ pointer-events: none;
213
+ }
214
+
215
+ .ptr-indicator {
216
+ position: absolute;
217
+ top: 0;
218
+ left: 50%;
219
+ transform: translateX(-50%);
220
+ display: flex;
221
+ align-items: center;
222
+ justify-content: center;
223
+ width: 40px;
224
+ height: 40px;
225
+ border-radius: 50%;
226
+ background: var(--color-bg, #ffffff);
227
+ box-shadow: var(
228
+ --shadow-md,
229
+ 0 4px 6px -1px rgba(0, 0, 0, 0.1),
230
+ 0 2px 4px -1px rgba(0, 0, 0, 0.06)
231
+ );
232
+ opacity: 0;
233
+ pointer-events: none;
234
+ z-index: 10;
235
+ margin-left: -20px;
236
+ transition: opacity 0.2s ease;
237
+ }
238
+
239
+ .ptr-indicator--visible {
240
+ opacity: 1;
241
+ }
242
+
243
+ .ptr-indicator--threshold-reached {
244
+ background: var(--color-primary-light, #dbeafe);
245
+ }
246
+
247
+ .ptr-indicator--refreshing {
248
+ background: var(--color-bg, #ffffff);
249
+ }
250
+
251
+ .ptr-spinner {
252
+ display: flex;
253
+ align-items: center;
254
+ justify-content: center;
255
+ width: 24px;
256
+ height: 24px;
257
+ color: var(--color-primary, #3b82f6);
258
+ transition: transform 0.1s linear;
259
+ }
260
+
261
+ .ptr-spinner--spinning {
262
+ animation: ptr-spin 1s linear infinite;
263
+ }
264
+
265
+ .ptr-spinner__icon {
266
+ width: 100%;
267
+ height: 100%;
268
+ }
269
+
270
+ .ptr-content {
271
+ position: relative;
272
+ width: 100%;
273
+ height: 100%;
274
+ overflow-y: auto;
275
+ overflow-x: hidden;
276
+ -webkit-overflow-scrolling: touch;
277
+ will-change: transform;
278
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
279
+ }
280
+
281
+ .ptr-container--pulling .ptr-content {
282
+ transition: none;
283
+ }
284
+
285
+ .ptr-container--refreshing .ptr-content {
286
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
287
+ }
288
+
289
+ /* Spinning animation */
290
+ @keyframes ptr-spin {
291
+ 0% {
292
+ transform: rotate(0deg);
293
+ }
294
+ 100% {
295
+ transform: rotate(360deg);
296
+ }
297
+ }
298
+
299
+ /* Ensure minimum touch target size (F20 standard) */
300
+ .ptr-indicator {
301
+ min-width: 44px;
302
+ min-height: 44px;
303
+ }
304
+ </style>
@@ -0,0 +1,20 @@
1
+ import type { PullToRefreshProps } from '../../types/index.js';
2
+ interface Props extends PullToRefreshProps {
3
+ /** Controlled loading state (bindable) */
4
+ refreshing?: boolean;
5
+ /** Pull distance in pixels to trigger refresh (default: 80) */
6
+ threshold?: number;
7
+ /** Maximum pull distance in pixels (default: 150) */
8
+ maxPull?: number;
9
+ /** Disable pull-to-refresh functionality */
10
+ disabled?: boolean;
11
+ /** Additional CSS class */
12
+ class?: string;
13
+ /** Called when threshold reached and released */
14
+ onrefresh?: () => void;
15
+ /** Content to render inside */
16
+ children?: import('svelte').Snippet;
17
+ }
18
+ declare const PullToRefresh: import("svelte").Component<Props, {}, "refreshing">;
19
+ type PullToRefresh = ReturnType<typeof PullToRefresh>;
20
+ export default PullToRefresh;
@@ -0,0 +1 @@
1
+ export { default as PullToRefresh } from './PullToRefresh.svelte';
@@ -0,0 +1 @@
1
+ export { default as PullToRefresh } from './PullToRefresh.svelte';
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ import type { SafeAreaEdge, SafeAreaProps } from '../../types/index.js';
3
+
4
+ interface Props extends SafeAreaProps {
5
+ children?: import('svelte').Snippet;
6
+ }
7
+
8
+ let {
9
+ edges = ['top', 'right', 'bottom', 'left'],
10
+ class: className = '',
11
+ children
12
+ }: Props = $props();
13
+
14
+ // Derive style string based on which edges are selected
15
+ const style = $derived.by(() => {
16
+ const styles: string[] = [];
17
+ if (edges?.includes('top')) styles.push('padding-top: env(safe-area-inset-top)');
18
+ if (edges?.includes('right')) styles.push('padding-right: env(safe-area-inset-right)');
19
+ if (edges?.includes('bottom')) styles.push('padding-bottom: env(safe-area-inset-bottom)');
20
+ if (edges?.includes('left')) styles.push('padding-left: env(safe-area-inset-left)');
21
+ return styles.join('; ');
22
+ });
23
+ </script>
24
+
25
+ <div class="safe-area {className}" {style}>
26
+ {@render children?.()}
27
+ </div>
28
+
29
+ <style>
30
+ .safe-area {
31
+ box-sizing: border-box;
32
+ }
33
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { SafeAreaProps } from '../../types/index.js';
2
+ interface Props extends SafeAreaProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const SafeArea: import("svelte").Component<Props, {}, "">;
6
+ type SafeArea = ReturnType<typeof SafeArea>;
7
+ export default SafeArea;
@@ -79,7 +79,7 @@
79
79
  </SelectPrimitive.Trigger>
80
80
 
81
81
  <SelectPrimitive.Portal>
82
- <SelectPrimitive.Content class="select__content" sideOffset={4}>
82
+ <SelectPrimitive.Content class="select__content" sideOffset={4} align="start">
83
83
  <SelectPrimitive.Viewport class="select__viewport">
84
84
  {#each options as option (option.value)}
85
85
  <SelectPrimitive.Item
@@ -195,46 +195,89 @@
195
195
 
196
196
  :global(.select__content) {
197
197
  z-index: 50;
198
- min-width: 8rem;
199
198
  overflow: hidden;
200
199
  border: 1px solid var(--color-border, #e5e7eb);
201
200
  border-radius: var(--radius-md, 0.375rem);
202
201
  background: var(--color-bg, #ffffff);
203
- box-shadow: var(--shadow-md, 0 4px 6px rgba(0, 0, 0, 0.1));
202
+ box-shadow: var(--shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));
204
203
  font-family: var(--font-family, system-ui, -apple-system, sans-serif);
204
+ /* Match trigger width - bits-ui provides this CSS variable */
205
+ min-width: var(--bits-floating-anchor-width, 200px);
206
+ width: var(--bits-floating-anchor-width, auto);
207
+ }
208
+
209
+ :global(.select__content[data-state='open']) {
210
+ animation: select-in 150ms ease-out;
211
+ }
212
+
213
+ :global(.select__content[data-state='closed']) {
214
+ animation: select-out 100ms ease-in;
215
+ }
216
+
217
+ @keyframes -global-select-in {
218
+ from {
219
+ opacity: 0;
220
+ transform: translateY(-4px);
221
+ }
222
+ to {
223
+ opacity: 1;
224
+ transform: translateY(0);
225
+ }
226
+ }
227
+
228
+ @keyframes -global-select-out {
229
+ from {
230
+ opacity: 1;
231
+ transform: translateY(0);
232
+ }
233
+ to {
234
+ opacity: 0;
235
+ transform: translateY(-4px);
236
+ }
205
237
  }
206
238
 
207
239
  :global(.select__viewport) {
208
- padding: var(--space-xs, 0.25rem);
240
+ padding: var(--space-xs, 0.25rem) 0;
241
+ max-height: 20rem;
242
+ overflow-y: auto;
209
243
  }
210
244
 
211
245
  :global(.select__item) {
212
246
  display: flex;
213
247
  align-items: center;
214
248
  justify-content: space-between;
215
- padding: 0.375rem 0.5rem;
216
- border-radius: var(--radius-sm, 0.25rem);
249
+ padding: 0.625rem 1rem;
217
250
  font-size: var(--text-sm, 0.875rem);
218
- line-height: 1.25;
251
+ line-height: 1.5;
219
252
  color: var(--color-text, #1f2937);
220
253
  cursor: pointer;
221
254
  outline: none;
222
- transition: background var(--transition-fast, 150ms ease);
255
+ transition:
256
+ background var(--transition-fast, 150ms ease),
257
+ color var(--transition-fast, 150ms ease);
223
258
  }
224
259
 
225
260
  :global(.select__item:hover),
226
261
  :global(.select__item[data-highlighted]) {
227
- background: var(--color-bg-muted, #f3f4f6);
262
+ background: var(--color-primary, #3b82f6);
263
+ color: var(--color-text-inverse, #ffffff);
228
264
  }
229
265
 
230
266
  :global(.select__item[data-selected]) {
231
- background: var(--color-primary-alpha, rgba(59, 130, 246, 0.1));
232
- color: var(--color-primary, #3b82f6);
267
+ background: var(--color-primary, #3b82f6);
268
+ color: var(--color-text-inverse, #ffffff);
233
269
  }
234
270
 
235
271
  :global(.select__item[data-disabled]) {
236
272
  opacity: 0.5;
237
273
  cursor: not-allowed;
274
+ background: transparent;
275
+ color: var(--color-text-muted, #9ca3af);
276
+ }
277
+
278
+ :global(.select__item[data-disabled]:hover) {
279
+ background: transparent;
280
+ color: var(--color-text-muted, #9ca3af);
238
281
  }
239
282
 
240
283
  .select__item-text {
@@ -245,7 +288,7 @@
245
288
  display: flex;
246
289
  align-items: center;
247
290
  justify-content: center;
248
- color: var(--color-primary, #3b82f6);
291
+ color: currentColor;
249
292
  margin-left: var(--space-sm, 0.5rem);
250
293
  }
251
294
  </style>
@@ -0,0 +1,59 @@
1
+ <script lang="ts">
2
+ import type { SkeletonProps } from '../../types/index.js';
3
+
4
+ interface Props extends SkeletonProps {
5
+ variant?: 'text' | 'circle' | 'rectangle';
6
+ width?: string;
7
+ height?: string;
8
+ class?: string;
9
+ }
10
+
11
+ let { variant = 'text', width, height, class: className = '' }: Props = $props();
12
+
13
+ // Determine default dimensions based on variant
14
+ const defaultWidth = $derived(
15
+ variant === 'text' ? '100%' : variant === 'circle' ? '2.5rem' : '100%'
16
+ );
17
+ const defaultHeight = $derived(
18
+ variant === 'text' ? '1rem' : variant === 'circle' ? '2.5rem' : '8rem'
19
+ );
20
+
21
+ // Use provided dimensions or defaults
22
+ const finalWidth = $derived(width ?? defaultWidth);
23
+ const finalHeight = $derived(height ?? defaultHeight);
24
+
25
+ // Border radius based on variant
26
+ const borderRadius = $derived(
27
+ variant === 'circle'
28
+ ? '50%'
29
+ : variant === 'text'
30
+ ? 'var(--exon-radius-sm, 0.25rem)'
31
+ : 'var(--exon-radius-md, 0.375rem)'
32
+ );
33
+ </script>
34
+
35
+ <div
36
+ class="skeleton {className}"
37
+ aria-hidden="true"
38
+ role="presentation"
39
+ style="width: {finalWidth}; height: {finalHeight}; border-radius: {borderRadius};"
40
+ ></div>
41
+
42
+ <style>
43
+ .skeleton {
44
+ display: block;
45
+ background: var(--exon-skeleton-bg, var(--color-neutral-200, #e5e7eb));
46
+ font-family: inherit;
47
+ animation: skeleton-pulse 1.5s ease-in-out infinite;
48
+ }
49
+
50
+ @keyframes skeleton-pulse {
51
+ 0%,
52
+ 100% {
53
+ opacity: 1;
54
+ }
55
+ 50% {
56
+ opacity: 0.5;
57
+ }
58
+ }
59
+ </style>
@@ -0,0 +1,10 @@
1
+ import type { SkeletonProps } from '../../types/index.js';
2
+ interface Props extends SkeletonProps {
3
+ variant?: 'text' | 'circle' | 'rectangle';
4
+ width?: string;
5
+ height?: string;
6
+ class?: string;
7
+ }
8
+ declare const Skeleton: import("svelte").Component<Props, {}, "">;
9
+ type Skeleton = ReturnType<typeof Skeleton>;
10
+ export default Skeleton;
@@ -0,0 +1 @@
1
+ export { default as Skeleton } from './Skeleton.svelte';
@@ -0,0 +1 @@
1
+ export { default as Skeleton } from './Skeleton.svelte';
@@ -0,0 +1,56 @@
1
+ <script lang="ts">
2
+ import type { SpacerProps, SpacerSize } from '../../types/index.js';
3
+
4
+ interface Props extends SpacerProps {}
5
+
6
+ let { size = 'md', class: className = '' }: Props = $props();
7
+ </script>
8
+
9
+ <div class="spacer {className}" data-size={size} aria-hidden="true"></div>
10
+
11
+ <style>
12
+ .spacer {
13
+ font-family: inherit;
14
+ }
15
+
16
+ /* Fixed size spacers */
17
+ .spacer[data-size='xs'] {
18
+ height: var(--space-xs, 0.25rem);
19
+ width: var(--space-xs, 0.25rem);
20
+ }
21
+
22
+ .spacer[data-size='sm'] {
23
+ height: var(--space-sm, 0.5rem);
24
+ width: var(--space-sm, 0.5rem);
25
+ }
26
+
27
+ .spacer[data-size='md'] {
28
+ height: var(--space-md, 1rem);
29
+ width: var(--space-md, 1rem);
30
+ }
31
+
32
+ .spacer[data-size='lg'] {
33
+ height: var(--space-lg, 1.5rem);
34
+ width: var(--space-lg, 1.5rem);
35
+ }
36
+
37
+ .spacer[data-size='xl'] {
38
+ height: var(--space-xl, 2rem);
39
+ width: var(--space-xl, 2rem);
40
+ }
41
+
42
+ .spacer[data-size='2xl'] {
43
+ height: var(--space-2xl, 3rem);
44
+ width: var(--space-2xl, 3rem);
45
+ }
46
+
47
+ .spacer[data-size='3xl'] {
48
+ height: var(--space-3xl, 4rem);
49
+ width: var(--space-3xl, 4rem);
50
+ }
51
+
52
+ /* Fill mode - grows to fill available space in flex container */
53
+ .spacer[data-size='fill'] {
54
+ flex: 1;
55
+ }
56
+ </style>
@@ -0,0 +1,6 @@
1
+ import type { SpacerProps } from '../../types/index.js';
2
+ interface Props extends SpacerProps {
3
+ }
4
+ declare const Spacer: import("svelte").Component<Props, {}, "">;
5
+ type Spacer = ReturnType<typeof Spacer>;
6
+ export default Spacer;
@@ -0,0 +1 @@
1
+ export { default as Spacer } from './Spacer.svelte';
@@ -0,0 +1 @@
1
+ export { default as Spacer } from './Spacer.svelte';