@react-stately/selection
Advanced tools
Comparing version 3.0.0-alpha.1 to 3.0.0-rc.0
602
dist/main.js
@@ -1,306 +0,358 @@ | ||
var _babelRuntimeHelpersSlicedToArray = $parcel$interopDefault(require("@babel/runtime/helpers/slicedToArray")); | ||
var { | ||
useControlledState | ||
} = require("@react-stately/utils"); | ||
var _babelRuntimeHelpersClassCallCheck = $parcel$interopDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
var { | ||
useMemo, | ||
useRef, | ||
useState | ||
} = require("react"); | ||
var _babelRuntimeHelpersAssertThisInitialized = $parcel$interopDefault(require("@babel/runtime/helpers/assertThisInitialized")); | ||
/* | ||
* Copyright 2020 Adobe. All rights reserved. | ||
* This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. You may obtain a copy | ||
* of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under | ||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
* OF ANY KIND, either express or implied. See the License for the specific language | ||
* governing permissions and limitations under the License. | ||
*/ | ||
var _babelRuntimeHelpersPossibleConstructorReturn = $parcel$interopDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); | ||
/** | ||
* A Selection is a special Set containing Keys, which also has an anchor | ||
* and current selected key for use when range selecting. | ||
*/ | ||
class $cc81f14158b02e1e259a5a46d24f0c$export$Selection extends Set { | ||
constructor(keys, anchorKey, currentKey) { | ||
super(keys); | ||
this.anchorKey = void 0; | ||
this.currentKey = void 0; | ||
var _babelRuntimeHelpersGetPrototypeOf = $parcel$interopDefault(require("@babel/runtime/helpers/getPrototypeOf")); | ||
if (keys instanceof $cc81f14158b02e1e259a5a46d24f0c$export$Selection) { | ||
this.anchorKey = anchorKey || keys.anchorKey; | ||
this.currentKey = currentKey || keys.currentKey; | ||
} else { | ||
this.anchorKey = anchorKey; | ||
this.currentKey = currentKey; | ||
} | ||
} | ||
var _babelRuntimeHelpersInherits = $parcel$interopDefault(require("@babel/runtime/helpers/inherits")); | ||
} | ||
var _babelRuntimeHelpersWrapNativeSuper = $parcel$interopDefault(require("@babel/runtime/helpers/wrapNativeSuper")); | ||
/** | ||
* Manages state for multiple selection and focus in a collection. | ||
*/ | ||
function useMultipleSelectionState(props) { | ||
let { | ||
selectionMode = 'none', | ||
disallowEmptySelection | ||
} = props; // We want synchronous updates to `isFocused` and `focusedKey` after their setters are called. | ||
// But we also need to trigger a react re-render. So, we have both a ref (sync) and state (async). | ||
var _babelRuntimeHelpersDefineProperty = $parcel$interopDefault(require("@babel/runtime/helpers/defineProperty")); | ||
let isFocusedRef = useRef(false); | ||
let [, setFocused] = useState(false); | ||
let focusedKeyRef = useRef(null); | ||
let [, setFocusedKey] = useState(null); | ||
let selectedKeysProp = useMemo(() => $e792d6adfd95a7ce87c6dd8b719ea117$var$convertSelection(props.selectedKeys), [props.selectedKeys]); | ||
let defaultSelectedKeys = useMemo(() => $e792d6adfd95a7ce87c6dd8b719ea117$var$convertSelection(props.defaultSelectedKeys, new $cc81f14158b02e1e259a5a46d24f0c$export$Selection()), [props.defaultSelectedKeys]); | ||
let [selectedKeys, setSelectedKeys] = useControlledState(selectedKeysProp, defaultSelectedKeys, props.onSelectionChange); | ||
return { | ||
selectionMode, | ||
disallowEmptySelection, | ||
var useControlledState = require("@react-stately/utils").useControlledState; | ||
get isFocused() { | ||
return isFocusedRef.current; | ||
}, | ||
var _temp = require("react"); | ||
setFocused(f) { | ||
isFocusedRef.current = f; | ||
setFocused(f); | ||
}, | ||
var useMemo = _temp.useMemo; | ||
var useRef = _temp.useRef; | ||
var useState = _temp.useState; | ||
get focusedKey() { | ||
return focusedKeyRef.current; | ||
}, | ||
var _babelRuntimeHelpersToConsumableArray = $parcel$interopDefault(require("@babel/runtime/helpers/toConsumableArray")); | ||
setFocusedKey(k) { | ||
focusedKeyRef.current = k; | ||
setFocusedKey(k); | ||
}, | ||
var _babelRuntimeHelpersCreateClass = $parcel$interopDefault(require("@babel/runtime/helpers/createClass")); | ||
selectedKeys, | ||
setSelectedKeys | ||
}; | ||
} | ||
function $parcel$interopDefault(a) { | ||
return a && a.__esModule ? a.default : a; | ||
exports.useMultipleSelectionState = useMultipleSelectionState; | ||
function $e792d6adfd95a7ce87c6dd8b719ea117$var$convertSelection(selection, defaultValue) { | ||
if (!selection) { | ||
return defaultValue; | ||
} | ||
return selection === 'all' ? 'all' : new $cc81f14158b02e1e259a5a46d24f0c$export$Selection(selection); | ||
} | ||
function $bb7d918fbed0fc92d25aabfc4c972843$var$_createSuper(Derived) { | ||
return function () { | ||
var Super = _babelRuntimeHelpersGetPrototypeOf(Derived), | ||
result; | ||
/** | ||
* An interface for reading and updating multiple selection state. | ||
*/ | ||
class SelectionManager { | ||
constructor(collection, state, options) { | ||
var _options$allowsCellSe; | ||
if ($bb7d918fbed0fc92d25aabfc4c972843$var$_isNativeReflectConstruct()) { | ||
var NewTarget = _babelRuntimeHelpersGetPrototypeOf(this).constructor; | ||
this.collection = void 0; | ||
this.state = void 0; | ||
this.allowsCellSelection = void 0; | ||
this._isSelectAll = void 0; | ||
this.collection = collection; | ||
this.state = state; | ||
this.allowsCellSelection = (_options$allowsCellSe = options == null ? void 0 : options.allowsCellSelection) != null ? _options$allowsCellSe : false; | ||
this._isSelectAll = null; | ||
} | ||
/** | ||
* The type of selection that is allowed in the collection. | ||
*/ | ||
result = Reflect.construct(Super, arguments, NewTarget); | ||
} else { | ||
result = Super.apply(this, arguments); | ||
} | ||
return _babelRuntimeHelpersPossibleConstructorReturn(this, result); | ||
}; | ||
} | ||
get selectionMode() { | ||
return this.state.selectionMode; | ||
} | ||
/** | ||
* Whether the collection allows empty selection. | ||
*/ | ||
function $bb7d918fbed0fc92d25aabfc4c972843$var$_isNativeReflectConstruct() { | ||
if (typeof Reflect === "undefined" || !Reflect.construct) return false; | ||
if (Reflect.construct.sham) return false; | ||
if (typeof Proxy === "function") return true; | ||
try { | ||
Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
get disallowEmptySelection() { | ||
return this.state.disallowEmptySelection; | ||
} | ||
} | ||
/* | ||
* Copyright 2020 Adobe. All rights reserved. | ||
* This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. You may obtain a copy | ||
* of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under | ||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
* OF ANY KIND, either express or implied. See the License for the specific language | ||
* governing permissions and limitations under the License. | ||
*/ | ||
/** | ||
* Whether the collection is currently focused. | ||
*/ | ||
/** | ||
* A Selection is a special Set containing Keys, which also has an anchor | ||
* and current selected key for use when range selecting. | ||
*/ | ||
get isFocused() { | ||
return this.state.isFocused; | ||
} | ||
/** | ||
* Sets whether the collection is focused. | ||
*/ | ||
var $bb7d918fbed0fc92d25aabfc4c972843$export$Selection = /*#__PURE__*/function (_Set) { | ||
_babelRuntimeHelpersInherits(Selection, _Set); | ||
var _super = $bb7d918fbed0fc92d25aabfc4c972843$var$_createSuper(Selection); | ||
setFocused(isFocused) { | ||
this.state.setFocused(isFocused); | ||
} | ||
/** | ||
* The current focused key in the collection. | ||
*/ | ||
function Selection(keys, anchorKey, currentKey) { | ||
var _this; | ||
_babelRuntimeHelpersClassCallCheck(this, Selection); | ||
get focusedKey() { | ||
return this.state.focusedKey; | ||
} | ||
/** | ||
* Sets the focused key. | ||
*/ | ||
_this = _super.call(this, keys); | ||
_babelRuntimeHelpersDefineProperty(_babelRuntimeHelpersAssertThisInitialized(_this), "anchorKey", void 0); | ||
setFocusedKey(key) { | ||
this.state.setFocusedKey(key); | ||
} | ||
/** | ||
* The currently selected keys in the collection. | ||
*/ | ||
_babelRuntimeHelpersDefineProperty(_babelRuntimeHelpersAssertThisInitialized(_this), "currentKey", void 0); | ||
if (keys instanceof Selection) { | ||
_this.anchorKey = anchorKey || keys.anchorKey; | ||
_this.currentKey = currentKey || keys.currentKey; | ||
} else { | ||
_this.anchorKey = anchorKey; | ||
_this.currentKey = currentKey; | ||
get selectedKeys() { | ||
return this.state.selectedKeys === 'all' ? new Set(this.getSelectAllKeys()) : this.state.selectedKeys; | ||
} | ||
/** | ||
* Returns whether a key is selected. | ||
*/ | ||
isSelected(key) { | ||
if (this.state.selectionMode === 'none') { | ||
return false; | ||
} | ||
return _this; | ||
return this.state.selectedKeys === 'all' || this.state.selectedKeys.has(key); | ||
} | ||
/** | ||
* Whether the selection is empty. | ||
*/ | ||
return Selection; | ||
}( /*#__PURE__*/_babelRuntimeHelpersWrapNativeSuper(Set)); | ||
function useMultipleSelectionState(props) { | ||
var isFocused = useRef(false); | ||
get isEmpty() { | ||
return this.state.selectedKeys !== 'all' && this.state.selectedKeys.size === 0; | ||
} | ||
/** | ||
* Whether all items in the collection are selected. | ||
*/ | ||
var _useState = useState(null), | ||
_useState2 = _babelRuntimeHelpersSlicedToArray(_useState, 2), | ||
focusedKey = _useState2[0], | ||
setFocusedKey = _useState2[1]; | ||
var selectedKeysProp = useMemo(function () { | ||
return props.selectedKeys ? new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection(props.selectedKeys) : undefined; | ||
}, [props.selectedKeys]); | ||
var defaultSelectedKeys = useMemo(function () { | ||
return props.defaultSelectedKeys ? new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection(props.defaultSelectedKeys) : new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection(); | ||
}, [props.defaultSelectedKeys]); | ||
get isSelectAll() { | ||
if (this.isEmpty) { | ||
return false; | ||
} | ||
var _useControlledState = useControlledState(selectedKeysProp, defaultSelectedKeys, props.onSelectionChange), | ||
_useControlledState2 = _babelRuntimeHelpersSlicedToArray(_useControlledState, 2), | ||
selectedKeys = _useControlledState2[0], | ||
setSelectedKeys = _useControlledState2[1]; | ||
if (this.state.selectedKeys === 'all') { | ||
return true; | ||
} | ||
return { | ||
selectionMode: props.selectionMode || 'multiple', | ||
if (this._isSelectAll != null) { | ||
return this._isSelectAll; | ||
} | ||
get isFocused() { | ||
return isFocused.current; | ||
}, | ||
let allKeys = this.getSelectAllKeys(); | ||
let selectedKeys = this.state.selectedKeys; | ||
this._isSelectAll = allKeys.every(k => selectedKeys.has(k)); | ||
return this._isSelectAll; | ||
} | ||
/** | ||
* Extends the selection to the given key. | ||
*/ | ||
setFocused: function setFocused(f) { | ||
isFocused.current = f; | ||
}, | ||
focusedKey: focusedKey, | ||
setFocusedKey: setFocusedKey, | ||
selectedKeys: selectedKeys, | ||
setSelectedKeys: setSelectedKeys | ||
}; | ||
} | ||
exports.useMultipleSelectionState = useMultipleSelectionState; | ||
extendSelection(toKey) { | ||
toKey = this.getKey(toKey); | ||
this.state.setSelectedKeys(selectedKeys => { | ||
// Only select the one key if coming from a select all. | ||
if (selectedKeys === 'all') { | ||
return new $cc81f14158b02e1e259a5a46d24f0c$export$Selection([toKey], toKey, toKey); | ||
} | ||
function $f1e9b103029d27866ace9fb906215618$var$_createForOfIteratorHelper(o) { | ||
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { | ||
if (Array.isArray(o) || (o = $f1e9b103029d27866ace9fb906215618$var$_unsupportedIterableToArray(o))) { | ||
var i = 0; | ||
let selection = selectedKeys; | ||
let anchorKey = selection.anchorKey || toKey; | ||
let keys = new $cc81f14158b02e1e259a5a46d24f0c$export$Selection(selection, anchorKey, toKey); | ||
var F = function F() {}; | ||
for (let key of this.getKeyRange(anchorKey, selection.currentKey || toKey)) { | ||
keys.delete(key); | ||
} | ||
return { | ||
s: F, | ||
n: function n() { | ||
if (i >= o.length) return { | ||
done: true | ||
}; | ||
return { | ||
done: false, | ||
value: o[i++] | ||
}; | ||
}, | ||
e: function e(_e) { | ||
throw _e; | ||
}, | ||
f: F | ||
}; | ||
} | ||
for (let key of this.getKeyRange(toKey, anchorKey)) { | ||
keys.add(key); | ||
} | ||
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); | ||
return keys; | ||
}); | ||
} | ||
var it, | ||
normalCompletion = true, | ||
didErr = false, | ||
err; | ||
return { | ||
s: function s() { | ||
it = o[Symbol.iterator](); | ||
}, | ||
n: function n() { | ||
var step = it.next(); | ||
normalCompletion = step.done; | ||
return step; | ||
}, | ||
e: function e(_e2) { | ||
didErr = true; | ||
err = _e2; | ||
}, | ||
f: function f() { | ||
try { | ||
if (!normalCompletion && it.return != null) it.return(); | ||
} finally { | ||
if (didErr) throw err; | ||
getKeyRange(from, to) { | ||
let fromItem = this.collection.getItem(from); | ||
let toItem = this.collection.getItem(to); | ||
if (fromItem && toItem) { | ||
if (fromItem.index <= toItem.index) { | ||
return this.getKeyRangeInternal(from, to); | ||
} | ||
return this.getKeyRangeInternal(to, from); | ||
} | ||
}; | ||
} | ||
function $f1e9b103029d27866ace9fb906215618$var$_unsupportedIterableToArray(o, minLen) { | ||
if (!o) return; | ||
if (typeof o === "string") return $f1e9b103029d27866ace9fb906215618$var$_arrayLikeToArray(o, minLen); | ||
var n = Object.prototype.toString.call(o).slice(8, -1); | ||
if (n === "Object" && o.constructor) n = o.constructor.name; | ||
if (n === "Map" || n === "Set") return Array.from(n); | ||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return $f1e9b103029d27866ace9fb906215618$var$_arrayLikeToArray(o, minLen); | ||
} | ||
return []; | ||
} | ||
function $f1e9b103029d27866ace9fb906215618$var$_arrayLikeToArray(arr, len) { | ||
if (len == null || len > arr.length) len = arr.length; | ||
getKeyRangeInternal(from, to) { | ||
let keys = []; | ||
let key = from; | ||
for (var i = 0, arr2 = new Array(len); i < len; i++) { | ||
arr2[i] = arr[i]; | ||
while (key) { | ||
let item = this.collection.getItem(key); | ||
if (item && item.type === 'item' || item.type === 'cell' && this.allowsCellSelection) { | ||
keys.push(key); | ||
} | ||
if (key === to) { | ||
return keys; | ||
} | ||
key = this.collection.getKeyAfter(key); | ||
} | ||
return []; | ||
} | ||
return arr2; | ||
} | ||
getKey(key) { | ||
let item = this.collection.getItem(key); | ||
var SelectionManager = /*#__PURE__*/function () { | ||
function SelectionManager(collection, state) { | ||
_babelRuntimeHelpersClassCallCheck(this, SelectionManager); | ||
if (!item) { | ||
// ¯\_(ツ)_/¯ | ||
return key; | ||
} // If cell selection is allowed, just return the key. | ||
_babelRuntimeHelpersDefineProperty(this, "collection", void 0); | ||
_babelRuntimeHelpersDefineProperty(this, "state", void 0); | ||
if (item.type === 'cell' && this.allowsCellSelection) { | ||
return key; | ||
} // Find a parent item to select | ||
this.collection = collection; | ||
this.state = state; | ||
} | ||
_babelRuntimeHelpersCreateClass(SelectionManager, [{ | ||
key: "setFocused", | ||
value: function setFocused(isFocused) { | ||
this.state.setFocused(isFocused); | ||
while (item.type !== 'item' && item.parentKey) { | ||
item = this.collection.getItem(item.parentKey); | ||
} | ||
}, { | ||
key: "setFocusedKey", | ||
value: function setFocusedKey(key) { | ||
this.state.setFocusedKey(key); | ||
if (!item || item.type !== 'item') { | ||
return null; | ||
} | ||
}, { | ||
key: "setSelectedKeys", | ||
value: function setSelectedKeys(keys) { | ||
this.state.setSelectedKeys(keys); | ||
return item.key; | ||
} | ||
/** | ||
* Toggles whether the given key is selected. | ||
*/ | ||
toggleSelection(key) { | ||
key = this.getKey(key); | ||
if (key == null) { | ||
return; | ||
} | ||
}, { | ||
key: "extendSelection", | ||
value: function extendSelection(toKey) { | ||
var _this = this; | ||
this.state.setSelectedKeys(function (selectedKeys) { | ||
var anchorKey = selectedKeys.anchorKey || toKey; | ||
var keys = new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection(selectedKeys, anchorKey, toKey); | ||
this.state.setSelectedKeys(selectedKeys => { | ||
let keys = new $cc81f14158b02e1e259a5a46d24f0c$export$Selection(selectedKeys === 'all' ? this.getSelectAllKeys() : selectedKeys); | ||
var _iterator = $f1e9b103029d27866ace9fb906215618$var$_createForOfIteratorHelper(_this.getKeyRange(anchorKey, selectedKeys.currentKey || toKey)), | ||
_step; | ||
if (keys.has(key)) { | ||
keys.delete(key); // TODO: move anchor to last selected key... | ||
// Does `current` need to move here too? | ||
} else { | ||
keys.add(key); | ||
keys.anchorKey = key; | ||
keys.currentKey = key; | ||
} | ||
try { | ||
for (_iterator.s(); !(_step = _iterator.n()).done;) { | ||
var key = _step.value; | ||
keys.delete(key); | ||
} | ||
} catch (err) { | ||
_iterator.e(err); | ||
} finally { | ||
_iterator.f(); | ||
} | ||
return keys; | ||
}); | ||
} | ||
/** | ||
* Replaces the selection with only the given key. | ||
*/ | ||
var _iterator2 = $f1e9b103029d27866ace9fb906215618$var$_createForOfIteratorHelper(_this.getKeyRange(toKey, anchorKey)), | ||
_step2; | ||
try { | ||
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { | ||
var _key = _step2.value; | ||
keys.add(_key); | ||
} | ||
} catch (err) { | ||
_iterator2.e(err); | ||
} finally { | ||
_iterator2.f(); | ||
} | ||
replaceSelection(key) { | ||
key = this.getKey(key); | ||
return keys; | ||
}); | ||
if (key == null) { | ||
return; | ||
} | ||
}, { | ||
key: "getKeyRange", | ||
value: function getKeyRange(from, to) { | ||
return this.getKeyRangeInternal(from, to) || this.getKeyRangeInternal(to, from) || []; | ||
} | ||
}, { | ||
key: "getKeyRangeInternal", | ||
value: function getKeyRangeInternal(from, to) { | ||
var keys = []; | ||
var key = from; | ||
this.state.setSelectedKeys(new $cc81f14158b02e1e259a5a46d24f0c$export$Selection([key], key, key)); | ||
} | ||
getSelectAllKeys() { | ||
let keys = []; | ||
let addKeys = key => { | ||
while (key) { | ||
keys.push(key); | ||
let item = this.collection.getItem(key); | ||
if (key === to) { | ||
return keys; | ||
if (item.type === 'item') { | ||
keys.push(key); | ||
} // Add child keys. If cell selection is allowed, then include item children too. | ||
if (item.hasChildNodes && (this.allowsCellSelection || item.type !== 'item')) { | ||
addKeys([...item.childNodes][0].key); | ||
} | ||
@@ -310,65 +362,41 @@ | ||
} | ||
}; | ||
return null; | ||
} | ||
}, { | ||
key: "toggleSelection", | ||
value: function toggleSelection(key) { | ||
this.state.setSelectedKeys(function (selectedKeys) { | ||
var keys = new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection(selectedKeys); | ||
addKeys(this.collection.getFirstKey()); | ||
return keys; | ||
} | ||
/** | ||
* Selects all items in the collection. | ||
*/ | ||
if (keys.has(key)) { | ||
keys.delete(key); // TODO: move anchor to last selected key... | ||
// Does `current` need to move here too? | ||
} else { | ||
keys.add(key); | ||
keys.anchorKey = key; | ||
keys.currentKey = key; | ||
} | ||
return keys; | ||
}); | ||
selectAll() { | ||
if (this.selectionMode === 'multiple') { | ||
this.state.setSelectedKeys('all'); | ||
} | ||
}, { | ||
key: "replaceSelection", | ||
value: function replaceSelection(key) { | ||
this.state.setSelectedKeys(new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection([key], key, key)); | ||
} | ||
}, { | ||
key: "selectAll", | ||
value: function selectAll() { | ||
var keys = _babelRuntimeHelpersToConsumableArray(this.collection.getKeys()); | ||
} | ||
/** | ||
* Removes all keys from the selection. | ||
*/ | ||
this.state.setSelectedKeys(new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection(keys, keys[0], keys[keys.length - 1])); | ||
clearSelection() { | ||
this.state.setSelectedKeys(new $cc81f14158b02e1e259a5a46d24f0c$export$Selection()); | ||
} | ||
/** | ||
* Toggles between select all and an empty selection. | ||
*/ | ||
toggleSelectAll() { | ||
if (this.isSelectAll) { | ||
this.clearSelection(); | ||
} else { | ||
this.selectAll(); | ||
} | ||
}, { | ||
key: "clearSelection", | ||
value: function clearSelection() { | ||
this.state.setSelectedKeys(new $bb7d918fbed0fc92d25aabfc4c972843$export$Selection()); | ||
} | ||
}, { | ||
key: "selectionMode", | ||
get: function get() { | ||
return this.state.selectionMode; | ||
} | ||
}, { | ||
key: "isFocused", | ||
get: function get() { | ||
return this.state.isFocused; | ||
} | ||
}, { | ||
key: "focusedKey", | ||
get: function get() { | ||
return this.state.focusedKey; | ||
} | ||
}, { | ||
key: "selectedKeys", | ||
get: function get() { | ||
return this.state.selectedKeys; | ||
} | ||
}]); | ||
} | ||
return SelectionManager; | ||
}(); | ||
} | ||
exports.SelectionManager = SelectionManager; | ||
exports.SelectionManager = SelectionManager; | ||
//# sourceMappingURL=main.js.map |
@@ -1,2 +0,1 @@ | ||
import _babelRuntimeHelpersEsmDefineProperty from "@babel/runtime/helpers/esm/defineProperty"; | ||
import { useControlledState } from "@react-stately/utils"; | ||
@@ -21,11 +20,9 @@ import { useMemo, useRef, useState } from "react"; | ||
*/ | ||
class $d6921aa3a5c375a16b83058bd8$export$Selection extends Set { | ||
class $c91e86e24f2dc9a2182dcc2674c58c$export$Selection extends Set { | ||
constructor(keys, anchorKey, currentKey) { | ||
super(keys); | ||
this.anchorKey = void 0; | ||
this.currentKey = void 0; | ||
_babelRuntimeHelpersEsmDefineProperty(this, "anchorKey", void 0); | ||
_babelRuntimeHelpersEsmDefineProperty(this, "currentKey", void 0); | ||
if (keys instanceof $d6921aa3a5c375a16b83058bd8$export$Selection) { | ||
if (keys instanceof $c91e86e24f2dc9a2182dcc2674c58c$export$Selection) { | ||
this.anchorKey = anchorKey || keys.anchorKey; | ||
@@ -41,21 +38,41 @@ this.currentKey = currentKey || keys.currentKey; | ||
/** | ||
* Manages state for multiple selection and focus in a collection. | ||
*/ | ||
export function useMultipleSelectionState(props) { | ||
let isFocused = useRef(false); | ||
let [focusedKey, setFocusedKey] = useState(null); | ||
let selectedKeysProp = useMemo(() => props.selectedKeys ? new $d6921aa3a5c375a16b83058bd8$export$Selection(props.selectedKeys) : undefined, [props.selectedKeys]); | ||
let defaultSelectedKeys = useMemo(() => props.defaultSelectedKeys ? new $d6921aa3a5c375a16b83058bd8$export$Selection(props.defaultSelectedKeys) : new $d6921aa3a5c375a16b83058bd8$export$Selection(), [props.defaultSelectedKeys]); | ||
let { | ||
selectionMode = 'none', | ||
disallowEmptySelection | ||
} = props; // We want synchronous updates to `isFocused` and `focusedKey` after their setters are called. | ||
// But we also need to trigger a react re-render. So, we have both a ref (sync) and state (async). | ||
let isFocusedRef = useRef(false); | ||
let [, setFocused] = useState(false); | ||
let focusedKeyRef = useRef(null); | ||
let [, setFocusedKey] = useState(null); | ||
let selectedKeysProp = useMemo(() => $c86d35e876e048ac11515eee40c7$var$convertSelection(props.selectedKeys), [props.selectedKeys]); | ||
let defaultSelectedKeys = useMemo(() => $c86d35e876e048ac11515eee40c7$var$convertSelection(props.defaultSelectedKeys, new $c91e86e24f2dc9a2182dcc2674c58c$export$Selection()), [props.defaultSelectedKeys]); | ||
let [selectedKeys, setSelectedKeys] = useControlledState(selectedKeysProp, defaultSelectedKeys, props.onSelectionChange); | ||
return { | ||
selectionMode: props.selectionMode || 'multiple', | ||
selectionMode, | ||
disallowEmptySelection, | ||
get isFocused() { | ||
return isFocused.current; | ||
return isFocusedRef.current; | ||
}, | ||
setFocused(f) { | ||
isFocused.current = f; | ||
isFocusedRef.current = f; | ||
setFocused(f); | ||
}, | ||
focusedKey, | ||
setFocusedKey, | ||
get focusedKey() { | ||
return focusedKeyRef.current; | ||
}, | ||
setFocusedKey(k) { | ||
focusedKeyRef.current = k; | ||
setFocusedKey(k); | ||
}, | ||
selectedKeys, | ||
@@ -65,46 +82,144 @@ setSelectedKeys | ||
} | ||
function $c86d35e876e048ac11515eee40c7$var$convertSelection(selection, defaultValue) { | ||
if (!selection) { | ||
return defaultValue; | ||
} | ||
return selection === 'all' ? 'all' : new $c91e86e24f2dc9a2182dcc2674c58c$export$Selection(selection); | ||
} | ||
/** | ||
* An interface for reading and updating multiple selection state. | ||
*/ | ||
export class SelectionManager { | ||
constructor(collection, state) { | ||
_babelRuntimeHelpersEsmDefineProperty(this, "collection", void 0); | ||
constructor(collection, state, options) { | ||
var _options$allowsCellSe; | ||
_babelRuntimeHelpersEsmDefineProperty(this, "state", void 0); | ||
this.collection = void 0; | ||
this.state = void 0; | ||
this.allowsCellSelection = void 0; | ||
this._isSelectAll = void 0; | ||
this.collection = collection; | ||
this.state = state; | ||
this.allowsCellSelection = (_options$allowsCellSe = options == null ? void 0 : options.allowsCellSelection) != null ? _options$allowsCellSe : false; | ||
this._isSelectAll = null; | ||
} | ||
/** | ||
* The type of selection that is allowed in the collection. | ||
*/ | ||
get selectionMode() { | ||
return this.state.selectionMode; | ||
} | ||
/** | ||
* Whether the collection allows empty selection. | ||
*/ | ||
get disallowEmptySelection() { | ||
return this.state.disallowEmptySelection; | ||
} | ||
/** | ||
* Whether the collection is currently focused. | ||
*/ | ||
get isFocused() { | ||
return this.state.isFocused; | ||
} | ||
/** | ||
* Sets whether the collection is focused. | ||
*/ | ||
setFocused(isFocused) { | ||
this.state.setFocused(isFocused); | ||
} | ||
/** | ||
* The current focused key in the collection. | ||
*/ | ||
get focusedKey() { | ||
return this.state.focusedKey; | ||
} | ||
/** | ||
* Sets the focused key. | ||
*/ | ||
setFocusedKey(key) { | ||
this.state.setFocusedKey(key); | ||
} | ||
/** | ||
* The currently selected keys in the collection. | ||
*/ | ||
get selectedKeys() { | ||
return this.state.selectedKeys; | ||
return this.state.selectedKeys === 'all' ? new Set(this.getSelectAllKeys()) : this.state.selectedKeys; | ||
} | ||
/** | ||
* Returns whether a key is selected. | ||
*/ | ||
setSelectedKeys(keys) { | ||
this.state.setSelectedKeys(keys); | ||
isSelected(key) { | ||
if (this.state.selectionMode === 'none') { | ||
return false; | ||
} | ||
return this.state.selectedKeys === 'all' || this.state.selectedKeys.has(key); | ||
} | ||
/** | ||
* Whether the selection is empty. | ||
*/ | ||
get isEmpty() { | ||
return this.state.selectedKeys !== 'all' && this.state.selectedKeys.size === 0; | ||
} | ||
/** | ||
* Whether all items in the collection are selected. | ||
*/ | ||
get isSelectAll() { | ||
if (this.isEmpty) { | ||
return false; | ||
} | ||
if (this.state.selectedKeys === 'all') { | ||
return true; | ||
} | ||
if (this._isSelectAll != null) { | ||
return this._isSelectAll; | ||
} | ||
let allKeys = this.getSelectAllKeys(); | ||
let selectedKeys = this.state.selectedKeys; | ||
this._isSelectAll = allKeys.every(k => selectedKeys.has(k)); | ||
return this._isSelectAll; | ||
} | ||
/** | ||
* Extends the selection to the given key. | ||
*/ | ||
extendSelection(toKey) { | ||
toKey = this.getKey(toKey); | ||
this.state.setSelectedKeys(selectedKeys => { | ||
let anchorKey = selectedKeys.anchorKey || toKey; | ||
let keys = new $d6921aa3a5c375a16b83058bd8$export$Selection(selectedKeys, anchorKey, toKey); | ||
// Only select the one key if coming from a select all. | ||
if (selectedKeys === 'all') { | ||
return new $c91e86e24f2dc9a2182dcc2674c58c$export$Selection([toKey], toKey, toKey); | ||
} | ||
for (let key of this.getKeyRange(anchorKey, selectedKeys.currentKey || toKey)) { | ||
let selection = selectedKeys; | ||
let anchorKey = selection.anchorKey || toKey; | ||
let keys = new $c91e86e24f2dc9a2182dcc2674c58c$export$Selection(selection, anchorKey, toKey); | ||
for (let key of this.getKeyRange(anchorKey, selection.currentKey || toKey)) { | ||
keys.delete(key); | ||
@@ -122,3 +237,14 @@ } | ||
getKeyRange(from, to) { | ||
return this.getKeyRangeInternal(from, to) || this.getKeyRangeInternal(to, from) || []; | ||
let fromItem = this.collection.getItem(from); | ||
let toItem = this.collection.getItem(to); | ||
if (fromItem && toItem) { | ||
if (fromItem.index <= toItem.index) { | ||
return this.getKeyRangeInternal(from, to); | ||
} | ||
return this.getKeyRangeInternal(to, from); | ||
} | ||
return []; | ||
} | ||
@@ -131,4 +257,8 @@ | ||
while (key) { | ||
keys.push(key); | ||
let item = this.collection.getItem(key); | ||
if (item && item.type === 'item' || item.type === 'cell' && this.allowsCellSelection) { | ||
keys.push(key); | ||
} | ||
if (key === to) { | ||
@@ -141,8 +271,43 @@ return keys; | ||
return null; | ||
return []; | ||
} | ||
getKey(key) { | ||
let item = this.collection.getItem(key); | ||
if (!item) { | ||
// ¯\_(ツ)_/¯ | ||
return key; | ||
} // If cell selection is allowed, just return the key. | ||
if (item.type === 'cell' && this.allowsCellSelection) { | ||
return key; | ||
} // Find a parent item to select | ||
while (item.type !== 'item' && item.parentKey) { | ||
item = this.collection.getItem(item.parentKey); | ||
} | ||
if (!item || item.type !== 'item') { | ||
return null; | ||
} | ||
return item.key; | ||
} | ||
/** | ||
* Toggles whether the given key is selected. | ||
*/ | ||
toggleSelection(key) { | ||
key = this.getKey(key); | ||
if (key == null) { | ||
return; | ||
} | ||
this.state.setSelectedKeys(selectedKeys => { | ||
let keys = new $d6921aa3a5c375a16b83058bd8$export$Selection(selectedKeys); | ||
let keys = new $c91e86e24f2dc9a2182dcc2674c58c$export$Selection(selectedKeys === 'all' ? this.getSelectAllKeys() : selectedKeys); | ||
@@ -161,16 +326,72 @@ if (keys.has(key)) { | ||
} | ||
/** | ||
* Replaces the selection with only the given key. | ||
*/ | ||
replaceSelection(key) { | ||
this.state.setSelectedKeys(new $d6921aa3a5c375a16b83058bd8$export$Selection([key], key, key)); | ||
key = this.getKey(key); | ||
if (key == null) { | ||
return; | ||
} | ||
this.state.setSelectedKeys(new $c91e86e24f2dc9a2182dcc2674c58c$export$Selection([key], key, key)); | ||
} | ||
getSelectAllKeys() { | ||
let keys = []; | ||
let addKeys = key => { | ||
while (key) { | ||
let item = this.collection.getItem(key); | ||
if (item.type === 'item') { | ||
keys.push(key); | ||
} // Add child keys. If cell selection is allowed, then include item children too. | ||
if (item.hasChildNodes && (this.allowsCellSelection || item.type !== 'item')) { | ||
addKeys([...item.childNodes][0].key); | ||
} | ||
key = this.collection.getKeyAfter(key); | ||
} | ||
}; | ||
addKeys(this.collection.getFirstKey()); | ||
return keys; | ||
} | ||
/** | ||
* Selects all items in the collection. | ||
*/ | ||
selectAll() { | ||
let keys = [...this.collection.getKeys()]; | ||
this.state.setSelectedKeys(new $d6921aa3a5c375a16b83058bd8$export$Selection(keys, keys[0], keys[keys.length - 1])); | ||
if (this.selectionMode === 'multiple') { | ||
this.state.setSelectedKeys('all'); | ||
} | ||
} | ||
/** | ||
* Removes all keys from the selection. | ||
*/ | ||
clearSelection() { | ||
this.state.setSelectedKeys(new $d6921aa3a5c375a16b83058bd8$export$Selection()); | ||
this.state.setSelectedKeys(new $c91e86e24f2dc9a2182dcc2674c58c$export$Selection()); | ||
} | ||
/** | ||
* Toggles between select all and an empty selection. | ||
*/ | ||
} | ||
toggleSelectAll() { | ||
if (this.isSelectAll) { | ||
this.clearSelection(); | ||
} else { | ||
this.selectAll(); | ||
} | ||
} | ||
} | ||
//# sourceMappingURL=module.js.map |
import { Key } from "react"; | ||
import { SelectionMode, MultipleSelection } from "@react-types/shared"; | ||
import { Collection } from "@react-stately/collections"; | ||
import { Selection, SelectionMode, MultipleSelection, Collection, Node } from "@react-types/shared"; | ||
export interface FocusState { | ||
isFocused: boolean; | ||
/** Whether the collection is currently focused. */ | ||
readonly isFocused: boolean; | ||
/** Sets whether the collection is focused. */ | ||
setFocused(isFocused: boolean): void; | ||
focusedKey: Key; | ||
/** The current focused key in the collection. */ | ||
readonly focusedKey: Key; | ||
/** Sets the focused key. */ | ||
setFocusedKey(key: Key): void; | ||
} | ||
export interface SingleSelectionState extends FocusState { | ||
selectedKey: Key; | ||
/** Whether the collection allows empty selection. */ | ||
readonly disallowEmptySelection?: boolean; | ||
/** The currently selected key in the collection. */ | ||
readonly selectedKey: Key; | ||
/** Sets the selected key in the collection. */ | ||
setSelectedKey(key: Key): void; | ||
} | ||
export interface MultipleSelectionState extends FocusState { | ||
selectionMode: SelectionMode; | ||
selectedKeys: Set<Key>; | ||
setSelectedKeys(keys: Set<Key> | ((v: Set<Key>) => Set<Key>)): void; | ||
/** The type of selection that is allowed in the collection. */ | ||
readonly selectionMode: SelectionMode; | ||
/** Whether the collection allows empty selection. */ | ||
readonly disallowEmptySelection: boolean; | ||
/** The currently selected keys in the collection. */ | ||
readonly selectedKeys: Selection; | ||
/** Sets the selected keys in the collection. */ | ||
setSelectedKeys(keys: Selection | ((v: Selection) => Selection)): void; | ||
} | ||
export interface MultipleSelectionManager extends MultipleSelectionState { | ||
export interface MultipleSelectionManager extends FocusState { | ||
/** The type of selection that is allowed in the collection. */ | ||
readonly selectionMode: SelectionMode; | ||
/** Whether the collection allows empty selection. */ | ||
readonly disallowEmptySelection?: boolean; | ||
/** The currently selected keys in the collection. */ | ||
readonly selectedKeys: Set<Key>; | ||
/** Whether the selection is empty. */ | ||
readonly isEmpty: boolean; | ||
/** Whether all items in the collection are selected. */ | ||
readonly isSelectAll: boolean; | ||
/** Returns whether a key is selected. */ | ||
isSelected(key: Key): boolean; | ||
/** Extends the selection to the given key. */ | ||
extendSelection(toKey: Key): void; | ||
/** Toggles whether the given key is selected. */ | ||
toggleSelection(key: Key): void; | ||
/** Replaces the selection with only the given key. */ | ||
replaceSelection(key: Key): void; | ||
/** Selects all items in the collection. */ | ||
selectAll(): void; | ||
/** Removes all keys from the selection. */ | ||
clearSelection(): void; | ||
/** Toggles between select all and an empty selection. */ | ||
toggleSelectAll(): void; | ||
} | ||
/** | ||
* A Selection is a special Set containing Keys, which also has an anchor | ||
* and current selected key for use when range selecting. | ||
* Manages state for multiple selection and focus in a collection. | ||
*/ | ||
declare class Selection extends Set<Key> { | ||
anchorKey: Key; | ||
currentKey: Key; | ||
constructor(keys?: Iterable<Key> | Selection, anchorKey?: Key, currentKey?: Key); | ||
export function useMultipleSelectionState(props: MultipleSelection): MultipleSelectionState; | ||
interface SelectionManagerOptions { | ||
allowsCellSelection?: boolean; | ||
} | ||
export function useMultipleSelectionState(props: MultipleSelection): MultipleSelectionState; | ||
/** | ||
* An interface for reading and updating multiple selection state. | ||
*/ | ||
export class SelectionManager implements MultipleSelectionManager { | ||
constructor(collection: Collection<unknown>, state: MultipleSelectionState); | ||
readonly selectionMode: import("@react-types/shared").SelectionMode; | ||
readonly isFocused: boolean; | ||
constructor(collection: Collection<Node<unknown>>, state: MultipleSelectionState, options?: SelectionManagerOptions); | ||
/** | ||
* The type of selection that is allowed in the collection. | ||
*/ | ||
get selectionMode(): SelectionMode; | ||
/** | ||
* Whether the collection allows empty selection. | ||
*/ | ||
get disallowEmptySelection(): boolean; | ||
/** | ||
* Whether the collection is currently focused. | ||
*/ | ||
get isFocused(): boolean; | ||
/** | ||
* Sets whether the collection is focused. | ||
*/ | ||
setFocused(isFocused: boolean): void; | ||
readonly focusedKey: Key; | ||
/** | ||
* The current focused key in the collection. | ||
*/ | ||
get focusedKey(): Key; | ||
/** | ||
* Sets the focused key. | ||
*/ | ||
setFocusedKey(key: Key): void; | ||
readonly selectedKeys: Set<Key>; | ||
setSelectedKeys(keys: Selection): void; | ||
/** | ||
* The currently selected keys in the collection. | ||
*/ | ||
get selectedKeys(): Set<Key>; | ||
/** | ||
* Returns whether a key is selected. | ||
*/ | ||
isSelected(key: Key): boolean; | ||
/** | ||
* Whether the selection is empty. | ||
*/ | ||
get isEmpty(): boolean; | ||
/** | ||
* Whether all items in the collection are selected. | ||
*/ | ||
get isSelectAll(): boolean; | ||
/** | ||
* Extends the selection to the given key. | ||
*/ | ||
extendSelection(toKey: Key): void; | ||
/** | ||
* Toggles whether the given key is selected. | ||
*/ | ||
toggleSelection(key: Key): void; | ||
/** | ||
* Replaces the selection with only the given key. | ||
*/ | ||
replaceSelection(key: Key): void; | ||
/** | ||
* Selects all items in the collection. | ||
*/ | ||
selectAll(): void; | ||
/** | ||
* Removes all keys from the selection. | ||
*/ | ||
clearSelection(): void; | ||
/** | ||
* Toggles between select all and an empty selection. | ||
*/ | ||
toggleSelectAll(): void; | ||
} | ||
//# sourceMappingURL=types.d.ts.map |
{ | ||
"name": "@react-stately/selection", | ||
"version": "3.0.0-alpha.1", | ||
"version": "3.0.0-rc.0", | ||
"description": "Spectrum UI components in React", | ||
@@ -20,4 +20,5 @@ "license": "Apache-2.0", | ||
"@babel/runtime": "^7.6.2", | ||
"@react-stately/collections": "^3.0.0-alpha.1", | ||
"@react-stately/utils": "^3.0.0-rc.2" | ||
"@react-stately/collections": "3.0.0-rc.0", | ||
"@react-stately/utils": "3.0.0-rc.3", | ||
"@react-types/shared": "3.0.0-rc.3" | ||
}, | ||
@@ -30,3 +31,3 @@ "peerDependencies": { | ||
}, | ||
"gitHead": "207e6ee9076905c96638a7f81a367758872e1410" | ||
"gitHead": "461d6321126ae9b4f1508aa912f7b36bf8a603f8" | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79121
9
748
41
5
1
+ Added@react-stately/collections@3.0.0-rc.0(transitive)
+ Added@react-stately/utils@3.0.0-rc.3(transitive)
+ Added@react-types/shared@3.0.0-rc.3(transitive)
- Removed@react-stately/collections@3.10.9(transitive)
- Removed@react-stately/utils@3.10.3(transitive)
- Removed@react-types/shared@3.24.1(transitive)
- Removed@swc/helpers@0.5.13(transitive)
- Removedtslib@2.7.0(transitive)