UNPKG

grommet

Version:

focus on the essential experience

267 lines (263 loc) 12.4 kB
"use strict"; exports.__esModule = true; exports.Box = void 0; var _react = _interopRequireWildcard(require("react")); var _styledComponents = require("styled-components"); var _utils = require("../../utils"); var _Keyboard = require("../Keyboard"); var _StyledBox = require("./StyledBox"); var _propTypes = require("./propTypes"); var _Skeleton = require("../Skeleton"); var _AnnounceContext = require("../../contexts/AnnounceContext"); var _OptionsContext = require("../../contexts/OptionsContext"); var _contexts = require("../../contexts"); var _ResponsiveContainerProvider = require("./ResponsiveContainerProvider"); var _useThemeValue2 = require("../../utils/useThemeValue"); var _responsive = require("../../utils/responsive"); var _excluded = ["a11yTitle", "background", "border", "children", "cssGap", "direction", "elevation", "fill", "gap", "kind", "onBlur", "onClick", "onFocus", "overflow", "responsive", "tag", "as", "wrap", "width", "height", "tabIndex", "skeleton"], _excluded2 = ["colors", "size"]; function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } var Box = exports.Box = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, refProp) { var a11yTitle = _ref.a11yTitle, backgroundProp = _ref.background, border = _ref.border, children = _ref.children, cssGap = _ref.cssGap, _ref$direction = _ref.direction, direction = _ref$direction === void 0 ? 'column' : _ref$direction, elevation = _ref.elevation, fill = _ref.fill, gap = _ref.gap, kind = _ref.kind, _onBlur = _ref.onBlur, onClick = _ref.onClick, _onFocus = _ref.onFocus, overflow = _ref.overflow, _ref$responsive = _ref.responsive, responsiveProp = _ref$responsive === void 0 ? true : _ref$responsive, tag = _ref.tag, as = _ref.as, wrap = _ref.wrap, width = _ref.width, height = _ref.height, tabIndex = _ref.tabIndex, skeletonProp = _ref.skeleton, rest = _objectWithoutPropertiesLoose(_ref, _excluded); var _useThemeValue = (0, _useThemeValue2.useThemeValue)(), theme = _useThemeValue.theme, passThemeFlag = _useThemeValue.passThemeFlag; // boxOptions was created to preserve backwards compatibility but // should not be supported in v3 var _useContext = (0, _react.useContext)(_OptionsContext.OptionsContext), boxOptions = _useContext.box; var skeleton = (0, _Skeleton.useSkeleton)(); var _useState = (0, _react.useState)(undefined), containerElement = _useState[0], setContainerElement = _useState[1]; var responsiveContainer = (0, _react.useContext)(_contexts.ResponsiveContainerContext); var responsive = responsiveContainer && responsiveProp ? 'container' : responsiveProp; var background = backgroundProp; var announce = (0, _react.useContext)(_AnnounceContext.AnnounceContext); var containerRef = (0, _utils.useForwardedRef)(refProp); // Save the ref as a state if we're in a responsive container. // We only need it in the responsive container case and it // needs to be in a state to cause a re-render. (0, _react.useEffect)(function () { if (responsiveProp === 'container' && containerRef.current) { setContainerElement(containerRef.current); } }, [containerRef, responsiveProp]); (0, _react.useEffect)(function () { if (typeof as === 'function') { if (refProp) { console.warn('ref and as={function} are incompatible. The ref will not get set.'); } if (responsiveProp === 'container') { console.warn( // eslint-disable-next-line max-len 'responsive="container" and as={function} are incompatible. Use one or the other.'); } } }, [refProp, as, responsiveProp]); (0, _react.useEffect)(function () { var _skeletonProp$message; if (skeletonProp != null && (_skeletonProp$message = skeletonProp.message) != null && _skeletonProp$message.start) announce(skeletonProp.message.start);else if (typeof (skeletonProp == null ? void 0 : skeletonProp.message) === 'string') announce(skeletonProp.message); return function () { var _skeletonProp$message2; return (skeletonProp == null || (_skeletonProp$message2 = skeletonProp.message) == null ? void 0 : _skeletonProp$message2.end) && announce(skeletonProp.message.end); }; }, [announce, skeletonProp]); var focusable = (0, _react.useMemo)(function () { return onClick && !(tabIndex < 0); }, [onClick, tabIndex]); var _useState2 = (0, _react.useState)(), focus = _useState2[0], setFocus = _useState2[1]; var clickProps = (0, _react.useMemo)(function () { if (focusable) { return { onClick: onClick, onFocus: function onFocus(event) { setFocus(true); if (_onFocus) _onFocus(event); }, onBlur: function onBlur(event) { setFocus(false); if (_onBlur) _onBlur(event); } }; } var result = {}; if (_onBlur) result.onBlur = _onBlur; if (onClick) result.onClick = onClick; if (_onFocus) result.onFocus = _onFocus; return result; }, [focusable, onClick, _onFocus, _onBlur]); var adjustedTabIndex = (0, _react.useMemo)(function () { if (tabIndex !== undefined) return tabIndex; if (focusable) return 0; return undefined; }, [focusable, tabIndex]); if ((border === 'between' || border && border.side === 'between' || Array.isArray(border) && border.find(function (b) { return b.side === 'between'; })) && !gap) { console.warn('Box must have a gap to use border between'); } var contents = children; if (gap && gap !== 'none' && (!(boxOptions != null && boxOptions.cssGap || cssGap || typeof gap === 'object') || // need this approach to show border between border === 'between' || (border == null ? void 0 : border.side) === 'between' || Array.isArray(border) && border.find(function (b) { return b.side === 'between'; }))) { // if border is an array, we need to extract the border between object var styledBoxGapBorder = Array.isArray(border) ? border.find(function (b) { return b.side === 'between'; }) : border; var boxAs = !as && tag ? tag : as; contents = []; var firstIndex; _react.Children.forEach(children, function (child, index) { if (child) { if (firstIndex === undefined) { firstIndex = index; } else { contents.push(/*#__PURE__*/_react["default"].createElement(_StyledBox.StyledBoxGap // eslint-disable-next-line react/no-array-index-key , _extends({ key: "gap-" + index, as: boxAs === 'span' ? boxAs : 'div', gap: gap, directionProp: direction, responsive: responsive, border: styledBoxGapBorder }, passThemeFlag))); } } contents.push(child); }); } var nextSkeleton = (0, _react.useMemo)(function () { // Decide if we need to add a new SkeletonContext. We need one if: // 1. skeleton info was set in a property OR // 2. there already is a SkeletonContext but this box has a // background or border. This means the box probably is more // distinguishable from the area around it. // We keep track of a depth so we know how to alternate backgrounds. if (skeletonProp || (background || border) && skeleton) { var depth = skeleton ? skeleton.depth + 1 : 0; return _extends({}, skeleton, { depth: depth }, typeof skeletonProp === 'object' ? skeletonProp : {}); } return undefined; }, [background, border, skeleton, skeletonProp]); var skeletonProps = {}; if (nextSkeleton) { var _theme$skeleton = theme.skeleton, skeletonThemeColors = _theme$skeleton.colors, skeletonThemeSize = _theme$skeleton.size, skeletonThemeProps = _objectWithoutPropertiesLoose(_theme$skeleton, _excluded2); var skeletonColors = nextSkeleton.colors ? nextSkeleton.colors[theme.dark ? 'dark' : 'light'] : skeletonThemeColors == null ? void 0 : skeletonThemeColors[theme.dark ? 'dark' : 'light']; skeletonProps = _extends({}, skeletonThemeProps); background = skeletonColors[nextSkeleton.depth % skeletonColors.length]; if (skeletonProp != null && skeletonProp.animation) { skeletonProps.animation = skeletonProp.animation; } contents = /*#__PURE__*/_react["default"].createElement(_Skeleton.SkeletonContext.Provider, { value: nextSkeleton }, contents); } // construct a new theme object in case we have a background that wants // to change the background color context var nextTheme = (0, _react.useMemo)(function () { var result; if (background || theme.darkChanged) { var dark = (0, _utils.backgroundIsDark)(background, theme); var darkChanged = dark !== undefined && dark !== theme.dark; if (darkChanged || theme.darkChanged) { result = _extends({}, theme); result.dark = dark === undefined ? theme.dark : dark; result.background = background; } else if (background) { // This allows DataTable to intelligently set the background // of a pinned header or footer. result = _extends({}, theme); result.background = background; } } return result || theme; }, [background, theme]); // Only pass along the ref if the as prop is not a function. // The styled component will throw a warning if we try to pass // a ref when the as prop is a function. We do a console.warn // about this above in this case. var ref = typeof as === 'function' ? undefined : containerRef; var content = /*#__PURE__*/_react["default"].createElement(_StyledBox.StyledBox, _extends({ as: !as && tag ? tag : as, "aria-label": a11yTitle, background: background, border: border, ref: ref, directionProp: direction, elevationProp: elevation, fillProp: fill, focus: focus, gap: ((boxOptions == null ? void 0 : boxOptions.cssGap) || cssGap || typeof gap === 'object') && gap && gap !== 'none' && border !== 'between' && (border == null ? void 0 : border.side) !== 'between' && (!Array.isArray(border) || !border.find(function (b) { return b.side === 'between'; })) && gap, kindProp: kind, overflowProp: overflow, wrapProp: wrap, widthProp: width, heightProp: height, responsive: responsive, responsiveContainer: responsiveProp === 'container', tabIndex: adjustedTabIndex }, clickProps, passThemeFlag, rest, skeletonProps), /*#__PURE__*/_react["default"].createElement(_styledComponents.ThemeContext.Provider, { value: nextTheme }, contents)); if (responsiveProp === 'container') { if ((0, _responsive.supportsContainerQueries)()) { content = /*#__PURE__*/_react["default"].createElement(_ResponsiveContainerProvider.ResponsiveContainerProvider, { container: containerElement, theme: theme }, content); } else { console.warn('<Box responsive="container"> requires styled-components v6 or later'); } } if (onClick) { content = /*#__PURE__*/_react["default"].createElement(_Keyboard.Keyboard, { onEnter: onClick, onSpace: function onSpace(e) { e.preventDefault(); // prevent page scroll onClick(e); } }, content); } return content; }); Box.displayName = 'Box'; Box.propTypes = _propTypes.BoxPropTypes;