@ryuzaki13/react-foundation-ui 3.0.0 → 3.1.0
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/COLOR_TOKENS_MIGRATION.md +66 -50
- package/README.md +8 -13
- package/dist/chunks/badge-6mXO9BWP.js.map +1 -1
- package/dist/chunks/ui.module-oRwY3Zli.js.map +1 -1
- package/dist/notifications/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/table-editor/index.js +20 -17
- package/dist/table-editor/index.js.map +1 -1
- package/dist/table-editor/ui/TableEditorGrid.d.ts.map +1 -1
- package/dist/tag-input/index.js.map +1 -1
- package/package.json +1 -1
- package/src/styles/_tone-derived.scss +18 -0
- package/src/styles/mixins/_controls.scss +3 -7
- package/src/styles/mixins/controls.test.ts +25 -0
- package/src/styles/themes/_theme.scss +19 -5
- package/src/styles/themes/theme.test.ts +30 -4
- package/storybook-static/assets/{Badge-DLpkFLAr.js → Badge-Esh85lzw.js} +1 -1
- package/storybook-static/assets/{Badge.stories-DwwZ0O7j.js → Badge.stories-DnU4Aj8m.js} +1 -1
- package/storybook-static/assets/{BadgeList-C0bhovUR.js → BadgeList-BxlBVt--.js} +1 -1
- package/storybook-static/assets/{BarcodeScannerDialog.stories-DYXaW4Vw.js → BarcodeScannerDialog.stories-B_KpAvZI.js} +1 -1
- package/storybook-static/assets/{Button-PAj4mH8o.js → Button-ZXxiD9P_.js} +1 -1
- package/storybook-static/assets/{Button-B1nvnaMI.js → Button-dvkBzy21.js} +1 -1
- package/storybook-static/assets/{Button.stories-CNvWyh5M.js → Button.stories-J4sJtC3v.js} +1 -1
- package/storybook-static/assets/{CalendarView-WUXapLvN.js → CalendarView-DGp2C40d.js} +1 -1
- package/storybook-static/assets/{CheckBox-C3r_FdXc.js → CheckBox-CGIztaSc.js} +1 -1
- package/storybook-static/assets/{CheckBox-B9f_n0Nh.js → CheckBox-IWsEVvwo.js} +1 -1
- package/storybook-static/assets/{CheckBox.stories-B5CFQBFx.js → CheckBox.stories-PatAgJNg.js} +1 -1
- package/storybook-static/assets/{Color-6AOWCN3U-tYUAsbHo.js → Color-6AOWCN3U-CObFhsdH.js} +1 -1
- package/storybook-static/assets/{ContextMenu-PIvPPvq1.js → ContextMenu-BpMNIGaS.js} +1 -1
- package/storybook-static/assets/{ContextMenu-C-T3O2d9.js → ContextMenu-PtQCIWby.js} +1 -1
- package/storybook-static/assets/{ContextMenu.stories-Bmy_0Oug.js → ContextMenu.stories-DRN3y3fq.js} +1 -1
- package/storybook-static/assets/{CustomOptionButton-D_qTIop3.js → CustomOptionButton-BypRyNBF.js} +1 -1
- package/storybook-static/assets/{DateInput-B7GZSkR3.js → DateInput-CtEsHpVC.js} +1 -1
- package/storybook-static/assets/{DateInput-C-goSdP-.js → DateInput-DMRmP2mq.js} +1 -1
- package/storybook-static/assets/{DateInput.stories-CeAMz_x1.js → DateInput.stories-kwV29Z7O.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-BmjgWIxM.js → DateRangePresetSelect-BBppsGIA.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect-BZ9U_l_x.js → DateRangePresetSelect-BSZ8AV5V.js} +1 -1
- package/storybook-static/assets/{DateRangePresetSelect.stories-5UGP9HcH.js → DateRangePresetSelect.stories-Brt_WHDa.js} +1 -1
- package/storybook-static/assets/{Detail-C6duvCft.js → Detail-DgopeQrm.js} +1 -1
- package/storybook-static/assets/{Detail.stories-DQZciNeZ.js → Detail.stories-9gNYQ6_t.js} +1 -1
- package/storybook-static/assets/{Dialog-Bx4-acbv.js → Dialog-BIMDgQGd.js} +1 -1
- package/storybook-static/assets/{Dialog-87D5Shqd.js → Dialog-BmgaXy1U.js} +1 -1
- package/storybook-static/assets/{Dialog.stories-BgOQABzP.js → Dialog.stories-gQNF3xNZ.js} +1 -1
- package/storybook-static/assets/{Disclosure-ZctFZjdw.js → Disclosure-DYkWCvOB.js} +1 -1
- package/storybook-static/assets/{Disclosure.stories-BioI8Dpv.js → Disclosure.stories-BkgXZx5X.js} +1 -1
- package/storybook-static/assets/{DisclosureGroup-Cn2EEocA.js → DisclosureGroup-CTkOG9uF.js} +1 -1
- package/storybook-static/assets/{DocsRenderer-JROSPFPF-CoppGUHs.js → DocsRenderer-JROSPFPF-CGYd7juA.js} +1 -1
- package/storybook-static/assets/{DropZone-68BioqBN.js → DropZone-BwnzxS_O.js} +1 -1
- package/storybook-static/assets/{DropZone-BpInQyuE.js → DropZone-C_QHZrKt.js} +1 -1
- package/storybook-static/assets/{DropZone.stories-DhVyaedf.js → DropZone.stories-Boz52u36.js} +1 -1
- package/storybook-static/assets/{DropdownMenu-Dw-i5abQ.js → DropdownMenu-CSMB10lt.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel-Bb7Eo_iW.js → ExpandableActionPanel-Bs__dpSI.js} +1 -1
- package/storybook-static/assets/{ExpandableActionPanel.stories-B0XABlVT.js → ExpandableActionPanel.stories-dz1gGOjf.js} +1 -1
- package/storybook-static/assets/{Flex-CG5yKEBH.js → Flex-B1k5JrkX.js} +1 -1
- package/storybook-static/assets/{Flex.stories-Cfx4TAqp.js → Flex.stories-DCEdIXaL.js} +1 -1
- package/storybook-static/assets/{FloatingPopover-B8zZ8eYf.js → FloatingPopover-Bcol5irF.js} +1 -1
- package/storybook-static/assets/{FormattedTableCell-BzBZlmxd.js → FormattedTableCell-BrUuqaAr.js} +1 -1
- package/storybook-static/assets/{Grid-3MdRiyY4.js → Grid-BP-ULpSq.js} +1 -1
- package/storybook-static/assets/{Grid.stories-DUfosHcu.js → Grid.stories-xZTqePJe.js} +1 -1
- package/storybook-static/assets/{ImageCropper.stories-DBLj9S4C.js → ImageCropper.stories-9VlHvauM.js} +1 -1
- package/storybook-static/assets/{ImageRenderer-bZHWE6lq.js → ImageRenderer-CZUio12Y.js} +1 -1
- package/storybook-static/assets/{ImageRenderer.stories-BU2tt9QR.js → ImageRenderer.stories-BMJ8rG5Y.js} +1 -1
- package/storybook-static/assets/{ImageView.stories-t_ree_kB.js → ImageView.stories-DwbVXc_9.js} +1 -1
- package/storybook-static/assets/{ImageViewer.stories-kodL93QT.js → ImageViewer.stories-N79zIcYB.js} +2 -2
- package/storybook-static/assets/{ImageViewerRuntime-Dkw7fwZ1.js → ImageViewerRuntime-eFkLooZd.js} +1 -1
- package/storybook-static/assets/{Input-C-Q_V0Uc.js → Input-C_pApI-f.js} +1 -1
- package/storybook-static/assets/{Input-Ckb0G4jj.js → Input-fyfY8tUJ.js} +1 -1
- package/storybook-static/assets/{Input.stories-BZITY0Np.js → Input.stories-DPx50f_P.js} +1 -1
- package/storybook-static/assets/{InputDateTime-DF-R-IPb.js → InputDateTime-BKOW723d.js} +1 -1
- package/storybook-static/assets/{InputDateTime.stories-2ELFc29n.js → InputDateTime.stories-DJpICa-C.js} +1 -1
- package/storybook-static/assets/{InputFile-3Sn8IwRI.js → InputFile-BIFMqbBI.js} +1 -1
- package/storybook-static/assets/{InputFile-Xo-rxvud.js → InputFile-CX8kMBfN.js} +1 -1
- package/storybook-static/assets/{InputFile.stories-B4EHuTtj.js → InputFile.stories-Dpiz4AE-.js} +1 -1
- package/storybook-static/assets/{InputFiles-CRFuoEBd.js → InputFiles-B-uYeAwK.js} +1 -1
- package/storybook-static/assets/{InputFiles-DzdnkOiD.js → InputFiles-g6BxqKY1.js} +1 -1
- package/storybook-static/assets/{InputFiles.stories-BRCSXgg-.js → InputFiles.stories-CIeEtuge.js} +1 -1
- package/storybook-static/assets/{InputFilesList-CvL4pjsZ.js → InputFilesList-EUw0PgRa.js} +1 -1
- package/storybook-static/assets/{InputImage-qAzSyHzj.js → InputImage-BHhhQ_DL.js} +1 -1
- package/storybook-static/assets/{InputImage-B1v_PWfN.js → InputImage-G56Xrlxa.js} +1 -1
- package/storybook-static/assets/{InputImage.stories-4NLpODaa.js → InputImage.stories-CzcxWNCg.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents-Bdy-KTOF.js → InteractiveComponents-BwuEU-Jx.js} +1 -1
- package/storybook-static/assets/{InteractiveComponents.stories-C_ZAVn0R.js → InteractiveComponents.stories-BFz-Wro0.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-8wwVLPom.js → LayoutPicker-XV5w8WPa.js} +1 -1
- package/storybook-static/assets/{LayoutPicker-B4eblsaF.js → LayoutPicker-dIhabh1s.js} +1 -1
- package/storybook-static/assets/{LayoutPicker.stories-BkA-VmHP.js → LayoutPicker.stories-CDt2569o.js} +1 -1
- package/storybook-static/assets/{Listbox-ChaW3JrO.js → Listbox-Bgo-nQ9Y.js} +1 -1
- package/storybook-static/assets/{Listbox-CyH7MftX.js → Listbox-DaW_mGeW.js} +1 -1
- package/storybook-static/assets/{Listbox.stories-_31FVhoW.js → Listbox.stories-CP6wE_7K.js} +1 -1
- package/storybook-static/assets/{Modal-DGR9lZ4E.js → Modal-Bqw7AE8B.js} +1 -1
- package/storybook-static/assets/{Modal-CaGOliEb.js → Modal-DDvcZVCM.js} +1 -1
- package/storybook-static/assets/{Modal.stories-C1yvEVNj.js → Modal.stories-BX600McN.js} +1 -1
- package/storybook-static/assets/{ModalManagerProvider-BrPY3nRM.js → ModalManagerProvider-CxtoDU9F.js} +1 -1
- package/storybook-static/assets/{MultiSelect-D4S4B3va.js → MultiSelect-BJIs_9bc.js} +1 -1
- package/storybook-static/assets/{MultiSelect-D-O71OBm.js → MultiSelect-yUk0g6i1.js} +1 -1
- package/storybook-static/assets/{MultiSelect.stories-B0QY0_Ru.js → MultiSelect.stories-DK5hmxUc.js} +1 -1
- package/storybook-static/assets/{NoData-B6xgAMXh.js → NoData-hc4EFPB8.js} +1 -1
- package/storybook-static/assets/{NotificationsHost-DJ3Y-Bov.js → NotificationsHost-DJrgoJC_.js} +1 -1
- package/storybook-static/assets/{NotificationsHost.stories-B2ULIi8d.js → NotificationsHost.stories-D7mi4TqE.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect-0SfdyLn9.js → ODataMultiSelect-DNrfwZV0.js} +1 -1
- package/storybook-static/assets/{ODataMultiSelect.stories-BLq2Lzuq.js → ODataMultiSelect.stories-kL4DXKxt.js} +1 -1
- package/storybook-static/assets/{ODataSelect-CkdBSdJ6.js → ODataSelect-DCDQ6QDE.js} +1 -1
- package/storybook-static/assets/{ODataSelect.stories-OLMZHd_q.js → ODataSelect.stories-C6kKriiF.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect-DMLCMhQn.js → ODataTreeMultiSelect-CHVUlk_U.js} +1 -1
- package/storybook-static/assets/{ODataTreeMultiSelect.stories-aY5Q0IHe.js → ODataTreeMultiSelect.stories-B9FhGd09.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect-ME1K7NL2.js → ODataTreeSelect-BtOXQoID.js} +1 -1
- package/storybook-static/assets/{ODataTreeSelect.stories-C7UPHKEr.js → ODataTreeSelect.stories-Chqlab-8.js} +1 -1
- package/storybook-static/assets/{OneStepScroller-RRsghqzx.js → OneStepScroller-DxeS1X71.js} +1 -1
- package/storybook-static/assets/{Option-CcZ3aKLZ.js → Option-ComrvJ9s.js} +1 -1
- package/storybook-static/assets/{OptionButton-B-RTb3Ua.js → OptionButton-DJAuLjhy.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-B-89h-o8.js → PeriodSelect-DcD82ag2.js} +1 -1
- package/storybook-static/assets/{PeriodSelect-CUUixF0M.js → PeriodSelect-RGiWiGWB.js} +1 -1
- package/storybook-static/assets/{PeriodSelect.stories-CU1V-pP4.js → PeriodSelect.stories-J0FBtti2.js} +1 -1
- package/storybook-static/assets/{PickerField-DykK8Xgu.js → PickerField-BamGqyTg.js} +1 -1
- package/storybook-static/assets/{PickerTriggerActions-C2qYXlH1.js → PickerTriggerActions-CrzexZv7.js} +1 -1
- package/storybook-static/assets/{Popover-D_MNKdnD.js → Popover-7hIGWFil.js} +1 -1
- package/storybook-static/assets/{Popover-Bg-XuklM.js → Popover-DA6FuPO9.js} +1 -1
- package/storybook-static/assets/{Popover.stories-D2Asjc6d.js → Popover.stories-BGX_E2Rj.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-CYXkpgts.js → PresetRangeDateInput-BZ5e4ulz.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput-B1KqD3aB.js → PresetRangeDateInput-DEMn-CKo.js} +1 -1
- package/storybook-static/assets/{PresetRangeDateInput.stories-CTML1dIg.js → PresetRangeDateInput.stories-DyQzNJiA.js} +1 -1
- package/storybook-static/assets/{PresetSelect-4PvR0s4U.js → PresetSelect-BsGseZxe.js} +1 -1
- package/storybook-static/assets/{README-BNUdkNxv.js → README-4wAMpqKW.js} +1 -1
- package/storybook-static/assets/{README-CjbqfpYX.js → README-530UIsM5.js} +1 -1
- package/storybook-static/assets/{README-CWxf5v2C.js → README-97xTDGmC.js} +1 -1
- package/storybook-static/assets/{README-bU5ZgdrN.js → README-B71F0K0c.js} +1 -1
- package/storybook-static/assets/{README-Bta2DZoW.js → README-B7DR00fM.js} +1 -1
- package/storybook-static/assets/{README-tetbJraG.js → README-B84EaQXv.js} +1 -1
- package/storybook-static/assets/{README-Bt44WdOn.js → README-BC4xt0AQ.js} +1 -1
- package/storybook-static/assets/{README-BVOzG1wf.js → README-BUa64A8D.js} +1 -1
- package/storybook-static/assets/{README-vjP8Z9fC.js → README-BXdudd03.js} +1 -1
- package/storybook-static/assets/{README-NCp7adRE.js → README-BbONAExJ.js} +1 -1
- package/storybook-static/assets/{README-BKGcgtnD.js → README-BcrNbNjI.js} +1 -1
- package/storybook-static/assets/{README-Dl_id19k.js → README-BgRQJ2S9.js} +1 -1
- package/storybook-static/assets/{README-l0W43XHl.js → README-BhxFmTpV.js} +1 -1
- package/storybook-static/assets/{README-ypHLhhny.js → README-Bjq9zsXL.js} +1 -1
- package/storybook-static/assets/{README-B5vVbHbw.js → README-BmrxdH-B.js} +1 -1
- package/storybook-static/assets/{README-DpxWpc-I.js → README-BrIfTQtc.js} +1 -1
- package/storybook-static/assets/{README-B3Q9ZlQz.js → README-Bup4xuqw.js} +1 -1
- package/storybook-static/assets/{README-CnE5ZG98.js → README-C0GgcK-F.js} +1 -1
- package/storybook-static/assets/{README-kpAlQZLM.js → README-C1zwQgxk.js} +1 -1
- package/storybook-static/assets/{README-B5MLKvrO.js → README-C4KUJF4d.js} +1 -1
- package/storybook-static/assets/{README-BcReoeGQ.js → README-C8fBLb8Q.js} +1 -1
- package/storybook-static/assets/{README-CE0sa_3S.js → README-CAaN4Ld-.js} +1 -1
- package/storybook-static/assets/{README-1Ks0ldtQ.js → README-CFR0mu0U.js} +1 -1
- package/storybook-static/assets/{README-Diow36TX.js → README-CGovAIuH.js} +1 -1
- package/storybook-static/assets/{README-DFiFAUAq.js → README-CQn8q9y9.js} +1 -1
- package/storybook-static/assets/{README-BpSdRy6R.js → README-CUhyCSGc.js} +1 -1
- package/storybook-static/assets/{README-CoJlt7mW.js → README-CY5Rzd4q.js} +1 -1
- package/storybook-static/assets/{README-Ib9AxEso.js → README-CgkwwR69.js} +1 -1
- package/storybook-static/assets/{README-Co-LXT0Y.js → README-CmkOA3wW.js} +1 -1
- package/storybook-static/assets/{README-44qHXI_X.js → README-CwZI_nQ7.js} +1 -1
- package/storybook-static/assets/{README-BSSrY3Ri.js → README-D2L5Yzv1.js} +1 -1
- package/storybook-static/assets/{README--I7LDhOP.js → README-D7L1Z6n9.js} +1 -1
- package/storybook-static/assets/{README-BdgUDdVT.js → README-D7_WRUZg.js} +1 -1
- package/storybook-static/assets/{README-Dtb7kJXX.js → README-DCJ0rsOW.js} +1 -1
- package/storybook-static/assets/{README-Dqpnap9b.js → README-DETry3fH.js} +1 -1
- package/storybook-static/assets/{README-DlE5gepf.js → README-DHwyWwmz.js} +1 -1
- package/storybook-static/assets/{README-C5Cq8Lo7.js → README-DMvM0CFG.js} +1 -1
- package/storybook-static/assets/{README-Ve2RJTbZ.js → README-DP6FJt9L.js} +1 -1
- package/storybook-static/assets/{README-VY7CL7vi.js → README-DYrhoV2x.js} +1 -1
- package/storybook-static/assets/{README-C1TqCBPf.js → README-DhMfO2Dl.js} +1 -1
- package/storybook-static/assets/{README-CVEiXGCU.js → README-DhOlNM3a.js} +1 -1
- package/storybook-static/assets/{README-DMCaXjMn.js → README-DnkpFu02.js} +1 -1
- package/storybook-static/assets/{README-BK-2_7T4.js → README-DtM6kMym.js} +1 -1
- package/storybook-static/assets/{README-COnopkzM.js → README-DuTHnM3g.js} +1 -1
- package/storybook-static/assets/{README-Bwa8ai1X.js → README-DvZb2tQw.js} +1 -1
- package/storybook-static/assets/{README-vUJFU3Tw.js → README-DzJwLpxb.js} +1 -1
- package/storybook-static/assets/{README-DrSuJ2Ll.js → README-Ld_nuS76.js} +1 -1
- package/storybook-static/assets/{README-DecmlELk.js → README-UQVgPCo3.js} +1 -1
- package/storybook-static/assets/{README-SHZwgJhZ.js → README-YY1Ajz1w.js} +1 -1
- package/storybook-static/assets/{README-BZbDJrol.js → README-_ZkqcsGp.js} +1 -1
- package/storybook-static/assets/{README-CUEwtG21.js → README-_oeRmsba.js} +1 -1
- package/storybook-static/assets/{README-BrduLUi1.js → README-mRxMTW_Z.js} +1 -1
- package/storybook-static/assets/{README-BJsszjH8.js → README-y9Bfe8iT.js} +1 -1
- package/storybook-static/assets/{RadioButton-ByRN6fXm.js → RadioButton-0axQ-WvZ.js} +1 -1
- package/storybook-static/assets/{RadioButton-DRIJvobR.js → RadioButton-AUoosUqB.js} +1 -1
- package/storybook-static/assets/{RadioButton.stories-C6lOZsje.js → RadioButton.stories-Dqe-r3lD.js} +1 -1
- package/storybook-static/assets/{RadioGroup-5P3FMqFW.js → RadioGroup-BgCjgFfe.js} +1 -1
- package/storybook-static/assets/{RadioGroup-Dskh-JZM.js → RadioGroup-Biy7jsOy.js} +1 -1
- package/storybook-static/assets/{RadioGroup.stories-BDbOjwVa.js → RadioGroup.stories-CHvNWKTQ.js} +1 -1
- package/storybook-static/assets/{Scrollable-Cat0ixOK.js → Scrollable-BYmva3ep.js} +1 -1
- package/storybook-static/assets/{Select-BiIixkSk.js → Select-CZCJfh1u.js} +1 -1
- package/storybook-static/assets/{Select-ImY9WR7I.js → Select-CoD4ahoj.js} +1 -1
- package/storybook-static/assets/{Select.stories-DR8qQrXW.js → Select.stories-B-PY1Sz5.js} +1 -1
- package/storybook-static/assets/{SerializableSelect-C2swvXju.js → SerializableSelect-DE8iNPWu.js} +1 -1
- package/storybook-static/assets/{SerializableSelect.stories-CvoyFECC.js → SerializableSelect.stories-Cgd2VT8m.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-hV5Om2LV.js → SingleDateTimeInput-BDHCGYJi.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput-CjixqW_K.js → SingleDateTimeInput-BzOL-IZJ.js} +1 -1
- package/storybook-static/assets/{SingleDateTimeInput.stories-CPDP-M6P.js → SingleDateTimeInput.stories-yuCgjvxm.js} +1 -1
- package/storybook-static/assets/{Slider-PcbxPCWE.js → Slider-BSYDJi1k.js} +1 -1
- package/storybook-static/assets/{Slider-FbV_mr1Y.js → Slider-Bx2jKg6R.js} +1 -1
- package/storybook-static/assets/{Slider.stories-CH9grPep.js → Slider.stories-P23SMkMP.js} +1 -1
- package/storybook-static/assets/{SliderInput-iqnLqNiU.js → SliderInput-AgH6kueH.js} +1 -1
- package/storybook-static/assets/{SliderInput-DPYcLCwD.js → SliderInput-CfK1Mnw8.js} +1 -1
- package/storybook-static/assets/{SliderInput.stories-qVDa0KhJ.js → SliderInput.stories-BIZQY77N.js} +1 -1
- package/storybook-static/assets/{Sortable-DzJSN0MG.js → Sortable-HAt33EOU.js} +1 -1
- package/storybook-static/assets/{Sortable.stories-BaQ2T15L.js → Sortable.stories-DpKHUgP7.js} +1 -1
- package/storybook-static/assets/{Splitter-Ka7c1ZDV.js → Splitter-XHLzIzBV.js} +1 -1
- package/storybook-static/assets/{Splitter.stories-BbjjUT39.js → Splitter.stories-AF5cuIrd.js} +1 -1
- package/storybook-static/assets/{StateSelect-DSzDU5Jy.js → StateSelect-Bc7THQz4.js} +1 -1
- package/storybook-static/assets/{StateSelect-CfyyDUiq.js → StateSelect-D_4JId4p.js} +1 -1
- package/storybook-static/assets/{StateSelect.stories-0c32Rlr2.js → StateSelect.stories-Dskb5EaO.js} +1 -1
- package/storybook-static/assets/{StatusIndicator-CcCdDffH.js → StatusIndicator-DgpNsNH9.js} +1 -1
- package/storybook-static/assets/{StatusIndicator.stories-Bazi6rxF.js → StatusIndicator.stories-CggWAarU.js} +1 -1
- package/storybook-static/assets/{StringToggle.stories-Bl6HAr4o.js → StringToggle.stories-C0ZhO81t.js} +1 -1
- package/storybook-static/assets/{Switch-BqAkQzIJ.js → Switch-CknduYVb.js} +1 -1
- package/storybook-static/assets/{Switch-Vl7s55bO.js → Switch-f3dsucrL.js} +1 -1
- package/storybook-static/assets/{Switch.stories-Cq2n8Vr4.js → Switch.stories-Chg3TrE2.js} +1 -1
- package/storybook-static/assets/{Table-BgxoZKJs.js → Table-A1OmUB1G.js} +1 -1
- package/storybook-static/assets/{Table.stories-DxnnXMZX.js → Table.stories-F0G5NqxY.js} +1 -1
- package/storybook-static/assets/{TableEditor.stories-D5Ke41-O.js → TableEditor.stories-Hq1Gc1oK.js} +1 -1
- package/storybook-static/assets/{Tabs-BPJG7wBI.js → Tabs-BmH25H7g.js} +1 -1
- package/storybook-static/assets/{Tabs.stories-cQ4RTo0w.js → Tabs.stories-CIX0RdTF.js} +1 -1
- package/storybook-static/assets/{TabsBox-CGgEovb9.js → TabsBox-C1OmrVhO.js} +1 -1
- package/storybook-static/assets/{TagInput-CGHC-7Rv.js → TagInput-CE0_PHMq.js} +1 -1
- package/storybook-static/assets/{TagInput.stories-BSy_dJ5n.js → TagInput.stories-CTlBOp-Y.js} +1 -1
- package/storybook-static/assets/{Text-D5fn4NbN.js → Text-Dm4ZV9wd.js} +1 -1
- package/storybook-static/assets/{Textarea-CbWAz4J8.js → Textarea-9eR-qNKs.js} +1 -1
- package/storybook-static/assets/{Textarea-pXxz-925.js → Textarea-CK7tpoYG.js} +1 -1
- package/storybook-static/assets/{Textarea.stories-BkPejDdf.js → Textarea.stories-vGi_UkyN.js} +1 -1
- package/storybook-static/assets/{TimePanel-BJulRHL2.js → TimePanel-BLQrdjYw.js} +1 -1
- package/storybook-static/assets/{TimePanel.stories-CJmuKdfu.js → TimePanel.stories-DOLgz23p.js} +1 -1
- package/storybook-static/assets/{Toggle-DjqQBHtJ.js → Toggle-DCT7y4pb.js} +1 -1
- package/storybook-static/assets/{Toggle-B2S8eW_z.js → Toggle-d3qw-5vS.js} +1 -1
- package/storybook-static/assets/{Toggle.stories-7KRSUGU9.js → Toggle.stories-DIc66YyI.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-DfvInPvn.js → TreeMultiSelect-3CrIhRKl.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect-B7Dd0sH5.js → TreeMultiSelect-Buj6k0wN.js} +1 -1
- package/storybook-static/assets/{TreeMultiSelect.stories-DrokeiS6.js → TreeMultiSelect.stories-BHxIRTEy.js} +1 -1
- package/storybook-static/assets/{TreePickerBase-CN9UeNWV.js → TreePickerBase-BHduNQZI.js} +1 -1
- package/storybook-static/assets/{TreeSelect-DPX2Q1Sv.js → TreeSelect-BO1tYVB4.js} +1 -1
- package/storybook-static/assets/{TreeSelect-D3s-_McF.js → TreeSelect-DfFbREJp.js} +1 -1
- package/storybook-static/assets/{TreeSelect.stories-DvUGVU34.js → TreeSelect.stories-ZwxGVFce.js} +1 -1
- package/storybook-static/assets/{TreeTable-By3223dp.js → TreeTable-CIxtOAyo.js} +1 -1
- package/storybook-static/assets/{TreeTable.stories-DKAKV_e2.js → TreeTable.stories-BQNgHwk9.js} +1 -1
- package/storybook-static/assets/{blocks-C4R1QC9R.js → blocks-OyR7mF18.js} +3 -3
- package/storybook-static/assets/{check-DkXl--jW.js → check-Gvk-f2eZ.js} +1 -1
- package/storybook-static/assets/{chevron-down-DnX0I3Pg.js → chevron-down-KZidOQ8z.js} +1 -1
- package/storybook-static/assets/{chevron-left-18ya0d2d.js → chevron-left-BmY0y72L.js} +1 -1
- package/storybook-static/assets/{chevron-right-DilGYzJ6.js → chevron-right-DwE6c1oF.js} +1 -1
- package/storybook-static/assets/{chunk-W22LQPXL-WTP7vHyr.js → chunk-W22LQPXL-Dvqa6-ec.js} +1 -1
- package/storybook-static/assets/{circle-alert-DVNv_dVS.js → circle-alert-CWi4rINy.js} +1 -1
- package/storybook-static/assets/{circle-check-vIdCi5Zq.js → circle-check-BWlhKN1l.js} +1 -1
- package/storybook-static/assets/{components-BtEbmBZQ.js → components-CoPo6nEv.js} +3 -3
- package/storybook-static/assets/{contextMenu-1dx6rzYN.js → contextMenu-DwYdo2Sb.js} +1 -1
- package/storybook-static/assets/{download-37V1rEcU.js → download-Bqp3e16u.js} +1 -1
- package/storybook-static/assets/{floating-ui.react-DT-xu5am.js → floating-ui.react-Dzrc1SBT.js} +1 -1
- package/storybook-static/assets/{foundationApi-FaYaPMaR.js → foundationApi-297mfV2y.js} +1 -1
- package/storybook-static/assets/{foundationLib-DLCLUXOF.js → foundationLib-CnmPNL2i.js} +1 -1
- package/storybook-static/assets/{hooks-BuU9-pEZ.js → hooks-CZ-c1LQK.js} +1 -1
- package/storybook-static/assets/iframe-3DMMfY6n.js +1 -0
- package/storybook-static/assets/{iframe-BT_jngkf.css → iframe-C-4tNqTX.css} +1 -1
- package/storybook-static/assets/{iframe-0M2vpakb.js → iframe-t8Ol-TlS.js} +3 -3
- package/storybook-static/assets/{info-2PUHH67D.js → info-BMddFLDT.js} +1 -1
- package/storybook-static/assets/{odata-DIkxH78d.js → odata-u98yP6vI.js} +1 -1
- package/storybook-static/assets/{odataStoryFixtures-BDQiSxyk.js → odataStoryFixtures-BX88AmEk.js} +1 -1
- package/storybook-static/assets/{react-CfjIdTfH.js → react-BwRTJdhk.js} +1 -1
- package/storybook-static/assets/{refresh-cw-CHFG8NIc.js → refresh-cw-BSZCBW1r.js} +1 -1
- package/storybook-static/assets/{settings-2-CYde2-4U.js → settings-2-UthslFqJ.js} +1 -1
- package/storybook-static/assets/{sortable-Cy9ZqA3f.js → sortable-C4MB--OV.js} +1 -1
- package/storybook-static/assets/{syntaxhighlighter-QEQV7K2Y-C2U-3XXV.js → syntaxhighlighter-QEQV7K2Y-DByUKVZY.js} +1 -1
- package/storybook-static/assets/{trash-2-7-oMZEr8.js → trash-2-CPAznzsr.js} +1 -1
- package/storybook-static/assets/{triangle-alert-BSmuthen.js → triangle-alert-B2jfGvCD.js} +1 -1
- package/storybook-static/assets/{ui-DSS1yTEO.css → ui-D4-nHP5x.css} +1 -1
- package/storybook-static/assets/{uiClasses-e9OQfdw2.js → uiClasses-BCk2WXc4.js} +1 -1
- package/storybook-static/assets/{useODataSelectBase-C3B3Xw87.js → useODataSelectBase-C-o3n-Rn.js} +1 -1
- package/storybook-static/assets/{useODataTreeData-deUW5mSv.js → useODataTreeData-DkF53Jgq.js} +1 -1
- package/storybook-static/assets/{usePickerQuery-DdE3I7AV.js → usePickerQuery-D609nrEf.js} +1 -1
- package/storybook-static/assets/{usePickerTriggerController-ZRvj4FHy.js → usePickerTriggerController-CiGxyPbG.js} +1 -1
- package/storybook-static/assets/{x-NXcyLtyX.js → x-Y6c20Jey.js} +1 -1
- package/storybook-static/iframe.html +3 -3
- package/storybook-static/project.json +1 -1
- package/storybook-static/assets/iframe-BMXB4CtM.js +0 -1
- /package/storybook-static/assets/{ui.module-SH8ehXul.js → ui.module-nb-nQZVN.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/table-editor/ui/TableEditor.module.scss","../../src/table-editor/model/useTableEditorTable.ts","../../src/table-editor/ui/TableEditorGrid.tsx","../../src/table-editor/ui/TableEditorStructure.tsx","../../src/table-editor/ui/TableEditorToolbar.tsx","../../src/table-editor/ui/TableEditor.tsx","../../src/table-editor/model/useTableEditor.ts"],"sourcesContent":[".editor {\n\tdisplay: grid;\n\tgap: var(--space-md);\n\tmin-width: 0;\n\tcolor: var(--content-0);\n}\n.toolbar {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: var(--space-sm);\n}\n.help {\n\tmargin: 0;\n\tcolor: var(--content-1);\n}\n.scroll {\n\tmax-height: 34rem;\n\toverflow: auto;\n\tborder: var(--border);\n\tborder-radius: var(--radius-sm);\n}\n.table {\n\twidth: max-content;\n\tmin-width: 100%;\n\ttable-layout: fixed;\n\tborder-collapse: collapse;\n\n\ttd,\n\tth {\n\t\tpadding: var(--space-sm);\n\t\tmin-width: 6rem;\n\t\tborder: var(--border);\n\t\tvertical-align: top;\n\t\ttext-align: start;\n\t\tbackground: var(--surface-0);\n\t\tcursor: cell;\n\t\t&[aria-selected=\"true\"] {\n\t\t\tbackground: var(--surface-2);\n\t\t\tbox-shadow: inset 0 0 0 2px var(--content-1);\n\t\t}\n\t\t&:focus {\n\t\t\toutline: 3px solid var(--content-0);\n\t\t\toutline-offset: -3px;\n\t\t}\n\t}\n\ttr[data-header] th {\n\t\tfont-weight: 600;\n\t\t&:not([aria-selected=\"true\"]) {\n\t\t\tbackground: var(--surface-1);\n\t\t}\n\t}\n}\n.cellContent {\n\tmin-height: 2rem;\n\toverflow-wrap: anywhere;\n\tpointer-events: none;\n\tuser-select: none;\n}\n.inspector {\n\tdisplay: grid;\n\tgap: var(--space-sm);\n\tpadding: var(--space-md);\n\tborder: var(--border);\n\tbackground: var(--surface-1);\n}\n.structure {\n\tdisplay: grid;\n\tpadding: var(--space-sm);\n\tborder: var(--border);\n\tsummary {\n\t\tcursor: pointer;\n\t\tmargin-bottom: var(--space-sm);\n\t}\n\t.toolbar {\n\t\tmargin-bottom: var(--space-sm);\n\t}\n}\n","import { useMemo } from \"react\";\n\nimport { getTableDocumentCellRange, type TableDocument, type TableDocumentRow } from \"@ryuzaki13/react-foundation-lib/table-document\";\nimport { cellSpanningFeature, tableFeatures, useTable, type ColumnDef } from \"@tanstack/react-table\";\n\nconst features = tableFeatures({ cellSpanningFeature });\n\n/**\n * TanStack 9 получает стабильный anchor как accessor value: одинаковый текст\n * соседних ячеек сам по себе никогда не объединяет их. Порядок документа не\n * сортируется и не фильтруется; authored spans остаются authoritative.\n */\nexport function useTableEditorTable<T>(document: TableDocument<T>) {\n\t// Merge меняет accessor identity даже без изменения rows. Новый snapshot data\n\t// сбрасывает кэш значений TanStack и не оставляет устаревшие spans на экране.\n\tconst data = useMemo(() => [...document.rows], [document]);\n\tconst columns = useMemo<ColumnDef<typeof features, TableDocumentRow<T>>[]>(\n\t\t() =>\n\t\t\tdocument.columns.map((column, c) => ({\n\t\t\t\tid: column.id,\n\t\t\t\taccessorFn: (_row, r) => {\n\t\t\t\t\tconst range = getTableDocumentCellRange(document, { row: r, column: c });\n\t\t\t\t\treturn document.rows[range.row].cells[range.column].id;\n\t\t\t\t},\n\t\t\t\tspanRows: true,\n\t\t\t\tspanColumns: ({ row }) => {\n\t\t\t\t\tconst range = getTableDocumentCellRange(document, { row: row.index, column: c });\n\t\t\t\t\treturn range.column === c ? range.columnSpan : 1;\n\t\t\t\t}\n\t\t\t})),\n\t\t[document]\n\t);\n\treturn useTable({ features, data, columns, getRowId: (row) => row.id });\n}\n","import { useId, useRef, type ReactNode } from \"react\";\n\nimport {\n\tgetTableDocumentCellRange,\n\ttype TableDocumentCell,\n\ttype TableDocumentPosition\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { type TableEditorController } from \"../model/useTableEditor\";\nimport { useTableEditorTable } from \"../model/useTableEditorTable\";\n\nimport styles from \"./TableEditor.module.scss\";\n\ntype TableEditorGridProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly extendSelection: boolean;\n\treadonly disabled?: boolean;\n\treadonly renderCell: (cell: TableDocumentCell<T>) => ReactNode;\n\treadonly getCellText: (cell: TableDocumentCell<T>) => string;\n};\n\n/** Доступная сетка: roving tabindex, стрелки/Shift и выбор диапазона без drag-only действий. */\nexport function TableEditorGrid<T>({ editor, extendSelection, disabled, renderCell, getCellText }: TableEditorGridProps<T>) {\n\tconst helpId = useId();\n\tconst nodes = useRef(new Map<string, HTMLTableCellElement>());\n\tconst table = useTableEditorTable(editor.document);\n\tconst { document, selection, focus } = editor;\n\treturn (\n\t\t<>\n\t\t\t<p id={helpId} className={styles.help}>\n\t\t\t\tСтрелки — переход между ячейками. Shift + стрелки или Shift + щелчок — выделение диапазона. Содержимое выбранной ячейки\n\t\t\t\tредактируется под таблицей.\n\t\t\t</p>\n\t\t\t<div className={styles.scroll}>\n\t\t\t\t<table\n\t\t\t\t\trole=\"grid\"\n\t\t\t\t\taria-label={document.caption || \"Редактор таблицы\"}\n\t\t\t\t\taria-describedby={helpId}\n\t\t\t\t\taria-multiselectable=\"true\"\n\t\t\t\t\taria-disabled={disabled || undefined}\n\t\t\t\t\tclassName={styles.table}>\n\t\t\t\t\t<colgroup>\n\t\t\t\t\t\t{document.columns.map((column) => (\n\t\t\t\t\t\t\t<col key={column.id} style={{ width: column.width ?? 180 }} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</colgroup>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{table.getRowModel().rows.map((row) => (\n\t\t\t\t\t\t\t<tr key={row.id} aria-rowindex={row.index + 1} data-header={row.index < document.headerRowCount || undefined}>\n\t\t\t\t\t\t\t\t{row.getAllCells().map((cell, column) => {\n\t\t\t\t\t\t\t\t\tif (cell.getIsCovered()) return null;\n\t\t\t\t\t\t\t\t\tconst selected =\n\t\t\t\t\t\t\t\t\t\trow.index >= selection.row &&\n\t\t\t\t\t\t\t\t\t\trow.index < selection.row + selection.rowSpan &&\n\t\t\t\t\t\t\t\t\t\tcolumn >= selection.column &&\n\t\t\t\t\t\t\t\t\t\tcolumn < selection.column + selection.columnSpan;\n\t\t\t\t\t\t\t\t\tconst position = { row: row.index, column };\n\t\t\t\t\t\t\t\t\tconst original = row.original.cells[column];\n\t\t\t\t\t\t\t\t\tconst Cell = row.index < document.headerRowCount ? \"th\" : \"td\";\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<Cell\n\t\t\t\t\t\t\t\t\t\t\tkey={cell.id}\n\t\t\t\t\t\t\t\t\t\t\trole={row.index < document.headerRowCount ? \"columnheader\" : \"gridcell\"}\n\t\t\t\t\t\t\t\t\t\t\tref={(node) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (node) nodes.current.set(original.id, node);\n\t\t\t\t\t\t\t\t\t\t\t\telse nodes.current.delete(original.id);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\trowSpan={cell.getRowSpan()}\n\t\t\t\t\t\t\t\t\t\t\tcolSpan={cell.getColSpan()}\n\t\t\t\t\t\t\t\t\t\t\taria-colindex={column + 1}\n\t\t\t\t\t\t\t\t\t\t\taria-label={`Строка ${row.index + 1}, столбец ${column + 1}: ${getCellText(original) || \"Пустая ячейка\"}`}\n\t\t\t\t\t\t\t\t\t\t\taria-selected={selected}\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={!disabled && focus.row === row.index && focus.column === column ? 0 : -1}\n\t\t\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!disabled) editor.select(position, extendSelection || event.shiftKey);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonPointerEnter={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!disabled && event.pointerType === \"mouse\" && event.buttons === 1)\n\t\t\t\t\t\t\t\t\t\t\t\t\teditor.select(position, true);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (disabled || event.altKey || event.ctrlKey || event.metaKey) return;\n\t\t\t\t\t\t\t\t\t\t\t\tlet next: TableDocumentPosition;\n\t\t\t\t\t\t\t\t\t\t\t\tswitch (event.key) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowRight\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: column + cell.getColSpan() };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowLeft\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: column - 1 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowDown\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, row: row.index + cell.getRowSpan() };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowUp\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, row: row.index - 1 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"Home\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: 0 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"End\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: document.columns.length - 1 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \" \":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teditor.select(position, event.shiftKey);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.row < 0 ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.column < 0 ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.row >= document.rows.length ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.column >= document.columns.length\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\tconst range = getTableDocumentCellRange(document, next);\n\t\t\t\t\t\t\t\t\t\t\t\teditor.select(next, event.shiftKey);\n\t\t\t\t\t\t\t\t\t\t\t\tnodes.current.get(document.rows[range.row].cells[range.column].id)?.focus();\n\t\t\t\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\t\t\t\t{/* Preview не должен создавать вложенные tab stops или открывать ссылки вместо выделения. */}\n\t\t\t\t\t\t\t\t\t\t\t<div inert className={styles.cellContent}>\n\t\t\t\t\t\t\t\t\t\t\t\t{renderCell(original)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</Cell>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { useState } from \"react\";\n\nimport { uuidv4 } from \"@ryuzaki13/react-foundation-lib/crypto\";\nimport {\n\tdeleteTableDocumentAxisGroup,\n\tgetTableDocumentAxisGroups,\n\tinsertTableDocumentAxis,\n\tmoveTableDocumentAxisGroup\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { Button } from \"../../button\";\nimport { Dialog } from \"../../dialog\";\nimport { type TableEditorController } from \"../model/useTableEditor\";\n\nimport styles from \"./TableEditor.module.scss\";\n\ntype TableEditorStructureProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly createEmptyValue: () => T;\n\treadonly disabled?: boolean;\n};\n\n/** Вставка и доступный reorder без обязательного drag; удаление подтверждает весь затронутый блок. */\nexport function TableEditorStructure<T>({ editor, createEmptyValue, disabled }: TableEditorStructureProps<T>) {\n\tconst [removing, setRemoving] = useState<\"row\" | \"column\" | null>(null);\n\tconst { document, focus } = editor;\n\tconst group = removing\n\t\t? getTableDocumentAxisGroups(document, removing).find(\n\t\t\t\t(item) => focus[removing] >= item.start && focus[removing] < item.start + item.count\n\t\t\t)\n\t\t: null;\n\treturn (\n\t\t<>\n\t\t\t<details className={styles.structure}>\n\t\t\t\t<summary>Строки и столбцы</summary>\n\t\t\t\t{([\"row\", \"column\"] as const).map((axis) => (\n\t\t\t\t\t<div key={axis} className={styles.toolbar} role=\"group\" aria-label={axis === \"row\" ? \"Строки\" : \"Столбцы\"}>\n\t\t\t\t\t\t<strong>{axis === \"row\" ? \"Строка\" : \"Столбец\"}</strong>\n\t\t\t\t\t\t{([0, 1] as const).map((offset) => (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tkey={offset}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tconst cells = Array.from(\n\t\t\t\t\t\t\t\t\t\t{ length: axis === \"row\" ? document.columns.length : document.rows.length },\n\t\t\t\t\t\t\t\t\t\t() => ({ id: uuidv4(), value: createEmptyValue() })\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tconst id = uuidv4();\n\t\t\t\t\t\t\t\t\teditor.execute((current) =>\n\t\t\t\t\t\t\t\t\t\tinsertTableDocumentAxis(\n\t\t\t\t\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\t\t\t\t\taxis,\n\t\t\t\t\t\t\t\t\t\t\tfocus[axis] + offset,\n\t\t\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\t\t\tcells,\n\t\t\t\t\t\t\t\t\t\t\tfocus.row < document.headerRowCount ? \"header\" : \"body\"\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\tВставить {offset ? \"после\" : \"перед\"}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t{([-1, 1] as const).map((direction) => (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tkey={direction}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\teditor.execute((current) => moveTableDocumentAxisGroup(current, axis, focus[axis], direction))\n\t\t\t\t\t\t\t\t}>\n\t\t\t\t\t\t\t\tПереместить {axis === \"row\" ? (direction === -1 ? \"выше\" : \"ниже\") : direction === -1 ? \"левее\" : \"правее\"}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<Button tone=\"error\" disabled={disabled} onClick={() => setRemoving(axis)}>\n\t\t\t\t\t\t\tУдалить {axis === \"row\" ? \"строку\" : \"столбец\"}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\t\t\t\t<Button\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tconst cells = document.columns.map(() => ({ id: uuidv4(), value: createEmptyValue() }));\n\t\t\t\t\t\tconst id = uuidv4();\n\t\t\t\t\t\teditor.execute((current) => insertTableDocumentAxis(current, \"row\", current.headerRowCount, id, cells, \"header\"));\n\t\t\t\t\t}}>\n\t\t\t\t\tДобавить строку заголовка\n\t\t\t\t</Button>\n\t\t\t</details>\n\t\t\t<Dialog\n\t\t\t\topen={Boolean(removing)}\n\t\t\t\tonClose={() => setRemoving(null)}\n\t\t\t\ttitle=\"Удалить часть таблицы?\"\n\t\t\t\tdescription={`Будет удалено ${group?.count ?? 0} ${removing === \"row\" ? \"строк\" : \"столбцов\"}, включая скрытое объединением содержимое. Объединённая группа удаляется целиком. До сохранения действие можно отменить.`}>\n\t\t\t\t<div className={styles.toolbar}>\n\t\t\t\t\t<Button onClick={() => setRemoving(null)}>Не удалять</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttone=\"error\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tif (removing) editor.execute((current) => deleteTableDocumentAxisGroup(current, removing, focus[removing]));\n\t\t\t\t\t\t\tsetRemoving(null);\n\t\t\t\t\t\t}}>\n\t\t\t\t\t\tУдалить группу\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</Dialog>\n\t\t</>\n\t);\n}\n","import {\n\tmergeTableDocumentCells,\n\tsplitTableDocumentCell,\n\ttype TableDocumentPosition\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { Button } from \"../../button\";\nimport { CheckBox } from \"../../check-box\";\nimport { type TableEditorController } from \"../model/useTableEditor\";\n\nimport styles from \"./TableEditor.module.scss\";\n\ntype TableEditorToolbarProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly disabled?: boolean;\n\treadonly extendSelection: boolean;\n\treadonly onExtendSelectionChange: (value: boolean) => void;\n};\n\n/** Явные названия действий вместо скрытых режимов merge/split из legacy. */\nexport function TableEditorToolbar<T>({ editor, disabled, extendSelection, onExtendSelectionChange }: TableEditorToolbarProps<T>) {\n\tconst { document, selection } = editor;\n\tconst end: TableDocumentPosition = { row: selection.row + selection.rowSpan - 1, column: selection.column + selection.columnSpan - 1 };\n\tconst isSingle = selection.rowSpan * selection.columnSpan === 1;\n\tconst crossesHeader = selection.row < document.headerRowCount && end.row >= document.headerRowCount;\n\tconst merge = document.merges.find(\n\t\t(range) =>\n\t\t\trange.row === selection.row &&\n\t\t\trange.column === selection.column &&\n\t\t\trange.rowSpan === selection.rowSpan &&\n\t\t\trange.columnSpan === selection.columnSpan\n\t);\n\treturn (\n\t\t<div className={styles.toolbar} role=\"group\" aria-label=\"История и объединение\">\n\t\t\t<Button disabled={disabled || !editor.canUndo} onClick={editor.undo}>\n\t\t\t\tОтменить\n\t\t\t</Button>\n\t\t\t<Button disabled={disabled || !editor.canRedo} onClick={editor.redo}>\n\t\t\t\tПовторить\n\t\t\t</Button>\n\t\t\t<Button\n\t\t\t\tdisabled={disabled || isSingle || crossesHeader || Boolean(merge)}\n\t\t\t\tonClick={() => editor.execute((current) => mergeTableDocumentCells(current, selection, end))}>\n\t\t\t\tОбъединить ячейки\n\t\t\t</Button>\n\t\t\t<Button disabled={disabled || !merge} onClick={() => editor.execute((current) => splitTableDocumentCell(current, selection))}>\n\t\t\t\tРазъединить ячейки\n\t\t\t</Button>\n\t\t\t<CheckBox label=\"Выделять диапазон\" value={extendSelection} disabled={disabled} onChange={onExtendSelectionChange} />\n\t\t\t<span role=\"status\">\n\t\t\t\tВыделение: {selection.rowSpan} × {selection.columnSpan}. Шаг {editor.historyPosition} из {editor.historyLength - 1}.\n\t\t\t</span>\n\t\t\t{crossesHeader ? <p>Заголовок и основную часть нельзя объединить в одну ячейку.</p> : null}\n\t\t</div>\n\t);\n}\n","import { useState, type ReactNode } from \"react\";\n\nimport { updateTableDocumentCell, type TableDocumentCell } from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { CheckBox } from \"../../check-box\";\nimport { Input, InputNumber } from \"../../input\";\nimport { type TableEditorController } from \"../model/useTableEditor\";\n\nimport styles from \"./TableEditor.module.scss\";\nimport { TableEditorGrid } from \"./TableEditorGrid\";\nimport { TableEditorStructure } from \"./TableEditorStructure\";\nimport { TableEditorToolbar } from \"./TableEditorToolbar\";\n\n/** Host задаёт редактор содержимого: plain text, Lexical или ссылки на документы без KTK-зависимости пакета. */\nexport type TableEditorValueProps<T> = {\n\treadonly cell: TableDocumentCell<T>;\n\treadonly disabled: boolean;\n\treadonly onChange: (value: T) => void;\n};\nexport type TableEditorProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly renderCell: (cell: TableDocumentCell<T>) => ReactNode;\n\t/** Доступное текстовое представление preview, в котором интерактивные ссылки отключены. */\n\treadonly getCellText: (cell: TableDocumentCell<T>) => string;\n\treadonly renderValueEditor: (props: TableEditorValueProps<T>) => ReactNode;\n\treadonly createEmptyValue: () => T;\n\treadonly disabled?: boolean;\n};\n\n/** Композиция редактора, не владеющая transport, server state или форматом содержимого ячеек. */\nexport function TableEditor<T>({\n\teditor,\n\trenderCell,\n\tgetCellText,\n\trenderValueEditor,\n\tcreateEmptyValue,\n\tdisabled = false\n}: TableEditorProps<T>) {\n\tconst [extendSelection, setExtendSelection] = useState(false);\n\tconst { document, focus } = editor;\n\tconst cell = document.rows[focus.row].cells[focus.column];\n\treturn (\n\t\t<section className={styles.editor} aria-label=\"Конструктор таблицы\">\n\t\t\t<Input\n\t\t\t\tlabel=\"Название таблицы\"\n\t\t\t\tvalue={document.caption}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonChange={(caption) => editor.change({ ...document, caption: caption ?? \"\" })}\n\t\t\t/>\n\t\t\t<TableEditorToolbar\n\t\t\t\teditor={editor}\n\t\t\t\tdisabled={disabled}\n\t\t\t\textendSelection={extendSelection}\n\t\t\t\tonExtendSelectionChange={setExtendSelection}\n\t\t\t/>\n\t\t\t{editor.error ? <p role=\"alert\">{editor.error}</p> : null}\n\t\t\t<TableEditorGrid\n\t\t\t\teditor={editor}\n\t\t\t\tdisabled={disabled}\n\t\t\t\trenderCell={renderCell}\n\t\t\t\tgetCellText={getCellText}\n\t\t\t\textendSelection={extendSelection}\n\t\t\t/>\n\t\t\t<div className={styles.inspector}>\n\t\t\t\t<strong>\n\t\t\t\t\tЯчейка: строка {focus.row + 1}, столбец {focus.column + 1}\n\t\t\t\t</strong>\n\t\t\t\t{renderValueEditor({ cell, disabled, onChange: (value) => editor.change(updateTableDocumentCell(document, focus, value)) })}\n\t\t\t\t{editor.selection.rowSpan * editor.selection.columnSpan > 1 ? (\n\t\t\t\t\t<p>\n\t\t\t\t\t\tПри объединении показывается верхняя левая ячейка. Остальное содержимое сохранится и снова появится после\n\t\t\t\t\t\tразъединения.\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t<TableEditorStructure editor={editor} disabled={disabled} createEmptyValue={createEmptyValue} />\n\t\t\t<div className={styles.toolbar}>\n\t\t\t\t<CheckBox\n\t\t\t\t\tlabel=\"Скрыть заголовки при публикации\"\n\t\t\t\t\tvalue={document.hideHeaders}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={(hideHeaders) => editor.change({ ...document, hideHeaders })}\n\t\t\t\t/>\n\t\t\t\t<CheckBox\n\t\t\t\t\tlabel=\"Показывать номера строк\"\n\t\t\t\t\tvalue={document.showRowNumbers}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={(showRowNumbers) => editor.change({ ...document, showRowNumbers })}\n\t\t\t\t/>\n\t\t\t\t<InputNumber\n\t\t\t\t\tlabel=\"Ширина выбранного столбца, px\"\n\t\t\t\t\tvalue={document.columns[focus.column].width ?? undefined}\n\t\t\t\t\tmin={40}\n\t\t\t\t\tmax={1600}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={(width) => {\n\t\t\t\t\t\tif (width !== undefined && (width < 40 || width > 1600)) return;\n\t\t\t\t\t\teditor.change({\n\t\t\t\t\t\t\t...document,\n\t\t\t\t\t\t\tcolumns: document.columns.map((column, c) =>\n\t\t\t\t\t\t\t\tc === focus.column ? { ...column, width: width ?? null } : column\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t});\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</section>\n\t);\n}\n","import { useState } from \"react\";\n\nimport {\n\tassertTableDocument,\n\texpandTableDocumentRange,\n\tgetTableDocumentCellRange,\n\ttype TableDocument,\n\ttype TableDocumentPosition,\n\ttype TableDocumentRange\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\n/** Локальный draft: серверные версии, сохранение и конфликты принадлежат host-приложению. */\nexport type TableEditorController<T> = {\n\treadonly document: TableDocument<T>;\n\treadonly selection: TableDocumentRange;\n\treadonly focus: TableDocumentPosition;\n\treadonly canUndo: boolean;\n\treadonly canRedo: boolean;\n\treadonly historyPosition: number;\n\treadonly historyLength: number;\n\treadonly error: string | null;\n\treadonly select: (position: TableDocumentPosition, extend?: boolean) => void;\n\treadonly change: (document: TableDocument<T>) => void;\n\treadonly execute: (command: (document: TableDocument<T>) => TableDocument<T>) => void;\n\treadonly undo: () => void;\n\treadonly redo: () => void;\n};\n\n/**\n * История хранит документы со структурным разделением, а не копии server cache.\n * Новый initialDocument применяется только при новом mount/key: refetch не\n * затирает ввод. Копировальный bounded-copy-stack не подходит — он дедуплицирует\n * элементы и не сохраняет ветку undo/redo. Здесь максимум 100 редакторских шагов.\n */\nexport function useTableEditor<T>(initialDocument: TableDocument<T>): TableEditorController<T> {\n\tconst [state, setState] = useState(() => {\n\t\tassertTableDocument(initialDocument);\n\t\treturn {\n\t\t\tdocuments: [initialDocument],\n\t\t\tindex: 0,\n\t\t\tanchor: { row: 0, column: 0 },\n\t\t\tfocus: { row: 0, column: 0 },\n\t\t\terror: null as string | null\n\t\t};\n\t});\n\tconst document = state.documents[state.index];\n\tconst select = (position: TableDocumentPosition, extend = false) => {\n\t\tconst range = getTableDocumentCellRange(document, position);\n\t\tconst focus = { row: range.row, column: range.column };\n\t\tsetState((current) => ({ ...current, anchor: extend ? current.anchor : focus, focus, error: null }));\n\t};\n\tconst change = (next: TableDocument<T>) => {\n\t\tassertTableDocument(next);\n\t\tsetState((current) => {\n\t\t\tif (current.documents[current.index] === next) return current;\n\t\t\tconst documents = [...current.documents.slice(0, current.index + 1), next].slice(-101);\n\t\t\tconst position = {\n\t\t\t\trow: Math.min(current.focus.row, next.rows.length - 1),\n\t\t\t\tcolumn: Math.min(current.focus.column, next.columns.length - 1)\n\t\t\t};\n\t\t\tconst range = getTableDocumentCellRange(next, position);\n\t\t\tconst focus = { row: range.row, column: range.column };\n\t\t\treturn { documents, index: documents.length - 1, anchor: focus, focus, error: null };\n\t\t});\n\t};\n\tconst travel = (direction: -1 | 1) =>\n\t\tsetState((current) => {\n\t\t\tconst index = Math.max(0, Math.min(current.index + direction, current.documents.length - 1));\n\t\t\treturn { ...current, index, anchor: { row: 0, column: 0 }, focus: { row: 0, column: 0 }, error: null };\n\t\t});\n\treturn {\n\t\tdocument,\n\t\tselection: expandTableDocumentRange(document, state.anchor, state.focus),\n\t\tfocus: state.focus,\n\t\tcanUndo: state.index > 0,\n\t\tcanRedo: state.index < state.documents.length - 1,\n\t\thistoryPosition: state.index,\n\t\thistoryLength: state.documents.length,\n\t\terror: state.error,\n\t\tselect,\n\t\tchange,\n\t\tundo: () => travel(-1),\n\t\tredo: () => travel(1),\n\t\texecute: (command) => {\n\t\t\ttry {\n\t\t\t\tchange(command(document));\n\t\t\t} catch (error) {\n\t\t\t\t// Геометрические предусловия отклоняют команду, сохраняя draft и историю.\n\t\t\t\tsetState((current) => ({ ...current, error: error instanceof Error ? error.message : \"Не удалось изменить таблицу.\" }));\n\t\t\t}\n\t\t}\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/table-editor/ui/TableEditor.module.scss","../../src/table-editor/model/useTableEditorTable.ts","../../src/table-editor/ui/TableEditorGrid.tsx","../../src/table-editor/ui/TableEditorStructure.tsx","../../src/table-editor/ui/TableEditorToolbar.tsx","../../src/table-editor/ui/TableEditor.tsx","../../src/table-editor/model/useTableEditor.ts"],"sourcesContent":[".editor {\n\tdisplay: grid;\n\tgap: var(--space-md);\n\tmin-width: 0;\n\tcolor: var(--content-0);\n}\n.toolbar {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: var(--space-sm);\n}\n.help {\n\tmargin: 0;\n\tcolor: var(--content-1);\n}\n.scroll {\n\tmax-height: 34rem;\n\toverflow: auto;\n\tborder: var(--border);\n\tborder-radius: var(--radius-sm);\n}\n.table {\n\twidth: max-content;\n\tmin-width: 100%;\n\ttable-layout: fixed;\n\tborder-collapse: collapse;\n\n\ttd,\n\tth {\n\t\tpadding: var(--space-sm);\n\t\tmin-width: 6rem;\n\t\tborder: var(--border);\n\t\tvertical-align: top;\n\t\ttext-align: start;\n\t\tbackground: var(--surface-0);\n\t\tcursor: cell;\n\t\t&[aria-selected=\"true\"] {\n\t\t\tbackground: var(--surface-2);\n\t\t\tbox-shadow: inset 0 0 0 2px var(--content-1);\n\t\t}\n\t\t&:focus {\n\t\t\toutline: 3px solid var(--content-0);\n\t\t\toutline-offset: -3px;\n\t\t}\n\t}\n\ttr[data-header] th {\n\t\tfont-weight: 600;\n\t\t&:not([aria-selected=\"true\"]) {\n\t\t\tbackground: var(--surface-1);\n\t\t}\n\t}\n}\n.cellContent {\n\tmin-height: 2rem;\n\toverflow-wrap: anywhere;\n\tpointer-events: none;\n\tuser-select: none;\n}\n.inspector {\n\tdisplay: grid;\n\tgap: var(--space-sm);\n\tpadding: var(--space-md);\n\tborder: var(--border);\n\tbackground: var(--surface-1);\n}\n.structure {\n\tdisplay: grid;\n\tpadding: var(--space-sm);\n\tborder: var(--border);\n\tsummary {\n\t\tcursor: pointer;\n\t\tmargin-bottom: var(--space-sm);\n\t}\n\t.toolbar {\n\t\tmargin-bottom: var(--space-sm);\n\t}\n}\n","import { useMemo } from \"react\";\n\nimport { getTableDocumentCellRange, type TableDocument, type TableDocumentRow } from \"@ryuzaki13/react-foundation-lib/table-document\";\nimport { cellSpanningFeature, tableFeatures, useTable, type ColumnDef } from \"@tanstack/react-table\";\n\nconst features = tableFeatures({ cellSpanningFeature });\n\n/**\n * TanStack 9 получает стабильный anchor как accessor value: одинаковый текст\n * соседних ячеек сам по себе никогда не объединяет их. Порядок документа не\n * сортируется и не фильтруется; authored spans остаются authoritative.\n */\nexport function useTableEditorTable<T>(document: TableDocument<T>) {\n\t// Merge меняет accessor identity даже без изменения rows. Новый snapshot data\n\t// сбрасывает кэш значений TanStack и не оставляет устаревшие spans на экране.\n\tconst data = useMemo(() => [...document.rows], [document]);\n\tconst columns = useMemo<ColumnDef<typeof features, TableDocumentRow<T>>[]>(\n\t\t() =>\n\t\t\tdocument.columns.map((column, c) => ({\n\t\t\t\tid: column.id,\n\t\t\t\taccessorFn: (_row, r) => {\n\t\t\t\t\tconst range = getTableDocumentCellRange(document, { row: r, column: c });\n\t\t\t\t\treturn document.rows[range.row].cells[range.column].id;\n\t\t\t\t},\n\t\t\t\tspanRows: true,\n\t\t\t\tspanColumns: ({ row }) => {\n\t\t\t\t\tconst range = getTableDocumentCellRange(document, { row: row.index, column: c });\n\t\t\t\t\treturn range.column === c ? range.columnSpan : 1;\n\t\t\t\t}\n\t\t\t})),\n\t\t[document]\n\t);\n\treturn useTable({ features, data, columns, getRowId: (row) => row.id });\n}\n","import { useId, useRef, type ReactNode } from \"react\";\n\nimport {\n\tgetTableDocumentCellRange,\n\ttype TableDocumentCell,\n\ttype TableDocumentPosition\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { type TableEditorController } from \"../model/useTableEditor\";\nimport { useTableEditorTable } from \"../model/useTableEditorTable\";\n\nimport styles from \"./TableEditor.module.scss\";\n\ntype TableEditorGridProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly extendSelection: boolean;\n\treadonly disabled?: boolean;\n\treadonly renderCell: (cell: TableDocumentCell<T>) => ReactNode;\n\treadonly getCellText: (cell: TableDocumentCell<T>) => string;\n};\n\n/** Доступная сетка: roving tabindex, стрелки/Shift и выбор диапазона без drag-only действий. */\nexport function TableEditorGrid<T>({ editor, extendSelection, disabled, renderCell, getCellText }: TableEditorGridProps<T>) {\n\tconst helpId = useId();\n\tconst nodes = useRef(new Map<string, HTMLTableCellElement>());\n\tconst table = useTableEditorTable(editor.document);\n\tconst { document, selection, focus } = editor;\n\treturn (\n\t\t<>\n\t\t\t<p id={helpId} className={styles.help}>\n\t\t\t\tСтрелки — переход между ячейками. Shift + стрелки или Shift + щелчок — выделение диапазона. Содержимое выбранной ячейки\n\t\t\t\tредактируется под таблицей.\n\t\t\t</p>\n\t\t\t<div className={styles.scroll}>\n\t\t\t\t<table\n\t\t\t\t\trole=\"grid\"\n\t\t\t\t\taria-label={document.caption || \"Редактор таблицы\"}\n\t\t\t\t\taria-describedby={helpId}\n\t\t\t\t\taria-multiselectable=\"true\"\n\t\t\t\t\taria-disabled={disabled || undefined}\n\t\t\t\t\tclassName={styles.table}>\n\t\t\t\t\t<colgroup>\n\t\t\t\t\t\t{document.columns.map((column) => (\n\t\t\t\t\t\t\t<col key={column.id} style={{ width: column.width ?? 180 }} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</colgroup>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{table.getRowModel().rows.map((row) => (\n\t\t\t\t\t\t\t<tr key={row.id} aria-rowindex={row.index + 1} data-header={row.index < document.headerRowCount || undefined}>\n\t\t\t\t\t\t\t\t{row.getAllCells().map((cell, column) => {\n\t\t\t\t\t\t\t\t\tif (cell.getIsCovered()) return null;\n\t\t\t\t\t\t\t\t\tconst selected =\n\t\t\t\t\t\t\t\t\t\trow.index >= selection.row &&\n\t\t\t\t\t\t\t\t\t\trow.index < selection.row + selection.rowSpan &&\n\t\t\t\t\t\t\t\t\t\tcolumn >= selection.column &&\n\t\t\t\t\t\t\t\t\t\tcolumn < selection.column + selection.columnSpan;\n\t\t\t\t\t\t\t\t\tconst position = { row: row.index, column };\n\t\t\t\t\t\t\t\t\tconst original = row.original.cells[column];\n\t\t\t\t\t\t\t\t\tconst Cell = row.index < document.headerRowCount ? \"th\" : \"td\";\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<Cell\n\t\t\t\t\t\t\t\t\t\t\tkey={cell.id}\n\t\t\t\t\t\t\t\t\t\t\trole={row.index < document.headerRowCount ? \"columnheader\" : \"gridcell\"}\n\t\t\t\t\t\t\t\t\t\t\tref={(node) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (node) nodes.current.set(original.id, node);\n\t\t\t\t\t\t\t\t\t\t\t\telse nodes.current.delete(original.id);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\trowSpan={cell.getRowSpan()}\n\t\t\t\t\t\t\t\t\t\t\tcolSpan={cell.getColSpan()}\n\t\t\t\t\t\t\t\t\t\t\taria-colindex={column + 1}\n\t\t\t\t\t\t\t\t\t\t\taria-label={`Строка ${row.index + 1}, столбец ${column + 1}: ${getCellText(original) || \"Пустая ячейка\"}`}\n\t\t\t\t\t\t\t\t\t\t\taria-selected={selected}\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={!disabled && focus.row === row.index && focus.column === column ? 0 : -1}\n\t\t\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!disabled) editor.select(position, extendSelection || event.shiftKey);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonPointerEnter={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!disabled && event.pointerType === \"mouse\" && event.buttons === 1)\n\t\t\t\t\t\t\t\t\t\t\t\t\teditor.select(position, true);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (disabled || event.altKey || event.ctrlKey || event.metaKey) return;\n\t\t\t\t\t\t\t\t\t\t\t\tlet next: TableDocumentPosition;\n\t\t\t\t\t\t\t\t\t\t\t\tswitch (event.key) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowRight\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: column + cell.getColSpan() };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowLeft\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: column - 1 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowDown\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, row: row.index + cell.getRowSpan() };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"ArrowUp\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, row: row.index - 1 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"Home\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: 0 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \"End\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnext = { ...position, column: document.columns.length - 1 };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase \" \":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teditor.select(position, event.shiftKey);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.row < 0 ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.column < 0 ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.row >= document.rows.length ||\n\t\t\t\t\t\t\t\t\t\t\t\t\tnext.column >= document.columns.length\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\tconst range = getTableDocumentCellRange(document, next);\n\t\t\t\t\t\t\t\t\t\t\t\teditor.select(next, event.shiftKey);\n\t\t\t\t\t\t\t\t\t\t\t\tnodes.current.get(document.rows[range.row].cells[range.column].id)?.focus();\n\t\t\t\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\t\t\t\t{/* Preview не должен создавать вложенные tab stops или открывать ссылки вместо выделения. */}\n\t\t\t\t\t\t\t\t\t\t\t{row.index < document.headerRowCount ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"visuallyHidden\">{getCellText(original) || \"Пустой заголовок\"}</span>\n\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t<div inert className={styles.cellContent}>\n\t\t\t\t\t\t\t\t\t\t\t\t{renderCell(original)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</Cell>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { useState } from \"react\";\n\nimport { uuidv4 } from \"@ryuzaki13/react-foundation-lib/crypto\";\nimport {\n\tdeleteTableDocumentAxisGroup,\n\tgetTableDocumentAxisGroups,\n\tinsertTableDocumentAxis,\n\tmoveTableDocumentAxisGroup\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { Button } from \"../../button\";\nimport { Dialog } from \"../../dialog\";\nimport { type TableEditorController } from \"../model/useTableEditor\";\n\nimport styles from \"./TableEditor.module.scss\";\n\ntype TableEditorStructureProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly createEmptyValue: () => T;\n\treadonly disabled?: boolean;\n};\n\n/** Вставка и доступный reorder без обязательного drag; удаление подтверждает весь затронутый блок. */\nexport function TableEditorStructure<T>({ editor, createEmptyValue, disabled }: TableEditorStructureProps<T>) {\n\tconst [removing, setRemoving] = useState<\"row\" | \"column\" | null>(null);\n\tconst { document, focus } = editor;\n\tconst group = removing\n\t\t? getTableDocumentAxisGroups(document, removing).find(\n\t\t\t\t(item) => focus[removing] >= item.start && focus[removing] < item.start + item.count\n\t\t\t)\n\t\t: null;\n\treturn (\n\t\t<>\n\t\t\t<details className={styles.structure}>\n\t\t\t\t<summary>Строки и столбцы</summary>\n\t\t\t\t{([\"row\", \"column\"] as const).map((axis) => (\n\t\t\t\t\t<div key={axis} className={styles.toolbar} role=\"group\" aria-label={axis === \"row\" ? \"Строки\" : \"Столбцы\"}>\n\t\t\t\t\t\t<strong>{axis === \"row\" ? \"Строка\" : \"Столбец\"}</strong>\n\t\t\t\t\t\t{([0, 1] as const).map((offset) => (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tkey={offset}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tconst cells = Array.from(\n\t\t\t\t\t\t\t\t\t\t{ length: axis === \"row\" ? document.columns.length : document.rows.length },\n\t\t\t\t\t\t\t\t\t\t() => ({ id: uuidv4(), value: createEmptyValue() })\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tconst id = uuidv4();\n\t\t\t\t\t\t\t\t\teditor.execute((current) =>\n\t\t\t\t\t\t\t\t\t\tinsertTableDocumentAxis(\n\t\t\t\t\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\t\t\t\t\taxis,\n\t\t\t\t\t\t\t\t\t\t\tfocus[axis] + offset,\n\t\t\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\t\t\tcells,\n\t\t\t\t\t\t\t\t\t\t\tfocus.row < document.headerRowCount ? \"header\" : \"body\"\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}}>\n\t\t\t\t\t\t\t\tВставить {offset ? \"после\" : \"перед\"}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t{([-1, 1] as const).map((direction) => (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tkey={direction}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\teditor.execute((current) => moveTableDocumentAxisGroup(current, axis, focus[axis], direction))\n\t\t\t\t\t\t\t\t}>\n\t\t\t\t\t\t\t\tПереместить {axis === \"row\" ? (direction === -1 ? \"выше\" : \"ниже\") : direction === -1 ? \"левее\" : \"правее\"}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<Button tone=\"error\" disabled={disabled} onClick={() => setRemoving(axis)}>\n\t\t\t\t\t\t\tУдалить {axis === \"row\" ? \"строку\" : \"столбец\"}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\t\t\t\t<Button\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tconst cells = document.columns.map(() => ({ id: uuidv4(), value: createEmptyValue() }));\n\t\t\t\t\t\tconst id = uuidv4();\n\t\t\t\t\t\teditor.execute((current) => insertTableDocumentAxis(current, \"row\", current.headerRowCount, id, cells, \"header\"));\n\t\t\t\t\t}}>\n\t\t\t\t\tДобавить строку заголовка\n\t\t\t\t</Button>\n\t\t\t</details>\n\t\t\t<Dialog\n\t\t\t\topen={Boolean(removing)}\n\t\t\t\tonClose={() => setRemoving(null)}\n\t\t\t\ttitle=\"Удалить часть таблицы?\"\n\t\t\t\tdescription={`Будет удалено ${group?.count ?? 0} ${removing === \"row\" ? \"строк\" : \"столбцов\"}, включая скрытое объединением содержимое. Объединённая группа удаляется целиком. До сохранения действие можно отменить.`}>\n\t\t\t\t<div className={styles.toolbar}>\n\t\t\t\t\t<Button onClick={() => setRemoving(null)}>Не удалять</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttone=\"error\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tif (removing) editor.execute((current) => deleteTableDocumentAxisGroup(current, removing, focus[removing]));\n\t\t\t\t\t\t\tsetRemoving(null);\n\t\t\t\t\t\t}}>\n\t\t\t\t\t\tУдалить группу\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</Dialog>\n\t\t</>\n\t);\n}\n","import {\n\tmergeTableDocumentCells,\n\tsplitTableDocumentCell,\n\ttype TableDocumentPosition\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { Button } from \"../../button\";\nimport { CheckBox } from \"../../check-box\";\nimport { type TableEditorController } from \"../model/useTableEditor\";\n\nimport styles from \"./TableEditor.module.scss\";\n\ntype TableEditorToolbarProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly disabled?: boolean;\n\treadonly extendSelection: boolean;\n\treadonly onExtendSelectionChange: (value: boolean) => void;\n};\n\n/** Явные названия действий вместо скрытых режимов merge/split из legacy. */\nexport function TableEditorToolbar<T>({ editor, disabled, extendSelection, onExtendSelectionChange }: TableEditorToolbarProps<T>) {\n\tconst { document, selection } = editor;\n\tconst end: TableDocumentPosition = { row: selection.row + selection.rowSpan - 1, column: selection.column + selection.columnSpan - 1 };\n\tconst isSingle = selection.rowSpan * selection.columnSpan === 1;\n\tconst crossesHeader = selection.row < document.headerRowCount && end.row >= document.headerRowCount;\n\tconst merge = document.merges.find(\n\t\t(range) =>\n\t\t\trange.row === selection.row &&\n\t\t\trange.column === selection.column &&\n\t\t\trange.rowSpan === selection.rowSpan &&\n\t\t\trange.columnSpan === selection.columnSpan\n\t);\n\treturn (\n\t\t<div className={styles.toolbar} role=\"group\" aria-label=\"История и объединение\">\n\t\t\t<Button disabled={disabled || !editor.canUndo} onClick={editor.undo}>\n\t\t\t\tОтменить\n\t\t\t</Button>\n\t\t\t<Button disabled={disabled || !editor.canRedo} onClick={editor.redo}>\n\t\t\t\tПовторить\n\t\t\t</Button>\n\t\t\t<Button\n\t\t\t\tdisabled={disabled || isSingle || crossesHeader || Boolean(merge)}\n\t\t\t\tonClick={() => editor.execute((current) => mergeTableDocumentCells(current, selection, end))}>\n\t\t\t\tОбъединить ячейки\n\t\t\t</Button>\n\t\t\t<Button disabled={disabled || !merge} onClick={() => editor.execute((current) => splitTableDocumentCell(current, selection))}>\n\t\t\t\tРазъединить ячейки\n\t\t\t</Button>\n\t\t\t<CheckBox label=\"Выделять диапазон\" value={extendSelection} disabled={disabled} onChange={onExtendSelectionChange} />\n\t\t\t<span role=\"status\">\n\t\t\t\tВыделение: {selection.rowSpan} × {selection.columnSpan}. Шаг {editor.historyPosition} из {editor.historyLength - 1}.\n\t\t\t</span>\n\t\t\t{crossesHeader ? <p>Заголовок и основную часть нельзя объединить в одну ячейку.</p> : null}\n\t\t</div>\n\t);\n}\n","import { useState, type ReactNode } from \"react\";\n\nimport { updateTableDocumentCell, type TableDocumentCell } from \"@ryuzaki13/react-foundation-lib/table-document\";\n\nimport { CheckBox } from \"../../check-box\";\nimport { Input, InputNumber } from \"../../input\";\nimport { type TableEditorController } from \"../model/useTableEditor\";\n\nimport styles from \"./TableEditor.module.scss\";\nimport { TableEditorGrid } from \"./TableEditorGrid\";\nimport { TableEditorStructure } from \"./TableEditorStructure\";\nimport { TableEditorToolbar } from \"./TableEditorToolbar\";\n\n/** Host задаёт редактор содержимого: plain text, Lexical или ссылки на документы без KTK-зависимости пакета. */\nexport type TableEditorValueProps<T> = {\n\treadonly cell: TableDocumentCell<T>;\n\treadonly disabled: boolean;\n\treadonly onChange: (value: T) => void;\n};\nexport type TableEditorProps<T> = {\n\treadonly editor: TableEditorController<T>;\n\treadonly renderCell: (cell: TableDocumentCell<T>) => ReactNode;\n\t/** Доступное текстовое представление preview, в котором интерактивные ссылки отключены. */\n\treadonly getCellText: (cell: TableDocumentCell<T>) => string;\n\treadonly renderValueEditor: (props: TableEditorValueProps<T>) => ReactNode;\n\treadonly createEmptyValue: () => T;\n\treadonly disabled?: boolean;\n};\n\n/** Композиция редактора, не владеющая transport, server state или форматом содержимого ячеек. */\nexport function TableEditor<T>({\n\teditor,\n\trenderCell,\n\tgetCellText,\n\trenderValueEditor,\n\tcreateEmptyValue,\n\tdisabled = false\n}: TableEditorProps<T>) {\n\tconst [extendSelection, setExtendSelection] = useState(false);\n\tconst { document, focus } = editor;\n\tconst cell = document.rows[focus.row].cells[focus.column];\n\treturn (\n\t\t<section className={styles.editor} aria-label=\"Конструктор таблицы\">\n\t\t\t<Input\n\t\t\t\tlabel=\"Название таблицы\"\n\t\t\t\tvalue={document.caption}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonChange={(caption) => editor.change({ ...document, caption: caption ?? \"\" })}\n\t\t\t/>\n\t\t\t<TableEditorToolbar\n\t\t\t\teditor={editor}\n\t\t\t\tdisabled={disabled}\n\t\t\t\textendSelection={extendSelection}\n\t\t\t\tonExtendSelectionChange={setExtendSelection}\n\t\t\t/>\n\t\t\t{editor.error ? <p role=\"alert\">{editor.error}</p> : null}\n\t\t\t<TableEditorGrid\n\t\t\t\teditor={editor}\n\t\t\t\tdisabled={disabled}\n\t\t\t\trenderCell={renderCell}\n\t\t\t\tgetCellText={getCellText}\n\t\t\t\textendSelection={extendSelection}\n\t\t\t/>\n\t\t\t<div className={styles.inspector}>\n\t\t\t\t<strong>\n\t\t\t\t\tЯчейка: строка {focus.row + 1}, столбец {focus.column + 1}\n\t\t\t\t</strong>\n\t\t\t\t{renderValueEditor({ cell, disabled, onChange: (value) => editor.change(updateTableDocumentCell(document, focus, value)) })}\n\t\t\t\t{editor.selection.rowSpan * editor.selection.columnSpan > 1 ? (\n\t\t\t\t\t<p>\n\t\t\t\t\t\tПри объединении показывается верхняя левая ячейка. Остальное содержимое сохранится и снова появится после\n\t\t\t\t\t\tразъединения.\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t<TableEditorStructure editor={editor} disabled={disabled} createEmptyValue={createEmptyValue} />\n\t\t\t<div className={styles.toolbar}>\n\t\t\t\t<CheckBox\n\t\t\t\t\tlabel=\"Скрыть заголовки при публикации\"\n\t\t\t\t\tvalue={document.hideHeaders}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={(hideHeaders) => editor.change({ ...document, hideHeaders })}\n\t\t\t\t/>\n\t\t\t\t<CheckBox\n\t\t\t\t\tlabel=\"Показывать номера строк\"\n\t\t\t\t\tvalue={document.showRowNumbers}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={(showRowNumbers) => editor.change({ ...document, showRowNumbers })}\n\t\t\t\t/>\n\t\t\t\t<InputNumber\n\t\t\t\t\tlabel=\"Ширина выбранного столбца, px\"\n\t\t\t\t\tvalue={document.columns[focus.column].width ?? undefined}\n\t\t\t\t\tmin={40}\n\t\t\t\t\tmax={1600}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={(width) => {\n\t\t\t\t\t\tif (width !== undefined && (width < 40 || width > 1600)) return;\n\t\t\t\t\t\teditor.change({\n\t\t\t\t\t\t\t...document,\n\t\t\t\t\t\t\tcolumns: document.columns.map((column, c) =>\n\t\t\t\t\t\t\t\tc === focus.column ? { ...column, width: width ?? null } : column\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t});\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</section>\n\t);\n}\n","import { useState } from \"react\";\n\nimport {\n\tassertTableDocument,\n\texpandTableDocumentRange,\n\tgetTableDocumentCellRange,\n\ttype TableDocument,\n\ttype TableDocumentPosition,\n\ttype TableDocumentRange\n} from \"@ryuzaki13/react-foundation-lib/table-document\";\n\n/** Локальный draft: серверные версии, сохранение и конфликты принадлежат host-приложению. */\nexport type TableEditorController<T> = {\n\treadonly document: TableDocument<T>;\n\treadonly selection: TableDocumentRange;\n\treadonly focus: TableDocumentPosition;\n\treadonly canUndo: boolean;\n\treadonly canRedo: boolean;\n\treadonly historyPosition: number;\n\treadonly historyLength: number;\n\treadonly error: string | null;\n\treadonly select: (position: TableDocumentPosition, extend?: boolean) => void;\n\treadonly change: (document: TableDocument<T>) => void;\n\treadonly execute: (command: (document: TableDocument<T>) => TableDocument<T>) => void;\n\treadonly undo: () => void;\n\treadonly redo: () => void;\n};\n\n/**\n * История хранит документы со структурным разделением, а не копии server cache.\n * Новый initialDocument применяется только при новом mount/key: refetch не\n * затирает ввод. Копировальный bounded-copy-stack не подходит — он дедуплицирует\n * элементы и не сохраняет ветку undo/redo. Здесь максимум 100 редакторских шагов.\n */\nexport function useTableEditor<T>(initialDocument: TableDocument<T>): TableEditorController<T> {\n\tconst [state, setState] = useState(() => {\n\t\tassertTableDocument(initialDocument);\n\t\treturn {\n\t\t\tdocuments: [initialDocument],\n\t\t\tindex: 0,\n\t\t\tanchor: { row: 0, column: 0 },\n\t\t\tfocus: { row: 0, column: 0 },\n\t\t\terror: null as string | null\n\t\t};\n\t});\n\tconst document = state.documents[state.index];\n\tconst select = (position: TableDocumentPosition, extend = false) => {\n\t\tconst range = getTableDocumentCellRange(document, position);\n\t\tconst focus = { row: range.row, column: range.column };\n\t\tsetState((current) => ({ ...current, anchor: extend ? current.anchor : focus, focus, error: null }));\n\t};\n\tconst change = (next: TableDocument<T>) => {\n\t\tassertTableDocument(next);\n\t\tsetState((current) => {\n\t\t\tif (current.documents[current.index] === next) return current;\n\t\t\tconst documents = [...current.documents.slice(0, current.index + 1), next].slice(-101);\n\t\t\tconst position = {\n\t\t\t\trow: Math.min(current.focus.row, next.rows.length - 1),\n\t\t\t\tcolumn: Math.min(current.focus.column, next.columns.length - 1)\n\t\t\t};\n\t\t\tconst range = getTableDocumentCellRange(next, position);\n\t\t\tconst focus = { row: range.row, column: range.column };\n\t\t\treturn { documents, index: documents.length - 1, anchor: focus, focus, error: null };\n\t\t});\n\t};\n\tconst travel = (direction: -1 | 1) =>\n\t\tsetState((current) => {\n\t\t\tconst index = Math.max(0, Math.min(current.index + direction, current.documents.length - 1));\n\t\t\treturn { ...current, index, anchor: { row: 0, column: 0 }, focus: { row: 0, column: 0 }, error: null };\n\t\t});\n\treturn {\n\t\tdocument,\n\t\tselection: expandTableDocumentRange(document, state.anchor, state.focus),\n\t\tfocus: state.focus,\n\t\tcanUndo: state.index > 0,\n\t\tcanRedo: state.index < state.documents.length - 1,\n\t\thistoryPosition: state.index,\n\t\thistoryLength: state.documents.length,\n\t\terror: state.error,\n\t\tselect,\n\t\tchange,\n\t\tundo: () => travel(-1),\n\t\tredo: () => travel(1),\n\t\texecute: (command) => {\n\t\t\ttry {\n\t\t\t\tchange(command(document));\n\t\t\t} catch (error) {\n\t\t\t\t// Геометрические предусловия отклоняют команду, сохраняя draft и историю.\n\t\t\t\tsetState((current) => ({ ...current, error: error instanceof Error ? error.message : \"Не удалось изменить таблицу.\" }));\n\t\t\t}\n\t\t}\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;GCKM,IAAW,EAAc,EAAE,uBAAoB,CAAC;AAOtD,SAAgB,EAAuB,GAA4B;CAGlE,IAAM,IAAO,QAAc,CAAC,GAAG,EAAS,IAAI,GAAG,CAAC,CAAQ,CAAC,GACnD,IAAU,QAEd,EAAS,QAAQ,KAAK,GAAQ,OAAO;EACpC,IAAI,EAAO;EACX,aAAa,GAAM,MAAM;GACxB,IAAM,IAAQ,EAA0B,GAAU;IAAE,KAAK;IAAG,QAAQ;GAAE,CAAC;GACvE,OAAO,EAAS,KAAK,EAAM,IAAI,CAAC,MAAM,EAAM,OAAO,CAAC;EACrD;EACA,UAAU;EACV,cAAc,EAAE,aAAU;GACzB,IAAM,IAAQ,EAA0B,GAAU;IAAE,KAAK,EAAI;IAAO,QAAQ;GAAE,CAAC;GAC/E,OAAO,EAAM,WAAW,IAAI,EAAM,aAAa;EAChD;CACD,EAAE,GACH,CAAC,CAAQ,CACV;CACA,OAAO,EAAS;EAAE;EAAU;EAAM;EAAS,WAAW,MAAQ,EAAI;CAAG,CAAC;AACvE;;;ACXA,SAAgB,EAAmB,EAAE,WAAQ,oBAAiB,aAAU,eAAY,kBAAwC;CAC3H,IAAM,IAAS,EAAM,GACf,IAAQ,kBAAO,IAAI,IAAkC,CAAC,GACtD,IAAQ,EAAoB,EAAO,QAAQ,GAC3C,EAAE,aAAU,cAAW,aAAU;CACvC,OACC,kBAAA,GAAA,EAAA,UAAA,CACC,kBAAC,KAAD;EAAG,IAAI;EAAQ,WAAW,EAAO;EAAM,UAAA;CAGpC,CAAA,GACH,kBAAC,OAAD;EAAK,WAAW,EAAO;EACtB,UAAA,kBAAC,SAAD;GACC,MAAK;GACL,cAAY,EAAS,WAAW;GAChC,oBAAkB;GAClB,wBAAqB;GACrB,iBAAe,KAAY,KAAA;GAC3B,WAAW,EAAO;GANnB,UAAA,CAOC,kBAAC,YAAD,EAAA,UACE,EAAS,QAAQ,KAAK,MACtB,kBAAC,OAAD,EAAqB,OAAO,EAAE,OAAO,EAAO,SAAS,IAAI,EAAI,GAAnD,EAAO,EAA4C,CAC7D,EACQ,CAAA,GACV,kBAAC,SAAD,EAAA,UACE,EAAM,YAAY,CAAC,CAAC,KAAK,KAAK,MAC9B,kBAAC,MAAD;IAAiB,iBAAe,EAAI,QAAQ;IAAG,eAAa,EAAI,QAAQ,EAAS,kBAAkB,KAAA;IACjG,UAAA,EAAI,YAAY,CAAC,CAAC,KAAK,GAAM,MAAW;KACxC,IAAI,EAAK,aAAa,GAAG,OAAO;KAChC,IAAM,IACL,EAAI,SAAS,EAAU,OACvB,EAAI,QAAQ,EAAU,MAAM,EAAU,WACtC,KAAU,EAAU,UACpB,IAAS,EAAU,SAAS,EAAU,YACjC,IAAW;MAAE,KAAK,EAAI;MAAO;KAAO,GACpC,IAAW,EAAI,SAAS,MAAM,IAC9B,IAAO,EAAI,QAAQ,EAAS,iBAAiB,OAAO;KAC1D,OACC,kBAAC,GAAD;MAEC,MAAM,EAAI,QAAQ,EAAS,iBAAiB,iBAAiB;MAC7D,MAAM,MAAS;OACd,AAAI,IAAM,EAAM,QAAQ,IAAI,EAAS,IAAI,CAAI,IACxC,EAAM,QAAQ,OAAO,EAAS,EAAE;MACtC;MACA,SAAS,EAAK,WAAW;MACzB,SAAS,EAAK,WAAW;MACzB,iBAAe,IAAS;MACxB,cAAY,UAAU,EAAI,QAAQ,EAAE,YAAY,IAAS,EAAE,IAAI,EAAY,CAAQ,KAAK;MACxF,iBAAe;MACf,UAAU,CAAC,KAAY,EAAM,QAAQ,EAAI,SAAS,EAAM,WAAW,IAAS,IAAI;MAChF,UAAU,MAAU;OACnB,AAAK,KAAU,EAAO,OAAO,GAAU,KAAmB,EAAM,QAAQ;MACzE;MACA,iBAAiB,MAAU;OAC1B,AAAI,CAAC,KAAY,EAAM,gBAAgB,WAAW,EAAM,YAAY,KACnE,EAAO,OAAO,GAAU,EAAI;MAC9B;MACA,YAAY,MAAU;OACrB,IAAI,KAAY,EAAM,UAAU,EAAM,WAAW,EAAM,SAAS;OAChE,IAAI;OACJ,QAAQ,EAAM,KAAd;QACC,KAAK;SACJ,IAAO;UAAE,GAAG;UAAU,QAAQ,IAAS,EAAK,WAAW;SAAE;SACzD;QACD,KAAK;SACJ,IAAO;UAAE,GAAG;UAAU,QAAQ,IAAS;SAAE;SACzC;QACD,KAAK;SACJ,IAAO;UAAE,GAAG;UAAU,KAAK,EAAI,QAAQ,EAAK,WAAW;SAAE;SACzD;QACD,KAAK;SACJ,IAAO;UAAE,GAAG;UAAU,KAAK,EAAI,QAAQ;SAAE;SACzC;QACD,KAAK;SACJ,IAAO;UAAE,GAAG;UAAU,QAAQ;SAAE;SAChC;QACD,KAAK;SACJ,IAAO;UAAE,GAAG;UAAU,QAAQ,EAAS,QAAQ,SAAS;SAAE;SAC1D;QACD,KAAK;SAEJ,AADA,EAAM,eAAe,GACrB,EAAO,OAAO,GAAU,EAAM,QAAQ;SACtC;QACD,SACC;OACF;OAEA,IADA,EAAM,eAAe,GAEpB,EAAK,MAAM,KACX,EAAK,SAAS,KACd,EAAK,OAAO,EAAS,KAAK,UAC1B,EAAK,UAAU,EAAS,QAAQ,QAEhC;OACD,IAAM,IAAQ,EAA0B,GAAU,CAAI;OAEtD,AADA,EAAO,OAAO,GAAM,EAAM,QAAQ,GAClC,EAAM,QAAQ,IAAI,EAAS,KAAK,EAAM,IAAI,CAAC,MAAM,EAAM,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM;MAC3E;MA5DD,UAAA,CA8DE,EAAI,QAAQ,EAAS,iBACrB,kBAAC,QAAD;OAAM,WAAU;OAAkB,UAAA,EAAY,CAAQ,KAAK;MAAyB,CAAA,IACjF,MACJ,kBAAC,OAAD;OAAK,OAAA;OAAM,WAAW,EAAO;OAC3B,UAAA,EAAW,CAAQ;MAChB,CAAA,CACA;KAnEA,GAAA,EAAK,EAmEL;IAER,CAAC;GACE,GAnFK,EAAI,EAmFT,CACJ,EACK,CAAA,CACD;;CACH,CAAA,CACJ,EAAA,CAAA;AAEJ;;;ACnHA,SAAgB,EAAwB,EAAE,WAAQ,qBAAkB,eAA0C;CAC7G,IAAM,CAAC,GAAU,KAAe,EAAkC,IAAI,GAChE,EAAE,aAAU,aAAU,GACtB,IAAQ,IACX,EAA2B,GAAU,CAAQ,CAAC,CAAC,MAC9C,MAAS,EAAM,MAAa,EAAK,SAAS,EAAM,KAAY,EAAK,QAAQ,EAAK,KAChF,IACC;CACH,OACC,kBAAA,GAAA,EAAA,UAAA,CACC,kBAAC,WAAD;EAAS,WAAW,EAAO;EAA3B,UAAA;GACC,kBAAC,WAAD,EAAA,UAAS,mBAAyB,CAAA;GAChC,CAAC,OAAO,QAAQ,CAAC,CAAW,KAAK,MAClC,kBAAC,OAAD;IAAgB,WAAW,EAAO;IAAS,MAAK;IAAQ,cAAY,MAAS,QAAQ,WAAW;IAAhG,UAAA;KACC,kBAAC,UAAD,EAAA,UAAS,MAAS,QAAQ,WAAW,UAAkB,CAAA;KACrD,CAAC,GAAG,CAAC,CAAC,CAAW,KAAK,MACvB,kBAAC,GAAD;MAEW;MACV,eAAe;OACd,IAAM,IAAQ,MAAM,KACnB,EAAE,QAAQ,MAAS,QAAQ,EAAS,QAAQ,SAAS,EAAS,KAAK,OAAO,UACnE;QAAE,IAAI,EAAO;QAAG,OAAO,EAAiB;OAAE,EAClD,GACM,IAAK,EAAO;OAClB,EAAO,SAAS,MACf,EACC,GACA,GACA,EAAM,KAAQ,GACd,GACA,GACA,EAAM,MAAM,EAAS,iBAAiB,WAAW,MAClD,CACD;MACD;MAnBD,UAAA,CAmBI,aACO,IAAS,UAAU,OACtB;KApBF,GAAA,CAoBE,CACR;KACC,CAAC,IAAI,CAAC,CAAC,CAAW,KAAK,MACxB,kBAAC,GAAD;MAEW;MACV,eACC,EAAO,SAAS,MAAY,EAA2B,GAAS,GAAM,EAAM,IAAO,CAAS,CAAC;MAJ/F,UAAA,CAKG,gBACW,MAAS,QAAS,MAAc,KAAK,SAAS,SAAU,MAAc,KAAK,UAAU,QAC3F;KANF,GAAA,CAME,CACR;KACD,kBAAC,GAAD;MAAQ,MAAK;MAAkB;MAAU,eAAe,EAAY,CAAI;MAAxE,UAAA,CAA2E,YACjE,MAAS,QAAQ,WAAW,SAC9B;;IACJ;GAvCK,GAAA,CAuCL,CACL;GACD,kBAAC,GAAD;IACW;IACV,eAAe;KACd,IAAM,IAAQ,EAAS,QAAQ,WAAW;MAAE,IAAI,EAAO;MAAG,OAAO,EAAiB;KAAE,EAAE,GAChF,IAAK,EAAO;KAClB,EAAO,SAAS,MAAY,EAAwB,GAAS,OAAO,EAAQ,gBAAgB,GAAI,GAAO,QAAQ,CAAC;IACjH;IAAG,UAAA;GAEI,CAAA;EACA;CACT,CAAA,GAAA,kBAAC,GAAD;EACC,MAAM,EAAQ;EACd,eAAe,EAAY,IAAI;EAC/B,OAAM;EACN,aAAa,iBAAiB,GAAO,SAAS,EAAE,GAAG,MAAa,QAAQ,UAAU,WAAW;EAC7F,UAAA,kBAAC,OAAD;GAAK,WAAW,EAAO;GAAvB,UAAA,CACC,kBAAC,GAAD;IAAQ,eAAe,EAAY,IAAI;IAAG,UAAA;GAAkB,CAAA,GAC5D,kBAAC,GAAD;IACC,MAAK;IACK;IACV,eAAe;KAEd,AADI,KAAU,EAAO,SAAS,MAAY,EAA6B,GAAS,GAAU,EAAM,EAAS,CAAC,GAC1G,EAAY,IAAI;IACjB;IAAG,UAAA;GAEI,CAAA,CACJ;;CACE,CAAA,CACP,EAAA,CAAA;AAEJ;;;ACvFA,SAAgB,EAAsB,EAAE,WAAQ,aAAU,oBAAiB,8BAAuD;CACjI,IAAM,EAAE,aAAU,iBAAc,GAC1B,IAA6B;EAAE,KAAK,EAAU,MAAM,EAAU,UAAU;EAAG,QAAQ,EAAU,SAAS,EAAU,aAAa;CAAE,GAC/H,IAAW,EAAU,UAAU,EAAU,eAAe,GACxD,IAAgB,EAAU,MAAM,EAAS,kBAAkB,EAAI,OAAO,EAAS,gBAC/E,IAAQ,EAAS,OAAO,MAC5B,MACA,EAAM,QAAQ,EAAU,OACxB,EAAM,WAAW,EAAU,UAC3B,EAAM,YAAY,EAAU,WAC5B,EAAM,eAAe,EAAU,UACjC;CACA,OACC,kBAAC,OAAD;EAAK,WAAW,EAAO;EAAS,MAAK;EAAQ,cAAW;EAAxD,UAAA;GACC,kBAAC,GAAD;IAAQ,UAAU,KAAY,CAAC,EAAO;IAAS,SAAS,EAAO;IAAM,UAAA;GAE7D,CAAA;GACR,kBAAC,GAAD;IAAQ,UAAU,KAAY,CAAC,EAAO;IAAS,SAAS,EAAO;IAAM,UAAA;GAE7D,CAAA;GACR,kBAAC,GAAD;IACC,UAAU,KAAY,KAAY,KAAiB,EAAQ;IAC3D,eAAe,EAAO,SAAS,MAAY,EAAwB,GAAS,GAAW,CAAG,CAAC;IAAG,UAAA;GAEvF,CAAA;GACR,kBAAC,GAAD;IAAQ,UAAU,KAAY,CAAC;IAAO,eAAe,EAAO,SAAS,MAAY,EAAuB,GAAS,CAAS,CAAC;IAAG,UAAA;GAEtH,CAAA;GACR,kBAAC,GAAD;IAAU,OAAM;IAAoB,OAAO;IAA2B;IAAU,UAAU;GAA0B,CAAA;GACpH,kBAAC,QAAD;IAAM,MAAK;IAAX,UAAA;KAAoB;KACP,EAAU;KAAQ;KAAI,EAAU;KAAW;KAAO,EAAO;KAAgB;KAAK,EAAO,gBAAgB;KAAE;IAC9G;;GACL,IAAgB,kBAAC,KAAD,EAAA,UAAG,8DAA8D,CAAA,IAAI;EAClF;;AAEP;;;ACzBA,SAAgB,EAAe,EAC9B,WACA,eACA,gBACA,sBACA,qBACA,cAAW,MACY;CACvB,IAAM,CAAC,GAAiB,KAAsB,EAAS,EAAK,GACtD,EAAE,aAAU,aAAU,GACtB,IAAO,EAAS,KAAK,EAAM,IAAI,CAAC,MAAM,EAAM;CAClD,OACC,kBAAC,WAAD;EAAS,WAAW,EAAO;EAAQ,cAAW;EAA9C,UAAA;GACC,kBAAC,GAAD;IACC,OAAM;IACN,OAAO,EAAS;IACN;IACV,WAAW,MAAY,EAAO,OAAO;KAAE,GAAG;KAAU,SAAS,KAAW;IAAG,CAAC;GAC5E,CAAA;GACD,kBAAC,GAAD;IACS;IACE;IACO;IACjB,yBAAyB;GACzB,CAAA;GACA,EAAO,QAAQ,kBAAC,KAAD;IAAG,MAAK;IAAS,UAAA,EAAO;GAAS,CAAA,IAAI;GACrD,kBAAC,GAAD;IACS;IACE;IACE;IACC;IACI;GACjB,CAAA;GACD,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA;KACC,kBAAC,UAAD,EAAA,UAAA;MAAQ;MACS,EAAM,MAAM;MAAE;MAAW,EAAM,SAAS;KACjD,EAAA,CAAA;KACP,EAAkB;MAAE;MAAM;MAAU,WAAW,MAAU,EAAO,OAAO,EAAwB,GAAU,GAAO,CAAK,CAAC;KAAE,CAAC;KACzH,EAAO,UAAU,UAAU,EAAO,UAAU,aAAa,IACzD,kBAAC,KAAD,EAAA,UAAG,0HAGA,CAAA,IACA;IACA;;GACL,kBAAC,GAAD;IAA8B;IAAkB;IAA4B;GAAmB,CAAA;GAC/F,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA;KACC,kBAAC,GAAD;MACC,OAAM;MACN,OAAO,EAAS;MACN;MACV,WAAW,MAAgB,EAAO,OAAO;OAAE,GAAG;OAAU;MAAY,CAAC;KACrE,CAAA;KACD,kBAAC,GAAD;MACC,OAAM;MACN,OAAO,EAAS;MACN;MACV,WAAW,MAAmB,EAAO,OAAO;OAAE,GAAG;OAAU;MAAe,CAAC;KAC3E,CAAA;KACD,kBAAC,GAAD;MACC,OAAM;MACN,OAAO,EAAS,QAAQ,EAAM,OAAO,CAAC,SAAS,KAAA;MAC/C,KAAK;MACL,KAAK;MACK;MACV,WAAW,MAAU;OAChB,MAAU,KAAA,MAAc,IAAQ,MAAM,IAAQ,SAClD,EAAO,OAAO;QACb,GAAG;QACH,SAAS,EAAS,QAAQ,KAAK,GAAQ,MACtC,MAAM,EAAM,SAAS;SAAE,GAAG;SAAQ,OAAO,KAAS;QAAK,IAAI,CAC5D;OACD,CAAC;MACF;KACA,CAAA;IACG;;EACG;;AAEX;;;AC1EA,SAAgB,EAAkB,GAA6D;CAC9F,IAAM,CAAC,GAAO,KAAY,SACzB,EAAoB,CAAe,GAC5B;EACN,WAAW,CAAC,CAAe;EAC3B,OAAO;EACP,QAAQ;GAAE,KAAK;GAAG,QAAQ;EAAE;EAC5B,OAAO;GAAE,KAAK;GAAG,QAAQ;EAAE;EAC3B,OAAO;CACR,EACA,GACK,IAAW,EAAM,UAAU,EAAM,QACjC,KAAU,GAAiC,IAAS,OAAU;EACnE,IAAM,IAAQ,EAA0B,GAAU,CAAQ,GACpD,IAAQ;GAAE,KAAK,EAAM;GAAK,QAAQ,EAAM;EAAO;EACrD,GAAU,OAAa;GAAE,GAAG;GAAS,QAAQ,IAAS,EAAQ,SAAS;GAAO;GAAO,OAAO;EAAK,EAAE;CACpG,GACM,KAAU,MAA2B;EAE1C,AADA,EAAoB,CAAI,GACxB,GAAU,MAAY;GACrB,IAAI,EAAQ,UAAU,EAAQ,WAAW,GAAM,OAAO;GACtD,IAAM,IAAY,CAAC,GAAG,EAAQ,UAAU,MAAM,GAAG,EAAQ,QAAQ,CAAC,GAAG,CAAI,CAAC,CAAC,MAAM,IAAI,GAC/E,IAAW;IAChB,KAAK,KAAK,IAAI,EAAQ,MAAM,KAAK,EAAK,KAAK,SAAS,CAAC;IACrD,QAAQ,KAAK,IAAI,EAAQ,MAAM,QAAQ,EAAK,QAAQ,SAAS,CAAC;GAC/D,GACM,IAAQ,EAA0B,GAAM,CAAQ,GAChD,IAAQ;IAAE,KAAK,EAAM;IAAK,QAAQ,EAAM;GAAO;GACrD,OAAO;IAAE;IAAW,OAAO,EAAU,SAAS;IAAG,QAAQ;IAAO;IAAO,OAAO;GAAK;EACpF,CAAC;CACF,GACM,KAAU,MACf,GAAU,MAAY;EACrB,IAAM,IAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,EAAQ,QAAQ,GAAW,EAAQ,UAAU,SAAS,CAAC,CAAC;EAC3F,OAAO;GAAE,GAAG;GAAS;GAAO,QAAQ;IAAE,KAAK;IAAG,QAAQ;GAAE;GAAG,OAAO;IAAE,KAAK;IAAG,QAAQ;GAAE;GAAG,OAAO;EAAK;CACtG,CAAC;CACF,OAAO;EACN;EACA,WAAW,EAAyB,GAAU,EAAM,QAAQ,EAAM,KAAK;EACvE,OAAO,EAAM;EACb,SAAS,EAAM,QAAQ;EACvB,SAAS,EAAM,QAAQ,EAAM,UAAU,SAAS;EAChD,iBAAiB,EAAM;EACvB,eAAe,EAAM,UAAU;EAC/B,OAAO,EAAM;EACb;EACA;EACA,YAAY,EAAO,EAAE;EACrB,YAAY,EAAO,CAAC;EACpB,UAAU,MAAY;GACrB,IAAI;IACH,EAAO,EAAQ,CAAQ,CAAC;GACzB,SAAS,GAAO;IAEf,GAAU,OAAa;KAAE,GAAG;KAAS,OAAO,aAAiB,QAAQ,EAAM,UAAU;IAA+B,EAAE;GACvH;EACD;CACD;AACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableEditorGrid.d.ts","sourceRoot":"","sources":["../../../src/table-editor/ui/TableEditorGrid.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAEN,KAAK,iBAAiB,EAEtB,MAAM,gDAAgD,CAAC;AAExD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKrE,KAAK,oBAAoB,CAAC,CAAC,IAAI;IAC9B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IAC/D,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;CAC7D,CAAC;AAEF,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC,+
|
|
1
|
+
{"version":3,"file":"TableEditorGrid.d.ts","sourceRoot":"","sources":["../../../src/table-editor/ui/TableEditorGrid.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAEN,KAAK,iBAAiB,EAEtB,MAAM,gDAAgD,CAAC;AAExD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKrE,KAAK,oBAAoB,CAAC,CAAC,IAAI;IAC9B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IAC/D,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;CAC7D,CAAC;AAEF,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC,+BAoHzH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/tag-input/lib/joinTagInputAriaIds.ts","../../src/tag-input/lib/tagInputDefaults.ts","../../src/tag-input/TagInput.module.scss","../../src/tag-input/TagInput.tsx"],"sourcesContent":["/** Объединяет сгенерированные и пользовательские ARIA ID, исключая пустые части. */\nexport function joinTagInputAriaIds(...ids: Array<string | undefined>) {\n\treturn ids.filter(Boolean).join(\" \") || undefined;\n}\n","/** Удаляет внешние пробелы перед сохранением созданного тега. */\nexport function defaultNormalizeTag(value: string) {\n\treturn value.trim();\n}\n\n/** Сохраняет регистр и использует точное значение как ключ сравнения по умолчанию. */\nexport function defaultGetTagKey(value: string) {\n\treturn value;\n}\n\n/** Формирует доступное имя действия удаления с конкретным значением тега. */\nexport function defaultGetRemoveButtonAriaLabel(value: string) {\n\treturn `Удалить тег «${value}»`;\n}\n","@use \"@/styles/mixins\" as *;\n\n.control {\n\tmin-height: var(--control-height);\n\tdisplay: flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tgap: var(--space-xs);\n\tpadding: calc(var(--space-xs) / 2) var(--space-sm);\n\tcursor: text;\n\n\t--ui-color: var(--content-0);\n\t--ui-color-hover: var(--content-0);\n\t--ui-color-active: var(--content-0);\n\n\t&[data-readonly] {\n\t\tcursor: default;\n\t\tbackground-color: var(--surface-1);\n\t}\n}\n\n.tagList {\n\tmin-width: 0;\n\tmax-width: 100%;\n\tdisplay: flex;\n\talign-items: center;\n\tflex: 0 1 auto;\n\tflex-wrap: wrap;\n\tgap: var(--space-xs);\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.tag {\n\t@include ui-static-surface;\n\n\t--ui-color: var(--content-0);\n\t--ui-background: var(--surface-2);\n\t--ui-border-color: var(--border-0);\n\n\tmin-width: 0;\n\tmax-width: 100%;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: var(--space-xs);\n\tpadding: calc(var(--space-xs) / 2) var(--space-xs);\n\tfont-size: var(--font-size-sm);\n}\n\n.tagText {\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.removeButton {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex-shrink: 0;\n\twidth: 1.25em;\n\theight: 1.25em;\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: var(--radius-xs);\n\tbackground: transparent;\n\tcolor: inherit;\n\ttransition:\n\t\tcolor var(--transition-fast) ease,\n\t\tbackground-color var(--transition-fast) ease;\n\n\t&:hover {\n\t\tbackground-color: color-mix(in srgb, var(--error-fill) 12%, var(--surface-0));\n\t\tcolor: var(--error-text);\n\t}\n\n\t&:focus-visible {\n\t\t@include focusVisible;\n\t}\n\n\tsvg {\n\t\tdisplay: block;\n\t}\n}\n\n.input {\n\tmin-width: 8ch;\n\tmin-height: calc(var(--control-height) - var(--space-xs) - (var(--border-width) * 2));\n\tflex: 1 1 8rem;\n\tpadding: 0;\n\tborder: none;\n\toutline: none;\n\tbackground: transparent;\n\tcolor: inherit;\n\tfont: inherit;\n\n\t&::placeholder {\n\t\tcolor: var(--content-2);\n\t}\n\n\t&:read-only {\n\t\tcursor: default;\n\t}\n}\n","import {\n\ttype ClipboardEvent,\n\ttype CompositionEvent,\n\ttype InputHTMLAttributes,\n\ttype KeyboardEvent,\n\ttype Ref,\n\tuseImperativeHandle,\n\tuseRef,\n\tuseState\n} from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { XIcon } from \"lucide-react\";\n\nimport { InputUI, useInputFieldIds } from \"../input\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport { joinTagInputAriaIds } from \"./lib/joinTagInputAriaIds\";\nimport { defaultGetRemoveButtonAriaLabel, defaultGetTagKey, defaultNormalizeTag } from \"./lib/tagInputDefaults\";\nimport styles from \"./TagInput.module.scss\";\n\nimport type { UiBaseProps } from \"../types\";\n\nconst TAG_DELIMITER_PATTERN = /[,\\r\\n]/;\nconst TAG_DELIMITER_SPLIT_PATTERN = /[,\\r\\n]+/;\n\nexport interface TagInputProps\n\textends\n\t\tOmit<InputHTMLAttributes<HTMLInputElement>, \"children\" | \"defaultValue\" | \"disabled\" | \"onChange\" | \"readOnly\" | \"size\" | \"value\">,\n\t\tUiBaseProps<string[], readonly string[]> {\n\t/** Ссылка на внутренний нативный `input`, передаваемая напрямую как React 19 prop. */\n\tref?: Ref<HTMLInputElement>;\n\n\t/** Сообщение валидации, связанное с полем через `aria-describedby`. */\n\terror?: string;\n\n\t/** Сбрасывает внешнюю ошибку после изменения черновика или набора тегов. */\n\tonClearError?: () => void;\n\n\t/** Запрещает изменение набора тегов, сохраняя возможность выделять и копировать текст. */\n\treadOnly?: boolean;\n\n\t/** Максимальное количество тегов. Отсутствие значения не ограничивает набор. */\n\tmaxTags?: number;\n\n\t/**\n\t * Нормализует введённое значение перед проверкой дубликата и добавлением.\n\t * По умолчанию удаляет пробелы в начале и конце.\n\t */\n\tnormalizeTag?: (value: string) => string;\n\n\t/**\n\t * Возвращает ключ сравнения тегов. Позволяет, например, запретить дубликаты без учёта регистра.\n\t * По умолчанию используется точное строковое сравнение.\n\t */\n\tgetTagKey?: (value: string) => string;\n\n\t/** Добавляет непустой черновик при уходе фокуса с input. По умолчанию включено. */\n\taddOnBlur?: boolean;\n\n\t/** Формирует доступное имя кнопки удаления конкретного тега. */\n\tgetRemoveButtonAriaLabel?: (value: string, index: number) => string;\n\n\t/** Доступное имя списка уже добавленных тегов. */\n\ttokensAriaLabel?: string;\n\n\t/** CSS-класс непосредственно для внутреннего `input`; `className` применяется к оболочке поля. */\n\tinputClassName?: string;\n}\n\n/**\n * Controlled-поле для создания коротких строковых тегов.\n *\n * Новое значение фиксируется по `Enter`, запятой, вставке списка или потере фокуса. Компонент хранит\n * только незавершённый текст input, а окончательный набор всегда принадлежит потребителю через `value`.\n */\nexport function TagInput({\n\tref,\n\tvalue,\n\tonChange,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\tsize,\n\tdisabled,\n\treadOnly = false,\n\terror,\n\tonClearError,\n\tmaxTags,\n\tnormalizeTag = defaultNormalizeTag,\n\tgetTagKey = defaultGetTagKey,\n\taddOnBlur = true,\n\tgetRemoveButtonAriaLabel = defaultGetRemoveButtonAriaLabel,\n\ttokensAriaLabel = \"Добавленные теги\",\n\tinputClassName,\n\tclassName,\n\tid: externalId,\n\tname,\n\tform,\n\trequired,\n\tmaxLength,\n\tonKeyDown,\n\tonPaste,\n\tonBlur,\n\tonCompositionStart,\n\tonCompositionEnd,\n\t\"aria-describedby\": externalAriaDescribedBy,\n\t\"aria-labelledby\": externalAriaLabelledBy,\n\t...inputProps\n}: TagInputProps) {\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst controlRef = useRef<HTMLDivElement>(null);\n\tconst isComposingRef = useRef(false);\n\tconst [draft, setDraft] = useState(\"\");\n\tconst [announcement, setAnnouncement] = useState(\"\");\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\tid: externalId,\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\tconst resolvedMaxTags = maxTags === undefined ? Number.POSITIVE_INFINITY : Math.max(0, Math.floor(maxTags));\n\tconst isEditingDisabled = disabled || readOnly;\n\tconst ariaDescribedBy = joinTagInputAriaIds(describedBy, externalAriaDescribedBy);\n\tconst ariaLabelledBy = joinTagInputAriaIds(labelId, externalAriaLabelledBy);\n\n\tuseImperativeHandle(ref, () => {\n\t\tconst input = inputRef.current;\n\n\t\tif (!input) {\n\t\t\tthrow new Error(\"TagInput: внутренний input недоступен при создании imperative handle.\");\n\t\t}\n\n\t\treturn input;\n\t}, []);\n\n\t/** Добавляет сразу несколько кандидатов одним controlled-обновлением и сообщает результат screen reader. */\n\tconst appendTags = (rawTags: readonly string[]) => {\n\t\tif (isEditingDisabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tonClearError?.();\n\n\t\tconst nextTags = [...value];\n\t\tconst knownKeys = new Set(nextTags.map((tag) => getTagKey(tag)));\n\t\tconst added: string[] = [];\n\t\tlet duplicateCount = 0;\n\t\tlet limitReached = false;\n\n\t\tfor (const rawTag of rawTags) {\n\t\t\tconst tag = normalizeTag(rawTag);\n\n\t\t\tif (!tag) continue;\n\n\t\t\tif (maxLength !== undefined && tag.length > maxLength) {\n\t\t\t\tsetAnnouncement(`Тег «${tag}» длиннее допустимого значения.`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst key = getTagKey(tag);\n\n\t\t\tif (knownKeys.has(key)) {\n\t\t\t\tduplicateCount += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (nextTags.length >= resolvedMaxTags) {\n\t\t\t\tlimitReached = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tknownKeys.add(key);\n\t\t\tnextTags.push(tag);\n\t\t\tadded.push(tag);\n\t\t}\n\n\t\tif (added.length > 0) {\n\t\t\tonChange(nextTags);\n\t\t\tsetAnnouncement(added.length === 1 ? `Добавлен тег «${added[0]}».` : `Добавлено тегов: ${added.length}.`);\n\t\t} else if (limitReached) {\n\t\t\tsetAnnouncement(`Достигнуто максимальное количество тегов: ${resolvedMaxTags}.`);\n\t\t} else if (duplicateCount > 0) {\n\t\t\tsetAnnouncement(\"Такой тег уже добавлен.\");\n\t\t}\n\t};\n\n\tconst commitDraft = () => {\n\t\tif (!draft) return false;\n\n\t\tappendTags(draft.split(TAG_DELIMITER_SPLIT_PATTERN));\n\t\tsetDraft(\"\");\n\t\treturn true;\n\t};\n\n\tconst removeTag = (index: number) => {\n\t\tif (isEditingDisabled) return;\n\n\t\tconst removedTag = value[index];\n\t\tif (removedTag === undefined) return;\n\n\t\tonChange(value.filter((_, currentIndex) => currentIndex !== index));\n\t\tonClearError?.();\n\t\tsetAnnouncement(`Удалён тег «${removedTag}».`);\n\t\tinputRef.current?.focus();\n\t};\n\n\tconst handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n\t\tonKeyDown?.(event);\n\t\tif (event.defaultPrevented || event.nativeEvent.isComposing || isComposingRef.current || isEditingDisabled) return;\n\n\t\tif (event.key === \"Enter\" || event.key === \",\") {\n\t\t\tif (commitDraft() || event.key === \",\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Backspace\" && draft.length === 0 && value.length > 0) {\n\t\t\tevent.preventDefault();\n\t\t\tremoveTag(value.length - 1);\n\t\t}\n\t};\n\n\tconst handlePaste = (event: ClipboardEvent<HTMLInputElement>) => {\n\t\tonPaste?.(event);\n\t\tif (event.defaultPrevented || isEditingDisabled) return;\n\n\t\tconst clipboardText = event.clipboardData.getData(\"text\");\n\t\tif (!TAG_DELIMITER_PATTERN.test(clipboardText)) return;\n\n\t\tevent.preventDefault();\n\t\tconst selectionStart = event.currentTarget.selectionStart ?? draft.length;\n\t\tconst selectionEnd = event.currentTarget.selectionEnd ?? selectionStart;\n\t\tconst pastedValue = `${draft.slice(0, selectionStart)}${clipboardText}${draft.slice(selectionEnd)}`;\n\n\t\tappendTags(pastedValue.split(TAG_DELIMITER_SPLIT_PATTERN));\n\t\tsetDraft(\"\");\n\t};\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<div\n\t\t\t\tref={controlRef}\n\t\t\t\tclassName={cn(uiStyles.uiControl, error && uiStyles.invalid, styles.control)}\n\t\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\t\tdata-readonly={readOnly ? \"\" : undefined}\n\t\t\t\tdata-invalid={error ? \"\" : undefined}\n\t\t\t\tonClick={() => inputRef.current?.focus()}>\n\t\t\t\t{value.length > 0 && (\n\t\t\t\t\t<ul className={styles.tagList} aria-label={tokensAriaLabel}>\n\t\t\t\t\t\t{value.map((tag, index) => (\n\t\t\t\t\t\t\t<li className={styles.tag} key={`${getTagKey(tag)}-${index}`}>\n\t\t\t\t\t\t\t\t<span className={styles.tagText}>{tag}</span>\n\t\t\t\t\t\t\t\t{!isEditingDisabled && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName={styles.removeButton}\n\t\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\tremoveTag(index);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\taria-label={getRemoveButtonAriaLabel(tag, index)}>\n\t\t\t\t\t\t\t\t\t\t<XIcon aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t)}\n\n\t\t\t\t<input\n\t\t\t\t\t{...inputProps}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tid={controlId}\n\t\t\t\t\tform={form}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\trequired={required && value.length === 0}\n\t\t\t\t\tmaxLength={maxLength}\n\t\t\t\t\tvalue={draft}\n\t\t\t\t\tplaceholder={value.length === 0 ? placeholder : undefined}\n\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\taria-labelledby={ariaLabelledBy}\n\t\t\t\t\taria-describedby={ariaDescribedBy}\n\t\t\t\t\tclassName={cn(styles.input, inputClassName)}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tconst nextDraft = event.target.value;\n\t\t\t\t\t\tconst hasDelimiter = TAG_DELIMITER_PATTERN.test(nextDraft);\n\n\t\t\t\t\t\tif (isComposingRef.current) {\n\t\t\t\t\t\t\tsetDraft(nextDraft);\n\t\t\t\t\t\t} else if (hasDelimiter) {\n\t\t\t\t\t\t\tconst parts = nextDraft.split(TAG_DELIMITER_SPLIT_PATTERN);\n\t\t\t\t\t\t\tconst hasTrailingDelimiter = TAG_DELIMITER_PATTERN.test(nextDraft.at(-1) ?? \"\");\n\t\t\t\t\t\t\tconst uncommittedPart = hasTrailingDelimiter ? \"\" : (parts.pop() ?? \"\");\n\n\t\t\t\t\t\t\tappendTags(parts);\n\t\t\t\t\t\t\tsetDraft(uncommittedPart);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsetDraft(nextDraft);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (isComposingRef.current || !hasDelimiter) {\n\t\t\t\t\t\t\tonClearError?.();\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\tonPaste={handlePaste}\n\t\t\t\t\tonCompositionStart={(event: CompositionEvent<HTMLInputElement>) => {\n\t\t\t\t\t\tisComposingRef.current = true;\n\t\t\t\t\t\tonCompositionStart?.(event);\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionEnd={(event: CompositionEvent<HTMLInputElement>) => {\n\t\t\t\t\t\tisComposingRef.current = false;\n\t\t\t\t\t\tonCompositionEnd?.(event);\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={(event) => {\n\t\t\t\t\t\tonBlur?.(event);\n\t\t\t\t\t\tconst nextFocusedNode = event.relatedTarget;\n\t\t\t\t\t\tconst focusRemainsInside = nextFocusedNode instanceof Node && controlRef.current?.contains(nextFocusedNode);\n\n\t\t\t\t\t\tif (!event.defaultPrevented && !focusRemainsInside && addOnBlur && !isEditingDisabled) {\n\t\t\t\t\t\t\tcommitDraft();\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\n\t\t\t\t{name &&\n\t\t\t\t\tvalue.map((tag, index) => (\n\t\t\t\t\t\t<input key={`${getTagKey(tag)}-${index}`} type=\"hidden\" name={name} value={tag} form={form} disabled={disabled} />\n\t\t\t\t\t))}\n\t\t\t</div>\n\n\t\t\t<span className=\"visuallyHidden\" aria-live=\"polite\" aria-atomic=\"true\">\n\t\t\t\t{announcement}\n\t\t\t</span>\n\t\t</InputUI>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/tag-input/lib/joinTagInputAriaIds.ts","../../src/tag-input/lib/tagInputDefaults.ts","../../src/tag-input/TagInput.module.scss","../../src/tag-input/TagInput.tsx"],"sourcesContent":["/** Объединяет сгенерированные и пользовательские ARIA ID, исключая пустые части. */\nexport function joinTagInputAriaIds(...ids: Array<string | undefined>) {\n\treturn ids.filter(Boolean).join(\" \") || undefined;\n}\n","/** Удаляет внешние пробелы перед сохранением созданного тега. */\nexport function defaultNormalizeTag(value: string) {\n\treturn value.trim();\n}\n\n/** Сохраняет регистр и использует точное значение как ключ сравнения по умолчанию. */\nexport function defaultGetTagKey(value: string) {\n\treturn value;\n}\n\n/** Формирует доступное имя действия удаления с конкретным значением тега. */\nexport function defaultGetRemoveButtonAriaLabel(value: string) {\n\treturn `Удалить тег «${value}»`;\n}\n","@use \"@/styles/mixins\" as *;\n@use \"@/styles/tone-derived\" as toneDerived;\n\n.control {\n\tmin-height: var(--control-height);\n\tdisplay: flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tgap: var(--space-xs);\n\tpadding: calc(var(--space-xs) / 2) var(--space-sm);\n\tcursor: text;\n\n\t--ui-color: var(--content-0);\n\t--ui-color-hover: var(--content-0);\n\t--ui-color-active: var(--content-0);\n\n\t&[data-readonly] {\n\t\tcursor: default;\n\t\tbackground-color: var(--surface-1);\n\t}\n}\n\n.tagList {\n\tmin-width: 0;\n\tmax-width: 100%;\n\tdisplay: flex;\n\talign-items: center;\n\tflex: 0 1 auto;\n\tflex-wrap: wrap;\n\tgap: var(--space-xs);\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.tag {\n\t@include ui-static-surface;\n\n\t--ui-color: var(--content-0);\n\t--ui-background: var(--surface-2);\n\t--ui-border-color: var(--border-0);\n\n\tmin-width: 0;\n\tmax-width: 100%;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: var(--space-xs);\n\tpadding: calc(var(--space-xs) / 2) var(--space-xs);\n\tfont-size: var(--font-size-sm);\n}\n\n.tagText {\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.removeButton {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex-shrink: 0;\n\twidth: 1.25em;\n\theight: 1.25em;\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: var(--radius-xs);\n\tbackground: transparent;\n\tcolor: inherit;\n\ttransition:\n\t\tcolor var(--transition-fast) ease,\n\t\tbackground-color var(--transition-fast) ease;\n\n\t&:hover {\n\t\t@include toneDerived.tone-soft-declaration(\"background-color\", \"error\");\n\t\tcolor: var(--error-text);\n\t}\n\n\t&:focus-visible {\n\t\t@include focusVisible;\n\t}\n\n\tsvg {\n\t\tdisplay: block;\n\t}\n}\n\n.input {\n\tmin-width: 8ch;\n\tmin-height: calc(var(--control-height) - var(--space-xs) - (var(--border-width) * 2));\n\tflex: 1 1 8rem;\n\tpadding: 0;\n\tborder: none;\n\toutline: none;\n\tbackground: transparent;\n\tcolor: inherit;\n\tfont: inherit;\n\n\t&::placeholder {\n\t\tcolor: var(--content-2);\n\t}\n\n\t&:read-only {\n\t\tcursor: default;\n\t}\n}\n","import {\n\ttype ClipboardEvent,\n\ttype CompositionEvent,\n\ttype InputHTMLAttributes,\n\ttype KeyboardEvent,\n\ttype Ref,\n\tuseImperativeHandle,\n\tuseRef,\n\tuseState\n} from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { XIcon } from \"lucide-react\";\n\nimport { InputUI, useInputFieldIds } from \"../input\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport { joinTagInputAriaIds } from \"./lib/joinTagInputAriaIds\";\nimport { defaultGetRemoveButtonAriaLabel, defaultGetTagKey, defaultNormalizeTag } from \"./lib/tagInputDefaults\";\nimport styles from \"./TagInput.module.scss\";\n\nimport type { UiBaseProps } from \"../types\";\n\nconst TAG_DELIMITER_PATTERN = /[,\\r\\n]/;\nconst TAG_DELIMITER_SPLIT_PATTERN = /[,\\r\\n]+/;\n\nexport interface TagInputProps\n\textends\n\t\tOmit<InputHTMLAttributes<HTMLInputElement>, \"children\" | \"defaultValue\" | \"disabled\" | \"onChange\" | \"readOnly\" | \"size\" | \"value\">,\n\t\tUiBaseProps<string[], readonly string[]> {\n\t/** Ссылка на внутренний нативный `input`, передаваемая напрямую как React 19 prop. */\n\tref?: Ref<HTMLInputElement>;\n\n\t/** Сообщение валидации, связанное с полем через `aria-describedby`. */\n\terror?: string;\n\n\t/** Сбрасывает внешнюю ошибку после изменения черновика или набора тегов. */\n\tonClearError?: () => void;\n\n\t/** Запрещает изменение набора тегов, сохраняя возможность выделять и копировать текст. */\n\treadOnly?: boolean;\n\n\t/** Максимальное количество тегов. Отсутствие значения не ограничивает набор. */\n\tmaxTags?: number;\n\n\t/**\n\t * Нормализует введённое значение перед проверкой дубликата и добавлением.\n\t * По умолчанию удаляет пробелы в начале и конце.\n\t */\n\tnormalizeTag?: (value: string) => string;\n\n\t/**\n\t * Возвращает ключ сравнения тегов. Позволяет, например, запретить дубликаты без учёта регистра.\n\t * По умолчанию используется точное строковое сравнение.\n\t */\n\tgetTagKey?: (value: string) => string;\n\n\t/** Добавляет непустой черновик при уходе фокуса с input. По умолчанию включено. */\n\taddOnBlur?: boolean;\n\n\t/** Формирует доступное имя кнопки удаления конкретного тега. */\n\tgetRemoveButtonAriaLabel?: (value: string, index: number) => string;\n\n\t/** Доступное имя списка уже добавленных тегов. */\n\ttokensAriaLabel?: string;\n\n\t/** CSS-класс непосредственно для внутреннего `input`; `className` применяется к оболочке поля. */\n\tinputClassName?: string;\n}\n\n/**\n * Controlled-поле для создания коротких строковых тегов.\n *\n * Новое значение фиксируется по `Enter`, запятой, вставке списка или потере фокуса. Компонент хранит\n * только незавершённый текст input, а окончательный набор всегда принадлежит потребителю через `value`.\n */\nexport function TagInput({\n\tref,\n\tvalue,\n\tonChange,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\tsize,\n\tdisabled,\n\treadOnly = false,\n\terror,\n\tonClearError,\n\tmaxTags,\n\tnormalizeTag = defaultNormalizeTag,\n\tgetTagKey = defaultGetTagKey,\n\taddOnBlur = true,\n\tgetRemoveButtonAriaLabel = defaultGetRemoveButtonAriaLabel,\n\ttokensAriaLabel = \"Добавленные теги\",\n\tinputClassName,\n\tclassName,\n\tid: externalId,\n\tname,\n\tform,\n\trequired,\n\tmaxLength,\n\tonKeyDown,\n\tonPaste,\n\tonBlur,\n\tonCompositionStart,\n\tonCompositionEnd,\n\t\"aria-describedby\": externalAriaDescribedBy,\n\t\"aria-labelledby\": externalAriaLabelledBy,\n\t...inputProps\n}: TagInputProps) {\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst controlRef = useRef<HTMLDivElement>(null);\n\tconst isComposingRef = useRef(false);\n\tconst [draft, setDraft] = useState(\"\");\n\tconst [announcement, setAnnouncement] = useState(\"\");\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\tid: externalId,\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\tconst resolvedMaxTags = maxTags === undefined ? Number.POSITIVE_INFINITY : Math.max(0, Math.floor(maxTags));\n\tconst isEditingDisabled = disabled || readOnly;\n\tconst ariaDescribedBy = joinTagInputAriaIds(describedBy, externalAriaDescribedBy);\n\tconst ariaLabelledBy = joinTagInputAriaIds(labelId, externalAriaLabelledBy);\n\n\tuseImperativeHandle(ref, () => {\n\t\tconst input = inputRef.current;\n\n\t\tif (!input) {\n\t\t\tthrow new Error(\"TagInput: внутренний input недоступен при создании imperative handle.\");\n\t\t}\n\n\t\treturn input;\n\t}, []);\n\n\t/** Добавляет сразу несколько кандидатов одним controlled-обновлением и сообщает результат screen reader. */\n\tconst appendTags = (rawTags: readonly string[]) => {\n\t\tif (isEditingDisabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tonClearError?.();\n\n\t\tconst nextTags = [...value];\n\t\tconst knownKeys = new Set(nextTags.map((tag) => getTagKey(tag)));\n\t\tconst added: string[] = [];\n\t\tlet duplicateCount = 0;\n\t\tlet limitReached = false;\n\n\t\tfor (const rawTag of rawTags) {\n\t\t\tconst tag = normalizeTag(rawTag);\n\n\t\t\tif (!tag) continue;\n\n\t\t\tif (maxLength !== undefined && tag.length > maxLength) {\n\t\t\t\tsetAnnouncement(`Тег «${tag}» длиннее допустимого значения.`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst key = getTagKey(tag);\n\n\t\t\tif (knownKeys.has(key)) {\n\t\t\t\tduplicateCount += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (nextTags.length >= resolvedMaxTags) {\n\t\t\t\tlimitReached = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tknownKeys.add(key);\n\t\t\tnextTags.push(tag);\n\t\t\tadded.push(tag);\n\t\t}\n\n\t\tif (added.length > 0) {\n\t\t\tonChange(nextTags);\n\t\t\tsetAnnouncement(added.length === 1 ? `Добавлен тег «${added[0]}».` : `Добавлено тегов: ${added.length}.`);\n\t\t} else if (limitReached) {\n\t\t\tsetAnnouncement(`Достигнуто максимальное количество тегов: ${resolvedMaxTags}.`);\n\t\t} else if (duplicateCount > 0) {\n\t\t\tsetAnnouncement(\"Такой тег уже добавлен.\");\n\t\t}\n\t};\n\n\tconst commitDraft = () => {\n\t\tif (!draft) return false;\n\n\t\tappendTags(draft.split(TAG_DELIMITER_SPLIT_PATTERN));\n\t\tsetDraft(\"\");\n\t\treturn true;\n\t};\n\n\tconst removeTag = (index: number) => {\n\t\tif (isEditingDisabled) return;\n\n\t\tconst removedTag = value[index];\n\t\tif (removedTag === undefined) return;\n\n\t\tonChange(value.filter((_, currentIndex) => currentIndex !== index));\n\t\tonClearError?.();\n\t\tsetAnnouncement(`Удалён тег «${removedTag}».`);\n\t\tinputRef.current?.focus();\n\t};\n\n\tconst handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n\t\tonKeyDown?.(event);\n\t\tif (event.defaultPrevented || event.nativeEvent.isComposing || isComposingRef.current || isEditingDisabled) return;\n\n\t\tif (event.key === \"Enter\" || event.key === \",\") {\n\t\t\tif (commitDraft() || event.key === \",\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Backspace\" && draft.length === 0 && value.length > 0) {\n\t\t\tevent.preventDefault();\n\t\t\tremoveTag(value.length - 1);\n\t\t}\n\t};\n\n\tconst handlePaste = (event: ClipboardEvent<HTMLInputElement>) => {\n\t\tonPaste?.(event);\n\t\tif (event.defaultPrevented || isEditingDisabled) return;\n\n\t\tconst clipboardText = event.clipboardData.getData(\"text\");\n\t\tif (!TAG_DELIMITER_PATTERN.test(clipboardText)) return;\n\n\t\tevent.preventDefault();\n\t\tconst selectionStart = event.currentTarget.selectionStart ?? draft.length;\n\t\tconst selectionEnd = event.currentTarget.selectionEnd ?? selectionStart;\n\t\tconst pastedValue = `${draft.slice(0, selectionStart)}${clipboardText}${draft.slice(selectionEnd)}`;\n\n\t\tappendTags(pastedValue.split(TAG_DELIMITER_SPLIT_PATTERN));\n\t\tsetDraft(\"\");\n\t};\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<div\n\t\t\t\tref={controlRef}\n\t\t\t\tclassName={cn(uiStyles.uiControl, error && uiStyles.invalid, styles.control)}\n\t\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\t\tdata-readonly={readOnly ? \"\" : undefined}\n\t\t\t\tdata-invalid={error ? \"\" : undefined}\n\t\t\t\tonClick={() => inputRef.current?.focus()}>\n\t\t\t\t{value.length > 0 && (\n\t\t\t\t\t<ul className={styles.tagList} aria-label={tokensAriaLabel}>\n\t\t\t\t\t\t{value.map((tag, index) => (\n\t\t\t\t\t\t\t<li className={styles.tag} key={`${getTagKey(tag)}-${index}`}>\n\t\t\t\t\t\t\t\t<span className={styles.tagText}>{tag}</span>\n\t\t\t\t\t\t\t\t{!isEditingDisabled && (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName={styles.removeButton}\n\t\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\tremoveTag(index);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\taria-label={getRemoveButtonAriaLabel(tag, index)}>\n\t\t\t\t\t\t\t\t\t\t<XIcon aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t)}\n\n\t\t\t\t<input\n\t\t\t\t\t{...inputProps}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tid={controlId}\n\t\t\t\t\tform={form}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\trequired={required && value.length === 0}\n\t\t\t\t\tmaxLength={maxLength}\n\t\t\t\t\tvalue={draft}\n\t\t\t\t\tplaceholder={value.length === 0 ? placeholder : undefined}\n\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\taria-labelledby={ariaLabelledBy}\n\t\t\t\t\taria-describedby={ariaDescribedBy}\n\t\t\t\t\tclassName={cn(styles.input, inputClassName)}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tconst nextDraft = event.target.value;\n\t\t\t\t\t\tconst hasDelimiter = TAG_DELIMITER_PATTERN.test(nextDraft);\n\n\t\t\t\t\t\tif (isComposingRef.current) {\n\t\t\t\t\t\t\tsetDraft(nextDraft);\n\t\t\t\t\t\t} else if (hasDelimiter) {\n\t\t\t\t\t\t\tconst parts = nextDraft.split(TAG_DELIMITER_SPLIT_PATTERN);\n\t\t\t\t\t\t\tconst hasTrailingDelimiter = TAG_DELIMITER_PATTERN.test(nextDraft.at(-1) ?? \"\");\n\t\t\t\t\t\t\tconst uncommittedPart = hasTrailingDelimiter ? \"\" : (parts.pop() ?? \"\");\n\n\t\t\t\t\t\t\tappendTags(parts);\n\t\t\t\t\t\t\tsetDraft(uncommittedPart);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsetDraft(nextDraft);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (isComposingRef.current || !hasDelimiter) {\n\t\t\t\t\t\t\tonClearError?.();\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\tonPaste={handlePaste}\n\t\t\t\t\tonCompositionStart={(event: CompositionEvent<HTMLInputElement>) => {\n\t\t\t\t\t\tisComposingRef.current = true;\n\t\t\t\t\t\tonCompositionStart?.(event);\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionEnd={(event: CompositionEvent<HTMLInputElement>) => {\n\t\t\t\t\t\tisComposingRef.current = false;\n\t\t\t\t\t\tonCompositionEnd?.(event);\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={(event) => {\n\t\t\t\t\t\tonBlur?.(event);\n\t\t\t\t\t\tconst nextFocusedNode = event.relatedTarget;\n\t\t\t\t\t\tconst focusRemainsInside = nextFocusedNode instanceof Node && controlRef.current?.contains(nextFocusedNode);\n\n\t\t\t\t\t\tif (!event.defaultPrevented && !focusRemainsInside && addOnBlur && !isEditingDisabled) {\n\t\t\t\t\t\t\tcommitDraft();\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\n\t\t\t\t{name &&\n\t\t\t\t\tvalue.map((tag, index) => (\n\t\t\t\t\t\t<input key={`${getTagKey(tag)}-${index}`} type=\"hidden\" name={name} value={tag} form={form} disabled={disabled} />\n\t\t\t\t\t))}\n\t\t\t</div>\n\n\t\t\t<span className=\"visuallyHidden\" aria-live=\"polite\" aria-atomic=\"true\">\n\t\t\t\t{announcement}\n\t\t\t</span>\n\t\t</InputUI>\n\t);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// Выводит мягкую заливку как указанное свойство в текущем CSS-контексте.
|
|
2
|
+
/// Это сохраняет реакцию значения на локальные overrides базовой роли и поверхности.
|
|
3
|
+
@mixin tone-soft-declaration($property, $source) {
|
|
4
|
+
#{$property}: color-mix(in srgb, var(--#{$source}-fill) 12%, var(--surface-0));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/// Выводит единые производные состояния tone-схемы.
|
|
8
|
+
/// Раздельные target и source позволяют использовать те же формулы как для
|
|
9
|
+
/// глобальных токенов темы, так и для локальных переменных UI-компонента.
|
|
10
|
+
@mixin derived-tone-declarations($target, $source) {
|
|
11
|
+
--#{$target}-text-hover: color-mix(in srgb, var(--#{$source}-text) 88%, var(--content-0));
|
|
12
|
+
--#{$target}-text-active: color-mix(in srgb, var(--#{$source}-text) 76%, var(--content-0));
|
|
13
|
+
--#{$target}-border-hover: color-mix(in srgb, var(--#{$source}-border) 88%, var(--content-0));
|
|
14
|
+
--#{$target}-border-active: color-mix(in srgb, var(--#{$source}-border) 76%, var(--content-0));
|
|
15
|
+
--#{$target}-fill-hover: color-mix(in srgb, var(--#{$source}-fill) 88%, var(--content-0));
|
|
16
|
+
--#{$target}-fill-active: color-mix(in srgb, var(--#{$source}-fill) 76%, var(--content-0));
|
|
17
|
+
@include tone-soft-declaration("--#{$target}-soft", $source);
|
|
18
|
+
}
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
@use "./mixin" as *;
|
|
2
|
+
@use "../tone-derived" as toneDerived;
|
|
2
3
|
|
|
3
4
|
@mixin ui-tone($tone) {
|
|
4
5
|
--ui-tone-text: var(--#{$tone}-text);
|
|
5
|
-
--ui-tone-text-hover: color-mix(in srgb, var(--#{$tone}-text) 88%, var(--content-0));
|
|
6
|
-
--ui-tone-text-active: color-mix(in srgb, var(--#{$tone}-text) 76%, var(--content-0));
|
|
7
6
|
--ui-tone-fill: var(--#{$tone}-fill);
|
|
8
|
-
--ui-tone-fill-hover: color-mix(in srgb, var(--#{$tone}-fill) 88%, var(--content-0));
|
|
9
|
-
--ui-tone-fill-active: color-mix(in srgb, var(--#{$tone}-fill) 76%, var(--content-0));
|
|
10
7
|
--ui-tone-on-fill: var(--#{$tone}-on-fill);
|
|
11
|
-
--ui-tone-soft: color-mix(in srgb, var(--#{$tone}-fill) 12%, var(--surface-0));
|
|
12
8
|
--ui-tone-border: var(--#{$tone}-border);
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
// Локальный вывод сохраняет реакцию компонента на subtree overrides базовых ролей.
|
|
10
|
+
@include toneDerived.derived-tone-declarations("ui-tone", $tone);
|
|
15
11
|
--ui-tone-border-focus: var(--focus-ring);
|
|
16
12
|
--ui-tone-ghost-hover: color-mix(in srgb, var(--#{$tone}-fill) 10%, var(--surface-0));
|
|
17
13
|
--ui-tone-ghost-active: color-mix(in srgb, var(--#{$tone}-fill) 20%, var(--surface-0));
|
|
@@ -32,6 +32,31 @@ function compileUiAppearances(): string {
|
|
|
32
32
|
).css;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/** Компилирует только tone-adapter, чтобы закрепить его связь с токенами темы. */
|
|
36
|
+
function compileUiTone(): string {
|
|
37
|
+
return compileString('@use "controls" as *; .tone { @include ui-tone("brand"); }', {
|
|
38
|
+
loadPaths: [resolve("src/styles/mixins")],
|
|
39
|
+
style: "expanded"
|
|
40
|
+
}).css;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe("ui-tone", () => {
|
|
44
|
+
it("использует единые формулы локально для поддержки subtree overrides", () => {
|
|
45
|
+
const css = compileUiTone();
|
|
46
|
+
|
|
47
|
+
expect(css).toContain("--ui-tone-text-hover: color-mix(in srgb, var(--brand-text) 88%, var(--content-0))");
|
|
48
|
+
expect(css).toContain("--ui-tone-text-active: color-mix(in srgb, var(--brand-text) 76%, var(--content-0))");
|
|
49
|
+
expect(css).toContain("--ui-tone-fill-hover: color-mix(in srgb, var(--brand-fill) 88%, var(--content-0))");
|
|
50
|
+
expect(css).toContain("--ui-tone-fill-active: color-mix(in srgb, var(--brand-fill) 76%, var(--content-0))");
|
|
51
|
+
expect(css).toContain("--ui-tone-soft: color-mix(in srgb, var(--brand-fill) 12%, var(--surface-0))");
|
|
52
|
+
expect(css).toContain("--ui-tone-border-hover: color-mix(in srgb, var(--brand-border) 88%, var(--content-0))");
|
|
53
|
+
expect(css).toContain("--ui-tone-border-active: color-mix(in srgb, var(--brand-border) 76%, var(--content-0))");
|
|
54
|
+
expect(css).toContain("--ui-tone-border-focus: var(--focus-ring)");
|
|
55
|
+
expect(css).toContain("--ui-tone-ghost-hover: color-mix(in srgb, var(--brand-fill) 10%, var(--surface-0))");
|
|
56
|
+
expect(css).toContain("--ui-tone-ghost-active: color-mix(in srgb, var(--brand-fill) 20%, var(--surface-0))");
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
35
60
|
describe("ui-control-base", () => {
|
|
36
61
|
it("ограничивает hover устройствами с поддержкой наведения", () => {
|
|
37
62
|
const css = compileUiControlBase();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
@use "sass:map";
|
|
2
2
|
|
|
3
3
|
@use "../config" as stylesConfig;
|
|
4
|
+
@use "../tone-derived" as toneDerived;
|
|
4
5
|
|
|
5
6
|
@function _theme-base($mode) {
|
|
6
7
|
@if $mode == light {
|
|
@@ -14,9 +15,7 @@
|
|
|
14
15
|
@error "Цветовая схема темы должна иметь значение light или dark, получено: #{$mode}.";
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
/// Выводит четыре
|
|
18
|
-
/// Состояния hover/active и мягкая заливка вычисляются внутри UI-компонентов,
|
|
19
|
-
/// поэтому host настраивает только устойчивый минимальный контракт.
|
|
18
|
+
/// Выводит четыре настраиваемые роли цветовой схемы.
|
|
20
19
|
@mixin _status-palette($name, $status) {
|
|
21
20
|
--#{$name}-text: var(--hc-#{$name}-text, #{map.get($status, text)});
|
|
22
21
|
--#{$name}-border: var(--hc-#{$name}-border, #{map.get($status, border)});
|
|
@@ -24,6 +23,13 @@
|
|
|
24
23
|
--#{$name}-on-fill: var(--hc-#{$name}-on-fill, #{map.get($status, on-fill)});
|
|
25
24
|
}
|
|
26
25
|
|
|
26
|
+
/// Выводит переиспользуемые состояния из уже разрешённых базовых ролей.
|
|
27
|
+
/// Host не настраивает эти токены через карту status: их единые формулы автоматически
|
|
28
|
+
/// учитывают обычные, переопределённые и high-contrast значения базовой схемы.
|
|
29
|
+
@mixin _status-derived-palette($name) {
|
|
30
|
+
@include toneDerived.derived-tone-declarations($name, $name);
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
@mixin _theme-palette($theme) {
|
|
28
34
|
@each $name, $status in map.get($theme, status) {
|
|
29
35
|
@include _status-palette($name, $status);
|
|
@@ -36,13 +42,21 @@
|
|
|
36
42
|
--border-focus: var(--hc-border-focus, var(--focus-ring));
|
|
37
43
|
}
|
|
38
44
|
|
|
45
|
+
@mixin _theme-derived-palettes($theme) {
|
|
46
|
+
@each $name in map.keys(map.get($theme, status)) {
|
|
47
|
+
@include _status-derived-palette($name);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
/// Формирует полную тему из baseline выбранной схемы и точечных переопределений.
|
|
40
52
|
/// Карта `status` содержит `accent`, `brand`, `neutral`, `error`, `warning`,
|
|
41
|
-
/// `success` и `info`; у каждой схемы ровно четыре роли: `text`,
|
|
42
|
-
/// `fill` и `on-fill`.
|
|
53
|
+
/// `success` и `info`; у каждой схемы ровно четыре настраиваемые роли: `text`,
|
|
54
|
+
/// `border`, `fill` и `on-fill`. Производные состояния выводятся из базовых
|
|
55
|
+
/// переменных, а карта `tokens` остаётся последним escape hatch темы.
|
|
43
56
|
@mixin theme($mode, $overrides: ()) {
|
|
44
57
|
$resolved-theme: map.deep-merge(_theme-base($mode), $overrides);
|
|
45
58
|
|
|
46
59
|
@include _theme-palette($resolved-theme);
|
|
60
|
+
@include _theme-derived-palettes($resolved-theme);
|
|
47
61
|
@include stylesConfig.emit-declarations(stylesConfig.theme-tokens($resolved-theme));
|
|
48
62
|
}
|
|
@@ -12,7 +12,8 @@ function compileExactTheme(): string {
|
|
|
12
12
|
@include foundationThemes.theme(light, (
|
|
13
13
|
tokens: (
|
|
14
14
|
"--surface-0": #fefefe,
|
|
15
|
-
"--error-text": #990011
|
|
15
|
+
"--error-text": #990011,
|
|
16
|
+
"--error-soft": var(--surface-2)
|
|
16
17
|
),
|
|
17
18
|
status: (
|
|
18
19
|
accent: (
|
|
@@ -38,7 +39,7 @@ function compileExactTheme(): string {
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
describe("theme", () => {
|
|
41
|
-
it("наследует baseline и принимает четыре роли каждой hex-схемы", () => {
|
|
42
|
+
it("наследует baseline и принимает четыре настраиваемые роли каждой hex-схемы", () => {
|
|
42
43
|
const css = compileExactTheme();
|
|
43
44
|
const tones = ["accent", "brand", "neutral", "error", "warning", "success", "info"] as const;
|
|
44
45
|
const roles = ["text", "border", "fill", "on-fill"] as const;
|
|
@@ -63,6 +64,26 @@ describe("theme", () => {
|
|
|
63
64
|
expect(css).toContain("--shadow-xs: var(--hc-shadow-xs, 0 0 0.25em #00000026)");
|
|
64
65
|
});
|
|
65
66
|
|
|
67
|
+
it("выводит переиспользуемые производные состояния для каждой схемы", () => {
|
|
68
|
+
const css = compileExactTheme();
|
|
69
|
+
const tones = ["accent", "brand", "neutral", "error", "warning", "success", "info"] as const;
|
|
70
|
+
const derivedRoles = ["text-hover", "text-active", "border-hover", "border-active", "fill-hover", "fill-active", "soft"] as const;
|
|
71
|
+
|
|
72
|
+
for (const tone of tones) {
|
|
73
|
+
for (const role of derivedRoles) {
|
|
74
|
+
expect(css).toContain(`--${tone}-${role}:`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
expect(css).toContain(`--${tone}-text-hover: color-mix(in srgb, var(--${tone}-text) 88%, var(--content-0))`);
|
|
78
|
+
expect(css).toContain(`--${tone}-text-active: color-mix(in srgb, var(--${tone}-text) 76%, var(--content-0))`);
|
|
79
|
+
expect(css).toContain(`--${tone}-border-hover: color-mix(in srgb, var(--${tone}-border) 88%, var(--content-0))`);
|
|
80
|
+
expect(css).toContain(`--${tone}-border-active: color-mix(in srgb, var(--${tone}-border) 76%, var(--content-0))`);
|
|
81
|
+
expect(css).toContain(`--${tone}-fill-hover: color-mix(in srgb, var(--${tone}-fill) 88%, var(--content-0))`);
|
|
82
|
+
expect(css).toContain(`--${tone}-fill-active: color-mix(in srgb, var(--${tone}-fill) 76%, var(--content-0))`);
|
|
83
|
+
expect(css).toContain(`--${tone}-soft: color-mix(in srgb, var(--${tone}-fill) 12%, var(--surface-0))`);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
66
87
|
it("оборачивает первичные root-цвета одноимёнными high-contrast токенами", () => {
|
|
67
88
|
const css = compileString('@use "root-tokens";', {
|
|
68
89
|
loadPaths: [resolve("src/styles")],
|
|
@@ -73,13 +94,18 @@ describe("theme", () => {
|
|
|
73
94
|
expect(css).toContain("--black: var(--hc-black, #000000)");
|
|
74
95
|
});
|
|
75
96
|
|
|
76
|
-
it("выводит плоские token overrides
|
|
97
|
+
it("выводит плоские token overrides последним escape hatch темы", () => {
|
|
77
98
|
const css = compileExactTheme();
|
|
78
99
|
const paletteTextIndex = css.indexOf("--error-text: var(--hc-error-text, #aa0011)");
|
|
79
100
|
const exactTokenIndex = css.lastIndexOf("--error-text: var(--hc-error-text, #990011)");
|
|
101
|
+
const derivedTextIndex = css.indexOf("--error-text-hover: color-mix(in srgb, var(--error-text) 88%, var(--content-0))");
|
|
102
|
+
const generatedSoftIndex = css.indexOf("--error-soft: color-mix(in srgb, var(--error-fill) 12%, var(--surface-0))");
|
|
103
|
+
const exactSoftIndex = css.lastIndexOf("--error-soft: var(--surface-2)");
|
|
80
104
|
|
|
81
105
|
expect(paletteTextIndex).toBeGreaterThanOrEqual(0);
|
|
82
|
-
expect(
|
|
106
|
+
expect(derivedTextIndex).toBeGreaterThan(paletteTextIndex);
|
|
107
|
+
expect(exactTokenIndex).toBeGreaterThan(derivedTextIndex);
|
|
108
|
+
expect(exactSoftIndex).toBeGreaterThan(generatedSoftIndex);
|
|
83
109
|
expect(css).toContain("--surface-0: var(--hc-surface-0, #fefefe)");
|
|
84
110
|
});
|
|
85
111
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe-
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe-t8Ol-TlS.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{a as i,d as a,f as o,l as s,m as c,n as l,p as u,r as d,u as f}from"./blocks-OyR7mF18.js";import{a as p,i as m,n as h,o as g,r as _,s as v,t as y}from"./Badge.stories-DnU4Aj8m.js";function b(e){let t={code:`code`,h2:`h2`,h3:`h3`,li:`li`,p:`p`,pre:`pre`,ul:`ul`,...n(),...e.components};return(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(s,{of:h,parameters:{atomicCanvas:!0,layout:`padded`,docs:{toc:!0}}}),`
|
|
2
2
|
`,(0,S.jsx)(u,{children:`Badge`}),`
|
|
3
3
|
`,(0,S.jsx)(o,{children:`Компактная текстовая метка для статусов, категорий, фильтров и коротких служебных пометок`}),`
|
|
4
4
|
`,(0,S.jsx)(t.p,{children:`Badge подходит для коротких подписей, которые должны быстро читаться и не перегружать интерфейс:`}),`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e,r as t}from"./rolldown-runtime-DkW27tQK.js";import{t as n}from"./react-BZJXY1be.js";import{n as r}from"./iframe-
|
|
1
|
+
import{n as e,r as t}from"./rolldown-runtime-DkW27tQK.js";import{t as n}from"./react-BZJXY1be.js";import{n as r}from"./iframe-t8Ol-TlS.js";import{i,n as a,r as o,t as s}from"./BadgeList-BxlBVt--.js";var c=t({Appearances:()=>h,Basic:()=>p,RemovableList:()=>_,Sizes:()=>g,Tones:()=>m,__namedExportsOrder:()=>v,default:()=>f}),l,u,d,f,p,m,h,g,_,v;function y(){return(y=e((()=>{l=n(),i(),a(),u=r(),{useArgs:d}=__STORYBOOK_MODULE_PREVIEW_API__,f={title:`UI/Badge`,component:o,args:{children:`Новый`,size:`md`,tone:`info`,appearance:`solid`},parameters:{atomicCanvas:!0,layout:`padded`},argTypes:{children:{description:`Текст внутри бейджа.`,control:`text`},size:{description:`Размер бейджа.`,control:`inline-radio`,options:[`xs`,`sm`,`md`,`lg`,`xl`]},tone:{description:`Цветовой тон бейджа.`,control:`inline-radio`,options:[`neutral`,`accent`,`brand`,`success`,`warning`,`error`,`info`]},appearance:{description:`Форма бейджа.`,control:`inline-radio`,options:[`solid`,`outline`,`ghost`,`transparent`]},onRemove:{description:`Показывает кнопку удаления и вызывает обработчик по клику.`,control:!1}}},p={render:function(){let[e]=d();return(0,u.jsx)(o,{...e})}},m={render:()=>(0,u.jsxs)(s,{children:[(0,u.jsx)(o,{tone:`neutral`,appearance:`outline`,children:`Neutral`}),(0,u.jsx)(o,{tone:`accent`,appearance:`solid`,children:`Акцент`}),(0,u.jsx)(o,{tone:`brand`,appearance:`solid`,children:`Бренд`}),(0,u.jsx)(o,{tone:`success`,appearance:`solid`,children:`Успешно`}),(0,u.jsx)(o,{tone:`warning`,appearance:`solid`,children:`Внимание`}),(0,u.jsx)(o,{tone:`error`,appearance:`solid`,children:`Ошибка`}),(0,u.jsx)(o,{tone:`info`,appearance:`solid`,children:`Информация`})]})},h={render:()=>(0,u.jsxs)(s,{children:[(0,u.jsx)(o,{tone:`neutral`,appearance:`solid`,children:`Solid`}),(0,u.jsx)(o,{tone:`neutral`,appearance:`outline`,children:`Outline`}),(0,u.jsx)(o,{tone:`info`,appearance:`ghost`,children:`Ghost`}),(0,u.jsx)(o,{tone:`warning`,appearance:`transparent`,children:`Transparent`})]})},g={render:()=>(0,u.jsxs)(s,{children:[(0,u.jsx)(o,{size:`xs`,children:`Extra Small`}),(0,u.jsx)(o,{size:`sm`,children:`Small`}),(0,u.jsx)(o,{size:`md`,children:`Medium`}),(0,u.jsx)(o,{size:`lg`,children:`Large`}),(0,u.jsx)(o,{size:`xl`,children:`Extra Large`})]})},_={render:()=>{let[e,t]=(0,l.useState)([`Фильтр A`,`Фильтр B`,`Фильтр C`]);return(0,u.jsx)(s,{children:e.map(e=>(0,u.jsx)(o,{tone:`info`,appearance:`outline`,onRemove:()=>t(t=>t.filter(t=>t!==e)),children:e},e))})}},p.parameters={...p.parameters,docs:{...p.parameters?.docs,source:{originalSource:`{
|
|
2
2
|
render: function Render() {
|
|
3
3
|
const [args] = useArgs<BadgeStoryArgs>();
|
|
4
4
|
return <Badge {...args} />;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{t}from"./react-BZJXY1be.js";import{n,t as r}from"./x-
|
|
1
|
+
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{t}from"./react-BZJXY1be.js";import{n,t as r}from"./x-Y6c20Jey.js";import{n as i}from"./iframe-t8Ol-TlS.js";import{a,i as o}from"./utils-tg3ibbzi.js";import{c as s,i as c}from"./array-D-_yMMUK-DnJ_b27D.js";import{n as l,t as u}from"./FloatingPopover-Bcol5irF.js";import{a as d,i as f,r as p,t as m}from"./uiClasses-BCk2WXc4.js";import{n as h,t as g}from"./FlexContainer-BWyPlTMB.js";function _({maxChar:e,placement:t=`left`,closeDelay:n=0,maxWidth:r,children:i,block:a,state:o,textWrap:c,textWrapProps:l}){let d=s(i);if(!d.length||e&&d.length<e)return(0,v.jsx)(`span`,{children:d});let f=c??`div`,p={style:{display:a?`block`:`inline-block`,width:e?`${e-3}ch`:`auto`},className:`textOverflow`},m={...l,...p,style:{...l?.style,...p.style},className:[l?.className,p.className].filter(Boolean).join(` `)};return(0,v.jsx)(u,{state:o,placement:t,openOnHover:!0,content:d,closeDelay:n,maxWidth:r,children:(0,v.jsx)(f,{...m,children:d})})}var v;function y(){return(y=e((()=>{c(),l(),v=i(),_.__docgenInfo={description:``,methods:[],displayName:`TextOverflow`,props:{children:{required:!0,tsType:{name:`string`},description:``},maxChar:{required:!1,tsType:{name:`number`},description:``},maxWidth:{required:!1,tsType:{name:`number`},description:`Максимальная ширина тултипа в em.`},placement:{required:!1,tsType:{name:`Placement`},description:``,defaultValue:{value:`"left"`,computed:!1}},closeDelay:{required:!1,tsType:{name:`number`},description:``,defaultValue:{value:`0`,computed:!1}},block:{required:!1,tsType:{name:`literal`,value:`true`},description:`Для работы text-overflow элемент обязан быть блочным или inline-block.
|
|
2
2
|
Если в качестве обёртки передается инлайновый компонент, то он будет
|
|
3
3
|
перезаписан через стили на display: block или inline-block в зависимости
|
|
4
4
|
от установки данного пропса.`},state:{required:!1,tsType:{name:`union`,raw:`"information" | "error" | "warning" | "success" | "negative"`,elements:[{name:`literal`,value:`"information"`},{name:`literal`,value:`"error"`},{name:`literal`,value:`"warning"`},{name:`literal`,value:`"success"`},{name:`literal`,value:`"negative"`}]},description:``},textWrap:{required:!1,tsType:{name:`T`},description:``},textWrapProps:{required:!1,tsType:{name:`Omit`,elements:[{name:`ComponentProps`,elements:[{name:`T`}],raw:`ComponentProps<T>`},{name:`literal`,value:`"children"`}],raw:`Omit<ComponentProps<T>, "children">`},description:``}}}})))()}var b,x,S,C,w,T,E,D,O,k;function A(){return(A=e((()=>{b=`qBtmnH`,x=`p-HsHY`,S=`u9tQAE`,C=`FRScRz`,w=`W13uQO`,T=`_3IRcM9`,E=`R3ybI7`,D=`DdWAaC`,O=`_5cXBQF`,k={badge:b,passive:x,sizeXs:S,sizeSm:C,sizeMd:w,sizeLg:T,sizeXl:E,content:D,removeButton:O}})))()}function j({children:e,size:t=`sm`,tone:n,appearance:i,className:o,onRemove:s}){let c=n??`neutral`,l=d({tone:n,appearance:i,fallbackTone:c,fallbackAppearance:c===`neutral`?`outline`:`solid`});return(0,M.jsxs)(`div`,{className:a(k.badge,N[t],p(l.tone),m(l.appearance),!s&&k.passive,o),children:[(0,M.jsx)(_,{maxChar:25,placement:`top`,block:!0,textWrapProps:{className:k.content},children:String(e)}),s&&(0,M.jsx)(`button`,{type:`button`,onClick:s,className:k.removeButton,"aria-label":`Удалить бейдж`,"data-ui":`badge-remove-button`,"data-action":`remove-badge`,children:(0,M.jsx)(r,{})})]})}var M,N;function P(){return(P=e((()=>{o(),n(),y(),f(),A(),M=i(),N={xs:k.sizeXs,sm:k.sizeSm,md:k.sizeMd,lg:k.sizeLg,xl:k.sizeXl},j.__docgenInfo={description:`Компактный индикатор для статусов, категорий и коротких служебных меток.`,methods:[],displayName:`Badge`,props:{children:{required:!0,tsType:{name:`union`,raw:`string | number`,elements:[{name:`string`},{name:`number`}]},description:``},size:{required:!1,tsType:{name:`union`,raw:`"xs" | "sm" | "md" | "lg" | "xl"`,elements:[{name:`literal`,value:`"xs"`},{name:`literal`,value:`"sm"`},{name:`literal`,value:`"md"`},{name:`literal`,value:`"lg"`},{name:`literal`,value:`"xl"`}]},description:``,defaultValue:{value:`"sm"`,computed:!1}},tone:{required:!1,tsType:{name:`union`,raw:`"accent" | "neutral" | "brand" | "error" | "warning" | "success" | "info"`,elements:[{name:`literal`,value:`"accent"`},{name:`literal`,value:`"neutral"`},{name:`literal`,value:`"brand"`},{name:`literal`,value:`"error"`},{name:`literal`,value:`"warning"`},{name:`literal`,value:`"success"`},{name:`literal`,value:`"info"`}]},description:``},appearance:{required:!1,tsType:{name:`union`,raw:`"solid" | "outline" | "ghost" | "transparent"`,elements:[{name:`literal`,value:`"solid"`},{name:`literal`,value:`"outline"`},{name:`literal`,value:`"ghost"`},{name:`literal`,value:`"transparent"`}]},description:``},className:{required:!1,tsType:{name:`string`},description:``},onRemove:{required:!1,tsType:{name:`signature`,type:`function`,raw:`() => void`,signature:{arguments:[],return:{name:`void`}}},description:``}}}})))()}function F({children:e}){return(0,L.jsx)(g,{inline:!0,wrap:!0,gap:`sm`,align:`baseline`,children:I.Children.map(e,(e,t)=>(0,L.jsx)(I.Fragment,{children:e},t))})}var I,L;function R(){return(R=e((()=>{I=t(),h(),L=i(),F.__docgenInfo={description:"Контейнер для группы `Badge`, который выстраивает элементы в единый список с предсказуемыми отступами. Используется для компактного вывода набора меток или фильтров.",methods:[],displayName:`BadgeList`,props:{children:{required:!0,tsType:{name:`Array`,elements:[{name:`ReactElement`,elements:[{name:`union`,raw:`typeof Badge | null | undefined | false`,elements:[{name:`Badge`},{name:`null`},{name:`undefined`},{name:`literal`,value:`false`}]}],raw:`ReactElement<typeof Badge | null | undefined | false>`}],raw:`ReactElement<typeof Badge | null | undefined | false>[]`},description:``}}}})))()}export{P as i,R as n,j as r,F as t};
|