UNPKG

@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
// 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