melt
Version:
The next generation of Melt UI. Built for Svelte 5.
65 lines (64 loc) • 1.77 kB
JavaScript
import { extract } from "../utils/extract";
import { Synced } from "../Synced.svelte";
import { dataAttr } from "../utils/attribute";
import { createBuilderMetadata } from "../utils/identifiers";
const { dataAttrs, createIds } = createBuilderMetadata("collapsible", ["trigger", "content"]);
export class Collapsible {
// Props
#props;
disabled = $derived(extract(this.#props.disabled, false));
// State
#open;
ids = $state(createIds());
constructor(props = {}) {
this.#props = props;
this.#open = new Synced({
value: props.open,
onChange: props.onOpenChange,
defaultValue: false,
});
}
/**
* The open state of the collapsible.
*/
get open() {
return this.#open.current;
}
set open(open) {
this.#open.current = open;
}
get #sharedAttrs() {
return {
"data-state": this.open ? "open" : "closed",
"data-disabled": dataAttr(this.disabled),
};
}
/**
* The spread attributes for the trigger button.
*/
get trigger() {
return {
[dataAttrs.trigger]: "",
id: this.ids.trigger,
"aria-expanded": this.open,
"aria-controls": this.ids.content,
...this.#sharedAttrs,
disabled: this.disabled,
onclick: () => {
if (this.disabled)
return;
this.#open.current = !this.#open.current;
},
};
}
/**
* The spread attributes for the content element.
*/
get content() {
return {
[dataAttrs.content]: "",
id: this.ids.content,
...this.#sharedAttrs,
};
}
}