Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 修复 sortable-list 上个版本发布问题 #70

Merged
merged 4 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/ColumnList/ColumnItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ColumnItemList,
DeleteAction,
HandleAction,
SortableItem,
useSortableList,
} from '@ant-design/pro-editor';
import { createStyles } from 'antd-style';
Expand Down Expand Up @@ -68,7 +69,7 @@ const useStyle = createStyles(({ css, cx }, prefixCls) => {
};
});

interface ItemRenderProps<T = any> {
interface ItemRenderProps<T extends SortableItem = SortableItem> {
columns: ColumnItemList<T>;
item: T;
index: number;
Expand Down Expand Up @@ -98,6 +99,7 @@ const ColumnItem = memo<ItemRenderProps>(
const props = {
dataIndex: col.dataIndex,
value: item[col.dataIndex],
id: item.id,
index,
prefixCls,
style,
Expand Down
18 changes: 10 additions & 8 deletions src/ColumnList/renderItem/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useSortableList } from '@ant-design/pro-editor';
import { genUniqueId, useSortableList } from '@ant-design/pro-editor';
import { UniqueIdentifier } from '@dnd-kit/core';
import { Input } from 'antd';
import { createStyles } from 'antd-style';
import { CSSProperties, memo, useRef, useState } from 'react';
import { genUniqueID } from '../utils';

const useStyle = createStyles(({ css, cx }, prefixCls) => {
const prefix = `${prefixCls}-content`;
Expand All @@ -20,13 +20,14 @@ interface ItemRenderProps {
dataIndex: string;
value: string;
index: number;
id: UniqueIdentifier;
prefixCls: string;
style: CSSProperties;
placeholder?: string;
}

const ControlInput = memo<ItemRenderProps>(
({ dataIndex, placeholder, value, index, prefixCls, style }) => {
({ dataIndex, placeholder, value, index, prefixCls, style, id }) => {
const instance = useSortableList();

const [innerValue, setInnerValue] = useState(value);
Expand All @@ -39,18 +40,19 @@ const ControlInput = memo<ItemRenderProps>(
setChanged(false);
};

const customListId = (index) => `column-list-index-${index}`;
const customListId = (index, id) => `column-list-${index}-${id}`;

const handleNextFocus = () => {
const value = instance.getValue() || [];
// 如果是最后一个节点,按下回车后,会自动添加一个新的节点
if (index + 1 === value.length) {
// TODO:create 项时 新建项的预填充内容
instance.addItem({ id: genUniqueID(value, value.length), [dataIndex]: '' });
instance.addItem({ id: genUniqueId(value.length.toString()), [dataIndex]: '' });
}

setTimeout(() => {
const nextNodeEl = document.getElementById(customListId(index + 1));
const nextNodeEl = document.getElementById(
customListId(index + 1, instance.getIdByIndex(index + 1)),
);
nextNodeEl?.focus();
}, 200);
};
Expand All @@ -60,7 +62,7 @@ const ControlInput = memo<ItemRenderProps>(
size={'small'}
value={innerValue}
style={style}
id={customListId(index)}
id={customListId(index, id)}
onCompositionStart={() => {
shouldChange.current = false;
}}
Expand Down
2 changes: 1 addition & 1 deletion src/SortableList/components/Item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const Item = memo(
</Flexbox>
)}
<Flexbox
className={classNames(styles.actions, styles.actionsRight)}
className={classNames(styles.actions)}
direction={'horizontal'}
align="center"
>
Expand Down
14 changes: 0 additions & 14 deletions src/SortableList/components/Item/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,5 @@ export const useStyle = createStyles(({ css, cx, token }, prefixCls: string) =>
}
`,
),
actionsRight: cx(
`${prefix}-actions-right`,
css`
position: absolute;
top: 1px;
right: 1px;
align-self: flex-end;
overflow: hidden;
border-radius: 1px;
// 采用背景模糊来解决多种背景色下覆盖内容的问题 TODO:FireFox 兼容
backdrop-filter: blur(5px);
//background-image: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, @bg-2 10%, @bg-2 100%);
`,
),
};
});
6 changes: 3 additions & 3 deletions src/SortableList/demos/_ItemRender.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useSortableList } from '@ant-design/pro-editor';
import { Input, Select } from 'antd';
import { useState } from 'react';
import { memo, useState } from 'react';
import { Flexbox } from 'react-layout-kit';
import { ItemRenderProps, fieldStyle, tableColumnValueOptions } from './data';

export const randomIndex = () => Math.random() * 10000;

const ItemRender = ({ item, index, compact = false }: ItemRenderProps) => {
const ItemRender = memo(({ item, index, compact = false }: ItemRenderProps) => {
const instance = useSortableList();
const [title, setTitle] = useState(item?.title);
const [changed, setChanged] = useState(false);
Expand Down Expand Up @@ -63,6 +63,6 @@ const ItemRender = ({ item, index, compact = false }: ItemRenderProps) => {
</div>
</Flexbox>
);
};
});

export default ItemRender;
57 changes: 36 additions & 21 deletions src/SortableList/demos/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,56 @@
/**
* title: Provider
* description: 为了方便用户在更高的上下文中通过 `useSortableList()` hook 获得组件实例,我们提供了 `SortableListProvider` 由用户控制 Provider 的作用范围。
* compact: true
*/
import { SortableList, SortableListProvider, useSortableList } from '@ant-design/pro-editor';
import { Button, message } from 'antd';
import { useTheme } from 'antd-style';
import { useState } from 'react';
import { Flexbox } from 'react-layout-kit';

import ItemRender from './_ItemRender';
import { INIT_VALUES, SchemaItem } from './data';

const App = () => {
const [listData, setListData] = useState<SchemaItem[]>(INIT_VALUES);

return (
<Flexbox padding={24}>
<SortableList<SchemaItem>
value={listData}
onChange={(data) => {
console.log('data', data);
setListData(data);
}}
renderContent={(item, index) => <ItemRender item={item} index={index} />}
SHOW_STORE_IN_DEVTOOLS // 用于显示 Redux Devtools
/>
</Flexbox>
<SortableList<SchemaItem>
value={listData}
onChange={(data) => {
console.log('data', data);
setListData(data);
}}
renderContent={(item, index) => <ItemRender item={item} index={index} />}
SHOW_STORE_IN_DEVTOOLS // 用于显示 Redux Devtools
/>
);
};

const Extra = () => {
const instance = useSortableList();
return (
<div>
<Button onClick={() => message.info(JSON.stringify(instance.getValue()))}>获取值</Button>
</div>
<Button
block
size="small"
type="primary"
style={{ marginBottom: 8 }}
onClick={() => message.info(JSON.stringify(instance.getValue()))}
>
获取值
</Button>
);
};

export default () => (
<SortableListProvider>
<Extra />
<App />
</SortableListProvider>
);
export default () => {
const token = useTheme();

return (
<SortableListProvider>
<Flexbox padding={24} style={{ background: token.colorBgLayout }}>
<Extra />
<App />
</Flexbox>
</SortableListProvider>
);
};
7 changes: 5 additions & 2 deletions src/SortableList/demos/ref.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/**
* title: 使用 ref 获得实例
* description: 提供传统的 `ref` 方式关联组件实例,可实现自定义功能,如将添加按钮渲染到组件右上方。
* compact: true
*/
import { PlusCircleFilled } from '@ant-design/icons';
import { ActionIcon, SortableList, SortableListRef } from '@ant-design/pro-editor';
import { useTheme } from 'antd-style';
import { useRef, useState } from 'react';
import { Flexbox } from 'react-layout-kit';
import ItemRender from './_ItemRender';
Expand All @@ -17,9 +19,10 @@ export const randomIndex = () => Math.random() * 10000;
export default () => {
const [listData, setListData] = useState<SchemaItem[]>(INIT_VALUES);
const ref = useRef<SortableListRef<SchemaItem>>(null);
const token = useTheme();

return (
<div style={{ width: 340, padding: '0 12px' }}>
<Flexbox padding={24} style={{ background: token.colorBgLayout }}>
<Flexbox horizontal align={'center'} distribution={'space-between'}>
<div>列配置项</div>
<ActionIcon
Expand All @@ -42,6 +45,6 @@ export default () => {
}}
renderContent={(item, index) => <ItemRender item={item} index={index} />}
/>
</div>
</Flexbox>
);
};
8 changes: 6 additions & 2 deletions src/SortableList/demos/renderContent.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
/**
* title: 自定义列表项内容
* description: 提供 `renderContent` 由用户自定义除拖拽等操作外的列表项内容。
* compact: true
*/
import { SortableList } from '@ant-design/pro-editor';
import { useTheme } from 'antd-style';
import { Flexbox } from 'react-layout-kit';
import ItemRender from './_ItemRender';
import { INIT_VALUES, SchemaItem } from './data';

export default () => {
const token = useTheme();
return (
<div style={{ width: 340, padding: '0 12px' }}>
<Flexbox padding={24} style={{ background: token.colorBgLayout }}>
<SortableList<SchemaItem>
initialValues={INIT_VALUES}
onChange={(data, event) => {
console.log('data', data, event);
}}
renderContent={(item, index) => <ItemRender item={item} index={index} />}
/>
</div>
</Flexbox>
);
};
1 change: 1 addition & 0 deletions src/SortableList/demos/renderItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* title: 自定义排序项
* description: 通过 `renderItem` 可以自定义每个排序项,相比于 `renderContent` 提供的自由度更大
* compact: true
*/
import { SortableList, SortableListRef } from '@ant-design/pro-editor';
import { Badge, Button } from 'antd';
Expand Down
9 changes: 6 additions & 3 deletions src/SortableList/demos/useSortableList.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
/**
* title: useSortableList
* description: 在 Item 子组件中使用 `useSortableList()` hook,可以获得当前组件实例
* compact: true
*/
import { SortableList } from '@ant-design/pro-editor';
import { useTheme } from 'antd-style';
import { useState } from 'react';

import { Flexbox } from 'react-layout-kit';
import ItemRender from './_ItemRender';
import { INIT_VALUES, SchemaItem } from './data';

export default () => {
const [listData, setListData] = useState<SchemaItem[]>(INIT_VALUES);
const token = useTheme();

return (
<div style={{ width: 340, padding: '0 12px' }}>
<Flexbox padding={24} style={{ background: token.colorBgLayout }}>
<SortableList<SchemaItem>
value={listData}
onChange={(data) => {
Expand All @@ -21,6 +24,6 @@ export default () => {
}}
renderContent={(item, index) => <ItemRender item={item} index={index} />}
/>
</div>
</Flexbox>
);
};
1 change: 1 addition & 0 deletions src/SortableList/features/DragOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const Overlay: FC<OverlayProps> = ({ prefixCls }) => {
<Item
id={activeId}
dragOverlay
index={activeIndex}
item={items[activeIndex]}
prefixCls={prefixCls}
renderItem={renderItem}
Expand Down
11 changes: 11 additions & 0 deletions src/SortableList/hooks/useSortableList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export interface SortableListInstance {
* @returns 当前激活节点的 id
*/
getActiveId: () => UniqueIdentifier;
/**
* 根据索引获取 id
* @param index
* @returns
*/
getIdByIndex: (index: number) => UniqueIdentifier;
/**
* 获取当前树的数据
* @returns 当前树的数据
Expand Down Expand Up @@ -42,6 +48,10 @@ export const useSortableList = (): SortableListInstance => {
const storeApi = useStoreApi();

const getActiveId = useMemoizedFn(() => storeApi.getState().activeId);
const getIdByIndex = useMemoizedFn((index?: number) => {
const indexId = storeApi.getState().value?.[index]?.id || null;
return indexId;
});
const getValue = useMemoizedFn(() => storeApi.getState().value);
const addItem = (item?: SortableItem, index?: number) =>
storeApi.getState().dispatchListData({ type: 'addItem', item, index });
Expand All @@ -55,6 +65,7 @@ export const useSortableList = (): SortableListInstance => {
getValue,
addItem,
removeItem,
getIdByIndex,
updateItem,
};
};
12 changes: 1 addition & 11 deletions src/SortableList/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,16 @@ demo:

针对可排序列表场景提供基础底层封装,可在其上进行进一步自定义,参考 `ColumnList`。

## 基础使用
## 使用方式

<code src="./demos/Basic.tsx" ></code>
<code src="./demos/controlled.tsx" ></code>
<code src="./demos/getItemStyles.tsx" ></code>
<code src="./demos/renderItem.tsx" ></code>
<code src="./demos/renderContent.tsx" ></code>
<code src="./demos/creatorButtonProps.tsx" ></code>

## 程序化控制

使用 `ref` 或者 `useSortableList()` hook 均可获取组件实例,进而自行控制状态变更。

<code src="./demos/ref.tsx" ></code>
<code src="./demos/useSortableList.tsx" ></code>

### Provider

为了方便用户在更高的上下文中通过 `useSortableList()` hook 获得组件实例,我们提供了 `SortableListProvider` 由用户控制 Provider 的作用范围。

<code src="./demos/provider.tsx" ></code>

## API
Expand Down
Loading