Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/@react-aria/grid/src/useGridSelectionAnnouncement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {announce} from '@react-aria/live-announcer';
import {Collection, Key, Node, Selection} from '@react-types/shared';
// @ts-ignore
import intlMessages from '../intl/*.json';
import {SelectionManager} from '@react-stately/selection';
import {MultipleSelectionManager} from '@react-stately/selection';
import {useEffectEvent, useUpdateEffect} from '@react-aria/utils';
import {useLocalizedStringFormatter} from '@react-aria/i18n';
import {useRef} from 'react';
Expand All @@ -33,7 +33,7 @@ interface GridSelectionState<T> {
/** A set of items that are disabled. */
disabledKeys: Set<Key>,
/** A selection manager to read and update multiple selection state. */
selectionManager: SelectionManager
selectionManager: MultipleSelectionManager
}

export function useGridSelectionAnnouncement<T>(props: GridSelectionAnnouncementProps, state: GridSelectionState<T>): void {
Expand Down
2 changes: 2 additions & 0 deletions packages/@react-aria/grid/src/useGridSelectionCheckbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function useGridSelectionCheckbox<T, C extends GridCollection<T>>(props:
let checkboxId = useId();
let isDisabled = !state.selectionManager.canSelectItem(key);
let isSelected = state.selectionManager.isSelected(key);
let isIndeterminate = state.selectionManager.isIndeterminate?.(key);

// Checkbox should always toggle selection, regardless of selectionBehavior.
let onChange = () => manager.toggleSelection(key);
Expand All @@ -42,6 +43,7 @@ export function useGridSelectionCheckbox<T, C extends GridCollection<T>>(props:
'aria-label': stringFormatter.format('select'),
isSelected,
isDisabled,
isIndeterminate,
onChange
}
};
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-aria/menu/src/useMenuItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {getItemCount} from '@react-stately/collections';
import {isFocusVisible, useFocus, useHover, useKeyboard, usePress} from '@react-aria/interactions';
import {menuData} from './utils';
import {MouseEvent, useRef} from 'react';
import {SelectionManager} from '@react-stately/selection';
import {MultipleSelectionManager} from '@react-stately/selection';
import {TreeState} from '@react-stately/tree';
import {useSelectableItem} from '@react-aria/selection';

Expand Down Expand Up @@ -95,7 +95,7 @@ export interface AriaMenuItemProps extends DOMProps, PressEvents, HoverEvents, K
'aria-controls'?: string,

/** Override of the selection manager. By default, `state.selectionManager` is used. */
selectionManager?: SelectionManager
selectionManager?: MultipleSelectionManager
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-stately/grid/src/useGridState.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {getChildNodes, getFirstItem, getLastItem} from '@react-stately/collections';
import {GridCollection, GridNode} from '@react-types/grid';
import {Key} from '@react-types/shared';
import {MultipleSelectionState, MultipleSelectionStateProps, SelectionManager, useMultipleSelectionState} from '@react-stately/selection';
import {MultipleSelectionManager, MultipleSelectionState, MultipleSelectionStateProps, SelectionManager, useMultipleSelectionState} from '@react-stately/selection';
import {useEffect, useMemo, useRef} from 'react';

export interface GridState<T, C extends GridCollection<T>> {
collection: C,
/** A set of keys for rows that are disabled. */
disabledKeys: Set<Key>,
/** A selection manager to read and update row selection state. */
selectionManager: SelectionManager,
selectionManager: MultipleSelectionManager,
/** Whether keyboard navigation is disabled, such as when the arrow keys should be handled by a component within a cell. */
isKeyboardNavigationDisabled: boolean
}
Expand Down
6 changes: 3 additions & 3 deletions packages/@react-stately/list/src/useListState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import {Collection, CollectionStateBase, Key, LayoutDelegate, Node} from '@react-types/shared';
import {ListCollection} from './ListCollection';
import {MultipleSelectionStateProps, SelectionManager, useMultipleSelectionState} from '@react-stately/selection';
import {MultipleSelectionManager, MultipleSelectionStateProps, SelectionManager, useMultipleSelectionState} from '@react-stately/selection';
import {useCallback, useEffect, useMemo, useRef} from 'react';
import {useCollection} from '@react-stately/collections';

Expand All @@ -36,7 +36,7 @@ export interface ListState<T> {
disabledKeys: Set<Key>,

/** A selection manager to read and update multiple selection state. */
selectionManager: SelectionManager
selectionManager: MultipleSelectionManager
}

/**
Expand Down Expand Up @@ -84,7 +84,7 @@ export function UNSTABLE_useFilteredListState<T extends object>(state: ListState
};
}

function useFocusedKeyReset<T>(collection: Collection<Node<T>>, selectionManager: SelectionManager) {
function useFocusedKeyReset<T>(collection: Collection<Node<T>>, selectionManager: MultipleSelectionManager) {
// Reset focused key if that item is deleted from the collection.
const cachedCollection = useRef<Collection<Node<T>> | null>(null);
useEffect(() => {
Expand Down
42 changes: 25 additions & 17 deletions packages/@react-stately/selection/src/SelectionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ interface SelectionManagerOptions {
*/
export class SelectionManager implements MultipleSelectionManager {
collection: Collection<Node<unknown>>;
private state: MultipleSelectionState;
protected state: MultipleSelectionState;
private allowsCellSelection: boolean;
private _isSelectAll: boolean | null;
private layoutDelegate: LayoutDelegate | null;
Expand All @@ -49,6 +49,14 @@ export class SelectionManager implements MultipleSelectionManager {
this.layoutDelegate = options?.layoutDelegate || null;
}

protected get selection(): ISelection {
return this.state.selectedKeys;
}

protected setSelection(selection: ISelection) {
this.state.setSelectedKeys(selection);
}

/**
* The type of selection that is allowed in the collection.
*/
Expand Down Expand Up @@ -116,9 +124,9 @@ export class SelectionManager implements MultipleSelectionManager {
* The currently selected keys in the collection.
*/
get selectedKeys(): Set<Key> {
return this.state.selectedKeys === 'all'
return this.selection === 'all'
? new Set(this.getSelectAllKeys())
: this.state.selectedKeys;
: this.selection;
}

/**
Expand All @@ -141,9 +149,9 @@ export class SelectionManager implements MultipleSelectionManager {
if (mappedKey == null) {
return false;
}
return this.state.selectedKeys === 'all'
return this.selection === 'all'
? this.canSelectItem(mappedKey)
: this.state.selectedKeys.has(mappedKey);
: this.selection.has(mappedKey);
}

/**
Expand All @@ -161,7 +169,7 @@ export class SelectionManager implements MultipleSelectionManager {
return false;
}

if (this.state.selectedKeys === 'all') {
if (this.selection === 'all') {
return true;
}

Expand All @@ -170,14 +178,14 @@ export class SelectionManager implements MultipleSelectionManager {
}

let allKeys = this.getSelectAllKeys();
let selectedKeys = this.state.selectedKeys;
let selectedKeys = this.selection;
this._isSelectAll = allKeys.every(k => selectedKeys.has(k));
return this._isSelectAll;
}

get firstSelectedKey(): Key | null {
let first: Node<unknown> | null = null;
for (let key of this.state.selectedKeys) {
for (let key of this.selectedKeys) {
let item = this.collection.getItem(key);
if (!first || (item && compareNodeOrder(this.collection, item, first) < 0)) {
first = item;
Expand All @@ -189,7 +197,7 @@ export class SelectionManager implements MultipleSelectionManager {

get lastSelectedKey(): Key | null {
let last: Node<unknown> | null = null;
for (let key of this.state.selectedKeys) {
for (let key of this.selectedKeys) {
let item = this.collection.getItem(key);
if (!last || (item && compareNodeOrder(this.collection, item, last) > 0)) {
last = item;
Expand Down Expand Up @@ -228,10 +236,10 @@ export class SelectionManager implements MultipleSelectionManager {
let selection: Selection;

// Only select the one key if coming from a select all.
if (this.state.selectedKeys === 'all') {
if (this.selection === 'all') {
selection = new Selection([mappedToKey], mappedToKey, mappedToKey);
} else {
let selectedKeys = this.state.selectedKeys as Selection;
let selectedKeys = this.selection as Selection;
let anchorKey = selectedKeys.anchorKey ?? mappedToKey;
selection = new Selection(selectedKeys, anchorKey, mappedToKey);
for (let key of this.getKeyRange(anchorKey, selectedKeys.currentKey ?? mappedToKey)) {
Expand All @@ -245,7 +253,7 @@ export class SelectionManager implements MultipleSelectionManager {
}
}

this.state.setSelectedKeys(selection);
this.setSelection(selection);
}

private getKeyRange(from: Key, to: Key) {
Expand Down Expand Up @@ -285,7 +293,7 @@ export class SelectionManager implements MultipleSelectionManager {
return [];
}

private getKey(key: Key) {
protected getKey(key: Key) {
let item = this.collection.getItem(key);
if (!item) {
// ¯\_(ツ)_/¯
Expand Down Expand Up @@ -327,7 +335,7 @@ export class SelectionManager implements MultipleSelectionManager {
return;
}

let keys = new Selection(this.state.selectedKeys === 'all' ? this.getSelectAllKeys() : this.state.selectedKeys);
let keys = new Selection(this.selection === 'all' ? this.getSelectAllKeys() : this.selection);
if (keys.has(mappedKey)) {
keys.delete(mappedKey);
// TODO: move anchor to last selected key...
Expand All @@ -342,7 +350,7 @@ export class SelectionManager implements MultipleSelectionManager {
return;
}

this.state.setSelectedKeys(keys);
this.setSelection(keys);
}

/**
Expand All @@ -362,7 +370,7 @@ export class SelectionManager implements MultipleSelectionManager {
? new Selection([mappedKey], mappedKey, mappedKey)
: new Selection();

this.state.setSelectedKeys(selection);
this.setSelection(selection);
}

/**
Expand All @@ -384,7 +392,7 @@ export class SelectionManager implements MultipleSelectionManager {
}
}

this.state.setSelectedKeys(selection);
this.setSelection(selection);
}

private getSelectAllKeys() {
Expand Down
Loading