Skip to content

Commit

Permalink
Merge pull request #110 from js-tool-pack/draggable-transition
Browse files Browse the repository at this point in the history
Draggable 新增动画功能
  • Loading branch information
mengxinssfd authored Jun 3, 2024
2 parents 5e5235f + 7df6414 commit 3535e56
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 15 deletions.
25 changes: 19 additions & 6 deletions packages/components/src/draggable/Draggable.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// import EnUS from './locale/en-US';
import type { DraggableProps, DraggableFC } from './draggable.types';
import { createElement, forwardRef, FC } from 'react';
// import { useLocale } from '~/config-provider/useLocale';
import type { RequiredPart } from '@tool-pack/types';
import { TransitionGroup } from '~/transition-group';
import { createElement, forwardRef } from 'react';
import { getClassNames } from '@tool-pack/basic';
import { useDraggableChildren } from './hooks';
import type { ReactElement, FC } from 'react';
import { getClasses } from '@pkg/shared';

export const cls = getClasses('draggable', ['ghost', 'item'], []);
Expand All @@ -18,18 +20,29 @@ export const _Draggable: FC<DraggableProps> = forwardRef<
DraggableProps
>((props, ref) => {
// const locale = useLocale('draggable', EnUS);
const { attrs = {}, tag } = props as RequiredPart<
DraggableProps,
keyof typeof defaultProps
>;
const {
transition,
attrs = {},
tag,
} = props as RequiredPart<DraggableProps, keyof typeof defaultProps>;
const children = useDraggableChildren(props);
const className = getClassNames(cls.root, attrs.className);

if (transition && children) {
const transitionProps = transition === true ? undefined : transition;
return (
<TransitionGroup {...transitionProps} className={className} tag={tag}>
{children as ReactElement[]}
</TransitionGroup>
);
}

if (tag === null) return children;
return createElement(
tag,
{
...attrs,
className: getClassNames(cls.root, attrs.className),
className,
ref,
},
children,
Expand Down
55 changes: 55 additions & 0 deletions packages/components/src/draggable/demo/transition-debug.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* title: transition debug
* debug: true
* description: 开启 transition 动画。
*/

import { ButtonGroup, Draggable, Button } from '@tool-pack/react-ui';
import styles from './transition.module.scss';
import React from 'react';

const App: React.FC = () => {
const [state, setState] = React.useState<{ name: string; id: number }[]>([
{ name: 'John', id: 1 },
{ name: 'Joao', id: 2 },
{ name: 'Jean', id: 3 },
{ name: 'Gerard', id: 4 },
]);
return (
<div className={styles['root']}>
<ButtonGroup>
<Button
onClick={() => {
const id = state.length + 1;
setState([...state, { name: 'anyone', id }]);
}}
type="primary"
>
添加
</Button>
<Button onClick={() => setState(state.slice(0, -1))} type="success">
删减
</Button>
</ButtonGroup>
<div className="main">
<Draggable onChange={setState} list={state} tag={null} transition>
{state.map((item, index) => (
<div className="draggable-item" key={item.id}>
<span>{index + 1}.</span> <span>{item.name}</span>{' '}
<span>{item.id}</span>
</div>
))}
</Draggable>
<div className="data">
[
{state.map((it) => (
<div key={it.id}>{JSON.stringify(it)}</div>
))}
]
</div>
</div>
</div>
);
};

export default App;
37 changes: 37 additions & 0 deletions packages/components/src/draggable/demo/transition.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.root {
:global {
.main {
display: flex;
margin-top: 1rem;
}
.t-draggable {
flex: 1;
}
.draggable-item {
padding: 0 0.5rem;
border: 1px solid #e6e6e6;
background: #fff1d7;
line-height: 32px;
}
.data {
flex: 1;
padding: 0 20px;
white-space: pre-wrap;
}
.t-group {
&-enter-active,
&-leave-active,
&-move-active {
transition: all 0.3s ease;
}
&-enter-from {
transform: translateY(-100%);
opacity: 0;
}
&-leave-to {
transform: translateY(100%);
opacity: 0;
}
}
}
}
54 changes: 54 additions & 0 deletions packages/components/src/draggable/demo/transition.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* title: transition
* description: 开启 transition 动画。
*/

import { ButtonGroup, Draggable, Button } from '@tool-pack/react-ui';
import styles from './transition.module.scss';
import React from 'react';

const App: React.FC = () => {
const [state, setState] = React.useState<{ name: string; id: number }[]>([
{ name: 'John', id: 1 },
{ name: 'Joao', id: 2 },
{ name: 'Jean', id: 3 },
{ name: 'Gerard', id: 4 },
]);
return (
<div className={styles['root']}>
<ButtonGroup>
<Button
onClick={() => {
const id = state.length + 1;
setState([...state, { name: 'anyone', id }]);
}}
type="primary"
>
添加
</Button>
<Button onClick={() => setState(state.slice(0, -1))} type="success">
删减
</Button>
</ButtonGroup>
<div className="main">
<Draggable onChange={setState} list={state} transition>
{state.map((item, index) => (
<div className="draggable-item" key={item.id}>
<span>{index + 1}.</span> <span>{item.name}</span>{' '}
<span>{item.id}</span>
</div>
))}
</Draggable>
<div className="data">
[
{state.map((it) => (
<div key={it.id}>{JSON.stringify(it)}</div>
))}
]
</div>
</div>
</div>
);
};

export default App;
2 changes: 2 additions & 0 deletions packages/components/src/draggable/draggable.types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { TransitionGroupProps } from '~/transition-group';
import type { PropsBase } from '@pkg/shared';
import type { ReactElement } from 'react';

export interface DraggableProps<T = unknown> extends PropsBase<HTMLDivElement> {
transition?: TransitionGroupProps | boolean;
tag?: keyof HTMLElementTagNameMap | null;
onChange?: (list: T[]) => void;
list: T[];
Expand Down
12 changes: 9 additions & 3 deletions packages/components/src/draggable/hooks/useDraggableChildren.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ import { cls } from '../Draggable';

export function useDraggableChildren({
children: outerChildren,
transition,
onChange,
list,
}: Pick<DraggableProps, 'children' | 'onChange' | 'list'>): ReactNode {
}: Pick<
DraggableProps,
'transition' | 'children' | 'onChange' | 'list'
>): ReactNode {
const forceUpdate = useForceUpdate();
const childrenRef = useFollowingRef(outerChildren, (v) =>
Children.toArray(v),
Expand Down Expand Up @@ -62,12 +66,14 @@ export function useDraggableChildren({
onChange?.(listRef.current.slice());
e.preventDefault();
},
onDragEnter: () => {
onDragEnterCapture(e: DragEvent) {
const target = e.target as HTMLElement;
const chosen = chosenRef.current;
if (
!chosen ||
chosen.overIndex === index ||
el.props.draggable === false
el.props.draggable === false ||
(transition && target.className.includes('move-active'))
)
return;

Expand Down
34 changes: 34 additions & 0 deletions packages/components/src/draggable/index.en-US.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
category: Components
title: Draggable
atomId: Draggable
demo:
cols: 2
group:
title: Common
---

Draggable 拖拽。

## 代码演示

<!-- prettier-ignore -->
<code src="./demo/basic.tsx"></code>
<code src="./demo/draggable.tsx"></code>
<code src="./demo/tag.tsx"></code>
<code src="./demo/transition.tsx"></code>
<code src="./demo/transition-debug.tsx"></code>

## API

Draggable 的属性说明如下:

| 属性 | 说明 | 类型 | 默认值 | 版本 |
| ---------- | ---------------- | --------------------------------------------------------- | ------ | ---- |
| list | 列表对应的数组 | any[] | -- | -- |
| onChange | 列表改动回调 | (list: T[]) => void | -- | -- |
| tag | 组件 html 根元素 | string \| null | 'div' | -- |
| transition | 动画效果 | boolean \| [TransitionGroupProps](./transition-group#api) | 'div' | -- |
| attrs | html 标签属性 | Partial\<React.HTMLAttributes\<HTMLDivElement>> | -- | -- |

其他说明。
15 changes: 9 additions & 6 deletions packages/components/src/draggable/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ Draggable 拖拽。
<code src="./demo/basic.tsx"></code>
<code src="./demo/draggable.tsx"></code>
<code src="./demo/tag.tsx"></code>
<code src="./demo/transition.tsx"></code>
<code src="./demo/transition-debug.tsx"></code>

## API

Draggable 的属性说明如下:

| 属性 | 说明 | 类型 | 默认值 | 版本 |
| -------- | ---------------- | ----------------------------------------------- | ------ | ---- |
| list | 列表对应的数组 | any[] | -- | -- |
| onChange | 列表改动回调 | (list: T[]) => void | -- | -- |
| tag | 组件 html 根元素 | string \| null | 'div' | -- |
| attrs | html 标签属性 | Partial\<React.HTMLAttributes\<HTMLDivElement>> | -- | -- |
| 属性 | 说明 | 类型 | 默认值 | 版本 |
| ---------- | ---------------- | ------------------------------------------------------------ | ------ | ---- |
| list | 列表对应的数组 | any[] | -- | -- |
| onChange | 列表改动回调 | (list: T[]) => void | -- | -- |
| tag | 组件 html 根元素 | string \| null | 'div' | -- |
| transition | 动画效果 | boolean \| [TransitionGroupProps](./transition-group-cn#api) | 'div' | -- |
| attrs | html 标签属性 | Partial\<React.HTMLAttributes\<HTMLDivElement>> | -- | -- |

其他说明。

0 comments on commit 3535e56

Please sign in to comment.