@aspect-ops/exon-ui 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +793 -43
- package/dist/components/Accordion/Accordion.svelte +79 -0
- package/dist/components/Accordion/Accordion.svelte.d.ts +10 -0
- package/dist/components/Accordion/AccordionItem.svelte +198 -0
- package/dist/components/Accordion/AccordionItem.svelte.d.ts +10 -0
- package/dist/components/Accordion/index.d.ts +2 -0
- package/dist/components/Accordion/index.js +2 -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/Carousel/Carousel.svelte +454 -0
- package/dist/components/Carousel/Carousel.svelte.d.ts +14 -0
- package/dist/components/Carousel/CarouselSlide.svelte +22 -0
- package/dist/components/Carousel/CarouselSlide.svelte.d.ts +7 -0
- package/dist/components/Carousel/index.d.ts +2 -0
- package/dist/components/Carousel/index.js +2 -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/Chip/Chip.svelte +461 -0
- package/dist/components/Chip/Chip.svelte.d.ts +17 -0
- package/dist/components/Chip/ChipGroup.svelte +76 -0
- package/dist/components/Chip/ChipGroup.svelte.d.ts +9 -0
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/Chip/index.js +2 -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/DatePicker/DatePicker.svelte +746 -0
- package/dist/components/DatePicker/DatePicker.svelte.d.ts +19 -0
- package/dist/components/DatePicker/index.d.ts +1 -0
- package/dist/components/DatePicker/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/FileUpload/FileUpload.svelte +484 -0
- package/dist/components/FileUpload/FileUpload.svelte.d.ts +16 -0
- package/dist/components/FileUpload/index.d.ts +1 -0
- package/dist/components/FileUpload/index.js +1 -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/Image/Image.svelte +223 -0
- package/dist/components/Image/Image.svelte.d.ts +19 -0
- package/dist/components/Image/index.d.ts +1 -0
- package/dist/components/Image/index.js +1 -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/OTPInput/OTPInput.svelte +312 -0
- package/dist/components/OTPInput/OTPInput.svelte.d.ts +57 -0
- package/dist/components/OTPInput/index.d.ts +1 -0
- package/dist/components/OTPInput/index.js +1 -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/Rating/Rating.svelte +316 -0
- package/dist/components/Rating/Rating.svelte.d.ts +16 -0
- package/dist/components/Rating/index.d.ts +1 -0
- package/dist/components/Rating/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/SearchInput/SearchInput.svelte +480 -0
- package/dist/components/SearchInput/SearchInput.svelte.d.ts +22 -0
- package/dist/components/SearchInput/index.d.ts +1 -0
- package/dist/components/SearchInput/index.js +1 -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/Slider/Slider.svelte +324 -0
- package/dist/components/Slider/Slider.svelte.d.ts +14 -0
- package/dist/components/Slider/index.d.ts +1 -0
- package/dist/components/Slider/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/Stepper/Stepper.svelte +100 -0
- package/dist/components/Stepper/Stepper.svelte.d.ts +11 -0
- package/dist/components/Stepper/StepperStep.svelte +391 -0
- package/dist/components/Stepper/StepperStep.svelte.d.ts +13 -0
- package/dist/components/Stepper/index.d.ts +2 -0
- package/dist/components/Stepper/index.js +2 -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/TimePicker/TimePicker.svelte +803 -0
- package/dist/components/TimePicker/TimePicker.svelte.d.ts +17 -0
- package/dist/components/TimePicker/index.d.ts +1 -0
- package/dist/components/TimePicker/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 +38 -1
- package/dist/index.js +41 -0
- package/dist/styles/tokens.css +5 -0
- package/dist/types/data-display.d.ts +161 -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 +6 -1
- package/dist/types/input.d.ts +67 -0
- package/dist/types/input.js +2 -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/types/navigation.d.ts +15 -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,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ModalBodyProps } from '../../types/index.js';
|
|
3
|
+
import { Dialog } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
interface Props extends ModalBodyProps {
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { class: className = '', children }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<div class="modal-body {className}">
|
|
13
|
+
<Dialog.Description class="modal-description">
|
|
14
|
+
{@render children?.()}
|
|
15
|
+
</Dialog.Description>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
:global(.modal-body) {
|
|
20
|
+
padding: var(--space-xl, 1.5rem);
|
|
21
|
+
overflow-y: auto;
|
|
22
|
+
flex: 1;
|
|
23
|
+
/* Smooth scrolling on iOS */
|
|
24
|
+
-webkit-overflow-scrolling: touch;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:global(.modal-description) {
|
|
28
|
+
font-size: var(--font-size-base, 1rem);
|
|
29
|
+
line-height: var(--line-height-normal, 1.5);
|
|
30
|
+
color: var(--color-text, #1f2937);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Scrollbar styling */
|
|
34
|
+
:global(.modal-body::-webkit-scrollbar) {
|
|
35
|
+
width: 0.5rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:global(.modal-body::-webkit-scrollbar-track) {
|
|
39
|
+
background: transparent;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:global(.modal-body::-webkit-scrollbar-thumb) {
|
|
43
|
+
background: var(--color-border, #e5e7eb);
|
|
44
|
+
border-radius: var(--radius-full, 9999px);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:global(.modal-body::-webkit-scrollbar-thumb:hover) {
|
|
48
|
+
background: var(--color-text-secondary, #6b7280);
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ModalBodyProps } from '../../types/index.js';
|
|
2
|
+
interface Props extends ModalBodyProps {
|
|
3
|
+
children?: import('svelte').Snippet;
|
|
4
|
+
}
|
|
5
|
+
declare const ModalBody: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type ModalBody = ReturnType<typeof ModalBody>;
|
|
7
|
+
export default ModalBody;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ModalFooterProps } from '../../types/index.js';
|
|
3
|
+
|
|
4
|
+
interface Props extends ModalFooterProps {
|
|
5
|
+
children?: import('svelte').Snippet;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let { class: className = '', children }: Props = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<div class="modal-footer {className}">
|
|
12
|
+
{@render children?.()}
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<style>
|
|
16
|
+
:global(.modal-footer) {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: flex-end;
|
|
20
|
+
padding: var(--space-lg, 1rem) var(--space-xl, 1.5rem);
|
|
21
|
+
border-top: 1px solid var(--color-border, #e5e7eb);
|
|
22
|
+
gap: var(--space-md, 0.75rem);
|
|
23
|
+
flex-shrink: 0;
|
|
24
|
+
flex-wrap: wrap;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Mobile: Stack buttons vertically */
|
|
28
|
+
@media (max-width: 640px) {
|
|
29
|
+
:global(.modal-footer) {
|
|
30
|
+
flex-direction: column-reverse;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:global(.modal-footer > *) {
|
|
34
|
+
width: 100%;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ModalFooterProps } from '../../types/index.js';
|
|
2
|
+
interface Props extends ModalFooterProps {
|
|
3
|
+
children?: import('svelte').Snippet;
|
|
4
|
+
}
|
|
5
|
+
declare const ModalFooter: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type ModalFooter = ReturnType<typeof ModalFooter>;
|
|
7
|
+
export default ModalFooter;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ModalHeaderProps } from '../../types/index.js';
|
|
3
|
+
import { Dialog } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
interface Props extends ModalHeaderProps {
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { class: className = '', children }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<div class="modal-header {className}">
|
|
13
|
+
<Dialog.Title class="modal-title">
|
|
14
|
+
{@render children?.()}
|
|
15
|
+
</Dialog.Title>
|
|
16
|
+
<Dialog.Close class="modal-close" aria-label="Close modal">×</Dialog.Close>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
:global(.modal-header) {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: space-between;
|
|
24
|
+
padding: var(--space-lg, 1rem) var(--space-xl, 1.5rem);
|
|
25
|
+
border-bottom: 1px solid var(--color-border, #e5e7eb);
|
|
26
|
+
gap: var(--space-md, 0.75rem);
|
|
27
|
+
flex-shrink: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:global(.modal-title) {
|
|
31
|
+
font-size: var(--font-size-lg, 1.125rem);
|
|
32
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
33
|
+
color: var(--color-text, #1f2937);
|
|
34
|
+
line-height: var(--line-height-tight, 1.25);
|
|
35
|
+
margin: 0;
|
|
36
|
+
flex: 1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:global(.modal-close) {
|
|
40
|
+
/* F20: Minimum 44x44px touch target */
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
min-width: 2.75rem;
|
|
45
|
+
min-height: 2.75rem;
|
|
46
|
+
width: 2.75rem;
|
|
47
|
+
height: 2.75rem;
|
|
48
|
+
border: none;
|
|
49
|
+
background: transparent;
|
|
50
|
+
color: var(--color-text-secondary, #6b7280);
|
|
51
|
+
font-size: var(--font-size-2xl, 1.5rem);
|
|
52
|
+
line-height: 1;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
border-radius: var(--radius-sm, 0.25rem);
|
|
55
|
+
transition: all 150ms ease;
|
|
56
|
+
flex-shrink: 0;
|
|
57
|
+
padding: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
:global(.modal-close:hover) {
|
|
61
|
+
background: var(--color-bg-secondary, #f3f4f6);
|
|
62
|
+
color: var(--color-text, #1f2937);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
:global(.modal-close:focus-visible) {
|
|
66
|
+
outline: 2px solid var(--color-primary, #3b82f6);
|
|
67
|
+
outline-offset: 2px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:global(.modal-close:active) {
|
|
71
|
+
transform: scale(0.95);
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ModalHeaderProps } from '../../types/index.js';
|
|
2
|
+
interface Props extends ModalHeaderProps {
|
|
3
|
+
children?: import('svelte').Snippet;
|
|
4
|
+
}
|
|
5
|
+
declare const ModalHeader: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type ModalHeader = ReturnType<typeof ModalHeader>;
|
|
7
|
+
export default ModalHeader;
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/**
|
|
6
|
+
* The OTP value (bindable)
|
|
7
|
+
* @default ''
|
|
8
|
+
*/
|
|
9
|
+
value?: string;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Number of OTP digits
|
|
13
|
+
* @default 6
|
|
14
|
+
*/
|
|
15
|
+
length?: number;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Input type validation
|
|
19
|
+
* @default 'numeric'
|
|
20
|
+
*/
|
|
21
|
+
type?: 'numeric' | 'alphanumeric';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Show dots instead of characters
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
masked?: boolean;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Disabled state
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Error state
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
error?: boolean;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Component size
|
|
43
|
+
* @default 'md'
|
|
44
|
+
*/
|
|
45
|
+
size?: 'sm' | 'md' | 'lg';
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Auto-focus first input on mount
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
autoFocus?: boolean;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Additional CSS classes
|
|
55
|
+
*/
|
|
56
|
+
class?: string;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Callback when all digits are entered
|
|
60
|
+
*/
|
|
61
|
+
oncomplete?: (value: string) => void;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Callback on value change
|
|
65
|
+
*/
|
|
66
|
+
onchange?: (value: string) => void;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let {
|
|
70
|
+
value = $bindable(''),
|
|
71
|
+
length = 6,
|
|
72
|
+
type = 'numeric',
|
|
73
|
+
masked = false,
|
|
74
|
+
disabled = false,
|
|
75
|
+
error = false,
|
|
76
|
+
size = 'md',
|
|
77
|
+
autoFocus = false,
|
|
78
|
+
class: className = '',
|
|
79
|
+
oncomplete,
|
|
80
|
+
onchange
|
|
81
|
+
}: Props = $props();
|
|
82
|
+
|
|
83
|
+
// Track individual input elements
|
|
84
|
+
let inputs: (HTMLInputElement | null)[] = $state([]);
|
|
85
|
+
|
|
86
|
+
// Split value into individual characters
|
|
87
|
+
let chars = $derived(value.padEnd(length, ' ').slice(0, length).split(''));
|
|
88
|
+
|
|
89
|
+
onMount(() => {
|
|
90
|
+
if (autoFocus && inputs[0]) {
|
|
91
|
+
inputs[0].focus();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
function handleInput(index: number, e: Event) {
|
|
96
|
+
const input = e.target as HTMLInputElement;
|
|
97
|
+
const char = input.value.slice(-1); // Get last character entered
|
|
98
|
+
|
|
99
|
+
// Validate based on type
|
|
100
|
+
if (type === 'numeric' && char && !/^\d$/.test(char)) {
|
|
101
|
+
input.value = '';
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (type === 'alphanumeric' && char && !/^[a-zA-Z0-9]$/.test(char)) {
|
|
106
|
+
input.value = '';
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Update value
|
|
111
|
+
const newChars = chars.map((c, i) => (i === index ? char : c));
|
|
112
|
+
const newValue = newChars.join('').trim();
|
|
113
|
+
value = newValue;
|
|
114
|
+
|
|
115
|
+
// Call onchange callback
|
|
116
|
+
onchange?.(newValue);
|
|
117
|
+
|
|
118
|
+
// Move to next input if character was entered
|
|
119
|
+
if (char && index < length - 1) {
|
|
120
|
+
inputs[index + 1]?.focus();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check completion
|
|
124
|
+
if (newValue.length === length) {
|
|
125
|
+
oncomplete?.(newValue);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function handleKeydown(index: number, e: KeyboardEvent) {
|
|
130
|
+
const input = e.target as HTMLInputElement;
|
|
131
|
+
|
|
132
|
+
switch (e.key) {
|
|
133
|
+
case 'Backspace':
|
|
134
|
+
// If input is empty, move to previous input
|
|
135
|
+
if (!input.value && index > 0) {
|
|
136
|
+
e.preventDefault();
|
|
137
|
+
inputs[index - 1]?.focus();
|
|
138
|
+
// Clear previous input
|
|
139
|
+
const newChars = chars.map((c, i) => (i === index - 1 ? '' : c));
|
|
140
|
+
value = newChars.join('').trim();
|
|
141
|
+
onchange?.(value);
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
|
|
145
|
+
case 'ArrowLeft':
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
if (index > 0) {
|
|
148
|
+
inputs[index - 1]?.focus();
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
|
|
152
|
+
case 'ArrowRight':
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
if (index < length - 1) {
|
|
155
|
+
inputs[index + 1]?.focus();
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
|
|
159
|
+
case 'ArrowUp':
|
|
160
|
+
case 'ArrowDown':
|
|
161
|
+
// Prevent default to avoid number spinner in numeric inputs
|
|
162
|
+
e.preventDefault();
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function handlePaste(e: ClipboardEvent) {
|
|
168
|
+
e.preventDefault();
|
|
169
|
+
const pastedData = e.clipboardData?.getData('text') || '';
|
|
170
|
+
|
|
171
|
+
// Filter based on type
|
|
172
|
+
let filteredData = pastedData;
|
|
173
|
+
if (type === 'numeric') {
|
|
174
|
+
filteredData = pastedData.replace(/\D/g, '');
|
|
175
|
+
} else if (type === 'alphanumeric') {
|
|
176
|
+
filteredData = pastedData.replace(/[^a-zA-Z0-9]/g, '');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Trim to length and update value
|
|
180
|
+
const newValue = filteredData.slice(0, length);
|
|
181
|
+
value = newValue;
|
|
182
|
+
onchange?.(newValue);
|
|
183
|
+
|
|
184
|
+
// Focus the next empty input or the last input
|
|
185
|
+
const nextEmptyIndex = newValue.length < length ? newValue.length : length - 1;
|
|
186
|
+
setTimeout(() => {
|
|
187
|
+
inputs[nextEmptyIndex]?.focus();
|
|
188
|
+
}, 0);
|
|
189
|
+
|
|
190
|
+
// Check completion
|
|
191
|
+
if (newValue.length === length) {
|
|
192
|
+
oncomplete?.(newValue);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function handleFocus(index: number, e: FocusEvent) {
|
|
197
|
+
const input = e.target as HTMLInputElement;
|
|
198
|
+
// Select content on focus for easy replacement
|
|
199
|
+
input.select();
|
|
200
|
+
}
|
|
201
|
+
</script>
|
|
202
|
+
|
|
203
|
+
<div
|
|
204
|
+
class="otp-input otp-input--{size} {error ? 'otp-input--error' : ''} {disabled
|
|
205
|
+
? 'otp-input--disabled'
|
|
206
|
+
: ''} {className}"
|
|
207
|
+
role="group"
|
|
208
|
+
aria-label="One-time password input"
|
|
209
|
+
>
|
|
210
|
+
{#each Array(length) as _, index (index)}
|
|
211
|
+
<input
|
|
212
|
+
bind:this={inputs[index]}
|
|
213
|
+
class="otp-input__field"
|
|
214
|
+
type={masked ? 'password' : 'text'}
|
|
215
|
+
inputmode={type === 'numeric' ? 'numeric' : 'text'}
|
|
216
|
+
autocomplete="one-time-code"
|
|
217
|
+
maxlength="1"
|
|
218
|
+
value={chars[index]?.trim() || ''}
|
|
219
|
+
aria-label="Digit {index + 1} of {length}"
|
|
220
|
+
aria-invalid={error}
|
|
221
|
+
{disabled}
|
|
222
|
+
oninput={(e) => handleInput(index, e)}
|
|
223
|
+
onkeydown={(e) => handleKeydown(index, e)}
|
|
224
|
+
onpaste={(e) => handlePaste(e)}
|
|
225
|
+
onfocus={(e) => handleFocus(index, e)}
|
|
226
|
+
/>
|
|
227
|
+
{/each}
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
<style>
|
|
231
|
+
.otp-input {
|
|
232
|
+
display: flex;
|
|
233
|
+
gap: var(--space-sm, 0.5rem);
|
|
234
|
+
align-items: center;
|
|
235
|
+
width: 100%;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.otp-input--disabled {
|
|
239
|
+
opacity: 0.5;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.otp-input__field {
|
|
243
|
+
flex: 1;
|
|
244
|
+
min-width: 0;
|
|
245
|
+
min-height: var(--touch-target-min, 44px);
|
|
246
|
+
max-width: 3rem;
|
|
247
|
+
padding: var(--space-sm, 0.5rem);
|
|
248
|
+
border: 1px solid var(--color-border, #e5e7eb);
|
|
249
|
+
border-radius: var(--radius-md, 0.375rem);
|
|
250
|
+
background: var(--color-bg, #ffffff);
|
|
251
|
+
color: var(--color-text, #1f2937);
|
|
252
|
+
font-family: inherit;
|
|
253
|
+
font-size: var(--text-lg, 1.125rem);
|
|
254
|
+
font-weight: var(--font-semibold, 600);
|
|
255
|
+
text-align: center;
|
|
256
|
+
line-height: 1;
|
|
257
|
+
transition:
|
|
258
|
+
border-color var(--transition-fast, 150ms ease),
|
|
259
|
+
box-shadow var(--transition-fast, 150ms ease);
|
|
260
|
+
-webkit-tap-highlight-color: transparent;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.otp-input__field:focus {
|
|
264
|
+
outline: none;
|
|
265
|
+
border-color: var(--color-primary, #3b82f6);
|
|
266
|
+
box-shadow: 0 0 0 3px var(--color-primary-alpha, rgba(59, 130, 246, 0.1));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.otp-input__field:disabled {
|
|
270
|
+
background: var(--color-bg-muted, #f3f4f6);
|
|
271
|
+
cursor: not-allowed;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Size variants */
|
|
275
|
+
.otp-input--sm .otp-input__field {
|
|
276
|
+
min-height: var(--touch-target-min, 44px);
|
|
277
|
+
max-width: 2.5rem;
|
|
278
|
+
padding: var(--space-xs, 0.25rem);
|
|
279
|
+
font-size: var(--text-base, 1rem);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.otp-input--md .otp-input__field {
|
|
283
|
+
min-height: var(--touch-target-min, 44px);
|
|
284
|
+
max-width: 3rem;
|
|
285
|
+
padding: var(--space-sm, 0.5rem);
|
|
286
|
+
font-size: var(--text-lg, 1.125rem);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.otp-input--lg .otp-input__field {
|
|
290
|
+
min-height: 3.25rem;
|
|
291
|
+
max-width: 3.5rem;
|
|
292
|
+
padding: var(--space-md, 1rem);
|
|
293
|
+
font-size: var(--text-xl, 1.25rem);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Error state */
|
|
297
|
+
.otp-input--error .otp-input__field {
|
|
298
|
+
border-color: var(--color-error, #ef4444);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.otp-input--error .otp-input__field:focus {
|
|
302
|
+
border-color: var(--color-error, #ef4444);
|
|
303
|
+
box-shadow: 0 0 0 3px var(--color-error-alpha, rgba(239, 68, 68, 0.1));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* Remove number spinner for numeric inputs */
|
|
307
|
+
.otp-input__field::-webkit-outer-spin-button,
|
|
308
|
+
.otp-input__field::-webkit-inner-spin-button {
|
|
309
|
+
-webkit-appearance: none;
|
|
310
|
+
margin: 0;
|
|
311
|
+
}
|
|
312
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/**
|
|
3
|
+
* The OTP value (bindable)
|
|
4
|
+
* @default ''
|
|
5
|
+
*/
|
|
6
|
+
value?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Number of OTP digits
|
|
9
|
+
* @default 6
|
|
10
|
+
*/
|
|
11
|
+
length?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Input type validation
|
|
14
|
+
* @default 'numeric'
|
|
15
|
+
*/
|
|
16
|
+
type?: 'numeric' | 'alphanumeric';
|
|
17
|
+
/**
|
|
18
|
+
* Show dots instead of characters
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
masked?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Disabled state
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Error state
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
error?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Component size
|
|
34
|
+
* @default 'md'
|
|
35
|
+
*/
|
|
36
|
+
size?: 'sm' | 'md' | 'lg';
|
|
37
|
+
/**
|
|
38
|
+
* Auto-focus first input on mount
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
autoFocus?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Additional CSS classes
|
|
44
|
+
*/
|
|
45
|
+
class?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Callback when all digits are entered
|
|
48
|
+
*/
|
|
49
|
+
oncomplete?: (value: string) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Callback on value change
|
|
52
|
+
*/
|
|
53
|
+
onchange?: (value: string) => void;
|
|
54
|
+
}
|
|
55
|
+
declare const OTPInput: import("svelte").Component<Props, {}, "value">;
|
|
56
|
+
type OTPInput = ReturnType<typeof OTPInput>;
|
|
57
|
+
export default OTPInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as OTPInput } from './OTPInput.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as OTPInput } from './OTPInput.svelte';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { PopoverProps } from '../../types/index.js';
|
|
3
|
+
import { Popover as BitsPopover } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
interface Props extends PopoverProps {
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { class: className = '', children }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<BitsPopover.Root>
|
|
13
|
+
{@render children?.()}
|
|
14
|
+
</BitsPopover.Root>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PopoverProps } from '../../types/index.js';
|
|
2
|
+
interface Props extends PopoverProps {
|
|
3
|
+
children?: import('svelte').Snippet;
|
|
4
|
+
}
|
|
5
|
+
declare const Popover: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type Popover = ReturnType<typeof Popover>;
|
|
7
|
+
export default Popover;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { PopoverContentProps } from '../../types/index.js';
|
|
3
|
+
import { Popover as BitsPopover } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
interface Props extends PopoverContentProps {
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { side = 'bottom', class: className = '', children }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<BitsPopover.Portal>
|
|
13
|
+
<BitsPopover.Content {side} class="popover-content {className}">
|
|
14
|
+
{@render children?.()}
|
|
15
|
+
</BitsPopover.Content>
|
|
16
|
+
</BitsPopover.Portal>
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
/* Popover content */
|
|
20
|
+
:global(.popover-content) {
|
|
21
|
+
/* MUST set font-family explicitly - portal doesn't inherit (F33) */
|
|
22
|
+
font-family: var(--exon-font-sans, var(--font-family, system-ui, -apple-system, sans-serif));
|
|
23
|
+
background: var(--exon-popover-bg, white);
|
|
24
|
+
border: 1px solid var(--exon-color-neutral-200, #e5e7eb);
|
|
25
|
+
border-radius: var(--exon-radius-lg, 0.5rem);
|
|
26
|
+
padding: 1rem;
|
|
27
|
+
box-shadow: var(--exon-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));
|
|
28
|
+
min-width: 12.5rem;
|
|
29
|
+
max-width: 20rem;
|
|
30
|
+
z-index: 150;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Fade-in animation */
|
|
34
|
+
:global(.popover-content[data-state='open']) {
|
|
35
|
+
animation: popover-fade-in 200ms ease-out;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:global(.popover-content[data-state='closed']) {
|
|
39
|
+
animation: popover-fade-out 150ms ease-in;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@keyframes -global-popover-fade-in {
|
|
43
|
+
from {
|
|
44
|
+
opacity: 0;
|
|
45
|
+
transform: scale(0.95);
|
|
46
|
+
}
|
|
47
|
+
to {
|
|
48
|
+
opacity: 1;
|
|
49
|
+
transform: scale(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@keyframes -global-popover-fade-out {
|
|
54
|
+
from {
|
|
55
|
+
opacity: 1;
|
|
56
|
+
transform: scale(1);
|
|
57
|
+
}
|
|
58
|
+
to {
|
|
59
|
+
opacity: 0;
|
|
60
|
+
transform: scale(0.95);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PopoverContentProps } from '../../types/index.js';
|
|
2
|
+
interface Props extends PopoverContentProps {
|
|
3
|
+
children?: import('svelte').Snippet;
|
|
4
|
+
}
|
|
5
|
+
declare const PopoverContent: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type PopoverContent = ReturnType<typeof PopoverContent>;
|
|
7
|
+
export default PopoverContent;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { PopoverTriggerProps } from '../../types/index.js';
|
|
3
|
+
import { Popover as BitsPopover } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
interface Props extends PopoverTriggerProps {
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { class: className = '', children }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<BitsPopover.Trigger class={className}>
|
|
13
|
+
{@render children?.()}
|
|
14
|
+
</BitsPopover.Trigger>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PopoverTriggerProps } from '../../types/index.js';
|
|
2
|
+
interface Props extends PopoverTriggerProps {
|
|
3
|
+
children?: import('svelte').Snippet;
|
|
4
|
+
}
|
|
5
|
+
declare const PopoverTrigger: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type PopoverTrigger = ReturnType<typeof PopoverTrigger>;
|
|
7
|
+
export default PopoverTrigger;
|