UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

184 lines (178 loc) • 8.13 kB
'use strict'; var React = require('react'); var styled = require('styled-components'); var styledSystem = require('styled-system'); var constants = require('../constants.js'); var sx = require('../sx.js'); var _VisuallyHidden = require('../_VisuallyHidden.js'); var useProvidedStateOrCreate = require('../hooks/useProvidedStateOrCreate.js'); var Box = require('../Box/Box.js'); var Spinner = require('../Spinner/Spinner.js'); var Text = require('../Text/Text.js'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefault(React); var styled__default = /*#__PURE__*/_interopDefault(styled); const TRANSITION_DURATION = '80ms'; const EASE_OUT_QUAD_CURVE = 'cubic-bezier(0.5, 1, 0.89, 1)'; const sizeVariants = styledSystem.variant({ prop: 'size', variants: { small: { height: '24px', width: '48px' } } }); const CircleIcon = ({ size }) => /*#__PURE__*/React__default.default.createElement("svg", { width: size === 'small' ? '12' : '16', height: size === 'small' ? '12' : '16', viewBox: "0 0 16 16", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg" }, /*#__PURE__*/React__default.default.createElement("path", { fillRule: "evenodd", d: "M8 12.5a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9ZM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12Z" })); CircleIcon.displayName = "CircleIcon"; const LineIcon = ({ size }) => /*#__PURE__*/React__default.default.createElement("svg", { width: size === 'small' ? '12' : '16', height: size === 'small' ? '12' : '16', viewBox: "0 0 16 16", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg" }, /*#__PURE__*/React__default.default.createElement("path", { fillRule: "evenodd", d: "M8 2a.75.75 0 0 1 .75.75v11.5a.75.75 0 0 1-1.5 0V2.75A.75.75 0 0 1 8 2Z" })); LineIcon.displayName = "LineIcon"; const SwitchButton = styled__default.default.button.withConfig({ displayName: "ToggleSwitch__SwitchButton", componentId: "sc-e6gszy-0" })(["vertical-align:middle;cursor:pointer;user-select:none;appearance:none;text-decoration:none;padding:0;transition-property:background-color,border-color;transition-duration:", ";transition-timing-function:", ";border-radius:", ";border-style:solid;border-width:1px;display:block;height:32px;width:64px;outline-offset:3px;position:relative;overflow:hidden;@media (pointer:coarse){&:before{content:'';position:absolute;left:0;right:0;transform:translateY(-50%);top:50%;min-height:44px;}}@media (prefers-reduced-motion){transition:none;*{transition:none;}}&:hover,&:focus:focus-visible{background-color:", ";}&:active,&:active:focus-visible{background-color:", ";}", " ", " ", ""], TRANSITION_DURATION, EASE_OUT_QUAD_CURVE, constants.get('radii.2'), constants.get('colors.switchTrack.hoverBg'), constants.get('colors.switchTrack.activeBg'), props => { if (props.disabled) { return styled.css(["background-color:", ";border-color:transparent;cursor:not-allowed;transition-property:none;"], constants.get('colors.switchTrack.disabledBg')); } if (props.checked) { return styled.css(["background-color:", ";border-color:transparent;&:hover,&:focus:focus-visible{background-color:", ";}&:active,&:active:focus-visible{background-color:", ";}"], constants.get('colors.switchTrack.checked.bg'), constants.get('colors.switchTrack.checked.hoverBg'), constants.get('colors.switchTrack.checked.activeBg')); } else { return styled.css(["background-color:", ";border-color:transparent;&:active{background-color:", ";}"], constants.get('colors.switchTrack.bg'), constants.get('colors.switchTrack.activeBg')); } }, sx.default, sizeVariants); const ToggleKnob = styled__default.default.div.withConfig({ displayName: "ToggleSwitch__ToggleKnob", componentId: "sc-e6gszy-1" })(["background-color:", ";border-width:1px;border-style:solid;border-color:", ";border-radius:calc(", " - 1px);width:50%;position:absolute;top:0;bottom:0;transition-property:transform;transition-duration:", ";transition-timing-function:", ";transform:", ";z-index:1;@media (prefers-reduced-motion){transition:none;}", ""], constants.get('colors.switchKnob.bg'), props => props.disabled ? constants.get('colors.switchTrack.disabledBg') : constants.get('colors.switchKnob.border'), constants.get('radii.2'), TRANSITION_DURATION, EASE_OUT_QUAD_CURVE, props => `translateX(${props.checked ? '100%' : '0px'})`, props => { if (props.disabled) { return styled.css(["border-color:", ";"], constants.get('colors.switchTrack.disabledBg')); } if (props.checked) { return styled.css(["border-color:", ";"], constants.get('colors.switchKnob.checked.border')); } }); const hiddenTextStyles = { visibility: 'hidden', height: 0 }; const ToggleSwitch = ({ 'aria-labelledby': ariaLabelledby, 'aria-describedby': ariaDescribedby, defaultChecked, disabled, loading, checked, onChange, onClick, size = 'medium', statusLabelPosition = 'start', sx: sxProp }) => { const isControlled = typeof checked !== 'undefined'; const [isOn, setIsOn] = useProvidedStateOrCreate.useProvidedStateOrCreate(checked, onChange, Boolean(defaultChecked)); const acceptsInteraction = !disabled && !loading; const handleToggleClick = React.useCallback(e => { if (!isControlled) { setIsOn(!isOn); } onClick && onClick(e); }, [onClick, isControlled, isOn, setIsOn]); React.useEffect(() => { if (onChange && isControlled) { onChange(Boolean(checked)); } }, [onChange, checked, isControlled]); return /*#__PURE__*/React__default.default.createElement(Box, { display: "inline-flex", alignItems: "center", flexDirection: statusLabelPosition === 'start' ? 'row' : 'row-reverse', sx: sxProp }, loading ? /*#__PURE__*/React__default.default.createElement(Spinner, { size: "small" }) : null, /*#__PURE__*/React__default.default.createElement(Text, { color: acceptsInteraction ? 'fg.default' : 'fg.muted', fontSize: size === 'small' ? 0 : 1, mx: 2, "aria-hidden": "true", sx: { position: 'relative' } }, /*#__PURE__*/React__default.default.createElement(Box, { textAlign: "right", sx: isOn ? null : hiddenTextStyles }, "On"), /*#__PURE__*/React__default.default.createElement(Box, { textAlign: "right", sx: isOn ? hiddenTextStyles : null }, "Off")), /*#__PURE__*/React__default.default.createElement(SwitchButton, { onClick: handleToggleClick, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, "aria-checked": isOn, role: "switch", checked: isOn, size: size, disabled: !acceptsInteraction }, /*#__PURE__*/React__default.default.createElement(_VisuallyHidden, null, isOn ? 'On' : 'Off'), /*#__PURE__*/React__default.default.createElement(Box, { "aria-hidden": "true", display: "flex", alignItems: "center", width: "100%", height: "100%", overflow: "hidden" }, /*#__PURE__*/React__default.default.createElement(Box, { flexGrow: 1, flexShrink: 0, flexBasis: "50%", color: acceptsInteraction ? 'switchTrack.checked.fg' : 'switchTrack.checked.disabledFg', lineHeight: "0", sx: { transform: `translateX(${isOn ? '0' : '-100%'})`, transitionProperty: 'transform', transitionDuration: TRANSITION_DURATION } }, /*#__PURE__*/React__default.default.createElement(LineIcon, { size: size })), /*#__PURE__*/React__default.default.createElement(Box, { flexGrow: 1, flexShrink: 0, flexBasis: "50%", color: acceptsInteraction ? 'switchTrack.fg' : 'switchTrack.disabledFg', lineHeight: "0", sx: { transform: `translateX(${isOn ? '100%' : '0'})`, transitionProperty: 'transform', transitionDuration: TRANSITION_DURATION } }, /*#__PURE__*/React__default.default.createElement(CircleIcon, { size: size }))), /*#__PURE__*/React__default.default.createElement(ToggleKnob, { "aria-hidden": "true", disabled: !acceptsInteraction, checked: isOn }))); }; ToggleSwitch.displayName = "ToggleSwitch"; var ToggleSwitch$1 = ToggleSwitch; module.exports = ToggleSwitch$1;