UNPKG

@cimpress/react-components

Version:
220 lines (212 loc) 7.46 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import React, { useEffect, useState } from 'react'; import { css, cx } from '@emotion/css'; import { useMemoizedId } from './utils'; import cvar from './theme/cvar'; import SuccessSvg from './icons/SuccessSvg'; import WarningSvg from './icons/WarningSvg'; import ErrorSvg from './icons/ErrorSvg'; const isTextTruthy = (val) => val !== undefined && val !== null && val.toString() !== ''; export const formGroupCss = css ` position: relative; margin-bottom: ${cvar('spacing-16')}; input { box-shadow: none; padding: ${cvar('spacing-16')}; transition: all 0.2s ease-out; &:focus { outline: none; box-shadow: none; border-color: ${cvar('color-border-interactive')}; } } textarea { box-shadow: none; padding: ${cvar('spacing-24')} ${cvar('spacing-16')} ${cvar('spacing-12')}; height: auto; &:focus { outline: none; box-shadow: none; border-color: ${cvar('color-border-interactive')}; } } label { color: ${cvar('color-text-label')}; font-weight: normal; position: absolute; left: ${cvar('spacing-16')}; top: ${cvar('spacing-16')}; line-height: 16px; margin-bottom: 0; transition: all 0.2s ease-out; z-index: 5; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; max-width: 90%; } `; export const formGroupActiveCss = css ` input { padding: ${cvar('spacing-24')} ${cvar('spacing-16')} ${cvar('spacing-8')}; } textarea { padding-top: ${cvar('spacing-24')}; } label { top: ${cvar('spacing-4')}; font-size: 12px; } `; export const controlLabelCss = css ` margin-bottom: 0; font-size: inherit; line-height: 1.5; `; const textAreaLabel = css ` top: 1px; z-index: 5; background-color: ${cvar('color-background')}; padding: 4px; `; const isRequired = css ` label:after { content: ' *'; color: ${cvar('color-required-asterisk')}; } `; const isDisabled = css ` input { color: ${cvar('color-text-label')}; background: ${cvar('color-textfield-disabled')}; } `; const formControl = css ` height: ${cvar('spacing-48')}; border: 1px solid ${cvar('color-border-default')}; `; const inputGroup = css ` zindex: 0; position: relative; display: flex; flex-wrap: wrap; align-items: stretch; width: 100%; > .crc-text-field { position: relative; flex: 1 1 auto; width: 1%; margin-bottom: 0; + .crc-text-field { margin-left: 1px; } } `; const inputGroupButton = css ` > button { padding: ${cvar('spacing-12')} ${cvar('spacing-24')}; border-bottom-right-radius: ${cvar('spacing-2')}; border-top-right-radius: ${cvar('spacing-2')}; line-height: 18px; height: ${cvar('spacing-48')}; border-bottom-left-radius: 0px; border-top-left-radius: 0px; } `; const helpBlock = css ` display: block; margin-top: ${cvar('spacing-4')}; `; const textfieldColorMap = { success: 'color-border-success', warning: 'color-border-warning', error: 'color-border-error', }; const statusIconSvg = { success: React.createElement(SuccessSvg, null), warning: React.createElement(WarningSvg, null), error: React.createElement(ErrorSvg, null), }; const statusCss = (status) => css ` input { box-shadow: none; padding-right: ${cvar('spacing-32')}; &:focus { border-color: ${cvar(textfieldColorMap[status])}; } } .crc-text-field { border-color: ${cvar(textfieldColorMap[status])}; } svg { position: absolute; right: ${cvar('spacing-12')}; top: ${cvar('spacing-16')}; color: ${cvar(textfieldColorMap[status])}; transition: all 0.2s ease-out; } `; const TextInputBase = React.forwardRef((_a, ref) => { var { autoFocus, className, disabled, helpText, id, inputStyle, label, name, onBlur, onChange, onClick, onFocus, onKeyDown, placeholder, required, rightAddon, status, style, type, value, pattern } = _a, rest = __rest(_a, ["autoFocus", "className", "disabled", "helpText", "id", "inputStyle", "label", "name", "onBlur", "onChange", "onClick", "onFocus", "onKeyDown", "placeholder", "required", "rightAddon", "status", "style", "type", "value", "pattern"]); const [float, setFloat] = useState(isTextTruthy(value)); const uniqueId = useMemoizedId({ label: `${name}-${placeholder}-${label}`, id }); useEffect(() => { setFloat(isTextTruthy(value)); }, [setFloat, value]); const handleBlur = (e) => { setFloat(isTextTruthy(value)); onBlur && onBlur(e); }; const handleFocus = (e) => { setFloat(true); onFocus && onFocus(e); }; const handleChange = (e) => { const isValid = !pattern || !!e.target.value.match(new RegExp(`^${pattern}$`)); onChange && onChange(Object.assign(Object.assign({}, e), { isValid })); }; const inputId = id || uniqueId; const isTextArea = type === 'textarea'; const wrapperClassNames = cx('crc-text-input', formGroupCss, className, { [formGroupActiveCss]: !!label && float, [statusCss(status)]: !!status, [isRequired]: !!required, [isDisabled]: !!disabled, }); const inputProps = Object.assign(Object.assign({}, rest), { autoFocus, disabled, id: inputId, name, onBlur: handleBlur, onChange: handleChange, onClick, onFocus: handleFocus, onKeyDown, placeholder, required, style: inputStyle, value, pattern, type: !isTextArea ? type : undefined }); const inputElement = isTextArea ? (React.createElement("textarea", Object.assign({}, inputProps, { className: cx(formControl, 'crc-text-field'), ref: ref }))) : (React.createElement("input", Object.assign({}, inputProps, { className: cx(formControl, 'crc-text-field'), ref: ref }))); const labelElement = label ? (React.createElement("label", { className: cx(controlLabelCss, { [textAreaLabel]: isTextArea }), htmlFor: inputId, title: label }, label)) : null; return (React.createElement("div", { className: wrapperClassNames, style: style }, React.createElement("div", { className: inputGroup }, inputElement, labelElement, rightAddon && React.createElement("span", { className: inputGroupButton }, rightAddon)), !!status && statusIconSvg[status], helpText ? React.createElement("small", { className: helpBlock }, helpText) : null)); }); TextInputBase.displayName = 'TextField'; TextInputBase.defaultProps = { autoFocus: false, className: '', disabled: false, required: false, type: 'text', value: '', }; export const TextField = React.forwardRef((props, ref) => (React.createElement(TextInputBase, Object.assign({}, props, { onChange: props.onChange, ref: ref })))); export const TextArea = React.forwardRef((props, ref) => (React.createElement(TextInputBase, Object.assign({}, props, { type: "textarea", onChange: props.onChange, ref: ref })))); //# sourceMappingURL=TextInput.js.map