diff --git a/package-lock.json b/package-lock.json index fe19286..ea2de7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "license": "ISC", "dependencies": { "@types/uuid": "^9.0.1", + "@uiw/react-color-alpha": "^1.1.3", + "classnames": "^2.3.2", "framer-motion": "^8.5.5", "uuid": "^9.0.0" }, @@ -39,6 +41,7 @@ "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "less-loader": "^11.1.0", + "moment": "^2.29.4", "postcss": "^8.4.21", "react": "^18.2.0", "rollup": "^3.19.1", @@ -1787,7 +1790,6 @@ "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -3493,6 +3495,38 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, + "node_modules/@uiw/color-convert": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-1.1.3.tgz", + "integrity": "sha512-/ZtvW4YWfM9vzrbZOmlSY3DQ0mll8D6uY87yITJnDmOh50qOpiZPC2/l3ReoUxbyS6xLcn4/ba1DzH5BEx6dCg==", + "peerDependencies": { + "@babel/runtime": ">=7.19.0" + } + }, + "node_modules/@uiw/react-color-alpha": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@uiw/react-color-alpha/-/react-color-alpha-1.1.3.tgz", + "integrity": "sha512-JenSKVRuDbScq0FUeIVVkIuP3x3SMdyqlwh6ik00wyvHQiaq7W1srihGtlRKlJKrignzELNprIppulI2euwvCA==", + "dependencies": { + "@uiw/color-convert": "1.1.3", + "@uiw/react-drag-event-interactive": "1.1.3" + }, + "peerDependencies": { + "@babel/runtime": ">=7.19.0", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@uiw/react-drag-event-interactive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@uiw/react-drag-event-interactive/-/react-drag-event-interactive-1.1.3.tgz", + "integrity": "sha512-PHbXPQELjh3TaU8m/wFblbQyiKujb/hHfs94PKfB69YnS7uZPKCMsasbxm08AmMVYSZ92MG1Ip/vIKVoAxEEaQ==", + "peerDependencies": { + "@babel/runtime": ">=7.19.0", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/@vue/compiler-core": { "version": "3.2.47", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", @@ -4883,6 +4917,11 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/clean-css": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", @@ -10290,6 +10329,15 @@ "node": ">=10" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11765,8 +11813,7 @@ "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regenerator-transform": { "version": "0.15.1", @@ -15489,7 +15536,6 @@ "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "dev": true, "requires": { "regenerator-runtime": "^0.13.11" } @@ -16857,6 +16903,27 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, + "@uiw/color-convert": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-1.1.3.tgz", + "integrity": "sha512-/ZtvW4YWfM9vzrbZOmlSY3DQ0mll8D6uY87yITJnDmOh50qOpiZPC2/l3ReoUxbyS6xLcn4/ba1DzH5BEx6dCg==", + "requires": {} + }, + "@uiw/react-color-alpha": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@uiw/react-color-alpha/-/react-color-alpha-1.1.3.tgz", + "integrity": "sha512-JenSKVRuDbScq0FUeIVVkIuP3x3SMdyqlwh6ik00wyvHQiaq7W1srihGtlRKlJKrignzELNprIppulI2euwvCA==", + "requires": { + "@uiw/color-convert": "1.1.3", + "@uiw/react-drag-event-interactive": "1.1.3" + } + }, + "@uiw/react-drag-event-interactive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@uiw/react-drag-event-interactive/-/react-drag-event-interactive-1.1.3.tgz", + "integrity": "sha512-PHbXPQELjh3TaU8m/wFblbQyiKujb/hHfs94PKfB69YnS7uZPKCMsasbxm08AmMVYSZ92MG1Ip/vIKVoAxEEaQ==", + "requires": {} + }, "@vue/compiler-core": { "version": "3.2.47", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", @@ -17996,6 +18063,11 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "clean-css": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", @@ -22060,6 +22132,12 @@ "brace-expansion": "^2.0.1" } }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -23084,8 +23162,7 @@ "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regenerator-transform": { "version": "0.15.1", diff --git a/package.json b/package.json index 6f4b3ba..b216125 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "less-loader": "^11.1.0", + "moment": "^2.29.4", "postcss": "^8.4.21", "react": "^18.2.0", "rollup": "^3.19.1", @@ -76,7 +77,9 @@ }, "dependencies": { "@types/uuid": "^9.0.1", + "@uiw/react-color-alpha": "^1.1.3", + "classnames": "^2.3.2", "framer-motion": "^8.5.5", "uuid": "^9.0.0" } -} \ No newline at end of file +} diff --git a/rollup.config.mjs b/rollup.config.mjs index b8ca7dc..66ef197 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -68,6 +68,6 @@ export default [ input: "dist/esm/types/index.d.ts", output: [{ file: "dist/index.d.ts", format: "esm" }], plugins: [dts.default()], - external: [/\.less$/], // telling rollup anything that is .css aren't part of type exports + external: [/\.less$/], // telling rollup anything that is .css aren't part of type exports }, -] \ No newline at end of file +] diff --git a/src/_test.css b/src/_test.css new file mode 100644 index 0000000..7da3761 --- /dev/null +++ b/src/_test.css @@ -0,0 +1,9 @@ +:root { + --background: #ebedff; + --blueDark: #5c6dff; + --fadedGary: #818181; + --white: #ffffff; + --black: #000000; + --white-shadow: 0px 0px 13px 5px rgba(173, 182, 255, 0.25); +} + diff --git a/src/_test.less b/src/_test.less new file mode 100644 index 0000000..718ed92 --- /dev/null +++ b/src/_test.less @@ -0,0 +1,5 @@ +@import '../src/common/style/index.less'; + +a{ + text-decoration: none; +} diff --git a/src/_test.tsx b/src/_test.tsx index b22835b..16141ba 100644 --- a/src/_test.tsx +++ b/src/_test.tsx @@ -1,17 +1,45 @@ +import React, { useEffect, useRef, useState } from "react"; +import ReactDom from "react-dom"; +import Modal from "./components/modal/modal"; +import Upload from "./components/upload/upload"; +import Tab from "./components/tab/tab"; +import * as GOJI from "goji_ui"; +import DropDown from "./components/dropDown"; +import Button from "./components/button/button"; +import "./_test.less"; +import Alpha from "@uiw/react-color-alpha"; +import Input from "./components/input/input"; +import useCountdown from "./components/countdown"; -import React, { useState } from 'react'; -import ReactDom from 'react-dom' -import Modal from './components/modal/modal'; -import Upload from './components/upload/upload'; -import Tab from './components/tab/tab'; +function App() { + const [visible, setVisible] = useState(false); + const [ev, setEv] = useState(false); + const [modalVisible, setModalVisible] = useState(false); + const [hsva, setHsva] = useState({ h: 0, s: 0, v: 20, a: 1 }); + const [value, setValue] = useState(10); + const { date } = useCountdown(3); -import * as GOJI from 'goji_ui' + const handleClick = (e: unknown) => { + setValue(e?.target.value); + console.log("e", e?.target.value); + }; -function App() { - const [visible, setVisible] = useState(false) - const [ev, setEv] = useState(false) - return
- {/* +
{date}
+ { + console.log("kdsk"); + }} + onFocus={() => { + console.log("sssss"); + }} + /> + {/* 这是扩展的内容
} items={[ @@ -27,77 +55,210 @@ function App() { } ]} /> */} +

test

+ + { + setEv(true); + }} + hiddenStyle={{ + height: "0px", + overflow: "hidden", + }} + tabContentVisible={ev} + extSelector={'[aria-label="tab"]'} + extension={ +
{ + setEv(!ev); + }} + className="ext" + > + 这是扩展的内容 +
+ } + items={[ + { + title: "tab1", + key: "tab1", + children:
tab1
, + }, + { + title: "tab2", + key: "tab2", + children:
tab2
, + }, + ]} + /> + { + setVisible(false); + }} + visible={visible} + > +
+ how to set default value for typescript interface field + +
+
+ { + for (var i = 0; i < f.length; i++) { + console.log(f[i].name); + } + return new Promise((r, j) => { + setTimeout(() => { + r(f); + }, 1000); + }); + }} + valueFilter={({ response }) => { + return (response as Record).url; + }} + onComplete={(res: any[]) => { + console.log(res); + }} + > + 请选择文件 + + {/* { + setModalVisible(!modalVisible); + }} + position="topRight" + width={150} + modelContent={[ + { + id: "1", + label: "first Item", + }, + { + id: "2", + label: "second Item", + }, + ]} + // className={"modless"} + > + SHOW MODEL + */} + { + setModalVisible(!modalVisible); + }} + position="bottom" + width={150} + modelContent={"KDSK"} + icons={[ + + + + , + + + + , + ]} + // className={"modless"} + > + SHOW MODEL + + + + + + + + + -

