vcc-ui
Version:
A React library for building user interfaces at Volvo Cars
212 lines (210 loc) • 6.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TextInput = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _propTypes = require("prop-types");
var _react = _interopRequireDefault(require("react"));
var _reactFela = require("react-fela");
var _autoId = require("../../utils/auto-id");
var _block = require("../block");
var _flex = require("../flex");
var _message = require("../message");
var _spacer = require("../spacer");
var _spinner = require("../spinner");
const defaultStyles = _ref => {
let {
theme,
disabled,
loading,
isValid
} = _ref;
return {
appearance: 'none',
borderWidth: 1,
borderStyle: 'solid',
borderRadius: 4,
boxSizing: 'border-box',
display: 'block',
width: '100%',
margin: 0,
outlineWidth: 0,
paddingTop: theme.tokens.inputPaddingVertical * 2,
paddingBottom: theme.tokens.inputPaddingVertical / 2,
paddingLeft: theme.tokens.inputPaddingHorizontal - 1,
paddingRight: theme.tokens.inputPaddingHorizontal - 1,
borderColor: theme.tokens.inputBorder,
color: theme.tokens.inputForeground,
background: theme.tokens.inputBackground,
...theme.typeScale.columbus.standard.styles,
'::placeholder': {
color: 'transparent'
},
'&[type="date"][value=""]:not(:focus)': {
color: 'transparent'
},
':focus': {
borderColor: theme.tokens.inputBorderFocus,
'::placeholder': {
color: theme.tokens.inputPlaceholder
}
},
extend: [{
condition: loading,
style: {
userSelect: 'none'
}
}, {
condition: disabled,
style: {
':disabled': {
cursor: 'not-allowed',
borderColor: theme.tokens.inputDisabledBorder,
backgroundColor: theme.tokens.inputDisabledBackground,
color: theme.tokens.inputForeground
}
}
}, {
condition: !isValid,
style: {
':not(:focus)': {
borderWidth: 2,
borderColor: theme.color.foreground.alert,
paddingTop: theme.tokens.inputPaddingVertical * 2 - 1,
paddingBottom: theme.tokens.inputPaddingVertical / 2 - 1,
paddingLeft: theme.tokens.inputPaddingHorizontal - 2,
paddingRight: theme.tokens.inputPaddingHorizontal - 2
}
}
}]
};
};
const labelStyle = _ref2 => {
let {
isEmpty,
isValid,
theme
} = _ref2;
return {
paddingLeft: theme.tokens.inputPaddingHorizontal,
paddingRight: theme.tokens.inputPaddingHorizontal,
color: isValid ? theme.color.foreground.secondary : theme.color.foreground.alert,
transitionProperty: 'font-size, transform',
transitionDuration: '60ms',
transitionTimingFunction: 'ease-out',
transform: 'translateY(' + (isEmpty ? 17 : 8) + 'px)',
fontSize: isEmpty ? 16 : 12,
letterSpacing: '0.02em',
fontFamily: theme.fontTypes.NOVUM,
fontWeight: 300,
position: 'absolute',
pointerEvents: 'none',
top: 0
};
};
/**
* @deprecated Use `import { TextInput } from '@volvo-cars/react-forms'` instead. See [TextInput](https://developer.volvocars.com/design-system/web/?path=/docs/components-forms-input-textinput--docs)
*/
const TextInput = exports.TextInput = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
let {
onChange,
type,
value = '',
isValid = true,
label = '',
description = '',
errorMessage = '',
loading = false,
disabled = false,
...props
} = _ref3;
const {
theme
} = (0, _reactFela.useFela)();
const isEmpty = (value || '').length === 0;
const styleProps = {
isEmpty,
isValid,
disabled,
loading,
theme
};
const id = (0, _autoId.useId)('vcc-ui-text-input', props.id);
const errorMessageId = (0, _autoId.makeId)(id, 'error');
const descriptionId = (0, _autoId.makeId)(id, 'description');
const describedBy = (0, _autoId.makeIdList)([errorMessage && errorMessageId, description && descriptionId]);
const messages = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, errorMessage || description ? /*#__PURE__*/_react.default.createElement(_spacer.Spacer, {
size: 0.5
}) : null, errorMessage ? /*#__PURE__*/_react.default.createElement(_message.Message, {
type: "error",
id: errorMessageId
}, errorMessage) : null, description ? /*#__PURE__*/_react.default.createElement(_message.Message, {
id: descriptionId
}, description) : null);
return /*#__PURE__*/_react.default.createElement(_flex.Flex, {
extend: {
flexDirection: 'column',
width: '100%',
':focus-within label': {
transform: 'translateY(8px)',
fontSize: 12
}
}
}, /*#__PURE__*/_react.default.createElement(_flex.Flex, {
extend: {
position: 'relative'
}
}, loading && /*#__PURE__*/_react.default.createElement(_flex.Flex, {
extend: {
position: 'absolute',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center'
}
}, /*#__PURE__*/_react.default.createElement(_spinner.Spinner, {
color: theme.tokens.inputForeground,
size: 24
})), !loading ? /*#__PURE__*/_react.default.createElement(_block.Block, {
as: "label",
htmlFor: id,
extend: labelStyle(styleProps)
}, label) : null, /*#__PURE__*/_react.default.createElement(_block.Block, (0, _extends2.default)({}, props, {
ref: ref,
as: "input",
value: loading ? '' : value,
disabled: disabled || loading,
type: type,
id: id,
onChange: onChange,
extend: defaultStyles(styleProps)
}, describedBy && {
'aria-describedby': describedBy
}))), messages);
});
TextInput.displayName = 'TextInput';
TextInput.propTypes = {
type: _propTypes.string,
id: _propTypes.string,
name: _propTypes.string,
/** Renders a label inside the input. */
label: _propTypes.string.isRequired,
/** Renders a description text underneath the input. */
description: _propTypes.string,
/** Renders a red error message for validation underneath the input. */
errorMessage: _propTypes.string,
/** onChange handler. Triggers on every keyboard and generally
* is here where you change the value of the `value` property. */
onChange: _propTypes.func.isRequired,
/**
* Value of the textInput. This should be stored in the
* state of the parent component.
*/
value: _propTypes.string.isRequired,
/** Renders the input as valid or invalid. */
isValid: _propTypes.bool,
loading: _propTypes.bool,
disabled: _propTypes.bool
};