Add action forwarding and add to Menu
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
import { writable, Writable } from "svelte/store";
|
||||
import { State } from "$lib/internal/open-closed";
|
||||
import { match } from "$lib/utils/match";
|
||||
import { ActionArray, useActions } from "$lib/hooks/use-actions";
|
||||
export enum MenuStates {
|
||||
Open,
|
||||
Closed,
|
||||
@@ -49,6 +50,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export let use: ActionArray = [];
|
||||
let menuState: StateDefinition["menuState"] = MenuStates.Closed;
|
||||
let buttonStore: StateDefinition["buttonStore"] = writable(null);
|
||||
let itemsStore: StateDefinition["itemsStore"] = writable(null);
|
||||
@@ -146,6 +148,6 @@
|
||||
</script>
|
||||
|
||||
<svelte:window on:mousedown={handleWindowMousedown} />
|
||||
<div {...$$restProps}>
|
||||
<div use:useActions={use} {...$$restProps}>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
import { Keys } from "$lib/utils/keyboard";
|
||||
import { Focus } from "$lib/utils/calculate-active-index";
|
||||
import { tick } from "svelte";
|
||||
import { ActionArray, useActions } from "$lib/hooks/use-actions";
|
||||
export let use: ActionArray = [];
|
||||
export let disabled = false;
|
||||
const api = useMenuContext("MenuButton");
|
||||
const id = `headlessui-menu-button-${useId()}`;
|
||||
@@ -73,6 +75,7 @@
|
||||
<button
|
||||
{...{ ...$$restProps, ...propsWeControl }}
|
||||
bind:this={$buttonStore}
|
||||
use:useActions={use}
|
||||
on:click={handleClick}
|
||||
on:keydown={handleKeyDown}
|
||||
on:keyup={handleKeyUp}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import { useId } from "$lib/hooks/use-id";
|
||||
import { Focus } from "$lib/utils/calculate-active-index";
|
||||
import { afterUpdate, onDestroy, onMount, tick } from "svelte";
|
||||
import { ActionArray, useActions } from "$lib/hooks/use-actions";
|
||||
export let use: ActionArray = [];
|
||||
export let disabled = false;
|
||||
const api = useMenuContext("MenuItem");
|
||||
const id = `headlessui-menu-item-${useId()}`;
|
||||
@@ -68,6 +70,7 @@
|
||||
<div
|
||||
{...{ ...$$restProps, ...propsWeControl }}
|
||||
bind:this={elementRef}
|
||||
use:useActions={use}
|
||||
on:click={handleClick}
|
||||
on:focus={handleFocus}
|
||||
on:pointermove={handleMove}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
import { State } from "$lib/internal/open-closed";
|
||||
import { getContext, tick } from "svelte";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { ActionArray, useActions } from "$lib/hooks/use-actions";
|
||||
export let use: ActionArray = [];
|
||||
const api = useMenuContext("MenuButton");
|
||||
const id = `headlessui-menu-items-${useId()}`;
|
||||
let searchDebounce: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -131,6 +133,7 @@
|
||||
<div
|
||||
{...{ ...$$restProps, ...propsWeControl }}
|
||||
bind:this={$itemsStore}
|
||||
use:useActions={use}
|
||||
on:keydown={handleKeyDown}
|
||||
on:keyup={handleKeyUp}
|
||||
>
|
||||
|
||||
82
src/lib/hooks/use-actions.ts
Normal file
82
src/lib/hooks/use-actions.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
// This file taken from hperrin/svelte-material-ui
|
||||
// Copyright 2020-present Hunter Perrin
|
||||
export type SvelteActionReturnType<P> = {
|
||||
update?: (newParams?: P) => void;
|
||||
destroy?: () => void;
|
||||
} | void;
|
||||
|
||||
export type SvelteHTMLActionType<P> = (
|
||||
node: HTMLElement,
|
||||
params?: P
|
||||
) => SvelteActionReturnType<P>;
|
||||
|
||||
export type HTMLActionEntry<P extends any = any> =
|
||||
| SvelteHTMLActionType<P>
|
||||
| [SvelteHTMLActionType<P>, P];
|
||||
|
||||
export type HTMLActionArray = HTMLActionEntry[];
|
||||
|
||||
export type SvelteSVGActionType<P> = (
|
||||
node: SVGElement,
|
||||
params?: P
|
||||
) => SvelteActionReturnType<P>;
|
||||
|
||||
export type SVGActionEntry<P extends any = any> =
|
||||
| SvelteSVGActionType<P>
|
||||
| [SvelteSVGActionType<P>, P];
|
||||
|
||||
export type SVGActionArray = SVGActionEntry[];
|
||||
|
||||
export type ActionArray = HTMLActionArray | SVGActionArray;
|
||||
|
||||
export function useActions(
|
||||
node: HTMLElement | SVGElement,
|
||||
actions: ActionArray
|
||||
) {
|
||||
let actionReturns: SvelteActionReturnType<any>[] = [];
|
||||
|
||||
if (actions) {
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
const actionEntry = actions[i];
|
||||
const action = Array.isArray(actionEntry) ? actionEntry[0] : actionEntry;
|
||||
if (Array.isArray(actionEntry) && actionEntry.length > 1) {
|
||||
actionReturns.push(
|
||||
action(node as HTMLElement & SVGElement, actionEntry[1])
|
||||
);
|
||||
} else {
|
||||
actionReturns.push(action(node as HTMLElement & SVGElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
update(actions: ActionArray) {
|
||||
if (((actions && actions.length) || 0) != actionReturns.length) {
|
||||
throw new Error('You must not change the length of an actions array.');
|
||||
}
|
||||
|
||||
if (actions) {
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
const returnEntry = actionReturns[i];
|
||||
if (returnEntry && returnEntry.update) {
|
||||
const actionEntry = actions[i];
|
||||
if (Array.isArray(actionEntry) && actionEntry.length > 1) {
|
||||
returnEntry.update(actionEntry[1]);
|
||||
} else {
|
||||
returnEntry.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
destroy() {
|
||||
for (let i = 0; i < actionReturns.length; i++) {
|
||||
const returnEntry = actionReturns[i];
|
||||
if (returnEntry && returnEntry.destroy) {
|
||||
returnEntry.destroy();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user