@feugene/granularity 0.36.0 → 0.38.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/dist/chunks/config-2ZHRsdOc.js.map +1 -1
- package/dist/chunks/config-2vrOFn2f.js.map +1 -1
- package/dist/chunks/config-3bQeQvqd.js.map +1 -1
- package/dist/chunks/config-87fszqnD.js.map +1 -1
- package/dist/chunks/config-8Pcutu1j.js.map +1 -1
- package/dist/chunks/config-A-bBiotF.js.map +1 -1
- package/dist/chunks/config-B0uvcTPH.js.map +1 -1
- package/dist/chunks/config-B3J0alyY.js.map +1 -1
- package/dist/chunks/config-B5SBUa6u.js.map +1 -1
- package/dist/chunks/config-B7W9VlZ7.js.map +1 -1
- package/dist/chunks/config-BDSaD-5p.js.map +1 -1
- package/dist/chunks/config-BEO7brpO.js.map +1 -1
- package/dist/chunks/config-BNu8lFQB.js.map +1 -1
- package/dist/chunks/config-BRESvs9g.js.map +1 -1
- package/dist/chunks/config-BTmfQFwi.js.map +1 -1
- package/dist/chunks/{config-CuQmUkMw2.js → config-BUNxHnEz.js} +1 -1
- package/dist/chunks/config-BUNxHnEz.js.map +1 -0
- package/dist/chunks/config-BaWANzzB.js.map +1 -1
- package/dist/chunks/config-BcXX7S7B.js.map +1 -1
- package/dist/chunks/config-Bd7QfiGj.js.map +1 -1
- package/dist/chunks/config-BhfNgyWL.js.map +1 -1
- package/dist/chunks/config-Bjn30smH.js.map +1 -1
- package/dist/chunks/config-BlJa1Mj9.js.map +1 -1
- package/dist/chunks/config-BoUI0t-t.js.map +1 -1
- package/dist/chunks/config-BqT6PMzO.js.map +1 -1
- package/dist/chunks/config-BscVxZR3.js.map +1 -1
- package/dist/chunks/config-BuGlNPE9.js.map +1 -1
- package/dist/chunks/config-C0Ea9ePP.js.map +1 -1
- package/dist/chunks/config-C0Eu8jpG.js.map +1 -1
- package/dist/chunks/config-CDat1wXf.js.map +1 -1
- package/dist/chunks/config-CIkdsWUk.js.map +1 -1
- package/dist/chunks/config-CJzmDHfI.js.map +1 -1
- package/dist/chunks/config-CLjjjPZj.js.map +1 -1
- package/dist/chunks/config-CMNfZO7S.js.map +1 -1
- package/dist/chunks/config-CQLNjc9X.js.map +1 -0
- package/dist/chunks/config-CT4lP6S4.js.map +1 -1
- package/dist/chunks/config-CWtfxkM9.js.map +1 -1
- package/dist/chunks/config-CYthTVK2.js.map +1 -1
- package/dist/chunks/config-CZPDPJlg.js.map +1 -1
- package/dist/chunks/config-CbEbLyDE.js.map +1 -1
- package/dist/chunks/config-ChPg-BQv.js.map +1 -1
- package/dist/chunks/config-CjKpUcmy.js.map +1 -1
- package/dist/chunks/config-CjWOTgLL.js.map +1 -1
- package/dist/chunks/config-CjXjhphs.js.map +1 -1
- package/dist/chunks/config-CnYdE3HZ.js.map +1 -0
- package/dist/chunks/config-CsCUuukB.js.map +1 -1
- package/dist/chunks/config-CvbVM4ep.js.map +1 -1
- package/dist/chunks/config-D0NzGYaE.js.map +1 -1
- package/dist/chunks/config-D0W8mGFD.js.map +1 -1
- package/dist/chunks/config-D82r782v.js.map +1 -1
- package/dist/chunks/config-DBi0GVce.js.map +1 -1
- package/dist/chunks/config-DBmdgoVf.js.map +1 -0
- package/dist/chunks/config-DCq4JySZ.js.map +1 -1
- package/dist/chunks/config-DGC00bTp.js.map +1 -1
- package/dist/chunks/config-DIDz_E5m.js.map +1 -1
- package/dist/chunks/config-DM0lsduD.js.map +1 -1
- package/dist/chunks/config-DNDgp9bB.js.map +1 -1
- package/dist/chunks/config-DOYz_SVK.js.map +1 -1
- package/dist/chunks/config-DRbojEzO.js.map +1 -1
- package/dist/chunks/config-DUNH02Fg.js.map +1 -1
- package/dist/chunks/config-DUbbGcfw.js.map +1 -1
- package/dist/chunks/config-DVCNvhIG.js.map +1 -0
- package/dist/chunks/config-DWL81-aM.js.map +1 -1
- package/dist/chunks/config-DZCUPHPU.js.map +1 -1
- package/dist/chunks/config-DeyT9dJl.js.map +1 -1
- package/dist/chunks/config-DolULhjJ.js.map +1 -1
- package/dist/chunks/config-DpAYidyY.js.map +1 -0
- package/dist/chunks/config-Droqn55j.js.map +1 -1
- package/dist/chunks/config-DwABJHEo.js.map +1 -1
- package/dist/chunks/config-E1cTyRVV.js.map +1 -1
- package/dist/chunks/config-MmPym-Z7.js.map +1 -0
- package/dist/chunks/config-QaIc_gRa.js.map +1 -1
- package/dist/chunks/config-Yy67uWHY.js.map +1 -1
- package/dist/chunks/config-Z5LeUXys.js.map +1 -1
- package/dist/chunks/config-_jbgsFpw.js.map +1 -1
- package/dist/chunks/config-eXB87DOi.js.map +1 -1
- package/dist/chunks/config-rLkc9Zn2.js.map +1 -1
- package/dist/chunks/{context-CTbuwcYs.js → context-CPMRfwVr.js} +1 -1
- package/dist/chunks/{context-CTbuwcYs.js.map → context-CPMRfwVr.js.map} +1 -1
- package/dist/chunks/devHook-CiqijpNM.js +44 -0
- package/dist/chunks/devHook-CiqijpNM.js.map +1 -0
- package/dist/chunks/{grRadioStyles-DGL2QLy6.js → grRadioStyles-BwRyCjQQ.js} +4 -2
- package/dist/chunks/{grRadioStyles-DGL2QLy6.js.map → grRadioStyles-BwRyCjQQ.js.map} +1 -1
- package/dist/chunks/{granular-provider-Bp_BCBnr.js → granular-provider-DP2gk0oa.js} +9 -8
- package/dist/chunks/{granular-provider-Bp_BCBnr.js.map → granular-provider-DP2gk0oa.js.map} +1 -1
- package/dist/chunks/{overlayStack-0CZS99Da.js → overlayStack-DH4Z7am1.js} +45 -25
- package/dist/chunks/overlayStack-DH4Z7am1.js.map +1 -0
- package/dist/chunks/{renamedProp-BwcN-SJg.js → renamedProp-Dy96tT-F.js} +1 -1
- package/dist/chunks/{renamedProp-BwcN-SJg.js.map → renamedProp-Dy96tT-F.js.map} +1 -1
- package/dist/chunks/{useModalOverlay-BnAGZpcI.js → useModalOverlay-ACRkflzx.js} +3 -3
- package/dist/chunks/{useModalOverlay-BnAGZpcI.js.map → useModalOverlay-ACRkflzx.js.map} +1 -1
- package/dist/chunks/{usePortalTarget-C0p-mhaM.js → usePortalTarget-BhrRgdqW.js} +1 -1
- package/dist/chunks/{usePortalTarget-C0p-mhaM.js.map → usePortalTarget-BhrRgdqW.js.map} +1 -1
- package/dist/chunks/{validation-5HhpanPP.js → validation-BDjqsuGB.js} +1 -1
- package/dist/chunks/{validation-5HhpanPP.js.map → validation-BDjqsuGB.js.map} +1 -1
- package/dist/components/GrAlert/chunks/{GrAlert-FAVf-ksH.js → GrAlert-D72y1IEh.js} +1 -1
- package/dist/components/GrAlert/chunks/{GrAlert-FAVf-ksH.js.map → GrAlert-D72y1IEh.js.map} +1 -1
- package/dist/components/GrAlert/index.js +1 -1
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-BQsSE7sj.js → GrAutocomplete-BpmFmpKs.js} +4 -6
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-BQsSE7sj.js.map → GrAutocomplete-BpmFmpKs.js.map} +1 -1
- package/dist/components/GrAutocomplete/index.js +1 -1
- package/dist/components/GrAvatar/chunks/{GrAvatar-CNmLmgcr.js → GrAvatar-dWEXiCJG.js} +1 -1
- package/dist/components/GrAvatar/chunks/{GrAvatar-CNmLmgcr.js.map → GrAvatar-dWEXiCJG.js.map} +1 -1
- package/dist/components/GrAvatar/index.js +1 -1
- package/dist/components/GrBadge/chunks/{GrBadge-DpUDXKbq.js → GrBadge-DBeQXEir.js} +2 -2
- package/dist/components/GrBadge/chunks/{GrBadge-DpUDXKbq.js.map → GrBadge-DBeQXEir.js.map} +1 -1
- package/dist/components/GrBadge/index.js +1 -1
- package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-B-A3PRkE.js → GrBadgeWrap-wdfxaXiu.js} +3 -1
- package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-B-A3PRkE.js.map → GrBadgeWrap-wdfxaXiu.js.map} +1 -1
- package/dist/components/GrBadgeWrap/index.js +1 -1
- package/dist/components/GrBottomNav/chunks/{GrBottomNav-wtFatLjB.js → GrBottomNav-nE08pVUJ.js} +1 -1
- package/dist/components/GrBottomNav/chunks/{GrBottomNav-wtFatLjB.js.map → GrBottomNav-nE08pVUJ.js.map} +1 -1
- package/dist/components/GrBottomNav/index.js +1 -1
- package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-DRDNan_n.js → GrBreadcrumbs-DOpwY2EF.js} +3 -3
- package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-DRDNan_n.js.map → GrBreadcrumbs-DOpwY2EF.js.map} +1 -1
- package/dist/components/GrBreadcrumbs/index.js +1 -1
- package/dist/components/GrButton/chunks/{GrButton-7GP0zObj.js → GrButton-CS4TqMtG.js} +1 -1
- package/dist/components/GrButton/chunks/{GrButton-7GP0zObj.js.map → GrButton-CS4TqMtG.js.map} +1 -1
- package/dist/components/GrButton/index.js +1 -1
- package/dist/components/GrButtonGroup/chunks/GrButtonGroup-CKyiAV8K.js.map +1 -1
- package/dist/components/GrButtonGroup/index.js +1 -1
- package/dist/components/GrCard/chunks/{GrCard-BttXz1pQ.js → GrCard-Ck5--lMF.js} +2 -2
- package/dist/components/GrCard/chunks/{GrCard-BttXz1pQ.js.map → GrCard-Ck5--lMF.js.map} +1 -1
- package/dist/components/GrCard/index.js +1 -1
- package/dist/components/GrCheckbox/chunks/{GrCheckbox-CEcHIsXM.js → GrCheckbox-Dp201frb.js} +1 -1
- package/dist/components/GrCheckbox/chunks/{GrCheckbox-CEcHIsXM.js.map → GrCheckbox-Dp201frb.js.map} +1 -1
- package/dist/components/GrCheckbox/index.js +1 -1
- package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-BOwrVcFr.js → GrCheckboxGroup-IpqG5qwm.js} +2 -2
- package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-BOwrVcFr.js.map → GrCheckboxGroup-IpqG5qwm.js.map} +1 -1
- package/dist/components/GrCheckboxGroup/index.js +1 -1
- package/dist/components/GrChip/chunks/{GrChip-BTivtwff.js → GrChip-CKqyzYcv.js} +10 -7
- package/dist/components/GrChip/chunks/{GrChip-BTivtwff.js.map → GrChip-CKqyzYcv.js.map} +1 -1
- package/dist/components/GrChip/index.js +1 -1
- package/dist/components/GrChipGroup/chunks/{GrChipGroup-C78Vcwos.js → GrChipGroup-dDGwnC04.js} +1 -1
- package/dist/components/GrChipGroup/chunks/{GrChipGroup-C78Vcwos.js.map → GrChipGroup-dDGwnC04.js.map} +1 -1
- package/dist/components/GrChipGroup/index.js +1 -1
- package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-Dp0eEBTZ.js → GrCodeBlock-BUOwKwQE.js} +2 -2
- package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-Dp0eEBTZ.js.map → GrCodeBlock-BUOwKwQE.js.map} +1 -1
- package/dist/components/GrCodeBlock/index.js +1 -1
- package/dist/components/GrCollapse/chunks/{GrCollapse-BlW6ybdL.js → GrCollapse-DWH3QAnU.js} +6 -5
- package/dist/components/GrCollapse/chunks/{GrCollapse-BlW6ybdL.js.map → GrCollapse-DWH3QAnU.js.map} +1 -1
- package/dist/components/GrCollapse/index.js +1 -1
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-B-L4CWMt.js → GrColorPicker-BwzRLs-i.js} +4 -4
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-B-L4CWMt.js.map → GrColorPicker-BwzRLs-i.js.map} +1 -1
- package/dist/components/GrColorPicker/index.js +1 -1
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-8HkYmMVP.js → GrCommandPalette-CnzPuoIM.js} +7 -7
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-8HkYmMVP.js.map → GrCommandPalette-CnzPuoIM.js.map} +1 -1
- package/dist/components/GrCommandPalette/index.js +1 -1
- package/dist/components/GrConfigProvider/chunks/{GrConfigProvider-BF7R3hgg.js → GrConfigProvider-t9x2UToH.js} +13 -12
- package/dist/components/GrConfigProvider/chunks/{GrConfigProvider-BF7R3hgg.js.map → GrConfigProvider-t9x2UToH.js.map} +1 -1
- package/dist/components/GrConfigProvider/index.js +2 -2
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-CZEO2JR4.js → GrConfirmDialog-e15nFI8M.js} +4 -4
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-CZEO2JR4.js.map → GrConfirmDialog-e15nFI8M.js.map} +1 -1
- package/dist/components/GrConfirmDialog/index.js +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-DlFWm0eW.js → GrContextMenu-RpxMHQXH.js} +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-DlFWm0eW.js.map → GrContextMenu-RpxMHQXH.js.map} +1 -1
- package/dist/components/GrContextMenu/index.js +1 -1
- package/dist/components/GrDataTable/chunks/{GrDataTable-4JAgOQ-7.js → GrDataTable-BYYG_XZA.js} +5 -5
- package/dist/components/GrDataTable/chunks/{GrDataTable-4JAgOQ-7.js.map → GrDataTable-BYYG_XZA.js.map} +1 -1
- package/dist/components/GrDataTable/index.js +1 -1
- package/dist/components/GrDelta/chunks/{GrDelta-BZwkgQW-.js → GrDelta-BpfqebEV.js} +0 -0
- package/dist/components/GrDelta/chunks/{GrDelta-BZwkgQW-.js.map → GrDelta-BpfqebEV.js.map} +1 -1
- package/dist/components/GrDelta/index.js +1 -1
- package/dist/components/GrDescriptionList/chunks/{GrDescriptionList-BMeCgFV3.js → GrDescriptionList-D8ANFpn_.js} +2 -2
- package/dist/components/GrDescriptionList/chunks/{GrDescriptionList-BMeCgFV3.js.map → GrDescriptionList-D8ANFpn_.js.map} +1 -1
- package/dist/components/GrDescriptionList/index.js +2 -2
- package/dist/components/GrDialog/chunks/{GrDialog-CKNbnxwO.js → GrDialog-DDz_OEhk.js} +3 -3
- package/dist/components/GrDialog/chunks/{GrDialog-CKNbnxwO.js.map → GrDialog-DDz_OEhk.js.map} +1 -1
- package/dist/components/GrDialog/index.js +1 -1
- package/dist/components/GrDialogService/chunks/{GrDialogService-Ut8iiBQh.js → GrDialogService-BmXiYmUp.js} +9 -8
- package/dist/components/GrDialogService/chunks/{GrDialogService-Ut8iiBQh.js.map → GrDialogService-BmXiYmUp.js.map} +1 -1
- package/dist/components/GrDialogService/index.js +1 -1
- package/dist/components/GrDivider/chunks/{GrDivider-BXavGcMX.js → GrDivider-DxA-zV25.js} +1 -1
- package/dist/components/GrDivider/chunks/{GrDivider-BXavGcMX.js.map → GrDivider-DxA-zV25.js.map} +1 -1
- package/dist/components/GrDivider/index.js +1 -1
- package/dist/components/GrDrawer/chunks/{GrDrawer-xfoy-MCj.js → GrDrawer-BRMHhvbd.js} +5 -5
- package/dist/components/GrDrawer/chunks/{GrDrawer-xfoy-MCj.js.map → GrDrawer-BRMHhvbd.js.map} +1 -1
- package/dist/components/GrDrawer/index.js +1 -1
- package/dist/components/GrDropdown/chunks/{GrDropdown-7r772-Cq.js → GrDropdown-cLZuZMEY.js} +6 -8
- package/dist/components/GrDropdown/chunks/{GrDropdown-7r772-Cq.js.map → GrDropdown-cLZuZMEY.js.map} +1 -1
- package/dist/components/GrDropdown/index.js +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DNurbsWc.js → GrDropdownMenu-Dxkz_ry4.js} +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DNurbsWc.js.map → GrDropdownMenu-Dxkz_ry4.js.map} +1 -1
- package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-B33ZzwfB.js.map +1 -1
- package/dist/components/GrDropdownMenu/index.js +1 -1
- package/dist/components/GrEmptyState/chunks/{GrEmptyState-RqsWvgI9.js → GrEmptyState-BbvwE-E0.js} +2 -2
- package/dist/components/GrEmptyState/chunks/{GrEmptyState-RqsWvgI9.js.map → GrEmptyState-BbvwE-E0.js.map} +1 -1
- package/dist/components/GrEmptyState/index.js +1 -1
- package/dist/components/GrFilePreview/chunks/{GrFilePreview-C9Z7hMK8.js → GrFilePreview-PabkLgYX.js} +1 -1
- package/dist/components/GrFilePreview/chunks/{GrFilePreview-C9Z7hMK8.js.map → GrFilePreview-PabkLgYX.js.map} +1 -1
- package/dist/components/GrFilePreview/index.js +1 -1
- package/dist/components/GrFileUpload/chunks/{GrFileUpload-C0ROpmOY.js → GrFileUpload-BwMR71zN.js} +4 -4
- package/dist/components/GrFileUpload/chunks/{GrFileUpload-C0ROpmOY.js.map → GrFileUpload-BwMR71zN.js.map} +1 -1
- package/dist/components/GrFileUpload/index.js +1 -1
- package/dist/components/GrForm/chunks/{GrForm-CrnfCsgj.js → GrForm-xTtavR-K.js} +1 -1
- package/dist/components/GrForm/chunks/{GrForm-CrnfCsgj.js.map → GrForm-xTtavR-K.js.map} +1 -1
- package/dist/components/GrForm/index.js +2 -2
- package/dist/components/GrFormField/chunks/{GrFormField-DSylU7IU.js → GrFormField-DO61vxpS.js} +2 -2
- package/dist/components/GrFormField/chunks/{GrFormField-DSylU7IU.js.map → GrFormField-DO61vxpS.js.map} +1 -1
- package/dist/components/GrFormField/index.js +1 -1
- package/dist/components/GrFormFile/chunks/{GrFormFile-B1jGZyIj.js → GrFormFile-Dlxx-9zi.js} +3 -3
- package/dist/components/GrFormFile/chunks/{GrFormFile-B1jGZyIj.js.map → GrFormFile-Dlxx-9zi.js.map} +1 -1
- package/dist/components/GrFormFile/index.js +1 -1
- package/dist/components/GrFormSection/chunks/{GrFormSection-ejieOg9H.js → GrFormSection-DV1S6R_N.js} +1 -1
- package/dist/components/GrFormSection/chunks/{GrFormSection-ejieOg9H.js.map → GrFormSection-DV1S6R_N.js.map} +1 -1
- package/dist/components/GrFormSection/index.js +1 -1
- package/dist/components/GrIcon/chunks/{GrIcon-Dmf0c9ba.js → GrIcon-DTZIgmje.js} +1 -1
- package/dist/components/GrIcon/chunks/{GrIcon-Dmf0c9ba.js.map → GrIcon-DTZIgmje.js.map} +1 -1
- package/dist/components/GrIcon/index.js +1 -1
- package/dist/components/GrImageViewer/chunks/{GrImageViewer--BU8yrfx.js → GrImageViewer-CcduIFsa.js} +2 -4
- package/dist/components/GrImageViewer/chunks/{GrImageViewer--BU8yrfx.js.map → GrImageViewer-CcduIFsa.js.map} +1 -1
- package/dist/components/GrImageViewer/index.js +1 -1
- package/dist/components/GrInput/chunks/{GrInput-CJ7eu3fR.js → GrInput-TFeBm3gQ.js} +1 -1
- package/dist/components/GrInput/chunks/{GrInput-CJ7eu3fR.js.map → GrInput-TFeBm3gQ.js.map} +1 -1
- package/dist/components/GrInput/index.js +1 -1
- package/dist/components/GrInputTag/chunks/{GrInputTag-ByD9NugQ.js → GrInputTag-DhfUNOA5.js} +3 -3
- package/dist/components/GrInputTag/chunks/{GrInputTag-ByD9NugQ.js.map → GrInputTag-DhfUNOA5.js.map} +1 -1
- package/dist/components/GrInputTag/index.js +1 -1
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-BXG7DdTe.js → GrJsonViewer-CdtmUpZ3.js} +6 -6
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-BXG7DdTe.js.map → GrJsonViewer-CdtmUpZ3.js.map} +1 -1
- package/dist/components/GrJsonViewer/index.js +2 -2
- package/dist/components/GrKbd/chunks/{GrKbd-D2ga1H9i.js → GrKbd-D_a1mPLe.js} +1 -1
- package/dist/components/GrKbd/chunks/{GrKbd-D2ga1H9i.js.map → GrKbd-D_a1mPLe.js.map} +1 -1
- package/dist/components/GrKbd/index.js +1 -1
- package/dist/components/GrLink/chunks/{GrLink-DYXw3W9w.js → GrLink-DwWErumU.js} +2 -2
- package/dist/components/GrLink/chunks/{GrLink-DYXw3W9w.js.map → GrLink-DwWErumU.js.map} +1 -1
- package/dist/components/GrLink/index.js +2 -2
- package/dist/components/GrList/chunks/{GrList-B_CRJB4c.js → GrList-Unya-LXb.js} +3 -3
- package/dist/components/GrList/chunks/{GrList-B_CRJB4c.js.map → GrList-Unya-LXb.js.map} +1 -1
- package/dist/components/GrList/index.js +1 -1
- package/dist/components/GrLoading/chunks/{GrLoading-CMD3Ri9P.js → GrLoading-BDrlrup_.js} +1 -1
- package/dist/components/GrLoading/chunks/{GrLoading-CMD3Ri9P.js.map → GrLoading-BDrlrup_.js.map} +1 -1
- package/dist/components/GrLoading/index.js +1 -1
- package/dist/components/GrModal/chunks/{GrModal-DixnhJcu.js → GrModal-Cm0mtSXk.js} +4 -4
- package/dist/components/GrModal/chunks/{GrModal-DixnhJcu.js.map → GrModal-Cm0mtSXk.js.map} +1 -1
- package/dist/components/GrModal/index.js +1 -1
- package/dist/components/GrNavbar/chunks/{GrNavbar-Dr8e5kW-.js → GrNavbar-BRGuksiy.js} +3 -3
- package/dist/components/GrNavbar/chunks/{GrNavbar-Dr8e5kW-.js.map → GrNavbar-BRGuksiy.js.map} +1 -1
- package/dist/components/GrNavbar/index.js +1 -1
- package/dist/components/GrNumberInput/chunks/{GrNumberInput-DQ59YICu.js → GrNumberInput-BqPydXpK.js} +7 -9
- package/dist/components/GrNumberInput/chunks/{GrNumberInput-DQ59YICu.js.map → GrNumberInput-BqPydXpK.js.map} +1 -1
- package/dist/components/GrNumberInput/index.js +2 -2
- package/dist/components/GrPagination/chunks/{GrPagination-68iyAwQz.js → GrPagination-DhbNZHEF.js} +4 -4
- package/dist/components/GrPagination/chunks/{GrPagination-68iyAwQz.js.map → GrPagination-DhbNZHEF.js.map} +1 -1
- package/dist/components/GrPagination/index.js +1 -1
- package/dist/components/GrPopover/chunks/{GrPopover-DEFxDffj.js → GrPopover-CcWvr1ZA.js} +3 -3
- package/dist/components/GrPopover/chunks/{GrPopover-DEFxDffj.js.map → GrPopover-CcWvr1ZA.js.map} +1 -1
- package/dist/components/GrPopover/index.js +2 -2
- package/dist/components/GrProgressBar/chunks/{GrProgressBar-Cd7AaJtR.js → GrProgressBar-C3NRBqIP.js} +2 -2
- package/dist/components/GrProgressBar/chunks/{GrProgressBar-Cd7AaJtR.js.map → GrProgressBar-C3NRBqIP.js.map} +1 -1
- package/dist/components/GrProgressBar/index.js +1 -1
- package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-D3yWXYDa.js → GrProgressCircle-CdvbINQc.js} +2 -2
- package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-D3yWXYDa.js.map → GrProgressCircle-CdvbINQc.js.map} +1 -1
- package/dist/components/GrProgressCircle/index.js +1 -1
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-Ckeombia.js → GrPromptDialog-8RxQsOQ_.js} +8 -8
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-Ckeombia.js.map → GrPromptDialog-8RxQsOQ_.js.map} +1 -1
- package/dist/components/GrPromptDialog/index.js +1 -1
- package/dist/components/GrRadio/chunks/{GrRadio-Aq3v8XgG.js → GrRadio-B1776V9D.js} +2 -2
- package/dist/components/GrRadio/chunks/{GrRadio-Aq3v8XgG.js.map → GrRadio-B1776V9D.js.map} +1 -1
- package/dist/components/GrRadio/index.js +2 -2
- package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-y9LVdTWh.js → GrRadioGroup-UgitrBFl.js} +2 -2
- package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-y9LVdTWh.js.map → GrRadioGroup-UgitrBFl.js.map} +1 -1
- package/dist/components/GrRadioGroup/index.js +1 -1
- package/dist/components/GrRating/chunks/{GrRating-IEiTOdnF.js → GrRating-DTriyyqG.js} +1 -1
- package/dist/components/GrRating/chunks/{GrRating-IEiTOdnF.js.map → GrRating-DTriyyqG.js.map} +1 -1
- package/dist/components/GrRating/index.js +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DMeOWlzj.js → GrResponseErrorBanner-NEEJZ8zi.js} +2 -2
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DMeOWlzj.js.map → GrResponseErrorBanner-NEEJZ8zi.js.map} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-CBVRpgIG.js → GrResponseErrorBanner-ZvBvEQDZ.js} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-CBVRpgIG.js.map → GrResponseErrorBanner-ZvBvEQDZ.js.map} +1 -1
- package/dist/components/GrResponseErrorBanner/index.js +2 -2
- package/dist/components/GrSegmented/chunks/{GrSegmented-CB-VR-yL.js → GrSegmented-NKTi9bMG.js} +1 -1
- package/dist/components/GrSegmented/chunks/{GrSegmented-CB-VR-yL.js.map → GrSegmented-NKTi9bMG.js.map} +1 -1
- package/dist/components/GrSegmented/index.js +1 -1
- package/dist/components/GrSelect/chunks/{GrSelect-Bm3Jugx8.js → GrSelect-Do1iAyp1.js} +6 -6
- package/dist/components/GrSelect/chunks/{GrSelect-Bm3Jugx8.js.map → GrSelect-Do1iAyp1.js.map} +1 -1
- package/dist/components/GrSelect/index.js +1 -1
- package/dist/components/GrSidebar/chunks/{GrSidebar-alkwBUzL.js → GrSidebar-DoKLlHSw.js} +2 -2
- package/dist/components/GrSidebar/chunks/{GrSidebar-alkwBUzL.js.map → GrSidebar-DoKLlHSw.js.map} +1 -1
- package/dist/components/GrSidebar/index.js +1 -1
- package/dist/components/GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js.map +1 -1
- package/dist/components/GrSlider/chunks/{GrSlider-DM6W6U9c.js → GrSlider-Db-jACXz.js} +6 -4
- package/dist/components/GrSlider/chunks/{GrSlider-DM6W6U9c.js.map → GrSlider-Db-jACXz.js.map} +1 -1
- package/dist/components/GrSlider/index.js +1 -1
- package/dist/components/GrSortableList/chunks/{GrSortableList-HyKX--rO.js → GrSortableList-CQCaWivn.js} +1 -1
- package/dist/components/GrSortableList/chunks/{GrSortableList-HyKX--rO.js.map → GrSortableList-CQCaWivn.js.map} +1 -1
- package/dist/components/GrSortableList/index.js +1 -1
- package/dist/components/GrSplitter/chunks/{GrSplitter-MltjaADn.js → GrSplitter-C-XQzq7q.js} +1 -1
- package/dist/components/GrSplitter/chunks/{GrSplitter-MltjaADn.js.map → GrSplitter-C-XQzq7q.js.map} +1 -1
- package/dist/components/GrSplitter/index.js +1 -1
- package/dist/components/GrStatistic/chunks/{GrStatistic-BoLkXw7F.js → GrStatistic-C1_nY4Gc.js} +2 -2
- package/dist/components/GrStatistic/chunks/{GrStatistic-BoLkXw7F.js.map → GrStatistic-C1_nY4Gc.js.map} +1 -1
- package/dist/components/GrStatistic/index.js +1 -1
- package/dist/components/GrSteps/chunks/{GrSteps-CpGHXLOc.js → GrSteps-DXj7m-WO.js} +2 -2
- package/dist/components/GrSteps/chunks/{GrSteps-CpGHXLOc.js.map → GrSteps-DXj7m-WO.js.map} +1 -1
- package/dist/components/GrSteps/index.js +1 -1
- package/dist/components/GrSwitch/chunks/{GrSwitch-7Oe5QfQZ.js → GrSwitch-CriHWT2A.js} +1 -1
- package/dist/components/GrSwitch/chunks/{GrSwitch-7Oe5QfQZ.js.map → GrSwitch-CriHWT2A.js.map} +1 -1
- package/dist/components/GrSwitch/index.js +1 -1
- package/dist/components/GrTabPanels/chunks/{GrTabPanels-BZQS8-JM.js → GrTabPanels-5zsbqS1v.js} +1 -1
- package/dist/components/GrTabPanels/chunks/{GrTabPanels-BZQS8-JM.js.map → GrTabPanels-5zsbqS1v.js.map} +1 -1
- package/dist/components/GrTabPanels/index.js +1 -1
- package/dist/components/GrTable/chunks/{GrTable-jhUTczjv.js → GrTable-iwzHvlMC.js} +1 -1
- package/dist/components/GrTable/chunks/{GrTable-jhUTczjv.js.map → GrTable-iwzHvlMC.js.map} +1 -1
- package/dist/components/GrTable/index.js +1 -1
- package/dist/components/GrTabs/chunks/{GrTabs-CT2nk_HV.js → GrTabs-DHfv67cp.js} +1 -1
- package/dist/components/GrTabs/chunks/{GrTabs-CT2nk_HV.js.map → GrTabs-DHfv67cp.js.map} +1 -1
- package/dist/components/GrTabs/index.js +1 -1
- package/dist/components/GrTextarea/chunks/{GrTextarea-DinXG12-.js → GrTextarea-BII3w61K.js} +1 -1
- package/dist/components/GrTextarea/chunks/{GrTextarea-DinXG12-.js.map → GrTextarea-BII3w61K.js.map} +1 -1
- package/dist/components/GrTextarea/index.js +1 -1
- package/dist/components/GrTimeline/chunks/{GrTimeline-BiHpArsg.js → GrTimeline-Bs60huw0.js} +2 -2
- package/dist/components/GrTimeline/chunks/{GrTimeline-BiHpArsg.js.map → GrTimeline-Bs60huw0.js.map} +1 -1
- package/dist/components/GrTimeline/index.js +1 -1
- package/dist/components/GrToaster/chunks/{GrToaster-COXIBKzq.js → GrToaster-D-sV-9of.js} +4 -4
- package/dist/components/GrToaster/chunks/{GrToaster-COXIBKzq.js.map → GrToaster-D-sV-9of.js.map} +1 -1
- package/dist/components/GrToaster/index.js +1 -1
- package/dist/components/GrTooltip/chunks/{GrTooltip-uYETdbCD.js → GrTooltip-BUiTbROv.js} +3 -3
- package/dist/components/GrTooltip/chunks/{GrTooltip-uYETdbCD.js.map → GrTooltip-BUiTbROv.js.map} +1 -1
- package/dist/components/GrTooltip/index.js +1 -1
- package/dist/components/GrTree/chunks/{GrTree-Ci6CZfKR.js → GrTree-CkELQwR8.js} +1 -2
- package/dist/components/GrTree/chunks/{GrTree-Ci6CZfKR.js.map → GrTree-CkELQwR8.js.map} +1 -1
- package/dist/components/GrTree/index.js +1 -1
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-MGsyvkJV.js → GrTreeSelect-DurwZ7Cz.js} +4 -4
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-MGsyvkJV.js.map → GrTreeSelect-DurwZ7Cz.js.map} +1 -1
- package/dist/components/GrTreeSelect/index.js +1 -1
- package/dist/components/GrValue/chunks/GrValue-ezkQM05Q.js.map +1 -1
- package/dist/composables/useFloating.js +1 -1
- package/dist/composables/useGrComponentConfig.js +1 -1
- package/dist/composables/useOverlayLayer.js +35 -6
- package/dist/composables/useOverlayLayer.js.map +1 -1
- package/dist/composables/usePortalTarget.js +1 -1
- package/dist/composables/useTheme.js +1 -1
- package/dist/composables/useTheme.js.map +1 -1
- package/dist/composables/useToast.js +1 -1
- package/dist/composables/useToast.js.map +1 -1
- package/dist/composables/useVirtualList.js +26 -6
- package/dist/composables/useVirtualList.js.map +1 -1
- package/dist/directives/loading.js +1 -1
- package/dist/granular-provider-node.js +1 -1
- package/dist/granular-provider.js +1 -1
- package/dist/index.js +86 -86
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/types/components/GrDialog/GrDialog.vue.d.ts +1 -1
- package/dist/types/components/GrDrawer/GrDrawer.vue.d.ts +1 -1
- package/dist/types/components/GrModal/GrModal.vue.d.ts +1 -1
- package/dist/types/composables/internal/overlayStack.d.ts +11 -0
- package/dist/types/internal/devHook.d.ts +119 -0
- package/dist/vue/index.js +2 -2
- package/dist/vue/index.js.map +1 -1
- package/dist/web-types.json +1 -1
- package/package.json +16 -16
- package/dist/chunks/config-CQLNjc9X2.js.map +0 -1
- package/dist/chunks/config-CnYdE3HZ2.js.map +0 -1
- package/dist/chunks/config-CuQmUkMw2.js.map +0 -1
- package/dist/chunks/config-DBmdgoVf2.js.map +0 -1
- package/dist/chunks/config-DVCNvhIG2.js.map +0 -1
- package/dist/chunks/config-DpAYidyY2.js.map +0 -1
- package/dist/chunks/config-MmPym-Z72.js.map +0 -1
- package/dist/chunks/overlayStack-0CZS99Da.js.map +0 -1
- /package/dist/chunks/{config-CQLNjc9X2.js → config-CQLNjc9X.js} +0 -0
- /package/dist/chunks/{config-CnYdE3HZ2.js → config-CnYdE3HZ.js} +0 -0
- /package/dist/chunks/{config-DBmdgoVf2.js → config-DBmdgoVf.js} +0 -0
- /package/dist/chunks/{config-DVCNvhIG2.js → config-DVCNvhIG.js} +0 -0
- /package/dist/chunks/{config-DpAYidyY2.js → config-DpAYidyY.js} +0 -0
- /package/dist/chunks/{config-MmPym-Z72.js → config-MmPym-Z7.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrSortableList-HyKX--rO.js","names":[],"sources":["../../../../src/components/GrSortableList/GrSortableList.vue","../../../../src/components/GrSortableList/GrSortableList.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T\">\nimport { computed, nextTick, ref } from 'vue'\n\nimport GrCard, { type GrCardVariant } from '../GrCard'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useDragSort } from '../../composables/useDragSort'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { insertionIndex, moveItem } from '../../composables/internal/dragSortGeometry'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport type { GrSortableOrientation } from './grSortableListStyles'\nimport {\n contentClass,\n dividedClass,\n emptyClass,\n handleClass,\n handleDisabledClass,\n indicatorAfterClass,\n indicatorBeforeClass,\n listClass,\n rowDisabledClass,\n rowDraggingClass,\n rowFocusClass,\n rowGrabbedClass,\n rowLayoutClass,\n} from './grSortableListStyles'\n\nimport IconGripVertical from '~icons/lucide/grip-vertical'\n\nexport interface GrSortableListProps<TItem = unknown> {\n /** Набор в текущем порядке. `v-model`: наружу уходит новый массив, вход не мутируется. */\n modelValue: TItem[]\n /** Ключ элемента: имя поля или функция. Без него — индекс. */\n itemKey?: string | ((item: TItem, index: number) => string | number)\n /** Список только для чтения: ни указателем, ни с клавиатуры. */\n disabled?: boolean\n /** Ось переноса. `horizontal` — ряд с переносом по ширине. */\n orientation?: GrSortableOrientation\n /** Поверхность под списком — вариант карточки. */\n variant?: GrCardVariant\n /** Разделители между строками. */\n divided?: boolean\n /** Тянуть можно только за ручку. Выключено — тянется вся строка. */\n handleOnly?: boolean\n /** Высота видимой части: список становится скроллером с автопрокруткой при переносе. */\n maxHeight?: number | string\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Имя списка для скринридера. Не задано — берётся из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSortableListEmits<TItem = unknown> {\n (e: 'update:modelValue', value: TItem[]): void\n (e: 'move', from: number, to: number): void\n (e: 'change', value: TItem[]): void\n}\n\nconst props = withDefaults(defineProps<GrSortableListProps<T>>(), {\n itemKey: undefined,\n disabled: false,\n orientation: 'vertical',\n variant: undefined,\n divided: true,\n handleOnly: true,\n maxHeight: undefined,\n emptyText: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrSortableListEmits<T>>()\n\ndefineSlots<{\n item?: (props: { item: T, index: number, dragging: boolean, grabbed: boolean }) => any\n handle?: (props: { item: T, index: number, disabled: boolean }) => any\n empty?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\n\nconst listEl = ref<HTMLElement | null>(null)\nconst rowEls = new Map<string, HTMLElement>()\n\nconst count = computed(() => props.modelValue.length)\nconst isEmpty = computed(() => count.value === 0)\nconst isVertical = computed(() => props.orientation === 'vertical')\n\nfunction keyOf(item: T, index: number): string {\n if (typeof props.itemKey === 'function')\n return String(props.itemKey(item, index))\n if (typeof props.itemKey === 'string')\n return String((item as Record<string, unknown>)[props.itemKey])\n\n return String(index)\n}\n\nconst keys = computed(() => props.modelValue.map((item, index) => keyOf(item, index)))\n\nfunction indexOfKey(key: string): number {\n return keys.value.indexOf(key)\n}\n\nfunction registerRow(key: string, el: unknown): void {\n if (el instanceof HTMLElement) {\n rowEls.set(key, el)\n return\n }\n\n // Перестановка размонтирует старый узел уже после того, как встал новый:\n // снимаем запись, только если она протухла (приём из `GrTree`).\n const previous = rowEls.get(key)\n if (previous && !previous.isConnected)\n rowEls.delete(key)\n}\n\nconst roving = useRovingFocus<string>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => (isVertical.value ? 'vertical' : 'horizontal'),\n wrap: () => false,\n})\n\nfunction applyMove(from: number, to: number): void {\n if (from < 0 || to < 0 || from === to)\n return\n\n const next = moveItem(props.modelValue, from, to)\n emit('update:modelValue', next)\n emit('move', from, to)\n emit('change', next)\n}\n\nconst sort = useDragSort<string, number>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => props.orientation,\n scroller: () => (props.maxHeight === undefined ? null : listEl.value),\n disabled: () => props.disabled,\n resolveTarget: (hit, source) => insertionIndex(hit, indexOfKey(source), count.value),\n onDrop: (source, to) => applyMove(indexOfKey(source), to),\n onUpdate: (source, target, mode) => {\n // Объявляется только клавиатурный перенос: у мыши всё видно на экране, а\n // поток объявлений на каждом движении указателя делает диктор бесполезным.\n if (mode !== 'keyboard' || source === null)\n return\n\n const position = (target ?? indexOfKey(source)) + 1\n announce(t('gr.sortable.moved', 'Position {position} of {count}', { position, count: count.value }))\n },\n})\n\nconst activeIndex = computed(() => (sort.source.value === null ? -1 : indexOfKey(sort.source.value)))\n\n/** Куда встанет строка: индикатор рисуется на строке-соседе, а не отдельным узлом. */\nfunction indicatorFor(index: number): 'before' | 'after' | null {\n const target = sort.target.value\n if (target === null || !sort.isActive.value || index === activeIndex.value)\n return null\n\n if (target === index)\n return target < activeIndex.value || activeIndex.value === -1 ? 'before' : 'after'\n\n return null\n}\n\nfunction rowClass(index: number, key: string): string[] {\n const grabbed = sort.mode.value === 'keyboard' && sort.source.value === key\n const dragging = sort.mode.value === 'pointer' && sort.source.value === key\n const indicator = indicatorFor(index)\n\n return [\n rowLayoutClass,\n rowFocusClass,\n props.disabled ? rowDisabledClass : '',\n grabbed ? rowGrabbedClass : '',\n dragging ? rowDraggingClass : '',\n indicator === 'before' ? indicatorBeforeClass : '',\n indicator === 'after' ? indicatorAfterClass : '',\n ]\n}\n\nfunction startPointer(key: string, event: PointerEvent): void {\n if (props.disabled)\n return\n\n sort.startFrom(key)(event)\n}\n\nfunction grab(key: string): void {\n sort.grab(key)\n if (sort.mode.value !== 'keyboard')\n return\n\n // Цель ставится до объявления: `setTarget` сам объявляет позицию, и обратный\n // порядок стёр бы более полное сообщение о захвате.\n sort.setTarget(indexOfKey(key))\n announce(t('gr.sortable.grabbed', 'Grabbed. Position {position} of {count}', {\n position: indexOfKey(key) + 1,\n count: count.value,\n }))\n}\n\nasync function drop(key: string): Promise<void> {\n const target = sort.target.value\n sort.drop()\n\n announce(t('gr.sortable.dropped', 'Dropped at position {position} of {count}', {\n position: (target ?? 0) + 1,\n count: count.value,\n }))\n\n // Фокус остаётся на перенесённой строке: иначе после переноса он падает на\n // тело документа и клавиатурный сценарий обрывается на первом же шаге.\n await nextTick()\n await roving.focusKey(key)\n}\n\nfunction cancel(): void {\n if (!sort.isActive.value)\n return\n\n sort.cancel()\n announce(t('gr.sortable.cancelled', 'Move cancelled'))\n}\n\nfunction moveTargetBy(delta: number): void {\n const current = sort.target.value ?? activeIndex.value\n const next = Math.min(count.value - 1, Math.max(0, current + delta))\n\n if (next !== current)\n sort.setTarget(next)\n}\n\nfunction onRowKeydown(event: KeyboardEvent, key: string): void {\n if (props.disabled)\n return\n\n const forward = isVertical.value ? 'ArrowDown' : 'ArrowRight'\n const backward = isVertical.value ? 'ArrowUp' : 'ArrowLeft'\n const grabbed = sort.mode.value === 'keyboard'\n\n if (event.key === 'Escape') {\n if (!grabbed)\n return\n\n event.preventDefault()\n cancel()\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n if (grabbed)\n void drop(key)\n else grab(key)\n return\n }\n\n if (grabbed) {\n // Взятая строка забирает стрелки себе: двигается она, а не фокус.\n if (event.key === forward || event.key === backward) {\n event.preventDefault()\n moveTargetBy(event.key === forward ? 1 : -1)\n }\n return\n }\n\n roving.handleNavigationKeys(event)\n}\n\n/** Фокус ушёл из списка — взятая строка не может остаться взятой навсегда. */\nfunction onFocusout(event: FocusEvent): void {\n if (sort.mode.value !== 'keyboard')\n return\n\n const next = event.relatedTarget as Node | null\n if (next && listEl.value?.contains(next))\n return\n\n cancel()\n}\n\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.sortable.empty', 'Nothing to sort yet'))\nconst resolvedLabel = computed(() => props.ariaLabel ?? t('gr.sortable.label', 'Sortable list'))\nconst handleLabel = computed(() => t('gr.sortable.handle', 'Reorder'))\n\nconst listStyle = computed(() => (props.maxHeight === undefined\n ? undefined\n : { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight, overflow: 'auto' }))\n\ndefineExpose({\n /** Программная перестановка — та же, что делает перенос. */\n move: (from: number, to: number) => applyMove(from, to),\n focusItem: (index: number) => roving.focusKey(keys.value[index]),\n})\n</script>\n\n<template>\n <GrCard :variant=\"variant\">\n <div\n ref=\"listEl\"\n role=\"list\"\n data-gr-sortable\n :aria-label=\"resolvedLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"[listClass[orientation], divided ? dividedClass : '']\"\n :style=\"listStyle\"\n @focusout=\"onFocusout\"\n >\n <div\n v-if=\"isEmpty\"\n data-gr-sortable-empty\n :class=\"emptyClass\"\n >\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-for=\"(item, index) in modelValue\"\n v-else\n :key=\"keys[index]\"\n :ref=\"el => registerRow(keys[index], el)\"\n role=\"listitem\"\n data-gr-sortable-item\n :tabindex=\"disabled ? -1 : roving.tabindexFor(keys[index])\"\n :aria-roledescription=\"handleLabel\"\n :aria-posinset=\"index + 1\"\n :aria-setsize=\"count\"\n :aria-grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index] ? 'true' : undefined\"\n :class=\"rowClass(index, keys[index])\"\n @keydown=\"onRowKeydown($event, keys[index])\"\n @focus=\"roving.setActive(keys[index])\"\n @pointerdown=\"handleOnly ? undefined : startPointer(keys[index], $event)\"\n >\n <button\n type=\"button\"\n tabindex=\"-1\"\n data-gr-sortable-handle\n :class=\"[handleClass, disabled ? handleDisabledClass : '']\"\n :aria-label=\"handleLabel\"\n :disabled=\"disabled\"\n @pointerdown=\"startPointer(keys[index], $event)\"\n @click.stop\n >\n <slot\n name=\"handle\"\n :item=\"item\"\n :index=\"index\"\n :disabled=\"disabled\"\n >\n <IconGripVertical class=\"block\" aria-hidden=\"true\" />\n </slot>\n </button>\n\n <div :class=\"contentClass\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :dragging=\"sort.mode.value === 'pointer' && sort.source.value === keys[index]\"\n :grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index]\"\n >\n {{ item }}\n </slot>\n </div>\n </div>\n </div>\n </GrCard>\n</template>\n","<script setup lang=\"ts\" generic=\"T\">\nimport { computed, nextTick, ref } from 'vue'\n\nimport GrCard, { type GrCardVariant } from '../GrCard'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useDragSort } from '../../composables/useDragSort'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { insertionIndex, moveItem } from '../../composables/internal/dragSortGeometry'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport type { GrSortableOrientation } from './grSortableListStyles'\nimport {\n contentClass,\n dividedClass,\n emptyClass,\n handleClass,\n handleDisabledClass,\n indicatorAfterClass,\n indicatorBeforeClass,\n listClass,\n rowDisabledClass,\n rowDraggingClass,\n rowFocusClass,\n rowGrabbedClass,\n rowLayoutClass,\n} from './grSortableListStyles'\n\nimport IconGripVertical from '~icons/lucide/grip-vertical'\n\nexport interface GrSortableListProps<TItem = unknown> {\n /** Набор в текущем порядке. `v-model`: наружу уходит новый массив, вход не мутируется. */\n modelValue: TItem[]\n /** Ключ элемента: имя поля или функция. Без него — индекс. */\n itemKey?: string | ((item: TItem, index: number) => string | number)\n /** Список только для чтения: ни указателем, ни с клавиатуры. */\n disabled?: boolean\n /** Ось переноса. `horizontal` — ряд с переносом по ширине. */\n orientation?: GrSortableOrientation\n /** Поверхность под списком — вариант карточки. */\n variant?: GrCardVariant\n /** Разделители между строками. */\n divided?: boolean\n /** Тянуть можно только за ручку. Выключено — тянется вся строка. */\n handleOnly?: boolean\n /** Высота видимой части: список становится скроллером с автопрокруткой при переносе. */\n maxHeight?: number | string\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Имя списка для скринридера. Не задано — берётся из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSortableListEmits<TItem = unknown> {\n (e: 'update:modelValue', value: TItem[]): void\n (e: 'move', from: number, to: number): void\n (e: 'change', value: TItem[]): void\n}\n\nconst props = withDefaults(defineProps<GrSortableListProps<T>>(), {\n itemKey: undefined,\n disabled: false,\n orientation: 'vertical',\n variant: undefined,\n divided: true,\n handleOnly: true,\n maxHeight: undefined,\n emptyText: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrSortableListEmits<T>>()\n\ndefineSlots<{\n item?: (props: { item: T, index: number, dragging: boolean, grabbed: boolean }) => any\n handle?: (props: { item: T, index: number, disabled: boolean }) => any\n empty?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\n\nconst listEl = ref<HTMLElement | null>(null)\nconst rowEls = new Map<string, HTMLElement>()\n\nconst count = computed(() => props.modelValue.length)\nconst isEmpty = computed(() => count.value === 0)\nconst isVertical = computed(() => props.orientation === 'vertical')\n\nfunction keyOf(item: T, index: number): string {\n if (typeof props.itemKey === 'function')\n return String(props.itemKey(item, index))\n if (typeof props.itemKey === 'string')\n return String((item as Record<string, unknown>)[props.itemKey])\n\n return String(index)\n}\n\nconst keys = computed(() => props.modelValue.map((item, index) => keyOf(item, index)))\n\nfunction indexOfKey(key: string): number {\n return keys.value.indexOf(key)\n}\n\nfunction registerRow(key: string, el: unknown): void {\n if (el instanceof HTMLElement) {\n rowEls.set(key, el)\n return\n }\n\n // Перестановка размонтирует старый узел уже после того, как встал новый:\n // снимаем запись, только если она протухла (приём из `GrTree`).\n const previous = rowEls.get(key)\n if (previous && !previous.isConnected)\n rowEls.delete(key)\n}\n\nconst roving = useRovingFocus<string>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => (isVertical.value ? 'vertical' : 'horizontal'),\n wrap: () => false,\n})\n\nfunction applyMove(from: number, to: number): void {\n if (from < 0 || to < 0 || from === to)\n return\n\n const next = moveItem(props.modelValue, from, to)\n emit('update:modelValue', next)\n emit('move', from, to)\n emit('change', next)\n}\n\nconst sort = useDragSort<string, number>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => props.orientation,\n scroller: () => (props.maxHeight === undefined ? null : listEl.value),\n disabled: () => props.disabled,\n resolveTarget: (hit, source) => insertionIndex(hit, indexOfKey(source), count.value),\n onDrop: (source, to) => applyMove(indexOfKey(source), to),\n onUpdate: (source, target, mode) => {\n // Объявляется только клавиатурный перенос: у мыши всё видно на экране, а\n // поток объявлений на каждом движении указателя делает диктор бесполезным.\n if (mode !== 'keyboard' || source === null)\n return\n\n const position = (target ?? indexOfKey(source)) + 1\n announce(t('gr.sortable.moved', 'Position {position} of {count}', { position, count: count.value }))\n },\n})\n\nconst activeIndex = computed(() => (sort.source.value === null ? -1 : indexOfKey(sort.source.value)))\n\n/** Куда встанет строка: индикатор рисуется на строке-соседе, а не отдельным узлом. */\nfunction indicatorFor(index: number): 'before' | 'after' | null {\n const target = sort.target.value\n if (target === null || !sort.isActive.value || index === activeIndex.value)\n return null\n\n if (target === index)\n return target < activeIndex.value || activeIndex.value === -1 ? 'before' : 'after'\n\n return null\n}\n\nfunction rowClass(index: number, key: string): string[] {\n const grabbed = sort.mode.value === 'keyboard' && sort.source.value === key\n const dragging = sort.mode.value === 'pointer' && sort.source.value === key\n const indicator = indicatorFor(index)\n\n return [\n rowLayoutClass,\n rowFocusClass,\n props.disabled ? rowDisabledClass : '',\n grabbed ? rowGrabbedClass : '',\n dragging ? rowDraggingClass : '',\n indicator === 'before' ? indicatorBeforeClass : '',\n indicator === 'after' ? indicatorAfterClass : '',\n ]\n}\n\nfunction startPointer(key: string, event: PointerEvent): void {\n if (props.disabled)\n return\n\n sort.startFrom(key)(event)\n}\n\nfunction grab(key: string): void {\n sort.grab(key)\n if (sort.mode.value !== 'keyboard')\n return\n\n // Цель ставится до объявления: `setTarget` сам объявляет позицию, и обратный\n // порядок стёр бы более полное сообщение о захвате.\n sort.setTarget(indexOfKey(key))\n announce(t('gr.sortable.grabbed', 'Grabbed. Position {position} of {count}', {\n position: indexOfKey(key) + 1,\n count: count.value,\n }))\n}\n\nasync function drop(key: string): Promise<void> {\n const target = sort.target.value\n sort.drop()\n\n announce(t('gr.sortable.dropped', 'Dropped at position {position} of {count}', {\n position: (target ?? 0) + 1,\n count: count.value,\n }))\n\n // Фокус остаётся на перенесённой строке: иначе после переноса он падает на\n // тело документа и клавиатурный сценарий обрывается на первом же шаге.\n await nextTick()\n await roving.focusKey(key)\n}\n\nfunction cancel(): void {\n if (!sort.isActive.value)\n return\n\n sort.cancel()\n announce(t('gr.sortable.cancelled', 'Move cancelled'))\n}\n\nfunction moveTargetBy(delta: number): void {\n const current = sort.target.value ?? activeIndex.value\n const next = Math.min(count.value - 1, Math.max(0, current + delta))\n\n if (next !== current)\n sort.setTarget(next)\n}\n\nfunction onRowKeydown(event: KeyboardEvent, key: string): void {\n if (props.disabled)\n return\n\n const forward = isVertical.value ? 'ArrowDown' : 'ArrowRight'\n const backward = isVertical.value ? 'ArrowUp' : 'ArrowLeft'\n const grabbed = sort.mode.value === 'keyboard'\n\n if (event.key === 'Escape') {\n if (!grabbed)\n return\n\n event.preventDefault()\n cancel()\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n if (grabbed)\n void drop(key)\n else grab(key)\n return\n }\n\n if (grabbed) {\n // Взятая строка забирает стрелки себе: двигается она, а не фокус.\n if (event.key === forward || event.key === backward) {\n event.preventDefault()\n moveTargetBy(event.key === forward ? 1 : -1)\n }\n return\n }\n\n roving.handleNavigationKeys(event)\n}\n\n/** Фокус ушёл из списка — взятая строка не может остаться взятой навсегда. */\nfunction onFocusout(event: FocusEvent): void {\n if (sort.mode.value !== 'keyboard')\n return\n\n const next = event.relatedTarget as Node | null\n if (next && listEl.value?.contains(next))\n return\n\n cancel()\n}\n\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.sortable.empty', 'Nothing to sort yet'))\nconst resolvedLabel = computed(() => props.ariaLabel ?? t('gr.sortable.label', 'Sortable list'))\nconst handleLabel = computed(() => t('gr.sortable.handle', 'Reorder'))\n\nconst listStyle = computed(() => (props.maxHeight === undefined\n ? undefined\n : { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight, overflow: 'auto' }))\n\ndefineExpose({\n /** Программная перестановка — та же, что делает перенос. */\n move: (from: number, to: number) => applyMove(from, to),\n focusItem: (index: number) => roving.focusKey(keys.value[index]),\n})\n</script>\n\n<template>\n <GrCard :variant=\"variant\">\n <div\n ref=\"listEl\"\n role=\"list\"\n data-gr-sortable\n :aria-label=\"resolvedLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"[listClass[orientation], divided ? dividedClass : '']\"\n :style=\"listStyle\"\n @focusout=\"onFocusout\"\n >\n <div\n v-if=\"isEmpty\"\n data-gr-sortable-empty\n :class=\"emptyClass\"\n >\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-for=\"(item, index) in modelValue\"\n v-else\n :key=\"keys[index]\"\n :ref=\"el => registerRow(keys[index], el)\"\n role=\"listitem\"\n data-gr-sortable-item\n :tabindex=\"disabled ? -1 : roving.tabindexFor(keys[index])\"\n :aria-roledescription=\"handleLabel\"\n :aria-posinset=\"index + 1\"\n :aria-setsize=\"count\"\n :aria-grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index] ? 'true' : undefined\"\n :class=\"rowClass(index, keys[index])\"\n @keydown=\"onRowKeydown($event, keys[index])\"\n @focus=\"roving.setActive(keys[index])\"\n @pointerdown=\"handleOnly ? undefined : startPointer(keys[index], $event)\"\n >\n <button\n type=\"button\"\n tabindex=\"-1\"\n data-gr-sortable-handle\n :class=\"[handleClass, disabled ? handleDisabledClass : '']\"\n :aria-label=\"handleLabel\"\n :disabled=\"disabled\"\n @pointerdown=\"startPointer(keys[index], $event)\"\n @click.stop\n >\n <slot\n name=\"handle\"\n :item=\"item\"\n :index=\"index\"\n :disabled=\"disabled\"\n >\n <IconGripVertical class=\"block\" aria-hidden=\"true\" />\n </slot>\n </button>\n\n <div :class=\"contentClass\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :dragging=\"sort.mode.value === 'pointer' && sort.source.value === keys[index]\"\n :grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index]\"\n >\n {{ item }}\n </slot>\n </div>\n </div>\n </div>\n </GrCard>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GrSortableList-CQCaWivn.js","names":[],"sources":["../../../../src/components/GrSortableList/GrSortableList.vue","../../../../src/components/GrSortableList/GrSortableList.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T\">\nimport { computed, nextTick, ref } from 'vue'\n\nimport GrCard, { type GrCardVariant } from '../GrCard'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useDragSort } from '../../composables/useDragSort'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { insertionIndex, moveItem } from '../../composables/internal/dragSortGeometry'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport type { GrSortableOrientation } from './grSortableListStyles'\nimport {\n contentClass,\n dividedClass,\n emptyClass,\n handleClass,\n handleDisabledClass,\n indicatorAfterClass,\n indicatorBeforeClass,\n listClass,\n rowDisabledClass,\n rowDraggingClass,\n rowFocusClass,\n rowGrabbedClass,\n rowLayoutClass,\n} from './grSortableListStyles'\n\nimport IconGripVertical from '~icons/lucide/grip-vertical'\n\nexport interface GrSortableListProps<TItem = unknown> {\n /** Набор в текущем порядке. `v-model`: наружу уходит новый массив, вход не мутируется. */\n modelValue: TItem[]\n /** Ключ элемента: имя поля или функция. Без него — индекс. */\n itemKey?: string | ((item: TItem, index: number) => string | number)\n /** Список только для чтения: ни указателем, ни с клавиатуры. */\n disabled?: boolean\n /** Ось переноса. `horizontal` — ряд с переносом по ширине. */\n orientation?: GrSortableOrientation\n /** Поверхность под списком — вариант карточки. */\n variant?: GrCardVariant\n /** Разделители между строками. */\n divided?: boolean\n /** Тянуть можно только за ручку. Выключено — тянется вся строка. */\n handleOnly?: boolean\n /** Высота видимой части: список становится скроллером с автопрокруткой при переносе. */\n maxHeight?: number | string\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Имя списка для скринридера. Не задано — берётся из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSortableListEmits<TItem = unknown> {\n (e: 'update:modelValue', value: TItem[]): void\n (e: 'move', from: number, to: number): void\n (e: 'change', value: TItem[]): void\n}\n\nconst props = withDefaults(defineProps<GrSortableListProps<T>>(), {\n itemKey: undefined,\n disabled: false,\n orientation: 'vertical',\n variant: undefined,\n divided: true,\n handleOnly: true,\n maxHeight: undefined,\n emptyText: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrSortableListEmits<T>>()\n\ndefineSlots<{\n item?: (props: { item: T, index: number, dragging: boolean, grabbed: boolean }) => any\n handle?: (props: { item: T, index: number, disabled: boolean }) => any\n empty?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\n\nconst listEl = ref<HTMLElement | null>(null)\nconst rowEls = new Map<string, HTMLElement>()\n\nconst count = computed(() => props.modelValue.length)\nconst isEmpty = computed(() => count.value === 0)\nconst isVertical = computed(() => props.orientation === 'vertical')\n\nfunction keyOf(item: T, index: number): string {\n if (typeof props.itemKey === 'function')\n return String(props.itemKey(item, index))\n if (typeof props.itemKey === 'string')\n return String((item as Record<string, unknown>)[props.itemKey])\n\n return String(index)\n}\n\nconst keys = computed(() => props.modelValue.map((item, index) => keyOf(item, index)))\n\nfunction indexOfKey(key: string): number {\n return keys.value.indexOf(key)\n}\n\nfunction registerRow(key: string, el: unknown): void {\n if (el instanceof HTMLElement) {\n rowEls.set(key, el)\n return\n }\n\n // Перестановка размонтирует старый узел уже после того, как встал новый:\n // снимаем запись, только если она протухла (приём из `GrTree`).\n const previous = rowEls.get(key)\n if (previous && !previous.isConnected)\n rowEls.delete(key)\n}\n\nconst roving = useRovingFocus<string>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => (isVertical.value ? 'vertical' : 'horizontal'),\n wrap: () => false,\n})\n\nfunction applyMove(from: number, to: number): void {\n if (from < 0 || to < 0 || from === to)\n return\n\n const next = moveItem(props.modelValue, from, to)\n emit('update:modelValue', next)\n emit('move', from, to)\n emit('change', next)\n}\n\nconst sort = useDragSort<string, number>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => props.orientation,\n scroller: () => (props.maxHeight === undefined ? null : listEl.value),\n disabled: () => props.disabled,\n resolveTarget: (hit, source) => insertionIndex(hit, indexOfKey(source), count.value),\n onDrop: (source, to) => applyMove(indexOfKey(source), to),\n onUpdate: (source, target, mode) => {\n // Объявляется только клавиатурный перенос: у мыши всё видно на экране, а\n // поток объявлений на каждом движении указателя делает диктор бесполезным.\n if (mode !== 'keyboard' || source === null)\n return\n\n const position = (target ?? indexOfKey(source)) + 1\n announce(t('gr.sortable.moved', 'Position {position} of {count}', { position, count: count.value }))\n },\n})\n\nconst activeIndex = computed(() => (sort.source.value === null ? -1 : indexOfKey(sort.source.value)))\n\n/** Куда встанет строка: индикатор рисуется на строке-соседе, а не отдельным узлом. */\nfunction indicatorFor(index: number): 'before' | 'after' | null {\n const target = sort.target.value\n if (target === null || !sort.isActive.value || index === activeIndex.value)\n return null\n\n if (target === index)\n return target < activeIndex.value || activeIndex.value === -1 ? 'before' : 'after'\n\n return null\n}\n\nfunction rowClass(index: number, key: string): string[] {\n const grabbed = sort.mode.value === 'keyboard' && sort.source.value === key\n const dragging = sort.mode.value === 'pointer' && sort.source.value === key\n const indicator = indicatorFor(index)\n\n return [\n rowLayoutClass,\n rowFocusClass,\n props.disabled ? rowDisabledClass : '',\n grabbed ? rowGrabbedClass : '',\n dragging ? rowDraggingClass : '',\n indicator === 'before' ? indicatorBeforeClass : '',\n indicator === 'after' ? indicatorAfterClass : '',\n ]\n}\n\nfunction startPointer(key: string, event: PointerEvent): void {\n if (props.disabled)\n return\n\n sort.startFrom(key)(event)\n}\n\nfunction grab(key: string): void {\n sort.grab(key)\n if (sort.mode.value !== 'keyboard')\n return\n\n // Цель ставится до объявления: `setTarget` сам объявляет позицию, и обратный\n // порядок стёр бы более полное сообщение о захвате.\n sort.setTarget(indexOfKey(key))\n announce(t('gr.sortable.grabbed', 'Grabbed. Position {position} of {count}', {\n position: indexOfKey(key) + 1,\n count: count.value,\n }))\n}\n\nasync function drop(key: string): Promise<void> {\n const target = sort.target.value\n sort.drop()\n\n announce(t('gr.sortable.dropped', 'Dropped at position {position} of {count}', {\n position: (target ?? 0) + 1,\n count: count.value,\n }))\n\n // Фокус остаётся на перенесённой строке: иначе после переноса он падает на\n // тело документа и клавиатурный сценарий обрывается на первом же шаге.\n await nextTick()\n await roving.focusKey(key)\n}\n\nfunction cancel(): void {\n if (!sort.isActive.value)\n return\n\n sort.cancel()\n announce(t('gr.sortable.cancelled', 'Move cancelled'))\n}\n\nfunction moveTargetBy(delta: number): void {\n const current = sort.target.value ?? activeIndex.value\n const next = Math.min(count.value - 1, Math.max(0, current + delta))\n\n if (next !== current)\n sort.setTarget(next)\n}\n\nfunction onRowKeydown(event: KeyboardEvent, key: string): void {\n if (props.disabled)\n return\n\n const forward = isVertical.value ? 'ArrowDown' : 'ArrowRight'\n const backward = isVertical.value ? 'ArrowUp' : 'ArrowLeft'\n const grabbed = sort.mode.value === 'keyboard'\n\n if (event.key === 'Escape') {\n if (!grabbed)\n return\n\n event.preventDefault()\n cancel()\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n if (grabbed)\n void drop(key)\n else grab(key)\n return\n }\n\n if (grabbed) {\n // Взятая строка забирает стрелки себе: двигается она, а не фокус.\n if (event.key === forward || event.key === backward) {\n event.preventDefault()\n moveTargetBy(event.key === forward ? 1 : -1)\n }\n return\n }\n\n roving.handleNavigationKeys(event)\n}\n\n/** Фокус ушёл из списка — взятая строка не может остаться взятой навсегда. */\nfunction onFocusout(event: FocusEvent): void {\n if (sort.mode.value !== 'keyboard')\n return\n\n const next = event.relatedTarget as Node | null\n if (next && listEl.value?.contains(next))\n return\n\n cancel()\n}\n\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.sortable.empty', 'Nothing to sort yet'))\nconst resolvedLabel = computed(() => props.ariaLabel ?? t('gr.sortable.label', 'Sortable list'))\nconst handleLabel = computed(() => t('gr.sortable.handle', 'Reorder'))\n\nconst listStyle = computed(() => (props.maxHeight === undefined\n ? undefined\n : { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight, overflow: 'auto' }))\n\ndefineExpose({\n /** Программная перестановка — та же, что делает перенос. */\n move: (from: number, to: number) => applyMove(from, to),\n focusItem: (index: number) => roving.focusKey(keys.value[index]),\n})\n</script>\n\n<template>\n <GrCard :variant=\"variant\">\n <div\n ref=\"listEl\"\n role=\"list\"\n data-gr-sortable\n :aria-label=\"resolvedLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"[listClass[orientation], divided ? dividedClass : '']\"\n :style=\"listStyle\"\n @focusout=\"onFocusout\"\n >\n <div\n v-if=\"isEmpty\"\n data-gr-sortable-empty\n :class=\"emptyClass\"\n >\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-for=\"(item, index) in modelValue\"\n v-else\n :key=\"keys[index]\"\n :ref=\"el => registerRow(keys[index], el)\"\n role=\"listitem\"\n data-gr-sortable-item\n :tabindex=\"disabled ? -1 : roving.tabindexFor(keys[index])\"\n :aria-roledescription=\"handleLabel\"\n :aria-posinset=\"index + 1\"\n :aria-setsize=\"count\"\n :aria-grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index] ? 'true' : undefined\"\n :class=\"rowClass(index, keys[index])\"\n @keydown=\"onRowKeydown($event, keys[index])\"\n @focus=\"roving.setActive(keys[index])\"\n @pointerdown=\"handleOnly ? undefined : startPointer(keys[index], $event)\"\n >\n <button\n type=\"button\"\n tabindex=\"-1\"\n data-gr-sortable-handle\n :class=\"[handleClass, disabled ? handleDisabledClass : '']\"\n :aria-label=\"handleLabel\"\n :disabled=\"disabled\"\n @pointerdown=\"startPointer(keys[index], $event)\"\n @click.stop\n >\n <slot\n name=\"handle\"\n :item=\"item\"\n :index=\"index\"\n :disabled=\"disabled\"\n >\n <IconGripVertical class=\"block\" aria-hidden=\"true\" />\n </slot>\n </button>\n\n <div :class=\"contentClass\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :dragging=\"sort.mode.value === 'pointer' && sort.source.value === keys[index]\"\n :grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index]\"\n >\n {{ item }}\n </slot>\n </div>\n </div>\n </div>\n </GrCard>\n</template>\n","<script setup lang=\"ts\" generic=\"T\">\nimport { computed, nextTick, ref } from 'vue'\n\nimport GrCard, { type GrCardVariant } from '../GrCard'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useDragSort } from '../../composables/useDragSort'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { insertionIndex, moveItem } from '../../composables/internal/dragSortGeometry'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport type { GrSortableOrientation } from './grSortableListStyles'\nimport {\n contentClass,\n dividedClass,\n emptyClass,\n handleClass,\n handleDisabledClass,\n indicatorAfterClass,\n indicatorBeforeClass,\n listClass,\n rowDisabledClass,\n rowDraggingClass,\n rowFocusClass,\n rowGrabbedClass,\n rowLayoutClass,\n} from './grSortableListStyles'\n\nimport IconGripVertical from '~icons/lucide/grip-vertical'\n\nexport interface GrSortableListProps<TItem = unknown> {\n /** Набор в текущем порядке. `v-model`: наружу уходит новый массив, вход не мутируется. */\n modelValue: TItem[]\n /** Ключ элемента: имя поля или функция. Без него — индекс. */\n itemKey?: string | ((item: TItem, index: number) => string | number)\n /** Список только для чтения: ни указателем, ни с клавиатуры. */\n disabled?: boolean\n /** Ось переноса. `horizontal` — ряд с переносом по ширине. */\n orientation?: GrSortableOrientation\n /** Поверхность под списком — вариант карточки. */\n variant?: GrCardVariant\n /** Разделители между строками. */\n divided?: boolean\n /** Тянуть можно только за ручку. Выключено — тянется вся строка. */\n handleOnly?: boolean\n /** Высота видимой части: список становится скроллером с автопрокруткой при переносе. */\n maxHeight?: number | string\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Имя списка для скринридера. Не задано — берётся из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSortableListEmits<TItem = unknown> {\n (e: 'update:modelValue', value: TItem[]): void\n (e: 'move', from: number, to: number): void\n (e: 'change', value: TItem[]): void\n}\n\nconst props = withDefaults(defineProps<GrSortableListProps<T>>(), {\n itemKey: undefined,\n disabled: false,\n orientation: 'vertical',\n variant: undefined,\n divided: true,\n handleOnly: true,\n maxHeight: undefined,\n emptyText: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrSortableListEmits<T>>()\n\ndefineSlots<{\n item?: (props: { item: T, index: number, dragging: boolean, grabbed: boolean }) => any\n handle?: (props: { item: T, index: number, disabled: boolean }) => any\n empty?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\n\nconst listEl = ref<HTMLElement | null>(null)\nconst rowEls = new Map<string, HTMLElement>()\n\nconst count = computed(() => props.modelValue.length)\nconst isEmpty = computed(() => count.value === 0)\nconst isVertical = computed(() => props.orientation === 'vertical')\n\nfunction keyOf(item: T, index: number): string {\n if (typeof props.itemKey === 'function')\n return String(props.itemKey(item, index))\n if (typeof props.itemKey === 'string')\n return String((item as Record<string, unknown>)[props.itemKey])\n\n return String(index)\n}\n\nconst keys = computed(() => props.modelValue.map((item, index) => keyOf(item, index)))\n\nfunction indexOfKey(key: string): number {\n return keys.value.indexOf(key)\n}\n\nfunction registerRow(key: string, el: unknown): void {\n if (el instanceof HTMLElement) {\n rowEls.set(key, el)\n return\n }\n\n // Перестановка размонтирует старый узел уже после того, как встал новый:\n // снимаем запись, только если она протухла (приём из `GrTree`).\n const previous = rowEls.get(key)\n if (previous && !previous.isConnected)\n rowEls.delete(key)\n}\n\nconst roving = useRovingFocus<string>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => (isVertical.value ? 'vertical' : 'horizontal'),\n wrap: () => false,\n})\n\nfunction applyMove(from: number, to: number): void {\n if (from < 0 || to < 0 || from === to)\n return\n\n const next = moveItem(props.modelValue, from, to)\n emit('update:modelValue', next)\n emit('move', from, to)\n emit('change', next)\n}\n\nconst sort = useDragSort<string, number>({\n items: () => keys.value,\n elementFor: key => rowEls.get(key) ?? null,\n orientation: () => props.orientation,\n scroller: () => (props.maxHeight === undefined ? null : listEl.value),\n disabled: () => props.disabled,\n resolveTarget: (hit, source) => insertionIndex(hit, indexOfKey(source), count.value),\n onDrop: (source, to) => applyMove(indexOfKey(source), to),\n onUpdate: (source, target, mode) => {\n // Объявляется только клавиатурный перенос: у мыши всё видно на экране, а\n // поток объявлений на каждом движении указателя делает диктор бесполезным.\n if (mode !== 'keyboard' || source === null)\n return\n\n const position = (target ?? indexOfKey(source)) + 1\n announce(t('gr.sortable.moved', 'Position {position} of {count}', { position, count: count.value }))\n },\n})\n\nconst activeIndex = computed(() => (sort.source.value === null ? -1 : indexOfKey(sort.source.value)))\n\n/** Куда встанет строка: индикатор рисуется на строке-соседе, а не отдельным узлом. */\nfunction indicatorFor(index: number): 'before' | 'after' | null {\n const target = sort.target.value\n if (target === null || !sort.isActive.value || index === activeIndex.value)\n return null\n\n if (target === index)\n return target < activeIndex.value || activeIndex.value === -1 ? 'before' : 'after'\n\n return null\n}\n\nfunction rowClass(index: number, key: string): string[] {\n const grabbed = sort.mode.value === 'keyboard' && sort.source.value === key\n const dragging = sort.mode.value === 'pointer' && sort.source.value === key\n const indicator = indicatorFor(index)\n\n return [\n rowLayoutClass,\n rowFocusClass,\n props.disabled ? rowDisabledClass : '',\n grabbed ? rowGrabbedClass : '',\n dragging ? rowDraggingClass : '',\n indicator === 'before' ? indicatorBeforeClass : '',\n indicator === 'after' ? indicatorAfterClass : '',\n ]\n}\n\nfunction startPointer(key: string, event: PointerEvent): void {\n if (props.disabled)\n return\n\n sort.startFrom(key)(event)\n}\n\nfunction grab(key: string): void {\n sort.grab(key)\n if (sort.mode.value !== 'keyboard')\n return\n\n // Цель ставится до объявления: `setTarget` сам объявляет позицию, и обратный\n // порядок стёр бы более полное сообщение о захвате.\n sort.setTarget(indexOfKey(key))\n announce(t('gr.sortable.grabbed', 'Grabbed. Position {position} of {count}', {\n position: indexOfKey(key) + 1,\n count: count.value,\n }))\n}\n\nasync function drop(key: string): Promise<void> {\n const target = sort.target.value\n sort.drop()\n\n announce(t('gr.sortable.dropped', 'Dropped at position {position} of {count}', {\n position: (target ?? 0) + 1,\n count: count.value,\n }))\n\n // Фокус остаётся на перенесённой строке: иначе после переноса он падает на\n // тело документа и клавиатурный сценарий обрывается на первом же шаге.\n await nextTick()\n await roving.focusKey(key)\n}\n\nfunction cancel(): void {\n if (!sort.isActive.value)\n return\n\n sort.cancel()\n announce(t('gr.sortable.cancelled', 'Move cancelled'))\n}\n\nfunction moveTargetBy(delta: number): void {\n const current = sort.target.value ?? activeIndex.value\n const next = Math.min(count.value - 1, Math.max(0, current + delta))\n\n if (next !== current)\n sort.setTarget(next)\n}\n\nfunction onRowKeydown(event: KeyboardEvent, key: string): void {\n if (props.disabled)\n return\n\n const forward = isVertical.value ? 'ArrowDown' : 'ArrowRight'\n const backward = isVertical.value ? 'ArrowUp' : 'ArrowLeft'\n const grabbed = sort.mode.value === 'keyboard'\n\n if (event.key === 'Escape') {\n if (!grabbed)\n return\n\n event.preventDefault()\n cancel()\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n if (grabbed)\n void drop(key)\n else grab(key)\n return\n }\n\n if (grabbed) {\n // Взятая строка забирает стрелки себе: двигается она, а не фокус.\n if (event.key === forward || event.key === backward) {\n event.preventDefault()\n moveTargetBy(event.key === forward ? 1 : -1)\n }\n return\n }\n\n roving.handleNavigationKeys(event)\n}\n\n/** Фокус ушёл из списка — взятая строка не может остаться взятой навсегда. */\nfunction onFocusout(event: FocusEvent): void {\n if (sort.mode.value !== 'keyboard')\n return\n\n const next = event.relatedTarget as Node | null\n if (next && listEl.value?.contains(next))\n return\n\n cancel()\n}\n\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.sortable.empty', 'Nothing to sort yet'))\nconst resolvedLabel = computed(() => props.ariaLabel ?? t('gr.sortable.label', 'Sortable list'))\nconst handleLabel = computed(() => t('gr.sortable.handle', 'Reorder'))\n\nconst listStyle = computed(() => (props.maxHeight === undefined\n ? undefined\n : { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight, overflow: 'auto' }))\n\ndefineExpose({\n /** Программная перестановка — та же, что делает перенос. */\n move: (from: number, to: number) => applyMove(from, to),\n focusItem: (index: number) => roving.focusKey(keys.value[index]),\n})\n</script>\n\n<template>\n <GrCard :variant=\"variant\">\n <div\n ref=\"listEl\"\n role=\"list\"\n data-gr-sortable\n :aria-label=\"resolvedLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"[listClass[orientation], divided ? dividedClass : '']\"\n :style=\"listStyle\"\n @focusout=\"onFocusout\"\n >\n <div\n v-if=\"isEmpty\"\n data-gr-sortable-empty\n :class=\"emptyClass\"\n >\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-for=\"(item, index) in modelValue\"\n v-else\n :key=\"keys[index]\"\n :ref=\"el => registerRow(keys[index], el)\"\n role=\"listitem\"\n data-gr-sortable-item\n :tabindex=\"disabled ? -1 : roving.tabindexFor(keys[index])\"\n :aria-roledescription=\"handleLabel\"\n :aria-posinset=\"index + 1\"\n :aria-setsize=\"count\"\n :aria-grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index] ? 'true' : undefined\"\n :class=\"rowClass(index, keys[index])\"\n @keydown=\"onRowKeydown($event, keys[index])\"\n @focus=\"roving.setActive(keys[index])\"\n @pointerdown=\"handleOnly ? undefined : startPointer(keys[index], $event)\"\n >\n <button\n type=\"button\"\n tabindex=\"-1\"\n data-gr-sortable-handle\n :class=\"[handleClass, disabled ? handleDisabledClass : '']\"\n :aria-label=\"handleLabel\"\n :disabled=\"disabled\"\n @pointerdown=\"startPointer(keys[index], $event)\"\n @click.stop\n >\n <slot\n name=\"handle\"\n :item=\"item\"\n :index=\"index\"\n :disabled=\"disabled\"\n >\n <IconGripVertical class=\"block\" aria-hidden=\"true\" />\n </slot>\n </button>\n\n <div :class=\"contentClass\">\n <slot\n name=\"item\"\n :item=\"item\"\n :index=\"index\"\n :dragging=\"sort.mode.value === 'pointer' && sort.source.value === keys[index]\"\n :grabbed=\"sort.mode.value === 'keyboard' && sort.source.value === keys[index]\"\n >\n {{ item }}\n </slot>\n </div>\n </div>\n </div>\n </GrCard>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as grSortableListSafelist, t as grSortableListConfig } from "../../chunks/config-CbEbLyDE.js";
|
|
2
|
-
import { t as GrSortableList_default } from "./chunks/GrSortableList-
|
|
2
|
+
import { t as GrSortableList_default } from "./chunks/GrSortableList-CQCaWivn.js";
|
|
3
3
|
export { GrSortableList_default as GrSortableList, GrSortableList_default as default, grSortableListConfig, grSortableListSafelist };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as useGrComponentProp } from "../../../chunks/context-
|
|
1
|
+
import { i as useGrComponentProp } from "../../../chunks/context-CPMRfwVr.js";
|
|
2
2
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
3
3
|
import { useDragGesture } from "../../../composables/useDragGesture.js";
|
|
4
4
|
import { a as separatorClass, i as rootClass, r as paneClass } from "../../../chunks/config-CvbVM4ep.js";
|
package/dist/components/GrSplitter/chunks/{GrSplitter-MltjaADn.js.map → GrSplitter-C-XQzq7q.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrSplitter-MltjaADn.js","names":[],"sources":["../../../../src/components/GrSplitter/splitterGeometry.ts","../../../../src/components/GrSplitter/GrSplitter.vue","../../../../src/components/GrSplitter/GrSplitter.vue"],"sourcesContent":["/**\n * Арифметика раздвижных панелей. Без Vue — проверяется без монтирования.\n *\n * Всё считается в процентах ширины (или высоты) контейнера: клавиатура,\n * границы и сворачивание работают без единого замера DOM, а серверный рендер\n * совпадает с клиентским. Замер нужен ровно в одном месте — перевод координаты\n * указателя в проценты.\n */\n\nexport const GR_SPLITTER_ORIENTATIONS = ['horizontal', 'vertical'] as const\n\nexport type GrSplitterOrientation = typeof GR_SPLITTER_ORIENTATIONS[number]\n\nexport interface GrSplitterBounds {\n /** Минимум первой панели. */\n min: number\n /** Максимум первой панели. */\n max: number\n /** Минимум второй панели: без него её можно задавить в ноль. */\n minEnd: number\n}\n\nfunction toFinite(value: number, fallback: number): number {\n return Number.isFinite(value) ? value : fallback\n}\n\n/**\n * Приводит долю первой панели к допустимой.\n *\n * При конфликте `min` и `minEnd` побеждает `min`: первая панель не должна\n * уезжать под свой минимум, даже если вторая при этом окажется уже своего.\n * Обратный порядок дал бы панель, которую пользователь не может вернуть.\n */\nexport function clampSize(value: number, bounds: GrSplitterBounds): number {\n const min = Math.min(100, Math.max(0, toFinite(bounds.min, 0)))\n const max = Math.min(100, Math.max(min, toFinite(bounds.max, 100)))\n const minEnd = Math.min(100, Math.max(0, toFinite(bounds.minEnd, 0)))\n\n const upper = Math.max(min, Math.min(max, 100 - minEnd))\n\n return Math.min(upper, Math.max(min, toFinite(value, min)))\n}\n\n/** Доля, соответствующая позиции указателя. Вне контейнера — его края. */\nexport function sizeFromPointer(\n rect: { left: number, top: number, width: number, height: number },\n clientX: number,\n clientY: number,\n orientation: GrSplitterOrientation,\n): number {\n const total = orientation === 'horizontal' ? rect.width : rect.height\n // Схлопнутый контейнер (ещё не в раскладке, `display: none`) — делить не на что.\n if (!(total > 0))\n return 0\n\n const offset = orientation === 'horizontal' ? clientX - rect.left : clientY - rect.top\n\n return Math.min(100, Math.max(0, (offset / total) * 100))\n}\n\n/**\n * Тянуть панель ниже половины её минимума пользователь может только с одним\n * намерением — убрать её совсем. Это единственный способ свернуть панель\n * мышью: двойной клик занят сбросом к дефолту, `Enter` — клавиатурой.\n */\nexport function shouldCollapse(value: number, bounds: GrSplitterBounds): boolean {\n const min = Math.min(100, Math.max(0, toFinite(bounds.min, 0)))\n if (min <= 0)\n return false\n\n return toFinite(value, min) < min / 2\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useDragGesture } from '../../composables/useDragGesture'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { paneClass, rootClass, separatorClass } from './grSplitterStyles'\nimport {\n clampSize,\n shouldCollapse,\n sizeFromPointer,\n type GrSplitterBounds,\n type GrSplitterOrientation,\n} from './splitterGeometry'\n\nexport type { GrSplitterOrientation } from './splitterGeometry'\n\n/**\n * Пропы {@link GrSplitter}.\n *\n * Две панели и разделитель между ними. Размер первой панели — доля контейнера\n * в процентах: она переживает смену ширины окна и рендерится на сервере без\n * замеров.\n */\nexport interface GrSplitterProps {\n /** Доля первой панели в процентах. Поддерживает `v-model`; без него компонент помнит размер сам. */\n modelValue?: number\n /** Стартовая доля и точка возврата по двойному клику. */\n defaultSize?: number\n /** `horizontal` — панели рядом, `vertical` — одна над другой. */\n orientation?: GrSplitterOrientation\n /** Минимум первой панели в процентах. */\n min?: number\n /** Максимум первой панели в процентах. */\n max?: number\n /** Минимум второй панели: без него её можно задавить в ноль. */\n minEnd?: number\n /** Шаг стрелок. */\n step?: number\n /** Шаг стрелок с `Shift`. */\n bigStep?: number\n /** Разрешить сворачивание первой панели. */\n collapsible?: boolean\n /** Первая панель свёрнута. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Разделитель не тянется, не фокусируется и не отвечает на клавиши. */\n disabled?: boolean\n /** Имя разделителя для скринридера. Не задано — из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSplitterEmits {\n (e: 'update:modelValue', value: number): void\n (e: 'update:collapsed', value: boolean): void\n /** Конец жеста и каждый шаг с клавиатуры: сюда вешают сохранение раскладки. */\n (e: 'change', value: number): void\n}\n\nconst props = withDefaults(defineProps<GrSplitterProps>(), {\n modelValue: undefined,\n defaultSize: 50,\n min: 10,\n max: 90,\n minEnd: 10,\n step: 1,\n bigStep: 10,\n collapsed: false,\n disabled: false,\n ariaLabel: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n orientation: undefined,\n collapsible: undefined,\n})\n\nconst emit = defineEmits<GrSplitterEmits>()\n\ndefineSlots<{\n /** Первая панель — та, чей размер задаёт модель. */\n start?: () => any\n /** Вторая панель: занимает остаток. */\n end?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst orientation = useGrComponentProp('GrSplitter', 'orientation', () => props.orientation, 'horizontal')\nconst collapsible = useGrComponentProp('GrSplitter', 'collapsible', () => props.collapsible, false)\n\nconst startId = useId()\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst bounds = computed<GrSplitterBounds>(() => ({\n min: props.min,\n max: props.max,\n minEnd: props.minEnd,\n}))\n\n/**\n * Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n * (`v-model`), и uncontrolled (сплиттер помнит размер сам), как `collapsed`\n * у `GrSidebar`.\n */\nconst sizeState = ref(clampSize(props.modelValue ?? props.defaultSize, bounds.value))\nwatch(() => props.modelValue, (value) => {\n if (value !== undefined)\n sizeState.value = clampSize(value, bounds.value)\n})\n\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\n/** Размер, к которому возвращает `Enter`: свёрнутость не должна его терять. */\nconst restoreSize = ref(sizeState.value)\n\n/** Значение до начала жеста: `pointercancel` откатывает к нему. */\nlet sizeBeforeDrag = sizeState.value\nlet collapsedBeforeDrag = false\n\nconst isCollapsed = computed(() => collapsible.value && collapsedState.value)\n\n/** Что видно на экране: свёрнутая панель — это ноль в треке, но не ноль в модели. */\nconst renderedSize = computed(() => (isCollapsed.value ? 0 : clampSize(sizeState.value, bounds.value)))\n\nconst gridStyle = computed(() => {\n const track = `${renderedSize.value}% var(--gr-splitter-size, 6px) 1fr`\n\n return orientation.value === 'horizontal'\n ? { gridTemplateColumns: track }\n : { gridTemplateRows: track }\n})\n\n/**\n * `aria-orientation` описывает **сам разделитель**, а не раскладку: панели,\n * стоящие рядом, разделяет вертикальная полоса.\n */\nconst separatorOrientation = computed(() => (orientation.value === 'horizontal' ? 'vertical' : 'horizontal'))\n\nconst label = computed(() => props.ariaLabel ?? t('gr.splitter.label', 'Resize panels'))\n\nfunction setSize(next: number, commit: boolean): void {\n const value = clampSize(next, bounds.value)\n const changed = value !== sizeState.value\n\n sizeState.value = value\n if (changed)\n emit('update:modelValue', value)\n if (commit)\n emit('change', value)\n}\n\nfunction setCollapsed(value: boolean): void {\n if (collapsedState.value === value)\n return\n\n collapsedState.value = value\n emit('update:collapsed', value)\n}\n\n/**\n * Шаг размера. Свёрнутая панель на первое нажатие возвращается — двигать\n * то, чего не видно, значит менять раскладку вслепую.\n */\nfunction moveBy(delta: number): void {\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = clampSize(sizeState.value + delta, bounds.value)\n setSize(sizeState.value + delta, true)\n}\n\nfunction toggleCollapsed(): void {\n if (!collapsible.value)\n return\n\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = sizeState.value\n setCollapsed(true)\n emit('change', 0)\n}\n\nfunction reset(): void {\n setCollapsed(false)\n restoreSize.value = clampSize(props.defaultSize, bounds.value)\n setSize(props.defaultSize, true)\n}\n\n// ————— Указатель.\nfunction onPointerMove(event: PointerEvent): void {\n const rect = rootEl.value?.getBoundingClientRect()\n if (!rect)\n return\n\n // Против выделения текста под курсором во время жеста.\n event.preventDefault()\n\n const raw = sizeFromPointer(rect, event.clientX, event.clientY, orientation.value)\n\n if (collapsible.value && shouldCollapse(raw, bounds.value)) {\n if (!collapsedState.value)\n restoreSize.value = sizeState.value\n setCollapsed(true)\n return\n }\n\n setCollapsed(false)\n restoreSize.value = clampSize(raw, bounds.value)\n setSize(raw, false)\n}\n\nconst { isDragging, start: onPointerDown } = useDragGesture({\n disabled: () => props.disabled,\n onStart: () => {\n sizeBeforeDrag = sizeState.value\n collapsedBeforeDrag = collapsedState.value\n },\n onMove: onPointerMove,\n onEnd: () => emit('change', renderedSize.value),\n // Оборванный жест (браузер забрал указатель) не коммитит ничего: раскладка\n // возвращается к той, что была до нажатия.\n onCancel: () => {\n setCollapsed(collapsedBeforeDrag)\n setSize(sizeBeforeDrag, false)\n },\n})\n\n// ————— Клавиатура.\nconst decreaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowLeft' : 'ArrowUp'))\nconst increaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowRight' : 'ArrowDown'))\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.disabled)\n return\n\n const step = event.shiftKey ? props.bigStep : props.step\n\n if (event.key === decreaseKey.value)\n moveBy(-step)\n else if (event.key === increaseKey.value)\n moveBy(step)\n else if (event.key === 'Home')\n moveBy(-100)\n else if (event.key === 'End')\n moveBy(100)\n else if (event.key === 'Enter')\n toggleCollapsed()\n else return\n\n // Дошли сюда — клавиша наша: страница не должна ещё и прокрутиться.\n event.preventDefault()\n}\n\nfunction onDoubleClick(): void {\n if (props.disabled)\n return\n\n reset()\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-splitter\n :data-orientation=\"orientation\"\n :data-dragging=\"isDragging ? '' : undefined\"\n :data-collapsed=\"isCollapsed ? '' : undefined\"\n :class=\"rootClass\"\n :style=\"gridStyle\"\n >\n <div\n :id=\"startId\"\n data-gr-splitter-pane=\"start\"\n :class=\"paneClass\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n data-gr-splitter-separator\n role=\"separator\"\n :tabindex=\"disabled ? undefined : 0\"\n :aria-orientation=\"separatorOrientation\"\n :aria-label=\"label\"\n :aria-controls=\"startId\"\n :aria-valuenow=\"Math.round(renderedSize)\"\n :aria-valuemin=\"Math.round(min)\"\n :aria-valuemax=\"Math.round(max)\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"separatorClass\"\n @pointerdown=\"onPointerDown\"\n @keydown=\"onKeydown\"\n @dblclick=\"onDoubleClick\"\n />\n\n <div\n data-gr-splitter-pane=\"end\"\n :class=\"paneClass\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-splitter-separator] {\n background-color: var(--gr-splitter-color, var(--gr-brd));\n}\n\n/*\n * Зона захвата шире видимой полосы: шесть пикселей мышью не берутся, а делать\n * ради этого полосу толще — значит красить раскладку под удобство мыши.\n */\n[data-gr-splitter-separator]::before {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--gr-splitter-hit, 4px));\n}\n\n/* Насечка: короткая полоса посередине — единственный видимый намёк, что это ручка. */\n[data-gr-splitter-separator]::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n border-radius: var(--gr-radius-full);\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n opacity: 0;\n transform: translate(-50%, -50%);\n transition: opacity var(--gr-duration-fast) var(--gr-ease-out);\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator] {\n cursor: col-resize;\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator]::after {\n width: 2px;\n height: var(--gr-splitter-grip, 24px);\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator] {\n cursor: row-resize;\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator]::after {\n width: var(--gr-splitter-grip, 24px);\n height: 2px;\n}\n\n[data-gr-splitter-separator]:hover {\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n}\n\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter-separator]:focus-visible::after {\n opacity: 1;\n}\n\n/* На залитой полосе насечка читается только вырезом — цветом страницы. */\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n background-color: var(--gr-bg);\n}\n\n/* Во время жеста полоса подсвечена, даже если курсор ушёл с неё. */\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator] {\n background-color: var(--gr-splitter-active-color, var(--gr-primary));\n}\n\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n opacity: 1;\n}\n\n/* Жест не должен попутно выделять текст в панелях. */\n[data-gr-splitter][data-dragging] {\n user-select: none;\n}\n\n[data-gr-splitter-separator][aria-disabled='true'] {\n cursor: default;\n}\n\n[data-gr-splitter-separator][aria-disabled='true']::after {\n display: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useDragGesture } from '../../composables/useDragGesture'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { paneClass, rootClass, separatorClass } from './grSplitterStyles'\nimport {\n clampSize,\n shouldCollapse,\n sizeFromPointer,\n type GrSplitterBounds,\n type GrSplitterOrientation,\n} from './splitterGeometry'\n\nexport type { GrSplitterOrientation } from './splitterGeometry'\n\n/**\n * Пропы {@link GrSplitter}.\n *\n * Две панели и разделитель между ними. Размер первой панели — доля контейнера\n * в процентах: она переживает смену ширины окна и рендерится на сервере без\n * замеров.\n */\nexport interface GrSplitterProps {\n /** Доля первой панели в процентах. Поддерживает `v-model`; без него компонент помнит размер сам. */\n modelValue?: number\n /** Стартовая доля и точка возврата по двойному клику. */\n defaultSize?: number\n /** `horizontal` — панели рядом, `vertical` — одна над другой. */\n orientation?: GrSplitterOrientation\n /** Минимум первой панели в процентах. */\n min?: number\n /** Максимум первой панели в процентах. */\n max?: number\n /** Минимум второй панели: без него её можно задавить в ноль. */\n minEnd?: number\n /** Шаг стрелок. */\n step?: number\n /** Шаг стрелок с `Shift`. */\n bigStep?: number\n /** Разрешить сворачивание первой панели. */\n collapsible?: boolean\n /** Первая панель свёрнута. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Разделитель не тянется, не фокусируется и не отвечает на клавиши. */\n disabled?: boolean\n /** Имя разделителя для скринридера. Не задано — из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSplitterEmits {\n (e: 'update:modelValue', value: number): void\n (e: 'update:collapsed', value: boolean): void\n /** Конец жеста и каждый шаг с клавиатуры: сюда вешают сохранение раскладки. */\n (e: 'change', value: number): void\n}\n\nconst props = withDefaults(defineProps<GrSplitterProps>(), {\n modelValue: undefined,\n defaultSize: 50,\n min: 10,\n max: 90,\n minEnd: 10,\n step: 1,\n bigStep: 10,\n collapsed: false,\n disabled: false,\n ariaLabel: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n orientation: undefined,\n collapsible: undefined,\n})\n\nconst emit = defineEmits<GrSplitterEmits>()\n\ndefineSlots<{\n /** Первая панель — та, чей размер задаёт модель. */\n start?: () => any\n /** Вторая панель: занимает остаток. */\n end?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst orientation = useGrComponentProp('GrSplitter', 'orientation', () => props.orientation, 'horizontal')\nconst collapsible = useGrComponentProp('GrSplitter', 'collapsible', () => props.collapsible, false)\n\nconst startId = useId()\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst bounds = computed<GrSplitterBounds>(() => ({\n min: props.min,\n max: props.max,\n minEnd: props.minEnd,\n}))\n\n/**\n * Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n * (`v-model`), и uncontrolled (сплиттер помнит размер сам), как `collapsed`\n * у `GrSidebar`.\n */\nconst sizeState = ref(clampSize(props.modelValue ?? props.defaultSize, bounds.value))\nwatch(() => props.modelValue, (value) => {\n if (value !== undefined)\n sizeState.value = clampSize(value, bounds.value)\n})\n\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\n/** Размер, к которому возвращает `Enter`: свёрнутость не должна его терять. */\nconst restoreSize = ref(sizeState.value)\n\n/** Значение до начала жеста: `pointercancel` откатывает к нему. */\nlet sizeBeforeDrag = sizeState.value\nlet collapsedBeforeDrag = false\n\nconst isCollapsed = computed(() => collapsible.value && collapsedState.value)\n\n/** Что видно на экране: свёрнутая панель — это ноль в треке, но не ноль в модели. */\nconst renderedSize = computed(() => (isCollapsed.value ? 0 : clampSize(sizeState.value, bounds.value)))\n\nconst gridStyle = computed(() => {\n const track = `${renderedSize.value}% var(--gr-splitter-size, 6px) 1fr`\n\n return orientation.value === 'horizontal'\n ? { gridTemplateColumns: track }\n : { gridTemplateRows: track }\n})\n\n/**\n * `aria-orientation` описывает **сам разделитель**, а не раскладку: панели,\n * стоящие рядом, разделяет вертикальная полоса.\n */\nconst separatorOrientation = computed(() => (orientation.value === 'horizontal' ? 'vertical' : 'horizontal'))\n\nconst label = computed(() => props.ariaLabel ?? t('gr.splitter.label', 'Resize panels'))\n\nfunction setSize(next: number, commit: boolean): void {\n const value = clampSize(next, bounds.value)\n const changed = value !== sizeState.value\n\n sizeState.value = value\n if (changed)\n emit('update:modelValue', value)\n if (commit)\n emit('change', value)\n}\n\nfunction setCollapsed(value: boolean): void {\n if (collapsedState.value === value)\n return\n\n collapsedState.value = value\n emit('update:collapsed', value)\n}\n\n/**\n * Шаг размера. Свёрнутая панель на первое нажатие возвращается — двигать\n * то, чего не видно, значит менять раскладку вслепую.\n */\nfunction moveBy(delta: number): void {\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = clampSize(sizeState.value + delta, bounds.value)\n setSize(sizeState.value + delta, true)\n}\n\nfunction toggleCollapsed(): void {\n if (!collapsible.value)\n return\n\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = sizeState.value\n setCollapsed(true)\n emit('change', 0)\n}\n\nfunction reset(): void {\n setCollapsed(false)\n restoreSize.value = clampSize(props.defaultSize, bounds.value)\n setSize(props.defaultSize, true)\n}\n\n// ————— Указатель.\nfunction onPointerMove(event: PointerEvent): void {\n const rect = rootEl.value?.getBoundingClientRect()\n if (!rect)\n return\n\n // Против выделения текста под курсором во время жеста.\n event.preventDefault()\n\n const raw = sizeFromPointer(rect, event.clientX, event.clientY, orientation.value)\n\n if (collapsible.value && shouldCollapse(raw, bounds.value)) {\n if (!collapsedState.value)\n restoreSize.value = sizeState.value\n setCollapsed(true)\n return\n }\n\n setCollapsed(false)\n restoreSize.value = clampSize(raw, bounds.value)\n setSize(raw, false)\n}\n\nconst { isDragging, start: onPointerDown } = useDragGesture({\n disabled: () => props.disabled,\n onStart: () => {\n sizeBeforeDrag = sizeState.value\n collapsedBeforeDrag = collapsedState.value\n },\n onMove: onPointerMove,\n onEnd: () => emit('change', renderedSize.value),\n // Оборванный жест (браузер забрал указатель) не коммитит ничего: раскладка\n // возвращается к той, что была до нажатия.\n onCancel: () => {\n setCollapsed(collapsedBeforeDrag)\n setSize(sizeBeforeDrag, false)\n },\n})\n\n// ————— Клавиатура.\nconst decreaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowLeft' : 'ArrowUp'))\nconst increaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowRight' : 'ArrowDown'))\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.disabled)\n return\n\n const step = event.shiftKey ? props.bigStep : props.step\n\n if (event.key === decreaseKey.value)\n moveBy(-step)\n else if (event.key === increaseKey.value)\n moveBy(step)\n else if (event.key === 'Home')\n moveBy(-100)\n else if (event.key === 'End')\n moveBy(100)\n else if (event.key === 'Enter')\n toggleCollapsed()\n else return\n\n // Дошли сюда — клавиша наша: страница не должна ещё и прокрутиться.\n event.preventDefault()\n}\n\nfunction onDoubleClick(): void {\n if (props.disabled)\n return\n\n reset()\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-splitter\n :data-orientation=\"orientation\"\n :data-dragging=\"isDragging ? '' : undefined\"\n :data-collapsed=\"isCollapsed ? '' : undefined\"\n :class=\"rootClass\"\n :style=\"gridStyle\"\n >\n <div\n :id=\"startId\"\n data-gr-splitter-pane=\"start\"\n :class=\"paneClass\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n data-gr-splitter-separator\n role=\"separator\"\n :tabindex=\"disabled ? undefined : 0\"\n :aria-orientation=\"separatorOrientation\"\n :aria-label=\"label\"\n :aria-controls=\"startId\"\n :aria-valuenow=\"Math.round(renderedSize)\"\n :aria-valuemin=\"Math.round(min)\"\n :aria-valuemax=\"Math.round(max)\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"separatorClass\"\n @pointerdown=\"onPointerDown\"\n @keydown=\"onKeydown\"\n @dblclick=\"onDoubleClick\"\n />\n\n <div\n data-gr-splitter-pane=\"end\"\n :class=\"paneClass\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-splitter-separator] {\n background-color: var(--gr-splitter-color, var(--gr-brd));\n}\n\n/*\n * Зона захвата шире видимой полосы: шесть пикселей мышью не берутся, а делать\n * ради этого полосу толще — значит красить раскладку под удобство мыши.\n */\n[data-gr-splitter-separator]::before {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--gr-splitter-hit, 4px));\n}\n\n/* Насечка: короткая полоса посередине — единственный видимый намёк, что это ручка. */\n[data-gr-splitter-separator]::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n border-radius: var(--gr-radius-full);\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n opacity: 0;\n transform: translate(-50%, -50%);\n transition: opacity var(--gr-duration-fast) var(--gr-ease-out);\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator] {\n cursor: col-resize;\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator]::after {\n width: 2px;\n height: var(--gr-splitter-grip, 24px);\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator] {\n cursor: row-resize;\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator]::after {\n width: var(--gr-splitter-grip, 24px);\n height: 2px;\n}\n\n[data-gr-splitter-separator]:hover {\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n}\n\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter-separator]:focus-visible::after {\n opacity: 1;\n}\n\n/* На залитой полосе насечка читается только вырезом — цветом страницы. */\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n background-color: var(--gr-bg);\n}\n\n/* Во время жеста полоса подсвечена, даже если курсор ушёл с неё. */\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator] {\n background-color: var(--gr-splitter-active-color, var(--gr-primary));\n}\n\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n opacity: 1;\n}\n\n/* Жест не должен попутно выделять текст в панелях. */\n[data-gr-splitter][data-dragging] {\n user-select: none;\n}\n\n[data-gr-splitter-separator][aria-disabled='true'] {\n cursor: default;\n}\n\n[data-gr-splitter-separator][aria-disabled='true']::after {\n display: none;\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GrSplitter-C-XQzq7q.js","names":[],"sources":["../../../../src/components/GrSplitter/splitterGeometry.ts","../../../../src/components/GrSplitter/GrSplitter.vue","../../../../src/components/GrSplitter/GrSplitter.vue"],"sourcesContent":["/**\n * Арифметика раздвижных панелей. Без Vue — проверяется без монтирования.\n *\n * Всё считается в процентах ширины (или высоты) контейнера: клавиатура,\n * границы и сворачивание работают без единого замера DOM, а серверный рендер\n * совпадает с клиентским. Замер нужен ровно в одном месте — перевод координаты\n * указателя в проценты.\n */\n\nexport const GR_SPLITTER_ORIENTATIONS = ['horizontal', 'vertical'] as const\n\nexport type GrSplitterOrientation = typeof GR_SPLITTER_ORIENTATIONS[number]\n\nexport interface GrSplitterBounds {\n /** Минимум первой панели. */\n min: number\n /** Максимум первой панели. */\n max: number\n /** Минимум второй панели: без него её можно задавить в ноль. */\n minEnd: number\n}\n\nfunction toFinite(value: number, fallback: number): number {\n return Number.isFinite(value) ? value : fallback\n}\n\n/**\n * Приводит долю первой панели к допустимой.\n *\n * При конфликте `min` и `minEnd` побеждает `min`: первая панель не должна\n * уезжать под свой минимум, даже если вторая при этом окажется уже своего.\n * Обратный порядок дал бы панель, которую пользователь не может вернуть.\n */\nexport function clampSize(value: number, bounds: GrSplitterBounds): number {\n const min = Math.min(100, Math.max(0, toFinite(bounds.min, 0)))\n const max = Math.min(100, Math.max(min, toFinite(bounds.max, 100)))\n const minEnd = Math.min(100, Math.max(0, toFinite(bounds.minEnd, 0)))\n\n const upper = Math.max(min, Math.min(max, 100 - minEnd))\n\n return Math.min(upper, Math.max(min, toFinite(value, min)))\n}\n\n/** Доля, соответствующая позиции указателя. Вне контейнера — его края. */\nexport function sizeFromPointer(\n rect: { left: number, top: number, width: number, height: number },\n clientX: number,\n clientY: number,\n orientation: GrSplitterOrientation,\n): number {\n const total = orientation === 'horizontal' ? rect.width : rect.height\n // Схлопнутый контейнер (ещё не в раскладке, `display: none`) — делить не на что.\n if (!(total > 0))\n return 0\n\n const offset = orientation === 'horizontal' ? clientX - rect.left : clientY - rect.top\n\n return Math.min(100, Math.max(0, (offset / total) * 100))\n}\n\n/**\n * Тянуть панель ниже половины её минимума пользователь может только с одним\n * намерением — убрать её совсем. Это единственный способ свернуть панель\n * мышью: двойной клик занят сбросом к дефолту, `Enter` — клавиатурой.\n */\nexport function shouldCollapse(value: number, bounds: GrSplitterBounds): boolean {\n const min = Math.min(100, Math.max(0, toFinite(bounds.min, 0)))\n if (min <= 0)\n return false\n\n return toFinite(value, min) < min / 2\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useDragGesture } from '../../composables/useDragGesture'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { paneClass, rootClass, separatorClass } from './grSplitterStyles'\nimport {\n clampSize,\n shouldCollapse,\n sizeFromPointer,\n type GrSplitterBounds,\n type GrSplitterOrientation,\n} from './splitterGeometry'\n\nexport type { GrSplitterOrientation } from './splitterGeometry'\n\n/**\n * Пропы {@link GrSplitter}.\n *\n * Две панели и разделитель между ними. Размер первой панели — доля контейнера\n * в процентах: она переживает смену ширины окна и рендерится на сервере без\n * замеров.\n */\nexport interface GrSplitterProps {\n /** Доля первой панели в процентах. Поддерживает `v-model`; без него компонент помнит размер сам. */\n modelValue?: number\n /** Стартовая доля и точка возврата по двойному клику. */\n defaultSize?: number\n /** `horizontal` — панели рядом, `vertical` — одна над другой. */\n orientation?: GrSplitterOrientation\n /** Минимум первой панели в процентах. */\n min?: number\n /** Максимум первой панели в процентах. */\n max?: number\n /** Минимум второй панели: без него её можно задавить в ноль. */\n minEnd?: number\n /** Шаг стрелок. */\n step?: number\n /** Шаг стрелок с `Shift`. */\n bigStep?: number\n /** Разрешить сворачивание первой панели. */\n collapsible?: boolean\n /** Первая панель свёрнута. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Разделитель не тянется, не фокусируется и не отвечает на клавиши. */\n disabled?: boolean\n /** Имя разделителя для скринридера. Не задано — из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSplitterEmits {\n (e: 'update:modelValue', value: number): void\n (e: 'update:collapsed', value: boolean): void\n /** Конец жеста и каждый шаг с клавиатуры: сюда вешают сохранение раскладки. */\n (e: 'change', value: number): void\n}\n\nconst props = withDefaults(defineProps<GrSplitterProps>(), {\n modelValue: undefined,\n defaultSize: 50,\n min: 10,\n max: 90,\n minEnd: 10,\n step: 1,\n bigStep: 10,\n collapsed: false,\n disabled: false,\n ariaLabel: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n orientation: undefined,\n collapsible: undefined,\n})\n\nconst emit = defineEmits<GrSplitterEmits>()\n\ndefineSlots<{\n /** Первая панель — та, чей размер задаёт модель. */\n start?: () => any\n /** Вторая панель: занимает остаток. */\n end?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst orientation = useGrComponentProp('GrSplitter', 'orientation', () => props.orientation, 'horizontal')\nconst collapsible = useGrComponentProp('GrSplitter', 'collapsible', () => props.collapsible, false)\n\nconst startId = useId()\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst bounds = computed<GrSplitterBounds>(() => ({\n min: props.min,\n max: props.max,\n minEnd: props.minEnd,\n}))\n\n/**\n * Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n * (`v-model`), и uncontrolled (сплиттер помнит размер сам), как `collapsed`\n * у `GrSidebar`.\n */\nconst sizeState = ref(clampSize(props.modelValue ?? props.defaultSize, bounds.value))\nwatch(() => props.modelValue, (value) => {\n if (value !== undefined)\n sizeState.value = clampSize(value, bounds.value)\n})\n\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\n/** Размер, к которому возвращает `Enter`: свёрнутость не должна его терять. */\nconst restoreSize = ref(sizeState.value)\n\n/** Значение до начала жеста: `pointercancel` откатывает к нему. */\nlet sizeBeforeDrag = sizeState.value\nlet collapsedBeforeDrag = false\n\nconst isCollapsed = computed(() => collapsible.value && collapsedState.value)\n\n/** Что видно на экране: свёрнутая панель — это ноль в треке, но не ноль в модели. */\nconst renderedSize = computed(() => (isCollapsed.value ? 0 : clampSize(sizeState.value, bounds.value)))\n\nconst gridStyle = computed(() => {\n const track = `${renderedSize.value}% var(--gr-splitter-size, 6px) 1fr`\n\n return orientation.value === 'horizontal'\n ? { gridTemplateColumns: track }\n : { gridTemplateRows: track }\n})\n\n/**\n * `aria-orientation` описывает **сам разделитель**, а не раскладку: панели,\n * стоящие рядом, разделяет вертикальная полоса.\n */\nconst separatorOrientation = computed(() => (orientation.value === 'horizontal' ? 'vertical' : 'horizontal'))\n\nconst label = computed(() => props.ariaLabel ?? t('gr.splitter.label', 'Resize panels'))\n\nfunction setSize(next: number, commit: boolean): void {\n const value = clampSize(next, bounds.value)\n const changed = value !== sizeState.value\n\n sizeState.value = value\n if (changed)\n emit('update:modelValue', value)\n if (commit)\n emit('change', value)\n}\n\nfunction setCollapsed(value: boolean): void {\n if (collapsedState.value === value)\n return\n\n collapsedState.value = value\n emit('update:collapsed', value)\n}\n\n/**\n * Шаг размера. Свёрнутая панель на первое нажатие возвращается — двигать\n * то, чего не видно, значит менять раскладку вслепую.\n */\nfunction moveBy(delta: number): void {\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = clampSize(sizeState.value + delta, bounds.value)\n setSize(sizeState.value + delta, true)\n}\n\nfunction toggleCollapsed(): void {\n if (!collapsible.value)\n return\n\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = sizeState.value\n setCollapsed(true)\n emit('change', 0)\n}\n\nfunction reset(): void {\n setCollapsed(false)\n restoreSize.value = clampSize(props.defaultSize, bounds.value)\n setSize(props.defaultSize, true)\n}\n\n// ————— Указатель.\nfunction onPointerMove(event: PointerEvent): void {\n const rect = rootEl.value?.getBoundingClientRect()\n if (!rect)\n return\n\n // Против выделения текста под курсором во время жеста.\n event.preventDefault()\n\n const raw = sizeFromPointer(rect, event.clientX, event.clientY, orientation.value)\n\n if (collapsible.value && shouldCollapse(raw, bounds.value)) {\n if (!collapsedState.value)\n restoreSize.value = sizeState.value\n setCollapsed(true)\n return\n }\n\n setCollapsed(false)\n restoreSize.value = clampSize(raw, bounds.value)\n setSize(raw, false)\n}\n\nconst { isDragging, start: onPointerDown } = useDragGesture({\n disabled: () => props.disabled,\n onStart: () => {\n sizeBeforeDrag = sizeState.value\n collapsedBeforeDrag = collapsedState.value\n },\n onMove: onPointerMove,\n onEnd: () => emit('change', renderedSize.value),\n // Оборванный жест (браузер забрал указатель) не коммитит ничего: раскладка\n // возвращается к той, что была до нажатия.\n onCancel: () => {\n setCollapsed(collapsedBeforeDrag)\n setSize(sizeBeforeDrag, false)\n },\n})\n\n// ————— Клавиатура.\nconst decreaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowLeft' : 'ArrowUp'))\nconst increaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowRight' : 'ArrowDown'))\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.disabled)\n return\n\n const step = event.shiftKey ? props.bigStep : props.step\n\n if (event.key === decreaseKey.value)\n moveBy(-step)\n else if (event.key === increaseKey.value)\n moveBy(step)\n else if (event.key === 'Home')\n moveBy(-100)\n else if (event.key === 'End')\n moveBy(100)\n else if (event.key === 'Enter')\n toggleCollapsed()\n else return\n\n // Дошли сюда — клавиша наша: страница не должна ещё и прокрутиться.\n event.preventDefault()\n}\n\nfunction onDoubleClick(): void {\n if (props.disabled)\n return\n\n reset()\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-splitter\n :data-orientation=\"orientation\"\n :data-dragging=\"isDragging ? '' : undefined\"\n :data-collapsed=\"isCollapsed ? '' : undefined\"\n :class=\"rootClass\"\n :style=\"gridStyle\"\n >\n <div\n :id=\"startId\"\n data-gr-splitter-pane=\"start\"\n :class=\"paneClass\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n data-gr-splitter-separator\n role=\"separator\"\n :tabindex=\"disabled ? undefined : 0\"\n :aria-orientation=\"separatorOrientation\"\n :aria-label=\"label\"\n :aria-controls=\"startId\"\n :aria-valuenow=\"Math.round(renderedSize)\"\n :aria-valuemin=\"Math.round(min)\"\n :aria-valuemax=\"Math.round(max)\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"separatorClass\"\n @pointerdown=\"onPointerDown\"\n @keydown=\"onKeydown\"\n @dblclick=\"onDoubleClick\"\n />\n\n <div\n data-gr-splitter-pane=\"end\"\n :class=\"paneClass\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-splitter-separator] {\n background-color: var(--gr-splitter-color, var(--gr-brd));\n}\n\n/*\n * Зона захвата шире видимой полосы: шесть пикселей мышью не берутся, а делать\n * ради этого полосу толще — значит красить раскладку под удобство мыши.\n */\n[data-gr-splitter-separator]::before {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--gr-splitter-hit, 4px));\n}\n\n/* Насечка: короткая полоса посередине — единственный видимый намёк, что это ручка. */\n[data-gr-splitter-separator]::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n border-radius: var(--gr-radius-full);\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n opacity: 0;\n transform: translate(-50%, -50%);\n transition: opacity var(--gr-duration-fast) var(--gr-ease-out);\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator] {\n cursor: col-resize;\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator]::after {\n width: 2px;\n height: var(--gr-splitter-grip, 24px);\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator] {\n cursor: row-resize;\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator]::after {\n width: var(--gr-splitter-grip, 24px);\n height: 2px;\n}\n\n[data-gr-splitter-separator]:hover {\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n}\n\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter-separator]:focus-visible::after {\n opacity: 1;\n}\n\n/* На залитой полосе насечка читается только вырезом — цветом страницы. */\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n background-color: var(--gr-bg);\n}\n\n/* Во время жеста полоса подсвечена, даже если курсор ушёл с неё. */\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator] {\n background-color: var(--gr-splitter-active-color, var(--gr-primary));\n}\n\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n opacity: 1;\n}\n\n/* Жест не должен попутно выделять текст в панелях. */\n[data-gr-splitter][data-dragging] {\n user-select: none;\n}\n\n[data-gr-splitter-separator][aria-disabled='true'] {\n cursor: default;\n}\n\n[data-gr-splitter-separator][aria-disabled='true']::after {\n display: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useDragGesture } from '../../composables/useDragGesture'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { paneClass, rootClass, separatorClass } from './grSplitterStyles'\nimport {\n clampSize,\n shouldCollapse,\n sizeFromPointer,\n type GrSplitterBounds,\n type GrSplitterOrientation,\n} from './splitterGeometry'\n\nexport type { GrSplitterOrientation } from './splitterGeometry'\n\n/**\n * Пропы {@link GrSplitter}.\n *\n * Две панели и разделитель между ними. Размер первой панели — доля контейнера\n * в процентах: она переживает смену ширины окна и рендерится на сервере без\n * замеров.\n */\nexport interface GrSplitterProps {\n /** Доля первой панели в процентах. Поддерживает `v-model`; без него компонент помнит размер сам. */\n modelValue?: number\n /** Стартовая доля и точка возврата по двойному клику. */\n defaultSize?: number\n /** `horizontal` — панели рядом, `vertical` — одна над другой. */\n orientation?: GrSplitterOrientation\n /** Минимум первой панели в процентах. */\n min?: number\n /** Максимум первой панели в процентах. */\n max?: number\n /** Минимум второй панели: без него её можно задавить в ноль. */\n minEnd?: number\n /** Шаг стрелок. */\n step?: number\n /** Шаг стрелок с `Shift`. */\n bigStep?: number\n /** Разрешить сворачивание первой панели. */\n collapsible?: boolean\n /** Первая панель свёрнута. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Разделитель не тянется, не фокусируется и не отвечает на клавиши. */\n disabled?: boolean\n /** Имя разделителя для скринридера. Не задано — из локали. */\n ariaLabel?: string\n}\n\nexport interface GrSplitterEmits {\n (e: 'update:modelValue', value: number): void\n (e: 'update:collapsed', value: boolean): void\n /** Конец жеста и каждый шаг с клавиатуры: сюда вешают сохранение раскладки. */\n (e: 'change', value: number): void\n}\n\nconst props = withDefaults(defineProps<GrSplitterProps>(), {\n modelValue: undefined,\n defaultSize: 50,\n min: 10,\n max: 90,\n minEnd: 10,\n step: 1,\n bigStep: 10,\n collapsed: false,\n disabled: false,\n ariaLabel: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n orientation: undefined,\n collapsible: undefined,\n})\n\nconst emit = defineEmits<GrSplitterEmits>()\n\ndefineSlots<{\n /** Первая панель — та, чей размер задаёт модель. */\n start?: () => any\n /** Вторая панель: занимает остаток. */\n end?: () => any\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst orientation = useGrComponentProp('GrSplitter', 'orientation', () => props.orientation, 'horizontal')\nconst collapsible = useGrComponentProp('GrSplitter', 'collapsible', () => props.collapsible, false)\n\nconst startId = useId()\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst bounds = computed<GrSplitterBounds>(() => ({\n min: props.min,\n max: props.max,\n minEnd: props.minEnd,\n}))\n\n/**\n * Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n * (`v-model`), и uncontrolled (сплиттер помнит размер сам), как `collapsed`\n * у `GrSidebar`.\n */\nconst sizeState = ref(clampSize(props.modelValue ?? props.defaultSize, bounds.value))\nwatch(() => props.modelValue, (value) => {\n if (value !== undefined)\n sizeState.value = clampSize(value, bounds.value)\n})\n\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\n/** Размер, к которому возвращает `Enter`: свёрнутость не должна его терять. */\nconst restoreSize = ref(sizeState.value)\n\n/** Значение до начала жеста: `pointercancel` откатывает к нему. */\nlet sizeBeforeDrag = sizeState.value\nlet collapsedBeforeDrag = false\n\nconst isCollapsed = computed(() => collapsible.value && collapsedState.value)\n\n/** Что видно на экране: свёрнутая панель — это ноль в треке, но не ноль в модели. */\nconst renderedSize = computed(() => (isCollapsed.value ? 0 : clampSize(sizeState.value, bounds.value)))\n\nconst gridStyle = computed(() => {\n const track = `${renderedSize.value}% var(--gr-splitter-size, 6px) 1fr`\n\n return orientation.value === 'horizontal'\n ? { gridTemplateColumns: track }\n : { gridTemplateRows: track }\n})\n\n/**\n * `aria-orientation` описывает **сам разделитель**, а не раскладку: панели,\n * стоящие рядом, разделяет вертикальная полоса.\n */\nconst separatorOrientation = computed(() => (orientation.value === 'horizontal' ? 'vertical' : 'horizontal'))\n\nconst label = computed(() => props.ariaLabel ?? t('gr.splitter.label', 'Resize panels'))\n\nfunction setSize(next: number, commit: boolean): void {\n const value = clampSize(next, bounds.value)\n const changed = value !== sizeState.value\n\n sizeState.value = value\n if (changed)\n emit('update:modelValue', value)\n if (commit)\n emit('change', value)\n}\n\nfunction setCollapsed(value: boolean): void {\n if (collapsedState.value === value)\n return\n\n collapsedState.value = value\n emit('update:collapsed', value)\n}\n\n/**\n * Шаг размера. Свёрнутая панель на первое нажатие возвращается — двигать\n * то, чего не видно, значит менять раскладку вслепую.\n */\nfunction moveBy(delta: number): void {\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = clampSize(sizeState.value + delta, bounds.value)\n setSize(sizeState.value + delta, true)\n}\n\nfunction toggleCollapsed(): void {\n if (!collapsible.value)\n return\n\n if (isCollapsed.value) {\n setCollapsed(false)\n setSize(restoreSize.value, true)\n return\n }\n\n restoreSize.value = sizeState.value\n setCollapsed(true)\n emit('change', 0)\n}\n\nfunction reset(): void {\n setCollapsed(false)\n restoreSize.value = clampSize(props.defaultSize, bounds.value)\n setSize(props.defaultSize, true)\n}\n\n// ————— Указатель.\nfunction onPointerMove(event: PointerEvent): void {\n const rect = rootEl.value?.getBoundingClientRect()\n if (!rect)\n return\n\n // Против выделения текста под курсором во время жеста.\n event.preventDefault()\n\n const raw = sizeFromPointer(rect, event.clientX, event.clientY, orientation.value)\n\n if (collapsible.value && shouldCollapse(raw, bounds.value)) {\n if (!collapsedState.value)\n restoreSize.value = sizeState.value\n setCollapsed(true)\n return\n }\n\n setCollapsed(false)\n restoreSize.value = clampSize(raw, bounds.value)\n setSize(raw, false)\n}\n\nconst { isDragging, start: onPointerDown } = useDragGesture({\n disabled: () => props.disabled,\n onStart: () => {\n sizeBeforeDrag = sizeState.value\n collapsedBeforeDrag = collapsedState.value\n },\n onMove: onPointerMove,\n onEnd: () => emit('change', renderedSize.value),\n // Оборванный жест (браузер забрал указатель) не коммитит ничего: раскладка\n // возвращается к той, что была до нажатия.\n onCancel: () => {\n setCollapsed(collapsedBeforeDrag)\n setSize(sizeBeforeDrag, false)\n },\n})\n\n// ————— Клавиатура.\nconst decreaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowLeft' : 'ArrowUp'))\nconst increaseKey = computed(() => (orientation.value === 'horizontal' ? 'ArrowRight' : 'ArrowDown'))\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.disabled)\n return\n\n const step = event.shiftKey ? props.bigStep : props.step\n\n if (event.key === decreaseKey.value)\n moveBy(-step)\n else if (event.key === increaseKey.value)\n moveBy(step)\n else if (event.key === 'Home')\n moveBy(-100)\n else if (event.key === 'End')\n moveBy(100)\n else if (event.key === 'Enter')\n toggleCollapsed()\n else return\n\n // Дошли сюда — клавиша наша: страница не должна ещё и прокрутиться.\n event.preventDefault()\n}\n\nfunction onDoubleClick(): void {\n if (props.disabled)\n return\n\n reset()\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-splitter\n :data-orientation=\"orientation\"\n :data-dragging=\"isDragging ? '' : undefined\"\n :data-collapsed=\"isCollapsed ? '' : undefined\"\n :class=\"rootClass\"\n :style=\"gridStyle\"\n >\n <div\n :id=\"startId\"\n data-gr-splitter-pane=\"start\"\n :class=\"paneClass\"\n >\n <slot name=\"start\" />\n </div>\n\n <div\n data-gr-splitter-separator\n role=\"separator\"\n :tabindex=\"disabled ? undefined : 0\"\n :aria-orientation=\"separatorOrientation\"\n :aria-label=\"label\"\n :aria-controls=\"startId\"\n :aria-valuenow=\"Math.round(renderedSize)\"\n :aria-valuemin=\"Math.round(min)\"\n :aria-valuemax=\"Math.round(max)\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"separatorClass\"\n @pointerdown=\"onPointerDown\"\n @keydown=\"onKeydown\"\n @dblclick=\"onDoubleClick\"\n />\n\n <div\n data-gr-splitter-pane=\"end\"\n :class=\"paneClass\"\n >\n <slot name=\"end\" />\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-splitter-separator] {\n background-color: var(--gr-splitter-color, var(--gr-brd));\n}\n\n/*\n * Зона захвата шире видимой полосы: шесть пикселей мышью не берутся, а делать\n * ради этого полосу толще — значит красить раскладку под удобство мыши.\n */\n[data-gr-splitter-separator]::before {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--gr-splitter-hit, 4px));\n}\n\n/* Насечка: короткая полоса посередине — единственный видимый намёк, что это ручка. */\n[data-gr-splitter-separator]::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n border-radius: var(--gr-radius-full);\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n opacity: 0;\n transform: translate(-50%, -50%);\n transition: opacity var(--gr-duration-fast) var(--gr-ease-out);\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator] {\n cursor: col-resize;\n}\n\n[data-gr-splitter][data-orientation='horizontal'] [data-gr-splitter-separator]::after {\n width: 2px;\n height: var(--gr-splitter-grip, 24px);\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator] {\n cursor: row-resize;\n}\n\n[data-gr-splitter][data-orientation='vertical'] [data-gr-splitter-separator]::after {\n width: var(--gr-splitter-grip, 24px);\n height: 2px;\n}\n\n[data-gr-splitter-separator]:hover {\n background-color: var(--gr-splitter-hover-color, var(--gr-muted-fg));\n}\n\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter-separator]:focus-visible::after {\n opacity: 1;\n}\n\n/* На залитой полосе насечка читается только вырезом — цветом страницы. */\n[data-gr-splitter-separator]:hover::after,\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n background-color: var(--gr-bg);\n}\n\n/* Во время жеста полоса подсвечена, даже если курсор ушёл с неё. */\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator] {\n background-color: var(--gr-splitter-active-color, var(--gr-primary));\n}\n\n[data-gr-splitter][data-dragging] [data-gr-splitter-separator]::after {\n opacity: 1;\n}\n\n/* Жест не должен попутно выделять текст в панелях. */\n[data-gr-splitter][data-dragging] {\n user-select: none;\n}\n\n[data-gr-splitter-separator][aria-disabled='true'] {\n cursor: default;\n}\n\n[data-gr-splitter-separator][aria-disabled='true']::after {\n display: none;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as grSplitterSafelist, t as grSplitterConfig } from "../../chunks/config-CvbVM4ep.js";
|
|
2
|
-
import { n as sizeFromPointer, t as GrSplitter_default } from "./chunks/GrSplitter-
|
|
2
|
+
import { n as sizeFromPointer, t as GrSplitter_default } from "./chunks/GrSplitter-C-XQzq7q.js";
|
|
3
3
|
export { GrSplitter_default as GrSplitter, GrSplitter_default as default, grSplitterConfig, grSplitterSafelist, sizeFromPointer };
|
package/dist/components/GrStatistic/chunks/{GrStatistic-BoLkXw7F.js → GrStatistic-C1_nY4Gc.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-
|
|
1
|
+
import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CPMRfwVr.js";
|
|
2
2
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
3
3
|
import { t as GrSkeleton_default } from "../../GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js";
|
|
4
4
|
import { n as iconTag, t as iconClass } from "../../../chunks/icon-Dag2tIMs.js";
|
|
@@ -165,7 +165,7 @@ var GrStatistic_default = /* @__PURE__ */ defineComponent({
|
|
|
165
165
|
locale: resolvedLocale.value
|
|
166
166
|
}));
|
|
167
167
|
const isCounting = computed(() => frameValue.value !== null);
|
|
168
|
-
if (
|
|
168
|
+
if (process.env.NODE_ENV !== "production") watchEffect(() => {
|
|
169
169
|
if (props.value === void 0 || props.value === null) console.warn(`[granularity] GrStatistic: обязательный проп \`value\` не передан — получено ${String(props.value)}.`);
|
|
170
170
|
});
|
|
171
171
|
const hasTitle = computed(() => Boolean(props.title || slots.title));
|