Support style as a function
Seems useful to add. Also improve the prop typing of <Render>, marginally, though as these types do not carry over to end users yet, it's just cosmetic for now.
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
|
||||
onMount(() => $contextStore?.register(id));
|
||||
|
||||
$: slotProps = $contextStore!.slotProps;
|
||||
$: slotProps = $contextStore!.slotProps || {};
|
||||
</script>
|
||||
|
||||
<Render
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
{...$$restProps}
|
||||
{as}
|
||||
use={[...use, forwardEvents]}
|
||||
slotProps={{}}
|
||||
name={"PopoverGroup"}
|
||||
bind:el={groupRef}
|
||||
>
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
{...{ ...$$restProps, ...propsWeControl }}
|
||||
{as}
|
||||
use={[...use, forwardEvents]}
|
||||
slotProps={{}}
|
||||
name={"RadioGroup"}
|
||||
bind:el={radioGroupRef}
|
||||
aria-labelledby={labelledby}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
{...$$restProps}
|
||||
{as}
|
||||
use={[...use, forwardEvents]}
|
||||
slotProps={{}}
|
||||
name={"SwitchGroup"}
|
||||
>
|
||||
<DescriptionProvider name="SwitchDescription">
|
||||
|
||||
@@ -195,6 +195,7 @@
|
||||
{...$$restProps}
|
||||
{as}
|
||||
use={[...use, forwardEvents]}
|
||||
slotProps={{}}
|
||||
name={"TransitionChild"}
|
||||
bind:el={container}
|
||||
class={classes}
|
||||
|
||||
@@ -34,16 +34,27 @@
|
||||
import { forwardEventsBuilder } from "$lib/internal/forwardEventsBuilder";
|
||||
const forwardEvents = forwardEventsBuilder(get_current_component());
|
||||
|
||||
type TSlotProps = $$Generic<{}>;
|
||||
|
||||
export let name: string;
|
||||
export let as: SvelteComponent | SupportedElement;
|
||||
export let slotProps: TSlotProps;
|
||||
|
||||
export let el: HTMLElement | null = null;
|
||||
export let use: ActionArray = [];
|
||||
export let slotProps: unknown = {};
|
||||
export let visible = true;
|
||||
export let features: Features = Features.None;
|
||||
// The static and unmount props are only used in conjunction with the render strategies
|
||||
export let unmount = true;
|
||||
|
||||
let classProp: ((props: TSlotProps) => string) | string | undefined =
|
||||
undefined;
|
||||
export { classProp as class };
|
||||
|
||||
// This is not in upstream Headless UI, but we might as well add it here
|
||||
export let style: ((props: TSlotProps) => string) | string | undefined =
|
||||
undefined;
|
||||
|
||||
if (!as) {
|
||||
throw new Error(`<${name}> did not provide an \`as\` value to <Render>`);
|
||||
}
|
||||
@@ -55,7 +66,9 @@
|
||||
);
|
||||
}
|
||||
|
||||
$: classStyle = $$props.class;
|
||||
$: computedClass =
|
||||
typeof classProp === "function" ? classProp(slotProps) : classProp;
|
||||
$: computedStyle = typeof style === "function" ? style(slotProps) : style;
|
||||
|
||||
$: show =
|
||||
visible ||
|
||||
@@ -74,10 +87,9 @@
|
||||
bind:el
|
||||
use={[...use, forwardEvents]}
|
||||
{...$$restProps}
|
||||
class={typeof classStyle === "function"
|
||||
? classStyle(slotProps)
|
||||
: classStyle}
|
||||
style={hidden ? "display: none" : $$props.style}
|
||||
class={computedClass}
|
||||
style={`${computedStyle ?? ""}${hidden ? " display: none" : ""}` ||
|
||||
undefined}
|
||||
hidden={hidden || undefined}
|
||||
>
|
||||
<slot />
|
||||
|
||||
52
src/lib/utils/render.test.ts
vendored
Normal file
52
src/lib/utils/render.test.ts
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import Render from "$lib/utils/Render.svelte";
|
||||
// import svelte from "svelte-inline-compile";
|
||||
import { getByTestId, render } from "@testing-library/svelte";
|
||||
|
||||
it("should be possible to use class as a string", () => {
|
||||
let { container } = render(Render, {
|
||||
as: "div",
|
||||
name: "test",
|
||||
slotProps: {},
|
||||
class: "test-class",
|
||||
"data-testid": "test-id",
|
||||
});
|
||||
let element = getByTestId(container, "test-id");
|
||||
expect(element).toHaveClass("test-class");
|
||||
});
|
||||
|
||||
it("should be possible to use class as a function", () => {
|
||||
render(Render, {
|
||||
as: "div",
|
||||
name: "test",
|
||||
slotProps: { foo: "bar" },
|
||||
class: JSON.stringify,
|
||||
id: "test-id",
|
||||
});
|
||||
expect("" + document.querySelector("#test-id")?.classList).toEqual(
|
||||
JSON.stringify({ foo: "bar" })
|
||||
);
|
||||
});
|
||||
|
||||
it("should be possible to use style as a string", () => {
|
||||
let { container } = render(Render, {
|
||||
as: "div",
|
||||
name: "test",
|
||||
slotProps: {},
|
||||
style: "background-color: green",
|
||||
"data-testid": "test-id",
|
||||
});
|
||||
let element = getByTestId(container, "test-id");
|
||||
expect(element).toHaveStyle("background-color: green");
|
||||
});
|
||||
|
||||
it("should be possible to use style as a function", () => {
|
||||
let { container } = render(Render, {
|
||||
as: "div",
|
||||
name: "test",
|
||||
slotProps: { enabled: true },
|
||||
style: ({ enabled }: { enabled: boolean }) => enabled ? "background-color: red" : "background-color: green",
|
||||
"data-testid": "test-id",
|
||||
});
|
||||
let element = getByTestId(container, "test-id");
|
||||
expect(element).toHaveStyle("background-color: red");
|
||||
});
|
||||
Reference in New Issue
Block a user