@stacksjs/components 0.2.35 → 0.2.53
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/dist/Accordion-19x8q4rj.stx +88 -0
- package/dist/{Audio-vdmg1258.stx → Audio-hjywk3qc.stx} +4 -4
- package/dist/{Avatar-365cvrh4.stx → Avatar-h3jmwcq0.stx} +23 -34
- package/dist/{Badge-8m3qete4.stx → Badge-k8dy3d53.stx} +11 -19
- package/dist/{Button-3tt4vsqt.stx → Button-1vknasy3.stx} +18 -33
- package/dist/Calendar-reny0et7.stx +189 -0
- package/dist/{Card-6wdbexqr.stx → Card-c1g1fd1w.stx} +27 -33
- package/dist/{Checkbox-p3q3e3nf.stx → Checkbox-zgdmy3p5.stx} +36 -44
- package/dist/{Checkout-e4037tyy.stx → Checkout-agt0ngpw.stx} +8 -16
- package/dist/Combobox-fdkr6cdq.stx +96 -0
- package/dist/{ComboboxButton-8gxwkhdx.stx → ComboboxButton-g76stp1e.stx} +14 -2
- package/dist/{ComboboxInput-mk99z65n.stx → ComboboxInput-z1293bbh.stx} +12 -5
- package/dist/ComboboxOption-hmxt3gte.stx +49 -0
- package/dist/{ListboxOptions-8kqvfp7z.stx → ComboboxOptions-sq5360ae.stx} +2 -2
- package/dist/CommandPalette-36mxf05w.stx +81 -0
- package/dist/CommandPaletteItem-mvk6q7a2.stx +27 -0
- package/dist/Dialog-hczpexs4.stx +37 -0
- package/dist/{Drawer-p7m351bn.stx → Drawer-xhevp5cw.stx} +29 -49
- package/dist/Dropdown-vvhemtc0.stx +82 -0
- package/dist/{DropdownButton-9w8zkfwj.stx → DropdownButton-wcz67dxy.stx} +12 -6
- package/dist/DropdownItem-c7rz08e5.stx +35 -0
- package/dist/{DropdownItems-aygjpxkx.stx → DropdownItems-1sxnd5qn.stx} +2 -2
- package/dist/EmailInput-vak3kkmk.stx +30 -0
- package/dist/Form-mas630hy.stx +95 -0
- package/dist/{Image-jhkm6w1f.stx → Image-yhxcvgzs.stx} +68 -100
- package/dist/Listbox-q49tnr90.stx +101 -0
- package/dist/{ListboxButton-spwx7513.stx → ListboxButton-keb8gm0q.stx} +12 -1
- package/dist/ListboxOption-e0dtv1gc.stx +49 -0
- package/dist/{ComboboxOptions-6b5ywc5x.stx → ListboxOptions-ejkatcfg.stx} +7 -3
- package/dist/{Login-rx9gyqhx.stx → Login-gepemsth.stx} +17 -19
- package/dist/Navigator-rk2a5wvk.stx +113 -0
- package/dist/Notification-tb9b525s.stx +78 -0
- package/dist/{NumberInput-nzpkx1ry.stx → NumberInput-drnvtqej.stx} +40 -53
- package/dist/{Pagination-h61eq390.stx → Pagination-n3d31cns.stx} +73 -108
- package/dist/PasswordInput-n02x6053.stx +142 -0
- package/dist/{PaymentMethods-j42jsk5x.stx → PaymentMethods-x4vrx9yb.stx} +21 -30
- package/dist/Popover-et2q44m7.stx +60 -0
- package/dist/{PopoverButton-fnaqc77g.stx → PopoverButton-mffzc9pr.stx} +12 -6
- package/dist/{PopoverPanel-y0vtf5w9.stx → PopoverPanel-054yh38h.stx} +6 -6
- package/dist/{Portal-s2q37yp0.stx → Portal-1vf14s4x.stx} +20 -37
- package/dist/{Progress-vmdkm06p.stx → Progress-yxcntr4x.stx} +36 -48
- package/dist/{Radio-04bs3d21.stx → Radio-cgjv2hb2.stx} +29 -34
- package/dist/RadioGroup-qxmnm3xm.stx +60 -0
- package/dist/RadioGroupOption-s1d6r221.stx +58 -0
- package/dist/SearchInput-pdx7agn0.stx +44 -0
- package/dist/{Select-g4mmvfv8.stx → Select-28y0pg83.stx} +23 -31
- package/dist/Sidebar-73vc78as.stx +236 -0
- package/dist/SidebarFooter-zsfsgcxb.stx +109 -0
- package/dist/SidebarHeader-7v174a9c.stx +122 -0
- package/dist/SidebarItem-3y3e8g2t.stx +92 -0
- package/dist/SidebarSection-z5ey6awe.stx +113 -0
- package/dist/{Signup-c4dyv6f3.stx → Signup-hxm5hwkr.stx} +26 -28
- package/dist/{StepperStep-en4r00zv.stx → StepperStep-wxgembat.stx} +9 -5
- package/dist/{SubscriptionCheckout-gawjzf3q.stx → SubscriptionCheckout-zy2ycrmw.stx} +99 -129
- package/dist/Switch-r5t5w04w.stx +70 -0
- package/dist/{TableHeader-ydys9rzz.stx → TableHeader-0eyzbqpz.stx} +10 -3
- package/dist/Tabs-bzvvn4ke.stx +126 -0
- package/dist/Teleport-tsx4bt4n.stx +65 -0
- package/dist/{TextInput-k2kfkgy1.stx → TextInput-kf084763.stx} +42 -59
- package/dist/{Textarea-szad57dz.stx → Textarea-xg4rr2xz.stx} +42 -54
- package/dist/{Tooltip-em7t551n.stx → Tooltip-m0tqd72e.stx} +34 -40
- package/dist/Transition-7smenaz8.stx +102 -0
- package/dist/{TwoFactorChallenge-an9yvxvq.stx → TwoFactorChallenge-y5m3nk79.stx} +49 -63
- package/dist/{Video-crxva65p.stx → Video-84j4pv6h.stx} +4 -4
- package/dist/VirtualList-fa7v5a3h.stx +67 -0
- package/dist/VirtualTable-f9crbfjr.stx +103 -0
- package/dist/components/CodeBlock.stx +1 -6
- package/dist/index.js +13 -13
- package/dist/ui/accordion/Accordion.stx +1 -3
- package/dist/ui/auth/Login.stx +0 -1
- package/dist/ui/auth/Signup.stx +0 -1
- package/dist/ui/auth/TwoFactorChallenge.stx +1 -3
- package/dist/ui/avatar/Avatar.stx +0 -2
- package/dist/ui/badge/Badge.stx +0 -1
- package/dist/ui/button/Button.stx +1 -2
- package/dist/ui/calendar/Calendar.stx +12 -2
- package/dist/ui/card/Card.stx +0 -2
- package/dist/ui/checkbox/Checkbox.stx +2 -2
- package/dist/ui/combobox/Combobox.stx +2 -1
- package/dist/ui/combobox/ComboboxButton.stx +1 -0
- package/dist/ui/combobox/ComboboxInput.stx +1 -4
- package/dist/ui/combobox/ComboboxOption.stx +2 -9
- package/dist/ui/combobox/ComboboxOptions.stx +1 -1
- package/dist/ui/command-palette/CommandPalette.stx +3 -6
- package/dist/ui/command-palette/CommandPaletteItem.stx +2 -7
- package/dist/ui/dialog/Dialog.stx +1 -3
- package/dist/ui/drawer/Drawer.stx +1 -3
- package/dist/ui/dropdown/Dropdown.stx +2 -5
- package/dist/ui/dropdown/DropdownButton.stx +1 -3
- package/dist/ui/dropdown/DropdownItem.stx +2 -7
- package/dist/ui/dropdown/DropdownItems.stx +1 -1
- package/dist/ui/form/Form.stx +0 -5
- package/dist/ui/image/Image.stx +1 -6
- package/dist/ui/input/EmailInput.stx +1 -1
- package/dist/ui/input/NumberInput.stx +0 -1
- package/dist/ui/input/PasswordInput.stx +1 -4
- package/dist/ui/input/SearchInput.stx +2 -2
- package/dist/ui/input/TextInput.stx +1 -2
- package/dist/ui/listbox/Listbox.stx +2 -1
- package/dist/ui/listbox/ListboxButton.stx +1 -0
- package/dist/ui/listbox/ListboxOption.stx +2 -9
- package/dist/ui/listbox/ListboxOptions.stx +1 -1
- package/dist/ui/navigator/Navigator.stx +4 -4
- package/dist/ui/notification/Notification.stx +1 -5
- package/dist/ui/pagination/Pagination.stx +1 -2
- package/dist/ui/payment/Checkout.stx +0 -4
- package/dist/ui/payment/PaymentMethods.stx +15 -2
- package/dist/ui/payment/SubscriptionCheckout.stx +3 -184
- package/dist/ui/popover/Popover.stx +2 -5
- package/dist/ui/popover/PopoverButton.stx +1 -3
- package/dist/ui/popover/PopoverPanel.stx +1 -1
- package/dist/ui/portal/Portal.stx +1 -0
- package/dist/ui/progress/Progress.stx +6 -1
- package/dist/ui/radio/Radio.stx +1 -1
- package/dist/ui/radio-group/RadioGroup.stx +2 -1
- package/dist/ui/radio-group/RadioGroupOption.stx +2 -9
- package/dist/ui/select/Select.stx +1 -1
- package/dist/ui/sidebar/Sidebar.stx +9 -26
- package/dist/ui/sidebar/SidebarFooter.stx +6 -21
- package/dist/ui/sidebar/SidebarHeader.stx +7 -18
- package/dist/ui/sidebar/SidebarItem.stx +4 -20
- package/dist/ui/sidebar/SidebarSection.stx +5 -18
- package/dist/ui/sidebar/index.d.ts +13 -1
- package/dist/ui/stepper/StepperStep.stx +1 -5
- package/dist/ui/switch/Switch.stx +4 -10
- package/dist/ui/table/TableHeader.stx +1 -1
- package/dist/ui/tabs/Tabs.stx +0 -1
- package/dist/ui/teleport/Teleport.stx +1 -0
- package/dist/ui/textarea/Textarea.stx +1 -1
- package/dist/ui/tooltip/Tooltip.stx +1 -2
- package/dist/ui/transition/Transition.stx +9 -16
- package/dist/ui/virtual-list/VirtualList.stx +2 -4
- package/dist/ui/virtual-table/VirtualTable.stx +1 -1
- package/package.json +3 -3
- package/src/components/CodeBlock.stx +26 -29
- package/src/components/Footer.stx +1 -1
- package/src/components/Hero.stx +1 -1
- package/src/components/Installation.stx +5 -7
- package/src/ui/accordion/Accordion.stx +48 -68
- package/src/ui/audio/Audio.stx +4 -4
- package/src/ui/auth/Login.stx +17 -19
- package/src/ui/auth/Signup.stx +26 -28
- package/src/ui/auth/TwoFactorChallenge.stx +49 -63
- package/src/ui/avatar/Avatar.stx +23 -34
- package/src/ui/badge/Badge.stx +11 -19
- package/src/ui/button/Button.stx +18 -33
- package/src/ui/calendar/Calendar.stx +93 -136
- package/src/ui/card/Card.stx +27 -33
- package/src/ui/checkbox/Checkbox.stx +36 -44
- package/src/ui/combobox/Combobox.stx +87 -4
- package/src/ui/combobox/ComboboxButton.stx +14 -2
- package/src/ui/combobox/ComboboxInput.stx +12 -5
- package/src/ui/combobox/ComboboxOption.stx +29 -32
- package/src/ui/combobox/ComboboxOptions.stx +7 -3
- package/src/ui/command-palette/CommandPalette.stx +70 -28
- package/src/ui/command-palette/CommandPaletteItem.stx +15 -20
- package/src/ui/dialog/Dialog.stx +28 -10
- package/src/ui/drawer/Drawer.stx +29 -49
- package/src/ui/dropdown/Dropdown.stx +69 -11
- package/src/ui/dropdown/DropdownButton.stx +12 -6
- package/src/ui/dropdown/DropdownItem.stx +18 -26
- package/src/ui/dropdown/DropdownItems.stx +2 -2
- package/src/ui/form/Form.stx +50 -164
- package/src/ui/heatmap/Heatmap.stx +16 -37
- package/src/ui/image/Image.stx +68 -100
- package/src/ui/input/EmailInput.stx +16 -27
- package/src/ui/input/NumberInput.stx +40 -53
- package/src/ui/input/PasswordInput.stx +64 -77
- package/src/ui/input/SearchInput.stx +27 -46
- package/src/ui/input/TextInput.stx +42 -59
- package/src/ui/listbox/Listbox.stx +91 -4
- package/src/ui/listbox/ListboxButton.stx +12 -1
- package/src/ui/listbox/ListboxOption.stx +30 -38
- package/src/ui/listbox/ListboxOptions.stx +2 -2
- package/src/ui/navigator/Navigator.stx +52 -77
- package/src/ui/notification/Notification.stx +46 -39
- package/src/ui/pagination/Pagination.stx +73 -108
- package/src/ui/payment/Checkout.stx +8 -16
- package/src/ui/payment/PaymentMethods.stx +21 -30
- package/src/ui/payment/SubscriptionCheckout.stx +99 -129
- package/src/ui/popover/Popover.stx +50 -14
- package/src/ui/popover/PopoverButton.stx +12 -6
- package/src/ui/popover/PopoverPanel.stx +6 -6
- package/src/ui/portal/Portal.stx +20 -37
- package/src/ui/progress/Progress.stx +36 -48
- package/src/ui/radio/Radio.stx +29 -34
- package/src/ui/radio-group/RadioGroup.stx +51 -4
- package/src/ui/radio-group/RadioGroupOption.stx +37 -30
- package/src/ui/select/Select.stx +23 -31
- package/src/ui/sidebar/Sidebar.stx +136 -188
- package/src/ui/sidebar/SidebarFooter.stx +49 -35
- package/src/ui/sidebar/SidebarHeader.stx +52 -30
- package/src/ui/sidebar/SidebarItem.stx +52 -78
- package/src/ui/sidebar/SidebarSection.stx +56 -51
- package/src/ui/sidebar/index.ts +21 -1
- package/src/ui/stepper/StepperStep.stx +9 -5
- package/src/ui/switch/Switch.stx +38 -42
- package/src/ui/table/TableHeader.stx +10 -3
- package/src/ui/tabs/Tabs.stx +68 -87
- package/src/ui/teleport/Teleport.stx +23 -59
- package/src/ui/textarea/Textarea.stx +42 -54
- package/src/ui/tooltip/Tooltip.stx +34 -40
- package/src/ui/transition/Transition.stx +76 -148
- package/src/ui/video/Video.stx +4 -4
- package/src/ui/virtual-list/VirtualList.stx +45 -61
- package/src/ui/virtual-table/VirtualTable.stx +62 -72
- package/dist/Accordion-sbfra0mz.stx +0 -108
- package/dist/Calendar-58nnkdh8.stx +0 -232
- package/dist/Combobox-th5ebw62.stx +0 -13
- package/dist/ComboboxOption-an9zyan6.stx +0 -52
- package/dist/CommandPalette-kwmdf2np.stx +0 -39
- package/dist/CommandPaletteItem-zx2fbpts.stx +0 -32
- package/dist/Dialog-rgmj8q2j.stx +0 -19
- package/dist/Dropdown-jz4jy0n3.stx +0 -24
- package/dist/DropdownItem-wagdspb8.stx +0 -43
- package/dist/EmailInput-ajsp9vw6.stx +0 -41
- package/dist/Form-1mdmx9b6.stx +0 -209
- package/dist/Listbox-pqqh72g8.stx +0 -14
- package/dist/ListboxOption-7nxzaexq.stx +0 -57
- package/dist/Navigator-aay8bjab.stx +0 -138
- package/dist/Notification-gk33gv7b.stx +0 -71
- package/dist/PasswordInput-zv4hm43j.stx +0 -155
- package/dist/Popover-469gbt6r.stx +0 -24
- package/dist/RadioGroup-bvb1mrhd.stx +0 -13
- package/dist/RadioGroupOption-cpdwgnhw.stx +0 -51
- package/dist/SearchInput-2521m475.stx +0 -63
- package/dist/Sidebar-40ckbzh8.stx +0 -288
- package/dist/SidebarFooter-hnth56mg.stx +0 -95
- package/dist/SidebarHeader-3wrte2p2.stx +0 -100
- package/dist/SidebarItem-zqtvvzpc.stx +0 -118
- package/dist/SidebarSection-3etwnbjr.stx +0 -108
- package/dist/Switch-036j9vm1.stx +0 -74
- package/dist/Tabs-svh721m0.stx +0 -145
- package/dist/Teleport-qfch3w0b.stx +0 -101
- package/dist/Transition-0hmr6zxb.stx +0 -174
- package/dist/VirtualList-cndhjejh.stx +0 -83
- package/dist/VirtualTable-ng0b48yp.stx +0 -113
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script server>
|
|
2
2
|
export const value = $props.value || ''
|
|
3
|
-
export const onChange = $props.onChange || (() => {})
|
|
4
3
|
export const placeholder = $props.placeholder || ''
|
|
5
4
|
export const disabled = $props.disabled || false
|
|
6
5
|
export const readonly = $props.readonly || false
|
|
@@ -17,45 +16,51 @@ export const showCount = $props.showCount || false
|
|
|
17
16
|
export const className = $props.className || ''
|
|
18
17
|
export const inputClassName = $props.inputClassName || ''
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
sm: 'px-3 py-1.5 text-sm h-8',
|
|
23
|
-
md: 'px-4 py-2 text-base h-10',
|
|
24
|
-
lg: 'px-5 py-3 text-lg h-12',
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Icon size classes
|
|
28
|
-
const iconSizeClasses = {
|
|
29
|
-
sm: 'h-4 w-4',
|
|
30
|
-
md: 'h-5 w-5',
|
|
31
|
-
lg: 'h-6 w-6',
|
|
32
|
-
}
|
|
19
|
+
const sizeClasses = { sm: 'px-3 py-1.5 text-sm h-8', md: 'px-4 py-2 text-base h-10', lg: 'px-5 py-3 text-lg h-12' }
|
|
20
|
+
const iconSizeClasses = { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6' }
|
|
33
21
|
|
|
34
|
-
// Base and state classes
|
|
35
22
|
const baseClasses = 'block w-full border-0 rounded-md shadow-sm ring-1 ring-inset transition-colors duration-200 focus:ring-2 focus:ring-inset dark:bg-blue-gray-700 dark:text-gray-100'
|
|
36
|
-
|
|
37
23
|
const stateClasses = error
|
|
38
24
|
? 'ring-red-300 dark:ring-red-600 text-red-900 dark:text-red-300 placeholder-red-300 dark:placeholder-red-500 focus:ring-red-500 dark:focus:ring-red-400'
|
|
39
25
|
: 'ring-gray-300 dark:ring-gray-600 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-indigo-600 dark:focus:ring-indigo-400'
|
|
40
|
-
|
|
41
26
|
const disabledClasses = disabled
|
|
42
27
|
? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
|
|
43
28
|
: readonly
|
|
44
29
|
? 'bg-gray-50 dark:bg-gray-800 cursor-default'
|
|
45
30
|
: 'bg-white dark:bg-blue-gray-700'
|
|
46
|
-
|
|
47
31
|
const paddingClasses = leftIcon ? 'pl-10' : rightIcon || clearable ? 'pr-10' : ''
|
|
48
32
|
|
|
49
33
|
export const inputClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses} ${paddingClasses} ${inputClassName}`.trim()
|
|
50
34
|
export const labelClasses = `block text-sm font-medium leading-6 mb-2 ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'}`.trim()
|
|
51
35
|
export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
|
|
52
36
|
export const iconClasses = iconSizeClasses[size]
|
|
53
|
-
export const
|
|
37
|
+
export const inputId = `input-${label}`
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<script client>
|
|
41
|
+
const emit = defineEmits()
|
|
42
|
+
const inputValue = state({{ value }})
|
|
43
|
+
|
|
44
|
+
function onInput(event) {
|
|
45
|
+
inputValue.set(event.target.value)
|
|
46
|
+
emit('input', inputValue())
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function onClear() {
|
|
50
|
+
inputValue.set('')
|
|
51
|
+
emit('input', '')
|
|
52
|
+
emit('clear')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const hasValue = derived(() => inputValue().length > 0)
|
|
56
|
+
const charCount = derived(() => `${inputValue().length} / {{ maxLength || 0 }}`)
|
|
57
|
+
|
|
58
|
+
defineExpose({ value: inputValue, clear: onClear })
|
|
54
59
|
</script>
|
|
55
60
|
|
|
56
61
|
<div class="w-full {{ className }}">
|
|
57
62
|
@if(label)
|
|
58
|
-
<label for="
|
|
63
|
+
<label for="{{ inputId }}" class="{{ labelClasses }}">
|
|
59
64
|
{{ label }}
|
|
60
65
|
@if(required)
|
|
61
66
|
<span class="text-red-500 ml-1">*</span>
|
|
@@ -65,33 +70,31 @@ export const hasValue = value && value.length > 0
|
|
|
65
70
|
|
|
66
71
|
<div class="relative">
|
|
67
72
|
@if(leftIcon)
|
|
68
|
-
<!-- Left icon -->
|
|
69
73
|
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
|
70
|
-
<span class="{{ iconClasses }} text-gray-400 dark:text-gray-500"
|
|
74
|
+
<span class="{{ iconClasses }} text-gray-400 dark:text-gray-500">{!! leftIcon !!}</span>
|
|
71
75
|
</div>
|
|
72
76
|
@endif
|
|
73
77
|
|
|
74
78
|
<input
|
|
75
79
|
type="text"
|
|
76
|
-
id="
|
|
80
|
+
id="{{ inputId }}"
|
|
77
81
|
class="{{ inputClasses }}"
|
|
78
|
-
value="
|
|
82
|
+
:value="inputValue()"
|
|
79
83
|
placeholder="{{ placeholder }}"
|
|
80
|
-
disabled
|
|
81
|
-
readonly
|
|
82
|
-
required
|
|
84
|
+
@if(disabled)disabled@endif
|
|
85
|
+
@if(readonly)readonly@endif
|
|
86
|
+
@if(required)required@endif
|
|
83
87
|
@if(maxLength)maxlength="{{ maxLength }}"@endif
|
|
84
|
-
|
|
85
|
-
aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
88
|
+
@input="onInput($event)"
|
|
89
|
+
:aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
86
90
|
@if(helperText)aria-describedby="helper-text"@endif
|
|
87
91
|
/>
|
|
88
92
|
|
|
89
|
-
@if(clearable
|
|
90
|
-
|
|
91
|
-
<div class="absolute inset-y-0 right-0 flex items-center pr-3">
|
|
93
|
+
@if(clearable)
|
|
94
|
+
<div :show="hasValue() && !{{ disabled }} && !{{ readonly }}" class="absolute inset-y-0 right-0 flex items-center pr-3">
|
|
92
95
|
<button
|
|
93
96
|
type="button"
|
|
94
|
-
@click="
|
|
97
|
+
@click="onClear()"
|
|
95
98
|
class="text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 focus:outline-none"
|
|
96
99
|
aria-label="Clear input"
|
|
97
100
|
>
|
|
@@ -100,13 +103,11 @@ export const hasValue = value && value.length > 0
|
|
|
100
103
|
</svg>
|
|
101
104
|
</button>
|
|
102
105
|
</div>
|
|
103
|
-
@
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
</div>
|
|
109
|
-
@endif
|
|
106
|
+
@endif
|
|
107
|
+
@if(rightIcon && !clearable)
|
|
108
|
+
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
|
|
109
|
+
<span class="{{ iconClasses }} text-gray-400 dark:text-gray-500">{!! rightIcon !!}</span>
|
|
110
|
+
</div>
|
|
110
111
|
@endif
|
|
111
112
|
</div>
|
|
112
113
|
|
|
@@ -121,26 +122,8 @@ export const hasValue = value && value.length > 0
|
|
|
121
122
|
@endif
|
|
122
123
|
|
|
123
124
|
@if(showCount && maxLength)
|
|
124
|
-
<p class="text-sm text-gray-500 dark:text-gray-400">
|
|
125
|
-
{{ value.length }} / {{ maxLength }}
|
|
126
|
-
</p>
|
|
125
|
+
<p class="text-sm text-gray-500 dark:text-gray-400" x-text="charCount()"></p>
|
|
127
126
|
@endif
|
|
128
127
|
</div>
|
|
129
128
|
@endif
|
|
130
129
|
</div>
|
|
131
|
-
|
|
132
|
-
<script>
|
|
133
|
-
function handleInput(event) {
|
|
134
|
-
const newValue = event.target.value
|
|
135
|
-
|
|
136
|
-
if (onChange) {
|
|
137
|
-
onChange(newValue)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function handleClear() {
|
|
142
|
-
if (onChange) {
|
|
143
|
-
onChange('')
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
</script>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script server>
|
|
2
2
|
export const value = $props.value || ''
|
|
3
|
-
export const onChange = $props.onChange || (() => {})
|
|
4
3
|
export const placeholder = $props.placeholder || ''
|
|
5
4
|
export const disabled = $props.disabled || false
|
|
6
5
|
export const readonly = $props.readonly || false
|
|
@@ -13,24 +12,14 @@ export const helperText = $props.helperText || ''
|
|
|
13
12
|
export const required = $props.required || false
|
|
14
13
|
export const maxLength = $props.maxLength
|
|
15
14
|
export const showCount = $props.showCount || false
|
|
16
|
-
export const resize = $props.resize || 'vertical'
|
|
15
|
+
export const resize = $props.resize || 'vertical'
|
|
17
16
|
export const className = $props.className || ''
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
const resizeClasses = {
|
|
21
|
-
none: 'resize-none',
|
|
22
|
-
vertical: 'resize-y',
|
|
23
|
-
horizontal: 'resize-x',
|
|
24
|
-
both: 'resize',
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Base and state classes
|
|
18
|
+
const resizeClasses = { none: 'resize-none', vertical: 'resize-y', horizontal: 'resize-x', both: 'resize' }
|
|
28
19
|
const baseClasses = 'block w-full border-0 rounded-md shadow-sm ring-1 ring-inset transition-colors duration-200 focus:ring-2 focus:ring-inset px-4 py-2 text-base dark:bg-blue-gray-700 dark:text-gray-100'
|
|
29
|
-
|
|
30
20
|
const stateClasses = error
|
|
31
21
|
? 'ring-red-300 dark:ring-red-600 text-red-900 dark:text-red-300 placeholder-red-300 dark:placeholder-red-500 focus:ring-red-500 dark:focus:ring-red-400'
|
|
32
22
|
: 'ring-gray-300 dark:ring-gray-600 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-indigo-600 dark:focus:ring-indigo-400'
|
|
33
|
-
|
|
34
23
|
const disabledClasses = disabled
|
|
35
24
|
? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
|
|
36
25
|
: readonly
|
|
@@ -42,6 +31,40 @@ export const labelClasses = `block text-sm font-medium leading-6 mb-2 ${error ?
|
|
|
42
31
|
export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
|
|
43
32
|
</script>
|
|
44
33
|
|
|
34
|
+
<script client>
|
|
35
|
+
const emit = defineEmits()
|
|
36
|
+
const autoResize = {{ autoResize }}
|
|
37
|
+
const maxRows = {{ maxRows }}
|
|
38
|
+
const inputValue = state({{ value }})
|
|
39
|
+
|
|
40
|
+
function resizeTextarea(el) {
|
|
41
|
+
if (!autoResize) return
|
|
42
|
+
el.style.height = 'auto'
|
|
43
|
+
const scrollHeight = el.scrollHeight
|
|
44
|
+
const lineHeight = Number.parseInt(window.getComputedStyle(el).lineHeight) || 20
|
|
45
|
+
const maxHeight = lineHeight * maxRows
|
|
46
|
+
el.style.height = `${Math.min(scrollHeight, maxHeight)}px`
|
|
47
|
+
el.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function onInput(event) {
|
|
51
|
+
inputValue.set(event.target.value)
|
|
52
|
+
resizeTextarea(event.target)
|
|
53
|
+
emit('input', inputValue())
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onMount(() => {
|
|
57
|
+
if (autoResize) {
|
|
58
|
+
const el = document.getElementById('textarea-input')
|
|
59
|
+
if (el) resizeTextarea(el)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const charCount = derived(() => `${inputValue().length} / {{ maxLength || 0 }}`)
|
|
64
|
+
|
|
65
|
+
defineExpose({ value: inputValue })
|
|
66
|
+
</script>
|
|
67
|
+
|
|
45
68
|
<div class="w-full">
|
|
46
69
|
@if(label)
|
|
47
70
|
<label for="textarea-input" class="{{ labelClasses }}">
|
|
@@ -57,12 +80,12 @@ export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red
|
|
|
57
80
|
class="{{ textareaClasses }}"
|
|
58
81
|
rows="{{ rows }}"
|
|
59
82
|
placeholder="{{ placeholder }}"
|
|
60
|
-
disabled
|
|
61
|
-
readonly
|
|
62
|
-
required
|
|
83
|
+
@if(disabled)disabled@endif
|
|
84
|
+
@if(readonly)readonly@endif
|
|
85
|
+
@if(required)required@endif
|
|
63
86
|
@if(maxLength)maxlength="{{ maxLength }}"@endif
|
|
64
|
-
|
|
65
|
-
aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
87
|
+
@input="onInput($event)"
|
|
88
|
+
:aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
66
89
|
@if(helperText)aria-describedby="helper-text"@endif
|
|
67
90
|
>{{ value }}</textarea>
|
|
68
91
|
|
|
@@ -77,43 +100,8 @@ export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red
|
|
|
77
100
|
@endif
|
|
78
101
|
|
|
79
102
|
@if(showCount && maxLength)
|
|
80
|
-
<p class="text-sm text-gray-500 dark:text-gray-400">
|
|
81
|
-
{{ value.length }} / {{ maxLength }}
|
|
82
|
-
</p>
|
|
103
|
+
<p class="text-sm text-gray-500 dark:text-gray-400" x-text="charCount()"></p>
|
|
83
104
|
@endif
|
|
84
105
|
</div>
|
|
85
106
|
@endif
|
|
86
107
|
</div>
|
|
87
|
-
|
|
88
|
-
<script>
|
|
89
|
-
function handleInput(event) {
|
|
90
|
-
const textarea = event.target
|
|
91
|
-
const newValue = textarea.value
|
|
92
|
-
|
|
93
|
-
if (autoResize && typeof window !== 'undefined') {
|
|
94
|
-
// Auto-resize functionality
|
|
95
|
-
textarea.style.height = 'auto'
|
|
96
|
-
const scrollHeight = textarea.scrollHeight
|
|
97
|
-
const lineHeight = parseInt(window.getComputedStyle(textarea).lineHeight)
|
|
98
|
-
const maxHeight = lineHeight * maxRows
|
|
99
|
-
|
|
100
|
-
textarea.style.height = Math.min(scrollHeight, maxHeight) + 'px'
|
|
101
|
-
textarea.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden'
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (onChange) {
|
|
105
|
-
onChange(newValue)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Initialize auto-resize on mount
|
|
110
|
-
if (autoResize && typeof window !== 'undefined') {
|
|
111
|
-
window.addEventListener('DOMContentLoaded', () => {
|
|
112
|
-
const textarea = document.getElementById('textarea-input')
|
|
113
|
-
if (textarea && value) {
|
|
114
|
-
// Trigger initial resize
|
|
115
|
-
textarea.dispatchEvent(new Event('input'))
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
</script>
|
|
@@ -6,7 +6,6 @@ export const className = $props.className || ''
|
|
|
6
6
|
export const show = $props.show || false
|
|
7
7
|
export const disabled = $props.disabled || false
|
|
8
8
|
|
|
9
|
-
// Position classes
|
|
10
9
|
const positionClasses = {
|
|
11
10
|
top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
|
|
12
11
|
bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
|
|
@@ -14,7 +13,6 @@ const positionClasses = {
|
|
|
14
13
|
right: 'left-full top-1/2 -translate-y-1/2 ml-2',
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
// Arrow classes
|
|
18
16
|
const arrowClasses = {
|
|
19
17
|
top: 'top-full left-1/2 -translate-x-1/2 border-t-gray-900 dark:border-t-gray-700',
|
|
20
18
|
bottom: 'bottom-full left-1/2 -translate-x-1/2 border-b-gray-900 dark:border-b-gray-700',
|
|
@@ -22,55 +20,51 @@ const arrowClasses = {
|
|
|
22
20
|
right: 'right-full top-1/2 -translate-y-1/2 border-r-gray-900 dark:border-r-gray-700',
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
export const tooltipClasses = `absolute z-50 px-3 py-2 text-sm font-medium text-white bg-gray-900 dark:bg-gray-700 rounded-lg shadow-lg whitespace-nowrap pointer-events-none
|
|
23
|
+
export const tooltipClasses = `absolute z-50 px-3 py-2 text-sm font-medium text-white bg-gray-900 dark:bg-gray-700 rounded-lg shadow-lg whitespace-nowrap pointer-events-none transition-opacity duration-200 ${positionClasses[position]} ${className}`.trim()
|
|
26
24
|
export const arrowClass = `absolute w-0 h-0 border-4 border-transparent ${arrowClasses[position]}`.trim()
|
|
27
|
-
|
|
28
|
-
let isVisible = show
|
|
29
|
-
let timeoutId = null
|
|
30
25
|
</script>
|
|
31
26
|
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
onfocus="handleMouseEnter()"
|
|
38
|
-
onblur="handleMouseLeave()"
|
|
39
|
-
>
|
|
40
|
-
<slot />
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
<!-- Tooltip -->
|
|
44
|
-
@if(isVisible && !disabled)
|
|
45
|
-
<div
|
|
46
|
-
class="{{ tooltipClasses }}"
|
|
47
|
-
role="tooltip"
|
|
48
|
-
style="opacity: 1"
|
|
49
|
-
>
|
|
50
|
-
{{ content }}
|
|
51
|
-
<div class="{{ arrowClass }}"></div>
|
|
52
|
-
</div>
|
|
53
|
-
@endif
|
|
54
|
-
</div>
|
|
55
|
-
|
|
56
|
-
<script>
|
|
57
|
-
function handleMouseEnter() {
|
|
58
|
-
if (disabled) return
|
|
27
|
+
<script client>
|
|
28
|
+
const delay = {{ delay }}
|
|
29
|
+
const isDisabled = {{ disabled }}
|
|
30
|
+
const isVisible = state({{ show }})
|
|
31
|
+
let timeoutId = null
|
|
59
32
|
|
|
33
|
+
function showTooltip() {
|
|
34
|
+
if (isDisabled) return
|
|
60
35
|
if (delay > 0) {
|
|
61
|
-
timeoutId = setTimeout(() =>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
isVisible = true
|
|
36
|
+
timeoutId = setTimeout(() => isVisible.set(true), delay)
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
isVisible.set(true)
|
|
66
40
|
}
|
|
67
41
|
}
|
|
68
42
|
|
|
69
|
-
function
|
|
43
|
+
function hideTooltip() {
|
|
70
44
|
if (timeoutId) {
|
|
71
45
|
clearTimeout(timeoutId)
|
|
72
46
|
timeoutId = null
|
|
73
47
|
}
|
|
74
|
-
isVisible
|
|
48
|
+
isVisible.set(false)
|
|
75
49
|
}
|
|
76
50
|
</script>
|
|
51
|
+
|
|
52
|
+
<div class="relative inline-block {{ disabled ? 'cursor-not-allowed' : '' }}">
|
|
53
|
+
<div
|
|
54
|
+
@mouseenter="showTooltip()"
|
|
55
|
+
@mouseleave="hideTooltip()"
|
|
56
|
+
@focusin="showTooltip()"
|
|
57
|
+
@focusout="hideTooltip()"
|
|
58
|
+
>
|
|
59
|
+
<slot />
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div
|
|
63
|
+
:show="isVisible() && !{{ disabled }}"
|
|
64
|
+
class="{{ tooltipClasses }}"
|
|
65
|
+
role="tooltip"
|
|
66
|
+
>
|
|
67
|
+
{{ content }}
|
|
68
|
+
<div class="{{ arrowClass }}"></div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
export const show = $props.show !== false
|
|
3
|
+
export const enter = $props.enter || 'transition-opacity duration-300'
|
|
4
|
+
export const enterFrom = $props.enterFrom || 'opacity-0'
|
|
5
|
+
export const enterTo = $props.enterTo || 'opacity-100'
|
|
6
|
+
export const leave = $props.leave || 'transition-opacity duration-200'
|
|
7
|
+
export const leaveFrom = $props.leaveFrom || 'opacity-100'
|
|
8
|
+
export const leaveTo = $props.leaveTo || 'opacity-0'
|
|
9
|
+
export const appear = $props.appear || false
|
|
10
|
+
export const duration = $props.duration || 300
|
|
11
|
+
export const delay = $props.delay || 0
|
|
12
|
+
export const preset = $props.preset || ''
|
|
13
|
+
export const className = $props.className || ''
|
|
14
|
+
|
|
15
|
+
const presets = {
|
|
16
|
+
fade: { enter: 'transition-opacity', enterFrom: 'opacity-0', enterTo: 'opacity-100', leave: 'transition-opacity', leaveFrom: 'opacity-100', leaveTo: 'opacity-0' },
|
|
17
|
+
slide: { enter: 'transition-transform', enterFrom: 'translate-y-2', enterTo: 'translate-y-0', leave: 'transition-transform', leaveFrom: 'translate-y-0', leaveTo: 'translate-y-2' },
|
|
18
|
+
slideLeft: { enter: 'transition-transform', enterFrom: 'translate-x-full', enterTo: 'translate-x-0', leave: 'transition-transform', leaveFrom: 'translate-x-0', leaveTo: '-translate-x-full' },
|
|
19
|
+
slideRight: { enter: 'transition-transform', enterFrom: '-translate-x-full', enterTo: 'translate-x-0', leave: 'transition-transform', leaveFrom: 'translate-x-0', leaveTo: 'translate-x-full' },
|
|
20
|
+
scale: { enter: 'transition-transform', enterFrom: 'scale-95', enterTo: 'scale-100', leave: 'transition-transform', leaveFrom: 'scale-100', leaveTo: 'scale-95' },
|
|
21
|
+
rotate: { enter: 'transition-transform', enterFrom: 'rotate-12 scale-95', enterTo: 'rotate-0 scale-100', leave: 'transition-transform', leaveFrom: 'rotate-0 scale-100', leaveTo: '-rotate-12 scale-95' },
|
|
22
|
+
zoom: { enter: 'transition-all', enterFrom: 'scale-0 opacity-0', enterTo: 'scale-100 opacity-100', leave: 'transition-all', leaveFrom: 'scale-100 opacity-100', leaveTo: 'scale-0 opacity-0' },
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const p = preset && presets[preset] ? presets[preset] : {}
|
|
26
|
+
export const enterClass = p.enter || enter
|
|
27
|
+
export const enterFromClass = p.enterFrom || enterFrom
|
|
28
|
+
export const enterToClass = p.enterTo || enterTo
|
|
29
|
+
export const leaveClass = p.leave || leave
|
|
30
|
+
export const leaveFromClass = p.leaveFrom || leaveFrom
|
|
31
|
+
export const leaveToClass = p.leaveTo || leaveTo
|
|
32
|
+
|
|
33
|
+
export const durationStyle = `transition-duration: ${duration}ms; transition-delay: ${delay}ms;`
|
|
34
|
+
export const extraClass = className
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<script client>
|
|
38
|
+
const emit = defineEmits()
|
|
39
|
+
const showProp = {{ show }}
|
|
40
|
+
const appear = {{ appear }}
|
|
41
|
+
const duration = {{ duration }}
|
|
42
|
+
const delay = {{ delay }}
|
|
43
|
+
const enterClass = {{ enterClass }}
|
|
44
|
+
const enterFromClass = {{ enterFromClass }}
|
|
45
|
+
const enterToClass = {{ enterToClass }}
|
|
46
|
+
const leaveClass = {{ leaveClass }}
|
|
47
|
+
const leaveFromClass = {{ leaveFromClass }}
|
|
48
|
+
const leaveToClass = {{ leaveToClass }}
|
|
49
|
+
const extraClass = {{ extraClass }}
|
|
50
|
+
|
|
51
|
+
const visible = state(showProp)
|
|
52
|
+
const isEntering = state(appear && showProp)
|
|
53
|
+
const isLeaving = state(false)
|
|
54
|
+
const shouldRender = state(showProp)
|
|
55
|
+
|
|
56
|
+
const transitionClass = derived(() => {
|
|
57
|
+
if (visible()) {
|
|
58
|
+
return isEntering() ? `${enterClass} ${enterFromClass}` : enterToClass
|
|
59
|
+
}
|
|
60
|
+
return isLeaving() ? `${leaveClass} ${leaveFromClass}` : leaveToClass
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const componentClass = derived(() => `${transitionClass()} ${extraClass}`.trim())
|
|
64
|
+
|
|
65
|
+
function setShow(next) {
|
|
66
|
+
if (next === visible()) return
|
|
67
|
+
if (next) {
|
|
68
|
+
emit('beforeEnter')
|
|
69
|
+
shouldRender.set(true)
|
|
70
|
+
visible.set(true)
|
|
71
|
+
isEntering.set(true)
|
|
72
|
+
setTimeout(() => emit('enter'), delay)
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
isEntering.set(false)
|
|
75
|
+
emit('afterEnter')
|
|
76
|
+
}, duration + delay)
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
emit('beforeLeave')
|
|
80
|
+
visible.set(false)
|
|
81
|
+
isLeaving.set(true)
|
|
82
|
+
setTimeout(() => emit('leave'), delay)
|
|
83
|
+
setTimeout(() => {
|
|
84
|
+
isLeaving.set(false)
|
|
85
|
+
shouldRender.set(false)
|
|
86
|
+
emit('afterLeave')
|
|
87
|
+
}, duration + delay)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
onMount(() => {
|
|
92
|
+
if (appear && showProp) {
|
|
93
|
+
setTimeout(() => isEntering.set(false), duration + delay)
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
defineExpose({ visible, setShow })
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<div :show="shouldRender()" :class="componentClass()" style="{{ durationStyle }}">
|
|
101
|
+
<slot />
|
|
102
|
+
</div>
|
|
@@ -3,12 +3,53 @@ export const headingText = $props.headingText || 'Two Factor Authentication'
|
|
|
3
3
|
export const labelText = $props.labelText || 'Authentication code'
|
|
4
4
|
export const instructionText = $props.instructionText || 'Open your Symantec 2FA app to view your authentication code.'
|
|
5
5
|
export const codeLength = $props.codeLength || 6
|
|
6
|
-
export const
|
|
7
|
-
export const onUseRecoveryCode = $props.onUseRecoveryCode
|
|
6
|
+
export const showRecoveryCode = $props.showRecoveryCode ?? true
|
|
8
7
|
export const className = $props.className || ''
|
|
9
8
|
|
|
10
9
|
export const containerClasses = `py-32 dark:bg-blue-gray-900 ${className}`.trim()
|
|
11
|
-
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<script client>
|
|
13
|
+
const emit = defineEmits()
|
|
14
|
+
const codeLength = {{ codeLength }}
|
|
15
|
+
|
|
16
|
+
function onCodeInput(event, index) {
|
|
17
|
+
const input = event.target
|
|
18
|
+
const value = input.value
|
|
19
|
+
if (!/^\d*$/.test(value)) {
|
|
20
|
+
input.value = ''
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
if (value.length === 1 && index < codeLength - 1) {
|
|
24
|
+
document.getElementById(`code-${index + 1}`)?.focus()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function onKeyDown(event, index) {
|
|
29
|
+
if (event.key === 'Backspace' && !event.target.value && index > 0) {
|
|
30
|
+
document.getElementById(`code-${index - 1}`)?.focus()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function onSubmit(event) {
|
|
35
|
+
event.preventDefault()
|
|
36
|
+
const code = []
|
|
37
|
+
for (let i = 0; i < codeLength; i++) {
|
|
38
|
+
const input = document.getElementById(`code-${i}`)
|
|
39
|
+
if (input?.value) code.push(input.value)
|
|
40
|
+
}
|
|
41
|
+
if (code.length === codeLength) {
|
|
42
|
+
emit('submit', code.join(''))
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
emit('error', { message: 'Please enter all digits' })
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function onRecoveryCode(event) {
|
|
50
|
+
event.preventDefault()
|
|
51
|
+
emit('useRecoveryCode')
|
|
52
|
+
}
|
|
12
53
|
</script>
|
|
13
54
|
|
|
14
55
|
<div class="{{ containerClasses }}">
|
|
@@ -21,7 +62,7 @@ export const codes = Array(codeLength).fill('')
|
|
|
21
62
|
<label for="code-0" class="mt-4 block text-sm text-gray-900 dark:text-gray-100 font-medium leading-6">
|
|
22
63
|
{{ labelText }}
|
|
23
64
|
</label>
|
|
24
|
-
<form
|
|
65
|
+
<form @submit="onSubmit($event)">
|
|
25
66
|
<div class="mt-2 flex rounded-md shadow-sm space-x-2">
|
|
26
67
|
@for(i in Array(codeLength).keys())
|
|
27
68
|
<input
|
|
@@ -31,8 +72,8 @@ export const codes = Array(codeLength).fill('')
|
|
|
31
72
|
name="code-{{ i }}"
|
|
32
73
|
placeholder="-"
|
|
33
74
|
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
|
-
|
|
35
|
-
|
|
75
|
+
@input="onCodeInput($event, {{ i }})"
|
|
76
|
+
@keydown="onKeyDown($event, {{ i }})"
|
|
36
77
|
/>
|
|
37
78
|
@endfor
|
|
38
79
|
</div>
|
|
@@ -50,14 +91,14 @@ export const codes = Array(codeLength).fill('')
|
|
|
50
91
|
{{ instructionText }}
|
|
51
92
|
</p>
|
|
52
93
|
</div>
|
|
53
|
-
@if(
|
|
94
|
+
@if(showRecoveryCode)
|
|
54
95
|
<div class="mt-4">
|
|
55
96
|
<p class="text-xs text-gray-700 dark:text-gray-300 font-semibold">
|
|
56
97
|
Having Problems?
|
|
57
98
|
</p>
|
|
58
99
|
<a
|
|
59
100
|
href="#"
|
|
60
|
-
@click="event
|
|
101
|
+
@click="onRecoveryCode($event)"
|
|
61
102
|
class="text-xs text-blue-500 hover:underline"
|
|
62
103
|
>
|
|
63
104
|
Use recovery code instead
|
|
@@ -68,58 +109,3 @@ export const codes = Array(codeLength).fill('')
|
|
|
68
109
|
</div>
|
|
69
110
|
</div>
|
|
70
111
|
</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>
|
|
@@ -31,10 +31,10 @@ export const aspectRatioClass = aspectRatio === '16/9' ? 'aspect-video' : aspect
|
|
|
31
31
|
class="{{ videoClasses }}"
|
|
32
32
|
src="{{ src }}"
|
|
33
33
|
poster="{{ poster }}"
|
|
34
|
-
controls
|
|
35
|
-
autoplay
|
|
36
|
-
loop
|
|
37
|
-
muted
|
|
34
|
+
@if(controls)controls@endif
|
|
35
|
+
@if(autoplay)autoplay@endif
|
|
36
|
+
@if(loop)loop@endif
|
|
37
|
+
@if(muted)muted@endif
|
|
38
38
|
preload="{{ preload }}"
|
|
39
39
|
width="{{ width }}"
|
|
40
40
|
height="{{ height }}"
|