adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
12.72k stars 1.09k forks source link

Render drop indicators with collection renderers and add GridLayout #6631

Closed devongovett closed 3 months ago

devongovett commented 3 months ago

Also fixes #6617.

This refactor makes collection renderers responsible for rendering the drop indicators between each item in a collection. That enables Virtualizer layouts to handle positioning them correctly, rather than being inside each item. This is implemented by passing a renderDropIndicator function to the CollectionRoot and CollectionBranch components from the collection component (e.g. ListBox/GridList). Each layout has a getDropTargetLayoutInfo method to retrieve the size and position of a drop indicator on demand. It is not included in the collection or returned as part of the visible layout infos.

There is also a refactor to Virtualizer to remove the renderWrapper function, which has been moved into the Virtualizer component rather than in stately. In RAC we handle this differently since children are rendered on demand (by CollectionBranch rather than eagerly.

Finally, I've added a new GridLayout that is a simplified version of the one from CardView but with fewer Spectrum-specific details. It also implements the new drag and drop methods to position drop indicators, including flipping from vertical to horizontal if only one column is shown in a narrow view.

rspbot commented 3 months ago

Build successful! 🎉

rspbot commented 3 months ago

Build successful! 🎉

rspbot commented 3 months ago

Build successful! 🎉

rspbot commented 3 months ago
## API Changes unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any', access: 'private' } unknown top level export { type: 'any', access: 'private' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'identifier', name: 'Column' } unknown top level export { type: 'identifier', name: 'Column' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } undefined already in set ### @react-aria/virtualizer #### useVirtualizer ```diff useVirtualizer { props: VirtualizerOptions - state: VirtualizerState + state: VirtualizerState ref: RefObject returnVal: undefined } ``` #### Virtualizer ```diff Virtualizer { children: (string, {}) => ReactNode collection: Collection<{}> focusedKey?: Key isLoading?: boolean layout: Layout<{}, O> layoutOptions?: O onLoadMore?: () => void - renderWrapper?: (ReusableView<{}, ReactNode> | null, ReusableView<{}, ReactNode>, Array>, (Array>) => Array) => ReactElement + renderWrapper?: RenderWrapper<{}, ReactNode> scrollDirection?: 'horizontal' | 'vertical' | 'both' sizeToFit?: 'width' | 'height' } ``` ----------------------------------- ### @react-stately/layout #### ListLayoutOptions ```diff ListLayoutOptions { + dropIndicatorThickness?: number estimatedHeadingHeight?: number estimatedRowHeight?: number headingHeight?: number rowHeight?: number ``` it changed: - ListLayout #### ListLayout changed by: - ListLayoutOptions ```diff ListLayout { constructor: (ListLayoutOptions) => void getContentSize: () => void getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget + getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo getLayoutInfo: (Key) => void getVisibleLayoutInfos: (Rect) => void updateItemSize: (Key, Size) => void validate: (InvalidationContext) => void ``` #### TableLayout ```diff TableLayout { constructor: (ListLayoutOptions) => void getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget + getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo getVisibleLayoutInfos: (Rect) => void validate: (InvalidationContext) => void } ``` #### GridLayoutOptions ```diff - +GridLayoutOptions { + dropIndicatorThickness?: number = 2 + maxColumns?: number = Infinity + maxItemSize?: Size = Infinity + minItemSize?: Size = 200 x 200 + minSpace?: Size = 18 x 18 +} ``` it changed: - GridLayout #### GridLayout changed by: - GridLayoutOptions ```diff - +GridLayout { + constructor: (GridLayoutOptions) => void + getContentSize: () => Size + getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget + getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo + getLayoutInfo: (Key) => LayoutInfo | null + getVisibleLayoutInfos: (Rect) => Array + validate: () => void +} ``` ----------------------------------- ### @react-stately/virtualizer #### VirtualizerState ```diff -VirtualizerState { - contentSize: Size - endScrolling: () => void - isScrolling: boolean - setVisibleRect: (Rect) => void - startScrolling: () => void - virtualizer: Virtualizer<{}, V, W> - visibleViews: Array -} + ``` it changed: - useVirtualizerState #### Layout ```diff Layout { getContentSize: () => Size + getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo getItemRect: (Key) => Rect getLayoutInfo: (Key) => LayoutInfo | null getVisibleLayoutInfos: (Rect) => Array getVisibleRect: () => Rect shouldInvalidate: (Rect, Rect) => boolean updateItemSize: (Key, Size) => boolean validate: (InvalidationContext) => void - virtualizer: Virtualizer<{}, any, any> + virtualizer: Virtualizer<{}, any> } ``` #### ReusableView changed by: - ReusableView ```diff ReusableView { children: Set> - constructor: (Virtualizer<{}, V, unknown>) => void + constructor: (Virtualizer<{}, V>) => void content: {} getReusableView: (string) => void key: Key layoutInfo: LayoutInfo | null parent: ReusableView<{}, V> | null prepareForReuse: () => void rendered: V reusableViews: Map>> reuseChild: (ReusableView<{}, V>) => void viewType: string - virtualizer: Virtualizer<{}, V, unknown> + virtualizer: Virtualizer<{}, V> } ``` it changed: - ReusableView #### useVirtualizerState changed by: - VirtualizerState ```diff -useVirtualizerState { - opts: VirtualizerProps - returnVal: undefined -} + ``` #### undefined ```diff - +VirtualizerState { + contentSize: Size + endScrolling: () => void + isScrolling: boolean + setVisibleRect: (Rect) => void + startScrolling: () => void + virtualizer: Virtualizer<{}, V> + visibleViews: Array> +} ``` #### undefined ```diff - +useVirtualizerState { + opts: VirtualizerProps + returnVal: undefined +} ``` -----------------------------------
devongovett commented 3 months ago

Merging to unblock merge conflicts in upcoming PR. Will fix bugs in subsequent PR.