mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-02-28 21:36:39 +08:00
🚧 add tag type picker
This commit is contained in:
parent
56677616b4
commit
c48231454e
@ -1,44 +1,10 @@
|
|||||||
import clsx from "clsx";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Link from "@docusaurus/Link";
|
import Link from "@docusaurus/Link";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import type { Obj, Tag as TagType } from "../../libs/store";
|
import type { Obj } from "../../libs/store";
|
||||||
|
import Tag from "../Tag";
|
||||||
function pickTextColor(bgColor, lightColor, darkColor) {
|
|
||||||
var color = bgColor.charAt(0) === "#" ? bgColor.substring(1, 7) : bgColor;
|
|
||||||
var r = parseInt(color.substring(0, 2), 16); // hexToR
|
|
||||||
var g = parseInt(color.substring(2, 4), 16); // hexToG
|
|
||||||
var b = parseInt(color.substring(4, 6), 16); // hexToB
|
|
||||||
return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? darkColor : lightColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Tag({
|
|
||||||
label,
|
|
||||||
color,
|
|
||||||
className,
|
|
||||||
onClick,
|
|
||||||
}: TagType & {
|
|
||||||
className?: string;
|
|
||||||
onClick?: React.MouseEventHandler<HTMLSpanElement>;
|
|
||||||
}): JSX.Element {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className={clsx(
|
|
||||||
"inline-flex px-3 rounded-full items-center align-middle mr-2",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
style={{
|
|
||||||
backgroundColor: color,
|
|
||||||
color: pickTextColor(color, "#fff", "#000"),
|
|
||||||
}}
|
|
||||||
onClick={onClick}
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Card({
|
export default function Card({
|
||||||
module_name,
|
module_name,
|
||||||
@ -79,16 +45,7 @@ export default function Card({
|
|||||||
{tags && (
|
{tags && (
|
||||||
<div className="pt-2 pb-4">
|
<div className="pt-2 pb-4">
|
||||||
{tags.map((tag, index) => (
|
{tags.map((tag, index) => (
|
||||||
<span
|
<Tag key={index} {...tag} />
|
||||||
key={index}
|
|
||||||
className="inline-flex px-3 rounded-full items-center align-middle mr-2"
|
|
||||||
style={{
|
|
||||||
backgroundColor: tag.color,
|
|
||||||
color: pickTextColor(tag.color, "#fff", "#000"),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tag.label}
|
|
||||||
</span>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -32,8 +32,12 @@ export default function Modal({
|
|||||||
{ hidden: !active }
|
{ hidden: !active }
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
<div className="w-full max-w-[600px] max-h-[90%] overflow-y-auto rounded shadow-lg m-6 origin-center transition z-[inherit] pointer-events-auto thin-scrollbar">
|
||||||
|
<div className="bg-light-nonepress-100 dark:bg-dark-nonepress-100">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
9
website/src/components/ModalAction/index.tsx
Normal file
9
website/src/components/ModalAction/index.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function ModalAction({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}): JSX.Element {
|
||||||
|
return <div className="px-4 py-2 flex justify-end">{children}</div>;
|
||||||
|
}
|
9
website/src/components/ModalContent/index.tsx
Normal file
9
website/src/components/ModalContent/index.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function ModalContent({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}): JSX.Element {
|
||||||
|
return <div className="px-6 pb-5 w-full">{children}</div>;
|
||||||
|
}
|
9
website/src/components/ModalTitle/index.tsx
Normal file
9
website/src/components/ModalTitle/index.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function ModalTitle({ title }: { title: string }): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className="px-6 pt-4 pb-2 font-medium text-xl">
|
||||||
|
<span>{title}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,13 +1,17 @@
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import React, { useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import { ChromePicker } from "react-color";
|
import { ChromePicker } from "react-color";
|
||||||
import { usePagination } from "react-use-pagination";
|
import { usePagination } from "react-use-pagination";
|
||||||
|
|
||||||
import plugins from "../../static/plugins.json";
|
import plugins from "../../static/plugins.json";
|
||||||
import { Tag, useFilteredObjs } from "../libs/store";
|
import { Tag, useFilteredObjs } from "../libs/store";
|
||||||
import Card, { Tag as TagComponent } from "./Card";
|
import Card from "./Card";
|
||||||
import Modal from "./Modal";
|
import Modal from "./Modal";
|
||||||
|
import ModalAction from "./ModalAction";
|
||||||
|
import ModalContent from "./ModalContent";
|
||||||
|
import ModalTitle from "./ModalTitle";
|
||||||
import Paginate from "./Paginate";
|
import Paginate from "./Paginate";
|
||||||
|
import TagComponent from "./Tag";
|
||||||
|
|
||||||
export default function Adapter(): JSX.Element {
|
export default function Adapter(): JSX.Element {
|
||||||
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
||||||
@ -31,9 +35,12 @@ export default function Adapter(): JSX.Element {
|
|||||||
moduleName: string;
|
moduleName: string;
|
||||||
homepage: string;
|
homepage: string;
|
||||||
}>({ name: "", desc: "", projectLink: "", moduleName: "", homepage: "" });
|
}>({ name: "", desc: "", projectLink: "", moduleName: "", homepage: "" });
|
||||||
|
|
||||||
|
const ref = useRef<HTMLInputElement>(null);
|
||||||
const [tags, setTags] = useState<Tag[]>([]);
|
const [tags, setTags] = useState<Tag[]>([]);
|
||||||
const [label, setLabel] = useState<string>("");
|
const [label, setLabel] = useState<string>("");
|
||||||
const [color, setColor] = useState<string>("#ea5252");
|
const [color, setColor] = useState<string>("#ea5252");
|
||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
const title = encodeURIComponent(`Plugin: ${form.name}`).replace(
|
const title = encodeURIComponent(`Plugin: ${form.name}`).replace(
|
||||||
@ -103,6 +110,10 @@ ${JSON.stringify(tags)}
|
|||||||
const delTag = (index: number) => {
|
const delTag = (index: number) => {
|
||||||
setTags(tags.filter((_, i) => i !== index));
|
setTags(tags.filter((_, i) => i !== index));
|
||||||
};
|
};
|
||||||
|
const insertTagType = (text: string) => {
|
||||||
|
setLabel(text + label);
|
||||||
|
ref.current.value = text + label;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -132,12 +143,8 @@ ${JSON.stringify(tags)}
|
|||||||
<Paginate {...props} />
|
<Paginate {...props} />
|
||||||
</div>
|
</div>
|
||||||
<Modal active={modalOpen} setActive={setModalOpen}>
|
<Modal active={modalOpen} setActive={setModalOpen}>
|
||||||
<div className="w-full max-w-[600px] max-h-[90%] overflow-y-auto rounded shadow-lg m-6 origin-center transition z-[inherit] pointer-events-auto thin-scrollbar">
|
<ModalTitle title={"插件信息"} />
|
||||||
<div className="bg-light-nonepress-100 dark:bg-dark-nonepress-100">
|
<ModalContent>
|
||||||
<div className="px-6 pt-4 pb-2 font-medium text-xl">
|
|
||||||
<span>插件信息</span>
|
|
||||||
</div>
|
|
||||||
<div className="px-6 pb-5 w-full">
|
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<div className="grid grid-cols-1 gap-4 p-4">
|
<div className="grid grid-cols-1 gap-4 p-4">
|
||||||
<label className="flex flex-wrap">
|
<label className="flex flex-wrap">
|
||||||
@ -203,6 +210,7 @@ ${JSON.stringify(tags)}
|
|||||||
</div>
|
</div>
|
||||||
<div className="px-4 pt-4">
|
<div className="px-4 pt-4">
|
||||||
<input
|
<input
|
||||||
|
ref={ref}
|
||||||
type="text"
|
type="text"
|
||||||
className="px-2 flex-grow rounded bg-light-nonepress-200 dark:bg-dark-nonepress-200"
|
className="px-2 flex-grow rounded bg-light-nonepress-200 dark:bg-dark-nonepress-200"
|
||||||
onChange={onChangeLabel}
|
onChange={onChangeLabel}
|
||||||
@ -213,6 +221,21 @@ ${JSON.stringify(tags)}
|
|||||||
disableAlpha={true}
|
disableAlpha={true}
|
||||||
onChangeComplete={onChangeColor}
|
onChangeComplete={onChangeColor}
|
||||||
/>
|
/>
|
||||||
|
<div className="flex flex-wrap mt-2 items-center">
|
||||||
|
<span className="mr-2">Type:</span>
|
||||||
|
<button
|
||||||
|
className="px-2 h-9 min-w-[64px] rounded text-hero hover:bg-hero hover:bg-opacity-[.08]"
|
||||||
|
onClick={() => insertTagType("a:")}
|
||||||
|
>
|
||||||
|
Adapter
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="px-2 h-9 min-w-[64px] rounded text-hero hover:bg-hero hover:bg-opacity-[.08]"
|
||||||
|
onClick={() => insertTagType("t:")}
|
||||||
|
>
|
||||||
|
Topic
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div className="flex mt-2">
|
<div className="flex mt-2">
|
||||||
<TagComponent label={label} color={color} />
|
<TagComponent label={label} color={color} />
|
||||||
<button
|
<button
|
||||||
@ -226,9 +249,12 @@ ${JSON.stringify(tags)}
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ModalContent>
|
||||||
<div className="px-4 py-2 flex justify-end">
|
<ModalAction>
|
||||||
<button className="px-2 h-9 min-w-[64px] rounded text-hero hover:bg-hero hover:bg-opacity-[.08]" onClick={() => setModalOpen(false)}>
|
<button
|
||||||
|
className="px-2 h-9 min-w-[64px] rounded text-hero hover:bg-hero hover:bg-opacity-[.08]"
|
||||||
|
onClick={() => setModalOpen(false)}
|
||||||
|
>
|
||||||
关闭
|
关闭
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@ -237,9 +263,7 @@ ${JSON.stringify(tags)}
|
|||||||
>
|
>
|
||||||
发布
|
发布
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</ModalAction>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
38
website/src/components/Tag/index.tsx
Normal file
38
website/src/components/Tag/index.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import clsx from "clsx";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { Tag as TagType } from "../../libs/store";
|
||||||
|
|
||||||
|
function pickTextColor(bgColor, lightColor, darkColor) {
|
||||||
|
var color = bgColor.charAt(0) === "#" ? bgColor.substring(1, 7) : bgColor;
|
||||||
|
var r = parseInt(color.substring(0, 2), 16); // hexToR
|
||||||
|
var g = parseInt(color.substring(2, 4), 16); // hexToG
|
||||||
|
var b = parseInt(color.substring(4, 6), 16); // hexToB
|
||||||
|
return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? darkColor : lightColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Tag({
|
||||||
|
label,
|
||||||
|
color,
|
||||||
|
className,
|
||||||
|
onClick,
|
||||||
|
}: TagType & {
|
||||||
|
className?: string;
|
||||||
|
onClick?: React.MouseEventHandler<HTMLSpanElement>;
|
||||||
|
}): JSX.Element {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={clsx(
|
||||||
|
"inline-flex px-3 rounded-full items-center align-middle mr-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
backgroundColor: color,
|
||||||
|
color: pickTextColor(color, "#fff", "#000"),
|
||||||
|
}}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user