webcoreui 0.3.0 → 0.4.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 +5 -2
- package/astro.d.ts +7 -1
- package/astro.js +6 -0
- package/components/Accordion/Accordion.astro +2 -0
- package/components/Accordion/Accordion.svelte +2 -0
- package/components/Accordion/Accordion.tsx +2 -0
- package/components/Alert/Alert.astro +3 -2
- package/components/Alert/Alert.svelte +4 -3
- package/components/Alert/Alert.tsx +3 -2
- package/components/Avatar/Avatar.astro +2 -1
- package/components/Avatar/Avatar.svelte +2 -1
- package/components/Avatar/Avatar.tsx +3 -3
- package/components/Badge/Badge.astro +1 -0
- package/components/Badge/Badge.svelte +3 -2
- package/components/Badge/Badge.tsx +2 -1
- package/components/Button/Button.astro +4 -5
- package/components/Button/Button.svelte +2 -1
- package/components/Button/Button.tsx +2 -1
- package/components/Button/button.ts +1 -1
- package/components/Card/Card.astro +11 -3
- package/components/Card/Card.svelte +5 -2
- package/components/Card/Card.tsx +5 -2
- package/components/Card/card.ts +1 -0
- package/components/Checkbox/Checkbox.astro +1 -0
- package/components/Checkbox/Checkbox.svelte +7 -5
- package/components/Checkbox/Checkbox.tsx +4 -2
- package/components/Collapsible/Collapsible.astro +2 -1
- package/components/Collapsible/Collapsible.svelte +2 -1
- package/components/Collapsible/Collapsible.tsx +55 -54
- package/components/ConditionalWrapper/ConditionalWrapper.astro +2 -1
- package/components/ConditionalWrapper/ConditionalWrapper.tsx +1 -2
- package/components/Group/Group.astro +22 -0
- package/components/Group/Group.svelte +20 -0
- package/components/Group/Group.tsx +22 -0
- package/components/Group/group.module.scss +43 -0
- package/components/Group/group.ts +8 -0
- package/components/Icon/map.ts +2 -0
- package/components/Input/Input.astro +8 -1
- package/components/Input/Input.svelte +15 -3
- package/components/Input/Input.tsx +10 -3
- package/components/Input/input.module.scss +4 -1
- package/components/Input/input.ts +9 -4
- package/components/List/List.astro +169 -0
- package/components/List/List.svelte +147 -0
- package/components/List/List.tsx +168 -0
- package/components/List/list.module.scss +91 -0
- package/components/List/list.ts +37 -0
- package/components/Menu/Menu.astro +2 -1
- package/components/Menu/Menu.svelte +7 -5
- package/components/Menu/Menu.tsx +116 -113
- package/components/Modal/Modal.astro +6 -4
- package/components/Modal/Modal.svelte +8 -6
- package/components/Modal/Modal.tsx +79 -76
- package/components/Modal/modal.ts +1 -0
- package/components/Popover/Popover.astro +4 -1
- package/components/Popover/Popover.svelte +4 -2
- package/components/Popover/Popover.tsx +55 -27
- package/components/Popover/popover.module.scss +1 -0
- package/components/Popover/popover.ts +2 -0
- package/components/Progress/Progress.astro +2 -1
- package/components/Progress/Progress.svelte +2 -1
- package/components/Progress/Progress.tsx +3 -2
- package/components/Radio/Radio.astro +1 -0
- package/components/Radio/Radio.svelte +4 -2
- package/components/Radio/Radio.tsx +3 -2
- package/components/Rating/Rating.astro +3 -1
- package/components/Rating/Rating.svelte +9 -7
- package/components/Rating/Rating.tsx +4 -2
- package/components/Select/Select.astro +135 -0
- package/components/Select/Select.svelte +122 -0
- package/components/Select/Select.tsx +142 -0
- package/components/Select/select.module.scss +25 -0
- package/components/Select/select.ts +21 -0
- package/components/Sheet/Sheet.astro +2 -1
- package/components/Sheet/Sheet.svelte +2 -1
- package/components/Sheet/Sheet.tsx +33 -32
- package/components/Slider/Slider.astro +2 -1
- package/components/Slider/Slider.svelte +2 -1
- package/components/Slider/Slider.tsx +49 -48
- package/components/Spinner/Spinner.astro +4 -3
- package/components/Spinner/Spinner.svelte +3 -2
- package/components/Spinner/Spinner.tsx +4 -3
- package/components/Switch/Switch.astro +2 -1
- package/components/Switch/Switch.svelte +5 -4
- package/components/Switch/Switch.tsx +2 -2
- package/components/Switch/switch.module.scss +1 -1
- package/components/Table/Table.astro +1 -0
- package/components/Table/Table.svelte +2 -1
- package/components/Table/Table.tsx +2 -1
- package/components/Tabs/Tabs.astro +2 -1
- package/components/Tabs/Tabs.svelte +2 -1
- package/components/Tabs/Tabs.tsx +4 -3
- package/components/Textarea/Textarea.astro +1 -0
- package/components/Textarea/Textarea.svelte +3 -1
- package/components/Textarea/Textarea.tsx +52 -50
- package/components/ThemeSwitcher/ThemeSwitcher.astro +108 -107
- package/components/ThemeSwitcher/ThemeSwitcher.svelte +5 -4
- package/components/ThemeSwitcher/ThemeSwitcher.tsx +91 -90
- package/components/Timeline/Timeline.astro +3 -2
- package/components/Timeline/Timeline.svelte +3 -2
- package/components/Timeline/Timeline.tsx +3 -2
- package/components/TimelineItem/TimelineItem.svelte +2 -1
- package/components/TimelineItem/TimelineItem.tsx +2 -1
- package/components/Toast/Toast.astro +3 -1
- package/components/Toast/Toast.svelte +3 -1
- package/components/Toast/Toast.tsx +3 -1
- package/icons/moon.svg +1 -1
- package/icons/search.svg +3 -0
- package/icons.d.ts +1 -0
- package/icons.js +1 -0
- package/index.d.ts +55 -25
- package/package.json +22 -4
- package/react.d.ts +6 -0
- package/react.js +6 -0
- package/scss/config/mixins.scss +12 -10
- package/scss/config/variables.scss +1 -0
- package/scss/config.scss +1 -0
- package/scss/global/utility.scss +2 -0
- package/svelte.d.ts +7 -1
- package/svelte.js +6 -0
- package/utils/cookies.ts +4 -4
- package/utils/debounce.ts +1 -1
- package/utils/event.ts +2 -2
- package/utils/interpolate.ts +5 -5
- package/utils/modal.ts +90 -27
- package/utils/popover.ts +30 -8
- package/utils/toast.ts +6 -2
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { SvelteRadioProps } from './radio'
|
|
3
|
+
|
|
3
4
|
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.svelte'
|
|
4
5
|
|
|
5
|
-
import styles from './radio.module.scss'
|
|
6
6
|
import { classNames } from '../../utils/classNames'
|
|
7
7
|
|
|
8
|
+
import styles from './radio.module.scss'
|
|
9
|
+
|
|
8
10
|
export let name: SvelteRadioProps['name'] = ''
|
|
9
11
|
export let items: SvelteRadioProps['items'] = []
|
|
10
|
-
export let color: SvelteRadioProps['color'] =
|
|
12
|
+
export let color: SvelteRadioProps['color'] = ''
|
|
11
13
|
export let inline: SvelteRadioProps['inline'] = false
|
|
12
14
|
export let className: SvelteRadioProps['className'] = ''
|
|
13
15
|
export let onChange: SvelteRadioProps['onChange'] = () => {}
|
|
@@ -3,9 +3,10 @@ import type { ReactRadioProps } from './radio'
|
|
|
3
3
|
|
|
4
4
|
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.tsx'
|
|
5
5
|
|
|
6
|
-
import styles from './radio.module.scss'
|
|
7
6
|
import { classNames } from '../../utils/classNames'
|
|
8
7
|
|
|
8
|
+
import styles from './radio.module.scss'
|
|
9
|
+
|
|
9
10
|
const Radio = ({
|
|
10
11
|
name,
|
|
11
12
|
items,
|
|
@@ -19,7 +20,7 @@ const Radio = ({
|
|
|
19
20
|
inline && styles.inline,
|
|
20
21
|
className
|
|
21
22
|
])
|
|
22
|
-
|
|
23
|
+
|
|
23
24
|
const style = color
|
|
24
25
|
? { '--w-radio-color': color } as React.CSSProperties
|
|
25
26
|
: undefined
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { RatingProps } from './rating'
|
|
3
|
+
|
|
3
4
|
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.astro'
|
|
4
5
|
|
|
5
|
-
import styles from './rating.module.scss'
|
|
6
6
|
import { classNames } from '../../utils/classNames'
|
|
7
7
|
|
|
8
|
+
import styles from './rating.module.scss'
|
|
9
|
+
|
|
8
10
|
interface Props extends RatingProps {}
|
|
9
11
|
|
|
10
12
|
const {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { RatingProps } from './rating'
|
|
3
|
+
|
|
3
4
|
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.svelte'
|
|
4
|
-
|
|
5
|
-
import styles from './rating.module.scss'
|
|
5
|
+
|
|
6
6
|
import { classNames } from '../../utils/classNames'
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
import styles from './rating.module.scss'
|
|
9
|
+
|
|
8
10
|
export let score: RatingProps['score']
|
|
9
11
|
export let total: RatingProps['total'] = 5
|
|
10
12
|
export let showText: RatingProps['showText'] = false
|
|
@@ -19,23 +21,23 @@
|
|
|
19
21
|
export let emptyColor: RatingProps['emptyColor'] = ''
|
|
20
22
|
export let size: RatingProps['size'] = 0
|
|
21
23
|
export let className: RatingProps['className'] = ''
|
|
22
|
-
|
|
24
|
+
|
|
23
25
|
const classes = classNames([
|
|
24
26
|
styles.rating,
|
|
25
27
|
outline && styles.outline,
|
|
26
28
|
className
|
|
27
29
|
])
|
|
28
|
-
|
|
30
|
+
|
|
29
31
|
const styleVariables = classNames([
|
|
30
32
|
color && `--w-rating-color: ${color};`,
|
|
31
33
|
size && `--w-rating-size: ${size}px;`,
|
|
32
34
|
emptyColor && `--w-rating-empty-color: ${emptyColor};`
|
|
33
35
|
])
|
|
34
|
-
|
|
36
|
+
|
|
35
37
|
const translatedText = text!
|
|
36
38
|
.replace('{0}', `${score}`)
|
|
37
39
|
.replace('{1}', `${total}`)
|
|
38
|
-
|
|
40
|
+
|
|
39
41
|
const translatedReviewText = reviewText?.replace('{0}', `${reviewCount}`)
|
|
40
42
|
</script>
|
|
41
43
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import type { RatingProps } from './rating'
|
|
3
|
+
|
|
3
4
|
import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.tsx'
|
|
4
5
|
|
|
5
|
-
import styles from './rating.module.scss'
|
|
6
6
|
import { classNames } from '../../utils/classNames'
|
|
7
7
|
|
|
8
|
+
import styles from './rating.module.scss'
|
|
9
|
+
|
|
8
10
|
const Rating = ({
|
|
9
11
|
score,
|
|
10
12
|
total = 5,
|
|
@@ -32,7 +34,7 @@ const Rating = ({
|
|
|
32
34
|
...(size && { '--w-rating-size': `${size}px` }),
|
|
33
35
|
...(emptyColor && { '--w-rating-empty-color': emptyColor })
|
|
34
36
|
} as React.CSSProperties
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
const translatedText = text
|
|
37
39
|
.replace('{0}', `${score}`)
|
|
38
40
|
.replace('{1}', `${total}`)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { SelectProps } from './select'
|
|
3
|
+
|
|
4
|
+
import Input from '../Input/Input.astro'
|
|
5
|
+
import List from '../List/List.astro'
|
|
6
|
+
import Modal from '../Modal/Modal.astro'
|
|
7
|
+
import Popover from '../Popover/Popover.astro'
|
|
8
|
+
|
|
9
|
+
import { classNames } from '../../utils/classNames'
|
|
10
|
+
|
|
11
|
+
import ArrowDown from '../../icons/arrow-down.svg?raw'
|
|
12
|
+
|
|
13
|
+
import styles from './select.module.scss'
|
|
14
|
+
|
|
15
|
+
interface Props extends SelectProps {}
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
name,
|
|
19
|
+
value,
|
|
20
|
+
placeholder,
|
|
21
|
+
label,
|
|
22
|
+
subText,
|
|
23
|
+
disabled,
|
|
24
|
+
className,
|
|
25
|
+
position,
|
|
26
|
+
...rest
|
|
27
|
+
} = Astro.props
|
|
28
|
+
|
|
29
|
+
const classes = classNames([
|
|
30
|
+
styles.select,
|
|
31
|
+
disabled && styles.disabled,
|
|
32
|
+
className
|
|
33
|
+
])
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
<Input
|
|
37
|
+
type="text"
|
|
38
|
+
value={value}
|
|
39
|
+
readonly={true}
|
|
40
|
+
disabled={disabled}
|
|
41
|
+
placeholder={placeholder}
|
|
42
|
+
label={label}
|
|
43
|
+
subText={subText}
|
|
44
|
+
data-id={`w-select-${name}`}
|
|
45
|
+
data-position={position}
|
|
46
|
+
labelClassName={classes}
|
|
47
|
+
>
|
|
48
|
+
<Fragment set:html={ArrowDown} />
|
|
49
|
+
</Input>
|
|
50
|
+
{position === 'modal'
|
|
51
|
+
? (
|
|
52
|
+
<Modal
|
|
53
|
+
className={styles.popover}
|
|
54
|
+
data-id={`w-options-${name}`}
|
|
55
|
+
showCloseIcon={false}
|
|
56
|
+
>
|
|
57
|
+
<List {...rest} />
|
|
58
|
+
</Modal>
|
|
59
|
+
) : (
|
|
60
|
+
<Popover className={styles.popover} data-id={`w-options-${name}`}>
|
|
61
|
+
<List {...rest} />
|
|
62
|
+
</Popover>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
<script>
|
|
67
|
+
import { debounce } from '../../utils/debounce'
|
|
68
|
+
import { dispatch, listen } from '../../utils/event'
|
|
69
|
+
import { modal } from '../../utils/modal'
|
|
70
|
+
import { closePopover, popover, type PopoverPosition } from '../../utils/popover'
|
|
71
|
+
|
|
72
|
+
const selects = document.querySelectorAll('[data-id^="w-select"]')
|
|
73
|
+
|
|
74
|
+
Array.from(selects).forEach(select => {
|
|
75
|
+
const selectElement = select as HTMLElement
|
|
76
|
+
const name = selectElement.dataset.id!.split('w-select-')[1]
|
|
77
|
+
const position = selectElement.dataset.position
|
|
78
|
+
|
|
79
|
+
if (position === 'modal') {
|
|
80
|
+
modal({
|
|
81
|
+
trigger: `[data-id="${selectElement.dataset.id}"]`,
|
|
82
|
+
modal: `[data-id="w-options-${name}"]`,
|
|
83
|
+
onOpen: ({ modal }) => {
|
|
84
|
+
const search = modal.querySelector('input')
|
|
85
|
+
|
|
86
|
+
if (search) {
|
|
87
|
+
search.focus()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
} else {
|
|
92
|
+
const resize = debounce(() => {
|
|
93
|
+
const { width } = selectElement.getBoundingClientRect()
|
|
94
|
+
const dialogElement = document.querySelector(`[data-id="w-options-${name}"]`) as HTMLDialogElement
|
|
95
|
+
|
|
96
|
+
if (dialogElement) {
|
|
97
|
+
dialogElement.style.width = `${width}px`
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
new ResizeObserver(() => resize()).observe(document.body)
|
|
102
|
+
|
|
103
|
+
popover({
|
|
104
|
+
trigger: `[data-id="${selectElement.dataset.id}"]`,
|
|
105
|
+
popover: `[data-id="w-options-${name}"]`,
|
|
106
|
+
position: position as PopoverPosition || 'bottom',
|
|
107
|
+
onOpen({ popover }) {
|
|
108
|
+
const search = popover.querySelector('input')
|
|
109
|
+
|
|
110
|
+
if (search) {
|
|
111
|
+
search.focus()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
listen('listOnSelect', payload => {
|
|
119
|
+
const { name, list } = payload
|
|
120
|
+
const dialog = list.closest('dialog')
|
|
121
|
+
const popoverId = dialog.dataset.id
|
|
122
|
+
const selectName = popoverId.split('w-options-')[1]
|
|
123
|
+
const selectId = `[data-id="w-select-${selectName}"]`
|
|
124
|
+
const selectElement = document.querySelector(selectId) as HTMLInputElement
|
|
125
|
+
|
|
126
|
+
closePopover(`[data-id="${popoverId}"]`)
|
|
127
|
+
|
|
128
|
+
selectElement.value = name
|
|
129
|
+
|
|
130
|
+
dispatch('selectOnChange', {
|
|
131
|
+
select: selectName,
|
|
132
|
+
...payload
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
</script>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte'
|
|
3
|
+
import type { SvelteSelectProps } from './select'
|
|
4
|
+
|
|
5
|
+
import Input from '../Input/Input.svelte'
|
|
6
|
+
import List from '../List/List.svelte'
|
|
7
|
+
import Modal from '../Modal/Modal.svelte'
|
|
8
|
+
import Popover from '../Popover/Popover.svelte'
|
|
9
|
+
|
|
10
|
+
import { classNames } from '../../utils/classNames'
|
|
11
|
+
import { debounce } from '../../utils/debounce'
|
|
12
|
+
import { modal } from '../../utils/modal'
|
|
13
|
+
import { closePopover, popover, type PopoverPosition } from '../../utils/popover'
|
|
14
|
+
|
|
15
|
+
import ArrowDown from '../../icons/arrow-down.svg?raw'
|
|
16
|
+
|
|
17
|
+
import styles from './select.module.scss'
|
|
18
|
+
|
|
19
|
+
export let name: SvelteSelectProps['name'] = ''
|
|
20
|
+
export let value: SvelteSelectProps['value'] = ''
|
|
21
|
+
export let placeholder: SvelteSelectProps['placeholder'] = ''
|
|
22
|
+
export let label: SvelteSelectProps['label'] = ''
|
|
23
|
+
export let subText: SvelteSelectProps['subText'] = ''
|
|
24
|
+
export let disabled: SvelteSelectProps['disabled'] = false
|
|
25
|
+
export let className: SvelteSelectProps['className'] = ''
|
|
26
|
+
export let position: SvelteSelectProps['position'] = 'bottom'
|
|
27
|
+
export let onChange: SvelteSelectProps['onChange'] = () => {}
|
|
28
|
+
|
|
29
|
+
let popoverInstance: any
|
|
30
|
+
|
|
31
|
+
const classes = classNames([
|
|
32
|
+
styles.select,
|
|
33
|
+
disabled && styles.disabled,
|
|
34
|
+
className
|
|
35
|
+
])
|
|
36
|
+
|
|
37
|
+
const popoverClasses = classNames([
|
|
38
|
+
`w-options-${name}`,
|
|
39
|
+
styles.popover
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
const select = (payload: any) => {
|
|
43
|
+
closePopover(`.w-options-${name}`)
|
|
44
|
+
|
|
45
|
+
value = payload.name
|
|
46
|
+
|
|
47
|
+
onChange?.({
|
|
48
|
+
select: name,
|
|
49
|
+
...payload
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
onMount(() => {
|
|
54
|
+
if (position === 'modal') {
|
|
55
|
+
modal({
|
|
56
|
+
trigger: `.w-select-${name}`,
|
|
57
|
+
modal: `.w-options-${name}`,
|
|
58
|
+
onOpen: ({ modal }) => {
|
|
59
|
+
const search = modal.querySelector('input')
|
|
60
|
+
|
|
61
|
+
if (search) {
|
|
62
|
+
search.focus()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
} else {
|
|
67
|
+
const resize = debounce(() => {
|
|
68
|
+
const selectElement = document.querySelector(`.w-select-${name}`) as HTMLInputElement
|
|
69
|
+
|
|
70
|
+
const { width } = selectElement.getBoundingClientRect()
|
|
71
|
+
const dialogElement = document.querySelector(`.w-options-${name}`) as HTMLDialogElement
|
|
72
|
+
|
|
73
|
+
dialogElement.style.width = `${width}px`
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
new ResizeObserver(() => resize()).observe(document.body)
|
|
77
|
+
|
|
78
|
+
popoverInstance = popover({
|
|
79
|
+
trigger: `.w-select-${name}`,
|
|
80
|
+
popover: `.w-options-${name}`,
|
|
81
|
+
position: position as PopoverPosition,
|
|
82
|
+
onOpen({ popover }) {
|
|
83
|
+
const search = popover.querySelector('input')
|
|
84
|
+
|
|
85
|
+
if (search) {
|
|
86
|
+
search.focus()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return () => {
|
|
93
|
+
popoverInstance?.remove()
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
</script>
|
|
97
|
+
|
|
98
|
+
<Input
|
|
99
|
+
type="text"
|
|
100
|
+
value={value}
|
|
101
|
+
readonly={true}
|
|
102
|
+
disabled={disabled}
|
|
103
|
+
placeholder={placeholder}
|
|
104
|
+
label={label}
|
|
105
|
+
subText={subText}
|
|
106
|
+
className={`w-select-${name}`}
|
|
107
|
+
labelClassName={classes}
|
|
108
|
+
>
|
|
109
|
+
{@html ArrowDown}
|
|
110
|
+
</Input>
|
|
111
|
+
{#if position === 'modal'}
|
|
112
|
+
<Modal
|
|
113
|
+
className={popoverClasses}
|
|
114
|
+
showCloseIcon={false}
|
|
115
|
+
>
|
|
116
|
+
<List onSelect={select} {...$$restProps} />
|
|
117
|
+
</Modal>
|
|
118
|
+
{:else}
|
|
119
|
+
<Popover className={popoverClasses}>
|
|
120
|
+
<List onSelect={select} {...$$restProps} />
|
|
121
|
+
</Popover>
|
|
122
|
+
{/if}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import React, { useEffect,useState } from 'react'
|
|
2
|
+
import type { ReactSelectProps } from './select'
|
|
3
|
+
|
|
4
|
+
import Input from '../Input/Input.tsx'
|
|
5
|
+
import List from '../List/List.tsx'
|
|
6
|
+
import Modal from '../Modal/Modal.tsx'
|
|
7
|
+
import Popover from '../Popover/Popover.tsx'
|
|
8
|
+
|
|
9
|
+
import { classNames } from '../../utils/classNames'
|
|
10
|
+
import { debounce } from '../../utils/debounce'
|
|
11
|
+
import { modal } from '../../utils/modal'
|
|
12
|
+
import { closePopover, popover, type PopoverPosition } from '../../utils/popover'
|
|
13
|
+
|
|
14
|
+
import ArrowDown from '../../icons/arrow-down.svg?raw'
|
|
15
|
+
|
|
16
|
+
import styles from './select.module.scss'
|
|
17
|
+
|
|
18
|
+
const Select = ({
|
|
19
|
+
name,
|
|
20
|
+
value,
|
|
21
|
+
placeholder,
|
|
22
|
+
label,
|
|
23
|
+
subText,
|
|
24
|
+
disabled,
|
|
25
|
+
className,
|
|
26
|
+
position = 'bottom',
|
|
27
|
+
onChange,
|
|
28
|
+
...rest
|
|
29
|
+
}: ReactSelectProps) => {
|
|
30
|
+
const [val, setValue] = useState(value)
|
|
31
|
+
|
|
32
|
+
const classes = classNames([
|
|
33
|
+
styles.select,
|
|
34
|
+
className
|
|
35
|
+
])
|
|
36
|
+
|
|
37
|
+
const popoverClasses = classNames([
|
|
38
|
+
`w-options-${name}`,
|
|
39
|
+
styles.popover
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
let popoverInstance: any
|
|
43
|
+
|
|
44
|
+
const select = (payload: any) => {
|
|
45
|
+
closePopover(`.w-options-${name}`)
|
|
46
|
+
|
|
47
|
+
setValue(payload.name)
|
|
48
|
+
|
|
49
|
+
onChange?.({
|
|
50
|
+
select: name,
|
|
51
|
+
...payload
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (position === 'modal') {
|
|
57
|
+
modal({
|
|
58
|
+
trigger: `.w-select-${name}`,
|
|
59
|
+
modal: `.w-options-${name}`,
|
|
60
|
+
onOpen: ({ modal }) => {
|
|
61
|
+
const search = modal.querySelector('input')
|
|
62
|
+
|
|
63
|
+
if (search) {
|
|
64
|
+
search.focus()
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
} else {
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
const resize = debounce(() => {
|
|
71
|
+
const selectElement = document.querySelector(`.w-select-${name}`) as HTMLInputElement
|
|
72
|
+
|
|
73
|
+
const { width } = selectElement.getBoundingClientRect()
|
|
74
|
+
const dialogElement = document.querySelector(`.w-options-${name}`) as HTMLDialogElement
|
|
75
|
+
|
|
76
|
+
dialogElement.style.width = `${width}px`
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
new ResizeObserver(() => resize()).observe(document.body)
|
|
80
|
+
|
|
81
|
+
popoverInstance = popover({
|
|
82
|
+
trigger: `.w-select-${name}`,
|
|
83
|
+
popover: `.w-options-${name}`,
|
|
84
|
+
position: position as PopoverPosition,
|
|
85
|
+
onOpen({ popover }) {
|
|
86
|
+
const search = popover.querySelector('input')
|
|
87
|
+
|
|
88
|
+
if (search) {
|
|
89
|
+
search.focus()
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
}, 0)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return () => {
|
|
97
|
+
popoverInstance?.remove()
|
|
98
|
+
}
|
|
99
|
+
}, [])
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<React.Fragment>
|
|
103
|
+
<Input
|
|
104
|
+
type="text"
|
|
105
|
+
value={val}
|
|
106
|
+
readOnly={true}
|
|
107
|
+
disabled={disabled}
|
|
108
|
+
placeholder={placeholder}
|
|
109
|
+
label={label}
|
|
110
|
+
subText={subText}
|
|
111
|
+
className={`w-select-${name}`}
|
|
112
|
+
labelClassName={classes}
|
|
113
|
+
>
|
|
114
|
+
<span
|
|
115
|
+
dangerouslySetInnerHTML={{ __html: ArrowDown }}
|
|
116
|
+
style={{
|
|
117
|
+
height: '18px',
|
|
118
|
+
position: 'absolute',
|
|
119
|
+
right: 0,
|
|
120
|
+
pointerEvents: 'none'
|
|
121
|
+
}}
|
|
122
|
+
/>
|
|
123
|
+
</Input>
|
|
124
|
+
{position === 'modal'
|
|
125
|
+
? (
|
|
126
|
+
<Modal
|
|
127
|
+
className={popoverClasses}
|
|
128
|
+
showCloseIcon={false}
|
|
129
|
+
>
|
|
130
|
+
<List onSelect={select} {...rest} />
|
|
131
|
+
</Modal>
|
|
132
|
+
) : (
|
|
133
|
+
<Popover className={popoverClasses} isInteractive={true}>
|
|
134
|
+
<List onSelect={select} {...rest} />
|
|
135
|
+
</Popover>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
</React.Fragment>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export default Select
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
@import '../../scss/config.scss';
|
|
2
|
+
|
|
3
|
+
.select {
|
|
4
|
+
svg {
|
|
5
|
+
@include position(r10px);
|
|
6
|
+
|
|
7
|
+
left: auto !important;
|
|
8
|
+
cursor: pointer;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
input {
|
|
12
|
+
cursor: pointer;
|
|
13
|
+
padding-left: 10px !important;
|
|
14
|
+
padding-right: 40px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&.disabled svg {
|
|
18
|
+
cursor: no-drop;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.popover {
|
|
23
|
+
padding: 0 !important;
|
|
24
|
+
border: 0 !important;
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PopoverPosition } from '../../utils/popover'
|
|
2
|
+
|
|
3
|
+
import type { ListEventType, ListProps } from '../List/list'
|
|
4
|
+
|
|
5
|
+
export type SelectProps = {
|
|
6
|
+
name: string
|
|
7
|
+
value?: string
|
|
8
|
+
placeholder?: string
|
|
9
|
+
label?: string
|
|
10
|
+
subText?: string
|
|
11
|
+
disabled?: boolean
|
|
12
|
+
position?: PopoverPosition | 'modal'
|
|
13
|
+
} & ListProps
|
|
14
|
+
|
|
15
|
+
export type SvelteSelectProps = {
|
|
16
|
+
onChange?: (event: ListEventType & { select: string }) => void
|
|
17
|
+
} & SelectProps
|
|
18
|
+
|
|
19
|
+
export type ReactSelectProps = {
|
|
20
|
+
onChange?: (event: ListEventType & { select: string }) => void
|
|
21
|
+
} & SelectProps
|
|
@@ -3,9 +3,10 @@ import type { SheetProps } from './sheet'
|
|
|
3
3
|
|
|
4
4
|
import Modal from '../Modal/Modal.astro'
|
|
5
5
|
|
|
6
|
-
import styles from './sheet.module.scss'
|
|
7
6
|
import { classNames } from '../../utils/classNames'
|
|
8
7
|
|
|
8
|
+
import styles from './sheet.module.scss'
|
|
9
|
+
|
|
9
10
|
interface Props extends SheetProps {}
|
|
10
11
|
|
|
11
12
|
const {
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
import Modal from '../Modal/Modal.svelte'
|
|
5
5
|
|
|
6
|
-
import styles from './sheet.module.scss'
|
|
7
6
|
import { classNames } from '../../utils/classNames'
|
|
8
7
|
|
|
8
|
+
import styles from './sheet.module.scss'
|
|
9
|
+
|
|
9
10
|
export let position: SheetProps['position'] = null
|
|
10
11
|
export let className: SheetProps['className'] = ''
|
|
11
12
|
|
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import type { ReactSheetProps } from './sheet'
|
|
3
|
-
|
|
4
|
-
import Modal from '../Modal/Modal.tsx'
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { ReactSheetProps } from './sheet'
|
|
3
|
+
|
|
4
|
+
import Modal from '../Modal/Modal.tsx'
|
|
5
|
+
|
|
6
|
+
import { classNames } from '../../utils/classNames'
|
|
7
|
+
|
|
8
|
+
import styles from './sheet.module.scss'
|
|
9
|
+
|
|
10
|
+
const Sheet = ({
|
|
11
|
+
position,
|
|
12
|
+
className,
|
|
13
|
+
children,
|
|
14
|
+
...rest
|
|
15
|
+
}: ReactSheetProps) => {
|
|
16
|
+
const classes = classNames([
|
|
17
|
+
styles.sheet,
|
|
18
|
+
position && styles[position],
|
|
19
|
+
className
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Modal
|
|
24
|
+
className={classes}
|
|
25
|
+
{...rest}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</Modal>
|
|
29
|
+
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default Sheet
|