@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,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ChangeEvent, useCallback, useContext } from 'react'
|
|
2
|
+
import * as React from 'react'
|
|
2
3
|
import styled, { css } from 'styled-components'
|
|
3
4
|
import warning from 'warning'
|
|
4
5
|
import { theme } from '../../styled'
|
|
@@ -8,7 +9,6 @@ import { MultiSelectGroupContext } from './context'
|
|
|
8
9
|
|
|
9
10
|
export type MultiSelectProps = React.PropsWithChildren<{
|
|
10
11
|
value: string
|
|
11
|
-
forceChecked?: boolean
|
|
12
12
|
disabled?: boolean
|
|
13
13
|
variant?: 'default' | 'overlay'
|
|
14
14
|
onChange?: (payload: { value: string; selected: boolean }) => void
|
|
@@ -16,7 +16,6 @@ export type MultiSelectProps = React.PropsWithChildren<{
|
|
|
16
16
|
|
|
17
17
|
export default function MultiSelect({
|
|
18
18
|
value,
|
|
19
|
-
forceChecked = false,
|
|
20
19
|
disabled = false,
|
|
21
20
|
onChange,
|
|
22
21
|
variant = 'default',
|
|
@@ -27,7 +26,7 @@ export default function MultiSelect({
|
|
|
27
26
|
selected,
|
|
28
27
|
disabled: parentDisabled,
|
|
29
28
|
readonly,
|
|
30
|
-
|
|
29
|
+
invalid,
|
|
31
30
|
onChange: parentOnChange,
|
|
32
31
|
} = useContext(MultiSelectGroupContext)
|
|
33
32
|
|
|
@@ -37,7 +36,7 @@ export default function MultiSelect({
|
|
|
37
36
|
`"name" is not Provided for <MultiSelect>. Perhaps you forgot to wrap with <MultiSelectGroup> ?`
|
|
38
37
|
)
|
|
39
38
|
|
|
40
|
-
const isSelected = selected.includes(value)
|
|
39
|
+
const isSelected = selected.includes(value)
|
|
41
40
|
const isDisabled = disabled || parentDisabled || readonly
|
|
42
41
|
|
|
43
42
|
const handleChange = useCallback(
|
|
@@ -57,17 +56,17 @@ export default function MultiSelect({
|
|
|
57
56
|
{...{
|
|
58
57
|
name,
|
|
59
58
|
value,
|
|
60
|
-
|
|
59
|
+
invalid,
|
|
61
60
|
}}
|
|
62
61
|
checked={isSelected}
|
|
63
62
|
disabled={isDisabled}
|
|
64
63
|
onChange={handleChange}
|
|
65
64
|
overlay={variant === 'overlay'}
|
|
66
|
-
aria-invalid={
|
|
65
|
+
aria-invalid={invalid}
|
|
67
66
|
/>
|
|
68
67
|
<MultiSelectInputOverlay
|
|
69
68
|
overlay={variant === 'overlay'}
|
|
70
|
-
|
|
69
|
+
invalid={invalid}
|
|
71
70
|
aria-hidden={true}
|
|
72
71
|
>
|
|
73
72
|
<pixiv-icon name="24/Check" unsafe-non-guideline-scale={16 / 24} />
|
|
@@ -97,7 +96,7 @@ const MultiSelectLabel = styled.div`
|
|
|
97
96
|
`
|
|
98
97
|
|
|
99
98
|
const MultiSelectInput = styled.input.attrs({ type: 'checkbox' })<{
|
|
100
|
-
|
|
99
|
+
invalid: boolean
|
|
101
100
|
overlay: boolean
|
|
102
101
|
}>`
|
|
103
102
|
&[type='checkbox'] {
|
|
@@ -111,11 +110,11 @@ const MultiSelectInput = styled.input.attrs({ type: 'checkbox' })<{
|
|
|
111
110
|
${theme((o) => o.bg.brand.hover.press)}
|
|
112
111
|
}
|
|
113
112
|
|
|
114
|
-
${({
|
|
113
|
+
${({ invalid, overlay }) =>
|
|
115
114
|
theme((o) => [
|
|
116
115
|
o.bg.text3.hover.press,
|
|
117
116
|
o.borderRadius('oval'),
|
|
118
|
-
|
|
117
|
+
invalid && !overlay && o.outline.assertive,
|
|
119
118
|
overlay && o.bg.surface4,
|
|
120
119
|
])};
|
|
121
120
|
}
|
|
@@ -123,7 +122,7 @@ const MultiSelectInput = styled.input.attrs({ type: 'checkbox' })<{
|
|
|
123
122
|
|
|
124
123
|
const MultiSelectInputOverlay = styled.div<{
|
|
125
124
|
overlay: boolean
|
|
126
|
-
|
|
125
|
+
invalid: boolean
|
|
127
126
|
}>`
|
|
128
127
|
position: absolute;
|
|
129
128
|
top: -2px;
|
|
@@ -133,13 +132,13 @@ const MultiSelectInputOverlay = styled.div<{
|
|
|
133
132
|
align-items: center;
|
|
134
133
|
justify-content: center;
|
|
135
134
|
|
|
136
|
-
${({
|
|
135
|
+
${({ invalid, overlay }) =>
|
|
137
136
|
theme((o) => [
|
|
138
137
|
o.width.px(24),
|
|
139
138
|
o.height.px(24),
|
|
140
139
|
o.borderRadius('oval'),
|
|
141
140
|
o.font.text5,
|
|
142
|
-
|
|
141
|
+
invalid && overlay && o.outline.assertive,
|
|
143
142
|
])}
|
|
144
143
|
|
|
145
144
|
${({ overlay }) =>
|
|
@@ -154,23 +153,23 @@ const MultiSelectInputOverlay = styled.div<{
|
|
|
154
153
|
export type MultiSelectGroupProps = React.PropsWithChildren<{
|
|
155
154
|
className?: string
|
|
156
155
|
name: string
|
|
157
|
-
|
|
156
|
+
label: string
|
|
158
157
|
selected: string[]
|
|
159
158
|
onChange: (selected: string[]) => void
|
|
160
159
|
disabled?: boolean
|
|
161
160
|
readonly?: boolean
|
|
162
|
-
|
|
161
|
+
invalid?: boolean
|
|
163
162
|
}>
|
|
164
163
|
|
|
165
164
|
export function MultiSelectGroup({
|
|
166
165
|
className,
|
|
167
166
|
name,
|
|
168
|
-
|
|
167
|
+
label,
|
|
169
168
|
selected,
|
|
170
169
|
onChange,
|
|
171
170
|
disabled = false,
|
|
172
171
|
readonly = false,
|
|
173
|
-
|
|
172
|
+
invalid = false,
|
|
174
173
|
children,
|
|
175
174
|
}: MultiSelectGroupProps) {
|
|
176
175
|
const handleChange = useCallback(
|
|
@@ -197,15 +196,11 @@ export function MultiSelectGroup({
|
|
|
197
196
|
selected: Array.from(new Set(selected)),
|
|
198
197
|
disabled,
|
|
199
198
|
readonly,
|
|
200
|
-
|
|
199
|
+
invalid,
|
|
201
200
|
onChange: handleChange,
|
|
202
201
|
}}
|
|
203
202
|
>
|
|
204
|
-
<div
|
|
205
|
-
className={className}
|
|
206
|
-
aria-label={ariaLabel}
|
|
207
|
-
data-testid="SelectGroup"
|
|
208
|
-
>
|
|
203
|
+
<div className={className} aria-label={label} data-testid="SelectGroup">
|
|
209
204
|
{children}
|
|
210
205
|
</div>
|
|
211
206
|
</MultiSelectGroupContext.Provider>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReactNode, forwardRef, memo, useMemo, useRef } from 'react'
|
|
2
|
+
import * as React from 'react'
|
|
2
3
|
import { useRadioGroupState } from 'react-stately'
|
|
3
4
|
import {
|
|
4
5
|
AriaRadioGroupProps,
|
|
@@ -76,13 +77,18 @@ export default memo(SegmentedControl)
|
|
|
76
77
|
type RadioProps = {
|
|
77
78
|
value: string
|
|
78
79
|
disabled?: boolean
|
|
80
|
+
children?: ReactNode
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
const Segmented
|
|
83
|
+
const Segmented = (props: RadioProps) => {
|
|
82
84
|
const state = useRadioContext()
|
|
83
85
|
const ref = useRef<HTMLInputElement>(null)
|
|
84
86
|
const ariaRadioProps = useMemo<AriaRadioProps>(
|
|
85
|
-
() => ({
|
|
87
|
+
() => ({
|
|
88
|
+
value: props.value,
|
|
89
|
+
isDisabled: props.disabled,
|
|
90
|
+
children: props.children,
|
|
91
|
+
}),
|
|
86
92
|
[props]
|
|
87
93
|
)
|
|
88
94
|
|
|
@@ -99,7 +105,7 @@ const Segmented: React.FC<RadioProps> = ({ children, ...props }) => {
|
|
|
99
105
|
>
|
|
100
106
|
<SegmentedInput {...inputProps} ref={ref} />
|
|
101
107
|
<RadioLabel>
|
|
102
|
-
<SegmentedLabelInner>{children}</SegmentedLabelInner>
|
|
108
|
+
<SegmentedLabelInner>{props.children}</SegmentedLabelInner>
|
|
103
109
|
</RadioLabel>
|
|
104
110
|
</SegmentedRoot>
|
|
105
111
|
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useSwitch } from '@react-aria/switch'
|
|
2
2
|
import type { AriaSwitchProps } from '@react-types/switch'
|
|
3
|
-
import
|
|
3
|
+
import { useRef, useMemo } from 'react'
|
|
4
|
+
import * as React from 'react'
|
|
4
5
|
import { useToggleState } from 'react-stately'
|
|
5
6
|
import styled from 'styled-components'
|
|
6
7
|
import { theme } from '../../styled'
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
forwardRef,
|
|
3
|
-
memo,
|
|
4
|
-
useMemo,
|
|
5
|
-
ComponentPropsWithoutRef,
|
|
6
|
-
} from 'react'
|
|
1
|
+
import { forwardRef, memo, useMemo, ComponentPropsWithoutRef } from 'react'
|
|
7
2
|
import { useObjectRef } from '@react-aria/utils'
|
|
8
3
|
import styled, { css } from 'styled-components'
|
|
9
4
|
import { theme } from '../../styled'
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { useTextField } from '@react-aria/textfield'
|
|
2
2
|
import { useVisuallyHidden } from '@react-aria/visually-hidden'
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
useCallback,
|
|
6
|
-
useEffect,
|
|
7
|
-
useRef,
|
|
8
|
-
useState,
|
|
9
|
-
} from 'react'
|
|
3
|
+
import { ReactNode, useCallback, useEffect, useRef, useState } from 'react'
|
|
4
|
+
import * as React from 'react'
|
|
10
5
|
import styled, { css } from 'styled-components'
|
|
11
6
|
import FieldLabel, { FieldLabelProps } from '../FieldLabel'
|
|
12
7
|
import { createTheme } from '@charcoal-ui/styled'
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
import glob from 'glob'
|
|
3
3
|
import { axe, toHaveNoViolations } from 'jest-axe'
|
|
4
|
-
import React from 'react'
|
|
5
4
|
import { render } from '@testing-library/react'
|
|
6
5
|
import { ThemeProvider } from 'styled-components'
|
|
7
6
|
import { Story } from '../_lib/compat'
|
package/src/index.ts
CHANGED
|
@@ -52,13 +52,16 @@ export {
|
|
|
52
52
|
} from './components/LoadingSpinner'
|
|
53
53
|
export {
|
|
54
54
|
default as DropdownSelector,
|
|
55
|
-
type DropdownSelectorOption,
|
|
56
55
|
type DropdownSelectorProps,
|
|
57
56
|
} from './components/DropdownSelector'
|
|
58
57
|
export {
|
|
59
|
-
|
|
60
|
-
type
|
|
61
|
-
} from './components/DropdownSelector/
|
|
58
|
+
default as DropdownMenuItem,
|
|
59
|
+
type DropdownMenuItemProps,
|
|
60
|
+
} from './components/DropdownSelector/DropdownMenuItem'
|
|
61
|
+
export {
|
|
62
|
+
default as MenuItemGroup,
|
|
63
|
+
type MenuItemGroupProps,
|
|
64
|
+
} from './components/DropdownSelector/MenuItemGroup'
|
|
62
65
|
export {
|
|
63
66
|
default as SegmentedControl,
|
|
64
67
|
type SegmentedControlProps,
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode, useContext } from 'react'
|
|
2
|
-
import styled from 'styled-components'
|
|
3
|
-
import { px } from '@charcoal-ui/utils'
|
|
4
|
-
import Icon from '../Icon'
|
|
5
|
-
import { theme } from '../../styled'
|
|
6
|
-
import { DropdownSelectorContext } from '.'
|
|
7
|
-
import { focusIfHTMLLIElement } from './utils/focusIfHTMLLIElement'
|
|
8
|
-
|
|
9
|
-
export type OptionItemProps = {
|
|
10
|
-
children?: ReactNode
|
|
11
|
-
value: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function OptionItem(props: OptionItemProps) {
|
|
15
|
-
const { value, setValue } = useContext(DropdownSelectorContext)
|
|
16
|
-
const isSelected = props.value === value
|
|
17
|
-
const onSelect = () => {
|
|
18
|
-
setValue(props.value)
|
|
19
|
-
}
|
|
20
|
-
return (
|
|
21
|
-
<OptionRoot
|
|
22
|
-
data-key={props.value}
|
|
23
|
-
onMouseMove={(e) => {
|
|
24
|
-
e.currentTarget.focus({ preventScroll: true })
|
|
25
|
-
}}
|
|
26
|
-
onKeyDown={(e) => {
|
|
27
|
-
if (e.key === 'Enter') {
|
|
28
|
-
onSelect()
|
|
29
|
-
} else if (e.key === 'ArrowUp') {
|
|
30
|
-
// prevent scroll
|
|
31
|
-
e.preventDefault()
|
|
32
|
-
const prev = e.currentTarget.previousElementSibling
|
|
33
|
-
if (prev === null) {
|
|
34
|
-
focusIfHTMLLIElement(e.currentTarget.parentElement?.lastChild)
|
|
35
|
-
}
|
|
36
|
-
focusIfHTMLLIElement(prev)
|
|
37
|
-
} else if (e.key === 'ArrowDown') {
|
|
38
|
-
// prevent scroll
|
|
39
|
-
e.preventDefault()
|
|
40
|
-
const next = e.currentTarget.nextElementSibling
|
|
41
|
-
if (next === null) {
|
|
42
|
-
focusIfHTMLLIElement(e.currentTarget.parentElement?.firstChild)
|
|
43
|
-
}
|
|
44
|
-
focusIfHTMLLIElement(next)
|
|
45
|
-
} else if (e.key === ' ') {
|
|
46
|
-
// prevent scroll
|
|
47
|
-
e.preventDefault()
|
|
48
|
-
}
|
|
49
|
-
}}
|
|
50
|
-
onClick={onSelect}
|
|
51
|
-
tabIndex={-1}
|
|
52
|
-
>
|
|
53
|
-
{isSelected && <OptionCheckIcon name="16/Check" />}
|
|
54
|
-
<OptionText isSelected={isSelected}>{props.children}</OptionText>
|
|
55
|
-
</OptionRoot>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const OptionRoot = styled.li`
|
|
60
|
-
display: flex;
|
|
61
|
-
align-items: center;
|
|
62
|
-
gap: ${({ theme }) => px(theme.spacing[4])};
|
|
63
|
-
height: 40px;
|
|
64
|
-
cursor: pointer;
|
|
65
|
-
outline: none;
|
|
66
|
-
|
|
67
|
-
${theme((o) => [o.padding.horizontal(8)])}
|
|
68
|
-
|
|
69
|
-
:focus {
|
|
70
|
-
${theme((o) => [o.bg.surface3])}
|
|
71
|
-
}
|
|
72
|
-
`
|
|
73
|
-
|
|
74
|
-
const OptionCheckIcon = styled(Icon)`
|
|
75
|
-
${theme((o) => [o.font.text2])}
|
|
76
|
-
`
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* アイコンがない時を考慮して20px(16pxのwidthと4pxのgap)の余白をとる
|
|
80
|
-
*/
|
|
81
|
-
const OptionText = styled.span<{ isSelected?: boolean }>`
|
|
82
|
-
display: block;
|
|
83
|
-
${theme((o) => [o.typography(14), o.font.text2])}
|
|
84
|
-
margin-left: ${({ isSelected }) => (isSelected === true ? 0 : 20)}px;
|
|
85
|
-
`
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { handleFocusByKeyBoard } from './handleFocusByKeyBoard'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* li要素ならフォーカスしてスクロールスクロール領域に見えるように親要素をスクロールする
|
|
5
|
-
* @param element
|
|
6
|
-
*/
|
|
7
|
-
export function focusIfHTMLLIElement(element: Node | null | undefined) {
|
|
8
|
-
if (element instanceof HTMLLIElement) {
|
|
9
|
-
element.focus({ preventScroll: true })
|
|
10
|
-
handleFocusByKeyBoard(element)
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* スクロールスクロール領域に見えるように親要素をスクロールする
|
|
3
|
-
* @param element
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export function handleFocusByKeyBoard(element: HTMLElement) {
|
|
7
|
-
const parent = element.parentElement
|
|
8
|
-
if (!parent) return
|
|
9
|
-
const rect = element.getBoundingClientRect()
|
|
10
|
-
const parentRect = parent.getBoundingClientRect()
|
|
11
|
-
if (rect.bottom > parentRect.bottom) {
|
|
12
|
-
parent.scrollTo({
|
|
13
|
-
top: parent.scrollTop + rect.bottom - parentRect.bottom,
|
|
14
|
-
})
|
|
15
|
-
} else if (rect.top < parentRect.top) {
|
|
16
|
-
parent.scrollTo({
|
|
17
|
-
top: parent.scrollTop - (parentRect.top - rect.top),
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
}
|