Skip to content

Commit 47a3fca

Browse files
committed
Merge branch 'main' of github.com:adobe/react-spectrum into multi-select
2 parents 5e158be + f821086 commit 47a3fca

File tree

5 files changed

+73
-11
lines changed

5 files changed

+73
-11
lines changed

packages/@react-stately/layout/src/GridLayout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export class GridLayout<T, O extends GridLayoutOptions = GridLayoutOptions> exte
126126
itemHeight = Math.max(minItemSize.height, Math.min(maxItemHeight, itemHeight));
127127

128128
// Compute the horizontal spacing, content height and horizontal margin
129-
let horizontalSpacing = Math.min(maxHorizontalSpace, Math.floor((visibleWidth - numColumns * itemWidth) / (numColumns + 1)));
129+
let horizontalSpacing = Math.min(Math.max(maxHorizontalSpace, minSpace.width), Math.floor((visibleWidth - numColumns * itemWidth) / (numColumns + 1)));
130130
this.gap = new Size(horizontalSpacing, minSpace.height);
131131
this.margin = Math.floor((visibleWidth - numColumns * itemWidth - horizontalSpacing * (numColumns + 1)) / 2);
132132

packages/@react-stately/layout/src/WaterfallLayout.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export interface WaterfallLayoutOptions {
2929
* @default 18 x 18
3030
*/
3131
minSpace?: Size,
32+
/**
33+
* The maximum allowed horizontal space between items.
34+
* @default Infinity
35+
*/
36+
maxHorizontalSpace?: number,
3237
/**
3338
* The maximum number of columns.
3439
* @default Infinity
@@ -55,6 +60,7 @@ const DEFAULT_OPTIONS = {
5560
minItemSize: new Size(200, 200),
5661
maxItemSize: new Size(Infinity, Infinity),
5762
minSpace: new Size(18, 18),
63+
maxSpace: Infinity,
5864
maxColumns: Infinity,
5965
dropIndicatorThickness: 2
6066
};
@@ -64,20 +70,23 @@ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions
6470
private layoutInfos: Map<Key, WaterfallLayoutInfo> = new Map();
6571
protected numColumns = 0;
6672
protected dropIndicatorThickness = 2;
73+
private margin: number = 0;
6774

6875
shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean {
6976
return newOptions.maxColumns !== oldOptions.maxColumns
7077
|| newOptions.dropIndicatorThickness !== oldOptions.dropIndicatorThickness
7178
|| (!(newOptions.minItemSize || DEFAULT_OPTIONS.minItemSize).equals(oldOptions.minItemSize || DEFAULT_OPTIONS.minItemSize))
7279
|| (!(newOptions.maxItemSize || DEFAULT_OPTIONS.maxItemSize).equals(oldOptions.maxItemSize || DEFAULT_OPTIONS.maxItemSize))
73-
|| (!(newOptions.minSpace || DEFAULT_OPTIONS.minSpace).equals(oldOptions.minSpace || DEFAULT_OPTIONS.minSpace));
80+
|| (!(newOptions.minSpace || DEFAULT_OPTIONS.minSpace).equals(oldOptions.minSpace || DEFAULT_OPTIONS.minSpace))
81+
|| (newOptions.maxHorizontalSpace !== oldOptions.maxHorizontalSpace);
7482
}
7583

7684
update(invalidationContext: InvalidationContext<O>): void {
7785
let {
7886
minItemSize = DEFAULT_OPTIONS.minItemSize,
7987
maxItemSize = DEFAULT_OPTIONS.maxItemSize,
8088
minSpace = DEFAULT_OPTIONS.minSpace,
89+
maxHorizontalSpace = DEFAULT_OPTIONS.maxSpace,
8190
maxColumns = DEFAULT_OPTIONS.maxColumns,
8291
dropIndicatorThickness = DEFAULT_OPTIONS.dropIndicatorThickness
8392
} = invalidationContext.layoutOptions || {};
@@ -107,8 +116,9 @@ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions
107116
let itemHeight = minItemSize.height + Math.floor((maxItemHeight - minItemSize.height) * t);
108117
itemHeight = Math.max(minItemSize.height, Math.min(maxItemHeight, itemHeight));
109118

110-
// Compute the horizontal spacing and content height
111-
let horizontalSpacing = Math.floor((visibleWidth - numColumns * itemWidth) / (numColumns + 1));
119+
// Compute the horizontal spacing, content height and horizontal margin
120+
let horizontalSpacing = Math.min(Math.max(maxHorizontalSpace, minSpace.width), Math.floor((visibleWidth - numColumns * itemWidth) / (numColumns + 1)));
121+
this.margin = Math.floor((visibleWidth - numColumns * itemWidth - horizontalSpacing * (numColumns + 1)) / 2);
112122

113123
// Setup an array of column heights
114124
let columnHeights = Array(numColumns).fill(minSpace.height);
@@ -126,7 +136,7 @@ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions
126136
// Preserve the previous column index so items don't jump around during resizing unless the number of columns changed.
127137
let prevColumn = numColumns === this.numColumns && oldLayoutInfo && oldLayoutInfo.rect.y < this.virtualizer!.visibleRect.maxY ? oldLayoutInfo.column : undefined;
128138
let column = prevColumn ?? columnHeights.reduce((minIndex, h, i) => h < columnHeights[minIndex] ? i : minIndex, 0);
129-
let x = horizontalSpacing + column * (itemWidth + horizontalSpacing);
139+
let x = horizontalSpacing + column * (itemWidth + horizontalSpacing) + this.margin;
130140
let y = columnHeights[column];
131141

132142
let rect = new Rect(x, y, itemWidth, height);

packages/react-aria-components/docs/Tree.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ function FileTree(props: TreeProps<FileType>) {
460460
return (
461461
<Tree
462462
aria-label="Files"
463-
defaultExpandedKeys={['1', '4']}
463+
defaultExpandedKeys={['1']}
464464
/*- begin highlight -*/
465465
items={items}
466466
/*- end highlight -*/
@@ -515,7 +515,7 @@ Multiple selection can be enabled by setting `selectionMode` to `multiple`.
515515

516516
```tsx example
517517
// Using the example above
518-
<FileTree selectionMode="multiple" defaultSelectedKeys={['2', '4']} defaultExpandedKeys={['1']} />
518+
<FileTree selectionMode="multiple" defaultSelectedKeys={['2', '4']} defaultExpandedKeys={['1', '2']} />
519519
```
520520

521521
### Disallow empty selection

packages/react-aria-components/stories/GridList.stories.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ export const VirtualizedGridList: StoryObj<typeof VirtualizedGridListRender> = {
302302
};
303303

304304
interface VirtualizedGridListGridProps {
305+
minItemSizeWidth?: number,
305306
maxItemSizeWidth?: number,
306307
maxColumns?: number,
307308
minHorizontalSpace?: number,
@@ -310,6 +311,7 @@ interface VirtualizedGridListGridProps {
310311

311312
export let VirtualizedGridListGrid: StoryFn<VirtualizedGridListGridProps> = (args) => {
312313
const {
314+
minItemSizeWidth = 40,
313315
maxItemSizeWidth = 65,
314316
maxColumns = Infinity,
315317
minHorizontalSpace = 0,
@@ -324,7 +326,7 @@ export let VirtualizedGridListGrid: StoryFn<VirtualizedGridListGridProps> = (arg
324326
<Virtualizer
325327
layout={GridLayout}
326328
layoutOptions={{
327-
minItemSize: new Size(40, 40),
329+
minItemSize: new Size(minItemSizeWidth, 40),
328330
maxItemSize: new Size(maxItemSizeWidth, 40),
329331
minSpace: new Size(minHorizontalSpace, 18),
330332
maxColumns,
@@ -339,12 +341,18 @@ export let VirtualizedGridListGrid: StoryFn<VirtualizedGridListGridProps> = (arg
339341

340342
VirtualizedGridListGrid.story = {
341343
args: {
344+
minItemSizeWidth: 40,
342345
maxItemSizeWidth: 65,
343346
maxColumns: undefined,
344347
minHorizontalSpace: 0,
345348
maxHorizontalSpace: undefined
346349
},
347350
argTypes: {
351+
minItemSizeWidth: {
352+
control: 'number',
353+
description: 'The minimum width of each item in the grid list',
354+
defaultValue: 40
355+
},
348356
maxItemSizeWidth: {
349357
control: 'number',
350358
description: 'Maximum width of each item in the grid list.',

packages/react-aria-components/stories/ListBox.stories.tsx

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ export const VirtualizedListBoxGrid: StoryObj<typeof VirtualizedListBoxGridExamp
514514

515515
let lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'.split(' ');
516516

517-
export function VirtualizedListBoxWaterfall({minSize = 80, maxSize = 100}: {minSize: number, maxSize: number}): JSX.Element {
517+
function VirtualizedListBoxWaterfallExample({minSize = 40, maxSize = 65, maxColumns = undefined, minSpace = undefined, maxSpace = undefined}: {minSize: number, maxSize: number, maxColumns?: number, minSpace?: number, maxSpace?: number}): JSX.Element {
518518
let items: {id: number, name: string}[] = [];
519519
for (let i = 0; i < 1000; i++) {
520520
let words = Math.max(2, Math.floor(Math.random() * 25));
@@ -527,8 +527,11 @@ export function VirtualizedListBoxWaterfall({minSize = 80, maxSize = 100}: {minS
527527
<Virtualizer
528528
layout={WaterfallLayout}
529529
layoutOptions={{
530-
minItemSize: new Size(minSize, minSize),
531-
maxItemSize: new Size(maxSize, maxSize)
530+
minItemSize: new Size(minSize, 40),
531+
maxItemSize: new Size(maxSize, 65),
532+
maxColumns,
533+
minSpace: new Size(minSpace, 18),
534+
maxHorizontalSpace: maxSpace
532535
}}>
533536
<ListBox
534537
className={styles.menu}
@@ -545,6 +548,47 @@ export function VirtualizedListBoxWaterfall({minSize = 80, maxSize = 100}: {minS
545548
);
546549
}
547550

551+
export const VirtualizedListBoxWaterfall: StoryObj<typeof VirtualizedListBoxWaterfallExample> = {
552+
render: (args) => {
553+
return <VirtualizedListBoxWaterfallExample {...args} />;
554+
},
555+
args: {
556+
minSize: 40,
557+
maxSize: 65,
558+
maxColumns: undefined,
559+
minSpace: undefined,
560+
maxSpace: undefined
561+
},
562+
argTypes: {
563+
minSize: {
564+
control: 'number',
565+
description: 'The minimum width of each item in the grid list',
566+
defaultValue: 40
567+
},
568+
maxSize: {
569+
control: 'number',
570+
description: 'Maximum width of each item in the grid list.',
571+
defaultValue: 65
572+
},
573+
maxColumns: {
574+
control: 'number',
575+
description: 'Maximum number of columns in the grid list.',
576+
defaultValue: undefined
577+
},
578+
minSpace: {
579+
control: 'number',
580+
description: 'Minimum horizontal space between grid items.',
581+
defaultValue: undefined
582+
},
583+
maxSpace: {
584+
control: 'number',
585+
description: 'Maximum horizontal space between grid items.',
586+
defaultValue: undefined
587+
}
588+
}
589+
};
590+
591+
548592
let renderEmptyState = ({isLoading}) => {
549593
return (
550594
<div style={{height: 30, width: '100%'}}>

0 commit comments

Comments
 (0)