-
Notifications
You must be signed in to change notification settings - Fork 3
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
✨ [progress] add progress #10
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* @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<ProgressProps>; | ||
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 ? ( | ||
<div className="m-progress-border" style={progressWrapperInfo?.baseStyle as CSSProperties}> | ||
<div className="m-progress-per" style={progressWrapperInfo?.textStyle as CSSProperties}> | ||
<img className="m-progress-leaf" src={leaf} alt=""/> | ||
{_props.children} | ||
</div> | ||
<progress className="m-progress" value={value} max={max} style={progressInfo.style as CSSProperties | undefined}/> | ||
</div> | ||
) : ( | ||
<progress className="m-progress" value={value} max={max} style={progressInfo.style as CSSProperties | undefined}/> | ||
)} | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. copy file from vue version , you should update comments |
||
* @description process api type | ||
* @author 阿怪 | ||
* @date 2022/4/17 01:12 | ||
* @version v1.0.0 | ||
* | ||
* @name m-progress | ||
* @docDescription progress component with shuimo-ui style. | ||
* 水墨组件的进度条组件。 | ||
* @docUrl https://shuimo.design/progress | ||
* | ||
* 江湖的业务千篇一律,复杂的代码好几百行。 | ||
*/ | ||
|
||
export declare type ProgressProps = { | ||
/** | ||
* @description progress bar width | ||
* 进度条的宽度 | ||
* @type number | ||
* @default 399 | ||
*/ | ||
width?: number, | ||
/** | ||
* @description progress bar height | ||
* 进度条的高度 | ||
* @type number | ||
* @default 26.547 | ||
*/ | ||
height?: number, | ||
/** | ||
* @description progress value | ||
* 进度条的值 | ||
* @type number | ||
* @default 0 | ||
*/ | ||
value?: number, | ||
/** | ||
* @description progress value max | ||
* 进度条最大值 | ||
* @type number | ||
* @default 100 | ||
*/ | ||
max?: number, | ||
/** | ||
* @description display value | ||
* 是否显示进度值 | ||
* @type boolean | ||
* @default false | ||
*/ | ||
showInfo?: boolean, | ||
/** | ||
* @description info width | ||
* 进度值的宽度 | ||
* @type number | ||
* @default 44 | ||
*/ | ||
infoWidth?: number, | ||
/** | ||
* @description leaf height | ||
* 叶子的高度 | ||
* @type number | ||
* @default 28 | ||
*/ | ||
leafHeight?: number | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
:root { | ||
--m-progress-width: 300px; | ||
--m-progress-height: unset; | ||
} | ||
|
||
.m-progress, .m-progress-border { | ||
--m-progress-real-width: calc(var(--m-progress-width, 556px)); | ||
--m-progress-real-height: var(--m-progress-height, 37px); | ||
--m-progress-bg-width: var(--m-progress-width, 556px); | ||
--m-progress-bg-size: calc(var(--m-progress-bg-width) / 2) var(--m-progress-height); | ||
--m-progress-leaf-height: var(--m-progress-leaf-height, 28px); | ||
--m-progress-per-width: var(--m-progress-per-width, 80px); | ||
--m-progress-per-height: max(var(--m-progress-per-height, 20px), var(--m-progress-leaf-height)); | ||
--m-progress-per-font-size: var(--m-progress-per-font-size, 16px); | ||
} | ||
|
||
|
||
.m-progress-border { | ||
display: inline-block; | ||
width: var(--m-progress-real-width); | ||
} | ||
|
||
.m-progress-per { | ||
position: relative; | ||
display: inline-block; | ||
width: var(--m-progress-per-width); | ||
height: var(--m-progress-per-height); | ||
line-height: var(--m-progress-per-height); | ||
top: calc(var(--m-progress-per-height) * 0.4); | ||
font-size: var(--m-progress-per-font-size); | ||
font-weight: bold; | ||
|
||
& img, & span { | ||
float: right; | ||
} | ||
} | ||
|
||
.m-progress-leaf { | ||
height: var(--m-progress-leaf-height); | ||
} | ||
|
||
.m-progress { | ||
width: var(--m-progress-real-width); | ||
height: var(--m-progress-real-height); | ||
-webkit-appearance: none; | ||
|
||
&::-webkit-progress-bar { | ||
background: url('./assets/bamboo_bg.webp') repeat-x; | ||
background-size: var(--m-progress-bg-size); | ||
} | ||
|
||
&::-webkit-progress-value { | ||
background: url('./assets/bamboo.webp') repeat-x; | ||
background-size: var(--m-progress-bg-size); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/** | ||
* @description progress hook | ||
* @author 阿怪 | ||
* @date 2023/4/23 01:39 | ||
* @version v1.0.0 | ||
* | ||
* 江湖的业务千篇一律,复杂的代码好几百行。 | ||
*/ | ||
import { ProgressProps } from './index'; | ||
// @ts-ignore todo fix this | ||
import leafPng from './assets/leaf.webp'; | ||
import { isEmpty, notEmpty } from '../../../tools'; | ||
import { Options } from '../../../compositions/common/defineCore.ts'; | ||
|
||
export const BASE_SIZE = { | ||
BG: { W: 556, H: 37 }, | ||
LEAF: { W: 95, H: 109 }, | ||
}; | ||
|
||
const W2H = BASE_SIZE.BG.W / BASE_SIZE.BG.H; | ||
const LEAF_W2H = BASE_SIZE.LEAF.W / BASE_SIZE.LEAF.H; | ||
|
||
const getSize = (w?: number, h?: number, w2h = W2H) => { | ||
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<{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. try this: export function useProgress(props:ProgressProps) |
||
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<typeof getProgressInfo>) => { | ||
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, | ||
}; | ||
|
||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. defineCore in vue version has some "historical reasons". |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 any[]> = T extends [infer H, ...infer R] | ||
? H extends undefined | ||
? IsAllUndefined<R> | ||
: false | ||
: true; | ||
|
||
interface OptionsNotEmpty<P, V, E> { | ||
props: Required<P>; | ||
value: { [K in keyof V]: React.MutableRefObject<V[K]>; }; | ||
event: E; | ||
} | ||
|
||
type CoreArguments = keyof OptionsNotEmpty<any, any, any>; | ||
type AnyArguments = { | ||
[K in CoreArguments]?: any | ||
} | ||
|
||
type DefinedKeys<T extends AnyArguments> = { [K in keyof T]: T[K] extends undefined ? never : K }[keyof T]; | ||
type UndefinedKeys<T extends AnyArguments> = Exclude<keyof CoreArguments, DefinedKeys<T>>; | ||
|
||
export type OptionsKeys< | ||
A extends AnyArguments, | ||
P, V, E, | ||
DK extends string | number | symbol = DefinedKeys<A>, | ||
UK extends string | number | symbol = UndefinedKeys<A> | ||
> = { | ||
[K in DK & keyof OptionsNotEmpty<P, V, E>]: OptionsNotEmpty<P, V, E>[K]; | ||
} & { | ||
[K in UK & keyof OptionsNotEmpty<P, V, E>]-?: OptionsNotEmpty<P, V, E>[K]; | ||
} | ||
|
||
export type Options< | ||
K extends AnyArguments, | ||
P = K['props'], | ||
V = K['value'], | ||
E = K['event'], | ||
> = | ||
IsAllUndefined<[P, V, E]> extends true | ||
? OptionsEmpty | ||
: OptionsKeys<K, P, V, E>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should
value
andmax
use twouseEffect
?Their changes don't seem to affect each other.