@react-aria/utils 3.25.3 → 3.27.0

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 (78) hide show
  1. package/LICENSE +201 -0
  2. package/dist/animation.main.js +97 -0
  3. package/dist/animation.main.js.map +1 -0
  4. package/dist/animation.mjs +91 -0
  5. package/dist/animation.module.js +91 -0
  6. package/dist/animation.module.js.map +1 -0
  7. package/dist/constants.main.js +25 -0
  8. package/dist/constants.main.js.map +1 -0
  9. package/dist/constants.mjs +18 -0
  10. package/dist/constants.module.js +18 -0
  11. package/dist/constants.module.js.map +1 -0
  12. package/dist/focusWithoutScrolling.main.js +1 -1
  13. package/dist/focusWithoutScrolling.main.js.map +1 -1
  14. package/dist/focusWithoutScrolling.mjs +1 -1
  15. package/dist/focusWithoutScrolling.module.js +1 -1
  16. package/dist/focusWithoutScrolling.module.js.map +1 -1
  17. package/dist/import.mjs +9 -1
  18. package/dist/isScrollable.main.js +1 -0
  19. package/dist/isScrollable.main.js.map +1 -1
  20. package/dist/isScrollable.mjs +1 -0
  21. package/dist/isScrollable.module.js +1 -0
  22. package/dist/isScrollable.module.js.map +1 -1
  23. package/dist/keyboard.main.js +26 -0
  24. package/dist/keyboard.main.js.map +1 -0
  25. package/dist/keyboard.mjs +21 -0
  26. package/dist/keyboard.module.js +21 -0
  27. package/dist/keyboard.module.js.map +1 -0
  28. package/dist/main.js +15 -0
  29. package/dist/main.js.map +1 -1
  30. package/dist/mergeProps.main.js.map +1 -1
  31. package/dist/mergeProps.module.js.map +1 -1
  32. package/dist/module.js +9 -1
  33. package/dist/module.js.map +1 -1
  34. package/dist/openLink.main.js.map +1 -1
  35. package/dist/openLink.module.js.map +1 -1
  36. package/dist/scrollIntoView.main.js +15 -9
  37. package/dist/scrollIntoView.main.js.map +1 -1
  38. package/dist/scrollIntoView.mjs +15 -9
  39. package/dist/scrollIntoView.module.js +15 -9
  40. package/dist/scrollIntoView.module.js.map +1 -1
  41. package/dist/types.d.ts +35 -23
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/useDescription.main.js.map +1 -1
  44. package/dist/useDescription.module.js.map +1 -1
  45. package/dist/useFormReset.main.js.map +1 -1
  46. package/dist/useFormReset.module.js.map +1 -1
  47. package/dist/useGlobalListeners.main.js +1 -2
  48. package/dist/useGlobalListeners.main.js.map +1 -1
  49. package/dist/useGlobalListeners.mjs +1 -2
  50. package/dist/useGlobalListeners.module.js +1 -2
  51. package/dist/useGlobalListeners.module.js.map +1 -1
  52. package/dist/useLoadMore.main.js.map +1 -1
  53. package/dist/useLoadMore.module.js.map +1 -1
  54. package/dist/useUpdateLayoutEffect.main.js +40 -0
  55. package/dist/useUpdateLayoutEffect.main.js.map +1 -0
  56. package/dist/useUpdateLayoutEffect.mjs +35 -0
  57. package/dist/useUpdateLayoutEffect.module.js +35 -0
  58. package/dist/useUpdateLayoutEffect.module.js.map +1 -0
  59. package/dist/useViewportSize.main.js +0 -1
  60. package/dist/useViewportSize.main.js.map +1 -1
  61. package/dist/useViewportSize.mjs +0 -1
  62. package/dist/useViewportSize.module.js +0 -1
  63. package/dist/useViewportSize.module.js.map +1 -1
  64. package/package.json +9 -7
  65. package/src/animation.ts +103 -0
  66. package/src/constants.ts +16 -0
  67. package/src/focusWithoutScrolling.ts +1 -1
  68. package/src/index.ts +4 -0
  69. package/src/isScrollable.ts +4 -1
  70. package/src/keyboard.tsx +27 -0
  71. package/src/mergeProps.ts +1 -1
  72. package/src/openLink.tsx +1 -1
  73. package/src/scrollIntoView.ts +31 -15
  74. package/src/useFormReset.ts +1 -1
  75. package/src/useGlobalListeners.ts +2 -2
  76. package/src/useLoadMore.ts +1 -1
  77. package/src/useUpdateLayoutEffect.ts +37 -0
  78. package/src/useViewportSize.ts +0 -1
