UNPKG

orcs-design-system

Version:
213 lines (212 loc) 10.4 kB
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 } } };