aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDhravya <[email protected]>2024-07-04 19:17:51 -0500
committerDhravya <[email protected]>2024-07-04 19:17:51 -0500
commit6ef746da542b8e5da3ef638fb7f46f5aa10a3a02 (patch)
tree07bceba625a40bc0fedd5b8028820ea50032d217
parentUX: Load while creating memory (diff)
downloadsupermemory-6ef746da542b8e5da3ef638fb7f46f5aa10a3a02.tar.xz
supermemory-6ef746da542b8e5da3ef638fb7f46f5aa10a3a02.zip
revamped extention
-rw-r--r--apps/cf-ai-backend/src/helper.ts1
-rw-r--r--apps/cf-ai-backend/src/index.ts2
-rw-r--r--apps/cf-ai-backend/src/utils/OpenAIEmbedder.ts23
-rw-r--r--apps/extension/background.ts72
-rw-r--r--apps/extension/content/ContentApp.tsx365
-rw-r--r--apps/extension/content/content.tsx2
-rw-r--r--apps/extension/content/ui/shadcn/input.tsx25
-rw-r--r--apps/extension/content/ui/shadcn/label.tsx26
-rw-r--r--apps/extension/content/ui/shadcn/popover.tsx2
-rw-r--r--apps/extension/content/ui/shadcn/select.tsx162
-rw-r--r--apps/extension/content/ui/shadcn/textarea.tsx24
-rw-r--r--apps/extension/content/ui/shadcn/tooltip.tsx2
-rw-r--r--apps/extension/content/ui/shadcn/use-toast.ts2
-rw-r--r--apps/extension/package.json2
-rw-r--r--apps/extension/public/output.css466
-rw-r--r--apps/web/app/api/ensureAuth.ts2
-rw-r--r--apps/web/app/api/store/route.ts16
-rw-r--r--apps/web/middleware.ts25
18 files changed, 839 insertions, 380 deletions
diff --git a/apps/cf-ai-backend/src/helper.ts b/apps/cf-ai-backend/src/helper.ts
index db3ab2d3..98e38ce8 100644
--- a/apps/cf-ai-backend/src/helper.ts
+++ b/apps/cf-ai-backend/src/helper.ts
@@ -51,6 +51,7 @@ export async function initQuery(
apiKey: c.env.OPENAI_API_KEY,
baseURL:
"https://gateway.ai.cloudflare.com/v1/47c2b4d598af9d423c06fc9f936226d5/supermemory/openai",
+ compatibility: "strict",
});
selectedModel = openai.chat("gpt-4o");
break;
diff --git a/apps/cf-ai-backend/src/index.ts b/apps/cf-ai-backend/src/index.ts
index 31ee520f..04f80f0d 100644
--- a/apps/cf-ai-backend/src/index.ts
+++ b/apps/cf-ai-backend/src/index.ts
@@ -509,7 +509,7 @@ app.post(
const userMessage: CoreMessage = { role: "user", content: prompt };
const response = await streamText({
- model,
+ model: model,
messages: [
...initialMessages,
...((body.chatHistory || []) as CoreMessage[]),
diff --git a/apps/cf-ai-backend/src/utils/OpenAIEmbedder.ts b/apps/cf-ai-backend/src/utils/OpenAIEmbedder.ts
index be5839b1..8364ed0d 100644
--- a/apps/cf-ai-backend/src/utils/OpenAIEmbedder.ts
+++ b/apps/cf-ai-backend/src/utils/OpenAIEmbedder.ts
@@ -22,17 +22,20 @@ export class OpenAIEmbeddings {
}
async embedQuery(text: string): Promise<number[]> {
- const response = await fetch("https://api.openai.com/v1/embeddings", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${this.apiKey}`,
+ const response = await fetch(
+ "https://gateway.ai.cloudflare.com/v1/47c2b4d598af9d423c06fc9f936226d5/supermemory/openai/embeddings",
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${this.apiKey}`,
+ },
+ body: JSON.stringify({
+ input: text,
+ model: this.modelName,
+ }),
},
- body: JSON.stringify({
- input: text,
- model: this.modelName,
- }),
- });
+ );
const data = await response.json();
diff --git a/apps/extension/background.ts b/apps/extension/background.ts
index 97bb341c..df4d0375 100644
--- a/apps/extension/background.ts
+++ b/apps/extension/background.ts
@@ -74,15 +74,28 @@ const batchImportAll = async (cursor = "", totalImported = 0) => {
description: tweet.text.slice(0, 200),
type: "tweet",
}),
- }).then((ers) => {
+ }).then(async (ers) => {
console.log(ers.status);
importedCount++;
totalImported++;
- // Send an update message to the content script
- chrome.runtime.sendMessage({
- type: "import-update",
- importedCount: totalImported,
- });
+ console.log(totalImported);
+ chrome.tabs.query(
+ { active: true, currentWindow: true },
+ async function (tabs) {
+ if (tabs.length > 0) {
+ let currentTabId = tabs[0].id;
+
+ if (!currentTabId) {
+ return;
+ }
+
+ await chrome.tabs.sendMessage(currentTabId, {
+ type: "import-update",
+ importedCount: totalImported,
+ });
+ }
+ },
+ );
});
});
})();
@@ -111,19 +124,45 @@ const batchImportAll = async (cursor = "", totalImported = 0) => {
batchImportAll(nextCursor, totalImported); // Recursively call with new cursor
} else {
console.log("All bookmarks imported");
- // Send a "done" message to the content script
- chrome.runtime.sendMessage({
- type: "import-done",
- importedCount: totalImported,
- });
+
+ chrome.tabs.query(
+ { active: true, currentWindow: true },
+ async function (tabs) {
+ if (tabs.length > 0) {
+ let currentTabId = tabs[0].id;
+
+ if (!currentTabId) {
+ return;
+ }
+
+ await chrome.runtime.sendMessage({
+ type: "import-done",
+ importedCount: totalImported,
+ });
+ }
+ },
+ );
}
} else {
console.log("All bookmarks imported");
// Send a "done" message to the content script
- chrome.runtime.sendMessage({
- type: "import-done",
- importedCount: totalImported,
- });
+ chrome.tabs.query(
+ { active: true, currentWindow: true },
+ async function (tabs) {
+ if (tabs.length > 0) {
+ let currentTabId = tabs[0].id;
+
+ if (!currentTabId) {
+ return;
+ }
+
+ await chrome.runtime.sendMessage({
+ type: "import-done",
+ importedCount: totalImported,
+ });
+ }
+ },
+ );
}
})
.catch((error) => console.error(error));
@@ -311,10 +350,9 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
}).then((ers) => console.log(ers.status));
});
})();
-
- return true;
} else if (request.type === "batchImportAll") {
batchImportAll();
+ return true;
}
});
diff --git a/apps/extension/content/ContentApp.tsx b/apps/extension/content/ContentApp.tsx
index c1af1dfc..1dea7645 100644
--- a/apps/extension/content/ContentApp.tsx
+++ b/apps/extension/content/ContentApp.tsx
@@ -1,6 +1,5 @@
import React, { useEffect, useRef, useState } from "react";
import { Readability } from "@mozilla/readability";
-import tailwindBg from "../public/tailwind_bg.png";
import {
Tooltip,
TooltipContent,
@@ -9,7 +8,19 @@ import {
} from "./ui/shadcn/tooltip";
import { Popover, PopoverContent, PopoverTrigger } from "./ui/shadcn/popover";
import { Toaster } from "./ui/shadcn/toaster";
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectTrigger,
+ SelectValue,
+} from "./ui/shadcn/select";
import { useToast } from "./ui/shadcn/use-toast";
+import { Input } from "./ui/shadcn/input";
+import { Label } from "./ui/shadcn/label";
+import { Textarea } from "./ui/shadcn/textarea";
const BACKEND_URL = "https://supermemory.ai";
@@ -20,19 +31,70 @@ export default function ContentApp({
token: string | undefined;
shadowRoot: ShadowRoot;
}) {
- const [text, setText] = useState("");
const [hover, setHover] = useState(false);
+ const { toast } = useToast();
+
const [loading, setLoading] = useState(false);
+ const [webNote, setWebNote] = useState<string>("");
+
const [importedCount, setImportedCount] = useState(0);
const [isImporting, setIsImporting] = useState(false);
+ const [importDone, setImportDone] = useState(false);
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
null,
);
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
- const { toast } = useToast();
+ const [isPopover2Open, setIsPopover2Open] = useState(false);
+
+ const [spacesOptions, setSpacesOptions] = useState<
+ { id: number; name: string }[]
+ >([]);
+ const [selectedSpace, setSelectedSpace] = useState<string>();
+
+ const [userNotLoggedIn, setUserNotLoggedIn] = useState(false);
+
+ const showLoginToast = async () => {
+ setUserNotLoggedIn(true);
+
+ const NOSHOW_TOAST = ["accounts.google.com", "supermemory.ai"];
+
+ const noLoginWarning = await chrome.storage.local.get("noLoginWarning");
+ if (Object.keys(noLoginWarning).length > 0) {
+ return;
+ }
+
+ if (!NOSHOW_TOAST.includes(window.location.host)) {
+ const t = toast({
+ title: "Please login to supermemory.ai to use this extension.",
+ action: (
+ <div className="flex flex-col gap-2">
+ <button
+ onClick={() =>
+ window.open("https://supermemory.ai/signin", "_blank")
+ }
+ >
+ Login
+ </button>
+
+ <button
+ className="text-xs"
+ onClick={async () => {
+ await chrome.storage.local.set({
+ noLoginWarning: true,
+ });
+ t.dismiss();
+ }}
+ >
+ Ignore
+ </button>
+ </div>
+ ),
+ });
+ }
+ };
useEffect(() => {
document.addEventListener("mousemove", (e) => {
@@ -47,24 +109,21 @@ export default function ContentApp({
});
const getUserData = () => {
- chrome.runtime.sendMessage({ type: "getJwt" }, (response) => {
- console.log("jwt", response.jwt);
- });
+ chrome.runtime.sendMessage({ type: "getJwt" });
};
getUserData();
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
- console.log("request", request);
- console.log("sender", sender);
- console.log("sendResponse", sendResponse);
if (request.type === "import-update") {
+ console.log(request);
setIsImporting(true);
setImportedCount(request.importedCount);
}
if (request.type === "import-done") {
setIsImporting(false);
+ setImportDone(true);
}
});
@@ -73,12 +132,36 @@ export default function ContentApp({
shadowRoot.appendChild(portalDiv);
setPortalContainer(portalDiv);
+ const getSpaces = async () => {
+ const response = await fetch(`${BACKEND_URL}/api/spaces`, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ });
+
+ if (response.status === 401) {
+ showLoginToast();
+ return;
+ }
+
+ try {
+ const data = await response.json();
+ setSpacesOptions(data.data);
+ } catch (e) {
+ console.error(
+ `Error in supermemory.ai extension: ${e}. Please contact the developer https://x.com/dhravyashah`,
+ );
+ }
+ };
+
+ getSpaces();
+
return () => {
document.removeEventListener("mousemove", () => {});
};
- }, [document.getElementById("supermemory-extension-host")]);
+ }, []);
- function sendUrlToAPI(spaces: number[]) {
+ async function sendUrlToAPI(spaces: string[]) {
setLoading(true);
setTimeout(() => {
@@ -91,7 +174,6 @@ export default function ContentApp({
const blacklist: string[] = [];
// check if the URL is blacklisted
if (blacklist.some((blacklisted) => url.includes(blacklisted))) {
- console.log("URL is blacklisted");
return;
} else {
const clone = document.cloneNode(true) as Document;
@@ -105,16 +187,45 @@ export default function ContentApp({
document.querySelector('link[rel="icon"]') as HTMLLinkElement
)?.href;
- console.log("article", article);
- chrome.runtime.sendMessage({
- type: "urlSave",
- content: article?.textContent,
- url,
- spaces,
- title: article?.title,
- description: article?.excerpt,
- ogImage: ogImage,
- favicon: favicon,
+ setLoading(true);
+
+ setIsPopoverOpen(false);
+
+ await fetch(`${BACKEND_URL}/api/store`, {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ body: JSON.stringify({
+ pageContent:
+ (webNote ? `Note about this website: ${webNote}\n\n` : "") +
+ article?.textContent,
+ url: url + "#supermemory-user-" + Math.random(),
+ title: article?.title.slice(0, 500),
+ spaces: spaces,
+ description: article?.excerpt.slice(0, 250),
+ ogImage: ogImage?.slice(0, 1000),
+ image: favicon,
+ }),
+ }).then(async (rep) => {
+ if (rep.status === 401) {
+ showLoginToast();
+ return;
+ }
+
+ const d = await rep.json();
+
+ if (rep.status === 200) {
+ toast({
+ title: "Saved to supermemory.ai",
+ });
+ } else {
+ toast({
+ title: `Failed to save to supermemory.ai: ${d.error ?? "Unknown error"}`,
+ });
+ }
+ setLoading(false);
+ return rep;
});
}
}
@@ -134,69 +245,179 @@ export default function ContentApp({
<PopoverTrigger
className={`${hover || isPopoverOpen ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-20 items-center text-lg`}
>
- {loading ? (
- <div className="text-sm">Saving...</div>
- ) : (
- <svg
- className="w-full h-full size-8"
- width={24}
- height={24}
- viewBox="0 0 42 42"
- fill="currentColor"
- xmlns="http://www.w3.org/2000/svg"
- >
- <path
- d="M19.0357 8C20.5531 8 21 9.27461 21 10.8438V16.3281H23.5536V14.2212C23.5536 13.1976 23.9468 12.216 24.6467 11.4922L25.0529 11.0721C24.9729 10.8772 24.9286 10.6627 24.9286 10.4375C24.9286 9.54004 25.6321 8.8125 26.5 8.8125C27.3679 8.8125 28.0714 9.54004 28.0714 10.4375C28.0714 11.335 27.3679 12.0625 26.5 12.0625C26.2822 12.0625 26.0748 12.0167 25.8863 11.9339L25.4801 12.354C25.0012 12.8492 24.7321 13.5209 24.7321 14.2212V16.3281H28.9714C29.2045 15.7326 29.7691 15.3125 30.4286 15.3125C31.2964 15.3125 32 16.04 32 16.9375C32 17.835 31.2964 18.5625 30.4286 18.5625C29.7691 18.5625 29.2045 18.1424 28.9714 17.5469H21V21.2031H25.0428C25.2759 20.6076 25.8405 20.1875 26.5 20.1875C27.3679 20.1875 28.0714 20.915 28.0714 21.8125C28.0714 22.71 27.3679 23.4375 26.5 23.4375C25.8405 23.4375 25.2759 23.0174 25.0428 22.4219H21V26.0781H24.4125C25.4023 26.0781 26.3516 26.4847 27.0515 27.2085L29.0292 29.2536C29.2177 29.1708 29.4251 29.125 29.6429 29.125C30.5107 29.125 31.2143 29.8525 31.2143 30.75C31.2143 31.6475 30.5107 32.375 29.6429 32.375C28.775 32.375 28.0714 31.6475 28.0714 30.75C28.0714 30.5248 28.1157 30.3103 28.1958 30.1154L26.2181 28.0703C25.7392 27.5751 25.0897 27.2969 24.4125 27.2969H21V31.1562C21 32.7254 20.5531 34 19.0357 34C17.6165 34 16.4478 32.8879 16.3004 31.4559C16.0451 31.527 15.775 31.5625 15.5 31.5625C13.7665 31.5625 12.3571 30.1051 12.3571 28.3125C12.3571 27.9367 12.421 27.5711 12.5339 27.2359C11.0509 26.657 10 25.1742 10 23.4375C10 21.8176 10.9183 20.416 12.2491 19.766C11.8219 19.2125 11.5714 18.5117 11.5714 17.75C11.5714 16.191 12.6321 14.891 14.0464 14.5711C13.9679 14.2918 13.9286 13.9922 13.9286 13.6875C13.9286 12.1691 14.9402 10.8895 16.3004 10.534C16.4478 9.11211 17.6165 8 19.0357 8Z"
- fill="#fff"
- />
- </svg>
- )}
+ <svg
+ className={`w-full h-full size-8 ${loading && "animate-spin"}`}
+ width={24}
+ height={24}
+ viewBox="0 0 42 42"
+ fill="currentColor"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M19.0357 8C20.5531 8 21 9.27461 21 10.8438V16.3281H23.5536V14.2212C23.5536 13.1976 23.9468 12.216 24.6467 11.4922L25.0529 11.0721C24.9729 10.8772 24.9286 10.6627 24.9286 10.4375C24.9286 9.54004 25.6321 8.8125 26.5 8.8125C27.3679 8.8125 28.0714 9.54004 28.0714 10.4375C28.0714 11.335 27.3679 12.0625 26.5 12.0625C26.2822 12.0625 26.0748 12.0167 25.8863 11.9339L25.4801 12.354C25.0012 12.8492 24.7321 13.5209 24.7321 14.2212V16.3281H28.9714C29.2045 15.7326 29.7691 15.3125 30.4286 15.3125C31.2964 15.3125 32 16.04 32 16.9375C32 17.835 31.2964 18.5625 30.4286 18.5625C29.7691 18.5625 29.2045 18.1424 28.9714 17.5469H21V21.2031H25.0428C25.2759 20.6076 25.8405 20.1875 26.5 20.1875C27.3679 20.1875 28.0714 20.915 28.0714 21.8125C28.0714 22.71 27.3679 23.4375 26.5 23.4375C25.8405 23.4375 25.2759 23.0174 25.0428 22.4219H21V26.0781H24.4125C25.4023 26.0781 26.3516 26.4847 27.0515 27.2085L29.0292 29.2536C29.2177 29.1708 29.4251 29.125 29.6429 29.125C30.5107 29.125 31.2143 29.8525 31.2143 30.75C31.2143 31.6475 30.5107 32.375 29.6429 32.375C28.775 32.375 28.0714 31.6475 28.0714 30.75C28.0714 30.5248 28.1157 30.3103 28.1958 30.1154L26.2181 28.0703C25.7392 27.5751 25.0897 27.2969 24.4125 27.2969H21V31.1562C21 32.7254 20.5531 34 19.0357 34C17.6165 34 16.4478 32.8879 16.3004 31.4559C16.0451 31.527 15.775 31.5625 15.5 31.5625C13.7665 31.5625 12.3571 30.1051 12.3571 28.3125C12.3571 27.9367 12.421 27.5711 12.5339 27.2359C11.0509 26.657 10 25.1742 10 23.4375C10 21.8176 10.9183 20.416 12.2491 19.766C11.8219 19.2125 11.5714 18.5117 11.5714 17.75C11.5714 16.191 12.6321 14.891 14.0464 14.5711C13.9679 14.2918 13.9286 13.9922 13.9286 13.6875C13.9286 12.1691 14.9402 10.8895 16.3004 10.534C16.4478 9.11211 17.6165 8 19.0357 8Z"
+ fill={loading ? "gray" : "#fff"}
+ />
+ </svg>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent side="left">
- <p>Add to supermemory.ai</p>
+ {userNotLoggedIn ? (
+ <>You need to login to use this extension.</>
+ ) : (
+ <p>Add to supermemory.ai</p>
+ )}
</TooltipContent>
</Tooltip>
</TooltipProvider>
- <PopoverContent container={portalContainer}>
- <div className="flex flex-col gap-2">
- <p className="font-semibold text-lg">Select a space</p>
+ <PopoverContent
+ key={userNotLoggedIn ? "login" : "spaces"}
+ container={portalContainer}
+ >
+ {userNotLoggedIn ? (
+ <div className="flex flex-col gap-2">
+ <button
+ onClick={() => {
+ window.open("https://supermemory.ai/signin", "_blank");
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md"
+ >
+ Login to supermemory.ai
+ </button>
+ </div>
+ ) : (
+ <div className="flex flex-col gap-2">
+ <Select onValueChange={(value) => setSelectedSpace(value)}>
+ <SelectTrigger className="text-white">
+ <SelectValue
+ className="placeholder:font-semibold placeholder:text-white"
+ placeholder="Select a space"
+ />
+ </SelectTrigger>
+ <SelectContent container={portalContainer}>
+ <SelectGroup>
+ <SelectLabel>Your spaces</SelectLabel>
+ {spacesOptions.map((space) => (
+ <SelectItem key={space.id} value={`${space.id}`}>
+ {space.name}
+ </SelectItem>
+ ))}
+ </SelectGroup>
+ </SelectContent>
+ </Select>
- <button
- onClick={() => {
- sendUrlToAPI([1]);
- }}
- className="bg-slate-700 text-white p-2 rounded-md"
- >
- Add to supermemory.ai
- </button>
- </div>
+ <Label className="text-slate-400" htmlFor="input-note">
+ Add a note
+ </Label>
+ <Textarea
+ value={webNote}
+ onChange={(e) => setWebNote(e.target.value)}
+ placeholder="Add a note"
+ className="text-white"
+ id="input-note"
+ />
+
+ <button
+ onClick={async () => {
+ await sendUrlToAPI(selectedSpace ? [selectedSpace] : []);
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md"
+ >
+ Add to{" "}
+ {selectedSpace
+ ? spacesOptions.find((s) => s.id === parseInt(selectedSpace))
+ ?.name
+ : "supermemory.ai"}
+ </button>
+ </div>
+ )}
</PopoverContent>
</Popover>
{(window.location.host === "twitter.com" ||
window.location.host === "x.com") && (
- <button
- onClick={() => {
- chrome.runtime.sendMessage({ type: "batchImportAll" });
- }}
- className={`${hover && "opacity-100"} group p-2 rounded-l-2xl transition bg-slate-700 border border-white/20 opacity-0 size-4 h-[30vh] absolute flex bottom-6 items-center`}
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 20 20"
- fill="#888B94"
- className="size-4"
- width={24}
- height={24}
+ <Popover open={isPopover2Open} onOpenChange={setIsPopover2Open}>
+ <TooltipProvider>
+ <Tooltip>
+ <TooltipTrigger asChild>
+ <PopoverTrigger
+ className={`${hover || isPopover2Open ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-6 items-center text-lg`}
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="currentColor"
+ className="size-8"
+ >
+ <path d="M12 1.5a.75.75 0 0 1 .75.75V7.5h-1.5V2.25A.75.75 0 0 1 12 1.5ZM11.25 7.5v5.69l-1.72-1.72a.75.75 0 0 0-1.06 1.06l3 3a.75.75 0 0 0 1.06 0l3-3a.75.75 0 1 0-1.06-1.06l-1.72 1.72V7.5h3.75a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-9a3 3 0 0 1 3-3h3.75Z" />
+ </svg>
+ </PopoverTrigger>
+ </TooltipTrigger>
+ <TooltipContent side="left">
+ {userNotLoggedIn ? (
+ <>You need to login to use this extension.</>
+ ) : (
+ <p>Import all twitter bookmarks</p>
+ )}
+ </TooltipContent>
+ </Tooltip>
+ </TooltipProvider>
+ <PopoverContent
+ key={userNotLoggedIn ? "login" : "spaces"}
+ container={portalContainer}
>
- <path
- fillRule="evenodd"
- d="M10 2c-1.716 0-3.408.106-5.07.31C3.806 2.45 3 3.414 3 4.517V17.25a.75.75 0 0 0 1.075.676L10 15.082l5.925 2.844A.75.75 0 0 0 17 17.25V4.517c0-1.103-.806-2.068-1.93-2.207A41.403 41.403 0 0 0 10 2Z"
- clipRule="evenodd"
- />
- </svg>
- </button>
+ {userNotLoggedIn ? (
+ <div className="flex flex-col gap-2">
+ <button
+ onClick={() => {
+ window.open("https://supermemory.ai/signin", "_blank");
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md"
+ >
+ Login to supermemory.ai
+ </button>
+ </div>
+ ) : (
+ <div className="flex flex-col gap-2">
+ <button
+ disabled={isImporting}
+ onClick={async () => {
+ setIsImporting(true);
+ chrome.runtime.sendMessage({ type: "batchImportAll" });
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md disabled:bg-slate-700/50 disabled:pointer-events-none"
+ >
+ Import all Twitter bookmarks
+ </button>
+
+ {isImporting && (
+ <div className="flex items-center gap-2">
+ <p>Imported {importedCount} bookmarks</p>
+ <svg
+ className="animate-spin w-6 h-6"
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke="currentColor"
+ >
+ <path
+ strokeLinecap="round"
+ strokeLinejoin="round"
+ strokeWidth={2}
+ d="M12 6v6m0 0v6m0-6h6m-6 0H6"
+ />
+ </svg>
+ </div>
+ )}
+
+ {importDone && (
+ <p className="text-green-500">
+ All your twitter bookmarks have been imported!
+ </p>
+ )}
+ </div>
+ )}
+ </PopoverContent>
+ </Popover>
)}
</div>
);
diff --git a/apps/extension/content/content.tsx b/apps/extension/content/content.tsx
index f44beacb..9accca62 100644
--- a/apps/extension/content/content.tsx
+++ b/apps/extension/content/content.tsx
@@ -73,7 +73,7 @@ window.addEventListener("message", (event) => {
)
) {
console.log(
- "JWT is only allowed to be used on localhost or anycontext.dhr.wtf",
+ "JWT is only allowed to be used on localhost or supermemory.ai",
);
return;
}
diff --git a/apps/extension/content/ui/shadcn/input.tsx b/apps/extension/content/ui/shadcn/input.tsx
new file mode 100644
index 00000000..96d600b7
--- /dev/null
+++ b/apps/extension/content/ui/shadcn/input.tsx
@@ -0,0 +1,25 @@
+import * as React from "react";
+
+import { cn } from "../../utils";
+
+export interface InputProps
+ extends React.InputHTMLAttributes<HTMLInputElement> {}
+
+const Input = React.forwardRef<HTMLInputElement, InputProps>(
+ ({ className, type, ...props }, ref) => {
+ return (
+ <input
+ type={type}
+ className={cn(
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
+ className,
+ )}
+ ref={ref}
+ {...props}
+ />
+ );
+ },
+);
+Input.displayName = "Input";
+
+export { Input };
diff --git a/apps/extension/content/ui/shadcn/label.tsx b/apps/extension/content/ui/shadcn/label.tsx
new file mode 100644
index 00000000..25199133
--- /dev/null
+++ b/apps/extension/content/ui/shadcn/label.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "../../utils";
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
+);
+
+const Label = React.forwardRef<
+ React.ElementRef<typeof LabelPrimitive.Root>,
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
+ VariantProps<typeof labelVariants>
+>(({ className, ...props }, ref) => (
+ <LabelPrimitive.Root
+ ref={ref}
+ className={cn(labelVariants(), className)}
+ {...props}
+ />
+));
+Label.displayName = LabelPrimitive.Root.displayName;
+
+export { Label };
diff --git a/apps/extension/content/ui/shadcn/popover.tsx b/apps/extension/content/ui/shadcn/popover.tsx
index e896283e..f84f8e46 100644
--- a/apps/extension/content/ui/shadcn/popover.tsx
+++ b/apps/extension/content/ui/shadcn/popover.tsx
@@ -25,7 +25,7 @@ const PopoverContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cn(
- "z-50 w-72 rounded-md border border-border bg-secondary p-4 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
+ "z-50 w-72 mx-4 my-2 rounded-md border border-border bg-secondary p-4 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
diff --git a/apps/extension/content/ui/shadcn/select.tsx b/apps/extension/content/ui/shadcn/select.tsx
new file mode 100644
index 00000000..f90195bd
--- /dev/null
+++ b/apps/extension/content/ui/shadcn/select.tsx
@@ -0,0 +1,162 @@
+"use client";
+
+import * as React from "react";
+import * as SelectPrimitive from "@radix-ui/react-select";
+import { Check, ChevronDown, ChevronUp } from "lucide-react";
+
+import { cn } from "../../utils";
+
+const Select = SelectPrimitive.Root;
+
+const SelectGroup = SelectPrimitive.Group;
+
+const SelectValue = SelectPrimitive.Value;
+
+const SelectTrigger = React.forwardRef<
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
+>(({ className, children, ...props }, ref) => (
+ <SelectPrimitive.Trigger
+ ref={ref}
+ className={cn(
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
+ className,
+ )}
+ {...props}
+ >
+ {children}
+ <SelectPrimitive.Icon asChild>
+ <ChevronDown className="h-4 w-4 opacity-50" />
+ </SelectPrimitive.Icon>
+ </SelectPrimitive.Trigger>
+));
+SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
+
+const SelectScrollUpButton = React.forwardRef<
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
+>(({ className, ...props }, ref) => (
+ <SelectPrimitive.ScrollUpButton
+ ref={ref}
+ className={cn(
+ "flex cursor-default items-center justify-center py-1",
+ className,
+ )}
+ {...props}
+ >
+ <ChevronUp className="h-4 w-4" />
+ </SelectPrimitive.ScrollUpButton>
+));
+SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
+
+const SelectScrollDownButton = React.forwardRef<
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
+>(({ className, ...props }, ref) => (
+ <SelectPrimitive.ScrollDownButton
+ ref={ref}
+ className={cn(
+ "flex cursor-default items-center justify-center py-1",
+ className,
+ )}
+ {...props}
+ >
+ <ChevronDown className="h-4 w-4" />
+ </SelectPrimitive.ScrollDownButton>
+));
+SelectScrollDownButton.displayName =
+ SelectPrimitive.ScrollDownButton.displayName;
+
+const SelectContent = React.forwardRef<
+ React.ElementRef<typeof SelectPrimitive.Content>,
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {
+ container?: Element;
+ }
+>(({ className, children, position = "popper", container, ...props }, ref) => (
+ <SelectPrimitive.Portal container={container}>
+ <SelectPrimitive.Content
+ ref={ref}
+ className={cn(
+ "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
+ position === "popper" &&
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
+ className,
+ )}
+ position={position}
+ {...props}
+ >
+ <SelectScrollUpButton />
+ <SelectPrimitive.Viewport
+ className={cn(
+ "p-1",
+ position === "popper" &&
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
+ )}
+ >
+ {children}
+ </SelectPrimitive.Viewport>
+ <SelectScrollDownButton />
+ </SelectPrimitive.Content>
+ </SelectPrimitive.Portal>
+));
+SelectContent.displayName = SelectPrimitive.Content.displayName;
+
+const SelectLabel = React.forwardRef<
+ React.ElementRef<typeof SelectPrimitive.Label>,
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
+>(({ className, ...props }, ref) => (
+ <SelectPrimitive.Label
+ ref={ref}
+ className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
+ {...props}
+ />
+));
+SelectLabel.displayName = SelectPrimitive.Label.displayName;
+
+const SelectItem = React.forwardRef<
+ React.ElementRef<typeof SelectPrimitive.Item>,
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
+>(({ className, children, ...props }, ref) => (
+ <SelectPrimitive.Item
+ ref={ref}
+ className={cn(
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
+ className,
+ )}
+ {...props}
+ >
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
+ <SelectPrimitive.ItemIndicator>
+ <Check className="h-4 w-4" />
+ </SelectPrimitive.ItemIndicator>
+ </span>
+
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
+ </SelectPrimitive.Item>
+));
+SelectItem.displayName = SelectPrimitive.Item.displayName;
+
+const SelectSeparator = React.forwardRef<
+ React.ElementRef<typeof SelectPrimitive.Separator>,
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
+>(({ className, ...props }, ref) => (
+ <SelectPrimitive.Separator
+ ref={ref}
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
+ {...props}
+ />
+));
+SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
+
+export {
+ Select,
+ SelectGroup,
+ SelectValue,
+ SelectTrigger,
+ SelectContent,
+ SelectLabel,
+ SelectItem,
+ SelectSeparator,
+ SelectScrollUpButton,
+ SelectScrollDownButton,
+};
diff --git a/apps/extension/content/ui/shadcn/textarea.tsx b/apps/extension/content/ui/shadcn/textarea.tsx
new file mode 100644
index 00000000..6ff704d8
--- /dev/null
+++ b/apps/extension/content/ui/shadcn/textarea.tsx
@@ -0,0 +1,24 @@
+import * as React from "react";
+
+import { cn } from "../../utils";
+
+export interface TextareaProps
+ extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
+
+const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
+ ({ className, ...props }, ref) => {
+ return (
+ <textarea
+ className={cn(
+ "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
+ className,
+ )}
+ ref={ref}
+ {...props}
+ />
+ );
+ },
+);
+Textarea.displayName = "Textarea";
+
+export { Textarea };
diff --git a/apps/extension/content/ui/shadcn/tooltip.tsx b/apps/extension/content/ui/shadcn/tooltip.tsx
index b3534220..35b9ffcc 100644
--- a/apps/extension/content/ui/shadcn/tooltip.tsx
+++ b/apps/extension/content/ui/shadcn/tooltip.tsx
@@ -19,7 +19,7 @@ const TooltipContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
- "z-50 overflow-hidden rounded-md border border-white/30 bg-black px-3 py-1.5 text-sm shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
+ "z-50 overflow-hidden rounded-md border border-white/30 text-white bg-black px-3 py-1.5 text-sm shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
diff --git a/apps/extension/content/ui/shadcn/use-toast.ts b/apps/extension/content/ui/shadcn/use-toast.ts
index 2f3870d8..4a64ceb6 100644
--- a/apps/extension/content/ui/shadcn/use-toast.ts
+++ b/apps/extension/content/ui/shadcn/use-toast.ts
@@ -3,7 +3,7 @@
// Inspired by react-hot-toast library
import * as React from "react";
-import type { ToastActionElement, ToastProps } from "content/ui/shadcn/toast";
+import type { ToastActionElement, ToastProps } from "./toast";
const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000;
diff --git a/apps/extension/package.json b/apps/extension/package.json
index e53d0787..a24d8355 100644
--- a/apps/extension/package.json
+++ b/apps/extension/package.json
@@ -20,7 +20,9 @@
"private": true,
"version": "0.0.0",
"dependencies": {
+ "@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
+ "@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-toast": "^1.2.1",
"@radix-ui/react-tooltip": "^1.1.2",
"class-variance-authority": "^0.7.0",
diff --git a/apps/extension/public/output.css b/apps/extension/public/output.css
index 038be1ea..77069c4a 100644
--- a/apps/extension/public/output.css
+++ b/apps/extension/public/output.css
@@ -22,7 +22,7 @@
::before,
::after {
- --tw-content: "";
+ --tw-content: '';
}
/*
@@ -44,10 +44,9 @@ html,
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
- tab-size: 4;
+ tab-size: 4;
/* 3 */
- font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
- "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
font-feature-settings: normal;
/* 5 */
@@ -90,7 +89,7 @@ Add the correct text decoration in Chrome, Edge, and Safari.
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
- text-decoration: underline dotted;
+ text-decoration: underline dotted;
}
/*
@@ -136,8 +135,7 @@ code,
kbd,
samp,
pre {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
- "Liberation Mono", "Courier New", monospace;
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* 1 */
font-feature-settings: normal;
/* 2 */
@@ -238,9 +236,9 @@ select {
*/
button,
-input:where([type="button"]),
-input:where([type="reset"]),
-input:where([type="submit"]) {
+input:where([type='button']),
+input:where([type='reset']),
+input:where([type='submit']) {
-webkit-appearance: button;
/* 1 */
background-color: transparent;
@@ -287,7 +285,7 @@ Correct the cursor style of increment and decrement buttons in Safari.
2. Correct the outline style in Safari.
*/
-[type="search"] {
+[type='search'] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
@@ -380,8 +378,7 @@ textarea {
2. Set the default placeholder color to the user's configured gray 400 color.
*/
-input::-moz-placeholder,
-textarea::-moz-placeholder {
+input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
@@ -454,9 +451,7 @@ video {
scrollbar-width: initial;
}
-*,
-::before,
-::after {
+*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
@@ -598,6 +593,10 @@ video {
pointer-events: auto;
}
+.static {
+ position: static;
+}
+
.fixed {
position: fixed;
}
@@ -663,6 +662,14 @@ video {
top: 50%;
}
+.bottom-12 {
+ bottom: 3rem;
+}
+
+.bottom-8 {
+ bottom: 2rem;
+}
+
.-z-\[1\] {
z-index: -1;
}
@@ -683,6 +690,10 @@ video {
z-index: 100;
}
+.m-4 {
+ margin: 1rem;
+}
+
.-mx-1 {
margin-left: -0.25rem;
margin-right: -0.25rem;
@@ -698,6 +709,16 @@ video {
margin-bottom: 0.25rem;
}
+.mx-4 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+}
+
+.my-2 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
.mb-1 {
margin-bottom: 0.25rem;
}
@@ -765,6 +786,11 @@ video {
height: 2rem;
}
+.size-6 {
+ width: 1.5rem;
+ height: 1.5rem;
+}
+
.h-10 {
height: 2.5rem;
}
@@ -901,6 +927,14 @@ video {
width: 100%;
}
+.w-\[180px\] {
+ width: 180px;
+}
+
+.w-6 {
+ width: 1.5rem;
+}
+
.min-w-\[8rem\] {
min-width: 8rem;
}
@@ -927,43 +961,41 @@ video {
.translate-x-3\/4 {
--tw-translate-x: 75%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-x-5 {
--tw-translate-x: 1.25rem;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-x-\[-50\%\] {
--tw-translate-x: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-y-12 {
--tw-translate-y: 3rem;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-y-\[-50\%\] {
--tw-translate-y: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.transform {
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.animate-spin {
+ animation: spin 1s linear infinite;
}
.cursor-default {
@@ -980,8 +1012,8 @@ video {
.select-none {
-webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
+ -moz-user-select: none;
+ user-select: none;
}
.flex-col {
@@ -1223,11 +1255,7 @@ video {
}
.bg-page-gradient {
- background-image: radial-gradient(
- ellipse 80% 50% at 50% -20%,
- rgba(120, 119, 198, 0.3),
- transparent
- );
+ background-image: radial-gradient(ellipse 80% 50% at 50% -20%,rgba(120, 119, 198, 0.3), transparent);
}
.fill-current {
@@ -1380,11 +1408,6 @@ video {
line-height: 1rem;
}
-.text-xl {
- font-size: 1.25rem;
- line-height: 1.75rem;
-}
-
.font-medium {
font-weight: 500;
}
@@ -1393,10 +1416,6 @@ video {
font-weight: 600;
}
-.italic {
- font-style: italic;
-}
-
.leading-none {
line-height: 1;
}
@@ -1437,6 +1456,11 @@ video {
color: var(--primary);
}
+.text-white {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
.text-zinc-200 {
--tw-text-opacity: 1;
color: rgb(228 228 231 / var(--tw-text-opacity));
@@ -1447,9 +1471,14 @@ video {
color: rgb(113 113 122 / var(--tw-text-opacity));
}
-.text-white {
+.text-slate-400 {
--tw-text-opacity: 1;
- color: rgb(255 255 255 / var(--tw-text-opacity));
+ color: rgb(148 163 184 / var(--tw-text-opacity));
+}
+
+.text-green-500 {
+ --tw-text-opacity: 1;
+ color: rgb(34 197 94 / var(--tw-text-opacity));
}
.underline-offset-4 {
@@ -1486,34 +1515,26 @@ video {
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color),
- 0 1px 2px -1px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
- var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-lg {
- --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1),
- 0 4px 6px -4px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color),
- 0 4px 6px -4px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
- var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+ --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-md {
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color),
- 0 2px 4px -2px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
- var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+ --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-sm {
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
- var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.outline-none {
@@ -1526,12 +1547,9 @@ video {
}
.ring-0 {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
- var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0
- calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
- var(--tw-shadow, 0 0 #0000);
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.ring-offset-background {
@@ -1539,54 +1557,19 @@ video {
}
.filter {
- filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast)
- var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate)
- var(--tw-sepia) var(--tw-drop-shadow);
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.backdrop-blur-sm {
--tw-backdrop-blur: blur(4px);
- -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness)
- var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale)
- var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert)
- var(--tw-backdrop-opacity) var(--tw-backdrop-saturate)
- var(--tw-backdrop-sepia);
- backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness)
- var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale)
- var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert)
- var(--tw-backdrop-opacity) var(--tw-backdrop-saturate)
- var(--tw-backdrop-sepia);
+ -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
+ backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.transition {
- transition-property:
- color,
- background-color,
- border-color,
- text-decoration-color,
- fill,
- stroke,
- opacity,
- box-shadow,
- transform,
- filter,
- -webkit-backdrop-filter;
- transition-property: color, background-color, border-color,
- text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter,
- backdrop-filter;
- transition-property:
- color,
- background-color,
- border-color,
- text-decoration-color,
- fill,
- stroke,
- opacity,
- box-shadow,
- transform,
- filter,
- backdrop-filter,
- -webkit-backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
@@ -1598,8 +1581,7 @@ video {
}
.transition-colors {
- transition-property: color, background-color, border-color,
- text-decoration-color, fill, stroke;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
@@ -1623,34 +1605,14 @@ video {
@keyframes enter {
from {
opacity: var(--tw-enter-opacity, 1);
- transform: translate3d(
- var(--tw-enter-translate-x, 0),
- var(--tw-enter-translate-y, 0),
- 0
- )
- scale3d(
- var(--tw-enter-scale, 1),
- var(--tw-enter-scale, 1),
- var(--tw-enter-scale, 1)
- )
- rotate(var(--tw-enter-rotate, 0));
+ transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0) scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0));
}
}
@keyframes exit {
to {
opacity: var(--tw-exit-opacity, 1);
- transform: translate3d(
- var(--tw-exit-translate-x, 0),
- var(--tw-exit-translate-y, 0),
- 0
- )
- scale3d(
- var(--tw-exit-scale, 1),
- var(--tw-exit-scale, 1),
- var(--tw-exit-scale, 1)
- )
- rotate(var(--tw-exit-rotate, 0));
+ transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0));
}
}
@@ -1669,21 +1631,15 @@ video {
}
.zoom-in-95 {
- --tw-enter-scale: 0.95;
+ --tw-enter-scale: .95;
}
.duration-200 {
animation-duration: 200ms;
}
-.\[background\:linear-gradient\(\#2E2E32\2c
- \#2E2E32\)\2c
- linear-gradient\(120deg\2c
- theme\(colors\.zinc\.700\)\2c
- theme\(colors\.zinc\.700\/0\)\2c
- theme\(colors\.zinc\.700\)\)\] {
- background: linear-gradient(#2e2e32, #2e2e32),
- linear-gradient(120deg, #3f3f46, rgb(63 63 70 / 0), #3f3f46);
+.\[background\:linear-gradient\(\#2E2E32\2c \#2E2E32\)\2c linear-gradient\(120deg\2c theme\(colors\.zinc\.700\)\2c theme\(colors\.zinc\.700\/0\)\2c theme\(colors\.zinc\.700\)\)\] {
+ background: linear-gradient(#2E2E32,#2E2E32),linear-gradient(120deg,#3f3f46,rgb(63 63 70 / 0),#3f3f46);
}
:root {
@@ -1846,6 +1802,14 @@ body {
font-weight: 500;
}
+.placeholder\:font-semibold::-moz-placeholder {
+ font-weight: 600;
+}
+
+.placeholder\:font-semibold::placeholder {
+ font-weight: 600;
+}
+
.placeholder\:text-muted::-moz-placeholder {
color: hsl(var(--muted));
}
@@ -1862,11 +1826,19 @@ body {
color: hsl(var(--muted-foreground));
}
+.placeholder\:text-white::-moz-placeholder {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
+.placeholder\:text-white::placeholder {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
.focus-within\:translate-x-0:focus-within {
--tw-translate-x: 0px;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group:focus-within .group-focus-within\:block {
@@ -1915,12 +1887,9 @@ body {
}
.group.toaster .group-\[\.toaster\]\:shadow-lg {
- --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1),
- 0 4px 6px -4px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color),
- 0 4px 6px -4px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
- var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+ --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.peer:disabled ~ .peer-disabled\:cursor-not-allowed {
@@ -1939,7 +1908,7 @@ body {
color: hsl(var(--accent-foreground));
}
-.data-\[disabled\=true\]\:pointer-events-none[data-disabled="true"] {
+.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true] {
pointer-events: none;
}
@@ -1947,67 +1916,49 @@ body {
pointer-events: none;
}
-.data-\[side\=bottom\]\:translate-y-1[data-side="bottom"] {
+.data-\[side\=bottom\]\:translate-y-1[data-side=bottom] {
--tw-translate-y: 0.25rem;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[side\=left\]\:-translate-x-1[data-side="left"] {
+.data-\[side\=left\]\:-translate-x-1[data-side=left] {
--tw-translate-x: -0.25rem;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[side\=right\]\:translate-x-1[data-side="right"] {
+.data-\[side\=right\]\:translate-x-1[data-side=right] {
--tw-translate-x: 0.25rem;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[side\=top\]\:-translate-y-1[data-side="top"] {
+.data-\[side\=top\]\:-translate-y-1[data-side=top] {
--tw-translate-y: -0.25rem;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[state\=checked\]\:translate-x-5[data-state="checked"] {
+.data-\[state\=checked\]\:translate-x-5[data-state=checked] {
--tw-translate-x: 1.25rem;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[state\=unchecked\]\:translate-x-0[data-state="unchecked"] {
+.data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked] {
--tw-translate-x: 0px;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[swipe\=cancel\]\:translate-x-0[data-swipe="cancel"] {
+.data-\[swipe\=cancel\]\:translate-x-0[data-swipe=cancel] {
--tw-translate-x: 0px;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[swipe\=end\]\:translate-x-\[var\(--radix-toast-swipe-end-x\)\][data-swipe="end"] {
+.data-\[swipe\=end\]\:translate-x-\[var\(--radix-toast-swipe-end-x\)\][data-swipe=end] {
--tw-translate-x: var(--radix-toast-swipe-end-x);
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-.data-\[swipe\=move\]\:translate-x-\[var\(--radix-toast-swipe-move-x\)\][data-swipe="move"] {
+.data-\[swipe\=move\]\:translate-x-\[var\(--radix-toast-swipe-move-x\)\][data-swipe=move] {
--tw-translate-x: var(--radix-toast-swipe-move-x);
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
@keyframes accordion-up {
@@ -2020,7 +1971,7 @@ body {
}
}
-.data-\[state\=closed\]\:animate-accordion-up[data-state="closed"] {
+.data-\[state\=closed\]\:animate-accordion-up[data-state=closed] {
animation: accordion-up 0.2s ease-out;
}
@@ -2034,39 +1985,39 @@ body {
}
}
-.data-\[state\=open\]\:animate-accordion-down[data-state="open"] {
+.data-\[state\=open\]\:animate-accordion-down[data-state=open] {
animation: accordion-down 0.2s ease-out;
}
-.data-\[state\=active\]\:bg-background[data-state="active"] {
+.data-\[state\=active\]\:bg-background[data-state=active] {
background-color: var(--background);
}
-.data-\[state\=checked\]\:bg-primary[data-state="checked"] {
+.data-\[state\=checked\]\:bg-primary[data-state=checked] {
background-color: var(--primary);
}
-.data-\[state\=open\]\:bg-accent[data-state="open"] {
+.data-\[state\=open\]\:bg-accent[data-state=open] {
background-color: hsl(var(--accent));
}
-.data-\[state\=open\]\:bg-secondary[data-state="open"] {
+.data-\[state\=open\]\:bg-secondary[data-state=open] {
background-color: var(--secondary);
}
-.data-\[state\=unchecked\]\:bg-input[data-state="unchecked"] {
+.data-\[state\=unchecked\]\:bg-input[data-state=unchecked] {
background-color: hsl(var(--input));
}
-.data-\[state\=active\]\:text-foreground[data-state="active"] {
+.data-\[state\=active\]\:text-foreground[data-state=active] {
color: var(--foreground);
}
-.data-\[state\=open\]\:text-muted-foreground[data-state="open"] {
+.data-\[state\=open\]\:text-muted-foreground[data-state=open] {
color: hsl(var(--muted-foreground));
}
-.data-\[disabled\=true\]\:opacity-50[data-disabled="true"] {
+.data-\[disabled\=true\]\:opacity-50[data-disabled=true] {
opacity: 0.5;
}
@@ -2074,18 +2025,17 @@ body {
opacity: 0.5;
}
-.data-\[state\=active\]\:shadow-sm[data-state="active"] {
+.data-\[state\=active\]\:shadow-sm[data-state=active] {
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
- var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
-.data-\[swipe\=move\]\:transition-none[data-swipe="move"] {
+.data-\[swipe\=move\]\:transition-none[data-swipe=move] {
transition-property: none;
}
-.data-\[state\=open\]\:animate-in[data-state="open"] {
+.data-\[state\=open\]\:animate-in[data-state=open] {
animation-name: enter;
animation-duration: 150ms;
--tw-enter-opacity: initial;
@@ -2095,7 +2045,7 @@ body {
--tw-enter-translate-y: initial;
}
-.data-\[state\=closed\]\:animate-out[data-state="closed"] {
+.data-\[state\=closed\]\:animate-out[data-state=closed] {
animation-name: exit;
animation-duration: 150ms;
--tw-exit-opacity: initial;
@@ -2105,7 +2055,7 @@ body {
--tw-exit-translate-y: initial;
}
-.data-\[swipe\=end\]\:animate-out[data-swipe="end"] {
+.data-\[swipe\=end\]\:animate-out[data-swipe=end] {
animation-name: exit;
animation-duration: 150ms;
--tw-exit-opacity: initial;
@@ -2115,63 +2065,63 @@ body {
--tw-exit-translate-y: initial;
}
-.data-\[state\=closed\]\:fade-out-0[data-state="closed"] {
+.data-\[state\=closed\]\:fade-out-0[data-state=closed] {
--tw-exit-opacity: 0;
}
-.data-\[state\=closed\]\:fade-out-80[data-state="closed"] {
+.data-\[state\=closed\]\:fade-out-80[data-state=closed] {
--tw-exit-opacity: 0.8;
}
-.data-\[state\=open\]\:fade-in-0[data-state="open"] {
+.data-\[state\=open\]\:fade-in-0[data-state=open] {
--tw-enter-opacity: 0;
}
-.data-\[state\=closed\]\:zoom-out-95[data-state="closed"] {
- --tw-exit-scale: 0.95;
+.data-\[state\=closed\]\:zoom-out-95[data-state=closed] {
+ --tw-exit-scale: .95;
}
-.data-\[state\=open\]\:zoom-in-95[data-state="open"] {
- --tw-enter-scale: 0.95;
+.data-\[state\=open\]\:zoom-in-95[data-state=open] {
+ --tw-enter-scale: .95;
}
-.data-\[side\=bottom\]\:slide-in-from-top-2[data-side="bottom"] {
+.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom] {
--tw-enter-translate-y: -0.5rem;
}
-.data-\[side\=left\]\:slide-in-from-right-2[data-side="left"] {
+.data-\[side\=left\]\:slide-in-from-right-2[data-side=left] {
--tw-enter-translate-x: 0.5rem;
}
-.data-\[side\=right\]\:slide-in-from-left-2[data-side="right"] {
+.data-\[side\=right\]\:slide-in-from-left-2[data-side=right] {
--tw-enter-translate-x: -0.5rem;
}
-.data-\[side\=top\]\:slide-in-from-bottom-2[data-side="top"] {
+.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top] {
--tw-enter-translate-y: 0.5rem;
}
-.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state="closed"] {
+.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed] {
--tw-exit-translate-x: -50%;
}
-.data-\[state\=closed\]\:slide-out-to-right-full[data-state="closed"] {
+.data-\[state\=closed\]\:slide-out-to-right-full[data-state=closed] {
--tw-exit-translate-x: 100%;
}
-.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state="closed"] {
+.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed] {
--tw-exit-translate-y: -48%;
}
-.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state="open"] {
+.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open] {
--tw-enter-translate-x: -50%;
}
-.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state="open"] {
+.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open] {
--tw-enter-translate-y: -48%;
}
-.data-\[state\=open\]\:slide-in-from-top-full[data-state="open"] {
+.data-\[state\=open\]\:slide-in-from-top-full[data-state=open] {
--tw-enter-translate-y: -100%;
}
@@ -2205,11 +2155,7 @@ body {
}
.hover\:bg-page-gradient:hover {
- background-image: radial-gradient(
- ellipse 80% 50% at 50% -20%,
- rgba(120, 119, 198, 0.3),
- transparent
- );
+ background-image: radial-gradient(ellipse 80% 50% at 50% -20%,rgba(120, 119, 198, 0.3), transparent);
}
.hover\:text-accent-foreground:hover {
@@ -2228,8 +2174,7 @@ body {
opacity: 1;
}
-.group.destructive
- .group-\[\.destructive\]\:hover\:border-destructive\/30:hover {
+.group.destructive .group-\[\.destructive\]\:hover\:border-destructive\/30:hover {
border-color: hsl(var(--destructive) / 0.3);
}
@@ -2237,8 +2182,7 @@ body {
background-color: hsl(var(--destructive));
}
-.group.destructive
- .group-\[\.destructive\]\:hover\:text-destructive-foreground:hover {
+.group.destructive .group-\[\.destructive\]\:hover\:text-destructive-foreground:hover {
color: hsl(var(--destructive-foreground));
}
@@ -2255,6 +2199,10 @@ body {
background-color: var(--secondary);
}
+.focus\:bg-accent:focus {
+ background-color: hsl(var(--accent));
+}
+
.focus\:text-accent-foreground:focus {
color: hsl(var(--accent-foreground));
}
@@ -2269,12 +2217,9 @@ body {
}
.focus\:ring-2:focus {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
- var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0
- calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
- var(--tw-shadow, 0 0 #0000);
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.focus\:ring-ring:focus {
@@ -2300,9 +2245,7 @@ body {
.focus-visible\:translate-x-0:focus-visible {
--tw-translate-x: 0px;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.focus-visible\:outline-none:focus-visible {
@@ -2311,12 +2254,9 @@ body {
}
.focus-visible\:ring-2:focus-visible {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
- var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0
- calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
- var(--tw-shadow, 0 0 #0000);
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.focus-visible\:ring-ring:focus-visible {
@@ -2339,6 +2279,14 @@ body {
cursor: not-allowed;
}
+.disabled\:bg-slate-700\/50:disabled {
+ background-color: rgb(51 65 85 / 0.5);
+}
+
+.disabled\:text-slate-700\/50:disabled {
+ color: rgb(51 65 85 / 0.5);
+}
+
.disabled\:opacity-50:disabled {
opacity: 0.5;
}
@@ -2378,7 +2326,7 @@ body {
text-align: left;
}
- .data-\[state\=open\]\:sm\:slide-in-from-bottom-full[data-state="open"] {
+ .data-\[state\=open\]\:sm\:slide-in-from-bottom-full[data-state=open] {
--tw-enter-translate-y: 100%;
}
}
@@ -2389,18 +2337,16 @@ body {
}
}
-.\[\&\>span\]\:line-clamp-1 > span {
+.\[\&\>span\]\:line-clamp-1>span {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
-.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state="open"] > svg {
+.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg {
--tw-rotate: 180deg;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y))
- rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
- scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading] {
@@ -2426,9 +2372,7 @@ body {
color: hsl(var(--muted-foreground));
}
-.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0
- [cmdk-group]:not([hidden])
- ~ [cmdk-group] {
+.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden]) ~[cmdk-group] {
padding-top: 0px;
}
diff --git a/apps/web/app/api/ensureAuth.ts b/apps/web/app/api/ensureAuth.ts
index d2fbac0b..d2c14b3b 100644
--- a/apps/web/app/api/ensureAuth.ts
+++ b/apps/web/app/api/ensureAuth.ts
@@ -22,7 +22,7 @@ export async function ensureAuth(req: NextRequest) {
.innerJoin(users, eq(users.id, sessions.userId))
.where(eq(sessions.sessionToken, token!));
- if (!sessionData || sessionData.length < 0) {
+ if (!sessionData || sessionData.length === 0) {
return undefined;
}
diff --git a/apps/web/app/api/store/route.ts b/apps/web/app/api/store/route.ts
index d9f99277..26636c5c 100644
--- a/apps/web/app/api/store/route.ts
+++ b/apps/web/app/api/store/route.ts
@@ -84,11 +84,7 @@ const createMemoryFromAPI = async (input: {
const error = e as Error;
console.log("Error: ", error.message);
- if (
- error.message.includes(
- "D1_ERROR: UNIQUE constraint failed: storedContent.baseUrl",
- )
- ) {
+ if (error.message.includes("D1_ERROR: UNIQUE constraint failed:")) {
return {
success: false,
data: 0,
@@ -204,9 +200,15 @@ export async function POST(req: NextRequest) {
message: "Failed to save document",
error: result.error,
}),
- { status: 500 },
+ { status: 501 },
);
}
- return new Response("ok", { status: 200 });
+ return new Response(
+ JSON.stringify({
+ message: "Document saved",
+ data: result.data,
+ }),
+ { status: 200 },
+ );
}
diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts
index b6cc4548..58ac535c 100644
--- a/apps/web/middleware.ts
+++ b/apps/web/middleware.ts
@@ -1,13 +1,24 @@
-// middleware.js
import { NextRequest, NextResponse } from "next/server";
+const corsHeaders = {
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
+ "Access-Control-Allow-Headers": "Content-Type, Authorization",
+};
+
export function middleware(request: NextRequest) {
- const requestHeaders = new Headers(request.headers);
- requestHeaders.set("x-pathname", request.nextUrl.pathname);
+ if (request.method === "OPTIONS") {
+ return new NextResponse(null, { headers: corsHeaders });
+ }
- return NextResponse.next({
- request: {
- headers: requestHeaders,
- },
+ const response = NextResponse.next();
+ Object.entries(corsHeaders).forEach(([key, value]) => {
+ response.headers.set(key, value);
});
+
+ return response;
}
+
+export const config = {
+ matcher: "/api/:path*",
+};