@contember/react-utils 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/development/hooks/useAddClassNameDuringResize.js +0 -5
  2. package/dist/development/hooks/useAddClassNameDuringResize.js.map +1 -1
  3. package/dist/development/hooks/useAutoHeightTextArea.js +5 -5
  4. package/dist/development/hooks/useAutoHeightTextArea.js.map +1 -1
  5. package/dist/development/hooks/useChildrenAsLabel.js +53 -0
  6. package/dist/development/hooks/useChildrenAsLabel.js.map +1 -0
  7. package/dist/development/hooks/useElementSize.js +13 -23
  8. package/dist/development/hooks/useElementSize.js.map +1 -1
  9. package/dist/development/hooks/useOnElementResize.js +24 -28
  10. package/dist/development/hooks/useOnElementResize.js.map +1 -1
  11. package/dist/development/hooks/useScrollOffsets.js +6 -7
  12. package/dist/development/hooks/useScrollOffsets.js.map +1 -1
  13. package/dist/development/index.js +3 -0
  14. package/dist/development/index.js.map +1 -1
  15. package/dist/production/hooks/useAddClassNameDuringResize.js +0 -5
  16. package/dist/production/hooks/useAddClassNameDuringResize.js.map +1 -1
  17. package/dist/production/hooks/useAutoHeightTextArea.js +5 -5
  18. package/dist/production/hooks/useAutoHeightTextArea.js.map +1 -1
  19. package/dist/production/hooks/useChildrenAsLabel.js +52 -0
  20. package/dist/production/hooks/useChildrenAsLabel.js.map +1 -0
  21. package/dist/production/hooks/useElementSize.js +13 -23
  22. package/dist/production/hooks/useElementSize.js.map +1 -1
  23. package/dist/production/hooks/useOnElementResize.js +24 -28
  24. package/dist/production/hooks/useOnElementResize.js.map +1 -1
  25. package/dist/production/hooks/useScrollOffsets.js +6 -7
  26. package/dist/production/hooks/useScrollOffsets.js.map +1 -1
  27. package/dist/production/index.js +3 -0
  28. package/dist/production/index.js.map +1 -1
  29. package/dist/types/hooks/index.d.ts +1 -0
  30. package/dist/types/hooks/index.d.ts.map +1 -1
  31. package/dist/types/hooks/useAddClassNameDuringResize.d.ts.map +1 -1
  32. package/dist/types/hooks/useChildrenAsLabel.d.ts +18 -0
  33. package/dist/types/hooks/useChildrenAsLabel.d.ts.map +1 -0
  34. package/dist/types/hooks/useElementSize.d.ts +4 -0
  35. package/dist/types/hooks/useElementSize.d.ts.map +1 -1
  36. package/dist/types/hooks/useOnElementResize.d.ts.map +1 -1
  37. package/dist/types/hooks/useScrollOffsets.d.ts.map +1 -1
  38. package/dist/types/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +4 -3
  40. package/src/hooks/index.ts +1 -0
  41. package/src/hooks/useAddClassNameDuringResize.ts +0 -6
  42. package/src/hooks/useAutoHeightTextArea.ts +5 -5
  43. package/src/hooks/useChildrenAsLabel.ts +72 -0
  44. package/src/hooks/useElementSize.ts +17 -34
  45. package/src/hooks/useOnElementResize.ts +30 -33
  46. package/src/hooks/useScrollOffsets.ts +6 -7
@@ -1,19 +1,14 @@
1
1
  import { useRef, useLayoutEffect } from "react";
2
2
  import { useOnWindowResize } from "./useOnWindowResize.js";
3
3
  import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js";
4
- function intendedFlushOfCSSChangesToCauseImmediateReflow(element) {
5
- element.offsetHeight;
6
- }
7
4
  function addClassName(className, element) {
8
5
  if (element.classList.contains(className)) {
9
6
  element.classList.remove(className);
10
- intendedFlushOfCSSChangesToCauseImmediateReflow(element);
11
7
  }
12
8
  }
13
9
  function removeClassName(className, element) {
14
10
  if (!element.classList.contains(className)) {
15
11
  element.classList.add(className);
16
- intendedFlushOfCSSChangesToCauseImmediateReflow(element);
17
12
  }
18
13
  }
