react-downscreen
Advanced tools
Comparing version 0.3.0 to 0.3.1
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var React = require('react'); | ||
var scrollIntoViewIfNeeded = _interopDefault(require('scroll-into-view-if-needed')); | ||
var initialState = { | ||
isOpen: false, | ||
selectedIndex: null, | ||
highlightedIndex: null, | ||
inputValue: '', | ||
lastSelectedInputValue: null, | ||
lastKeyOnClose: null | ||
}; | ||
var DownscreenContext = React.createContext({ | ||
state: initialState, | ||
setState: function setState() {}, | ||
totalCount: 0, | ||
id: '', | ||
getMenuItemsRef: function getMenuItemsRef() { | ||
return { | ||
current: {} | ||
}; | ||
} | ||
}); | ||
var useEffectAfterMount = function useEffectAfterMount(cb, deps) { | ||
var justMounted = React.useRef(true); | ||
React.useEffect(function () { | ||
if (!justMounted.current) { | ||
return cb(); | ||
} | ||
justMounted.current = false; | ||
}, deps); | ||
}; | ||
var getFirstPossibleIndex = function getFirstPossibleIndex(totalCount, map) { | ||
for (var i = 0; i < totalCount; i++) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
return null; | ||
}; | ||
var getLastPossibleIndex = function getLastPossibleIndex(totalCount, map) { | ||
for (var i = totalCount - 1; i >= 0; i--) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
return null; | ||
}; | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys(source, true).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _slicedToArray(arr, i) { | ||
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); | ||
} | ||
function _nonIterableRest() { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
function _iterableToArrayLimit(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"] != null) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
function _arrayWithHoles(arr) { | ||
if (Array.isArray(arr)) return arr; | ||
} | ||
// TODO: clean up state management (useReducer), memoize more for better performance (useMemo) | ||
var Downscreen = function Downscreen(_ref) { | ||
var children = _ref.children, | ||
_ref$onSelect = _ref.onSelect, | ||
onSelect = _ref$onSelect === void 0 ? function () {} : _ref$onSelect, | ||
_ref$initial = _ref.initial, | ||
initial = _ref$initial === void 0 ? initialState : _ref$initial, | ||
totalCount = _ref.totalCount, | ||
id = _ref.id, | ||
className = _ref.className, | ||
style = _ref.style; | ||
var menuItemsRef = React.useRef({}); | ||
var _React$useState = React.useState(initial), | ||
_React$useState2 = _slicedToArray(_React$useState, 2), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; | ||
var value = React.useMemo(function () { | ||
return { | ||
state: state, | ||
setState: setState, | ||
totalCount: totalCount, | ||
id: id, | ||
getMenuItemsRef: function getMenuItemsRef() { | ||
return menuItemsRef; | ||
} | ||
}; | ||
}, [state, totalCount, id]); | ||
useEffectAfterMount(function () { | ||
if (state.isOpen) { | ||
switch (state.lastKeyOnClose) { | ||
case 'ArrowUp': | ||
{ | ||
setState(function (s) { | ||
return _objectSpread({}, s, { | ||
highlightedIndex: getLastPossibleIndex(totalCount, menuItemsRef.current), | ||
lastKeyOnClose: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'ArrowDown': | ||
{ | ||
setState(function (s) { | ||
return _objectSpread({}, s, { | ||
highlightedIndex: getFirstPossibleIndex(totalCount, menuItemsRef.current), | ||
lastKeyOnClose: null | ||
}); | ||
}); | ||
break; | ||
} | ||
} | ||
} | ||
}, [state.isOpen]); | ||
useEffectAfterMount(function () { | ||
onSelect(state.selectedIndex); | ||
}, [state.selectedIndex]); | ||
return React.createElement(DownscreenContext.Provider, { | ||
value: value | ||
}, React.createElement("div", { | ||
id: id, | ||
role: "combobox", | ||
"aria-haspopup": "listbox", | ||
"aria-expanded": state.isOpen, | ||
"aria-controls": state.isOpen ? "".concat(id, "-menu") : undefined, | ||
"aria-owns": state.isOpen ? "".concat(id, "-menu") : undefined, | ||
"aria-labelledby": "".concat(id, "-label"), | ||
className: className, | ||
style: style | ||
}, children)); | ||
}; | ||
var normalizeArrowKey = function normalizeArrowKey(event) { | ||
var key = event.key, | ||
keyCode = event.keyCode; | ||
if (keyCode >= 37 && keyCode <= 40 && key.indexOf('Arrow') !== 0) { | ||
return "Arrow".concat(key); | ||
} | ||
return key; | ||
}; | ||
var getNextIndex = function getNextIndex(currentIndex, totalCount, map) { | ||
for (var i = currentIndex === null ? 0 : currentIndex + 1; i < totalCount; i++) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
return getFirstPossibleIndex(totalCount, map); | ||
}; | ||
var getPreviousIndex = function getPreviousIndex(currentIndex, totalCount, map) { | ||
if (currentIndex !== null) { | ||
for (var i = currentIndex - 1; i >= 0; i--) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
} | ||
return getLastPossibleIndex(totalCount, map); | ||
}; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function ownKeys$1(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread$1(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys$1(source, true).forEach(function (key) { | ||
_defineProperty$1(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys$1(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty$1(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
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 Button = function Button(_ref) { | ||
var children = _ref.children, | ||
props = _objectWithoutProperties(_ref, ["children"]); | ||
var _React$useContext = React.useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
setState = _React$useContext.setState, | ||
totalCount = _React$useContext.totalCount, | ||
id = _React$useContext.id, | ||
getMenuItemsRef = _React$useContext.getMenuItemsRef; | ||
var onBlur = React.useCallback(function () { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: false, | ||
highlightedIndex: null | ||
}); | ||
}); | ||
}, []); | ||
var onKeyUp = React.useCallback(function (event) { | ||
event.preventDefault(); | ||
}, []); | ||
var onKeyDown = React.useCallback(function (event) { | ||
var key = normalizeArrowKey(event); | ||
switch (key) { | ||
case ' ': | ||
{ | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: !s.isOpen, | ||
highlightedIndex: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'Enter': | ||
{ | ||
if (state.isOpen) { | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: false, | ||
selectedIndex: s.highlightedIndex === null ? s.selectedIndex : s.highlightedIndex, | ||
highlightedIndex: null | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'Escape': | ||
{ | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: false, | ||
selectedIndex: null, | ||
highlightedIndex: null, | ||
inputValue: '', | ||
lastSelectedInputValue: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'ArrowUp': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
highlightedIndex: getPreviousIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowUp' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'ArrowDown': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
highlightedIndex: getNextIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowDown' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
} | ||
}, [totalCount, state.highlightedIndex, state.isOpen]); | ||
var onClick = React.useCallback(function (event) { | ||
event.preventDefault(); | ||
event.target.focus(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: !s.isOpen | ||
}); | ||
}); | ||
}, []); | ||
var buttonChildren = React.useMemo(function () { | ||
return children(state.selectedIndex); | ||
}, [state.selectedIndex]); | ||
return React.createElement("button", _extends({ | ||
"aria-label": state.isOpen ? 'close menu' : 'open menu', | ||
"aria-haspopup": true, | ||
"data-toggle": true, | ||
id: "".concat(id, "-button"), | ||
role: "button", | ||
type: "button", | ||
onBlur: onBlur, | ||
onKeyUp: onKeyUp, | ||
onKeyDown: onKeyDown, | ||
onClick: onClick | ||
}, props), buttonChildren); | ||
}; | ||
function _extends$1() { | ||
_extends$1 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$1.apply(this, arguments); | ||
} | ||
function ownKeys$2(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread$2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys$2(source, true).forEach(function (key) { | ||
_defineProperty$2(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys$2(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty$2(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _objectWithoutProperties$1(source, excluded) { | ||
if (source == null) return {}; | ||
var target = _objectWithoutPropertiesLoose$1(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$1(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 Input = function Input(_ref) { | ||
var children = _ref.children, | ||
props = _objectWithoutProperties$1(_ref, ["children"]); | ||
var _React$useContext = React.useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
setState = _React$useContext.setState, | ||
totalCount = _React$useContext.totalCount, | ||
id = _React$useContext.id, | ||
getMenuItemsRef = _React$useContext.getMenuItemsRef; | ||
var onChange = React.useCallback(function (event) { | ||
var inputValue = event.target.value; | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: true, | ||
highlightedIndex: null, | ||
inputValue: inputValue | ||
}); | ||
}); | ||
}, []); | ||
var onBlur = React.useCallback(function () { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: false, | ||
highlightedIndex: null, | ||
inputValue: typeof s.lastSelectedInputValue === 'string' ? s.lastSelectedInputValue : s.inputValue | ||
}); | ||
}); | ||
}, []); | ||
var onKeyDown = React.useCallback(function (event) { | ||
var key = normalizeArrowKey(event); | ||
switch (key) { | ||
case 'Enter': | ||
{ | ||
if (state.isOpen) { | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: false, | ||
selectedIndex: s.highlightedIndex === null ? s.selectedIndex : s.highlightedIndex, | ||
highlightedIndex: null, | ||
inputValue: typeof s.lastSelectedInputValue === 'string' && s.selectedIndex === s.highlightedIndex ? s.lastSelectedInputValue : s.inputValue | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'Escape': | ||
{ | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: false, | ||
selectedIndex: null, | ||
highlightedIndex: null, | ||
inputValue: '', | ||
lastSelectedInputValue: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'End': | ||
case 'ArrowUp': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
highlightedIndex: getPreviousIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowUp' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'Home': | ||
case 'ArrowDown': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
highlightedIndex: getNextIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowDown' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
} | ||
}, [totalCount, state.highlightedIndex, state.isOpen]); | ||
var inputChildren = React.useMemo(function () { | ||
return children(state.selectedIndex); | ||
}, [state.selectedIndex]); | ||
useEffectAfterMount(function () { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
inputValue: typeof inputChildren === 'string' ? inputChildren : s.inputValue, | ||
lastSelectedInputValue: typeof inputChildren === 'string' ? inputChildren : s.lastSelectedInputValue | ||
}); | ||
}); | ||
}, [inputChildren]); | ||
return React.createElement("input", _extends$1({ | ||
"aria-autocomplete": "list", | ||
"aria-activedescendant": state.isOpen && state.highlightedIndex !== null ? "".concat(id, "-menu-item-").concat(state.highlightedIndex) : undefined, | ||
"aria-controls": state.isOpen ? "".concat(id, "-menu") : undefined, | ||
"aria-labelledby": "".concat(id, "-label"), | ||
autoComplete: "off", | ||
id: "".concat(id, "-input"), | ||
type: "text", | ||
value: state.inputValue, | ||
onChange: onChange, | ||
onBlur: onBlur, | ||
onKeyDown: onKeyDown | ||
}, props)); | ||
}; | ||
function _extends$2() { | ||
_extends$2 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$2.apply(this, arguments); | ||
} | ||
var Label = function Label(props) { | ||
var _React$useContext = React.useContext(DownscreenContext), | ||
id = _React$useContext.id; | ||
return React.createElement("label", _extends$2({ | ||
id: "".concat(id, "-label"), | ||
htmlFor: "".concat(id, "-input") | ||
}, props)); | ||
}; | ||
function _extends$3() { | ||
_extends$3 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$3.apply(this, arguments); | ||
} | ||
function _objectWithoutProperties$2(source, excluded) { | ||
if (source == null) return {}; | ||
var target = _objectWithoutPropertiesLoose$2(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$2(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 Menu = function Menu(_ref) { | ||
var children = _ref.children, | ||
props = _objectWithoutProperties$2(_ref, ["children"]); | ||
var _React$useContext = React.useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
totalCount = _React$useContext.totalCount, | ||
id = _React$useContext.id; | ||
var menuChildren = React.useMemo(function () { | ||
return Array.from({ | ||
length: totalCount | ||
}, function (_, index) { | ||
return children({ | ||
index: index, | ||
selectedIndex: state.selectedIndex, | ||
highlightedIndex: state.highlightedIndex, | ||
inputValue: state.inputValue | ||
}); | ||
}); | ||
}, [state.selectedIndex, state.highlightedIndex, state.inputValue]); | ||
return state.isOpen ? React.createElement("div", _extends$3({ | ||
id: "".concat(id, "-menu"), | ||
role: "listbox" | ||
}, props), menuChildren) : null; | ||
}; | ||
function _extends$4() { | ||
_extends$4 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$4.apply(this, arguments); | ||
} | ||
function ownKeys$3(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread$3(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys$3(source, true).forEach(function (key) { | ||
_defineProperty$3(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys$3(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty$3(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _objectWithoutProperties$3(source, excluded) { | ||
if (source == null) return {}; | ||
var target = _objectWithoutPropertiesLoose$3(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$3(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 MenuItem = function MenuItem(_ref) { | ||
var index = _ref.index, | ||
children = _ref.children, | ||
props = _objectWithoutProperties$3(_ref, ["index", "children"]); | ||
var _React$useContext = React.useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
setState = _React$useContext.setState, | ||
id = _React$useContext.id, | ||
getMenuItemsRef = _React$useContext.getMenuItemsRef; | ||
var shouldScroll = React.useRef(true); | ||
var scrollRef = React.useRef(null); | ||
React.useEffect(function () { | ||
getMenuItemsRef().current = _objectSpread$3({}, getMenuItemsRef().current, _defineProperty$3({}, index, true)); | ||
return function () { | ||
getMenuItemsRef().current = _objectSpread$3({}, getMenuItemsRef().current, _defineProperty$3({}, index, false)); | ||
}; | ||
}, []); | ||
React.useEffect(function () { | ||
if (state.highlightedIndex === index && shouldScroll.current && scrollRef.current) { | ||
scrollIntoViewIfNeeded(scrollRef.current, { | ||
scrollMode: 'if-needed', | ||
block: 'nearest', | ||
inline: 'nearest' | ||
}); | ||
} | ||
if (!shouldScroll.current) { | ||
shouldScroll.current = true; | ||
} | ||
}, [state.highlightedIndex, index]); | ||
var onClick = React.useCallback(function () { | ||
setState(function (s) { | ||
return _objectSpread$3({}, s, { | ||
isOpen: false, | ||
selectedIndex: index, | ||
highlightedIndex: null, | ||
inputValue: typeof s.lastSelectedInputValue === 'string' && s.selectedIndex === s.highlightedIndex ? s.lastSelectedInputValue : s.inputValue | ||
}); | ||
}); | ||
}, [index]); | ||
var onMouseMove = React.useCallback(function () { | ||
if (state.highlightedIndex !== index) { | ||
shouldScroll.current = false; | ||
setState(function (s) { | ||
return _objectSpread$3({}, s, { | ||
highlightedIndex: index | ||
}); | ||
}); | ||
} | ||
}, [state.highlightedIndex, index]); | ||
var onMouseDown = React.useCallback(function (event) { | ||
event.preventDefault(); | ||
}, []); | ||
return React.createElement("div", _extends$4({ | ||
ref: scrollRef, | ||
"aria-selected": state.highlightedIndex === index, | ||
id: "".concat(id, "-menu-item-").concat(index), | ||
role: "option", | ||
onClick: onClick, | ||
onMouseMove: onMouseMove, | ||
onMouseDown: onMouseDown | ||
}, props), children); | ||
}; | ||
exports.Button = Button; | ||
exports.Input = Input; | ||
exports.Label = Label; | ||
exports.Menu = Menu; | ||
exports.MenuItem = MenuItem; | ||
exports.default = Downscreen; |
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { if (i % 2) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } else { Object.defineProperties(target, Object.getOwnPropertyDescriptors(arguments[i])); } } return target; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -6,0 +8,0 @@ |
@@ -1,3 +0,5 @@ | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { if (i % 2) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } else { Object.defineProperties(target, Object.getOwnPropertyDescriptors(arguments[i])); } } return target; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -4,0 +6,0 @@ |
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { if (i % 2) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } else { Object.defineProperties(target, Object.getOwnPropertyDescriptors(arguments[i])); } } return target; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -6,0 +8,0 @@ |
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { if (i % 2) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } else { Object.defineProperties(target, Object.getOwnPropertyDescriptors(arguments[i])); } } return target; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -6,0 +8,0 @@ |
@@ -0,1 +1,1009 @@ | ||
import { createContext, useRef, useEffect, useState, useMemo, createElement, useContext, useCallback } from 'react'; | ||
import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'; | ||
var initialState = { | ||
isOpen: false, | ||
selectedIndex: null, | ||
highlightedIndex: null, | ||
inputValue: '', | ||
lastSelectedInputValue: null, | ||
lastKeyOnClose: null | ||
}; | ||
var DownscreenContext = createContext({ | ||
state: initialState, | ||
setState: function setState() {}, | ||
totalCount: 0, | ||
id: '', | ||
getMenuItemsRef: function getMenuItemsRef() { | ||
return { | ||
current: {} | ||
}; | ||
} | ||
}); | ||
var useEffectAfterMount = function useEffectAfterMount(cb, deps) { | ||
var justMounted = useRef(true); | ||
useEffect(function () { | ||
if (!justMounted.current) { | ||
return cb(); | ||
} | ||
justMounted.current = false; | ||
}, deps); | ||
}; | ||
var getFirstPossibleIndex = function getFirstPossibleIndex(totalCount, map) { | ||
for (var i = 0; i < totalCount; i++) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
return null; | ||
}; | ||
var getLastPossibleIndex = function getLastPossibleIndex(totalCount, map) { | ||
for (var i = totalCount - 1; i >= 0; i--) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
return null; | ||
}; | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys(source, true).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _slicedToArray(arr, i) { | ||
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); | ||
} | ||
function _nonIterableRest() { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
function _iterableToArrayLimit(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"] != null) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
function _arrayWithHoles(arr) { | ||
if (Array.isArray(arr)) return arr; | ||
} | ||
// TODO: clean up state management (useReducer), memoize more for better performance (useMemo) | ||
var Downscreen = function Downscreen(_ref) { | ||
var children = _ref.children, | ||
_ref$onSelect = _ref.onSelect, | ||
onSelect = _ref$onSelect === void 0 ? function () {} : _ref$onSelect, | ||
_ref$initial = _ref.initial, | ||
initial = _ref$initial === void 0 ? initialState : _ref$initial, | ||
totalCount = _ref.totalCount, | ||
id = _ref.id, | ||
className = _ref.className, | ||
style = _ref.style; | ||
var menuItemsRef = useRef({}); | ||
var _React$useState = useState(initial), | ||
_React$useState2 = _slicedToArray(_React$useState, 2), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; | ||
var value = useMemo(function () { | ||
return { | ||
state: state, | ||
setState: setState, | ||
totalCount: totalCount, | ||
id: id, | ||
getMenuItemsRef: function getMenuItemsRef() { | ||
return menuItemsRef; | ||
} | ||
}; | ||
}, [state, totalCount, id]); | ||
useEffectAfterMount(function () { | ||
if (state.isOpen) { | ||
switch (state.lastKeyOnClose) { | ||
case 'ArrowUp': | ||
{ | ||
setState(function (s) { | ||
return _objectSpread({}, s, { | ||
highlightedIndex: getLastPossibleIndex(totalCount, menuItemsRef.current), | ||
lastKeyOnClose: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'ArrowDown': | ||
{ | ||
setState(function (s) { | ||
return _objectSpread({}, s, { | ||
highlightedIndex: getFirstPossibleIndex(totalCount, menuItemsRef.current), | ||
lastKeyOnClose: null | ||
}); | ||
}); | ||
break; | ||
} | ||
} | ||
} | ||
}, [state.isOpen]); | ||
useEffectAfterMount(function () { | ||
onSelect(state.selectedIndex); | ||
}, [state.selectedIndex]); | ||
return createElement(DownscreenContext.Provider, { | ||
value: value | ||
}, createElement("div", { | ||
id: id, | ||
role: "combobox", | ||
"aria-haspopup": "listbox", | ||
"aria-expanded": state.isOpen, | ||
"aria-controls": state.isOpen ? "".concat(id, "-menu") : undefined, | ||
"aria-owns": state.isOpen ? "".concat(id, "-menu") : undefined, | ||
"aria-labelledby": "".concat(id, "-label"), | ||
className: className, | ||
style: style | ||
}, children)); | ||
}; | ||
var normalizeArrowKey = function normalizeArrowKey(event) { | ||
var key = event.key, | ||
keyCode = event.keyCode; | ||
if (keyCode >= 37 && keyCode <= 40 && key.indexOf('Arrow') !== 0) { | ||
return "Arrow".concat(key); | ||
} | ||
return key; | ||
}; | ||
var getNextIndex = function getNextIndex(currentIndex, totalCount, map) { | ||
for (var i = currentIndex === null ? 0 : currentIndex + 1; i < totalCount; i++) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
return getFirstPossibleIndex(totalCount, map); | ||
}; | ||
var getPreviousIndex = function getPreviousIndex(currentIndex, totalCount, map) { | ||
if (currentIndex !== null) { | ||
for (var i = currentIndex - 1; i >= 0; i--) { | ||
if (map[i]) { | ||
return i; | ||
} | ||
} | ||
} | ||
return getLastPossibleIndex(totalCount, map); | ||
}; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function ownKeys$1(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread$1(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys$1(source, true).forEach(function (key) { | ||
_defineProperty$1(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys$1(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty$1(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
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 Button = function Button(_ref) { | ||
var children = _ref.children, | ||
props = _objectWithoutProperties(_ref, ["children"]); | ||
var _React$useContext = useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
setState = _React$useContext.setState, | ||
totalCount = _React$useContext.totalCount, | ||
id = _React$useContext.id, | ||
getMenuItemsRef = _React$useContext.getMenuItemsRef; | ||
var onBlur = useCallback(function () { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: false, | ||
highlightedIndex: null | ||
}); | ||
}); | ||
}, []); | ||
var onKeyUp = useCallback(function (event) { | ||
event.preventDefault(); | ||
}, []); | ||
var onKeyDown = useCallback(function (event) { | ||
var key = normalizeArrowKey(event); | ||
switch (key) { | ||
case ' ': | ||
{ | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: !s.isOpen, | ||
highlightedIndex: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'Enter': | ||
{ | ||
if (state.isOpen) { | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: false, | ||
selectedIndex: s.highlightedIndex === null ? s.selectedIndex : s.highlightedIndex, | ||
highlightedIndex: null | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'Escape': | ||
{ | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: false, | ||
selectedIndex: null, | ||
highlightedIndex: null, | ||
inputValue: '', | ||
lastSelectedInputValue: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'ArrowUp': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
highlightedIndex: getPreviousIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowUp' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'ArrowDown': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
highlightedIndex: getNextIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowDown' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
} | ||
}, [totalCount, state.highlightedIndex, state.isOpen]); | ||
var onClick = useCallback(function (event) { | ||
event.preventDefault(); | ||
event.target.focus(); | ||
setState(function (s) { | ||
return _objectSpread$1({}, s, { | ||
isOpen: !s.isOpen | ||
}); | ||
}); | ||
}, []); | ||
var buttonChildren = useMemo(function () { | ||
return children(state.selectedIndex); | ||
}, [state.selectedIndex]); | ||
return createElement("button", _extends({ | ||
"aria-label": state.isOpen ? 'close menu' : 'open menu', | ||
"aria-haspopup": true, | ||
"data-toggle": true, | ||
id: "".concat(id, "-button"), | ||
role: "button", | ||
type: "button", | ||
onBlur: onBlur, | ||
onKeyUp: onKeyUp, | ||
onKeyDown: onKeyDown, | ||
onClick: onClick | ||
}, props), buttonChildren); | ||
}; | ||
function _extends$1() { | ||
_extends$1 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$1.apply(this, arguments); | ||
} | ||
function ownKeys$2(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread$2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys$2(source, true).forEach(function (key) { | ||
_defineProperty$2(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys$2(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty$2(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _objectWithoutProperties$1(source, excluded) { | ||
if (source == null) return {}; | ||
var target = _objectWithoutPropertiesLoose$1(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$1(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 Input = function Input(_ref) { | ||
var children = _ref.children, | ||
props = _objectWithoutProperties$1(_ref, ["children"]); | ||
var _React$useContext = useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
setState = _React$useContext.setState, | ||
totalCount = _React$useContext.totalCount, | ||
id = _React$useContext.id, | ||
getMenuItemsRef = _React$useContext.getMenuItemsRef; | ||
var onChange = useCallback(function (event) { | ||
var inputValue = event.target.value; | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: true, | ||
highlightedIndex: null, | ||
inputValue: inputValue | ||
}); | ||
}); | ||
}, []); | ||
var onBlur = useCallback(function () { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: false, | ||
highlightedIndex: null, | ||
inputValue: typeof s.lastSelectedInputValue === 'string' ? s.lastSelectedInputValue : s.inputValue | ||
}); | ||
}); | ||
}, []); | ||
var onKeyDown = useCallback(function (event) { | ||
var key = normalizeArrowKey(event); | ||
switch (key) { | ||
case 'Enter': | ||
{ | ||
if (state.isOpen) { | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: false, | ||
selectedIndex: s.highlightedIndex === null ? s.selectedIndex : s.highlightedIndex, | ||
highlightedIndex: null, | ||
inputValue: typeof s.lastSelectedInputValue === 'string' && s.selectedIndex === s.highlightedIndex ? s.lastSelectedInputValue : s.inputValue | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'Escape': | ||
{ | ||
event.preventDefault(); | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: false, | ||
selectedIndex: null, | ||
highlightedIndex: null, | ||
inputValue: '', | ||
lastSelectedInputValue: null | ||
}); | ||
}); | ||
break; | ||
} | ||
case 'End': | ||
case 'ArrowUp': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
highlightedIndex: getPreviousIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowUp' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'Home': | ||
case 'ArrowDown': | ||
{ | ||
event.preventDefault(); | ||
if (state.isOpen) { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
highlightedIndex: getNextIndex(s.highlightedIndex, totalCount, getMenuItemsRef().current) | ||
}); | ||
}); | ||
} else { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
isOpen: true, | ||
lastKeyOnClose: 'ArrowDown' | ||
}); | ||
}); | ||
} | ||
break; | ||
} | ||
} | ||
}, [totalCount, state.highlightedIndex, state.isOpen]); | ||
var inputChildren = useMemo(function () { | ||
return children(state.selectedIndex); | ||
}, [state.selectedIndex]); | ||
useEffectAfterMount(function () { | ||
setState(function (s) { | ||
return _objectSpread$2({}, s, { | ||
inputValue: typeof inputChildren === 'string' ? inputChildren : s.inputValue, | ||
lastSelectedInputValue: typeof inputChildren === 'string' ? inputChildren : s.lastSelectedInputValue | ||
}); | ||
}); | ||
}, [inputChildren]); | ||
return createElement("input", _extends$1({ | ||
"aria-autocomplete": "list", | ||
"aria-activedescendant": state.isOpen && state.highlightedIndex !== null ? "".concat(id, "-menu-item-").concat(state.highlightedIndex) : undefined, | ||
"aria-controls": state.isOpen ? "".concat(id, "-menu") : undefined, | ||
"aria-labelledby": "".concat(id, "-label"), | ||
autoComplete: "off", | ||
id: "".concat(id, "-input"), | ||
type: "text", | ||
value: state.inputValue, | ||
onChange: onChange, | ||
onBlur: onBlur, | ||
onKeyDown: onKeyDown | ||
}, props)); | ||
}; | ||
function _extends$2() { | ||
_extends$2 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$2.apply(this, arguments); | ||
} | ||
var Label = function Label(props) { | ||
var _React$useContext = useContext(DownscreenContext), | ||
id = _React$useContext.id; | ||
return createElement("label", _extends$2({ | ||
id: "".concat(id, "-label"), | ||
htmlFor: "".concat(id, "-input") | ||
}, props)); | ||
}; | ||
function _extends$3() { | ||
_extends$3 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$3.apply(this, arguments); | ||
} | ||
function _objectWithoutProperties$2(source, excluded) { | ||
if (source == null) return {}; | ||
var target = _objectWithoutPropertiesLoose$2(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$2(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 Menu = function Menu(_ref) { | ||
var children = _ref.children, | ||
props = _objectWithoutProperties$2(_ref, ["children"]); | ||
var _React$useContext = useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
totalCount = _React$useContext.totalCount, | ||
id = _React$useContext.id; | ||
var menuChildren = useMemo(function () { | ||
return Array.from({ | ||
length: totalCount | ||
}, function (_, index) { | ||
return children({ | ||
index: index, | ||
selectedIndex: state.selectedIndex, | ||
highlightedIndex: state.highlightedIndex, | ||
inputValue: state.inputValue | ||
}); | ||
}); | ||
}, [state.selectedIndex, state.highlightedIndex, state.inputValue]); | ||
return state.isOpen ? createElement("div", _extends$3({ | ||
id: "".concat(id, "-menu"), | ||
role: "listbox" | ||
}, props), menuChildren) : null; | ||
}; | ||
function _extends$4() { | ||
_extends$4 = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends$4.apply(this, arguments); | ||
} | ||
function ownKeys$3(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
keys.push.apply(keys, Object.getOwnPropertySymbols(object)); | ||
} | ||
if (enumerableOnly) keys = keys.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
return keys; | ||
} | ||
function _objectSpread$3(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys$3(source, true).forEach(function (key) { | ||
_defineProperty$3(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys$3(source).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
function _defineProperty$3(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _objectWithoutProperties$3(source, excluded) { | ||
if (source == null) return {}; | ||
var target = _objectWithoutPropertiesLoose$3(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$3(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 MenuItem = function MenuItem(_ref) { | ||
var index = _ref.index, | ||
children = _ref.children, | ||
props = _objectWithoutProperties$3(_ref, ["index", "children"]); | ||
var _React$useContext = useContext(DownscreenContext), | ||
state = _React$useContext.state, | ||
setState = _React$useContext.setState, | ||
id = _React$useContext.id, | ||
getMenuItemsRef = _React$useContext.getMenuItemsRef; | ||
var shouldScroll = useRef(true); | ||
var scrollRef = useRef(null); | ||
useEffect(function () { | ||
getMenuItemsRef().current = _objectSpread$3({}, getMenuItemsRef().current, _defineProperty$3({}, index, true)); | ||
return function () { | ||
getMenuItemsRef().current = _objectSpread$3({}, getMenuItemsRef().current, _defineProperty$3({}, index, false)); | ||
}; | ||
}, []); | ||
useEffect(function () { | ||
if (state.highlightedIndex === index && shouldScroll.current && scrollRef.current) { | ||
scrollIntoViewIfNeeded(scrollRef.current, { | ||
scrollMode: 'if-needed', | ||
block: 'nearest', | ||
inline: 'nearest' | ||
}); | ||
} | ||
if (!shouldScroll.current) { | ||
shouldScroll.current = true; | ||
} | ||
}, [state.highlightedIndex, index]); | ||
var onClick = useCallback(function () { | ||
setState(function (s) { | ||
return _objectSpread$3({}, s, { | ||
isOpen: false, | ||
selectedIndex: index, | ||
highlightedIndex: null, | ||
inputValue: typeof s.lastSelectedInputValue === 'string' && s.selectedIndex === s.highlightedIndex ? s.lastSelectedInputValue : s.inputValue | ||
}); | ||
}); | ||
}, [index]); | ||
var onMouseMove = useCallback(function () { | ||
if (state.highlightedIndex !== index) { | ||
shouldScroll.current = false; | ||
setState(function (s) { | ||
return _objectSpread$3({}, s, { | ||
highlightedIndex: index | ||
}); | ||
}); | ||
} | ||
}, [state.highlightedIndex, index]); | ||
var onMouseDown = useCallback(function (event) { | ||
event.preventDefault(); | ||
}, []); | ||
return createElement("div", _extends$4({ | ||
ref: scrollRef, | ||
"aria-selected": state.highlightedIndex === index, | ||
id: "".concat(id, "-menu-item-").concat(index), | ||
role: "option", | ||
onClick: onClick, | ||
onMouseMove: onMouseMove, | ||
onMouseDown: onMouseDown | ||
}, props), children); | ||
}; | ||
export default Downscreen; | ||
export { Button, Input, Label, Menu, MenuItem }; |
{ | ||
"name": "react-downscreen", | ||
"description": "React Downscreen ⛹️", | ||
"version": "0.3.0", | ||
"version": "0.3.1", | ||
"license": "MIT", | ||
@@ -10,6 +10,2 @@ "files": [ | ||
], | ||
"esnext": "dist-src/index.js", | ||
"main": "dist-node/index.js", | ||
"module": "dist-web/index.js", | ||
"types": "dist-types/index.d.ts", | ||
"pika": true, | ||
@@ -25,4 +21,4 @@ "sideEffects": false, | ||
"devDependencies": { | ||
"@babel/core": "7.5.0", | ||
"@babel/preset-env": "7.5.0", | ||
"@babel/core": "7.5.4", | ||
"@babel/preset-env": "7.5.4", | ||
"@babel/preset-react": "7.0.0", | ||
@@ -36,3 +32,3 @@ "@babel/preset-typescript": "7.3.3", | ||
"@types/react": "16.8.23", | ||
"@types/styled-components": "4.1.16", | ||
"@types/styled-components": "4.1.18", | ||
"docz": "1.2.0", | ||
@@ -43,4 +39,8 @@ "docz-theme-default": "1.2.0", | ||
"styled-components": "4.3.2", | ||
"typescript": "3.5.2" | ||
} | ||
"typescript": "3.5.3" | ||
}, | ||
"esnext": "dist-src/index.js", | ||
"main": "dist-node/index.js", | ||
"module": "dist-web/index.js", | ||
"types": "dist-types/index.d.ts" | ||
} |
@@ -1,1 +0,3 @@ | ||
# React Downscreen ⛹️ | ||
**React Downscreen ⛹️** - A simple framework for building accessibility-friendly selects, dropdowns, autocompletes, and comboboxes in React. Heavily inspired by [the excellent library Downshift](https://github.com/downshift-js/downshift). | ||
[Documentation](https://therealparmesh.github.io/react-downscreen/) |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
92512
2517
3