@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,133 @@
|
|
|
1
|
+
# Switch Component
|
|
2
|
+
|
|
3
|
+
A modern toggle switch component built with STX and headwind utility classes, inspired by Headless UI.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @stacksjs/components
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```stx
|
|
14
|
+
@component('Switch', { checked: true, label: 'Enable notifications' })
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Description |
|
|
20
|
+
|------|------|---------|-------------|
|
|
21
|
+
| `checked` | `boolean` | `false` | Whether the switch is checked |
|
|
22
|
+
| `disabled` | `boolean` | `false` | Disable the switch |
|
|
23
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Switch size |
|
|
24
|
+
| `className` | `string` | `''` | Additional CSS classes |
|
|
25
|
+
| `onChange` | `(checked: boolean) => void` | - | Change handler |
|
|
26
|
+
| `label` | `string` | `''` | Optional label text |
|
|
27
|
+
|
|
28
|
+
## Examples
|
|
29
|
+
|
|
30
|
+
### Basic Switch
|
|
31
|
+
|
|
32
|
+
```stx
|
|
33
|
+
<script>
|
|
34
|
+
let enabled = false
|
|
35
|
+
|
|
36
|
+
function handleChange(checked) {
|
|
37
|
+
enabled = checked
|
|
38
|
+
console.log('Switch is now:', checked)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = { enabled, handleChange }
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
@component('Switch', {
|
|
45
|
+
checked: enabled,
|
|
46
|
+
onChange: handleChange
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### With Label
|
|
51
|
+
|
|
52
|
+
```stx
|
|
53
|
+
@component('Switch', {
|
|
54
|
+
checked: true,
|
|
55
|
+
label: 'Enable notifications',
|
|
56
|
+
onChange: handleChange
|
|
57
|
+
})
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Sizes
|
|
61
|
+
|
|
62
|
+
```stx
|
|
63
|
+
@component('Switch', { size: 'sm', checked: true })
|
|
64
|
+
|
|
65
|
+
@component('Switch', { size: 'md', checked: true })
|
|
66
|
+
|
|
67
|
+
@component('Switch', { size: 'lg', checked: true })
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Disabled State
|
|
71
|
+
|
|
72
|
+
```stx
|
|
73
|
+
@component('Switch', {
|
|
74
|
+
checked: true,
|
|
75
|
+
disabled: true,
|
|
76
|
+
label: 'Cannot toggle'
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Custom Styling
|
|
81
|
+
|
|
82
|
+
```stx
|
|
83
|
+
@component('Switch', {
|
|
84
|
+
checked: true,
|
|
85
|
+
className: 'my-4'
|
|
86
|
+
})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Accessibility
|
|
90
|
+
|
|
91
|
+
The Switch component follows WAI-ARIA best practices:
|
|
92
|
+
|
|
93
|
+
- Proper `role="switch"` attribute
|
|
94
|
+
- `aria-checked` reflects the current state
|
|
95
|
+
- `aria-disabled` when disabled
|
|
96
|
+
- Screen reader text via `sr-only` class
|
|
97
|
+
- Keyboard accessible (can be toggled with Space/Enter)
|
|
98
|
+
- Focus visible ring for keyboard navigation
|
|
99
|
+
|
|
100
|
+
## Features
|
|
101
|
+
|
|
102
|
+
- Smooth animations and transitions
|
|
103
|
+
- Three size options (sm, md, lg)
|
|
104
|
+
- Dark mode support
|
|
105
|
+
- Disabled state
|
|
106
|
+
- Optional label
|
|
107
|
+
- Accessible by default
|
|
108
|
+
- Headwind utility classes for easy customization
|
|
109
|
+
- Inspired by Headless UI design
|
|
110
|
+
|
|
111
|
+
## Styling
|
|
112
|
+
|
|
113
|
+
The component uses headwind utility classes for styling. You can customize it by:
|
|
114
|
+
|
|
115
|
+
1. Passing additional classes via `className` prop
|
|
116
|
+
2. Modifying the component source
|
|
117
|
+
3. Using headwind configuration to adjust the design system
|
|
118
|
+
|
|
119
|
+
### Color Customization
|
|
120
|
+
|
|
121
|
+
To customize colors, you can:
|
|
122
|
+
|
|
123
|
+
- Override the checked state background color in your headwind config
|
|
124
|
+
- Pass custom classes via `className` prop
|
|
125
|
+
- Modify the component's source code
|
|
126
|
+
|
|
127
|
+
Example:
|
|
128
|
+
```stx
|
|
129
|
+
@component('Switch', {
|
|
130
|
+
checked: true,
|
|
131
|
+
className: '!bg-green-500'
|
|
132
|
+
})
|
|
133
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const checked = $props.checked || false
|
|
3
|
+
export const disabled = $props.disabled || false
|
|
4
|
+
export const size = $props.size || 'md'
|
|
5
|
+
export const className = $props.className || ''
|
|
6
|
+
export const onChange = $props.onChange
|
|
7
|
+
export const label = $props.label || ''
|
|
8
|
+
|
|
9
|
+
// Size configurations using headwind
|
|
10
|
+
const sizeConfig = {
|
|
11
|
+
sm: {
|
|
12
|
+
track: 'h-5 w-9',
|
|
13
|
+
thumb: 'h-4 w-4',
|
|
14
|
+
translate: 'translate-x-4',
|
|
15
|
+
},
|
|
16
|
+
md: {
|
|
17
|
+
track: 'h-[38px] w-[74px]',
|
|
18
|
+
thumb: 'h-[34px] w-[34px]',
|
|
19
|
+
translate: 'translate-x-9',
|
|
20
|
+
},
|
|
21
|
+
lg: {
|
|
22
|
+
track: 'h-12 w-24',
|
|
23
|
+
thumb: 'h-11 w-11',
|
|
24
|
+
translate: 'translate-x-12',
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const config = sizeConfig[size]
|
|
29
|
+
|
|
30
|
+
// Track classes
|
|
31
|
+
const trackBaseClasses = 'relative inline-flex shrink-0 cursor-pointer border-2 border-transparent rounded-full transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-neutral-300 dark:focus-visible:ring-offset-neutral-700'
|
|
32
|
+
const trackStateClasses = checked
|
|
33
|
+
? 'bg-blue-500 dark:bg-blue-600'
|
|
34
|
+
: 'bg-neutral-400 dark:bg-neutral-600'
|
|
35
|
+
const trackDisabledClasses = disabled
|
|
36
|
+
? 'opacity-50 cursor-not-allowed pointer-events-none'
|
|
37
|
+
: ''
|
|
38
|
+
|
|
39
|
+
export const trackClasses = `${trackBaseClasses} ${trackStateClasses} ${trackDisabledClasses} ${config.track} ${className}`.trim()
|
|
40
|
+
|
|
41
|
+
// Thumb classes
|
|
42
|
+
const thumbBaseClasses = 'pointer-events-none inline-block transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out'
|
|
43
|
+
const thumbPositionClasses = checked ? config.translate : 'translate-x-0'
|
|
44
|
+
export const thumbClasses = `${thumbBaseClasses} ${thumbPositionClasses} ${config.thumb}`.trim()
|
|
45
|
+
|
|
46
|
+
// Toggle function
|
|
47
|
+
export function toggle() {
|
|
48
|
+
if (disabled) return
|
|
49
|
+
onChange?.(!checked)
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<label class="inline-flex items-center gap-3 cursor-pointer">
|
|
54
|
+
@if(label)
|
|
55
|
+
<span class="text-sm font-medium text-neutral-700 dark:text-neutral-300">
|
|
56
|
+
{{ label }}
|
|
57
|
+
</span>
|
|
58
|
+
@endif
|
|
59
|
+
|
|
60
|
+
<button
|
|
61
|
+
type="button"
|
|
62
|
+
role="switch"
|
|
63
|
+
aria-checked="{{ checked ? 'true' : 'false' }}"
|
|
64
|
+
class="{{ trackClasses }}"
|
|
65
|
+
@if(disabled)disabled aria-disabled="true"@endif
|
|
66
|
+
@click="toggle"
|
|
67
|
+
>
|
|
68
|
+
<span class="sr-only">@if(label){{ label }}@else Toggle switch@endif</span>
|
|
69
|
+
<span
|
|
70
|
+
aria-hidden="true"
|
|
71
|
+
class="{{ thumbClasses }}"
|
|
72
|
+
/>
|
|
73
|
+
</button>
|
|
74
|
+
</label>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Table Component
|
|
2
|
+
|
|
3
|
+
Responsive table component with sorting and styling options.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @stacksjs/components
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```stx
|
|
14
|
+
@component('Table')
|
|
15
|
+
@component('TableHead')
|
|
16
|
+
@component('TableRow')
|
|
17
|
+
@component('TableHeader') Name @endcomponent
|
|
18
|
+
@component('TableHeader') Email @endcomponent
|
|
19
|
+
@component('TableHeader') Role @endcomponent
|
|
20
|
+
@endcomponent
|
|
21
|
+
@endcomponent
|
|
22
|
+
|
|
23
|
+
@component('TableBody')
|
|
24
|
+
@component('TableRow')
|
|
25
|
+
@component('TableCell') John Doe @endcomponent
|
|
26
|
+
@component('TableCell') john@example.com @endcomponent
|
|
27
|
+
@component('TableCell') Admin @endcomponent
|
|
28
|
+
@endcomponent
|
|
29
|
+
@endcomponent
|
|
30
|
+
@endcomponent
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- Responsive design
|
|
36
|
+
- Sortable columns
|
|
37
|
+
- Striped rows
|
|
38
|
+
- Hover effects
|
|
39
|
+
- Dark mode support
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const striped = $props.striped || false
|
|
4
|
+
export const hoverable = $props.hoverable !== false
|
|
5
|
+
|
|
6
|
+
const baseClasses = 'min-w-full divide-y divide-neutral-200 dark:divide-neutral-700'
|
|
7
|
+
const tableClasses = `${baseClasses} ${className}`.trim()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<div class="overflow-x-auto">
|
|
11
|
+
<table class="{{ tableClasses }}">
|
|
12
|
+
<slot :striped="striped" :hoverable="hoverable" />
|
|
13
|
+
</table>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
|
|
4
|
+
const baseClasses = 'bg-white divide-y divide-neutral-200 dark:bg-neutral-900 dark:divide-neutral-700'
|
|
5
|
+
const bodyClasses = `${baseClasses} ${className}`.trim()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<tbody class="{{ bodyClasses }}">
|
|
9
|
+
<slot />
|
|
10
|
+
</tbody>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
|
|
4
|
+
const baseClasses = 'px-6 py-4 whitespace-nowrap text-sm text-neutral-900 dark:text-neutral-100'
|
|
5
|
+
const cellClasses = `${baseClasses} ${className}`.trim()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<td class="{{ cellClasses }}">
|
|
9
|
+
<slot />
|
|
10
|
+
</td>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const sortable = $props.sortable || false
|
|
4
|
+
export const onClick = $props.onClick
|
|
5
|
+
|
|
6
|
+
const baseClasses = 'px-6 py-3 text-left text-xs font-medium text-neutral-500 uppercase tracking-wider dark:text-neutral-400'
|
|
7
|
+
const sortableClasses = sortable ? 'cursor-pointer hover:text-neutral-700 dark:hover:text-neutral-200' : ''
|
|
8
|
+
const headerClasses = `${baseClasses} ${sortableClasses} ${className}`.trim()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<th class="{{ headerClasses }}" @if(sortable)@click="onClick"@endif>
|
|
12
|
+
<slot />
|
|
13
|
+
</th>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const className = $props.className || ''
|
|
3
|
+
export const hoverable = $props.hoverable !== false
|
|
4
|
+
|
|
5
|
+
const hoverClasses = hoverable ? 'hover:bg-neutral-50 dark:hover:bg-neutral-800' : ''
|
|
6
|
+
const rowClasses = `${hoverClasses} ${className}`.trim()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<tr class="{{ rowClasses }}">
|
|
10
|
+
<slot />
|
|
11
|
+
</tr>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export { default as Table } from './Table.stx'
|
|
2
|
+
export { default as TableBody } from './TableBody.stx'
|
|
3
|
+
export { default as TableCell } from './TableCell.stx'
|
|
4
|
+
export { default as TableHead } from './TableHead.stx'
|
|
5
|
+
export { default as TableHeader } from './TableHeader.stx'
|
|
6
|
+
export { default as TableRow } from './TableRow.stx'
|
|
7
|
+
|
|
8
|
+
export interface TableProps {
|
|
9
|
+
className?: string
|
|
10
|
+
striped?: boolean
|
|
11
|
+
hoverable?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TableHeadProps {
|
|
15
|
+
className?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TableBodyProps {
|
|
19
|
+
className?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface TableRowProps {
|
|
23
|
+
className?: string
|
|
24
|
+
hoverable?: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface TableHeaderProps {
|
|
28
|
+
className?: string
|
|
29
|
+
sortable?: boolean
|
|
30
|
+
onClick?: () => void
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface TableCellProps {
|
|
34
|
+
className?: string
|
|
35
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const tabs = $props.tabs || []
|
|
3
|
+
export const defaultTab = $props.defaultTab || 0
|
|
4
|
+
export const orientation = $props.orientation || 'horizontal'
|
|
5
|
+
export const variant = $props.variant || 'line'
|
|
6
|
+
export const className = $props.className || ''
|
|
7
|
+
export const onChange = $props.onChange
|
|
8
|
+
|
|
9
|
+
let activeTab = defaultTab
|
|
10
|
+
|
|
11
|
+
function selectTab(index) {
|
|
12
|
+
activeTab = index
|
|
13
|
+
if (onChange) {
|
|
14
|
+
onChange(index, tabs[index])
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Orientation classes
|
|
19
|
+
const orientationClasses = {
|
|
20
|
+
horizontal: 'flex-col',
|
|
21
|
+
vertical: 'flex-row',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Tab list orientation classes
|
|
25
|
+
const tabListOrientationClasses = {
|
|
26
|
+
horizontal: 'flex-row border-b',
|
|
27
|
+
vertical: 'flex-col border-r',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Variant classes for tab list
|
|
31
|
+
const variantClasses = {
|
|
32
|
+
line: 'border-gray-200 dark:border-gray-700',
|
|
33
|
+
pills: 'gap-2 border-0 bg-gray-100 dark:bg-gray-800 p-1 rounded-lg',
|
|
34
|
+
enclosed: 'border-gray-200 dark:border-gray-700',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Tab button classes based on variant
|
|
38
|
+
function getTabClasses(index, variant, orientation) {
|
|
39
|
+
const isActive = index === activeTab
|
|
40
|
+
const baseClasses = 'px-4 py-2 font-medium text-sm transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900'
|
|
41
|
+
|
|
42
|
+
if (variant === 'line') {
|
|
43
|
+
const borderPosition = orientation === 'horizontal' ? 'border-b-2' : 'border-r-2'
|
|
44
|
+
return `${baseClasses} ${borderPosition} ${isActive ? 'border-blue-500 text-blue-600 dark:text-blue-400' : 'border-transparent text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:border-gray-300 dark:hover:border-gray-600'}`
|
|
45
|
+
} else if (variant === 'pills') {
|
|
46
|
+
return `${baseClasses} rounded-md ${isActive ? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 shadow-sm' : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'}`
|
|
47
|
+
} else if (variant === 'enclosed') {
|
|
48
|
+
const borderClasses = orientation === 'horizontal' ? 'border-t border-l border-r rounded-t-md' : 'border-t border-l border-b rounded-l-md'
|
|
49
|
+
return `${baseClasses} ${borderClasses} ${isActive ? 'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700 -mb-px' : 'bg-gray-50 dark:bg-gray-900 border-transparent hover:border-gray-200 dark:hover:border-gray-700'}`
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const containerClasses = `flex ${orientationClasses[orientation]} ${className}`.trim()
|
|
54
|
+
export const tabListClasses = `flex ${tabListOrientationClasses[orientation]} ${variantClasses[variant]}`.trim()
|
|
55
|
+
export const tabPanelClasses = `p-4 focus:outline-none`.trim()
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<div class="{{ containerClasses }}">
|
|
59
|
+
<!-- Tab List -->
|
|
60
|
+
<div
|
|
61
|
+
class="{{ tabListClasses }}"
|
|
62
|
+
role="tablist"
|
|
63
|
+
aria-orientation="{{ orientation }}"
|
|
64
|
+
>
|
|
65
|
+
@foreach(tab in tabs)
|
|
66
|
+
<button
|
|
67
|
+
type="button"
|
|
68
|
+
class="{{ getTabClasses($loop.index, variant, orientation) }}"
|
|
69
|
+
role="tab"
|
|
70
|
+
aria-selected="{{ activeTab === $loop.index ? 'true' : 'false' }}"
|
|
71
|
+
aria-controls="tab-panel-{{ $loop.index }}"
|
|
72
|
+
id="tab-{{ $loop.index }}"
|
|
73
|
+
tabindex="{{ activeTab === $loop.index ? '0' : '-1' }}"
|
|
74
|
+
onclick="selectTab({{ $loop.index }})"
|
|
75
|
+
onkeydown="handleKeyDown(event, {{ $loop.index }})"
|
|
76
|
+
>
|
|
77
|
+
@if(tab.icon)
|
|
78
|
+
<span class="inline-flex items-center gap-2">
|
|
79
|
+
<span innerHTML="{!! tab.icon !!}"></span>
|
|
80
|
+
<span>{{ tab.label }}</span>
|
|
81
|
+
</span>
|
|
82
|
+
@else
|
|
83
|
+
{{ tab.label }}
|
|
84
|
+
@endif
|
|
85
|
+
</button>
|
|
86
|
+
@endforeach
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<!-- Tab Panels -->
|
|
90
|
+
@foreach(tab in tabs)
|
|
91
|
+
@if(activeTab === $loop.index)
|
|
92
|
+
<div
|
|
93
|
+
id="tab-panel-{{ $loop.index }}"
|
|
94
|
+
class="{{ tabPanelClasses }}"
|
|
95
|
+
role="tabpanel"
|
|
96
|
+
aria-labelledby="tab-{{ $loop.index }}"
|
|
97
|
+
tabindex="0"
|
|
98
|
+
>
|
|
99
|
+
{!! tab.content !!}
|
|
100
|
+
</div>
|
|
101
|
+
@endif
|
|
102
|
+
@endforeach
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<script>
|
|
106
|
+
function handleKeyDown(event, currentIndex) {
|
|
107
|
+
const tabCount = tabs.length
|
|
108
|
+
let newIndex = currentIndex
|
|
109
|
+
|
|
110
|
+
if (orientation === 'horizontal') {
|
|
111
|
+
if (event.key === 'ArrowRight') {
|
|
112
|
+
event.preventDefault()
|
|
113
|
+
newIndex = (currentIndex + 1) % tabCount
|
|
114
|
+
} else if (event.key === 'ArrowLeft') {
|
|
115
|
+
event.preventDefault()
|
|
116
|
+
newIndex = (currentIndex - 1 + tabCount) % tabCount
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
if (event.key === 'ArrowDown') {
|
|
120
|
+
event.preventDefault()
|
|
121
|
+
newIndex = (currentIndex + 1) % tabCount
|
|
122
|
+
} else if (event.key === 'ArrowUp') {
|
|
123
|
+
event.preventDefault()
|
|
124
|
+
newIndex = (currentIndex - 1 + tabCount) % tabCount
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (event.key === 'Home') {
|
|
129
|
+
event.preventDefault()
|
|
130
|
+
newIndex = 0
|
|
131
|
+
} else if (event.key === 'End') {
|
|
132
|
+
event.preventDefault()
|
|
133
|
+
newIndex = tabCount - 1
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (newIndex !== currentIndex) {
|
|
137
|
+
selectTab(newIndex)
|
|
138
|
+
// Focus the new tab
|
|
139
|
+
if (typeof window !== 'undefined') {
|
|
140
|
+
const newTab = document.getElementById(`tab-${newIndex}`)
|
|
141
|
+
if (newTab) newTab.focus()
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
</script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { default as Tabs } from './Tabs.stx'
|
|
2
|
+
|
|
3
|
+
export interface Tab {
|
|
4
|
+
label: string
|
|
5
|
+
content: string
|
|
6
|
+
icon?: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface TabsProps {
|
|
10
|
+
tabs: Tab[]
|
|
11
|
+
defaultTab?: number
|
|
12
|
+
orientation?: 'horizontal' | 'vertical'
|
|
13
|
+
variant?: 'line' | 'pills' | 'enclosed'
|
|
14
|
+
onChange?: (index: number, tab: Tab) => void
|
|
15
|
+
className?: string
|
|
16
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const to = $props.to || 'body'
|
|
3
|
+
export const disabled = $props.disabled || false
|
|
4
|
+
export const defer = $props.defer || false
|
|
5
|
+
|
|
6
|
+
let teleportContainer = null
|
|
7
|
+
let teleportId = `teleport-${Math.random().toString(36).substr(2, 9)}`
|
|
8
|
+
|
|
9
|
+
// Teleport content to target
|
|
10
|
+
function teleport() {
|
|
11
|
+
if (typeof window === 'undefined' || disabled)
|
|
12
|
+
return
|
|
13
|
+
|
|
14
|
+
// Get target element
|
|
15
|
+
const targetElement = typeof to === 'string'
|
|
16
|
+
? document.querySelector(to)
|
|
17
|
+
: to
|
|
18
|
+
|
|
19
|
+
if (!targetElement) {
|
|
20
|
+
console.warn(`Teleport target "${to}" not found`)
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Get source element
|
|
25
|
+
const sourceElement = document.getElementById(teleportId)
|
|
26
|
+
if (!sourceElement)
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
// Create teleport container if needed
|
|
30
|
+
if (!teleportContainer) {
|
|
31
|
+
teleportContainer = document.createElement('div')
|
|
32
|
+
teleportContainer.setAttribute('data-teleport-id', teleportId)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Move all child nodes to container
|
|
36
|
+
while (sourceElement.firstChild) {
|
|
37
|
+
teleportContainer.appendChild(sourceElement.firstChild)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Append to target
|
|
41
|
+
targetElement.appendChild(teleportContainer)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Return content back to original location
|
|
45
|
+
function returnContent() {
|
|
46
|
+
if (!teleportContainer || !teleportContainer.parentNode)
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
const sourceElement = document.getElementById(teleportId)
|
|
50
|
+
if (!sourceElement)
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
// Move content back
|
|
54
|
+
while (teleportContainer.firstChild) {
|
|
55
|
+
sourceElement.appendChild(teleportContainer.firstChild)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Remove container
|
|
59
|
+
teleportContainer.parentNode.removeChild(teleportContainer)
|
|
60
|
+
teleportContainer = null
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Initialize teleport
|
|
64
|
+
if (typeof window !== 'undefined') {
|
|
65
|
+
if (defer) {
|
|
66
|
+
// Defer until next tick
|
|
67
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
68
|
+
setTimeout(teleport, 0)
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Immediate
|
|
73
|
+
window.addEventListener('DOMContentLoaded', teleport)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Cleanup on page unload
|
|
77
|
+
window.addEventListener('beforeunload', returnContent)
|
|
78
|
+
}
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
@if(disabled)
|
|
82
|
+
<!-- Render in place if disabled -->
|
|
83
|
+
<slot />
|
|
84
|
+
@else
|
|
85
|
+
<!-- Source container -->
|
|
86
|
+
<div id="{{ teleportId }}" data-teleport-source="true">
|
|
87
|
+
<slot />
|
|
88
|
+
</div>
|
|
89
|
+
@endif
|
|
90
|
+
|
|
91
|
+
<script>
|
|
92
|
+
// Trigger teleport after render
|
|
93
|
+
if (typeof window !== 'undefined' && document.readyState === 'complete') {
|
|
94
|
+
if (defer) {
|
|
95
|
+
setTimeout(teleport, 0)
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
teleport()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
</script>
|