From 2563a4b25ad3ea1bc40256bd07136eb427609004 Mon Sep 17 00:00:00 2001 From: Li0329 Date: Fri, 15 Mar 2024 16:15:31 +0800 Subject: [PATCH 1/2] add progress component --- doc/app/page.tsx | 30 +++++- lib/components/base/progress/MProgress.tsx | 54 +++++++++++ .../base/progress/assets/bamboo.webp | Bin 0 -> 3102 bytes .../base/progress/assets/bamboo_bg.webp | Bin 0 -> 2000 bytes lib/components/base/progress/assets/leaf.webp | Bin 0 -> 2408 bytes lib/components/base/progress/index.d.ts | 65 +++++++++++++ lib/components/base/progress/progress.css | 56 +++++++++++ lib/components/base/progress/useProgress.ts | 87 ++++++++++++++++++ lib/compositions/common/defineCore.ts | 55 +++++++++++ lib/index.ts | 3 + lib/tools/empty.ts | 81 ++++++++++++++++ lib/tools/index.ts | 14 +++ playground/src/components/Base.tsx | 32 ++++++- 13 files changed, 474 insertions(+), 3 deletions(-) create mode 100644 lib/components/base/progress/MProgress.tsx create mode 100644 lib/components/base/progress/assets/bamboo.webp create mode 100644 lib/components/base/progress/assets/bamboo_bg.webp create mode 100644 lib/components/base/progress/assets/leaf.webp create mode 100644 lib/components/base/progress/index.d.ts create mode 100644 lib/components/base/progress/progress.css create mode 100644 lib/components/base/progress/useProgress.ts create mode 100644 lib/compositions/common/defineCore.ts create mode 100644 lib/tools/empty.ts create mode 100644 lib/tools/index.ts diff --git a/doc/app/page.tsx b/doc/app/page.tsx index 291869c..98410c8 100644 --- a/doc/app/page.tsx +++ b/doc/app/page.tsx @@ -8,7 +8,34 @@ * 江湖的业务千篇一律,复杂的代码好几百行。 */ import 'shuimo-ui-react/global.css'; -import { MButton, MAvatar, MTag } from 'shuimo-ui-react'; +import { MButton, MAvatar, MTag, MProgress } from 'shuimo-ui-react'; +import { useState, useEffect } from 'react'; + +function Progress() { + const [loopPer, setLoopPer] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + if (loopPer < 1000) { + setLoopPer(prevLoopPer => prevLoopPer + 1); + } else { + setLoopPer(0); + } + }, 16); + return () => clearInterval(interval); + }) + + return ( + + {Math.ceil(loopPer / 10)}% + + ) +} export default function Page() { @@ -30,6 +57,7 @@ export default function Page() { 你好 你好 菜头紫 + ); } diff --git a/lib/components/base/progress/MProgress.tsx b/lib/components/base/progress/MProgress.tsx new file mode 100644 index 0000000..a6a3caf --- /dev/null +++ b/lib/components/base/progress/MProgress.tsx @@ -0,0 +1,54 @@ +/** + * @description 进度条组件 + * @author Muzych + * @date 2024/03/15 12:04 + * @version v1.0.0 + */ +import './progress.css'; +import { ProgressProps } from './index'; +import { MC, Slot } from '../../../types'; +import { leaf, useProgress } from './useProgress.ts'; +import { CSSProperties, useEffect, useMemo, useState } from "react"; + +export default function MProgress(_props: ProgressProps & MC & Slot) { + + const props = _props as Required + + + const [value, setValue] = useState(props.value ?? 0); + const [max, setMax] = useState(props.max ?? 100); + + useEffect(() => { + setValue(props.value ?? 0); + setMax(props.max ?? 100); + }, [props.value, props.max]); + + const { getProgressWrapperStyle, getProgressInfo } = useProgress({ props }); + const progressInfo = useMemo(() => getProgressInfo(), [value, max]) + const progressWrapperInfo = useMemo(() => { + if (props.showInfo) { + return getProgressWrapperStyle(progressInfo) + } + return undefined; + }, [props.showInfo, progressInfo]) + + + + + + return ( + <> + {props.showInfo ? ( +
+
+ + {_props.children} +
+ +
+ ) : ( + + )} + + ) +} \ No newline at end of file diff --git a/lib/components/base/progress/assets/bamboo.webp b/lib/components/base/progress/assets/bamboo.webp new file mode 100644 index 0000000000000000000000000000000000000000..31677046bbb3c15400936a0e8559b97f4da76114 GIT binary patch literal 3102 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 literal 0 HcmV?d00001 diff --git a/lib/components/base/progress/assets/leaf.webp b/lib/components/base/progress/assets/leaf.webp new file mode 100644 index 0000000000000000000000000000000000000000..e734b8525db3c53534af313a22267dcffd3b799e GIT binary patch literal 2408 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 { + const size = { + width: w || BASE_SIZE.BG.W, + height: h || BASE_SIZE.BG.H, + }; + if (isEmpty(h) && notEmpty(w)) { + return { width: w!, height: w! / w2h }; + } + if (notEmpty(h) && isEmpty(w)) { + return { width: h! * w2h, height: h! }; + } + return size; +}; + +const getTextLeft = (width: number, infoWidth: number, leafWidth: number, per: number) => { + return ((width - leafWidth) * per) / 100 - infoWidth / 2; +}; + + +export const leaf = leafPng; + + +export function useProgress(options: Options<{ + props: ProgressProps, +}>) { + const { props } = options; + const getProgressInfo = () => { + const { width, height } = getSize(props.width ?? 399, props.height ?? 26.547); + + return { + style: { + '--m-progress-width': `${width}px`, + '--m-progress-height': `${height}px`, + }, + width, + }; + }; + + const getProgressWrapperStyle = (progressInfo: ReturnType) => { + const { width, style } = progressInfo; + const leafSize = getSize(undefined, props.leafHeight ?? 28, LEAF_W2H); + const per = Math.ceil((props.value / props.max) * 100); + const perWidth = leafSize.width + props.infoWidth; + const textStyle = { + left: `${getTextLeft(width, props.infoWidth ?? 44, leafSize.width, per)}px`, + }; + + const baseStyle = { + ...style, + '--m-progress-per-height': `${leafSize.height}px`, + '--m-progress-per-width': `${perWidth}px`, + '--m-progress-leaf-height': `${props.leafHeight ?? 28}px`, + }; + + return { + textStyle, baseStyle, + }; + }; + + return { + getProgressInfo, + getProgressWrapperStyle, + }; + +} \ No newline at end of file diff --git a/lib/compositions/common/defineCore.ts b/lib/compositions/common/defineCore.ts new file mode 100644 index 0000000..41e819c --- /dev/null +++ b/lib/compositions/common/defineCore.ts @@ -0,0 +1,55 @@ +/* eslint-disable */ +/** + * @description A tool for normalizing grammatical structures + * @author 阿怪 + * @date 2023/6/16 11:25 + * @version v1.0.0 + * + * 江湖的业务千篇一律,复杂的代码好几百行。 + */ + +import { useRef } from 'react'; + +type OptionsEmpty = undefined; + + +type IsAllUndefined = T extends [infer H, ...infer R] + ? H extends undefined + ? IsAllUndefined + : false + : true; + +interface OptionsNotEmpty { + props: Required

; + value: { [K in keyof V]: React.MutableRefObject; }; + event: E; +} + +type CoreArguments = keyof OptionsNotEmpty; +type AnyArguments = { + [K in CoreArguments]?: any +} + +type DefinedKeys = { [K in keyof T]: T[K] extends undefined ? never : K }[keyof T]; +type UndefinedKeys = Exclude>; + +export type OptionsKeys< + A extends AnyArguments, + P, V, E, + DK extends string | number | symbol = DefinedKeys, + UK extends string | number | symbol = UndefinedKeys +> = { + [K in DK & keyof OptionsNotEmpty]: OptionsNotEmpty[K]; +} & { + [K in UK & keyof OptionsNotEmpty]-?: OptionsNotEmpty[K]; +} + +export type Options< + K extends AnyArguments, + P = K['props'], + V = K['value'], + E = K['event'], +> = + IsAllUndefined<[P, V, E]> extends true + ? OptionsEmpty + : OptionsKeys; \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index fd9ed29..62e9b71 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -18,3 +18,6 @@ export { default as MAvatar } from './components/base/avatar/MAvatar.tsx'; export { default as MTag } from './components/base/tag/MTag.tsx'; + + +export { default as MProgress } from './components/base/progress/MProgress.tsx'; \ No newline at end of file diff --git a/lib/tools/empty.ts b/lib/tools/empty.ts new file mode 100644 index 0000000..a6ebfcb --- /dev/null +++ b/lib/tools/empty.ts @@ -0,0 +1,81 @@ +/** + * @description common tools + * @author 阿怪 + * @date 2023/4/20 22:31 + * @version v1.0.0 + * + * 江湖的业务千篇一律,复杂的代码好几百行。 + */ + +/** + * 支持稍多类型的判断非空的方法 + * @param value + */ +export const notEmpty = (value: any) => { + // 先处理基本类型 + // null + // undefined + if (value === undefined || value === null) { + return false; + } + const valueType = typeof value; + // string + if (valueType === 'string') { + return value !== ''; + } + // number bigint boolean + if (valueType === 'number' || valueType === 'bigint' || valueType === 'boolean' || valueType === 'function') { + return true; + } + // symbol + if (valueType === 'symbol') { + return value.toString() !== 'Symbol()'; + } + + if (valueType === 'object') { + // Bigint/Symbol no new + + if (value instanceof String || value instanceof Array) { + return value.length !== 0; + } + + if (value instanceof Number || value instanceof Boolean) { + return true; + } + + if (value instanceof Map || value instanceof Set) { + return value.size > 0; + } + + if (value instanceof WeakMap || value instanceof WeakSet) { + console.error('WeakMap和WeakSet无法以通用的方式判断是否为空。'); + return false; + } + + if (value instanceof RegExp) { + return value.toString() !== '/(?:)/'; + } + + if (value instanceof Date) { + return value.toString() !== 'Invalid Date'; + } + + const typedArrayTypes = [Int8Array, Uint8Array, Uint8ClampedArray, + Int16Array, Uint16Array, + Int32Array, Uint32Array, Float32Array, + Float64Array]; + for (const arrayType of typedArrayTypes) { + if (value instanceof arrayType) { + return value.length; + } + } + + return Object.keys(value).length > 0; + } + }; + + /** + * 判断为空的方法,即notEmpty的取反 + * @param value + */ + export const isEmpty = (value: any) => !notEmpty(value); \ No newline at end of file diff --git a/lib/tools/index.ts b/lib/tools/index.ts new file mode 100644 index 0000000..6e0ab2b --- /dev/null +++ b/lib/tools/index.ts @@ -0,0 +1,14 @@ +/** + * @description tools index + * @author 阿怪 + * @date 2023/4/20 22:38 + * @version v1.0.0 + * + * 江湖的业务千篇一律,复杂的代码好几百行。 + */ +// import clsx from 'clsx'; +// +// export { +// clsx +// }; +export * from './empty'; diff --git a/playground/src/components/Base.tsx b/playground/src/components/Base.tsx index c02d226..0afffb0 100644 --- a/playground/src/components/Base.tsx +++ b/playground/src/components/Base.tsx @@ -6,8 +6,8 @@ * * 江湖的业务千篇一律,复杂的代码好几百行。 */ -import { MAvatar, MButton, MTag } from 'shuimo-ui-react/index.ts'; - +import { MAvatar, MButton, MTag, MProgress } from 'shuimo-ui-react/index.ts'; +import { useState, useEffect } from 'react'; function Button() { @@ -53,6 +53,33 @@ function Tag() { ) } +function Progress() { + const [loopPer, setLoopPer] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + if (loopPer < 1000) { + setLoopPer(prevLoopPer => prevLoopPer + 1); + } else { + setLoopPer(0); + } + }, 16); + return () => clearInterval(interval); + }) + + return ( + + {Math.ceil(loopPer / 10)}% + + ) +} + + export default function Base() { @@ -62,6 +89,7 @@ export default function Base() {