webcoreui 0.6.0 → 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/Button/button.ts +1 -1
- package/components/Carousel/Carousel.astro +16 -7
- package/components/Carousel/Carousel.svelte +15 -5
- package/components/Carousel/Carousel.tsx +15 -5
- package/components/Carousel/carousel.module.scss +4 -1
- package/components/Carousel/carousel.ts +1 -1
- package/components/DataTable/DataTable.astro +2 -2
- package/components/DataTable/DataTable.tsx +287 -287
- 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/Pagination/Pagination.astro +2 -0
- package/components/Pagination/Pagination.svelte +6 -3
- package/components/Pagination/Pagination.tsx +5 -3
- package/components/Pagination/pagination.ts +1 -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/index.d.ts +8 -0
- package/index.js +1 -0
- package/package.json +5 -4
- package/react.d.ts +15 -0
- package/react.js +10 -0
- package/scss/config/typography.scss +3 -1
- package/scss/global/utility.scss +5 -1
- package/scss/resets.scss +5 -0
- package/svelte.d.ts +15 -0
- package/svelte.js +10 -0
- package/utils/DOMUtils.ts +28 -0
- package/scss/global/elements.scss +0 -31
|
@@ -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
|
+
}
|
|
@@ -150,6 +150,7 @@ const generatedPages = pages?.length
|
|
|
150
150
|
const prevPageButton = element.querySelector('[data-page="prev"]') as HTMLButtonElement
|
|
151
151
|
const nextPageButton = element.querySelector('[data-page="next"]') as HTMLButtonElement
|
|
152
152
|
const currentPageButton = element.querySelector('[data-active]') as HTMLButtonElement
|
|
153
|
+
const previousPage = currentPage
|
|
153
154
|
|
|
154
155
|
const pageElements = Array
|
|
155
156
|
.from(pagination.children)
|
|
@@ -179,6 +180,7 @@ const generatedPages = pages?.length
|
|
|
179
180
|
|
|
180
181
|
dispatch('paginate', {
|
|
181
182
|
page: currentPage,
|
|
183
|
+
direction: previousPage > currentPage ? 'prev' : 'next',
|
|
182
184
|
...(activeButton?.dataset.page && { label: activeButton?.dataset.page }),
|
|
183
185
|
target: element,
|
|
184
186
|
trusted: event.isTrusted
|
|
@@ -45,6 +45,8 @@
|
|
|
45
45
|
}))
|
|
46
46
|
|
|
47
47
|
const paginate = (to: string | number) => {
|
|
48
|
+
const previousPage = calculatedCurrentPage
|
|
49
|
+
|
|
48
50
|
if (to === 'prev') {
|
|
49
51
|
calculatedCurrentPage = calculatedCurrentPage - 1
|
|
50
52
|
} else if (to === 'next') {
|
|
@@ -57,6 +59,7 @@
|
|
|
57
59
|
|
|
58
60
|
onChange?.({
|
|
59
61
|
page: calculatedCurrentPage,
|
|
62
|
+
direction: previousPage > calculatedCurrentPage ? 'prev' : 'next',
|
|
60
63
|
...(label && { label })
|
|
61
64
|
})
|
|
62
65
|
}
|
|
@@ -87,7 +90,7 @@
|
|
|
87
90
|
theme={theme}
|
|
88
91
|
onClick={!(disablePrevious || (calculatedCurrentPage === 1 && !previousLink))
|
|
89
92
|
? () => paginate('prev')
|
|
90
|
-
:
|
|
93
|
+
: undefined
|
|
91
94
|
}
|
|
92
95
|
>
|
|
93
96
|
{#if showChevrons || type === 'arrows'}
|
|
@@ -107,7 +110,7 @@
|
|
|
107
110
|
theme={theme}
|
|
108
111
|
onClick={calculatedCurrentPage !== index + 1
|
|
109
112
|
? () => paginate(index + 1)
|
|
110
|
-
:
|
|
113
|
+
: undefined
|
|
111
114
|
}
|
|
112
115
|
>
|
|
113
116
|
{page.label}
|
|
@@ -129,7 +132,7 @@
|
|
|
129
132
|
theme={theme}
|
|
130
133
|
onClick={!disableNext
|
|
131
134
|
? () => paginate('next')
|
|
132
|
-
:
|
|
135
|
+
: undefined
|
|
133
136
|
}
|
|
134
137
|
>
|
|
135
138
|
{#if type !== 'arrows'}
|
|
@@ -53,6 +53,7 @@ const Pagination = ({
|
|
|
53
53
|
}))
|
|
54
54
|
|
|
55
55
|
const paginate = (to: string | number) => {
|
|
56
|
+
const previousPage = calculatedCurrentPage
|
|
56
57
|
let currentPage = calculatedCurrentPage
|
|
57
58
|
|
|
58
59
|
if (to === 'prev') {
|
|
@@ -69,6 +70,7 @@ const Pagination = ({
|
|
|
69
70
|
|
|
70
71
|
onChange?.({
|
|
71
72
|
page: currentPage,
|
|
73
|
+
direction: previousPage > currentPage ? 'prev' : 'next',
|
|
72
74
|
...(label && { label })
|
|
73
75
|
})
|
|
74
76
|
}
|
|
@@ -104,7 +106,7 @@ const Pagination = ({
|
|
|
104
106
|
theme={theme}
|
|
105
107
|
onClick={!(disablePrevious || (calculatedCurrentPage === 1 && !previousLink))
|
|
106
108
|
? () => paginate('prev')
|
|
107
|
-
:
|
|
109
|
+
: undefined
|
|
108
110
|
}
|
|
109
111
|
>
|
|
110
112
|
{(showChevrons || type === 'arrows') && (
|
|
@@ -122,7 +124,7 @@ const Pagination = ({
|
|
|
122
124
|
theme={theme}
|
|
123
125
|
onClick={calculatedCurrentPage !== index + 1
|
|
124
126
|
? () => paginate(index + 1)
|
|
125
|
-
:
|
|
127
|
+
: undefined
|
|
126
128
|
}
|
|
127
129
|
>
|
|
128
130
|
{page.label}
|
|
@@ -144,7 +146,7 @@ const Pagination = ({
|
|
|
144
146
|
theme={theme}
|
|
145
147
|
onClick={!disableNext
|
|
146
148
|
? () => paginate('next')
|
|
147
|
-
:
|
|
149
|
+
: undefined
|
|
148
150
|
}
|
|
149
151
|
>
|
|
150
152
|
{type !== 'arrows' && nextPageLabel}
|
|
@@ -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
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
@import '../../scss/config.scss';
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
--w-stepper-color-border: var(--w-color-primary-50);
|
|
5
|
+
--w-stepper-color-active: var(--w-color-info);
|
|
6
|
+
--w-stepper-color-complete: var(--w-color-success);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
$size: 20px;
|
|
10
|
+
|
|
11
|
+
.stepper {
|
|
12
|
+
@include layout(flex, default, column);
|
|
13
|
+
@include spacing(0);
|
|
14
|
+
@include size('w100%');
|
|
15
|
+
|
|
16
|
+
list-style-type: none;
|
|
17
|
+
|
|
18
|
+
&:not(.borderless) .number {
|
|
19
|
+
border: 2px solid var(--w-stepper-color-border);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
li {
|
|
23
|
+
@include layout(flex, sm, v-center);
|
|
24
|
+
@include typography(normal);
|
|
25
|
+
@include spacing(m0);
|
|
26
|
+
|
|
27
|
+
flex: 1;
|
|
28
|
+
|
|
29
|
+
&.connect {
|
|
30
|
+
@include position(relative);
|
|
31
|
+
|
|
32
|
+
&::before {
|
|
33
|
+
@include position(absolute, l16px);
|
|
34
|
+
@include background(var(--w-stepper-color-border));
|
|
35
|
+
@include size(w2px);
|
|
36
|
+
|
|
37
|
+
top: -50%;
|
|
38
|
+
bottom: calc(50% + $size);
|
|
39
|
+
|
|
40
|
+
content: '';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&.completed::before,
|
|
44
|
+
&.active::before {
|
|
45
|
+
@include background(var(--w-stepper-color-complete));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&.active .number {
|
|
50
|
+
border-color: var(--w-stepper-color-active);
|
|
51
|
+
color: var(--w-stepper-color-active);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&.completed .number {
|
|
55
|
+
border-color: var(--w-stepper-color-complete);
|
|
56
|
+
color: var(--w-stepper-color-complete);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.number {
|
|
60
|
+
@include size($size);
|
|
61
|
+
@include border-radius(max);
|
|
62
|
+
@include layout(flex, center);
|
|
63
|
+
@include spacing(p-md);
|
|
64
|
+
@include typography(bold, md);
|
|
65
|
+
|
|
66
|
+
svg {
|
|
67
|
+
@include position(absolute);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.container {
|
|
72
|
+
@include layout(flex, column);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.muted {
|
|
76
|
+
@include typography(primary-20, md);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@include media(xs) {
|
|
82
|
+
.stepper:not(.vertical) {
|
|
83
|
+
@include layout(row);
|
|
84
|
+
|
|
85
|
+
li {
|
|
86
|
+
@include layout(column, xs, v-center);
|
|
87
|
+
|
|
88
|
+
&.connect::before {
|
|
89
|
+
@include size(h2px);
|
|
90
|
+
|
|
91
|
+
width: auto;
|
|
92
|
+
top: 16px;
|
|
93
|
+
left: calc(-50%);
|
|
94
|
+
right: calc(50% + $size);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.container {
|
|
98
|
+
@include layout(v-center);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IconProps } from '../Icon/icon'
|
|
2
|
+
|
|
3
|
+
export type StepperProps = {
|
|
4
|
+
items: {
|
|
5
|
+
icon?: IconProps['type'] | string
|
|
6
|
+
title?: string
|
|
7
|
+
subTitle?: string
|
|
8
|
+
completed?: boolean
|
|
9
|
+
active?: boolean
|
|
10
|
+
}[]
|
|
11
|
+
color?: string
|
|
12
|
+
completedColor?: string
|
|
13
|
+
activeColor?: string
|
|
14
|
+
borderless?: boolean
|
|
15
|
+
vertical?: boolean
|
|
16
|
+
className?: string
|
|
17
|
+
}
|
package/icons/close.svg
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<path
|
|
2
|
+
<path d="M23 1L1 23M1 1L23 23" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
3
|
</svg>
|
package/icons/plus.svg
ADDED