From 4ef31630ef7f1b32d64b4bab23796e0aefdef5b3 Mon Sep 17 00:00:00 2001
From: panyushan <1193345664@qq.com>
Date: Thu, 5 Jan 2023 18:18:34 +0800
Subject: [PATCH 1/4] =?UTF-8?q?feat:=20rate=E7=BB=84=E4=BB=B6=E5=88=9D?=
=?UTF-8?q?=E6=AD=A5=E5=B8=83=E5=B1=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/IconFont/icon.stories.tsx | 42 ++++++++--------
src/components/IconFont/index.tsx | 4 +-
src/components/Rate/_style.scss | 25 ++++++++++
src/components/Rate/index.tsx | 62 ++++++++++++++++++++++++
src/components/Rate/rate.stories.tsx | 10 ++++
src/styles/_reboot.scss | 1 +
src/styles/index.scss | 3 ++
7 files changed, 124 insertions(+), 23 deletions(-)
create mode 100644 src/components/Rate/_style.scss
create mode 100644 src/components/Rate/index.tsx
create mode 100644 src/components/Rate/rate.stories.tsx
diff --git a/src/components/IconFont/icon.stories.tsx b/src/components/IconFont/icon.stories.tsx
index 60d8759..2bf0848 100644
--- a/src/components/IconFont/icon.stories.tsx
+++ b/src/components/IconFont/icon.stories.tsx
@@ -3,33 +3,33 @@ import { storiesOf } from "@storybook/react";
// import { action } from "@storybook/addon-actions";
// import { withInfo } from '@storybook/addon-info'
-import IconFont from "./index";
+import Icon from "./index";
const IconFontComp = () => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
-const SpinIconFont = () => ;
+const SpinIconFont = () => ;
storiesOf("Icon图标", module)
.add("IconFont", IconFontComp)
diff --git a/src/components/IconFont/index.tsx b/src/components/IconFont/index.tsx
index 37d78d1..72cf1c9 100644
--- a/src/components/IconFont/index.tsx
+++ b/src/components/IconFont/index.tsx
@@ -32,7 +32,7 @@ function createScript() {
* import { Icon } from 'jadedui'
* ~~~
*/
-const IconFont: FC = (props) => {
+const Icon: FC = (props) => {
const { type, color, spin = false, ...restProps } = props;
createScript();
@@ -51,4 +51,4 @@ const IconFont: FC = (props) => {
);
};
-export default IconFont;
+export default Icon;
diff --git a/src/components/Rate/_style.scss b/src/components/Rate/_style.scss
new file mode 100644
index 0000000..2bd95b3
--- /dev/null
+++ b/src/components/Rate/_style.scss
@@ -0,0 +1,25 @@
+.dui-rate {
+ display: flex;
+
+ .dui-rate-star:not(:last-child) {
+ margin-right: 8px;
+ }
+
+ .dui-rate-star {
+ position: relative;
+
+ .dui-rate-star-first {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 50%;
+ height: 100%;
+ overflow: hidden;
+ opacity: 0;
+
+ // &:hover{
+ // color: #fadb14;
+ // }
+ }
+ }
+}
diff --git a/src/components/Rate/index.tsx b/src/components/Rate/index.tsx
new file mode 100644
index 0000000..7f80759
--- /dev/null
+++ b/src/components/Rate/index.tsx
@@ -0,0 +1,62 @@
+import React from "react"; // , { ReactNode }
+import classnames from "classnames";
+import Icon from "../IconFont";
+
+export type OrientationType = "left" | "right" | "center";
+
+export interface RateProps {
+ /** 评分样式类 */
+ className?: string;
+ /** 评分样式对象 */
+ style?: React.CSSProperties;
+ /** 是否允许半选 */
+ allowHalf?: boolean;
+}
+
+/**
+ * Rate 评分
+ * 对评价进行展示
+ * 对事物进行快速的评级操作
+ * ### 引用方法
+ *
+ * ~~~js
+ * import { Rate } from 'jadedui'
+ * ~~~
+ */
+const Rate: React.FC = (props) => {
+ const { className, allowHalf } = props;
+ console.log("allowHalf: ", allowHalf);
+ const classNames = classnames("dui-rate", className);
+
+ return (
+
+ {new Array(5).fill("").map(() => {
+ return (
+ -
+
+
+
+
+
+
+
+ );
+ })}
+
+ );
+};
+
+// Divider.defaultProps = {
+// plain: false,
+// orientation: "center",
+// type: "horizontal",
+// dashed: false,
+// };
+
+export default Rate;
diff --git a/src/components/Rate/rate.stories.tsx b/src/components/Rate/rate.stories.tsx
new file mode 100644
index 0000000..45bc6d8
--- /dev/null
+++ b/src/components/Rate/rate.stories.tsx
@@ -0,0 +1,10 @@
+import React from "react";
+import { storiesOf } from "@storybook/react";
+// import { action } from "@storybook/addon-actions";
+// import { withInfo } from '@storybook/addon-info'
+
+import Rate from "./index";
+
+const defaultRate = () => ;
+
+storiesOf("Rate 评分", module).add("默认 Rate", defaultRate);
diff --git a/src/styles/_reboot.scss b/src/styles/_reboot.scss
index 4f782d4..403bbd4 100644
--- a/src/styles/_reboot.scss
+++ b/src/styles/_reboot.scss
@@ -150,6 +150,7 @@ address {
ol,
ul {
padding-left: 2rem;
+ list-style: none;
}
ol,
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 3374646..3bc37db 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -28,3 +28,6 @@
//Divider
@import "../components/Divider/style";
+
+//Rate
+@import "../components/Rate/style";
From e86e6c1018d8c67e2e1b71590d6f143b64d409b2 Mon Sep 17 00:00:00 2001
From: panyushan <1193345664@qq.com>
Date: Fri, 6 Jan 2023 18:30:54 +0800
Subject: [PATCH 2/4] =?UTF-8?q?perf:=20feat:=20rate=E7=BB=84=E4=BB=B6?=
=?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=B8=83=E5=B1=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/Rate/_style.scss | 4 ---
src/components/Rate/index.tsx | 51 ++++++++++++++++++++++++++++-----
2 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/src/components/Rate/_style.scss b/src/components/Rate/_style.scss
index 2bd95b3..eb78e77 100644
--- a/src/components/Rate/_style.scss
+++ b/src/components/Rate/_style.scss
@@ -16,10 +16,6 @@
height: 100%;
overflow: hidden;
opacity: 0;
-
- // &:hover{
- // color: #fadb14;
- // }
}
}
}
diff --git a/src/components/Rate/index.tsx b/src/components/Rate/index.tsx
index 7f80759..ddd5f66 100644
--- a/src/components/Rate/index.tsx
+++ b/src/components/Rate/index.tsx
@@ -1,4 +1,4 @@
-import React from "react"; // , { ReactNode }
+import React, { useState } from "react"; // , { ReactNode }
import classnames from "classnames";
import Icon from "../IconFont";
@@ -26,20 +26,57 @@ export interface RateProps {
const Rate: React.FC = (props) => {
const { className, allowHalf } = props;
console.log("allowHalf: ", allowHalf);
- const classNames = classnames("dui-rate", className);
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const [ids, setIds] = useState([0, 1, 2, 3, 4]);
+ const [pos, setPos] = useState({
+ curIndexLi: -1,
+ curIndexStar: -1,
+ });
+ // const [classNames,setClassNames] = useState>({
+ // 'dui-rate-star': true, // 基础类
+ // 'dui-rate-star-zero': false, // 0 星
+ // 'dui-rate-star-half': false, // 半星
+ // 'dui-rate-star-full': false, // 满星
+ // 'dui-rate-star-active': false, // 当前激活星
+ // })
+
+ const onMouseFirstEnter = (d: number, curStar: number) => {
+ console.log("onMouseFirstEnter");
+ const curIndex = ids.findIndex((id) => id == d);
+ console.log("curIndex: ", curIndex, curStar);
+ setPos({
+ curIndexLi: curIndex,
+ curIndexStar: curStar,
+ });
+ };
+
+ const renderClassNames = (key: number) => {
+ console.log("key: ", key);
+ let classNames = "dui-rate-star";
+ if (pos.curIndexLi === -1) {
+ classNames += " dui-rate-star-zero";
+ }
+ return classNames;
+ };
return (
-
- {new Array(5).fill("").map(() => {
+
+ {ids.map((key) => {
return (
- -
-
+
-
+
onMouseFirstEnter(key, 0)}
+ >
-
+
onMouseFirstEnter(key, 1)}
+ >
Date: Sun, 29 Jan 2023 18:14:16 +0800
Subject: [PATCH 3/4] =?UTF-8?q?perf:=20=E5=AE=8C=E5=96=84rate=E7=BB=84?=
=?UTF-8?q?=E4=BB=B6=2090%?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/Rate/_style.scss | 51 +++++++++++
src/components/Rate/index.tsx | 129 ++++++++++++++++++++-------
src/components/Rate/rate.stories.tsx | 15 +++-
src/styles/_variables.scss | 4 +
todoList.md | 1 +
5 files changed, 167 insertions(+), 33 deletions(-)
diff --git a/src/components/Rate/_style.scss b/src/components/Rate/_style.scss
index eb78e77..7e1122e 100644
--- a/src/components/Rate/_style.scss
+++ b/src/components/Rate/_style.scss
@@ -1,12 +1,18 @@
.dui-rate {
display: flex;
+ svg {
+ color: $rate-color-default;
+ font-size: 25px;
+ }
+
.dui-rate-star:not(:last-child) {
margin-right: 8px;
}
.dui-rate-star {
position: relative;
+ transition: all 0.2s;
.dui-rate-star-first {
position: absolute;
@@ -16,6 +22,51 @@
height: 100%;
overflow: hidden;
opacity: 0;
+ color: $rate-color-default;
+ font-size: 25px;
+ }
+
+ .dui-rate-star-second {
+ color: $rate-color-default;
+ font-size: 25px;
+ }
+ }
+
+ .dui-rate-star:hover {
+ transform: scale(1.1);
+ }
+
+ .dui-rate-star-disabled:hover {
+ transform: none;
+ }
+
+ .dui-rate-star.ant-rate-star-half {
+ .dui-rate-star-first {
+ opacity: 1;
+ color: $rate-color;
+
+ svg {
+ color: $rate-color;
+ }
+ }
+ }
+
+ .dui-rate-star.ant-rate-star-full {
+ .dui-rate-star-first {
+ opacity: 0;
+ color: $rate-color-default;
+
+ svg {
+ color: $rate-color-default;
+ }
+ }
+
+ .dui-rate-star-second {
+ color: $rate-color;
+
+ svg {
+ color: $rate-color;
+ }
}
}
}
diff --git a/src/components/Rate/index.tsx b/src/components/Rate/index.tsx
index ddd5f66..78d69e7 100644
--- a/src/components/Rate/index.tsx
+++ b/src/components/Rate/index.tsx
@@ -1,16 +1,23 @@
-import React, { useState } from "react"; // , { ReactNode }
+import React, { useEffect, useState } from "react";
+import type { ReactNode } from "react";
import classnames from "classnames";
import Icon from "../IconFont";
export type OrientationType = "left" | "right" | "center";
export interface RateProps {
- /** 评分样式类 */
+ /** 自定义样式类名 */
className?: string;
- /** 评分样式对象 */
+ /** 自定义样式对象 */
style?: React.CSSProperties;
- /** 是否允许半选 */
- allowHalf?: boolean;
+ /** 当前数,受控值 */
+ value?: number;
+ /** 默认值 */
+ defaultValue?: number;
+ /** 只读,无法进行交互 */
+ disabled?: boolean;
+ /** 自定义字符 */
+ character?: ReactNode | ((index: number) => ReactNode);
}
/**
@@ -24,63 +31,123 @@ export interface RateProps {
* ~~~
*/
const Rate: React.FC = (props) => {
- const { className, allowHalf } = props;
- console.log("allowHalf: ", allowHalf);
+ const { className, value, defaultValue, character, disabled } = props;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [ids, setIds] = useState([0, 1, 2, 3, 4]);
+ const [rateValue, setRateValue] = useState<[number, number]>([-1, -1]);
+ // const [rateDefaultValue,setRateDefaultValue] = useState<[number,number]>([-1,-1]);
const [pos, setPos] = useState({
curIndexLi: -1,
curIndexStar: -1,
+ isFocus: false,
});
- // const [classNames,setClassNames] = useState>({
- // 'dui-rate-star': true, // 基础类
- // 'dui-rate-star-zero': false, // 0 星
- // 'dui-rate-star-half': false, // 半星
- // 'dui-rate-star-full': false, // 满星
- // 'dui-rate-star-active': false, // 当前激活星
- // })
+ const cls = ["ant-rate-star-half", "ant-rate-star-full"];
+ if (
+ (value && typeof value !== "number") ||
+ (defaultValue && typeof defaultValue !== "number")
+ ) {
+ throw new Error("value or defaultValue must be a number!");
+ }
+
+ const initRate = () => {
+ if (value || defaultValue) {
+ const transValue = String(value || defaultValue).split(".");
+ const curIndexLi = Number(transValue[0]);
+ const curIndexStar = transValue[1]
+ ? Number(transValue[1]) >= 5
+ ? 0
+ : -1
+ : -1;
+ console.log("curIndexLi: ", curIndexLi);
+ console.log("curIndexStar: ", curIndexStar);
+ setRateValue([curIndexLi, curIndexStar]);
+ setPos({
+ curIndexLi,
+ curIndexStar,
+ isFocus: true,
+ });
+ }
+ };
+
+ useEffect(() => {
+ initRate();
+ }, [value]);
const onMouseFirstEnter = (d: number, curStar: number) => {
- console.log("onMouseFirstEnter");
+ if (disabled) return;
const curIndex = ids.findIndex((id) => id == d);
- console.log("curIndex: ", curIndex, curStar);
setPos({
+ ...pos,
curIndexLi: curIndex,
curIndexStar: curStar,
});
};
const renderClassNames = (key: number) => {
- console.log("key: ", key);
let classNames = "dui-rate-star";
+ if (disabled) classNames += " dui-rate-star-disabled";
if (pos.curIndexLi === -1) {
classNames += " dui-rate-star-zero";
+ } else {
+ if (key < pos.curIndexLi) {
+ classNames += " ant-rate-star-full";
+ return classNames;
+ }
+ if (key == pos.curIndexLi) {
+ classNames += " " + cls[pos.curIndexStar];
+ return classNames;
+ }
+ if (key > pos.curIndexLi) {
+ classNames += " dui-rate-star-zero";
+ }
}
+
return classNames;
};
+ const rateClickHandle = (type: string, key: number) => {
+ if (value || disabled) return;
+ onMouseFirstEnter(key, type === "first" ? 0 : 1);
+ setRateValue([key, type === "first" ? 0 : 1]);
+ setPos({
+ ...pos,
+ isFocus: true,
+ });
+ };
+
+ const onMouseLeave = () => {
+ if (disabled) return;
+ if (!pos.isFocus) {
+ onMouseFirstEnter(-1, -1);
+ } else {
+ onMouseFirstEnter(...rateValue);
+ }
+ };
+
+ const renderNode = (key: number) =>
+ typeof character === "function" ? character(key) : character;
+
return (
-
+
{ids.map((key) => {
return (
-
onMouseFirstEnter(key, 0)}
+ onClick={() => rateClickHandle("first", key)}
>
-
+ {renderNode(key)}
onMouseFirstEnter(key, 1)}
+ onClick={() => rateClickHandle("second", key)}
>
-
+ {renderNode(key)}
);
@@ -89,11 +156,9 @@ const Rate: React.FC = (props) => {
);
};
-// Divider.defaultProps = {
-// plain: false,
-// orientation: "center",
-// type: "horizontal",
-// dashed: false,
-// };
+Rate.defaultProps = {
+ character: ,
+ disabled: false,
+};
export default Rate;
diff --git a/src/components/Rate/rate.stories.tsx b/src/components/Rate/rate.stories.tsx
index 45bc6d8..3978ef4 100644
--- a/src/components/Rate/rate.stories.tsx
+++ b/src/components/Rate/rate.stories.tsx
@@ -7,4 +7,17 @@ import Rate from "./index";
const defaultRate = () => ;
-storiesOf("Rate 评分", module).add("默认 Rate", defaultRate);
+const characterRate = () => (
+ <>
+
+
+ 星} />
+ >
+);
+
+const disableRate = () => ;
+
+storiesOf("Rate 评分", module)
+ .add("Rate", defaultRate)
+ .add("只读 Rate", disableRate)
+ .add("自定义字符 Rate", characterRate);
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index a2ceb94..084c518 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -274,3 +274,7 @@ $alert-padding-x-right: 1rem !default;
$alert-font-color: #000000d9;
$alert-message-font-size: $font-size-base * 1.1 !default;
$alert-description-font-size: $font-size-base * 0.8 !default;
+
+// Rate
+$rate-color: $yellow !default;
+$rate-color-default: $gray-200 !default;
diff --git a/todoList.md b/todoList.md
index 722e641..f9a32d4 100644
--- a/todoList.md
+++ b/todoList.md
@@ -4,5 +4,6 @@
- 图片水印
canvas、mutationObserver
- Flip 动画思路
+- 滑动验证码
From ea5bbafd6d57723240f9deeb0f4cc19956c27915 Mon Sep 17 00:00:00 2001
From: panyushan <1193345664@qq.com>
Date: Mon, 30 Jan 2023 10:28:33 +0800
Subject: [PATCH 4/4] perf: complete rate component
---
src/components/Rate/index.tsx | 6 +++++-
src/components/Rate/rate.stories.tsx | 7 ++++++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/components/Rate/index.tsx b/src/components/Rate/index.tsx
index 78d69e7..e4d2039 100644
--- a/src/components/Rate/index.tsx
+++ b/src/components/Rate/index.tsx
@@ -18,6 +18,8 @@ export interface RateProps {
disabled?: boolean;
/** 自定义字符 */
character?: ReactNode | ((index: number) => ReactNode);
+ /** 选择时的回调 */
+ onChange?: (value: number) => void;
}
/**
@@ -31,7 +33,8 @@ export interface RateProps {
* ~~~
*/
const Rate: React.FC = (props) => {
- const { className, value, defaultValue, character, disabled } = props;
+ const { className, value, defaultValue, character, disabled, onChange } =
+ props;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [ids, setIds] = useState([0, 1, 2, 3, 4]);
const [rateValue, setRateValue] = useState<[number, number]>([-1, -1]);
@@ -113,6 +116,7 @@ const Rate: React.FC = (props) => {
...pos,
isFocus: true,
});
+ onChange && onChange(type === "first" ? key + 0.5 : key + 1);
};
const onMouseLeave = () => {
diff --git a/src/components/Rate/rate.stories.tsx b/src/components/Rate/rate.stories.tsx
index 3978ef4..d04beb7 100644
--- a/src/components/Rate/rate.stories.tsx
+++ b/src/components/Rate/rate.stories.tsx
@@ -5,7 +5,12 @@ import { storiesOf } from "@storybook/react";
import Rate from "./index";
-const defaultRate = () => ;
+const defaultRate = () => {
+ const onChange = (v: any) => {
+ console.log("v: ", v);
+ };
+ return ;
+};
const characterRate = () => (
<>