Skip to content

Commit

Permalink
refactor: improve autoresize
Browse files Browse the repository at this point in the history
  • Loading branch information
segunadebayo committed Nov 8, 2024
1 parent 5fba0e3 commit 75be963
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 8 deletions.
6 changes: 6 additions & 0 deletions .changeset/odd-wombats-arrive.md
Original file line number Diff line number Diff line change
@@ -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.
25 changes: 17 additions & 8 deletions packages/utilities/auto-resize/src/autoresize-textarea.ts
Original file line number Diff line number Diff line change
@@ -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")
Expand All @@ -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()
}
}

0 comments on commit 75be963

Please sign in to comment.