diff --git a/src/lib/components/menu/MenuItem.svelte b/src/lib/components/menu/MenuItem.svelte index 8b74baf..9424e01 100644 --- a/src/lib/components/menu/MenuItem.svelte +++ b/src/lib/components/menu/MenuItem.svelte @@ -8,7 +8,9 @@ import { forwardEventsBuilder } from "$lib/internal/forwardEventsBuilder"; import { get_current_component } from "svelte/internal"; import type { HTMLActionArray } from "$lib/hooks/use-actions"; - const forwardEvents = forwardEventsBuilder(get_current_component()); + const forwardEvents = forwardEventsBuilder(get_current_component(), [ + { name: "click", shouldExclude: () => disabled }, + ]); export let as: SupportedAs = "a"; export let use: HTMLActionArray = []; export let disabled = false; diff --git a/src/lib/internal/forwardEventsBuilder.ts b/src/lib/internal/forwardEventsBuilder.ts index de6715d..7cb34d4 100644 --- a/src/lib/internal/forwardEventsBuilder.ts +++ b/src/lib/internal/forwardEventsBuilder.ts @@ -1,16 +1,22 @@ // This is a modified version of code from hperrin/svelte-material-ui -import type { SvelteComponent } from 'svelte'; +import type { SvelteComponent } from "svelte"; import { bubble, listen, prevent_default, stop_propagation, -} from 'svelte/internal'; +} from "svelte/internal"; const MODIFIER_DIVIDER = "!"; -const modifierRegex = new RegExp(`^[^${MODIFIER_DIVIDER}]+(?:${MODIFIER_DIVIDER}(?:preventDefault|stopPropagation|passive|nonpassive|capture|once|self))+$`); +const modifierRegex = new RegExp( + `^[^${MODIFIER_DIVIDER}]+(?:${MODIFIER_DIVIDER}(?:preventDefault|stopPropagation|passive|nonpassive|capture|once|self))+$` +); -export function forwardEventsBuilder(component: SvelteComponent, except: string[] = []) { +type ForwardException = string | { name: string; shouldExclude: () => boolean }; +export function forwardEventsBuilder( + component: SvelteComponent, + except: ForwardException[] = [] +) { // This is our pseudo $on function. It is defined on component mount. let $on: (eventType: string, callback: (event: any) => void) => () => void; // This is a list of events bound before mount. @@ -19,16 +25,29 @@ export function forwardEventsBuilder(component: SvelteComponent, except: string[ // And we override the $on function to forward all bound events. component.$on = (fullEventType: string, callback: (event: any) => void) => { let eventType = fullEventType; - let destructor = () => { }; - if (except.includes(eventType)) { - // Bail out of the event forwarding and run the normal Svelte $on() code - const callbacks = (component.$$.callbacks[eventType] || (component.$$.callbacks[eventType] = [])); - callbacks.push(callback); - return () => { - const index = callbacks.indexOf(callback); - if (index !== -1) - callbacks.splice(index, 1); - }; + let destructor = () => {}; + for (let exception of except) { + if (typeof exception === "string" && exception === eventType) { + // Bail out of the event forwarding and run the normal Svelte $on() code + const callbacks = + component.$$.callbacks[eventType] || + (component.$$.callbacks[eventType] = []); + callbacks.push(callback); + return () => { + const index = callbacks.indexOf(callback); + if (index !== -1) callbacks.splice(index, 1); + }; + } + if (typeof exception === "object" && exception["name"] === eventType) { + let oldCallback = callback; + callback = (...props) => { + if ( + !(typeof exception === "object" && exception["shouldExclude"]()) + ) { + oldCallback(...props); + } + }; + } } if ($on) { // The event was bound programmatically.