webcoreui 1.1.0 → 1.2.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 +9 -1
- 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/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
|
@@ -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}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
import type { OTPInputProps } from './otpinput'
|
|
3
3
|
|
|
4
4
|
import Input from '../Input/Input.tsx'
|
|
@@ -8,7 +8,7 @@ import { classNames } from '../../utils/classNames'
|
|
|
8
8
|
import styles from './otpinput.module.scss'
|
|
9
9
|
|
|
10
10
|
const OTPInput = ({
|
|
11
|
-
name,
|
|
11
|
+
name = 'otp',
|
|
12
12
|
disabled,
|
|
13
13
|
length = 6,
|
|
14
14
|
groupLength = 0,
|
|
@@ -16,68 +16,172 @@ const OTPInput = ({
|
|
|
16
16
|
label,
|
|
17
17
|
subText,
|
|
18
18
|
className,
|
|
19
|
-
value,
|
|
20
19
|
onChange,
|
|
21
20
|
...rest
|
|
22
21
|
}: OTPInputProps) => {
|
|
23
|
-
const [inputValue, setValue] = useState(value || '')
|
|
24
|
-
|
|
25
22
|
const classes = classNames([
|
|
26
23
|
styles.wrapper,
|
|
27
24
|
className
|
|
28
25
|
])
|
|
29
26
|
|
|
30
|
-
const
|
|
27
|
+
const inputs = Array.from({ length }, (_, i) => i + 1)
|
|
31
28
|
.reduce<(number | string)[]>((acc, num, i) =>
|
|
32
29
|
groupLength > 0 && i % groupLength === 0 && i !== 0
|
|
33
30
|
? [...acc, separator, num]
|
|
34
31
|
: [...acc, num]
|
|
35
32
|
, [])
|
|
36
33
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
const focus = (direction: 'next' | 'prev', wrapper: HTMLElement | null, clear?: boolean) => {
|
|
35
|
+
const index = Number(wrapper?.dataset.active)
|
|
36
|
+
const nextIndex = direction === 'next' ? index + 1 : index - 1
|
|
37
|
+
|
|
38
|
+
const input = wrapper?.querySelector(`[data-index="${nextIndex}"]`)
|
|
39
|
+
|
|
40
|
+
if (input instanceof HTMLInputElement) {
|
|
41
|
+
input.focus()
|
|
42
|
+
|
|
43
|
+
if (clear) {
|
|
44
|
+
input.value = ''
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
50
|
+
const target = event.target as HTMLInputElement
|
|
51
|
+
|
|
52
|
+
if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
53
|
+
if (!target.value) {
|
|
54
|
+
focus('prev', target.parentElement, true)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (event.key === 'ArrowLeft') {
|
|
59
|
+
focus('prev', target.parentElement)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (event.key === 'ArrowRight') {
|
|
63
|
+
focus('next', target.parentElement)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const handleInput = (event: React.FormEvent<HTMLInputElement>) => {
|
|
68
|
+
const target = event.target
|
|
69
|
+
|
|
70
|
+
if (!(target instanceof HTMLInputElement)) {
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const index = Number(target.dataset.index)
|
|
75
|
+
const emptyIndex = Array.from(target.parentElement?.querySelectorAll('input') || [])
|
|
76
|
+
.findIndex(element => !element.value) + 1
|
|
77
|
+
|
|
78
|
+
if (emptyIndex !== 0 && emptyIndex < index) {
|
|
79
|
+
const emptyElement = target.parentElement?.querySelector(`[data-index="${emptyIndex}"]`)
|
|
80
|
+
const nextFocusElement = target.parentElement?.querySelector(`[data-index="${emptyIndex + 1}"]`)
|
|
81
|
+
|
|
82
|
+
if (emptyElement instanceof HTMLInputElement) {
|
|
83
|
+
emptyElement.value = target.value
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (nextFocusElement instanceof HTMLInputElement) {
|
|
87
|
+
nextFocusElement.focus()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
target.value = ''
|
|
91
|
+
|
|
92
|
+
return
|
|
93
|
+
}
|
|
41
94
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
95
|
+
if (target.value) {
|
|
96
|
+
focus('next', target.parentElement)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const handlePaste = (event: ClipboardEvent) => {
|
|
101
|
+
event.preventDefault()
|
|
102
|
+
|
|
103
|
+
const target = event.target
|
|
104
|
+
const container = target instanceof HTMLInputElement ? target.parentElement : null
|
|
105
|
+
|
|
106
|
+
if (container) {
|
|
107
|
+
const paste = event.clipboardData?.getData('text') ?? ''
|
|
108
|
+
const nextIndex = Math.min(paste.length + 1, length)
|
|
109
|
+
const focusInput = container.querySelector(`[data-index="${nextIndex}"]`)
|
|
110
|
+
|
|
111
|
+
if (focusInput instanceof HTMLInputElement) {
|
|
112
|
+
focusInput.focus()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
paste.split('').slice(0, length).forEach((char, i) => {
|
|
116
|
+
const input = container.querySelector(`[data-index="${i + 1}"]`)
|
|
117
|
+
|
|
118
|
+
if (input instanceof HTMLInputElement) {
|
|
119
|
+
input.value = char
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const handleFocus = (event: Event) => {
|
|
126
|
+
const target = event.target
|
|
127
|
+
|
|
128
|
+
if (target instanceof HTMLInputElement) {
|
|
129
|
+
if (target.parentElement) {
|
|
130
|
+
target.parentElement.dataset.active = target.dataset.index
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
setTimeout(() => target.select(), 0)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
138
|
+
const target = event.target
|
|
139
|
+
const container = target instanceof HTMLInputElement ? target.parentElement : null
|
|
140
|
+
|
|
141
|
+
if (container) {
|
|
142
|
+
const newValue = Array.from(container.querySelectorAll('input') || [])
|
|
143
|
+
.map(input => input.value)
|
|
144
|
+
.join('')
|
|
145
|
+
|
|
146
|
+
onChange?.(newValue)
|
|
147
|
+
}
|
|
45
148
|
}
|
|
46
149
|
|
|
47
150
|
return (
|
|
48
151
|
<div className={classes}>
|
|
49
152
|
{label && (
|
|
50
153
|
<label
|
|
51
|
-
htmlFor={name}
|
|
154
|
+
htmlFor={`${name}-0`}
|
|
52
155
|
className={styles.label}
|
|
53
156
|
dangerouslySetInnerHTML={{ __html: label }}
|
|
54
157
|
/>
|
|
55
158
|
)}
|
|
56
159
|
|
|
57
160
|
<div className={styles['input-wrapper']}>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
value={inputValue}
|
|
64
|
-
onChange={updateInput}
|
|
65
|
-
{...rest}
|
|
66
|
-
/>
|
|
67
|
-
|
|
68
|
-
<div className={styles.placeholders}>
|
|
69
|
-
{inputPlaceholders.map((placeholder, index) => (
|
|
70
|
-
<div
|
|
161
|
+
{inputs.map((input, index) =>
|
|
162
|
+
typeof input === 'string' ? (
|
|
163
|
+
<div className={styles.separator} key={index}>{input}</div>
|
|
164
|
+
) : (
|
|
165
|
+
<Input
|
|
71
166
|
key={index}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
167
|
+
id={`${name}-${index}`}
|
|
168
|
+
className={styles.input}
|
|
169
|
+
type="text"
|
|
170
|
+
maxLength={1}
|
|
171
|
+
disabled={disabled}
|
|
172
|
+
inputMode="numeric"
|
|
173
|
+
autoComplete="one-time-code"
|
|
174
|
+
data-index={input}
|
|
175
|
+
aria-label={`OTP digit ${input + 1}`}
|
|
176
|
+
onKeyDown={handleKeyDown}
|
|
177
|
+
onKeyUp={handleKeyUp}
|
|
178
|
+
onFocus={handleFocus}
|
|
179
|
+
onInput={handleInput}
|
|
180
|
+
onPaste={handlePaste}
|
|
181
|
+
{...rest}
|
|
182
|
+
/>
|
|
183
|
+
)
|
|
184
|
+
)}
|
|
81
185
|
</div>
|
|
82
186
|
|
|
83
187
|
{subText && (
|
|
@@ -1,85 +1,59 @@
|
|
|
1
|
-
@use '../../scss/config.scss' as *;
|
|
2
|
-
|
|
3
|
-
.wrapper {
|
|
4
|
-
@include layout(flex, column, xs);
|
|
5
|
-
|
|
6
|
-
.label {
|
|
7
|
-
@include typography(primary-20);
|
|
8
|
-
@include spacing(mb-xs);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.input-wrapper {
|
|
12
|
-
@include position(relative);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@include
|
|
17
|
-
@include size(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@include border
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
@include
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
+ .placeholder {
|
|
61
|
-
@include border(left, primary-50);
|
|
62
|
-
|
|
63
|
-
&[data-active="true"] {
|
|
64
|
-
@include border(left, primary);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.subtext {
|
|
70
|
-
@include typography(md, primary-30);
|
|
71
|
-
@include spacing(mt-xs);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@keyframes flash {
|
|
76
|
-
0% {
|
|
77
|
-
@include visibility(0);
|
|
78
|
-
}
|
|
79
|
-
50% {
|
|
80
|
-
@include visibility(1);
|
|
81
|
-
}
|
|
82
|
-
100% {
|
|
83
|
-
@include visibility(0);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
1
|
+
@use '../../scss/config.scss' as *;
|
|
2
|
+
|
|
3
|
+
.wrapper {
|
|
4
|
+
@include layout(flex, column, xs);
|
|
5
|
+
|
|
6
|
+
.label {
|
|
7
|
+
@include typography(primary-20);
|
|
8
|
+
@include spacing(mb-xs);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.input-wrapper {
|
|
12
|
+
@include position(relative);
|
|
13
|
+
@include layout(flex);
|
|
14
|
+
|
|
15
|
+
input {
|
|
16
|
+
@include border-radius(none);
|
|
17
|
+
@include size(40px);
|
|
18
|
+
@include typography(center, default);
|
|
19
|
+
|
|
20
|
+
&:not(:first-child) {
|
|
21
|
+
@include border(left, 0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&:first-child {
|
|
25
|
+
@include border-radius(left);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:last-child {
|
|
29
|
+
@include border-radius(right);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.separator + input {
|
|
34
|
+
@include border(left, primary-50);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.separator {
|
|
39
|
+
@include size(40px);
|
|
40
|
+
@include layout(flex, center);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.subtext {
|
|
44
|
+
@include typography(md, primary-30);
|
|
45
|
+
@include spacing(mt-xs);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@keyframes flash {
|
|
50
|
+
0% {
|
|
51
|
+
@include visibility(0);
|
|
52
|
+
}
|
|
53
|
+
50% {
|
|
54
|
+
@include visibility(1);
|
|
55
|
+
}
|
|
56
|
+
100% {
|
|
57
|
+
@include visibility(0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -139,20 +139,20 @@ const generatedPages = pages?.length
|
|
|
139
139
|
|
|
140
140
|
Array.from(paginations).forEach(element => {
|
|
141
141
|
const pagination = element as HTMLUListElement
|
|
142
|
-
const totalPages = Number(pagination.dataset.totalPages)
|
|
143
142
|
let currentPage = Number(pagination.dataset.currentPage)
|
|
144
143
|
|
|
145
144
|
element.addEventListener('click', event => {
|
|
146
145
|
const target = event.target as HTMLButtonElement
|
|
147
146
|
const navigated = target.nodeName === 'BUTTON'
|
|
148
|
-
&&
|
|
147
|
+
&& target.dataset.active !== 'true'
|
|
149
148
|
&& !target.disabled
|
|
150
149
|
|
|
151
150
|
if (navigated) {
|
|
152
151
|
const prevPageButton = element.querySelector('[data-page="prev"]') as HTMLButtonElement
|
|
153
152
|
const nextPageButton = element.querySelector('[data-page="next"]') as HTMLButtonElement
|
|
154
|
-
const currentPageButton = element.querySelector('[data-active]') as HTMLButtonElement
|
|
153
|
+
const currentPageButton = element.querySelector('[data-active="true"]') as HTMLButtonElement
|
|
155
154
|
const previousPage = currentPage
|
|
155
|
+
const totalPages = Number(pagination.dataset.totalPages)
|
|
156
156
|
|
|
157
157
|
const pageElements = Array
|
|
158
158
|
.from(pagination.children)
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
className
|
|
36
36
|
])
|
|
37
37
|
|
|
38
|
-
const calculatedTotalPages = totalPages
|
|
38
|
+
const calculatedTotalPages = $derived(totalPages
|
|
39
39
|
|| pages?.length
|
|
40
|
-
|| 0
|
|
40
|
+
|| 0)
|
|
41
41
|
|
|
42
|
-
const generatedPages = pages?.length
|
|
42
|
+
const generatedPages = $derived(pages?.length
|
|
43
43
|
? pages
|
|
44
44
|
: Array(totalPages || 0).fill(0).map((_, index) => ({
|
|
45
45
|
...(index === 0 && { active: true }),
|
|
46
46
|
label: index + 1
|
|
47
|
-
}))
|
|
47
|
+
})))
|
|
48
48
|
|
|
49
49
|
const paginate = (to: string | number) => {
|
|
50
50
|
const previousPage = calculatedCurrentPage
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
list-style-type: none;
|
|
8
8
|
|
|
9
|
-
&.primary [data-active] {
|
|
9
|
+
&.primary [data-active="true"] {
|
|
10
10
|
@include typography(primary-70);
|
|
11
11
|
@include background(primary-20);
|
|
12
12
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
cursor: pointer;
|
|
23
23
|
|
|
24
|
-
&[data-active] {
|
|
24
|
+
&[data-active="true"] {
|
|
25
25
|
@include background(primary);
|
|
26
26
|
@include size(w20px);
|
|
27
27
|
@include border-radius(lg);
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
[data-active] {
|
|
44
|
+
[data-active="true"] {
|
|
45
45
|
@include typography(primary);
|
|
46
46
|
box-shadow: inset 0px 0px 0px 1px var(--w-color-primary);
|
|
47
47
|
}
|