orcs-design-system
Version:
TeamForm's Design System, aka: ORCS
213 lines (212 loc) • 10.4 kB
JavaScript
import React, { useRef } from "react";
import PropTypes from "prop-types";
import styled, { keyframes, ThemeProvider } from "styled-components";
import { space, layout, typography } from "styled-system";
import { themeGet } from "@styled-system/theme-get";
import { pick } from "lodash";
/* Animations */
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const checkboxOn = keyframes(["0%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0px 0 20px,0px 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px;}50%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0px 0 20px,0px 32px 0 20px,-5px 5px 0 10px,20px 2px 0 11px;}100%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0px 0 20px,0px 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px;}"]);
const checkboxOff = keyframes(["0%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0px 0 20px,0px 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset;}25%{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0px 0 20px,0px 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px,0 0 0 0 inset;}50%{transform:rotate(45deg);margin-top:-4px;margin-left:6px;width:0px;height:0px;box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0px 0 20px,0px 32px 0 20px,-5px 5px 0 10px,15px 2px 0 11px,0 0 0 0 inset;}51%{transform:rotate(0deg);margin-top:-2px;margin-left:-2px;width:20px;height:20px;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0px 0px 0 10px inset;}100%{transform:rotate(0deg);margin-top:-2px;margin-left:-2px;width:20px;height:20px;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0px 0px 0 0px inset;}"]);
const rippleOn = keyframes(["0%{opacity:0.5;}100%{opacity:0;transform:scale(13,13);}"]);
const rippleOff = keyframes(["0%{opacity:0.5;}100%{opacity:0;transform:scale(13,13);}"]);
const Item = styled.div.withConfig({
displayName: "Checkbox__Item",
componentId: "sc-p4d19b-0"
})(["", " ", " display:block;transform:translateZ(0);color:", ";"], space, layout, props => props.colour === "white" ? themeGet("colors.white")(props) : themeGet("colors.greyDarkest")(props));
const Label = styled.label.withConfig({
displayName: "Checkbox__Label",
componentId: "sc-p4d19b-1"
})(["display:flex;align-items:center;cursor:", ";opacity:", ";"], props => props.disabled ? "default" : "pointer", props => props.disabled ? "0.5" : "1");
const Control = styled.input.attrs({
type: "checkbox"
}).withConfig({
displayName: "Checkbox__Control",
componentId: "sc-p4d19b-2"
})(["opacity:0;position:absolute;margin:0;z-index:-1;width:0;height:0;overflow:hidden;pointer-events:none;&:focus{+ div{border-radius:2px;box-shadow:", ";}}+ div{transition:", ";&:before{background-color:", ";}> div{color:", ";}}:focus + div div:after{opacity:0.2;}:checked{+ div div:before{box-shadow:0 0 0 10px,10px -10px 0 10px,32px 0px 0 20px,0px 32px 0 20px,-5px 5px 0 10px,20px -12px 0 11px;.animate&{animation:", " 300ms forwards ease-out;}}}&:not(:checked) + div div:before{.animate&{animation:", " 300ms forwards ease-out;}}"], props => props.colour ? themeGet("shadows.thickOutline")(props) + " " + themeGet("colors." + props.colour + "30")(props) : themeGet("shadows.thickOutline")(props) + " " + themeGet("colors.black20")(props), themeGet("transition.transitionDefault"), props => props.colour ? themeGet(`colors.${props.colour}`)(props) : themeGet("colors.greyDarker")(props), props => props.colour ? themeGet(`colors.${props.colour}`)(props) : themeGet("colors.greyDarker")(props), checkboxOn, checkboxOff);
const Box = styled.div.withConfig({
displayName: "Checkbox__Box",
componentId: "sc-p4d19b-3"
})(["position:relative;height:20px;width:20px;&:before{content:\"\";display:block;position:absolute;left:8px;top:8px;height:4px;width:4px;border-radius:100%;z-index:1;opacity:0;margin:0;pointer-events:none;background-color:", ";}"], props => themeGet("colors.black50")(props));
const Check = styled.div.withConfig({
displayName: "Checkbox__Check",
componentId: "sc-p4d19b-4"
})(["position:relative;display:inline-block;width:20px;height:20px;border:2px solid;border-radius:", ";overflow:hidden;z-index:1;color:", ";&:before{content:\"\";position:absolute;transform:rotate(45deg);display:block;margin-top:-4px;margin-left:6px;width:0;height:0;box-shadow:0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0,0 0 0 0 inset;@media not all and (min-resolution:0.001dpcm){@supports (-webkit-appearance:none){width:1px;height:1px;}}}"], props => themeGet("radii.1")(props), props => themeGet("colors.greyDarker")(props));
const Text = styled.div.withConfig({
displayName: "Checkbox__Text",
componentId: "sc-p4d19b-5"
})(["font-size:", ";padding-left:8px;", ""], props => themeGet("fontSizes.2")(props), typography);
/**
* The default checkbox (or inverted if on dark background) should be used for the majority of the UI; however, the coloured ones can be used in situations where the colour corresponds with some indication of status, e.g. in a task list, green could denote task completed, red could denote task overdue.
*/
export default function Checkbox(_ref) {
let {
name,
label,
colour,
disabled,
checked,
onClick,
onChange,
theme,
ariaLabel,
...props
} = _ref;
const inputRef = useRef(null);
const handleClick = () => {
if (!inputRef.current || disabled) {
return;
}
inputRef.current.classList.add("animate");
};
const handleAnimationEnd = () => {
if (!inputRef.current || disabled) {
return;
}
inputRef.current.classList.remove("animate");
};
const component = /*#__PURE__*/_jsx(Item, {
colour: colour,
...props,
onClick: handleClick,
onAnimationEnd: handleAnimationEnd,
children: /*#__PURE__*/_jsxs(Label, {
disabled: disabled,
children: [/*#__PURE__*/_jsx(Control, {
name: name,
colour: colour,
disabled: disabled,
checked: checked,
onChange: onChange,
ref: inputRef,
"aria-label": ariaLabel
}), /*#__PURE__*/_jsx(Box, {
colour: colour,
onClick: onClick,
children: /*#__PURE__*/_jsx(Check, {})
}), /*#__PURE__*/_jsx(Text, {
...pick(props, typography.propNames),
children: label
})]
})
});
return theme ? /*#__PURE__*/_jsx(ThemeProvider, {
theme: theme,
children: component
}) : component;
}
Checkbox.propTypes = {
/** Sets the colour of the checkbox. Colours used are the design system standard colours. */
colour: PropTypes.oneOf(["success", "warning", "danger", "primary", "white"]),
/** Applies disabled attribute and styling */
disabled: PropTypes.bool,
/** Applies checked attribute and styling */
checked: PropTypes.bool,
/** Input name attribute (should be unique id) */
name: PropTypes.string,
/** On checkbox input change handler */
onChange: PropTypes.func,
/** On checkbox click handler */
onClick: PropTypes.string,
/** Text label to display beside the checkbox */
label: PropTypes.string,
// ariaLabel prop must be specified if label is not provided
ariaLabel: (props, propName) => {
if (!props.label && (props[propName] == null || props[propName] === "")) {
return new Error(`Missing prop \`${propName}\` not specified for Checkbox component. When \`label\` is not provided, \`${propName}\` is required.`);
}
if (props[propName] && typeof props[propName] !== "string") {
return new Error(`Invalid propType \`${propName}\` supplied to Checkbox component. Expected \`string\`, received \`${typeof props[propName]}\`.`);
}
return null;
},
/** Specifies the system design theme. */
theme: PropTypes.object
};
Checkbox.__docgenInfo = {
"description": "The default checkbox (or inverted if on dark background) should be used for the majority of the UI; however, the coloured ones can be used in situations where the colour corresponds with some indication of status, e.g. in a task list, green could denote task completed, red could denote task overdue.",
"methods": [],
"displayName": "Checkbox",
"props": {
"colour": {
"description": "Sets the colour of the checkbox. Colours used are the design system standard colours.",
"type": {
"name": "enum",
"value": [{
"value": "\"success\"",
"computed": false
}, {
"value": "\"warning\"",
"computed": false
}, {
"value": "\"danger\"",
"computed": false
}, {
"value": "\"primary\"",
"computed": false
}, {
"value": "\"white\"",
"computed": false
}]
},
"required": false
},
"disabled": {
"description": "Applies disabled attribute and styling",
"type": {
"name": "bool"
},
"required": false
},
"checked": {
"description": "Applies checked attribute and styling",
"type": {
"name": "bool"
},
"required": false
},
"name": {
"description": "Input name attribute (should be unique id)",
"type": {
"name": "string"
},
"required": false
},
"onChange": {
"description": "On checkbox input change handler",
"type": {
"name": "func"
},
"required": false
},
"onClick": {
"description": "On checkbox click handler",
"type": {
"name": "string"
},
"required": false
},
"label": {
"description": "Text label to display beside the checkbox",
"type": {
"name": "string"
},
"required": false
},
"ariaLabel": {
"description": "",
"type": {
"name": "custom",
"raw": "(props, propName) => {\n if (!props.label && (props[propName] == null || props[propName] === \"\")) {\n return new Error(\n `Missing prop \\`${propName}\\` not specified for Checkbox component. When \\`label\\` is not provided, \\`${propName}\\` is required.`\n );\n }\n if (props[propName] && typeof props[propName] !== \"string\") {\n return new Error(\n `Invalid propType \\`${propName}\\` supplied to Checkbox component. Expected \\`string\\`, received \\`${typeof props[\n propName\n ]}\\`.`\n );\n }\n return null;\n}"
},
"required": false
},
"theme": {
"description": "Specifies the system design theme.",
"type": {
"name": "object"
},
"required": false
}
}
};