@charcoal-ui/react 3.3.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_lib/useForwardedRef.d.ts +3 -0
- package/dist/_lib/useForwardedRef.d.ts.map +1 -0
- package/dist/components/Clickable/index.d.ts.map +1 -1
- package/dist/components/DropdownSelector/DropdownPopover.d.ts.map +1 -1
- package/dist/components/DropdownSelector/Popover/index.d.ts.map +1 -1
- package/dist/components/DropdownSelector/Popover/usePreventScroll.d.ts +2 -0
- package/dist/components/DropdownSelector/Popover/usePreventScroll.d.ts.map +1 -0
- package/dist/components/DropdownSelector/index.story.d.ts +1 -0
- package/dist/components/DropdownSelector/index.story.d.ts.map +1 -1
- package/dist/components/Icon/index.story.d.ts +1 -1
- package/dist/components/Modal/Dialog/index.d.ts +26 -0
- package/dist/components/Modal/Dialog/index.d.ts.map +1 -0
- package/dist/components/Modal/ModalBackgroundContext.d.ts +6 -0
- package/dist/components/Modal/ModalBackgroundContext.d.ts.map +1 -0
- package/dist/components/Modal/ModalPlumbing.d.ts.map +1 -1
- package/dist/components/Modal/__stories__/InternalScrollStory.d.ts +4 -0
- package/dist/components/Modal/__stories__/InternalScrollStory.d.ts.map +1 -0
- package/dist/components/Modal/index.d.ts +12 -2
- package/dist/components/Modal/index.d.ts.map +1 -1
- package/dist/components/Modal/index.story.d.ts +3 -2
- package/dist/components/Modal/index.story.d.ts.map +1 -1
- package/dist/components/TextArea/index.d.ts.map +1 -1
- package/dist/components/TextField/index.d.ts +4 -0
- package/dist/components/TextField/index.d.ts.map +1 -1
- package/dist/components/TextField/useFocusWithClick.d.ts +3 -0
- package/dist/components/TextField/useFocusWithClick.d.ts.map +1 -0
- package/dist/index.cjs.js +532 -426
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +482 -377
- package/dist/index.esm.js.map +1 -1
- package/package.json +6 -6
- package/src/_lib/useForwardedRef.tsx +16 -0
- package/src/components/Button/__snapshots__/index.story.storyshot +1971 -0
- package/src/components/Checkbox/__snapshots__/index.story.storyshot +390 -0
- package/src/components/Clickable/__snapshots__/index.story.storyshot +100 -0
- package/src/components/Clickable/index.tsx +17 -35
- package/src/components/DropdownSelector/DropdownPopover.tsx +0 -1
- package/src/components/DropdownSelector/ListItem/__snapshots__/index.story.storyshot +245 -0
- package/src/components/DropdownSelector/MenuList/__snapshots__/index.story.storyshot +555 -0
- package/src/components/DropdownSelector/Popover/__snapshots__/index.story.storyshot +174 -0
- package/src/components/DropdownSelector/Popover/index.tsx +17 -2
- package/src/components/DropdownSelector/Popover/usePreventScroll.tsx +18 -0
- package/src/components/DropdownSelector/__snapshots__/index.story.storyshot +1241 -0
- package/src/components/DropdownSelector/index.story.tsx +69 -13
- package/src/components/Icon/__snapshots__/index.story.storyshot +12 -0
- package/src/components/{Button/__snapshots__/index.test.tsx.snap → IconButton/__snapshots__/index.story.storyshot} +94 -91
- package/src/components/LoadingSpinner/__snapshots__/index.story.storyshot +81 -0
- package/src/components/Modal/Dialog/index.tsx +82 -0
- package/src/components/Modal/ModalBackgroundContext.tsx +8 -0
- package/src/components/Modal/ModalPlumbing.tsx +16 -4
- package/src/components/Modal/__snapshots__/index.story.storyshot +533 -0
- package/src/components/Modal/__stories__/InternalScrollStory.tsx +75 -0
- package/src/components/Modal/index.story.tsx +57 -38
- package/src/components/Modal/index.tsx +63 -94
- package/src/components/MultiSelect/__snapshots__/index.story.storyshot +511 -0
- package/src/components/Radio/__snapshots__/index.story.storyshot +319 -0
- package/src/components/SegmentedControl/__snapshots__/index.story.storyshot +483 -0
- package/src/components/Switch/__snapshots__/index.story.storyshot +454 -0
- package/src/components/TagItem/__snapshots__/index.story.storyshot +1181 -0
- package/src/components/TextArea/__snapshots__/TextArea.story.storyshot +1114 -0
- package/src/components/TextArea/index.tsx +38 -43
- package/src/components/TextField/TextField.story.tsx +2 -3
- package/src/components/TextField/__snapshots__/TextField.story.storyshot +1603 -0
- package/src/components/TextField/index.tsx +86 -84
- package/src/components/TextField/useFocusWithClick.tsx +22 -0
- package/dist/components/Button/index.test.d.ts +0 -4
- package/dist/components/Button/index.test.d.ts.map +0 -1
- package/src/components/Button/index.test.tsx +0 -24
|
@@ -2,11 +2,11 @@ import { useTextField } from '@react-aria/textfield'
|
|
|
2
2
|
import { useVisuallyHidden } from '@react-aria/visually-hidden'
|
|
3
3
|
import { ReactNode, useCallback, useEffect, useRef, useState } from 'react'
|
|
4
4
|
import * as React from 'react'
|
|
5
|
-
import styled from 'styled-components'
|
|
5
|
+
import styled, { css } from 'styled-components'
|
|
6
6
|
import FieldLabel, { FieldLabelProps } from '../FieldLabel'
|
|
7
7
|
import { countCodePointsInString, mergeRefs } from '../../_lib'
|
|
8
|
-
import { theme } from '../../styled'
|
|
9
8
|
import { ReactAreaUseTextFieldCompat } from '../../_lib/compat'
|
|
9
|
+
import { useFocusWithClick } from './useFocusWithClick'
|
|
10
10
|
|
|
11
11
|
type DOMProps = Omit<
|
|
12
12
|
React.InputHTMLAttributes<HTMLInputElement>,
|
|
@@ -64,13 +64,9 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
64
64
|
|
|
65
65
|
const { visuallyHiddenProps } = useVisuallyHidden()
|
|
66
66
|
const ariaRef = useRef<HTMLInputElement>(null)
|
|
67
|
-
const prefixRef = useRef<HTMLSpanElement>(null)
|
|
68
|
-
const suffixRef = useRef<HTMLSpanElement>(null)
|
|
69
67
|
const [count, setCount] = useState(
|
|
70
68
|
countCodePointsInString(props.value ?? '')
|
|
71
69
|
)
|
|
72
|
-
const [prefixWidth, setPrefixWidth] = useState(0)
|
|
73
|
-
const [suffixWidth, setSuffixWidth] = useState(0)
|
|
74
70
|
|
|
75
71
|
const nonControlled = props.value === undefined
|
|
76
72
|
const handleChange = useCallback(
|
|
@@ -106,26 +102,9 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
106
102
|
ariaRef
|
|
107
103
|
)
|
|
108
104
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
})
|
|
113
|
-
const suffixObserver = new ResizeObserver((entries) => {
|
|
114
|
-
setSuffixWidth(entries[0].contentRect.width)
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
if (prefixRef.current !== null) {
|
|
118
|
-
prefixObserver.observe(prefixRef.current)
|
|
119
|
-
}
|
|
120
|
-
if (suffixRef.current !== null) {
|
|
121
|
-
suffixObserver.observe(suffixRef.current)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return () => {
|
|
125
|
-
suffixObserver.disconnect()
|
|
126
|
-
prefixObserver.disconnect()
|
|
127
|
-
}
|
|
128
|
-
}, [])
|
|
105
|
+
const containerRef = useRef(null)
|
|
106
|
+
|
|
107
|
+
useFocusWithClick(containerRef, ariaRef)
|
|
129
108
|
|
|
130
109
|
return (
|
|
131
110
|
<TextFieldRoot className={className} isDisabled={disabled}>
|
|
@@ -137,25 +116,29 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
137
116
|
{...labelProps}
|
|
138
117
|
{...(!showLabel ? visuallyHiddenProps : {})}
|
|
139
118
|
/>
|
|
140
|
-
<StyledInputContainer
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
119
|
+
<StyledInputContainer
|
|
120
|
+
ref={containerRef}
|
|
121
|
+
invalid={invalid}
|
|
122
|
+
aria-disabled={disabled === true ? true : undefined}
|
|
123
|
+
hasPrefix={prefix != null}
|
|
124
|
+
hasSuffix={suffix != null || showCount}
|
|
125
|
+
>
|
|
126
|
+
{prefix && <PrefixContainer>{prefix}</PrefixContainer>}
|
|
144
127
|
<StyledInput
|
|
145
128
|
ref={mergeRefs(forwardRef, ariaRef)}
|
|
146
129
|
invalid={invalid}
|
|
147
|
-
extraLeftPadding={prefixWidth}
|
|
148
|
-
extraRightPadding={suffixWidth}
|
|
149
130
|
{...inputProps}
|
|
150
131
|
/>
|
|
151
|
-
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
132
|
+
{(suffix || showCount) && (
|
|
133
|
+
<SuffixContainer>
|
|
134
|
+
{suffix}
|
|
135
|
+
{showCount && (
|
|
136
|
+
<SingleLineCounter>
|
|
137
|
+
{maxLength !== undefined ? `${count}/${maxLength}` : count}
|
|
138
|
+
</SingleLineCounter>
|
|
139
|
+
)}
|
|
140
|
+
</SuffixContainer>
|
|
141
|
+
)}
|
|
159
142
|
</StyledInputContainer>
|
|
160
143
|
{assistiveText != null && assistiveText.length !== 0 && (
|
|
161
144
|
<AssistiveText
|
|
@@ -179,44 +162,69 @@ const TextFieldRoot = styled.div<{ isDisabled: boolean }>`
|
|
|
179
162
|
${(p) => p.isDisabled && { opacity: p.theme.elementEffect.disabled.opacity }}
|
|
180
163
|
`
|
|
181
164
|
|
|
182
|
-
const TextFieldLabel = styled(FieldLabel)`
|
|
183
|
-
|
|
165
|
+
export const TextFieldLabel = styled(FieldLabel)`
|
|
166
|
+
margin-bottom: 8px;
|
|
184
167
|
`
|
|
185
168
|
|
|
186
|
-
const StyledInputContainer = styled.div
|
|
187
|
-
|
|
169
|
+
const StyledInputContainer = styled.div<{
|
|
170
|
+
invalid: boolean
|
|
171
|
+
hasPrefix: boolean
|
|
172
|
+
hasSuffix: boolean
|
|
173
|
+
}>`
|
|
188
174
|
display: grid;
|
|
189
|
-
|
|
175
|
+
grid-template-columns: ${(p) =>
|
|
176
|
+
[p.hasPrefix && 'auto', '1fr', p.hasSuffix && 'auto']
|
|
177
|
+
.filter(Boolean)
|
|
178
|
+
.join(' ')};
|
|
179
|
+
height: 40px;
|
|
180
|
+
transition: 0.2s background-color, 0.2s box-shadow;
|
|
181
|
+
color: var(--charcoal-text2);
|
|
182
|
+
background-color: var(--charcoal-surface3);
|
|
183
|
+
border-radius: 4px;
|
|
184
|
+
gap: 4px;
|
|
185
|
+
padding: 0 8px;
|
|
186
|
+
line-height: 22px;
|
|
187
|
+
font-size: 14px;
|
|
188
|
+
|
|
189
|
+
:not(:disabled):not([aria-disabled]):hover,
|
|
190
|
+
[aria-disabled='false']:hover {
|
|
191
|
+
background-color: var(--charcoal-surface3-hover);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
:not(:disabled):not([aria-disabled]):active,
|
|
195
|
+
[aria-disabled='false']:active {
|
|
196
|
+
outline: none;
|
|
197
|
+
box-shadow: 0 0 0 4px
|
|
198
|
+
${(p) => (p.invalid ? `rgba(255,43,0,0.32)` : `rgba(0, 150, 250, 0.32);`)};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
:focus-within {
|
|
202
|
+
outline: none;
|
|
203
|
+
box-shadow: 0 0 0 4px
|
|
204
|
+
${(p) => (p.invalid ? `rgba(255,43,0,0.32)` : `rgba(0, 150, 250, 0.32);`)};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
${(p) =>
|
|
208
|
+
p.invalid &&
|
|
209
|
+
css`
|
|
210
|
+
box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
|
|
211
|
+
`}
|
|
190
212
|
`
|
|
191
213
|
|
|
192
|
-
const PrefixContainer = styled.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
transform: translateY(-50%);
|
|
197
|
-
z-index: 1;
|
|
214
|
+
const PrefixContainer = styled.div`
|
|
215
|
+
display: flex;
|
|
216
|
+
padding-left: 8px;
|
|
217
|
+
align-items: center;
|
|
198
218
|
`
|
|
199
219
|
|
|
200
220
|
const SuffixContainer = styled.span`
|
|
201
|
-
position: absolute;
|
|
202
|
-
top: 50%;
|
|
203
|
-
right: 8px;
|
|
204
|
-
transform: translateY(-50%);
|
|
205
|
-
|
|
206
221
|
display: flex;
|
|
222
|
+
align-items: center;
|
|
207
223
|
gap: 8px;
|
|
208
224
|
`
|
|
209
225
|
|
|
210
|
-
const Affix = styled.span`
|
|
211
|
-
user-select: none;
|
|
212
|
-
|
|
213
|
-
${theme((o) => [o.typography(14).preserveHalfLeading, o.font.text2])}
|
|
214
|
-
`
|
|
215
|
-
|
|
216
226
|
const StyledInput = styled.input<{
|
|
217
227
|
invalid: boolean
|
|
218
|
-
extraLeftPadding: number
|
|
219
|
-
extraRightPadding: number
|
|
220
228
|
}>`
|
|
221
229
|
border: none;
|
|
222
230
|
box-sizing: border-box;
|
|
@@ -230,36 +238,30 @@ const StyledInput = styled.input<{
|
|
|
230
238
|
height: calc(100% / 0.875);
|
|
231
239
|
font-size: calc(14px / 0.875);
|
|
232
240
|
line-height: calc(22px / 0.875);
|
|
233
|
-
padding-left:
|
|
234
|
-
padding-right:
|
|
241
|
+
padding-left: 0;
|
|
242
|
+
padding-right: 0;
|
|
235
243
|
border-radius: calc(4px / 0.875);
|
|
236
244
|
|
|
237
245
|
/* Display box-shadow for iOS Safari */
|
|
238
246
|
appearance: none;
|
|
247
|
+
background: transparent;
|
|
239
248
|
|
|
240
|
-
|
|
241
|
-
theme((o) => [
|
|
242
|
-
o.bg.surface3.hover,
|
|
243
|
-
o.outline.default.focus,
|
|
244
|
-
p.invalid && o.outline.assertive,
|
|
245
|
-
o.font.text2,
|
|
246
|
-
])}
|
|
247
|
-
|
|
249
|
+
color: var(--charcoal-text2);
|
|
248
250
|
&::placeholder {
|
|
249
|
-
|
|
251
|
+
color: var(--charcoal-text3);
|
|
250
252
|
}
|
|
251
253
|
`
|
|
252
254
|
|
|
253
255
|
const SingleLineCounter = styled.span`
|
|
254
|
-
|
|
256
|
+
line-height: 22px;
|
|
257
|
+
font-size: 14px;
|
|
258
|
+
color: var(--charcoal-text3);
|
|
255
259
|
`
|
|
256
260
|
|
|
257
|
-
const AssistiveText = styled.p<{ invalid: boolean }>`
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
o.font[p.invalid ? 'assertive' : 'text1'],
|
|
264
|
-
])}
|
|
261
|
+
export const AssistiveText = styled.p<{ invalid: boolean }>`
|
|
262
|
+
font-size: 14px;
|
|
263
|
+
line-height: 22px;
|
|
264
|
+
margin-top: 4px;
|
|
265
|
+
margin-bottom: -4px;
|
|
266
|
+
color: ${(p) => `var(--charcoal-${p.invalid ? `assertive` : `text2`})`};
|
|
265
267
|
`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
|
|
4
|
+
export function useFocusWithClick(
|
|
5
|
+
containerRef: React.RefObject<HTMLDivElement>,
|
|
6
|
+
inputRef: React.RefObject<HTMLInputElement | HTMLTextAreaElement>
|
|
7
|
+
) {
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const el = containerRef.current
|
|
10
|
+
if (el) {
|
|
11
|
+
const handleDown = (e: MouseEvent) => {
|
|
12
|
+
if (e.target !== inputRef.current) {
|
|
13
|
+
inputRef.current?.focus()
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
el.addEventListener('click', handleDown)
|
|
17
|
+
return () => {
|
|
18
|
+
el.removeEventListener('click', handleDown)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/components/Button/index.test.tsx"],"names":[],"mappings":"AAAA,OAAO,wBAAwB,CAAA;AAG/B,OAAO,QAAQ,MAAM,qBAAqB,CAAA;AAI1C,wBAAgB,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,4EAI3C"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import 'jest-styled-components'
|
|
2
|
-
|
|
3
|
-
import Button from '.'
|
|
4
|
-
import renderer from 'react-test-renderer'
|
|
5
|
-
import { ThemeProvider } from 'styled-components'
|
|
6
|
-
import { light } from '@charcoal-ui/theme'
|
|
7
|
-
|
|
8
|
-
export function render(children: JSX.Element) {
|
|
9
|
-
return renderer
|
|
10
|
-
.create(<ThemeProvider theme={light}>{children}</ThemeProvider>)
|
|
11
|
-
.toJSON()
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
describe('Basic', () => {
|
|
15
|
-
test('<Button>Hello</Button>', () => {
|
|
16
|
-
expect(render(<Button>Hello</Button>)).toMatchSnapshot()
|
|
17
|
-
})
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
describe('Link', () => {
|
|
21
|
-
test('<Button to="#">Hello</Button>', () => {
|
|
22
|
-
expect(render(<Button to="#">Hello</Button>)).toMatchSnapshot()
|
|
23
|
-
})
|
|
24
|
-
})
|