UNPKG

@enact/sandstone

Version:

Large-screen/TV support library for Enact, containing a variety of UI components.

346 lines (341 loc) 15.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.TabGroup = void 0; var _handle = _interopRequireWildcard(require("@enact/core/handle")); var _kind = _interopRequireDefault(require("@enact/core/kind")); var _spotlight = _interopRequireDefault(require("@enact/spotlight")); var _SpotlightContainerDecorator = _interopRequireDefault(require("@enact/spotlight/SpotlightContainerDecorator")); var _Group = _interopRequireDefault(require("@enact/ui/Group")); var _IdProvider = _interopRequireDefault(require("@enact/ui/internal/IdProvider")); var _Layout = require("@enact/ui/Layout"); var _Toggleable = _interopRequireDefault(require("@enact/ui/Toggleable")); var _IString = _interopRequireDefault(require("ilib/lib/IString")); var _propTypes = _interopRequireDefault(require("prop-types")); var _compose = _interopRequireDefault(require("ramda/src/compose")); var _react = require("react"); var _$L = _interopRequireDefault(require("../internal/$L")); var _DebounceDecorator = _interopRequireDefault(require("../internal/DebounceDecorator")); var _Button = _interopRequireDefault(require("../Button")); var _Skinnable = _interopRequireDefault(require("../Skinnable")); var _Scroller = _interopRequireDefault(require("../Scroller")); var _Sprite = _interopRequireDefault(require("../Sprite")); var _TabGroupModule = _interopRequireDefault(require("./TabGroup.module.css")); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["buttonSize"], _excluded2 = ["children", "collapsed", "css", "orientation", "size"], _excluded3 = ["css", "collapsed", "id", "noIcons", "onBlur", "onBlurList", "onFocus", "onFocusTab", "onSelect", "orientation", "selectedIndex", "spotlightId", "spotlightDisabled", "tabs", "tabSize", "tabsDisabled", "tabsSpotlightDisabled"], _excluded4 = ["icon", "title", "tabKey", "sprite"]; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } var MAX_TABS_BEFORE_SCROLLING = 7; // Since Button and Cell both have a `size` prop, TabButton is required to relay the Button.size to Button, rather than Cell. // eslint-disable-next-line enact/prop-types var TabButton = function TabButton(_ref) { var buttonSize = _ref.buttonSize, rest = _objectWithoutProperties(_ref, _excluded); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button["default"], _objectSpread(_objectSpread({ size: buttonSize }, rest), {}, { css: _TabGroupModule["default"] })); }; var TabBase = (0, _kind["default"])({ name: 'Tab', propTypes: { collapsed: _propTypes["default"].bool, css: _propTypes["default"].object, icon: _propTypes["default"].string, index: _propTypes["default"].number, onFocusTab: _propTypes["default"].func, onTabClick: _propTypes["default"].func, orientation: _propTypes["default"].string, selected: _propTypes["default"].bool, size: _propTypes["default"].number, sprite: _propTypes["default"].object, stopped: _propTypes["default"].bool }, defaultProps: { orientation: 'vertical' }, styles: { css: _TabGroupModule["default"], className: 'tab', publicClassNames: ['bg', 'button', 'client', 'selected', 'tab', 'vertical'] }, handlers: { onClick: (0, _handle["default"])((0, _handle.forward)('onClick'), (0, _handle.not)((0, _handle.forProp)('disabled', true)), (0, _handle.forwardCustom)('onTabClick', function (ev, _ref2) { var index = _ref2.index; return { selected: index }; })), onFocus: (0, _handle["default"])((0, _handle.forward)('onFocus'), (0, _handle.not)((0, _handle.forProp)('disabled', true)), function () { return !_spotlight["default"].getPointerMode(); }, (0, _handle.forwardCustom)('onFocusTab', function (ev, _ref3) { var index = _ref3.index; return { selected: index }; })) }, computed: { className: function className(_ref4) { var collapsed = _ref4.collapsed, orientation = _ref4.orientation, styler = _ref4.styler; return styler.append({ collapsed: collapsed }, orientation); }, iconComponent: function iconComponent(_ref5) { var sprite = _ref5.sprite, stopped = _ref5.stopped; if (sprite) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Sprite["default"], _objectSpread({ stopped: stopped }, sprite)); } } }, render: function render(_ref6) { var children = _ref6.children, collapsed = _ref6.collapsed, css = _ref6.css, orientation = _ref6.orientation, size = _ref6.size, rest = _objectWithoutProperties(_ref6, _excluded2); delete rest.index; delete rest.onFocusTab; delete rest.onTabClick; delete rest.stopped; delete rest.sprite; if (collapsed) children = null; var commonProps = { backgroundOpacity: 'transparent', children: children, collapsable: true, css: css, focusEffect: 'static', minWidth: false, role: 'tab' }; switch (orientation) { // Horizontal Cell sizing can auto-size width or be set to a finite value, stretching the Button. case 'horizontal': { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Layout.Cell, _objectSpread(_objectSpread({}, rest), {}, { size: size, component: TabButton }, commonProps)); } case 'vertical': { // Vertical sizing depends on Button establishing the dimensions of the Cell. return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button["default"], _objectSpread(_objectSpread({}, rest), commonProps)); } } } }); var Tab = (0, _Toggleable["default"])({ prop: 'stopped', activate: 'onBlur', deactivate: 'onFocus' }, (0, _Skinnable["default"])(TabBase)); var GroupComponent = (0, _SpotlightContainerDecorator["default"])({ // using default-element so we always land on the selected tab in order to avoid changing // the view when re-entering the tab group defaultElement: ".".concat(_TabGroupModule["default"].selected), enterTo: 'default-element', partition: true, // When swapping from unscrolled to scrolled tab group, the container config is lost so this // preserves it across unmounts / remounts preserveId: true }, _Group["default"]); /** * A group of tabs * * @class TabGroup * @memberof sandstone/TabLayout * @ui * @private */ var TabGroupBase = (0, _kind["default"])({ name: 'TabGroup', functional: true, propTypes: /** @lends sandstone/TabGroup.TabGroup.prototype */{ tabs: _propTypes["default"].array.isRequired, collapsed: _propTypes["default"].bool, css: _propTypes["default"].object, id: _propTypes["default"].string, onBlur: _propTypes["default"].func, onBlurList: _propTypes["default"].func, onFocus: _propTypes["default"].func, onFocusTab: _propTypes["default"].func, onSelect: _propTypes["default"].func, orientation: _propTypes["default"].string, selectedIndex: _propTypes["default"].number, spotlightDisabled: _propTypes["default"].bool, spotlightId: _propTypes["default"].string, tabSize: _propTypes["default"].number }, styles: { css: _TabGroupModule["default"], className: 'tabGroup', publicClassNames: ['bg', 'button', 'client', 'selected', 'tab', 'tabGroup', 'vertical'] }, computed: { className: function className(_ref7) { var collapsed = _ref7.collapsed, orientation = _ref7.orientation, styler = _ref7.styler; return styler.append({ collapsed: collapsed }, orientation); }, // check if there's no tab icons noIcons: function noIcons(_ref8) { var collapsed = _ref8.collapsed, orientation = _ref8.orientation, tabs = _ref8.tabs; return orientation === 'vertical' && collapsed && tabs.filter(function (tab) { return !tab.icon && !tab.sprite; }).length; }, tabsDisabled: function tabsDisabled(_ref9) { var tabs = _ref9.tabs; return tabs.find(function (tab) { return tab && !tab.disabled; }) == null; }, tabsSpotlightDisabled: function tabsSpotlightDisabled(_ref10) { var spotlightDisabled = _ref10.spotlightDisabled, tabs = _ref10.tabs; return spotlightDisabled || tabs.find(function (tab) { return tab && !tab.spotlightDisabled; }) == null; } }, render: function render(_ref11) { var css = _ref11.css, collapsed = _ref11.collapsed, id = _ref11.id, noIcons = _ref11.noIcons, onBlur = _ref11.onBlur, onBlurList = _ref11.onBlurList, onFocus = _ref11.onFocus, onFocusTab = _ref11.onFocusTab, onSelect = _ref11.onSelect, orientation = _ref11.orientation, selectedIndex = _ref11.selectedIndex, spotlightId = _ref11.spotlightId, spotlightDisabled = _ref11.spotlightDisabled, tabs = _ref11.tabs, tabSize = _ref11.tabSize, tabsDisabled = _ref11.tabsDisabled, tabsSpotlightDisabled = _ref11.tabsSpotlightDisabled, rest = _objectWithoutProperties(_ref11, _excluded3); delete rest.children; // eslint-disable-next-line react-hooks/rules-of-hooks var itemProps = (0, _react.useMemo)(function () { return { css: css, collapsed: collapsed, orientation: orientation, size: tabSize }; }, [css, collapsed, orientation, tabSize]); // eslint-disable-next-line react-hooks/rules-of-hooks var children = (0, _react.useMemo)(function () { return tabs.map(function (tab) { if (tab) { // eslint-disable-next-line no-shadow var icon = tab.icon, title = tab.title, tabKey = tab.tabKey, sprite = tab.sprite, _rest = _objectWithoutProperties(tab, _excluded4); var key = tabKey || tabKey === 0 ? tabKey : "tabs_".concat(title + (typeof icon === 'string' ? icon : '')); return _objectSpread({ children: title, defaultStopped: Boolean(sprite), icon: icon, key: key, onFocusTab: onFocusTab, sprite: sprite }, _rest); } else { return null; } }).filter(function (tab) { return tab != null; }); }, [onFocusTab, tabs]); var isHorizontal = orientation === 'horizontal'; var groupComponent = isHorizontal ? _Layout.Layout : 'div'; // Only horizontal needs the arrangement capabilities of `Layout` // Only vertical with more than MAX_TABS should use scroller var useScroller = !isHorizontal && children.length > MAX_TABS_BEFORE_SCROLLING; var scrollerProps = useScroller ? { horizontalScrollbar: 'hidden', verticalScrollbar: 'hidden' } : null; var Component = useScroller ? _Scroller["default"] : 'div'; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Component, _objectSpread(_objectSpread(_objectSpread({}, rest), {}, { onBlur: onBlur, onFocus: onFocus }, scrollerProps), {}, { children: [noIcons ? /*#__PURE__*/(0, _jsxRuntime.jsx)(TabBase, { icon: "list", collapsed: true, disabled: tabsDisabled, onSpotlightDisappear: onBlurList, spotlightDisabled: tabsSpotlightDisabled }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { role: "region", "aria-labelledby": "".concat(id, "_tabgroup"), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(GroupComponent, { id: "".concat(id, "_tabgroup"), childComponent: Tab, "aria-label": "".concat(new _IString["default"]((0, _$L["default"])('{total} items in total')).format({ 'total': tabs.length })), className: _TabGroupModule["default"].tabs, component: groupComponent, indexProp: "index", itemProps: itemProps, onSelect: onSelect, orientation: orientation, role: "tablist", select: "radio", selected: selectedIndex, selectedProp: "selected", spotlightId: spotlightId, spotlightDisabled: spotlightDisabled, children: children }) }), isHorizontal ? /*#__PURE__*/(0, _jsxRuntime.jsx)("hr", { className: _TabGroupModule["default"].horizontalLine }) : null] })); } }); var TabGroupDecorator = (0, _compose["default"])((0, _DebounceDecorator["default"])({ cancel: 'onBlur', debounce: 'onFocusTab', delay: 300 }), (0, _IdProvider["default"])({ generateProp: null, prefix: 'tg_' })); // Only documenting TabGroup since base is not useful for extension as-is var TabGroup = exports.TabGroup = TabGroupDecorator(TabGroupBase); var _default = exports["default"] = TabGroup;