@ryuzaki13/react-foundation-ui 1.4.2 → 1.4.3
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/advanced-search/index.js +12 -11
- package/dist/advanced-search/index.js.map +1 -1
- package/dist/badge/index.js +1 -1
- package/dist/base-table/index.js +2 -2
- package/dist/button/index.js +1 -1
- package/dist/chunks/{CalendarView-KCkhCtK-.js → CalendarView-Z_XWk7aI.js} +8 -8
- package/dist/chunks/{CalendarView-KCkhCtK-.js.map → CalendarView-Z_XWk7aI.js.map} +1 -1
- package/dist/chunks/{ImageViewerRuntime-RN49by8Y.js → ImageViewerRuntime-BMs3BBkV.js} +4 -4
- package/dist/chunks/{ImageViewerRuntime-RN49by8Y.js.map → ImageViewerRuntime-BMs3BBkV.js.map} +1 -1
- package/dist/chunks/{TextEditorLexicalClient-CVTrglWP.js → TextEditorLexicalClient-CK8j3RA4.js} +16 -18
- package/dist/chunks/{TextEditorLexicalClient-CVTrglWP.js.map → TextEditorLexicalClient-CK8j3RA4.js.map} +1 -1
- package/dist/chunks/{badge-Cri0-kVK.js → badge-DwIUjH0a.js} +2 -2
- package/dist/chunks/{badge-Cri0-kVK.js.map → badge-DwIUjH0a.js.map} +1 -1
- package/dist/chunks/{base-table-D5IqsjQD.js → base-table-BFsVwXg3.js} +13 -12
- package/dist/chunks/{base-table-D5IqsjQD.js.map → base-table-BFsVwXg3.js.map} +1 -1
- package/dist/chunks/{button-CC0Jdx1j.js → button-BU2kRzwu.js} +2 -2
- package/dist/chunks/{button-CC0Jdx1j.js.map → button-BU2kRzwu.js.map} +1 -1
- package/dist/chunks/check-box-Dd3YFuxd.js.map +1 -1
- package/dist/chunks/{context-menu-DQeR3y7M.js → context-menu-C6RO7soI.js} +7 -2
- package/dist/chunks/{context-menu-DQeR3y7M.js.map → context-menu-C6RO7soI.js.map} +1 -1
- package/dist/chunks/{date-input-DBJisPRz.js → date-input-BzExUQnc.js} +5 -5
- package/dist/chunks/{date-input-DBJisPRz.js.map → date-input-BzExUQnc.js.map} +1 -1
- package/dist/chunks/{flex-DYZ0IbU6.js → flex-C7njxZ74.js} +10 -7
- package/dist/chunks/{flex-DYZ0IbU6.js.map → flex-C7njxZ74.js.map} +1 -1
- package/dist/chunks/floating-arrow-BE-z4QkE.js.map +1 -1
- package/dist/chunks/{input-BCJfUdK_.js → input-Bp6_Ucgr.js} +15 -15
- package/dist/chunks/{input-BCJfUdK_.js.map → input-Bp6_Ucgr.js.map} +1 -1
- package/dist/chunks/{input-files-Dcc5K-_1.js → input-files-D1JzSw_Y.js} +2 -2
- package/dist/chunks/{input-files-Dcc5K-_1.js.map → input-files-D1JzSw_Y.js.map} +1 -1
- package/dist/chunks/{input-search-B7HmrAM7.js → input-search-Bkhcinru.js} +2 -2
- package/dist/chunks/{input-search-B7HmrAM7.js.map → input-search-Bkhcinru.js.map} +1 -1
- package/dist/chunks/{misc-DIF5h9ba.js → misc-BYxxlJz6.js} +3 -3
- package/dist/chunks/{misc-DIF5h9ba.js.map → misc-BYxxlJz6.js.map} +1 -1
- package/dist/chunks/{modal-DXHX_sA-.js → modal-paexEF0j.js} +4 -5
- package/dist/chunks/{modal-DXHX_sA-.js.map → modal-paexEF0j.js.map} +1 -1
- package/dist/chunks/{multi-select-CWx12rgb.js → multi-select-COa6-owj.js} +3 -3
- package/dist/chunks/{multi-select-CWx12rgb.js.map → multi-select-COa6-owj.js.map} +1 -1
- package/dist/chunks/{picker-BAQ9NeHe.js → picker-e6IsrMUG.js} +3 -3
- package/dist/chunks/{picker-BAQ9NeHe.js.map → picker-e6IsrMUG.js.map} +1 -1
- package/dist/chunks/{popover-xJJqy1v6.js → popover-CGU3MlsH.js} +14 -14
- package/dist/chunks/{popover-xJJqy1v6.js.map → popover-CGU3MlsH.js.map} +1 -1
- package/dist/chunks/radio-group-CM9Lg_nc.js.map +1 -1
- package/dist/chunks/{select-BPb-eL3O.js → select-C95db02j.js} +32 -31
- package/dist/chunks/{select-BPb-eL3O.js.map → select-C95db02j.js.map} +1 -1
- package/dist/chunks/sortable-DcTIAbjD.js.map +1 -1
- package/dist/chunks/{table-xMAjqtcY.js → table-Dd5BcC0k.js} +3 -3
- package/dist/chunks/{table-xMAjqtcY.js.map → table-Dd5BcC0k.js.map} +1 -1
- package/dist/chunks/{table-column-interactions-BGd5Lwy9.js → table-column-interactions-DzEvVuXe.js} +8 -5
- package/dist/chunks/{table-column-interactions-BGd5Lwy9.js.map → table-column-interactions-DzEvVuXe.js.map} +1 -1
- package/dist/chunks/useODataSelectBase-CKe1AVMI.js.map +1 -1
- package/dist/chunks/wheel-picker-FS58cRsQ.js.map +1 -1
- package/dist/context-menu/index.js +1 -1
- package/dist/date-input/index.js +2 -2
- package/dist/date-time-input/index.js +4 -4
- package/dist/date-time-input/index.js.map +1 -1
- package/dist/detail/index.js.map +1 -1
- package/dist/dialog/index.js.map +1 -1
- package/dist/disclosure/index.js +1 -1
- package/dist/disclosure/index.js.map +1 -1
- package/dist/drop-zone/index.js +1 -1
- package/dist/drop-zone/index.js.map +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/expandable-action-panel/index.js +2 -2
- package/dist/expandable-action-panel/index.js.map +1 -1
- package/dist/flex/index.js +1 -1
- package/dist/fullscreen-portal/index.js +3 -3
- package/dist/fullscreen-portal/index.js.map +1 -1
- package/dist/image/index.js +5 -5
- package/dist/image/index.js.map +1 -1
- package/dist/input/index.js +1 -1
- package/dist/input-date-time/index.js +1 -1
- package/dist/input-date-time/index.js.map +1 -1
- package/dist/input-file/index.js +1 -1
- package/dist/input-file/index.js.map +1 -1
- package/dist/input-files/index.js +1 -1
- package/dist/input-image/index.js +1 -1
- package/dist/input-image/index.js.map +1 -1
- package/dist/input-search/index.js +1 -1
- package/dist/layout-picker/index.js +3 -3
- package/dist/layout-picker/index.js.map +1 -1
- package/dist/list/index.js +7 -7
- package/dist/list/index.js.map +1 -1
- package/dist/listbox/index.js.map +1 -1
- package/dist/misc/index.js +1 -1
- package/dist/modal/index.js +1 -1
- package/dist/multi-select/index.js +1 -1
- package/dist/notifications/index.js +13 -11
- package/dist/notifications/index.js.map +1 -1
- package/dist/pages/index.js.map +1 -1
- package/dist/panel/index.js.map +1 -1
- package/dist/picker/index.js +1 -1
- package/dist/popover/index.js +1 -1
- package/dist/preset-range-date-input/index.js +2 -2
- package/dist/preset-range-date-input/index.js.map +1 -1
- package/dist/preset-select/index.js +1 -1
- package/dist/radio-button/index.js.map +1 -1
- package/dist/select/index.js +1 -1
- package/dist/simple-table/index.js +1 -1
- package/dist/slider/index.js +27 -24
- package/dist/slider/index.js.map +1 -1
- package/dist/splitter/index.js.map +1 -1
- package/dist/state-select/index.js +12 -10
- package/dist/state-select/index.js.map +1 -1
- package/dist/switch/index.js +1 -1
- package/dist/switch/index.js.map +1 -1
- package/dist/table/index.js +1 -1
- package/dist/table-column-interactions/index.js +1 -1
- package/dist/table-sorting/index.js +1 -1
- package/dist/table-sorting/index.js.map +1 -1
- package/dist/tabs/index.js +6 -6
- package/dist/tabs/index.js.map +1 -1
- package/dist/tag-input/index.js +1 -1
- package/dist/tag-input/index.js.map +1 -1
- package/dist/text/index.js +10 -8
- package/dist/text/index.js.map +1 -1
- package/dist/text-editor/index.js +2 -2
- package/dist/textarea/index.js +1 -1
- package/dist/textarea/index.js.map +1 -1
- package/dist/toggle/index.js.map +1 -1
- package/dist/toolbar/index.js +1 -2
- package/dist/toolbar/index.js.map +1 -1
- package/dist/tree/index.js.map +1 -1
- package/dist/tree-select/index.js +83 -80
- package/dist/tree-select/index.js.map +1 -1
- package/dist/tree-table/index.js +2 -2
- package/dist/tree-table/index.js.map +1 -1
- package/package.json +51 -59
- package/storybook-static/assets/{Badge-SZ48u9qp.js → Badge-DHexWW92.js} +11 -11
- package/storybook-static/assets/Badge.stories-CeWDekpP.js +54 -0
- package/storybook-static/assets/Button-VdPdxcvG.js +12 -0
- package/storybook-static/assets/{Button-CFCpYiPy.js → Button-kybsFNS9.js} +10 -10
- package/storybook-static/assets/Button.stories-DhgYDM_q.js +75 -0
- package/storybook-static/assets/{DateInput-BfFTwd_P.css → CalendarView-DKvrkS40.css} +1 -1
- package/storybook-static/assets/CalendarView-DTX0eO8t.js +1 -0
- package/storybook-static/assets/CheckBox-B6rTemHK.js +2 -0
- package/storybook-static/assets/{CheckBox-FoMSruZC.js → CheckBox-CDwboiFD.js} +11 -11
- package/storybook-static/assets/CheckBox.module-BBzuj5He.js +1 -0
- package/storybook-static/assets/CheckBox.stories-BSMihxpY.js +60 -0
- package/storybook-static/assets/Color-6AOWCN3U-D5F38IUU.js +1 -0
- package/storybook-static/assets/{ContextMenu-CU_1kOzV.js → ContextMenu-2ZQAeo_p.js} +9 -9
- package/storybook-static/assets/ContextMenu-CQtvL8kx.js +1 -0
- package/storybook-static/assets/ContextMenu.stories-Dtz2YIGk.js +90 -0
- package/storybook-static/assets/{DateInput-BeZ5esVE.js → DateInput-D41aWZ7_.js} +11 -11
- package/storybook-static/assets/DateInput-DBwgBhFj.js +1 -0
- package/storybook-static/assets/DateInput-pmGiwdvw.css +1 -0
- package/storybook-static/assets/{DateInput.stories-Bkw2r8CD.js → DateInput.stories-CMV96t-8.js} +2 -2
- package/storybook-static/assets/{DateRangePresetSelect-C_mLvEoK.js → DateRangePresetSelect-BLKJkg8X.js} +8 -8
- package/storybook-static/assets/DateRangePresetSelect-DXYYFJJn.js +3 -0
- package/storybook-static/assets/DateRangePresetSelect.stories-BNtFx_iG.js +11 -0
- package/storybook-static/assets/{Detail-WzciiK9S.js → Detail-BHcGLZok.js} +11 -11
- package/storybook-static/assets/Detail.stories-C4smn8Uu.js +44 -0
- package/storybook-static/assets/{Dialog-CwLsVxJY.js → Dialog-kji1ho-G.js} +9 -9
- package/storybook-static/assets/Dialog.stories-DYzrVcIT.js +31 -0
- package/storybook-static/assets/{Disclosure-BlRuGrk2.js → Disclosure-BVLfp53o.js} +10 -10
- package/storybook-static/assets/Disclosure.stories-DcV1pGCt.js +41 -0
- package/storybook-static/assets/DocsRenderer-JROSPFPF-CCwX0YiR.js +2 -0
- package/storybook-static/assets/{DropZone-Cr3nfCWA.js → DropZone-6iWHt6C_.js} +10 -10
- package/storybook-static/assets/DropZone.stories-bASZNbD5.js +44 -0
- package/storybook-static/assets/ExpandableActionPanel.stories-CMMbHs_d.js +20 -0
- package/storybook-static/assets/{Flex-C10912WS.js → Flex-BJViOwhH.js} +18 -18
- package/storybook-static/assets/Flex.stories-CI6DdxU7.js +300 -0
- package/storybook-static/assets/FlexContainer-LmZIdhq2.js +1 -0
- package/storybook-static/assets/FlexItem-vkDYa5tA.js +3 -0
- package/storybook-static/assets/FloatingPopover-CPLOruAY.js +1 -0
- package/storybook-static/assets/FloatingPopover-DC84VrV3.css +1 -0
- package/storybook-static/assets/FormattedTableCell-CV4yLuxl.js +18 -0
- package/storybook-static/assets/FormattedTableCell-CY3E21k8.css +1 -0
- package/storybook-static/assets/Grid-BCzygAqy.js +52 -0
- package/storybook-static/assets/{Grid-G88y3oB_.js → Grid-CNEn2bRE.js} +18 -18
- package/storybook-static/assets/{Grid.stories-BV7zL-6n.js → Grid.stories-qFo5E3qE.js} +2 -2
- package/storybook-static/assets/{Grid-Bb0gH6CX.js → GridContainer-qDguE1HS.js} +2 -53
- package/storybook-static/assets/ImageCropper.stories-BeQI7oKQ.js +115 -0
- package/storybook-static/assets/ImageRenderer-DK2ibQyr.js +2 -0
- package/storybook-static/assets/ImageRenderer.stories-C1T4ne0G.js +22 -0
- package/storybook-static/assets/ImageView.stories-D_Q-ZBtQ.js +9 -0
- package/storybook-static/assets/{ImageViewer.stories-PlFXSB5n.js → ImageViewer.stories-boombTJI.js} +5 -5
- package/storybook-static/assets/ImageViewerRuntime-D8KSESgf.js +51 -0
- package/storybook-static/assets/{Input-pyUNDVtk.js → Input-CGHba0oM.js} +11 -11
- package/storybook-static/assets/Input-DtOsW7ur.js +3 -0
- package/storybook-static/assets/Input.stories-C0qWd6SH.js +38 -0
- package/storybook-static/assets/{InputDateTime-CWk5KBwD.js → InputDateTime-CgYkmVYu.js} +11 -11
- package/storybook-static/assets/InputDateTime.stories-Brxo7Chn.js +35 -0
- package/storybook-static/assets/{InputFile-BLQq7mY9.js → InputFile-Bsxafe88.js} +10 -10
- package/storybook-static/assets/InputFile.stories-BzEV7ybE.js +36 -0
- package/storybook-static/assets/{InputFiles-B6J4XBdP.js → InputFiles-KJFUsmSS.js} +10 -10
- package/storybook-static/assets/InputFiles.stories-ffjxiHSh.js +33 -0
- package/storybook-static/assets/InputFilesList-D6B5g99M.js +1 -0
- package/storybook-static/assets/{InputImage--2PSB_E_.js → InputImage-Cd39V4Vc.js} +10 -10
- package/storybook-static/assets/InputImage.stories-n-tpY8OO.js +51 -0
- package/storybook-static/assets/{LayoutPicker-RZDisgZ_.js → LayoutPicker-CGQFfQk6.js} +13 -13
- package/storybook-static/assets/LayoutPicker.stories-xSL2qafC.js +449 -0
- package/storybook-static/assets/{Listbox-xwfNjBpV.js → Listbox-CxISK8c5.js} +10 -10
- package/storybook-static/assets/Listbox.stories-BdQBmVFI.js +47 -0
- package/storybook-static/assets/{Modal-HJt_Y-a6.js → Modal-BiaAWMdV.js} +12 -12
- package/storybook-static/assets/Modal.stories-GV7fGqyd.js +180 -0
- package/storybook-static/assets/MultiSelect-D5XFosSU.js +2 -0
- package/storybook-static/assets/{MultiSelect-CvNsFdE4.js → MultiSelect-Df2CpyNH.js} +11 -11
- package/storybook-static/assets/MultiSelect.stories-BEVQF6hO.js +29 -0
- package/storybook-static/assets/MultiSelectToken-CrVawISu.js +1 -0
- package/storybook-static/assets/NoData-C7KqaHUh.css +1 -0
- package/storybook-static/assets/NoData-Fm23iF4n.js +1 -0
- package/storybook-static/assets/{NotificationsHost-DXCf3CQX.js → NotificationsHost-C2vSwAjz.js} +9 -9
- package/storybook-static/assets/NotificationsHost.stories-IbgayDlM.js +25 -0
- package/storybook-static/assets/{ODataMultiSelect-CIJNiwGb.js → ODataMultiSelect-oW3kW0nO.js} +15 -15
- package/storybook-static/assets/ODataMultiSelect.stories-CP6_jGSr.js +73 -0
- package/storybook-static/assets/{ODataSelect-BDga9TUb.js → ODataSelect-CrGF8fyC.js} +15 -15
- package/storybook-static/assets/ODataSelect.stories-DTv31Rkv.js +73 -0
- package/storybook-static/assets/ODataTreeMultiSelect-D0h8H3gw.js +19 -0
- package/storybook-static/assets/ODataTreeMultiSelect.stories-CM8QjG8r.js +30 -0
- package/storybook-static/assets/ODataTreeSelect-PWn0-hI4.js +17 -0
- package/storybook-static/assets/ODataTreeSelect.stories-2UkFTnbE.js +24 -0
- package/storybook-static/assets/OneStepScroller-CH6K7wiO.js +5 -0
- package/storybook-static/assets/OneStepScroller-NRYd-egY.css +1 -0
- package/storybook-static/assets/{PeriodSelect-BJbjl62O.js → PeriodSelect-BtwJuAO6.js} +13 -13
- package/storybook-static/assets/PeriodSelect.stories-BH8I5Wmg.js +64 -0
- package/storybook-static/assets/PickerSelectionToolbar-BcL8-O6n.js +2 -0
- package/storybook-static/assets/PickerTriggerActions-C8Asdp5e.js +1 -0
- package/storybook-static/assets/{Popover-Dg2T0DoN.js → Popover-Ch5btFhR.js} +11 -11
- package/storybook-static/assets/Popover-DGX7JNNK.css +1 -0
- package/storybook-static/assets/Popover-Djns7yXR.js +2 -0
- package/storybook-static/assets/Popover.stories-Bask2I1I.js +69 -0
- package/storybook-static/assets/{PresetRangeDateInput-CNmTMNHF.js → PresetRangeDateInput-DvsTjQNP.js} +8 -8
- package/storybook-static/assets/PresetRangeDateInput.stories-BNfOUWgp.js +15 -0
- package/storybook-static/assets/PresetSelect-9zitP0-V.js +5 -0
- package/storybook-static/assets/{RadioButton-2rfUPkwC.js → RadioButton-Yb9bQKYe.js} +10 -10
- package/storybook-static/assets/RadioButton.stories-FIFxXFVP.js +36 -0
- package/storybook-static/assets/RadioGroup-CWsVqwtm.js +1 -0
- package/storybook-static/assets/{RadioGroup-BduGGVKj.js → RadioGroup-Dn0zL838.js} +10 -10
- package/storybook-static/assets/RadioGroup.stories-B_drop9x.js +42 -0
- package/storybook-static/assets/Scrollable-3Z6b5g0Z.js +1 -0
- package/storybook-static/assets/{Select-DnZ83aZs.js → Select-BaR8D89E.js} +13 -13
- package/storybook-static/assets/Select-BiOxxy0y.js +12 -0
- package/storybook-static/assets/Select.stories-CMlWu7vC.js +46 -0
- package/storybook-static/assets/SelectOptionContent-DhtCMwz6.js +1 -0
- package/storybook-static/assets/{SerializableSelect-BiFhAxAJ.js → SerializableSelect-BDiZo_-M.js} +12 -12
- package/storybook-static/assets/SerializableSelect.stories-DgC6oiRx.js +46 -0
- package/storybook-static/assets/{SingleDateTimeInput-Bc-ifbML.js → SingleDateTimeInput-Dx1fvzyr.js} +12 -12
- package/storybook-static/assets/SingleDateTimeInput.stories-NRUE7nnA.js +78 -0
- package/storybook-static/assets/Slider-DJpzPo7f.js +1 -0
- package/storybook-static/assets/{Slider-DfjBSsR3.js → Slider-aiFcrSGY.js} +15 -15
- package/storybook-static/assets/Slider.stories-B0YHmFf5.js +77 -0
- package/storybook-static/assets/{SliderInput-o9uCcVMP.js → SliderInput-sOoxvdku.js} +16 -16
- package/storybook-static/assets/SliderInput.stories-BYk1V19Z.js +68 -0
- package/storybook-static/assets/{Sortable-B6Y9Q9Yn.js → Sortable-CuVT40f8.js} +13 -13
- package/storybook-static/assets/Sortable.stories-KSWGoKrN.js +141 -0
- package/storybook-static/assets/{Splitter-CfUVnAs7.js → Splitter-EoNOj4XF.js} +11 -11
- package/storybook-static/assets/Splitter.stories-CuAZab2y.js +22 -0
- package/storybook-static/assets/{StateSelect-h0i4M4vO.js → StateSelect-B_M50HZl.js} +10 -10
- package/storybook-static/assets/StateSelect.stories-DQ_MzvL4.js +47 -0
- package/storybook-static/assets/StringToggle.stories-BbRysCKA.js +6 -0
- package/storybook-static/assets/{Switch-CPKaENqL.js → Switch-DO_tyZIc.js} +10 -10
- package/storybook-static/assets/Switch.stories-BQakMoPp.js +26 -0
- package/storybook-static/assets/{Table-xV66crR1.js → Table-CVK5rwmT.js} +22 -22
- package/storybook-static/assets/Table.stories-IZaleOjp.js +122 -0
- package/storybook-static/assets/{Tabs-v9YZeJoc.js → Tabs-DAaWUQb4.js} +15 -15
- package/storybook-static/assets/Tabs.stories-BC8LwG22.js +58 -0
- package/storybook-static/assets/TagInput.stories-CrXD57LV.js +18 -0
- package/storybook-static/assets/Text-cVBcGheg.js +1 -0
- package/storybook-static/assets/{Textarea-CRThqX0z.js → Textarea-9VdIC6G0.js} +10 -10
- package/storybook-static/assets/Textarea.stories-CEaMwEau.js +27 -0
- package/storybook-static/assets/TimePanel-vx1aOwT4.js +1 -0
- package/storybook-static/assets/TimePanel.stories-BKyiLEgy.js +25 -0
- package/storybook-static/assets/Toggle-CyajrRVE.js +1 -0
- package/storybook-static/assets/{Toggle-CzopviU2.js → Toggle-DrNoVpGe.js} +10 -10
- package/storybook-static/assets/Toggle.stories-CT0mQbdm.js +30 -0
- package/storybook-static/assets/TreeMultiSelect-CtDZ1cXU.js +1 -0
- package/storybook-static/assets/TreeMultiSelect-ag5i_Hw_.js +19 -0
- package/storybook-static/assets/TreeMultiSelect.stories-BxrbKopS.js +35 -0
- package/storybook-static/assets/TreePickerBase-DQzUtuAm.js +22 -0
- package/storybook-static/assets/TreeSelect-BNuJBo9x.js +1 -0
- package/storybook-static/assets/TreeSelect-CL8REXC5.js +16 -0
- package/storybook-static/assets/TreeSelect.stories-CsWGc9X0.js +18 -0
- package/storybook-static/assets/{TreeTable-DbzoCcR5.js → TreeTable-DrIFC4Oh.js} +22 -22
- package/storybook-static/assets/TreeTable.stories-Dq5c4_qe.js +83 -0
- package/storybook-static/assets/WithTooltip-7X4HQR7L-Cakt_JaX.js +9 -0
- package/storybook-static/assets/array-BBSjoTRy-CIRmlF93.js +1 -0
- package/storybook-static/assets/{async-D27PcxoG.js → async-0-Te_uje.js} +3 -3
- package/storybook-static/assets/axe-Bq-2xuso.js +20 -0
- package/storybook-static/assets/blocks-Dz3dJBcm.js +48 -0
- package/storybook-static/assets/browserAndReact-kZBm3nQe.js +105 -0
- package/storybook-static/assets/check-BMyoSD8F.js +1 -0
- package/storybook-static/assets/chevron-down-QDFtnGcg.js +1 -0
- package/storybook-static/assets/chevron-left-BoVuWD4h.js +1 -0
- package/storybook-static/assets/chevron-right-DS62_o_9.js +1 -0
- package/storybook-static/assets/chunk-242VQQM5-BMWWiybC.js +1 -0
- package/storybook-static/assets/chunk-DRQKCCAG-CqE-Zrl9.js +1 -0
- package/storybook-static/assets/chunk-IMSF75WX-yvVUwIQZ.js +6 -0
- package/storybook-static/assets/chunk-KJHJLCBK-D-yQfkOi.js +1 -0
- package/storybook-static/assets/chunk-QQBDHPVZ-B98qboss.js +1 -0
- package/storybook-static/assets/chunk-W22LQPXL-DDIvKskF.js +18 -0
- package/storybook-static/assets/circle-alert-CXg50Gb0.js +1 -0
- package/storybook-static/assets/circle-check-BPfYNWmz.js +1 -0
- package/storybook-static/assets/components-BejapTpU.js +241 -0
- package/storybook-static/assets/contextMenu-DtXkMNr6.js +2 -0
- package/storybook-static/assets/date-segments-D3HouZ37.js +1 -0
- package/storybook-static/assets/dom-B3G_GtJw.js +1 -0
- package/storybook-static/assets/download-DnZ6jhvY.js +1 -0
- package/storybook-static/assets/error-BZrNlEUO.js +1 -0
- package/storybook-static/assets/file-vPGnhPr-.js +1 -0
- package/storybook-static/assets/filesAndExcel-CXMXtMjq.js +122 -0
- package/storybook-static/assets/floating-ui.react-PN45KvBS.js +1 -0
- package/storybook-static/assets/formatter-L2YTDE3Q-x0raBH34.js +1 -0
- package/storybook-static/assets/formatters--mhLir82-v41eaI4a.js +1 -0
- package/storybook-static/assets/formatters-DGXR8csR.js +291 -0
- package/storybook-static/assets/formatters-runtime-GsS-hTg9.js +384 -0
- package/storybook-static/assets/foundationLib-XrLbqi3r.js +82 -0
- package/storybook-static/assets/hooks-Ddmw7JMF.js +5 -0
- package/storybook-static/assets/iframe-CrnMVMTc.js +1151 -0
- package/storybook-static/assets/iframe-FUHzX0Mr.js +1 -0
- package/storybook-static/assets/info-Dqq5QHG7.js +1 -0
- package/storybook-static/assets/{matchers-JIUQ3HVY-BPS-eazD.js → matchers-JIUQ3HVY-DvR2XErZ.js} +3 -3
- package/storybook-static/assets/media-BycWpjAl.js +1 -0
- package/storybook-static/assets/odata-BaxgzNGj.js +1 -0
- package/storybook-static/assets/odata-service-DnPlNGpU-Bpd4Zh9L.js +3 -0
- package/storybook-static/assets/odataAndTables-OEVW-gFK.js +126 -0
- package/storybook-static/assets/{odataFetchFn-BVgXXKgx.js → odataFetchFn-BLWeF0ZQ.js} +3 -3
- package/storybook-static/assets/odataStoryFixtures-BbswaX_5.js +25 -0
- package/storybook-static/assets/{persisted-D8qUQbts.js → persisted-BpFojVXw.js} +3 -3
- package/storybook-static/assets/preload-helper-BHmFeTtP.js +1 -0
- package/storybook-static/assets/pureUtilities-3afQk5ld.js +69 -0
- package/storybook-static/assets/react-18-CgkwBzTo.js +9 -0
- package/storybook-static/assets/react-C21x__mS.js +1 -0
- package/storybook-static/assets/react-CpOcCp9T.js +9 -0
- package/storybook-static/assets/react-CvkUhHUq.js +1 -0
- package/storybook-static/assets/react-dom-2o2phaJG.js +1 -0
- package/storybook-static/assets/react-qN2cStNd.js +1 -0
- package/storybook-static/assets/refresh-cw-B2VU4UNA.js +1 -0
- package/storybook-static/assets/rolldown-runtime-C0FnF6B9.js +1 -0
- package/storybook-static/assets/runtimeAndState-BEFDbOiZ.js +117 -0
- package/storybook-static/assets/settings-2-CLJhjWJl.js +1 -0
- package/storybook-static/assets/sortable-DW_Veba0.js +1 -0
- package/storybook-static/assets/syntaxhighlighter-T5IQBZDB-D0RhvxXU.js +6 -0
- package/storybook-static/assets/theming-mTWhffkp.js +39 -0
- package/storybook-static/assets/trash-2-yLqdtpz8.js +1 -0
- package/storybook-static/assets/treeStoryFixtures-Ci7STpiz.js +1 -0
- package/storybook-static/assets/triangle-alert-wI8Cd8tI.js +1 -0
- package/storybook-static/assets/ui.module-DoMIk8Oc.js +1 -0
- package/storybook-static/assets/uiClasses-CO3Cdv1E.js +1 -0
- package/storybook-static/assets/useFlexClasses-Gn9spXEB.js +1 -0
- package/storybook-static/assets/useODataSelectBase-WnxdcAM4.js +1 -0
- package/storybook-static/assets/useODataTreeData-C7L5TOjl.js +1 -0
- package/storybook-static/assets/usePickerDefaultFilter-DdxyE_i8.js +1 -0
- package/storybook-static/assets/usePickerQuery-CAWYFpCv.js +1 -0
- package/storybook-static/assets/usePickerTriggerController-BRXUlggw.js +1 -0
- package/storybook-static/assets/utils-DUM89eIj.js +1 -0
- package/storybook-static/assets/x-CyFk00QC.js +1 -0
- package/storybook-static/iframe.html +8 -3
- package/storybook-static/index.html +6 -0
- package/storybook-static/index.json +1 -1
- package/storybook-static/project.json +1 -1
- package/storybook-static/sb-addons/a11y-3/manager-bundle.js +3 -3
- package/storybook-static/sb-addons/chromatic-com-storybook-1/manager-bundle.js +17 -17
- package/storybook-static/sb-addons/docs-2/manager-bundle.js +16 -1
- package/storybook-static/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +85 -83
- package/storybook-static/sb-addons/vitest-4/manager-bundle.js +1 -1
- package/storybook-static/sb-manager/globals-runtime.js +9939 -7695
- package/storybook-static/sb-manager/runtime.js +16128 -15326
- package/storybook-static/vite-inject-mocker-entry.js +2 -2
- package/storybook-static/assets/Badge.stories-CzsgAfG9.js +0 -51
- package/storybook-static/assets/Button-MoWVKehO.js +0 -12
- package/storybook-static/assets/Button.stories-wwep4c2p.js +0 -75
- package/storybook-static/assets/CheckBox-DHvne_6w.js +0 -2
- package/storybook-static/assets/CheckBox.module-ezWPE2pa.js +0 -1
- package/storybook-static/assets/CheckBox.stories-C14Axs5p.js +0 -60
- package/storybook-static/assets/Color-KMSTOMOX-CmMBFN4-.js +0 -1
- package/storybook-static/assets/ContextMenu.stories-Dr-tkpqd.js +0 -90
- package/storybook-static/assets/DateInput-erobPRG_.js +0 -1
- package/storybook-static/assets/DateRangePresetSelect-Cg90Kc_w.js +0 -3
- package/storybook-static/assets/DateRangePresetSelect.stories-BVap0joC.js +0 -11
- package/storybook-static/assets/Detail.stories-CLdtvJ7q.js +0 -44
- package/storybook-static/assets/Dialog.stories-Dx0jZO19.js +0 -31
- package/storybook-static/assets/Disclosure.stories-DhUdeDK6.js +0 -41
- package/storybook-static/assets/DocsRenderer-JROSPFPF-Dd1n83Uq.js +0 -2
- package/storybook-static/assets/DropZone.stories-6yYrwQOe.js +0 -44
- package/storybook-static/assets/DropdownMenu-D_2LfViU.js +0 -1
- package/storybook-static/assets/ExpandableActionPanel.stories-DVOFSOlm.js +0 -20
- package/storybook-static/assets/Flex-V-qg6Ejw.js +0 -3
- package/storybook-static/assets/Flex.stories-BZv94LD8.js +0 -300
- package/storybook-static/assets/ImageCropper.stories-MLFZyJxZ.js +0 -115
- package/storybook-static/assets/ImageRenderer-DHhD7mUz.js +0 -2
- package/storybook-static/assets/ImageRenderer.stories-ChcPymk2.js +0 -22
- package/storybook-static/assets/ImageView.stories-DszVNgC8.js +0 -9
- package/storybook-static/assets/ImageViewerRuntime-D8wFAKx5.js +0 -51
- package/storybook-static/assets/Input-BGdz8TmT.js +0 -3
- package/storybook-static/assets/Input.stories-Ban0Gnck.js +0 -38
- package/storybook-static/assets/InputDateTime.stories-DgKVmf54.js +0 -35
- package/storybook-static/assets/InputFile.stories-VnRv_q2r.js +0 -36
- package/storybook-static/assets/InputFiles-Dn9afnyd.js +0 -1
- package/storybook-static/assets/InputFiles.stories-CLVn5Xfq.js +0 -33
- package/storybook-static/assets/InputImage.stories-D__QcSho.js +0 -51
- package/storybook-static/assets/LayoutPicker.stories-BCnR-zBu.js +0 -449
- package/storybook-static/assets/Listbox.stories-B0HctqVp.js +0 -47
- package/storybook-static/assets/Modal.stories-BE-VpK-a.js +0 -180
- package/storybook-static/assets/MultiSelect-CaCNRNIe.js +0 -2
- package/storybook-static/assets/MultiSelect.stories-CNkbVGsb.js +0 -29
- package/storybook-static/assets/NotificationsHost.stories-BgqvZzT3.js +0 -25
- package/storybook-static/assets/ODataMultiSelect-CMyI4yYs.js +0 -1
- package/storybook-static/assets/ODataMultiSelect.stories-DTGCC6np.js +0 -73
- package/storybook-static/assets/ODataSelect-CGplYBh_.js +0 -1
- package/storybook-static/assets/ODataSelect.stories-CsxqRAvn.js +0 -73
- package/storybook-static/assets/ODataTreeMultiSelect-4ZiAtFZk.js +0 -19
- package/storybook-static/assets/ODataTreeMultiSelect.stories-B29Od8BL.js +0 -30
- package/storybook-static/assets/ODataTreeSelect-yZy7MBsZ.js +0 -17
- package/storybook-static/assets/ODataTreeSelect.stories-H7eaj1Sz.js +0 -24
- package/storybook-static/assets/PeriodSelect.stories-6CEzS2_H.js +0 -64
- package/storybook-static/assets/Popover.stories-BNgWOHlJ.js +0 -69
- package/storybook-static/assets/PresetRangeDateInput.stories-6UPVDF62.js +0 -15
- package/storybook-static/assets/RadioButton.stories-DbdFfJqO.js +0 -36
- package/storybook-static/assets/RadioGroup-BA21indC.js +0 -1
- package/storybook-static/assets/RadioGroup.stories-Ce6x0WUN.js +0 -42
- package/storybook-static/assets/Select-DyO25wSA.js +0 -12
- package/storybook-static/assets/Select.stories-CQ8f9fY9.js +0 -46
- package/storybook-static/assets/SelectOptionContent-fC4HFG5Q.js +0 -1
- package/storybook-static/assets/SerializableSelect-ki4BThj7.js +0 -4
- package/storybook-static/assets/SerializableSelect.stories-BzXBkWPI.js +0 -43
- package/storybook-static/assets/SingleDateTimeInput.stories-CI2yrD-f.js +0 -78
- package/storybook-static/assets/Slider.stories-D3O3_tqE.js +0 -77
- package/storybook-static/assets/SliderInput.stories-D1puleZB.js +0 -67
- package/storybook-static/assets/Sortable.stories-BoaL4W6r.js +0 -141
- package/storybook-static/assets/Splitter.stories-DJpFzZVJ.js +0 -22
- package/storybook-static/assets/StateSelect.stories-Ch2Gzzmd.js +0 -47
- package/storybook-static/assets/StringToggle.stories-B8qIG0M3.js +0 -6
- package/storybook-static/assets/Switch.stories-BysIhUHa.js +0 -26
- package/storybook-static/assets/Table.stories-CBpgmq7b.js +0 -122
- package/storybook-static/assets/Tabs.stories-BPYZuvzR.js +0 -58
- package/storybook-static/assets/TagInput.stories-BwOEnVpz.js +0 -18
- package/storybook-static/assets/Textarea.stories-BSJGz7JF.js +0 -27
- package/storybook-static/assets/TimePanel-ClMfq_py.js +0 -1
- package/storybook-static/assets/TimePanel.stories-_FqWdmta.js +0 -25
- package/storybook-static/assets/Toggle-BFhzeK2e.js +0 -1
- package/storybook-static/assets/Toggle.stories-Dw5UkD_b.js +0 -30
- package/storybook-static/assets/TreeMultiSelect-CerqHY2K.js +0 -19
- package/storybook-static/assets/TreeMultiSelect-Dw7FI3ic.js +0 -1
- package/storybook-static/assets/TreeMultiSelect.stories-BTQKFbeP.js +0 -35
- package/storybook-static/assets/TreePickerBase-rJISGJBT.js +0 -22
- package/storybook-static/assets/TreeSelect-CQ1vj_c9.js +0 -16
- package/storybook-static/assets/TreeSelect-Cp_lX0-B.js +0 -1
- package/storybook-static/assets/TreeSelect.stories-D6Q02Phx.js +0 -18
- package/storybook-static/assets/TreeTable.stories-YfyhkqH9.js +0 -83
- package/storybook-static/assets/WithTooltip-7X4HQR7L-BSQyvCOM.js +0 -9
- package/storybook-static/assets/axe-GLfyhAYL.js +0 -20
- package/storybook-static/assets/base-table-BNO0lnTL.css +0 -1
- package/storybook-static/assets/base-table-Dy3fEhQe.js +0 -18
- package/storybook-static/assets/blocks-ixiC6_NZ.js +0 -285
- package/storybook-static/assets/button-DZpTIXz2.js +0 -1
- package/storybook-static/assets/check-box-DByHwJGx.js +0 -1
- package/storybook-static/assets/chunk-242VQQM5-Dtm7LRbQ.js +0 -1
- package/storybook-static/assets/chunk-3LY4VQVK-BohfESrT.js +0 -6
- package/storybook-static/assets/chunk-LITCR56V-XaMGADKk.js +0 -18
- package/storybook-static/assets/contextMenu-BbMrBF3b.js +0 -2
- package/storybook-static/assets/date-7kR6zFX5.js +0 -461
- package/storybook-static/assets/date-segments-CzU9k5bl.js +0 -1
- package/storybook-static/assets/error-BRUjWXbJ.js +0 -1
- package/storybook-static/assets/file-CI_sonB1.js +0 -291
- package/storybook-static/assets/file-hArYcyES.js +0 -1
- package/storybook-static/assets/flex-C--89Z3g.js +0 -1
- package/storybook-static/assets/floating-ui.react-DLXcGGFR.js +0 -1
- package/storybook-static/assets/formatter-L2YTDE3Q-DgyzUf7M.js +0 -1
- package/storybook-static/assets/formatters-BtIOYENB.js +0 -3
- package/storybook-static/assets/formulas-DRh9I2eS.js +0 -2
- package/storybook-static/assets/grid-DLxeTZJe.js +0 -1
- package/storybook-static/assets/hooks-DWeJq8G1.js +0 -5
- package/storybook-static/assets/iframe-BJGIOdSH.js +0 -1119
- package/storybook-static/assets/input-DXi75xv1.js +0 -1
- package/storybook-static/assets/mdx-react-shim-CmoAsjhK.js +0 -1
- package/storybook-static/assets/media-DWFaNgLM.js +0 -1
- package/storybook-static/assets/misc-BElIqBdV.css +0 -1
- package/storybook-static/assets/misc-DNZTbWc6.js +0 -5
- package/storybook-static/assets/notifications-DjtgzFqT.js +0 -1
- package/storybook-static/assets/number-Xkw1yPJo.js +0 -2
- package/storybook-static/assets/odata-C4Liwkjx.js +0 -1
- package/storybook-static/assets/odata-service-C2oJ-ZmZ.js +0 -1
- package/storybook-static/assets/odataStoryFixtures-eEGvvtmw.js +0 -25
- package/storybook-static/assets/picker-DsP4xCcJ.js +0 -2
- package/storybook-static/assets/popover-BiQHI7Wi.css +0 -1
- package/storybook-static/assets/popover-CuFTypCp.js +0 -2
- package/storybook-static/assets/preload-helper-B45gAKPr.js +0 -1
- package/storybook-static/assets/preset-select-SPNHA-mp.js +0 -5
- package/storybook-static/assets/pwa-B7uYfAPd.js +0 -640
- package/storybook-static/assets/queryClient-CA0puYc0.js +0 -567
- package/storybook-static/assets/react-18-CaNSmcD-.js +0 -9
- package/storybook-static/assets/react-3qMIUlAf.js +0 -9
- package/storybook-static/assets/react-dom-BC7xZNHy.js +0 -1
- package/storybook-static/assets/select-sUla5-3b.js +0 -1
- package/storybook-static/assets/slider--Yp_sa_W.js +0 -2
- package/storybook-static/assets/sortable-jALaQqYE.js +0 -1
- package/storybook-static/assets/syntaxhighlighter-RTCFPKCB-u_WDwfDn.js +0 -6
- package/storybook-static/assets/text-D5xgciF8.js +0 -4
- package/storybook-static/assets/theming-oB64gsjY.js +0 -39
- package/storybook-static/assets/treeStoryFixtures-Y_nnjz0_.js +0 -1
- package/storybook-static/assets/ui-DWDaBPQx.js +0 -1
- package/storybook-static/assets/ui.module-wFHXkJzp.js +0 -1
- package/storybook-static/assets/uiClasses-CaHp0EWd.js +0 -1
- package/storybook-static/assets/useODataSelectBase-DjlPxmxr.js +0 -1
- package/storybook-static/assets/useODataTreeData-1W6cbuec.js +0 -1
- package/storybook-static/assets/utils-DzbSigQl.js +0 -1
- package/storybook-static/assets/valueState-GnkKWBTr.js +0 -277
- /package/storybook-static/assets/{DropdownMenu-BgzIzwzM.css → ContextMenu-BgzIzwzM.css} +0 -0
- /package/storybook-static/assets/{Grid-K9R_IHaw.css → GridContainer-K9R_IHaw.css} +0 -0
- /package/storybook-static/assets/{InputFiles-ByK52qUe.css → InputFilesList-ByK52qUe.css} +0 -0
- /package/storybook-static/assets/{MultiSelect-BoIwmje6.css → MultiSelectToken-BoIwmje6.css} +0 -0
- /package/storybook-static/assets/{slider-DMDFRH6B.css → Slider-DMDFRH6B.css} +0 -0
- /package/storybook-static/assets/{Flex-IXK2se1Y.css → useFlexClasses-IXK2se1Y.css} +0 -0
- /package/storybook-static/assets/{picker-DzBkX15M.css → usePickerTriggerController-DzBkX15M.css} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/drop-zone/DropZone.module.scss","../../src/drop-zone/DropZone.tsx"],"sourcesContent":[".zone {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tjustify-content: center;\n\tgap: var(--space-sm);\n\n\tmin-height: 8em;\n\tpadding: var(--space-lg);\n\n\tborder: var(--border-width) dashed var(--border-0);\n\tborder-radius: var(--radius-sm);\n\tbackground-color: var(--surface-0);\n\n\tcolor: var(--content-2);\n\tcursor: pointer;\n\n\ttransition-property: border-color, background-color;\n\ttransition-duration: var(--transition-fast);\n\n\t&.dragOver {\n\t\tborder-color: var(--content-accent);\n\t\tbackground-color: var(--surface-1);\n\t}\n\n\t&.disabled {\n\t\tcursor: default;\n\t\tpointer-events: none;\n\t\tbackground-color: var(--surface-2);\n\t\tborder-color: var(--overlay-backdrop);\n\n\t\t.icon,\n\t\t.hint {\n\t\t\topacity: 0.25;\n\t\t}\n\t}\n}\n\n.icon {\n\twidth: 2em;\n\theight: 2em;\n\tcolor: var(--content-2);\n}\n\n.hint {\n\ttext-align: center;\n}\n","import { ChangeEvent, ReactNode, useCallback, useMemo, useRef, useState } from \"react\";\n\nimport {\n\tassertValidAccept,\n\tassertValidAllowedMime,\n\treadFile,\n\tReadFileError,\n\tReadFileResult,\n\tReadMode\n} from \"@ryuzaki13/react-foundation-lib/file\";\nimport { cn, handleKeyboardActivation } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { UploadIcon } from \"lucide-react\";\n\nimport { InputFilesList } from \"../input-files\";\n\nimport styles from \"./DropZone.module.scss\";\n\n/**\n * Пропсы компонента DropZone.\n *\n * Компонент представляет собой визуальную зону для выбора файлов.\n * Поддерживает перетаскивание и выбор по клику, а результаты передаются в onDrop.\n */\nexport interface DropZoneProps {\n\tvalue: ReadFileResult[];\n\t/** Вызывается с массивом результатов readFile после сброса файлов */\n\tonChange: (results: ReadFileResult[]) => void;\n\t/** Callback ошибки чтения одного из файлов */\n\tonChangeError?: (error: ReadFileError) => void;\n\n\t/** HTML-атрибут accept для нативного input[type=\"file\"] (например `[\".pdf\", \".docx\"]`) */\n\taccept?: readonly string[];\n\t/** Список допустимых MIME-типов — передаётся в readFile (например `[\"application/pdf\", \"image/png\"]`) */\n\tallowedMime?: readonly string[];\n\t/** Максимальный размер одного файла в байтах */\n\tmaxBytes?: number;\n\t/** Режим чтения: \"data-url\" (по умолчанию) или \"array-buffer\" */\n\treadMode?: ReadMode;\n\t/** Разрешить сброс нескольких файлов (по умолчанию true) */\n\tmultiple?: boolean;\n\n\t/** Блокировка компонента */\n\tdisabled?: boolean;\n\t/** CSS-класс обёртки */\n\tclassName?: string;\n\t/**\n\t * Кастомный контент внутри зоны.\n\t * По умолчанию отображается иконка загрузки и текст \"Перетащите файлы сюда\".\n\t */\n\tchildren?: ReactNode;\n}\n\n/**\n * DropZone — зона для перетаскивания файлов и выбора по клику.\n *\n * При наведении файла зона подсвечивается (пунктирная рамка меняет цвет).\n * При сбросе файлов каждый читается через readFile, успешные результаты\n * передаются в onDrop, ошибки — в onDropError.\n *\n * Поддерживает кастомный контент через children.\n * Если children не указан — отображается иконка загрузки и подсказка.\n */\nexport function DropZone({\n\tvalue,\n\tonChange,\n\tonChangeError,\n\taccept,\n\tallowedMime,\n\tmaxBytes,\n\treadMode,\n\tmultiple = true,\n\tdisabled,\n\tclassName,\n\tchildren\n}: DropZoneProps) {\n\tassertValidAllowedMime(allowedMime);\n\tassertValidAccept(accept);\n\n\t/** Счётчик вложенности drag-событий для корректной обработки dragLeave */\n\tconst dragCounter = useRef(0);\n\t/** Скрытый input для выбора файлов по клику */\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\t/** Состояние: файл перетаскивается над зоной */\n\tconst [isDragOver, setIsDragOver] = useState(false);\n\n\t/**\n\t * Формируем HTML-атрибут accept из accept или allowedMime.\n\t */\n\tconst acceptAttr = useMemo(() => {\n\t\tif (accept && accept.length > 0) {\n\t\t\treturn accept.join(\",\");\n\t\t}\n\t\tif (allowedMime && allowedMime.length > 0) {\n\t\t\treturn allowedMime.join(\",\");\n\t\t}\n\t\treturn \"*\";\n\t}, [allowedMime, accept]);\n\n\tconst readDroppedFile = useCallback(\n\t\t(file: File) => {\n\t\t\tif (readMode === \"array-buffer\") {\n\t\t\t\treturn readFile(file, { allowedMime, maxBytes, mode: \"array-buffer\" });\n\t\t\t}\n\n\t\t\treturn readFile(file, { allowedMime, maxBytes });\n\t\t},\n\t\t[allowedMime, maxBytes, readMode]\n\t);\n\n\tconst processFiles = useCallback(\n\t\tasync (files: File[]) => {\n\t\t\tif (disabled || files.length === 0) return;\n\n\t\t\tconst filesToProcess = multiple ? files : files.slice(0, 1);\n\t\t\tconst results: ReadFileResult[] = [];\n\n\t\t\tfor (const file of filesToProcess) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await readDroppedFile(file);\n\t\t\t\t\tresults.push(result);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof ReadFileError && onChangeError) {\n\t\t\t\t\t\tonChangeError(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (results.length > 0) {\n\t\t\t\tonChange(results);\n\t\t\t}\n\t\t},\n\t\t[disabled, multiple, onChange, onChangeError, readDroppedFile]\n\t);\n\n\tconst openFileDialog = useCallback(() => {\n\t\tif (disabled) return;\n\n\t\tinputRef.current?.click();\n\t}, [disabled]);\n\n\t/**\n\t * Обработка dragEnter — увеличиваем счётчик и включаем подсветку.\n\t * Счётчик нужен потому что dragEnter/dragLeave срабатывают\n\t * на каждом дочернем элементе внутри зоны.\n\t */\n\tconst handleDragEnter = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif (disabled) return;\n\n\t\t\tdragCounter.current += 1;\n\t\t\tif (dragCounter.current === 1) {\n\t\t\t\tsetIsDragOver(true);\n\t\t\t}\n\t\t},\n\t\t[disabled]\n\t);\n\n\t/**\n\t * Обработка dragOver — предотвращаем дефолтное поведение браузера\n\t * (иначе drop-событие не сработает).\n\t */\n\tconst handleDragOver = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif (disabled) return;\n\n\t\t\te.dataTransfer.dropEffect = \"copy\";\n\t\t},\n\t\t[disabled]\n\t);\n\n\t/**\n\t * Обработка dragLeave — уменьшаем счётчик, выключаем подсветку при 0.\n\t */\n\tconst handleDragLeave = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif (disabled) return;\n\n\t\t\tdragCounter.current -= 1;\n\t\t\tif (dragCounter.current === 0) {\n\t\t\t\tsetIsDragOver(false);\n\t\t\t}\n\t\t},\n\t\t[disabled]\n\t);\n\n\t/**\n\t * Обработка drop — читаем сброшенные файлы через общую логику.\n\t */\n\tconst handleDrop = useCallback(\n\t\tasync (e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\n\t\t\t// Сбрасываем состояние drag\n\t\t\tdragCounter.current = 0;\n\t\t\tsetIsDragOver(false);\n\n\t\t\tif (disabled) return;\n\n\t\t\tconst droppedFiles = Array.from(e.dataTransfer.files);\n\t\t\tawait processFiles(droppedFiles);\n\t\t},\n\t\t[disabled, processFiles]\n\t);\n\n\tconst handleInputChange = useCallback(\n\t\tasync (e: ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst selectedFiles = Array.from(e.target.files ?? []);\n\t\t\tawait processFiles(selectedFiles);\n\n\t\t\t// Сбрасываем значение, чтобы повторный выбор того же файла тоже вызывал change.\n\t\t\te.target.value = \"\";\n\t\t},\n\t\t[processFiles]\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent<HTMLDivElement>) => {\n\t\t\thandleKeyboardActivation(e, openFileDialog, { disabled });\n\t\t},\n\t\t[disabled, openFileDialog]\n\t);\n\n\treturn (\n\t\t<div>\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\ttype=\"file\"\n\t\t\t\thidden\n\t\t\t\tdisabled={disabled}\n\t\t\t\tmultiple={multiple}\n\t\t\t\taccept={acceptAttr}\n\t\t\t\tonChange={handleInputChange}\n\t\t\t/>\n\t\t\t<div\n\t\t\t\tclassName={cn(styles.zone, isDragOver && styles.dragOver, disabled && styles.disabled, className)}\n\t\t\t\tonClick={openFileDialog}\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tonDragEnter={handleDragEnter}\n\t\t\t\tonDragOver={handleDragOver}\n\t\t\t\tonDragLeave={handleDragLeave}\n\t\t\t\tonDrop={handleDrop}\n\t\t\t\trole=\"button\"\n\t\t\t\ttabIndex={disabled ? -1 : 0}\n\t\t\t\taria-disabled={disabled}>\n\t\t\t\t{children ?? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{/* Иконка загрузки по умолчанию */}\n\t\t\t\t\t\t<UploadIcon className={styles.icon} />\n\t\t\t\t\t\t{/* Текст подсказки */}\n\t\t\t\t\t\t<span className={styles.hint}>\n\t\t\t\t\t\t\t{multiple ? \"Перетащите файлы сюда или нажмите для выбора\" : \"Перетащите файл сюда или нажмите для выбора\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Список выбранных файлов */}\n\t\t\t<InputFilesList files={value} onChange={onChange} />\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/drop-zone/DropZone.module.scss","../../src/drop-zone/DropZone.tsx"],"sourcesContent":[".zone {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tjustify-content: center;\n\tgap: var(--space-sm);\n\n\tmin-height: 8em;\n\tpadding: var(--space-lg);\n\n\tborder: var(--border-width) dashed var(--border-0);\n\tborder-radius: var(--radius-sm);\n\tbackground-color: var(--surface-0);\n\n\tcolor: var(--content-2);\n\tcursor: pointer;\n\n\ttransition-property: border-color, background-color;\n\ttransition-duration: var(--transition-fast);\n\n\t&.dragOver {\n\t\tborder-color: var(--content-accent);\n\t\tbackground-color: var(--surface-1);\n\t}\n\n\t&.disabled {\n\t\tcursor: default;\n\t\tpointer-events: none;\n\t\tbackground-color: var(--surface-2);\n\t\tborder-color: var(--overlay-backdrop);\n\n\t\t.icon,\n\t\t.hint {\n\t\t\topacity: 0.25;\n\t\t}\n\t}\n}\n\n.icon {\n\twidth: 2em;\n\theight: 2em;\n\tcolor: var(--content-2);\n}\n\n.hint {\n\ttext-align: center;\n}\n","import { ChangeEvent, ReactNode, useCallback, useMemo, useRef, useState } from \"react\";\n\nimport {\n\tassertValidAccept,\n\tassertValidAllowedMime,\n\treadFile,\n\tReadFileError,\n\tReadFileResult,\n\tReadMode\n} from \"@ryuzaki13/react-foundation-lib/file\";\nimport { cn, handleKeyboardActivation } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { UploadIcon } from \"lucide-react\";\n\nimport { InputFilesList } from \"../input-files\";\n\nimport styles from \"./DropZone.module.scss\";\n\n/**\n * Пропсы компонента DropZone.\n *\n * Компонент представляет собой визуальную зону для выбора файлов.\n * Поддерживает перетаскивание и выбор по клику, а результаты передаются в onDrop.\n */\nexport interface DropZoneProps {\n\tvalue: ReadFileResult[];\n\t/** Вызывается с массивом результатов readFile после сброса файлов */\n\tonChange: (results: ReadFileResult[]) => void;\n\t/** Callback ошибки чтения одного из файлов */\n\tonChangeError?: (error: ReadFileError) => void;\n\n\t/** HTML-атрибут accept для нативного input[type=\"file\"] (например `[\".pdf\", \".docx\"]`) */\n\taccept?: readonly string[];\n\t/** Список допустимых MIME-типов — передаётся в readFile (например `[\"application/pdf\", \"image/png\"]`) */\n\tallowedMime?: readonly string[];\n\t/** Максимальный размер одного файла в байтах */\n\tmaxBytes?: number;\n\t/** Режим чтения: \"data-url\" (по умолчанию) или \"array-buffer\" */\n\treadMode?: ReadMode;\n\t/** Разрешить сброс нескольких файлов (по умолчанию true) */\n\tmultiple?: boolean;\n\n\t/** Блокировка компонента */\n\tdisabled?: boolean;\n\t/** CSS-класс обёртки */\n\tclassName?: string;\n\t/**\n\t * Кастомный контент внутри зоны.\n\t * По умолчанию отображается иконка загрузки и текст \"Перетащите файлы сюда\".\n\t */\n\tchildren?: ReactNode;\n}\n\n/**\n * DropZone — зона для перетаскивания файлов и выбора по клику.\n *\n * При наведении файла зона подсвечивается (пунктирная рамка меняет цвет).\n * При сбросе файлов каждый читается через readFile, успешные результаты\n * передаются в onDrop, ошибки — в onDropError.\n *\n * Поддерживает кастомный контент через children.\n * Если children не указан — отображается иконка загрузки и подсказка.\n */\nexport function DropZone({\n\tvalue,\n\tonChange,\n\tonChangeError,\n\taccept,\n\tallowedMime,\n\tmaxBytes,\n\treadMode,\n\tmultiple = true,\n\tdisabled,\n\tclassName,\n\tchildren\n}: DropZoneProps) {\n\tassertValidAllowedMime(allowedMime);\n\tassertValidAccept(accept);\n\n\t/** Счётчик вложенности drag-событий для корректной обработки dragLeave */\n\tconst dragCounter = useRef(0);\n\t/** Скрытый input для выбора файлов по клику */\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\t/** Состояние: файл перетаскивается над зоной */\n\tconst [isDragOver, setIsDragOver] = useState(false);\n\n\t/**\n\t * Формируем HTML-атрибут accept из accept или allowedMime.\n\t */\n\tconst acceptAttr = useMemo(() => {\n\t\tif (accept && accept.length > 0) {\n\t\t\treturn accept.join(\",\");\n\t\t}\n\t\tif (allowedMime && allowedMime.length > 0) {\n\t\t\treturn allowedMime.join(\",\");\n\t\t}\n\t\treturn \"*\";\n\t}, [allowedMime, accept]);\n\n\tconst readDroppedFile = useCallback(\n\t\t(file: File) => {\n\t\t\tif (readMode === \"array-buffer\") {\n\t\t\t\treturn readFile(file, { allowedMime, maxBytes, mode: \"array-buffer\" });\n\t\t\t}\n\n\t\t\treturn readFile(file, { allowedMime, maxBytes });\n\t\t},\n\t\t[allowedMime, maxBytes, readMode]\n\t);\n\n\tconst processFiles = useCallback(\n\t\tasync (files: File[]) => {\n\t\t\tif (disabled || files.length === 0) return;\n\n\t\t\tconst filesToProcess = multiple ? files : files.slice(0, 1);\n\t\t\tconst results: ReadFileResult[] = [];\n\n\t\t\tfor (const file of filesToProcess) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await readDroppedFile(file);\n\t\t\t\t\tresults.push(result);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof ReadFileError && onChangeError) {\n\t\t\t\t\t\tonChangeError(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (results.length > 0) {\n\t\t\t\tonChange(results);\n\t\t\t}\n\t\t},\n\t\t[disabled, multiple, onChange, onChangeError, readDroppedFile]\n\t);\n\n\tconst openFileDialog = useCallback(() => {\n\t\tif (disabled) return;\n\n\t\tinputRef.current?.click();\n\t}, [disabled]);\n\n\t/**\n\t * Обработка dragEnter — увеличиваем счётчик и включаем подсветку.\n\t * Счётчик нужен потому что dragEnter/dragLeave срабатывают\n\t * на каждом дочернем элементе внутри зоны.\n\t */\n\tconst handleDragEnter = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif (disabled) return;\n\n\t\t\tdragCounter.current += 1;\n\t\t\tif (dragCounter.current === 1) {\n\t\t\t\tsetIsDragOver(true);\n\t\t\t}\n\t\t},\n\t\t[disabled]\n\t);\n\n\t/**\n\t * Обработка dragOver — предотвращаем дефолтное поведение браузера\n\t * (иначе drop-событие не сработает).\n\t */\n\tconst handleDragOver = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif (disabled) return;\n\n\t\t\te.dataTransfer.dropEffect = \"copy\";\n\t\t},\n\t\t[disabled]\n\t);\n\n\t/**\n\t * Обработка dragLeave — уменьшаем счётчик, выключаем подсветку при 0.\n\t */\n\tconst handleDragLeave = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif (disabled) return;\n\n\t\t\tdragCounter.current -= 1;\n\t\t\tif (dragCounter.current === 0) {\n\t\t\t\tsetIsDragOver(false);\n\t\t\t}\n\t\t},\n\t\t[disabled]\n\t);\n\n\t/**\n\t * Обработка drop — читаем сброшенные файлы через общую логику.\n\t */\n\tconst handleDrop = useCallback(\n\t\tasync (e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\n\t\t\t// Сбрасываем состояние drag\n\t\t\tdragCounter.current = 0;\n\t\t\tsetIsDragOver(false);\n\n\t\t\tif (disabled) return;\n\n\t\t\tconst droppedFiles = Array.from(e.dataTransfer.files);\n\t\t\tawait processFiles(droppedFiles);\n\t\t},\n\t\t[disabled, processFiles]\n\t);\n\n\tconst handleInputChange = useCallback(\n\t\tasync (e: ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst selectedFiles = Array.from(e.target.files ?? []);\n\t\t\tawait processFiles(selectedFiles);\n\n\t\t\t// Сбрасываем значение, чтобы повторный выбор того же файла тоже вызывал change.\n\t\t\te.target.value = \"\";\n\t\t},\n\t\t[processFiles]\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent<HTMLDivElement>) => {\n\t\t\thandleKeyboardActivation(e, openFileDialog, { disabled });\n\t\t},\n\t\t[disabled, openFileDialog]\n\t);\n\n\treturn (\n\t\t<div>\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\ttype=\"file\"\n\t\t\t\thidden\n\t\t\t\tdisabled={disabled}\n\t\t\t\tmultiple={multiple}\n\t\t\t\taccept={acceptAttr}\n\t\t\t\tonChange={handleInputChange}\n\t\t\t/>\n\t\t\t<div\n\t\t\t\tclassName={cn(styles.zone, isDragOver && styles.dragOver, disabled && styles.disabled, className)}\n\t\t\t\tonClick={openFileDialog}\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tonDragEnter={handleDragEnter}\n\t\t\t\tonDragOver={handleDragOver}\n\t\t\t\tonDragLeave={handleDragLeave}\n\t\t\t\tonDrop={handleDrop}\n\t\t\t\trole=\"button\"\n\t\t\t\ttabIndex={disabled ? -1 : 0}\n\t\t\t\taria-disabled={disabled}>\n\t\t\t\t{children ?? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{/* Иконка загрузки по умолчанию */}\n\t\t\t\t\t\t<UploadIcon className={styles.icon} />\n\t\t\t\t\t\t{/* Текст подсказки */}\n\t\t\t\t\t\t<span className={styles.hint}>\n\t\t\t\t\t\t\t{multiple ? \"Перетащите файлы сюда или нажмите для выбора\" : \"Перетащите файл сюда или нажмите для выбора\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Список выбранных файлов */}\n\t\t\t<InputFilesList files={value} onChange={onChange} />\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
package/dist/errors/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Text as e } from "../text/index.js";
|
|
2
|
-
import { r as t } from "../chunks/flex-
|
|
2
|
+
import { r as t } from "../chunks/flex-C7njxZ74.js";
|
|
3
3
|
import { Component as n, useEffect as r, useState as i } from "react";
|
|
4
4
|
import { useQueryClient as a } from "@tanstack/react-query";
|
|
5
5
|
import { logError as o } from "@ryuzaki13/react-foundation-lib/utils";
|
package/dist/errors/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/errors/PageError.tsx","../../src/errors/BadRequestPage.tsx","../../src/errors/BoomExplosion.tsx","../../src/errors/constants.ts","../../src/errors/ForbiddenPage.tsx","../../src/errors/NotFoundPage.tsx","../../src/errors/ErrorDisplay.tsx","../../src/errors/ErrorBoundary.tsx","../../src/errors/ErrorExplosion.tsx","../../src/errors/SimpleErrorDisplay.tsx","../../src/errors/UnauthorizedPage.tsx","../../src/errors/ViewNotChanged.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flex } from \"../flex\";\n\ninterface PageErrorProps {\n\tcode: string | number;\n\ttitle: string;\n\tdescription: string;\n}\n\nexport const PageError: React.FC<PageErrorProps> = ({ code, title, description }) => {\n\treturn (\n\t\t<Flex.Predefined variant=\"columnCenter\" className=\"paddingXl\">\n\t\t\t<div aria-hidden=\"true\" className=\"content2 fontBolded\" style={{ fontSize: \"5em\" }}>\n\t\t\t\t{code}\n\t\t\t</div>\n\t\t\t<h2>{title}</h2>\n\t\t\t<p>{description}</p>\n\t\t\t{/* <Link to=\"/\">Вернуться на главную</Link> */}\n\t\t</Flex.Predefined>\n\t);\n};\n","import { PageError } from \"./PageError\";\n\nexport const BadRequestPage: React.FC = () => {\n\treturn (\n\t\t<PageError\n\t\t\tcode={400}\n\t\t\ttitle=\"Некорректный запрос\"\n\t\t\tdescription=\"Похоже, что запрос был сформирован неверно. Попробуйте обновить страницу или вернуться на главную.\"\n\t\t/>\n\t);\n};\n","import { useState } from \"react\";\n\nexport function BoomExplosion() {\n\tconst [transform] = useState(() => {\n\t\tconst scale = 0.7 + Math.random() * 0.3;\n\t\tconst rotate = Math.random() * 45 - 15;\n\t\treturn `scale(${scale}) rotateZ(${rotate}deg)`;\n\t});\n\n\treturn (\n\t\t<svg\n\t\t\tviewBox=\"0 0 300 300\"\n\t\t\twidth=\"300\"\n\t\t\theight=\"300\"\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: \"50%\",\n\t\t\t\tleft: \"50%\",\n\t\t\t\ttransform: `translate(-50%, -50%) ${transform}`,\n\t\t\t\tzIndex: 0,\n\t\t\t\topacity: 0.5\n\t\t\t}}>\n\t\t\t<polygon\n\t\t\t\tpoints=\"\n150,10 170,60 230,40 200,100 270,110 210,150 270,190 200,200 230,260 170,240 150,290 130,240\n70,260 100,200 30,190 90,150 30,110 100,100 70,40 130,60\"\n\t\t\t\tfill=\"var(--status-error-on-fill)\"\n\t\t\t\tstroke=\"var(--status-error-fill)\"\n\t\t\t\tstrokeWidth=\"5\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n","export const ERROR_BOOM_MESSAGES = [\"Упс!\", \"Ой!\", \"Эх!\", \"Ай-ай-ай!\", \"Бах!\", \"Бум!\", \"Ого!\", \"Облом!\", \"Ёлки-палки!\", \"Хлоп!\"];\n","import { PageError } from \"./PageError\";\n\nexport const ForbiddenPage: React.FC = () => {\n\treturn <PageError code={403} title=\"Доступ запрещён\" description=\"У вас нет прав для просмотра этой страницы.\" />;\n};\n","import { PageError } from \"./PageError\";\n\nexport const NotFoundPage: React.FC = () => {\n\treturn <PageError code={404} title=\"Страница не найдена\" description=\"Извините, запрашиваемая страница не существует\" />;\n};\n","import { useEffect, useState } from \"react\";\n\nimport { captureRuntimeErrorReport } from \"@ryuzaki13/react-foundation-lib/error-report\";\nimport { logError } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { BadRequestPage } from \"./BadRequestPage\";\nimport { BoomExplosion } from \"./BoomExplosion\";\nimport { ERROR_BOOM_MESSAGES } from \"./constants\";\nimport { ForbiddenPage } from \"./ForbiddenPage\";\nimport { NotFoundPage } from \"./NotFoundPage\";\n\nfunction getHttpStatusCode(error: Error): number | undefined {\n\tif (!(\"status\" in error) || typeof error.status !== \"number\") return undefined;\n\treturn error.status;\n}\n\nexport const ErrorDisplay: React.FC<{ error: Error; componentStack?: string; draftId?: string | null }> = ({\n\terror,\n\tcomponentStack,\n\tdraftId\n}) => {\n\tconst [randomValue] = useState(() => Math.random());\n\tconst queryClient = useQueryClient();\n\n\tuseEffect(() => {\n\t\tif (draftId !== undefined) return;\n\n\t\tvoid captureRuntimeErrorReport(\n\t\t\terror,\n\t\t\t{\n\t\t\t\tcategory: \"react\",\n\t\t\t\tcomponentStack\n\t\t\t},\n\t\t\tqueryClient\n\t\t);\n\t}, [componentStack, draftId, error, queryClient]);\n\n\tconst httpStatusCode = getHttpStatusCode(error);\n\n\tif (httpStatusCode) {\n\t\tswitch (httpStatusCode) {\n\t\t\tcase 400:\n\t\t\t\treturn <BadRequestPage />;\n\t\t\tcase 403:\n\t\t\t\treturn <ForbiddenPage />;\n\t\t\tcase 404:\n\t\t\t\treturn <NotFoundPage />;\n\t\t}\n\t}\n\n\tlogError(error.stack);\n\n\treturn (\n\t\t<section className=\"w100 h100 flexColumn justifyContentCenter paddingMd\">\n\t\t\t<div aria-hidden=\"true\" className=\"textCenter relative fontBolded statusError\" style={{ fontSize: \"4em\", marginBlock: \"2em\" }}>\n\t\t\t\t<BoomExplosion />\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tzIndex: 1,\n\t\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\t\ttextShadow: \"1px -1px 1px var(--status-warning-border-focus), -1px 1px 1px var(--status-info-border-focus)\"\n\t\t\t\t\t}}>\n\t\t\t\t\t{ERROR_BOOM_MESSAGES[Math.floor(randomValue * ERROR_BOOM_MESSAGES.length)]}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"textCenter\">\n\t\t\t\t<h2 className=\"statusError\">Критическая ошибка</h2>\n\t\t\t\t<p className=\"statusError fontSizeLg\">\n\t\t\t\t\t<code>{error.message}</code>\n\t\t\t\t</p>\n\t\t\t\t<p>Попробуйте перезагрузить страницу или вернуться позже.</p>\n\t\t\t</div>\n\t\t</section>\n\t);\n};\n","import React, { Component } from \"react\";\n\nimport { captureRuntimeErrorReport } from \"@ryuzaki13/react-foundation-lib/error-report\";\n\nimport { ErrorDisplay } from \"./ErrorDisplay\";\n\ninterface ErrorBoundaryProps {\n\tchildren: React.ReactNode;\n\tcustomComponent?: React.ComponentType<{ error: Error }>;\n}\n\ntype ErrorBoundaryState = {\n\terror: Error | null;\n\tcomponentStack?: string;\n\tdraftId?: string | null;\n};\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n\tconstructor(props: ErrorBoundaryProps) {\n\t\tsuper(props);\n\t\tthis.state = { error: null };\n\t}\n\n\tstatic getDerivedStateFromError(error: Error) {\n\t\treturn { error };\n\t}\n\n\tcomponentDidUpdate(prevProps: ErrorBoundaryProps) {\n\t\t// Сбрасываем ошибку при изменении children\n\t\tif (this.state.error && prevProps.children !== this.props.children) {\n\t\t\tthis.setState({ error: null, componentStack: undefined, draftId: undefined });\n\t\t}\n\t}\n\n\tcomponentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n\t\tthis.setState({ componentStack: errorInfo.componentStack ?? undefined, draftId: null });\n\n\t\tcaptureRuntimeErrorReport(error, {\n\t\t\tcategory: \"react\",\n\t\t\tcomponentStack: errorInfo.componentStack ?? undefined\n\t\t}).then((draft) => {\n\t\t\tif (draft && this.state.error === error) {\n\t\t\t\tthis.setState({ draftId: draft.reportId });\n\t\t\t}\n\t\t});\n\t}\n\n\trender() {\n\t\tif (this.state.error) {\n\t\t\tconst CustomComponent = this.props.customComponent;\n\t\t\treturn CustomComponent ? (\n\t\t\t\t<CustomComponent error={this.state.error} />\n\t\t\t) : (\n\t\t\t\t<ErrorDisplay error={this.state.error} componentStack={this.state.componentStack} draftId={this.state.draftId} />\n\t\t\t);\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import React, { useState } from \"react\";\n\nimport { BoomExplosion } from \"./BoomExplosion\";\nimport { ERROR_BOOM_MESSAGES } from \"./constants\";\n\ninterface ErrorExplosionProps {\n\theader?: string;\n\tdescription?: string;\n}\n\nexport const ErrorExplosion: React.FC<ErrorExplosionProps> = ({ header, description }) => {\n\tconst [randomValue] = useState(() => Math.random());\n\n\treturn (\n\t\t<div className=\"container marginBlockLg\">\n\t\t\t<div aria-hidden=\"true\" className={\"textCenter relative fontBolded statusWarning marginBlockMd\"} style={{ fontSize: \"6em\" }}>\n\t\t\t\t<BoomExplosion />\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tzIndex: 1,\n\t\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\t\ttextShadow: \"1px 0 1px var(--status-error-fill), -1px 0 1px var(--status-info-fill)\"\n\t\t\t\t\t}}>\n\t\t\t\t\t{ERROR_BOOM_MESSAGES[Math.floor(randomValue * ERROR_BOOM_MESSAGES.length)]}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"flexColumn alignItemsCenter textCenter marginBlockMd\">\n\t\t\t\t{header && <h2 className=\"statusWarning\">{header}</h2>}\n\t\t\t\t{description && <p>{description}</p>}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { logError } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { Text } from \"../text\";\n\nexport function SimpleErrorDisplay({ error }: { error: Error }) {\n\tlogError(error.stack);\n\n\treturn (\n\t\t<Text color=\"error\">\n\t\t\t<code>{error.message}</code>\n\t\t</Text>\n\t);\n}\n","import { PageError } from \"./PageError\";\n\nexport const UnauthorizedPage: React.FC = () => {\n\treturn (\n\t\t<PageError\n\t\t\tcode={401}\n\t\t\ttitle=\"Необходима авторизация\"\n\t\t\tdescription=\"Для доступа к этой странице нужно войти в систему. Пожалуйста, авторизуйтесь и попробуйте снова.\"\n\t\t/>\n\t);\n};\n","import React from \"react\";\n\nimport { Flex } from \"../flex\";\n\nexport const ViewNotChanged: React.FC = () => {\n\treturn (\n\t\t<Flex.Predefined variant=\"columnCenter\" className=\"paddingXl\">\n\t\t\t<h2 className=\"content2\">Выберите ракурс</h2>\n\t\t</Flex.Predefined>\n\t);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/errors/PageError.tsx","../../src/errors/BadRequestPage.tsx","../../src/errors/BoomExplosion.tsx","../../src/errors/constants.ts","../../src/errors/ForbiddenPage.tsx","../../src/errors/NotFoundPage.tsx","../../src/errors/ErrorDisplay.tsx","../../src/errors/ErrorBoundary.tsx","../../src/errors/ErrorExplosion.tsx","../../src/errors/SimpleErrorDisplay.tsx","../../src/errors/UnauthorizedPage.tsx","../../src/errors/ViewNotChanged.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flex } from \"../flex\";\n\ninterface PageErrorProps {\n\tcode: string | number;\n\ttitle: string;\n\tdescription: string;\n}\n\nexport const PageError: React.FC<PageErrorProps> = ({ code, title, description }) => {\n\treturn (\n\t\t<Flex.Predefined variant=\"columnCenter\" className=\"paddingXl\">\n\t\t\t<div aria-hidden=\"true\" className=\"content2 fontBolded\" style={{ fontSize: \"5em\" }}>\n\t\t\t\t{code}\n\t\t\t</div>\n\t\t\t<h2>{title}</h2>\n\t\t\t<p>{description}</p>\n\t\t\t{/* <Link to=\"/\">Вернуться на главную</Link> */}\n\t\t</Flex.Predefined>\n\t);\n};\n","import { PageError } from \"./PageError\";\n\nexport const BadRequestPage: React.FC = () => {\n\treturn (\n\t\t<PageError\n\t\t\tcode={400}\n\t\t\ttitle=\"Некорректный запрос\"\n\t\t\tdescription=\"Похоже, что запрос был сформирован неверно. Попробуйте обновить страницу или вернуться на главную.\"\n\t\t/>\n\t);\n};\n","import { useState } from \"react\";\n\nexport function BoomExplosion() {\n\tconst [transform] = useState(() => {\n\t\tconst scale = 0.7 + Math.random() * 0.3;\n\t\tconst rotate = Math.random() * 45 - 15;\n\t\treturn `scale(${scale}) rotateZ(${rotate}deg)`;\n\t});\n\n\treturn (\n\t\t<svg\n\t\t\tviewBox=\"0 0 300 300\"\n\t\t\twidth=\"300\"\n\t\t\theight=\"300\"\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: \"50%\",\n\t\t\t\tleft: \"50%\",\n\t\t\t\ttransform: `translate(-50%, -50%) ${transform}`,\n\t\t\t\tzIndex: 0,\n\t\t\t\topacity: 0.5\n\t\t\t}}>\n\t\t\t<polygon\n\t\t\t\tpoints=\"\n150,10 170,60 230,40 200,100 270,110 210,150 270,190 200,200 230,260 170,240 150,290 130,240\n70,260 100,200 30,190 90,150 30,110 100,100 70,40 130,60\"\n\t\t\t\tfill=\"var(--status-error-on-fill)\"\n\t\t\t\tstroke=\"var(--status-error-fill)\"\n\t\t\t\tstrokeWidth=\"5\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n","export const ERROR_BOOM_MESSAGES = [\"Упс!\", \"Ой!\", \"Эх!\", \"Ай-ай-ай!\", \"Бах!\", \"Бум!\", \"Ого!\", \"Облом!\", \"Ёлки-палки!\", \"Хлоп!\"];\n","import { PageError } from \"./PageError\";\n\nexport const ForbiddenPage: React.FC = () => {\n\treturn <PageError code={403} title=\"Доступ запрещён\" description=\"У вас нет прав для просмотра этой страницы.\" />;\n};\n","import { PageError } from \"./PageError\";\n\nexport const NotFoundPage: React.FC = () => {\n\treturn <PageError code={404} title=\"Страница не найдена\" description=\"Извините, запрашиваемая страница не существует\" />;\n};\n","import { useEffect, useState } from \"react\";\n\nimport { captureRuntimeErrorReport } from \"@ryuzaki13/react-foundation-lib/error-report\";\nimport { logError } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { BadRequestPage } from \"./BadRequestPage\";\nimport { BoomExplosion } from \"./BoomExplosion\";\nimport { ERROR_BOOM_MESSAGES } from \"./constants\";\nimport { ForbiddenPage } from \"./ForbiddenPage\";\nimport { NotFoundPage } from \"./NotFoundPage\";\n\nfunction getHttpStatusCode(error: Error): number | undefined {\n\tif (!(\"status\" in error) || typeof error.status !== \"number\") return undefined;\n\treturn error.status;\n}\n\nexport const ErrorDisplay: React.FC<{ error: Error; componentStack?: string; draftId?: string | null }> = ({\n\terror,\n\tcomponentStack,\n\tdraftId\n}) => {\n\tconst [randomValue] = useState(() => Math.random());\n\tconst queryClient = useQueryClient();\n\n\tuseEffect(() => {\n\t\tif (draftId !== undefined) return;\n\n\t\tvoid captureRuntimeErrorReport(\n\t\t\terror,\n\t\t\t{\n\t\t\t\tcategory: \"react\",\n\t\t\t\tcomponentStack\n\t\t\t},\n\t\t\tqueryClient\n\t\t);\n\t}, [componentStack, draftId, error, queryClient]);\n\n\tconst httpStatusCode = getHttpStatusCode(error);\n\n\tif (httpStatusCode) {\n\t\tswitch (httpStatusCode) {\n\t\t\tcase 400:\n\t\t\t\treturn <BadRequestPage />;\n\t\t\tcase 403:\n\t\t\t\treturn <ForbiddenPage />;\n\t\t\tcase 404:\n\t\t\t\treturn <NotFoundPage />;\n\t\t}\n\t}\n\n\tlogError(error.stack);\n\n\treturn (\n\t\t<section className=\"w100 h100 flexColumn justifyContentCenter paddingMd\">\n\t\t\t<div aria-hidden=\"true\" className=\"textCenter relative fontBolded statusError\" style={{ fontSize: \"4em\", marginBlock: \"2em\" }}>\n\t\t\t\t<BoomExplosion />\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tzIndex: 1,\n\t\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\t\ttextShadow: \"1px -1px 1px var(--status-warning-border-focus), -1px 1px 1px var(--status-info-border-focus)\"\n\t\t\t\t\t}}>\n\t\t\t\t\t{ERROR_BOOM_MESSAGES[Math.floor(randomValue * ERROR_BOOM_MESSAGES.length)]}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"textCenter\">\n\t\t\t\t<h2 className=\"statusError\">Критическая ошибка</h2>\n\t\t\t\t<p className=\"statusError fontSizeLg\">\n\t\t\t\t\t<code>{error.message}</code>\n\t\t\t\t</p>\n\t\t\t\t<p>Попробуйте перезагрузить страницу или вернуться позже.</p>\n\t\t\t</div>\n\t\t</section>\n\t);\n};\n","import React, { Component } from \"react\";\n\nimport { captureRuntimeErrorReport } from \"@ryuzaki13/react-foundation-lib/error-report\";\n\nimport { ErrorDisplay } from \"./ErrorDisplay\";\n\ninterface ErrorBoundaryProps {\n\tchildren: React.ReactNode;\n\tcustomComponent?: React.ComponentType<{ error: Error }>;\n}\n\ntype ErrorBoundaryState = {\n\terror: Error | null;\n\tcomponentStack?: string;\n\tdraftId?: string | null;\n};\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n\tconstructor(props: ErrorBoundaryProps) {\n\t\tsuper(props);\n\t\tthis.state = { error: null };\n\t}\n\n\tstatic getDerivedStateFromError(error: Error) {\n\t\treturn { error };\n\t}\n\n\tcomponentDidUpdate(prevProps: ErrorBoundaryProps) {\n\t\t// Сбрасываем ошибку при изменении children\n\t\tif (this.state.error && prevProps.children !== this.props.children) {\n\t\t\tthis.setState({ error: null, componentStack: undefined, draftId: undefined });\n\t\t}\n\t}\n\n\tcomponentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n\t\tthis.setState({ componentStack: errorInfo.componentStack ?? undefined, draftId: null });\n\n\t\tcaptureRuntimeErrorReport(error, {\n\t\t\tcategory: \"react\",\n\t\t\tcomponentStack: errorInfo.componentStack ?? undefined\n\t\t}).then((draft) => {\n\t\t\tif (draft && this.state.error === error) {\n\t\t\t\tthis.setState({ draftId: draft.reportId });\n\t\t\t}\n\t\t});\n\t}\n\n\trender() {\n\t\tif (this.state.error) {\n\t\t\tconst CustomComponent = this.props.customComponent;\n\t\t\treturn CustomComponent ? (\n\t\t\t\t<CustomComponent error={this.state.error} />\n\t\t\t) : (\n\t\t\t\t<ErrorDisplay error={this.state.error} componentStack={this.state.componentStack} draftId={this.state.draftId} />\n\t\t\t);\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import React, { useState } from \"react\";\n\nimport { BoomExplosion } from \"./BoomExplosion\";\nimport { ERROR_BOOM_MESSAGES } from \"./constants\";\n\ninterface ErrorExplosionProps {\n\theader?: string;\n\tdescription?: string;\n}\n\nexport const ErrorExplosion: React.FC<ErrorExplosionProps> = ({ header, description }) => {\n\tconst [randomValue] = useState(() => Math.random());\n\n\treturn (\n\t\t<div className=\"container marginBlockLg\">\n\t\t\t<div aria-hidden=\"true\" className={\"textCenter relative fontBolded statusWarning marginBlockMd\"} style={{ fontSize: \"6em\" }}>\n\t\t\t\t<BoomExplosion />\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tzIndex: 1,\n\t\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\t\ttextShadow: \"1px 0 1px var(--status-error-fill), -1px 0 1px var(--status-info-fill)\"\n\t\t\t\t\t}}>\n\t\t\t\t\t{ERROR_BOOM_MESSAGES[Math.floor(randomValue * ERROR_BOOM_MESSAGES.length)]}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"flexColumn alignItemsCenter textCenter marginBlockMd\">\n\t\t\t\t{header && <h2 className=\"statusWarning\">{header}</h2>}\n\t\t\t\t{description && <p>{description}</p>}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import { logError } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { Text } from \"../text\";\n\nexport function SimpleErrorDisplay({ error }: { error: Error }) {\n\tlogError(error.stack);\n\n\treturn (\n\t\t<Text color=\"error\">\n\t\t\t<code>{error.message}</code>\n\t\t</Text>\n\t);\n}\n","import { PageError } from \"./PageError\";\n\nexport const UnauthorizedPage: React.FC = () => {\n\treturn (\n\t\t<PageError\n\t\t\tcode={401}\n\t\t\ttitle=\"Необходима авторизация\"\n\t\t\tdescription=\"Для доступа к этой странице нужно войти в систему. Пожалуйста, авторизуйтесь и попробуйте снова.\"\n\t\t/>\n\t);\n};\n","import React from \"react\";\n\nimport { Flex } from \"../flex\";\n\nexport const ViewNotChanged: React.FC = () => {\n\treturn (\n\t\t<Flex.Predefined variant=\"columnCenter\" className=\"paddingXl\">\n\t\t\t<h2 className=\"content2\">Выберите ракурс</h2>\n\t\t</Flex.Predefined>\n\t);\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as e } from "../chunks/button-
|
|
2
|
-
import { l as t } from "../chunks/misc-
|
|
1
|
+
import { n as e } from "../chunks/button-BU2kRzwu.js";
|
|
2
|
+
import { l as t } from "../chunks/misc-BYxxlJz6.js";
|
|
3
3
|
import { useCallback as n, useId as r, useState as i } from "react";
|
|
4
4
|
import { cn as a } from "@ryuzaki13/react-foundation-lib/utils";
|
|
5
5
|
import { ChevronsLeftIcon as o, ChevronsRightIcon as s } from "lucide-react";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/expandable-action-panel/ExpandableActionPanel.module.scss","../../src/expandable-action-panel/ExpandableActionPanel.tsx","../../src/expandable-action-panel/LabeledExpandableActionPanel.tsx"],"sourcesContent":[".expandableActionPanel {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: flex-end;\n\tgap: var(--space-sm);\n\tmin-width: var(--control-height);\n\tmax-width: 100%;\n\toverflow: hidden;\n}\n\n.content {\n\tmin-width: 0;\n\tmax-width: 100%;\n\tflex: 1 1 auto;\n\toverflow: hidden;\n}\n\n.contentScroller {\n\twidth: 100%;\n\tmin-width: 0;\n}\n\n.labeledPanel {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-sm);\n\twidth: 100%;\n\tmin-width: 0;\n}\n\n.label {\n\tcolor: var(--content-0);\n}\n\n.labeledActionPanel {\n\tflex: 0 1 auto;\n}\n","import React, { PropsWithChildren, useCallback, useId, useState } from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { ChevronsLeftIcon, ChevronsRightIcon } from \"lucide-react\";\n\nimport { Button } from \"../button\";\nimport { OneStepScroller } from \"../misc\";\n\nimport styles from \"./ExpandableActionPanel.module.scss\";\n\nexport interface ExpandableActionPanelProps extends PropsWithChildren {\n\tclassName?: string;\n\tcontentClassName?: string;\n\ttoggleClassName?: string;\n\topen?: boolean;\n\tdefaultOpen?: boolean;\n\tdisabled?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n\texpandLabel?: string;\n\tcollapseLabel?: string;\n\tpanelLabel?: string;\n\titemSelector?: string;\n\tscrollPadding?: number;\n\tsmoothScroll?: boolean;\n}\n\n/**\n * Горизонтальная раскрывающаяся панель действий.\n * Не знает о внешнем layout и может использоваться рядом с любым содержимым.\n */\nexport function ExpandableActionPanel({\n\tchildren,\n\tclassName,\n\tcontentClassName,\n\ttoggleClassName,\n\topen: controlledOpen,\n\tdefaultOpen = false,\n\tdisabled,\n\tonOpenChange,\n\texpandLabel = \"Раскрыть панель действий влево\",\n\tcollapseLabel = \"Свернуть панель действий\",\n\tpanelLabel = \"Действия панели\",\n\titemSelector,\n\tscrollPadding,\n\tsmoothScroll\n}: ExpandableActionPanelProps) {\n\tconst [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\tconst panelId = useId();\n\tconst isControlled = controlledOpen !== undefined;\n\tconst open = isControlled ? controlledOpen : uncontrolledOpen;\n\n\tconst setOpen = useCallback<React.Dispatch<React.SetStateAction<boolean>>>(\n\t\t(value) => {\n\t\t\tconst nextOpen = typeof value === \"function\" ? value(open) : value;\n\n\t\t\tif (!isControlled) {\n\t\t\t\tsetUncontrolledOpen(nextOpen);\n\t\t\t}\n\n\t\t\tonOpenChange?.(nextOpen);\n\t\t},\n\t\t[isControlled, onOpenChange, open]\n\t);\n\n\tconst handleToggle = () => setOpen((prevOpen) => !prevOpen);\n\tconst ToggleIcon = open ? ChevronsRightIcon : ChevronsLeftIcon;\n\n\treturn (\n\t\t<div className={cn(styles.expandableActionPanel, className)} data-ui=\"expandable-action-panel\" data-open={open ? \"\" : undefined}>\n\t\t\t<Button\n\t\t\t\tclassName={toggleClassName}\n\t\t\t\ticon={<ToggleIcon />}\n\t\t\t\ttitle={open ? collapseLabel : expandLabel}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tvariant=\"neutralOutline\"\n\t\t\t\taria-expanded={open}\n\t\t\t\taria-controls={panelId}\n\t\t\t\tdata-ui=\"expandable-action-panel-toggle\"\n\t\t\t\tdata-action={open ? \"collapse-action-panel\" : \"expand-action-panel\"}\n\t\t\t\tonClick={handleToggle}\n\t\t\t/>\n\n\t\t\t{open && (\n\t\t\t\t<div id={panelId} role=\"group\" aria-label={panelLabel} className={cn(styles.content, contentClassName)}>\n\t\t\t\t\t<OneStepScroller\n\t\t\t\t\t\tclassName={styles.contentScroller}\n\t\t\t\t\t\titemSelector={itemSelector}\n\t\t\t\t\t\tscrollPadding={scrollPadding}\n\t\t\t\t\t\tsmooth={smoothScroll}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</OneStepScroller>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import React from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { ExpandableActionPanel, ExpandableActionPanelProps } from \"./ExpandableActionPanel\";\nimport styles from \"./ExpandableActionPanel.module.scss\";\n\nexport interface LabeledExpandableActionPanelProps extends Omit<ExpandableActionPanelProps, \"className\"> {\n\tlabel: React.ReactNode;\n\tclassName?: string;\n\tlabelClassName?: string;\n\tlabelStyle?: React.CSSProperties;\n\tlabelMinWidth?: React.CSSProperties[\"minWidth\"];\n\tpanelClassName?: string;\n}\n\n/**\n * Раскрывающаяся панель действий с левым текстом, который сжимается через `flexEllipsis`.\n */\nexport function LabeledExpandableActionPanel({\n\tlabel,\n\tclassName,\n\tlabelClassName,\n\tlabelStyle,\n\tlabelMinWidth = \"12em\",\n\tpanelClassName,\n\topen,\n\tdefaultOpen,\n\t...panelProps\n}: LabeledExpandableActionPanelProps) {\n\tconst resolvedLabelStyle: React.CSSProperties = {\n\t\t...labelStyle,\n\t\tminWidth: labelMinWidth\n\t};\n\tconst title = typeof label === \"string\" ? label : undefined;\n\n\treturn (\n\t\t<div className={cn(styles.labeledPanel, className)} data-ui=\"labeled-expandable-action-panel\">\n\t\t\t<div className={cn(\"flexEllipsis\", styles.label, labelClassName)} style={resolvedLabelStyle} title={title}>\n\t\t\t\t{label}\n\t\t\t</div>\n\t\t\t<ExpandableActionPanel\n\t\t\t\t{...panelProps}\n\t\t\t\topen={open}\n\t\t\t\tdefaultOpen={defaultOpen}\n\t\t\t\tclassName={cn(styles.labeledActionPanel, panelClassName)}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AC8BA,SAAgB,EAAsB,EACrC,aACA,cACA,qBACA,oBACA,MAAM,GACN,iBAAc,IACd,aACA,iBACA,iBAAc,kCACd,mBAAgB,4BAChB,gBAAa,mBACb,iBACA,kBACA,mBAC8B;CAC9B,IAAM,CAAC,GAAkB,KAAuB,EAAS,CAAW,GAC9D,IAAU,EAAM,GAChB,IAAe,MAAmB,KAAA,GAClC,IAAO,IAAe,IAAiB,GAEvC,IAAU,GACd,MAAU;EACV,IAAM,IAAW,OAAO,KAAU,aAAa,EAAM,CAAI,IAAI;EAM7D,AAJK,KACJ,EAAoB,CAAQ,GAG7B,IAAe,CAAQ;CACxB,GACA;EAAC;EAAc;EAAc;CAAI,CAClC,GAEM,UAAqB,GAAS,MAAa,CAAC,CAAQ,GACpD,IAAa,IAAO,IAAoB;CAE9C,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,uBAAuB,CAAS;EAAG,WAAQ;EAA0B,aAAW,IAAO,KAAK,KAAA;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/expandable-action-panel/ExpandableActionPanel.module.scss","../../src/expandable-action-panel/ExpandableActionPanel.tsx","../../src/expandable-action-panel/LabeledExpandableActionPanel.tsx"],"sourcesContent":[".expandableActionPanel {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: flex-end;\n\tgap: var(--space-sm);\n\tmin-width: var(--control-height);\n\tmax-width: 100%;\n\toverflow: hidden;\n}\n\n.content {\n\tmin-width: 0;\n\tmax-width: 100%;\n\tflex: 1 1 auto;\n\toverflow: hidden;\n}\n\n.contentScroller {\n\twidth: 100%;\n\tmin-width: 0;\n}\n\n.labeledPanel {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-sm);\n\twidth: 100%;\n\tmin-width: 0;\n}\n\n.label {\n\tcolor: var(--content-0);\n}\n\n.labeledActionPanel {\n\tflex: 0 1 auto;\n}\n","import React, { PropsWithChildren, useCallback, useId, useState } from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { ChevronsLeftIcon, ChevronsRightIcon } from \"lucide-react\";\n\nimport { Button } from \"../button\";\nimport { OneStepScroller } from \"../misc\";\n\nimport styles from \"./ExpandableActionPanel.module.scss\";\n\nexport interface ExpandableActionPanelProps extends PropsWithChildren {\n\tclassName?: string;\n\tcontentClassName?: string;\n\ttoggleClassName?: string;\n\topen?: boolean;\n\tdefaultOpen?: boolean;\n\tdisabled?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n\texpandLabel?: string;\n\tcollapseLabel?: string;\n\tpanelLabel?: string;\n\titemSelector?: string;\n\tscrollPadding?: number;\n\tsmoothScroll?: boolean;\n}\n\n/**\n * Горизонтальная раскрывающаяся панель действий.\n * Не знает о внешнем layout и может использоваться рядом с любым содержимым.\n */\nexport function ExpandableActionPanel({\n\tchildren,\n\tclassName,\n\tcontentClassName,\n\ttoggleClassName,\n\topen: controlledOpen,\n\tdefaultOpen = false,\n\tdisabled,\n\tonOpenChange,\n\texpandLabel = \"Раскрыть панель действий влево\",\n\tcollapseLabel = \"Свернуть панель действий\",\n\tpanelLabel = \"Действия панели\",\n\titemSelector,\n\tscrollPadding,\n\tsmoothScroll\n}: ExpandableActionPanelProps) {\n\tconst [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\tconst panelId = useId();\n\tconst isControlled = controlledOpen !== undefined;\n\tconst open = isControlled ? controlledOpen : uncontrolledOpen;\n\n\tconst setOpen = useCallback<React.Dispatch<React.SetStateAction<boolean>>>(\n\t\t(value) => {\n\t\t\tconst nextOpen = typeof value === \"function\" ? value(open) : value;\n\n\t\t\tif (!isControlled) {\n\t\t\t\tsetUncontrolledOpen(nextOpen);\n\t\t\t}\n\n\t\t\tonOpenChange?.(nextOpen);\n\t\t},\n\t\t[isControlled, onOpenChange, open]\n\t);\n\n\tconst handleToggle = () => setOpen((prevOpen) => !prevOpen);\n\tconst ToggleIcon = open ? ChevronsRightIcon : ChevronsLeftIcon;\n\n\treturn (\n\t\t<div className={cn(styles.expandableActionPanel, className)} data-ui=\"expandable-action-panel\" data-open={open ? \"\" : undefined}>\n\t\t\t<Button\n\t\t\t\tclassName={toggleClassName}\n\t\t\t\ticon={<ToggleIcon />}\n\t\t\t\ttitle={open ? collapseLabel : expandLabel}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tvariant=\"neutralOutline\"\n\t\t\t\taria-expanded={open}\n\t\t\t\taria-controls={panelId}\n\t\t\t\tdata-ui=\"expandable-action-panel-toggle\"\n\t\t\t\tdata-action={open ? \"collapse-action-panel\" : \"expand-action-panel\"}\n\t\t\t\tonClick={handleToggle}\n\t\t\t/>\n\n\t\t\t{open && (\n\t\t\t\t<div id={panelId} role=\"group\" aria-label={panelLabel} className={cn(styles.content, contentClassName)}>\n\t\t\t\t\t<OneStepScroller\n\t\t\t\t\t\tclassName={styles.contentScroller}\n\t\t\t\t\t\titemSelector={itemSelector}\n\t\t\t\t\t\tscrollPadding={scrollPadding}\n\t\t\t\t\t\tsmooth={smoothScroll}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</OneStepScroller>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import React from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { ExpandableActionPanel, ExpandableActionPanelProps } from \"./ExpandableActionPanel\";\nimport styles from \"./ExpandableActionPanel.module.scss\";\n\nexport interface LabeledExpandableActionPanelProps extends Omit<ExpandableActionPanelProps, \"className\"> {\n\tlabel: React.ReactNode;\n\tclassName?: string;\n\tlabelClassName?: string;\n\tlabelStyle?: React.CSSProperties;\n\tlabelMinWidth?: React.CSSProperties[\"minWidth\"];\n\tpanelClassName?: string;\n}\n\n/**\n * Раскрывающаяся панель действий с левым текстом, который сжимается через `flexEllipsis`.\n */\nexport function LabeledExpandableActionPanel({\n\tlabel,\n\tclassName,\n\tlabelClassName,\n\tlabelStyle,\n\tlabelMinWidth = \"12em\",\n\tpanelClassName,\n\topen,\n\tdefaultOpen,\n\t...panelProps\n}: LabeledExpandableActionPanelProps) {\n\tconst resolvedLabelStyle: React.CSSProperties = {\n\t\t...labelStyle,\n\t\tminWidth: labelMinWidth\n\t};\n\tconst title = typeof label === \"string\" ? label : undefined;\n\n\treturn (\n\t\t<div className={cn(styles.labeledPanel, className)} data-ui=\"labeled-expandable-action-panel\">\n\t\t\t<div className={cn(\"flexEllipsis\", styles.label, labelClassName)} style={resolvedLabelStyle} title={title}>\n\t\t\t\t{label}\n\t\t\t</div>\n\t\t\t<ExpandableActionPanel\n\t\t\t\t{...panelProps}\n\t\t\t\topen={open}\n\t\t\t\tdefaultOpen={defaultOpen}\n\t\t\t\tclassName={cn(styles.labeledActionPanel, panelClassName)}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AC8BA,SAAgB,EAAsB,EACrC,aACA,cACA,qBACA,oBACA,MAAM,GACN,iBAAc,IACd,aACA,iBACA,iBAAc,kCACd,mBAAgB,4BAChB,gBAAa,mBACb,iBACA,kBACA,mBAC8B;CAC9B,IAAM,CAAC,GAAkB,KAAuB,EAAS,CAAW,GAC9D,IAAU,EAAM,GAChB,IAAe,MAAmB,KAAA,GAClC,IAAO,IAAe,IAAiB,GAEvC,IAAU,GACd,MAAU;EACV,IAAM,IAAW,OAAO,KAAU,aAAa,EAAM,CAAI,IAAI;EAM7D,AAJK,KACJ,EAAoB,CAAQ,GAG7B,IAAe,CAAQ;CACxB,GACA;EAAC;EAAc;EAAc;CAAI,CAClC,GAEM,UAAqB,GAAS,MAAa,CAAC,CAAQ,GACpD,IAAa,IAAO,IAAoB;CAE9C,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,uBAAuB,CAAS;EAAG,WAAQ;EAA0B,aAAW,IAAO,KAAK,KAAA;EAAtH,UAAA,CACC,kBAAC,GAAD;GACC,WAAW;GACX,MAAM,kBAAC,GAAD,CAAa,CAAA;GACnB,OAAO,IAAO,IAAgB;GACpB;GACV,SAAQ;GACR,iBAAe;GACf,iBAAe;GACf,WAAQ;GACR,eAAa,IAAO,0BAA0B;GAC9C,SAAS;EACT,CAAA,GAEA,KACA,kBAAC,OAAD;GAAK,IAAI;GAAS,MAAK;GAAQ,cAAY;GAAY,WAAW,EAAG,EAAO,SAAS,CAAgB;GACpG,UAAA,kBAAC,GAAD;IACC,WAAW,EAAO;IACJ;IACC;IACf,QAAQ;IACP;GACe,CAAA;EACb,CAAA,CAEF;;AAEP;;;AC5EA,SAAgB,EAA6B,EAC5C,UACA,cACA,mBACA,eACA,mBAAgB,QAChB,mBACA,SACA,gBACA,GAAG,KACkC;CACrC,IAAM,IAA0C;EAC/C,GAAG;EACH,UAAU;CACX,GACM,IAAQ,OAAO,KAAU,WAAW,IAAQ,KAAA;CAElD,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,cAAc,CAAS;EAAG,WAAQ;EAA5D,UAAA,CACC,kBAAC,OAAD;GAAK,WAAW,EAAG,gBAAgB,EAAO,OAAO,CAAc;GAAG,OAAO;GAA2B;GAClG,UAAA;EACG,CAAA,GACL,kBAAC,GAAD;GACC,GAAI;GACE;GACO;GACb,WAAW,EAAG,EAAO,oBAAoB,CAAc;EACvD,CAAA,CACG;;AAEP"}
|
package/dist/flex/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i, t as a } from "../chunks/flex-
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, t as a } from "../chunks/flex-C7njxZ74.js";
|
|
2
2
|
export { i as Flex, n as FlexCenter, r as FlexContainer, e as FlexItem, a as FlexSpacer, t as PredefinedFlex };
|
|
@@ -15,7 +15,7 @@ function d({ open: d, title: f, description: p, onOpenChange: m, children: h })
|
|
|
15
15
|
let { refs: g, context: _ } = o({
|
|
16
16
|
open: d,
|
|
17
17
|
onOpenChange: m
|
|
18
|
-
}),
|
|
18
|
+
}), v = a(_, { outsidePress: !1 }), y = c(_, { role: "dialog" }), { getFloatingProps: b } = s([v, y]), x = e((e) => {
|
|
19
19
|
g.setFloating(e);
|
|
20
20
|
}, [g]);
|
|
21
21
|
return d ? /* @__PURE__ */ t(i, { children: /* @__PURE__ */ t(r, {
|
|
@@ -26,8 +26,8 @@ function d({ open: d, title: f, description: p, onOpenChange: m, children: h })
|
|
|
26
26
|
modal: !1,
|
|
27
27
|
returnFocus: !0,
|
|
28
28
|
children: /* @__PURE__ */ t("section", {
|
|
29
|
-
ref:
|
|
30
|
-
...
|
|
29
|
+
ref: x,
|
|
30
|
+
...b({
|
|
31
31
|
className: l.panel,
|
|
32
32
|
"aria-label": u(f, p)
|
|
33
33
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/fullscreen-portal/FullscreenPortal.module.scss","../../src/fullscreen-portal/FullscreenPortal.tsx"],"sourcesContent":[".overlay {\n\tposition: fixed;\n\tinset: 0;\n\tz-index: var(--z-fullscreen-portal);\n\tbackground: var(--overlay-glass);\n}\n\n.panel {\n\tposition: fixed;\n\tinset: var(--space-lg);\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tmin-height: 0;\n\tpadding: var(--space-md);\n\tborder: var(--border);\n\tborder-radius: var(--radius-md);\n\tbackground: var(--surface-1);\n\tbox-shadow: var(--shadow-lg);\n\toverflow: hidden;\n\n\t&:focus-visible {\n\t\toutline: var(--focus);\n\t\toutline-offset: var(--focus-offset);\n\t}\n}\n","import { useCallback, type ReactNode } from \"react\";\n\nimport {\n\tFloatingFocusManager,\n\tFloatingOverlay,\n\tFloatingPortal,\n\tuseDismiss,\n\tuseFloating,\n\tuseInteractions,\n\tuseRole\n} from \"@floating-ui/react\";\n\nimport styles from \"./FullscreenPortal.module.scss\";\n\n/** Props полноэкранного портала для поверхностных UI-блоков. */\nexport type FullscreenPortalProps = {\n\t/** Признак открытого fullscreen-режима. */\n\topen: boolean;\n\t/** Заголовок содержимого, используемый для доступного имени dialog. */\n\ttitle: string;\n\t/** Описание fullscreen-режима для доступного имени dialog. */\n\tdescription: string;\n\t/** Callback изменения состояния fullscreen-режима. */\n\tonOpenChange: (open: boolean) => void;\n\t/** Содержимое, которое нужно отрендерить в полноэкранном слое. */\n\tchildren: ReactNode;\n};\n\n/** Формирует доступное имя dialog из заголовка и описания fullscreen-режима. */\nfunction resolveFullscreenAriaLabel(title: string, description: string): string {\n\tconst trimmedTitle = title.trim();\n\treturn trimmedTitle ? `${trimmedTitle}. ${description}` : description;\n}\n\n/** Универсальный fullscreen-портал на базе Floating UI. */\nexport function FullscreenPortal({ open, title, description, onOpenChange, children }: FullscreenPortalProps) {\n\tconst { refs, context } = useFloating({ open, onOpenChange });\n\tconst dismiss = useDismiss(context, { outsidePress: false });\n\tconst role = useRole(context, { role: \"dialog\" });\n\tconst { getFloatingProps } = useInteractions([dismiss, role]);\n\t/** Передает DOM-узел полноэкранной панели в Floating UI context. */\n\tconst setFloating = useCallback(\n\t\t(node: HTMLElement | null) => {\n\t\t\trefs.setFloating(node);\n\t\t},\n\t\t[refs]\n\t);\n\n\tif (!open) return null;\n\n\treturn (\n\t\t<FloatingPortal>\n\t\t\t<FloatingOverlay lockScroll className={styles.overlay}>\n\t\t\t\t<FloatingFocusManager context={context} modal={false} returnFocus>\n\t\t\t\t\t<section\n\t\t\t\t\t\tref={setFloating}\n\t\t\t\t\t\t{...getFloatingProps({\n\t\t\t\t\t\t\tclassName: styles.panel,\n\t\t\t\t\t\t\t\"aria-label\": resolveFullscreenAriaLabel(title, description)\n\t\t\t\t\t\t})}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</section>\n\t\t\t\t</FloatingFocusManager>\n\t\t\t</FloatingOverlay>\n\t\t</FloatingPortal>\n\t);\n}\n"],"mappings":";;;;;;;;;AC6BA,SAAS,EAA2B,GAAe,GAA6B;CAC/E,IAAM,IAAe,EAAM,KAAK;CAChC,OAAO,IAAe,GAAG,EAAa,IAAI,MAAgB;AAC3D;AAGA,SAAgB,EAAiB,EAAE,SAAM,UAAO,gBAAa,iBAAc,eAAmC;CAC7G,IAAM,EAAE,SAAM,eAAY,EAAY;EAAE;EAAM;CAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/fullscreen-portal/FullscreenPortal.module.scss","../../src/fullscreen-portal/FullscreenPortal.tsx"],"sourcesContent":[".overlay {\n\tposition: fixed;\n\tinset: 0;\n\tz-index: var(--z-fullscreen-portal);\n\tbackground: var(--overlay-glass);\n}\n\n.panel {\n\tposition: fixed;\n\tinset: var(--space-lg);\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tmin-height: 0;\n\tpadding: var(--space-md);\n\tborder: var(--border);\n\tborder-radius: var(--radius-md);\n\tbackground: var(--surface-1);\n\tbox-shadow: var(--shadow-lg);\n\toverflow: hidden;\n\n\t&:focus-visible {\n\t\toutline: var(--focus);\n\t\toutline-offset: var(--focus-offset);\n\t}\n}\n","import { useCallback, type ReactNode } from \"react\";\n\nimport {\n\tFloatingFocusManager,\n\tFloatingOverlay,\n\tFloatingPortal,\n\tuseDismiss,\n\tuseFloating,\n\tuseInteractions,\n\tuseRole\n} from \"@floating-ui/react\";\n\nimport styles from \"./FullscreenPortal.module.scss\";\n\n/** Props полноэкранного портала для поверхностных UI-блоков. */\nexport type FullscreenPortalProps = {\n\t/** Признак открытого fullscreen-режима. */\n\topen: boolean;\n\t/** Заголовок содержимого, используемый для доступного имени dialog. */\n\ttitle: string;\n\t/** Описание fullscreen-режима для доступного имени dialog. */\n\tdescription: string;\n\t/** Callback изменения состояния fullscreen-режима. */\n\tonOpenChange: (open: boolean) => void;\n\t/** Содержимое, которое нужно отрендерить в полноэкранном слое. */\n\tchildren: ReactNode;\n};\n\n/** Формирует доступное имя dialog из заголовка и описания fullscreen-режима. */\nfunction resolveFullscreenAriaLabel(title: string, description: string): string {\n\tconst trimmedTitle = title.trim();\n\treturn trimmedTitle ? `${trimmedTitle}. ${description}` : description;\n}\n\n/** Универсальный fullscreen-портал на базе Floating UI. */\nexport function FullscreenPortal({ open, title, description, onOpenChange, children }: FullscreenPortalProps) {\n\tconst { refs, context } = useFloating({ open, onOpenChange });\n\tconst dismiss = useDismiss(context, { outsidePress: false });\n\tconst role = useRole(context, { role: \"dialog\" });\n\tconst { getFloatingProps } = useInteractions([dismiss, role]);\n\t/** Передает DOM-узел полноэкранной панели в Floating UI context. */\n\tconst setFloating = useCallback(\n\t\t(node: HTMLElement | null) => {\n\t\t\trefs.setFloating(node);\n\t\t},\n\t\t[refs]\n\t);\n\n\tif (!open) return null;\n\n\treturn (\n\t\t<FloatingPortal>\n\t\t\t<FloatingOverlay lockScroll className={styles.overlay}>\n\t\t\t\t<FloatingFocusManager context={context} modal={false} returnFocus>\n\t\t\t\t\t<section\n\t\t\t\t\t\tref={setFloating}\n\t\t\t\t\t\t{...getFloatingProps({\n\t\t\t\t\t\t\tclassName: styles.panel,\n\t\t\t\t\t\t\t\"aria-label\": resolveFullscreenAriaLabel(title, description)\n\t\t\t\t\t\t})}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</section>\n\t\t\t\t</FloatingFocusManager>\n\t\t\t</FloatingOverlay>\n\t\t</FloatingPortal>\n\t);\n}\n"],"mappings":";;;;;;;;;AC6BA,SAAS,EAA2B,GAAe,GAA6B;CAC/E,IAAM,IAAe,EAAM,KAAK;CAChC,OAAO,IAAe,GAAG,EAAa,IAAI,MAAgB;AAC3D;AAGA,SAAgB,EAAiB,EAAE,SAAM,UAAO,gBAAa,iBAAc,eAAmC;CAC7G,IAAM,EAAE,SAAM,eAAY,EAAY;EAAE;EAAM;CAAa,CAAC,GACtD,IAAU,EAAW,GAAS,EAAE,cAAc,GAAM,CAAC,GACrD,IAAO,EAAQ,GAAS,EAAE,MAAM,SAAS,CAAC,GAC1C,EAAE,wBAAqB,EAAgB,CAAC,GAAS,CAAI,CAAC,GAEtD,IAAc,GAClB,MAA6B;EAC7B,EAAK,YAAY,CAAI;CACtB,GACA,CAAC,CAAI,CACN;CAIA,OAFK,IAGJ,kBAAC,GAAD,EAAA,UACC,kBAAC,GAAD;EAAiB,YAAA;EAAW,WAAW,EAAO;EAC7C,UAAA,kBAAC,GAAD;GAA+B;GAAS,OAAO;GAAO,aAAA;GACrD,UAAA,kBAAC,WAAD;IACC,KAAK;IACL,GAAI,EAAiB;KACpB,WAAW,EAAO;KAClB,cAAc,EAA2B,GAAO,CAAW;IAC5D,CAAC;IACA;GACO,CAAA;EACY,CAAA;CACN,CAAA,EACF,CAAA,IAhBC;AAkBnB"}
|
package/dist/image/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as e } from "../chunks/button-
|
|
1
|
+
import { n as e } from "../chunks/button-BU2kRzwu.js";
|
|
2
2
|
import { r as t } from "../chunks/grid-dI94AAbi.js";
|
|
3
|
-
import { o as n } from "../chunks/input-
|
|
4
|
-
import { i as r, n as i, r as a } from "../chunks/modal-
|
|
5
|
-
import { t as o } from "../chunks/input-files-
|
|
3
|
+
import { o as n } from "../chunks/input-Bp6_Ucgr.js";
|
|
4
|
+
import { i as r, n as i, r as a } from "../chunks/modal-paexEF0j.js";
|
|
5
|
+
import { t as o } from "../chunks/input-files-D1JzSw_Y.js";
|
|
6
6
|
import { Suspense as s, lazy as c, useCallback as l, useEffect as u, useMemo as d, useRef as f, useState as p } from "react";
|
|
7
7
|
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
8
8
|
import _ from "react-easy-crop";
|
|
@@ -500,7 +500,7 @@ function M({ image: e, alt: t, sizes: n, aspectRatio: r, ...i }) {
|
|
|
500
500
|
}
|
|
501
501
|
//#endregion
|
|
502
502
|
//#region src/image/ui/ImageViewer.tsx
|
|
503
|
-
var N = c(() => import("../chunks/ImageViewerRuntime-
|
|
503
|
+
var N = c(() => import("../chunks/ImageViewerRuntime-BMs3BBkV.js"));
|
|
504
504
|
function P(e) {
|
|
505
505
|
let [t, n] = p(!1), r = l(() => n(!0), []);
|
|
506
506
|
return typeof document < "u" && (e.open || t) ? /* @__PURE__ */ h(s, {
|
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","../../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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"}
|
|
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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"}
|
package/dist/input/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "../chunks/input-
|
|
1
|
+
import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "../chunks/input-Bp6_Ucgr.js";
|
|
2
2
|
export { i as Input, o as InputClearButton, n as InputControl, c as InputErrorComponent, e as InputNumber, a as InputText, s as InputUI, t as InputUILoading, r as useInputFieldIds };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as e } from "../chunks/ui.module-BisoTevy.js";
|
|
2
|
-
import { i as t, l as n, r, s as i } from "../chunks/input-
|
|
2
|
+
import { i as t, l as n, r, s as i } from "../chunks/input-Bp6_Ucgr.js";
|
|
3
3
|
import { useCallback as a, useMemo as o, useRef as s, useState as c } from "react";
|
|
4
4
|
import { cn as l } from "@ryuzaki13/react-foundation-lib/utils";
|
|
5
5
|
import { jsx as u } from "react/jsx-runtime";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/input-date-time/InputDateTime.module.scss","../../src/input-date-time/maskParser.ts","../../src/input-date-time/useMaskedSegments.ts","../../src/input-date-time/InputDateTime.tsx"],"sourcesContent":["@use \"@/styles/mixins\" as *;\n\n.segmentInput {\n\tborder: none;\n\tbackground: transparent;\n\toutline: none;\n\tpadding: 0;\n\tmargin: 0;\n\tfont-family: var(--font-family-mono);\n\tcolor: inherit;\n\ttext-align: center;\n\tcaret-color: var(--content-0);\n\tfont-variant-numeric: tabular-nums;\n\n\t&::placeholder {\n\t\tcolor: var(--content-2);\n\t\t// font-size: var(--font-size-sm);\n\t}\n\n\t&::selection {\n\t\tbackground-color: var(--focus-ring);\n\t\tcolor: var(--surface-0);\n\t}\n\n\t// Remove spin buttons\n\t&::-webkit-inner-spin-button,\n\t&::-webkit-outer-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n\n\t&:disabled {\n\t\topacity: 0.25;\n\t}\n}\n\n.separator {\n\tuser-select: none;\n\tcolor: var(--content-2);\n\tflex-shrink: 0;\n\n\t&[data-disabled] {\n\t\topacity: 0.25;\n\t}\n}\n","import {\n\ttype DateMaskSegment,\n\ttype DateSegmentId,\n\tdateToIndexedSegmentValues,\n\ttype EditableDateSegment,\n\tindexedSegmentsToDate,\n\ttype LiteralDateSegment,\n\tparseDateSegmentMask\n} from \"@ryuzaki13/react-foundation-lib/date-segments\";\n\n/**\n * Совместимый тип сегмента для существующего `InputDateTime`.\n */\nexport type SegmentType = DateSegmentId;\n\n/**\n * Совместимый редактируемый сегмент для существующего `InputDateTime`.\n */\nexport interface EditableSegment extends Omit<EditableDateSegment, \"id\"> {\n\ttype: SegmentType;\n}\n\n/**\n * Совместимый литеральный сегмент для существующего `InputDateTime`.\n */\nexport type LiteralSegment = LiteralDateSegment;\n\n/**\n * Совместимый тип сегмента маски для существующего `InputDateTime`.\n */\nexport type Segment = EditableSegment | LiteralSegment;\n\n/**\n * Разбирает строковую маску, сохраняя прежний контракт `InputDateTime`.\n */\nexport function parseMask(mask: string): Segment[] {\n\treturn parseDateSegmentMask(mask).map((segment) => (segment.kind === \"editable\" ? { ...segment, type: segment.id } : segment));\n}\n\n/**\n * Преобразует Date в карту значений сегментов по их совместимым типам.\n */\nexport function dateToSegmentValues(date: Date | undefined, segments: Segment[]): Map<SegmentType, string> {\n\tconst indexedValues = dateToIndexedSegmentValues(date, segments as DateMaskSegment[]);\n\tconst values = new Map<SegmentType, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tvalues.set(segment.type, indexedValues.get(index) ?? \"\");\n\t});\n\n\treturn values;\n}\n\n/**\n * Собирает строгий Date из карты сегментов старого формата.\n */\nexport function segmentsToDate(segments: Segment[], values: Map<SegmentType, string>): Date | null {\n\tconst indexedValues = new Map<number, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tindexedValues.set(index, values.get(segment.type) ?? \"\");\n\t});\n\n\treturn indexedSegmentsToDate(segments as DateMaskSegment[], indexedValues);\n}\n","import React, { useCallback, useMemo, useRef, useState } from \"react\";\n\nimport { dateToSegmentValues, EditableSegment, parseMask, segmentsToDate, SegmentType } from \"./maskParser\";\n\ninterface UseMaskedSegmentsOptions {\n\tmask: string;\n\tvalue: Date | undefined;\n\tonChange: (date: Date) => void;\n\tonClearError?: () => void;\n\tdisabled?: boolean;\n}\n\n// Вычисляет Map<index, string> из Date и массива сегментов\nfunction buildSegmentMap(date: Date | undefined, segments: ReturnType<typeof parseMask>): Map<number, string> {\n\tconst typeValues = dateToSegmentValues(date, segments);\n\tconst map = new Map<number, string>();\n\n\tsegments.forEach((seg, i) => {\n\t\tif (seg.kind === \"editable\") {\n\t\t\tmap.set(i, typeValues.get(seg.type) ?? \"\");\n\t\t}\n\t});\n\n\treturn map;\n}\n\n// TODO: Duplicate date-time-input/model/useDateTimeSegments\nfunction resolveEditableIndices(segments: ReturnType<typeof parseMask>): number[] {\n\tconst indices: number[] = [];\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind === \"editable\") {\n\t\t\tindices.push(index);\n\t\t}\n\t});\n\n\treturn indices;\n}\n\nexport function useMaskedSegments({ mask, value, onChange, onClearError, disabled }: UseMaskedSegmentsOptions) {\n\tconst segments = useMemo(() => parseMask(mask), [mask]);\n\n\tconst editableIndices = useMemo(() => resolveEditableIndices(segments), [segments]);\n\n\t// Значения сегментов, вычисленные из пропса value (источник истины)\n\tconst committedValues = useMemo(() => buildSegmentMap(value, segments), [value, segments]);\n\n\t// Локальные «грязные» значения при редактировании (null → используем committedValues)\n\tconst [dirtyValues, setDirtyValues] = useState<Map<number, string> | null>(null);\n\n\t// Сброс грязного состояния при внешнем изменении value (паттерн «adjusting state during render»)\n\tconst [prevValueTime, setPrevValueTime] = useState(() => value?.getTime());\n\tconst currentValueTime = value?.getTime();\n\tif (currentValueTime !== prevValueTime) {\n\t\tsetPrevValueTime(currentValueTime);\n\t\tsetDirtyValues(null);\n\t}\n\n\t// Текущие отображаемые значения\n\tconst segmentValues = dirtyValues ?? committedValues;\n\n\tconst refsMap = useRef<Map<number, HTMLInputElement>>(new Map());\n\tconst blurTimeout = useRef<number>(0);\n\tconst [isFocused, setIsFocused] = useState(false);\n\n\tconst tryFireOnChange = useCallback(\n\t\t(updatedValues: Map<number, string>) => {\n\t\t\tconst typeValues = new Map<SegmentType, string>();\n\n\t\t\tsegments.forEach((seg, i) => {\n\t\t\t\tif (seg.kind === \"editable\") {\n\t\t\t\t\ttypeValues.set(seg.type, updatedValues.get(i) ?? \"\");\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst date = segmentsToDate(segments, typeValues);\n\t\t\tif (date !== null) {\n\t\t\t\tonChange(date);\n\t\t\t}\n\t\t},\n\t\t[segments, onChange]\n\t);\n\n\tconst focusSegment = useCallback((index: number, selectAll = true) => {\n\t\tconst el = refsMap.current.get(index);\n\t\tif (el) {\n\t\t\tel.focus();\n\t\t\tif (selectAll) {\n\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t}\n\t\t}\n\t}, []);\n\n\tconst getNextEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos < editableIndices.length - 1 ? editableIndices[pos + 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst getPrevEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos > 0 ? editableIndices[pos - 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst padValue = useCallback((val: string, segment: EditableSegment): string => {\n\t\treturn val.padStart(segment.length, \"0\");\n\t}, []);\n\n\tconst registerRef = useCallback(\n\t\t(index: number) => (el: HTMLInputElement | null) => {\n\t\t\tif (el) {\n\t\t\t\trefsMap.current.set(index, el);\n\t\t\t} else {\n\t\t\t\trefsMap.current.delete(index);\n\t\t\t}\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleInput = useCallback(\n\t\t(index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst raw = e.target.value.replace(/\\D/g, \"\");\n\t\t\tconst clamped = raw.slice(0, segment.length);\n\n\t\t\tconst updated = new Map(segmentValues);\n\t\t\tupdated.set(index, clamped);\n\t\t\tsetDirtyValues(updated);\n\n\t\t\tonClearError?.();\n\n\t\t\t// Авто-переход к следующему сегменту при заполнении текущего\n\t\t\tif (clamped.length === segment.length) {\n\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\tif (next !== null) {\n\t\t\t\t\trequestAnimationFrame(() => focusSegment(next));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttryFireOnChange(updated);\n\t\t},\n\t\t[disabled, segments, segmentValues, onClearError, getNextEditable, focusSegment, tryFireOnChange]\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(index: number) => (e: React.KeyboardEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst currentVal = segmentValues.get(index) ?? \"\";\n\t\t\tconst el = e.currentTarget;\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase \"ArrowRight\": {\n\t\t\t\t\tif (el.selectionStart === currentVal.length || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\t\t\tif (next !== null) focusSegment(next);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowLeft\": {\n\t\t\t\t\tif (el.selectionStart === 0 || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowUp\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.min : parseInt(currentVal, 10) + 1;\n\t\t\t\t\tif (num > segment.max) num = segment.min;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowDown\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.max : parseInt(currentVal, 10) - 1;\n\t\t\t\t\tif (num < segment.min) num = segment.max;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Backspace\": {\n\t\t\t\t\tif (currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Delete\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, \"\");\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[disabled, segments, segmentValues, getNextEditable, getPrevEditable, focusSegment, padValue, tryFireOnChange]\n\t);\n\n\tconst handleFocus = useCallback(\n\t\t() => (e: React.FocusEvent<HTMLInputElement>) => {\n\t\t\te.target.select();\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleContainerFocus = useCallback(() => {\n\t\tclearTimeout(blurTimeout.current);\n\t\tsetIsFocused(true);\n\t}, []);\n\n\tconst handleContainerBlur = useCallback(() => {\n\t\tblurTimeout.current = window.setTimeout(() => {\n\t\t\tsetIsFocused(false);\n\t\t\t// Откат к последнему валидному значению (из пропса) при потере фокуса\n\t\t\tsetDirtyValues(null);\n\t\t}, 0);\n\t}, []);\n\n\tconst focusFirstEmpty = useCallback(() => {\n\t\tconst firstEmpty = editableIndices.find((i) => !(segmentValues.get(i) ?? \"\"));\n\t\tconst target = firstEmpty ?? editableIndices[editableIndices.length - 1];\n\t\tif (target !== undefined) focusSegment(target);\n\t}, [editableIndices, segmentValues, focusSegment]);\n\n\treturn {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tisFocused,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t};\n}\n","import { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { InputClearButton, InputControl, InputUI, useInputFieldIds } from \"../input\";\nimport { UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./InputDateTime.module.scss\";\nimport { useMaskedSegments } from \"./useMaskedSegments\";\n\ninterface InputDateTimeBaseProps extends UiBaseProps<Date, Date | undefined> {\n\tmask: string;\n\n\tclassName?: string;\n\n\terror?: string;\n\tonClearError?: () => void;\n\tonClear?: () => void;\n\n\t\"aria-label\"?: string;\n}\n\nfunction InputDateTimeBase({\n\tmask,\n\tvalue,\n\tonChange,\n\tlabel,\n\tdescription,\n\tdisabled,\n\tsize,\n\tclassName,\n\terror,\n\tonClearError,\n\tonClear,\n\t\"aria-label\": ariaLabel\n}: InputDateTimeBaseProps) {\n\tconst {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t} = useMaskedSegments({ mask, value, onChange, onClearError, disabled });\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={onClear ? <InputClearButton onClick={onClear} disabled={disabled} /> : undefined}\n\t\t\t\tendAdornmentWidth={onClear ? \"var(--control-height)\" : undefined}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<div\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControlFake, controlClassName)}\n\t\t\t\t\t\tdata-invalid={error ? \"\" : undefined}\n\t\t\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\t\t\trole=\"group\"\n\t\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\t\taria-label={ariaLabel || (typeof label === \"string\" ? label : undefined)}\n\t\t\t\t\t\taria-labelledby={ariaLabel ? undefined : labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tonFocus={handleContainerFocus}\n\t\t\t\t\t\tonBlur={handleContainerBlur}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\tif (e.target === e.currentTarget) focusFirstEmpty();\n\t\t\t\t\t\t}}>\n\t\t\t\t\t\t{segments.map((segment, index) => {\n\t\t\t\t\t\t\tif (segment.kind === \"literal\") {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<span key={index} className={styles.separator} data-disabled={disabled || undefined}>\n\t\t\t\t\t\t\t\t\t\t{segment.text}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\t\tref={registerRef(index)}\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tinputMode=\"numeric\"\n\t\t\t\t\t\t\t\t\tclassName={styles.segmentInput}\n\t\t\t\t\t\t\t\t\tstyle={{ width: `${segment.length + 0.5}ch` }}\n\t\t\t\t\t\t\t\t\tvalue={segmentValues.get(index) ?? \"\"}\n\t\t\t\t\t\t\t\t\tplaceholder={segment.placeholder}\n\t\t\t\t\t\t\t\t\tmaxLength={segment.length}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\taria-label={segment.type}\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tonChange={handleInput(index)}\n\t\t\t\t\t\t\t\t\tonKeyDown={handleKeyDown(index)}\n\t\t\t\t\t\t\t\t\tonFocus={handleFocus()}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\nexport type InputDateProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputDateTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\n\nexport function InputDate({ mask = \"YYYY.MM.DD\", ...props }: InputDateProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputTime({ mask = \"hh:mm\", ...props }: InputTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputDateTime({ mask = \"YYYY.MM.DD hh:mm\", ...props }: InputDateTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/input-date-time/InputDateTime.module.scss","../../src/input-date-time/maskParser.ts","../../src/input-date-time/useMaskedSegments.ts","../../src/input-date-time/InputDateTime.tsx"],"sourcesContent":["@use \"@/styles/mixins\" as *;\n\n.segmentInput {\n\tborder: none;\n\tbackground: transparent;\n\toutline: none;\n\tpadding: 0;\n\tmargin: 0;\n\tfont-family: var(--font-family-mono);\n\tcolor: inherit;\n\ttext-align: center;\n\tcaret-color: var(--content-0);\n\tfont-variant-numeric: tabular-nums;\n\n\t&::placeholder {\n\t\tcolor: var(--content-2);\n\t\t// font-size: var(--font-size-sm);\n\t}\n\n\t&::selection {\n\t\tbackground-color: var(--focus-ring);\n\t\tcolor: var(--surface-0);\n\t}\n\n\t// Remove spin buttons\n\t&::-webkit-inner-spin-button,\n\t&::-webkit-outer-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n\n\t&:disabled {\n\t\topacity: 0.25;\n\t}\n}\n\n.separator {\n\tuser-select: none;\n\tcolor: var(--content-2);\n\tflex-shrink: 0;\n\n\t&[data-disabled] {\n\t\topacity: 0.25;\n\t}\n}\n","import {\n\ttype DateMaskSegment,\n\ttype DateSegmentId,\n\tdateToIndexedSegmentValues,\n\ttype EditableDateSegment,\n\tindexedSegmentsToDate,\n\ttype LiteralDateSegment,\n\tparseDateSegmentMask\n} from \"@ryuzaki13/react-foundation-lib/date-segments\";\n\n/**\n * Совместимый тип сегмента для существующего `InputDateTime`.\n */\nexport type SegmentType = DateSegmentId;\n\n/**\n * Совместимый редактируемый сегмент для существующего `InputDateTime`.\n */\nexport interface EditableSegment extends Omit<EditableDateSegment, \"id\"> {\n\ttype: SegmentType;\n}\n\n/**\n * Совместимый литеральный сегмент для существующего `InputDateTime`.\n */\nexport type LiteralSegment = LiteralDateSegment;\n\n/**\n * Совместимый тип сегмента маски для существующего `InputDateTime`.\n */\nexport type Segment = EditableSegment | LiteralSegment;\n\n/**\n * Разбирает строковую маску, сохраняя прежний контракт `InputDateTime`.\n */\nexport function parseMask(mask: string): Segment[] {\n\treturn parseDateSegmentMask(mask).map((segment) => (segment.kind === \"editable\" ? { ...segment, type: segment.id } : segment));\n}\n\n/**\n * Преобразует Date в карту значений сегментов по их совместимым типам.\n */\nexport function dateToSegmentValues(date: Date | undefined, segments: Segment[]): Map<SegmentType, string> {\n\tconst indexedValues = dateToIndexedSegmentValues(date, segments as DateMaskSegment[]);\n\tconst values = new Map<SegmentType, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tvalues.set(segment.type, indexedValues.get(index) ?? \"\");\n\t});\n\n\treturn values;\n}\n\n/**\n * Собирает строгий Date из карты сегментов старого формата.\n */\nexport function segmentsToDate(segments: Segment[], values: Map<SegmentType, string>): Date | null {\n\tconst indexedValues = new Map<number, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tindexedValues.set(index, values.get(segment.type) ?? \"\");\n\t});\n\n\treturn indexedSegmentsToDate(segments as DateMaskSegment[], indexedValues);\n}\n","import React, { useCallback, useMemo, useRef, useState } from \"react\";\n\nimport { dateToSegmentValues, EditableSegment, parseMask, segmentsToDate, SegmentType } from \"./maskParser\";\n\ninterface UseMaskedSegmentsOptions {\n\tmask: string;\n\tvalue: Date | undefined;\n\tonChange: (date: Date) => void;\n\tonClearError?: () => void;\n\tdisabled?: boolean;\n}\n\n// Вычисляет Map<index, string> из Date и массива сегментов\nfunction buildSegmentMap(date: Date | undefined, segments: ReturnType<typeof parseMask>): Map<number, string> {\n\tconst typeValues = dateToSegmentValues(date, segments);\n\tconst map = new Map<number, string>();\n\n\tsegments.forEach((seg, i) => {\n\t\tif (seg.kind === \"editable\") {\n\t\t\tmap.set(i, typeValues.get(seg.type) ?? \"\");\n\t\t}\n\t});\n\n\treturn map;\n}\n\n// TODO: Duplicate date-time-input/model/useDateTimeSegments\nfunction resolveEditableIndices(segments: ReturnType<typeof parseMask>): number[] {\n\tconst indices: number[] = [];\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind === \"editable\") {\n\t\t\tindices.push(index);\n\t\t}\n\t});\n\n\treturn indices;\n}\n\nexport function useMaskedSegments({ mask, value, onChange, onClearError, disabled }: UseMaskedSegmentsOptions) {\n\tconst segments = useMemo(() => parseMask(mask), [mask]);\n\n\tconst editableIndices = useMemo(() => resolveEditableIndices(segments), [segments]);\n\n\t// Значения сегментов, вычисленные из пропса value (источник истины)\n\tconst committedValues = useMemo(() => buildSegmentMap(value, segments), [value, segments]);\n\n\t// Локальные «грязные» значения при редактировании (null → используем committedValues)\n\tconst [dirtyValues, setDirtyValues] = useState<Map<number, string> | null>(null);\n\n\t// Сброс грязного состояния при внешнем изменении value (паттерн «adjusting state during render»)\n\tconst [prevValueTime, setPrevValueTime] = useState(() => value?.getTime());\n\tconst currentValueTime = value?.getTime();\n\tif (currentValueTime !== prevValueTime) {\n\t\tsetPrevValueTime(currentValueTime);\n\t\tsetDirtyValues(null);\n\t}\n\n\t// Текущие отображаемые значения\n\tconst segmentValues = dirtyValues ?? committedValues;\n\n\tconst refsMap = useRef<Map<number, HTMLInputElement>>(new Map());\n\tconst blurTimeout = useRef<number>(0);\n\tconst [isFocused, setIsFocused] = useState(false);\n\n\tconst tryFireOnChange = useCallback(\n\t\t(updatedValues: Map<number, string>) => {\n\t\t\tconst typeValues = new Map<SegmentType, string>();\n\n\t\t\tsegments.forEach((seg, i) => {\n\t\t\t\tif (seg.kind === \"editable\") {\n\t\t\t\t\ttypeValues.set(seg.type, updatedValues.get(i) ?? \"\");\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst date = segmentsToDate(segments, typeValues);\n\t\t\tif (date !== null) {\n\t\t\t\tonChange(date);\n\t\t\t}\n\t\t},\n\t\t[segments, onChange]\n\t);\n\n\tconst focusSegment = useCallback((index: number, selectAll = true) => {\n\t\tconst el = refsMap.current.get(index);\n\t\tif (el) {\n\t\t\tel.focus();\n\t\t\tif (selectAll) {\n\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t}\n\t\t}\n\t}, []);\n\n\tconst getNextEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos < editableIndices.length - 1 ? editableIndices[pos + 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst getPrevEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos > 0 ? editableIndices[pos - 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst padValue = useCallback((val: string, segment: EditableSegment): string => {\n\t\treturn val.padStart(segment.length, \"0\");\n\t}, []);\n\n\tconst registerRef = useCallback(\n\t\t(index: number) => (el: HTMLInputElement | null) => {\n\t\t\tif (el) {\n\t\t\t\trefsMap.current.set(index, el);\n\t\t\t} else {\n\t\t\t\trefsMap.current.delete(index);\n\t\t\t}\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleInput = useCallback(\n\t\t(index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst raw = e.target.value.replace(/\\D/g, \"\");\n\t\t\tconst clamped = raw.slice(0, segment.length);\n\n\t\t\tconst updated = new Map(segmentValues);\n\t\t\tupdated.set(index, clamped);\n\t\t\tsetDirtyValues(updated);\n\n\t\t\tonClearError?.();\n\n\t\t\t// Авто-переход к следующему сегменту при заполнении текущего\n\t\t\tif (clamped.length === segment.length) {\n\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\tif (next !== null) {\n\t\t\t\t\trequestAnimationFrame(() => focusSegment(next));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttryFireOnChange(updated);\n\t\t},\n\t\t[disabled, segments, segmentValues, onClearError, getNextEditable, focusSegment, tryFireOnChange]\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(index: number) => (e: React.KeyboardEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst currentVal = segmentValues.get(index) ?? \"\";\n\t\t\tconst el = e.currentTarget;\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase \"ArrowRight\": {\n\t\t\t\t\tif (el.selectionStart === currentVal.length || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\t\t\tif (next !== null) focusSegment(next);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowLeft\": {\n\t\t\t\t\tif (el.selectionStart === 0 || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowUp\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.min : parseInt(currentVal, 10) + 1;\n\t\t\t\t\tif (num > segment.max) num = segment.min;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowDown\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.max : parseInt(currentVal, 10) - 1;\n\t\t\t\t\tif (num < segment.min) num = segment.max;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Backspace\": {\n\t\t\t\t\tif (currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Delete\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, \"\");\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[disabled, segments, segmentValues, getNextEditable, getPrevEditable, focusSegment, padValue, tryFireOnChange]\n\t);\n\n\tconst handleFocus = useCallback(\n\t\t() => (e: React.FocusEvent<HTMLInputElement>) => {\n\t\t\te.target.select();\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleContainerFocus = useCallback(() => {\n\t\tclearTimeout(blurTimeout.current);\n\t\tsetIsFocused(true);\n\t}, []);\n\n\tconst handleContainerBlur = useCallback(() => {\n\t\tblurTimeout.current = window.setTimeout(() => {\n\t\t\tsetIsFocused(false);\n\t\t\t// Откат к последнему валидному значению (из пропса) при потере фокуса\n\t\t\tsetDirtyValues(null);\n\t\t}, 0);\n\t}, []);\n\n\tconst focusFirstEmpty = useCallback(() => {\n\t\tconst firstEmpty = editableIndices.find((i) => !(segmentValues.get(i) ?? \"\"));\n\t\tconst target = firstEmpty ?? editableIndices[editableIndices.length - 1];\n\t\tif (target !== undefined) focusSegment(target);\n\t}, [editableIndices, segmentValues, focusSegment]);\n\n\treturn {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tisFocused,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t};\n}\n","import { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { InputClearButton, InputControl, InputUI, useInputFieldIds } from \"../input\";\nimport { UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./InputDateTime.module.scss\";\nimport { useMaskedSegments } from \"./useMaskedSegments\";\n\ninterface InputDateTimeBaseProps extends UiBaseProps<Date, Date | undefined> {\n\tmask: string;\n\n\tclassName?: string;\n\n\terror?: string;\n\tonClearError?: () => void;\n\tonClear?: () => void;\n\n\t\"aria-label\"?: string;\n}\n\nfunction InputDateTimeBase({\n\tmask,\n\tvalue,\n\tonChange,\n\tlabel,\n\tdescription,\n\tdisabled,\n\tsize,\n\tclassName,\n\terror,\n\tonClearError,\n\tonClear,\n\t\"aria-label\": ariaLabel\n}: InputDateTimeBaseProps) {\n\tconst {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t} = useMaskedSegments({ mask, value, onChange, onClearError, disabled });\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={onClear ? <InputClearButton onClick={onClear} disabled={disabled} /> : undefined}\n\t\t\t\tendAdornmentWidth={onClear ? \"var(--control-height)\" : undefined}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<div\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControlFake, controlClassName)}\n\t\t\t\t\t\tdata-invalid={error ? \"\" : undefined}\n\t\t\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\t\t\trole=\"group\"\n\t\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\t\taria-label={ariaLabel || (typeof label === \"string\" ? label : undefined)}\n\t\t\t\t\t\taria-labelledby={ariaLabel ? undefined : labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tonFocus={handleContainerFocus}\n\t\t\t\t\t\tonBlur={handleContainerBlur}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\tif (e.target === e.currentTarget) focusFirstEmpty();\n\t\t\t\t\t\t}}>\n\t\t\t\t\t\t{segments.map((segment, index) => {\n\t\t\t\t\t\t\tif (segment.kind === \"literal\") {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<span key={index} className={styles.separator} data-disabled={disabled || undefined}>\n\t\t\t\t\t\t\t\t\t\t{segment.text}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\t\tref={registerRef(index)}\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tinputMode=\"numeric\"\n\t\t\t\t\t\t\t\t\tclassName={styles.segmentInput}\n\t\t\t\t\t\t\t\t\tstyle={{ width: `${segment.length + 0.5}ch` }}\n\t\t\t\t\t\t\t\t\tvalue={segmentValues.get(index) ?? \"\"}\n\t\t\t\t\t\t\t\t\tplaceholder={segment.placeholder}\n\t\t\t\t\t\t\t\t\tmaxLength={segment.length}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\taria-label={segment.type}\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tonChange={handleInput(index)}\n\t\t\t\t\t\t\t\t\tonKeyDown={handleKeyDown(index)}\n\t\t\t\t\t\t\t\t\tonFocus={handleFocus()}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\nexport type InputDateProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputDateTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\n\nexport function InputDate({ mask = \"YYYY.MM.DD\", ...props }: InputDateProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputTime({ mask = \"hh:mm\", ...props }: InputTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputDateTime({ mask = \"YYYY.MM.DD hh:mm\", ...props }: InputDateTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n"],"mappings":"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"}
|