@ryuzaki13/react-foundation-ui 1.8.5 → 1.8.7
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 +2 -2
- package/dist/base-table/index.js +1 -1
- package/dist/chunks/{base-table-CsnUiMTe.js → base-table-CYbtifH0.js} +2 -2
- package/dist/chunks/{base-table-CsnUiMTe.js.map → base-table-CYbtifH0.js.map} +1 -1
- package/dist/chunks/{context-menu-C8sA7xCN.js → context-menu-L4KM0FRD.js} +2 -2
- package/dist/chunks/{context-menu-C8sA7xCN.js.map → context-menu-L4KM0FRD.js.map} +1 -1
- package/dist/chunks/date-input-g6l1iDmf.js.map +1 -1
- package/dist/chunks/{multi-select-Cvjz9W07.js → multi-select-CCgoTHWI.js} +2 -2
- package/dist/chunks/{multi-select-Cvjz9W07.js.map → multi-select-CCgoTHWI.js.map} +1 -1
- package/dist/chunks/{picker-0I1yMKIY.js → picker-Cb3D2Hts.js} +6 -2
- package/dist/chunks/picker-Cb3D2Hts.js.map +1 -0
- package/dist/chunks/{select-CUQ91FIc.js → select-Baek-IUe.js} +2 -2
- package/dist/chunks/{select-CUQ91FIc.js.map → select-Baek-IUe.js.map} +1 -1
- package/dist/chunks/{table-z9kyd9U3.js → table-CrQiurtA.js} +2 -2
- package/dist/chunks/{table-z9kyd9U3.js.map → table-CrQiurtA.js.map} +1 -1
- package/dist/context-menu/index.js +1 -1
- package/dist/layout-picker/index.js +1 -1
- package/dist/listbox/index.js +1 -1
- package/dist/multi-select/index.js +1 -1
- package/dist/picker/index.js +1 -1
- package/dist/preset-select/index.js +1 -1
- package/dist/select/index.js +1 -1
- package/dist/simple-table/index.js +1 -1
- package/dist/slider/index.js +1 -1
- package/dist/state-select/index.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/table/index.js +1 -1
- package/dist/table-sorting/index.js +1 -1
- package/dist/tree-select/index.js +1 -1
- package/dist/tree-table/index.js +1 -1
- package/package.json +4 -4
- package/storybook-static/assets/{Badge-CzxxuE7D.js → Badge-C4U4sxtF.js} +1 -1
- package/storybook-static/assets/{Badge.stories-RaI7qvpZ.js → Badge.stories-DHmJTpdf.js} +1 -1
- package/storybook-static/assets/{BadgeList-B7cF3h_F.js → BadgeList-BOs5ycWn.js} +1 -1
- package/storybook-static/assets/{Button-Cjmm8oDV.js → Button-BTtYeCS_.js} +1 -1
- package/storybook-static/assets/{Button-6z1R7ZA8.js → Button-Bkb3wQw6.js} +1 -1
- package/storybook-static/assets/{Button.stories-B5fUA2Gu.js → Button.stories-DgFLAdcg.js} +1 -1
- package/storybook-static/assets/{CalendarView-Dlt0f4Jr.js → CalendarView-BIFHbOTr.js} +1 -1
- package/storybook-static/assets/{CheckBox-L4324ZCs.js → CheckBox-76M-N56J.js} +1 -1
- package/storybook-static/assets/{CheckBox-BOSDcvCd.js → CheckBox-D4u-58g8.js} +1 -1
- package/storybook-static/assets/{CheckBox.module-CoYygdZx.js → CheckBox.module-BOAVN-Ny.js} +1 -1
- package/storybook-static/assets/{CheckBox.stories-DALRNTV0.js → CheckBox.stories-Caw6-hSQ.js} +1 -1
- package/storybook-static/assets/{Color-6AOWCN3U-UmlmbwVs.js → Color-6AOWCN3U-CPYGaU3y.js} +1 -1
- package/storybook-static/assets/{ContextMenu-giZ56GIC.js → ContextMenu-CUWt-eg1.js} +1 -1
- package/storybook-static/assets/{ContextMenu-BOez7LwB.js → ContextMenu-gfYYiVdR.js} +1 -1
- package/storybook-static/assets/{ContextMenu.stories-BnoaSq3Q.js → ContextMenu.stories-BuQS57wW.js} +1 -1
- package/storybook-static/assets/{CustomOptionButton-C1VgtQgI.js → CustomOptionButton-Be7sd0Lb.js} +1 -1
- package/storybook-static/assets/{DateInput-A3468S6P.js → DateInput-B4oviF7J.js} +1 -1
- package/storybook-static/assets/{DateInput-oWtyLo3Q.js → DateInput-BQGUMYsW.js} +1 -1
- package/storybook-static/assets/{DateInput.stories-BeGG7Vzf.js → DateInput.stories-D6q7J1C4.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect--h5MdeWg.js → DateRangePresetSelect-BAxaG0HP.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-DbKRsjNX.js → DateRangePresetSelect-Cq6pOZPu.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect.stories-BS1ll9RK.js → DateRangePresetSelect.stories-d4HFbao6.js} +1 -1
- package/storybook-static/assets/{Detail-FEi6FSkD.js → Detail-DlETcWVp.js} +1 -1
- package/storybook-static/assets/{Detail.stories-Dy2yKBDx.js → Detail.stories-BEwFXEZH.js} +1 -1
- package/storybook-static/assets/{Dialog-C7Zfcyjf.js → Dialog-Bk8aoiOf.js} +1 -1
- package/storybook-static/assets/{Dialog-CXnHtk_h.js → Dialog-D63TJr1M.js} +1 -1
- package/storybook-static/assets/{Dialog.stories-BeUqdA_f.js → Dialog.stories-BR7NqeZj.js} +1 -1
- package/storybook-static/assets/{Disclosure-BqsgTrM0.js → Disclosure-zQK54WKU.js} +1 -1
- package/storybook-static/assets/{Disclosure.stories-D3LzXhet.js → Disclosure.stories-CNLpB5YJ.js} +1 -1
- package/storybook-static/assets/{DisclosureGroup-BAF5Untb.js → DisclosureGroup-C_nZSLZw.js} +1 -1
- package/storybook-static/assets/{DocsRenderer-JROSPFPF-luRRUpJ_.js → DocsRenderer-JROSPFPF-CoU8mWAw.js} +2 -2
- package/storybook-static/assets/{DropZone-B-YA4zyu.js → DropZone-CUz1Q4bA.js} +1 -1
- package/storybook-static/assets/{DropZone-DKrOIaeH.js → DropZone-Y5hvED_x.js} +1 -1
- package/storybook-static/assets/{DropZone.stories-wf2ubfGc.js → DropZone.stories-BH4FSM4P.js} +1 -1
- package/storybook-static/assets/{DropdownMenu-BiWUESj0.js → DropdownMenu-Bi6-5Gqf.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel-Dtfw5TWs.js → ExpandableActionPanel-BfWj887r.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel.stories-BOdw0CLN.js → ExpandableActionPanel.stories-CGxcwRMU.js} +1 -1
- package/storybook-static/assets/{Flex-BaSYiAMD.js → Flex-Dm-Qfvzk.js} +1 -1
- package/storybook-static/assets/{Flex.stories-CD_e9R5B.js → Flex.stories-B3zMz03s.js} +1 -1
- package/storybook-static/assets/{FlexContainer-LmZIdhq2.js → FlexContainer-BWyPlTMB.js} +1 -1
- package/storybook-static/assets/{FlexItem-vkDYa5tA.js → FlexItem-pu3E11Sf.js} +1 -1
- package/storybook-static/assets/{FloatingPopover-C65hSmop.js → FloatingPopover-NMRTnqfo.js} +1 -1
- package/storybook-static/assets/FormattedTableCell-BISjHrBJ.js +15 -0
- package/storybook-static/assets/{Grid-BCzygAqy.js → Grid-CzO0Ae1r.js} +1 -1
- package/storybook-static/assets/{Grid-8eLmW2AB.js → Grid-vZyA-712.js} +1 -1
- package/storybook-static/assets/{Grid.stories-DULQOmbC.js → Grid.stories-BQqK0zom.js} +1 -1
- package/storybook-static/assets/{GridContainer-qDguE1HS.js → GridContainer-fKYgDsLl.js} +1 -1
- package/storybook-static/assets/{ImageCropper.stories-C1O-Zv4X.js → ImageCropper.stories-Ca4MZWOW.js} +3 -3
- package/storybook-static/assets/{ImageRenderer-BOyGnl1v.js → ImageRenderer-BWIk_76e.js} +1 -1
- package/storybook-static/assets/{ImageRenderer.stories-Cms0kMXA.js → ImageRenderer.stories-C1FfOcFD.js} +1 -1
- package/storybook-static/assets/{ImageView.stories-CUR6bAyn.js → ImageView.stories-DyuR7kdq.js} +1 -1
- package/storybook-static/assets/{ImageViewer.stories-BwJKAIT7.js → ImageViewer.stories-PcvOFYqC.js} +2 -2
- package/storybook-static/assets/{ImageViewerRuntime-CzkvEHax.js → ImageViewerRuntime-BiI7Xukq.js} +2 -2
- package/storybook-static/assets/{Input-B2_RznVE.js → Input-CsD-x1BQ.js} +1 -1
- package/storybook-static/assets/{Input-ebp78QN1.js → Input-D_4GoCLl.js} +1 -1
- package/storybook-static/assets/{Input.stories-BKwTRsUL.js → Input.stories-D-1urO1N.js} +1 -1
- package/storybook-static/assets/{InputDateTime-pK4mlxxm.js → InputDateTime-CFQanHxB.js} +1 -1
- package/storybook-static/assets/{InputDateTime.stories-J4Gd0DaU.js → InputDateTime.stories-Q4Ao5Tat.js} +1 -1
- package/storybook-static/assets/{InputFile-D1x1T--f.js → InputFile-Bj8PXGY3.js} +1 -1
- package/storybook-static/assets/{InputFile-BYcgJx2f.js → InputFile-DM6fBXUx.js} +1 -1
- package/storybook-static/assets/{InputFile.stories-DAYDiSFH.js → InputFile.stories-DC27BYoQ.js} +1 -1
- package/storybook-static/assets/{InputFiles-D7kcGvWK.js → InputFiles-D59MGS0Z.js} +1 -1
- package/storybook-static/assets/{InputFiles-C9HH7fIG.js → InputFiles-teFj6f6X.js} +1 -1
- package/storybook-static/assets/{InputFiles.stories-CJTwQutb.js → InputFiles.stories-DX5UEvYR.js} +1 -1
- package/storybook-static/assets/{InputFilesList-ChI0hQ07.js → InputFilesList-BD4Y0gN-.js} +1 -1
- package/storybook-static/assets/{InputImage-B3KFrWqa.js → InputImage-DmsFGNLJ.js} +1 -1
- package/storybook-static/assets/{InputImage-C0-U_QHU.js → InputImage-Du6jGDmY.js} +1 -1
- package/storybook-static/assets/{InputImage.stories-QEtqeok5.js → InputImage.stories-u0hrr-Da.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents-DB71eb-1.js → InteractiveComponents-BLQiSO3p.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents.stories-DdZpmMis.js → InteractiveComponents.stories-BxIVvRz5.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-CicZY4X9.js → LayoutPicker-TecE4x6w.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-DBEYC_LA.js → LayoutPicker-xUooYcbS.js} +1 -1
- package/storybook-static/assets/{LayoutPicker.stories-BFtP0gOy.js → LayoutPicker.stories-YDMnmhJ4.js} +1 -1
- package/storybook-static/assets/{Listbox-B0Nqys9f.js → Listbox-D2k8QfTs.js} +1 -1
- package/storybook-static/assets/{Listbox-CLP0Cpin.js → Listbox-DplAn6ND.js} +1 -1
- package/storybook-static/assets/{Listbox.stories-BHeIn0H8.js → Listbox.stories-Bg3_UQD4.js} +1 -1
- package/storybook-static/assets/{Modal-D4jDp5U4.js → Modal-4OdkCwCv.js} +1 -1
- package/storybook-static/assets/{Modal.stories-CMHJdaj1.js → Modal.stories-BwawDSGR.js} +1 -1
- package/storybook-static/assets/{ModalManagerProvider-D8tCMe07.js → ModalManagerProvider-CYR_xbpx.js} +1 -1
- package/storybook-static/assets/{MultiSelect-Bmb0qTzT.js → MultiSelect-CXn1CY9G.js} +1 -1
- package/storybook-static/assets/{MultiSelect-y6FjtCjy.js → MultiSelect-iwbCRD9H.js} +1 -1
- package/storybook-static/assets/{MultiSelect.stories-B9TZNWng.js → MultiSelect.stories-BSjAL2ua.js} +1 -1
- package/storybook-static/assets/{NoData-CzlhZzHI.js → NoData-6Scjk2OD.js} +1 -1
- package/storybook-static/assets/{NotificationsHost-AE9gk5zq.js → NotificationsHost-DK3A-iq7.js} +1 -1
- package/storybook-static/assets/{NotificationsHost.stories-Bu0__u38.js → NotificationsHost.stories-BRmPf9Q7.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect-DJ6zie6W.js → ODataMultiSelect-CuNGV1QU.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect.stories-BjgJGbWL.js → ODataMultiSelect.stories-CyAonfZC.js} +1 -1
- package/storybook-static/assets/{ODataSelect-V1JJpKB9.js → ODataSelect-vhh4NJS_.js} +1 -1
- package/storybook-static/assets/{ODataSelect.stories-B2INiDvW.js → ODataSelect.stories-aJBFF45H.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect-BKMrgz8e.js → ODataTreeMultiSelect-vPtlTloF.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect.stories-CjLPeqio.js → ODataTreeMultiSelect.stories-DTBAF628.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect-C2iGJdYk.js → ODataTreeSelect-BCVVLB9M.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect.stories-ReyoXlcX.js → ODataTreeSelect.stories-CptC0p6O.js} +1 -1
- package/storybook-static/assets/{OneStepScroller-knlVIvl2.js → OneStepScroller-DerjCiL3.js} +1 -1
- package/storybook-static/assets/{Option-CJBK9i2B.css → Option-CwetjUM8.css} +1 -1
- package/storybook-static/assets/{Option-KVcu4DcX.js → Option-DkAw9S3l.js} +4 -4
- package/storybook-static/assets/{OptionButton-D2ZcZtPU.js → OptionButton-CGurT23Z.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-BsET8TST.js → PeriodSelect-DOO139ke.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-Bm_VPE_5.js → PeriodSelect-TrGTMIid.js} +1 -1
- package/storybook-static/assets/{PeriodSelect.stories-Due2DawD.js → PeriodSelect.stories-B3GEgBZ1.js} +1 -1
- package/storybook-static/assets/{PickerTriggerActions-KgIZBVSt.js → PickerTriggerActions-CKVPuKEC.js} +1 -1
- package/storybook-static/assets/{Popover-Cq1q1mW3.js → Popover-BNItmUQ9.js} +1 -1
- package/storybook-static/assets/{Popover-D38IExq9.js → Popover-DgXqO0PN.js} +1 -1
- package/storybook-static/assets/{Popover.stories-B5MXPFi2.js → Popover.stories-bX5S41pH.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-dWe-Zcrb.js → PresetRangeDateInput-B4FYPy8g.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-C4iOgcKK.js → PresetRangeDateInput-GSnnpZzy.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput.stories-C8JiJCpi.js → PresetRangeDateInput.stories-Ca0mIo33.js} +1 -1
- package/storybook-static/assets/{PresetSelect-CIqamiLP.js → PresetSelect-B_KRl4SQ.js} +1 -1
- package/storybook-static/assets/README-1RIcD7RV.js +694 -0
- package/storybook-static/assets/README-B1XUsXZj.js +334 -0
- package/storybook-static/assets/README-BH78sIZ_.js +288 -0
- package/storybook-static/assets/README-BgeYwR6t.js +347 -0
- package/storybook-static/assets/README-BhsUMTSk.js +860 -0
- package/storybook-static/assets/README-Bj88Ecb7.js +876 -0
- package/storybook-static/assets/README-C9saKIyr.js +417 -0
- package/storybook-static/assets/README-CP1S4LYF.js +1309 -0
- package/storybook-static/assets/README-Cc-guFb0.js +1487 -0
- package/storybook-static/assets/README-CheO0E1A.js +282 -0
- package/storybook-static/assets/README-CiuVVUgE.js +420 -0
- package/storybook-static/assets/README-CvRg9lqh.js +273 -0
- package/storybook-static/assets/README-DCdV2RQL.js +1093 -0
- package/storybook-static/assets/README-DyNQqotW.js +338 -0
- package/storybook-static/assets/README-W1rhe8Sk.js +648 -0
- package/storybook-static/assets/{RadioButton-CTA-WBmG.js → RadioButton-CA9DN5bY.js} +1 -1
- package/storybook-static/assets/{RadioButton-DfRRX6Id.js → RadioButton-DcXbcFW1.js} +1 -1
- package/storybook-static/assets/{RadioButton.stories-D6MO9y2H.js → RadioButton.stories-1_kzxnXY.js} +1 -1
- package/storybook-static/assets/{RadioGroup-CiEUg_Oc.js → RadioGroup-bEwTHCyS.js} +1 -1
- package/storybook-static/assets/{RadioGroup-BAoD6ZDR.js → RadioGroup-mfYgdfXM.js} +1 -1
- package/storybook-static/assets/{RadioGroup.stories-CCjYE-3G.js → RadioGroup.stories-CecdqPms.js} +1 -1
- package/storybook-static/assets/{Scrollable-ns4PHUAk.js → Scrollable-1fdTDJHK.js} +1 -1
- package/storybook-static/assets/{Select-Bj9NxEJa.js → Select-CvQZGS1G.js} +1 -1
- package/storybook-static/assets/{Select-D2aDjIb_.js → Select-Df5Md2Cm.js} +1 -1
- package/storybook-static/assets/{Select.stories-zErlbrrD.js → Select.stories-M4M80KTq.js} +1 -1
- package/storybook-static/assets/{SerializableSelect-P7iNwTbc.js → SerializableSelect-CnsGo9Ep.js} +1 -1
- package/storybook-static/assets/{SerializableSelect.stories-DUAK_mo8.js → SerializableSelect.stories-BJ6MlNDx.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-vvyw15zU.js → SingleDateTimeInput-BCV0gfB9.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-CkMMccYd.js → SingleDateTimeInput-DJH7zSIz.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput.stories-CSW9M9hH.js → SingleDateTimeInput.stories-DgEwAFe8.js} +1 -1
- package/storybook-static/assets/{Slider-Dftgrmfi.js → Slider-D504FPH3.js} +1 -1
- package/storybook-static/assets/{Slider-CkUdrb57.js → Slider-cLRAHPLi.js} +1 -1
- package/storybook-static/assets/{Slider.stories-zVUgi1Wb.js → Slider.stories-EI314Iff.js} +1 -1
- package/storybook-static/assets/{SliderInput-BINdZsru.js → SliderInput-Bt0H8rgN.js} +1 -1
- package/storybook-static/assets/{SliderInput-DnVNzY_q.js → SliderInput-E5p3n3VY.js} +1 -1
- package/storybook-static/assets/{SliderInput.stories-CfY1B4PZ.js → SliderInput.stories-CDYPq7fP.js} +1 -1
- package/storybook-static/assets/{Sortable-BnixGZFs.js → Sortable-Bzd7JK4E.js} +1 -1
- package/storybook-static/assets/{Sortable.stories-DFzv9lnf.js → Sortable.stories-DNGbmn2a.js} +1 -1
- package/storybook-static/assets/{Splitter-BtDFBrQ3.js → Splitter-DSf48AOW.js} +1 -1
- package/storybook-static/assets/{Splitter.stories-CipjzPJH.js → Splitter.stories-DUKsOqNN.js} +1 -1
- package/storybook-static/assets/{StateSelect-DagWIbnr.js → StateSelect-BxuKIsLa.js} +1 -1
- package/storybook-static/assets/{StateSelect-J5sxWYjq.js → StateSelect-HKOT6kq9.js} +1 -1
- package/storybook-static/assets/{StateSelect.stories-DDIqhm2K.js → StateSelect.stories-CbLvq7ou.js} +1 -1
- package/storybook-static/assets/{StringToggle.stories-CkYGiOe-.js → StringToggle.stories-DOKL-aWy.js} +1 -1
- package/storybook-static/assets/{Switch-B5TS1mrR.js → Switch-CLAfhk73.js} +1 -1
- package/storybook-static/assets/{Switch-N-Lxev-q.js → Switch-CVTjSEq1.js} +1 -1
- package/storybook-static/assets/{Switch.stories-HNOx5mPv.js → Switch.stories-CL5Xe_HQ.js} +1 -1
- package/storybook-static/assets/{Table-DTzmRzDD.js → Table-DKc19RME.js} +1 -1
- package/storybook-static/assets/Table.stories-CJ9DR1S-.js +207 -0
- package/storybook-static/assets/{Tabs-Bc5dgtoT.js → Tabs-De_4F0H3.js} +1 -1
- package/storybook-static/assets/{Tabs.stories-BgLnKKFv.js → Tabs.stories-DPAvvkh9.js} +2 -2
- package/storybook-static/assets/{TabsBox-sTVLs8k0.js → TabsBox-Cy5CICcb.js} +1 -1
- package/storybook-static/assets/{TagInput-yPLHo0PJ.js → TagInput-7n98ftvD.js} +1 -1
- package/storybook-static/assets/{TagInput.stories-B4C-230C.js → TagInput.stories-B6JAb3XA.js} +1 -1
- package/storybook-static/assets/{Text-C2-mep6V.js → Text-CjSG8mvD.js} +1 -1
- package/storybook-static/assets/{Textarea-bqvYs13v.js → Textarea-CQqwaJ0Q.js} +1 -1
- package/storybook-static/assets/{Textarea-B7pXYTGv.js → Textarea-Dea29_yQ.js} +1 -1
- package/storybook-static/assets/{Textarea.stories-BSSaqnZI.js → Textarea.stories-BZf3Cu4S.js} +1 -1
- package/storybook-static/assets/{TimePanel-pMBlR0ZN.js → TimePanel-CPZ4jOw2.js} +1 -1
- package/storybook-static/assets/{TimePanel.stories-Cn5IEcsV.js → TimePanel.stories-y5Lp9sMG.js} +1 -1
- package/storybook-static/assets/{Toggle-E4xV63pY.js → Toggle-CJHzo9mB.js} +1 -1
- package/storybook-static/assets/{Toggle-h6ESIcwX.js → Toggle-s7SzQ11W.js} +1 -1
- package/storybook-static/assets/{Toggle.stories-9uqFBAAr.js → Toggle.stories-Dk3C5Le5.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-DBGlliij.js → TreeMultiSelect-CxXF7pQE.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-J8Tlnv3Y.js → TreeMultiSelect-DfeggvLr.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect.stories-CYDuvIk7.js → TreeMultiSelect.stories-DKiHT_6L.js} +1 -1
- package/storybook-static/assets/{TreePickerBase-BswrqgW3.js → TreePickerBase-DKJJDVC_.js} +1 -1
- package/storybook-static/assets/{TreeSelect-B1Buti64.js → TreeSelect-2E1KhJMi.js} +1 -1
- package/storybook-static/assets/{TreeSelect-Jchj-RXf.js → TreeSelect-h23orAoA.js} +1 -1
- package/storybook-static/assets/{TreeSelect.stories-DzCqueCG.js → TreeSelect.stories-DO06yaS0.js} +1 -1
- package/storybook-static/assets/{TreeTable-oYCdUTsS.js → TreeTable-ByV2_E0S.js} +1 -1
- package/storybook-static/assets/{TreeTable.stories-L4FHah8x.js → TreeTable.stories-D4gbQx59.js} +2 -2
- package/storybook-static/assets/{WithTooltip-7X4HQR7L-Cakt_JaX.js → WithTooltip-7X4HQR7L-DQ4Qthn2.js} +1 -1
- package/storybook-static/assets/{array-D-_yMMUK-CIRmlF93.js → array-D-_yMMUK-BQ0uu1hZ.js} +1 -1
- package/storybook-static/assets/{async-Bsdhj8g_.js → async-BI7SlYp0.js} +1 -1
- package/storybook-static/assets/axe-_9eNhXQJ.js +20 -0
- package/storybook-static/assets/{blocks-BA_1CXsr.js → blocks-B8F5vBhs.js} +6 -6
- package/storybook-static/assets/check-mlY_aVEI.js +1 -0
- package/storybook-static/assets/chevron-down-C7c-TcEc.js +1 -0
- package/storybook-static/assets/chevron-left-2LrGBhDY.js +1 -0
- package/storybook-static/assets/chevron-right-D6NN1_UQ.js +1 -0
- package/storybook-static/assets/{chunk-242VQQM5-BMWWiybC.js → chunk-242VQQM5-bHL6qIJq.js} +1 -1
- package/storybook-static/assets/{chunk-DRQKCCAG-CqE-Zrl9.js → chunk-DRQKCCAG-DvsmU7ha.js} +1 -1
- package/storybook-static/assets/{chunk-IMSF75WX-yvVUwIQZ.js → chunk-IMSF75WX-CGYlPTyG.js} +1 -1
- package/storybook-static/assets/{chunk-KJHJLCBK-D-yQfkOi.js → chunk-KJHJLCBK-yRlRMfNs.js} +1 -1
- package/storybook-static/assets/{chunk-QQBDHPVZ-B98qboss.js → chunk-QQBDHPVZ-DC5n6Pix.js} +1 -1
- package/storybook-static/assets/{chunk-W22LQPXL-B40Li12y.js → chunk-W22LQPXL-5sD3hVeE.js} +1 -1
- package/storybook-static/assets/{circle-alert-C855gqBz.js → circle-alert-H_7GSXFp.js} +1 -1
- package/storybook-static/assets/circle-check-B0voRIBT.js +1 -0
- package/storybook-static/assets/{components-DSUjzUVy.js → components-Bw-2TeQP.js} +12 -12
- package/storybook-static/assets/{contextMenu-DCSPTQNQ.js → contextMenu-B8JusItT.js} +1 -1
- package/storybook-static/assets/{createControlledStoryRender-DHsyXc1B.js → createControlledStoryRender-BouhvX-R.js} +1 -1
- package/storybook-static/assets/{date-segments-D3HouZ37.js → date-segments-DeoMkKv9.js} +1 -1
- package/storybook-static/assets/{defaultRenderers-V5HI39JH.js → defaultRenderers-BHXboKuy.js} +1 -1
- package/storybook-static/assets/{dom-B3G_GtJw.js → dom-DBd_DWF8.js} +1 -1
- package/storybook-static/assets/{download-B3oJ9vHV.js → download-CSY7aIz0.js} +1 -1
- package/storybook-static/assets/{error-BZrNlEUO.js → error-De9R4E_F.js} +1 -1
- package/storybook-static/assets/{file-vPGnhPr-.js → file-CwRoWxeB.js} +1 -1
- package/storybook-static/assets/floating-ui.react-D7RwPYeO.js +1 -0
- package/storybook-static/assets/formatter-L2YTDE3Q-CRGuSxAF.js +1 -0
- package/storybook-static/assets/{formatters-CBgrBeSA-DY6OIAc8.js → formatters-CBgrBeSA-CqB1pZxS.js} +1 -1
- package/storybook-static/assets/{foundationLib-BFrQ5jez.js → foundationLib-BoYGVeXe.js} +1 -1
- package/storybook-static/assets/{hooks-_jPrECht.js → hooks-DQXvhAPr.js} +2 -2
- package/storybook-static/assets/iframe-B8PAuhnL.js +1 -0
- package/storybook-static/assets/{iframe-Cq8y-8O_.js → iframe-CViB2sFm.js} +23 -23
- package/storybook-static/assets/{info-CiT6g2aP.js → info-MrQcS8jn.js} +1 -1
- package/storybook-static/assets/{matchers-JIUQ3HVY-DvR2XErZ.js → matchers-JIUQ3HVY-C789_MAK.js} +1 -1
- package/storybook-static/assets/{media-BycWpjAl.js → media-D9cE2tzi.js} +1 -1
- package/storybook-static/assets/odata-CBGaUmRT.js +1 -0
- package/storybook-static/assets/{odata-service-B6TxBSLm-BW9QLSrS.js → odata-service-B6TxBSLm-Bq8Ya67E.js} +1 -1
- package/storybook-static/assets/{odataFetchFn-C6ps_31t.js → odataFetchFn-CPO8XIYX.js} +1 -1
- package/storybook-static/assets/{odataStoryFixtures-BcNo-Wxr.js → odataStoryFixtures--SWu2yC_.js} +2 -2
- package/storybook-static/assets/{persisted-B6h1b3UG.js → persisted-B2dfNRCz.js} +1 -1
- package/storybook-static/assets/{preload-helper-BHmFeTtP.js → preload-helper-wdlQj8DP.js} +1 -1
- package/storybook-static/assets/react-18-D4o7zN8K.js +9 -0
- package/storybook-static/assets/{react-C21x__mS.js → react-BZJXY1be.js} +1 -1
- package/storybook-static/assets/{react-qN2cStNd.js → react-Bl2r1tuC.js} +1 -1
- package/storybook-static/assets/{react-CvkUhHUq.js → react-GkniIHEK.js} +1 -1
- package/storybook-static/assets/{react-dom-2o2phaJG.js → react-dom-BzEl8usk.js} +1 -1
- package/storybook-static/assets/react-iQQwtFPL.js +9 -0
- package/storybook-static/assets/{refresh-cw-DIeuulxV.js → refresh-cw-_wTFfhR2.js} +1 -1
- package/storybook-static/assets/{rolldown-runtime-C0FnF6B9.js → rolldown-runtime-DkW27tQK.js} +1 -1
- package/storybook-static/assets/{settings-2-Gfu_uw21.js → settings-2-BqduNJjJ.js} +1 -1
- package/storybook-static/assets/{shim-BUMlC1GG.js → shim-DlYORV19.js} +1 -1
- package/storybook-static/assets/{sortable-DxRr6Rgq.js → sortable-D-m6SEp7.js} +1 -1
- package/storybook-static/assets/syntaxhighlighter-QEQV7K2Y-CEo9I1qZ.js +6 -0
- package/storybook-static/assets/{theming-mTWhffkp.js → theming-Cvtrnj7n.js} +1 -1
- package/storybook-static/assets/{trash-2-CqKAB1Q0.js → trash-2-65ZF92zp.js} +1 -1
- package/storybook-static/assets/{treeStoryFixtures-Ci7STpiz.js → treeStoryFixtures-DXHh9GL3.js} +1 -1
- package/storybook-static/assets/{triangle-alert-D4omsgZJ.js → triangle-alert-k_CRNi0k.js} +1 -1
- package/storybook-static/assets/{ui.module-D4CuGr8r.js → ui.module-Cat84Nza.js} +1 -1
- package/storybook-static/assets/{uiClasses-CVGbL980.js → uiClasses-B9c6dZuu.js} +1 -1
- package/storybook-static/assets/{useFlexClasses-Gn9spXEB.js → useFlexClasses-SgVG37Bb.js} +1 -1
- package/storybook-static/assets/{useODataSelectBase-DacE6X5d.js → useODataSelectBase-Ck_hduYv.js} +1 -1
- package/storybook-static/assets/{useODataTreeData-BEYyje5V.js → useODataTreeData-DTrxPY_k.js} +1 -1
- package/storybook-static/assets/usePickerDefaultFilter-5Q1pAV4d.js +1 -0
- package/storybook-static/assets/{usePickerQuery-BRsuRnoH.js → usePickerQuery-DdeWtJWc.js} +1 -1
- package/storybook-static/assets/{usePickerTriggerController-DyFq40t1.js → usePickerTriggerController-D8hxWmGo.js} +2 -2
- package/storybook-static/assets/{utils-DUM89eIj.js → utils-tg3ibbzi.js} +1 -1
- package/storybook-static/assets/x-C5XG0bD4.js +1 -0
- package/storybook-static/iframe.html +7 -7
- package/storybook-static/index.json +1 -1
- package/storybook-static/project.json +1 -1
- package/storybook-static/sb-addons/chromatic-com-storybook-1/manager-bundle.js +35 -33
- package/storybook-static/sb-manager/globals-runtime.js +7 -7
- package/storybook-static/sb-manager/globals.js +1 -1
- package/storybook-static/sb-manager/runtime.js +88 -89
- package/storybook-static/vite-inject-mocker-entry.js +2 -2
- package/dist/chunks/picker-0I1yMKIY.js.map +0 -1
- package/storybook-static/assets/FormattedTableCell-BdA15EY1.js +0 -15
- package/storybook-static/assets/Table.stories-DY5NfoVd.js +0 -207
- package/storybook-static/assets/axe-Bq-2xuso.js +0 -20
- package/storybook-static/assets/browserAndReact-fXgh8QfO.js +0 -70
- package/storybook-static/assets/check-wNoLJyvD.js +0 -1
- package/storybook-static/assets/chevron-down-DjM4Yyml.js +0 -1
- package/storybook-static/assets/chevron-left-BT138_KT.js +0 -1
- package/storybook-static/assets/chevron-right-DEvxOiq2.js +0 -1
- package/storybook-static/assets/circle-check-BDVZ6tz8.js +0 -1
- package/storybook-static/assets/filesAndExcel-Bj4tkdkM.js +0 -92
- package/storybook-static/assets/floating-ui.react-BewtdZNK.js +0 -1
- package/storybook-static/assets/formatter-L2YTDE3Q-x0raBH34.js +0 -1
- package/storybook-static/assets/formatters-DYZ7voq3.js +0 -202
- package/storybook-static/assets/formatters-runtime-Ddmbt5yI.js +0 -329
- package/storybook-static/assets/iframe-C7ggO0sY.js +0 -1
- package/storybook-static/assets/odata-ClP2t_-O.js +0 -1
- package/storybook-static/assets/odataAndTables-Cjwl3uWE.js +0 -77
- package/storybook-static/assets/pureUtilities-CO1AJvbl.js +0 -30
- package/storybook-static/assets/react-18-CgkwBzTo.js +0 -9
- package/storybook-static/assets/react-D4nkG-T7.js +0 -9
- package/storybook-static/assets/runtimeAndState-TcnlLgJx.js +0 -93
- package/storybook-static/assets/syntaxhighlighter-T5IQBZDB-BIwIp4cU.js +0 -6
- package/storybook-static/assets/usePickerDefaultFilter-Be420WNF.js +0 -1
- package/storybook-static/assets/x-zmaXH4MN.js +0 -1
|
@@ -0,0 +1,1093 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe-CViB2sFm.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-B8F5vBhs.js";function o(e){let t={a:`a`,code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,h4:`h4`,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/Array`}),`
|
|
2
|
+
`,(0,c.jsxs)(t.h1,{id:`работа-с-массивами-через-ryuzaki13react-foundation-libarray`,children:[`Работа с массивами через `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/array`})]}),`
|
|
3
|
+
`,(0,c.jsxs)(t.p,{children:[`Модуль `,(0,c.jsx)(t.code,{children:`array`}),` содержит небольшие типизированные функции для типовых операций с массивами:`]}),`
|
|
4
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
5
|
+
`,(0,c.jsx)(t.li,{children:`группировки элементов;`}),`
|
|
6
|
+
`,(0,c.jsx)(t.li,{children:`построения словаря по полю объекта;`}),`
|
|
7
|
+
`,(0,c.jsx)(t.li,{children:`удаления дубликатов;`}),`
|
|
8
|
+
`,(0,c.jsx)(t.li,{children:`восстановления порядка элементов по списку идентификаторов;`}),`
|
|
9
|
+
`,(0,c.jsx)(t.li,{children:`сравнения массивов;`}),`
|
|
10
|
+
`,(0,c.jsx)(t.li,{children:`перемещения элементов;`}),`
|
|
11
|
+
`,(0,c.jsx)(t.li,{children:`нормализации строковых идентификаторов и объектов.`}),`
|
|
12
|
+
`]}),`
|
|
13
|
+
`,(0,c.jsx)(t.p,{children:`Функции не зависят от React, браузерного DOM, TanStack или других внешних runtime-библиотек. Их можно использовать в обычном TypeScript/JavaScript-коде, React-компонентах, store, mapper, validator и на границах сохранения или восстановления конфигурации.`}),`
|
|
14
|
+
`,(0,c.jsx)(t.p,{children:`README рассчитан на разработчика, который использует опубликованный пакет и не читает его исходный код. Здесь отдельно объясняются базовые понятия JavaScript/TypeScript, точное поведение каждой функции, ограничения и типовые ошибки.`}),`
|
|
15
|
+
`,(0,c.jsx)(t.h2,{id:`содержание`,children:`Содержание`}),`
|
|
16
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
17
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%B8-%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82`,children:`Установка и импорт`})}),`
|
|
18
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BF%D0%BE%D0%BD%D1%8F%D1%82%D0%B8%D1%8F-javascript-%D0%B8-typescript`,children:`Минимальные понятия JavaScript и TypeScript`})}),`
|
|
19
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BA%D0%B0%D0%BA-%D0%B2%D1%8B%D0%B1%D1%80%D0%B0%D1%82%D1%8C-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8E`,children:`Как выбрать функцию`})}),`
|
|
20
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B1%D1%8B%D1%81%D1%82%D1%80%D1%8B%D0%B9-%D1%81%D1%82%D0%B0%D1%80%D1%82`,children:`Быстрый старт`})}),`
|
|
21
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BE%D0%B1%D1%89%D0%B8%D0%B5-%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8F`,children:`Общие правила модуля`})}),`
|
|
22
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B3%D1%80%D1%83%D0%BF%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0-%D0%B8-%D0%BF%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8F`,children:`Группировка и построение словаря`})}),`
|
|
23
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B4%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D0%B2`,children:`Удаление дубликатов`})}),`
|
|
24
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsxs)(t.a,{href:`#%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80%D0%B0%D0%BC%D0%B8-%D0%B8-map`,children:[`Работа с идентификаторами и `,(0,c.jsx)(t.code,{children:`Map`})]})}),`
|
|
25
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2%D0%BE%D0%B2`,children:`Сравнение массивов`})}),`
|
|
26
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D0%B5-%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D0%BE%D0%B2`,children:`Перемещение элементов`})}),`
|
|
27
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D1%81%D1%82%D1%80%D0%BE%D0%BA-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BE%D0%B2`,children:`Нормализация строк и объектов`})}),`
|
|
28
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D1%8B%D0%B5-%D1%80%D0%B5%D1%86%D0%B5%D0%BF%D1%82%D1%8B`,children:`Готовые рецепты`})}),`
|
|
29
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D1%8C`,children:`Производительность`})}),`
|
|
30
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BE%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D1%87%D0%B0%D1%81%D1%82%D1%8B%D0%B5-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B8`,children:`Ограничения и частые ошибки`})}),`
|
|
31
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BA%D1%80%D0%B0%D1%82%D0%BA%D0%B8%D0%B9-%D1%81%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D1%87%D0%BD%D0%B8%D0%BA-api`,children:`Краткий справочник API`})}),`
|
|
32
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B2%D0%BE%D0%BF%D1%80%D0%BE%D1%81%D1%8B-%D0%B8-%D0%BE%D1%82%D0%B2%D0%B5%D1%82%D1%8B`,children:`Вопросы и ответы`})}),`
|
|
33
|
+
`]}),`
|
|
34
|
+
`,(0,c.jsx)(t.h2,{id:`установка-и-импорт`,children:`Установка и импорт`}),`
|
|
35
|
+
`,(0,c.jsx)(t.p,{children:`Установите пакет в приложении:`}),`
|
|
36
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-bash`,children:`npm install @ryuzaki13/react-foundation-lib
|
|
37
|
+
`})}),`
|
|
38
|
+
`,(0,c.jsxs)(t.p,{children:[`Импортируйте функции только из точечного entrypoint `,(0,c.jsx)(t.code,{children:`/array`}),`:`]}),`
|
|
39
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { arrayGroupBy, arrayToMap, arrayUniqueBy, moveArrayItem } from "@ryuzaki13/react-foundation-lib/array";
|
|
40
|
+
|
|
41
|
+
import type { ReorderAction } from "@ryuzaki13/react-foundation-lib/array";
|
|
42
|
+
`})}),`
|
|
43
|
+
`,(0,c.jsx)(t.p,{children:`Корневой импорт пакета не поддерживается:`}),`
|
|
44
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Неправильно: у пакета нет корневого export.
|
|
45
|
+
import { arrayGroupBy } from "@ryuzaki13/react-foundation-lib";
|
|
46
|
+
|
|
47
|
+
// Правильно.
|
|
48
|
+
import { arrayGroupBy } from "@ryuzaki13/react-foundation-lib/array";
|
|
49
|
+
`})}),`
|
|
50
|
+
`,(0,c.jsx)(t.p,{children:`Модуль поставляется как ESM. Для его функций не нужно устанавливать дополнительные peer-зависимости.`}),`
|
|
51
|
+
`,(0,c.jsx)(t.h2,{id:`минимальные-понятия-javascript-и-typescript`,children:`Минимальные понятия JavaScript и TypeScript`}),`
|
|
52
|
+
`,(0,c.jsx)(t.h3,{id:`массив-элемент-и-индекс`,children:`Массив, элемент и индекс`}),`
|
|
53
|
+
`,(0,c.jsx)(t.p,{children:`Массив — упорядоченный список значений:`}),`
|
|
54
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const letters = ["A", "B", "C"];
|
|
55
|
+
`})}),`
|
|
56
|
+
`,(0,c.jsx)(t.p,{children:`Каждое значение называется элементом. Позиция элемента называется индексом. Индексы начинаются с нуля:`}),`
|
|
57
|
+
`,(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,{style:{textAlign:`right`},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:`"A"`})}),(0,c.jsx)(t.td,{style:{textAlign:`right`},children:`0`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`"B"`})}),(0,c.jsx)(t.td,{style:{textAlign:`right`},children:`1`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`"C"`})}),(0,c.jsx)(t.td,{style:{textAlign:`right`},children:`2`})]})]})]}),`
|
|
58
|
+
`,(0,c.jsxs)(t.p,{children:[`Поэтому перемещение элемента с индекса `,(0,c.jsx)(t.code,{children:`0`}),` на индекс `,(0,c.jsx)(t.code,{children:`2`}),` означает перемещение `,(0,c.jsx)(t.code,{children:`"A"`}),` в конец.`]}),`
|
|
59
|
+
`,(0,c.jsx)(t.h3,{id:`объект-и-ключ-объекта`,children:`Объект и ключ объекта`}),`
|
|
60
|
+
`,(0,c.jsx)(t.p,{children:`Объект хранит именованные свойства:`}),`
|
|
61
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const user = {
|
|
62
|
+
id: "U-1",
|
|
63
|
+
name: "Анна",
|
|
64
|
+
department: "Продажи"
|
|
65
|
+
};
|
|
66
|
+
`})}),`
|
|
67
|
+
`,(0,c.jsxs)(t.p,{children:[`Вызов `,(0,c.jsx)(t.code,{children:`arrayGroupBy(users, "department")`}),` означает: взять у каждого пользователя свойство `,(0,c.jsx)(t.code,{children:`department`}),` и использовать его значение как ключ группы.`]}),`
|
|
68
|
+
`,(0,c.jsxs)(t.p,{children:[`TypeScript-конструкция `,(0,c.jsx)(t.code,{children:`keyof T`}),` запрещает случайно передать имя свойства, которого нет в элементах массива:`]}),`
|
|
69
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type User = {
|
|
70
|
+
id: string;
|
|
71
|
+
name: string;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const users: User[] = [];
|
|
75
|
+
|
|
76
|
+
arrayToMap(users, "id"); // Корректно.
|
|
77
|
+
arrayToMap(users, "department"); // Ошибка TypeScript: такого свойства нет в User.
|
|
78
|
+
`})}),`
|
|
79
|
+
`,(0,c.jsx)(t.h3,{id:`ссылка-на-объект`,children:`Ссылка на объект`}),`
|
|
80
|
+
`,(0,c.jsx)(t.p,{children:`Объекты и массивы являются ссылочными значениями. Две переменные могут указывать на один объект:`}),`
|
|
81
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const first = { id: "A" };
|
|
82
|
+
const second = first;
|
|
83
|
+
|
|
84
|
+
console.log(first === second); // true
|
|
85
|
+
`})}),`
|
|
86
|
+
`,(0,c.jsx)(t.p,{children:`Два отдельно созданных объекта с одинаковыми полями имеют разные ссылки:`}),`
|
|
87
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const first = { id: "A" };
|
|
88
|
+
const second = { id: "A" };
|
|
89
|
+
|
|
90
|
+
console.log(first === second); // false
|
|
91
|
+
`})}),`
|
|
92
|
+
`,(0,c.jsxs)(t.p,{children:[`Это важно для `,(0,c.jsx)(t.code,{children:`arrayDeduplicate`}),` и `,(0,c.jsx)(t.code,{children:`arraysEqual`}),`: они не выполняют глубокое сравнение содержимого объектов.`]}),`
|
|
93
|
+
`,(0,c.jsx)(t.h3,{id:`мутация-и-неизменяемое-преобразование`,children:`Мутация и неизменяемое преобразование`}),`
|
|
94
|
+
`,(0,c.jsx)(t.p,{children:`Мутация — изменение уже существующего массива или объекта:`}),`
|
|
95
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = ["A", "B"];
|
|
96
|
+
source.push("C"); // source изменён.
|
|
97
|
+
`})}),`
|
|
98
|
+
`,(0,c.jsx)(t.p,{children:`Неизменяемое преобразование создаёт новый массив и оставляет исходный без изменений:`}),`
|
|
99
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = ["A", "B"];
|
|
100
|
+
const result = [...source, "C"];
|
|
101
|
+
|
|
102
|
+
console.log(source); // ["A", "B"]
|
|
103
|
+
console.log(result); // ["A", "B", "C"]
|
|
104
|
+
`})}),`
|
|
105
|
+
`,(0,c.jsxs)(t.p,{children:[`Почти все функции этого модуля работают неизменяемо. Исключение — `,(0,c.jsx)(t.code,{children:`addUnique`}),`, которая специально изменяет переданные `,(0,c.jsx)(t.code,{children:`target`}),` и `,(0,c.jsx)(t.code,{children:`seen`}),`.`]}),`
|
|
106
|
+
`,(0,c.jsx)(t.h3,{id:`поверхностная-копия`,children:`Поверхностная копия`}),`
|
|
107
|
+
`,(0,c.jsx)(t.p,{children:`Поверхностная копия создаёт новый внешний массив или объект, но не копирует вложенные объекты:`}),`
|
|
108
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const profile = { city: "Казань" };
|
|
109
|
+
const source = [{ id: "A", profile }];
|
|
110
|
+
const copy = [...source];
|
|
111
|
+
|
|
112
|
+
console.log(copy !== source); // true: массив новый.
|
|
113
|
+
console.log(copy[0] === source[0]); // true: элемент тот же.
|
|
114
|
+
console.log(copy[0].profile === profile); // true: вложенный объект тот же.
|
|
115
|
+
`})}),`
|
|
116
|
+
`,(0,c.jsx)(t.p,{children:`Функции модуля не выполняют глубокое клонирование.`}),`
|
|
117
|
+
`,(0,c.jsxs)(t.h3,{id:`что-означают-t-readonly-t-record-map-и-set`,children:[`Что означают `,(0,c.jsx)(t.code,{children:`T`}),`, `,(0,c.jsx)(t.code,{children:`readonly T[]`}),`, `,(0,c.jsx)(t.code,{children:`Record`}),`, `,(0,c.jsx)(t.code,{children:`Map`}),` и `,(0,c.jsx)(t.code,{children:`Set`})]}),`
|
|
118
|
+
`,(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:`T`})}),(0,c.jsx)(t.td,{children:`Обобщённый тип элемента. TypeScript подставит фактический тип из переданного массива.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`readonly T[]`})}),(0,c.jsx)(t.td,{children:`Функция обещает не изменять входной массив. Обычный изменяемый массив тоже можно передать.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`T[]`})}),(0,c.jsxs)(t.td,{children:[`Массив элементов типа `,(0,c.jsx)(t.code,{children:`T`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Record<string,T>`})}),(0,c.jsxs)(t.td,{children:[`Обычный JavaScript-объект, в котором строковый ключ ведёт к значению типа `,(0,c.jsx)(t.code,{children:`T`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Map<K,V>`})}),(0,c.jsxs)(t.td,{children:[`Коллекция пар «ключ → значение» с методами `,(0,c.jsx)(t.code,{children:`get`}),`, `,(0,c.jsx)(t.code,{children:`set`}),`, `,(0,c.jsx)(t.code,{children:`has`}),`. Ключ может иметь любой тип.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Set<T>`})}),(0,c.jsxs)(t.td,{children:[`Коллекция уникальных значений. Метод `,(0,c.jsx)(t.code,{children:`has`}),` проверяет, встречалось ли значение, а `,(0,c.jsx)(t.code,{children:`add`}),` добавляет его в набор.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`undefined`})}),(0,c.jsx)(t.td,{children:`Значение отсутствует. Некоторые normalizer-функции возвращают его вместо пустого результата.`})]})]})]}),`
|
|
119
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`readonly`}),` в типе параметра не замораживает массив во время выполнения. Это ограничение TypeScript внутри функции, а не вызов `,(0,c.jsx)(t.code,{children:`Object.freeze`}),`.`]}),`
|
|
120
|
+
`,(0,c.jsx)(t.h2,{id:`как-выбрать-функцию`,children:`Как выбрать функцию`}),`
|
|
121
|
+
`,(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.td,{children:(0,c.jsx)(t.code,{children:`arrayGroupBy`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Получить группы как массив `,(0,c.jsx)(t.code,{children:`{ key, items }`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayGroupByToArray`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Быстро находить объект по его `,(0,c.jsx)(t.code,{children:`id`}),` или другому полю`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayToMap`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Оставить первый объект для каждого уникального значения поля`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayUniqueBy`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Удалить повторяющиеся примитивы или повторные ссылки`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayDeduplicate`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Оставить только разрешённые ID и убрать их повторы`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`filterAndDeduplicateIds`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Дописать в конец отсутствующие ID`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`appendMissingIds`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Получить значения `,(0,c.jsx)(t.code,{children:`Map`}),` в заданном порядке ключей`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`pickExistingMapValues`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Проверить одинаковую длину, порядок и строгую идентичность элементов`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arraysEqual`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Переместить элемент с одного числового индекса на другой`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`moveArrayItem`}),` или `,(0,c.jsx)(t.code,{children:`moveItem`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Переместить элемент в начало, конец, на одну позицию вверх или вниз`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`moveArrayItemByIndex`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Обрезать пробелы у строк, удалить пустые строки и дубли`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeStringArray`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Нормализовать строковое ключевое поле списка объектов`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeObjects`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Постепенно собрать уникальные строковые ID в уже существующий массив`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`addUnique`})})]})]})]}),`
|
|
122
|
+
`,(0,c.jsx)(t.h2,{id:`быстрый-старт`,children:`Быстрый старт`}),`
|
|
123
|
+
`,(0,c.jsx)(t.p,{children:`Пусть сервер вернул список пользователей:`}),`
|
|
124
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type User = {
|
|
125
|
+
id: string;
|
|
126
|
+
name: string;
|
|
127
|
+
department: string;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const users: User[] = [
|
|
131
|
+
{ id: "U-1", name: "Анна", department: "Продажи" },
|
|
132
|
+
{ id: "U-2", name: "Иван", department: "ИТ" },
|
|
133
|
+
{ id: "U-3", name: "Ольга", department: "Продажи" }
|
|
134
|
+
];
|
|
135
|
+
`})}),`
|
|
136
|
+
`,(0,c.jsx)(t.p,{children:`Сгруппировать пользователей по подразделению:`}),`
|
|
137
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const usersByDepartment = arrayGroupBy(users, "department");
|
|
138
|
+
|
|
139
|
+
console.log(usersByDepartment["Продажи"]);
|
|
140
|
+
// [
|
|
141
|
+
// { id: "U-1", name: "Анна", department: "Продажи" },
|
|
142
|
+
// { id: "U-3", name: "Ольга", department: "Продажи" }
|
|
143
|
+
// ]
|
|
144
|
+
`})}),`
|
|
145
|
+
`,(0,c.jsx)(t.p,{children:`Построить словарь для быстрого поиска по ID:`}),`
|
|
146
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const usersById = arrayToMap(users, "id");
|
|
147
|
+
|
|
148
|
+
console.log(usersById["U-2"]);
|
|
149
|
+
// { id: "U-2", name: "Иван", department: "ИТ" }
|
|
150
|
+
`})}),`
|
|
151
|
+
`,(0,c.jsxs)(t.p,{children:[`Переместить первого пользователя в конец без изменения `,(0,c.jsx)(t.code,{children:`users`}),`:`]}),`
|
|
152
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const reorderedUsers = moveArrayItem(users, 0, 2);
|
|
153
|
+
|
|
154
|
+
console.log(reorderedUsers.map((user) => user.id)); // ["U-2", "U-3", "U-1"]
|
|
155
|
+
console.log(users.map((user) => user.id)); // ["U-1", "U-2", "U-3"]
|
|
156
|
+
`})}),`
|
|
157
|
+
`,(0,c.jsx)(t.h2,{id:`общие-правила-модуля`,children:`Общие правила модуля`}),`
|
|
158
|
+
`,(0,c.jsx)(t.h3,{id:`исходный-массив-обычно-не-изменяется`,children:`Исходный массив обычно не изменяется`}),`
|
|
159
|
+
`,(0,c.jsxs)(t.p,{children:[`Все функции, кроме `,(0,c.jsx)(t.code,{children:`addUnique`}),`, не изменяют переданный массив. Функции, которые возвращают массив, создают новый внешний массив.`]}),`
|
|
160
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = ["A", "B", "C"];
|
|
161
|
+
const result = moveArrayItem(source, 0, 2);
|
|
162
|
+
|
|
163
|
+
console.log(result === source); // false
|
|
164
|
+
console.log(source); // ["A", "B", "C"]
|
|
165
|
+
`})}),`
|
|
166
|
+
`,(0,c.jsx)(t.p,{children:`Даже если перемещение невозможно или не требуется, функции перемещения возвращают копию:`}),`
|
|
167
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = ["A", "B"];
|
|
168
|
+
const result = moveArrayItem(source, 0, 0);
|
|
169
|
+
|
|
170
|
+
console.log(result); // ["A", "B"]
|
|
171
|
+
console.log(result === source); // false
|
|
172
|
+
`})}),`
|
|
173
|
+
`,(0,c.jsx)(t.h3,{id:`элементы-обычно-не-клонируются`,children:`Элементы обычно не клонируются`}),`
|
|
174
|
+
`,(0,c.jsxs)(t.p,{children:[`Новые массивы содержат прежние значения и ссылки. Исключение — `,(0,c.jsx)(t.code,{children:`normalizeObjects`}),` в режиме по умолчанию: она поверхностно копирует каждый сохранённый объект.`]}),`
|
|
175
|
+
`,(0,c.jsx)(t.p,{children:`Если изменить вложенный объект через результат, изменение будет видно через исходный объект:`}),`
|
|
176
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = [{ id: "A", settings: { visible: true } }];
|
|
177
|
+
const result = arrayUniqueBy(source, "id");
|
|
178
|
+
|
|
179
|
+
result[0].settings.visible = false;
|
|
180
|
+
|
|
181
|
+
console.log(source[0].settings.visible); // false
|
|
182
|
+
`})}),`
|
|
183
|
+
`,(0,c.jsx)(t.h3,{id:`сохраняется-первое-подходящее-значение`,children:`Сохраняется первое подходящее значение`}),`
|
|
184
|
+
`,(0,c.jsx)(t.p,{children:`Функции удаления дубликатов и построения словаря сохраняют первое вхождение:`}),`
|
|
185
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const rows = [
|
|
186
|
+
{ id: "A", value: 1 },
|
|
187
|
+
{ id: "A", value: 2 }
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
console.log(arrayToMap(rows, "id")["A"].value); // 1
|
|
191
|
+
console.log(arrayUniqueBy(rows, "id")); // Только первый объект.
|
|
192
|
+
`})}),`
|
|
193
|
+
`,(0,c.jsx)(t.h3,{id:`регистр-обычно-учитывается`,children:`Регистр обычно учитывается`}),`
|
|
194
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`"A"`}),` и `,(0,c.jsx)(t.code,{children:`"a"`}),` считаются разными значениями. Модуль не переводит текст в нижний или верхний регистр.`]}),`
|
|
195
|
+
`,(0,c.jsx)(t.h3,{id:`ошибки-не-логируются-и-не-скрываются`,children:`Ошибки не логируются и не скрываются`}),`
|
|
196
|
+
`,(0,c.jsxs)(t.p,{children:[`Функции ожидают значения, соответствующие TypeScript-сигнатурам. Например, вместо массива нельзя передавать `,(0,c.jsx)(t.code,{children:`null`}),`. TypeScript должен обнаружить такую ошибку до запуска программы.`]}),`
|
|
197
|
+
`,(0,c.jsx)(t.p,{children:`Исключение — функции перемещения: для целых индексов вне границ массива они безопасно возвращают копию без перестановки.`}),`
|
|
198
|
+
`,(0,c.jsx)(t.h2,{id:`группировка-и-построение-словаря`,children:`Группировка и построение словаря`}),`
|
|
199
|
+
`,(0,c.jsx)(t.h3,{id:`arraygroupby`,children:(0,c.jsx)(t.code,{children:`arrayGroupBy`})}),`
|
|
200
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
201
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function arrayGroupBy<T>(array: readonly T[], key: keyof T): Record<string, T[]>;
|
|
202
|
+
`})}),`
|
|
203
|
+
`,(0,c.jsx)(t.p,{children:`Функция группирует элементы по значению выбранного свойства.`}),`
|
|
204
|
+
`,(0,c.jsx)(t.p,{children:`Параметры:`}),`
|
|
205
|
+
`,(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:`array`})}),(0,c.jsx)(t.td,{children:`Исходный массив объектов.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`key`})}),(0,c.jsx)(t.td,{children:`Имя свойства, значение которого определяет группу.`})]})]})]}),`
|
|
206
|
+
`,(0,c.jsx)(t.p,{children:`Результат — обычный объект. Каждый его ключ ведёт к массиву элементов соответствующей группы.`}),`
|
|
207
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const tasks = [
|
|
208
|
+
{ id: 1, status: "new" },
|
|
209
|
+
{ id: 2, status: "done" },
|
|
210
|
+
{ id: 3, status: "new" }
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
const tasksByStatus = arrayGroupBy(tasks, "status");
|
|
214
|
+
|
|
215
|
+
console.log(tasksByStatus);
|
|
216
|
+
// {
|
|
217
|
+
// new: [
|
|
218
|
+
// { id: 1, status: "new" },
|
|
219
|
+
// { id: 3, status: "new" }
|
|
220
|
+
// ],
|
|
221
|
+
// done: [
|
|
222
|
+
// { id: 2, status: "done" }
|
|
223
|
+
// ]
|
|
224
|
+
// }
|
|
225
|
+
`})}),`
|
|
226
|
+
`,(0,c.jsx)(t.p,{children:`Точное поведение:`}),`
|
|
227
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
228
|
+
`,(0,c.jsxs)(t.li,{children:[`значение `,(0,c.jsx)(t.code,{children:`item[key]`}),` преобразуется через `,(0,c.jsx)(t.code,{children:`String`}),`;`]}),`
|
|
229
|
+
`,(0,c.jsx)(t.li,{children:`элементы внутри каждой группы остаются в исходном порядке;`}),`
|
|
230
|
+
`,(0,c.jsx)(t.li,{children:`одинаковые строковые ключи попадают в одну группу;`}),`
|
|
231
|
+
`,(0,c.jsxs)(t.li,{children:[`пустой входной массив возвращает `,(0,c.jsx)(t.code,{children:`{}`}),`;`]}),`
|
|
232
|
+
`,(0,c.jsx)(t.li,{children:`внешний объект и массивы групп новые;`}),`
|
|
233
|
+
`,(0,c.jsx)(t.li,{children:`сами элементы не копируются.`}),`
|
|
234
|
+
`]}),`
|
|
235
|
+
`,(0,c.jsxs)(t.p,{children:[`Преобразование через `,(0,c.jsx)(t.code,{children:`String`}),` означает, что разные исходные типы могут стать одним ключом:`]}),`
|
|
236
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const rows = [
|
|
237
|
+
{ value: "строка", group: 1 },
|
|
238
|
+
{ value: "число", group: "1" }
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
const grouped = arrayGroupBy(rows, "group");
|
|
242
|
+
|
|
243
|
+
console.log(grouped["1"].length); // 2
|
|
244
|
+
`})}),`
|
|
245
|
+
`,(0,c.jsx)(t.p,{children:`Не используйте для группировки сложный объект:`}),`
|
|
246
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const rows = [
|
|
247
|
+
{ id: 1, group: { code: "A" } },
|
|
248
|
+
{ id: 2, group: { code: "B" } }
|
|
249
|
+
];
|
|
250
|
+
|
|
251
|
+
// Оба объекта обычно превратятся в строку "[object Object]".
|
|
252
|
+
const grouped = arrayGroupBy(rows, "group");
|
|
253
|
+
`})}),`
|
|
254
|
+
`,(0,c.jsx)(t.p,{children:`Выбирайте строковое, числовое или boolean-поле с однозначным строковым представлением.`}),`
|
|
255
|
+
`,(0,c.jsx)(t.h3,{id:`arraygroupbytoarray`,children:(0,c.jsx)(t.code,{children:`arrayGroupByToArray`})}),`
|
|
256
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
257
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function arrayGroupByToArray<T>(
|
|
258
|
+
array: readonly T[],
|
|
259
|
+
key: keyof T
|
|
260
|
+
): Array<{
|
|
261
|
+
key: string;
|
|
262
|
+
items: T[];
|
|
263
|
+
}>;
|
|
264
|
+
`})}),`
|
|
265
|
+
`,(0,c.jsxs)(t.p,{children:[`Функция выполняет ту же группировку, что `,(0,c.jsx)(t.code,{children:`arrayGroupBy`}),`, но возвращает массив групп. Такой результат удобен для `,(0,c.jsx)(t.code,{children:`.map()`}),` в UI.`]}),`
|
|
266
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const tasks = [
|
|
267
|
+
{ id: 1, status: "new" },
|
|
268
|
+
{ id: 2, status: "done" },
|
|
269
|
+
{ id: 3, status: "new" }
|
|
270
|
+
];
|
|
271
|
+
|
|
272
|
+
const groups = arrayGroupByToArray(tasks, "status");
|
|
273
|
+
|
|
274
|
+
console.log(groups);
|
|
275
|
+
// [
|
|
276
|
+
// {
|
|
277
|
+
// key: "new",
|
|
278
|
+
// items: [
|
|
279
|
+
// { id: 1, status: "new" },
|
|
280
|
+
// { id: 3, status: "new" }
|
|
281
|
+
// ]
|
|
282
|
+
// },
|
|
283
|
+
// {
|
|
284
|
+
// key: "done",
|
|
285
|
+
// items: [
|
|
286
|
+
// { id: 2, status: "done" }
|
|
287
|
+
// ]
|
|
288
|
+
// }
|
|
289
|
+
// ]
|
|
290
|
+
`})}),`
|
|
291
|
+
`,(0,c.jsx)(t.p,{children:`Пример React-рендера:`}),`
|
|
292
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`const groups = arrayGroupByToArray(tasks, "status");
|
|
293
|
+
|
|
294
|
+
return groups.map((group) => (
|
|
295
|
+
<section key={group.key}>
|
|
296
|
+
<h2>{group.key}</h2>
|
|
297
|
+
<ul>
|
|
298
|
+
{group.items.map((task) => (
|
|
299
|
+
<li key={task.id}>{task.id}</li>
|
|
300
|
+
))}
|
|
301
|
+
</ul>
|
|
302
|
+
</section>
|
|
303
|
+
));
|
|
304
|
+
`})}),`
|
|
305
|
+
`,(0,c.jsxs)(t.p,{children:[`Важно: порядок элементов внутри каждой группы сохраняется. Порядок самих групп следует правилам перечисления свойств обычного JavaScript-объекта. Строковые ключи вроде `,(0,c.jsx)(t.code,{children:`"new"`}),` и `,(0,c.jsx)(t.code,{children:`"done"`}),` обычно сохраняют порядок первого появления, но ключи, похожие на неотрицательные целые числа, перечисляются по возрастанию:`]}),`
|
|
306
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const rows = [{ group: "10" }, { group: "2" }, { group: "A" }];
|
|
307
|
+
|
|
308
|
+
console.log(arrayGroupByToArray(rows, "group").map((group) => group.key));
|
|
309
|
+
// ["2", "10", "A"], а не ["10", "2", "A"].
|
|
310
|
+
`})}),`
|
|
311
|
+
`,(0,c.jsxs)(t.p,{children:[`Если порядок групп является бизнес-правилом, сортируйте готовый массив явно или используйте собственную группировку через `,(0,c.jsx)(t.code,{children:`Map`}),`.`]}),`
|
|
312
|
+
`,(0,c.jsx)(t.h3,{id:`arraytomap`,children:(0,c.jsx)(t.code,{children:`arrayToMap`})}),`
|
|
313
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
314
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function arrayToMap<T>(array: readonly T[], key: keyof T): Record<string, T>;
|
|
315
|
+
`})}),`
|
|
316
|
+
`,(0,c.jsxs)(t.p,{children:[`Несмотря на имя, функция возвращает не экземпляр JavaScript `,(0,c.jsx)(t.code,{children:`Map`}),`, а обычный объект-словарь.`]}),`
|
|
317
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const products = [
|
|
318
|
+
{ id: "P-1", name: "Стол" },
|
|
319
|
+
{ id: "P-2", name: "Стул" }
|
|
320
|
+
];
|
|
321
|
+
|
|
322
|
+
const productsById = arrayToMap(products, "id");
|
|
323
|
+
|
|
324
|
+
console.log(productsById["P-2"]);
|
|
325
|
+
// { id: "P-2", name: "Стул" }
|
|
326
|
+
`})}),`
|
|
327
|
+
`,(0,c.jsx)(t.p,{children:`Повторный ключ не перезаписывает первое значение:`}),`
|
|
328
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const rows = [
|
|
329
|
+
{ id: "A", version: 1 },
|
|
330
|
+
{ id: "A", version: 2 }
|
|
331
|
+
];
|
|
332
|
+
|
|
333
|
+
console.log(arrayToMap(rows, "id")["A"].version); // 1
|
|
334
|
+
`})}),`
|
|
335
|
+
`,(0,c.jsx)(t.p,{children:`Точное поведение:`}),`
|
|
336
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
337
|
+
`,(0,c.jsxs)(t.li,{children:[`ключ преобразуется через `,(0,c.jsx)(t.code,{children:`String`}),`;`]}),`
|
|
338
|
+
`,(0,c.jsx)(t.li,{children:`сохраняется первый элемент с каждым строковым ключом;`}),`
|
|
339
|
+
`,(0,c.jsxs)(t.li,{children:[`пустой массив возвращает `,(0,c.jsx)(t.code,{children:`{}`}),`;`]}),`
|
|
340
|
+
`,(0,c.jsx)(t.li,{children:`результат новый, элементы не копируются;`}),`
|
|
341
|
+
`,(0,c.jsxs)(t.li,{children:[`поиск выполняется через квадратные скобки: `,(0,c.jsx)(t.code,{children:`result[id]`}),`;`]}),`
|
|
342
|
+
`,(0,c.jsxs)(t.li,{children:[`отсутствующий ключ во время выполнения даёт `,(0,c.jsx)(t.code,{children:`undefined`}),`, хотя тип результата записан как `,(0,c.jsx)(t.code,{children:`Record<string, T>`}),`.`]}),`
|
|
343
|
+
`]}),`
|
|
344
|
+
`,(0,c.jsx)(t.p,{children:`Безопасно проверяйте наличие значения:`}),`
|
|
345
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const product = productsById[selectedId];
|
|
346
|
+
|
|
347
|
+
if (product) {
|
|
348
|
+
console.log(product.name);
|
|
349
|
+
}
|
|
350
|
+
`})}),`
|
|
351
|
+
`,(0,c.jsxs)(t.p,{children:[`Для произвольных внешних ключей предпочитайте настоящий `,(0,c.jsx)(t.code,{children:`Map`}),`, потому что `,(0,c.jsx)(t.code,{children:`arrayToMap`}),`, `,(0,c.jsx)(t.code,{children:`arrayGroupBy`}),` и `,(0,c.jsx)(t.code,{children:`arrayGroupByToArray`}),` строят обычный объект. Значения вроде `,(0,c.jsx)(t.code,{children:`"__proto__"`}),`, `,(0,c.jsx)(t.code,{children:`"constructor"`}),` и `,(0,c.jsx)(t.code,{children:`"toString"`}),` пересекаются со специальными свойствами прототипа объекта и могут привести к неправильному результату или runtime-ошибке.`]}),`
|
|
352
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Хороший вход: заранее проверенные технические ID.
|
|
353
|
+
const productsById = arrayToMap(products, "id");
|
|
354
|
+
|
|
355
|
+
// Для произвольного пользовательского ключа безопаснее Map.
|
|
356
|
+
const productsByExternalKey = new Map(products.map((product) => [product.externalKey, product]));
|
|
357
|
+
`})}),`
|
|
358
|
+
`,(0,c.jsx)(t.h2,{id:`удаление-дубликатов`,children:`Удаление дубликатов`}),`
|
|
359
|
+
`,(0,c.jsx)(t.h3,{id:`arrayuniqueby`,children:(0,c.jsx)(t.code,{children:`arrayUniqueBy`})}),`
|
|
360
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
361
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function arrayUniqueBy<T>(array: readonly T[], key: keyof T): T[];
|
|
362
|
+
`})}),`
|
|
363
|
+
`,(0,c.jsx)(t.p,{children:`Функция оставляет первый объект для каждого уникального строкового представления выбранного свойства.`}),`
|
|
364
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const rows = [
|
|
365
|
+
{ id: "A", value: 1 },
|
|
366
|
+
{ id: "B", value: 2 },
|
|
367
|
+
{ id: "A", value: 3 }
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
const uniqueRows = arrayUniqueBy(rows, "id");
|
|
371
|
+
|
|
372
|
+
console.log(uniqueRows);
|
|
373
|
+
// [
|
|
374
|
+
// { id: "A", value: 1 },
|
|
375
|
+
// { id: "B", value: 2 }
|
|
376
|
+
// ]
|
|
377
|
+
`})}),`
|
|
378
|
+
`,(0,c.jsx)(t.p,{children:`Точное поведение:`}),`
|
|
379
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
380
|
+
`,(0,c.jsx)(t.li,{children:`порядок первых вхождений сохраняется;`}),`
|
|
381
|
+
`,(0,c.jsx)(t.li,{children:`исходный массив не изменяется;`}),`
|
|
382
|
+
`,(0,c.jsx)(t.li,{children:`элементы не копируются;`}),`
|
|
383
|
+
`,(0,c.jsx)(t.li,{children:`пустой массив возвращает новый пустой массив;`}),`
|
|
384
|
+
`,(0,c.jsxs)(t.li,{children:[`ключ сравнивается после `,(0,c.jsx)(t.code,{children:`String(item[key])`}),`;`]}),`
|
|
385
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`"A"`}),` и `,(0,c.jsx)(t.code,{children:`"a"`}),` считаются разными;`]}),`
|
|
386
|
+
`,(0,c.jsxs)(t.li,{children:[`число `,(0,c.jsx)(t.code,{children:`1`}),` и строка `,(0,c.jsx)(t.code,{children:`"1"`}),` считаются одним ключом;`]}),`
|
|
387
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`null`}),` превращается в `,(0,c.jsx)(t.code,{children:`"null"`}),`, а `,(0,c.jsx)(t.code,{children:`undefined`}),` — в `,(0,c.jsx)(t.code,{children:`"undefined"`}),`.`]}),`
|
|
388
|
+
`]}),`
|
|
389
|
+
`,(0,c.jsxs)(t.p,{children:[`Функция подходит для объектов, когда уникальность определяется конкретным полем. Для массива примитивов используйте `,(0,c.jsx)(t.code,{children:`arrayDeduplicate`}),`.`]}),`
|
|
390
|
+
`,(0,c.jsx)(t.h3,{id:`arraydeduplicate`,children:(0,c.jsx)(t.code,{children:`arrayDeduplicate`})}),`
|
|
391
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
392
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function arrayDeduplicate<T>(array: readonly T[]): T[];
|
|
393
|
+
`})}),`
|
|
394
|
+
`,(0,c.jsx)(t.p,{children:`Функция удаляет повторяющиеся значения и сохраняет первое вхождение.`}),`
|
|
395
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const ids = ["A", "B", "A", "C", "B"];
|
|
396
|
+
|
|
397
|
+
console.log(arrayDeduplicate(ids));
|
|
398
|
+
// ["A", "B", "C"]
|
|
399
|
+
`})}),`
|
|
400
|
+
`,(0,c.jsx)(t.p,{children:`Для примитивов сравниваются сами значения:`}),`
|
|
401
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(arrayDeduplicate([1, 2, 1, 3])); // [1, 2, 3]
|
|
402
|
+
console.log(arrayDeduplicate([true, false, true])); // [true, false]
|
|
403
|
+
console.log(arrayDeduplicate([Number.NaN, Number.NaN])); // [NaN]
|
|
404
|
+
`})}),`
|
|
405
|
+
`,(0,c.jsx)(t.p,{children:`Для объектов сравниваются ссылки, а не поля:`}),`
|
|
406
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const shared = { id: "A" };
|
|
407
|
+
|
|
408
|
+
console.log(arrayDeduplicate([shared, shared]).length); // 1
|
|
409
|
+
console.log(arrayDeduplicate([{ id: "A" }, { id: "A" }]).length); // 2
|
|
410
|
+
`})}),`
|
|
411
|
+
`,(0,c.jsxs)(t.p,{children:[`Если нужно удалить дубликаты объектов по `,(0,c.jsx)(t.code,{children:`id`}),`, используйте:`]}),`
|
|
412
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`arrayUniqueBy(objects, "id");
|
|
413
|
+
`})}),`
|
|
414
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`arrayDeduplicate`}),` использует правила равенства `,(0,c.jsx)(t.code,{children:`Set`}),`:`]}),`
|
|
415
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
416
|
+
`,(0,c.jsx)(t.li,{children:`одинаковые примитивы считаются дублями;`}),`
|
|
417
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`NaN`}),` считается равным `,(0,c.jsx)(t.code,{children:`NaN`}),`;`]}),`
|
|
418
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`0`}),` и `,(0,c.jsx)(t.code,{children:`-0`}),` считаются одним значением;`]}),`
|
|
419
|
+
`,(0,c.jsx)(t.li,{children:`объекты считаются одинаковыми только при совпадении ссылки.`}),`
|
|
420
|
+
`]}),`
|
|
421
|
+
`,(0,c.jsxs)(t.h2,{id:`работа-с-идентификаторами-и-map`,children:[`Работа с идентификаторами и `,(0,c.jsx)(t.code,{children:`Map`})]}),`
|
|
422
|
+
`,(0,c.jsx)(t.h3,{id:`filteranddeduplicateids`,children:(0,c.jsx)(t.code,{children:`filterAndDeduplicateIds`})}),`
|
|
423
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
424
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function filterAndDeduplicateIds<TId extends string>(ids: readonly string[] | undefined, allowedIds: readonly TId[]): TId[];
|
|
425
|
+
`})}),`
|
|
426
|
+
`,(0,c.jsx)(t.p,{children:`Функция очищает список идентификаторов по разрешённому набору:`}),`
|
|
427
|
+
`,(0,c.jsxs)(t.ol,{children:[`
|
|
428
|
+
`,(0,c.jsxs)(t.li,{children:[`сохраняет только ID, которые есть в `,(0,c.jsx)(t.code,{children:`allowedIds`}),`;`]}),`
|
|
429
|
+
`,(0,c.jsxs)(t.li,{children:[`удаляет пустую строку `,(0,c.jsx)(t.code,{children:`""`}),`;`]}),`
|
|
430
|
+
`,(0,c.jsx)(t.li,{children:`удаляет повторы;`}),`
|
|
431
|
+
`,(0,c.jsxs)(t.li,{children:[`сохраняет порядок первого появления в `,(0,c.jsx)(t.code,{children:`ids`}),`.`]}),`
|
|
432
|
+
`]}),`
|
|
433
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const savedOrder = ["D", "B", "UNKNOWN", "B", ""];
|
|
434
|
+
const allowedIds = ["A", "B", "C", "D"] as const;
|
|
435
|
+
|
|
436
|
+
const validOrder = filterAndDeduplicateIds(savedOrder, allowedIds);
|
|
437
|
+
|
|
438
|
+
console.log(validOrder); // ["D", "B"]
|
|
439
|
+
`})}),`
|
|
440
|
+
`,(0,c.jsxs)(t.p,{children:[`Если `,(0,c.jsx)(t.code,{children:`ids`}),` равен `,(0,c.jsx)(t.code,{children:`undefined`}),`, функция возвращает пустой массив:`]}),`
|
|
441
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(filterAndDeduplicateIds(undefined, ["A", "B"]));
|
|
442
|
+
// []
|
|
443
|
+
`})}),`
|
|
444
|
+
`,(0,c.jsxs)(t.p,{children:[`Функция не вызывает `,(0,c.jsx)(t.code,{children:`trim`}),`:`]}),`
|
|
445
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(filterAndDeduplicateIds([" A "], ["A"]));
|
|
446
|
+
// []
|
|
447
|
+
`})}),`
|
|
448
|
+
`,(0,c.jsxs)(t.p,{children:[`Если вход может содержать пробелы, сначала вызовите `,(0,c.jsx)(t.code,{children:`normalizeStringArray`}),`:`]}),`
|
|
449
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const normalizedIds = normalizeStringArray([" A ", "B "]);
|
|
450
|
+
const validIds = filterAndDeduplicateIds(normalizedIds, ["A", "B"]);
|
|
451
|
+
|
|
452
|
+
console.log(validIds); // ["A", "B"]
|
|
453
|
+
`})}),`
|
|
454
|
+
`,(0,c.jsxs)(t.p,{children:[`Сравнение чувствительно к регистру. `,(0,c.jsx)(t.code,{children:`"a"`}),` не совпадает с `,(0,c.jsx)(t.code,{children:`"A"`}),`.`]}),`
|
|
455
|
+
`,(0,c.jsxs)(t.p,{children:[`Generic `,(0,c.jsx)(t.code,{children:`TId`}),` сохраняет точный union разрешённых значений:`]}),`
|
|
456
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const allowedIds = ["name", "email", "phone"] as const;
|
|
457
|
+
const result = filterAndDeduplicateIds(["email", "unknown"], allowedIds);
|
|
458
|
+
|
|
459
|
+
// Тип result:
|
|
460
|
+
// Array<"name" | "email" | "phone">
|
|
461
|
+
`})}),`
|
|
462
|
+
`,(0,c.jsx)(t.h3,{id:`appendmissingids`,children:(0,c.jsx)(t.code,{children:`appendMissingIds`})}),`
|
|
463
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
464
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function appendMissingIds<TId extends string>(baseIds: readonly TId[], idsToAppend: readonly TId[]): TId[];
|
|
465
|
+
`})}),`
|
|
466
|
+
`,(0,c.jsxs)(t.p,{children:[`Функция создаёт копию `,(0,c.jsx)(t.code,{children:`baseIds`}),`, затем добавляет в конец непустые ID из `,(0,c.jsx)(t.code,{children:`idsToAppend`}),`, которых ещё нет в результате.`]}),`
|
|
467
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = appendMissingIds(["D", "B"], ["A", "B", "C", "D"]);
|
|
468
|
+
|
|
469
|
+
console.log(result); // ["D", "B", "A", "C"]
|
|
470
|
+
`})}),`
|
|
471
|
+
`,(0,c.jsx)(t.p,{children:`Порядок:`}),`
|
|
472
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
473
|
+
`,(0,c.jsxs)(t.li,{children:[`существующий порядок `,(0,c.jsx)(t.code,{children:`baseIds`}),` сохраняется;`]}),`
|
|
474
|
+
`,(0,c.jsxs)(t.li,{children:[`новые ID добавляются в порядке `,(0,c.jsx)(t.code,{children:`idsToAppend`}),`;`]}),`
|
|
475
|
+
`,(0,c.jsxs)(t.li,{children:[`ID, уже встреченный в `,(0,c.jsx)(t.code,{children:`baseIds`}),` или ранее добавленный из `,(0,c.jsx)(t.code,{children:`idsToAppend`}),`, повторно не добавляется.`]}),`
|
|
476
|
+
`]}),`
|
|
477
|
+
`,(0,c.jsxs)(t.p,{children:[`Важно: функция не очищает сам `,(0,c.jsx)(t.code,{children:`baseIds`}),`. Уже существующие там пустые строки и дубли сохраняются:`]}),`
|
|
478
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = appendMissingIds(["A", "A", ""], ["A", "B", ""]);
|
|
479
|
+
|
|
480
|
+
console.log(result); // ["A", "A", "", "B"]
|
|
481
|
+
`})}),`
|
|
482
|
+
`,(0,c.jsxs)(t.p,{children:[`Если нужно очистить базовый список, сначала используйте `,(0,c.jsx)(t.code,{children:`filterAndDeduplicateIds`}),`:`]}),`
|
|
483
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const allowedIds = ["A", "B", "C"] as const;
|
|
484
|
+
const cleanBase = filterAndDeduplicateIds(savedIds, allowedIds);
|
|
485
|
+
const completeOrder = appendMissingIds(cleanBase, allowedIds);
|
|
486
|
+
`})}),`
|
|
487
|
+
`,(0,c.jsx)(t.h3,{id:`pickexistingmapvalues`,children:(0,c.jsx)(t.code,{children:`pickExistingMapValues`})}),`
|
|
488
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
489
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function pickExistingMapValues<TKey, TValue>(keys: readonly TKey[], valuesByKey: ReadonlyMap<TKey, TValue>): TValue[];
|
|
490
|
+
`})}),`
|
|
491
|
+
`,(0,c.jsxs)(t.p,{children:[`Функция последовательно проходит по `,(0,c.jsx)(t.code,{children:`keys`}),`, берёт значения из `,(0,c.jsx)(t.code,{children:`Map`}),` и возвращает их в порядке ключей. Отсутствующие ключи пропускаются.`]}),`
|
|
492
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const usersById = new Map([
|
|
493
|
+
["A", { id: "A", name: "Анна" }],
|
|
494
|
+
["B", { id: "B", name: "Иван" }],
|
|
495
|
+
["C", { id: "C", name: "Ольга" }]
|
|
496
|
+
]);
|
|
497
|
+
|
|
498
|
+
const users = pickExistingMapValues(["C", "UNKNOWN", "A"], usersById);
|
|
499
|
+
|
|
500
|
+
console.log(users.map((user) => user.id)); // ["C", "A"]
|
|
501
|
+
`})}),`
|
|
502
|
+
`,(0,c.jsx)(t.p,{children:`Точное поведение:`}),`
|
|
503
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
504
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`valuesByKey`}),` не изменяется;`]}),`
|
|
505
|
+
`,(0,c.jsx)(t.li,{children:`результат — новый массив;`}),`
|
|
506
|
+
`,(0,c.jsxs)(t.li,{children:[`порядок задаёт именно `,(0,c.jsx)(t.code,{children:`keys`}),`, а не порядок вставки в `,(0,c.jsx)(t.code,{children:`Map`}),`;`]}),`
|
|
507
|
+
`,(0,c.jsx)(t.li,{children:`повторный ключ даёт повторное значение;`}),`
|
|
508
|
+
`,(0,c.jsx)(t.li,{children:`отсутствующий ключ пропускается;`}),`
|
|
509
|
+
`,(0,c.jsxs)(t.li,{children:[`значение `,(0,c.jsx)(t.code,{children:`undefined`}),` пропускается, даже если такой ключ существует в `,(0,c.jsx)(t.code,{children:`Map`}),`;`]}),`
|
|
510
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`null`}),`, `,(0,c.jsx)(t.code,{children:`false`}),`, `,(0,c.jsx)(t.code,{children:`0`}),` и пустая строка являются допустимыми значениями и не пропускаются.`]}),`
|
|
511
|
+
`]}),`
|
|
512
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const values = new Map<string, number | undefined>([
|
|
513
|
+
["A", 0],
|
|
514
|
+
["B", undefined],
|
|
515
|
+
["C", 3]
|
|
516
|
+
]);
|
|
517
|
+
|
|
518
|
+
console.log(pickExistingMapValues(["A", "B", "A", "C"], values));
|
|
519
|
+
// [0, 0, 3]
|
|
520
|
+
`})}),`
|
|
521
|
+
`,(0,c.jsxs)(t.p,{children:[`Для объектных ключей `,(0,c.jsx)(t.code,{children:`Map`}),` сравнивает ссылки:`]}),`
|
|
522
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const key = { id: "A" };
|
|
523
|
+
const values = new Map([[key, "значение"]]);
|
|
524
|
+
|
|
525
|
+
console.log(pickExistingMapValues([key], values)); // ["значение"]
|
|
526
|
+
console.log(pickExistingMapValues([{ id: "A" }], values)); // []
|
|
527
|
+
`})}),`
|
|
528
|
+
`,(0,c.jsx)(t.h2,{id:`сравнение-массивов`,children:`Сравнение массивов`}),`
|
|
529
|
+
`,(0,c.jsx)(t.h3,{id:`arraysequal`,children:(0,c.jsx)(t.code,{children:`arraysEqual`})}),`
|
|
530
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
531
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function arraysEqual<T>(left: readonly T[], right: readonly T[]): boolean;
|
|
532
|
+
`})}),`
|
|
533
|
+
`,(0,c.jsxs)(t.p,{children:[`Функция возвращает `,(0,c.jsx)(t.code,{children:`true`}),`, только если:`]}),`
|
|
534
|
+
`,(0,c.jsxs)(t.ol,{children:[`
|
|
535
|
+
`,(0,c.jsx)(t.li,{children:`длина массивов одинакова;`}),`
|
|
536
|
+
`,(0,c.jsx)(t.li,{children:`значения находятся в одинаковом порядке;`}),`
|
|
537
|
+
`,(0,c.jsxs)(t.li,{children:[`каждая пара элементов проходит строгое сравнение `,(0,c.jsx)(t.code,{children:`!==`}),`.`]}),`
|
|
538
|
+
`]}),`
|
|
539
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(arraysEqual(["A", "B"], ["A", "B"])); // true
|
|
540
|
+
console.log(arraysEqual(["A", "B"], ["B", "A"])); // false
|
|
541
|
+
console.log(arraysEqual(["A"], ["A", "B"])); // false
|
|
542
|
+
`})}),`
|
|
543
|
+
`,(0,c.jsx)(t.p,{children:`Объекты сравниваются по ссылке:`}),`
|
|
544
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const shared = { id: "A" };
|
|
545
|
+
|
|
546
|
+
console.log(arraysEqual([shared], [shared])); // true
|
|
547
|
+
console.log(arraysEqual([{ id: "A" }], [{ id: "A" }])); // false
|
|
548
|
+
`})}),`
|
|
549
|
+
`,(0,c.jsx)(t.p,{children:`Функция не подходит для глубокого сравнения объектов:`}),`
|
|
550
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const left = [{ id: "A", settings: { visible: true } }];
|
|
551
|
+
const right = [{ id: "A", settings: { visible: true } }];
|
|
552
|
+
|
|
553
|
+
console.log(arraysEqual(left, right)); // false
|
|
554
|
+
`})}),`
|
|
555
|
+
`,(0,c.jsx)(t.p,{children:`Дополнительные особенности строгого сравнения:`}),`
|
|
556
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
557
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`0`}),` и `,(0,c.jsx)(t.code,{children:`-0`}),` считаются равными;`]}),`
|
|
558
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`NaN`}),` не считается равным `,(0,c.jsx)(t.code,{children:`NaN`}),`;`]}),`
|
|
559
|
+
`,(0,c.jsxs)(t.li,{children:[`пустая позиция разреженного массива и явный `,(0,c.jsx)(t.code,{children:`undefined`}),` на той же позиции будут прочитаны как `,(0,c.jsx)(t.code,{children:`undefined`}),` и могут считаться равными.`]}),`
|
|
560
|
+
`]}),`
|
|
561
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(arraysEqual([Number.NaN], [Number.NaN])); // false
|
|
562
|
+
`})}),`
|
|
563
|
+
`,(0,c.jsx)(t.p,{children:`Типовые применения:`}),`
|
|
564
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
565
|
+
`,(0,c.jsx)(t.li,{children:`сравнение массивов строковых ID;`}),`
|
|
566
|
+
`,(0,c.jsx)(t.li,{children:`проверка, изменился ли порядок колонок;`}),`
|
|
567
|
+
`,(0,c.jsx)(t.li,{children:`сравнение списков примитивных значений;`}),`
|
|
568
|
+
`,(0,c.jsx)(t.li,{children:`сравнение массивов стабильных ссылок из одного cache snapshot.`}),`
|
|
569
|
+
`]}),`
|
|
570
|
+
`,(0,c.jsx)(t.h2,{id:`перемещение-элементов`,children:`Перемещение элементов`}),`
|
|
571
|
+
`,(0,c.jsx)(t.h3,{id:`индексы-и-общие-гарантии`,children:`Индексы и общие гарантии`}),`
|
|
572
|
+
`,(0,c.jsx)(t.p,{children:`Модуль предоставляет три функции перемещения:`}),`
|
|
573
|
+
`,(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:`moveItem`})}),(0,c.jsxs)(t.td,{children:[`Числовыми индексами `,(0,c.jsx)(t.code,{children:`from`}),` и `,(0,c.jsx)(t.code,{children:`to`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`moveArrayItem`})}),(0,c.jsxs)(t.td,{children:[`Числовыми индексами `,(0,c.jsx)(t.code,{children:`fromIndex`}),` и `,(0,c.jsx)(t.code,{children:`toIndex`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`moveArrayItemByIndex`})}),(0,c.jsxs)(t.td,{children:[`Исходным `,(0,c.jsx)(t.code,{children:`index`}),` и действием `,(0,c.jsx)(t.code,{children:`start/end/up/down`}),`.`]})]})]})]}),`
|
|
574
|
+
`,(0,c.jsxs)(t.p,{children:[`Для обычного массива без элементов `,(0,c.jsx)(t.code,{children:`undefined`}),`:`]}),`
|
|
575
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
576
|
+
`,(0,c.jsx)(t.li,{children:`исходный массив не изменяется;`}),`
|
|
577
|
+
`,(0,c.jsx)(t.li,{children:`возвращается новый массив;`}),`
|
|
578
|
+
`,(0,c.jsx)(t.li,{children:`остальные элементы сохраняют относительный порядок;`}),`
|
|
579
|
+
`,(0,c.jsxs)(t.li,{children:[`целый индекс меньше `,(0,c.jsx)(t.code,{children:`0`}),` или не меньше длины считается некорректным;`]}),`
|
|
580
|
+
`,(0,c.jsx)(t.li,{children:`одинаковые исходный и целевой индексы дают копию без перестановки.`}),`
|
|
581
|
+
`]}),`
|
|
582
|
+
`,(0,c.jsxs)(t.p,{children:[`Передавайте только конечные целые индексы: `,(0,c.jsx)(t.code,{children:`0`}),`, `,(0,c.jsx)(t.code,{children:`1`}),`, `,(0,c.jsx)(t.code,{children:`2`}),` и так далее. Дробные значения, `,(0,c.jsx)(t.code,{children:`NaN`}),` и `,(0,c.jsx)(t.code,{children:`Infinity`}),` не являются частью поддерживаемого контракта.`]}),`
|
|
583
|
+
`,(0,c.jsx)(t.h3,{id:`moveitem`,children:(0,c.jsx)(t.code,{children:`moveItem`})}),`
|
|
584
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
585
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function moveItem<T>(items: readonly T[], from: number, to: number): T[];
|
|
586
|
+
`})}),`
|
|
587
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = ["A", "B", "C", "D"];
|
|
588
|
+
|
|
589
|
+
console.log(moveItem(source, 0, 2));
|
|
590
|
+
// ["B", "C", "A", "D"]
|
|
591
|
+
|
|
592
|
+
console.log(moveItem(source, 3, 1));
|
|
593
|
+
// ["A", "D", "B", "C"]
|
|
594
|
+
|
|
595
|
+
console.log(source);
|
|
596
|
+
// ["A", "B", "C", "D"]
|
|
597
|
+
`})}),`
|
|
598
|
+
`,(0,c.jsx)(t.p,{children:`Некорректный индекс не вызывает исключение:`}),`
|
|
599
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = ["A", "B", "C"];
|
|
600
|
+
const result = moveItem(source, -1, 2);
|
|
601
|
+
|
|
602
|
+
console.log(result); // ["A", "B", "C"]
|
|
603
|
+
console.log(result === source); // false
|
|
604
|
+
`})}),`
|
|
605
|
+
`,(0,c.jsx)(t.h3,{id:`movearrayitem`,children:(0,c.jsx)(t.code,{children:`moveArrayItem`})}),`
|
|
606
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
607
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function moveArrayItem<T>(items: readonly T[], fromIndex: number, toIndex: number): T[];
|
|
608
|
+
`})}),`
|
|
609
|
+
`,(0,c.jsxs)(t.p,{children:[`Для массивов с определёнными элементами поведение совпадает с `,(0,c.jsx)(t.code,{children:`moveItem`}),`. Имя `,(0,c.jsx)(t.code,{children:`moveArrayItem`}),` явно сообщает, что функция перемещает элемент массива.`]}),`
|
|
610
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const columns = ["name", "email", "phone"];
|
|
611
|
+
const nextColumns = moveArrayItem(columns, 2, 0);
|
|
612
|
+
|
|
613
|
+
console.log(nextColumns);
|
|
614
|
+
// ["phone", "name", "email"]
|
|
615
|
+
`})}),`
|
|
616
|
+
`,(0,c.jsx)(t.p,{children:`Пример с React state:`}),`
|
|
617
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`const [columnIds, setColumnIds] = useState(["name", "email", "phone"]);
|
|
618
|
+
|
|
619
|
+
function moveColumn(fromIndex: number, toIndex: number) {
|
|
620
|
+
setColumnIds((currentIds) => moveArrayItem(currentIds, fromIndex, toIndex));
|
|
621
|
+
}
|
|
622
|
+
`})}),`
|
|
623
|
+
`,(0,c.jsx)(t.h3,{id:`reorderaction`,children:(0,c.jsx)(t.code,{children:`ReorderAction`})}),`
|
|
624
|
+
`,(0,c.jsx)(t.p,{children:`Тип:`}),`
|
|
625
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type ReorderAction = "start" | "end" | "up" | "down";
|
|
626
|
+
`})}),`
|
|
627
|
+
`,(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:`"start"`})}),(0,c.jsxs)(t.td,{children:[`Переместить элемент на индекс `,(0,c.jsx)(t.code,{children:`0`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`"end"`})}),(0,c.jsx)(t.td,{children:`Переместить элемент на последний индекс.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`"up"`})}),(0,c.jsx)(t.td,{children:`Переместить элемент на одну позицию ближе к началу массива.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`"down"`})}),(0,c.jsx)(t.td,{children:`Переместить элемент на одну позицию ближе к концу массива.`})]})]})]}),`
|
|
628
|
+
`,(0,c.jsxs)(t.p,{children:[`Это техническое действие, а не направление на экране. Для вертикального списка `,(0,c.jsx)(t.code,{children:`"up"`}),` обычно означает визуально вверх, но для горизонтального списка интерпретация интерфейса остаётся ответственностью приложения.`]}),`
|
|
629
|
+
`,(0,c.jsx)(t.h3,{id:`movearrayitembyindex`,children:(0,c.jsx)(t.code,{children:`moveArrayItemByIndex`})}),`
|
|
630
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
631
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function moveArrayItemByIndex<T>(items: readonly T[], index: number, action: ReorderAction): T[];
|
|
632
|
+
`})}),`
|
|
633
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const items = ["A", "B", "C", "D"];
|
|
634
|
+
|
|
635
|
+
console.log(moveArrayItemByIndex(items, 2, "start"));
|
|
636
|
+
// ["C", "A", "B", "D"]
|
|
637
|
+
|
|
638
|
+
console.log(moveArrayItemByIndex(items, 1, "end"));
|
|
639
|
+
// ["A", "C", "D", "B"]
|
|
640
|
+
|
|
641
|
+
console.log(moveArrayItemByIndex(items, 2, "up"));
|
|
642
|
+
// ["A", "C", "B", "D"]
|
|
643
|
+
|
|
644
|
+
console.log(moveArrayItemByIndex(items, 1, "down"));
|
|
645
|
+
// ["A", "C", "B", "D"]
|
|
646
|
+
`})}),`
|
|
647
|
+
`,(0,c.jsx)(t.p,{children:`Действие на границе возвращает копию без перестановки:`}),`
|
|
648
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const items = ["A", "B", "C"];
|
|
649
|
+
|
|
650
|
+
console.log(moveArrayItemByIndex(items, 0, "up"));
|
|
651
|
+
// ["A", "B", "C"]
|
|
652
|
+
|
|
653
|
+
console.log(moveArrayItemByIndex(items, 2, "down"));
|
|
654
|
+
// ["A", "B", "C"]
|
|
655
|
+
`})}),`
|
|
656
|
+
`,(0,c.jsx)(t.p,{children:`Пример обработчика кнопок:`}),`
|
|
657
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function reorderColumn(columnIds: readonly string[], activeIndex: number, action: ReorderAction) {
|
|
658
|
+
return moveArrayItemByIndex(columnIds, activeIndex, action);
|
|
659
|
+
}
|
|
660
|
+
`})}),`
|
|
661
|
+
`,(0,c.jsxs)(t.h3,{id:`ограничение-для-undefined`,children:[`Ограничение для `,(0,c.jsx)(t.code,{children:`undefined`})]}),`
|
|
662
|
+
`,(0,c.jsxs)(t.p,{children:[`Функции перемещения предназначены для массивов, в которых каждый индекс содержит определённый элемент. Не используйте их для перемещения фактического значения `,(0,c.jsx)(t.code,{children:`undefined`}),` или разреженных массивов:`]}),`
|
|
663
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const unsupported = ["A", undefined, "C"];
|
|
664
|
+
`})}),`
|
|
665
|
+
`,(0,c.jsxs)(t.p,{children:[`Внутренняя проверка извлечённого элемента использует `,(0,c.jsx)(t.code,{children:`item === undefined`}),`. Из-за этого `,(0,c.jsx)(t.code,{children:`undefined`}),` нельзя отличить от отсутствующего элемента, а результат разных функций в таком сценарии не является надёжным контрактом. Сначала отфильтруйте или замените такие значения.`]}),`
|
|
666
|
+
`,(0,c.jsx)(t.h2,{id:`нормализация-строк-и-объектов`,children:`Нормализация строк и объектов`}),`
|
|
667
|
+
`,(0,c.jsx)(t.p,{children:`Нормализация — преобразование разных вариантов одного логического значения в единый канонический вид.`}),`
|
|
668
|
+
`,(0,c.jsxs)(t.p,{children:[`Например, строки `,(0,c.jsx)(t.code,{children:`" A "`}),`, `,(0,c.jsx)(t.code,{children:`"A"`}),` и повторная `,(0,c.jsx)(t.code,{children:`"A"`}),` после обрезки пробелов представляют один ID `,(0,c.jsx)(t.code,{children:`"A"`}),`.`]}),`
|
|
669
|
+
`,(0,c.jsx)(t.p,{children:`Нормализаторы изменяют представление данных. Поэтому вызывайте их на явно выбранной границе:`}),`
|
|
670
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
671
|
+
`,(0,c.jsx)(t.li,{children:`при восстановлении сохранённой конфигурации;`}),`
|
|
672
|
+
`,(0,c.jsx)(t.li,{children:`перед созданием save snapshot;`}),`
|
|
673
|
+
`,(0,c.jsx)(t.li,{children:`при принятии внешнего payload;`}),`
|
|
674
|
+
`,(0,c.jsx)(t.li,{children:`перед сравнением или построением identity, если это предусмотрено контрактом.`}),`
|
|
675
|
+
`]}),`
|
|
676
|
+
`,(0,c.jsx)(t.p,{children:`Не записывайте нормализованный результат обратно в пользовательский draft во время обычного ввода, если интерфейс должен сохранять введённое значение буквально.`}),`
|
|
677
|
+
`,(0,c.jsx)(t.h3,{id:`normalizestringarray`,children:(0,c.jsx)(t.code,{children:`normalizeStringArray`})}),`
|
|
678
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
679
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function normalizeStringArray(items: readonly string[] | undefined): string[] | undefined;
|
|
680
|
+
`})}),`
|
|
681
|
+
`,(0,c.jsx)(t.p,{children:`Функция:`}),`
|
|
682
|
+
`,(0,c.jsxs)(t.ol,{children:[`
|
|
683
|
+
`,(0,c.jsxs)(t.li,{children:[`применяет `,(0,c.jsx)(t.code,{children:`trim()`}),` к каждой строке;`]}),`
|
|
684
|
+
`,(0,c.jsxs)(t.li,{children:[`удаляет пустые строки после `,(0,c.jsx)(t.code,{children:`trim()`}),`;`]}),`
|
|
685
|
+
`,(0,c.jsxs)(t.li,{children:[`удаляет повторы после `,(0,c.jsx)(t.code,{children:`trim()`}),`;`]}),`
|
|
686
|
+
`,(0,c.jsx)(t.li,{children:`сохраняет первое вхождение и его порядок;`}),`
|
|
687
|
+
`,(0,c.jsxs)(t.li,{children:[`возвращает `,(0,c.jsx)(t.code,{children:`undefined`}),`, если полезных значений не осталось.`]}),`
|
|
688
|
+
`]}),`
|
|
689
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = normalizeStringArray([" A ", "", "A", "B ", " "]);
|
|
690
|
+
|
|
691
|
+
console.log(result); // ["A", "B"]
|
|
692
|
+
`})}),`
|
|
693
|
+
`,(0,c.jsx)(t.p,{children:`Пустые варианты:`}),`
|
|
694
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(normalizeStringArray(undefined)); // undefined
|
|
695
|
+
console.log(normalizeStringArray([])); // undefined
|
|
696
|
+
console.log(normalizeStringArray([" ", "\\t"])); // undefined
|
|
697
|
+
`})}),`
|
|
698
|
+
`,(0,c.jsx)(t.p,{children:`Регистр не меняется:`}),`
|
|
699
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(normalizeStringArray(["A", "a", " A "]));
|
|
700
|
+
// ["A", "a"]
|
|
701
|
+
`})}),`
|
|
702
|
+
`,(0,c.jsx)(t.p,{children:`Внутренние пробелы не схлопываются:`}),`
|
|
703
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(normalizeStringArray([" Новая группа "]));
|
|
704
|
+
// ["Новая группа"]
|
|
705
|
+
`})}),`
|
|
706
|
+
`,(0,c.jsx)(t.p,{children:`Если вызывающему коду всегда нужен массив:`}),`
|
|
707
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const ids = normalizeStringArray(rawIds) ?? [];
|
|
708
|
+
`})}),`
|
|
709
|
+
`,(0,c.jsxs)(t.p,{children:[`Если нужно сохранить различие между «значение отсутствует» и «передан пустой массив», не заменяйте `,(0,c.jsx)(t.code,{children:`undefined`}),` автоматически — выберите поведение на своей boundary.`]}),`
|
|
710
|
+
`,(0,c.jsx)(t.h3,{id:`normalizeobjects`,children:(0,c.jsx)(t.code,{children:`normalizeObjects`})}),`
|
|
711
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
712
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function normalizeObjects<T, K extends keyof T, O = T>(
|
|
713
|
+
items: readonly T[] | undefined,
|
|
714
|
+
key: K,
|
|
715
|
+
copyist?: ((item: T, normalizedKey: T[K]) => O) | false
|
|
716
|
+
): O[] | undefined;
|
|
717
|
+
`})}),`
|
|
718
|
+
`,(0,c.jsxs)(t.p,{children:[`Фактическая сигнатура третьего параметра допускает либо callback, либо отдельное значение `,(0,c.jsx)(t.code,{children:`false`}),`:`]}),`
|
|
719
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`copyist?: ((item: T, key: T[K]) => O) | false
|
|
720
|
+
`})}),`
|
|
721
|
+
`,(0,c.jsx)(t.p,{children:`Функция предназначена для объектов со строковым ключевым полем:`}),`
|
|
722
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type Item = {
|
|
723
|
+
id: string;
|
|
724
|
+
label: string;
|
|
725
|
+
};
|
|
726
|
+
`})}),`
|
|
727
|
+
`,(0,c.jsx)(t.p,{children:`Она:`}),`
|
|
728
|
+
`,(0,c.jsxs)(t.ol,{children:[`
|
|
729
|
+
`,(0,c.jsx)(t.li,{children:`читает выбранное поле;`}),`
|
|
730
|
+
`,(0,c.jsx)(t.li,{children:`принимает его только если это строка;`}),`
|
|
731
|
+
`,(0,c.jsxs)(t.li,{children:[`применяет `,(0,c.jsx)(t.code,{children:`trim()`}),`;`]}),`
|
|
732
|
+
`,(0,c.jsx)(t.li,{children:`удаляет объект с пустым ключом;`}),`
|
|
733
|
+
`,(0,c.jsx)(t.li,{children:`удаляет повтор по нормализованному ключу;`}),`
|
|
734
|
+
`,(0,c.jsx)(t.li,{children:`сохраняет первое вхождение;`}),`
|
|
735
|
+
`,(0,c.jsx)(t.li,{children:`создаёт результат выбранным способом;`}),`
|
|
736
|
+
`,(0,c.jsxs)(t.li,{children:[`возвращает `,(0,c.jsx)(t.code,{children:`undefined`}),`, если результат пуст.`]}),`
|
|
737
|
+
`]}),`
|
|
738
|
+
`,(0,c.jsxs)(t.p,{children:[`Числовое, boolean, объектное, `,(0,c.jsx)(t.code,{children:`null`}),` или `,(0,c.jsx)(t.code,{children:`undefined`}),` значение выбранного поля считается невалидным и удаляется. Несмотря на общий TypeScript generic, на практике `,(0,c.jsx)(t.code,{children:`key`}),` должен указывать на строковое поле.`]}),`
|
|
739
|
+
`,(0,c.jsx)(t.h4,{id:`режим-по-умолчанию-поверхностная-копия`,children:`Режим по умолчанию: поверхностная копия`}),`
|
|
740
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = [
|
|
741
|
+
{ id: " A ", label: "Первый" },
|
|
742
|
+
{ id: "", label: "Пустой" },
|
|
743
|
+
{ id: "A", label: "Дубликат" },
|
|
744
|
+
{ id: "B", label: "Второй" }
|
|
745
|
+
];
|
|
746
|
+
|
|
747
|
+
const result = normalizeObjects(source, "id");
|
|
748
|
+
|
|
749
|
+
console.log(result);
|
|
750
|
+
// [
|
|
751
|
+
// { id: " A ", label: "Первый" },
|
|
752
|
+
// { id: "B", label: "Второй" }
|
|
753
|
+
// ]
|
|
754
|
+
`})}),`
|
|
755
|
+
`,(0,c.jsxs)(t.p,{children:[`Обратите внимание: нормализованный ключ используется для проверки пустоты и дубликатов, но в стандартной поверхностной копии исходное поле не перезаписывается. Поэтому первый объект сохранил `,(0,c.jsx)(t.code,{children:`id: " A "`}),`.`]}),`
|
|
756
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(result?.[0] !== source[0]); // true
|
|
757
|
+
`})}),`
|
|
758
|
+
`,(0,c.jsx)(t.p,{children:`Вложенные объекты остаются общими:`}),`
|
|
759
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const settings = { visible: true };
|
|
760
|
+
const source = [{ id: "A", settings }];
|
|
761
|
+
const result = normalizeObjects(source, "id");
|
|
762
|
+
|
|
763
|
+
console.log(result?.[0].settings === settings); // true
|
|
764
|
+
`})}),`
|
|
765
|
+
`,(0,c.jsx)(t.h4,{id:`callback-построение-канонического-результата`,children:`Callback: построение канонического результата`}),`
|
|
766
|
+
`,(0,c.jsx)(t.p,{children:`Callback получает исходный объект и нормализованный ключ. Используйте его, если нужно записать нормализованное значение в результат или изменить форму объекта:`}),`
|
|
767
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = [
|
|
768
|
+
{ id: " A ", value: 1 },
|
|
769
|
+
{ id: "A", value: 2 },
|
|
770
|
+
{ id: " B ", value: 3 }
|
|
771
|
+
];
|
|
772
|
+
|
|
773
|
+
const result = normalizeObjects(source, "id", (item, normalizedId) => ({
|
|
774
|
+
id: normalizedId,
|
|
775
|
+
label: String(item.value)
|
|
776
|
+
}));
|
|
777
|
+
|
|
778
|
+
console.log(result);
|
|
779
|
+
// [
|
|
780
|
+
// { id: "A", label: "1" },
|
|
781
|
+
// { id: "B", label: "3" }
|
|
782
|
+
// ]
|
|
783
|
+
`})}),`
|
|
784
|
+
`,(0,c.jsx)(t.p,{children:`TypeScript выводит тип возвращаемых объектов из callback:`}),`
|
|
785
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Тип result:
|
|
786
|
+
// Array<{ id: string; label: string }> | undefined
|
|
787
|
+
`})}),`
|
|
788
|
+
`,(0,c.jsxs)(t.h4,{id:`copyist--false-сохранить-исходные-ссылки`,children:[(0,c.jsx)(t.code,{children:`copyist = false`}),`: сохранить исходные ссылки`]}),`
|
|
789
|
+
`,(0,c.jsxs)(t.p,{children:[`Если третьим аргументом передать `,(0,c.jsx)(t.code,{children:`false`}),`, функция не копирует сохранённые объекты:`]}),`
|
|
790
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = [{ id: "A", value: 1 }];
|
|
791
|
+
const result = normalizeObjects(source, "id", false);
|
|
792
|
+
|
|
793
|
+
console.log(result?.[0] === source[0]); // true
|
|
794
|
+
console.log(result === source); // false: внешний массив всё равно новый.
|
|
795
|
+
`})}),`
|
|
796
|
+
`,(0,c.jsx)(t.p,{children:`Используйте этот режим только когда общие ссылки являются ожидаемым поведением.`}),`
|
|
797
|
+
`,(0,c.jsx)(t.h4,{id:`пустой-результат`,children:`Пустой результат`}),`
|
|
798
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`console.log(normalizeObjects(undefined, "id")); // undefined
|
|
799
|
+
console.log(normalizeObjects([], "id")); // undefined
|
|
800
|
+
console.log(normalizeObjects([{ id: " " }], "id")); // undefined
|
|
801
|
+
`})}),`
|
|
802
|
+
`,(0,c.jsxs)(t.h4,{id:`частые-ошибки-с-normalizeobjects`,children:[`Частые ошибки с `,(0,c.jsx)(t.code,{children:`normalizeObjects`})]}),`
|
|
803
|
+
`,(0,c.jsx)(t.p,{children:`Неверно ожидать, что стандартный режим перезапишет ключ:`}),`
|
|
804
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = normalizeObjects([{ id: " A " }], "id");
|
|
805
|
+
|
|
806
|
+
console.log(result?.[0].id); // " A ", а не "A".
|
|
807
|
+
`})}),`
|
|
808
|
+
`,(0,c.jsx)(t.p,{children:`Для канонического ключа нужен callback:`}),`
|
|
809
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = normalizeObjects([{ id: " A " }], "id", (item, normalizedId) => ({
|
|
810
|
+
...item,
|
|
811
|
+
id: normalizedId
|
|
812
|
+
}));
|
|
813
|
+
|
|
814
|
+
console.log(result?.[0].id); // "A"
|
|
815
|
+
`})}),`
|
|
816
|
+
`,(0,c.jsx)(t.p,{children:`Неверно выбирать числовое поле:`}),`
|
|
817
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const source = [{ id: 1, label: "Первый" }];
|
|
818
|
+
const result = normalizeObjects(source, "id");
|
|
819
|
+
|
|
820
|
+
console.log(result); // undefined
|
|
821
|
+
`})}),`
|
|
822
|
+
`,(0,c.jsx)(t.p,{children:`Если уникальность должна определяться числом без строковой нормализации, используйте другую функцию или явный mapper, соответствующий вашему контракту.`}),`
|
|
823
|
+
`,(0,c.jsx)(t.h3,{id:`addunique`,children:(0,c.jsx)(t.code,{children:`addUnique`})}),`
|
|
824
|
+
`,(0,c.jsx)(t.p,{children:`Сигнатура:`}),`
|
|
825
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function addUnique(target: string[], seen: Set<string>, fieldId: string | undefined): void;
|
|
826
|
+
`})}),`
|
|
827
|
+
`,(0,c.jsx)(t.p,{children:`Это единственная намеренно мутирующая функция модуля. Она:`}),`
|
|
828
|
+
`,(0,c.jsxs)(t.ol,{children:[`
|
|
829
|
+
`,(0,c.jsxs)(t.li,{children:[`применяет `,(0,c.jsx)(t.code,{children:`trim()`}),` к `,(0,c.jsx)(t.code,{children:`fieldId`}),`;`]}),`
|
|
830
|
+
`,(0,c.jsxs)(t.li,{children:[`ничего не делает для `,(0,c.jsx)(t.code,{children:`undefined`}),` или пустой строки;`]}),`
|
|
831
|
+
`,(0,c.jsxs)(t.li,{children:[`проверяет нормализованный ID в `,(0,c.jsx)(t.code,{children:`seen`}),`;`]}),`
|
|
832
|
+
`,(0,c.jsxs)(t.li,{children:[`добавляет новый ID одновременно в `,(0,c.jsx)(t.code,{children:`seen`}),` и в конец `,(0,c.jsx)(t.code,{children:`target`}),`;`]}),`
|
|
833
|
+
`,(0,c.jsxs)(t.li,{children:[`возвращает `,(0,c.jsx)(t.code,{children:`void`}),`.`]}),`
|
|
834
|
+
`]}),`
|
|
835
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const target: string[] = [];
|
|
836
|
+
const seen = new Set<string>();
|
|
837
|
+
|
|
838
|
+
addUnique(target, seen, " A ");
|
|
839
|
+
addUnique(target, seen, "A");
|
|
840
|
+
addUnique(target, seen, " ");
|
|
841
|
+
addUnique(target, seen, "B");
|
|
842
|
+
|
|
843
|
+
console.log(target); // ["A", "B"]
|
|
844
|
+
console.log([...seen]); // ["A", "B"]
|
|
845
|
+
`})}),`
|
|
846
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`seen`}),` является источником истины для проверки дублей. Передавайте один и тот же `,(0,c.jsx)(t.code,{children:`Set`}),` на протяжении всей операции:`]}),`
|
|
847
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const target: string[] = [];
|
|
848
|
+
const seen = new Set<string>();
|
|
849
|
+
|
|
850
|
+
for (const field of fields) {
|
|
851
|
+
addUnique(target, seen, field.id);
|
|
852
|
+
}
|
|
853
|
+
`})}),`
|
|
854
|
+
`,(0,c.jsxs)(t.p,{children:[`Если `,(0,c.jsx)(t.code,{children:`target`}),` уже заполнен, сначала синхронизируйте `,(0,c.jsx)(t.code,{children:`seen`}),`:`]}),`
|
|
855
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const target = normalizeStringArray(existingIds) ?? [];
|
|
856
|
+
const seen = new Set(target);
|
|
857
|
+
|
|
858
|
+
for (const id of additionalIds) {
|
|
859
|
+
addUnique(target, seen, id);
|
|
860
|
+
}
|
|
861
|
+
`})}),`
|
|
862
|
+
`,(0,c.jsxs)(t.p,{children:[`Не создавайте новый `,(0,c.jsx)(t.code,{children:`Set`}),` при каждом вызове:`]}),`
|
|
863
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Неправильно: каждый вызов забывает ранее добавленные значения.
|
|
864
|
+
addUnique(target, new Set(), "A");
|
|
865
|
+
addUnique(target, new Set(), "A");
|
|
866
|
+
`})}),`
|
|
867
|
+
`,(0,c.jsxs)(t.p,{children:[`Для нормализации уже готового массива проще использовать `,(0,c.jsx)(t.code,{children:`normalizeStringArray`}),`.`]}),`
|
|
868
|
+
`,(0,c.jsx)(t.h2,{id:`готовые-рецепты`,children:`Готовые рецепты`}),`
|
|
869
|
+
`,(0,c.jsx)(t.h3,{id:`восстановить-сохранённый-порядок-и-дописать-новые-элементы`,children:`Восстановить сохранённый порядок и дописать новые элементы`}),`
|
|
870
|
+
`,(0,c.jsx)(t.p,{children:`Сценарий:`}),`
|
|
871
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
872
|
+
`,(0,c.jsx)(t.li,{children:`в сохранённой конфигурации есть порядок ID;`}),`
|
|
873
|
+
`,(0,c.jsx)(t.li,{children:`часть ID устарела;`}),`
|
|
874
|
+
`,(0,c.jsx)(t.li,{children:`появились новые доступные элементы;`}),`
|
|
875
|
+
`,(0,c.jsx)(t.li,{children:`на выходе нужны существующие элементы в восстановленном порядке.`}),`
|
|
876
|
+
`]}),`
|
|
877
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type Column = {
|
|
878
|
+
id: string;
|
|
879
|
+
label: string;
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
const columns: Column[] = [
|
|
883
|
+
{ id: "name", label: "Имя" },
|
|
884
|
+
{ id: "email", label: "E-mail" },
|
|
885
|
+
{ id: "phone", label: "Телефон" }
|
|
886
|
+
];
|
|
887
|
+
|
|
888
|
+
const savedOrder = [" phone ", "removed", "name", "name"];
|
|
889
|
+
|
|
890
|
+
const availableIds = columns.map((column) => column.id);
|
|
891
|
+
|
|
892
|
+
const normalizedSavedOrder = normalizeStringArray(savedOrder);
|
|
893
|
+
|
|
894
|
+
const validSavedOrder = filterAndDeduplicateIds(normalizedSavedOrder, availableIds);
|
|
895
|
+
|
|
896
|
+
const completeOrder = appendMissingIds(validSavedOrder, availableIds);
|
|
897
|
+
|
|
898
|
+
const columnsById = new Map(columns.map((column) => [column.id, column]));
|
|
899
|
+
|
|
900
|
+
const orderedColumns = pickExistingMapValues(completeOrder, columnsById);
|
|
901
|
+
|
|
902
|
+
console.log(completeOrder);
|
|
903
|
+
// ["phone", "name", "email"]
|
|
904
|
+
|
|
905
|
+
console.log(orderedColumns.map((column) => column.label));
|
|
906
|
+
// ["Телефон", "Имя", "E-mail"]
|
|
907
|
+
`})}),`
|
|
908
|
+
`,(0,c.jsx)(t.p,{children:`Каждый шаг имеет отдельную ответственность:`}),`
|
|
909
|
+
`,(0,c.jsxs)(t.ol,{children:[`
|
|
910
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`normalizeStringArray`}),` обрезает пробелы и удаляет пустые значения;`]}),`
|
|
911
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`filterAndDeduplicateIds`}),` удаляет неизвестные ID;`]}),`
|
|
912
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`appendMissingIds`}),` добавляет новые ID;`]}),`
|
|
913
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`pickExistingMapValues`}),` восстанавливает объекты в нужном порядке.`]}),`
|
|
914
|
+
`]}),`
|
|
915
|
+
`,(0,c.jsx)(t.h3,{id:`сгруппировать-данные-для-ui`,children:`Сгруппировать данные для UI`}),`
|
|
916
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const groups = arrayGroupByToArray(employees, "department");
|
|
917
|
+
|
|
918
|
+
const viewModel = groups.map((group) => ({
|
|
919
|
+
department: group.key,
|
|
920
|
+
count: group.items.length,
|
|
921
|
+
employees: group.items
|
|
922
|
+
}));
|
|
923
|
+
`})}),`
|
|
924
|
+
`,(0,c.jsx)(t.p,{children:`Если нужен обязательный порядок подразделений:`}),`
|
|
925
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const departmentOrder = ["Руководство", "Продажи", "ИТ"];
|
|
926
|
+
|
|
927
|
+
const orderByDepartment = new Map(departmentOrder.map((name, index) => [name, index]));
|
|
928
|
+
|
|
929
|
+
const groups = arrayGroupByToArray(employees, "department").sort((left, right) => {
|
|
930
|
+
return (orderByDepartment.get(left.key) ?? Number.MAX_SAFE_INTEGER) - (orderByDepartment.get(right.key) ?? Number.MAX_SAFE_INTEGER);
|
|
931
|
+
});
|
|
932
|
+
`})}),`
|
|
933
|
+
`,(0,c.jsx)(t.h3,{id:`построить-словарь-и-сохранить-первое-значение`,children:`Построить словарь и сохранить первое значение`}),`
|
|
934
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const metadataByFieldId = arrayToMap(metadataColumns, "fieldId");
|
|
935
|
+
|
|
936
|
+
const selectedMetadata = metadataByFieldId[selectedFieldId];
|
|
937
|
+
|
|
938
|
+
if (!selectedMetadata) {
|
|
939
|
+
throw new Error(\`Не найдена metadata для поля \${selectedFieldId}\`);
|
|
940
|
+
}
|
|
941
|
+
`})}),`
|
|
942
|
+
`,(0,c.jsx)(t.h3,{id:`удалить-дубли-объектов-по-id`,children:`Удалить дубли объектов по ID`}),`
|
|
943
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const uniqueUsers = arrayUniqueBy(users, "id");
|
|
944
|
+
`})}),`
|
|
945
|
+
`,(0,c.jsxs)(t.p,{children:[`Не заменяйте это на `,(0,c.jsx)(t.code,{children:`arrayDeduplicate(users)`}),`, если одинаковые пользователи представлены разными объектами.`]}),`
|
|
946
|
+
`,(0,c.jsx)(t.h3,{id:`переместить-элемент-по-команде-интерфейса`,children:`Переместить элемент по команде интерфейса`}),`
|
|
947
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type MoveCommand = {
|
|
948
|
+
activeIndex: number;
|
|
949
|
+
action: ReorderAction;
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
function applyMove(currentIds: readonly string[], command: MoveCommand) {
|
|
953
|
+
return moveArrayItemByIndex(currentIds, command.activeIndex, command.action);
|
|
954
|
+
}
|
|
955
|
+
`})}),`
|
|
956
|
+
`,(0,c.jsx)(t.h3,{id:`подготовить-канонический-save-snapshot`,children:`Подготовить канонический save snapshot`}),`
|
|
957
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type DraftItem = {
|
|
958
|
+
id: string;
|
|
959
|
+
label: string;
|
|
960
|
+
};
|
|
961
|
+
|
|
962
|
+
function createSaveSnapshot(draftItems: readonly DraftItem[]) {
|
|
963
|
+
return (
|
|
964
|
+
normalizeObjects(draftItems, "id", (item, normalizedId) => ({
|
|
965
|
+
...item,
|
|
966
|
+
id: normalizedId,
|
|
967
|
+
label: item.label.trim()
|
|
968
|
+
})) ?? []
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
`})}),`
|
|
972
|
+
`,(0,c.jsx)(t.p,{children:`Такой normalizer следует вызывать на границе сохранения. Обычный setter draft должен хранить пользовательский ввод буквально, если контракт приложения не говорит обратного.`}),`
|
|
973
|
+
`,(0,c.jsx)(t.h2,{id:`производительность`,children:`Производительность`}),`
|
|
974
|
+
`,(0,c.jsxs)(t.p,{children:[`Обозначение `,(0,c.jsx)(t.code,{children:`n`}),` — количество элементов входного массива.`]}),`
|
|
975
|
+
`,(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.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:`arrayGroupBy`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsx)(t.td,{children:`Объект групп и новые массивы групп.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayGroupByToArray`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsx)(t.td,{children:`Объект групп, массив групп и массивы элементов.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayToMap`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsx)(t.td,{children:`Объект-словарь.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayUniqueBy`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsxs)(t.td,{children:[`Новый массив и `,(0,c.jsx)(t.code,{children:`Set`}),` строковых ключей.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayDeduplicate`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsxs)(t.td,{children:[`Новый массив и `,(0,c.jsx)(t.code,{children:`Set`}),` значений.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`filterAndDeduplicateIds`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n + m)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`Map`}),` разрешённых ID, `,(0,c.jsx)(t.code,{children:`Set`}),` и результат.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`appendMissingIds`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n + m)`})}),(0,c.jsxs)(t.td,{children:[`Копия массива и `,(0,c.jsx)(t.code,{children:`Set`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`pickExistingMapValues`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`O(n)`}),` в среднем`]}),(0,c.jsx)(t.td,{children:`Новый массив.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arraysEqual`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`O(n)`}),` в худшем случае`]}),(0,c.jsx)(t.td,{children:`Постоянная память; может завершиться на первом различии.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Функции перемещения`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsx)(t.td,{children:`Копия массива.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeStringArray`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsxs)(t.td,{children:[`Новый массив и `,(0,c.jsx)(t.code,{children:`Set`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeObjects`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`O(n)`})}),(0,c.jsxs)(t.td,{children:[`Новый массив, `,(0,c.jsx)(t.code,{children:`Set`}),`, обычно поверхностные копии объектов.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`addUnique`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`O(1)`}),` в среднем за вызов`]}),(0,c.jsxs)(t.td,{children:[`Новое значение в переданных `,(0,c.jsx)(t.code,{children:`Set`}),` и массиве.`]})]})]})]}),`
|
|
976
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`m`}),` — количество элементов второго массива (`,(0,c.jsx)(t.code,{children:`allowedIds`}),` или `,(0,c.jsx)(t.code,{children:`idsToAppend`}),`).`]}),`
|
|
977
|
+
`,(0,c.jsx)(t.p,{children:`Для обычных UI-списков стоимость функций обычно несущественна. Для очень больших массивов не вызывайте одно и то же преобразование многократно внутри цикла или каждого render без необходимости.`}),`
|
|
978
|
+
`,(0,c.jsx)(t.p,{children:`В React вычисление можно мемоизировать, если входные ссылки стабильны и преобразование действительно заметно:`}),`
|
|
979
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`const usersById = useMemo(() => arrayToMap(users, "id"), [users]);
|
|
980
|
+
`})}),`
|
|
981
|
+
`,(0,c.jsxs)(t.p,{children:[`Не добавляйте `,(0,c.jsx)(t.code,{children:`useMemo`}),` автоматически для маленьких массивов: сама мемоизация тоже усложняет код и имеет стоимость.`]}),`
|
|
982
|
+
`,(0,c.jsx)(t.h2,{id:`ограничения-и-частые-ошибки`,children:`Ограничения и частые ошибки`}),`
|
|
983
|
+
`,(0,c.jsx)(t.h3,{id:`неправильный-entrypoint`,children:`Неправильный entrypoint`}),`
|
|
984
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Неправильно.
|
|
985
|
+
import { arraysEqual } from "@ryuzaki13/react-foundation-lib";
|
|
986
|
+
|
|
987
|
+
// Правильно.
|
|
988
|
+
import { arraysEqual } from "@ryuzaki13/react-foundation-lib/array";
|
|
989
|
+
`})}),`
|
|
990
|
+
`,(0,c.jsx)(t.h3,{id:`ожидание-глубокого-клонирования`,children:`Ожидание глубокого клонирования`}),`
|
|
991
|
+
`,(0,c.jsx)(t.p,{children:`Функции работают с внешним массивом и ссылками. Они не создают независимую копию всего дерева данных.`}),`
|
|
992
|
+
`,(0,c.jsxs)(t.p,{children:[`Для сериализуемой конфигурации, которой действительно нужна глубокая копия, используйте профильную clone-утилиту из `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/utils`}),` в соответствии с её контрактом.`]}),`
|
|
993
|
+
`,(0,c.jsx)(t.h3,{id:`ожидание-глубокого-сравнения`,children:`Ожидание глубокого сравнения`}),`
|
|
994
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`arraysEqual([{ id: "A" }], [{ id: "A" }]); // false
|
|
995
|
+
`})}),`
|
|
996
|
+
`,(0,c.jsx)(t.p,{children:`Сначала сформируйте сравниваемую identity:`}),`
|
|
997
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`arraysEqual(
|
|
998
|
+
left.map((item) => item.id),
|
|
999
|
+
right.map((item) => item.id)
|
|
1000
|
+
);
|
|
1001
|
+
`})}),`
|
|
1002
|
+
`,(0,c.jsxs)(t.h3,{id:`потеря-различия-между-undefined-и-`,children:[`Потеря различия между `,(0,c.jsx)(t.code,{children:`undefined`}),` и `,(0,c.jsx)(t.code,{children:`[]`})]}),`
|
|
1003
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`normalizeStringArray`}),` и `,(0,c.jsx)(t.code,{children:`normalizeObjects`}),` могут вернуть `,(0,c.jsx)(t.code,{children:`undefined`}),`. Это часть их контракта.`]}),`
|
|
1004
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const normalized = normalizeStringArray(raw);
|
|
1005
|
+
|
|
1006
|
+
if (normalized === undefined) {
|
|
1007
|
+
// Полезных значений нет.
|
|
1008
|
+
}
|
|
1009
|
+
`})}),`
|
|
1010
|
+
`,(0,c.jsxs)(t.p,{children:[`Используйте `,(0,c.jsx)(t.code,{children:`?? []`}),` только если ваш вызывающий контракт действительно требует массив.`]}),`
|
|
1011
|
+
`,(0,c.jsxs)(t.h3,{id:`ожидание-автоматического-trim`,children:[`Ожидание автоматического `,(0,c.jsx)(t.code,{children:`trim`})]}),`
|
|
1012
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`filterAndDeduplicateIds`}),`, `,(0,c.jsx)(t.code,{children:`appendMissingIds`}),`, `,(0,c.jsx)(t.code,{children:`arrayUniqueBy`}),`, `,(0,c.jsx)(t.code,{children:`arrayGroupBy`}),` и `,(0,c.jsx)(t.code,{children:`arrayToMap`}),` не обрезают строки.`]}),`
|
|
1013
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`arrayUniqueBy([{ id: "A" }, { id: " A " }], "id"); // Останутся два объекта.
|
|
1014
|
+
`})}),`
|
|
1015
|
+
`,(0,c.jsx)(t.p,{children:`Если пробелы нужно игнорировать, нормализуйте значение на явно выбранной boundary.`}),`
|
|
1016
|
+
`,(0,c.jsx)(t.h3,{id:`использование-произвольного-значения-как-ключа-обычного-объекта`,children:`Использование произвольного значения как ключа обычного объекта`}),`
|
|
1017
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`arrayGroupBy`}),`, `,(0,c.jsx)(t.code,{children:`arrayGroupByToArray`}),` и `,(0,c.jsx)(t.code,{children:`arrayToMap`}),` используют `,(0,c.jsx)(t.code,{children:`Record`}),`, а не `,(0,c.jsx)(t.code,{children:`Map`}),`.`]}),`
|
|
1018
|
+
`,(0,c.jsxs)(t.p,{children:[`Не передавайте в них непроверенные ключи, которые могут быть равны `,(0,c.jsx)(t.code,{children:`"__proto__"`}),`, `,(0,c.jsx)(t.code,{children:`"constructor"`}),` или `,(0,c.jsx)(t.code,{children:`"toString"`}),`. Для произвольных внешних значений используйте `,(0,c.jsx)(t.code,{children:`Map`}),`.`]}),`
|
|
1019
|
+
`,(0,c.jsx)(t.h3,{id:`ожидание-порядка-групп-для-числовых-строк`,children:`Ожидание порядка групп для числовых строк`}),`
|
|
1020
|
+
`,(0,c.jsxs)(t.p,{children:[`Группа `,(0,c.jsx)(t.code,{children:`"2"`}),` может оказаться раньше группы `,(0,c.jsx)(t.code,{children:`"10"`}),` независимо от первого появления. Если порядок важен, сортируйте результат `,(0,c.jsx)(t.code,{children:`arrayGroupByToArray`}),` явно.`]}),`
|
|
1021
|
+
`,(0,c.jsxs)(t.h3,{id:`передача-undefined-как-перемещаемого-элемента`,children:[`Передача `,(0,c.jsx)(t.code,{children:`undefined`}),` как перемещаемого элемента`]}),`
|
|
1022
|
+
`,(0,c.jsx)(t.p,{children:`Функции перемещения предназначены для плотных массивов определённых значений. Предварительно очистите массив:`}),`
|
|
1023
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const definedItems = items.filter((item): item is Item => item !== undefined);
|
|
1024
|
+
`})}),`
|
|
1025
|
+
`,(0,c.jsxs)(t.h3,{id:`использование-addunique-как-pure-function`,children:[`Использование `,(0,c.jsx)(t.code,{children:`addUnique`}),` как pure function`]}),`
|
|
1026
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`addUnique`}),` меняет аргументы и возвращает `,(0,c.jsx)(t.code,{children:`void`}),`:`]}),`
|
|
1027
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const result = addUnique(target, seen, id);
|
|
1028
|
+
|
|
1029
|
+
console.log(result); // undefined
|
|
1030
|
+
`})}),`
|
|
1031
|
+
`,(0,c.jsxs)(t.p,{children:[`Проверяйте изменившийся `,(0,c.jsx)(t.code,{children:`target`}),`, а не return value.`]}),`
|
|
1032
|
+
`,(0,c.jsxs)(t.h3,{id:`несинхронизированные-target-и-seen`,children:[`Несинхронизированные `,(0,c.jsx)(t.code,{children:`target`}),` и `,(0,c.jsx)(t.code,{children:`seen`})]}),`
|
|
1033
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const target = ["A"];
|
|
1034
|
+
const seen = new Set<string>();
|
|
1035
|
+
|
|
1036
|
+
addUnique(target, seen, "A");
|
|
1037
|
+
|
|
1038
|
+
console.log(target); // ["A", "A"]
|
|
1039
|
+
`})}),`
|
|
1040
|
+
`,(0,c.jsx)(t.p,{children:`Правильно:`}),`
|
|
1041
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const target = ["A"];
|
|
1042
|
+
const seen = new Set(target);
|
|
1043
|
+
`})}),`
|
|
1044
|
+
`,(0,c.jsx)(t.h3,{id:`нормализация-draft-во-время-ввода`,children:`Нормализация draft во время ввода`}),`
|
|
1045
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`normalizeStringArray`}),` и `,(0,c.jsx)(t.code,{children:`normalizeObjects`}),` меняют пользовательское представление: обрезают ключи, удаляют пустые значения и дубли. Не применяйте их внутри обычного store setter, если draft должен сохранять ввод буквально.`]}),`
|
|
1046
|
+
`,(0,c.jsxs)(t.p,{children:[`Например, строка `,(0,c.jsx)(t.code,{children:`"Новая группа "`}),` должна оставаться с завершающим пробелом до явно определённой границы сохранения или восстановления.`]}),`
|
|
1047
|
+
`,(0,c.jsx)(t.h2,{id:`краткий-справочник-api`,children:`Краткий справочник API`}),`
|
|
1048
|
+
`,(0,c.jsx)(t.p,{children:`Все значения импортируются из:`}),`
|
|
1049
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
|
|
1050
|
+
addUnique,
|
|
1051
|
+
appendMissingIds,
|
|
1052
|
+
arrayDeduplicate,
|
|
1053
|
+
arrayGroupBy,
|
|
1054
|
+
arrayGroupByToArray,
|
|
1055
|
+
arrayToMap,
|
|
1056
|
+
arrayUniqueBy,
|
|
1057
|
+
arraysEqual,
|
|
1058
|
+
filterAndDeduplicateIds,
|
|
1059
|
+
moveArrayItem,
|
|
1060
|
+
moveArrayItemByIndex,
|
|
1061
|
+
moveItem,
|
|
1062
|
+
normalizeObjects,
|
|
1063
|
+
normalizeStringArray,
|
|
1064
|
+
pickExistingMapValues,
|
|
1065
|
+
type ReorderAction
|
|
1066
|
+
} from "@ryuzaki13/react-foundation-lib/array";
|
|
1067
|
+
`})}),`
|
|
1068
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{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:`arrayGroupBy`})}),(0,c.jsx)(t.td,{children:`Массив объектов, имя поля`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Record<string, T[]>`})}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayGroupByToArray`})}),(0,c.jsx)(t.td,{children:`Массив объектов, имя поля`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Array<{ key: string; items: T[] }>`})}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayToMap`})}),(0,c.jsx)(t.td,{children:`Массив объектов, имя поля`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Record<string, T>`})}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayUniqueBy`})}),(0,c.jsx)(t.td,{children:`Массив объектов, имя поля`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`T[]`}),` без повторных строковых ключей`]}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arrayDeduplicate`})}),(0,c.jsx)(t.td,{children:`Массив значений`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`T[]`}),` без повторных значений или ссылок`]}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`filterAndDeduplicateIds`})}),(0,c.jsxs)(t.td,{children:[`ID или `,(0,c.jsx)(t.code,{children:`undefined`}),`, разрешённые ID`]}),(0,c.jsx)(t.td,{children:`Валидные уникальные ID`}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`appendMissingIds`})}),(0,c.jsx)(t.td,{children:`Базовые ID, добавляемые ID`}),(0,c.jsx)(t.td,{children:`Копия с отсутствующими ID в конце`}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`pickExistingMapValues`})}),(0,c.jsxs)(t.td,{children:[`Порядок ключей, `,(0,c.jsx)(t.code,{children:`ReadonlyMap`})]}),(0,c.jsx)(t.td,{children:`Найденные значения в порядке ключей`}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`arraysEqual`})}),(0,c.jsx)(t.td,{children:`Два массива`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`boolean`})}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`moveItem`})}),(0,c.jsxs)(t.td,{children:[`Массив, `,(0,c.jsx)(t.code,{children:`from`}),`, `,(0,c.jsx)(t.code,{children:`to`})]}),(0,c.jsx)(t.td,{children:`Переставленная копия`}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`moveArrayItem`})}),(0,c.jsxs)(t.td,{children:[`Массив, `,(0,c.jsx)(t.code,{children:`fromIndex`}),`, `,(0,c.jsx)(t.code,{children:`toIndex`})]}),(0,c.jsx)(t.td,{children:`Переставленная копия`}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`moveArrayItemByIndex`})}),(0,c.jsxs)(t.td,{children:[`Массив, `,(0,c.jsx)(t.code,{children:`index`}),`, `,(0,c.jsx)(t.code,{children:`ReorderAction`})]}),(0,c.jsx)(t.td,{children:`Переставленная копия`}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeStringArray`})}),(0,c.jsxs)(t.td,{children:[`Строки или `,(0,c.jsx)(t.code,{children:`undefined`})]}),(0,c.jsxs)(t.td,{children:[`Нормализованные строки или `,(0,c.jsx)(t.code,{children:`undefined`})]}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeObjects`})}),(0,c.jsxs)(t.td,{children:[`Объекты, строковое поле, callback или `,(0,c.jsx)(t.code,{children:`false`})]}),(0,c.jsxs)(t.td,{children:[`Нормализованные объекты или `,(0,c.jsx)(t.code,{children:`undefined`})]}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`addUnique`})}),(0,c.jsxs)(t.td,{children:[`Изменяемый массив, `,(0,c.jsx)(t.code,{children:`Set`}),`, строка или `,(0,c.jsx)(t.code,{children:`undefined`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`void`})}),(0,c.jsx)(t.td,{children:`Да`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`ReorderAction`})}),(0,c.jsx)(t.td,{children:`TypeScript type`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`"start" | "end" | "up" | "down"`})}),(0,c.jsx)(t.td,{children:`Не применимо`})]})]})]}),`
|
|
1069
|
+
`,(0,c.jsx)(t.h2,{id:`вопросы-и-ответы`,children:`Вопросы и ответы`}),`
|
|
1070
|
+
`,(0,c.jsxs)(t.h3,{id:`почему-функции-принимают-readonly-t-но-возвращают-t`,children:[`Почему функции принимают `,(0,c.jsx)(t.code,{children:`readonly T[]`}),`, но возвращают `,(0,c.jsx)(t.code,{children:`T[]`}),`?`]}),`
|
|
1071
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`readonly`}),` запрещает функции изменять входной массив. Результат создаётся заново и может быть изменяемым. Это позволяет безопасно передавать как обычные массивы, так и readonly-массивы.`]}),`
|
|
1072
|
+
`,(0,c.jsxs)(t.h3,{id:`почему-arraytomap-называется-map-но-возвращает-объект`,children:[`Почему `,(0,c.jsx)(t.code,{children:`arrayToMap`}),` называется `,(0,c.jsx)(t.code,{children:`Map`}),`, но возвращает объект?`]}),`
|
|
1073
|
+
`,(0,c.jsxs)(t.p,{children:[`Имя описывает идею сопоставления ключа и значения. Фактический тип результата — `,(0,c.jsx)(t.code,{children:`Record<string, T>`}),`, поэтому доступ выполняется как `,(0,c.jsx)(t.code,{children:`result[id]`}),`, а не `,(0,c.jsx)(t.code,{children:`result.get(id)`}),`.`]}),`
|
|
1074
|
+
`,(0,c.jsxs)(t.p,{children:[`Если нужен ключ не строкового типа, гарантированное сохранение порядка вставки или безопасная работа с произвольными внешними ключами, используйте встроенный `,(0,c.jsx)(t.code,{children:`Map`}),`.`]}),`
|
|
1075
|
+
`,(0,c.jsxs)(t.h3,{id:`почему-arraysequal-возвращает-false-для-одинаково-выглядящих-объектов`,children:[`Почему `,(0,c.jsx)(t.code,{children:`arraysEqual`}),` возвращает `,(0,c.jsx)(t.code,{children:`false`}),` для одинаково выглядящих объектов?`]}),`
|
|
1076
|
+
`,(0,c.jsx)(t.p,{children:`Потому что функция использует строгое сравнение элементов. Отдельно созданные объекты имеют разные ссылки. Сравните стабильные ID или используйте предметный comparator.`}),`
|
|
1077
|
+
`,(0,c.jsxs)(t.h3,{id:`почему-arraydeduplicate-не-удалил-одинаковые-объекты`,children:[`Почему `,(0,c.jsx)(t.code,{children:`arrayDeduplicate`}),` не удалил одинаковые объекты?`]}),`
|
|
1078
|
+
`,(0,c.jsxs)(t.p,{children:[`Она удаляет повторные ссылки, а не объекты с одинаковыми полями. Для уникальности по полю используйте `,(0,c.jsx)(t.code,{children:`arrayUniqueBy`}),`.`]}),`
|
|
1079
|
+
`,(0,c.jsxs)(t.h3,{id:`почему-normalizeobjects-не-записал-обрезанный-ключ-в-объект`,children:[`Почему `,(0,c.jsx)(t.code,{children:`normalizeObjects`}),` не записал обрезанный ключ в объект?`]}),`
|
|
1080
|
+
`,(0,c.jsxs)(t.p,{children:[`В режиме по умолчанию нормализованный ключ используется только для проверки пустоты и дублей. Результат содержит поверхностную копию исходного объекта. Передайте callback и явно запишите `,(0,c.jsx)(t.code,{children:`normalizedKey`}),`.`]}),`
|
|
1081
|
+
`,(0,c.jsxs)(t.h3,{id:`почему-normalizer-возвращает-undefined-а-не-`,children:[`Почему normalizer возвращает `,(0,c.jsx)(t.code,{children:`undefined`}),`, а не `,(0,c.jsx)(t.code,{children:`[]`}),`?`]}),`
|
|
1082
|
+
`,(0,c.jsxs)(t.p,{children:[`Так контракт позволяет обозначить отсутствие полезной конфигурации. Если вашему коду нужен пустой массив, используйте `,(0,c.jsx)(t.code,{children:`normalizeStringArray(value) ?? []`}),` или `,(0,c.jsx)(t.code,{children:`normalizeObjects(value, "id") ?? []`}),`.`]}),`
|
|
1083
|
+
`,(0,c.jsx)(t.h3,{id:`можно-ли-использовать-функции-в-react-state`,children:`Можно ли использовать функции в React state?`}),`
|
|
1084
|
+
`,(0,c.jsx)(t.p,{children:`Да. Функции перемещения и большинство преобразований возвращают новый массив, поэтому подходят для функционального обновления state:`}),`
|
|
1085
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`setItems((currentItems) => moveArrayItem(currentItems, fromIndex, toIndex));
|
|
1086
|
+
`})}),`
|
|
1087
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`addUnique`}),` мутирует аргументы, поэтому не вызывайте её напрямую над текущим state-массивом. Сначала создайте копию или соберите новый результат вне state.`]}),`
|
|
1088
|
+
`,(0,c.jsx)(t.h3,{id:`меняют-ли-функции-вложенные-объекты`,children:`Меняют ли функции вложенные объекты?`}),`
|
|
1089
|
+
`,(0,c.jsx)(t.p,{children:`Нет, но обычно сохраняют ссылки на них. Если вызывающий код затем мутирует вложенный объект через результат, это изменение будет видно и через исходные данные.`}),`
|
|
1090
|
+
`,(0,c.jsxs)(t.h3,{id:`считаются-ли-a-и-a-дублями`,children:[`Считаются ли `,(0,c.jsx)(t.code,{children:`"A"`}),` и `,(0,c.jsx)(t.code,{children:`"a"`}),` дублями?`]}),`
|
|
1091
|
+
`,(0,c.jsx)(t.p,{children:`Нет. Сравнение строк чувствительно к регистру. Если регистр не должен иметь значения, создайте отдельное нормализованное identity в своём предметном контракте.`}),`
|
|
1092
|
+
`,(0,c.jsxs)(t.h3,{id:`нужно-ли-оборачивать-каждый-вызов-в-trycatch`,children:[`Нужно ли оборачивать каждый вызов в `,(0,c.jsx)(t.code,{children:`try/catch`}),`?`]}),`
|
|
1093
|
+
`,(0,c.jsx)(t.p,{children:`Нет, если аргументы соответствуют TypeScript-сигнатуре. Эти функции не используют сеть и не выполняют асинхронные операции. Ошибка обычно означает нарушение контракта входных данных, которое нужно исправить или валидировать на внешней boundary.`})]})}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};
|