lucid-ui
Version:
A UI component library from Xandr.
141 lines • 6.26 kB
JavaScript
import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import MinusCircleIcon from '../Icon/MinusCircleIcon/MinusCircleIcon';
import SuccessIcon from '../Icon/SuccessIcon/SuccessIcon';
import CloseIcon from '../Icon/CloseIcon/CloseIcon';
import InfoIcon from '../Icon/InfoIcon/InfoIcon';
import WarningIcon from '../Icon/WarningIcon/WarningIcon';
import { lucidClassNames } from '../../util/style-helpers';
import { getFirst } from '../../util/component-types';
const { createElement } = React;
const { bool, func, string, node, oneOf } = PropTypes;
const cx = lucidClassNames.bind('&-Selection');
/** SELECTION ICON */
function defaultIcon(kind, responsiveMode) {
return kind === 'default' ? null : kind === 'container' ? null : kind ===
'success' ? (React.createElement(SuccessIcon, { className: cx('&-Icon', `&-Icon-is-${responsiveMode}`) })) : kind === 'danger' ? (React.createElement(MinusCircleIcon, { className: cx('&-Icon', `&-Icon-is-${responsiveMode}`) })) : kind === 'info' ? (React.createElement(InfoIcon, { className: cx('&-Icon', `&-Icon-is-${responsiveMode}`) })) : kind === 'warning' ? (React.createElement(WarningIcon, { className: cx('&-Icon', `&-Icon-is-${responsiveMode}`) })) : null;
}
const SelectionIcon = () => null;
SelectionIcon.peek = {
description: `
Icon that is displayed within the Selection. Any of the lucid \`*Icon\` components should work.
`,
};
SelectionIcon.displayName = 'Selection.Icon';
SelectionIcon.propName = 'Icon';
const SelectionLabel = () => null;
SelectionLabel.peek = {
description: `\`Label\` for the \`Selection\`.`,
};
SelectionLabel.displayName = 'Selection.Label';
SelectionLabel.propName = 'Label';
const defaultProps = {
isRemovable: true,
onRemove: _.noop,
hasBackground: false,
isBold: false,
kind: 'default',
responsiveMode: 'large',
};
const Selection = (props) => {
const { className, isRemovable, children, hasBackground, isBold, isFilled, isTop, kind, onRemove, responsiveMode, ...passThroughs } = props;
const isSmall = responsiveMode === 'small';
const labelProps = _.get(getFirst(props, Selection.Label), 'props', {});
const iconElement = getFirst(props, Selection.Icon);
const iconChildren = _.get(iconElement, 'props.children');
const icon = iconChildren
? createElement(iconChildren.type, {
...iconChildren.props,
className: cx('&-Icon', iconChildren.props.className),
})
: defaultIcon(kind, responsiveMode);
return (React.createElement("div", { ..._.omit(passThroughs, ['callbackId', 'Label']), className: cx('&', `&-is-${responsiveMode}`, kind && `&-${kind}`, {
'&-has-background': hasBackground,
'&-is-bold': isBold,
'&-is-filled': isFilled,
'&-is-top': isTop,
'&-no-title': _.isEmpty(labelProps),
}, className) },
icon,
React.createElement("div", { className: cx('&-content') },
React.createElement("div", { className: cx('&-label-container') },
React.createElement("span", { ...labelProps, className: cx('&-label', isSmall && '&-label-is-small') }),
isRemovable ? (React.createElement(CloseIcon, { isClickable: true, size: !isSmall ? 8 : 16, className: cx('&-close-button', isSmall && '&-close-button-is-small'), onClick: ({ event }) => {
onRemove({ event, props });
} })) : null),
!_.isEmpty(children) && (React.createElement("div", { className: cx('&-children-container') }, _.map(React.Children.toArray(children), (child, i) => {
if (React.isValidElement(child) && child.type === Selection) {
return (React.createElement(Selection, { key: _.get(getFirst(child.props, Selection.Label), ['props', 'children'], {}) + i, ...child.props }));
}
return child;
}))))));
};
Selection.displayName = 'Selection';
Selection.Icon = SelectionIcon;
Selection.Label = SelectionLabel;
Selection.peek = {
description: `Used to indicate selections. \`Selection\` is very similar to \`Tag\` but is meant to be used in areas of the UI that have more space available to them.`,
categories: ['communication'],
};
Selection.defaultProps = defaultProps;
Selection.propTypes = {
/**
Appended to the component-specific class names set on the root element.
*/
className: string,
/**
Applies an icon and styles for the kind of selection.
*/
kind: oneOf(['default', 'container', 'success', 'danger', 'info', 'warning']),
/**
Apply to the top of a nested sequence of Selection components.
Adds some spacing for a list of top level Selections with nested Selctions inside each.
*/
isTop: bool,
/**
Only applies to \`container\` Selection components.
Fills with a darker gray background.
Defaults to false.
*/
isFilled: bool,
/**
Shows or hides the little "x" for a given item.
*/
isRemovable: bool,
/**
Gives the selection a background. This is desirable when you only have
one level of nested selections.
*/
hasBackground: bool,
/**
Make the content text bold. This is desirable when you only have one
level of nested selections.
*/
isBold: bool,
/**
Called when the close button is clicked.
*/
onRemove: func,
/**
Label of the component.
*/
Label: node,
/**
Display a custom icon for the selection. Generally you shouldn't need
this prop since the \`kind\` prop will pick the correct icon for you.
*/
Icon: node,
/**
Arbitrary children.
*/
children: node,
/**
Adjusts the display of this component. This should typically be driven by
screen size. Currently \`small\` and \`large\` are explicitly handled by
this component.
*/
responsiveMode: oneOf(['small', 'medium', 'large']),
};
export default Selection;
//# sourceMappingURL=Selection.js.map