@aspect-ops/exon-ui 0.0.2 → 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 (237) 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/ActionSheet/ActionSheet.svelte +270 -0
  9. package/dist/components/ActionSheet/ActionSheet.svelte.d.ts +12 -0
  10. package/dist/components/ActionSheet/ActionSheetItem.svelte +151 -0
  11. package/dist/components/ActionSheet/ActionSheetItem.svelte.d.ts +10 -0
  12. package/dist/components/ActionSheet/index.d.ts +3 -0
  13. package/dist/components/ActionSheet/index.js +2 -0
  14. package/dist/components/Alert/Alert.svelte +165 -0
  15. package/dist/components/Alert/Alert.svelte.d.ts +11 -0
  16. package/dist/components/Alert/index.d.ts +1 -0
  17. package/dist/components/Alert/index.js +1 -0
  18. package/dist/components/AspectRatio/AspectRatio.svelte +42 -0
  19. package/dist/components/AspectRatio/AspectRatio.svelte.d.ts +9 -0
  20. package/dist/components/AspectRatio/index.d.ts +1 -0
  21. package/dist/components/AspectRatio/index.js +1 -0
  22. package/dist/components/Avatar/Avatar.svelte +147 -0
  23. package/dist/components/Avatar/Avatar.svelte.d.ts +12 -0
  24. package/dist/components/Avatar/AvatarGroup.svelte +153 -0
  25. package/dist/components/Avatar/AvatarGroup.svelte.d.ts +12 -0
  26. package/dist/components/Avatar/index.d.ts +2 -0
  27. package/dist/components/Avatar/index.js +2 -0
  28. package/dist/components/BottomSheet/BottomSheet.svelte +230 -0
  29. package/dist/components/BottomSheet/BottomSheet.svelte.d.ts +7 -0
  30. package/dist/components/BottomSheet/BottomSheetBody.svelte +20 -0
  31. package/dist/components/BottomSheet/BottomSheetBody.svelte.d.ts +7 -0
  32. package/dist/components/BottomSheet/BottomSheetHeader.svelte +27 -0
  33. package/dist/components/BottomSheet/BottomSheetHeader.svelte.d.ts +7 -0
  34. package/dist/components/BottomSheet/index.d.ts +3 -0
  35. package/dist/components/BottomSheet/index.js +3 -0
  36. package/dist/components/Box/Box.svelte +41 -0
  37. package/dist/components/Box/Box.svelte.d.ts +7 -0
  38. package/dist/components/Box/index.d.ts +1 -0
  39. package/dist/components/Box/index.js +1 -0
  40. package/dist/components/Card/Card.svelte +95 -0
  41. package/dist/components/Card/Card.svelte.d.ts +10 -0
  42. package/dist/components/Card/CardBody.svelte +32 -0
  43. package/dist/components/Card/CardBody.svelte.d.ts +7 -0
  44. package/dist/components/Card/CardFooter.svelte +34 -0
  45. package/dist/components/Card/CardFooter.svelte.d.ts +7 -0
  46. package/dist/components/Card/CardHeader.svelte +67 -0
  47. package/dist/components/Card/CardHeader.svelte.d.ts +9 -0
  48. package/dist/components/Card/index.d.ts +4 -0
  49. package/dist/components/Card/index.js +4 -0
  50. package/dist/components/Carousel/Carousel.svelte +454 -0
  51. package/dist/components/Carousel/Carousel.svelte.d.ts +14 -0
  52. package/dist/components/Carousel/CarouselSlide.svelte +22 -0
  53. package/dist/components/Carousel/CarouselSlide.svelte.d.ts +7 -0
  54. package/dist/components/Carousel/index.d.ts +2 -0
  55. package/dist/components/Carousel/index.js +2 -0
  56. package/dist/components/Center/Center.svelte +28 -0
  57. package/dist/components/Center/Center.svelte.d.ts +8 -0
  58. package/dist/components/Center/index.d.ts +1 -0
  59. package/dist/components/Center/index.js +1 -0
  60. package/dist/components/Chip/Chip.svelte +461 -0
  61. package/dist/components/Chip/Chip.svelte.d.ts +17 -0
  62. package/dist/components/Chip/ChipGroup.svelte +76 -0
  63. package/dist/components/Chip/ChipGroup.svelte.d.ts +9 -0
  64. package/dist/components/Chip/index.d.ts +2 -0
  65. package/dist/components/Chip/index.js +2 -0
  66. package/dist/components/Container/Container.svelte +58 -0
  67. package/dist/components/Container/Container.svelte.d.ts +10 -0
  68. package/dist/components/Container/index.d.ts +1 -0
  69. package/dist/components/Container/index.js +1 -0
  70. package/dist/components/DatePicker/DatePicker.svelte +746 -0
  71. package/dist/components/DatePicker/DatePicker.svelte.d.ts +19 -0
  72. package/dist/components/DatePicker/index.d.ts +1 -0
  73. package/dist/components/DatePicker/index.js +1 -0
  74. package/dist/components/Divider/Divider.svelte +38 -0
  75. package/dist/components/Divider/Divider.svelte.d.ts +9 -0
  76. package/dist/components/Divider/index.d.ts +1 -0
  77. package/dist/components/Divider/index.js +1 -0
  78. package/dist/components/EmptyState/EmptyState.svelte +164 -0
  79. package/dist/components/EmptyState/EmptyState.svelte.d.ts +12 -0
  80. package/dist/components/EmptyState/index.d.ts +1 -0
  81. package/dist/components/EmptyState/index.js +1 -0
  82. package/dist/components/FAB/FAB.svelte +242 -0
  83. package/dist/components/FAB/FAB.svelte.d.ts +9 -0
  84. package/dist/components/FAB/FABGroup.svelte +449 -0
  85. package/dist/components/FAB/FABGroup.svelte.d.ts +9 -0
  86. package/dist/components/FAB/index.d.ts +3 -0
  87. package/dist/components/FAB/index.js +2 -0
  88. package/dist/components/FileUpload/FileUpload.svelte +484 -0
  89. package/dist/components/FileUpload/FileUpload.svelte.d.ts +16 -0
  90. package/dist/components/FileUpload/index.d.ts +1 -0
  91. package/dist/components/FileUpload/index.js +1 -0
  92. package/dist/components/Grid/Grid.svelte +136 -0
  93. package/dist/components/Grid/Grid.svelte.d.ts +12 -0
  94. package/dist/components/Grid/GridItem.svelte +21 -0
  95. package/dist/components/Grid/GridItem.svelte.d.ts +7 -0
  96. package/dist/components/Grid/index.d.ts +2 -0
  97. package/dist/components/Grid/index.js +2 -0
  98. package/dist/components/Image/Image.svelte +223 -0
  99. package/dist/components/Image/Image.svelte.d.ts +19 -0
  100. package/dist/components/Image/index.d.ts +1 -0
  101. package/dist/components/Image/index.js +1 -0
  102. package/dist/components/List/List.svelte +42 -0
  103. package/dist/components/List/List.svelte.d.ts +18 -0
  104. package/dist/components/List/ListItem.svelte +139 -0
  105. package/dist/components/List/ListItem.svelte.d.ts +36 -0
  106. package/dist/components/List/index.d.ts +2 -0
  107. package/dist/components/List/index.js +2 -0
  108. package/dist/components/Modal/Modal.svelte +204 -0
  109. package/dist/components/Modal/Modal.svelte.d.ts +7 -0
  110. package/dist/components/Modal/ModalBody.svelte +50 -0
  111. package/dist/components/Modal/ModalBody.svelte.d.ts +7 -0
  112. package/dist/components/Modal/ModalFooter.svelte +37 -0
  113. package/dist/components/Modal/ModalFooter.svelte.d.ts +7 -0
  114. package/dist/components/Modal/ModalHeader.svelte +73 -0
  115. package/dist/components/Modal/ModalHeader.svelte.d.ts +7 -0
  116. package/dist/components/Modal/index.d.ts +4 -0
  117. package/dist/components/Modal/index.js +4 -0
  118. package/dist/components/OTPInput/OTPInput.svelte +312 -0
  119. package/dist/components/OTPInput/OTPInput.svelte.d.ts +57 -0
  120. package/dist/components/OTPInput/index.d.ts +1 -0
  121. package/dist/components/OTPInput/index.js +1 -0
  122. package/dist/components/Popover/Popover.svelte +14 -0
  123. package/dist/components/Popover/Popover.svelte.d.ts +7 -0
  124. package/dist/components/Popover/PopoverContent.svelte +63 -0
  125. package/dist/components/Popover/PopoverContent.svelte.d.ts +7 -0
  126. package/dist/components/Popover/PopoverTrigger.svelte +14 -0
  127. package/dist/components/Popover/PopoverTrigger.svelte.d.ts +7 -0
  128. package/dist/components/Popover/index.d.ts +3 -0
  129. package/dist/components/Popover/index.js +3 -0
  130. package/dist/components/Progress/ProgressBar.svelte +86 -0
  131. package/dist/components/Progress/ProgressBar.svelte.d.ts +11 -0
  132. package/dist/components/Progress/ProgressCircle.svelte +134 -0
  133. package/dist/components/Progress/ProgressCircle.svelte.d.ts +12 -0
  134. package/dist/components/Progress/Spinner.svelte +68 -0
  135. package/dist/components/Progress/Spinner.svelte.d.ts +8 -0
  136. package/dist/components/Progress/index.d.ts +3 -0
  137. package/dist/components/Progress/index.js +3 -0
  138. package/dist/components/PullToRefresh/PullToRefresh.svelte +304 -0
  139. package/dist/components/PullToRefresh/PullToRefresh.svelte.d.ts +20 -0
  140. package/dist/components/PullToRefresh/index.d.ts +1 -0
  141. package/dist/components/PullToRefresh/index.js +1 -0
  142. package/dist/components/Rating/Rating.svelte +316 -0
  143. package/dist/components/Rating/Rating.svelte.d.ts +16 -0
  144. package/dist/components/Rating/index.d.ts +1 -0
  145. package/dist/components/Rating/index.js +1 -0
  146. package/dist/components/SafeArea/SafeArea.svelte +33 -0
  147. package/dist/components/SafeArea/SafeArea.svelte.d.ts +7 -0
  148. package/dist/components/SearchInput/SearchInput.svelte +480 -0
  149. package/dist/components/SearchInput/SearchInput.svelte.d.ts +22 -0
  150. package/dist/components/SearchInput/index.d.ts +1 -0
  151. package/dist/components/SearchInput/index.js +1 -0
  152. package/dist/components/Select/Select.svelte +55 -12
  153. package/dist/components/Skeleton/Skeleton.svelte +59 -0
  154. package/dist/components/Skeleton/Skeleton.svelte.d.ts +10 -0
  155. package/dist/components/Skeleton/index.d.ts +1 -0
  156. package/dist/components/Skeleton/index.js +1 -0
  157. package/dist/components/Slider/Slider.svelte +324 -0
  158. package/dist/components/Slider/Slider.svelte.d.ts +14 -0
  159. package/dist/components/Slider/index.d.ts +1 -0
  160. package/dist/components/Slider/index.js +1 -0
  161. package/dist/components/Spacer/Spacer.svelte +56 -0
  162. package/dist/components/Spacer/Spacer.svelte.d.ts +6 -0
  163. package/dist/components/Spacer/index.d.ts +1 -0
  164. package/dist/components/Spacer/index.js +1 -0
  165. package/dist/components/Stack/Stack.svelte +117 -0
  166. package/dist/components/Stack/Stack.svelte.d.ts +13 -0
  167. package/dist/components/Stack/index.d.ts +1 -0
  168. package/dist/components/Stack/index.js +1 -0
  169. package/dist/components/Stepper/Stepper.svelte +100 -0
  170. package/dist/components/Stepper/Stepper.svelte.d.ts +11 -0
  171. package/dist/components/Stepper/StepperStep.svelte +391 -0
  172. package/dist/components/Stepper/StepperStep.svelte.d.ts +13 -0
  173. package/dist/components/Stepper/index.d.ts +2 -0
  174. package/dist/components/Stepper/index.js +2 -0
  175. package/dist/components/SwipeActions/SwipeAction.svelte +43 -0
  176. package/dist/components/SwipeActions/SwipeAction.svelte.d.ts +8 -0
  177. package/dist/components/SwipeActions/SwipeActions.svelte +193 -0
  178. package/dist/components/SwipeActions/SwipeActions.svelte.d.ts +9 -0
  179. package/dist/components/SwipeActions/index.d.ts +2 -0
  180. package/dist/components/SwipeActions/index.js +2 -0
  181. package/dist/components/Switch/Switch.svelte +29 -9
  182. package/dist/components/Table/Table.svelte +175 -0
  183. package/dist/components/Table/Table.svelte.d.ts +38 -0
  184. package/dist/components/Table/TableBody.svelte +26 -0
  185. package/dist/components/Table/TableBody.svelte.d.ts +13 -0
  186. package/dist/components/Table/TableCell.svelte +85 -0
  187. package/dist/components/Table/TableCell.svelte.d.ts +28 -0
  188. package/dist/components/Table/TableHead.svelte +36 -0
  189. package/dist/components/Table/TableHead.svelte.d.ts +13 -0
  190. package/dist/components/Table/TableHeader.svelte +217 -0
  191. package/dist/components/Table/TableHeader.svelte.d.ts +32 -0
  192. package/dist/components/Table/TableRow.svelte +92 -0
  193. package/dist/components/Table/TableRow.svelte.d.ts +28 -0
  194. package/dist/components/Table/index.d.ts +6 -0
  195. package/dist/components/Table/index.js +6 -0
  196. package/dist/components/Tag/Tag.svelte +189 -0
  197. package/dist/components/Tag/Tag.svelte.d.ts +13 -0
  198. package/dist/components/Tag/index.d.ts +1 -0
  199. package/dist/components/Tag/index.js +1 -0
  200. package/dist/components/TimePicker/TimePicker.svelte +803 -0
  201. package/dist/components/TimePicker/TimePicker.svelte.d.ts +17 -0
  202. package/dist/components/TimePicker/index.d.ts +1 -0
  203. package/dist/components/TimePicker/index.js +1 -0
  204. package/dist/components/Toast/Toast.svelte +241 -0
  205. package/dist/components/Toast/Toast.svelte.d.ts +18 -0
  206. package/dist/components/Toast/ToastContainer.svelte +110 -0
  207. package/dist/components/Toast/ToastContainer.svelte.d.ts +8 -0
  208. package/dist/components/Toast/index.d.ts +3 -0
  209. package/dist/components/Toast/index.js +3 -0
  210. package/dist/components/Toast/toast.d.ts +13 -0
  211. package/dist/components/Toast/toast.js +55 -0
  212. package/dist/components/Tooltip/Tooltip.svelte +71 -0
  213. package/dist/components/Tooltip/Tooltip.svelte.d.ts +7 -0
  214. package/dist/components/Tooltip/index.d.ts +2 -0
  215. package/dist/components/Tooltip/index.js +1 -0
  216. package/dist/index.d.ts +38 -1
  217. package/dist/index.js +41 -0
  218. package/dist/styles/tokens.css +5 -0
  219. package/dist/types/data-display.d.ts +161 -0
  220. package/dist/types/data-display.js +1 -0
  221. package/dist/types/feedback.d.ts +92 -0
  222. package/dist/types/feedback.js +1 -0
  223. package/dist/types/index.d.ts +6 -1
  224. package/dist/types/input.d.ts +67 -0
  225. package/dist/types/input.js +2 -0
  226. package/dist/types/layout.d.ts +57 -0
  227. package/dist/types/layout.js +1 -0
  228. package/dist/types/mobile.d.ts +91 -0
  229. package/dist/types/mobile.js +1 -0
  230. package/dist/types/navigation.d.ts +15 -0
  231. package/dist/utils/gestures.d.ts +219 -0
  232. package/dist/utils/gestures.js +492 -0
  233. package/dist/utils/haptics.d.ts +89 -0
  234. package/dist/utils/haptics.js +198 -0
  235. package/dist/utils/platform.d.ts +47 -0
  236. package/dist/utils/platform.js +156 -0
  237. package/package.json +1 -1
