@ryuzaki13/react-foundation-ui 1.8.10 → 1.8.12
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 +1 -1
- package/dist/chunks/{defaultRenderers-Dbhg2hHc.js → defaultRenderers-u_Vep6Pj.js} +2 -2
- package/dist/chunks/defaultRenderers-u_Vep6Pj.js.map +1 -0
- package/dist/chunks/{multi-select-CHZhWoq6.js → multi-select-DtmRtX6v.js} +2 -2
- package/dist/chunks/multi-select-DtmRtX6v.js.map +1 -0
- package/dist/chunks/select-MN6zDPKM.js.map +1 -1
- package/dist/chunks/useODataSelectBase-DR4PrY1j.js.map +1 -1
- package/dist/multi-select/index.js +1 -1
- package/dist/multi-select/model/useODataMultiSelect.d.ts +1 -1
- package/dist/multi-select/model/useODataMultiSelect.d.ts.map +1 -1
- package/dist/multi-select/ui/MultiSelect.d.ts +2 -2
- package/dist/multi-select/ui/MultiSelect.d.ts.map +1 -1
- package/dist/multi-select/ui/SerializableMultiSelect.d.ts.map +1 -1
- package/dist/multi-select/ui/defaultRenderers.d.ts +2 -2
- package/dist/multi-select/ui/defaultRenderers.d.ts.map +1 -1
- package/dist/select/model/useODataSelect.d.ts +1 -1
- package/dist/select/model/useODataSelect.d.ts.map +1 -1
- package/dist/select/model/useODataSelectBase.d.ts +1 -1
- package/dist/select/model/useODataSelectBase.d.ts.map +1 -1
- package/dist/tree-select/index.js +1 -1
- package/dist/tree-select/index.js.map +1 -1
- package/dist/tree-select/model/buildODataTreeNodes.d.ts +1 -1
- package/dist/tree-select/model/buildODataTreeNodes.d.ts.map +1 -1
- package/package.json +3 -3
- package/storybook-static/assets/{Badge-BqQpQw_L.js → Badge-CveIo2LZ.js} +1 -1
- package/storybook-static/assets/{Badge.stories-BLEc3pho.js → Badge.stories-Bd8M64xJ.js} +1 -1
- package/storybook-static/assets/{BadgeList-DfMo6yit.js → BadgeList-xT41a0VL.js} +1 -1
- package/storybook-static/assets/{Button-D1w_se49.js → Button-C5bBSb3k.js} +1 -1
- package/storybook-static/assets/{Button-D6MwkfU8.js → Button-DkDgfpHL.js} +1 -1
- package/storybook-static/assets/{Button.stories-DsEGxbz-.js → Button.stories-CeKPeGK5.js} +1 -1
- package/storybook-static/assets/{CalendarView-FWwbhHMn.js → CalendarView-CEqcrblx.js} +1 -1
- package/storybook-static/assets/{CheckBox-BIeKlLsQ.js → CheckBox-DKeFkdOt.js} +1 -1
- package/storybook-static/assets/{CheckBox-krtKLFK6.js → CheckBox-OVvAarW-.js} +1 -1
- package/storybook-static/assets/{CheckBox.stories-gV23d8F9.js → CheckBox.stories-CfZ0p1yo.js} +1 -1
- package/storybook-static/assets/{Color-6AOWCN3U-DF3lA8Cg.js → Color-6AOWCN3U-BWW7zrfs.js} +1 -1
- package/storybook-static/assets/{ContextMenu-Jid_pp7z.js → ContextMenu-kia7is1N.js} +1 -1
- package/storybook-static/assets/{ContextMenu-CvOaSUdS.js → ContextMenu-xn2GtiLR.js} +1 -1
- package/storybook-static/assets/{ContextMenu.stories-BMRQo225.js → ContextMenu.stories-CYuy9uXF.js} +1 -1
- package/storybook-static/assets/{CustomOptionButton-B_3l2oEp.js → CustomOptionButton-C4w-APws.js} +1 -1
- package/storybook-static/assets/DateInput-BiUFIihm.js +1 -0
- package/storybook-static/assets/{DateInput-Dmfu-QPI.js → DateInput-DAzE5mCE.js} +1 -1
- package/storybook-static/assets/{DateInput.stories-BcZKAAUH.js → DateInput.stories-BcowGCRD.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-Dpjei_qk.js → DateRangePresetSelect-CQm4dNLR.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-C4QK2uI5.js → DateRangePresetSelect-RIyqNBk9.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect.stories-HuFMQCzg.js → DateRangePresetSelect.stories-ypGyuGfy.js} +1 -1
- package/storybook-static/assets/{Detail-mSGrPHPd.js → Detail-CEypL2Nh.js} +1 -1
- package/storybook-static/assets/{Detail.stories-CNmeyajk.js → Detail.stories-DNkT7B-u.js} +1 -1
- package/storybook-static/assets/{Dialog-CNPtztC5.js → Dialog-BVFFQJDH.js} +1 -1
- package/storybook-static/assets/{Dialog-C4lB95kT.js → Dialog-DD0grLG3.js} +1 -1
- package/storybook-static/assets/{Dialog.stories-DGC2CdmD.js → Dialog.stories-DSCypHqR.js} +1 -1
- package/storybook-static/assets/{Disclosure-Bg9Uurzq.js → Disclosure-DauUgrev.js} +1 -1
- package/storybook-static/assets/{Disclosure.stories-52zq3d3b.js → Disclosure.stories-B1qB8vQZ.js} +1 -1
- package/storybook-static/assets/{DisclosureGroup-htBmjuHs.js → DisclosureGroup-D9oCCeHf.js} +1 -1
- package/storybook-static/assets/{DocsRenderer-JROSPFPF-CfCr8YB1.js → DocsRenderer-JROSPFPF-CmSf6tXp.js} +1 -1
- package/storybook-static/assets/{DropZone-DHl97f8Y.js → DropZone-D42ueN1w.js} +1 -1
- package/storybook-static/assets/{DropZone-BsjXindv.js → DropZone-D8hbPCAv.js} +1 -1
- package/storybook-static/assets/{DropZone.stories-UxmcssH9.js → DropZone.stories-DO-T_Bh4.js} +1 -1
- package/storybook-static/assets/{DropdownMenu-Bq4Z7eyk.js → DropdownMenu-CknJDoji.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel-Buvm-uo_.js → ExpandableActionPanel-Dqi_bo3c.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel.stories-DHjq73og.js → ExpandableActionPanel.stories-BD9QZGZN.js} +1 -1
- package/storybook-static/assets/{Flex-B9W01d7p.js → Flex-CaVn1IOP.js} +1 -1
- package/storybook-static/assets/{Flex.stories-Y8vGrgl5.js → Flex.stories-Bp9Y6q6b.js} +1 -1
- package/storybook-static/assets/{FloatingPopover-C06XhNb8.js → FloatingPopover-U7tx-Jlw.js} +1 -1
- package/storybook-static/assets/{FormattedTableCell-DnBQJjql.js → FormattedTableCell-pmmhsAbN.js} +1 -1
- package/storybook-static/assets/{Grid-BNsdOQE3.js → Grid-CEpMNurH.js} +1 -1
- package/storybook-static/assets/{Grid.stories-hwxpk_k9.js → Grid.stories-BM-gO5DN.js} +1 -1
- package/storybook-static/assets/{ImageCropper.stories-L6AaNzcC.js → ImageCropper.stories-BWz5XU6U.js} +1 -1
- package/storybook-static/assets/{ImageRenderer-DA4vCb7C.js → ImageRenderer-BTYZEX5t.js} +1 -1
- package/storybook-static/assets/{ImageRenderer.stories-eWJHpmcc.js → ImageRenderer.stories-Dz2STM95.js} +1 -1
- package/storybook-static/assets/{ImageView.stories-CDZmePLC.js → ImageView.stories-DBVe0an3.js} +1 -1
- package/storybook-static/assets/{ImageViewer.stories-c1s8XOKG.js → ImageViewer.stories-C4Px97lD.js} +2 -2
- package/storybook-static/assets/{ImageViewerRuntime-CB58FU7X.js → ImageViewerRuntime-TJtlJVfa.js} +1 -1
- package/storybook-static/assets/{Input-k78uABnO.js → Input-CIPgijvW.js} +1 -1
- package/storybook-static/assets/{Input-CPh1-5MN.js → Input-D8io9jVS.js} +1 -1
- package/storybook-static/assets/{Input.stories-Bjo-quWE.js → Input.stories-SUk3aYaC.js} +1 -1
- package/storybook-static/assets/{InputDateTime-D6wx8NHg.js → InputDateTime-DA5pIDuE.js} +1 -1
- package/storybook-static/assets/{InputDateTime.stories-DKYu3IHZ.js → InputDateTime.stories-DeudzDSU.js} +1 -1
- package/storybook-static/assets/{InputFile-B_d9cuuZ.js → InputFile-C5mp5Y5I.js} +1 -1
- package/storybook-static/assets/{InputFile-jyLYajsV.js → InputFile-CGAC7ruP.js} +1 -1
- package/storybook-static/assets/{InputFile.stories-BdefvDig.js → InputFile.stories-Cx1xQ6PE.js} +1 -1
- package/storybook-static/assets/{InputFiles-Bk5cxV_q.js → InputFiles-B7OBcPJN.js} +1 -1
- package/storybook-static/assets/{InputFiles-8NO4ybbw.js → InputFiles-Hzl89Ghf.js} +1 -1
- package/storybook-static/assets/{InputFiles.stories-ByWo1zY4.js → InputFiles.stories-CG6QjDZH.js} +1 -1
- package/storybook-static/assets/{InputFilesList-D4SB2px7.js → InputFilesList-B6htWHF1.js} +1 -1
- package/storybook-static/assets/{InputImage-Zoi-dxR0.js → InputImage-BTa4S4Wp.js} +1 -1
- package/storybook-static/assets/{InputImage-DehD0dUv.js → InputImage-CQnoblAE.js} +1 -1
- package/storybook-static/assets/{InputImage.stories-Bm6vjE22.js → InputImage.stories-CEI44Eyz.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents-B1kglKoK.js → InteractiveComponents-B0ypWz1x.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents.stories-HmO6jYBZ.js → InteractiveComponents.stories-BadApta9.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-BdaZMF1N.js → LayoutPicker-COB9GlV_.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-C__JzlAL.js → LayoutPicker-C_Uz7Tnj.js} +1 -1
- package/storybook-static/assets/{LayoutPicker.stories-Q1MsCb_7.js → LayoutPicker.stories-Btp0IcaL.js} +1 -1
- package/storybook-static/assets/{Listbox-_2Lhh6GE.js → Listbox-AAaZGSAl.js} +1 -1
- package/storybook-static/assets/{Listbox-HDTB2yAv.js → Listbox-CyfuZw7w.js} +1 -1
- package/storybook-static/assets/{Listbox.stories-C5uX1wxr.js → Listbox.stories-NDKQmjyQ.js} +1 -1
- package/storybook-static/assets/{Modal-Blv9Namu.js → Modal-BJDnJ4zv.js} +1 -1
- package/storybook-static/assets/{Modal.stories-Bh5G9FLw.js → Modal.stories-D_X5lTLO.js} +1 -1
- package/storybook-static/assets/{ModalManagerProvider-DedM4XGI.js → ModalManagerProvider-ShDjozpW.js} +1 -1
- package/storybook-static/assets/{MultiSelect-B_2TcTLI.js → MultiSelect-B5CElQ3-.js} +1 -1
- package/storybook-static/assets/{MultiSelect-C9a9z0VK.js → MultiSelect-DqXfrjcH.js} +1 -1
- package/storybook-static/assets/{MultiSelect.stories-D5Ly4DPj.js → MultiSelect.stories-fB3mcFmx.js} +1 -1
- package/storybook-static/assets/{NoData-CD8_tH4f.js → NoData-DDb0G7T8.js} +1 -1
- package/storybook-static/assets/{NotificationsHost-MW4gDQQK.js → NotificationsHost-CIGL-pKX.js} +1 -1
- package/storybook-static/assets/NotificationsHost.stories-B_MRb3fs.js +29 -0
- package/storybook-static/assets/{ODataMultiSelect-DjVOp5BB.js → ODataMultiSelect-DQAitH4N.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect.stories-Cpxe83Z0.js → ODataMultiSelect.stories-DwW221S9.js} +2 -2
- package/storybook-static/assets/{ODataSelect-C_2GMQva.js → ODataSelect-tiZhOIhE.js} +1 -1
- package/storybook-static/assets/{ODataSelect.stories-C6Wo7X-M.js → ODataSelect.stories-BhaatPjK.js} +2 -2
- package/storybook-static/assets/{ODataTreeMultiSelect-1PxW1yEH.js → ODataTreeMultiSelect-B9WqJ-Un.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect.stories-AetogHrA.js → ODataTreeMultiSelect.stories-CAfKuhfU.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect-vPvVKIRZ.js → ODataTreeSelect-Cel1phxZ.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect.stories-Cvyu6C2q.js → ODataTreeSelect.stories-BpBCpBA9.js} +1 -1
- package/storybook-static/assets/{OneStepScroller-BtSUY6R7.js → OneStepScroller-BSeGbz02.js} +1 -1
- package/storybook-static/assets/{Option-D5HVST0Y.js → Option-BBtQ3GdK.js} +1 -1
- package/storybook-static/assets/{OptionButton-DMZn3qex.js → OptionButton-B9nZuqqW.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-ccgbEHCS.js → PeriodSelect-BGvhR3to.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-BirdSdPT.js → PeriodSelect-DA_zjcdA.js} +1 -1
- package/storybook-static/assets/{PeriodSelect.stories-LnR8MJQQ.js → PeriodSelect.stories-DDP1eXyM.js} +1 -1
- package/storybook-static/assets/{PickerTriggerActions-DEXowtVB.js → PickerTriggerActions-BgvzqRBd.js} +1 -1
- package/storybook-static/assets/{Popover-CfT-5TUj.js → Popover-BQql18MF.js} +1 -1
- package/storybook-static/assets/{Popover-B9Pbbd8S.js → Popover-C0NebUMz.js} +1 -1
- package/storybook-static/assets/{Popover.stories-DkIh7SkO.js → Popover.stories-CIyDUtlz.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-BshHlO-z.js → PresetRangeDateInput-BsgzPwCV.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-rHxPNjnG.js → PresetRangeDateInput-htbxc3ni.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput.stories-BToClw-C.js → PresetRangeDateInput.stories-ClHM5Kah.js} +1 -1
- package/storybook-static/assets/{PresetSelect-BND50bCx.js → PresetSelect-Dcx0BOTx.js} +1 -1
- package/storybook-static/assets/README--LCKbep-.js +110 -0
- package/storybook-static/assets/{README-Du53oOl4.js → README-5M8ajrJp.js} +1 -1
- package/storybook-static/assets/README-5NhzH8VL.js +95 -0
- package/storybook-static/assets/README-Am6Fa6-b.js +69 -0
- package/storybook-static/assets/README-B3bFglqG.js +82 -0
- package/storybook-static/assets/README-B45Cwj2a.js +95 -0
- package/storybook-static/assets/README-B6Nq7NCU.js +416 -0
- package/storybook-static/assets/{README-s-T48I9S.js → README-B6ltJiw3.js} +1 -1
- package/storybook-static/assets/{README-DUA1kfLE.js → README-BB_JPejH.js} +1 -1
- package/storybook-static/assets/README-BIq-FXcN.js +2124 -0
- package/storybook-static/assets/README-BSh5XUR9.js +110 -0
- package/storybook-static/assets/README-BXJneZAJ.js +147 -0
- package/storybook-static/assets/README-BYSgTTZt.js +296 -0
- package/storybook-static/assets/{README-BRNFl9WV.js → README-BmhhWWEk.js} +1 -1
- package/storybook-static/assets/README-Bqnqu1bC.js +118 -0
- package/storybook-static/assets/README-BuMMG4_N.js +192 -0
- package/storybook-static/assets/README-BxjYCoYA.js +186 -0
- package/storybook-static/assets/{README-BsxKAG_a.js → README-ByALXSEH.js} +1 -1
- package/storybook-static/assets/README-Byo6DxIF.js +101 -0
- package/storybook-static/assets/README-C3UcjOGB.js +208 -0
- package/storybook-static/assets/README-C6BOdXNV.js +322 -0
- package/storybook-static/assets/README-C8E1O7DQ.js +230 -0
- package/storybook-static/assets/README-C9eh0JLs.js +64 -0
- package/storybook-static/assets/README-CAGQnLsv.js +90 -0
- package/storybook-static/assets/README-CC00hlZK.js +527 -0
- package/storybook-static/assets/README-CH_6ZIO2.js +64 -0
- package/storybook-static/assets/README-CHbo4O3Z.js +75 -0
- package/storybook-static/assets/{README-Y0nGf_0E.js → README-CIGfHKKE.js} +1 -1
- package/storybook-static/assets/{README-B7XIrdXq.js → README-CM-7E-Jf.js} +1 -1
- package/storybook-static/assets/{README-8Lm1JpdJ.js → README-CNHemCS2.js} +1 -1
- package/storybook-static/assets/{README-fxPT-NzI.js → README-CWfPiPIB.js} +1 -1
- package/storybook-static/assets/{README-Dw1C16bT.js → README-CeK4kfFO.js} +1 -1
- package/storybook-static/assets/README-Cj2e6HrF.js +178 -0
- package/storybook-static/assets/README-CsoHGRve.js +1844 -0
- package/storybook-static/assets/README-D9OypaFB.js +208 -0
- package/storybook-static/assets/{README-zAGDQqES.js → README-DDBqoI-T.js} +1 -1
- package/storybook-static/assets/README-DE2wk9-v.js +1282 -0
- package/storybook-static/assets/README-DEj2wSK0.js +264 -0
- package/storybook-static/assets/{README-DJlxGqOL.js → README-DIbfpC-2.js} +1 -1
- package/storybook-static/assets/{README-D5VR4x0m.js → README-DJHVgrpj.js} +1 -1
- package/storybook-static/assets/README-DN9HKtp_.js +124 -0
- package/storybook-static/assets/README-DNricOkt.js +136 -0
- package/storybook-static/assets/README-DV4fCpqN.js +1146 -0
- package/storybook-static/assets/{README-BMmR1B7a.js → README-DjCArsA5.js} +1 -1
- package/storybook-static/assets/README-Dl92E69Z.js +1704 -0
- package/storybook-static/assets/README-DnA-4W65.js +226 -0
- package/storybook-static/assets/README-DoCA4JXf.js +273 -0
- package/storybook-static/assets/{README-DUxV9GhP.js → README-DvAlDsh9.js} +1 -1
- package/storybook-static/assets/README-Ss-3t1nX.js +158 -0
- package/storybook-static/assets/README-eHCINzP3.js +154 -0
- package/storybook-static/assets/README-qHKxXU95.js +98 -0
- package/storybook-static/assets/README-tm9QH9cF.js +103 -0
- package/storybook-static/assets/README-ui-uanyg.js +672 -0
- package/storybook-static/assets/{RadioButton-BKvo6LIi.js → RadioButton-CWtjclwT.js} +1 -1
- package/storybook-static/assets/{RadioButton-D8KuponB.js → RadioButton-YIQXt0wx.js} +1 -1
- package/storybook-static/assets/{RadioButton.stories-BabeLrwX.js → RadioButton.stories-Ah-CBpeC.js} +1 -1
- package/storybook-static/assets/{RadioGroup-CsWjbEp2.js → RadioGroup-BnO-GL7A.js} +1 -1
- package/storybook-static/assets/{RadioGroup-jl5PxZpJ.js → RadioGroup-CUS0etBD.js} +1 -1
- package/storybook-static/assets/{RadioGroup.stories-BGoWy9-B.js → RadioGroup.stories-DGwCawtU.js} +1 -1
- package/storybook-static/assets/{Scrollable-CmPEHdW8.js → Scrollable-D85fA6pO.js} +1 -1
- package/storybook-static/assets/{Select-DiN4WVRM.js → Select-CGCxJjL9.js} +1 -1
- package/storybook-static/assets/{Select-BGM16rM6.js → Select-gRnfvfGh.js} +1 -1
- package/storybook-static/assets/{Select.stories-BEO6vXD_.js → Select.stories-CMwt4F9i.js} +1 -1
- package/storybook-static/assets/{SerializableSelect-B0DuNSqT.js → SerializableSelect-BLXfKJ38.js} +1 -1
- package/storybook-static/assets/{SerializableSelect.stories-DcI6UQCk.js → SerializableSelect.stories-Bca1a9ZU.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-C_Itd_An.js → SingleDateTimeInput-CyeQN0Rd.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-CwYhFl03.js → SingleDateTimeInput-xrmZckzw.js} +1 -1
- package/storybook-static/assets/SingleDateTimeInput.stories-BYFTQM9z.js +48 -0
- package/storybook-static/assets/{Slider-DCEQ39ar.js → Slider-1yJ3uVeR.js} +1 -1
- package/storybook-static/assets/{Slider-r4NefX-L.js → Slider-D8GtXVGI.js} +1 -1
- package/storybook-static/assets/{Slider.stories-B3M87sif.js → Slider.stories-CyQ3ns_C.js} +1 -1
- package/storybook-static/assets/{SliderInput-BmLucI1O.js → SliderInput-BOzHhEUA.js} +1 -1
- package/storybook-static/assets/{SliderInput-2ThnJzQ4.js → SliderInput-ISSx9vH_.js} +1 -1
- package/storybook-static/assets/{SliderInput.stories-B64rkErN.js → SliderInput.stories-7ooTghrS.js} +1 -1
- package/storybook-static/assets/{Sortable-Bx0rDd7W.js → Sortable-CCLiMmfZ.js} +1 -1
- package/storybook-static/assets/{Sortable.stories-BizbKIHw.js → Sortable.stories-B36szI6t.js} +1 -1
- package/storybook-static/assets/{Splitter-DGCB2owx.js → Splitter-DQGhgRwx.js} +1 -1
- package/storybook-static/assets/{Splitter.stories-8Oh14fbm.js → Splitter.stories-Hsq1wYaq.js} +1 -1
- package/storybook-static/assets/{StateSelect-Dw0Qm14-.js → StateSelect-C6hldFgO.js} +1 -1
- package/storybook-static/assets/{StateSelect-BSQUSTgI.js → StateSelect-DieNn4VC.js} +1 -1
- package/storybook-static/assets/{StateSelect.stories-C8WPRJNx.js → StateSelect.stories-CvAhDMix.js} +1 -1
- package/storybook-static/assets/{StringToggle.stories-K9u9rdE8.js → StringToggle.stories-CUT1tvt-.js} +1 -1
- package/storybook-static/assets/{Switch-BBuNsdNx.js → Switch-CX9p_uYU.js} +1 -1
- package/storybook-static/assets/{Switch-CtpvrECR.js → Switch-nEMRtcWe.js} +1 -1
- package/storybook-static/assets/{Switch.stories-Bcr4zA7L.js → Switch.stories-CPsHa2_m.js} +1 -1
- package/storybook-static/assets/{Table-iYeIie6s.js → Table-BhtITVtj.js} +1 -1
- package/storybook-static/assets/{Table.stories-BESdXqZx.js → Table.stories-nWNhSydG.js} +2 -2
- package/storybook-static/assets/{Tabs-aqWeCgs4.js → Tabs-DMQFh2BJ.js} +1 -1
- package/storybook-static/assets/{Tabs.stories-BSnrKg5G.js → Tabs.stories-D23_xvom.js} +1 -1
- package/storybook-static/assets/{TabsBox-CvRq3QA7.js → TabsBox-B5BsD_j_.js} +1 -1
- package/storybook-static/assets/{TagInput-CfKrOpJJ.js → TagInput-DO17z100.js} +1 -1
- package/storybook-static/assets/{TagInput.stories-CvXZl_qX.js → TagInput.stories-CMMFnIzb.js} +1 -1
- package/storybook-static/assets/{Text-_hP7L82D.js → Text-ClnbDqRk.js} +1 -1
- package/storybook-static/assets/{Textarea-Ujw8jml9.js → Textarea-C2IO_zsP.js} +1 -1
- package/storybook-static/assets/{Textarea-C6X20K4X.js → Textarea-DkhohiNc.js} +1 -1
- package/storybook-static/assets/{Textarea.stories-Bi4BQMxQ.js → Textarea.stories-NL6Aq8Vc.js} +1 -1
- package/storybook-static/assets/{TimePanel-B3eqkZj8.js → TimePanel-DNEPDlSW.js} +1 -1
- package/storybook-static/assets/{TimePanel.stories-BHXkDSMy.js → TimePanel.stories-DlfdPsz1.js} +1 -1
- package/storybook-static/assets/{Toggle-DS-Q4jwI.js → Toggle-3U5CceQN.js} +1 -1
- package/storybook-static/assets/{Toggle-6sjykxYk.js → Toggle-Cc6Ca-HI.js} +1 -1
- package/storybook-static/assets/{Toggle.stories-BhM1so-Z.js → Toggle.stories-BR-hVLDp.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-D2lWYAa2.js → TreeMultiSelect-B0oBc-4y.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-BudM77CT.js → TreeMultiSelect-D9hMQN2O.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect.stories-Bhh1zaAQ.js → TreeMultiSelect.stories-CslpbvPR.js} +1 -1
- package/storybook-static/assets/{TreePickerBase-CJfbJ6Ap.js → TreePickerBase-B_dMCe45.js} +1 -1
- package/storybook-static/assets/{TreeSelect-BFD6AKMu.js → TreeSelect-2lj0Q8gm.js} +1 -1
- package/storybook-static/assets/{TreeSelect-B7SG9PV7.js → TreeSelect-DEKNYF2b.js} +1 -1
- package/storybook-static/assets/{TreeSelect.stories-C-bHnrPH.js → TreeSelect.stories-CVDxn8Vm.js} +1 -1
- package/storybook-static/assets/{TreeTable-D-z37qlF.js → TreeTable-CBIpzYRL.js} +1 -1
- package/storybook-static/assets/{TreeTable.stories-CF_mH9Zz.js → TreeTable.stories-BMzrr2Kc.js} +2 -2
- package/storybook-static/assets/{blocks-Ddv0ZNIG.js → blocks-B5YBxaaS.js} +3 -3
- package/storybook-static/assets/{check-CgNbDbzr.js → check-BjtdCRaW.js} +1 -1
- package/storybook-static/assets/{chevron-down-0EnY_Ds_.js → chevron-down-B4u-y8Z1.js} +1 -1
- package/storybook-static/assets/{chevron-left-D5M5fFYk.js → chevron-left-BQfWs7Ah.js} +1 -1
- package/storybook-static/assets/{chevron-right-Uz5Iy_m-.js → chevron-right-ChokKd-f.js} +1 -1
- package/storybook-static/assets/{chunk-W22LQPXL-THpLoWLV.js → chunk-W22LQPXL-meOkhzk4.js} +1 -1
- package/storybook-static/assets/{circle-alert-B6Z--uoZ.js → circle-alert-B1AnDRf_.js} +1 -1
- package/storybook-static/assets/{circle-check-DMzkBUqN.js → circle-check-JYnlcC1F.js} +1 -1
- package/storybook-static/assets/{components-BmKs7c49.js → components-C_wl1sL5.js} +3 -3
- package/storybook-static/assets/{contextMenu-Dct-XhfD.js → contextMenu-B-TUGs_1.js} +1 -1
- package/storybook-static/assets/{defaultRenderers-BHXboKuy.js → defaultRenderers-DfmnIuod.js} +1 -1
- package/storybook-static/assets/{download-wey0TOZ0.js → download-eR3X8I-h.js} +1 -1
- package/storybook-static/assets/{floating-ui.react-COVT_I6r.js → floating-ui.react-D95VPQ0b.js} +1 -1
- package/storybook-static/assets/formatters-D33Uh3si-CxrG0jsB.js +1 -0
- package/storybook-static/assets/foundationApi-QhHXpYLB.js +59 -0
- package/storybook-static/assets/foundationLib-CEAjnstw.js +30 -0
- package/storybook-static/assets/{hooks-Baxp-XYz.js → hooks-awde7r2r.js} +1 -1
- package/storybook-static/assets/iframe-DzQq_POR.js +1 -0
- package/storybook-static/assets/{iframe-BOu-P2xF.js → iframe-FSp_AjJa.js} +4 -4
- package/storybook-static/assets/{info-gF0pk8a1.js → info-12vmb1sT.js} +1 -1
- package/storybook-static/assets/odata-C0Kpvttz.js +1 -0
- package/storybook-static/assets/odata-service-CWkHASdw-DlmSiioz.js +3 -0
- package/storybook-static/assets/{odataStoryFixtures-BUio-7WG.js → odataStoryFixtures-BXZnk_C7.js} +1 -1
- package/storybook-static/assets/{react-CN73PS7L.js → react-BlCqWuXr.js} +1 -1
- package/storybook-static/assets/{refresh-cw-BZ2qxodL.js → refresh-cw-Bf5ufPte.js} +1 -1
- package/storybook-static/assets/{settings-2-B33BG8wi.js → settings-2-DR-dTXIC.js} +1 -1
- package/storybook-static/assets/{sortable-CmC4atFR.js → sortable-B5e5yb_-.js} +1 -1
- package/storybook-static/assets/{syntaxhighlighter-QEQV7K2Y-Di0K55k7.js → syntaxhighlighter-QEQV7K2Y-EVJARTec.js} +1 -1
- package/storybook-static/assets/{trash-2-TnhWnKGO.js → trash-2-QP7TS18H.js} +1 -1
- package/storybook-static/assets/{triangle-alert-hZRwHRWu.js → triangle-alert-qw19mxHr.js} +1 -1
- package/storybook-static/assets/{useODataSelectBase-bTXYj3rC.js → useODataSelectBase-Csu_Cct9.js} +1 -1
- package/storybook-static/assets/useODataTreeData-BAv-Twqf.js +1 -0
- package/storybook-static/assets/{usePickerQuery-BMGBq6pi.js → usePickerQuery-Da-XM_Y0.js} +1 -1
- package/storybook-static/assets/{usePickerTriggerController-CB_TIrYx.js → usePickerTriggerController-C0TdC2Pz.js} +1 -1
- package/storybook-static/assets/{x-D86ykZGt.js → x-aCjYTirW.js} +1 -1
- package/storybook-static/iframe.html +2 -2
- package/storybook-static/index.json +1 -1
- package/storybook-static/project.json +1 -1
- package/dist/chunks/defaultRenderers-Dbhg2hHc.js.map +0 -1
- package/dist/chunks/multi-select-CHZhWoq6.js.map +0 -1
- package/storybook-static/assets/DateInput-DSwx7eI6.js +0 -1
- package/storybook-static/assets/NotificationsHost.stories-BZJG9Nvq.js +0 -29
- package/storybook-static/assets/SingleDateTimeInput.stories-kdKdW6al.js +0 -48
- package/storybook-static/assets/async-D1NpMm55.js +0 -625
- package/storybook-static/assets/formatters-CBgrBeSA-CqB1pZxS.js +0 -1
- package/storybook-static/assets/foundationLib-CRTVZVS8.js +0 -25
- package/storybook-static/assets/iframe-CDj936Ul.js +0 -1
- package/storybook-static/assets/odata-D9Wmxqmj.js +0 -1
- package/storybook-static/assets/odata-service-B6TxBSLm-Bq8Ya67E.js +0 -3
- package/storybook-static/assets/odataFetchFn-DfJwHTw8.js +0 -763
- package/storybook-static/assets/persisted-4qmfJLE0.js +0 -600
- package/storybook-static/assets/useODataTreeData-ZcX73Wdh.js +0 -1
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe-FSp_AjJa.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-B5YBxaaS.js";function o(e){let t={a:`a`,code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation API/Query/Persisted Records`}),`
|
|
2
|
+
`,(0,c.jsxs)(t.h1,{id:`сохранённые-записи-через-ryuzaki13react-foundation-apipersisted`,children:[`Сохранённые записи через `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-api/persisted`})]}),`
|
|
3
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`persisted`}),` — специализированный слой поверх TanStack Query для данных, которые пользователь сохраняет и позднее восстанавливает: presets, variants, view configs и другие versioned records.`]}),`
|
|
4
|
+
`,(0,c.jsx)(t.h2,{id:`ментальная-модель`,children:`Ментальная модель`}),`
|
|
5
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`PersistedResourceDescriptor
|
|
6
|
+
├─ identity: namespace + resource + normalized scope
|
|
7
|
+
├─ read capability: list | latest | history
|
|
8
|
+
├─ write capability: save | create | delete
|
|
9
|
+
├─ transport operation: REST | OData | server-fn | custom
|
|
10
|
+
└─ cache strategy после успешной mutation
|
|
11
|
+
`})}),`
|
|
12
|
+
`,(0,c.jsx)(t.p,{children:`Capability optional: resource не обязан поддерживать все шесть операций. TypeScript разрешит соответствующий hook только когда operation присутствует в descriptor; runtime также выдаёт понятную ошибку при неправильном объекте.`}),`
|
|
13
|
+
`,(0,c.jsxs)(t.h2,{id:`persisted-или-resource`,children:[(0,c.jsx)(t.code,{children:`persisted`}),` или `,(0,c.jsx)(t.code,{children:`resource`})]}),`
|
|
14
|
+
`,(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:`Фиксированные сохранённые records: list/latest/history/save/create/delete`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`/persisted`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Произвольные названия и semantics операций`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.a,{href:`../resource/README.mdx`,children:(0,c.jsx)(t.code,{children:`/resource`})})})]})]})]}),`
|
|
15
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`persisted`}),` построен на тех же принципах keys/cache, но намеренно не является универсальным CRUD.`]}),`
|
|
16
|
+
`,(0,c.jsx)(t.h2,{id:`установка-и-provider`,children:`Установка и provider`}),`
|
|
17
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-bash`,children:`npm install @ryuzaki13/react-foundation-api @ryuzaki13/react-foundation-lib @tanstack/react-query react
|
|
18
|
+
`})}),`
|
|
19
|
+
`,(0,c.jsxs)(t.p,{children:[`Hooks требуют `,(0,c.jsx)(t.code,{children:`QueryClientProvider`}),`. Descriptor и operations создавайте на module level, чтобы ссылки были стабильными.`]}),`
|
|
20
|
+
`,(0,c.jsx)(t.h2,{id:`импорт`,children:`Импорт`}),`
|
|
21
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
|
|
22
|
+
applyPersistedCacheStrategy,
|
|
23
|
+
composePersistedCacheStrategies,
|
|
24
|
+
createInvalidatePersistedScopeCacheStrategy,
|
|
25
|
+
createPersistedJsonCodec,
|
|
26
|
+
createPersistedODataMutationOperation,
|
|
27
|
+
createPersistedODataQueryOperation,
|
|
28
|
+
createPersistedODataReadOperation,
|
|
29
|
+
createPersistedRecordKeys,
|
|
30
|
+
createPersistedResourceDescriptor,
|
|
31
|
+
createPersistedRestMutationOperation,
|
|
32
|
+
createPersistedRestQueryOperation,
|
|
33
|
+
createSetPersistedQueryDataCacheStrategy,
|
|
34
|
+
getPersistedHistoryData,
|
|
35
|
+
getPersistedLatestData,
|
|
36
|
+
getPersistedListData,
|
|
37
|
+
parsePersistedJson,
|
|
38
|
+
stringifyPersistedJson,
|
|
39
|
+
usePersistedCreateMutation,
|
|
40
|
+
usePersistedDeleteMutation,
|
|
41
|
+
usePersistedHistoryQuery,
|
|
42
|
+
usePersistedLatestQuery,
|
|
43
|
+
usePersistedListQuery,
|
|
44
|
+
usePersistedSaveMutation
|
|
45
|
+
} from "@ryuzaki13/react-foundation-api/persisted";
|
|
46
|
+
`})}),`
|
|
47
|
+
`,(0,c.jsx)(t.h2,{id:`пошаговый-rest-пример`,children:`Пошаговый REST пример`}),`
|
|
48
|
+
`,(0,c.jsx)(t.h3,{id:`1-контракты`,children:`1. Контракты`}),`
|
|
49
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type ViewScope = {
|
|
50
|
+
userId: string;
|
|
51
|
+
viewId: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type ViewConfig = {
|
|
55
|
+
columns: string[];
|
|
56
|
+
compact: boolean;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
type SavedViewRecord = {
|
|
60
|
+
id: string;
|
|
61
|
+
createdUtc: string;
|
|
62
|
+
payload: string;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
type SaveViewInput = {
|
|
66
|
+
payload: ViewConfig;
|
|
67
|
+
};
|
|
68
|
+
`})}),`
|
|
69
|
+
`,(0,c.jsx)(t.p,{children:`Внешний record и распарсенный config — разные типы. TypeScript не проверяет network payload автоматически.`}),`
|
|
70
|
+
`,(0,c.jsx)(t.h3,{id:`2-runtime-parsers`,children:`2. Runtime parsers`}),`
|
|
71
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function parseRecord(value: unknown): SavedViewRecord {
|
|
72
|
+
if (!isSavedViewRecord(value)) {
|
|
73
|
+
throw new Error("Некорректный SavedViewRecord payload");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function parseRecordList(value: unknown): SavedViewRecord[] {
|
|
80
|
+
if (!Array.isArray(value)) throw new Error("Ожидался массив records");
|
|
81
|
+
return value.map(parseRecord);
|
|
82
|
+
}
|
|
83
|
+
`})}),`
|
|
84
|
+
`,(0,c.jsx)(t.h3,{id:`3-operations`,children:`3. Operations`}),`
|
|
85
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const listOperation = createPersistedRestQueryOperation<
|
|
86
|
+
ViewScope,
|
|
87
|
+
void,
|
|
88
|
+
SavedViewRecord[]
|
|
89
|
+
>({
|
|
90
|
+
buildUrl: (scope) =>
|
|
91
|
+
\`/api/users/\${encodeURIComponent(scope.userId)}/views/\${encodeURIComponent(scope.viewId)}\`,
|
|
92
|
+
parseResponse: parseRecordList,
|
|
93
|
+
staleTime: 60_000
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const latestOperation = createPersistedRestQueryOperation<
|
|
97
|
+
ViewScope,
|
|
98
|
+
void,
|
|
99
|
+
SavedViewRecord,
|
|
100
|
+
ViewConfig | null
|
|
101
|
+
>({
|
|
102
|
+
buildUrl: (scope) =>
|
|
103
|
+
\`/api/users/\${encodeURIComponent(scope.userId)}/views/\${encodeURIComponent(scope.viewId)}/latest\`,
|
|
104
|
+
parseResponse: parseRecord,
|
|
105
|
+
transform: (record) => parsePersistedJson<ViewConfig>(record.payload)
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const saveOperation = createPersistedRestMutationOperation<
|
|
109
|
+
ViewScope,
|
|
110
|
+
SaveViewInput,
|
|
111
|
+
SavedViewRecord
|
|
112
|
+
>({
|
|
113
|
+
buildUrl: (scope) =>
|
|
114
|
+
\`/api/users/\${encodeURIComponent(scope.userId)}/views/\${encodeURIComponent(scope.viewId)}\`,
|
|
115
|
+
method: "PUT",
|
|
116
|
+
bodyMapper: (_scope, input) => ({
|
|
117
|
+
payload: stringifyPersistedJson(input.payload)
|
|
118
|
+
}),
|
|
119
|
+
parseResponse: parseRecord,
|
|
120
|
+
cacheStrategy: createInvalidatePersistedScopeCacheStrategy()
|
|
121
|
+
});
|
|
122
|
+
`})}),`
|
|
123
|
+
`,(0,c.jsx)(t.h3,{id:`4-descriptor`,children:`4. Descriptor`}),`
|
|
124
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const viewResource = createPersistedResourceDescriptor({
|
|
125
|
+
namespace: "view-config",
|
|
126
|
+
resource: "view",
|
|
127
|
+
normalizeScope: (scope: ViewScope | null | undefined) => ({
|
|
128
|
+
userId: scope?.userId.trim() ?? "",
|
|
129
|
+
viewId: scope?.viewId.trim() ?? ""
|
|
130
|
+
}),
|
|
131
|
+
isEnabled: (scope) => Boolean(scope?.userId && scope?.viewId),
|
|
132
|
+
getScopeError: () => "Не определён пользователь или представление",
|
|
133
|
+
transport: {
|
|
134
|
+
list: listOperation,
|
|
135
|
+
latest: latestOperation,
|
|
136
|
+
save: saveOperation
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
`})}),`
|
|
140
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`normalizeScope`}),` изменяет только cache identity. В `,(0,c.jsx)(t.code,{children:`buildUrl`}),`/`,(0,c.jsx)(t.code,{children:`execute`}),` передаётся исходный scope.`]}),`
|
|
141
|
+
`,(0,c.jsx)(t.h3,{id:`5-hooks`,children:`5. Hooks`}),`
|
|
142
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`const scope = { userId, viewId };
|
|
143
|
+
const latestQuery = usePersistedLatestQuery(viewResource, scope);
|
|
144
|
+
const listQuery = usePersistedListQuery(viewResource, scope);
|
|
145
|
+
const saveMutation = usePersistedSaveMutation(viewResource, scope);
|
|
146
|
+
|
|
147
|
+
saveMutation.mutate({
|
|
148
|
+
payload: { columns: ["name", "status"], compact: true }
|
|
149
|
+
});
|
|
150
|
+
`})}),`
|
|
151
|
+
`,(0,c.jsxs)(t.p,{children:[`Нельзя вызвать `,(0,c.jsx)(t.code,{children:`usePersistedHistoryQuery`}),` для этого descriptor, пока capability `,(0,c.jsx)(t.code,{children:`history`}),` не добавлена.`]}),`
|
|
152
|
+
`,(0,c.jsx)(t.h2,{id:`read-capabilities`,children:`Read capabilities`}),`
|
|
153
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Capability`}),(0,c.jsx)(t.th,{children:`Hook`}),(0,c.jsx)(t.th,{children:`Imperative helper`}),(0,c.jsx)(t.th,{children:`Args`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`list`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedListQuery`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getPersistedListData`})}),(0,c.jsxs)(t.td,{children:[`нет (`,(0,c.jsx)(t.code,{children:`void`}),`)`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`latest`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedLatestQuery`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getPersistedLatestData`})}),(0,c.jsxs)(t.td,{children:[`нет (`,(0,c.jsx)(t.code,{children:`void`}),`)`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`history`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedHistoryQuery`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getPersistedHistoryData`})}),(0,c.jsx)(t.td,{children:`обязательный generic args`})]})]})]}),`
|
|
154
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const page = await getPersistedHistoryData(
|
|
155
|
+
resourceWithHistory,
|
|
156
|
+
scope,
|
|
157
|
+
{ cursor: "next", limit: 20 },
|
|
158
|
+
queryClient
|
|
159
|
+
);
|
|
160
|
+
`})}),`
|
|
161
|
+
`,(0,c.jsxs)(t.p,{children:[`Query operation получает `,(0,c.jsx)(t.code,{children:`{ scope, args, client, signal }`}),`. `,(0,c.jsx)(t.code,{children:`isEnabled`}),` operation и descriptor определяют автоматический запуск React observer; `,(0,c.jsx)(t.code,{children:`staleTime`}),`, `,(0,c.jsx)(t.code,{children:`gcTime`}),`, `,(0,c.jsx)(t.code,{children:`meta`}),` переходят в TanStack Query options.`]}),`
|
|
162
|
+
`,(0,c.jsxs)(t.p,{children:[`Imperative helpers используют `,(0,c.jsx)(t.code,{children:`queryClient.fetchQuery`}),`. Передавайте валидный scope; disabled policy в первую очередь управляет observer, а фактическая query function всё равно проверяет scope.`]}),`
|
|
163
|
+
`,(0,c.jsx)(t.h2,{id:`write-capabilities`,children:`Write capabilities`}),`
|
|
164
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Capability`}),(0,c.jsx)(t.th,{children:`Hook`}),(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:`save`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedSaveMutation`})}),(0,c.jsx)(t.td,{children:`Сохранить/обновить snapshot`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`create`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedCreateMutation`})}),(0,c.jsx)(t.td,{children:`Создать новую именованную запись`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`delete`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedDeleteMutation`})}),(0,c.jsx)(t.td,{children:`Удалить запись`})]})]})]}),`
|
|
165
|
+
`,(0,c.jsxs)(t.p,{children:[`Mutation operation получает `,(0,c.jsx)(t.code,{children:`{ scope, input, client }`}),`. Generic persisted contract не передаёт `,(0,c.jsx)(t.code,{children:`AbortSignal`}),` для mutation.`]}),`
|
|
166
|
+
`,(0,c.jsx)(t.p,{children:`После успешного transport:`}),`
|
|
167
|
+
`,(0,c.jsxs)(t.ol,{children:[`
|
|
168
|
+
`,(0,c.jsx)(t.li,{children:`выбирается cache strategy;`}),`
|
|
169
|
+
`,(0,c.jsx)(t.li,{children:`strategy выполняется и awaited;`}),`
|
|
170
|
+
`,(0,c.jsxs)(t.li,{children:[`вызывается optional hook `,(0,c.jsx)(t.code,{children:`onSuccess(result, input)`}),`.`]}),`
|
|
171
|
+
`]}),`
|
|
172
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`usePersistedSaveMutation(resource, scope, {
|
|
173
|
+
cacheStrategy: null, // Отключить operation strategy.
|
|
174
|
+
onSuccess(result) {
|
|
175
|
+
showSuccess(\`Сохранено \${result.id}\`);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
`})}),`
|
|
179
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`cacheStrategy: undefined`}),` использует strategy операции; `,(0,c.jsx)(t.code,{children:`null`}),` отключает; объект заменяет исходную strategy. Для дополнения применяйте композицию.`]}),`
|
|
180
|
+
`,(0,c.jsx)(t.h2,{id:`query-keys`,children:`Query keys`}),`
|
|
181
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const keys = createPersistedRecordKeys<ViewScope>({
|
|
182
|
+
namespace: "view-config",
|
|
183
|
+
resource: "view",
|
|
184
|
+
normalizeScope: (scope) => ({
|
|
185
|
+
userId: scope?.userId ?? "",
|
|
186
|
+
viewId: scope?.viewId ?? ""
|
|
187
|
+
})
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
keys.all;
|
|
191
|
+
keys.scope(scope);
|
|
192
|
+
keys.list(scope);
|
|
193
|
+
keys.latest(scope);
|
|
194
|
+
keys.history(scope, { limit: 20 });
|
|
195
|
+
keys.save(scope);
|
|
196
|
+
keys.create(scope);
|
|
197
|
+
keys.delete(scope);
|
|
198
|
+
`})}),`
|
|
199
|
+
`,(0,c.jsx)(t.p,{children:`Форма:`}),`
|
|
200
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`[namespace, resource, normalizedScope, operation, optionalArgs]
|
|
201
|
+
`})}),`
|
|
202
|
+
`,(0,c.jsxs)(t.p,{children:[`Используется нормализация `,(0,c.jsx)(t.code,{children:`/resource`}),`: strings trim, object keys сортируются, `,(0,c.jsx)(t.code,{children:`undefined`}),` становится `,(0,c.jsx)(t.code,{children:`null`}),`. Date/Map/cyclic object требуют явного нормализатора.`]}),`
|
|
203
|
+
`,(0,c.jsx)(t.h2,{id:`json-payload-codec`,children:`JSON payload codec`}),`
|
|
204
|
+
`,(0,c.jsx)(t.h3,{id:`parse`,children:`Parse`}),`
|
|
205
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`parsePersistedJson<ViewConfig>(null); // null.
|
|
206
|
+
parsePersistedJson<ViewConfig>(""); // null.
|
|
207
|
+
parsePersistedJson<ViewConfig>("broken"); // null.
|
|
208
|
+
parsePersistedJson<ViewConfig>('{"compact":true,"columns":[]}');
|
|
209
|
+
// Object, но без runtime validation.
|
|
210
|
+
`})}),`
|
|
211
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`parsePersistedJson<T>`}),` только вызывает `,(0,c.jsx)(t.code,{children:`JSON.parse`}),` и делает TypeScript cast. Он не проверяет schema. После parse примените domain validator/normalizer на явной restore boundary.`]}),`
|
|
212
|
+
`,(0,c.jsx)(t.h3,{id:`stringify`,children:`Stringify`}),`
|
|
213
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const payload = stringifyPersistedJson({ compact: false, columns: [] });
|
|
214
|
+
`})}),`
|
|
215
|
+
`,(0,c.jsxs)(t.p,{children:[`Ошибки `,(0,c.jsx)(t.code,{children:`JSON.stringify`}),` пробрасываются. Передавайте только JSON-compatible данные. В частности:`]}),`
|
|
216
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
217
|
+
`,(0,c.jsxs)(t.li,{children:[`cyclic object и `,(0,c.jsx)(t.code,{children:`BigInt`}),` приводят к ошибке;`]}),`
|
|
218
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`Date`}),` превращается в ISO string;`]}),`
|
|
219
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`undefined`}),` в object-поле удаляется;`]}),`
|
|
220
|
+
`,(0,c.jsxs)(t.li,{children:[`вызов с корневым `,(0,c.jsx)(t.code,{children:`undefined`}),` фактически может вернуть `,(0,c.jsx)(t.code,{children:`undefined`}),`, несмотря на заявленный string contract — не передавайте его.`]}),`
|
|
221
|
+
`]}),`
|
|
222
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedJsonCodec<T>()`}),` возвращает `,(0,c.jsx)(t.code,{children:`{ parse, stringify }`}),` для передачи единым контрактом.`]}),`
|
|
223
|
+
`,(0,c.jsx)(t.h2,{id:`rest-adapters`,children:`REST adapters`}),`
|
|
224
|
+
`,(0,c.jsx)(t.h3,{id:`query`,children:`Query`}),`
|
|
225
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedRestQueryOperation`}),` принимает:`]}),`
|
|
226
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
227
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`buildUrl(scope, args)`}),` — относительный или абсолютный URL;`]}),`
|
|
228
|
+
`,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`baseUrl`}),`;`]}),`
|
|
229
|
+
`,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`buildInit(scope, args)`}),`;`]}),`
|
|
230
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`parseResponse(unknown)`}),` или custom `,(0,c.jsx)(t.code,{children:`executor`}),`;`]}),`
|
|
231
|
+
`,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`transform`}),`;`]}),`
|
|
232
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`staleTime`}),`, `,(0,c.jsx)(t.code,{children:`gcTime`}),`, `,(0,c.jsx)(t.code,{children:`isEnabled`}),`.`]}),`
|
|
233
|
+
`]}),`
|
|
234
|
+
`,(0,c.jsxs)(t.p,{children:[`Если нет ни `,(0,c.jsx)(t.code,{children:`executor`}),`, ни `,(0,c.jsx)(t.code,{children:`parseResponse`}),`, operation бросит `,(0,c.jsx)(t.code,{children:`REST persisted operation requires executor or parseResponse.`})]}),`
|
|
235
|
+
`,(0,c.jsxs)(t.p,{children:[`Read signal всегда записывается поверх `,(0,c.jsx)(t.code,{children:`buildInit.signal`}),`, чтобы текущая TanStack Query отменяла именно свой запрос.`]}),`
|
|
236
|
+
`,(0,c.jsx)(t.h3,{id:`mutation`,children:`Mutation`}),`
|
|
237
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedRestMutationOperation`}),` поддерживает method `,(0,c.jsx)(t.code,{children:`POST`}),`, `,(0,c.jsx)(t.code,{children:`PUT`}),`, `,(0,c.jsx)(t.code,{children:`DELETE`}),`.`]}),`
|
|
238
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
239
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`bodyMapper(scope, input)`}),` создаёт JSON body;`]}),`
|
|
240
|
+
`,(0,c.jsxs)(t.li,{children:[`если mapper отсутствует/вернул `,(0,c.jsx)(t.code,{children:`undefined`}),`, body и default Content-Type не задаются;`]}),`
|
|
241
|
+
`,(0,c.jsxs)(t.li,{children:[`иначе body сериализуется и default header равен `,(0,c.jsx)(t.code,{children:`application/json`}),`;`]}),`
|
|
242
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`buildInit`}),` применяется после default headers и может полностью заменить headers;`]}),`
|
|
243
|
+
`,(0,c.jsxs)(t.li,{children:[`response обязательно проходит `,(0,c.jsx)(t.code,{children:`parseResponse`}),` или custom executor;`]}),`
|
|
244
|
+
`,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`transform`}),` строит domain result;`]}),`
|
|
245
|
+
`,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`cacheStrategy`}),` прикрепляется к operation.`]}),`
|
|
246
|
+
`]}),`
|
|
247
|
+
`,(0,c.jsxs)(t.p,{children:[`REST adapter использует нейтральный `,(0,c.jsx)(t.code,{children:`/http`}),`: SAP SSO/X-CSRF policy здесь нет.`]}),`
|
|
248
|
+
`,(0,c.jsx)(t.h2,{id:`odata-adapters`,children:`OData adapters`}),`
|
|
249
|
+
`,(0,c.jsxs)(t.p,{children:[`OData operations используют metadata-aware transport из `,(0,c.jsx)(t.a,{href:`../odata/README.mdx`,children:(0,c.jsx)(t.code,{children:`/odata`})}),`.`]}),`
|
|
250
|
+
`,(0,c.jsx)(t.h3,{id:`query-collection`,children:`Query collection`}),`
|
|
251
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const list = createPersistedODataQueryOperation<
|
|
252
|
+
ViewScope,
|
|
253
|
+
void,
|
|
254
|
+
SavedViewRecord[]
|
|
255
|
+
>({
|
|
256
|
+
odata: { service: "Z_VIEW_CONFIG_SRV", target: "ViewSet" },
|
|
257
|
+
buildOptions: (scope) => ({
|
|
258
|
+
expression: createFilterEqual("UserId", scope.userId)
|
|
259
|
+
}),
|
|
260
|
+
transform: (rows) => rows
|
|
261
|
+
});
|
|
262
|
+
`})}),`
|
|
263
|
+
`,(0,c.jsxs)(t.p,{children:[`Доступные options factory: `,(0,c.jsx)(t.code,{children:`odata`}),`, optional `,(0,c.jsx)(t.code,{children:`baseUrl`}),`, `,(0,c.jsx)(t.code,{children:`buildParams`}),`, `,(0,c.jsx)(t.code,{children:`buildOptions`}),`, `,(0,c.jsx)(t.code,{children:`buildInit`}),`, `,(0,c.jsx)(t.code,{children:`transform`}),`, `,(0,c.jsx)(t.code,{children:`executor`}),`, `,(0,c.jsx)(t.code,{children:`staleTime`}),`, `,(0,c.jsx)(t.code,{children:`gcTime`}),`, `,(0,c.jsx)(t.code,{children:`meta`}),`, `,(0,c.jsx)(t.code,{children:`isEnabled`}),`.`]}),`
|
|
264
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedODataQueryOperation`}),` использует semantic method `,(0,c.jsx)(t.code,{children:`query`}),` и возвращает collection response data. `,(0,c.jsx)(t.code,{children:`createPersistedODataReadOperation`}),` использует `,(0,c.jsx)(t.code,{children:`read`}),` для одной entity по key parameters:`]}),`
|
|
265
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const latest = createPersistedODataReadOperation({
|
|
266
|
+
odata: { service: "Z_VIEW_CONFIG_SRV", target: "ViewSet" },
|
|
267
|
+
buildParams: (scope: ViewScope) => wrapODataParams({
|
|
268
|
+
UserId: scope.userId,
|
|
269
|
+
ViewId: scope.viewId
|
|
270
|
+
}),
|
|
271
|
+
transform: (record: SavedViewRecord) =>
|
|
272
|
+
parsePersistedJson<ViewConfig>(record.payload)
|
|
273
|
+
});
|
|
274
|
+
`})}),`
|
|
275
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`buildParams`}),` должен возвращать wrapped OData parameters из `,(0,c.jsx)(t.code,{children:`foundation-lib/odata-service`}),`.`]}),`
|
|
276
|
+
`,(0,c.jsx)(t.h3,{id:`mutation-1`,children:`Mutation`}),`
|
|
277
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const save = createPersistedODataMutationOperation({
|
|
278
|
+
odata: { service: "Z_VIEW_CONFIG_SRV", target: "ViewSet" },
|
|
279
|
+
method: "update",
|
|
280
|
+
buildParams: (scope: ViewScope) => wrapODataParams({
|
|
281
|
+
UserId: scope.userId,
|
|
282
|
+
ViewId: scope.viewId
|
|
283
|
+
}),
|
|
284
|
+
bodyMapper: (_scope, input: SaveViewInput) => ({
|
|
285
|
+
Payload: stringifyPersistedJson(input.payload)
|
|
286
|
+
}),
|
|
287
|
+
cacheStrategy: createInvalidatePersistedScopeCacheStrategy()
|
|
288
|
+
});
|
|
289
|
+
`})}),`
|
|
290
|
+
`,(0,c.jsx)(t.p,{children:`Semantic methods:`}),`
|
|
291
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Method`}),(0,c.jsx)(t.th,{children:`Params`}),(0,c.jsx)(t.th,{children:`Body`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`create`})}),(0,c.jsx)(t.td,{children:`запрещены`}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`bodyMapper`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`update`})}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`buildParams`})]}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`bodyMapper`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`delete`})}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`buildParams`})]}),(0,c.jsx)(t.td,{children:`запрещён`})]})]})]}),`
|
|
292
|
+
`,(0,c.jsxs)(t.p,{children:[`Это OData operation names, а не raw HTTP strings. Не передавайте `,(0,c.jsx)(t.code,{children:`"PUT"`}),`/`,(0,c.jsx)(t.code,{children:`"POST"`}),`.`]}),`
|
|
293
|
+
`,(0,c.jsx)(t.p,{children:`OData adapter наследует metadata validation, SAP cookies, SSO recovery и X-CSRF lifecycle. Query/read получают AbortSignal; mutations — нет в generic contract.`}),`
|
|
294
|
+
`,(0,c.jsx)(t.h2,{id:`custom-и-server-function-operations`,children:`Custom и server-function operations`}),`
|
|
295
|
+
`,(0,c.jsxs)(t.p,{children:[`Descriptor принимает любой object, соответствующий `,(0,c.jsx)(t.code,{children:`PersistedQueryOperation`}),`/`,(0,c.jsx)(t.code,{children:`PersistedMutationOperation`}),`. Server-function factories из `,(0,c.jsx)(t.a,{href:`../server-fn/README.mdx`,children:(0,c.jsx)(t.code,{children:`/server-fn`})}),` возвращают совместимые resource operations и могут быть использованы как capabilities, если их generic contract совпадает.`]}),`
|
|
296
|
+
`,(0,c.jsx)(t.h2,{id:`cache-strategies`,children:`Cache strategies`}),`
|
|
297
|
+
`,(0,c.jsx)(t.h3,{id:`инвалидация-всего-scope`,children:`Инвалидация всего scope`}),`
|
|
298
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const invalidate = createInvalidatePersistedScopeCacheStrategy();
|
|
299
|
+
`})}),`
|
|
300
|
+
`,(0,c.jsxs)(t.p,{children:[`Инвалидирует prefix `,(0,c.jsx)(t.code,{children:`descriptor.keys.scope(scope)`}),`, поэтому затрагивает list/latest/history данного scope.`]}),`
|
|
301
|
+
`,(0,c.jsx)(t.h3,{id:`точечное-обновление`,children:`Точечное обновление`}),`
|
|
302
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const setLatest = createSetPersistedQueryDataCacheStrategy({
|
|
303
|
+
getQueryKey: ({ descriptor, scope }) => descriptor.keys.latest(scope),
|
|
304
|
+
update: (_current, { result }) => result
|
|
305
|
+
});
|
|
306
|
+
`})}),`
|
|
307
|
+
`,(0,c.jsx)(t.h3,{id:`композиция`,children:`Композиция`}),`
|
|
308
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const combined = composePersistedCacheStrategies(setLatest, invalidate);
|
|
309
|
+
`})}),`
|
|
310
|
+
`,(0,c.jsxs)(t.p,{children:[`Порядок последовательный. Если strategy бросила ошибку, следующие steps и hook `,(0,c.jsx)(t.code,{children:`onSuccess`}),` не выполняются, хотя backend mutation уже могла завершиться.`]}),`
|
|
311
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`applyPersistedCacheStrategy`}),` — низкоуровневый helper для ручного вызова optional strategy.`]}),`
|
|
312
|
+
`,(0,c.jsx)(t.h2,{id:`ошибки-и-безопасность`,children:`Ошибки и безопасность`}),`
|
|
313
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
314
|
+
`,(0,c.jsxs)(t.li,{children:[`Scope `,(0,c.jsx)(t.code,{children:`null`}),`/`,(0,c.jsx)(t.code,{children:`undefined`}),` или rejected `,(0,c.jsx)(t.code,{children:`isEnabled`}),` блокирует query и вызывает ошибку при фактическом execution.`]}),`
|
|
315
|
+
`,(0,c.jsxs)(t.li,{children:[`Network payload валидируйте в `,(0,c.jsx)(t.code,{children:`parseResponse`}),`/`,(0,c.jsx)(t.code,{children:`transform`}),`; TypeScript generic не является validator-ом.`]}),`
|
|
316
|
+
`,(0,c.jsx)(t.li,{children:`Не храните secrets в payload/query keys/client persistence.`}),`
|
|
317
|
+
`,(0,c.jsx)(t.li,{children:`Save/create должны быть идемпотентны настолько, насколько это возможно для retry policy.`}),`
|
|
318
|
+
`,(0,c.jsx)(t.li,{children:`Cache update — локальная проекция, backend остаётся source of truth.`}),`
|
|
319
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`parsePersistedJson`}),` подавляет syntax error и возвращает `,(0,c.jsx)(t.code,{children:`null`}),`; различайте «нет payload» и «повреждён payload» на уровне продукта, если это важно.`]}),`
|
|
320
|
+
`]}),`
|
|
321
|
+
`,(0,c.jsx)(t.h2,{id:`полный-api`,children:`Полный API`}),`
|
|
322
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Группа`}),(0,c.jsx)(t.th,{children:`Exports`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Descriptor/keys`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`createPersistedResourceDescriptor`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedRecordKeys`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`React reads`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`usePersistedListQuery`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedLatestQuery`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedHistoryQuery`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Imperative reads`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getPersistedListData`}),`, `,(0,c.jsx)(t.code,{children:`getPersistedLatestData`}),`, `,(0,c.jsx)(t.code,{children:`getPersistedHistoryData`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Mutations`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`usePersistedSaveMutation`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedCreateMutation`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedDeleteMutation`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Payload`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`parsePersistedJson`}),`, `,(0,c.jsx)(t.code,{children:`stringifyPersistedJson`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedJsonCodec`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`REST adapters`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`createPersistedRestQueryOperation`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedRestMutationOperation`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`OData adapters`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`createPersistedODataQueryOperation`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedODataReadOperation`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedODataMutationOperation`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Cache`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`applyPersistedCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`createInvalidatePersistedScopeCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`createSetPersistedQueryDataCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`composePersistedCacheStrategies`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Names/types`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`PersistedReadOperationName`}),`, `,(0,c.jsx)(t.code,{children:`PersistedWriteOperationName`}),`, `,(0,c.jsx)(t.code,{children:`PersistedOperationName`}),`, `,(0,c.jsx)(t.code,{children:`PersistedPayloadCodec`}),`, `,(0,c.jsx)(t.code,{children:`PersistedRecordKeys`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Operation contracts`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`PersistedQueryOperationContext`}),`, `,(0,c.jsx)(t.code,{children:`PersistedMutationOperationContext`}),`, `,(0,c.jsx)(t.code,{children:`PersistedQueryOperation`}),`, `,(0,c.jsx)(t.code,{children:`PersistedMutationOperation`}),`, `,(0,c.jsx)(t.code,{children:`PersistedOperationCapabilities`}),`, `,(0,c.jsx)(t.code,{children:`PersistedTransportAdapter`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Descriptor/cache contracts`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`PersistedResourceDescriptor`}),`, `,(0,c.jsx)(t.code,{children:`CreatePersistedResourceDescriptorOptions`}),`, `,(0,c.jsx)(t.code,{children:`PersistedCacheStrategyContext`}),`, `,(0,c.jsx)(t.code,{children:`PersistedCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`PersistedSetQueryDataStrategyOptions`})]})]})]})]})]})}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};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe-FSp_AjJa.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-B5YBxaaS.js";function o(e){let t={a:`a`,code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,li:`li`,p:`p`,pre:`pre`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation Lib/Interaction/Context Menu State`}),`
|
|
2
|
+
`,(0,c.jsxs)(t.h1,{id:`состояние-и-anchors-контекстного-меню-через-ryuzaki13react-foundation-libcontext-menu`,children:[`Состояние и anchors контекстного меню через `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/context-menu`})]}),`
|
|
3
|
+
`,(0,c.jsx)(t.p,{children:`Модуль описывает открытое/закрытое состояние контекстного меню, источник открытия и два вида anchor: DOM element или экранная точка. Также он создаёт virtual anchor для Floating UI.`}),`
|
|
4
|
+
`,(0,c.jsx)(t.p,{children:`Модуль не содержит React hook и не рисует меню.`}),`
|
|
5
|
+
`,(0,c.jsx)(t.h2,{id:`содержание`,children:`Содержание`}),`
|
|
6
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
7
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B8-%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B`,children:`Назначение и границы`})}),`
|
|
8
|
+
`,(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:`Установка и импорт`})}),`
|
|
9
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85`,children:`Модель данных`})}),`
|
|
10
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%82%D0%BE%D1%87%D0%BA%D0%B8`,children:`Получение точки`})}),`
|
|
11
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#createvirtualanchor`,children:(0,c.jsx)(t.code,{children:`createVirtualAnchor`})})}),`
|
|
12
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#state-helpers`,children:`State helpers`})}),`
|
|
13
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#react-reducer-recipe`,children:`React reducer recipe`})}),`
|
|
14
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#floating-ui-recipe`,children:`Floating UI recipe`})}),`
|
|
15
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BD%D0%BE%D1%81%D1%82%D1%8C`,children:`Доступность`})}),`
|
|
16
|
+
`,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BF%D0%BE%D0%BB%D0%BD%D1%8B%D0%B9-api-%D0%B8-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B8`,children:`Полный API и ошибки`})}),`
|
|
17
|
+
`]}),`
|
|
18
|
+
`,(0,c.jsx)(t.h2,{id:`назначение-и-границы`,children:`Назначение и границы`}),`
|
|
19
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`click/contextmenu/keyboard
|
|
20
|
+
│
|
|
21
|
+
├─ element anchor
|
|
22
|
+
└─ point {x,y}
|
|
23
|
+
│
|
|
24
|
+
▼
|
|
25
|
+
MenuState
|
|
26
|
+
│
|
|
27
|
+
▼
|
|
28
|
+
host React/Floating UI/menu component
|
|
29
|
+
`})}),`
|
|
30
|
+
`,(0,c.jsx)(t.p,{children:`Модуль:`}),`
|
|
31
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
32
|
+
`,(0,c.jsx)(t.li,{children:`не добавляет event listeners;`}),`
|
|
33
|
+
`,(0,c.jsxs)(t.li,{children:[`не вызывает `,(0,c.jsx)(t.code,{children:`preventDefault`}),`;`]}),`
|
|
34
|
+
`,(0,c.jsx)(t.li,{children:`не хранит global state;`}),`
|
|
35
|
+
`,(0,c.jsx)(t.li,{children:`не позиционирует floating element;`}),`
|
|
36
|
+
`,(0,c.jsx)(t.li,{children:`не закрывает меню по Escape/outside click;`}),`
|
|
37
|
+
`,(0,c.jsx)(t.li,{children:`не управляет focus/ARIA;`}),`
|
|
38
|
+
`,(0,c.jsx)(t.li,{children:`не клонирует DOM elements.`}),`
|
|
39
|
+
`]}),`
|
|
40
|
+
`,(0,c.jsxs)(t.p,{children:[`Готовый visual primitive находится в `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-ui/context-menu`}),`.`]}),`
|
|
41
|
+
`,(0,c.jsx)(t.h2,{id:`установка-и-импорт`,children:`Установка и импорт`}),`
|
|
42
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
|
|
43
|
+
closeMenu,
|
|
44
|
+
createVirtualAnchor,
|
|
45
|
+
getMenuPointFromEvent,
|
|
46
|
+
getMenuPointFromRect,
|
|
47
|
+
initialMenuState,
|
|
48
|
+
openMenu,
|
|
49
|
+
toggleMenu
|
|
50
|
+
} from "@ryuzaki13/react-foundation-lib/context-menu";
|
|
51
|
+
|
|
52
|
+
import type {
|
|
53
|
+
ElementMenuAnchor,
|
|
54
|
+
MenuAnchor,
|
|
55
|
+
MenuOpenSource,
|
|
56
|
+
MenuPoint,
|
|
57
|
+
MenuState,
|
|
58
|
+
OpenMenuPayload,
|
|
59
|
+
PointMenuAnchor
|
|
60
|
+
} from "@ryuzaki13/react-foundation-lib/context-menu";
|
|
61
|
+
`})}),`
|
|
62
|
+
`,(0,c.jsxs)(t.p,{children:[`Functions pure, но types/anchors используют DOM `,(0,c.jsx)(t.code,{children:`Element`}),`/`,(0,c.jsx)(t.code,{children:`HTMLElement`}),`. Публичный subpath не импортирует Floating UI runtime.`]}),`
|
|
63
|
+
`,(0,c.jsx)(t.h2,{id:`модель-данных`,children:`Модель данных`}),`
|
|
64
|
+
`,(0,c.jsx)(t.h3,{id:`point`,children:`Point`}),`
|
|
65
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`interface MenuPoint {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
}
|
|
69
|
+
`})}),`
|
|
70
|
+
`,(0,c.jsx)(t.p,{children:`Координаты соответствуют viewport/client coordinates, а не page scroll coordinates.`}),`
|
|
71
|
+
`,(0,c.jsx)(t.h3,{id:`источник-открытия`,children:`Источник открытия`}),`
|
|
72
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type MenuOpenSource = "click" | "contextmenu" | "keyboard" | "programmatic";
|
|
73
|
+
`})}),`
|
|
74
|
+
`,(0,c.jsx)(t.p,{children:`Source помогает UI выбирать focus/animation/recovery, но helpers сами не меняют поведение по source.`}),`
|
|
75
|
+
`,(0,c.jsx)(t.h3,{id:`anchors`,children:`Anchors`}),`
|
|
76
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type ElementMenuAnchor = {
|
|
77
|
+
type: "element";
|
|
78
|
+
element: HTMLElement;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
type PointMenuAnchor = {
|
|
82
|
+
type: "point";
|
|
83
|
+
point: MenuPoint;
|
|
84
|
+
contextElement?: Element | null;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
type MenuAnchor = ElementMenuAnchor | PointMenuAnchor;
|
|
88
|
+
`})}),`
|
|
89
|
+
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`contextElement`}),` помогает Floating UI определить document/layout context для virtual element.`]}),`
|
|
90
|
+
`,(0,c.jsx)(t.h3,{id:`state`,children:`State`}),`
|
|
91
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`interface MenuState {
|
|
92
|
+
open: boolean;
|
|
93
|
+
source: MenuOpenSource | null;
|
|
94
|
+
anchor: MenuAnchor | null;
|
|
95
|
+
}
|
|
96
|
+
`})}),`
|
|
97
|
+
`,(0,c.jsx)(t.p,{children:`Нормальное закрытое состояние:`}),`
|
|
98
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`{
|
|
99
|
+
open: false,
|
|
100
|
+
source: null,
|
|
101
|
+
anchor: null
|
|
102
|
+
}
|
|
103
|
+
`})}),`
|
|
104
|
+
`,(0,c.jsx)(t.h2,{id:`получение-точки`,children:`Получение точки`}),`
|
|
105
|
+
`,(0,c.jsx)(t.h3,{id:`getmenupointfromevent`,children:(0,c.jsx)(t.code,{children:`getMenuPointFromEvent`})}),`
|
|
106
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function onContextMenu(event: React.MouseEvent<HTMLElement>) {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
|
|
109
|
+
const point = getMenuPointFromEvent(event);
|
|
110
|
+
// { x: event.clientX, y: event.clientY }.
|
|
111
|
+
}
|
|
112
|
+
`})}),`
|
|
113
|
+
`,(0,c.jsxs)(t.p,{children:[`Функции нужен только structural object с `,(0,c.jsx)(t.code,{children:`clientX`}),`/`,(0,c.jsx)(t.code,{children:`clientY`}),`, поэтому подходят native и React mouse events.`]}),`
|
|
114
|
+
`,(0,c.jsxs)(t.p,{children:[`Она не вызывает `,(0,c.jsx)(t.code,{children:`preventDefault`}),` и не проверяет finite coordinates.`]}),`
|
|
115
|
+
`,(0,c.jsx)(t.h3,{id:`getmenupointfromrect`,children:(0,c.jsx)(t.code,{children:`getMenuPointFromRect`})}),`
|
|
116
|
+
`,(0,c.jsx)(t.p,{children:`Возвращает геометрический центр rect:`}),`
|
|
117
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const point = getMenuPointFromRect({
|
|
118
|
+
left: 10,
|
|
119
|
+
top: 20,
|
|
120
|
+
width: 80,
|
|
121
|
+
height: 40
|
|
122
|
+
});
|
|
123
|
+
// { x: 50, y: 40 }.
|
|
124
|
+
`})}),`
|
|
125
|
+
`,(0,c.jsxs)(t.p,{children:[`Подходит для keyboard opening от центра `,(0,c.jsx)(t.code,{children:`element.getBoundingClientRect()`}),`:`]}),`
|
|
126
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const point = getMenuPointFromRect(button.getBoundingClientRect());
|
|
127
|
+
`})}),`
|
|
128
|
+
`,(0,c.jsx)(t.h2,{id:`createvirtualanchor`,children:(0,c.jsx)(t.code,{children:`createVirtualAnchor`})}),`
|
|
129
|
+
`,(0,c.jsxs)(t.p,{children:[`Создаёт object с `,(0,c.jsx)(t.code,{children:`getBoundingClientRect`}),`, представляющий точку нулевого размера:`]}),`
|
|
130
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const virtualAnchor = createVirtualAnchor({ x: 120, y: 240 }, triggerElement);
|
|
131
|
+
`})}),`
|
|
132
|
+
`,(0,c.jsx)(t.p,{children:`Возвращаемый rect:`}),`
|
|
133
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`{
|
|
134
|
+
x: 120,
|
|
135
|
+
y: 240,
|
|
136
|
+
top: 240,
|
|
137
|
+
left: 120,
|
|
138
|
+
bottom: 240,
|
|
139
|
+
right: 120,
|
|
140
|
+
width: 0,
|
|
141
|
+
height: 0,
|
|
142
|
+
toJSON: () => undefined
|
|
143
|
+
}
|
|
144
|
+
`})}),`
|
|
145
|
+
`,(0,c.jsxs)(t.p,{children:[`Если `,(0,c.jsx)(t.code,{children:`contextElement`}),` равен `,(0,c.jsx)(t.code,{children:`null`}),`/`,(0,c.jsx)(t.code,{children:`undefined`}),`, в результате поле становится `,(0,c.jsx)(t.code,{children:`undefined`}),`.`]}),`
|
|
146
|
+
`,(0,c.jsxs)(t.p,{children:[`Point object читается при каждом `,(0,c.jsx)(t.code,{children:`getBoundingClientRect`}),`. Не мутируйте его; создайте новый anchor при изменении координат.`]}),`
|
|
147
|
+
`,(0,c.jsx)(t.h2,{id:`state-helpers`,children:`State helpers`}),`
|
|
148
|
+
`,(0,c.jsx)(t.h3,{id:`initialmenustate`,children:(0,c.jsx)(t.code,{children:`initialMenuState`})}),`
|
|
149
|
+
`,(0,c.jsx)(t.p,{children:`Экспортируется один module-level object. Рассматривайте его как readonly-константу и не мутируйте:`}),`
|
|
150
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const [state, setState] = useState<MenuState>(initialMenuState);
|
|
151
|
+
`})}),`
|
|
152
|
+
`,(0,c.jsx)(t.h3,{id:`openmenu`,children:(0,c.jsx)(t.code,{children:`openMenu`})}),`
|
|
153
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const state = openMenu({
|
|
154
|
+
source: "contextmenu",
|
|
155
|
+
anchor: {
|
|
156
|
+
type: "point",
|
|
157
|
+
point: { x: 100, y: 200 }
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
`})}),`
|
|
161
|
+
`,(0,c.jsxs)(t.p,{children:[`Всегда возвращает новый state `,(0,c.jsx)(t.code,{children:`{ open: true, source, anchor }`}),`. Anchor/element переносятся по ссылке.`]}),`
|
|
162
|
+
`,(0,c.jsx)(t.h3,{id:`closemenu`,children:(0,c.jsx)(t.code,{children:`closeMenu`})}),`
|
|
163
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const closed = closeMenu(opened);
|
|
164
|
+
`})}),`
|
|
165
|
+
`,(0,c.jsxs)(t.p,{children:[`Открытое состояние превращается в canonical closed state. Если `,(0,c.jsx)(t.code,{children:`state.open === false`}),` и `,(0,c.jsx)(t.code,{children:`state.anchor === null`}),`, возвращается исходная ссылка `,(0,c.jsx)(t.code,{children:`state`}),`, что удобно для reducer no-op.`]}),`
|
|
166
|
+
`,(0,c.jsxs)(t.p,{children:[`Передавайте согласованное состояние. Если вручную создать `,(0,c.jsx)(t.code,{children:`{ open:false, source:"click", anchor:null }`}),`, `,(0,c.jsx)(t.code,{children:`closeMenu`}),` вернёт его без очистки source.`]}),`
|
|
167
|
+
`,(0,c.jsx)(t.h3,{id:`togglemenu`,children:(0,c.jsx)(t.code,{children:`toggleMenu`})}),`
|
|
168
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const next = toggleMenu(current, payload);
|
|
169
|
+
`})}),`
|
|
170
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
171
|
+
`,(0,c.jsxs)(t.li,{children:[`если `,(0,c.jsx)(t.code,{children:`current.open === true`}),`, закрывает меню и игнорирует payload;`]}),`
|
|
172
|
+
`,(0,c.jsxs)(t.li,{children:[`если меню закрыто, вызывает `,(0,c.jsx)(t.code,{children:`openMenu(payload)`}),`.`]}),`
|
|
173
|
+
`]}),`
|
|
174
|
+
`,(0,c.jsxs)(t.p,{children:[`Toggle подходит для click button. Для `,(0,c.jsx)(t.code,{children:`contextmenu`}),` чаще нужен явный `,(0,c.jsx)(t.code,{children:`openMenu`}),`, чтобы повторный right-click перемещал anchor, а не закрывал меню.`]}),`
|
|
175
|
+
`,(0,c.jsx)(t.h2,{id:`react-reducer-recipe`,children:`React reducer recipe`}),`
|
|
176
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`const [menu, setMenu] = useState<MenuState>(initialMenuState);
|
|
177
|
+
|
|
178
|
+
function handleContextMenu(event: React.MouseEvent<HTMLElement>) {
|
|
179
|
+
event.preventDefault();
|
|
180
|
+
|
|
181
|
+
setMenu(
|
|
182
|
+
openMenu({
|
|
183
|
+
source: "contextmenu",
|
|
184
|
+
anchor: {
|
|
185
|
+
type: "point",
|
|
186
|
+
point: getMenuPointFromEvent(event),
|
|
187
|
+
contextElement: event.currentTarget
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function handleClose() {
|
|
194
|
+
setMenu((current) => closeMenu(current));
|
|
195
|
+
}
|
|
196
|
+
`})}),`
|
|
197
|
+
`,(0,c.jsxs)(t.p,{children:[`Не сохраняйте `,(0,c.jsx)(t.code,{children:`MenuState`}),` в JSON/localStorage: он может содержать `,(0,c.jsx)(t.code,{children:`HTMLElement`}),`.`]}),`
|
|
198
|
+
`,(0,c.jsx)(t.h2,{id:`floating-ui-recipe`,children:`Floating UI recipe`}),`
|
|
199
|
+
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const reference =
|
|
200
|
+
menu.anchor?.type === "element"
|
|
201
|
+
? menu.anchor.element
|
|
202
|
+
: menu.anchor?.type === "point"
|
|
203
|
+
? createVirtualAnchor(menu.anchor.point, menu.anchor.contextElement)
|
|
204
|
+
: null;
|
|
205
|
+
`})}),`
|
|
206
|
+
`,(0,c.jsxs)(t.p,{children:[`Передайте `,(0,c.jsx)(t.code,{children:`reference`}),` в public API выбранного Floating UI wrapper. Не импортируйте private package files.`]}),`
|
|
207
|
+
`,(0,c.jsx)(t.h2,{id:`доступность`,children:`Доступность`}),`
|
|
208
|
+
`,(0,c.jsx)(t.p,{children:`Host обязан реализовать:`}),`
|
|
209
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
210
|
+
`,(0,c.jsx)(t.li,{children:`открытие клавишей Context Menu/Shift+F10 или принятой командой;`}),`
|
|
211
|
+
`,(0,c.jsx)(t.li,{children:`focus первого/выбранного item;`}),`
|
|
212
|
+
`,(0,c.jsx)(t.li,{children:`Arrow/Home/End navigation;`}),`
|
|
213
|
+
`,(0,c.jsx)(t.li,{children:`закрытие по Escape и возврат focus;`}),`
|
|
214
|
+
`,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`role="menu"`}),`/`,(0,c.jsx)(t.code,{children:`menuitem`}),` только если semantics действительно menu;`]}),`
|
|
215
|
+
`,(0,c.jsx)(t.li,{children:`disabled items;`}),`
|
|
216
|
+
`,(0,c.jsx)(t.li,{children:`outside click и focus dismissal;`}),`
|
|
217
|
+
`,(0,c.jsx)(t.li,{children:`сохранение trigger element для keyboard recovery.`}),`
|
|
218
|
+
`]}),`
|
|
219
|
+
`,(0,c.jsx)(t.p,{children:`Для keyboard source element anchor обычно лучше point без pointer coordinates.`}),`
|
|
220
|
+
`,(0,c.jsx)(t.h2,{id:`полный-api-и-ошибки`,children:`Полный API и ошибки`}),`
|
|
221
|
+
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Export`}),(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:`getMenuPointFromEvent`})}),(0,c.jsx)(t.td,{children:`Читает client coordinates`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getMenuPointFromRect`})}),(0,c.jsx)(t.td,{children:`Центр rect`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`createVirtualAnchor`})}),(0,c.jsx)(t.td,{children:`Point-like DOMRect provider`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`initialMenuState`})}),(0,c.jsx)(t.td,{children:`Canonical closed state`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`openMenu`})}),(0,c.jsx)(t.td,{children:`Новый opened state`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`closeMenu`})}),(0,c.jsx)(t.td,{children:`Закрывает/очищает state`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`toggleMenu`})}),(0,c.jsxs)(t.td,{children:[`Toggle по `,(0,c.jsx)(t.code,{children:`open`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`MenuPoint`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ x, y }`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`MenuOpenSource`})}),(0,c.jsx)(t.td,{children:`Источник открытия`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`MenuAnchor`})}),(0,c.jsx)(t.td,{children:`Element/point union`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`MenuState`})}),(0,c.jsx)(t.td,{children:`Полное state`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`OpenMenuPayload`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ source, anchor }`})})]})]})]}),`
|
|
222
|
+
`,(0,c.jsx)(t.p,{children:`Типичные ошибки:`}),`
|
|
223
|
+
`,(0,c.jsxs)(t.ul,{children:[`
|
|
224
|
+
`,(0,c.jsxs)(t.li,{children:[`Использовать `,(0,c.jsx)(t.code,{children:`pageX/pageY`}),` вместо client coordinates.`]}),`
|
|
225
|
+
`,(0,c.jsxs)(t.li,{children:[`Вызывать toggle при каждом `,(0,c.jsx)(t.code,{children:`contextmenu`}),` и неожиданно закрывать открытое меню.`]}),`
|
|
226
|
+
`,(0,c.jsxs)(t.li,{children:[`Мутировать `,(0,c.jsx)(t.code,{children:`initialMenuState`}),`.`]}),`
|
|
227
|
+
`,(0,c.jsx)(t.li,{children:`Persist DOM element.`}),`
|
|
228
|
+
`,(0,c.jsx)(t.li,{children:`Считать virtual anchor готовым positioner-ом.`}),`
|
|
229
|
+
`,(0,c.jsx)(t.li,{children:`Не возвращать focus после keyboard menu.`}),`
|
|
230
|
+
`]})]})}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};
|