UNPKG

@enact/sandstone

Version:

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

157 lines (145 loc) 5.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useSpotlightRestore = exports.useSpotlightConfig = void 0; var _spotlight = _interopRequireDefault(require("@enact/spotlight")); var _utilDOM = _interopRequireDefault(require("@enact/ui/useScroll/utilDOM")); var _react = require("react"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } var useSpotlightConfig = exports.useSpotlightConfig = function useSpotlightConfig(props, instances) { // Hooks (0, _react.useEffect)(function () { function lastFocusedPersist() { var lastFocusedIndex = instances.spottable.current.lastFocusedIndex; if (lastFocusedIndex != null) { return { container: false, element: true, key: lastFocusedIndex }; } } function lastFocusedRestore(_ref, all) { var key = _ref.key; var placeholder = all.find(function (el) { return 'vlPlaceholder' in el.dataset; }); if (placeholder) { placeholder.dataset.index = key; return placeholder; } return all.reduce(function (focused, node) { return focused || Number(node.dataset.index) === key && node; }, null); } function configureSpotlight() { var spacing = props.spacing, spotlightId = props.spotlightId; _spotlight["default"].set(spotlightId, { enterTo: 'last-focused', /* * Returns the data-index as the key for last focused */ lastFocusedPersist: lastFocusedPersist, /* * Restores the data-index into the placeholder if its the only element. Tries to find a * matching child otherwise. */ lastFocusedRestore: lastFocusedRestore, /* * Directs spotlight focus to favor straight elements that are within range of `spacing` * over oblique elements, like scroll buttons. */ obliqueMultiplier: spacing > 0 ? spacing : 1 }); } configureSpotlight(); }, [props, instances]); }; var getNumberValue = function getNumberValue(index) { // using '+ operator' for string > number conversion based on performance: https://jsperf.com/convert-string-to-number-techniques/7 var number = +index; // should return -1 if index is not a number or a negative value return number >= 0 ? number : -1; }; var useSpotlightRestore = exports.useSpotlightRestore = function useSpotlightRestore(props, instances, context) { var scrollContentRef = instances.scrollContentRef, spottable = instances.spottable; var focusByIndex = context.focusByIndex, getItemNode = context.getItemNode; // Mutable value var mutableRef = (0, _react.useRef)({ preservedIndex: false, lastSpotlightDirection: null, restoreLastFocused: false }); // Hooks (0, _react.useEffect)(restoreFocus); // Functions function handlePlaceholderFocus(ev) { var placeholder = ev.currentTarget; if (placeholder) { var index = placeholder.dataset.index; if (index) { mutableRef.current.preservedIndex = getNumberValue(index); mutableRef.current.lastSpotlightDirection = null; mutableRef.current.restoreLastFocused = true; } } } function isPlaceholderFocused() { var current = _spotlight["default"].getCurrent(); if (current && current.dataset.vlPlaceholder && _utilDOM["default"].containsDangerously(scrollContentRef.current, current)) { return true; } return false; } function restoreFocus() { if (mutableRef.current.restoreLastFocused && !isPlaceholderFocused()) { var spotlightId = props.spotlightId, itemNode = getItemNode(mutableRef.current.preservedIndex); if (itemNode) { // if we're supposed to restore focus and virtual list has positioned a set of items // that includes lastFocusedIndex, clear the indicator mutableRef.current.restoreLastFocused = false; // try to focus the last focused item spottable.current.isScrolledByJump = true; var foundLastFocused = focusByIndex(mutableRef.current.preservedIndex, mutableRef.current.lastSpotlightDirection); spottable.current.isScrolledByJump = false; // but if that fails (because it isn't found or is disabled), focus the container so // spotlight isn't lost if (!foundLastFocused) { mutableRef.current.restoreLastFocused = true; _spotlight["default"].focus(spotlightId); } } } } function handleRestoreLastFocus(_ref2) { var firstIndex = _ref2.firstIndex, lastIndex = _ref2.lastIndex; if (mutableRef.current.restoreLastFocused && mutableRef.current.preservedIndex >= firstIndex && mutableRef.current.preservedIndex <= lastIndex) { restoreFocus(); } } function updateStatesAndBounds(_ref3) { var dataSize = _ref3.dataSize, moreInfo = _ref3.moreInfo, numOfItems = _ref3.numOfItems; return mutableRef.current.restoreLastFocused && numOfItems > 0 && mutableRef.current.preservedIndex < dataSize && (mutableRef.current.preservedIndex < moreInfo.firstVisibleIndex || mutableRef.current.preservedIndex > moreInfo.lastVisibleIndex); } function setPreservedIndex(index) { var direction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; mutableRef.current.preservedIndex = index; mutableRef.current.lastSpotlightDirection = direction; mutableRef.current.restoreLastFocused = true; } // Return return { handlePlaceholderFocus: handlePlaceholderFocus, handleRestoreLastFocus: handleRestoreLastFocus, setPreservedIndex: setPreservedIndex, updateStatesAndBounds: updateStatesAndBounds }; };