@charcoal-ui/react 3.0.0-beta.1 → 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 (176) 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 +6 -3
  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 +794 -518
  106. package/dist/index.cjs.js.map +1 -1
  107. package/dist/index.d.ts +4 -3
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.esm.js +739 -477
  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 +19 -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 +81 -62
  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 +4 -1
  159. package/src/components/SegmentedControl/RadioGroupContext.tsx +2 -1
  160. package/src/components/SegmentedControl/index.story.tsx +2 -1
  161. package/src/components/SegmentedControl/index.tsx +11 -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 +3 -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 +8 -5
  172. package/dist/components/DropdownSelector/OptionLi.d.ts +0 -11
  173. package/dist/components/DropdownSelector/OptionLi.d.ts.map +0 -1
  174. package/src/components/DropdownSelector/OptionItem.tsx +0 -85
  175. package/src/components/DropdownSelector/utils/focusIfHTMLLIElement.tsx +0 -12
  176. 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
 
@@ -19,6 +19,7 @@ const LoadingSpinnerRoot = styled.div.attrs({ role: 'progressbar' })<{
19
19
  padding: number
20
20
  transparent: boolean
21
21
  }>`
22
+ box-sizing: content-box;
22
23
  margin: auto;
23
24
  padding: ${(props) => props.padding}px;
24
25
  border-radius: 8px;
@@ -66,23 +67,22 @@ export interface LoadingSpinnerIconHandler {
66
67
  restart(): void
67
68
  }
68
69
 
69
- export const LoadingSpinnerIcon = React.forwardRef<
70
- LoadingSpinnerIconHandler,
71
- Props
72
- >(function LoadingSpinnerIcon({ once = false }, ref) {
73
- const iconRef = useRef<HTMLDivElement>(null)
70
+ export const LoadingSpinnerIcon = forwardRef<LoadingSpinnerIconHandler, Props>(
71
+ function LoadingSpinnerIcon({ once = false }, ref) {
72
+ const iconRef = useRef<HTMLDivElement>(null)
74
73
 
75
- useImperativeHandle(ref, () => ({
76
- restart: () => {
77
- if (!iconRef.current) {
78
- return
79
- }
80
- iconRef.current.dataset.resetAnimation = 'true'
81
- // Force reflow hack!
82
- void iconRef.current.offsetWidth
83
- delete iconRef.current.dataset.resetAnimation
84
- },
85
- }))
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
+ }))
86
85
 
87
- return <Icon ref={iconRef} once={once} />
88
- })
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,
@@ -18,13 +19,16 @@ import { animated, useTransition, easings } from 'react-spring'
18
19
  import Button, { ButtonProps } from '../Button'
19
20
  import IconButton from '../IconButton'
20
21
 
22
+ type BottomSheet = boolean | 'full'
23
+ type Size = 'S' | 'M' | 'L'
24
+
21
25
  export type ModalProps = AriaModalOverlayProps &
22
26
  AriaDialogProps & {
23
27
  children: React.ReactNode
24
28
  zIndex?: number
25
29
  title: string
26
- size?: 'S' | 'M' | 'L'
27
- bottomSheet?: boolean | 'full'
30
+ size?: Size
31
+ bottomSheet?: BottomSheet
28
32
  isOpen: boolean
29
33
  onClose: () => void
30
34
 
@@ -133,28 +137,30 @@ export default function Modal({
133
137
  style={transitionEnabled ? { backgroundColor } : {}}
134
138
  >
135
139
  <FocusScope contain restoreFocus autoFocus>
136
- <ModalDialog
137
- ref={ref}
138
- {...overlayProps}
139
- {...modalProps}
140
- {...dialogProps}
141
- style={transitionEnabled ? { transform } : {}}
142
- size={size}
143
- bottomSheet={bottomSheet}
144
- >
145
- <ModalContext.Provider
146
- value={{ titleProps, title, close: onClose, showDismiss }}
140
+ <DialogContainer bottomSheet={bottomSheet} size={size}>
141
+ <ModalDialog
142
+ ref={ref}
143
+ {...overlayProps}
144
+ {...modalProps}
145
+ {...dialogProps}
146
+ style={transitionEnabled ? { transform } : {}}
147
+ size={size}
148
+ bottomSheet={bottomSheet}
147
149
  >
148
- {children}
149
- {isDismissable === true && (
150
- <ModalCrossButton
151
- size="S"
152
- icon="24/Close"
153
- onClick={onClose}
154
- />
155
- )}
156
- </ModalContext.Provider>
157
- </ModalDialog>
150
+ <ModalContext.Provider
151
+ value={{ titleProps, title, close: onClose, showDismiss }}
152
+ >
153
+ {children}
154
+ {isDismissable === true && (
155
+ <ModalCrossButton
156
+ size="S"
157
+ icon="24/Close"
158
+ onClick={onClose}
159
+ />
160
+ )}
161
+ </ModalContext.Provider>
162
+ </ModalDialog>
163
+ </DialogContainer>
158
164
  </FocusScope>
159
165
  </ModalBackground>
160
166
  </Overlay>
@@ -176,6 +182,8 @@ const ModalContext = React.createContext<{
176
182
 
177
183
  const ModalBackground = animated(styled.div<{ zIndex: number }>`
