@aspect-ops/exon-ui 0.0.2 → 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 (177) hide show
  1. package/dist/components/ActionSheet/ActionSheet.svelte +270 -0
  2. package/dist/components/ActionSheet/ActionSheet.svelte.d.ts +12 -0
  3. package/dist/components/ActionSheet/ActionSheetItem.svelte +151 -0
  4. package/dist/components/ActionSheet/ActionSheetItem.svelte.d.ts +10 -0
  5. package/dist/components/ActionSheet/index.d.ts +3 -0
  6. package/dist/components/ActionSheet/index.js +2 -0
  7. package/dist/components/Alert/Alert.svelte +165 -0
  8. package/dist/components/Alert/Alert.svelte.d.ts +11 -0
  9. package/dist/components/Alert/index.d.ts +1 -0
  10. package/dist/components/Alert/index.js +1 -0
  11. package/dist/components/AspectRatio/AspectRatio.svelte +42 -0
  12. package/dist/components/AspectRatio/AspectRatio.svelte.d.ts +9 -0
  13. package/dist/components/AspectRatio/index.d.ts +1 -0
  14. package/dist/components/AspectRatio/index.js +1 -0
  15. package/dist/components/Avatar/Avatar.svelte +147 -0
  16. package/dist/components/Avatar/Avatar.svelte.d.ts +12 -0
  17. package/dist/components/Avatar/AvatarGroup.svelte +153 -0
  18. package/dist/components/Avatar/AvatarGroup.svelte.d.ts +12 -0
  19. package/dist/components/Avatar/index.d.ts +2 -0
  20. package/dist/components/Avatar/index.js +2 -0
  21. package/dist/components/BottomSheet/BottomSheet.svelte +230 -0
  22. package/dist/components/BottomSheet/BottomSheet.svelte.d.ts +7 -0
  23. package/dist/components/BottomSheet/BottomSheetBody.svelte +20 -0
  24. package/dist/components/BottomSheet/BottomSheetBody.svelte.d.ts +7 -0
  25. package/dist/components/BottomSheet/BottomSheetHeader.svelte +27 -0
  26. package/dist/components/BottomSheet/BottomSheetHeader.svelte.d.ts +7 -0
  27. package/dist/components/BottomSheet/index.d.ts +3 -0
  28. package/dist/components/BottomSheet/index.js +3 -0
  29. package/dist/components/Box/Box.svelte +41 -0
  30. package/dist/components/Box/Box.svelte.d.ts +7 -0
  31. package/dist/components/Box/index.d.ts +1 -0
  32. package/dist/components/Box/index.js +1 -0
  33. package/dist/components/Card/Card.svelte +95 -0
  34. package/dist/components/Card/Card.svelte.d.ts +10 -0
  35. package/dist/components/Card/CardBody.svelte +32 -0
  36. package/dist/components/Card/CardBody.svelte.d.ts +7 -0
  37. package/dist/components/Card/CardFooter.svelte +34 -0
  38. package/dist/components/Card/CardFooter.svelte.d.ts +7 -0
  39. package/dist/components/Card/CardHeader.svelte +67 -0
  40. package/dist/components/Card/CardHeader.svelte.d.ts +9 -0
  41. package/dist/components/Card/index.d.ts +4 -0
  42. package/dist/components/Card/index.js +4 -0
  43. package/dist/components/Center/Center.svelte +28 -0
  44. package/dist/components/Center/Center.svelte.d.ts +8 -0
  45. package/dist/components/Center/index.d.ts +1 -0
  46. package/dist/components/Center/index.js +1 -0
  47. package/dist/components/Container/Container.svelte +58 -0
  48. package/dist/components/Container/Container.svelte.d.ts +10 -0
  49. package/dist/components/Container/index.d.ts +1 -0
  50. package/dist/components/Container/index.js +1 -0
  51. package/dist/components/Divider/Divider.svelte +38 -0
  52. package/dist/components/Divider/Divider.svelte.d.ts +9 -0
  53. package/dist/components/Divider/index.d.ts +1 -0
  54. package/dist/components/Divider/index.js +1 -0
  55. package/dist/components/EmptyState/EmptyState.svelte +164 -0
  56. package/dist/components/EmptyState/EmptyState.svelte.d.ts +12 -0
  57. package/dist/components/EmptyState/index.d.ts +1 -0
  58. package/dist/components/EmptyState/index.js +1 -0
  59. package/dist/components/FAB/FAB.svelte +242 -0
  60. package/dist/components/FAB/FAB.svelte.d.ts +9 -0
  61. package/dist/components/FAB/FABGroup.svelte +449 -0
  62. package/dist/components/FAB/FABGroup.svelte.d.ts +9 -0
  63. package/dist/components/FAB/index.d.ts +3 -0
  64. package/dist/components/FAB/index.js +2 -0
  65. package/dist/components/Grid/Grid.svelte +136 -0
  66. package/dist/components/Grid/Grid.svelte.d.ts +12 -0
  67. package/dist/components/Grid/GridItem.svelte +21 -0
  68. package/dist/components/Grid/GridItem.svelte.d.ts +7 -0
  69. package/dist/components/Grid/index.d.ts +2 -0
  70. package/dist/components/Grid/index.js +2 -0
  71. package/dist/components/List/List.svelte +42 -0
  72. package/dist/components/List/List.svelte.d.ts +18 -0
  73. package/dist/components/List/ListItem.svelte +139 -0
  74. package/dist/components/List/ListItem.svelte.d.ts +36 -0
  75. package/dist/components/List/index.d.ts +2 -0
  76. package/dist/components/List/index.js +2 -0
  77. package/dist/components/Modal/Modal.svelte +204 -0
  78. package/dist/components/Modal/Modal.svelte.d.ts +7 -0
  79. package/dist/components/Modal/ModalBody.svelte +50 -0
  80. package/dist/components/Modal/ModalBody.svelte.d.ts +7 -0
  81. package/dist/components/Modal/ModalFooter.svelte +37 -0
  82. package/dist/components/Modal/ModalFooter.svelte.d.ts +7 -0
  83. package/dist/components/Modal/ModalHeader.svelte +73 -0
  84. package/dist/components/Modal/ModalHeader.svelte.d.ts +7 -0
  85. package/dist/components/Modal/index.d.ts +4 -0
  86. package/dist/components/Modal/index.js +4 -0
  87. package/dist/components/Popover/Popover.svelte +14 -0
  88. package/dist/components/Popover/Popover.svelte.d.ts +7 -0
  89. package/dist/components/Popover/PopoverContent.svelte +63 -0
  90. package/dist/components/Popover/PopoverContent.svelte.d.ts +7 -0
  91. package/dist/components/Popover/PopoverTrigger.svelte +14 -0
  92. package/dist/components/Popover/PopoverTrigger.svelte.d.ts +7 -0
  93. package/dist/components/Popover/index.d.ts +3 -0
  94. package/dist/components/Popover/index.js +3 -0
  95. package/dist/components/Progress/ProgressBar.svelte +86 -0
  96. package/dist/components/Progress/ProgressBar.svelte.d.ts +11 -0
  97. package/dist/components/Progress/ProgressCircle.svelte +134 -0
  98. package/dist/components/Progress/ProgressCircle.svelte.d.ts +12 -0
  99. package/dist/components/Progress/Spinner.svelte +68 -0
  100. package/dist/components/Progress/Spinner.svelte.d.ts +8 -0
  101. package/dist/components/Progress/index.d.ts +3 -0
  102. package/dist/components/Progress/index.js +3 -0
  103. package/dist/components/PullToRefresh/PullToRefresh.svelte +304 -0
  104. package/dist/components/PullToRefresh/PullToRefresh.svelte.d.ts +20 -0
  105. package/dist/components/PullToRefresh/index.d.ts +1 -0
  106. package/dist/components/PullToRefresh/index.js +1 -0
  107. package/dist/components/SafeArea/SafeArea.svelte +33 -0
  108. package/dist/components/SafeArea/SafeArea.svelte.d.ts +7 -0
  109. package/dist/components/Select/Select.svelte +55 -12
  110. package/dist/components/Skeleton/Skeleton.svelte +59 -0
  111. package/dist/components/Skeleton/Skeleton.svelte.d.ts +10 -0
  112. package/dist/components/Skeleton/index.d.ts +1 -0
  113. package/dist/components/Skeleton/index.js +1 -0
  114. package/dist/components/Spacer/Spacer.svelte +56 -0
  115. package/dist/components/Spacer/Spacer.svelte.d.ts +6 -0
  116. package/dist/components/Spacer/index.d.ts +1 -0
  117. package/dist/components/Spacer/index.js +1 -0
  118. package/dist/components/Stack/Stack.svelte +117 -0
  119. package/dist/components/Stack/Stack.svelte.d.ts +13 -0
  120. package/dist/components/Stack/index.d.ts +1 -0
  121. package/dist/components/Stack/index.js +1 -0
  122. package/dist/components/SwipeActions/SwipeAction.svelte +43 -0
  123. package/dist/components/SwipeActions/SwipeAction.svelte.d.ts +8 -0
  124. package/dist/components/SwipeActions/SwipeActions.svelte +193 -0
  125. package/dist/components/SwipeActions/SwipeActions.svelte.d.ts +9 -0
  126. package/dist/components/SwipeActions/index.d.ts +2 -0
  127. package/dist/components/SwipeActions/index.js +2 -0
  128. package/dist/components/Switch/Switch.svelte +29 -9
  129. package/dist/components/Table/Table.svelte +175 -0
  130. package/dist/components/Table/Table.svelte.d.ts +38 -0
  131. package/dist/components/Table/TableBody.svelte +26 -0
  132. package/dist/components/Table/TableBody.svelte.d.ts +13 -0
  133. package/dist/components/Table/TableCell.svelte +85 -0
  134. package/dist/components/Table/TableCell.svelte.d.ts +28 -0
  135. package/dist/components/Table/TableHead.svelte +36 -0
  136. package/dist/components/Table/TableHead.svelte.d.ts +13 -0
  137. package/dist/components/Table/TableHeader.svelte +217 -0
  138. package/dist/components/Table/TableHeader.svelte.d.ts +32 -0
  139. package/dist/components/Table/TableRow.svelte +92 -0
  140. package/dist/components/Table/TableRow.svelte.d.ts +28 -0
  141. package/dist/components/Table/index.d.ts +6 -0
  142. package/dist/components/Table/index.js +6 -0
  143. package/dist/components/Tag/Tag.svelte +189 -0
  144. package/dist/components/Tag/Tag.svelte.d.ts +13 -0
  145. package/dist/components/Tag/index.d.ts +1 -0
  146. package/dist/components/Tag/index.js +1 -0
  147. package/dist/components/Toast/Toast.svelte +241 -0
  148. package/dist/components/Toast/Toast.svelte.d.ts +18 -0
  149. package/dist/components/Toast/ToastContainer.svelte +110 -0
  150. package/dist/components/Toast/ToastContainer.svelte.d.ts +8 -0
  151. package/dist/components/Toast/index.d.ts +3 -0
  152. package/dist/components/Toast/index.js +3 -0
  153. package/dist/components/Toast/toast.d.ts +13 -0
  154. package/dist/components/Toast/toast.js +55 -0
  155. package/dist/components/Tooltip/Tooltip.svelte +71 -0
  156. package/dist/components/Tooltip/Tooltip.svelte.d.ts +7 -0
  157. package/dist/components/Tooltip/index.d.ts +2 -0
  158. package/dist/components/Tooltip/index.js +1 -0
  159. package/dist/index.d.ts +29 -1
  160. package/dist/index.js +32 -0
  161. package/dist/styles/tokens.css +5 -0
  162. package/dist/types/data-display.d.ts +93 -0
  163. package/dist/types/data-display.js +1 -0
  164. package/dist/types/feedback.d.ts +92 -0
  165. package/dist/types/feedback.js +1 -0
  166. package/dist/types/index.d.ts +4 -0
  167. package/dist/types/layout.d.ts +57 -0
  168. package/dist/types/layout.js +1 -0
  169. package/dist/types/mobile.d.ts +91 -0
  170. package/dist/types/mobile.js +1 -0
  171. package/dist/utils/gestures.d.ts +219 -0
  172. package/dist/utils/gestures.js +492 -0
  173. package/dist/utils/haptics.d.ts +89 -0
  174. package/dist/utils/haptics.js +198 -0
  175. package/dist/utils/platform.d.ts +47 -0
  176. package/dist/utils/platform.js +156 -0
  177. package/package.json +1 -1
