Skip to content

Commit

Permalink
✨ feat: pull-refresh 组件
Browse files Browse the repository at this point in the history
  • Loading branch information
zzxming authored Jun 2, 2024
2 parents eea6925 + 820364d commit 05c021d
Show file tree
Hide file tree
Showing 20 changed files with 10,909 additions and 7,721 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default defineConfig({
{ text: 'Overlay', link: '/component/overlay' },
{ text: 'TextEllipsis', link: '/component/text-ellipsis' },
{ text: 'TextHighlight', link: '/component/text-highlight' },
{ text: 'PullRefresh', link: '/component/pull-refresh' },
],
},
],
Expand Down
7 changes: 1 addition & 6 deletions docs/component/captcha.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

| 名称 | 类型 | 说明 | 默认值 |
| --------------- | ------------------------------------------------------------------------- | --------------------------------- | ------------ |
| type | `CaptchType` | 验证的方式 | `'slider'` |
| type | `'slider' \| 'pointer'` | 验证的方式 | `'slider'` |
| canvasSize | `[number, number]` | 画布大小 | `[500, 300]` |
| image | `string` | 图片地址 | - |
| texts | `string[]` | 验证方式为 `pointer` 时的验证文字 | - |
Expand Down Expand Up @@ -90,11 +90,6 @@
## 内置类型

