From 71e3212fa7834bf1af69516a1c57bc98706503a3 Mon Sep 17 00:00:00 2001 From: Herman Wikner Date: Tue, 20 Dec 2022 15:26:07 +0100 Subject: [PATCH] fix(core): add transition effect when sorting array of primitives --- .../ArrayOfPrimitivesInput.tsx | 39 ++++++++++++++++++- .../core/form/inputs/arrays/common/list.tsx | 26 ++++++++++--- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/packages/sanity/src/core/form/inputs/arrays/ArrayOfPrimitivesInput/ArrayOfPrimitivesInput.tsx b/packages/sanity/src/core/form/inputs/arrays/ArrayOfPrimitivesInput/ArrayOfPrimitivesInput.tsx index a66dd35d583..3be7f1af51f 100644 --- a/packages/sanity/src/core/form/inputs/arrays/ArrayOfPrimitivesInput/ArrayOfPrimitivesInput.tsx +++ b/packages/sanity/src/core/form/inputs/arrays/ArrayOfPrimitivesInput/ArrayOfPrimitivesInput.tsx @@ -14,11 +14,25 @@ import {nearestIndexOf} from './utils/nearestIndex' import {ItemRow} from './ItemRow' import {ArrayOfPrimitivesFunctions} from './ArrayOfPrimitivesFunctions' +interface State { + disableTransition: boolean +} // Note: this should be a class component until React provides support for a hook version of getSnapshotBeforeUpdate /** @beta */ -export class ArrayOfPrimitivesInput extends React.PureComponent { +export class ArrayOfPrimitivesInput extends React.PureComponent< + ArrayOfPrimitivesInputProps, + State +> { _element: HTMLElement | null = null + constructor(props: ArrayOfPrimitivesInputProps) { + super(props) + + this.state = { + disableTransition: false, + } + } + handleAppend = (itemValue: PrimitiveValue) => { const {value = [], onIndexFocus, onItemAppend} = this.props onItemAppend(itemValue) @@ -30,12 +44,26 @@ export class ArrayOfPrimitivesInput extends React.PureComponent { const {onIndexFocus, onMoveItem, value} = this.props + if (value) onMoveItem(event) onIndexFocus(event.toIndex) } + // Enable transition when the user starts dragging an item + handleItemMoveStart = () => { + this.setState({disableTransition: false}) + } + + // Disable transition when the user stops dragging an item. + // Note: there's an issue with the transition of items when the sorting is completed, so we disable the + // transition effect when the user stops dragging. + handleItemMoveEnd = () => { + this.setState({disableTransition: true}) + } + focus() { if (this._element) { this._element.focus() @@ -154,13 +182,20 @@ export class ArrayOfPrimitivesInput extends React.PureComponent m.id)} sortable={isSortable} gap={1} > {membersWithSortIds.map(({member, id}, index) => { return ( - + {member.kind === 'item' && ( [restrictToParentElementWithMargins({y: 4}), ...(axis ? [restrictToAxis(axis)] : [])], @@ -90,6 +92,7 @@ function SortableList(props: ListProps) { modifiers={modifiers} collisionDetection={closestCenter} onDragEnd={handleDragEnd} + onDragStart={onItemMoveStart} > {children} @@ -133,19 +136,32 @@ interface ListProps extends ComponentProps { axis?: Axis items: string[] onItemMove?: (event: {fromIndex: number; toIndex: number}) => void + onItemMoveStart?: () => void + onItemMoveEnd?: () => void children?: React.ReactNode } export function List(props: ListProps) { - const {onItemMove, sortable, ...rest} = props + const {onItemMove, onItemMoveEnd, onItemMoveStart, sortable, ...rest} = props // Note: this is here to make SortableList API compatible with onItemMove const handleSortEnd = useCallback( - (event: {fromIndex: number; toIndex: number}) => onItemMove?.(event), + (event: {fromIndex: number; toIndex: number}) => { + onItemMove?.(event) + }, [onItemMove] ) - return sortable ? : + return sortable ? ( + + ) : ( + + ) } interface ItemProps {