Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next: chores and cleanup #576

Merged
merged 5 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"build:packages": "pnpm -F \"./packages/**\" --parallel build",
"check": "pnpm build:packages && pnpm -r check",
"ci:publish": "pnpm build:packages && changeset publish",
"dev": "pnpm -r --parallel dev",
"dev": "pnpm -F \"./packages/**\" svelte-kit sync && pnpm -r --parallel dev",
"format": "prettier --write .",
"lint": "prettier --check . && eslint .",
"lint:fix": "eslint --fix .",
Expand Down
2 changes: 1 addition & 1 deletion packages/bits-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"vite": "^5.2.8",
"vitest": "^1.5.0"
"vitest": "^1.6.0"
},
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
99 changes: 75 additions & 24 deletions packages/bits-ui/src/lib/bits/accordion/accordion.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { WritableBox } from "svelte-toolbelt";
import {
type Box,
type ReadableBoxedValues,
Expand All @@ -10,7 +9,7 @@ import {
getDataOpenClosed,
getDataOrientation,
kbd,
useNodeById,
useRefById,
} from "$lib/internal/index.js";
import { type UseRovingFocusReturn, useRovingFocus } from "$lib/internal/useRovingFocus.svelte.js";
import type { Orientation } from "$lib/shared/index.js";
Expand All @@ -31,25 +30,33 @@ type AccordionBaseStateProps = ReadableBoxedValues<{
disabled: boolean;
orientation: Orientation;
loop: boolean;
ref: HTMLElement | null | undefined;
}>;
}> &
WritableBoxedValues<{
ref: HTMLElement | null;
}>;

