@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,125 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const headingText = $props.headingText || 'Two Factor Authentication'
|
|
3
|
+
export const labelText = $props.labelText || 'Authentication code'
|
|
4
|
+
export const instructionText = $props.instructionText || 'Open your Symantec 2FA app to view your authentication code.'
|
|
5
|
+
export const codeLength = $props.codeLength || 6
|
|
6
|
+
export const onSubmit = $props.onSubmit || (() => {})
|
|
7
|
+
export const onUseRecoveryCode = $props.onUseRecoveryCode
|
|
8
|
+
export const className = $props.className || ''
|
|
9
|
+
|
|
10
|
+
export const containerClasses = `py-32 dark:bg-blue-gray-900 ${className}`.trim()
|
|
11
|
+
export const codes = Array(codeLength).fill('')
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div class="{{ containerClasses }}">
|
|
15
|
+
<div class="mx-auto max-w-sm rounded-md px-8 py-4 shadow-md bg-white dark:bg-blue-gray-800">
|
|
16
|
+
<div class="card-body">
|
|
17
|
+
<div>
|
|
18
|
+
<h3 class="text-center text-sm text-gray-900 dark:text-gray-100 font-semibold">
|
|
19
|
+
{{ headingText }}
|
|
20
|
+
</h3>
|
|
21
|
+
<label for="code-0" class="mt-4 block text-sm text-gray-900 dark:text-gray-100 font-medium leading-6">
|
|
22
|
+
{{ labelText }}
|
|
23
|
+
</label>
|
|
24
|
+
<form onsubmit="event.preventDefault(); handleSubmit(event)">
|
|
25
|
+
<div class="mt-2 flex rounded-md shadow-sm space-x-2">
|
|
26
|
+
@for(i in Array(codeLength).keys())
|
|
27
|
+
<input
|
|
28
|
+
id="code-{{ i }}"
|
|
29
|
+
type="text"
|
|
30
|
+
maxlength="1"
|
|
31
|
+
name="code-{{ i }}"
|
|
32
|
+
placeholder="-"
|
|
33
|
+
class="block w-full border-0 rounded-md px-2 py-2 text-center text-gray-900 dark:text-gray-100 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"
|
|
34
|
+
oninput="handleCodeInput(event, {{ i }})"
|
|
35
|
+
onkeydown="handleKeyDown(event, {{ i }})"
|
|
36
|
+
/>
|
|
37
|
+
@endfor
|
|
38
|
+
</div>
|
|
39
|
+
<div class="py-4">
|
|
40
|
+
<button
|
|
41
|
+
type="submit"
|
|
42
|
+
class="relative h-8 w-full flex items-center justify-center rounded-full bg-teal-600 px-4 text-white font-semibold hover:bg-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-600 focus:ring-offset-2"
|
|
43
|
+
>
|
|
44
|
+
Verify
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
</form>
|
|
48
|
+
<div>
|
|
49
|
+
<p class="text-xs text-gray-700 dark:text-gray-300 font-semibold">
|
|
50
|
+
{{ instructionText }}
|
|
51
|
+
</p>
|
|
52
|
+
</div>
|
|
53
|
+
@if(onUseRecoveryCode)
|
|
54
|
+
<div class="mt-4">
|
|
55
|
+
<p class="text-xs text-gray-700 dark:text-gray-300 font-semibold">
|
|
56
|
+
Having Problems?
|
|
57
|
+
</p>
|
|
58
|
+
<a
|
|
59
|
+
href="#"
|
|
60
|
+
onclick="event.preventDefault(); handleRecoveryCode()"
|
|
61
|
+
class="text-xs text-blue-500 hover:underline"
|
|
62
|
+
>
|
|
63
|
+
Use recovery code instead
|
|
64
|
+
</a>
|
|
65
|
+
</div>
|
|
66
|
+
@endif
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<script>
|
|
73
|
+
function handleCodeInput(event, index) {
|
|
74
|
+
const input = event.target
|
|
75
|
+
const value = input.value
|
|
76
|
+
|
|
77
|
+
// Only allow digits
|
|
78
|
+
if (!/^\d*$/.test(value)) {
|
|
79
|
+
input.value = ''
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Auto-focus next input
|
|
84
|
+
if (value.length === 1 && index < codeLength - 1) {
|
|
85
|
+
const nextInput = document.getElementById(`code-${index + 1}`)
|
|
86
|
+
if (nextInput) {
|
|
87
|
+
nextInput.focus()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function handleKeyDown(event, index) {
|
|
93
|
+
// Handle backspace to move to previous input
|
|
94
|
+
if (event.key === 'Backspace' && !event.target.value && index > 0) {
|
|
95
|
+
const prevInput = document.getElementById(`code-${index - 1}`)
|
|
96
|
+
if (prevInput) {
|
|
97
|
+
prevInput.focus()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function handleSubmit(event) {
|
|
103
|
+
const code = []
|
|
104
|
+
for (let i = 0; i < codeLength; i++) {
|
|
105
|
+
const input = document.getElementById(`code-${i}`)
|
|
106
|
+
if (input && input.value) {
|
|
107
|
+
code.push(input.value)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (code.length === codeLength) {
|
|
112
|
+
if (onSubmit) {
|
|
113
|
+
onSubmit(code.join(''))
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
alert('Please enter all digits')
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function handleRecoveryCode() {
|
|
121
|
+
if (onUseRecoveryCode) {
|
|
122
|
+
onUseRecoveryCode()
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
</script>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const src = $props.src || ''
|
|
3
|
+
export const poster = $props.poster || ''
|
|
4
|
+
export const autoplay = $props.autoplay || false
|
|
5
|
+
export const loop = $props.loop || false
|
|
6
|
+
export const muted = $props.muted || false
|
|
7
|
+
export const controls = $props.controls ?? true
|
|
8
|
+
export const preload = $props.preload || 'metadata'
|
|
9
|
+
export const width = $props.width
|
|
10
|
+
export const height = $props.height
|
|
11
|
+
export const aspectRatio = $props.aspectRatio || '16/9'
|
|
12
|
+
export const className = $props.className || ''
|
|
13
|
+
export const title = $props.title || ''
|
|
14
|
+
|
|
15
|
+
export const containerClasses = `relative w-full overflow-hidden rounded-lg ${className}`.trim()
|
|
16
|
+
export const videoClasses = 'w-full h-full object-cover bg-gray-900 dark:bg-gray-950'
|
|
17
|
+
export const aspectRatioClass = aspectRatio === '16/9' ? 'aspect-video' : aspectRatio === '4/3' ? 'aspect-[4/3]' : aspectRatio === '1/1' ? 'aspect-square' : ''
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<div class="{{ containerClasses }}">
|
|
21
|
+
@if(title)
|
|
22
|
+
<div class="mb-2 px-1">
|
|
23
|
+
<h3 class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
24
|
+
{{ title }}
|
|
25
|
+
</h3>
|
|
26
|
+
</div>
|
|
27
|
+
@endif
|
|
28
|
+
|
|
29
|
+
<div class="{{ aspectRatioClass }}">
|
|
30
|
+
<video
|
|
31
|
+
class="{{ videoClasses }}"
|
|
32
|
+
src="{{ src }}"
|
|
33
|
+
poster="{{ poster }}"
|
|
34
|
+
controls="{{ controls }}"
|
|
35
|
+
autoplay="{{ autoplay }}"
|
|
36
|
+
loop="{{ loop }}"
|
|
37
|
+
muted="{{ muted }}"
|
|
38
|
+
preload="{{ preload }}"
|
|
39
|
+
width="{{ width }}"
|
|
40
|
+
height="{{ height }}"
|
|
41
|
+
>
|
|
42
|
+
Your browser does not support the video element.
|
|
43
|
+
</video>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const items = $props.items || []
|
|
3
|
+
export const itemHeight = $props.itemHeight || 50
|
|
4
|
+
export const height = $props.height || 400
|
|
5
|
+
export const overscan = $props.overscan || 3
|
|
6
|
+
export const renderItem = $props.renderItem
|
|
7
|
+
export const className = $props.className || ''
|
|
8
|
+
|
|
9
|
+
// Calculate visible range
|
|
10
|
+
let scrollTop = 0
|
|
11
|
+
const visibleCount = Math.ceil(height / itemHeight)
|
|
12
|
+
const totalHeight = items.length * itemHeight
|
|
13
|
+
|
|
14
|
+
// Calculate start and end indices with overscan
|
|
15
|
+
function getVisibleRange() {
|
|
16
|
+
const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan)
|
|
17
|
+
const endIndex = Math.min(items.length - 1, Math.floor((scrollTop + height) / itemHeight) + overscan)
|
|
18
|
+
return { startIndex, endIndex }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { startIndex, endIndex } = getVisibleRange()
|
|
22
|
+
const visibleItems = items.slice(startIndex, endIndex + 1)
|
|
23
|
+
const offsetY = startIndex * itemHeight
|
|
24
|
+
|
|
25
|
+
// Handle scroll
|
|
26
|
+
function handleScroll(event) {
|
|
27
|
+
const target = event.target
|
|
28
|
+
scrollTop = target.scrollTop
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const containerClasses = `overflow-auto ${className}`.trim()
|
|
32
|
+
export const innerClasses = `relative`.trim()
|
|
33
|
+
export const itemClasses = `absolute left-0 right-0`.trim()
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<div
|
|
37
|
+
class="{{ containerClasses }}"
|
|
38
|
+
style="height: {{ height }}px"
|
|
39
|
+
onscroll="handleScroll(event)"
|
|
40
|
+
>
|
|
41
|
+
<div
|
|
42
|
+
class="{{ innerClasses }}"
|
|
43
|
+
style="height: {{ totalHeight }}px"
|
|
44
|
+
>
|
|
45
|
+
@foreach(item in visibleItems)
|
|
46
|
+
<div
|
|
47
|
+
class="{{ itemClasses }}"
|
|
48
|
+
style="top: {{ (startIndex + $loop.index) * itemHeight }}px; height: {{ itemHeight }}px"
|
|
49
|
+
data-index="{{ startIndex + $loop.index }}"
|
|
50
|
+
>
|
|
51
|
+
@if(renderItem)
|
|
52
|
+
{!! renderItem(item, startIndex + $loop.index) !!}
|
|
53
|
+
@else
|
|
54
|
+
<slot item="{{ item }}" index="{{ startIndex + $loop.index }}" />
|
|
55
|
+
@endif
|
|
56
|
+
</div>
|
|
57
|
+
@endforeach
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<script>
|
|
62
|
+
// Re-render on scroll (simplified reactivity)
|
|
63
|
+
if (typeof window !== 'undefined') {
|
|
64
|
+
let ticking = false
|
|
65
|
+
|
|
66
|
+
function updateVisibleItems() {
|
|
67
|
+
const range = getVisibleRange()
|
|
68
|
+
// Trigger re-render by updating visible range
|
|
69
|
+
// In a real implementation, this would update reactive state
|
|
70
|
+
ticking = false
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const scrollContainer = document.querySelector('.overflow-auto')
|
|
74
|
+
if (scrollContainer) {
|
|
75
|
+
scrollContainer.addEventListener('scroll', () => {
|
|
76
|
+
if (!ticking) {
|
|
77
|
+
window.requestAnimationFrame(updateVisibleItems)
|
|
78
|
+
ticking = true
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export const columns = $props.columns || []
|
|
3
|
+
export const data = $props.data || []
|
|
4
|
+
export const rowHeight = $props.rowHeight || 48
|
|
5
|
+
export const height = $props.height || 600
|
|
6
|
+
export const headerHeight = $props.headerHeight || 56
|
|
7
|
+
export const overscan = $props.overscan || 5
|
|
8
|
+
export const striped = $props.striped || false
|
|
9
|
+
export const hoverable = $props.hoverable ?? true
|
|
10
|
+
export const className = $props.className || ''
|
|
11
|
+
|
|
12
|
+
// Calculate visible range
|
|
13
|
+
let scrollTop = 0
|
|
14
|
+
const visibleCount = Math.ceil((height - headerHeight) / rowHeight)
|
|
15
|
+
const totalHeight = data.length * rowHeight
|
|
16
|
+
|
|
17
|
+
function getVisibleRange() {
|
|
18
|
+
const startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan)
|
|
19
|
+
const endIndex = Math.min(data.length - 1, Math.floor((scrollTop + height - headerHeight) / rowHeight) + overscan)
|
|
20
|
+
return { startIndex, endIndex }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { startIndex, endIndex } = getVisibleRange()
|
|
24
|
+
const visibleRows = data.slice(startIndex, endIndex + 1)
|
|
25
|
+
const offsetY = startIndex * rowHeight
|
|
26
|
+
|
|
27
|
+
function handleScroll(event) {
|
|
28
|
+
const target = event.target
|
|
29
|
+
scrollTop = target.scrollTop
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Get cell value
|
|
33
|
+
function getCellValue(row, column) {
|
|
34
|
+
if (column.render) {
|
|
35
|
+
return column.render(row[column.key], row)
|
|
36
|
+
}
|
|
37
|
+
return row[column.key]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const containerClasses = `border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden ${className}`.trim()
|
|
41
|
+
export const headerClasses = `bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 flex`.trim()
|
|
42
|
+
export const headerCellClasses = `px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider`.trim()
|
|
43
|
+
export const bodyClasses = `overflow-auto bg-white dark:bg-gray-900`.trim()
|
|
44
|
+
export const innerClasses = `relative`.trim()
|
|
45
|
+
export const rowClasses = `absolute left-0 right-0 flex border-b border-gray-200 dark:border-gray-700 ${hoverable ? 'hover:bg-gray-50 dark:hover:bg-gray-800' : ''}`.trim()
|
|
46
|
+
export const cellClasses = `px-6 py-4 text-sm text-gray-900 dark:text-gray-100`.trim()
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<div class="{{ containerClasses }}">
|
|
50
|
+
<!-- Header -->
|
|
51
|
+
<div class="{{ headerClasses }}" style="height: {{ headerHeight }}px">
|
|
52
|
+
@foreach(column in columns)
|
|
53
|
+
<div
|
|
54
|
+
class="{{ headerCellClasses }}"
|
|
55
|
+
style="flex: {{ column.width || 1 }}; min-width: {{ column.minWidth || 'auto' }}"
|
|
56
|
+
>
|
|
57
|
+
{{ column.label || column.key }}
|
|
58
|
+
</div>
|
|
59
|
+
@endforeach
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<!-- Body -->
|
|
63
|
+
<div
|
|
64
|
+
class="{{ bodyClasses }}"
|
|
65
|
+
style="height: {{ height - headerHeight }}px"
|
|
66
|
+
onscroll="handleScroll(event)"
|
|
67
|
+
>
|
|
68
|
+
<div
|
|
69
|
+
class="{{ innerClasses }}"
|
|
70
|
+
style="height: {{ totalHeight }}px"
|
|
71
|
+
>
|
|
72
|
+
@foreach(row in visibleRows)
|
|
73
|
+
<div
|
|
74
|
+
class="{{ rowClasses }} {{ striped && ($loop.index % 2 === 1) ? 'bg-gray-50 dark:bg-gray-800' : '' }}"
|
|
75
|
+
style="top: {{ (startIndex + $loop.index) * rowHeight }}px; height: {{ rowHeight }}px"
|
|
76
|
+
data-index="{{ startIndex + $loop.index }}"
|
|
77
|
+
>
|
|
78
|
+
@foreach(column in columns)
|
|
79
|
+
<div
|
|
80
|
+
class="{{ cellClasses }}"
|
|
81
|
+
style="flex: {{ column.width || 1 }}; min-width: {{ column.minWidth || 'auto' }}"
|
|
82
|
+
>
|
|
83
|
+
{!! getCellValue(row, column) !!}
|
|
84
|
+
</div>
|
|
85
|
+
@endforeach
|
|
86
|
+
</div>
|
|
87
|
+
@endforeach
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<script>
|
|
93
|
+
// Re-render on scroll (simplified reactivity)
|
|
94
|
+
if (typeof window !== 'undefined') {
|
|
95
|
+
let ticking = false
|
|
96
|
+
|
|
97
|
+
function updateVisibleRows() {
|
|
98
|
+
const range = getVisibleRange()
|
|
99
|
+
// Trigger re-render
|
|
100
|
+
ticking = false
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const bodyContainer = document.querySelector('.overflow-auto')
|
|
104
|
+
if (bodyContainer) {
|
|
105
|
+
bodyContainer.addEventListener('scroll', () => {
|
|
106
|
+
if (!ticking) {
|
|
107
|
+
window.requestAnimationFrame(updateVisibleRows)
|
|
108
|
+
ticking = true
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
</script>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
function I(j){let{code:x,onSuccess:O,onError:J,timeout:U=2000}=j,G=!1,Y=null;return{copied:G,copy:async()=>{try{if(!navigator.clipboard)throw Error("Clipboard API not available");await navigator.clipboard.writeText(x),G=!0,O?.(),Y=setTimeout(()=>{G=!1,Y=null},U)}catch(X){let z=X instanceof Error?X:Error("Failed to copy code");J?.(z),console.error("Failed to copy code:",z)}},reset:()=>{if(G=!1,Y)clearTimeout(Y),Y=null}}}async function R(j){try{return await navigator.clipboard.writeText(j),!0}catch(x){return console.error("Failed to copy to clipboard:",x),!1}}function Q(){if(typeof window>"u")return"light";return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function A(j){return j==="system"?Q():j}function M(j={}){let{storageKey:x="theme",defaultTheme:O="system"}=j,J=O;if(typeof window<"u"&&typeof localStorage<"u"){let N=localStorage.getItem(x);if(N)J=N}let U=A(J)==="dark",G=(N)=>{let X=A(N);if(typeof document<"u")if(X==="dark")document.documentElement.classList.add("dark");else document.documentElement.classList.remove("dark");if(typeof localStorage<"u")localStorage.setItem(x,N)},Y=(N)=>{J=N,G(N)},Z=()=>{let X=A(J)==="dark"?"light":"dark";Y(X)};if(G(J),typeof window<"u"&&J==="system")window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(N)=>{if(J==="system")G("system")});return{isDark:U,theme:J,toggle:Z,setTheme:Y}}function S(j,x){if(typeof document>"u")return;document.title=x?x.replace("%s",j):j}function D(j,x,O=!1){if(typeof document>"u")return;let J=O?"property":"name",U=document.querySelector(`meta[${J}="${j}"]`);if(!U)U=document.createElement("meta"),U.setAttribute(J,j),document.head.appendChild(U);U.setAttribute("content",x)}function C(j,x){if(typeof document>"u")return;let O=document.querySelector(`link[rel="${j}"]`);if(!O)O=document.createElement("link"),O.setAttribute("rel",j),document.head.appendChild(O);O.setAttribute("href",x)}function T(j){let{title:x,description:O,author:J,keywords:U,ogImage:G,ogImageWidth:Y,ogImageHeight:Z,twitterCard:N="summary_large_image",twitterSite:X,twitterCreator:z,canonical:_}=j;if(x)S(x),D("og:title",x,!0),D("twitter:title",x);if(O)D("description",O),D("og:description",O,!0),D("twitter:description",O);if(J)D("author",J);if(U&&U.length>0)D("keywords",U.join(", "));if(G)D("og:image",G,!0),D("twitter:image",G);if(Y)D("og:image:width",Y,!0);if(Z)D("og:image:height",Z,!0);if(D("twitter:card",N),X)D("twitter:site",X);if(z)D("twitter:creator",z);if(_)C("canonical",_);if(D("og:type","website",!0),typeof window<"u")D("og:url",window.location.href,!0)}function E(j){let x=[],{title:O,description:J,author:U,keywords:G,ogImage:Y,ogImageWidth:Z,ogImageHeight:N,twitterCard:X="summary_large_image",twitterSite:z,twitterCreator:_,canonical:q}=j;if(O)x.push(`<title>${P(O)}</title>`),x.push(`<meta property="og:title" content="${P(O)}" />`),x.push(`<meta name="twitter:title" content="${P(O)}" />`);if(J)x.push(`<meta name="description" content="${P(J)}" />`),x.push(`<meta property="og:description" content="${P(J)}" />`),x.push(`<meta name="twitter:description" content="${P(J)}" />`);if(U)x.push(`<meta name="author" content="${P(U)}" />`);if(G&&G.length>0)x.push(`<meta name="keywords" content="${P(G.join(", "))}" />`);if(Y)x.push(`<meta property="og:image" content="${P(Y)}" />`),x.push(`<meta name="twitter:image" content="${P(Y)}" />`);if(Z)x.push(`<meta property="og:image:width" content="${P(Z)}" />`);if(N)x.push(`<meta property="og:image:height" content="${P(N)}" />`);if(x.push(`<meta name="twitter:card" content="${P(X)}" />`),z)x.push(`<meta name="twitter:site" content="${P(z)}" />`);if(_)x.push(`<meta name="twitter:creator" content="${P(_)}" />`);if(q)x.push(`<link rel="canonical" href="${P(q)}" />`);return x.push('<meta property="og:type" content="website" />'),x.join(`
|
|
3
|
+
`)}function P(j){return j.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function w(j,x,O={}){let{enabled:J=!0,ignore:U=[]}=O,G=(Y)=>{if(!J||!j)return;let Z=Y.target;if(!j.contains(Z)){if(!U.some((X)=>{let z=document.querySelectorAll(X);return Array.from(z).some((_)=>_.contains(Z))}))x(Y)}};if(typeof document<"u")document.addEventListener("mousedown",G),document.addEventListener("touchstart",G);return()=>{if(typeof document<"u")document.removeEventListener("mousedown",G),document.removeEventListener("touchstart",G)}}function f(j,x={}){let{enabled:O=!0,initialFocus:J=null,returnFocus:U=!0,fallbackFocus:G=null}=x,Y=null,Z=!1;function N(){if(!j)return[];let $=["a[href]","button:not([disabled])","textarea:not([disabled])","input:not([disabled])","select:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(",");return Array.from(j.querySelectorAll($))}function X($){if(!O||!Z||!j)return;let K=N();if(K.length===0){$.preventDefault();return}let F=K[0],L=K[K.length-1];if($.shiftKey){if(document.activeElement===F||document.activeElement===j)$.preventDefault(),L.focus()}else if(document.activeElement===L)$.preventDefault(),F.focus()}function z($){if($.key==="Escape"&&O&&Z)q()}function _(){if(!O||!j||Z)return;if(Y=document.activeElement,J)J.focus();else{let $=N();if($.length>0)$[0].focus();else if(G)G.focus();else j.focus()}document.addEventListener("keydown",X),document.addEventListener("keydown",z),Z=!0}function q(){if(!Z)return;if(document.removeEventListener("keydown",X),document.removeEventListener("keydown",z),U&&Y)Y.focus();Z=!1}return{activate:_,deactivate:q}}function v(j,x={}){let{enabled:O=!0,preventDefault:J=!0,stopPropagation:U=!1,target:G=typeof document<"u"?document:null}=x,Y=Array.isArray(j)?j:[j],Z=(N)=>{if(!O)return;Y.forEach((X)=>{if(!(Array.isArray(X.key)?X.key:[X.key]).some((q)=>q.toLowerCase()===N.key.toLowerCase()))return;if(X.ctrl!==void 0&&X.ctrl!==N.ctrlKey)return;if(X.shift!==void 0&&X.shift!==N.shiftKey)return;if(X.alt!==void 0&&X.alt!==N.altKey)return;if(X.meta!==void 0&&X.meta!==N.metaKey)return;if(J)N.preventDefault();if(U)N.stopPropagation();X.handler(N)})};if(G)G.addEventListener("keydown",Z);return()=>{if(G)G.removeEventListener("keydown",Z)}}var g={ESCAPE:"Escape",ENTER:"Enter",SPACE:" ",TAB:"Tab",ARROW_UP:"ArrowUp",ARROW_DOWN:"ArrowDown",ARROW_LEFT:"ArrowLeft",ARROW_RIGHT:"ArrowRight",HOME:"Home",END:"End",PAGE_UP:"PageUp",PAGE_DOWN:"PageDown"};function u(j,x,O={}){let{serializer:J=JSON.stringify,deserializer:U=JSON.parse,onError:G=console.error}=O,Y=x;try{if(typeof window<"u"){let _=window.localStorage.getItem(j);if(_!==null)Y=U(_)}}catch(_){G(_)}let Z=Y,N=new Set;function X(_){try{let q=typeof _==="function"?_(Z):_;if(Z=q,typeof window<"u")window.localStorage.setItem(j,J(q));N.forEach(($)=>$(q))}catch(q){G(q)}}function z(){try{if(Z=x,typeof window<"u")window.localStorage.removeItem(j);N.forEach((_)=>_(x))}catch(_){G(_)}}if(typeof window<"u"){let _=(q)=>{if(q.key===j&&q.newValue!==null)try{let $=U(q.newValue);Z=$,N.forEach((K)=>K($))}catch($){G($)}else if(q.key===j&&q.newValue===null)Z=x,N.forEach(($)=>$(x))};window.addEventListener("storage",_)}return{value:Z,setValue:X,removeValue:z}}function W(j,x={}){let{defaultValue:O=!1}=x,J=O,U=null;if(typeof window<"u"&&"matchMedia"in window){U=window.matchMedia(j),J=U.matches;let Y=(Z)=>{J=Z.matches};if(U.addEventListener)U.addEventListener("change",Y);else U.addListener(Y)}function G(){if(U)J=U.matches}return{matches:J,updateMatches:G}}var B={xs:"(min-width: 320px)",sm:"(min-width: 640px)",md:"(min-width: 768px)",lg:"(min-width: 1024px)",xl:"(min-width: 1280px)","2xl":"(min-width: 1536px)",mobile:"(max-width: 767px)",tablet:"(min-width: 768px) and (max-width: 1023px)",desktop:"(min-width: 1024px)",dark:"(prefers-color-scheme: dark)",light:"(prefers-color-scheme: light)",reducedMotion:"(prefers-reduced-motion: reduce)",portrait:"(orientation: portrait)",landscape:"(orientation: landscape)"};function d(j){return W(B[j])}function m(){return W(B.mobile)}function c(){return W(B.desktop)}function o(){return W(B.dark)}function l(){return W(B.reducedMotion)}export{T as useSEO,l as usePrefersReducedMotion,W as useMediaQuery,u as useLocalStorage,v as useKeyboard,m as useIsMobile,c as useIsDesktop,o as useIsDarkMode,f as useFocusTrap,M as useDarkMode,I as useCopyCode,w as useClickOutside,d as useBreakpoint,S as setTitle,D as setMeta,C as setLink,Q as getSystemTheme,A as getEffectiveTheme,E as generateSEOTags,R as copyToClipboard,g as KeyboardShortcuts,B as Breakpoints};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare function useCopyCode(options: CopyCodeOptions): CopyCodeResult;
|
|
2
|
+
/**
|
|
3
|
+
* Simple synchronous copy function for direct use
|
|
4
|
+
*/
|
|
5
|
+
export declare function copyToClipboard(text: string): Promise<boolean>;
|
|
6
|
+
/**
|
|
7
|
+
* Copy code to clipboard with visual feedback
|
|
8
|
+
*/
|
|
9
|
+
export declare interface CopyCodeOptions {
|
|
10
|
+
code: string
|
|
11
|
+
onSuccess?: () => void
|
|
12
|
+
onError?: (error: Error) => void
|
|
13
|
+
timeout?: number
|
|
14
|
+
}
|
|
15
|
+
export declare interface CopyCodeResult {
|
|
16
|
+
copied: boolean
|
|
17
|
+
copy: () => Promise<void>
|
|
18
|
+
reset: () => void
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if system prefers dark mode
|
|
3
|
+
*/
|
|
4
|
+
export declare function getSystemTheme(): 'light' | 'dark';
|
|
5
|
+
/**
|
|
6
|
+
* Get the effective theme (resolving 'system' to actual theme)
|
|
7
|
+
*/
|
|
8
|
+
export declare function getEffectiveTheme(theme: 'light' | 'dark' | 'system'): 'light' | 'dark';
|
|
9
|
+
/**
|
|
10
|
+
* Use dark mode hook
|
|
11
|
+
*/
|
|
12
|
+
export declare function useDarkMode(options?: DarkModeOptions): DarkModeResult;
|
|
13
|
+
/**
|
|
14
|
+
* Dark mode utilities for STX components
|
|
15
|
+
*/
|
|
16
|
+
export declare interface DarkModeOptions {
|
|
17
|
+
storageKey?: string
|
|
18
|
+
defaultTheme?: 'light' | 'dark' | 'system'
|
|
19
|
+
}
|
|
20
|
+
export declare interface DarkModeResult {
|
|
21
|
+
isDark: boolean
|
|
22
|
+
theme: 'light' | 'dark' | 'system'
|
|
23
|
+
toggle: () => void
|
|
24
|
+
setTheme: (theme: 'light' | 'dark' | 'system') => void
|
|
25
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set document title
|
|
3
|
+
*/
|
|
4
|
+
export declare function setTitle(title: string, template?: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Set meta tag
|
|
7
|
+
*/
|
|
8
|
+
export declare function setMeta(name: string, content: string, isProperty?: any): void;
|
|
9
|
+
/**
|
|
10
|
+
* Set link tag
|
|
11
|
+
*/
|
|
12
|
+
export declare function setLink(rel: string, href: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Use SEO meta tags
|
|
15
|
+
*/
|
|
16
|
+
export declare function useSEO(options: SEOMetaOptions): void;
|
|
17
|
+
/**
|
|
18
|
+
* Generate SEO meta tags as HTML string for server-side rendering
|
|
19
|
+
*/
|
|
20
|
+
export declare function generateSEOTags(options: SEOMetaOptions): string;
|
|
21
|
+
/**
|
|
22
|
+
* SEO and meta tag utilities for STX components
|
|
23
|
+
*/
|
|
24
|
+
export declare interface SEOMetaOptions {
|
|
25
|
+
title?: string
|
|
26
|
+
description?: string
|
|
27
|
+
author?: string
|
|
28
|
+
keywords?: string[]
|
|
29
|
+
ogImage?: string
|
|
30
|
+
ogImageWidth?: string
|
|
31
|
+
ogImageHeight?: string
|
|
32
|
+
twitterCard?: 'summary' | 'summary_large_image' | 'app' | 'player'
|
|
33
|
+
twitterSite?: string
|
|
34
|
+
twitterCreator?: string
|
|
35
|
+
canonical?: string
|
|
36
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to detect clicks outside an element
|
|
3
|
+
*
|
|
4
|
+
* @param elementRef - The element to detect clicks outside of
|
|
5
|
+
* @param callback - Function to call when click occurs outside element
|
|
6
|
+
* @param options - Configuration options
|
|
7
|
+
* @returns Cleanup function to remove event listeners
|
|
8
|
+
*/
|
|
9
|
+
export declare function useClickOutside(elementRef: HTMLElement | null, callback: (event: MouseEvent | TouchEvent) => void, options?: UseClickOutsideOptions): () => void;
|
|
10
|
+
/**
|
|
11
|
+
* Detects clicks outside a specified element
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const cleanup = useClickOutside(
|
|
16
|
+
* modalRef,
|
|
17
|
+
* () => closeModal(),
|
|
18
|
+
* { enabled: isOpen, ignore: ['.tooltip'] }
|
|
19
|
+
* )
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Options for useClickOutside hook
|
|
24
|
+
*/
|
|
25
|
+
export declare interface UseClickOutsideOptions {
|
|
26
|
+
enabled?: boolean
|
|
27
|
+
ignore?: string[]
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to trap focus within an element
|
|
3
|
+
*
|
|
4
|
+
* @param containerRef - The container element to trap focus within
|
|
5
|
+
* @param options - Configuration options
|
|
6
|
+
* @returns Object with activate and deactivate functions
|
|
7
|
+
*/
|
|
8
|
+
export declare function useFocusTrap(containerRef: HTMLElement | null, options?: UseFocusTrapOptions): { activate: () => void, deactivate: () => void };
|
|
9
|
+
/**
|
|
10
|
+
* Traps focus within a container element (useful for modals, dialogs, dropdowns)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const { activate, deactivate } = useFocusTrap(modalRef, {
|
|
15
|
+
* initialFocus: firstInputRef,
|
|
16
|
+
* returnFocus: true
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* // When modal opens
|
|
20
|
+
* activate()
|
|
21
|
+
*
|
|
22
|
+
* // When modal closes
|
|
23
|
+
* deactivate()
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Options for useFocusTrap hook
|
|
28
|
+
*/
|
|
29
|
+
export declare interface UseFocusTrapOptions {
|
|
30
|
+
enabled?: boolean
|
|
31
|
+
initialFocus?: HTMLElement | null
|
|
32
|
+
returnFocus?: boolean
|
|
33
|
+
fallbackFocus?: HTMLElement | null
|
|
34
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for keyboard event handling
|
|
3
|
+
*
|
|
4
|
+
* @param handlers - Single handler or array of keyboard handlers
|
|
5
|
+
* @param options - Configuration options
|
|
6
|
+
* @returns Cleanup function to remove event listeners
|
|
7
|
+
*/
|
|
8
|
+
export declare function useKeyboard(handlers: KeyboardHandler | KeyboardHandler[], options?: UseKeyboardOptions): () => void;
|
|
9
|
+
// Common keyboard shortcuts
|
|
10
|
+
export declare const KeyboardShortcuts: {
|
|
11
|
+
ESCAPE: 'Escape';
|
|
12
|
+
ENTER: 'Enter';
|
|
13
|
+
SPACE: ' ';
|
|
14
|
+
TAB: 'Tab';
|
|
15
|
+
ARROW_UP: 'ArrowUp';
|
|
16
|
+
ARROW_DOWN: 'ArrowDown';
|
|
17
|
+
ARROW_LEFT: 'ArrowLeft';
|
|
18
|
+
ARROW_RIGHT: 'ArrowRight';
|
|
19
|
+
HOME: 'Home';
|
|
20
|
+
END: 'End';
|
|
21
|
+
PAGE_UP: 'PageUp';
|
|
22
|
+
PAGE_DOWN: 'PageDown'
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Hook for keyboard event handling with support for shortcuts and modifiers
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* useKeyboard([
|
|
30
|
+
* { key: 'Escape', handler: () => closeModal() },
|
|
31
|
+
* { key: 's', ctrl: true, handler: () => save() },
|
|
32
|
+
* { key: ['ArrowUp', 'ArrowDown'], handler: (e) => navigate(e.key) }
|
|
33
|
+
* ])
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Options for useKeyboard hook
|
|
38
|
+
*/
|
|
39
|
+
export declare interface UseKeyboardOptions {
|
|
40
|
+
enabled?: boolean
|
|
41
|
+
preventDefault?: boolean
|
|
42
|
+
stopPropagation?: boolean
|
|
43
|
+
target?: HTMLElement | Document | Window | null
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Keyboard event handler configuration
|
|
47
|
+
*/
|
|
48
|
+
export declare interface KeyboardHandler {
|
|
49
|
+
key: string | string[]
|
|
50
|
+
handler: (event: KeyboardEvent) => void
|
|
51
|
+
ctrl?: boolean
|
|
52
|
+
shift?: boolean
|
|
53
|
+
alt?: boolean
|
|
54
|
+
meta?: boolean
|
|
55
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for reactive localStorage with cross-tab sync
|
|
3
|
+
*
|
|
4
|
+
* @param key - Storage key
|
|
5
|
+
* @param initialValue - Initial value if key doesn't exist
|
|
6
|
+
* @param options - Configuration options
|
|
7
|
+
* @returns Object with value, setValue, and removeValue
|
|
8
|
+
*/
|
|
9
|
+
export declare function useLocalStorage<T>(key: string, initialValue: T, options?: UseLocalStorageOptions<T>): {
|
|
10
|
+
value: T
|
|
11
|
+
setValue: (newValue: T | ((prev: T) => T)) => void
|
|
12
|
+
removeValue: () => void
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Reactive localStorage hook with cross-tab synchronization
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const { value, setValue, removeValue } = useLocalStorage('user', { name: 'John' })
|
|
20
|
+
*
|
|
21
|
+
* setValue({ name: 'Jane' })
|
|
22
|
+
* setValue(prev => ({ ...prev, age: 30 }))
|
|
23
|
+
* removeValue()
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Options for useLocalStorage hook
|
|
28
|
+
*/
|
|
29
|
+
export declare interface UseLocalStorageOptions<T> {
|
|
30
|
+
serializer?: (value: T) => string
|
|
31
|
+
deserializer?: (value: string) => T
|
|
32
|
+
onError?: (error: Error) => void
|
|
33
|
+
}
|