Type Menu with $$Props

This commit is contained in:
Ryan Gossiaux
2022-02-07 16:25:22 -08:00
parent 6bc781b86e
commit 168f7f1e3d
4 changed files with 82 additions and 12 deletions

View File

@@ -12,7 +12,7 @@
import type { SupportedAs } from "$lib/internal/elements"; import type { SupportedAs } from "$lib/internal/elements";
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 Render from "$lib/utils/Render.svelte"; import Render, { type TPassThroughProps } from "$lib/utils/Render.svelte";
export enum MenuStates { export enum MenuStates {
Open, Open,
@@ -53,13 +53,25 @@
} }
return context; return context;
} }
type TMenuProps<
TSlotProps extends {},
TAsProp extends SupportedAs
> = TPassThroughProps<TSlotProps, TAsProp> & {};
</script> </script>
<script lang="ts"> <script lang="ts">
/***** Props *****/
type TAsProp = $$Generic<SupportedAs>;
type $$Props = TMenuProps<typeof slotProps, TAsProp>;
export let use: HTMLActionArray = []; export let use: HTMLActionArray = [];
export let as: SupportedAs = "div"; export let as: SupportedAs = "div";
/***** Events *****/
const forwardEvents = forwardEventsBuilder(get_current_component()); const forwardEvents = forwardEventsBuilder(get_current_component());
/***** Component *****/
let menuState: StateDefinition["menuState"] = MenuStates.Closed; let menuState: StateDefinition["menuState"] = MenuStates.Closed;
let buttonStore: StateDefinition["buttonStore"] = writable(null); let buttonStore: StateDefinition["buttonStore"] = writable(null);
let itemsStore: StateDefinition["itemsStore"] = writable(null); let itemsStore: StateDefinition["itemsStore"] = writable(null);

View File

@@ -1,3 +1,12 @@
<script lang="ts" context="module">
type TMenuButtonProps<
TSlotProps extends {},
TAsProp extends SupportedAs
> = TPassThroughProps<TSlotProps, TAsProp> & {
disabled?: boolean;
};
</script>
<script lang="ts"> <script lang="ts">
import { useMenuContext, MenuStates } from "./Menu.svelte"; import { useMenuContext, MenuStates } from "./Menu.svelte";
import { useId } from "$lib/hooks/use-id"; import { useId } from "$lib/hooks/use-id";
@@ -5,16 +14,24 @@
import { Focus } from "$lib/utils/calculate-active-index"; import { Focus } from "$lib/utils/calculate-active-index";
import { tick } from "svelte"; import { tick } from "svelte";
import type { HTMLActionArray } from "$lib/hooks/use-actions"; import type { HTMLActionArray } from "$lib/hooks/use-actions";
import Render from "$lib/utils/Render.svelte"; import Render, { type TPassThroughProps } from "$lib/utils/Render.svelte";
import type { SupportedAs } from "$lib/internal/elements"; import type { SupportedAs } from "$lib/internal/elements";
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 { resolveButtonType } from "$lib/utils/resolve-button-type"; import { resolveButtonType } from "$lib/utils/resolve-button-type";
const forwardEvents = forwardEventsBuilder(get_current_component());
/***** Props *****/
type TAsProp = $$Generic<SupportedAs>;
type $$Props = TMenuButtonProps<typeof slotProps, TAsProp>;
export let as: SupportedAs = "button"; export let as: SupportedAs = "button";
export let use: HTMLActionArray = []; export let use: HTMLActionArray = [];
export let disabled = false; export let disabled = false;
/***** Events *****/
const forwardEvents = forwardEventsBuilder(get_current_component());
/***** Component *****/
const api = useMenuContext("MenuButton"); const api = useMenuContext("MenuButton");
const id = `headlessui-menu-button-${useId()}`; const id = `headlessui-menu-button-${useId()}`;
@@ -84,7 +101,9 @@
"aria-expanded": disabled ? undefined : $api.menuState === MenuStates.Open, "aria-expanded": disabled ? undefined : $api.menuState === MenuStates.Open,
}; };
$: slotProps = { open: $api.menuState === MenuStates.Open }; $: slotProps = {
open: $api.menuState === MenuStates.Open,
};
</script> </script>
<Render <Render

