@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.
Files changed (174) hide show
  1. package/dist/_lib/compat.d.ts +1 -1
  2. package/dist/_lib/compat.d.ts.map +1 -1
  3. package/dist/components/Button/index.d.ts +1 -2
  4. package/dist/components/Button/index.d.ts.map +1 -1
  5. package/dist/components/Button/index.story.d.ts +1 -2
  6. package/dist/components/Button/index.story.d.ts.map +1 -1
  7. package/dist/components/Button/index.test.d.ts +4 -0
  8. package/dist/components/Button/index.test.d.ts.map +1 -0
  9. package/dist/components/Checkbox/index.d.ts +1 -1
  10. package/dist/components/Checkbox/index.d.ts.map +1 -1
  11. package/dist/components/Checkbox/index.story.d.ts +1 -2
  12. package/dist/components/Checkbox/index.story.d.ts.map +1 -1
  13. package/dist/components/Clickable/index.d.ts +1 -1
  14. package/dist/components/Clickable/index.d.ts.map +1 -1
  15. package/dist/components/Clickable/index.story.d.ts +1 -2
  16. package/dist/components/Clickable/index.story.d.ts.map +1 -1
  17. package/dist/components/DropdownSelector/Divider.d.ts +3 -0
  18. package/dist/components/DropdownSelector/Divider.d.ts.map +1 -1
  19. package/dist/components/DropdownSelector/DropdownMenuItem.d.ts +7 -0
  20. package/dist/components/DropdownSelector/DropdownMenuItem.d.ts.map +1 -0
  21. package/dist/components/DropdownSelector/DropdownPopover.d.ts +8 -8
  22. package/dist/components/DropdownSelector/DropdownPopover.d.ts.map +1 -1
  23. package/dist/components/DropdownSelector/ListItem/index.d.ts +18 -0
  24. package/dist/components/DropdownSelector/ListItem/index.d.ts.map +1 -0
  25. package/dist/components/DropdownSelector/ListItem/index.story.d.ts +9 -0
  26. package/dist/components/DropdownSelector/ListItem/index.story.d.ts.map +1 -0
  27. package/dist/components/DropdownSelector/MenuItem/index.d.ts +11 -0
  28. package/dist/components/DropdownSelector/MenuItem/index.d.ts.map +1 -0
  29. package/dist/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.d.ts +9 -0
  30. package/dist/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.d.ts.map +1 -0
  31. package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.d.ts +10 -0
  32. package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.d.ts.map +1 -0
  33. package/dist/components/DropdownSelector/MenuItemGroup/index.d.ts +14 -0
  34. package/dist/components/DropdownSelector/MenuItemGroup/index.d.ts.map +1 -0
  35. package/dist/components/DropdownSelector/MenuList/MenuListContext.d.ts +10 -0
  36. package/dist/components/DropdownSelector/MenuList/MenuListContext.d.ts.map +1 -0
  37. package/dist/components/DropdownSelector/MenuList/index.d.ts +18 -0
  38. package/dist/components/DropdownSelector/MenuList/index.d.ts.map +1 -0
  39. package/dist/components/DropdownSelector/MenuList/index.story.d.ts +11 -0
  40. package/dist/components/DropdownSelector/MenuList/index.story.d.ts.map +1 -0
  41. package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.d.ts +11 -0
  42. package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.d.ts.map +1 -0
  43. package/dist/components/DropdownSelector/Popover/index.d.ts +17 -0
  44. package/dist/components/DropdownSelector/Popover/index.d.ts.map +1 -0
  45. package/dist/components/DropdownSelector/Popover/index.story.d.ts +9 -0
  46. package/dist/components/DropdownSelector/Popover/index.story.d.ts.map +1 -0
  47. package/dist/components/DropdownSelector/index.d.ts +3 -10
  48. package/dist/components/DropdownSelector/index.d.ts.map +1 -1
  49. package/dist/components/DropdownSelector/index.story.d.ts +4 -4
  50. package/dist/components/DropdownSelector/index.story.d.ts.map +1 -1
  51. package/dist/components/DropdownSelector/utils/findPreviewRecursive.d.ts +12 -0
  52. package/dist/components/DropdownSelector/utils/findPreviewRecursive.d.ts.map +1 -0
  53. package/dist/components/FieldLabel/index.d.ts +1 -1
  54. package/dist/components/FieldLabel/index.d.ts.map +1 -1
  55. package/dist/components/Icon/index.d.ts +1 -1
  56. package/dist/components/Icon/index.d.ts.map +1 -1
  57. package/dist/components/Icon/index.story.d.ts +2 -3
  58. package/dist/components/Icon/index.story.d.ts.map +1 -1
  59. package/dist/components/IconButton/index.d.ts +1 -2
  60. package/dist/components/IconButton/index.d.ts.map +1 -1
  61. package/dist/components/IconButton/index.story.d.ts +1 -2
  62. package/dist/components/IconButton/index.story.d.ts.map +1 -1
  63. package/dist/components/LoadingSpinner/index.d.ts +1 -2
  64. package/dist/components/LoadingSpinner/index.d.ts.map +1 -1
  65. package/dist/components/Modal/ModalPlumbing.d.ts.map +1 -1
  66. package/dist/components/Modal/index.d.ts +1 -1
  67. package/dist/components/Modal/index.d.ts.map +1 -1
  68. package/dist/components/Modal/index.story.d.ts.map +1 -1
  69. package/dist/components/MultiSelect/context.d.ts +1 -1
  70. package/dist/components/MultiSelect/context.d.ts.map +1 -1
  71. package/dist/components/MultiSelect/index.d.ts +5 -6
  72. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  73. package/dist/components/MultiSelect/index.story.d.ts +7 -14
  74. package/dist/components/MultiSelect/index.story.d.ts.map +1 -1
  75. package/dist/components/Radio/index.d.ts +1 -1
  76. package/dist/components/Radio/index.d.ts.map +1 -1
  77. package/dist/components/Radio/index.story.d.ts +1 -2
  78. package/dist/components/Radio/index.story.d.ts.map +1 -1
  79. package/dist/components/SegmentedControl/RadioGroupContext.d.ts +1 -1
  80. package/dist/components/SegmentedControl/RadioGroupContext.d.ts.map +1 -1
  81. package/dist/components/SegmentedControl/index.d.ts +1 -1
  82. package/dist/components/SegmentedControl/index.d.ts.map +1 -1
  83. package/dist/components/SegmentedControl/index.story.d.ts +1 -2
  84. package/dist/components/SegmentedControl/index.story.d.ts.map +1 -1
  85. package/dist/components/Switch/index.d.ts +1 -1
  86. package/dist/components/Switch/index.d.ts.map +1 -1
  87. package/dist/components/TagItem/index.d.ts +3 -3
  88. package/dist/components/TagItem/index.d.ts.map +1 -1
  89. package/dist/components/TagItem/index.story.d.ts +2 -3
  90. package/dist/components/TagItem/index.story.d.ts.map +1 -1
  91. package/dist/components/TextArea/TextArea.story.d.ts +28 -0
  92. package/dist/components/TextArea/TextArea.story.d.ts.map +1 -0
  93. package/dist/components/TextArea/index.d.ts +28 -0
  94. package/dist/components/TextArea/index.d.ts.map +1 -0
  95. package/dist/components/TextField/TextField.story.d.ts +29 -0
  96. package/dist/components/TextField/TextField.story.d.ts.map +1 -0
  97. package/dist/components/TextField/index.d.ts +2 -1
  98. package/dist/components/TextField/index.d.ts.map +1 -1
  99. package/dist/components/TextField/index.story.d.ts +4 -5
  100. package/dist/components/TextField/index.story.d.ts.map +1 -1
  101. package/dist/core/CharcoalProvider.d.ts +1 -1
  102. package/dist/core/CharcoalProvider.d.ts.map +1 -1
  103. package/dist/core/ComponentAbstraction.d.ts +1 -1
  104. package/dist/core/ComponentAbstraction.d.ts.map +1 -1
  105. package/dist/index.cjs.js +744 -493
  106. package/dist/index.cjs.js.map +1 -1
  107. package/dist/index.d.ts +3 -2
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.esm.js +689 -452
  110. package/dist/index.esm.js.map +1 -1
  111. package/dist/styled.d.ts +13 -13
  112. package/dist/types/CustomJSXElement.d.ts +3 -0
  113. package/dist/types/CustomJSXElement.d.ts.map +1 -0
  114. package/package.json +7 -7
  115. package/src/_lib/compat.ts +1 -1
  116. package/src/components/Button/__snapshots__/index.test.tsx.snap +385 -0
  117. package/src/components/Button/index.story.tsx +1 -1
  118. package/src/components/Button/index.test.tsx +24 -0
  119. package/src/components/Button/index.tsx +2 -2
  120. package/src/components/Checkbox/index.story.tsx +0 -1
  121. package/src/components/Checkbox/index.tsx +2 -1
  122. package/src/components/Clickable/index.story.tsx +0 -1
  123. package/src/components/Clickable/index.tsx +1 -1
  124. package/src/components/DropdownSelector/Divider.tsx +3 -0
  125. package/src/components/DropdownSelector/DropdownMenuItem.tsx +40 -0
  126. package/src/components/DropdownSelector/DropdownPopover.tsx +21 -42
  127. package/src/components/DropdownSelector/ListItem/index.story.tsx +51 -0
  128. package/src/components/DropdownSelector/ListItem/index.tsx +58 -0
  129. package/src/components/DropdownSelector/MenuItem/index.tsx +32 -0
  130. package/src/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.tsx +43 -0
  131. package/src/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.tsx +55 -0
  132. package/src/components/DropdownSelector/MenuItemGroup/index.tsx +43 -0
  133. package/src/components/DropdownSelector/MenuList/MenuListContext.ts +17 -0
  134. package/src/components/DropdownSelector/MenuList/index.story.tsx +52 -0
  135. package/src/components/DropdownSelector/MenuList/index.tsx +51 -0
  136. package/src/components/DropdownSelector/MenuList/internals/getValuesRecursive.tsx +35 -0
  137. package/src/components/DropdownSelector/Popover/index.story.tsx +65 -0
  138. package/src/components/DropdownSelector/Popover/index.tsx +69 -0
  139. package/src/components/DropdownSelector/index.story.tsx +56 -21
  140. package/src/components/DropdownSelector/index.tsx +21 -64
  141. package/src/components/DropdownSelector/utils/findPreviewRecursive.tsx +38 -0
  142. package/src/components/FieldLabel/index.tsx +1 -1
  143. package/src/components/Icon/index.story.tsx +0 -1
  144. package/src/components/Icon/index.tsx +1 -1
  145. package/src/components/IconButton/index.story.tsx +0 -1
  146. package/src/components/IconButton/index.tsx +2 -2
  147. package/src/components/LoadingSpinner/index.story.tsx +1 -1
  148. package/src/components/LoadingSpinner/index.tsx +18 -19
  149. package/src/components/Modal/ModalPlumbing.tsx +0 -1
  150. package/src/components/Modal/index.story.tsx +0 -1
  151. package/src/components/Modal/index.tsx +2 -1
  152. package/src/components/MultiSelect/context.ts +2 -2
  153. package/src/components/MultiSelect/index.story.tsx +16 -29
  154. package/src/components/MultiSelect/index.test.tsx +5 -23
  155. package/src/components/MultiSelect/index.tsx +19 -24
  156. package/src/components/Radio/index.story.tsx +0 -1
  157. package/src/components/Radio/index.test.tsx +0 -1
  158. package/src/components/Radio/index.tsx +2 -1
  159. package/src/components/SegmentedControl/RadioGroupContext.tsx +2 -1
  160. package/src/components/SegmentedControl/index.story.tsx +0 -1
  161. package/src/components/SegmentedControl/index.tsx +10 -4
  162. package/src/components/Switch/index.story.tsx +1 -1
  163. package/src/components/Switch/index.tsx +2 -1
  164. package/src/components/TagItem/index.story.tsx +0 -1
  165. package/src/components/TagItem/index.tsx +1 -6
  166. package/src/components/TextField/index.story.tsx +0 -1
  167. package/src/components/TextField/index.tsx +2 -7
  168. package/src/components/a11y.test.tsx +0 -1
  169. package/src/core/CharcoalProvider.tsx +1 -1
  170. package/src/core/ComponentAbstraction.tsx +2 -1
  171. package/src/index.ts +7 -4
  172. package/src/components/DropdownSelector/OptionItem.tsx +0 -85
  173. package/src/components/DropdownSelector/utils/focusIfHTMLLIElement.tsx +0 -12
  174. package/src/components/DropdownSelector/utils/handleFocusByKeyBoard.tsx +0 -20
