From 23a844dd12a28ef29809525a1139b826baf4c5bf Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 7 Oct 2025 22:13:30 -0700 Subject: [PATCH] fix(actions): prevent clickOutside race condition in update method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a race condition where the clickOutside action's update() method would remove and re-add the event listener every time it was called, even when the enabled state hadn't changed. This caused clicks to be missed during the setTimeout delay. Changes: - Track previous enabled state before updating - Only use setTimeout when transitioning from disabled to enabled - Immediately re-add listener when enabled state stays true - No listener changes when enabled state stays false This ensures click-outside events are consistently detected without gaps in event listener registration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/lib/actions/clickOutside.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/lib/actions/clickOutside.ts b/src/lib/actions/clickOutside.ts index 26ffbce..5f93e64 100644 --- a/src/lib/actions/clickOutside.ts +++ b/src/lib/actions/clickOutside.ts @@ -68,6 +68,8 @@ export function clickOutside( return { update(newOptions: ClickOutsideOptions | (() => void)) { + const wasEnabled = enabled + // Remove old listener document.removeEventListener('click', handleClick, true) @@ -80,11 +82,16 @@ export function clickOutside( callback = newOptions.callback } - // Add new listener if enabled - if (enabled) { - setTimeout(() => { - document.addEventListener('click', handleClick, true) - }, 0) + // Only modify listener if enabled state actually changed + if (wasEnabled !== enabled) { + if (enabled) { + setTimeout(() => { + document.addEventListener('click', handleClick, true) + }, 0) + } + } else if (enabled) { + // State didn't change but we're still enabled - re-add immediately + document.addEventListener('click', handleClick, true) } }, destroy() {