@techzyapp/ui-library 1.0.50 → 1.0.51
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/dist/{AdminRoot-MEfy9xtz.cjs → AdminRoot-CFDMjB1A.cjs} +2 -2
- package/dist/{AdminRoot-MEfy9xtz.cjs.map → AdminRoot-CFDMjB1A.cjs.map} +1 -1
- package/dist/{AdminRoot-C5l8PIyi.js → AdminRoot-D4GGvprQ.js} +8 -8
- package/dist/{AdminRoot-C5l8PIyi.js.map → AdminRoot-D4GGvprQ.js.map} +1 -1
- package/dist/{Alert--ZnlCjaL.cjs → Alert-CC4gxX9w.cjs} +2 -2
- package/dist/{Alert--ZnlCjaL.cjs.map → Alert-CC4gxX9w.cjs.map} +1 -1
- package/dist/{Alert-BVs-GcZQ.js → Alert-D56N-LeR.js} +3 -3
- package/dist/{Alert-BVs-GcZQ.js.map → Alert-D56N-LeR.js.map} +1 -1
- package/dist/{AuthGuard-DJ_mMwfg.js → AuthGuard-D6_sTASu.js} +2 -2
- package/dist/{AuthGuard-DJ_mMwfg.js.map → AuthGuard-D6_sTASu.js.map} +1 -1
- package/dist/{AuthGuard-Cm-tqCto.cjs → AuthGuard-DM1nDTE5.cjs} +2 -2
- package/dist/{AuthGuard-Cm-tqCto.cjs.map → AuthGuard-DM1nDTE5.cjs.map} +1 -1
- package/dist/BottomSheet-0oqSWjBx.js +646 -0
- package/dist/BottomSheet-0oqSWjBx.js.map +1 -0
- package/dist/BottomSheet-BWTYMGOU.cjs +2 -0
- package/dist/BottomSheet-BWTYMGOU.cjs.map +1 -0
- package/dist/{Breadcrumbs-HGk4DKrc.js → Breadcrumbs-BEcEVdRt.js} +3 -3
- package/dist/{Breadcrumbs-HGk4DKrc.js.map → Breadcrumbs-BEcEVdRt.js.map} +1 -1
- package/dist/{Breadcrumbs-D4wv2-T7.cjs → Breadcrumbs-DGyb8ntF.cjs} +2 -2
- package/dist/{Breadcrumbs-D4wv2-T7.cjs.map → Breadcrumbs-DGyb8ntF.cjs.map} +1 -1
- package/dist/{Button-7mgXcRdw.js → Button-CwwuhATn.js} +2 -2
- package/dist/{Button-7mgXcRdw.js.map → Button-CwwuhATn.js.map} +1 -1
- package/dist/{Button-DAvQCGIw.cjs → Button-D6f4SooD.cjs} +2 -2
- package/dist/{Button-DAvQCGIw.cjs.map → Button-D6f4SooD.cjs.map} +1 -1
- package/dist/{Calendar-B1ZJHqjB.js → Calendar-CGLl3HmM.js} +3 -3
- package/dist/{Calendar-B1ZJHqjB.js.map → Calendar-CGLl3HmM.js.map} +1 -1
- package/dist/{Calendar-BPYjqBy9.cjs → Calendar-CjHLOfVw.cjs} +2 -2
- package/dist/{Calendar-BPYjqBy9.cjs.map → Calendar-CjHLOfVw.cjs.map} +1 -1
- package/dist/{Card-B-Qso__1.cjs → Card-BbfesgrZ.cjs} +2 -2
- package/dist/{Card-B-Qso__1.cjs.map → Card-BbfesgrZ.cjs.map} +1 -1
- package/dist/{Card-vFsIhkyR.js → Card-DTmvoxKG.js} +3 -3
- package/dist/{Card-vFsIhkyR.js.map → Card-DTmvoxKG.js.map} +1 -1
- package/dist/{Chip-CovsonP1.cjs → Chip-CguuQYqY.cjs} +2 -2
- package/dist/{Chip-CovsonP1.cjs.map → Chip-CguuQYqY.cjs.map} +1 -1
- package/dist/{Chip-CU0J7HJa.js → Chip-DRwzCG96.js} +2 -2
- package/dist/{Chip-CU0J7HJa.js.map → Chip-DRwzCG96.js.map} +1 -1
- package/dist/{CodeBlock-DvJ45qEp.js → CodeBlock-C-8MTy4V.js} +3 -3
- package/dist/{CodeBlock-DvJ45qEp.js.map → CodeBlock-C-8MTy4V.js.map} +1 -1
- package/dist/{CodeBlock-B404V_cc.cjs → CodeBlock-Dv7hXdPl.cjs} +2 -2
- package/dist/{CodeBlock-B404V_cc.cjs.map → CodeBlock-Dv7hXdPl.cjs.map} +1 -1
- package/dist/{ColorPicker-_RBW51XB.cjs → ColorPicker-B4UqiIvG.cjs} +2 -2
- package/dist/{ColorPicker-_RBW51XB.cjs.map → ColorPicker-B4UqiIvG.cjs.map} +1 -1
- package/dist/{ColorPicker-C4slmEZC.js → ColorPicker-Rva-0w3d.js} +3 -3
- package/dist/{ColorPicker-C4slmEZC.js.map → ColorPicker-Rva-0w3d.js.map} +1 -1
- package/dist/{ColorPickerPanel-CNspBZre.cjs → ColorPickerPanel-DRJzClGA.cjs} +2 -2
- package/dist/{ColorPickerPanel-CNspBZre.cjs.map → ColorPickerPanel-DRJzClGA.cjs.map} +1 -1
- package/dist/{ColorPickerPanel-CQNfIbgc.js → ColorPickerPanel-Dx_TIReY.js} +2 -2
- package/dist/{ColorPickerPanel-CQNfIbgc.js.map → ColorPickerPanel-Dx_TIReY.js.map} +1 -1
- package/dist/{ColorRamp-DuO7gkru.cjs → ColorRamp-C5KkZS8L.cjs} +2 -2
- package/dist/{ColorRamp-DuO7gkru.cjs.map → ColorRamp-C5KkZS8L.cjs.map} +1 -1
- package/dist/{ColorRamp-DQZZiE5I.js → ColorRamp-CBkbpBHf.js} +2 -2
- package/dist/{ColorRamp-DQZZiE5I.js.map → ColorRamp-CBkbpBHf.js.map} +1 -1
- package/dist/{ConfigProvider-bXX8dnhY.js → ConfigProvider-BOcVBt4M.js} +2 -2
- package/dist/{ConfigProvider-bXX8dnhY.js.map → ConfigProvider-BOcVBt4M.js.map} +1 -1
- package/dist/{ConfigProvider-BFhkb0BV.cjs → ConfigProvider-DPk0aHDG.cjs} +2 -2
- package/dist/{ConfigProvider-BFhkb0BV.cjs.map → ConfigProvider-DPk0aHDG.cjs.map} +1 -1
- package/dist/{CopyButton-DfYAslz-.js → CopyButton-BjNknp73.js} +3 -3
- package/dist/{CopyButton-DfYAslz-.js.map → CopyButton-BjNknp73.js.map} +1 -1
- package/dist/{CopyButton-B2V6guZ0.cjs → CopyButton-BxOhFQiM.cjs} +2 -2
- package/dist/{CopyButton-B2V6guZ0.cjs.map → CopyButton-BxOhFQiM.cjs.map} +1 -1
- package/dist/{DatePicker-DrIHa1j1.cjs → DatePicker-DCCq8OCQ.cjs} +2 -2
- package/dist/{DatePicker-DrIHa1j1.cjs.map → DatePicker-DCCq8OCQ.cjs.map} +1 -1
- package/dist/{DatePicker-CNUDjOxA.js → DatePicker-UCzOaIUQ.js} +4 -4
- package/dist/{DatePicker-CNUDjOxA.js.map → DatePicker-UCzOaIUQ.js.map} +1 -1
- package/dist/{DateTimePicker-CvWNDbib.js → DateTimePicker-1716FCsy.js} +7 -7
- package/dist/{DateTimePicker-CvWNDbib.js.map → DateTimePicker-1716FCsy.js.map} +1 -1
- package/dist/{DateTimePicker-BzwxaOPb.cjs → DateTimePicker-nN9Okf1Y.cjs} +2 -2
- package/dist/{DateTimePicker-BzwxaOPb.cjs.map → DateTimePicker-nN9Okf1Y.cjs.map} +1 -1
- package/dist/{DescriptionList-BgMNjHJQ.js → DescriptionList-BTdmaD1T.js} +4 -4
- package/dist/{DescriptionList-BgMNjHJQ.js.map → DescriptionList-BTdmaD1T.js.map} +1 -1
- package/dist/{DescriptionList-Bed1MHU8.cjs → DescriptionList-BbLVh3eI.cjs} +2 -2
- package/dist/{DescriptionList-Bed1MHU8.cjs.map → DescriptionList-BbLVh3eI.cjs.map} +1 -1
- package/dist/{Dropdown-iWbHokT7.js → Dropdown-CmEWQTdx.js} +2 -2
- package/dist/{Dropdown-iWbHokT7.js.map → Dropdown-CmEWQTdx.js.map} +1 -1
- package/dist/{Dropdown-DNL7RWdL.cjs → Dropdown-DC0Cl9Tb.cjs} +2 -2
- package/dist/{Dropdown-DNL7RWdL.cjs.map → Dropdown-DC0Cl9Tb.cjs.map} +1 -1
- package/dist/{EmptyState-CmcjJl_K.js → EmptyState-Cd1IxApj.js} +2 -2
- package/dist/{EmptyState-CmcjJl_K.js.map → EmptyState-Cd1IxApj.js.map} +1 -1
- package/dist/{EmptyState-BzwrOICc.cjs → EmptyState-DQJ1JswD.cjs} +2 -2
- package/dist/{EmptyState-BzwrOICc.cjs.map → EmptyState-DQJ1JswD.cjs.map} +1 -1
- package/dist/{ErrorBoundary-BcZgeSsu.cjs → ErrorBoundary-CXhzkfEl.cjs} +2 -2
- package/dist/{ErrorBoundary-BcZgeSsu.cjs.map → ErrorBoundary-CXhzkfEl.cjs.map} +1 -1
- package/dist/{ErrorBoundary-TfeJetWc.js → ErrorBoundary-DUbPB1_a.js} +3 -3
- package/dist/{ErrorBoundary-TfeJetWc.js.map → ErrorBoundary-DUbPB1_a.js.map} +1 -1
- package/dist/{ErrorState-EjIhdq7S.js → ErrorState-CbKuo8cI.js} +7 -7
- package/dist/{ErrorState-EjIhdq7S.js.map → ErrorState-CbKuo8cI.js.map} +1 -1
- package/dist/{ErrorState-CzWz5UcX.cjs → ErrorState-URYycye9.cjs} +2 -2
- package/dist/{ErrorState-CzWz5UcX.cjs.map → ErrorState-URYycye9.cjs.map} +1 -1
- package/dist/{FileCard-CmMxVyk3.js → FileCard-DxwKSMN1.js} +3 -3
- package/dist/{FileCard-CmMxVyk3.js.map → FileCard-DxwKSMN1.js.map} +1 -1
- package/dist/{FileCard-Cxr1_eF2.cjs → FileCard-o7zymUXi.cjs} +2 -2
- package/dist/{FileCard-Cxr1_eF2.cjs.map → FileCard-o7zymUXi.cjs.map} +1 -1
- package/dist/{FileUploader-2cXBI4Nh.js → FileUploader-CS5HbKW3.js} +6 -6
- package/dist/{FileUploader-2cXBI4Nh.js.map → FileUploader-CS5HbKW3.js.map} +1 -1
- package/dist/{FileUploader-BkM1t2aE.cjs → FileUploader-uaTl82eB.cjs} +2 -2
- package/dist/{FileUploader-BkM1t2aE.cjs.map → FileUploader-uaTl82eB.cjs.map} +1 -1
- package/dist/{Flag-CWp81_zX.cjs → Flag-BodaDmHB.cjs} +2 -2
- package/dist/{Flag-CWp81_zX.cjs.map → Flag-BodaDmHB.cjs.map} +1 -1
- package/dist/{Flag-IQolG3j6.js → Flag-CS4SH1Nt.js} +2 -2
- package/dist/{Flag-IQolG3j6.js.map → Flag-CS4SH1Nt.js.map} +1 -1
- package/dist/{FullscreenToggle-DXVAeN3M.cjs → FullscreenToggle--qqOi3Bw.cjs} +2 -2
- package/dist/{FullscreenToggle-DXVAeN3M.cjs.map → FullscreenToggle--qqOi3Bw.cjs.map} +1 -1
- package/dist/{FullscreenToggle-B1DH_-k3.js → FullscreenToggle-CI3fmt9Q.js} +3 -3
- package/dist/{FullscreenToggle-B1DH_-k3.js.map → FullscreenToggle-CI3fmt9Q.js.map} +1 -1
- package/dist/{IconButton-s5hohjxu.js → IconButton-CCxNWwlu.js} +2 -2
- package/dist/{IconButton-s5hohjxu.js.map → IconButton-CCxNWwlu.js.map} +1 -1
- package/dist/{IconButton-ChhZqleN.cjs → IconButton-DOlCOuKu.cjs} +2 -2
- package/dist/{IconButton-ChhZqleN.cjs.map → IconButton-DOlCOuKu.cjs.map} +1 -1
- package/dist/{ImageEditor-DWbWjGQ8.js → ImageEditor-CKfaHNGz.js} +7 -7
- package/dist/{ImageEditor-DWbWjGQ8.js.map → ImageEditor-CKfaHNGz.js.map} +1 -1
- package/dist/{ImageEditor-C8tFTX4e.cjs → ImageEditor-CWISFJ1J.cjs} +2 -2
- package/dist/{ImageEditor-C8tFTX4e.cjs.map → ImageEditor-CWISFJ1J.cjs.map} +1 -1
- package/dist/{List-Dfa7mlSZ.cjs → List-4VSERgRp.cjs} +2 -2
- package/dist/{List-Dfa7mlSZ.cjs.map → List-4VSERgRp.cjs.map} +1 -1
- package/dist/{List-DQlEG_S5.js → List-H70lnOLB.js} +2 -2
- package/dist/{List-DQlEG_S5.js.map → List-H70lnOLB.js.map} +1 -1
- package/dist/ListItem-DRzwCAvN.js +79 -0
- package/dist/ListItem-DRzwCAvN.js.map +1 -0
- package/dist/ListItem-wMTmx1yX.cjs +2 -0
- package/dist/ListItem-wMTmx1yX.cjs.map +1 -0
- package/dist/{Loader-BCrMy9NU.cjs → Loader-DUp5O6pO.cjs} +2 -2
- package/dist/{Loader-BCrMy9NU.cjs.map → Loader-DUp5O6pO.cjs.map} +1 -1
- package/dist/{Loader-CShIWNfG.js → Loader-Dj_lwZT2.js} +2 -2
- package/dist/{Loader-CShIWNfG.js.map → Loader-Dj_lwZT2.js.map} +1 -1
- package/dist/{LocationPicker-DsV_s2Ur.js → LocationPicker-CB2vrhu0.js} +7 -7
- package/dist/{LocationPicker-DsV_s2Ur.js.map → LocationPicker-CB2vrhu0.js.map} +1 -1
- package/dist/{LocationPicker-8Tt0zJU4.cjs → LocationPicker-DzCmt8Xb.cjs} +2 -2
- package/dist/{LocationPicker-8Tt0zJU4.cjs.map → LocationPicker-DzCmt8Xb.cjs.map} +1 -1
- package/dist/{Modal-yj92WLay.cjs → Modal-C5sKj4UK.cjs} +2 -2
- package/dist/{Modal-yj92WLay.cjs.map → Modal-C5sKj4UK.cjs.map} +1 -1
- package/dist/{Modal-BO7fHn0r.js → Modal-Cr1aqYgb.js} +3 -3
- package/dist/{Modal-BO7fHn0r.js.map → Modal-Cr1aqYgb.js.map} +1 -1
- package/dist/{MultiSelect-D-QWlfwD.js → MultiSelect-DgrL23Nr.js} +4 -4
- package/dist/{MultiSelect-D-QWlfwD.js.map → MultiSelect-DgrL23Nr.js.map} +1 -1
- package/dist/{MultiSelect-B6JZb_5N.cjs → MultiSelect-mY7X3O7V.cjs} +2 -2
- package/dist/{MultiSelect-B6JZb_5N.cjs.map → MultiSelect-mY7X3O7V.cjs.map} +1 -1
- package/dist/{NumberField-CS5VMnk4.cjs → NumberField-CnsHPDuN.cjs} +2 -2
- package/dist/{NumberField-CS5VMnk4.cjs.map → NumberField-CnsHPDuN.cjs.map} +1 -1
- package/dist/{NumberField-D_UxKjVN.js → NumberField-GxQeV07e.js} +3 -3
- package/dist/{NumberField-D_UxKjVN.js.map → NumberField-GxQeV07e.js.map} +1 -1
- package/dist/{OtpField-BuS_8j9L.cjs → OtpField-Dt71t0PF.cjs} +2 -2
- package/dist/{OtpField-BuS_8j9L.cjs.map → OtpField-Dt71t0PF.cjs.map} +1 -1
- package/dist/{OtpField-CpjDid5_.js → OtpField-b31rUMV1.js} +2 -2
- package/dist/{OtpField-CpjDid5_.js.map → OtpField-b31rUMV1.js.map} +1 -1
- package/dist/{PageError-DjyJrGmR.js → PageError-0it6u2r9.js} +5 -5
- package/dist/{PageError-DjyJrGmR.js.map → PageError-0it6u2r9.js.map} +1 -1
- package/dist/{PageError-CTEOASeb.cjs → PageError-BYIkzEfs.cjs} +2 -2
- package/dist/{PageError-CTEOASeb.cjs.map → PageError-BYIkzEfs.cjs.map} +1 -1
- package/dist/{PageLayout-BYKRmCAL.cjs → PageLayout-8ZHBwDeC.cjs} +2 -2
- package/dist/{PageLayout-BYKRmCAL.cjs.map → PageLayout-8ZHBwDeC.cjs.map} +1 -1
- package/dist/{PageLayout-Cz1OhQZ7.js → PageLayout-Cqb2pczH.js} +4 -4
- package/dist/{PageLayout-Cz1OhQZ7.js.map → PageLayout-Cqb2pczH.js.map} +1 -1
- package/dist/{PageNotFound-u9Q4KG6B.cjs → PageNotFound-BCX-XQLA.cjs} +2 -2
- package/dist/{PageNotFound-u9Q4KG6B.cjs.map → PageNotFound-BCX-XQLA.cjs.map} +1 -1
- package/dist/{PageNotFound-CwBtrllo.js → PageNotFound-ChpqEtgV.js} +5 -5
- package/dist/{PageNotFound-CwBtrllo.js.map → PageNotFound-ChpqEtgV.js.map} +1 -1
- package/dist/{Pagination-HtS5gPnd.cjs → Pagination-DSdcF9UF.cjs} +2 -2
- package/dist/{Pagination-HtS5gPnd.cjs.map → Pagination-DSdcF9UF.cjs.map} +1 -1
- package/dist/{Pagination-CLjNwqie.js → Pagination-Du6tATTZ.js} +2 -2
- package/dist/{Pagination-CLjNwqie.js.map → Pagination-Du6tATTZ.js.map} +1 -1
- package/dist/{PaletteField-BSgx5pxh.cjs → PaletteField-D_wYeYEx.cjs} +2 -2
- package/dist/{PaletteField-BSgx5pxh.cjs.map → PaletteField-D_wYeYEx.cjs.map} +1 -1
- package/dist/{PaletteField-Bk7cnSla.js → PaletteField-F-6hF1Ly.js} +3 -3
- package/dist/{PaletteField-Bk7cnSla.js.map → PaletteField-F-6hF1Ly.js.map} +1 -1
- package/dist/{PhoneField-CzFv2Vci.cjs → PhoneField-BdRlvj7L.cjs} +2 -2
- package/dist/{PhoneField-CzFv2Vci.cjs.map → PhoneField-BdRlvj7L.cjs.map} +1 -1
- package/dist/{PhoneField-DhoumZNG.js → PhoneField-D99W6Abz.js} +4 -4
- package/dist/{PhoneField-DhoumZNG.js.map → PhoneField-D99W6Abz.js.map} +1 -1
- package/dist/{Popconfirm-Cb9LlmZb.cjs → Popconfirm-B4506C47.cjs} +2 -2
- package/dist/{Popconfirm-Cb9LlmZb.cjs.map → Popconfirm-B4506C47.cjs.map} +1 -1
- package/dist/{Popconfirm-D7J5JbF-.js → Popconfirm-C5ldh11s.js} +3 -3
- package/dist/{Popconfirm-D7J5JbF-.js.map → Popconfirm-C5ldh11s.js.map} +1 -1
- package/dist/{Progress-Bt2LDqbD.js → Progress-C71Yo8Mw.js} +2 -2
- package/dist/{Progress-Bt2LDqbD.js.map → Progress-C71Yo8Mw.js.map} +1 -1
- package/dist/{Progress-dAtQ2BN-.cjs → Progress-sa-c4iAK.cjs} +2 -2
- package/dist/{Progress-dAtQ2BN-.cjs.map → Progress-sa-c4iAK.cjs.map} +1 -1
- package/dist/{QrCode-jaDZxZkv.js → QrCode-CMLPHVUN.js} +2 -2
- package/dist/{QrCode-jaDZxZkv.js.map → QrCode-CMLPHVUN.js.map} +1 -1
- package/dist/{QrCode-FHUAxI8u.cjs → QrCode-lWfNmqL8.cjs} +2 -2
- package/dist/{QrCode-FHUAxI8u.cjs.map → QrCode-lWfNmqL8.cjs.map} +1 -1
- package/dist/{RemoveDialog-eGNxdyoO.cjs → RemoveDialog-C6XRG1SG.cjs} +2 -2
- package/dist/{RemoveDialog-eGNxdyoO.cjs.map → RemoveDialog-C6XRG1SG.cjs.map} +1 -1
- package/dist/{RemoveDialog-DdO5E3Wl.js → RemoveDialog-D01OLxbj.js} +5 -5
- package/dist/{RemoveDialog-DdO5E3Wl.js.map → RemoveDialog-D01OLxbj.js.map} +1 -1
- package/dist/{RichTextEditor-DHRiJchI.js → RichTextEditor-BFzWo8Ih.js} +9 -9
- package/dist/{RichTextEditor-DHRiJchI.js.map → RichTextEditor-BFzWo8Ih.js.map} +1 -1
- package/dist/{RichTextEditor-CoYuQurR.cjs → RichTextEditor-JpvFdJMa.cjs} +2 -2
- package/dist/{RichTextEditor-CoYuQurR.cjs.map → RichTextEditor-JpvFdJMa.cjs.map} +1 -1
- package/dist/{RootLayout-pd66MZtI.js → RootLayout-Dbika05Y.js} +17 -17
- package/dist/{RootLayout-pd66MZtI.js.map → RootLayout-Dbika05Y.js.map} +1 -1
- package/dist/{RootLayout-CEplIlVR.cjs → RootLayout-IwlWqYVL.cjs} +2 -2
- package/dist/{RootLayout-CEplIlVR.cjs.map → RootLayout-IwlWqYVL.cjs.map} +1 -1
- package/dist/{Select-CvW_T9R-.cjs → Select-CioU7fV7.cjs} +2 -2
- package/dist/{Select-CvW_T9R-.cjs.map → Select-CioU7fV7.cjs.map} +1 -1
- package/dist/{Select-C2iiQLMh.js → Select-DKaKdvG0.js} +3 -3
- package/dist/{Select-C2iiQLMh.js.map → Select-DKaKdvG0.js.map} +1 -1
- package/dist/{Sidebar-CqGCazeA.cjs → Sidebar-B7mCqEkl.cjs} +2 -2
- package/dist/{Sidebar-CqGCazeA.cjs.map → Sidebar-B7mCqEkl.cjs.map} +1 -1
- package/dist/{Sidebar-DuUhzQBi.js → Sidebar-D0pNTtIb.js} +6 -6
- package/dist/{Sidebar-DuUhzQBi.js.map → Sidebar-D0pNTtIb.js.map} +1 -1
- package/dist/{Slider-UY29adRu.js → Slider-BVM_MXjM.js} +2 -2
- package/dist/{Slider-UY29adRu.js.map → Slider-BVM_MXjM.js.map} +1 -1
- package/dist/{Slider-DlPMPdHA.cjs → Slider-RpFfWXLX.cjs} +2 -2
- package/dist/{Slider-DlPMPdHA.cjs.map → Slider-RpFfWXLX.cjs.map} +1 -1
- package/dist/{SpeedDial-DOWefQgo.js → SpeedDial-BMd4lvc6.js} +2 -2
- package/dist/{SpeedDial-DOWefQgo.js.map → SpeedDial-BMd4lvc6.js.map} +1 -1
- package/dist/{SpeedDial-Cms5pJ9t.cjs → SpeedDial-BpHZ09TN.cjs} +2 -2
- package/dist/{SpeedDial-Cms5pJ9t.cjs.map → SpeedDial-BpHZ09TN.cjs.map} +1 -1
- package/dist/{Stepper-4wCyTnwi.cjs → Stepper-BhtP1FgK.cjs} +2 -2
- package/dist/{Stepper-4wCyTnwi.cjs.map → Stepper-BhtP1FgK.cjs.map} +1 -1
- package/dist/{Stepper-yQEJkbUJ.js → Stepper-CedGw8c6.js} +2 -2
- package/dist/{Stepper-yQEJkbUJ.js.map → Stepper-CedGw8c6.js.map} +1 -1
- package/dist/{Table-D4pqLNtE.cjs → Table-C-s1M3ZJ.cjs} +2 -2
- package/dist/{Table-D4pqLNtE.cjs.map → Table-C-s1M3ZJ.cjs.map} +1 -1
- package/dist/{Table-CNrt1EWm.js → Table-CEIZw6O7.js} +18 -18
- package/dist/{Table-CNrt1EWm.js.map → Table-CEIZw6O7.js.map} +1 -1
- package/dist/{Tabs-lezN63jW.js → Tabs-BryFjibj.js} +2 -2
- package/dist/{Tabs-lezN63jW.js.map → Tabs-BryFjibj.js.map} +1 -1
- package/dist/{Tabs-D6qrgZTM.cjs → Tabs-DXb1phlV.cjs} +2 -2
- package/dist/{Tabs-D6qrgZTM.cjs.map → Tabs-DXb1phlV.cjs.map} +1 -1
- package/dist/{TagsField-BIJEDyfz.cjs → TagsField-BG7ianZI.cjs} +2 -2
- package/dist/{TagsField-BIJEDyfz.cjs.map → TagsField-BG7ianZI.cjs.map} +1 -1
- package/dist/{TagsField-D_a2I8eU.js → TagsField-Dju_vk92.js} +4 -4
- package/dist/{TagsField-D_a2I8eU.js.map → TagsField-Dju_vk92.js.map} +1 -1
- package/dist/{TextField-CXDBlP-8.cjs → TextField-D5NDKrbU.cjs} +2 -2
- package/dist/{TextField-CXDBlP-8.cjs.map → TextField-D5NDKrbU.cjs.map} +1 -1
- package/dist/{TextField-BsC2zoHI.js → TextField-DATNsTzX.js} +3 -3
- package/dist/{TextField-BsC2zoHI.js.map → TextField-DATNsTzX.js.map} +1 -1
- package/dist/{ThemeToggle-Dh6XxqM7.js → ThemeToggle-CCSi6b_Z.js} +3 -3
- package/dist/{ThemeToggle-Dh6XxqM7.js.map → ThemeToggle-CCSi6b_Z.js.map} +1 -1
- package/dist/{ThemeToggle-zbKf4ph5.cjs → ThemeToggle-or27hawd.cjs} +2 -2
- package/dist/{ThemeToggle-zbKf4ph5.cjs.map → ThemeToggle-or27hawd.cjs.map} +1 -1
- package/dist/{TimeColumns-CR__2LXh.js → TimeColumns-B5LAStb0.js} +2 -2
- package/dist/{TimeColumns-CR__2LXh.js.map → TimeColumns-B5LAStb0.js.map} +1 -1
- package/dist/{TimeColumns-CjBeUPtV.cjs → TimeColumns-BNmC-5do.cjs} +2 -2
- package/dist/{TimeColumns-CjBeUPtV.cjs.map → TimeColumns-BNmC-5do.cjs.map} +1 -1
- package/dist/{TimePicker-DtqmD2bH.cjs → TimePicker-CKNymi90.cjs} +2 -2
- package/dist/{TimePicker-DtqmD2bH.cjs.map → TimePicker-CKNymi90.cjs.map} +1 -1
- package/dist/{TimePicker-BakQ-wPd.js → TimePicker-D43aa4JA.js} +5 -5
- package/dist/{TimePicker-BakQ-wPd.js.map → TimePicker-D43aa4JA.js.map} +1 -1
- package/dist/{Toaster-C5jWNL-o.js → Toaster-BmH9V76v.js} +3 -3
- package/dist/{Toaster-C5jWNL-o.js.map → Toaster-BmH9V76v.js.map} +1 -1
- package/dist/{Toaster-BpXPWJ_n.cjs → Toaster-CvtKx3FV.cjs} +2 -2
- package/dist/{Toaster-BpXPWJ_n.cjs.map → Toaster-CvtKx3FV.cjs.map} +1 -1
- package/dist/{TranslatedFields-C8oxlGIQ.js → TranslatedFields-Bn0cR47v.js} +5 -5
- package/dist/{TranslatedFields-C8oxlGIQ.js.map → TranslatedFields-Bn0cR47v.js.map} +1 -1
- package/dist/{TranslatedFields-Che_ZPHk.cjs → TranslatedFields-U1cjZKWn.cjs} +2 -2
- package/dist/{TranslatedFields-Che_ZPHk.cjs.map → TranslatedFields-U1cjZKWn.cjs.map} +1 -1
- package/dist/{UserCard-Dr1A_bdA.js → UserCard-BNKMs48t.js} +3 -3
- package/dist/{UserCard-Dr1A_bdA.js.map → UserCard-BNKMs48t.js.map} +1 -1
- package/dist/{UserCard-DlrdIJHW.cjs → UserCard-D0RokNh8.cjs} +2 -2
- package/dist/{UserCard-DlrdIJHW.cjs.map → UserCard-D0RokNh8.cjs.map} +1 -1
- package/dist/{authLayoutRoute-CPLqQVvx.cjs → authLayoutRoute-23XOJ9q9.cjs} +2 -2
- package/dist/{authLayoutRoute-CPLqQVvx.cjs.map → authLayoutRoute-23XOJ9q9.cjs.map} +1 -1
- package/dist/{authLayoutRoute-nSZq8JYA.js → authLayoutRoute-BE0nGH_N.js} +2 -2
- package/dist/{authLayoutRoute-nSZq8JYA.js.map → authLayoutRoute-BE0nGH_N.js.map} +1 -1
- package/dist/components/Alert/index.cjs +1 -1
- package/dist/components/Alert/index.js +1 -1
- package/dist/components/BottomSheet/BottomSheet.d.cts +59 -0
- package/dist/components/BottomSheet/BottomSheet.d.ts +59 -0
- package/dist/components/BottomSheet/gesture.d.cts +51 -0
- package/dist/components/BottomSheet/gesture.d.ts +51 -0
- package/dist/components/BottomSheet/index.cjs +2 -0
- package/dist/components/BottomSheet/index.cjs.map +1 -0
- package/dist/components/BottomSheet/index.d.cts +2 -0
- package/dist/components/BottomSheet/index.d.ts +2 -0
- package/dist/components/BottomSheet/index.js +6 -0
- package/dist/components/BottomSheet/index.js.map +1 -0
- package/dist/components/BottomSheet/motion.d.cts +47 -0
- package/dist/components/BottomSheet/motion.d.ts +47 -0
- package/dist/components/Breadcrumbs/index.cjs +1 -1
- package/dist/components/Breadcrumbs/index.js +1 -1
- package/dist/components/Button/index.cjs +1 -1
- package/dist/components/Button/index.js +1 -1
- package/dist/components/Card/index.cjs +1 -1
- package/dist/components/Card/index.js +1 -1
- package/dist/components/Chip/index.cjs +1 -1
- package/dist/components/Chip/index.js +1 -1
- package/dist/components/CodeBlock/index.cjs +1 -1
- package/dist/components/CodeBlock/index.js +1 -1
- package/dist/components/ColorPicker/index.cjs +1 -1
- package/dist/components/ColorPicker/index.js +1 -1
- package/dist/components/ColorRamp/index.cjs +1 -1
- package/dist/components/ColorRamp/index.js +1 -1
- package/dist/components/CopyButton/index.cjs +1 -1
- package/dist/components/CopyButton/index.js +1 -1
- package/dist/components/DatePicker/index.cjs +1 -1
- package/dist/components/DatePicker/index.js +1 -1
- package/dist/components/DateTimePicker/index.cjs +1 -1
- package/dist/components/DateTimePicker/index.js +1 -1
- package/dist/components/DescriptionList/index.cjs +1 -1
- package/dist/components/DescriptionList/index.js +1 -1
- package/dist/components/Dropdown/index.cjs +1 -1
- package/dist/components/Dropdown/index.js +1 -1
- package/dist/components/EmptyState/index.cjs +1 -1
- package/dist/components/EmptyState/index.js +1 -1
- package/dist/components/ErrorState/index.cjs +1 -1
- package/dist/components/ErrorState/index.js +2 -2
- package/dist/components/FileCard/index.cjs +1 -1
- package/dist/components/FileCard/index.js +1 -1
- package/dist/components/FileUploader/index.cjs +1 -1
- package/dist/components/FileUploader/index.js +1 -1
- package/dist/components/Flag/index.cjs +1 -1
- package/dist/components/Flag/index.js +1 -1
- package/dist/components/FullscreenToggle/index.cjs +1 -1
- package/dist/components/FullscreenToggle/index.js +1 -1
- package/dist/components/IconButton/index.cjs +1 -1
- package/dist/components/IconButton/index.js +1 -1
- package/dist/components/ImageEditor/index.cjs +1 -1
- package/dist/components/ImageEditor/index.js +1 -1
- package/dist/components/List/ListItem.d.cts +9 -1
- package/dist/components/List/ListItem.d.ts +9 -1
- package/dist/components/List/index.cjs +1 -1
- package/dist/components/List/index.d.cts +1 -1
- package/dist/components/List/index.d.ts +1 -1
- package/dist/components/List/index.js +2 -2
- package/dist/components/Loader/index.cjs +1 -1
- package/dist/components/Loader/index.js +1 -1
- package/dist/components/LocationPicker/index.cjs +1 -1
- package/dist/components/LocationPicker/index.js +1 -1
- package/dist/components/Modal/index.cjs +1 -1
- package/dist/components/Modal/index.js +1 -1
- package/dist/components/MultiSelect/index.cjs +1 -1
- package/dist/components/MultiSelect/index.js +1 -1
- package/dist/components/NumberField/index.cjs +1 -1
- package/dist/components/NumberField/index.js +1 -1
- package/dist/components/OtpField/index.cjs +1 -1
- package/dist/components/OtpField/index.js +1 -1
- package/dist/components/PageError/index.cjs +1 -1
- package/dist/components/PageError/index.js +1 -1
- package/dist/components/PageLayout/index.cjs +1 -1
- package/dist/components/PageLayout/index.js +1 -1
- package/dist/components/PageNotFound/index.cjs +1 -1
- package/dist/components/PageNotFound/index.js +1 -1
- package/dist/components/Pagination/index.cjs +1 -1
- package/dist/components/Pagination/index.js +1 -1
- package/dist/components/PaletteField/index.cjs +1 -1
- package/dist/components/PaletteField/index.js +1 -1
- package/dist/components/PhoneField/index.cjs +1 -1
- package/dist/components/PhoneField/index.js +1 -1
- package/dist/components/Popconfirm/index.cjs +1 -1
- package/dist/components/Popconfirm/index.js +1 -1
- package/dist/components/Progress/index.cjs +1 -1
- package/dist/components/Progress/index.js +1 -1
- package/dist/components/QrCode/index.cjs +1 -1
- package/dist/components/QrCode/index.js +1 -1
- package/dist/components/RemoveDialog/index.cjs +1 -1
- package/dist/components/RemoveDialog/index.js +1 -1
- package/dist/components/RichTextEditor/index.cjs +1 -1
- package/dist/components/RichTextEditor/index.js +1 -1
- package/dist/components/RootLayout/index.cjs +1 -1
- package/dist/components/RootLayout/index.js +1 -1
- package/dist/components/Select/index.cjs +1 -1
- package/dist/components/Select/index.js +1 -1
- package/dist/components/Sidebar/index.cjs +1 -1
- package/dist/components/Sidebar/index.js +1 -1
- package/dist/components/Slider/index.cjs +1 -1
- package/dist/components/Slider/index.js +1 -1
- package/dist/components/SpeedDial/index.cjs +1 -1
- package/dist/components/SpeedDial/index.js +1 -1
- package/dist/components/Stepper/index.cjs +1 -1
- package/dist/components/Stepper/index.js +1 -1
- package/dist/components/Table/index.cjs +1 -1
- package/dist/components/Table/index.js +1 -1
- package/dist/components/Tabs/index.cjs +1 -1
- package/dist/components/Tabs/index.js +1 -1
- package/dist/components/TagsField/index.cjs +1 -1
- package/dist/components/TagsField/index.js +1 -1
- package/dist/components/TextField/index.cjs +1 -1
- package/dist/components/TextField/index.js +1 -1
- package/dist/components/ThemeToggle/index.cjs +1 -1
- package/dist/components/ThemeToggle/index.js +1 -1
- package/dist/components/TimePicker/index.cjs +1 -1
- package/dist/components/TimePicker/index.js +1 -1
- package/dist/components/Toast/index.cjs +1 -1
- package/dist/components/Toast/index.js +1 -1
- package/dist/components/TranslatedFields/index.cjs +1 -1
- package/dist/components/TranslatedFields/index.js +1 -1
- package/dist/components/UserCard/index.cjs +1 -1
- package/dist/components/UserCard/index.js +1 -1
- package/dist/components/index.d.cts +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/entries/app.cjs +1 -1
- package/dist/entries/app.js +1 -1
- package/dist/entries/auth.cjs +1 -1
- package/dist/entries/auth.js +2 -2
- package/dist/entries/components.cjs +1 -1
- package/dist/entries/components.js +186 -184
- package/dist/entries/components.js.map +1 -1
- package/dist/entries/i18n.cjs +1 -1
- package/dist/entries/i18n.js +2 -2
- package/dist/entries/theme.cjs +1 -1
- package/dist/entries/theme.js +1 -1
- package/dist/i18n/messages.d.cts +2 -0
- package/dist/i18n/messages.d.ts +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +193 -191
- package/dist/index.js.map +1 -1
- package/dist/messages-C2DUaZkS.cjs +36 -0
- package/dist/messages-C2DUaZkS.cjs.map +1 -0
- package/dist/{messages-CZbb1xNN.js → messages-DWL0ZaKa.js} +8 -1
- package/dist/messages-DWL0ZaKa.js.map +1 -0
- package/dist/{useHomeTo---51HTJ0.cjs → useHomeTo-Ao53ZjWz.cjs} +2 -2
- package/dist/{useHomeTo---51HTJ0.cjs.map → useHomeTo-Ao53ZjWz.cjs.map} +1 -1
- package/dist/{useHomeTo-CJj94TdV.js → useHomeTo-DG69efNE.js} +2 -2
- package/dist/{useHomeTo-CJj94TdV.js.map → useHomeTo-DG69efNE.js.map} +1 -1
- package/dist/{useOptionMenu-DS___46k.cjs → useOptionMenu-B9zQfGTN.cjs} +2 -2
- package/dist/{useOptionMenu-DS___46k.cjs.map → useOptionMenu-B9zQfGTN.cjs.map} +1 -1
- package/dist/{useOptionMenu-Sp2d3Bzi.js → useOptionMenu-C8SEMVFV.js} +5 -5
- package/dist/{useOptionMenu-Sp2d3Bzi.js.map → useOptionMenu-C8SEMVFV.js.map} +1 -1
- package/package.json +1 -1
- package/dist/ListItem-CLmg9xKQ.js +0 -76
- package/dist/ListItem-CLmg9xKQ.js.map +0 -1
- package/dist/ListItem-CWM2fUS2.cjs +0 -2
- package/dist/ListItem-CWM2fUS2.cjs.map +0 -1
- package/dist/messages-CZbb1xNN.js.map +0 -1
- package/dist/messages-D4ooXnUr.cjs +0 -36
- package/dist/messages-D4ooXnUr.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageEditor-DWbWjGQ8.js","sources":["../src/components/ImageEditor/core/matrix.ts","../src/components/ImageEditor/core/geometry.ts","../src/components/ImageEditor/core/pixels.ts","../src/components/ImageEditor/core/load.ts","../src/components/ImageEditor/core/affine.ts","../src/components/ImageEditor/core/redact.ts","../src/components/ImageEditor/core/scene.ts","../src/components/ImageEditor/core/webgl.ts","../src/components/ImageEditor/core/render.ts","../src/components/ImageEditor/core/editor.ts","../src/components/ImageEditor/core/spring.ts","../src/components/ImageEditor/EditorStage.tsx","../src/components/ImageEditor/CropShapeMenu.tsx","../src/components/ImageEditor/FilterStrip.tsx","../src/components/ImageEditor/ResizePanel.tsx","../src/components/ImageEditor/RulerSlider.tsx","../src/components/ImageEditor/ImageEditor.tsx"],"sourcesContent":["// Color matrices — the 4×5 (20-number, row-major) form the editor uses for filters and the matrix-based\n// finetune adjustments. Row i computes channel i (r, g, b, a) as\n// out = m[0]·r + m[1]·g + m[2]·b + m[3]·a + m[4]\n// with every channel and the offset in 0…1. Composition goes through the 5×5 homogeneous form.\n\nimport type { ImageFilterId, ImageFinetuneId } from './types'\n\nexport type ColorMatrix = number[]\n\n/** The identity matrix (no change). */\nexport const IDENTITY_MATRIX: ColorMatrix = [\n 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,\n]\n\n/** Rec. 709 luma weights (the grayscale / saturation basis). */\nconst LR = 0.2126\nconst LG = 0.7152\nconst LB = 0.0722\n\n/** `a ∘ b` — the matrix that applies `b` first, then `a`. */\nexport function multiplyMatrix(a: ColorMatrix, b: ColorMatrix): ColorMatrix {\n const out = new Array<number>(20)\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 5; col++) {\n let sum = 0\n for (let k = 0; k < 4; k++) sum += a[row * 5 + k] * b[k * 5 + col]\n // the homogeneous row of b is [0 0 0 0 1], so a's offset carries through only for the last column\n if (col === 4) sum += a[row * 5 + 4]\n out[row * 5 + col] = sum\n }\n }\n return out\n}\n\n/** Compose matrices in application order: `composeMatrices(m1, m2, m3)` applies m1, then m2, then m3. */\nexport function composeMatrices(...matrices: ColorMatrix[]): ColorMatrix {\n return matrices.reduce((acc, m) => multiplyMatrix(m, acc), IDENTITY_MATRIX)\n}\n\n/** Whether a matrix is (numerically) the identity. */\nexport function isIdentityMatrix(m: ColorMatrix | null | undefined): boolean {\n return !m || m.every((v, i) => Math.abs(v - IDENTITY_MATRIX[i]) < 1e-6)\n}\n\n/** Apply a matrix to one straight-alpha RGBA color (each 0…1). */\nexport function applyMatrix(\n m: ColorMatrix,\n r: number,\n g: number,\n b: number,\n a = 1,\n): [number, number, number, number] {\n return [\n m[0] * r + m[1] * g + m[2] * b + m[3] * a + m[4],\n m[5] * r + m[6] * g + m[7] * b + m[8] * a + m[9],\n m[10] * r + m[11] * g + m[12] * b + m[13] * a + m[14],\n m[15] * r + m[16] * g + m[17] * b + m[18] * a + m[19],\n ]\n}\n\n// ── building blocks ─────────────────────────────────────────────────────────────────────────────\n\n/** Add `v` to r, g and b. */\nexport const brightnessMatrix = (v: number): ColorMatrix => [\n 1,\n 0,\n 0,\n 0,\n v,\n 0,\n 1,\n 0,\n 0,\n v,\n 0,\n 0,\n 1,\n 0,\n v,\n 0,\n 0,\n 0,\n 1,\n 0,\n]\n\n/** Scale r, g, b around the 0.5 midpoint by `c`. */\nexport const contrastMatrix = (c: number): ColorMatrix => {\n const o = 0.5 * (1 - c)\n return [c, 0, 0, 0, o, 0, c, 0, 0, o, 0, 0, c, 0, o, 0, 0, 0, 1, 0]\n}\n\n/** Saturation `s` (0 = grayscale, 1 = unchanged, 2 = doubled), on Rec. 709 luma. */\nexport const saturationMatrix = (s: number): ColorMatrix => {\n const i = 1 - s\n return [\n LR * i + s,\n LG * i,\n LB * i,\n 0,\n 0,\n LR * i,\n LG * i + s,\n LB * i,\n 0,\n 0,\n LR * i,\n LG * i,\n LB * i + s,\n 0,\n 0,\n 0,\n 0,\n 0,\n 1,\n 0,\n ]\n}\n\n/** Multiply each channel (and optionally add a per-channel offset). */\nexport const channelMatrix = (r: number, g: number, b: number, or = 0, og = 0, ob = 0) => [\n r,\n 0,\n 0,\n 0,\n or,\n 0,\n g,\n 0,\n 0,\n og,\n 0,\n 0,\n b,\n 0,\n ob,\n 0,\n 0,\n 0,\n 1,\n 0,\n]\n\n/** Remap 0…1 to `low`…`high` (lifts blacks / dims whites). */\nexport const levelsMatrix = (low: number, high: number): ColorMatrix => {\n const k = high - low\n return [k, 0, 0, 0, low, 0, k, 0, 0, low, 0, 0, k, 0, low, 0, 0, 0, 1, 0]\n}\n\n/** The classic sepia matrix. */\nexport const SEPIA_MATRIX: ColorMatrix = [\n 0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0,\n]\n\n// ── filters ─────────────────────────────────────────────────────────────────────────────────────\n\n/** The filter presets in display order, grouped (a gap between groups). */\nexport const FILTER_GROUPS: ImageFilterId[][] = [\n ['default'],\n ['chrome', 'fade', 'cold', 'warm', 'pastel'],\n ['mono', 'noir', 'stark', 'wash'],\n ['sepia', 'rust', 'blues', 'color'],\n]\n\nconst MONO = saturationMatrix(0)\n\n/** Each filter's 4×5 matrix (`default` → `null`, no filter). */\nexport const FILTER_MATRICES: Record<ImageFilterId, ColorMatrix | null> = {\n default: null,\n // more contrast + saturation\n chrome: composeMatrices(saturationMatrix(1.3), contrastMatrix(1.15)),\n // lifted blacks, softer whites, desaturated\n fade: composeMatrices(saturationMatrix(0.7), levelsMatrix(0.12, 0.92)),\n // a blue shift\n cold: composeMatrices(channelMatrix(0.9, 0.98, 1.12, 0, 0.01, 0.03), contrastMatrix(1.04)),\n // a red / yellow shift\n warm: composeMatrices(channelMatrix(1.1, 1.03, 0.86, 0.03, 0.01, 0), contrastMatrix(1.04)),\n // brightened + desaturated\n pastel: composeMatrices(saturationMatrix(0.6), levelsMatrix(0.16, 1)),\n // luminance grayscale\n mono: MONO,\n // high-contrast grayscale\n noir: composeMatrices(MONO, contrastMatrix(1.45), brightnessMatrix(-0.04)),\n // very high-contrast grayscale\n stark: composeMatrices(MONO, contrastMatrix(2.1)),\n // low-contrast, bright grayscale\n wash: composeMatrices(MONO, levelsMatrix(0.22, 0.98)),\n sepia: SEPIA_MATRIX,\n // a warm, strong sepia\n rust: composeMatrices(SEPIA_MATRIX, channelMatrix(1.12, 0.9, 0.7), contrastMatrix(1.12)),\n // blue-tinted monochrome\n blues: composeMatrices(MONO, channelMatrix(0.72, 0.88, 1.08, 0, 0.02, 0.08)),\n // boosted, vivid color\n color: composeMatrices(saturationMatrix(1.65), contrastMatrix(1.06)),\n}\n\n// ── finetune ────────────────────────────────────────────────────────────────────────────────────\n\n/** The finetune adjustments in display order. */\nexport const FINETUNE_IDS: ImageFinetuneId[] = [\n 'brightness',\n 'contrast',\n 'saturation',\n 'exposure',\n 'temperature',\n 'gamma',\n 'clarity',\n 'vignette',\n]\n\n/** All adjustments at 0. */\nexport const ZERO_FINETUNE: Record<ImageFinetuneId, number> = {\n brightness: 0,\n contrast: 0,\n saturation: 0,\n exposure: 0,\n temperature: 0,\n gamma: 0,\n clarity: 0,\n vignette: 0,\n}\n\n/** The UI value (−100…100) → the shader parameter for each adjustment. */\nexport const finetuneParam = {\n /** additive: −0.25…+0.25 */\n brightness: (v: number) => (v / 100) * 0.25,\n /** multiply around the midpoint: 0.5…1.5 */\n contrast: (v: number) => 1 + (v / 100) * 0.5,\n /** 0 (grayscale)…2 */\n saturation: (v: number) => 1 + v / 100,\n /** multiply: 0.5…1.5 */\n exposure: (v: number) => 1 + (v / 100) * 0.5,\n /** −1…1, shifts R and B in opposite directions */\n temperature: (v: number) => v / 100,\n /** exponent 0.5…1.5 (applied as x^(1/γ), so positive brightens the midtones) */\n gamma: (v: number) => 1 + (v / 100) * 0.5,\n /** −1…1 local-contrast amount (negative softens) */\n clarity: (v: number) => v / 100,\n /** −1…1 (positive darkens the edges, negative lightens them) */\n vignette: (v: number) => v / 100,\n}\n\n/** The matrix-based finetune adjustments (exposure → brightness → contrast → saturation → temperature). */\nexport function finetuneMatrix(f: Record<ImageFinetuneId, number>): ColorMatrix {\n const t = finetuneParam.temperature(f.temperature)\n return composeMatrices(\n channelMatrix(\n finetuneParam.exposure(f.exposure),\n finetuneParam.exposure(f.exposure),\n finetuneParam.exposure(f.exposure),\n ),\n brightnessMatrix(finetuneParam.brightness(f.brightness)),\n contrastMatrix(finetuneParam.contrast(f.contrast)),\n saturationMatrix(finetuneParam.saturation(f.saturation)),\n channelMatrix(1 + 0.12 * t, 1 + 0.02 * t, 1 - 0.12 * t),\n )\n}\n\n/** The whole color pipeline as one matrix: the filter, then the matrix-based finetune adjustments. */\nexport function combinedMatrix(\n colorMatrix: ColorMatrix | null,\n finetune: Record<ImageFinetuneId, number>,\n): ColorMatrix {\n return composeMatrices(colorMatrix ?? IDENTITY_MATRIX, finetuneMatrix(finetune))\n}\n","// Geometry of the editor — pure math over `ImageState` (no DOM).\n//\n// Model: the source image (W×H, top-left at 0,0) is flipped (F), rotated (R(θ)) and scaled (s) about its\n// own center C = (W/2, H/2) into a \"plane\"; the crop is an axis-aligned rect in that plane:\n//\n// plane point q = C + s · R(θ) · F · (p − C) (p = a source pixel position)\n// source point p = C + F · R(−θ) · (q − C) / s\n//\n// y points down, so a positive θ turns the image clockwise on screen. The image must always cover the\n// crop: every crop corner, taken back to the image's own frame u = R(−θ)(q − C)/s, has |uₓ| ≤ W/2 and\n// |u_y| ≤ H/2. The flip doesn't change that test (the image rect is symmetric about C).\n\nimport type { ImageRect, ImageState } from './types'\nimport { ZERO_FINETUNE } from './matrix'\n\nexport interface Size {\n width: number\n height: number\n}\nexport type Vec = [number, number]\n\nconst QUARTER = Math.PI / 2\nconst EPS = 1e-6\n\n/** Rotate a vector by θ (positive = clockwise on a y-down screen). */\nexport const rotate = ([x, y]: Vec, theta: number): Vec => {\n const c = Math.cos(theta)\n const s = Math.sin(theta)\n return [x * c - y * s, x * s + y * c]\n}\n\n/** Half the size of a w×h box's bounding box once it's turned by θ. */\nexport function halfExtents(w: number, h: number, theta: number): Vec {\n const c = Math.abs(Math.cos(theta))\n const s = Math.abs(Math.sin(theta))\n return [(w / 2) * c + (h / 2) * s, (w / 2) * s + (h / 2) * c]\n}\n\n/** The crop's center. */\nexport const cropCenter = (crop: ImageRect): Vec => [\n crop.x + crop.width / 2,\n crop.y + crop.height / 2,\n]\n\n/**\n * The minimum `scale` at which an image of `size` covers a w×h crop turned by θ **when centered on the\n * image** — the \"cover\" scale every zoom is measured from (zoom = scale / coverScale).\n */\nexport function coverScale(w: number, h: number, theta: number, size: Size): number {\n const [ex, ey] = halfExtents(w, h, theta)\n return Math.max((2 * ex) / size.width, (2 * ey) / size.height)\n}\n\n/** The image point (image-centered, unrotated, unscaled) under the crop's center. */\nexport function cropAnchor(state: ImageState, size: Size): Vec {\n const [kx, ky] = cropCenter(state.crop)\n const [ux, uy] = rotate([kx - size.width / 2, ky - size.height / 2], -state.rotation)\n return [ux / state.scale, uy / state.scale]\n}\n\n/** Clamp the crop anchor so a w×h crop (turned by θ, image scaled by s) stays inside the image. */\nexport function clampAnchor(\n [ux, uy]: Vec,\n w: number,\n h: number,\n theta: number,\n s: number,\n size: Size,\n): Vec {\n const [ex, ey] = halfExtents(w, h, theta)\n const lx = Math.max(0, size.width / 2 - ex / s)\n const ly = Math.max(0, size.height / 2 - ey / s)\n return [Math.min(lx, Math.max(-lx, ux)), Math.min(ly, Math.max(-ly, uy))]\n}\n\n/** Place a w×h crop so its center sits over image point `u` (inverse of `cropAnchor`). */\nexport function cropAt(u: Vec, w: number, h: number, theta: number, s: number, size: Size) {\n const [dx, dy] = rotate([u[0] * s, u[1] * s], theta)\n const kx = size.width / 2 + dx\n const ky = size.height / 2 + dy\n return { x: kx - w / 2, y: ky - h / 2, width: w, height: h }\n}\n\n/** Whether the image fully covers `crop` (with a small tolerance). */\nexport function coversCrop(crop: ImageRect, theta: number, s: number, size: Size): boolean {\n const corners: Vec[] = [\n [crop.x, crop.y],\n [crop.x + crop.width, crop.y],\n [crop.x, crop.y + crop.height],\n [crop.x + crop.width, crop.y + crop.height],\n ]\n // a float-noise tolerance only — anything looser lets a crop overshoot the image by real pixels\n const tol = 1e-6 * Math.max(size.width, size.height)\n return corners.every(([qx, qy]) => {\n const [ux, uy] = rotate([qx - size.width / 2, qy - size.height / 2], -theta)\n return (\n Math.abs(ux / s) <= size.width / 2 + tol / s && Math.abs(uy / s) <= size.height / 2 + tol / s\n )\n })\n}\n\n/**\n * Re-fit a state so the image covers the crop: the scale is raised to at least the cover scale, then the\n * anchor (the image point under the crop's center) is clamped. The crop's size never changes here.\n */\nexport function fitState(state: ImageState, size: Size): ImageState {\n const { width: w, height: h } = state.crop\n const s = Math.max(state.scale, coverScale(w, h, state.rotation, size))\n const u = clampAnchor(cropAnchor({ ...state, scale: s }, size), w, h, state.rotation, s, size)\n return { ...state, scale: s, crop: cropAt(u, w, h, state.rotation, s, size) }\n}\n\n/** The output size in pixels — the crop at full source resolution. */\nexport function outputSize(state: ImageState): Size {\n return {\n width: Math.max(1, Math.round(state.crop.width / state.scale)),\n height: Math.max(1, Math.round(state.crop.height / state.scale)),\n }\n}\n\n/** The size `process()` renders — the Resize tool's pick, else the crop at full resolution. */\nexport function finalSize(state: ImageState): Size {\n const out = outputSize(state)\n if (!state.resize) return out\n return {\n width: Math.max(1, Math.min(out.width, Math.round(state.resize.width))),\n height: Math.max(1, Math.min(out.height, Math.round(state.resize.height))),\n }\n}\n\n/**\n * The part of the crop the output shows — the crop itself, or for a Resize pick of another aspect its\n * largest centered sub-rect of that aspect (`object-fit: cover`: the image is cut, never squashed).\n */\nexport function resizedCrop(state: ImageState): ImageRect {\n const { crop } = state\n const r = state.resize\n if (!r) return crop\n const target = r.width / r.height\n const aspect = crop.width / crop.height\n if (Math.abs(aspect - target) < 1e-9 * Math.max(aspect, target)) return crop\n if (aspect > target) {\n const width = crop.height * target\n return { ...crop, x: crop.x + (crop.width - width) / 2, width }\n }\n const height = crop.width / target\n return { ...crop, y: crop.y + (crop.height - height) / 2, height }\n}\n\n/**\n * Apply a Resize pick to `base` (the state the pick is made from). A size of the crop's own aspect just\n * scales the output; another aspect first cuts the crop to it — its largest centered part of that aspect\n * (`object-fit: cover`) — so the Crop tool shows exactly what's kept. `null` (or the crop's full size)\n * clears it. The size never goes above what `base`'s crop holds.\n */\nexport function applyResize(base: ImageState, pick: Size | null): ImageState {\n if (!pick) return { ...base, resize: null }\n const out = outputSize(base)\n const width = Math.max(1, Math.min(out.width, Math.round(pick.width)))\n const height = Math.max(1, Math.min(out.height, Math.round(pick.height)))\n // proportional when the other side, derived from this one, rounds to what was asked\n const proportional =\n Math.round((width * out.height) / out.width) === height ||\n Math.round((height * out.width) / out.height) === width\n let next: ImageState = base\n if (!proportional) {\n const crop = resizedCrop({ ...base, resize: { width, height } })\n // a picked Crop Shape no longer holds — the crop is custom now\n next = { ...base, crop, cropRatio: null }\n }\n const full = outputSize(next)\n const resize =\n width >= full.width && height >= full.height\n ? null\n : { width: Math.min(width, full.width), height: Math.min(height, full.height) }\n return { ...next, resize }\n}\n\n/**\n * Keep a Resize pick in step when the crop changes under it: it keeps its share of the crop (a 25% pick\n * stays 25% of the new crop), so the result size follows the crop. Unchanged when no resize is set or the\n * crop's output size didn't move.\n */\nexport function syncResize(prev: ImageState, next: ImageState): ImageState['resize'] {\n const r = next.resize\n if (!r) return r\n const before = outputSize(prev)\n const after = outputSize(next)\n if (before.width === after.width && before.height === after.height) return r\n const width = Math.max(\n 1,\n Math.min(after.width, Math.round((r.width * after.width) / before.width)),\n )\n const height = Math.max(\n 1,\n Math.min(after.height, Math.round((r.height * after.height) / before.height)),\n )\n return width === after.width && height === after.height ? null : { width, height }\n}\n\n/** The largest crop of the given ratio that fits the (unrotated) image, centered. */\nexport function initialCrop(size: Size, aspectRatio?: number | null): ImageRect {\n let w = size.width\n let h = size.height\n if (aspectRatio && aspectRatio > 0) {\n if (w / h > aspectRatio) w = h * aspectRatio\n else h = w / aspectRatio\n }\n return { x: (size.width - w) / 2, y: (size.height - h) / 2, width: w, height: h }\n}\n\n/** The untouched state for an image of `size`. */\nexport function defaultState(size: Size, aspectRatio?: number | null): ImageState {\n return {\n crop: initialCrop(size, aspectRatio),\n cropRatio: aspectRatio && aspectRatio > 0 ? aspectRatio : null,\n resize: null,\n rotation: 0,\n flipX: false,\n flipY: false,\n scale: 1,\n filter: null,\n colorMatrix: null,\n finetune: { ...ZERO_FINETUNE },\n redact: { effect: 'blur', amount: 0 },\n }\n}\n\n// ── rotation ────────────────────────────────────────────────────────────────────────────────────\n\n/** Split a rotation into its quarter turns (multiple of π/2, normalized to [0, 2π)) + the fine part. */\nexport function splitRotation(\n theta: number,\n quarterHint?: number,\n): { quarter: number; fine: number } {\n const turns = (((Math.round(theta / QUARTER) % 4) + 4) % 4) as 0 | 1 | 2 | 3\n const quarter = quarterHint ?? turns * QUARTER\n let fine = theta - quarter\n // wrap the fine part into (−π, π] relative to the quarter\n fine = Math.atan2(Math.sin(fine), Math.cos(fine))\n return { quarter: normalizeAngle(quarter), fine }\n}\n\n/** Normalize an angle into [0, 2π). */\nexport const normalizeAngle = (a: number) => {\n const t = a % (2 * Math.PI)\n const n = t < 0 ? t + 2 * Math.PI : t\n return Math.abs(n - 2 * Math.PI) < EPS ? 0 : n\n}\n\n/**\n * Set the rotation to `theta`, keeping the same image point under the crop's center: the image scales up\n * to cover the crop when needed (never below `base.scale`) and the anchor is clamped. `base` is the state\n * at the start of the interaction, so turning back restores the original zoom.\n */\nexport function rotateTo(base: ImageState, theta: number, size: Size): ImageState {\n const { width: w, height: h } = base.crop\n const u = cropAnchor(base, size)\n const s = Math.max(base.scale, coverScale(w, h, theta, size))\n const clamped = clampAnchor(u, w, h, theta, s, size)\n return { ...base, rotation: theta, scale: s, crop: cropAt(clamped, w, h, theta, s, size) }\n}\n\n/** Rotate the whole image −90° (counter-clockwise): the crop turns with it (its width/height swap, and so\n * does a picked crop shape — 16:9 becomes 9:16). */\nexport function rotateLeft(state: ImageState, size: Size): ImageState {\n const [kx, ky] = cropCenter(state.crop)\n const cx = size.width / 2\n const cy = size.height / 2\n const [dx, dy] = rotate([kx - cx, ky - cy], -QUARTER)\n const w = state.crop.height\n const h = state.crop.width\n return {\n ...state,\n rotation: state.rotation - QUARTER,\n crop: { x: cx + dx - w / 2, y: cy + dy - h / 2, width: w, height: h },\n cropRatio: state.cropRatio ? 1 / state.cropRatio : state.cropRatio,\n }\n}\n\n/** Mirror the result horizontally (the image flips inside the crop; the crop mirrors about the center). */\nexport function flipHorizontal(state: ImageState, size: Size): ImageState {\n return {\n ...state,\n rotation: -state.rotation,\n flipX: !state.flipX,\n crop: { ...state.crop, x: size.width - state.crop.x - state.crop.width },\n }\n}\n\n// ── scale / pan ─────────────────────────────────────────────────────────────────────────────────\n\n/** The current zoom relative to the cover scale (1 = the image just covers the crop). */\nexport function zoomOf(state: ImageState, size: Size): number {\n return state.scale / coverScale(state.crop.width, state.crop.height, state.rotation, size)\n}\n\n/** The largest zoom inside the crop (relative to the cover scale) — 500%. */\nexport const MAX_CROP_ZOOM = 5\n\n/**\n * Set the zoom (1…`MAX_CROP_ZOOM`, relative to the cover scale), keeping the image point under the\n * crop's center.\n */\nexport function zoomTo(state: ImageState, zoom: number, size: Size): ImageState {\n const { width: w, height: h } = state.crop\n const u = cropAnchor(state, size)\n const s = coverScale(w, h, state.rotation, size) * Math.min(MAX_CROP_ZOOM, Math.max(1, zoom))\n const clamped = clampAnchor(u, w, h, state.rotation, s, size)\n return { ...state, scale: s, crop: cropAt(clamped, w, h, state.rotation, s, size) }\n}\n\n/** Move the crop across the image by (dx, dy) plane units (the image moves the other way on screen). */\nexport function panBy(state: ImageState, dx: number, dy: number, size: Size): ImageState {\n const { width: w, height: h } = state.crop\n const moved = { ...state, crop: { ...state.crop, x: state.crop.x + dx, y: state.crop.y + dy } }\n const u = clampAnchor(cropAnchor(moved, size), w, h, state.rotation, state.scale, size)\n return { ...state, crop: cropAt(u, w, h, state.rotation, state.scale, size) }\n}\n\n// ── crop shape ──────────────────────────────────────────────────────────────────────────────────\n\n/**\n * Pick a crop shape: `ratio` (width / height) reshapes the crop into the largest rect of that ratio the\n * image covers at the current rotation + zoom, kept over the same image point (moved only as far as it\n * must to stay on the image); `null` frees it (the crop itself is left as is).\n */\nexport function setCropRatio(state: ImageState, ratio: number | null, size: Size): ImageState {\n if (!ratio || ratio <= 0) return { ...state, cropRatio: null }\n const c = Math.abs(Math.cos(state.rotation))\n const s = Math.abs(Math.sin(state.rotation))\n // the cover condition, solved for the height of a ratio-r crop centered on the image\n const h = Math.min(\n (size.width * state.scale) / (ratio * c + s),\n (size.height * state.scale) / (ratio * s + c),\n )\n const w = h * ratio\n const u = clampAnchor(cropAnchor(state, size), w, h, state.rotation, state.scale, size)\n return {\n ...state,\n cropRatio: ratio,\n crop: cropAt(u, w, h, state.rotation, state.scale, size),\n }\n}\n\n// ── crop resize ─────────────────────────────────────────────────────────────────────────────────\n\nexport type CropHandle = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw'\n\nexport interface ResizeOptions {\n /** Lock the crop to this width/height ratio. */\n aspectRatio?: number | null\n /** The smallest crop side, in plane units. */\n minSize: number\n}\n\n/**\n * Resize the crop by dragging `handle` by (dx, dy) plane units from the interaction's `start` state. A\n * corner moves against its opposite corner, an edge moves one side (with a locked ratio the other side\n * follows, centered). The result never leaves the image: an out-of-bounds request is pulled back along\n * the way from `start` to it (so it stops at the image's edge instead of jumping).\n */\nexport function resizeCrop(\n start: ImageState,\n handle: CropHandle,\n dx: number,\n dy: number,\n size: Size,\n { aspectRatio, minSize }: ResizeOptions,\n): ImageState {\n const c = start.crop\n let left = c.x\n let top = c.y\n let right = c.x + c.width\n let bottom = c.y + c.height\n const hasN = handle.includes('n')\n const hasS = handle.includes('s')\n const hasW = handle.includes('w')\n const hasE = handle.includes('e')\n if (hasN) top = Math.min(top + dy, bottom - minSize)\n if (hasS) bottom = Math.max(bottom + dy, top + minSize)\n if (hasW) left = Math.min(left + dx, right - minSize)\n if (hasE) right = Math.max(right + dx, left + minSize)\n\n if (aspectRatio && aspectRatio > 0) {\n let w = right - left\n let h = bottom - top\n const corner = (hasN || hasS) && (hasW || hasE)\n if (corner) {\n // follow whichever side moved more (relative to the ratio), anchored at the opposite corner\n if (w / h > aspectRatio) h = w / aspectRatio\n else w = h * aspectRatio\n if (hasW) left = right - w\n else right = left + w\n if (hasN) top = bottom - h\n else bottom = top + h\n } else if (hasN || hasS) {\n w = h * aspectRatio\n const cx = c.x + c.width / 2\n left = cx - w / 2\n right = cx + w / 2\n } else {\n h = w / aspectRatio\n const cy = c.y + c.height / 2\n top = cy - h / 2\n bottom = cy + h / 2\n }\n }\n\n const target: ImageRect = { x: left, y: top, width: right - left, height: bottom - top }\n const fits = (r: ImageRect) => coversCrop(r, start.rotation, start.scale, size)\n if (fits(target)) return { ...start, crop: target }\n const free = !(aspectRatio && aspectRatio > 0) && (hasN || hasS) && (hasW || hasE)\n if (!free) return { ...start, crop: furthest(c, target, fits) }\n // a free corner past the image edge: each axis stops at the edge on its own, so the corner keeps\n // sliding along the edge after the pointer (one shared stop would leave it short on the other axis)\n const horizontal = (from: ImageRect): ImageRect => ({ ...from, x: left, width: right - left })\n const vertical = (from: ImageRect): ImageRect => ({ ...from, y: top, height: bottom - top })\n const viaX = furthest(furthest(c, horizontal(c), fits), vertical, fits)\n const viaY = furthest(furthest(c, vertical(c), fits), horizontal, fits)\n // the order that ends closer to where the pointer asked for\n const miss = (r: ImageRect) =>\n Math.abs(r.x - target.x) +\n Math.abs(r.y - target.y) +\n Math.abs(r.width - target.width) +\n Math.abs(r.height - target.height)\n return { ...start, crop: miss(viaX) <= miss(viaY) ? viaX : viaY }\n}\n\n/**\n * The furthest rect along the straight path from `from` (valid) toward `to` (or `to(from)`) that still\n * passes `fits` — binary-searched.\n */\nfunction furthest(\n from: ImageRect,\n to: ImageRect | ((from: ImageRect) => ImageRect),\n fits: (r: ImageRect) => boolean,\n): ImageRect {\n const dest = typeof to === 'function' ? to(from) : to\n if (fits(dest)) return dest\n let lo = 0\n let hi = 1\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2\n if (fits(lerpRect(from, dest, mid))) lo = mid\n else hi = mid\n }\n return lerpRect(from, dest, lo)\n}\n\nconst lerpRect = (a: ImageRect, b: ImageRect, t: number): ImageRect => ({\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n width: a.width + (b.width - a.width) * t,\n height: a.height + (b.height - a.height) * t,\n})\n\n/** Clamp a state's crop + scale into a valid configuration (used on `setState` / `initialState`). */\nexport function normalizeState(state: ImageState, size: Size): ImageState {\n const crop = {\n ...state.crop,\n width: Math.max(1, state.crop.width),\n height: Math.max(1, state.crop.height),\n }\n return fitState({ ...state, crop, scale: Math.max(EPS, state.scale || 1) }, size)\n}\n","// The CPU side of the color pipeline — the exact math the WebGL fragment shader runs, over RGBA bytes.\n// Used for the Canvas2D fallback (no WebGL), the filter thumbnails, and the unit tests.\n\nimport type { Affine } from './affine'\nimport { type ColorMatrix } from './matrix'\n\n/** Every non-geometry parameter of one render. */\nexport interface ColorParams {\n /** The combined filter + matrix-finetune matrix. */\n matrix: ColorMatrix\n /** Gamma exponent (1 = none), applied as x^(1/γ). */\n gamma: number\n /** Local-contrast amount −1…1 (0 = none). */\n clarity: number\n /** Vignette amount −1…1 (0 = none). */\n vignette: number\n}\n\n/** How strongly a full vignette darkens / lightens the corners. */\nexport const VIGNETTE_STRENGTH = 0.85\n\nconst smoothstep = (e0: number, e1: number, x: number) => {\n const t = Math.min(1, Math.max(0, (x - e0) / (e1 - e0)))\n return t * t * (3 - 2 * t)\n}\n\n/** The vignette falloff at crop-normalized (−1…1) coords: 0 in the middle, 1 in the corners. */\nexport const vignetteFalloff = (nx: number, ny: number) =>\n smoothstep(0.3, 1, Math.hypot(nx, ny) / Math.SQRT2)\n\n/**\n * Apply the color pipeline in place: matrix → clarity (against `blur`, the same pixels blurred) → gamma\n * → vignette (positioned by `toCrop`, pixel → crop-normalized coords). Alpha is straight (non-premultiplied).\n */\nexport function applyColorOps(\n data: Uint8ClampedArray,\n width: number,\n height: number,\n p: ColorParams,\n blur?: Uint8ClampedArray | null,\n toCrop?: Affine | null,\n): void {\n const m = p.matrix\n const invGamma = 1 / p.gamma\n const useGamma = Math.abs(p.gamma - 1) > 1e-4\n const useClarity = Math.abs(p.clarity) > 1e-4 && !!blur\n const useVignette = Math.abs(p.vignette) > 1e-4 && !!toCrop\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const i = (y * width + x) * 4\n const a = data[i + 3] / 255\n if (a === 0) continue\n const r0 = data[i] / 255\n const g0 = data[i + 1] / 255\n const b0 = data[i + 2] / 255\n let r = m[0] * r0 + m[1] * g0 + m[2] * b0 + m[3] * a + m[4]\n let g = m[5] * r0 + m[6] * g0 + m[7] * b0 + m[8] * a + m[9]\n let b = m[10] * r0 + m[11] * g0 + m[12] * b0 + m[13] * a + m[14]\n if (useClarity) {\n const br = blur![i] / 255\n const bg = blur![i + 1] / 255\n const bb = blur![i + 2] / 255\n const ba = blur![i + 3] / 255\n const mr = m[0] * br + m[1] * bg + m[2] * bb + m[3] * ba + m[4]\n const mg = m[5] * br + m[6] * bg + m[7] * bb + m[8] * ba + m[9]\n const mb = m[10] * br + m[11] * bg + m[12] * bb + m[13] * ba + m[14]\n r += p.clarity * (r - mr)\n g += p.clarity * (g - mg)\n b += p.clarity * (b - mb)\n }\n if (useGamma) {\n r = Math.pow(Math.max(0, r), invGamma)\n g = Math.pow(Math.max(0, g), invGamma)\n b = Math.pow(Math.max(0, b), invGamma)\n }\n if (useVignette) {\n const px = x + 0.5\n const py = y + 0.5\n const nx = toCrop![0] * px + toCrop![1] * py + toCrop![2]\n const ny = toCrop![3] * px + toCrop![4] * py + toCrop![5]\n const f = vignetteFalloff(nx, ny) * VIGNETTE_STRENGTH * Math.abs(p.vignette)\n if (p.vignette > 0) {\n r *= 1 - f\n g *= 1 - f\n b *= 1 - f\n } else {\n r += (1 - r) * f\n g += (1 - g) * f\n b += (1 - b) * f\n }\n }\n data[i] = r * 255\n data[i + 1] = g * 255\n data[i + 2] = b * 255\n }\n }\n}\n\n/** A fast approximate Gaussian blur (three box passes, horizontal + vertical) over RGBA bytes. */\nexport function boxBlur(\n src: Uint8ClampedArray,\n width: number,\n height: number,\n radius: number,\n): Uint8ClampedArray {\n const r = Math.max(1, Math.round(radius))\n const a = new Uint8ClampedArray(src)\n const b = new Uint8ClampedArray(src.length)\n for (let pass = 0; pass < 3; pass++) {\n blurLine(a, b, width, height, r, true)\n blurLine(b, a, width, height, r, false)\n }\n return a\n function blurLine(\n from: Uint8ClampedArray,\n to: Uint8ClampedArray,\n w: number,\n h: number,\n rad: number,\n horizontal: boolean,\n ) {\n const lines = horizontal ? h : w\n const len = horizontal ? w : h\n const stride = horizontal ? 4 : w * 4\n const span = rad * 2 + 1\n for (let l = 0; l < lines; l++) {\n const base = horizontal ? l * w * 4 : l * 4\n for (let c = 0; c < 4; c++) {\n // running sum with clamped edges\n let sum = 0\n for (let k = -rad; k <= rad; k++) {\n const idx = Math.min(len - 1, Math.max(0, k))\n sum += from[base + idx * stride + c]\n }\n for (let k = 0; k < len; k++) {\n to[base + k * stride + c] = sum / span\n const out = Math.max(0, k - rad)\n const inn = Math.min(len - 1, k + rad + 1)\n sum += from[base + inn * stride + c] - from[base + out * stride + c]\n }\n }\n }\n }\n}\n","// Image loading + the derived bitmaps the renderers use (a downscaled preview, a blurred copy for clarity).\n\nimport { boxBlur } from './pixels'\n\nexport type ImageSource = ImageBitmap | HTMLImageElement | HTMLCanvasElement\n\nexport interface LoadedImage {\n /** The full-resolution, EXIF-oriented image. */\n image: ImageSource\n width: number\n height: number\n /** The input's MIME type ('' when unknown). */\n type: string\n}\n\n/** The clarity blur radius, as a fraction of the image's long side. */\nexport const CLARITY_RADIUS = 0.012\n\nconst canvasOf = (w: number, h: number) => {\n const c = document.createElement('canvas')\n c.width = Math.max(1, Math.round(w))\n c.height = Math.max(1, Math.round(h))\n return c\n}\n\nasync function decodeBlob(blob: Blob): Promise<ImageSource> {\n if (typeof createImageBitmap === 'function') {\n try {\n return await createImageBitmap(blob, { imageOrientation: 'from-image' })\n } catch {\n // fall through to <img> (some browsers can't decode e.g. SVG into a bitmap)\n }\n }\n const url = URL.createObjectURL(blob)\n try {\n return await decodeUrl(url, false)\n } finally {\n URL.revokeObjectURL(url)\n }\n}\n\nfunction decodeUrl(url: string, crossOrigin: boolean): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image()\n if (crossOrigin) img.crossOrigin = 'anonymous'\n img.decoding = 'async'\n img.onload = () => resolve(img)\n img.onerror = () => reject(new Error(`Could not load image: ${url.slice(0, 80)}`))\n img.src = url\n })\n}\n\nconst sizeOf = (img: ImageSource) =>\n img instanceof HTMLImageElement\n ? { width: img.naturalWidth, height: img.naturalHeight }\n : { width: img.width, height: img.height }\n\n/** Load a File / Blob / URL / data URL into a decoded, EXIF-oriented image. */\nexport async function loadImage(src: File | Blob | string): Promise<LoadedImage> {\n let image: ImageSource\n let type = ''\n if (typeof src === 'string') {\n try {\n const res = await fetch(src)\n if (!res.ok) throw new Error(String(res.status))\n const blob = await res.blob()\n type = blob.type\n image = await decodeBlob(blob)\n } catch {\n // a cross-origin URL without CORS can't be fetched — decode it through <img> (CORS-enabled, so the\n // canvas stays exportable when the server allows it)\n image = await decodeUrl(src, !src.startsWith('data:') && !src.startsWith('blob:'))\n const m = /^data:([^;,]+)/.exec(src) ?? /\\.(png|jpe?g|webp|gif|avif)(?:[?#]|$)/i.exec(src)\n if (m) type = m[1].includes('/') ? m[1] : `image/${m[1].toLowerCase().replace('jpg', 'jpeg')}`\n }\n } else {\n type = src.type\n image = await decodeBlob(src)\n }\n const { width, height } = sizeOf(image)\n if (!width || !height) throw new Error('The image has no size')\n return { image, width, height, type }\n}\n\n/** A copy of `source` no larger than `maxSide` on its long side (the source itself when it already fits). */\nexport function downscale(\n source: CanvasImageSource,\n width: number,\n height: number,\n maxSide: number,\n): { canvas: CanvasImageSource; width: number; height: number } {\n const k = Math.min(1, maxSide / Math.max(width, height))\n if (k >= 1) return { canvas: source, width, height }\n const c = canvasOf(width * k, height * k)\n const ctx = c.getContext('2d')\n if (ctx) {\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(source, 0, 0, c.width, c.height)\n }\n return { canvas: c, width: c.width, height: c.height }\n}\n\n/**\n * A small, blurred copy of `source` (≤ `maxSide`) for the clarity (local-contrast) pass. `radius` is the\n * blur radius in `source` pixels — it's scaled down with the copy, so the effect matches at any size.\n */\nexport function blurredCopy(\n source: CanvasImageSource,\n width: number,\n height: number,\n radius: number,\n maxSide = 384,\n): HTMLCanvasElement {\n const k = Math.min(1, maxSide / Math.max(width, height))\n const c = canvasOf(width * k, height * k)\n const ctx = c.getContext('2d', { willReadFrequently: true })\n if (!ctx) return c\n ctx.drawImage(source, 0, 0, c.width, c.height)\n try {\n const data = ctx.getImageData(0, 0, c.width, c.height)\n data.data.set(boxBlur(data.data, c.width, c.height, Math.max(1, radius * k)))\n ctx.putImageData(data, 0, 0)\n } catch {\n // a tainted (cross-origin) canvas can't be read — clarity just has no effect then\n }\n return c\n}\n\n/** The output MIME type: the requested one, else the input's (when it's a type canvases encode), else PNG. */\nexport function resolveOutputType(requested: string | undefined, input: string): string {\n if (requested) return requested\n return ['image/jpeg', 'image/png', 'image/webp'].includes(input) ? input : 'image/png'\n}\n","// 2D affine transforms as [a, b, c, d, e, f]: x' = a·x + b·y + c, y' = d·x + e·y + f.\n\nexport type Affine = [number, number, number, number, number, number]\n\nexport const IDENTITY_AFFINE: Affine = [1, 0, 0, 0, 1, 0]\n\nexport const translate = (x: number, y: number): Affine => [1, 0, x, 0, 1, y]\nexport const scaleAffine = (sx: number, sy = sx): Affine => [sx, 0, 0, 0, sy, 0]\nexport const rotateAffine = (theta: number): Affine => {\n const c = Math.cos(theta)\n const s = Math.sin(theta)\n return [c, -s, 0, s, c, 0]\n}\n\n/** `a ∘ b` — apply `b` first, then `a`. */\nexport function multiplyAffine(a: Affine, b: Affine): Affine {\n return [\n a[0] * b[0] + a[1] * b[3],\n a[0] * b[1] + a[1] * b[4],\n a[0] * b[2] + a[1] * b[5] + a[2],\n a[3] * b[0] + a[4] * b[3],\n a[3] * b[1] + a[4] * b[4],\n a[3] * b[2] + a[4] * b[5] + a[5],\n ]\n}\n\n/** Compose in application order: `chain(t1, t2, t3)` applies t1, then t2, then t3. */\nexport const chain = (...ts: Affine[]): Affine =>\n ts.reduce((acc, t) => multiplyAffine(t, acc), IDENTITY_AFFINE)\n\nexport function invertAffine([a, b, c, d, e, f]: Affine): Affine {\n const det = a * e - b * d\n const k = Math.abs(det) < 1e-12 ? 1e12 : 1 / det\n return [e * k, -b * k, (b * f - c * e) * k, -d * k, a * k, (c * d - a * f) * k]\n}\n\nexport const applyAffine = ([a, b, c, d, e, f]: Affine, x: number, y: number): [number, number] => [\n a * x + b * y + c,\n d * x + e * y + f,\n]\n","// The Redact tool's effects (blur / pixelate over the whole image) — shared by the preview and the\n// full-resolution export, so both look the same.\n//\n// The blur is laid over the source image (it has no direction, so rotating doesn't change it). The\n// pixelation is laid over the *output*: its blocks follow the crop's grid, so they stay square and upright\n// whatever the image's rotation.\nimport { boxBlur } from './pixels'\nimport type { ImageRedactEffect, ImageState } from './types'\n\n/**\n * Each effect's size at `amount` 100, as a share of the image's long side: the blur radius (1.5% — past\n * that the image is just a wash) and the pixel block (5%).\n */\nexport const REDACT_MAX: Record<ImageRedactEffect, number> = { blur: 0.015, pixelate: 0.05 }\n\n/** The blur radius / pixel block side (source px) for a state — 0 when there's no effect. */\nexport function redactRadius(\n state: Pick<ImageState, 'redact'>,\n size: { width: number; height: number },\n) {\n const effect = state.redact?.effect ?? 'blur'\n const amount = Math.max(0, Math.min(100, state.redact?.amount ?? 0))\n return (amount / 100) * (REDACT_MAX[effect] ?? 0) * Math.max(size.width, size.height)\n}\n\n/**\n * The pixelation grid over a crop: whole blocks across and down (the block stretched a hair so they fit\n * exactly — no partial block at an edge). `block` is in the crop's own (plane) units.\n */\nexport function pixelGrid(\n crop: { width: number; height: number },\n block: number,\n): { cols: number; rows: number } {\n const b = Math.max(1e-6, block)\n return {\n cols: Math.max(1, Math.round(crop.width / b)),\n rows: Math.max(1, Math.round(crop.height / b)),\n }\n}\n\n/** The blur radius in working pixels it aims for (smaller copies for bigger blurs). */\nconst BLUR_WORK_RADIUS = 4\n\nconst canvasOf = (w: number, h: number) => {\n const c = document.createElement('canvas')\n c.width = Math.max(1, Math.round(w))\n c.height = Math.max(1, Math.round(h))\n return c\n}\n\n/**\n * A small blurred copy of `source` (`width` × `height`, `radius` in its pixels): it's sized so the radius\n * is a few pixels there, at most `maxSide` long — a blur has no fine detail, so scaling it back up\n * (on the GPU, or a canvas draw) loses nothing, and the small copy is quick to make while a ruler moves.\n */\nexport function blurredSmall(\n source: CanvasImageSource,\n width: number,\n height: number,\n radius: number,\n maxSide: number,\n): HTMLCanvasElement {\n const k = Math.min(1, BLUR_WORK_RADIUS / Math.max(1, radius), maxSide / Math.max(width, height))\n const work = canvasOf(width * k, height * k)\n const ctx = work.getContext('2d', { willReadFrequently: true })\n if (!ctx) return work\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(source, 0, 0, work.width, work.height)\n try {\n const data = ctx.getImageData(0, 0, work.width, work.height)\n data.data.set(boxBlur(data.data, work.width, work.height, Math.max(1, radius * k)))\n ctx.putImageData(data, 0, 0)\n } catch {\n // a tainted (cross-origin) canvas can't be read — the down / up scale alone still softens it\n }\n return work\n}\n\n/** A `width` × `height` blurred copy of `source` (`radius` in its pixels) — the export's blur. */\nexport function blurredFull(\n source: CanvasImageSource,\n width: number,\n height: number,\n radius: number,\n): HTMLCanvasElement {\n const out = canvasOf(width, height)\n const ctx = out.getContext('2d')\n if (!ctx) return out\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(blurredSmall(source, width, height, radius, 1024), 0, 0, width, height)\n return out\n}\n\n/** Pixelate a canvas in place into `cols` × `rows` blocks (each the average of what it covers). */\nexport function pixelateCanvas(canvas: HTMLCanvasElement, cols: number, rows: number) {\n const small = canvasOf(cols, rows)\n const sctx = small.getContext('2d')\n const ctx = canvas.getContext('2d')\n if (!sctx || !ctx) return\n sctx.imageSmoothingQuality = 'high'\n sctx.drawImage(canvas, 0, 0, small.width, small.height)\n ctx.save()\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n ctx.globalCompositeOperation = 'copy'\n ctx.imageSmoothingEnabled = false\n ctx.drawImage(small, 0, 0, canvas.width, canvas.height)\n ctx.restore()\n}\n\n/**\n * A `width` × `height` copy of `source` pixelated in its own pixel grid (`block` px) — only for the\n * Canvas2D preview fallback, which can't lay the output grid over a rotated image.\n */\nexport function pixelatedCopy(\n source: CanvasImageSource,\n width: number,\n height: number,\n block: number,\n): HTMLCanvasElement {\n const out = canvasOf(width, height)\n const ctx = out.getContext('2d')\n if (!ctx) return out\n ctx.drawImage(source, 0, 0, width, height)\n pixelateCanvas(\n out,\n Math.max(1, Math.round(width / Math.max(2, block))),\n Math.max(1, Math.round(height / Math.max(2, block))),\n )\n return out\n}\n","// Scene math: how the transformed image plane is laid out on screen (the \"view\"), and the affines the\n// renderers need (device pixel → texture / crop space).\n\nimport { chain, invertAffine, rotateAffine, scaleAffine, translate, type Affine } from './affine'\nimport { cropCenter, type Size, type Vec } from './geometry'\nimport type { ImageRect, ImageState } from './types'\n\n/** How the plane sits on screen. View-only — never part of `ImageState`. */\nexport interface View {\n /** The plane point shown at the stage's center. */\n center: Vec\n /** CSS pixels per plane unit. */\n scale: number\n /** Extra rotation (radians) — only non-zero while a rotate-left animates. */\n rotation: number\n /** Horizontal mirror factor (1 = none) — only ≠ 1 while a flip animates (−1 → 1). */\n flip: number\n}\n\n/** The stage the view is drawn in (CSS pixels) + the device pixel ratio. */\nexport interface Stage {\n width: number\n height: number\n dpr: number\n /**\n * The free area the crop is laid out in (CSS px, relative to the stage) — the canvas spans the whole\n * editor, behind the toolbars, but the crop fits + centers in the space between them. Defaults to the\n * whole stage.\n */\n area?: { x: number; y: number; width: number; height: number }\n}\n\n/** The point on screen the view's center lands on (the free area's center). */\nexport const stageOrigin = (stage: Pick<Stage, 'width' | 'height' | 'area'>): [number, number] =>\n stage.area\n ? [stage.area.x + stage.area.width / 2, stage.area.y + stage.area.height / 2]\n : [stage.width / 2, stage.height / 2]\n\n/** source pixel → plane (the image state's flip / rotation / scale about the image center). */\nexport function sourceToPlane(state: ImageState, size: Size): Affine {\n const cx = size.width / 2\n const cy = size.height / 2\n return chain(\n translate(-cx, -cy),\n scaleAffine(state.flipX ? -1 : 1, state.flipY ? -1 : 1),\n rotateAffine(state.rotation),\n scaleAffine(state.scale),\n translate(cx, cy),\n )\n}\n\n/** plane → stage CSS pixels. */\nexport function planeToScreen(view: View, stage: Pick<Stage, 'width' | 'height' | 'area'>): Affine {\n // keep the mirror factor off exact zero (the mid-point of a flip animation) so it stays invertible\n const flip = Math.abs(view.flip) < 0.02 ? 0.02 * Math.sign(view.flip || 1) : view.flip\n const [ox, oy] = stageOrigin(stage)\n return chain(\n translate(-view.center[0], -view.center[1]),\n rotateAffine(view.rotation),\n scaleAffine(view.scale * flip, view.scale),\n translate(ox, oy),\n )\n}\n\n/** plane → crop-normalized coords (−1…1 across the crop). */\nexport function planeToCrop(crop: ImageRect): Affine {\n const [kx, ky] = cropCenter(crop)\n return chain(translate(-kx, -ky), scaleAffine(2 / crop.width, 2 / crop.height))\n}\n\n/** The affines a renderer needs to draw `state` in `view` on `stage`. */\nexport function sceneAffines(state: ImageState, size: Size, view: View, stage: Stage) {\n const deviceToPlane = chain(scaleAffine(1 / stage.dpr), invertAffine(planeToScreen(view, stage)))\n const toUV = chain(\n deviceToPlane,\n invertAffine(sourceToPlane(state, size)),\n scaleAffine(1 / size.width, 1 / size.height),\n )\n return { toUV, toBlurUV: toUV, toCrop: chain(deviceToPlane, planeToCrop(state.crop)) }\n}\n\n/** The view that fits the crop in the stage with `padding` CSS px around it. */\nexport function fitView(\n crop: ImageRect,\n stage: Pick<Stage, 'width' | 'height'>,\n padding: number,\n): View {\n const w = Math.max(1, stage.width - padding * 2)\n const h = Math.max(1, stage.height - padding * 2)\n return {\n center: cropCenter(crop),\n scale: Math.min(w / crop.width, h / crop.height),\n rotation: 0,\n flip: 1,\n }\n}\n","// The WebGL renderer — one full-canvas quad whose fragment shader maps every device pixel back to the source\n// texture (geometry as an affine) and runs the color pipeline (the same math as `pixels.ts`). GLSL ES 1.00,\n// so the one shader runs on WebGL2 (preferred — mipmapped non-power-of-two textures) and WebGL1.\n\nimport type { Affine } from './affine'\nimport { VIGNETTE_STRENGTH, type ColorParams } from './pixels'\n\n/** One draw's inputs. */\nexport interface RenderParams extends ColorParams {\n /** device pixel (top-left origin, y down) → image texture coords (0…1). */\n toUV: Affine\n /** device pixel → blur texture coords (0…1). */\n toBlurUV: Affine\n /** device pixel → crop-normalized coords (−1…1 across the crop) — vignette + clipping. */\n toCrop: Affine\n /** Draw nothing outside the crop (the Filter / Finetune views, export). */\n clip: boolean\n /** How much of the image shows outside the crop (the Crop view fades it into the background); 1 = all. */\n dim?: number\n /** The color the image fades into outside the crop (0…1 rgb — the theme's background). */\n dimColor?: [number, number, number]\n /**\n * Pixelate into this many blocks across × down the crop (`null` = off): every pixel samples its\n * block's center, so the blocks follow the crop's grid, not the (maybe rotated) image's.\n */\n pixel?: [number, number] | null\n /** crop-normalized coords → image texture coords (needed with `pixel`). */\n cropToUV?: Affine\n}\n\nconst VERTEX = `\nattribute vec2 a_pos;\nvoid main() { gl_Position = vec4(a_pos, 0.0, 1.0); }\n`\n\nconst FRAGMENT = `\n#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\nuniform sampler2D u_image;\nuniform sampler2D u_blur;\nuniform vec2 u_size;\nuniform vec3 u_uvX; uniform vec3 u_uvY;\nuniform vec3 u_blurX; uniform vec3 u_blurY;\nuniform vec3 u_cropX; uniform vec3 u_cropY;\nuniform bool u_clip;\nuniform float u_dim;\nuniform vec3 u_dimColor;\nuniform mat4 u_cm; uniform vec4 u_co;\nuniform float u_gamma; uniform float u_clarity; uniform float u_vignette;\nuniform vec2 u_pixel; uniform vec3 u_cuvX; uniform vec3 u_cuvY;\n\nvec3 grade(vec4 c) { return (u_cm * c + u_co).rgb; }\n\nvoid main() {\n vec3 px = vec3(gl_FragCoord.x, u_size.y - gl_FragCoord.y, 1.0);\n vec2 cn = vec2(dot(u_cropX, px), dot(u_cropY, px));\n // the pixel's own place in the crop (before a pixelation snaps cn to its block) — for the clip\n bool outsideCrop = abs(cn.x) > 1.0 || abs(cn.y) > 1.0;\n vec2 uv = vec2(dot(u_uvX, px), dot(u_uvY, px));\n vec2 buv = vec2(dot(u_blurX, px), dot(u_blurY, px));\n if (u_pixel.x > 0.0) {\n // the center of this pixel's block (whole blocks across the crop; the edge pixel stays in the last)\n vec2 cell = 2.0 / u_pixel;\n vec2 idx = floor((cn + 1.0) / cell);\n if (abs(cn.x) <= 1.0) idx.x = min(idx.x, u_pixel.x - 1.0);\n if (abs(cn.y) <= 1.0) idx.y = min(idx.y, u_pixel.y - 1.0);\n cn = (idx + 0.5) * cell - 1.0;\n vec3 q = vec3(cn, 1.0);\n uv = vec2(dot(u_cuvX, q), dot(u_cuvY, q));\n buv = uv;\n }\n // sample BEFORE any early return: a texture read in a branch only some pixels of a 2×2 quad take has no\n // defined derivatives, so at the image's edge the GPU picked a far too coarse mip level — a blurred\n // copy of the content showed through as a faint line along a transparent image's sides\n vec4 c = texture2D(u_image, uv);\n vec4 bl = texture2D(u_blur, buv);\n if ((u_clip && outsideCrop) || uv.x < 0.0 || uv.y < 0.0 || uv.x > 1.0 || uv.y > 1.0 || c.a <= 0.0) {\n gl_FragColor = vec4(0.0);\n return;\n }\n vec3 rgb = grade(c);\n if (u_clarity != 0.0) rgb += u_clarity * (rgb - grade(bl));\n if (u_gamma != 1.0) rgb = pow(max(rgb, 0.0), vec3(1.0 / u_gamma));\n if (u_vignette != 0.0) {\n float f = smoothstep(0.3, 1.0, length(cn) / 1.41421356) * ${VIGNETTE_STRENGTH.toFixed(2)} * abs(u_vignette);\n rgb = u_vignette > 0.0 ? rgb * (1.0 - f) : rgb + (1.0 - rgb) * f;\n }\n rgb = clamp(rgb, 0.0, 1.0);\n if (outsideCrop) rgb = mix(u_dimColor, rgb, u_dim);\n gl_FragColor = vec4(rgb * c.a, c.a);\n}\n`\n\ntype GL = WebGLRenderingContext | WebGL2RenderingContext\n\nexport class WebGLRenderer {\n readonly canvas: HTMLCanvasElement\n readonly gl: GL\n readonly maxTextureSize: number\n private program: WebGLProgram\n private image: WebGLTexture\n private blur: WebGLTexture\n private loc: Record<string, WebGLUniformLocation | null> = {}\n\n /** Create a renderer on `canvas`, or `null` when WebGL is unavailable. */\n static create(canvas: HTMLCanvasElement): WebGLRenderer | null {\n try {\n const opts: WebGLContextAttributes = {\n premultipliedAlpha: true,\n alpha: true,\n antialias: false,\n preserveDrawingBuffer: true,\n }\n const gl =\n (canvas.getContext('webgl2', opts) as WebGL2RenderingContext | null) ??\n (canvas.getContext('webgl', opts) as WebGLRenderingContext | null)\n if (!gl) return null\n return new WebGLRenderer(canvas, gl)\n } catch {\n return null\n }\n }\n\n private constructor(canvas: HTMLCanvasElement, gl: GL) {\n this.canvas = canvas\n this.gl = gl\n this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number\n this.program = this.link()\n gl.useProgram(this.program)\n const buffer = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW)\n const pos = gl.getAttribLocation(this.program, 'a_pos')\n gl.enableVertexAttribArray(pos)\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0)\n for (const name of [\n 'u_image',\n 'u_blur',\n 'u_size',\n 'u_uvX',\n 'u_uvY',\n 'u_blurX',\n 'u_blurY',\n 'u_cropX',\n 'u_cropY',\n 'u_clip',\n 'u_dim',\n 'u_dimColor',\n 'u_cm',\n 'u_co',\n 'u_gamma',\n 'u_clarity',\n 'u_vignette',\n 'u_pixel',\n 'u_cuvX',\n 'u_cuvY',\n ])\n this.loc[name] = gl.getUniformLocation(this.program, name)\n this.image = this.texture()\n this.blur = this.texture()\n gl.uniform1i(this.loc.u_image, 0)\n gl.uniform1i(this.loc.u_blur, 1)\n }\n\n private link(): WebGLProgram {\n const gl = this.gl\n const compile = (type: number, src: string) => {\n const sh = gl.createShader(type)!\n gl.shaderSource(sh, src)\n gl.compileShader(sh)\n if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS))\n throw new Error(gl.getShaderInfoLog(sh) ?? 'shader compile failed')\n return sh\n }\n const program = gl.createProgram()!\n gl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX))\n gl.attachShader(program, compile(gl.FRAGMENT_SHADER, FRAGMENT))\n gl.linkProgram(program)\n if (!gl.getProgramParameter(program, gl.LINK_STATUS))\n throw new Error(gl.getProgramInfoLog(program) ?? 'program link failed')\n return program\n }\n\n private texture(): WebGLTexture {\n const gl = this.gl\n const tex = gl.createTexture()!\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)\n return tex\n }\n\n private upload(unit: number, tex: WebGLTexture, source: TexImageSource, mipmap: boolean) {\n const gl = this.gl\n gl.activeTexture(gl.TEXTURE0 + unit)\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source)\n // mipmaps keep a big image crisp (not shimmering) when shown small — WebGL2 handles any size\n const isGL2 =\n typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext\n if (mipmap && isGL2) {\n gl.generateMipmap(gl.TEXTURE_2D)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)\n } else {\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n }\n }\n\n /** Upload the image (and its blurred copy for clarity). */\n setImage(image: TexImageSource, blur: TexImageSource, mipmap = true) {\n this.upload(0, this.image, image, mipmap)\n this.upload(1, this.blur, blur, false)\n }\n\n /**\n * Swap just the image texture (e.g. for a coarser copy) — the blurred copy stays. `mipmap: false` for\n * a pixelation's texture: its blocks sample one point each, and mip levels would seam their borders.\n */\n setSource(image: TexImageSource, mipmap = true) {\n this.upload(0, this.image, image, mipmap)\n }\n\n /** Draw one frame at the canvas's current pixel size. */\n render(p: RenderParams) {\n const gl = this.gl\n const { width, height } = this.canvas\n gl.viewport(0, 0, width, height)\n gl.clearColor(0, 0, 0, 0)\n gl.clear(gl.COLOR_BUFFER_BIT)\n gl.uniform2f(this.loc.u_size, width, height)\n const rows = (a: Affine, x: string, y: string) => {\n gl.uniform3f(this.loc[x], a[0], a[1], a[2])\n gl.uniform3f(this.loc[y], a[3], a[4], a[5])\n }\n rows(p.toUV, 'u_uvX', 'u_uvY')\n rows(p.toBlurUV, 'u_blurX', 'u_blurY')\n rows(p.toCrop, 'u_cropX', 'u_cropY')\n gl.uniform1i(this.loc.u_clip, p.clip ? 1 : 0)\n gl.uniform1f(this.loc.u_dim, p.dim ?? 1)\n const [dr, dg, db] = p.dimColor ?? [0, 0, 0]\n gl.uniform3f(this.loc.u_dimColor, dr, dg, db)\n const m = p.matrix\n // GLSL mat4 is column-major: column j holds the coefficient of input channel j for each output row\n const cm = new Float32Array(16)\n for (let row = 0; row < 4; row++)\n for (let col = 0; col < 4; col++) cm[col * 4 + row] = m[row * 5 + col]\n gl.uniformMatrix4fv(this.loc.u_cm, false, cm)\n gl.uniform4f(this.loc.u_co, m[4], m[9], m[14], m[19])\n gl.uniform1f(this.loc.u_gamma, p.gamma)\n gl.uniform1f(this.loc.u_clarity, p.clarity)\n gl.uniform1f(this.loc.u_vignette, p.vignette)\n const [cols, rowCount] = p.pixel ?? [0, 0]\n gl.uniform2f(this.loc.u_pixel, cols, rowCount)\n if (p.pixel && p.cropToUV) rows(p.cropToUV, 'u_cuvX', 'u_cuvY')\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n }\n\n /**\n * Release the GPU resources. `loseContext` also drops the context itself (a throwaway export canvas —\n * browsers cap live contexts); a canvas that will be drawn on again keeps it.\n */\n dispose(loseContext = true) {\n const gl = this.gl\n gl.deleteTexture(this.image)\n gl.deleteTexture(this.blur)\n gl.deleteProgram(this.program)\n if (loseContext) gl.getExtension('WEBGL_lose_context')?.loseContext()\n }\n}\n","// Rendering glue shared by the preview, the thumbnails and `process()`: the color parameters of a state,\n// the Canvas2D fallback renderer, and the full-resolution export.\n\nimport { applyAffine, chain, invertAffine, scaleAffine, translate, type Affine } from './affine'\nimport { finalSize, resizedCrop, type Size } from './geometry'\nimport { blurredFull, pixelateCanvas, pixelGrid, redactRadius } from './redact'\nimport { combinedMatrix, finetuneParam, isIdentityMatrix } from './matrix'\nimport { applyColorOps, type ColorParams } from './pixels'\nimport { blurredCopy, CLARITY_RADIUS } from './load'\nimport { sourceToPlane } from './scene'\nimport type { ImageState } from './types'\nimport { WebGLRenderer, type RenderParams } from './webgl'\n\n/** The color parameters for a state (optionally with another filter matrix — the filter thumbnails). */\nexport function colorParams(\n state: ImageState,\n colorMatrix: number[] | null = state.colorMatrix,\n): ColorParams {\n const f = state.finetune\n return {\n matrix: combinedMatrix(colorMatrix, f),\n gamma: finetuneParam.gamma(f.gamma),\n clarity: finetuneParam.clarity(f.clarity),\n vignette: finetuneParam.vignette(f.vignette),\n }\n}\n\n/** Whether a render needs the color pass at all. */\nexport const hasColorOps = (p: ColorParams) =>\n !isIdentityMatrix(p.matrix) || p.gamma !== 1 || p.clarity !== 0 || p.vignette !== 0\n\nconst canvas2d = (w: number, h: number) => {\n const c = document.createElement('canvas')\n c.width = Math.max(1, Math.round(w))\n c.height = Math.max(1, Math.round(h))\n return c\n}\n\n/**\n * The Canvas2D renderer (no WebGL): draws the texture through the inverse of `toUV`, clips to the crop,\n * then runs the color pipeline on the pixels (with the blur copy drawn through `toBlurUV`).\n */\nexport function render2D(\n canvas: HTMLCanvasElement,\n texture: CanvasImageSource,\n textureSize: Size,\n blur: CanvasImageSource,\n blurSize: Size,\n p: RenderParams,\n) {\n const ctx = canvas.getContext('2d', { willReadFrequently: true })\n if (!ctx) return\n const { width, height } = canvas\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n ctx.clearRect(0, 0, width, height)\n const drawThrough = (\n target: CanvasRenderingContext2D,\n img: CanvasImageSource,\n size: Size,\n toUV: Affine,\n ) => {\n // texture pixel → uv → device\n const m = chain(scaleAffine(1 / size.width, 1 / size.height), invertAffine(toUV))\n target.save()\n if (p.clip) {\n const fromCrop = invertAffine(p.toCrop)\n target.beginPath()\n ;[\n [-1, -1],\n [1, -1],\n [1, 1],\n [-1, 1],\n ].forEach(([x, y], i) => {\n const [dx, dy] = applyAffine(fromCrop, x, y)\n if (i === 0) target.moveTo(dx, dy)\n else target.lineTo(dx, dy)\n })\n target.closePath()\n target.clip()\n }\n target.setTransform(m[0], m[3], m[1], m[4], m[2], m[5])\n target.imageSmoothingQuality = 'high'\n target.drawImage(img, 0, 0, size.width, size.height)\n target.restore()\n }\n drawThrough(ctx, texture, textureSize, p.toUV)\n if (hasColorOps(p)) colorPass2D()\n if (p.dim != null && p.dim < 1) {\n // fade the image around the crop into the background color (only where it's painted — `source-atop`)\n const fromCrop = invertAffine(p.toCrop)\n ctx.save()\n ctx.globalCompositeOperation = 'source-atop'\n ctx.beginPath()\n ctx.rect(0, 0, width, height)\n ;[\n [-1, -1],\n [1, -1],\n [1, 1],\n [-1, 1],\n ].forEach(([x, y], i) => {\n const [dx, dy] = applyAffine(fromCrop, x, y)\n if (i === 0) ctx.moveTo(dx, dy)\n else ctx.lineTo(dx, dy)\n })\n ctx.closePath()\n const [dr, dg, db] = (p.dimColor ?? [0, 0, 0]).map((v) => Math.round(v * 255))\n ctx.fillStyle = `rgba(${dr}, ${dg}, ${db}, ${1 - p.dim})`\n ctx.fill('evenodd')\n ctx.restore()\n }\n\n function colorPass2D() {\n if (!ctx) return\n try {\n const data = ctx.getImageData(0, 0, width, height)\n let blurData: Uint8ClampedArray | null = null\n if (p.clarity !== 0) {\n const b = canvas2d(width, height)\n const bctx = b.getContext('2d', { willReadFrequently: true })\n if (bctx) {\n drawThrough(bctx, blur, blurSize, p.toBlurUV)\n blurData = bctx.getImageData(0, 0, width, height).data\n }\n }\n applyColorOps(data.data, width, height, p, blurData, p.toCrop)\n ctx.putImageData(data, 0, 0)\n } catch {\n // a tainted canvas can't be read back — show the geometry only\n }\n }\n}\n\n/** The largest canvas we'll ask a browser for (per side / in total). */\nconst MAX_SIDE = 16384\nconst MAX_AREA = 16384 * 16384\n\n/** A canvas's `toBlob` as a promise (rejects when the canvas is tainted or the encode fails). */\nconst toBlob = (canvas: HTMLCanvasElement, type: string, quality: number) =>\n new Promise<Blob>((resolve, reject) => {\n try {\n canvas.toBlob(\n (blob) => (blob ? resolve(blob) : reject(new Error('Encoding failed'))),\n type,\n quality,\n )\n } catch (e) {\n reject(e)\n }\n })\n\n/**\n * Render `state` at full source resolution and encode it. Geometry goes through Canvas2D (it handles any\n * image size natively); the color pass runs on WebGL in tiles no larger than `MAX_TEXTURE_SIZE` (or on the\n * CPU without WebGL).\n */\nexport async function renderOutput(\n image: CanvasImageSource,\n size: Size,\n state: ImageState,\n type: string,\n quality: number,\n): Promise<Blob> {\n const out = finalSize(state)\n // a Resize pick of another aspect cuts the crop to it (cover), never squashes it\n const crop = resizedCrop(state)\n // stay inside what browsers will allocate (very large crops are scaled down, never failed)\n const k = Math.min(\n 1,\n MAX_SIDE / Math.max(out.width, out.height),\n Math.sqrt(MAX_AREA / (out.width * out.height)),\n )\n const ow = Math.max(1, Math.round(out.width * k))\n const oh = Math.max(1, Math.round(out.height * k))\n const canvas = canvas2d(ow, oh)\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('Canvas 2D is unavailable')\n // source px → plane → output px\n const m = chain(\n sourceToPlane(state, size),\n translate(-crop.x, -crop.y),\n scaleAffine(ow / crop.width, oh / crop.height),\n )\n if (type === 'image/jpeg') {\n // JPEG has no alpha — fill what transparency would become black with white instead\n ctx.fillStyle = '#fff'\n ctx.fillRect(0, 0, ow, oh)\n }\n ctx.setTransform(m[0], m[3], m[1], m[4], m[2], m[5])\n ctx.imageSmoothingEnabled = true\n ctx.imageSmoothingQuality = 'high'\n // Redact: a blur goes over the source (it has no direction); a pixelation over the output, below\n const radius = redactRadius(state, size)\n const effect = state.redact?.effect\n const source =\n radius > 0 && effect === 'blur' ? blurredFull(image, size.width, size.height, radius) : image\n ctx.drawImage(source, 0, 0, size.width, size.height)\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n\n const params = colorParams(state)\n if (hasColorOps(params)) {\n // the clarity blur radius is defined in source pixels → scale it to output pixels\n const radius =\n CLARITY_RADIUS * Math.max(size.width, size.height) * (ow / crop.width) * state.scale\n const blur = blurredCopy(canvas, ow, oh, radius)\n colorPassTiled(canvas, blur, params)\n }\n // the pixel blocks follow the output's grid — square and upright, whatever the rotation\n if (radius > 0 && effect === 'pixelate') {\n const { cols, rows } = pixelGrid(crop, radius * state.scale)\n pixelateCanvas(canvas, cols, rows)\n }\n return toBlob(canvas, type, quality)\n}\n\n/** Run the color pipeline over `canvas` in place, tile by tile (WebGL, or the CPU without it). */\nfunction colorPassTiled(canvas: HTMLCanvasElement, blur: HTMLCanvasElement, params: ColorParams) {\n const { width: ow, height: oh } = canvas\n const ctx = canvas.getContext('2d', { willReadFrequently: true })!\n const glCanvas = document.createElement('canvas')\n const gl = WebGLRenderer.create(glCanvas)\n const tileSize = gl ? Math.min(2048, gl.maxTextureSize) : 1024\n const tile = canvas2d(tileSize, tileSize)\n const tctx = tile.getContext('2d', { willReadFrequently: true })!\n try {\n for (let ty = 0; ty < oh; ty += tileSize) {\n for (let tx = 0; tx < ow; tx += tileSize) {\n const tw = Math.min(tileSize, ow - tx)\n const th = Math.min(tileSize, oh - ty)\n const toCrop = chain(translate(tx, ty), scaleAffine(2 / ow, 2 / oh), translate(-1, -1))\n const toBlurUV = chain(translate(tx, ty), scaleAffine(1 / ow, 1 / oh))\n if (gl) {\n tile.width = tw\n tile.height = th\n tctx.clearRect(0, 0, tw, th)\n tctx.drawImage(canvas, tx, ty, tw, th, 0, 0, tw, th)\n glCanvas.width = tw\n glCanvas.height = th\n gl.setImage(tile, blur, false)\n gl.render({ ...params, toUV: scaleAffine(1 / tw, 1 / th), toBlurUV, toCrop, clip: false })\n ctx.clearRect(tx, ty, tw, th)\n ctx.drawImage(glCanvas, tx, ty)\n } else {\n const data = ctx.getImageData(tx, ty, tw, th)\n let blurData: Uint8ClampedArray | null = null\n if (params.clarity !== 0) {\n tile.width = tw\n tile.height = th\n tctx.drawImage(\n blur,\n (tx / ow) * blur.width,\n (ty / oh) * blur.height,\n (tw / ow) * blur.width,\n (th / oh) * blur.height,\n 0,\n 0,\n tw,\n th,\n )\n blurData = tctx.getImageData(0, 0, tw, th).data\n }\n applyColorOps(data.data, tw, th, params, blurData, toCrop)\n ctx.putImageData(data, tx, ty)\n }\n }\n }\n } finally {\n gl?.dispose()\n }\n}\n","// The framework-agnostic editor core: one store holding the `ImageState` + the UI state, an undo / redo\n// history of committed states, events, image loading and `process()`. The React `ImageEditor` is a view\n// over it; it can also be used headless (open → setState → process).\n\nimport { defaultState, normalizeState, syncResize, type Size } from './geometry'\nimport { FILTER_MATRICES, ZERO_FINETUNE } from './matrix'\nimport { loadImage, resolveOutputType, type LoadedImage } from './load'\nimport { renderOutput } from './render'\nimport type { ImageEditorOptions, ImageEditorResult, ImageEditorUiState, ImageState } from './types'\n\nexport type ImageEditorEvent = 'load' | 'update' | 'process' | 'close' | 'undo' | 'redo' | 'revert'\n\n/** The store snapshot (a new object on every change — safe for `useSyncExternalStore`). */\nexport interface ImageEditorSnapshot {\n status: 'idle' | 'loading' | 'ready' | 'error'\n error: unknown\n state: ImageState | null\n ui: ImageEditorUiState\n size: Size | null\n canUndo: boolean\n canRedo: boolean\n canRevert: boolean\n}\n\n/** The headless editor API. */\nexport interface Editor {\n open(options: ImageEditorOptions): Promise<void>\n close(): void\n getState(): ImageState\n setState(s: Partial<ImageState>): void\n undo(): void\n redo(): void\n revert(): void\n on(event: ImageEditorEvent, cb: (payload?: unknown) => void): () => void\n process(): Promise<ImageEditorResult>\n}\n\nconst MAX_HISTORY = 50\nconst same = (a: ImageState, b: ImageState) => JSON.stringify(a) === JSON.stringify(b)\nconst sameSize = (a: ImageState['resize'], b: ImageState['resize']) =>\n a === b || (!!a && !!b && a.width === b.width && a.height === b.height)\nconst clone = (s: ImageState): ImageState => JSON.parse(JSON.stringify(s)) as ImageState\n\nexport class ImageEditorCore implements Editor {\n private snapshot: ImageEditorSnapshot = {\n status: 'idle',\n error: null,\n state: null,\n ui: { util: 'crop', cropTab: 'rotation', finetuneTab: 'brightness', resizeLocked: true },\n size: null,\n canUndo: false,\n canRedo: false,\n canRevert: false,\n }\n private storeListeners = new Set<() => void>()\n private events = new Map<ImageEditorEvent, Set<(payload?: unknown) => void>>()\n private history: ImageState[] = []\n private index = -1\n /** The untouched state of the loaded image (what `revert()` goes back to). */\n private initial: ImageState | null = null\n private loaded: LoadedImage | null = null\n private options: ImageEditorOptions | null = null\n private openToken = 0\n\n // ── store (for UI bindings) ──────────────────────────────────────────────────────────────────\n\n subscribe = (fn: () => void) => {\n this.storeListeners.add(fn)\n return () => {\n this.storeListeners.delete(fn)\n }\n }\n getSnapshot = () => this.snapshot\n\n private patch(next: Partial<ImageEditorSnapshot>) {\n const state = next.state !== undefined ? next.state : this.snapshot.state\n this.snapshot = {\n ...this.snapshot,\n ...next,\n canUndo: this.index > 0,\n canRedo: this.index < this.history.length - 1,\n canRevert: !!state && !!this.initial && !same(state, this.initial),\n }\n this.storeListeners.forEach((fn) => fn())\n }\n\n on(event: ImageEditorEvent, cb: (payload?: unknown) => void) {\n let set = this.events.get(event)\n if (!set) this.events.set(event, (set = new Set()))\n set.add(cb)\n return () => {\n set!.delete(cb)\n }\n }\n private emit(event: ImageEditorEvent, payload?: unknown) {\n this.events.get(event)?.forEach((cb) => cb(payload))\n }\n\n // ── lifecycle ────────────────────────────────────────────────────────────────────────────────\n\n /** The loaded image (full resolution) — for renderers. */\n get image() {\n return this.loaded\n }\n /** The `open()` options. */\n get openOptions() {\n return this.options\n }\n\n async open(options: ImageEditorOptions): Promise<void> {\n const token = ++this.openToken\n this.options = options\n this.history = []\n this.index = -1\n this.initial = null\n this.loaded = null\n this.patch({\n status: 'loading',\n error: null,\n state: null,\n size: null,\n ui: { ...this.snapshot.ui, util: options.util ?? 'crop' },\n })\n try {\n const loaded = await loadImage(options.src)\n if (token !== this.openToken) return\n this.loaded = loaded\n const size = { width: loaded.width, height: loaded.height }\n const base = defaultState(size, options.cropAspectRatio)\n const init = options.initialState ?? {}\n const merged: ImageState = {\n ...base,\n ...init,\n crop: { ...base.crop, ...init.crop },\n finetune: { ...ZERO_FINETUNE, ...init.finetune },\n redact: { ...base.redact, ...init.redact },\n }\n // a known filter id restores its matrix when the state carries none\n if (merged.filter && merged.filter !== 'default' && !merged.colorMatrix)\n merged.colorMatrix = FILTER_MATRICES[merged.filter] ?? null\n const state = normalizeState(merged, size)\n // revert always means \"the original image\", even when re-opened with previous edits\n this.initial = normalizeState(base, size)\n this.history = [clone(state)]\n this.index = 0\n this.patch({ status: 'ready', state, size })\n this.emit('load', { size })\n } catch (error) {\n if (token !== this.openToken) return\n this.patch({ status: 'error', error })\n throw error\n }\n }\n\n close() {\n this.openToken++\n const img = this.loaded?.image\n if (img && 'close' in img && typeof img.close === 'function') img.close()\n this.loaded = null\n this.emit('close')\n }\n\n // ── state ────────────────────────────────────────────────────────────────────────────────────\n\n getState(): ImageState {\n if (!this.snapshot.state) throw new Error('No image is open')\n return clone(this.snapshot.state)\n }\n\n /** Replace part of the state and commit it (one undo step). */\n setState(s: Partial<ImageState>) {\n this.preview(s)\n this.commit()\n }\n\n /** Apply a live (uncommitted) change — e.g. while dragging. Call `commit()` when the interaction ends. */\n preview(s: Partial<ImageState>) {\n const cur = this.snapshot.state\n const size = this.snapshot.size\n if (!cur || !size) return\n const next = { ...cur, ...s }\n // a geometry change keeps a Resize pick in step with the new crop — scaled from the last committed\n // state, so a drag's many frames can't drift it by rounding — unless it sets a new resize itself\n // (geometry helpers hand back the whole state, the resize they started from included)\n const anchor = this.index >= 0 ? this.history[this.index] : cur\n const explicit = 'resize' in s && !sameSize(s.resize ?? null, anchor.resize)\n if (!explicit) next.resize = syncResize(anchor, { ...next, resize: anchor.resize })\n this.patch({ state: next })\n }\n\n /** Push the current state onto the history (if it changed) and emit `update`. */\n commit() {\n const state = this.snapshot.state\n if (!state) return\n if (this.index >= 0 && same(state, this.history[this.index])) return\n // a new change after an undo drops the redo branch\n this.history = this.history.slice(0, this.index + 1)\n this.history.push(clone(state))\n if (this.history.length > MAX_HISTORY) this.history.shift()\n this.index = this.history.length - 1\n this.patch({})\n this.emit('update', clone(state))\n }\n\n undo() {\n if (this.index <= 0) return\n this.index--\n this.patch({ state: clone(this.history[this.index]) })\n this.emit('undo', this.getState())\n this.emit('update', this.getState())\n }\n\n redo() {\n if (this.index >= this.history.length - 1) return\n this.index++\n this.patch({ state: clone(this.history[this.index]) })\n this.emit('redo', this.getState())\n this.emit('update', this.getState())\n }\n\n /**\n * Back to the original image — every edit dropped, including the ones an `initialState` re-opened with.\n * It's one history step, so Undo brings the edits back.\n */\n revert() {\n const state = this.snapshot.state\n if (!this.initial || !state || same(state, this.initial)) return\n this.patch({ state: clone(this.initial) })\n this.commit()\n this.emit('revert', this.getState())\n }\n\n setUi(ui: Partial<ImageEditorUiState>) {\n // leaving a tool ends its live edit (e.g. a size typed but not yet committed) — keep it\n if (ui.util && ui.util !== this.snapshot.ui.util) this.commit()\n this.patch({ ui: { ...this.snapshot.ui, ...ui } })\n }\n\n /** Render the current state at full resolution. */\n async process(): Promise<ImageEditorResult> {\n const loaded = this.loaded\n const state = this.snapshot.state\n if (!loaded || !state) throw new Error('No image is open')\n const type = resolveOutputType(this.options?.outputType, loaded.type)\n const dest = await renderOutput(\n loaded.image,\n { width: loaded.width, height: loaded.height },\n state,\n type,\n this.options?.outputQuality ?? 0.92,\n )\n const result = { dest, imageState: clone(state) }\n this.emit('process', result)\n return result\n }\n}\n\n/** Create a headless editor. */\nexport const createImageEditor = () => new ImageEditorCore()\n","// A tiny spring animator for the view (rotate / flip / crop fit). Animates a vector of numbers.\n\nexport interface SpringOptions {\n stiffness?: number\n damping?: number\n}\n\n/** Whether the user asked for reduced motion (then every spring jumps straight to its target). */\nexport const prefersReducedMotion = () =>\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\n/** A running spring: call it to cancel; `retarget` moves its target without losing the current motion. */\nexport interface SpringHandle {\n (): void\n retarget: (to: number[]) => void\n}\n\n/**\n * Spring `from` → `to`, calling `onFrame` with the current values every animation frame (and once with\n * `to` at the end). Returns a handle: call it to cancel, or `retarget(to)` to aim it elsewhere mid-flight\n * (position + velocity carry over, so there's no jolt). Jumps straight to `to` under reduced motion.\n */\nexport function springTo(\n from: number[],\n target: number[],\n onFrame: (values: number[]) => void,\n { stiffness = 240, damping = 30 }: SpringOptions = {},\n onDone?: () => void,\n): SpringHandle {\n if (prefersReducedMotion() || typeof requestAnimationFrame !== 'function') {\n onFrame(target)\n onDone?.()\n const noop = (() => {}) as SpringHandle\n noop.retarget = (next) => onFrame(next)\n return noop\n }\n const to = [...target]\n const x = [...from]\n const v = from.map(() => 0)\n const tol = from.map((f, i) => Math.max(1e-5, Math.abs(to[i] - f) * 1e-3))\n let last = performance.now()\n let raf = 0\n let cancelled = false\n const step = (now: number) => {\n if (cancelled) return\n // sub-step so a long frame can't blow the integration up\n let dt = Math.min(0.064, (now - last) / 1000)\n last = now\n while (dt > 0) {\n const h = Math.min(dt, 1 / 120)\n for (let i = 0; i < x.length; i++) {\n const a = -stiffness * (x[i] - to[i]) - damping * v[i]\n v[i] += a * h\n x[i] += v[i] * h\n }\n dt -= h\n }\n const settled = x.every(\n (xi, i) => Math.abs(xi - to[i]) < tol[i] && Math.abs(v[i]) < tol[i] * 10,\n )\n if (settled) {\n onFrame(to)\n onDone?.()\n return\n }\n onFrame([...x])\n raf = requestAnimationFrame(step)\n }\n raf = requestAnimationFrame(step)\n const handle = (() => {\n cancelled = true\n cancelAnimationFrame(raf)\n }) as SpringHandle\n handle.retarget = (next) => {\n for (let i = 0; i < to.length; i++) {\n to[i] = next[i]\n tol[i] = Math.max(tol[i], 1e-5)\n }\n }\n return handle\n}\n","import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type PointerEvent,\n type RefObject,\n type WheelEvent,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { applyAffine, chain, invertAffine } from './core/affine'\nimport type { ImageEditorCore, ImageEditorSnapshot } from './core/editor'\nimport {\n MAX_CROP_ZOOM,\n panBy,\n resizeCrop,\n zoomOf,\n resizedCrop,\n finalSize,\n zoomTo,\n type CropHandle,\n type Vec,\n} from './core/geometry'\nimport { blurredCopy, CLARITY_RADIUS, downscale } from './core/load'\nimport { blurredSmall, pixelatedCopy, pixelGrid, redactRadius } from './core/redact'\nimport { colorParams, render2D } from './core/render'\nimport {\n fitView,\n planeToScreen,\n sceneAffines,\n stageOrigin,\n type Stage,\n type View,\n} from './core/scene'\nimport { springTo, type SpringHandle } from './core/spring'\nimport type { ImageState } from './core/types'\nimport { WebGLRenderer } from './core/webgl'\nimport { useColorMode } from '../../theme'\nimport styles from './ImageEditor.module.css'\n\n/** Breathing room around the crop (CSS px) in the Crop view / the Filter + Finetune views. */\nconst PAD_CROP = 24\nconst PAD_VIEW = 12\n/** The largest preview texture side (the full image is only used by `process()`). */\nconst PREVIEW_MAX = 4096\n/** The Crop view enlarges a tiny crop (past its real size) until its long side is this many CSS px. */\nconst CROP_VIEW_MIN_SIDE = 320\n/** The Redact blur's preview texture (long side, at most) — a blur has no finer detail to show. */\nconst BLUR_PREVIEW_MAX = 768\n\n/** The texture the preview draws from, and how. */\ntype PreviewSource = {\n canvas: CanvasImageSource\n width: number\n height: number\n /** Upload with mipmaps (off for a pixelation — its block samples would seam at mip borders). */\n mipmap: boolean\n /** Sample it per pixel block (the shader's crop-grid pixelation). */\n pixelate: boolean\n}\n/** How much of the image shows outside the crop in the Crop view (the rest fades into the background). */\nconst CROP_DIM = 0.35\n\n/** The theme's background as 0…1 rgb (read off the `--tz-color-background-rgb` triplet). */\nfunction backgroundRgb(el: Element | null): [number, number, number] {\n const raw = el ? getComputedStyle(el).getPropertyValue('--tz-color-background-rgb') : ''\n const [r, g, b] = raw.split(',').map((v) => Number(v.trim()) / 255)\n return [r, g, b].every((v) => Number.isFinite(v)) ? [r, g, b] : [0, 0, 0]\n}\n/** The smallest crop side on screen while resizing (CSS px). */\nconst MIN_CROP_SCREEN = 40\n\nexport interface EditorStageHandle {\n /** Call right before a rotate-left / flip / other jump changes the state, so the view animates it. */\n transition(kind: 'rotate' | 'flip' | 'jump'): void\n}\n\nexport interface EditorStageProps {\n core: ImageEditorCore\n snapshot: ImageEditorSnapshot\n /** Lock crop resizing to this ratio. */\n cropAspectRatio?: number | null\n /** Filter / Finetune view zoom (CSS px per source px), `null` = fit. */\n viewZoom: number | null\n onViewZoom: (zoom: number | null) => void\n /** Reports the effective view zoom (CSS px per source px) for the header label. */\n onZoomReport: (zoom: number) => void\n /**\n * The free area between the toolbars: the canvas fills the whole editor (the image runs behind the\n * header / nav / footer), but the crop fits + centers in this element's box.\n */\n areaRef?: RefObject<HTMLElement | null>\n}\n\ntype Gesture =\n | { kind: 'pan'; id: number; x: number; y: number; base: ImageState }\n | { kind: 'resize'; id: number; x: number; y: number; base: ImageState; handle: CropHandle }\n | { kind: 'viewPan'; id: number; x: number; y: number; pan: Vec }\n | { kind: 'pinch'; dist: number; base: ImageState; zoom: number; viewZoom: number }\n\nconst HANDLES: CropHandle[] = ['nw', 'ne', 'sw', 'se', 'n', 's', 'w', 'e']\n\nconst viewToVector = (v: View) => [v.center[0], v.center[1], Math.log(v.scale), v.rotation, v.flip]\nconst vectorToView = (x: number[]): View => ({\n center: [x[0], x[1]],\n scale: Math.exp(x[2]),\n rotation: x[3],\n flip: x[4],\n})\n\n/** The editor's canvas + crop overlay: renders the image, owns the view and the pointer gestures. */\nexport const EditorStage = forwardRef<EditorStageHandle, EditorStageProps>(function EditorStage(\n { core, snapshot, cropAspectRatio, viewZoom, onViewZoom, onZoomReport, areaRef },\n ref,\n) {\n const { state, size, ui } = snapshot\n const mode = useColorMode()\n const util = ui.util\n const viewportRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [stage, setStage] = useState<Stage | null>(null)\n const [view, setView] = useState<View | null>(null)\n const viewRef = useRef<View | null>(null)\n viewRef.current = view\n const [pan, setPan] = useState<Vec>([0, 0])\n const [interacting, setInteracting] = useState(false)\n // bumped to re-run the view effect when a gesture ends without a state change (e.g. a handle click)\n const [nonce, setNonce] = useState(0)\n const frozen = useRef(false) // the view holds still while the crop is being resized\n const pending = useRef<'rotate' | 'flip' | 'jump' | null>(null)\n const stopSpring = useRef<SpringHandle | null>(null)\n const gesture = useRef<Gesture | null>(null)\n const pointers = useRef(new Map<number, { x: number; y: number }>())\n const wheelCommit = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\n // ── the stage size ───────────────────────────────────────────────────────────────────────────\n // a passive effect, not a layout one: the area element is a later sibling of this stage, so its ref is\n // only attached once the whole editor has committed (a layout effect here would see it still null)\n useEffect(() => {\n const el = viewportRef.current\n if (!el) return\n const measure = () => {\n const r = el.getBoundingClientRect()\n const a = areaRef?.current?.getBoundingClientRect()\n setStage({\n width: r.width,\n height: r.height,\n dpr: window.devicePixelRatio || 1,\n // horizontally the area is mirrored to the wider side, so the crop sits in the middle of the\n // screen (not of the space right of the tool menu); vertically it's the space between the bars\n area: a ? symmetricArea(r, a) : undefined,\n })\n }\n measure()\n measureRef.current = measure\n if (typeof ResizeObserver === 'undefined') return\n const ro = new ResizeObserver(measure)\n ro.observe(el)\n if (areaRef?.current) ro.observe(areaRef.current)\n return () => ro.disconnect()\n }, [areaRef])\n\n // the toolbar / footer change with the tool and once the image is in — re-measure right away rather\n // than waiting on the ResizeObserver (whose callback can lag a frame, or more in a background tab)\n const measureRef = useRef<(() => void) | null>(null)\n useLayoutEffect(() => {\n measureRef.current?.()\n }, [util, snapshot.status])\n\n // ── the renderer + its textures (re-made per loaded image) ───────────────────────────────────\n const loaded = snapshot.status === 'ready' ? core.image : null\n const [renderer, setRenderer] = useState<{\n gl: WebGLRenderer | null\n tex: ReturnType<typeof downscale>\n blur: HTMLCanvasElement\n } | null>(null)\n useEffect(() => {\n const canvas = canvasRef.current\n if (!loaded || !canvas) return\n // WebGL when available (the same context is handed back on a re-run), else the Canvas2D fallback\n const gl = WebGLRenderer.create(canvas)\n const maxSide = Math.min(PREVIEW_MAX, gl?.maxTextureSize ?? PREVIEW_MAX)\n const tex = downscale(loaded.image, loaded.width, loaded.height, maxSide)\n const radius =\n CLARITY_RADIUS * Math.max(loaded.width, loaded.height) * (tex.width / loaded.width)\n const blur = blurredCopy(tex.canvas, tex.width, tex.height, radius)\n gl?.setImage(tex.canvas as TexImageSource, blur)\n setRenderer({ gl, tex, blur })\n return () => {\n gl?.dispose(false) // keep the canvas's context alive — a re-run reuses it\n setRenderer(null)\n }\n }, [loaded])\n\n // a Resize pick below the preview's own resolution: draw from a copy that coarse, so the preview shows\n // the output's real quality (a 50 px wide result looks soft at any zoom, as the file will)\n const detail =\n state && size ? (finalSize(state).width * state.scale) / resizedCrop(state).width : 1\n const coarseWidth = size ? Math.max(1, Math.round(size.width * detail)) : 0\n // …and the Redact effect: a blur is baked into the texture (a small blurred copy the GPU scales up);\n // a pixelation samples a smoothed copy at each block's center (the shader lays the crop's grid over it)\n const redactEffect = state?.redact.effect ?? 'blur'\n const redactAmount = state?.redact.amount ?? 0\n const [source, setSource] = useState<PreviewSource | null>(null)\n useEffect(() => {\n if (!renderer || !size) {\n setSource(null)\n return\n }\n // made in a frame callback, not during render: a moving ruler then costs one copy per frame at most\n const raf = requestAnimationFrame(() => {\n let base: PreviewSource = { ...renderer.tex, mipmap: true, pixelate: false }\n if (coarseWidth < base.width)\n base = {\n ...downscale(\n base.canvas,\n base.width,\n base.height,\n Math.max(1, Math.round(Math.max(size.width, size.height) * detail)),\n ),\n mipmap: true,\n pixelate: false,\n }\n const radius = redactRadius({ redact: { effect: redactEffect, amount: redactAmount } }, size)\n if (radius <= 0) return setSource(base)\n const r = radius * (base.width / size.width) // in this texture's pixels\n if (redactEffect === 'blur') {\n const small = blurredSmall(base.canvas, base.width, base.height, r, BLUR_PREVIEW_MAX)\n return setSource({\n canvas: small,\n width: small.width,\n height: small.height,\n mipmap: true,\n pixelate: false,\n })\n }\n if (!renderer.gl) {\n // the Canvas2D fallback can't lay the output grid over a rotated image — it pixelates the source\n const c = pixelatedCopy(base.canvas, base.width, base.height, r)\n return setSource({\n canvas: c,\n width: c.width,\n height: c.height,\n mipmap: false,\n pixelate: false,\n })\n }\n // about one texel per block: each block's center sample is then its neighborhood's average\n const smooth = downscale(\n base.canvas,\n base.width,\n base.height,\n Math.max(base.width, base.height) / Math.max(1, r),\n )\n setSource({ ...smooth, mipmap: false, pixelate: true })\n })\n return () => cancelAnimationFrame(raf)\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed on the integer width, not every `detail`\n }, [renderer, coarseWidth, redactEffect, redactAmount])\n useLayoutEffect(() => {\n if (renderer?.gl && source)\n renderer.gl.setSource(source.canvas as TexImageSource, source.mipmap)\n }, [renderer, source])\n\n // ── the view ─────────────────────────────────────────────────────────────────────────────────\n const target = useMemo<View | null>(() => {\n if (!state || !stage) return null\n const area = stage.area ?? stage\n if (util === 'crop') {\n // the Crop view: a crop bigger than the area is fitted to it (scaled down); a smaller one shows at\n // its real size (1 output px = 1 CSS px); a tiny one is enlarged just enough (its long side to\n // CROP_VIEW_MIN_SIDE) that the crop box is still easy to handle — never past the fit. \"Real size\"\n // is taken at the image's base (unzoomed) scale, so the Scale ruler / a pinch still zoom the image\n // inside a steady crop box (sized by the live scale, zooming in would shrink the box instead)\n const fitted = fitView(state.crop, area, Math.min(PAD_CROP, area.width * 0.06))\n const real = size ? zoomOf(state, size) / state.scale : 1 / state.scale\n const handleable = CROP_VIEW_MIN_SIDE / Math.max(state.crop.width, state.crop.height)\n return { ...fitted, scale: Math.min(fitted.scale, Math.max(real, handleable)) }\n }\n // the other tools show what the output will: a Resize pick of another aspect cuts the crop (cover)\n const crop = resizedCrop(state)\n const fitted = fitView(crop, area, PAD_VIEW)\n // …at its real size (1 output px = 1 CSS px — the Resize pick, else the crop at full resolution)\n // when it fits, so a small image or a smaller size looks small and sharp; it fits the area otherwise\n const fit = { ...fitted, scale: Math.min(fitted.scale, finalSize(state).width / crop.width) }\n if (viewZoom == null) return fit\n const scale = viewZoom / state.scale\n // keep the crop covering the stage center when zoomed in\n const lx = Math.max(0, crop.width / 2 - area.width / 2 / scale)\n const ly = Math.max(0, crop.height / 2 - area.height / 2 / scale)\n const px = Math.max(-lx, Math.min(lx, pan[0]))\n const py = Math.max(-ly, Math.min(ly, pan[1]))\n return { ...fit, scale, center: [fit.center[0] + px, fit.center[1] + py] }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `nonce` only forces a recompute\n }, [state, stage, util, viewZoom, pan, nonce])\n\n // switching tools re-fits the view (the Crop view leaves room around the crop, Filter / Finetune fill\n // the area with it) — spring there instead of jumping\n const prevUtil = useRef(util)\n // whether a view spring is running, and the stage + state the view was last laid out for\n const springing = useRef(false)\n const lastLayout = useRef<{ stage: typeof stage; state: typeof state; target?: View }>({\n stage,\n state,\n })\n const startSpring = (from: View, to: View) => {\n stopSpring.current?.()\n springing.current = true\n stopSpring.current = springTo(\n viewToVector(from),\n viewToVector(to),\n (x) => setView(vectorToView(x)),\n undefined,\n () => {\n springing.current = false\n },\n )\n }\n // how much of the image shows around the crop (CROP_DIM in the Crop view, 0 elsewhere), animated\n const [surround, setSurround] = useState(util === 'crop' ? CROP_DIM : 0)\n const surroundRef = useRef(surround)\n surroundRef.current = surround\n useEffect(() => {\n const to = util === 'crop' ? CROP_DIM : 0\n return springTo([surroundRef.current], [to], ([v]) => setSurround(Math.max(0, v)))\n }, [util])\n useLayoutEffect(() => {\n if (!target) return\n if (prevUtil.current !== util) {\n prevUtil.current = util\n if (viewRef.current && !pending.current) pending.current = 'jump'\n }\n // a layout-only change (the stage / free area re-measured — e.g. the footer swapped with the tool)\n const layoutOnly = stage !== lastLayout.current.stage && state === lastLayout.current.state\n // a new Resize pick (typed, a preset, undo) — the view eases into the new cut\n const prevResize = lastLayout.current.state?.resize\n const resized =\n util === 'resize' &&\n (state?.resize?.width !== prevResize?.width || state?.resize?.height !== prevResize?.height)\n // a commit that lands on the view already being animated to (e.g. a typed size, committed on blur)\n const prevTarget = lastLayout.current.target\n const sameTarget =\n !!prevTarget &&\n viewToVector(prevTarget).every((v, i) => Math.abs(v - viewToVector(target)[i]) < 1e-9)\n lastLayout.current = { stage, state, target }\n const kind = pending.current\n if (kind) {\n pending.current = null\n const cur = viewRef.current ?? target\n const from: View =\n kind === 'rotate'\n ? { center: target.center, scale: cur.scale, rotation: Math.PI / 2, flip: 1 }\n : kind === 'flip'\n ? { center: target.center, scale: cur.scale, rotation: 0, flip: -1 }\n : cur\n startSpring(from, target)\n return\n }\n // …while a view animation runs: keep animating, just toward the corrected target\n if ((layoutOnly || resized || sameTarget) && springing.current && stopSpring.current) {\n stopSpring.current.retarget(viewToVector(target))\n return\n }\n if (resized && viewRef.current && !frozen.current) {\n startSpring(viewRef.current, target)\n return\n }\n if (frozen.current) return\n stopSpring.current?.()\n stopSpring.current = null\n springing.current = false\n setView(target)\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `target` already folds in stage + state\n }, [target])\n useEffect(() => () => stopSpring.current?.(), [])\n\n // the effective zoom (CSS px per source px) for the header\n useEffect(() => {\n if (view && state) onZoomReport(view.scale * state.scale)\n }, [view, state, onZoomReport])\n\n // ── drawing ──────────────────────────────────────────────────────────────────────────────────\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas || !stage) return\n const w = Math.max(1, Math.round(stage.width * stage.dpr))\n const h = Math.max(1, Math.round(stage.height * stage.dpr))\n if (canvas.width !== w) canvas.width = w\n if (canvas.height !== h) canvas.height = h\n }, [stage])\n\n useEffect(() => {\n if (!renderer || !source || !state || !size || !view || !stage) return\n // outside the Crop tool the image is clipped to the part the output keeps (see `resizedCrop`)\n const shown = util === 'crop' ? state : { ...state, crop: resizedCrop(state) }\n const affines = sceneAffines(shown, size, view, stage)\n // a pixelation's blocks: whole blocks across the crop, as the export lays them\n const radius = source.pixelate ? redactRadius(state, size) : 0\n const pixel =\n radius > 0\n ? {\n pixel: ((g) => [g.cols, g.rows] as [number, number])(\n pixelGrid(shown.crop, radius * state.scale),\n ),\n cropToUV: chain(invertAffine(affines.toCrop), affines.toUV),\n }\n : null\n const raf = requestAnimationFrame(() => {\n const params = {\n ...colorParams(state),\n ...affines,\n ...pixel,\n // the image around the crop: dimmed in the Crop view, gone (faded into the background) in the\n // others — `surround` springs between the two on a tool switch\n clip: surround <= 0.001,\n dim: surround,\n dimColor: backgroundRgb(viewportRef.current),\n }\n if (renderer.gl) renderer.gl.render(params)\n else if (canvasRef.current)\n render2D(canvasRef.current, source.canvas, source, renderer.blur, renderer.blur, params)\n })\n return () => cancelAnimationFrame(raf)\n // `mode`: a light / dark switch changes the background the crop surround fades into\n }, [renderer, source, state, size, view, stage, surround, mode, util])\n\n // ── imperative API ───────────────────────────────────────────────────────────────────────────\n useImperativeHandle(ref, () => ({\n transition(kind) {\n pending.current = kind\n },\n }))\n\n // ── gestures ─────────────────────────────────────────────────────────────────────────────────\n const scale = view?.scale ?? 1\n const onViewZoomRef = useRef(onViewZoom)\n onViewZoomRef.current = onViewZoom\n const pinchDistance = () => {\n const [a, b] = [...pointers.current.values()]\n return a && b ? Math.hypot(a.x - b.x, a.y - b.y) : 0\n }\n\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (!state || !size || (e.pointerType === 'mouse' && e.button !== 0)) return\n if ((e.target as HTMLElement).closest('button')) return\n e.currentTarget.setPointerCapture(e.pointerId)\n pointers.current.set(e.pointerId, { x: e.clientX, y: e.clientY })\n stopSpring.current?.()\n if (pointers.current.size === 2) {\n gesture.current = {\n kind: 'pinch',\n dist: pinchDistance(),\n base: state,\n zoom: zoomOf(state, size),\n viewZoom: (view?.scale ?? 1) * state.scale,\n }\n return\n }\n const handle = (e.target as HTMLElement).closest<HTMLElement>('[data-handle]')?.dataset\n .handle as CropHandle | undefined\n if (util === 'crop') {\n gesture.current = handle\n ? { kind: 'resize', id: e.pointerId, x: e.clientX, y: e.clientY, base: state, handle }\n : { kind: 'pan', id: e.pointerId, x: e.clientX, y: e.clientY, base: state }\n if (handle) frozen.current = true\n setInteracting(true)\n } else if (viewZoom != null) {\n gesture.current = { kind: 'viewPan', id: e.pointerId, x: e.clientX, y: e.clientY, pan }\n }\n }\n\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n if (!pointers.current.has(e.pointerId) || !size) return\n pointers.current.set(e.pointerId, { x: e.clientX, y: e.clientY })\n const g = gesture.current\n if (!g) return\n if (g.kind === 'pinch') {\n const ratio = pinchDistance() / Math.max(1, g.dist)\n if (util === 'crop')\n core.preview(zoomTo(g.base, Math.min(MAX_CROP_ZOOM, g.zoom * ratio), size))\n else onViewZoom(clampZoom(g.viewZoom * ratio))\n return\n }\n if (g.id !== e.pointerId) return\n const dx = (e.clientX - g.x) / scale\n const dy = (e.clientY - g.y) / scale\n if (g.kind === 'pan') core.preview(panBy(g.base, -dx, -dy, size))\n else if (g.kind === 'resize') {\n const base = g.base.crop\n // a locked editor, a picked crop shape or a held Shift keeps the crop's ratio\n const locked = cropAspectRatio || g.base.cropRatio || e.shiftKey\n const ratio = locked ? base.width / base.height : null\n core.preview(\n resizeCrop(g.base, g.handle, dx, dy, size, {\n aspectRatio: ratio,\n minSize: Math.max(g.base.scale, MIN_CROP_SCREEN / scale),\n }),\n )\n } else if (g.kind === 'viewPan') setPan([g.pan[0] - dx, g.pan[1] - dy])\n }\n\n const onPointerUp = (e: PointerEvent<HTMLDivElement>) => {\n if (!pointers.current.has(e.pointerId)) return\n pointers.current.delete(e.pointerId)\n const g = gesture.current\n if (!g) return\n if (g.kind === 'pinch') {\n if (pointers.current.size === 0) {\n gesture.current = null\n if (util === 'crop') core.commit()\n }\n return\n }\n if (g.id !== e.pointerId) return\n gesture.current = null\n setInteracting(false)\n if (g.kind === 'resize') {\n // re-fit: spring the view so the new crop is centered + scaled to the viewport\n frozen.current = false\n pending.current = 'jump'\n core.commit()\n // the crop may be unchanged (a click on a handle) — still settle the view\n setNonce((n) => n + 1)\n } else if (g.kind === 'pan') core.commit()\n }\n\n const onWheel = (e: WheelEvent<HTMLDivElement>) => {\n if (!state || !size) return\n const zoomGesture = e.ctrlKey || e.metaKey\n // Safari reports a trackpad pinch as gesture events (handled below) — don't zoom twice\n if (zoomGesture && safariGesture.current) return\n if (util === 'crop') {\n const factor = Math.exp(-e.deltaY * (zoomGesture ? 0.01 : 0.002))\n core.preview(zoomTo(state, Math.min(MAX_CROP_ZOOM, zoomOf(state, size) * factor), size))\n clearTimeout(wheelCommit.current)\n wheelCommit.current = setTimeout(() => core.commit(), 250)\n return\n }\n if (zoomGesture) {\n const current = (view?.scale ?? 1) * state.scale\n onViewZoom(clampZoom(current * Math.exp(-e.deltaY * 0.01)))\n } else if (viewZoom != null) {\n setPan(([x, y]) => [x + e.deltaX / scale, y + e.deltaY / scale])\n }\n }\n useEffect(() => () => clearTimeout(wheelCommit.current), [])\n\n // Safari's trackpad pinch: `gesturestart` / `gesturechange` (a cumulative `scale`) / `gestureend`. The\n // page-zoom default is cancelled by the ImageEditor while it's open; here the pinch zooms the image.\n const safariGesture = useRef<{ base: ImageState; zoom: number; viewZoom: number } | null>(null)\n const live = useRef({ state, size, util, view })\n live.current = { state, size, util, view }\n useEffect(() => {\n const el = viewportRef.current\n if (!el) return\n type GestureEvent = Event & { scale: number }\n const onStart = (e: Event) => {\n const { state: s, size: sz, view: v } = live.current\n e.preventDefault()\n // a touch pinch on iOS also fires gesture events — the pointer pinch already handles that one\n if (!s || !sz || pointers.current.size > 0) return\n safariGesture.current = { base: s, zoom: zoomOf(s, sz), viewZoom: (v?.scale ?? 1) * s.scale }\n }\n const onChange = (e: Event) => {\n const g = safariGesture.current\n const { size: sz, util: u } = live.current\n if (!g || !sz) return\n e.preventDefault()\n const k = (e as GestureEvent).scale || 1\n if (u === 'crop') core.preview(zoomTo(g.base, Math.min(MAX_CROP_ZOOM, g.zoom * k), sz))\n else onViewZoomRef.current(clampZoom(g.viewZoom * k))\n }\n const onEnd = (e: Event) => {\n if (!safariGesture.current) return\n e.preventDefault()\n safariGesture.current = null\n if (live.current.util === 'crop') core.commit()\n }\n el.addEventListener('gesturestart', onStart)\n el.addEventListener('gesturechange', onChange)\n el.addEventListener('gestureend', onEnd)\n return () => {\n el.removeEventListener('gesturestart', onStart)\n el.removeEventListener('gesturechange', onChange)\n el.removeEventListener('gestureend', onEnd)\n }\n }, [core])\n\n // ── the crop overlay (screen rect at the view's resting rotation; animations ride a CSS transform) ──\n let cropBox: CSSProperties | null = null\n if (util === 'crop' && state && stage && view) {\n const m = planeToScreen({ ...view, rotation: 0, flip: 1 }, stage)\n const [x0, y0] = applyAffine(m, state.crop.x, state.crop.y)\n const [x1, y1] = applyAffine(\n m,\n state.crop.x + state.crop.width,\n state.crop.y + state.crop.height,\n )\n cropBox = { left: x0, top: y0, width: x1 - x0, height: y1 - y0 }\n }\n const sceneTransform: CSSProperties | undefined =\n view && stage\n ? {\n transform: `scaleX(${view.flip}) rotate(${view.rotation}rad)`,\n transformOrigin: stageOrigin(stage)\n .map((v) => `${v}px`)\n .join(' '),\n }\n : undefined\n\n return (\n <div\n ref={viewportRef}\n className={clsx(\n styles.viewport,\n util === 'crop' ? styles.viewportCrop : viewZoom != null && styles.viewportPannable,\n )}\n data-part=\"viewport\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onWheel={onWheel}\n >\n <canvas ref={canvasRef} className={styles.canvas} data-part=\"canvas\" />\n {cropBox && (\n <div className={clsx(styles.scene, styles.fadeIn)} style={sceneTransform}>\n <div\n className={clsx(styles.cropBox, interacting && styles.cropInteracting)}\n style={cropBox}\n data-part=\"crop\"\n >\n <span className={styles.grid} aria-hidden=\"true\" />\n {HANDLES.map((h) => (\n <span\n key={h}\n className={clsx(styles.handle, styles[`handle_${h}`])}\n data-handle={h}\n aria-hidden=\"true\"\n />\n ))}\n </div>\n </div>\n )}\n {/* the result's pixel size, in the crop's bottom edge — hidden while a rotate / flip animates\n (it sits at the crop's resting place, outside the animated scene, so it never mirrors) */}\n {cropBox && state && view && view.rotation === 0 && view.flip === 1 && (\n <div\n className={clsx(styles.sizeBadge, interacting && styles.sizeBadgeActive)}\n style={{\n left: (cropBox.left as number) + (cropBox.width as number) / 2,\n top: (cropBox.top as number) + (cropBox.height as number),\n }}\n data-part=\"size\"\n >\n {finalSize(state).width}\n <span className={styles.sizeTimes}>×</span>\n {finalSize(state).height}\n <span className={styles.sizeUnit}>px</span>\n </div>\n )}\n </div>\n )\n})\n\n/** The free area relative to the stage, its horizontal insets evened out to the larger one. */\nfunction symmetricArea(stage: DOMRect, area: DOMRect) {\n const inset = Math.max(0, area.left - stage.left, stage.right - area.right)\n return {\n x: inset,\n y: area.top - stage.top,\n width: Math.max(1, stage.width - inset * 2),\n height: area.height,\n }\n}\n\n/** The Filter / Finetune view zoom range (CSS px per source px). */\nexport const VIEW_ZOOM_MIN = 0.02\nexport const VIEW_ZOOM_MAX = 8\nconst clampZoom = (z: number) => Math.min(VIEW_ZOOM_MAX, Math.max(VIEW_ZOOM_MIN, z))\n","import { useState, type CSSProperties } from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport { Button } from '../Button'\nimport { Dropdown } from '../Dropdown'\nimport { Icon } from '../Icon'\nimport { ListItem } from '../List'\nimport type { ImageCropRatioOption } from './core/types'\nimport styles from './ImageEditor.module.css'\n\n/** The Crop Shape presets (landscape form — the portrait toggle flips them). */\nexport const DEFAULT_CROP_RATIOS: ImageCropRatioOption[] = [\n { label: '1:1', ratio: 1 },\n { label: '2:1', ratio: 2 },\n { label: '3:2', ratio: 3 / 2 },\n { label: '4:3', ratio: 4 / 3 },\n { label: '5:4', ratio: 5 / 4 },\n { label: '16:10', ratio: 16 / 10 },\n { label: '16:9', ratio: 16 / 9 },\n]\n\nconst same = (a: number, b: number) => Math.abs(a - b) < 1e-3\n/** `16:9` → `9:16` */\nconst flipLabel = (label: string) => label.split(':').reverse().join(':')\n\n/**\n * A small filled box of the given ratio, centered in a fixed square slot — the shape's preview (the\n * slot keeps every label at the same x, whatever the shape's width).\n */\nfunction ShapePreview({ ratio }: { ratio: number | null }) {\n const box = 16\n const w = ratio == null || ratio >= 1 ? box : Math.max(6, box * ratio)\n const h = ratio == null || ratio <= 1 ? box : Math.max(6, box / ratio)\n return (\n <span className={styles.shapeSlot}>\n <span\n className={clsx(styles.shapePreview, ratio == null && styles.shapeCustom)}\n style={{ width: w, height: h } as CSSProperties}\n />\n </span>\n )\n}\n\nexport interface CropShapeMenuProps {\n /** The current crop shape (width / height), `null` = custom. */\n ratio: number | null\n /** The presets (landscape form). */\n options: ImageCropRatioOption[]\n /** Pick a shape (`null` = custom). */\n onChange: (ratio: number | null) => void\n}\n\n/**\n * The Crop tool's **Crop Shape** menu: a landscape / portrait toggle on top, then Custom (free) and the\n * ratio presets, each with a little preview of its shape. Picking one reshapes the crop and locks it to\n * that ratio. Internal to the ImageEditor.\n */\nexport function CropShapeMenu({ ratio, options, onChange }: CropShapeMenuProps) {\n const t = useT()\n const [open, setOpen] = useState(false)\n const [portraitPref, setPortraitPref] = useState(false)\n // a picked non-square shape decides the orientation; otherwise the last toggle does\n const portrait = ratio != null && !same(ratio, 1) ? ratio < 1 : portraitPref\n\n const pick = (next: number | null) => {\n onChange(next)\n setOpen(false)\n }\n const setOrientation = (toPortrait: boolean) => {\n setPortraitPref(toPortrait)\n // flip the picked shape along with it (16:9 ⇄ 9:16)\n if (ratio != null && !same(ratio, 1) && ratio < 1 !== toPortrait) onChange(1 / ratio)\n }\n\n return (\n <Dropdown\n open={open}\n onOpenChange={setOpen}\n closeOnSelect={false}\n placement=\"bottom-start\"\n size=\"sm\"\n trigger={\n <Button\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n startIcon={<Icon name=\"MaximizeFormat\" />}\n title={t('imageEditor.cropShape')}\n aria-label={t('imageEditor.cropShape')}\n className={styles.toolbarIconOnPhone}\n >\n <span className={styles.toolbarLabel}>{t('imageEditor.cropShape')}</span>\n </Button>\n }\n >\n <div\n className={styles.shapeOrientation}\n role=\"group\"\n aria-label={t('imageEditor.orientation')}\n >\n {[false, true].map((p) => (\n <button\n key={String(p)}\n type=\"button\"\n className={clsx(styles.orientButton, portrait === p && styles.orientActive)}\n aria-pressed={portrait === p}\n aria-label={t(p ? 'imageEditor.portrait' : 'imageEditor.landscape')}\n title={t(p ? 'imageEditor.portrait' : 'imageEditor.landscape')}\n onClick={() => setOrientation(p)}\n >\n <Icon name={p ? 'Mobile' : 'Monitor'} size=\"sm\" />\n </button>\n ))}\n </div>\n <ListItem\n icon={<ShapePreview ratio={null} />}\n clickable\n selected={ratio == null}\n onClick={() => pick(null)}\n >\n {t('imageEditor.custom')}\n </ListItem>\n {options.map((o) => {\n const r = portrait ? 1 / o.ratio : o.ratio\n return (\n <ListItem\n key={o.label}\n icon={<ShapePreview ratio={r} />}\n clickable\n selected={ratio != null && same(ratio, r)}\n onClick={() => pick(r)}\n >\n {portrait && !same(o.ratio, 1) ? flipLabel(o.label) : o.label}\n </ListItem>\n )\n })}\n </Dropdown>\n )\n}\n","import { useEffect, useRef, useState, type KeyboardEvent, type PointerEvent } from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport type { MessageKey } from '../../i18n/messages'\nimport { chain, scaleAffine, translate } from './core/affine'\nimport { cropCenter, type Size } from './core/geometry'\nimport { CLARITY_RADIUS, downscale, type ImageSource } from './core/load'\nimport { FILTER_GROUPS, FILTER_MATRICES } from './core/matrix'\nimport { applyColorOps, boxBlur } from './core/pixels'\nimport { colorParams } from './core/render'\nimport { sourceToPlane } from './core/scene'\nimport type { ImageFilterId, ImageState } from './core/types'\nimport styles from './ImageEditor.module.css'\n\n/** Thumbnail edge in CSS px (rendered at the device pixel ratio). */\nconst THUMB = 52\n\nexport interface FilterStripProps {\n image: ImageSource\n size: Size\n state: ImageState\n onSelect: (id: ImageFilterId) => void\n}\n\n/** Render every filter's thumbnail of the current (cropped / rotated / finetuned) image as data URLs. */\nfunction renderThumbs(source: CanvasImageSource, size: Size, state: ImageState) {\n const dpr = Math.min(2, typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1)\n const t = Math.round(THUMB * dpr)\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = t\n const ctx = canvas.getContext('2d', { willReadFrequently: true })\n if (!ctx) return null\n // source px → plane → thumbnail px (the crop covers the square, centered)\n const { crop } = state\n const k = t / Math.min(crop.width, crop.height)\n const [kx, ky] = cropCenter(crop)\n const m = chain(\n sourceToPlane(state, size),\n translate(-kx, -ky),\n scaleAffine(k),\n translate(t / 2, t / 2),\n )\n ctx.setTransform(m[0], m[3], m[1], m[4], m[2], m[5])\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(source, 0, 0, size.width, size.height)\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n let base: ImageData\n try {\n base = ctx.getImageData(0, 0, t, t)\n } catch {\n return null // a tainted canvas — no thumbnails\n }\n const radius = CLARITY_RADIUS * Math.max(size.width, size.height) * state.scale * k\n const blur = state.finetune.clarity ? boxBlur(base.data, t, t, radius) : null\n // thumbnail px → crop-normalized coords (for the vignette)\n const toCrop = chain(\n translate(-t / 2, -t / 2),\n scaleAffine(1 / k),\n scaleAffine(2 / crop.width, 2 / crop.height),\n )\n const out: Partial<Record<ImageFilterId, string>> = {}\n for (const id of FILTER_GROUPS.flat()) {\n const data = new ImageData(new Uint8ClampedArray(base.data), t, t)\n applyColorOps(data.data, t, t, colorParams(state, FILTER_MATRICES[id]), blur, toCrop)\n ctx.putImageData(data, 0, 0)\n out[id] = canvas.toDataURL()\n }\n return out\n}\n\n/**\n * The Filter tool's footer: a horizontally scrolling strip of preset tiles (live thumbnails), grouped.\n * Wheel scrolls it sideways, it drags with momentum, arrows move between tiles; the edges fade.\n */\nexport function FilterStrip({ image, size, state, onSelect }: FilterStripProps) {\n const t = useT()\n const scrollerRef = useRef<HTMLDivElement>(null)\n const [thumbs, setThumbs] = useState<Partial<Record<ImageFilterId, string>>>({})\n const [edges, setEdges] = useState({ start: false, end: false })\n const active: ImageFilterId = state.filter ?? 'default'\n\n // a small copy of the image for the thumbnails (re-made per image)\n const small = useRef<{ image: ImageSource; source: CanvasImageSource } | null>(null)\n if (small.current?.image !== image)\n small.current = { image, source: downscale(image, size.width, size.height, 512).canvas }\n\n // the geometry + finetune the thumbnails depend on (not the active filter itself)\n const key = JSON.stringify([\n state.crop,\n state.rotation,\n state.flipX,\n state.flipY,\n state.scale,\n state.finetune,\n ])\n useEffect(() => {\n const id = setTimeout(() => {\n const src = small.current?.source\n if (!src) return\n // the small copy has its own pixel size; draw it as if it were the full image\n const r = renderThumbs(src, size, state)\n if (r) setThumbs(r)\n }, 120)\n return () => clearTimeout(id)\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed on the serialized inputs\n }, [key, image])\n\n // edge fades\n const updateEdges = () => {\n const el = scrollerRef.current\n if (!el) return\n setEdges({\n start: el.scrollLeft > 2,\n end: el.scrollLeft + el.clientWidth < el.scrollWidth - 2,\n })\n }\n useEffect(() => {\n updateEdges()\n const el = scrollerRef.current\n if (!el || typeof ResizeObserver === 'undefined') return\n const ro = new ResizeObserver(updateEdges)\n ro.observe(el)\n return () => ro.disconnect()\n }, [])\n\n // keep the active tile in view\n useEffect(() => {\n scrollerRef.current\n ?.querySelector<HTMLElement>(`[data-filter=\"${active}\"]`)\n ?.scrollIntoView?.({ block: 'nearest', inline: 'nearest', behavior: 'smooth' })\n }, [active])\n\n // vertical wheel → horizontal scroll\n useEffect(() => {\n const el = scrollerRef.current\n if (!el) return\n const onWheel = (e: WheelEvent) => {\n if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return\n e.preventDefault()\n el.scrollLeft += e.deltaY\n }\n el.addEventListener('wheel', onWheel, { passive: false })\n return () => el.removeEventListener('wheel', onWheel)\n }, [])\n\n // mouse drag-to-scroll with momentum (touch scrolls natively)\n const drag = useRef<{ x: number; left: number; v: number; t: number; moved: boolean } | null>(\n null,\n )\n const momentum = useRef(0)\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (e.pointerType !== 'mouse' || e.button !== 0) return\n cancelAnimationFrame(momentum.current)\n const el = scrollerRef.current!\n drag.current = { x: e.clientX, left: el.scrollLeft, v: 0, t: performance.now(), moved: false }\n }\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n const d = drag.current\n if (!d) return\n const el = scrollerRef.current!\n const dx = e.clientX - d.x\n if (Math.abs(dx) > 4 && !d.moved) {\n d.moved = true\n el.setPointerCapture(e.pointerId)\n }\n if (!d.moved) return\n const now = performance.now()\n const next = d.left - dx\n d.v = (el.scrollLeft - next) / Math.max(1, now - d.t)\n d.t = now\n el.scrollLeft = next\n }\n const onPointerUp = () => {\n const d = drag.current\n drag.current = null\n if (!d?.moved) return\n const el = scrollerRef.current!\n let v = -d.v\n let last = performance.now()\n const step = (now: number) => {\n const dt = now - last\n last = now\n el.scrollLeft += v * dt\n v *= Math.pow(0.995, dt)\n if (Math.abs(v) > 0.02) momentum.current = requestAnimationFrame(step)\n }\n momentum.current = requestAnimationFrame(step)\n // swallow the click that ends a drag\n const block = (ev: MouseEvent) => {\n ev.stopPropagation()\n ev.preventDefault()\n }\n el.addEventListener('click', block, { capture: true, once: true })\n setTimeout(() => el.removeEventListener('click', block, { capture: true }), 0)\n }\n useEffect(() => () => cancelAnimationFrame(momentum.current), [])\n\n // ←/→ move between tiles\n const ids = FILTER_GROUPS.flat()\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return\n const i = ids.indexOf((e.target as HTMLElement).dataset.filter as ImageFilterId)\n if (i === -1) return\n e.preventDefault()\n const next = ids[Math.min(ids.length - 1, Math.max(0, i + (e.key === 'ArrowRight' ? 1 : -1)))]\n scrollerRef.current?.querySelector<HTMLElement>(`[data-filter=\"${next}\"]`)?.focus()\n }\n\n return (\n <div\n ref={scrollerRef}\n className={clsx(styles.strip, edges.start && styles.fadeStart, edges.end && styles.fadeEnd)}\n data-part=\"filters\"\n role=\"group\"\n aria-label={t('imageEditor.filters')}\n onScroll={updateEdges}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onKeyDown={onKeyDown}\n >\n {FILTER_GROUPS.map((group, gi) => (\n <div key={gi} className={styles.stripGroup}>\n {group.map((id) => (\n <button\n key={id}\n type=\"button\"\n className={clsx(styles.filterTile, id === active && styles.filterActive)}\n data-filter={id}\n aria-pressed={id === active}\n onClick={() => onSelect(id)}\n >\n <span className={styles.filterThumb}>\n {thumbs[id] && <img src={thumbs[id]} alt=\"\" draggable={false} />}\n </span>\n <span className={styles.filterLabel}>\n {t(`imageEditor.filter.${id}` as MessageKey)}\n </span>\n </button>\n ))}\n </div>\n ))}\n </div>\n )\n}\n","import { useEffect, useRef, useState, type KeyboardEvent } from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport { Icon } from '../Icon'\nimport type { Size } from './core/geometry'\nimport styles from './ImageEditor.module.css'\n\nexport interface ResizePanelProps {\n /** The largest size — the crop at full resolution (the tool never upscales). */\n max: Size\n /** The current result size. */\n value: Size\n /** Keep the crop's aspect ratio while typing. */\n locked: boolean\n onLockedChange: (locked: boolean) => void\n /** A live change (while typing). */\n onInput: (size: Size | null) => void\n /** A committed change (Enter, blur, a preset). */\n onChange: (size: Size | null) => void\n}\n\n/** The quick picks, as a share of the full size. */\nconst PRESETS = [1, 0.75, 0.5, 0.25]\n\nconst clampSide = (v: number, max: number) => Math.max(1, Math.min(max, Math.round(v)))\n\n/**\n * The Resize tool's footer: a Width × Height pair (with an aspect-ratio lock between them) under the\n * full size it can go up to, and Original / 75% / 50% / 25% quick picks. Internal to the ImageEditor.\n */\nexport function ResizePanel({\n max,\n value,\n locked,\n onLockedChange,\n onInput,\n onChange,\n}: ResizePanelProps) {\n const t = useT()\n const size = value\n const [draft, setDraft] = useState({ w: String(size.width), h: String(size.height) })\n // follow outside changes (undo, a preset, a crop change) when not mid-typing\n useEffect(() => {\n setDraft({ w: String(size.width), h: String(size.height) })\n }, [size.width, size.height])\n\n // the aspect the lock keeps: the crop's — or, once a free pick cut it, that pick's\n const sameAspect =\n Math.round((size.width * max.height) / max.width) === size.height ||\n Math.round((size.height * max.width) / max.height) === size.width\n const liveRatio = sameAspect ? max.width / max.height : size.width / size.height\n // held for a whole edit (focus → blur), so rounding while typing can't drift it\n const heldRatio = useRef<number | null>(null)\n const ratio = heldRatio.current ?? liveRatio\n /** The size an edit of one side means (the other side follows when locked). */\n const resolve = (side: 'w' | 'h', raw: string): Size | null => {\n const n = Number(raw)\n if (!raw || !Number.isFinite(n) || n <= 0) return null\n if (side === 'w') {\n let width = clampSide(n, max.width)\n if (!locked) return { width, height: size.height }\n const height = clampSide(width / ratio, max.height)\n // a side that hit its limit pulls the other back to the ratio\n if (height < width / ratio - 0.5) width = clampSide(height * ratio, max.width)\n return { width, height }\n }\n let height = clampSide(n, max.height)\n if (!locked) return { width: size.width, height }\n const width = clampSide(height * ratio, max.width)\n if (width < height * ratio - 0.5) height = clampSide(width / ratio, max.height)\n return { width, height }\n }\n /** `null` when it's the full size (no resize). */\n const normalize = (s: Size) => (s.width === max.width && s.height === max.height ? null : s)\n\n const edit = (side: 'w' | 'h', raw: string) => {\n const digits = raw.replace(/[^\\d]/g, '')\n const next = resolve(side, digits)\n setDraft((d) =>\n next\n ? {\n w: side === 'w' ? digits : String(next.width),\n h: side === 'h' ? digits : String(next.height),\n }\n : { ...d, [side]: digits },\n )\n if (next) onInput(normalize(next))\n }\n const commit = () => {\n const w = Number(draft.w)\n const h = Number(draft.h)\n // an empty / zero field falls back to the last good size\n let s: Size = size\n if (w > 0 && h > 0)\n s = locked\n ? (resolve('w', draft.w) ?? size)\n : { width: clampSide(w, max.width), height: clampSide(h, max.height) }\n setDraft({ w: String(s.width), h: String(s.height) })\n onChange(normalize(s))\n }\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>, side: 'w' | 'h') => {\n if (e.key === 'Enter') {\n e.preventDefault()\n commit()\n return\n }\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return\n e.preventDefault()\n const step = (e.shiftKey ? 10 : 1) * (e.key === 'ArrowUp' ? 1 : -1)\n const cur = side === 'w' ? size.width : size.height\n const next = resolve(side, String(cur + step))\n if (next) {\n setDraft({ w: String(next.width), h: String(next.height) })\n onChange(normalize(next))\n }\n }\n\n const presetActive = (p: number) =>\n size.width === Math.max(1, Math.round(max.width * p)) &&\n size.height === Math.max(1, Math.round(max.height * p))\n\n return (\n <div className={styles.resizePanel} data-part=\"resize\">\n <div className={styles.resizeFields}>\n <label className={styles.dimField}>\n <span className={styles.dimLabel}>\n <span className={styles.dimLabelFull}>{t('imageEditor.width')}</span>\n {/* a phone shows just the first letter (W / H) */}\n <span className={styles.dimLabelShort} aria-hidden=\"true\">\n {t('imageEditor.width').charAt(0)}\n </span>\n </span>\n <input\n className={styles.dimInput}\n inputMode=\"numeric\"\n value={draft.w}\n aria-label={t('imageEditor.width')}\n onChange={(e) => edit('w', e.target.value)}\n onBlur={() => {\n commit()\n heldRatio.current = null\n }}\n onKeyDown={(e) => onKeyDown(e, 'w')}\n onFocus={(e) => {\n heldRatio.current = liveRatio\n e.target.select()\n }}\n />\n <span className={styles.dimUnit}>px</span>\n </label>\n <button\n type=\"button\"\n className={clsx(styles.lockButton, locked && styles.lockActive)}\n aria-pressed={locked}\n aria-label={t('imageEditor.lockRatio')}\n title={t('imageEditor.lockRatio')}\n onClick={() => onLockedChange(!locked)}\n >\n <Icon name={locked ? 'Unlock' : 'LockSlash'} size=\"sm\" />\n </button>\n <label className={styles.dimField}>\n <span className={styles.dimLabel}>\n <span className={styles.dimLabelFull}>{t('imageEditor.height')}</span>\n {/* a phone shows just the first letter (W / H) */}\n <span className={styles.dimLabelShort} aria-hidden=\"true\">\n {t('imageEditor.height').charAt(0)}\n </span>\n </span>\n <input\n className={styles.dimInput}\n inputMode=\"numeric\"\n value={draft.h}\n aria-label={t('imageEditor.height')}\n onChange={(e) => edit('h', e.target.value)}\n onBlur={() => {\n commit()\n heldRatio.current = null\n }}\n onKeyDown={(e) => onKeyDown(e, 'h')}\n onFocus={(e) => {\n heldRatio.current = liveRatio\n e.target.select()\n }}\n />\n <span className={styles.dimUnit}>px</span>\n </label>\n </div>\n <div\n className={styles.tabs}\n role=\"group\"\n aria-label={t('imageEditor.resize')}\n data-part=\"tabs\"\n >\n {PRESETS.map((p) => (\n <button\n key={p}\n type=\"button\"\n aria-pressed={presetActive(p)}\n className={clsx(styles.tab, presetActive(p) && styles.tabActive)}\n onClick={() =>\n onChange(\n normalize({\n width: Math.max(1, Math.round(max.width * p)),\n height: Math.max(1, Math.round(max.height * p)),\n }),\n )\n }\n >\n {p === 1 ? t('imageEditor.original') : `${Math.round(p * 100)}%`}\n </button>\n ))}\n </div>\n </div>\n )\n}\n","import {\n useEffect,\n useRef,\n type CSSProperties,\n type KeyboardEvent,\n type PointerEvent,\n type WheelEvent,\n} from 'react'\nimport { clsx } from 'clsx'\nimport styles from './RulerSlider.module.css'\n\nexport interface RulerSliderProps {\n /** Lowest value. */\n min: number\n /** Highest value. */\n max: number\n /** The current value. */\n value: number\n /** Value granularity. Defaults to `1`. */\n step?: number\n /** Arrow-key step (Shift = ×10). Defaults to `1`. */\n keyStep?: number\n /** Values the ruler snaps to when within `snapThreshold`. Defaults to `[0]`. */\n snapPoints?: number[]\n /** Snap distance in value units. Defaults to 2% of the range. */\n snapThreshold?: number\n /** Value units between two ruler dots. Defaults to 5% of the range. */\n tickStep?: number\n /** Every n-th dot is a bigger one. Defaults to `5`. */\n majorEvery?: number\n /** The value a double-click resets to. Defaults to `0` (clamped into the range). */\n resetValue?: number\n /** The label shown at the center (and the `aria-valuetext`). */\n format?: (value: number) => string\n /** Fired continuously while the value changes (drag, inertia, wheel). */\n onInput: (value: number) => void\n /** Fired when a change is committed (pointer-up / inertia end, a key press, wheel idle, reset). */\n onChange: (value: number) => void\n /** Accessible name. */\n 'aria-label': string\n className?: string\n}\n\n/** Pixels between two ruler dots. */\nconst TICK_GAP = 9\n\n/**\n * A tape-measure slider: a dotted ruler slides under a fixed center indicator (drag left → the value\n * grows), with inertia, wheel and keyboard control, snapping to `snapPoints`, and a double-click reset.\n * Internal to the ImageEditor (Rotation / Scale / Finetune).\n */\nexport function RulerSlider({\n min,\n max,\n value,\n step = 1,\n keyStep = 1,\n snapPoints = [0],\n snapThreshold = (max - min) * 0.02,\n tickStep = (max - min) / 20,\n majorEvery = 5,\n resetValue = 0,\n format = (v) => String(Math.round(v)),\n onInput,\n onChange,\n 'aria-label': ariaLabel,\n className,\n}: RulerSliderProps) {\n const pxPerUnit = TICK_GAP / tickStep\n const drag = useRef<{\n id: number\n startX: number\n startValue: number\n lastX: number\n lastT: number\n velocity: number\n moved: boolean\n } | null>(null)\n const inertia = useRef(0)\n const wheelTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const live = useRef(value)\n live.current = value\n // a glide / wheel whose commit hasn't fired yet — flushed on unmount (switching tab / tool mid-gesture),\n // so the value it previewed is committed rather than left half-applied\n const pending = useRef(false)\n const latestOnChange = useRef(onChange)\n latestOnChange.current = onChange\n const commitValue = (v: number) => {\n pending.current = false\n onChange(v)\n }\n\n useEffect(\n () => () => {\n cancelAnimationFrame(inertia.current)\n clearTimeout(wheelTimer.current)\n if (pending.current) {\n pending.current = false\n latestOnChange.current(live.current)\n }\n },\n [],\n )\n\n const settle = (raw: number, snap = true) => {\n let v = Math.min(max, Math.max(min, raw))\n v = Math.round(v / step) * step\n if (snap)\n for (const p of snapPoints)\n if (Math.abs(v - p) <= snapThreshold) {\n v = p\n break\n }\n return Number(v.toFixed(6))\n }\n\n const emitInput = (v: number) => {\n if (v !== live.current) {\n live.current = v\n pending.current = true\n onInput(v)\n }\n }\n\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return\n cancelAnimationFrame(inertia.current)\n e.currentTarget.setPointerCapture(e.pointerId)\n drag.current = {\n id: e.pointerId,\n startX: e.clientX,\n startValue: value,\n lastX: e.clientX,\n lastT: performance.now(),\n velocity: 0,\n moved: false,\n }\n }\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n const d = drag.current\n if (!d || d.id !== e.pointerId) return\n const now = performance.now()\n const dt = Math.max(1, now - d.lastT)\n // a smoothed velocity (value units per ms) for the release inertia\n d.velocity = 0.7 * (-(e.clientX - d.lastX) / pxPerUnit / dt) + 0.3 * d.velocity\n d.lastX = e.clientX\n d.lastT = now\n if (Math.abs(e.clientX - d.startX) > 2) d.moved = true\n emitInput(settle(d.startValue - (e.clientX - d.startX) / pxPerUnit))\n }\n const onPointerUp = (e: PointerEvent<HTMLDivElement>) => {\n const d = drag.current\n if (!d || d.id !== e.pointerId) return\n drag.current = null\n // keep sliding with the release speed, decaying exponentially\n let v = live.current\n // a gentle glide: capped so a flick never sails across the whole range\n const cap = (max - min) / 1500\n let vel = performance.now() - d.lastT < 80 ? Math.max(-cap, Math.min(cap, d.velocity)) : 0\n if (!d.moved || Math.abs(vel) < cap / 20) return commitValue(settle(v))\n let last = performance.now()\n const tick = (now: number) => {\n // a late frame (a busy main thread, a background tab) mustn't turn into one big jump\n const dt = Math.min(32, Math.max(0, now - last))\n last = now\n v += vel * dt\n vel *= Math.pow(0.99, dt)\n const next = settle(v, Math.abs(vel) < cap / 6)\n emitInput(next)\n if (Math.abs(vel) < cap / 40 || next <= min || next >= max) return commitValue(next)\n inertia.current = requestAnimationFrame(tick)\n }\n inertia.current = requestAnimationFrame(tick)\n }\n\n const onWheel = (e: WheelEvent<HTMLDivElement>) => {\n const delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY\n if (!delta) return\n const next = settle(live.current + delta / pxPerUnit / 2)\n emitInput(next)\n clearTimeout(wheelTimer.current)\n wheelTimer.current = setTimeout(() => commitValue(live.current), 220)\n }\n\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n const big = e.shiftKey ? 10 : 1\n let next: number | null = null\n const cur = live.current\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') next = cur + keyStep * big\n else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') next = cur - keyStep * big\n else if (e.key === 'Home') next = min\n else if (e.key === 'End') next = max\n if (next == null) return\n e.preventDefault()\n const v = settle(next, false)\n emitInput(v)\n commitValue(v)\n }\n\n const reset = () => {\n cancelAnimationFrame(inertia.current)\n const v = settle(resetValue, false)\n emitInput(v)\n commitValue(v)\n }\n\n const ticks = Math.floor((max - min) / tickStep)\n const label = format(value)\n return (\n <div\n role=\"slider\"\n tabIndex={0}\n aria-label={ariaLabel}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-valuetext={label}\n aria-orientation=\"horizontal\"\n className={clsx(styles.ruler, className)}\n data-part=\"ruler\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onWheel={onWheel}\n onKeyDown={onKeyDown}\n onDoubleClick={reset}\n >\n <span className={styles.value} aria-hidden=\"true\">\n {label}\n </span>\n <span className={styles.viewport} aria-hidden=\"true\">\n <span\n className={styles.track}\n style={\n {\n width: ticks * TICK_GAP,\n transform: `translateX(${-(value - min) * pxPerUnit}px)`,\n } as CSSProperties\n }\n >\n {Array.from({ length: ticks + 1 }, (_, i) => {\n const tickValue = min + i * tickStep\n return (\n <span\n key={i}\n className={clsx(\n styles.tick,\n i % majorEvery === 0 && styles.major,\n Math.abs(tickValue - resetValue) < 1e-9 && styles.origin,\n )}\n style={{ left: i * TICK_GAP }}\n />\n )\n })}\n </span>\n <span className={styles.indicator} />\n </span>\n </div>\n )\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport type { MessageKey } from '../../i18n/messages'\nimport { Button } from '../Button'\nimport { Icon, type IconName } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Loader } from '../Loader'\nimport { Overlay } from '../Overlay/Overlay'\nimport { ImageEditorCore } from './core/editor'\nimport {\n flipHorizontal,\n MAX_CROP_ZOOM,\n normalizeAngle,\n rotateLeft,\n rotateTo,\n setCropRatio,\n splitRotation,\n applyResize,\n finalSize,\n outputSize,\n zoomOf,\n zoomTo,\n} from './core/geometry'\nimport { FILTER_MATRICES, FINETUNE_IDS } from './core/matrix'\nimport type {\n ImageEditorOptions,\n ImageEditorResult,\n ImageEditorUtil,\n ImageFinetuneId,\n ImageRedactEffect,\n ImageState,\n} from './core/types'\nimport { EditorStage, VIEW_ZOOM_MAX, VIEW_ZOOM_MIN, type EditorStageHandle } from './EditorStage'\nimport { CropShapeMenu, DEFAULT_CROP_RATIOS } from './CropShapeMenu'\nimport { FilterStrip } from './FilterStrip'\nimport { ResizePanel } from './ResizePanel'\nimport { RulerSlider } from './RulerSlider'\nimport styles from './ImageEditor.module.css'\n\nexport interface ImageEditorProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onLoad' | 'title' | 'children'>,\n Omit<ImageEditorOptions, 'src'> {\n /** Whether the editor is shown (a fullscreen overlay). */\n open: boolean\n /** The image to edit: a `File` / `Blob`, a URL or a data URL. */\n src: ImageEditorOptions['src'] | null\n /** Fired once the image has loaded. */\n onLoad?: (info: { width: number; height: number }) => void\n /** Fired on every committed change (a drag's end, a click, a preset). */\n onUpdate?: (state: ImageState) => void\n /** Fired by **Done** with the rendered image + the state it came from; the editor then closes. */\n onProcess?: (result: ImageEditorResult) => void\n /** Requested close (✕, Escape, or after **Done**). Changes are discarded unless processed. */\n onClose: () => void\n}\n\nconst TOOLS: { id: ImageEditorUtil; icon: IconName }[] = [\n { id: 'crop', icon: 'Crop' },\n { id: 'filter', icon: 'Colorfilter' },\n { id: 'finetune', icon: 'Brush' },\n { id: 'redact', icon: 'Blur' },\n { id: 'resize', icon: 'Maximize3' },\n]\n\n/** The Redact tool's effects, in tab order. */\nconst REDACT_EFFECTS: ImageRedactEffect[] = ['blur', 'pixelate']\n\n/** The Filter / Finetune view zoom steps (CSS px per source px). */\nconst ZOOM_LEVELS = [0.05, 0.1, 0.15, 0.2, 0.25, 0.33, 0.5, 0.67, 0.75, 1, 1.5, 2, 3, 4, 6, 8]\n\nconst FOCUSABLE =\n 'a[href]:not([tabindex=\"-1\"]), button:not(:disabled):not([tabindex=\"-1\"]), input:not(:disabled):not([tabindex=\"-1\"]), [tabindex]:not([tabindex=\"-1\"])'\n\nconst RAD = Math.PI / 180\n\n/**\n * A fullscreen image editor — **Crop** (resize, pan, zoom, rotate ±45°, scale, rotate left, flip, Crop\n * Shape presets), **Filter** (14 presets with live thumbnails), **Finetune** (brightness, contrast,\n * saturation, exposure, temperature, gamma, clarity, vignette), **Redact** (blur or pixelate the whole\n * image) and **Resize** (width × height, aspect lock, never upscales) — over a WebGL renderer (Canvas2D\n * fallback), with undo / redo / revert (Revert = back to the original image). **Done** renders the result\n * at full source resolution (JPEG / PNG / WebP keep their type, anything else becomes PNG) and hands it to\n * `onProcess` with the `imageState`, which re-opens the edit non-destructively via `initialState`. Follows\n * the app's light / dark theme.\n */\nexport const ImageEditor = forwardRef<HTMLDivElement, ImageEditorProps>(function ImageEditor(\n {\n open,\n src,\n initialState,\n util = 'crop',\n cropAspectRatio,\n cropRatioOptions,\n outputType,\n outputQuality,\n onLoad,\n onUpdate,\n onProcess,\n onClose,\n className,\n onKeyDown: onKeyDownProp,\n ...props\n },\n ref,\n) {\n const t = useT()\n const [core] = useState(() => new ImageEditorCore())\n const snap = useSyncExternalStore(core.subscribe, core.getSnapshot, core.getSnapshot)\n const { state, size, ui, status } = snap\n const stageRef = useRef<EditorStageHandle>(null)\n const rootRef = useRef<HTMLDivElement | null>(null)\n const areaRef = useRef<HTMLDivElement | null>(null)\n const [viewZoom, setViewZoom] = useState<number | null>(null)\n const [effectiveZoom, setEffectiveZoom] = useState(1)\n const [processing, setProcessing] = useState(false)\n const [processError, setProcessError] = useState(false)\n // the quarter-turn part of the rotation (the fine slider moves only the rest)\n const quarter = useRef(0)\n const rotationBase = useRef<ImageState | null>(null)\n // the state the Resize tool's picks are made from: the one it was entered with (re-taken after an\n // undo / redo / revert) — so typing 1800 × 100, then 1800 × 600 cuts from the full crop again\n const resizeBase = useRef<ImageState | null>(null)\n const resizeOwn = useRef<ImageState | null>(null)\n if (ui.util !== 'resize' || !state) resizeBase.current = null\n else if (!resizeBase.current || (state !== resizeOwn.current && state !== resizeBase.current))\n resizeBase.current = state\n\n // latest callbacks for the event subscriptions\n const cbs = useRef({ onLoad, onUpdate })\n cbs.current = { onLoad, onUpdate }\n useEffect(() => {\n const offs = [\n core.on('load', (p) =>\n cbs.current.onLoad?.((p as { size: { width: number; height: number } }).size),\n ),\n core.on('update', (s) => cbs.current.onUpdate?.(s as ImageState)),\n // a rotation drag's base is stale once history moves under it\n ...(['undo', 'redo', 'revert'] as const).map((e) =>\n core.on(e, () => {\n rotationBase.current = null\n }),\n ),\n ]\n return () => offs.forEach((off) => off())\n }, [core])\n\n // open / re-open on a new source\n useEffect(() => {\n if (!open || !src) return\n setViewZoom(null)\n setProcessError(false)\n core\n .open({ src, initialState, util, cropAspectRatio, outputType, outputQuality })\n .then(() => {\n const s = core.getSnapshot().state\n if (s) quarter.current = splitRotation(s.rotation).quarter\n })\n .catch(() => {}) // surfaced through the snapshot's `error` status\n return () => core.close()\n // eslint-disable-next-line react-hooks/exhaustive-deps -- re-open only when the image changes\n }, [open, src, core])\n\n // while open, a pinch / Ctrl+wheel zooms the IMAGE, never the page: Chrome / Edge / Firefox send a\n // trackpad pinch as a Ctrl+wheel (React's wheel listener is passive, so it can't cancel it — this one\n // isn't), Safari as gesture events\n useEffect(() => {\n if (!open) return\n const onWheel = (e: WheelEvent) => {\n if (e.ctrlKey || e.metaKey) e.preventDefault()\n }\n const onGesture = (e: Event) => e.preventDefault()\n const gestures = ['gesturestart', 'gesturechange', 'gestureend']\n window.addEventListener('wheel', onWheel, { passive: false })\n gestures.forEach((g) => document.addEventListener(g, onGesture))\n return () => {\n window.removeEventListener('wheel', onWheel)\n gestures.forEach((g) => document.removeEventListener(g, onGesture))\n }\n }, [open])\n\n // focus: into the editor on open, back to the opener on close\n useEffect(() => {\n if (!open) return\n const opener = document.activeElement as HTMLElement | null\n const id = requestAnimationFrame(() => rootRef.current?.focus())\n return () => {\n cancelAnimationFrame(id)\n opener?.focus?.()\n }\n }, [open])\n\n const setRef = (node: HTMLDivElement | null) => {\n rootRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }\n\n // ── actions ──────────────────────────────────────────────────────────────────────────────────\n const syncQuarter = () => {\n const s = core.getSnapshot().state\n if (s) quarter.current = splitRotation(s.rotation).quarter\n }\n const undo = () => {\n stageRef.current?.transition('jump')\n core.undo()\n syncQuarter()\n }\n const redo = () => {\n stageRef.current?.transition('jump')\n core.redo()\n syncQuarter()\n }\n const revert = () => {\n stageRef.current?.transition('jump')\n core.revert()\n syncQuarter()\n }\n const doRotateLeft = () => {\n if (!state || !size) return\n stageRef.current?.transition('rotate')\n quarter.current = normalizeAngle(quarter.current - Math.PI / 2)\n core.setState(rotateLeft(state, size))\n }\n const doFlip = () => {\n if (!state || !size) return\n stageRef.current?.transition('flip')\n quarter.current = normalizeAngle(-quarter.current)\n core.setState(flipHorizontal(state, size))\n }\n\n const close = useCallback(() => onClose(), [onClose])\n // ✕ / Escape close straight away — unsaved edits are dropped (no confirmation)\n const requestClose = () => {\n if (!processing) close()\n }\n const done = async () => {\n if (!state || processing) return\n setProcessing(true)\n setProcessError(false)\n try {\n const result = await core.process()\n onProcess?.(result)\n close()\n } catch {\n setProcessError(true)\n } finally {\n setProcessing(false)\n }\n }\n\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n // the consumer's handler runs first and can opt out with preventDefault (its own shortcuts win)\n onKeyDownProp?.(e)\n if (e.defaultPrevented) return\n const mod = e.metaKey || e.ctrlKey\n if (mod && e.key.toLowerCase() === 'z') {\n e.preventDefault()\n if (e.shiftKey) redo()\n else undo()\n return\n }\n if (mod && e.key.toLowerCase() === 'y') {\n e.preventDefault()\n redo()\n return\n }\n if (e.key !== 'Tab' || !rootRef.current) return\n // trap Tab inside the editor\n const els = [...rootRef.current.querySelectorAll<HTMLElement>(FOCUSABLE)].filter(\n (el) => el.offsetParent !== null,\n )\n if (els.length === 0) return\n const first = els[0]\n const last = els[els.length - 1]\n if (\n e.shiftKey &&\n (document.activeElement === first || document.activeElement === rootRef.current)\n ) {\n e.preventDefault()\n last.focus()\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault()\n first.focus()\n }\n }\n\n // ── view zoom (Filter / Finetune) ────────────────────────────────────────────────────────────\n const zoomStep = (dir: 1 | -1) => {\n const z = effectiveZoom\n const next =\n dir > 0\n ? (ZOOM_LEVELS.find((l) => l > z * 1.01) ?? VIEW_ZOOM_MAX)\n : ([...ZOOM_LEVELS].reverse().find((l) => l < z * 0.99) ?? VIEW_ZOOM_MIN)\n setViewZoom(next)\n }\n\n // ── footers ──────────────────────────────────────────────────────────────────────────────────\n const fine = state ? splitRotation(state.rotation, quarter.current).fine / RAD : 0\n /** Apply a Resize pick (from the tool's base state) as a live change. */\n const resizeTo = (pick: { width: number; height: number } | null) => {\n const base = resizeBase.current ?? core.getSnapshot().state\n if (!base) return\n core.preview(applyResize(base, pick))\n resizeOwn.current = core.getSnapshot().state\n }\n\n let footer: ReactNode = null\n if (state && size) {\n if (ui.util === 'crop') {\n footer = (\n <>\n {ui.cropTab === 'rotation' ? (\n <RulerSlider\n key=\"rotation\"\n aria-label={t('imageEditor.rotation')}\n min={-45}\n max={45}\n step={0.1}\n tickStep={1}\n majorEvery={5}\n snapThreshold={0.6}\n value={Number(fine.toFixed(1))}\n format={(v) => `${Number(v.toFixed(1))}°`}\n onInput={(v) => {\n const s = core.getSnapshot().state\n if (!s) return\n rotationBase.current ??= s\n core.preview(rotateTo(rotationBase.current, quarter.current + v * RAD, size))\n }}\n onChange={(v) => {\n const base = rotationBase.current ?? core.getSnapshot().state\n rotationBase.current = null\n if (!base) return\n core.preview(rotateTo(base, quarter.current + v * RAD, size))\n core.commit()\n }}\n />\n ) : (\n <RulerSlider\n key=\"scale\"\n aria-label={t('imageEditor.scale')}\n min={100}\n max={MAX_CROP_ZOOM * 100}\n step={1}\n tickStep={10}\n majorEvery={5}\n snapPoints={[100]}\n snapThreshold={4}\n resetValue={100}\n value={Math.round(zoomOf(state, size) * 100)}\n format={(v) => `${Math.round(v)}%`}\n onInput={(v) => {\n const s = core.getSnapshot().state\n if (s) core.preview(zoomTo(s, v / 100, size))\n }}\n onChange={(v) => {\n const s = core.getSnapshot().state\n if (!s) return\n core.preview(zoomTo(s, v / 100, size))\n core.commit()\n }}\n />\n )}\n <SegmentedTabs\n label={t('imageEditor.crop')}\n value={ui.cropTab}\n options={[\n { id: 'rotation', label: t('imageEditor.rotation') },\n { id: 'scale', label: t('imageEditor.scale') },\n ]}\n onChange={(cropTab) => core.setUi({ cropTab })}\n />\n </>\n )\n } else if (ui.util === 'filter' && core.image) {\n footer = (\n <FilterStrip\n image={core.image.image}\n size={size}\n state={state}\n onSelect={(id) =>\n core.setState({\n filter: id === 'default' ? null : id,\n colorMatrix: FILTER_MATRICES[id],\n })\n }\n />\n )\n } else if (ui.util === 'resize') {\n footer = (\n <ResizePanel\n max={outputSize(resizeBase.current ?? state)}\n value={finalSize(state)}\n locked={ui.resizeLocked}\n onLockedChange={(resizeLocked) => core.setUi({ resizeLocked })}\n onInput={resizeTo}\n onChange={(pick) => {\n resizeTo(pick)\n core.commit()\n }}\n />\n )\n } else if (ui.util === 'redact') {\n const redact = state.redact\n footer = (\n <>\n <RulerSlider\n key={redact.effect}\n aria-label={t(`imageEditor.redact.${redact.effect}` as MessageKey)}\n min={0}\n max={100}\n step={1}\n // 40 ticks — the same length as the Finetune ruler\n tickStep={2.5}\n majorEvery={4}\n // no snapping — the small values are the useful ones here\n snapThreshold={0}\n value={redact.amount}\n format={(v) => String(Math.round(v))}\n onInput={(amount) => core.preview({ redact: { ...redact, amount } })}\n onChange={(amount) => {\n core.preview({ redact: { ...redact, amount } })\n core.commit()\n }}\n />\n <SegmentedTabs\n label={t('imageEditor.redact')}\n value={redact.effect}\n options={REDACT_EFFECTS.map((id) => ({\n id,\n label: t(`imageEditor.redact.${id}` as MessageKey),\n }))}\n onChange={(effect: ImageRedactEffect) =>\n core.setState({ redact: { ...redact, effect } })\n }\n />\n </>\n )\n } else if (ui.util === 'finetune') {\n const tab = ui.finetuneTab\n footer = (\n <>\n <RulerSlider\n key={tab}\n aria-label={t(`imageEditor.finetune.${tab}` as MessageKey)}\n min={-100}\n max={100}\n step={1}\n tickStep={5}\n majorEvery={4}\n snapThreshold={3}\n value={state.finetune[tab]}\n format={(v) => String(Math.round(v))}\n onInput={(v) => {\n const s = core.getSnapshot().state\n if (s) core.preview({ finetune: { ...s.finetune, [tab]: v } })\n }}\n onChange={(v) => {\n const s = core.getSnapshot().state\n if (!s) return\n core.preview({ finetune: { ...s.finetune, [tab]: v } })\n core.commit()\n }}\n />\n <SegmentedTabs\n label={t('imageEditor.finetune')}\n value={tab}\n options={FINETUNE_IDS.map((id) => ({\n id,\n label: t(`imageEditor.finetune.${id}` as MessageKey),\n dot: state.finetune[id] !== 0,\n }))}\n onChange={(finetuneTab: ImageFinetuneId) => core.setUi({ finetuneTab })}\n />\n </>\n )\n }\n }\n\n const ready = status === 'ready' && !!state\n const showZoom = ready && ui.util !== 'crop'\n return (\n <Overlay\n open={open}\n onClose={requestClose}\n closeOnBackdrop={false}\n dim={0}\n className={styles.overlay}\n >\n <div\n ref={setRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t('imageEditor.title')}\n tabIndex={-1}\n className={clsx(styles.editor, className)}\n data-part=\"editor\"\n onKeyDown={onKeyDown}\n {...props}\n >\n {/* the canvas fills the whole editor — the image runs behind the header, tools and footer */}\n <EditorStage\n ref={stageRef}\n core={core}\n snapshot={snap}\n cropAspectRatio={cropAspectRatio}\n viewZoom={ui.util === 'crop' ? null : viewZoom}\n onViewZoom={setViewZoom}\n onZoomReport={setEffectiveZoom}\n areaRef={areaRef}\n />\n {/* ── header ─────────────────────────────────────────────────────────────────────── */}\n <header className={styles.header} data-part=\"header\">\n <div className={styles.headerStart}>\n <div className={styles.group}>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.close')}\n title={t('imageEditor.close')}\n onClick={requestClose}\n >\n <Icon name=\"Close\" className={styles.closeIcon} />\n </IconButton>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.revert')}\n title={t('imageEditor.revert')}\n disabled={!snap.canRevert}\n onClick={revert}\n >\n <Icon name=\"ReverseTimeArrow\" />\n </IconButton>\n </div>\n </div>\n <div className={styles.headerCenter}>\n <div className={styles.group}>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.undo')}\n title={t('imageEditor.undo')}\n disabled={!snap.canUndo}\n onClick={undo}\n >\n <Icon name=\"UndoArrow\" />\n </IconButton>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.redo')}\n title={t('imageEditor.redo')}\n disabled={!snap.canRedo}\n onClick={redo}\n >\n <Icon name=\"RedoArrow\" />\n </IconButton>\n </div>\n {/* the Crop view's zoom is set by its own rules (fit / real size / enlarged when tiny) — shown,\n not driven from here (the Scale ruler and a pinch zoom the image itself) */}\n {ready && ui.util === 'crop' && (\n <div className={clsx(styles.group, styles.fadeIn)}>\n <span\n className={clsx(styles.zoomLabel, styles.zoomReadout)}\n role=\"status\"\n aria-label={t('imageEditor.zoom')}\n >\n {Math.round(effectiveZoom * 100)}%\n </span>\n </div>\n )}\n {showZoom && (\n <div className={clsx(styles.group, styles.fadeIn)}>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.zoomOut')}\n title={t('imageEditor.zoomOut')}\n disabled={effectiveZoom <= VIEW_ZOOM_MIN * 1.01}\n onClick={() => zoomStep(-1)}\n >\n <Icon name=\"Minus\" />\n </IconButton>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <button\n type=\"button\"\n className={styles.zoomLabel}\n aria-label={t('imageEditor.zoom')}\n title={t('imageEditor.zoomFit')}\n onClick={() => setViewZoom(null)}\n >\n {Math.round(effectiveZoom * 100)}%\n </button>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.zoomIn')}\n title={t('imageEditor.zoomIn')}\n disabled={effectiveZoom >= VIEW_ZOOM_MAX * 0.99}\n onClick={() => zoomStep(1)}\n >\n <Icon name=\"Add\" />\n </IconButton>\n </div>\n )}\n </div>\n <div className={styles.headerEnd}>\n {/* Done — the primary action: a solid accent circle, the size of the other header pills (the\n whole circle is the hit area) */}\n <IconButton\n variant=\"contained\"\n color=\"accent\"\n size=\"sm\"\n loading={processing}\n disabled={!ready}\n aria-label={t('imageEditor.done')}\n title={t('imageEditor.done')}\n onClick={done}\n className={styles.done}\n >\n <Icon name=\"CheckMarkTick\" />\n </IconButton>\n </div>\n </header>\n\n {/* ── main ───────────────────────────────────────────────────────────────────────── */}\n <div className={styles.main} data-part=\"main\">\n <nav className={styles.nav} data-part=\"nav\">\n <div\n role=\"tablist\"\n aria-label={t('imageEditor.tools')}\n aria-orientation=\"vertical\"\n className={styles.navList}\n onKeyDown={(e) => {\n const i = TOOLS.findIndex((tool) => tool.id === ui.util)\n const next =\n e.key === 'ArrowDown' || e.key === 'ArrowRight'\n ? TOOLS[(i + 1) % TOOLS.length]\n : e.key === 'ArrowUp' || e.key === 'ArrowLeft'\n ? TOOLS[(i + TOOLS.length - 1) % TOOLS.length]\n : null\n if (!next) return\n e.preventDefault()\n core.setUi({ util: next.id })\n ;(e.currentTarget.querySelector(`[data-util=\"${next.id}\"]`) as HTMLElement)?.focus()\n }}\n >\n {TOOLS.map((tool) => {\n const active = ui.util === tool.id\n return (\n <button\n key={tool.id}\n type=\"button\"\n role=\"tab\"\n id={`tz-ie-tab-${tool.id}`}\n aria-selected={active}\n aria-controls=\"tz-ie-panel\"\n tabIndex={active ? 0 : -1}\n title={t(`imageEditor.${tool.id}` as MessageKey)}\n className={clsx(styles.tool, active && styles.toolActive)}\n data-util={tool.id}\n onClick={() => core.setUi({ util: tool.id })}\n >\n <Icon name={tool.icon} size=\"sm\" />\n <span className={styles.toolLabel}>\n {t(`imageEditor.${tool.id}` as MessageKey)}\n </span>\n </button>\n )\n })}\n </div>\n </nav>\n\n <section\n className={styles.stage}\n id=\"tz-ie-panel\"\n role=\"tabpanel\"\n aria-labelledby={`tz-ie-tab-${ui.util}`}\n data-part=\"stage\"\n data-util={ui.util}\n >\n <div className={styles.toolbar} data-part=\"toolbar\">\n {ready && ui.util === 'crop' && (\n <div key=\"crop-toolbar\" className={clsx(styles.toolbarRow, styles.fadeIn)}>\n <Button\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n startIcon={<Icon name=\"RotateLeft\" />}\n title={t('imageEditor.rotateLeft')}\n aria-label={t('imageEditor.rotateLeft')}\n onClick={doRotateLeft}\n className={styles.toolbarIconOnPhone}\n >\n <span className={styles.toolbarLabel}>{t('imageEditor.rotateLeft')}</span>\n </Button>\n <Button\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n startIcon={<Icon name=\"FlipHorizontal\" />}\n title={t('imageEditor.flipHorizontal')}\n aria-label={t('imageEditor.flipHorizontal')}\n onClick={doFlip}\n className={styles.toolbarIconOnPhone}\n >\n <span className={styles.toolbarLabel}>{t('imageEditor.flipHorizontal')}</span>\n </Button>\n {/* a ratio-locked editor (`cropAspectRatio`) has no shape to pick */}\n {!cropAspectRatio && state && (\n <CropShapeMenu\n ratio={state.cropRatio}\n options={cropRatioOptions ?? DEFAULT_CROP_RATIOS}\n onChange={(ratio) => {\n const s = core.getSnapshot().state\n if (!s || !size) return\n stageRef.current?.transition('jump')\n core.setState(setCropRatio(s, ratio, size))\n }}\n />\n )}\n </div>\n )}\n </div>\n\n {/* the free area the crop is laid out in (the canvas itself spans the whole editor) */}\n <div ref={areaRef} className={styles.canvasArea} data-part=\"area\">\n {status === 'loading' && (\n <div className={styles.status} role=\"status\">\n <Loader size=\"lg\" />\n <span>{t('imageEditor.loading')}</span>\n </div>\n )}\n {status === 'error' && (\n <div className={styles.status} role=\"alert\">\n <Icon name=\"Gallery\" size=\"lg\" />\n <span>{t('imageEditor.loadError')}</span>\n </div>\n )}\n {processError && (\n <div className={styles.toastError} role=\"alert\">\n {t('imageEditor.processError')}\n </div>\n )}\n </div>\n\n <div className={styles.footer} data-part=\"footer\">\n <div key={ui.util} className={clsx(styles.footerInner, styles.fadeIn)}>\n {footer}\n </div>\n </div>\n </section>\n </div>\n </div>\n </Overlay>\n )\n})\n\n/** A small segmented tab list (the Rotation | Scale and the finetune adjustment tabs). */\nfunction SegmentedTabs<T extends string>({\n label,\n value,\n options,\n onChange,\n}: {\n label: string\n value: T\n options: { id: T; label: string; dot?: boolean }[]\n onChange: (id: T) => void\n}) {\n const listRef = useRef<HTMLDivElement>(null)\n // keep the active tab in view when the row scrolls (phones)\n useEffect(() => {\n listRef.current\n ?.querySelector<HTMLElement>(`[data-tab=\"${value}\"]`)\n ?.scrollIntoView?.({ block: 'nearest', inline: 'nearest', behavior: 'smooth' })\n }, [value])\n return (\n <div\n ref={listRef}\n role=\"tablist\"\n aria-label={label}\n className={styles.tabs}\n data-part=\"tabs\"\n onKeyDown={(e) => {\n const i = options.findIndex((o) => o.id === value)\n const step = e.key === 'ArrowRight' ? 1 : e.key === 'ArrowLeft' ? -1 : 0\n if (!step) return\n e.preventDefault()\n const next = options[(i + step + options.length) % options.length]\n onChange(next.id)\n ;(e.currentTarget.querySelector(`[data-tab=\"${next.id}\"]`) as HTMLElement)?.focus()\n }}\n >\n {options.map((o) => (\n <button\n key={o.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={o.id === value}\n tabIndex={o.id === value ? 0 : -1}\n className={clsx(styles.tab, o.id === value && styles.tabActive)}\n data-tab={o.id}\n onClick={() => onChange(o.id)}\n >\n {o.label}\n {o.dot && <span className={styles.tabDot} aria-hidden=\"true\" />}\n </button>\n ))}\n </div>\n )\n}\n"],"names":["IDENTITY_MATRIX","LR","LG","LB","multiplyMatrix","a","b","out","row","col","sum","k","composeMatrices","matrices","acc","m","isIdentityMatrix","v","i","brightnessMatrix","contrastMatrix","c","o","saturationMatrix","s","channelMatrix","r","g","or","og","ob","levelsMatrix","low","high","SEPIA_MATRIX","FILTER_GROUPS","MONO","FILTER_MATRICES","FINETUNE_IDS","ZERO_FINETUNE","finetuneParam","finetuneMatrix","f","t","combinedMatrix","colorMatrix","finetune","QUARTER","EPS","rotate","x","y","theta","halfExtents","w","h","cropCenter","crop","coverScale","size","ex","ey","cropAnchor","state","kx","ky","ux","uy","clampAnchor","lx","ly","cropAt","u","dx","dy","coversCrop","corners","tol","qx","qy","fitState","outputSize","finalSize","resizedCrop","target","aspect","width","height","applyResize","base","pick","proportional","next","full","resize","syncResize","prev","before","after","initialCrop","aspectRatio","defaultState","splitRotation","quarterHint","turns","quarter","fine","normalizeAngle","rotateTo","clamped","rotateLeft","cx","cy","flipHorizontal","zoomOf","MAX_CROP_ZOOM","zoomTo","zoom","panBy","moved","setCropRatio","ratio","resizeCrop","start","handle","minSize","left","top","right","bottom","hasN","hasS","hasW","hasE","fits","furthest","horizontal","from","vertical","viaX","viaY","miss","to","dest","lo","hi","mid","lerpRect","normalizeState","VIGNETTE_STRENGTH","smoothstep","e0","e1","vignetteFalloff","nx","ny","applyColorOps","data","p","blur","toCrop","invGamma","useGamma","useClarity","useVignette","r0","g0","b0","br","bg","bb","ba","mr","mg","mb","px","py","boxBlur","src","radius","pass","blurLine","rad","lines","len","stride","span","idx","inn","CLARITY_RADIUS","canvasOf","decodeBlob","blob","url","decodeUrl","crossOrigin","resolve","reject","img","sizeOf","loadImage","image","type","res","downscale","source","maxSide","ctx","blurredCopy","resolveOutputType","requested","input","IDENTITY_AFFINE","translate","scaleAffine","sx","sy","rotateAffine","multiplyAffine","chain","ts","invertAffine","d","e","det","applyAffine","REDACT_MAX","redactRadius","effect","_a","_b","pixelGrid","block","BLUR_WORK_RADIUS","blurredSmall","work","blurredFull","pixelateCanvas","canvas","cols","rows","small","sctx","pixelatedCopy","stageOrigin","stage","sourceToPlane","planeToScreen","view","flip","ox","oy","planeToCrop","sceneAffines","deviceToPlane","toUV","fitView","padding","VERTEX","FRAGMENT","WebGLRenderer","gl","buffer","pos","name","opts","compile","sh","program","tex","unit","mipmap","isGL2","dr","dg","db","cm","rowCount","loseContext","colorParams","hasColorOps","canvas2d","render2D","texture","textureSize","blurSize","drawThrough","fromCrop","colorPass2D","blurData","bctx","MAX_SIDE","MAX_AREA","toBlob","quality","renderOutput","ow","oh","params","colorPassTiled","glCanvas","tileSize","tile","tctx","ty","tx","tw","th","toBlurUV","MAX_HISTORY","same","sameSize","clone","ImageEditorCore","fn","event","cb","set","payload","options","token","loaded","init","merged","error","cur","anchor","ui","result","createImageEditor","prefersReducedMotion","springTo","onFrame","stiffness","damping","onDone","noop","last","raf","cancelled","step","now","dt","xi","PAD_CROP","PAD_VIEW","PREVIEW_MAX","CROP_VIEW_MIN_SIDE","BLUR_PREVIEW_MAX","CROP_DIM","backgroundRgb","el","raw","MIN_CROP_SCREEN","HANDLES","viewToVector","vectorToView","EditorStage","forwardRef","core","snapshot","cropAspectRatio","viewZoom","onViewZoom","onZoomReport","areaRef","ref","mode","useColorMode","util","viewportRef","useRef","canvasRef","setStage","useState","setView","viewRef","pan","setPan","interacting","setInteracting","nonce","setNonce","frozen","pending","stopSpring","gesture","pointers","wheelCommit","useEffect","measure","symmetricArea","measureRef","ro","useLayoutEffect","renderer","setRenderer","detail","coarseWidth","redactEffect","redactAmount","setSource","smooth","useMemo","area","fitted","real","handleable","fit","scale","prevUtil","springing","lastLayout","startSpring","surround","setSurround","surroundRef","layoutOnly","prevResize","resized","_c","prevTarget","sameTarget","kind","_d","shown","affines","pixel","useImperativeHandle","onViewZoomRef","pinchDistance","onPointerDown","onPointerMove","clampZoom","onPointerUp","n","onWheel","zoomGesture","safariGesture","factor","current","live","onStart","sz","onChange","onEnd","cropBox","x0","y0","x1","y1","sceneTransform","jsxs","clsx","styles","jsx","inset","VIEW_ZOOM_MIN","VIEW_ZOOM_MAX","z","DEFAULT_CROP_RATIOS","flipLabel","label","ShapePreview","CropShapeMenu","useT","open","setOpen","portraitPref","setPortraitPref","portrait","setOrientation","toPortrait","Dropdown","Button","Icon","ListItem","THUMB","renderThumbs","dpr","id","FilterStrip","onSelect","scrollerRef","thumbs","setThumbs","edges","setEdges","active","key","updateEdges","drag","momentum","ev","ids","onKeyDown","group","gi","PRESETS","clampSide","max","ResizePanel","value","locked","onLockedChange","onInput","draft","setDraft","liveRatio","heldRatio","side","normalize","edit","digits","commit","presetActive","TICK_GAP","RulerSlider","min","keyStep","snapPoints","snapThreshold","tickStep","majorEvery","resetValue","format","ariaLabel","className","pxPerUnit","inertia","wheelTimer","latestOnChange","commitValue","settle","snap","emitInput","cap","vel","tick","delta","big","reset","ticks","_","tickValue","TOOLS","REDACT_EFFECTS","ZOOM_LEVELS","FOCUSABLE","RAD","ImageEditor","initialState","cropRatioOptions","outputType","outputQuality","onLoad","onUpdate","onProcess","onClose","onKeyDownProp","props","useSyncExternalStore","status","stageRef","rootRef","setViewZoom","effectiveZoom","setEffectiveZoom","processing","setProcessing","processError","setProcessError","rotationBase","resizeBase","resizeOwn","cbs","offs","off","onGesture","gestures","opener","setRef","node","syncQuarter","undo","redo","revert","doRotateLeft","doFlip","close","useCallback","requestClose","done","mod","els","first","zoomStep","dir","l","resizeTo","footer","Fragment","SegmentedTabs","cropTab","resizeLocked","redact","amount","tab","finetuneTab","ready","showZoom","Overlay","IconButton","tool","Loader","listRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ImageEditor-CKfaHNGz.js","sources":["../src/components/ImageEditor/core/matrix.ts","../src/components/ImageEditor/core/geometry.ts","../src/components/ImageEditor/core/pixels.ts","../src/components/ImageEditor/core/load.ts","../src/components/ImageEditor/core/affine.ts","../src/components/ImageEditor/core/redact.ts","../src/components/ImageEditor/core/scene.ts","../src/components/ImageEditor/core/webgl.ts","../src/components/ImageEditor/core/render.ts","../src/components/ImageEditor/core/editor.ts","../src/components/ImageEditor/core/spring.ts","../src/components/ImageEditor/EditorStage.tsx","../src/components/ImageEditor/CropShapeMenu.tsx","../src/components/ImageEditor/FilterStrip.tsx","../src/components/ImageEditor/ResizePanel.tsx","../src/components/ImageEditor/RulerSlider.tsx","../src/components/ImageEditor/ImageEditor.tsx"],"sourcesContent":["// Color matrices — the 4×5 (20-number, row-major) form the editor uses for filters and the matrix-based\n// finetune adjustments. Row i computes channel i (r, g, b, a) as\n// out = m[0]·r + m[1]·g + m[2]·b + m[3]·a + m[4]\n// with every channel and the offset in 0…1. Composition goes through the 5×5 homogeneous form.\n\nimport type { ImageFilterId, ImageFinetuneId } from './types'\n\nexport type ColorMatrix = number[]\n\n/** The identity matrix (no change). */\nexport const IDENTITY_MATRIX: ColorMatrix = [\n 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,\n]\n\n/** Rec. 709 luma weights (the grayscale / saturation basis). */\nconst LR = 0.2126\nconst LG = 0.7152\nconst LB = 0.0722\n\n/** `a ∘ b` — the matrix that applies `b` first, then `a`. */\nexport function multiplyMatrix(a: ColorMatrix, b: ColorMatrix): ColorMatrix {\n const out = new Array<number>(20)\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 5; col++) {\n let sum = 0\n for (let k = 0; k < 4; k++) sum += a[row * 5 + k] * b[k * 5 + col]\n // the homogeneous row of b is [0 0 0 0 1], so a's offset carries through only for the last column\n if (col === 4) sum += a[row * 5 + 4]\n out[row * 5 + col] = sum\n }\n }\n return out\n}\n\n/** Compose matrices in application order: `composeMatrices(m1, m2, m3)` applies m1, then m2, then m3. */\nexport function composeMatrices(...matrices: ColorMatrix[]): ColorMatrix {\n return matrices.reduce((acc, m) => multiplyMatrix(m, acc), IDENTITY_MATRIX)\n}\n\n/** Whether a matrix is (numerically) the identity. */\nexport function isIdentityMatrix(m: ColorMatrix | null | undefined): boolean {\n return !m || m.every((v, i) => Math.abs(v - IDENTITY_MATRIX[i]) < 1e-6)\n}\n\n/** Apply a matrix to one straight-alpha RGBA color (each 0…1). */\nexport function applyMatrix(\n m: ColorMatrix,\n r: number,\n g: number,\n b: number,\n a = 1,\n): [number, number, number, number] {\n return [\n m[0] * r + m[1] * g + m[2] * b + m[3] * a + m[4],\n m[5] * r + m[6] * g + m[7] * b + m[8] * a + m[9],\n m[10] * r + m[11] * g + m[12] * b + m[13] * a + m[14],\n m[15] * r + m[16] * g + m[17] * b + m[18] * a + m[19],\n ]\n}\n\n// ── building blocks ─────────────────────────────────────────────────────────────────────────────\n\n/** Add `v` to r, g and b. */\nexport const brightnessMatrix = (v: number): ColorMatrix => [\n 1,\n 0,\n 0,\n 0,\n v,\n 0,\n 1,\n 0,\n 0,\n v,\n 0,\n 0,\n 1,\n 0,\n v,\n 0,\n 0,\n 0,\n 1,\n 0,\n]\n\n/** Scale r, g, b around the 0.5 midpoint by `c`. */\nexport const contrastMatrix = (c: number): ColorMatrix => {\n const o = 0.5 * (1 - c)\n return [c, 0, 0, 0, o, 0, c, 0, 0, o, 0, 0, c, 0, o, 0, 0, 0, 1, 0]\n}\n\n/** Saturation `s` (0 = grayscale, 1 = unchanged, 2 = doubled), on Rec. 709 luma. */\nexport const saturationMatrix = (s: number): ColorMatrix => {\n const i = 1 - s\n return [\n LR * i + s,\n LG * i,\n LB * i,\n 0,\n 0,\n LR * i,\n LG * i + s,\n LB * i,\n 0,\n 0,\n LR * i,\n LG * i,\n LB * i + s,\n 0,\n 0,\n 0,\n 0,\n 0,\n 1,\n 0,\n ]\n}\n\n/** Multiply each channel (and optionally add a per-channel offset). */\nexport const channelMatrix = (r: number, g: number, b: number, or = 0, og = 0, ob = 0) => [\n r,\n 0,\n 0,\n 0,\n or,\n 0,\n g,\n 0,\n 0,\n og,\n 0,\n 0,\n b,\n 0,\n ob,\n 0,\n 0,\n 0,\n 1,\n 0,\n]\n\n/** Remap 0…1 to `low`…`high` (lifts blacks / dims whites). */\nexport const levelsMatrix = (low: number, high: number): ColorMatrix => {\n const k = high - low\n return [k, 0, 0, 0, low, 0, k, 0, 0, low, 0, 0, k, 0, low, 0, 0, 0, 1, 0]\n}\n\n/** The classic sepia matrix. */\nexport const SEPIA_MATRIX: ColorMatrix = [\n 0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0,\n]\n\n// ── filters ─────────────────────────────────────────────────────────────────────────────────────\n\n/** The filter presets in display order, grouped (a gap between groups). */\nexport const FILTER_GROUPS: ImageFilterId[][] = [\n ['default'],\n ['chrome', 'fade', 'cold', 'warm', 'pastel'],\n ['mono', 'noir', 'stark', 'wash'],\n ['sepia', 'rust', 'blues', 'color'],\n]\n\nconst MONO = saturationMatrix(0)\n\n/** Each filter's 4×5 matrix (`default` → `null`, no filter). */\nexport const FILTER_MATRICES: Record<ImageFilterId, ColorMatrix | null> = {\n default: null,\n // more contrast + saturation\n chrome: composeMatrices(saturationMatrix(1.3), contrastMatrix(1.15)),\n // lifted blacks, softer whites, desaturated\n fade: composeMatrices(saturationMatrix(0.7), levelsMatrix(0.12, 0.92)),\n // a blue shift\n cold: composeMatrices(channelMatrix(0.9, 0.98, 1.12, 0, 0.01, 0.03), contrastMatrix(1.04)),\n // a red / yellow shift\n warm: composeMatrices(channelMatrix(1.1, 1.03, 0.86, 0.03, 0.01, 0), contrastMatrix(1.04)),\n // brightened + desaturated\n pastel: composeMatrices(saturationMatrix(0.6), levelsMatrix(0.16, 1)),\n // luminance grayscale\n mono: MONO,\n // high-contrast grayscale\n noir: composeMatrices(MONO, contrastMatrix(1.45), brightnessMatrix(-0.04)),\n // very high-contrast grayscale\n stark: composeMatrices(MONO, contrastMatrix(2.1)),\n // low-contrast, bright grayscale\n wash: composeMatrices(MONO, levelsMatrix(0.22, 0.98)),\n sepia: SEPIA_MATRIX,\n // a warm, strong sepia\n rust: composeMatrices(SEPIA_MATRIX, channelMatrix(1.12, 0.9, 0.7), contrastMatrix(1.12)),\n // blue-tinted monochrome\n blues: composeMatrices(MONO, channelMatrix(0.72, 0.88, 1.08, 0, 0.02, 0.08)),\n // boosted, vivid color\n color: composeMatrices(saturationMatrix(1.65), contrastMatrix(1.06)),\n}\n\n// ── finetune ────────────────────────────────────────────────────────────────────────────────────\n\n/** The finetune adjustments in display order. */\nexport const FINETUNE_IDS: ImageFinetuneId[] = [\n 'brightness',\n 'contrast',\n 'saturation',\n 'exposure',\n 'temperature',\n 'gamma',\n 'clarity',\n 'vignette',\n]\n\n/** All adjustments at 0. */\nexport const ZERO_FINETUNE: Record<ImageFinetuneId, number> = {\n brightness: 0,\n contrast: 0,\n saturation: 0,\n exposure: 0,\n temperature: 0,\n gamma: 0,\n clarity: 0,\n vignette: 0,\n}\n\n/** The UI value (−100…100) → the shader parameter for each adjustment. */\nexport const finetuneParam = {\n /** additive: −0.25…+0.25 */\n brightness: (v: number) => (v / 100) * 0.25,\n /** multiply around the midpoint: 0.5…1.5 */\n contrast: (v: number) => 1 + (v / 100) * 0.5,\n /** 0 (grayscale)…2 */\n saturation: (v: number) => 1 + v / 100,\n /** multiply: 0.5…1.5 */\n exposure: (v: number) => 1 + (v / 100) * 0.5,\n /** −1…1, shifts R and B in opposite directions */\n temperature: (v: number) => v / 100,\n /** exponent 0.5…1.5 (applied as x^(1/γ), so positive brightens the midtones) */\n gamma: (v: number) => 1 + (v / 100) * 0.5,\n /** −1…1 local-contrast amount (negative softens) */\n clarity: (v: number) => v / 100,\n /** −1…1 (positive darkens the edges, negative lightens them) */\n vignette: (v: number) => v / 100,\n}\n\n/** The matrix-based finetune adjustments (exposure → brightness → contrast → saturation → temperature). */\nexport function finetuneMatrix(f: Record<ImageFinetuneId, number>): ColorMatrix {\n const t = finetuneParam.temperature(f.temperature)\n return composeMatrices(\n channelMatrix(\n finetuneParam.exposure(f.exposure),\n finetuneParam.exposure(f.exposure),\n finetuneParam.exposure(f.exposure),\n ),\n brightnessMatrix(finetuneParam.brightness(f.brightness)),\n contrastMatrix(finetuneParam.contrast(f.contrast)),\n saturationMatrix(finetuneParam.saturation(f.saturation)),\n channelMatrix(1 + 0.12 * t, 1 + 0.02 * t, 1 - 0.12 * t),\n )\n}\n\n/** The whole color pipeline as one matrix: the filter, then the matrix-based finetune adjustments. */\nexport function combinedMatrix(\n colorMatrix: ColorMatrix | null,\n finetune: Record<ImageFinetuneId, number>,\n): ColorMatrix {\n return composeMatrices(colorMatrix ?? IDENTITY_MATRIX, finetuneMatrix(finetune))\n}\n","// Geometry of the editor — pure math over `ImageState` (no DOM).\n//\n// Model: the source image (W×H, top-left at 0,0) is flipped (F), rotated (R(θ)) and scaled (s) about its\n// own center C = (W/2, H/2) into a \"plane\"; the crop is an axis-aligned rect in that plane:\n//\n// plane point q = C + s · R(θ) · F · (p − C) (p = a source pixel position)\n// source point p = C + F · R(−θ) · (q − C) / s\n//\n// y points down, so a positive θ turns the image clockwise on screen. The image must always cover the\n// crop: every crop corner, taken back to the image's own frame u = R(−θ)(q − C)/s, has |uₓ| ≤ W/2 and\n// |u_y| ≤ H/2. The flip doesn't change that test (the image rect is symmetric about C).\n\nimport type { ImageRect, ImageState } from './types'\nimport { ZERO_FINETUNE } from './matrix'\n\nexport interface Size {\n width: number\n height: number\n}\nexport type Vec = [number, number]\n\nconst QUARTER = Math.PI / 2\nconst EPS = 1e-6\n\n/** Rotate a vector by θ (positive = clockwise on a y-down screen). */\nexport const rotate = ([x, y]: Vec, theta: number): Vec => {\n const c = Math.cos(theta)\n const s = Math.sin(theta)\n return [x * c - y * s, x * s + y * c]\n}\n\n/** Half the size of a w×h box's bounding box once it's turned by θ. */\nexport function halfExtents(w: number, h: number, theta: number): Vec {\n const c = Math.abs(Math.cos(theta))\n const s = Math.abs(Math.sin(theta))\n return [(w / 2) * c + (h / 2) * s, (w / 2) * s + (h / 2) * c]\n}\n\n/** The crop's center. */\nexport const cropCenter = (crop: ImageRect): Vec => [\n crop.x + crop.width / 2,\n crop.y + crop.height / 2,\n]\n\n/**\n * The minimum `scale` at which an image of `size` covers a w×h crop turned by θ **when centered on the\n * image** — the \"cover\" scale every zoom is measured from (zoom = scale / coverScale).\n */\nexport function coverScale(w: number, h: number, theta: number, size: Size): number {\n const [ex, ey] = halfExtents(w, h, theta)\n return Math.max((2 * ex) / size.width, (2 * ey) / size.height)\n}\n\n/** The image point (image-centered, unrotated, unscaled) under the crop's center. */\nexport function cropAnchor(state: ImageState, size: Size): Vec {\n const [kx, ky] = cropCenter(state.crop)\n const [ux, uy] = rotate([kx - size.width / 2, ky - size.height / 2], -state.rotation)\n return [ux / state.scale, uy / state.scale]\n}\n\n/** Clamp the crop anchor so a w×h crop (turned by θ, image scaled by s) stays inside the image. */\nexport function clampAnchor(\n [ux, uy]: Vec,\n w: number,\n h: number,\n theta: number,\n s: number,\n size: Size,\n): Vec {\n const [ex, ey] = halfExtents(w, h, theta)\n const lx = Math.max(0, size.width / 2 - ex / s)\n const ly = Math.max(0, size.height / 2 - ey / s)\n return [Math.min(lx, Math.max(-lx, ux)), Math.min(ly, Math.max(-ly, uy))]\n}\n\n/** Place a w×h crop so its center sits over image point `u` (inverse of `cropAnchor`). */\nexport function cropAt(u: Vec, w: number, h: number, theta: number, s: number, size: Size) {\n const [dx, dy] = rotate([u[0] * s, u[1] * s], theta)\n const kx = size.width / 2 + dx\n const ky = size.height / 2 + dy\n return { x: kx - w / 2, y: ky - h / 2, width: w, height: h }\n}\n\n/** Whether the image fully covers `crop` (with a small tolerance). */\nexport function coversCrop(crop: ImageRect, theta: number, s: number, size: Size): boolean {\n const corners: Vec[] = [\n [crop.x, crop.y],\n [crop.x + crop.width, crop.y],\n [crop.x, crop.y + crop.height],\n [crop.x + crop.width, crop.y + crop.height],\n ]\n // a float-noise tolerance only — anything looser lets a crop overshoot the image by real pixels\n const tol = 1e-6 * Math.max(size.width, size.height)\n return corners.every(([qx, qy]) => {\n const [ux, uy] = rotate([qx - size.width / 2, qy - size.height / 2], -theta)\n return (\n Math.abs(ux / s) <= size.width / 2 + tol / s && Math.abs(uy / s) <= size.height / 2 + tol / s\n )\n })\n}\n\n/**\n * Re-fit a state so the image covers the crop: the scale is raised to at least the cover scale, then the\n * anchor (the image point under the crop's center) is clamped. The crop's size never changes here.\n */\nexport function fitState(state: ImageState, size: Size): ImageState {\n const { width: w, height: h } = state.crop\n const s = Math.max(state.scale, coverScale(w, h, state.rotation, size))\n const u = clampAnchor(cropAnchor({ ...state, scale: s }, size), w, h, state.rotation, s, size)\n return { ...state, scale: s, crop: cropAt(u, w, h, state.rotation, s, size) }\n}\n\n/** The output size in pixels — the crop at full source resolution. */\nexport function outputSize(state: ImageState): Size {\n return {\n width: Math.max(1, Math.round(state.crop.width / state.scale)),\n height: Math.max(1, Math.round(state.crop.height / state.scale)),\n }\n}\n\n/** The size `process()` renders — the Resize tool's pick, else the crop at full resolution. */\nexport function finalSize(state: ImageState): Size {\n const out = outputSize(state)\n if (!state.resize) return out\n return {\n width: Math.max(1, Math.min(out.width, Math.round(state.resize.width))),\n height: Math.max(1, Math.min(out.height, Math.round(state.resize.height))),\n }\n}\n\n/**\n * The part of the crop the output shows — the crop itself, or for a Resize pick of another aspect its\n * largest centered sub-rect of that aspect (`object-fit: cover`: the image is cut, never squashed).\n */\nexport function resizedCrop(state: ImageState): ImageRect {\n const { crop } = state\n const r = state.resize\n if (!r) return crop\n const target = r.width / r.height\n const aspect = crop.width / crop.height\n if (Math.abs(aspect - target) < 1e-9 * Math.max(aspect, target)) return crop\n if (aspect > target) {\n const width = crop.height * target\n return { ...crop, x: crop.x + (crop.width - width) / 2, width }\n }\n const height = crop.width / target\n return { ...crop, y: crop.y + (crop.height - height) / 2, height }\n}\n\n/**\n * Apply a Resize pick to `base` (the state the pick is made from). A size of the crop's own aspect just\n * scales the output; another aspect first cuts the crop to it — its largest centered part of that aspect\n * (`object-fit: cover`) — so the Crop tool shows exactly what's kept. `null` (or the crop's full size)\n * clears it. The size never goes above what `base`'s crop holds.\n */\nexport function applyResize(base: ImageState, pick: Size | null): ImageState {\n if (!pick) return { ...base, resize: null }\n const out = outputSize(base)\n const width = Math.max(1, Math.min(out.width, Math.round(pick.width)))\n const height = Math.max(1, Math.min(out.height, Math.round(pick.height)))\n // proportional when the other side, derived from this one, rounds to what was asked\n const proportional =\n Math.round((width * out.height) / out.width) === height ||\n Math.round((height * out.width) / out.height) === width\n let next: ImageState = base\n if (!proportional) {\n const crop = resizedCrop({ ...base, resize: { width, height } })\n // a picked Crop Shape no longer holds — the crop is custom now\n next = { ...base, crop, cropRatio: null }\n }\n const full = outputSize(next)\n const resize =\n width >= full.width && height >= full.height\n ? null\n : { width: Math.min(width, full.width), height: Math.min(height, full.height) }\n return { ...next, resize }\n}\n\n/**\n * Keep a Resize pick in step when the crop changes under it: it keeps its share of the crop (a 25% pick\n * stays 25% of the new crop), so the result size follows the crop. Unchanged when no resize is set or the\n * crop's output size didn't move.\n */\nexport function syncResize(prev: ImageState, next: ImageState): ImageState['resize'] {\n const r = next.resize\n if (!r) return r\n const before = outputSize(prev)\n const after = outputSize(next)\n if (before.width === after.width && before.height === after.height) return r\n const width = Math.max(\n 1,\n Math.min(after.width, Math.round((r.width * after.width) / before.width)),\n )\n const height = Math.max(\n 1,\n Math.min(after.height, Math.round((r.height * after.height) / before.height)),\n )\n return width === after.width && height === after.height ? null : { width, height }\n}\n\n/** The largest crop of the given ratio that fits the (unrotated) image, centered. */\nexport function initialCrop(size: Size, aspectRatio?: number | null): ImageRect {\n let w = size.width\n let h = size.height\n if (aspectRatio && aspectRatio > 0) {\n if (w / h > aspectRatio) w = h * aspectRatio\n else h = w / aspectRatio\n }\n return { x: (size.width - w) / 2, y: (size.height - h) / 2, width: w, height: h }\n}\n\n/** The untouched state for an image of `size`. */\nexport function defaultState(size: Size, aspectRatio?: number | null): ImageState {\n return {\n crop: initialCrop(size, aspectRatio),\n cropRatio: aspectRatio && aspectRatio > 0 ? aspectRatio : null,\n resize: null,\n rotation: 0,\n flipX: false,\n flipY: false,\n scale: 1,\n filter: null,\n colorMatrix: null,\n finetune: { ...ZERO_FINETUNE },\n redact: { effect: 'blur', amount: 0 },\n }\n}\n\n// ── rotation ────────────────────────────────────────────────────────────────────────────────────\n\n/** Split a rotation into its quarter turns (multiple of π/2, normalized to [0, 2π)) + the fine part. */\nexport function splitRotation(\n theta: number,\n quarterHint?: number,\n): { quarter: number; fine: number } {\n const turns = (((Math.round(theta / QUARTER) % 4) + 4) % 4) as 0 | 1 | 2 | 3\n const quarter = quarterHint ?? turns * QUARTER\n let fine = theta - quarter\n // wrap the fine part into (−π, π] relative to the quarter\n fine = Math.atan2(Math.sin(fine), Math.cos(fine))\n return { quarter: normalizeAngle(quarter), fine }\n}\n\n/** Normalize an angle into [0, 2π). */\nexport const normalizeAngle = (a: number) => {\n const t = a % (2 * Math.PI)\n const n = t < 0 ? t + 2 * Math.PI : t\n return Math.abs(n - 2 * Math.PI) < EPS ? 0 : n\n}\n\n/**\n * Set the rotation to `theta`, keeping the same image point under the crop's center: the image scales up\n * to cover the crop when needed (never below `base.scale`) and the anchor is clamped. `base` is the state\n * at the start of the interaction, so turning back restores the original zoom.\n */\nexport function rotateTo(base: ImageState, theta: number, size: Size): ImageState {\n const { width: w, height: h } = base.crop\n const u = cropAnchor(base, size)\n const s = Math.max(base.scale, coverScale(w, h, theta, size))\n const clamped = clampAnchor(u, w, h, theta, s, size)\n return { ...base, rotation: theta, scale: s, crop: cropAt(clamped, w, h, theta, s, size) }\n}\n\n/** Rotate the whole image −90° (counter-clockwise): the crop turns with it (its width/height swap, and so\n * does a picked crop shape — 16:9 becomes 9:16). */\nexport function rotateLeft(state: ImageState, size: Size): ImageState {\n const [kx, ky] = cropCenter(state.crop)\n const cx = size.width / 2\n const cy = size.height / 2\n const [dx, dy] = rotate([kx - cx, ky - cy], -QUARTER)\n const w = state.crop.height\n const h = state.crop.width\n return {\n ...state,\n rotation: state.rotation - QUARTER,\n crop: { x: cx + dx - w / 2, y: cy + dy - h / 2, width: w, height: h },\n cropRatio: state.cropRatio ? 1 / state.cropRatio : state.cropRatio,\n }\n}\n\n/** Mirror the result horizontally (the image flips inside the crop; the crop mirrors about the center). */\nexport function flipHorizontal(state: ImageState, size: Size): ImageState {\n return {\n ...state,\n rotation: -state.rotation,\n flipX: !state.flipX,\n crop: { ...state.crop, x: size.width - state.crop.x - state.crop.width },\n }\n}\n\n// ── scale / pan ─────────────────────────────────────────────────────────────────────────────────\n\n/** The current zoom relative to the cover scale (1 = the image just covers the crop). */\nexport function zoomOf(state: ImageState, size: Size): number {\n return state.scale / coverScale(state.crop.width, state.crop.height, state.rotation, size)\n}\n\n/** The largest zoom inside the crop (relative to the cover scale) — 500%. */\nexport const MAX_CROP_ZOOM = 5\n\n/**\n * Set the zoom (1…`MAX_CROP_ZOOM`, relative to the cover scale), keeping the image point under the\n * crop's center.\n */\nexport function zoomTo(state: ImageState, zoom: number, size: Size): ImageState {\n const { width: w, height: h } = state.crop\n const u = cropAnchor(state, size)\n const s = coverScale(w, h, state.rotation, size) * Math.min(MAX_CROP_ZOOM, Math.max(1, zoom))\n const clamped = clampAnchor(u, w, h, state.rotation, s, size)\n return { ...state, scale: s, crop: cropAt(clamped, w, h, state.rotation, s, size) }\n}\n\n/** Move the crop across the image by (dx, dy) plane units (the image moves the other way on screen). */\nexport function panBy(state: ImageState, dx: number, dy: number, size: Size): ImageState {\n const { width: w, height: h } = state.crop\n const moved = { ...state, crop: { ...state.crop, x: state.crop.x + dx, y: state.crop.y + dy } }\n const u = clampAnchor(cropAnchor(moved, size), w, h, state.rotation, state.scale, size)\n return { ...state, crop: cropAt(u, w, h, state.rotation, state.scale, size) }\n}\n\n// ── crop shape ──────────────────────────────────────────────────────────────────────────────────\n\n/**\n * Pick a crop shape: `ratio` (width / height) reshapes the crop into the largest rect of that ratio the\n * image covers at the current rotation + zoom, kept over the same image point (moved only as far as it\n * must to stay on the image); `null` frees it (the crop itself is left as is).\n */\nexport function setCropRatio(state: ImageState, ratio: number | null, size: Size): ImageState {\n if (!ratio || ratio <= 0) return { ...state, cropRatio: null }\n const c = Math.abs(Math.cos(state.rotation))\n const s = Math.abs(Math.sin(state.rotation))\n // the cover condition, solved for the height of a ratio-r crop centered on the image\n const h = Math.min(\n (size.width * state.scale) / (ratio * c + s),\n (size.height * state.scale) / (ratio * s + c),\n )\n const w = h * ratio\n const u = clampAnchor(cropAnchor(state, size), w, h, state.rotation, state.scale, size)\n return {\n ...state,\n cropRatio: ratio,\n crop: cropAt(u, w, h, state.rotation, state.scale, size),\n }\n}\n\n// ── crop resize ─────────────────────────────────────────────────────────────────────────────────\n\nexport type CropHandle = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw'\n\nexport interface ResizeOptions {\n /** Lock the crop to this width/height ratio. */\n aspectRatio?: number | null\n /** The smallest crop side, in plane units. */\n minSize: number\n}\n\n/**\n * Resize the crop by dragging `handle` by (dx, dy) plane units from the interaction's `start` state. A\n * corner moves against its opposite corner, an edge moves one side (with a locked ratio the other side\n * follows, centered). The result never leaves the image: an out-of-bounds request is pulled back along\n * the way from `start` to it (so it stops at the image's edge instead of jumping).\n */\nexport function resizeCrop(\n start: ImageState,\n handle: CropHandle,\n dx: number,\n dy: number,\n size: Size,\n { aspectRatio, minSize }: ResizeOptions,\n): ImageState {\n const c = start.crop\n let left = c.x\n let top = c.y\n let right = c.x + c.width\n let bottom = c.y + c.height\n const hasN = handle.includes('n')\n const hasS = handle.includes('s')\n const hasW = handle.includes('w')\n const hasE = handle.includes('e')\n if (hasN) top = Math.min(top + dy, bottom - minSize)\n if (hasS) bottom = Math.max(bottom + dy, top + minSize)\n if (hasW) left = Math.min(left + dx, right - minSize)\n if (hasE) right = Math.max(right + dx, left + minSize)\n\n if (aspectRatio && aspectRatio > 0) {\n let w = right - left\n let h = bottom - top\n const corner = (hasN || hasS) && (hasW || hasE)\n if (corner) {\n // follow whichever side moved more (relative to the ratio), anchored at the opposite corner\n if (w / h > aspectRatio) h = w / aspectRatio\n else w = h * aspectRatio\n if (hasW) left = right - w\n else right = left + w\n if (hasN) top = bottom - h\n else bottom = top + h\n } else if (hasN || hasS) {\n w = h * aspectRatio\n const cx = c.x + c.width / 2\n left = cx - w / 2\n right = cx + w / 2\n } else {\n h = w / aspectRatio\n const cy = c.y + c.height / 2\n top = cy - h / 2\n bottom = cy + h / 2\n }\n }\n\n const target: ImageRect = { x: left, y: top, width: right - left, height: bottom - top }\n const fits = (r: ImageRect) => coversCrop(r, start.rotation, start.scale, size)\n if (fits(target)) return { ...start, crop: target }\n const free = !(aspectRatio && aspectRatio > 0) && (hasN || hasS) && (hasW || hasE)\n if (!free) return { ...start, crop: furthest(c, target, fits) }\n // a free corner past the image edge: each axis stops at the edge on its own, so the corner keeps\n // sliding along the edge after the pointer (one shared stop would leave it short on the other axis)\n const horizontal = (from: ImageRect): ImageRect => ({ ...from, x: left, width: right - left })\n const vertical = (from: ImageRect): ImageRect => ({ ...from, y: top, height: bottom - top })\n const viaX = furthest(furthest(c, horizontal(c), fits), vertical, fits)\n const viaY = furthest(furthest(c, vertical(c), fits), horizontal, fits)\n // the order that ends closer to where the pointer asked for\n const miss = (r: ImageRect) =>\n Math.abs(r.x - target.x) +\n Math.abs(r.y - target.y) +\n Math.abs(r.width - target.width) +\n Math.abs(r.height - target.height)\n return { ...start, crop: miss(viaX) <= miss(viaY) ? viaX : viaY }\n}\n\n/**\n * The furthest rect along the straight path from `from` (valid) toward `to` (or `to(from)`) that still\n * passes `fits` — binary-searched.\n */\nfunction furthest(\n from: ImageRect,\n to: ImageRect | ((from: ImageRect) => ImageRect),\n fits: (r: ImageRect) => boolean,\n): ImageRect {\n const dest = typeof to === 'function' ? to(from) : to\n if (fits(dest)) return dest\n let lo = 0\n let hi = 1\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2\n if (fits(lerpRect(from, dest, mid))) lo = mid\n else hi = mid\n }\n return lerpRect(from, dest, lo)\n}\n\nconst lerpRect = (a: ImageRect, b: ImageRect, t: number): ImageRect => ({\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n width: a.width + (b.width - a.width) * t,\n height: a.height + (b.height - a.height) * t,\n})\n\n/** Clamp a state's crop + scale into a valid configuration (used on `setState` / `initialState`). */\nexport function normalizeState(state: ImageState, size: Size): ImageState {\n const crop = {\n ...state.crop,\n width: Math.max(1, state.crop.width),\n height: Math.max(1, state.crop.height),\n }\n return fitState({ ...state, crop, scale: Math.max(EPS, state.scale || 1) }, size)\n}\n","// The CPU side of the color pipeline — the exact math the WebGL fragment shader runs, over RGBA bytes.\n// Used for the Canvas2D fallback (no WebGL), the filter thumbnails, and the unit tests.\n\nimport type { Affine } from './affine'\nimport { type ColorMatrix } from './matrix'\n\n/** Every non-geometry parameter of one render. */\nexport interface ColorParams {\n /** The combined filter + matrix-finetune matrix. */\n matrix: ColorMatrix\n /** Gamma exponent (1 = none), applied as x^(1/γ). */\n gamma: number\n /** Local-contrast amount −1…1 (0 = none). */\n clarity: number\n /** Vignette amount −1…1 (0 = none). */\n vignette: number\n}\n\n/** How strongly a full vignette darkens / lightens the corners. */\nexport const VIGNETTE_STRENGTH = 0.85\n\nconst smoothstep = (e0: number, e1: number, x: number) => {\n const t = Math.min(1, Math.max(0, (x - e0) / (e1 - e0)))\n return t * t * (3 - 2 * t)\n}\n\n/** The vignette falloff at crop-normalized (−1…1) coords: 0 in the middle, 1 in the corners. */\nexport const vignetteFalloff = (nx: number, ny: number) =>\n smoothstep(0.3, 1, Math.hypot(nx, ny) / Math.SQRT2)\n\n/**\n * Apply the color pipeline in place: matrix → clarity (against `blur`, the same pixels blurred) → gamma\n * → vignette (positioned by `toCrop`, pixel → crop-normalized coords). Alpha is straight (non-premultiplied).\n */\nexport function applyColorOps(\n data: Uint8ClampedArray,\n width: number,\n height: number,\n p: ColorParams,\n blur?: Uint8ClampedArray | null,\n toCrop?: Affine | null,\n): void {\n const m = p.matrix\n const invGamma = 1 / p.gamma\n const useGamma = Math.abs(p.gamma - 1) > 1e-4\n const useClarity = Math.abs(p.clarity) > 1e-4 && !!blur\n const useVignette = Math.abs(p.vignette) > 1e-4 && !!toCrop\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const i = (y * width + x) * 4\n const a = data[i + 3] / 255\n if (a === 0) continue\n const r0 = data[i] / 255\n const g0 = data[i + 1] / 255\n const b0 = data[i + 2] / 255\n let r = m[0] * r0 + m[1] * g0 + m[2] * b0 + m[3] * a + m[4]\n let g = m[5] * r0 + m[6] * g0 + m[7] * b0 + m[8] * a + m[9]\n let b = m[10] * r0 + m[11] * g0 + m[12] * b0 + m[13] * a + m[14]\n if (useClarity) {\n const br = blur![i] / 255\n const bg = blur![i + 1] / 255\n const bb = blur![i + 2] / 255\n const ba = blur![i + 3] / 255\n const mr = m[0] * br + m[1] * bg + m[2] * bb + m[3] * ba + m[4]\n const mg = m[5] * br + m[6] * bg + m[7] * bb + m[8] * ba + m[9]\n const mb = m[10] * br + m[11] * bg + m[12] * bb + m[13] * ba + m[14]\n r += p.clarity * (r - mr)\n g += p.clarity * (g - mg)\n b += p.clarity * (b - mb)\n }\n if (useGamma) {\n r = Math.pow(Math.max(0, r), invGamma)\n g = Math.pow(Math.max(0, g), invGamma)\n b = Math.pow(Math.max(0, b), invGamma)\n }\n if (useVignette) {\n const px = x + 0.5\n const py = y + 0.5\n const nx = toCrop![0] * px + toCrop![1] * py + toCrop![2]\n const ny = toCrop![3] * px + toCrop![4] * py + toCrop![5]\n const f = vignetteFalloff(nx, ny) * VIGNETTE_STRENGTH * Math.abs(p.vignette)\n if (p.vignette > 0) {\n r *= 1 - f\n g *= 1 - f\n b *= 1 - f\n } else {\n r += (1 - r) * f\n g += (1 - g) * f\n b += (1 - b) * f\n }\n }\n data[i] = r * 255\n data[i + 1] = g * 255\n data[i + 2] = b * 255\n }\n }\n}\n\n/** A fast approximate Gaussian blur (three box passes, horizontal + vertical) over RGBA bytes. */\nexport function boxBlur(\n src: Uint8ClampedArray,\n width: number,\n height: number,\n radius: number,\n): Uint8ClampedArray {\n const r = Math.max(1, Math.round(radius))\n const a = new Uint8ClampedArray(src)\n const b = new Uint8ClampedArray(src.length)\n for (let pass = 0; pass < 3; pass++) {\n blurLine(a, b, width, height, r, true)\n blurLine(b, a, width, height, r, false)\n }\n return a\n function blurLine(\n from: Uint8ClampedArray,\n to: Uint8ClampedArray,\n w: number,\n h: number,\n rad: number,\n horizontal: boolean,\n ) {\n const lines = horizontal ? h : w\n const len = horizontal ? w : h\n const stride = horizontal ? 4 : w * 4\n const span = rad * 2 + 1\n for (let l = 0; l < lines; l++) {\n const base = horizontal ? l * w * 4 : l * 4\n for (let c = 0; c < 4; c++) {\n // running sum with clamped edges\n let sum = 0\n for (let k = -rad; k <= rad; k++) {\n const idx = Math.min(len - 1, Math.max(0, k))\n sum += from[base + idx * stride + c]\n }\n for (let k = 0; k < len; k++) {\n to[base + k * stride + c] = sum / span\n const out = Math.max(0, k - rad)\n const inn = Math.min(len - 1, k + rad + 1)\n sum += from[base + inn * stride + c] - from[base + out * stride + c]\n }\n }\n }\n }\n}\n","// Image loading + the derived bitmaps the renderers use (a downscaled preview, a blurred copy for clarity).\n\nimport { boxBlur } from './pixels'\n\nexport type ImageSource = ImageBitmap | HTMLImageElement | HTMLCanvasElement\n\nexport interface LoadedImage {\n /** The full-resolution, EXIF-oriented image. */\n image: ImageSource\n width: number\n height: number\n /** The input's MIME type ('' when unknown). */\n type: string\n}\n\n/** The clarity blur radius, as a fraction of the image's long side. */\nexport const CLARITY_RADIUS = 0.012\n\nconst canvasOf = (w: number, h: number) => {\n const c = document.createElement('canvas')\n c.width = Math.max(1, Math.round(w))\n c.height = Math.max(1, Math.round(h))\n return c\n}\n\nasync function decodeBlob(blob: Blob): Promise<ImageSource> {\n if (typeof createImageBitmap === 'function') {\n try {\n return await createImageBitmap(blob, { imageOrientation: 'from-image' })\n } catch {\n // fall through to <img> (some browsers can't decode e.g. SVG into a bitmap)\n }\n }\n const url = URL.createObjectURL(blob)\n try {\n return await decodeUrl(url, false)\n } finally {\n URL.revokeObjectURL(url)\n }\n}\n\nfunction decodeUrl(url: string, crossOrigin: boolean): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image()\n if (crossOrigin) img.crossOrigin = 'anonymous'\n img.decoding = 'async'\n img.onload = () => resolve(img)\n img.onerror = () => reject(new Error(`Could not load image: ${url.slice(0, 80)}`))\n img.src = url\n })\n}\n\nconst sizeOf = (img: ImageSource) =>\n img instanceof HTMLImageElement\n ? { width: img.naturalWidth, height: img.naturalHeight }\n : { width: img.width, height: img.height }\n\n/** Load a File / Blob / URL / data URL into a decoded, EXIF-oriented image. */\nexport async function loadImage(src: File | Blob | string): Promise<LoadedImage> {\n let image: ImageSource\n let type = ''\n if (typeof src === 'string') {\n try {\n const res = await fetch(src)\n if (!res.ok) throw new Error(String(res.status))\n const blob = await res.blob()\n type = blob.type\n image = await decodeBlob(blob)\n } catch {\n // a cross-origin URL without CORS can't be fetched — decode it through <img> (CORS-enabled, so the\n // canvas stays exportable when the server allows it)\n image = await decodeUrl(src, !src.startsWith('data:') && !src.startsWith('blob:'))\n const m = /^data:([^;,]+)/.exec(src) ?? /\\.(png|jpe?g|webp|gif|avif)(?:[?#]|$)/i.exec(src)\n if (m) type = m[1].includes('/') ? m[1] : `image/${m[1].toLowerCase().replace('jpg', 'jpeg')}`\n }\n } else {\n type = src.type\n image = await decodeBlob(src)\n }\n const { width, height } = sizeOf(image)\n if (!width || !height) throw new Error('The image has no size')\n return { image, width, height, type }\n}\n\n/** A copy of `source` no larger than `maxSide` on its long side (the source itself when it already fits). */\nexport function downscale(\n source: CanvasImageSource,\n width: number,\n height: number,\n maxSide: number,\n): { canvas: CanvasImageSource; width: number; height: number } {\n const k = Math.min(1, maxSide / Math.max(width, height))\n if (k >= 1) return { canvas: source, width, height }\n const c = canvasOf(width * k, height * k)\n const ctx = c.getContext('2d')\n if (ctx) {\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(source, 0, 0, c.width, c.height)\n }\n return { canvas: c, width: c.width, height: c.height }\n}\n\n/**\n * A small, blurred copy of `source` (≤ `maxSide`) for the clarity (local-contrast) pass. `radius` is the\n * blur radius in `source` pixels — it's scaled down with the copy, so the effect matches at any size.\n */\nexport function blurredCopy(\n source: CanvasImageSource,\n width: number,\n height: number,\n radius: number,\n maxSide = 384,\n): HTMLCanvasElement {\n const k = Math.min(1, maxSide / Math.max(width, height))\n const c = canvasOf(width * k, height * k)\n const ctx = c.getContext('2d', { willReadFrequently: true })\n if (!ctx) return c\n ctx.drawImage(source, 0, 0, c.width, c.height)\n try {\n const data = ctx.getImageData(0, 0, c.width, c.height)\n data.data.set(boxBlur(data.data, c.width, c.height, Math.max(1, radius * k)))\n ctx.putImageData(data, 0, 0)\n } catch {\n // a tainted (cross-origin) canvas can't be read — clarity just has no effect then\n }\n return c\n}\n\n/** The output MIME type: the requested one, else the input's (when it's a type canvases encode), else PNG. */\nexport function resolveOutputType(requested: string | undefined, input: string): string {\n if (requested) return requested\n return ['image/jpeg', 'image/png', 'image/webp'].includes(input) ? input : 'image/png'\n}\n","// 2D affine transforms as [a, b, c, d, e, f]: x' = a·x + b·y + c, y' = d·x + e·y + f.\n\nexport type Affine = [number, number, number, number, number, number]\n\nexport const IDENTITY_AFFINE: Affine = [1, 0, 0, 0, 1, 0]\n\nexport const translate = (x: number, y: number): Affine => [1, 0, x, 0, 1, y]\nexport const scaleAffine = (sx: number, sy = sx): Affine => [sx, 0, 0, 0, sy, 0]\nexport const rotateAffine = (theta: number): Affine => {\n const c = Math.cos(theta)\n const s = Math.sin(theta)\n return [c, -s, 0, s, c, 0]\n}\n\n/** `a ∘ b` — apply `b` first, then `a`. */\nexport function multiplyAffine(a: Affine, b: Affine): Affine {\n return [\n a[0] * b[0] + a[1] * b[3],\n a[0] * b[1] + a[1] * b[4],\n a[0] * b[2] + a[1] * b[5] + a[2],\n a[3] * b[0] + a[4] * b[3],\n a[3] * b[1] + a[4] * b[4],\n a[3] * b[2] + a[4] * b[5] + a[5],\n ]\n}\n\n/** Compose in application order: `chain(t1, t2, t3)` applies t1, then t2, then t3. */\nexport const chain = (...ts: Affine[]): Affine =>\n ts.reduce((acc, t) => multiplyAffine(t, acc), IDENTITY_AFFINE)\n\nexport function invertAffine([a, b, c, d, e, f]: Affine): Affine {\n const det = a * e - b * d\n const k = Math.abs(det) < 1e-12 ? 1e12 : 1 / det\n return [e * k, -b * k, (b * f - c * e) * k, -d * k, a * k, (c * d - a * f) * k]\n}\n\nexport const applyAffine = ([a, b, c, d, e, f]: Affine, x: number, y: number): [number, number] => [\n a * x + b * y + c,\n d * x + e * y + f,\n]\n","// The Redact tool's effects (blur / pixelate over the whole image) — shared by the preview and the\n// full-resolution export, so both look the same.\n//\n// The blur is laid over the source image (it has no direction, so rotating doesn't change it). The\n// pixelation is laid over the *output*: its blocks follow the crop's grid, so they stay square and upright\n// whatever the image's rotation.\nimport { boxBlur } from './pixels'\nimport type { ImageRedactEffect, ImageState } from './types'\n\n/**\n * Each effect's size at `amount` 100, as a share of the image's long side: the blur radius (1.5% — past\n * that the image is just a wash) and the pixel block (5%).\n */\nexport const REDACT_MAX: Record<ImageRedactEffect, number> = { blur: 0.015, pixelate: 0.05 }\n\n/** The blur radius / pixel block side (source px) for a state — 0 when there's no effect. */\nexport function redactRadius(\n state: Pick<ImageState, 'redact'>,\n size: { width: number; height: number },\n) {\n const effect = state.redact?.effect ?? 'blur'\n const amount = Math.max(0, Math.min(100, state.redact?.amount ?? 0))\n return (amount / 100) * (REDACT_MAX[effect] ?? 0) * Math.max(size.width, size.height)\n}\n\n/**\n * The pixelation grid over a crop: whole blocks across and down (the block stretched a hair so they fit\n * exactly — no partial block at an edge). `block` is in the crop's own (plane) units.\n */\nexport function pixelGrid(\n crop: { width: number; height: number },\n block: number,\n): { cols: number; rows: number } {\n const b = Math.max(1e-6, block)\n return {\n cols: Math.max(1, Math.round(crop.width / b)),\n rows: Math.max(1, Math.round(crop.height / b)),\n }\n}\n\n/** The blur radius in working pixels it aims for (smaller copies for bigger blurs). */\nconst BLUR_WORK_RADIUS = 4\n\nconst canvasOf = (w: number, h: number) => {\n const c = document.createElement('canvas')\n c.width = Math.max(1, Math.round(w))\n c.height = Math.max(1, Math.round(h))\n return c\n}\n\n/**\n * A small blurred copy of `source` (`width` × `height`, `radius` in its pixels): it's sized so the radius\n * is a few pixels there, at most `maxSide` long — a blur has no fine detail, so scaling it back up\n * (on the GPU, or a canvas draw) loses nothing, and the small copy is quick to make while a ruler moves.\n */\nexport function blurredSmall(\n source: CanvasImageSource,\n width: number,\n height: number,\n radius: number,\n maxSide: number,\n): HTMLCanvasElement {\n const k = Math.min(1, BLUR_WORK_RADIUS / Math.max(1, radius), maxSide / Math.max(width, height))\n const work = canvasOf(width * k, height * k)\n const ctx = work.getContext('2d', { willReadFrequently: true })\n if (!ctx) return work\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(source, 0, 0, work.width, work.height)\n try {\n const data = ctx.getImageData(0, 0, work.width, work.height)\n data.data.set(boxBlur(data.data, work.width, work.height, Math.max(1, radius * k)))\n ctx.putImageData(data, 0, 0)\n } catch {\n // a tainted (cross-origin) canvas can't be read — the down / up scale alone still softens it\n }\n return work\n}\n\n/** A `width` × `height` blurred copy of `source` (`radius` in its pixels) — the export's blur. */\nexport function blurredFull(\n source: CanvasImageSource,\n width: number,\n height: number,\n radius: number,\n): HTMLCanvasElement {\n const out = canvasOf(width, height)\n const ctx = out.getContext('2d')\n if (!ctx) return out\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(blurredSmall(source, width, height, radius, 1024), 0, 0, width, height)\n return out\n}\n\n/** Pixelate a canvas in place into `cols` × `rows` blocks (each the average of what it covers). */\nexport function pixelateCanvas(canvas: HTMLCanvasElement, cols: number, rows: number) {\n const small = canvasOf(cols, rows)\n const sctx = small.getContext('2d')\n const ctx = canvas.getContext('2d')\n if (!sctx || !ctx) return\n sctx.imageSmoothingQuality = 'high'\n sctx.drawImage(canvas, 0, 0, small.width, small.height)\n ctx.save()\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n ctx.globalCompositeOperation = 'copy'\n ctx.imageSmoothingEnabled = false\n ctx.drawImage(small, 0, 0, canvas.width, canvas.height)\n ctx.restore()\n}\n\n/**\n * A `width` × `height` copy of `source` pixelated in its own pixel grid (`block` px) — only for the\n * Canvas2D preview fallback, which can't lay the output grid over a rotated image.\n */\nexport function pixelatedCopy(\n source: CanvasImageSource,\n width: number,\n height: number,\n block: number,\n): HTMLCanvasElement {\n const out = canvasOf(width, height)\n const ctx = out.getContext('2d')\n if (!ctx) return out\n ctx.drawImage(source, 0, 0, width, height)\n pixelateCanvas(\n out,\n Math.max(1, Math.round(width / Math.max(2, block))),\n Math.max(1, Math.round(height / Math.max(2, block))),\n )\n return out\n}\n","// Scene math: how the transformed image plane is laid out on screen (the \"view\"), and the affines the\n// renderers need (device pixel → texture / crop space).\n\nimport { chain, invertAffine, rotateAffine, scaleAffine, translate, type Affine } from './affine'\nimport { cropCenter, type Size, type Vec } from './geometry'\nimport type { ImageRect, ImageState } from './types'\n\n/** How the plane sits on screen. View-only — never part of `ImageState`. */\nexport interface View {\n /** The plane point shown at the stage's center. */\n center: Vec\n /** CSS pixels per plane unit. */\n scale: number\n /** Extra rotation (radians) — only non-zero while a rotate-left animates. */\n rotation: number\n /** Horizontal mirror factor (1 = none) — only ≠ 1 while a flip animates (−1 → 1). */\n flip: number\n}\n\n/** The stage the view is drawn in (CSS pixels) + the device pixel ratio. */\nexport interface Stage {\n width: number\n height: number\n dpr: number\n /**\n * The free area the crop is laid out in (CSS px, relative to the stage) — the canvas spans the whole\n * editor, behind the toolbars, but the crop fits + centers in the space between them. Defaults to the\n * whole stage.\n */\n area?: { x: number; y: number; width: number; height: number }\n}\n\n/** The point on screen the view's center lands on (the free area's center). */\nexport const stageOrigin = (stage: Pick<Stage, 'width' | 'height' | 'area'>): [number, number] =>\n stage.area\n ? [stage.area.x + stage.area.width / 2, stage.area.y + stage.area.height / 2]\n : [stage.width / 2, stage.height / 2]\n\n/** source pixel → plane (the image state's flip / rotation / scale about the image center). */\nexport function sourceToPlane(state: ImageState, size: Size): Affine {\n const cx = size.width / 2\n const cy = size.height / 2\n return chain(\n translate(-cx, -cy),\n scaleAffine(state.flipX ? -1 : 1, state.flipY ? -1 : 1),\n rotateAffine(state.rotation),\n scaleAffine(state.scale),\n translate(cx, cy),\n )\n}\n\n/** plane → stage CSS pixels. */\nexport function planeToScreen(view: View, stage: Pick<Stage, 'width' | 'height' | 'area'>): Affine {\n // keep the mirror factor off exact zero (the mid-point of a flip animation) so it stays invertible\n const flip = Math.abs(view.flip) < 0.02 ? 0.02 * Math.sign(view.flip || 1) : view.flip\n const [ox, oy] = stageOrigin(stage)\n return chain(\n translate(-view.center[0], -view.center[1]),\n rotateAffine(view.rotation),\n scaleAffine(view.scale * flip, view.scale),\n translate(ox, oy),\n )\n}\n\n/** plane → crop-normalized coords (−1…1 across the crop). */\nexport function planeToCrop(crop: ImageRect): Affine {\n const [kx, ky] = cropCenter(crop)\n return chain(translate(-kx, -ky), scaleAffine(2 / crop.width, 2 / crop.height))\n}\n\n/** The affines a renderer needs to draw `state` in `view` on `stage`. */\nexport function sceneAffines(state: ImageState, size: Size, view: View, stage: Stage) {\n const deviceToPlane = chain(scaleAffine(1 / stage.dpr), invertAffine(planeToScreen(view, stage)))\n const toUV = chain(\n deviceToPlane,\n invertAffine(sourceToPlane(state, size)),\n scaleAffine(1 / size.width, 1 / size.height),\n )\n return { toUV, toBlurUV: toUV, toCrop: chain(deviceToPlane, planeToCrop(state.crop)) }\n}\n\n/** The view that fits the crop in the stage with `padding` CSS px around it. */\nexport function fitView(\n crop: ImageRect,\n stage: Pick<Stage, 'width' | 'height'>,\n padding: number,\n): View {\n const w = Math.max(1, stage.width - padding * 2)\n const h = Math.max(1, stage.height - padding * 2)\n return {\n center: cropCenter(crop),\n scale: Math.min(w / crop.width, h / crop.height),\n rotation: 0,\n flip: 1,\n }\n}\n","// The WebGL renderer — one full-canvas quad whose fragment shader maps every device pixel back to the source\n// texture (geometry as an affine) and runs the color pipeline (the same math as `pixels.ts`). GLSL ES 1.00,\n// so the one shader runs on WebGL2 (preferred — mipmapped non-power-of-two textures) and WebGL1.\n\nimport type { Affine } from './affine'\nimport { VIGNETTE_STRENGTH, type ColorParams } from './pixels'\n\n/** One draw's inputs. */\nexport interface RenderParams extends ColorParams {\n /** device pixel (top-left origin, y down) → image texture coords (0…1). */\n toUV: Affine\n /** device pixel → blur texture coords (0…1). */\n toBlurUV: Affine\n /** device pixel → crop-normalized coords (−1…1 across the crop) — vignette + clipping. */\n toCrop: Affine\n /** Draw nothing outside the crop (the Filter / Finetune views, export). */\n clip: boolean\n /** How much of the image shows outside the crop (the Crop view fades it into the background); 1 = all. */\n dim?: number\n /** The color the image fades into outside the crop (0…1 rgb — the theme's background). */\n dimColor?: [number, number, number]\n /**\n * Pixelate into this many blocks across × down the crop (`null` = off): every pixel samples its\n * block's center, so the blocks follow the crop's grid, not the (maybe rotated) image's.\n */\n pixel?: [number, number] | null\n /** crop-normalized coords → image texture coords (needed with `pixel`). */\n cropToUV?: Affine\n}\n\nconst VERTEX = `\nattribute vec2 a_pos;\nvoid main() { gl_Position = vec4(a_pos, 0.0, 1.0); }\n`\n\nconst FRAGMENT = `\n#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\nuniform sampler2D u_image;\nuniform sampler2D u_blur;\nuniform vec2 u_size;\nuniform vec3 u_uvX; uniform vec3 u_uvY;\nuniform vec3 u_blurX; uniform vec3 u_blurY;\nuniform vec3 u_cropX; uniform vec3 u_cropY;\nuniform bool u_clip;\nuniform float u_dim;\nuniform vec3 u_dimColor;\nuniform mat4 u_cm; uniform vec4 u_co;\nuniform float u_gamma; uniform float u_clarity; uniform float u_vignette;\nuniform vec2 u_pixel; uniform vec3 u_cuvX; uniform vec3 u_cuvY;\n\nvec3 grade(vec4 c) { return (u_cm * c + u_co).rgb; }\n\nvoid main() {\n vec3 px = vec3(gl_FragCoord.x, u_size.y - gl_FragCoord.y, 1.0);\n vec2 cn = vec2(dot(u_cropX, px), dot(u_cropY, px));\n // the pixel's own place in the crop (before a pixelation snaps cn to its block) — for the clip\n bool outsideCrop = abs(cn.x) > 1.0 || abs(cn.y) > 1.0;\n vec2 uv = vec2(dot(u_uvX, px), dot(u_uvY, px));\n vec2 buv = vec2(dot(u_blurX, px), dot(u_blurY, px));\n if (u_pixel.x > 0.0) {\n // the center of this pixel's block (whole blocks across the crop; the edge pixel stays in the last)\n vec2 cell = 2.0 / u_pixel;\n vec2 idx = floor((cn + 1.0) / cell);\n if (abs(cn.x) <= 1.0) idx.x = min(idx.x, u_pixel.x - 1.0);\n if (abs(cn.y) <= 1.0) idx.y = min(idx.y, u_pixel.y - 1.0);\n cn = (idx + 0.5) * cell - 1.0;\n vec3 q = vec3(cn, 1.0);\n uv = vec2(dot(u_cuvX, q), dot(u_cuvY, q));\n buv = uv;\n }\n // sample BEFORE any early return: a texture read in a branch only some pixels of a 2×2 quad take has no\n // defined derivatives, so at the image's edge the GPU picked a far too coarse mip level — a blurred\n // copy of the content showed through as a faint line along a transparent image's sides\n vec4 c = texture2D(u_image, uv);\n vec4 bl = texture2D(u_blur, buv);\n if ((u_clip && outsideCrop) || uv.x < 0.0 || uv.y < 0.0 || uv.x > 1.0 || uv.y > 1.0 || c.a <= 0.0) {\n gl_FragColor = vec4(0.0);\n return;\n }\n vec3 rgb = grade(c);\n if (u_clarity != 0.0) rgb += u_clarity * (rgb - grade(bl));\n if (u_gamma != 1.0) rgb = pow(max(rgb, 0.0), vec3(1.0 / u_gamma));\n if (u_vignette != 0.0) {\n float f = smoothstep(0.3, 1.0, length(cn) / 1.41421356) * ${VIGNETTE_STRENGTH.toFixed(2)} * abs(u_vignette);\n rgb = u_vignette > 0.0 ? rgb * (1.0 - f) : rgb + (1.0 - rgb) * f;\n }\n rgb = clamp(rgb, 0.0, 1.0);\n if (outsideCrop) rgb = mix(u_dimColor, rgb, u_dim);\n gl_FragColor = vec4(rgb * c.a, c.a);\n}\n`\n\ntype GL = WebGLRenderingContext | WebGL2RenderingContext\n\nexport class WebGLRenderer {\n readonly canvas: HTMLCanvasElement\n readonly gl: GL\n readonly maxTextureSize: number\n private program: WebGLProgram\n private image: WebGLTexture\n private blur: WebGLTexture\n private loc: Record<string, WebGLUniformLocation | null> = {}\n\n /** Create a renderer on `canvas`, or `null` when WebGL is unavailable. */\n static create(canvas: HTMLCanvasElement): WebGLRenderer | null {\n try {\n const opts: WebGLContextAttributes = {\n premultipliedAlpha: true,\n alpha: true,\n antialias: false,\n preserveDrawingBuffer: true,\n }\n const gl =\n (canvas.getContext('webgl2', opts) as WebGL2RenderingContext | null) ??\n (canvas.getContext('webgl', opts) as WebGLRenderingContext | null)\n if (!gl) return null\n return new WebGLRenderer(canvas, gl)\n } catch {\n return null\n }\n }\n\n private constructor(canvas: HTMLCanvasElement, gl: GL) {\n this.canvas = canvas\n this.gl = gl\n this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number\n this.program = this.link()\n gl.useProgram(this.program)\n const buffer = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW)\n const pos = gl.getAttribLocation(this.program, 'a_pos')\n gl.enableVertexAttribArray(pos)\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0)\n for (const name of [\n 'u_image',\n 'u_blur',\n 'u_size',\n 'u_uvX',\n 'u_uvY',\n 'u_blurX',\n 'u_blurY',\n 'u_cropX',\n 'u_cropY',\n 'u_clip',\n 'u_dim',\n 'u_dimColor',\n 'u_cm',\n 'u_co',\n 'u_gamma',\n 'u_clarity',\n 'u_vignette',\n 'u_pixel',\n 'u_cuvX',\n 'u_cuvY',\n ])\n this.loc[name] = gl.getUniformLocation(this.program, name)\n this.image = this.texture()\n this.blur = this.texture()\n gl.uniform1i(this.loc.u_image, 0)\n gl.uniform1i(this.loc.u_blur, 1)\n }\n\n private link(): WebGLProgram {\n const gl = this.gl\n const compile = (type: number, src: string) => {\n const sh = gl.createShader(type)!\n gl.shaderSource(sh, src)\n gl.compileShader(sh)\n if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS))\n throw new Error(gl.getShaderInfoLog(sh) ?? 'shader compile failed')\n return sh\n }\n const program = gl.createProgram()!\n gl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX))\n gl.attachShader(program, compile(gl.FRAGMENT_SHADER, FRAGMENT))\n gl.linkProgram(program)\n if (!gl.getProgramParameter(program, gl.LINK_STATUS))\n throw new Error(gl.getProgramInfoLog(program) ?? 'program link failed')\n return program\n }\n\n private texture(): WebGLTexture {\n const gl = this.gl\n const tex = gl.createTexture()!\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)\n return tex\n }\n\n private upload(unit: number, tex: WebGLTexture, source: TexImageSource, mipmap: boolean) {\n const gl = this.gl\n gl.activeTexture(gl.TEXTURE0 + unit)\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source)\n // mipmaps keep a big image crisp (not shimmering) when shown small — WebGL2 handles any size\n const isGL2 =\n typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext\n if (mipmap && isGL2) {\n gl.generateMipmap(gl.TEXTURE_2D)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)\n } else {\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n }\n }\n\n /** Upload the image (and its blurred copy for clarity). */\n setImage(image: TexImageSource, blur: TexImageSource, mipmap = true) {\n this.upload(0, this.image, image, mipmap)\n this.upload(1, this.blur, blur, false)\n }\n\n /**\n * Swap just the image texture (e.g. for a coarser copy) — the blurred copy stays. `mipmap: false` for\n * a pixelation's texture: its blocks sample one point each, and mip levels would seam their borders.\n */\n setSource(image: TexImageSource, mipmap = true) {\n this.upload(0, this.image, image, mipmap)\n }\n\n /** Draw one frame at the canvas's current pixel size. */\n render(p: RenderParams) {\n const gl = this.gl\n const { width, height } = this.canvas\n gl.viewport(0, 0, width, height)\n gl.clearColor(0, 0, 0, 0)\n gl.clear(gl.COLOR_BUFFER_BIT)\n gl.uniform2f(this.loc.u_size, width, height)\n const rows = (a: Affine, x: string, y: string) => {\n gl.uniform3f(this.loc[x], a[0], a[1], a[2])\n gl.uniform3f(this.loc[y], a[3], a[4], a[5])\n }\n rows(p.toUV, 'u_uvX', 'u_uvY')\n rows(p.toBlurUV, 'u_blurX', 'u_blurY')\n rows(p.toCrop, 'u_cropX', 'u_cropY')\n gl.uniform1i(this.loc.u_clip, p.clip ? 1 : 0)\n gl.uniform1f(this.loc.u_dim, p.dim ?? 1)\n const [dr, dg, db] = p.dimColor ?? [0, 0, 0]\n gl.uniform3f(this.loc.u_dimColor, dr, dg, db)\n const m = p.matrix\n // GLSL mat4 is column-major: column j holds the coefficient of input channel j for each output row\n const cm = new Float32Array(16)\n for (let row = 0; row < 4; row++)\n for (let col = 0; col < 4; col++) cm[col * 4 + row] = m[row * 5 + col]\n gl.uniformMatrix4fv(this.loc.u_cm, false, cm)\n gl.uniform4f(this.loc.u_co, m[4], m[9], m[14], m[19])\n gl.uniform1f(this.loc.u_gamma, p.gamma)\n gl.uniform1f(this.loc.u_clarity, p.clarity)\n gl.uniform1f(this.loc.u_vignette, p.vignette)\n const [cols, rowCount] = p.pixel ?? [0, 0]\n gl.uniform2f(this.loc.u_pixel, cols, rowCount)\n if (p.pixel && p.cropToUV) rows(p.cropToUV, 'u_cuvX', 'u_cuvY')\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n }\n\n /**\n * Release the GPU resources. `loseContext` also drops the context itself (a throwaway export canvas —\n * browsers cap live contexts); a canvas that will be drawn on again keeps it.\n */\n dispose(loseContext = true) {\n const gl = this.gl\n gl.deleteTexture(this.image)\n gl.deleteTexture(this.blur)\n gl.deleteProgram(this.program)\n if (loseContext) gl.getExtension('WEBGL_lose_context')?.loseContext()\n }\n}\n","// Rendering glue shared by the preview, the thumbnails and `process()`: the color parameters of a state,\n// the Canvas2D fallback renderer, and the full-resolution export.\n\nimport { applyAffine, chain, invertAffine, scaleAffine, translate, type Affine } from './affine'\nimport { finalSize, resizedCrop, type Size } from './geometry'\nimport { blurredFull, pixelateCanvas, pixelGrid, redactRadius } from './redact'\nimport { combinedMatrix, finetuneParam, isIdentityMatrix } from './matrix'\nimport { applyColorOps, type ColorParams } from './pixels'\nimport { blurredCopy, CLARITY_RADIUS } from './load'\nimport { sourceToPlane } from './scene'\nimport type { ImageState } from './types'\nimport { WebGLRenderer, type RenderParams } from './webgl'\n\n/** The color parameters for a state (optionally with another filter matrix — the filter thumbnails). */\nexport function colorParams(\n state: ImageState,\n colorMatrix: number[] | null = state.colorMatrix,\n): ColorParams {\n const f = state.finetune\n return {\n matrix: combinedMatrix(colorMatrix, f),\n gamma: finetuneParam.gamma(f.gamma),\n clarity: finetuneParam.clarity(f.clarity),\n vignette: finetuneParam.vignette(f.vignette),\n }\n}\n\n/** Whether a render needs the color pass at all. */\nexport const hasColorOps = (p: ColorParams) =>\n !isIdentityMatrix(p.matrix) || p.gamma !== 1 || p.clarity !== 0 || p.vignette !== 0\n\nconst canvas2d = (w: number, h: number) => {\n const c = document.createElement('canvas')\n c.width = Math.max(1, Math.round(w))\n c.height = Math.max(1, Math.round(h))\n return c\n}\n\n/**\n * The Canvas2D renderer (no WebGL): draws the texture through the inverse of `toUV`, clips to the crop,\n * then runs the color pipeline on the pixels (with the blur copy drawn through `toBlurUV`).\n */\nexport function render2D(\n canvas: HTMLCanvasElement,\n texture: CanvasImageSource,\n textureSize: Size,\n blur: CanvasImageSource,\n blurSize: Size,\n p: RenderParams,\n) {\n const ctx = canvas.getContext('2d', { willReadFrequently: true })\n if (!ctx) return\n const { width, height } = canvas\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n ctx.clearRect(0, 0, width, height)\n const drawThrough = (\n target: CanvasRenderingContext2D,\n img: CanvasImageSource,\n size: Size,\n toUV: Affine,\n ) => {\n // texture pixel → uv → device\n const m = chain(scaleAffine(1 / size.width, 1 / size.height), invertAffine(toUV))\n target.save()\n if (p.clip) {\n const fromCrop = invertAffine(p.toCrop)\n target.beginPath()\n ;[\n [-1, -1],\n [1, -1],\n [1, 1],\n [-1, 1],\n ].forEach(([x, y], i) => {\n const [dx, dy] = applyAffine(fromCrop, x, y)\n if (i === 0) target.moveTo(dx, dy)\n else target.lineTo(dx, dy)\n })\n target.closePath()\n target.clip()\n }\n target.setTransform(m[0], m[3], m[1], m[4], m[2], m[5])\n target.imageSmoothingQuality = 'high'\n target.drawImage(img, 0, 0, size.width, size.height)\n target.restore()\n }\n drawThrough(ctx, texture, textureSize, p.toUV)\n if (hasColorOps(p)) colorPass2D()\n if (p.dim != null && p.dim < 1) {\n // fade the image around the crop into the background color (only where it's painted — `source-atop`)\n const fromCrop = invertAffine(p.toCrop)\n ctx.save()\n ctx.globalCompositeOperation = 'source-atop'\n ctx.beginPath()\n ctx.rect(0, 0, width, height)\n ;[\n [-1, -1],\n [1, -1],\n [1, 1],\n [-1, 1],\n ].forEach(([x, y], i) => {\n const [dx, dy] = applyAffine(fromCrop, x, y)\n if (i === 0) ctx.moveTo(dx, dy)\n else ctx.lineTo(dx, dy)\n })\n ctx.closePath()\n const [dr, dg, db] = (p.dimColor ?? [0, 0, 0]).map((v) => Math.round(v * 255))\n ctx.fillStyle = `rgba(${dr}, ${dg}, ${db}, ${1 - p.dim})`\n ctx.fill('evenodd')\n ctx.restore()\n }\n\n function colorPass2D() {\n if (!ctx) return\n try {\n const data = ctx.getImageData(0, 0, width, height)\n let blurData: Uint8ClampedArray | null = null\n if (p.clarity !== 0) {\n const b = canvas2d(width, height)\n const bctx = b.getContext('2d', { willReadFrequently: true })\n if (bctx) {\n drawThrough(bctx, blur, blurSize, p.toBlurUV)\n blurData = bctx.getImageData(0, 0, width, height).data\n }\n }\n applyColorOps(data.data, width, height, p, blurData, p.toCrop)\n ctx.putImageData(data, 0, 0)\n } catch {\n // a tainted canvas can't be read back — show the geometry only\n }\n }\n}\n\n/** The largest canvas we'll ask a browser for (per side / in total). */\nconst MAX_SIDE = 16384\nconst MAX_AREA = 16384 * 16384\n\n/** A canvas's `toBlob` as a promise (rejects when the canvas is tainted or the encode fails). */\nconst toBlob = (canvas: HTMLCanvasElement, type: string, quality: number) =>\n new Promise<Blob>((resolve, reject) => {\n try {\n canvas.toBlob(\n (blob) => (blob ? resolve(blob) : reject(new Error('Encoding failed'))),\n type,\n quality,\n )\n } catch (e) {\n reject(e)\n }\n })\n\n/**\n * Render `state` at full source resolution and encode it. Geometry goes through Canvas2D (it handles any\n * image size natively); the color pass runs on WebGL in tiles no larger than `MAX_TEXTURE_SIZE` (or on the\n * CPU without WebGL).\n */\nexport async function renderOutput(\n image: CanvasImageSource,\n size: Size,\n state: ImageState,\n type: string,\n quality: number,\n): Promise<Blob> {\n const out = finalSize(state)\n // a Resize pick of another aspect cuts the crop to it (cover), never squashes it\n const crop = resizedCrop(state)\n // stay inside what browsers will allocate (very large crops are scaled down, never failed)\n const k = Math.min(\n 1,\n MAX_SIDE / Math.max(out.width, out.height),\n Math.sqrt(MAX_AREA / (out.width * out.height)),\n )\n const ow = Math.max(1, Math.round(out.width * k))\n const oh = Math.max(1, Math.round(out.height * k))\n const canvas = canvas2d(ow, oh)\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('Canvas 2D is unavailable')\n // source px → plane → output px\n const m = chain(\n sourceToPlane(state, size),\n translate(-crop.x, -crop.y),\n scaleAffine(ow / crop.width, oh / crop.height),\n )\n if (type === 'image/jpeg') {\n // JPEG has no alpha — fill what transparency would become black with white instead\n ctx.fillStyle = '#fff'\n ctx.fillRect(0, 0, ow, oh)\n }\n ctx.setTransform(m[0], m[3], m[1], m[4], m[2], m[5])\n ctx.imageSmoothingEnabled = true\n ctx.imageSmoothingQuality = 'high'\n // Redact: a blur goes over the source (it has no direction); a pixelation over the output, below\n const radius = redactRadius(state, size)\n const effect = state.redact?.effect\n const source =\n radius > 0 && effect === 'blur' ? blurredFull(image, size.width, size.height, radius) : image\n ctx.drawImage(source, 0, 0, size.width, size.height)\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n\n const params = colorParams(state)\n if (hasColorOps(params)) {\n // the clarity blur radius is defined in source pixels → scale it to output pixels\n const radius =\n CLARITY_RADIUS * Math.max(size.width, size.height) * (ow / crop.width) * state.scale\n const blur = blurredCopy(canvas, ow, oh, radius)\n colorPassTiled(canvas, blur, params)\n }\n // the pixel blocks follow the output's grid — square and upright, whatever the rotation\n if (radius > 0 && effect === 'pixelate') {\n const { cols, rows } = pixelGrid(crop, radius * state.scale)\n pixelateCanvas(canvas, cols, rows)\n }\n return toBlob(canvas, type, quality)\n}\n\n/** Run the color pipeline over `canvas` in place, tile by tile (WebGL, or the CPU without it). */\nfunction colorPassTiled(canvas: HTMLCanvasElement, blur: HTMLCanvasElement, params: ColorParams) {\n const { width: ow, height: oh } = canvas\n const ctx = canvas.getContext('2d', { willReadFrequently: true })!\n const glCanvas = document.createElement('canvas')\n const gl = WebGLRenderer.create(glCanvas)\n const tileSize = gl ? Math.min(2048, gl.maxTextureSize) : 1024\n const tile = canvas2d(tileSize, tileSize)\n const tctx = tile.getContext('2d', { willReadFrequently: true })!\n try {\n for (let ty = 0; ty < oh; ty += tileSize) {\n for (let tx = 0; tx < ow; tx += tileSize) {\n const tw = Math.min(tileSize, ow - tx)\n const th = Math.min(tileSize, oh - ty)\n const toCrop = chain(translate(tx, ty), scaleAffine(2 / ow, 2 / oh), translate(-1, -1))\n const toBlurUV = chain(translate(tx, ty), scaleAffine(1 / ow, 1 / oh))\n if (gl) {\n tile.width = tw\n tile.height = th\n tctx.clearRect(0, 0, tw, th)\n tctx.drawImage(canvas, tx, ty, tw, th, 0, 0, tw, th)\n glCanvas.width = tw\n glCanvas.height = th\n gl.setImage(tile, blur, false)\n gl.render({ ...params, toUV: scaleAffine(1 / tw, 1 / th), toBlurUV, toCrop, clip: false })\n ctx.clearRect(tx, ty, tw, th)\n ctx.drawImage(glCanvas, tx, ty)\n } else {\n const data = ctx.getImageData(tx, ty, tw, th)\n let blurData: Uint8ClampedArray | null = null\n if (params.clarity !== 0) {\n tile.width = tw\n tile.height = th\n tctx.drawImage(\n blur,\n (tx / ow) * blur.width,\n (ty / oh) * blur.height,\n (tw / ow) * blur.width,\n (th / oh) * blur.height,\n 0,\n 0,\n tw,\n th,\n )\n blurData = tctx.getImageData(0, 0, tw, th).data\n }\n applyColorOps(data.data, tw, th, params, blurData, toCrop)\n ctx.putImageData(data, tx, ty)\n }\n }\n }\n } finally {\n gl?.dispose()\n }\n}\n","// The framework-agnostic editor core: one store holding the `ImageState` + the UI state, an undo / redo\n// history of committed states, events, image loading and `process()`. The React `ImageEditor` is a view\n// over it; it can also be used headless (open → setState → process).\n\nimport { defaultState, normalizeState, syncResize, type Size } from './geometry'\nimport { FILTER_MATRICES, ZERO_FINETUNE } from './matrix'\nimport { loadImage, resolveOutputType, type LoadedImage } from './load'\nimport { renderOutput } from './render'\nimport type { ImageEditorOptions, ImageEditorResult, ImageEditorUiState, ImageState } from './types'\n\nexport type ImageEditorEvent = 'load' | 'update' | 'process' | 'close' | 'undo' | 'redo' | 'revert'\n\n/** The store snapshot (a new object on every change — safe for `useSyncExternalStore`). */\nexport interface ImageEditorSnapshot {\n status: 'idle' | 'loading' | 'ready' | 'error'\n error: unknown\n state: ImageState | null\n ui: ImageEditorUiState\n size: Size | null\n canUndo: boolean\n canRedo: boolean\n canRevert: boolean\n}\n\n/** The headless editor API. */\nexport interface Editor {\n open(options: ImageEditorOptions): Promise<void>\n close(): void\n getState(): ImageState\n setState(s: Partial<ImageState>): void\n undo(): void\n redo(): void\n revert(): void\n on(event: ImageEditorEvent, cb: (payload?: unknown) => void): () => void\n process(): Promise<ImageEditorResult>\n}\n\nconst MAX_HISTORY = 50\nconst same = (a: ImageState, b: ImageState) => JSON.stringify(a) === JSON.stringify(b)\nconst sameSize = (a: ImageState['resize'], b: ImageState['resize']) =>\n a === b || (!!a && !!b && a.width === b.width && a.height === b.height)\nconst clone = (s: ImageState): ImageState => JSON.parse(JSON.stringify(s)) as ImageState\n\nexport class ImageEditorCore implements Editor {\n private snapshot: ImageEditorSnapshot = {\n status: 'idle',\n error: null,\n state: null,\n ui: { util: 'crop', cropTab: 'rotation', finetuneTab: 'brightness', resizeLocked: true },\n size: null,\n canUndo: false,\n canRedo: false,\n canRevert: false,\n }\n private storeListeners = new Set<() => void>()\n private events = new Map<ImageEditorEvent, Set<(payload?: unknown) => void>>()\n private history: ImageState[] = []\n private index = -1\n /** The untouched state of the loaded image (what `revert()` goes back to). */\n private initial: ImageState | null = null\n private loaded: LoadedImage | null = null\n private options: ImageEditorOptions | null = null\n private openToken = 0\n\n // ── store (for UI bindings) ──────────────────────────────────────────────────────────────────\n\n subscribe = (fn: () => void) => {\n this.storeListeners.add(fn)\n return () => {\n this.storeListeners.delete(fn)\n }\n }\n getSnapshot = () => this.snapshot\n\n private patch(next: Partial<ImageEditorSnapshot>) {\n const state = next.state !== undefined ? next.state : this.snapshot.state\n this.snapshot = {\n ...this.snapshot,\n ...next,\n canUndo: this.index > 0,\n canRedo: this.index < this.history.length - 1,\n canRevert: !!state && !!this.initial && !same(state, this.initial),\n }\n this.storeListeners.forEach((fn) => fn())\n }\n\n on(event: ImageEditorEvent, cb: (payload?: unknown) => void) {\n let set = this.events.get(event)\n if (!set) this.events.set(event, (set = new Set()))\n set.add(cb)\n return () => {\n set!.delete(cb)\n }\n }\n private emit(event: ImageEditorEvent, payload?: unknown) {\n this.events.get(event)?.forEach((cb) => cb(payload))\n }\n\n // ── lifecycle ────────────────────────────────────────────────────────────────────────────────\n\n /** The loaded image (full resolution) — for renderers. */\n get image() {\n return this.loaded\n }\n /** The `open()` options. */\n get openOptions() {\n return this.options\n }\n\n async open(options: ImageEditorOptions): Promise<void> {\n const token = ++this.openToken\n this.options = options\n this.history = []\n this.index = -1\n this.initial = null\n this.loaded = null\n this.patch({\n status: 'loading',\n error: null,\n state: null,\n size: null,\n ui: { ...this.snapshot.ui, util: options.util ?? 'crop' },\n })\n try {\n const loaded = await loadImage(options.src)\n if (token !== this.openToken) return\n this.loaded = loaded\n const size = { width: loaded.width, height: loaded.height }\n const base = defaultState(size, options.cropAspectRatio)\n const init = options.initialState ?? {}\n const merged: ImageState = {\n ...base,\n ...init,\n crop: { ...base.crop, ...init.crop },\n finetune: { ...ZERO_FINETUNE, ...init.finetune },\n redact: { ...base.redact, ...init.redact },\n }\n // a known filter id restores its matrix when the state carries none\n if (merged.filter && merged.filter !== 'default' && !merged.colorMatrix)\n merged.colorMatrix = FILTER_MATRICES[merged.filter] ?? null\n const state = normalizeState(merged, size)\n // revert always means \"the original image\", even when re-opened with previous edits\n this.initial = normalizeState(base, size)\n this.history = [clone(state)]\n this.index = 0\n this.patch({ status: 'ready', state, size })\n this.emit('load', { size })\n } catch (error) {\n if (token !== this.openToken) return\n this.patch({ status: 'error', error })\n throw error\n }\n }\n\n close() {\n this.openToken++\n const img = this.loaded?.image\n if (img && 'close' in img && typeof img.close === 'function') img.close()\n this.loaded = null\n this.emit('close')\n }\n\n // ── state ────────────────────────────────────────────────────────────────────────────────────\n\n getState(): ImageState {\n if (!this.snapshot.state) throw new Error('No image is open')\n return clone(this.snapshot.state)\n }\n\n /** Replace part of the state and commit it (one undo step). */\n setState(s: Partial<ImageState>) {\n this.preview(s)\n this.commit()\n }\n\n /** Apply a live (uncommitted) change — e.g. while dragging. Call `commit()` when the interaction ends. */\n preview(s: Partial<ImageState>) {\n const cur = this.snapshot.state\n const size = this.snapshot.size\n if (!cur || !size) return\n const next = { ...cur, ...s }\n // a geometry change keeps a Resize pick in step with the new crop — scaled from the last committed\n // state, so a drag's many frames can't drift it by rounding — unless it sets a new resize itself\n // (geometry helpers hand back the whole state, the resize they started from included)\n const anchor = this.index >= 0 ? this.history[this.index] : cur\n const explicit = 'resize' in s && !sameSize(s.resize ?? null, anchor.resize)\n if (!explicit) next.resize = syncResize(anchor, { ...next, resize: anchor.resize })\n this.patch({ state: next })\n }\n\n /** Push the current state onto the history (if it changed) and emit `update`. */\n commit() {\n const state = this.snapshot.state\n if (!state) return\n if (this.index >= 0 && same(state, this.history[this.index])) return\n // a new change after an undo drops the redo branch\n this.history = this.history.slice(0, this.index + 1)\n this.history.push(clone(state))\n if (this.history.length > MAX_HISTORY) this.history.shift()\n this.index = this.history.length - 1\n this.patch({})\n this.emit('update', clone(state))\n }\n\n undo() {\n if (this.index <= 0) return\n this.index--\n this.patch({ state: clone(this.history[this.index]) })\n this.emit('undo', this.getState())\n this.emit('update', this.getState())\n }\n\n redo() {\n if (this.index >= this.history.length - 1) return\n this.index++\n this.patch({ state: clone(this.history[this.index]) })\n this.emit('redo', this.getState())\n this.emit('update', this.getState())\n }\n\n /**\n * Back to the original image — every edit dropped, including the ones an `initialState` re-opened with.\n * It's one history step, so Undo brings the edits back.\n */\n revert() {\n const state = this.snapshot.state\n if (!this.initial || !state || same(state, this.initial)) return\n this.patch({ state: clone(this.initial) })\n this.commit()\n this.emit('revert', this.getState())\n }\n\n setUi(ui: Partial<ImageEditorUiState>) {\n // leaving a tool ends its live edit (e.g. a size typed but not yet committed) — keep it\n if (ui.util && ui.util !== this.snapshot.ui.util) this.commit()\n this.patch({ ui: { ...this.snapshot.ui, ...ui } })\n }\n\n /** Render the current state at full resolution. */\n async process(): Promise<ImageEditorResult> {\n const loaded = this.loaded\n const state = this.snapshot.state\n if (!loaded || !state) throw new Error('No image is open')\n const type = resolveOutputType(this.options?.outputType, loaded.type)\n const dest = await renderOutput(\n loaded.image,\n { width: loaded.width, height: loaded.height },\n state,\n type,\n this.options?.outputQuality ?? 0.92,\n )\n const result = { dest, imageState: clone(state) }\n this.emit('process', result)\n return result\n }\n}\n\n/** Create a headless editor. */\nexport const createImageEditor = () => new ImageEditorCore()\n","// A tiny spring animator for the view (rotate / flip / crop fit). Animates a vector of numbers.\n\nexport interface SpringOptions {\n stiffness?: number\n damping?: number\n}\n\n/** Whether the user asked for reduced motion (then every spring jumps straight to its target). */\nexport const prefersReducedMotion = () =>\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\n/** A running spring: call it to cancel; `retarget` moves its target without losing the current motion. */\nexport interface SpringHandle {\n (): void\n retarget: (to: number[]) => void\n}\n\n/**\n * Spring `from` → `to`, calling `onFrame` with the current values every animation frame (and once with\n * `to` at the end). Returns a handle: call it to cancel, or `retarget(to)` to aim it elsewhere mid-flight\n * (position + velocity carry over, so there's no jolt). Jumps straight to `to` under reduced motion.\n */\nexport function springTo(\n from: number[],\n target: number[],\n onFrame: (values: number[]) => void,\n { stiffness = 240, damping = 30 }: SpringOptions = {},\n onDone?: () => void,\n): SpringHandle {\n if (prefersReducedMotion() || typeof requestAnimationFrame !== 'function') {\n onFrame(target)\n onDone?.()\n const noop = (() => {}) as SpringHandle\n noop.retarget = (next) => onFrame(next)\n return noop\n }\n const to = [...target]\n const x = [...from]\n const v = from.map(() => 0)\n const tol = from.map((f, i) => Math.max(1e-5, Math.abs(to[i] - f) * 1e-3))\n let last = performance.now()\n let raf = 0\n let cancelled = false\n const step = (now: number) => {\n if (cancelled) return\n // sub-step so a long frame can't blow the integration up\n let dt = Math.min(0.064, (now - last) / 1000)\n last = now\n while (dt > 0) {\n const h = Math.min(dt, 1 / 120)\n for (let i = 0; i < x.length; i++) {\n const a = -stiffness * (x[i] - to[i]) - damping * v[i]\n v[i] += a * h\n x[i] += v[i] * h\n }\n dt -= h\n }\n const settled = x.every(\n (xi, i) => Math.abs(xi - to[i]) < tol[i] && Math.abs(v[i]) < tol[i] * 10,\n )\n if (settled) {\n onFrame(to)\n onDone?.()\n return\n }\n onFrame([...x])\n raf = requestAnimationFrame(step)\n }\n raf = requestAnimationFrame(step)\n const handle = (() => {\n cancelled = true\n cancelAnimationFrame(raf)\n }) as SpringHandle\n handle.retarget = (next) => {\n for (let i = 0; i < to.length; i++) {\n to[i] = next[i]\n tol[i] = Math.max(tol[i], 1e-5)\n }\n }\n return handle\n}\n","import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type PointerEvent,\n type RefObject,\n type WheelEvent,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { applyAffine, chain, invertAffine } from './core/affine'\nimport type { ImageEditorCore, ImageEditorSnapshot } from './core/editor'\nimport {\n MAX_CROP_ZOOM,\n panBy,\n resizeCrop,\n zoomOf,\n resizedCrop,\n finalSize,\n zoomTo,\n type CropHandle,\n type Vec,\n} from './core/geometry'\nimport { blurredCopy, CLARITY_RADIUS, downscale } from './core/load'\nimport { blurredSmall, pixelatedCopy, pixelGrid, redactRadius } from './core/redact'\nimport { colorParams, render2D } from './core/render'\nimport {\n fitView,\n planeToScreen,\n sceneAffines,\n stageOrigin,\n type Stage,\n type View,\n} from './core/scene'\nimport { springTo, type SpringHandle } from './core/spring'\nimport type { ImageState } from './core/types'\nimport { WebGLRenderer } from './core/webgl'\nimport { useColorMode } from '../../theme'\nimport styles from './ImageEditor.module.css'\n\n/** Breathing room around the crop (CSS px) in the Crop view / the Filter + Finetune views. */\nconst PAD_CROP = 24\nconst PAD_VIEW = 12\n/** The largest preview texture side (the full image is only used by `process()`). */\nconst PREVIEW_MAX = 4096\n/** The Crop view enlarges a tiny crop (past its real size) until its long side is this many CSS px. */\nconst CROP_VIEW_MIN_SIDE = 320\n/** The Redact blur's preview texture (long side, at most) — a blur has no finer detail to show. */\nconst BLUR_PREVIEW_MAX = 768\n\n/** The texture the preview draws from, and how. */\ntype PreviewSource = {\n canvas: CanvasImageSource\n width: number\n height: number\n /** Upload with mipmaps (off for a pixelation — its block samples would seam at mip borders). */\n mipmap: boolean\n /** Sample it per pixel block (the shader's crop-grid pixelation). */\n pixelate: boolean\n}\n/** How much of the image shows outside the crop in the Crop view (the rest fades into the background). */\nconst CROP_DIM = 0.35\n\n/** The theme's background as 0…1 rgb (read off the `--tz-color-background-rgb` triplet). */\nfunction backgroundRgb(el: Element | null): [number, number, number] {\n const raw = el ? getComputedStyle(el).getPropertyValue('--tz-color-background-rgb') : ''\n const [r, g, b] = raw.split(',').map((v) => Number(v.trim()) / 255)\n return [r, g, b].every((v) => Number.isFinite(v)) ? [r, g, b] : [0, 0, 0]\n}\n/** The smallest crop side on screen while resizing (CSS px). */\nconst MIN_CROP_SCREEN = 40\n\nexport interface EditorStageHandle {\n /** Call right before a rotate-left / flip / other jump changes the state, so the view animates it. */\n transition(kind: 'rotate' | 'flip' | 'jump'): void\n}\n\nexport interface EditorStageProps {\n core: ImageEditorCore\n snapshot: ImageEditorSnapshot\n /** Lock crop resizing to this ratio. */\n cropAspectRatio?: number | null\n /** Filter / Finetune view zoom (CSS px per source px), `null` = fit. */\n viewZoom: number | null\n onViewZoom: (zoom: number | null) => void\n /** Reports the effective view zoom (CSS px per source px) for the header label. */\n onZoomReport: (zoom: number) => void\n /**\n * The free area between the toolbars: the canvas fills the whole editor (the image runs behind the\n * header / nav / footer), but the crop fits + centers in this element's box.\n */\n areaRef?: RefObject<HTMLElement | null>\n}\n\ntype Gesture =\n | { kind: 'pan'; id: number; x: number; y: number; base: ImageState }\n | { kind: 'resize'; id: number; x: number; y: number; base: ImageState; handle: CropHandle }\n | { kind: 'viewPan'; id: number; x: number; y: number; pan: Vec }\n | { kind: 'pinch'; dist: number; base: ImageState; zoom: number; viewZoom: number }\n\nconst HANDLES: CropHandle[] = ['nw', 'ne', 'sw', 'se', 'n', 's', 'w', 'e']\n\nconst viewToVector = (v: View) => [v.center[0], v.center[1], Math.log(v.scale), v.rotation, v.flip]\nconst vectorToView = (x: number[]): View => ({\n center: [x[0], x[1]],\n scale: Math.exp(x[2]),\n rotation: x[3],\n flip: x[4],\n})\n\n/** The editor's canvas + crop overlay: renders the image, owns the view and the pointer gestures. */\nexport const EditorStage = forwardRef<EditorStageHandle, EditorStageProps>(function EditorStage(\n { core, snapshot, cropAspectRatio, viewZoom, onViewZoom, onZoomReport, areaRef },\n ref,\n) {\n const { state, size, ui } = snapshot\n const mode = useColorMode()\n const util = ui.util\n const viewportRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [stage, setStage] = useState<Stage | null>(null)\n const [view, setView] = useState<View | null>(null)\n const viewRef = useRef<View | null>(null)\n viewRef.current = view\n const [pan, setPan] = useState<Vec>([0, 0])\n const [interacting, setInteracting] = useState(false)\n // bumped to re-run the view effect when a gesture ends without a state change (e.g. a handle click)\n const [nonce, setNonce] = useState(0)\n const frozen = useRef(false) // the view holds still while the crop is being resized\n const pending = useRef<'rotate' | 'flip' | 'jump' | null>(null)\n const stopSpring = useRef<SpringHandle | null>(null)\n const gesture = useRef<Gesture | null>(null)\n const pointers = useRef(new Map<number, { x: number; y: number }>())\n const wheelCommit = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\n // ── the stage size ───────────────────────────────────────────────────────────────────────────\n // a passive effect, not a layout one: the area element is a later sibling of this stage, so its ref is\n // only attached once the whole editor has committed (a layout effect here would see it still null)\n useEffect(() => {\n const el = viewportRef.current\n if (!el) return\n const measure = () => {\n const r = el.getBoundingClientRect()\n const a = areaRef?.current?.getBoundingClientRect()\n setStage({\n width: r.width,\n height: r.height,\n dpr: window.devicePixelRatio || 1,\n // horizontally the area is mirrored to the wider side, so the crop sits in the middle of the\n // screen (not of the space right of the tool menu); vertically it's the space between the bars\n area: a ? symmetricArea(r, a) : undefined,\n })\n }\n measure()\n measureRef.current = measure\n if (typeof ResizeObserver === 'undefined') return\n const ro = new ResizeObserver(measure)\n ro.observe(el)\n if (areaRef?.current) ro.observe(areaRef.current)\n return () => ro.disconnect()\n }, [areaRef])\n\n // the toolbar / footer change with the tool and once the image is in — re-measure right away rather\n // than waiting on the ResizeObserver (whose callback can lag a frame, or more in a background tab)\n const measureRef = useRef<(() => void) | null>(null)\n useLayoutEffect(() => {\n measureRef.current?.()\n }, [util, snapshot.status])\n\n // ── the renderer + its textures (re-made per loaded image) ───────────────────────────────────\n const loaded = snapshot.status === 'ready' ? core.image : null\n const [renderer, setRenderer] = useState<{\n gl: WebGLRenderer | null\n tex: ReturnType<typeof downscale>\n blur: HTMLCanvasElement\n } | null>(null)\n useEffect(() => {\n const canvas = canvasRef.current\n if (!loaded || !canvas) return\n // WebGL when available (the same context is handed back on a re-run), else the Canvas2D fallback\n const gl = WebGLRenderer.create(canvas)\n const maxSide = Math.min(PREVIEW_MAX, gl?.maxTextureSize ?? PREVIEW_MAX)\n const tex = downscale(loaded.image, loaded.width, loaded.height, maxSide)\n const radius =\n CLARITY_RADIUS * Math.max(loaded.width, loaded.height) * (tex.width / loaded.width)\n const blur = blurredCopy(tex.canvas, tex.width, tex.height, radius)\n gl?.setImage(tex.canvas as TexImageSource, blur)\n setRenderer({ gl, tex, blur })\n return () => {\n gl?.dispose(false) // keep the canvas's context alive — a re-run reuses it\n setRenderer(null)\n }\n }, [loaded])\n\n // a Resize pick below the preview's own resolution: draw from a copy that coarse, so the preview shows\n // the output's real quality (a 50 px wide result looks soft at any zoom, as the file will)\n const detail =\n state && size ? (finalSize(state).width * state.scale) / resizedCrop(state).width : 1\n const coarseWidth = size ? Math.max(1, Math.round(size.width * detail)) : 0\n // …and the Redact effect: a blur is baked into the texture (a small blurred copy the GPU scales up);\n // a pixelation samples a smoothed copy at each block's center (the shader lays the crop's grid over it)\n const redactEffect = state?.redact.effect ?? 'blur'\n const redactAmount = state?.redact.amount ?? 0\n const [source, setSource] = useState<PreviewSource | null>(null)\n useEffect(() => {\n if (!renderer || !size) {\n setSource(null)\n return\n }\n // made in a frame callback, not during render: a moving ruler then costs one copy per frame at most\n const raf = requestAnimationFrame(() => {\n let base: PreviewSource = { ...renderer.tex, mipmap: true, pixelate: false }\n if (coarseWidth < base.width)\n base = {\n ...downscale(\n base.canvas,\n base.width,\n base.height,\n Math.max(1, Math.round(Math.max(size.width, size.height) * detail)),\n ),\n mipmap: true,\n pixelate: false,\n }\n const radius = redactRadius({ redact: { effect: redactEffect, amount: redactAmount } }, size)\n if (radius <= 0) return setSource(base)\n const r = radius * (base.width / size.width) // in this texture's pixels\n if (redactEffect === 'blur') {\n const small = blurredSmall(base.canvas, base.width, base.height, r, BLUR_PREVIEW_MAX)\n return setSource({\n canvas: small,\n width: small.width,\n height: small.height,\n mipmap: true,\n pixelate: false,\n })\n }\n if (!renderer.gl) {\n // the Canvas2D fallback can't lay the output grid over a rotated image — it pixelates the source\n const c = pixelatedCopy(base.canvas, base.width, base.height, r)\n return setSource({\n canvas: c,\n width: c.width,\n height: c.height,\n mipmap: false,\n pixelate: false,\n })\n }\n // about one texel per block: each block's center sample is then its neighborhood's average\n const smooth = downscale(\n base.canvas,\n base.width,\n base.height,\n Math.max(base.width, base.height) / Math.max(1, r),\n )\n setSource({ ...smooth, mipmap: false, pixelate: true })\n })\n return () => cancelAnimationFrame(raf)\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed on the integer width, not every `detail`\n }, [renderer, coarseWidth, redactEffect, redactAmount])\n useLayoutEffect(() => {\n if (renderer?.gl && source)\n renderer.gl.setSource(source.canvas as TexImageSource, source.mipmap)\n }, [renderer, source])\n\n // ── the view ─────────────────────────────────────────────────────────────────────────────────\n const target = useMemo<View | null>(() => {\n if (!state || !stage) return null\n const area = stage.area ?? stage\n if (util === 'crop') {\n // the Crop view: a crop bigger than the area is fitted to it (scaled down); a smaller one shows at\n // its real size (1 output px = 1 CSS px); a tiny one is enlarged just enough (its long side to\n // CROP_VIEW_MIN_SIDE) that the crop box is still easy to handle — never past the fit. \"Real size\"\n // is taken at the image's base (unzoomed) scale, so the Scale ruler / a pinch still zoom the image\n // inside a steady crop box (sized by the live scale, zooming in would shrink the box instead)\n const fitted = fitView(state.crop, area, Math.min(PAD_CROP, area.width * 0.06))\n const real = size ? zoomOf(state, size) / state.scale : 1 / state.scale\n const handleable = CROP_VIEW_MIN_SIDE / Math.max(state.crop.width, state.crop.height)\n return { ...fitted, scale: Math.min(fitted.scale, Math.max(real, handleable)) }\n }\n // the other tools show what the output will: a Resize pick of another aspect cuts the crop (cover)\n const crop = resizedCrop(state)\n const fitted = fitView(crop, area, PAD_VIEW)\n // …at its real size (1 output px = 1 CSS px — the Resize pick, else the crop at full resolution)\n // when it fits, so a small image or a smaller size looks small and sharp; it fits the area otherwise\n const fit = { ...fitted, scale: Math.min(fitted.scale, finalSize(state).width / crop.width) }\n if (viewZoom == null) return fit\n const scale = viewZoom / state.scale\n // keep the crop covering the stage center when zoomed in\n const lx = Math.max(0, crop.width / 2 - area.width / 2 / scale)\n const ly = Math.max(0, crop.height / 2 - area.height / 2 / scale)\n const px = Math.max(-lx, Math.min(lx, pan[0]))\n const py = Math.max(-ly, Math.min(ly, pan[1]))\n return { ...fit, scale, center: [fit.center[0] + px, fit.center[1] + py] }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `nonce` only forces a recompute\n }, [state, stage, util, viewZoom, pan, nonce])\n\n // switching tools re-fits the view (the Crop view leaves room around the crop, Filter / Finetune fill\n // the area with it) — spring there instead of jumping\n const prevUtil = useRef(util)\n // whether a view spring is running, and the stage + state the view was last laid out for\n const springing = useRef(false)\n const lastLayout = useRef<{ stage: typeof stage; state: typeof state; target?: View }>({\n stage,\n state,\n })\n const startSpring = (from: View, to: View) => {\n stopSpring.current?.()\n springing.current = true\n stopSpring.current = springTo(\n viewToVector(from),\n viewToVector(to),\n (x) => setView(vectorToView(x)),\n undefined,\n () => {\n springing.current = false\n },\n )\n }\n // how much of the image shows around the crop (CROP_DIM in the Crop view, 0 elsewhere), animated\n const [surround, setSurround] = useState(util === 'crop' ? CROP_DIM : 0)\n const surroundRef = useRef(surround)\n surroundRef.current = surround\n useEffect(() => {\n const to = util === 'crop' ? CROP_DIM : 0\n return springTo([surroundRef.current], [to], ([v]) => setSurround(Math.max(0, v)))\n }, [util])\n useLayoutEffect(() => {\n if (!target) return\n if (prevUtil.current !== util) {\n prevUtil.current = util\n if (viewRef.current && !pending.current) pending.current = 'jump'\n }\n // a layout-only change (the stage / free area re-measured — e.g. the footer swapped with the tool)\n const layoutOnly = stage !== lastLayout.current.stage && state === lastLayout.current.state\n // a new Resize pick (typed, a preset, undo) — the view eases into the new cut\n const prevResize = lastLayout.current.state?.resize\n const resized =\n util === 'resize' &&\n (state?.resize?.width !== prevResize?.width || state?.resize?.height !== prevResize?.height)\n // a commit that lands on the view already being animated to (e.g. a typed size, committed on blur)\n const prevTarget = lastLayout.current.target\n const sameTarget =\n !!prevTarget &&\n viewToVector(prevTarget).every((v, i) => Math.abs(v - viewToVector(target)[i]) < 1e-9)\n lastLayout.current = { stage, state, target }\n const kind = pending.current\n if (kind) {\n pending.current = null\n const cur = viewRef.current ?? target\n const from: View =\n kind === 'rotate'\n ? { center: target.center, scale: cur.scale, rotation: Math.PI / 2, flip: 1 }\n : kind === 'flip'\n ? { center: target.center, scale: cur.scale, rotation: 0, flip: -1 }\n : cur\n startSpring(from, target)\n return\n }\n // …while a view animation runs: keep animating, just toward the corrected target\n if ((layoutOnly || resized || sameTarget) && springing.current && stopSpring.current) {\n stopSpring.current.retarget(viewToVector(target))\n return\n }\n if (resized && viewRef.current && !frozen.current) {\n startSpring(viewRef.current, target)\n return\n }\n if (frozen.current) return\n stopSpring.current?.()\n stopSpring.current = null\n springing.current = false\n setView(target)\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `target` already folds in stage + state\n }, [target])\n useEffect(() => () => stopSpring.current?.(), [])\n\n // the effective zoom (CSS px per source px) for the header\n useEffect(() => {\n if (view && state) onZoomReport(view.scale * state.scale)\n }, [view, state, onZoomReport])\n\n // ── drawing ──────────────────────────────────────────────────────────────────────────────────\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas || !stage) return\n const w = Math.max(1, Math.round(stage.width * stage.dpr))\n const h = Math.max(1, Math.round(stage.height * stage.dpr))\n if (canvas.width !== w) canvas.width = w\n if (canvas.height !== h) canvas.height = h\n }, [stage])\n\n useEffect(() => {\n if (!renderer || !source || !state || !size || !view || !stage) return\n // outside the Crop tool the image is clipped to the part the output keeps (see `resizedCrop`)\n const shown = util === 'crop' ? state : { ...state, crop: resizedCrop(state) }\n const affines = sceneAffines(shown, size, view, stage)\n // a pixelation's blocks: whole blocks across the crop, as the export lays them\n const radius = source.pixelate ? redactRadius(state, size) : 0\n const pixel =\n radius > 0\n ? {\n pixel: ((g) => [g.cols, g.rows] as [number, number])(\n pixelGrid(shown.crop, radius * state.scale),\n ),\n cropToUV: chain(invertAffine(affines.toCrop), affines.toUV),\n }\n : null\n const raf = requestAnimationFrame(() => {\n const params = {\n ...colorParams(state),\n ...affines,\n ...pixel,\n // the image around the crop: dimmed in the Crop view, gone (faded into the background) in the\n // others — `surround` springs between the two on a tool switch\n clip: surround <= 0.001,\n dim: surround,\n dimColor: backgroundRgb(viewportRef.current),\n }\n if (renderer.gl) renderer.gl.render(params)\n else if (canvasRef.current)\n render2D(canvasRef.current, source.canvas, source, renderer.blur, renderer.blur, params)\n })\n return () => cancelAnimationFrame(raf)\n // `mode`: a light / dark switch changes the background the crop surround fades into\n }, [renderer, source, state, size, view, stage, surround, mode, util])\n\n // ── imperative API ───────────────────────────────────────────────────────────────────────────\n useImperativeHandle(ref, () => ({\n transition(kind) {\n pending.current = kind\n },\n }))\n\n // ── gestures ─────────────────────────────────────────────────────────────────────────────────\n const scale = view?.scale ?? 1\n const onViewZoomRef = useRef(onViewZoom)\n onViewZoomRef.current = onViewZoom\n const pinchDistance = () => {\n const [a, b] = [...pointers.current.values()]\n return a && b ? Math.hypot(a.x - b.x, a.y - b.y) : 0\n }\n\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (!state || !size || (e.pointerType === 'mouse' && e.button !== 0)) return\n if ((e.target as HTMLElement).closest('button')) return\n e.currentTarget.setPointerCapture(e.pointerId)\n pointers.current.set(e.pointerId, { x: e.clientX, y: e.clientY })\n stopSpring.current?.()\n if (pointers.current.size === 2) {\n gesture.current = {\n kind: 'pinch',\n dist: pinchDistance(),\n base: state,\n zoom: zoomOf(state, size),\n viewZoom: (view?.scale ?? 1) * state.scale,\n }\n return\n }\n const handle = (e.target as HTMLElement).closest<HTMLElement>('[data-handle]')?.dataset\n .handle as CropHandle | undefined\n if (util === 'crop') {\n gesture.current = handle\n ? { kind: 'resize', id: e.pointerId, x: e.clientX, y: e.clientY, base: state, handle }\n : { kind: 'pan', id: e.pointerId, x: e.clientX, y: e.clientY, base: state }\n if (handle) frozen.current = true\n setInteracting(true)\n } else if (viewZoom != null) {\n gesture.current = { kind: 'viewPan', id: e.pointerId, x: e.clientX, y: e.clientY, pan }\n }\n }\n\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n if (!pointers.current.has(e.pointerId) || !size) return\n pointers.current.set(e.pointerId, { x: e.clientX, y: e.clientY })\n const g = gesture.current\n if (!g) return\n if (g.kind === 'pinch') {\n const ratio = pinchDistance() / Math.max(1, g.dist)\n if (util === 'crop')\n core.preview(zoomTo(g.base, Math.min(MAX_CROP_ZOOM, g.zoom * ratio), size))\n else onViewZoom(clampZoom(g.viewZoom * ratio))\n return\n }\n if (g.id !== e.pointerId) return\n const dx = (e.clientX - g.x) / scale\n const dy = (e.clientY - g.y) / scale\n if (g.kind === 'pan') core.preview(panBy(g.base, -dx, -dy, size))\n else if (g.kind === 'resize') {\n const base = g.base.crop\n // a locked editor, a picked crop shape or a held Shift keeps the crop's ratio\n const locked = cropAspectRatio || g.base.cropRatio || e.shiftKey\n const ratio = locked ? base.width / base.height : null\n core.preview(\n resizeCrop(g.base, g.handle, dx, dy, size, {\n aspectRatio: ratio,\n minSize: Math.max(g.base.scale, MIN_CROP_SCREEN / scale),\n }),\n )\n } else if (g.kind === 'viewPan') setPan([g.pan[0] - dx, g.pan[1] - dy])\n }\n\n const onPointerUp = (e: PointerEvent<HTMLDivElement>) => {\n if (!pointers.current.has(e.pointerId)) return\n pointers.current.delete(e.pointerId)\n const g = gesture.current\n if (!g) return\n if (g.kind === 'pinch') {\n if (pointers.current.size === 0) {\n gesture.current = null\n if (util === 'crop') core.commit()\n }\n return\n }\n if (g.id !== e.pointerId) return\n gesture.current = null\n setInteracting(false)\n if (g.kind === 'resize') {\n // re-fit: spring the view so the new crop is centered + scaled to the viewport\n frozen.current = false\n pending.current = 'jump'\n core.commit()\n // the crop may be unchanged (a click on a handle) — still settle the view\n setNonce((n) => n + 1)\n } else if (g.kind === 'pan') core.commit()\n }\n\n const onWheel = (e: WheelEvent<HTMLDivElement>) => {\n if (!state || !size) return\n const zoomGesture = e.ctrlKey || e.metaKey\n // Safari reports a trackpad pinch as gesture events (handled below) — don't zoom twice\n if (zoomGesture && safariGesture.current) return\n if (util === 'crop') {\n const factor = Math.exp(-e.deltaY * (zoomGesture ? 0.01 : 0.002))\n core.preview(zoomTo(state, Math.min(MAX_CROP_ZOOM, zoomOf(state, size) * factor), size))\n clearTimeout(wheelCommit.current)\n wheelCommit.current = setTimeout(() => core.commit(), 250)\n return\n }\n if (zoomGesture) {\n const current = (view?.scale ?? 1) * state.scale\n onViewZoom(clampZoom(current * Math.exp(-e.deltaY * 0.01)))\n } else if (viewZoom != null) {\n setPan(([x, y]) => [x + e.deltaX / scale, y + e.deltaY / scale])\n }\n }\n useEffect(() => () => clearTimeout(wheelCommit.current), [])\n\n // Safari's trackpad pinch: `gesturestart` / `gesturechange` (a cumulative `scale`) / `gestureend`. The\n // page-zoom default is cancelled by the ImageEditor while it's open; here the pinch zooms the image.\n const safariGesture = useRef<{ base: ImageState; zoom: number; viewZoom: number } | null>(null)\n const live = useRef({ state, size, util, view })\n live.current = { state, size, util, view }\n useEffect(() => {\n const el = viewportRef.current\n if (!el) return\n type GestureEvent = Event & { scale: number }\n const onStart = (e: Event) => {\n const { state: s, size: sz, view: v } = live.current\n e.preventDefault()\n // a touch pinch on iOS also fires gesture events — the pointer pinch already handles that one\n if (!s || !sz || pointers.current.size > 0) return\n safariGesture.current = { base: s, zoom: zoomOf(s, sz), viewZoom: (v?.scale ?? 1) * s.scale }\n }\n const onChange = (e: Event) => {\n const g = safariGesture.current\n const { size: sz, util: u } = live.current\n if (!g || !sz) return\n e.preventDefault()\n const k = (e as GestureEvent).scale || 1\n if (u === 'crop') core.preview(zoomTo(g.base, Math.min(MAX_CROP_ZOOM, g.zoom * k), sz))\n else onViewZoomRef.current(clampZoom(g.viewZoom * k))\n }\n const onEnd = (e: Event) => {\n if (!safariGesture.current) return\n e.preventDefault()\n safariGesture.current = null\n if (live.current.util === 'crop') core.commit()\n }\n el.addEventListener('gesturestart', onStart)\n el.addEventListener('gesturechange', onChange)\n el.addEventListener('gestureend', onEnd)\n return () => {\n el.removeEventListener('gesturestart', onStart)\n el.removeEventListener('gesturechange', onChange)\n el.removeEventListener('gestureend', onEnd)\n }\n }, [core])\n\n // ── the crop overlay (screen rect at the view's resting rotation; animations ride a CSS transform) ──\n let cropBox: CSSProperties | null = null\n if (util === 'crop' && state && stage && view) {\n const m = planeToScreen({ ...view, rotation: 0, flip: 1 }, stage)\n const [x0, y0] = applyAffine(m, state.crop.x, state.crop.y)\n const [x1, y1] = applyAffine(\n m,\n state.crop.x + state.crop.width,\n state.crop.y + state.crop.height,\n )\n cropBox = { left: x0, top: y0, width: x1 - x0, height: y1 - y0 }\n }\n const sceneTransform: CSSProperties | undefined =\n view && stage\n ? {\n transform: `scaleX(${view.flip}) rotate(${view.rotation}rad)`,\n transformOrigin: stageOrigin(stage)\n .map((v) => `${v}px`)\n .join(' '),\n }\n : undefined\n\n return (\n <div\n ref={viewportRef}\n className={clsx(\n styles.viewport,\n util === 'crop' ? styles.viewportCrop : viewZoom != null && styles.viewportPannable,\n )}\n data-part=\"viewport\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onWheel={onWheel}\n >\n <canvas ref={canvasRef} className={styles.canvas} data-part=\"canvas\" />\n {cropBox && (\n <div className={clsx(styles.scene, styles.fadeIn)} style={sceneTransform}>\n <div\n className={clsx(styles.cropBox, interacting && styles.cropInteracting)}\n style={cropBox}\n data-part=\"crop\"\n >\n <span className={styles.grid} aria-hidden=\"true\" />\n {HANDLES.map((h) => (\n <span\n key={h}\n className={clsx(styles.handle, styles[`handle_${h}`])}\n data-handle={h}\n aria-hidden=\"true\"\n />\n ))}\n </div>\n </div>\n )}\n {/* the result's pixel size, in the crop's bottom edge — hidden while a rotate / flip animates\n (it sits at the crop's resting place, outside the animated scene, so it never mirrors) */}\n {cropBox && state && view && view.rotation === 0 && view.flip === 1 && (\n <div\n className={clsx(styles.sizeBadge, interacting && styles.sizeBadgeActive)}\n style={{\n left: (cropBox.left as number) + (cropBox.width as number) / 2,\n top: (cropBox.top as number) + (cropBox.height as number),\n }}\n data-part=\"size\"\n >\n {finalSize(state).width}\n <span className={styles.sizeTimes}>×</span>\n {finalSize(state).height}\n <span className={styles.sizeUnit}>px</span>\n </div>\n )}\n </div>\n )\n})\n\n/** The free area relative to the stage, its horizontal insets evened out to the larger one. */\nfunction symmetricArea(stage: DOMRect, area: DOMRect) {\n const inset = Math.max(0, area.left - stage.left, stage.right - area.right)\n return {\n x: inset,\n y: area.top - stage.top,\n width: Math.max(1, stage.width - inset * 2),\n height: area.height,\n }\n}\n\n/** The Filter / Finetune view zoom range (CSS px per source px). */\nexport const VIEW_ZOOM_MIN = 0.02\nexport const VIEW_ZOOM_MAX = 8\nconst clampZoom = (z: number) => Math.min(VIEW_ZOOM_MAX, Math.max(VIEW_ZOOM_MIN, z))\n","import { useState, type CSSProperties } from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport { Button } from '../Button'\nimport { Dropdown } from '../Dropdown'\nimport { Icon } from '../Icon'\nimport { ListItem } from '../List'\nimport type { ImageCropRatioOption } from './core/types'\nimport styles from './ImageEditor.module.css'\n\n/** The Crop Shape presets (landscape form — the portrait toggle flips them). */\nexport const DEFAULT_CROP_RATIOS: ImageCropRatioOption[] = [\n { label: '1:1', ratio: 1 },\n { label: '2:1', ratio: 2 },\n { label: '3:2', ratio: 3 / 2 },\n { label: '4:3', ratio: 4 / 3 },\n { label: '5:4', ratio: 5 / 4 },\n { label: '16:10', ratio: 16 / 10 },\n { label: '16:9', ratio: 16 / 9 },\n]\n\nconst same = (a: number, b: number) => Math.abs(a - b) < 1e-3\n/** `16:9` → `9:16` */\nconst flipLabel = (label: string) => label.split(':').reverse().join(':')\n\n/**\n * A small filled box of the given ratio, centered in a fixed square slot — the shape's preview (the\n * slot keeps every label at the same x, whatever the shape's width).\n */\nfunction ShapePreview({ ratio }: { ratio: number | null }) {\n const box = 16\n const w = ratio == null || ratio >= 1 ? box : Math.max(6, box * ratio)\n const h = ratio == null || ratio <= 1 ? box : Math.max(6, box / ratio)\n return (\n <span className={styles.shapeSlot}>\n <span\n className={clsx(styles.shapePreview, ratio == null && styles.shapeCustom)}\n style={{ width: w, height: h } as CSSProperties}\n />\n </span>\n )\n}\n\nexport interface CropShapeMenuProps {\n /** The current crop shape (width / height), `null` = custom. */\n ratio: number | null\n /** The presets (landscape form). */\n options: ImageCropRatioOption[]\n /** Pick a shape (`null` = custom). */\n onChange: (ratio: number | null) => void\n}\n\n/**\n * The Crop tool's **Crop Shape** menu: a landscape / portrait toggle on top, then Custom (free) and the\n * ratio presets, each with a little preview of its shape. Picking one reshapes the crop and locks it to\n * that ratio. Internal to the ImageEditor.\n */\nexport function CropShapeMenu({ ratio, options, onChange }: CropShapeMenuProps) {\n const t = useT()\n const [open, setOpen] = useState(false)\n const [portraitPref, setPortraitPref] = useState(false)\n // a picked non-square shape decides the orientation; otherwise the last toggle does\n const portrait = ratio != null && !same(ratio, 1) ? ratio < 1 : portraitPref\n\n const pick = (next: number | null) => {\n onChange(next)\n setOpen(false)\n }\n const setOrientation = (toPortrait: boolean) => {\n setPortraitPref(toPortrait)\n // flip the picked shape along with it (16:9 ⇄ 9:16)\n if (ratio != null && !same(ratio, 1) && ratio < 1 !== toPortrait) onChange(1 / ratio)\n }\n\n return (\n <Dropdown\n open={open}\n onOpenChange={setOpen}\n closeOnSelect={false}\n placement=\"bottom-start\"\n size=\"sm\"\n trigger={\n <Button\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n startIcon={<Icon name=\"MaximizeFormat\" />}\n title={t('imageEditor.cropShape')}\n aria-label={t('imageEditor.cropShape')}\n className={styles.toolbarIconOnPhone}\n >\n <span className={styles.toolbarLabel}>{t('imageEditor.cropShape')}</span>\n </Button>\n }\n >\n <div\n className={styles.shapeOrientation}\n role=\"group\"\n aria-label={t('imageEditor.orientation')}\n >\n {[false, true].map((p) => (\n <button\n key={String(p)}\n type=\"button\"\n className={clsx(styles.orientButton, portrait === p && styles.orientActive)}\n aria-pressed={portrait === p}\n aria-label={t(p ? 'imageEditor.portrait' : 'imageEditor.landscape')}\n title={t(p ? 'imageEditor.portrait' : 'imageEditor.landscape')}\n onClick={() => setOrientation(p)}\n >\n <Icon name={p ? 'Mobile' : 'Monitor'} size=\"sm\" />\n </button>\n ))}\n </div>\n <ListItem\n icon={<ShapePreview ratio={null} />}\n clickable\n selected={ratio == null}\n onClick={() => pick(null)}\n >\n {t('imageEditor.custom')}\n </ListItem>\n {options.map((o) => {\n const r = portrait ? 1 / o.ratio : o.ratio\n return (\n <ListItem\n key={o.label}\n icon={<ShapePreview ratio={r} />}\n clickable\n selected={ratio != null && same(ratio, r)}\n onClick={() => pick(r)}\n >\n {portrait && !same(o.ratio, 1) ? flipLabel(o.label) : o.label}\n </ListItem>\n )\n })}\n </Dropdown>\n )\n}\n","import { useEffect, useRef, useState, type KeyboardEvent, type PointerEvent } from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport type { MessageKey } from '../../i18n/messages'\nimport { chain, scaleAffine, translate } from './core/affine'\nimport { cropCenter, type Size } from './core/geometry'\nimport { CLARITY_RADIUS, downscale, type ImageSource } from './core/load'\nimport { FILTER_GROUPS, FILTER_MATRICES } from './core/matrix'\nimport { applyColorOps, boxBlur } from './core/pixels'\nimport { colorParams } from './core/render'\nimport { sourceToPlane } from './core/scene'\nimport type { ImageFilterId, ImageState } from './core/types'\nimport styles from './ImageEditor.module.css'\n\n/** Thumbnail edge in CSS px (rendered at the device pixel ratio). */\nconst THUMB = 52\n\nexport interface FilterStripProps {\n image: ImageSource\n size: Size\n state: ImageState\n onSelect: (id: ImageFilterId) => void\n}\n\n/** Render every filter's thumbnail of the current (cropped / rotated / finetuned) image as data URLs. */\nfunction renderThumbs(source: CanvasImageSource, size: Size, state: ImageState) {\n const dpr = Math.min(2, typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1)\n const t = Math.round(THUMB * dpr)\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = t\n const ctx = canvas.getContext('2d', { willReadFrequently: true })\n if (!ctx) return null\n // source px → plane → thumbnail px (the crop covers the square, centered)\n const { crop } = state\n const k = t / Math.min(crop.width, crop.height)\n const [kx, ky] = cropCenter(crop)\n const m = chain(\n sourceToPlane(state, size),\n translate(-kx, -ky),\n scaleAffine(k),\n translate(t / 2, t / 2),\n )\n ctx.setTransform(m[0], m[3], m[1], m[4], m[2], m[5])\n ctx.imageSmoothingQuality = 'high'\n ctx.drawImage(source, 0, 0, size.width, size.height)\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n let base: ImageData\n try {\n base = ctx.getImageData(0, 0, t, t)\n } catch {\n return null // a tainted canvas — no thumbnails\n }\n const radius = CLARITY_RADIUS * Math.max(size.width, size.height) * state.scale * k\n const blur = state.finetune.clarity ? boxBlur(base.data, t, t, radius) : null\n // thumbnail px → crop-normalized coords (for the vignette)\n const toCrop = chain(\n translate(-t / 2, -t / 2),\n scaleAffine(1 / k),\n scaleAffine(2 / crop.width, 2 / crop.height),\n )\n const out: Partial<Record<ImageFilterId, string>> = {}\n for (const id of FILTER_GROUPS.flat()) {\n const data = new ImageData(new Uint8ClampedArray(base.data), t, t)\n applyColorOps(data.data, t, t, colorParams(state, FILTER_MATRICES[id]), blur, toCrop)\n ctx.putImageData(data, 0, 0)\n out[id] = canvas.toDataURL()\n }\n return out\n}\n\n/**\n * The Filter tool's footer: a horizontally scrolling strip of preset tiles (live thumbnails), grouped.\n * Wheel scrolls it sideways, it drags with momentum, arrows move between tiles; the edges fade.\n */\nexport function FilterStrip({ image, size, state, onSelect }: FilterStripProps) {\n const t = useT()\n const scrollerRef = useRef<HTMLDivElement>(null)\n const [thumbs, setThumbs] = useState<Partial<Record<ImageFilterId, string>>>({})\n const [edges, setEdges] = useState({ start: false, end: false })\n const active: ImageFilterId = state.filter ?? 'default'\n\n // a small copy of the image for the thumbnails (re-made per image)\n const small = useRef<{ image: ImageSource; source: CanvasImageSource } | null>(null)\n if (small.current?.image !== image)\n small.current = { image, source: downscale(image, size.width, size.height, 512).canvas }\n\n // the geometry + finetune the thumbnails depend on (not the active filter itself)\n const key = JSON.stringify([\n state.crop,\n state.rotation,\n state.flipX,\n state.flipY,\n state.scale,\n state.finetune,\n ])\n useEffect(() => {\n const id = setTimeout(() => {\n const src = small.current?.source\n if (!src) return\n // the small copy has its own pixel size; draw it as if it were the full image\n const r = renderThumbs(src, size, state)\n if (r) setThumbs(r)\n }, 120)\n return () => clearTimeout(id)\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed on the serialized inputs\n }, [key, image])\n\n // edge fades\n const updateEdges = () => {\n const el = scrollerRef.current\n if (!el) return\n setEdges({\n start: el.scrollLeft > 2,\n end: el.scrollLeft + el.clientWidth < el.scrollWidth - 2,\n })\n }\n useEffect(() => {\n updateEdges()\n const el = scrollerRef.current\n if (!el || typeof ResizeObserver === 'undefined') return\n const ro = new ResizeObserver(updateEdges)\n ro.observe(el)\n return () => ro.disconnect()\n }, [])\n\n // keep the active tile in view\n useEffect(() => {\n scrollerRef.current\n ?.querySelector<HTMLElement>(`[data-filter=\"${active}\"]`)\n ?.scrollIntoView?.({ block: 'nearest', inline: 'nearest', behavior: 'smooth' })\n }, [active])\n\n // vertical wheel → horizontal scroll\n useEffect(() => {\n const el = scrollerRef.current\n if (!el) return\n const onWheel = (e: WheelEvent) => {\n if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return\n e.preventDefault()\n el.scrollLeft += e.deltaY\n }\n el.addEventListener('wheel', onWheel, { passive: false })\n return () => el.removeEventListener('wheel', onWheel)\n }, [])\n\n // mouse drag-to-scroll with momentum (touch scrolls natively)\n const drag = useRef<{ x: number; left: number; v: number; t: number; moved: boolean } | null>(\n null,\n )\n const momentum = useRef(0)\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (e.pointerType !== 'mouse' || e.button !== 0) return\n cancelAnimationFrame(momentum.current)\n const el = scrollerRef.current!\n drag.current = { x: e.clientX, left: el.scrollLeft, v: 0, t: performance.now(), moved: false }\n }\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n const d = drag.current\n if (!d) return\n const el = scrollerRef.current!\n const dx = e.clientX - d.x\n if (Math.abs(dx) > 4 && !d.moved) {\n d.moved = true\n el.setPointerCapture(e.pointerId)\n }\n if (!d.moved) return\n const now = performance.now()\n const next = d.left - dx\n d.v = (el.scrollLeft - next) / Math.max(1, now - d.t)\n d.t = now\n el.scrollLeft = next\n }\n const onPointerUp = () => {\n const d = drag.current\n drag.current = null\n if (!d?.moved) return\n const el = scrollerRef.current!\n let v = -d.v\n let last = performance.now()\n const step = (now: number) => {\n const dt = now - last\n last = now\n el.scrollLeft += v * dt\n v *= Math.pow(0.995, dt)\n if (Math.abs(v) > 0.02) momentum.current = requestAnimationFrame(step)\n }\n momentum.current = requestAnimationFrame(step)\n // swallow the click that ends a drag\n const block = (ev: MouseEvent) => {\n ev.stopPropagation()\n ev.preventDefault()\n }\n el.addEventListener('click', block, { capture: true, once: true })\n setTimeout(() => el.removeEventListener('click', block, { capture: true }), 0)\n }\n useEffect(() => () => cancelAnimationFrame(momentum.current), [])\n\n // ←/→ move between tiles\n const ids = FILTER_GROUPS.flat()\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return\n const i = ids.indexOf((e.target as HTMLElement).dataset.filter as ImageFilterId)\n if (i === -1) return\n e.preventDefault()\n const next = ids[Math.min(ids.length - 1, Math.max(0, i + (e.key === 'ArrowRight' ? 1 : -1)))]\n scrollerRef.current?.querySelector<HTMLElement>(`[data-filter=\"${next}\"]`)?.focus()\n }\n\n return (\n <div\n ref={scrollerRef}\n className={clsx(styles.strip, edges.start && styles.fadeStart, edges.end && styles.fadeEnd)}\n data-part=\"filters\"\n role=\"group\"\n aria-label={t('imageEditor.filters')}\n onScroll={updateEdges}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onKeyDown={onKeyDown}\n >\n {FILTER_GROUPS.map((group, gi) => (\n <div key={gi} className={styles.stripGroup}>\n {group.map((id) => (\n <button\n key={id}\n type=\"button\"\n className={clsx(styles.filterTile, id === active && styles.filterActive)}\n data-filter={id}\n aria-pressed={id === active}\n onClick={() => onSelect(id)}\n >\n <span className={styles.filterThumb}>\n {thumbs[id] && <img src={thumbs[id]} alt=\"\" draggable={false} />}\n </span>\n <span className={styles.filterLabel}>\n {t(`imageEditor.filter.${id}` as MessageKey)}\n </span>\n </button>\n ))}\n </div>\n ))}\n </div>\n )\n}\n","import { useEffect, useRef, useState, type KeyboardEvent } from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport { Icon } from '../Icon'\nimport type { Size } from './core/geometry'\nimport styles from './ImageEditor.module.css'\n\nexport interface ResizePanelProps {\n /** The largest size — the crop at full resolution (the tool never upscales). */\n max: Size\n /** The current result size. */\n value: Size\n /** Keep the crop's aspect ratio while typing. */\n locked: boolean\n onLockedChange: (locked: boolean) => void\n /** A live change (while typing). */\n onInput: (size: Size | null) => void\n /** A committed change (Enter, blur, a preset). */\n onChange: (size: Size | null) => void\n}\n\n/** The quick picks, as a share of the full size. */\nconst PRESETS = [1, 0.75, 0.5, 0.25]\n\nconst clampSide = (v: number, max: number) => Math.max(1, Math.min(max, Math.round(v)))\n\n/**\n * The Resize tool's footer: a Width × Height pair (with an aspect-ratio lock between them) under the\n * full size it can go up to, and Original / 75% / 50% / 25% quick picks. Internal to the ImageEditor.\n */\nexport function ResizePanel({\n max,\n value,\n locked,\n onLockedChange,\n onInput,\n onChange,\n}: ResizePanelProps) {\n const t = useT()\n const size = value\n const [draft, setDraft] = useState({ w: String(size.width), h: String(size.height) })\n // follow outside changes (undo, a preset, a crop change) when not mid-typing\n useEffect(() => {\n setDraft({ w: String(size.width), h: String(size.height) })\n }, [size.width, size.height])\n\n // the aspect the lock keeps: the crop's — or, once a free pick cut it, that pick's\n const sameAspect =\n Math.round((size.width * max.height) / max.width) === size.height ||\n Math.round((size.height * max.width) / max.height) === size.width\n const liveRatio = sameAspect ? max.width / max.height : size.width / size.height\n // held for a whole edit (focus → blur), so rounding while typing can't drift it\n const heldRatio = useRef<number | null>(null)\n const ratio = heldRatio.current ?? liveRatio\n /** The size an edit of one side means (the other side follows when locked). */\n const resolve = (side: 'w' | 'h', raw: string): Size | null => {\n const n = Number(raw)\n if (!raw || !Number.isFinite(n) || n <= 0) return null\n if (side === 'w') {\n let width = clampSide(n, max.width)\n if (!locked) return { width, height: size.height }\n const height = clampSide(width / ratio, max.height)\n // a side that hit its limit pulls the other back to the ratio\n if (height < width / ratio - 0.5) width = clampSide(height * ratio, max.width)\n return { width, height }\n }\n let height = clampSide(n, max.height)\n if (!locked) return { width: size.width, height }\n const width = clampSide(height * ratio, max.width)\n if (width < height * ratio - 0.5) height = clampSide(width / ratio, max.height)\n return { width, height }\n }\n /** `null` when it's the full size (no resize). */\n const normalize = (s: Size) => (s.width === max.width && s.height === max.height ? null : s)\n\n const edit = (side: 'w' | 'h', raw: string) => {\n const digits = raw.replace(/[^\\d]/g, '')\n const next = resolve(side, digits)\n setDraft((d) =>\n next\n ? {\n w: side === 'w' ? digits : String(next.width),\n h: side === 'h' ? digits : String(next.height),\n }\n : { ...d, [side]: digits },\n )\n if (next) onInput(normalize(next))\n }\n const commit = () => {\n const w = Number(draft.w)\n const h = Number(draft.h)\n // an empty / zero field falls back to the last good size\n let s: Size = size\n if (w > 0 && h > 0)\n s = locked\n ? (resolve('w', draft.w) ?? size)\n : { width: clampSide(w, max.width), height: clampSide(h, max.height) }\n setDraft({ w: String(s.width), h: String(s.height) })\n onChange(normalize(s))\n }\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>, side: 'w' | 'h') => {\n if (e.key === 'Enter') {\n e.preventDefault()\n commit()\n return\n }\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return\n e.preventDefault()\n const step = (e.shiftKey ? 10 : 1) * (e.key === 'ArrowUp' ? 1 : -1)\n const cur = side === 'w' ? size.width : size.height\n const next = resolve(side, String(cur + step))\n if (next) {\n setDraft({ w: String(next.width), h: String(next.height) })\n onChange(normalize(next))\n }\n }\n\n const presetActive = (p: number) =>\n size.width === Math.max(1, Math.round(max.width * p)) &&\n size.height === Math.max(1, Math.round(max.height * p))\n\n return (\n <div className={styles.resizePanel} data-part=\"resize\">\n <div className={styles.resizeFields}>\n <label className={styles.dimField}>\n <span className={styles.dimLabel}>\n <span className={styles.dimLabelFull}>{t('imageEditor.width')}</span>\n {/* a phone shows just the first letter (W / H) */}\n <span className={styles.dimLabelShort} aria-hidden=\"true\">\n {t('imageEditor.width').charAt(0)}\n </span>\n </span>\n <input\n className={styles.dimInput}\n inputMode=\"numeric\"\n value={draft.w}\n aria-label={t('imageEditor.width')}\n onChange={(e) => edit('w', e.target.value)}\n onBlur={() => {\n commit()\n heldRatio.current = null\n }}\n onKeyDown={(e) => onKeyDown(e, 'w')}\n onFocus={(e) => {\n heldRatio.current = liveRatio\n e.target.select()\n }}\n />\n <span className={styles.dimUnit}>px</span>\n </label>\n <button\n type=\"button\"\n className={clsx(styles.lockButton, locked && styles.lockActive)}\n aria-pressed={locked}\n aria-label={t('imageEditor.lockRatio')}\n title={t('imageEditor.lockRatio')}\n onClick={() => onLockedChange(!locked)}\n >\n <Icon name={locked ? 'Unlock' : 'LockSlash'} size=\"sm\" />\n </button>\n <label className={styles.dimField}>\n <span className={styles.dimLabel}>\n <span className={styles.dimLabelFull}>{t('imageEditor.height')}</span>\n {/* a phone shows just the first letter (W / H) */}\n <span className={styles.dimLabelShort} aria-hidden=\"true\">\n {t('imageEditor.height').charAt(0)}\n </span>\n </span>\n <input\n className={styles.dimInput}\n inputMode=\"numeric\"\n value={draft.h}\n aria-label={t('imageEditor.height')}\n onChange={(e) => edit('h', e.target.value)}\n onBlur={() => {\n commit()\n heldRatio.current = null\n }}\n onKeyDown={(e) => onKeyDown(e, 'h')}\n onFocus={(e) => {\n heldRatio.current = liveRatio\n e.target.select()\n }}\n />\n <span className={styles.dimUnit}>px</span>\n </label>\n </div>\n <div\n className={styles.tabs}\n role=\"group\"\n aria-label={t('imageEditor.resize')}\n data-part=\"tabs\"\n >\n {PRESETS.map((p) => (\n <button\n key={p}\n type=\"button\"\n aria-pressed={presetActive(p)}\n className={clsx(styles.tab, presetActive(p) && styles.tabActive)}\n onClick={() =>\n onChange(\n normalize({\n width: Math.max(1, Math.round(max.width * p)),\n height: Math.max(1, Math.round(max.height * p)),\n }),\n )\n }\n >\n {p === 1 ? t('imageEditor.original') : `${Math.round(p * 100)}%`}\n </button>\n ))}\n </div>\n </div>\n )\n}\n","import {\n useEffect,\n useRef,\n type CSSProperties,\n type KeyboardEvent,\n type PointerEvent,\n type WheelEvent,\n} from 'react'\nimport { clsx } from 'clsx'\nimport styles from './RulerSlider.module.css'\n\nexport interface RulerSliderProps {\n /** Lowest value. */\n min: number\n /** Highest value. */\n max: number\n /** The current value. */\n value: number\n /** Value granularity. Defaults to `1`. */\n step?: number\n /** Arrow-key step (Shift = ×10). Defaults to `1`. */\n keyStep?: number\n /** Values the ruler snaps to when within `snapThreshold`. Defaults to `[0]`. */\n snapPoints?: number[]\n /** Snap distance in value units. Defaults to 2% of the range. */\n snapThreshold?: number\n /** Value units between two ruler dots. Defaults to 5% of the range. */\n tickStep?: number\n /** Every n-th dot is a bigger one. Defaults to `5`. */\n majorEvery?: number\n /** The value a double-click resets to. Defaults to `0` (clamped into the range). */\n resetValue?: number\n /** The label shown at the center (and the `aria-valuetext`). */\n format?: (value: number) => string\n /** Fired continuously while the value changes (drag, inertia, wheel). */\n onInput: (value: number) => void\n /** Fired when a change is committed (pointer-up / inertia end, a key press, wheel idle, reset). */\n onChange: (value: number) => void\n /** Accessible name. */\n 'aria-label': string\n className?: string\n}\n\n/** Pixels between two ruler dots. */\nconst TICK_GAP = 9\n\n/**\n * A tape-measure slider: a dotted ruler slides under a fixed center indicator (drag left → the value\n * grows), with inertia, wheel and keyboard control, snapping to `snapPoints`, and a double-click reset.\n * Internal to the ImageEditor (Rotation / Scale / Finetune).\n */\nexport function RulerSlider({\n min,\n max,\n value,\n step = 1,\n keyStep = 1,\n snapPoints = [0],\n snapThreshold = (max - min) * 0.02,\n tickStep = (max - min) / 20,\n majorEvery = 5,\n resetValue = 0,\n format = (v) => String(Math.round(v)),\n onInput,\n onChange,\n 'aria-label': ariaLabel,\n className,\n}: RulerSliderProps) {\n const pxPerUnit = TICK_GAP / tickStep\n const drag = useRef<{\n id: number\n startX: number\n startValue: number\n lastX: number\n lastT: number\n velocity: number\n moved: boolean\n } | null>(null)\n const inertia = useRef(0)\n const wheelTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const live = useRef(value)\n live.current = value\n // a glide / wheel whose commit hasn't fired yet — flushed on unmount (switching tab / tool mid-gesture),\n // so the value it previewed is committed rather than left half-applied\n const pending = useRef(false)\n const latestOnChange = useRef(onChange)\n latestOnChange.current = onChange\n const commitValue = (v: number) => {\n pending.current = false\n onChange(v)\n }\n\n useEffect(\n () => () => {\n cancelAnimationFrame(inertia.current)\n clearTimeout(wheelTimer.current)\n if (pending.current) {\n pending.current = false\n latestOnChange.current(live.current)\n }\n },\n [],\n )\n\n const settle = (raw: number, snap = true) => {\n let v = Math.min(max, Math.max(min, raw))\n v = Math.round(v / step) * step\n if (snap)\n for (const p of snapPoints)\n if (Math.abs(v - p) <= snapThreshold) {\n v = p\n break\n }\n return Number(v.toFixed(6))\n }\n\n const emitInput = (v: number) => {\n if (v !== live.current) {\n live.current = v\n pending.current = true\n onInput(v)\n }\n }\n\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return\n cancelAnimationFrame(inertia.current)\n e.currentTarget.setPointerCapture(e.pointerId)\n drag.current = {\n id: e.pointerId,\n startX: e.clientX,\n startValue: value,\n lastX: e.clientX,\n lastT: performance.now(),\n velocity: 0,\n moved: false,\n }\n }\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n const d = drag.current\n if (!d || d.id !== e.pointerId) return\n const now = performance.now()\n const dt = Math.max(1, now - d.lastT)\n // a smoothed velocity (value units per ms) for the release inertia\n d.velocity = 0.7 * (-(e.clientX - d.lastX) / pxPerUnit / dt) + 0.3 * d.velocity\n d.lastX = e.clientX\n d.lastT = now\n if (Math.abs(e.clientX - d.startX) > 2) d.moved = true\n emitInput(settle(d.startValue - (e.clientX - d.startX) / pxPerUnit))\n }\n const onPointerUp = (e: PointerEvent<HTMLDivElement>) => {\n const d = drag.current\n if (!d || d.id !== e.pointerId) return\n drag.current = null\n // keep sliding with the release speed, decaying exponentially\n let v = live.current\n // a gentle glide: capped so a flick never sails across the whole range\n const cap = (max - min) / 1500\n let vel = performance.now() - d.lastT < 80 ? Math.max(-cap, Math.min(cap, d.velocity)) : 0\n if (!d.moved || Math.abs(vel) < cap / 20) return commitValue(settle(v))\n let last = performance.now()\n const tick = (now: number) => {\n // a late frame (a busy main thread, a background tab) mustn't turn into one big jump\n const dt = Math.min(32, Math.max(0, now - last))\n last = now\n v += vel * dt\n vel *= Math.pow(0.99, dt)\n const next = settle(v, Math.abs(vel) < cap / 6)\n emitInput(next)\n if (Math.abs(vel) < cap / 40 || next <= min || next >= max) return commitValue(next)\n inertia.current = requestAnimationFrame(tick)\n }\n inertia.current = requestAnimationFrame(tick)\n }\n\n const onWheel = (e: WheelEvent<HTMLDivElement>) => {\n const delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY\n if (!delta) return\n const next = settle(live.current + delta / pxPerUnit / 2)\n emitInput(next)\n clearTimeout(wheelTimer.current)\n wheelTimer.current = setTimeout(() => commitValue(live.current), 220)\n }\n\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n const big = e.shiftKey ? 10 : 1\n let next: number | null = null\n const cur = live.current\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') next = cur + keyStep * big\n else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') next = cur - keyStep * big\n else if (e.key === 'Home') next = min\n else if (e.key === 'End') next = max\n if (next == null) return\n e.preventDefault()\n const v = settle(next, false)\n emitInput(v)\n commitValue(v)\n }\n\n const reset = () => {\n cancelAnimationFrame(inertia.current)\n const v = settle(resetValue, false)\n emitInput(v)\n commitValue(v)\n }\n\n const ticks = Math.floor((max - min) / tickStep)\n const label = format(value)\n return (\n <div\n role=\"slider\"\n tabIndex={0}\n aria-label={ariaLabel}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-valuetext={label}\n aria-orientation=\"horizontal\"\n className={clsx(styles.ruler, className)}\n data-part=\"ruler\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onWheel={onWheel}\n onKeyDown={onKeyDown}\n onDoubleClick={reset}\n >\n <span className={styles.value} aria-hidden=\"true\">\n {label}\n </span>\n <span className={styles.viewport} aria-hidden=\"true\">\n <span\n className={styles.track}\n style={\n {\n width: ticks * TICK_GAP,\n transform: `translateX(${-(value - min) * pxPerUnit}px)`,\n } as CSSProperties\n }\n >\n {Array.from({ length: ticks + 1 }, (_, i) => {\n const tickValue = min + i * tickStep\n return (\n <span\n key={i}\n className={clsx(\n styles.tick,\n i % majorEvery === 0 && styles.major,\n Math.abs(tickValue - resetValue) < 1e-9 && styles.origin,\n )}\n style={{ left: i * TICK_GAP }}\n />\n )\n })}\n </span>\n <span className={styles.indicator} />\n </span>\n </div>\n )\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useT } from '../../theme'\nimport type { MessageKey } from '../../i18n/messages'\nimport { Button } from '../Button'\nimport { Icon, type IconName } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Loader } from '../Loader'\nimport { Overlay } from '../Overlay/Overlay'\nimport { ImageEditorCore } from './core/editor'\nimport {\n flipHorizontal,\n MAX_CROP_ZOOM,\n normalizeAngle,\n rotateLeft,\n rotateTo,\n setCropRatio,\n splitRotation,\n applyResize,\n finalSize,\n outputSize,\n zoomOf,\n zoomTo,\n} from './core/geometry'\nimport { FILTER_MATRICES, FINETUNE_IDS } from './core/matrix'\nimport type {\n ImageEditorOptions,\n ImageEditorResult,\n ImageEditorUtil,\n ImageFinetuneId,\n ImageRedactEffect,\n ImageState,\n} from './core/types'\nimport { EditorStage, VIEW_ZOOM_MAX, VIEW_ZOOM_MIN, type EditorStageHandle } from './EditorStage'\nimport { CropShapeMenu, DEFAULT_CROP_RATIOS } from './CropShapeMenu'\nimport { FilterStrip } from './FilterStrip'\nimport { ResizePanel } from './ResizePanel'\nimport { RulerSlider } from './RulerSlider'\nimport styles from './ImageEditor.module.css'\n\nexport interface ImageEditorProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onLoad' | 'title' | 'children'>,\n Omit<ImageEditorOptions, 'src'> {\n /** Whether the editor is shown (a fullscreen overlay). */\n open: boolean\n /** The image to edit: a `File` / `Blob`, a URL or a data URL. */\n src: ImageEditorOptions['src'] | null\n /** Fired once the image has loaded. */\n onLoad?: (info: { width: number; height: number }) => void\n /** Fired on every committed change (a drag's end, a click, a preset). */\n onUpdate?: (state: ImageState) => void\n /** Fired by **Done** with the rendered image + the state it came from; the editor then closes. */\n onProcess?: (result: ImageEditorResult) => void\n /** Requested close (✕, Escape, or after **Done**). Changes are discarded unless processed. */\n onClose: () => void\n}\n\nconst TOOLS: { id: ImageEditorUtil; icon: IconName }[] = [\n { id: 'crop', icon: 'Crop' },\n { id: 'filter', icon: 'Colorfilter' },\n { id: 'finetune', icon: 'Brush' },\n { id: 'redact', icon: 'Blur' },\n { id: 'resize', icon: 'Maximize3' },\n]\n\n/** The Redact tool's effects, in tab order. */\nconst REDACT_EFFECTS: ImageRedactEffect[] = ['blur', 'pixelate']\n\n/** The Filter / Finetune view zoom steps (CSS px per source px). */\nconst ZOOM_LEVELS = [0.05, 0.1, 0.15, 0.2, 0.25, 0.33, 0.5, 0.67, 0.75, 1, 1.5, 2, 3, 4, 6, 8]\n\nconst FOCUSABLE =\n 'a[href]:not([tabindex=\"-1\"]), button:not(:disabled):not([tabindex=\"-1\"]), input:not(:disabled):not([tabindex=\"-1\"]), [tabindex]:not([tabindex=\"-1\"])'\n\nconst RAD = Math.PI / 180\n\n/**\n * A fullscreen image editor — **Crop** (resize, pan, zoom, rotate ±45°, scale, rotate left, flip, Crop\n * Shape presets), **Filter** (14 presets with live thumbnails), **Finetune** (brightness, contrast,\n * saturation, exposure, temperature, gamma, clarity, vignette), **Redact** (blur or pixelate the whole\n * image) and **Resize** (width × height, aspect lock, never upscales) — over a WebGL renderer (Canvas2D\n * fallback), with undo / redo / revert (Revert = back to the original image). **Done** renders the result\n * at full source resolution (JPEG / PNG / WebP keep their type, anything else becomes PNG) and hands it to\n * `onProcess` with the `imageState`, which re-opens the edit non-destructively via `initialState`. Follows\n * the app's light / dark theme.\n */\nexport const ImageEditor = forwardRef<HTMLDivElement, ImageEditorProps>(function ImageEditor(\n {\n open,\n src,\n initialState,\n util = 'crop',\n cropAspectRatio,\n cropRatioOptions,\n outputType,\n outputQuality,\n onLoad,\n onUpdate,\n onProcess,\n onClose,\n className,\n onKeyDown: onKeyDownProp,\n ...props\n },\n ref,\n) {\n const t = useT()\n const [core] = useState(() => new ImageEditorCore())\n const snap = useSyncExternalStore(core.subscribe, core.getSnapshot, core.getSnapshot)\n const { state, size, ui, status } = snap\n const stageRef = useRef<EditorStageHandle>(null)\n const rootRef = useRef<HTMLDivElement | null>(null)\n const areaRef = useRef<HTMLDivElement | null>(null)\n const [viewZoom, setViewZoom] = useState<number | null>(null)\n const [effectiveZoom, setEffectiveZoom] = useState(1)\n const [processing, setProcessing] = useState(false)\n const [processError, setProcessError] = useState(false)\n // the quarter-turn part of the rotation (the fine slider moves only the rest)\n const quarter = useRef(0)\n const rotationBase = useRef<ImageState | null>(null)\n // the state the Resize tool's picks are made from: the one it was entered with (re-taken after an\n // undo / redo / revert) — so typing 1800 × 100, then 1800 × 600 cuts from the full crop again\n const resizeBase = useRef<ImageState | null>(null)\n const resizeOwn = useRef<ImageState | null>(null)\n if (ui.util !== 'resize' || !state) resizeBase.current = null\n else if (!resizeBase.current || (state !== resizeOwn.current && state !== resizeBase.current))\n resizeBase.current = state\n\n // latest callbacks for the event subscriptions\n const cbs = useRef({ onLoad, onUpdate })\n cbs.current = { onLoad, onUpdate }\n useEffect(() => {\n const offs = [\n core.on('load', (p) =>\n cbs.current.onLoad?.((p as { size: { width: number; height: number } }).size),\n ),\n core.on('update', (s) => cbs.current.onUpdate?.(s as ImageState)),\n // a rotation drag's base is stale once history moves under it\n ...(['undo', 'redo', 'revert'] as const).map((e) =>\n core.on(e, () => {\n rotationBase.current = null\n }),\n ),\n ]\n return () => offs.forEach((off) => off())\n }, [core])\n\n // open / re-open on a new source\n useEffect(() => {\n if (!open || !src) return\n setViewZoom(null)\n setProcessError(false)\n core\n .open({ src, initialState, util, cropAspectRatio, outputType, outputQuality })\n .then(() => {\n const s = core.getSnapshot().state\n if (s) quarter.current = splitRotation(s.rotation).quarter\n })\n .catch(() => {}) // surfaced through the snapshot's `error` status\n return () => core.close()\n // eslint-disable-next-line react-hooks/exhaustive-deps -- re-open only when the image changes\n }, [open, src, core])\n\n // while open, a pinch / Ctrl+wheel zooms the IMAGE, never the page: Chrome / Edge / Firefox send a\n // trackpad pinch as a Ctrl+wheel (React's wheel listener is passive, so it can't cancel it — this one\n // isn't), Safari as gesture events\n useEffect(() => {\n if (!open) return\n const onWheel = (e: WheelEvent) => {\n if (e.ctrlKey || e.metaKey) e.preventDefault()\n }\n const onGesture = (e: Event) => e.preventDefault()\n const gestures = ['gesturestart', 'gesturechange', 'gestureend']\n window.addEventListener('wheel', onWheel, { passive: false })\n gestures.forEach((g) => document.addEventListener(g, onGesture))\n return () => {\n window.removeEventListener('wheel', onWheel)\n gestures.forEach((g) => document.removeEventListener(g, onGesture))\n }\n }, [open])\n\n // focus: into the editor on open, back to the opener on close\n useEffect(() => {\n if (!open) return\n const opener = document.activeElement as HTMLElement | null\n const id = requestAnimationFrame(() => rootRef.current?.focus())\n return () => {\n cancelAnimationFrame(id)\n opener?.focus?.()\n }\n }, [open])\n\n const setRef = (node: HTMLDivElement | null) => {\n rootRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }\n\n // ── actions ──────────────────────────────────────────────────────────────────────────────────\n const syncQuarter = () => {\n const s = core.getSnapshot().state\n if (s) quarter.current = splitRotation(s.rotation).quarter\n }\n const undo = () => {\n stageRef.current?.transition('jump')\n core.undo()\n syncQuarter()\n }\n const redo = () => {\n stageRef.current?.transition('jump')\n core.redo()\n syncQuarter()\n }\n const revert = () => {\n stageRef.current?.transition('jump')\n core.revert()\n syncQuarter()\n }\n const doRotateLeft = () => {\n if (!state || !size) return\n stageRef.current?.transition('rotate')\n quarter.current = normalizeAngle(quarter.current - Math.PI / 2)\n core.setState(rotateLeft(state, size))\n }\n const doFlip = () => {\n if (!state || !size) return\n stageRef.current?.transition('flip')\n quarter.current = normalizeAngle(-quarter.current)\n core.setState(flipHorizontal(state, size))\n }\n\n const close = useCallback(() => onClose(), [onClose])\n // ✕ / Escape close straight away — unsaved edits are dropped (no confirmation)\n const requestClose = () => {\n if (!processing) close()\n }\n const done = async () => {\n if (!state || processing) return\n setProcessing(true)\n setProcessError(false)\n try {\n const result = await core.process()\n onProcess?.(result)\n close()\n } catch {\n setProcessError(true)\n } finally {\n setProcessing(false)\n }\n }\n\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n // the consumer's handler runs first and can opt out with preventDefault (its own shortcuts win)\n onKeyDownProp?.(e)\n if (e.defaultPrevented) return\n const mod = e.metaKey || e.ctrlKey\n if (mod && e.key.toLowerCase() === 'z') {\n e.preventDefault()\n if (e.shiftKey) redo()\n else undo()\n return\n }\n if (mod && e.key.toLowerCase() === 'y') {\n e.preventDefault()\n redo()\n return\n }\n if (e.key !== 'Tab' || !rootRef.current) return\n // trap Tab inside the editor\n const els = [...rootRef.current.querySelectorAll<HTMLElement>(FOCUSABLE)].filter(\n (el) => el.offsetParent !== null,\n )\n if (els.length === 0) return\n const first = els[0]\n const last = els[els.length - 1]\n if (\n e.shiftKey &&\n (document.activeElement === first || document.activeElement === rootRef.current)\n ) {\n e.preventDefault()\n last.focus()\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault()\n first.focus()\n }\n }\n\n // ── view zoom (Filter / Finetune) ────────────────────────────────────────────────────────────\n const zoomStep = (dir: 1 | -1) => {\n const z = effectiveZoom\n const next =\n dir > 0\n ? (ZOOM_LEVELS.find((l) => l > z * 1.01) ?? VIEW_ZOOM_MAX)\n : ([...ZOOM_LEVELS].reverse().find((l) => l < z * 0.99) ?? VIEW_ZOOM_MIN)\n setViewZoom(next)\n }\n\n // ── footers ──────────────────────────────────────────────────────────────────────────────────\n const fine = state ? splitRotation(state.rotation, quarter.current).fine / RAD : 0\n /** Apply a Resize pick (from the tool's base state) as a live change. */\n const resizeTo = (pick: { width: number; height: number } | null) => {\n const base = resizeBase.current ?? core.getSnapshot().state\n if (!base) return\n core.preview(applyResize(base, pick))\n resizeOwn.current = core.getSnapshot().state\n }\n\n let footer: ReactNode = null\n if (state && size) {\n if (ui.util === 'crop') {\n footer = (\n <>\n {ui.cropTab === 'rotation' ? (\n <RulerSlider\n key=\"rotation\"\n aria-label={t('imageEditor.rotation')}\n min={-45}\n max={45}\n step={0.1}\n tickStep={1}\n majorEvery={5}\n snapThreshold={0.6}\n value={Number(fine.toFixed(1))}\n format={(v) => `${Number(v.toFixed(1))}°`}\n onInput={(v) => {\n const s = core.getSnapshot().state\n if (!s) return\n rotationBase.current ??= s\n core.preview(rotateTo(rotationBase.current, quarter.current + v * RAD, size))\n }}\n onChange={(v) => {\n const base = rotationBase.current ?? core.getSnapshot().state\n rotationBase.current = null\n if (!base) return\n core.preview(rotateTo(base, quarter.current + v * RAD, size))\n core.commit()\n }}\n />\n ) : (\n <RulerSlider\n key=\"scale\"\n aria-label={t('imageEditor.scale')}\n min={100}\n max={MAX_CROP_ZOOM * 100}\n step={1}\n tickStep={10}\n majorEvery={5}\n snapPoints={[100]}\n snapThreshold={4}\n resetValue={100}\n value={Math.round(zoomOf(state, size) * 100)}\n format={(v) => `${Math.round(v)}%`}\n onInput={(v) => {\n const s = core.getSnapshot().state\n if (s) core.preview(zoomTo(s, v / 100, size))\n }}\n onChange={(v) => {\n const s = core.getSnapshot().state\n if (!s) return\n core.preview(zoomTo(s, v / 100, size))\n core.commit()\n }}\n />\n )}\n <SegmentedTabs\n label={t('imageEditor.crop')}\n value={ui.cropTab}\n options={[\n { id: 'rotation', label: t('imageEditor.rotation') },\n { id: 'scale', label: t('imageEditor.scale') },\n ]}\n onChange={(cropTab) => core.setUi({ cropTab })}\n />\n </>\n )\n } else if (ui.util === 'filter' && core.image) {\n footer = (\n <FilterStrip\n image={core.image.image}\n size={size}\n state={state}\n onSelect={(id) =>\n core.setState({\n filter: id === 'default' ? null : id,\n colorMatrix: FILTER_MATRICES[id],\n })\n }\n />\n )\n } else if (ui.util === 'resize') {\n footer = (\n <ResizePanel\n max={outputSize(resizeBase.current ?? state)}\n value={finalSize(state)}\n locked={ui.resizeLocked}\n onLockedChange={(resizeLocked) => core.setUi({ resizeLocked })}\n onInput={resizeTo}\n onChange={(pick) => {\n resizeTo(pick)\n core.commit()\n }}\n />\n )\n } else if (ui.util === 'redact') {\n const redact = state.redact\n footer = (\n <>\n <RulerSlider\n key={redact.effect}\n aria-label={t(`imageEditor.redact.${redact.effect}` as MessageKey)}\n min={0}\n max={100}\n step={1}\n // 40 ticks — the same length as the Finetune ruler\n tickStep={2.5}\n majorEvery={4}\n // no snapping — the small values are the useful ones here\n snapThreshold={0}\n value={redact.amount}\n format={(v) => String(Math.round(v))}\n onInput={(amount) => core.preview({ redact: { ...redact, amount } })}\n onChange={(amount) => {\n core.preview({ redact: { ...redact, amount } })\n core.commit()\n }}\n />\n <SegmentedTabs\n label={t('imageEditor.redact')}\n value={redact.effect}\n options={REDACT_EFFECTS.map((id) => ({\n id,\n label: t(`imageEditor.redact.${id}` as MessageKey),\n }))}\n onChange={(effect: ImageRedactEffect) =>\n core.setState({ redact: { ...redact, effect } })\n }\n />\n </>\n )\n } else if (ui.util === 'finetune') {\n const tab = ui.finetuneTab\n footer = (\n <>\n <RulerSlider\n key={tab}\n aria-label={t(`imageEditor.finetune.${tab}` as MessageKey)}\n min={-100}\n max={100}\n step={1}\n tickStep={5}\n majorEvery={4}\n snapThreshold={3}\n value={state.finetune[tab]}\n format={(v) => String(Math.round(v))}\n onInput={(v) => {\n const s = core.getSnapshot().state\n if (s) core.preview({ finetune: { ...s.finetune, [tab]: v } })\n }}\n onChange={(v) => {\n const s = core.getSnapshot().state\n if (!s) return\n core.preview({ finetune: { ...s.finetune, [tab]: v } })\n core.commit()\n }}\n />\n <SegmentedTabs\n label={t('imageEditor.finetune')}\n value={tab}\n options={FINETUNE_IDS.map((id) => ({\n id,\n label: t(`imageEditor.finetune.${id}` as MessageKey),\n dot: state.finetune[id] !== 0,\n }))}\n onChange={(finetuneTab: ImageFinetuneId) => core.setUi({ finetuneTab })}\n />\n </>\n )\n }\n }\n\n const ready = status === 'ready' && !!state\n const showZoom = ready && ui.util !== 'crop'\n return (\n <Overlay\n open={open}\n onClose={requestClose}\n closeOnBackdrop={false}\n dim={0}\n className={styles.overlay}\n >\n <div\n ref={setRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t('imageEditor.title')}\n tabIndex={-1}\n className={clsx(styles.editor, className)}\n data-part=\"editor\"\n onKeyDown={onKeyDown}\n {...props}\n >\n {/* the canvas fills the whole editor — the image runs behind the header, tools and footer */}\n <EditorStage\n ref={stageRef}\n core={core}\n snapshot={snap}\n cropAspectRatio={cropAspectRatio}\n viewZoom={ui.util === 'crop' ? null : viewZoom}\n onViewZoom={setViewZoom}\n onZoomReport={setEffectiveZoom}\n areaRef={areaRef}\n />\n {/* ── header ─────────────────────────────────────────────────────────────────────── */}\n <header className={styles.header} data-part=\"header\">\n <div className={styles.headerStart}>\n <div className={styles.group}>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.close')}\n title={t('imageEditor.close')}\n onClick={requestClose}\n >\n <Icon name=\"Close\" className={styles.closeIcon} />\n </IconButton>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.revert')}\n title={t('imageEditor.revert')}\n disabled={!snap.canRevert}\n onClick={revert}\n >\n <Icon name=\"ReverseTimeArrow\" />\n </IconButton>\n </div>\n </div>\n <div className={styles.headerCenter}>\n <div className={styles.group}>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.undo')}\n title={t('imageEditor.undo')}\n disabled={!snap.canUndo}\n onClick={undo}\n >\n <Icon name=\"UndoArrow\" />\n </IconButton>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.redo')}\n title={t('imageEditor.redo')}\n disabled={!snap.canRedo}\n onClick={redo}\n >\n <Icon name=\"RedoArrow\" />\n </IconButton>\n </div>\n {/* the Crop view's zoom is set by its own rules (fit / real size / enlarged when tiny) — shown,\n not driven from here (the Scale ruler and a pinch zoom the image itself) */}\n {ready && ui.util === 'crop' && (\n <div className={clsx(styles.group, styles.fadeIn)}>\n <span\n className={clsx(styles.zoomLabel, styles.zoomReadout)}\n role=\"status\"\n aria-label={t('imageEditor.zoom')}\n >\n {Math.round(effectiveZoom * 100)}%\n </span>\n </div>\n )}\n {showZoom && (\n <div className={clsx(styles.group, styles.fadeIn)}>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.zoomOut')}\n title={t('imageEditor.zoomOut')}\n disabled={effectiveZoom <= VIEW_ZOOM_MIN * 1.01}\n onClick={() => zoomStep(-1)}\n >\n <Icon name=\"Minus\" />\n </IconButton>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <button\n type=\"button\"\n className={styles.zoomLabel}\n aria-label={t('imageEditor.zoom')}\n title={t('imageEditor.zoomFit')}\n onClick={() => setViewZoom(null)}\n >\n {Math.round(effectiveZoom * 100)}%\n </button>\n <span className={styles.groupDivider} aria-hidden=\"true\" />\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n aria-label={t('imageEditor.zoomIn')}\n title={t('imageEditor.zoomIn')}\n disabled={effectiveZoom >= VIEW_ZOOM_MAX * 0.99}\n onClick={() => zoomStep(1)}\n >\n <Icon name=\"Add\" />\n </IconButton>\n </div>\n )}\n </div>\n <div className={styles.headerEnd}>\n {/* Done — the primary action: a solid accent circle, the size of the other header pills (the\n whole circle is the hit area) */}\n <IconButton\n variant=\"contained\"\n color=\"accent\"\n size=\"sm\"\n loading={processing}\n disabled={!ready}\n aria-label={t('imageEditor.done')}\n title={t('imageEditor.done')}\n onClick={done}\n className={styles.done}\n >\n <Icon name=\"CheckMarkTick\" />\n </IconButton>\n </div>\n </header>\n\n {/* ── main ───────────────────────────────────────────────────────────────────────── */}\n <div className={styles.main} data-part=\"main\">\n <nav className={styles.nav} data-part=\"nav\">\n <div\n role=\"tablist\"\n aria-label={t('imageEditor.tools')}\n aria-orientation=\"vertical\"\n className={styles.navList}\n onKeyDown={(e) => {\n const i = TOOLS.findIndex((tool) => tool.id === ui.util)\n const next =\n e.key === 'ArrowDown' || e.key === 'ArrowRight'\n ? TOOLS[(i + 1) % TOOLS.length]\n : e.key === 'ArrowUp' || e.key === 'ArrowLeft'\n ? TOOLS[(i + TOOLS.length - 1) % TOOLS.length]\n : null\n if (!next) return\n e.preventDefault()\n core.setUi({ util: next.id })\n ;(e.currentTarget.querySelector(`[data-util=\"${next.id}\"]`) as HTMLElement)?.focus()\n }}\n >\n {TOOLS.map((tool) => {\n const active = ui.util === tool.id\n return (\n <button\n key={tool.id}\n type=\"button\"\n role=\"tab\"\n id={`tz-ie-tab-${tool.id}`}\n aria-selected={active}\n aria-controls=\"tz-ie-panel\"\n tabIndex={active ? 0 : -1}\n title={t(`imageEditor.${tool.id}` as MessageKey)}\n className={clsx(styles.tool, active && styles.toolActive)}\n data-util={tool.id}\n onClick={() => core.setUi({ util: tool.id })}\n >\n <Icon name={tool.icon} size=\"sm\" />\n <span className={styles.toolLabel}>\n {t(`imageEditor.${tool.id}` as MessageKey)}\n </span>\n </button>\n )\n })}\n </div>\n </nav>\n\n <section\n className={styles.stage}\n id=\"tz-ie-panel\"\n role=\"tabpanel\"\n aria-labelledby={`tz-ie-tab-${ui.util}`}\n data-part=\"stage\"\n data-util={ui.util}\n >\n <div className={styles.toolbar} data-part=\"toolbar\">\n {ready && ui.util === 'crop' && (\n <div key=\"crop-toolbar\" className={clsx(styles.toolbarRow, styles.fadeIn)}>\n <Button\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n startIcon={<Icon name=\"RotateLeft\" />}\n title={t('imageEditor.rotateLeft')}\n aria-label={t('imageEditor.rotateLeft')}\n onClick={doRotateLeft}\n className={styles.toolbarIconOnPhone}\n >\n <span className={styles.toolbarLabel}>{t('imageEditor.rotateLeft')}</span>\n </Button>\n <Button\n variant=\"text\"\n color=\"primary\"\n size=\"sm\"\n startIcon={<Icon name=\"FlipHorizontal\" />}\n title={t('imageEditor.flipHorizontal')}\n aria-label={t('imageEditor.flipHorizontal')}\n onClick={doFlip}\n className={styles.toolbarIconOnPhone}\n >\n <span className={styles.toolbarLabel}>{t('imageEditor.flipHorizontal')}</span>\n </Button>\n {/* a ratio-locked editor (`cropAspectRatio`) has no shape to pick */}\n {!cropAspectRatio && state && (\n <CropShapeMenu\n ratio={state.cropRatio}\n options={cropRatioOptions ?? DEFAULT_CROP_RATIOS}\n onChange={(ratio) => {\n const s = core.getSnapshot().state\n if (!s || !size) return\n stageRef.current?.transition('jump')\n core.setState(setCropRatio(s, ratio, size))\n }}\n />\n )}\n </div>\n )}\n </div>\n\n {/* the free area the crop is laid out in (the canvas itself spans the whole editor) */}\n <div ref={areaRef} className={styles.canvasArea} data-part=\"area\">\n {status === 'loading' && (\n <div className={styles.status} role=\"status\">\n <Loader size=\"lg\" />\n <span>{t('imageEditor.loading')}</span>\n </div>\n )}\n {status === 'error' && (\n <div className={styles.status} role=\"alert\">\n <Icon name=\"Gallery\" size=\"lg\" />\n <span>{t('imageEditor.loadError')}</span>\n </div>\n )}\n {processError && (\n <div className={styles.toastError} role=\"alert\">\n {t('imageEditor.processError')}\n </div>\n )}\n </div>\n\n <div className={styles.footer} data-part=\"footer\">\n <div key={ui.util} className={clsx(styles.footerInner, styles.fadeIn)}>\n {footer}\n </div>\n </div>\n </section>\n </div>\n </div>\n </Overlay>\n )\n})\n\n/** A small segmented tab list (the Rotation | Scale and the finetune adjustment tabs). */\nfunction SegmentedTabs<T extends string>({\n label,\n value,\n options,\n onChange,\n}: {\n label: string\n value: T\n options: { id: T; label: string; dot?: boolean }[]\n onChange: (id: T) => void\n}) {\n const listRef = useRef<HTMLDivElement>(null)\n // keep the active tab in view when the row scrolls (phones)\n useEffect(() => {\n listRef.current\n ?.querySelector<HTMLElement>(`[data-tab=\"${value}\"]`)\n ?.scrollIntoView?.({ block: 'nearest', inline: 'nearest', behavior: 'smooth' })\n }, [value])\n return (\n <div\n ref={listRef}\n role=\"tablist\"\n aria-label={label}\n className={styles.tabs}\n data-part=\"tabs\"\n onKeyDown={(e) => {\n const i = options.findIndex((o) => o.id === value)\n const step = e.key === 'ArrowRight' ? 1 : e.key === 'ArrowLeft' ? -1 : 0\n if (!step) return\n e.preventDefault()\n const next = options[(i + step + options.length) % options.length]\n onChange(next.id)\n ;(e.currentTarget.querySelector(`[data-tab=\"${next.id}\"]`) as HTMLElement)?.focus()\n }}\n >\n {options.map((o) => (\n <button\n key={o.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={o.id === value}\n tabIndex={o.id === value ? 0 : -1}\n className={clsx(styles.tab, o.id === value && styles.tabActive)}\n data-tab={o.id}\n onClick={() => onChange(o.id)}\n >\n {o.label}\n {o.dot && <span className={styles.tabDot} aria-hidden=\"true\" />}\n </button>\n ))}\n </div>\n )\n}\n"],"names":["IDENTITY_MATRIX","LR","LG","LB","multiplyMatrix","a","b","out","row","col","sum","k","composeMatrices","matrices","acc","m","isIdentityMatrix","v","i","brightnessMatrix","contrastMatrix","c","o","saturationMatrix","s","channelMatrix","r","g","or","og","ob","levelsMatrix","low","high","SEPIA_MATRIX","FILTER_GROUPS","MONO","FILTER_MATRICES","FINETUNE_IDS","ZERO_FINETUNE","finetuneParam","finetuneMatrix","f","t","combinedMatrix","colorMatrix","finetune","QUARTER","EPS","rotate","x","y","theta","halfExtents","w","h","cropCenter","crop","coverScale","size","ex","ey","cropAnchor","state","kx","ky","ux","uy","clampAnchor","lx","ly","cropAt","u","dx","dy","coversCrop","corners","tol","qx","qy","fitState","outputSize","finalSize","resizedCrop","target","aspect","width","height","applyResize","base","pick","proportional","next","full","resize","syncResize","prev","before","after","initialCrop","aspectRatio","defaultState","splitRotation","quarterHint","turns","quarter","fine","normalizeAngle","rotateTo","clamped","rotateLeft","cx","cy","flipHorizontal","zoomOf","MAX_CROP_ZOOM","zoomTo","zoom","panBy","moved","setCropRatio","ratio","resizeCrop","start","handle","minSize","left","top","right","bottom","hasN","hasS","hasW","hasE","fits","furthest","horizontal","from","vertical","viaX","viaY","miss","to","dest","lo","hi","mid","lerpRect","normalizeState","VIGNETTE_STRENGTH","smoothstep","e0","e1","vignetteFalloff","nx","ny","applyColorOps","data","p","blur","toCrop","invGamma","useGamma","useClarity","useVignette","r0","g0","b0","br","bg","bb","ba","mr","mg","mb","px","py","boxBlur","src","radius","pass","blurLine","rad","lines","len","stride","span","idx","inn","CLARITY_RADIUS","canvasOf","decodeBlob","blob","url","decodeUrl","crossOrigin","resolve","reject","img","sizeOf","loadImage","image","type","res","downscale","source","maxSide","ctx","blurredCopy","resolveOutputType","requested","input","IDENTITY_AFFINE","translate","scaleAffine","sx","sy","rotateAffine","multiplyAffine","chain","ts","invertAffine","d","e","det","applyAffine","REDACT_MAX","redactRadius","effect","_a","_b","pixelGrid","block","BLUR_WORK_RADIUS","blurredSmall","work","blurredFull","pixelateCanvas","canvas","cols","rows","small","sctx","pixelatedCopy","stageOrigin","stage","sourceToPlane","planeToScreen","view","flip","ox","oy","planeToCrop","sceneAffines","deviceToPlane","toUV","fitView","padding","VERTEX","FRAGMENT","WebGLRenderer","gl","buffer","pos","name","opts","compile","sh","program","tex","unit","mipmap","isGL2","dr","dg","db","cm","rowCount","loseContext","colorParams","hasColorOps","canvas2d","render2D","texture","textureSize","blurSize","drawThrough","fromCrop","colorPass2D","blurData","bctx","MAX_SIDE","MAX_AREA","toBlob","quality","renderOutput","ow","oh","params","colorPassTiled","glCanvas","tileSize","tile","tctx","ty","tx","tw","th","toBlurUV","MAX_HISTORY","same","sameSize","clone","ImageEditorCore","fn","event","cb","set","payload","options","token","loaded","init","merged","error","cur","anchor","ui","result","createImageEditor","prefersReducedMotion","springTo","onFrame","stiffness","damping","onDone","noop","last","raf","cancelled","step","now","dt","xi","PAD_CROP","PAD_VIEW","PREVIEW_MAX","CROP_VIEW_MIN_SIDE","BLUR_PREVIEW_MAX","CROP_DIM","backgroundRgb","el","raw","MIN_CROP_SCREEN","HANDLES","viewToVector","vectorToView","EditorStage","forwardRef","core","snapshot","cropAspectRatio","viewZoom","onViewZoom","onZoomReport","areaRef","ref","mode","useColorMode","util","viewportRef","useRef","canvasRef","setStage","useState","setView","viewRef","pan","setPan","interacting","setInteracting","nonce","setNonce","frozen","pending","stopSpring","gesture","pointers","wheelCommit","useEffect","measure","symmetricArea","measureRef","ro","useLayoutEffect","renderer","setRenderer","detail","coarseWidth","redactEffect","redactAmount","setSource","smooth","useMemo","area","fitted","real","handleable","fit","scale","prevUtil","springing","lastLayout","startSpring","surround","setSurround","surroundRef","layoutOnly","prevResize","resized","_c","prevTarget","sameTarget","kind","_d","shown","affines","pixel","useImperativeHandle","onViewZoomRef","pinchDistance","onPointerDown","onPointerMove","clampZoom","onPointerUp","n","onWheel","zoomGesture","safariGesture","factor","current","live","onStart","sz","onChange","onEnd","cropBox","x0","y0","x1","y1","sceneTransform","jsxs","clsx","styles","jsx","inset","VIEW_ZOOM_MIN","VIEW_ZOOM_MAX","z","DEFAULT_CROP_RATIOS","flipLabel","label","ShapePreview","CropShapeMenu","useT","open","setOpen","portraitPref","setPortraitPref","portrait","setOrientation","toPortrait","Dropdown","Button","Icon","ListItem","THUMB","renderThumbs","dpr","id","FilterStrip","onSelect","scrollerRef","thumbs","setThumbs","edges","setEdges","active","key","updateEdges","drag","momentum","ev","ids","onKeyDown","group","gi","PRESETS","clampSide","max","ResizePanel","value","locked","onLockedChange","onInput","draft","setDraft","liveRatio","heldRatio","side","normalize","edit","digits","commit","presetActive","TICK_GAP","RulerSlider","min","keyStep","snapPoints","snapThreshold","tickStep","majorEvery","resetValue","format","ariaLabel","className","pxPerUnit","inertia","wheelTimer","latestOnChange","commitValue","settle","snap","emitInput","cap","vel","tick","delta","big","reset","ticks","_","tickValue","TOOLS","REDACT_EFFECTS","ZOOM_LEVELS","FOCUSABLE","RAD","ImageEditor","initialState","cropRatioOptions","outputType","outputQuality","onLoad","onUpdate","onProcess","onClose","onKeyDownProp","props","useSyncExternalStore","status","stageRef","rootRef","setViewZoom","effectiveZoom","setEffectiveZoom","processing","setProcessing","processError","setProcessError","rotationBase","resizeBase","resizeOwn","cbs","offs","off","onGesture","gestures","opener","setRef","node","syncQuarter","undo","redo","revert","doRotateLeft","doFlip","close","useCallback","requestClose","done","mod","els","first","zoomStep","dir","l","resizeTo","footer","Fragment","SegmentedTabs","cropTab","resizeLocked","redact","amount","tab","finetuneTab","ready","showZoom","Overlay","IconButton","tool","Loader","listRef"],"mappings":"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"}
|