Skip to content

Commit

Permalink
chore: swipe-action mini (#1141)
Browse files Browse the repository at this point in the history
* feat: swipeAction mini

* chore: swipeAction

* chore: swipe-action

* fix: ts error

* chore: 修复小程序swipeaction 卡顿

* chore: swipeAction mini resize

* chore: swipeAction mini resize

* fix: 单元测试

* fix: 单元测试

* fix: swipeAction close without animation

---------

Co-authored-by: Yang <[email protected]>
  • Loading branch information
Yang03 and Yang authored Nov 28, 2023
1 parent 6773de0 commit c2babc2
Show file tree
Hide file tree
Showing 21 changed files with 832 additions and 89 deletions.
6 changes: 4 additions & 2 deletions packages/mini-demo/config/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
const path = require('path');

console.log(path.resolve(__dirname, '../'));

let alias = {
// 'zarm/mini': path.resolve(__dirname, '../', '../zarm/src'),
react: path.resolve(__dirname, '../', 'node_modules/react'),
Expand Down Expand Up @@ -51,6 +49,10 @@ const config = {
enable: false, // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
},
mini: {
miniCssExtractPluginOption: {
// 忽略css文件引入顺序
ignoreOrder: true
},
postcss: {
pxtransform: {
enable: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/mini-demo/order.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"input":{"AutoHeight":"6","Basic":"1","Clearable":"2","Disabled":"5","Native":"3","ReadOnly":"4","ShowLength":"7","Vertical":"8","Readonly":"4","Disable":0}}
{"input":{"AutoHeight":"6","Basic":"1","Clearable":"2","Disabled":"5","Native":"3","ReadOnly":"4","ShowLength":"7","Vertical":"8","Readonly":"4","Disable":0},"swipe-action":{"Basic":0}}
1 change: 1 addition & 0 deletions packages/mini-demo/src/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default defineAppConfig({
'pages/collapse/index',
'pages/tabs/index',
'pages/input/index',
'pages/swipe-action/index',
],
window: {
backgroundTextStyle: 'light',
Expand Down
4 changes: 4 additions & 0 deletions packages/mini-demo/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@
</head>
<body>
<div id="app"></div>
<!-- <script src="//unpkg.com/[email protected]/dist/vconsole.min.js"></script>
<script>
window.vConsole = new window.VConsole();
</script> -->
</body>
</html>
83 changes: 83 additions & 0 deletions packages/mini-demo/src/pages/swipe-action/component/basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';
import { List, Panel, SwipeAction } from 'zarm/mini';

const RIGHT_BUTTONS = [
{
text: '右按钮1',
onClick: () => console.log('右按钮1'),
},
{
text: '右按钮2',
theme: 'danger',
onClick: () => console.log('右按钮2'),
},
];
const LEFT_BUTTONS = [
{
text: '左按钮1',
onClick: () => console.log('左按钮1'),
},
{
text: '左按钮2',
theme: 'danger',
onClick: () => console.log('左按钮2'),
},
];

function Demo() {
return (
<Panel title="基本用法">
<List>
<SwipeAction
onOpen={() => console.log('open')}
onClose={() => console.log('close')}
rightActions={RIGHT_BUTTONS}
>
<List.Item title="左滑看看" />
</SwipeAction>

<SwipeAction
onOpen={() => console.log('open')}
onClose={() => console.log('close')}
leftActions={LEFT_BUTTONS}
>
<List.Item title="右滑看看" />
</SwipeAction>

<SwipeAction
onOpen={() => console.log('open')}
onClose={() => console.log('close')}
leftActions={LEFT_BUTTONS}
rightActions={[RIGHT_BUTTONS[0]]}
>
<List.Item title="左右都能滑动(自动关闭)" />
</SwipeAction>

{/* <SwipeAction
onOpen={() => console.log('open')}
onClose={() => console.log('close')}
leftActions={[
{
text: '异步',
onClick: async () => {
const confirm = Modal.confirm({
title: '确定要关闭吗?',
content: '这里是确认框的内容部分,点击确定按钮,将触发 Promise 关闭确认框',
onConfirm: async () => {
await new Promise((resolve) => setTimeout(resolve, 3000));
console.log('异步按钮回调');
},
});
await confirm;
},
},
]}
>
<List.Item title="异步关闭" />
</SwipeAction> */}
</List>
</Panel>
);
}

export default Demo;
3 changes: 3 additions & 0 deletions packages/mini-demo/src/pages/swipe-action/index.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: 'Swipe-Action',
});
3 changes: 3 additions & 0 deletions packages/mini-demo/src/pages/swipe-action/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
view {
box-sizing: border-box;
}
13 changes: 13 additions & 0 deletions packages/mini-demo/src/pages/swipe-action/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

import * as React from 'react';
import Basic from './component/basic';

import './index.scss';

export default () => {
return (
<>
<Basic />
</>
)
}
5 changes: 5 additions & 0 deletions packages/mini-demo/src/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ const siteMap = {
name: '折叠面板',
page: '/pages/collapse/index',
},
{
key: 'SwipeAction',
name: '滑动操作',
page: '/pages/swipe-action/index',
},
// {
// key: 'Message',
// name: '消息',
Expand Down
2 changes: 1 addition & 1 deletion packages/zarm/src/calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const Calendar = React.forwardRef<HTMLDivElement, CalendarProps>((props, ref) =>
const target = value[0] || new Date();
const key = `${target.getFullYear()}-${target.getMonth() + 1}`;
const node = nodes.current[key]!;
node?.el()?.scrollIntoView();
node?.el()?.scrollIntoView?.();
};

const handleDateClick = useCallback(
Expand Down
4 changes: 2 additions & 2 deletions packages/zarm/src/custom-input/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ describe('CustomInput', () => {
const { container } = render(
<CustomInput className="custom-input" value="test" onFocus={onFocus} />,
);
const input = container.querySelector('.za-custom-input');
const input = container.querySelector('.za-custom-input__content');
fireEvent.click(input!);
expect(onFocus).toBeCalled();
});

it('disabled focus', () => {
const onFocus = jest.fn();
render(<CustomInput className="custom-input" value="test" onFocus={onFocus} disabled />);
const input = document.body.querySelector('.za-custom-input');
const input = document.body.querySelector('.za-custom-input__content');
fireEvent.click(input!);
expect(onFocus).toBeCalledTimes(0);
});
Expand Down
202 changes: 202 additions & 0 deletions packages/zarm/src/swipe-action/SwipeAction.mini.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import { View, ViewProps } from '@tarojs/components';
import { createBEM } from '@zarm-design/bem';
import React, { useContext, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
import Taro from '@tarojs/taro';
import { ConfigContext } from '../config-provider';
import { nanoid } from '../utils';
import { getRect } from '../utils/dom/dom.mini';
import useDrag from '../utils/hooks/useDrag';
import type { HTMLProps } from '../utils/utilityTypes';
import type { BaseSwipeActionItemProps, BaseSwipeActionProps } from './interface';
import SwipeActionItem from './SwipeActionItem.mini';
import useSwipe from './useSwipe';

export interface SwipeActionCssVars {
'--background'?: React.CSSProperties['background'];
}

export interface SwipeActionElement extends ViewProps {
close: () => void;
}

export type SwipeActionItemProps = ViewProps & BaseSwipeActionItemProps;

export type SwipeActionProps = BaseSwipeActionProps &
React.PropsWithChildren<HTMLProps<SwipeActionCssVars>> & {
leftActions?: SwipeActionItemProps[];
rightActions?: SwipeActionItemProps[];
};

let SwipeActions = [];

const SwipeAction = React.forwardRef<SwipeActionElement, SwipeActionProps>((props, ref) => {
const {
children,
className,
leftActions,
rightActions,
moveDistanceRatio,
moveTimeSpan,
animationDuration: initialAnimationDuration,
offset,
autoClose,
disabled,
onClose,
onOpen,
} = props;

const { isOpen, style, doTransition, onSwipe, afterClose } = useSwipe({ animationDuration: initialAnimationDuration });
// const isOpen = useRef<null | string>(null);
const pending = useRef(false);
const leftId = useMemo(() => `swipe-action-left-${nanoid()}`, []);
const rightId = useMemo(() => `swipe-action-right-${nanoid()}`, []);
const { prefixCls } = useContext(ConfigContext);

const swipeActionWrap = React.useRef<SwipeActionElement | null>((ref as any) || null);
const bem = createBEM('swipe-action', { prefixCls });

useImperativeHandle(swipeActionWrap, () => {
return {
close: () => {
close();
},
};
});

const close = () => {
if (pending.current) return;
doTransition(0, initialAnimationDuration);
afterClose();
};

const renderButtons = (actions, direction, id) => {
if (!actions || actions.length === 0) {
return;
}

const cls = bem('actions', [{ [`${direction}`]: true }]);

return (
<View className={cls} id={id}>
{actions.map((action, index) => {
return (
<SwipeActionItem
{...action}
key={+index}
onClick={async () => {
pending.current = true;
await action.onClick?.();
pending.current = false;
if (autoClose) {
close?.();
}
}}
/>
);
})}
</View>
);
};

let btnsLeftWidth = 0;
let btnsRightWidth = 0;
const computeBtnSize = async () => {
btnsLeftWidth = (await getRect(leftId))?.width;
btnsRightWidth = (await getRect(rightId))?.width;
};

const dragging = useRef(false);

useEffect(() => {
computeBtnSize();
SwipeActions.push(swipeActionWrap);
Taro.onWindowResize(computeBtnSize);
return () => {
SwipeActions = SwipeActions.filter((action) => action !== swipeActionWrap);
Taro.offWindowResize(computeBtnSize);
};
}, []);

const closeOther = () => {
SwipeActions.filter((action) => action !== swipeActionWrap).map((action) =>
action?.current?.close(),
);
};

const bind = useDrag(
(state) => {
if (state.first) {
closeOther();
return false;
}
onSwipe(state, {
moveDistanceRatio,
moveTimeSpan,
leftActions,
rightActions,
btnsLeftWidth,
btnsRightWidth,
onOpen,
animationDuration: initialAnimationDuration,
close,
});
},
{
bounds: async () => {
return {
left: rightActions.length ? -btnsRightWidth - offset! : 0,
right: leftActions.length ? btnsLeftWidth + offset! : 0,
};
},
enabled: !disabled,
axis: 'x',
// pointer: { touch: true },
// preventScroll: true,
// triggerAllEvents: true,
},
);

const cls = bem([className]);

return (
<>
{leftActions || rightActions ? (
<View className={cls} style={props.style} {...bind()} ref={swipeActionWrap}>
{renderButtons(leftActions, 'left', leftId)}
{renderButtons(rightActions, 'right', rightId)}
<View
className={bem('content')}
style={style}
onTransitionEnd={() => !isOpen.current && onClose?.()}
onClick={(e) => {
if (isOpen.current && !dragging.current) {
e.preventDefault();
e.stopPropagation();
close();
}
}}
>
{children}
</View>
</View>
) : (
children
)}
</>
);
});

SwipeAction.displayName = 'SwipeAction';

SwipeAction.defaultProps = {
leftActions: [],
rightActions: [],
moveDistanceRatio: 0.5,
moveTimeSpan: 300,
animationDuration: 300,
offset: 10,
autoClose: true,
disabled: false,
};

export default SwipeAction;
Loading

0 comments on commit c2babc2

Please sign in to comment.