From 45dd1d42fbf0787c9bb1777b9f532fad69d55879 Mon Sep 17 00:00:00 2001 From: Thanan Traiongthawon <95660+nullcoder@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:42:15 -0700 Subject: [PATCH] feat: add refresh-expired and refresh-timeout attributes to Turnstile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add refreshExpired and refreshTimeout props with "auto" | "manual" | "never" options - Add onTimeout callback for handling interactive timeouts - Update Window interface to include timeout-callback and refresh attributes - Remove onExpire handler from create page since refreshExpired="auto" handles it - Fix test to use correct placeholder text for password input - Both refresh attributes default to "auto" for automatic handling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- app/create/page.test.tsx | 2 +- app/create/page.tsx | 10 +--------- components/ui/turnstile.tsx | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/app/create/page.test.tsx b/app/create/page.test.tsx index e43078d..1fbbe13 100644 --- a/app/create/page.test.tsx +++ b/app/create/page.test.tsx @@ -162,7 +162,7 @@ describe("CreateGistPage", () => { render(); const pinInput = screen.getByPlaceholderText( - "Set a PIN to protect edits" + "Leave empty for no protection" ); expect(pinInput).toBeInTheDocument(); diff --git a/app/create/page.tsx b/app/create/page.tsx index a7f5f29..b26a3d3 100644 --- a/app/create/page.tsx +++ b/app/create/page.tsx @@ -72,14 +72,6 @@ export default function CreateGistPage() { setIsTurnstileReady(false); }, []); - const handleTurnstileExpire = useCallback(() => { - setTurnstileToken(null); - setIsTurnstileReady(false); - setError( - "⏰ Security verification expired. Please refresh the page to continue." - ); - }, []); - const handleFilesChange = useCallback((newFiles: FileData[]) => { setFiles(newFiles); // Don't clear errors on file change - let them persist @@ -391,9 +383,9 @@ export default function CreateGistPage() { )} diff --git a/components/ui/turnstile.tsx b/components/ui/turnstile.tsx index 9f3ba82..c073e1f 100644 --- a/components/ui/turnstile.tsx +++ b/components/ui/turnstile.tsx @@ -7,12 +7,15 @@ interface TurnstileProps { onSuccess?: (token: string) => void; onExpire?: () => void; onError?: () => void; + onTimeout?: () => void; theme?: "light" | "dark" | "auto"; action?: string; size?: "normal" | "flexible" | "compact"; appearance?: "always" | "execute" | "interaction-only"; execution?: "render" | "execute"; language?: string; + refreshExpired?: "auto" | "manual" | "never"; + refreshTimeout?: "auto" | "manual" | "never"; } declare global { @@ -25,12 +28,15 @@ declare global { callback?: (token: string) => void; "error-callback"?: () => void; "expired-callback"?: () => void; + "timeout-callback"?: () => void; theme?: "light" | "dark" | "auto"; action?: string; size?: "normal" | "flexible" | "compact"; appearance?: "always" | "execute" | "interaction-only"; execution?: "render" | "execute"; language?: string; + "refresh-expired"?: "auto" | "manual" | "never"; + "refresh-timeout"?: "auto" | "manual" | "never"; } ) => string; reset: (widgetId: string) => void; @@ -46,12 +52,15 @@ const Turnstile: React.FC = ({ onSuccess, onExpire, onError, + onTimeout, theme = "auto", action, size = "normal", appearance = "interaction-only", execution = "render", language = "auto", + refreshExpired = "auto", + refreshTimeout = "auto", }) => { const containerRef = useRef(null); const widgetIdRef = useRef(null); @@ -67,9 +76,12 @@ const Turnstile: React.FC = ({ appearance, execution, language, + "refresh-expired": refreshExpired, + "refresh-timeout": refreshTimeout, callback: onSuccess, "error-callback": onError, "expired-callback": onExpire, + "timeout-callback": onTimeout, }); } }; @@ -110,12 +122,15 @@ const Turnstile: React.FC = ({ onSuccess, onError, onExpire, + onTimeout, theme, action, size, appearance, execution, language, + refreshExpired, + refreshTimeout, ]); return
;