@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.
- 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,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,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';
|