@@ -1,18 +1,15 @@
1
- import React, { useState } from 'react'
1
+ import { useState } from 'react'
2
2
  import DropdownSelector, { DropdownSelectorProps } from '.'
3
3
  import { Story } from '../../_lib/compat'
4
- import { OptionItem } from './OptionItem'
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<Props> = (props: DropdownSelectorProps) => {
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
- <OptionItem key={i} value={i.toString()}>
39
+ <DropdownMenuItem key={i} value={i.toString()}>
40
40
  {i}
41
- </OptionItem>
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<Props> = (props: DropdownSelectorProps) => {
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
- <OptionItem value={'10'}>Apple</OptionItem>
64
- <OptionItem value={'20'}>Banana</OptionItem>
65
- <OptionItem value={'30'}>Orange</OptionItem>
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<Props> = (props: DropdownSelectorProps) => {
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
- <OptionItem value={'10'}>
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
- </OptionItem>
95
- <OptionItem value={'20'}>
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
- </OptionItem>
105
- <OptionItem value={'30'}>
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
- </OptionItem>
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 React, { ReactNode, createContext, useRef } from 'react'
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
- export const DropdownSelectorContext = createContext({
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?: ReactNode
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 state = useOverlayTriggerState({})
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
- state.open()
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
- {state.isOpen && (
83
- <DropdownPopover
84
- state={state}
85
- triggerRef={triggerRef}
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
- <ListboxRoot>
89
- <DropdownSelectorContext.Provider
90
- value={{
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 React from 'react'
1
+ import * as React from 'react'
2
2
  import styled from 'styled-components'
3
3
  import { createTheme } from '@charcoal-ui/styled'
4
4
 
@@ -1,4 +1,3 @@
1
- import React from 'react'
2
1
  import Icon, { IconProps } from '.'
3
2
  import { KNOWN_ICON_FILES } from '@charcoal-ui/icons'
4
3
  import { Story } from '../../_lib/compat'
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import * as React from 'react'
2
2
 
3
3
  import '@charcoal-ui/icons'
4
4
  import type { PixivIcon, Props } from '@charcoal-ui/icons'
@@ -1,4 +1,3 @@
1
- import React from 'react'
2
1
  import type { Story } from '../../_lib/compat'
3
2
  import '@charcoal-ui/icons'
4
3
  import IconButton from '.'
@@ -1,4 +1,4 @@
1
- import React from 'react'
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 = React.forwardRef<ClickableElement, IconButtonProps>(
18
+ const IconButton = forwardRef<ClickableElement, IconButtonProps>(
19
19
  function IconButtonInner(
20
20
  { variant = 'Default', size = 'M', icon, ...rest }: IconButtonProps,
21
21
  ref
@@ -5,7 +5,7 @@ import {
5
5
  text,
6
6
  withKnobs,
7
7
  } from '@storybook/addon-knobs'
8
- import React, { useRef } from 'react'
8
+ import { useRef } from 'react'
9
9
  import LoadingSpinner, {
10
10
  LoadingSpinnerIcon,
11
11
  LoadingSpinnerIconHandler,
@@ -1,4 +1,4 @@
1
- import React, { useImperativeHandle, useRef } from 'react'
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 = React.forwardRef<
71
- LoadingSpinnerIconHandler,
72
- Props
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
- useImperativeHandle(ref, () => ({
77
- restart: () => {
78
- if (!iconRef.current) {
79
- return
80
- }
81
- iconRef.current.dataset.resetAnimation = 'true'
82
- // Force reflow hack!
83
- void iconRef.current.offsetWidth
84
- delete iconRef.current.dataset.resetAnimation
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
- return <Icon ref={iconRef} once={once} />
89
- })
86
+ return <Icon ref={iconRef} once={once} />
87
+ }
88
+ )
@@ -1,4 +1,3 @@
1
- import React from 'react'
2
1
  import { ModalTitle } from '.'
3
2
  import styled from 'styled-components'
4
3
  import { theme } from '../../styled'
@@ -1,4 +1,3 @@
1
- import React from 'react'
2
1
  import { Story } from '../../_lib/compat'
3
2
  import Modal, { ModalDismissButton, ModalProps } from '.'
4
3
  import { OverlayProvider } from '@react-aria/overlays'
@@ -1,4 +1,5 @@
1
- import React, { useContext, useRef } from 'react'
1
+ import { useContext, useRef } from 'react'
2
+ import * as React from 'react'
2
3
  import {
3
4
  AriaModalOverlayProps,
4
5
  Overlay,
@@ -5,7 +5,7 @@ type MultiSelectGroupContext = {
5
5
  selected: string[]
6
6
  disabled: boolean
7
7
  readonly: boolean
8
- hasError: boolean
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
- hasError: false,
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 React, { useState } from 'react'
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
- ariaLabel: {
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
- hasError: {
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
- ariaLabel: string
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
- hasError?: boolean
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
- ariaLabel,
68
+ label,
75
69
  selected,
76
- firstOptionForceChecked,
77
70
  onChange,
78
71
  disabled,
79
72
  readonly,
80
- hasError,
73
+ invalid,
81
74
  variant,
82
75
  }) => {
83
76
  return (
84
77
  <StyledMultiSelectGroup
85
78
  {...{
86
79
  name,
87
- ariaLabel,
80
+ label,
88
81
  onChange,
89
82
  disabled,
90
83
  readonly,
91
- hasError,
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
- ariaLabel: '',
101
+ label: '',
114
102
  selected: true,
115
- firstOptionForceChecked: false,
116
103
  disabled: false,
117
104
  readonly: false,
118
- hasError: false,
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
- ariaLabel: string
113
+ label: string
127
114
  disabled?: boolean
128
115
  readonly?: boolean
129
- hasError?: boolean
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
- ariaLabel: '',
139
+ label: '',
153
140
  disabled: false,
154
141
  readonly: false,
155
- hasError: false,
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']} hasError={true} />)
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
- hasError = false,
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
- hasError?: boolean
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
- ariaLabel="defaultAriaLabel"
242
+ label="defaultAriaLabel"
260
243
  disabled={parentDisabled}
261
244
  onChange={parentOnChange}
262
- {...{ selected, readonly, hasError }}
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