webcoreui 0.6.1 → 0.7.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 +30 -1
- package/astro.d.ts +15 -0
- package/astro.js +10 -0
- package/components/Accordion/Accordion.astro +32 -20
- package/components/Accordion/Accordion.svelte +22 -4
- package/components/Accordion/Accordion.tsx +29 -7
- package/components/Accordion/accordion.module.scss +12 -0
- package/components/Accordion/accordion.ts +4 -0
- package/components/AspectRatio/AspectRatio.astro +21 -0
- package/components/AspectRatio/AspectRatio.svelte +19 -0
- package/components/AspectRatio/AspectRatio.tsx +28 -0
- package/components/AspectRatio/aspect-ratio.module.scss +10 -0
- package/components/AspectRatio/aspectratio.ts +8 -0
- package/components/Banner/Banner.astro +56 -0
- package/components/Banner/Banner.svelte +47 -0
- package/components/Banner/Banner.tsx +54 -0
- package/components/Banner/banner.module.scss +57 -0
- package/components/Banner/banner.ts +12 -0
- package/components/Icon/map.ts +2 -0
- package/components/Kbd/Kbd.astro +20 -0
- package/components/Kbd/Kbd.svelte +18 -0
- package/components/Kbd/Kbd.tsx +27 -0
- package/components/Kbd/kbd.module.scss +8 -0
- package/components/Kbd/kbd.ts +26 -0
- package/components/Kbd/keyMap.ts +21 -0
- package/components/Spoiler/Spoiler.astro +50 -0
- package/components/Spoiler/Spoiler.svelte +45 -0
- package/components/Spoiler/Spoiler.tsx +50 -0
- package/components/Spoiler/spoiler.module.scss +40 -0
- package/components/Spoiler/spoiler.ts +11 -0
- package/components/Stepper/Stepper.astro +61 -0
- package/components/Stepper/Stepper.svelte +59 -0
- package/components/Stepper/Stepper.tsx +60 -0
- package/components/Stepper/stepper.module.scss +102 -0
- package/components/Stepper/stepper.ts +17 -0
- package/icons/close.svg +1 -1
- package/icons/plus.svg +3 -0
- package/icons.d.ts +1 -0
- package/icons.js +1 -0
- package/package.json +4 -4
- package/react.d.ts +15 -0
- package/react.js +10 -0
- package/scss/global/utility.scss +4 -0
- package/scss/resets.scss +5 -0
- package/svelte.d.ts +15 -0
- package/svelte.js +10 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import type { ReactBannerProps } from './banner'
|
|
3
|
+
|
|
4
|
+
import Button from '../Button/Button.tsx'
|
|
5
|
+
|
|
6
|
+
import { classNames } from '../../utils/classNames'
|
|
7
|
+
|
|
8
|
+
import closeIcon from '../../icons/close.svg?raw'
|
|
9
|
+
|
|
10
|
+
import styles from './banner.module.scss'
|
|
11
|
+
|
|
12
|
+
const Banner = ({
|
|
13
|
+
top,
|
|
14
|
+
bottom,
|
|
15
|
+
closeable,
|
|
16
|
+
padded,
|
|
17
|
+
sticky = true,
|
|
18
|
+
className,
|
|
19
|
+
children
|
|
20
|
+
}: ReactBannerProps) => {
|
|
21
|
+
const [visible, setVisible] = useState(true)
|
|
22
|
+
|
|
23
|
+
const classes = classNames([
|
|
24
|
+
styles.banner,
|
|
25
|
+
bottom && styles.bottom,
|
|
26
|
+
padded && styles.padded,
|
|
27
|
+
!sticky && styles.relative,
|
|
28
|
+
className
|
|
29
|
+
])
|
|
30
|
+
|
|
31
|
+
const style = top
|
|
32
|
+
? { '--w-banner-top': `${top}px` } as React.CSSProperties
|
|
33
|
+
: undefined
|
|
34
|
+
|
|
35
|
+
if (!visible) {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className={classes} style={style}>
|
|
41
|
+
{children}
|
|
42
|
+
{closeable && (
|
|
43
|
+
<Button
|
|
44
|
+
theme="flat"
|
|
45
|
+
className={styles.close}
|
|
46
|
+
dangerouslySetInnerHTML={{ __html: closeIcon }}
|
|
47
|
+
onClick={() => setVisible(false)}
|
|
48
|
+
/>
|
|
49
|
+
)}
|
|
50
|
+
</div>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default Banner
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
@import '../../scss/config.scss';
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
--w-banner-top: 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.banner {
|
|
8
|
+
@include background(primary-60);
|
|
9
|
+
@include spacing(p-default);
|
|
10
|
+
@include position(sticky);
|
|
11
|
+
@include layer(top);
|
|
12
|
+
@include typography(center);
|
|
13
|
+
|
|
14
|
+
top: var(--w-banner-top);
|
|
15
|
+
|
|
16
|
+
&.padded {
|
|
17
|
+
@include border-radius();
|
|
18
|
+
@include position(l20px);
|
|
19
|
+
|
|
20
|
+
width: calc(100% - 40px);
|
|
21
|
+
top: calc(var(--w-banner-top) + 20px);
|
|
22
|
+
|
|
23
|
+
&.bottom {
|
|
24
|
+
@include position(l20px, b20px);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&.relative {
|
|
29
|
+
@include position(relative);
|
|
30
|
+
top: auto;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&.bottom {
|
|
34
|
+
@include position(fixed, b0, l0, r0);
|
|
35
|
+
|
|
36
|
+
top: auto;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&.closeable {
|
|
40
|
+
@include spacing(pl-default, pt-default, pb-default, pr-3xl);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.close {
|
|
44
|
+
@include position(absolute, v-center, r10px);
|
|
45
|
+
@include spacing(p-xs);
|
|
46
|
+
|
|
47
|
+
svg {
|
|
48
|
+
@include size(10px);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@include media(xs) {
|
|
54
|
+
.banner.closeable {
|
|
55
|
+
@include spacing(p-default);
|
|
56
|
+
}
|
|
57
|
+
}
|
package/components/Icon/map.ts
CHANGED
|
@@ -13,6 +13,7 @@ import Home from '../../icons/home.svg?raw'
|
|
|
13
13
|
import Info from '../../icons/info.svg?raw'
|
|
14
14
|
import Moon from '../../icons/moon.svg?raw'
|
|
15
15
|
import Order from '../../icons/order.svg?raw'
|
|
16
|
+
import Plus from '../../icons/plus.svg?raw'
|
|
16
17
|
import Search from '../../icons/search.svg?raw'
|
|
17
18
|
import Sun from '../../icons/sun.svg?raw'
|
|
18
19
|
import Warning from '../../icons/warning.svg?raw'
|
|
@@ -33,6 +34,7 @@ const iconMap = {
|
|
|
33
34
|
'info': Info,
|
|
34
35
|
'moon': Moon,
|
|
35
36
|
'order': Order,
|
|
37
|
+
'plus': Plus,
|
|
36
38
|
'search': Search,
|
|
37
39
|
'sun': Sun,
|
|
38
40
|
'warning': Warning
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { KbdProps } from './kbd'
|
|
3
|
+
import { keyMap } from './keyMap'
|
|
4
|
+
|
|
5
|
+
import styles from './kbd.module.scss'
|
|
6
|
+
|
|
7
|
+
interface Props extends KbdProps {}
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
keys,
|
|
11
|
+
className
|
|
12
|
+
} = Astro.props
|
|
13
|
+
|
|
14
|
+
const classes = [
|
|
15
|
+
styles.kbd,
|
|
16
|
+
className
|
|
17
|
+
]
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<kbd class:list={classes}>{keys?.map(key => keyMap[key])}<slot /></kbd>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { KbdProps } from './kbd'
|
|
3
|
+
import { keyMap } from './keyMap'
|
|
4
|
+
|
|
5
|
+
import { classNames } from '../../utils/classNames'
|
|
6
|
+
|
|
7
|
+
import styles from './kbd.module.scss'
|
|
8
|
+
|
|
9
|
+
export let keys: KbdProps['keys'] = []
|
|
10
|
+
export let className: KbdProps['className'] = ''
|
|
11
|
+
|
|
12
|
+
const classes = classNames([
|
|
13
|
+
styles.kbd,
|
|
14
|
+
className
|
|
15
|
+
])
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<kbd class={classes}>{keys?.map(key => keyMap[key]).join('')}<slot /></kbd>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { ReactKbdProps } from './kbd'
|
|
3
|
+
import { keyMap } from './keyMap'
|
|
4
|
+
|
|
5
|
+
import { classNames } from '../../utils/classNames'
|
|
6
|
+
|
|
7
|
+
import styles from './kbd.module.scss'
|
|
8
|
+
|
|
9
|
+
const Kbd = ({
|
|
10
|
+
keys,
|
|
11
|
+
className,
|
|
12
|
+
children
|
|
13
|
+
}: ReactKbdProps) => {
|
|
14
|
+
const classes = classNames([
|
|
15
|
+
styles.kbd,
|
|
16
|
+
className
|
|
17
|
+
])
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<kbd className={classes}>
|
|
21
|
+
{keys?.map(key => keyMap[key]).join('')}
|
|
22
|
+
{children}
|
|
23
|
+
</kbd>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default Kbd
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type KbdProps = {
|
|
2
|
+
keys?: ('cmd'
|
|
3
|
+
| 'shift'
|
|
4
|
+
| 'ctrl'
|
|
5
|
+
| 'option'
|
|
6
|
+
| 'enter'
|
|
7
|
+
| 'del'
|
|
8
|
+
| 'esc'
|
|
9
|
+
| 'tab'
|
|
10
|
+
| 'capslock'
|
|
11
|
+
| 'up'
|
|
12
|
+
| 'down'
|
|
13
|
+
| 'left'
|
|
14
|
+
| 'right'
|
|
15
|
+
| 'pageup'
|
|
16
|
+
| 'pagedown'
|
|
17
|
+
| 'home'
|
|
18
|
+
| 'end'
|
|
19
|
+
| 'help'
|
|
20
|
+
| 'space')[]
|
|
21
|
+
className?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type ReactKbdProps = {
|
|
25
|
+
children?: React.ReactNode
|
|
26
|
+
} & KbdProps
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const keyMap = {
|
|
2
|
+
cmd: '⌘',
|
|
3
|
+
shift: '⇧',
|
|
4
|
+
ctrl: '⌃',
|
|
5
|
+
option: '⌥',
|
|
6
|
+
enter: '↵',
|
|
7
|
+
del: '⌫',
|
|
8
|
+
esc: '⎋',
|
|
9
|
+
tab: '⇥',
|
|
10
|
+
capslock: '⇪',
|
|
11
|
+
up: '↑',
|
|
12
|
+
down: '↓',
|
|
13
|
+
left: '←',
|
|
14
|
+
right: '→',
|
|
15
|
+
pageup: '⇞',
|
|
16
|
+
pagedown: '⇟',
|
|
17
|
+
home: '↖',
|
|
18
|
+
end: '↘',
|
|
19
|
+
help: '?',
|
|
20
|
+
space: '␣'
|
|
21
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { SpoilerProps } from './spoiler'
|
|
3
|
+
|
|
4
|
+
import styles from './spoiler.module.scss'
|
|
5
|
+
|
|
6
|
+
interface Props extends SpoilerProps {}
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
color,
|
|
10
|
+
animated = true,
|
|
11
|
+
block,
|
|
12
|
+
tooltip,
|
|
13
|
+
tooltipPosition
|
|
14
|
+
} = Astro.props
|
|
15
|
+
|
|
16
|
+
const classes = [
|
|
17
|
+
styles.spoiler,
|
|
18
|
+
animated && styles.anim,
|
|
19
|
+
block && styles.block
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
const style = color
|
|
23
|
+
? `--w-spoiler-color: ${color};`
|
|
24
|
+
: null
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<span
|
|
28
|
+
class:list={classes}
|
|
29
|
+
style={style}
|
|
30
|
+
data-tooltip={tooltip}
|
|
31
|
+
data-position={tooltipPosition}
|
|
32
|
+
data-id="w-spoiler"
|
|
33
|
+
role="button"
|
|
34
|
+
tabindex="0"
|
|
35
|
+
>
|
|
36
|
+
<slot />
|
|
37
|
+
</span>
|
|
38
|
+
|
|
39
|
+
<script>
|
|
40
|
+
import { on } from '../../utils/DOMUtils'
|
|
41
|
+
|
|
42
|
+
on('[data-id="w-spoiler"]', 'click', (event: Event) => {
|
|
43
|
+
const target = event.currentTarget as HTMLDivElement
|
|
44
|
+
|
|
45
|
+
target.dataset.visible = 'true'
|
|
46
|
+
target.removeAttribute('data-tooltip')
|
|
47
|
+
target.removeAttribute('role')
|
|
48
|
+
target.removeAttribute('tabindex')
|
|
49
|
+
}, true)
|
|
50
|
+
</script>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { SpoilerProps } from './spoiler'
|
|
3
|
+
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
|
|
6
|
+
import styles from './spoiler.module.scss'
|
|
7
|
+
|
|
8
|
+
export let color: SpoilerProps['color'] = ''
|
|
9
|
+
export let animated: SpoilerProps['animated'] = true
|
|
10
|
+
export let block: SpoilerProps['block'] = false
|
|
11
|
+
export let tooltip: SpoilerProps['tooltip'] = ''
|
|
12
|
+
export let tooltipPosition: SpoilerProps['tooltipPosition'] = null
|
|
13
|
+
|
|
14
|
+
const classes = classNames([
|
|
15
|
+
styles.spoiler,
|
|
16
|
+
animated && styles.anim,
|
|
17
|
+
block && styles.block
|
|
18
|
+
])
|
|
19
|
+
|
|
20
|
+
const style = color
|
|
21
|
+
? `--w-spoiler-color: ${color};`
|
|
22
|
+
: null
|
|
23
|
+
|
|
24
|
+
const toggle = (event: MouseEvent | KeyboardEvent) => {
|
|
25
|
+
const target = event.currentTarget as HTMLSpanElement
|
|
26
|
+
|
|
27
|
+
target.dataset.visible = 'true'
|
|
28
|
+
target.removeAttribute('data-tooltip')
|
|
29
|
+
target.removeAttribute('role')
|
|
30
|
+
target.removeAttribute('tabindex')
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<span
|
|
35
|
+
class={classes}
|
|
36
|
+
style={style}
|
|
37
|
+
data-tooltip={tooltip || null}
|
|
38
|
+
data-position={tooltipPosition}
|
|
39
|
+
role="button"
|
|
40
|
+
tabindex="0"
|
|
41
|
+
on:click={toggle}
|
|
42
|
+
on:keyup={toggle}
|
|
43
|
+
>
|
|
44
|
+
<slot />
|
|
45
|
+
</span>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { ReactSpoilerProps } from './spoiler'
|
|
3
|
+
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
|
|
6
|
+
import styles from './spoiler.module.scss'
|
|
7
|
+
|
|
8
|
+
const Spoiler = ({
|
|
9
|
+
color,
|
|
10
|
+
animated = true,
|
|
11
|
+
block,
|
|
12
|
+
tooltip,
|
|
13
|
+
tooltipPosition,
|
|
14
|
+
children
|
|
15
|
+
}: ReactSpoilerProps) => {
|
|
16
|
+
const classes = classNames([
|
|
17
|
+
styles.spoiler,
|
|
18
|
+
animated && styles.anim,
|
|
19
|
+
block && styles.block
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
const style = color
|
|
23
|
+
? { '--w-spoiler-color': color } as React.CSSProperties
|
|
24
|
+
: undefined
|
|
25
|
+
|
|
26
|
+
const toggle = (event: React.MouseEvent<HTMLSpanElement>) => {
|
|
27
|
+
const target = event.currentTarget
|
|
28
|
+
|
|
29
|
+
target.dataset.visible = 'true'
|
|
30
|
+
target.removeAttribute('data-tooltip')
|
|
31
|
+
target.removeAttribute('role')
|
|
32
|
+
target.removeAttribute('tabindex')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<span
|
|
37
|
+
className={classes}
|
|
38
|
+
style={style}
|
|
39
|
+
data-tooltip={tooltip}
|
|
40
|
+
data-position={tooltipPosition}
|
|
41
|
+
role="button"
|
|
42
|
+
tabIndex={0}
|
|
43
|
+
onClick={toggle}
|
|
44
|
+
>
|
|
45
|
+
{children}
|
|
46
|
+
</span>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default Spoiler
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@import '../../scss/config.scss';
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
--w-spoiler-color: var(--w-color-primary);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
span.spoiler {
|
|
8
|
+
@include border-radius();
|
|
9
|
+
@include background(var(--w-spoiler-color));
|
|
10
|
+
@include typography(hmd);
|
|
11
|
+
@include visibility(inline);
|
|
12
|
+
|
|
13
|
+
color: transparent;
|
|
14
|
+
user-select: none;
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
|
|
17
|
+
&.anim {
|
|
18
|
+
@include transition();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&.block {
|
|
22
|
+
@include visibility(block);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
code {
|
|
26
|
+
@include border(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&[data-visible] {
|
|
30
|
+
@include background(transparent);
|
|
31
|
+
|
|
32
|
+
color: inherit;
|
|
33
|
+
user-select: auto;
|
|
34
|
+
cursor: auto;
|
|
35
|
+
|
|
36
|
+
code {
|
|
37
|
+
@include border(primary-50);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { StepperProps } from './stepper'
|
|
3
|
+
|
|
4
|
+
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.astro'
|
|
5
|
+
import Icon from '../Icon/Icon.astro'
|
|
6
|
+
|
|
7
|
+
import styles from './stepper.module.scss'
|
|
8
|
+
|
|
9
|
+
import type { IconProps } from '../Icon/icon'
|
|
10
|
+
|
|
11
|
+
interface Props extends StepperProps {}
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
items,
|
|
15
|
+
color,
|
|
16
|
+
completedColor,
|
|
17
|
+
activeColor,
|
|
18
|
+
borderless,
|
|
19
|
+
vertical,
|
|
20
|
+
className
|
|
21
|
+
} = Astro.props
|
|
22
|
+
|
|
23
|
+
const classes = [
|
|
24
|
+
styles.stepper,
|
|
25
|
+
borderless && styles.borderless,
|
|
26
|
+
vertical && styles.vertical,
|
|
27
|
+
className
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
const styleVariables = [
|
|
31
|
+
color && `--w-stepper-color-border: ${color}`,
|
|
32
|
+
completedColor && `--w-stepper-color-complete: ${completedColor}`,
|
|
33
|
+
activeColor && `--w-stepper-color-active: ${activeColor}`
|
|
34
|
+
].filter(Boolean).join(';')
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
<ol class:list={classes} style={styleVariables}>
|
|
38
|
+
{items?.map((item, index) => (
|
|
39
|
+
<li class:list={[
|
|
40
|
+
index !== 0 && styles.connect,
|
|
41
|
+
item.active && styles.active,
|
|
42
|
+
item.completed && styles.completed
|
|
43
|
+
]}>
|
|
44
|
+
<span class={styles.number}>
|
|
45
|
+
{item.icon ? (
|
|
46
|
+
<Fragment>
|
|
47
|
+
{item.icon.startsWith('<svg')
|
|
48
|
+
? <Fragment set:html={item.icon} />
|
|
49
|
+
: <Icon type={item.icon as IconProps['type']} />
|
|
50
|
+
}
|
|
51
|
+
</Fragment>
|
|
52
|
+
) : index + 1}
|
|
53
|
+
</span>
|
|
54
|
+
<ConditionalWrapper condition={!!(item.title && item.subTitle)}>
|
|
55
|
+
<div slot="wrapper" class={styles.container}>children</div>
|
|
56
|
+
{item.title && <span>{item.title}</span>}
|
|
57
|
+
{item.subTitle && <span class={styles.muted}>{item.subTitle}</span>}
|
|
58
|
+
</ConditionalWrapper>
|
|
59
|
+
</li>
|
|
60
|
+
))}
|
|
61
|
+
</ol>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { StepperProps } from './stepper'
|
|
3
|
+
|
|
4
|
+
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.svelte'
|
|
5
|
+
|
|
6
|
+
import { classNames } from '../../utils/classNames'
|
|
7
|
+
|
|
8
|
+
import styles from './stepper.module.scss'
|
|
9
|
+
|
|
10
|
+
export let items: StepperProps['items'] = []
|
|
11
|
+
export let color: StepperProps['color'] = ''
|
|
12
|
+
export let completedColor: StepperProps['completedColor'] = ''
|
|
13
|
+
export let activeColor: StepperProps['activeColor'] = ''
|
|
14
|
+
export let borderless: StepperProps['vertical'] = false
|
|
15
|
+
export let vertical: StepperProps['vertical'] = false
|
|
16
|
+
export let className: StepperProps['className'] = ''
|
|
17
|
+
|
|
18
|
+
const classes = classNames([
|
|
19
|
+
styles.stepper,
|
|
20
|
+
borderless && styles.borderless,
|
|
21
|
+
vertical && styles.vertical,
|
|
22
|
+
className
|
|
23
|
+
])
|
|
24
|
+
|
|
25
|
+
const styleVariables = [
|
|
26
|
+
color && `--w-stepper-color-border: ${color}`,
|
|
27
|
+
completedColor && `--w-stepper-color-complete: ${completedColor}`,
|
|
28
|
+
activeColor && `--w-stepper-color-active: ${activeColor}`
|
|
29
|
+
].filter(Boolean).join(';')
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<ol class={classes} style={styleVariables || null}>
|
|
33
|
+
{#each items as item, index}
|
|
34
|
+
<li class={classNames([
|
|
35
|
+
index !== 0 && styles.connect,
|
|
36
|
+
item.active && styles.active,
|
|
37
|
+
item.completed && styles.completed
|
|
38
|
+
])}>
|
|
39
|
+
<span class={styles.number}>
|
|
40
|
+
{#if item.icon}
|
|
41
|
+
{@html item.icon}
|
|
42
|
+
{:else}
|
|
43
|
+
{index + 1}
|
|
44
|
+
{/if}
|
|
45
|
+
</span>
|
|
46
|
+
<ConditionalWrapper
|
|
47
|
+
condition={!!(item.title && item.subTitle)}
|
|
48
|
+
class={styles.container}
|
|
49
|
+
>
|
|
50
|
+
{#if item.title}
|
|
51
|
+
<span>{item.title}</span>
|
|
52
|
+
{/if}
|
|
53
|
+
{#if item.subTitle}
|
|
54
|
+
<span class={styles.muted}>{item.subTitle}</span>
|
|
55
|
+
{/if}
|
|
56
|
+
</ConditionalWrapper>
|
|
57
|
+
</li>
|
|
58
|
+
{/each}
|
|
59
|
+
</ol>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { StepperProps } from './stepper'
|
|
3
|
+
|
|
4
|
+
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.tsx'
|
|
5
|
+
|
|
6
|
+
import { classNames } from '../../utils/classNames'
|
|
7
|
+
|
|
8
|
+
import styles from './stepper.module.scss'
|
|
9
|
+
|
|
10
|
+
const Stepper = ({
|
|
11
|
+
items,
|
|
12
|
+
color,
|
|
13
|
+
completedColor,
|
|
14
|
+
activeColor,
|
|
15
|
+
borderless,
|
|
16
|
+
vertical,
|
|
17
|
+
className
|
|
18
|
+
}: StepperProps) => {
|
|
19
|
+
const classes = classNames([
|
|
20
|
+
styles.stepper,
|
|
21
|
+
borderless && styles.borderless,
|
|
22
|
+
vertical && styles.vertical,
|
|
23
|
+
className
|
|
24
|
+
])
|
|
25
|
+
|
|
26
|
+
const styleVariables = {
|
|
27
|
+
...(color && { '--w-stepper-color-border': color }),
|
|
28
|
+
...(completedColor && { '--w-stepper-color-complete': completedColor }),
|
|
29
|
+
...(activeColor && { '--w-stepper-color-active': activeColor })
|
|
30
|
+
} as React.CSSProperties
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<ol className={classes} style={styleVariables}>
|
|
34
|
+
{items?.map((item, index) => (
|
|
35
|
+
<li className={classNames([
|
|
36
|
+
index !== 0 && styles.connect,
|
|
37
|
+
item.active && styles.active,
|
|
38
|
+
item.completed && styles.completed
|
|
39
|
+
])} key={index}>
|
|
40
|
+
<span
|
|
41
|
+
className={styles.number}
|
|
42
|
+
dangerouslySetInnerHTML={{ __html: item.icon
|
|
43
|
+
? item.icon
|
|
44
|
+
: index + 1
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
<ConditionalWrapper
|
|
48
|
+
condition={!!(item.title && item.subTitle)}
|
|
49
|
+
wrapper={children => <div className={styles.container}>{children}</div>}
|
|
50
|
+
>
|
|
51
|
+
{item.title && <span>{item.title}</span>}
|
|
52
|
+
{item.subTitle && <span className={styles.muted}>{item.subTitle}</span>}
|
|
53
|
+
</ConditionalWrapper>
|
|
54
|
+
</li>
|
|
55
|
+
))}
|
|
56
|
+
</ol>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default Stepper
|