Files
eewing ec317eb17c
CI / build (push) Has been skipped
CI / deploy (push) Successful in 1m11s
INIT
2026-02-18 15:17:47 -06:00

51 lines
1.8 KiB
JavaScript

import { untrack } from "svelte";
import { isBox } from "../box/box-extras.svelte.js";
import { createAttachmentKey } from "svelte/attachments";
/**
* Creates a Svelte Attachment that attaches a DOM element to a ref.
* The ref can be either a WritableBox or a callback function.
*
* @param ref - Either a WritableBox to store the element in, or a callback function that receives the element
* @param onChange - Optional callback that fires when the ref changes
* @returns An object with a spreadable attachment key that should be spread onto the element
*
* @example
* // Using with WritableBox
* const ref = box<HTMLDivElement | null>(null);
* <div {...attachRef(ref)}>Content</div>
*
* @example
* // Using with callback
* <div {...attachRef((node) => myNode = node)}>Content</div>
*
* @example
* // Using with onChange
* <div {...attachRef(ref, (node) => console.log(node))}>Content</div>
*/
export function attachRef(ref, onChange) {
return {
[createAttachmentKey()]: (node) => {
if (isBox(ref)) {
ref.current = node;
untrack(() => onChange?.(node));
return () => {
// we don't want to detach the node if it's still connected
if ("isConnected" in node && node.isConnected)
return;
ref.current = null;
onChange?.(null);
};
}
ref(node);
untrack(() => onChange?.(node));
return () => {
// we don't want to detach the node if it's still connected
if ("isConnected" in node && node.isConnected)
return;
ref(null);
onChange?.(null);
};
}
};
}