webcoreui 0.10.1 → 1.1.0-beta.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.
Files changed (46) hide show
  1. package/README.md +15 -8
  2. package/astro.d.ts +6 -0
  3. package/astro.js +4 -0
  4. package/components/Carousel/Carousel.svelte +18 -15
  5. package/components/OTPInput/OTPInput.astro +96 -0
  6. package/components/OTPInput/OTPInput.svelte +73 -0
  7. package/components/OTPInput/OTPInput.tsx +93 -0
  8. package/components/OTPInput/otpinput.module.scss +85 -0
  9. package/components/OTPInput/otpinput.ts +11 -0
  10. package/components/Pagination/Pagination.svelte +1 -1
  11. package/components/Rating/Rating.svelte +1 -1
  12. package/components/SpeedDial/SpeedDial.astro +106 -0
  13. package/components/SpeedDial/SpeedDial.svelte +102 -0
  14. package/components/SpeedDial/SpeedDial.tsx +106 -0
  15. package/components/SpeedDial/speeddial.module.scss +94 -0
  16. package/components/SpeedDial/speeddial.ts +18 -0
  17. package/components/Switch/Switch.astro +1 -1
  18. package/components/Switch/Switch.svelte +1 -1
  19. package/components/Switch/Switch.tsx +6 -1
  20. package/components/Timeline/timeline.module.scss +11 -0
  21. package/components/Timeline/timeline.ts +1 -1
  22. package/components/TimelineItem/TimelineItem.astro +12 -0
  23. package/components/TimelineItem/TimelineItem.svelte +7 -0
  24. package/components/TimelineItem/TimelineItem.tsx +8 -0
  25. package/components/TimelineItem/timelineitem.module.scss +16 -1
  26. package/components/TimelineItem/timelineitem.ts +3 -0
  27. package/index.d.ts +3 -0
  28. package/index.js +2 -1
  29. package/package.json +17 -17
  30. package/react.d.ts +6 -0
  31. package/react.js +4 -0
  32. package/scss/config/color-palette.scss +1 -1
  33. package/scss/config/css-values.scss +1 -1
  34. package/scss/config/layout.scss +1 -1
  35. package/scss/config/mixins.scss +1 -1
  36. package/scss/config/typography.scss +1 -1
  37. package/scss/config/variables.scss +1 -1
  38. package/scss/config.scss +1 -1
  39. package/scss/global/theme.scss +77 -49
  40. package/scss/resets.scss +10 -1
  41. package/svelte.d.ts +6 -0
  42. package/svelte.js +4 -0
  43. package/utils/getLayoutClasses.ts +1 -1
  44. package/utils/modal.ts +1 -1
  45. package/utils/popover.ts +2 -2
  46. package/utils/webcore.ts +28 -0
package/README.md CHANGED
@@ -34,10 +34,6 @@
34
34
  </a>
35
35
  </p>
36
36
 
37
- > [!IMPORTANT]
38
- > This library is still in early development. New changes can break existing functionality, and no functionality should be considered final at this stage. The library will be considered stable once it reaches v1.0.
39
-
40
- ---
41
37
  ## Table of Contents
42
38
 
