Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
c3b9fe5
first stab at adding ListViewSection
LFDanLu Feb 3, 2023
ab65acb
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Feb 7, 2023
13fb063
rough modifications to TableBody to accept Sections
LFDanLu Feb 8, 2023
f86cd72
rough implementation of section in tableview
LFDanLu Feb 9, 2023
5d822e2
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Feb 21, 2023
3b9eb67
update keyboard delegate and add some initial structure
LFDanLu Feb 22, 2023
01a06d1
refactor ListViewSection to work with multiple row groups
LFDanLu Feb 23, 2023
cf184bc
updating styles for section headers and first/last listview items
LFDanLu Feb 24, 2023
bdde904
tentative refactor to listview css to unify lists with section and wi…
LFDanLu Feb 25, 2023
741c77d
revert style changes
LFDanLu Feb 25, 2023
808f737
adding more stories and trying to add padding after section
LFDanLu Feb 25, 2023
a13989d
some additional brain storming for adding spacing between sections an…
LFDanLu Feb 27, 2023
62d0b6c
add useTableSection
LFDanLu Feb 27, 2023
b2f19df
Adding styles to table headers
LFDanLu Feb 28, 2023
cfd3529
Adding section tracking to GridCollection + colspan row gridnodes
LFDanLu Feb 28, 2023
9dd8ef9
fix sections when table selection is enabled
LFDanLu Mar 1, 2023
ecdb1d4
debugging table layout persisted keys
LFDanLu Mar 2, 2023
7e8b19c
updated buildBody, debugging odd rerendering
LFDanLu Mar 2, 2023
e972a30
fixing toggling selection for tables with sections
LFDanLu Mar 3, 2023
9737e70
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Mar 6, 2023
6b00dae
Add TableSection and cleanup some todos
LFDanLu Mar 6, 2023
9185ed8
using pred to avoid focusing sections via keyboard
LFDanLu Mar 7, 2023
ec61a57
tentative change to make section announce alongside the row headers
LFDanLu Mar 7, 2023
ede57de
remove extraneous dep
LFDanLu Mar 7, 2023
152ae9d
Making Table section title required and warning if row doesnt belong …
LFDanLu Mar 8, 2023
dbfbc5c
make title only required for spectrum table section
LFDanLu Mar 8, 2023
a169887
making ListView and ListBox warn if row isnt in section if sections e…
LFDanLu Mar 8, 2023
591f136
fix tests and lint
LFDanLu Mar 8, 2023
98a9335
Revert "tentative change to make section announce alongside the row h…
LFDanLu Mar 8, 2023
2cc10df
Adding section announcement for grid sections for VoiceOver
LFDanLu Mar 9, 2023
1e9960e
Fix section header width when there is horizontal scrolling
LFDanLu Mar 9, 2023
f76b73a
hacky sticky section header
LFDanLu Mar 9, 2023
1b82666
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Mar 9, 2023
c65448b
fix lint
LFDanLu Mar 9, 2023
866e132
update how we apply sticky to section header
LFDanLu Mar 9, 2023
62c2500
intial working styles for listview sections
LFDanLu Mar 10, 2023
1c58e91
partial move into shared style
LFDanLu Mar 10, 2023
5728fb1
just use keymap to figure out the row index for listview
LFDanLu Mar 10, 2023
52df49e
fix focus ring indicator rounded corners for sections
LFDanLu Mar 10, 2023
08a4762
Fix chromatic stories
LFDanLu Mar 14, 2023
dbb9af3
fixing tests and updating TableBody section check
LFDanLu Mar 15, 2023
c232741
moving emphasized styles to top level
LFDanLu Mar 15, 2023
9320f56
clean up some todos
LFDanLu Mar 15, 2023
0c9a331
removing listview specific changes
LFDanLu Mar 15, 2023
6d35df9
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Mar 28, 2023
9849944
addressing review comments and fix persistedIndex increment
LFDanLu Mar 29, 2023
8c1d66d
revert change with persist index change
LFDanLu Mar 29, 2023
22e8fbc
adding basic tests before collection refactor
LFDanLu Mar 29, 2023
01f47d7
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Mar 29, 2023
047aa97
refactoring collection and layout so that we generate a section heade…
LFDanLu Mar 15, 2023
65e47f1
fixes to table collection refactor
LFDanLu Mar 30, 2023
a987c70
cleanup
LFDanLu Mar 31, 2023
c042720
fix keyboard navigation and persisted key index calc after refactor
LFDanLu Mar 31, 2023
734b17e
fix End/PageUp/tab into table, calculated rowIndex and investiagtion …
LFDanLu Mar 31, 2023
7d1732d
merge section and row group cases in addVisibleLayouts and fix bugs
LFDanLu Mar 31, 2023
9af598b
add more tests and fix more bugs
LFDanLu Apr 3, 2023
ab92e48
fix logic
LFDanLu Apr 4, 2023
4b0fd4a
fix test
LFDanLu Apr 4, 2023
36a73a3
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Apr 4, 2023
ca029a9
cherry pick Object assign fix from GridCollection refactor
LFDanLu Apr 4, 2023
6f60708
refactor GridCollection so it accepts just the top level nodes and di…
LFDanLu Apr 5, 2023
735b48a
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Apr 6, 2023
14c4fef
updating section custom announcement so it announces number of rows
LFDanLu Apr 6, 2023
dbc9834
add test for section announcement
LFDanLu Apr 6, 2023
2ef6380
add chromatic stories
LFDanLu Apr 6, 2023
3c9901b
port over listview DnD section fixes and update for tableview
LFDanLu Apr 7, 2023
97ef9b2
fix drop indicator for last row in section
LFDanLu Apr 10, 2023
d013ef3
commiting first pass of fixing DnD issues
LFDanLu Apr 10, 2023
dc7fa56
changing type of section row header from row to header
LFDanLu Apr 11, 2023
b23c3a8
refactor to remove sections prop from TableCollection
LFDanLu Apr 11, 2023
8e557f7
update section header color during root drop
LFDanLu Apr 11, 2023
fd586d1
testing aria-posinset instead of aria-rowindex
LFDanLu Apr 12, 2023
f409365
Revert "testing aria-posinset instead of aria-rowindex"
LFDanLu Apr 12, 2023
d828d0e
fix Table section DnD story
LFDanLu Apr 13, 2023
b63add7
fixing useTreeData remove stale items state usage
LFDanLu Apr 13, 2023
76bcda5
adding TableView sections DnD tests
LFDanLu Apr 13, 2023
6edb61c
cleanup and moving types around
LFDanLu Apr 14, 2023
0750def
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Apr 14, 2023
f00cfb5
updating controls for loadingState
LFDanLu Apr 14, 2023
36b6448
fixing stories
LFDanLu Apr 14, 2023
cbd6a31
fixing lint
LFDanLu Apr 14, 2023
72ec02b
fix ListBox test
LFDanLu Apr 14, 2023
02a27b7
Merge branch 'main' into sections_in_table
LFDanLu Apr 24, 2023
96f4921
tentative support for dropping on empty sections
LFDanLu Apr 24, 2023
4b7e356
fix some section dnd bugs
LFDanLu Apr 25, 2023
98e6faf
fix crash and support mouse dnd into empty section
LFDanLu Apr 25, 2023
fcf0c6e
refactor so dnd specific key navigation is obtained via ListLayout
LFDanLu Apr 25, 2023
f500a0c
fix section drop indicator announcement and navigation between empty …
LFDanLu Apr 25, 2023
ddb4bd8
updating stories with stopgap solution for updating .value
LFDanLu Apr 27, 2023
8544edb
fix case where you could mistakenly drop on before/after the section
LFDanLu Apr 27, 2023
481cd43
Merge branch 'main' of github.com:adobe/react-spectrum into sections_…
LFDanLu Apr 27, 2023
6b412f3
adding tests and some clean up
LFDanLu Apr 28, 2023
197d3e5
Merge branch 'main' into sections_in_table
LFDanLu May 2, 2023
8358184
cleanup and story updates for mobile from testing
LFDanLu May 2, 2023
3d38bea
one last comment to clean up
LFDanLu May 2, 2023
066bf93
update announcements for positions before/after section headers
LFDanLu May 4, 2023
61712d2
fix test
LFDanLu May 4, 2023
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
3 changes: 3 additions & 0 deletions packages/@adobe/spectrum-css-temp/components/table/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ svg.spectrum-Table-sortedIcon {
margin-bottom: -1px;
z-index: 1;
}

