@toptal/picasso-outlined-input 1.1.5 → 2.0.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-package/src/OutlinedInput/OutlinedInput.d.ts +1 -48
- package/dist-package/src/OutlinedInput/OutlinedInput.d.ts.map +1 -1
- package/dist-package/src/OutlinedInput/OutlinedInput.js +58 -35
- package/dist-package/src/OutlinedInput/OutlinedInput.js.map +1 -1
- package/dist-package/src/OutlinedInput/index.d.ts +2 -1
- package/dist-package/src/OutlinedInput/index.d.ts.map +1 -1
- package/dist-package/src/OutlinedInput/stylesInput.d.ts +24 -0
- package/dist-package/src/OutlinedInput/stylesInput.d.ts.map +1 -0
- package/dist-package/src/OutlinedInput/stylesInput.js +60 -0
- package/dist-package/src/OutlinedInput/stylesInput.js.map +1 -0
- package/dist-package/src/OutlinedInput/stylesRoot.d.ts +66 -0
- package/dist-package/src/OutlinedInput/stylesRoot.d.ts.map +1 -0
- package/dist-package/src/OutlinedInput/stylesRoot.js +142 -0
- package/dist-package/src/OutlinedInput/stylesRoot.js.map +1 -0
- package/dist-package/src/OutlinedInput/types.d.ts +62 -0
- package/dist-package/src/OutlinedInput/types.d.ts.map +1 -0
- package/dist-package/src/OutlinedInput/types.js +2 -0
- package/dist-package/src/OutlinedInput/types.js.map +1 -0
- package/dist-package/src/OutlinedInput/utils.d.ts +2 -0
- package/dist-package/src/OutlinedInput/utils.d.ts.map +1 -0
- package/dist-package/src/OutlinedInput/utils.js +2 -0
- package/dist-package/src/OutlinedInput/utils.js.map +1 -0
- package/package.json +10 -9
- package/src/OutlinedInput/OutlinedInput.tsx +95 -129
- package/src/OutlinedInput/index.ts +2 -1
- package/src/OutlinedInput/stylesInput.test.ts +152 -0
- package/src/OutlinedInput/stylesInput.ts +87 -0
- package/src/OutlinedInput/stylesRoot.test.ts +195 -0
- package/src/OutlinedInput/stylesRoot.ts +217 -0
- package/src/OutlinedInput/types.ts +87 -0
- package/src/OutlinedInput/utils.ts +2 -0
- package/dist-package/src/OutlinedInput/styles.d.ts +0 -4
- package/dist-package/src/OutlinedInput/styles.d.ts.map +0 -1
- package/dist-package/src/OutlinedInput/styles.js +0 -157
- package/dist-package/src/OutlinedInput/styles.js.map +0 -1
- package/dist-package/src/styles.d.ts +0 -2
- package/dist-package/src/styles.d.ts.map +0 -1
- package/dist-package/src/styles.js +0 -2
- package/dist-package/src/styles.js.map +0 -1
- package/src/OutlinedInput/styles.ts +0 -183
- package/src/styles.ts +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/OutlinedInput/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAiC,EAAE,EAAE,CAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/picasso-outlined-input",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Toptal UI components library - OutlinedInput",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -22,12 +22,13 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://github.com/toptal/picasso/tree/master/packages/picasso#readme",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@toptal/picasso-button": "
|
|
26
|
-
"@toptal/picasso-form": "
|
|
25
|
+
"@toptal/picasso-button": "3.0.0",
|
|
26
|
+
"@toptal/picasso-form": "4.0.0",
|
|
27
27
|
"@toptal/picasso-icons": "1.5.0",
|
|
28
|
-
"@toptal/picasso-input-adornment": "
|
|
28
|
+
"@toptal/picasso-input-adornment": "2.0.0",
|
|
29
29
|
"@toptal/picasso-shared": "15.0.0",
|
|
30
30
|
"@toptal/picasso-utils": "1.0.3",
|
|
31
|
+
"@mui/base": "5.0.0-beta.40",
|
|
31
32
|
"classnames": "^2.5.1"
|
|
32
33
|
},
|
|
33
34
|
"sideEffects": [
|
|
@@ -35,17 +36,17 @@
|
|
|
35
36
|
"**/styles.js"
|
|
36
37
|
],
|
|
37
38
|
"peerDependencies": {
|
|
38
|
-
"@
|
|
39
|
-
"@toptal/picasso-
|
|
39
|
+
"@toptal/picasso-tailwind-merge": "1.2.0",
|
|
40
|
+
"@toptal/picasso-tailwind": ">=2.5.0",
|
|
40
41
|
"react": ">=16.12.0 < 19.0.0"
|
|
41
42
|
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@toptal/picasso-tailwind-merge": "1.2.0"
|
|
45
|
+
},
|
|
42
46
|
"exports": {
|
|
43
47
|
".": "./dist-package/src/index.js",
|
|
44
48
|
"./styles": "./dist-package/src/styles.js"
|
|
45
49
|
},
|
|
46
|
-
"devDependencies": {
|
|
47
|
-
"@toptal/picasso-provider": "4.2.1"
|
|
48
|
-
},
|
|
49
50
|
"files": [
|
|
50
51
|
"dist-package/**",
|
|
51
52
|
"!dist-package/tsconfig.tsbuildinfo",
|
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
ReactType,
|
|
4
|
-
ReactNode,
|
|
5
|
-
InputHTMLAttributes,
|
|
6
|
-
MouseEvent,
|
|
7
|
-
} from 'react'
|
|
8
|
-
import React, { forwardRef } from 'react'
|
|
9
|
-
import cx from 'classnames'
|
|
10
|
-
import type { Theme } from '@material-ui/core/styles'
|
|
11
|
-
import { makeStyles } from '@material-ui/core/styles'
|
|
12
|
-
import { OutlinedInput as MUIOutlinedInput } from '@material-ui/core'
|
|
13
|
-
import type { InputBaseComponentProps } from '@material-ui/core/InputBase'
|
|
14
|
-
import capitalize from '@material-ui/core/utils/capitalize'
|
|
15
|
-
import type { StandardProps, SizeType, Classes } from '@toptal/picasso-shared'
|
|
1
|
+
import type { MouseEvent } from 'react'
|
|
2
|
+
import React, { forwardRef, useImperativeHandle, useRef } from 'react'
|
|
16
3
|
import {
|
|
17
4
|
InputAdornment,
|
|
18
5
|
InputValidIconAdornment,
|
|
@@ -21,82 +8,23 @@ import { ButtonCircular } from '@toptal/picasso-button'
|
|
|
21
8
|
import { CloseMinor16 } from '@toptal/picasso-icons'
|
|
22
9
|
import { noop, usePropDeprecationWarning } from '@toptal/picasso-utils'
|
|
23
10
|
import { useFieldsLayoutContext } from '@toptal/picasso-form'
|
|
11
|
+
import { Input, type InputOwnerState } from '@mui/base/Input'
|
|
12
|
+
import {
|
|
13
|
+
TextareaAutosize,
|
|
14
|
+
type TextareaAutosizeProps,
|
|
15
|
+
} from '@mui/base/TextareaAutosize'
|
|
16
|
+
import { twJoin, twMerge } from '@toptal/picasso-tailwind-merge'
|
|
24
17
|
|
|
25
|
-
import
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| string
|
|
30
|
-
| number
|
|
31
|
-
| boolean
|
|
32
|
-
| object
|
|
33
|
-
|
|
34
|
-
export type Status = 'error' | 'success' | 'default'
|
|
35
|
-
|
|
36
|
-
export type BaseInputProps = InputBaseComponentProps & {
|
|
37
|
-
variant?: 'dark' | 'light'
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface Props
|
|
41
|
-
extends StandardProps,
|
|
42
|
-
Omit<
|
|
43
|
-
InputHTMLAttributes<HTMLInputElement>,
|
|
44
|
-
'value' | 'defaultValue' | 'size' | 'color'
|
|
45
|
-
> {
|
|
46
|
-
/** Width of the component */
|
|
47
|
-
width?: 'full' | 'shrink' | 'auto'
|
|
48
|
-
inputComponent?: ReactType<InputBaseComponentProps>
|
|
49
|
-
inputProps?: BaseInputProps
|
|
50
|
-
defaultValue?: ValueType
|
|
51
|
-
value?: ValueType
|
|
52
|
-
/** Whether `Input` should be rendered as `TextArea` or not */
|
|
53
|
-
multiline?: boolean
|
|
54
|
-
/** If true, the input element will be focused during the first mount */
|
|
55
|
-
autoFocus?: boolean
|
|
56
|
-
/** Specify rows amount for `TextArea` */
|
|
57
|
-
rows?: string | number
|
|
58
|
-
/* Maximum number of rows to display when multiline option is set to true. */
|
|
59
|
-
rowsMax?: string | number
|
|
60
|
-
/** Type attribute of the Input element. It should be a valid HTML5 input type */
|
|
61
|
-
type?: string
|
|
62
|
-
/**
|
|
63
|
-
* @deprecated [FX-4715] Use the `status` prop instead to both support success and error states
|
|
64
|
-
* Indicate whether input is in error state
|
|
65
|
-
*/
|
|
66
|
-
error?: boolean
|
|
67
|
-
/** Indicate input status */
|
|
68
|
-
status?: Status
|
|
69
|
-
startAdornment?: ReactNode
|
|
70
|
-
endAdornment?: ReactNode
|
|
71
|
-
onChange?: ChangeEventHandler<HTMLInputElement>
|
|
72
|
-
/** Component size */
|
|
73
|
-
size?: SizeType<'small' | 'medium' | 'large'>
|
|
74
|
-
/** Whether to render reset icon when there is a value in the input */
|
|
75
|
-
enableReset?: boolean
|
|
76
|
-
/** Callback invoked when reset button was clicked */
|
|
77
|
-
onResetClick?: (
|
|
78
|
-
event: MouseEvent<HTMLButtonElement & HTMLAnchorElement>
|
|
79
|
-
) => void
|
|
80
|
-
/** Ref of the input element */
|
|
81
|
-
inputRef?: React.Ref<HTMLInputElement>
|
|
82
|
-
testIds?: {
|
|
83
|
-
resetButton?: string
|
|
84
|
-
validIcon?: string
|
|
85
|
-
}
|
|
86
|
-
highlight?: 'autofill'
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const useStyles = makeStyles<Theme, Props>(styles, {
|
|
90
|
-
name: 'PicassoOutlinedInput',
|
|
91
|
-
})
|
|
18
|
+
import { getRootClassName } from './stylesRoot'
|
|
19
|
+
import { getInputClassName } from './stylesInput'
|
|
20
|
+
import { getRows } from './utils'
|
|
21
|
+
import type { Props } from './types'
|
|
92
22
|
|
|
93
23
|
const ResetButton = ({
|
|
94
|
-
classes,
|
|
95
24
|
hasValue,
|
|
96
25
|
onClick,
|
|
97
26
|
testIds,
|
|
98
27
|
}: {
|
|
99
|
-
classes: Classes
|
|
100
28
|
hasValue: boolean
|
|
101
29
|
onClick: (event: MouseEvent<HTMLButtonElement & HTMLAnchorElement>) => void
|
|
102
30
|
testIds?: Props['testIds']
|
|
@@ -104,9 +32,10 @@ const ResetButton = ({
|
|
|
104
32
|
<InputAdornment
|
|
105
33
|
data-testid={testIds?.resetButton}
|
|
106
34
|
position='end'
|
|
107
|
-
className={
|
|
108
|
-
|
|
109
|
-
|
|
35
|
+
className={twJoin(
|
|
36
|
+
'invisible',
|
|
37
|
+
hasValue && 'peer-focus:visible peer-hover:visible'
|
|
38
|
+
)}
|
|
110
39
|
>
|
|
111
40
|
<ButtonCircular
|
|
112
41
|
tabIndex={-1}
|
|
@@ -124,6 +53,22 @@ const ResetButton = ({
|
|
|
124
53
|
</InputAdornment>
|
|
125
54
|
)
|
|
126
55
|
|
|
56
|
+
const Textarea = forwardRef<
|
|
57
|
+
HTMLTextAreaElement,
|
|
58
|
+
{ ownerState: InputOwnerState } & TextareaAutosizeProps
|
|
59
|
+
>(
|
|
60
|
+
(
|
|
61
|
+
{
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
63
|
+
ownerState,
|
|
64
|
+
...rest
|
|
65
|
+
},
|
|
66
|
+
ref
|
|
67
|
+
) => {
|
|
68
|
+
return <TextareaAutosize ref={ref} {...rest} />
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
|
|
127
72
|
const OutlinedInput = forwardRef<HTMLElement, Props>(function OutlinedInput(
|
|
128
73
|
props,
|
|
129
74
|
ref
|
|
@@ -132,6 +77,7 @@ const OutlinedInput = forwardRef<HTMLElement, Props>(function OutlinedInput(
|
|
|
132
77
|
className,
|
|
133
78
|
style,
|
|
134
79
|
multiline,
|
|
80
|
+
multilineResizable,
|
|
135
81
|
autoFocus,
|
|
136
82
|
rows,
|
|
137
83
|
rowsMax,
|
|
@@ -140,7 +86,7 @@ const OutlinedInput = forwardRef<HTMLElement, Props>(function OutlinedInput(
|
|
|
140
86
|
inputProps,
|
|
141
87
|
defaultValue,
|
|
142
88
|
value,
|
|
143
|
-
type,
|
|
89
|
+
type = 'text',
|
|
144
90
|
error,
|
|
145
91
|
status,
|
|
146
92
|
startAdornment,
|
|
@@ -153,6 +99,7 @@ const OutlinedInput = forwardRef<HTMLElement, Props>(function OutlinedInput(
|
|
|
153
99
|
inputRef,
|
|
154
100
|
testIds,
|
|
155
101
|
highlight,
|
|
102
|
+
classes,
|
|
156
103
|
...rest
|
|
157
104
|
} = props
|
|
158
105
|
|
|
@@ -166,7 +113,6 @@ const OutlinedInput = forwardRef<HTMLElement, Props>(function OutlinedInput(
|
|
|
166
113
|
})
|
|
167
114
|
|
|
168
115
|
const { layout } = useFieldsLayoutContext()
|
|
169
|
-
const classes = useStyles(props)
|
|
170
116
|
const isDark = inputProps?.variant === 'dark'
|
|
171
117
|
const shouldShowReset = enableReset && !disabled
|
|
172
118
|
const hasEndAdornment = status === 'success' || shouldShowReset
|
|
@@ -174,7 +120,6 @@ const OutlinedInput = forwardRef<HTMLElement, Props>(function OutlinedInput(
|
|
|
174
120
|
<>
|
|
175
121
|
{shouldShowReset && (
|
|
176
122
|
<ResetButton
|
|
177
|
-
classes={classes}
|
|
178
123
|
hasValue={Boolean(value)}
|
|
179
124
|
onClick={onResetClick}
|
|
180
125
|
testIds={testIds}
|
|
@@ -189,56 +134,77 @@ const OutlinedInput = forwardRef<HTMLElement, Props>(function OutlinedInput(
|
|
|
189
134
|
userDefinedEndAdornment
|
|
190
135
|
)
|
|
191
136
|
|
|
137
|
+
const divRef = useRef<HTMLDivElement | null>(null)
|
|
138
|
+
|
|
139
|
+
useImperativeHandle(ref, () => divRef.current as HTMLElement, [])
|
|
140
|
+
|
|
141
|
+
const isError = Boolean(status === 'error' || error)
|
|
142
|
+
|
|
143
|
+
const inputClassName = getInputClassName({
|
|
144
|
+
size,
|
|
145
|
+
disabled,
|
|
146
|
+
isDark,
|
|
147
|
+
multiline,
|
|
148
|
+
multilineResizable,
|
|
149
|
+
type,
|
|
150
|
+
inputProps,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const rootClassName = getRootClassName({
|
|
154
|
+
size,
|
|
155
|
+
width,
|
|
156
|
+
type,
|
|
157
|
+
layout,
|
|
158
|
+
isDark,
|
|
159
|
+
multiline,
|
|
160
|
+
highlight,
|
|
161
|
+
disabled,
|
|
162
|
+
className,
|
|
163
|
+
classes,
|
|
164
|
+
isError,
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
const multilineProps = multiline
|
|
168
|
+
? ({
|
|
169
|
+
multiline: true,
|
|
170
|
+
// to keep the same behavior as in MUI@4
|
|
171
|
+
// rows: getRows(rows),
|
|
172
|
+
minRows: getRows(rows),
|
|
173
|
+
maxRows: getRows(rowsMax),
|
|
174
|
+
} as const)
|
|
175
|
+
: {}
|
|
176
|
+
|
|
192
177
|
return (
|
|
193
|
-
<
|
|
178
|
+
<Input
|
|
194
179
|
{...rest}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
classes
|
|
200
|
-
{
|
|
201
|
-
[`${classes.hidden}`]: type === 'hidden',
|
|
202
|
-
[classes.rootDark]: isDark,
|
|
203
|
-
[classes.highlightAutofill]: highlight === 'autofill',
|
|
204
|
-
[classes.horizontalLayout]: layout === 'horizontal',
|
|
205
|
-
[classes.error]: Boolean(status === 'error' || error),
|
|
206
|
-
}
|
|
207
|
-
),
|
|
208
|
-
input: cx(classes.input, classes[`input${capitalize(size)}`], {
|
|
209
|
-
[classes.inputDark]: isDark,
|
|
210
|
-
}),
|
|
211
|
-
inputMultiline: classes.inputMultiline,
|
|
212
|
-
notchedOutline: cx(classes.notchedOutline, {
|
|
213
|
-
[classes.notchedOutlineDark]: isDark,
|
|
214
|
-
}),
|
|
215
|
-
focused: classes.focused,
|
|
216
|
-
}}
|
|
217
|
-
className={cx(
|
|
218
|
-
{
|
|
219
|
-
[classes.error]: Boolean(status === 'error' || error),
|
|
180
|
+
slots={{ input: inputComponent, textarea: Textarea }}
|
|
181
|
+
slotProps={{
|
|
182
|
+
root: {
|
|
183
|
+
ref: divRef,
|
|
184
|
+
className: twMerge(rootClassName, classes?.root, className),
|
|
220
185
|
},
|
|
221
|
-
|
|
222
|
-
|
|
186
|
+
input: {
|
|
187
|
+
...inputProps,
|
|
188
|
+
ref: inputRef,
|
|
189
|
+
className: twMerge(
|
|
190
|
+
inputClassName,
|
|
191
|
+
classes?.input,
|
|
192
|
+
inputProps?.className
|
|
193
|
+
),
|
|
194
|
+
type,
|
|
195
|
+
'aria-invalid': isError,
|
|
196
|
+
},
|
|
197
|
+
}}
|
|
223
198
|
style={style}
|
|
224
|
-
|
|
225
|
-
fullWidth={width === 'full'}
|
|
226
|
-
error={Boolean(status === 'error' || error)}
|
|
227
|
-
inputComponent={inputComponent}
|
|
228
|
-
inputProps={inputProps}
|
|
229
|
-
ref={ref}
|
|
230
|
-
inputRef={inputRef}
|
|
199
|
+
error={isError}
|
|
231
200
|
defaultValue={defaultValue}
|
|
232
201
|
value={value}
|
|
233
|
-
type={type}
|
|
234
202
|
startAdornment={startAdornment}
|
|
235
203
|
endAdornment={endAdornment}
|
|
236
|
-
multiline={multiline}
|
|
237
204
|
autoFocus={autoFocus}
|
|
238
|
-
minRows={rows}
|
|
239
|
-
maxRows={rowsMax}
|
|
240
205
|
onChange={onChange}
|
|
241
206
|
disabled={disabled}
|
|
207
|
+
{...multilineProps}
|
|
242
208
|
/>
|
|
243
209
|
)
|
|
244
210
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { OmitInternalProps } from '@toptal/picasso-shared'
|
|
2
2
|
|
|
3
|
-
import type { Props } from './
|
|
3
|
+
import type { Props } from './types'
|
|
4
4
|
|
|
5
5
|
export { default as OutlinedInput } from './OutlinedInput'
|
|
6
6
|
export type OutlinedInputProps = OmitInternalProps<Props>
|
|
7
7
|
export * from './OutlinedInput'
|
|
8
|
+
export type { Status, BaseInputProps, InputProps, Size, Props } from './types'
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getInputClassName,
|
|
3
|
+
classesBySize,
|
|
4
|
+
fontColorClasses,
|
|
5
|
+
inputClasses,
|
|
6
|
+
placeholderClasses,
|
|
7
|
+
getFontColorClass,
|
|
8
|
+
} from './stylesInput'
|
|
9
|
+
import type { Size } from './types'
|
|
10
|
+
|
|
11
|
+
describe('getInputClassName', () => {
|
|
12
|
+
const baseProps = {
|
|
13
|
+
isDark: false,
|
|
14
|
+
size: 'medium' as Size,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('when determining the basic input classes', () => {
|
|
18
|
+
it('always includes basic input classes', () => {
|
|
19
|
+
const result = getInputClassName(baseProps)
|
|
20
|
+
|
|
21
|
+
expect(result).toContainEqual(inputClasses)
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('when determining classes based on size', () => {
|
|
26
|
+
it.each([
|
|
27
|
+
['small', classesBySize.small],
|
|
28
|
+
['medium', classesBySize.medium],
|
|
29
|
+
['large', classesBySize.large],
|
|
30
|
+
])('returns the correct class for size "%s"', (size, expectedClass) => {
|
|
31
|
+
const result = getInputClassName({ ...baseProps, size: size as Size })
|
|
32
|
+
|
|
33
|
+
expect(result).toContain(expectedClass)
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
describe('when determining font color', () => {
|
|
38
|
+
describe('when isDark is true', () => {
|
|
39
|
+
it('returns font color class as "text-white"', () => {
|
|
40
|
+
const result = getInputClassName({ ...baseProps, isDark: true })
|
|
41
|
+
|
|
42
|
+
expect(result).toContain(fontColorClasses.dark)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('when type is "time" and inputPropsDisabled is true', () => {
|
|
47
|
+
it('returns font color class as "text-black" for timepicker', () => {
|
|
48
|
+
const result = getInputClassName({
|
|
49
|
+
...baseProps,
|
|
50
|
+
type: 'time',
|
|
51
|
+
inputProps: { disabled: true },
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
expect(result).toContain(fontColorClasses.timepicker)
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe('when disabled is true', () => {
|
|
59
|
+
it('returns font color class as "text-gray-600"', () => {
|
|
60
|
+
const result = getInputClassName({ ...baseProps, disabled: true })
|
|
61
|
+
|
|
62
|
+
expect(result).toContainEqual(fontColorClasses.disabled)
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
describe('default case', () => {
|
|
67
|
+
it('returns font color class as "text-black"', () => {
|
|
68
|
+
const result = getInputClassName(baseProps)
|
|
69
|
+
|
|
70
|
+
expect(result).toContain(fontColorClasses.default)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('when determining placeholder classes', () => {
|
|
76
|
+
describe('when isDark is true', () => {
|
|
77
|
+
it('returns dark mode placeholder classes', () => {
|
|
78
|
+
const result = getInputClassName({ ...baseProps, isDark: true })
|
|
79
|
+
|
|
80
|
+
expect(result).toContainEqual(placeholderClasses.dark)
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
describe('default case', () => {
|
|
85
|
+
it('returns default placeholder classes', () => {
|
|
86
|
+
const result = getInputClassName(baseProps)
|
|
87
|
+
|
|
88
|
+
expect(result).toContainEqual(placeholderClasses.default)
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
describe('when determining additional classes', () => {
|
|
94
|
+
describe('when multiline and multilineResizable', () => {
|
|
95
|
+
it('includes "resize-y" class', () => {
|
|
96
|
+
const result = getInputClassName({
|
|
97
|
+
...baseProps,
|
|
98
|
+
multiline: true,
|
|
99
|
+
multilineResizable: true,
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
expect(result).toContain('resize-y')
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
describe('default case', () => {
|
|
107
|
+
it('does not include "resize-y" class', () => {
|
|
108
|
+
const result = getInputClassName(baseProps)
|
|
109
|
+
|
|
110
|
+
expect(result).not.toContain('resize-y')
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
describe('getFontColorClass', () => {
|
|
117
|
+
describe('when isDark is true', () => {
|
|
118
|
+
it('returns "text-white"', () => {
|
|
119
|
+
const result = getFontColorClass({ isDark: true })
|
|
120
|
+
|
|
121
|
+
expect(result).toBe(fontColorClasses.dark)
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
describe('when type is "time" and inputPropsDisabled is true', () => {
|
|
126
|
+
it('returns "text-black" for timepicker', () => {
|
|
127
|
+
const result = getFontColorClass({
|
|
128
|
+
isDark: false,
|
|
129
|
+
type: 'time',
|
|
130
|
+
inputPropsDisabled: true,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
expect(result).toBe(fontColorClasses.timepicker)
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
describe('when disabled is true', () => {
|
|
138
|
+
it('returns an array including "text-gray-600"', () => {
|
|
139
|
+
const result = getFontColorClass({ isDark: false, disabled: true })
|
|
140
|
+
|
|
141
|
+
expect(result).toEqual(fontColorClasses.disabled)
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
describe('default case', () => {
|
|
146
|
+
it('returns "text-black"', () => {
|
|
147
|
+
const result = getFontColorClass({ isDark: false })
|
|
148
|
+
|
|
149
|
+
expect(result).toBe(fontColorClasses.default)
|
|
150
|
+
})
|
|
151
|
+
})
|
|
152
|
+
})
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Size, Props } from './types'
|
|
2
|
+
|
|
3
|
+
export const classesBySize: Record<Size, string> = {
|
|
4
|
+
small: 'text-xxs leading-4',
|
|
5
|
+
medium: 'text-md leading-4',
|
|
6
|
+
large: 'text-lg leading-4',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const fontColorClasses = {
|
|
10
|
+
dark: 'text-white',
|
|
11
|
+
disabled: [
|
|
12
|
+
'text-gray-600',
|
|
13
|
+
// On Safari the text gets a bit lighter as if it had some transparency applied to it
|
|
14
|
+
// We need this webkit-specific property to achieve the exact font color
|
|
15
|
+
'[&::-webkit-text-fill-color]:text-gray-600',
|
|
16
|
+
] as string[],
|
|
17
|
+
default: 'text-black',
|
|
18
|
+
timepicker: 'text-black',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const getFontColorClass = ({
|
|
22
|
+
isDark,
|
|
23
|
+
disabled,
|
|
24
|
+
type,
|
|
25
|
+
inputPropsDisabled,
|
|
26
|
+
}: {
|
|
27
|
+
isDark: boolean
|
|
28
|
+
disabled?: boolean
|
|
29
|
+
type?: string
|
|
30
|
+
inputPropsDisabled?: boolean
|
|
31
|
+
}) => {
|
|
32
|
+
if (isDark) {
|
|
33
|
+
return fontColorClasses.dark
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (type === 'time' && inputPropsDisabled) {
|
|
37
|
+
// It's a special case for TimePicker
|
|
38
|
+
return fontColorClasses.timepicker
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (disabled) {
|
|
42
|
+
return fontColorClasses.disabled
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return fontColorClasses.default
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const placeholderClasses = {
|
|
49
|
+
default: ['[&::placeholder]:text-gray-600', '[&::placeholder]:opacity-100'],
|
|
50
|
+
dark: ['[&::placeholder]:text-white', '[&::placeholder]:opacity-[0.64]'],
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const inputClasses = [
|
|
54
|
+
'[&::-webkit-calendar-picker-indicator]:bg-none',
|
|
55
|
+
'bg-transparent',
|
|
56
|
+
'border-none',
|
|
57
|
+
'box-border',
|
|
58
|
+
'cursor-[inherit]',
|
|
59
|
+
'h-full',
|
|
60
|
+
'outline-none',
|
|
61
|
+
'p-0',
|
|
62
|
+
'peer',
|
|
63
|
+
'resize-none',
|
|
64
|
+
'resize-none',
|
|
65
|
+
'w-full',
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
export const getInputClassName = ({
|
|
69
|
+
size,
|
|
70
|
+
disabled,
|
|
71
|
+
isDark,
|
|
72
|
+
multiline,
|
|
73
|
+
multilineResizable,
|
|
74
|
+
type,
|
|
75
|
+
inputProps,
|
|
76
|
+
}: Partial<Props> & { isDark: boolean; size: Size }) => [
|
|
77
|
+
inputClasses,
|
|
78
|
+
classesBySize[size],
|
|
79
|
+
getFontColorClass({
|
|
80
|
+
isDark,
|
|
81
|
+
disabled,
|
|
82
|
+
type,
|
|
83
|
+
inputPropsDisabled: inputProps?.disabled,
|
|
84
|
+
}),
|
|
85
|
+
isDark ? placeholderClasses.dark : placeholderClasses.default,
|
|
86
|
+
multiline && multilineResizable && 'resize-y',
|
|
87
|
+
]
|