178
184
  z-index: ${({ zIndex }) => zIndex};
185
+ overflow: scroll;
186
+ display: flex;
179
187
  position: fixed;
180
188
  top: 0;
181
189
  left: 0;
@@ -185,50 +193,61 @@ const ModalBackground = animated(styled.div<{ zIndex: number }>`
185
193
  ${theme((o) => [o.bg.surface4])}
186
194
  `)
187
195
 
196
+ const DialogContainer = styled.div<{ bottomSheet: BottomSheet; size: Size }>`
197
+ position: relative;
198
+ margin: auto;
199
+ padding: 24px 0;
200
+ width: ${(p) => {
201
+ switch (p.size) {
202
+ case 'S': {
203
+ return columnSystem(3, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
204
+ }
205
+ case 'M': {
206
+ return columnSystem(4, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
207
+ }
208
+ case 'L': {
209
+ return columnSystem(6, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
210
+ }
211
+ default: {
212
+ return unreachable(p.size)
213
+ }
214
+ }
215
+ }}px;
216
+
217
+ @media ${({ theme }) => maxWidth(theme.breakpoint.screen1)} {
218
+ width: calc(100% - 48px);
219
+ ${(p) =>
220
+ p.bottomSheet !== false &&
221
+ css`
222
+ margin: 0;
223
+ padding: 0;
224
+ bottom: 0;
225
+ position: absolute;
226
+ width: 100%;
227
+ ${p.bottomSheet === 'full' ? 'height: 100%' : ''};
228
+ `}
229
+ }
230
+ `
231
+
188
232
  const ModalDialog = animated(styled.div<{
189
- size: 'S' | 'M' | 'L'
190
- bottomSheet: boolean | 'full'
233
+ size: Size
234
+ bottomSheet: BottomSheet
191
235
  }>`
192
- position: absolute;
193
- top: 50%;
194
- left: 50%;
195
- transform: translate(-50%, -50%);
196
- width: ${(p) =>
197
- p.size === 'S'
198
- ? columnSystem(3, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
199
- : p.size === 'M'
200
- ? columnSystem(4, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
201
- : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
202
- p.size === 'L'
203
- ? columnSystem(6, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
204
- : unreachable(p.size)}px;
236
+ position: relative;
237
+ margin: auto;
238
+ padding: 24px 0;
205
239
 
206
240
  ${theme((o) => [o.bg.background1, o.borderRadius(24)])}
207
-
208
241
  @media ${({ theme }) => maxWidth(theme.breakpoint.screen1)} {
209
242
  ${(p) =>
210
- p.bottomSheet === 'full'
211
- ? css`
212
- top: auto;
213
- bottom: 0;
214
- left: 0;
215
- transform: none;
216
- border-radius: 0;
217
- width: 100%;
218
- height: 100%;
219
- `
220
- : p.bottomSheet
221
- ? css`
222
- top: auto;
223
- bottom: 0;
224
- left: 0;
225
- transform: none;
226
- border-radius: 0;
227
- width: 100%;
228
- `
229
- : css`
230
- width: calc(100% - 48px);
231
- `}
243
+ p.bottomSheet !== false &&
244
+ css`
245
+ border-radius: 0;
246
+ ${p.bottomSheet === 'full' &&
247
+ css`
248
+ height: 100%;
249
+ `}
250
+ `}
232
251
  }
233
252
  `)
234
253
 
@@ -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 />` ?'