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 { 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;

View File

@@ -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.