Skip to content
This repository was archived by the owner on Apr 18, 2024. It is now read-only.

Commit 8fe43cb

Browse files
committed
chore: copy click prompt button related component and setup its package
Signed-off-by: teobler <teobler@163.com>
1 parent 9643520 commit 8fe43cb

22 files changed

+3469
-1
lines changed

package-lock.json

Lines changed: 2202 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# ClickPromptButton - shift your prompt to everywhere
22

3-
click prompt button is a component that can be used to execute a prompt from ChatGPT in any web page. It is a part of the [ClickPrompt](https://www.clickprompt.org/)
3+
click prompt button is react component that can be used to execute a prompt from ChatGPT in any web page. It is a part of the [ClickPrompt](https://www.clickprompt.org/)
4+
5+
notice: click prompt button is just for nextjs now, will update it to support React.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "click-prompt-button",
3+
"version": "0.1.0",
4+
"description": "click prompt button is react component that can be used to execute a prompt from ChatGPT in any web page. It is a part of the ClickPrompt",
5+
"main": "index.js",
6+
"license": "MIT",
7+
"scripts": {
8+
"build": "vite build"
9+
},
10+
"dependencies": {
11+
"@chakra-ui/icons": "^2.0.17",
12+
"@chakra-ui/react": "^2.5.1",
13+
"@chakra-ui/spinner": "^2.0.13",
14+
"@chakra-ui/system": "^2.5.1",
15+
"@emotion/react": "^11.10.6",
16+
"@emotion/styled": "^11.10.6",
17+
"client-only": "^0.0.1",
18+
"mermaid": "^10.0.2",
19+
"react": "^18.2.0",
20+
"react-dom": "^18.2.0",
21+
"react-markdown": "^8.0.5",
22+
"react-spinners": "^0.13.8",
23+
"react-syntax-highlighter": "^15.5.0",
24+
"remark-gfm": "^3.0.1",
25+
"svg-pan-zoom": "^3.6.1"
26+
},
27+
"devDependencies": {
28+
"@vitejs/plugin-react": "^3.1.0",
29+
"vite": "^4.2.1",
30+
"vite-plugin-dts": "^2.1.0",
31+
"vite-plugin-linter": "^2.0.2",
32+
"vite-tsconfig-paths": "^4.0.7"
33+
},
34+
"peerDependencies": {
35+
"next": ">=13.0.0",
36+
"react": ">=16.8.0",
37+
"react-dom": ">=16.8.0"
38+
}
39+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import Image from "next/image";
2+
import React, { MouseEventHandler } from "react";
3+
import styled from "@emotion/styled";
4+
5+
export type ButtonSize = "sm" | "md" | "lg";
6+
7+
export const StyledBird = styled(Image)`
8+
position: absolute;
9+
top: -20px;
10+
right: -20px;
11+
`;
12+
13+
export const StyledPromptButton = styled.div`
14+
position: relative;
15+
width: min-content;
16+
`;
17+
18+
export type CPButtonProps = {
19+
loading?: boolean;
20+
onClick?: MouseEventHandler;
21+
size?: ButtonSize;
22+
text: string;
23+
children?: React.ReactNode;
24+
[key: string]: any;
25+
isLoggedIn: () => Promise<any>;
26+
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React, { useState } from "react";
2+
import { Box, Button, Text, Tooltip, useDisclosure } from "@chakra-ui/react";
3+
import { BeatLoader } from "react-spinners";
4+
import { ClickPromptSmall } from "./CustomIcon";
5+
import clickPromptLogo from "@/assets/clickprompt-light.svg?url";
6+
import { CPButtonProps, StyledBird, StyledPromptButton } from "./Button.shared";
7+
import { LoggingDrawer } from "./LoggingDrawer";
8+
9+
export type ClickPromptBirdParams = { width?: number; height?: number };
10+
11+
export function ClickPromptBird(props: ClickPromptBirdParams) {
12+
const width = props.width || 38;
13+
const height = props.height || 32;
14+
15+
return <StyledBird src={clickPromptLogo} alt="ClickPrompt Logo" width={width} height={height} />;
16+
}
17+
18+
export function ClickPromptButton(props: CPButtonProps) {
19+
const [isLoading, setIsLoading] = useState(props.loading);
20+
const [isLoggedIn, setIsLoggedIn] = useState(false);
21+
const { isOpen, onOpen, onClose } = useDisclosure();
22+
23+
const handleClick = async (event: any) => {
24+
setIsLoading(true);
25+
const isLoggedIn = await props.isLoggedIn();
26+
setIsLoggedIn(isLoggedIn);
27+
onOpen();
28+
props.onClick && props.onClick(event);
29+
};
30+
31+
const handleClose = () => {
32+
setIsLoading(false);
33+
onClose();
34+
};
35+
36+
function NormalSize() {
37+
return (
38+
<StyledPromptButton>
39+
<Button colorScheme="twitter" className="bg-blue" onClick={handleClick} {...props}>
40+
{props.children}
41+
{!isLoading && <Text>Prompt</Text>}
42+
{isLoading && <BeatLoader size={8} color="black" />}
43+
</Button>
44+
<ClickPromptBird />
45+
</StyledPromptButton>
46+
);
47+
}
48+
49+
function SmallSize() {
50+
return (
51+
<Button variant="unstyled" onClick={handleClick} {...props}>
52+
{props.children}
53+
<Tooltip label="Execute ChatGPT Prompt" aria-label="A tooltip">
54+
<ClickPromptSmall width={32} height={32} />
55+
</Tooltip>
56+
</Button>
57+
);
58+
}
59+
60+
return (
61+
<Box>
62+
{props.size !== "sm" && <NormalSize />}
63+
{props.size === "sm" && <SmallSize />}
64+
65+
{LoggingDrawer(isOpen, handleClose, isLoggedIn, props)}
66+
</Box>
67+
);
68+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from "react";
2+
import Image from "next/image";
3+
import clickPromptSmall from "@/assets/clickprompt-small.svg?url";
4+
5+
export function ClickPromptSmall({ width = 32, height = 32 }) {
6+
return <Image className="inline-block" src={clickPromptSmall} alt="ClickPrompt Logo" width={width} height={height} />;
7+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import React, { MouseEventHandler, useEffect, useState } from "react";
2+
import { Button, Text, useDisclosure } from "@chakra-ui/react";
3+
import { BeatLoader } from "react-spinners";
4+
import { ClickPromptBird } from "./ClickPromptButton";
5+
import { ButtonSize, StyledPromptButton } from "./Button.shared";
6+
import { LoggingDrawer } from "./LoggingDrawer";
7+
8+
export type ExecButtonProps = {
9+
loading?: boolean;
10+
onClick?: MouseEventHandler;
11+
name: string;
12+
text: string;
13+
size?: ButtonSize;
14+
children?: React.ReactNode;
15+
handleResponse?: (response: any) => void;
16+
conversationId?: number;
17+
updateConversationId?: (conversationId: number) => void;
18+
isLoggedIn: () => Promise<any>;
19+
createConversation: (name?: string) => Promise<any>;
20+
sendMessage: (conversageId: number, message: string, name?: string) => Promise<any>;
21+
};
22+
23+
function ExecutePromptButton(props: ExecButtonProps) {
24+
const [isLoading, setIsLoading] = useState(props.loading);
25+
const { isOpen, onOpen, onClose } = useDisclosure();
26+
const [hasLogin, setHasLogin] = useState(false);
27+
28+
const handleClick = async () => {
29+
setIsLoading(true);
30+
31+
try {
32+
const isLoggedIn = await props.isLoggedIn();
33+
if (!isLoggedIn) {
34+
onOpen();
35+
setIsLoading(false);
36+
return;
37+
}
38+
} catch (e) {
39+
console.log(e);
40+
setHasLogin(false);
41+
}
42+
43+
let conversationId = props.conversationId;
44+
if (!props.conversationId) {
45+
const conversation = await props.createConversation();
46+
if (!conversation) {
47+
return;
48+
}
49+
50+
conversationId = conversation.id as number;
51+
props.updateConversationId ? props.updateConversationId(conversationId) : null;
52+
}
53+
54+
if (conversationId) {
55+
const response: any = await props.sendMessage(conversationId, props.text);
56+
if (response && props.handleResponse) {
57+
props.handleResponse(response as any);
58+
}
59+
}
60+
61+
setIsLoading(false);
62+
};
63+
64+
useEffect(() => {
65+
console.log(`hasLogin: ${hasLogin}`);
66+
if (hasLogin) {
67+
onClose();
68+
}
69+
}, [hasLogin]);
70+
71+
const handleClose = () => {
72+
onClose();
73+
};
74+
75+
const updateLoginStatus = (status: boolean) => {
76+
if (status) {
77+
setHasLogin(true);
78+
onClose();
79+
}
80+
};
81+
82+
return (
83+
<>
84+
<StyledPromptButton>
85+
<Button colorScheme="twitter" className="bg-blue" onClick={handleClick}>
86+
{props.children}
87+
{!isLoading && <Text>Prompt</Text>}
88+
{isLoading && <BeatLoader size={8} color="black" />}
89+
</Button>
90+
<ClickPromptBird />
91+
</StyledPromptButton>
92+
{!hasLogin && LoggingDrawer(isOpen, handleClose, hasLogin, props, updateLoginStatus)}
93+
</>
94+
);
95+
}
96+
97+
export default ExecutePromptButton;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerOverlay } from "@chakra-ui/react";
2+
import { ChatGPTApp } from "@/chatgpt/ChatGPTApp";
3+
import React from "react";
4+
import { CPButtonProps } from "./Button.shared";
5+
6+
export function LoggingDrawer(
7+
isOpen: boolean,
8+
handleClose: () => void,
9+
isLoggedIn: boolean,
10+
props: CPButtonProps,
11+
updateStatus?: (loggedIn: boolean) => void
12+
) {
13+
return (
14+
<Drawer isOpen={isOpen} placement="right" onClose={handleClose} size={"2xl"}>
15+
<DrawerOverlay />
16+
<DrawerContent>
17+
<DrawerCloseButton className="text-white z-50" />
18+
<DrawerBody padding={0}>
19+
<div className="bg-[#343541] flex flex-1 h-[100%] overflow-y-auto items-center justify-center">
20+
<ChatGPTApp loggedIn={isLoggedIn} initMessage={props.text} updateLoginStatus={updateStatus} />
21+
</div>
22+
</DrawerBody>
23+
</DrawerContent>
24+
</Drawer>
25+
);
26+
}
Lines changed: 11 additions & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)