@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
package/README.md
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# @stacksjs/components
|
|
2
|
+
|
|
3
|
+
A modern, accessible component library built with STX, featuring headwind utility classes and TypeScript syntax highlighting.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 Built with STX templating engine
|
|
8
|
+
- 🎨 Styled with headwind utility-first CSS
|
|
9
|
+
- 🎯 TypeScript syntax highlighting with ts-syntax-highlighter
|
|
10
|
+
- ♿ Accessible by default (WAI-ARIA compliant)
|
|
11
|
+
- 🌙 Dark mode support
|
|
12
|
+
- 📦 Tree-shakeable
|
|
13
|
+
- 🔧 Fully customizable
|
|
14
|
+
- ⚡ Optimized for performance
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
bun add @stacksjs/components
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or with other package managers:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @stacksjs/components
|
|
26
|
+
pnpm add @stacksjs/components
|
|
27
|
+
yarn add @stacksjs/components
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Components
|
|
31
|
+
|
|
32
|
+
### UI Components (35)
|
|
33
|
+
|
|
34
|
+
- **Accordion** - Expandable content sections with keyboard navigation
|
|
35
|
+
- **Auth** - Login, Signup, and 2FA components
|
|
36
|
+
- **Audio** - Audio player with waveform visualization
|
|
37
|
+
- **Avatar** - User avatars with fallback initials and status indicators
|
|
38
|
+
- **Badge** - Labels and tags with color variants and removable option
|
|
39
|
+
- **Breadcrumb** - Navigation breadcrumbs with collapse support
|
|
40
|
+
- **Button** - Versatile button with loading, icons, 5 sizes (xs-xl), full-width
|
|
41
|
+
- **Calendar** - Date picker with localization, min/max dates, disabled dates, dark mode ✨ NEW
|
|
42
|
+
- **Card** - Content cards with images, variants, and hover effects
|
|
43
|
+
- **Drawer** - Slide-out panel from any direction
|
|
44
|
+
- **Form** - Form wrapper with validation, error handling, and submit management
|
|
45
|
+
- **Image** - Optimized images with lazy loading, srcset, WebP, blur placeholder
|
|
46
|
+
- **Pagination** - Page navigation with customizable display
|
|
47
|
+
- **Portal** - Render content outside DOM hierarchy
|
|
48
|
+
- **Teleport** - Move content to different DOM nodes
|
|
49
|
+
- **Payment** - Stripe checkout and payment management (3 components)
|
|
50
|
+
- **Progress** - Linear and circular progress indicators
|
|
51
|
+
- **Select** - Native-style select dropdown
|
|
52
|
+
- **Skeleton** - Loading placeholders with multiple variants
|
|
53
|
+
- **Spinner** - Loading spinners with multiple styles (circle, dots, bars, ring)
|
|
54
|
+
- **Storage** - Enhanced storage with watch, compression, encryption, batch operations, quota checking
|
|
55
|
+
- **Switch** - Modern toggle switch component
|
|
56
|
+
- **Tabs** - Tabbed content with horizontal/vertical layouts and multiple variants
|
|
57
|
+
- **Tooltip** - Contextual tooltips with positioning options
|
|
58
|
+
- **Video** - Video player with aspect ratio support
|
|
59
|
+
- **VirtualList** - Windowed list for rendering large datasets efficiently
|
|
60
|
+
- **VirtualTable** - Windowed table with columns for large datasets
|
|
61
|
+
- **Dropdown** - Menu dropdown component with keyboard navigation
|
|
62
|
+
- **Dialog** - Modal dialog component with backdrop
|
|
63
|
+
- **Radio Group** - Radio button group with single selection
|
|
64
|
+
- **Popover** - Floating panel component with positioning
|
|
65
|
+
- **Listbox** - Custom select component with keyboard support
|
|
66
|
+
- **Combobox** - Searchable select with filtering
|
|
67
|
+
- **Navigator** - Navigation component with 4 variants (default, pills, underline, sidebar), icons, badges ✨ NEW
|
|
68
|
+
- **Notification** - Toast notifications with auto-hide
|
|
69
|
+
- **Stepper** - Multi-step progress indicator
|
|
70
|
+
- **Transition** - Enter/leave animations with 7 presets, lifecycle hooks, and custom timing
|
|
71
|
+
- **Table** - Responsive table with sorting/filtering
|
|
72
|
+
- **Command Palette** - Searchable command menu
|
|
73
|
+
|
|
74
|
+
### Input Components (5)
|
|
75
|
+
|
|
76
|
+
- **TextInput** - Base input with icons, clear button, character counter
|
|
77
|
+
- **EmailInput** - Email input with validation
|
|
78
|
+
- **PasswordInput** - Password input with show/hide toggle & strength indicator
|
|
79
|
+
- **NumberInput** - Number input with increment/decrement controls
|
|
80
|
+
- **SearchInput** - Search with debounced callback
|
|
81
|
+
|
|
82
|
+
### Form Components (3)
|
|
83
|
+
|
|
84
|
+
- **Textarea** - Multi-line input with auto-resize
|
|
85
|
+
- **Checkbox** - Checkbox with indeterminate state
|
|
86
|
+
- **Radio** - Radio button with descriptions
|
|
87
|
+
|
|
88
|
+
### Utility Components
|
|
89
|
+
|
|
90
|
+
- **CodeBlock** - Syntax highlighted code blocks with copy functionality
|
|
91
|
+
- **Hero** - Hero section component
|
|
92
|
+
- **Footer** - Footer component with social links
|
|
93
|
+
- **Installation** - Installation instructions component
|
|
94
|
+
|
|
95
|
+
## Component Syntax
|
|
96
|
+
|
|
97
|
+
stx provides multiple ways to use components, giving you flexibility to choose the syntax that best fits your project:
|
|
98
|
+
|
|
99
|
+
### 1. @component Directive with Object Shorthand (Recommended)
|
|
100
|
+
|
|
101
|
+
The most concise syntax using ES6 object shorthand:
|
|
102
|
+
|
|
103
|
+
```stx
|
|
104
|
+
<script>
|
|
105
|
+
export const title = 'Welcome'
|
|
106
|
+
export const variant = 'primary'
|
|
107
|
+
export const onClick = () => console.log('clicked')
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
@component('Button', {
|
|
111
|
+
title,
|
|
112
|
+
variant,
|
|
113
|
+
onClick
|
|
114
|
+
})
|
|
115
|
+
@endcomponent
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 2. @component Directive with Full Props
|
|
119
|
+
|
|
120
|
+
Traditional explicit prop mapping:
|
|
121
|
+
|
|
122
|
+
```stx
|
|
123
|
+
@component('Button', {
|
|
124
|
+
title: title,
|
|
125
|
+
variant: variant,
|
|
126
|
+
onClick: onClick
|
|
127
|
+
})
|
|
128
|
+
@endcomponent
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 3. PascalCase Component Tags with Dynamic Binding (Vue-like)
|
|
132
|
+
|
|
133
|
+
Use `:prop` syntax for dynamic values from context:
|
|
134
|
+
|
|
135
|
+
```stx
|
|
136
|
+
<script>
|
|
137
|
+
export const title = 'Welcome'
|
|
138
|
+
export const variant = 'primary'
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<Button
|
|
142
|
+
:title="title"
|
|
143
|
+
:variant="variant"
|
|
144
|
+
:onClick="onClick"
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 4. PascalCase Component Tags with Static Values
|
|
149
|
+
|
|
150
|
+
Use regular attributes for static strings:
|
|
151
|
+
|
|
152
|
+
```stx
|
|
153
|
+
<Button
|
|
154
|
+
title="Welcome"
|
|
155
|
+
variant="primary"
|
|
156
|
+
/>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 5. Mixed Static and Dynamic Props
|
|
160
|
+
|
|
161
|
+
Combine static strings and dynamic bindings:
|
|
162
|
+
|
|
163
|
+
```stx
|
|
164
|
+
<Button
|
|
165
|
+
title="Static Title"
|
|
166
|
+
:variant="dynamicVariant"
|
|
167
|
+
size="large"
|
|
168
|
+
/>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
All these syntaxes are equivalent and fully interchangeable. Choose the one that fits your coding style!
|
|
172
|
+
|
|
173
|
+
## Usage
|
|
174
|
+
|
|
175
|
+
### Basic Example
|
|
176
|
+
|
|
177
|
+
```stx
|
|
178
|
+
<script>
|
|
179
|
+
import { Button, Switch } from '@stacksjs/components'
|
|
180
|
+
|
|
181
|
+
let notifications = true
|
|
182
|
+
|
|
183
|
+
function handleNotificationChange(checked) {
|
|
184
|
+
notifications = checked
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = { notifications, handleNotificationChange }
|
|
188
|
+
</script>
|
|
189
|
+
|
|
190
|
+
<div class="p-6">
|
|
191
|
+
<h1 class="text-2xl font-bold mb-4">Settings</h1>
|
|
192
|
+
|
|
193
|
+
@component('Switch', {
|
|
194
|
+
checked: notifications,
|
|
195
|
+
label: 'Enable notifications',
|
|
196
|
+
onChange: handleNotificationChange
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
<div class="mt-4">
|
|
200
|
+
@component('Button', { variant: 'primary' })
|
|
201
|
+
Save Changes
|
|
202
|
+
@endcomponent
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### With Code Highlighting
|
|
208
|
+
|
|
209
|
+
```stx
|
|
210
|
+
<script>
|
|
211
|
+
import { CodeBlock } from '@stacksjs/components'
|
|
212
|
+
|
|
213
|
+
const code = `
|
|
214
|
+
function greet(name: string) {
|
|
215
|
+
console.log(\`Hello, \${name}!\`)
|
|
216
|
+
}
|
|
217
|
+
`
|
|
218
|
+
|
|
219
|
+
module.exports = { code }
|
|
220
|
+
</script>
|
|
221
|
+
|
|
222
|
+
@component('CodeBlock', {
|
|
223
|
+
code: code,
|
|
224
|
+
language: 'typescript',
|
|
225
|
+
copyable: true
|
|
226
|
+
})
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Using Composables
|
|
230
|
+
|
|
231
|
+
```stx
|
|
232
|
+
<script>
|
|
233
|
+
import { useDarkMode, useCopyCode } from '@stacksjs/components'
|
|
234
|
+
|
|
235
|
+
const { isDark, toggle } = useDarkMode()
|
|
236
|
+
|
|
237
|
+
module.exports = { isDark, toggle }
|
|
238
|
+
</script>
|
|
239
|
+
|
|
240
|
+
<button @click="toggle">
|
|
241
|
+
@if(isDark)
|
|
242
|
+
Switch to Light Mode
|
|
243
|
+
@else
|
|
244
|
+
Switch to Dark Mode
|
|
245
|
+
@endif
|
|
246
|
+
</button>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Configuration
|
|
250
|
+
|
|
251
|
+
### Headwind Configuration
|
|
252
|
+
|
|
253
|
+
The components use headwind for utility classes. You can customize the design system by creating a `headwind.config.ts` file:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
import type { HeadwindConfig } from '@stacksjs/headwind'
|
|
257
|
+
|
|
258
|
+
export default {
|
|
259
|
+
theme: {
|
|
260
|
+
extend: {
|
|
261
|
+
colors: {
|
|
262
|
+
primary: {
|
|
263
|
+
500: '#your-color',
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
} satisfies HeadwindConfig
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Syntax Highlighting Themes
|
|
272
|
+
|
|
273
|
+
Configure syntax highlighting themes for code blocks:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import { createHighlighter } from 'ts-syntax-highlighter'
|
|
277
|
+
|
|
278
|
+
const highlighter = await createHighlighter({
|
|
279
|
+
themes: ['github-light', 'github-dark'],
|
|
280
|
+
languages: ['typescript', 'javascript', 'html'],
|
|
281
|
+
})
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Component APIs
|
|
285
|
+
|
|
286
|
+
### Button
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
interface ButtonProps {
|
|
290
|
+
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger'
|
|
291
|
+
size?: 'sm' | 'md' | 'lg'
|
|
292
|
+
disabled?: boolean
|
|
293
|
+
type?: 'button' | 'submit' | 'reset'
|
|
294
|
+
className?: string
|
|
295
|
+
onClick?: () => void
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Switch
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
interface SwitchProps {
|
|
303
|
+
checked?: boolean
|
|
304
|
+
disabled?: boolean
|
|
305
|
+
size?: 'sm' | 'md' | 'lg'
|
|
306
|
+
className?: string
|
|
307
|
+
onChange?: (checked: boolean) => void
|
|
308
|
+
label?: string
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### CodeBlock
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
interface CodeBlockProps {
|
|
316
|
+
code: string
|
|
317
|
+
language?: string
|
|
318
|
+
theme?: 'light' | 'dark' | 'auto'
|
|
319
|
+
lineNumbers?: boolean
|
|
320
|
+
copyable?: boolean
|
|
321
|
+
className?: string
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Composables
|
|
326
|
+
|
|
327
|
+
### Core Composables
|
|
328
|
+
|
|
329
|
+
#### useDarkMode
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
const { isDark, theme, toggle, setTheme } = useDarkMode({
|
|
333
|
+
storageKey: 'theme',
|
|
334
|
+
defaultTheme: 'system',
|
|
335
|
+
})
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
#### useCopyCode
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
const { copied, copy, reset } = useCopyCode({
|
|
342
|
+
code: 'const foo = "bar"',
|
|
343
|
+
onSuccess: () => console.log('Copied!'),
|
|
344
|
+
timeout: 2000,
|
|
345
|
+
})
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
#### useSEO
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
useSEO({
|
|
352
|
+
title: 'My Page',
|
|
353
|
+
description: 'Page description',
|
|
354
|
+
ogImage: 'https://example.com/og.png',
|
|
355
|
+
})
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Utility Composables (5 new)
|
|
359
|
+
|
|
360
|
+
#### useClickOutside
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
const cleanup = useClickOutside(
|
|
364
|
+
elementRef,
|
|
365
|
+
() => console.log('Clicked outside!'),
|
|
366
|
+
{ enabled: true, ignore: ['.modal'] }
|
|
367
|
+
)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
#### useKeyboard
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
useKeyboard([
|
|
374
|
+
{ key: 'Escape', handler: () => closeModal() },
|
|
375
|
+
{ key: 's', ctrl: true, handler: () => save() },
|
|
376
|
+
])
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### useFocusTrap
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
const { activate, deactivate } = useFocusTrap(containerRef, {
|
|
383
|
+
initialFocus: firstInputRef,
|
|
384
|
+
returnFocus: true,
|
|
385
|
+
})
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### useMediaQuery
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
const { matches } = useMediaQuery('(min-width: 768px)')
|
|
392
|
+
const { matches: isDark } = useIsDarkMode()
|
|
393
|
+
const { matches: isMobile } = useIsMobile()
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
#### useLocalStorage
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
const { value, setValue, removeValue } = useLocalStorage('key', 'initial')
|
|
400
|
+
setValue('new value')
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Animation Utilities (3 modules)
|
|
404
|
+
|
|
405
|
+
### Easing Functions (33 functions)
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
import { Easing } from '@stacksjs/components'
|
|
409
|
+
|
|
410
|
+
// Linear, Quad, Cubic, Quart, Quint, Sine, Expo, Circ, Elastic, Back, Bounce
|
|
411
|
+
const value = Easing.easeInOutCubic(time, start, change, duration)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Keyframe Animations (15 presets)
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { animate, KeyframeAnimations } from '@stacksjs/components'
|
|
418
|
+
|
|
419
|
+
// Predefined animations: fadeIn, fadeOut, slideInUp, slideInDown, zoom, bounce, pulse, shake, etc.
|
|
420
|
+
animate(element, 'fadeIn', { duration: 500 })
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### CSS Animation Helpers
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { applyAnimation, staggerAnimation, sequenceAnimations } from '@stacksjs/components'
|
|
427
|
+
|
|
428
|
+
applyAnimation(element, 'slide-in', { duration: '300ms' })
|
|
429
|
+
staggerAnimation(elements, 'fade-in', { stagger: 100 })
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
## Development
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
# Install dependencies
|
|
436
|
+
bun install
|
|
437
|
+
|
|
438
|
+
# Build the library
|
|
439
|
+
bun run build
|
|
440
|
+
|
|
441
|
+
# Run tests
|
|
442
|
+
bun test
|
|
443
|
+
|
|
444
|
+
# Watch mode
|
|
445
|
+
bun run dev
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Contributing
|
|
449
|
+
|
|
450
|
+
Contributions are welcome! Please read our [contributing guidelines](../../CONTRIBUTING.md) before submitting a PR.
|
|
451
|
+
|
|
452
|
+
## Migration Status
|
|
453
|
+
|
|
454
|
+
This library is actively being migrated from Vue to STX. Check our [TODO.md](../../TODO.md) for the complete migration roadmap and progress.
|
|
455
|
+
|
|
456
|
+
**Completed:**
|
|
457
|
+
|
|
458
|
+
- ✅ Infrastructure setup
|
|
459
|
+
- ✅ Composables (useDarkMode, useCopyCode, useSEO)
|
|
460
|
+
- ✅ Base components (CodeBlock, Hero, Footer, Installation)
|
|
461
|
+
- ✅ 35 UI Components (Accordion, Auth, Audio, Avatar, Badge, Breadcrumb, Button, Card, Drawer, Form, Image, Pagination, Portal, Teleport, Payment, Progress, Select, Skeleton, Spinner, Storage, Switch, Tabs, Tooltip, Video, VirtualList, VirtualTable, Dropdown, Dialog, Radio Group, Popover, Listbox, Combobox, Notification, Stepper, Transition, Table, Command Palette)
|
|
462
|
+
- ✅ 5 Input Components (TextInput, EmailInput, PasswordInput, NumberInput, SearchInput)
|
|
463
|
+
- ✅ 3 Form Components (Textarea, Checkbox, Radio)
|
|
464
|
+
- ✅ 8 Composables (useDarkMode, useCopyCode, useSEO, useClickOutside, useKeyboard, useFocusTrap, useMediaQuery, useLocalStorage)
|
|
465
|
+
- ✅ Animation Utilities (33 easing functions, 15 keyframe presets, CSS helpers)
|
|
466
|
+
- ✅ **Total: 47 Components + 8 Composables + Animation Utils**
|
|
467
|
+
|
|
468
|
+
## License
|
|
469
|
+
|
|
470
|
+
MIT © [Chris Breuer](https://github.com/chrisbbreuer)
|
|
471
|
+
|
|
472
|
+
## Credits
|
|
473
|
+
|
|
474
|
+
- Built with [STX](https://github.com/stacksjs/stx)
|
|
475
|
+
- Styled with [Headwind](https://github.com/stacksjs/headwind)
|
|
476
|
+
- Syntax highlighting by [ts-syntax-highlighter](https://github.com/stacksjs/ts-syntax-highlighter)
|
|
477
|
+
- Inspired by [Headless UI](https://headlessui.com)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const items = $props.items || []
|
|
3
|
+
export const allowMultiple = $props.allowMultiple || false
|
|
4
|
+
export const defaultOpen = $props.defaultOpen || []
|
|
5
|
+
export const className = $props.className || ''
|
|
6
|
+
export const onChange = $props.onChange
|
|
7
|
+
|
|
8
|
+
// Track which items are open
|
|
9
|
+
let openItems = defaultOpen
|
|
10
|
+
|
|
11
|
+
// Toggle an item
|
|
12
|
+
function toggleItem(index) {
|
|
13
|
+
if (allowMultiple) {
|
|
14
|
+
// Multiple items can be open
|
|
15
|
+
if (openItems.includes(index)) {
|
|
16
|
+
openItems = openItems.filter(i => i !== index)
|
|
17
|
+
} else {
|
|
18
|
+
openItems = [...openItems, index]
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
// Only one item can be open
|
|
22
|
+
if (openItems.includes(index)) {
|
|
23
|
+
openItems = []
|
|
24
|
+
} else {
|
|
25
|
+
openItems = [index]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (onChange) {
|
|
30
|
+
onChange(openItems)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Check if item is open
|
|
35
|
+
function isOpen(index) {
|
|
36
|
+
return openItems.includes(index)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const accordionClasses = `divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg ${className}`.trim()
|
|
40
|
+
export const itemClasses = ``.trim()
|
|
41
|
+
export const headerClasses = `w-full flex items-center justify-between px-4 py-3 text-left font-medium text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900`.trim()
|
|
42
|
+
export const iconClasses = `w-5 h-5 text-gray-500 dark:text-gray-400 transition-transform duration-200`.trim()
|
|
43
|
+
export const contentClasses = `px-4 py-3 text-gray-700 dark:text-gray-300`.trim()
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<div class="{{ accordionClasses }}" role="region">
|
|
47
|
+
@foreach(item in items)
|
|
48
|
+
<div class="{{ itemClasses }}">
|
|
49
|
+
<button
|
|
50
|
+
type="button"
|
|
51
|
+
class="{{ headerClasses }}"
|
|
52
|
+
onclick="toggleItem({{ $loop.index }})"
|
|
53
|
+
aria-expanded="{{ isOpen($loop.index) ? 'true' : 'false' }}"
|
|
54
|
+
aria-controls="accordion-content-{{ $loop.index }}"
|
|
55
|
+
>
|
|
56
|
+
<span>{{ item.title }}</span>
|
|
57
|
+
<svg
|
|
58
|
+
class="{{ iconClasses }}"
|
|
59
|
+
style="transform: rotate({{ isOpen($loop.index) ? '180' : '0' }}deg)"
|
|
60
|
+
fill="none"
|
|
61
|
+
viewBox="0 0 24 24"
|
|
62
|
+
stroke="currentColor"
|
|
63
|
+
>
|
|
64
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
|
65
|
+
</svg>
|
|
66
|
+
</button>
|
|
67
|
+
|
|
68
|
+
@if(isOpen($loop.index))
|
|
69
|
+
<div
|
|
70
|
+
id="accordion-content-{{ $loop.index }}"
|
|
71
|
+
class="{{ contentClasses }}"
|
|
72
|
+
role="region"
|
|
73
|
+
>
|
|
74
|
+
{!! item.content !!}
|
|
75
|
+
</div>
|
|
76
|
+
@endif
|
|
77
|
+
</div>
|
|
78
|
+
@endforeach
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<script>
|
|
82
|
+
// Keyboard navigation
|
|
83
|
+
if (typeof window !== 'undefined') {
|
|
84
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
85
|
+
const buttons = document.querySelectorAll('[aria-expanded]')
|
|
86
|
+
|
|
87
|
+
buttons.forEach((button, index) => {
|
|
88
|
+
button.addEventListener('keydown', (event) => {
|
|
89
|
+
if (event.key === 'ArrowDown') {
|
|
90
|
+
event.preventDefault()
|
|
91
|
+
const nextButton = buttons[index + 1]
|
|
92
|
+
if (nextButton) nextButton.focus()
|
|
93
|
+
} else if (event.key === 'ArrowUp') {
|
|
94
|
+
event.preventDefault()
|
|
95
|
+
const prevButton = buttons[index - 1]
|
|
96
|
+
if (prevButton) prevButton.focus()
|
|
97
|
+
} else if (event.key === 'Home') {
|
|
98
|
+
event.preventDefault()
|
|
99
|
+
buttons[0].focus()
|
|
100
|
+
} else if (event.key === 'End') {
|
|
101
|
+
event.preventDefault()
|
|
102
|
+
buttons[buttons.length - 1].focus()
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
</script>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const src = $props.src || ''
|
|
3
|
+
export const autoplay = $props.autoplay || false
|
|
4
|
+
export const loop = $props.loop || false
|
|
5
|
+
export const muted = $props.muted || false
|
|
6
|
+
export const controls = $props.controls ?? true
|
|
7
|
+
export const preload = $props.preload || 'metadata'
|
|
8
|
+
export const className = $props.className || ''
|
|
9
|
+
export const showWaveform = $props.showWaveform || false
|
|
10
|
+
export const title = $props.title || ''
|
|
11
|
+
|
|
12
|
+
export const containerClasses = `relative w-full ${className}`.trim()
|
|
13
|
+
export const audioClasses = 'w-full rounded-md bg-gray-100 dark:bg-gray-800'
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="{{ containerClasses }}">
|
|
17
|
+
@if(title)
|
|
18
|
+
<div class="mb-2 px-1">
|
|
19
|
+
<h3 class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
20
|
+
{{ title }}
|
|
21
|
+
</h3>
|
|
22
|
+
</div>
|
|
23
|
+
@endif
|
|
24
|
+
|
|
25
|
+
<audio
|
|
26
|
+
class="{{ audioClasses }}"
|
|
27
|
+
src="{{ src }}"
|
|
28
|
+
controls="{{ controls }}"
|
|
29
|
+
autoplay="{{ autoplay }}"
|
|
30
|
+
loop="{{ loop }}"
|
|
31
|
+
muted="{{ muted }}"
|
|
32
|
+
preload="{{ preload }}"
|
|
33
|
+
>
|
|
34
|
+
Your browser does not support the audio element.
|
|
35
|
+
</audio>
|
|
36
|
+
|
|
37
|
+
@if(showWaveform)
|
|
38
|
+
<div class="mt-2 h-16 bg-gray-100 dark:bg-gray-800 rounded-md flex items-center justify-center">
|
|
39
|
+
<svg class="w-full h-full px-4" viewBox="0 0 100 40" preserveAspectRatio="none">
|
|
40
|
+
<path
|
|
41
|
+
d="M 0,20 L 10,15 L 20,10 L 30,5 L 40,15 L 50,20 L 60,25 L 70,30 L 80,20 L 90,15 L 100,20"
|
|
42
|
+
fill="none"
|
|
43
|
+
stroke="currentColor"
|
|
44
|
+
stroke-width="2"
|
|
45
|
+
class="text-indigo-500 dark:text-indigo-400"
|
|
46
|
+
/>
|
|
47
|
+
</svg>
|
|
48
|
+
</div>
|
|
49
|
+
@endif
|
|
50
|
+
</div>
|