19
14
  function useAddClassNameDuringResize(className, timeoutToRestore = 300, element) {
@@ -1 +1 @@
1
- {"version":3,"file":"useAddClassNameDuringResize.js","sources":["../../../src/hooks/useAddClassNameDuringResize.ts"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react'\nimport { useReferentiallyStableCallback } from '../referentiallyStable'\nimport { useOnWindowResize } from './useOnWindowResize'\n\nfunction intendedFlushOfCSSChangesToCauseImmediateReflow(element: HTMLElement) {\n\telement.offsetHeight\n}\n\nfunction addClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (element.classList.contains(className)) {\n\t\telement.classList.remove(className)\n\t\tintendedFlushOfCSSChangesToCauseImmediateReflow(element)\n\t}\n}\n\nfunction removeClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (!element.classList.contains(className)) {\n\t\telement.classList.add(className)\n\t\tintendedFlushOfCSSChangesToCauseImmediateReflow(element)\n\t}\n}\n\n/**\n * Adds CSS class during resize event to element\n *\n * - Falls back to document.body when no element is specified\n * - Adds CSS class to element also on the initial load\n * - Uses element.classList directly\n *\n * @param className - CSS class to apply during the resize event\n * @param timeoutToRestore - Timeout in milliseconds to wait before finally removing the CSS class\n * @param element - Optional HTML element to apply CSS class to\n */\nexport function useAddClassNameDuringResize(\n\tclassName: string,\n\ttimeoutToRestore: number = 300,\n\telement?: HTMLElement,\n) {\n\tconst timeoutID = useRef<number>()\n\n\tconst addTemporaryClassName = useReferentiallyStableCallback(() => {\n\t\tclearTimeout(timeoutID.current)\n\t\tremoveClassName(className, element ?? document.body)\n\n\t\ttimeoutID.current = setTimeout(() => {\n\t\t\taddClassName(className, element ?? document.body)\n\t\t}, timeoutToRestore)\n\n\t\treturn () => {\n\t\t\tclearTimeout(timeoutID.current)\n\t\t}\n\t})\n\n\tuseLayoutEffect(addTemporaryClassName, [addTemporaryClassName])\n\tuseOnWindowResize(addTemporaryClassName)\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,gDAAgD,SAAsB;AACtE,UAAA;AACT;AAEA,SAAS,aACR,WACA,SACC;AACD,MAAI,QAAQ,UAAU,SAAS,SAAS,GAAG;AAClC,YAAA,UAAU,OAAO,SAAS;AAClC,oDAAgD,OAAO;AAAA,EACxD;AACD;AAEA,SAAS,gBACR,WACA,SACC;AACD,MAAI,CAAC,QAAQ,UAAU,SAAS,SAAS,GAAG;AACnC,YAAA,UAAU,IAAI,SAAS;AAC/B,oDAAgD,OAAO;AAAA,EACxD;AACD;AAaO,SAAS,4BACf,WACA,mBAA2B,KAC3B,SACC;AACD,QAAM,YAAY;AAEZ,QAAA,wBAAwB,+BAA+B,MAAM;AAClE,iBAAa,UAAU,OAAO;AACd,oBAAA,WAAW,WAAW,SAAS,IAAI;AAEzC,cAAA,UAAU,WAAW,MAAM;AACvB,mBAAA,WAAW,WAAW,SAAS,IAAI;AAAA,OAC9C,gBAAgB;AAEnB,WAAO,MAAM;AACZ,mBAAa,UAAU,OAAO;AAAA,IAAA;AAAA,EAC/B,CACA;AAEe,kBAAA,uBAAuB,CAAC,qBAAqB,CAAC;AAC9D,oBAAkB,qBAAqB;AACxC;"}
1
+ {"version":3,"file":"useAddClassNameDuringResize.js","sources":["../../../src/hooks/useAddClassNameDuringResize.ts"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react'\nimport { useReferentiallyStableCallback } from '../referentiallyStable'\nimport { useOnWindowResize } from './useOnWindowResize'\n\nfunction addClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (element.classList.contains(className)) {\n\t\telement.classList.remove(className)\n\t}\n}\n\nfunction removeClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (!element.classList.contains(className)) {\n\t\telement.classList.add(className)\n\t}\n}\n\n/**\n * Adds CSS class during resize event to element\n *\n * - Falls back to document.body when no element is specified\n * - Adds CSS class to element also on the initial load\n * - Uses element.classList directly\n *\n * @param className - CSS class to apply during the resize event\n * @param timeoutToRestore - Timeout in milliseconds to wait before finally removing the CSS class\n * @param element - Optional HTML element to apply CSS class to\n */\nexport function useAddClassNameDuringResize(\n\tclassName: string,\n\ttimeoutToRestore: number = 300,\n\telement?: HTMLElement,\n) {\n\tconst timeoutID = useRef<number>()\n\n\tconst addTemporaryClassName = useReferentiallyStableCallback(() => {\n\t\tclearTimeout(timeoutID.current)\n\t\tremoveClassName(className, element ?? document.body)\n\n\t\ttimeoutID.current = setTimeout(() => {\n\t\t\taddClassName(className, element ?? document.body)\n\t\t}, timeoutToRestore)\n\n\t\treturn () => {\n\t\t\tclearTimeout(timeoutID.current)\n\t\t}\n\t})\n\n\tuseLayoutEffect(addTemporaryClassName, [addTemporaryClassName])\n\tuseOnWindowResize(addTemporaryClassName)\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,aACR,WACA,SACC;AACD,MAAI,QAAQ,UAAU,SAAS,SAAS,GAAG;AAClC,YAAA,UAAU,OAAO,SAAS;AAAA,EACnC;AACD;AAEA,SAAS,gBACR,WACA,SACC;AACD,MAAI,CAAC,QAAQ,UAAU,SAAS,SAAS,GAAG;AACnC,YAAA,UAAU,IAAI,SAAS;AAAA,EAChC;AACD;AAaO,SAAS,4BACf,WACA,mBAA2B,KAC3B,SACC;AACD,QAAM,YAAY;AAEZ,QAAA,wBAAwB,+BAA+B,MAAM;AAClE,iBAAa,UAAU,OAAO;AACd,oBAAA,WAAW,WAAW,SAAS,IAAI;AAEzC,cAAA,UAAU,WAAW,MAAM;AACvB,mBAAA,WAAW,WAAW,SAAS,IAAI;AAAA,OAC9C,gBAAgB;AAEnB,WAAO,MAAM;AACZ,mBAAa,UAAU,OAAO;AAAA,IAAA;AAAA,EAC/B,CACA;AAEe,kBAAA,uBAAuB,CAAC,qBAAqB,CAAC;AAC9D,oBAAkB,qBAAqB;AACxC;"}
@@ -3,7 +3,7 @@ import { useCallback, useLayoutEffect } from "react";
3
3
  import { unwrapRefValue } from "./unwrapRefValue.js";
4
4
  import { useOnElementResize } from "./useOnElementResize.js";
5
5
  const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => {
6
- const measure = useCallback((ref, minRows2, maxRows2, value2) => {
6
+ const measure = useCallback(async (ref, minRows2, maxRows2) => {
7
7
  if (ref) {
8
8
  const rowsAttribute = ref.rows;
9
9
  ref.style.height = "";
@@ -14,12 +14,12 @@ const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => {
14
14
  let minHeight;
15
15
  let maxHeight;
16
16
  ref.rows = minRows2;
17
- minHeight = ref.offsetHeight;
17
+ minHeight = await ref.getBoundingClientRect().height;
18
18
  if (maxRows2 === Infinity) {
19
19
  maxHeight = Infinity;
20
20
  } else {
21
21
  ref.rows = maxRows2;
22
- maxHeight = ref.offsetHeight;
22
+ maxHeight = await ref.getBoundingClientRect().height;
23
23
  }
24
24
  ref.style.height = px(height);
25
25
  ref.style.minHeight = px(minHeight);
@@ -29,10 +29,10 @@ const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => {
29
29
  }
30
30
  }, []);
31
31
  useOnElementResize(textAreaRef, () => {
32
- measure(unwrapRefValue(textAreaRef), minRows, maxRows, value);
32
+ measure(unwrapRefValue(textAreaRef), minRows, maxRows);
33
33
  });
34
34
  useLayoutEffect(() => {
35
- measure(unwrapRefValue(textAreaRef), minRows, maxRows, value);
35
+ measure(unwrapRefValue(textAreaRef), minRows, maxRows);
36
36
  }, [maxRows, measure, minRows, textAreaRef, value]);
37
37
  };
38
38
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"useAutoHeightTextArea.js","sources":["../../../src/hooks/useAutoHeightTextArea.ts"],"sourcesContent":["import { px } from '@contember/utilities'\nimport { useCallback, useLayoutEffect } from 'react'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnElementResize } from './useOnElementResize'\n\nexport const useAutoHeightTextArea = (\n\ttextAreaRef: RefObjectOrElement<HTMLTextAreaElement>,\n\tvalue: string,\n\tminRows: number,\n\tmaxRows: number,\n) => {\n\tconst measure = useCallback((ref: HTMLTextAreaElement | null, minRows: number, maxRows: number, value: string) => {\n\t\tif (ref) {\n\t\t\tconst rowsAttribute = ref.rows\n\n\t\t\tref.style.height = ''\n\t\t\tref.style.minHeight = ''\n\t\t\tref.style.maxHeight = ''\n\n\t\t\tif (minRows !== maxRows) {\n\t\t\t\tconst height = ref.scrollHeight\n\t\t\t\tlet minHeight: number\n\t\t\t\tlet maxHeight: number\n\n\t\t\t\tref.rows = minRows\n\t\t\t\tminHeight = ref.offsetHeight\n\n\t\t\t\tif (maxRows === Infinity) {\n\t\t\t\t\tmaxHeight = Infinity\n\t\t\t\t} else {\n\t\t\t\t\tref.rows = maxRows\n\t\t\t\t\tmaxHeight = ref.offsetHeight\n\t\t\t\t}\n\n\t\t\t\tref.style.height = px(height)\n\t\t\t\tref.style.minHeight = px(minHeight)\n\t\t\t\tref.style.maxHeight = px(maxHeight)\n\t\t\t}\n\n\t\t\tref.rows = rowsAttribute\n\t\t}\n\t}, [])\n\n\tuseOnElementResize(textAreaRef, () => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows, value)\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows, value)\n\t}, [maxRows, measure, minRows, textAreaRef, value])\n}\n"],"names":["minRows","maxRows","value"],"mappings":";;;;AAKO,MAAM,wBAAwB,CACpC,aACA,OACA,SACA,YACI;AACJ,QAAM,UAAU,YAAY,CAAC,KAAiCA,UAAiBC,UAAiBC,WAAkB;AACjH,QAAI,KAAK;AACR,YAAM,gBAAgB,IAAI;AAE1B,UAAI,MAAM,SAAS;AACnB,UAAI,MAAM,YAAY;AACtB,UAAI,MAAM,YAAY;AAEtB,UAAIF,aAAYC,UAAS;AACxB,cAAM,SAAS,IAAI;AACf,YAAA;AACA,YAAA;AAEJ,YAAI,OAAOD;AACX,oBAAY,IAAI;AAEhB,YAAIC,aAAY,UAAU;AACb,sBAAA;AAAA,QAAA,OACN;AACN,cAAI,OAAOA;AACX,sBAAY,IAAI;AAAA,QACjB;AAEI,YAAA,MAAM,SAAS,GAAG,MAAM;AACxB,YAAA,MAAM,YAAY,GAAG,SAAS;AAC9B,YAAA,MAAM,YAAY,GAAG,SAAS;AAAA,MACnC;AAEA,UAAI,OAAO;AAAA,IACZ;AAAA,EACD,GAAG,CAAE,CAAA;AAEL,qBAAmB,aAAa,MAAM;AACrC,YAAQ,eAAe,WAAW,GAAG,SAAS,SAAS,KAAK;AAAA,EAAA,CAC5D;AAED,kBAAgB,MAAM;AACrB,YAAQ,eAAe,WAAW,GAAG,SAAS,SAAS,KAAK;AAAA,EAAA,GAC1D,CAAC,SAAS,SAAS,SAAS,aAAa,KAAK,CAAC;AACnD;"}
1
+ {"version":3,"file":"useAutoHeightTextArea.js","sources":["../../../src/hooks/useAutoHeightTextArea.ts"],"sourcesContent":["import { px } from '@contember/utilities'\nimport { useCallback, useLayoutEffect } from 'react'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnElementResize } from './useOnElementResize'\n\nexport const useAutoHeightTextArea = (\n\ttextAreaRef: RefObjectOrElement<HTMLTextAreaElement>,\n\tvalue: string,\n\tminRows: number,\n\tmaxRows: number,\n) => {\n\tconst measure = useCallback(async (ref: HTMLTextAreaElement | null, minRows: number, maxRows: number) => {\n\t\tif (ref) {\n\t\t\tconst rowsAttribute = ref.rows\n\n\t\t\tref.style.height = ''\n\t\t\tref.style.minHeight = ''\n\t\t\tref.style.maxHeight = ''\n\n\t\t\tif (minRows !== maxRows) {\n\t\t\t\tconst height = ref.scrollHeight\n\t\t\t\tlet minHeight: number\n\t\t\t\tlet maxHeight: number\n\n\t\t\t\tref.rows = minRows\n\t\t\t\tminHeight = await ref.getBoundingClientRect().height\n\n\t\t\t\tif (maxRows === Infinity) {\n\t\t\t\t\tmaxHeight = Infinity\n\t\t\t\t} else {\n\t\t\t\t\tref.rows = maxRows\n\t\t\t\t\tmaxHeight = await ref.getBoundingClientRect().height\n\t\t\t\t}\n\n\t\t\t\tref.style.height = px(height)\n\t\t\t\tref.style.minHeight = px(minHeight)\n\t\t\t\tref.style.maxHeight = px(maxHeight)\n\t\t\t}\n\n\t\t\tref.rows = rowsAttribute\n\t\t}\n\t}, [])\n\n\tuseOnElementResize(textAreaRef, () => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows)\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows)\n\t}, [maxRows, measure, minRows, textAreaRef, value])\n}\n"],"names":["minRows","maxRows"],"mappings":";;;;AAKO,MAAM,wBAAwB,CACpC,aACA,OACA,SACA,YACI;AACJ,QAAM,UAAU,YAAY,OAAO,KAAiCA,UAAiBC,aAAoB;AACxG,QAAI,KAAK;AACR,YAAM,gBAAgB,IAAI;AAE1B,UAAI,MAAM,SAAS;AACnB,UAAI,MAAM,YAAY;AACtB,UAAI,MAAM,YAAY;AAEtB,UAAID,aAAYC,UAAS;AACxB,cAAM,SAAS,IAAI;AACf,YAAA;AACA,YAAA;AAEJ,YAAI,OAAOD;AACC,oBAAA,MAAM,IAAI,sBAAA,EAAwB;AAE9C,YAAIC,aAAY,UAAU;AACb,sBAAA;AAAA,QAAA,OACN;AACN,cAAI,OAAOA;AACC,sBAAA,MAAM,IAAI,sBAAA,EAAwB;AAAA,QAC/C;AAEI,YAAA,MAAM,SAAS,GAAG,MAAM;AACxB,YAAA,MAAM,YAAY,GAAG,SAAS;AAC9B,YAAA,MAAM,YAAY,GAAG,SAAS;AAAA,MACnC;AAEA,UAAI,OAAO;AAAA,IACZ;AAAA,EACD,GAAG,CAAE,CAAA;AAEL,qBAAmB,aAAa,MAAM;AACrC,YAAQ,eAAe,WAAW,GAAG,SAAS,OAAO;AAAA,EAAA,CACrD;AAED,kBAAgB,MAAM;AACrB,YAAQ,eAAe,WAAW,GAAG,SAAS,OAAO;AAAA,EAAA,GACnD,CAAC,SAAS,SAAS,SAAS,aAAa,KAAK,CAAC;AACnD;"}
@@ -0,0 +1,53 @@
1
+ import { Children, useMemo } from "react";
2
+ const MULTIPLE_SPACES_REG_EXP = / +/g;
3
+ function normalize(text) {
4
+ return text.replace(MULTIPLE_SPACES_REG_EXP, " ").trim();
5
+ }
6
+ function getChildrenAsLabel(node) {
7
+ if (typeof node === "string" || typeof node === "number") {
8
+ return String(node);
9
+ } else if (node === null || node === void 0 || typeof node === "boolean") {
10
+ return void 0;
11
+ } else if (Array.isArray(node)) {
12
+ return normalize(node.map(getChildrenAsLabel).join(""));
13
+ } else {
14
+ let label = [];
15
+ Children.map(node, (child) => {
16
+ if (child === null || child === void 0 || typeof child === "boolean")
17
+ ;
18
+ else if (typeof child === "string") {
19
+ label.push(child);
20
+ } else if (typeof child === "number") {
21
+ label.push(child);
22
+ } else if (Array.isArray(child)) {
23
+ const childLabel = getChildrenAsLabel(child);
24
+ if (childLabel) {
25
+ label.push(childLabel);
26
+ }
27
+ } else {
28
+ if ("props" in child && "children" in child.props) {
29
+ const childLabel = getChildrenAsLabel(child.props.children);
30
+ if (childLabel) {
31
+ label.push(childLabel);
32
+ }
33
+ } else if ("children" in child) {
34
+ const childLabel = getChildrenAsLabel(child.children);
35
+ if (childLabel) {
36
+ label.push(childLabel);
37
+ }
38
+ } else {
39
+ console.warn("Unsupported child:", child);
40
+ }
41
+ }
42
+ });
43
+ return label.length > 0 ? label.join("") : void 0;
44
+ }
45
+ }
46
+ function useChildrenAsLabel(node) {
47
+ return useMemo(() => getChildrenAsLabel(node), [node]);
48
+ }
49
+ export {
50
+ getChildrenAsLabel,
51
+ useChildrenAsLabel
52
+ };
53
+ //# sourceMappingURL=useChildrenAsLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChildrenAsLabel.js","sources":["../../../src/hooks/useChildrenAsLabel.ts"],"sourcesContent":["import { Children, ReactNode, useMemo } from 'react'\n\nconst MULTIPLE_SPACES_REG_EXP = / +/g\n\nfunction normalize(text: string): string {\n\treturn text.replace(MULTIPLE_SPACES_REG_EXP, ' ').trim()\n}\n\n/**\n * Walks through the children and returns a string representation of the text content.\n *\n * @param node - The children to walk through.\n * @returns String representation of the text content or undefined if there is no text content.\n *\n */\nexport function getChildrenAsLabel(node: ReactNode): string | undefined {\n\tif (typeof node === 'string' || typeof node === 'number') {\n\t\treturn String(node)\n\t} else if (node === null || node === undefined || typeof node === 'boolean') {\n\t\treturn undefined\n\t} else if (Array.isArray(node)) {\n\t\treturn normalize(node.map(getChildrenAsLabel).join(''))\n\t} else {\n\t\tlet label: (string | number)[] = []\n\n\t\tChildren.map(node, child => {\n\t\t\tif (child === null || child === undefined || typeof child === 'boolean') {\n\t\t\t} else if (typeof child === 'string') {\n\t\t\t\tlabel.push(child)\n\t\t\t} else if (typeof child === 'number') {\n\t\t\t\tlabel.push(child)\n\t\t\t} else if (Array.isArray(child)) {\n\t\t\t\tconst childLabel = getChildrenAsLabel(child)\n\n\t\t\t\tif (childLabel) {\n\t\t\t\t\tlabel.push(childLabel)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// ReactElement | JSXElementConstructor | ReactPortal\n\t\t\t\tif ('props' in child && 'children' in child.props) {\n\t\t\t\t\tconst childLabel = getChildrenAsLabel(child.props.children)\n\n\t\t\t\t\tif (childLabel) {\n\t\t\t\t\t\tlabel.push(childLabel)\n\t\t\t\t\t}\n\t\t\t\t} else if ('children' in child) {\n\t\t\t\t\t// ReactPortal\n\t\t\t\t\tconst childLabel = getChildrenAsLabel(child.children)\n\n\t\t\t\t\tif (childLabel) {\n\t\t\t\t\t\tlabel.push(childLabel)\n\t\t\t\t\t}\n\t\t\t\t} else if (import.meta.env.DEV) {\n\t\t\t\t\tconsole.warn('Unsupported child:', child)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\treturn label.length > 0 ? label.join('') : undefined\n\t}\n}\n\n/**\n * Walks through the children and returns a string representation of the text content.\n *\n * @param node - The children to walk through.\n * @returns String representation of the text content or undefined if there is no text content.\n *\n */\nexport function useChildrenAsLabel(node: ReactNode): string | undefined {\n\treturn useMemo(() => getChildrenAsLabel(node), [node])\n}\n"],"names":[],"mappings":";AAEA,MAAM,0BAA0B;AAEhC,SAAS,UAAU,MAAsB;AACxC,SAAO,KAAK,QAAQ,yBAAyB,GAAG,EAAE,KAAK;AACxD;AASO,SAAS,mBAAmB,MAAqC;AACvE,MAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU;AACzD,WAAO,OAAO,IAAI;AAAA,EAAA,WACR,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,WAAW;AACrE,WAAA;AAAA,EACG,WAAA,MAAM,QAAQ,IAAI,GAAG;AAC/B,WAAO,UAAU,KAAK,IAAI,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAAA,EAAA,OAChD;AACN,QAAI,QAA6B,CAAA;AAExB,aAAA,IAAI,MAAM,CAAS,UAAA;AAC3B,UAAI,UAAU,QAAQ,UAAU,UAAa,OAAO,UAAU;AAAW;AAAA,eAC9D,OAAO,UAAU,UAAU;AACrC,cAAM,KAAK,KAAK;AAAA,MAAA,WACN,OAAO,UAAU,UAAU;AACrC,cAAM,KAAK,KAAK;AAAA,MACN,WAAA,MAAM,QAAQ,KAAK,GAAG;AAC1B,cAAA,aAAa,mBAAmB,KAAK;AAE3C,YAAI,YAAY;AACf,gBAAM,KAAK,UAAU;AAAA,QACtB;AAAA,MAAA,OACM;AAEN,YAAI,WAAW,SAAS,cAAc,MAAM,OAAO;AAClD,gBAAM,aAAa,mBAAmB,MAAM,MAAM,QAAQ;AAE1D,cAAI,YAAY;AACf,kBAAM,KAAK,UAAU;AAAA,UACtB;AAAA,QAAA,WACU,cAAc,OAAO;AAEzB,gBAAA,aAAa,mBAAmB,MAAM,QAAQ;AAEpD,cAAI,YAAY;AACf,kBAAM,KAAK,UAAU;AAAA,UACtB;AAAA,QAAA,OAC+B;AACvB,kBAAA,KAAK,sBAAsB,KAAK;AAAA,QACzC;AAAA,MACD;AAAA,IAAA,CACA;AAED,WAAO,MAAM,SAAS,IAAI,MAAM,KAAK,EAAE,IAAI;AAAA,EAC5C;AACD;AASO,SAAS,mBAAmB,MAAqC;AACvE,SAAO,QAAQ,MAAM,mBAAmB,IAAI,GAAG,CAAC,IAAI,CAAC;AACtD;"}
@@ -1,43 +1,33 @@
1
- import { getSizeFromResizeObserverEntryFactory } from "@contember/utilities";
2
- import { useMemo, useState, useRef, useLayoutEffect } from "react";
1
+ import { getSizeFromResizeObserverEntryFactory, getElementDimensionsCallback } from "@contember/utilities";
2
+ import { useMemo, useState, useLayoutEffect } from "react";
3
3
  import { unwrapRefValue } from "./unwrapRefValue.js";
4
4
  import { useOnElementResize } from "./useOnElementResize.js";
5
5
  import { useScopedConsoleRef } from "../debug-context/Context.js";
6
- function getElementWidth(element) {
7
- return element.offsetWidth;
8
- }
9
- function getElementHeight(element) {
10
- return element.offsetHeight;
11
- }
6
+ import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js";
12
7
  function useElementSize(refOrElement, options = {}, timeout = 300) {
13
8
  const { logged } = useScopedConsoleRef("useElementSize").current;
14
9
  const { box = "border-box" } = options;
15
10
  const getSizeFromResizeObserverEntry = useMemo(() => getSizeFromResizeObserverEntryFactory(box), [box]);
16
- const refValue = unwrapRefValue(refOrElement);
17
- const [width, setWidth] = useState(refValue?.offsetWidth);
18
- const [height, setHeight] = useState(refValue?.offsetHeight);
11
+ const [width, setWidth] = useState();
12
+ const [height, setHeight] = useState();
19
13
  logged("dimensions", { width, height });
20
- useOnElementResize(refOrElement, (entry) => {
21
- const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry));
14
+ const maybeSetNewDimensions = useReferentiallyStableCallback((dimensions) => {
22
15
  if (width !== dimensions.width) {
23
16
  setWidth(dimensions.width);
24
17
  }
25
18
  if (height !== dimensions.height) {
26
19
  setHeight(dimensions.height);
27
20
  }
28
- }, { box }, timeout);
29
- const measure = useRef((element) => {
30
- logged("measure(element)", element);
31
- if (element instanceof HTMLElement) {
32
- setWidth(logged("getElementWidth(element):", getElementWidth(element)));
33
- setHeight(logged("getElementHeight(element):", getElementHeight(element)));
34
- } else if (element) {
35
- throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement or Window");
36
- }
37
21
  });
22
+ useOnElementResize(refOrElement, (entry) => {
23
+ const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry));
24
+ maybeSetNewDimensions(dimensions);
25
+ }, { box }, timeout);
38
26
  useLayoutEffect(() => {
39
27
  const element = unwrapRefValue(refOrElement);
40
- logged("useLayoutEffect => measure", measure.current(element));
28
+ if (element) {
29
+ getElementDimensionsCallback(element, (dimensions) => maybeSetNewDimensions(dimensions));
30
+ }
41
31
  });
42
32
  return { height, width };
43
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useElementSize.js","sources":["../../../src/hooks/useElementSize.ts"],"sourcesContent":["import { getSizeFromResizeObserverEntryFactory } from '@contember/utilities'\nimport { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { useScopedConsoleRef } from '../debug-context'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnElementResize } from './useOnElementResize'\n\nfunction getElementWidth(element: HTMLElement) {\n\treturn element.offsetWidth\n}\n\nfunction getElementHeight(element: HTMLElement) {\n\treturn element.offsetHeight\n}\n\n/**\n * Measure HTMLElement\n *\n * @param refOrElement - HTMLElement passed directly or indirectly as RefObject\n * @returns Size vector consisting of width and height properties\n */\nexport function useElementSize(\n\trefOrElement: RefObjectOrElement<HTMLElement>,\n\toptions: ResizeObserverOptions = {},\n\ttimeout: number = 300,\n): { height: number | undefined, width: number | undefined } {\n\tconst { logged } = useScopedConsoleRef('useElementSize').current\n\n\tconst { box = 'border-box' } = options\n\tconst getSizeFromResizeObserverEntry = useMemo(() => getSizeFromResizeObserverEntryFactory(box), [box])\n\n\tconst refValue = unwrapRefValue(refOrElement)\n\tconst [width, setWidth] = useState<number | undefined>(refValue?.offsetWidth)\n\tconst [height, setHeight] = useState<number | undefined>(refValue?.offsetHeight)\n\n\tlogged('dimensions', { width, height })\n\n\tuseOnElementResize(refOrElement, entry => {\n\t\tconst dimensions = logged('useOnElementResize => entry:dimensions', getSizeFromResizeObserverEntry(entry))\n\n\t\tif (width !== dimensions.width) {\n\t\t\tsetWidth(dimensions.width)\n\t\t}\n\t\tif (height !== dimensions.height) {\n\t\t\tsetHeight(dimensions.height)\n\t\t}\n\t}, { box }, timeout)\n\n\t// INTENTIONAL AVOID OF ESLint ERROR: We need measure on every Layout side-effect\n\t// otherwise the browser will paint and cause layout shifts.\n\t//\n\t// React Hook useLayoutEffect contains a call to 'setWidth'. Without a list of dependencies,\n\t// this can lead to an infinite chain of updates. To fix this, pass [element] as a second argument\n\t// to the useLayoutEffect Hook.\n\t//\n\t// Seems like only pure function lets us measure before the browser has a chance to paint\n\tconst measure = useRef((element: HTMLElement | null) => {\n\t\tlogged('measure(element)', element)\n\n\t\tif (element instanceof HTMLElement) {\n\t\t\tsetWidth(logged('getElementWidth(element):', getElementWidth(element)))\n\t\t\tsetHeight(logged('getElementHeight(element):', getElementHeight(element)))\n\t\t} else if (element) {\n\t\t\tthrow new Error('Exhaustive error: Expecting element to be instance of HTMLElement or Window')\n\t\t}\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tconst element = unwrapRefValue(refOrElement)\n\t\tlogged('useLayoutEffect => measure', measure.current(element))\n\t})\n\n\treturn { height, width }\n}\n"],"names":[],"mappings":";;;;;AAMA,SAAS,gBAAgB,SAAsB;AAC9C,SAAO,QAAQ;AAChB;AAEA,SAAS,iBAAiB,SAAsB;AAC/C,SAAO,QAAQ;AAChB;AAQO,SAAS,eACf,cACA,UAAiC,CAAA,GACjC,UAAkB,KAC0C;AAC5D,QAAM,EAAE,OAAW,IAAA,oBAAoB,gBAAgB,EAAE;AAEnD,QAAA,EAAE,MAAM,aAAiB,IAAA;AACzB,QAAA,iCAAiC,QAAQ,MAAM,sCAAsC,GAAG,GAAG,CAAC,GAAG,CAAC;AAEhG,QAAA,WAAW,eAAe,YAAY;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA6B,UAAU,WAAW;AAC5E,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA6B,UAAU,YAAY;AAE/E,SAAO,cAAc,EAAE,OAAO,OAAQ,CAAA;AAEtC,qBAAmB,cAAc,CAAS,UAAA;AACzC,UAAM,aAAa,OAAO,0CAA0C,+BAA+B,KAAK,CAAC;AAErG,QAAA,UAAU,WAAW,OAAO;AAC/B,eAAS,WAAW,KAAK;AAAA,IAC1B;AACI,QAAA,WAAW,WAAW,QAAQ;AACjC,gBAAU,WAAW,MAAM;AAAA,IAC5B;AAAA,EAAA,GACE,EAAE,OAAO,OAAO;AAUb,QAAA,UAAU,OAAO,CAAC,YAAgC;AACvD,WAAO,oBAAoB,OAAO;AAElC,QAAI,mBAAmB,aAAa;AACnC,eAAS,OAAO,6BAA6B,gBAAgB,OAAO,CAAC,CAAC;AACtE,gBAAU,OAAO,8BAA8B,iBAAiB,OAAO,CAAC,CAAC;AAAA,eAC/D,SAAS;AACb,YAAA,IAAI,MAAM,6EAA6E;AAAA,IAC9F;AAAA,EAAA,CACA;AAED,kBAAgB,MAAM;AACf,UAAA,UAAU,eAAe,YAAY;AAC3C,WAAO,8BAA8B,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAAA,CAC7D;AAEM,SAAA,EAAE,QAAQ;AAClB;"}
1
+ {"version":3,"file":"useElementSize.js","sources":["../../../src/hooks/useElementSize.ts"],"sourcesContent":["import { getElementDimensionsCallback, getSizeFromResizeObserverEntryFactory } from '@contember/utilities'\nimport { useLayoutEffect, useMemo, useState } from 'react'\nimport { useScopedConsoleRef } from '../debug-context'\nimport { useReferentiallyStableCallback } from '../referentiallyStable'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnElementResize } from './useOnElementResize'\n\nexport type ElementSize = {\n\theight: number\n\twidth: number\n}\n\n/**\n * Measure HTMLElement\n *\n * @param refOrElement - HTMLElement passed directly or indirectly as RefObject\n * @returns Size vector consisting of width and height properties\n */\nexport function useElementSize(\n\trefOrElement: RefObjectOrElement<HTMLElement>,\n\toptions: ResizeObserverOptions = {},\n\ttimeout: number = 300,\n): { height: number | undefined, width: number | undefined } {\n\tconst { logged } = useScopedConsoleRef('useElementSize').current\n\n\tconst { box = 'border-box' } = options\n\tconst getSizeFromResizeObserverEntry = useMemo(() => getSizeFromResizeObserverEntryFactory(box), [box])\n\n\tconst [width, setWidth] = useState<number | undefined>()\n\tconst [height, setHeight] = useState<number | undefined>()\n\n\tlogged('dimensions', { width, height })\n\n\tconst maybeSetNewDimensions = useReferentiallyStableCallback((dimensions: ElementSize) => {\n\t\tif (width !== dimensions.width) {\n\t\t\tsetWidth(dimensions.width)\n\t\t}\n\t\tif (height !== dimensions.height) {\n\t\t\tsetHeight(dimensions.height)\n\t\t}\n\t})\n\n\tuseOnElementResize(refOrElement, entry => {\n\t\tconst dimensions = logged('useOnElementResize => entry:dimensions', getSizeFromResizeObserverEntry(entry))\n\t\tmaybeSetNewDimensions(dimensions)\n\t}, { box }, timeout)\n\n\tuseLayoutEffect(() => {\n\t\tconst element = unwrapRefValue(refOrElement)\n\t\tif (element) {\n\t\t\tgetElementDimensionsCallback(element, dimensions => maybeSetNewDimensions(dimensions))\n\t\t}\n\t})\n\n\treturn { height, width }\n}\n"],"names":[],"mappings":";;;;;;AAkBO,SAAS,eACf,cACA,UAAiC,CAAA,GACjC,UAAkB,KAC0C;AAC5D,QAAM,EAAE,OAAW,IAAA,oBAAoB,gBAAgB,EAAE;AAEnD,QAAA,EAAE,MAAM,aAAiB,IAAA;AACzB,QAAA,iCAAiC,QAAQ,MAAM,sCAAsC,GAAG,GAAG,CAAC,GAAG,CAAC;AAEtG,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA6B;AACvD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA6B;AAEzD,SAAO,cAAc,EAAE,OAAO,OAAQ,CAAA;AAEhC,QAAA,wBAAwB,+BAA+B,CAAC,eAA4B;AACrF,QAAA,UAAU,WAAW,OAAO;AAC/B,eAAS,WAAW,KAAK;AAAA,IAC1B;AACI,QAAA,WAAW,WAAW,QAAQ;AACjC,gBAAU,WAAW,MAAM;AAAA,IAC5B;AAAA,EAAA,CACA;AAED,qBAAmB,cAAc,CAAS,UAAA;AACzC,UAAM,aAAa,OAAO,0CAA0C,+BAA+B,KAAK,CAAC;AACzG,0BAAsB,UAAU;AAAA,EAAA,GAC9B,EAAE,OAAO,OAAO;AAEnB,kBAAgB,MAAM;AACf,UAAA,UAAU,eAAe,YAAY;AAC3C,QAAI,SAAS;AACZ,mCAA6B,SAAS,CAAA,eAAc,sBAAsB,UAAU,CAAC;AAAA,IACtF;AAAA,EAAA,CACA;AAEM,SAAA,EAAE,QAAQ;AAClB;"}
@@ -9,35 +9,31 @@ function useOnElementResize(refOrElement, callback, options = {}, timeout = 300)
9
9
  const lastTimeStamp = useRef(0);
10
10
  useLayoutEffect(() => {
11
11
  const element = unwrapRefValue(refOrElement);
12
- if (element) {
13
- if (element instanceof HTMLElement) {
14
- let debouncedOnChange = function([entry]) {
15
- const timeStamp = Date.now();
16
- const delta = timeStamp - lastTimeStamp.current;
17
- if (delta > timeout) {
18
- scopedConsoleRef.current.warned("element.resize:immediate", null);
19
- callbackRef.current(entry);
20
- lastTimeStamp.current = timeStamp;
21
- } else {
22
- clearTimeout(timeoutID);
23
- timeoutID = setTimeout(() => {
24
- scopedConsoleRef.current.warned("element.resize:debounced", null);
25
- callbackRef.current(entry);
26
- lastTimeStamp.current = timeStamp;
27
- }, timeout);
28
- }
29
- };
30
- let timeoutID = void 0;
31
- const resizeObserver = new ResizeObserver(debouncedOnChange);
32
- resizeObserver.observe(element, { box });
33
- return () => {
34
- clearTimeout(timeoutID);
35
- resizeObserver.unobserve(element);
36
- };
37
- } else {
38
- throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement");
39
- }
12
+ if (!element) {
13
+ return;
40
14
  }
15
+ if (!(element instanceof HTMLElement)) {
16
+ throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement");
17
+ }
18
+ let timeoutID = void 0;
19
+ function debouncedOnChange([entry]) {
20
+ const timeStamp = Date.now();
21
+ const delta = timeStamp - lastTimeStamp.current;
22
+ clearTimeout(timeoutID);
23
+ const timeoutFinal = delta > timeout ? 0 : timeout;
24
+ timeoutID = setTimeout(() => {
25
+ const message = timeoutFinal > 0 ? "element.resize:debounced" : "element.resize:immediate";
26
+ scopedConsoleRef.current.warned(message, null);
27
+ callbackRef.current(entry);
28
+ lastTimeStamp.current = timeStamp;
29
+ }, timeoutFinal);
30
+ }
31
+ const resizeObserver = new ResizeObserver(debouncedOnChange);
32
+ resizeObserver.observe(element, { box });
33
+ return () => {
34
+ clearTimeout(timeoutID);
35
+ resizeObserver.unobserve(element);
36
+ };
41
37
  }, [box, refOrElement, scopedConsoleRef, timeout]);
42
38
  }
43
39
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"useOnElementResize.js","sources":["../../../src/hooks/useOnElementResize.ts"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react'\nimport { useScopedConsoleRef } from '../debug-context'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\n\nexport function useOnElementResize(\n\trefOrElement: RefObjectOrElement<HTMLElement | null> | null,\n\tcallback: (entries: ResizeObserverEntry) => void,\n\toptions: ResizeObserverOptions = {},\n\ttimeout: number = 300,\n): void {\n\tconst scopedConsoleRef = useScopedConsoleRef('useOnElementResize')\n\n\tconst { box = 'border-box' } = options\n\tconst callbackRef = useRef(callback); callbackRef.current = callback\n\tconst lastTimeStamp = useRef<number>(0)\n\n\tuseLayoutEffect(() => {\n\t\tconst element = unwrapRefValue(refOrElement)\n\n\t\tif (element) {\n\t\t\tif (element instanceof HTMLElement) {\n\t\t\t\tlet timeoutID: number | undefined = undefined\n\n\t\t\t\tfunction debouncedOnChange([entry]: ResizeObserverEntry[]) {\n\t\t\t\t\tconst timeStamp = Date.now()\n\t\t\t\t\tconst delta = timeStamp - lastTimeStamp.current\n\n\t\t\t\t\tif (delta > timeout) {\n\t\t\t\t\t\tscopedConsoleRef.current.warned('element.resize:immediate', null)\n\t\t\t\t\t\tcallbackRef.current(entry)\n\t\t\t\t\t\tlastTimeStamp.current = timeStamp\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclearTimeout(timeoutID)\n\t\t\t\t\t\ttimeoutID = setTimeout(() => {\n\t\t\t\t\t\t\tscopedConsoleRef.current.warned('element.resize:debounced', null)\n\t\t\t\t\t\t\tcallbackRef.current(entry)\n\t\t\t\t\t\t\tlastTimeStamp.current = timeStamp\n\t\t\t\t\t\t}, timeout)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst resizeObserver = new ResizeObserver(debouncedOnChange)\n\n\t\t\t\tresizeObserver.observe(element, { box })\n\n\t\t\t\treturn () => {\n\t\t\t\t\tclearTimeout(timeoutID)\n\t\t\t\t\tresizeObserver.unobserve(element)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error('Exhaustive error: Expecting element to be instance of HTMLElement')\n\t\t\t}\n\t\t}\n\t}, [box, refOrElement, scopedConsoleRef, timeout])\n}\n"],"names":[],"mappings":";;;AAIO,SAAS,mBACf,cACA,UACA,UAAiC,CAAC,GAClC,UAAkB,KACX;AACD,QAAA,mBAAmB,oBAAoB,oBAAoB;AAE3D,QAAA,EAAE,MAAM,aAAiB,IAAA;AACzB,QAAA,cAAc,OAAO,QAAQ;AAAG,cAAY,UAAU;AACtD,QAAA,gBAAgB,OAAe,CAAC;AAEtC,kBAAgB,MAAM;AACf,UAAA,UAAU,eAAe,YAAY;AAE3C,QAAI,SAAS;AACZ,UAAI,mBAAmB,aAAa;AAGnC,YAAS,oBAAT,SAA2B,CAAC,KAAK,GAA0B;AACpD,gBAAA,YAAY,KAAK;AACjB,gBAAA,QAAQ,YAAY,cAAc;AAExC,cAAI,QAAQ,SAAS;AACH,6BAAA,QAAQ,OAAO,4BAA4B,IAAI;AAChE,wBAAY,QAAQ,KAAK;AACzB,0BAAc,UAAU;AAAA,UAAA,OAClB;AACN,yBAAa,SAAS;AACtB,wBAAY,WAAW,MAAM;AACX,+BAAA,QAAQ,OAAO,4BAA4B,IAAI;AAChE,0BAAY,QAAQ,KAAK;AACzB,4BAAc,UAAU;AAAA,eACtB,OAAO;AAAA,UACX;AAAA,QAAA;AAjBD,YAAI,YAAgC;AAoB9B,cAAA,iBAAiB,IAAI,eAAe,iBAAiB;AAE3D,uBAAe,QAAQ,SAAS,EAAE,IAAK,CAAA;AAEvC,eAAO,MAAM;AACZ,uBAAa,SAAS;AACtB,yBAAe,UAAU,OAAO;AAAA,QAAA;AAAA,MACjC,OACM;AACA,cAAA,IAAI,MAAM,mEAAmE;AAAA,MACpF;AAAA,IACD;AAAA,KACE,CAAC,KAAK,cAAc,kBAAkB,OAAO,CAAC;AAClD;"}
1
+ {"version":3,"file":"useOnElementResize.js","sources":["../../../src/hooks/useOnElementResize.ts"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react'\nimport { useScopedConsoleRef } from '../debug-context'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\n\nexport function useOnElementResize(\n\trefOrElement: RefObjectOrElement<HTMLElement | null> | null,\n\tcallback: (entries: ResizeObserverEntry) => void,\n\toptions: ResizeObserverOptions = {},\n\ttimeout: number = 300,\n): void {\n\tconst scopedConsoleRef = useScopedConsoleRef('useOnElementResize')\n\n\tconst { box = 'border-box' } = options\n\tconst callbackRef = useRef(callback); callbackRef.current = callback\n\tconst lastTimeStamp = useRef<number>(0)\n\n\tuseLayoutEffect(() => {\n\t\tconst element = unwrapRefValue(refOrElement)\n\t\tif (!element) {\n\t\t\treturn\n\t\t}\n\t\tif (!(element instanceof HTMLElement)) {\n\t\t\tthrow new Error('Exhaustive error: Expecting element to be instance of HTMLElement')\n\t\t}\n\n\t\tlet timeoutID: number | undefined = undefined\n\n\t\tfunction debouncedOnChange([entry]: ResizeObserverEntry[]) {\n\t\t\tconst timeStamp = Date.now()\n\t\t\tconst delta = timeStamp - lastTimeStamp.current\n\n\t\t\tclearTimeout(timeoutID)\n\t\t\tconst timeoutFinal = delta > timeout ? 0 : timeout\n\n\t\t\ttimeoutID = setTimeout(() => {\n\t\t\t\tconst message = timeoutFinal > 0 ? 'element.resize:debounced' : 'element.resize:immediate'\n\t\t\t\tscopedConsoleRef.current.warned(message, null)\n\t\t\t\tcallbackRef.current(entry)\n\t\t\t\tlastTimeStamp.current = timeStamp\n\t\t\t}, timeoutFinal)\n\t\t}\n\n\t\tconst resizeObserver = new ResizeObserver(debouncedOnChange)\n\n\t\tresizeObserver.observe(element, { box })\n\n\t\treturn () => {\n\t\t\tclearTimeout(timeoutID)\n\t\t\tresizeObserver.unobserve(element)\n\t\t}\n\t}, [box, refOrElement, scopedConsoleRef, timeout])\n}\n"],"names":[],"mappings":";;;AAIO,SAAS,mBACf,cACA,UACA,UAAiC,CAAC,GAClC,UAAkB,KACX;AACD,QAAA,mBAAmB,oBAAoB,oBAAoB;AAE3D,QAAA,EAAE,MAAM,aAAiB,IAAA;AACzB,QAAA,cAAc,OAAO,QAAQ;AAAG,cAAY,UAAU;AACtD,QAAA,gBAAgB,OAAe,CAAC;AAEtC,kBAAgB,MAAM;AACf,UAAA,UAAU,eAAe,YAAY;AAC3C,QAAI,CAAC,SAAS;AACb;AAAA,IACD;AACI,QAAA,EAAE,mBAAmB,cAAc;AAChC,YAAA,IAAI,MAAM,mEAAmE;AAAA,IACpF;AAEA,QAAI,YAAgC;AAE3B,aAAA,kBAAkB,CAAC,KAAK,GAA0B;AACpD,YAAA,YAAY,KAAK;AACjB,YAAA,QAAQ,YAAY,cAAc;AAExC,mBAAa,SAAS;AAChB,YAAA,eAAe,QAAQ,UAAU,IAAI;AAE3C,kBAAY,WAAW,MAAM;AACtB,cAAA,UAAU,eAAe,IAAI,6BAA6B;AAC/C,yBAAA,QAAQ,OAAO,SAAS,IAAI;AAC7C,oBAAY,QAAQ,KAAK;AACzB,sBAAc,UAAU;AAAA,SACtB,YAAY;AAAA,IAChB;AAEM,UAAA,iBAAiB,IAAI,eAAe,iBAAiB;AAE3D,mBAAe,QAAQ,SAAS,EAAE,IAAK,CAAA;AAEvC,WAAO,MAAM;AACZ,mBAAa,SAAS;AACtB,qBAAe,UAAU,OAAO;AAAA,IAAA;AAAA,KAE/B,CAAC,KAAK,cAAc,kBAAkB,OAAO,CAAC;AAClD;"}
@@ -1,4 +1,4 @@
1
- import { assert } from "@contember/utilities";
1
+ import { getElementDimensions, assert } from "@contember/utilities";
2
2
  import { useState, useLayoutEffect, useMemo } from "react";
3
3
  import { unwrapRefValue } from "./unwrapRefValue.js";
4
4
  import { useOnScrollWithin } from "./useOnScrollWithin.js";
@@ -28,9 +28,7 @@ function useScrollOffsets(refOrElement, interval = 1e3 / 60) {
28
28
  const handler = useReferentiallyStableCallback(() => {
29
29
  const maybeScrollContent = unwrapRefValue(refOrElement) ?? document;
30
30
  if (maybeScrollContent) {
31
- updateScrollOffsetsState(
32
- getElementScrollOffsets(maybeScrollContent)
33
- );
31
+ getElementScrollOffsets(maybeScrollContent).then(updateScrollOffsetsState);
34
32
  }
35
33
  });
36
34
  useOnScrollWithin(refOrElement, handler, interval);
@@ -50,12 +48,13 @@ function getIntrinsicScrollContainer(element) {
50
48
  return element;
51
49
  }
52
50
  }
53
- function getElementScrollOffsets(element) {
51
+ async function getElementScrollOffsets(element) {
54
52
  const isIntrinsicScrolling = isIntrinsicScrollElement(element);
55
53
  const scrollContainer = getIntrinsicScrollContainer(element);
56
54
  const { scrollLeft, scrollTop, scrollHeight, scrollWidth } = scrollContainer;
57
- const height = isIntrinsicScrolling ? window.innerHeight : scrollContainer.offsetHeight;
58
- const width = isIntrinsicScrolling ? window.innerWidth : scrollContainer.offsetWidth;
55
+ const { height: scrollContainerHeight, width: scrollContainerWidth } = await getElementDimensions(scrollContainer);
56
+ const height = isIntrinsicScrolling ? window.innerHeight : scrollContainerHeight;
57
+ const width = isIntrinsicScrolling ? window.innerWidth : scrollContainerWidth;
59
58
  const left = Math.round(scrollLeft);
60
59
  const top = Math.round(scrollTop);
61
60
  const right = Math.round(scrollWidth - width - left);
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollOffsets.js","sources":["../../../src/hooks/useScrollOffsets.ts"],"sourcesContent":["import { assert } from '@contember/utilities'\nimport { useLayoutEffect, useMemo, useState } from 'react'\nimport { useScopedConsoleRef } from '../debug-context'\nimport { useReferentiallyStableCallback } from '../referentiallyStable'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnScrollWithin } from './useOnScrollWithin'\nimport { useOnWindowResize } from './useOnWindowResize'\n\nexport type Offsets = {\n\tbottom: number;\n\tleft: number;\n\tright: number;\n\ttop: number;\n}\n\nexport function useScrollOffsets(refOrElement: RefObjectOrElement<HTMLElement | null> | null, interval: number = 1000 / 60) {\n\tconst { logged } = useScopedConsoleRef('useScrollOffsets').current\n\n\tconst [top, setTop] = useState(0)\n\tconst [bottom, setBottom] = useState(0)\n\tconst [left, setLeft] = useState(0)\n\tconst [right, setRight] = useState(0)\n\n\tconst updateScrollOffsetsState = useReferentiallyStableCallback((offsets: Offsets) => {\n\t\tlogged('Update the offsets:', {\n\t\t\tprevious: { bottom, left, right, top },\n\t\t\tnext: offsets,\n\t\t})\n\n\t\tif (offsets.bottom !== bottom) setBottom(offsets.bottom)\n\t\tif (offsets.left !== left) setLeft(offsets.left)\n\t\tif (offsets.right !== right) setRight(offsets.right)\n\t\tif (offsets.top !== top) setTop(offsets.top)\n\t})\n\n\tconst handler = useReferentiallyStableCallback(() => {\n\t\tconst maybeScrollContent = unwrapRefValue(refOrElement) ?? document\n\n\t\tif (maybeScrollContent) {\n\t\t\tupdateScrollOffsetsState(\n\t\t\t\tgetElementScrollOffsets(maybeScrollContent),\n\t\t\t)\n\t\t}\n\t})\n\n\tuseOnScrollWithin(refOrElement, handler, interval)\n\tuseOnWindowResize(handler)\n\tuseLayoutEffect(handler, [handler])\n\n\treturn useMemo(() => ({ bottom, left, right, top }), [bottom, left, right, top])\n}\n\nfunction isIntrinsicScrollElement(element: unknown): element is Document {\n\treturn element instanceof HTMLBodyElement\n\t\t|| element instanceof HTMLHtmlElement\n\t\t|| element instanceof DocumentType\n\t\t|| element instanceof Document\n\t\t|| element instanceof HTMLDocument\n}\n\nfunction getIntrinsicScrollContainer(element: HTMLElement | Document): HTMLElement {\n\tconst html = document.body.parentElement\n\tassert('HTML element exists', html, (value): value is HTMLElement => value instanceof HTMLElement)\n\n\tif (isIntrinsicScrollElement(element)) {\n\t\treturn html\n\t} else {\n\t\treturn element\n\t}\n}\n\nfunction getElementScrollOffsets(element: HTMLElement | Document): Offsets {\n\tconst isIntrinsicScrolling = isIntrinsicScrollElement(element)\n\tconst scrollContainer = getIntrinsicScrollContainer(element)\n\n\tconst { scrollLeft, scrollTop, scrollHeight, scrollWidth } = scrollContainer\n\n\tconst height = isIntrinsicScrolling ? window.innerHeight : scrollContainer.offsetHeight\n\tconst width = isIntrinsicScrolling ? window.innerWidth : scrollContainer.offsetWidth\n\n\tconst left = Math.round(scrollLeft)\n\tconst top = Math.round(scrollTop)\n\n\tconst right = Math.round(scrollWidth - width - left)\n\tconst bottom = Math.round(scrollHeight - height - top)\n\n\treturn { bottom, left, right, top }\n}\n"],"names":[],"mappings":";;;;;;;AAeO,SAAS,iBAAiB,cAA6D,WAAmB,MAAO,IAAI;AAC3H,QAAM,EAAE,OAAW,IAAA,oBAAoB,kBAAkB,EAAE;AAE3D,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,CAAC;AAChC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,CAAC;AACtC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,CAAC;AAClC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC;AAE9B,QAAA,2BAA2B,+BAA+B,CAAC,YAAqB;AACrF,WAAO,uBAAuB;AAAA,MAC7B,UAAU,EAAE,QAAQ,MAAM,OAAO,IAAI;AAAA,MACrC,MAAM;AAAA,IAAA,CACN;AAED,QAAI,QAAQ,WAAW;AAAQ,gBAAU,QAAQ,MAAM;AACvD,QAAI,QAAQ,SAAS;AAAM,cAAQ,QAAQ,IAAI;AAC/C,QAAI,QAAQ,UAAU;AAAO,eAAS,QAAQ,KAAK;AACnD,QAAI,QAAQ,QAAQ;AAAK,aAAO,QAAQ,GAAG;AAAA,EAAA,CAC3C;AAEK,QAAA,UAAU,+BAA+B,MAAM;AAC9C,UAAA,qBAAqB,eAAe,YAAY,KAAK;AAE3D,QAAI,oBAAoB;AACvB;AAAA,QACC,wBAAwB,kBAAkB;AAAA,MAAA;AAAA,IAE5C;AAAA,EAAA,CACA;AAEiB,oBAAA,cAAc,SAAS,QAAQ;AACjD,oBAAkB,OAAO;AACT,kBAAA,SAAS,CAAC,OAAO,CAAC;AAElC,SAAO,QAAQ,OAAO,EAAE,QAAQ,MAAM,OAAO,QAAQ,CAAC,QAAQ,MAAM,OAAO,GAAG,CAAC;AAChF;AAEA,SAAS,yBAAyB,SAAuC;AACjE,SAAA,mBAAmB,mBACtB,mBAAmB,mBACnB,mBAAmB,gBACnB,mBAAmB,YACnB,mBAAmB;AACxB;AAEA,SAAS,4BAA4B,SAA8C;AAC5E,QAAA,OAAO,SAAS,KAAK;AAC3B,SAAO,uBAAuB,MAAM,CAAC,UAAgC,iBAAiB,WAAW;AAE7F,MAAA,yBAAyB,OAAO,GAAG;AAC/B,WAAA;AAAA,EAAA,OACD;AACC,WAAA;AAAA,EACR;AACD;AAEA,SAAS,wBAAwB,SAA0C;AACpE,QAAA,uBAAuB,yBAAyB,OAAO;AACvD,QAAA,kBAAkB,4BAA4B,OAAO;AAE3D,QAAM,EAAE,YAAY,WAAW,cAAc,gBAAgB;AAE7D,QAAM,SAAS,uBAAuB,OAAO,cAAc,gBAAgB;AAC3E,QAAM,QAAQ,uBAAuB,OAAO,aAAa,gBAAgB;AAEnE,QAAA,OAAO,KAAK,MAAM,UAAU;AAC5B,QAAA,MAAM,KAAK,MAAM,SAAS;AAEhC,QAAM,QAAQ,KAAK,MAAM,cAAc,QAAQ,IAAI;AACnD,QAAM,SAAS,KAAK,MAAM,eAAe,SAAS,GAAG;AAErD,SAAO,EAAE,QAAQ,MAAM,OAAO,IAAI;AACnC;"}
1
+ {"version":3,"file":"useScrollOffsets.js","sources":["../../../src/hooks/useScrollOffsets.ts"],"sourcesContent":["import { assert, getElementDimensions } from '@contember/utilities'\nimport { useLayoutEffect, useMemo, useState } from 'react'\nimport { useScopedConsoleRef } from '../debug-context'\nimport { useReferentiallyStableCallback } from '../referentiallyStable'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnScrollWithin } from './useOnScrollWithin'\nimport { useOnWindowResize } from './useOnWindowResize'\n\nexport type Offsets = {\n\tbottom: number;\n\tleft: number;\n\tright: number;\n\ttop: number;\n}\n\nexport function useScrollOffsets(refOrElement: RefObjectOrElement<HTMLElement | null> | null, interval: number = 1000 / 60) {\n\tconst { logged } = useScopedConsoleRef('useScrollOffsets').current\n\n\tconst [top, setTop] = useState(0)\n\tconst [bottom, setBottom] = useState(0)\n\tconst [left, setLeft] = useState(0)\n\tconst [right, setRight] = useState(0)\n\n\tconst updateScrollOffsetsState = useReferentiallyStableCallback((offsets: Offsets) => {\n\t\tlogged('Update the offsets:', {\n\t\t\tprevious: { bottom, left, right, top },\n\t\t\tnext: offsets,\n\t\t})\n\n\t\tif (offsets.bottom !== bottom) setBottom(offsets.bottom)\n\t\tif (offsets.left !== left) setLeft(offsets.left)\n\t\tif (offsets.right !== right) setRight(offsets.right)\n\t\tif (offsets.top !== top) setTop(offsets.top)\n\t})\n\n\tconst handler = useReferentiallyStableCallback(() => {\n\t\tconst maybeScrollContent = unwrapRefValue(refOrElement) ?? document\n\n\t\tif (maybeScrollContent) {\n\t\t\tgetElementScrollOffsets(maybeScrollContent).then(updateScrollOffsetsState)\n\t\t}\n\t})\n\n\tuseOnScrollWithin(refOrElement, handler, interval)\n\tuseOnWindowResize(handler)\n\tuseLayoutEffect(handler, [handler])\n\n\treturn useMemo(() => ({ bottom, left, right, top }), [bottom, left, right, top])\n}\n\nfunction isIntrinsicScrollElement(element: unknown): element is Document {\n\treturn element instanceof HTMLBodyElement\n\t\t|| element instanceof HTMLHtmlElement\n\t\t|| element instanceof DocumentType\n\t\t|| element instanceof Document\n\t\t|| element instanceof HTMLDocument\n}\n\nfunction getIntrinsicScrollContainer(element: HTMLElement | Document): HTMLElement {\n\tconst html = document.body.parentElement\n\tassert('HTML element exists', html, (value): value is HTMLElement => value instanceof HTMLElement)\n\n\tif (isIntrinsicScrollElement(element)) {\n\t\treturn html\n\t} else {\n\t\treturn element\n\t}\n}\n\nasync function getElementScrollOffsets(element: HTMLElement | Document): Promise<Offsets> {\n\tconst isIntrinsicScrolling = isIntrinsicScrollElement(element)\n\tconst scrollContainer = getIntrinsicScrollContainer(element)\n\n\tconst { scrollLeft, scrollTop, scrollHeight, scrollWidth } = scrollContainer\n\tconst { height: scrollContainerHeight, width: scrollContainerWidth } = await getElementDimensions(scrollContainer)\n\n\tconst height = isIntrinsicScrolling ? window.innerHeight : scrollContainerHeight\n\tconst width = isIntrinsicScrolling ? window.innerWidth : scrollContainerWidth\n\n\tconst left = Math.round(scrollLeft)\n\tconst top = Math.round(scrollTop)\n\n\tconst right = Math.round(scrollWidth - width - left)\n\tconst bottom = Math.round(scrollHeight - height - top)\n\n\treturn { bottom, left, right, top }\n}\n"],"names":[],"mappings":";;;;;;;AAeO,SAAS,iBAAiB,cAA6D,WAAmB,MAAO,IAAI;AAC3H,QAAM,EAAE,OAAW,IAAA,oBAAoB,kBAAkB,EAAE;AAE3D,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,CAAC;AAChC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,CAAC;AACtC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,CAAC;AAClC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC;AAE9B,QAAA,2BAA2B,+BAA+B,CAAC,YAAqB;AACrF,WAAO,uBAAuB;AAAA,MAC7B,UAAU,EAAE,QAAQ,MAAM,OAAO,IAAI;AAAA,MACrC,MAAM;AAAA,IAAA,CACN;AAED,QAAI,QAAQ,WAAW;AAAQ,gBAAU,QAAQ,MAAM;AACvD,QAAI,QAAQ,SAAS;AAAM,cAAQ,QAAQ,IAAI;AAC/C,QAAI,QAAQ,UAAU;AAAO,eAAS,QAAQ,KAAK;AACnD,QAAI,QAAQ,QAAQ;AAAK,aAAO,QAAQ,GAAG;AAAA,EAAA,CAC3C;AAEK,QAAA,UAAU,+BAA+B,MAAM;AAC9C,UAAA,qBAAqB,eAAe,YAAY,KAAK;AAE3D,QAAI,oBAAoB;AACC,8BAAA,kBAAkB,EAAE,KAAK,wBAAwB;AAAA,IAC1E;AAAA,EAAA,CACA;AAEiB,oBAAA,cAAc,SAAS,QAAQ;AACjD,oBAAkB,OAAO;AACT,kBAAA,SAAS,CAAC,OAAO,CAAC;AAElC,SAAO,QAAQ,OAAO,EAAE,QAAQ,MAAM,OAAO,QAAQ,CAAC,QAAQ,MAAM,OAAO,GAAG,CAAC;AAChF;AAEA,SAAS,yBAAyB,SAAuC;AACjE,SAAA,mBAAmB,mBACtB,mBAAmB,mBACnB,mBAAmB,gBACnB,mBAAmB,YACnB,mBAAmB;AACxB;AAEA,SAAS,4BAA4B,SAA8C;AAC5E,QAAA,OAAO,SAAS,KAAK;AAC3B,SAAO,uBAAuB,MAAM,CAAC,UAAgC,iBAAiB,WAAW;AAE7F,MAAA,yBAAyB,OAAO,GAAG;AAC/B,WAAA;AAAA,EAAA,OACD;AACC,WAAA;AAAA,EACR;AACD;AAEA,eAAe,wBAAwB,SAAmD;AACnF,QAAA,uBAAuB,yBAAyB,OAAO;AACvD,QAAA,kBAAkB,4BAA4B,OAAO;AAE3D,QAAM,EAAE,YAAY,WAAW,cAAc,gBAAgB;AACvD,QAAA,EAAE,QAAQ,uBAAuB,OAAO,yBAAyB,MAAM,qBAAqB,eAAe;AAE3G,QAAA,SAAS,uBAAuB,OAAO,cAAc;AACrD,QAAA,QAAQ,uBAAuB,OAAO,aAAa;AAEnD,QAAA,OAAO,KAAK,MAAM,UAAU;AAC5B,QAAA,MAAM,KAAK,MAAM,SAAS;AAEhC,QAAM,QAAQ,KAAK,MAAM,cAAc,QAAQ,IAAI;AACnD,QAAM,SAAS,KAAK,MAAM,eAAe,SAAS,GAAG;AAErD,SAAO,EAAE,QAAQ,MAAM,OAAO,IAAI;AACnC;"}
@@ -7,6 +7,7 @@ import { useAbortController } from "./hooks/useAbortController.js";
7
7
  import { useAddClassNameDuringResize } from "./hooks/useAddClassNameDuringResize.js";
8
8
  import { useArrayMapMemo } from "./hooks/useArrayMapMemo.js";
9
9
  import { useAutoHeightTextArea } from "./hooks/useAutoHeightTextArea.js";
10
+ import { getChildrenAsLabel, useChildrenAsLabel } from "./hooks/useChildrenAsLabel.js";
10
11
  import { useComposeRef } from "./hooks/useComposeRef.js";
11
12
  import { useConstantLengthInvariant } from "./hooks/useConstantLengthInvariant.js";
12
13
  import { useConstantValueInvariant } from "./hooks/useConstantValueInvariant.js";
@@ -59,6 +60,7 @@ export {
59
60
  createOptionalContextFactory,
60
61
  emptyArray,
61
62
  emptyObject,
63
+ getChildrenAsLabel,
62
64
  identityFunction,
63
65
  isNoopScopedConsole,
64
66
  noop,
@@ -72,6 +74,7 @@ export {
72
74
  useAddClassNameDuringResize,
73
75
  useArrayMapMemo,
74
76
  useAutoHeightTextArea,
77
+ useChildrenAsLabel,
75
78
  useClassName,
76
79
  useClassNameFactory,
77
80
  useColorScheme,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,19 +1,14 @@
1
1
  import { useRef, useLayoutEffect } from "react";
2
2
  import { useOnWindowResize } from "./useOnWindowResize.js";
3
3
  import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js";
4
- function intendedFlushOfCSSChangesToCauseImmediateReflow(element) {
5
- element.offsetHeight;
6
- }
7
4
  function addClassName(className, element) {
8
5
  if (element.classList.contains(className)) {
9
6
  element.classList.remove(className);
10
- intendedFlushOfCSSChangesToCauseImmediateReflow(element);
11
7
  }
12
8
  }
13
9
  function removeClassName(className, element) {
14
10
  if (!element.classList.contains(className)) {
15
11
  element.classList.add(className);
16
- intendedFlushOfCSSChangesToCauseImmediateReflow(element);
17
12
  }
18
13
  }
19
14
  function useAddClassNameDuringResize(className, timeoutToRestore = 300, element) {
@@ -1 +1 @@
1
- {"version":3,"file":"useAddClassNameDuringResize.js","sources":["../../../src/hooks/useAddClassNameDuringResize.ts"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react'\nimport { useReferentiallyStableCallback } from '../referentiallyStable'\nimport { useOnWindowResize } from './useOnWindowResize'\n\nfunction intendedFlushOfCSSChangesToCauseImmediateReflow(element: HTMLElement) {\n\telement.offsetHeight\n}\n\nfunction addClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (element.classList.contains(className)) {\n\t\telement.classList.remove(className)\n\t\tintendedFlushOfCSSChangesToCauseImmediateReflow(element)\n\t}\n}\n\nfunction removeClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (!element.classList.contains(className)) {\n\t\telement.classList.add(className)\n\t\tintendedFlushOfCSSChangesToCauseImmediateReflow(element)\n\t}\n}\n\n/**\n * Adds CSS class during resize event to element\n *\n * - Falls back to document.body when no element is specified\n * - Adds CSS class to element also on the initial load\n * - Uses element.classList directly\n *\n * @param className - CSS class to apply during the resize event\n * @param timeoutToRestore - Timeout in milliseconds to wait before finally removing the CSS class\n * @param element - Optional HTML element to apply CSS class to\n */\nexport function useAddClassNameDuringResize(\n\tclassName: string,\n\ttimeoutToRestore: number = 300,\n\telement?: HTMLElement,\n) {\n\tconst timeoutID = useRef<number>()\n\n\tconst addTemporaryClassName = useReferentiallyStableCallback(() => {\n\t\tclearTimeout(timeoutID.current)\n\t\tremoveClassName(className, element ?? document.body)\n\n\t\ttimeoutID.current = setTimeout(() => {\n\t\t\taddClassName(className, element ?? document.body)\n\t\t}, timeoutToRestore)\n\n\t\treturn () => {\n\t\t\tclearTimeout(timeoutID.current)\n\t\t}\n\t})\n\n\tuseLayoutEffect(addTemporaryClassName, [addTemporaryClassName])\n\tuseOnWindowResize(addTemporaryClassName)\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,gDAAgD,SAAsB;AACtE,UAAA;AACT;AAEA,SAAS,aACR,WACA,SACC;AACD,MAAI,QAAQ,UAAU,SAAS,SAAS,GAAG;AAClC,YAAA,UAAU,OAAO,SAAS;AAClC,oDAAgD,OAAO;AAAA,EACxD;AACD;AAEA,SAAS,gBACR,WACA,SACC;AACD,MAAI,CAAC,QAAQ,UAAU,SAAS,SAAS,GAAG;AACnC,YAAA,UAAU,IAAI,SAAS;AAC/B,oDAAgD,OAAO;AAAA,EACxD;AACD;AAaO,SAAS,4BACf,WACA,mBAA2B,KAC3B,SACC;AACD,QAAM,YAAY;AAEZ,QAAA,wBAAwB,+BAA+B,MAAM;AAClE,iBAAa,UAAU,OAAO;AACd,oBAAA,WAAW,WAAW,SAAS,IAAI;AAEzC,cAAA,UAAU,WAAW,MAAM;AACvB,mBAAA,WAAW,WAAW,SAAS,IAAI;AAAA,OAC9C,gBAAgB;AAEnB,WAAO,MAAM;AACZ,mBAAa,UAAU,OAAO;AAAA,IAAA;AAAA,EAC/B,CACA;AAEe,kBAAA,uBAAuB,CAAC,qBAAqB,CAAC;AAC9D,oBAAkB,qBAAqB;AACxC;"}
1
+ {"version":3,"file":"useAddClassNameDuringResize.js","sources":["../../../src/hooks/useAddClassNameDuringResize.ts"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react'\nimport { useReferentiallyStableCallback } from '../referentiallyStable'\nimport { useOnWindowResize } from './useOnWindowResize'\n\nfunction addClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (element.classList.contains(className)) {\n\t\telement.classList.remove(className)\n\t}\n}\n\nfunction removeClassName(\n\tclassName: string,\n\telement: HTMLElement,\n) {\n\tif (!element.classList.contains(className)) {\n\t\telement.classList.add(className)\n\t}\n}\n\n/**\n * Adds CSS class during resize event to element\n *\n * - Falls back to document.body when no element is specified\n * - Adds CSS class to element also on the initial load\n * - Uses element.classList directly\n *\n * @param className - CSS class to apply during the resize event\n * @param timeoutToRestore - Timeout in milliseconds to wait before finally removing the CSS class\n * @param element - Optional HTML element to apply CSS class to\n */\nexport function useAddClassNameDuringResize(\n\tclassName: string,\n\ttimeoutToRestore: number = 300,\n\telement?: HTMLElement,\n) {\n\tconst timeoutID = useRef<number>()\n\n\tconst addTemporaryClassName = useReferentiallyStableCallback(() => {\n\t\tclearTimeout(timeoutID.current)\n\t\tremoveClassName(className, element ?? document.body)\n\n\t\ttimeoutID.current = setTimeout(() => {\n\t\t\taddClassName(className, element ?? document.body)\n\t\t}, timeoutToRestore)\n\n\t\treturn () => {\n\t\t\tclearTimeout(timeoutID.current)\n\t\t}\n\t})\n\n\tuseLayoutEffect(addTemporaryClassName, [addTemporaryClassName])\n\tuseOnWindowResize(addTemporaryClassName)\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,aACR,WACA,SACC;AACD,MAAI,QAAQ,UAAU,SAAS,SAAS,GAAG;AAClC,YAAA,UAAU,OAAO,SAAS;AAAA,EACnC;AACD;AAEA,SAAS,gBACR,WACA,SACC;AACD,MAAI,CAAC,QAAQ,UAAU,SAAS,SAAS,GAAG;AACnC,YAAA,UAAU,IAAI,SAAS;AAAA,EAChC;AACD;AAaO,SAAS,4BACf,WACA,mBAA2B,KAC3B,SACC;AACD,QAAM,YAAY;AAEZ,QAAA,wBAAwB,+BAA+B,MAAM;AAClE,iBAAa,UAAU,OAAO;AACd,oBAAA,WAAW,WAAW,SAAS,IAAI;AAEzC,cAAA,UAAU,WAAW,MAAM;AACvB,mBAAA,WAAW,WAAW,SAAS,IAAI;AAAA,OAC9C,gBAAgB;AAEnB,WAAO,MAAM;AACZ,mBAAa,UAAU,OAAO;AAAA,IAAA;AAAA,EAC/B,CACA;AAEe,kBAAA,uBAAuB,CAAC,qBAAqB,CAAC;AAC9D,oBAAkB,qBAAqB;AACxC;"}
@@ -3,7 +3,7 @@ import { useCallback, useLayoutEffect } from "react";
3
3
  import { unwrapRefValue } from "./unwrapRefValue.js";
4
4
  import { useOnElementResize } from "./useOnElementResize.js";
5
5
  const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => {
6
- const measure = useCallback((ref, minRows2, maxRows2, value2) => {
6
+ const measure = useCallback(async (ref, minRows2, maxRows2) => {
7
7
  if (ref) {
8
8
  const rowsAttribute = ref.rows;
9
9
  ref.style.height = "";
@@ -14,12 +14,12 @@ const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => {
14
14
  let minHeight;
15
15
  let maxHeight;
16
16
  ref.rows = minRows2;
17
- minHeight = ref.offsetHeight;
17
+ minHeight = await ref.getBoundingClientRect().height;
18
18
  if (maxRows2 === Infinity) {
19
19
  maxHeight = Infinity;
20
20
  } else {
21
21
  ref.rows = maxRows2;
22
- maxHeight = ref.offsetHeight;
22
+ maxHeight = await ref.getBoundingClientRect().height;
23
23
  }
24
24
  ref.style.height = px(height);
25
25
  ref.style.minHeight = px(minHeight);
@@ -29,10 +29,10 @@ const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => {
29
29
  }
30
30
  }, []);
31
31
  useOnElementResize(textAreaRef, () => {
32
- measure(unwrapRefValue(textAreaRef), minRows, maxRows, value);
32
+ measure(unwrapRefValue(textAreaRef), minRows, maxRows);
33
33
  });
34
34
  useLayoutEffect(() => {
35
- measure(unwrapRefValue(textAreaRef), minRows, maxRows, value);
35
+ measure(unwrapRefValue(textAreaRef), minRows, maxRows);
36
36
  }, [maxRows, measure, minRows, textAreaRef, value]);
37
37
  };
38
38
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"useAutoHeightTextArea.js","sources":["../../../src/hooks/useAutoHeightTextArea.ts"],"sourcesContent":["import { px } from '@contember/utilities'\nimport { useCallback, useLayoutEffect } from 'react'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnElementResize } from './useOnElementResize'\n\nexport const useAutoHeightTextArea = (\n\ttextAreaRef: RefObjectOrElement<HTMLTextAreaElement>,\n\tvalue: string,\n\tminRows: number,\n\tmaxRows: number,\n) => {\n\tconst measure = useCallback((ref: HTMLTextAreaElement | null, minRows: number, maxRows: number, value: string) => {\n\t\tif (ref) {\n\t\t\tconst rowsAttribute = ref.rows\n\n\t\t\tref.style.height = ''\n\t\t\tref.style.minHeight = ''\n\t\t\tref.style.maxHeight = ''\n\n\t\t\tif (minRows !== maxRows) {\n\t\t\t\tconst height = ref.scrollHeight\n\t\t\t\tlet minHeight: number\n\t\t\t\tlet maxHeight: number\n\n\t\t\t\tref.rows = minRows\n\t\t\t\tminHeight = ref.offsetHeight\n\n\t\t\t\tif (maxRows === Infinity) {\n\t\t\t\t\tmaxHeight = Infinity\n\t\t\t\t} else {\n\t\t\t\t\tref.rows = maxRows\n\t\t\t\t\tmaxHeight = ref.offsetHeight\n\t\t\t\t}\n\n\t\t\t\tref.style.height = px(height)\n\t\t\t\tref.style.minHeight = px(minHeight)\n\t\t\t\tref.style.maxHeight = px(maxHeight)\n\t\t\t}\n\n\t\t\tref.rows = rowsAttribute\n\t\t}\n\t}, [])\n\n\tuseOnElementResize(textAreaRef, () => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows, value)\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows, value)\n\t}, [maxRows, measure, minRows, textAreaRef, value])\n}\n"],"names":["minRows","maxRows","value"],"mappings":";;;;AAKO,MAAM,wBAAwB,CACpC,aACA,OACA,SACA,YACI;AACJ,QAAM,UAAU,YAAY,CAAC,KAAiCA,UAAiBC,UAAiBC,WAAkB;AACjH,QAAI,KAAK;AACR,YAAM,gBAAgB,IAAI;AAE1B,UAAI,MAAM,SAAS;AACnB,UAAI,MAAM,YAAY;AACtB,UAAI,MAAM,YAAY;AAEtB,UAAIF,aAAYC,UAAS;AACxB,cAAM,SAAS,IAAI;AACf,YAAA;AACA,YAAA;AAEJ,YAAI,OAAOD;AACX,oBAAY,IAAI;AAEhB,YAAIC,aAAY,UAAU;AACb,sBAAA;AAAA,QAAA,OACN;AACN,cAAI,OAAOA;AACX,sBAAY,IAAI;AAAA,QACjB;AAEI,YAAA,MAAM,SAAS,GAAG,MAAM;AACxB,YAAA,MAAM,YAAY,GAAG,SAAS;AAC9B,YAAA,MAAM,YAAY,GAAG,SAAS;AAAA,MACnC;AAEA,UAAI,OAAO;AAAA,IACZ;AAAA,EACD,GAAG,CAAE,CAAA;AAEL,qBAAmB,aAAa,MAAM;AACrC,YAAQ,eAAe,WAAW,GAAG,SAAS,SAAS,KAAK;AAAA,EAAA,CAC5D;AAED,kBAAgB,MAAM;AACrB,YAAQ,eAAe,WAAW,GAAG,SAAS,SAAS,KAAK;AAAA,EAAA,GAC1D,CAAC,SAAS,SAAS,SAAS,aAAa,KAAK,CAAC;AACnD;"}
1
+ {"version":3,"file":"useAutoHeightTextArea.js","sources":["../../../src/hooks/useAutoHeightTextArea.ts"],"sourcesContent":["import { px } from '@contember/utilities'\nimport { useCallback, useLayoutEffect } from 'react'\nimport { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue'\nimport { useOnElementResize } from './useOnElementResize'\n\nexport const useAutoHeightTextArea = (\n\ttextAreaRef: RefObjectOrElement<HTMLTextAreaElement>,\n\tvalue: string,\n\tminRows: number,\n\tmaxRows: number,\n) => {\n\tconst measure = useCallback(async (ref: HTMLTextAreaElement | null, minRows: number, maxRows: number) => {\n\t\tif (ref) {\n\t\t\tconst rowsAttribute = ref.rows\n\n\t\t\tref.style.height = ''\n\t\t\tref.style.minHeight = ''\n\t\t\tref.style.maxHeight = ''\n\n\t\t\tif (minRows !== maxRows) {\n\t\t\t\tconst height = ref.scrollHeight\n\t\t\t\tlet minHeight: number\n\t\t\t\tlet maxHeight: number\n\n\t\t\t\tref.rows = minRows\n\t\t\t\tminHeight = await ref.getBoundingClientRect().height\n\n\t\t\t\tif (maxRows === Infinity) {\n\t\t\t\t\tmaxHeight = Infinity\n\t\t\t\t} else {\n\t\t\t\t\tref.rows = maxRows\n\t\t\t\t\tmaxHeight = await ref.getBoundingClientRect().height\n\t\t\t\t}\n\n\t\t\t\tref.style.height = px(height)\n\t\t\t\tref.style.minHeight = px(minHeight)\n\t\t\t\tref.style.maxHeight = px(maxHeight)\n\t\t\t}\n\n\t\t\tref.rows = rowsAttribute\n\t\t}\n\t}, [])\n\n\tuseOnElementResize(textAreaRef, () => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows)\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tmeasure(unwrapRefValue(textAreaRef), minRows, maxRows)\n\t}, [maxRows, measure, minRows, textAreaRef, value])\n}\n"],"names":["minRows","maxRows"],"mappings":";;;;AAKO,MAAM,wBAAwB,CACpC,aACA,OACA,SACA,YACI;AACJ,QAAM,UAAU,YAAY,OAAO,KAAiCA,UAAiBC,aAAoB;AACxG,QAAI,KAAK;AACR,YAAM,gBAAgB,IAAI;AAE1B,UAAI,MAAM,SAAS;AACnB,UAAI,MAAM,YAAY;AACtB,UAAI,MAAM,YAAY;AAEtB,UAAID,aAAYC,UAAS;AACxB,cAAM,SAAS,IAAI;AACf,YAAA;AACA,YAAA;AAEJ,YAAI,OAAOD;AACC,oBAAA,MAAM,IAAI,sBAAA,EAAwB;AAE9C,YAAIC,aAAY,UAAU;AACb,sBAAA;AAAA,QAAA,OACN;AACN,cAAI,OAAOA;AACC,sBAAA,MAAM,IAAI,sBAAA,EAAwB;AAAA,QAC/C;AAEI,YAAA,MAAM,SAAS,GAAG,MAAM;AACxB,YAAA,MAAM,YAAY,GAAG,SAAS;AAC9B,YAAA,MAAM,YAAY,GAAG,SAAS;AAAA,MACnC;AAEA,UAAI,OAAO;AAAA,IACZ;AAAA,EACD,GAAG,CAAE,CAAA;AAEL,qBAAmB,aAAa,MAAM;AACrC,YAAQ,eAAe,WAAW,GAAG,SAAS,OAAO;AAAA,EAAA,CACrD;AAED,kBAAgB,MAAM;AACrB,YAAQ,eAAe,WAAW,GAAG,SAAS,OAAO;AAAA,EAAA,GACnD,CAAC,SAAS,SAAS,SAAS,aAAa,KAAK,CAAC;AACnD;"}
@@ -0,0 +1,52 @@
1
+ import { Children, useMemo } from "react";
2
+ const MULTIPLE_SPACES_REG_EXP = / +/g;
3
+ function normalize(text) {
4
+ return text.replace(MULTIPLE_SPACES_REG_EXP, " ").trim();
5
+ }
6
+ function getChildrenAsLabel(node) {
7
+ if (typeof node === "string" || typeof node === "number") {
8
+ return String(node);
9
+ } else if (node === null || node === void 0 || typeof node === "boolean") {
10
+ return void 0;
11
+ } else if (Array.isArray(node)) {
12
+ return normalize(node.map(getChildrenAsLabel).join(""));
13
+ } else {
14
+ let label = [];
15
+ Children.map(node, (child) => {
16
+ if (child === null || child === void 0 || typeof child === "boolean")
17
+ ;
18
+ else if (typeof child === "string") {
19
+ label.push(child);
20
+ } else if (typeof child === "number") {
21
+ label.push(child);
22
+ } else if (Array.isArray(child)) {
23
+ const childLabel = getChildrenAsLabel(child);
24
+ if (childLabel) {
25
+ label.push(childLabel);
26
+ }
27
+ } else {
28
+ if ("props" in child && "children" in child.props) {
29
+ const childLabel = getChildrenAsLabel(child.props.children);
30
+ if (childLabel) {
31
+ label.push(childLabel);
32
+ }
33
+ } else if ("children" in child) {
34
+ const childLabel = getChildrenAsLabel(child.children);
35
+ if (childLabel) {
36
+ label.push(childLabel);
37
+ }
38
+ } else
39
+ ;
40
+ }
41
+ });
42
+ return label.length > 0 ? label.join("") : void 0;
43
+ }
44
+ }
45
+ function useChildrenAsLabel(node) {
46
+ return useMemo(() => getChildrenAsLabel(node), [node]);
47
+ }
48
+ export {
49
+ getChildrenAsLabel,
50
+ useChildrenAsLabel
51
+ };
52
+ //# sourceMappingURL=useChildrenAsLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChildrenAsLabel.js","sources":["../../../src/hooks/useChildrenAsLabel.ts"],"sourcesContent":["import { Children, ReactNode, useMemo } from 'react'\n\nconst MULTIPLE_SPACES_REG_EXP = / +/g\n\nfunction normalize(text: string): string {\n\treturn text.replace(MULTIPLE_SPACES_REG_EXP, ' ').trim()\n}\n\n/**\n * Walks through the children and returns a string representation of the text content.\n *\n * @param node - The children to walk through.\n * @returns String representation of the text content or undefined if there is no text content.\n *\n */\nexport function getChildrenAsLabel(node: ReactNode): string | undefined {\n\tif (typeof node === 'string' || typeof node === 'number') {\n\t\treturn String(node)\n\t} else if (node === null || node === undefined || typeof node === 'boolean') {\n\t\treturn undefined\n\t} else if (Array.isArray(node)) {\n\t\treturn normalize(node.map(getChildrenAsLabel).join(''))\n\t} else {\n\t\tlet label: (string | number)[] = []\n\n\t\tChildren.map(node, child => {\n\t\t\tif (child === null || child === undefined || typeof child === 'boolean') {\n\t\t\t} else if (typeof child === 'string') {\n\t\t\t\tlabel.push(child)\n\t\t\t} else if (typeof child === 'number') {\n\t\t\t\tlabel.push(child)\n\t\t\t} else if (Array.isArray(child)) {\n\t\t\t\tconst childLabel = getChildrenAsLabel(child)\n\n\t\t\t\tif (childLabel) {\n\t\t\t\t\tlabel.push(childLabel)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// ReactElement | JSXElementConstructor | ReactPortal\n\t\t\t\tif ('props' in child && 'children' in child.props) {\n\t\t\t\t\tconst childLabel = getChildrenAsLabel(child.props.children)\n\n\t\t\t\t\tif (childLabel) {\n\t\t\t\t\t\tlabel.push(childLabel)\n\t\t\t\t\t}\n\t\t\t\t} else if ('children' in child) {\n\t\t\t\t\t// ReactPortal\n\t\t\t\t\tconst childLabel = getChildrenAsLabel(child.children)\n\n\t\t\t\t\tif (childLabel) {\n\t\t\t\t\t\tlabel.push(childLabel)\n\t\t\t\t\t}\n\t\t\t\t} else if (import.meta.env.DEV) {\n\t\t\t\t\tconsole.warn('Unsupported child:', child)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\treturn label.length > 0 ? label.join('') : undefined\n\t}\n}\n\n/**\n * Walks through the children and returns a string representation of the text content.\n *\n * @param node - The children to walk through.\n * @returns String representation of the text content or undefined if there is no text content.\n *\n */\nexport function useChildrenAsLabel(node: ReactNode): string | undefined {\n\treturn useMemo(() => getChildrenAsLabel(node), [node])\n}\n"],"names":[],"mappings":";AAEA,MAAM,0BAA0B;AAEhC,SAAS,UAAU,MAAsB;AACxC,SAAO,KAAK,QAAQ,yBAAyB,GAAG,EAAE,KAAK;AACxD;AASO,SAAS,mBAAmB,MAAqC;AACvE,MAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU;AACzD,WAAO,OAAO,IAAI;AAAA,EAAA,WACR,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,WAAW;AACrE,WAAA;AAAA,EACG,WAAA,MAAM,QAAQ,IAAI,GAAG;AAC/B,WAAO,UAAU,KAAK,IAAI,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAAA,EAAA,OAChD;AACN,QAAI,QAA6B,CAAA;AAExB,aAAA,IAAI,MAAM,CAAS,UAAA;AAC3B,UAAI,UAAU,QAAQ,UAAU,UAAa,OAAO,UAAU;AAAW;AAAA,eAC9D,OAAO,UAAU,UAAU;AACrC,cAAM,KAAK,KAAK;AAAA,MAAA,WACN,OAAO,UAAU,UAAU;AACrC,cAAM,KAAK,KAAK;AAAA,MACN,WAAA,MAAM,QAAQ,KAAK,GAAG;AAC1B,cAAA,aAAa,mBAAmB,KAAK;AAE3C,YAAI,YAAY;AACf,gBAAM,KAAK,UAAU;AAAA,QACtB;AAAA,MAAA,OACM;AAEN,YAAI,WAAW,SAAS,cAAc,MAAM,OAAO;AAClD,gBAAM,aAAa,mBAAmB,MAAM,MAAM,QAAQ;AAE1D,cAAI,YAAY;AACf,kBAAM,KAAK,UAAU;AAAA,UACtB;AAAA,QAAA,WACU,cAAc,OAAO;AAEzB,gBAAA,aAAa,mBAAmB,MAAM,QAAQ;AAEpD,cAAI,YAAY;AACf,kBAAM,KAAK,UAAU;AAAA,UACtB;AAAA,QAAA;AACD;AAAA,MAGD;AAAA,IAAA,CACA;AAED,WAAO,MAAM,SAAS,IAAI,MAAM,KAAK,EAAE,IAAI;AAAA,EAC5C;AACD;AASO,SAAS,mBAAmB,MAAqC;AACvE,SAAO,QAAQ,MAAM,mBAAmB,IAAI,GAAG,CAAC,IAAI,CAAC;AACtD;"}
@@ -1,43 +1,33 @@
1
- import { getSizeFromResizeObserverEntryFactory } from "@contember/utilities";
2
- import { useMemo, useState, useRef, useLayoutEffect } from "react";
1
+ import { getSizeFromResizeObserverEntryFactory, getElementDimensionsCallback } from "@contember/utilities";
2
+ import { useMemo, useState, useLayoutEffect } from "react";
3
3
  import { unwrapRefValue } from "./unwrapRefValue.js";
4
4
  import { useOnElementResize } from "./useOnElementResize.js";
5
5
  import { useScopedConsoleRef } from "../debug-context/Context.js";
6
- function getElementWidth(element) {
7
- return element.offsetWidth;
8
- }
9
- function getElementHeight(element) {
10
- return element.offsetHeight;
11
- }
6
+ import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js";
12
7
  function useElementSize(refOrElement, options = {}, timeout = 300) {
13
8
  const { logged } = useScopedConsoleRef("useElementSize").current;
14
9
  const { box = "border-box" } = options;
15
10
  const getSizeFromResizeObserverEntry = useMemo(() => getSizeFromResizeObserverEntryFactory(box), [box]);
16
- const refValue = unwrapRefValue(refOrElement);
17
- const [width, setWidth] = useState(refValue?.offsetWidth);
18
- const [height, setHeight] = useState(refValue?.offsetHeight);
11
+ const [width, setWidth] = useState();
12
+ const [height, setHeight] = useState();
19
13
  logged("dimensions", { width, height });
20
- useOnElementResize(refOrElement, (entry) => {
21
- const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry));
14
+ const maybeSetNewDimensions = useReferentiallyStableCallback((dimensions) => {
22
15
  if (width !== dimensions.width) {
23
16
  setWidth(dimensions.width);
24
17
  }
25
18
  if (height !== dimensions.height) {
26
19
  setHeight(dimensions.height);
27
20
  }
28
- }, { box }, timeout);
29
- const measure = useRef((element) => {
30
- logged("measure(element)", element);
31
- if (element instanceof HTMLElement) {
32
- setWidth(logged("getElementWidth(element):", getElementWidth(element)));
33
- setHeight(logged("getElementHeight(element):", getElementHeight(element)));
34
- } else if (element) {
35
- throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement or Window");
36
- }
37
21
  });
22
+ useOnElementResize(refOrElement, (entry) => {
23
+ const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry));
24
+ maybeSetNewDimensions(dimensions);
25
+ }, { box }, timeout);
38
26
  useLayoutEffect(() => {
39
27
  const element = unwrapRefValue(refOrElement);
40
- logged("useLayoutEffect => measure", measure.current(element));
28
+ if (element) {
29
+ getElementDimensionsCallback(element, (dimensions) => maybeSetNewDimensions(dimensions));
30
+ }
41
31
  });
42
32
  return { height, width };
43
33
  }