@@ -0,0 +1,35 @@
1
+ import {useLayoutEffect as $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c} from "./useLayoutEffect.module.js";
2
+ import {useRef as $azsE2$useRef} from "react";
3
+
4
+ /*
5
+ * Copyright 2024 Adobe. All rights reserved.
6
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License. You may obtain a copy
8
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software distributed under
11
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
12
+ * OF ANY KIND, either express or implied. See the License for the specific language
13
+ * governing permissions and limitations under the License.
14
+ */
15
+
16
+ function $ca9b37712f007381$export$72ef708ab07251f1(effect, dependencies) {
17
+ const isInitialMount = (0, $azsE2$useRef)(true);
18
+ const lastDeps = (0, $azsE2$useRef)(null);
19
+ (0, $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c)(()=>{
20
+ isInitialMount.current = true;
21
+ return ()=>{
22
+ isInitialMount.current = false;
23
+ };
24
+ }, []);
25
+ (0, $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c)(()=>{
26
+ if (isInitialMount.current) isInitialMount.current = false;
27
+ else if (!lastDeps.current || dependencies.some((dep, i)=>!Object.is(dep, lastDeps[i]))) effect();
28
+ lastDeps.current = dependencies;
29
+ // eslint-disable-next-line react-hooks/exhaustive-deps
30
+ }, dependencies);
31
+ }
32
+
33
+
34
+ export {$ca9b37712f007381$export$72ef708ab07251f1 as useUpdateLayoutEffect};
35
+ //# sourceMappingURL=useUpdateLayoutEffect.module.js.map
@@ -0,0 +1 @@
1
+ {"mappings":";;;AAAA;;;;;;;;;;CAUC;;AAMM,SAAS,0CAAsB,MAAsB,EAAE,YAAmB;IAC/E,MAAM,iBAAiB,CAAA,GAAA,aAAK,EAAE;IAC9B,MAAM,WAAW,CAAA,GAAA,aAAK,EAAgB;IAEtC,CAAA,GAAA,yCAAc,EAAE;QACd,eAAe,OAAO,GAAG;QACzB,OAAO;YACL,eAAe,OAAO,GAAG;QAC3B;IACF,GAAG,EAAE;IAEL,CAAA,GAAA,yCAAc,EAAE;QACd,IAAI,eAAe,OAAO,EACxB,eAAe,OAAO,GAAG;aACpB,IAAI,CAAC,SAAS,OAAO,IAAI,aAAa,IAAI,CAAC,CAAC,KAAK,IAAM,CAAC,OAAO,EAAE,CAAC,KAAK,QAAQ,CAAC,EAAE,IACvF;QAEF,SAAS,OAAO,GAAG;IACnB,uDAAuD;IACzD,GAAG;AACL","sources":["packages/@react-aria/utils/src/useUpdateLayoutEffect.ts"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {EffectCallback, useRef} from 'react';\nimport {useLayoutEffect} from './useLayoutEffect';\n\n// Like useLayoutEffect, but only called for updates after the initial render.\nexport function useUpdateLayoutEffect(effect: EffectCallback, dependencies: any[]) {\n const isInitialMount = useRef(true);\n const lastDeps = useRef<any[] | null>(null);\n\n useLayoutEffect(() => {\n isInitialMount.current = true;\n return () => {\n isInitialMount.current = false;\n };\n }, []);\n\n useLayoutEffect(() => {\n if (isInitialMount.current) {\n isInitialMount.current = false;\n } else if (!lastDeps.current || dependencies.some((dep, i) => !Object.is(dep, lastDeps[i]))) {\n effect();\n }\n lastDeps.current = dependencies;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, dependencies);\n}\n"],"names":[],"version":3,"file":"useUpdateLayoutEffect.module.js.map"}
@@ -19,7 +19,6 @@ $parcel$export(module.exports, "useViewportSize", () => $8b24bab62f5c65ad$export
19
19
  * governing permissions and limitations under the License.
20
20
  */
21
21
 
22
- // @ts-ignore
23
22
  let $8b24bab62f5c65ad$var$visualViewport = typeof document !== 'undefined' && window.visualViewport;
24
23
  function $8b24bab62f5c65ad$export$d699905dd57c73ca() {
25
24
  let isSSR = (0, $4gIVO$reactariassr.useIsSSR)();
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;AAAA;;;;;;;;;;CAUC;;AAUD,aAAa;AACb,IAAI,uCAAiB,OAAO,aAAa,eAAe,OAAO,cAAc;AAEtE,SAAS;IACd,IAAI,QAAQ,CAAA,GAAA,4BAAO;IACnB,IAAI,CAAC,MAAM,QAAQ,GAAG,CAAA,GAAA,qBAAO,EAAE,IAAM,QAAQ;YAAC,OAAO;YAAG,QAAQ;QAAC,IAAI;IAErE,CAAA,GAAA,sBAAQ,EAAE;QACR,wFAAwF;QACxF,IAAI,WAAW;YACb,QAAQ,CAAA;gBACN,IAAI,UAAU;gBACd,IAAI,QAAQ,KAAK,KAAK,KAAK,KAAK,IAAI,QAAQ,MAAM,KAAK,KAAK,MAAM,EAChE,OAAO;gBAET,OAAO;YACT;QACF;QAEA,IAAI,CAAC,sCACH,OAAO,gBAAgB,CAAC,UAAU;aAElC,qCAAe,gBAAgB,CAAC,UAAU;QAG5C,OAAO;YACL,IAAI,CAAC,sCACH,OAAO,mBAAmB,CAAC,UAAU;iBAErC,qCAAe,mBAAmB,CAAC,UAAU;QAEjD;IACF,GAAG,EAAE;IAEL,OAAO;AACT;AAEA,SAAS;IACP,OAAO;QACL,OAAO,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,KAAK,KAAK,OAAO,UAAU;QACrE,QAAQ,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,MAAM,KAAK,OAAO,WAAW;IAC1E;AACF","sources":["packages/@react-aria/utils/src/useViewportSize.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useEffect, useState} from 'react';\nimport {useIsSSR} from '@react-aria/ssr';\n\ninterface ViewportSize {\n width: number,\n height: number\n}\n\n// @ts-ignore\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\nexport function useViewportSize(): ViewportSize {\n let isSSR = useIsSSR();\n let [size, setSize] = useState(() => isSSR ? {width: 0, height: 0} : getViewportSize());\n\n useEffect(() => {\n // Use visualViewport api to track available height even on iOS virtual keyboard opening\n let onResize = () => {\n setSize(size => {\n let newSize = getViewportSize();\n if (newSize.width === size.width && newSize.height === size.height) {\n return size;\n }\n return newSize;\n });\n };\n\n if (!visualViewport) {\n window.addEventListener('resize', onResize);\n } else {\n visualViewport.addEventListener('resize', onResize);\n }\n\n return () => {\n if (!visualViewport) {\n window.removeEventListener('resize', onResize);\n } else {\n visualViewport.removeEventListener('resize', onResize);\n }\n };\n }, []);\n\n return size;\n}\n\nfunction getViewportSize(): ViewportSize {\n return {\n width: (visualViewport && visualViewport?.width) || window.innerWidth,\n height: (visualViewport && visualViewport?.height) || window.innerHeight\n };\n}\n"],"names":[],"version":3,"file":"useViewportSize.main.js.map"}
1
+ {"mappings":";;;;;;;;;AAAA;;;;;;;;;;CAUC;;AAUD,IAAI,uCAAiB,OAAO,aAAa,eAAe,OAAO,cAAc;AAEtE,SAAS;IACd,IAAI,QAAQ,CAAA,GAAA,4BAAO;IACnB,IAAI,CAAC,MAAM,QAAQ,GAAG,CAAA,GAAA,qBAAO,EAAE,IAAM,QAAQ;YAAC,OAAO;YAAG,QAAQ;QAAC,IAAI;IAErE,CAAA,GAAA,sBAAQ,EAAE;QACR,wFAAwF;QACxF,IAAI,WAAW;YACb,QAAQ,CAAA;gBACN,IAAI,UAAU;gBACd,IAAI,QAAQ,KAAK,KAAK,KAAK,KAAK,IAAI,QAAQ,MAAM,KAAK,KAAK,MAAM,EAChE,OAAO;gBAET,OAAO;YACT;QACF;QAEA,IAAI,CAAC,sCACH,OAAO,gBAAgB,CAAC,UAAU;aAElC,qCAAe,gBAAgB,CAAC,UAAU;QAG5C,OAAO;YACL,IAAI,CAAC,sCACH,OAAO,mBAAmB,CAAC,UAAU;iBAErC,qCAAe,mBAAmB,CAAC,UAAU;QAEjD;IACF,GAAG,EAAE;IAEL,OAAO;AACT;AAEA,SAAS;IACP,OAAO;QACL,OAAO,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,KAAK,KAAK,OAAO,UAAU;QACrE,QAAQ,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,MAAM,KAAK,OAAO,WAAW;IAC1E;AACF","sources":["packages/@react-aria/utils/src/useViewportSize.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useEffect, useState} from 'react';\nimport {useIsSSR} from '@react-aria/ssr';\n\ninterface ViewportSize {\n width: number,\n height: number\n}\n\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\nexport function useViewportSize(): ViewportSize {\n let isSSR = useIsSSR();\n let [size, setSize] = useState(() => isSSR ? {width: 0, height: 0} : getViewportSize());\n\n useEffect(() => {\n // Use visualViewport api to track available height even on iOS virtual keyboard opening\n let onResize = () => {\n setSize(size => {\n let newSize = getViewportSize();\n if (newSize.width === size.width && newSize.height === size.height) {\n return size;\n }\n return newSize;\n });\n };\n\n if (!visualViewport) {\n window.addEventListener('resize', onResize);\n } else {\n visualViewport.addEventListener('resize', onResize);\n }\n\n return () => {\n if (!visualViewport) {\n window.removeEventListener('resize', onResize);\n } else {\n visualViewport.removeEventListener('resize', onResize);\n }\n };\n }, []);\n\n return size;\n}\n\nfunction getViewportSize(): ViewportSize {\n return {\n width: (visualViewport && visualViewport?.width) || window.innerWidth,\n height: (visualViewport && visualViewport?.height) || window.innerHeight\n };\n}\n"],"names":[],"version":3,"file":"useViewportSize.main.js.map"}
@@ -13,7 +13,6 @@ import {useIsSSR as $fuDHA$useIsSSR} from "@react-aria/ssr";
13
13
  * governing permissions and limitations under the License.
14
14
  */
15
15
 
16
- // @ts-ignore
17
16
  let $5df64b3807dc15ee$var$visualViewport = typeof document !== 'undefined' && window.visualViewport;
18
17
  function $5df64b3807dc15ee$export$d699905dd57c73ca() {
19
18
  let isSSR = (0, $fuDHA$useIsSSR)();
@@ -13,7 +13,6 @@ import {useIsSSR as $fuDHA$useIsSSR} from "@react-aria/ssr";
13
13
  * governing permissions and limitations under the License.
14
14
  */
15
15
 
16
- // @ts-ignore
17
16
  let $5df64b3807dc15ee$var$visualViewport = typeof document !== 'undefined' && window.visualViewport;
18
17
  function $5df64b3807dc15ee$export$d699905dd57c73ca() {
19
18
  let isSSR = (0, $fuDHA$useIsSSR)();
@@ -1 +1 @@
1
- {"mappings":";;;AAAA;;;;;;;;;;CAUC;;AAUD,aAAa;AACb,IAAI,uCAAiB,OAAO,aAAa,eAAe,OAAO,cAAc;AAEtE,SAAS;IACd,IAAI,QAAQ,CAAA,GAAA,eAAO;IACnB,IAAI,CAAC,MAAM,QAAQ,GAAG,CAAA,GAAA,eAAO,EAAE,IAAM,QAAQ;YAAC,OAAO;YAAG,QAAQ;QAAC,IAAI;IAErE,CAAA,GAAA,gBAAQ,EAAE;QACR,wFAAwF;QACxF,IAAI,WAAW;YACb,QAAQ,CAAA;gBACN,IAAI,UAAU;gBACd,IAAI,QAAQ,KAAK,KAAK,KAAK,KAAK,IAAI,QAAQ,MAAM,KAAK,KAAK,MAAM,EAChE,OAAO;gBAET,OAAO;YACT;QACF;QAEA,IAAI,CAAC,sCACH,OAAO,gBAAgB,CAAC,UAAU;aAElC,qCAAe,gBAAgB,CAAC,UAAU;QAG5C,OAAO;YACL,IAAI,CAAC,sCACH,OAAO,mBAAmB,CAAC,UAAU;iBAErC,qCAAe,mBAAmB,CAAC,UAAU;QAEjD;IACF,GAAG,EAAE;IAEL,OAAO;AACT;AAEA,SAAS;IACP,OAAO;QACL,OAAO,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,KAAK,KAAK,OAAO,UAAU;QACrE,QAAQ,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,MAAM,KAAK,OAAO,WAAW;IAC1E;AACF","sources":["packages/@react-aria/utils/src/useViewportSize.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useEffect, useState} from 'react';\nimport {useIsSSR} from '@react-aria/ssr';\n\ninterface ViewportSize {\n width: number,\n height: number\n}\n\n// @ts-ignore\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\nexport function useViewportSize(): ViewportSize {\n let isSSR = useIsSSR();\n let [size, setSize] = useState(() => isSSR ? {width: 0, height: 0} : getViewportSize());\n\n useEffect(() => {\n // Use visualViewport api to track available height even on iOS virtual keyboard opening\n let onResize = () => {\n setSize(size => {\n let newSize = getViewportSize();\n if (newSize.width === size.width && newSize.height === size.height) {\n return size;\n }\n return newSize;\n });\n };\n\n if (!visualViewport) {\n window.addEventListener('resize', onResize);\n } else {\n visualViewport.addEventListener('resize', onResize);\n }\n\n return () => {\n if (!visualViewport) {\n window.removeEventListener('resize', onResize);\n } else {\n visualViewport.removeEventListener('resize', onResize);\n }\n };\n }, []);\n\n return size;\n}\n\nfunction getViewportSize(): ViewportSize {\n return {\n width: (visualViewport && visualViewport?.width) || window.innerWidth,\n height: (visualViewport && visualViewport?.height) || window.innerHeight\n };\n}\n"],"names":[],"version":3,"file":"useViewportSize.module.js.map"}
1
+ {"mappings":";;;AAAA;;;;;;;;;;CAUC;;AAUD,IAAI,uCAAiB,OAAO,aAAa,eAAe,OAAO,cAAc;AAEtE,SAAS;IACd,IAAI,QAAQ,CAAA,GAAA,eAAO;IACnB,IAAI,CAAC,MAAM,QAAQ,GAAG,CAAA,GAAA,eAAO,EAAE,IAAM,QAAQ;YAAC,OAAO;YAAG,QAAQ;QAAC,IAAI;IAErE,CAAA,GAAA,gBAAQ,EAAE;QACR,wFAAwF;QACxF,IAAI,WAAW;YACb,QAAQ,CAAA;gBACN,IAAI,UAAU;gBACd,IAAI,QAAQ,KAAK,KAAK,KAAK,KAAK,IAAI,QAAQ,MAAM,KAAK,KAAK,MAAM,EAChE,OAAO;gBAET,OAAO;YACT;QACF;QAEA,IAAI,CAAC,sCACH,OAAO,gBAAgB,CAAC,UAAU;aAElC,qCAAe,gBAAgB,CAAC,UAAU;QAG5C,OAAO;YACL,IAAI,CAAC,sCACH,OAAO,mBAAmB,CAAC,UAAU;iBAErC,qCAAe,mBAAmB,CAAC,UAAU;QAEjD;IACF,GAAG,EAAE;IAEL,OAAO;AACT;AAEA,SAAS;IACP,OAAO;QACL,OAAO,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,KAAK,KAAK,OAAO,UAAU;QACrE,QAAQ,AAAC,yCAAkB,iDAAA,2DAAA,qCAAgB,MAAM,KAAK,OAAO,WAAW;IAC1E;AACF","sources":["packages/@react-aria/utils/src/useViewportSize.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useEffect, useState} from 'react';\nimport {useIsSSR} from '@react-aria/ssr';\n\ninterface ViewportSize {\n width: number,\n height: number\n}\n\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\nexport function useViewportSize(): ViewportSize {\n let isSSR = useIsSSR();\n let [size, setSize] = useState(() => isSSR ? {width: 0, height: 0} : getViewportSize());\n\n useEffect(() => {\n // Use visualViewport api to track available height even on iOS virtual keyboard opening\n let onResize = () => {\n setSize(size => {\n let newSize = getViewportSize();\n if (newSize.width === size.width && newSize.height === size.height) {\n return size;\n }\n return newSize;\n });\n };\n\n if (!visualViewport) {\n window.addEventListener('resize', onResize);\n } else {\n visualViewport.addEventListener('resize', onResize);\n }\n\n return () => {\n if (!visualViewport) {\n window.removeEventListener('resize', onResize);\n } else {\n visualViewport.removeEventListener('resize', onResize);\n }\n };\n }, []);\n\n return size;\n}\n\nfunction getViewportSize(): ViewportSize {\n return {\n width: (visualViewport && visualViewport?.width) || window.innerWidth,\n height: (visualViewport && visualViewport?.height) || window.innerHeight\n };\n}\n"],"names":[],"version":3,"file":"useViewportSize.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-aria/utils",
3
- "version": "3.25.3",
3
+ "version": "3.27.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -22,16 +22,18 @@
22
22
  "url": "https://github.com/adobe/react-spectrum"
23
23
  },
24
24
  "dependencies": {
25
- "@react-aria/ssr": "^3.9.6",
26
- "@react-stately/utils": "^3.10.4",
27
- "@react-types/shared": "^3.25.0",
25
+ "@react-aria/ssr": "^3.9.7",
26
+ "@react-stately/utils": "^3.10.5",
27
+ "@react-types/shared": "^3.27.0",
28
28
  "@swc/helpers": "^0.5.0",
29
29
  "clsx": "^2.0.0"
30
30
  },
31
31
  "peerDependencies": {
32
- "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
32
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
33
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
33
34
  },
34
35
  "publishConfig": {
35
36
  "access": "public"
36
- }
37
- }
37
+ },
38
+ "gitHead": "09e7f44bebdc9d89122926b2b439a0a38a2814ea"
39
+ }
@@ -0,0 +1,103 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {flushSync} from 'react-dom';
14
+ import {RefObject, useCallback, useState} from 'react';
15
+ import {useLayoutEffect} from './useLayoutEffect';
16
+
17
+ export function useEnterAnimation(ref: RefObject<HTMLElement | null>, isReady: boolean = true) {
18
+ let [isEntering, setEntering] = useState(true);
19
+ let isAnimationReady = isEntering && isReady;
20
+
21
+ // There are two cases for entry animations:
22
+ // 1. CSS @keyframes. The `animation` property is set during the isEntering state, and it is removed after the animation finishes.
23
+ // 2. CSS transitions. The initial styles are applied during the isEntering state, and removed immediately, causing the transition to occur.
24
+ //
25
+ // In the second case, cancel any transitions that were triggered prior to the isEntering = false state (when the transition is supposed to start).
26
+ // This can happen when isReady starts as false (e.g. popovers prior to placement calculation).
27
+ useLayoutEffect(() => {
28
+ if (isAnimationReady && ref.current && 'getAnimations' in ref.current) {
29
+ for (let animation of ref.current.getAnimations()) {
30
+ if (animation instanceof CSSTransition) {
31
+ animation.cancel();
32
+ }
33
+ }
34
+ }
35
+ }, [ref, isAnimationReady]);
36
+
37
+ useAnimation(ref, isAnimationReady, useCallback(() => setEntering(false), []));
38
+ return isAnimationReady;
39
+ }
40
+
41
+ export function useExitAnimation(ref: RefObject<HTMLElement | null>, isOpen: boolean) {
42
+ let [exitState, setExitState] = useState<'closed' | 'open' | 'exiting'>(isOpen ? 'open' : 'closed');
43
+
44
+ switch (exitState) {
45
+ case 'open':
46
+ // If isOpen becomes false, set the state to exiting.
47
+ if (!isOpen) {
48
+ setExitState('exiting');
49
+ }
50
+ break;
51
+ case 'closed':
52
+ case 'exiting':
53
+ // If we are exiting and isOpen becomes true, the animation was interrupted.
54
+ // Reset the state to open.
55
+ if (isOpen) {
56
+ setExitState('open');
57
+ }
58
+ break;
59
+ }
60
+
61
+ let isExiting = exitState === 'exiting';
62
+ useAnimation(
63
+ ref,
64
+ isExiting,
65
+ useCallback(() => {
66
+ // Set the state to closed, which will cause the element to be unmounted.
67
+ setExitState(state => state === 'exiting' ? 'closed' : state);
68
+ }, [])
69
+ );
70
+
71
+ return isExiting;
72
+ }
73
+
74
+ function useAnimation(ref: RefObject<HTMLElement | null>, isActive: boolean, onEnd: () => void) {
75
+ useLayoutEffect(() => {
76
+ if (isActive && ref.current) {
77
+ if (!('getAnimations' in ref.current)) {
78
+ // JSDOM
79
+ onEnd();
80
+ return;
81
+ }
82
+
83
+ let animations = ref.current.getAnimations();
84
+ if (animations.length === 0) {
85
+ onEnd();
86
+ return;
87
+ }
88
+
89
+ let canceled = false;
90
+ Promise.all(animations.map(a => a.finished)).then(() => {
91
+ if (!canceled) {
92
+ flushSync(() => {
93
+ onEnd();
94
+ });
95
+ }
96
+ }).catch(() => {});
97
+
98
+ return () => {
99
+ canceled = true;
100
+ };
101
+ }
102
+ }, [ref, isActive, onEnd]);
103
+ }
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ // Custom event names for updating the autocomplete's aria-activedecendant.
14
+ export const CLEAR_FOCUS_EVENT = 'react-aria-clear-focus';
15
+ export const FOCUS_EVENT = 'react-aria-focus';
16
+ export const UPDATE_ACTIVEDESCENDANT = 'react-aria-update-activedescendant';
@@ -50,7 +50,7 @@ function supportsPreventScroll() {
50
50
  return true;
51
51
  }
52
52
  });
