@getmicdrop/svelte-components 5.10.3 → 5.12.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/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.spec.js +1 -1
- 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/datetime/__tests__/format.test.js +1 -1
- package/dist/datetime/__tests__/parse.test.js +1 -1
- package/dist/datetime/__tests__/timezone.test.js +1 -1
- package/dist/datetime/parse.js +1 -1
- package/dist/forms/createFormStore.svelte.js +0 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -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 +123 -122
- package/dist/primitives/Breadcrumb/Breadcrumb.stories.svelte +23 -23
- package/dist/primitives/Breadcrumb/Breadcrumb.svelte +99 -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 +314 -283
- package/dist/primitives/Button/Button.svelte.d.ts +2 -0
- package/dist/primitives/Button/Button.svelte.d.ts.map +1 -1
- 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 +174 -157
- package/dist/primitives/Modal/Modal.svelte.d.ts +2 -0
- package/dist/primitives/Modal/Modal.svelte.d.ts.map +1 -1
- 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 +141 -131
- package/dist/primitives/Toggle.svelte.d.ts +2 -0
- package/dist/primitives/Toggle.svelte.d.ts.map +1 -1
- 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 -131
- 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 +162 -152
- package/dist/recipes/modals/ConfirmationModal.svelte.d.ts +2 -0
- package/dist/recipes/modals/ConfirmationModal.svelte.d.ts.map +1 -1
- 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/haptic.d.ts +41 -0
- package/dist/utils/haptic.d.ts.map +1 -0
- package/dist/utils/haptic.js +115 -0
- package/dist/utils/transitions.js +4 -4
- package/dist/utils/utils.js +693 -693
- package/package.json +297 -297
|
@@ -1,471 +1,471 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
// ============================================================================
|
|
3
|
-
// RECIPES VISUAL GALLERY
|
|
4
|
-
// Displays ALL recipe components (Layer 2) - Domain-agnostic compositions
|
|
5
|
-
// ============================================================================
|
|
6
|
-
|
|
7
|
-
// Feedback
|
|
8
|
-
import EmptyState from '../recipes/feedback/EmptyState/EmptyState.svelte';
|
|
9
|
-
import ErrorDisplay from '../recipes/feedback/ErrorDisplay.svelte';
|
|
10
|
-
import StatusIndicator from '../recipes/feedback/StatusIndicator/StatusIndicator.svelte';
|
|
11
|
-
|
|
12
|
-
// Inputs
|
|
13
|
-
import MultiSelect from '../recipes/inputs/MultiSelect.svelte';
|
|
14
|
-
import OTPInput from '../recipes/inputs/OTPInput.svelte';
|
|
15
|
-
import PasswordInput from '../recipes/inputs/PasswordInput.svelte';
|
|
16
|
-
import PasswordStrengthIndicator from '../recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte';
|
|
17
|
-
import Search from '../recipes/inputs/Search.svelte';
|
|
18
|
-
import SelectDropdown from '../recipes/inputs/SelectDropdown.svelte';
|
|
19
|
-
|
|
20
|
-
// Modals
|
|
21
|
-
import AlertModal from '../recipes/modals/AlertModal.svelte';
|
|
22
|
-
import ConfirmationModal from '../recipes/modals/ConfirmationModal.svelte';
|
|
23
|
-
import InputModal from '../recipes/modals/InputModal.svelte';
|
|
24
|
-
import StatusModal from '../recipes/modals/StatusModal.svelte';
|
|
25
|
-
|
|
26
|
-
// Fields
|
|
27
|
-
import CheckboxField from '../recipes/fields/CheckboxField.svelte';
|
|
28
|
-
import FormField from '../recipes/fields/FormField.svelte';
|
|
29
|
-
import RadioGroup from '../recipes/fields/RadioGroup.svelte';
|
|
30
|
-
import SelectField from '../recipes/fields/SelectField.svelte';
|
|
31
|
-
import TextareaField from '../recipes/fields/TextareaField.svelte';
|
|
32
|
-
import ToggleField from '../recipes/fields/ToggleField.svelte';
|
|
33
|
-
|
|
34
|
-
// Primitives for demos
|
|
35
|
-
import Button from '../primitives/Button/Button.svelte';
|
|
36
|
-
import Card from '../primitives/Card.svelte';
|
|
37
|
-
|
|
38
|
-
// State
|
|
39
|
-
let isDark = $state(false);
|
|
40
|
-
|
|
41
|
-
// Modal states
|
|
42
|
-
let showAlertModal = $state(false);
|
|
43
|
-
let showConfirmModal = $state(false);
|
|
44
|
-
let showInputModal = $state(false);
|
|
45
|
-
let showStatusModal = $state(false);
|
|
46
|
-
let statusModalType = $state<'success' | 'error' | 'loading'>('success');
|
|
47
|
-
|
|
48
|
-
// Input states
|
|
49
|
-
let otpValue = $state<string[]>(['', '', '', '', '', '']); // OTPInput expects string[]
|
|
50
|
-
let passwordValue = $state('');
|
|
51
|
-
let searchValue = $state('');
|
|
52
|
-
let multiSelectValue = $state<string[]>([]);
|
|
53
|
-
let selectDropdownValue = $state<{label: string, value: string} | null>(null); // SelectDropdown expects object
|
|
54
|
-
|
|
55
|
-
// Field states
|
|
56
|
-
let checkboxChecked = $state(false);
|
|
57
|
-
let toggleChecked = $state(false);
|
|
58
|
-
let radioValue = $state('');
|
|
59
|
-
let textareaValue = $state('');
|
|
60
|
-
let selectFieldValue = $state('');
|
|
61
|
-
let formFieldValue = $state('');
|
|
62
|
-
|
|
63
|
-
function toggleDark() {
|
|
64
|
-
isDark = !isDark;
|
|
65
|
-
document.documentElement.classList.toggle('dark', isDark);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Section styling
|
|
69
|
-
const sectionClass = (dark: boolean) =>
|
|
70
|
-
`rounded-xl p-6 ${dark ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'} border`;
|
|
71
|
-
|
|
72
|
-
const headingClass = (dark: boolean) =>
|
|
73
|
-
`text-xl font-semibold mb-1 ${dark ? 'text-white' : 'text-gray-900'}`;
|
|
74
|
-
|
|
75
|
-
const subheadingClass = (dark: boolean) =>
|
|
76
|
-
`text-sm mb-4 ${dark ? 'text-gray-400' : 'text-gray-500'}`;
|
|
77
|
-
|
|
78
|
-
// Demo data - MultiSelect uses 'items' with {name, value} format
|
|
79
|
-
const multiSelectItems = [
|
|
80
|
-
{ value: 'react', name: 'React' },
|
|
81
|
-
{ value: 'vue', name: 'Vue' },
|
|
82
|
-
{ value: 'svelte', name: 'Svelte' },
|
|
83
|
-
{ value: 'angular', name: 'Angular' },
|
|
84
|
-
{ value: 'solid', name: 'Solid' },
|
|
85
|
-
];
|
|
86
|
-
|
|
87
|
-
// SelectField uses 'items' with {name, value} format
|
|
88
|
-
const selectFieldItems = [
|
|
89
|
-
{ value: 'sm', name: 'Small' },
|
|
90
|
-
{ value: 'md', name: 'Medium' },
|
|
91
|
-
{ value: 'lg', name: 'Large' },
|
|
92
|
-
{ value: 'xl', name: 'Extra Large' },
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
// SelectDropdown uses 'options' with {label, value} format
|
|
96
|
-
const selectDropdownOptions = [
|
|
97
|
-
{ value: 'low', label: 'Low Priority' },
|
|
98
|
-
{ value: 'medium', label: 'Medium Priority' },
|
|
99
|
-
{ value: 'high', label: 'High Priority' },
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
const radioOptions = [
|
|
103
|
-
{ value: 'daily', label: 'Daily', description: 'Get updates every day' },
|
|
104
|
-
{ value: 'weekly', label: 'Weekly', description: 'Get updates once a week' },
|
|
105
|
-
{ value: 'monthly', label: 'Monthly', description: 'Get updates once a month' },
|
|
106
|
-
];
|
|
107
|
-
</script>
|
|
108
|
-
|
|
109
|
-
<div class="min-h-screen p-6 space-y-8 {isDark ? 'bg-gray-900' : 'bg-gray-50'}">
|
|
110
|
-
<!-- Header -->
|
|
111
|
-
<div class="flex items-center justify-between mb-8">
|
|
112
|
-
<div>
|
|
113
|
-
<h1 class="text-3xl font-bold {isDark ? 'text-white' : 'text-gray-900'}">Recipes Gallery</h1>
|
|
114
|
-
<p class="{isDark ? 'text-gray-400' : 'text-gray-600'}">Domain-agnostic compositions (Layer 2)</p>
|
|
115
|
-
</div>
|
|
116
|
-
<button
|
|
117
|
-
onclick={toggleDark}
|
|
118
|
-
class="px-4 py-2 rounded-lg font-medium {isDark ? 'bg-yellow-500 text-black' : 'bg-gray-800 text-white'}"
|
|
119
|
-
>
|
|
120
|
-
{isDark ? '☀️ Light' : '🌙 Dark'}
|
|
121
|
-
</button>
|
|
122
|
-
</div>
|
|
123
|
-
|
|
124
|
-
<!-- ========== FEEDBACK COMPONENTS ========== -->
|
|
125
|
-
<section class={sectionClass(isDark)}>
|
|
126
|
-
<h2 class={headingClass(isDark)}>Feedback Components</h2>
|
|
127
|
-
<p class={subheadingClass(isDark)}>EmptyState, ErrorDisplay, StatusIndicator</p>
|
|
128
|
-
|
|
129
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
130
|
-
<Card>
|
|
131
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">EmptyState</p>
|
|
132
|
-
<EmptyState
|
|
133
|
-
title="No items yet"
|
|
134
|
-
description="Get started by creating your first item"
|
|
135
|
-
>
|
|
136
|
-
<Button size="sm">Create Item</Button>
|
|
137
|
-
</EmptyState>
|
|
138
|
-
</Card>
|
|
139
|
-
|
|
140
|
-
<Card>
|
|
141
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">ErrorDisplay</p>
|
|
142
|
-
<ErrorDisplay
|
|
143
|
-
title="Something went wrong"
|
|
144
|
-
message="We couldn't load the data. Please try again."
|
|
145
|
-
>
|
|
146
|
-
<Button size="sm" variant="outline">Retry</Button>
|
|
147
|
-
</ErrorDisplay>
|
|
148
|
-
</Card>
|
|
149
|
-
</div>
|
|
150
|
-
|
|
151
|
-
<div class="mt-6">
|
|
152
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-3">StatusIndicator</p>
|
|
153
|
-
<div class="flex flex-wrap gap-6">
|
|
154
|
-
<div class="flex items-center gap-2">
|
|
155
|
-
<StatusIndicator status="active" />
|
|
156
|
-
<span class={isDark ? 'text-white' : 'text-gray-900'}>Active</span>
|
|
157
|
-
</div>
|
|
158
|
-
<div class="flex items-center gap-2">
|
|
159
|
-
<StatusIndicator status="pending" />
|
|
160
|
-
<span class={isDark ? 'text-white' : 'text-gray-900'}>Pending</span>
|
|
161
|
-
</div>
|
|
162
|
-
<div class="flex items-center gap-2">
|
|
163
|
-
<StatusIndicator status="inactive" />
|
|
164
|
-
<span class={isDark ? 'text-white' : 'text-gray-900'}>Inactive</span>
|
|
165
|
-
</div>
|
|
166
|
-
<div class="flex items-center gap-2">
|
|
167
|
-
<StatusIndicator status="error" />
|
|
168
|
-
<span class={isDark ? 'text-white' : 'text-gray-900'}>Error</span>
|
|
169
|
-
</div>
|
|
170
|
-
<div class="flex items-center gap-2">
|
|
171
|
-
<StatusIndicator status="success" />
|
|
172
|
-
<span class={isDark ? 'text-white' : 'text-gray-900'}>Success</span>
|
|
173
|
-
</div>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
</section>
|
|
177
|
-
|
|
178
|
-
<!-- ========== FORM FIELDS ========== -->
|
|
179
|
-
<section class={sectionClass(isDark)}>
|
|
180
|
-
<h2 class={headingClass(isDark)}>Form Fields</h2>
|
|
181
|
-
<p class={subheadingClass(isDark)}>Composed field components with labels, validation, and help text</p>
|
|
182
|
-
|
|
183
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
184
|
-
<div>
|
|
185
|
-
<FormField
|
|
186
|
-
label="Full Name"
|
|
187
|
-
hint="Enter your legal name"
|
|
188
|
-
>
|
|
189
|
-
{#snippet children({ id, error })}
|
|
190
|
-
<input
|
|
191
|
-
{id}
|
|
192
|
-
type="text"
|
|
193
|
-
placeholder="John Doe"
|
|
194
|
-
bind:value={formFieldValue}
|
|
195
|
-
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
196
|
-
/>
|
|
197
|
-
{/snippet}
|
|
198
|
-
</FormField>
|
|
199
|
-
</div>
|
|
200
|
-
|
|
201
|
-
<div>
|
|
202
|
-
<FormField
|
|
203
|
-
label="Email (with error)"
|
|
204
|
-
error="Please enter a valid email address"
|
|
205
|
-
>
|
|
206
|
-
{#snippet children({ id, error })}
|
|
207
|
-
<input
|
|
208
|
-
{id}
|
|
209
|
-
type="email"
|
|
210
|
-
placeholder="email@example.com"
|
|
211
|
-
class="w-full px-3 py-2 border {error ? 'border-red-500' : 'border-gray-300 dark:border-gray-600'} rounded-lg bg-gray-50 dark:bg-gray-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
212
|
-
/>
|
|
213
|
-
{/snippet}
|
|
214
|
-
</FormField>
|
|
215
|
-
</div>
|
|
216
|
-
|
|
217
|
-
<div>
|
|
218
|
-
<SelectField
|
|
219
|
-
label="Size"
|
|
220
|
-
items={selectFieldItems}
|
|
221
|
-
bind:value={selectFieldValue}
|
|
222
|
-
placeholder="Choose a size"
|
|
223
|
-
/>
|
|
224
|
-
</div>
|
|
225
|
-
|
|
226
|
-
<div>
|
|
227
|
-
<TextareaField
|
|
228
|
-
label="Bio"
|
|
229
|
-
placeholder="Tell us about yourself..."
|
|
230
|
-
bind:value={textareaValue}
|
|
231
|
-
hint="Maximum 500 characters"
|
|
232
|
-
/>
|
|
233
|
-
</div>
|
|
234
|
-
</div>
|
|
235
|
-
|
|
236
|
-
<div class="mt-6 space-y-4">
|
|
237
|
-
<CheckboxField
|
|
238
|
-
label="I agree to the terms and conditions"
|
|
239
|
-
description="You must agree to continue"
|
|
240
|
-
bind:checked={checkboxChecked}
|
|
241
|
-
/>
|
|
242
|
-
|
|
243
|
-
<ToggleField
|
|
244
|
-
label="Enable notifications"
|
|
245
|
-
description="Receive email updates about your account"
|
|
246
|
-
bind:checked={toggleChecked}
|
|
247
|
-
/>
|
|
248
|
-
|
|
249
|
-
<div class="max-w-md">
|
|
250
|
-
<RadioGroup
|
|
251
|
-
label="Update frequency"
|
|
252
|
-
options={radioOptions}
|
|
253
|
-
bind:value={radioValue}
|
|
254
|
-
/>
|
|
255
|
-
</div>
|
|
256
|
-
</div>
|
|
257
|
-
</section>
|
|
258
|
-
|
|
259
|
-
<!-- ========== SPECIAL INPUTS ========== -->
|
|
260
|
-
<section class={sectionClass(isDark)}>
|
|
261
|
-
<h2 class={headingClass(isDark)}>Special Inputs</h2>
|
|
262
|
-
<p class={subheadingClass(isDark)}>Password, OTP, Search, MultiSelect, SelectDropdown</p>
|
|
263
|
-
|
|
264
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
265
|
-
<div>
|
|
266
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">PasswordInput</p>
|
|
267
|
-
<PasswordInput
|
|
268
|
-
label="Password"
|
|
269
|
-
placeholder="Enter password"
|
|
270
|
-
bind:value={passwordValue}
|
|
271
|
-
/>
|
|
272
|
-
</div>
|
|
273
|
-
|
|
274
|
-
<div>
|
|
275
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">PasswordStrengthIndicator</p>
|
|
276
|
-
<PasswordStrengthIndicator password={passwordValue} />
|
|
277
|
-
</div>
|
|
278
|
-
|
|
279
|
-
<div>
|
|
280
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">OTPInput (6 digits)</p>
|
|
281
|
-
<OTPInput
|
|
282
|
-
length={6}
|
|
283
|
-
bind:value={otpValue}
|
|
284
|
-
/>
|
|
285
|
-
<p class="text-sm text-gray-500 mt-2">Value: {otpValue || '(empty)'}</p>
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
<div>
|
|
289
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">Search</p>
|
|
290
|
-
<Search
|
|
291
|
-
placeholder="Search..."
|
|
292
|
-
bind:value={searchValue}
|
|
293
|
-
/>
|
|
294
|
-
</div>
|
|
295
|
-
|
|
296
|
-
<div>
|
|
297
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">MultiSelect</p>
|
|
298
|
-
<MultiSelect
|
|
299
|
-
label="Frameworks"
|
|
300
|
-
items={multiSelectItems}
|
|
301
|
-
bind:value={multiSelectValue}
|
|
302
|
-
placeholder="Select frameworks"
|
|
303
|
-
/>
|
|
304
|
-
</div>
|
|
305
|
-
|
|
306
|
-
<div>
|
|
307
|
-
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">SelectDropdown</p>
|
|
308
|
-
<SelectDropdown
|
|
309
|
-
options={selectDropdownOptions}
|
|
310
|
-
bind:selected={selectDropdownValue}
|
|
311
|
-
placeholder="Priority"
|
|
312
|
-
/>
|
|
313
|
-
</div>
|
|
314
|
-
</div>
|
|
315
|
-
</section>
|
|
316
|
-
|
|
317
|
-
<!-- ========== MODALS ========== -->
|
|
318
|
-
<section class={sectionClass(isDark)}>
|
|
319
|
-
<h2 class={headingClass(isDark)}>Modals</h2>
|
|
320
|
-
<p class={subheadingClass(isDark)}>AlertModal, ConfirmationModal, InputModal, StatusModal</p>
|
|
321
|
-
|
|
322
|
-
<div class="flex flex-wrap gap-4">
|
|
323
|
-
<Button onclick={() => showAlertModal = true}>
|
|
324
|
-
Open AlertModal
|
|
325
|
-
</Button>
|
|
326
|
-
|
|
327
|
-
<Button variant="alternative" onclick={() => showConfirmModal = true}>
|
|
328
|
-
Open ConfirmationModal
|
|
329
|
-
</Button>
|
|
330
|
-
|
|
331
|
-
<Button variant="outline" onclick={() => showInputModal = true}>
|
|
332
|
-
Open InputModal
|
|
333
|
-
</Button>
|
|
334
|
-
|
|
335
|
-
<Button variant="ghost" onclick={() => {
|
|
336
|
-
statusModalType = 'success';
|
|
337
|
-
showStatusModal = true;
|
|
338
|
-
setTimeout(() => showStatusModal = false, 2000);
|
|
339
|
-
}}>
|
|
340
|
-
StatusModal (Success)
|
|
341
|
-
</Button>
|
|
342
|
-
|
|
343
|
-
<Button variant="ghost" onclick={() => {
|
|
344
|
-
statusModalType = 'error';
|
|
345
|
-
showStatusModal = true;
|
|
346
|
-
setTimeout(() => showStatusModal = false, 2000);
|
|
347
|
-
}}>
|
|
348
|
-
StatusModal (Error)
|
|
349
|
-
</Button>
|
|
350
|
-
|
|
351
|
-
<Button variant="ghost" onclick={() => {
|
|
352
|
-
statusModalType = 'loading';
|
|
353
|
-
showStatusModal = true;
|
|
354
|
-
setTimeout(() => showStatusModal = false, 2000);
|
|
355
|
-
}}>
|
|
356
|
-
StatusModal (Loading)
|
|
357
|
-
</Button>
|
|
358
|
-
</div>
|
|
359
|
-
</section>
|
|
360
|
-
|
|
361
|
-
<!-- AlertModal -->
|
|
362
|
-
<AlertModal
|
|
363
|
-
bind:show={showAlertModal}
|
|
364
|
-
title="Alert"
|
|
365
|
-
message="This is an alert message that requires your attention."
|
|
366
|
-
buttonText="OK"
|
|
367
|
-
onconfirm={() => showAlertModal = false}
|
|
368
|
-
onclose={() => showAlertModal = false}
|
|
369
|
-
/>
|
|
370
|
-
|
|
371
|
-
<!-- ConfirmationModal -->
|
|
372
|
-
<ConfirmationModal
|
|
373
|
-
bind:show={showConfirmModal}
|
|
374
|
-
title="Confirm Action"
|
|
375
|
-
description="Are you sure you want to proceed? This action cannot be undone."
|
|
376
|
-
primaryButtonText="Yes, proceed"
|
|
377
|
-
secondaryButtonText="Cancel"
|
|
378
|
-
onconfirm={() => {
|
|
379
|
-
showConfirmModal = false;
|
|
380
|
-
console.log('Confirmed!');
|
|
381
|
-
}}
|
|
382
|
-
oncancel={() => showConfirmModal = false}
|
|
383
|
-
onclose={() => showConfirmModal = false}
|
|
384
|
-
/>
|
|
385
|
-
|
|
386
|
-
<!-- InputModal -->
|
|
387
|
-
<InputModal
|
|
388
|
-
bind:show={showInputModal}
|
|
389
|
-
title="Enter Information"
|
|
390
|
-
inputLabel="Name"
|
|
391
|
-
inputPlaceholder="Enter your name"
|
|
392
|
-
primaryButtonText="Submit"
|
|
393
|
-
onconfirm={(detail: { value: string }) => {
|
|
394
|
-
console.log('Submitted:', detail.value);
|
|
395
|
-
showInputModal = false;
|
|
396
|
-
}}
|
|
397
|
-
oncancel={() => showInputModal = false}
|
|
398
|
-
onclose={() => showInputModal = false}
|
|
399
|
-
/>
|
|
400
|
-
|
|
401
|
-
<!-- StatusModal -->
|
|
402
|
-
<StatusModal
|
|
403
|
-
bind:show={showStatusModal}
|
|
404
|
-
iconType={statusModalType}
|
|
405
|
-
title={statusModalType === 'loading' ? 'Processing...' : statusModalType === 'success' ? 'Success!' : 'Error'}
|
|
406
|
-
description={statusModalType === 'loading' ? 'Please wait...' : statusModalType === 'success' ? 'Operation completed successfully.' : 'Something went wrong.'}
|
|
407
|
-
onconfirm={() => showStatusModal = false}
|
|
408
|
-
onclose={() => showStatusModal = false}
|
|
409
|
-
/>
|
|
410
|
-
|
|
411
|
-
<!-- ========== COMMON PATTERNS ========== -->
|
|
412
|
-
<section class={sectionClass(isDark)}>
|
|
413
|
-
<h2 class={headingClass(isDark)}>Common Recipe Patterns</h2>
|
|
414
|
-
<p class={subheadingClass(isDark)}>How recipes compose together</p>
|
|
415
|
-
|
|
416
|
-
<div class="space-y-6">
|
|
417
|
-
<Card>
|
|
418
|
-
<h4 class="font-medium mb-4">Registration Form Pattern</h4>
|
|
419
|
-
<div class="space-y-4 max-w-md">
|
|
420
|
-
<FormField label="Email">
|
|
421
|
-
{#snippet children({ id })}
|
|
422
|
-
<input
|
|
423
|
-
{id}
|
|
424
|
-
type="email"
|
|
425
|
-
placeholder="email@example.com"
|
|
426
|
-
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
427
|
-
/>
|
|
428
|
-
{/snippet}
|
|
429
|
-
</FormField>
|
|
430
|
-
<PasswordInput
|
|
431
|
-
label="Password"
|
|
432
|
-
placeholder="Create a password"
|
|
433
|
-
bind:value={passwordValue}
|
|
434
|
-
/>
|
|
435
|
-
<PasswordStrengthIndicator password={passwordValue} />
|
|
436
|
-
<CheckboxField
|
|
437
|
-
label="I agree to the Terms of Service"
|
|
438
|
-
/>
|
|
439
|
-
<Button size="full">Create Account</Button>
|
|
440
|
-
</div>
|
|
441
|
-
</Card>
|
|
442
|
-
|
|
443
|
-
<Card>
|
|
444
|
-
<h4 class="font-medium mb-4">Settings Form Pattern</h4>
|
|
445
|
-
<div class="space-y-4 max-w-md">
|
|
446
|
-
<ToggleField
|
|
447
|
-
label="Email notifications"
|
|
448
|
-
description="Receive updates via email"
|
|
449
|
-
/>
|
|
450
|
-
<ToggleField
|
|
451
|
-
label="Push notifications"
|
|
452
|
-
description="Receive mobile push notifications"
|
|
453
|
-
/>
|
|
454
|
-
<SelectField
|
|
455
|
-
label="Language"
|
|
456
|
-
items={[
|
|
457
|
-
{ value: 'en', name: 'English' },
|
|
458
|
-
{ value: 'es', name: 'Spanish' },
|
|
459
|
-
{ value: 'fr', name: 'French' },
|
|
460
|
-
]}
|
|
461
|
-
placeholder="Select language"
|
|
462
|
-
/>
|
|
463
|
-
<div class="flex justify-end gap-2 pt-4">
|
|
464
|
-
<Button variant="ghost">Cancel</Button>
|
|
465
|
-
<Button>Save Changes</Button>
|
|
466
|
-
</div>
|
|
467
|
-
</div>
|
|
468
|
-
</Card>
|
|
469
|
-
</div>
|
|
470
|
-
</section>
|
|
471
|
-
</div>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// RECIPES VISUAL GALLERY
|
|
4
|
+
// Displays ALL recipe components (Layer 2) - Domain-agnostic compositions
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
// Feedback
|
|
8
|
+
import EmptyState from '../recipes/feedback/EmptyState/EmptyState.svelte';
|
|
9
|
+
import ErrorDisplay from '../recipes/feedback/ErrorDisplay.svelte';
|
|
10
|
+
import StatusIndicator from '../recipes/feedback/StatusIndicator/StatusIndicator.svelte';
|
|
11
|
+
|
|
12
|
+
// Inputs
|
|
13
|
+
import MultiSelect from '../recipes/inputs/MultiSelect.svelte';
|
|
14
|
+
import OTPInput from '../recipes/inputs/OTPInput.svelte';
|
|
15
|
+
import PasswordInput from '../recipes/inputs/PasswordInput.svelte';
|
|
16
|
+
import PasswordStrengthIndicator from '../recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte';
|
|
17
|
+
import Search from '../recipes/inputs/Search.svelte';
|
|
18
|
+
import SelectDropdown from '../recipes/inputs/SelectDropdown.svelte';
|
|
19
|
+
|
|
20
|
+
// Modals
|
|
21
|
+
import AlertModal from '../recipes/modals/AlertModal.svelte';
|
|
22
|
+
import ConfirmationModal from '../recipes/modals/ConfirmationModal.svelte';
|
|
23
|
+
import InputModal from '../recipes/modals/InputModal.svelte';
|
|
24
|
+
import StatusModal from '../recipes/modals/StatusModal.svelte';
|
|
25
|
+
|
|
26
|
+
// Fields
|
|
27
|
+
import CheckboxField from '../recipes/fields/CheckboxField.svelte';
|
|
28
|
+
import FormField from '../recipes/fields/FormField.svelte';
|
|
29
|
+
import RadioGroup from '../recipes/fields/RadioGroup.svelte';
|
|
30
|
+
import SelectField from '../recipes/fields/SelectField.svelte';
|
|
31
|
+
import TextareaField from '../recipes/fields/TextareaField.svelte';
|
|
32
|
+
import ToggleField from '../recipes/fields/ToggleField.svelte';
|
|
33
|
+
|
|
34
|
+
// Primitives for demos
|
|
35
|
+
import Button from '../primitives/Button/Button.svelte';
|
|
36
|
+
import Card from '../primitives/Card.svelte';
|
|
37
|
+
|
|
38
|
+
// State
|
|
39
|
+
let isDark = $state(false);
|
|
40
|
+
|
|
41
|
+
// Modal states
|
|
42
|
+
let showAlertModal = $state(false);
|
|
43
|
+
let showConfirmModal = $state(false);
|
|
44
|
+
let showInputModal = $state(false);
|
|
45
|
+
let showStatusModal = $state(false);
|
|
46
|
+
let statusModalType = $state<'success' | 'error' | 'loading'>('success');
|
|
47
|
+
|
|
48
|
+
// Input states
|
|
49
|
+
let otpValue = $state<string[]>(['', '', '', '', '', '']); // OTPInput expects string[]
|
|
50
|
+
let passwordValue = $state('');
|
|
51
|
+
let searchValue = $state('');
|
|
52
|
+
let multiSelectValue = $state<string[]>([]);
|
|
53
|
+
let selectDropdownValue = $state<{label: string, value: string} | null>(null); // SelectDropdown expects object
|
|
54
|
+
|
|
55
|
+
// Field states
|
|
56
|
+
let checkboxChecked = $state(false);
|
|
57
|
+
let toggleChecked = $state(false);
|
|
58
|
+
let radioValue = $state('');
|
|
59
|
+
let textareaValue = $state('');
|
|
60
|
+
let selectFieldValue = $state('');
|
|
61
|
+
let formFieldValue = $state('');
|
|
62
|
+
|
|
63
|
+
function toggleDark() {
|
|
64
|
+
isDark = !isDark;
|
|
65
|
+
document.documentElement.classList.toggle('dark', isDark);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Section styling
|
|
69
|
+
const sectionClass = (dark: boolean) =>
|
|
70
|
+
`rounded-xl p-6 ${dark ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'} border`;
|
|
71
|
+
|
|
72
|
+
const headingClass = (dark: boolean) =>
|
|
73
|
+
`text-xl font-semibold mb-1 ${dark ? 'text-white' : 'text-gray-900'}`;
|
|
74
|
+
|
|
75
|
+
const subheadingClass = (dark: boolean) =>
|
|
76
|
+
`text-sm mb-4 ${dark ? 'text-gray-400' : 'text-gray-500'}`;
|
|
77
|
+
|
|
78
|
+
// Demo data - MultiSelect uses 'items' with {name, value} format
|
|
79
|
+
const multiSelectItems = [
|
|
80
|
+
{ value: 'react', name: 'React' },
|
|
81
|
+
{ value: 'vue', name: 'Vue' },
|
|
82
|
+
{ value: 'svelte', name: 'Svelte' },
|
|
83
|
+
{ value: 'angular', name: 'Angular' },
|
|
84
|
+
{ value: 'solid', name: 'Solid' },
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
// SelectField uses 'items' with {name, value} format
|
|
88
|
+
const selectFieldItems = [
|
|
89
|
+
{ value: 'sm', name: 'Small' },
|
|
90
|
+
{ value: 'md', name: 'Medium' },
|
|
91
|
+
{ value: 'lg', name: 'Large' },
|
|
92
|
+
{ value: 'xl', name: 'Extra Large' },
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
// SelectDropdown uses 'options' with {label, value} format
|
|
96
|
+
const selectDropdownOptions = [
|
|
97
|
+
{ value: 'low', label: 'Low Priority' },
|
|
98
|
+
{ value: 'medium', label: 'Medium Priority' },
|
|
99
|
+
{ value: 'high', label: 'High Priority' },
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const radioOptions = [
|
|
103
|
+
{ value: 'daily', label: 'Daily', description: 'Get updates every day' },
|
|
104
|
+
{ value: 'weekly', label: 'Weekly', description: 'Get updates once a week' },
|
|
105
|
+
{ value: 'monthly', label: 'Monthly', description: 'Get updates once a month' },
|
|
106
|
+
];
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<div class="min-h-screen p-6 space-y-8 {isDark ? 'bg-gray-900' : 'bg-gray-50'}">
|
|
110
|
+
<!-- Header -->
|
|
111
|
+
<div class="flex items-center justify-between mb-8">
|
|
112
|
+
<div>
|
|
113
|
+
<h1 class="text-3xl font-bold {isDark ? 'text-white' : 'text-gray-900'}">Recipes Gallery</h1>
|
|
114
|
+
<p class="{isDark ? 'text-gray-400' : 'text-gray-600'}">Domain-agnostic compositions (Layer 2)</p>
|
|
115
|
+
</div>
|
|
116
|
+
<button
|
|
117
|
+
onclick={toggleDark}
|
|
118
|
+
class="px-4 py-2 rounded-lg font-medium {isDark ? 'bg-yellow-500 text-black' : 'bg-gray-800 text-white'}"
|
|
119
|
+
>
|
|
120
|
+
{isDark ? '☀️ Light' : '🌙 Dark'}
|
|
121
|
+
</button>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<!-- ========== FEEDBACK COMPONENTS ========== -->
|
|
125
|
+
<section class={sectionClass(isDark)}>
|
|
126
|
+
<h2 class={headingClass(isDark)}>Feedback Components</h2>
|
|
127
|
+
<p class={subheadingClass(isDark)}>EmptyState, ErrorDisplay, StatusIndicator</p>
|
|
128
|
+
|
|
129
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
130
|
+
<Card>
|
|
131
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">EmptyState</p>
|
|
132
|
+
<EmptyState
|
|
133
|
+
title="No items yet"
|
|
134
|
+
description="Get started by creating your first item"
|
|
135
|
+
>
|
|
136
|
+
<Button size="sm">Create Item</Button>
|
|
137
|
+
</EmptyState>
|
|
138
|
+
</Card>
|
|
139
|
+
|
|
140
|
+
<Card>
|
|
141
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">ErrorDisplay</p>
|
|
142
|
+
<ErrorDisplay
|
|
143
|
+
title="Something went wrong"
|
|
144
|
+
message="We couldn't load the data. Please try again."
|
|
145
|
+
>
|
|
146
|
+
<Button size="sm" variant="outline">Retry</Button>
|
|
147
|
+
</ErrorDisplay>
|
|
148
|
+
</Card>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
<div class="mt-6">
|
|
152
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-3">StatusIndicator</p>
|
|
153
|
+
<div class="flex flex-wrap gap-6">
|
|
154
|
+
<div class="flex items-center gap-2">
|
|
155
|
+
<StatusIndicator status="active" />
|
|
156
|
+
<span class={isDark ? 'text-white' : 'text-gray-900'}>Active</span>
|
|
157
|
+
</div>
|
|
158
|
+
<div class="flex items-center gap-2">
|
|
159
|
+
<StatusIndicator status="pending" />
|
|
160
|
+
<span class={isDark ? 'text-white' : 'text-gray-900'}>Pending</span>
|
|
161
|
+
</div>
|
|
162
|
+
<div class="flex items-center gap-2">
|
|
163
|
+
<StatusIndicator status="inactive" />
|
|
164
|
+
<span class={isDark ? 'text-white' : 'text-gray-900'}>Inactive</span>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="flex items-center gap-2">
|
|
167
|
+
<StatusIndicator status="error" />
|
|
168
|
+
<span class={isDark ? 'text-white' : 'text-gray-900'}>Error</span>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="flex items-center gap-2">
|
|
171
|
+
<StatusIndicator status="success" />
|
|
172
|
+
<span class={isDark ? 'text-white' : 'text-gray-900'}>Success</span>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</section>
|
|
177
|
+
|
|
178
|
+
<!-- ========== FORM FIELDS ========== -->
|
|
179
|
+
<section class={sectionClass(isDark)}>
|
|
180
|
+
<h2 class={headingClass(isDark)}>Form Fields</h2>
|
|
181
|
+
<p class={subheadingClass(isDark)}>Composed field components with labels, validation, and help text</p>
|
|
182
|
+
|
|
183
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
184
|
+
<div>
|
|
185
|
+
<FormField
|
|
186
|
+
label="Full Name"
|
|
187
|
+
hint="Enter your legal name"
|
|
188
|
+
>
|
|
189
|
+
{#snippet children({ id, error })}
|
|
190
|
+
<input
|
|
191
|
+
{id}
|
|
192
|
+
type="text"
|
|
193
|
+
placeholder="John Doe"
|
|
194
|
+
bind:value={formFieldValue}
|
|
195
|
+
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
196
|
+
/>
|
|
197
|
+
{/snippet}
|
|
198
|
+
</FormField>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
<div>
|
|
202
|
+
<FormField
|
|
203
|
+
label="Email (with error)"
|
|
204
|
+
error="Please enter a valid email address"
|
|
205
|
+
>
|
|
206
|
+
{#snippet children({ id, error })}
|
|
207
|
+
<input
|
|
208
|
+
{id}
|
|
209
|
+
type="email"
|
|
210
|
+
placeholder="email@example.com"
|
|
211
|
+
class="w-full px-3 py-2 border {error ? 'border-red-500' : 'border-gray-300 dark:border-gray-600'} rounded-lg bg-gray-50 dark:bg-gray-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
212
|
+
/>
|
|
213
|
+
{/snippet}
|
|
214
|
+
</FormField>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<div>
|
|
218
|
+
<SelectField
|
|
219
|
+
label="Size"
|
|
220
|
+
items={selectFieldItems}
|
|
221
|
+
bind:value={selectFieldValue}
|
|
222
|
+
placeholder="Choose a size"
|
|
223
|
+
/>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<div>
|
|
227
|
+
<TextareaField
|
|
228
|
+
label="Bio"
|
|
229
|
+
placeholder="Tell us about yourself..."
|
|
230
|
+
bind:value={textareaValue}
|
|
231
|
+
hint="Maximum 500 characters"
|
|
232
|
+
/>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
|
|
236
|
+
<div class="mt-6 space-y-4">
|
|
237
|
+
<CheckboxField
|
|
238
|
+
label="I agree to the terms and conditions"
|
|
239
|
+
description="You must agree to continue"
|
|
240
|
+
bind:checked={checkboxChecked}
|
|
241
|
+
/>
|
|
242
|
+
|
|
243
|
+
<ToggleField
|
|
244
|
+
label="Enable notifications"
|
|
245
|
+
description="Receive email updates about your account"
|
|
246
|
+
bind:checked={toggleChecked}
|
|
247
|
+
/>
|
|
248
|
+
|
|
249
|
+
<div class="max-w-md">
|
|
250
|
+
<RadioGroup
|
|
251
|
+
label="Update frequency"
|
|
252
|
+
options={radioOptions}
|
|
253
|
+
bind:value={radioValue}
|
|
254
|
+
/>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
</section>
|
|
258
|
+
|
|
259
|
+
<!-- ========== SPECIAL INPUTS ========== -->
|
|
260
|
+
<section class={sectionClass(isDark)}>
|
|
261
|
+
<h2 class={headingClass(isDark)}>Special Inputs</h2>
|
|
262
|
+
<p class={subheadingClass(isDark)}>Password, OTP, Search, MultiSelect, SelectDropdown</p>
|
|
263
|
+
|
|
264
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
265
|
+
<div>
|
|
266
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">PasswordInput</p>
|
|
267
|
+
<PasswordInput
|
|
268
|
+
label="Password"
|
|
269
|
+
placeholder="Enter password"
|
|
270
|
+
bind:value={passwordValue}
|
|
271
|
+
/>
|
|
272
|
+
</div>
|
|
273
|
+
|
|
274
|
+
<div>
|
|
275
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">PasswordStrengthIndicator</p>
|
|
276
|
+
<PasswordStrengthIndicator password={passwordValue} />
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<div>
|
|
280
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">OTPInput (6 digits)</p>
|
|
281
|
+
<OTPInput
|
|
282
|
+
length={6}
|
|
283
|
+
bind:value={otpValue}
|
|
284
|
+
/>
|
|
285
|
+
<p class="text-sm text-gray-500 mt-2">Value: {otpValue || '(empty)'}</p>
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<div>
|
|
289
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">Search</p>
|
|
290
|
+
<Search
|
|
291
|
+
placeholder="Search..."
|
|
292
|
+
bind:value={searchValue}
|
|
293
|
+
/>
|
|
294
|
+
</div>
|
|
295
|
+
|
|
296
|
+
<div>
|
|
297
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">MultiSelect</p>
|
|
298
|
+
<MultiSelect
|
|
299
|
+
label="Frameworks"
|
|
300
|
+
items={multiSelectItems}
|
|
301
|
+
bind:value={multiSelectValue}
|
|
302
|
+
placeholder="Select frameworks"
|
|
303
|
+
/>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<div>
|
|
307
|
+
<p class="text-xs {isDark ? 'text-gray-500' : 'text-gray-400'} mb-2">SelectDropdown</p>
|
|
308
|
+
<SelectDropdown
|
|
309
|
+
options={selectDropdownOptions}
|
|
310
|
+
bind:selected={selectDropdownValue}
|
|
311
|
+
placeholder="Priority"
|
|
312
|
+
/>
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
</section>
|
|
316
|
+
|
|
317
|
+
<!-- ========== MODALS ========== -->
|
|
318
|
+
<section class={sectionClass(isDark)}>
|
|
319
|
+
<h2 class={headingClass(isDark)}>Modals</h2>
|
|
320
|
+
<p class={subheadingClass(isDark)}>AlertModal, ConfirmationModal, InputModal, StatusModal</p>
|
|
321
|
+
|
|
322
|
+
<div class="flex flex-wrap gap-4">
|
|
323
|
+
<Button onclick={() => showAlertModal = true}>
|
|
324
|
+
Open AlertModal
|
|
325
|
+
</Button>
|
|
326
|
+
|
|
327
|
+
<Button variant="alternative" onclick={() => showConfirmModal = true}>
|
|
328
|
+
Open ConfirmationModal
|
|
329
|
+
</Button>
|
|
330
|
+
|
|
331
|
+
<Button variant="outline" onclick={() => showInputModal = true}>
|
|
332
|
+
Open InputModal
|
|
333
|
+
</Button>
|
|
334
|
+
|
|
335
|
+
<Button variant="ghost" onclick={() => {
|
|
336
|
+
statusModalType = 'success';
|
|
337
|
+
showStatusModal = true;
|
|
338
|
+
setTimeout(() => showStatusModal = false, 2000);
|
|
339
|
+
}}>
|
|
340
|
+
StatusModal (Success)
|
|
341
|
+
</Button>
|
|
342
|
+
|
|
343
|
+
<Button variant="ghost" onclick={() => {
|
|
344
|
+
statusModalType = 'error';
|
|
345
|
+
showStatusModal = true;
|
|
346
|
+
setTimeout(() => showStatusModal = false, 2000);
|
|
347
|
+
}}>
|
|
348
|
+
StatusModal (Error)
|
|
349
|
+
</Button>
|
|
350
|
+
|
|
351
|
+
<Button variant="ghost" onclick={() => {
|
|
352
|
+
statusModalType = 'loading';
|
|
353
|
+
showStatusModal = true;
|
|
354
|
+
setTimeout(() => showStatusModal = false, 2000);
|
|
355
|
+
}}>
|
|
356
|
+
StatusModal (Loading)
|
|
357
|
+
</Button>
|
|
358
|
+
</div>
|
|
359
|
+
</section>
|
|
360
|
+
|
|
361
|
+
<!-- AlertModal -->
|
|
362
|
+
<AlertModal
|
|
363
|
+
bind:show={showAlertModal}
|
|
364
|
+
title="Alert"
|
|
365
|
+
message="This is an alert message that requires your attention."
|
|
366
|
+
buttonText="OK"
|
|
367
|
+
onconfirm={() => showAlertModal = false}
|
|
368
|
+
onclose={() => showAlertModal = false}
|
|
369
|
+
/>
|
|
370
|
+
|
|
371
|
+
<!-- ConfirmationModal -->
|
|
372
|
+
<ConfirmationModal
|
|
373
|
+
bind:show={showConfirmModal}
|
|
374
|
+
title="Confirm Action"
|
|
375
|
+
description="Are you sure you want to proceed? This action cannot be undone."
|
|
376
|
+
primaryButtonText="Yes, proceed"
|
|
377
|
+
secondaryButtonText="Cancel"
|
|
378
|
+
onconfirm={() => {
|
|
379
|
+
showConfirmModal = false;
|
|
380
|
+
console.log('Confirmed!');
|
|
381
|
+
}}
|
|
382
|
+
oncancel={() => showConfirmModal = false}
|
|
383
|
+
onclose={() => showConfirmModal = false}
|
|
384
|
+
/>
|
|
385
|
+
|
|
386
|
+
<!-- InputModal -->
|
|
387
|
+
<InputModal
|
|
388
|
+
bind:show={showInputModal}
|
|
389
|
+
title="Enter Information"
|
|
390
|
+
inputLabel="Name"
|
|
391
|
+
inputPlaceholder="Enter your name"
|
|
392
|
+
primaryButtonText="Submit"
|
|
393
|
+
onconfirm={(detail: { value: string }) => {
|
|
394
|
+
console.log('Submitted:', detail.value);
|
|
395
|
+
showInputModal = false;
|
|
396
|
+
}}
|
|
397
|
+
oncancel={() => showInputModal = false}
|
|
398
|
+
onclose={() => showInputModal = false}
|
|
399
|
+
/>
|
|
400
|
+
|
|
401
|
+
<!-- StatusModal -->
|
|
402
|
+
<StatusModal
|
|
403
|
+
bind:show={showStatusModal}
|
|
404
|
+
iconType={statusModalType}
|
|
405
|
+
title={statusModalType === 'loading' ? 'Processing...' : statusModalType === 'success' ? 'Success!' : 'Error'}
|
|
406
|
+
description={statusModalType === 'loading' ? 'Please wait...' : statusModalType === 'success' ? 'Operation completed successfully.' : 'Something went wrong.'}
|
|
407
|
+
onconfirm={() => showStatusModal = false}
|
|
408
|
+
onclose={() => showStatusModal = false}
|
|
409
|
+
/>
|
|
410
|
+
|
|
411
|
+
<!-- ========== COMMON PATTERNS ========== -->
|
|
412
|
+
<section class={sectionClass(isDark)}>
|
|
413
|
+
<h2 class={headingClass(isDark)}>Common Recipe Patterns</h2>
|
|
414
|
+
<p class={subheadingClass(isDark)}>How recipes compose together</p>
|
|
415
|
+
|
|
416
|
+
<div class="space-y-6">
|
|
417
|
+
<Card>
|
|
418
|
+
<h4 class="font-medium mb-4">Registration Form Pattern</h4>
|
|
419
|
+
<div class="space-y-4 max-w-md">
|
|
420
|
+
<FormField label="Email">
|
|
421
|
+
{#snippet children({ id })}
|
|
422
|
+
<input
|
|
423
|
+
{id}
|
|
424
|
+
type="email"
|
|
425
|
+
placeholder="email@example.com"
|
|
426
|
+
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
427
|
+
/>
|
|
428
|
+
{/snippet}
|
|
429
|
+
</FormField>
|
|
430
|
+
<PasswordInput
|
|
431
|
+
label="Password"
|
|
432
|
+
placeholder="Create a password"
|
|
433
|
+
bind:value={passwordValue}
|
|
434
|
+
/>
|
|
435
|
+
<PasswordStrengthIndicator password={passwordValue} />
|
|
436
|
+
<CheckboxField
|
|
437
|
+
label="I agree to the Terms of Service"
|
|
438
|
+
/>
|
|
439
|
+
<Button size="full">Create Account</Button>
|
|
440
|
+
</div>
|
|
441
|
+
</Card>
|
|
442
|
+
|
|
443
|
+
<Card>
|
|
444
|
+
<h4 class="font-medium mb-4">Settings Form Pattern</h4>
|
|
445
|
+
<div class="space-y-4 max-w-md">
|
|
446
|
+
<ToggleField
|
|
447
|
+
label="Email notifications"
|
|
448
|
+
description="Receive updates via email"
|
|
449
|
+
/>
|
|
450
|
+
<ToggleField
|
|
451
|
+
label="Push notifications"
|
|
452
|
+
description="Receive mobile push notifications"
|
|
453
|
+
/>
|
|
454
|
+
<SelectField
|
|
455
|
+
label="Language"
|
|
456
|
+
items={[
|
|
457
|
+
{ value: 'en', name: 'English' },
|
|
458
|
+
{ value: 'es', name: 'Spanish' },
|
|
459
|
+
{ value: 'fr', name: 'French' },
|
|
460
|
+
]}
|
|
461
|
+
placeholder="Select language"
|
|
462
|
+
/>
|
|
463
|
+
<div class="flex justify-end gap-2 pt-4">
|
|
464
|
+
<Button variant="ghost">Cancel</Button>
|
|
465
|
+
<Button>Save Changes</Button>
|
|
466
|
+
</div>
|
|
467
|
+
</div>
|
|
468
|
+
</Card>
|
|
469
|
+
</div>
|
|
470
|
+
</section>
|
|
471
|
+
</div>
|