@awsui/components-react
Version:
On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en
117 lines • 7.12 kB
JavaScript
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useRef } from 'react';
import clsx from 'clsx';
import { useMergeRefs } from '@awsui/component-toolkit/internal';
import { copyAnalyticsMetadataAttribute, getAnalyticsMetadataAttribute, } from '@awsui/component-toolkit/internal/analytics-metadata';
import InternalButton from '../button/internal';
import { useInternalI18n } from '../i18n/context';
import InternalIcon from '../icon/internal';
import { getBaseProps } from '../internal/base-component';
import { useFormFieldContext } from '../internal/context/form-field-context';
import { fireKeyboardEvent, fireNonCancelableEvent } from '../internal/events';
import { useDebounceCallback } from '../internal/hooks/use-debounce-callback';
import WithNativeAttributes from '../internal/utils/with-native-attributes';
import { getInputStyles } from './styles';
import { convertAutoComplete, useSearchProps } from './utils';
import styles from './styles.css.js';
function InternalInput({ type = 'text', step, inputMode, autoComplete = true, ariaLabel, clearAriaLabel: clearAriaLabelOverride, name, value, placeholder, autoFocus, disabled, readOnly, disableBrowserAutocorrect, spellcheck, __noBorderRadius, __leftIcon, __leftIconVariant = 'subtle', __onLeftIconClick, ariaRequired, __rightIcon, __onRightIconClick, onKeyDown, onKeyUp, onChange, __onDelayedInput, __onBlurWithDetail, onBlur, onFocus, nativeInputAttributes, __internalRootRef, __inheritFormFieldProps, __injectAnalyticsComponentMetadata, __skipNativeAttributesWarnings, style, ...rest }, ref) {
const baseProps = getBaseProps(rest);
const i18n = useInternalI18n('input');
const fireDelayedInput = useDebounceCallback((value) => fireNonCancelableEvent(__onDelayedInput, { value }));
const handleChange = (value) => {
fireDelayedInput(value);
fireNonCancelableEvent(onChange, { value });
};
const inputRef = useRef(null);
const searchProps = useSearchProps(type, disabled, readOnly, value, inputRef, handleChange);
__leftIcon = __leftIcon !== null && __leftIcon !== void 0 ? __leftIcon : searchProps.__leftIcon;
__rightIcon = __rightIcon !== null && __rightIcon !== void 0 ? __rightIcon : searchProps.__rightIcon;
__onRightIconClick = __onRightIconClick !== null && __onRightIconClick !== void 0 ? __onRightIconClick : searchProps.__onRightIconClick;
const formFieldContext = useFormFieldContext(rest);
const { ariaLabelledby, ariaDescribedby, controlId, invalid, warning } = __inheritFormFieldProps
? formFieldContext
: rest;
const attributes = {
'aria-label': ariaLabel,
// aria-labelledby has precedence over aria-label in accessible name calculation.
// When aria-label is provided for Input, it should override aria-labelledBy from form-field context.
// If both aria-label and aria-labelledby come from Input props, aria-labelledby will be used in accessible name
'aria-labelledby': ariaLabel && !rest.ariaLabelledby ? undefined : ariaLabelledby,
'aria-describedby': ariaDescribedby,
name,
placeholder,
autoFocus,
id: controlId,
className: clsx(styles.input, type && styles[`input-type-${type}`], __rightIcon && styles['input-has-icon-right'], __leftIcon && styles['input-has-icon-left'], __noBorderRadius && styles['input-has-no-border-radius'], {
[styles['input-readonly']]: readOnly,
[styles['input-invalid']]: invalid,
[styles['input-warning']]: warning && !invalid,
}),
autoComplete: convertAutoComplete(autoComplete),
disabled,
readOnly,
type,
step,
inputMode,
spellCheck: spellcheck,
onKeyDown: onKeyDown && (event => fireKeyboardEvent(onKeyDown, event)),
onKeyUp: onKeyUp && (event => fireKeyboardEvent(onKeyUp, event)),
// We set a default value on the component in order to force it into the controlled mode.
value: value !== null && value !== void 0 ? value : '',
onChange: onChange && (event => handleChange(event.target.value)),
onBlur: e => {
fireNonCancelableEvent(onBlur);
fireNonCancelableEvent(__onBlurWithDetail, { relatedTarget: e.relatedTarget });
},
onFocus: onFocus && (() => fireNonCancelableEvent(onFocus)),
};
if (type === 'number') {
// Chrome and Safari have a weird built-in behavior of letting focused
// number inputs be controlled by scrolling on them. However, they don't
// lock the browser's scroll, so it's very easy to accidentally increment
// the input while scrolling down the page.
attributes.onWheel = event => event.currentTarget.blur();
}
if (disableBrowserAutocorrect) {
attributes.autoCorrect = 'off';
attributes.autoCapitalize = 'off';
}
// ensure aria properties are string literal "true"
if (ariaRequired) {
attributes['aria-required'] = 'true';
}
if (invalid) {
attributes['aria-invalid'] = 'true';
}
const mergedRef = useMergeRefs(ref, inputRef);
// type = "visualSearch" renders a type="text' input
if (attributes.type === 'visualSearch') {
attributes.type = 'text';
}
const componentAnalyticsMetadata = {
name: 'awsui.Input',
label: 'input',
properties: {
value: value || '',
},
};
return (React.createElement("div", { ...baseProps, className: clsx(baseProps.className, styles['input-container']), ref: __internalRootRef, dir: type === 'email' ? 'ltr' : undefined, ...(__injectAnalyticsComponentMetadata
? getAnalyticsMetadataAttribute({ component: componentAnalyticsMetadata })
: copyAnalyticsMetadataAttribute(rest)) },
__leftIcon && (React.createElement("span", { onClick: __onLeftIconClick, className: styles['input-icon-left'] },
React.createElement(InternalIcon, { name: __leftIcon, variant: disabled || readOnly ? 'disabled' : __leftIconVariant }))),
React.createElement(WithNativeAttributes, { ...attributes, tag: "input", componentName: "Input", nativeAttributes: nativeInputAttributes, skipWarnings: __skipNativeAttributesWarnings, ref: mergedRef, style: getInputStyles(style) }),
__rightIcon && (React.createElement("span", { className: styles['input-icon-right'], ...(__rightIcon === 'close'
? getAnalyticsMetadataAttribute({
action: 'clearInput',
})
: {}) },
React.createElement(InternalButton
// Used for test utils
, {
// Used for test utils
className: styles['input-button-right'], variant: "inline-icon-pointer-target", formAction: "none", iconName: __rightIcon, onClick: __onRightIconClick, ariaLabel: i18n('clearAriaLabel', clearAriaLabelOverride), disabled: disabled })))));
}
export default React.forwardRef(InternalInput);
//# sourceMappingURL=internal.js.map