react-aria
Version:
Spectrum UI components in React
220 lines (214 loc) • 11.7 kB
JavaScript
import {DOMLayoutDelegate as $a83747cc3f035330$export$8f5ed9ff9f511381} from "./DOMLayoutDelegate.mjs";
import {getItemElement as $22bbea12c2567021$export$c3d8340acf92597f} from "./utils.mjs";
import {isScrollable as $901761b40e390936$export$2bb74740c4e19def} from "../utils/isScrollable.mjs";
/*
* 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.
*/
class $ae8f8d98b2b18f2f$export$a05409b8bb224a5a {
constructor(...args){
if (args.length === 1) {
let opts = args[0];
this.collection = opts.collection;
this.ref = opts.ref;
this.collator = opts.collator;
this.disabledKeys = opts.disabledKeys || new Set();
this.disabledBehavior = opts.disabledBehavior || 'all';
this.orientation = opts.orientation || 'vertical';
this.direction = opts.direction;
this.layout = opts.layout || 'stack';
this.layoutDelegate = opts.layoutDelegate || new (0, $a83747cc3f035330$export$8f5ed9ff9f511381)(opts.ref);
} else {
this.collection = args[0];
this.disabledKeys = args[1];
this.ref = args[2];
this.collator = args[3];
this.layout = 'stack';
this.orientation = 'vertical';
this.disabledBehavior = 'all';
this.layoutDelegate = new (0, $a83747cc3f035330$export$8f5ed9ff9f511381)(this.ref);
}
// If this is a vertical stack, remove the left/right methods completely
// so they aren't called by useDroppableCollection.
if (this.layout === 'stack' && this.orientation === 'vertical') {
this.getKeyLeftOf = undefined;
this.getKeyRightOf = undefined;
}
}
isDisabled(item) {
return this.disabledBehavior === 'all' && (item.props?.isDisabled || this.disabledKeys.has(item.key)) && item.props?.disabledBehavior !== 'selection';
}
findNextNonDisabled(key, getNext, includeDisabled = false) {
let nextKey = key;
while(nextKey != null){
let item = this.collection.getItem(nextKey);
if (item?.type === 'item' && (includeDisabled || !this.isDisabled(item))) return nextKey;
nextKey = getNext(nextKey);
}
return null;
}
getNextKey(key, options) {
let nextKey = key;
nextKey = this.collection.getKeyAfter(nextKey);
return this.findNextNonDisabled(nextKey, (key)=>this.collection.getKeyAfter(key), options?.includeDisabled);
}
getPreviousKey(key, options) {
let nextKey = key;
nextKey = this.collection.getKeyBefore(nextKey);
return this.findNextNonDisabled(nextKey, (key)=>this.collection.getKeyBefore(key), options?.includeDisabled);
}
findKey(key, nextKey, shouldSkip) {
let tempKey = key;
let itemRect = this.layoutDelegate.getItemRect(tempKey);
if (!itemRect || tempKey == null) return null;
// Find the item above or below in the same column.
let prevRect = itemRect;
do {
tempKey = nextKey(tempKey);
if (tempKey == null) break;
itemRect = this.layoutDelegate.getItemRect(tempKey);
}while (itemRect && shouldSkip(prevRect, itemRect) && tempKey != null);
return tempKey;
}
isSameRow(prevRect, itemRect) {
return prevRect.y === itemRect.y || prevRect.x !== itemRect.x;
}
isSameColumn(prevRect, itemRect) {
return prevRect.x === itemRect.x || prevRect.y !== itemRect.y;
}
// checks to see if the next/prev key is spatially above/below the current key. If not, that means we are in
// a reversed column layout and need to adjust appropriately
// TODO: still need to see how this works with virtualizer once there is handling for the reverse layout
// this felt like a simpler approach then changing getKeyAbove/Below to be purely spatial calculations
isReversed(key) {
let nextKey = this.getNextKey(key);
let currentEl = (0, $22bbea12c2567021$export$c3d8340acf92597f)(this.ref, key);
if (nextKey != null) {
let nextEl = (0, $22bbea12c2567021$export$c3d8340acf92597f)(this.ref, nextKey);
if (!currentEl || !nextEl) return false;
return currentEl.getBoundingClientRect().top > nextEl.getBoundingClientRect().top;
}
let prevKey = this.getPreviousKey(key);
if (prevKey != null) {
let prevEl = (0, $22bbea12c2567021$export$c3d8340acf92597f)(this.ref, prevKey);
if (!currentEl || !prevEl) return false;
return prevEl.getBoundingClientRect().top > currentEl.getBoundingClientRect().top;
}
return false;
}
getKeyBelow(key, options) {
if (this.layout === 'grid' && this.orientation === 'vertical') return this.findKey(key, (key)=>this.getNextKey(key, options), this.isSameRow);
else if (this.orientation === 'vertical') return this.isReversed(key) ? this.getPreviousKey(key, options) : this.getNextKey(key, options);
else return this.getNextKey(key, options);
}
getKeyAbove(key, options) {
if (this.layout === 'grid' && this.orientation === 'vertical') return this.findKey(key, (key)=>this.getPreviousKey(key, options), this.isSameRow);
else if (this.orientation === 'vertical') return this.isReversed(key) ? this.getNextKey(key, options) : this.getPreviousKey(key, options);
else return this.getPreviousKey(key, options);
}
getNextColumn(key, right, options) {
return right ? this.getPreviousKey(key, options) : this.getNextKey(key, options);
}
getKeyRightOf(key, options) {
// This is a temporary solution for CardView until we refactor useSelectableCollection.
// https://github.com/orgs/adobe/projects/19/views/32?pane=issue&itemId=77825042
let layoutDelegateMethod = this.direction === 'ltr' ? 'getKeyRightOf' : 'getKeyLeftOf';
if (this.layoutDelegate[layoutDelegateMethod]) {
key = this.layoutDelegate[layoutDelegateMethod](key);
return this.findNextNonDisabled(key, (key)=>this.layoutDelegate[layoutDelegateMethod](key), options?.includeDisabled);
}
if (this.layout === 'grid') {
if (this.orientation === 'vertical') return this.getNextColumn(key, this.direction === 'rtl', options);
else return this.findKey(key, (key)=>this.getNextColumn(key, this.direction === 'rtl', options), this.isSameColumn);
} else if (this.orientation === 'horizontal') return this.getNextColumn(key, this.direction === 'rtl', options);
return null;
}
getKeyLeftOf(key, options) {
let layoutDelegateMethod = this.direction === 'ltr' ? 'getKeyLeftOf' : 'getKeyRightOf';
if (this.layoutDelegate[layoutDelegateMethod]) {
key = this.layoutDelegate[layoutDelegateMethod](key);
return this.findNextNonDisabled(key, (key)=>this.layoutDelegate[layoutDelegateMethod](key), options?.includeDisabled);
}
if (this.layout === 'grid') {
if (this.orientation === 'vertical') return this.getNextColumn(key, this.direction === 'ltr', options);
else return this.findKey(key, (key)=>this.getNextColumn(key, this.direction === 'ltr', options), this.isSameColumn);
} else if (this.orientation === 'horizontal') return this.getNextColumn(key, this.direction === 'ltr', options);
return null;
}
getFirstKey() {
let key = this.collection.getFirstKey();
return this.findNextNonDisabled(key, (key)=>this.collection.getKeyAfter(key));
}
getLastKey() {
let key = this.collection.getLastKey();
return this.findNextNonDisabled(key, (key)=>this.collection.getKeyBefore(key));
}
getKeyPageAbove(key) {
let menu = this.ref.current;
let itemRect = this.layoutDelegate.getItemRect(key);
if (!itemRect) return null;
let reversed = this.isReversed(key);
if (menu && !(0, $901761b40e390936$export$2bb74740c4e19def)(menu)) return this.getFirstKey();
let nextKey = key;
if (this.orientation === 'horizontal') {
let pageX = Math.max(0, itemRect.x + itemRect.width - this.layoutDelegate.getVisibleRect().width);
while(itemRect && itemRect.x > pageX && nextKey != null){
nextKey = this.getKeyAbove(nextKey);
itemRect = nextKey == null ? null : this.layoutDelegate.getItemRect(nextKey);
}
} else {
let visibleRect = this.layoutDelegate.getVisibleRect();
// column reverse makes y negative for items so we need to instead do current pos - height instead
let pageY = reversed ? itemRect.y - visibleRect.height : Math.max(0, itemRect.y + itemRect.height - visibleRect.height);
while(itemRect && itemRect.y > pageY && nextKey != null){
nextKey = this.getKeyAbove(nextKey);
itemRect = nextKey == null ? null : this.layoutDelegate.getItemRect(nextKey);
}
}
return nextKey ?? (reversed ? this.getLastKey() : this.getFirstKey());
}
getKeyPageBelow(key) {
let menu = this.ref.current;
let itemRect = this.layoutDelegate.getItemRect(key);
if (!itemRect) return null;
let reversed = this.isReversed(key);
if (menu && !(0, $901761b40e390936$export$2bb74740c4e19def)(menu)) return this.getLastKey();
let nextKey = key;
if (this.orientation === 'horizontal') {
let pageX = Math.min(this.layoutDelegate.getContentSize().width, itemRect.x - itemRect.width + this.layoutDelegate.getVisibleRect().width);
while(itemRect && itemRect.x < pageX && nextKey != null){
nextKey = this.getKeyBelow(nextKey);
itemRect = nextKey == null ? null : this.layoutDelegate.getItemRect(nextKey);
}
} else {
let pageY = Math.min(this.layoutDelegate.getContentSize().height, itemRect.y - itemRect.height + this.layoutDelegate.getVisibleRect().height);
while(itemRect && itemRect.y < pageY && nextKey != null){
nextKey = this.getKeyBelow(nextKey);
itemRect = nextKey == null ? null : this.layoutDelegate.getItemRect(nextKey);
}
}
return nextKey ?? (reversed ? this.getFirstKey() : this.getLastKey());
}
getKeyForSearch(search, fromKey) {
if (!this.collator) return null;
let collection = this.collection;
let key = fromKey || this.getFirstKey();
while(key != null){
let item = collection.getItem(key);
if (!item) return null;
let substring = item.textValue.slice(0, search.length);
if (item.textValue && this.collator.compare(substring, search) === 0) return key;
key = this.getNextKey(key);
}
return null;
}
}
export {$ae8f8d98b2b18f2f$export$a05409b8bb224a5a as ListKeyboardDelegate};
//# sourceMappingURL=ListKeyboardDelegate.mjs.map