@ryuzaki13/react-foundation-ui 1.8.12 → 1.8.14
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/chunks/ui.module-BsDio9A3.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
- package/storybook-static/assets/{Badge-CveIo2LZ.js → Badge-Sv6eRVzK.js} +1 -1
- package/storybook-static/assets/{Badge.stories-Bd8M64xJ.js → Badge.stories-DVmquAc-.js} +1 -1
- package/storybook-static/assets/{BadgeList-xT41a0VL.js → BadgeList-CDdjSFhA.js} +1 -1
- package/storybook-static/assets/{Button-DkDgfpHL.js → Button-CkXBOqtg.js} +1 -1
- package/storybook-static/assets/{Button-C5bBSb3k.js → Button-DLdmu_Qa.js} +1 -1
- package/storybook-static/assets/{Button.stories-CeKPeGK5.js → Button.stories-BhhPN3cO.js} +1 -1
- package/storybook-static/assets/{CalendarView-CEqcrblx.js → CalendarView-Cz74PFcU.js} +1 -1
- package/storybook-static/assets/{CheckBox-DKeFkdOt.js → CheckBox-8sW-kpX-.js} +1 -1
- package/storybook-static/assets/{CheckBox-OVvAarW-.js → CheckBox-DcH3qwbm.js} +1 -1
- package/storybook-static/assets/{CheckBox.stories-CfZ0p1yo.js → CheckBox.stories-BA9MwVIi.js} +1 -1
- package/storybook-static/assets/{Color-6AOWCN3U-BWW7zrfs.js → Color-6AOWCN3U-DW9_SixM.js} +1 -1
- package/storybook-static/assets/{ContextMenu-kia7is1N.js → ContextMenu-6XIB9-E_.js} +1 -1
- package/storybook-static/assets/{ContextMenu-xn2GtiLR.js → ContextMenu-oCfsHX5G.js} +1 -1
- package/storybook-static/assets/{ContextMenu.stories-CYuy9uXF.js → ContextMenu.stories-DsRiGv-d.js} +1 -1
- package/storybook-static/assets/{CustomOptionButton-C4w-APws.js → CustomOptionButton-By6XsDCG.js} +1 -1
- package/storybook-static/assets/{DateInput-BiUFIihm.js → DateInput-CD_CDw8L.js} +1 -1
- package/storybook-static/assets/{DateInput-DAzE5mCE.js → DateInput-CMxzQRo_.js} +1 -1
- package/storybook-static/assets/{DateInput.stories-BcowGCRD.js → DateInput.stories-BL0d4llb.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-RIyqNBk9.js → DateRangePresetSelect-393Izw7W.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-CQm4dNLR.js → DateRangePresetSelect-BeEhwdah.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect.stories-ypGyuGfy.js → DateRangePresetSelect.stories-BKRFlABX.js} +1 -1
- package/storybook-static/assets/{Detail-CEypL2Nh.js → Detail-BbQSGgu7.js} +1 -1
- package/storybook-static/assets/{Detail.stories-DNkT7B-u.js → Detail.stories-BMD_2zWN.js} +1 -1
- package/storybook-static/assets/{Dialog-BVFFQJDH.js → Dialog-CAM8VuM7.js} +1 -1
- package/storybook-static/assets/{Dialog-DD0grLG3.js → Dialog-Dw9rG9oU.js} +1 -1
- package/storybook-static/assets/{Dialog.stories-DSCypHqR.js → Dialog.stories-C3NKTM84.js} +1 -1
- package/storybook-static/assets/{Disclosure-DauUgrev.js → Disclosure-CRP1Wrwg.js} +1 -1
- package/storybook-static/assets/{Disclosure.stories-B1qB8vQZ.js → Disclosure.stories-uOnVxNv4.js} +1 -1
- package/storybook-static/assets/{DisclosureGroup-D9oCCeHf.js → DisclosureGroup-CV9aHNnL.js} +1 -1
- package/storybook-static/assets/{DocsRenderer-JROSPFPF-CmSf6tXp.js → DocsRenderer-JROSPFPF-Dt6sU0Wy.js} +1 -1
- package/storybook-static/assets/{DropZone-D8hbPCAv.js → DropZone-1-qIEJTI.js} +1 -1
- package/storybook-static/assets/{DropZone-D42ueN1w.js → DropZone-UOOd3d_D.js} +1 -1
- package/storybook-static/assets/{DropZone.stories-DO-T_Bh4.js → DropZone.stories-P0P8n3BX.js} +1 -1
- package/storybook-static/assets/{DropdownMenu-CknJDoji.js → DropdownMenu-CIkQkHEe.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel-Dqi_bo3c.js → ExpandableActionPanel-BVxtZtja.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel.stories-BD9QZGZN.js → ExpandableActionPanel.stories-Bw-Nbxjl.js} +1 -1
- package/storybook-static/assets/{Flex-CaVn1IOP.js → Flex-v3qGyymY.js} +1 -1
- package/storybook-static/assets/{Flex.stories-Bp9Y6q6b.js → Flex.stories-BZWj9Yqq.js} +1 -1
- package/storybook-static/assets/{FloatingPopover-U7tx-Jlw.js → FloatingPopover-CBzRVsZl.js} +1 -1
- package/storybook-static/assets/{FormattedTableCell-pmmhsAbN.js → FormattedTableCell-woQYObYH.js} +1 -1
- package/storybook-static/assets/{Grid-CEpMNurH.js → Grid-BuA8kbGl.js} +1 -1
- package/storybook-static/assets/{Grid.stories-BM-gO5DN.js → Grid.stories-DkQGjuPs.js} +1 -1
- package/storybook-static/assets/{ImageCropper.stories-BWz5XU6U.js → ImageCropper.stories-DWU8FP_b.js} +1 -1
- package/storybook-static/assets/{ImageRenderer-BTYZEX5t.js → ImageRenderer-BYrN4S_Z.js} +1 -1
- package/storybook-static/assets/{ImageRenderer.stories-Dz2STM95.js → ImageRenderer.stories-ChjsjhPh.js} +1 -1
- package/storybook-static/assets/{ImageView.stories-DBVe0an3.js → ImageView.stories-CWkyOzLP.js} +1 -1
- package/storybook-static/assets/{ImageViewer.stories-C4Px97lD.js → ImageViewer.stories-BAJJBDHc.js} +2 -2
- package/storybook-static/assets/{ImageViewerRuntime-TJtlJVfa.js → ImageViewerRuntime-DGLE97-e.js} +1 -1
- package/storybook-static/assets/{Input-CIPgijvW.js → Input-B8ZadIiC.js} +1 -1
- package/storybook-static/assets/{Input-D8io9jVS.js → Input-BoKPLAe2.js} +1 -1
- package/storybook-static/assets/{Input.stories-SUk3aYaC.js → Input.stories-JHdz5Jsc.js} +1 -1
- package/storybook-static/assets/{InputDateTime-DA5pIDuE.js → InputDateTime-D0IxugsL.js} +1 -1
- package/storybook-static/assets/{InputDateTime.stories-DeudzDSU.js → InputDateTime.stories-Ba0D7xF9.js} +1 -1
- package/storybook-static/assets/{InputFile-CGAC7ruP.js → InputFile--u_0dj3Y.js} +1 -1
- package/storybook-static/assets/{InputFile-C5mp5Y5I.js → InputFile-BTJBqn1m.js} +1 -1
- package/storybook-static/assets/{InputFile.stories-Cx1xQ6PE.js → InputFile.stories-CwpNYB5J.js} +1 -1
- package/storybook-static/assets/{InputFiles-B7OBcPJN.js → InputFiles-B6vhWm7I.js} +1 -1
- package/storybook-static/assets/{InputFiles-Hzl89Ghf.js → InputFiles-DwMvXQb3.js} +1 -1
- package/storybook-static/assets/{InputFiles.stories-CG6QjDZH.js → InputFiles.stories-5oCc9HHg.js} +1 -1
- package/storybook-static/assets/{InputFilesList-B6htWHF1.js → InputFilesList-D51n4iSR.js} +1 -1
- package/storybook-static/assets/{InputImage-CQnoblAE.js → InputImage-DPnitmQk.js} +1 -1
- package/storybook-static/assets/{InputImage-BTa4S4Wp.js → InputImage-bnYOQAkQ.js} +1 -1
- package/storybook-static/assets/{InputImage.stories-CEI44Eyz.js → InputImage.stories-uf2LvY4r.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents-B0ypWz1x.js → InteractiveComponents-CJn1YMhT.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents.stories-BadApta9.js → InteractiveComponents.stories-fFTx5yhl.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-C_Uz7Tnj.js → LayoutPicker-BPBdZChZ.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-COB9GlV_.js → LayoutPicker-C_NUvbsk.js} +1 -1
- package/storybook-static/assets/{LayoutPicker.stories-Btp0IcaL.js → LayoutPicker.stories-DBzM8rRy.js} +1 -1
- package/storybook-static/assets/{Listbox-CyfuZw7w.js → Listbox-Cqgq5Wny.js} +1 -1
- package/storybook-static/assets/{Listbox-AAaZGSAl.js → Listbox-D7jP8mCo.js} +1 -1
- package/storybook-static/assets/{Listbox.stories-NDKQmjyQ.js → Listbox.stories-X2jhmC90.js} +1 -1
- package/storybook-static/assets/{Modal-BJDnJ4zv.js → Modal-QiGhxbkR.js} +1 -1
- package/storybook-static/assets/{Modal.stories-D_X5lTLO.js → Modal.stories-CPLTAhHy.js} +1 -1
- package/storybook-static/assets/{ModalManagerProvider-ShDjozpW.js → ModalManagerProvider-DpbTvfL4.js} +1 -1
- package/storybook-static/assets/{MultiSelect-B5CElQ3-.js → MultiSelect-CJN6yc1C.js} +1 -1
- package/storybook-static/assets/{MultiSelect-DqXfrjcH.js → MultiSelect-DeAFY3RP.js} +1 -1
- package/storybook-static/assets/{MultiSelect.stories-fB3mcFmx.js → MultiSelect.stories-DHrCaM8r.js} +1 -1
- package/storybook-static/assets/{NoData-DDb0G7T8.js → NoData-Cw6KaFFK.js} +1 -1
- package/storybook-static/assets/{NotificationsHost-CIGL-pKX.js → NotificationsHost-BjEs_A2p.js} +1 -1
- package/storybook-static/assets/{NotificationsHost.stories-B_MRb3fs.js → NotificationsHost.stories-DUyWIJ9o.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect-DQAitH4N.js → ODataMultiSelect-DsGVEtfr.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect.stories-DwW221S9.js → ODataMultiSelect.stories-CV8LD8fz.js} +1 -1
- package/storybook-static/assets/{ODataSelect-tiZhOIhE.js → ODataSelect-nPkCWP7P.js} +1 -1
- package/storybook-static/assets/{ODataSelect.stories-BhaatPjK.js → ODataSelect.stories-BT5zNMAw.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect-B9WqJ-Un.js → ODataTreeMultiSelect-BnA7iZbw.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect.stories-CAfKuhfU.js → ODataTreeMultiSelect.stories-Ddu-3L1X.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect-Cel1phxZ.js → ODataTreeSelect-Df18JZjH.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect.stories-BpBCpBA9.js → ODataTreeSelect.stories-CnbN0_2o.js} +1 -1
- package/storybook-static/assets/{OneStepScroller-BSeGbz02.js → OneStepScroller-pCI7NBLQ.js} +1 -1
- package/storybook-static/assets/{Option-BBtQ3GdK.js → Option-rYnCuHwV.js} +1 -1
- package/storybook-static/assets/{OptionButton-B9nZuqqW.js → OptionButton-dRTEtcWJ.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-DA_zjcdA.js → PeriodSelect-BbxmKATg.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-BGvhR3to.js → PeriodSelect-QdYqbYVi.js} +1 -1
- package/storybook-static/assets/{PeriodSelect.stories-DDP1eXyM.js → PeriodSelect.stories-C_w6x_nb.js} +1 -1
- package/storybook-static/assets/{PickerTriggerActions-BgvzqRBd.js → PickerTriggerActions-B9PzXuqb.js} +1 -1
- package/storybook-static/assets/{Popover-C0NebUMz.js → Popover-C7EBSl-A.js} +1 -1
- package/storybook-static/assets/{Popover-BQql18MF.js → Popover-DTIeV8sp.js} +1 -1
- package/storybook-static/assets/{Popover.stories-CIyDUtlz.js → Popover.stories-DdK6opAj.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-htbxc3ni.js → PresetRangeDateInput-BuzCEA0N.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-BsgzPwCV.js → PresetRangeDateInput-wM7gI2RF.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput.stories-ClHM5Kah.js → PresetRangeDateInput.stories-BHzW7J5Y.js} +1 -1
- package/storybook-static/assets/{PresetSelect-Dcx0BOTx.js → PresetSelect-qwyBKXya.js} +1 -1
- package/storybook-static/assets/{README-eHCINzP3.js → README-3kx1b1eN.js} +1 -1
- package/storybook-static/assets/{README-CHbo4O3Z.js → README-B1TFddGZ.js} +1 -1
- package/storybook-static/assets/{README-ByALXSEH.js → README-B6UdiKEB.js} +1 -1
- package/storybook-static/assets/README-BB1nn-L1.js +740 -0
- package/storybook-static/assets/{README-CWfPiPIB.js → README-BLliGbp2.js} +1 -1
- package/storybook-static/assets/{README-DV4fCpqN.js → README-BRAIrWZ5.js} +1 -1
- package/storybook-static/assets/README-BS_UTHKY.js +441 -0
- package/storybook-static/assets/README-BUwRENpH.js +448 -0
- package/storybook-static/assets/README-BZ5VcRb-.js +583 -0
- package/storybook-static/assets/{README-CNHemCS2.js → README-BbvZ3Kxp.js} +1 -1
- package/storybook-static/assets/{README-BSh5XUR9.js → README-BcQVOGWd.js} +1 -1
- package/storybook-static/assets/{README-ui-uanyg.js → README-Bdo7L8re.js} +1 -1
- package/storybook-static/assets/README-Bl5v6SbZ.js +325 -0
- package/storybook-static/assets/{README-C3UcjOGB.js → README-Bs5hFsTF.js} +1 -1
- package/storybook-static/assets/{README-C8E1O7DQ.js → README-Bt-vDWJK.js} +1 -1
- package/storybook-static/assets/{README-CsoHGRve.js → README-BxWQjG0l.js} +1 -1
- package/storybook-static/assets/{README-BIq-FXcN.js → README-C1-upl_v.js} +1 -1
- package/storybook-static/assets/{README-qHKxXU95.js → README-C3kroViK.js} +1 -1
- package/storybook-static/assets/{README-CH_6ZIO2.js → README-C5VbGqji.js} +1 -1
- package/storybook-static/assets/README-CAN_sUOj.js +400 -0
- package/storybook-static/assets/{README-BB_JPejH.js → README-CAu_o5w0.js} +1 -1
- package/storybook-static/assets/{README-Ss-3t1nX.js → README-CB8w2VUq.js} +1 -1
- package/storybook-static/assets/README-CJ5dluvT.js +3591 -0
- package/storybook-static/assets/{README-B3bFglqG.js → README-CMdJkXoj.js} +1 -1
- package/storybook-static/assets/{README-Dl92E69Z.js → README-CUjyWC3m.js} +1 -1
- package/storybook-static/assets/{README-B45Cwj2a.js → README-CV3k61OS.js} +1 -1
- package/storybook-static/assets/README-CYOVpnIy.js +324 -0
- package/storybook-static/assets/{README-CM-7E-Jf.js → README-CeyhIAvP.js} +1 -1
- package/storybook-static/assets/{README-Byo6DxIF.js → README-Ci8Dg8Od.js} +1 -1
- package/storybook-static/assets/{README-DJHVgrpj.js → README-CiQrgj9L.js} +1 -1
- package/storybook-static/assets/{README-BxjYCoYA.js → README-CjAvZYa8.js} +1 -1
- package/storybook-static/assets/{README-5NhzH8VL.js → README-Cjkxz5fF.js} +1 -1
- package/storybook-static/assets/{README-DE2wk9-v.js → README-Cl_7GagY.js} +1 -1
- package/storybook-static/assets/{README-CIGfHKKE.js → README-CnncCyVQ.js} +1 -1
- package/storybook-static/assets/{README-Bqnqu1bC.js → README-CqqJTDcO.js} +1 -1
- package/storybook-static/assets/{README-D9OypaFB.js → README-CrjrH7U6.js} +1 -1
- package/storybook-static/assets/{README-DvAlDsh9.js → README-D1mTncLb.js} +1 -1
- package/storybook-static/assets/{README-B6Nq7NCU.js → README-DFH1zDp2.js} +1 -1
- package/storybook-static/assets/README-DIqS0sM9.js +355 -0
- package/storybook-static/assets/{README-DjCArsA5.js → README-DLaJrEGM.js} +1 -1
- package/storybook-static/assets/{README-Am6Fa6-b.js → README-DO23FJAl.js} +1 -1
- package/storybook-static/assets/{README-CeK4kfFO.js → README-DeAPv0Mf.js} +1 -1
- package/storybook-static/assets/{README-CAGQnLsv.js → README-Dy9sTa_6.js} +1 -1
- package/storybook-static/assets/{README-5M8ajrJp.js → README-JtT-ZtO0.js} +1 -1
- package/storybook-static/assets/{README-B6ltJiw3.js → README-OYzQVQte.js} +1 -1
- package/storybook-static/assets/{README-C9eh0JLs.js → README-UoSNP7Tk.js} +1 -1
- package/storybook-static/assets/{README-DDBqoI-T.js → README-a5ZgliOG.js} +1 -1
- package/storybook-static/assets/{README-DEj2wSK0.js → README-dokGlpDu.js} +1 -1
- package/storybook-static/assets/{README-BmhhWWEk.js → README-kQRTlSA-.js} +1 -1
- package/storybook-static/assets/{README-DIbfpC-2.js → README-rDh9Q6yY.js} +1 -1
- package/storybook-static/assets/{README-BuMMG4_N.js → README-rhPk9fCo.js} +1 -1
- package/storybook-static/assets/{README-DnA-4W65.js → README-rzRXnvCP.js} +1 -1
- package/storybook-static/assets/{README-BYSgTTZt.js → README-twVQ7X9P.js} +1 -1
- package/storybook-static/assets/{RadioButton-CWtjclwT.js → RadioButton-B_oQ8Wlu.js} +1 -1
- package/storybook-static/assets/{RadioButton-YIQXt0wx.js → RadioButton-Baxj9d9s.js} +1 -1
- package/storybook-static/assets/{RadioButton.stories-Ah-CBpeC.js → RadioButton.stories-CsHPV3Wm.js} +1 -1
- package/storybook-static/assets/{RadioGroup-CUS0etBD.js → RadioGroup-Dz0J0QJk.js} +1 -1
- package/storybook-static/assets/{RadioGroup-BnO-GL7A.js → RadioGroup-PH_lOUuL.js} +1 -1
- package/storybook-static/assets/{RadioGroup.stories-DGwCawtU.js → RadioGroup.stories-B3Nbh5ui.js} +1 -1
- package/storybook-static/assets/{Scrollable-D85fA6pO.js → Scrollable-BnVRtd7g.js} +1 -1
- package/storybook-static/assets/{Select-gRnfvfGh.js → Select-CqFdLQiM.js} +1 -1
- package/storybook-static/assets/{Select-CGCxJjL9.js → Select-DlCmYtXt.js} +1 -1
- package/storybook-static/assets/{Select.stories-CMwt4F9i.js → Select.stories-wUtNe9Ec.js} +1 -1
- package/storybook-static/assets/{SerializableSelect-BLXfKJ38.js → SerializableSelect-Cxj4rBI9.js} +1 -1
- package/storybook-static/assets/{SerializableSelect.stories-Bca1a9ZU.js → SerializableSelect.stories-D8S4jMFa.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-CyeQN0Rd.js → SingleDateTimeInput-B00ILEN6.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-xrmZckzw.js → SingleDateTimeInput-Z6TGUUj6.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput.stories-BYFTQM9z.js → SingleDateTimeInput.stories-CV6Nv9qi.js} +1 -1
- package/storybook-static/assets/{Slider-D8GtXVGI.js → Slider-B9FxWdEJ.js} +1 -1
- package/storybook-static/assets/{Slider-1yJ3uVeR.js → Slider-Dk01oltE.js} +1 -1
- package/storybook-static/assets/{Slider.stories-CyQ3ns_C.js → Slider.stories-VNmcaz3A.js} +1 -1
- package/storybook-static/assets/{SliderInput-ISSx9vH_.js → SliderInput-E86RlSIn.js} +1 -1
- package/storybook-static/assets/{SliderInput-BOzHhEUA.js → SliderInput-V3uHOcZ2.js} +1 -1
- package/storybook-static/assets/{SliderInput.stories-7ooTghrS.js → SliderInput.stories-Bwl2rOaJ.js} +1 -1
- package/storybook-static/assets/{Sortable-CCLiMmfZ.js → Sortable-DaGz4_X2.js} +1 -1
- package/storybook-static/assets/{Sortable.stories-B36szI6t.js → Sortable.stories-Ba8gP0xY.js} +1 -1
- package/storybook-static/assets/{Splitter-DQGhgRwx.js → Splitter-BIsxdfsl.js} +1 -1
- package/storybook-static/assets/{Splitter.stories-Hsq1wYaq.js → Splitter.stories-DlgVxAnv.js} +1 -1
- package/storybook-static/assets/{StateSelect-DieNn4VC.js → StateSelect-3pOCDdLu.js} +1 -1
- package/storybook-static/assets/{StateSelect-C6hldFgO.js → StateSelect-Q0-lss-x.js} +1 -1
- package/storybook-static/assets/{StateSelect.stories-CvAhDMix.js → StateSelect.stories-B2W4sd0y.js} +1 -1
- package/storybook-static/assets/{StringToggle.stories-CUT1tvt-.js → StringToggle.stories-CwhsQCkG.js} +1 -1
- package/storybook-static/assets/{Switch-nEMRtcWe.js → Switch-8ZMASw90.js} +1 -1
- package/storybook-static/assets/{Switch-CX9p_uYU.js → Switch-CxoCcf-H.js} +1 -1
- package/storybook-static/assets/{Switch.stories-CPsHa2_m.js → Switch.stories-Ceo-Mw04.js} +1 -1
- package/storybook-static/assets/{Table-BhtITVtj.js → Table-nJgo4qpK.js} +1 -1
- package/storybook-static/assets/{Table.stories-nWNhSydG.js → Table.stories-CSCZ9sFd.js} +1 -1
- package/storybook-static/assets/{Tabs-DMQFh2BJ.js → Tabs-D-gRjKef.js} +1 -1
- package/storybook-static/assets/{Tabs.stories-D23_xvom.js → Tabs.stories-EQ3VUnt-.js} +1 -1
- package/storybook-static/assets/{TabsBox-B5BsD_j_.js → TabsBox-NrlLIwhz.js} +1 -1
- package/storybook-static/assets/{TagInput-DO17z100.js → TagInput-Drf7SeTu.js} +1 -1
- package/storybook-static/assets/{TagInput.stories-CMMFnIzb.js → TagInput.stories-BcM6J6I9.js} +1 -1
- package/storybook-static/assets/{Text-ClnbDqRk.js → Text-Ck_6UUKY.js} +1 -1
- package/storybook-static/assets/{Textarea-DkhohiNc.js → Textarea-C7SEoYQa.js} +1 -1
- package/storybook-static/assets/{Textarea-C2IO_zsP.js → Textarea-DFko4W6r.js} +1 -1
- package/storybook-static/assets/{Textarea.stories-NL6Aq8Vc.js → Textarea.stories-BW5QBRXP.js} +1 -1
- package/storybook-static/assets/{TimePanel-DNEPDlSW.js → TimePanel-BcCaEcjP.js} +1 -1
- package/storybook-static/assets/{TimePanel.stories-DlfdPsz1.js → TimePanel.stories-OjUebxOe.js} +1 -1
- package/storybook-static/assets/{Toggle-3U5CceQN.js → Toggle-BN83AOrV.js} +1 -1
- package/storybook-static/assets/{Toggle-Cc6Ca-HI.js → Toggle-Cs5KD8Kd.js} +1 -1
- package/storybook-static/assets/{Toggle.stories-BR-hVLDp.js → Toggle.stories-UtFKPdYx.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-D9hMQN2O.js → TreeMultiSelect-04RqLe9P.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-B0oBc-4y.js → TreeMultiSelect-CN_rnzFe.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect.stories-CslpbvPR.js → TreeMultiSelect.stories-BbYabVXc.js} +1 -1
- package/storybook-static/assets/{TreePickerBase-B_dMCe45.js → TreePickerBase-FDlZpaH2.js} +1 -1
- package/storybook-static/assets/{TreeSelect-2lj0Q8gm.js → TreeSelect-DGSc7Vg9.js} +1 -1
- package/storybook-static/assets/{TreeSelect-DEKNYF2b.js → TreeSelect-DT6WnSjM.js} +1 -1
- package/storybook-static/assets/{TreeSelect.stories-CVDxn8Vm.js → TreeSelect.stories-C3jdjFQY.js} +1 -1
- package/storybook-static/assets/{TreeTable-CBIpzYRL.js → TreeTable-_ymCr62E.js} +1 -1
- package/storybook-static/assets/{TreeTable.stories-BMzrr2Kc.js → TreeTable.stories-DHShLIUZ.js} +1 -1
- package/storybook-static/assets/{blocks-B5YBxaaS.js → blocks-DcVVTXzf.js} +3 -3
- package/storybook-static/assets/{check-BjtdCRaW.js → check-5jIlw3QY.js} +1 -1
- package/storybook-static/assets/{chevron-down-B4u-y8Z1.js → chevron-down-CkkAjpRn.js} +1 -1
- package/storybook-static/assets/{chevron-left-BQfWs7Ah.js → chevron-left-DNKAotw1.js} +1 -1
- package/storybook-static/assets/{chevron-right-ChokKd-f.js → chevron-right-CYbSLSbL.js} +1 -1
- package/storybook-static/assets/{chunk-W22LQPXL-meOkhzk4.js → chunk-W22LQPXL-CfJS6YKX.js} +1 -1
- package/storybook-static/assets/{circle-alert-B1AnDRf_.js → circle-alert-DXlaxNFD.js} +1 -1
- package/storybook-static/assets/{circle-check-JYnlcC1F.js → circle-check-BEKmaVgA.js} +1 -1
- package/storybook-static/assets/{components-C_wl1sL5.js → components-tbVBP-zS.js} +3 -3
- package/storybook-static/assets/{contextMenu-B-TUGs_1.js → contextMenu-DsufH6U8.js} +1 -1
- package/storybook-static/assets/{download-eR3X8I-h.js → download-C9jGmfx6.js} +1 -1
- package/storybook-static/assets/{floating-ui.react-D95VPQ0b.js → floating-ui.react-YV96fWnb.js} +1 -1
- package/storybook-static/assets/{foundationApi-QhHXpYLB.js → foundationApi-DoAXLuxI.js} +1 -1
- package/storybook-static/assets/{foundationLib-CEAjnstw.js → foundationLib-C7xkVQAX.js} +1 -1
- package/storybook-static/assets/{hooks-awde7r2r.js → hooks-pjRWWXeZ.js} +1 -1
- package/storybook-static/assets/{iframe-FSp_AjJa.js → iframe--RU38UHO.js} +3 -3
- package/storybook-static/assets/iframe-BpGl-WdJ.js +1 -0
- package/storybook-static/assets/{info-12vmb1sT.js → info-CI9KvIum.js} +1 -1
- package/storybook-static/assets/{odata-C0Kpvttz.js → odata-bRglfPOU.js} +1 -1
- package/storybook-static/assets/{odataStoryFixtures-BXZnk_C7.js → odataStoryFixtures-B8p8bkan.js} +1 -1
- package/storybook-static/assets/{react-BlCqWuXr.js → react-pQ8GL5b8.js} +1 -1
- package/storybook-static/assets/{refresh-cw-Bf5ufPte.js → refresh-cw-BJlS8-cO.js} +1 -1
- package/storybook-static/assets/{settings-2-DR-dTXIC.js → settings-2-CDqhDJH7.js} +1 -1
- package/storybook-static/assets/{sortable-B5e5yb_-.js → sortable-CPlbom2V.js} +1 -1
- package/storybook-static/assets/{syntaxhighlighter-QEQV7K2Y-EVJARTec.js → syntaxhighlighter-QEQV7K2Y-Dh9tQsbp.js} +1 -1
- package/storybook-static/assets/{trash-2-QP7TS18H.js → trash-2-B3rSNw_b.js} +1 -1
- package/storybook-static/assets/{triangle-alert-qw19mxHr.js → triangle-alert-zaUE1fxx.js} +1 -1
- package/storybook-static/assets/{ui-CatTcSJL.css → ui-aDejsbZB.css} +1 -1
- package/storybook-static/assets/{uiClasses-B9c6dZuu.js → uiClasses-Cmg8Dx0X.js} +1 -1
- package/storybook-static/assets/{useODataSelectBase-Csu_Cct9.js → useODataSelectBase-DH9eFTxr.js} +1 -1
- package/storybook-static/assets/{useODataTreeData-BAv-Twqf.js → useODataTreeData-BrcEV-bK.js} +1 -1
- package/storybook-static/assets/{usePickerQuery-Da-XM_Y0.js → usePickerQuery-BbTJGOEV.js} +1 -1
- package/storybook-static/assets/{usePickerTriggerController-C0TdC2Pz.js → usePickerTriggerController-DNei2G7n.js} +1 -1
- package/storybook-static/assets/{x-aCjYTirW.js → x-BiHHkto5.js} +1 -1
- package/storybook-static/iframe.html +2 -2
- package/storybook-static/project.json +1 -1
- package/storybook-static/assets/README--LCKbep-.js +0 -110
- package/storybook-static/assets/README-BXJneZAJ.js +0 -147
- package/storybook-static/assets/README-C6BOdXNV.js +0 -322
- package/storybook-static/assets/README-CC00hlZK.js +0 -527
- package/storybook-static/assets/README-Cj2e6HrF.js +0 -178
- package/storybook-static/assets/README-DN9HKtp_.js +0 -124
- package/storybook-static/assets/README-DNricOkt.js +0 -136
- package/storybook-static/assets/README-DoCA4JXf.js +0 -273
- package/storybook-static/assets/README-tm9QH9cF.js +0 -103
- package/storybook-static/assets/iframe-DzQq_POR.js +0 -1
- /package/storybook-static/assets/{ui.module-Cat84Nza.js → ui.module-BDnTp43_.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe--RU38UHO.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-DcVVTXzf.js";function o(e){let t={a:`a`,code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation Lib/API/Formatters/Strings`}),`
|
|
2
2
|
`,(0,c.jsx)(t.h1,{id:`строковые-форматтеры`,children:`Строковые форматтеры`}),`
|
|
3
3
|
`,(0,c.jsx)(t.p,{children:`Модуль содержит небольшие предсказуемые функции для подготовки пользовательского текста: обрезки пробелов, безопасного преобразования в строку, удаления ведущих нулей, сокращения длинного текста и выбора русской формы слова.`}),`
|
|
4
4
|
`,(0,c.jsx)(t.p,{children:`Все функции экспортируются через один публичный entrypoint:`}),`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe--RU38UHO.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-DcVVTXzf.js";function o(e){let t={a:`a`,blockquote:`blockquote`,code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation Lib/API/Utils`}),`
|
|
2
2
|
`,(0,c.jsxs)(t.h1,{id:`общие-утилиты-ryuzaki13react-foundation-libutils`,children:[`Общие утилиты `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/utils`})]}),`
|
|
3
3
|
`,(0,c.jsxs)(t.p,{children:[`Модуль `,(0,c.jsx)(t.code,{children:`utils`}),` объединяет небольшие технические функции, которые нужны в разных частях React- и TypeScript-приложения:`]}),`
|
|
4
4
|
`,(0,c.jsxs)(t.ul,{children:[`
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe--RU38UHO.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-DcVVTXzf.js";function o(e){let t={code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,li:`li`,p:`p`,pre:`pre`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation API/Orchestration/Async Tasks`}),`
|
|
2
|
+
`,(0,c.jsxs)(t.h1,{id:`асинхронные-задачи-через-ryuzaki13react-foundation-apiasync`,children:[`Асинхронные задачи через `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-api/async`})]}),`
|
|
3
|
+
`,(0,c.jsx)(t.p,{children:`Модуль запускает независимые Promise-задачи, сохраняет связь результата с исходным элементом и формирует удобную сводку для UI/логов.`}),`
|
|
4
|
+
`,(0,c.jsx)(t.h2,{id:`какой-runner-выбрать`,children:`Какой runner выбрать`}),`
|
|
5
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Сценарий`}),(0,c.jsx)(t.th,{children:`Функция`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Задач немного, можно начать все одновременно, любая ошибка должна завершить batch исключением`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`runAsyncTasks`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Нужно ограничить число одновременных запросов, показать progress или поддержать abort`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`runConcurrentTasks`})})]})]})]}),`
|
|
6
|
+
`,(0,c.jsx)(t.p,{children:`Обе функции выполняют задачи параллельно. Они не создают web workers и не ускоряют CPU-bound JavaScript: Promise-concurrency полезна прежде всего для I/O — HTTP, чтения storage и других async операций.`}),`
|
|
7
|
+
`,(0,c.jsx)(t.h3,{id:`ментальная-модель-concurrency`,children:`Ментальная модель concurrency`}),`
|
|
8
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`Параллельно в Promise-смысле:
|
|
9
|
+
request A ───────────────►
|
|
10
|
+
request B ─────────►
|
|
11
|
+
request C ─────────────────────►
|
|
12
|
+
|
|
13
|
+
JavaScript thread при этом остаётся один.
|
|
14
|
+
`})}),`
|
|
15
|
+
`,(0,c.jsx)(t.p,{children:`Пока request ждёт сеть, event loop может продолжить другую задачу. Но три тяжёлых синхронных вычисления всё равно блокируют один thread по очереди.`}),`
|
|
16
|
+
`,(0,c.jsx)(t.h2,{id:`импорт`,children:`Импорт`}),`
|
|
17
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
|
|
18
|
+
AsyncTasksError,
|
|
19
|
+
ConcurrencyPartialError,
|
|
20
|
+
runAsyncTasks,
|
|
21
|
+
runConcurrentTasks
|
|
22
|
+
} from "@ryuzaki13/react-foundation-api/async";
|
|
23
|
+
|
|
24
|
+
import type {
|
|
25
|
+
AsyncTask,
|
|
26
|
+
RunAsyncTasksResult,
|
|
27
|
+
RunConcurrentTasksOptions,
|
|
28
|
+
RunConcurrentTasksResult
|
|
29
|
+
} from "@ryuzaki13/react-foundation-api/async";
|
|
30
|
+
`})}),`
|
|
31
|
+
`,(0,c.jsx)(t.p,{children:`Модуль не требует React или TanStack Query.`}),`
|
|
32
|
+
`,(0,c.jsxs)(t.h2,{id:`база-async-promise-и-await`,children:[`База: `,(0,c.jsx)(t.code,{children:`async`}),`, `,(0,c.jsx)(t.code,{children:`Promise`}),` и `,(0,c.jsx)(t.code,{children:`await`})]}),`
|
|
33
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`async`}),`-функция всегда возвращает `,(0,c.jsx)(t.code,{children:`Promise`}),`. `,(0,c.jsx)(t.code,{children:`await`}),` приостанавливает только текущую async-функцию, а не весь browser thread:`]}),`
|
|
34
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`async function loadName() {
|
|
35
|
+
const response = await fetch("/api/me");
|
|
36
|
+
return response.text();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const namePromise = loadName(); // Promise<string>.
|
|
40
|
+
const name = await namePromise; // string.
|
|
41
|
+
`})}),`
|
|
42
|
+
`,(0,c.jsxs)(t.p,{children:[`Ошибку Promise обрабатывают через `,(0,c.jsx)(t.code,{children:`try/catch`}),` вокруг `,(0,c.jsx)(t.code,{children:`await`}),`.`]}),`
|
|
43
|
+
`,(0,c.jsx)(t.h2,{id:`runasynctasks`,children:(0,c.jsx)(t.code,{children:`runAsyncTasks`})}),`
|
|
44
|
+
`,(0,c.jsx)(t.h3,{id:`быстрый-старт`,children:`Быстрый старт`}),`
|
|
45
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = await runAsyncTasks([
|
|
46
|
+
{ name: "profile", run: () => fetchProfile() },
|
|
47
|
+
{ name: "settings", run: () => fetchSettings() }
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
console.log(result.summary);
|
|
51
|
+
// { total: 2, succeeded: 2, failed: 0 }
|
|
52
|
+
`})}),`
|
|
53
|
+
`,(0,c.jsxs)(t.p,{children:[`Все `,(0,c.jsx)(t.code,{children:`run`}),` запускаются сразу через `,(0,c.jsx)(t.code,{children:`Promise.all`}),`. Важное отличие от обычного `,(0,c.jsx)(t.code,{children:`Promise.all`}),`: ошибка одной задачи перехватывается внутри runner-а, поэтому остальные задачи успевают завершиться. После завершения всего batch функция либо возвращает полный результат, либо бросает `,(0,c.jsx)(t.code,{children:`AsyncTasksError`}),` с тем же полным результатом.`]}),`
|
|
54
|
+
`,(0,c.jsx)(t.h3,{id:`обработка-частичного-успеха`,children:`Обработка частичного успеха`}),`
|
|
55
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`try {
|
|
56
|
+
const result = await runAsyncTasks(tasks, {
|
|
57
|
+
errorMessage: "Не все стартовые данные загрузились"
|
|
58
|
+
});
|
|
59
|
+
useData(result.successes);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (error instanceof AsyncTasksError) {
|
|
62
|
+
usePartialData(error.result.successes);
|
|
63
|
+
showErrors(error.result.errors);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
`})}),`
|
|
70
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`AsyncTasksError.result`}),` содержит:`]}),`
|
|
71
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type RunAsyncTasksResult<TResult> = {
|
|
72
|
+
settled: readonly AsyncTaskSettled<TResult>[];
|
|
73
|
+
successes: readonly AsyncTaskSuccess<TResult>[];
|
|
74
|
+
errors: readonly AsyncTaskFailure[];
|
|
75
|
+
summary: {
|
|
76
|
+
total: number;
|
|
77
|
+
succeeded: number;
|
|
78
|
+
failed: number;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
`})}),`
|
|
82
|
+
`,(0,c.jsxs)(t.p,{children:[`Элементы `,(0,c.jsx)(t.code,{children:`settled`}),`, `,(0,c.jsx)(t.code,{children:`successes`}),` и `,(0,c.jsx)(t.code,{children:`errors`}),` сохраняют порядок исходного массива. Каждый элемент содержит `,(0,c.jsx)(t.code,{children:`index`}),` и `,(0,c.jsx)(t.code,{children:`name`}),`.`]}),`
|
|
83
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`if (item.status === "fulfilled") {
|
|
84
|
+
console.log(item.data);
|
|
85
|
+
} else {
|
|
86
|
+
console.error(item.error);
|
|
87
|
+
}
|
|
88
|
+
`})}),`
|
|
89
|
+
`,(0,c.jsxs)(t.p,{children:[`TypeScript сужает union по `,(0,c.jsx)(t.code,{children:`status`}),`.`]}),`
|
|
90
|
+
`,(0,c.jsxs)(t.p,{children:[`Пустой список возвращает успешный пустой результат. `,(0,c.jsx)(t.code,{children:`runAsyncTasks`}),` не имеет встроенного concurrency limit и AbortSignal.`]}),`
|
|
91
|
+
`,(0,c.jsx)(t.h3,{id:`полные-типы-taskresult`,children:`Полные типы task/result`}),`
|
|
92
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type AsyncTask<TResult = unknown> = {
|
|
93
|
+
readonly name: string;
|
|
94
|
+
readonly run: () => Promise<TResult>;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
type AsyncTaskSuccess<TResult> = {
|
|
98
|
+
readonly status: "fulfilled";
|
|
99
|
+
readonly index: number;
|
|
100
|
+
readonly name: string;
|
|
101
|
+
readonly data: TResult;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
type AsyncTaskFailure = {
|
|
105
|
+
readonly status: "rejected";
|
|
106
|
+
readonly index: number;
|
|
107
|
+
readonly name: string;
|
|
108
|
+
readonly error: unknown;
|
|
109
|
+
};
|
|
110
|
+
`})}),`
|
|
111
|
+
`,(0,c.jsxs)(t.p,{children:[`Имена не обязаны быть уникальными. Для надёжной identity используйте `,(0,c.jsx)(t.code,{children:`index`}),`, если caller допускает повторяющиеся names.`]}),`
|
|
112
|
+
`,(0,c.jsxs)(t.h3,{id:`синхронный-throw-внутри-run`,children:[`Синхронный throw внутри `,(0,c.jsx)(t.code,{children:`run`})]}),`
|
|
113
|
+
`,(0,c.jsx)(t.p,{children:`Хотя тип обещает Promise, runtime callback может бросить сразу:`}),`
|
|
114
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`{
|
|
115
|
+
name: "invalid",
|
|
116
|
+
run: () => {
|
|
117
|
+
throw new Error("Ошибка до Promise");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
`})}),`
|
|
121
|
+
`,(0,c.jsxs)(t.p,{children:[`Runner ловит такой throw так же, как rejected Promise, и помещает его в `,(0,c.jsx)(t.code,{children:`AsyncTasksError.result.errors`}),`.`]}),`
|
|
122
|
+
`,(0,c.jsx)(t.h3,{id:`все-задачи-действительно-стартуют-сразу`,children:`Все задачи действительно стартуют сразу`}),`
|
|
123
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`await runAsyncTasks(tenThousandRequests);
|
|
124
|
+
`})}),`
|
|
125
|
+
`,(0,c.jsxs)(t.p,{children:[`создаст попытку запуска всех 10 000 operations. Это может перегрузить browser, backend или connection pool. Для большого массива используйте `,(0,c.jsx)(t.code,{children:`runConcurrentTasks`}),`.`]}),`
|
|
126
|
+
`,(0,c.jsx)(t.h3,{id:`homogeneous-result-type`,children:`Homogeneous result type`}),`
|
|
127
|
+
`,(0,c.jsxs)(t.p,{children:[`Один вызов использует общий `,(0,c.jsx)(t.code,{children:`TResult`}),`. Если задачи возвращают принципиально разные shapes, создайте union/discriminated result либо выполняйте независимые batches:`]}),`
|
|
128
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type StartupResult =
|
|
129
|
+
| { kind: "profile"; value: Profile }
|
|
130
|
+
| { kind: "settings"; value: Settings };
|
|
131
|
+
`})}),`
|
|
132
|
+
`,(0,c.jsx)(t.h3,{id:`default-error-message`,children:`Default error message`}),`
|
|
133
|
+
`,(0,c.jsxs)(t.p,{children:[`Если `,(0,c.jsx)(t.code,{children:`options.errorMessage`}),` отсутствует:`]}),`
|
|
134
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`Не удалось выполнить все асинхронные задачи.
|
|
135
|
+
`})}),`
|
|
136
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`AsyncTasksError.name`}),` равен `,(0,c.jsx)(t.code,{children:`"AsyncTasksError"`}),`, а `,(0,c.jsx)(t.code,{children:`result`}),` содержит полный batch snapshot.`]}),`
|
|
137
|
+
`,(0,c.jsx)(t.h2,{id:`runconcurrenttasks`,children:(0,c.jsx)(t.code,{children:`runConcurrentTasks`})}),`
|
|
138
|
+
`,(0,c.jsx)(t.h3,{id:`ограничение-одновременных-запросов`,children:`Ограничение одновременных запросов`}),`
|
|
139
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = await runConcurrentTasks(
|
|
140
|
+
userIds,
|
|
141
|
+
async (userId, { signal }) => {
|
|
142
|
+
const response = await fetch(\`/api/users/\${userId}\`, { signal });
|
|
143
|
+
if (!response.ok) throw new Error(\`HTTP \${response.status}\`);
|
|
144
|
+
return response.json();
|
|
145
|
+
},
|
|
146
|
+
{ concurrency: 4 }
|
|
147
|
+
);
|
|
148
|
+
`})}),`
|
|
149
|
+
`,(0,c.jsxs)(t.p,{children:[`Не более четырёх задач будут находиться в работе одновременно. Значение по умолчанию — `,(0,c.jsx)(t.code,{children:`4`}),`. Если элементов меньше, workers создаются только по числу элементов.`]}),`
|
|
150
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`concurrency`}),` обязан быть целым числом не меньше `,(0,c.jsx)(t.code,{children:`1`}),`:`]}),`
|
|
151
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Значение`}),(0,c.jsx)(t.th,{children:`Результат`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`4`})}),(0,c.jsx)(t.td,{children:`Работает`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`1`})}),(0,c.jsx)(t.td,{children:`Последовательное выполнение`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`0`}),`, `,(0,c.jsx)(t.code,{children:`-1`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`RangeError`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`1.5`}),`, `,(0,c.jsx)(t.code,{children:`NaN`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`TypeError`})})]})]})]}),`
|
|
152
|
+
`,(0,c.jsx)(t.h3,{id:`ошибки-отдельных-элементов`,children:`Ошибки отдельных элементов`}),`
|
|
153
|
+
`,(0,c.jsxs)(t.p,{children:[`Runner не бросает ошибки отдельных задач. Он помещает их в `,(0,c.jsx)(t.code,{children:`result.errors`}),` и продолжает обработку:`]}),`
|
|
154
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = await runConcurrentTasks(inputs, task);
|
|
155
|
+
|
|
156
|
+
if (result.errors.length > 0) {
|
|
157
|
+
for (const failure of result.errors) {
|
|
158
|
+
console.error(failure.index, failure.input, failure.error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
`})}),`
|
|
162
|
+
`,(0,c.jsxs)(t.p,{children:[`Исключение самой функции возможно при невалидном `,(0,c.jsx)(t.code,{children:`concurrency`}),` или если callback `,(0,c.jsx)(t.code,{children:`onProgress`}),`/`,(0,c.jsx)(t.code,{children:`onItemSuccess`}),`/`,(0,c.jsx)(t.code,{children:`onItemError`}),` сам бросил ошибку. Callbacks должны быть безопасными и быстрыми.`]}),`
|
|
163
|
+
`,(0,c.jsx)(t.h3,{id:`progress`,children:`Progress`}),`
|
|
164
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`await runConcurrentTasks(files, uploadFile, {
|
|
165
|
+
concurrency: 3,
|
|
166
|
+
onProgress(progress) {
|
|
167
|
+
setProgress(progress.percentage);
|
|
168
|
+
},
|
|
169
|
+
onItemSuccess(item) {
|
|
170
|
+
console.log("Загружен", item.input.name);
|
|
171
|
+
},
|
|
172
|
+
onItemError(item) {
|
|
173
|
+
console.error("Ошибка", item.input.name, item.error);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
`})}),`
|
|
177
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`onProgress`}),` вызывается после каждой завершённой задачи. В первом вызове процент уже больше нуля; отдельного начального события `,(0,c.jsx)(t.code,{children:`0%`}),` нет.`]}),`
|
|
178
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type ConcurrentTaskProgress<TInput, TResult> = {
|
|
179
|
+
total: number;
|
|
180
|
+
completed: number;
|
|
181
|
+
succeeded: number;
|
|
182
|
+
failed: number;
|
|
183
|
+
running: number;
|
|
184
|
+
pending: number;
|
|
185
|
+
percentage: number;
|
|
186
|
+
aborted: boolean;
|
|
187
|
+
lastSettled?: ConcurrentTaskSettled<TInput, TResult>;
|
|
188
|
+
};
|
|
189
|
+
`})}),`
|
|
190
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`percentage`}),` округляется через `,(0,c.jsx)(t.code,{children:`Math.round`}),`.`]}),`
|
|
191
|
+
`,(0,c.jsx)(t.h3,{id:`точная-последовательность-callbacks`,children:`Точная последовательность callbacks`}),`
|
|
192
|
+
`,(0,c.jsx)(t.p,{children:`Для успешной task:`}),`
|
|
193
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`task resolved
|
|
194
|
+
→ сохранить fulfilled item
|
|
195
|
+
→ увеличить succeeded
|
|
196
|
+
→ onItemSuccess(item)
|
|
197
|
+
→ уменьшить running
|
|
198
|
+
→ увеличить completed
|
|
199
|
+
→ onProgress(progress)
|
|
200
|
+
`})}),`
|
|
201
|
+
`,(0,c.jsxs)(t.p,{children:[`Для rejected task аналогично вызывается `,(0,c.jsx)(t.code,{children:`onItemError`}),`, затем `,(0,c.jsx)(t.code,{children:`onProgress`}),`.`]}),`
|
|
202
|
+
`,(0,c.jsxs)(t.p,{children:[`Callbacks синхронные: runner не `,(0,c.jsx)(t.code,{children:`await`}),`-ит Promise, который callback мог случайно вернуть. Делайте их быстрыми state/logging callbacks.`]}),`
|
|
203
|
+
`,(0,c.jsxs)(t.p,{children:[`Критически важно не бросать из callbacks. Если `,(0,c.jsx)(t.code,{children:`onItemSuccess`}),` бросит, worker попадёт в `,(0,c.jsx)(t.code,{children:`catch`}),`, перезапишет item как rejected и вызовет `,(0,c.jsx)(t.code,{children:`onItemError`}),`. Если затем бросит `,(0,c.jsx)(t.code,{children:`onItemError`}),` или `,(0,c.jsx)(t.code,{children:`onProgress`}),`, весь runner может reject. Кроме того, промежуточные progress counters могут стать нелогичными. Оборачивайте необязательную telemetry:`]}),`
|
|
204
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`onItemSuccess(item) {
|
|
205
|
+
try {
|
|
206
|
+
analytics.track("uploaded", { index: item.index });
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.warn("Telemetry недоступна", error);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
`})}),`
|
|
212
|
+
`,(0,c.jsx)(t.h3,{id:`abort`,children:`Abort`}),`
|
|
213
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const controller = new AbortController();
|
|
214
|
+
|
|
215
|
+
const promise = runConcurrentTasks(urls, async (url, { signal }) => {
|
|
216
|
+
const response = await fetch(url, { signal });
|
|
217
|
+
return response.text();
|
|
218
|
+
}, {
|
|
219
|
+
concurrency: 2,
|
|
220
|
+
signal: controller.signal
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
controller.abort();
|
|
224
|
+
const result = await promise;
|
|
225
|
+
`})}),`
|
|
226
|
+
`,(0,c.jsxs)(t.p,{children:[`После abort новые задачи не стартуют. Уже начатая операция прервётся только если сама использует переданный `,(0,c.jsx)(t.code,{children:`signal`}),`. Runner ждёт завершения начатых tasks и возвращает:`]}),`
|
|
227
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
228
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`aborted: true`}),`;`]}),`
|
|
229
|
+
`,(0,c.jsxs)(t.li,{children:[`обработанные элементы в `,(0,c.jsx)(t.code,{children:`settled`}),`;`]}),`
|
|
230
|
+
`,(0,c.jsxs)(t.li,{children:[`не начатые элементы в `,(0,c.jsx)(t.code,{children:`unprocessed`}),`.`]}),`
|
|
231
|
+
`]}),`
|
|
232
|
+
`,(0,c.jsxs)(t.p,{children:[`Abort не является ошибкой runner-а и сам по себе не приводит к `,(0,c.jsx)(t.code,{children:`throw`}),`.`]}),`
|
|
233
|
+
`,(0,c.jsx)(t.h3,{id:`signal-уже-aborted-до-запуска`,children:`Signal уже aborted до запуска`}),`
|
|
234
|
+
`,(0,c.jsx)(t.p,{children:`Для непустого input ни одна task не стартует:`}),`
|
|
235
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const controller = new AbortController();
|
|
236
|
+
controller.abort();
|
|
237
|
+
|
|
238
|
+
const result = await runConcurrentTasks([1, 2, 3], task, {
|
|
239
|
+
signal: controller.signal
|
|
240
|
+
});
|
|
241
|
+
`})}),`
|
|
242
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`result.aborted; // true
|
|
243
|
+
result.settled; // []
|
|
244
|
+
result.unprocessed; // все три input с индексами
|
|
245
|
+
`})}),`
|
|
246
|
+
`,(0,c.jsxs)(t.p,{children:[`Initial progress event `,(0,c.jsx)(t.code,{children:`0%`}),` не генерируется.`]}),`
|
|
247
|
+
`,(0,c.jsx)(t.h3,{id:`abort-уже-начатых-tasks`,children:`Abort уже начатых tasks`}),`
|
|
248
|
+
`,(0,c.jsx)(t.p,{children:`Runner только прекращает выдавать новые inputs workers. Реальная отмена зависит от task:`}),`
|
|
249
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Signal используется — fetch может прерваться.
|
|
250
|
+
async (url, { signal }) => fetch(url, { signal })
|
|
251
|
+
`})}),`
|
|
252
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Signal игнорируется — task завершится несмотря на abort batch-а.
|
|
253
|
+
async (url) => fetch(url)
|
|
254
|
+
`})}),`
|
|
255
|
+
`,(0,c.jsxs)(t.p,{children:[`Если task с signal отклоняется AbortError, она попадёт в `,(0,c.jsx)(t.code,{children:`errors`}),`, а ещё не стартовавшие inputs — в `,(0,c.jsx)(t.code,{children:`unprocessed`}),`.`]}),`
|
|
256
|
+
`,(0,c.jsx)(t.h3,{id:`порядок-результата`,children:`Порядок результата`}),`
|
|
257
|
+
`,(0,c.jsxs)(t.p,{children:[`Tasks могут завершаться в любом порядке, callbacks идут в порядке фактического завершения. Итоговые `,(0,c.jsx)(t.code,{children:`settled`}),`, `,(0,c.jsx)(t.code,{children:`successes`}),`, `,(0,c.jsx)(t.code,{children:`errors`}),` и `,(0,c.jsx)(t.code,{children:`unprocessed`}),` собираются по исходным индексам, поэтому результат детерминирован относительно input.`]}),`
|
|
258
|
+
`,(0,c.jsx)(t.h3,{id:`полный-result`,children:`Полный result`}),`
|
|
259
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type RunConcurrentTasksResult<TInput, TResult> = {
|
|
260
|
+
settled: ConcurrentTaskSettled<TInput, TResult>[];
|
|
261
|
+
successes: ConcurrentTaskSuccess<TInput, TResult>[];
|
|
262
|
+
errors: ConcurrentTaskError<TInput>[];
|
|
263
|
+
unprocessed: ConcurrentTaskUnprocessed<TInput>[];
|
|
264
|
+
aborted: boolean;
|
|
265
|
+
summary: {
|
|
266
|
+
total: number;
|
|
267
|
+
completed: number;
|
|
268
|
+
succeeded: number;
|
|
269
|
+
failed: number;
|
|
270
|
+
unprocessed: number;
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
`})}),`
|
|
274
|
+
`,(0,c.jsx)(t.p,{children:`Invariant после нормального завершения:`}),`
|
|
275
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`summary.total = summary.completed + summary.unprocessed
|
|
276
|
+
summary.completed = summary.succeeded + summary.failed
|
|
277
|
+
`})}),`
|
|
278
|
+
`,(0,c.jsx)(t.h3,{id:`пустой-input`,children:`Пустой input`}),`
|
|
279
|
+
`,(0,c.jsxs)(t.p,{children:[`Возвращается empty result. Если signal уже aborted, `,(0,c.jsx)(t.code,{children:`aborted`}),` будет `,(0,c.jsx)(t.code,{children:`true`}),`; иначе `,(0,c.jsx)(t.code,{children:`false`}),`. `,(0,c.jsx)(t.code,{children:`percentage`}),` отсутствует в final summary, а progress callback не вызывается.`]}),`
|
|
280
|
+
`,(0,c.jsx)(t.h2,{id:`практический-пример-upload-batch`,children:`Практический пример: upload batch`}),`
|
|
281
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type UploadInput = {
|
|
282
|
+
id: string;
|
|
283
|
+
file: File;
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const result = await runConcurrentTasks(
|
|
287
|
+
files,
|
|
288
|
+
async ({ id, file }, { signal }) => {
|
|
289
|
+
const body = new FormData();
|
|
290
|
+
body.set("file", file);
|
|
291
|
+
|
|
292
|
+
const response = await fetch(\`/api/files/\${encodeURIComponent(id)}\`, {
|
|
293
|
+
method: "PUT",
|
|
294
|
+
body,
|
|
295
|
+
signal
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
if (!response.ok) {
|
|
299
|
+
throw new Error(\`HTTP \${response.status}\`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return { id, uploaded: true };
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
concurrency: 3,
|
|
306
|
+
signal: controller.signal,
|
|
307
|
+
onProgress: ({ completed, total, percentage }) => {
|
|
308
|
+
console.log(\`\${completed}/\${total}: \${percentage}%\`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
);
|
|
312
|
+
`})}),`
|
|
313
|
+
`,(0,c.jsx)(t.h3,{id:`retry-только-failures`,children:`Retry только failures`}),`
|
|
314
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const retryInputs = result.errors.map((item) => item.input);
|
|
315
|
+
|
|
316
|
+
const retryResult = await runConcurrentTasks(retryInputs, uploadTask, {
|
|
317
|
+
concurrency: 2
|
|
318
|
+
});
|
|
319
|
+
`})}),`
|
|
320
|
+
`,(0,c.jsx)(t.p,{children:`У write operations retry безопасен только при idempotent server contract. Потерянный response не доказывает, что первая запись не произошла.`}),`
|
|
321
|
+
`,(0,c.jsx)(t.h3,{id:`продолжить-unprocessed-после-abort`,children:`Продолжить unprocessed после abort`}),`
|
|
322
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const remainingInputs = result.unprocessed.map((item) => item.input);
|
|
323
|
+
`})}),`
|
|
324
|
+
`,(0,c.jsxs)(t.p,{children:[`Не добавляйте автоматически `,(0,c.jsx)(t.code,{children:`errors`}),` к `,(0,c.jsx)(t.code,{children:`unprocessed`}),`: rejected task уже запускалась и могла частично изменить backend.`]}),`
|
|
325
|
+
`,(0,c.jsx)(t.h2,{id:`concurrencypartialerror`,children:(0,c.jsx)(t.code,{children:`ConcurrencyPartialError`})}),`
|
|
326
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`runConcurrentTasks`}),` сам не создаёт этот error. Класс нужен, если слой приложения хочет преобразовать частичный результат в исключение:`]}),`
|
|
327
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = await runConcurrentTasks(inputs, task);
|
|
328
|
+
|
|
329
|
+
if (result.errors.length > 0 || result.aborted) {
|
|
330
|
+
throw new ConcurrencyPartialError("Batch выполнен частично", result);
|
|
331
|
+
}
|
|
332
|
+
`})}),`
|
|
333
|
+
`,(0,c.jsxs)(t.p,{children:[`Не путайте его с `,(0,c.jsx)(t.code,{children:`AsyncTasksError`}),`: первый создаёт consumer по своей policy, второй автоматически бросает `,(0,c.jsx)(t.code,{children:`runAsyncTasks`}),`.`]}),`
|
|
334
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`ConcurrencyPartialError.name`}),` равен `,(0,c.jsx)(t.code,{children:`"ConcurrencyPartialError"`}),`, field `,(0,c.jsx)(t.code,{children:`result`}),` сохраняет переданный snapshot без преобразований.`]}),`
|
|
335
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`try {
|
|
336
|
+
const result = await runConcurrentTasks(inputs, task);
|
|
337
|
+
|
|
338
|
+
if (result.errors.length || result.aborted) {
|
|
339
|
+
throw new ConcurrencyPartialError(
|
|
340
|
+
"Не все файлы обработаны",
|
|
341
|
+
result
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
} catch (error) {
|
|
345
|
+
if (error instanceof ConcurrencyPartialError) {
|
|
346
|
+
showPartialResult(error.result);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
`})}),`
|
|
353
|
+
`,(0,c.jsxs)(t.h2,{id:`выбор-concurrency`,children:[`Выбор `,(0,c.jsx)(t.code,{children:`concurrency`})]}),`
|
|
354
|
+
`,(0,c.jsx)(t.p,{children:`Нет универсального максимума:`}),`
|
|
355
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Тип работы`}),(0,c.jsx)(t.th,{children:`Стартовая оценка`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Тяжёлые SAP write requests`}),(0,c.jsx)(t.td,{children:`2–4`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Небольшие independent reads`}),(0,c.jsx)(t.td,{children:`4–8`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Local async storage`}),(0,c.jsx)(t.td,{children:`зависит от adapter-а`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`CPU-bound parsing`}),(0,c.jsx)(t.td,{children:`runner не решает задачу`})]})]})]}),`
|
|
356
|
+
`,(0,c.jsx)(t.p,{children:`Начните с малого значения, измерьте latency/error rate и согласуйте лимит с backend.`}),`
|
|
357
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`concurrency: 1`}),` полезен для последовательной обработки независимых элементов с единым result contract. Но если шаг B зависит от output A, обычный последовательный workflow будет понятнее.`]}),`
|
|
358
|
+
`,(0,c.jsx)(t.h2,{id:`тестирование`,children:`Тестирование`}),`
|
|
359
|
+
`,(0,c.jsx)(t.h3,{id:`runasynctasks-1`,children:(0,c.jsx)(t.code,{children:`runAsyncTasks`})}),`
|
|
360
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`it("сохраняет partial result в AsyncTasksError", async () => {
|
|
361
|
+
const promise = runAsyncTasks([
|
|
362
|
+
{ name: "ok", run: async () => 1 },
|
|
363
|
+
{ name: "failed", run: async () => { throw new Error("boom"); } }
|
|
364
|
+
]);
|
|
365
|
+
|
|
366
|
+
await expect(promise).rejects.toMatchObject({
|
|
367
|
+
name: "AsyncTasksError",
|
|
368
|
+
result: {
|
|
369
|
+
summary: { total: 2, succeeded: 1, failed: 1 }
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
`})}),`
|
|
374
|
+
`,(0,c.jsx)(t.h3,{id:`проверка-лимита-concurrency`,children:`Проверка лимита concurrency`}),`
|
|
375
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`it("не запускает больше двух tasks одновременно", async () => {
|
|
376
|
+
let running = 0;
|
|
377
|
+
let maximum = 0;
|
|
378
|
+
|
|
379
|
+
await runConcurrentTasks(
|
|
380
|
+
[1, 2, 3, 4],
|
|
381
|
+
async () => {
|
|
382
|
+
running += 1;
|
|
383
|
+
maximum = Math.max(maximum, running);
|
|
384
|
+
await Promise.resolve();
|
|
385
|
+
running -= 1;
|
|
386
|
+
return true;
|
|
387
|
+
},
|
|
388
|
+
{ concurrency: 2 }
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
expect(maximum).toBe(2);
|
|
392
|
+
});
|
|
393
|
+
`})}),`
|
|
394
|
+
`,(0,c.jsx)(t.p,{children:`Покройте:`}),`
|
|
395
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
396
|
+
`,(0,c.jsx)(t.li,{children:`empty input;`}),`
|
|
397
|
+
`,(0,c.jsxs)(t.li,{children:[`validation `,(0,c.jsx)(t.code,{children:`concurrency`}),`;`]}),`
|
|
398
|
+
`,(0,c.jsx)(t.li,{children:`sync throw и rejected Promise;`}),`
|
|
399
|
+
`,(0,c.jsx)(t.li,{children:`input order result-а;`}),`
|
|
400
|
+
`,(0,c.jsx)(t.li,{children:`completion order callbacks;`}),`
|
|
401
|
+
`,(0,c.jsx)(t.li,{children:`abort до старта;`}),`
|
|
402
|
+
`,(0,c.jsx)(t.li,{children:`abort во время работы;`}),`
|
|
403
|
+
`,(0,c.jsx)(t.li,{children:`task, игнорирующую signal;`}),`
|
|
404
|
+
`,(0,c.jsx)(t.li,{children:`unprocessed indices;`}),`
|
|
405
|
+
`,(0,c.jsx)(t.li,{children:`custom partial-error policy.`}),`
|
|
406
|
+
`]}),`
|
|
407
|
+
`,(0,c.jsx)(t.h2,{id:`частые-ошибки`,children:`Частые ошибки`}),`
|
|
408
|
+
`,(0,c.jsxs)(t.h3,{id:`использовать-runasynctasks-для-тысяч-requests`,children:[`Использовать `,(0,c.jsx)(t.code,{children:`runAsyncTasks`}),` для тысяч requests`]}),`
|
|
409
|
+
`,(0,c.jsx)(t.p,{children:`Он стартует всё сразу. Нужен bounded runner.`}),`
|
|
410
|
+
`,(0,c.jsx)(t.h3,{id:`считать-abort-мгновенной-отменой`,children:`Считать abort мгновенной отменой`}),`
|
|
411
|
+
`,(0,c.jsx)(t.p,{children:`Task обязана использовать signal.`}),`
|
|
412
|
+
`,(0,c.jsx)(t.h3,{id:`бросать-из-progress-callback`,children:`Бросать из progress callback`}),`
|
|
413
|
+
`,(0,c.jsx)(t.p,{children:`Callbacks являются частью worker execution и могут сломать batch.`}),`
|
|
414
|
+
`,(0,c.jsx)(t.h3,{id:`считать-individual-errors-исключением-bounded-runner-а`,children:`Считать individual errors исключением bounded runner-а`}),`
|
|
415
|
+
`,(0,c.jsxs)(t.p,{children:[`Читайте `,(0,c.jsx)(t.code,{children:`result.errors`}),`. Сам runner их не бросает.`]}),`
|
|
416
|
+
`,(0,c.jsx)(t.h3,{id:`мутировать-input`,children:`Мутировать input`}),`
|
|
417
|
+
`,(0,c.jsx)(t.p,{children:`Result сохраняет ссылку на исходный input. Mutation может неожиданно изменить UI/result history.`}),`
|
|
418
|
+
`,(0,c.jsx)(t.h3,{id:`использовать-batch-как-query-cache`,children:`Использовать batch как Query cache`}),`
|
|
419
|
+
`,(0,c.jsx)(t.p,{children:`Runner orchestrates promises, но не заменяет query identity, stale policy и cache ownership.`}),`
|
|
420
|
+
`,(0,c.jsx)(t.h2,{id:`практические-рекомендации`,children:`Практические рекомендации`}),`
|
|
421
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
422
|
+
`,(0,c.jsx)(t.li,{children:`Не ставьте слишком большой concurrency: browser, proxy и backend имеют свои лимиты.`}),`
|
|
423
|
+
`,(0,c.jsx)(t.li,{children:`Для write-операций продумайте идемпотентность: retry может повторить уже выполненное действие.`}),`
|
|
424
|
+
`,(0,c.jsx)(t.li,{children:`Не меняйте input objects внутри task, если те же значения использует UI.`}),`
|
|
425
|
+
`,(0,c.jsxs)(t.li,{children:[`Обрабатывайте `,(0,c.jsx)(t.code,{children:`unknown`}),` error через безопасный normalizer.`]}),`
|
|
426
|
+
`,(0,c.jsx)(t.li,{children:`Не используйте runner вместо TanStack Query cache для одного и того же resource.`}),`
|
|
427
|
+
`,(0,c.jsx)(t.li,{children:`Если задача зависит от результата предыдущей, это не независимый batch: выполните зависимые шаги последовательно.`}),`
|
|
428
|
+
`]}),`
|
|
429
|
+
`,(0,c.jsx)(t.h2,{id:`faq`,children:`FAQ`}),`
|
|
430
|
+
`,(0,c.jsx)(t.h3,{id:`сохраняется-ли-порядок`,children:`Сохраняется ли порядок?`}),`
|
|
431
|
+
`,(0,c.jsx)(t.p,{children:`В final arrays — да, по input index. В callbacks — нет, они идут по завершению.`}),`
|
|
432
|
+
`,(0,c.jsx)(t.h3,{id:`останавливается-ли-batch-на-первой-task-error`,children:`Останавливается ли batch на первой task error?`}),`
|
|
433
|
+
`,(0,c.jsxs)(t.p,{children:[`Нет. Оба runner-а дают уже запущенным tasks завершиться. `,(0,c.jsx)(t.code,{children:`runAsyncTasks`}),` бросает aggregated error после всего batch, bounded runner возвращает errors.`]}),`
|
|
434
|
+
`,(0,c.jsx)(t.h3,{id:`можно-ли-менять-concurrency-во-время-запуска`,children:`Можно ли менять concurrency во время запуска?`}),`
|
|
435
|
+
`,(0,c.jsx)(t.p,{children:`Нет. Значение фиксируется при старте.`}),`
|
|
436
|
+
`,(0,c.jsx)(t.h3,{id:`есть-ли-automatic-retry`,children:`Есть ли automatic retry?`}),`
|
|
437
|
+
`,(0,c.jsx)(t.p,{children:`Нет. Он должен быть явным и безопасным для operation.`}),`
|
|
438
|
+
`,(0,c.jsxs)(t.h3,{id:`почему-error-имеет-type-unknown`,children:[`Почему `,(0,c.jsx)(t.code,{children:`error`}),` имеет type `,(0,c.jsx)(t.code,{children:`unknown`}),`?`]}),`
|
|
439
|
+
`,(0,c.jsx)(t.p,{children:`Promise может reject любым JS value. Сужайте/нормализуйте его перед UI/logging.`}),`
|
|
440
|
+
`,(0,c.jsx)(t.h2,{id:`полный-api`,children:`Полный API`}),`
|
|
441
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Группа`}),(0,c.jsx)(t.th,{children:`Exports`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`All-at-once`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`runAsyncTasks`}),`, `,(0,c.jsx)(t.code,{children:`AsyncTasksError`}),`, `,(0,c.jsx)(t.code,{children:`AsyncTask`}),`, `,(0,c.jsx)(t.code,{children:`AsyncTaskSuccess`}),`, `,(0,c.jsx)(t.code,{children:`AsyncTaskFailure`}),`, `,(0,c.jsx)(t.code,{children:`AsyncTaskSettled`}),`, `,(0,c.jsx)(t.code,{children:`RunAsyncTasksResult`}),`, `,(0,c.jsx)(t.code,{children:`RunAsyncTasksOptions`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Bounded concurrency`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`runConcurrentTasks`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrencyPartialError`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrentTaskContext`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrentTaskFn`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrentTaskSuccess`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrentTaskError`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrentTaskSettled`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrentTaskUnprocessed`}),`, `,(0,c.jsx)(t.code,{children:`ConcurrentTaskProgress`}),`, `,(0,c.jsx)(t.code,{children:`RunConcurrentTasksOptions`}),`, `,(0,c.jsx)(t.code,{children:`RunConcurrentTasksResult`})]})]})]})]})]})}function s(e={}){let{wrapper:t}={...n(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(o,{...e})}):o(e)}var c;function l(){return(l=e((()=>{c=t(),r(),a()})))()}l();export{s as default};
|