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

refactor(SwipeCell): change to tsx #1499

Merged
merged 10 commits into from
Jul 23, 2024
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
176 changes: 90 additions & 86 deletions src/swipe-cell/__test__/__snapshots__/demo.test.jsx.snap

Large diffs are not rendered by default.

345 changes: 158 additions & 187 deletions src/swipe-cell/__test__/index.test.jsx

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/swipe-cell/demos/event.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import Toast from '../../toast/index';
import SwipeCell from '..';

const opened = ref([false, true]);
const cellRef = ref<InstanceType<typeof SwipeCell>>();
const cellRef = ref();

const handleChange = (d: string) => {
if (d) {
Expand All @@ -44,7 +44,7 @@ const handleEdit = () => {};
const dir = ref('right');

const handleDelete = (val: string) => {
cellRef.value?.showSure('sure-delete');
cellRef.value?.showSure(val, handleSureConfirm);
};
</script>

Expand Down
2 changes: 1 addition & 1 deletion src/swipe-cell/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import _SwipeCell from './swipe-cell.vue';
import _SwipeCell from './swipe-cell';
import { withInstall, WithInstallType } from '../shared';
import { TdSwipeCellProps } from './type';

Expand Down
10 changes: 5 additions & 5 deletions src/swipe-cell/swipe-cell.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ name | type | default | description | required
content | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
disabled | Boolean | - | \- | N
left | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem>` | N
left | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem> \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
opened | Boolean / Array | false | Typescript:`boolean \| Array<boolean>` | N
right | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem>` `interface SwipeActionItem {text: string; className?: string; style?: string; onClick?: () => void; [key: string]: any }`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
right | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem> \| TNode` `interface SwipeActionItem {text: string; className?: string; style?: string; sure?: string \| TNode; onClick?: () => void; [key: string]: any }`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
onChange | Function | | Typescript:`(value: string) => void`<br/> | N
onClick | Function | | Typescript:`(action: SwipeActionItem, source: SwipeSource) => void`<br/>[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`type SwipeSource = 'left' \| 'right'`<br/> | N

Expand All @@ -22,8 +22,8 @@ name | params | description
change | `(value: string)` | \-
click | `(action: SwipeActionItem, source: SwipeSource)` | [see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`type SwipeSource = 'left' \| 'right'`<br/>

### SwipeCellInstanceFunctions
### SwipeCellInstanceFunctions 组件实例方法

名称 | 参数 | 返回值 | 描述
name | params | return | description
-- | -- | -- | --
showSure | `(sure: string | TNode, onClick?: SwipeActionItem['onClick'])` | `void` | [see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>
showSure | `(sure: string \| TNode, onClick?: SwipeActionItem['onClick'])` | `void` | Typescript:`string \| TNode;如果设置了 `onClick`,则点击二次确认内容时,会执行此onClick方法。<br />[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)
9 changes: 5 additions & 4 deletions src/swipe-cell/swipe-cell.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
:: BASE_DOC ::

## API

### SwipeCell Props

名称 | 类型 | 默认值 | 说明 | 必传
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
content | String / Slot / Function | - | 操作项以外的内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | 操作项以外的内容,同 content。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
disabled | Boolean | - | 是否禁用滑动 | N
left | Array / Slot / Function | - | 左侧滑动操作项。所有行为同 `right`。TS 类型:`Array<SwipeActionItem>` | N
left | Array / Slot / Function | - | 左侧滑动操作项。所有行为同 `right`。TS 类型:`Array<SwipeActionItem> \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
opened | Boolean / Array | false | 操作项是否呈现为打开态,值为数组时表示分别控制左右滑动的展开和收起状态。TS 类型:`boolean \| Array<boolean>` | N
right | Array / Slot / Function | - | 右侧滑动操作项。有两种定义方式,一种是使用数组,二种是使用插槽。`right.text` 表示操作文本,`right.className` 表示操作项类名,`right.style` 表示操作项样式,`right.onClick` 表示点击操作项后执行的回调函数。示例:`[{ text: '删除', style: 'background-color: red', onClick: () => {} }]`。TS 类型:`Array<SwipeActionItem>` `interface SwipeActionItem {text: string; className?: string; style?: string; onClick?: () => void; [key: string]: any }`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
right | Array / Slot / Function | - | 右侧滑动操作项。有两种定义方式,一种是使用数组,二种是使用插槽。`right.text` 表示操作文本,`right.className` 表示操作项类名,`right.style` 表示操作项样式,`right.onClick` 表示点击操作项后执行的回调函数。示例:`[{ text: '删除', style: 'background-color: red', onClick: () => {} }]`。TS 类型:`Array<SwipeActionItem> \| TNode` `interface SwipeActionItem {text: string; className?: string; style?: string; sure?: string \| TNode; onClick?: () => void; [key: string]: any }`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
onChange | Function | | TS 类型:`(value: string) => void`<br/>菜单展开或者收回后将菜单的状态传递给父组件,值为数组时表示分别控制左右滑动的展开和收起状态。 | N
onClick | Function | | TS 类型:`(action: SwipeActionItem, source: SwipeSource) => void`<br/>操作项点击时触发(插槽写法组件不触发,业务侧自定义内容和事件)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`type SwipeSource = 'left' \| 'right'`<br/> | N

Expand All @@ -25,4 +26,4 @@ click | `(action: SwipeActionItem, source: SwipeSource)` | 操作项点击时触

名称 | 参数 | 返回值 | 描述
-- | -- | -- | --
showSure | `(sure: string | TNode, onClick?: SwipeActionItem['onClick'])` | `void` | 显示二次确认内容的函数。<br/>【关于参数】`sure` 表示二次确认的具体内容,同contentTS 类型:`string | TNode`;如果设置了 `onClick`,则点击二次确认内容时,会执行此onClick方法。<br />[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>
showSure | `(sure: string \| TNode, onClick?: SwipeActionItem['onClick'])` | `void` | 显示二次确认内容的函数。<br/>【关于参数】`sure` 表示二次确认的具体内容,同contentTS 类型:`string \| TNode;如果设置了 `onClick`,则点击二次确认内容时,会执行此onClick方法。<br />[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)
225 changes: 102 additions & 123 deletions src/swipe-cell/swipe-cell.vue → src/swipe-cell/swipe-cell.tsx
Original file line number Diff line number Diff line change
@@ -1,80 +1,6 @@
<template>
<div ref="swipeCell" :class="classes" @click.capture="handleCellClick">
<div :style="wrapperStyle">
<div
ref="leftRef"
:class="classes + '__left'"
:style="{
width: initData.leftWidth ? `${initData.leftWidth}px` : 'auto',
}"
>
<t-node v-if="swipeLeftMenu" :content="swipeLeftMenu"></t-node>
<template v-else>
<template v-for="(btn, index) of left" :key="index">
<div
:class="[classes + '__content', btn.className || '']"
:style="btn.style || 'height: 100%;'"
@click="
handleClickBtn({
action: { ...btn },
source: 'left',
})
"
>
<t-node v-if="btn.icon" :class="classes + '__icon'" :content="btn.icon"></t-node>
<span v-if="btn.text" :class="classes + '__text'">
<t-node :content="btn.text"></t-node>
</span>
</div>
</template>
</template>
<div :style="sureLeftBgStyle"></div>
<div ref="sureLeftRef" :style="sureLeftStyle" @click="handleSureClick">
<t-node v-if="sureLeftContent" :content="sureLeftContent"></t-node>
</div>
</div>
<t-node v-if="swipeContent" :content="swipeContent"></t-node>
<div
ref="rightRef"
:class="classes + '__right'"
:style="{
width: initData.rightWidth ? `${initData.rightWidth}px` : 'auto',
}"
>
<t-node v-if="swipeRightMenu" :content="swipeRightMenu"></t-node>
<template v-else>
<template v-for="(btn, index) of right" :key="index">
<div
:class="[classes + '__content', btn.className || '']"
:style="btn.style || 'height: 100%;'"
@click="
handleClickBtn({
action: { ...btn },
source: 'right',
})
"
>
<t-node v-if="btn.icon" :class="classes + '__icon'" :content="btn.icon"></t-node>
<span v-if="btn.text" :class="classes + '__text'">
<t-node :content="btn.text"></t-node>
</span>
</div>
</template>
</template>
<div :style="sureRightBgStyle"></div>
<div ref="sureRightRef" :style="sureRightStyle" @click="handleSureClick">
<t-node v-if="sureRightContent" :content="sureRightContent"></t-node>
</div>
</div>
</div>
</div>
</template>

