webcoreui 1.1.0-beta.3 → 1.2.0-0
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 +47 -4
- package/astro.d.ts +5 -0
- package/astro.js +2 -0
- package/components/BottomNavigation/BottomNavigation.astro +1 -3
- package/components/Breadcrumb/Breadcrumb.astro +1 -3
- package/components/Carousel/Carousel.astro +79 -9
- package/components/Carousel/Carousel.svelte +40 -9
- package/components/Carousel/Carousel.tsx +46 -11
- package/components/Carousel/carousel.ts +3 -1
- package/components/ContextMenu/ContextMenu.astro +8 -3
- package/components/ContextMenu/ContextMenu.svelte +7 -2
- package/components/ContextMenu/ContextMenu.tsx +7 -2
- package/components/Copy/Copy.astro +3 -5
- package/components/Copy/Copy.svelte +1 -1
- package/components/Copy/Copy.tsx +1 -1
- package/components/Input/input.ts +62 -62
- package/components/Modal/Modal.astro +75 -75
- package/components/Modal/modal.ts +25 -25
- package/components/OTPInput/OTPInput.astro +194 -96
- package/components/OTPInput/OTPInput.svelte +141 -26
- package/components/OTPInput/OTPInput.tsx +140 -36
- package/components/OTPInput/otpinput.module.scss +59 -85
- package/components/Pagination/Pagination.astro +3 -3
- package/components/Pagination/Pagination.svelte +4 -4
- package/components/Pagination/pagination.module.scss +3 -3
- package/components/RangeSlider/RangeSlider.astro +270 -0
- package/components/RangeSlider/RangeSlider.svelte +188 -0
- package/components/RangeSlider/RangeSlider.tsx +205 -0
- package/components/RangeSlider/rangeslider.module.scss +143 -0
- package/components/RangeSlider/rangeslider.ts +37 -0
- package/components/Sidebar/Sidebar.astro +1 -3
- package/components/Stepper/Stepper.astro +1 -3
- package/index.d.ts +23 -4
- package/index.js +2 -0
- package/package.json +109 -103
- package/react.d.ts +5 -0
- package/react.js +2 -0
- package/scss/global/breakpoints.scss +15 -0
- package/scss/setup.scss +7 -1
- package/svelte.d.ts +5 -0
- package/svelte.js +2 -0
- package/utils/DOMUtils.ts +27 -2
- package/utils/bodyFreeze.ts +1 -1
- package/utils/context.ts +2 -2
- package/utils/getBreakpoint.ts +17 -0
- package/utils/isOneOf.ts +5 -0
- package/utils/modal.ts +54 -55
- package/utils/toast.ts +1 -1
- package/utils/webcore.ts +0 -28
|
@@ -1,96 +1,194 @@
|
|
|
1
|
-
---
|
|
2
|
-
import type { OTPInputProps } from './otpinput'
|
|
3
|
-
|
|
4
|
-
import Input from '../Input/Input.astro'
|
|
5
|
-
|
|
6
|
-
import styles from './otpinput.module.scss'
|
|
7
|
-
|
|
8
|
-
interface Props extends OTPInputProps {}
|
|
9
|
-
|
|
10
|
-
const {
|
|
11
|
-
name,
|
|
12
|
-
disabled,
|
|
13
|
-
length = 6,
|
|
14
|
-
groupLength = 0,
|
|
15
|
-
separator = '•',
|
|
16
|
-
label,
|
|
17
|
-
subText,
|
|
18
|
-
className,
|
|
19
|
-
...rest
|
|
20
|
-
} = Astro.props
|
|
21
|
-
|
|
22
|
-
const classes = [
|
|
23
|
-
styles.wrapper,
|
|
24
|
-
className
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
.reduce<(number | string)[]>((acc, num, i) =>
|
|
29
|
-
groupLength > 0 && i % groupLength === 0 && i !== 0
|
|
30
|
-
? [...acc, separator, num]
|
|
31
|
-
: [...acc, num]
|
|
32
|
-
, [])
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
<div class:list={classes}>
|
|
36
|
-
{label && (
|
|
37
|
-
<label
|
|
38
|
-
for={name}
|
|
39
|
-
class={styles.label}
|
|
40
|
-
set:html={label}
|
|
41
|
-
/>
|
|
42
|
-
)}
|
|
43
|
-
|
|
44
|
-
<div class={styles['input-wrapper']}>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
data-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
1
|
+
---
|
|
2
|
+
import type { OTPInputProps } from './otpinput'
|
|
3
|
+
|
|
4
|
+
import Input from '../Input/Input.astro'
|
|
5
|
+
|
|
6
|
+
import styles from './otpinput.module.scss'
|
|
7
|
+
|
|
8
|
+
interface Props extends OTPInputProps {}
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
name = 'otp',
|
|
12
|
+
disabled,
|
|
13
|
+
length = 6,
|
|
14
|
+
groupLength = 0,
|
|
15
|
+
separator = '•',
|
|
16
|
+
label,
|
|
17
|
+
subText,
|
|
18
|
+
className,
|
|
19
|
+
...rest
|
|
20
|
+
} = Astro.props
|
|
21
|
+
|
|
22
|
+
const classes = [
|
|
23
|
+
styles.wrapper,
|
|
24
|
+
className
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
const inputs = Array.from({ length }, (_, i) => i + 1)
|
|
28
|
+
.reduce<(number | string)[]>((acc, num, i) =>
|
|
29
|
+
groupLength > 0 && i % groupLength === 0 && i !== 0
|
|
30
|
+
? [...acc, separator, num]
|
|
31
|
+
: [...acc, num]
|
|
32
|
+
, [])
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<div class:list={classes}>
|
|
36
|
+
{label && (
|
|
37
|
+
<label
|
|
38
|
+
for={`${name}-0`}
|
|
39
|
+
class={styles.label}
|
|
40
|
+
set:html={label}
|
|
41
|
+
/>
|
|
42
|
+
)}
|
|
43
|
+
|
|
44
|
+
<div class={styles['input-wrapper']} data-length={length}>
|
|
45
|
+
{inputs.map((input, index) =>
|
|
46
|
+
typeof input === 'string' ? (
|
|
47
|
+
<div class={styles.separator}>{input}</div>
|
|
48
|
+
) : (
|
|
49
|
+
<Input
|
|
50
|
+
id={`${name}-${index}`}
|
|
51
|
+
class={styles.input}
|
|
52
|
+
type="text"
|
|
53
|
+
maxlength="1"
|
|
54
|
+
disabled={disabled}
|
|
55
|
+
inputmode="numeric"
|
|
56
|
+
autocomplete="one-time-code"
|
|
57
|
+
data-id="w-input-otp"
|
|
58
|
+
data-index={input}
|
|
59
|
+
aria-label={`OTP digit ${input + 1}`}
|
|
60
|
+
{...rest}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
{subText && <div class={styles.subtext}>{subText}</div>}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<script>
|
|
70
|
+
import { on } from '../../utils/DOMUtils'
|
|
71
|
+
import { dispatch } from '../../utils/event'
|
|
72
|
+
|
|
73
|
+
const focus = (direction: 'next' | 'prev', wrapper: HTMLElement | null, clear?: boolean) => {
|
|
74
|
+
const index = Number(wrapper?.dataset.active)
|
|
75
|
+
const nextIndex = direction === 'next' ? index + 1 : index - 1
|
|
76
|
+
|
|
77
|
+
const input = wrapper?.querySelector(`[data-index="${nextIndex}"]`)
|
|
78
|
+
|
|
79
|
+
if (input instanceof HTMLInputElement) {
|
|
80
|
+
input.focus()
|
|
81
|
+
|
|
82
|
+
if (clear) {
|
|
83
|
+
input.value = ''
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const addEventListeners = () => {
|
|
89
|
+
on('[data-id="w-input-otp"]', 'keydown', (event: KeyboardEvent) => {
|
|
90
|
+
const target = event.target as HTMLInputElement
|
|
91
|
+
|
|
92
|
+
if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
93
|
+
if (!target.value) {
|
|
94
|
+
focus('prev', target.parentElement, true)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (event.key === 'ArrowLeft') {
|
|
99
|
+
focus('prev', target.parentElement)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (event.key === 'ArrowRight') {
|
|
103
|
+
focus('next', target.parentElement)
|
|
104
|
+
}
|
|
105
|
+
}, true)
|
|
106
|
+
|
|
107
|
+
on('[data-id="w-input-otp"]', 'input', (event: Event) => {
|
|
108
|
+
const target = event.target
|
|
109
|
+
|
|
110
|
+
if (!(target instanceof HTMLInputElement)) {
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const index = Number(target.dataset.index)
|
|
115
|
+
const emptyIndex = Array.from(target.parentElement?.querySelectorAll('input') || [])
|
|
116
|
+
.findIndex(element => !element.value) + 1
|
|
117
|
+
|
|
118
|
+
if (emptyIndex !== 0 && emptyIndex < index) {
|
|
119
|
+
const emptyElement = target.parentElement?.querySelector(`[data-index="${emptyIndex}"]`)
|
|
120
|
+
const nextFocusElement = target.parentElement?.querySelector(`[data-index="${emptyIndex + 1}"]`)
|
|
121
|
+
|
|
122
|
+
if (emptyElement instanceof HTMLInputElement) {
|
|
123
|
+
emptyElement.value = target.value
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (nextFocusElement instanceof HTMLInputElement) {
|
|
127
|
+
nextFocusElement.focus()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
target.value = ''
|
|
131
|
+
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (target.value) {
|
|
136
|
+
focus('next', target.parentElement)
|
|
137
|
+
}
|
|
138
|
+
}, true)
|
|
139
|
+
|
|
140
|
+
on('[data-id="w-input-otp"]', 'keyup', (event: Event) => {
|
|
141
|
+
const target = event.target
|
|
142
|
+
const container = target instanceof HTMLInputElement ? target.parentElement : null
|
|
143
|
+
|
|
144
|
+
if (container) {
|
|
145
|
+
const value = Array.from(container.querySelectorAll('input') || [])
|
|
146
|
+
.map(input => input.value)
|
|
147
|
+
.join('')
|
|
148
|
+
|
|
149
|
+
dispatch('otpOnChange', value)
|
|
150
|
+
}
|
|
151
|
+
}, true)
|
|
152
|
+
|
|
153
|
+
on('[data-id="w-input-otp"]', 'paste', (event: ClipboardEvent) => {
|
|
154
|
+
event.preventDefault()
|
|
155
|
+
|
|
156
|
+
const target = event.target
|
|
157
|
+
const container = target instanceof HTMLInputElement ? target.parentElement : null
|
|
158
|
+
|
|
159
|
+
if (container) {
|
|
160
|
+
const inputLength = Number(container.dataset.length)
|
|
161
|
+
const paste = event.clipboardData?.getData('text') ?? ''
|
|
162
|
+
const nextIndex = Math.min(paste.length + 1, inputLength)
|
|
163
|
+
const focusInput = container.querySelector(`[data-index="${nextIndex}"]`)
|
|
164
|
+
|
|
165
|
+
if (focusInput instanceof HTMLInputElement) {
|
|
166
|
+
focusInput.focus()
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
paste.split('').slice(0, inputLength).forEach((char, i) => {
|
|
170
|
+
const input = container.querySelector(`[data-index="${i + 1}"]`)
|
|
171
|
+
|
|
172
|
+
if (input instanceof HTMLInputElement) {
|
|
173
|
+
input.value = char
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
}
|
|
177
|
+
}, true)
|
|
178
|
+
|
|
179
|
+
on('[data-id="w-input-otp"]', 'focus', (event: Event) => {
|
|
180
|
+
const target = event.target
|
|
181
|
+
|
|
182
|
+
if (target instanceof HTMLInputElement) {
|
|
183
|
+
if (target.parentElement) {
|
|
184
|
+
target.parentElement.dataset.active = target.dataset.index
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
setTimeout(() => target.select(), 0)
|
|
188
|
+
}
|
|
189
|
+
}, true)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
on(document, 'astro:after-swap', addEventListeners)
|
|
193
|
+
addEventListeners()
|
|
194
|
+
</script>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import styles from './otpinput.module.scss'
|
|
9
9
|
|
|
10
10
|
let {
|
|
11
|
-
name,
|
|
11
|
+
name = 'otp',
|
|
12
12
|
disabled,
|
|
13
13
|
length = 6,
|
|
14
14
|
groupLength = 0,
|
|
@@ -25,44 +25,159 @@
|
|
|
25
25
|
className
|
|
26
26
|
])
|
|
27
27
|
|
|
28
|
-
const
|
|
28
|
+
const inputs = Array.from({ length }, (_, i) => i + 1)
|
|
29
29
|
.reduce<(number | string)[]>((acc, num, i) =>
|
|
30
30
|
groupLength > 0 && i % groupLength === 0 && i !== 0
|
|
31
31
|
? [...acc, separator, num]
|
|
32
32
|
: [...acc, num]
|
|
33
33
|
, [])
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
const focus = (direction: 'next' | 'prev', wrapper: HTMLElement | null, clear?: boolean) => {
|
|
36
|
+
const index = Number(wrapper?.dataset.active)
|
|
37
|
+
const nextIndex = direction === 'next' ? index + 1 : index - 1
|
|
38
|
+
|
|
39
|
+
const input = wrapper?.querySelector(`[data-index="${nextIndex}"]`)
|
|
40
|
+
|
|
41
|
+
if (input instanceof HTMLInputElement) {
|
|
42
|
+
input.focus()
|
|
43
|
+
|
|
44
|
+
if (clear) {
|
|
45
|
+
input.value = ''
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
51
|
+
const target = event.target as HTMLInputElement
|
|
52
|
+
|
|
53
|
+
if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
54
|
+
if (!target.value) {
|
|
55
|
+
focus('prev', target.parentElement, true)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (event.key === 'ArrowLeft') {
|
|
60
|
+
focus('prev', target.parentElement)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (event.key === 'ArrowRight') {
|
|
64
|
+
focus('next', target.parentElement)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const handleInput = (event: Event) => {
|
|
69
|
+
const target = event.target
|
|
70
|
+
|
|
71
|
+
if (!(target instanceof HTMLInputElement)) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const index = Number(target.dataset.index)
|
|
76
|
+
const emptyIndex = Array.from(target.parentElement?.querySelectorAll('input') || [])
|
|
77
|
+
.findIndex(element => !element.value) + 1
|
|
78
|
+
|
|
79
|
+
if (emptyIndex !== 0 && emptyIndex < index) {
|
|
80
|
+
const emptyElement = target.parentElement?.querySelector(`[data-index="${emptyIndex}"]`)
|
|
81
|
+
const nextFocusElement = target.parentElement?.querySelector(`[data-index="${emptyIndex + 1}"]`)
|
|
82
|
+
|
|
83
|
+
if (emptyElement instanceof HTMLInputElement) {
|
|
84
|
+
emptyElement.value = target.value
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (nextFocusElement instanceof HTMLInputElement) {
|
|
88
|
+
nextFocusElement.focus()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
target.value = ''
|
|
92
|
+
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (target.value) {
|
|
97
|
+
focus('next', target.parentElement)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const handlePaste = (event: ClipboardEvent) => {
|
|
102
|
+
event.preventDefault()
|
|
103
|
+
|
|
104
|
+
const target = event.target
|
|
105
|
+
const container = target instanceof HTMLInputElement ? target.parentElement : null
|
|
106
|
+
|
|
107
|
+
if (container) {
|
|
108
|
+
const paste = event.clipboardData?.getData('text') ?? ''
|
|
109
|
+
const nextIndex = Math.min(paste.length + 1, length)
|
|
110
|
+
const focusInput = container.querySelector(`[data-index="${nextIndex}"]`)
|
|
111
|
+
|
|
112
|
+
if (focusInput instanceof HTMLInputElement) {
|
|
113
|
+
focusInput.focus()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
paste.split('').slice(0, length).forEach((char, i) => {
|
|
117
|
+
const input = container.querySelector(`[data-index="${i + 1}"]`)
|
|
118
|
+
|
|
119
|
+
if (input instanceof HTMLInputElement) {
|
|
120
|
+
input.value = char
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const handleFocus = (event: Event) => {
|
|
127
|
+
const target = event.target
|
|
128
|
+
|
|
129
|
+
if (target instanceof HTMLInputElement) {
|
|
130
|
+
if (target.parentElement) {
|
|
131
|
+
target.parentElement.dataset.active = target.dataset.index
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
setTimeout(() => target.select(), 0)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const handleKeyUp = (event: Event) => {
|
|
139
|
+
const target = event.target
|
|
140
|
+
const container = target instanceof HTMLInputElement ? target.parentElement : null
|
|
141
|
+
|
|
142
|
+
if (container) {
|
|
143
|
+
const newValue = Array.from(container.querySelectorAll('input') || [])
|
|
144
|
+
.map(input => input.value)
|
|
145
|
+
.join('')
|
|
146
|
+
|
|
147
|
+
value = newValue
|
|
148
|
+
}
|
|
149
|
+
}
|
|
39
150
|
</script>
|
|
40
151
|
|
|
41
152
|
<div class={classes}>
|
|
42
153
|
{#if label}
|
|
43
|
-
<label for={name} class={styles.label}>{@html label}</label>
|
|
154
|
+
<label for={`${name}-0`} class={styles.label}>{@html label}</label>
|
|
44
155
|
{/if}
|
|
45
156
|
|
|
46
157
|
<div class={styles['input-wrapper']}>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
158
|
+
{#each inputs as input, index}
|
|
159
|
+
{#if typeof input === 'string'}
|
|
160
|
+
<div class={styles.separator}>{input}</div>
|
|
161
|
+
{:else}
|
|
162
|
+
<Input
|
|
163
|
+
id={`${name}-${index}`}
|
|
164
|
+
className={styles.input}
|
|
165
|
+
type="text"
|
|
166
|
+
maxlength="1"
|
|
167
|
+
disabled={disabled}
|
|
168
|
+
inputmode="numeric"
|
|
169
|
+
autocomplete="one-time-code"
|
|
170
|
+
data-index={input}
|
|
171
|
+
aria-label={`OTP digit ${input + 1}`}
|
|
172
|
+
onkeydown={handleKeyDown}
|
|
173
|
+
onKeyUp={handleKeyUp}
|
|
174
|
+
onfocus={handleFocus}
|
|
175
|
+
onInput={handleInput}
|
|
176
|
+
onpaste={handlePaste}
|
|
177
|
+
{...rest}
|
|
178
|
+
/>
|
|
179
|
+
{/if}
|
|
180
|
+
{/each}
|
|
66
181
|
</div>
|
|
67
182
|
|
|
68
183
|
{#if subText}
|