53
- } catch (e) {
53
+ } catch {
54
54
  // Ignore
55
55
  }
56
56
  }
package/src/index.ts CHANGED
@@ -24,6 +24,7 @@ export {useGlobalListeners} from './useGlobalListeners';
24
24
  export {useLabels} from './useLabels';
25
25
  export {useObjectRef} from './useObjectRef';
26
26
  export {useUpdateEffect} from './useUpdateEffect';
27
+ export {useUpdateLayoutEffect} from './useUpdateLayoutEffect';
27
28
  export {useLayoutEffect} from './useLayoutEffect';
28
29
  export {useResizeObserver} from './useResizeObserver';
29
30
  export {useSyncRef} from './useSyncRef';
@@ -42,3 +43,6 @@ export {useEffectEvent} from './useEffectEvent';
42
43
  export {useDeepMemo} from './useDeepMemo';
43
44
  export {useFormReset} from './useFormReset';
44
45
  export {useLoadMore} from './useLoadMore';
46
+ export {CLEAR_FOCUS_EVENT, FOCUS_EVENT, UPDATE_ACTIVEDESCENDANT} from './constants';
47
+ export {isCtrlKeyPressed} from './keyboard';
48
+ export {useEnterAnimation, useExitAnimation} from './animation';
@@ -10,7 +10,10 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- export function isScrollable(node: Element, checkForOverflow?: boolean): boolean {
13
+ export function isScrollable(node: Element | null, checkForOverflow?: boolean): boolean {
14
+ if (!node) {
15
+ return false;
16
+ }
14
17
  let style = window.getComputedStyle(node);
15
18
  let isScrollable = /(auto|scroll)/.test(style.overflow + style.overflowX + style.overflowY);
16
19
 
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {isMac} from './platform';
14
+
15
+ interface Event {
16
+ altKey: boolean,
17
+ ctrlKey: boolean,
18
+ metaKey: boolean
19
+ }
20
+
21
+ export function isCtrlKeyPressed(e: Event) {
22
+ if (isMac()) {
23
+ return e.metaKey;
24
+ }
25
+
26
+ return e.ctrlKey;
27
+ }
package/src/mergeProps.ts CHANGED
@@ -23,7 +23,7 @@ type PropsArg = Props | null | undefined;
23
23
  // taken from: https://stackoverflow.com/questions/51603250/typescript-3-parameter-list-intersection-type/51604379#51604379
24
24
  type TupleTypes<T> = { [P in keyof T]: T[P] } extends { [key: number]: infer V } ? NullToObject<V> : never;
25
25
  type NullToObject<T> = T extends (null | undefined) ? {} : T;
26
- // eslint-disable-next-line no-undef, @typescript-eslint/no-unused-vars
26
+
27
27
  type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
28
28
 
29
29
  /**
package/src/openLink.tsx CHANGED
@@ -171,7 +171,7 @@ export function getSyntheticLinkProps(props: LinkDOMProps) {
171
171
  };
172
172
  }
173
173
 
174
- export function useLinkProps(props: LinkDOMProps) {
174
+ export function useLinkProps(props?: LinkDOMProps) {
175
175
  let router = useRouter();
176
176
  const href = router.useHref(props?.href ?? '');
177
177
  return {
@@ -14,7 +14,7 @@ import {getScrollParents} from './getScrollParents';
14
14
 
15
15
  interface ScrollIntoViewportOpts {
16
16
  /** The optional containing element of the target to be centered in the viewport. */
17
- containingElement?: Element
17
+ containingElement?: Element | null
18
18
  }
19
19
 
20
20
  /**
@@ -30,24 +30,40 @@ export function scrollIntoView(scrollView: HTMLElement, element: HTMLElement) {
30
30
  let x = scrollView.scrollLeft;
31
31
  let y = scrollView.scrollTop;
32
32
 
33
- // Account for top/left border offsetting the scroll top/Left
34
- let {borderTopWidth, borderLeftWidth} = getComputedStyle(scrollView);
35
- let borderAdjustedX = scrollView.scrollLeft + parseInt(borderLeftWidth, 10);
36
- let borderAdjustedY = scrollView.scrollTop + parseInt(borderTopWidth, 10);
33
+ // Account for top/left border offsetting the scroll top/Left + scroll padding
34
+ let {
35
+ borderTopWidth,
36
+ borderLeftWidth,
37
+ scrollPaddingTop,
38
+ scrollPaddingRight,
39
+ scrollPaddingBottom,
40
+ scrollPaddingLeft
41
+ } = getComputedStyle(scrollView);
42
+
43
+ let borderAdjustedX = x + parseInt(borderLeftWidth, 10);
44
+ let borderAdjustedY = y + parseInt(borderTopWidth, 10);
37
45
  // Ignore end/bottom border via clientHeight/Width instead of offsetHeight/Width
38
46
  let maxX = borderAdjustedX + scrollView.clientWidth;
39
47
  let maxY = borderAdjustedY + scrollView.clientHeight;
40
48
 
41
- if (offsetX <= x) {
42
- x = offsetX - parseInt(borderLeftWidth, 10);
43
- } else if (offsetX + width > maxX) {
44
- x += offsetX + width - maxX;
49
+ // Get scroll padding values as pixels - defaults to 0 if no scroll padding
50
+ // is used.
51
+ let scrollPaddingTopNumber = parseInt(scrollPaddingTop, 10) || 0;
52
+ let scrollPaddingBottomNumber = parseInt(scrollPaddingBottom, 10) || 0;
53
+ let scrollPaddingRightNumber = parseInt(scrollPaddingRight, 10) || 0;
54
+ let scrollPaddingLeftNumber = parseInt(scrollPaddingLeft, 10) || 0;
55
+
56
+ if (offsetX <= x + scrollPaddingLeftNumber) {
57
+ x = offsetX - parseInt(borderLeftWidth, 10) - scrollPaddingLeftNumber;
58
+ } else if (offsetX + width > maxX - scrollPaddingRightNumber) {
59
+ x += offsetX + width - maxX + scrollPaddingRightNumber;
45
60
  }
46
- if (offsetY <= borderAdjustedY) {
47
- y = offsetY - parseInt(borderTopWidth, 10);
48
- } else if (offsetY + height > maxY) {
49
- y += offsetY + height - maxY;
61
+ if (offsetY <= borderAdjustedY + scrollPaddingTopNumber) {
62
+ y = offsetY - parseInt(borderTopWidth, 10) - scrollPaddingTopNumber;
63
+ } else if (offsetY + height > maxY - scrollPaddingBottomNumber) {
64
+ y += offsetY + height - maxY + scrollPaddingBottomNumber;
50
65
  }
66
+
51
67
  scrollView.scrollLeft = x;
52
68
  scrollView.scrollTop = y;
53
69
  }
@@ -81,8 +97,8 @@ function relativeOffset(ancestor: HTMLElement, child: HTMLElement, axis: 'left'|
81
97
  * that will be centered in the viewport prior to scrolling the targetElement into view. If scrolling is prevented on
82
98
  * the body (e.g. targetElement is in a popover), this will only scroll the scroll parents of the targetElement up to but not including the body itself.
83
99
  */
84
- export function scrollIntoViewport(targetElement: Element, opts?: ScrollIntoViewportOpts) {
85
- if (document.contains(targetElement)) {
100
+ export function scrollIntoViewport(targetElement: Element | null, opts?: ScrollIntoViewportOpts) {
101
+ if (targetElement && document.contains(targetElement)) {
86
102
  let root = document.scrollingElement || document.documentElement;
87
103
  let isScrollPrevented = window.getComputedStyle(root).overflow === 'hidden';
88
104
  // If scrolling is not currently prevented then we aren’t in a overlay nor is a overlay open, just use element.scrollIntoView to bring the element into view
@@ -15,7 +15,7 @@ import {useEffect, useRef} from 'react';
15
15
  import {useEffectEvent} from './useEffectEvent';
16
16
 
17
17
  export function useFormReset<T>(
18
- ref: RefObject<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null>,
18
+ ref: RefObject<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null> | undefined,
19
19
  initialValue: T,
20
20
  onReset: (value: T) => void
21
21
  ) {
@@ -29,7 +29,7 @@ export function useGlobalListeners(): GlobalListeners {
29
29
  listener(...args);
30
30
  } : listener;
31
31
  globalListeners.current.set(listener, {type, eventTarget, fn, options});
32
- eventTarget.addEventListener(type, listener, options);
32
+ eventTarget.addEventListener(type, fn, options);
33
33
  }, []);
34
34
  let removeGlobalListener = useCallback((eventTarget, type, listener, options) => {
35
35
  let fn = globalListeners.current.get(listener)?.fn || listener;
@@ -42,7 +42,7 @@ export function useGlobalListeners(): GlobalListeners {
42
42
  });
43
43
  }, [removeGlobalListener]);
44
44
 
45
- // eslint-disable-next-line arrow-body-style
45
+
46
46
  useEffect(() => {
47
47
  return removeAllGlobalListeners;
48
48
  }, [removeAllGlobalListeners]);
@@ -12,7 +12,7 @@
12
12
 
13
13
  import {RefObject, useCallback, useRef} from 'react';
14
14
  import {useEvent} from './useEvent';
15
- // eslint-disable-next-line rulesdir/useLayoutEffectRule
15
+
16
16
  import {useLayoutEffect} from './useLayoutEffect';
17
17
 
18
18
  export interface LoadMoreProps {
@@ -0,0 +1,37 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {EffectCallback, useRef} from 'react';
14
+ import {useLayoutEffect} from './useLayoutEffect';
15
+
16
+ // Like useLayoutEffect, but only called for updates after the initial render.
17
+ export function useUpdateLayoutEffect(effect: EffectCallback, dependencies: any[]) {
18
+ const isInitialMount = useRef(true);
19
+ const lastDeps = useRef<any[] | null>(null);
20
+
21
+ useLayoutEffect(() => {
22
+ isInitialMount.current = true;
23
+ return () => {
24
+ isInitialMount.current = false;
25
+ };
26
+ }, []);
27
+
28
+ useLayoutEffect(() => {
29
+ if (isInitialMount.current) {
30
+ isInitialMount.current = false;
31
+ } else if (!lastDeps.current || dependencies.some((dep, i) => !Object.is(dep, lastDeps[i]))) {
32
+ effect();
33
+ }
34
+ lastDeps.current = dependencies;
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ }, dependencies);
37
+ }
@@ -18,7 +18,6 @@ interface ViewportSize {
18
18
  height: number
19
19
  }
20
20
 
21
- // @ts-ignore
22
21
  let visualViewport = typeof document !== 'undefined' && window.visualViewport;
23
22
 
24
23
  export function useViewportSize(): ViewportSize {