@react-spectrum/textfield 3.0.0-nightly-641446f65-240905

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.
@@ -0,0 +1,97 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {chain, useLayoutEffect} from '@react-aria/utils';
14
+ import React, {Ref, useCallback, useRef} from 'react';
15
+ import {SpectrumTextAreaProps, TextFieldRef} from '@react-types/textfield';
16
+ import {TextFieldBase} from './TextFieldBase';
17
+ import {useControlledState} from '@react-stately/utils';
18
+ import {useFormProps} from '@react-spectrum/form';
19
+ import {useProviderProps} from '@react-spectrum/provider';
20
+ import {useTextField} from '@react-aria/textfield';
21
+
22
+ function TextArea(props: SpectrumTextAreaProps, ref: Ref<TextFieldRef<HTMLTextAreaElement>>) {
23
+ props = useProviderProps(props);
24
+ props = useFormProps(props);
25
+ let {
26
+ isDisabled = false,
27
+ isQuiet = false,
28
+ isReadOnly = false,
29
+ isRequired = false,
30
+ onChange,
31
+ ...otherProps
32
+ } = props;
33
+
34
+ // not in stately because this is so we know when to re-measure, which is a spectrum design
35
+ let [inputValue, setInputValue] = useControlledState(props.value, props.defaultValue ?? '', () => {});
36
+ let inputRef = useRef<HTMLTextAreaElement>(null);
37
+
38
+ let onHeightChange = useCallback(() => {
39
+ // Quiet textareas always grow based on their text content.
40
+ // Standard textareas also grow by default, unless an explicit height is set.
41
+ if ((isQuiet || !props.height) && inputRef.current) {
42
+ let input = inputRef.current;
43
+ let prevAlignment = input.style.alignSelf;
44
+ let prevOverflow = input.style.overflow;
45
+ // Firefox scroll position is lost when overflow: 'hidden' is applied so we skip applying it.
46
+ // The measure/applied height is also incorrect/reset if we turn on and off
47
+ // overflow: hidden in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1787062
48
+ let isFirefox = 'MozAppearance' in input.style;
49
+ if (!isFirefox) {
50
+ input.style.overflow = 'hidden';
51
+ }
52
+ input.style.alignSelf = 'start';
53
+ input.style.height = 'auto';
54
+ // offsetHeight - clientHeight accounts for the border/padding.
55
+ input.style.height = `${input.scrollHeight + (input.offsetHeight - input.clientHeight)}px`;
56
+ input.style.overflow = prevOverflow;
57
+ input.style.alignSelf = prevAlignment;
58
+ }
59
+ }, [isQuiet, inputRef, props.height]);
60
+
61
+ useLayoutEffect(() => {
62
+ if (inputRef.current) {
63
+ onHeightChange();
64
+ }
65
+ }, [onHeightChange, inputValue, inputRef]);
66
+
67
+ if (props.placeholder) {
68
+ console.warn('Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/TextArea.html#help-text');
69
+ }
70
+
71
+ let result = useTextField({
72
+ ...props,
73
+ onChange: chain(onChange, setInputValue),
74
+ inputElementType: 'textarea'
75
+ }, inputRef);
76
+
77
+ return (
78
+ <TextFieldBase
79
+ {...otherProps}
80
+ ref={ref}
81
+ inputRef={inputRef}
82
+ {...result}
83
+ multiLine
84
+ isDisabled={isDisabled}
85
+ isQuiet={isQuiet}
86
+ isReadOnly={isReadOnly}
87
+ isRequired={isRequired} />
88
+ );
89
+ }
90
+
91
+ /**
92
+ * TextAreas are multiline text inputs, useful for cases where users have
93
+ * a sizable amount of text to enter. They allow for all customizations that
94
+ * are available to text fields.
95
+ */
96
+ let _TextArea = React.forwardRef(TextArea);
97
+ export {_TextArea as TextArea};
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import React, {forwardRef, Ref, useRef} from 'react';
14
+ import {SpectrumTextFieldProps, TextFieldRef} from '@react-types/textfield';
15
+ import {TextFieldBase} from './TextFieldBase';
16
+ import {useFormProps} from '@react-spectrum/form';
17
+ import {useProviderProps} from '@react-spectrum/provider';
18
+ import {useTextField} from '@react-aria/textfield';
19
+
20
+ function TextField(props: SpectrumTextFieldProps, ref: Ref<TextFieldRef>) {
21
+ props = useProviderProps(props);
22
+ props = useFormProps(props);
23
+
24
+ let inputRef = useRef<HTMLInputElement>(null);
25
+ let result = useTextField(props, inputRef);
26
+
27
+ if (props.placeholder) {
28
+ console.warn('Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/TextField.html#help-text');
29
+ }
30
+
31
+ return (
32
+ <TextFieldBase
33
+ {...props}
34
+ {...result}
35
+ ref={ref}
36
+ inputRef={inputRef} />
37
+ );
38
+ }
39
+
40
+ /**
41
+ * TextFields are text inputs that allow users to input custom text entries
42
+ * with a keyboard. Various decorations can be displayed around the field to
43
+ * communicate the entry requirements.
44
+ */
45
+ const _TextField = forwardRef(TextField);
46
+ export {_TextField as TextField};
@@ -0,0 +1,169 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import AlertMedium from '@spectrum-icons/ui/AlertMedium';
14
+ import CheckmarkMedium from '@spectrum-icons/ui/CheckmarkMedium';
15
+ import {classNames, createFocusableRef} from '@react-spectrum/utils';
16
+ import {Field} from '@react-spectrum/label';
17
+ import {mergeProps} from '@react-aria/utils';
18
+ import {PressEvents, RefObject, ValidationResult} from '@react-types/shared';
19
+ import React, {cloneElement, forwardRef, HTMLAttributes, InputHTMLAttributes, LabelHTMLAttributes, ReactElement, Ref, TextareaHTMLAttributes, useImperativeHandle, useRef} from 'react';
20
+ import {SpectrumTextFieldProps, TextFieldRef} from '@react-types/textfield';
21
+ import styles from '@adobe/spectrum-css-temp/components/textfield/vars.css';
22
+ import {useFocusRing} from '@react-aria/focus';
23
+ import {useHover} from '@react-aria/interactions';
24
+
25
+ interface TextFieldBaseProps extends Omit<SpectrumTextFieldProps, 'onChange' | 'validate'>, PressEvents, Partial<ValidationResult> {
26
+ wrapperChildren?: ReactElement | ReactElement[],
27
+ inputClassName?: string,
28
+ validationIconClassName?: string,
29
+ multiLine?: boolean,
30
+ labelProps?: LabelHTMLAttributes<HTMLLabelElement>,
31
+ inputProps: InputHTMLAttributes<HTMLInputElement> | TextareaHTMLAttributes<HTMLTextAreaElement>,
32
+ descriptionProps?: HTMLAttributes<HTMLElement>,
33
+ errorMessageProps?: HTMLAttributes<HTMLElement>,
34
+ inputRef?: RefObject<HTMLInputElement | HTMLTextAreaElement | null>,
35
+ loadingIndicator?: ReactElement,
36
+ isLoading?: boolean,
37
+ disableFocusRing?: boolean
38
+ }
39
+
40
+ function TextFieldBase(props: TextFieldBaseProps, ref: Ref<TextFieldRef<HTMLInputElement | HTMLTextAreaElement>>) {
41
+ let {
42
+ validationState = props.isInvalid ? 'invalid' : null,
43
+ icon,
44
+ isQuiet = false,
45
+ isDisabled,
46
+ multiLine,
47
+ autoFocus,
48
+ inputClassName,
49
+ wrapperChildren,
50
+ labelProps,
51
+ inputProps,
52
+ descriptionProps,
53
+ errorMessageProps,
54
+ inputRef: userInputRef,
55
+ isLoading,
56
+ loadingIndicator,
57
+ validationIconClassName,
58
+ disableFocusRing
59
+ } = props;
60
+ let {hoverProps, isHovered} = useHover({isDisabled});
61
+ let domRef = useRef<HTMLDivElement>(null);
62
+ let defaultInputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);
63
+ let inputRef = userInputRef || defaultInputRef;
64
+
65
+ // Expose imperative interface for ref
66
+ useImperativeHandle(ref, () => ({
67
+ ...createFocusableRef(domRef, inputRef),
68
+ select() {
69
+ if (inputRef.current) {
70
+ inputRef.current.select();
71
+ }
72
+ },
73
+ getInputElement() {
74
+ return inputRef.current;
75
+ }
76
+ }));
77
+
78
+ let ElementType: React.ElementType = multiLine ? 'textarea' : 'input';
79
+ let isInvalid = validationState === 'invalid' && !isDisabled;
80
+
81
+ if (icon) {
82
+ let UNSAFE_className = classNames(
83
+ styles,
84
+ icon.props && (icon.props as any).UNSAFE_className,
85
+ 'spectrum-Textfield-icon'
86
+ );
87
+
88
+ icon = cloneElement(icon, {
89
+ UNSAFE_className,
90
+ size: 'S'
91
+ } as any);
92
+ }
93
+
94
+ let validationIcon = isInvalid ? <AlertMedium /> : <CheckmarkMedium />;
95
+ let validation = cloneElement(validationIcon, {
96
+ UNSAFE_className: classNames(
97
+ styles,
98
+ 'spectrum-Textfield-validationIcon',
99
+ validationIconClassName
100
+ )
101
+ });
102
+
103
+ let {focusProps, isFocusVisible} = useFocusRing({
104
+ isTextInput: true,
105
+ autoFocus
106
+ });
107
+
108
+ let textField = (
109
+ <div
110
+ className={
111
+ classNames(
112
+ styles,
113
+ 'spectrum-Textfield',
114
+ {
115
+ 'spectrum-Textfield--invalid': isInvalid,
116
+ 'spectrum-Textfield--valid': validationState === 'valid' && !isDisabled,
117
+ 'spectrum-Textfield--loadable': loadingIndicator,
118
+ 'spectrum-Textfield--quiet': isQuiet,
119
+ 'spectrum-Textfield--multiline': multiLine,
120
+ 'focus-ring': !disableFocusRing && isFocusVisible
121
+ }
122
+ )
123
+ }>
124
+ <ElementType
125
+ {...mergeProps(inputProps, hoverProps, focusProps)}
126
+ ref={inputRef as any}
127
+ rows={multiLine ? 1 : undefined}
128
+ className={
129
+ classNames(
130
+ styles,
131
+ 'spectrum-Textfield-input',
132
+ {
133
+ 'spectrum-Textfield-inputIcon': icon,
134
+ 'is-hovered': isHovered
135
+ },
136
+ inputClassName
137
+ )
138
+ } />
139
+ {icon}
140
+ {validationState && !isLoading && !isDisabled ? validation : null}
141
+ {isLoading && loadingIndicator}
142
+ {wrapperChildren}
143
+ </div>
144
+ );
145
+
146
+ return (
147
+ <Field
148
+ {...props}
149
+ labelProps={labelProps}
150
+ descriptionProps={descriptionProps}
151
+ errorMessageProps={errorMessageProps}
152
+ wrapperClassName={
153
+ classNames(
154
+ styles,
155
+ 'spectrum-Textfield-wrapper',
156
+ {
157
+ 'spectrum-Textfield-wrapper--quiet': isQuiet
158
+ }
159
+ )
160
+ }
161
+ showErrorIcon={false}
162
+ ref={domRef}>
163
+ {textField}
164
+ </Field>
165
+ );
166
+ }
167
+
168
+ const _TextFieldBase = forwardRef(TextFieldBase);
169
+ export {_TextFieldBase as TextFieldBase};
package/src/index.ts ADDED
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ /// <reference types="css-module-types" />
14
+
15
+ export {TextArea} from './TextArea';
16
+ export {TextField} from './TextField';
17
+ export {TextFieldBase} from './TextFieldBase';
18
+ export type {SpectrumTextFieldProps, SpectrumTextAreaProps} from '@react-types/textfield';