@charcoal-ui/react 3.0.0-beta.2 → 3.0.0-beta.3
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/dist/_lib/compat.d.ts +1 -1
- package/dist/_lib/compat.d.ts.map +1 -1
- package/dist/components/Button/index.d.ts +1 -2
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.story.d.ts +1 -2
- package/dist/components/Button/index.story.d.ts.map +1 -1
- package/dist/components/Button/index.test.d.ts +4 -0
- package/dist/components/Button/index.test.d.ts.map +1 -0
- package/dist/components/Checkbox/index.d.ts +1 -1
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.story.d.ts +1 -2
- package/dist/components/Checkbox/index.story.d.ts.map +1 -1
- package/dist/components/Clickable/index.d.ts +1 -1
- package/dist/components/Clickable/index.d.ts.map +1 -1
- package/dist/components/Clickable/index.story.d.ts +1 -2
- package/dist/components/Clickable/index.story.d.ts.map +1 -1
- package/dist/components/DropdownSelector/Divider.d.ts +3 -0
- package/dist/components/DropdownSelector/Divider.d.ts.map +1 -1
- package/dist/components/DropdownSelector/DropdownMenuItem.d.ts +7 -0
- package/dist/components/DropdownSelector/DropdownMenuItem.d.ts.map +1 -0
- package/dist/components/DropdownSelector/DropdownPopover.d.ts +8 -8
- package/dist/components/DropdownSelector/DropdownPopover.d.ts.map +1 -1
- package/dist/components/DropdownSelector/ListItem/index.d.ts +18 -0
- package/dist/components/DropdownSelector/ListItem/index.d.ts.map +1 -0
- package/dist/components/DropdownSelector/ListItem/index.story.d.ts +9 -0
- package/dist/components/DropdownSelector/ListItem/index.story.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuItem/index.d.ts +11 -0
- package/dist/components/DropdownSelector/MenuItem/index.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.d.ts +9 -0
- package/dist/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.d.ts +10 -0
- package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuItemGroup/index.d.ts +14 -0
- package/dist/components/DropdownSelector/MenuItemGroup/index.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuList/MenuListContext.d.ts +10 -0
- package/dist/components/DropdownSelector/MenuList/MenuListContext.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuList/index.d.ts +18 -0
- package/dist/components/DropdownSelector/MenuList/index.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuList/index.story.d.ts +11 -0
- package/dist/components/DropdownSelector/MenuList/index.story.d.ts.map +1 -0
- package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.d.ts +11 -0
- package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.d.ts.map +1 -0
- package/dist/components/DropdownSelector/Popover/index.d.ts +17 -0
- package/dist/components/DropdownSelector/Popover/index.d.ts.map +1 -0
- package/dist/components/DropdownSelector/Popover/index.story.d.ts +9 -0
- package/dist/components/DropdownSelector/Popover/index.story.d.ts.map +1 -0
- package/dist/components/DropdownSelector/index.d.ts +3 -10
- package/dist/components/DropdownSelector/index.d.ts.map +1 -1
- package/dist/components/DropdownSelector/index.story.d.ts +4 -4
- package/dist/components/DropdownSelector/index.story.d.ts.map +1 -1
- package/dist/components/DropdownSelector/utils/findPreviewRecursive.d.ts +12 -0
- package/dist/components/DropdownSelector/utils/findPreviewRecursive.d.ts.map +1 -0
- package/dist/components/FieldLabel/index.d.ts +1 -1
- package/dist/components/FieldLabel/index.d.ts.map +1 -1
- package/dist/components/Icon/index.d.ts +1 -1
- package/dist/components/Icon/index.d.ts.map +1 -1
- package/dist/components/Icon/index.story.d.ts +2 -3
- package/dist/components/Icon/index.story.d.ts.map +1 -1
- package/dist/components/IconButton/index.d.ts +1 -2
- package/dist/components/IconButton/index.d.ts.map +1 -1
- package/dist/components/IconButton/index.story.d.ts +1 -2
- package/dist/components/IconButton/index.story.d.ts.map +1 -1
- package/dist/components/LoadingSpinner/index.d.ts +1 -2
- package/dist/components/LoadingSpinner/index.d.ts.map +1 -1
- package/dist/components/Modal/ModalPlumbing.d.ts.map +1 -1
- package/dist/components/Modal/index.d.ts +1 -1
- package/dist/components/Modal/index.d.ts.map +1 -1
- package/dist/components/Modal/index.story.d.ts.map +1 -1
- package/dist/components/MultiSelect/context.d.ts +1 -1
- package/dist/components/MultiSelect/context.d.ts.map +1 -1
- package/dist/components/MultiSelect/index.d.ts +5 -6
- package/dist/components/MultiSelect/index.d.ts.map +1 -1
- package/dist/components/MultiSelect/index.story.d.ts +7 -14
- package/dist/components/MultiSelect/index.story.d.ts.map +1 -1
- package/dist/components/Radio/index.d.ts +1 -1
- package/dist/components/Radio/index.d.ts.map +1 -1
- package/dist/components/Radio/index.story.d.ts +1 -2
- package/dist/components/Radio/index.story.d.ts.map +1 -1
- package/dist/components/SegmentedControl/RadioGroupContext.d.ts +1 -1
- package/dist/components/SegmentedControl/RadioGroupContext.d.ts.map +1 -1
- package/dist/components/SegmentedControl/index.d.ts +1 -1
- package/dist/components/SegmentedControl/index.d.ts.map +1 -1
- package/dist/components/SegmentedControl/index.story.d.ts +1 -2
- package/dist/components/SegmentedControl/index.story.d.ts.map +1 -1
- package/dist/components/Switch/index.d.ts +1 -1
- package/dist/components/Switch/index.d.ts.map +1 -1
- package/dist/components/TagItem/index.d.ts +3 -3
- package/dist/components/TagItem/index.d.ts.map +1 -1
- package/dist/components/TagItem/index.story.d.ts +2 -3
- package/dist/components/TagItem/index.story.d.ts.map +1 -1
- package/dist/components/TextArea/TextArea.story.d.ts +28 -0
- package/dist/components/TextArea/TextArea.story.d.ts.map +1 -0
- package/dist/components/TextArea/index.d.ts +28 -0
- package/dist/components/TextArea/index.d.ts.map +1 -0
- package/dist/components/TextField/TextField.story.d.ts +29 -0
- package/dist/components/TextField/TextField.story.d.ts.map +1 -0
- package/dist/components/TextField/index.d.ts +2 -1
- package/dist/components/TextField/index.d.ts.map +1 -1
- package/dist/components/TextField/index.story.d.ts +4 -5
- package/dist/components/TextField/index.story.d.ts.map +1 -1
- package/dist/core/CharcoalProvider.d.ts +1 -1
- package/dist/core/CharcoalProvider.d.ts.map +1 -1
- package/dist/core/ComponentAbstraction.d.ts +1 -1
- package/dist/core/ComponentAbstraction.d.ts.map +1 -1
- package/dist/index.cjs.js +744 -493
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +689 -452
- package/dist/index.esm.js.map +1 -1
- package/dist/styled.d.ts +13 -13
- package/dist/types/CustomJSXElement.d.ts +3 -0
- package/dist/types/CustomJSXElement.d.ts.map +1 -0
- package/package.json +7 -7
- package/src/_lib/compat.ts +1 -1
- package/src/components/Button/__snapshots__/index.test.tsx.snap +385 -0
- package/src/components/Button/index.story.tsx +1 -1
- package/src/components/Button/index.test.tsx +24 -0
- package/src/components/Button/index.tsx +2 -2
- package/src/components/Checkbox/index.story.tsx +0 -1
- package/src/components/Checkbox/index.tsx +2 -1
- package/src/components/Clickable/index.story.tsx +0 -1
- package/src/components/Clickable/index.tsx +1 -1
- package/src/components/DropdownSelector/Divider.tsx +3 -0
- package/src/components/DropdownSelector/DropdownMenuItem.tsx +40 -0
- package/src/components/DropdownSelector/DropdownPopover.tsx +21 -42
- package/src/components/DropdownSelector/ListItem/index.story.tsx +51 -0
- package/src/components/DropdownSelector/ListItem/index.tsx +58 -0
- package/src/components/DropdownSelector/MenuItem/index.tsx +32 -0
- package/src/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.tsx +43 -0
- package/src/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.tsx +55 -0
- package/src/components/DropdownSelector/MenuItemGroup/index.tsx +43 -0
- package/src/components/DropdownSelector/MenuList/MenuListContext.ts +17 -0
- package/src/components/DropdownSelector/MenuList/index.story.tsx +52 -0
- package/src/components/DropdownSelector/MenuList/index.tsx +51 -0
- package/src/components/DropdownSelector/MenuList/internals/getValuesRecursive.tsx +35 -0
- package/src/components/DropdownSelector/Popover/index.story.tsx +65 -0
- package/src/components/DropdownSelector/Popover/index.tsx +69 -0
- package/src/components/DropdownSelector/index.story.tsx +56 -21
- package/src/components/DropdownSelector/index.tsx +21 -64
- package/src/components/DropdownSelector/utils/findPreviewRecursive.tsx +38 -0
- package/src/components/FieldLabel/index.tsx +1 -1
- package/src/components/Icon/index.story.tsx +0 -1
- package/src/components/Icon/index.tsx +1 -1
- package/src/components/IconButton/index.story.tsx +0 -1
- package/src/components/IconButton/index.tsx +2 -2
- package/src/components/LoadingSpinner/index.story.tsx +1 -1
- package/src/components/LoadingSpinner/index.tsx +18 -19
- package/src/components/Modal/ModalPlumbing.tsx +0 -1
- package/src/components/Modal/index.story.tsx +0 -1
- package/src/components/Modal/index.tsx +2 -1
- package/src/components/MultiSelect/context.ts +2 -2
- package/src/components/MultiSelect/index.story.tsx +16 -29
- package/src/components/MultiSelect/index.test.tsx +5 -23
- package/src/components/MultiSelect/index.tsx +19 -24
- package/src/components/Radio/index.story.tsx +0 -1
- package/src/components/Radio/index.test.tsx +0 -1
- package/src/components/Radio/index.tsx +2 -1
- package/src/components/SegmentedControl/RadioGroupContext.tsx +2 -1
- package/src/components/SegmentedControl/index.story.tsx +0 -1
- package/src/components/SegmentedControl/index.tsx +10 -4
- package/src/components/Switch/index.story.tsx +1 -1
- package/src/components/Switch/index.tsx +2 -1
- package/src/components/TagItem/index.story.tsx +0 -1
- package/src/components/TagItem/index.tsx +1 -6
- package/src/components/TextField/index.story.tsx +0 -1
- package/src/components/TextField/index.tsx +2 -7
- package/src/components/a11y.test.tsx +0 -1
- package/src/core/CharcoalProvider.tsx +1 -1
- package/src/core/ComponentAbstraction.tsx +2 -1
- package/src/index.ts +7 -4
- package/src/components/DropdownSelector/OptionItem.tsx +0 -85
- package/src/components/DropdownSelector/utils/focusIfHTMLLIElement.tsx +0 -12
- package/src/components/DropdownSelector/utils/handleFocusByKeyBoard.tsx +0 -20
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from 'react'
|
|
2
2
|
import DropdownSelector, { DropdownSelectorProps } from '.'
|
|
3
3
|
import { Story } from '../../_lib/compat'
|
|
4
|
-
import {
|
|
4
|
+
import { Divider } from './Divider'
|
|
5
|
+
import MenuItemGroup from './MenuItemGroup'
|
|
6
|
+
import DropdownMenuItem from './DropdownMenuItem'
|
|
5
7
|
|
|
6
8
|
export default {
|
|
7
9
|
title: 'DropdownSelector',
|
|
8
10
|
component: DropdownSelector,
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
type Props = Omit<
|
|
12
|
-
DropdownSelectorProps,
|
|
13
|
-
'subLabel' | 'children' | 'onOpenChange'
|
|
14
|
-
>
|
|
15
|
-
|
|
16
13
|
const baseProps: DropdownSelectorProps = {
|
|
17
14
|
label: 'Label',
|
|
18
15
|
value: '',
|
|
@@ -20,9 +17,12 @@ const baseProps: DropdownSelectorProps = {
|
|
|
20
17
|
onChange: () => {
|
|
21
18
|
//
|
|
22
19
|
},
|
|
20
|
+
children: <DropdownMenuItem value="item" />,
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
export const Playground: Story<
|
|
23
|
+
export const Playground: Story<DropdownSelectorProps> = (
|
|
24
|
+
props: DropdownSelectorProps
|
|
25
|
+
) => {
|
|
26
26
|
const [selected, setSelected] = useState('50')
|
|
27
27
|
return (
|
|
28
28
|
<div style={{ width: 288 }}>
|
|
@@ -36,9 +36,9 @@ export const Playground: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
36
36
|
>
|
|
37
37
|
{[...(Array(100) as undefined[])].map((_, i) => {
|
|
38
38
|
return (
|
|
39
|
-
<
|
|
39
|
+
<DropdownMenuItem key={i} value={i.toString()}>
|
|
40
40
|
{i}
|
|
41
|
-
</
|
|
41
|
+
</DropdownMenuItem>
|
|
42
42
|
)
|
|
43
43
|
})}
|
|
44
44
|
</DropdownSelector>
|
|
@@ -48,7 +48,9 @@ export const Playground: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
48
48
|
|
|
49
49
|
Playground.args = { ...baseProps }
|
|
50
50
|
|
|
51
|
-
export const Basic: Story<
|
|
51
|
+
export const Basic: Story<DropdownSelectorProps> = (
|
|
52
|
+
props: DropdownSelectorProps
|
|
53
|
+
) => {
|
|
52
54
|
const [selected, setSelected] = useState('')
|
|
53
55
|
return (
|
|
54
56
|
<div style={{ width: 288 }}>
|
|
@@ -60,9 +62,9 @@ export const Basic: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
60
62
|
value={selected}
|
|
61
63
|
label="label"
|
|
62
64
|
>
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
<
|
|
65
|
+
<DropdownMenuItem value={'10'}>Apple</DropdownMenuItem>
|
|
66
|
+
<DropdownMenuItem value={'20'}>Banana</DropdownMenuItem>
|
|
67
|
+
<DropdownMenuItem value={'30'}>Orange</DropdownMenuItem>
|
|
66
68
|
</DropdownSelector>
|
|
67
69
|
</div>
|
|
68
70
|
)
|
|
@@ -70,7 +72,9 @@ export const Basic: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
70
72
|
|
|
71
73
|
Basic.args = { ...baseProps }
|
|
72
74
|
|
|
73
|
-
export const CustomChildren: Story<
|
|
75
|
+
export const CustomChildren: Story<DropdownSelectorProps> = (
|
|
76
|
+
props: DropdownSelectorProps
|
|
77
|
+
) => {
|
|
74
78
|
const [selected, setSelected] = useState('10')
|
|
75
79
|
return (
|
|
76
80
|
<div style={{ width: 288 }}>
|
|
@@ -82,7 +86,7 @@ export const CustomChildren: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
82
86
|
value={selected}
|
|
83
87
|
label="label"
|
|
84
88
|
>
|
|
85
|
-
<
|
|
89
|
+
<DropdownMenuItem value={'10'}>
|
|
86
90
|
<div
|
|
87
91
|
style={{
|
|
88
92
|
color: 'pink',
|
|
@@ -91,8 +95,8 @@ export const CustomChildren: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
91
95
|
>
|
|
92
96
|
Apple
|
|
93
97
|
</div>
|
|
94
|
-
</
|
|
95
|
-
<
|
|
98
|
+
</DropdownMenuItem>
|
|
99
|
+
<DropdownMenuItem value={'20'}>
|
|
96
100
|
<div
|
|
97
101
|
style={{
|
|
98
102
|
color: 'yellowgreen',
|
|
@@ -101,8 +105,8 @@ export const CustomChildren: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
101
105
|
>
|
|
102
106
|
Banana
|
|
103
107
|
</div>
|
|
104
|
-
</
|
|
105
|
-
<
|
|
108
|
+
</DropdownMenuItem>
|
|
109
|
+
<DropdownMenuItem value={'30'}>
|
|
106
110
|
<div
|
|
107
111
|
style={{
|
|
108
112
|
color: 'orange',
|
|
@@ -111,10 +115,41 @@ export const CustomChildren: Story<Props> = (props: DropdownSelectorProps) => {
|
|
|
111
115
|
>
|
|
112
116
|
Orange
|
|
113
117
|
</div>
|
|
114
|
-
</
|
|
118
|
+
</DropdownMenuItem>
|
|
115
119
|
</DropdownSelector>
|
|
116
120
|
</div>
|
|
117
121
|
)
|
|
118
122
|
}
|
|
119
123
|
|
|
120
124
|
CustomChildren.args = { ...baseProps }
|
|
125
|
+
|
|
126
|
+
export const SectionList: Story<DropdownSelectorProps> = (
|
|
127
|
+
props: DropdownSelectorProps
|
|
128
|
+
) => {
|
|
129
|
+
const [selected, setSelected] = useState('10')
|
|
130
|
+
return (
|
|
131
|
+
<div style={{ width: 288 }}>
|
|
132
|
+
<DropdownSelector
|
|
133
|
+
{...props}
|
|
134
|
+
onChange={(value) => {
|
|
135
|
+
setSelected(value)
|
|
136
|
+
}}
|
|
137
|
+
value={selected}
|
|
138
|
+
label="label"
|
|
139
|
+
>
|
|
140
|
+
<MenuItemGroup text="fruits">
|
|
141
|
+
<DropdownMenuItem value={'10'}>Apple</DropdownMenuItem>
|
|
142
|
+
<DropdownMenuItem value={'20'}>Banana</DropdownMenuItem>
|
|
143
|
+
<DropdownMenuItem value={'30'}>Orange</DropdownMenuItem>
|
|
144
|
+
</MenuItemGroup>
|
|
145
|
+
<Divider />
|
|
146
|
+
<MenuItemGroup text="vehicle">
|
|
147
|
+
<DropdownMenuItem value={'40'}>bicycle</DropdownMenuItem>
|
|
148
|
+
<DropdownMenuItem value={'50'}>car</DropdownMenuItem>
|
|
149
|
+
<DropdownMenuItem value={'60'}>train</DropdownMenuItem>
|
|
150
|
+
</MenuItemGroup>
|
|
151
|
+
</DropdownSelector>
|
|
152
|
+
</div>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
SectionList.args = { ...baseProps }
|
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReactNode, useState, useRef } from 'react'
|
|
2
2
|
import styled from 'styled-components'
|
|
3
|
-
import { useOverlayTriggerState } from 'react-stately'
|
|
4
3
|
import { disabledSelector } from '@charcoal-ui/utils'
|
|
5
4
|
import Icon from '../Icon'
|
|
6
5
|
import FieldLabel from '../FieldLabel'
|
|
7
6
|
import { theme } from '../../styled'
|
|
8
7
|
import { DropdownPopover } from './DropdownPopover'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
value: '',
|
|
12
|
-
setValue: (_v: string) => {
|
|
13
|
-
// empty
|
|
14
|
-
},
|
|
15
|
-
})
|
|
8
|
+
import { findPreviewRecursive } from './utils/findPreviewRecursive'
|
|
9
|
+
import MenuList, { MenuListChildren } from './MenuList'
|
|
16
10
|
|
|
17
11
|
export type DropdownSelectorProps = {
|
|
18
12
|
label: string
|
|
@@ -25,33 +19,16 @@ export type DropdownSelectorProps = {
|
|
|
25
19
|
required?: boolean
|
|
26
20
|
requiredText?: string
|
|
27
21
|
subLabel?: ReactNode
|
|
28
|
-
children
|
|
22
|
+
children: MenuListChildren
|
|
29
23
|
onChange: (value: string) => void
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
export type DropdownSelectorOption = {
|
|
33
|
-
label: string
|
|
34
|
-
id: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
26
|
const defaultRequiredText = '*必須'
|
|
38
27
|
|
|
39
28
|
export default function DropdownSelector(props: DropdownSelectorProps) {
|
|
40
29
|
const triggerRef = useRef<HTMLButtonElement>(null)
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
let preview: ReactNode | undefined
|
|
44
|
-
const childArray = React.Children.toArray(props.children)
|
|
45
|
-
for (let i = 0; i < childArray.length; i++) {
|
|
46
|
-
const child = childArray[i]
|
|
47
|
-
if (React.isValidElement(child) && 'value' in child.props) {
|
|
48
|
-
const find = (child.props as { value: string }).value === props.value
|
|
49
|
-
if (find && 'children' in child.props) {
|
|
50
|
-
preview = (child.props as { children: ReactNode }).children
|
|
51
|
-
break
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
30
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
31
|
+
const preview = findPreviewRecursive(props.children, props.value)
|
|
55
32
|
|
|
56
33
|
return (
|
|
57
34
|
<DropdownSelectorRoot aria-disabled={props.disabled}>
|
|
@@ -68,7 +45,7 @@ export default function DropdownSelector(props: DropdownSelectorProps) {
|
|
|
68
45
|
disabled={props.disabled}
|
|
69
46
|
onClick={() => {
|
|
70
47
|
if (props.disabled === true) return
|
|
71
|
-
|
|
48
|
+
setIsOpen(true)
|
|
72
49
|
}}
|
|
73
50
|
ref={triggerRef}
|
|
74
51
|
>
|
|
@@ -79,27 +56,22 @@ export default function DropdownSelector(props: DropdownSelectorProps) {
|
|
|
79
56
|
</DropdownButtonText>
|
|
80
57
|
<DropdownButtonIcon name="16/Menu" />
|
|
81
58
|
</DropdownButton>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
59
|
+
<DropdownPopover
|
|
60
|
+
isOpen={isOpen}
|
|
61
|
+
onClose={() => setIsOpen(false)}
|
|
62
|
+
triggerRef={triggerRef}
|
|
63
|
+
value={props.value}
|
|
64
|
+
>
|
|
65
|
+
<MenuList
|
|
86
66
|
value={props.value}
|
|
67
|
+
onChange={(v) => {
|
|
68
|
+
props.onChange(v)
|
|
69
|
+
setIsOpen(false)
|
|
70
|
+
}}
|
|
87
71
|
>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
value: props.value,
|
|
92
|
-
setValue: (v) => {
|
|
93
|
-
props.onChange(v)
|
|
94
|
-
state.close()
|
|
95
|
-
},
|
|
96
|
-
}}
|
|
97
|
-
>
|
|
98
|
-
{props.children}
|
|
99
|
-
</DropdownSelectorContext.Provider>
|
|
100
|
-
</ListboxRoot>
|
|
101
|
-
</DropdownPopover>
|
|
102
|
-
)}
|
|
72
|
+
{props.children}
|
|
73
|
+
</MenuList>
|
|
74
|
+
</DropdownPopover>
|
|
103
75
|
{props.assistiveText !== undefined && (
|
|
104
76
|
<AssertiveText invalid={props.invalid}>
|
|
105
77
|
{props.assistiveText}
|
|
@@ -109,21 +81,6 @@ export default function DropdownSelector(props: DropdownSelectorProps) {
|
|
|
109
81
|
)
|
|
110
82
|
}
|
|
111
83
|
|
|
112
|
-
const ListboxRoot = styled.ul`
|
|
113
|
-
padding-left: 0;
|
|
114
|
-
margin: 0;
|
|
115
|
-
box-sizing: border-box;
|
|
116
|
-
list-style: none;
|
|
117
|
-
overflow: auto;
|
|
118
|
-
max-height: inherit;
|
|
119
|
-
|
|
120
|
-
${theme((o) => [
|
|
121
|
-
o.bg.background1,
|
|
122
|
-
o.border.default,
|
|
123
|
-
o.borderRadius(8),
|
|
124
|
-
o.padding.vertical(8),
|
|
125
|
-
])}
|
|
126
|
-
`
|
|
127
84
|
const DropdownSelectorRoot = styled.div`
|
|
128
85
|
display: inline-block;
|
|
129
86
|
width: 100%;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* DropdownSelectorの選択中の要素をレンダリングするため、
|
|
5
|
+
* 選択中のMenuItemを再帰的に探索しReactNodeを返す。
|
|
6
|
+
*
|
|
7
|
+
* @param children
|
|
8
|
+
* @param value
|
|
9
|
+
* @param values
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export function findPreviewRecursive(
|
|
13
|
+
children: ReactNode,
|
|
14
|
+
value: string
|
|
15
|
+
): ReactNode | undefined {
|
|
16
|
+
const childArray = React.Children.toArray(children)
|
|
17
|
+
for (let i = 0; i < childArray.length; i++) {
|
|
18
|
+
const child = childArray[i]
|
|
19
|
+
if (React.isValidElement(child)) {
|
|
20
|
+
if ('value' in child.props) {
|
|
21
|
+
const childValue = (child.props as { value: string }).value
|
|
22
|
+
if (childValue === value && 'children' in child.props) {
|
|
23
|
+
const children = (child.props as { children: ReactNode }).children
|
|
24
|
+
return children
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if ('children' in child.props) {
|
|
28
|
+
const children = findPreviewRecursive(
|
|
29
|
+
(child.props as { children: ReactNode }).children,
|
|
30
|
+
value
|
|
31
|
+
)
|
|
32
|
+
if (children !== undefined) {
|
|
33
|
+
return children
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { forwardRef } from 'react'
|
|
2
2
|
import styled from 'styled-components'
|
|
3
3
|
import { theme } from '../../styled'
|
|
4
4
|
import Clickable, { ClickableElement, ClickableProps } from '../Clickable'
|
|
@@ -15,7 +15,7 @@ interface StyledProps {
|
|
|
15
15
|
|
|
16
16
|
export type IconButtonProps = StyledProps & ClickableProps
|
|
17
17
|
|
|
18
|
-
const IconButton =
|
|
18
|
+
const IconButton = forwardRef<ClickableElement, IconButtonProps>(
|
|
19
19
|
function IconButtonInner(
|
|
20
20
|
{ variant = 'Default', size = 'M', icon, ...rest }: IconButtonProps,
|
|
21
21
|
ref
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { forwardRef, useImperativeHandle, useRef } from 'react'
|
|
2
2
|
import styled, { keyframes } from 'styled-components'
|
|
3
3
|
import { theme } from '../../styled'
|
|
4
4
|
|
|
@@ -67,23 +67,22 @@ export interface LoadingSpinnerIconHandler {
|
|
|
67
67
|
restart(): void
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export const LoadingSpinnerIcon =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
>(function LoadingSpinnerIcon({ once = false }, ref) {
|
|
74
|
-
const iconRef = useRef<HTMLDivElement>(null)
|
|
70
|
+
export const LoadingSpinnerIcon = forwardRef<LoadingSpinnerIconHandler, Props>(
|
|
71
|
+
function LoadingSpinnerIcon({ once = false }, ref) {
|
|
72
|
+
const iconRef = useRef<HTMLDivElement>(null)
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
useImperativeHandle(ref, () => ({
|
|
75
|
+
restart: () => {
|
|
76
|
+
if (!iconRef.current) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
iconRef.current.dataset.resetAnimation = 'true'
|
|
80
|
+
// Force reflow hack!
|
|
81
|
+
void iconRef.current.offsetWidth
|
|
82
|
+
delete iconRef.current.dataset.resetAnimation
|
|
83
|
+
},
|
|
84
|
+
}))
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
}
|
|
86
|
+
return <Icon ref={iconRef} once={once} />
|
|
87
|
+
}
|
|
88
|
+
)
|
|
@@ -5,7 +5,7 @@ type MultiSelectGroupContext = {
|
|
|
5
5
|
selected: string[]
|
|
6
6
|
disabled: boolean
|
|
7
7
|
readonly: boolean
|
|
8
|
-
|
|
8
|
+
invalid: boolean
|
|
9
9
|
onChange: ({ value, selected }: { value: string; selected: boolean }) => void
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ export const MultiSelectGroupContext = createContext<MultiSelectGroupContext>({
|
|
|
14
14
|
selected: [],
|
|
15
15
|
disabled: false,
|
|
16
16
|
readonly: false,
|
|
17
|
-
|
|
17
|
+
invalid: false,
|
|
18
18
|
onChange() {
|
|
19
19
|
throw new Error(
|
|
20
20
|
'Cannot find `onChange()` handler. Perhaps you forgot to wrap it with `<MultiSelectGroup />` ?'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from 'react'
|
|
2
2
|
import { Story } from '../../_lib/compat'
|
|
3
3
|
import styled from 'styled-components'
|
|
4
4
|
import { MultiSelectGroup, default as MultiSelect } from '.'
|
|
@@ -12,7 +12,7 @@ export default {
|
|
|
12
12
|
type: 'text',
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
|
-
|
|
15
|
+
label: {
|
|
16
16
|
control: {
|
|
17
17
|
type: 'text',
|
|
18
18
|
},
|
|
@@ -22,11 +22,6 @@ export default {
|
|
|
22
22
|
type: 'boolean',
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
|
-
firstOptionForceChecked: {
|
|
26
|
-
control: {
|
|
27
|
-
type: 'boolean',
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
25
|
disabled: {
|
|
31
26
|
control: {
|
|
32
27
|
type: 'boolean',
|
|
@@ -37,7 +32,7 @@ export default {
|
|
|
37
32
|
type: 'boolean',
|
|
38
33
|
},
|
|
39
34
|
},
|
|
40
|
-
|
|
35
|
+
invalid: {
|
|
41
36
|
control: {
|
|
42
37
|
type: 'boolean',
|
|
43
38
|
},
|
|
@@ -53,13 +48,12 @@ export default {
|
|
|
53
48
|
|
|
54
49
|
type Props = {
|
|
55
50
|
name: string
|
|
56
|
-
|
|
51
|
+
label: string
|
|
57
52
|
selected: boolean
|
|
58
|
-
firstOptionForceChecked: boolean
|
|
59
53
|
onChange: (selected: string[]) => void
|
|
60
54
|
disabled?: boolean
|
|
61
55
|
readonly?: boolean
|
|
62
|
-
|
|
56
|
+
invalid?: boolean
|
|
63
57
|
variant?: 'default' | 'overlay'
|
|
64
58
|
}
|
|
65
59
|
|
|
@@ -71,35 +65,29 @@ const StyledMultiSelectGroup = styled(MultiSelectGroup)`
|
|
|
71
65
|
|
|
72
66
|
const Template: Story<Props> = ({
|
|
73
67
|
name,
|
|
74
|
-
|
|
68
|
+
label,
|
|
75
69
|
selected,
|
|
76
|
-
firstOptionForceChecked,
|
|
77
70
|
onChange,
|
|
78
71
|
disabled,
|
|
79
72
|
readonly,
|
|
80
|
-
|
|
73
|
+
invalid,
|
|
81
74
|
variant,
|
|
82
75
|
}) => {
|
|
83
76
|
return (
|
|
84
77
|
<StyledMultiSelectGroup
|
|
85
78
|
{...{
|
|
86
79
|
name,
|
|
87
|
-
|
|
80
|
+
label,
|
|
88
81
|
onChange,
|
|
89
82
|
disabled,
|
|
90
83
|
readonly,
|
|
91
|
-
|
|
84
|
+
invalid,
|
|
92
85
|
}}
|
|
93
86
|
className={''}
|
|
94
87
|
selected={selected ? ['選択肢1', '選択肢3'] : []}
|
|
95
88
|
>
|
|
96
89
|
{[1, 2, 3, 4].map((idx) => (
|
|
97
|
-
<MultiSelect
|
|
98
|
-
value={`選択肢${idx}`}
|
|
99
|
-
forceChecked={firstOptionForceChecked && idx === 1}
|
|
100
|
-
variant={variant}
|
|
101
|
-
key={idx}
|
|
102
|
-
>
|
|
90
|
+
<MultiSelect value={`選択肢${idx}`} variant={variant} key={idx}>
|
|
103
91
|
選択肢{idx}
|
|
104
92
|
</MultiSelect>
|
|
105
93
|
))}
|
|
@@ -110,12 +98,11 @@ const Template: Story<Props> = ({
|
|
|
110
98
|
export const Default = Template.bind({})
|
|
111
99
|
Default.args = {
|
|
112
100
|
name: '',
|
|
113
|
-
|
|
101
|
+
label: '',
|
|
114
102
|
selected: true,
|
|
115
|
-
firstOptionForceChecked: false,
|
|
116
103
|
disabled: false,
|
|
117
104
|
readonly: false,
|
|
118
|
-
|
|
105
|
+
invalid: false,
|
|
119
106
|
variant: 'default',
|
|
120
107
|
// eslint-disable-next-line no-console
|
|
121
108
|
onChange: (selected) => console.log(selected),
|
|
@@ -123,10 +110,10 @@ Default.args = {
|
|
|
123
110
|
|
|
124
111
|
type PlaygroundProps = {
|
|
125
112
|
name: string
|
|
126
|
-
|
|
113
|
+
label: string
|
|
127
114
|
disabled?: boolean
|
|
128
115
|
readonly?: boolean
|
|
129
|
-
|
|
116
|
+
invalid?: boolean
|
|
130
117
|
variant?: 'default' | 'overlay'
|
|
131
118
|
}
|
|
132
119
|
|
|
@@ -149,9 +136,9 @@ export const Playground: Story<PlaygroundProps> = (props) => {
|
|
|
149
136
|
}
|
|
150
137
|
Playground.args = {
|
|
151
138
|
name: 'defaultName',
|
|
152
|
-
|
|
139
|
+
label: '',
|
|
153
140
|
disabled: false,
|
|
154
141
|
readonly: false,
|
|
155
|
-
|
|
142
|
+
invalid: false,
|
|
156
143
|
variant: 'default',
|
|
157
144
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { fireEvent, render, screen } from '@testing-library/react'
|
|
2
|
-
import React from 'react'
|
|
3
2
|
import { ThemeProvider } from 'styled-components'
|
|
4
3
|
import { default as MultiSelect, MultiSelectGroup } from '.'
|
|
5
4
|
import { light } from '@charcoal-ui/theme'
|
|
@@ -184,7 +183,7 @@ describe('MultiSelect', () => {
|
|
|
184
183
|
let allOptions: HTMLInputElement[]
|
|
185
184
|
|
|
186
185
|
beforeEach(() => {
|
|
187
|
-
render(<TestComponent selected={['option1']}
|
|
186
|
+
render(<TestComponent selected={['option1']} invalid={true} />)
|
|
188
187
|
|
|
189
188
|
option1 = screen.getByDisplayValue('option1')
|
|
190
189
|
option2 = screen.getByDisplayValue('option2')
|
|
@@ -199,20 +198,6 @@ describe('MultiSelect', () => {
|
|
|
199
198
|
})
|
|
200
199
|
})
|
|
201
200
|
|
|
202
|
-
describe('option1 is force checked', () => {
|
|
203
|
-
let option1: HTMLInputElement
|
|
204
|
-
|
|
205
|
-
beforeEach(() => {
|
|
206
|
-
render(<TestComponent selected={[]} firstOptionForceChecked={true} />)
|
|
207
|
-
|
|
208
|
-
option1 = screen.getByDisplayValue('option1')
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
it('option1 is force checked', () => {
|
|
212
|
-
expect(option1.checked).toBeTruthy()
|
|
213
|
-
})
|
|
214
|
-
})
|
|
215
|
-
|
|
216
201
|
describe('option1 is disabled', () => {
|
|
217
202
|
let option1: HTMLInputElement
|
|
218
203
|
let option2: HTMLInputElement
|
|
@@ -239,8 +224,7 @@ const TestComponent = ({
|
|
|
239
224
|
childOnChange,
|
|
240
225
|
parentDisabled = false,
|
|
241
226
|
readonly = false,
|
|
242
|
-
|
|
243
|
-
firstOptionForceChecked = false,
|
|
227
|
+
invalid = false,
|
|
244
228
|
firstOptionDisabled = false,
|
|
245
229
|
}: {
|
|
246
230
|
selected: string[]
|
|
@@ -248,23 +232,21 @@ const TestComponent = ({
|
|
|
248
232
|
childOnChange?: (payload: { value: string; selected: boolean }) => void
|
|
249
233
|
parentDisabled?: boolean
|
|
250
234
|
readonly?: boolean
|
|
251
|
-
|
|
252
|
-
firstOptionForceChecked?: boolean
|
|
235
|
+
invalid?: boolean
|
|
253
236
|
firstOptionDisabled?: boolean
|
|
254
237
|
}) => {
|
|
255
238
|
return (
|
|
256
239
|
<ThemeProvider theme={light}>
|
|
257
240
|
<MultiSelectGroup
|
|
258
241
|
name="defaultName"
|
|
259
|
-
|
|
242
|
+
label="defaultAriaLabel"
|
|
260
243
|
disabled={parentDisabled}
|
|
261
244
|
onChange={parentOnChange}
|
|
262
|
-
{...{ selected, readonly,
|
|
245
|
+
{...{ selected, readonly, invalid }}
|
|
263
246
|
>
|
|
264
247
|
<MultiSelect
|
|
265
248
|
value="option1"
|
|
266
249
|
disabled={firstOptionDisabled}
|
|
267
|
-
forceChecked={firstOptionForceChecked}
|
|
268
250
|
onChange={childOnChange}
|
|
269
251
|
>
|
|
270
252
|
Option 1
|