generated from arvinxx/monorepo-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
811 additions
and
582 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import React, { useState } from 'react'; | ||
import { Badge, Button } from 'antd'; | ||
|
||
import SortableList from '@arvinxu/sortable-list'; | ||
import { Flexbox } from '@arvinxu/layout-kit'; | ||
|
||
interface Item { | ||
id: string; | ||
text: string; | ||
} | ||
|
||
const Demo = () => { | ||
const [list, setList] = useState<Item[]>([ | ||
{ id: '1', text: '关关雎鸠' }, | ||
{ id: '2', text: '在河之洲' }, | ||
{ id: '3', text: '窈窕淑女' }, | ||
{ id: '4', text: '君子好逑' }, | ||
]); | ||
|
||
return ( | ||
<SortableList<Item[]> | ||
dataSource={list} | ||
onChange={setList} | ||
getItemStyles={() => ({ padding: '16px' })} | ||
renderItem={(item: Item, { onRemove, onAddItem, index }) => { | ||
return ( | ||
<Flexbox | ||
horizontal | ||
width={'100%'} | ||
distribution={'space-between'} | ||
gap={12} | ||
> | ||
<Flexbox horizontal gap={8}> | ||
<div> | ||
<Badge count={item.id} /> | ||
</div> | ||
<div>{item.text}</div> | ||
</Flexbox> | ||
<Flexbox | ||
horizontal // 由于拖拽事件是通过监听 onMouseDown 来识别用户动作 | ||
// 因此针对相关用户操作,需要终止 onMouseDown 的冒泡行为 | ||
onMouseDown={(e) => { | ||
e.stopPropagation(); | ||
}} | ||
> | ||
<Button | ||
size={'small'} | ||
type={'link'} | ||
onClick={() => { | ||
onAddItem(index, { | ||
id: Math.ceil(Math.random() * 100000).toString(16), | ||
text: 'new', | ||
}); | ||
}} | ||
> | ||
上方 | ||
</Button> | ||
<Button | ||
size={'small'} | ||
type={'link'} | ||
onClick={() => { | ||
onAddItem(index + 1, { | ||
id: Math.ceil(Math.random() * 1000).toString(16), | ||
text: 'new', | ||
}); | ||
}} | ||
> | ||
下方 | ||
</Button> | ||
<Button size={'small'} danger type={'text'} onClick={onRemove}> | ||
删除 | ||
</Button> | ||
</Flexbox> | ||
</Flexbox> | ||
); | ||
}} | ||
/> | ||
); | ||
}; | ||
|
||
export default Demo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React, { useState } from 'react'; | ||
|
||
import SortableList from '@arvinxu/sortable-list'; | ||
|
||
const Demo = () => { | ||
const [list, setList] = useState([ | ||
{ id: '关关雎鸠' }, | ||
{ id: '在河之洲' }, | ||
{ id: '窈窕淑女' }, | ||
{ id: '君子好逑' }, | ||
]); | ||
|
||
return ( | ||
<SortableList | ||
dataSource={list} | ||
onChange={setList} | ||
style={{ background: 'rgb(255,224,224)', padding: 24, borderRadius: 12 }} | ||
removable={false} | ||
className={'custom-class'} | ||
gap={24} | ||
getItemStyles={({ isSorting, isDragging, isDragOverlay }) => { | ||
// overlay 使用默认样式 | ||
if (isDragOverlay) return; | ||
|
||
return { | ||
padding: 24, | ||
// 拖拽项修改背景色 | ||
background: isDragging ? 'rgb(74,135,82)' : 'pink', | ||
color: isDragging ? 'rgb(139,212,148)' : 'rgb(135,74,74)', | ||
// 在 拖拽过程中放大所有item的圆角 | ||
borderRadius: isSorting ? 100 : 16, | ||
boxShadow: 'none', | ||
}; | ||
}} | ||
/> | ||
); | ||
}; | ||
|
||
export default Demo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
@background-color: #fff; | ||
@border-color: #efefef; | ||
@handle-color: rgba(0, 0, 0, 0.25); | ||
@box-shadow-border: 0 0 0 calc(1px / var(--scale-x, 1)) hsla(240, 0%, 26%, 0.05); | ||
@box-shadow-common: 0 1px calc(3px / var(--scale-x, 1)) hsla(240, 0%, 22%, 0.15); | ||
@box-shadow: @box-shadow-border, @box-shadow-common; | ||
|
||
@keyframes pop { | ||
0% { | ||
transform: scale(1); | ||
box-shadow: var(--box-shadow); | ||
} | ||
100% { | ||
transform: scale(var(--scale)); | ||
box-shadow: var(--box-shadow-picked-up); | ||
} | ||
} | ||
|
||
@keyframes fadeIn { | ||
0% { | ||
opacity: 0; | ||
} | ||
100% { | ||
opacity: 1; | ||
} | ||
} | ||
|
||
.avx-sortable { | ||
&-item-container { | ||
display: flex; | ||
box-sizing: border-box; | ||
transform: translate3d(var(--translate-x, 0), var(--translate-y, 0), 0) | ||
scaleX(var(--scale-x, 1)) scaleY(var(--scale-y, 1)); | ||
transform-origin: 0 0; | ||
touch-action: manipulation; | ||
} | ||
|
||
&-fadeIn { | ||
animation: fadeIn 500ms ease; | ||
} | ||
|
||
&-dragOverlay { | ||
--scale: 1.05; | ||
--box-shadow: @box-shadow; | ||
--box-shadow-picked-up: @box-shadow-border, | ||
-1px 0 15px 0 rgba(34, 33, 81, 0.01), | ||
0px 15px 15px 0 rgba(34, 33, 81, 0.25); | ||
z-index: 999; | ||
} | ||
|
||
&-item { | ||
position: relative; | ||
display: flex; | ||
flex-grow: 1; | ||
align-items: center; | ||
padding: 16px 24px; | ||
background-color: @background-color; | ||
box-shadow: @box-shadow; | ||
outline: none; | ||
border-radius: 4px; | ||
box-sizing: border-box; | ||
list-style: none; | ||
transform-origin: 50% 50%; | ||
|
||
transform: scale(var(--scale, 1)); | ||
transition: box-shadow 200ms ease-in-out; | ||
|
||
&:hover { | ||
.avx-sortable-action-remove { | ||
visibility: visible; | ||
} | ||
} | ||
|
||
&:not(.avx-sortable-withHandle) { | ||
touch-action: manipulation; | ||
cursor: grab; | ||
} | ||
|
||
&-dragging:not(&-dragOverlay) { | ||
opacity: var(--dragging-opacity, 0.5); | ||
z-index: 0; | ||
|
||
&:focus { | ||
box-shadow: @box-shadow; | ||
} | ||
} | ||
|
||
&-disabled { | ||
color: #999; | ||
background-color: #f1f1f1; | ||
&:focus { | ||
box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.1), @box-shadow; | ||
} | ||
cursor: not-allowed; | ||
} | ||
|
||
&-dragOverlay { | ||
cursor: inherit; | ||
animation: pop 200ms cubic-bezier(0.18, 0.67, 0.6, 1.22); | ||
transform: scale(var(--scale)); | ||
box-shadow: var(--box-shadow-picked-up); | ||
opacity: 1; | ||
} | ||
|
||
&-color:before { | ||
content: ''; | ||
position: absolute; | ||
top: 50%; | ||
transform: translateY(-50%); | ||
left: 0; | ||
height: 100%; | ||
width: 3px; | ||
display: block; | ||
border-top-left-radius: 3px; | ||
border-bottom-left-radius: 3px; | ||
background-color: var(--color); | ||
} | ||
} | ||
|
||
&-action { | ||
display: flex; | ||
align-self: flex-start; | ||
margin: -12px -10px -15px auto; | ||
|
||
&-remove { | ||
visibility: hidden; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import type { CSSProperties } from 'react'; | ||
import React, { forwardRef, memo, useEffect } from 'react'; | ||
import classNames from 'classnames'; | ||
|
||
import { Handle, Remove } from '../components'; | ||
|
||
import type { BaseItemProps } from '../types'; | ||
|
||
import './index.less'; | ||
|
||
export const Item = memo( | ||
forwardRef<HTMLLIElement, BaseItemProps>((p, ref) => { | ||
const { | ||
color, | ||
dragOverlay, | ||
dragging, | ||
disabled, | ||
fadeIn, | ||
handle, | ||
height, | ||
index, | ||
listeners, | ||
onRemove, | ||
renderItem, | ||
sorting, | ||
style, | ||
transition, | ||
transform, | ||
item, | ||
wrapperStyle, | ||
removable, | ||
onAddItem, | ||
...props | ||
} = p; | ||
|
||
const prefix = 'avx-sortable'; | ||
|
||
// 添加 overlay 抓手 | ||
useEffect(() => { | ||
if (!dragOverlay) { | ||
return; | ||
} | ||
|
||
document.body.style.cursor = 'grabbing'; | ||
|
||
return () => { | ||
document.body.style.cursor = ''; | ||
}; | ||
}, [dragOverlay]); | ||
|
||
const containerStyle = { | ||
...wrapperStyle, | ||
transition: [transition, wrapperStyle?.transition] | ||
.filter(Boolean) | ||
.join(', '), | ||
'--translate-x': transform ? `${Math.round(transform.x)}px` : undefined, | ||
'--translate-y': transform ? `${Math.round(transform.y)}px` : undefined, | ||
'--scale-x': transform?.scaleX ? `${transform.scaleX}` : undefined, | ||
'--scale-y': transform?.scaleY ? `${transform.scaleY}` : undefined, | ||
'--index': index, | ||
'--color': color, | ||
} as CSSProperties; | ||
|
||
return ( | ||
<li | ||
className={classNames( | ||
`${prefix}-item-container`, | ||
fadeIn && `${prefix}-fadeIn`, | ||
sorting && `${prefix}-sorting`, | ||
dragOverlay && `${prefix}-dragOverlay`, | ||
)} | ||
style={containerStyle} | ||
ref={ref} | ||
> | ||
<div | ||
className={classNames( | ||
`${prefix}-item`, | ||
dragging && `${prefix}-item-dragging`, | ||
handle && `${prefix}-withHandle`, | ||
dragOverlay && `${prefix}-item-dragOverlay`, | ||
disabled && `${prefix}-item-disable`, | ||
color && `${prefix}-item-color`, | ||
)} | ||
style={style} | ||
{...(!handle ? listeners : undefined)} | ||
{...props} | ||
tabIndex={!handle ? 0 : undefined} | ||
> | ||
{renderItem ? ( | ||
renderItem(item, { | ||
dragOverlay: Boolean(dragOverlay), | ||
dragging: Boolean(dragging), | ||
sorting: Boolean(sorting), | ||
index, | ||
fadeIn: Boolean(fadeIn), | ||
listeners, | ||
ref, | ||
style, | ||
transform, | ||
transition, | ||
onRemove: removable ? onRemove : undefined, | ||
onAddItem: onAddItem, | ||
}) | ||
) : ( | ||
<> | ||
{item.id} | ||
<span | ||
className={`${prefix}-action`} | ||
onClick={() => { | ||
console.log('123'); | ||
}} | ||
> | ||
{removable ? ( | ||
<Remove | ||
className={`${prefix}-action-remove`} | ||
onMouseDown={(e) => { | ||
e.stopPropagation(); | ||
}} | ||
onClick={onRemove} | ||
/> | ||
) : null} | ||
{handle ? <Handle {...listeners} /> : null} | ||
</span> | ||
</> | ||
)} | ||
</div> | ||
</li> | ||
); | ||
}), | ||
); |
Oops, something went wrong.