@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,39 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { CodeBlock } from './CodeBlock.stx'
|
|
3
|
+
|
|
4
|
+
export const packageName = $props.packageName || '@stacksjs/component'
|
|
5
|
+
export const installCode = `bun add ${packageName}`
|
|
6
|
+
export const npmCode = `npm install ${packageName}`
|
|
7
|
+
export const pnpmCode = `pnpm add ${packageName}`
|
|
8
|
+
export const yarnCode = `yarn add ${packageName}`
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<div class="installation">
|
|
12
|
+
<h2 class="my-2 text-lg font-semibold">Installation</h2>
|
|
13
|
+
|
|
14
|
+
<p class="my-3 text-base">
|
|
15
|
+
Install the component using your preferred package manager:
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<div class="space-y-4">
|
|
19
|
+
<div>
|
|
20
|
+
<h3 class="text-sm font-medium mb-2 text-neutral-700 dark:text-neutral-300">Bun (recommended)</h3>
|
|
21
|
+
@component('CodeBlock', { code: installCode, language: 'bash' })
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div>
|
|
25
|
+
<h3 class="text-sm font-medium mb-2 text-neutral-700 dark:text-neutral-300">npm</h3>
|
|
26
|
+
@component('CodeBlock', { code: npmCode, language: 'bash' })
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div>
|
|
30
|
+
<h3 class="text-sm font-medium mb-2 text-neutral-700 dark:text-neutral-300">pnpm</h3>
|
|
31
|
+
@component('CodeBlock', { code: pnpmCode, language: 'bash' })
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div>
|
|
35
|
+
<h3 class="text-sm font-medium mb-2 text-neutral-700 dark:text-neutral-300">Yarn</h3>
|
|
36
|
+
@component('CodeBlock', { code: yarnCode, language: 'bash' })
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const value = $props.value
|
|
3
|
+
export const onChange = $props.onChange
|
|
4
|
+
export const multiple = $props.multiple || false
|
|
5
|
+
export const className = $props.className || ''
|
|
6
|
+
export const as = $props.as || 'div'
|
|
7
|
+
|
|
8
|
+
const baseClasses = 'relative'
|
|
9
|
+
const listboxClasses = `${baseClasses} ${className}`.trim()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<component :is="{{ as }}" class="{{ listboxClasses }}">
|
|
13
|
+
<slot :value="value" :onChange="onChange" :multiple="multiple" />
|
|
14
|
+
</component>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'button'
|
|
4
|
+
export const disabled = $props.disabled || false
|
|
5
|
+
|
|
6
|
+
const baseClasses = 'relative w-full cursor-pointer rounded-lg bg-white dark:bg-neutral-800 py-2 pl-3 pr-10 text-left shadow-md 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 focus-visible:ring-offset-blue-300'
|
|
7
|
+
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
|
|
8
|
+
const buttonClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<component
|
|
12
|
+
:is="{{ as }}"
|
|
13
|
+
class="{{ buttonClasses }}"
|
|
14
|
+
@if(disabled)disabled aria-disabled="true"@endif
|
|
15
|
+
>
|
|
16
|
+
<slot />
|
|
17
|
+
</component>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const as = $props.as || 'label'
|
|
4
|
+
|
|
5
|
+
const baseClasses = 'block text-sm font-medium text-neutral-900 dark:text-white'
|
|
6
|
+
const labelClasses = `${baseClasses} ${className}`.trim()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<component :is="{{ as }}" class="{{ labelClasses }}">
|
|
10
|
+
<slot />
|
|
11
|
+
</component>
|
|
@@ -0,0 +1,57 @@
|
|
|
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 = Array.isArray(currentValue)
|
|
11
|
+
? currentValue.includes(value)
|
|
12
|
+
: currentValue === value
|
|
13
|
+
|
|
14
|
+
const baseClasses = 'relative cursor-pointer select-none py-2 pl-10 pr-4'
|
|
15
|
+
const stateClasses = active
|
|
16
|
+
? 'bg-blue-100 text-blue-900 dark:bg-blue-900 dark:text-blue-100'
|
|
17
|
+
: 'text-neutral-900 dark:text-neutral-100'
|
|
18
|
+
const disabledClasses = disabled
|
|
19
|
+
? 'opacity-50 cursor-not-allowed'
|
|
20
|
+
: ''
|
|
21
|
+
|
|
22
|
+
const optionClasses = `${baseClasses} ${stateClasses} ${disabledClasses} ${className}`.trim()
|
|
23
|
+
|
|
24
|
+
export function handleClick() {
|
|
25
|
+
if (disabled) return
|
|
26
|
+
onChange?.(value)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function handleMouseEnter() {
|
|
30
|
+
if (!disabled) active = true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function handleMouseLeave() {
|
|
34
|
+
active = false
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<component
|
|
39
|
+
:is="{{ as }}"
|
|
40
|
+
class="{{ optionClasses }}"
|
|
41
|
+
role="option"
|
|
42
|
+
aria-selected="{{ selected ? 'true' : 'false' }}"
|
|
43
|
+
@if(disabled)aria-disabled="true"@endif
|
|
44
|
+
@click="handleClick"
|
|
45
|
+
@mouseenter="handleMouseEnter"
|
|
46
|
+
@mouseleave="handleMouseLeave"
|
|
47
|
+
>
|
|
48
|
+
@if(selected)
|
|
49
|
+
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600 dark:text-blue-400">
|
|
50
|
+
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
51
|
+
<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" />
|
|
52
|
+
</svg>
|
|
53
|
+
</span>
|
|
54
|
+
@endif
|
|
55
|
+
|
|
56
|
+
<slot :active="active" :selected="selected" :disabled="disabled" />
|
|
57
|
+
</component>
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
|
11
|
+
:is="{{ as }}"
|
|
12
|
+
class="{{ optionsClasses }}"
|
|
13
|
+
role="listbox"
|
|
14
|
+
>
|
|
15
|
+
<slot />
|
|
16
|
+
</component>
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const showLogo = $props.showLogo ?? true
|
|
3
|
+
export const headingText = $props.headingText || 'Sign in to your account'
|
|
4
|
+
export const showSocialLogin = $props.showSocialLogin ?? true
|
|
5
|
+
export const showRememberMe = $props.showRememberMe ?? true
|
|
6
|
+
export const showForgotPassword = $props.showForgotPassword ?? true
|
|
7
|
+
export const showSignup = $props.showSignup ?? true
|
|
8
|
+
export const signupText = $props.signupText || 'Start a 14 day free trial'
|
|
9
|
+
export const onSubmit = $props.onSubmit || (() => {})
|
|
10
|
+
export const className = $props.className || ''
|
|
11
|
+
|
|
12
|
+
export const containerClasses = `min-h-full flex flex-col justify-center py-12 lg:px-8 sm:px-6 dark:bg-blue-gray-900 ${className}`.trim()
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div class="{{ containerClasses }}">
|
|
16
|
+
<div class="sm:mx-auto sm:max-w-md sm:w-full">
|
|
17
|
+
@if(showLogo)
|
|
18
|
+
<img src="/logo.svg" alt="Logo" class="mx-auto h-11 w-auto" />
|
|
19
|
+
@endif
|
|
20
|
+
<h2 class="mt-6 text-center text-2xl text-gray-900 dark:text-gray-100 font-bold leading-9 tracking-tight">
|
|
21
|
+
{{ headingText }}
|
|
22
|
+
</h2>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<form onsubmit="event.preventDefault(); handleSubmit(event)">
|
|
26
|
+
<div class="mt-10 sm:mx-auto sm:max-w-[480px] sm:w-full">
|
|
27
|
+
<div class="bg-white dark:bg-blue-gray-800 px-6 py-12 shadow sm:rounded-lg sm:px-12">
|
|
28
|
+
<div class="space-y-6">
|
|
29
|
+
<div>
|
|
30
|
+
<label for="email" class="block text-sm text-gray-900 dark:text-gray-100 font-medium leading-6">
|
|
31
|
+
Email address
|
|
32
|
+
</label>
|
|
33
|
+
<div class="mt-2">
|
|
34
|
+
<input
|
|
35
|
+
id="email"
|
|
36
|
+
name="email"
|
|
37
|
+
type="email"
|
|
38
|
+
autocomplete="email"
|
|
39
|
+
required
|
|
40
|
+
class="block w-full border-0 rounded-md py-1.5 text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-gray-300 dark:ring-gray-600 ring-inset sm:text-sm placeholder:text-gray-400 dark:placeholder:text-gray-500 sm:leading-6 focus:ring-2 focus:ring-indigo-600 focus:ring-inset dark:bg-blue-gray-700"
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div>
|
|
46
|
+
<label for="password" class="block text-sm text-gray-900 dark:text-gray-100 font-medium leading-6">
|
|
47
|
+
Password
|
|
48
|
+
</label>
|
|
49
|
+
<div class="mt-2">
|
|
50
|
+
<input
|
|
51
|
+
id="password"
|
|
52
|
+
name="password"
|
|
53
|
+
type="password"
|
|
54
|
+
autocomplete="current-password"
|
|
55
|
+
required
|
|
56
|
+
class="block w-full border-0 rounded-md py-1.5 text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-gray-300 dark:ring-gray-600 ring-inset sm:text-sm placeholder:text-gray-400 dark:placeholder:text-gray-500 sm:leading-6 focus:ring-2 focus:ring-indigo-600 focus:ring-inset dark:bg-blue-gray-700"
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="flex items-center justify-between">
|
|
62
|
+
@if(showRememberMe)
|
|
63
|
+
<div class="flex items-center">
|
|
64
|
+
<input
|
|
65
|
+
id="remember-me"
|
|
66
|
+
name="remember-me"
|
|
67
|
+
type="checkbox"
|
|
68
|
+
class="h-4 w-4 border-gray-300 dark:border-gray-600 rounded text-indigo-600 focus:ring-indigo-600 dark:bg-blue-gray-700"
|
|
69
|
+
/>
|
|
70
|
+
<label for="remember-me" class="ml-3 block text-sm text-gray-900 dark:text-gray-100 leading-6">
|
|
71
|
+
Remember me
|
|
72
|
+
</label>
|
|
73
|
+
</div>
|
|
74
|
+
@endif
|
|
75
|
+
|
|
76
|
+
@if(showForgotPassword)
|
|
77
|
+
<div class="text-sm leading-6">
|
|
78
|
+
<a href="#" class="text-indigo-600 dark:text-indigo-400 font-semibold hover:text-indigo-500 dark:hover:text-indigo-300">
|
|
79
|
+
Forgot password?
|
|
80
|
+
</a>
|
|
81
|
+
</div>
|
|
82
|
+
@endif
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div>
|
|
86
|
+
<button
|
|
87
|
+
type="submit"
|
|
88
|
+
class="w-full flex justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm text-white font-semibold leading-6 shadow-sm hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-indigo-600 focus-visible:outline-offset-2 focus-visible:outline"
|
|
89
|
+
>
|
|
90
|
+
Sign in
|
|
91
|
+
</button>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
@if(showSocialLogin)
|
|
96
|
+
<div>
|
|
97
|
+
<div class="relative mt-10">
|
|
98
|
+
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
|
99
|
+
<div class="w-full border-t border-gray-200 dark:border-gray-600"></div>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="relative flex justify-center text-sm font-medium leading-6">
|
|
102
|
+
<span class="bg-white dark:bg-blue-gray-800 px-6 text-gray-900 dark:text-gray-100">
|
|
103
|
+
Or continue with
|
|
104
|
+
</span>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div class="grid grid-cols-2 mt-6 gap-4">
|
|
109
|
+
<a
|
|
110
|
+
href="#"
|
|
111
|
+
class="w-full flex items-center justify-center gap-3 rounded-md bg-white dark:bg-blue-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 font-semibold shadow-sm ring-1 ring-gray-300 dark:ring-gray-600 ring-inset hover:bg-gray-50 dark:hover:bg-blue-gray-600 focus-visible:ring-transparent"
|
|
112
|
+
>
|
|
113
|
+
<svg class="h-5 w-5" viewBox="0 0 24 24" aria-hidden="true">
|
|
114
|
+
<path d="M12.0003 4.75C13.7703 4.75 15.3553 5.36002 16.6053 6.54998L20.0303 3.125C17.9502 1.19 15.2353 0 12.0003 0C7.31028 0 3.25527 2.69 1.28027 6.60998L5.27028 9.70498C6.21525 6.86002 8.87028 4.75 12.0003 4.75Z" fill="#EA4335" />
|
|
115
|
+
<path d="M23.49 12.275C23.49 11.49 23.415 10.73 23.3 10H12V14.51H18.47C18.18 15.99 17.34 17.25 16.08 18.1L19.945 21.1C22.2 19.01 23.49 15.92 23.49 12.275Z" fill="#4285F4" />
|
|
116
|
+
<path d="M5.26498 14.2949C5.02498 13.5699 4.88501 12.7999 4.88501 11.9999C4.88501 11.1999 5.01998 10.4299 5.26498 9.7049L1.275 6.60986C0.46 8.22986 0 10.0599 0 11.9999C0 13.9399 0.46 15.7699 1.28 17.3899L5.26498 14.2949Z" fill="#FBBC05" />
|
|
117
|
+
<path d="M12.0004 24.0001C15.2404 24.0001 17.9654 22.935 19.9454 21.095L16.0804 18.095C15.0054 18.82 13.6204 19.245 12.0004 19.245C8.8704 19.245 6.21537 17.135 5.2654 14.29L1.27539 17.385C3.25539 21.31 7.3104 24.0001 12.0004 24.0001Z" fill="#34A853" />
|
|
118
|
+
</svg>
|
|
119
|
+
<span class="text-sm font-semibold leading-6">Google</span>
|
|
120
|
+
</a>
|
|
121
|
+
|
|
122
|
+
<a
|
|
123
|
+
href="#"
|
|
124
|
+
class="w-full flex items-center justify-center gap-3 rounded-md bg-white dark:bg-blue-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 font-semibold shadow-sm ring-1 ring-gray-300 dark:ring-gray-600 ring-inset hover:bg-gray-50 dark:hover:bg-blue-gray-600 focus-visible:ring-transparent"
|
|
125
|
+
>
|
|
126
|
+
<svg class="h-5 w-5 fill-[#24292F]" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
127
|
+
<path fill-rule="evenodd" d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z" clip-rule="evenodd" />
|
|
128
|
+
</svg>
|
|
129
|
+
<span class="text-sm font-semibold leading-6">GitHub</span>
|
|
130
|
+
</a>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
@endif
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
@if(showSignup)
|
|
137
|
+
<p class="mt-10 text-center text-sm text-gray-500 dark:text-gray-400">
|
|
138
|
+
Not a member?
|
|
139
|
+
<a href="#" class="text-indigo-600 dark:text-indigo-400 font-semibold leading-6 hover:text-indigo-500 dark:hover:text-indigo-300">
|
|
140
|
+
{{ signupText }}
|
|
141
|
+
</a>
|
|
142
|
+
</p>
|
|
143
|
+
@endif
|
|
144
|
+
</div>
|
|
145
|
+
</form>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<script>
|
|
149
|
+
function handleSubmit(event) {
|
|
150
|
+
const formData = new FormData(event.target)
|
|
151
|
+
const email = formData.get('email')
|
|
152
|
+
const password = formData.get('password')
|
|
153
|
+
|
|
154
|
+
if (onSubmit) {
|
|
155
|
+
onSubmit({ email, password })
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Clear password after submission
|
|
159
|
+
setTimeout(() => {
|
|
160
|
+
event.target.querySelector('#password').value = ''
|
|
161
|
+
}, 1000)
|
|
162
|
+
}
|
|
163
|
+
</script>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
// Navigator Component Props
|
|
3
|
+
export const items = $props.items || []
|
|
4
|
+
export const active = $props.active || ''
|
|
5
|
+
export const orientation = $props.orientation || 'horizontal' // 'horizontal' | 'vertical'
|
|
6
|
+
export const variant = $props.variant || 'default' // 'default' | 'pills' | 'underline' | 'sidebar'
|
|
7
|
+
export const size = $props.size || 'md' // 'sm' | 'md' | 'lg'
|
|
8
|
+
export const onNavigate = $props.onNavigate
|
|
9
|
+
export const className = $props.className || ''
|
|
10
|
+
|
|
11
|
+
// Helper function to check if item is active
|
|
12
|
+
function isActive(item) {
|
|
13
|
+
if (typeof item.href === 'string' && typeof active === 'string') {
|
|
14
|
+
// Exact match
|
|
15
|
+
if (item.href === active) return true
|
|
16
|
+
// Match with query params/hash
|
|
17
|
+
if (active.startsWith(item.href)) return true
|
|
18
|
+
}
|
|
19
|
+
if (item.id && item.id === active) return true
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Base classes
|
|
24
|
+
const containerBaseClasses = orientation === 'horizontal'
|
|
25
|
+
? 'flex items-center'
|
|
26
|
+
: 'flex flex-col'
|
|
27
|
+
|
|
28
|
+
const containerClasses = `${containerBaseClasses} ${className}`.trim()
|
|
29
|
+
|
|
30
|
+
// Item classes based on variant and size
|
|
31
|
+
function getItemClasses(item) {
|
|
32
|
+
const active = isActive(item)
|
|
33
|
+
let classes = ''
|
|
34
|
+
|
|
35
|
+
// Size classes
|
|
36
|
+
const sizeClasses = {
|
|
37
|
+
sm: 'px-2 py-1 text-sm',
|
|
38
|
+
md: 'px-3 py-2 text-base',
|
|
39
|
+
lg: 'px-4 py-3 text-lg',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
classes += sizeClasses[size] || sizeClasses.md
|
|
43
|
+
|
|
44
|
+
// Variant classes
|
|
45
|
+
if (variant === 'default') {
|
|
46
|
+
classes += active
|
|
47
|
+
? ' text-gray-900 dark:text-gray-100 font-medium'
|
|
48
|
+
: ' text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
|
|
49
|
+
} else if (variant === 'pills') {
|
|
50
|
+
classes += active
|
|
51
|
+
? ' bg-blue-600 text-white font-medium rounded-full'
|
|
52
|
+
: ' text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full'
|
|
53
|
+
} else if (variant === 'underline') {
|
|
54
|
+
classes += active
|
|
55
|
+
? ' text-blue-600 dark:text-blue-400 font-medium border-b-2 border-blue-600 dark:border-blue-400'
|
|
56
|
+
: ' text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 border-b-2 border-transparent'
|
|
57
|
+
} else if (variant === 'sidebar') {
|
|
58
|
+
classes += active
|
|
59
|
+
? ' bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-medium border-l-4 border-blue-600 dark:border-blue-400'
|
|
60
|
+
: ' text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 border-l-4 border-transparent'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Common classes
|
|
64
|
+
classes += ' transition-all duration-200 cursor-pointer flex items-center gap-2'
|
|
65
|
+
|
|
66
|
+
if (item.disabled) {
|
|
67
|
+
classes += ' opacity-50 cursor-not-allowed pointer-events-none'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return classes.trim()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Gap classes between items
|
|
74
|
+
const gapClasses = orientation === 'horizontal'
|
|
75
|
+
? 'gap-1'
|
|
76
|
+
: 'gap-0.5'
|
|
77
|
+
|
|
78
|
+
function handleClick(item, event) {
|
|
79
|
+
if (item.disabled) {
|
|
80
|
+
event.preventDefault()
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (onNavigate) {
|
|
85
|
+
event.preventDefault()
|
|
86
|
+
onNavigate(item)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<nav class="{{ containerClasses }} {{ gapClasses }}" role="navigation" aria-label="Main navigation">
|
|
92
|
+
@foreach(item in items)
|
|
93
|
+
@if(item.href)
|
|
94
|
+
<a
|
|
95
|
+
href="{{ item.href }}"
|
|
96
|
+
class="{{ getItemClasses(item) }}"
|
|
97
|
+
onclick="handleClick(item, event)"
|
|
98
|
+
@if(isActive(item))
|
|
99
|
+
aria-current="page"
|
|
100
|
+
@endif
|
|
101
|
+
@if(item.disabled)
|
|
102
|
+
aria-disabled="true"
|
|
103
|
+
tabindex="-1"
|
|
104
|
+
@endif
|
|
105
|
+
>
|
|
106
|
+
@if(item.icon)
|
|
107
|
+
<span class="flex-shrink-0" innerHTML="{!! item.icon !!}"></span>
|
|
108
|
+
@endif
|
|
109
|
+
<span>{{ item.label }}</span>
|
|
110
|
+
@if(item.badge)
|
|
111
|
+
<span class="ml-auto px-2 py-0.5 text-xs font-semibold rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300">
|
|
112
|
+
{{ item.badge }}
|
|
113
|
+
</span>
|
|
114
|
+
@endif
|
|
115
|
+
</a>
|
|
116
|
+
@else
|
|
117
|
+
<button
|
|
118
|
+
type="button"
|
|
119
|
+
class="{{ getItemClasses(item) }}"
|
|
120
|
+
onclick="handleClick(item, event)"
|
|
121
|
+
@if(item.disabled)
|
|
122
|
+
disabled
|
|
123
|
+
aria-disabled="true"
|
|
124
|
+
@endif
|
|
125
|
+
>
|
|
126
|
+
@if(item.icon)
|
|
127
|
+
<span class="flex-shrink-0" innerHTML="{!! item.icon !!}"></span>
|
|
128
|
+
@endif
|
|
129
|
+
<span>{{ item.label }}</span>
|
|
130
|
+
@if(item.badge)
|
|
131
|
+
<span class="ml-auto px-2 py-0.5 text-xs font-semibold rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300">
|
|
132
|
+
{{ item.badge }}
|
|
133
|
+
</span>
|
|
134
|
+
@endif
|
|
135
|
+
</button>
|
|
136
|
+
@endif
|
|
137
|
+
@endforeach
|
|
138
|
+
</nav>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const show = $props.show !== false
|
|
3
|
+
export const title = $props.title || ''
|
|
4
|
+
export const message = $props.message || ''
|
|
5
|
+
export const type = $props.type || 'info'
|
|
6
|
+
export const position = $props.position || 'top-right'
|
|
7
|
+
export const duration = $props.duration || 5000
|
|
8
|
+
export const onClose = $props.onClose
|
|
9
|
+
export const className = $props.className || ''
|
|
10
|
+
|
|
11
|
+
const typeColors = {
|
|
12
|
+
info: 'bg-blue-50 text-blue-900 dark:bg-blue-900 dark:text-blue-100',
|
|
13
|
+
success: 'bg-green-50 text-green-900 dark:bg-green-900 dark:text-green-100',
|
|
14
|
+
warning: 'bg-yellow-50 text-yellow-900 dark:bg-yellow-900 dark:text-yellow-100',
|
|
15
|
+
error: 'bg-red-50 text-red-900 dark:bg-red-900 dark:text-red-100',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const positions = {
|
|
19
|
+
'top-left': 'top-0 left-0',
|
|
20
|
+
'top-right': 'top-0 right-0',
|
|
21
|
+
'top-center': 'top-0 left-1/2 -translate-x-1/2',
|
|
22
|
+
'bottom-left': 'bottom-0 left-0',
|
|
23
|
+
'bottom-right': 'bottom-0 right-0',
|
|
24
|
+
'bottom-center': 'bottom-0 left-1/2 -translate-x-1/2',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const baseClasses = 'fixed z-50 m-4 max-w-md w-full pointer-events-auto rounded-lg p-4 shadow-lg ring-1 ring-black ring-opacity-5 transition-all'
|
|
28
|
+
const notificationClasses = `${baseClasses} ${typeColors[type]} ${positions[position]} ${className}`.trim()
|
|
29
|
+
|
|
30
|
+
export function handleClose() {
|
|
31
|
+
onClose?.()
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
@if(show)
|
|
36
|
+
<div class="{{ notificationClasses }}" role="alert">
|
|
37
|
+
<div class="flex items-start">
|
|
38
|
+
<div class="flex-1">
|
|
39
|
+
@if(title)
|
|
40
|
+
<p class="text-sm font-medium">{{ title }}</p>
|
|
41
|
+
@endif
|
|
42
|
+
@if(message)
|
|
43
|
+
<p class="mt-1 text-sm {{ title ? 'opacity-90' : '' }}">{{ message }}</p>
|
|
44
|
+
@endif
|
|
45
|
+
@if(!title && !message)
|
|
46
|
+
<slot />
|
|
47
|
+
@endif
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
@click="handleClose"
|
|
53
|
+
class="ml-4 inline-flex rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2"
|
|
54
|
+
>
|
|
55
|
+
<span class="sr-only">Close</span>
|
|
56
|
+
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
57
|
+
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
|
|
58
|
+
</svg>
|
|
59
|
+
</button>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<script>
|
|
64
|
+
// Auto-hide after duration (client-side only)
|
|
65
|
+
if (typeof window !== 'undefined' && duration > 0) {
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
handleClose()
|
|
68
|
+
}, duration)
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
@endif
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const value = $props.value || ''
|
|
3
|
+
export const onChange = $props.onChange || (() => {})
|
|
4
|
+
export const placeholder = $props.placeholder || '0'
|
|
5
|
+
export const disabled = $props.disabled || false
|
|
6
|
+
export const readonly = $props.readonly || false
|
|
7
|
+
export const size = $props.size || 'md'
|
|
8
|
+
export const error = $props.error || false
|
|
9
|
+
export const label = $props.label || ''
|
|
10
|
+
export const helperText = $props.helperText || ''
|
|
11
|
+
export const required = $props.required || false
|
|
12
|
+
export const min = $props.min
|
|
13
|
+
export const max = $props.max
|
|
14
|
+
export const step = $props.step || 1
|
|
15
|
+
export const showControls = $props.showControls ?? true
|
|
16
|
+
export const className = $props.className || ''
|
|
17
|
+
export const inputClassName = $props.inputClassName || ''
|
|
18
|
+
|
|
19
|
+
// Size classes
|
|
20
|
+
const sizeClasses = {
|
|
21
|
+
sm: 'px-3 py-1.5 text-sm h-8',
|
|
22
|
+
md: 'px-4 py-2 text-base h-10',
|
|
23
|
+
lg: 'px-5 py-3 text-lg h-12',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Base and state classes
|
|
27
|
+
const baseClasses = 'block w-full border-0 rounded-md shadow-sm ring-1 ring-inset transition-colors duration-200 focus:ring-2 focus:ring-inset dark:bg-blue-gray-700 dark:text-gray-100'
|
|
28
|
+
|
|
29
|
+
const stateClasses = error
|
|
30
|
+
? 'ring-red-300 dark:ring-red-600 text-red-900 dark:text-red-300 placeholder-red-300 dark:placeholder-red-500 focus:ring-red-500 dark:focus:ring-red-400'
|
|
31
|
+
: 'ring-gray-300 dark:ring-gray-600 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-indigo-600 dark:focus:ring-indigo-400'
|
|
32
|
+
|
|
33
|
+
const disabledClasses = disabled
|
|
34
|
+
? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
|
|
35
|
+
: readonly
|
|
36
|
+
? 'bg-gray-50 dark:bg-gray-800 cursor-default'
|
|
37
|
+
: 'bg-white dark:bg-blue-gray-700'
|
|
38
|
+
|
|
39
|
+
const paddingClasses = showControls ? 'pr-10' : ''
|
|
40
|
+
|
|
41
|
+
export const inputClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses} ${paddingClasses} ${inputClassName}`.trim()
|
|
42
|
+
export const labelClasses = `block text-sm font-medium leading-6 mb-2 ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'}`.trim()
|
|
43
|
+
export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<div class="w-full {{ className }}">
|
|
47
|
+
@if(label)
|
|
48
|
+
<label for="number-input" class="{{ labelClasses }}">
|
|
49
|
+
{{ label }}
|
|
50
|
+
@if(required)
|
|
51
|
+
<span class="text-red-500 ml-1">*</span>
|
|
52
|
+
@endif
|
|
53
|
+
</label>
|
|
54
|
+
@endif
|
|
55
|
+
|
|
56
|
+
<div class="relative">
|
|
57
|
+
<input
|
|
58
|
+
type="number"
|
|
59
|
+
id="number-input"
|
|
60
|
+
class="{{ inputClasses }}"
|
|
61
|
+
value="{{ value }}"
|
|
62
|
+
placeholder="{{ placeholder }}"
|
|
63
|
+
disabled="{{ disabled }}"
|
|
64
|
+
readonly="{{ readonly }}"
|
|
65
|
+
required="{{ required }}"
|
|
66
|
+
@if(min !== undefined)min="{{ min }}"@endif
|
|
67
|
+
@if(max !== undefined)max="{{ max }}"@endif
|
|
68
|
+
step="{{ step }}"
|
|
69
|
+
oninput="handleInput(event)"
|
|
70
|
+
aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
71
|
+
@if(helperText)aria-describedby="helper-text"@endif
|
|
72
|
+
/>
|
|
73
|
+
|
|
74
|
+
@if(showControls && !disabled && !readonly)
|
|
75
|
+
<!-- Increment/Decrement controls -->
|
|
76
|
+
<div class="absolute inset-y-0 right-0 flex flex-col">
|
|
77
|
+
<button
|
|
78
|
+
type="button"
|
|
79
|
+
onclick="handleIncrement()"
|
|
80
|
+
class="flex items-center justify-center w-8 h-1/2 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 focus:outline-none border-b border-gray-300 dark:border-gray-600"
|
|
81
|
+
aria-label="Increment"
|
|
82
|
+
>
|
|
83
|
+
<svg class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
84
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
|
|
85
|
+
</svg>
|
|
86
|
+
</button>
|
|
87
|
+
<button
|
|
88
|
+
type="button"
|
|
89
|
+
onclick="handleDecrement()"
|
|
90
|
+
class="flex items-center justify-center w-8 h-1/2 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 focus:outline-none"
|
|
91
|
+
aria-label="Decrement"
|
|
92
|
+
>
|
|
93
|
+
<svg class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
94
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
|
95
|
+
</svg>
|
|
96
|
+
</button>
|
|
97
|
+
</div>
|
|
98
|
+
@endif
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
@if(helperText)
|
|
102
|
+
<p id="helper-text" class="{{ helperClasses }}">
|
|
103
|
+
{{ helperText }}
|
|
104
|
+
</p>
|
|
105
|
+
@endif
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<script>
|
|
109
|
+
function handleInput(event) {
|
|
110
|
+
const newValue = event.target.value
|
|
111
|
+
|
|
112
|
+
if (onChange) {
|
|
113
|
+
onChange(newValue)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function handleIncrement() {
|
|
118
|
+
const currentValue = parseFloat(value) || 0
|
|
119
|
+
const newValue = currentValue + step
|
|
120
|
+
|
|
121
|
+
if (max !== undefined && newValue > max) return
|
|
122
|
+
|
|
123
|
+
if (onChange) {
|
|
124
|
+
onChange(String(newValue))
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function handleDecrement() {
|
|
129
|
+
const currentValue = parseFloat(value) || 0
|
|
130
|
+
const newValue = currentValue - step
|
|
131
|
+
|
|
132
|
+
if (min !== undefined && newValue < min) return
|
|
133
|
+
|
|
134
|
+
if (onChange) {
|
|
135
|
+
onChange(String(newValue))
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
</script>
|