43
39
  - [Table of Contents](#table-of-contents)
@@ -64,15 +60,15 @@ Webcore can be used as a standalone project, or it can be integrated into your e
64
60
 
65
61
  Webcore components use Sass for styling. To use the component library, you must have the following packages installed:
66
62
 
67
- - [Sass](https://www.npmjs.com/package/sass) - `v1.83`
68
- - [TypeScript](https://www.npmjs.com/package/typescript) - `v5.7`
63
+ - [Sass](https://www.npmjs.com/package/sass) - `v1.86`
64
+ - [TypeScript](https://www.npmjs.com/package/typescript) - `v5.8`
69
65
 
70
66
  Depending on your project setup, you'll also need the following packages:
71
67
 
72
68
  - **For Astro projects**
73
- - [Astro](https://www.npmjs.com/package/astro) - `v5.1`
69
+ - [Astro](https://www.npmjs.com/package/astro) - `v5.5`
74
70
  - **For Svelte projects**
75
- - [Svelte](https://www.npmjs.com/package/svelte) - `v5.19`
71
+ - [Svelte](https://www.npmjs.com/package/svelte) - `v5.25`
76
72
  - **For React projects**
77
73
  - [React](https://www.npmjs.com/package/react) - `v19.0`
78
74
  - [React DOM](https://www.npmjs.com/package/react-dom) -`v19.0`
@@ -170,6 +166,9 @@ html body {
170
166
  --w-slider-color: var(--w-color-primary);
171
167
  --w-slider-thumb: var(--w-color-primary-50);
172
168
 
169
+ // SpeedDial component
170
+ --w-speed-dial-size: 50px;
171
+
173
172
  // Spinner component
174
173
  --w-spinner-color: var(--w-color-primary);
175
174
  --w-spinner-width: 2px;
@@ -258,6 +257,7 @@ import { Accordion } from 'webcoreui/react'
258
257
  - [Masonry](https://github.com/Frontendland/webcoreui/tree/main/src/components/Masonry)
259
258
  - [Menu](https://github.com/Frontendland/webcoreui/tree/main/src/components/Menu)
260
259
  - [Modal](https://github.com/Frontendland/webcoreui/tree/main/src/components/Modal)
260
+ - [OTPInput](https://github.com/Frontendland/webcoreui/tree/main/src/components/OTPInput)
261
261
  - [Pagination](https://github.com/Frontendland/webcoreui/tree/main/src/components/Pagination)
262
262
  - [Popover](https://github.com/Frontendland/webcoreui/tree/main/src/components/Popover)
263
263
  - [Progress](https://github.com/Frontendland/webcoreui/tree/main/src/components/Progress)
@@ -269,6 +269,7 @@ import { Accordion } from 'webcoreui/react'
269
269
  - [Sidebar](https://github.com/Frontendland/webcoreui/tree/main/src/components/Sidebar)
270
270
  - [Skeleton](https://github.com/Frontendland/webcoreui/tree/main/src/components/Skeleton)
271
271
  - [Slider](https://github.com/Frontendland/webcoreui/tree/main/src/components/Slider)
272
+ - [SpeedDial](https://github.com/Frontendland/webcoreui/tree/main/src/components/SpeedDial)
272
273
  - [Spinner](https://github.com/Frontendland/webcoreui/tree/main/src/components/Spinner)
273
274
  - [Spoiler](https://github.com/Frontendland/webcoreui/tree/main/src/components/Spoiler)
274
275
  - [Stepper](https://github.com/Frontendland/webcoreui/tree/main/src/components/Stepper)
@@ -288,21 +289,27 @@ import { Accordion } from 'webcoreui/react'
288
289
  - [ComponentMap](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ComponentMap)
289
290
  - [DeviceMockup](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/DeviceMockup)
290
291
  - [ErrorPage](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ErrorPage)
292
+ - [ExpandableTable](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ExpandableTable)
291
293
  - [FAQ](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/FAQ)
294
+ - [Form](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Form)
292
295
  - [GridWithIcons](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/GridWithIcons)
293
296
  - [Hero](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Hero)
294
297
  - [Icon](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Icon)
295
298
  - [IconList](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/IconList)
296
299
  - [Layout](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Layout)
300
+ - [Maintenance](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Maintenance)
297
301
  - [SEO](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/SEO)
298
302
  - [SettingCard](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/SettingCard)
299
303
  - [SignUp](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/SignUp)
300
304
  - [SocialProof](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/SocialProof)
301
305
  - [Socials](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Socials)
306
+ - [Team](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Team)
302
307
  - [Tiles](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Tiles)
303
308
  - [User](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/User)
304
309
 
305
310
  ## Templates
306
311
 
312
+ - [Authentication](https://github.com/Frontendland/webcoreui/tree/main/src/templates/Authentication)
313
+ - [Blog](https://github.com/Frontendland/webcoreui/tree/main/src/templates/Blog)
307
314
  - [Portfolio](https://github.com/Frontendland/webcoreui/tree/main/src/templates/Portfolio)
308
315
  - [ProductPage](https://github.com/Frontendland/webcoreui/tree/main/src/templates/ProductPage)
package/astro.d.ts CHANGED
@@ -25,6 +25,7 @@ import type { ListProps as WListProps } from './components/List/list'
25
25
  import type { MasonryProps as WMasonryProps } from './components/Masonry/masonry'
26
26
  import type { MenuProps as WMenuProps } from './components/Menu/menu'
27
27
  import type { ModalProps as WModalProps } from './components/Modal/modal'
28
+ import type { OTPInputProps as WOTPInputProps } from './components/OTPInput/otpinput'
28
29
  import type { PaginationProps as WPaginationProps } from './components/Pagination/pagination'
29
30
  import type { PopoverProps as WPopoverProps } from './components/Popover/popover'
30
31
  import type { ProgressProps as WProgressProps } from './components/Progress/progress'
@@ -36,6 +37,7 @@ import type { SheetProps as WSheetProps } from './components/Sheet/sheet'
36
37
  import type { SidebarProps as WSidebarProps } from './components/Sidebar/sidebar'
37
38
  import type { SkeletonProps as WSkeletonProps } from './components/Skeleton/skeleton'
38
39
  import type { SliderProps as WSliderProps } from './components/Slider/slider'
40
+ import type { SpeedDialProps as WSpeedDialProps } from './components/SpeedDial/speeddial'
39
41
  import type { SpinnerProps as WSpinnerProps } from './components/Spinner/spinner'
40
42
  import type { SpoilerProps as WSpoilerProps } from './components/Spoiler/spoiler'
41
43
  import type { StepperProps as WStepperProps } from './components/Stepper/stepper'
@@ -81,6 +83,7 @@ declare module 'webcoreui/astro' {
81
83
  export function Masonry(_props: WMasonryProps): any
82
84
  export function Menu(_props: WMenuProps): any
83
85
  export function Modal(_props: WModalProps): any
86
+ export function OTPInput(_props: WOTPInputProps): any
84
87
  export function Pagination(_props: WPaginationProps): any
85
88
  export function Popover(_props: WPopoverProps): any
86
89
  export function Progress(_props: WProgressProps): any
@@ -92,6 +95,7 @@ declare module 'webcoreui/astro' {
92
95
  export function Sidebar(_props: WSidebarProps): any
93
96
  export function Skeleton(_props: WSkeletonProps): any
94
97
  export function Slider(_props: WSliderProps): any
98
+ export function SpeedDial(_props: WSpeedDialProps): any
95
99
  export function Spinner(_props: WSpinnerProps): any
96
100
  export function Spoiler(_props: WSpoilerProps): any
97
101
  export function Stepper(_props: WStepperProps): any
@@ -131,6 +135,7 @@ declare module 'webcoreui/astro' {
131
135
  export type MasonryProps = WMasonryProps
132
136
  export type MenuProps = WMenuProps
133
137
  export type ModalProps = WModalProps
138
+ export type OTPInputProps = WOTPInputProps
134
139
  export type PaginationProps = WPaginationProps
135
140
  export type PopoverProps = WPopoverProps
136
141
  export type ProgressProps = WProgressProps
@@ -142,6 +147,7 @@ declare module 'webcoreui/astro' {
142
147
  export type SidebarProps = WSidebarProps
143
148
  export type SkeletonProps = WSkeletonProps
144
149
  export type SliderProps = WSliderProps
150
+ export type SpeedDialProps = WSpeedDialProps
145
151
  export type SpinnerProps = WSpinnerProps
146
152
  export type SpoilerProps = WSpoilerProps
147
153
  export type StepperProps = WStepperProps
package/astro.js CHANGED
@@ -25,6 +25,7 @@ import ListComponent from './components/List/List.astro'
25
25
  import MasonryComponent from './components/Masonry/Masonry.astro'
26
26
  import MenuComponent from './components/Menu/Menu.astro'
27
27
  import ModalComponent from './components/Modal/Modal.astro'
28
+ import OTPInputComponent from './components/OTPInput/OTPInput.astro'
28
29
  import PaginationComponent from './components/Pagination/Pagination.astro'
29
30
  import PopoverComponent from './components/Popover/Popover.astro'
30
31
  import ProgressComponent from './components/Progress/Progress.astro'
@@ -36,6 +37,7 @@ import SheetComponent from './components/Sheet/Sheet.astro'
36
37
  import SidebarComponent from './components/Sidebar/Sidebar.astro'
37
38
  import SkeletonComponent from './components/Skeleton/Skeleton.astro'
38
39
  import SliderComponent from './components/Slider/Slider.astro'
40
+ import SpeedDialComponent from './components/SpeedDial/SpeedDial.astro'
39
41
  import SpinnerComponent from './components/Spinner/Spinner.astro'
40
42
  import SpoilerComponent from './components/Spoiler/Spoiler.astro'
41
43
  import StepperComponent from './components/Stepper/Stepper.astro'
@@ -75,6 +77,7 @@ export const List = ListComponent
75
77
  export const Masonry = MasonryComponent
76
78
  export const Menu = MenuComponent
77
79
  export const Modal = ModalComponent
80
+ export const OTPInput = OTPInputComponent
78
81
  export const Pagination = PaginationComponent
79
82
  export const Popover = PopoverComponent
80
83
  export const Progress = ProgressComponent
@@ -86,6 +89,7 @@ export const Sheet = SheetComponent
86
89
  export const Sidebar = SidebarComponent
87
90
  export const Skeleton = SkeletonComponent
88
91
  export const Slider = SliderComponent
92
+ export const SpeedDial = SpeedDialComponent
89
93
  export const Spinner = SpinnerComponent
90
94
  export const Spoiler = SpoilerComponent
91
95
  export const Stepper = StepperComponent
@@ -13,25 +13,28 @@
13
13
 
14
14
  import type { PaginationEventType } from '../Pagination/pagination'
15
15
 
16
- export let items: SvelteCarouselProps['items'] = 0
17
- export let itemsPerSlide: SvelteCarouselProps['itemsPerSlide'] = 1
18
- export let subText: SvelteCarouselProps['subText'] = ''
19
- export let scrollSnap: SvelteCarouselProps['scrollSnap'] = true
20
- export let progress: SvelteCarouselProps['progress'] = false
21
- export let pagination: SvelteCarouselProps['pagination'] = {}
22
- export let effect: SvelteCarouselProps['effect'] = null
23
- export let debounce: SvelteCarouselProps['debounce'] = 20
24
- export let className: SvelteCarouselProps['className'] = ''
25
- export let wrapperClassName: SvelteCarouselProps['wrapperClassName'] = ''
26
- export let paginationClassName: SvelteCarouselProps['paginationClassName'] = ''
27
- export let onScroll: SvelteCarouselProps['onScroll'] = () => {}
16
+ let {
17
+ items = 0,
18
+ itemsPerSlide = 1,
19
+ subText,
20
+ scrollSnap = true,
21
+ progress,
22
+ pagination,
23
+ effect,
24
+ debounce = 20,
25
+ className,
26
+ wrapperClassName,
27
+ paginationClassName,
28
+ children,
29
+ onScroll
30
+ }: SvelteCarouselProps = $props()
28
31
 
29
32
  let carouselContainer: HTMLDivElement
30
33
  let carousel: HTMLUListElement
31
34
  let carouselItems: HTMLCollection | NodeListOf<HTMLLIElement>
32
- let progressValue = 0
35
+ let progressValue = $state(0)
33
36
  let paginated = false
34
- let currentPage = 1
37
+ let currentPage = $state(1)
35
38
 
36
39
  const classes = classNames([
37
40
  styles.carousel,
@@ -141,7 +144,7 @@
141
144
  <section class={classes}>
142
145
  <div class={containerClasses} bind:this={carouselContainer}>
143
146
  <ul class={wrapperClasses} style={style} bind:this={carousel}>
144
- <slot />
147
+ {@render children?.()}
145
148
  </ul>
146
149
  </div>
147
150
  <ConditionalWrapper
@@ -0,0 +1,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,
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 inputPlaceholders = 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}
39
+ class={styles.label}
40
+ set:html={label}
41
+ />
42
+ )}
43
+
44
+ <div class={styles['input-wrapper']}>
45
+ <Input
46
+ name={name || 'otp'}
47
+ data-id="w-input-otp"
48
+ disabled={disabled}
49
+ maxlength={length}
50
+ required={true}
51
+ {...rest}
52
+ />
53
+
54
+ <div class={styles.placeholders}>
55
+ {inputPlaceholders.map((placeholder, index) => (
56
+ <div
57
+ class={typeof placeholder === 'string' ? styles.separator : styles.placeholder}
58
+ data-active={index === 0 ? true : undefined}
59
+ data-separator={typeof placeholder === 'string' ? true : undefined}
60
+ >
61
+ {typeof placeholder === 'string' ? placeholder : ''}
62
+ </div>
63
+ ))}
64
+ </div>
65
+ </div>
66
+
67
+ {subText && (
68
+ <div class={styles.subtext} set:html={subText} />
69
+ )}
70
+ </div>
71
+
72
+ <script>
73
+ import { on } from '../../utils/DOMUtils'
74
+
75
+ const addEventListeners = () => {
76
+ on('[data-id="w-input-otp"]', 'input', (event: Event) => {
77
+ const target = event.target as HTMLInputElement
78
+ const value = target.value
79
+ const placeholders = Array.from(target.nextElementSibling!.children)
80
+ .filter(child => !(child as HTMLDivElement).dataset.separator)
81
+
82
+
83
+ placeholders.forEach((placeholder, index) => {
84
+ const placeholderElement = placeholder as HTMLDivElement
85
+
86
+ placeholderElement.innerText = value[index] || ''
87
+ placeholderElement.dataset.active = value.length === index
88
+ ? 'true'
89
+ : 'false'
90
+ })
91
+ }, true)
92
+ }
93
+
94
+ on(document, 'astro:after-swap', addEventListeners)
95
+ addEventListeners()
96
+ </script>
@@ -0,0 +1,73 @@
1
+ <script lang="ts">
2
+ import type { OTPInputProps } from './otpinput'
3
+
4
+ import Input from '../Input/Input.svelte'
5
+
6
+ import { classNames } from '../../utils/classNames'
7
+
8
+ import styles from './otpinput.module.scss'
9
+
10
+ let {
11
+ name,
12
+ disabled,
13
+ length = 6,
14
+ groupLength = 0,
15
+ separator = '•',
16
+ label,
17
+ subText,
18
+ className,
19
+ value = $bindable(''),
20
+ ...rest
21
+ }: OTPInputProps = $props()
22
+
23
+ const classes = classNames([
24
+ styles.wrapper,
25
+ className
26
+ ])
27
+
28
+ const inputPlaceholders = Array.from({ length }, (_, i) => i + 1)
29
+ .reduce<(number | string)[]>((acc, num, i) =>
30
+ groupLength > 0 && i % groupLength === 0 && i !== 0
31
+ ? [...acc, separator, num]
32
+ : [...acc, num]
33
+ , [])
34
+
35
+ const getAdjustedIndex = (index: number) => inputPlaceholders
36
+ .slice(0, index)
37
+ .filter(placeholder => typeof placeholder !== 'string')
38
+ .length
39
+ </script>
40
+
41
+ <div class={classes}>
42
+ {#if label}
43
+ <label for={name} class={styles.label}>{@html label}</label>
44
+ {/if}
45
+
46
+ <div class={styles['input-wrapper']}>
47
+ <Input
48
+ name={name || 'otp'}
49
+ disabled={disabled}
50
+ maxlength={length}
51
+ required={true}
52
+ bind:value
53
+ {...rest}
54
+ />
55
+
56
+ <div class={styles.placeholders}>
57
+ {#each inputPlaceholders as placeholder, index}
58
+ <div
59
+ class={typeof placeholder === 'string' ? styles.separator : styles.placeholder}
60
+ data-active={getAdjustedIndex(index) === value.length ? true : undefined}
61
+ >
62
+ {typeof placeholder === 'string' ? placeholder : value[getAdjustedIndex(index)]}
63
+ </div>
64
+ {/each}
65
+ </div>
66
+ </div>
67
+
68
+ {#if subText}
69
+ <div class={styles.subtext}>
70
+ {@html subText}
71
+ </div>
72
+ {/if}
73
+ </div>
@@ -0,0 +1,93 @@
1
+ import React, { useState } from 'react'
2
+ import type { OTPInputProps } from './otpinput'
3
+
4
+ import Input from '../Input/Input.tsx'
5
+
6
+ import { classNames } from '../../utils/classNames'
7
+
8
+ import styles from './otpinput.module.scss'
9
+
10
+ const OTPInput = ({
11
+ name,
12
+ disabled,
13
+ length = 6,
14
+ groupLength = 0,
15
+ separator = '•',
16
+ label,
17
+ subText,
18
+ className,
19
+ value,
20
+ onChange,
21
+ ...rest
22
+ }: OTPInputProps) => {
23
+ const [inputValue, setValue] = useState(value || '')
24
+
25
+ const classes = classNames([
26
+ styles.wrapper,
27
+ className
28
+ ])
29
+
30
+ const inputPlaceholders = Array.from({ length }, (_, i) => i + 1)
31
+ .reduce<(number | string)[]>((acc, num, i) =>
32
+ groupLength > 0 && i % groupLength === 0 && i !== 0
33
+ ? [...acc, separator, num]
34
+ : [...acc, num]
35
+ , [])
36
+
37
+ const getAdjustedIndex = (index: number) => inputPlaceholders
38
+ .slice(0, index)
39
+ .filter(placeholder => typeof placeholder !== 'string')
40
+ .length
41
+
42
+ const updateInput = (event: React.ChangeEvent<HTMLInputElement>) => {
43
+ setValue(event.target.value)
44
+ onChange?.(inputValue)
45
+ }
46
+
47
+ return (
48
+ <div className={classes}>
49
+ {label && (
50
+ <label
51
+ htmlFor={name}
52
+ className={styles.label}
53
+ dangerouslySetInnerHTML={{ __html: label }}
54
+ />
55
+ )}
56
+
57
+ <div className={styles['input-wrapper']}>
58
+ <Input
59
+ name={name || 'otp'}
60
+ disabled={disabled}
61
+ maxLength={length}
62
+ required={true}
63
+ value={inputValue}
64
+ onChange={updateInput}
65
+ {...rest}
66
+ />
67
+
68
+ <div className={styles.placeholders}>
69
+ {inputPlaceholders.map((placeholder, index) => (
70
+ <div
71
+ key={index}
72
+ className={typeof placeholder === 'string' ? styles.separator : styles.placeholder}
73
+ data-active={getAdjustedIndex(index) === inputValue.length ? true : undefined}
74
+ >
75
+ {typeof placeholder === 'string'
76
+ ? placeholder
77
+ : inputValue[getAdjustedIndex(index)]}
78
+ </div>
79
+ ))}
80
+ </div>
81
+ </div>
82
+
83
+ {subText && (
84
+ <div
85
+ className={styles.subtext}
86
+ dangerouslySetInnerHTML={{ __html: subText }}
87
+ />
88
+ )}
89
+ </div>
90
+ )
91
+ }
92
+
93
+ export default OTPInput
@@ -0,0 +1,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
+
14
+ input {
15
+ @include visibility(0);
16
+ @include position(absolute, t0, l0);
17
+ @include size(h40px);
18
+ }
19
+ }
20
+
21
+ .placeholders {
22
+ @include layout(flex);
23
+ }
24
+
25
+ .placeholder {
26
+ @include layout(flex, center);
27
+ @include border(top, primary-50);
28
+ @include border(bottom, primary-50);
29
+ @include border(right, primary-50);
30
+ @include size(40px);
31
+
32
+ &:first-child {
33
+ @include border(primary-50);
34
+ @include border-radius(left);
35
+ }
36
+
37
+ &:last-child {
38
+ @include border(primary-50);
39
+ @include border(left, 0);
40
+ @include border-radius(right);
41
+ }
42
+
43
+ &[data-active="true"] {
44
+ @include border(primary);
45
+
46
+ &::before {
47
+ @include size(w1px, h15px);
48
+ @include background(primary);
49
+
50
+ content: '';
51
+ animation: flash 1s infinite forwards;
52
+ }
53
+ }
54
+ }
55
+
56
+ .separator {
57
+ @include size(40px);
58
+ @include layout(flex, center);
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
+ }
@@ -0,0 +1,11 @@
1
+ export type OTPInputProps = {
2
+ name?: string
3
+ disabled?: boolean
4
+ length?: number
5
+ groupLength?: number
6
+ separator?: string
7
+ label?: string
8
+ subText?: string
9
+ className?: string
10
+ [key: string]: any
11
+ }
@@ -66,7 +66,7 @@
66
66
  })
67
67
  }
68
68
 
69
- let calculatedCurrentPage = $state(
69
+ let calculatedCurrentPage = $derived(
70
70
  currentPage
71
71
  || (pages?.findIndex(page => page.active) || -1) + 1
72
72
  || 1
@@ -61,7 +61,7 @@
61
61
  {/if}
62
62
 
63
63
  {#if reviewCount}
64
- {''}
64
+
65
65
  <ConditionalWrapper
66
66
  condition={!!reviewLink}
67
67
  element="a"