diff --git a/app/page.tsx b/app/page.tsx
index 8aac3a14..2e2179db 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -9,7 +9,7 @@ import { Header } from "@/components/home/header";
import { Hero } from "@/components/home/hero";
import { HowItWorks } from "@/components/home/how-it-works";
import { Roadmap } from "@/components/home/roadmap";
-import { Testimonials } from "@/components/home/testimonials";
+import { ThemeHotKeyHandler } from "@/components/home/theme-hotkey-handler";
import { ThemePresetSelector } from "@/components/home/theme-preset-selector";
import { useEffect, useState } from "react";
@@ -19,7 +19,7 @@ export default function Home() {
useEffect(() => {
const handleScroll = () => {
- if (window.scrollY > 10) {
+ if (window.scrollY > 10){
setIsScrolled(true);
} else {
setIsScrolled(false);
@@ -32,6 +32,7 @@ export default function Home() {
return (
+
-
@@ -49,6 +49,7 @@ export default function Home() {
+
);
}
diff --git a/components/editor/keyboard-shortcut-overlay.tsx b/components/editor/keyboard-shortcut-overlay.tsx
new file mode 100644
index 00000000..36e8d8e6
--- /dev/null
+++ b/components/editor/keyboard-shortcut-overlay.tsx
@@ -0,0 +1,180 @@
+"use client";
+
+import React, { useState, useEffect, useRef, useCallback } from 'react';
+import { X } from 'lucide-react';
+import { cn } from '@/lib/utils';
+import { ScrollArea } from '@/components/ui/scroll-area';
+
+interface KeyboardShortcutsOverlayProps {
+ children: React.ReactNode;
+}
+
+const KeyboardShortcutsOverlay: React.FC = ({ children }) => {
+ const [isVisible, setIsVisible] = useState(false);
+ const overlayRef = useRef(null);
+
+ const shortcuts = [
+ {
+ category: "EDITING",
+ items: [
+ { action: "Apply random theme", keys: ["Space"] },
+ { action: "Undo", keys: ["Ctrl", "Z"] },
+ { action: "Redo", keys: ["Ctrl", "Y"] },
+ { action: "Reset to current preset", keys: ["Ctrl", "R"] },
+ { action: "Save theme", keys: ["Ctrl", "S"] },
+ ]
+ },
+ {
+ category: "NAVIGATION",
+ items: [
+ { action: "Next theme", keys: ["Ctrl", "→"] },
+ { action: "Previous theme", keys: ["Ctrl", "←"] },
+ { action: "Open AI tab", fun: () => console.log("Open AI Tab (Ctrl+Shift+O)"), keys: ["Ctrl", "Shift", "O"] },
+ { action: "Toggle code panel", keys: ["Ctrl", "B"] },
+ ]
+ },
+ {
+ category: "COPY",
+ items: [
+ { action: "Copy theme CSS", keys: ["Ctrl", "Shift", "C"] },
+ { action: "Copy registry command", keys: ["Ctrl", "Alt", "C"] },
+ ]
+ },
+ {
+ category: "HELP",
+ items: [
+ { action: "Show/hide shortcuts", keys: ["Ctrl", "/"] },
+ ]
+ }
+ ];
+
+ const handleClose = useCallback(() => {
+ setIsVisible(false);
+ }, []);
+
+ useEffect(() => {
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (event.ctrlKey && event.code === 'Slash') {
+ event.preventDefault();
+ setIsVisible(prev => !prev);
+ return;
+ }
+
+
+ if (event.code === 'Escape' && isVisible) {
+ event.preventDefault();
+ handleClose();
+ return;
+ }
+ };
+
+ const handleClickOutside = (event: MouseEvent) => {
+ if (isVisible && overlayRef.current && !overlayRef.current.contains(event.target as Node)) {
+ handleClose();
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ document.addEventListener('mousedown', handleClickOutside);
+
+ return () => {
+ window.removeEventListener('keydown', handleKeyDown);
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, [isVisible, handleClose]);
+
+ useEffect(() => {
+ if (isVisible) {
+ document.body.style.overflow = 'hidden';
+ } else {
+ document.body.style.overflow = '';
+ }
+ return () => {
+ document.body.style.overflow = '';
+ };
+ }, [isVisible]);
+
+ const KeyBadge: React.FC<{ keyName: string; className?: string }> = ({ keyName, className }) => (
+
+ {keyName}
+
+ );
+
+ return (
+ <>
+ {children}
+ {isVisible && (
+
+
+
+
+
+ ⌘
+
+
Keyboard Shortcuts
+
+
+
+
+
+
+ Speed up your theme editing workflow with these keyboard shortcuts.
+
+
+
+ {shortcuts.map((category, categoryIndex) => (
+
+
+ {category.category}
+
+
+ {category.items.map((shortcut, index) => (
+
+
+ {shortcut.action}
+
+
+ {shortcut.keys.map((key, keyIndex) => (
+
+
+ {keyIndex < shortcut.keys.length - 1 && (
+ +
+ )}
+
+ ))}
+
+
+ ))}
+
+
+ ))}
+
+
+
+
+ )}
+ >
+ );
+};
+
+export default KeyboardShortcutsOverlay;
\ No newline at end of file
diff --git a/components/home/theme-hotkey-handler.tsx b/components/home/theme-hotkey-handler.tsx
new file mode 100644
index 00000000..a9da91e0
--- /dev/null
+++ b/components/home/theme-hotkey-handler.tsx
@@ -0,0 +1,60 @@
+"use client"
+import { useClient } from "@/hooks/use-client"
+import { useEditorStore } from "@/store/editor-store"
+import { defaultPresets } from "@/utils/theme-presets"
+import { useEffect, useMemo } from "react"
+
+
+export const ThemeHotKeyHandler = ({children}:{children:React.ReactNode}) => {
+
+ const { themeState, applyThemePreset } = useEditorStore()
+
+ const availableThemes = useMemo(() => Object.keys(defaultPresets),[])
+ const isClient = useClient()
+
+ const applyRandomTheme = () => {
+
+ if(!isClient) return;
+
+ const currentTheme = themeState.preset
+ const otherThemes = availableThemes.filter(theme => theme != currentTheme)
+
+ if(otherThemes.length > 0){
+ const randomIndex = Math.floor(Math.random()* otherThemes.length)
+ const randomTheme = otherThemes[randomIndex]
+ applyThemePreset(randomTheme)
+ }
+ }
+
+ useEffect(() => {
+
+ if(!isClient) return;
+
+ const handleKeySpaceStroke = (event: KeyboardEvent) => {
+ if(!event.target || !(event.target instanceof HTMLElement)) return;
+
+ if(event.code === "Space" &&
+ event.target.tagName !== "INPUT" &&
+ event.target.tagName !== "TEXTAREA" &&
+ !event.target.isContentEditable &&
+ !event.target.closest('[contenteditable="true"]')) {
+
+ event.preventDefault();
+ applyRandomTheme();
+ }
+ };
+
+ window.addEventListener('keydown', handleKeySpaceStroke);
+
+
+ return () => {
+ window.removeEventListener('keydown', handleKeySpaceStroke);
+ };
+ }, [isClient, themeState.preset]);
+
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/hooks/use-client.ts b/hooks/use-client.ts
new file mode 100644
index 00000000..fea0ad98
--- /dev/null
+++ b/hooks/use-client.ts
@@ -0,0 +1,15 @@
+"use client"
+
+import { useEffect, useState } from "react";
+
+export function useClient(){
+
+ const [isClient,setIsClient] = useState(false)
+
+ useEffect(() => {
+
+ setIsClient(true)
+ },[])
+
+ return isClient;
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 1cd2f8bc..4ebaa7a7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,9 @@
"@hookform/resolvers": "^5.0.1",
"@lexical/react": "^0.31.0",
"@neondatabase/serverless": "^1.0.0",
+ "@polar-sh/checkout": "^0.1.11",
+ "@polar-sh/nextjs": "^0.4.3",
+ "@polar-sh/sdk": "^0.34.5",
"@radix-ui/react-accordion": "^1.2.7",
"@radix-ui/react-alert-dialog": "^1.1.10",
"@radix-ui/react-aspect-ratio": "^1.1.4",
@@ -67,12 +70,13 @@
"dotenv": "^16.5.0",
"drizzle-orm": "^0.42.0",
"embla-carousel-react": "^8.6.0",
+ "idb-keyval": "^6.2.2",
"input-otp": "^1.4.2",
"isbot": "^5.1.26",
"lexical": "^0.31.0",
"lucide-react": "^0.488.0",
"motion": "^12.7.3",
- "next": "15.3.0",
+ "next": "15.4.1",
"next-themes": "^0.4.6",
"nuqs": "^2.4.3",
"openai": "^4.96.2",
@@ -80,10 +84,12 @@
"react": "^19.0.0",
"react-day-picker": "^9.6.7",
"react-dom": "^19.0.0",
+ "react-dropzone": "^14.3.8",
"react-hook-form": "^7.55.0",
"react-resizable-panels": "^2.1.7",
"recharts": "^2.15.2",
"screenfull": "^6.0.2",
+ "server-only": "^0.0.1",
"shadcn": "^2.5.0",
"sonner": "^2.0.3",
"swr": "^2.3.3",
@@ -4052,17 +4058,16 @@
}
},
"node_modules/@modelcontextprotocol/sdk": {
- "version": "1.15.1",
- "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.15.1.tgz",
- "integrity": "sha512-W/XlN9c528yYn+9MQkVjxiTPgPxoxt+oczfjHBDsJx0+59+O7B75Zhsp0B16Xbwbz8ANISDajh6+V7nIcPMc5w==",
- "license": "MIT",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.9.0.tgz",
+ "integrity": "sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==",
+ "optional": true,
+ "peer": true,
"dependencies": {
- "ajv": "^6.12.6",
"content-type": "^1.0.5",
"cors": "^2.8.5",
- "cross-spawn": "^7.0.5",
+ "cross-spawn": "^7.0.3",
"eventsource": "^3.0.2",
- "eventsource-parser": "^3.0.0",
"express": "^5.0.1",
"express-rate-limit": "^7.5.0",
"pkce-challenge": "^5.0.0",
@@ -4127,10 +4132,9 @@
}
},
"node_modules/@next/env": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.0.tgz",
- "integrity": "sha512-6mDmHX24nWlHOlbwUiAOmMyY7KELimmi+ed8qWcJYjqXeC+G6JzPZ3QosOAfjNwgMIzwhXBiRiCgdh8axTTdTA==",
- "license": "MIT"
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-15.4.1.tgz",
+ "integrity": "sha512-DXQwFGAE2VH+f2TJsKepRXpODPU+scf5fDbKOME8MMyeyswe4XwgRdiiIYmBfkXU+2ssliLYznajTrOQdnLR5A=="
},
"node_modules/@next/eslint-plugin-next": {
"version": "15.3.0",
@@ -4143,13 +4147,12 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.0.tgz",
- "integrity": "sha512-PDQcByT0ZfF2q7QR9d+PNj3wlNN4K6Q8JoHMwFyk252gWo4gKt7BF8Y2+KBgDjTFBETXZ/TkBEUY7NIIY7A/Kw==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.1.tgz",
+ "integrity": "sha512-L+81yMsiHq82VRXS2RVq6OgDwjvA4kDksGU8hfiDHEXP+ncKIUhUsadAVB+MRIp2FErs/5hpXR0u2eluWPAhig==",
"cpu": [
"arm64"
],
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -4159,13 +4162,12 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.0.tgz",
- "integrity": "sha512-m+eO21yg80En8HJ5c49AOQpFDq+nP51nu88ZOMCorvw3g//8g1JSUsEiPSiFpJo1KCTQ+jm9H0hwXK49H/RmXg==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.4.1.tgz",
+ "integrity": "sha512-jfz1RXu6SzL14lFl05/MNkcN35lTLMJWPbqt7Xaj35+ZWAX342aePIJrN6xBdGeKl6jPXJm0Yqo3Xvh3Gpo3Uw==",
"cpu": [
"x64"
],
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -4175,13 +4177,12 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.0.tgz",
- "integrity": "sha512-H0Kk04ZNzb6Aq/G6e0un4B3HekPnyy6D+eUBYPJv9Abx8KDYgNMWzKt4Qhj57HXV3sTTjsfc1Trc1SxuhQB+Tg==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.4.1.tgz",
+ "integrity": "sha512-k0tOFn3dsnkaGfs6iQz8Ms6f1CyQe4GacXF979sL8PNQxjYS1swx9VsOyUQYaPoGV8nAZ7OX8cYaeiXGq9ahPQ==",
"cpu": [
"arm64"
],
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -4191,13 +4192,12 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.0.tgz",
- "integrity": "sha512-k8GVkdMrh/+J9uIv/GpnHakzgDQhrprJ/FbGQvwWmstaeFG06nnAoZCJV+wO/bb603iKV1BXt4gHG+s2buJqZA==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.4.1.tgz",
+ "integrity": "sha512-4ogGQ/3qDzbbK3IwV88ltihHFbQVq6Qr+uEapzXHXBH1KsVBZOB50sn6BWHPcFjwSoMX2Tj9eH/fZvQnSIgc3g==",
"cpu": [
"arm64"
],
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -4207,13 +4207,12 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.0.tgz",
- "integrity": "sha512-ZMQ9yzDEts/vkpFLRAqfYO1wSpIJGlQNK9gZ09PgyjBJUmg8F/bb8fw2EXKgEaHbCc4gmqMpDfh+T07qUphp9A==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.4.1.tgz",
+ "integrity": "sha512-Jj0Rfw3wIgp+eahMz/tOGwlcYYEFjlBPKU7NqoOkTX0LY45i5W0WcDpgiDWSLrN8KFQq/LW7fZq46gxGCiOYlQ==",
"cpu": [
"x64"
],
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -4223,13 +4222,12 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.0.tgz",
- "integrity": "sha512-RFwq5VKYTw9TMr4T3e5HRP6T4RiAzfDJ6XsxH8j/ZeYq2aLsBqCkFzwMI0FmnSsLaUbOb46Uov0VvN3UciHX5A==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.4.1.tgz",
+ "integrity": "sha512-9WlEZfnw1vFqkWsTMzZDgNL7AUI1aiBHi0S2m8jvycPyCq/fbZjtE/nDkhJRYbSjXbtRHYLDBlmP95kpjEmJbw==",
"cpu": [
"x64"
],
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -4239,13 +4237,12 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.0.tgz",
- "integrity": "sha512-a7kUbqa/k09xPjfCl0RSVAvEjAkYBYxUzSVAzk2ptXiNEL+4bDBo9wNC43G/osLA/EOGzG4CuNRFnQyIHfkRgQ==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.4.1.tgz",
+ "integrity": "sha512-WodRbZ9g6CQLRZsG3gtrA9w7Qfa9BwDzhFVdlI6sV0OCPq9JrOrJSp9/ioLsezbV8w9RCJ8v55uzJuJ5RgWLZg==",
"cpu": [
"arm64"
],
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -4255,13 +4252,12 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.0.tgz",
- "integrity": "sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.4.1.tgz",
+ "integrity": "sha512-y+wTBxelk2xiNofmDOVU7O5WxTHcvOoL3srOM0kxTzKDjQ57kPU0tpnPJ/BWrRnsOwXEv0+3QSbGR7hY4n9LkQ==",
"cpu": [
"x64"
],
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -4432,6 +4428,201 @@
"tslib": "^2.8.1"
}
},
+ "node_modules/@polar-sh/adapter-utils": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@polar-sh/adapter-utils/-/adapter-utils-0.2.2.tgz",
+ "integrity": "sha512-BlQHNvykZF7d+v9IFdKv52FcZt7ijSvu/8SCjCKM+kM+L7VIvrkC4qGHplMLLUHn7HYrZ+te0k77Q7SugBF0/Q==",
+ "dependencies": {
+ "@polar-sh/sdk": "^0.34.5"
+ }
+ },
+ "node_modules/@polar-sh/checkout": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/@polar-sh/checkout/-/checkout-0.1.11.tgz",
+ "integrity": "sha512-cRhXB5vw/cYxTKmHlmMU2Z3h5QfNEitftE/s/i/g88eyeJJ06YffmftwjdwT3jJJvMu8YZX7dHRZFljrEMi8gA==",
+ "dependencies": {
+ "@polar-sh/sdk": "^0.32.11",
+ "@polar-sh/ui": "^0.1.1",
+ "event-source-plus": "^0.1.8",
+ "eventemitter3": "^5.0.1",
+ "markdown-to-jsx": "^7.7.4",
+ "react-hook-form": "^7.55.0"
+ },
+ "peerDependencies": {
+ "@stripe/react-stripe-js": "^3.6.0",
+ "@stripe/stripe-js": "^7.1.0",
+ "react": "^18 || ^19"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/@polar-sh/sdk": {
+ "version": "0.32.16",
+ "resolved": "https://registry.npmjs.org/@polar-sh/sdk/-/sdk-0.32.16.tgz",
+ "integrity": "sha512-s+FvSJieNv9KcXGFNSbVzXpTY/hW8oYk8soa3Ow7NgWw/dY+pJ1py+qv+hNwxIuEmlHlpBIBHJVYQqPI9lLzCA==",
+ "dependencies": {
+ "standardwebhooks": "^1.0.0"
+ },
+ "bin": {
+ "mcp": "bin/mcp-server.js"
+ },
+ "peerDependencies": {
+ "@modelcontextprotocol/sdk": ">=1.5.0 <1.10.0",
+ "zod": ">= 3"
+ },
+ "peerDependenciesMeta": {
+ "@modelcontextprotocol/sdk": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/@polar-sh/ui": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@polar-sh/ui/-/ui-0.1.1.tgz",
+ "integrity": "sha512-DZfYUTMxqXNPmYr2l9dhaY+zmFNANlKe7bzjV5mgUrBFo4SjxytELErOjM2g5aTmuDm7kPuGB2YJnuqnvhqRTw==",
+ "dependencies": {
+ "@radix-ui/react-accordion": "^1.1.2",
+ "@radix-ui/react-alert-dialog": "^1.1.2",
+ "@radix-ui/react-checkbox": "^1.0.4",
+ "@radix-ui/react-dialog": "^1.1.2",
+ "@radix-ui/react-dropdown-menu": "^2.1.2",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-popover": "^1.0.7",
+ "@radix-ui/react-radio-group": "^1.1.3",
+ "@radix-ui/react-select": "^2.1.4",
+ "@radix-ui/react-separator": "^1.0.3",
+ "@radix-ui/react-slot": "^1.1.0",
+ "@radix-ui/react-switch": "^1.0.3",
+ "@radix-ui/react-tabs": "^1.0.4",
+ "@radix-ui/react-toast": "^1.2.2",
+ "@radix-ui/react-toggle": "^1.1.0",
+ "@radix-ui/react-toggle-group": "^1.1.0",
+ "@radix-ui/react-tooltip": "^1.0.7",
+ "@tanstack/react-table": "^8.20.5",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "cmdk": "^1.0.0",
+ "countries-list": "^3.1.1",
+ "date-fns": "^3.6.0",
+ "input-otp": "^1.4.1",
+ "lucide-react": "^0.461.0",
+ "react-day-picker": "^8.10.1",
+ "react-hook-form": "^7.54.2",
+ "react-timeago": "^7.2.0",
+ "tailwind-merge": "^2.5.5"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/@polar-sh/ui/node_modules/react-day-picker": {
+ "version": "8.10.1",
+ "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
+ "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==",
+ "funding": {
+ "type": "individual",
+ "url": "https://github.com/sponsors/gpbl"
+ },
+ "peerDependencies": {
+ "date-fns": "^2.28.0 || ^3.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/@polar-sh/ui/node_modules/react-timeago": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/react-timeago/-/react-timeago-7.2.0.tgz",
+ "integrity": "sha512-2KsBEEs+qRhKx/kekUVNSTIpop3Jwd7SRBm0R4Eiq3mPeswRGSsftY9FpKsE/lXLdURyQFiHeHFrIUxLYskG5g==",
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/date-fns": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
+ "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
+ },
+ "node_modules/@polar-sh/checkout/node_modules/lucide-react": {
+ "version": "0.461.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.461.0.tgz",
+ "integrity": "sha512-Scpw3D/dV1bgVRC5Kh774RCm99z0iZpPv75M6kg7QL1lLvkQ1rmI1Sjjic1aGp1ULBwd7FokV6ry0g+d6pMB+w==",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/@polar-sh/checkout/node_modules/tailwind-merge": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz",
+ "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/@polar-sh/nextjs": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@polar-sh/nextjs/-/nextjs-0.4.3.tgz",
+ "integrity": "sha512-3b/5lag6D1M0jCXZllEzCpnE4R1LW8vev0DNrmG/I6suAnLxnnYI4vHJGlZRuufFxuVpqCZdYe1LkGPV31hD+A==",
+ "dependencies": {
+ "@polar-sh/adapter-utils": "0.2.2",
+ "@polar-sh/sdk": "^0.34.5"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "next": "^15.0.0 || ^15.2.0-canary.*"
+ }
+ },
+ "node_modules/@polar-sh/sdk": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@polar-sh/sdk/-/sdk-0.34.5.tgz",
+ "integrity": "sha512-9dDw5QSsl9NT/GB77cibRLjAT+qNkdavxCL7YOjBTuwThJb7qrzhV2EzAQ+uM8UvY3ZGptu2tGCODnRLRRvVCQ==",
+ "dependencies": {
+ "standardwebhooks": "^1.0.0"
+ },
+ "bin": {
+ "mcp": "bin/mcp-server.js"
+ },
+ "peerDependencies": {
+ "@modelcontextprotocol/sdk": ">=1.5.0 <1.10.0",
+ "zod": "^3"
+ },
+ "peerDependenciesMeta": {
+ "@modelcontextprotocol/sdk": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
@@ -5871,12 +6062,40 @@
"node": ">=20.0.0"
}
},
+ "node_modules/@stablelib/base64": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
+ "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="
+ },
"node_modules/@standard-schema/utils": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
"integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
"license": "MIT"
},
+ "node_modules/@stripe/react-stripe-js": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.7.0.tgz",
+ "integrity": "sha512-PYls/2S9l0FF+2n0wHaEJsEU8x7CmBagiH7zYOsxbBlLIHEsqUIQ4MlIAbV9Zg6xwT8jlYdlRIyBTHmO3yM7kQ==",
+ "peer": true,
+ "dependencies": {
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "@stripe/stripe-js": ">=1.44.1 <8.0.0",
+ "react": ">=16.8.0 <20.0.0",
+ "react-dom": ">=16.8.0 <20.0.0"
+ }
+ },
+ "node_modules/@stripe/stripe-js": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.5.0.tgz",
+ "integrity": "sha512-Cq3KKe+G1o7PSBMbmrgpT2JgBeyH2THHr3RdIX2MqF7AnBuspIMgtZ3ktcCgP7kZsTMvnmWymr7zZCT1zeWbMw==",
+ "peer": true,
+ "engines": {
+ "node": ">=12.16"
+ }
+ },
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
@@ -6148,12 +6367,6 @@
"url": "https://github.com/sponsors/gregberge"
}
},
- "node_modules/@swc/counter": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
- "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
- "license": "Apache-2.0"
- },
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -8633,6 +8846,14 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
+ "node_modules/attr-accept": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz",
+ "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@@ -8911,17 +9132,6 @@
],
"license": "MIT"
},
- "node_modules/busboy": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
- "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
- "dependencies": {
- "streamsearch": "^1.1.0"
- },
- "engines": {
- "node": ">=10.16.0"
- }
- },
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -9394,6 +9604,11 @@
}
}
},
+ "node_modules/countries-list": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/countries-list/-/countries-list-3.1.1.tgz",
+ "integrity": "sha512-nPklKJ5qtmY5MdBKw1NiBAoyx5Sa7p2yPpljZyQ7gyCN1m+eMFs9I6CT37Mxt8zvR5L3VzD3DJBE4WQzX3WF4A=="
+ },
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
@@ -9884,6 +10099,11 @@
"node": ">=6"
}
},
+ "node_modules/destr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
+ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="
+ },
"node_modules/detect-libc": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
@@ -10963,6 +11183,14 @@
"node": ">= 0.6"
}
},
+ "node_modules/event-source-plus": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/event-source-plus/-/event-source-plus-0.1.11.tgz",
+ "integrity": "sha512-vdqQnx9eCUbtjdGyuIaaWm9pYRDCTxWgRV9JBvTuxpKMFzQZIrkT3/CqSlmilypVMAnB0nO1+X8GDGOmuh0Rfw==",
+ "dependencies": {
+ "ofetch": "^1.4.1"
+ }
+ },
"node_modules/event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
@@ -11167,6 +11395,11 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-sha256": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz",
+ "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="
+ },
"node_modules/fast-uri": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
@@ -11245,6 +11478,17 @@
"node": ">=16.0.0"
}
},
+ "node_modules/file-selector": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz",
+ "integrity": "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==",
+ "dependencies": {
+ "tslib": "^2.7.0"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -11886,6 +12130,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/idb-keyval": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz",
+ "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg=="
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -13234,6 +13483,17 @@
"markdown-it": "bin/markdown-it.mjs"
}
},
+ "node_modules/markdown-to-jsx": {
+ "version": "7.7.10",
+ "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.7.10.tgz",
+ "integrity": "sha512-au62yyLyJukhC2P1TYi3uBi/RScGYai69uT72D8a048QH8rRj+yhND3C21GdZHE+6emtsf6Yqemcf//K+EIWDg==",
+ "engines": {
+ "node": ">= 10"
+ },
+ "peerDependencies": {
+ "react": ">= 0.14.0"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -13579,15 +13839,12 @@
"peer": true
},
"node_modules/next": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/next/-/next-15.3.0.tgz",
- "integrity": "sha512-k0MgP6BsK8cZ73wRjMazl2y2UcXj49ZXLDEgx6BikWuby/CN+nh81qFFI16edgd7xYpe/jj2OZEIwCoqnzz0bQ==",
- "license": "MIT",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/next/-/next-15.4.1.tgz",
+ "integrity": "sha512-eNKB1q8C7o9zXF8+jgJs2CzSLIU3T6bQtX6DcTnCq1sIR1CJ0GlSyRs1BubQi3/JgCnr9Vr+rS5mOMI38FFyQw==",
"dependencies": {
- "@next/env": "15.3.0",
- "@swc/counter": "0.1.3",
+ "@next/env": "15.4.1",
"@swc/helpers": "0.5.15",
- "busboy": "1.6.0",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
"styled-jsx": "5.1.6"
@@ -13599,19 +13856,19 @@
"node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "15.3.0",
- "@next/swc-darwin-x64": "15.3.0",
- "@next/swc-linux-arm64-gnu": "15.3.0",
- "@next/swc-linux-arm64-musl": "15.3.0",
- "@next/swc-linux-x64-gnu": "15.3.0",
- "@next/swc-linux-x64-musl": "15.3.0",
- "@next/swc-win32-arm64-msvc": "15.3.0",
- "@next/swc-win32-x64-msvc": "15.3.0",
- "sharp": "^0.34.1"
+ "@next/swc-darwin-arm64": "15.4.1",
+ "@next/swc-darwin-x64": "15.4.1",
+ "@next/swc-linux-arm64-gnu": "15.4.1",
+ "@next/swc-linux-arm64-musl": "15.4.1",
+ "@next/swc-linux-x64-gnu": "15.4.1",
+ "@next/swc-linux-x64-musl": "15.4.1",
+ "@next/swc-win32-arm64-msvc": "15.4.1",
+ "@next/swc-win32-x64-msvc": "15.4.1",
+ "sharp": "^0.34.3"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
- "@playwright/test": "^1.41.2",
+ "@playwright/test": "^1.51.1",
"babel-plugin-react-compiler": "*",
"react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
"react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
@@ -13721,6 +13978,11 @@
}
}
},
+ "node_modules/node-fetch-native": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz",
+ "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="
+ },
"node_modules/node-releases": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
@@ -13921,6 +14183,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/ofetch": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz",
+ "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==",
+ "dependencies": {
+ "destr": "^2.0.3",
+ "node-fetch-native": "^1.6.4",
+ "ufo": "^1.5.4"
+ }
+ },
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -14944,6 +15216,22 @@
"react": "^19.1.0"
}
},
+ "node_modules/react-dropzone": {
+ "version": "14.3.8",
+ "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.3.8.tgz",
+ "integrity": "sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug==",
+ "dependencies": {
+ "attr-accept": "^2.2.4",
+ "file-selector": "^2.1.0",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">= 10.13"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8 || 18.0.0"
+ }
+ },
"node_modules/react-error-boundary": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz",
@@ -15681,6 +15969,11 @@
"node": ">= 18"
}
},
+ "node_modules/server-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz",
+ "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="
+ },
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
@@ -15778,6 +16071,28 @@
"shadcn": "dist/index.js"
}
},
+ "node_modules/shadcn/node_modules/@modelcontextprotocol/sdk": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.15.1.tgz",
+ "integrity": "sha512-W/XlN9c528yYn+9MQkVjxiTPgPxoxt+oczfjHBDsJx0+59+O7B75Zhsp0B16Xbwbz8ANISDajh6+V7nIcPMc5w==",
+ "dependencies": {
+ "ajv": "^6.12.6",
+ "content-type": "^1.0.5",
+ "cors": "^2.8.5",
+ "cross-spawn": "^7.0.5",
+ "eventsource": "^3.0.2",
+ "eventsource-parser": "^3.0.0",
+ "express": "^5.0.1",
+ "express-rate-limit": "^7.5.0",
+ "pkce-challenge": "^5.0.0",
+ "raw-body": "^3.0.0",
+ "zod": "^3.23.8",
+ "zod-to-json-schema": "^3.24.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/shadcn/node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
@@ -16073,6 +16388,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/standardwebhooks": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz",
+ "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==",
+ "dependencies": {
+ "@stablelib/base64": "^1.0.0",
+ "fast-sha256": "^1.3.0"
+ }
+ },
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
@@ -16111,14 +16435,6 @@
"node": ">= 0.4"
}
},
- "node_modules/streamsearch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
- "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
- "engines": {
- "node": ">=10.0.0"
- }
- },
"node_modules/strict-event-emitter": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
@@ -17016,6 +17332,11 @@
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"license": "MIT"
},
+ "node_modules/ufo": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
+ "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="
+ },
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
diff --git a/store/action-store.ts b/store/action-store.ts
new file mode 100644
index 00000000..0bc682e6
--- /dev/null
+++ b/store/action-store.ts
@@ -0,0 +1,56 @@
+import { create } from 'zustand';
+
+interface ActionsStateProps {
+ _handleSaveClickRef: (() => void) | null;
+ setHandleSaveClick: (handler: () => void) => void;
+ triggerSaveTheme: () => void;
+
+ _setCodePanelOpenRef: ((open: boolean) => void) | null;
+ setSetCodePanelOpen: (handler: (open: boolean) => void) => void;
+ triggerCodePanelOpen: () => void;
+
+ _handleResetClickRef: (() => void) | null;
+ setHandleRestClick: (handler: () => void) => void;
+ triggerResetTheme: () => void;
+}
+
+export const useActionsStore = create((set, get) => ({
+ _handleSaveClickRef: null,
+ setHandleSaveClick: (handler) => {
+ set({ _handleSaveClickRef: handler });
+ },
+ triggerSaveTheme: () => {
+ const handler = get()._handleSaveClickRef;
+ if (handler) {
+ handler();
+ } else {
+ console.warn("Save handler not set.");
+ }
+ },
+
+ _setCodePanelOpenRef: null,
+ setSetCodePanelOpen: (handler) => {
+ set({ _setCodePanelOpenRef: handler });
+ },
+ triggerCodePanelOpen: () => {
+ const handler = get()._setCodePanelOpenRef;
+ if (handler) {
+ handler(true);
+ } else {
+ console.warn("Code Panel handler not set.");
+ }
+ },
+
+ _handleResetClickRef: null,
+ setHandleRestClick: (handler) => {
+ set({_handleResetClickRef: handler});
+ },
+ triggerResetTheme: () => {
+ const handler = get()._handleResetClickRef;
+ if(handler){
+ handler();
+ }else{
+ console.warn("Reset handler not set")
+ }
+ },
+}));
\ No newline at end of file