mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
chore(docs): remove chat linkage (#5959)
* chore: remove unused globalEnv * chore(docs): remove chat links
This commit is contained in:
parent
4e3098a512
commit
a7655ad2c9
@ -22,8 +22,3 @@ NEXT_PUBLIC_FB_FEEDBACK_URL=
|
||||
# PostHog
|
||||
NEXT_PUBLIC_POSTHOG_KEY=your-posthog-key
|
||||
NEXT_PUBLIC_POSTHOG_HOST=your-posthog-host
|
||||
|
||||
# Chat
|
||||
IMPORT_API_KEY=your-import-api-key
|
||||
CHAT_API_URL=
|
||||
CHAT_URL=
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import {toKebabCase, toPascalCase} from "@/components/docs/components/code-demo/utils";
|
||||
|
||||
const importReact = 'import React from "react";';
|
||||
|
||||
export const openInChat = async ({
|
||||
component,
|
||||
title,
|
||||
content,
|
||||
dependencies,
|
||||
useWrapper,
|
||||
}: {
|
||||
component: string;
|
||||
title?: string;
|
||||
content: string;
|
||||
dependencies: {name: string; version: string}[];
|
||||
useWrapper: boolean;
|
||||
}) => {
|
||||
try {
|
||||
// Check if the file content includes 'React' import statements, if not, add it
|
||||
if (
|
||||
content.includes("React.") &&
|
||||
!content.includes("from 'react'") &&
|
||||
!content.includes('from "react"')
|
||||
) {
|
||||
content = `${importReact}\n${content}\n`;
|
||||
}
|
||||
|
||||
let files: Record<string, string> = {
|
||||
"src/App.tsx": content,
|
||||
};
|
||||
|
||||
const fullName = `${component.charAt(0).toUpperCase() + component.slice(1)} - ${title}`;
|
||||
|
||||
if (useWrapper) {
|
||||
files = getFilesWithWrapper(fullName, content);
|
||||
}
|
||||
|
||||
const response = await fetch(`${process.env.CHAT_API_URL}/import`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${process.env.IMPORT_API_KEY}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title: `${component.charAt(0).toUpperCase() + component.slice(1)} - ${title}`,
|
||||
files,
|
||||
dependencies,
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.error || !result.path) {
|
||||
return {
|
||||
error: result.error ?? "Unknown error",
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: null,
|
||||
data: `${process.env.CHAT_URL}${
|
||||
result.path
|
||||
}&utm_source=heroui.com&utm_medium=open-in-chat&utm_content=${encodeURIComponent(
|
||||
title ?? "unknown",
|
||||
)}`,
|
||||
};
|
||||
} catch (error) {
|
||||
return {error: error, data: null};
|
||||
}
|
||||
};
|
||||
|
||||
const getFilesWithWrapper = (name: string, content: string) => {
|
||||
const pascalName = toPascalCase(name);
|
||||
const kebabName = toKebabCase(name);
|
||||
|
||||
// Replace the export default function name
|
||||
const updatedContent = content.replace(
|
||||
"export default function App()",
|
||||
`export default function ${pascalName}()`,
|
||||
);
|
||||
|
||||
const wrapperContent = `import ${pascalName} from "./components/${kebabName}";
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center p-6">
|
||||
<${pascalName} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
return {
|
||||
[`src/components/${kebabName}.tsx`]: updatedContent,
|
||||
[`src/App.tsx`]: wrapperContent,
|
||||
};
|
||||
};
|
||||
@ -4,18 +4,13 @@ import type {UseCodeDemoProps} from "./use-code-demo";
|
||||
import type {WindowResizerProps} from "./window-resizer";
|
||||
import type {GradientBoxProps} from "@/components/gradient-box";
|
||||
|
||||
import React, {useCallback, useMemo, useRef, useState} from "react";
|
||||
import React, {useCallback, useMemo, useRef} from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import {addToast, Button, Skeleton, Spinner, Tab, Tabs} from "@heroui/react";
|
||||
import {Skeleton, Tab, Tabs} from "@heroui/react";
|
||||
import {useInView} from "framer-motion";
|
||||
import {usePostHog} from "posthog-js/react";
|
||||
import {usePathname} from "next/navigation";
|
||||
|
||||
import {useCodeDemo} from "./use-code-demo";
|
||||
import WindowResizer from "./window-resizer";
|
||||
import {parseDependencies} from "./parse-dependencies";
|
||||
|
||||
import {openInChat} from "@/actions/open-in-chat";
|
||||
|
||||
const DynamicReactLiveDemo = dynamic(
|
||||
() => import("./react-live-demo").then((m) => m.ReactLiveDemo),
|
||||
@ -82,11 +77,6 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
|
||||
margin: "600px",
|
||||
});
|
||||
|
||||
const pathname = usePathname();
|
||||
const posthog = usePostHog();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const {noInline, code} = useCodeDemo({
|
||||
files,
|
||||
});
|
||||
@ -178,64 +168,6 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
|
||||
return true;
|
||||
}, [showTabs, showPreview, showEditor]);
|
||||
|
||||
const isComponentsPage = pathname.includes("/components/");
|
||||
|
||||
const handleOpenInChat = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
|
||||
// assume doc demo files are all App.jsx
|
||||
const content = files["/App.jsx"];
|
||||
|
||||
if (!content || typeof content !== "string") {
|
||||
addToast({
|
||||
title: "Error",
|
||||
description: "Invalid demo content",
|
||||
color: "danger",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const component = pathname.split("/components/")[1];
|
||||
const dependencies = parseDependencies(content);
|
||||
|
||||
posthog.capture("CodeDemo - Open in Chat", {
|
||||
component,
|
||||
demo: title,
|
||||
});
|
||||
|
||||
const newTab = window.open(undefined, "_blank");
|
||||
|
||||
const {data, error} = await openInChat({
|
||||
component,
|
||||
title,
|
||||
content,
|
||||
dependencies,
|
||||
useWrapper: !asIframe,
|
||||
});
|
||||
|
||||
setIsLoading(false);
|
||||
|
||||
if (error || !data) {
|
||||
if (newTab) newTab.close();
|
||||
posthog.capture("CodeDemo - Open in Chat Error", {
|
||||
component,
|
||||
demo: title,
|
||||
error: error ?? "Unknown error",
|
||||
});
|
||||
|
||||
addToast({
|
||||
title: "Error",
|
||||
description: error ?? "Unknown error",
|
||||
color: "danger",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (newTab) newTab.location.href = data;
|
||||
}, [pathname, title, files, posthog]);
|
||||
|
||||
return (
|
||||
<div ref={ref} className="flex flex-col gap-2 relative">
|
||||
{shouldRenderTabs ? (
|
||||
@ -255,26 +187,6 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
|
||||
{editorContent}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
{isComponentsPage && (
|
||||
<Button
|
||||
disableRipple
|
||||
className="absolute rounded-[9px] right-1 top-1 border-1 border-default-200 dark:border-default-100 data-[hover=true]:bg-default-50/80"
|
||||
isDisabled={isLoading}
|
||||
size="sm"
|
||||
variant="bordered"
|
||||
onPress={handleOpenInChat}
|
||||
>
|
||||
Open in Chat{" "}
|
||||
{isLoading ? (
|
||||
<Spinner
|
||||
classNames={{wrapper: "h-4 w-4"}}
|
||||
color="current"
|
||||
size="sm"
|
||||
variant="simple"
|
||||
/>
|
||||
) : null}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import {Icon} from "@iconify/react/dist/offline";
|
||||
import arrowRightIcon from "@iconify/icons-solar/arrow-right-linear";
|
||||
import {usePathname} from "next/navigation";
|
||||
import {useEffect} from "react";
|
||||
import {usePostHog} from "posthog-js/react";
|
||||
|
||||
import emitter from "@/libs/emitter";
|
||||
|
||||
const hideOnPaths = ["examples"];
|
||||
|
||||
export const HeroUIChatBanner = () => {
|
||||
const posthog = usePostHog();
|
||||
|
||||
const handleClick = () => {
|
||||
posthog.capture("HeroUI Chat Banner", {
|
||||
action: "click",
|
||||
category: "landing-page",
|
||||
});
|
||||
};
|
||||
|
||||
const pathname = usePathname();
|
||||
const shouldBeVisible = !hideOnPaths.some((path) => pathname.includes(path));
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldBeVisible) return;
|
||||
|
||||
// listen to scroll event, dispatch an event when scroll is at the top < 48 px
|
||||
const handleScroll = () => {
|
||||
if (window.scrollY < 48) {
|
||||
emitter.emit("proBannerVisibilityChange", "visible");
|
||||
} else {
|
||||
emitter.emit("proBannerVisibilityChange", "hidden");
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
};
|
||||
}, [shouldBeVisible]);
|
||||
|
||||
if (!shouldBeVisible) return null;
|
||||
|
||||
return (
|
||||
<div className="relative z-50 isolate flex items-center gap-x-6 overflow-hidden bg-background border-b-1 border-divider px-6 py-2 sm:px-3.5 sm:before:flex-1">
|
||||
<div className="flex w-full items-center justify-between md:justify-center gap-x-3">
|
||||
<a
|
||||
className="text-small flex items-end sm:text-[0.93rem] text-foreground hover:opacity-80 transition-opacity"
|
||||
href="https://heroui.chat?utm_source=heroui.com&utm_medium=top-banner"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<span aria-label="rocket" className="hidden md:block" role="img">
|
||||
🚀
|
||||
</span>
|
||||
<span
|
||||
className="inline-flex md:ml-1 animate-text-gradient font-medium bg-clip-text text-transparent bg-[linear-gradient(90deg,#27272A_0%,#52525B_50%,#52525B_100%)] dark:bg-[linear-gradient(90deg,#E5E5E5_0%,#A1A1AA_50%,#E5E5E5_100%)]"
|
||||
style={{
|
||||
fontSize: "inherit",
|
||||
backgroundSize: "200%",
|
||||
backgroundClip: "text",
|
||||
WebkitBackgroundClip: "text",
|
||||
color: "transparent",
|
||||
}}
|
||||
>
|
||||
Generate, edit and deploy beautiful apps
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
className="flex group min-w-[120px] items-center font-semibold text-background bg-foreground shadow-sm gap-1.5 relative overflow-hidden rounded-full p-[1px] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary"
|
||||
href="https://heroui.chat?utm_source=heroui.com&utm_medium=top-banner"
|
||||
rel="noopener noreferrer"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div className="inline-flex h-full w-full cursor-pointer items-center justify-center rounded-full bg-foreground group-hover:bg-foreground/70 transition-background px-3 py-1 text-sm font-medium text-background">
|
||||
HeroUI Chat
|
||||
<Icon
|
||||
aria-hidden="true"
|
||||
className="outline-solid outline-transparent transition-transform group-hover:translate-x-0.5 [&>path]:stroke-[2px]"
|
||||
icon={arrowRightIcon}
|
||||
width={16}
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -1,26 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import {useState, useEffect} from "react";
|
||||
|
||||
import {HeroUIChatBanner} from "@/components/heroui-chat-banner";
|
||||
import {ProBanner} from "@/components/pro-banner";
|
||||
|
||||
export const RandomBanner = () => {
|
||||
const [showChatBanner, setShowChatBanner] = useState<boolean | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const bannerCount = parseInt(sessionStorage.getItem("bannerCount") || "0", 10);
|
||||
|
||||
const shouldShowChat = bannerCount % 2 === 0;
|
||||
|
||||
setShowChatBanner(shouldShowChat);
|
||||
|
||||
sessionStorage.setItem("bannerCount", String(bannerCount + 1));
|
||||
}, []);
|
||||
|
||||
if (showChatBanner === null) {
|
||||
return <div className="h-[47px] border-b border-divider" />;
|
||||
}
|
||||
|
||||
return showChatBanner ? <HeroUIChatBanner /> : <ProBanner />;
|
||||
};
|
||||
@ -6,10 +6,7 @@
|
||||
"IS_PREVIEW",
|
||||
"IS_VA_ENABLED",
|
||||
"ENABLE_EXPERIMENTAL_COREPACK",
|
||||
"PLAIN_USER_AUTHENTICATED",
|
||||
"IMPORT_API_KEY",
|
||||
"CHAT_URL",
|
||||
"CHAT_API_URL"
|
||||
"PLAIN_USER_AUTHENTICATED"
|
||||
],
|
||||
"tasks": {
|
||||
"build": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user