.spectrum-Table-sectionCellContents,
.spectrum-Table-headCellContents {
display: inline-block;
min-inline-size: 0;
Expand All @@ -69,6 +71,7 @@ svg.spectrum-Table-sortedIcon {
text-overflow: ellipsis;
}

.spectrum-Table-sectionCell,
.spectrum-Table-headCell {
display: flex;
box-sizing: border-box;
Expand Down
7 changes: 7 additions & 0 deletions packages/@adobe/spectrum-css-temp/components/table/skin.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ governing permissions and limitations under the License.
--spectrum-table-row-border-color-selected: var(--spectrum-global-color-blue-500);
--spectrum-table-cell-border-color-selected: var(--spectrum-global-color-blue-500);
--spectrum-table-row-focus-indicator-color: var(--spectrum-selectlist-option-focus-indicator-color);
--spectrum-table-section-header-background-color: var(--spectrum-global-color-gray-200);
}

.spectrum-Table-headWrapper {
Expand All @@ -32,6 +33,11 @@ governing permissions and limitations under the License.
forced-color-adjust: none;
}

.spectrum-Table-sectionCell {
color: var(--spectrum-alias-text-color);
background-color: var(--spectrum-table-section-header-background-color);
}

.spectrum-Table-headCell {
color: var(--spectrum-alias-text-color);
background-color: var(--spectrum-alias-background-color-default);
Expand Down Expand Up @@ -142,6 +148,7 @@ tbody.spectrum-Table-body {
}
}

.spectrum-Table-sectionRow,
.spectrum-Table-row {
box-sizing: border-box;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface AriaSearchAutocompleteOptions<T> extends AriaSearchAutocomplete
/** The ref for the list box. */
listBoxRef: RefObject<HTMLElement>,
/** An optional keyboard delegate implementation, to override the default. */
keyboardDelegate?: KeyboardDelegate
keyboardDelegate?: KeyboardDelegate<T>
}

/**
Expand Down Expand Up @@ -87,7 +87,7 @@ export function useSearchAutocomplete<T>(props: AriaSearchAutocompleteOptions<T>
value: state.inputValue,
setValue: state.setInputValue
}, inputRef);


let {listBoxProps, labelProps, inputProps: comboBoxInputProps} = useComboBox(
{
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-aria/combobox/src/useComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface AriaComboBoxOptions<T> extends Omit<AriaComboBoxProps<T>, 'chil
/** The ref for the optional list box popup trigger button. */
buttonRef?: RefObject<Element>,
/** An optional keyboard delegate implementation, to override the default. */
keyboardDelegate?: KeyboardDelegate
keyboardDelegate?: KeyboardDelegate<T>
}

