@equinor/eds-core-react
Version:
The React implementation of the Equinor Design System
136 lines (132 loc) • 4.17 kB
JavaScript
import styled from 'styled-components';
import { tokens } from '@equinor/eds-tokens';
import { forwardRef, useEffect } from 'react';
import { Popover } from '../../Popover/index.js';
import { filterDOMProps } from '@react-aria/utils';
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import { InputWrapper } from '../../InputWrapper/InputWrapper.js';
import { useEds } from '../../EdsProvider/eds.context.js';
const getVariant = variant => {
if (variant === 'error') {
return tokens.colors.interactive.danger__resting.rgba;
}
if (variant === 'success') {
return tokens.colors.interactive.success__resting.rgba;
}
if (variant === 'warning') {
return tokens.colors.interactive.warning__resting.rgba;
}
return tokens.colors.interactive.primary__resting.rgba;
};
const getVariantText = variant => {
if (variant === 'error') {
return tokens.colors.interactive.danger__text.rgba;
}
if (variant === 'success') {
return tokens.colors.interactive.success__text.rgba;
}
if (variant === 'warning') {
return tokens.colors.interactive.warning__text.rgba;
}
return tokens.typography.input.text.color;
};
const StyledInputFieldWrapper = styled.div.withConfig({
displayName: "FieldWrapper__StyledInputFieldWrapper",
componentId: "sc-1h0kqs9-0"
})(["display:flex;align-items:center;background-color:", ";height:", ";padding:0 8px;", " ", " color:", ";cursor:default;"], tokens.colors.ui.background__light.rgba, ({
$density
}) => $density === 'compact' ? '24px' : '36px', ({
$variant,
$disabled,
$readonly
}) => {
if (!$variant && !$readonly) {
return `&:focus-within:not(.invalid) {
outline: 2px solid
${tokens.colors.interactive.primary__resting.rgba};
}
${!$disabled && `&:not(:focus-within) {
box-shadow: inset 0 -1px 0 0 ${tokens.colors.text.static_icons__tertiary.rgba};`}
}
`;
}
return `outline: 2px solid ${getVariant($variant)};`;
}, ({
$readonly
}) => {
return $readonly && `background-color: ${tokens.colors.ui.background__default.rgba};
outline: none;`;
}, p => getVariantText(p.$variant));
/**
* Applies styles around the date input fields (density, color etc.)
*/
const InputFieldWrapper = /*#__PURE__*/forwardRef(({
children,
color,
disabled,
readonly,
...props
}, ref) => {
const {
density
} = useEds();
// As the props returned are designed for react-aria, some of them are not valid DOM props (i.e. onPress).
// The filterDOMProps-method strips out the invalid props, but it also removes event listeners due to casing
const filteredProps = filterDOMProps(props);
// filterDOMProps also strips event handlers
const eventHandlers = Object.keys(props).filter(k => k.startsWith('on')).reduce((a, b) => ({
...a,
[b]: props[b]
}), {});
return /*#__PURE__*/jsx(StyledInputFieldWrapper, {
ref: ref,
$density: density,
$variant: color,
$disabled: disabled ?? false,
$readonly: readonly ?? false,
...filteredProps,
...eventHandlers,
children: children
});
});
const FieldWrapper = /*#__PURE__*/forwardRef(({
children,
pickerRef,
calendar,
isOpen,
setIsOpen,
label,
readonly,
...props
}, ref) => {
useEffect(() => {
if (isOpen === false) {
// Focus the first segment in the input field
const segment = ref.current?.querySelector('.segment');
segment?.focus();
}
}, [ref, isOpen, pickerRef]);
return /*#__PURE__*/jsxs(Fragment, {
children: [/*#__PURE__*/jsx(InputWrapper, {
readOnly: readonly,
label: label,
onKeyDownCapture: event => {
const isIconTarget = event.target instanceof SVGSVGElement;
if (!isIconTarget && (event.code === 'Space' || event.code === 'Enter')) {
setIsOpen(true);
}
},
...props,
children: children
}), /*#__PURE__*/jsx(Popover, {
open: isOpen ?? false,
onClose: () => setIsOpen(false),
anchorEl: ref.current,
placement: 'bottom-start',
children: calendar
})]
});
});
InputFieldWrapper.displayName = 'InputFieldWrapper';
FieldWrapper.displayName = 'FieldWrapper';
export { FieldWrapper, InputFieldWrapper };