From a5e24c236ae5860b55a02c7e83023c73b6919272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 29 Oct 2021 12:43:55 +0100 Subject: [PATCH 1/4] Update tsconfig.json --- tsconfig.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 9cf7595..14a67b3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,11 @@ { "compilerOptions": { "module": "esnext", - "target": "es5", + "target": "esnext", "strict": true, "declaration": true, "outDir": "dist", - "removeComments": true, - "preserveConstEnums": true + "lib": ["esnext", "dom"] }, "files": [ "src/index.ts" From f4af55e0647b287112ae06a24fcf25ef92dd2e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 29 Oct 2021 12:44:10 +0100 Subject: [PATCH 2/4] Refactor code significantly --- src/index.ts | 87 +++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/src/index.ts b/src/index.ts index 38294e5..8c45069 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,53 +1,52 @@ -interface Subscription { - unsubscribe(): void +interface TextAreaData { + previousValue?: string + previousHeight?: string + x?: number + y?: number + isUserResized?: boolean } -export default function autosize(textarea: HTMLTextAreaElement, {viewportMarginBottom = 100} = {}): Subscription { - let previousValue: string | null = null - let isUserResized = false - - let x: number - let y: number - let height: string - - function onUserResize(event: MouseEvent) { - if (x !== event.clientX || y !== event.clientY) { - const newHeight = textarea.style.height - if (height && height !== newHeight) { - isUserResized = true - textarea.style.maxHeight = '' - textarea.removeEventListener('mousemove', onUserResize) - } - height = newHeight - } +const map = new WeakMap() - x = event.clientX - y = event.clientY +function onUserResize(event: MouseEvent) { + const textarea = event.currentTarget as HTMLTextAreaElement + const options = map.get(textarea) || {} + if (options.x !== event.clientX || options.y !== event.clientY) { + const newHeight = textarea.style.height + if (options.previousHeight && options.previousHeight !== newHeight) { + options.isUserResized = true + textarea.style.maxHeight = '' + textarea.removeEventListener('mousemove', onUserResize) + } + options.previousHeight = newHeight } - const document = textarea.ownerDocument - const documentElement = document.documentElement + options.x = event.clientX + options.y = event.clientY + map.set(textarea, options) +} - function overflowOffset() { - let offsetTop = 0 - let el = textarea +function overflowOffset(textarea: HTMLElement) { + let offsetTop = 0 + let el = textarea - while (el !== document.body && el !== null) { - offsetTop += el.offsetTop || 0 - el = el.offsetParent as HTMLTextAreaElement - } - - const top = offsetTop - document.defaultView!.pageYOffset - const bottom = documentElement.clientHeight - (top + textarea.offsetHeight) - return {top, bottom} + while (el !== textarea.ownerDocument.body && el !== null) { + offsetTop += el.offsetTop || 0 + el = el.offsetParent as HTMLTextAreaElement } + const top = offsetTop - textarea.ownerDocument.defaultView!.pageYOffset + const bottom = textarea.ownerDocument.documentElement.clientHeight - (top + textarea.offsetHeight) + return {top, bottom} +} + +export default function autosize(textarea: HTMLTextAreaElement, {viewportMarginBottom = 100} = {}) { function sizeToFit() { - if (isUserResized) return - if (textarea.value === previousValue) return + if (map.get(textarea)?.isUserResized) return + if (textarea.value === map.get(textarea)?.previousValue) return if (textarea.offsetWidth <= 0 && textarea.offsetHeight <= 0) return - const {top, bottom} = overflowOffset() + const {top, bottom} = overflowOffset(textarea) if (top < 0 || bottom < 0) { return } @@ -71,14 +70,20 @@ export default function autosize(textarea: HTMLTextAreaElement, {viewportMarginB textarea.style.height = 'auto' textarea.style.height = `${textarea.scrollHeight + borderAddOn}px` container.style.height = containerHeight - height = textarea.style.height + const options = map.get(textarea) || {} + options.previousHeight = textarea.style.height } - previousValue = textarea.value + const options = map.get(textarea) || {} + options.previousValue = textarea.value + map.set(textarea, options) } function onFormReset() { - isUserResized = false + const options = map.get(textarea) || {} + options.isUserResized = false + map.set(textarea, options) + textarea.style.height = '' textarea.style.maxHeight = '' } From 2c3352ba4b85f71d542f7680f98e985b8d41db34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 29 Oct 2021 12:59:11 +0100 Subject: [PATCH 3/4] Reset correctly --- src/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8c45069..78e7c7f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -80,9 +80,7 @@ export default function autosize(textarea: HTMLTextAreaElement, {viewportMarginB } function onFormReset() { - const options = map.get(textarea) || {} - options.isUserResized = false - map.set(textarea, options) + map.set(textarea, {}) textarea.style.height = '' textarea.style.maxHeight = '' From fd3ae467c6eeee5d830dff741055ed9a22f4a911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 29 Oct 2021 12:59:23 +0100 Subject: [PATCH 4/4] Add a comment --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index 78e7c7f..c058549 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ interface TextAreaData { const map = new WeakMap() +// Check if textarea has been resized by the user. function onUserResize(event: MouseEvent) { const textarea = event.currentTarget as HTMLTextAreaElement const options = map.get(textarea) || {}