class AccordionBaseState {
id: AccordionBaseStateProps["id"];
node: WritableBox<HTMLElement | null>;
#id: AccordionBaseStateProps["id"];
#ref: AccordionBaseStateProps["ref"];
disabled: AccordionBaseStateProps["disabled"];
#loop: AccordionBaseStateProps["loop"];
orientation: AccordionBaseStateProps["orientation"];
rovingFocusGroup: UseRovingFocusReturn;

constructor(props: AccordionBaseStateProps) {
this.id = props.id;
this.#id = props.id;
this.disabled = props.disabled;
this.node = useNodeById(this.id);
this.#ref = props.ref;

useRefById({
id: props.id,
ref: this.#ref,
});

this.orientation = props.orientation;
this.#loop = props.loop;
this.rovingFocusGroup = useRovingFocus({
rootNodeId: this.id,
rootNodeId: this.#id,
candidateSelector: TRIGGER_ATTR,
loop: this.#loop,
orientation: this.orientation,
Expand All @@ -59,7 +66,7 @@ class AccordionBaseState {
props = $derived.by(
() =>
({
id: this.id.value,
id: this.#id.value,
"data-orientation": getDataOrientation(this.orientation.value),
"data-disabled": getDataDisabled(this.disabled.value),
[ROOT_ATTR]: "",
Expand Down Expand Up @@ -126,11 +133,16 @@ export class AccordionMultiState extends AccordionBaseState {
type AccordionItemStateProps = ReadableBoxedValues<{
value: string;
disabled: boolean;
id: string;
}> & {
rootState: AccordionState;
};
} & WritableBoxedValues<{
ref: HTMLElement | null;
}>;

export class AccordionItemState {
#id: AccordionItemStateProps["id"];
#ref: AccordionItemStateProps["ref"];
value: AccordionItemStateProps["value"];
disabled: AccordionItemStateProps["disabled"];
root: AccordionState;
Expand All @@ -141,6 +153,13 @@ export class AccordionItemState {
this.value = props.value;
this.disabled = props.disabled;
this.root = props.rootState;
this.#id = props.id;
this.#ref = props.ref;

useRefById({
id: this.#id,
ref: this.#ref,
});
}

updateValue() {
Expand All @@ -162,6 +181,7 @@ export class AccordionItemState {
props = $derived.by(
() =>
({
id: this.#id.value,
[ITEM_ATTR]: "",
"data-state": getDataOpenClosed(this.isSelected),
"data-disabled": getDataDisabled(this.isDisabled),
Expand All @@ -176,12 +196,15 @@ export class AccordionItemState {
type AccordionTriggerStateProps = ReadableBoxedValues<{
disabled: boolean;
id: string;
}>;
}> &
WritableBoxedValues<{
ref: HTMLElement | null;
}>;

class AccordionTriggerState {
#ref: AccordionTriggerStateProps["ref"];
#disabled: AccordionTriggerStateProps["disabled"];
#id: AccordionTriggerStateProps["id"];
#node: Box<HTMLElement | null>;
#root: AccordionState;
#itemState: AccordionItemState;
#isDisabled = $derived.by(
Expand All @@ -193,8 +216,12 @@ class AccordionTriggerState {
this.#itemState = itemState;
this.#root = itemState.root;
this.#id = props.id;
this.#ref = props.ref;

this.#node = useNodeById(this.#id);
useRefById({
id: props.id,
ref: this.#ref,
});
}

#onclick = () => {
Expand All @@ -209,7 +236,7 @@ class AccordionTriggerState {
return;
}

this.#root.rovingFocusGroup.handleKeydown(this.#node.value, e);
this.#root.rovingFocusGroup.handleKeydown(this.#ref.value, e);
};

props = $derived.by(
Expand Down Expand Up @@ -238,11 +265,14 @@ class AccordionTriggerState {
type AccordionContentStateProps = ReadableBoxedValues<{
forceMount: boolean;
id: string;
}>;
}> &
WritableBoxedValues<{
ref: HTMLElement | null;
}>;

class AccordionContentState {
item: AccordionItemState;
node: WritableBox<HTMLElement | null>;
#ref: AccordionContentStateProps["ref"];
#id: AccordionContentStateProps["id"];
#originalStyles: { transitionDuration: string; animationName: string } | undefined = undefined;
#isMountAnimationPrevented = false;
Expand All @@ -257,8 +287,12 @@ class AccordionContentState {
this.#forceMount = props.forceMount;
this.#isMountAnimationPrevented = this.item.isSelected;
this.#id = props.id;
this.#ref = props.ref;

this.node = useNodeById(this.#id);
useRefById({
id: this.#id,
ref: this.#ref,
});

$effect.pre(() => {
const rAF = requestAnimationFrame(() => {
Expand All @@ -273,11 +307,11 @@ class AccordionContentState {
$effect(() => {
// eslint-disable-next-line no-unused-expressions
this.present;
const node = this.node.value;
const node = this.#ref.value;
if (!node) return;

afterTick(() => {
if (!this.node) return;
if (!this.#ref.value) return;
// get the dimensions of the element
this.#originalStyles = this.#originalStyles || {
transitionDuration: node.style.transitionDuration,
Expand Down Expand Up @@ -320,19 +354,34 @@ class AccordionContentState {

type AccordionHeaderStateProps = ReadableBoxedValues<{
level: 1 | 2 | 3 | 4 | 5 | 6;
}>;
id: string;
}> &
WritableBoxedValues<{
ref: HTMLElement | null;
}>;

class AccordionHeaderState {
#item: AccordionItemState;
#id: AccordionHeaderStateProps["id"];
#ref: AccordionHeaderStateProps["ref"];
#level: AccordionHeaderStateProps["level"];
#item: AccordionItemState;
constructor(props: AccordionHeaderStateProps, item: AccordionItemState) {
this.#level = props.level;
this.#id = props.id;
this.#ref = props.ref;

useRefById({
id: this.#id,
ref: this.#ref,
});

this.#item = item;
}

props = $derived.by(
() =>
({
id: this.#id.value,
role: "heading",
"aria-level": this.#level.value,
"data-heading-level": this.#level.value,
Expand All @@ -357,8 +406,10 @@ type InitAccordionProps = {
disabled: boolean;
orientation: Orientation;
loop: boolean;
ref: HTMLElement | null | undefined;
}>;
}> &
WritableBoxedValues<{
ref: HTMLElement | null;
}>;

const [setAccordionRootContext, getAccordionRootContext] =
createContext<AccordionState>("Accordion.Root");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
let {
child,
asChild,
ref = $bindable(),
ref = $bindable(null),
id = useId(),
forceMount = false,
children,
Expand All @@ -18,6 +18,10 @@
const contentState = useAccordionContent({
forceMount: box.with(() => forceMount),
id: box.with(() => id),
ref: box.with(
() => ref,
(v) => (ref = v)
),
});
</script>

Expand All @@ -31,7 +35,7 @@
props: mergedProps,
})}
{:else}
<div {...mergedProps} bind:this={ref}>
<div {...mergedProps}>
{@render children?.()}
</div>
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@
import type { AccordionHeaderProps } from "../types.js";
import { useAccordionHeader } from "../accordion.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
import { useId } from "$lib/internal/useId.svelte.js";

let {
id = useId(),
asChild,
level = 2,
children,
child,
ref = $bindable(),
ref = $bindable(null),
...restProps
}: AccordionHeaderProps = $props();

const headerState = useAccordionHeader({
id: box.with(() => id),
level: box.with(() => level),
ref: box.with(
() => ref,
(v) => (ref = v)
),
});

const mergedProps = $derived(mergeProps(restProps, headerState.props));
Expand All @@ -23,7 +30,7 @@
{#if asChild}
{@render child?.({ props: mergedProps })}
{:else}
<div {...mergedProps} bind:this={ref}>
<div {...mergedProps}>
{@render children?.()}
</div>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,27 @@
import type { AccordionItemProps } from "../types.js";
import { useAccordionItem } from "../accordion.svelte.js";
import { mergeProps } from "$lib/internal/mergeProps.js";
import { useId } from "$lib/internal/useId.svelte.js";

let {
id = useId(),
asChild,
disabled = false,
value,
children,
child,
ref = $bindable(),
ref = $bindable(null),
...restProps
}: AccordionItemProps = $props();

const itemState = useAccordionItem({
value: box.with(() => value),
disabled: box.with(() => disabled),
id: box.with(() => id),
ref: box.with(
() => ref,
(v) => (ref = v)
),
});

const mergedProps = $derived(mergeProps(restProps, itemState.props));
Expand All @@ -25,7 +32,7 @@
{#if asChild}
{@render child?.({ props: mergedProps })}
{:else}
<div {...mergedProps} bind:this={ref}>
<div {...mergedProps}>
{@render children?.()}
</div>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let {
disabled = false,
asChild,
ref = $bindable(),
ref = $bindable(null),
id = useId(),
children,
child,
Expand All @@ -17,6 +17,10 @@
const triggerState = useAccordionTrigger({
disabled: box.with(() => disabled),
id: box.with(() => id),
ref: box.with(
() => ref,
(v) => (ref = v)
),
});

const mergedProps = $derived(mergeProps(restProps, triggerState.props));
Expand All @@ -25,7 +29,7 @@
{#if asChild}
{@render child?.({ props: mergedProps })}
{:else}
<button bind:this={ref} type="button" {...mergedProps}>
<button type="button" {...mergedProps}>
{@render children?.()}
</button>
{/if}
Loading
Loading