@ryuzaki13/react-foundation-ui 1.0.23 → 1.1.1
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/README.md +86 -0
- package/dist/chunks/ImageViewerRuntime-RN49by8Y.js +225 -0
- package/dist/chunks/ImageViewerRuntime-RN49by8Y.js.map +1 -0
- package/dist/image/index.d.ts +2 -0
- package/dist/image/index.d.ts.map +1 -1
- package/dist/image/index.js +116 -103
- package/dist/image/index.js.map +1 -1
- package/dist/image/lib/buildImageViewerSlides.d.ts +8 -0
- package/dist/image/lib/buildImageViewerSlides.d.ts.map +1 -0
- package/dist/image/lib/resolveImageViewerLabels.d.ts +24 -0
- package/dist/image/lib/resolveImageViewerLabels.d.ts.map +1 -0
- package/dist/image/model/imageViewerTypes.d.ts +70 -0
- package/dist/image/model/imageViewerTypes.d.ts.map +1 -0
- package/dist/image/ui/ImageViewer.d.ts +12 -0
- package/dist/image/ui/ImageViewer.d.ts.map +1 -0
- package/dist/image/ui/ImageViewerRuntime.d.ts +11 -0
- package/dist/image/ui/ImageViewerRuntime.d.ts.map +1 -0
- package/dist/styles.css +1 -1
- package/package.json +6 -1
- package/src/styles/config/_index.scss +1 -0
- package/storybook-static/assets/{Badge-Dk1ppt6h.js → Badge-D4ZNwyJI.js} +1 -1
- package/storybook-static/assets/{Badge.stories-DGed-OBQ.js → Badge.stories-QbQZ3Lun.js} +1 -1
- package/storybook-static/assets/{Button-c4nDxtrg.js → Button-CO9qTYjf.js} +1 -1
- package/storybook-static/assets/{Button-BrdeQlDt.js → Button-dAzTo4v8.js} +1 -1
- package/storybook-static/assets/{Button.stories-CYjvIvUW.js → Button.stories-wcPcMM2N.js} +1 -1
- package/storybook-static/assets/{CheckBox-rqQjSYV-.js → CheckBox-BuWKFvO2.js} +1 -1
- package/storybook-static/assets/{CheckBox-6Qr3jWMy.js → CheckBox-IVs8Ft1J.js} +1 -1
- package/storybook-static/assets/{CheckBox.stories-Q78_xCB-.js → CheckBox.stories-B2P4Xgjx.js} +1 -1
- package/storybook-static/assets/{Color-KMSTOMOX-BMBFTpCU.js → Color-KMSTOMOX-DO11DnAB.js} +1 -1
- package/storybook-static/assets/{ContextMenu-Dy6qjxlr.js → ContextMenu-YIVSJPGZ.js} +1 -1
- package/storybook-static/assets/{ContextMenu.stories-ArVPg2Iz.js → ContextMenu.stories-pPfA4c51.js} +1 -1
- package/storybook-static/assets/{DateInput-eu7DXgSU.js → DateInput-CJjcOU3w.js} +1 -1
- package/storybook-static/assets/{DateInput-Dk1l_hxJ.js → DateInput-CMk0Q3-1.js} +1 -1
- package/storybook-static/assets/{DateInput.stories-GCltuReT.js → DateInput.stories-BeYqSTLP.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-2dHNAnUX.js → DateRangePresetSelect-CprGmjzY.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-aiAJs_u-.js → DateRangePresetSelect-HobGj82_.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect.stories-BXPIK_Co.js → DateRangePresetSelect.stories-C0C1Z7Ef.js} +1 -1
- package/storybook-static/assets/{Detail-C-0qKqgn.js → Detail-7DE7B2fS.js} +1 -1
- package/storybook-static/assets/{Detail.stories-BpD2YoZq.js → Detail.stories-BI42UERO.js} +1 -1
- package/storybook-static/assets/{Dialog-BHOqDS4r.js → Dialog-CPl9ePpk.js} +1 -1
- package/storybook-static/assets/{Dialog.stories-DbY2IVcJ.js → Dialog.stories-DLlXkr6b.js} +1 -1
- package/storybook-static/assets/{Disclosure-BIS573Xf.js → Disclosure-DiE1KhPu.js} +1 -1
- package/storybook-static/assets/{Disclosure.stories-BEXgpOqT.js → Disclosure.stories-DZj3PP0E.js} +1 -1
- package/storybook-static/assets/{DocsRenderer-JROSPFPF-DBLxlIku.js → DocsRenderer-JROSPFPF-BarB-6yi.js} +2 -2
- package/storybook-static/assets/{DropZone-DCOH76_B.js → DropZone-BH0RZWxI.js} +1 -1
- package/storybook-static/assets/{DropZone.stories-D1SI6gcY.js → DropZone.stories-CMgWL5O8.js} +1 -1
- package/storybook-static/assets/{DropdownMenu-mb1Hg5Gl.js → DropdownMenu-Bg9OjuHI.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel.stories-CXJMi0D0.js → ExpandableActionPanel.stories-Bs5nj5tL.js} +2 -2
- package/storybook-static/assets/{Flex-aMhUlmFA.js → Flex-B7YhSwT5.js} +1 -1
- package/storybook-static/assets/{Flex-D1ZBJLmP.js → Flex-DTualGXt.js} +1 -1
- package/storybook-static/assets/{Flex.stories-Cq9hTA2s.js → Flex.stories-CJZWUeDx.js} +1 -1
- package/storybook-static/assets/{Grid-DrwSe074.js → Grid-D3pn3Bv6.js} +1 -1
- package/storybook-static/assets/{Grid-D4xblGva.js → Grid-NUIGfEZg.js} +1 -1
- package/storybook-static/assets/{Grid.stories-CsQlxLGT.js → Grid.stories-BU3qiQ_o.js} +1 -1
- package/storybook-static/assets/{ImageCropper.stories-Da0fJQ1n.js → ImageCropper.stories-B8LIeZot.js} +1 -1
- package/storybook-static/assets/{ImageRenderer-dXWklz9J.js → ImageRenderer-D6m0TXv1.js} +1 -1
- package/storybook-static/assets/{ImageRenderer.stories-C2l796Hd.js → ImageRenderer.stories-Bwv7-mmo.js} +1 -1
- package/storybook-static/assets/{ImageView.stories-Cee_V0zr.js → ImageView.stories-B2bnEYTW.js} +1 -1
- package/storybook-static/assets/ImageViewer-imFO-FH3.css +1 -0
- package/storybook-static/assets/ImageViewer.stories-DaMTLSzl.js +72 -0
- package/storybook-static/assets/ImageViewerRuntime-CRmlrtpL.css +1 -0
- package/storybook-static/assets/ImageViewerRuntime-nB82ciX9.js +51 -0
- package/storybook-static/assets/{Input-DoTXagjB.js → Input-NjYnjmpA.js} +1 -1
- package/storybook-static/assets/Input-XmHlbTYH.js +3 -0
- package/storybook-static/assets/{Input.stories-mPAKrIP1.js → Input.stories-B2NJY4s9.js} +1 -1
- package/storybook-static/assets/{InputDateTime-BgIJNCpv.js → InputDateTime-DYx7fZqV.js} +1 -1
- package/storybook-static/assets/{InputDateTime.stories-Ck0MCRBJ.js → InputDateTime.stories-BP70hMlC.js} +1 -1
- package/storybook-static/assets/{InputFile-BZqKG2Zr.js → InputFile-cDPgb3yd.js} +1 -1
- package/storybook-static/assets/{InputFile.stories-QbTuArh1.js → InputFile.stories-B8l1oAAa.js} +1 -1
- package/storybook-static/assets/{InputFiles-BUoDhUef.js → InputFiles-C54yHWFW.js} +1 -1
- package/storybook-static/assets/{InputFiles-ChhwyB9P.js → InputFiles-RV5Ldp6x.js} +1 -1
- package/storybook-static/assets/{InputFiles.stories-PD0pr8y6.js → InputFiles.stories-DBpBymQR.js} +1 -1
- package/storybook-static/assets/{InputImage-YxBujSop.js → InputImage-CCz9j5pF.js} +1 -1
- package/storybook-static/assets/{InputImage.stories-CHjyI709.js → InputImage.stories-_p9hjvIE.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-DJT0cL8d.js → LayoutPicker-rkC7rVNj.js} +1 -1
- package/storybook-static/assets/{LayoutPicker.stories-DvTvYmfw.js → LayoutPicker.stories-Dua-laJ2.js} +1 -1
- package/storybook-static/assets/{Listbox-D7w7HJNg.js → Listbox-C9gRtOeO.js} +1 -1
- package/storybook-static/assets/{Listbox.stories-D4EMWR6l.js → Listbox.stories-m8Brn-ay.js} +1 -1
- package/storybook-static/assets/{Modal-BCn0aKBf.js → Modal-D62mL35g.js} +1 -1
- package/storybook-static/assets/{Modal.stories-BgnMPuDy.js → Modal.stories-DOU0t6f-.js} +1 -1
- package/storybook-static/assets/{MultiSelect-D7N8euwu.js → MultiSelect-C5W7r_IH.js} +1 -1
- package/storybook-static/assets/{MultiSelect-CZW1VSbD.js → MultiSelect-LhGz99f4.js} +1 -1
- package/storybook-static/assets/{MultiSelect.stories-DV9nyDoE.js → MultiSelect.stories-DcHKp4JR.js} +1 -1
- package/storybook-static/assets/{NotificationsHost-DJILaEyi.js → NotificationsHost-BSH5jCG2.js} +1 -1
- package/storybook-static/assets/{NotificationsHost.stories-DlO0kPbm.js → NotificationsHost.stories-DTM5-qkf.js} +2 -2
- package/storybook-static/assets/{ODataMultiSelect-C-DKYFLx.js → ODataMultiSelect-C2S7qyv5.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect.stories-DypA5OPM.js → ODataMultiSelect.stories-DOzE_OKZ.js} +1 -1
- package/storybook-static/assets/{ODataSelect-CMrLfCwp.js → ODataSelect-BG7NWPTV.js} +1 -1
- package/storybook-static/assets/{ODataSelect-ANgknc8h.js → ODataSelect-lT0xOKvb.js} +1 -1
- package/storybook-static/assets/{ODataSelect.stories-icXU3Kk-.js → ODataSelect.stories-CKBvtx-H.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect-C6yg6DFE.js → ODataTreeMultiSelect-u8tiVTCb.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect.stories-CT_tBJph.js → ODataTreeMultiSelect.stories-CzH4V42Q.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect-hiY9TK6F.js → ODataTreeSelect-CwOHUVab.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect.stories-DPNG2-gB.js → ODataTreeSelect.stories-DjVMiCJ1.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-5CQZq007.js → PeriodSelect-BFGqQf0k.js} +1 -1
- package/storybook-static/assets/{PeriodSelect.stories-DuwM__eX.js → PeriodSelect.stories-BG6WXQ18.js} +1 -1
- package/storybook-static/assets/{Popover-BuB6NaNL.js → Popover-OlRhMSrF.js} +1 -1
- package/storybook-static/assets/{Popover.stories-DNHTB9O2.js → Popover.stories-C5FOSas_.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-C6ke1QJN.js → PresetRangeDateInput-Dtisg-hx.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput.stories-BiFR6FF_.js → PresetRangeDateInput.stories-DKW4o_cP.js} +1 -1
- package/storybook-static/assets/{RadioButton-bmKQ4B96.js → RadioButton-B6Kj1uHa.js} +1 -1
- package/storybook-static/assets/{RadioButton.stories-CZatWIEO.js → RadioButton.stories-0YupGfXc.js} +1 -1
- package/storybook-static/assets/{RadioGroup-diPPm8OV.js → RadioGroup-b972E4de.js} +1 -1
- package/storybook-static/assets/{RadioGroup-Vnr3qZKk.js → RadioGroup-g9jHDZ1a.js} +1 -1
- package/storybook-static/assets/{RadioGroup.stories-BY_ORcvQ.js → RadioGroup.stories-CncOV2Km.js} +1 -1
- package/storybook-static/assets/{Select-Cq66yRYB.js → Select-Deq1B8d4.js} +1 -1
- package/storybook-static/assets/Select-V5lTi2fc.js +12 -0
- package/storybook-static/assets/{Select.stories-CevvmTWz.js → Select.stories-ehFtiqH9.js} +1 -1
- package/storybook-static/assets/{SelectOptionContent-C1-duJ6s.js → SelectOptionContent-CCp1Zygd.js} +1 -1
- package/storybook-static/assets/{SerializableSelect-C6jj7wLf.js → SerializableSelect-CvMVlLei.js} +1 -1
- package/storybook-static/assets/{SerializableSelect-CnwfEnur.js → SerializableSelect-IyNh3eLS.js} +1 -1
- package/storybook-static/assets/{SerializableSelect.stories-DOTdXeIP.js → SerializableSelect.stories-wcj4bFZq.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-BtSG1SZF.js → SingleDateTimeInput-DyLXAP7B.js} +1 -1
- package/storybook-static/assets/SingleDateTimeInput.stories-WvQxqelt.js +78 -0
- package/storybook-static/assets/{Slider-pb7TgPmP.js → Slider-Cp8CtB-I.js} +1 -1
- package/storybook-static/assets/{Slider.stories-Cj9sU7k1.js → Slider.stories-BsIcLc-d.js} +1 -1
- package/storybook-static/assets/{SliderInput-Dp4r4RqZ.js → SliderInput-4jPJ7yM1.js} +1 -1
- package/storybook-static/assets/{SliderInput.stories-DKV9C_mb.js → SliderInput.stories-DPK4tJ2q.js} +1 -1
- package/storybook-static/assets/{Sortable-BbVzA3mH.js → Sortable-CAX_xvIn.js} +1 -1
- package/storybook-static/assets/{Sortable.stories-nttQ0wQV.js → Sortable.stories-Dn2kDyA2.js} +1 -1
- package/storybook-static/assets/{Splitter-DQip0vEb.js → Splitter-Blfeifky.js} +1 -1
- package/storybook-static/assets/{Splitter.stories-B7IdmITM.js → Splitter.stories-k9ZItdL9.js} +1 -1
- package/storybook-static/assets/{StateSelect-BZeQfOZk.js → StateSelect-CSDCsDb8.js} +1 -1
- package/storybook-static/assets/{StateSelect.stories-Cia0oYUX.js → StateSelect.stories-DwdGHqbu.js} +2 -2
- package/storybook-static/assets/{Switch-DzxseHUx.js → Switch-BUhpEhzV.js} +1 -1
- package/storybook-static/assets/Switch.stories-BC2DPnRn.js +26 -0
- package/storybook-static/assets/{Table-lzcaRxDg.js → Table-9XwMCwrN.js} +1 -1
- package/storybook-static/assets/{Table.stories-sckp-lho.js → Table.stories-BYXgzUfU.js} +1 -1
- package/storybook-static/assets/{Tabs-DyBBFEsD.js → Tabs-Bow33W8U.js} +1 -1
- package/storybook-static/assets/{Tabs.stories-C6-sZs4H.js → Tabs.stories-CZT7skiV.js} +1 -1
- package/storybook-static/assets/TagInput.stories-b8xiLHof.js +18 -0
- package/storybook-static/assets/{Textarea-D1fEct22.js → Textarea-DpY7S_ja.js} +1 -1
- package/storybook-static/assets/{Textarea.stories-ByJH2uhT.js → Textarea.stories-Dd223jGP.js} +1 -1
- package/storybook-static/assets/{TimePanel-B5c9MfmC.js → TimePanel-CVg_B6n6.js} +1 -1
- package/storybook-static/assets/{TimePanel.stories-DBgXVhz1.js → TimePanel.stories-BLQ1P0G1.js} +1 -1
- package/storybook-static/assets/{Toggle-CHx3ZZfu.js → Toggle-DFqklqKe.js} +1 -1
- package/storybook-static/assets/{Toggle.stories-g3Eq8oVl.js → Toggle.stories-Dn1ZNjzs.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-CrKusouJ.js → TreeMultiSelect-CUVgAxbI.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-T05Sk9sh.js → TreeMultiSelect-KJZy7baA.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect.stories-C85O7gDN.js → TreeMultiSelect.stories-BwgaL6Xq.js} +1 -1
- package/storybook-static/assets/{TreePickerBase-VJSaTBqo.js → TreePickerBase-pdzKfA0G.js} +2 -2
- package/storybook-static/assets/{TreeSelect-Dw-svVvg.js → TreeSelect-5pb94-io.js} +1 -1
- package/storybook-static/assets/{TreeSelect-DQmAaKsJ.js → TreeSelect-CVwWW2jD.js} +1 -1
- package/storybook-static/assets/{TreeSelect.stories-Bqv2L08v.js → TreeSelect.stories-BYqkPLt1.js} +1 -1
- package/storybook-static/assets/{TreeTable-JJK6sE1o.js → TreeTable-CkBy8VlX.js} +1 -1
- package/storybook-static/assets/{TreeTable.stories-yOu-SM17.js → TreeTable.stories-BXWFw5wG.js} +1 -1
- package/storybook-static/assets/{WithTooltip-7X4HQR7L-Cib98jGG.js → WithTooltip-7X4HQR7L-tzCCckGL.js} +1 -1
- package/storybook-static/assets/{base-table-BbenC81q.js → base-table-J0VmPU8w.js} +1 -1
- package/storybook-static/assets/{blocks-DsN3hykK.js → blocks-BqMyWalM.js} +6 -6
- package/storybook-static/assets/{button-C8nkqC6f.js → button-BOWFIeDh.js} +1 -1
- package/storybook-static/assets/{check-box-BRod99sY.js → check-box-CPBNfroU.js} +1 -1
- package/storybook-static/assets/{chunk-3LY4VQVK-DSSlp6en.js → chunk-3LY4VQVK-cdx-m4dV.js} +1 -1
- package/storybook-static/assets/{chunk-LITCR56V-CB95AMSh.js → chunk-LITCR56V-B9dgggkx.js} +1 -1
- package/storybook-static/assets/{contextMenu-iKy1R_pJ.js → contextMenu-DtwOXbRw.js} +1 -1
- package/storybook-static/assets/{error-ChmbU9Ma.js → error-C-yEsKLJ.js} +1 -1
- package/storybook-static/assets/{flex-CMA-ZjxB.js → flex-Cf2jLP1U.js} +1 -1
- package/storybook-static/assets/{floating-ui.react-BpBaLM_G.js → floating-ui.react-6B4p8HDR.js} +1 -1
- package/storybook-static/assets/formatter-L2YTDE3Q-BEJcUUWn.js +1 -0
- package/storybook-static/assets/{formatters-C0d3JoZj.js → formatters-DXHNQSpS.js} +1 -1
- package/storybook-static/assets/grid-0riWQzPS.js +1 -0
- package/storybook-static/assets/{hooks-BpEcTBvi.js → hooks-Cp3Hd96H.js} +1 -1
- package/storybook-static/assets/{iframe-D90hKkIJ.js → iframe-B1CjCwLr.js} +4 -4
- package/storybook-static/assets/{input-D77vjPVL.js → input-Ciguy4IH.js} +1 -1
- package/storybook-static/assets/lucide-react-DNKi1M4I.js +1 -0
- package/storybook-static/assets/{mdx-react-shim-CdXPOrRW.js → mdx-react-shim-BmHrz8Qy.js} +1 -1
- package/storybook-static/assets/{media-C4dafSHo.js → media-CYiNdyXU.js} +1 -1
- package/storybook-static/assets/misc-C0xWU5l4.js +5 -0
- package/storybook-static/assets/{notifications-Dt8NSgnT.js → notifications-BnIn-1bS.js} +1 -1
- package/storybook-static/assets/{odata-DQSm2H7O.js → odata-CBfXwTuv.js} +1 -1
- package/storybook-static/assets/odata-service-C5AB3b3v.js +1 -0
- package/storybook-static/assets/{odataStoryFixtures-D0p0XtmS.js → odataStoryFixtures-B4Ph79L8.js} +1 -1
- package/storybook-static/assets/{picker-9SOfvJPJ.js → picker-hyCPyMP8.js} +1 -1
- package/storybook-static/assets/{popover-Dph7wJ1_.js → popover-DLIoVp94.js} +1 -1
- package/storybook-static/assets/{preset-select-mubmWRO9.js → preset-select-BjG9VTrg.js} +1 -1
- package/storybook-static/assets/{react-18-CSg0VXTL.js → react-18-Bz7Vh-KR.js} +1 -1
- package/storybook-static/assets/{react-Cr3aZrbF.js → react-D7DXSuVH.js} +1 -1
- package/storybook-static/assets/{react-dom-Iu9X9_7I.js → react-dom-Wlkt-dsb.js} +1 -1
- package/storybook-static/assets/select-C3btTxoQ.js +1 -0
- package/storybook-static/assets/{slider-C8Udy6I7.js → slider-DMChsrbR.js} +1 -1
- package/storybook-static/assets/{sortable-xt2HCdf-.js → sortable-BPfL-XUN.js} +1 -1
- package/storybook-static/assets/{syntaxhighlighter-RTCFPKCB-4Ttp-ccw.js → syntaxhighlighter-RTCFPKCB-BA7fKjuW.js} +1 -1
- package/storybook-static/assets/{text-CwWM1WCX.js → text-9sGnwPB7.js} +1 -1
- package/storybook-static/assets/{theming--foXdFDq.js → theming-4yGRJc-V.js} +1 -1
- package/storybook-static/assets/ui-krJ8_ODv.js +1 -0
- package/storybook-static/assets/{useODataSelectBase-C7f1zxWc.js → useODataSelectBase-CIjzs3rn.js} +1 -1
- package/storybook-static/assets/{useODataTreeData-7hwK6Byp.js → useODataTreeData-BnifkleR.js} +1 -1
- package/storybook-static/assets/{utils-Bg8QclQy.js → utils-BY_HhyoQ.js} +1 -1
- package/storybook-static/iframe.html +1 -1
- package/storybook-static/index.json +1 -1
- package/storybook-static/project.json +1 -1
- package/storybook-static/assets/Input-B6UklXwb.js +0 -3
- package/storybook-static/assets/Select-BxK9yj6_.js +0 -12
- package/storybook-static/assets/SingleDateTimeInput.stories-CSFUpLfK.js +0 -78
- package/storybook-static/assets/Switch.stories-BVAIn4yd.js +0 -26
- package/storybook-static/assets/TagInput.stories-iI1hZ8CY.js +0 -18
- package/storybook-static/assets/formatter-L2YTDE3Q-tZc7M3Ad.js +0 -1
- package/storybook-static/assets/grid-Ck5-5Szv.js +0 -1
- package/storybook-static/assets/lucide-react-ClGevkpS.js +0 -1
- package/storybook-static/assets/misc-yRJvnOkX.js +0 -5
- package/storybook-static/assets/odata-service-CMTV9-cO.js +0 -1
- package/storybook-static/assets/select-DYXb71nn.js +0 -1
- package/storybook-static/assets/ui-BJnukgBU.js +0 -1
package/dist/image/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/image/lib/buildImageSrcSet.ts","../../src/image/lib/buildImageSources.ts","../../src/image/ui/ImageCropper.tsx","../../src/image/ui/ImagePlaceholder.tsx","../../src/image/ui/ImageRenderer.tsx","../../src/image/lib/getImageSelectionKey.ts","../../src/image/model/useImageSelectionState.ts","../../src/image/lib/getImageCropPreviewStyle.ts","../../src/image/ui/ImageSelectionFields.tsx","../../src/image/ui/ImageSelectionModal.tsx","../../src/image/ui/ImageSelectionPanel.tsx","../../src/image/ui/ImageView.tsx"],"sourcesContent":["import { type ImageCandidate } from \"../model/imageTypes\";\n\n/** Собирает валидный srcset из уже разрешённых вызывающим кодом URL вариантов. */\nexport function buildImageSrcSet(candidates: readonly ImageCandidate[]): string {\n\treturn candidates\n\t\t.map((candidate) => (\"width\" in candidate ? `${candidate.src} ${candidate.width}w` : `${candidate.src} ${candidate.density}x`))\n\t\t.join(\", \");\n}\n","import { type ImageSource, type ResponsiveImageSource } from \"../model/imageTypes\";\n\nimport { buildImageSrcSet } from \"./buildImageSrcSet\";\n\n/** Преобразует декларативные наборы кандидатов в готовые source-дескрипторы. */\nexport function buildImageSources(sources: readonly ResponsiveImageSource[] | undefined, defaultSizes?: string): ImageSource[] {\n\treturn (sources ?? [])\n\t\t.map((source) => ({\n\t\t\tsrcSet: buildImageSrcSet(source.candidates),\n\t\t\ttype: source.type,\n\t\t\tsizes: source.sizes ?? defaultSizes\n\t\t}))\n\t\t.filter((source) => source.srcSet.length > 0);\n}\n","import { useCallback, useState } from \"react\";\n\nimport Cropper from \"react-easy-crop\";\n\nimport { type ImageCropArea, type ImageCropperProps, type ImageCropPoint } from \"../model/imageCropTypes\";\n\nconst DEFAULT_CROP: ImageCropPoint = { x: 0, y: 0 };\n\n/**\n * Управляемая или автономная область обрезки изображения.\n * Числовой aspect задаётся вызывающим кодом и не связан с назначением изображения.\n */\nexport function ImageCropper({\n\timage,\n\taspect = 16 / 9,\n\twidth = \"100%\",\n\tclassName,\n\tstyle,\n\tcrop,\n\tdefaultCrop = DEFAULT_CROP,\n\tzoom,\n\tdefaultZoom = 1,\n\tminZoom = 1,\n\tmaxZoom = 3,\n\tzoomSpeed = 0.1,\n\tobjectFit = \"contain\",\n\tdisabled = false,\n\tonCropChange,\n\tonZoomChange,\n\tonCropComplete\n}: ImageCropperProps) {\n\tconst [uncontrolledCrop, setUncontrolledCrop] = useState(defaultCrop);\n\tconst [uncontrolledZoom, setUncontrolledZoom] = useState(defaultZoom);\n\tconst resolvedCrop = crop ?? uncontrolledCrop;\n\tconst resolvedZoom = zoom ?? uncontrolledZoom;\n\n\tconst handleCropChange = useCallback(\n\t\t(nextCrop: ImageCropPoint) => {\n\t\t\tif (disabled) return;\n\n\t\t\tif (crop === undefined) {\n\t\t\t\tsetUncontrolledCrop(nextCrop);\n\t\t\t}\n\n\t\t\tonCropChange?.(nextCrop);\n\t\t},\n\t\t[crop, disabled, onCropChange]\n\t);\n\n\tconst handleZoomChange = useCallback(\n\t\t(nextZoom: number) => {\n\t\t\tif (disabled) return;\n\n\t\t\tif (zoom === undefined) {\n\t\t\t\tsetUncontrolledZoom(nextZoom);\n\t\t\t}\n\n\t\t\tonZoomChange?.(nextZoom);\n\t\t},\n\t\t[disabled, onZoomChange, zoom]\n\t);\n\n\tconst handleCropComplete = useCallback(\n\t\t(croppedAreaPercentages: ImageCropArea, croppedAreaPixels: ImageCropArea) => {\n\t\t\tif (disabled) return;\n\n\t\t\tonCropComplete?.(croppedAreaPixels, croppedAreaPercentages);\n\t\t},\n\t\t[disabled, onCropComplete]\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={className}\n\t\t\tstyle={{ position: \"relative\", width, aspectRatio: aspect, pointerEvents: disabled ? \"none\" : undefined, ...style }}>\n\t\t\t<Cropper\n\t\t\t\timage={image}\n\t\t\t\tcrop={resolvedCrop}\n\t\t\t\tzoom={resolvedZoom}\n\t\t\t\taspect={aspect}\n\t\t\t\tminZoom={minZoom}\n\t\t\t\tmaxZoom={maxZoom}\n\t\t\t\tzoomSpeed={zoomSpeed}\n\t\t\t\tobjectFit={objectFit}\n\t\t\t\tonCropChange={handleCropChange}\n\t\t\t\tonZoomChange={handleZoomChange}\n\t\t\t\tonCropComplete={handleCropComplete}\n\t\t\t\tcropperProps={{ \"aria-disabled\": disabled || undefined }}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","export interface ImagePlaceholderProps {\n\twidth?: number | string;\n\theight?: number | string;\n\taspectRatio?: string | \"unset\";\n\tclassName?: string;\n}\n\nexport function ImagePlaceholder({ width = \"100%\", height = \"100%\", aspectRatio = \"16 / 9\", className }: ImagePlaceholderProps) {\n\treturn (\n\t\t<div style={{ width, height, aspectRatio }} className={className}>\n\t\t\t<svg\n\t\t\t\twidth={width}\n\t\t\t\theight={height}\n\t\t\t\tviewBox=\"0 0 200 200\"\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\trole=\"img\"\n\t\t\t\tfill=\"none\"\n\t\t\t\trx=\"10\"\n\t\t\t\try=\"10\"\n\t\t\t\tstyle={{ display: \"block\" }}\n\t\t\t\taria-label=\"Изображение недоступно\">\n\t\t\t\t{/* <rect width=\"200\" height=\"200\" fill=\"var(--surface-2)\" rx=\"10\" ry=\"10\" /> */}\n\t\t\t\t<g fill=\"var(--surface-0)\">\n\t\t\t\t\t<rect x=\"40\" y=\"50\" width=\"120\" height=\"100\" rx=\"10\" />\n\n\t\t\t\t\t<circle cx=\"60\" cy=\"70\" r=\"8\" fill=\"var(--surface-2)\" />\n\n\t\t\t\t\t<path d=\"M50 130 L75 100 L100 130 Z\" fill=\"var(--surface-2)\" />\n\t\t\t\t\t<path d=\"M90 130 L120 90 L150 130 Z\" fill=\"var(--surface-2)\" />\n\n\t\t\t\t\t<line x1=\"160\" y1=\"40\" x2=\"40\" y2=\"160\" stroke=\"var(--surface-0)\" strokeWidth=\"15\" strokeLinecap=\"round\" />\n\t\t\t\t\t<line x1=\"160\" y1=\"40\" x2=\"40\" y2=\"160\" stroke=\"var(--surface-2)\" strokeWidth=\"5\" strokeLinecap=\"round\" />\n\t\t\t\t</g>\n\t\t\t</svg>\n\t\t</div>\n\t);\n}\n","import { type CSSProperties, type ImgHTMLAttributes, type ReactNode, useEffect, useRef, useState } from \"react\";\n\nimport { type ImageLayout, type ImageSource } from \"../model/imageTypes\";\n\nimport { ImagePlaceholder } from \"./ImagePlaceholder\";\n\nexport interface ImageRendererProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\" | \"width\" | \"height\"> {\n\tsrc: string;\n\tsources?: readonly ImageSource[];\n\tlayout?: ImageLayout;\n\talt?: string;\n\trole?: string;\n\tariaLabel?: string;\n\tcaption?: string;\n\tfallback?: ReactNode;\n\tuseFigure?: boolean;\n\taspectRatio?: string | \"unset\";\n\twidth?: CSSProperties[\"width\"];\n\theight?: CSSProperties[\"height\"];\n\tintrinsicWidth?: number;\n\tintrinsicHeight?: number;\n\twrapperStyle?: CSSProperties;\n}\n\n/**\n * Базовый рендер изображения: lazy-появление, placeholder, обработка ошибки и figure/caption.\n * Компонент не знает, как устроено хранилище и какие форматы/размеры доступны.\n */\nexport function ImageRenderer({\n\tsrc,\n\tsources,\n\talt,\n\trole,\n\tariaLabel,\n\tcaption,\n\tfallback,\n\tuseFigure = false,\n\tlayout = \"cover\",\n\twidth = \"100%\",\n\theight = \"100%\",\n\taspectRatio,\n\tintrinsicWidth,\n\tintrinsicHeight,\n\tonLoad,\n\tonError,\n\tstyle,\n\twrapperStyle,\n\t...imgProps\n}: ImageRendererProps) {\n\tconst wrapperRef = useRef<HTMLDivElement | null>(null);\n\tconst [containerWidth, setContainerWidth] = useState(0);\n\tconst [isVisible, setIsVisible] = useState(false);\n\tconst [hasLoaded, setHasLoaded] = useState(false);\n\tconst [hasError, setHasError] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (typeof IntersectionObserver === \"undefined\") {\n\t\t\t// Отложенный fallback сохраняет одинаковый первый render на сервере и в браузере без IntersectionObserver.\n\t\t\tconst timeoutId = window.setTimeout(() => setIsVisible(true), 0);\n\n\t\t\treturn () => window.clearTimeout(timeoutId);\n\t\t}\n\n\t\tconst observer = new IntersectionObserver(\n\t\t\t([entry]) => {\n\t\t\t\tif (entry.isIntersecting) {\n\t\t\t\t\tconst parentWidth = Math.round(entry.boundingClientRect.width);\n\n\t\t\t\t\tsetContainerWidth(parentWidth);\n\t\t\t\t\tsetIsVisible(true);\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ rootMargin: \"100px\", threshold: 0.01 }\n\t\t);\n\n\t\tif (wrapperRef.current) {\n\t\t\tobserver.observe(wrapperRef.current);\n\t\t}\n\n\t\treturn () => observer.disconnect();\n\t}, []);\n\n\tconst isIntrinsic = layout === \"intrinsic\";\n\tconst resolvedHeight = isIntrinsic ? \"auto\" : height;\n\tconst intrinsicAspectRatio = intrinsicWidth && intrinsicHeight ? `${intrinsicWidth} / ${intrinsicHeight}` : undefined;\n\tconst resolvedAspectRatio = isIntrinsic ? (intrinsicAspectRatio ?? aspectRatio ?? \"auto\") : (aspectRatio ?? \"16 / 9\");\n\tconst placeholderHeight = isIntrinsic && resolvedAspectRatio !== \"auto\" && resolvedAspectRatio !== \"unset\" ? \"100%\" : resolvedHeight;\n\tconst sizesAttr = containerWidth ? `${containerWidth}px` : \"100vw\";\n\tconst defaultFallback = <ImagePlaceholder width={width} height={placeholderHeight} aspectRatio={resolvedAspectRatio} />;\n\tconst loadedImageStyle: CSSProperties = isIntrinsic\n\t\t? {\n\t\t\t\t...style,\n\t\t\t\tdisplay: \"block\",\n\t\t\t\twidth: \"100%\",\n\t\t\t\theight: \"auto\",\n\t\t\t\tobjectFit: undefined\n\t\t\t}\n\t\t: {\n\t\t\t\tdisplay: \"block\",\n\t\t\t\twidth: \"100%\",\n\t\t\t\theight: \"100%\",\n\t\t\t\tobjectFit: layout,\n\t\t\t\t...style\n\t\t\t};\n\n\tconst content = (\n\t\t<>\n\t\t\t{!hasLoaded && !hasError && (fallback || defaultFallback)}\n\t\t\t{isVisible && !hasError && (\n\t\t\t\t<picture>\n\t\t\t\t\t{sources?.map((source) => (\n\t\t\t\t\t\t<source\n\t\t\t\t\t\t\tkey={`${source.type ?? \"source\"}-${source.srcSet}`}\n\t\t\t\t\t\t\tsrcSet={source.srcSet}\n\t\t\t\t\t\t\ttype={source.type}\n\t\t\t\t\t\t\tsizes={source.sizes ?? sizesAttr}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={src}\n\t\t\t\t\t\talt={alt}\n\t\t\t\t\t\trole={role}\n\t\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\t\tonLoad={(event) => {\n\t\t\t\t\t\t\tsetHasLoaded(true);\n\t\t\t\t\t\t\tonLoad?.(event);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonError={(event) => {\n\t\t\t\t\t\t\tsetHasError(true);\n\t\t\t\t\t\t\tonError?.(event);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tstyle={!hasLoaded ? { display: \"none\" } : loadedImageStyle}\n\t\t\t\t\t\taria-busy={!hasLoaded}\n\t\t\t\t\t\twidth={intrinsicWidth}\n\t\t\t\t\t\theight={intrinsicHeight}\n\t\t\t\t\t\t{...imgProps}\n\t\t\t\t\t/>\n\t\t\t\t</picture>\n\t\t\t)}\n\t\t\t{hasError && defaultFallback}\n\t\t</>\n\t);\n\n\tconst wrapped = (\n\t\t<div ref={wrapperRef} style={{ width, height: resolvedHeight, aspectRatio: resolvedAspectRatio, ...wrapperStyle }}>\n\t\t\t{content}\n\t\t</div>\n\t);\n\n\treturn useFigure ? (\n\t\t<figure className=\"relative\">\n\t\t\t{wrapped}\n\t\t\t{caption && (\n\t\t\t\t<figcaption\n\t\t\t\t\tstyle={{ bottom: 2, right: 2, maxWidth: \"calc(100% - 4px)\" }}\n\t\t\t\t\tclassName=\"absolute paddingInlineMd textRight radiusSm fontSizeSm\">\n\t\t\t\t\t{caption}\n\t\t\t\t</figcaption>\n\t\t\t)}\n\t\t</figure>\n\t) : (\n\t\twrapped\n\t);\n}\n","import { type SelectedImageData } from \"../model/imageSelectionTypes\";\n\n/** Возвращает устойчивый ключ файла внутри текущего набора выбранных изображений. */\nexport function getImageSelectionKey(image: SelectedImageData, index: number): string {\n\treturn `${image.file.meta.name}-${image.file.meta.size}-${image.file.meta.lastModified}-${index}`;\n}\n","import { useCallback, useMemo, useState } from \"react\";\n\nimport { getImageSelectionKey } from \"../lib/getImageSelectionKey\";\n\nimport { type ImageCropArea, type ImageCropPoint } from \"./imageCropTypes\";\nimport {\n\ttype ImageCropperState,\n\ttype ImageSelectionPanelProps,\n\ttype ImageSelectionState,\n\ttype SelectedImageData,\n\ttype SelectedImageFile\n} from \"./imageSelectionTypes\";\n\nconst INITIAL_CROPPER_STATE: ImageCropperState = { crop: { x: 0, y: 0 }, zoom: 1 };\n\n/**\n * Управляет набором изображений в conventional controlled/uncontrolled-режиме.\n * В controlled-режиме каждое изменение сразу передаётся через onChange, а источник истины остаётся у вызывающего кода.\n */\nexport function useImageSelectionState({\n\tvalue,\n\tdefaultValue,\n\tdisabled,\n\tonChange,\n\tonApply\n}: Pick<ImageSelectionPanelProps, \"value\" | \"defaultValue\" | \"disabled\" | \"onChange\" | \"onApply\">): ImageSelectionState {\n\tconst [uncontrolledValue, setUncontrolledValue] = useState<SelectedImageData[]>(defaultValue ?? []);\n\tconst [requestedActiveIndex, setActiveIndex] = useState(0);\n\tconst [cropperStateByImage, setCropperStateByImage] = useState<Record<string, ImageCropperState>>({});\n\tconst resolvedValue = value ?? uncontrolledValue;\n\n\tconst updateValue = useCallback(\n\t\t(updater: (currentValue: SelectedImageData[]) => SelectedImageData[]) => {\n\t\t\tconst nextValue = updater(resolvedValue);\n\n\t\t\tif (value === undefined) {\n\t\t\t\tsetUncontrolledValue(nextValue);\n\t\t\t}\n\n\t\t\tonChange?.(nextValue);\n\t\t},\n\t\t[onChange, resolvedValue, value]\n\t);\n\n\tconst files = useMemo(() => resolvedValue.map((image) => image.file), [resolvedValue]);\n\tconst activeIndex = resolvedValue.length === 0 ? 0 : Math.min(requestedActiveIndex, resolvedValue.length - 1);\n\tconst activeImage = resolvedValue[activeIndex];\n\tconst activeImageKey = activeImage ? getImageSelectionKey(activeImage, activeIndex) : undefined;\n\tconst activeCropperState = activeImageKey ? (cropperStateByImage[activeImageKey] ?? INITIAL_CROPPER_STATE) : INITIAL_CROPPER_STATE;\n\tconst hasSelected = resolvedValue.length > 0;\n\tconst canApply = !disabled && hasSelected && resolvedValue.every((image) => image.alt.trim() && image.crop);\n\n\tconst setFiles = useCallback(\n\t\t(nextFiles: SelectedImageFile[]) => {\n\t\t\tupdateValue((currentValue) =>\n\t\t\t\tnextFiles.map((file) => {\n\t\t\t\t\t// Сохраняем описание и crop для файлов, которые остались в выборе.\n\t\t\t\t\tconst existingImage = currentValue.find((image) => image.file.file === file.file);\n\n\t\t\t\t\treturn existingImage ? { ...existingImage, file } : { file, alt: \"\" };\n\t\t\t\t})\n\t\t\t);\n\t\t},\n\t\t[updateValue]\n\t);\n\n\tconst setActiveAlt = useCallback(\n\t\t(alt: string) => {\n\t\t\tupdateValue((currentValue) => currentValue.map((image, index) => (index === activeIndex ? { ...image, alt } : image)));\n\t\t},\n\t\t[activeIndex, updateValue]\n\t);\n\n\tconst setActiveCrop = useCallback(\n\t\t(crop: ImageCropArea) => {\n\t\t\tupdateValue((currentValue) => currentValue.map((image, index) => (index === activeIndex ? { ...image, crop } : image)));\n\t\t},\n\t\t[activeIndex, updateValue]\n\t);\n\n\tconst setActiveCropperCrop = useCallback(\n\t\t(crop: ImageCropPoint) => {\n\t\t\tif (!activeImageKey) return;\n\n\t\t\tsetCropperStateByImage((currentState) => ({\n\t\t\t\t...currentState,\n\t\t\t\t[activeImageKey]: {\n\t\t\t\t\tcrop,\n\t\t\t\t\tzoom: currentState[activeImageKey]?.zoom ?? 1\n\t\t\t\t}\n\t\t\t}));\n\t\t},\n\t\t[activeImageKey]\n\t);\n\n\tconst setActiveCropperZoom = useCallback(\n\t\t(zoom: number) => {\n\t\t\tif (!activeImageKey) return;\n\n\t\t\tsetCropperStateByImage((currentState) => ({\n\t\t\t\t...currentState,\n\t\t\t\t[activeImageKey]: {\n\t\t\t\t\tcrop: currentState[activeImageKey]?.crop ?? { x: 0, y: 0 },\n\t\t\t\t\tzoom\n\t\t\t\t}\n\t\t\t}));\n\t\t},\n\t\t[activeImageKey]\n\t);\n\n\tconst apply = useCallback(() => {\n\t\tonApply?.(resolvedValue);\n\t}, [onApply, resolvedValue]);\n\n\treturn {\n\t\tvalue: resolvedValue,\n\t\tfiles,\n\t\tactiveIndex,\n\t\tactiveImage,\n\t\tactiveCropperState,\n\t\thasSelected,\n\t\tcanApply,\n\t\tapply,\n\t\tsetFiles,\n\t\tsetActiveIndex,\n\t\tsetActiveAlt,\n\t\tsetActiveCrop,\n\t\tsetActiveCropperCrop,\n\t\tsetActiveCropperZoom\n\t};\n}\n","import { type CSSProperties } from \"react\";\n\nimport { type SelectedImageData } from \"../model/imageSelectionTypes\";\n\nexport type ImageNaturalSize = {\n\twidth: number;\n\theight: number;\n};\n\n/** Масштабирует preview так, чтобы контейнер показывал только выбранную область crop. */\nexport function getImageCropPreviewStyle(image: SelectedImageData, size: ImageNaturalSize | undefined, aspect: number): CSSProperties {\n\tif (!image.crop || !size) {\n\t\treturn {\n\t\t\twidth: \"100%\",\n\t\t\taspectRatio: aspect,\n\t\t\tobjectFit: \"cover\",\n\t\t\tdisplay: \"block\"\n\t\t};\n\t}\n\n\tconst crop = image.crop;\n\n\treturn {\n\t\tposition: \"absolute\",\n\t\tleft: `${-(crop.x / crop.width) * 100}%`,\n\t\ttop: `${-(crop.y / crop.height) * 100}%`,\n\t\twidth: `${(size.width / crop.width) * 100}%`,\n\t\theight: `${(size.height / crop.height) * 100}%`,\n\t\tmaxWidth: \"none\"\n\t};\n}\n","import { useState } from \"react\";\n\nimport { GridContainer } from \"../../grid\";\nimport { InputText } from \"../../input\";\nimport { InputFiles } from \"../../input-files\";\nimport { getImageCropPreviewStyle, type ImageNaturalSize } from \"../lib/getImageCropPreviewStyle\";\nimport { getImageSelectionKey } from \"../lib/getImageSelectionKey\";\nimport { type ImageSelectionPanelProps, type ImageSelectionState } from \"../model/imageSelectionTypes\";\n\nimport { ImageCropper } from \"./ImageCropper\";\n\nconst DEFAULT_ALLOWED_IMAGE_MIME = [\"image/jpeg\", \"image/png\", \"image/webp\", \"image/avif\"] as const;\n\ninterface ImageSelectionFieldsProps extends Pick<\n\tImageSelectionPanelProps,\n\t\"aspect\" | \"disabled\" | \"allowedMime\" | \"maxBytes\" | \"minimumCropWidth\" | \"onReadError\"\n> {\n\tstate: ImageSelectionState;\n}\n\n/** Поля выбора файлов, crop и альтернативного текста для активного изображения. */\nexport function ImageSelectionFields({\n\taspect = 16 / 9,\n\tdisabled,\n\tallowedMime = DEFAULT_ALLOWED_IMAGE_MIME,\n\tmaxBytes,\n\tminimumCropWidth,\n\tonReadError,\n\tstate\n}: ImageSelectionFieldsProps) {\n\tconst area = state.activeImage?.crop;\n\tconst [imageSizes, setImageSizes] = useState<Record<string, ImageNaturalSize>>({});\n\n\treturn (\n\t\t<GridContainer gap=\"md\">\n\t\t\t<InputFiles\n\t\t\t\tlabel=\"Файл изображения\"\n\t\t\t\tallowedMime={allowedMime}\n\t\t\t\tvalue={state.files}\n\t\t\t\tonChange={state.setFiles}\n\t\t\t\tmaxBytes={maxBytes}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonReadError={onReadError}\n\t\t\t/>\n\n\t\t\t{state.hasSelected && state.activeImage && (\n\t\t\t\t<div>\n\t\t\t\t\t<GridContainer templateColumns=\"repeat(auto-fill, minmax(10em, 1fr))\" gap=\"xs\">\n\t\t\t\t\t\t{state.value.map((image, index) => {\n\t\t\t\t\t\t\tconst imageKey = getImageSelectionKey(image, index);\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={imageKey}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\tonClick={() => state.setActiveIndex(index)}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\t\t\tborder: index === state.activeIndex ? \"2px solid var(--border-accent)\" : \"2px solid transparent\",\n\t\t\t\t\t\t\t\t\t\tbackground: \"transparent\",\n\t\t\t\t\t\t\t\t\t\tcursor: disabled ? \"default\" : \"pointer\"\n\t\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\t\t\t\t\t\t\tdisplay: \"block\",\n\t\t\t\t\t\t\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\t\t\t\t\t\t\taspectRatio: aspect,\n\t\t\t\t\t\t\t\t\t\t\toverflow: \"hidden\"\n\t\t\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\tsrc={image.file.dataUrl}\n\t\t\t\t\t\t\t\t\t\t\talt={image.alt || `Предпросмотр изображения ${index + 1}`}\n\t\t\t\t\t\t\t\t\t\t\tstyle={getImageCropPreviewStyle(image, imageSizes[imageKey], aspect)}\n\t\t\t\t\t\t\t\t\t\t\tonLoad={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst target = event.currentTarget;\n\n\t\t\t\t\t\t\t\t\t\t\t\tsetImageSizes((currentSizes) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t...currentSizes,\n\t\t\t\t\t\t\t\t\t\t\t\t\t[imageKey]: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: target.naturalWidth,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: target.naturalHeight\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</GridContainer>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\tВыберите область изображения{\" \"}\n\t\t\t\t\t\t{area && (\n\t\t\t\t\t\t\t<code className={minimumCropWidth && area.width < minimumCropWidth ? \"statusError\" : \"statusSuccess\"}>\n\t\t\t\t\t\t\t\t{area.width}x{area.height}\n\t\t\t\t\t\t\t\t{minimumCropWidth && area.width < minimumCropWidth ? \" — недостаточная ширина\" : \"\"}\n\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<ImageCropper\n\t\t\t\t\t\tkey={getImageSelectionKey(state.activeImage, state.activeIndex)}\n\t\t\t\t\t\timage={state.activeImage.file.dataUrl}\n\t\t\t\t\t\tcrop={state.activeCropperState.crop}\n\t\t\t\t\t\tzoom={state.activeCropperState.zoom}\n\t\t\t\t\t\taspect={aspect}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tonCropChange={state.setActiveCropperCrop}\n\t\t\t\t\t\tonZoomChange={state.setActiveCropperZoom}\n\t\t\t\t\t\tonCropComplete={state.setActiveCrop}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<InputText\n\t\t\t\trequired\n\t\t\t\tdisabled={!state.hasSelected || disabled}\n\t\t\t\tlabel=\"Краткое описание изображения\"\n\t\t\t\tplaceholder=\"\"\n\t\t\t\tvalue={state.activeImage?.alt ?? \"\"}\n\t\t\t\tonChange={state.setActiveAlt}\n\t\t\t/>\n\t\t</GridContainer>\n\t);\n}\n","import { Button } from \"../../button\";\nimport { Modal, ModalContent, ModalFooter } from \"../../modal\";\nimport { type ImageSelectionModalProps } from \"../model/imageSelectionTypes\";\nimport { useImageSelectionState } from \"../model/useImageSelectionState\";\n\nimport { ImageSelectionFields } from \"./ImageSelectionFields\";\n\n/** Модальная форма выбора изображений с необязательным этапом подтверждения. */\nexport function ImageSelectionModal({\n\tdisabled,\n\tisOpen = true,\n\tonClose = () => {},\n\ttitle = \"Загрузка нового изображения\",\n\t...props\n}: ImageSelectionModalProps) {\n\tconst state = useImageSelectionState({ ...props, disabled });\n\n\tif (!props.onApply) {\n\t\treturn (\n\t\t\t<Modal isOpen={isOpen} onClose={onClose} title={title} size=\"xl\">\n\t\t\t\t<ModalContent scrollable>\n\t\t\t\t\t<ImageSelectionFields {...props} disabled={disabled} state={state} />\n\t\t\t\t</ModalContent>\n\t\t\t</Modal>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Modal isOpen={isOpen} onClose={onClose} title={title} size=\"xl\">\n\t\t\t<ModalContent scrollable>\n\t\t\t\t<ImageSelectionFields {...props} disabled={disabled} state={state} />\n\t\t\t</ModalContent>\n\t\t\t<ModalFooter>\n\t\t\t\t<Button disabled={!state.canApply} tone=\"success\" onClick={state.apply}>\n\t\t\t\t\tПрименить\n\t\t\t\t</Button>\n\t\t\t</ModalFooter>\n\t\t</Modal>\n\t);\n}\n","import { Button } from \"../../button\";\nimport { type ImageSelectionActionsData, type ImageSelectionPanelProps } from \"../model/imageSelectionTypes\";\nimport { useImageSelectionState } from \"../model/useImageSelectionState\";\n\nimport { ImageSelectionFields } from \"./ImageSelectionFields\";\n\n/** Встраиваемая форма выбора и обрезки одного или нескольких изображений. */\nexport function ImageSelectionPanel({ disabled, renderActions, ...props }: ImageSelectionPanelProps) {\n\tconst state = useImageSelectionState({ ...props, disabled });\n\tconst actionsData: ImageSelectionActionsData = {\n\t\tvalue: state.value,\n\t\tactiveIndex: state.activeIndex,\n\t\thasSelected: state.hasSelected,\n\t\tcanApply: state.canApply,\n\t\tapply: state.apply\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<ImageSelectionFields {...props} disabled={disabled} state={state} />\n\t\t\t{renderActions\n\t\t\t\t? renderActions(actionsData)\n\t\t\t\t: props.onApply && (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<Button disabled={!state.canApply} tone=\"success\" onClick={state.apply}>\n\t\t\t\t\t\t\t\tПрименить\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t</>\n\t);\n}\n","import { type ImgHTMLAttributes } from \"react\";\n\nimport { buildImageSources } from \"../lib/buildImageSources\";\nimport { buildImageSrcSet } from \"../lib/buildImageSrcSet\";\nimport { type ResponsiveImageData } from \"../model/imageTypes\";\n\nimport { ImageRenderer, type ImageRendererProps } from \"./ImageRenderer\";\n\nexport interface ImageViewProps\n\textends\n\t\tOmit<ImageRendererProps, \"src\" | \"sources\" | \"alt\" | \"intrinsicWidth\" | \"intrinsicHeight\" | \"srcSet\" | \"sizes\">,\n\t\tPick<ImgHTMLAttributes<HTMLImageElement>, \"sizes\"> {\n\timage: ResponsiveImageData;\n\talt?: string;\n}\n\n/**\n * Собирает picture/srcset из готовых URL и делегирует отображение ImageRenderer.\n * Компонент не формирует имена файлов и не знает о форматах или размерах хранилища.\n */\nexport function ImageView({ image, alt, sizes, aspectRatio, ...props }: ImageViewProps) {\n\tconst sources = buildImageSources(image.sources, sizes);\n\tconst srcSet = image.candidates ? buildImageSrcSet(image.candidates) : undefined;\n\tconst resolvedAspectRatio =\n\t\taspectRatio ?? (image.intrinsicWidth && image.intrinsicHeight ? `${image.intrinsicWidth} / ${image.intrinsicHeight}` : undefined);\n\n\treturn (\n\t\t<ImageRenderer\n\t\t\t{...props}\n\t\t\tsrc={image.src}\n\t\t\tsrcSet={srcSet || undefined}\n\t\t\tsources={sources}\n\t\t\tsizes={sizes}\n\t\t\talt={alt ?? image.alt}\n\t\t\tintrinsicWidth={image.intrinsicWidth}\n\t\t\tintrinsicHeight={image.intrinsicHeight}\n\t\t\taspectRatio={resolvedAspectRatio}\n\t\t/>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/image/lib/buildImageSrcSet.ts","../../src/image/lib/buildImageSources.ts","../../src/image/ui/ImageCropper.tsx","../../src/image/ui/ImagePlaceholder.tsx","../../src/image/ui/ImageRenderer.tsx","../../src/image/lib/getImageSelectionKey.ts","../../src/image/model/useImageSelectionState.ts","../../src/image/lib/getImageCropPreviewStyle.ts","../../src/image/ui/ImageSelectionFields.tsx","../../src/image/ui/ImageSelectionModal.tsx","../../src/image/ui/ImageSelectionPanel.tsx","../../src/image/ui/ImageView.tsx","../../src/image/ui/ImageViewer.tsx"],"sourcesContent":["import { type ImageCandidate } from \"../model/imageTypes\";\n\n/** Собирает валидный srcset из уже разрешённых вызывающим кодом URL вариантов. */\nexport function buildImageSrcSet(candidates: readonly ImageCandidate[]): string {\n\treturn candidates\n\t\t.map((candidate) => (\"width\" in candidate ? `${candidate.src} ${candidate.width}w` : `${candidate.src} ${candidate.density}x`))\n\t\t.join(\", \");\n}\n","import { type ImageSource, type ResponsiveImageSource } from \"../model/imageTypes\";\n\nimport { buildImageSrcSet } from \"./buildImageSrcSet\";\n\n/** Преобразует декларативные наборы кандидатов в готовые source-дескрипторы. */\nexport function buildImageSources(sources: readonly ResponsiveImageSource[] | undefined, defaultSizes?: string): ImageSource[] {\n\treturn (sources ?? [])\n\t\t.map((source) => ({\n\t\t\tsrcSet: buildImageSrcSet(source.candidates),\n\t\t\ttype: source.type,\n\t\t\tsizes: source.sizes ?? defaultSizes\n\t\t}))\n\t\t.filter((source) => source.srcSet.length > 0);\n}\n","import { useCallback, useState } from \"react\";\n\nimport Cropper from \"react-easy-crop\";\n\nimport { type ImageCropArea, type ImageCropperProps, type ImageCropPoint } from \"../model/imageCropTypes\";\n\nconst DEFAULT_CROP: ImageCropPoint = { x: 0, y: 0 };\n\n/**\n * Управляемая или автономная область обрезки изображения.\n * Числовой aspect задаётся вызывающим кодом и не связан с назначением изображения.\n */\nexport function ImageCropper({\n\timage,\n\taspect = 16 / 9,\n\twidth = \"100%\",\n\tclassName,\n\tstyle,\n\tcrop,\n\tdefaultCrop = DEFAULT_CROP,\n\tzoom,\n\tdefaultZoom = 1,\n\tminZoom = 1,\n\tmaxZoom = 3,\n\tzoomSpeed = 0.1,\n\tobjectFit = \"contain\",\n\tdisabled = false,\n\tonCropChange,\n\tonZoomChange,\n\tonCropComplete\n}: ImageCropperProps) {\n\tconst [uncontrolledCrop, setUncontrolledCrop] = useState(defaultCrop);\n\tconst [uncontrolledZoom, setUncontrolledZoom] = useState(defaultZoom);\n\tconst resolvedCrop = crop ?? uncontrolledCrop;\n\tconst resolvedZoom = zoom ?? uncontrolledZoom;\n\n\tconst handleCropChange = useCallback(\n\t\t(nextCrop: ImageCropPoint) => {\n\t\t\tif (disabled) return;\n\n\t\t\tif (crop === undefined) {\n\t\t\t\tsetUncontrolledCrop(nextCrop);\n\t\t\t}\n\n\t\t\tonCropChange?.(nextCrop);\n\t\t},\n\t\t[crop, disabled, onCropChange]\n\t);\n\n\tconst handleZoomChange = useCallback(\n\t\t(nextZoom: number) => {\n\t\t\tif (disabled) return;\n\n\t\t\tif (zoom === undefined) {\n\t\t\t\tsetUncontrolledZoom(nextZoom);\n\t\t\t}\n\n\t\t\tonZoomChange?.(nextZoom);\n\t\t},\n\t\t[disabled, onZoomChange, zoom]\n\t);\n\n\tconst handleCropComplete = useCallback(\n\t\t(croppedAreaPercentages: ImageCropArea, croppedAreaPixels: ImageCropArea) => {\n\t\t\tif (disabled) return;\n\n\t\t\tonCropComplete?.(croppedAreaPixels, croppedAreaPercentages);\n\t\t},\n\t\t[disabled, onCropComplete]\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={className}\n\t\t\tstyle={{ position: \"relative\", width, aspectRatio: aspect, pointerEvents: disabled ? \"none\" : undefined, ...style }}>\n\t\t\t<Cropper\n\t\t\t\timage={image}\n\t\t\t\tcrop={resolvedCrop}\n\t\t\t\tzoom={resolvedZoom}\n\t\t\t\taspect={aspect}\n\t\t\t\tminZoom={minZoom}\n\t\t\t\tmaxZoom={maxZoom}\n\t\t\t\tzoomSpeed={zoomSpeed}\n\t\t\t\tobjectFit={objectFit}\n\t\t\t\tonCropChange={handleCropChange}\n\t\t\t\tonZoomChange={handleZoomChange}\n\t\t\t\tonCropComplete={handleCropComplete}\n\t\t\t\tcropperProps={{ \"aria-disabled\": disabled || undefined }}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","export interface ImagePlaceholderProps {\n\twidth?: number | string;\n\theight?: number | string;\n\taspectRatio?: string | \"unset\";\n\tclassName?: string;\n}\n\nexport function ImagePlaceholder({ width = \"100%\", height = \"100%\", aspectRatio = \"16 / 9\", className }: ImagePlaceholderProps) {\n\treturn (\n\t\t<div style={{ width, height, aspectRatio }} className={className}>\n\t\t\t<svg\n\t\t\t\twidth={width}\n\t\t\t\theight={height}\n\t\t\t\tviewBox=\"0 0 200 200\"\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\trole=\"img\"\n\t\t\t\tfill=\"none\"\n\t\t\t\trx=\"10\"\n\t\t\t\try=\"10\"\n\t\t\t\tstyle={{ display: \"block\" }}\n\t\t\t\taria-label=\"Изображение недоступно\">\n\t\t\t\t{/* <rect width=\"200\" height=\"200\" fill=\"var(--surface-2)\" rx=\"10\" ry=\"10\" /> */}\n\t\t\t\t<g fill=\"var(--surface-0)\">\n\t\t\t\t\t<rect x=\"40\" y=\"50\" width=\"120\" height=\"100\" rx=\"10\" />\n\n\t\t\t\t\t<circle cx=\"60\" cy=\"70\" r=\"8\" fill=\"var(--surface-2)\" />\n\n\t\t\t\t\t<path d=\"M50 130 L75 100 L100 130 Z\" fill=\"var(--surface-2)\" />\n\t\t\t\t\t<path d=\"M90 130 L120 90 L150 130 Z\" fill=\"var(--surface-2)\" />\n\n\t\t\t\t\t<line x1=\"160\" y1=\"40\" x2=\"40\" y2=\"160\" stroke=\"var(--surface-0)\" strokeWidth=\"15\" strokeLinecap=\"round\" />\n\t\t\t\t\t<line x1=\"160\" y1=\"40\" x2=\"40\" y2=\"160\" stroke=\"var(--surface-2)\" strokeWidth=\"5\" strokeLinecap=\"round\" />\n\t\t\t\t</g>\n\t\t\t</svg>\n\t\t</div>\n\t);\n}\n","import { type CSSProperties, type ImgHTMLAttributes, type ReactNode, useEffect, useRef, useState } from \"react\";\n\nimport { type ImageLayout, type ImageSource } from \"../model/imageTypes\";\n\nimport { ImagePlaceholder } from \"./ImagePlaceholder\";\n\nexport interface ImageRendererProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\" | \"width\" | \"height\"> {\n\tsrc: string;\n\tsources?: readonly ImageSource[];\n\tlayout?: ImageLayout;\n\talt?: string;\n\trole?: string;\n\tariaLabel?: string;\n\tcaption?: string;\n\tfallback?: ReactNode;\n\tuseFigure?: boolean;\n\taspectRatio?: string | \"unset\";\n\twidth?: CSSProperties[\"width\"];\n\theight?: CSSProperties[\"height\"];\n\tintrinsicWidth?: number;\n\tintrinsicHeight?: number;\n\twrapperStyle?: CSSProperties;\n}\n\n/**\n * Базовый рендер изображения: lazy-появление, placeholder, обработка ошибки и figure/caption.\n * Компонент не знает, как устроено хранилище и какие форматы/размеры доступны.\n */\nexport function ImageRenderer({\n\tsrc,\n\tsources,\n\talt,\n\trole,\n\tariaLabel,\n\tcaption,\n\tfallback,\n\tuseFigure = false,\n\tlayout = \"cover\",\n\twidth = \"100%\",\n\theight = \"100%\",\n\taspectRatio,\n\tintrinsicWidth,\n\tintrinsicHeight,\n\tonLoad,\n\tonError,\n\tstyle,\n\twrapperStyle,\n\t...imgProps\n}: ImageRendererProps) {\n\tconst wrapperRef = useRef<HTMLDivElement | null>(null);\n\tconst [containerWidth, setContainerWidth] = useState(0);\n\tconst [isVisible, setIsVisible] = useState(false);\n\tconst [hasLoaded, setHasLoaded] = useState(false);\n\tconst [hasError, setHasError] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (typeof IntersectionObserver === \"undefined\") {\n\t\t\t// Отложенный fallback сохраняет одинаковый первый render на сервере и в браузере без IntersectionObserver.\n\t\t\tconst timeoutId = window.setTimeout(() => setIsVisible(true), 0);\n\n\t\t\treturn () => window.clearTimeout(timeoutId);\n\t\t}\n\n\t\tconst observer = new IntersectionObserver(\n\t\t\t([entry]) => {\n\t\t\t\tif (entry.isIntersecting) {\n\t\t\t\t\tconst parentWidth = Math.round(entry.boundingClientRect.width);\n\n\t\t\t\t\tsetContainerWidth(parentWidth);\n\t\t\t\t\tsetIsVisible(true);\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ rootMargin: \"100px\", threshold: 0.01 }\n\t\t);\n\n\t\tif (wrapperRef.current) {\n\t\t\tobserver.observe(wrapperRef.current);\n\t\t}\n\n\t\treturn () => observer.disconnect();\n\t}, []);\n\n\tconst isIntrinsic = layout === \"intrinsic\";\n\tconst resolvedHeight = isIntrinsic ? \"auto\" : height;\n\tconst intrinsicAspectRatio = intrinsicWidth && intrinsicHeight ? `${intrinsicWidth} / ${intrinsicHeight}` : undefined;\n\tconst resolvedAspectRatio = isIntrinsic ? (intrinsicAspectRatio ?? aspectRatio ?? \"auto\") : (aspectRatio ?? \"16 / 9\");\n\tconst placeholderHeight = isIntrinsic && resolvedAspectRatio !== \"auto\" && resolvedAspectRatio !== \"unset\" ? \"100%\" : resolvedHeight;\n\tconst sizesAttr = containerWidth ? `${containerWidth}px` : \"100vw\";\n\tconst defaultFallback = <ImagePlaceholder width={width} height={placeholderHeight} aspectRatio={resolvedAspectRatio} />;\n\tconst loadedImageStyle: CSSProperties = isIntrinsic\n\t\t? {\n\t\t\t\t...style,\n\t\t\t\tdisplay: \"block\",\n\t\t\t\twidth: \"100%\",\n\t\t\t\theight: \"auto\",\n\t\t\t\tobjectFit: undefined\n\t\t\t}\n\t\t: {\n\t\t\t\tdisplay: \"block\",\n\t\t\t\twidth: \"100%\",\n\t\t\t\theight: \"100%\",\n\t\t\t\tobjectFit: layout,\n\t\t\t\t...style\n\t\t\t};\n\n\tconst content = (\n\t\t<>\n\t\t\t{!hasLoaded && !hasError && (fallback || defaultFallback)}\n\t\t\t{isVisible && !hasError && (\n\t\t\t\t<picture>\n\t\t\t\t\t{sources?.map((source) => (\n\t\t\t\t\t\t<source\n\t\t\t\t\t\t\tkey={`${source.type ?? \"source\"}-${source.srcSet}`}\n\t\t\t\t\t\t\tsrcSet={source.srcSet}\n\t\t\t\t\t\t\ttype={source.type}\n\t\t\t\t\t\t\tsizes={source.sizes ?? sizesAttr}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={src}\n\t\t\t\t\t\talt={alt}\n\t\t\t\t\t\trole={role}\n\t\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\t\tonLoad={(event) => {\n\t\t\t\t\t\t\tsetHasLoaded(true);\n\t\t\t\t\t\t\tonLoad?.(event);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonError={(event) => {\n\t\t\t\t\t\t\tsetHasError(true);\n\t\t\t\t\t\t\tonError?.(event);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tstyle={!hasLoaded ? { display: \"none\" } : loadedImageStyle}\n\t\t\t\t\t\taria-busy={!hasLoaded}\n\t\t\t\t\t\twidth={intrinsicWidth}\n\t\t\t\t\t\theight={intrinsicHeight}\n\t\t\t\t\t\t{...imgProps}\n\t\t\t\t\t/>\n\t\t\t\t</picture>\n\t\t\t)}\n\t\t\t{hasError && defaultFallback}\n\t\t</>\n\t);\n\n\tconst wrapped = (\n\t\t<div ref={wrapperRef} style={{ width, height: resolvedHeight, aspectRatio: resolvedAspectRatio, ...wrapperStyle }}>\n\t\t\t{content}\n\t\t</div>\n\t);\n\n\treturn useFigure ? (\n\t\t<figure className=\"relative\">\n\t\t\t{wrapped}\n\t\t\t{caption && (\n\t\t\t\t<figcaption\n\t\t\t\t\tstyle={{ bottom: 2, right: 2, maxWidth: \"calc(100% - 4px)\" }}\n\t\t\t\t\tclassName=\"absolute paddingInlineMd textRight radiusSm fontSizeSm\">\n\t\t\t\t\t{caption}\n\t\t\t\t</figcaption>\n\t\t\t)}\n\t\t</figure>\n\t) : (\n\t\twrapped\n\t);\n}\n","import { type SelectedImageData } from \"../model/imageSelectionTypes\";\n\n/** Возвращает устойчивый ключ файла внутри текущего набора выбранных изображений. */\nexport function getImageSelectionKey(image: SelectedImageData, index: number): string {\n\treturn `${image.file.meta.name}-${image.file.meta.size}-${image.file.meta.lastModified}-${index}`;\n}\n","import { useCallback, useMemo, useState } from \"react\";\n\nimport { getImageSelectionKey } from \"../lib/getImageSelectionKey\";\n\nimport { type ImageCropArea, type ImageCropPoint } from \"./imageCropTypes\";\nimport {\n\ttype ImageCropperState,\n\ttype ImageSelectionPanelProps,\n\ttype ImageSelectionState,\n\ttype SelectedImageData,\n\ttype SelectedImageFile\n} from \"./imageSelectionTypes\";\n\nconst INITIAL_CROPPER_STATE: ImageCropperState = { crop: { x: 0, y: 0 }, zoom: 1 };\n\n/**\n * Управляет набором изображений в conventional controlled/uncontrolled-режиме.\n * В controlled-режиме каждое изменение сразу передаётся через onChange, а источник истины остаётся у вызывающего кода.\n */\nexport function useImageSelectionState({\n\tvalue,\n\tdefaultValue,\n\tdisabled,\n\tonChange,\n\tonApply\n}: Pick<ImageSelectionPanelProps, \"value\" | \"defaultValue\" | \"disabled\" | \"onChange\" | \"onApply\">): ImageSelectionState {\n\tconst [uncontrolledValue, setUncontrolledValue] = useState<SelectedImageData[]>(defaultValue ?? []);\n\tconst [requestedActiveIndex, setActiveIndex] = useState(0);\n\tconst [cropperStateByImage, setCropperStateByImage] = useState<Record<string, ImageCropperState>>({});\n\tconst resolvedValue = value ?? uncontrolledValue;\n\n\tconst updateValue = useCallback(\n\t\t(updater: (currentValue: SelectedImageData[]) => SelectedImageData[]) => {\n\t\t\tconst nextValue = updater(resolvedValue);\n\n\t\t\tif (value === undefined) {\n\t\t\t\tsetUncontrolledValue(nextValue);\n\t\t\t}\n\n\t\t\tonChange?.(nextValue);\n\t\t},\n\t\t[onChange, resolvedValue, value]\n\t);\n\n\tconst files = useMemo(() => resolvedValue.map((image) => image.file), [resolvedValue]);\n\tconst activeIndex = resolvedValue.length === 0 ? 0 : Math.min(requestedActiveIndex, resolvedValue.length - 1);\n\tconst activeImage = resolvedValue[activeIndex];\n\tconst activeImageKey = activeImage ? getImageSelectionKey(activeImage, activeIndex) : undefined;\n\tconst activeCropperState = activeImageKey ? (cropperStateByImage[activeImageKey] ?? INITIAL_CROPPER_STATE) : INITIAL_CROPPER_STATE;\n\tconst hasSelected = resolvedValue.length > 0;\n\tconst canApply = !disabled && hasSelected && resolvedValue.every((image) => image.alt.trim() && image.crop);\n\n\tconst setFiles = useCallback(\n\t\t(nextFiles: SelectedImageFile[]) => {\n\t\t\tupdateValue((currentValue) =>\n\t\t\t\tnextFiles.map((file) => {\n\t\t\t\t\t// Сохраняем описание и crop для файлов, которые остались в выборе.\n\t\t\t\t\tconst existingImage = currentValue.find((image) => image.file.file === file.file);\n\n\t\t\t\t\treturn existingImage ? { ...existingImage, file } : { file, alt: \"\" };\n\t\t\t\t})\n\t\t\t);\n\t\t},\n\t\t[updateValue]\n\t);\n\n\tconst setActiveAlt = useCallback(\n\t\t(alt: string) => {\n\t\t\tupdateValue((currentValue) => currentValue.map((image, index) => (index === activeIndex ? { ...image, alt } : image)));\n\t\t},\n\t\t[activeIndex, updateValue]\n\t);\n\n\tconst setActiveCrop = useCallback(\n\t\t(crop: ImageCropArea) => {\n\t\t\tupdateValue((currentValue) => currentValue.map((image, index) => (index === activeIndex ? { ...image, crop } : image)));\n\t\t},\n\t\t[activeIndex, updateValue]\n\t);\n\n\tconst setActiveCropperCrop = useCallback(\n\t\t(crop: ImageCropPoint) => {\n\t\t\tif (!activeImageKey) return;\n\n\t\t\tsetCropperStateByImage((currentState) => ({\n\t\t\t\t...currentState,\n\t\t\t\t[activeImageKey]: {\n\t\t\t\t\tcrop,\n\t\t\t\t\tzoom: currentState[activeImageKey]?.zoom ?? 1\n\t\t\t\t}\n\t\t\t}));\n\t\t},\n\t\t[activeImageKey]\n\t);\n\n\tconst setActiveCropperZoom = useCallback(\n\t\t(zoom: number) => {\n\t\t\tif (!activeImageKey) return;\n\n\t\t\tsetCropperStateByImage((currentState) => ({\n\t\t\t\t...currentState,\n\t\t\t\t[activeImageKey]: {\n\t\t\t\t\tcrop: currentState[activeImageKey]?.crop ?? { x: 0, y: 0 },\n\t\t\t\t\tzoom\n\t\t\t\t}\n\t\t\t}));\n\t\t},\n\t\t[activeImageKey]\n\t);\n\n\tconst apply = useCallback(() => {\n\t\tonApply?.(resolvedValue);\n\t}, [onApply, resolvedValue]);\n\n\treturn {\n\t\tvalue: resolvedValue,\n\t\tfiles,\n\t\tactiveIndex,\n\t\tactiveImage,\n\t\tactiveCropperState,\n\t\thasSelected,\n\t\tcanApply,\n\t\tapply,\n\t\tsetFiles,\n\t\tsetActiveIndex,\n\t\tsetActiveAlt,\n\t\tsetActiveCrop,\n\t\tsetActiveCropperCrop,\n\t\tsetActiveCropperZoom\n\t};\n}\n","import { type CSSProperties } from \"react\";\n\nimport { type SelectedImageData } from \"../model/imageSelectionTypes\";\n\nexport type ImageNaturalSize = {\n\twidth: number;\n\theight: number;\n};\n\n/** Масштабирует preview так, чтобы контейнер показывал только выбранную область crop. */\nexport function getImageCropPreviewStyle(image: SelectedImageData, size: ImageNaturalSize | undefined, aspect: number): CSSProperties {\n\tif (!image.crop || !size) {\n\t\treturn {\n\t\t\twidth: \"100%\",\n\t\t\taspectRatio: aspect,\n\t\t\tobjectFit: \"cover\",\n\t\t\tdisplay: \"block\"\n\t\t};\n\t}\n\n\tconst crop = image.crop;\n\n\treturn {\n\t\tposition: \"absolute\",\n\t\tleft: `${-(crop.x / crop.width) * 100}%`,\n\t\ttop: `${-(crop.y / crop.height) * 100}%`,\n\t\twidth: `${(size.width / crop.width) * 100}%`,\n\t\theight: `${(size.height / crop.height) * 100}%`,\n\t\tmaxWidth: \"none\"\n\t};\n}\n","import { useState } from \"react\";\n\nimport { GridContainer } from \"../../grid\";\nimport { InputText } from \"../../input\";\nimport { InputFiles } from \"../../input-files\";\nimport { getImageCropPreviewStyle, type ImageNaturalSize } from \"../lib/getImageCropPreviewStyle\";\nimport { getImageSelectionKey } from \"../lib/getImageSelectionKey\";\nimport { type ImageSelectionPanelProps, type ImageSelectionState } from \"../model/imageSelectionTypes\";\n\nimport { ImageCropper } from \"./ImageCropper\";\n\nconst DEFAULT_ALLOWED_IMAGE_MIME = [\"image/jpeg\", \"image/png\", \"image/webp\", \"image/avif\"] as const;\n\ninterface ImageSelectionFieldsProps extends Pick<\n\tImageSelectionPanelProps,\n\t\"aspect\" | \"disabled\" | \"allowedMime\" | \"maxBytes\" | \"minimumCropWidth\" | \"onReadError\"\n> {\n\tstate: ImageSelectionState;\n}\n\n/** Поля выбора файлов, crop и альтернативного текста для активного изображения. */\nexport function ImageSelectionFields({\n\taspect = 16 / 9,\n\tdisabled,\n\tallowedMime = DEFAULT_ALLOWED_IMAGE_MIME,\n\tmaxBytes,\n\tminimumCropWidth,\n\tonReadError,\n\tstate\n}: ImageSelectionFieldsProps) {\n\tconst area = state.activeImage?.crop;\n\tconst [imageSizes, setImageSizes] = useState<Record<string, ImageNaturalSize>>({});\n\n\treturn (\n\t\t<GridContainer gap=\"md\">\n\t\t\t<InputFiles\n\t\t\t\tlabel=\"Файл изображения\"\n\t\t\t\tallowedMime={allowedMime}\n\t\t\t\tvalue={state.files}\n\t\t\t\tonChange={state.setFiles}\n\t\t\t\tmaxBytes={maxBytes}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonReadError={onReadError}\n\t\t\t/>\n\n\t\t\t{state.hasSelected && state.activeImage && (\n\t\t\t\t<div>\n\t\t\t\t\t<GridContainer templateColumns=\"repeat(auto-fill, minmax(10em, 1fr))\" gap=\"xs\">\n\t\t\t\t\t\t{state.value.map((image, index) => {\n\t\t\t\t\t\t\tconst imageKey = getImageSelectionKey(image, index);\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={imageKey}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\tonClick={() => state.setActiveIndex(index)}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\t\t\tborder: index === state.activeIndex ? \"2px solid var(--border-accent)\" : \"2px solid transparent\",\n\t\t\t\t\t\t\t\t\t\tbackground: \"transparent\",\n\t\t\t\t\t\t\t\t\t\tcursor: disabled ? \"default\" : \"pointer\"\n\t\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\t\t\t\t\t\t\tdisplay: \"block\",\n\t\t\t\t\t\t\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\t\t\t\t\t\t\taspectRatio: aspect,\n\t\t\t\t\t\t\t\t\t\t\toverflow: \"hidden\"\n\t\t\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\tsrc={image.file.dataUrl}\n\t\t\t\t\t\t\t\t\t\t\talt={image.alt || `Предпросмотр изображения ${index + 1}`}\n\t\t\t\t\t\t\t\t\t\t\tstyle={getImageCropPreviewStyle(image, imageSizes[imageKey], aspect)}\n\t\t\t\t\t\t\t\t\t\t\tonLoad={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst target = event.currentTarget;\n\n\t\t\t\t\t\t\t\t\t\t\t\tsetImageSizes((currentSizes) => ({\n\t\t\t\t\t\t\t\t\t\t\t\t\t...currentSizes,\n\t\t\t\t\t\t\t\t\t\t\t\t\t[imageKey]: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: target.naturalWidth,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: target.naturalHeight\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</GridContainer>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\tВыберите область изображения{\" \"}\n\t\t\t\t\t\t{area && (\n\t\t\t\t\t\t\t<code className={minimumCropWidth && area.width < minimumCropWidth ? \"statusError\" : \"statusSuccess\"}>\n\t\t\t\t\t\t\t\t{area.width}x{area.height}\n\t\t\t\t\t\t\t\t{minimumCropWidth && area.width < minimumCropWidth ? \" — недостаточная ширина\" : \"\"}\n\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<ImageCropper\n\t\t\t\t\t\tkey={getImageSelectionKey(state.activeImage, state.activeIndex)}\n\t\t\t\t\t\timage={state.activeImage.file.dataUrl}\n\t\t\t\t\t\tcrop={state.activeCropperState.crop}\n\t\t\t\t\t\tzoom={state.activeCropperState.zoom}\n\t\t\t\t\t\taspect={aspect}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tonCropChange={state.setActiveCropperCrop}\n\t\t\t\t\t\tonZoomChange={state.setActiveCropperZoom}\n\t\t\t\t\t\tonCropComplete={state.setActiveCrop}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<InputText\n\t\t\t\trequired\n\t\t\t\tdisabled={!state.hasSelected || disabled}\n\t\t\t\tlabel=\"Краткое описание изображения\"\n\t\t\t\tplaceholder=\"\"\n\t\t\t\tvalue={state.activeImage?.alt ?? \"\"}\n\t\t\t\tonChange={state.setActiveAlt}\n\t\t\t/>\n\t\t</GridContainer>\n\t);\n}\n","import { Button } from \"../../button\";\nimport { Modal, ModalContent, ModalFooter } from \"../../modal\";\nimport { type ImageSelectionModalProps } from \"../model/imageSelectionTypes\";\nimport { useImageSelectionState } from \"../model/useImageSelectionState\";\n\nimport { ImageSelectionFields } from \"./ImageSelectionFields\";\n\n/** Модальная форма выбора изображений с необязательным этапом подтверждения. */\nexport function ImageSelectionModal({\n\tdisabled,\n\tisOpen = true,\n\tonClose = () => {},\n\ttitle = \"Загрузка нового изображения\",\n\t...props\n}: ImageSelectionModalProps) {\n\tconst state = useImageSelectionState({ ...props, disabled });\n\n\tif (!props.onApply) {\n\t\treturn (\n\t\t\t<Modal isOpen={isOpen} onClose={onClose} title={title} size=\"xl\">\n\t\t\t\t<ModalContent scrollable>\n\t\t\t\t\t<ImageSelectionFields {...props} disabled={disabled} state={state} />\n\t\t\t\t</ModalContent>\n\t\t\t</Modal>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Modal isOpen={isOpen} onClose={onClose} title={title} size=\"xl\">\n\t\t\t<ModalContent scrollable>\n\t\t\t\t<ImageSelectionFields {...props} disabled={disabled} state={state} />\n\t\t\t</ModalContent>\n\t\t\t<ModalFooter>\n\t\t\t\t<Button disabled={!state.canApply} tone=\"success\" onClick={state.apply}>\n\t\t\t\t\tПрименить\n\t\t\t\t</Button>\n\t\t\t</ModalFooter>\n\t\t</Modal>\n\t);\n}\n","import { Button } from \"../../button\";\nimport { type ImageSelectionActionsData, type ImageSelectionPanelProps } from \"../model/imageSelectionTypes\";\nimport { useImageSelectionState } from \"../model/useImageSelectionState\";\n\nimport { ImageSelectionFields } from \"./ImageSelectionFields\";\n\n/** Встраиваемая форма выбора и обрезки одного или нескольких изображений. */\nexport function ImageSelectionPanel({ disabled, renderActions, ...props }: ImageSelectionPanelProps) {\n\tconst state = useImageSelectionState({ ...props, disabled });\n\tconst actionsData: ImageSelectionActionsData = {\n\t\tvalue: state.value,\n\t\tactiveIndex: state.activeIndex,\n\t\thasSelected: state.hasSelected,\n\t\tcanApply: state.canApply,\n\t\tapply: state.apply\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<ImageSelectionFields {...props} disabled={disabled} state={state} />\n\t\t\t{renderActions\n\t\t\t\t? renderActions(actionsData)\n\t\t\t\t: props.onApply && (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<Button disabled={!state.canApply} tone=\"success\" onClick={state.apply}>\n\t\t\t\t\t\t\t\tПрименить\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t</>\n\t);\n}\n","import { type ImgHTMLAttributes } from \"react\";\n\nimport { buildImageSources } from \"../lib/buildImageSources\";\nimport { buildImageSrcSet } from \"../lib/buildImageSrcSet\";\nimport { type ResponsiveImageData } from \"../model/imageTypes\";\n\nimport { ImageRenderer, type ImageRendererProps } from \"./ImageRenderer\";\n\nexport interface ImageViewProps\n\textends\n\t\tOmit<ImageRendererProps, \"src\" | \"sources\" | \"alt\" | \"intrinsicWidth\" | \"intrinsicHeight\" | \"srcSet\" | \"sizes\">,\n\t\tPick<ImgHTMLAttributes<HTMLImageElement>, \"sizes\"> {\n\timage: ResponsiveImageData;\n\talt?: string;\n}\n\n/**\n * Собирает picture/srcset из готовых URL и делегирует отображение ImageRenderer.\n * Компонент не формирует имена файлов и не знает о форматах или размерах хранилища.\n */\nexport function ImageView({ image, alt, sizes, aspectRatio, ...props }: ImageViewProps) {\n\tconst sources = buildImageSources(image.sources, sizes);\n\tconst srcSet = image.candidates ? buildImageSrcSet(image.candidates) : undefined;\n\tconst resolvedAspectRatio =\n\t\taspectRatio ?? (image.intrinsicWidth && image.intrinsicHeight ? `${image.intrinsicWidth} / ${image.intrinsicHeight}` : undefined);\n\n\treturn (\n\t\t<ImageRenderer\n\t\t\t{...props}\n\t\t\tsrc={image.src}\n\t\t\tsrcSet={srcSet || undefined}\n\t\t\tsources={sources}\n\t\t\tsizes={sizes}\n\t\t\talt={alt ?? image.alt}\n\t\t\tintrinsicWidth={image.intrinsicWidth}\n\t\t\tintrinsicHeight={image.intrinsicHeight}\n\t\t\taspectRatio={resolvedAspectRatio}\n\t\t/>\n\t);\n}\n","import { lazy, Suspense, useCallback, useState } from \"react\";\n\nimport { type ImageViewerProps } from \"../model/imageViewerTypes\";\n\nimport \"yet-another-react-lightbox/plugins/captions.css\";\nimport \"yet-another-react-lightbox/plugins/counter.css\";\nimport \"yet-another-react-lightbox/plugins/thumbnails.css\";\nimport \"yet-another-react-lightbox/styles.css\";\n\nconst LazyImageViewerRuntime = lazy(() => import(\"./ImageViewerRuntime\"));\n\n/**\n * Управляемый полноэкранный viewer с ленивой границей vendor runtime.\n * YARL и его плагины загружаются только при первом открытии, а после mount runtime остаётся в React-дереве,\n * чтобы закрытие успело завершить анимацию, снять inert и вернуть focus исходному trigger.\n */\nexport function ImageViewer(props: ImageViewerProps) {\n\tconst [runtimeMounted, setRuntimeMounted] = useState(false);\n\tconst handleRuntimeMounted = useCallback(() => setRuntimeMounted(true), []);\n\tconst canRenderRuntime = typeof document !== \"undefined\" && (props.open || runtimeMounted);\n\n\tif (!canRenderRuntime) return null;\n\n\treturn (\n\t\t<Suspense fallback={null}>\n\t\t\t<LazyImageViewerRuntime {...props} onRuntimeMounted={handleRuntimeMounted} />\n\t\t</Suspense>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Slide } from "yet-another-react-lightbox";
|
|
2
|
+
import { type ImageViewerImage } from "../model/imageViewerTypes";
|
|
3
|
+
/**
|
|
4
|
+
* Адаптирует storage-agnostic ResponsiveImageData к image slides Yet Another React Lightbox.
|
|
5
|
+
* Функция остаётся приватной для `/image`, чтобы vendor contract не становился public API пакета.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildImageViewerSlides(images: readonly ImageViewerImage[]): Slide[];
|
|
8
|
+
//# sourceMappingURL=buildImageViewerSlides.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildImageViewerSlides.d.ts","sourceRoot":"","sources":["../../../src/image/lib/buildImageViewerSlides.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAGxD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAqDlE;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAAG,KAAK,EAAE,CAgBnF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ImageViewerLabels } from "../model/imageViewerTypes";
|
|
2
|
+
/** Преобразует стабильные semantic labels foundation в ключи локализации YARL. */
|
|
3
|
+
export declare function resolveImageViewerLabels(overrides: Partial<ImageViewerLabels> | undefined): {
|
|
4
|
+
Previous: string;
|
|
5
|
+
Next: string;
|
|
6
|
+
Close: string;
|
|
7
|
+
Slide: string;
|
|
8
|
+
Carousel: string;
|
|
9
|
+
Lightbox: string;
|
|
10
|
+
"Photo gallery": string;
|
|
11
|
+
"{index} of {total}": string;
|
|
12
|
+
"Zoom in": string;
|
|
13
|
+
"Zoom out": string;
|
|
14
|
+
"Enter Fullscreen": string;
|
|
15
|
+
"Exit Fullscreen": string;
|
|
16
|
+
Thumbnails: string;
|
|
17
|
+
"Show thumbnails": string;
|
|
18
|
+
"Hide thumbnails": string;
|
|
19
|
+
Caption: string;
|
|
20
|
+
"Show captions": string;
|
|
21
|
+
"Hide captions": string;
|
|
22
|
+
Download: string;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=resolveImageViewerLabels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveImageViewerLabels.d.ts","sourceRoot":"","sources":["../../../src/image/lib/resolveImageViewerLabels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAwBnE,kFAAkF;AAClF,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,SAAS;;;;;;;;;;;;;;;;;;;;EAwBzF"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
import { type ResponsiveImageData } from "./imageTypes";
|
|
3
|
+
type ImageViewerDownload = false | string | {
|
|
4
|
+
readonly url: string;
|
|
5
|
+
readonly filename: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Изображение lightbox поверх базового responsive-контракта.
|
|
9
|
+
* Дополнительные поля описывают только представление в viewer и не связывают primitive со схемой хранения.
|
|
10
|
+
*/
|
|
11
|
+
export type ImageViewerImage = ResponsiveImageData & {
|
|
12
|
+
readonly title?: ReactNode;
|
|
13
|
+
readonly description?: ReactNode;
|
|
14
|
+
readonly thumbnail?: string;
|
|
15
|
+
readonly download?: ImageViewerDownload;
|
|
16
|
+
};
|
|
17
|
+
/** Набор независимо включаемых возможностей ImageViewer. */
|
|
18
|
+
export type ImageViewerFeatures = {
|
|
19
|
+
readonly captions?: boolean;
|
|
20
|
+
readonly counter?: boolean;
|
|
21
|
+
readonly download?: boolean;
|
|
22
|
+
readonly fullscreen?: boolean;
|
|
23
|
+
readonly thumbnails?: boolean;
|
|
24
|
+
readonly zoom?: boolean;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Семантические подписи viewer без раскрытия ключей конкретной lightbox-библиотеки.
|
|
28
|
+
* Шаблон slideCounter поддерживает маркеры `{index}` и `{total}`.
|
|
29
|
+
*/
|
|
30
|
+
export type ImageViewerLabels = {
|
|
31
|
+
readonly previous: string;
|
|
32
|
+
readonly next: string;
|
|
33
|
+
readonly close: string;
|
|
34
|
+
readonly slide: string;
|
|
35
|
+
readonly carousel: string;
|
|
36
|
+
readonly lightbox: string;
|
|
37
|
+
readonly photoGallery: string;
|
|
38
|
+
readonly slideCounter: string;
|
|
39
|
+
readonly zoomIn: string;
|
|
40
|
+
readonly zoomOut: string;
|
|
41
|
+
readonly enterFullscreen: string;
|
|
42
|
+
readonly exitFullscreen: string;
|
|
43
|
+
readonly thumbnails: string;
|
|
44
|
+
readonly showThumbnails: string;
|
|
45
|
+
readonly hideThumbnails: string;
|
|
46
|
+
readonly caption: string;
|
|
47
|
+
readonly showCaptions: string;
|
|
48
|
+
readonly hideCaptions: string;
|
|
49
|
+
readonly download: string;
|
|
50
|
+
};
|
|
51
|
+
type ImageViewerCssVariable = "--image-viewer-z-index" | "--image-viewer-backdrop" | "--image-viewer-control-color" | "--image-viewer-control-active-color" | "--image-viewer-control-disabled-color" | "--image-viewer-control-background" | "--image-viewer-control-border" | "--image-viewer-control-radius" | "--image-viewer-control-filter" | "--image-viewer-icon-size" | "--image-viewer-icon-stroke-width" | "--image-viewer-toolbar-padding" | "--image-viewer-focus" | "--image-viewer-focus-offset" | "--image-viewer-image-radius" | "--image-viewer-caption-background" | "--image-viewer-caption-color" | "--image-viewer-counter-color" | "--image-viewer-thumbnail-background" | "--image-viewer-thumbnail-border-color" | "--image-viewer-thumbnail-active-border-color" | "--image-viewer-loading-color" | "--image-viewer-error-color";
|
|
52
|
+
/** Inline-стили viewer с типизированным публичным набором CSS-переменных. */
|
|
53
|
+
export type ImageViewerStyle = CSSProperties & Partial<Record<ImageViewerCssVariable, string | number>>;
|
|
54
|
+
/** Публичный controlled-контракт полноэкранного просмотра изображений. */
|
|
55
|
+
export type ImageViewerProps = {
|
|
56
|
+
readonly open: boolean;
|
|
57
|
+
readonly images: readonly ImageViewerImage[];
|
|
58
|
+
readonly index?: number;
|
|
59
|
+
readonly onClose: () => void;
|
|
60
|
+
readonly onIndexChange?: (index: number) => void;
|
|
61
|
+
readonly features?: ImageViewerFeatures;
|
|
62
|
+
readonly loop?: boolean;
|
|
63
|
+
readonly closeOnBackdropClick?: boolean;
|
|
64
|
+
readonly closeOnPullDown?: boolean;
|
|
65
|
+
readonly labels?: Partial<ImageViewerLabels>;
|
|
66
|
+
readonly className?: string;
|
|
67
|
+
readonly style?: ImageViewerStyle;
|
|
68
|
+
};
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=imageViewerTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageViewerTypes.d.ts","sourceRoot":"","sources":["../../../src/image/model/imageViewerTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ImageViewerProps } from "../model/imageViewerTypes";
|
|
2
|
+
import "yet-another-react-lightbox/plugins/captions.css";
|
|
3
|
+
import "yet-another-react-lightbox/plugins/counter.css";
|
|
4
|
+
import "yet-another-react-lightbox/plugins/thumbnails.css";
|
|
5
|
+
import "yet-another-react-lightbox/styles.css";
|
|
6
|
+
/**
|
|
7
|
+
* Управляемый полноэкранный viewer с ленивой границей vendor runtime.
|
|
8
|
+
* YARL и его плагины загружаются только при первом открытии, а после mount runtime остаётся в React-дереве,
|
|
9
|
+
* чтобы закрытие успело завершить анимацию, снять inert и вернуть focus исходному trigger.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ImageViewer(props: ImageViewerProps): import("react").JSX.Element | null;
|
|
12
|
+
//# sourceMappingURL=ImageViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageViewer.d.ts","sourceRoot":"","sources":["../../../src/image/ui/ImageViewer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,iDAAiD,CAAC;AACzD,OAAO,gDAAgD,CAAC;AACxD,OAAO,mDAAmD,CAAC;AAC3D,OAAO,uCAAuC,CAAC;AAI/C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,sCAYlD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ImageViewerProps } from "../model/imageViewerTypes";
|
|
2
|
+
type ImageViewerRuntimeProps = ImageViewerProps & {
|
|
3
|
+
readonly onRuntimeMounted: () => void;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Тяжёлый runtime ImageViewer, изолированный в отдельном динамическом chunk.
|
|
7
|
+
* Компонент приватен для `/image`: YARL-типы и plugin-контракты не должны становиться API foundation.
|
|
8
|
+
*/
|
|
9
|
+
export default function ImageViewerRuntime({ open, images, index, onClose, onIndexChange, features, loop, closeOnBackdropClick, closeOnPullDown, labels, className, style, onRuntimeMounted }: ImageViewerRuntimeProps): import("react").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=ImageViewerRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageViewerRuntime.d.ts","sourceRoot":"","sources":["../../../src/image/ui/ImageViewerRuntime.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAIlE,KAAK,uBAAuB,GAAG,gBAAgB,GAAG;IACjD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,IAAI,CAAC;CACtC,CAAC;AAKF;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAC1C,IAAI,EACJ,MAAM,EACN,KAAS,EACT,OAAO,EACP,aAAa,EACb,QAAQ,EACR,IAAY,EACZ,oBAA2B,EAC3B,eAAsB,EACtB,MAAM,EACN,SAAS,EACT,KAAK,EACL,gBAAgB,EAChB,EAAE,uBAAuB,+BA6FzB"}
|