<script lang="ts">
import {
ref,
watch,
toRefs,
reactive,
computed,
onMounted,
Expand All @@ -83,16 +9,17 @@ import {
StyleValue,
onUnmounted,
} from 'vue';
import isFunction from 'lodash/isFunction';
import isArray from 'lodash/isArray';
import isBoolean from 'lodash/isBoolean';
import { useSwipe } from './useSwipe';
import props from './props';
import config from '../config';
import { SwipeActionItem } from './type';
import { renderContent, renderTNode, TNode, useClickAway } from '../shared';
import { SwipeActionItem, SwipeSource } from './type';
import { useClickAway } from '../shared';
import { preventDefault } from '../shared/dom';
import { useSureConfirm } from './useSureConfirm';
import { useContent, useTNodeJSX } from '../hooks/tnode';
import { usePrefixClass } from '../hooks/useClass';

const { prefix } = config;
const name = `${prefix}-swipe-cell`;
Expand All @@ -109,22 +36,17 @@ export interface SwipeInitData {

export default defineComponent({
name,
components: { TNode },
props,
emits: ['click', 'change'],
setup(props, context) {
const renderTNodeJSX = useTNodeJSX();
const renderTNodeContent = useContent();
const swipeCellClass = usePrefixClass('swipe-cell');

const internalInstance = getCurrentInstance();
const swipeContent = computed(() => renderContent(internalInstance, 'default', 'content'));
const swipeLeftMenu = computed(() =>
isFunction(props.left) || internalInstance?.slots.left ? renderTNode(internalInstance, 'left') : false,
);
const swipeRightMenu = computed(() =>
isFunction(props.right) || internalInstance?.slots.right ? renderTNode(internalInstance, 'right') : false,
);
const wrapperRef = ref<HTMLElement>();

const leftRef = ref<HTMLElement>();
const rightRef = ref<HTMLElement>();
const swipeCell = ref<HTMLElement>();
const swipeCellRef = ref<HTMLElement>();
const wrapperStyle = computed(() => {
const transform = `translate3d(${initData.pos}px, 0, 0)`;
let transition = 'margin-left .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
Expand Down Expand Up @@ -175,7 +97,7 @@ export default defineComponent({
};
// 首次touchmove的方向,用于分开左右和上下滑动,左右滑动时禁止上下滑动,上下滑动时禁止左右滑动
let swipeDir: -1 | 0 | 1 = 0;
const { lengthX, lengthY, stop } = useSwipe(swipeCell, {
const { lengthX, lengthY, stop } = useSwipe(swipeCellRef, {
threshold: 0,
onSwipeStart: (e: TouchEvent) => {
if (props.disabled) {
Expand Down Expand Up @@ -284,7 +206,7 @@ export default defineComponent({
const updateLeftMenuPosStyle = (value?: number) => {
if (!leftRef.value) return;
const pos = value || initData.pos;
const children: string | any[] | HTMLCollection = leftRef.value.children || [];
const { children } = leftRef.value;
const wArr: number[] = [];
for (let i = 0, len = children.length - 2; i < len; ++i) {
const el = children[i] as HTMLElement;
Expand All @@ -301,7 +223,7 @@ export default defineComponent({
};
const stopClickAway = ref(
useClickAway(
swipeCell,
swipeCellRef,
() => {
close();
},
Expand Down Expand Up @@ -379,18 +301,18 @@ export default defineComponent({
initData.pos = 0;
props.onChange?.(undefined);
};
const handleClickBtn = ({ action, source }: { action: SwipeActionItem; source: String }) => {
const handleClickBtn = ({ action, source }: { action: SwipeActionItem; source: SwipeSource }) => {
const clickFn = () => {
if (autoBack) {
close();
}
if (action.onClick) {
if (action?.onClick) {
action.onClick();
return;
}
props.onClick?.({ action, source });
props.onClick?.(action, source);
};
if (action.sure) {
if (action?.sure) {
showSure(action.sure, clickFn);
return;
}
Expand All @@ -401,39 +323,96 @@ export default defineComponent({
if (initData.moved) {
preventDefault(e, true);
}
e.stopPropagation();
};

context.expose({
showSure,
});
return {
...toRefs(props),
swipeContent,
swipeLeftMenu,
swipeRightMenu,
initData,
classes,
wrapperRef,
wrapperStyle,
swipeCell,
leftRef,
rightRef,
handleClickBtn,
end,
handleCellClick,
showSureRight,
showSureLeft,
sureLeftBgStyle,
sureRightBgStyle,
sureRightStyle,
sureLeftStyle,
sureRightRef,
sureLeftRef,
sureRightContent,
sureLeftContent,
showSure,
handleSureClick,
const renderLeft = () => {
const leftContent = () => {
if (Array.isArray(props.left)) {
return props.left.map((btn) => {
const btnClass = [`${swipeCellClass.value}__content`, btn.className || ''];
const style = btn.style || 'height: 100%';
const { icon: btnIcon } = btn;
const { text: btnText } = btn;
return (
<div
class={btnClass}
style={style}
onClick={(e: MouseEvent) => handleClickBtn({ action: btn, source: 'left' })}
>
{btnIcon ? <btnIcon class={`${swipeCellClass.value}__icon`} /> : null}
{btnText ? <span class={`${swipeCellClass.value}__text`}>{btnText}</span> : null}
</div>
);
});
}
return renderTNodeJSX('left');
};

return (
<div
ref={leftRef}
class={`${swipeCellClass.value}__left`}
style={{
width: initData?.leftWidth ? `${initData.leftWidth}px` : 'auto',
}}
>
{leftContent()}
<div style={sureLeftBgStyle.value}></div>
<div ref={sureLeftRef} style={sureLeftStyle.value} onClick={(e: MouseEvent) => handleSureClick}>
{sureLeftContent.value}
</div>
</div>
);
};
const renderRight = () => {
const rightContent = () => {
if (Array.isArray(props.right)) {
return props.right.map((btn) => {
const btnClass = [`${swipeCellClass.value}__content`, btn.className || ''];
const style = btn.style || 'height: 100%';
const { icon: btnIcon } = btn;
const { text: btnText } = btn;
return (
<div class={btnClass} style={style} onClick={() => handleClickBtn({ action: btn, source: 'right' })}>
{btnIcon && <btnIcon class={`${swipeCellClass.value}__icon`}></btnIcon>}
{btnText && <span class={`${swipeCellClass.value}__text`}>{btnText}</span>}
</div>
);
});
}
return renderTNodeJSX('right');
};

return (
<div
ref={rightRef}
class={`${swipeCellClass.value}__right`}
style={{
width: initData.rightWidth ? `${initData.rightWidth}px` : 'auto',
}}
>
{rightContent()}
<div style={sureRightBgStyle.value}></div>
<div ref={sureRightRef} style={sureRightStyle.value} onClick={(e: MouseEvent) => handleSureClick}>
{sureRightContent.value}
</div>
</div>
);
};
return () => {
return (
<div ref={swipeCellRef} class={swipeCellClass.value} onClick={handleCellClick}>
<div class={`${swipeCellClass.value}__wrapper`} style={wrapperStyle.value}>
{renderLeft()}
{renderTNodeContent('default', 'content')}
{renderRight()}
</div>
</div>
);
};
},
});
</script>
Loading
Loading