Skip to content

Commit

Permalink
♻️ refactor: 初步完成组件重构
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Feb 2, 2022
1 parent f2f0b80 commit c0c170c
Show file tree
Hide file tree
Showing 19 changed files with 425 additions and 97 deletions.
63 changes: 63 additions & 0 deletions packages/sortable-list/src/DraggingOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import { DragOverlay } from '@dnd-kit/core';
import { Item } from './components';
import type { FC } from 'react';

import type { SortableItem, SortableProps } from './types';

interface DraggingOverlayProps
extends Pick<
SortableProps,
| 'adjustScale'
| 'dropAnimation'
| 'renderItem'
| 'handle'
| 'wrapperStyle'
| 'getItemStyles'
> {
dragging: boolean;
item: SortableItem;
activeIndex: number;
activeId: string;
}

const DraggingOverlay: FC<DraggingOverlayProps> = ({
dragging,
dropAnimation,
adjustScale,
item,
renderItem,
handle,
getItemStyles,
wrapperStyle,
activeIndex,
activeId,
}) => {
return (
<DragOverlay adjustScale={adjustScale} dropAnimation={dropAnimation}>
{dragging ? (
<Item
value={item.id}
handle={handle}
renderItem={renderItem}
wrapperStyle={wrapperStyle({
index: activeIndex,
isDragging: true,
id: item.id,
})}
style={getItemStyles({
id: item.id,
index: activeIndex,
isSorting: activeId !== null,
isDragging: true,
overIndex: -1,
isDragOverlay: true,
})}
dragOverlay
/>
) : null}
</DragOverlay>
);
};

export default DraggingOverlay;
2 changes: 0 additions & 2 deletions packages/sortable-list/src/Item/components/Action/index.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/sortable-list/src/Item/components/Handle/index.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/sortable-list/src/Item/index.ts

This file was deleted.

149 changes: 65 additions & 84 deletions packages/sortable-list/src/Sortable.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { FC } from 'react';
import React, { useCallback, useState } from 'react';
import React from 'react';
import { createPortal } from 'react-dom';