export interface ComboBoxAria<T> {
Expand Down
4 changes: 3 additions & 1 deletion packages/@react-aria/dnd/intl/ar-AE.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@
"endDragVirtual": "السحب. انقر لإلغاء السحب.",
"insertAfter": "أدخل بعد {itemText}",
"insertBefore": "أدخل قبل {itemText}",
"insertBetween": "أدخل بين {beforeItemText} و {afterItemText}"
"insertBetween": "أدخل بين {beforeItemText} و {afterItemText}",
"insertBeforeSection": "Insert after {itemText} in {sectionText}",
"insertAfterSection": "Insert before {itemText} in {sectionText}"
}
4 changes: 3 additions & 1 deletion packages/@react-aria/dnd/intl/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@
"dropOnItem": "Drop on {itemText}",
"insertBefore": "Insert before {itemText}",
"insertBetween": "Insert between {beforeItemText} and {afterItemText}",
"insertAfter": "Insert after {itemText}"
"insertAfter": "Insert after {itemText}",
"insertBeforeSection": "Insert after {itemText} in {sectionText}",
"insertAfterSection": "Insert before {itemText} in {sectionText}"
}
59 changes: 47 additions & 12 deletions packages/@react-aria/dnd/src/useDropIndicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import * as DragManager from './DragManager';
import {DroppableCollectionState} from '@react-stately/dnd';
import {DropTarget} from '@react-types/shared';
import {DropTarget, KeyboardDelegate} from '@react-types/shared';
import {getDroppableCollectionId} from './utils';
import {HTMLAttributes, Key, RefObject} from 'react';
// @ts-ignore
Expand All @@ -23,7 +23,9 @@ import {useLocalizedStringFormatter} from '@react-aria/i18n';

export interface DropIndicatorProps {
/** The drop target that the drop indicator represents. */
target: DropTarget
target: DropTarget,
/** A delegate object that implements behavior for keyboard focus movement. */
keyboardDelegate?: KeyboardDelegate<unknown>
Comment on lines +27 to +28
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update to useDropIndicator api, see discussion here for background.

}

export interface DropIndicatorAria {
Expand All @@ -42,14 +44,16 @@ export interface DropIndicatorAria {
* Handles drop interactions for a target within a droppable collection.
*/
export function useDropIndicator(props: DropIndicatorProps, state: DroppableCollectionState, ref: RefObject<HTMLElement>): DropIndicatorAria {
let {target} = props;
let {target, keyboardDelegate} = props;
let {collection} = state;

let stringFormatter = useLocalizedStringFormatter(intlMessages);
let dragSession = DragManager.useDragSession();
let {dropProps} = useDroppableItem(props, state, ref);
let id = useId();
let getText = (key: Key) => collection.getTextValue?.(key) ?? collection.getItem(key)?.textValue;
let itemFilter = (item) => item.type === 'item' || item.type === 'section';
let getNode = (key: Key) => collection.getItem(key);

let label = '';
let labelledBy: string;
Expand All @@ -63,23 +67,54 @@ export function useDropIndicator(props: DropIndicatorProps, state: DroppableColl
} else {
let before: Key | null;
let after: Key | null;
if (collection.getFirstKey() === target.key && target.dropPosition === 'before') {
let keyGetter = keyboardDelegate ?? collection;

let targetNode = getNode(target.key);
let keyBefore = keyboardDelegate != null ? keyboardDelegate.getKeyAbove(target.key, itemFilter) : collection.getKeyBefore(target.key);
if (keyGetter.getFirstKey() === target.key && target.dropPosition === 'before' && getNode(targetNode.parentKey)?.type !== 'section') {
before = null;
} else {
before = target.dropPosition === 'before' ? collection.getKeyBefore(target.key) : target.key;
before = target.dropPosition === 'before' ? keyBefore : target.key;
}

if (collection.getLastKey() === target.key && target.dropPosition === 'after') {
after = null;
let keyAfter = keyboardDelegate != null ? keyboardDelegate.getKeyBelow(target.key, itemFilter) : collection.getKeyAfter(target.key);
if (keyGetter.getLastKey() === target.key && target.dropPosition === 'after') {
if (getNode(targetNode.parentKey)?.type === 'section') {
after = targetNode.parentKey;
} else {
after = null;
}
} else {
after = target.dropPosition === 'after' ? collection.getKeyAfter(target.key) : target.key;
if (target.dropPosition === 'before') {
after = target.key;
} else {
if (getNode(keyAfter)?.type === 'section') {
after = targetNode.parentKey;
} else {
after = keyAfter;
}
}
}

if (before && after) {
label = stringFormatter.format('insertBetween', {
beforeItemText: getText(before),
afterItemText: getText(after)
});
let beforeNode = getNode(before);
let afterNode = getNode(after);
if (beforeNode.type === 'section') {
label = stringFormatter.format('insertAfterSection', {
itemText: getText(after),
sectionText: getText(before)
});
} else if (afterNode.type === 'section') {
label = stringFormatter.format('insertBeforeSection', {
itemText: getText(before),
sectionText: getText(after)
});
} else {
label = stringFormatter.format('insertBetween', {
beforeItemText: getText(before),
afterItemText: getText(after)
});
}
} else if (before) {
label = stringFormatter.format('insertAfter', {
itemText: getText(before)
Expand Down
90 changes: 63 additions & 27 deletions packages/@react-aria/dnd/src/useDroppableCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {useDrop} from './useDrop';

export interface DroppableCollectionOptions extends DroppableCollectionProps {
/** A delegate object that implements behavior for keyboard focus movement. */
keyboardDelegate: KeyboardDelegate,
keyboardDelegate: KeyboardDelegate<unknown>,
/** A delegate object that provides drop targets for pointer coordinates within the collection. */
dropTargetDelegate: DropTargetDelegate
}
Expand Down Expand Up @@ -74,6 +74,11 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
localState.props = props;
localState.state = state;

let itemFilter = useCallback((item) => {
let isEmptySection = item?.type === 'section' && [...item.childNodes].filter((child) => child.type === 'item').length === 0;
return item.type === 'item' || isEmptySection;
}, []);

let defaultOnDrop = useCallback(async (e: DroppableCollectionDropEvent) => {
let {
onInsert,
Expand Down Expand Up @@ -325,24 +330,30 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:

let {keyboardDelegate} = localState.props;
let nextKey = target.type === 'item'
? keyboardDelegate.getKeyBelow(target.key)
: keyboardDelegate.getFirstKey();
let dropPosition: DropPosition = 'before';
? keyboardDelegate.getKeyBelow(target.key, itemFilter)
: keyboardDelegate.getFirstKey(undefined, undefined, itemFilter);
let targetItem = target.type === 'item' ? localState.state.collection.getItem(target.key) : undefined;
let nextItem = nextKey != null ? localState.state.collection.getItem(nextKey) : undefined;
let dropPosition: DropPosition = nextItem && nextItem.type === 'section' ? 'on' : 'before';

if (target.type === 'item') {
if (target?.type === 'item' && targetItem?.type !== 'section') {
let positionIndex = DROP_POSITIONS.indexOf(target.dropPosition);
let nextDropPosition = DROP_POSITIONS[positionIndex + 1];
if (positionIndex < DROP_POSITIONS.length - 1 && !(nextDropPosition === 'after' && nextKey != null)) {
if (
targetItem?.type === 'item' &&
(positionIndex < DROP_POSITIONS.length - 1 && !(nextDropPosition === 'after' && nextKey != null)) ||
(nextDropPosition === 'after' && nextKey != null && targetItem.parentKey !== nextItem.parentKey)
) {
return {
type: 'item',
key: target.key,
dropPosition: nextDropPosition
};
}

// If the last drop position was 'after', then 'before' on the next key is equivalent.
// Switch to 'on' instead.
if (target.dropPosition === 'after') {
// If the last drop position was 'after', then 'before' on the next key is equivalent if they have the same parent.
// Switch to 'on' instead. Do the same if the next key is a section as well.
if (target.dropPosition === 'after' && (targetItem?.parentKey === nextItem?.parentKey || nextItem?.type === 'section')) {
dropPosition = 'on';
}
}
Expand All @@ -367,25 +378,30 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
let getPreviousTarget = (target: DropTarget, wrap = true): DropTarget => {
let {keyboardDelegate} = localState.props;
let nextKey = target?.type === 'item'
? keyboardDelegate.getKeyAbove(target.key)
: keyboardDelegate.getLastKey();
let dropPosition: DropPosition = !target || target.type === 'root' ? 'after' : 'on';
? keyboardDelegate.getKeyAbove(target.key, itemFilter)
: keyboardDelegate.getLastKey(undefined, undefined, itemFilter);
let targetItem = target?.type === 'item' ? localState.state.collection.getItem(target.key) : undefined;
let nextItem = nextKey != null ? localState.state.collection.getItem(nextKey) : undefined;
let dropPosition: DropPosition = (!target || target.type === 'root') && nextItem.type !== 'section' ? 'after' : 'on';

if (target?.type === 'item') {
if (target?.type === 'item' && targetItem?.type !== 'section') {
let positionIndex = DROP_POSITIONS.indexOf(target.dropPosition);
let nextDropPosition = DROP_POSITIONS[positionIndex - 1];
if (positionIndex > 0 && nextDropPosition !== 'after') {
if (targetItem?.type === 'item' && positionIndex > 0 && nextDropPosition !== 'after') {
return {
type: 'item',
key: target.key,
dropPosition: nextDropPosition
};
}

// If the last drop position was 'before', then 'after' on the previous key is equivalent.
// Switch to 'on' instead.
if (target.dropPosition === 'before') {
// If the last drop position was 'before', then 'after' on the previous key is equivalent if they have the same parent.
// Switch to 'on' instead. Do the same if the next key is a section as well.
// If we are changing sections or moving from an empty section to a row then the dropPosition is after
if (target.dropPosition === 'before' && (targetItem?.parentKey === nextItem?.parentKey || nextItem?.type === 'section')) {
dropPosition = 'on';
} else if ((target.dropPosition === 'before' || targetItem.type === 'section') && nextItem && targetItem.parentKey !== nextItem.parentKey) {
dropPosition = 'after';
}
}

Expand Down Expand Up @@ -471,6 +487,13 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
let item = localState.state.collection.getItem(key);
if (item?.type === 'cell') {
key = item.parentKey;
item = localState.state.collection.getItem(key);
}

if (item != null && !itemFilter(item)) {
// If the previously focused item in the droppable collection isn't an item or a section (e.g. table column header)
// then set key to null so we start from root
key = null;
}

// If the focused item is also selected, the default drop target is after the last selected item.
Expand Down Expand Up @@ -577,22 +600,25 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
let nextKey = keyboardDelegate.getKeyPageBelow(
target.type === 'item'
? target.key
: keyboardDelegate.getFirstKey()
: keyboardDelegate.getFirstKey(undefined, undefined, itemFilter),
itemFilter
);

// Prioritize the same drop position that we started on, even if the next key is less than a whole page down
let dropPosition = target.type === 'item' ? target.dropPosition : 'after';

// If there is no next key, or we are starting on the last key, jump to the last possible position.
if (nextKey == null || (target.type === 'item' && target.key === keyboardDelegate.getLastKey())) {
nextKey = keyboardDelegate.getLastKey();
if (nextKey == null || (target.type === 'item' && target.key === keyboardDelegate.getLastKey(undefined, undefined, itemFilter))) {
nextKey = keyboardDelegate.getLastKey(undefined, undefined, itemFilter);
dropPosition = 'after';

}

target = {
type: 'item',
key: nextKey,
dropPosition
};

// If the target does not accept the drop, find the next valid target.
// If no next valid target, find the previous valid target.
let {draggingCollectionRef, draggingKeys} = globalDndState;
Expand All @@ -604,7 +630,12 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
}
}

localState.state.setTarget(target ?? localState.state.target);
let finalTarget = target ?? localState.state.target;
if (finalTarget.type === 'item' && localState.state.collection.getItem(finalTarget.key).type === 'section') {
finalTarget.dropPosition = 'on';
}

localState.state.setTarget(finalTarget);
}
break;
}
Expand All @@ -618,15 +649,15 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
target = nextValidTarget(null, types, drag.allowedDropOperations, getPreviousTarget);
} else if (target.type === 'item') {
// If at the top already, switch to the root. Otherwise navigate a page up.
if (target.key === keyboardDelegate.getFirstKey()) {
if (target.key === keyboardDelegate.getFirstKey(undefined, undefined, itemFilter)) {
target = {
type: 'root'
};
} else {
let nextKey = keyboardDelegate.getKeyPageAbove(target.key);
let nextKey = keyboardDelegate.getKeyPageAbove(target.key, itemFilter);
let dropPosition = target.dropPosition;
if (nextKey == null) {
nextKey = keyboardDelegate.getFirstKey();
nextKey = keyboardDelegate.getFirstKey(undefined, undefined, itemFilter);
dropPosition = 'before';
}

Expand All @@ -648,13 +679,18 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
}
}

localState.state.setTarget(target ?? localState.state.target);
let finalTarget = target ?? localState.state.target;
if (finalTarget.type === 'item' && localState.state.collection.getItem(finalTarget.key).type === 'section') {
finalTarget.dropPosition = 'on';
}

localState.state.setTarget(finalTarget);
break;
}
}
}
});
}, [localState, ref, onDrop]);
}, [localState, ref, onDrop, itemFilter]);

let id = useId();
droppableCollectionMap.set(state, {id, ref});
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-aria/grid/intl/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"selectedCount": "{count, plural, =0 {No items selected} one {# item selected} other {# items selected}}.",
"selectedAll": "All items selected.",
"selectedItem": "{item} selected.",
"longPressToSelect": "Long press to enter selection mode."
"longPressToSelect": "Long press to enter selection mode.",
"sectionAnnouncement": "Entered section {sectionTitle}, with {sectionSize, plural, one {# row} other {# rows}}."
}
Loading