test

- - { - setEv(true) - }} - hiddenStyle={{ - height: '0px', - overflow: 'hidden' - }} - tabContentVisible={ev} - extSelector={'[aria-label="tab"]'} - extension={
{ setEv(!ev) }} className="ext">这是扩展的内容
} - items={[ - { - title: "tab1", - key: "tab1", - children:
tab1
- }, - { - title: "tab2", - key: "tab2", - children:
tab2
- } - ]} - /> - - { - setVisible(false) - }} - visible={visible} - > -
- how to set default value for typescript interface field - -
-
+ + - { - for (var i = 0; i < f.length; i++) { - console.log(f[i].name) - } - return new Promise((r, j) => { - setTimeout(() => { - r(f) - }, 1000); - }) - }} + - valueFilter={({ response }) => { - return (response as Record).url - }} - onComplete={(res: any[]) => { - console.log(res) - }} - > - 请选择文件 - - + <> + { + setHsva({ ...hsva, ...newAlpha }); + }} + background={`linear-gradient(to right,rgb(218,44,2) 0%, rgb(253,253,32)20%, rgb(255,255,255) 35%, rgb(255,255,255) 60% ,#D0F5FB 65%, rgb(98,165,218) 100%)`} + /> + {/*
+ {JSON.stringify(hsva)} +
*/} + + + ); } -ReactDom.render(, document.getElementById("app")) \ No newline at end of file +ReactDom.render(, document.getElementById("app")); diff --git a/src/common/style/index.css b/src/common/style/index.css new file mode 100644 index 0000000..98383e1 --- /dev/null +++ b/src/common/style/index.css @@ -0,0 +1,8 @@ +:root { + --background: #ebedff; + --blueDark: #5c6dff; + --fadedGary: #818181; + --white: #ffffff; + --black: #000000; + --white-shadow: 0px 0px 13px 5px rgba(173, 182, 255, 0.25); +} diff --git a/src/common/style/index.less b/src/common/style/index.less new file mode 100644 index 0000000..97b05a3 --- /dev/null +++ b/src/common/style/index.less @@ -0,0 +1,9 @@ +// :root 伪类选择器 匹配文档树的根节点 +:root { + --background: #ebedff; + --blueDark: #5c6dff; + --fadedGary: #818181; + --white: #ffffff; + --black: #000000; + --white-shadow: 0px 0px 13px 5px rgba(173, 182, 255, 0.25); +} diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx new file mode 100644 index 0000000..9855c5f --- /dev/null +++ b/src/components/button/button.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import "./index.less"; +import classnames from "classnames"; + +//如何继承 DOMAttributes + +type type = "primary" | "link" | "dashed" | "text" | "disable"; +type shape = "round" | "circle"; +type iconPos = "left" | "right"; + +interface IButton extends React.ButtonHTMLAttributes { + types?: type | undefined; + style?: React.CSSProperties | undefined; + className?: string | undefined; + children?: React.ReactNode | undefined; + shape?: shape | undefined; + icon?: React.ReactNode | undefined; + iconPos?: iconPos | undefined; + herf?: string | undefined; + disabled?: boolean | undefined; +} + +const Button = (props: IButton) => { + const { types, style, className, children, shape, icon, iconPos, disabled } = + props; + + const getBtnClass = () => { + switch (types) { + case "primary": + return "primaryButton gojiButton"; + case "dashed": + return "dashedButton gojiButton"; + case "link": + return "linkButton gojiButton"; + case "text": + return "textButton gojiButton"; + case "disable": + return "disable gojiButton"; + default: + return "gojiButton"; + } + }; + + const shapes = () => { + switch (shape) { + case "circle": + return "circle"; + case "round": + return "round"; + default: + break; + } + }; + + return ( + + ); +}; + +export default Button; diff --git a/src/components/button/index.css b/src/components/button/index.css new file mode 100644 index 0000000..2779de2 --- /dev/null +++ b/src/components/button/index.css @@ -0,0 +1,61 @@ +.gojiButton { + display: inline-block; + font-size: 14px; + padding: 0px 15px; + border-radius: 6px; + cursor: pointer; + background-color: #fff; + color: #000; + text-align: center; + border: 1px solid; + margin: 6px; + line-height: 30px; +} +.gojiButton:hover { + color: red; +} +.primaryButton { + font-size: 14px; + padding: 0px 15px; + border-radius: 6px; + cursor: pointer; + background-color: #fff; + list-style: none; + color: rgba(0, 0, 0, 0.88); + text-align: center; + border: 1px solid; +} +.primaryButton:hover { + background-color: green !important; + color: #fff !important; +} +.linkButton { + border: none; + color: green; +} +.linkButton:hover { + color: #1f77db !important; +} +.textButton { + border: none; +} +.textButton:hover { + background-color: #b3b4b4; + color: #000; +} +.round { + border-radius: 40px; +} +.circle { + border-radius: 50%; +} +.dashedButton { + border: 1px dashed; +} +.disableButton { + cursor: not-allowed !important; + border-color: #d9d9d9; + color: rgba(0, 0, 0, 0.25); + background-color: rgba(0, 0, 0, 0.04); + box-shadow: none; +} diff --git a/src/components/button/index.less b/src/components/button/index.less new file mode 100644 index 0000000..5cd6cdc --- /dev/null +++ b/src/components/button/index.less @@ -0,0 +1,72 @@ +.gojiButton { + display: inline-block; + font-size: 14px; + padding: 0px 15px; + border-radius: 6px; + cursor: pointer; + background-color: #fff; + color: #000; + text-align: center; + border: 1px solid; + margin: 6px; + line-height: 30px; +} + +.gojiButton:hover { + color: red; +} + +.primaryButton { + font-size: 14px; + padding: 0px 15px; + border-radius: 6px; + cursor: pointer; + background-color: #fff; + list-style: none; + color: rgba(0, 0, 0, 0.88); + text-align: center; + border: 1px solid; +} + +.primaryButton:hover { + background-color: green !important; + color: #fff !important; +} + +.linkButton { + border: none; + color: green; +} + +.linkButton:hover { + color: rgb(31, 119, 219) !important; +} + +.textButton { + border: none; +} + +.textButton:hover { + background-color: rgb(179, 180, 180); + color: #000; +} + +.round { + border-radius: 40px; +} + +.circle { + border-radius: 50%; +} + +.dashedButton { + border: 1px dashed; +} + +.disableButton { + cursor: not-allowed !important; + border-color: #d9d9d9; + color: rgba(0, 0, 0, 0.25); + background-color: rgba(0, 0, 0, 0.04); + box-shadow: none; +} diff --git a/src/components/countdown/index.tsx b/src/components/countdown/index.tsx new file mode 100644 index 0000000..f2025ac --- /dev/null +++ b/src/components/countdown/index.tsx @@ -0,0 +1,27 @@ +import { useEffect, useRef, useState } from "react"; + +export default function useCountdown(time: number) { + const [date, setDate] = useState(time); + const timeRef = useRef(); + + useEffect(() => { + //timeRef.current是定时器 + timeRef.current = setInterval(() => { + setDate((t) => t - 1); + }, 1000); + + return () => { + clearInterval(timeRef.current); + }; + }, []); + + useEffect(() => { + if (date <= 0) { + clearInterval(timeRef.current); + } + }, [date]); + + return { + date, + }; +} diff --git a/src/components/dropDown/dropDown.css b/src/components/dropDown/dropDown.css new file mode 100644 index 0000000..ae20d94 --- /dev/null +++ b/src/components/dropDown/dropDown.css @@ -0,0 +1,156 @@ +.dropDown { + display: flex; + justify-content: space-between; + align-items: center; + box-shadow: var(--white-shadow); + padding: 12px 24px; + cursor: pointer; + position: relative; + border-radius: 5px; +} +.dropDown .dropDownOption { + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); + padding: 2px; +} +.dropDown .dropDownOption .dropDownOptionItem { + padding: 12px; + color: var(--black); +} +.dropDown .dropDownOption .dropDownOptionItem:hover { + background: var(--background); + color: var(--fadedGary); +} +.dropDown .PositionTop { + position: absolute; + top: -12px; + left: 0; + transform: translateY(-100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); +} +.dropDown .PositionTop::after { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 45%; + z-index: 99; +} +.dropDown .PositionTop::before { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 45%; + z-index: 99; +} +.dropDown .PositionTopRight { + position: absolute; + top: -12px; + left: 0; + transform: translateY(-100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); +} +.dropDown .PositionTopRight::after { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 9px; + z-index: 99; +} +.dropDown .PositionTopRight::before { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 9px; + z-index: 99; +} +.dropDown .PositionBottom { + position: absolute; + left: 0; + bottom: -10px; + transform: translateY(100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); +} +.dropDown .PositionBottom::after { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: transparent transparent #ffffff transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -14px; + right: 45%; + z-index: 99; +} +.dropDown .PositionBottom::before { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: transparent transparent #ffffff transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -14px; + right: 45%; + z-index: 99; +} +.dropDown .PositionBottomRight { + position: absolute; + left: 0; + bottom: -10px; + transform: translateY(100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); +} +.dropDown .PositionBottomRight::after { + width: 0; + height: 0; + content: ""; + border-width: 6px; + border-color: transparent transparent #a07676 transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -11px; + right: 9px; + z-index: 99; +} +.dropDown .PositionBottomRight::before { + width: 0; + height: 0; + content: ""; + border-width: 6px; + border-color: transparent transparent #884b4b transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -11px; + right: 9px; + z-index: 99; +} diff --git a/src/components/dropDown/dropDown.less b/src/components/dropDown/dropDown.less new file mode 100644 index 0000000..d2fc826 --- /dev/null +++ b/src/components/dropDown/dropDown.less @@ -0,0 +1,170 @@ +.dropDown { + display: flex; + justify-content: space-between; + align-items: center; + box-shadow: var(--white-shadow); + padding: 12px 24px; + cursor: pointer; + position: relative; + border-radius: 5px; + + .dropDownOption { + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); + padding: 2px; + .dropDownOptionItem { + padding: 12px; + color: var(--black); + } + + .dropDownOptionItem:hover { + background: var(--background); + color: var(--fadedGary); + } + } + + .PositionTop { + position: absolute; + top: -12px; + left: 0; + transform: translateY(-100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); + } + + .PositionTop::after { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 45%; + z-index: 99; + } + + .PositionTop::before { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 45%; + z-index: 99; + } + + .PositionTopRight { + position: absolute; + top: -12px; + left: 0; + transform: translateY(-100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); + } + + .PositionTopRight::after { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 9px; + z-index: 99; + } + + .PositionTopRight::before { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: #ffffff transparent transparent transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: 91px; + right: 9px; + z-index: 99; + } + + .PositionBottom { + position: absolute; + left: 0; + bottom: -10px; + transform: translateY(100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); + } + + .PositionBottom::after { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: transparent transparent #ffffff transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -14px; + right: 45%; + z-index: 99; + } + + .PositionBottom::before { + width: 0; + height: 0; + content: ""; + border-width: 8px; + border-color: transparent transparent #ffffff transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -14px; + right: 45%; + z-index: 99; + } + + .PositionBottomRight { + position: absolute; + left: 0; + bottom: -10px; + transform: translateY(100%); + background: var(--white); + width: 100%; + box-shadow: var(--white-shadow); + } + + .PositionBottomRight::after { + width: 0; + height: 0; + content: ""; + border-width: 6px; + border-color: transparent transparent #a07676 transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -11px; + right: 9px; + z-index: 99; + } + + .PositionBottomRight::before { + width: 0; + height: 0; + content: ""; + border-width: 6px; + border-color: transparent transparent #884b4b transparent; + border-style: dashed dashed solid dashed; + position: absolute; + top: -11px; + right: 9px; + z-index: 99; + } +} diff --git a/src/components/dropDown/index.tsx b/src/components/dropDown/index.tsx new file mode 100644 index 0000000..cdd777d --- /dev/null +++ b/src/components/dropDown/index.tsx @@ -0,0 +1,90 @@ +import React, { ReactNode, useState } from "react"; +import { createPortal } from "react-dom"; +import "./dropDown.less"; +import { v4 as uuidv4 } from "uuid"; +type trigger = "click" | "hover"; +type position = "bottomRight" | "bottom" | "top" | "topRight"; + +type IDropDown = { + trigger: trigger; + style?: React.CSSProperties; + className?: string; + children?: ReactNode; + visible?: boolean; + setVisible?: any; + modelContent?: ReactNode; + width?: number; + position?: position; + onChangeVisible: () => void; + icons: ReactNode[]; +}; + +const DropDown: React.FC = ({ + trigger, + style, + width, + className, + children, + visible, + modelContent, + position, + icons, + setVisible, + onChangeVisible, +}) => { + // const dropDown = document.getElementById("dropDown") as HTMLElement; + + const [optionValue, setOptionValue] = useState(children); + + const fixedPosition = (position: position) => { + switch (position) { + case "bottom": + return "PositionBottom"; + case "bottomRight": + return "PositionBottomRight"; + case "top": + return "PositionTop"; + case "topRight": + return "PositionTopRight"; + default: + break; + } + }; + + return ( + <> + {trigger === "click" ? ( +
onChangeVisible()} + style={{ width: `${width}px`, ...style }} + > + {optionValue} + {visible ? icons[0] : icons[1]} + {visible && ( +
+ {modelContent} +
+ )} +
+ ) : ( +
setVisible(true)} + onMouseLeave={() => setVisible(false)} + > + {optionValue} + {visible ? icons[0] : icons[1]} + {visible && ( +
+ {modelContent} +
+ )} +
+ )} + + ); +}; + +export default DropDown; diff --git a/src/components/dropDown/model.tsx b/src/components/dropDown/model.tsx new file mode 100644 index 0000000..855e68a --- /dev/null +++ b/src/components/dropDown/model.tsx @@ -0,0 +1,50 @@ +import classNames from "classnames"; +import React from "react"; +import { createPortal } from "react-dom"; +import styles from "./dropDown.module.less"; + +interface IModel { + modelContent: object[] | undefined; + dropDown?: HTMLElement | undefined; + width?: number | undefined; + fixedPosition?: any; + position?: string | undefined; + className?: string | undefined; + style?: React.CSSProperties; +} + +const Model: React.FC = ({ + modelContent, + dropDown, + width, + fixedPosition, + position, + className, + style, +}) => { + return ( + <> + {createPortal( +
+
    + {modelContent?.map((item) => { + return ( +
  • + {item?.label} +
  • + ); + })} +
+
, + dropDown + )} + + ); +}; + +export default Model; diff --git a/src/components/input/index.css b/src/components/input/index.css new file mode 100644 index 0000000..0accd21 --- /dev/null +++ b/src/components/input/index.css @@ -0,0 +1,36 @@ +.inputBox { + border: 1px solid #036df7; + display: inline; + padding: 4px; + border-radius: 5px; + margin: 10px; +} +.inputBox input { + outline: none; + border: none; + height: 19px; +} +.inputBox .numberLimit { + font-size: 14px; +} +.action { + border: 1px solid red; + display: inline; + padding: 4px; + border-radius: 5px; + margin: 10px; +} +.action input { + outline: none; + border: none; + height: 19px; +} +.action .numberLimit { + font-size: 14px; +} +.message { + margin: 0; + padding: 0; + color: red; + font-size: 12px; +} diff --git a/src/components/input/index.less b/src/components/input/index.less new file mode 100644 index 0000000..bd420c7 --- /dev/null +++ b/src/components/input/index.less @@ -0,0 +1,39 @@ +.inputBox { + border: 1px solid rgb(3, 109, 247); + display: inline; + padding: 4px; + border-radius: 5px; + margin: 10px; + input { + outline: none; + border: none; + height: 19px; + } + + .numberLimit { + font-size: 14px; + } +} + +.action { + border: 1px solid red; + display: inline; + padding: 4px; + border-radius: 5px; + margin: 10px; + input { + outline: none; + border: none; + height: 19px; + } + .numberLimit { + font-size: 14px; + } +} + +.message { + margin: 0; + padding: 0; + color: red; + font-size: 12px; +} diff --git a/src/components/input/input.tsx b/src/components/input/input.tsx new file mode 100644 index 0000000..57ee9fe --- /dev/null +++ b/src/components/input/input.tsx @@ -0,0 +1,59 @@ +import React, { useEffect, useState } from "react"; +import "./index.less"; + +interface IProps extends React.HTMLProps { + className?: string | undefined; + style?: React.CSSProperties; + value: string | number | undefined; + maxLength?: number | undefined; + defaultValue?: string | undefined; +} + +const Input = (props: IProps) => { + const { value, defaultValue, maxLength, className, style } = props; + const [inputLength, setInputLength] = useState(0); + + useEffect(() => { + if (value === "string") { + let inputValues = value?.split("").length; + setInputLength(inputValues); + } else { + setInputLength(0); + } + }, [value]); + + useEffect(() => { + if (defaultValue) { + if (typeof defaultValue === "number") { + let defaultValueArrayLength = defaultValue + ?.toString() + ?.split("")?.length; + setInputLength(defaultValueArrayLength); + } else if (typeof defaultValue === "string") { + let defaultValues = defaultValue.split("").length; + setInputLength(defaultValues); + } else { + setInputLength(0); + } + } + }, []); + + return ( + <> +
+ + {`${inputLength}/${ + maxLength && maxLength + }`} +
+ {inputLength > 10 && ( + 内容超过10,请重新输入 + )} + + ); +}; + +export default Input; diff --git "a/static/\344\270\213\347\256\255\345\244\264.jpg" "b/static/\344\270\213\347\256\255\345\244\264.jpg" new file mode 100644 index 0000000..bb86ebe Binary files /dev/null and "b/static/\344\270\213\347\256\255\345\244\264.jpg" differ