@getmicdrop/svelte-components 5.10.1 → 5.10.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/calendar/AboutShow/AboutShow.svelte +172 -172
- package/dist/calendar/Calendar/MiniMonthCalendar.svelte +782 -782
- package/dist/calendar/FAQs/FAQs.svelte +75 -75
- package/dist/calendar/MonthSwitcher/MonthSwitcher.svelte +126 -126
- package/dist/calendar/OrderSummary/OrderSummary.svelte +367 -367
- package/dist/calendar/PublicCard/PublicCard.svelte +146 -146
- package/dist/calendar/ShowCard/ShowCard.svelte +157 -157
- package/dist/calendar/ShowTimeCard/ShowTimeCard.svelte +61 -61
- package/dist/components/Heading.svelte +60 -60
- package/dist/components/Layout/AppShell.svelte +104 -104
- package/dist/components/Layout/ContentSection.svelte +80 -80
- package/dist/components/Layout/Grid.svelte +4 -4
- package/dist/components/Layout/Heading.svelte +81 -81
- package/dist/components/Layout/PageContainer.svelte +69 -69
- package/dist/components/Layout/Responsive.svelte +75 -75
- package/dist/components/Layout/Section.svelte +80 -80
- package/dist/components/Layout/ShowOnDesktop.svelte +37 -37
- package/dist/components/Layout/ShowOnMobile.svelte +37 -37
- package/dist/components/Layout/Sidebar.svelte +108 -108
- package/dist/components/Layout/Stack.svelte +6 -6
- package/dist/components/Layout/Text.svelte +87 -87
- package/dist/components/Layout/TwoColumn.svelte +108 -108
- package/dist/components/Text.svelte +53 -53
- package/dist/constants/validation.js +91 -91
- package/dist/constants/validation.spec.js +64 -64
- package/dist/index.js +51 -51
- package/dist/patterns/data/DataGrid.svelte +45 -45
- package/dist/patterns/data/DataList.svelte +24 -24
- package/dist/patterns/data/DataTable.svelte +36 -36
- package/dist/patterns/forms/FormActions.spec.js +95 -95
- package/dist/patterns/forms/FormActions.stories.svelte +97 -97
- package/dist/patterns/forms/FormActions.svelte +46 -46
- package/dist/patterns/forms/FormGrid.svelte +33 -33
- package/dist/patterns/forms/FormSection.svelte +32 -32
- package/dist/patterns/forms/FormValidationSummary.stories.svelte +83 -83
- package/dist/patterns/forms/FormValidationSummary.svelte +74 -74
- package/dist/patterns/layout/Sidebar.svelte +39 -39
- package/dist/patterns/layout/index.js +29 -29
- package/dist/patterns/navigation/BottomNav.stories.svelte +117 -117
- package/dist/patterns/navigation/BottomNav.svelte +74 -74
- package/dist/patterns/navigation/Header.stories.svelte +77 -77
- package/dist/patterns/navigation/Header.svelte +255 -255
- package/dist/patterns/page/PageHeader.svelte +18 -18
- package/dist/patterns/page/PageLayout.svelte +40 -40
- package/dist/patterns/page/PageLoader.spec.js +57 -57
- package/dist/patterns/page/PageLoader.stories.svelte +137 -137
- package/dist/patterns/page/PageLoader.svelte +24 -24
- package/dist/patterns/page/SectionHeader.svelte +29 -29
- package/dist/presets/badges.js +112 -112
- package/dist/presets/buttons.js +76 -76
- package/dist/presets/index.js +9 -9
- package/dist/primitives/Accordion/Accordion.stories.svelte +75 -75
- package/dist/primitives/Accordion/Accordion.svelte +42 -42
- package/dist/primitives/Accordion/AccordionItem.svelte +95 -95
- package/dist/primitives/Alert/Alert.spec.js +173 -173
- package/dist/primitives/Alert/Alert.stories.svelte +88 -88
- package/dist/primitives/Alert/Alert.svelte +27 -27
- package/dist/primitives/Avatar/Avatar.stories.svelte +94 -94
- package/dist/primitives/Avatar/Avatar.svelte +66 -66
- package/dist/primitives/Badges/Badge.spec.js +144 -144
- package/dist/primitives/Badges/Badge.stories.svelte +86 -86
- package/dist/primitives/Badges/Badge.svelte +99 -99
- package/dist/primitives/BottomSheet/BottomSheet.spec.js +136 -136
- package/dist/primitives/BottomSheet/BottomSheet.stories.svelte +83 -83
- package/dist/primitives/BottomSheet/BottomSheet.svelte +100 -100
- package/dist/primitives/Breadcrumb/Breadcrumb.spec.js +122 -122
- package/dist/primitives/Breadcrumb/Breadcrumb.stories.svelte +23 -23
- package/dist/primitives/Breadcrumb/Breadcrumb.svelte +98 -98
- package/dist/primitives/Button/Button.spec.js +223 -223
- package/dist/primitives/Button/Button.stories.svelte +76 -76
- package/dist/primitives/Button/Button.svelte +283 -283
- package/dist/primitives/Button/ButtonGroup.svelte +50 -50
- package/dist/primitives/Button/ButtonSaveDemo.spec.js +146 -146
- package/dist/primitives/Button/ButtonSaveDemo.svelte +25 -25
- package/dist/primitives/Button/ButtonVariantShowcase.svelte +129 -129
- package/dist/primitives/Card.spec.js +49 -49
- package/dist/primitives/Card.stories.svelte +22 -22
- package/dist/primitives/Card.svelte +28 -28
- package/dist/primitives/Checkbox/Checkbox.stories.svelte +84 -84
- package/dist/primitives/Checkbox/Checkbox.svelte +88 -88
- package/dist/primitives/DarkModeToggle.spec.js +390 -390
- package/dist/primitives/DarkModeToggle.stories.svelte +57 -57
- package/dist/primitives/DarkModeToggle.svelte +136 -136
- package/dist/primitives/Drawer/Drawer.stories.svelte +80 -80
- package/dist/primitives/Drawer/Drawer.svelte +120 -120
- package/dist/primitives/Dropdown/Dropdown.stories.svelte +137 -137
- package/dist/primitives/Dropdown/Dropdown.svelte +170 -170
- package/dist/primitives/Dropdown/DropdownDivider.svelte +9 -9
- package/dist/primitives/Dropdown/DropdownItem.svelte +80 -80
- package/dist/primitives/Helper/Helper.svelte +33 -33
- package/dist/primitives/Icons/ArrowLeft.svelte +8 -8
- package/dist/primitives/Icons/ArrowRight.svelte +8 -8
- package/dist/primitives/Icons/Availability.svelte +14 -14
- package/dist/primitives/Icons/Back.svelte +14 -14
- package/dist/primitives/Icons/CheckCircle.svelte +6 -6
- package/dist/primitives/Icons/CheckCircleOutline.svelte +15 -15
- package/dist/primitives/Icons/ChevronLeft.svelte +4 -4
- package/dist/primitives/Icons/ChevronRight.svelte +4 -4
- package/dist/primitives/Icons/Copy.svelte +15 -15
- package/dist/primitives/Icons/Cross.svelte +5 -5
- package/dist/primitives/Icons/DownArrow.svelte +8 -8
- package/dist/primitives/Icons/ErrorCircle.svelte +6 -6
- package/dist/primitives/Icons/FacebookIcon.svelte +2 -2
- package/dist/primitives/Icons/Home.svelte +15 -15
- package/dist/primitives/Icons/Icon.spec.js +169 -169
- package/dist/primitives/Icons/Icon.stories.svelte +100 -100
- package/dist/primitives/Icons/Icon.svelte +52 -52
- package/dist/primitives/Icons/IconGallery.stories.svelte +235 -235
- package/dist/primitives/Icons/Info.svelte +7 -7
- package/dist/primitives/Icons/InstagramIcon.svelte +4 -4
- package/dist/primitives/Icons/LogoInstagram.svelte +2 -2
- package/dist/primitives/Icons/Message.svelte +15 -15
- package/dist/primitives/Icons/MoonIcon.svelte +5 -5
- package/dist/primitives/Icons/More.svelte +21 -21
- package/dist/primitives/Icons/MoreHori.spec.js +61 -61
- package/dist/primitives/Icons/MoreHori.svelte +22 -22
- package/dist/primitives/Icons/Notification.svelte +14 -14
- package/dist/primitives/Icons/Payment.svelte +14 -14
- package/dist/primitives/Icons/Profile.svelte +21 -21
- package/dist/primitives/Icons/Reload.svelte +29 -29
- package/dist/primitives/Icons/Shows.svelte +21 -21
- package/dist/primitives/Icons/Signout.svelte +21 -21
- package/dist/primitives/Icons/SunIcon.svelte +8 -8
- package/dist/primitives/Icons/TiktokIcon.svelte +2 -2
- package/dist/primitives/Icons/TwitterIcon.svelte +2 -2
- package/dist/primitives/Icons/WarningIcon.spec.js +18 -18
- package/dist/primitives/Icons/WarningIcon.svelte +5 -5
- package/dist/primitives/Input/Input.spec.js +573 -573
- package/dist/primitives/Input/Input.stories.svelte +139 -139
- package/dist/primitives/Input/Input.svelte +423 -423
- package/dist/primitives/Input/Select.spec.js +218 -218
- package/dist/primitives/Input/Select.stories.svelte +112 -112
- package/dist/primitives/Input/Select.svelte +252 -252
- package/dist/primitives/Input/Textarea.stories.svelte +137 -137
- package/dist/primitives/Input/Textarea.svelte +105 -105
- package/dist/primitives/Label/Label.svelte +37 -37
- package/dist/primitives/Modal/Modal.spec.js +99 -99
- package/dist/primitives/Modal/Modal.stories.svelte +86 -86
- package/dist/primitives/Modal/Modal.svelte +157 -157
- package/dist/primitives/Pagination/Pagination.stories.svelte +76 -76
- package/dist/primitives/Pagination/Pagination.svelte +261 -261
- package/dist/primitives/Radio/Radio.stories.svelte +80 -80
- package/dist/primitives/Radio/Radio.svelte +67 -67
- package/dist/primitives/Skeleton/CardPlaceholder.svelte +87 -87
- package/dist/primitives/Skeleton/ImagePlaceholder.svelte +59 -59
- package/dist/primitives/Skeleton/ListPlaceholder.svelte +76 -76
- package/dist/primitives/Skeleton/Skeleton.stories.svelte +151 -151
- package/dist/primitives/Skeleton/Skeleton.svelte +26 -26
- package/dist/primitives/Spinner/Spinner.spec.js +71 -71
- package/dist/primitives/Spinner/Spinner.stories.svelte +29 -29
- package/dist/primitives/Spinner/Spinner.svelte +20 -20
- package/dist/primitives/Tabs/TabItem.svelte +49 -49
- package/dist/primitives/Tabs/Tabs.stories.svelte +112 -112
- package/dist/primitives/Tabs/Tabs.svelte +137 -137
- package/dist/primitives/Toggle.spec.js +146 -146
- package/dist/primitives/Toggle.stories.svelte +92 -92
- package/dist/primitives/Toggle.svelte +131 -131
- package/dist/primitives/Tooltip/Tooltip.svelte +83 -83
- package/dist/primitives/Typography/Typography.svelte +53 -53
- package/dist/primitives/ValidationError.spec.js +103 -103
- package/dist/primitives/ValidationError.stories.svelte +69 -69
- package/dist/primitives/ValidationError.svelte +29 -29
- package/dist/primitives/index.js +92 -92
- package/dist/recipes/CropImage/CropImage.spec.js +208 -208
- package/dist/recipes/CropImage/CropImage.stories.svelte +104 -104
- package/dist/recipes/CropImage/CropImage.svelte +219 -219
- package/dist/recipes/ImageUploader/ImageUploader.stories.svelte +125 -125
- package/dist/recipes/ImageUploader/ImageUploader.svelte +970 -970
- package/dist/recipes/Toaster/Toaster.stories.svelte +62 -62
- package/dist/recipes/feedback/EmptyState/EmptyState.svelte +1 -1
- package/dist/recipes/feedback/ErrorDisplay.spec.js +69 -69
- package/dist/recipes/feedback/ErrorDisplay.stories.svelte +101 -101
- package/dist/recipes/feedback/ErrorDisplay.svelte +1 -1
- package/dist/recipes/feedback/StatusIndicator/StatusIndicator.spec.js +133 -133
- package/dist/recipes/feedback/StatusIndicator/StatusIndicator.svelte +157 -157
- package/dist/recipes/fields/CheckboxField.svelte +85 -85
- package/dist/recipes/fields/FormField.svelte +58 -58
- package/dist/recipes/fields/RadioGroup.svelte +95 -95
- package/dist/recipes/fields/SelectField.svelte +80 -80
- package/dist/recipes/fields/TextareaField.svelte +97 -97
- package/dist/recipes/fields/ToggleField.svelte +60 -60
- package/dist/recipes/fields/index.js +7 -7
- package/dist/recipes/inputs/MultiSelect.spec.js +260 -260
- package/dist/recipes/inputs/MultiSelect.stories.svelte +133 -133
- package/dist/recipes/inputs/MultiSelect.svelte +283 -283
- package/dist/recipes/inputs/OTPInput.spec.js +251 -251
- package/dist/recipes/inputs/OTPInput.stories.svelte +162 -162
- package/dist/recipes/inputs/OTPInput.svelte +117 -117
- package/dist/recipes/inputs/PasswordInput.svelte +22 -22
- package/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte +131 -117
- package/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte.d.ts.map +1 -1
- package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.stories.svelte +123 -123
- package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.svelte +344 -344
- package/dist/recipes/inputs/Search.svelte +102 -102
- package/dist/recipes/inputs/SelectDropdown.svelte +171 -171
- package/dist/recipes/modals/AlertModal.svelte +130 -130
- package/dist/recipes/modals/ConfirmationModal.spec.js +206 -206
- package/dist/recipes/modals/ConfirmationModal.stories.svelte +119 -119
- package/dist/recipes/modals/ConfirmationModal.svelte +152 -152
- package/dist/recipes/modals/InputModal.svelte +182 -182
- package/dist/recipes/modals/ModalStateManager.spec.js +100 -100
- package/dist/recipes/modals/ModalStateManager.svelte +77 -77
- package/dist/recipes/modals/ModalTestWrapper.svelte +65 -65
- package/dist/recipes/modals/StatusModal.svelte +206 -206
- package/dist/services/EventService.js +75 -75
- package/dist/services/EventService.spec.js +217 -217
- package/dist/services/ShowService.spec.js +345 -345
- package/dist/stores/toaster.js +13 -13
- package/dist/stories/ButtonAuditReview.stories.svelte +14 -14
- package/dist/stories/ButtonAuditReview.svelte +427 -427
- package/dist/stories/PatternsGallery.stories.svelte +19 -19
- package/dist/stories/PatternsGallery.svelte +206 -206
- package/dist/stories/PrimitivesGallery.stories.svelte +19 -19
- package/dist/stories/PrimitivesGallery.svelte +752 -752
- package/dist/stories/RecipesGallery.stories.svelte +19 -19
- package/dist/stories/RecipesGallery.svelte +471 -471
- package/dist/stories/button-audit-manifest.json +11186 -11186
- package/dist/tailwind/preset.cjs +82 -82
- package/dist/telemetry.js +405 -405
- package/dist/telemetry.spec.js +1169 -1169
- package/dist/tokens/tokens.css +87 -87
- package/dist/tokens/typography-base.css +163 -163
- package/dist/tokens/utilities.css +353 -353
- package/dist/utils/apiConfig.spec.js +219 -219
- package/dist/utils/transitions.js +4 -4
- package/dist/utils/utils.js +693 -693
- package/package.json +297 -297
|
@@ -1,157 +1,157 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
/**
|
|
3
|
-
* Modal Component - Flowbite Native
|
|
4
|
-
* Migrated to Svelte 5 runes
|
|
5
|
-
*/
|
|
6
|
-
import { onDestroy } from "svelte";
|
|
7
|
-
import { fade, fly } from "svelte/transition";
|
|
8
|
-
import { cubicOut } from "svelte/easing";
|
|
9
|
-
import { portal } from "../../utils/portal.js";
|
|
10
|
-
|
|
11
|
-
/** @type {{
|
|
12
|
-
show?: boolean,
|
|
13
|
-
isProcessing?: boolean,
|
|
14
|
-
isSuccess?: boolean,
|
|
15
|
-
size?: 'default' | 'small' | 'large' | 'xlarge',
|
|
16
|
-
persistent?: boolean,
|
|
17
|
-
oncancel?: () => void,
|
|
18
|
-
header?: import('svelte').Snippet,
|
|
19
|
-
body?: import('svelte').Snippet,
|
|
20
|
-
footer?: import('svelte').Snippet,
|
|
21
|
-
class?: string,
|
|
22
|
-
}} */
|
|
23
|
-
let {
|
|
24
|
-
show = $bindable(false),
|
|
25
|
-
isProcessing = false,
|
|
26
|
-
isSuccess = false,
|
|
27
|
-
size = "default",
|
|
28
|
-
persistent = false,
|
|
29
|
-
oncancel,
|
|
30
|
-
header,
|
|
31
|
-
body,
|
|
32
|
-
footer,
|
|
33
|
-
class: _className,
|
|
34
|
-
...restProps
|
|
35
|
-
} = $props();
|
|
36
|
-
|
|
37
|
-
// Store scroll position for iOS scroll lock
|
|
38
|
-
let scrollY = $state(0);
|
|
39
|
-
|
|
40
|
-
// Handle escape key
|
|
41
|
-
function handleKeydown(event) {
|
|
42
|
-
if (event.key === "Escape" && show && !persistent) {
|
|
43
|
-
resetModal();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const resetModal = () => {
|
|
48
|
-
oncancel?.();
|
|
49
|
-
show = false;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// Size classes for desktop modal (Tailwind scale)
|
|
53
|
-
const sizeClasses = {
|
|
54
|
-
default: "max-w-md",
|
|
55
|
-
small: "max-w-sm",
|
|
56
|
-
large: "max-w-xl",
|
|
57
|
-
xlarge: "max-w-2xl"
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
let modalSizeClass = $derived(sizeClasses[size] || sizeClasses.default);
|
|
61
|
-
|
|
62
|
-
// iOS-compatible scroll lock using position:fixed approach
|
|
63
|
-
$effect(() => {
|
|
64
|
-
if (typeof document !== "undefined") {
|
|
65
|
-
if (show) {
|
|
66
|
-
scrollY = window.scrollY;
|
|
67
|
-
document.body.style.position = "fixed";
|
|
68
|
-
document.body.style.top = `-${scrollY}px`;
|
|
69
|
-
document.body.style.left = "0";
|
|
70
|
-
document.body.style.right = "0";
|
|
71
|
-
document.body.style.overflow = "hidden";
|
|
72
|
-
} else {
|
|
73
|
-
document.body.style.position = "";
|
|
74
|
-
document.body.style.top = "";
|
|
75
|
-
document.body.style.left = "";
|
|
76
|
-
document.body.style.right = "";
|
|
77
|
-
document.body.style.overflow = "";
|
|
78
|
-
window.scrollTo(0, scrollY);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
onDestroy(() => {
|
|
84
|
-
if (typeof document !== "undefined") {
|
|
85
|
-
document.body.style.position = "";
|
|
86
|
-
document.body.style.top = "";
|
|
87
|
-
document.body.style.left = "";
|
|
88
|
-
document.body.style.right = "";
|
|
89
|
-
document.body.style.overflow = "";
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
</script>
|
|
93
|
-
|
|
94
|
-
<svelte:window onkeydown={handleKeydown} />
|
|
95
|
-
|
|
96
|
-
{#if show}
|
|
97
|
-
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
98
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
99
|
-
<div
|
|
100
|
-
class="fixed inset-0 flex bg-black/50 z-50 items-end justify-center md:items-center md:p-4 touch-none overscroll-none"
|
|
101
|
-
onmousedown={(e) => {
|
|
102
|
-
// Only track direct clicks on backdrop, not drags that end on backdrop
|
|
103
|
-
if (e.target === e.currentTarget && !persistent) {
|
|
104
|
-
e.currentTarget.dataset.clickStartedOnBackdrop = 'true';
|
|
105
|
-
}
|
|
106
|
-
}}
|
|
107
|
-
onmouseup={(e) => {
|
|
108
|
-
// Only close if both mousedown and mouseup were on the backdrop
|
|
109
|
-
if (e.target === e.currentTarget && e.currentTarget.dataset.clickStartedOnBackdrop === 'true' && !persistent) {
|
|
110
|
-
resetModal();
|
|
111
|
-
}
|
|
112
|
-
delete e.currentTarget.dataset.clickStartedOnBackdrop;
|
|
113
|
-
}}
|
|
114
|
-
transition:fade={{ duration: 300 }}
|
|
115
|
-
role="dialog"
|
|
116
|
-
aria-modal="true"
|
|
117
|
-
use:portal
|
|
118
|
-
{...restProps}
|
|
119
|
-
>
|
|
120
|
-
<!-- Mobile: Bottom sheet -->
|
|
121
|
-
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
122
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
123
|
-
<div
|
|
124
|
-
class="md:hidden bg-white dark:bg-gray-800 rounded-t-3xl w-full max-h-[90vh] max-h-[90dvh] overflow-hidden flex flex-col shadow-[0_-10px_40px_rgba(0,0,0,0.15)] touch-pan-y overscroll-contain"
|
|
125
|
-
onclick={(e) => e.stopPropagation()}
|
|
126
|
-
transition:fly={{ y: 300, duration: 300, easing: cubicOut }}
|
|
127
|
-
>
|
|
128
|
-
<!-- Handle bar -->
|
|
129
|
-
<div class="flex justify-center pt-3 pb-1 shrink-0">
|
|
130
|
-
<div class="w-10 h-1 bg-gray-300 dark:bg-gray-600 rounded-xs"></div>
|
|
131
|
-
</div>
|
|
132
|
-
|
|
133
|
-
<div class="p-6 pb-[calc(5rem+env(safe-area-inset-bottom,0px))] overflow-y-auto flex-1">
|
|
134
|
-
{#if header}{@render header()}{/if}
|
|
135
|
-
{#if body}{@render body()}{/if}
|
|
136
|
-
<div class="w-full flex flex-col gap-3 mt-6 empty:hidden empty:mt-0">
|
|
137
|
-
{#if footer}{@render footer()}{/if}
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
</div>
|
|
141
|
-
|
|
142
|
-
<!-- Desktop: Centered modal -->
|
|
143
|
-
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
144
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
145
|
-
<div
|
|
146
|
-
class="hidden md:block bg-white dark:bg-gray-800 p-6 rounded-lg {modalSizeClass} w-full max-h-[calc(100vh-4rem)] overflow-y-auto shadow-2xl"
|
|
147
|
-
onclick={(e) => e.stopPropagation()}
|
|
148
|
-
transition:fly={{ y: 20, duration: 200 }}
|
|
149
|
-
>
|
|
150
|
-
{#if header}{@render header()}{/if}
|
|
151
|
-
{#if body}{@render body()}{/if}
|
|
152
|
-
<div class="w-full flex flex-col md:flex-row md:justify-end gap-3 mt-6 empty:hidden empty:mt-0">
|
|
153
|
-
{#if footer}{@render footer()}{/if}
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
{/if}
|
|
1
|
+
<script>
|
|
2
|
+
/**
|
|
3
|
+
* Modal Component - Flowbite Native
|
|
4
|
+
* Migrated to Svelte 5 runes
|
|
5
|
+
*/
|
|
6
|
+
import { onDestroy } from "svelte";
|
|
7
|
+
import { fade, fly } from "svelte/transition";
|
|
8
|
+
import { cubicOut } from "svelte/easing";
|
|
9
|
+
import { portal } from "../../utils/portal.js";
|
|
10
|
+
|
|
11
|
+
/** @type {{
|
|
12
|
+
show?: boolean,
|
|
13
|
+
isProcessing?: boolean,
|
|
14
|
+
isSuccess?: boolean,
|
|
15
|
+
size?: 'default' | 'small' | 'large' | 'xlarge',
|
|
16
|
+
persistent?: boolean,
|
|
17
|
+
oncancel?: () => void,
|
|
18
|
+
header?: import('svelte').Snippet,
|
|
19
|
+
body?: import('svelte').Snippet,
|
|
20
|
+
footer?: import('svelte').Snippet,
|
|
21
|
+
class?: string,
|
|
22
|
+
}} */
|
|
23
|
+
let {
|
|
24
|
+
show = $bindable(false),
|
|
25
|
+
isProcessing = false,
|
|
26
|
+
isSuccess = false,
|
|
27
|
+
size = "default",
|
|
28
|
+
persistent = false,
|
|
29
|
+
oncancel,
|
|
30
|
+
header,
|
|
31
|
+
body,
|
|
32
|
+
footer,
|
|
33
|
+
class: _className,
|
|
34
|
+
...restProps
|
|
35
|
+
} = $props();
|
|
36
|
+
|
|
37
|
+
// Store scroll position for iOS scroll lock
|
|
38
|
+
let scrollY = $state(0);
|
|
39
|
+
|
|
40
|
+
// Handle escape key
|
|
41
|
+
function handleKeydown(event) {
|
|
42
|
+
if (event.key === "Escape" && show && !persistent) {
|
|
43
|
+
resetModal();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const resetModal = () => {
|
|
48
|
+
oncancel?.();
|
|
49
|
+
show = false;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Size classes for desktop modal (Tailwind scale)
|
|
53
|
+
const sizeClasses = {
|
|
54
|
+
default: "max-w-md",
|
|
55
|
+
small: "max-w-sm",
|
|
56
|
+
large: "max-w-xl",
|
|
57
|
+
xlarge: "max-w-2xl"
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
let modalSizeClass = $derived(sizeClasses[size] || sizeClasses.default);
|
|
61
|
+
|
|
62
|
+
// iOS-compatible scroll lock using position:fixed approach
|
|
63
|
+
$effect(() => {
|
|
64
|
+
if (typeof document !== "undefined") {
|
|
65
|
+
if (show) {
|
|
66
|
+
scrollY = window.scrollY;
|
|
67
|
+
document.body.style.position = "fixed";
|
|
68
|
+
document.body.style.top = `-${scrollY}px`;
|
|
69
|
+
document.body.style.left = "0";
|
|
70
|
+
document.body.style.right = "0";
|
|
71
|
+
document.body.style.overflow = "hidden";
|
|
72
|
+
} else {
|
|
73
|
+
document.body.style.position = "";
|
|
74
|
+
document.body.style.top = "";
|
|
75
|
+
document.body.style.left = "";
|
|
76
|
+
document.body.style.right = "";
|
|
77
|
+
document.body.style.overflow = "";
|
|
78
|
+
window.scrollTo(0, scrollY);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
onDestroy(() => {
|
|
84
|
+
if (typeof document !== "undefined") {
|
|
85
|
+
document.body.style.position = "";
|
|
86
|
+
document.body.style.top = "";
|
|
87
|
+
document.body.style.left = "";
|
|
88
|
+
document.body.style.right = "";
|
|
89
|
+
document.body.style.overflow = "";
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<svelte:window onkeydown={handleKeydown} />
|
|
95
|
+
|
|
96
|
+
{#if show}
|
|
97
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
98
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
99
|
+
<div
|
|
100
|
+
class="fixed inset-0 flex bg-black/50 z-50 items-end justify-center md:items-center md:p-4 touch-none overscroll-none"
|
|
101
|
+
onmousedown={(e) => {
|
|
102
|
+
// Only track direct clicks on backdrop, not drags that end on backdrop
|
|
103
|
+
if (e.target === e.currentTarget && !persistent) {
|
|
104
|
+
e.currentTarget.dataset.clickStartedOnBackdrop = 'true';
|
|
105
|
+
}
|
|
106
|
+
}}
|
|
107
|
+
onmouseup={(e) => {
|
|
108
|
+
// Only close if both mousedown and mouseup were on the backdrop
|
|
109
|
+
if (e.target === e.currentTarget && e.currentTarget.dataset.clickStartedOnBackdrop === 'true' && !persistent) {
|
|
110
|
+
resetModal();
|
|
111
|
+
}
|
|
112
|
+
delete e.currentTarget.dataset.clickStartedOnBackdrop;
|
|
113
|
+
}}
|
|
114
|
+
transition:fade={{ duration: 300 }}
|
|
115
|
+
role="dialog"
|
|
116
|
+
aria-modal="true"
|
|
117
|
+
use:portal
|
|
118
|
+
{...restProps}
|
|
119
|
+
>
|
|
120
|
+
<!-- Mobile: Bottom sheet -->
|
|
121
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
122
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
123
|
+
<div
|
|
124
|
+
class="md:hidden bg-white dark:bg-gray-800 rounded-t-3xl w-full max-h-[90vh] max-h-[90dvh] overflow-hidden flex flex-col shadow-[0_-10px_40px_rgba(0,0,0,0.15)] touch-pan-y overscroll-contain"
|
|
125
|
+
onclick={(e) => e.stopPropagation()}
|
|
126
|
+
transition:fly={{ y: 300, duration: 300, easing: cubicOut }}
|
|
127
|
+
>
|
|
128
|
+
<!-- Handle bar -->
|
|
129
|
+
<div class="flex justify-center pt-3 pb-1 shrink-0">
|
|
130
|
+
<div class="w-10 h-1 bg-gray-300 dark:bg-gray-600 rounded-xs"></div>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<div class="p-6 pb-[calc(5rem+env(safe-area-inset-bottom,0px))] overflow-y-auto flex-1">
|
|
134
|
+
{#if header}{@render header()}{/if}
|
|
135
|
+
{#if body}{@render body()}{/if}
|
|
136
|
+
<div class="w-full flex flex-col gap-3 mt-6 empty:hidden empty:mt-0">
|
|
137
|
+
{#if footer}{@render footer()}{/if}
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<!-- Desktop: Centered modal -->
|
|
143
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
144
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
145
|
+
<div
|
|
146
|
+
class="hidden md:block bg-white dark:bg-gray-800 p-6 rounded-lg {modalSizeClass} w-full max-h-[calc(100vh-4rem)] overflow-y-auto shadow-2xl"
|
|
147
|
+
onclick={(e) => e.stopPropagation()}
|
|
148
|
+
transition:fly={{ y: 20, duration: 200 }}
|
|
149
|
+
>
|
|
150
|
+
{#if header}{@render header()}{/if}
|
|
151
|
+
{#if body}{@render body()}{/if}
|
|
152
|
+
<div class="w-full flex flex-col md:flex-row md:justify-end gap-3 mt-6 empty:hidden empty:mt-0">
|
|
153
|
+
{#if footer}{@render footer()}{/if}
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
{/if}
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
<script module>
|
|
2
|
-
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
-
import Pagination from './Pagination.svelte';
|
|
4
|
-
|
|
5
|
-
const { Story } = defineMeta({
|
|
6
|
-
title: 'Primitives/Pagination',
|
|
7
|
-
component: Pagination,
|
|
8
|
-
tags: ['autodocs'],
|
|
9
|
-
argTypes: {
|
|
10
|
-
totalPages: { control: 'number' },
|
|
11
|
-
currentPage: { control: 'number' },
|
|
12
|
-
},
|
|
13
|
-
parameters: {
|
|
14
|
-
docs: {
|
|
15
|
-
description: {
|
|
16
|
-
component: 'Page navigation control for paginated data.',
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
let page1 = $state(1);
|
|
23
|
-
let page2 = $state(5);
|
|
24
|
-
let page3 = $state(1);
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<Story name="Default">
|
|
28
|
-
{#snippet template()}
|
|
29
|
-
<div>
|
|
30
|
-
<Pagination totalPages={10} bind:currentPage={page1} />
|
|
31
|
-
<p class="text-sm text-gray-500 mt-4">Current page: {page1}</p>
|
|
32
|
-
</div>
|
|
33
|
-
{/snippet}
|
|
34
|
-
</Story>
|
|
35
|
-
|
|
36
|
-
<Story name="Middle Page">
|
|
37
|
-
{#snippet template()}
|
|
38
|
-
<div>
|
|
39
|
-
<Pagination totalPages={10} bind:currentPage={page2} />
|
|
40
|
-
<p class="text-sm text-gray-500 mt-4">Current page: {page2}</p>
|
|
41
|
-
</div>
|
|
42
|
-
{/snippet}
|
|
43
|
-
</Story>
|
|
44
|
-
|
|
45
|
-
<Story name="Few Pages">
|
|
46
|
-
{#snippet template()}
|
|
47
|
-
<div>
|
|
48
|
-
<Pagination totalPages={3} bind:currentPage={page3} />
|
|
49
|
-
<p class="text-sm text-gray-500 mt-4">Current page: {page3}</p>
|
|
50
|
-
</div>
|
|
51
|
-
{/snippet}
|
|
52
|
-
</Story>
|
|
53
|
-
|
|
54
|
-
<Story name="Many Pages">
|
|
55
|
-
{#snippet template()}
|
|
56
|
-
<Pagination totalPages={100} currentPage={50} />
|
|
57
|
-
{/snippet}
|
|
58
|
-
</Story>
|
|
59
|
-
|
|
60
|
-
<Story name="In Context">
|
|
61
|
-
{#snippet template()}
|
|
62
|
-
<div class="border rounded-lg p-4">
|
|
63
|
-
<h3 class="font-medium mb-4">Search Results</h3>
|
|
64
|
-
<ul class="space-y-2 mb-4">
|
|
65
|
-
{#each [1, 2, 3, 4, 5] as i}
|
|
66
|
-
<li class="p-3 border rounded hover:bg-gray-50">
|
|
67
|
-
Result item {i}
|
|
68
|
-
</li>
|
|
69
|
-
{/each}
|
|
70
|
-
</ul>
|
|
71
|
-
<div class="border-t pt-4">
|
|
72
|
-
<Pagination totalPages={20} bind:currentPage={page1} />
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
{/snippet}
|
|
76
|
-
</Story>
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import Pagination from './Pagination.svelte';
|
|
4
|
+
|
|
5
|
+
const { Story } = defineMeta({
|
|
6
|
+
title: 'Primitives/Pagination',
|
|
7
|
+
component: Pagination,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
argTypes: {
|
|
10
|
+
totalPages: { control: 'number' },
|
|
11
|
+
currentPage: { control: 'number' },
|
|
12
|
+
},
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component: 'Page navigation control for paginated data.',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
let page1 = $state(1);
|
|
23
|
+
let page2 = $state(5);
|
|
24
|
+
let page3 = $state(1);
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<Story name="Default">
|
|
28
|
+
{#snippet template()}
|
|
29
|
+
<div>
|
|
30
|
+
<Pagination totalPages={10} bind:currentPage={page1} />
|
|
31
|
+
<p class="text-sm text-gray-500 mt-4">Current page: {page1}</p>
|
|
32
|
+
</div>
|
|
33
|
+
{/snippet}
|
|
34
|
+
</Story>
|
|
35
|
+
|
|
36
|
+
<Story name="Middle Page">
|
|
37
|
+
{#snippet template()}
|
|
38
|
+
<div>
|
|
39
|
+
<Pagination totalPages={10} bind:currentPage={page2} />
|
|
40
|
+
<p class="text-sm text-gray-500 mt-4">Current page: {page2}</p>
|
|
41
|
+
</div>
|
|
42
|
+
{/snippet}
|
|
43
|
+
</Story>
|
|
44
|
+
|
|
45
|
+
<Story name="Few Pages">
|
|
46
|
+
{#snippet template()}
|
|
47
|
+
<div>
|
|
48
|
+
<Pagination totalPages={3} bind:currentPage={page3} />
|
|
49
|
+
<p class="text-sm text-gray-500 mt-4">Current page: {page3}</p>
|
|
50
|
+
</div>
|
|
51
|
+
{/snippet}
|
|
52
|
+
</Story>
|
|
53
|
+
|
|
54
|
+
<Story name="Many Pages">
|
|
55
|
+
{#snippet template()}
|
|
56
|
+
<Pagination totalPages={100} currentPage={50} />
|
|
57
|
+
{/snippet}
|
|
58
|
+
</Story>
|
|
59
|
+
|
|
60
|
+
<Story name="In Context">
|
|
61
|
+
{#snippet template()}
|
|
62
|
+
<div class="border rounded-lg p-4">
|
|
63
|
+
<h3 class="font-medium mb-4">Search Results</h3>
|
|
64
|
+
<ul class="space-y-2 mb-4">
|
|
65
|
+
{#each [1, 2, 3, 4, 5] as i}
|
|
66
|
+
<li class="p-3 border rounded hover:bg-gray-50">
|
|
67
|
+
Result item {i}
|
|
68
|
+
</li>
|
|
69
|
+
{/each}
|
|
70
|
+
</ul>
|
|
71
|
+
<div class="border-t pt-4">
|
|
72
|
+
<Pagination totalPages={20} bind:currentPage={page1} />
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
{/snippet}
|
|
76
|
+
</Story>
|