Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@enact/spotlight

Package Overview
Dependencies
Maintainers
1
Versions
218
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@enact/spotlight - npm Package Compare versions

Comparing version 1.0.0-beta.2 to 1.0.0-beta.3

9

CHANGELOG.md

@@ -5,2 +5,11 @@ # Change Log

## [unreleased]
### Fixed
- `spotlight.Spotlight` behavior to follow container config rules when navigating between containers
- `spotlight.Spotlight` behavior to not set focus on spottable components animating past the pointer when not in pointer-mode
- `spotlight.Spotlight` 5-way behavior where selecting a spottable component may require multiple attempts before performing actions
- `spotlight.Spotlight` to not unfocus elements on scroll
## [1.0.0-beta.2] - 2017-01-30

@@ -7,0 +16,0 @@

@@ -65,2 +65,19 @@ ---

Spottable controls can receive `onSpotlight[Direction]` properties to handle custom
navigation actions. This is mainly a convenience function used for preventing natural
5-way behavior and setting focus on specific spottable components that may not normally
be in the next component to be spotted.
```javascript
handleSpotlightDown = (e) => {
e.preventDefault();
e.stopPropagation();
Spotlight.focus('[data-component-id="myButton"]');
}
```
```jsx harmony
<Button data-component-id='myButton'>Source Button</Button>
<Button onSpotlightDown={this.handleSpotlightDown}>Target Button</Button>
```
<a name="4"></a>

@@ -267,2 +284,15 @@ ## 4. Selectors

`onSpotlightLeft`
`onSpotlightRight`
`onSpotlightUp`
`onSpotlightDown`
+ Type: [function]
A callback function to override default spotlight behavior when exiting the spottable control.
`onSpotlightDisappear`
+ Type: [function]
A callback function to be called when the component is removed while retaining focus.
### Container ###

@@ -269,0 +299,0 @@

3

index.js

@@ -6,3 +6,3 @@ 'use strict';

});
exports.getDirection = exports.spotlightDefaultClass = exports.Spottable = exports.SpotlightContainerDecorator = exports.SpotlightRootDecorator = exports.Spotlight = undefined;
exports.getDirection = exports.spotlightDefaultClass = exports.spottableClass = exports.Spottable = exports.SpotlightContainerDecorator = exports.SpotlightRootDecorator = exports.Spotlight = undefined;

@@ -22,3 +22,4 @@ var _spotlight = require('./src/spotlight');

exports.Spottable = _spottable.Spottable;
exports.spottableClass = _spottable.spottableClass;
exports.spotlightDefaultClass = _container.spotlightDefaultClass;
exports.getDirection = _spotlight.getDirection;
{
"name": "@enact/spotlight",
"version": "1.0.0-beta.2",
"version": "1.0.0-beta.3",
"description": "A focus management library",

@@ -22,5 +22,5 @@ "main": "index.js",

"dependencies": {
"@enact/core": "^1.0.0-beta.2",
"@enact/core": "^1.0.0-beta.3",
"react": "~15.4.0"
}
}

@@ -28,4 +28,2 @@ 'use strict';

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -37,4 +35,5 @@

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
var spotlightDefaultClass = 'spottable-default';
var enterEvent = 'onMouseEnter';

@@ -116,4 +115,5 @@ var leaveEvent = 'onMouseLeave';

var forwardMouseLeave = (0, _handle.forward)(leaveEvent);
var preserveId = config.preserveId;
var preserveId = config.preserveId,
containerConfig = _objectWithoutProperties(config, ['preserveId']);

