From 75be9630851f64cce365b178c8200eeec7829605 Mon Sep 17 00:00:00 2001 From: Segun Adebayo Date: Fri, 8 Nov 2024 13:59:05 +0000 Subject: [PATCH] refactor: improve autoresize --- .changeset/odd-wombats-arrive.md | 6 +++++ .../auto-resize/src/autoresize-textarea.ts | 25 +++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 .changeset/odd-wombats-arrive.md diff --git a/.changeset/odd-wombats-arrive.md b/.changeset/odd-wombats-arrive.md new file mode 100644 index 0000000000..f9419c579e --- /dev/null +++ b/.changeset/odd-wombats-arrive.md @@ -0,0 +1,6 @@ +--- +"@zag-js/auto-resize": patch +--- + +- Fix issue where resize observer was not cleanup. +- Trigger resize when `rows` attribute changes and fonts are loaded. diff --git a/packages/utilities/auto-resize/src/autoresize-textarea.ts b/packages/utilities/auto-resize/src/autoresize-textarea.ts index 1e7edcf127..1b17c4f370 100644 --- a/packages/utilities/auto-resize/src/autoresize-textarea.ts +++ b/packages/utilities/auto-resize/src/autoresize-textarea.ts @@ -1,19 +1,21 @@ -import { getComputedStyle } from "@zag-js/dom-query" +import { getComputedStyle, getDocument, getWindow } from "@zag-js/dom-query" export const autoresizeTextarea = (el: HTMLTextAreaElement | null) => { if (!el) return const style = getComputedStyle(el) - const win = el.ownerDocument.defaultView || window - const onInput = () => { + const win = getWindow(el) + const doc = getDocument(el) + + const resize = () => { el.style.height = "auto" const borderTopWidth = parseInt(style.borderTopWidth, 10) const borderBottomWidth = parseInt(style.borderBottomWidth, 10) el.style.height = `${el.scrollHeight + borderTopWidth + borderBottomWidth}px` } - el.addEventListener("input", onInput) + el.addEventListener("input", resize) const elementPrototype = Object.getPrototypeOf(el) const descriptor = Object.getOwnPropertyDescriptor(elementPrototype, "value") @@ -22,15 +24,22 @@ export const autoresizeTextarea = (el: HTMLTextAreaElement | null) => { set() { // @ts-ignore descriptor?.set?.apply(this, arguments as unknown as [unknown]) - onInput() + resize() }, }) - const resizeObserver = new win.ResizeObserver(() => onInput()) - + const resizeObserver = new win.ResizeObserver(() => resize()) resizeObserver.observe(el) + const attrObserver = new win.MutationObserver(() => resize()) + attrObserver.observe(el, { attributes: true, attributeFilter: ["rows", "placeholder"] }) + + doc.fonts?.addEventListener("loadingdone", resize) + return () => { - el.removeEventListener("input", onInput) + el.removeEventListener("input", resize) + doc.fonts?.removeEventListener("loadingdone", resize) + resizeObserver.disconnect() + attrObserver.disconnect() } }