@stacksjs/components 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +477 -0
- package/dist/Accordion-x2gjedap.stx +108 -0
- package/dist/Audio-0fk6p9tn.stx +50 -0
- package/dist/Avatar-5m0v0s4x.stx +88 -0
- package/dist/Badge-ynes82vv.stx +70 -0
- package/dist/Breadcrumb-h9n427sk.stx +79 -0
- package/dist/Button-7xtrzn14.stx +89 -0
- package/dist/Calendar-egvx1pma.stx +232 -0
- package/dist/Card-r9w7vy1a.stx +74 -0
- package/dist/Checkbox-m8v46pmx.stx +92 -0
- package/dist/Checkout-vcnnr176.stx +39 -0
- package/dist/CodeBlock-mwex82cm.stx +57 -0
- package/dist/Combobox-npb08vkp.stx +13 -0
- package/dist/ComboboxButton-vcdyq4zw.stx +13 -0
- package/dist/ComboboxInput-c9d2p02m.stx +25 -0
- package/dist/ComboboxOption-7d0h9ash.stx +52 -0
- package/dist/ComboboxOptions-4dtqc0qa.stx +12 -0
- package/dist/CommandPalette-ah00bf8v.stx +39 -0
- package/dist/CommandPaletteItem-2yx0gvtj.stx +32 -0
- package/dist/DefaultPaymentMethod-emw5fg8s.stx +62 -0
- package/dist/Dialog-1w4rz7x0.stx +19 -0
- package/dist/DialogBackdrop-qbm3y5ab.stx +9 -0
- package/dist/DialogDescription-01w5j74b.stx +11 -0
- package/dist/DialogPanel-brsszrrs.stx +16 -0
- package/dist/DialogTitle-3rxhwg21.stx +11 -0
- package/dist/Drawer-yfaz8q7f.stx +137 -0
- package/dist/Dropdown-ng7nx556.stx +24 -0
- package/dist/DropdownButton-vc4zpyrb.stx +23 -0
- package/dist/DropdownItem-z491y23c.stx +43 -0
- package/dist/DropdownItems-7ykf29sj.stx +18 -0
- package/dist/EmailInput-bfshpj92.stx +41 -0
- package/dist/Footer-xdaf02nr.stx +66 -0
- package/dist/Form-z4f7w6r1.stx +209 -0
- package/dist/Hero-9vvp7pxf.stx +25 -0
- package/dist/Image-ktk0451c.stx +197 -0
- package/dist/Installation-33bj4rm7.stx +39 -0
- package/dist/Listbox-xcejcmyc.stx +14 -0
- package/dist/ListboxButton-nx5kmw19.stx +17 -0
- package/dist/ListboxLabel-aky8a73n.stx +11 -0
- package/dist/ListboxOption-6h4hsdz5.stx +57 -0
- package/dist/ListboxOptions-2sacdtm5.stx +16 -0
- package/dist/Login-s2jkvd9y.stx +163 -0
- package/dist/Navigator-tqqdgdkw.stx +138 -0
- package/dist/Notification-sry8egea.stx +71 -0
- package/dist/NumberInput-zm93ddfw.stx +138 -0
- package/dist/Pagination-yza9v4qw.stx +183 -0
- package/dist/PasswordInput-4xnndp5y.stx +155 -0
- package/dist/PaymentMethods-jxba6kek.stx +113 -0
- package/dist/Popover-scbqatjq.stx +24 -0
- package/dist/PopoverButton-rbxhzj4k.stx +23 -0
- package/dist/PopoverPanel-9ng1rm6e.stx +23 -0
- package/dist/Portal-j111yvqp.stx +74 -0
- package/dist/Progress-gbmw3akr.stx +142 -0
- package/dist/Radio-1n9qamv1.stx +81 -0
- package/dist/RadioGroup-12dw2vhk.stx +13 -0
- package/dist/RadioGroupDescription-bjm3mdht.stx +11 -0
- package/dist/RadioGroupLabel-aky8a73n.stx +11 -0
- package/dist/RadioGroupOption-9pcxgwmd.stx +51 -0
- package/dist/SearchInput-g240e2nq.stx +63 -0
- package/dist/Select-p9f94b20.stx +89 -0
- package/dist/Sidebar-gwxw8q38.stx +288 -0
- package/dist/SidebarFooter-887kxret.stx +95 -0
- package/dist/SidebarHeader-qjeyx0hv.stx +100 -0
- package/dist/SidebarItem-4dpwtmb4.stx +118 -0
- package/dist/SidebarSection-kh92fk4m.stx +108 -0
- package/dist/Signup-3nxq5zag.stx +161 -0
- package/dist/Skeleton-g0nx1njm.stx +48 -0
- package/dist/Spinner-w4zj58xp.stx +109 -0
- package/dist/Stepper-rwc5actp.stx +17 -0
- package/dist/StepperStep-h0k657nm.stx +53 -0
- package/dist/SubscriptionCheckout-4cbxdg7w.stx +353 -0
- package/dist/Switch-kjq8qd2p.stx +74 -0
- package/dist/Table-59j9qwp0.stx +14 -0
- package/dist/TableBody-reka2gwv.stx +10 -0
- package/dist/TableCell-j7nh4sgr.stx +10 -0
- package/dist/TableHead-ecbrwpqm.stx +10 -0
- package/dist/TableHeader-jn2shwsv.stx +13 -0
- package/dist/TableRow-xz8rrxhc.stx +11 -0
- package/dist/Tabs-kb6ex6m7.stx +145 -0
- package/dist/Teleport-819cg9zm.stx +101 -0
- package/dist/TextInput-zx9kgr79.stx +146 -0
- package/dist/Textarea-5xvmrb0z.stx +119 -0
- package/dist/Tooltip-5ehqsy49.stx +76 -0
- package/dist/Transition-2j39s044.stx +174 -0
- package/dist/TwoFactorChallenge-2q4gg89m.stx +125 -0
- package/dist/Video-6aq4shh4.stx +45 -0
- package/dist/VirtualList-weh5qtm1.stx +83 -0
- package/dist/VirtualTable-59a1eskc.stx +113 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/composables/index.d.ts +4 -0
- package/dist/composables/index.js +3 -0
- package/dist/composables/useCopyCode.d.ts +19 -0
- package/dist/composables/useDarkMode.d.ts +25 -0
- package/dist/composables/useSEO.d.ts +36 -0
- package/dist/composables/utilities/index.d.ts +5 -0
- package/dist/composables/utilities/useClickOutside.d.ts +28 -0
- package/dist/composables/utilities/useFocusTrap.d.ts +34 -0
- package/dist/composables/utilities/useKeyboard.d.ts +55 -0
- package/dist/composables/utilities/useLocalStorage.d.ts +33 -0
- package/dist/composables/utilities/useMediaQuery.d.ts +64 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +19 -0
- package/dist/ui/accordion/index.d.ts +12 -0
- package/dist/ui/audio/index.d.ts +12 -0
- package/dist/ui/auth/index.d.ts +29 -0
- package/dist/ui/avatar/index.d.ts +11 -0
- package/dist/ui/badge/index.d.ts +9 -0
- package/dist/ui/breadcrumb/index.d.ts +13 -0
- package/dist/ui/button/index.d.ts +45 -0
- package/dist/ui/calendar/index.d.ts +13 -0
- package/dist/ui/card/index.d.ts +12 -0
- package/dist/ui/checkbox/index.d.ts +15 -0
- package/dist/ui/combobox/index.d.ts +35 -0
- package/dist/ui/command-palette/index.d.ts +13 -0
- package/dist/ui/dialog/index.d.ts +27 -0
- package/dist/ui/drawer/index.d.ts +8 -0
- package/dist/ui/dropdown/index.d.ts +25 -0
- package/dist/ui/form/index.d.ts +48 -0
- package/dist/ui/image/index.d.ts +21 -0
- package/dist/ui/input/index.d.ts +73 -0
- package/dist/ui/listbox/index.d.ts +34 -0
- package/dist/ui/navigator/index.d.ts +18 -0
- package/dist/ui/notification/index.d.ts +11 -0
- package/dist/ui/pagination/index.d.ts +10 -0
- package/dist/ui/payment/index.d.ts +53 -0
- package/dist/ui/popover/index.d.ts +19 -0
- package/dist/ui/portal/index.d.ts +5 -0
- package/dist/ui/progress/index.d.ts +11 -0
- package/dist/ui/radio/index.d.ts +14 -0
- package/dist/ui/radio-group/index.d.ts +26 -0
- package/dist/ui/select/index.d.ts +19 -0
- package/dist/ui/sidebar/index.d.ts +129 -0
- package/dist/ui/skeleton/index.d.ts +10 -0
- package/dist/ui/spinner/index.d.ts +8 -0
- package/dist/ui/stepper/index.d.ts +17 -0
- package/dist/ui/storage/index.d.ts +40 -0
- package/dist/ui/switch/index.d.ts +9 -0
- package/dist/ui/table/index.d.ts +29 -0
- package/dist/ui/tabs/index.d.ts +14 -0
- package/dist/ui/teleport/index.d.ts +6 -0
- package/dist/ui/textarea/index.d.ts +19 -0
- package/dist/ui/tooltip/index.d.ts +9 -0
- package/dist/ui/transition/index.d.ts +24 -0
- package/dist/ui/video/index.d.ts +15 -0
- package/dist/ui/virtual-list/index.d.ts +9 -0
- package/dist/ui/virtual-table/index.d.ts +19 -0
- package/dist/utils/accessibility.d.ts +285 -0
- package/dist/utils/animation/easing.d.ts +112 -0
- package/dist/utils/animation/helpers.d.ts +119 -0
- package/dist/utils/animation/index.d.ts +3 -0
- package/dist/utils/animation/keyframes.d.ts +334 -0
- package/dist/utils/error-handling.d.ts +182 -0
- package/dist/utils/highlighter.d.ts +27 -0
- package/dist/utils/highlighter.js +2 -0
- package/dist/utils/i18n.d.ts +245 -0
- package/dist/utils/keep-alive.d.ts +171 -0
- package/dist/utils/lazy-loading.d.ts +174 -0
- package/dist/utils/prop-validation.d.ts +106 -0
- package/dist/utils/theme.d.ts +234 -0
- package/package.json +69 -0
- package/src/components/CodeBlock.stx +57 -0
- package/src/components/Footer.stx +66 -0
- package/src/components/Hero.stx +25 -0
- package/src/components/Installation.stx +39 -0
- package/src/components/index.ts +4 -0
- package/src/composables/index.ts +4 -0
- package/src/composables/useCopyCode.ts +73 -0
- package/src/composables/useDarkMode.ts +100 -0
- package/src/composables/useSEO.ts +229 -0
- package/src/composables/utilities/index.ts +7 -0
- package/src/composables/utilities/useClickOutside.ts +72 -0
- package/src/composables/utilities/useFocusTrap.ts +159 -0
- package/src/composables/utilities/useKeyboard.ts +124 -0
- package/src/composables/utilities/useLocalStorage.ts +132 -0
- package/src/composables/utilities/useMediaQuery.ts +118 -0
- package/src/index.ts +99 -0
- package/src/stx.d.ts +4 -0
- package/src/ui/accordion/Accordion.stx +108 -0
- package/src/ui/accordion/index.ts +14 -0
- package/src/ui/audio/Audio.stx +50 -0
- package/src/ui/audio/README.md +42 -0
- package/src/ui/audio/index.ts +13 -0
- package/src/ui/auth/Login.stx +163 -0
- package/src/ui/auth/README.md +145 -0
- package/src/ui/auth/Signup.stx +161 -0
- package/src/ui/auth/TwoFactorChallenge.stx +125 -0
- package/src/ui/auth/index.ts +32 -0
- package/src/ui/avatar/Avatar.stx +88 -0
- package/src/ui/avatar/index.ts +12 -0
- package/src/ui/badge/Badge.stx +70 -0
- package/src/ui/badge/index.ts +10 -0
- package/src/ui/breadcrumb/Breadcrumb.stx +79 -0
- package/src/ui/breadcrumb/index.ts +15 -0
- package/src/ui/button/Button.stx +89 -0
- package/src/ui/button/README.md +100 -0
- package/src/ui/button/index.ts +85 -0
- package/src/ui/calendar/Calendar.stx +232 -0
- package/src/ui/calendar/README.md +254 -0
- package/src/ui/calendar/index.ts +14 -0
- package/src/ui/card/Card.stx +74 -0
- package/src/ui/card/index.ts +13 -0
- package/src/ui/checkbox/Checkbox.stx +92 -0
- package/src/ui/checkbox/index.ts +16 -0
- package/src/ui/combobox/Combobox.stx +13 -0
- package/src/ui/combobox/ComboboxButton.stx +13 -0
- package/src/ui/combobox/ComboboxInput.stx +25 -0
- package/src/ui/combobox/ComboboxOption.stx +52 -0
- package/src/ui/combobox/ComboboxOptions.stx +12 -0
- package/src/ui/combobox/README.md +154 -0
- package/src/ui/combobox/index.ts +40 -0
- package/src/ui/command-palette/CommandPalette.stx +39 -0
- package/src/ui/command-palette/CommandPaletteItem.stx +32 -0
- package/src/ui/command-palette/README.md +42 -0
- package/src/ui/command-palette/index.ts +15 -0
- package/src/ui/dialog/Dialog.stx +19 -0
- package/src/ui/dialog/DialogBackdrop.stx +9 -0
- package/src/ui/dialog/DialogDescription.stx +11 -0
- package/src/ui/dialog/DialogPanel.stx +16 -0
- package/src/ui/dialog/DialogTitle.stx +11 -0
- package/src/ui/dialog/README.md +133 -0
- package/src/ui/dialog/index.ts +32 -0
- package/src/ui/drawer/Drawer.stx +137 -0
- package/src/ui/drawer/README.md +110 -0
- package/src/ui/drawer/index.ts +9 -0
- package/src/ui/dropdown/Dropdown.stx +24 -0
- package/src/ui/dropdown/DropdownButton.stx +23 -0
- package/src/ui/dropdown/DropdownItem.stx +43 -0
- package/src/ui/dropdown/DropdownItems.stx +18 -0
- package/src/ui/dropdown/README.md +142 -0
- package/src/ui/dropdown/index.ts +29 -0
- package/src/ui/form/Form.stx +209 -0
- package/src/ui/form/index.ts +67 -0
- package/src/ui/heatmap/Heatmap.stx +315 -0
- package/src/ui/image/Image.stx +197 -0
- package/src/ui/image/README.md +171 -0
- package/src/ui/image/index.ts +22 -0
- package/src/ui/input/EmailInput.stx +41 -0
- package/src/ui/input/NumberInput.stx +138 -0
- package/src/ui/input/PasswordInput.stx +155 -0
- package/src/ui/input/SearchInput.stx +63 -0
- package/src/ui/input/TextInput.stx +146 -0
- package/src/ui/input/index.ts +180 -0
- package/src/ui/listbox/Listbox.stx +14 -0
- package/src/ui/listbox/ListboxButton.stx +17 -0
- package/src/ui/listbox/ListboxLabel.stx +11 -0
- package/src/ui/listbox/ListboxOption.stx +57 -0
- package/src/ui/listbox/ListboxOptions.stx +16 -0
- package/src/ui/listbox/README.md +143 -0
- package/src/ui/listbox/index.ts +39 -0
- package/src/ui/navigator/Navigator.stx +138 -0
- package/src/ui/navigator/README.md +352 -0
- package/src/ui/navigator/index.ts +20 -0
- package/src/ui/notification/Notification.stx +71 -0
- package/src/ui/notification/README.md +118 -0
- package/src/ui/notification/index.ts +12 -0
- package/src/ui/pagination/Pagination.stx +183 -0
- package/src/ui/pagination/index.ts +11 -0
- package/src/ui/payment/Checkout.stx +39 -0
- package/src/ui/payment/DefaultPaymentMethod.stx +62 -0
- package/src/ui/payment/PaymentMethods.stx +113 -0
- package/src/ui/payment/README.md +427 -0
- package/src/ui/payment/SubscriptionCheckout.stx +353 -0
- package/src/ui/payment/index.ts +59 -0
- package/src/ui/popover/Popover.stx +24 -0
- package/src/ui/popover/PopoverButton.stx +23 -0
- package/src/ui/popover/PopoverPanel.stx +23 -0
- package/src/ui/popover/README.md +95 -0
- package/src/ui/popover/index.ts +22 -0
- package/src/ui/portal/Portal.stx +74 -0
- package/src/ui/portal/index.ts +6 -0
- package/src/ui/progress/Progress.stx +142 -0
- package/src/ui/progress/index.ts +12 -0
- package/src/ui/radio/Radio.stx +81 -0
- package/src/ui/radio/index.ts +15 -0
- package/src/ui/radio-group/README.md +145 -0
- package/src/ui/radio-group/RadioGroup.stx +13 -0
- package/src/ui/radio-group/RadioGroupDescription.stx +11 -0
- package/src/ui/radio-group/RadioGroupLabel.stx +11 -0
- package/src/ui/radio-group/RadioGroupOption.stx +51 -0
- package/src/ui/radio-group/index.ts +30 -0
- package/src/ui/select/README.md +204 -0
- package/src/ui/select/Select.stx +89 -0
- package/src/ui/select/index.ts +21 -0
- package/src/ui/sidebar/Sidebar.stx +288 -0
- package/src/ui/sidebar/SidebarFooter.stx +95 -0
- package/src/ui/sidebar/SidebarHeader.stx +100 -0
- package/src/ui/sidebar/SidebarItem.stx +118 -0
- package/src/ui/sidebar/SidebarSection.stx +108 -0
- package/src/ui/sidebar/index.ts +175 -0
- package/src/ui/skeleton/Skeleton.stx +48 -0
- package/src/ui/skeleton/index.ts +11 -0
- package/src/ui/spinner/Spinner.stx +109 -0
- package/src/ui/spinner/index.ts +9 -0
- package/src/ui/stepper/README.md +36 -0
- package/src/ui/stepper/Stepper.stx +17 -0
- package/src/ui/stepper/StepperStep.stx +53 -0
- package/src/ui/stepper/index.ts +19 -0
- package/src/ui/storage/README.md +193 -0
- package/src/ui/storage/index.ts +347 -0
- package/src/ui/switch/README.md +133 -0
- package/src/ui/switch/Switch.stx +74 -0
- package/src/ui/switch/index.ts +10 -0
- package/src/ui/table/README.md +39 -0
- package/src/ui/table/Table.stx +14 -0
- package/src/ui/table/TableBody.stx +10 -0
- package/src/ui/table/TableCell.stx +10 -0
- package/src/ui/table/TableHead.stx +10 -0
- package/src/ui/table/TableHeader.stx +13 -0
- package/src/ui/table/TableRow.stx +11 -0
- package/src/ui/table/index.ts +35 -0
- package/src/ui/tabs/Tabs.stx +145 -0
- package/src/ui/tabs/index.ts +16 -0
- package/src/ui/teleport/Teleport.stx +101 -0
- package/src/ui/teleport/index.ts +7 -0
- package/src/ui/textarea/Textarea.stx +119 -0
- package/src/ui/textarea/index.ts +20 -0
- package/src/ui/tooltip/Tooltip.stx +76 -0
- package/src/ui/tooltip/index.ts +10 -0
- package/src/ui/transition/README.md +30 -0
- package/src/ui/transition/Transition.stx +174 -0
- package/src/ui/transition/index.ts +25 -0
- package/src/ui/video/README.md +48 -0
- package/src/ui/video/Video.stx +45 -0
- package/src/ui/video/index.ts +16 -0
- package/src/ui/virtual-list/VirtualList.stx +83 -0
- package/src/ui/virtual-list/index.ts +10 -0
- package/src/ui/virtual-table/VirtualTable.stx +113 -0
- package/src/ui/virtual-table/index.ts +21 -0
- package/src/utils/PROP_VALIDATION.md +458 -0
- package/src/utils/THEME_SYSTEM.md +702 -0
- package/src/utils/accessibility.ts +841 -0
- package/src/utils/animation/easing.ts +368 -0
- package/src/utils/animation/helpers.ts +223 -0
- package/src/utils/animation/index.ts +5 -0
- package/src/utils/animation/keyframes.ts +230 -0
- package/src/utils/error-handling.ts +473 -0
- package/src/utils/highlighter.ts +93 -0
- package/src/utils/i18n.ts +634 -0
- package/src/utils/keep-alive.ts +818 -0
- package/src/utils/lazy-loading.ts +530 -0
- package/src/utils/prop-validation.ts +478 -0
- package/src/utils/theme.ts +626 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const checked = $props.checked || false
|
|
3
|
+
export const onChange = $props.onChange || (() => {})
|
|
4
|
+
export const disabled = $props.disabled || false
|
|
5
|
+
export const indeterminate = $props.indeterminate || false
|
|
6
|
+
export const size = $props.size || 'md'
|
|
7
|
+
export const label = $props.label || ''
|
|
8
|
+
export const description = $props.description || ''
|
|
9
|
+
export const error = $props.error || false
|
|
10
|
+
export const required = $props.required || false
|
|
11
|
+
export const value = $props.value || ''
|
|
12
|
+
export const name = $props.name || ''
|
|
13
|
+
export const className = $props.className || ''
|
|
14
|
+
|
|
15
|
+
// Size classes
|
|
16
|
+
const sizeClasses = {
|
|
17
|
+
sm: 'h-4 w-4',
|
|
18
|
+
md: 'h-5 w-5',
|
|
19
|
+
lg: 'h-6 w-6',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Base classes for checkbox
|
|
23
|
+
const baseClasses = 'rounded border-gray-300 dark:border-gray-600 text-indigo-600 dark:text-indigo-500 focus:ring-indigo-600 dark:focus:ring-indigo-500 focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-900 transition-colors'
|
|
24
|
+
|
|
25
|
+
const stateClasses = error
|
|
26
|
+
? 'border-red-300 dark:border-red-600 text-red-600 dark:text-red-500 focus:ring-red-500 dark:focus:ring-red-400'
|
|
27
|
+
: ''
|
|
28
|
+
|
|
29
|
+
const disabledClasses = disabled
|
|
30
|
+
? 'opacity-50 cursor-not-allowed'
|
|
31
|
+
: 'cursor-pointer'
|
|
32
|
+
|
|
33
|
+
export const checkboxClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses}`.trim()
|
|
34
|
+
export const labelClasses = `text-sm font-medium ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'} ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`.trim()
|
|
35
|
+
export const descriptionClasses = `text-sm ${error ? 'text-red-500 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<div class="relative flex items-start {{ className }}">
|
|
39
|
+
<div class="flex h-6 items-center">
|
|
40
|
+
<input
|
|
41
|
+
id="checkbox-{{ value || label }}"
|
|
42
|
+
type="checkbox"
|
|
43
|
+
name="{{ name }}"
|
|
44
|
+
value="{{ value }}"
|
|
45
|
+
checked="{{ checked }}"
|
|
46
|
+
disabled="{{ disabled }}"
|
|
47
|
+
required="{{ required }}"
|
|
48
|
+
class="{{ checkboxClasses }}"
|
|
49
|
+
onchange="handleChange(event)"
|
|
50
|
+
aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
51
|
+
@if(description)aria-describedby="checkbox-description"@endif
|
|
52
|
+
/>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
@if(label || description)
|
|
56
|
+
<div class="ml-3 text-sm leading-6">
|
|
57
|
+
@if(label)
|
|
58
|
+
<label for="checkbox-{{ value || label }}" class="{{ labelClasses }}">
|
|
59
|
+
{{ label }}
|
|
60
|
+
@if(required)
|
|
61
|
+
<span class="text-red-500 ml-1">*</span>
|
|
62
|
+
@endif
|
|
63
|
+
</label>
|
|
64
|
+
@endif
|
|
65
|
+
@if(description)
|
|
66
|
+
<p id="checkbox-description" class="{{ descriptionClasses }}">
|
|
67
|
+
{{ description }}
|
|
68
|
+
</p>
|
|
69
|
+
@endif
|
|
70
|
+
</div>
|
|
71
|
+
@endif
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<script>
|
|
75
|
+
function handleChange(event) {
|
|
76
|
+
const isChecked = event.target.checked
|
|
77
|
+
|
|
78
|
+
if (!disabled && onChange) {
|
|
79
|
+
onChange(isChecked)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Handle indeterminate state
|
|
84
|
+
if (indeterminate && typeof window !== 'undefined') {
|
|
85
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
86
|
+
const checkbox = document.getElementById('checkbox-{{ value || label }}')
|
|
87
|
+
if (checkbox) {
|
|
88
|
+
checkbox.indeterminate = true
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
</script>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const products = $props.products || []
|
|
3
|
+
export const redirectUrl = $props.redirectUrl || ''
|
|
4
|
+
export const mode = $props.mode || 'subscription'
|
|
5
|
+
export const stripePublicKey = $props.stripePublicKey || ''
|
|
6
|
+
export const apiUrl = $props.apiUrl || ''
|
|
7
|
+
export const onSubmit = $props.onSubmit
|
|
8
|
+
export const onRemoveProduct = $props.onRemoveProduct
|
|
9
|
+
export const shipping = $props.shipping || 0
|
|
10
|
+
export const taxes = $props.taxes || 0
|
|
11
|
+
export const className = $props.className || ''
|
|
12
|
+
|
|
13
|
+
// For future expansion - one-time payment support
|
|
14
|
+
export const isSubscription = mode === 'subscription'
|
|
15
|
+
export const isOneTime = mode === 'one-time'
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
@if(isSubscription)
|
|
19
|
+
@component('SubscriptionCheckout', {
|
|
20
|
+
products,
|
|
21
|
+
stripePublicKey,
|
|
22
|
+
apiUrl,
|
|
23
|
+
onSubmit,
|
|
24
|
+
onRemoveProduct,
|
|
25
|
+
shipping,
|
|
26
|
+
taxes,
|
|
27
|
+
className
|
|
28
|
+
})
|
|
29
|
+
@endcomponent
|
|
30
|
+
@endif
|
|
31
|
+
|
|
32
|
+
@if(isOneTime)
|
|
33
|
+
<!-- One-time payment component can be implemented here in the future -->
|
|
34
|
+
<div class="p-8 text-center">
|
|
35
|
+
<p class="text-gray-600 dark:text-gray-400">
|
|
36
|
+
One-time payment mode is not yet implemented.
|
|
37
|
+
</p>
|
|
38
|
+
</div>
|
|
39
|
+
@endif
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { highlight, applyHeadwindClasses } from '../utils/highlighter'
|
|
3
|
+
|
|
4
|
+
export const code = $props.code || ''
|
|
5
|
+
export const language = $props.language || 'typescript'
|
|
6
|
+
export const theme = $props.theme || 'auto'
|
|
7
|
+
export const lineNumbers = $props.lineNumbers !== false
|
|
8
|
+
export const copyable = $props.copyable !== false
|
|
9
|
+
export const className = $props.className || ''
|
|
10
|
+
|
|
11
|
+
export let highlightedCode = ''
|
|
12
|
+
export let copied = false
|
|
13
|
+
|
|
14
|
+
// Highlight the code
|
|
15
|
+
const result = await highlight(code, { language, theme, lineNumbers })
|
|
16
|
+
highlightedCode = applyHeadwindClasses(result.html, className)
|
|
17
|
+
|
|
18
|
+
export async function copyToClipboard() {
|
|
19
|
+
try {
|
|
20
|
+
await navigator.clipboard.writeText(code)
|
|
21
|
+
copied = true
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
copied = false
|
|
24
|
+
}, 2000)
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.error('Failed to copy code:', err)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<div class="relative group">
|
|
32
|
+
{!! highlightedCode !!}
|
|
33
|
+
|
|
34
|
+
@if(copyable)
|
|
35
|
+
<button
|
|
36
|
+
@click="copyToClipboard"
|
|
37
|
+
class="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 px-3 py-1.5 bg-neutral-800 hover:bg-neutral-700 text-white text-xs rounded-md font-medium"
|
|
38
|
+
aria-label="Copy code"
|
|
39
|
+
>
|
|
40
|
+
@if(copied)
|
|
41
|
+
<span class="flex items-center gap-1.5">
|
|
42
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
43
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
|
44
|
+
</svg>
|
|
45
|
+
Copied!
|
|
46
|
+
</span>
|
|
47
|
+
@else
|
|
48
|
+
<span class="flex items-center gap-1.5">
|
|
49
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
50
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
|
51
|
+
</svg>
|
|
52
|
+
Copy
|
|
53
|
+
</span>
|
|
54
|
+
@endif
|
|
55
|
+
</button>
|
|
56
|
+
@endif
|
|
57
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const value = $props.value
|
|
3
|
+
export const onChange = $props.onChange
|
|
4
|
+
export const className = $props.className || ''
|
|
5
|
+
export const as = $props.as || 'div'
|
|
6
|
+
|
|
7
|
+
const baseClasses = 'relative'
|
|
8
|
+
const comboboxClasses = `${baseClasses} ${className}`.trim()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<component :is="{{ as }}" class="{{ comboboxClasses }}">
|
|
12
|
+
<slot :value="value" :onChange="onChange" />
|
|
13
|
+
</component>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'button'
|
|
4
|
+
|
|
5
|
+
const baseClasses = 'absolute inset-y-0 right-0 flex items-center pr-2'
|
|
6
|
+
const buttonClasses = `${baseClasses} ${className}`.trim()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<component :is="{{ as }}" class="{{ buttonClasses }}" tabindex="-1">
|
|
10
|
+
<svg class="h-5 w-5 text-neutral-400" viewBox="0 0 20 20" fill="none" stroke="currentColor">
|
|
11
|
+
<path d="M7 7l3-3 3 3m0 6l-3 3-3-3" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
12
|
+
</svg>
|
|
13
|
+
</component>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const displayValue = $props.displayValue
|
|
3
|
+
export const onChange = $props.onChange
|
|
4
|
+
export const className = $props.className || ''
|
|
5
|
+
export const placeholder = $props.placeholder || ''
|
|
6
|
+
export const disabled = $props.disabled || false
|
|
7
|
+
|
|
8
|
+
const baseClasses = 'w-full rounded-lg border-none bg-white dark:bg-neutral-800 py-2 pl-3 pr-10 text-sm leading-5 text-neutral-900 dark:text-white focus:ring-0 focus:outline-none focus-visible:border-blue-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2'
|
|
9
|
+
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
|
|
10
|
+
const inputClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
|
|
11
|
+
|
|
12
|
+
export function handleChange(e) {
|
|
13
|
+
onChange?.(e.target.value)
|
|
14
|
+
}
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<input
|
|
18
|
+
type="text"
|
|
19
|
+
class="{{ inputClasses }}"
|
|
20
|
+
placeholder="{{ placeholder }}"
|
|
21
|
+
value="{{ displayValue }}"
|
|
22
|
+
@if(disabled)disabled@endif
|
|
23
|
+
@input="handleChange"
|
|
24
|
+
autocomplete="off"
|
|
25
|
+
/>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const value = $props.value
|
|
3
|
+
export const disabled = $props.disabled || false
|
|
4
|
+
export const className = $props.className || ''
|
|
5
|
+
export const as = $props.as || 'li'
|
|
6
|
+
export const currentValue = $props.currentValue
|
|
7
|
+
export const onChange = $props.onChange
|
|
8
|
+
|
|
9
|
+
export let active = false
|
|
10
|
+
export const selected = currentValue === value
|
|
11
|
+
|
|
12
|
+
const baseClasses = 'relative cursor-pointer select-none py-2 pl-10 pr-4'
|
|
13
|
+
const stateClasses = active
|
|
14
|
+
? 'bg-blue-100 text-blue-900 dark:bg-blue-900 dark:text-blue-100'
|
|
15
|
+
: 'text-neutral-900 dark:text-neutral-100'
|
|
16
|
+
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
|
|
17
|
+
const optionClasses = `${baseClasses} ${stateClasses} ${disabledClasses} ${className}`.trim()
|
|
18
|
+
|
|
19
|
+
export function handleClick() {
|
|
20
|
+
if (disabled) return
|
|
21
|
+
onChange?.(value)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function handleMouseEnter() {
|
|
25
|
+
if (!disabled) active = true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function handleMouseLeave() {
|
|
29
|
+
active = false
|
|
30
|
+
}
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<component
|
|
34
|
+
:is="{{ as }}"
|
|
35
|
+
class="{{ optionClasses }}"
|
|
36
|
+
role="option"
|
|
37
|
+
aria-selected="{{ selected ? 'true' : 'false' }}"
|
|
38
|
+
@if(disabled)aria-disabled="true"@endif
|
|
39
|
+
@click="handleClick"
|
|
40
|
+
@mouseenter="handleMouseEnter"
|
|
41
|
+
@mouseleave="handleMouseLeave"
|
|
42
|
+
>
|
|
43
|
+
@if(selected)
|
|
44
|
+
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600 dark:text-blue-400">
|
|
45
|
+
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
46
|
+
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
|
47
|
+
</svg>
|
|
48
|
+
</span>
|
|
49
|
+
@endif
|
|
50
|
+
|
|
51
|
+
<slot :active="active" :selected="selected" :disabled="disabled" />
|
|
52
|
+
</component>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'ul'
|
|
4
|
+
export const static_ = $props.static || false
|
|
5
|
+
|
|
6
|
+
const baseClasses = 'absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white dark:bg-neutral-800 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none'
|
|
7
|
+
const optionsClasses = `${baseClasses} ${className}`.trim()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<component :is="{{ as }}" class="{{ optionsClasses }}" role="listbox">
|
|
11
|
+
<slot />
|
|
12
|
+
</component>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const open = $props.open || false
|
|
3
|
+
export const onClose = $props.onClose
|
|
4
|
+
export const query = $props.query || ''
|
|
5
|
+
export const onQueryChange = $props.onQueryChange
|
|
6
|
+
export const className = $props.className || ''
|
|
7
|
+
|
|
8
|
+
const baseClasses = 'fixed inset-0 z-50 overflow-y-auto p-4 sm:p-6 md:p-20'
|
|
9
|
+
const paletteClasses = `${baseClasses} ${className}`.trim()
|
|
10
|
+
|
|
11
|
+
export function handleClose() {
|
|
12
|
+
onClose?.()
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
@if(open)
|
|
17
|
+
<div class="{{ paletteClasses }}">
|
|
18
|
+
<div class="fixed inset-0 bg-neutral-500 bg-opacity-25 dark:bg-opacity-50 transition-opacity" @click="handleClose" />
|
|
19
|
+
|
|
20
|
+
<div class="mx-auto max-w-xl transform divide-y divide-neutral-100 dark:divide-neutral-800 overflow-hidden rounded-xl bg-white dark:bg-neutral-900 shadow-2xl ring-1 ring-black ring-opacity-5 transition-all">
|
|
21
|
+
<div class="relative">
|
|
22
|
+
<svg class="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-neutral-400" viewBox="0 0 20 20" fill="currentColor">
|
|
23
|
+
<path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd" />
|
|
24
|
+
</svg>
|
|
25
|
+
<input
|
|
26
|
+
type="text"
|
|
27
|
+
class="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-neutral-900 dark:text-white placeholder-neutral-400 focus:ring-0 sm:text-sm"
|
|
28
|
+
placeholder="Search..."
|
|
29
|
+
value="{{ query }}"
|
|
30
|
+
@input="(e) => onQueryChange?.(e.target.value)"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="max-h-96 overflow-y-auto py-2">
|
|
35
|
+
<slot :query="query" />
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
@endif
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const onClick = $props.onClick
|
|
4
|
+
export let active = false
|
|
5
|
+
|
|
6
|
+
const baseClasses = 'flex cursor-pointer select-none items-center px-4 py-2'
|
|
7
|
+
const activeClasses = active
|
|
8
|
+
? 'bg-blue-600 text-white'
|
|
9
|
+
: 'text-neutral-900 dark:text-neutral-100'
|
|
10
|
+
const itemClasses = `${baseClasses} ${activeClasses} ${className}`.trim()
|
|
11
|
+
|
|
12
|
+
export function handleClick() {
|
|
13
|
+
onClick?.()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function handleMouseEnter() {
|
|
17
|
+
active = true
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function handleMouseLeave() {
|
|
21
|
+
active = false
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<div
|
|
26
|
+
class="{{ itemClasses }}"
|
|
27
|
+
@click="handleClick"
|
|
28
|
+
@mouseenter="handleMouseEnter"
|
|
29
|
+
@mouseleave="handleMouseLeave"
|
|
30
|
+
>
|
|
31
|
+
<slot :active="active" />
|
|
32
|
+
</div>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const paymentMethod = $props.paymentMethod
|
|
3
|
+
export const isLoading = $props.isLoading || false
|
|
4
|
+
export const className = $props.className || ''
|
|
5
|
+
|
|
6
|
+
const brandIcons = {
|
|
7
|
+
visa: '💳',
|
|
8
|
+
mastercard: '💳',
|
|
9
|
+
amex: '💳',
|
|
10
|
+
discover: '💳',
|
|
11
|
+
default: '💳',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const containerClasses = `mt-16 w-2/3 bg-white dark:bg-blue-gray-800 px-8 py-6 shadow ring-1 ring-black dark:ring-gray-700 ring-opacity-5 sm:rounded-lg ${className}`.trim()
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<div class="{{ containerClasses }}">
|
|
18
|
+
<h2 class="text-lg text-gray-900 dark:text-gray-100 font-medium">
|
|
19
|
+
Payment Info
|
|
20
|
+
</h2>
|
|
21
|
+
|
|
22
|
+
@if(isLoading)
|
|
23
|
+
<!-- Loading skeleton -->
|
|
24
|
+
<div class="mt-8 animate-pulse">
|
|
25
|
+
<div class="h-20 bg-gray-200 dark:bg-gray-700 rounded-lg"></div>
|
|
26
|
+
</div>
|
|
27
|
+
@else
|
|
28
|
+
@if(paymentMethod)
|
|
29
|
+
<div class="col-span-1 mt-8 border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-blue-gray-800 shadow divide-y divide-gray-200 dark:divide-gray-700">
|
|
30
|
+
<div class="w-full p-3">
|
|
31
|
+
<div class="flex items-center justify-between">
|
|
32
|
+
<div class="flex items-center space-x-4">
|
|
33
|
+
<!-- Card Brand Icon -->
|
|
34
|
+
<div class="flex-shrink-0 h-10 w-10 flex items-center justify-center bg-gray-100 dark:bg-gray-700 rounded-md">
|
|
35
|
+
<span class="text-2xl">{{ brandIcons[paymentMethod.brand.toLowerCase()] || brandIcons.default }}</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<!-- Card Details -->
|
|
39
|
+
<div>
|
|
40
|
+
<h2 class="text-sm text-gray-600 dark:text-gray-300">
|
|
41
|
+
{{ paymentMethod.brand }} •••• {{ paymentMethod.last_four }}
|
|
42
|
+
<span class="ml-4 inline-flex items-center rounded-md bg-indigo-50 dark:bg-indigo-900/30 px-2 py-1 text-xs text-indigo-700 dark:text-indigo-300 font-medium ring-1 ring-indigo-700/10 dark:ring-indigo-300/20 ring-inset">Default</span>
|
|
43
|
+
<br>
|
|
44
|
+
<span class="text-xs text-gray-500 dark:text-gray-400 italic">Expires {{ paymentMethod.exp_month }} / {{ paymentMethod.exp_year }}</span>
|
|
45
|
+
</h2>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
@else
|
|
52
|
+
<!-- Empty state -->
|
|
53
|
+
<div class="col-span-1 mt-8 border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-blue-gray-800 shadow divide-y divide-gray-200 dark:divide-gray-700">
|
|
54
|
+
<div class="w-full px-4 py-5">
|
|
55
|
+
<h2 class="text-center text-sm text-gray-600 dark:text-gray-300">
|
|
56
|
+
You haven't added any payment methods yet.
|
|
57
|
+
</h2>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
@endif
|
|
61
|
+
@endif
|
|
62
|
+
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const open = $props.open || false
|
|
3
|
+
export const onClose = $props.onClose
|
|
4
|
+
export const className = $props.className || ''
|
|
5
|
+
export const as = $props.as || 'div'
|
|
6
|
+
|
|
7
|
+
const baseClasses = 'relative z-50'
|
|
8
|
+
const dialogClasses = `${baseClasses} ${className}`.trim()
|
|
9
|
+
|
|
10
|
+
export function handleClose() {
|
|
11
|
+
onClose?.(false)
|
|
12
|
+
}
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
@if(open)
|
|
16
|
+
<div class="{{ dialogClasses }}" role="dialog" aria-modal="true">
|
|
17
|
+
<slot />
|
|
18
|
+
</div>
|
|
19
|
+
@endif
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'div'
|
|
4
|
+
|
|
5
|
+
const baseClasses = 'fixed inset-0 bg-black bg-opacity-25 dark:bg-opacity-50 transition-opacity'
|
|
6
|
+
const backdropClasses = `${baseClasses} ${className}`.trim()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<component :is="{{ as }}" class="{{ backdropClasses }}" aria-hidden="true" />
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'p'
|
|
4
|
+
|
|
5
|
+
const baseClasses = 'mt-2 text-sm text-neutral-500 dark:text-neutral-400'
|
|
6
|
+
const descriptionClasses = `${baseClasses} ${className}`.trim()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<component :is="{{ as }}" class="{{ descriptionClasses }}">
|
|
10
|
+
<slot />
|
|
11
|
+
</component>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'div'
|
|
4
|
+
|
|
5
|
+
const baseClasses = 'fixed inset-0 overflow-y-auto'
|
|
6
|
+
const panelWrapperClasses = 'flex min-h-full items-center justify-center p-4 text-center'
|
|
7
|
+
const panelClasses = `transform overflow-hidden rounded-lg bg-white dark:bg-neutral-800 p-6 text-left align-middle shadow-xl transition-all ${className}`.trim()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<component :is="{{ as }}" class="{{ baseClasses }}">
|
|
11
|
+
<div class="{{ panelWrapperClasses }}">
|
|
12
|
+
<div class="{{ panelClasses }}">
|
|
13
|
+
<slot />
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</component>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'h3'
|
|
4
|
+
|
|
5
|
+
const baseClasses = 'text-lg font-medium leading-6 text-neutral-900 dark:text-white'
|
|
6
|
+
const titleClasses = `${baseClasses} ${className}`.trim()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<component :is="{{ as }}" class="{{ titleClasses }}">
|
|
10
|
+
<slot />
|
|
11
|
+
</component>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const open = $props.open ?? false
|
|
3
|
+
export const onClose = $props.onClose || (() => {})
|
|
4
|
+
export const position = $props.position || 'right'
|
|
5
|
+
export const title = $props.title || ''
|
|
6
|
+
export const className = $props.className || ''
|
|
7
|
+
|
|
8
|
+
// Position classes
|
|
9
|
+
const positionClasses = {
|
|
10
|
+
right: 'inset-y-0 right-0 pl-10 sm:pl-16',
|
|
11
|
+
left: 'inset-y-0 left-0 pr-10 sm:pr-16',
|
|
12
|
+
top: 'inset-x-0 top-0 pb-10',
|
|
13
|
+
bottom: 'inset-x-0 bottom-0 pt-10',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Slide animation classes
|
|
17
|
+
const slideClasses = {
|
|
18
|
+
right: {
|
|
19
|
+
enter: 'translate-x-full',
|
|
20
|
+
leave: 'translate-x-0',
|
|
21
|
+
},
|
|
22
|
+
left: {
|
|
23
|
+
enter: '-translate-x-full',
|
|
24
|
+
leave: 'translate-x-0',
|
|
25
|
+
},
|
|
26
|
+
top: {
|
|
27
|
+
enter: '-translate-y-full',
|
|
28
|
+
leave: 'translate-y-0',
|
|
29
|
+
},
|
|
30
|
+
bottom: {
|
|
31
|
+
enter: 'translate-y-full',
|
|
32
|
+
leave: 'translate-y-0',
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Size classes based on position
|
|
37
|
+
const sizeClasses = {
|
|
38
|
+
right: 'max-w-md w-screen',
|
|
39
|
+
left: 'max-w-md w-screen',
|
|
40
|
+
top: 'max-h-[90vh] w-full',
|
|
41
|
+
bottom: 'max-h-[90vh] w-full',
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Close button position
|
|
45
|
+
const closeButtonPosition = {
|
|
46
|
+
right: 'left-0 -ml-8 sm:-ml-10',
|
|
47
|
+
left: 'right-0 -mr-8 sm:-mr-10',
|
|
48
|
+
top: 'right-0 -mr-8',
|
|
49
|
+
bottom: 'right-0 -mr-8',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const containerClasses = `pointer-events-none fixed ${positionClasses[position]} flex max-w-full`.trim()
|
|
53
|
+
export const panelClasses = `pointer-events-auto relative ${sizeClasses[position]} ${className}`.trim()
|
|
54
|
+
export const slideAnimation = slideClasses[position]
|
|
55
|
+
export const closeButtonClasses = `absolute top-0 ${closeButtonPosition[position]} flex pt-4 pr-2 sm:pr-4`.trim()
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
@if(open)
|
|
59
|
+
<!-- Backdrop -->
|
|
60
|
+
<div
|
|
61
|
+
class="fixed inset-0 z-50 bg-gray-500/75 dark:bg-gray-900/75 transition-opacity duration-500"
|
|
62
|
+
style="animation: fadeIn 0.5s ease-in-out"
|
|
63
|
+
onclick="handleBackdropClick()"
|
|
64
|
+
></div>
|
|
65
|
+
|
|
66
|
+
<!-- Drawer Container -->
|
|
67
|
+
<div class="fixed inset-0 z-50 overflow-hidden">
|
|
68
|
+
<div class="absolute inset-0 overflow-hidden">
|
|
69
|
+
<div class="{{ containerClasses }}">
|
|
70
|
+
<!-- Drawer Panel -->
|
|
71
|
+
<div
|
|
72
|
+
class="{{ panelClasses }}"
|
|
73
|
+
style="animation: slideIn 0.5s ease-in-out"
|
|
74
|
+
>
|
|
75
|
+
<!-- Close Button -->
|
|
76
|
+
<div class="{{ closeButtonClasses }}">
|
|
77
|
+
<button
|
|
78
|
+
type="button"
|
|
79
|
+
class="relative rounded-md text-gray-300 dark:text-gray-400 hover:text-white dark:hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
|
|
80
|
+
onclick="handleClose()"
|
|
81
|
+
>
|
|
82
|
+
<span class="absolute -inset-2.5"></span>
|
|
83
|
+
<span class="sr-only">Close panel</span>
|
|
84
|
+
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
|
85
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
86
|
+
</svg>
|
|
87
|
+
</button>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<!-- Drawer Content -->
|
|
91
|
+
<div class="relative flex h-full flex-col overflow-y-auto bg-white dark:bg-blue-gray-800 py-6 shadow-xl">
|
|
92
|
+
@if(title)
|
|
93
|
+
<div class="px-4 sm:px-6">
|
|
94
|
+
<h2 class="text-base font-semibold text-gray-900 dark:text-gray-100">
|
|
95
|
+
{{ title }}
|
|
96
|
+
</h2>
|
|
97
|
+
</div>
|
|
98
|
+
@endif
|
|
99
|
+
<div class="relative mt-6 flex-1 px-4 sm:px-6">
|
|
100
|
+
<slot />
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
@endif
|
|
108
|
+
|
|
109
|
+
<style>
|
|
110
|
+
@keyframes fadeIn {
|
|
111
|
+
from { opacity: 0; }
|
|
112
|
+
to { opacity: 1; }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@keyframes slideIn {
|
|
116
|
+
from {
|
|
117
|
+
transform: {{ position === 'right' ? 'translateX(100%)' : position === 'left' ? 'translateX(-100%)' : position === 'top' ? 'translateY(-100%)' : 'translateY(100%)' }};
|
|
118
|
+
}
|
|
119
|
+
to {
|
|
120
|
+
transform: translate(0, 0);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
</style>
|
|
124
|
+
|
|
125
|
+
<script>
|
|
126
|
+
function handleClose() {
|
|
127
|
+
if (onClose) {
|
|
128
|
+
onClose()
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function handleBackdropClick() {
|
|
133
|
+
if (onClose) {
|
|
134
|
+
onClose()
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
</script>
|