@@ -146,3 +146,5 @@ return _temp = _class = function (_React$Component) {

_this.handleMouseLeave = function (ev) {
_spotlight2.default.setActiveContainer(null);
var parentContainer = ev.currentTarget.parentNode.closest('[data-container-id]');
var activeContainer = parentContainer ? parentContainer.dataset.containerId : null;
_spotlight2.default.setActiveContainer(activeContainer);
forwardMouseLeave(ev, _this.props);

@@ -179,3 +181,3 @@ };

var selector = '[data-container-id="' + this.state.id + '"]:not([data-container-disabled="true"]) .' + _spottable.spottableClass,
cfg = Object.assign({}, config, { selector: selector, navigableFilter: this.navigableFilter, restrict: this.props.spotlightRestrict });
cfg = Object.assign({}, containerConfig, { selector: selector, navigableFilter: this.navigableFilter, restrict: this.props.spotlightRestrict });

@@ -182,0 +184,0 @@ _spotlight2.default.set(this.state.id, cfg);

@@ -31,2 +31,4 @@ 'use strict';

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var isDown = (0, _keymap.is)('down');

@@ -87,4 +89,3 @@ var isEnter = (0, _keymap.is)('enter');

var _pause = false;
var _containers = {};
var _containerCount = 0;
var _containers = new Map();
var _defaultContainerId = '';

@@ -452,3 +453,3 @@ var _lastContainerId = '';

id = _containerPrefix + String(++_ids);
if (!_containers[id]) {
if (!_containers.get(id)) {
break;

@@ -521,3 +522,5 @@ }

function isNavigable(elem, containerId, verifyContainerSelector) {
if (!elem || !containerId || !_containers[containerId] || _containers[containerId].selectorDisabled) {
var config = _containers.get(containerId);
if (!elem || !containerId || !config || config.selectorDisabled) {
return false;

@@ -528,7 +531,7 @@ }

}
if (verifyContainerSelector && !matchSelector(elem, _containers[containerId].selector)) {
if (verifyContainerSelector && !matchSelector(elem, config.selector)) {
return false;
}
if (typeof _containers[containerId].navigableFilter === 'function') {
if (_containers[containerId].navigableFilter(elem, containerId) === false) {
if (typeof config.navigableFilter === 'function') {
if (config.navigableFilter(elem, containerId) === false) {
return false;

@@ -545,4 +548,7 @@ }

function getContainerId(elem) {
for (var id in _containers) {
if (!_containers[id].selectorDisabled && isNavigable(elem, id, true)) {
var containers = [].concat(_toConsumableArray(_containers.keys()));
for (var i = containers.length; i-- > 0;) {
var id = containers[i];
if (!_containers.get(id).selectorDisabled && isNavigable(elem, id, true)) {
return id;

@@ -554,3 +560,3 @@ }

function getContainerNavigableElements(containerId) {
return parseSelector(_containers[containerId].selector).filter(function (elem) {
return parseSelector(_containers.get(containerId).selector).filter(function (elem) {
return isNavigable(elem, containerId);

@@ -561,3 +567,3 @@ });

function getContainerDefaultElement(containerId) {
var defaultElement = _containers[containerId].defaultElement;
var defaultElement = _containers.get(containerId).defaultElement;
if (!defaultElement) {

@@ -576,3 +582,3 @@ return null;

function getContainerLastFocusedElement(containerId) {
var lastFocusedElement = _containers[containerId].lastFocusedElement;
var lastFocusedElement = _containers.get(containerId).lastFocusedElement;
if (!isNavigable(lastFocusedElement, containerId, true)) {

@@ -590,3 +596,3 @@ return null;

if (_pointerMode && !fromPointer) {
_containers[containerId].lastFocusedElement = elem;
_containers.get(containerId).lastFocusedElement = elem;
return false;

@@ -635,3 +641,3 @@ }

if (containerId) {
_containers[containerId].lastFocusedElement = elem;
_containers.get(containerId).lastFocusedElement = elem;
_lastContainerId = containerId;

@@ -664,3 +670,4 @@ }

var addRange = function addRange(id) {
if (id && range.indexOf(id) < 0 && _containers[id] && !_containers[id].selectorDisabled) {
var config = _containers.get(id);
if (id && range.indexOf(id) < 0 && config && !config.selectorDisabled) {
range.push(id);

@@ -675,3 +682,3 @@ }

addRange(_lastContainerId);
Object.keys(_containers).map(addRange);
[].concat(_toConsumableArray(_containers.keys())).map(addRange);
}

@@ -683,3 +690,3 @@

if (_containers[id].enterTo === 'last-focused') {
if (_containers.get(id).enterTo === 'last-focused') {
next = getContainerLastFocusedElement(id) || getContainerDefaultElement(id) || getContainerNavigableElements(id)[0];

@@ -699,5 +706,7 @@ } else {

function gotoLeaveFor(containerId, direction) {
if (_containers[containerId].leaveFor && typeof _containers[containerId].leaveFor[direction] !== 'undefined') {
var next = _containers[containerId].leaveFor[direction];
var config = _containers.get(containerId);
if (config.leaveFor && typeof config.leaveFor[direction] !== 'undefined') {
var next = config.leaveFor[direction];
if (typeof next === 'string') {

@@ -721,6 +730,29 @@ if (next === '') {

var allNavigableElements = [];
for (var id in _containers) {
containerNavigableElements[id] = getContainerNavigableElements(id);
allNavigableElements = allNavigableElements.concat(containerNavigableElements[id]);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = _containers.keys()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var id = _step.value;
containerNavigableElements[id] = getContainerNavigableElements(id);
allNavigableElements = allNavigableElements.concat(containerNavigableElements[id]);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return { allNavigableElements: allNavigableElements, containerNavigableElements: containerNavigableElements };

@@ -744,3 +776,3 @@ }

var enterToElement = void 0;
switch (_containers[nextContainerId].enterTo) {
switch (_containers.get(nextContainerId).enterTo) {
case 'last-focused':

@@ -762,3 +794,3 @@ enterToElement = getContainerLastFocusedElement(nextContainerId) || getContainerDefaultElement(nextContainerId);

function spotNextFromPoint(direction, position, containerId) {
var config = extend({}, GlobalConfig, _containers[containerId]);
var config = extend({}, GlobalConfig, _containers.get(containerId));

@@ -779,3 +811,3 @@ var _getNavigableElements = getNavigableElements(),

if (next) {
_containers[containerId].previous = {
_containers.get(containerId).previous = {
target: getContainerLastFocusedElement(_lastContainerId),

@@ -806,3 +838,3 @@ destination: next,

var config = extend({}, GlobalConfig, _containers[currentContainerId]);
var config = extend({}, GlobalConfig, _containers.get(currentContainerId));
var next = void 0;

@@ -823,3 +855,3 @@

if (next) {
_containers[currentContainerId].previous = {
_containers.get(currentContainerId).previous = {
target: currentFocusedElement,

@@ -868,3 +900,3 @@ destination: next,

function shouldPreventNavigation() {
return !_containerCount || _pause;
return !_containers.size || _pause;
}

@@ -875,3 +907,3 @@

if (!shouldPreventNavigation() && getDirection(keyCode)) {
if (getDirection(keyCode) || isEnter(keyCode)) {
SpotlightAccelerator.reset();

@@ -926,3 +958,5 @@ _5WayKeyHold = false;

function onMouseOver(evt) {
if (shouldPreventNavigation()) {
// a motionless pointer over animated spottable dom (such as list scrolling via 5-way) still emits
// an `onMouseOver` event even when `_pointerMode` is `false`, in which case we terminate early.
if (!_pointerMode || shouldPreventNavigation()) {
return;

@@ -941,2 +975,7 @@ }

function onMouseMove(evt) {
// Chrome emits mousemove on scroll, but client coordinates do not change.
if (!_pointerMode && evt.clientX === _pointerX && evt.clientY === _pointerY) {
return;
}
_pointerMode = true;

@@ -970,6 +1009,27 @@

function isFocusable(elem) {
for (var id in _containers) {
// check *all* the containers to see if the specified element is a focusable element
if (isNavigable(elem, id, true)) return true;
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = _containers.keys()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var id = _step2.value;
// check *all* the containers to see if the specified element is a focusable element
if (isNavigable(elem, id, true)) return true;
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
return false;

@@ -1004,4 +1064,3 @@ }

clear: function clear() {
_containers = {};
_containerCount = 0;
_containers.clear();
_defaultContainerId = '';

@@ -1023,3 +1082,3 @@ _lastContainerId = '';

config = arguments[1];
if (!_containers[containerId]) {
if (!_containers.get(containerId)) {
throw new Error('Container "' + containerId + '" doesn\'t exist!');

@@ -1032,8 +1091,8 @@ }

for (var key in config) {
if (typeof GlobalConfig[key] !== 'undefined') {
if (containerId) {
_containers[containerId][key] = config[key];
} else if (typeof config[key] !== 'undefined') {
GlobalConfig[key] = config[key];
}
var validKey = typeof GlobalConfig[key] !== 'undefined';
if (!containerId && validKey && typeof config[key] !== 'undefined') {
GlobalConfig[key] = config[key];
} else if (containerId && !validKey) {
delete config[key];
}

@@ -1044,3 +1103,3 @@ }

// remove "undefined" items
_containers[containerId] = extend({}, _containers[containerId]);
_containers.set(containerId, extend({}, config));
}

@@ -1066,8 +1125,7 @@ },

if (_containers[containerId]) {
if (_containers.get(containerId)) {
throw new Error('Container "' + containerId + '" has already existed!');
}
_containers[containerId] = {};
_containerCount++;
_containers.set(containerId, config);

@@ -1083,6 +1141,4 @@ Spotlight.set(containerId, config);

}
if (_containers[containerId]) {
_containers[containerId] = void 0;
_containers = extend({}, _containers);
_containerCount--;
if (_containers.get(containerId)) {
_containers.delete(containerId);
if (_lastContainerId === containerId) {

@@ -1097,4 +1153,7 @@ Spotlight.setActiveContainer(null);

disableSelector: function disableSelector(containerId) {
if (_containers[containerId]) {
_containers[containerId].selectorDisabled = true;
var config = _containers.get(containerId);
if (config) {
config.selectorDisabled = true;
_containers.set(containerId, config);
return true;

@@ -1106,4 +1165,7 @@ }

enableSelector: function enableSelector(containerId) {
if (_containers[containerId]) {
_containers[containerId].selectorDisabled = false;
var config = _containers.get(containerId);
if (config) {
config.selectorDisabled = false;
_containers.set(containerId, config);
return true;

@@ -1143,3 +1205,3 @@ }

} else if (typeof elem === 'string') {
if (_containers[elem]) {
if (_containers.get(elem)) {
result = focusContainer(elem);

@@ -1190,3 +1252,3 @@ } else {

_defaultContainerId = '';
} else if (!_containers[containerId]) {
} else if (!_containers.get(containerId)) {
throw new Error('Container "' + containerId + '" doesn\'t exist!');

@@ -1193,0 +1255,0 @@ } else {

@@ -288,3 +288,3 @@ 'use strict';

/**
* Whether or not the component can be navigated using spotlight.
* When `true`, the component cannot be navigated using spotlight.
*

@@ -291,0 +291,0 @@ * @type {Boolean}

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc