Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
theomessin committed May 22, 2023
2 parents dd14039 + 1d3e034 commit aa52464
Show file tree
Hide file tree
Showing 34 changed files with 622 additions and 319 deletions.
2 changes: 0 additions & 2 deletions packages/@adobe/spectrum-css-temp/components/tags/skin.css
Expand Up @@ -62,7 +62,6 @@ governing permissions and limitations under the License.
color: var(--spectrum-tag-removable-button-icon-color-key-focus);
}
&:hover {
background-color: var(--spectrum-tag-removable-button-background-color-hover);
color: var(--spectrum-tag-removable-button-icon-color-hover);
}
}
Expand All @@ -81,7 +80,6 @@ governing permissions and limitations under the License.
--spectrum-tag-border-color-hover: Highlight;
--spectrum-tag-border-color-key-focus: Highlight;
--spectrum-tag-removable-border-color-key-focus: Highlight;
--spectrum-tag-removable-button-background-color-hover: ButtonFace;
--spectrum-tag-removable-button-background-color-key-focus: ButtonFace;
--spectrum-tag-removable-button-icon-color-hover: Highlight;
--spectrum-tag-removable-button-icon-color-key-focus: Highlight;
Expand Down
6 changes: 3 additions & 3 deletions packages/@react-aria/dnd/test/useDroppableCollection.test.js
Expand Up @@ -575,7 +575,7 @@ describe('useDroppableCollection', () => {
}
let tree = render(<>
<Draggable />
<DroppableGridExample items={items} onDropEnter={onDropEnter} onDropExit={onDragExit} onDrop={onDrop} />
<DroppableGridExample style={{overflow: 'auto'}} items={items} onDropEnter={onDropEnter} onDropExit={onDragExit} onDrop={onDrop} />
</>);

let draggable = tree.getByText('Drag me');
Expand Down Expand Up @@ -659,7 +659,7 @@ describe('useDroppableCollection', () => {
let getDropOperation = (target) => target.type === 'item' && target.dropPosition === 'on' && target.key !== '4' && target.key !== '1' ? 'move' : 'cancel';
let tree = render(<>
<Draggable />
<DroppableGridExample items={items} getDropOperation={getDropOperation} onDropEnter={onDropEnter} onDropExit={onDragExit} onDrop={onDrop} />
<DroppableGridExample style={{overflow: 'auto'}} items={items} getDropOperation={getDropOperation} onDropEnter={onDropEnter} onDropExit={onDragExit} onDrop={onDrop} />
</>);

let draggable = tree.getByText('Drag me');
Expand Down Expand Up @@ -742,7 +742,7 @@ describe('useDroppableCollection', () => {
let getDropOperation = (target) => target.type === 'item' && target.dropPosition === 'on' && target.key !== '0' && target.key !== '5' ? 'move' : 'cancel';
let tree = render(<>
<Draggable />
<DroppableGridExample items={items} getDropOperation={getDropOperation} onDropEnter={onDropEnter} onDropExit={onDragExit} onDrop={onDrop} />
<DroppableGridExample style={{overflow: 'auto'}} items={items} getDropOperation={getDropOperation} onDropEnter={onDropEnter} onDropExit={onDragExit} onDrop={onDrop} />
</>);

let draggable = tree.getByText('Drag me');
Expand Down
10 changes: 8 additions & 2 deletions packages/@react-aria/gridlist/src/useGridList.ts
Expand Up @@ -46,7 +46,12 @@ export interface AriaGridListOptions<T> extends Omit<AriaGridListProps<T>, 'chil
* An optional keyboard delegate implementation for type to select,
* to override the default.
*/
keyboardDelegate?: KeyboardDelegate
keyboardDelegate?: KeyboardDelegate,
/**
* Whether focus should wrap around when the end/start is reached.
* @default false
*/
shouldFocusWrap?: boolean
}

export interface GridListAria {
Expand Down Expand Up @@ -79,7 +84,8 @@ export function useGridList<T>(props: AriaGridListOptions<T>, state: ListState<T
ref,
keyboardDelegate: keyboardDelegate,
isVirtualized,
selectOnFocus: state.selectionManager.selectionBehavior === 'replace'
selectOnFocus: state.selectionManager.selectionBehavior === 'replace',
shouldFocusWrap: props.shouldFocusWrap
});

let id = useId(props.id);
Expand Down
110 changes: 93 additions & 17 deletions packages/@react-aria/selection/src/ListKeyboardDelegate.ts
Expand Up @@ -10,20 +10,42 @@
* governing permissions and limitations under the License.
*/

import {Collection, KeyboardDelegate, Node} from '@react-types/shared';
import {Collection, Direction, KeyboardDelegate, Node, Orientation} from '@react-types/shared';
import {isScrollable} from '@react-aria/utils';
import {Key, RefObject} from 'react';

interface ListKeyboardDelegateOptions<T> {
collection: Collection<Node<T>>,
ref: RefObject<HTMLElement>,
orientation?: Orientation,
direction?: Direction,
disabledKeys?: Set<Key>
}

export class ListKeyboardDelegate<T> implements KeyboardDelegate {
private collection: Collection<Node<T>>;
private disabledKeys: Set<Key>;
private ref: RefObject<HTMLElement>;
private collator: Intl.Collator;

constructor(collection: Collection<Node<T>>, disabledKeys: Set<Key>, ref: RefObject<HTMLElement>, collator?: Intl.Collator) {
this.collection = collection;
this.disabledKeys = disabledKeys;
this.ref = ref;
this.collator = collator;
private orientation?: Orientation;
private direction?: Direction;

constructor(collection: Collection<Node<T>>, disabledKeys: Set<Key>, ref: RefObject<HTMLElement>, collator?: Intl.Collator);
constructor(options: ListKeyboardDelegateOptions<T>);
constructor(...args: any[]) {
if (args.length === 1) {
let opts = args[0] as ListKeyboardDelegateOptions<T>;
this.collection = opts.collection;
this.ref = opts.ref;
this.disabledKeys = opts.disabledKeys || new Set();
this.orientation = opts.orientation;
this.direction = opts.direction;
} else {
this.collection = args[0];
this.disabledKeys = args[1];
this.ref = args[2];
this.collator = args[3];
}
}

getKeyBelow(key: Key) {
Expand Down Expand Up @@ -54,6 +76,22 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
return null;
}

getKeyRightOf(key: Key) {
if (this.orientation === 'horizontal') {
return this.direction === 'rtl' ? this.getKeyAbove(key) : this.getKeyBelow(key);
}

return null;
}

getKeyLeftOf(key: Key) {
if (this.orientation === 'horizontal') {
return this.direction === 'rtl' ? this.getKeyBelow(key) : this.getKeyAbove(key);
}

return null;
}

getFirstKey() {
let key = this.collection.getFirstKey();
while (key != null) {
Expand Down Expand Up @@ -93,14 +131,33 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
return null;
}

let pageY = Math.max(0, item.offsetTop + item.offsetHeight - menu.offsetHeight);
if (!isScrollable(menu)) {
return this.getFirstKey();
}

let containerRect = menu.getBoundingClientRect();
let itemRect = item.getBoundingClientRect();
if (this.orientation === 'horizontal') {
let containerX = containerRect.x - menu.scrollLeft;
let pageX = Math.max(0, (itemRect.x - containerX) + itemRect.width - containerRect.width);

while (item && item.offsetTop > pageY) {
key = this.getKeyAbove(key);
item = key == null ? null : this.getItem(key);
while (item && (itemRect.x - containerX) > pageX) {
key = this.getKeyAbove(key);
item = key == null ? null : this.getItem(key);
itemRect = item?.getBoundingClientRect();
}
} else {
let containerY = containerRect.y - menu.scrollTop;
let pageY = Math.max(0, (itemRect.y - containerY) + itemRect.height - containerRect.height);

while (item && (itemRect.y - containerY) > pageY) {
key = this.getKeyAbove(key);
item = key == null ? null : this.getItem(key);
itemRect = item?.getBoundingClientRect();
}
}

return key;
return key ?? this.getFirstKey();
}

getKeyPageBelow(key: Key) {
Expand All @@ -110,14 +167,33 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
return null;
}

let pageY = Math.min(menu.scrollHeight, item.offsetTop - item.offsetHeight + menu.offsetHeight);
if (!isScrollable(menu)) {
return this.getLastKey();
}

while (item && item.offsetTop < pageY) {
key = this.getKeyBelow(key);
item = key == null ? null : this.getItem(key);
let containerRect = menu.getBoundingClientRect();
let itemRect = item.getBoundingClientRect();
if (this.orientation === 'horizontal') {
let containerX = containerRect.x - menu.scrollLeft;
let pageX = Math.min(menu.scrollWidth, (itemRect.x - containerX) - itemRect.width + containerRect.width);

while (item && (itemRect.x - containerX) < pageX) {
key = this.getKeyBelow(key);
item = key == null ? null : this.getItem(key);
itemRect = item?.getBoundingClientRect();
}
} else {
let containerY = containerRect.y - menu.scrollTop;
let pageY = Math.min(menu.scrollHeight, (itemRect.y - containerY) - itemRect.height + containerRect.height);

while (item && (itemRect.y - containerY) < pageY) {
key = this.getKeyBelow(key);
item = key == null ? null : this.getItem(key);
itemRect = item?.getBoundingClientRect();
}
}

return key;
return key ?? this.getLastKey();
}

getKeyForSearch(search: string, fromKey?: Key) {
Expand Down
6 changes: 6 additions & 0 deletions packages/@react-aria/selection/src/useSelectableCollection.ts
Expand Up @@ -165,6 +165,9 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
if (delegate.getKeyLeftOf) {
e.preventDefault();
let nextKey = delegate.getKeyLeftOf(manager.focusedKey);
if (nextKey == null && shouldFocusWrap) {
nextKey = direction === 'rtl' ? delegate.getFirstKey?.(manager.focusedKey) : delegate.getLastKey?.(manager.focusedKey);
}
navigateToKey(nextKey, direction === 'rtl' ? 'first' : 'last');
}
break;
Expand All @@ -173,6 +176,9 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
if (delegate.getKeyRightOf) {
e.preventDefault();
let nextKey = delegate.getKeyRightOf(manager.focusedKey);
if (nextKey == null && shouldFocusWrap) {
nextKey = direction === 'rtl' ? delegate.getLastKey?.(manager.focusedKey) : delegate.getFirstKey?.(manager.focusedKey);
}
navigateToKey(nextKey, direction === 'rtl' ? 'last' : 'first');
}
break;
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-aria/tag/package.json
Expand Up @@ -26,11 +26,11 @@
"@react-aria/i18n": "^3.7.1",
"@react-aria/interactions": "^3.15.0",
"@react-aria/label": "^3.5.1",
"@react-aria/selection": "^3.14.0",
"@react-aria/utils": "^3.16.0",
"@react-stately/list": "^3.8.0",
"@react-types/button": "^3.7.2",
"@react-types/shared": "^3.18.0",
"@react-types/tag": "3.0.0-rc.0",
"@swc/helpers": "^0.4.14"
},
"peerDependencies": {
Expand Down
79 changes: 0 additions & 79 deletions packages/@react-aria/tag/src/TagKeyboardDelegate.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/@react-aria/tag/src/index.ts
Expand Up @@ -10,10 +10,8 @@
* governing permissions and limitations under the License.
*/

export {TagKeyboardDelegate} from './TagKeyboardDelegate';
export {useTag} from './useTag';
export {useTagGroup} from './useTagGroup';

export type {TagProps} from '@react-types/tag';
export type {TagGroupAria, AriaTagGroupProps} from './useTagGroup';
export type {AriaTagProps, TagAria} from './useTag';

0 comments on commit aa52464

Please sign in to comment.