UNPKG

@enact/sandstone

Version:

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

192 lines (186 loc) 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.ScrollbarTrackBase = exports.ScrollbarTrack = void 0; var _classnames = _interopRequireDefault(require("classnames")); var _keymap = require("@enact/core/keymap"); var _Accelerator = _interopRequireDefault(require("@enact/spotlight/Accelerator")); var _Spottable = _interopRequireDefault(require("@enact/spotlight/Spottable")); var _AnnounceDecorator = require("@enact/ui/AnnounceDecorator"); var _propTypes = _interopRequireDefault(require("prop-types")); var _react = require("react"); var _$L = _interopRequireDefault(require("../internal/$L")); var _ScrollbarTrackModule = _interopRequireDefault(require("./ScrollbarTrack.module.css")); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["aria-label", "cbAlertScrollbarTrack", "focusableScrollbar", "onInteractionForScroll", "rtl", "scrollbarTrackCss", "vertical"]; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 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 nop = function nop() {}; var isDown = (0, _keymap.is)('down'), isLeft = (0, _keymap.is)('left'), isPageUp = (0, _keymap.is)('pageUp'), isPageDown = (0, _keymap.is)('pageDown'), isRight = (0, _keymap.is)('right'), isUp = (0, _keymap.is)('up'); var scrollStopWaiting = 500; // Wait for finishing scroll animation. var SpotlightAccelerator = new _Accelerator["default"](); var SpottableDiv = (0, _Spottable["default"])('div'); /** * A Sandstone-styled scrollbar track with sandstone behavior * * @class ScrollbarTrack * @memberof sandstone/useScroll * @ui * @private */ var ScrollbarTrack = exports.ScrollbarTrackBase = exports.ScrollbarTrack = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) { var ariaLabel = props['aria-label'], cbAlertScrollbarTrack = props.cbAlertScrollbarTrack, focusableScrollbar = props.focusableScrollbar, onInteractionForScroll = props.onInteractionForScroll, rtl = props.rtl, scrollbarTrackCss = props.scrollbarTrackCss, vertical = props.vertical, rest = _objectWithoutProperties(props, _excluded), className = (0, _classnames["default"])(_ScrollbarTrackModule["default"].scrollbarTrack, _defineProperty(_defineProperty({}, _ScrollbarTrackModule["default"].vertical, vertical), _ScrollbarTrackModule["default"].focusableScrollbar, focusableScrollbar)), ScrollbarThumb = focusableScrollbar ? SpottableDiv : 'div', announceRef = (0, _react.useRef)({}); (0, _react.useEffect)(function () { cbAlertScrollbarTrack(); SpotlightAccelerator.reset(); return function () { SpotlightAccelerator.reset(); }; }, []); // eslint-disable-line react-hooks/exhaustive-deps var consumeEventWithScroll = (0, _react.useCallback)(function (scrollParam, ev) { ev.preventDefault(); ev.stopPropagation(); // stop propagation of React synthetic event to other components like PopupDecorator ev.nativeEvent.stopImmediatePropagation(); // stop propagation of browser native event to Spotlight onInteractionForScroll(scrollParam); }, [onInteractionForScroll]); var onKeyDown = (0, _react.useCallback)(function (ev) { if (SpotlightAccelerator.processKey(ev, nop)) { ev.stopPropagation(); // stop propagation of React synthetic event to other components like PopupDecorator ev.nativeEvent.stopImmediatePropagation(); // stop propagation of browser native event to Spotlight } else { var keyCode = ev.keyCode, isLeftRight = isLeft(keyCode) || isRight(keyCode), isUpDown = isUp(keyCode) || isDown(keyCode), isPageKey = isPageUp(keyCode) || isPageDown(keyCode), scrollParam = { inputType: isPageKey ? 'pageKey' : 'arrowKey', isPagination: isPageKey, isForward: !rtl && isRight(keyCode) || rtl && isLeft(keyCode) || isDown(keyCode) || isPageDown(keyCode), isVerticalScrollBar: vertical }, scrollProgress = Number(ref.current && ref.current.style.getPropertyValue('--scrollbar-thumb-progress-ratio')), scrollSize = Number(ref.current && ref.current.style.getPropertyValue('--scrollbar-thumb-size-ratio')); if (vertical && (isUpDown || isPageKey) || !vertical && isLeftRight) { // Do nothing when (!vertical && pageKey) if (!ev.repeat && announceRef.current.announce) { announceRef.current.announce((isDown(keyCode) || isPageDown(keyCode)) && (0, _$L["default"])('DOWN') || (isUp(keyCode) || isPageUp(keyCode)) && (0, _$L["default"])('UP') || isLeft(keyCode) && (0, _$L["default"])('LEFT') || (0, _$L["default"])('RIGHT') // the case that isRight(keyCode) is true ); } if (ev.repeat || scrollSize !== 1 && (scrollParam.isForward && scrollProgress !== 1 || !scrollParam.isForward && scrollProgress !== 0)) { consumeEventWithScroll(scrollParam, ev); setTimeout(function () { var updatedScrollProgress = Number(ref.current && ref.current.style.getPropertyValue('--scrollbar-thumb-progress-ratio')); var horizontalReachLeftMost = rtl ? updatedScrollProgress === 1 : updatedScrollProgress === 0; var horizontalReachRightMost = rtl ? updatedScrollProgress === 0 : updatedScrollProgress === 1; // Current UX announce only after Scroll via Scrollthumb. if (announceRef.current.announce && (updatedScrollProgress === 0 || updatedScrollProgress === 1)) { announceRef.current.announce((isDown(keyCode) || isPageDown(keyCode)) && updatedScrollProgress === 1 && (0, _$L["default"])('DOWNMOST') || (isUp(keyCode) || isPageUp(keyCode)) && updatedScrollProgress === 0 && (0, _$L["default"])('UPMOST') || isLeft(keyCode) && horizontalReachLeftMost && (0, _$L["default"])('LEFTMOST') || isRight(keyCode) && horizontalReachRightMost && (0, _$L["default"])('RIGHTMOST') // the case that isRight(keyCode) is true ); } }, scrollStopWaiting); } } if (!ev.repeat) { SpotlightAccelerator.reset(); } } }, [consumeEventWithScroll, ref, rtl, vertical]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", _objectSpread(_objectSpread({}, rest), {}, { className: (0, _classnames["default"])(className, scrollbarTrackCss && scrollbarTrackCss.scrollbarTrack), ref: ref, children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(ScrollbarThumb, { "aria-label": ariaLabel, className: (0, _classnames["default"])(_ScrollbarTrackModule["default"].thumb, scrollbarTrackCss && scrollbarTrackCss.thumb), "data-spotlight-ignore-restore": true, onKeyDown: onKeyDown, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: (0, _classnames["default"])(_ScrollbarTrackModule["default"].directionIndicator, _ScrollbarTrackModule["default"].backward) }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: (0, _classnames["default"])(_ScrollbarTrackModule["default"].directionIndicator, _ScrollbarTrackModule["default"].forward) })] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AnnounceDecorator.Announce, { ref: announceRef }, "announce")] })); }); ScrollbarTrack.displayName = 'ScrollbarTrack'; ScrollbarTrack.propTypes = /** @lends sandstone/useScroll.ScrollbarTrack.prototype */{ /** * Called when {@link sandstone/useScroll.ScrollbarTrack|ScrollbarTrack} is updated. * * @type {Function} * @private */ cbAlertScrollbarTrack: _propTypes["default"].func, /** * `true` if scroll thumb is spottable. * * @type {Boolean|'byEnter'} * @private */ focusableScrollbar: _propTypes["default"].oneOfType([_propTypes["default"].bool, _propTypes["default"].oneOf(['byEnter'])]), /** * Called when the user requests scroll. * * @type {Function} * @private */ onInteractionForScroll: _propTypes["default"].func, /** * `true` if rtl, `false` if ltr. * * @type {Boolean} * @private */ rtl: _propTypes["default"].bool, /** * Customizes the component by mapping the supplied collection of CSS class names to the * corresponding internal elements and states of this component. * * The following classes are supported: * * * `scrollbarTrack` - The scrollbarTrack component class * * `thumb` - The scrollbar thumb component class * * @type {Object} * @public */ scrollbarTrackCss: _propTypes["default"].object, /** * `true` if vertical scroll, `false` if horizontal scroll. * * @type {Boolean} * @private */ vertical: _propTypes["default"].bool }; ScrollbarTrack.defaultProps = { cbAlertScrollbarTrack: nop, focusableScrollbar: false, onInteractionForScroll: nop, rtl: false, vertical: true }; var _default = exports["default"] = ScrollbarTrack;