@@ -0,0 +1,3 @@
1
+ export { default as Popover } from './Popover.svelte';
2
+ export { default as PopoverTrigger } from './PopoverTrigger.svelte';
3
+ export { default as PopoverContent } from './PopoverContent.svelte';
@@ -0,0 +1,86 @@
1
+ <script lang="ts">
2
+ import type { ProgressBarProps } from '../../types/index.js';
3
+
4
+ interface Props extends ProgressBarProps {
5
+ value?: number;
6
+ max?: number;
7
+ indeterminate?: boolean;
8
+ size?: 'sm' | 'md' | 'lg';
9
+ class?: string;
10
+ }
11
+
12
+ let {
13
+ value = 0,
14
+ max = 100,
15
+ indeterminate = false,
16
+ size = 'md',
17
+ class: className = ''
18
+ }: Props = $props();
19
+
20
+ // Calculate percentage for determinate mode
21
+ const percentage = $derived(indeterminate ? 0 : Math.min(100, Math.max(0, (value / max) * 100)));
22
+ </script>
23
+
24
+ <div
25
+ class="progress-bar progress-bar--{size} {className}"
26
+ role="progressbar"
27
+ aria-valuemin="0"
28
+ aria-valuemax={max}
29
+ aria-valuenow={indeterminate ? undefined : value}
30
+ aria-label={indeterminate ? 'Loading' : `${Math.round(percentage)}% complete`}
31
+ >
32
+ <div
33
+ class="progress-bar__fill"
34
+ class:progress-bar__fill--indeterminate={indeterminate}
35
+ style="width: {indeterminate ? '30%' : `${percentage}%`}"
36
+ ></div>
37
+ </div>
38
+
39
+ <style>
40
+ .progress-bar {
41
+ position: relative;
42
+ width: 100%;
43
+ overflow: hidden;
44
+ background-color: var(--exon-progress-track, var(--color-neutral-200, #e5e7eb));
45
+ border-radius: var(--exon-radius-full, 9999px);
46
+ font-family: inherit;
47
+ }
48
+
49
+ /* Size variants */
50
+ .progress-bar--sm {
51
+ height: 0.25rem;
52
+ }
53
+
54
+ .progress-bar--md {
55
+ height: 0.5rem;
56
+ }
57
+
58
+ .progress-bar--lg {
59
+ height: 0.75rem;
60
+ }
61
+
62
+ /* Progress fill */
63
+ .progress-bar__fill {
64
+ height: 100%;
65
+ background-color: var(--exon-progress-fill, var(--color-primary, #3b82f6));
66
+ border-radius: var(--exon-radius-full, 9999px);
67
+ transition: width 0.3s ease;
68
+ }
69
+
70
+ /* Indeterminate animation */
71
+ .progress-bar__fill--indeterminate {
72
+ animation: progress-indeterminate 1.5s ease-in-out infinite;
73
+ }
74
+
75
+ @keyframes progress-indeterminate {
76
+ 0% {
77
+ transform: translateX(-100%);
78
+ }
79
+ 50% {
80
+ transform: translateX(350%);
81
+ }
82
+ 100% {
83
+ transform: translateX(-100%);
84
+ }
85
+ }
86
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { ProgressBarProps } from '../../types/index.js';
2
+ interface Props extends ProgressBarProps {
3
+ value?: number;
4
+ max?: number;
5
+ indeterminate?: boolean;
6
+ size?: 'sm' | 'md' | 'lg';
7
+ class?: string;
8
+ }
9
+ declare const ProgressBar: import("svelte").Component<Props, {}, "">;
10
+ type ProgressBar = ReturnType<typeof ProgressBar>;
11
+ export default ProgressBar;
@@ -0,0 +1,134 @@
1
+ <script lang="ts">
2
+ import type { ProgressCircleProps } from '../../types/index.js';
3
+
4
+ interface Props extends ProgressCircleProps {
5
+ value?: number;
6
+ max?: number;
7
+ indeterminate?: boolean;
8
+ size?: 'sm' | 'md' | 'lg';
9
+ strokeWidth?: number;
10
+ class?: string;
11
+ }
12
+
13
+ let {
14
+ value = 0,
15
+ max = 100,
16
+ indeterminate = false,
17
+ size = 'md',
18
+ strokeWidth = 4,
19
+ class: className = ''
20
+ }: Props = $props();
21
+
22
+ // SVG constants
23
+ const radius = 45;
24
+ const circumference = 2 * Math.PI * radius;
25
+
26
+ // Calculate percentage and stroke-dashoffset for determinate mode
27
+ const percentage = $derived(indeterminate ? 0 : Math.min(100, Math.max(0, (value / max) * 100)));
28
+ const strokeDashoffset = $derived(circumference * (1 - percentage / 100));
29
+ </script>
30
+
31
+ <div
32
+ class="progress-circle progress-circle--{size} {className}"
33
+ role="progressbar"
34
+ aria-valuemin="0"
35
+ aria-valuemax={max}
36
+ aria-valuenow={indeterminate ? undefined : value}
37
+ aria-label={indeterminate ? 'Loading' : `${Math.round(percentage)}% complete`}
38
+ >
39
+ <svg class="progress-circle__svg" viewBox="0 0 100 100">
40
+ <!-- Track circle (background) -->
41
+ <circle
42
+ class="progress-circle__track"
43
+ cx="50"
44
+ cy="50"
45
+ r={radius}
46
+ fill="none"
47
+ stroke-width={strokeWidth}
48
+ />
49
+
50
+ <!-- Progress circle (foreground) -->
51
+ <circle
52
+ class="progress-circle__fill"
53
+ class:progress-circle__fill--indeterminate={indeterminate}
54
+ cx="50"
55
+ cy="50"
56
+ r={radius}
57
+ fill="none"
58
+ stroke-width={strokeWidth}
59
+ stroke-dasharray={circumference}
60
+ stroke-dashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}
61
+ stroke-linecap="round"
62
+ />
63
+ </svg>
64
+ </div>
65
+
66
+ <style>
67
+ .progress-circle {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ font-family: inherit;
72
+ }
73
+
74
+ /* Size variants */
75
+ .progress-circle--sm {
76
+ width: 1.5rem;
77
+ height: 1.5rem;
78
+ }
79
+
80
+ .progress-circle--md {
81
+ width: 2.5rem;
82
+ height: 2.5rem;
83
+ }
84
+
85
+ .progress-circle--lg {
86
+ width: 3.5rem;
87
+ height: 3.5rem;
88
+ }
89
+
90
+ .progress-circle__svg {
91
+ width: 100%;
92
+ height: 100%;
93
+ transform: rotate(-90deg);
94
+ }
95
+
96
+ /* Track circle (background) */
97
+ .progress-circle__track {
98
+ stroke: var(--exon-progress-track, var(--color-neutral-200, #e5e7eb));
99
+ }
100
+
101
+ /* Progress circle (foreground fill) */
102
+ .progress-circle__fill {
103
+ stroke: var(--exon-progress-fill, var(--color-primary, #3b82f6));
104
+ transition: stroke-dashoffset 0.3s ease;
105
+ }
106
+
107
+ /* Indeterminate animation */
108
+ .progress-circle__fill--indeterminate {
109
+ animation:
110
+ progress-circle-rotate 1.5s linear infinite,
111
+ progress-circle-dash 1.5s ease-in-out infinite;
112
+ }
113
+
114
+ @keyframes progress-circle-rotate {
115
+ 0% {
116
+ transform: rotate(0deg);
117
+ }
118
+ 100% {
119
+ transform: rotate(360deg);
120
+ }
121
+ }
122
+
123
+ @keyframes progress-circle-dash {
124
+ 0% {
125
+ stroke-dashoffset: 282.74;
126
+ }
127
+ 50% {
128
+ stroke-dashoffset: 70.685;
129
+ }
130
+ 100% {
131
+ stroke-dashoffset: 282.74;
132
+ }
133
+ }
134
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { ProgressCircleProps } from '../../types/index.js';
2
+ interface Props extends ProgressCircleProps {
3
+ value?: number;
4
+ max?: number;
5
+ indeterminate?: boolean;
6
+ size?: 'sm' | 'md' | 'lg';
7
+ strokeWidth?: number;
8
+ class?: string;
9
+ }
10
+ declare const ProgressCircle: import("svelte").Component<Props, {}, "">;
11
+ type ProgressCircle = ReturnType<typeof ProgressCircle>;
12
+ export default ProgressCircle;
@@ -0,0 +1,68 @@
1
+ <script lang="ts">
2
+ import type { SpinnerProps } from '../../types/index.js';
3
+
4
+ interface Props extends SpinnerProps {
5
+ size?: 'sm' | 'md' | 'lg';
6
+ class?: string;
7
+ }
8
+
9
+ let { size = 'md', class: className = '' }: Props = $props();
10
+ </script>
11
+
12
+ <div class="spinner spinner--{size} {className}" role="status" aria-label="Loading">
13
+ <span class="spinner__visually-hidden">Loading...</span>
14
+ </div>
15
+
16
+ <style>
17
+ .spinner {
18
+ display: inline-block;
19
+ border-style: solid;
20
+ border-color: var(--exon-spinner-color, var(--color-primary, #3b82f6)) transparent transparent
21
+ transparent;
22
+ border-radius: 50%;
23
+ animation: spinner-rotate 0.75s linear infinite;
24
+ font-family: inherit;
25
+ }
26
+
27
+ /* Size variants - diameter and border-width */
28
+ .spinner--sm {
29
+ width: 1rem;
30
+ height: 1rem;
31
+ border-width: 2px;
32
+ }
33
+
34
+ .spinner--md {
35
+ width: 1.5rem;
36
+ height: 1.5rem;
37
+ border-width: 2px;
38
+ }
39
+
40
+ .spinner--lg {
41
+ width: 2rem;
42
+ height: 2rem;
43
+ border-width: 3px;
44
+ }
45
+
46
+ /* Visually hidden text for screen readers */
47
+ .spinner__visually-hidden {
48
+ position: absolute;
49
+ width: 1px;
50
+ height: 1px;
51
+ padding: 0;
52
+ margin: -1px;
53
+ overflow: hidden;
54
+ clip: rect(0, 0, 0, 0);
55
+ white-space: nowrap;
56
+ border-width: 0;
57
+ }
58
+
59
+ /* Rotation animation */
60
+ @keyframes spinner-rotate {
61
+ 0% {
62
+ transform: rotate(0deg);
63
+ }
64
+ 100% {
65
+ transform: rotate(360deg);
66
+ }
67
+ }
68
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { SpinnerProps } from '../../types/index.js';
2
+ interface Props extends SpinnerProps {
3
+ size?: 'sm' | 'md' | 'lg';
4
+ class?: string;
5
+ }
6
+ declare const Spinner: import("svelte").Component<Props, {}, "">;
7
+ type Spinner = ReturnType<typeof Spinner>;
8
+ export default Spinner;
@@ -0,0 +1,3 @@
1
+ export { default as ProgressBar } from './ProgressBar.svelte';
2
+ export { default as ProgressCircle } from './ProgressCircle.svelte';
3
+ export { default as Spinner } from './Spinner.svelte';
@@ -0,0 +1,3 @@
1
+ export { default as ProgressBar } from './ProgressBar.svelte';
2
+ export { default as ProgressCircle } from './ProgressCircle.svelte';
3
+ export { default as Spinner } from './Spinner.svelte';
@@ -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';