UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

1 lines 7.29 kB
{"version":3,"file":"use-autosize.cjs","names":["rows: number","value","getTextareaProps: PropGetter<\"textarea\">","mergeRefs"],"sources":["../../../../src/components/textarea/use-autosize.ts"],"sourcesContent":["\"use client\"\n\nimport type { PropGetter } from \"../../core\"\nimport { useCallback, useRef } from \"react\"\nimport {\n addDomEvent,\n createdDom,\n handlerAll,\n mergeRefs,\n noop,\n pickObject,\n useSafeLayoutEffect,\n useUpdateEffect,\n} from \"../../utils\"\n\nconst SIZING_STYLE_PROPERTIES = [\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderRightWidth\",\n \"borderTopWidth\",\n \"boxSizing\",\n \"fontFamily\",\n \"fontSize\",\n \"fontStyle\",\n \"fontWeight\",\n \"letterSpacing\",\n \"lineHeight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"paddingRight\",\n \"paddingTop\",\n // non-standard\n \"tabSize\",\n \"textIndent\",\n // non-standard\n \"textRendering\",\n \"textTransform\",\n \"width\",\n \"wordBreak\",\n] as const\n\nconst HIDDEN_STYLE = {\n height: \"0\",\n \"max-height\": \"none\",\n \"min-height\": \"0\",\n overflow: \"hidden\",\n position: \"absolute\",\n right: \"0\",\n top: \"0\",\n visibility: \"hidden\",\n \"z-index\": \"-1000\",\n} as const\n\ntype SizingProperties = Extract<\n (typeof SIZING_STYLE_PROPERTIES)[number],\n keyof CSSStyleDeclaration\n>\n\ninterface SizingStyle {\n style: Pick<CSSStyleDeclaration, SizingProperties>\n border: number\n padding: number\n rowHeight: number\n}\n\nconst getSizingStyle = (el: HTMLElement): null | SizingStyle => {\n const style = window.getComputedStyle(el) as CSSStyleDeclaration | undefined\n\n if (style == null) return null\n\n const computedStyle = pickObject(style, SIZING_STYLE_PROPERTIES)\n\n if (computedStyle.boxSizing === \"\") return null\n\n const padding =\n parseFloat(computedStyle.paddingBottom!) +\n parseFloat(computedStyle.paddingTop!)\n\n const border =\n parseFloat(computedStyle.borderBottomWidth!) +\n parseFloat(computedStyle.borderTopWidth!)\n\n const rowHeight = parseFloat(computedStyle.lineHeight!)\n\n return {\n style: computedStyle,\n border,\n padding,\n rowHeight,\n }\n}\n\nconst setHiddenStyle = (el: HTMLElement) => {\n Object.keys(HIDDEN_STYLE).forEach((key) => {\n el.style.setProperty(\n key,\n HIDDEN_STYLE[key as keyof typeof HIDDEN_STYLE],\n \"important\",\n )\n })\n}\n\nconst calcRows = (\n el: HTMLTextAreaElement,\n sizingStyle: SizingStyle,\n value: string,\n maxRows: number,\n minRows: number,\n) => {\n const cloneEl = el.cloneNode() as HTMLTextAreaElement\n\n Object.assign(cloneEl.style, sizingStyle.style)\n\n setHiddenStyle(cloneEl)\n\n cloneEl.value = value\n\n document.body.appendChild(cloneEl)\n\n let rows: number\n\n if (cloneEl.scrollHeight) {\n const rowHeight = sizingStyle.rowHeight\n\n rows = Math.min(\n maxRows,\n Math.max(minRows, Math.floor(cloneEl.scrollHeight / rowHeight)),\n )\n } else {\n const lineBreaks = (value.match(/\\n/g) || []).length\n\n rows = Math.min(maxRows, Math.max(minRows, lineBreaks + 1))\n }\n\n document.body.removeChild(cloneEl)\n\n return rows\n}\n\nexport interface UseAutosizeProps {\n /**\n * If `true`, the Textarea height will not be adjusted.\n *\n * @default false\n */\n disabled?: boolean\n /**\n * Autosize up to maxRows rows.\n *\n * @default Infinity\n */\n maxRows?: number\n /**\n * Autosize up to minRows rows.\n *\n * @default 2\n */\n minRows?: number\n}\n\nexport const useAutosize = ({\n disabled = false,\n maxRows = Infinity,\n minRows = 2,\n}: UseAutosizeProps = {}) => {\n const ref = useRef<HTMLTextAreaElement>(null)\n const beforeValueRef = useRef<string>(null)\n const value = ref.current?.value ?? \"\"\n\n const onResizeTextarea = useCallback(() => {\n const el = ref.current\n\n if (!el) return\n\n let { placeholder, value } = el\n\n if (value === beforeValueRef.current) return\n\n beforeValueRef.current = value\n\n value ||= placeholder || \"x\"\n\n const sizingStyle = getSizingStyle(el)\n\n if (!sizingStyle) return\n\n const rows = calcRows(el, sizingStyle, value, maxRows, minRows)\n\n el.rows = rows\n }, [ref, maxRows, minRows])\n\n const getTextareaProps: PropGetter<\"textarea\"> = useCallback(\n (props = {}) => ({\n ...props,\n ref: mergeRefs(props.ref, ref),\n style: { resize: !disabled ? \"none\" : undefined, ...props.style },\n onChange: handlerAll(props.onChange, !disabled ? onResizeTextarea : noop),\n }),\n [ref, onResizeTextarea, disabled],\n )\n\n useSafeLayoutEffect(() => {\n if (!createdDom() || disabled) return\n\n onResizeTextarea()\n\n const unsubscribeResize = addDomEvent(window, \"resize\", onResizeTextarea)\n const unsubscribeLoadingdone = addDomEvent(\n document.fonts,\n \"loadingdone\",\n onResizeTextarea,\n )\n\n return () => {\n unsubscribeResize()\n unsubscribeLoadingdone()\n }\n }, [])\n\n useUpdateEffect(() => {\n if (disabled) return\n\n onResizeTextarea()\n }, [value])\n\n return { ref, getTextareaProps, onResizeTextarea }\n}\n\nexport type UseAutosizeReturn = ReturnType<typeof useAutosize>\n"],"mappings":";;;;;;;;;;;AAeA,MAAM,0BAA0B;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACD;AAED,MAAM,eAAe;CACnB,QAAQ;CACR,cAAc;CACd,cAAc;CACd,UAAU;CACV,UAAU;CACV,OAAO;CACP,KAAK;CACL,YAAY;CACZ,WAAW;CACZ;AAcD,MAAM,kBAAkB,OAAwC;CAC9D,MAAM,QAAQ,OAAO,iBAAiB,GAAG;AAEzC,KAAI,SAAS,KAAM,QAAO;CAE1B,MAAM,kEAA2B,OAAO,wBAAwB;AAEhE,KAAI,cAAc,cAAc,GAAI,QAAO;CAE3C,MAAM,UACJ,WAAW,cAAc,cAAe,GACxC,WAAW,cAAc,WAAY;AAQvC,QAAO;EACL,OAAO;EACP,QAPA,WAAW,cAAc,kBAAmB,GAC5C,WAAW,cAAc,eAAgB;EAOzC;EACA,WANgB,WAAW,cAAc,WAAY;EAOtD;;AAGH,MAAM,kBAAkB,OAAoB;AAC1C,QAAO,KAAK,aAAa,CAAC,SAAS,QAAQ;AACzC,KAAG,MAAM,YACP,KACA,aAAa,MACb,YACD;GACD;;AAGJ,MAAM,YACJ,IACA,aACA,OACA,SACA,YACG;CACH,MAAM,UAAU,GAAG,WAAW;AAE9B,QAAO,OAAO,QAAQ,OAAO,YAAY,MAAM;AAE/C,gBAAe,QAAQ;AAEvB,SAAQ,QAAQ;AAEhB,UAAS,KAAK,YAAY,QAAQ;CAElC,IAAIA;AAEJ,KAAI,QAAQ,cAAc;EACxB,MAAM,YAAY,YAAY;AAE9B,SAAO,KAAK,IACV,SACA,KAAK,IAAI,SAAS,KAAK,MAAM,QAAQ,eAAe,UAAU,CAAC,CAChE;QACI;EACL,MAAM,cAAc,MAAM,MAAM,MAAM,IAAI,EAAE,EAAE;AAE9C,SAAO,KAAK,IAAI,SAAS,KAAK,IAAI,SAAS,aAAa,EAAE,CAAC;;AAG7D,UAAS,KAAK,YAAY,QAAQ;AAElC,QAAO;;AAwBT,MAAa,eAAe,EAC1B,WAAW,OACX,UAAU,UACV,UAAU,MACU,EAAE,KAAK;CAC3B,MAAM,wBAAkC,KAAK;CAC7C,MAAM,mCAAgC,KAAK;CAC3C,MAAM,QAAQ,IAAI,SAAS,SAAS;CAEpC,MAAM,gDAAqC;EACzC,MAAM,KAAK,IAAI;AAEf,MAAI,CAAC,GAAI;EAET,IAAI,EAAE,aAAa,mBAAU;AAE7B,MAAIC,YAAU,eAAe,QAAS;AAEtC,iBAAe,UAAUA;AAEzB,cAAU,eAAe;EAEzB,MAAM,cAAc,eAAe,GAAG;AAEtC,MAAI,CAAC,YAAa;AAIlB,KAAG,OAFU,SAAS,IAAI,aAAaA,SAAO,SAAS,QAAQ;IAG9D;EAAC;EAAK;EAAS;EAAQ,CAAC;CAE3B,MAAMC,2CACH,QAAQ,EAAE,MAAM;EACf,GAAG;EACH,KAAKC,sBAAU,MAAM,KAAK,IAAI;EAC9B,OAAO;GAAE,QAAQ,CAAC,WAAW,SAAS;GAAW,GAAG,MAAM;GAAO;EACjE,4DAAqB,MAAM,UAAU,CAAC,WAAW,qDAAmB,KAAK;EAC1E,GACD;EAAC;EAAK;EAAkB;EAAS,CAClC;AAED,0CAA0B;AACxB,MAAI,oDAAa,IAAI,SAAU;AAE/B,oBAAkB;EAElB,MAAM,uEAAgC,QAAQ,UAAU,iBAAiB;EACzE,MAAM,4EACJ,SAAS,OACT,eACA,iBACD;AAED,eAAa;AACX,sBAAmB;AACnB,2BAAwB;;IAEzB,EAAE,CAAC;AAEN,sCAAsB;AACpB,MAAI,SAAU;AAEd,oBAAkB;IACjB,CAAC,MAAM,CAAC;AAEX,QAAO;EAAE;EAAK;EAAkB;EAAkB"}