Move Tabs to <Render>

This is the last component to move to <Render>!
This commit is contained in:
Ryan Gossiaux
2021-12-20 23:19:31 -08:00
parent aa3017990d
commit b973fa6fe2
5 changed files with 105 additions and 34 deletions

View File

@@ -3,9 +3,17 @@
import { Focus, focusIn } from "$lib/utils/focus-management"; import { Focus, focusIn } from "$lib/utils/focus-management";
import { Keys } from "$lib/utils/keyboard"; import { Keys } from "$lib/utils/keyboard";
import { match } from "$lib/utils/match"; import { match } from "$lib/utils/match";
import { useTabsContext } from "./TabGroup.svelte"; import { useTabsContext } from "./TabGroup.svelte";
import { useId } from "$lib/hooks/use-id"; import { useId } from "$lib/hooks/use-id";
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;
@@ -21,7 +29,8 @@
$: myIndex = $api.tabs.indexOf(tabRef); $: myIndex = $api.tabs.indexOf(tabRef);
$: selected = myIndex === $api.selectedIndex; $: selected = myIndex === $api.selectedIndex;
function handleKeyDown(event: KeyboardEvent) { function handleKeyDown(e: CustomEvent) {
let event = e as any as KeyboardEvent;
let list = $api.tabs.filter(Boolean) as HTMLElement[]; let list = $api.tabs.filter(Boolean) as HTMLElement[];
if (event.key === Keys.Space || event.key === Keys.Enter) { if (event.key === Keys.Space || event.key === Keys.Enter) {
@@ -86,22 +95,19 @@
disabled: disabled ? true : undefined, disabled: disabled ? true : undefined,
}; };
$: classStyle = $$props.class $: slotProps = { selected };
? typeof $$props.class === "function"
? $$props.class({
selected,
})
: $$props.class
: "";
</script> </script>
<button <Render
{...{ ...$$restProps, ...propsWeControl }} {...{ ...$$restProps, ...propsWeControl }}
bind:this={tabRef} {as}
class={classStyle} {slotProps}
use={[...use, forwardEvents]}
name={"Tab"}
bind:el={tabRef}
on:keydown={handleKeyDown} on:keydown={handleKeyDown}
on:click={handleSelection} on:click={handleSelection}
on:focus={$api.activation === "manual" ? handleFocus : handleSelection} on:focus={$api.activation === "manual" ? handleFocus : handleSelection}
> >
<slot {selected} /> <slot {...slotProps} />
</button> </Render>

View File

@@ -1,13 +1,4 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
import {
createEventDispatcher,
getContext,
onMount,
setContext,
} from "svelte";
import { Readable, writable, Writable } from "svelte/store";
export type StateDefinition = { export type StateDefinition = {
// State // State
selectedIndex: number | null; selectedIndex: number | null;
@@ -42,6 +33,25 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import {
createEventDispatcher,
getContext,
onMount,
setContext,
} from "svelte";
import { Readable, writable, Writable } from "svelte/store";
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(), [
"change",
]);
export let as: SupportedAs = "div";
export let use: HTMLActionArray = [];
export let defaultIndex = 0; export let defaultIndex = 0;
export let vertical = false; export let vertical = false;
export let manual = false; export let manual = false;
@@ -120,8 +130,16 @@
selectedIndex = tabs.indexOf(next); selectedIndex = tabs.indexOf(next);
} }
}); });
$: slotProps = { selectedIndex };
</script> </script>
<div {...$$restProps}> <Render
<slot {selectedIndex} /> {...$$restProps}
</div> {as}
{slotProps}
use={[...use, forwardEvents]}
name={"TabGroup"}
>
<slot {...slotProps} />
</Render>

View File

@@ -1,13 +1,30 @@
<script lang="ts"> <script lang="ts">
import { useTabsContext } from "./TabGroup.svelte"; import { useTabsContext } from "./TabGroup.svelte";
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 = [];
let api = useTabsContext("TabList"); let api = useTabsContext("TabList");
$: propsWeControl = { $: propsWeControl = {
role: "tablist", role: "tablist",
"aria-orientation": $api.orientation, "aria-orientation": $api.orientation,
}; };
$: slotProps = { selectedIndex: $api.selectedIndex };
</script> </script>
<div {...{ ...$$restProps, ...propsWeControl }}> <Render
<slot selectedIndex={$api.selectedIndex} /> {...{ ...$$restProps, ...propsWeControl }}
</div> {as}
{slotProps}
use={[...use, forwardEvents]}
name={"TabList"}
>
<slot {...slotProps} />
</Render>

View File

@@ -2,6 +2,15 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { useTabsContext } from "./TabGroup.svelte"; import { useTabsContext } from "./TabGroup.svelte";
import { useId } from "$lib/hooks/use-id"; import { useId } from "$lib/hooks/use-id";
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 = [];
let api = useTabsContext("TabPanel"); let api = useTabsContext("TabPanel");
let id = `headlessui-tabs-panel-${useId()}`; let id = `headlessui-tabs-panel-${useId()}`;
@@ -23,7 +32,12 @@
</script> </script>
{#if selected} {#if selected}
<div {...{ ...$$restProps, ...propsWeControl }}> <Render
{...{ ...$$restProps, ...propsWeControl }}
{as}
use={[...use, forwardEvents]}
name={"TabPanel"}
>
<slot /> <slot />
</div> </Render>
{/if} {/if}

View File

@@ -1,9 +1,25 @@
<script lang="ts"> <script lang="ts">
import { useTabsContext } from "./TabGroup.svelte"; import { useTabsContext } from "./TabGroup.svelte";
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 = [];
let api = useTabsContext("TabPanels"); let api = useTabsContext("TabPanels");
$: slotProps = { selectedIndex: $api.selectedIndex };
</script> </script>
<div {...$$restProps}> <Render
<slot selectedIndex={$api.selectedIndex} /> {...$$restProps}
</div> {as}
{slotProps}
use={[...use, forwardEvents]}
name={"TabPanels"}
>
<slot {...slotProps} />
</Render>