@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.
- package/README.md +438 -0
- package/dist/components/ActionSheet/ActionSheet.svelte +270 -0
- package/dist/components/ActionSheet/ActionSheet.svelte.d.ts +12 -0
- package/dist/components/ActionSheet/ActionSheetItem.svelte +151 -0
- package/dist/components/ActionSheet/ActionSheetItem.svelte.d.ts +10 -0
- package/dist/components/ActionSheet/index.d.ts +3 -0
- package/dist/components/ActionSheet/index.js +2 -0
- package/dist/components/Alert/Alert.svelte +165 -0
- package/dist/components/Alert/Alert.svelte.d.ts +11 -0
- package/dist/components/Alert/index.d.ts +1 -0
- package/dist/components/Alert/index.js +1 -0
- package/dist/components/AspectRatio/AspectRatio.svelte +42 -0
- package/dist/components/AspectRatio/AspectRatio.svelte.d.ts +9 -0
- package/dist/components/AspectRatio/index.d.ts +1 -0
- package/dist/components/AspectRatio/index.js +1 -0
- package/dist/components/Avatar/Avatar.svelte +147 -0
- package/dist/components/Avatar/Avatar.svelte.d.ts +12 -0
- package/dist/components/Avatar/AvatarGroup.svelte +153 -0
- package/dist/components/Avatar/AvatarGroup.svelte.d.ts +12 -0
- package/dist/components/Avatar/index.d.ts +2 -0
- package/dist/components/Avatar/index.js +2 -0
- package/dist/components/BottomSheet/BottomSheet.svelte +230 -0
- package/dist/components/BottomSheet/BottomSheet.svelte.d.ts +7 -0
- package/dist/components/BottomSheet/BottomSheetBody.svelte +20 -0
- package/dist/components/BottomSheet/BottomSheetBody.svelte.d.ts +7 -0
- package/dist/components/BottomSheet/BottomSheetHeader.svelte +27 -0
- package/dist/components/BottomSheet/BottomSheetHeader.svelte.d.ts +7 -0
- package/dist/components/BottomSheet/index.d.ts +3 -0
- package/dist/components/BottomSheet/index.js +3 -0
- package/dist/components/Box/Box.svelte +41 -0
- package/dist/components/Box/Box.svelte.d.ts +7 -0
- package/dist/components/Box/index.d.ts +1 -0
- package/dist/components/Box/index.js +1 -0
- package/dist/components/Card/Card.svelte +95 -0
- package/dist/components/Card/Card.svelte.d.ts +10 -0
- package/dist/components/Card/CardBody.svelte +32 -0
- package/dist/components/Card/CardBody.svelte.d.ts +7 -0
- package/dist/components/Card/CardFooter.svelte +34 -0
- package/dist/components/Card/CardFooter.svelte.d.ts +7 -0
- package/dist/components/Card/CardHeader.svelte +67 -0
- package/dist/components/Card/CardHeader.svelte.d.ts +9 -0
- package/dist/components/Card/index.d.ts +4 -0
- package/dist/components/Card/index.js +4 -0
- package/dist/components/Center/Center.svelte +28 -0
- package/dist/components/Center/Center.svelte.d.ts +8 -0
- package/dist/components/Center/index.d.ts +1 -0
- package/dist/components/Center/index.js +1 -0
- package/dist/components/Container/Container.svelte +58 -0
- package/dist/components/Container/Container.svelte.d.ts +10 -0
- package/dist/components/Container/index.d.ts +1 -0
- package/dist/components/Container/index.js +1 -0
- package/dist/components/Divider/Divider.svelte +38 -0
- package/dist/components/Divider/Divider.svelte.d.ts +9 -0
- package/dist/components/Divider/index.d.ts +1 -0
- package/dist/components/Divider/index.js +1 -0
- package/dist/components/EmptyState/EmptyState.svelte +164 -0
- package/dist/components/EmptyState/EmptyState.svelte.d.ts +12 -0
- package/dist/components/EmptyState/index.d.ts +1 -0
- package/dist/components/EmptyState/index.js +1 -0
- package/dist/components/FAB/FAB.svelte +242 -0
- package/dist/components/FAB/FAB.svelte.d.ts +9 -0
- package/dist/components/FAB/FABGroup.svelte +449 -0
- package/dist/components/FAB/FABGroup.svelte.d.ts +9 -0
- package/dist/components/FAB/index.d.ts +3 -0
- package/dist/components/FAB/index.js +2 -0
- package/dist/components/Grid/Grid.svelte +136 -0
- package/dist/components/Grid/Grid.svelte.d.ts +12 -0
- package/dist/components/Grid/GridItem.svelte +21 -0
- package/dist/components/Grid/GridItem.svelte.d.ts +7 -0
- package/dist/components/Grid/index.d.ts +2 -0
- package/dist/components/Grid/index.js +2 -0
- package/dist/components/List/List.svelte +42 -0
- package/dist/components/List/List.svelte.d.ts +18 -0
- package/dist/components/List/ListItem.svelte +139 -0
- package/dist/components/List/ListItem.svelte.d.ts +36 -0
- package/dist/components/List/index.d.ts +2 -0
- package/dist/components/List/index.js +2 -0
- package/dist/components/Modal/Modal.svelte +204 -0
- package/dist/components/Modal/Modal.svelte.d.ts +7 -0
- package/dist/components/Modal/ModalBody.svelte +50 -0
- package/dist/components/Modal/ModalBody.svelte.d.ts +7 -0
- package/dist/components/Modal/ModalFooter.svelte +37 -0
- package/dist/components/Modal/ModalFooter.svelte.d.ts +7 -0
- package/dist/components/Modal/ModalHeader.svelte +73 -0
- package/dist/components/Modal/ModalHeader.svelte.d.ts +7 -0
- package/dist/components/Modal/index.d.ts +4 -0
- package/dist/components/Modal/index.js +4 -0
- package/dist/components/Popover/Popover.svelte +14 -0
- package/dist/components/Popover/Popover.svelte.d.ts +7 -0
- package/dist/components/Popover/PopoverContent.svelte +63 -0
- package/dist/components/Popover/PopoverContent.svelte.d.ts +7 -0
- package/dist/components/Popover/PopoverTrigger.svelte +14 -0
- package/dist/components/Popover/PopoverTrigger.svelte.d.ts +7 -0
- package/dist/components/Popover/index.d.ts +3 -0
- package/dist/components/Popover/index.js +3 -0
- package/dist/components/Progress/ProgressBar.svelte +86 -0
- package/dist/components/Progress/ProgressBar.svelte.d.ts +11 -0
- package/dist/components/Progress/ProgressCircle.svelte +134 -0
- package/dist/components/Progress/ProgressCircle.svelte.d.ts +12 -0
- package/dist/components/Progress/Spinner.svelte +68 -0
- package/dist/components/Progress/Spinner.svelte.d.ts +8 -0
- package/dist/components/Progress/index.d.ts +3 -0
- package/dist/components/Progress/index.js +3 -0
- package/dist/components/PullToRefresh/PullToRefresh.svelte +304 -0
- package/dist/components/PullToRefresh/PullToRefresh.svelte.d.ts +20 -0
- package/dist/components/PullToRefresh/index.d.ts +1 -0
- package/dist/components/PullToRefresh/index.js +1 -0
- package/dist/components/SafeArea/SafeArea.svelte +33 -0
- package/dist/components/SafeArea/SafeArea.svelte.d.ts +7 -0
- package/dist/components/Select/Select.svelte +55 -12
- package/dist/components/Skeleton/Skeleton.svelte +59 -0
- package/dist/components/Skeleton/Skeleton.svelte.d.ts +10 -0
- package/dist/components/Skeleton/index.d.ts +1 -0
- package/dist/components/Skeleton/index.js +1 -0
- package/dist/components/Spacer/Spacer.svelte +56 -0
- package/dist/components/Spacer/Spacer.svelte.d.ts +6 -0
- package/dist/components/Spacer/index.d.ts +1 -0
- package/dist/components/Spacer/index.js +1 -0
- package/dist/components/Stack/Stack.svelte +117 -0
- package/dist/components/Stack/Stack.svelte.d.ts +13 -0
- package/dist/components/Stack/index.d.ts +1 -0
- package/dist/components/Stack/index.js +1 -0
- package/dist/components/SwipeActions/SwipeAction.svelte +43 -0
- package/dist/components/SwipeActions/SwipeAction.svelte.d.ts +8 -0
- package/dist/components/SwipeActions/SwipeActions.svelte +193 -0
- package/dist/components/SwipeActions/SwipeActions.svelte.d.ts +9 -0
- package/dist/components/SwipeActions/index.d.ts +2 -0
- package/dist/components/SwipeActions/index.js +2 -0
- package/dist/components/Switch/Switch.svelte +29 -9
- package/dist/components/Table/Table.svelte +175 -0
- package/dist/components/Table/Table.svelte.d.ts +38 -0
- package/dist/components/Table/TableBody.svelte +26 -0
- package/dist/components/Table/TableBody.svelte.d.ts +13 -0
- package/dist/components/Table/TableCell.svelte +85 -0
- package/dist/components/Table/TableCell.svelte.d.ts +28 -0
- package/dist/components/Table/TableHead.svelte +36 -0
- package/dist/components/Table/TableHead.svelte.d.ts +13 -0
- package/dist/components/Table/TableHeader.svelte +217 -0
- package/dist/components/Table/TableHeader.svelte.d.ts +32 -0
- package/dist/components/Table/TableRow.svelte +92 -0
- package/dist/components/Table/TableRow.svelte.d.ts +28 -0
- package/dist/components/Table/index.d.ts +6 -0
- package/dist/components/Table/index.js +6 -0
- package/dist/components/Tag/Tag.svelte +189 -0
- package/dist/components/Tag/Tag.svelte.d.ts +13 -0
- package/dist/components/Tag/index.d.ts +1 -0
- package/dist/components/Tag/index.js +1 -0
- package/dist/components/Toast/Toast.svelte +241 -0
- package/dist/components/Toast/Toast.svelte.d.ts +18 -0
- package/dist/components/Toast/ToastContainer.svelte +110 -0
- package/dist/components/Toast/ToastContainer.svelte.d.ts +8 -0
- package/dist/components/Toast/index.d.ts +3 -0
- package/dist/components/Toast/index.js +3 -0
- package/dist/components/Toast/toast.d.ts +13 -0
- package/dist/components/Toast/toast.js +55 -0
- package/dist/components/Tooltip/Tooltip.svelte +71 -0
- package/dist/components/Tooltip/Tooltip.svelte.d.ts +7 -0
- package/dist/components/Tooltip/index.d.ts +2 -0
- package/dist/components/Tooltip/index.js +1 -0
- package/dist/index.d.ts +29 -1
- package/dist/index.js +32 -0
- package/dist/styles/tokens.css +5 -0
- package/dist/types/data-display.d.ts +93 -0
- package/dist/types/data-display.js +1 -0
- package/dist/types/feedback.d.ts +92 -0
- package/dist/types/feedback.js +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/layout.d.ts +57 -0
- package/dist/types/layout.js +1 -0
- package/dist/types/mobile.d.ts +91 -0
- package/dist/types/mobile.js +1 -0
- package/dist/utils/gestures.d.ts +219 -0
- package/dist/utils/gestures.js +492 -0
- package/dist/utils/haptics.d.ts +89 -0
- package/dist/utils/haptics.js +198 -0
- package/dist/utils/platform.d.ts +47 -0
- package/dist/utils/platform.js +156 -0
- package/package.json +1 -1
|
@@ -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,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,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 @@
|
|
|
1
|
+
export { default as Box } from './Box.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Box } from './Box.svelte';
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { CardVariant } from '../../types/index.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
variant?: CardVariant;
|
|
6
|
+
clickable?: boolean;
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: import('svelte').Snippet;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
variant = 'elevated',
|
|
13
|
+
clickable = false,
|
|
14
|
+
class: className = '',
|
|
15
|
+
children
|
|
16
|
+
}: Props = $props();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
{#if clickable}
|
|
20
|
+
<button type="button" class="card card--{variant} card--clickable {className}">
|
|
21
|
+
{#if children}
|
|
22
|
+
{@render children()}
|
|
23
|
+
{/if}
|
|
24
|
+
</button>
|
|
25
|
+
{:else}
|
|
26
|
+
<div class="card card--{variant} {className}">
|
|
27
|
+
{#if children}
|
|
28
|
+
{@render children()}
|
|
29
|
+
{/if}
|
|
30
|
+
</div>
|
|
31
|
+
{/if}
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.card {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
background: var(--color-bg-card, #ffffff);
|
|
38
|
+
border-radius: var(--radius-lg, 0.5rem);
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
font-family: inherit;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Elevated variant (default) - uses shadow */
|
|
44
|
+
.card--elevated {
|
|
45
|
+
box-shadow: var(
|
|
46
|
+
--shadow-md,
|
|
47
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
48
|
+
0 2px 4px -1px rgba(0, 0, 0, 0.06)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Outlined variant - uses border */
|
|
53
|
+
.card--outlined {
|
|
54
|
+
border: 1px solid var(--color-border, #e5e7eb);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Filled variant - uses background color */
|
|
58
|
+
.card--filled {
|
|
59
|
+
background: var(--color-bg-muted, #f3f4f6);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Clickable state */
|
|
63
|
+
.card--clickable {
|
|
64
|
+
width: 100%;
|
|
65
|
+
text-align: left;
|
|
66
|
+
padding: 0;
|
|
67
|
+
border: none;
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
transition:
|
|
70
|
+
transform 0.2s ease,
|
|
71
|
+
box-shadow 0.2s ease;
|
|
72
|
+
min-height: 2.75rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.card--clickable:hover {
|
|
76
|
+
transform: translateY(-2px);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.card--clickable.card--elevated:hover {
|
|
80
|
+
box-shadow: var(
|
|
81
|
+
--shadow-lg,
|
|
82
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
|
83
|
+
0 4px 6px -2px rgba(0, 0, 0, 0.05)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.card--clickable:focus-visible {
|
|
88
|
+
outline: 2px solid var(--color-primary, #3b82f6);
|
|
89
|
+
outline-offset: 2px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.card--clickable:active {
|
|
93
|
+
transform: translateY(0);
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CardVariant } from '../../types/index.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
variant?: CardVariant;
|
|
4
|
+
clickable?: boolean;
|
|
5
|
+
class?: string;
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
declare const Card: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type Card = ReturnType<typeof Card>;
|
|
10
|
+
export default Card;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
children?: import('svelte').Snippet;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let { class: className = '', children }: Props = $props();
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<div class="card__body {className}">
|
|
11
|
+
{#if children}
|
|
12
|
+
{@render children()}
|
|
13
|
+
{/if}
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<style>
|
|
17
|
+
.card__body {
|
|
18
|
+
flex: 1;
|
|
19
|
+
padding: var(--space-lg, 1.25rem);
|
|
20
|
+
font-family: inherit;
|
|
21
|
+
font-size: var(--text-base, 1rem);
|
|
22
|
+
line-height: 1.5;
|
|
23
|
+
color: var(--color-text, var(--gray-12, inherit));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Mobile-first: Adjust padding for smaller screens */
|
|
27
|
+
@media (max-width: 30rem) {
|
|
28
|
+
.card__body {
|
|
29
|
+
padding: var(--space-md, 1rem);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
</style>
|