View File

@@ -1,20 +1,36 @@
<script lang="ts" context="module">
type TMenuItemProps<
TSlotProps extends {},
TAsProp extends SupportedAs
> = TPassThroughProps<TSlotProps, TAsProp> & {};
</script>
<script lang="ts"> <script lang="ts">
import type { MenuItemData } from "./Menu.svelte"; import type { MenuItemData } from "./Menu.svelte";
import { useMenuContext, MenuStates } from "./Menu.svelte"; import { useMenuContext, MenuStates } from "./Menu.svelte";
import { useId } from "$lib/hooks/use-id"; import { useId } from "$lib/hooks/use-id";
import { Focus } from "$lib/utils/calculate-active-index"; import { Focus } from "$lib/utils/calculate-active-index";
import { afterUpdate, onDestroy, onMount, tick } from "svelte"; import { afterUpdate, onDestroy, onMount, tick } from "svelte";
import Render from "$lib/utils/Render.svelte"; import Render, { type TPassThroughProps } from "$lib/utils/Render.svelte";
import type { SupportedAs } from "$lib/internal/elements"; import type { SupportedAs } from "$lib/internal/elements";
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(), [
{ name: "click", shouldExclude: () => disabled }, /***** Props *****/
]); type TAsProp = $$Generic<SupportedAs>;
type $$Props = TMenuItemProps<typeof slotProps, TAsProp>;
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;
/***** Events *****/
const forwardEvents = forwardEventsBuilder(get_current_component(), [
{ name: "click", shouldExclude: () => disabled },
]);
/***** Component *****/
const api = useMenuContext("MenuItem"); const api = useMenuContext("MenuItem");
const id = `headlessui-menu-item-${useId()}`; const id = `headlessui-menu-item-${useId()}`;

View File

@@ -1,3 +1,13 @@
<script lang="ts" context="module">
type TMenuItemsProps<
TSlotProp extends {},
TAsProp extends SupportedAs
> = TPassThroughProps<TSlotProp, TAsProp> & {
static?: boolean;
unmount?: boolean;
};
</script>
<script lang="ts"> <script lang="ts">
import { useMenuContext, MenuStates } from "./Menu.svelte"; import { useMenuContext, MenuStates } from "./Menu.svelte";
import { useId } from "$lib/hooks/use-id"; import { useId } from "$lib/hooks/use-id";
@@ -8,13 +18,24 @@
import { tick } from "svelte"; import { tick } from "svelte";
import type { HTMLActionArray } from "$lib/hooks/use-actions"; import type { HTMLActionArray } from "$lib/hooks/use-actions";
import type { SupportedAs } from "$lib/internal/elements"; import type { SupportedAs } from "$lib/internal/elements";
import Render, { Features } from "$lib/utils/Render.svelte"; import Render, {
Features,
type TPassThroughProps,
} from "$lib/utils/Render.svelte";
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";
const forwardEvents = forwardEventsBuilder(get_current_component()); /***** Props *****/
type TAsProp = $$Generic<SupportedAs>;
type $$Props = TMenuItemsProps<typeof slotProps, TAsProp>;
export let as: SupportedAs = "div"; export let as: SupportedAs = "div";
export let use: HTMLActionArray = []; export let use: HTMLActionArray = [];
/***** Events *****/
const forwardEvents = forwardEventsBuilder(get_current_component());
/***** Component *****/
const api = useMenuContext("MenuItems"); const api = useMenuContext("MenuItems");
const id = `headlessui-menu-items-${useId()}`; const id = `headlessui-menu-items-${useId()}`;
let searchDebounce: ReturnType<typeof setTimeout> | null = null; let searchDebounce: ReturnType<typeof setTimeout> | null = null;
@@ -135,7 +156,9 @@
role: "menu", role: "menu",
tabIndex: 0, tabIndex: 0,
}; };
$: slotProps = { open: $api.menuState === MenuStates.Open }; $: slotProps = {
open: $api.menuState === MenuStates.Open,
};
</script> </script>
<Render <Render