diff --git a/apps/v4/app/(create)/components/main-menu.tsx b/apps/v4/app/(create)/components/main-menu.tsx index 9e8fd11d3c..6663ce680f 100644 --- a/apps/v4/app/(create)/components/main-menu.tsx +++ b/apps/v4/app/(create)/components/main-menu.tsx @@ -73,7 +73,7 @@ export function MainMenu({ className }: React.ComponentProps) { setShowResetDialog(true)}> - Reset + Reset ⇧R diff --git a/apps/v4/app/(create)/components/menu-picker.tsx b/apps/v4/app/(create)/components/menu-picker.tsx index 7e841a9b6b..ce86d7fc71 100644 --- a/apps/v4/app/(create)/components/menu-picker.tsx +++ b/apps/v4/app/(create)/components/menu-picker.tsx @@ -104,7 +104,7 @@ export function MenuColorPicker({
Menu
-
+
{currentMenu?.label}
diff --git a/apps/v4/app/(create)/components/preview.tsx b/apps/v4/app/(create)/components/preview.tsx index cf99e7feac..06bbffcdbc 100644 --- a/apps/v4/app/(create)/components/preview.tsx +++ b/apps/v4/app/(create)/components/preview.tsx @@ -10,6 +10,7 @@ import { import { DARK_MODE_FORWARD_TYPE } from "@/app/(create)/components/mode-switcher" import { RANDOMIZE_FORWARD_TYPE } from "@/app/(create)/components/random-button" import { sendToIframe } from "@/app/(create)/hooks/use-iframe-sync" +import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset" import { serializeDesignSystemSearchParams, useDesignSystemSearchParams, @@ -70,6 +71,15 @@ function handleMessage(event: MessageEvent) { cancelable: true, }) ) + } else if (type === RESET_FORWARD_TYPE) { + document.dispatchEvent( + new KeyboardEvent("keydown", { + key: "R", + shiftKey: true, + bubbles: true, + cancelable: true, + }) + ) } else if (type === DARK_MODE_FORWARD_TYPE) { document.dispatchEvent( new KeyboardEvent("keydown", { diff --git a/apps/v4/app/(create)/components/random-button.tsx b/apps/v4/app/(create)/components/random-button.tsx index cc23a4cfe8..d57d2609ab 100644 --- a/apps/v4/app/(create)/components/random-button.tsx +++ b/apps/v4/app/(create)/components/random-button.tsx @@ -7,6 +7,7 @@ import { HugeiconsIcon } from "@hugeicons/react" import { cn } from "@/lib/utils" import { useRandom } from "@/app/(create)/hooks/use-random" +import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset" export const RANDOMIZE_FORWARD_TYPE = "randomize-forward" @@ -40,7 +41,7 @@ export function RandomizeScript() { dangerouslySetInnerHTML={{ __html: ` (function() { - // Forward R key + // Forward r key (shuffle) and Shift+R (reset). document.addEventListener('keydown', function(e) { if ((e.key === 'r' || e.key === 'R') && !e.metaKey && !e.ctrlKey) { if ( @@ -53,8 +54,11 @@ export function RandomizeScript() { } e.preventDefault(); if (window.parent && window.parent !== window) { + var type = e.shiftKey + ? '${RESET_FORWARD_TYPE}' + : '${RANDOMIZE_FORWARD_TYPE}'; window.parent.postMessage({ - type: '${RANDOMIZE_FORWARD_TYPE}', + type: type, key: e.key }, '*'); } diff --git a/apps/v4/app/(create)/create/page.tsx b/apps/v4/app/(create)/create/page.tsx index 013b5bd3ad..1e21ef0098 100644 --- a/apps/v4/app/(create)/create/page.tsx +++ b/apps/v4/app/(create)/create/page.tsx @@ -44,7 +44,7 @@ export default async function CreatePage() { return (
{ const down = (e: KeyboardEvent) => { - if ((e.key === "r" || e.key === "R") && !e.metaKey && !e.ctrlKey) { + if (e.key === "r" && !e.shiftKey && !e.metaKey && !e.ctrlKey) { if ( (e.target instanceof HTMLElement && e.target.isContentEditable) || e.target instanceof HTMLInputElement || diff --git a/apps/v4/app/(create)/hooks/use-reset.tsx b/apps/v4/app/(create)/hooks/use-reset.tsx index a2498edafc..ad90419fc2 100644 --- a/apps/v4/app/(create)/hooks/use-reset.tsx +++ b/apps/v4/app/(create)/hooks/use-reset.tsx @@ -7,6 +7,7 @@ import { DEFAULT_CONFIG } from "@/registry/config" import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" const RESET_DIALOG_KEY = "create:reset-dialog-open" +export const RESET_FORWARD_TYPE = "reset-forward" export function useReset() { const [params, setParams] = useDesignSystemSearchParams() @@ -32,9 +33,9 @@ export function useReset() { menuColor: DEFAULT_CONFIG.menuColor, radius: DEFAULT_CONFIG.radius, template: DEFAULT_CONFIG.template, - item: "preview", + item: params.item, }) - }, [setParams, params.base]) + }, [setParams, params.base, params.item]) const handleShowResetDialogChange = React.useCallback( (open: boolean) => { @@ -48,6 +49,46 @@ export function useReset() { void setShowResetDialogData(false, { revalidate: false }) }, [reset, setShowResetDialogData]) + const showResetDialogRef = React.useRef(showResetDialog) + React.useEffect(() => { + showResetDialogRef.current = showResetDialog + }, [showResetDialog]) + + const confirmResetRef = React.useRef(confirmReset) + React.useEffect(() => { + confirmResetRef.current = confirmReset + }, [confirmReset]) + + React.useEffect(() => { + const down = (e: KeyboardEvent) => { + if (e.key === "R" && e.shiftKey && !e.metaKey && !e.ctrlKey) { + if ( + (e.target instanceof HTMLElement && e.target.isContentEditable) || + e.target instanceof HTMLInputElement || + e.target instanceof HTMLTextAreaElement || + e.target instanceof HTMLSelectElement + ) { + return + } + + e.preventDefault() + + // If the dialog is already open, confirm the reset. + if (showResetDialogRef.current) { + confirmResetRef.current() + return + } + + handleShowResetDialogChange(true) + } + } + + document.addEventListener("keydown", down) + return () => { + document.removeEventListener("keydown", down) + } + }, [handleShowResetDialogChange]) + return { reset, showResetDialog, diff --git a/apps/v4/next.config.mjs b/apps/v4/next.config.mjs index b40450abd4..68b21d89f4 100644 --- a/apps/v4/next.config.mjs +++ b/apps/v4/next.config.mjs @@ -1,3 +1,4 @@ +import path from "path" import { createMDX } from "fumadocs-mdx/next" /** @type {import('next').NextConfig} */ @@ -25,6 +26,9 @@ const nextConfig = { }, ], }, + turbopack: { + root: path.resolve(import.meta.dirname, "../.."), + }, experimental: { turbopackFileSystemCacheForDev: true, },