eidos-ui 0.1.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.
- package/LICENSE +22 -0
- package/README.md +175 -0
- package/dist/Breadcrumb.types-DaykU-C8.d.cts +20 -0
- package/dist/Breadcrumb.types-DaykU-C8.d.ts +20 -0
- package/dist/Button.types-BH0CPyPx.d.ts +33 -0
- package/dist/Button.types-DZRCVqyN.d.cts +33 -0
- package/dist/CommandPalette.types-DRMMS_ev.d.cts +73 -0
- package/dist/CommandPalette.types-DRMMS_ev.d.ts +73 -0
- package/dist/Footer.types-Dv2TPN2J.d.cts +24 -0
- package/dist/Footer.types-Dv2TPN2J.d.ts +24 -0
- package/dist/Header.types-BZi80bWz.d.cts +17 -0
- package/dist/Header.types-DJt-q01P.d.ts +17 -0
- package/dist/Input.types-DFZNyJGF.d.cts +45 -0
- package/dist/Input.types-XrJTI0JC.d.ts +45 -0
- package/dist/Menu.types-DNIpjSAK.d.ts +49 -0
- package/dist/Menu.types-DwcuCZM7.d.cts +49 -0
- package/dist/Navigation.types-Ctu5mlTa.d.cts +94 -0
- package/dist/Navigation.types-DVcLJnrB.d.ts +94 -0
- package/dist/Table.types-Bv9l7qxd.d.ts +103 -0
- package/dist/Table.types-DQ0ReOLj.d.cts +103 -0
- package/dist/Toolbar.types-BGD57Uhm.d.ts +22 -0
- package/dist/Toolbar.types-tQkLmPIu.d.cts +22 -0
- package/dist/accordion/index.cjs +10 -0
- package/dist/accordion/index.cjs.map +1 -0
- package/dist/accordion/index.d.cts +39 -0
- package/dist/accordion/index.d.ts +39 -0
- package/dist/accordion/index.js +10 -0
- package/dist/accordion/index.js.map +1 -0
- package/dist/alert/index.cjs +12 -0
- package/dist/alert/index.cjs.map +1 -0
- package/dist/alert/index.d.cts +29 -0
- package/dist/alert/index.d.ts +29 -0
- package/dist/alert/index.js +12 -0
- package/dist/alert/index.js.map +1 -0
- package/dist/avatar/index.cjs +10 -0
- package/dist/avatar/index.cjs.map +1 -0
- package/dist/avatar/index.d.cts +26 -0
- package/dist/avatar/index.d.ts +26 -0
- package/dist/avatar/index.js +10 -0
- package/dist/avatar/index.js.map +1 -0
- package/dist/badge/index.cjs +8 -0
- package/dist/badge/index.cjs.map +1 -0
- package/dist/badge/index.d.cts +27 -0
- package/dist/badge/index.d.ts +27 -0
- package/dist/badge/index.js +8 -0
- package/dist/badge/index.js.map +1 -0
- package/dist/breadcrumb/index.cjs +8 -0
- package/dist/breadcrumb/index.cjs.map +1 -0
- package/dist/breadcrumb/index.d.cts +7 -0
- package/dist/breadcrumb/index.d.ts +7 -0
- package/dist/breadcrumb/index.js +8 -0
- package/dist/breadcrumb/index.js.map +1 -0
- package/dist/button/index.cjs +14 -0
- package/dist/button/index.cjs.map +1 -0
- package/dist/button/index.d.cts +21 -0
- package/dist/button/index.d.ts +21 -0
- package/dist/button/index.js +14 -0
- package/dist/button/index.js.map +1 -0
- package/dist/button-group/index.cjs +8 -0
- package/dist/button-group/index.cjs.map +1 -0
- package/dist/button-group/index.d.cts +46 -0
- package/dist/button-group/index.d.ts +46 -0
- package/dist/button-group/index.js +8 -0
- package/dist/button-group/index.js.map +1 -0
- package/dist/card/index.cjs +8 -0
- package/dist/card/index.cjs.map +1 -0
- package/dist/card/index.d.cts +18 -0
- package/dist/card/index.d.ts +18 -0
- package/dist/card/index.js +8 -0
- package/dist/card/index.js.map +1 -0
- package/dist/checkbox/index.cjs +9 -0
- package/dist/checkbox/index.cjs.map +1 -0
- package/dist/checkbox/index.d.cts +16 -0
- package/dist/checkbox/index.d.ts +16 -0
- package/dist/checkbox/index.js +9 -0
- package/dist/checkbox/index.js.map +1 -0
- package/dist/chip/index.cjs +11 -0
- package/dist/chip/index.cjs.map +1 -0
- package/dist/chip/index.d.cts +27 -0
- package/dist/chip/index.d.ts +27 -0
- package/dist/chip/index.js +11 -0
- package/dist/chip/index.js.map +1 -0
- package/dist/chunk-2HTBZGBP.cjs +113 -0
- package/dist/chunk-2HTBZGBP.cjs.map +1 -0
- package/dist/chunk-2JWY36LD.cjs +112 -0
- package/dist/chunk-2JWY36LD.cjs.map +1 -0
- package/dist/chunk-2YQE26EK.js +54 -0
- package/dist/chunk-2YQE26EK.js.map +1 -0
- package/dist/chunk-2ZWBN3LK.cjs +92 -0
- package/dist/chunk-2ZWBN3LK.cjs.map +1 -0
- package/dist/chunk-3ETWFS2N.cjs +40 -0
- package/dist/chunk-3ETWFS2N.cjs.map +1 -0
- package/dist/chunk-3KAR5KCS.cjs +47 -0
- package/dist/chunk-3KAR5KCS.cjs.map +1 -0
- package/dist/chunk-3RUIKBH4.cjs +1 -0
- package/dist/chunk-3RUIKBH4.cjs.map +1 -0
- package/dist/chunk-3SKI6FXB.js +40 -0
- package/dist/chunk-3SKI6FXB.js.map +1 -0
- package/dist/chunk-3YPTYI7R.js +194 -0
- package/dist/chunk-3YPTYI7R.js.map +1 -0
- package/dist/chunk-4NUZP66U.js +299 -0
- package/dist/chunk-4NUZP66U.js.map +1 -0
- package/dist/chunk-5D3LIJYW.cjs +299 -0
- package/dist/chunk-5D3LIJYW.cjs.map +1 -0
- package/dist/chunk-5QG2I3FK.cjs +169 -0
- package/dist/chunk-5QG2I3FK.cjs.map +1 -0
- package/dist/chunk-5TGBNYZK.cjs +11 -0
- package/dist/chunk-5TGBNYZK.cjs.map +1 -0
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/chunk-5WRI5ZAA.js.map +1 -0
- package/dist/chunk-63N2KZZX.cjs +54 -0
- package/dist/chunk-63N2KZZX.cjs.map +1 -0
- package/dist/chunk-66R54X6R.js +1 -0
- package/dist/chunk-66R54X6R.js.map +1 -0
- package/dist/chunk-6NZXWKUE.js +1 -0
- package/dist/chunk-6NZXWKUE.js.map +1 -0
- package/dist/chunk-6P4WYB3B.js +169 -0
- package/dist/chunk-6P4WYB3B.js.map +1 -0
- package/dist/chunk-6QFT3BUD.cjs +28 -0
- package/dist/chunk-6QFT3BUD.cjs.map +1 -0
- package/dist/chunk-6USUVU6J.js +26 -0
- package/dist/chunk-6USUVU6J.js.map +1 -0
- package/dist/chunk-73EKJU4G.js +11 -0
- package/dist/chunk-73EKJU4G.js.map +1 -0
- package/dist/chunk-7IOOFKG3.js +26 -0
- package/dist/chunk-7IOOFKG3.js.map +1 -0
- package/dist/chunk-7KGV6YCG.cjs +54 -0
- package/dist/chunk-7KGV6YCG.cjs.map +1 -0
- package/dist/chunk-7NZTRSMT.js +1484 -0
- package/dist/chunk-7NZTRSMT.js.map +1 -0
- package/dist/chunk-7R7IFWGB.cjs +86 -0
- package/dist/chunk-7R7IFWGB.cjs.map +1 -0
- package/dist/chunk-A35Y5MRJ.js +235 -0
- package/dist/chunk-A35Y5MRJ.js.map +1 -0
- package/dist/chunk-AOV32YBE.js +113 -0
- package/dist/chunk-AOV32YBE.js.map +1 -0
- package/dist/chunk-AUFCW7QU.cjs +526 -0
- package/dist/chunk-AUFCW7QU.cjs.map +1 -0
- package/dist/chunk-BFYSYUA6.cjs +125 -0
- package/dist/chunk-BFYSYUA6.cjs.map +1 -0
- package/dist/chunk-BTPCSBGP.js +1622 -0
- package/dist/chunk-BTPCSBGP.js.map +1 -0
- package/dist/chunk-C7F2VFAI.cjs +259 -0
- package/dist/chunk-C7F2VFAI.cjs.map +1 -0
- package/dist/chunk-CDV2OAS3.cjs +235 -0
- package/dist/chunk-CDV2OAS3.cjs.map +1 -0
- package/dist/chunk-CJUZDUXW.cjs +79 -0
- package/dist/chunk-CJUZDUXW.cjs.map +1 -0
- package/dist/chunk-CKH36D7H.js +28 -0
- package/dist/chunk-CKH36D7H.js.map +1 -0
- package/dist/chunk-D7PGZ3M3.cjs +117 -0
- package/dist/chunk-D7PGZ3M3.cjs.map +1 -0
- package/dist/chunk-DFADZZ3K.js +126 -0
- package/dist/chunk-DFADZZ3K.js.map +1 -0
- package/dist/chunk-DI2VKKLW.js +1 -0
- package/dist/chunk-DI2VKKLW.js.map +1 -0
- package/dist/chunk-DK4S3EHG.js +29 -0
- package/dist/chunk-DK4S3EHG.js.map +1 -0
- package/dist/chunk-DZUJEN5N.cjs +31 -0
- package/dist/chunk-DZUJEN5N.cjs.map +1 -0
- package/dist/chunk-E2B33QB7.js +97 -0
- package/dist/chunk-E2B33QB7.js.map +1 -0
- package/dist/chunk-E3XATJ63.js +4418 -0
- package/dist/chunk-E3XATJ63.js.map +1 -0
- package/dist/chunk-EACNRR3C.cjs +1 -0
- package/dist/chunk-EACNRR3C.cjs.map +1 -0
- package/dist/chunk-EQ6BNPTL.cjs +39 -0
- package/dist/chunk-EQ6BNPTL.cjs.map +1 -0
- package/dist/chunk-F54MVGKO.js +342 -0
- package/dist/chunk-F54MVGKO.js.map +1 -0
- package/dist/chunk-FNUOTM44.cjs +238 -0
- package/dist/chunk-FNUOTM44.cjs.map +1 -0
- package/dist/chunk-FO5FNTJX.js +69 -0
- package/dist/chunk-FO5FNTJX.js.map +1 -0
- package/dist/chunk-FQZ6F7FQ.cjs +1 -0
- package/dist/chunk-FQZ6F7FQ.cjs.map +1 -0
- package/dist/chunk-G2FANEA2.cjs +101 -0
- package/dist/chunk-G2FANEA2.cjs.map +1 -0
- package/dist/chunk-G36S5CWN.cjs +26 -0
- package/dist/chunk-G36S5CWN.cjs.map +1 -0
- package/dist/chunk-GI7WPGP2.cjs +454 -0
- package/dist/chunk-GI7WPGP2.cjs.map +1 -0
- package/dist/chunk-GL4DHGQE.js +1316 -0
- package/dist/chunk-GL4DHGQE.js.map +1 -0
- package/dist/chunk-GOVOQZYN.js +18 -0
- package/dist/chunk-GOVOQZYN.js.map +1 -0
- package/dist/chunk-GRH57M3E.js +88 -0
- package/dist/chunk-GRH57M3E.js.map +1 -0
- package/dist/chunk-H523JFY2.js +303 -0
- package/dist/chunk-H523JFY2.js.map +1 -0
- package/dist/chunk-H56YUMFB.cjs +1622 -0
- package/dist/chunk-H56YUMFB.cjs.map +1 -0
- package/dist/chunk-HO7P6IJO.js +238 -0
- package/dist/chunk-HO7P6IJO.js.map +1 -0
- package/dist/chunk-HPIBYEGE.cjs +1484 -0
- package/dist/chunk-HPIBYEGE.cjs.map +1 -0
- package/dist/chunk-HQ4KZRFH.js +67 -0
- package/dist/chunk-HQ4KZRFH.js.map +1 -0
- package/dist/chunk-HUNMRKGE.js +21 -0
- package/dist/chunk-HUNMRKGE.js.map +1 -0
- package/dist/chunk-I44YNYI6.cjs +1 -0
- package/dist/chunk-I44YNYI6.cjs.map +1 -0
- package/dist/chunk-I6UOIS4J.cjs +1 -0
- package/dist/chunk-I6UOIS4J.cjs.map +1 -0
- package/dist/chunk-ICJ3SV5I.cjs +183 -0
- package/dist/chunk-ICJ3SV5I.cjs.map +1 -0
- package/dist/chunk-IYQX7PBO.cjs +320 -0
- package/dist/chunk-IYQX7PBO.cjs.map +1 -0
- package/dist/chunk-JFA5ABVE.js +54 -0
- package/dist/chunk-JFA5ABVE.js.map +1 -0
- package/dist/chunk-JORQYNJD.js +79 -0
- package/dist/chunk-JORQYNJD.js.map +1 -0
- package/dist/chunk-K5TKNT6I.cjs +34 -0
- package/dist/chunk-K5TKNT6I.cjs.map +1 -0
- package/dist/chunk-KF64C4QI.js +138 -0
- package/dist/chunk-KF64C4QI.js.map +1 -0
- package/dist/chunk-KGXGTWUL.js +1 -0
- package/dist/chunk-KGXGTWUL.js.map +1 -0
- package/dist/chunk-KKOZX64Z.js +34 -0
- package/dist/chunk-KKOZX64Z.js.map +1 -0
- package/dist/chunk-KO2MKZDW.cjs +69 -0
- package/dist/chunk-KO2MKZDW.cjs.map +1 -0
- package/dist/chunk-KQKJVFYF.js +259 -0
- package/dist/chunk-KQKJVFYF.js.map +1 -0
- package/dist/chunk-KV2FG7AN.cjs +401 -0
- package/dist/chunk-KV2FG7AN.cjs.map +1 -0
- package/dist/chunk-L3UPSLJ5.cjs +4418 -0
- package/dist/chunk-L3UPSLJ5.cjs.map +1 -0
- package/dist/chunk-LEZ4HSBD.cjs +744 -0
- package/dist/chunk-LEZ4HSBD.cjs.map +1 -0
- package/dist/chunk-LQ3C3OR2.js +21 -0
- package/dist/chunk-LQ3C3OR2.js.map +1 -0
- package/dist/chunk-LTOHGCU4.cjs +69 -0
- package/dist/chunk-LTOHGCU4.cjs.map +1 -0
- package/dist/chunk-M56IGNH7.cjs +125 -0
- package/dist/chunk-M56IGNH7.cjs.map +1 -0
- package/dist/chunk-MOX6LYGC.js +125 -0
- package/dist/chunk-MOX6LYGC.js.map +1 -0
- package/dist/chunk-MSQXPGOD.cjs +125 -0
- package/dist/chunk-MSQXPGOD.cjs.map +1 -0
- package/dist/chunk-N5JDL4VE.js +1 -0
- package/dist/chunk-N5JDL4VE.js.map +1 -0
- package/dist/chunk-N7HX5635.cjs +138 -0
- package/dist/chunk-N7HX5635.cjs.map +1 -0
- package/dist/chunk-NDLMU6HJ.js +744 -0
- package/dist/chunk-NDLMU6HJ.js.map +1 -0
- package/dist/chunk-O5ZPSZNY.cjs +88 -0
- package/dist/chunk-O5ZPSZNY.cjs.map +1 -0
- package/dist/chunk-O6B4KB4D.js +125 -0
- package/dist/chunk-O6B4KB4D.js.map +1 -0
- package/dist/chunk-OHUVWPFJ.js +86 -0
- package/dist/chunk-OHUVWPFJ.js.map +1 -0
- package/dist/chunk-OT3VZLN4.js +117 -0
- package/dist/chunk-OT3VZLN4.js.map +1 -0
- package/dist/chunk-OVYIBDGE.js +183 -0
- package/dist/chunk-OVYIBDGE.js.map +1 -0
- package/dist/chunk-P2BTQ33C.cjs +126 -0
- package/dist/chunk-P2BTQ33C.cjs.map +1 -0
- package/dist/chunk-P6ZBENAG.js +211 -0
- package/dist/chunk-P6ZBENAG.js.map +1 -0
- package/dist/chunk-P74HNSNJ.cjs +106 -0
- package/dist/chunk-P74HNSNJ.cjs.map +1 -0
- package/dist/chunk-PEPYVWGY.cjs +327 -0
- package/dist/chunk-PEPYVWGY.cjs.map +1 -0
- package/dist/chunk-POX6JZLO.cjs +67 -0
- package/dist/chunk-POX6JZLO.cjs.map +1 -0
- package/dist/chunk-PWIA4XQD.js +320 -0
- package/dist/chunk-PWIA4XQD.js.map +1 -0
- package/dist/chunk-QGZF5MOS.cjs +342 -0
- package/dist/chunk-QGZF5MOS.cjs.map +1 -0
- package/dist/chunk-QP2A5ZMK.cjs +18 -0
- package/dist/chunk-QP2A5ZMK.cjs.map +1 -0
- package/dist/chunk-QYHTMEI5.js +92 -0
- package/dist/chunk-QYHTMEI5.js.map +1 -0
- package/dist/chunk-QYK4ECSZ.js +69 -0
- package/dist/chunk-QYK4ECSZ.js.map +1 -0
- package/dist/chunk-R36SGSJX.cjs +26 -0
- package/dist/chunk-R36SGSJX.cjs.map +1 -0
- package/dist/chunk-R5QPUQSI.cjs +303 -0
- package/dist/chunk-R5QPUQSI.cjs.map +1 -0
- package/dist/chunk-R5UNLPQZ.cjs +103 -0
- package/dist/chunk-R5UNLPQZ.cjs.map +1 -0
- package/dist/chunk-RSBQNIJZ.js +199 -0
- package/dist/chunk-RSBQNIJZ.js.map +1 -0
- package/dist/chunk-S25WB7KJ.js +50 -0
- package/dist/chunk-S25WB7KJ.js.map +1 -0
- package/dist/chunk-SAFSEXMU.cjs +211 -0
- package/dist/chunk-SAFSEXMU.cjs.map +1 -0
- package/dist/chunk-SJDTFR3I.cjs +1 -0
- package/dist/chunk-SJDTFR3I.cjs.map +1 -0
- package/dist/chunk-SOGUWOSQ.cjs +21 -0
- package/dist/chunk-SOGUWOSQ.cjs.map +1 -0
- package/dist/chunk-SWPZ3HFY.cjs +1 -0
- package/dist/chunk-SWPZ3HFY.cjs.map +1 -0
- package/dist/chunk-SXF3TCYA.js +401 -0
- package/dist/chunk-SXF3TCYA.js.map +1 -0
- package/dist/chunk-T56K5IKQ.js +526 -0
- package/dist/chunk-T56K5IKQ.js.map +1 -0
- package/dist/chunk-TBMVUI7S.cjs +21 -0
- package/dist/chunk-TBMVUI7S.cjs.map +1 -0
- package/dist/chunk-TCX3QKF3.js +103 -0
- package/dist/chunk-TCX3QKF3.js.map +1 -0
- package/dist/chunk-TH3ITGUM.js +1 -0
- package/dist/chunk-TH3ITGUM.js.map +1 -0
- package/dist/chunk-TPNCV7KA.js +1 -0
- package/dist/chunk-TPNCV7KA.js.map +1 -0
- package/dist/chunk-TQCNQKWF.cjs +194 -0
- package/dist/chunk-TQCNQKWF.cjs.map +1 -0
- package/dist/chunk-TZWNX7FF.js +1 -0
- package/dist/chunk-TZWNX7FF.js.map +1 -0
- package/dist/chunk-UEJSRMU2.js +39 -0
- package/dist/chunk-UEJSRMU2.js.map +1 -0
- package/dist/chunk-UTENJWSE.cjs +21 -0
- package/dist/chunk-UTENJWSE.cjs.map +1 -0
- package/dist/chunk-V5JNYS77.cjs +29 -0
- package/dist/chunk-V5JNYS77.cjs.map +1 -0
- package/dist/chunk-VFYG7GAH.js +327 -0
- package/dist/chunk-VFYG7GAH.js.map +1 -0
- package/dist/chunk-VGYJ4VKX.cjs +62 -0
- package/dist/chunk-VGYJ4VKX.cjs.map +1 -0
- package/dist/chunk-VLC2OZV3.cjs +50 -0
- package/dist/chunk-VLC2OZV3.cjs.map +1 -0
- package/dist/chunk-VTAABT55.js +47 -0
- package/dist/chunk-VTAABT55.js.map +1 -0
- package/dist/chunk-VW32UTUE.cjs +1 -0
- package/dist/chunk-VW32UTUE.cjs.map +1 -0
- package/dist/chunk-VYV45YOK.cjs +1316 -0
- package/dist/chunk-VYV45YOK.cjs.map +1 -0
- package/dist/chunk-VZ43OLU6.cjs +97 -0
- package/dist/chunk-VZ43OLU6.cjs.map +1 -0
- package/dist/chunk-XJAXKENE.cjs +1 -0
- package/dist/chunk-XJAXKENE.cjs.map +1 -0
- package/dist/chunk-XJBMEDQ5.js +101 -0
- package/dist/chunk-XJBMEDQ5.js.map +1 -0
- package/dist/chunk-XMRMCWSQ.js +454 -0
- package/dist/chunk-XMRMCWSQ.js.map +1 -0
- package/dist/chunk-XSGUFMT4.js +21 -0
- package/dist/chunk-XSGUFMT4.js.map +1 -0
- package/dist/chunk-XUZOU2EB.js +1 -0
- package/dist/chunk-XUZOU2EB.js.map +1 -0
- package/dist/chunk-YCUT6NQ4.js +106 -0
- package/dist/chunk-YCUT6NQ4.js.map +1 -0
- package/dist/chunk-YLKESEHQ.cjs +199 -0
- package/dist/chunk-YLKESEHQ.cjs.map +1 -0
- package/dist/chunk-YPK7RV3Y.js +62 -0
- package/dist/chunk-YPK7RV3Y.js.map +1 -0
- package/dist/chunk-Z7S4UQKY.js +125 -0
- package/dist/chunk-Z7S4UQKY.js.map +1 -0
- package/dist/chunk-ZBGTVTQJ.js +112 -0
- package/dist/chunk-ZBGTVTQJ.js.map +1 -0
- package/dist/color-picker/index.cjs +9 -0
- package/dist/color-picker/index.cjs.map +1 -0
- package/dist/color-picker/index.d.cts +40 -0
- package/dist/color-picker/index.d.ts +40 -0
- package/dist/color-picker/index.js +9 -0
- package/dist/color-picker/index.js.map +1 -0
- package/dist/combobox/index.cjs +12 -0
- package/dist/combobox/index.cjs.map +1 -0
- package/dist/combobox/index.d.cts +37 -0
- package/dist/combobox/index.d.ts +37 -0
- package/dist/combobox/index.js +12 -0
- package/dist/combobox/index.js.map +1 -0
- package/dist/command-palette/index.cjs +10 -0
- package/dist/command-palette/index.cjs.map +1 -0
- package/dist/command-palette/index.d.cts +7 -0
- package/dist/command-palette/index.d.ts +7 -0
- package/dist/command-palette/index.js +10 -0
- package/dist/command-palette/index.js.map +1 -0
- package/dist/context-menu/index.cjs +13 -0
- package/dist/context-menu/index.cjs.map +1 -0
- package/dist/context-menu/index.d.cts +38 -0
- package/dist/context-menu/index.d.ts +38 -0
- package/dist/context-menu/index.js +13 -0
- package/dist/context-menu/index.js.map +1 -0
- package/dist/data-grid/index.cjs +28 -0
- package/dist/data-grid/index.cjs.map +1 -0
- package/dist/data-grid/index.d.cts +217 -0
- package/dist/data-grid/index.d.ts +217 -0
- package/dist/data-grid/index.js +28 -0
- package/dist/data-grid/index.js.map +1 -0
- package/dist/date-picker/index.cjs +19 -0
- package/dist/date-picker/index.cjs.map +1 -0
- package/dist/date-picker/index.d.cts +106 -0
- package/dist/date-picker/index.d.ts +106 -0
- package/dist/date-picker/index.js +19 -0
- package/dist/date-picker/index.js.map +1 -0
- package/dist/divider/index.cjs +8 -0
- package/dist/divider/index.cjs.map +1 -0
- package/dist/divider/index.d.cts +9 -0
- package/dist/divider/index.d.ts +9 -0
- package/dist/divider/index.js +8 -0
- package/dist/divider/index.js.map +1 -0
- package/dist/drawer/index.cjs +13 -0
- package/dist/drawer/index.cjs.map +1 -0
- package/dist/drawer/index.d.cts +39 -0
- package/dist/drawer/index.d.ts +39 -0
- package/dist/drawer/index.js +13 -0
- package/dist/drawer/index.js.map +1 -0
- package/dist/dropdown/index.cjs +13 -0
- package/dist/dropdown/index.cjs.map +1 -0
- package/dist/dropdown/index.d.cts +66 -0
- package/dist/dropdown/index.d.ts +66 -0
- package/dist/dropdown/index.js +13 -0
- package/dist/dropdown/index.js.map +1 -0
- package/dist/empty-state/index.cjs +8 -0
- package/dist/empty-state/index.cjs.map +1 -0
- package/dist/empty-state/index.d.cts +20 -0
- package/dist/empty-state/index.d.ts +20 -0
- package/dist/empty-state/index.js +8 -0
- package/dist/empty-state/index.js.map +1 -0
- package/dist/file-upload/index.cjs +8 -0
- package/dist/file-upload/index.cjs.map +1 -0
- package/dist/file-upload/index.d.cts +27 -0
- package/dist/file-upload/index.d.ts +27 -0
- package/dist/file-upload/index.js +8 -0
- package/dist/file-upload/index.js.map +1 -0
- package/dist/footer/index.cjs +8 -0
- package/dist/footer/index.cjs.map +1 -0
- package/dist/footer/index.d.cts +7 -0
- package/dist/footer/index.d.ts +7 -0
- package/dist/footer/index.js +8 -0
- package/dist/footer/index.js.map +1 -0
- package/dist/header/index.cjs +13 -0
- package/dist/header/index.cjs.map +1 -0
- package/dist/header/index.d.cts +10 -0
- package/dist/header/index.d.ts +10 -0
- package/dist/header/index.js +13 -0
- package/dist/header/index.js.map +1 -0
- package/dist/index.cjs +269 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +8895 -0
- package/dist/index.css.d.ts +2 -0
- package/dist/index.d.cts +69 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +269 -0
- package/dist/index.js.map +1 -0
- package/dist/inline-edit/index.cjs +11 -0
- package/dist/inline-edit/index.cjs.map +1 -0
- package/dist/inline-edit/index.d.cts +56 -0
- package/dist/inline-edit/index.d.ts +56 -0
- package/dist/inline-edit/index.js +11 -0
- package/dist/inline-edit/index.js.map +1 -0
- package/dist/input/index.cjs +11 -0
- package/dist/input/index.cjs.map +1 -0
- package/dist/input/index.d.cts +9 -0
- package/dist/input/index.d.ts +9 -0
- package/dist/input/index.js +11 -0
- package/dist/input/index.js.map +1 -0
- package/dist/kbd/index.cjs +9 -0
- package/dist/kbd/index.cjs.map +1 -0
- package/dist/kbd/index.d.cts +34 -0
- package/dist/kbd/index.d.ts +34 -0
- package/dist/kbd/index.js +9 -0
- package/dist/kbd/index.js.map +1 -0
- package/dist/menu/index.cjs +14 -0
- package/dist/menu/index.cjs.map +1 -0
- package/dist/menu/index.d.cts +14 -0
- package/dist/menu/index.d.ts +14 -0
- package/dist/menu/index.js +14 -0
- package/dist/menu/index.js.map +1 -0
- package/dist/modal/index.cjs +12 -0
- package/dist/modal/index.cjs.map +1 -0
- package/dist/modal/index.d.cts +34 -0
- package/dist/modal/index.d.ts +34 -0
- package/dist/modal/index.js +12 -0
- package/dist/modal/index.js.map +1 -0
- package/dist/navigation/index.cjs +14 -0
- package/dist/navigation/index.cjs.map +1 -0
- package/dist/navigation/index.d.cts +8 -0
- package/dist/navigation/index.d.ts +8 -0
- package/dist/navigation/index.js +14 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/number-input/index.cjs +8 -0
- package/dist/number-input/index.cjs.map +1 -0
- package/dist/number-input/index.d.cts +31 -0
- package/dist/number-input/index.d.ts +31 -0
- package/dist/number-input/index.js +8 -0
- package/dist/number-input/index.js.map +1 -0
- package/dist/o-t-p-input/index.cjs +8 -0
- package/dist/o-t-p-input/index.cjs.map +1 -0
- package/dist/o-t-p-input/index.d.cts +33 -0
- package/dist/o-t-p-input/index.d.ts +33 -0
- package/dist/o-t-p-input/index.js +8 -0
- package/dist/o-t-p-input/index.js.map +1 -0
- package/dist/page-layout/index.cjs +24 -0
- package/dist/page-layout/index.cjs.map +1 -0
- package/dist/page-layout/index.d.cts +28 -0
- package/dist/page-layout/index.d.ts +28 -0
- package/dist/page-layout/index.js +24 -0
- package/dist/page-layout/index.js.map +1 -0
- package/dist/pagination/index.cjs +17 -0
- package/dist/pagination/index.cjs.map +1 -0
- package/dist/pagination/index.d.cts +34 -0
- package/dist/pagination/index.d.ts +34 -0
- package/dist/pagination/index.js +17 -0
- package/dist/pagination/index.js.map +1 -0
- package/dist/pill/index.cjs +8 -0
- package/dist/pill/index.cjs.map +1 -0
- package/dist/pill/index.d.cts +20 -0
- package/dist/pill/index.d.ts +20 -0
- package/dist/pill/index.js +8 -0
- package/dist/pill/index.js.map +1 -0
- package/dist/popover/index.cjs +8 -0
- package/dist/popover/index.cjs.map +1 -0
- package/dist/popover/index.d.cts +35 -0
- package/dist/popover/index.d.ts +35 -0
- package/dist/popover/index.js +8 -0
- package/dist/popover/index.js.map +1 -0
- package/dist/progress/index.cjs +8 -0
- package/dist/progress/index.cjs.map +1 -0
- package/dist/progress/index.d.cts +18 -0
- package/dist/progress/index.d.ts +18 -0
- package/dist/progress/index.js +8 -0
- package/dist/progress/index.js.map +1 -0
- package/dist/radio/index.cjs +10 -0
- package/dist/radio/index.cjs.map +1 -0
- package/dist/radio/index.d.cts +33 -0
- package/dist/radio/index.d.ts +33 -0
- package/dist/radio/index.js +10 -0
- package/dist/radio/index.js.map +1 -0
- package/dist/renderIcon-C2lEMMzb.d.cts +30 -0
- package/dist/renderIcon-C2lEMMzb.d.ts +30 -0
- package/dist/segmented-control/index.cjs +11 -0
- package/dist/segmented-control/index.cjs.map +1 -0
- package/dist/segmented-control/index.d.cts +70 -0
- package/dist/segmented-control/index.d.ts +70 -0
- package/dist/segmented-control/index.js +11 -0
- package/dist/segmented-control/index.js.map +1 -0
- package/dist/select/index.cjs +13 -0
- package/dist/select/index.cjs.map +1 -0
- package/dist/select/index.d.cts +46 -0
- package/dist/select/index.d.ts +46 -0
- package/dist/select/index.js +13 -0
- package/dist/select/index.js.map +1 -0
- package/dist/sizes-DM6Rrrgq.d.cts +11 -0
- package/dist/sizes-DM6Rrrgq.d.ts +11 -0
- package/dist/skeleton/index.cjs +8 -0
- package/dist/skeleton/index.cjs.map +1 -0
- package/dist/skeleton/index.d.cts +14 -0
- package/dist/skeleton/index.d.ts +14 -0
- package/dist/skeleton/index.js +8 -0
- package/dist/skeleton/index.js.map +1 -0
- package/dist/slider/index.cjs +8 -0
- package/dist/slider/index.cjs.map +1 -0
- package/dist/slider/index.d.cts +37 -0
- package/dist/slider/index.d.ts +37 -0
- package/dist/slider/index.js +8 -0
- package/dist/slider/index.js.map +1 -0
- package/dist/snackbar/index.cjs +18 -0
- package/dist/snackbar/index.cjs.map +1 -0
- package/dist/snackbar/index.d.cts +68 -0
- package/dist/snackbar/index.d.ts +68 -0
- package/dist/snackbar/index.js +18 -0
- package/dist/snackbar/index.js.map +1 -0
- package/dist/spinner/index.cjs +9 -0
- package/dist/spinner/index.cjs.map +1 -0
- package/dist/spinner/index.d.cts +12 -0
- package/dist/spinner/index.d.ts +12 -0
- package/dist/spinner/index.js +9 -0
- package/dist/spinner/index.js.map +1 -0
- package/dist/split-button/index.cjs +13 -0
- package/dist/split-button/index.cjs.map +1 -0
- package/dist/split-button/index.d.cts +53 -0
- package/dist/split-button/index.d.ts +53 -0
- package/dist/split-button/index.js +13 -0
- package/dist/split-button/index.js.map +1 -0
- package/dist/stepper/index.cjs +8 -0
- package/dist/stepper/index.cjs.map +1 -0
- package/dist/stepper/index.d.cts +42 -0
- package/dist/stepper/index.d.ts +42 -0
- package/dist/stepper/index.js +8 -0
- package/dist/stepper/index.js.map +1 -0
- package/dist/switch/index.cjs +8 -0
- package/dist/switch/index.cjs.map +1 -0
- package/dist/switch/index.d.cts +15 -0
- package/dist/switch/index.d.ts +15 -0
- package/dist/switch/index.js +8 -0
- package/dist/switch/index.js.map +1 -0
- package/dist/table/index.cjs +33 -0
- package/dist/table/index.cjs.map +1 -0
- package/dist/table/index.d.cts +20 -0
- package/dist/table/index.d.ts +20 -0
- package/dist/table/index.js +33 -0
- package/dist/table/index.js.map +1 -0
- package/dist/tabs/index.cjs +13 -0
- package/dist/tabs/index.cjs.map +1 -0
- package/dist/tabs/index.d.cts +34 -0
- package/dist/tabs/index.d.ts +34 -0
- package/dist/tabs/index.js +13 -0
- package/dist/tabs/index.js.map +1 -0
- package/dist/tag-input/index.cjs +12 -0
- package/dist/tag-input/index.cjs.map +1 -0
- package/dist/tag-input/index.d.cts +36 -0
- package/dist/tag-input/index.d.ts +36 -0
- package/dist/tag-input/index.js +12 -0
- package/dist/tag-input/index.js.map +1 -0
- package/dist/textarea/index.cjs +10 -0
- package/dist/textarea/index.cjs.map +1 -0
- package/dist/textarea/index.d.cts +28 -0
- package/dist/textarea/index.d.ts +28 -0
- package/dist/textarea/index.js +10 -0
- package/dist/textarea/index.js.map +1 -0
- package/dist/timeline/index.cjs +8 -0
- package/dist/timeline/index.cjs.map +1 -0
- package/dist/timeline/index.d.cts +24 -0
- package/dist/timeline/index.d.ts +24 -0
- package/dist/timeline/index.js +8 -0
- package/dist/timeline/index.js.map +1 -0
- package/dist/toolbar/index.cjs +20 -0
- package/dist/toolbar/index.cjs.map +1 -0
- package/dist/toolbar/index.d.cts +13 -0
- package/dist/toolbar/index.d.ts +13 -0
- package/dist/toolbar/index.js +20 -0
- package/dist/toolbar/index.js.map +1 -0
- package/dist/tooltip/index.cjs +9 -0
- package/dist/tooltip/index.cjs.map +1 -0
- package/dist/tooltip/index.d.cts +25 -0
- package/dist/tooltip/index.d.ts +25 -0
- package/dist/tooltip/index.js +9 -0
- package/dist/tooltip/index.js.map +1 -0
- package/dist/tree-view/index.cjs +8 -0
- package/dist/tree-view/index.cjs.map +1 -0
- package/dist/tree-view/index.d.cts +36 -0
- package/dist/tree-view/index.d.ts +36 -0
- package/dist/tree-view/index.js +8 -0
- package/dist/tree-view/index.js.map +1 -0
- package/dist/virtual-list/index.cjs +9 -0
- package/dist/virtual-list/index.cjs.map +1 -0
- package/dist/virtual-list/index.d.cts +58 -0
- package/dist/virtual-list/index.d.ts +58 -0
- package/dist/virtual-list/index.js +9 -0
- package/dist/virtual-list/index.js.map +1 -0
- package/package.json +108 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/VirtualList/VirtualList.component.tsx","../node_modules/@tanstack/virtual-core/src/lazy-measurements.ts","../node_modules/@tanstack/virtual-core/src/utils.ts","../node_modules/@tanstack/virtual-core/src/index.ts","../node_modules/@tanstack/react-virtual/src/index.tsx"],"sourcesContent":["import React, { useCallback, useRef } from 'react';\r\nimport { useVirtualizer } from '@tanstack/react-virtual';\r\nimport { Skeleton } from '../Skeleton';\r\nimport type { VirtualListProps } from './VirtualList.types';\r\nimport './VirtualList.scss';\r\n\r\n// ============================================================================\r\n// Helpers\r\n// ============================================================================\r\n\r\nfunction toCssSize(value: number | string): string {\r\n return typeof value === 'number' ? `${value}px` : value;\r\n}\r\n\r\n// ============================================================================\r\n// Component\r\n// ============================================================================\r\n\r\nfunction VirtualListInner<T = unknown>({\r\n data,\r\n renderRow,\r\n rowHeight,\r\n height,\r\n width = '100%',\r\n overscan = 3,\r\n loading = false,\r\n loadingRowCount = 10,\r\n emptyContent,\r\n className,\r\n onScroll,\r\n onEndReached,\r\n endReachedThreshold = 100,\r\n getRowKey,\r\n}: VirtualListProps<T>): React.ReactElement | null {\r\n const scrollRef = useRef<HTMLDivElement>(null);\r\n\r\n /**\r\n * Guards against firing `onEndReached` repeatedly while the user remains at\r\n * the bottom. Resets when they scroll back above the threshold, so\r\n * subsequent page fetches work correctly.\r\n */\r\n const endReachedFiredRef = useRef(false);\r\n\r\n // Normalise both the fixed-number and per-index-function variants of\r\n // `rowHeight` into the single `(index: number) => number` signature that\r\n // `useVirtualizer` expects for `estimateSize`.\r\n const estimateSize = useCallback(\r\n (index: number): number => (typeof rowHeight === 'function' ? rowHeight(index) : rowHeight),\r\n [rowHeight],\r\n );\r\n\r\n const virtualizer = useVirtualizer({\r\n count: data.length,\r\n getScrollElement: () => scrollRef.current,\r\n estimateSize,\r\n overscan,\r\n });\r\n\r\n // ─── Scroll handler ───────────────────────────────────────────────────────\r\n // `useVirtualizer` already subscribes to scroll events on `scrollRef`\r\n // internally. We attach our own handler purely to forward `onScroll` and\r\n // drive the `onEndReached` logic - both operate independently of the\r\n // virtualizer's own scroll bookkeeping.\r\n const handleScroll = useCallback(\r\n (e: React.UIEvent<HTMLDivElement>) => {\r\n const { scrollTop: st, clientHeight: ch, scrollHeight: sh } = e.currentTarget;\r\n onScroll?.(st);\r\n\r\n if (onEndReached) {\r\n const nearEnd = st + ch >= sh - endReachedThreshold;\r\n if (nearEnd && !endReachedFiredRef.current) {\r\n endReachedFiredRef.current = true;\r\n onEndReached();\r\n } else if (!nearEnd) {\r\n // Reset so the next time the user reaches the bottom it fires again\r\n endReachedFiredRef.current = false;\r\n }\r\n }\r\n },\r\n [onScroll, onEndReached, endReachedThreshold],\r\n );\r\n\r\n // ─── Derived values ───────────────────────────────────────────────────────\r\n const containerStyle: React.CSSProperties = {\r\n height: toCssSize(height),\r\n width: toCssSize(width),\r\n };\r\n\r\n // Use the numeric rowHeight for skeleton rows; fall back to a sensible default\r\n // when rowHeight is a function (we don't have real data to compute from).\r\n const skeletonRowHeight = typeof rowHeight === 'number' ? rowHeight : 56;\r\n\r\n // ─── Render ───────────────────────────────────────────────────────────────\r\n return (\r\n <div\r\n ref={scrollRef}\r\n className={['eidos-virtual-list', className].filter(Boolean).join(' ')}\r\n style={containerStyle}\r\n onScroll={loading ? undefined : handleScroll}\r\n role=\"list\"\r\n aria-busy={loading}\r\n >\r\n {/* ── Loading state ─────────────────────────────────────────────── */}\r\n {loading && (\r\n <div className=\"eidos-virtual-list-loading\" aria-label=\"Loading content\">\r\n {Array.from({ length: loadingRowCount }, (_, idx) => (\r\n <div\r\n key={idx}\r\n className=\"eidos-virtual-list-skeleton-row\"\r\n style={{ height: skeletonRowHeight }}\r\n >\r\n <Skeleton\r\n variant=\"circular\"\r\n width={skeletonRowHeight - 20}\r\n height={skeletonRowHeight - 20}\r\n />\r\n <div className=\"eidos-virtual-list-skeleton-row-content\">\r\n <Skeleton variant=\"rounded\" width=\"55%\" height={12} />\r\n <Skeleton variant=\"rounded\" width=\"38%\" height={12} />\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* ── Empty state ───────────────────────────────────────────────── */}\r\n {!loading && data.length === 0 && (\r\n <div className=\"eidos-virtual-list-empty\" role=\"status\">\r\n {emptyContent}\r\n </div>\r\n )}\r\n\r\n {/* ── Virtualized content ───────────────────────────────────────── */}\r\n {!loading && data.length > 0 && (\r\n <div className=\"eidos-virtual-list-inner\" style={{ height: virtualizer.getTotalSize() }}>\r\n {virtualizer.getVirtualItems().map((virtualItem) => {\r\n const item = data[virtualItem.index] as T;\r\n // Prefer the consumer's stable key; fall back to the numeric index.\r\n // We intentionally avoid `virtualItem.key` here because its type\r\n // includes `bigint` (per @tanstack/virtual-core), which React's\r\n // `key` prop does not accept.\r\n const key = getRowKey ? getRowKey(item, virtualItem.index) : virtualItem.index;\r\n return (\r\n <div\r\n key={key}\r\n className=\"eidos-virtual-list-row\"\r\n style={{\r\n // `top: 0` anchors the absolutely-positioned row to the top\r\n // of the inner spacer; `transform` then translates it into\r\n // position. This is the recommended pattern for\r\n // @tanstack/react-virtual and keeps compositing efficient.\r\n top: 0,\r\n height: virtualItem.size,\r\n transform: `translateY(${virtualItem.start}px)`,\r\n }}\r\n role=\"listitem\"\r\n >\r\n {renderRow(item, virtualItem.index)}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nexport const VirtualList = Object.assign(VirtualListInner, {\r\n displayName: 'VirtualList',\r\n});\r\n","// Lazy materialization for the lanes===1 fast path. Backed by a\n// Float64Array (stride 2: start, size, …); VirtualItems are constructed on\n// first indexed read and cached. Saves the per-item object allocation at\n// large list counts where most items are never visible.\n\nimport type { VirtualItem } from './index'\n\ntype Key = number | string | bigint\n\nexport function createLazyMeasurementsView(\n count: number,\n flat: Float64Array,\n getItemKey: (i: number) => Key,\n): Array<VirtualItem> {\n const cache: Array<VirtualItem | undefined> = new Array(count)\n return new Proxy(cache as any, {\n get(target, prop, receiver) {\n if (typeof prop === 'string') {\n // Cheap digit-prefix sniff before number coerce.\n const c = prop.charCodeAt(0)\n if (c >= 48 && c <= 57) {\n const i = +prop\n if (Number.isInteger(i) && i >= 0 && i < count) {\n let v = target[i]\n if (!v) {\n const s = flat[i * 2]!\n v = target[i] = {\n index: i,\n key: getItemKey(i),\n start: s,\n size: flat[i * 2 + 1]!,\n end: s + flat[i * 2 + 1]!,\n lane: 0,\n }\n }\n return v\n }\n }\n if (prop === 'length') return count\n }\n return Reflect.get(target, prop, receiver)\n },\n }) as Array<VirtualItem>\n}\n","export type NoInfer<A extends any> = [A][A extends any ? 0 : never]\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n\nexport function memo<TDeps extends ReadonlyArray<any>, TResult>(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => boolean\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n skipInitialOnChange?: boolean\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n let isInitial = true\n\n function memoizedFunction(): TResult {\n // Debug-only timing. In production builds, `process.env.NODE_ENV !==\n // 'production'` is constant-folded to `false` by downstream minifiers\n // (Terser/esbuild/swc with `define`), which DCEs the entire block.\n const debugEnabled =\n process.env.NODE_ENV !== 'production' && !!opts.key && !!opts.debug?.()\n let depTime = 0\n if (debugEnabled) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime = 0\n if (debugEnabled) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (debugEnabled) {\n const depEndTime = Math.round((Date.now() - depTime) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n if (opts?.onChange && !(isInitial && opts.skipInitialOnChange)) {\n opts.onChange(result)\n }\n\n isInitial = false\n\n return result\n }\n\n // Attach updateDeps to the function itself\n memoizedFunction.updateDeps = (newDeps: [...TDeps]) => {\n deps = newDeps\n }\n\n return memoizedFunction\n}\n\nexport function notUndefined<T>(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1.01\n\nexport const debounce = (\n targetWindow: Window & typeof globalThis,\n fn: Function,\n ms: number,\n) => {\n let timeoutId: number\n return Object.assign(\n function (this: any, ...args: Array<any>) {\n targetWindow.clearTimeout(timeoutId)\n timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms)\n },\n {\n // The handle is closure-local, so a caller that has already\n // unsubscribed has no way to stop a queued call. Teardown paths use\n // this to drop the pending invocation instead of letting it land.\n cancel: () => {\n targetWindow.clearTimeout(timeoutId)\n },\n },\n )\n}\n","import { createLazyMeasurementsView } from './lazy-measurements'\nimport { approxEqual, debounce, memo, notUndefined } from './utils'\n\n// Browser-aware iOS detection. Programmatic `scrollTo`/`scrollTop` writes\n// during a momentum-scroll cancel the momentum on iOS WebKit, so we defer\n// scroll-position adjustments triggered by mid-scroll resizes until the\n// scroll settles. SSR-safe (returns false when navigator is unavailable).\nlet _isIOSResult: boolean | undefined\nconst isIOSWebKit = (): boolean => {\n if (_isIOSResult !== undefined) return _isIOSResult\n if (typeof navigator === 'undefined') return (_isIOSResult = false)\n if (/iP(hone|od|ad)/.test(navigator.userAgent)) return (_isIOSResult = true)\n // iPadOS 13+ reports as MacIntel; touch-points distinguishes it from desktop.\n const mtp = (navigator as Navigator & { maxTouchPoints?: number })\n .maxTouchPoints\n return (_isIOSResult =\n navigator.platform === 'MacIntel' && mtp !== undefined && mtp > 0)\n}\n\n// Test hook: reset the iOS detection cache. Not exported.\nexport const _resetIOSDetectionForTests = () => {\n _isIOSResult = undefined\n}\n\nexport { approxEqual, debounce, memo, notUndefined } from './utils'\nexport type { NoInfer, PartialKeys } from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth' | 'instant'\n\ntype ScrollAnchor = 'start' | 'end'\n\ntype FollowOnAppend = boolean | ScrollBehavior\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\ntype ScrollToEndOptions = Pick<ScrollToOptions, 'behavior'>\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string | bigint\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n lane: number\n}\n\nexport interface Rect {\n width: number\n height: number\n}\n\n//\n\nconst getRect = (element: HTMLElement): Rect => {\n const { offsetWidth, offsetHeight } = element\n return { width: offsetWidth, height: offsetHeight }\n}\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n const len = end - start + 1\n\n const arr = new Array<number>(len)\n for (let i = 0; i < len; i++) {\n arr[i] = start + i\n }\n return arr\n}\n\nexport const observeElementRect = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n const handler = (rect: Rect) => {\n const { width, height } = rect\n cb({ width: Math.round(width), height: Math.round(height) })\n }\n\n handler(getRect(element as unknown as HTMLElement))\n\n if (!targetWindow.ResizeObserver) {\n return () => {}\n }\n\n const observer = new targetWindow.ResizeObserver((entries) => {\n const run = () => {\n const entry = entries[0]\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n handler({ width: box.inlineSize, height: box.blockSize })\n return\n }\n }\n handler(getRect(element as unknown as HTMLElement))\n }\n\n instance.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\n })\n\n observer.observe(element, { box: 'border-box' })\n\n return () => {\n observer.unobserve(element)\n }\n}\n\nconst addEventListenerOptions = {\n passive: true,\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer<Window, any>,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight })\n }\n handler()\n\n element.addEventListener('resize', handler, addEventListenerOptions)\n\n return () => {\n element.removeEventListener('resize', handler)\n }\n}\n\nconst supportsScrollend =\n typeof window == 'undefined' ? true : 'onscrollend' in window\n\ntype ObserveOffsetCallBack = (offset: number, isScrolling: boolean) => void\n\n// Shared core: both element and window variants attach scroll/scrollend\n// listeners with the same lifecycle; they only differ in how to read the\n// current offset from the scroll target.\nconst observeOffset = <T extends Element | Window>(\n instance: Virtualizer<T, any>,\n cb: ObserveOffsetCallBack,\n readOffset: (target: T) => number,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n const targetWindow = instance.targetWindow\n if (!targetWindow) {\n return\n }\n\n const registerScrollendEvent =\n instance.options.useScrollendEvent && supportsScrollend\n\n let offset = 0\n const fallback = registerScrollendEvent\n ? null\n : debounce(\n targetWindow,\n () => cb(offset, false),\n instance.options.isScrollingResetDelay,\n )\n\n const createHandler = (isScrolling: boolean) => () => {\n offset = readOffset(element)\n fallback?.()\n cb(offset, isScrolling)\n }\n const handler = createHandler(true)\n const endHandler = createHandler(false)\n\n element.addEventListener('scroll', handler, addEventListenerOptions)\n if (registerScrollendEvent) {\n element.addEventListener('scrollend', endHandler, addEventListenerOptions)\n }\n return () => {\n element.removeEventListener('scroll', handler)\n if (registerScrollendEvent) {\n element.removeEventListener('scrollend', endHandler)\n }\n // Removing the listener doesn't retract a reset already queued by the\n // last scroll, and that call would land on a virtualizer that has been\n // torn down — in React, a dispatch into an unmounted tree.\n fallback?.cancel()\n }\n}\n\nexport const observeElementOffset = <T extends Element>(\n instance: Virtualizer<T, any>,\n cb: ObserveOffsetCallBack,\n) =>\n observeOffset(instance, cb, (el) => {\n const { horizontal, isRtl } = instance.options\n return horizontal ? el.scrollLeft * ((isRtl && -1) || 1) : el.scrollTop\n })\n\nexport const observeWindowOffset = (\n instance: Virtualizer<Window, any>,\n cb: ObserveOffsetCallBack,\n) =>\n observeOffset(instance, cb, (win) =>\n instance.options.horizontal ? win.scrollX : win.scrollY,\n )\n\nexport const measureElement = <TItemElement extends Element>(\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<any, TItemElement>,\n) => {\n // When useCachedMeasurements is enabled, return the cached size\n // (or estimateSize as fallback) instead of measuring the DOM.\n if (instance.options.useCachedMeasurements) {\n const index = instance.indexFromElement(element)\n const key = instance.options.getItemKey(index)\n return (\n instance.itemSizeCache.get(key) ?? instance.options.estimateSize(index)\n )\n }\n\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],\n )\n return size\n }\n }\n\n // When called without a ResizeObserverEntry (sync measurement path),\n // return the previously measured size if available. This avoids a\n // synchronous layout read (offsetWidth/offsetHeight) on re-renders.\n // The ResizeObserver is already observing the element and will deliver\n // the accurate size asynchronously if it changed.\n // Users who need synchronous DOM reads can provide a custom measureElement.\n if (!entry) {\n const index = instance.indexFromElement(element)\n const key = instance.options.getItemKey(index)\n const cachedSize = instance.itemSizeCache.get(key)\n if (cachedSize !== undefined) {\n return cachedSize\n }\n }\n\n return (element as unknown as HTMLElement)[\n instance.options.horizontal ? 'offsetWidth' : 'offsetHeight'\n ]\n}\n\nconst scrollWithAdjustments = (\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<any, any>,\n) => {\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: offset + adjustments,\n behavior,\n })\n}\n\nexport const windowScroll: <T extends Window>(\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => void = scrollWithAdjustments\n\nexport const elementScroll: <T extends Element>(\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<T, any>,\n) => void = scrollWithAdjustments\n\ntype LaneAssignmentMode = 'estimate' | 'measured'\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => void\n observeElementRect: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n cb: ObserveOffsetCallBack,\n ) => void | (() => void)\n // Optional\n debug?: boolean\n initialRect?: Rect\n onChange?: (\n instance: Virtualizer<TScrollElement, TItemElement>,\n sync: boolean,\n ) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => number\n overscan?: number\n horizontal?: boolean\n paddingStart?: number\n paddingEnd?: number\n scrollPaddingStart?: number\n scrollPaddingEnd?: number\n initialOffset?: number | (() => number)\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => Array<number>\n scrollMargin?: number\n gap?: number\n indexAttribute?: string\n initialMeasurementsCache?: Array<VirtualItem>\n lanes?: number\n anchorTo?: ScrollAnchor\n followOnAppend?: FollowOnAppend\n scrollEndThreshold?: number\n isScrollingResetDelay?: number\n useScrollendEvent?: boolean\n enabled?: boolean\n isRtl?: boolean\n useAnimationFrameWithResizeObserver?: boolean\n laneAssignmentMode?: LaneAssignmentMode\n useCachedMeasurements?: boolean\n}\n\ntype ScrollState = {\n // what we want\n index: number | null\n align: ScrollAlignment\n behavior: ScrollBehavior\n\n // lifecycle\n startedAt: number\n\n // target tracking\n lastTargetOffset: number\n\n // settling\n stableFrames: number\n}\n\ntype PendingScrollAnchor = [\n key: Key | null,\n offset: number,\n followOnAppend: ScrollBehavior | null,\n anchorDelta: number,\n]\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: Array<void | (() => void)> = []\n options!: Required<VirtualizerOptions<TScrollElement, TItemElement>>\n scrollElement: TScrollElement | null = null\n targetWindow: (Window & typeof globalThis) | null = null\n isScrolling = false\n private scrollState: ScrollState | null = null\n measurementsCache: Array<VirtualItem> = []\n // Flat backing store for the lanes===1 fast path: [start_0, size_0, start_1, size_1, ...].\n // null until the first single-lane build; reused (and grown) across rebuilds.\n private _flatMeasurements: Float64Array | null = null\n itemSizeCache = new Map<Key, number>()\n private itemSizeCacheVersion = 0\n private laneAssignments = new Map<number, number>() // index → lane cache\n // Earliest index dirtied since last getMeasurements() rebuild, or null.\n private pendingMin: number | null = null\n private prevLanes: number | undefined = undefined\n private lanesChangedFlag = false\n private lanesSettling = false\n private pendingScrollAnchor: PendingScrollAnchor | null = null\n scrollRect: Rect | null = null\n scrollOffset: number | null = null\n scrollDirection: ScrollDirection | null = null\n scrollAdjustments = 0\n // Sum of size-change deltas above-viewport that were skipped during\n // iOS momentum scroll (writing scrollTop mid-momentum cancels it).\n // Flushed in a single scrollTo when iOS is fully settled.\n private _iosDeferredAdjustment = 0\n // Touch state. iOS WebKit cancels momentum when scrollTop is written, so\n // we defer adjustments not only during `isScrolling` but also through the\n // touchstart→touchend window (active drag) and a short tail after\n // touchend (early-momentum window — iOS only fires touch events once at\n // the start of momentum, so we use a timer rather than another event).\n private _iosTouching = false\n private _iosJustTouchEnded = false\n private _iosTouchEndTimerId: number | null = null\n // Subpixel reconciliation. Safari (and Chrome/Firefox under certain DPRs)\n // round scrollTop/scrollLeft writes to integer pixels. If we wrote 12345.5\n // but the browser reports back 12346, the next reconcileScroll sees a\n // \"target changed\" and re-fires scrollTo — a feedback loop that the\n // approxEqual(<1.01) tolerance otherwise absorbs as a workaround.\n // By remembering the intended value of our most-recent self-driven\n // scrollTo, we can match the browser's rounded read back to the intended\n // value when the diff is < 1.5 px, distinguishing it from a real user\n // scroll. The +0.5 over Math.abs lets us also absorb the +1 / -1 cases.\n private _intendedScrollOffset: number | null = null\n shouldAdjustScrollPositionOnItemSizeChange:\n | undefined\n | ((\n item: VirtualItem,\n delta: number,\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => boolean)\n elementsCache = new Map<Key, TItemElement>()\n private now = () => this.targetWindow?.performance?.now?.() ?? Date.now()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\n if (_ro) {\n return _ro\n }\n\n if (!this.targetWindow || !this.targetWindow.ResizeObserver) {\n return null\n }\n\n return (_ro = new this.targetWindow.ResizeObserver((entries) => {\n entries.forEach((entry) => {\n const run = () => {\n const node = entry.target as TItemElement\n const index = this.indexFromElement(node)\n\n if (!node.isConnected) {\n this.observer.unobserve(node)\n // Find the cache entry pointing to this exact node and remove\n // it. We can't call getItemKey(index) here because items may\n // have been removed since this node was rendered — the index\n // could be stale and out-of-bounds in the user's data array\n // (regression test in e2e/.../stale-index.spec.ts, fix #1148).\n // The === comparison naturally handles the React-replaced-\n // a-node-for-the-same-key case: that entry now points to a\n // different node, so this loop won't match.\n for (const [cacheKey, cachedNode] of this.elementsCache) {\n if (cachedNode === node) {\n this.elementsCache.delete(cacheKey)\n break\n }\n }\n return\n }\n\n if (!this.isIndexInRange(index)) return\n\n if (this.shouldMeasureDuringScroll(index)) {\n this.resizeItem(\n index,\n this.options.measureElement(node, entry, this),\n )\n }\n }\n this.options.useAnimationFrameWithResizeObserver\n ? requestAnimationFrame(run)\n : run()\n })\n }))\n }\n\n return {\n disconnect: () => {\n get()?.disconnect()\n _ro = null\n },\n observe: (target: Element) =>\n get()?.observe(target, { box: 'border-box' }),\n unobserve: (target: Element) => get()?.unobserve(target),\n }\n })()\n range: { startIndex: number; endIndex: number } | null = null\n\n constructor(opts: VirtualizerOptions<TScrollElement, TItemElement>) {\n this.setOptions(opts)\n }\n\n setOptions = (opts: VirtualizerOptions<TScrollElement, TItemElement>) => {\n // Skip `{...defaults, ...opts}` because explicit `undefined` values in\n // opts would override defaults with `undefined`.\n const merged = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n gap: 0,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n lanes: 1,\n anchorTo: 'start',\n followOnAppend: false,\n scrollEndThreshold: 1,\n isScrollingResetDelay: 150,\n enabled: true,\n isRtl: false,\n useScrollendEvent: false,\n useAnimationFrameWithResizeObserver: false,\n laneAssignmentMode: 'estimate',\n useCachedMeasurements: false,\n } as unknown as Required<VirtualizerOptions<TScrollElement, TItemElement>>\n\n for (const key in opts) {\n const v = (opts as any)[key]\n if (v !== undefined) (merged as any)[key] = v\n }\n\n const prevOptions = this.options as\n | Required<VirtualizerOptions<TScrollElement, TItemElement>>\n | undefined\n let anchor: [Key, number] | null = null\n let followOnAppend: ScrollBehavior | null = null\n let edgeKeysChanged = false\n\n if (\n prevOptions !== undefined &&\n prevOptions.enabled &&\n merged.enabled &&\n merged.anchorTo === 'end' &&\n this.scrollElement !== null\n ) {\n const prevCount = prevOptions.count\n const nextCount = merged.count\n const measurements = this.getMeasurements()\n const prevFirstKey =\n prevCount > 0\n ? (measurements[0]?.key ?? prevOptions.getItemKey(0))\n : null\n const prevLastKey =\n prevCount > 0\n ? (measurements[prevCount - 1]?.key ??\n prevOptions.getItemKey(prevCount - 1))\n : null\n const didCountChange = nextCount !== prevCount\n const didEdgeKeysChange =\n didCountChange ||\n (prevCount > 0 &&\n nextCount > 0 &&\n (merged.getItemKey(0) !== prevFirstKey ||\n merged.getItemKey(nextCount - 1) !== prevLastKey))\n\n if (didEdgeKeysChange) {\n edgeKeysChanged = true\n const item =\n prevCount > 0\n ? (this.getVirtualItemForOffset(this.getScrollOffset()) ??\n measurements[0])\n : null\n\n if (item) {\n anchor = [item.key, this.getScrollOffset() - item.start]\n }\n\n const behavior =\n merged.followOnAppend === true\n ? 'auto'\n : merged.followOnAppend || null\n\n if (\n behavior &&\n nextCount > prevCount &&\n this.isAtEnd(prevOptions.scrollEndThreshold) &&\n (prevCount === 0 || merged.getItemKey(nextCount - 1) !== prevLastKey)\n ) {\n followOnAppend = behavior\n }\n }\n }\n\n this.options = merged\n\n // When edge keys changed (prepend, trim, reorder, etc.) the key→index\n // mapping has shifted. Force a full measurement rebuild so the anchor\n // resolution below reads positions from the new layout, not the stale\n // memoised cache. Without this, a stable `getItemKey` reference +\n // unchanged `count` would let getMeasurements() return the old layout.\n if (edgeKeysChanged) {\n this.pendingMin = 0\n this.itemSizeCacheVersion++\n }\n\n // Eagerly adjust scrollOffset so the virtualizer computes the correct\n // visible range during the current render pass — before _willUpdate\n // syncs the DOM scroll position in a layout effect. Without this,\n // the virtualizer would render the wrong items for one frame (the\n // estimate-based positions are stale) and then correct in the next\n // frame, producing a visible \"jump\" on prepend with dynamic sizes.\n let anchorResolved = false\n let anchorDelta = 0\n if (anchor && this.scrollOffset !== null) {\n const [anchorKey, anchorOffset] = anchor\n const newMeasurements = this.getMeasurements()\n const { count, getItemKey } = this.options\n let idx = 0\n while (idx < count && getItemKey(idx) !== anchorKey) {\n idx++\n }\n if (idx < count) {\n const anchorItem = newMeasurements[idx]\n if (anchorItem) {\n // Clamp to the reachable range's lower bound — anchorOffset may\n // have been derived from a transiently negative scrollOffset\n // (rubber-band), and a negative tracked offset never self-heals\n // when the element cannot scroll (#1229).\n const newOffset = Math.max(0, anchorItem.start + anchorOffset)\n if (newOffset !== this.scrollOffset) {\n anchorDelta = newOffset - this.scrollOffset\n this.scrollOffset = newOffset\n anchorResolved = true\n }\n }\n }\n }\n\n if (anchorResolved || followOnAppend) {\n this.pendingScrollAnchor = [\n anchorResolved ? anchor![0] : null,\n anchorResolved ? anchor![1] : 0,\n followOnAppend,\n anchorDelta,\n ]\n }\n }\n\n private notify = (sync: boolean) => {\n this.options.onChange?.(this, sync)\n }\n\n // Returns `true` when it performed a synchronous `scrollTop` write this\n // tick, `false` when the delta was zero or the write was deferred (iOS).\n // `resizeItem` uses that to decide whether the follow-up `notify` must be\n // synchronous so the grown transforms commit in the same paint (#1227).\n private applyScrollAdjustment(\n delta: number,\n behavior?: ScrollBehavior,\n ): boolean {\n if (delta === 0) return false\n\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n if (\n isIOSWebKit() &&\n (this.isScrolling || this._iosTouching || this._iosJustTouchEnded)\n ) {\n this._iosDeferredAdjustment += delta\n return false\n } else {\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: (this.scrollAdjustments += delta),\n behavior,\n })\n // Eagerly carry the intended target in `scrollOffset` so callers that\n // read it before the next scroll event — notably the next `resizeItem`\n // tick's `getVirtualDistanceFromEnd()` / `wasAtEnd` check — see the\n // post-adjustment position even when the DOM `scrollTop` write was\n // clamped because the consumer hasn't grown the sizer yet (`notify()`\n // runs after this in `resizeItem`). Same idea as the eager\n // `scrollOffset` adjustment for prepend in `setOptions` (#1176). The\n // adjustment is now baked into `scrollOffset`, so zero\n // `scrollAdjustments` to keep their sum invariant.\n if (this.scrollOffset !== null) {\n this.scrollOffset += this.scrollAdjustments\n // Clamp only the lower bound: a negative offset is unreachable, and\n // on an unscrollable element (content fits the viewport) no scroll\n // event ever fires to correct it, permanently skewing\n // getDistanceFromEnd() and wedging _flushIosDeferredIfReady (#1229).\n // Upper-bound overflow stays untouched — it is transiently\n // legitimate mid-prepend while the consumer's sizer catches up.\n if (this.scrollOffset < 0) this.scrollOffset = 0\n this.scrollAdjustments = 0\n }\n return true\n }\n }\n\n private maybeNotify = memo(\n () => {\n this.calculateRange()\n\n return [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ]\n },\n (isScrolling) => {\n this.notify(isScrolling)\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.isScrolling,\n this.range ? this.range.startIndex : null,\n this.range ? this.range.endIndex : null,\n ] as [boolean, number | null, number | null],\n },\n )\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.observer.disconnect()\n if (this.rafId != null && this.targetWindow) {\n this.targetWindow.cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.scrollState = null\n // The debounce cancelled above is the only thing that writes `isScrolling`\n // back to false, so a cleanup inside the reset window would strand it, and\n // the direction derived from it, as true. That matters because `cleanup`\n // also runs when the scroll element changes or `enabled` goes false, where\n // the instance lives on.\n this.isScrolling = false\n this.scrollDirection = null\n // The iOS gesture/deferral state is scoped to the current scroll\n // element: the touch listeners that maintain it were just removed, and\n // an in-flight touch keeps targeting the old element (implicit touch\n // capture), so the new element never reports it. Carrying the state\n // over would replay a stale deferred delta on the new element's first\n // flush, and a cleanup that lands mid-touch or inside the post-touchend\n // grace window would strand _iosTouching / _iosJustTouchEnded as true\n // (the listener unsub clears the grace timer, and with it the only\n // pending reset of the flag), deferring every adjustment on the new\n // element until its next touch cycle.\n this._iosDeferredAdjustment = 0\n this._iosTouching = false\n this._iosJustTouchEnded = false\n this.scrollElement = null\n this.targetWindow = null\n }\n\n _didMount = () => {\n return () => {\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.enabled\n ? this.options.getScrollElement()\n : null\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n if (!scrollElement) {\n this.maybeNotify()\n return\n }\n\n this.scrollElement = scrollElement\n\n if (this.scrollElement && 'ownerDocument' in this.scrollElement) {\n this.targetWindow = this.scrollElement.ownerDocument.defaultView\n } else {\n this.targetWindow = this.scrollElement?.window ?? null\n }\n\n this.elementsCache.forEach((cached) => {\n this.observer.observe(cached)\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n this.scrollRect = rect\n this.maybeNotify()\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset, isScrolling) => {\n // A scroll event that reports movement but lands on the offset we\n // already hold — and isn't a self-write read-back — is a spurious\n // no-op re-emit that Safari/Firefox fire after a re-render's layout\n // (Chrome doesn't). Treating it as scrolling re-arms `isScrolling`,\n // which forces a render that triggers another such event: an\n // infinite re-render loop. Ignore it. (Self-writes are handled by\n // the `_intendedScrollOffset` reconciliation just below.)\n if (\n isScrolling &&\n this._intendedScrollOffset === null &&\n offset === this.scrollOffset\n ) {\n return\n }\n\n // If this scroll event looks like the browser's read-back of a\n // value we just wrote, prefer our intended (sub-pixel-accurate)\n // value over the browser's rounded one. The 1.5 px tolerance is\n // tight enough to avoid mistaking a real user scroll for a\n // self-write — by the time the user has moved 1.5 px, the\n // intended value will already have been consumed by a prior\n // scroll event and cleared.\n if (\n this._intendedScrollOffset !== null &&\n Math.abs(offset - this._intendedScrollOffset) < 1.5\n ) {\n offset = this._intendedScrollOffset\n }\n this._intendedScrollOffset = null\n\n this.scrollAdjustments = 0\n // If the offset hasn't moved, this is the echo of our own\n // adjustment write — `applyScrollAdjustment` already folded it\n // into `scrollOffset`. There's no direction to infer, so leave\n // it alone; a real gesture always moves the offset.\n const prevOffset = this.getScrollOffset()\n this.scrollDirection = isScrolling\n ? prevOffset === offset\n ? this.scrollDirection\n : prevOffset < offset\n ? 'forward'\n : 'backward'\n : null\n this.scrollOffset = offset\n this.isScrolling = isScrolling\n\n // Flush deferred iOS adjustments if we're now fully settled.\n // \"Fully settled\" means: not actively scrolling, no finger on\n // screen, and the post-touchend grace window has expired.\n this._flushIosDeferredIfReady()\n\n if (this.scrollState) {\n this.scheduleScrollReconcile()\n }\n this.maybeNotify()\n }),\n )\n\n // Touch event listeners (iOS-aware deferral). We attach unconditionally\n // — the listeners are passive and cheap; on non-touch devices they\n // simply never fire. The gating by isIOSWebKit() lives in resizeItem\n // and _flushIosDeferredIfReady so we only burn the path on iOS.\n if ('addEventListener' in this.scrollElement) {\n const scrollEl = this.scrollElement as unknown as EventTarget\n const onTouchStart = () => {\n this._iosTouching = true\n this._iosJustTouchEnded = false\n if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {\n this.targetWindow.clearTimeout(this._iosTouchEndTimerId)\n this._iosTouchEndTimerId = null\n }\n }\n const onTouchEnd = () => {\n this._iosTouching = false\n if (!isIOSWebKit() || this.targetWindow == null) {\n // Non-iOS: nothing more to track. Just clear the touching flag.\n return\n }\n this._iosJustTouchEnded = true\n // After ~150 ms with no scroll/touch events, momentum is done.\n this._iosTouchEndTimerId = this.targetWindow.setTimeout(() => {\n this._iosJustTouchEnded = false\n this._iosTouchEndTimerId = null\n // After the grace window, attempt to flush. The scroll event\n // for momentum decay may have already fired before our timer.\n this._flushIosDeferredIfReady()\n }, 150)\n }\n scrollEl.addEventListener(\n 'touchstart',\n onTouchStart,\n addEventListenerOptions,\n )\n scrollEl.addEventListener(\n 'touchend',\n onTouchEnd,\n addEventListenerOptions,\n )\n this.unsubs.push(() => {\n scrollEl.removeEventListener('touchstart', onTouchStart)\n scrollEl.removeEventListener('touchend', onTouchEnd)\n if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {\n this.targetWindow.clearTimeout(this._iosTouchEndTimerId)\n this._iosTouchEndTimerId = null\n }\n })\n }\n\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n\n const anchor = this.pendingScrollAnchor\n this.pendingScrollAnchor = null\n\n if (anchor && this.scrollElement && this.options.enabled) {\n const [key, _offset, followOnAppend, anchorDelta] = anchor\n\n if (key !== null && !followOnAppend) {\n // scrollOffset was eagerly adjusted in setOptions so the\n // virtualizer already computed the correct range during render.\n // Now sync the browser's actual scroll position to match.\n // Skip when followOnAppend is set — scrollToEnd will handle it.\n //\n // On iOS WebKit, writing scrollTop during touch/momentum cancels\n // the in-flight scroll. Defer the DOM sync the same way\n // applyScrollAdjustment does — accumulate the delta and let\n // _flushIosDeferredIfReady handle it once the scroll settles.\n if (\n isIOSWebKit() &&\n (this.isScrolling || this._iosTouching || this._iosJustTouchEnded)\n ) {\n if (anchorDelta !== 0) {\n this._iosDeferredAdjustment += anchorDelta\n }\n } else {\n this._scrollToOffset(this.getScrollOffset(), {\n adjustments: undefined,\n behavior: undefined,\n })\n }\n }\n\n if (followOnAppend) {\n this.scrollToEnd({ behavior: followOnAppend })\n }\n }\n }\n\n // Apply any accumulated iOS-deferred scroll adjustment, but only when we're\n // truly settled — not actively scrolling, not under an active touch, and\n // past the post-touchend grace window. Called from the scroll callback\n // and the touchend grace-timer.\n private _flushIosDeferredIfReady = () => {\n if (this._iosDeferredAdjustment === 0) return\n if (this.isScrolling) return\n if (this._iosTouching) return\n if (this._iosJustTouchEnded) return\n // Phase 2b: Safari elastic-overscroll (rubber-band) lets scrollTop go\n // negative or beyond scrollHeight - clientHeight. Writing scrollTop\n // while in that zone snaps the page back to the clamped value at the\n // end of the bounce, often discarding the user's intent. Skip the\n // flush; the next in-bounds scroll event will retry.\n const cur = this.getScrollOffset()\n const max = this.getMaxScrollOffset()\n if (cur < 0 || cur > max) return\n // At the end clamp the browser already absorbed a shrink above the\n // viewport (it clamped scrollTop onto the new bottom), so replaying our\n // deferred negative delta would lift the view off the bottom — drop it.\n // Positive deltas still replay: growth above doesn't clamp. (#1233)\n if (this._iosDeferredAdjustment < 0 && cur >= max - 1) {\n this._iosDeferredAdjustment = 0\n return\n }\n const delta = this._iosDeferredAdjustment\n this._iosDeferredAdjustment = 0\n // Roll the deferred delta into the running accumulator so any resize\n // landing between now and the resulting scroll event computes from the\n // post-flush offset rather than the stale one.\n this._scrollToOffset(cur, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n private rafId: number | null = null\n private scheduleScrollReconcile() {\n if (!this.targetWindow) {\n this.scrollState = null\n return\n }\n if (this.rafId != null) return\n this.rafId = this.targetWindow.requestAnimationFrame(() => {\n this.rafId = null\n this.reconcileScroll()\n })\n }\n private reconcileScroll() {\n if (!this.scrollState) return\n\n const el = this.scrollElement\n if (!el) return\n\n // Safety valve: bail out if reconciliation has been running too long\n const MAX_RECONCILE_MS = 5000\n if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {\n this.scrollState = null\n return\n }\n\n const offsetInfo =\n this.scrollState.index != null\n ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align)\n : undefined\n const targetOffset = offsetInfo\n ? offsetInfo[0]\n : this.scrollState.lastTargetOffset\n\n // Require one stable frame where target matches scroll offset.\n // approxEqual() already tolerates minor fluctuations, so one frame is sufficient\n // to confirm scroll has reached its target without premature cleanup.\n const STABLE_FRAMES = 1\n\n const targetChanged = targetOffset !== this.scrollState.lastTargetOffset\n\n if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {\n this.scrollState.stableFrames++\n if (this.scrollState.stableFrames >= STABLE_FRAMES) {\n // Final-pass exact landing. The reconcile-stable check uses a 1.01px\n // tolerance (approxEqual) so we don't fight subpixel browser rounding\n // during the converging phase. Once we're definitively settled,\n // commit the exact target so consumers calling scrollToIndex(N)\n // end up at the EXACT computed position of item N — matching\n // virtuoso's 0px landing accuracy rather than our prior 0.5-1px.\n if (this.getScrollOffset() !== targetOffset) {\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: 'auto',\n })\n }\n this.scrollState = null\n return\n }\n } else {\n this.scrollState.stableFrames = 0\n\n if (targetChanged) {\n // When the target moves during smooth scroll (because items came into\n // view and got measured, shifting positions), the original logic was\n // to immediately snap to 'auto' — visibly jarring on long\n // scroll-to-index calls. Now: keep smooth while we're still far\n // (more than a viewport) from the new target. Only fall back to\n // 'auto' for the final approach, so the user sees one continuous\n // motion that smoothly adjusts its endpoint as measurements arrive.\n const viewport = this.getSize() || 600\n const distance = Math.abs(targetOffset - this.getScrollOffset())\n const keepSmooth =\n this.scrollState.behavior === 'smooth' && distance > viewport\n\n this.scrollState.lastTargetOffset = targetOffset\n if (!keepSmooth) {\n this.scrollState.behavior = 'auto'\n }\n\n this._scrollToOffset(targetOffset, {\n adjustments: undefined,\n behavior: keepSmooth ? 'smooth' : 'auto',\n })\n }\n }\n\n // Always reschedule while scrollState is active to guarantee\n // the safety valve timeout runs even if no scroll events fire\n // (e.g. no-op scrollToFn, detached element)\n this.scheduleScrollReconcile()\n }\n\n private getSize = () => {\n if (!this.options.enabled) {\n this.scrollRect = null\n return 0\n }\n\n this.scrollRect = this.scrollRect ?? this.options.initialRect\n\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private getScrollOffset = () => {\n if (!this.options.enabled) {\n this.scrollOffset = null\n return 0\n }\n\n this.scrollOffset =\n this.scrollOffset ??\n (typeof this.options.initialOffset === 'function'\n ? this.options.initialOffset()\n : this.options.initialOffset)\n\n return this.scrollOffset\n }\n\n private getMeasurementOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n this.options.enabled,\n this.options.lanes,\n this.options.laneAssignmentMode,\n this.options.gap,\n ],\n (\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n gap,\n ) => {\n const lanesChanged =\n this.prevLanes !== undefined && this.prevLanes !== lanes\n\n if (lanesChanged) {\n // Set flag for getMeasurements to handle\n this.lanesChangedFlag = true\n }\n\n this.prevLanes = lanes\n this.pendingMin = null\n\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n gap,\n }\n },\n {\n key: false,\n },\n )\n\n private isIndexInRange = (index: number): boolean =>\n index >= 0 && index < this.options.count\n\n private getMeasurements = memo(\n () => [this.getMeasurementOptions(), this.itemSizeCacheVersion],\n (\n {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n enabled,\n lanes,\n laneAssignmentMode,\n gap,\n },\n _itemSizeCacheVersion,\n ) => {\n const itemSizeCache = this.itemSizeCache\n if (!enabled) {\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear()\n return []\n }\n\n // Clean up stale lane cache entries when count decreases\n if (this.laneAssignments.size > count) {\n for (const index of this.laneAssignments.keys()) {\n if (index >= count) {\n this.laneAssignments.delete(index)\n }\n }\n }\n\n // ✅ Force complete recalculation when lanes change\n if (this.lanesChangedFlag) {\n this.lanesChangedFlag = false // Reset immediately\n this.lanesSettling = true // Start settling period\n this.measurementsCache = []\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for new lane count\n // Force min = 0 on the rebuild\n this.pendingMin = null\n }\n\n // Don't restore from initialMeasurementsCache during lane changes\n // as it contains stale lane assignments from the previous lane count\n if (this.measurementsCache.length === 0 && !this.lanesSettling) {\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n }\n\n // During lanes settling, ignore pendingMin to prevent repositioning\n const min = this.lanesSettling ? 0 : (this.pendingMin ?? 0)\n this.pendingMin = null\n\n // ✅ End settling period when cache is fully built\n if (this.lanesSettling && this.measurementsCache.length === count) {\n this.lanesSettling = false\n }\n\n // ─── Fast path: single-lane lazy materialization ────────────────────\n // For lanes === 1 (the default and most common case), skip the\n // per-item VirtualItem object allocation. We write start/size pairs\n // into a Float64Array and return a Proxy that builds VirtualItem\n // objects on demand (only the indices a consumer actually reads).\n //\n // At n=100k this drops cold-mount cost from ~2.5ms (eager object\n // allocation) to roughly the cost of a single typed-array fill.\n if (lanes === 1) {\n // Reuse flat backing if large enough; else grow (preserving data\n // before `min` to mirror the slice-and-rebuild contract).\n const need = count * 2\n let flat = this._flatMeasurements\n if (!flat || flat.length < need) {\n const next = new Float64Array(need)\n if (flat && min > 0) next.set(flat.subarray(0, min * 2))\n flat = next\n this._flatMeasurements = flat\n }\n\n let runningStart: number\n if (min === 0) {\n runningStart = paddingStart + scrollMargin\n } else {\n // Continue from where we left off\n const prevIdx = min - 1\n runningStart = flat[prevIdx * 2]! + flat[prevIdx * 2 + 1]! + gap\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n flat[i * 2] = runningStart\n flat[i * 2 + 1] = size\n runningStart += size + gap\n }\n\n const view = createLazyMeasurementsView(count, flat, getItemKey)\n this.measurementsCache = view\n return view\n }\n\n const measurements = this.measurementsCache.slice(0, min)\n\n // ✅ Performance: Track last item index per lane for O(1) lookup\n const laneLastIndex: Array<number | undefined> = new Array(lanes).fill(\n undefined,\n )\n // Running end position of each lane's last item, so the shortest lane\n // can be found with an O(lanes) argmin instead of the old backward walk\n // through `measurements` (getFurthestMeasurement). `filledLanes` tracks\n // how many lanes have at least one item, mirroring the previous\n // \"all lanes seen → shortest lane, else i % lanes\" branch.\n const laneEnds = new Float64Array(lanes)\n let filledLanes = 0\n\n // Initialize from existing measurements (before min)\n for (let m = 0; m < min; m++) {\n const item = measurements[m]\n if (item) {\n if (laneLastIndex[item.lane] === undefined) filledLanes++\n laneLastIndex[item.lane] = m\n laneEnds[item.lane] = item.end\n }\n }\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n // Check for cached lane assignment\n const cachedLane = this.laneAssignments.get(i)\n let lane: number\n let start: number\n\n const shouldCacheLane =\n laneAssignmentMode === 'estimate' || itemSizeCache.has(key)\n\n if (cachedLane !== undefined && this.options.lanes > 1) {\n // Use cached lane - O(1) lookup for previous item in same lane\n lane = cachedLane\n const prevIndex = laneLastIndex[lane]\n const prevInLane =\n prevIndex !== undefined ? measurements[prevIndex] : undefined\n start = prevInLane\n ? prevInLane.end + gap\n : paddingStart + scrollMargin\n } else if (filledLanes === lanes) {\n // No cache, every lane seeded: place in the shortest lane.\n // Read the running per-lane ends (O(lanes) argmin) instead of the\n // old backward scan. Tie-break on the lane's last-item index to\n // preserve the previous sort-by-(end, index) placement exactly.\n let bestLane = 0\n let bestEnd = laneEnds[0]!\n let bestIdx = laneLastIndex[0]!\n for (let l = 1; l < lanes; l++) {\n const e = laneEnds[l]!\n if (e < bestEnd || (e === bestEnd && laneLastIndex[l]! < bestIdx)) {\n bestLane = l\n bestEnd = e\n bestIdx = laneLastIndex[l]!\n }\n }\n lane = bestLane\n start = bestEnd + gap\n\n if (shouldCacheLane) {\n this.laneAssignments.set(i, lane)\n }\n } else {\n // No cache and not every lane seeded yet — seed lanes in order,\n // matching the previous `i % lanes` fallback for the first row.\n lane = i % this.options.lanes\n start = paddingStart + scrollMargin\n\n if (shouldCacheLane) {\n this.laneAssignments.set(i, lane)\n }\n }\n\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n\n const end = start + size\n\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n\n // ✅ Performance: Update lane's last item index + running end\n if (laneLastIndex[lane] === undefined) filledLanes++\n laneLastIndex[lane] = i\n laneEnds[lane] = end\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [\n this.getMeasurements(),\n this.getSize(),\n this.getScrollOffset(),\n this.options.lanes,\n ],\n (measurements, outerSize, scrollOffset, lanes) => {\n if (measurements.length === 0 || outerSize === 0) {\n this.range = null\n return null\n }\n this.range = calculateRangeImpl(\n measurements,\n outerSize,\n scrollOffset,\n lanes,\n // Pass the typed array so binary search + forward-walk can read\n // start/end directly from Float64Array, skipping the Proxy traps.\n lanes === 1 && this._flatMeasurements != null\n ? this._flatMeasurements\n : null,\n )\n return this.range\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualIndexes = memo(\n () => {\n let startIndex: number | null = null\n let endIndex: number | null = null\n const range = this.calculateRange()\n if (range) {\n startIndex = range.startIndex\n endIndex = range.endIndex\n }\n this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex])\n return [\n this.options.rangeExtractor,\n this.options.overscan,\n this.options.count,\n startIndex,\n endIndex,\n ]\n },\n (rangeExtractor, overscan, count, startIndex, endIndex) => {\n return startIndex === null || endIndex === null\n ? []\n : rangeExtractor({\n startIndex,\n endIndex,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n /**\n * Determines if an item at the given index should be measured during smooth scroll.\n * During smooth scroll, only items within a buffer range around the target are measured\n * to prevent items far from the target from pushing it away.\n */\n private shouldMeasureDuringScroll = (index: number): boolean => {\n // No scroll state or not smooth scroll - always allow measurements\n if (!this.scrollState || this.scrollState.behavior !== 'smooth') {\n return true\n }\n\n const scrollIndex =\n this.scrollState.index ??\n this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)?.index\n\n if (scrollIndex !== undefined && this.range) {\n // Allow measurements within a buffer range around the scroll target\n const bufferSize = Math.max(\n this.options.overscan,\n Math.ceil((this.range.endIndex - this.range.startIndex) / 2),\n )\n const minIndex = Math.max(0, scrollIndex - bufferSize)\n const maxIndex = Math.min(\n this.options.count - 1,\n scrollIndex + bufferSize,\n )\n return index >= minIndex && index <= maxIndex\n }\n\n return true\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n this.elementsCache.forEach((cached, key) => {\n if (!cached.isConnected) {\n this.observer.unobserve(cached)\n this.elementsCache.delete(key)\n }\n })\n return\n }\n\n const index = this.indexFromElement(node)\n if (!this.isIndexInRange(index)) return\n\n const key = this.options.getItemKey(index)\n const prevNode = this.elementsCache.get(key)\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.elementsCache.set(key, node)\n }\n\n // Sync-measure when idle (initial render) or during programmatic scrolling\n // (scrollToIndex/scrollToOffset) where reconcileScroll needs sizes in the same frame.\n // During normal user scrolling, skip sync measurement — the RO callback handles it async.\n if (\n (!this.isScrolling || this.scrollState) &&\n this.shouldMeasureDuringScroll(index)\n ) {\n this.resizeItem(index, this.options.measureElement(node, undefined, this))\n }\n }\n\n resizeItem = (index: number, size: number) => {\n if (!this.isIndexInRange(index)) return\n\n // Fast field reads. For lanes===1 we read raw start/size from the flat\n // typed array, avoiding a Proxy.get + VirtualItem allocation per call.\n // For lanes>1 we fall back to the cached VirtualItem array.\n let cachedSize: number\n let itemStart: number\n let key: Key\n const flat = this._flatMeasurements\n if (this.options.lanes === 1 && flat !== null) {\n key = this.options.getItemKey(index)\n itemStart = flat[index * 2]!\n cachedSize = flat[index * 2 + 1]!\n } else {\n const item = this.measurementsCache[index]\n if (!item) return\n key = item.key\n itemStart = item.start\n cachedSize = item.size\n }\n\n const itemSize = this.itemSizeCache.get(key) ?? cachedSize\n const delta = size - itemSize\n\n if (delta !== 0) {\n const wasAtEnd =\n this.options.anchorTo === 'end' &&\n this.scrollState?.behavior !== 'smooth' &&\n this.getVirtualDistanceFromEnd() <= this.options.scrollEndThreshold\n const prevTotalSize = wasAtEnd ? this.getTotalSize() : 0\n // Default anchoring predicate (used unless the consumer supplies a\n // custom shouldAdjustScrollPositionOnItemSizeChange).\n const scrollOffsetWithAdj =\n this.getScrollOffset() + this.scrollAdjustments\n const isFirstMeasure = !this.itemSizeCache.has(key)\n const defaultShouldAdjust = isFirstMeasure\n ? // First measurement: compensate any item whose top sits above the\n // fold — the estimate→actual delta must be corrected regardless of\n // scroll direction, since the whole estimated block was above it.\n itemStart < scrollOffsetWithAdj\n : // Re-measurement: only compensate an item that is ENTIRELY above the\n // fold. An item that merely *spans* the fold (top above, bottom\n // below — e.g. a streaming chat message growing at its bottom)\n // changes size *below* the anchor point, so shifting scrollTop by the\n // delta would drag the viewport downward on every growth (#1218).\n // Also skip during backward scroll to avoid the \"items jump while\n // scrolling up\" cascade.\n itemStart + itemSize <= scrollOffsetWithAdj &&\n this.scrollDirection !== 'backward'\n const shouldAdjustScroll =\n this.scrollState?.behavior !== 'smooth' &&\n (this.shouldAdjustScrollPositionOnItemSizeChange !== undefined\n ? this.shouldAdjustScrollPositionOnItemSizeChange(\n // The callback expects a VirtualItem; build one lazily only\n // when the consumer actually supplied a custom predicate.\n this.measurementsCache[index] ?? {\n index,\n key,\n start: itemStart,\n size: cachedSize,\n end: itemStart + cachedSize,\n lane: 0,\n },\n delta,\n this,\n )\n : defaultShouldAdjust)\n\n if (this.pendingMin === null || index < this.pendingMin) {\n this.pendingMin = index\n }\n this.itemSizeCache.set(key, size)\n this.itemSizeCacheVersion++\n\n let adjustedSync = false\n if (wasAtEnd) {\n adjustedSync = this.applyScrollAdjustment(\n this.getTotalSize() - prevTotalSize,\n )\n } else if (shouldAdjustScroll) {\n adjustedSync = this.applyScrollAdjustment(delta)\n }\n\n // When we just moved `scrollTop` to compensate for an above-viewport\n // resize, the grown item transforms must commit in the SAME frame as\n // that write. `applyScrollAdjustment` writes `scrollTop` synchronously\n // inside this ResizeObserver callback, but an async `notify` schedules\n // the transform render for a later commit — so the browser can paint\n // one frame with the new `scrollTop` and the old positions, and the\n // viewport visibly jumps by `delta` before snapping back (#1227). A\n // synchronous notify flushes the render in this same callback, so both\n // land in one paint. When nothing moved (or the write was deferred on\n // iOS), keep the cheaper async notify.\n this.notify(adjustedSync)\n }\n }\n\n getVirtualItems = memo(\n () => [this.getVirtualIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: Array<VirtualItem> = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getVirtualItems',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualItemForOffset = (offset: number) => {\n const measurements = this.getMeasurements()\n if (measurements.length === 0) {\n return undefined\n }\n // Same fast-path as calculateRange: read start values directly from the\n // typed array during binary search to skip the Proxy.get materialization\n // per probe.\n const flat = this._flatMeasurements\n const useFlat = this.options.lanes === 1 && flat != null\n const idx = findNearestBinarySearch(\n 0,\n measurements.length - 1,\n useFlat\n ? (i: number) => flat[i * 2]!\n : (i: number) => notUndefined(measurements[i]).start,\n offset,\n )\n return notUndefined(measurements[idx])\n }\n\n private getMaxScrollOffset = () => {\n if (!this.scrollElement) return 0\n\n if ('scrollHeight' in this.scrollElement) {\n // Element\n return this.options.horizontal\n ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth\n : this.scrollElement.scrollHeight - this.scrollElement.clientHeight\n } else {\n // Window\n const doc = this.scrollElement.document.documentElement\n return this.options.horizontal\n ? doc.scrollWidth - this.scrollElement.innerWidth\n : doc.scrollHeight - this.scrollElement.innerHeight\n }\n }\n\n private getVirtualDistanceFromEnd = () => {\n return Math.max(\n this.getTotalSize() - this.getSize() - this.getScrollOffset(),\n 0,\n )\n }\n\n getDistanceFromEnd = () => {\n return Math.max(this.getMaxScrollOffset() - this.getScrollOffset(), 0)\n }\n\n isAtEnd = (threshold = this.options.scrollEndThreshold) => {\n return this.getDistanceFromEnd() <= threshold\n }\n\n getOffsetForAlignment = (\n toOffset: number,\n align: ScrollAlignment,\n itemSize = 0,\n ) => {\n if (!this.scrollElement) return 0\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n if (align === 'auto') {\n align = toOffset >= scrollOffset + size ? 'end' : 'start'\n }\n\n if (align === 'center') {\n // When aligning to a particular item (e.g. with scrollToIndex),\n // adjust offset by the size of the item to center on the item\n toOffset += (itemSize - size) / 2\n } else if (align === 'end') {\n toOffset -= size\n }\n\n const maxOffset = this.getMaxScrollOffset()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const size = this.getSize()\n const scrollOffset = this.getScrollOffset()\n\n const item = this.measurementsCache[index]\n if (!item) return\n\n if (align === 'auto') {\n if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {\n align = 'end'\n } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {\n align = 'start'\n } else {\n return [scrollOffset, align] as const\n }\n }\n\n // For the last item with 'end' alignment, use browser's actual max scroll\n // to account for borders/padding that aren't in our measurements\n if (align === 'end' && index === this.options.count - 1) {\n return [this.getMaxScrollOffset(), align] as const\n }\n\n const toOffset =\n align === 'end'\n ? item.end + this.options.scrollPaddingEnd\n : item.start - this.options.scrollPaddingStart\n\n return [\n this.getOffsetForAlignment(toOffset, align, item.size),\n align,\n ] as const\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n // An absolute scroll command derives its target from current\n // measurements, so any iOS-deferred compensation still pending is stale by\n // definition — the command already accounts for the measurements the delta\n // was compensating for. Drop it so _flushIosDeferredIfReady doesn't replay\n // it onto the just-established position (relative commands like scrollBy\n // intentionally keep the deferral, since they build on the current offset).\n this._iosDeferredAdjustment = 0\n\n const offset = this.getOffsetForAlignment(toOffset, align)\n\n const now = this.now()\n this.scrollState = {\n index: null,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollToIndex = (\n index: number,\n {\n align: initialAlign = 'auto',\n behavior = 'auto',\n }: ScrollToIndexOptions = {},\n ) => {\n // See scrollToOffset: an absolute target invalidates any pending\n // iOS-deferred compensation.\n this._iosDeferredAdjustment = 0\n\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const offsetInfo = this.getOffsetForIndex(index, initialAlign)\n if (!offsetInfo) {\n return\n }\n const [offset, align] = offsetInfo\n\n const now = this.now()\n this.scrollState = {\n index,\n align,\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollBy = (\n delta: number,\n { behavior = 'auto' }: ScrollToOffsetOptions = {},\n ) => {\n const offset = this.getScrollOffset() + delta\n const now = this.now()\n\n this.scrollState = {\n index: null,\n align: 'start',\n behavior,\n startedAt: now,\n lastTargetOffset: offset,\n stableFrames: 0,\n }\n\n this._scrollToOffset(offset, { adjustments: undefined, behavior })\n\n this.scheduleScrollReconcile()\n }\n\n scrollToEnd = ({ behavior = 'auto' }: ScrollToEndOptions = {}) => {\n if (this.options.count > 0) {\n this.scrollToIndex(this.options.count - 1, {\n align: 'end',\n behavior,\n })\n return\n }\n\n this.scrollToOffset(Math.max(this.getTotalSize() - this.getSize(), 0), {\n behavior,\n })\n }\n\n getTotalSize = () => {\n const measurements = this.getMeasurements()\n\n let end: number\n // If there are no measurements, set the end to paddingStart\n // If there is only one lane, use the last measurement's end\n // Otherwise find the maximum end value among all measurements\n if (measurements.length === 0) {\n end = this.options.paddingStart\n } else if (this.options.lanes === 1) {\n // Fast path: read last item's end directly from the flat typed array\n // when available; avoids a Proxy.get + VirtualItem materialization\n // just to call getTotalSize (which React renders trigger every commit).\n const lastIdx = measurements.length - 1\n const flat = this._flatMeasurements\n if (flat != null) {\n end = flat[lastIdx * 2]! + flat[lastIdx * 2 + 1]!\n } else {\n end = measurements[lastIdx]?.end ?? 0\n }\n } else {\n const endByLane = Array<number | null>(this.options.lanes).fill(null)\n let endIndex = measurements.length - 1\n while (endIndex >= 0 && endByLane.some((val) => val === null)) {\n const item = measurements[endIndex]!\n if (endByLane[item.lane] === null) {\n endByLane[item.lane] = item.end\n }\n\n endIndex--\n }\n\n end = Math.max(...endByLane.filter((val): val is number => val !== null))\n }\n\n return Math.max(\n end - this.options.scrollMargin + this.options.paddingEnd,\n 0,\n )\n }\n\n /**\n * Returns a snapshot of currently-measured items suitable for round-\n * tripping through state storage (sessionStorage, history, etc.) and\n * passing back as `initialMeasurementsCache` on remount. Pair with the\n * current `scrollOffset` to restore exact scroll position after navigation.\n *\n * Only items the consumer has actually rendered (and thus measured) appear\n * in the snapshot; unmeasured items will fall back to `estimateSize` on\n * restore. Returns an empty array if no items have been measured.\n */\n takeSnapshot = (): Array<VirtualItem> => {\n const snapshot: Array<VirtualItem> = []\n if (this.itemSizeCache.size === 0) return snapshot\n // Iterate measurementsCache only for indices whose key is in itemSizeCache\n // (i.e., have been measured). We build VirtualItem objects with the\n // current start/size/end so they can be persisted as plain data.\n const m = this.getMeasurements()\n for (const item of m) {\n if (item && this.itemSizeCache.has(item.key)) {\n // Force materialization (lazy path) and copy plain fields.\n snapshot.push({\n index: item.index,\n key: item.key,\n start: item.start,\n size: item.size,\n end: item.end,\n lane: item.lane,\n })\n }\n }\n return snapshot\n }\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n // Record the intended logical scroll target so the next scroll event\n // can reconcile against subpixel rounding by the browser.\n this._intendedScrollOffset = offset + (adjustments ?? 0)\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n // Reset pendingMin so the next getMeasurements rebuilds from index 0.\n // Without this, a prior resizeItem() that left pendingMin > 0 would\n // cause the rebuild to preserve stale items before that index.\n this.pendingMin = null\n this.itemSizeCache.clear()\n this.laneAssignments.clear() // Clear lane cache for full re-layout\n this.itemSizeCacheVersion++\n this.notify(false)\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\n// Monomorphic Float64Array variant — reads start values directly at stride\n// 2 instead of through a getter closure. JITs the inner load to a typed-\n// array bounds-check + load with no indirect call.\nfunction findNearestBinarySearchFlat(\n flat: Float64Array,\n high: number,\n value: number,\n) {\n let low = 0\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = flat[middle * 2]!\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n return low > 0 ? low - 1 : 0\n}\n\nfunction calculateRangeImpl(\n measurements: Array<VirtualItem>,\n outerSize: number,\n scrollOffset: number,\n lanes: number,\n flat: Float64Array | null,\n) {\n const lastIndex = measurements.length - 1\n\n // handle case when item count is less than or equal to lanes\n if (measurements.length <= lanes) {\n return { startIndex: 0, endIndex: lastIndex }\n }\n\n if (lanes === 1 && flat !== null) {\n // Hot single-lane path: typed-array reads, no closures, no Proxy traps.\n const startIndex = findNearestBinarySearchFlat(\n flat,\n lastIndex,\n scrollOffset,\n )\n let endIndex = startIndex\n const limit = scrollOffset + outerSize\n while (\n endIndex < lastIndex &&\n flat[endIndex * 2]! + flat[endIndex * 2 + 1]! < limit\n ) {\n endIndex++\n }\n return { startIndex, endIndex }\n }\n\n // Fallback (lanes > 1 or no flat array): closure-based reads.\n const getStart = (index: number) => measurements[index]!.start\n let startIndex = findNearestBinarySearch(0, lastIndex, getStart, scrollOffset)\n let endIndex = startIndex\n\n if (lanes === 1) {\n while (\n endIndex < lastIndex &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n } else if (lanes > 1) {\n // Expand forward until we include the visible items from all lanes\n // which are closer to the end of the virtualizer window\n const endPerLane = Array(lanes).fill(0)\n while (\n endIndex < lastIndex &&\n endPerLane.some((pos) => pos < scrollOffset + outerSize)\n ) {\n const item = measurements[endIndex]!\n endPerLane[item.lane] = item.end\n endIndex++\n }\n\n // Expand backward until we include all lanes' visible items\n // closer to the top\n const startPerLane = Array(lanes).fill(scrollOffset + outerSize)\n while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {\n const item = measurements[startIndex]!\n startPerLane[item.lane] = item.start\n startIndex--\n }\n\n // Align startIndex to the beginning of its lane\n startIndex = Math.max(0, startIndex - (startIndex % lanes))\n // Align endIndex to the end of its lane\n endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - (endIndex % lanes)))\n }\n\n return { startIndex, endIndex }\n}\n","import * as React from 'react'\nimport { flushSync } from 'react-dom'\nimport {\n Virtualizer,\n elementScroll,\n observeElementOffset,\n observeElementRect,\n observeWindowOffset,\n observeWindowRect,\n windowScroll,\n} from '@tanstack/virtual-core'\nimport type { PartialKeys, VirtualizerOptions } from '@tanstack/virtual-core'\n\nexport * from '@tanstack/virtual-core'\n\nconst useIsomorphicLayoutEffect =\n typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\nexport type ReactVirtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> = Virtualizer<TScrollElement, TItemElement> & {\n /**\n * Ref callback for the inner size container element. Only meaningful when\n * `directDomUpdates: true` — the virtualizer writes the container's\n * main-axis size (`height` or `width`) directly to skip React re-renders.\n */\n containerRef: (node: HTMLElement | null) => void\n}\n\nexport type ReactVirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> = VirtualizerOptions<TScrollElement, TItemElement> & {\n useFlushSync?: boolean\n /**\n * Skip React re-renders for scroll-only updates. The virtualizer writes\n * item positions (`top`/`left`) and the container size (`height`/`width`)\n * directly to the DOM, and only re-renders when the visible index range\n * or `isScrolling` changes.\n *\n * Requirements when enabled:\n * - Item elements must be `position: absolute`; in `'transform'` mode they\n * must also be anchored with `top: 0` / `left: 0`.\n * - Item elements must NOT set the main-axis position in their style — the\n * virtualizer owns `top` / `left` in `'position'` mode and `transform` in\n * `'transform'` mode.\n * - The inner size container must receive `virtualizer.containerRef` and\n * must NOT set `height` / `width` in its style.\n * - For multi-lane layouts (grids / masonry), the cross-axis position\n * (e.g. `left: ${(item.lane * 100) / lanes}%`) is stable per item and\n * must still be set in your JSX — only the main axis is automated.\n *\n * This flag is intended to be set once at mount. Toggling it (or\n * `directDomUpdatesMode`) at runtime can leave stale inline styles on\n * items and the container.\n */\n directDomUpdates?: boolean\n /**\n * How `directDomUpdates` positions item elements.\n * - `'transform'` (default): writes `transform: translate3d(...)`.\n * Promotes items to their own compositor layer — usually smoother on long\n * lists, but creates a stacking context and can interfere with\n * `position: fixed` descendants. Item elements must still be anchored with\n * `position: absolute`, `top: 0`, and `left: 0`.\n * - `'position'`: writes `top` / `left`. Item elements must be\n * `position: absolute`.\n */\n directDomUpdatesMode?: 'position' | 'transform'\n}\n\nfunction useVirtualizerBase<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n>({\n useFlushSync = true,\n directDomUpdates = false,\n directDomUpdatesMode = 'transform',\n ...options\n}: ReactVirtualizerOptions<TScrollElement, TItemElement>): ReactVirtualizer<\n TScrollElement,\n TItemElement\n> {\n const rerender = React.useReducer((x: number) => x + 1, 0)[1]\n\n // Mutable across renders so the onChange closure captured by setOptions\n // always reads the latest values without us having to re-create it.\n const directRef = React.useRef({\n enabled: directDomUpdates,\n mode: directDomUpdatesMode,\n container: null as HTMLElement | null,\n lastSize: null as number | null,\n // Keyed by the element itself so a remounted node (same key, new DOM\n // node — e.g. when `enabled` is toggled off then on) is treated as fresh\n // and gets its style written.\n lastPositions: new WeakMap<HTMLElement, number>(),\n prevRange: null as {\n startIndex: number\n endIndex: number\n isScrolling: boolean\n } | null,\n })\n directRef.current.enabled = directDomUpdates\n directRef.current.mode = directDomUpdatesMode\n\n // Writes the size container's total extent to the DOM. Idempotent — guarded\n // by lastSize. Split out from applyDirectStyles so it can run *before* the\n // scroll-position sync in the _willUpdate effect: an end-anchored prepend\n // grows the total and bumps scrollOffset in the same pass, and if scrollTop\n // is written before the container has grown the browser clamps it to the\n // stale (shorter) scrollHeight, leaving a gap at the top until the next\n // scroll (visible only in directDomUpdates mode — React-rendered sizers get\n // their height during render).\n const applyContainerSize = (\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => {\n const state = directRef.current\n if (!state.enabled || !state.container) return\n\n const totalSize = instance.getTotalSize()\n if (totalSize !== state.lastSize) {\n state.lastSize = totalSize\n const sizeAxis = instance.options.horizontal ? 'width' : 'height'\n state.container.style[sizeAxis] = `${totalSize}px`\n }\n }\n\n // Writes container size + item positions to the DOM. Idempotent — guarded\n // by lastSize / lastPositions. Called from onChange (covers scroll-driven\n // updates) and from a layout effect (covers post-render commits when refs\n // have just registered new items in elementsCache).\n const applyDirectStyles = (\n instance: Virtualizer<TScrollElement, TItemElement>,\n ) => {\n const state = directRef.current\n if (!state.enabled || !state.container) return\n\n applyContainerSize(instance)\n\n const horizontal = !!instance.options.horizontal\n const useTransform = state.mode === 'transform'\n const posAxis = horizontal ? 'left' : 'top'\n const scrollMargin = instance.options.scrollMargin\n const items = instance.getVirtualItems()\n for (const item of items) {\n const next = item.start - scrollMargin\n const el = instance.elementsCache.get(item.key) as HTMLElement | undefined\n if (!el) continue\n if (state.lastPositions.get(el) === next) continue\n state.lastPositions.set(el, next)\n if (useTransform) {\n el.style.transform = horizontal\n ? `translate3d(${next}px, 0, 0)`\n : `translate3d(0, ${next}px, 0)`\n } else {\n el.style[posAxis] = `${next}px`\n }\n }\n }\n\n const resolvedOptions: VirtualizerOptions<TScrollElement, TItemElement> = {\n ...options,\n onChange: (instance, sync) => {\n const state = directRef.current\n let shouldRerender = true\n\n if (state.enabled) {\n applyDirectStyles(instance)\n\n // Only re-render on range / isScrolling changes\n const range = instance.range\n const prev = state.prevRange\n shouldRerender =\n !prev ||\n prev.isScrolling !== instance.isScrolling ||\n prev.startIndex !== range?.startIndex ||\n prev.endIndex !== range?.endIndex\n if (shouldRerender) {\n state.prevRange = range\n ? {\n startIndex: range.startIndex,\n endIndex: range.endIndex,\n isScrolling: instance.isScrolling,\n }\n : null\n }\n }\n\n if (shouldRerender) {\n if (useFlushSync && sync) {\n flushSync(rerender)\n } else {\n rerender()\n }\n }\n\n options.onChange?.(instance, sync)\n },\n }\n\n const [instance] = React.useState(() => {\n const v = new Virtualizer<TScrollElement, TItemElement>(resolvedOptions)\n return Object.assign(v, {\n containerRef: (node: HTMLElement | null) => {\n const state = directRef.current\n state.container = node\n state.lastSize = null\n if (node && state.enabled) {\n const total = v.getTotalSize()\n state.lastSize = total\n const axis = v.options.horizontal ? 'width' : 'height'\n node.style[axis] = `${total}px`\n }\n },\n })\n })\n\n instance.setOptions(resolvedOptions)\n\n useIsomorphicLayoutEffect(() => {\n return instance._didMount()\n }, [])\n\n useIsomorphicLayoutEffect(() => {\n // Grow the size container to the new total BEFORE _willUpdate syncs the\n // scroll position. On an end-anchored prepend the scroll target lands at\n // the new bottom; if the container is still at its old (shorter) height the\n // browser clamps the scrollTop write and the list is left with a gap at the\n // top until the next scroll. Positions are written afterwards by the\n // applyDirectStyles effect below.\n applyContainerSize(instance)\n return instance._willUpdate()\n })\n\n // After every render commit, newly mounted item refs have registered in\n // elementsCache; write their positions to the DOM so the user doesn't see\n // them at (0, 0) until the next onChange.\n useIsomorphicLayoutEffect(() => {\n applyDirectStyles(instance)\n })\n\n return instance\n}\n\nexport function useVirtualizer<\n TScrollElement extends Element,\n TItemElement extends Element,\n>(\n options: PartialKeys<\n ReactVirtualizerOptions<TScrollElement, TItemElement>,\n 'observeElementRect' | 'observeElementOffset' | 'scrollToFn'\n >,\n): ReactVirtualizer<TScrollElement, TItemElement> {\n return useVirtualizerBase<TScrollElement, TItemElement>({\n observeElementRect: observeElementRect,\n observeElementOffset: observeElementOffset,\n scrollToFn: elementScroll,\n ...options,\n })\n}\n\nexport function useWindowVirtualizer<TItemElement extends Element>(\n options: PartialKeys<\n ReactVirtualizerOptions<Window, TItemElement>,\n | 'getScrollElement'\n | 'observeElementRect'\n | 'observeElementOffset'\n | 'scrollToFn'\n >,\n): ReactVirtualizer<Window, TItemElement> {\n return useVirtualizerBase<Window, TItemElement>({\n getScrollElement: () => (typeof document !== 'undefined' ? window : null),\n observeElementRect: observeWindowRect,\n observeElementOffset: observeWindowOffset,\n scrollToFn: windowScroll,\n initialOffset: () => (typeof document !== 'undefined' ? window.scrollY : 0),\n ...options,\n })\n}\n"],"mappings":"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","names":["useRef","opts","key","startIndex","endIndex","instance","useRef"]}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/components/Popover/Popover.component.tsx
|
|
2
|
+
var _react = require('react');
|
|
3
|
+
var _reactdom = require('react-dom');
|
|
4
|
+
var _lucidereact = require('lucide-react');
|
|
5
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
6
|
+
var Popover = ({
|
|
7
|
+
trigger,
|
|
8
|
+
children,
|
|
9
|
+
title,
|
|
10
|
+
placement: preferredPlacement = "bottom",
|
|
11
|
+
showCloseButton = false,
|
|
12
|
+
closeOnClickOutside = true,
|
|
13
|
+
closeOnEscape = true,
|
|
14
|
+
disabled = false,
|
|
15
|
+
isOpen,
|
|
16
|
+
defaultOpen,
|
|
17
|
+
onOpenChange,
|
|
18
|
+
maxWidth = 320,
|
|
19
|
+
className,
|
|
20
|
+
contentClassName
|
|
21
|
+
}) => {
|
|
22
|
+
const isControlled = isOpen !== void 0;
|
|
23
|
+
const [localOpen, setLocalOpen] = _react.useState.call(void 0, _nullishCoalesce(defaultOpen, () => ( false)));
|
|
24
|
+
const isVisible = isControlled ? isOpen : localOpen;
|
|
25
|
+
const [popoverState, setPopoverState] = _react.useState.call(void 0, {
|
|
26
|
+
isVisible: false,
|
|
27
|
+
isPositioned: false,
|
|
28
|
+
position: { top: 0, left: 0, placement: preferredPlacement }
|
|
29
|
+
});
|
|
30
|
+
const triggerRef = _react.useRef.call(void 0, null);
|
|
31
|
+
const contentRef = _react.useRef.call(void 0, null);
|
|
32
|
+
const timeoutRef = _react.useRef.call(void 0, void 0);
|
|
33
|
+
const animationFrameRef = _react.useRef.call(void 0, void 0);
|
|
34
|
+
const isScrollingRef = _react.useRef.call(void 0, false);
|
|
35
|
+
const open = _react.useCallback.call(void 0, () => {
|
|
36
|
+
if (disabled) return;
|
|
37
|
+
if (!isControlled) setLocalOpen(true);
|
|
38
|
+
_optionalChain([onOpenChange, 'optionalCall', _ => _(true)]);
|
|
39
|
+
}, [disabled, isControlled, onOpenChange]);
|
|
40
|
+
const close = _react.useCallback.call(void 0, () => {
|
|
41
|
+
if (!isControlled) setLocalOpen(false);
|
|
42
|
+
_optionalChain([onOpenChange, 'optionalCall', _2 => _2(false)]);
|
|
43
|
+
}, [isControlled, onOpenChange]);
|
|
44
|
+
const toggle = _react.useCallback.call(void 0, () => {
|
|
45
|
+
if (isVisible) {
|
|
46
|
+
close();
|
|
47
|
+
} else {
|
|
48
|
+
open();
|
|
49
|
+
}
|
|
50
|
+
}, [isVisible, open, close]);
|
|
51
|
+
const calculateOptimalPosition = _react.useCallback.call(void 0,
|
|
52
|
+
(triggerRect, contentRect) => {
|
|
53
|
+
const viewportWidth = window.innerWidth;
|
|
54
|
+
const viewportHeight = window.innerHeight;
|
|
55
|
+
const gap = 8;
|
|
56
|
+
let placement = preferredPlacement;
|
|
57
|
+
let top = 0;
|
|
58
|
+
let left = 0;
|
|
59
|
+
switch (preferredPlacement) {
|
|
60
|
+
case "top":
|
|
61
|
+
top = triggerRect.top - contentRect.height - gap;
|
|
62
|
+
left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;
|
|
63
|
+
break;
|
|
64
|
+
case "bottom":
|
|
65
|
+
top = triggerRect.bottom + gap;
|
|
66
|
+
left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;
|
|
67
|
+
break;
|
|
68
|
+
case "left":
|
|
69
|
+
top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;
|
|
70
|
+
left = triggerRect.left - contentRect.width - gap;
|
|
71
|
+
break;
|
|
72
|
+
case "right":
|
|
73
|
+
top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;
|
|
74
|
+
left = triggerRect.right + gap;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
if (placement === "top" && top < gap) {
|
|
78
|
+
placement = "bottom";
|
|
79
|
+
top = triggerRect.bottom + gap;
|
|
80
|
+
left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;
|
|
81
|
+
} else if (placement === "bottom" && top + contentRect.height > viewportHeight - gap) {
|
|
82
|
+
placement = "top";
|
|
83
|
+
top = triggerRect.top - contentRect.height - gap;
|
|
84
|
+
left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;
|
|
85
|
+
} else if (placement === "left" && left < gap) {
|
|
86
|
+
placement = "right";
|
|
87
|
+
top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;
|
|
88
|
+
left = triggerRect.right + gap;
|
|
89
|
+
} else if (placement === "right" && left + contentRect.width > viewportWidth - gap) {
|
|
90
|
+
placement = "left";
|
|
91
|
+
top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;
|
|
92
|
+
left = triggerRect.left - contentRect.width - gap;
|
|
93
|
+
}
|
|
94
|
+
top = Math.max(gap, Math.min(top, viewportHeight - contentRect.height - gap));
|
|
95
|
+
left = Math.max(gap, Math.min(left, viewportWidth - contentRect.width - gap));
|
|
96
|
+
return { top, left, placement };
|
|
97
|
+
},
|
|
98
|
+
[preferredPlacement]
|
|
99
|
+
);
|
|
100
|
+
_react.useEffect.call(void 0, () => {
|
|
101
|
+
if (isVisible) {
|
|
102
|
+
setPopoverState((prev) => ({ ...prev, isVisible: true, isPositioned: false }));
|
|
103
|
+
} else {
|
|
104
|
+
setPopoverState((prev) => ({ ...prev, isVisible: false, isPositioned: false }));
|
|
105
|
+
}
|
|
106
|
+
}, [isVisible]);
|
|
107
|
+
_react.useEffect.call(void 0, () => {
|
|
108
|
+
if (popoverState.isVisible && !popoverState.isPositioned && contentRef.current && triggerRef.current) {
|
|
109
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
110
|
+
const contentRect = contentRef.current.getBoundingClientRect();
|
|
111
|
+
const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);
|
|
112
|
+
setPopoverState((prev) => ({
|
|
113
|
+
...prev,
|
|
114
|
+
position: { top, left, placement },
|
|
115
|
+
isPositioned: true
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
}, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);
|
|
119
|
+
const handleScroll = _react.useCallback.call(void 0, () => {
|
|
120
|
+
if (!popoverState.isVisible || !popoverState.isPositioned || isScrollingRef.current) return;
|
|
121
|
+
isScrollingRef.current = true;
|
|
122
|
+
animationFrameRef.current = requestAnimationFrame(() => {
|
|
123
|
+
if (triggerRef.current && contentRef.current) {
|
|
124
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
125
|
+
const contentRect = contentRef.current.getBoundingClientRect();
|
|
126
|
+
const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);
|
|
127
|
+
setPopoverState((prev) => ({
|
|
128
|
+
...prev,
|
|
129
|
+
position: { top, left, placement }
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
isScrollingRef.current = false;
|
|
133
|
+
});
|
|
134
|
+
}, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);
|
|
135
|
+
_react.useEffect.call(void 0, () => {
|
|
136
|
+
const handleResize = () => {
|
|
137
|
+
if (popoverState.isVisible && popoverState.isPositioned && contentRef.current && triggerRef.current) {
|
|
138
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
139
|
+
const contentRect = contentRef.current.getBoundingClientRect();
|
|
140
|
+
const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);
|
|
141
|
+
setPopoverState((prev) => ({
|
|
142
|
+
...prev,
|
|
143
|
+
position: { top, left, placement }
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
window.addEventListener("resize", handleResize);
|
|
148
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
149
|
+
}, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);
|
|
150
|
+
_react.useEffect.call(void 0, () => {
|
|
151
|
+
if (popoverState.isVisible) {
|
|
152
|
+
window.addEventListener("scroll", handleScroll, { passive: true });
|
|
153
|
+
document.body.addEventListener("scroll", handleScroll, { passive: true });
|
|
154
|
+
}
|
|
155
|
+
return () => {
|
|
156
|
+
window.removeEventListener("scroll", handleScroll);
|
|
157
|
+
document.body.removeEventListener("scroll", handleScroll);
|
|
158
|
+
};
|
|
159
|
+
}, [popoverState.isVisible, handleScroll]);
|
|
160
|
+
const handleClickOutside = _react.useCallback.call(void 0,
|
|
161
|
+
(event) => {
|
|
162
|
+
if (!closeOnClickOutside || !popoverState.isVisible) return;
|
|
163
|
+
const target = event.target;
|
|
164
|
+
if (_optionalChain([contentRef, 'access', _3 => _3.current, 'optionalAccess', _4 => _4.contains, 'call', _5 => _5(target)]) || _optionalChain([triggerRef, 'access', _6 => _6.current, 'optionalAccess', _7 => _7.contains, 'call', _8 => _8(target)])) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
close();
|
|
168
|
+
},
|
|
169
|
+
[closeOnClickOutside, popoverState.isVisible, close]
|
|
170
|
+
);
|
|
171
|
+
const handleEscapeKey = _react.useCallback.call(void 0,
|
|
172
|
+
(event) => {
|
|
173
|
+
if (closeOnEscape && event.key === "Escape" && popoverState.isVisible) {
|
|
174
|
+
close();
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
[closeOnEscape, popoverState.isVisible, close]
|
|
178
|
+
);
|
|
179
|
+
_react.useEffect.call(void 0, () => {
|
|
180
|
+
if (popoverState.isVisible) {
|
|
181
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
182
|
+
document.addEventListener("keydown", handleEscapeKey);
|
|
183
|
+
}
|
|
184
|
+
return () => {
|
|
185
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
186
|
+
document.removeEventListener("keydown", handleEscapeKey);
|
|
187
|
+
};
|
|
188
|
+
}, [popoverState.isVisible, handleClickOutside, handleEscapeKey]);
|
|
189
|
+
_react.useEffect.call(void 0, () => {
|
|
190
|
+
const timeoutId = timeoutRef.current;
|
|
191
|
+
const animationFrameId = animationFrameRef.current;
|
|
192
|
+
return () => {
|
|
193
|
+
if (timeoutId) {
|
|
194
|
+
clearTimeout(timeoutId);
|
|
195
|
+
}
|
|
196
|
+
if (animationFrameId) {
|
|
197
|
+
cancelAnimationFrame(animationFrameId);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}, []);
|
|
201
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
202
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
203
|
+
"div",
|
|
204
|
+
{
|
|
205
|
+
ref: triggerRef,
|
|
206
|
+
className: ["eidos-popover-trigger", className].filter(Boolean).join(" "),
|
|
207
|
+
onClick: toggle,
|
|
208
|
+
"aria-expanded": popoverState.isVisible,
|
|
209
|
+
"aria-haspopup": "dialog",
|
|
210
|
+
children: trigger
|
|
211
|
+
}
|
|
212
|
+
),
|
|
213
|
+
popoverState.isVisible && _reactdom.createPortal.call(void 0,
|
|
214
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
215
|
+
"div",
|
|
216
|
+
{
|
|
217
|
+
ref: contentRef,
|
|
218
|
+
role: "dialog",
|
|
219
|
+
"aria-modal": "false",
|
|
220
|
+
"aria-label": _nullishCoalesce(title, () => ( "Popover")),
|
|
221
|
+
className: [
|
|
222
|
+
"eidos-popover-content",
|
|
223
|
+
`eidos-popover-content--${popoverState.position.placement}`,
|
|
224
|
+
popoverState.isPositioned ? "eidos-popover-content--visible" : "",
|
|
225
|
+
contentClassName
|
|
226
|
+
].filter(Boolean).join(" "),
|
|
227
|
+
style: {
|
|
228
|
+
top: popoverState.position.top,
|
|
229
|
+
left: popoverState.position.left,
|
|
230
|
+
maxWidth
|
|
231
|
+
},
|
|
232
|
+
children: [
|
|
233
|
+
(title || showCloseButton) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "eidos-popover-header", children: [
|
|
234
|
+
title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "eidos-popover-title", children: title }),
|
|
235
|
+
showCloseButton && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
236
|
+
"button",
|
|
237
|
+
{
|
|
238
|
+
type: "button",
|
|
239
|
+
className: "eidos-popover-close",
|
|
240
|
+
onClick: close,
|
|
241
|
+
"aria-label": "Close popover",
|
|
242
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { "aria-hidden": "true" })
|
|
243
|
+
}
|
|
244
|
+
)
|
|
245
|
+
] }),
|
|
246
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "eidos-popover-body", children })
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
),
|
|
250
|
+
document.body
|
|
251
|
+
)
|
|
252
|
+
] });
|
|
253
|
+
};
|
|
254
|
+
Popover.displayName = "Popover";
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
exports.Popover = Popover;
|
|
259
|
+
//# sourceMappingURL=chunk-C7F2VFAI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/pedromealha/Documents/Repositories/Personal/eidos-ui/dist/chunk-C7F2VFAI.cjs","../src/components/Popover/Popover.component.tsx"],"names":[],"mappings":"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","file":"/Users/pedromealha/Documents/Repositories/Personal/eidos-ui/dist/chunk-C7F2VFAI.cjs","sourcesContent":[null,"import React, { useState, useRef, useCallback, useEffect } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { X } from 'lucide-react';\r\nimport type { PopoverProps, PopoverState, PopoverPlacement } from './Popover.types';\r\n\r\nexport const Popover: React.FC<PopoverProps> = ({\r\n trigger,\r\n children,\r\n title,\r\n placement: preferredPlacement = 'bottom',\r\n showCloseButton = false,\r\n closeOnClickOutside = true,\r\n closeOnEscape = true,\r\n disabled = false,\r\n isOpen,\r\n defaultOpen,\r\n onOpenChange,\r\n maxWidth = 320,\r\n className,\r\n contentClassName,\r\n}) => {\r\n // ── Controlled / uncontrolled bridge ──────────────────────────────────────\r\n const isControlled = isOpen !== undefined;\r\n const [localOpen, setLocalOpen] = useState(defaultOpen ?? false);\r\n const isVisible = isControlled ? isOpen! : localOpen;\r\n\r\n // ── Positioning state ─────────────────────────────────────────────────────\r\n const [popoverState, setPopoverState] = useState<PopoverState>({\r\n isVisible: false,\r\n isPositioned: false,\r\n position: { top: 0, left: 0, placement: preferredPlacement },\r\n });\r\n\r\n // ── Refs ──────────────────────────────────────────────────────────────────\r\n const triggerRef = useRef<HTMLDivElement>(null);\r\n const contentRef = useRef<HTMLDivElement>(null);\r\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\r\n const animationFrameRef = useRef<number | undefined>(undefined);\r\n const isScrollingRef = useRef(false);\r\n\r\n // ── Open / close helpers ──────────────────────────────────────────────────\r\n const open = useCallback(() => {\r\n if (disabled) return;\r\n if (!isControlled) setLocalOpen(true);\r\n onOpenChange?.(true);\r\n }, [disabled, isControlled, onOpenChange]);\r\n\r\n const close = useCallback(() => {\r\n if (!isControlled) setLocalOpen(false);\r\n onOpenChange?.(false);\r\n }, [isControlled, onOpenChange]);\r\n\r\n const toggle = useCallback(() => {\r\n if (isVisible) {\r\n close();\r\n } else {\r\n open();\r\n }\r\n }, [isVisible, open, close]);\r\n\r\n // ── Positioning calculation ───────────────────────────────────────────────\r\n const calculateOptimalPosition = useCallback(\r\n (triggerRect: DOMRect, contentRect: DOMRect) => {\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n const gap = 8;\r\n\r\n let placement: PopoverPlacement = preferredPlacement;\r\n let top = 0;\r\n let left = 0;\r\n\r\n switch (preferredPlacement) {\r\n case 'top':\r\n top = triggerRect.top - contentRect.height - gap;\r\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\r\n break;\r\n case 'bottom':\r\n top = triggerRect.bottom + gap;\r\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\r\n break;\r\n case 'left':\r\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\r\n left = triggerRect.left - contentRect.width - gap;\r\n break;\r\n case 'right':\r\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\r\n left = triggerRect.right + gap;\r\n break;\r\n }\r\n\r\n // Flip if it doesn't fit in the preferred direction\r\n if (placement === 'top' && top < gap) {\r\n placement = 'bottom';\r\n top = triggerRect.bottom + gap;\r\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\r\n } else if (placement === 'bottom' && top + contentRect.height > viewportHeight - gap) {\r\n placement = 'top';\r\n top = triggerRect.top - contentRect.height - gap;\r\n left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2;\r\n } else if (placement === 'left' && left < gap) {\r\n placement = 'right';\r\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\r\n left = triggerRect.right + gap;\r\n } else if (placement === 'right' && left + contentRect.width > viewportWidth - gap) {\r\n placement = 'left';\r\n top = triggerRect.top + triggerRect.height / 2 - contentRect.height / 2;\r\n left = triggerRect.left - contentRect.width - gap;\r\n }\r\n\r\n // Clamp to viewport\r\n top = Math.max(gap, Math.min(top, viewportHeight - contentRect.height - gap));\r\n left = Math.max(gap, Math.min(left, viewportWidth - contentRect.width - gap));\r\n\r\n return { top, left, placement };\r\n },\r\n [preferredPlacement],\r\n );\r\n\r\n // ── Sync isVisible → popoverState ─────────────────────────────────────────\r\n useEffect(() => {\r\n if (isVisible) {\r\n setPopoverState((prev) => ({ ...prev, isVisible: true, isPositioned: false }));\r\n } else {\r\n setPopoverState((prev) => ({ ...prev, isVisible: false, isPositioned: false }));\r\n }\r\n }, [isVisible]);\r\n\r\n // ── Two-pass positioning (Pass 2: measure then commit) ────────────────────\r\n useEffect(() => {\r\n if (\r\n popoverState.isVisible &&\r\n !popoverState.isPositioned &&\r\n contentRef.current &&\r\n triggerRef.current\r\n ) {\r\n const triggerRect = triggerRef.current.getBoundingClientRect();\r\n const contentRect = contentRef.current.getBoundingClientRect();\r\n\r\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\r\n\r\n setPopoverState((prev) => ({\r\n ...prev,\r\n position: { top, left, placement },\r\n isPositioned: true,\r\n }));\r\n }\r\n }, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);\r\n\r\n // ── Scroll repositioning ─────────────────────────────────────────────────\r\n const handleScroll = useCallback(() => {\r\n if (!popoverState.isVisible || !popoverState.isPositioned || isScrollingRef.current) return;\r\n\r\n isScrollingRef.current = true;\r\n\r\n animationFrameRef.current = requestAnimationFrame(() => {\r\n if (triggerRef.current && contentRef.current) {\r\n const triggerRect = triggerRef.current.getBoundingClientRect();\r\n const contentRect = contentRef.current.getBoundingClientRect();\r\n\r\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\r\n\r\n setPopoverState((prev) => ({\r\n ...prev,\r\n position: { top, left, placement },\r\n }));\r\n }\r\n\r\n isScrollingRef.current = false;\r\n });\r\n }, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);\r\n\r\n // ── Resize repositioning ──────────────────────────────────────────────────\r\n useEffect(() => {\r\n const handleResize = () => {\r\n if (\r\n popoverState.isVisible &&\r\n popoverState.isPositioned &&\r\n contentRef.current &&\r\n triggerRef.current\r\n ) {\r\n const triggerRect = triggerRef.current.getBoundingClientRect();\r\n const contentRect = contentRef.current.getBoundingClientRect();\r\n\r\n const { top, left, placement } = calculateOptimalPosition(triggerRect, contentRect);\r\n\r\n setPopoverState((prev) => ({\r\n ...prev,\r\n position: { top, left, placement },\r\n }));\r\n }\r\n };\r\n\r\n window.addEventListener('resize', handleResize);\r\n return () => window.removeEventListener('resize', handleResize);\r\n }, [popoverState.isVisible, popoverState.isPositioned, calculateOptimalPosition]);\r\n\r\n // ── Scroll listener registration ─────────────────────────────────────────\r\n useEffect(() => {\r\n if (popoverState.isVisible) {\r\n window.addEventListener('scroll', handleScroll, { passive: true });\r\n document.body.addEventListener('scroll', handleScroll, { passive: true });\r\n }\r\n\r\n return () => {\r\n window.removeEventListener('scroll', handleScroll);\r\n document.body.removeEventListener('scroll', handleScroll);\r\n };\r\n }, [popoverState.isVisible, handleScroll]);\r\n\r\n // ── Click-outside handler ─────────────────────────────────────────────────\r\n const handleClickOutside = useCallback(\r\n (event: MouseEvent) => {\r\n if (!closeOnClickOutside || !popoverState.isVisible) return;\r\n\r\n const target = event.target as Node;\r\n\r\n if (contentRef.current?.contains(target) || triggerRef.current?.contains(target)) {\r\n return;\r\n }\r\n\r\n close();\r\n },\r\n [closeOnClickOutside, popoverState.isVisible, close],\r\n );\r\n\r\n // ── Escape key handler ────────────────────────────────────────────────────\r\n const handleEscapeKey = useCallback(\r\n (event: KeyboardEvent) => {\r\n if (closeOnEscape && event.key === 'Escape' && popoverState.isVisible) {\r\n close();\r\n }\r\n },\r\n [closeOnEscape, popoverState.isVisible, close],\r\n );\r\n\r\n // ── Register global event listeners ──────────────────────────────────────\r\n useEffect(() => {\r\n if (popoverState.isVisible) {\r\n document.addEventListener('mousedown', handleClickOutside);\r\n document.addEventListener('keydown', handleEscapeKey);\r\n }\r\n\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside);\r\n document.removeEventListener('keydown', handleEscapeKey);\r\n };\r\n }, [popoverState.isVisible, handleClickOutside, handleEscapeKey]);\r\n\r\n // ── Cleanup on unmount ────────────────────────────────────────────────────\r\n useEffect(() => {\r\n const timeoutId = timeoutRef.current;\r\n const animationFrameId = animationFrameRef.current;\r\n return () => {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n if (animationFrameId) {\r\n cancelAnimationFrame(animationFrameId);\r\n }\r\n };\r\n }, []);\r\n\r\n // ── Render ────────────────────────────────────────────────────────────────\r\n return (\r\n <>\r\n {/* Trigger wrapper */}\r\n <div\r\n ref={triggerRef}\r\n className={['eidos-popover-trigger', className].filter(Boolean).join(' ')}\r\n onClick={toggle}\r\n aria-expanded={popoverState.isVisible}\r\n aria-haspopup=\"dialog\"\r\n >\r\n {trigger}\r\n </div>\r\n\r\n {/* Portal: floating panel */}\r\n {popoverState.isVisible &&\r\n createPortal(\r\n <div\r\n ref={contentRef}\r\n role=\"dialog\"\r\n aria-modal=\"false\"\r\n aria-label={title ?? 'Popover'}\r\n className={[\r\n 'eidos-popover-content',\r\n `eidos-popover-content--${popoverState.position.placement}`,\r\n popoverState.isPositioned ? 'eidos-popover-content--visible' : '',\r\n contentClassName,\r\n ]\r\n .filter(Boolean)\r\n .join(' ')}\r\n style={{\r\n top: popoverState.position.top,\r\n left: popoverState.position.left,\r\n maxWidth: maxWidth,\r\n }}\r\n >\r\n {(title || showCloseButton) && (\r\n <div className=\"eidos-popover-header\">\r\n {title && <span className=\"eidos-popover-title\">{title}</span>}\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"eidos-popover-close\"\r\n onClick={close}\r\n aria-label=\"Close popover\"\r\n >\r\n <X aria-hidden=\"true\" />\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n <div className=\"eidos-popover-body\">{children}</div>\r\n </div>,\r\n document.body,\r\n )}\r\n </>\r\n );\r\n};\r\n\r\nPopover.displayName = 'Popover';\r\n"]}
|