import {
closestCenter,
DragOverlay,
DndContext,
KeyboardSensor,
MouseSensor,
Expand All @@ -14,16 +13,20 @@ import {
} from '@dnd-kit/core';

import {
arrayMove,
SortableContext,
sortableKeyboardCoordinates,
} from '@dnd-kit/sortable';
import useMergeState from 'use-merge-value';

import { Item } from './Item';
import { Wrapper } from './Wrapper';
import { Wrapper } from './components';

import SortableItem from './SortableItem';
import type { SortableItemList, SortableProps } from './types';
import DraggingOverlay from './DraggingOverlay';

import type { SortableProps } from './types';

import { useSortableList } from './hooks/useSortableList';
import { useActiveItem } from './hooks/useActiveItem';
import { getIndexOfActiveItem } from './utils';

export const Sortable: FC<SortableProps> = ({
activationConstraint,
Expand All @@ -44,20 +47,12 @@ export const Sortable: FC<SortableProps> = ({
modifiers,
removable,
renderItem,
reorderItems = arrayMove,
strategy,
style,
useDragOverlay = true,
wrapperStyle = () => ({}),
direction,
}) => {
const [items, setItems] = useMergeState<SortableItemList>([], {
value: controlledItems,
defaultValue: defaultItems,
onChange: onItemChange,
});

const [activeId, setActiveId] = useState<string | null>(null);

const sensors = useSensors(
useSensor(MouseSensor, {
activationConstraint,
Expand All @@ -70,96 +65,82 @@ export const Sortable: FC<SortableProps> = ({
}),
);

const getIndex = items.indexOf.bind(items);
const activeIndex = activeId ? getIndex(activeId) : -1;
const { items, dispatchSortable } = useSortableList({
value: controlledItems,
defaultValue: defaultItems,
onChange: onItemChange,
});

const handleRemove = useCallback(
(id: string) => {
if (!removable) return;
const { deactivateItem, activateItem, activeId, isDragging } =
useActiveItem();

const newItem = items.filter((item) => item.id !== id);
setItems(newItem);
},
[removable, items],
);
const activeIndex = getIndexOfActiveItem(items, activeId);

const handleRemove = (id: string) => {
if (!removable) return;

dispatchSortable({ type: 'removeItem', id });
};

return (
<DndContext
sensors={sensors}
collisionDetection={collisionDetection}
onDragStart={({ active }) => {
if (!active) {
return;
}
if (!active) return;

setActiveId(active.id);
activateItem(active.id);
}}
onDragEnd={({ over }) => {
setActiveId(null);

if (over) {
const overIndex = getIndex(over.id);
if (activeIndex !== overIndex) {
const newItems = reorderItems(items, activeIndex, overIndex);
const endIndex = getIndexOfActiveItem(items, over.id);

setItems(newItems);
}
dispatchSortable({
type: 'reorder',
startIndex: activeIndex,
endIndex,
});
}
deactivateItem();
}}
onDragCancel={() => setActiveId(null)}
onDragCancel={() => deactivateItem()}
measuring={measuring}
modifiers={modifiers}
>
<Wrapper style={style}>
<SortableContext items={items} strategy={strategy}>
<Container>
{items.map((value, index) => (
<SortableItem
key={value.id}
id={value.id}
handle={handle}
index={index}
style={getItemStyles}
wrapperStyle={wrapperStyle}
disabled={isDisabled(value.id)}
renderItem={renderItem}
onRemove={handleRemove}
animateLayoutChanges={animateLayoutChanges}
useDragOverlay={useDragOverlay}
getNewIndex={getNewIndex}
/>
))}
</Container>
</SortableContext>
</Wrapper>
<SortableContext items={items} strategy={strategy}>
<Container style={style}>
{items.map((value, index) => (
<SortableItem
key={value.id}
id={value.id}
handle={handle}
index={index}
style={getItemStyles}
wrapperStyle={wrapperStyle}
disabled={isDisabled(value.id)}
renderItem={renderItem}
onRemove={handleRemove}
animateLayoutChanges={animateLayoutChanges}
useDragOverlay={useDragOverlay}
getNewIndex={getNewIndex}
/>
))}
</Container>
</SortableContext>
{useDragOverlay
? createPortal(
<DragOverlay
<DraggingOverlay
adjustScale={adjustScale}
dropAnimation={dropAnimation}
>
{activeId ? (
<Item
value={items[activeIndex]}
handle={handle}
renderItem={renderItem}
wrapperStyle={wrapperStyle({
index: activeIndex,
isDragging: true,
id: items[activeIndex].id,
})}
style={getItemStyles({
id: items[activeIndex].id,
index: activeIndex,
isSorting: activeId !== null,
isDragging: true,
overIndex: -1,
isDragOverlay: true,
})}
dragOverlay
/>
) : null}
</DragOverlay>,
dragging={isDragging}
activeId={activeId}
activeIndex={activeIndex}
item={items[activeIndex]}
getItemStyles={getItemStyles}
wrapperStyle={wrapperStyle}
handle={handle}
renderItem={renderItem}
/>,
document.body,
)
: null}
Expand Down
2 changes: 1 addition & 1 deletion packages/sortable-list/src/SortableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import type { AnimateLayoutChanges, NewIndexGetter } from '@dnd-kit/sortable';
import { useSortable } from '@dnd-kit/sortable';

import { Item } from './Item';
import { Item } from './components';

interface SortableItemProps {
animateLayoutChanges?: AnimateLayoutChanges;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
$focused-outline-color: #4c9ffe;
@focused-outline-color: #4c9ffe;

.Action {
display: flex;
Expand Down Expand Up @@ -45,6 +45,6 @@ $focused-outline-color: #4c9ffe;
&:focus-visible {
outline: none;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0),
0 0px 0px 2px $focused-outline-color;
0 0px 0px 2px @focused-outline-color;
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import classNames from 'classnames';
import type { DraggableSyntheticListeners } from '@dnd-kit/core';
import type { Transform } from '@dnd-kit/utilities';

import { Handle, Remove } from './components';
import { Handle } from '../Handle';
import { Remove } from '../Remove';

import styles from './index.less';

Expand Down Expand Up @@ -76,6 +77,7 @@ export const Item = React.memo(
};
}, [dragOverlay]);

// @ts-ignore
return renderItem ? (
renderItem({
dragOverlay: Boolean(dragOverlay),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import {Action, ActionProps} from '../Action';
import type { ActionProps } from '../Action';
import { Action } from '../Action';

export function Remove(props: ActionProps) {
return (
Expand Down
17 changes: 17 additions & 0 deletions packages/sortable-list/src/hooks/useActiveItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useCallback, useState } from 'react';

export const useActiveItem = () => {
const [activeId, setActiveId] = useState<string>(null);

const activateItem = useCallback((id: string) => {
setActiveId(id);
}, []);

const deactivateItem = useCallback(() => {
setActiveId(null);
}, []);

const isDragging = activeId !== null;

return { isDragging, activeId, activateItem, deactivateItem };
};
Loading

0 comments on commit c0c170c

Please sign in to comment.