Move Disclosure to <Render>

This commit is contained in:
Ryan Gossiaux
2021-12-20 19:26:04 -08:00
parent c73d9bf919
commit 93e7148e1b
3 changed files with 83 additions and 24 deletions

View File

@@ -45,6 +45,16 @@
import { useId } from "$lib/hooks/use-id"; import { useId } from "$lib/hooks/use-id";
import { match } from "$lib/utils/match"; import { match } from "$lib/utils/match";
import { State, useOpenClosedProvider } from "$lib/internal/open-closed"; import { State, useOpenClosedProvider } from "$lib/internal/open-closed";
import { forwardEventsBuilder } from "$lib/internal/forwardEventsBuilder";
import { get_current_component } from "svelte/internal";
import type { SupportedAs } from "$lib/internal/elements";
import type { HTMLActionArray } from "$lib/hooks/use-actions";
import Render from "$lib/utils/Render.svelte";
const forwardEvents = forwardEventsBuilder(get_current_component());
export let as: SupportedAs = "div";
export let use: HTMLActionArray = [];
export let defaultOpen = false; export let defaultOpen = false;
let buttonId = `headlessui-disclosure-button-${useId()}`; let buttonId = `headlessui-disclosure-button-${useId()}`;
let panelId = `headlessui-disclosure-panel-${useId()}`; let panelId = `headlessui-disclosure-panel-${useId()}`;
@@ -107,8 +117,19 @@
useOpenClosedProvider(openClosedState); useOpenClosedProvider(openClosedState);
$: $openClosedState = computeOpenClosedState(disclosureState); $: $openClosedState = computeOpenClosedState(disclosureState);
$: slotProps = {
open: disclosureState === DisclosureStates.Open,
close: $api.close,
};
</script> </script>
<div {...$$restProps}> <Render
<slot open={disclosureState === DisclosureStates.Open} close={$api.close} /> {...$$restProps}
</div> {as}
{slotProps}
use={[...use, forwardEvents]}
name={"Disclosure"}
>
<slot {...slotProps} />
</Render>

View File

@@ -3,6 +3,16 @@
import { usePanelContext } from "./DisclosurePanel.svelte"; import { usePanelContext } from "./DisclosurePanel.svelte";
import { useId } from "$lib/hooks/use-id"; import { useId } from "$lib/hooks/use-id";
import { Keys } from "$lib/utils/keyboard"; import { Keys } from "$lib/utils/keyboard";
import { forwardEventsBuilder } from "$lib/internal/forwardEventsBuilder";
import { get_current_component } from "svelte/internal";
import type { SupportedAs } from "$lib/internal/elements";
import type { HTMLActionArray } from "$lib/hooks/use-actions";
import Render from "$lib/utils/Render.svelte";
const forwardEvents = forwardEventsBuilder(get_current_component());
export let as: SupportedAs = "button";
export let use: HTMLActionArray = [];
export let disabled = false; export let disabled = false;
const api = useDisclosureContext("DisclosureButton"); const api = useDisclosureContext("DisclosureButton");
const panelContext = usePanelContext(); const panelContext = usePanelContext();
@@ -25,8 +35,9 @@
} }
} }
function handleKeyDown(event: KeyboardEvent) { function handleKeyDown(e: CustomEvent) {
if (disabled) return; if (disabled) return;
let event = e as any as KeyboardEvent;
if (isWithinPanel) { if (isWithinPanel) {
switch (event.key) { switch (event.key) {
@@ -50,7 +61,8 @@
} }
} }
function handleKeyUp(event: KeyboardEvent) { function handleKeyUp(e: CustomEvent) {
let event = e as any as KeyboardEvent;
switch (event.key) { switch (event.key) {
case Keys.Space: case Keys.Space:
// Required for firefox, event.preventDefault() in handleKeyDown for // Required for firefox, event.preventDefault() in handleKeyDown for
@@ -71,30 +83,37 @@
"aria-controls": $panelStore ? $api.panelId : undefined, "aria-controls": $panelStore ? $api.panelId : undefined,
disabled: disabled ? true : undefined, disabled: disabled ? true : undefined,
}; };
$: slotProps = {
open: $api.disclosureState === DisclosureStates.Open,
close: $api.close,
};
</script> </script>
{#if isWithinPanel} {#if isWithinPanel}
<button <Render
{...{ ...$$restProps, ...propsWeControl }} {...{ ...$$restProps, ...propsWeControl }}
{as}
{slotProps}
use={[...use, forwardEvents]}
name={"DisclosureButton"}
on:click={handleClick} on:click={handleClick}
on:keydown={handleKeyDown} on:keydown={handleKeyDown}
> >
<slot <slot {...slotProps} />
open={$api.disclosureState === DisclosureStates.Open} </Render>
close={$api.close}
/>
</button>
{:else} {:else}
<button <Render
{...{ ...$$restProps, ...propsWeControl }} {...{ ...$$restProps, ...propsWeControl }}
bind:this={$buttonStore} {as}
{slotProps}
use={[...use, forwardEvents]}
name={"DisclosureButton"}
bind:el={$buttonStore}
on:click={handleClick} on:click={handleClick}
on:keydown={handleKeyDown} on:keydown={handleKeyDown}
on:keyup={handleKeyUp} on:keyup={handleKeyUp}
> >
<slot <slot {...slotProps} />
open={$api.disclosureState === DisclosureStates.Open} </Render>
close={$api.close}
/>
</button>
{/if} {/if}

View File

@@ -10,6 +10,16 @@
<script lang="ts"> <script lang="ts">
import { useDisclosureContext, DisclosureStates } from "./Disclosure.svelte"; import { useDisclosureContext, DisclosureStates } from "./Disclosure.svelte";
import { State, useOpenClosed } from "$lib/internal/open-closed"; import { State, useOpenClosed } from "$lib/internal/open-closed";
import { forwardEventsBuilder } from "$lib/internal/forwardEventsBuilder";
import { get_current_component } from "svelte/internal";
import type { SupportedAs } from "$lib/internal/elements";
import type { HTMLActionArray } from "$lib/hooks/use-actions";
import Render from "$lib/utils/Render.svelte";
const forwardEvents = forwardEventsBuilder(get_current_component());
export let as: SupportedAs = "div";
export let use: HTMLActionArray = [];
const api = useDisclosureContext("DisclosureButton"); const api = useDisclosureContext("DisclosureButton");
$: id = $api.panelId; $: id = $api.panelId;
let openClosedState = useOpenClosed(); let openClosedState = useOpenClosed();
@@ -24,13 +34,22 @@
: $api.disclosureState === DisclosureStates.Open; : $api.disclosureState === DisclosureStates.Open;
$: propsWeControl = { id }; $: propsWeControl = { id };
$: slotProps = {
open: $api.disclosureState === DisclosureStates.Open,
close: $api.close,
};
</script> </script>
{#if visible} {#if visible}
<div {...{ ...$$restProps, ...propsWeControl }} bind:this={$panelStore}> <Render
<slot {...{ ...$$restProps, ...propsWeControl }}
open={$api.disclosureState === DisclosureStates.Open} {as}
close={$api.close} {slotProps}
/> use={[...use, forwardEvents]}
</div> name={"DisclosurePanel"}
bind:el={$panelStore}
>
<slot {...slotProps} />
</Render>
{/if} {/if}