@@ -0,0 +1,147 @@
1
+ <script lang="ts">
2
+ import type { AvatarSize, AvatarShape } from '../../types/index.js';
3
+
4
+ interface Props {
5
+ src?: string;
6
+ alt?: string;
7
+ name?: string;
8
+ size?: AvatarSize;
9
+ shape?: AvatarShape;
10
+ class?: string;
11
+ }
12
+
13
+ let {
14
+ src,
15
+ alt = '',
16
+ name,
17
+ size = 'md',
18
+ shape = 'circle',
19
+ class: className = ''
20
+ }: Props = $props();
21
+
22
+ let imageLoaded = $state(false);
23
+ let imageFailed = $state(false);
24
+
25
+ // Generate initials from name (first letter of first and last word)
26
+ function getInitials(name: string): string {
27
+ const words = name.trim().split(/\s+/);
28
+ if (words.length === 0) return '';
29
+ if (words.length === 1) return words[0].charAt(0).toUpperCase();
30
+ return (words[0].charAt(0) + words[words.length - 1].charAt(0)).toUpperCase();
31
+ }
32
+
33
+ // Determine what to display based on fallback chain
34
+ const showImage = $derived(src && !imageFailed);
35
+ const showInitials = $derived(!showImage && name);
36
+ const showIcon = $derived(!showImage && !showInitials);
37
+ const initials = $derived(name ? getInitials(name) : '');
38
+
39
+ function handleImageLoad() {
40
+ imageLoaded = true;
41
+ imageFailed = false;
42
+ }
43
+
44
+ function handleImageError() {
45
+ imageLoaded = false;
46
+ imageFailed = true;
47
+ }
48
+ </script>
49
+
50
+ <div
51
+ class="avatar avatar--{size} avatar--{shape} {className}"
52
+ role="img"
53
+ aria-label={alt || name || 'Avatar'}
54
+ >
55
+ {#if showImage}
56
+ <img class="avatar__image" {src} {alt} onload={handleImageLoad} onerror={handleImageError} />
57
+ {:else if showInitials}
58
+ <span class="avatar__initials">{initials}</span>
59
+ {:else}
60
+ <svg
61
+ class="avatar__icon"
62
+ viewBox="0 0 24 24"
63
+ fill="none"
64
+ xmlns="http://www.w3.org/2000/svg"
65
+ aria-hidden="true"
66
+ >
67
+ <path
68
+ d="M12 12C14.21 12 16 10.21 16 8C16 5.79 14.21 4 12 4C9.79 4 8 5.79 8 8C8 10.21 9.79 12 12 12ZM12 14C9.33 14 4 15.34 4 18V20H20V18C20 15.34 14.67 14 12 14Z"
69
+ fill="currentColor"
70
+ />
71
+ </svg>
72
+ {/if}
73
+ </div>
74
+
75
+ <style>
76
+ .avatar {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ overflow: hidden;
81
+ background: var(--color-bg-muted, #f3f4f6);
82
+ color: var(--color-text, #1f2937);
83
+ font-family: inherit;
84
+ font-weight: 500;
85
+ flex-shrink: 0;
86
+ user-select: none;
87
+ }
88
+
89
+ /* Size variants */
90
+ .avatar--xs {
91
+ width: 1.5rem;
92
+ height: 1.5rem;
93
+ font-size: 0.625rem;
94
+ }
95
+
96
+ .avatar--sm {
97
+ width: 2rem;
98
+ height: 2rem;
99
+ font-size: 0.75rem;
100
+ }
101
+
102
+ .avatar--md {
103
+ width: 2.5rem;
104
+ height: 2.5rem;
105
+ font-size: 0.875rem;
106
+ }
107
+
108
+ .avatar--lg {
109
+ width: 3rem;
110
+ height: 3rem;
111
+ font-size: 1rem;
112
+ }
113
+
114
+ .avatar--xl {
115
+ width: 4rem;
116
+ height: 4rem;
117
+ font-size: 1.25rem;
118
+ }
119
+
120
+ /* Shape variants */
121
+ .avatar--circle {
122
+ border-radius: var(--radius-full, 9999px);
123
+ }
124
+
125
+ .avatar--square {
126
+ border-radius: var(--radius-md, 0.375rem);
127
+ }
128
+
129
+ /* Image */
130
+ .avatar__image {
131
+ width: 100%;
132
+ height: 100%;
133
+ object-fit: cover;
134
+ }
135
+
136
+ /* Initials */
137
+ .avatar__initials {
138
+ line-height: 1;
139
+ }
140
+
141
+ /* Icon */
142
+ .avatar__icon {
143
+ width: 60%;
144
+ height: 60%;
145
+ color: var(--color-text-muted, #6b7280);
146
+ }
147
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { AvatarSize, AvatarShape } from '../../types/index.js';
2
+ interface Props {
3
+ src?: string;
4
+ alt?: string;
5
+ name?: string;
6
+ size?: AvatarSize;
7
+ shape?: AvatarShape;
8
+ class?: string;
9
+ }
10
+ declare const Avatar: import("svelte").Component<Props, {}, "">;
11
+ type Avatar = ReturnType<typeof Avatar>;
12
+ export default Avatar;
@@ -0,0 +1,153 @@
1
+ <script lang="ts">
2
+ import type { AvatarSize } from '../../types/index.js';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ max?: number;
7
+ size?: AvatarSize;
8
+ spacing?: string;
9
+ children: Snippet;
10
+ class?: string;
11
+ }
12
+
13
+ let { max, size = 'md', spacing = '-0.5rem', children, class: className = '' }: Props = $props();
14
+
15
+ // Reference to the wrapper div to count children
16
+ let wrapperRef: HTMLDivElement | undefined = $state();
17
+ let totalAvatars = $state(0);
18
+ let overflowCount = $derived(max && totalAvatars > max ? totalAvatars - max : 0);
19
+
20
+ // Count child avatars and hide excess ones after mount
21
+ $effect(() => {
22
+ if (wrapperRef) {
23
+ const avatars = wrapperRef.querySelectorAll('.avatar');
24
+ totalAvatars = avatars.length;
25
+
26
+ // Hide avatars beyond max
27
+ if (max !== undefined) {
28
+ avatars.forEach((avatar, index) => {
29
+ if (index >= max) {
30
+ (avatar as HTMLElement).style.display = 'none';
31
+ } else {
32
+ (avatar as HTMLElement).style.display = '';
33
+ }
34
+ });
35
+ }
36
+ }
37
+ });
38
+ </script>
39
+
40
+ <div
41
+ bind:this={wrapperRef}
42
+ class="avatar-group avatar-group--{size} {className}"
43
+ class:avatar-group--limited={max !== undefined}
44
+ style="--avatar-group-spacing: {spacing}; --avatar-group-max: {max ?? 999};"
45
+ >
46
+ {@render children()}
47
+ {#if overflowCount > 0}
48
+ <div class="avatar-group__overflow" role="img" aria-label="+{overflowCount} more">
49
+ +{overflowCount}
50
+ </div>
51
+ {/if}
52
+ </div>
53
+
54
+ <style>
55
+ .avatar-group {
56
+ display: inline-flex;
57
+ align-items: center;
58
+ flex-direction: row;
59
+ }
60
+
61
+ /* Apply size to all child avatars via custom property */
62
+ .avatar-group :global(.avatar) {
63
+ margin-left: var(--avatar-group-spacing);
64
+ border: 2px solid var(--color-bg, #ffffff);
65
+ position: relative;
66
+ }
67
+
68
+ .avatar-group :global(.avatar:first-child) {
69
+ margin-left: 0;
70
+ }
71
+
72
+ /* Hide avatars beyond max limit - using attribute selector for dynamic max */
73
+ /* Note: This will be handled by hiding avatars beyond the max count using JavaScript */
74
+
75
+ /* Override size on child avatars when group size is set */
76
+ .avatar-group--xs :global(.avatar) {
77
+ width: 1.5rem;
78
+ height: 1.5rem;
79
+ font-size: 0.625rem;
80
+ }
81
+
82
+ .avatar-group--sm :global(.avatar) {
83
+ width: 2rem;
84
+ height: 2rem;
85
+ font-size: 0.75rem;
86
+ }
87
+
88
+ .avatar-group--md :global(.avatar) {
89
+ width: 2.5rem;
90
+ height: 2.5rem;
91
+ font-size: 0.875rem;
92
+ }
93
+
94
+ .avatar-group--lg :global(.avatar) {
95
+ width: 3rem;
96
+ height: 3rem;
97
+ font-size: 1rem;
98
+ }
99
+
100
+ .avatar-group--xl :global(.avatar) {
101
+ width: 4rem;
102
+ height: 4rem;
103
+ font-size: 1.25rem;
104
+ }
105
+
106
+ /* Overflow indicator styling */
107
+ .avatar-group__overflow {
108
+ display: inline-flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ border-radius: var(--radius-full, 9999px);
112
+ background: var(--color-bg-muted, #f3f4f6);
113
+ color: var(--color-text, #1f2937);
114
+ font-family: inherit;
115
+ font-weight: 500;
116
+ flex-shrink: 0;
117
+ user-select: none;
118
+ margin-left: var(--avatar-group-spacing);
119
+ border: 2px solid var(--color-bg, #ffffff);
120
+ position: relative;
121
+ }
122
+
123
+ /* Size variants for overflow indicator */
124
+ .avatar-group--xs .avatar-group__overflow {
125
+ width: 1.5rem;
126
+ height: 1.5rem;
127
+ font-size: 0.625rem;
128
+ }
129
+
130
+ .avatar-group--sm .avatar-group__overflow {
131
+ width: 2rem;
132
+ height: 2rem;
133
+ font-size: 0.75rem;
134
+ }
135
+
136
+ .avatar-group--md .avatar-group__overflow {
137
+ width: 2.5rem;
138
+ height: 2.5rem;
139
+ font-size: 0.875rem;
140
+ }
141
+
142
+ .avatar-group--lg .avatar-group__overflow {
143
+ width: 3rem;
144
+ height: 3rem;
145
+ font-size: 1rem;
146
+ }
147
+
148
+ .avatar-group--xl .avatar-group__overflow {
149
+ width: 4rem;
150
+ height: 4rem;
151
+ font-size: 1.25rem;
152
+ }
153
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { AvatarSize } from '../../types/index.js';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ max?: number;
5
+ size?: AvatarSize;
6
+ spacing?: string;
7
+ children: Snippet;
8
+ class?: string;
9
+ }
10
+ declare const AvatarGroup: import("svelte").Component<Props, {}, "">;
11
+ type AvatarGroup = ReturnType<typeof AvatarGroup>;
12
+ export default AvatarGroup;
@@ -0,0 +1,2 @@
1
+ export { default as Avatar } from './Avatar.svelte';
2
+ export { default as AvatarGroup } from './AvatarGroup.svelte';
@@ -0,0 +1,2 @@
1
+ export { default as Avatar } from './Avatar.svelte';
2
+ export { default as AvatarGroup } from './AvatarGroup.svelte';
@@ -0,0 +1,230 @@
1
+ <script lang="ts">
2
+ import type { BottomSheetSnapPoint, BottomSheetProps } from '../../types/index.js';
3
+ import { Dialog } from 'bits-ui';
4
+
5
+ interface Props extends BottomSheetProps {
6
+ children?: import('svelte').Snippet;
7
+ }
8
+
9
+ let {
10
+ open = $bindable(false),
11
+ snapPoints = ['half', 'full'],
12
+ defaultSnapPoint = 'half',
13
+ showHandle = true,
14
+ closeOnBackdrop = true,
15
+ closeOnEscape = true,
16
+ class: className = '',
17
+ children
18
+ }: Props = $props();
19
+
20
+ function getSnapPointValue(point: BottomSheetSnapPoint): number {
21
+ if (typeof point === 'number') return point;
22
+ const vh = typeof window !== 'undefined' ? window.innerHeight : 800;
23
+ switch (point) {
24
+ case 'min':
25
+ return vh * 0.25;
26
+ case 'half':
27
+ return vh * 0.5;
28
+ case 'full':
29
+ return vh * 0.9;
30
+ default:
31
+ return vh * 0.5;
32
+ }
33
+ }
34
+
35
+ let sheetHeight = $state(0);
36
+ let isDragging = $state(false);
37
+ let startY = 0;
38
+ let startHeight = 0;
39
+
40
+ $effect(() => {
41
+ if (open && typeof window !== 'undefined') {
42
+ sheetHeight = getSnapPointValue(defaultSnapPoint);
43
+ }
44
+ });
45
+
46
+ function handleTouchStart(e: TouchEvent) {
47
+ isDragging = true;
48
+ startY = e.touches[0].clientY;
49
+ startHeight = sheetHeight;
50
+ }
51
+
52
+ function handleTouchMove(e: TouchEvent) {
53
+ if (!isDragging) return;
54
+ const deltaY = startY - e.touches[0].clientY;
55
+ const maxHeight = typeof window !== 'undefined' ? window.innerHeight * 0.95 : 760;
56
+ const newHeight = Math.max(0, Math.min(maxHeight, startHeight + deltaY));
57
+ sheetHeight = newHeight;
58
+ }
59
+
60
+ function handleTouchEnd() {
61
+ isDragging = false;
62
+ const points = snapPoints.map(getSnapPointValue).sort((a, b) => a - b);
63
+ const minPoint = points[0] * 0.5;
64
+
65
+ if (sheetHeight < minPoint) {
66
+ open = false;
67
+ return;
68
+ }
69
+
70
+ let closest = points[0];
71
+ let minDiff = Math.abs(sheetHeight - closest);
72
+ for (const p of points) {
73
+ const diff = Math.abs(sheetHeight - p);
74
+ if (diff < minDiff) {
75
+ minDiff = diff;
76
+ closest = p;
77
+ }
78
+ }
79
+ sheetHeight = closest;
80
+ }
81
+
82
+ function handleOpenChange(value: boolean) {
83
+ if (!value && !closeOnEscape) return;
84
+ open = value;
85
+ }
86
+
87
+ function handleBackdropClick() {
88
+ if (closeOnBackdrop) open = false;
89
+ }
90
+
91
+ function handleKeydown(e: KeyboardEvent) {
92
+ if (e.key === 'Escape' && !closeOnEscape) {
93
+ e.preventDefault();
94
+ }
95
+ }
96
+ </script>
97
+
98
+ <Dialog.Root {open} onOpenChange={handleOpenChange}>
99
+ <Dialog.Portal>
100
+ <Dialog.Overlay class="bottom-sheet-overlay" onclick={handleBackdropClick} />
101
+ <Dialog.Content
102
+ class="bottom-sheet-content {className}"
103
+ style="height: {sheetHeight}px; transition: {isDragging
104
+ ? 'none'
105
+ : 'height 0.3s cubic-bezier(0.32, 0.72, 0, 1)'};"
106
+ onkeydown={handleKeydown}
107
+ >
108
+ {#if showHandle}
109
+ <div
110
+ class="bottom-sheet-handle"
111
+ ontouchstart={handleTouchStart}
112
+ ontouchmove={handleTouchMove}
113
+ ontouchend={handleTouchEnd}
114
+ role="slider"
115
+ tabindex="0"
116
+ aria-label="Resize sheet"
117
+ aria-valuenow={sheetHeight}
118
+ >
119
+ <div class="bottom-sheet-handle-bar"></div>
120
+ </div>
121
+ {/if}
122
+ <div class="bottom-sheet-inner">
123
+ {@render children?.()}
124
+ </div>
125
+ </Dialog.Content>
126
+ </Dialog.Portal>
127
+ </Dialog.Root>
128
+
129
+ <style>
130
+ :global(.bottom-sheet-overlay) {
131
+ position: fixed;
132
+ inset: 0;
133
+ background: rgba(0, 0, 0, 0.5);
134
+ z-index: 100;
135
+ }
136
+
137
+ :global(.bottom-sheet-overlay[data-state='open']) {
138
+ animation: bs-fade-in 200ms ease-out;
139
+ }
140
+
141
+ :global(.bottom-sheet-overlay[data-state='closed']) {
142
+ animation: bs-fade-out 150ms ease-in;
143
+ }
144
+
145
+ @keyframes -global-bs-fade-in {
146
+ from {
147
+ opacity: 0;
148
+ }
149
+ to {
150
+ opacity: 1;
151
+ }
152
+ }
153
+
154
+ @keyframes -global-bs-fade-out {
155
+ from {
156
+ opacity: 1;
157
+ }
158
+ to {
159
+ opacity: 0;
160
+ }
161
+ }
162
+
163
+ :global(.bottom-sheet-content) {
164
+ font-family: var(--font-family, system-ui, -apple-system, sans-serif);
165
+ position: fixed;
166
+ bottom: 0;
167
+ left: 0;
168
+ right: 0;
169
+ background: var(--color-bg, #ffffff);
170
+ border-radius: 1rem 1rem 0 0;
171
+ z-index: 101;
172
+ display: flex;
173
+ flex-direction: column;
174
+ padding-bottom: env(safe-area-inset-bottom);
175
+ box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);
176
+ }
177
+
178
+ :global(.bottom-sheet-content[data-state='open']) {
179
+ animation: bs-slide-up 300ms cubic-bezier(0.32, 0.72, 0, 1);
180
+ }
181
+
182
+ :global(.bottom-sheet-content[data-state='closed']) {
183
+ animation: bs-slide-down 200ms ease-in;
184
+ }
185
+
186
+ @keyframes -global-bs-slide-up {
187
+ from {
188
+ transform: translateY(100%);
189
+ }
190
+ to {
191
+ transform: translateY(0);
192
+ }
193
+ }
194
+
195
+ @keyframes -global-bs-slide-down {
196
+ from {
197
+ transform: translateY(0);
198
+ }
199
+ to {
200
+ transform: translateY(100%);
201
+ }
202
+ }
203
+
204
+ .bottom-sheet-handle {
205
+ display: flex;
206
+ justify-content: center;
207
+ padding: 0.75rem;
208
+ cursor: grab;
209
+ touch-action: none;
210
+ min-height: 44px;
211
+ align-items: center;
212
+ }
213
+
214
+ .bottom-sheet-handle:active {
215
+ cursor: grabbing;
216
+ }
217
+
218
+ .bottom-sheet-handle-bar {
219
+ width: 2.5rem;
220
+ height: 0.25rem;
221
+ background: var(--color-border, #e5e7eb);
222
+ border-radius: 0.125rem;
223
+ }
224
+
225
+ .bottom-sheet-inner {
226
+ flex: 1;
227
+ overflow-y: auto;
228
+ overscroll-behavior: contain;
229
+ }
230
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { BottomSheetProps } from '../../types/index.js';
2
+ interface Props extends BottomSheetProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const BottomSheet: import("svelte").Component<Props, {}, "open">;
6
+ type BottomSheet = ReturnType<typeof BottomSheet>;
7
+ export default BottomSheet;
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import type { BottomSheetBodyProps } from '../../types/index.js';
3
+
4
+ interface Props extends BottomSheetBodyProps {
5
+ children?: import('svelte').Snippet;
6
+ }
7
+
8
+ let { class: className = '', children }: Props = $props();
9
+ </script>
10
+
11
+ <div class="bottom-sheet-body {className}">
12
+ {@render children?.()}
13
+ </div>
14
+
15
+ <style>
16
+ .bottom-sheet-body {
17
+ padding: var(--space-md, 1rem);
18
+ flex: 1;
19
+ }
20
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { BottomSheetBodyProps } from '../../types/index.js';
2
+ interface Props extends BottomSheetBodyProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const BottomSheetBody: import("svelte").Component<Props, {}, "">;
6
+ type BottomSheetBody = ReturnType<typeof BottomSheetBody>;
7
+ export default BottomSheetBody;
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import type { BottomSheetHeaderProps } from '../../types/index.js';
3
+
4
+ interface Props extends BottomSheetHeaderProps {
5
+ children?: import('svelte').Snippet;
6
+ }
7
+
8
+ let { sticky = false, class: className = '', children }: Props = $props();
9
+ </script>
10
+
11
+ <div class="bottom-sheet-header {sticky ? 'bottom-sheet-header--sticky' : ''} {className}">
12
+ {@render children?.()}
13
+ </div>
14
+
15
+ <style>
16
+ .bottom-sheet-header {
17
+ padding: var(--space-md, 1rem);
18
+ border-bottom: 1px solid var(--color-border, #e5e7eb);
19
+ }
20
+
21
+ .bottom-sheet-header--sticky {
22
+ position: sticky;
23
+ top: 0;
24
+ background: var(--color-bg, #ffffff);
25
+ z-index: 1;
26
+ }
27
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { BottomSheetHeaderProps } from '../../types/index.js';
2
+ interface Props extends BottomSheetHeaderProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const BottomSheetHeader: import("svelte").Component<Props, {}, "">;
6
+ type BottomSheetHeader = ReturnType<typeof BottomSheetHeader>;
7
+ export default BottomSheetHeader;
@@ -0,0 +1,3 @@
1
+ export { default as BottomSheet } from './BottomSheet.svelte';
2
+ export { default as BottomSheetHeader } from './BottomSheetHeader.svelte';
3
+ export { default as BottomSheetBody } from './BottomSheetBody.svelte';
@@ -0,0 +1,3 @@
1
+ export { default as BottomSheet } from './BottomSheet.svelte';
2
+ export { default as BottomSheetHeader } from './BottomSheetHeader.svelte';
3
+ export { default as BottomSheetBody } from './BottomSheetBody.svelte';
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ import type { BoxProps, SpacingToken } from '../../types/index.js';
3
+
4
+ interface Props extends BoxProps {
5
+ children?: import('svelte').Snippet;
6
+ }
7
+
8
+ let { padding, margin, radius, as = 'div', class: className = '', children }: Props = $props();
9
+
10
+ function getSpacing(token: SpacingToken | undefined): string | undefined {
11
+ if (!token) return undefined;
12
+ const map: Record<SpacingToken, string> = {
13
+ xs: 'var(--space-xs, 0.25rem)',
14
+ sm: 'var(--space-sm, 0.5rem)',
15
+ md: 'var(--space-md, 1rem)',
16
+ lg: 'var(--space-lg, 1.5rem)',
17
+ xl: 'var(--space-xl, 2rem)',
18
+ '2xl': 'var(--space-2xl, 3rem)',
19
+ '3xl': 'var(--space-3xl, 4rem)'
20
+ };
21
+ return map[token];
22
+ }
23
+ </script>
24
+
25
+ <svelte:element
26
+ this={as}
27
+ class="box {className}"
28
+ style:padding={getSpacing(padding)}
29
+ style:margin={getSpacing(margin)}
30
+ style:border-radius={getSpacing(radius)}
31
+ >
32
+ {#if children}
33
+ {@render children()}
34
+ {/if}
35
+ </svelte:element>
36
+
37
+ <style>
38
+ .box {
39
+ font-family: inherit;
40
+ }
41
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { BoxProps } from '../../types/index.js';
2
+ interface Props extends BoxProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const Box: import("svelte").Component<Props, {}, "">;
6
+ type Box = ReturnType<typeof Box>;
7
+ export default Box;
@@ -0,0 +1 @@
1
+ export { default as Box } from './Box.svelte';