```ts
enum CaptchType {
slider = 'slider',
pointer = 'pointer',
}

type CheckStatusInfo = {
success: boolean;
message: string;
Expand Down
7 changes: 7 additions & 0 deletions docs/component/pull-refresh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# PullRefresh

## 基础用法

:::demo pull-refresh/base

:::
22 changes: 22 additions & 0 deletions docs/demos/pull-refresh/base.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<CdxPullRefresh
v-model="loading"
@refresh="handleRefresh"
style="height: 400px"
>
<p v-for="i in 20">{{ i }}</p>
</CdxPullRefresh>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const loading = ref(false);
const handleRefresh = () => {
console.log('refresh');
setTimeout(() => {
loading.value = false;
}, 3000);
};
</script>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"build:build-utils": "pnpm -C ./internal/build-utils build && pnpm i",
"docs:dev": "pnpm -C ./docs dev",
"docs:build": "pnpm -C ./docs build",
"play:dev": "pnpm -C ./playground dev",
"create": "tsx ./scripts/create.ts"
},
"peerDependencies": {
Expand Down
4 changes: 3 additions & 1 deletion packages/cdx-component/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { CdxTextEllipsis } from '../components/text-ellipsis';
import { CdxTextHighlight } from '../components/text-highlight';
import { CdxModel } from '../components/model';
import { CdxCountTo } from '../components/count-to';
import { CdxCollapse ,CdxCollapseItem} from '../components/collapse';
import { CdxCollapse, CdxCollapseItem } from '../components/collapse';
import { CdxCollapseTransition } from '../components/collapse-transition';
import { CdxPullRefresh } from '../components/pull-refresh';

import type { Plugin } from 'vue';

Expand All @@ -30,4 +31,5 @@ export default [
CdxCollapse,
CdxCollapseItem,
CdxCollapseTransition,
CdxPullRefresh,
] as Plugin[];
123 changes: 60 additions & 63 deletions packages/components/captcha/src/captcha.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,60 @@
import { buildProps, definePropType } from '@cdx-component/utils';
import type { ExtractPropTypes } from 'vue';

export type CheckStatusInfo = {
success: boolean;
message: string;
};
export enum CheckStatus {
success = 'success',
fail = 'fail',
none = 'none',
}
export enum CaptchType {
slider = 'slider',
pointer = 'pointer',
}
export const captchaProps = buildProps({
type: {
type: String,
values: ['slider', 'pointer'],
default: CaptchType.slider,
},
image: {
type: String,
required: true,
},
canvasSize: {
type: definePropType<[number, number]>(Array),
default: () => [500, 300],
},
texts: {
type: definePropType<string[]>(Array),
validator: (v: any) =>
Array.isArray(v) && v.every((item: any) => typeof item === 'string' && item.length === 1),
},
fontRate: {
type: Number,
default: 0.108,
validator: (v: any) => typeof v === 'number' && v >= 0 && v <= 1,
},
onBeforSuccess: {
type: definePropType<() => Promise<boolean | CheckStatusInfo> | boolean | CheckStatusInfo>(Function),
},
loading: {
type: Boolean,
default: false,
},
onRefresh: {
type: definePropType<() => void | Promise<void>>(Function),
},
tipDuration: {
type: Number,
default: 3000,
},
} as const);
export type CaptchaProps = ExtractPropTypes<typeof captchaProps>;

export const captchaEmits = {
success: () => true,
fail: () => true,
imgError: () => true,
};
export type CaptchaEmits = typeof captchaEmits;
import { buildProps, definePropType } from '@cdx-component/utils';
import type { ExtractPropTypes } from 'vue';

export type CheckStatusInfo = {
success: boolean;
message: string;
};
export enum CheckStatus {
success = 'success',
fail = 'fail',
none = 'none',
}

export const captchaProps = buildProps({
type: {
type: String,
values: ['slider', 'pointer'],
default: 'slider',
},
image: {
type: String,
required: true,
},
canvasSize: {
type: definePropType<[number, number]>(Array),
default: () => [500, 300],
},
texts: {
type: definePropType<string[]>(Array),
validator: (v: any) =>
Array.isArray(v) && v.every((item: any) => typeof item === 'string' && item.length === 1),
},
fontRate: {
type: Number,
default: 0.108,
validator: (v: any) => typeof v === 'number' && v >= 0 && v <= 1,
},
onBeforSuccess: {
type: definePropType<() => Promise<boolean | CheckStatusInfo> | boolean | CheckStatusInfo>(Function),
},
loading: {
type: Boolean,
default: false,
},
onRefresh: {
type: definePropType<() => void | Promise<void>>(Function),
},
tipDuration: {
type: Number,
default: 3000,
},
} as const);
export type CaptchaProps = ExtractPropTypes<typeof captchaProps>;

export const captchaEmits = {
success: () => true,
fail: () => true,
imgError: () => true,
};
export type CaptchaEmits = typeof captchaEmits;
18 changes: 9 additions & 9 deletions packages/components/captcha/src/captcha.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { isFunction, isBoolean, generateRandomColor } from '@cdx-component/utils';
import { ref, computed, watch, nextTick, onMounted } from 'vue';
import { captchaProps, CheckStatus, captchaEmits, CaptchType } from './captcha';
import { captchaProps, CheckStatus, captchaEmits } from './captcha';
import { squarePath } from './canvasPath';
import { CdxLoading, CdxCaptchaSlider } from '@cdx-component/components';
import { useBem } from '@cdx-component/hooks';
Expand Down Expand Up @@ -176,14 +176,14 @@ const drawImage = async (imageSrc: string, canvasEl?: HTMLCanvasElement) => {
if (!ctx) return;
const { width, height } = canvasEl;
ctx.drawImage(image, 0, 0, width, height);
if (props.type === CaptchType.pointer) {
if (props.type === 'pointer') {
return drawText(ctx, { width, height });
}
const subCanvasEl = subCanvasRef.value;
const subCtx = subCanvasEl?.getContext?.('2d');
if (!subCanvasEl || !subCtx || !trackRef.value) return;
if (props.type === CaptchType.slider) {
if (props.type === 'slider') {
const canvasRect = canvasEl.getBoundingClientRect();
const trackRect = trackRef.value.getBoundingClientRect();
// 滑动时以轨道为准, 需要补正 canvas 宽度和 track 宽度的差值
Expand Down Expand Up @@ -245,7 +245,7 @@ const handleRefresh = async () => {
refreshLoading.value = false;
};
const handlePointerSetClick = async (e: MouseEvent) => {
if (props.type !== CaptchType.pointer || !canvasRef.value || !pointerTargets.length || isLock.value) return;
if (props.type !== 'pointer' || !canvasRef.value || !pointerTargets.length || isLock.value) return;
const { offsetX, offsetY } = e;
const { clientWidth: width, clientHeight: height } = canvasRef.value;
pointers.value.push([(offsetX / width) * 100, (offsetY / height) * 100]);
Expand Down Expand Up @@ -319,7 +319,7 @@ onMounted(() => {
:class="[
bem.be('container'),
isLock && bem.bem('container', 'lock'),
type === CaptchType.pointer && bem.bs('pointer'),
type === 'pointer' && bem.bs('pointer'),
]"
@click="handlePointerSetClick"
>
Expand All @@ -331,7 +331,7 @@ onMounted(() => {
:height="canvasSize[1]"
></canvas>
<div
v-if="type === CaptchType.slider"
v-if="type === 'slider'"
:class="bem.be('sub-image')"
>
<canvas
Expand All @@ -342,7 +342,7 @@ onMounted(() => {
></canvas>
</div>
</template>
<template v-if="type === CaptchType.pointer">
<template v-if="type === 'pointer'">
<span
v-for="([x, y], i) in pointers"
:class="bem.be('pointer')"
Expand All @@ -367,7 +367,7 @@ onMounted(() => {
</div>
<div :class="bem.be('footer')">
<div
v-if="type === CaptchType.pointer"
v-if="type === 'pointer'"
:class="bem.be('text-list')"
>
<span :class="bem.be('tip')">请依次点击:</span>
Expand All @@ -379,7 +379,7 @@ onMounted(() => {
</span>
</div>
<CdxCaptchaSlider
v-else-if="type === CaptchType.slider"
v-else-if="type === 'slider'"
ref="sliderRef"
:lock="isLock"
:loading="isLoading"
Expand Down
1 change: 1 addition & 0 deletions packages/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './model';
export * from './count-to';
export * from './collapse';
export * from './collapse-transition';
export * from './pull-refresh';
6 changes: 6 additions & 0 deletions packages/components/pull-refresh/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { withInstall } from '@cdx-component/utils';
import PullRefresh from './src/pull-refresh.vue';

export const CdxPullRefresh = withInstall(PullRefresh);
export * from './src/pull-refresh';
export default CdxPullRefresh;
35 changes: 35 additions & 0 deletions packages/components/pull-refresh/src/pull-refresh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { UPDATE_MODEL_EVENT } from '@cdx-component/constants';
import { buildProps, isBoolean } from '@cdx-component/utils';
import type { ExtractPropTypes } from 'vue';

export enum PullRefreshStatus {
pulling = 'pulling',
loading = 'loading',
loosing = 'loosing',
none = 'none',
}

export const pullRefreshProps = buildProps({
modelValue: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
headHeight: {
type: [Number, String],
default: 50,
},
refreshDistance: {
type: [Number, String],
},
} as const);
export type PullRefreshProps = ExtractPropTypes<typeof pullRefreshProps>;

export const pullRefreshEmits = {
[UPDATE_MODEL_EVENT]: (value: boolean) => isBoolean(value),
refresh: () => true,
};
export type PullRefreshEmits = typeof pullRefreshEmits;
Loading

0 comments on commit 05c021d

Please sign in to comment.