Conditionally forward MenuItem click events only if the MenuItem is not disabled

This is obviously a lot easier in React, but at any rate this mimics upstream behavior here.
This commit is contained in:
Ryan Gossiaux
2021-12-28 09:03:43 -10:00
parent 2c09162fc0
commit d7348b35b6
2 changed files with 36 additions and 15 deletions

View File

@@ -8,7 +8,9 @@
import { forwardEventsBuilder } from "$lib/internal/forwardEventsBuilder"; import { forwardEventsBuilder } from "$lib/internal/forwardEventsBuilder";
import { get_current_component } from "svelte/internal"; import { get_current_component } from "svelte/internal";
import type { HTMLActionArray } from "$lib/hooks/use-actions"; 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 as: SupportedAs = "a";
export let use: HTMLActionArray = []; export let use: HTMLActionArray = [];
export let disabled = false; export let disabled = false;

View File

@@ -1,16 +1,22 @@
// This is a modified version of code from hperrin/svelte-material-ui // This is a modified version of code from hperrin/svelte-material-ui
import type { SvelteComponent } from 'svelte'; import type { SvelteComponent } from "svelte";
import { import {
bubble, bubble,
listen, listen,
prevent_default, prevent_default,
stop_propagation, stop_propagation,
} from 'svelte/internal'; } from "svelte/internal";
const MODIFIER_DIVIDER = "!"; 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. // This is our pseudo $on function. It is defined on component mount.
let $on: (eventType: string, callback: (event: any) => void) => () => void; let $on: (eventType: string, callback: (event: any) => void) => () => void;
// This is a list of events bound before mount. // This is a list of events bound before mount.
@@ -19,17 +25,30 @@ export function forwardEventsBuilder(component: SvelteComponent, except: string[
// And we override the $on function to forward all bound events. // And we override the $on function to forward all bound events.
component.$on = (fullEventType: string, callback: (event: any) => void) => { component.$on = (fullEventType: string, callback: (event: any) => void) => {
let eventType = fullEventType; let eventType = fullEventType;
let destructor = () => { }; let destructor = () => {};
if (except.includes(eventType)) { for (let exception of except) {
if (typeof exception === "string" && exception === eventType) {
// Bail out of the event forwarding and run the normal Svelte $on() code // Bail out of the event forwarding and run the normal Svelte $on() code
const callbacks = (component.$$.callbacks[eventType] || (component.$$.callbacks[eventType] = [])); const callbacks =
component.$$.callbacks[eventType] ||
(component.$$.callbacks[eventType] = []);
callbacks.push(callback); callbacks.push(callback);
return () => { return () => {
const index = callbacks.indexOf(callback); const index = callbacks.indexOf(callback);
if (index !== -1) if (index !== -1) callbacks.splice(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) { if ($on) {
// The event was bound programmatically. // The event was bound programmatically.
destructor = $on(eventType, callback); destructor = $on(eventType, callback);