@react-aria/grid
Advanced tools
Comparing version
@@ -54,2 +54,17 @@ var $iKGCm$reactariaselection = require("@react-aria/selection"); | ||
} | ||
getKeyForItemInRowByIndex(key, index = 0) { | ||
if (index < 0) return null; | ||
let item = this.collection.getItem(key); | ||
if (!item) return null; | ||
let i = 0; | ||
for (let child of (0, $iKGCm$reactstatelycollections.getChildNodes)(item, this.collection)){ | ||
var _child_key; | ||
if (child.colSpan && child.colSpan + i > index) return (_child_key = child.key) !== null && _child_key !== void 0 ? _child_key : null; | ||
if (child.colSpan) i = i + child.colSpan - 1; | ||
var _child_key1; | ||
if (i === index) return (_child_key1 = child.key) !== null && _child_key1 !== void 0 ? _child_key1 : null; | ||
i++; | ||
} | ||
return null; | ||
} | ||
getKeyBelow(fromKey) { | ||
@@ -68,7 +83,4 @@ let key = fromKey; | ||
if (this.isCell(startItem)) { | ||
var _getNthItem; | ||
let item = this.collection.getItem(key); | ||
if (!item) return null; | ||
var _startItem_index, _getNthItem_key; | ||
return (_getNthItem_key = (_getNthItem = (0, $iKGCm$reactstatelycollections.getNthItem)((0, $iKGCm$reactstatelycollections.getChildNodes)(item, this.collection), (_startItem_index = startItem.index) !== null && _startItem_index !== void 0 ? _startItem_index : 0)) === null || _getNthItem === void 0 ? void 0 : _getNthItem.key) !== null && _getNthItem_key !== void 0 ? _getNthItem_key : null; | ||
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index; | ||
return this.getKeyForItemInRowByIndex(key, startIndex); | ||
} | ||
@@ -93,7 +105,4 @@ // Otherwise, focus the next row | ||
if (this.isCell(startItem)) { | ||
var _getNthItem; | ||
let item = this.collection.getItem(key); | ||
if (!item) return null; | ||
var _startItem_index; | ||
return ((_getNthItem = (0, $iKGCm$reactstatelycollections.getNthItem)((0, $iKGCm$reactstatelycollections.getChildNodes)(item, this.collection), (_startItem_index = startItem.index) !== null && _startItem_index !== void 0 ? _startItem_index : 0)) === null || _getNthItem === void 0 ? void 0 : _getNthItem.key) || null; | ||
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index; | ||
return this.getKeyForItemInRowByIndex(key, startIndex); | ||
} | ||
@@ -291,3 +300,4 @@ // Otherwise, focus the previous row | ||
this.layoutDelegate = options.layoutDelegate || (options.layout ? new $3187c0e19200cb16$var$DeprecatedLayoutDelegate(options.layout) : new (0, $iKGCm$reactariaselection.DOMLayoutDelegate)(options.ref)); | ||
this.focusMode = options.focusMode || 'row'; | ||
var _options_focusMode; | ||
this.focusMode = (_options_focusMode = options.focusMode) !== null && _options_focusMode !== void 0 ? _options_focusMode : 'row'; | ||
} | ||
@@ -294,0 +304,0 @@ } |
import {DOMLayoutDelegate as $kbsd1$DOMLayoutDelegate} from "@react-aria/selection"; | ||
import {getNthItem as $kbsd1$getNthItem, getChildNodes as $kbsd1$getChildNodes, getLastItem as $kbsd1$getLastItem, getFirstItem as $kbsd1$getFirstItem} from "@react-stately/collections"; | ||
import {getChildNodes as $kbsd1$getChildNodes, getLastItem as $kbsd1$getLastItem, getFirstItem as $kbsd1$getFirstItem, getNthItem as $kbsd1$getNthItem} from "@react-stately/collections"; | ||
@@ -48,2 +48,17 @@ /* | ||
} | ||
getKeyForItemInRowByIndex(key, index = 0) { | ||
if (index < 0) return null; | ||
let item = this.collection.getItem(key); | ||
if (!item) return null; | ||
let i = 0; | ||
for (let child of (0, $kbsd1$getChildNodes)(item, this.collection)){ | ||
var _child_key; | ||
if (child.colSpan && child.colSpan + i > index) return (_child_key = child.key) !== null && _child_key !== void 0 ? _child_key : null; | ||
if (child.colSpan) i = i + child.colSpan - 1; | ||
var _child_key1; | ||
if (i === index) return (_child_key1 = child.key) !== null && _child_key1 !== void 0 ? _child_key1 : null; | ||
i++; | ||
} | ||
return null; | ||
} | ||
getKeyBelow(fromKey) { | ||
@@ -62,7 +77,4 @@ let key = fromKey; | ||
if (this.isCell(startItem)) { | ||
var _getNthItem; | ||
let item = this.collection.getItem(key); | ||
if (!item) return null; | ||
var _startItem_index, _getNthItem_key; | ||
return (_getNthItem_key = (_getNthItem = (0, $kbsd1$getNthItem)((0, $kbsd1$getChildNodes)(item, this.collection), (_startItem_index = startItem.index) !== null && _startItem_index !== void 0 ? _startItem_index : 0)) === null || _getNthItem === void 0 ? void 0 : _getNthItem.key) !== null && _getNthItem_key !== void 0 ? _getNthItem_key : null; | ||
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index; | ||
return this.getKeyForItemInRowByIndex(key, startIndex); | ||
} | ||
@@ -87,7 +99,4 @@ // Otherwise, focus the next row | ||
if (this.isCell(startItem)) { | ||
var _getNthItem; | ||
let item = this.collection.getItem(key); | ||
if (!item) return null; | ||
var _startItem_index; | ||
return ((_getNthItem = (0, $kbsd1$getNthItem)((0, $kbsd1$getChildNodes)(item, this.collection), (_startItem_index = startItem.index) !== null && _startItem_index !== void 0 ? _startItem_index : 0)) === null || _getNthItem === void 0 ? void 0 : _getNthItem.key) || null; | ||
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index; | ||
return this.getKeyForItemInRowByIndex(key, startIndex); | ||
} | ||
@@ -285,3 +294,4 @@ // Otherwise, focus the previous row | ||
this.layoutDelegate = options.layoutDelegate || (options.layout ? new $d1c300d9c497e402$var$DeprecatedLayoutDelegate(options.layout) : new (0, $kbsd1$DOMLayoutDelegate)(options.ref)); | ||
this.focusMode = options.focusMode || 'row'; | ||
var _options_focusMode; | ||
this.focusMode = (_options_focusMode = options.focusMode) !== null && _options_focusMode !== void 0 ? _options_focusMode : 'row'; | ||
} | ||
@@ -288,0 +298,0 @@ } |
@@ -26,3 +26,3 @@ import { Direction, DisabledBehavior, Key, KeyboardDelegate, LayoutDelegate, Node, Rect, RefObject, Size, Collection, AriaLabelingProps, DOMAttributes, DOMProps, FocusableElement } from "@react-types/shared"; | ||
protected layoutDelegate: LayoutDelegate; | ||
protected focusMode: any; | ||
protected focusMode: 'row' | 'cell'; | ||
constructor(options: GridKeyboardDelegateOptions<C>); | ||
@@ -33,2 +33,3 @@ protected isCell(node: Node<T>): boolean; | ||
protected findNextKey(fromKey?: Key, pred?: (item: Node<T>) => boolean): Key | null; | ||
protected getKeyForItemInRowByIndex(key: Key, index?: number): Key | null; | ||
getKeyBelow(fromKey: Key): Key | null; | ||
@@ -84,2 +85,7 @@ getKeyAbove(fromKey: Key): Key | null; | ||
/** | ||
* Whether typeahead navigation is disabled. | ||
* @default false | ||
*/ | ||
disallowTypeAhead?: boolean; | ||
/** | ||
* An optional keyboard delegate implementation for type to select, | ||
@@ -107,2 +113,13 @@ * to override the default. | ||
onCellAction?: (key: Key) => void; | ||
/** | ||
* Whether pressing the escape key should clear selection in the grid or not. | ||
* | ||
* Most experiences should not modify this option as it eliminates a keyboard user's ability to | ||
* easily clear selection. Only use if the escape key is being handled externally or should not | ||
* trigger selection clearing contextually. | ||
* @default 'clearSelection' | ||
*/ | ||
escapeKeyBehavior?: 'clearSelection' | 'none'; | ||
/** Whether selection should occur on press up instead of press down. */ | ||
shouldSelectOnPressUp?: boolean; | ||
} | ||
@@ -164,2 +181,4 @@ export interface GridAria { | ||
shouldSelectOnPressUp?: boolean; | ||
/** Indicates how many columns the data cell spans. */ | ||
colSpan?: number; | ||
/** | ||
@@ -166,0 +185,0 @@ * Handler that is called when a user performs an action on the cell. |
@@ -37,3 +37,3 @@ var $3187c0e19200cb16$exports = require("./GridKeyboardDelegate.main.js"); | ||
function $11d770dfabe45077$export$f6b86a04e5d66d90(props, state, ref) { | ||
let { isVirtualized: isVirtualized, keyboardDelegate: keyboardDelegate, focusMode: focusMode, scrollRef: scrollRef, getRowText: getRowText, onRowAction: onRowAction, onCellAction: onCellAction } = props; | ||
let { isVirtualized: isVirtualized, disallowTypeAhead: disallowTypeAhead, keyboardDelegate: keyboardDelegate, focusMode: focusMode, scrollRef: scrollRef, getRowText: getRowText, onRowAction: onRowAction, onCellAction: onCellAction, escapeKeyBehavior: escapeKeyBehavior = 'clearSelection', shouldSelectOnPressUp: shouldSelectOnPressUp } = props; | ||
let { selectionManager: manager } = state; | ||
@@ -72,3 +72,5 @@ if (!props['aria-label'] && !props['aria-labelledby']) console.warn('An aria-label or aria-labelledby prop is required for accessibility.'); | ||
isVirtualized: isVirtualized, | ||
scrollRef: scrollRef | ||
scrollRef: scrollRef, | ||
disallowTypeAhead: disallowTypeAhead, | ||
escapeKeyBehavior: escapeKeyBehavior | ||
}); | ||
@@ -81,3 +83,4 @@ let id = (0, $lBaOG$reactariautils.useId)(props.id); | ||
onCellAction: onCellAction | ||
} | ||
}, | ||
shouldSelectOnPressUp: shouldSelectOnPressUp | ||
}); | ||
@@ -84,0 +87,0 @@ let descriptionProps = (0, $340f2fcd0ef9ce8d$exports.useHighlightSelectionDescription)({ |
@@ -31,3 +31,3 @@ import {GridKeyboardDelegate as $d1c300d9c497e402$export$de9feff04fda126e} from "./GridKeyboardDelegate.module.js"; | ||
function $83c6e2eafa584c67$export$f6b86a04e5d66d90(props, state, ref) { | ||
let { isVirtualized: isVirtualized, keyboardDelegate: keyboardDelegate, focusMode: focusMode, scrollRef: scrollRef, getRowText: getRowText, onRowAction: onRowAction, onCellAction: onCellAction } = props; | ||
let { isVirtualized: isVirtualized, disallowTypeAhead: disallowTypeAhead, keyboardDelegate: keyboardDelegate, focusMode: focusMode, scrollRef: scrollRef, getRowText: getRowText, onRowAction: onRowAction, onCellAction: onCellAction, escapeKeyBehavior: escapeKeyBehavior = 'clearSelection', shouldSelectOnPressUp: shouldSelectOnPressUp } = props; | ||
let { selectionManager: manager } = state; | ||
@@ -66,3 +66,5 @@ if (!props['aria-label'] && !props['aria-labelledby']) console.warn('An aria-label or aria-labelledby prop is required for accessibility.'); | ||
isVirtualized: isVirtualized, | ||
scrollRef: scrollRef | ||
scrollRef: scrollRef, | ||
disallowTypeAhead: disallowTypeAhead, | ||
escapeKeyBehavior: escapeKeyBehavior | ||
}); | ||
@@ -75,3 +77,4 @@ let id = (0, $eV0xE$useId)(props.id); | ||
onCellAction: onCellAction | ||
} | ||
}, | ||
shouldSelectOnPressUp: shouldSelectOnPressUp | ||
}); | ||
@@ -78,0 +81,0 @@ let descriptionProps = (0, $5b9b5b5723db6ae1$export$be42ebdab07ae4c2)({ |
var $8ee34951196858d0$exports = require("./utils.main.js"); | ||
var $9yLAi$reactariainteractions = require("@react-aria/interactions"); | ||
var $9yLAi$reactariafocus = require("@react-aria/focus"); | ||
var $9yLAi$reactariautils = require("@react-aria/utils"); | ||
var $9yLAi$reactariainteractions = require("@react-aria/interactions"); | ||
var $9yLAi$react = require("react"); | ||
@@ -49,7 +49,7 @@ var $9yLAi$reactariai18n = require("@react-aria/i18n"); | ||
if (focusable) { | ||
(0, $9yLAi$reactariafocus.focusSafely)(focusable); | ||
(0, $9yLAi$reactariainteractions.focusSafely)(focusable); | ||
return; | ||
} | ||
} | ||
if (keyWhenFocused.current != null && node.key !== keyWhenFocused.current || !ref.current.contains(document.activeElement)) (0, $9yLAi$reactariafocus.focusSafely)(ref.current); | ||
if (keyWhenFocused.current != null && node.key !== keyWhenFocused.current || !ref.current.contains(document.activeElement)) (0, $9yLAi$reactariainteractions.focusSafely)(ref.current); | ||
} | ||
@@ -81,3 +81,3 @@ }; | ||
if (focusable) { | ||
(0, $9yLAi$reactariafocus.focusSafely)(focusable); | ||
(0, $9yLAi$reactariainteractions.focusSafely)(focusable); | ||
(0, $9yLAi$reactariautils.scrollIntoViewport)(focusable, { | ||
@@ -103,3 +103,3 @@ containingElement: (0, $9yLAi$reactariautils.getScrollParent)(ref.current) | ||
if (focusMode === 'cell' && direction === 'rtl') { | ||
(0, $9yLAi$reactariafocus.focusSafely)(ref.current); | ||
(0, $9yLAi$reactariainteractions.focusSafely)(ref.current); | ||
(0, $9yLAi$reactariautils.scrollIntoViewport)(ref.current, { | ||
@@ -112,3 +112,3 @@ containingElement: (0, $9yLAi$reactariautils.getScrollParent)(ref.current) | ||
if (focusable) { | ||
(0, $9yLAi$reactariafocus.focusSafely)(focusable); | ||
(0, $9yLAi$reactariainteractions.focusSafely)(focusable); | ||
(0, $9yLAi$reactariautils.scrollIntoViewport)(focusable, { | ||
@@ -129,3 +129,3 @@ containingElement: (0, $9yLAi$reactariautils.getScrollParent)(ref.current) | ||
if (focusable) { | ||
(0, $9yLAi$reactariafocus.focusSafely)(focusable); | ||
(0, $9yLAi$reactariainteractions.focusSafely)(focusable); | ||
(0, $9yLAi$reactariautils.scrollIntoViewport)(focusable, { | ||
@@ -146,3 +146,3 @@ containingElement: (0, $9yLAi$reactariautils.getScrollParent)(ref.current) | ||
if (focusMode === 'cell' && direction === 'ltr') { | ||
(0, $9yLAi$reactariafocus.focusSafely)(ref.current); | ||
(0, $9yLAi$reactariainteractions.focusSafely)(ref.current); | ||
(0, $9yLAi$reactariautils.scrollIntoViewport)(ref.current, { | ||
@@ -155,3 +155,3 @@ containingElement: (0, $9yLAi$reactariautils.getScrollParent)(ref.current) | ||
if (focusable) { | ||
(0, $9yLAi$reactariafocus.focusSafely)(focusable); | ||
(0, $9yLAi$reactariainteractions.focusSafely)(focusable); | ||
(0, $9yLAi$reactariautils.scrollIntoViewport)(focusable, { | ||
@@ -202,2 +202,5 @@ containingElement: (0, $9yLAi$reactariautils.getScrollParent)(ref.current) | ||
onKeyDownCapture: onKeyDownCapture, | ||
'aria-colspan': node.colSpan, | ||
'aria-colindex': node.colIndex != null ? node.colIndex + 1 : undefined, | ||
colSpan: isVirtualized ? undefined : node.colSpan, | ||
onFocus: onFocus | ||
@@ -204,0 +207,0 @@ }); |
import {gridMap as $1af922eb41e03c8f$export$e6235c0d09b995d0} from "./utils.module.js"; | ||
import {getFocusableTreeWalker as $j4Qbl$getFocusableTreeWalker, focusSafely as $j4Qbl$focusSafely} from "@react-aria/focus"; | ||
import {focusSafely as $j4Qbl$focusSafely, isFocusVisible as $j4Qbl$isFocusVisible} from "@react-aria/interactions"; | ||
import {getFocusableTreeWalker as $j4Qbl$getFocusableTreeWalker} from "@react-aria/focus"; | ||
import {scrollIntoViewport as $j4Qbl$scrollIntoViewport, getScrollParent as $j4Qbl$getScrollParent, mergeProps as $j4Qbl$mergeProps} from "@react-aria/utils"; | ||
import {isFocusVisible as $j4Qbl$isFocusVisible} from "@react-aria/interactions"; | ||
import {useRef as $j4Qbl$useRef} from "react"; | ||
@@ -189,2 +189,5 @@ import {useLocale as $j4Qbl$useLocale} from "@react-aria/i18n"; | ||
onKeyDownCapture: onKeyDownCapture, | ||
'aria-colspan': node.colSpan, | ||
'aria-colindex': node.colIndex != null ? node.colIndex + 1 : undefined, | ||
colSpan: isVirtualized ? undefined : node.colSpan, | ||
onFocus: onFocus | ||
@@ -191,0 +194,0 @@ }); |
@@ -27,3 +27,3 @@ var $8ee34951196858d0$exports = require("./utils.main.js"); | ||
let { node: node, isVirtualized: isVirtualized, shouldSelectOnPressUp: shouldSelectOnPressUp, onAction: onAction } = props; | ||
let { actions: actions } = (0, $8ee34951196858d0$exports.gridMap).get(state); | ||
let { actions: actions, shouldSelectOnPressUp: gridShouldSelectOnPressUp } = (0, $8ee34951196858d0$exports.gridMap).get(state); | ||
let onRowAction = actions.onRowAction ? ()=>{ | ||
@@ -38,3 +38,3 @@ var _actions_onRowAction; | ||
isVirtualized: isVirtualized, | ||
shouldSelectOnPressUp: shouldSelectOnPressUp, | ||
shouldSelectOnPressUp: gridShouldSelectOnPressUp || shouldSelectOnPressUp, | ||
onAction: onRowAction || (node === null || node === void 0 ? void 0 : (_node_props = node.props) === null || _node_props === void 0 ? void 0 : _node_props.onAction) ? (0, $apCYc$reactariautils.chain)(node === null || node === void 0 ? void 0 : (_node_props1 = node.props) === null || _node_props1 === void 0 ? void 0 : _node_props1.onAction, onRowAction) : undefined, | ||
@@ -41,0 +41,0 @@ isDisabled: state.collection.size === 0 |
@@ -21,3 +21,3 @@ import {gridMap as $1af922eb41e03c8f$export$e6235c0d09b995d0} from "./utils.module.js"; | ||
let { node: node, isVirtualized: isVirtualized, shouldSelectOnPressUp: shouldSelectOnPressUp, onAction: onAction } = props; | ||
let { actions: actions } = (0, $1af922eb41e03c8f$export$e6235c0d09b995d0).get(state); | ||
let { actions: actions, shouldSelectOnPressUp: gridShouldSelectOnPressUp } = (0, $1af922eb41e03c8f$export$e6235c0d09b995d0).get(state); | ||
let onRowAction = actions.onRowAction ? ()=>{ | ||
@@ -32,3 +32,3 @@ var _actions_onRowAction; | ||
isVirtualized: isVirtualized, | ||
shouldSelectOnPressUp: shouldSelectOnPressUp, | ||
shouldSelectOnPressUp: gridShouldSelectOnPressUp || shouldSelectOnPressUp, | ||
onAction: onRowAction || (node === null || node === void 0 ? void 0 : (_node_props = node.props) === null || _node_props === void 0 ? void 0 : _node_props.onAction) ? (0, $kA5if$chain)(node === null || node === void 0 ? void 0 : (_node_props1 = node.props) === null || _node_props1 === void 0 ? void 0 : _node_props1.onAction, onRowAction) : undefined, | ||
@@ -35,0 +35,0 @@ isDisabled: state.collection.size === 0 |
var $085250522aa37816$exports = require("./intlStrings.main.js"); | ||
var $iMOYA$reactarialiveannouncer = require("@react-aria/live-announcer"); | ||
var $iMOYA$reactariautils = require("@react-aria/utils"); | ||
var $iMOYA$reactariai18n = require("@react-aria/i18n"); | ||
var $iMOYA$react = require("react"); | ||
var $iMOYA$reactariautils = require("@react-aria/utils"); | ||
@@ -43,5 +43,5 @@ | ||
let lastSelection = (0, $iMOYA$react.useRef)(selection); | ||
(0, $iMOYA$reactariautils.useUpdateEffect)(()=>{ | ||
let announceSelectionChange = (0, $iMOYA$reactariautils.useEffectEvent)(()=>{ | ||
var _lastSelection_current; | ||
if (!state.selectionManager.isFocused) { | ||
if (!state.selectionManager.isFocused || selection === lastSelection.current) { | ||
lastSelection.current = selection; | ||
@@ -56,4 +56,5 @@ return; | ||
if (state.selectionManager.selectedKeys.size === 1 && isReplace) { | ||
if (state.collection.getItem(state.selectionManager.selectedKeys.keys().next().value)) { | ||
let currentSelectionText = getRowText(state.selectionManager.selectedKeys.keys().next().value); | ||
let firstKey = state.selectionManager.selectedKeys.keys().next().value; | ||
if (firstKey != null && state.collection.getItem(firstKey)) { | ||
let currentSelectionText = getRowText(firstKey); | ||
if (currentSelectionText) messages.push(stringFormatter.format('selectedItem', { | ||
@@ -64,9 +65,13 @@ item: currentSelectionText | ||
} else if (addedKeys.size === 1 && removedKeys.size === 0) { | ||
let addedText = getRowText(addedKeys.keys().next().value); | ||
if (addedText) messages.push(stringFormatter.format('selectedItem', { | ||
item: addedText | ||
})); | ||
let firstKey = addedKeys.keys().next().value; | ||
if (firstKey != null) { | ||
let addedText = getRowText(firstKey); | ||
if (addedText) messages.push(stringFormatter.format('selectedItem', { | ||
item: addedText | ||
})); | ||
} | ||
} else if (removedKeys.size === 1 && addedKeys.size === 0) { | ||
if (state.collection.getItem(removedKeys.keys().next().value)) { | ||
let removedText = getRowText(removedKeys.keys().next().value); | ||
let firstKey = removedKeys.keys().next().value; | ||
if (firstKey != null && state.collection.getItem(firstKey)) { | ||
let removedText = getRowText(firstKey); | ||
if (removedText) messages.push(stringFormatter.format('deselectedItem', { | ||
@@ -85,4 +90,13 @@ item: removedText | ||
lastSelection.current = selection; | ||
}); | ||
(0, $iMOYA$reactariautils.useUpdateEffect)(()=>{ | ||
if (state.selectionManager.isFocused) announceSelectionChange(); | ||
else { | ||
// Wait a frame in case the collection is about to become focused (e.g. on mouse down). | ||
let raf = requestAnimationFrame(announceSelectionChange); | ||
return ()=>cancelAnimationFrame(raf); | ||
} | ||
}, [ | ||
selection | ||
selection, | ||
state.selectionManager.isFocused | ||
]); | ||
@@ -89,0 +103,0 @@ } |
import $4stjr$intlStringsmodulejs from "./intlStrings.module.js"; | ||
import {announce as $4stjr$announce} from "@react-aria/live-announcer"; | ||
import {useEffectEvent as $4stjr$useEffectEvent, useUpdateEffect as $4stjr$useUpdateEffect} from "@react-aria/utils"; | ||
import {useLocalizedStringFormatter as $4stjr$useLocalizedStringFormatter} from "@react-aria/i18n"; | ||
import {useRef as $4stjr$useRef} from "react"; | ||
import {useUpdateEffect as $4stjr$useUpdateEffect} from "@react-aria/utils"; | ||
@@ -37,5 +37,5 @@ | ||
let lastSelection = (0, $4stjr$useRef)(selection); | ||
(0, $4stjr$useUpdateEffect)(()=>{ | ||
let announceSelectionChange = (0, $4stjr$useEffectEvent)(()=>{ | ||
var _lastSelection_current; | ||
if (!state.selectionManager.isFocused) { | ||
if (!state.selectionManager.isFocused || selection === lastSelection.current) { | ||
lastSelection.current = selection; | ||
@@ -50,4 +50,5 @@ return; | ||
if (state.selectionManager.selectedKeys.size === 1 && isReplace) { | ||
if (state.collection.getItem(state.selectionManager.selectedKeys.keys().next().value)) { | ||
let currentSelectionText = getRowText(state.selectionManager.selectedKeys.keys().next().value); | ||
let firstKey = state.selectionManager.selectedKeys.keys().next().value; | ||
if (firstKey != null && state.collection.getItem(firstKey)) { | ||
let currentSelectionText = getRowText(firstKey); | ||
if (currentSelectionText) messages.push(stringFormatter.format('selectedItem', { | ||
@@ -58,9 +59,13 @@ item: currentSelectionText | ||
} else if (addedKeys.size === 1 && removedKeys.size === 0) { | ||
let addedText = getRowText(addedKeys.keys().next().value); | ||
if (addedText) messages.push(stringFormatter.format('selectedItem', { | ||
item: addedText | ||
})); | ||
let firstKey = addedKeys.keys().next().value; | ||
if (firstKey != null) { | ||
let addedText = getRowText(firstKey); | ||
if (addedText) messages.push(stringFormatter.format('selectedItem', { | ||
item: addedText | ||
})); | ||
} | ||
} else if (removedKeys.size === 1 && addedKeys.size === 0) { | ||
if (state.collection.getItem(removedKeys.keys().next().value)) { | ||
let removedText = getRowText(removedKeys.keys().next().value); | ||
let firstKey = removedKeys.keys().next().value; | ||
if (firstKey != null && state.collection.getItem(firstKey)) { | ||
let removedText = getRowText(firstKey); | ||
if (removedText) messages.push(stringFormatter.format('deselectedItem', { | ||
@@ -79,4 +84,13 @@ item: removedText | ||
lastSelection.current = selection; | ||
}); | ||
(0, $4stjr$useUpdateEffect)(()=>{ | ||
if (state.selectionManager.isFocused) announceSelectionChange(); | ||
else { | ||
// Wait a frame in case the collection is about to become focused (e.g. on mouse down). | ||
let raf = requestAnimationFrame(announceSelectionChange); | ||
return ()=>cancelAnimationFrame(raf); | ||
} | ||
}, [ | ||
selection | ||
selection, | ||
state.selectionManager.isFocused | ||
]); | ||
@@ -83,0 +97,0 @@ } |
{ | ||
"name": "@react-aria/grid", | ||
"version": "3.0.0-nightly-326f48154-241216", | ||
"version": "3.0.0-nightly-3bc78aeea-250821", | ||
"description": "Spectrum UI components in React", | ||
@@ -9,3 +9,7 @@ "license": "Apache-2.0", | ||
"exports": { | ||
"types": "./dist/types.d.ts", | ||
"source": "./src/index.ts", | ||
"types": [ | ||
"./dist/types.d.ts", | ||
"./src/index.ts" | ||
], | ||
"import": "./dist/import.mjs", | ||
@@ -26,14 +30,14 @@ "require": "./dist/main.js" | ||
"dependencies": { | ||
"@react-aria/focus": "3.0.0-nightly-326f48154-241216", | ||
"@react-aria/i18n": "3.0.0-nightly-326f48154-241216", | ||
"@react-aria/interactions": "3.0.0-nightly-326f48154-241216", | ||
"@react-aria/live-announcer": "3.0.0-nightly-326f48154-241216", | ||
"@react-aria/selection": "3.0.0-nightly-326f48154-241216", | ||
"@react-aria/utils": "3.0.0-nightly-326f48154-241216", | ||
"@react-stately/collections": "3.0.0-nightly-326f48154-241216", | ||
"@react-stately/grid": "3.0.0-nightly-326f48154-241216", | ||
"@react-stately/selection": "3.0.0-nightly-326f48154-241216", | ||
"@react-types/checkbox": "3.0.0-nightly-326f48154-241216", | ||
"@react-types/grid": "3.0.0-nightly-326f48154-241216", | ||
"@react-types/shared": "3.0.0-nightly-326f48154-241216", | ||
"@react-aria/focus": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-aria/i18n": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-aria/interactions": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-aria/live-announcer": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-aria/selection": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-aria/utils": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-stately/collections": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-stately/grid": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-stately/selection": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-types/checkbox": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-types/grid": "3.0.0-nightly-3bc78aeea-250821", | ||
"@react-types/shared": "3.0.0-nightly-3bc78aeea-250821", | ||
"@swc/helpers": "^0.5.0" | ||
@@ -40,0 +44,0 @@ }, |
@@ -16,3 +16,3 @@ /* | ||
import {getChildNodes, getFirstItem, getLastItem, getNthItem} from '@react-stately/collections'; | ||
import {GridCollection} from '@react-types/grid'; | ||
import {GridCollection, GridNode} from '@react-types/grid'; | ||
@@ -39,3 +39,3 @@ export interface GridKeyboardDelegateOptions<C> { | ||
protected layoutDelegate: LayoutDelegate; | ||
protected focusMode; | ||
protected focusMode: 'row' | 'cell'; | ||
@@ -52,10 +52,10 @@ constructor(options: GridKeyboardDelegateOptions<C>) { | ||
this.layoutDelegate = options.layoutDelegate || (options.layout ? new DeprecatedLayoutDelegate(options.layout) : new DOMLayoutDelegate(options.ref!)); | ||
this.focusMode = options.focusMode || 'row'; | ||
this.focusMode = options.focusMode ?? 'row'; | ||
} | ||
protected isCell(node: Node<T>) { | ||
protected isCell(node: Node<T>): boolean { | ||
return node.type === 'cell'; | ||
} | ||
protected isRow(node: Node<T>) { | ||
protected isRow(node: Node<T>): boolean { | ||
return node.type === 'row' || node.type === 'item'; | ||
@@ -68,3 +68,3 @@ } | ||
protected findPreviousKey(fromKey?: Key, pred?: (item: Node<T>) => boolean) { | ||
protected findPreviousKey(fromKey?: Key, pred?: (item: Node<T>) => boolean): Key | null { | ||
let key = fromKey != null | ||
@@ -88,3 +88,3 @@ ? this.collection.getKeyBefore(fromKey) | ||
protected findNextKey(fromKey?: Key, pred?: (item: Node<T>) => boolean) { | ||
protected findNextKey(fromKey?: Key, pred?: (item: Node<T>) => boolean): Key | null { | ||
let key = fromKey != null | ||
@@ -111,3 +111,32 @@ ? this.collection.getKeyAfter(fromKey) | ||
getKeyBelow(fromKey: Key) { | ||
protected getKeyForItemInRowByIndex(key: Key, index: number = 0): Key | null { | ||
if (index < 0) { | ||
return null; | ||
} | ||
let item = this.collection.getItem(key); | ||
if (!item) { | ||
return null; | ||
} | ||
let i = 0; | ||
for (let child of getChildNodes(item, this.collection) as Iterable<GridNode<T>>) { | ||
if (child.colSpan && child.colSpan + i > index) { | ||
return child.key ?? null; | ||
} | ||
if (child.colSpan) { | ||
i = i + child.colSpan - 1; | ||
} | ||
if (i === index) { | ||
return child.key ?? null; | ||
} | ||
i++; | ||
} | ||
return null; | ||
} | ||
getKeyBelow(fromKey: Key): Key | null { | ||
let key: Key | null = fromKey; | ||
@@ -132,7 +161,4 @@ let startItem = this.collection.getItem(key); | ||
if (this.isCell(startItem)) { | ||
let item = this.collection.getItem(key); | ||
if (!item) { | ||
return null; | ||
} | ||
return getNthItem(getChildNodes(item, this.collection), startItem.index ?? 0)?.key ?? null; | ||
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index; | ||
return this.getKeyForItemInRowByIndex(key, startIndex); | ||
} | ||
@@ -148,3 +174,3 @@ | ||
getKeyAbove(fromKey: Key) { | ||
getKeyAbove(fromKey: Key): Key | null { | ||
let key: Key | null = fromKey; | ||
@@ -169,7 +195,4 @@ let startItem = this.collection.getItem(key); | ||
if (this.isCell(startItem)) { | ||
let item = this.collection.getItem(key); | ||
if (!item) { | ||
return null; | ||
} | ||
return getNthItem(getChildNodes(item, this.collection), startItem.index ?? 0)?.key || null; | ||
let startIndex = startItem.colIndex ? startItem.colIndex : startItem.index; | ||
return this.getKeyForItemInRowByIndex(key, startIndex); | ||
} | ||
@@ -185,3 +208,3 @@ | ||
getKeyRightOf(key: Key) { | ||
getKeyRightOf(key: Key): Key | null { | ||
let item = this.collection.getItem(key); | ||
@@ -226,3 +249,3 @@ if (!item) { | ||
getKeyLeftOf(key: Key) { | ||
getKeyLeftOf(key: Key): Key | null { | ||
let item = this.collection.getItem(key); | ||
@@ -267,3 +290,3 @@ if (!item) { | ||
getFirstKey(fromKey?: Key, global?: boolean) { | ||
getFirstKey(fromKey?: Key, global?: boolean): Key | null { | ||
let key: Key | null = fromKey ?? null; | ||
@@ -304,3 +327,3 @@ let item: Node<T> | undefined | null; | ||
getLastKey(fromKey?: Key, global?: boolean) { | ||
getLastKey(fromKey?: Key, global?: boolean): Key | null { | ||
let key: Key | null = fromKey ?? null; | ||
@@ -343,3 +366,3 @@ let item: Node<T> | undefined | null; | ||
getKeyPageAbove(fromKey: Key) { | ||
getKeyPageAbove(fromKey: Key): Key | null { | ||
let key: Key | null = fromKey; | ||
@@ -364,3 +387,3 @@ let itemRect = this.layoutDelegate.getItemRect(key); | ||
getKeyPageBelow(fromKey: Key) { | ||
getKeyPageBelow(fromKey: Key): Key | null { | ||
let key: Key | null = fromKey; | ||
@@ -390,3 +413,3 @@ let itemRect = this.layoutDelegate.getItemRect(key); | ||
getKeyForSearch(search: string, fromKey?: Key) { | ||
getKeyForSearch(search: string, fromKey?: Key): Key | null { | ||
let key: Key | null = fromKey ?? null; | ||
@@ -393,0 +416,0 @@ if (!this.collator) { |
@@ -30,2 +30,7 @@ /* | ||
/** | ||
* Whether typeahead navigation is disabled. | ||
* @default false | ||
*/ | ||
disallowTypeAhead?: boolean, | ||
/** | ||
* An optional keyboard delegate implementation for type to select, | ||
@@ -52,3 +57,14 @@ * to override the default. | ||
/** Handler that is called when a user performs an action on the cell. */ | ||
onCellAction?: (key: Key) => void | ||
onCellAction?: (key: Key) => void, | ||
/** | ||
* Whether pressing the escape key should clear selection in the grid or not. | ||
* | ||
* Most experiences should not modify this option as it eliminates a keyboard user's ability to | ||
* easily clear selection. Only use if the escape key is being handled externally or should not | ||
* trigger selection clearing contextually. | ||
* @default 'clearSelection' | ||
*/ | ||
escapeKeyBehavior?: 'clearSelection' | 'none', | ||
/** Whether selection should occur on press up instead of press down. */ | ||
shouldSelectOnPressUp?: boolean | ||
} | ||
@@ -71,2 +87,3 @@ | ||
isVirtualized, | ||
disallowTypeAhead, | ||
keyboardDelegate, | ||
@@ -77,3 +94,5 @@ focusMode, | ||
onRowAction, | ||
onCellAction | ||
onCellAction, | ||
escapeKeyBehavior = 'clearSelection', | ||
shouldSelectOnPressUp | ||
} = props; | ||
@@ -106,7 +125,9 @@ let {selectionManager: manager} = state; | ||
isVirtualized, | ||
scrollRef | ||
scrollRef, | ||
disallowTypeAhead, | ||
escapeKeyBehavior | ||
}); | ||
let id = useId(props.id); | ||
gridMap.set(state, {keyboardDelegate: delegate, actions: {onRowAction, onCellAction}}); | ||
gridMap.set(state, {keyboardDelegate: delegate, actions: {onRowAction, onCellAction}, shouldSelectOnPressUp}); | ||
@@ -113,0 +134,0 @@ let descriptionProps = useHighlightSelectionDescription({ |
@@ -14,3 +14,4 @@ /* | ||
import {DOMAttributes, FocusableElement, Key, RefObject} from '@react-types/shared'; | ||
import {focusSafely, getFocusableTreeWalker} from '@react-aria/focus'; | ||
import {focusSafely, isFocusVisible} from '@react-aria/interactions'; | ||
import {getFocusableTreeWalker} from '@react-aria/focus'; | ||
import {getScrollParent, mergeProps, scrollIntoViewport} from '@react-aria/utils'; | ||
@@ -20,3 +21,2 @@ import {GridCollection, GridNode} from '@react-types/grid'; | ||
import {GridState} from '@react-stately/grid'; | ||
import {isFocusVisible} from '@react-aria/interactions'; | ||
import {KeyboardEvent as ReactKeyboardEvent, useRef} from 'react'; | ||
@@ -35,2 +35,4 @@ import {useLocale} from '@react-aria/i18n'; | ||
shouldSelectOnPressUp?: boolean, | ||
/** Indicates how many columns the data cell spans. */ | ||
colSpan?: number, | ||
/** | ||
@@ -257,2 +259,5 @@ * Handler that is called when a user performs an action on the cell. | ||
onKeyDownCapture, | ||
'aria-colspan': node.colSpan, | ||
'aria-colindex': node.colIndex != null ? node.colIndex + 1 : undefined, // aria-colindex is 1-based | ||
colSpan: isVirtualized ? undefined : node.colSpan, | ||
onFocus | ||
@@ -259,0 +264,0 @@ }); |
@@ -55,3 +55,3 @@ /* | ||
let {actions} = gridMap.get(state)!; | ||
let {actions, shouldSelectOnPressUp: gridShouldSelectOnPressUp} = gridMap.get(state)!; | ||
let onRowAction = actions.onRowAction ? () => actions.onRowAction?.(node.key) : onAction; | ||
@@ -63,3 +63,3 @@ let {itemProps, ...states} = useSelectableItem({ | ||
isVirtualized, | ||
shouldSelectOnPressUp, | ||
shouldSelectOnPressUp: gridShouldSelectOnPressUp || shouldSelectOnPressUp, | ||
onAction: onRowAction || node?.props?.onAction ? chain(node?.props?.onAction, onRowAction) : undefined, | ||
@@ -66,0 +66,0 @@ isDisabled: state.collection.size === 0 |
@@ -18,5 +18,5 @@ /* | ||
import {SelectionManager} from '@react-stately/selection'; | ||
import {useEffectEvent, useUpdateEffect} from '@react-aria/utils'; | ||
import {useLocalizedStringFormatter} from '@react-aria/i18n'; | ||
import {useRef} from 'react'; | ||
import {useUpdateEffect} from '@react-aria/utils'; | ||
@@ -40,3 +40,3 @@ export interface GridSelectionAnnouncementProps { | ||
export function useGridSelectionAnnouncement<T>(props: GridSelectionAnnouncementProps, state: GridSelectionState<T>) { | ||
export function useGridSelectionAnnouncement<T>(props: GridSelectionAnnouncementProps, state: GridSelectionState<T>): void { | ||
let { | ||
@@ -51,4 +51,4 @@ getRowText = (key) => state.collection.getTextValue?.(key) ?? state.collection.getItem(key)?.textValue | ||
let lastSelection = useRef(selection); | ||
useUpdateEffect(() => { | ||
if (!state.selectionManager.isFocused) { | ||
let announceSelectionChange = useEffectEvent(() => { | ||
if (!state.selectionManager.isFocused || selection === lastSelection.current) { | ||
lastSelection.current = selection; | ||
@@ -67,4 +67,5 @@ | ||
if ((state.selectionManager.selectedKeys.size === 1 && isReplace)) { | ||
if (state.collection.getItem(state.selectionManager.selectedKeys.keys().next().value)) { | ||
let currentSelectionText = getRowText(state.selectionManager.selectedKeys.keys().next().value); | ||
let firstKey = state.selectionManager.selectedKeys.keys().next().value; | ||
if (firstKey != null && state.collection.getItem(firstKey)) { | ||
let currentSelectionText = getRowText(firstKey); | ||
if (currentSelectionText) { | ||
@@ -75,9 +76,13 @@ messages.push(stringFormatter.format('selectedItem', {item: currentSelectionText})); | ||
} else if (addedKeys.size === 1 && removedKeys.size === 0) { | ||
let addedText = getRowText(addedKeys.keys().next().value); | ||
if (addedText) { | ||
messages.push(stringFormatter.format('selectedItem', {item: addedText})); | ||
let firstKey = addedKeys.keys().next().value; | ||
if (firstKey != null) { | ||
let addedText = getRowText(firstKey); | ||
if (addedText) { | ||
messages.push(stringFormatter.format('selectedItem', {item: addedText})); | ||
} | ||
} | ||
} else if (removedKeys.size === 1 && addedKeys.size === 0) { | ||
if (state.collection.getItem(removedKeys.keys().next().value)) { | ||
let removedText = getRowText(removedKeys.keys().next().value); | ||
let firstKey = removedKeys.keys().next().value; | ||
if (firstKey != null && state.collection.getItem(firstKey)) { | ||
let removedText = getRowText(firstKey); | ||
if (removedText) { | ||
@@ -104,3 +109,13 @@ messages.push(stringFormatter.format('deselectedItem', {item: removedText})); | ||
lastSelection.current = selection; | ||
}, [selection]); | ||
}); | ||
useUpdateEffect(() => { | ||
if (state.selectionManager.isFocused) { | ||
announceSelectionChange(); | ||
} else { | ||
// Wait a frame in case the collection is about to become focused (e.g. on mouse down). | ||
let raf = requestAnimationFrame(announceSelectionChange); | ||
return () => cancelAnimationFrame(raf); | ||
} | ||
}, [selection, state.selectionManager.isFocused]); | ||
} | ||
@@ -107,0 +122,0 @@ |
@@ -22,3 +22,4 @@ /* | ||
onCellAction?: (key: Key) => void | ||
} | ||
}, | ||
shouldSelectOnPressUp?: boolean | ||
} | ||
@@ -29,2 +30,2 @@ | ||
// onRowAction/onCellAction across hooks | ||
export const gridMap = new WeakMap<GridState<unknown, GridCollection<unknown>>, GridMapShared>(); | ||
export const gridMap: WeakMap<GridState<unknown, GridCollection<unknown>>, GridMapShared> = new WeakMap<GridState<unknown, GridCollection<unknown>>, GridMapShared>(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
546338
2.68%5887
2.9%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated