@feugene/granularity 0.25.0 → 0.27.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/classTokens-8v2XC74x.js +16 -0
- package/dist/chunks/classTokens-8v2XC74x.js.map +1 -0
- package/dist/chunks/{config-Bpt9Xbxm.js → config-2ZHRsdOc.js} +2 -2
- package/dist/chunks/config-2ZHRsdOc.js.map +1 -0
- package/dist/chunks/{config-D6W1rnlp.js → config-B0uvcTPH.js} +1 -1
- package/dist/chunks/{config-D6W1rnlp.js.map → config-B0uvcTPH.js.map} +1 -1
- package/dist/chunks/{config-Bsh948nP.js → config-B3J0alyY.js} +1 -1
- package/dist/chunks/{config-Bsh948nP.js.map → config-B3J0alyY.js.map} +1 -1
- package/dist/chunks/{config-ScuvHw6k.js → config-B5SBUa6u.js} +1 -1
- package/dist/chunks/{config-ScuvHw6k.js.map → config-B5SBUa6u.js.map} +1 -1
- package/dist/chunks/{config-BeZRuonp.js → config-BDSaD-5p.js} +1 -1
- package/dist/chunks/{config-BeZRuonp.js.map → config-BDSaD-5p.js.map} +1 -1
- package/dist/chunks/{config-Dgj1Q6JY.js → config-BEO7brpO.js} +3 -3
- package/dist/chunks/config-BEO7brpO.js.map +1 -0
- package/dist/chunks/{config-B84z1aos.js → config-BHcS5Cwm.js} +1 -1
- package/dist/chunks/{config-B84z1aos.js.map → config-BHcS5Cwm.js.map} +1 -1
- package/dist/chunks/{config-DA6SnEoy.js → config-BRESvs9g.js} +2 -2
- package/dist/chunks/{config-DA6SnEoy.js.map → config-BRESvs9g.js.map} +1 -1
- package/dist/chunks/{config-CN2ULSQL.js → config-BTmfQFwi.js} +5 -5
- package/dist/chunks/config-BTmfQFwi.js.map +1 -0
- package/dist/chunks/{config-DtgYuGUn2.js → config-BTwYMQaz2.js} +5 -3
- package/dist/chunks/config-BTwYMQaz2.js.map +1 -0
- package/dist/chunks/{config-QJ54_fcM.js → config-BaWANzzB.js} +1 -1
- package/dist/chunks/{config-QJ54_fcM.js.map → config-BaWANzzB.js.map} +1 -1
- package/dist/chunks/{config-COvrUfhR.js → config-BcXX7S7B.js} +5 -5
- package/dist/chunks/config-BcXX7S7B.js.map +1 -0
- package/dist/chunks/{config-COpuWGr_.js → config-Bd7QfiGj.js} +1 -1
- package/dist/chunks/{config-COpuWGr_.js.map → config-Bd7QfiGj.js.map} +1 -1
- package/dist/chunks/{config-BDfTXHo1.js → config-BhfNgyWL.js} +2 -2
- package/dist/chunks/{config-BDfTXHo1.js.map → config-BhfNgyWL.js.map} +1 -1
- package/dist/chunks/{config-CjnbevbD.js → config-Bjn30smH.js} +1 -1
- package/dist/chunks/{config-CjnbevbD.js.map → config-Bjn30smH.js.map} +1 -1
- package/dist/chunks/{config-CN970ZcJ.js → config-BlJa1Mj9.js} +13 -13
- package/dist/chunks/config-BlJa1Mj9.js.map +1 -0
- package/dist/chunks/{config-DU2DNSRx.js → config-BoUI0t-t.js} +1 -1
- package/dist/chunks/{config-DU2DNSRx.js.map → config-BoUI0t-t.js.map} +1 -1
- package/dist/chunks/{config-BN4sXYXn.js → config-BqT6PMzO.js} +7 -14
- package/dist/chunks/config-BqT6PMzO.js.map +1 -0
- package/dist/chunks/config-BuGlNPE9.js.map +1 -0
- package/dist/chunks/{config-MRvhUl-O.js → config-CJzmDHfI.js} +1 -1
- package/dist/chunks/{config-MRvhUl-O.js.map → config-CJzmDHfI.js.map} +1 -1
- package/dist/chunks/{config-DGWFal5h.js → config-CLjjjPZj.js} +7 -7
- package/dist/chunks/config-CLjjjPZj.js.map +1 -0
- package/dist/chunks/{config-Cl4ST6Qd.js → config-CQLNjc9X2.js} +2 -2
- package/dist/chunks/config-CQLNjc9X2.js.map +1 -0
- package/dist/chunks/{config-vSji8w90.js → config-CWtfxkM9.js} +9 -9
- package/dist/chunks/config-CWtfxkM9.js.map +1 -0
- package/dist/chunks/{config-DKISz9gR.js → config-CWthWcWY.js} +2 -2
- package/dist/chunks/{config-DKISz9gR.js.map → config-CWthWcWY.js.map} +1 -1
- package/dist/chunks/{config-Iu684VNI.js → config-CZPDPJlg.js} +1 -1
- package/dist/chunks/{config-Iu684VNI.js.map → config-CZPDPJlg.js.map} +1 -1
- package/dist/chunks/{config-DAX8Deh1.js → config-CbEbLyDE.js} +3 -3
- package/dist/chunks/config-CbEbLyDE.js.map +1 -0
- package/dist/chunks/{config-D94Z9po5.js → config-ChPg-BQv.js} +2 -2
- package/dist/chunks/config-ChPg-BQv.js.map +1 -0
- package/dist/chunks/{config-DSJY6aEl.js → config-CjKpUcmy.js} +17 -17
- package/dist/chunks/config-CjKpUcmy.js.map +1 -0
- package/dist/chunks/{config-BIa3ilQm.js → config-CjWOTgLL.js} +4 -4
- package/dist/chunks/{config-BIa3ilQm.js.map → config-CjWOTgLL.js.map} +1 -1
- package/dist/chunks/{config-rkcKArZQ.js → config-CnYdE3HZ2.js} +5 -5
- package/dist/chunks/config-CnYdE3HZ2.js.map +1 -0
- package/dist/chunks/{config-BE6n20np.js → config-CvbVM4ep.js} +1 -1
- package/dist/chunks/{config-BE6n20np.js.map → config-CvbVM4ep.js.map} +1 -1
- package/dist/chunks/{config-9PYRZlKE.js → config-D0NzGYaE.js} +6 -6
- package/dist/chunks/config-D0NzGYaE.js.map +1 -0
- package/dist/chunks/{config-CKULiuvc.js → config-D0W8mGFD.js} +4 -4
- package/dist/chunks/{config-CKULiuvc.js.map → config-D0W8mGFD.js.map} +1 -1
- package/dist/chunks/{config-CY0_6cMi.js → config-D82r782v.js} +1 -1
- package/dist/chunks/{config-CY0_6cMi.js.map → config-D82r782v.js.map} +1 -1
- package/dist/chunks/config-DBmdgoVf2.js.map +1 -0
- package/dist/chunks/{config-WTNhdh6T.js → config-DCq4JySZ.js} +2 -2
- package/dist/chunks/{config-WTNhdh6T.js.map → config-DCq4JySZ.js.map} +1 -1
- package/dist/chunks/{config-C8tVRv8i.js → config-DGC00bTp.js} +13 -13
- package/dist/chunks/config-DGC00bTp.js.map +1 -0
- package/dist/chunks/{config-BsPDQ0dS.js → config-DIDz_E5m.js} +9 -9
- package/dist/chunks/config-DIDz_E5m.js.map +1 -0
- package/dist/chunks/{config-Dguto_6o.js → config-DM0lsduD.js} +6 -6
- package/dist/chunks/config-DM0lsduD.js.map +1 -0
- package/dist/chunks/{config-BfsBepkH.js → config-DNDgp9bB.js} +5 -5
- package/dist/chunks/config-DNDgp9bB.js.map +1 -0
- package/dist/chunks/{config-DpeQchsV.js → config-DO8mjeIo.js} +2 -2
- package/dist/chunks/{config-DpeQchsV.js.map → config-DO8mjeIo.js.map} +1 -1
- package/dist/chunks/{config-Baj7Wvx-.js → config-DRbojEzO.js} +4 -4
- package/dist/chunks/config-DRbojEzO.js.map +1 -0
- package/dist/chunks/{config-CQzGyi1C.js → config-DWL81-aM.js} +1 -1
- package/dist/chunks/{config-CQzGyi1C.js.map → config-DWL81-aM.js.map} +1 -1
- package/dist/chunks/{config-esdviAPL.js → config-DZCUPHPU.js} +1 -1
- package/dist/chunks/{config-esdviAPL.js.map → config-DZCUPHPU.js.map} +1 -1
- package/dist/chunks/{config-DKdlqXiY.js → config-DcfWZOi5.js} +5 -5
- package/dist/chunks/config-DcfWZOi5.js.map +1 -0
- package/dist/chunks/{config-BC8d_smz.js → config-DeyT9dJl.js} +3 -3
- package/dist/chunks/{config-BC8d_smz.js.map → config-DeyT9dJl.js.map} +1 -1
- package/dist/chunks/{config-Cwd3yjRw.js → config-DnF472Ox.js} +6 -4
- package/dist/chunks/config-DnF472Ox.js.map +1 -0
- package/dist/chunks/{config-B_qi4Fma.js → config-DolULhjJ.js} +5 -5
- package/dist/chunks/config-DolULhjJ.js.map +1 -0
- package/dist/chunks/{config-CIcynHGr.js → config-DpAYidyY2.js} +1 -1
- package/dist/chunks/config-DpAYidyY2.js.map +1 -0
- package/dist/chunks/{config-DYgfMrIF.js → config-Dpk-eVkS.js} +1 -1
- package/dist/chunks/{config-DYgfMrIF.js.map → config-Dpk-eVkS.js.map} +1 -1
- package/dist/chunks/config-Dv_r92GL.js +35 -0
- package/dist/chunks/config-Dv_r92GL.js.map +1 -0
- package/dist/chunks/{config-B4w5gBD0.js → config-DwABJHEo.js} +2 -2
- package/dist/chunks/config-DwABJHEo.js.map +1 -0
- package/dist/chunks/{config-zjeAJ4ho2.js → config-MmPym-Z72.js} +5 -5
- package/dist/chunks/config-MmPym-Z72.js.map +1 -0
- package/dist/chunks/{config-DCFvmHEv.js → config-T3-DMXYm.js} +9 -7
- package/dist/chunks/config-T3-DMXYm.js.map +1 -0
- package/dist/chunks/{config-BoNR7_PD.js → config-Yy67uWHY.js} +1 -1
- package/dist/chunks/{config-BoNR7_PD.js.map → config-Yy67uWHY.js.map} +1 -1
- package/dist/chunks/{config-BFJIxE8b.js → config-Z5LeUXys.js} +1 -1
- package/dist/chunks/{config-BFJIxE8b.js.map → config-Z5LeUXys.js.map} +1 -1
- package/dist/chunks/{config-DWN4x6_e.js → config-_QF0O1vq.js} +9 -9
- package/dist/chunks/config-_QF0O1vq.js.map +1 -0
- package/dist/chunks/{config-Cp0DE0GH.js → config-_jO3q1Le.js} +1 -1
- package/dist/chunks/{config-Cp0DE0GH.js.map → config-_jO3q1Le.js.map} +1 -1
- package/dist/chunks/{config-DGCMHPCR.js → config-g8-JGZ_Y.js} +1 -1
- package/dist/chunks/{config-DGCMHPCR.js.map → config-g8-JGZ_Y.js.map} +1 -1
- package/dist/chunks/{config-BTCOJO5z2.js → config-jyr6AIZt2.js} +3 -3
- package/dist/chunks/{config-BTCOJO5z2.js.map → config-jyr6AIZt2.js.map} +1 -1
- package/dist/chunks/{config-BtXRpAtq.js → config-mlheIMtV.js} +3 -6
- package/dist/chunks/config-mlheIMtV.js.map +1 -0
- package/dist/chunks/{config-BEVBsvni2.js → config-rLkc9Zn2.js} +1 -1
- package/dist/chunks/config-rLkc9Zn2.js.map +1 -0
- package/dist/chunks/{config-T3qdQBgU.js → config-tiUtEn4Q.js} +1 -1
- package/dist/chunks/{config-T3qdQBgU.js.map → config-tiUtEn4Q.js.map} +1 -1
- package/dist/chunks/{config-BViooYNv.js → config-uzUuosv7.js} +7 -2
- package/dist/chunks/config-uzUuosv7.js.map +1 -0
- package/dist/chunks/{config-BbY2SKGE.js → config-vYMJ3Cr1.js} +11 -9
- package/dist/chunks/config-vYMJ3Cr1.js.map +1 -0
- package/dist/chunks/context-BfIQv7m1.js.map +1 -0
- package/dist/chunks/{generated-CJe6hdiE.js → generated-DJ2dJ__C.js} +48 -0
- package/dist/chunks/generated-DJ2dJ__C.js.map +1 -0
- package/dist/chunks/{grBadgeStyles-C1S56Alo.js → grBadgeStyles-D8Mz73B5.js} +4 -4
- package/dist/chunks/grBadgeStyles-D8Mz73B5.js.map +1 -0
- package/dist/chunks/{config-D7zgE_Gr.js → grChipStyles-3JZApw03.js} +21 -43
- package/dist/chunks/grChipStyles-3JZApw03.js.map +1 -0
- package/dist/chunks/{grDropdownMenuStyles-D1LOkdVj.js → grDropdownMenuStyles-DG3aYHkT.js} +3 -3
- package/dist/chunks/grDropdownMenuStyles-DG3aYHkT.js.map +1 -0
- package/dist/chunks/{grIconStyles-BwJrml2L.js → grIconStyles-B6BRqUld.js} +1 -1
- package/dist/chunks/{grIconStyles-BwJrml2L.js.map → grIconStyles-B6BRqUld.js.map} +1 -1
- package/dist/chunks/{grInputStyles-CJeMhUe5.js → grInputStyles-CAk3xKIb.js} +4 -4
- package/dist/chunks/grInputStyles-CAk3xKIb.js.map +1 -0
- package/dist/chunks/{grKbdStyles-CeZhGQHr.js → grKbdStyles-DENu8pUK.js} +5 -0
- package/dist/chunks/grKbdStyles-DENu8pUK.js.map +1 -0
- package/dist/chunks/{grLinkStyles-BoL8QYcV.js → grLinkStyles-FME_qMpi.js} +4 -4
- package/dist/chunks/grLinkStyles-FME_qMpi.js.map +1 -0
- package/dist/chunks/{grLoadingStyles-DEmji2wv.js → grLoadingStyles-CnQaf5ry.js} +1 -1
- package/dist/chunks/{grLoadingStyles-DEmji2wv.js.map → grLoadingStyles-CnQaf5ry.js.map} +1 -1
- package/dist/chunks/{grPopoverStyles-Cke_BZsM.js → grPopoverStyles-Djh5RNhn.js} +4 -4
- package/dist/chunks/grPopoverStyles-Djh5RNhn.js.map +1 -0
- package/dist/chunks/{grRadioStyles-BTjGNhtU.js → grRadioStyles-D4gnU65n.js} +4 -4
- package/dist/chunks/grRadioStyles-D4gnU65n.js.map +1 -0
- package/dist/chunks/{grSelectStyles-eTz4uPMP.js → grSelectStyles-Cdtd10eY.js} +9 -9
- package/dist/chunks/grSelectStyles-Cdtd10eY.js.map +1 -0
- package/dist/chunks/{grTableStyles-C-iaqQUN.js → grTableStyles-uuMPSOBR.js} +2 -2
- package/dist/chunks/{grTableStyles-C-iaqQUN.js.map → grTableStyles-uuMPSOBR.js.map} +1 -1
- package/dist/chunks/{grTextareaStyles-iOcHuVMM.js → grTextareaStyles-Bp35BGna.js} +4 -4
- package/dist/chunks/grTextareaStyles-Bp35BGna.js.map +1 -0
- package/dist/chunks/{granular-provider-BaHkLjFX.js → granular-provider-DvvRayEh.js} +67 -67
- package/dist/chunks/{granular-provider-BaHkLjFX.js.map → granular-provider-DvvRayEh.js.map} +1 -1
- package/dist/chunks/numericStep-Bq2lj4ew.js +23 -0
- package/dist/chunks/numericStep-Bq2lj4ew.js.map +1 -0
- package/dist/chunks/overlayTransition-0Fj5tQbq.js +36 -0
- package/dist/chunks/overlayTransition-0Fj5tQbq.js.map +1 -0
- package/dist/chunks/{safelist-CudBLyAD.js → safelist-BOq5Li7p.js} +1 -1
- package/dist/chunks/{safelist-CudBLyAD.js.map → safelist-BOq5Li7p.js.map} +1 -1
- package/dist/chunks/{safelist-DOfCQR5O.js → safelist-CtiHPgrj.js} +2 -2
- package/dist/chunks/{safelist-DOfCQR5O.js.map → safelist-CtiHPgrj.js.map} +1 -1
- package/dist/chunks/{safelist-CkF4v7DC.js → safelist-Y3zrlhOa.js} +1 -1
- package/dist/chunks/{safelist-CkF4v7DC.js.map → safelist-Y3zrlhOa.js.map} +1 -1
- package/dist/chunks/{useMenuItemsFocus-OyOnIAlr.js → useMenuItemsFocus-B6TldmGf.js} +1 -43
- package/dist/chunks/useMenuItemsFocus-B6TldmGf.js.map +1 -0
- package/dist/chunks/useTypeahead-mxPtPBf2.js +44 -0
- package/dist/chunks/useTypeahead-mxPtPBf2.js.map +1 -0
- package/dist/chunks/{validation-DauXRIkL.js → validation-5HhpanPP.js} +1 -1
- package/dist/chunks/{validation-DauXRIkL.js.map → validation-5HhpanPP.js.map} +1 -1
- package/dist/components/GrAlert/chunks/{GrAlert-B21QGele.js → GrAlert-FAVf-ksH.js} +1 -1
- package/dist/components/GrAlert/chunks/{GrAlert-B21QGele.js.map → GrAlert-FAVf-ksH.js.map} +1 -1
- package/dist/components/GrAlert/index.js +1 -1
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-D9c9BNFg.js → GrAutocomplete-BwhUTqmG.js} +88 -81
- package/dist/components/GrAutocomplete/chunks/GrAutocomplete-BwhUTqmG.js.map +1 -0
- package/dist/components/GrAutocomplete/index.js +2 -2
- package/dist/components/GrAutocomplete/styles.css +1 -1
- package/dist/components/GrAvatar/chunks/{GrAvatar-BbdKRX8i.js → GrAvatar-CNmLmgcr.js} +1 -1
- package/dist/components/GrAvatar/chunks/{GrAvatar-BbdKRX8i.js.map → GrAvatar-CNmLmgcr.js.map} +1 -1
- package/dist/components/GrAvatar/index.js +2 -2
- package/dist/components/GrBadge/chunks/{GrBadge-_9rCHuE1.js → GrBadge-BM3f9PME.js} +2 -2
- package/dist/components/GrBadge/chunks/GrBadge-BM3f9PME.js.map +1 -0
- package/dist/components/GrBadge/index.js +3 -3
- package/dist/components/GrBadge/styles.css +1 -1
- package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-DDoFQscR.js → GrBadgeWrap-B-A3PRkE.js} +1 -1
- package/dist/components/GrBadgeWrap/chunks/GrBadgeWrap-B-A3PRkE.js.map +1 -0
- package/dist/components/GrBadgeWrap/index.js +2 -2
- package/dist/components/GrBottomNav/chunks/{GrBottomNav-JUu4ylYv.js → GrBottomNav-wtFatLjB.js} +1 -1
- package/dist/components/GrBottomNav/chunks/{GrBottomNav-JUu4ylYv.js.map → GrBottomNav-wtFatLjB.js.map} +1 -1
- package/dist/components/GrBottomNav/index.js +2 -2
- package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-CQ44iU2o.js → GrBreadcrumbs-jtSnMEtg.js} +2 -2
- package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-CQ44iU2o.js.map → GrBreadcrumbs-jtSnMEtg.js.map} +1 -1
- package/dist/components/GrBreadcrumbs/index.js +2 -2
- package/dist/components/GrButton/chunks/{GrButton-DCz-Wn-V.js → GrButton-Bw2AH4uX.js} +1 -1
- package/dist/components/GrButton/chunks/GrButton-Bw2AH4uX.js.map +1 -0
- package/dist/components/GrButton/index.js +3 -3
- package/dist/components/GrButtonGroup/chunks/{GrButtonGroup-BQo5VQ_c.js → GrButtonGroup-CKyiAV8K.js} +1 -1
- package/dist/components/GrButtonGroup/chunks/GrButtonGroup-CKyiAV8K.js.map +1 -0
- package/dist/components/GrButtonGroup/index.js +3 -3
- package/dist/components/GrCard/chunks/{GrCard-aQIjk6I9.js → GrCard-DR3ehBt8.js} +1 -1
- package/dist/components/GrCard/chunks/GrCard-DR3ehBt8.js.map +1 -0
- package/dist/components/GrCard/index.js +2 -2
- package/dist/components/GrCheckbox/index.js +1 -1
- package/dist/components/GrCheckboxGroup/index.js +1 -1
- package/dist/components/GrChip/chunks/{GrChip-BnL2FedO.js → GrChip-Df4orxRH.js} +15 -4
- package/dist/components/GrChip/chunks/GrChip-Df4orxRH.js.map +1 -0
- package/dist/components/GrChip/index.js +2 -2
- package/dist/components/GrChipGroup/chunks/{GrChipGroup-DefmSdY9.js → GrChipGroup-C78Vcwos.js} +2 -2
- package/dist/components/GrChipGroup/chunks/{GrChipGroup-DefmSdY9.js.map → GrChipGroup-C78Vcwos.js.map} +1 -1
- package/dist/components/GrChipGroup/index.js +2 -2
- package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-CyptiEo4.js → GrCodeBlock-Dkvkr91t.js} +2 -2
- package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-CyptiEo4.js.map → GrCodeBlock-Dkvkr91t.js.map} +1 -1
- package/dist/components/GrCodeBlock/index.js +2 -2
- package/dist/components/GrCollapse/chunks/{GrCollapse-DUROgAgc.js → GrCollapse-CytiA2Sx.js} +3 -3
- package/dist/components/GrCollapse/chunks/{GrCollapse-DUROgAgc.js.map → GrCollapse-CytiA2Sx.js.map} +1 -1
- package/dist/components/GrCollapse/index.js +2 -2
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-CDaJRVIM.js → GrColorPicker-0n_KGeUy.js} +4 -4
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-CDaJRVIM.js.map → GrColorPicker-0n_KGeUy.js.map} +1 -1
- package/dist/components/GrColorPicker/index.js +2 -2
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BPsVN_XU.js → GrCommandPalette-C5abL2Y7.js} +3 -3
- package/dist/components/GrCommandPalette/chunks/GrCommandPalette-C5abL2Y7.js.map +1 -0
- package/dist/components/GrCommandPalette/index.js +2 -2
- package/dist/components/GrCommandPalette/styles.css +1 -1
- package/dist/components/GrConfigProvider/chunks/GrConfigProvider-BF7R3hgg.js.map +1 -1
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-CwXNLyzk.js → GrConfirmDialog-B9mIU78E.js} +4 -4
- package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-B9mIU78E.js.map +1 -0
- package/dist/components/GrConfirmDialog/index.js +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-BbAJholy.js → GrContextMenu-DDAUvrDK.js} +3 -3
- package/dist/components/GrContextMenu/chunks/GrContextMenu-DDAUvrDK.js.map +1 -0
- package/dist/components/GrContextMenu/index.js +1 -1
- package/dist/components/GrDataTable/chunks/{GrDataTable-NRbrXpdx.js → GrDataTable-DU00V44y.js} +14 -4
- package/dist/components/GrDataTable/chunks/GrDataTable-DU00V44y.js.map +1 -0
- package/dist/components/GrDataTable/index.js +2 -2
- package/dist/components/GrDelta/chunks/{GrDelta-NE5HhXoo.js → GrDelta-04j9WmEY.js} +0 -0
- package/dist/components/GrDelta/chunks/{GrDelta-NE5HhXoo.js.map → GrDelta-04j9WmEY.js.map} +1 -1
- package/dist/components/GrDelta/index.js +2 -2
- package/dist/components/GrDescriptionList/chunks/{GrDescriptionList-1mICfrqX.js → GrDescriptionList-BMeCgFV3.js} +1 -1
- package/dist/components/GrDescriptionList/chunks/GrDescriptionList-BMeCgFV3.js.map +1 -0
- package/dist/components/GrDescriptionList/index.js +2 -2
- package/dist/components/GrDialog/chunks/{GrDialog-5Y5K87ss.js → GrDialog-bOUDYfmh.js} +2 -2
- package/dist/components/GrDialog/chunks/GrDialog-bOUDYfmh.js.map +1 -0
- package/dist/components/GrDialog/index.js +2 -2
- package/dist/components/GrDialogService/chunks/{GrDialogService-CHhzGRWy.js → GrDialogService-B--br5so.js} +4 -4
- package/dist/components/GrDialogService/chunks/{GrDialogService-CHhzGRWy.js.map → GrDialogService-B--br5so.js.map} +1 -1
- package/dist/components/GrDialogService/index.js +1 -1
- package/dist/components/GrDivider/chunks/{GrDivider-CAhm9jbE.js → GrDivider-BXavGcMX.js} +1 -1
- package/dist/components/GrDivider/chunks/GrDivider-BXavGcMX.js.map +1 -0
- package/dist/components/GrDivider/index.js +2 -2
- package/dist/components/GrDrawer/chunks/{GrDrawer-CXy3-SVd.js → GrDrawer-BCreL-eq.js} +3 -3
- package/dist/components/GrDrawer/chunks/{GrDrawer-CXy3-SVd.js.map → GrDrawer-BCreL-eq.js.map} +1 -1
- package/dist/components/GrDrawer/index.js +2 -2
- package/dist/components/GrDropdown/chunks/{GrDropdown-BfTmdPyh.js → GrDropdown-13Wt9eB_.js} +16 -8
- package/dist/components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js.map +1 -0
- package/dist/components/GrDropdown/index.js +2 -2
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-l5HEqzjr.js → GrDropdownMenu-5zoOL8Oj.js} +3 -3
- package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-5zoOL8Oj.js.map +1 -0
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenuList-BGA_xNVo.js → GrDropdownMenuList-CT_1TQJo.js} +1 -1
- package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-CT_1TQJo.js.map +1 -0
- package/dist/components/GrDropdownMenu/index.js +3 -3
- package/dist/components/GrEmptyState/chunks/{GrEmptyState-CS9do8eM.js → GrEmptyState-D4T5pzXA.js} +2 -2
- package/dist/components/GrEmptyState/chunks/{GrEmptyState-CS9do8eM.js.map → GrEmptyState-D4T5pzXA.js.map} +1 -1
- package/dist/components/GrEmptyState/index.js +2 -2
- package/dist/components/GrFilePreview/chunks/{GrFilePreview-D0Bt-0nn.js → GrFilePreview-C9Z7hMK8.js} +1 -1
- package/dist/components/GrFilePreview/chunks/{GrFilePreview-D0Bt-0nn.js.map → GrFilePreview-C9Z7hMK8.js.map} +1 -1
- package/dist/components/GrFilePreview/index.js +2 -2
- package/dist/components/GrFileUpload/chunks/{GrFileUpload-wNXzHb5N.js → GrFileUpload-FjbaYGjL.js} +2 -2
- package/dist/components/GrFileUpload/chunks/{GrFileUpload-wNXzHb5N.js.map → GrFileUpload-FjbaYGjL.js.map} +1 -1
- package/dist/components/GrFileUpload/index.js +2 -2
- package/dist/components/GrForm/chunks/{GrForm-B_Qq_13k.js → GrForm-CrnfCsgj.js} +9 -3
- package/dist/components/GrForm/chunks/GrForm-CrnfCsgj.js.map +1 -0
- package/dist/components/GrForm/index.js +3 -3
- package/dist/components/GrFormField/chunks/GrFormField-DSylU7IU.js.map +1 -1
- package/dist/components/GrFormField/index.js +1 -1
- package/dist/components/GrFormFile/chunks/{GrFormFile-DhVkB2gm.js → GrFormFile-ChdKlN83.js} +3 -3
- package/dist/components/GrFormFile/chunks/{GrFormFile-DhVkB2gm.js.map → GrFormFile-ChdKlN83.js.map} +1 -1
- package/dist/components/GrFormFile/index.js +2 -2
- package/dist/components/GrFormSection/chunks/{GrFormSection-CdGWvzXO.js → GrFormSection-ejieOg9H.js} +1 -1
- package/dist/components/GrFormSection/chunks/{GrFormSection-CdGWvzXO.js.map → GrFormSection-ejieOg9H.js.map} +1 -1
- package/dist/components/GrFormSection/index.js +2 -2
- package/dist/components/GrIcon/chunks/{GrIcon-bQwtZtYT.js → GrIcon-Bn1XEriL.js} +1 -1
- package/dist/components/GrIcon/chunks/GrIcon-Bn1XEriL.js.map +1 -0
- package/dist/components/GrIcon/index.js +2 -2
- package/dist/components/GrImageViewer/chunks/{GrImageViewer-ng7el4wn.js → GrImageViewer-COUcpOgR.js} +2 -2
- package/dist/components/GrImageViewer/chunks/GrImageViewer-COUcpOgR.js.map +1 -0
- package/dist/components/GrImageViewer/index.js +2 -2
- package/dist/components/GrInput/chunks/{GrInput-Bb_pxqpT.js → GrInput-c53iltz0.js} +1 -1
- package/dist/components/GrInput/chunks/{GrInput-Bb_pxqpT.js.map → GrInput-c53iltz0.js.map} +1 -1
- package/dist/components/GrInput/index.js +2 -2
- package/dist/components/GrInputTag/chunks/{GrInputTag-UI8kIB_F.js → GrInputTag-LP3smqOv.js} +46 -49
- package/dist/components/GrInputTag/chunks/GrInputTag-LP3smqOv.js.map +1 -0
- package/dist/components/GrInputTag/index.js +2 -2
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-jk3ylOTc.js → GrJsonViewer-ClTvjlFx.js} +4 -4
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-jk3ylOTc.js.map → GrJsonViewer-ClTvjlFx.js.map} +1 -1
- package/dist/components/GrJsonViewer/index.js +2 -2
- package/dist/components/GrKbd/chunks/{GrKbd-BXbhsH0M.js → GrKbd-D2ga1H9i.js} +1 -1
- package/dist/components/GrKbd/chunks/{GrKbd-BXbhsH0M.js.map → GrKbd-D2ga1H9i.js.map} +1 -1
- package/dist/components/GrKbd/index.js +2 -2
- package/dist/components/GrLink/chunks/{GrLink-BQb7U4so.js → GrLink-DAGCFYO7.js} +2 -2
- package/dist/components/GrLink/chunks/GrLink-DAGCFYO7.js.map +1 -0
- package/dist/components/GrLink/index.js +2 -2
- package/dist/components/GrList/chunks/{GrList-B5bclmHV.js → GrList-DrXrKU37.js} +3 -3
- package/dist/components/GrList/chunks/GrList-DrXrKU37.js.map +1 -0
- package/dist/components/GrList/index.js +2 -2
- package/dist/components/GrList/styles.css +1 -1
- package/dist/components/GrLoading/chunks/{GrLoading-DeBFTvFX.js → GrLoading-DDD8WAIH.js} +2 -2
- package/dist/components/GrLoading/chunks/{GrLoading-DeBFTvFX.js.map → GrLoading-DDD8WAIH.js.map} +1 -1
- package/dist/components/GrLoading/index.js +2 -2
- package/dist/components/GrModal/index.js +1 -1
- package/dist/components/GrNavbar/chunks/{GrNavbar-DPj30sHX.js → GrNavbar-DhswlYyh.js} +3 -3
- package/dist/components/GrNavbar/chunks/{GrNavbar-DPj30sHX.js.map → GrNavbar-DhswlYyh.js.map} +1 -1
- package/dist/components/GrNavbar/index.js +2 -2
- package/dist/components/GrNumberInput/chunks/{GrNumberInput-V2mZvDDC.js → GrNumberInput-Daud9Jdm.js} +3 -14
- package/dist/components/GrNumberInput/chunks/GrNumberInput-Daud9Jdm.js.map +1 -0
- package/dist/components/GrNumberInput/index.js +2 -2
- package/dist/components/GrPagination/chunks/{GrPagination-DG7kp6VL.js → GrPagination-CaNTZc-v.js} +3 -3
- package/dist/components/GrPagination/chunks/{GrPagination-DG7kp6VL.js.map → GrPagination-CaNTZc-v.js.map} +1 -1
- package/dist/components/GrPagination/index.js +2 -2
- package/dist/components/GrPopover/chunks/{GrPopover-DDChM1jD.js → GrPopover-CofG-Tfe.js} +16 -8
- package/dist/components/GrPopover/chunks/GrPopover-CofG-Tfe.js.map +1 -0
- package/dist/components/GrPopover/index.js +2 -2
- package/dist/components/GrProgressBar/index.js +1 -1
- package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-BeUx1g1f.js → GrProgressCircle-D3yWXYDa.js} +1 -1
- package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-BeUx1g1f.js.map → GrProgressCircle-D3yWXYDa.js.map} +1 -1
- package/dist/components/GrProgressCircle/index.js +2 -2
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-DjF-5oD9.js → GrPromptDialog-DMhALhSS.js} +7 -7
- package/dist/components/GrPromptDialog/chunks/GrPromptDialog-DMhALhSS.js.map +1 -0
- package/dist/components/GrPromptDialog/index.js +1 -1
- package/dist/components/GrRadio/chunks/{GrRadio-BdhknbO8.js → GrRadio-C_rESc5g.js} +1 -1
- package/dist/components/GrRadio/chunks/GrRadio-C_rESc5g.js.map +1 -0
- package/dist/components/GrRadio/index.js +2 -2
- package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-7w4bXIg_.js → GrRadioGroup-CdQO4G-U.js} +2 -2
- package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-7w4bXIg_.js.map → GrRadioGroup-CdQO4G-U.js.map} +1 -1
- package/dist/components/GrRadioGroup/index.js +1 -1
- package/dist/components/GrRating/chunks/{GrRating-BSEtaibx.js → GrRating-IEiTOdnF.js} +1 -1
- package/dist/components/GrRating/chunks/{GrRating-BSEtaibx.js.map → GrRating-IEiTOdnF.js.map} +1 -1
- package/dist/components/GrRating/index.js +2 -2
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DA4q90Zt.js → GrResponseErrorBanner-C_skObtv.js} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DA4q90Zt.js.map → GrResponseErrorBanner-C_skObtv.js.map} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-BhP-xw2P.js → GrResponseErrorBanner-DudGc9LO.js} +4 -4
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-BhP-xw2P.js.map → GrResponseErrorBanner-DudGc9LO.js.map} +1 -1
- package/dist/components/GrResponseErrorBanner/index.js +2 -2
- package/dist/components/GrSegmented/chunks/{GrSegmented-DKpo3cnC.js → GrSegmented-CB-VR-yL.js} +1 -1
- package/dist/components/GrSegmented/chunks/{GrSegmented-DKpo3cnC.js.map → GrSegmented-CB-VR-yL.js.map} +1 -1
- package/dist/components/GrSegmented/index.js +2 -2
- package/dist/components/GrSelect/chunks/{GrSelect-BA1wfX3c.js → GrSelect-BE1VNTiY.js} +96 -89
- package/dist/components/GrSelect/chunks/GrSelect-BE1VNTiY.js.map +1 -0
- package/dist/components/GrSelect/index.js +2 -2
- package/dist/components/GrSelect/styles.css +1 -1
- package/dist/components/GrSidebar/chunks/{GrSidebar-DY-LgIbS.js → GrSidebar-DxPhIiWs.js} +3 -3
- package/dist/components/GrSidebar/chunks/{GrSidebar-DY-LgIbS.js.map → GrSidebar-DxPhIiWs.js.map} +1 -1
- package/dist/components/GrSidebar/index.js +2 -2
- package/dist/components/GrSlider/chunks/{GrSlider-s99yAyz6.js → GrSlider-DJfeEl4h.js} +5 -4
- package/dist/components/GrSlider/chunks/GrSlider-DJfeEl4h.js.map +1 -0
- package/dist/components/GrSlider/index.js +2 -2
- package/dist/components/GrSortableList/chunks/{GrSortableList-BMXyxmRc.js → GrSortableList-DGs3Pi2J.js} +2 -2
- package/dist/components/GrSortableList/chunks/{GrSortableList-BMXyxmRc.js.map → GrSortableList-DGs3Pi2J.js.map} +1 -1
- package/dist/components/GrSortableList/index.js +2 -2
- package/dist/components/GrSplitter/chunks/{GrSplitter-B9_JrT7q.js → GrSplitter-MltjaADn.js} +1 -1
- package/dist/components/GrSplitter/chunks/{GrSplitter-B9_JrT7q.js.map → GrSplitter-MltjaADn.js.map} +1 -1
- package/dist/components/GrSplitter/index.js +2 -2
- package/dist/components/GrStatistic/chunks/{GrStatistic-BJQv5aOS.js → GrStatistic-qHVasK37.js} +2 -2
- package/dist/components/GrStatistic/chunks/GrStatistic-qHVasK37.js.map +1 -0
- package/dist/components/GrStatistic/index.js +2 -2
- package/dist/components/GrSteps/chunks/{GrSteps-Cce4rfr3.js → GrSteps-C2jxpZoN.js} +1 -1
- package/dist/components/GrSteps/chunks/{GrSteps-Cce4rfr3.js.map → GrSteps-C2jxpZoN.js.map} +1 -1
- package/dist/components/GrSteps/index.js +2 -2
- package/dist/components/GrSwitch/chunks/{GrSwitch-CHiIj9GT.js → GrSwitch-KRlRMwgp.js} +1 -1
- package/dist/components/GrSwitch/chunks/{GrSwitch-CHiIj9GT.js.map → GrSwitch-KRlRMwgp.js.map} +1 -1
- package/dist/components/GrSwitch/index.js +2 -2
- package/dist/components/GrTabPanels/chunks/GrTabPanels-BZQS8-JM.js.map +1 -1
- package/dist/components/GrTable/chunks/{GrTable-f3qCWa99.js → GrTable-Zcdz2St_.js} +1 -1
- package/dist/components/GrTable/chunks/GrTable-Zcdz2St_.js.map +1 -0
- package/dist/components/GrTable/index.js +2 -2
- package/dist/components/GrTabs/chunks/{GrTabs-CBHZkOFY.js → GrTabs-ugDnkk-2.js} +2 -2
- package/dist/components/GrTabs/chunks/{GrTabs-CBHZkOFY.js.map → GrTabs-ugDnkk-2.js.map} +1 -1
- package/dist/components/GrTabs/index.js +2 -2
- package/dist/components/GrTextarea/chunks/{GrTextarea-CNnkcIG1.js → GrTextarea-KREK75Bu.js} +1 -1
- package/dist/components/GrTextarea/chunks/{GrTextarea-CNnkcIG1.js.map → GrTextarea-KREK75Bu.js.map} +1 -1
- package/dist/components/GrTextarea/index.js +2 -2
- package/dist/components/GrTimeline/chunks/{GrTimeline-DIDdkTn7.js → GrTimeline-BiHpArsg.js} +1 -1
- package/dist/components/GrTimeline/chunks/{GrTimeline-DIDdkTn7.js.map → GrTimeline-BiHpArsg.js.map} +1 -1
- package/dist/components/GrTimeline/index.js +2 -2
- package/dist/components/GrToaster/chunks/{GrToaster-CC49q3a4.js → GrToaster-CUi3ldJ0.js} +6 -6
- package/dist/components/GrToaster/chunks/GrToaster-CUi3ldJ0.js.map +1 -0
- package/dist/components/GrToaster/index.js +2 -2
- package/dist/components/GrToaster/styles.css +1 -1
- package/dist/components/GrTooltip/chunks/{GrTooltip-B6AwE_UX.js → GrTooltip-BKFjqu0E.js} +4 -4
- package/dist/components/GrTooltip/chunks/GrTooltip-BKFjqu0E.js.map +1 -0
- package/dist/components/GrTooltip/index.js +2 -2
- package/dist/components/GrTree/chunks/{GrTree-J5q8aCya.js → GrTree-D5ozu6U4.js} +15 -25
- package/dist/components/GrTree/chunks/GrTree-D5ozu6U4.js.map +1 -0
- package/dist/components/GrTree/index.js +1 -1
- package/dist/components/GrTree/styles.css +1 -1
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DEfxWAc3.js → GrTreeSelect-Db_uKdNa.js} +18 -10
- package/dist/components/GrTreeSelect/chunks/GrTreeSelect-Db_uKdNa.js.map +1 -0
- package/dist/components/GrTreeSelect/index.js +2 -2
- package/dist/components/GrValue/chunks/{GrValue-CZsuZ4x-.js → GrValue-ezkQM05Q.js} +1 -1
- package/dist/components/GrValue/chunks/{GrValue-CZsuZ4x-.js.map → GrValue-ezkQM05Q.js.map} +1 -1
- package/dist/components/GrValue/index.js +2 -2
- 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 +145 -145
- package/dist/styles/tokens.css +11 -0
- package/dist/theme.js +1 -1
- package/dist/tokens.js +1 -1
- package/dist/types/components/GrAutocomplete/GrAutocomplete.vue.d.ts +4 -3
- package/dist/types/components/GrAutocomplete/grAutocompleteStyles.d.ts +2 -2
- package/dist/types/components/GrBadge/GrBadge.vue.d.ts +3 -3
- package/dist/types/components/GrBadgeWrap/GrBadgeWrap.vue.d.ts +3 -3
- package/dist/types/components/GrBadgeWrap/grBadgeWrapStyles.d.ts +1 -1
- package/dist/types/components/GrBottomNav/grBottomNavStyles.d.ts +1 -1
- package/dist/types/components/GrButton/GrButton.vue.d.ts +7 -7
- package/dist/types/components/GrButtonGroup/GrButtonGroup.vue.d.ts +3 -3
- package/dist/types/components/GrCard/GrCard.vue.d.ts +7 -9
- package/dist/types/components/GrCheckbox/GrCheckbox.vue.d.ts +1 -1
- package/dist/types/components/GrCheckboxGroup/GrCheckboxGroup.vue.d.ts +1 -1
- package/dist/types/components/GrChip/GrChip.vue.d.ts +19 -1
- package/dist/types/components/GrChip/grChipStyles.d.ts +10 -6
- package/dist/types/components/GrChipGroup/GrChipGroup.vue.d.ts +2 -2
- package/dist/types/components/GrCollapse/GrCollapseItem.vue.d.ts +9 -11
- package/dist/types/components/GrColorPicker/GrColorPicker.vue.d.ts +1 -1
- package/dist/types/components/GrCommandPalette/GrCommandPalette.vue.d.ts +13 -13
- package/dist/types/components/GrCommandPalette/grCommandPaletteStyles.d.ts +5 -5
- package/dist/types/components/GrConfigProvider/GrConfigProvider.vue.d.ts +3 -3
- package/dist/types/components/GrConfirmDialog/GrConfirmDialog.vue.d.ts +9 -9
- package/dist/types/components/GrContextMenu/GrContextMenu.vue.d.ts +9 -9
- package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +9 -17
- package/dist/types/components/GrDescriptionList/GrDescriptionList.vue.d.ts +16 -13
- package/dist/types/components/GrDialog/GrDialogFooter.vue.d.ts +3 -3
- package/dist/types/components/GrDivider/GrDivider.vue.d.ts +3 -3
- package/dist/types/components/GrDrawer/grDrawerStyles.d.ts +1 -1
- package/dist/types/components/GrDropdown/GrDropdown.vue.d.ts +16 -20
- package/dist/types/components/GrDropdownMenu/GrDropdownMenu.vue.d.ts +16 -19
- package/dist/types/components/GrDropdownMenu/GrDropdownMenuColumn.vue.d.ts +3 -3
- package/dist/types/components/GrDropdownMenu/GrDropdownMenuColumns.vue.d.ts +3 -3
- package/dist/types/components/GrDropdownMenu/GrDropdownMenuGroup.vue.d.ts +3 -3
- package/dist/types/components/GrDropdownMenu/GrDropdownMenuHeader.vue.d.ts +3 -3
- package/dist/types/components/GrDropdownMenu/GrDropdownMenuItem.vue.d.ts +7 -7
- package/dist/types/components/GrDropdownMenu/GrDropdownMenuList.vue.d.ts +3 -3
- package/dist/types/components/GrDropdownMenu/grDropdownMenuStyles.d.ts +3 -3
- package/dist/types/components/GrForm/GrForm.vue.d.ts +5 -1
- package/dist/types/components/GrForm/index.d.ts +1 -1
- package/dist/types/components/GrFormField/GrFormField.vue.d.ts +11 -11
- package/dist/types/components/GrFormFile/GrFormFile.vue.d.ts +1 -1
- package/dist/types/components/GrFormSection/grFormSectionStyles.d.ts +2 -2
- package/dist/types/components/GrIcon/GrIcon.vue.d.ts +3 -3
- package/dist/types/components/GrImageViewer/GrImageViewer.vue.d.ts +6 -25
- package/dist/types/components/GrInput/GrInput.vue.d.ts +1 -1
- package/dist/types/components/GrInput/grInputStyles.d.ts +4 -4
- package/dist/types/components/GrInputTag/GrInputTag.vue.d.ts +2 -2
- package/dist/types/components/GrInputTag/grInputTagStyles.d.ts +0 -6
- package/dist/types/components/GrKbd/GrKbd.vue.d.ts +3 -3
- package/dist/types/components/GrKbd/grKbdStyles.d.ts +5 -0
- package/dist/types/components/GrLink/GrLink.vue.d.ts +3 -3
- package/dist/types/components/GrList/GrList.vue.d.ts +12 -6
- package/dist/types/components/GrList/GrListItem.vue.d.ts +9 -9
- package/dist/types/components/GrList/grListStyles.d.ts +3 -3
- package/dist/types/components/GrNavbar/grNavbarStyles.d.ts +1 -1
- package/dist/types/components/GrNumberInput/GrNumberInput.vue.d.ts +1 -1
- package/dist/types/components/GrNumberInput/numberInputMath.d.ts +1 -6
- package/dist/types/components/GrPopover/GrPopover.vue.d.ts +16 -17
- package/dist/types/components/GrPromptDialog/GrPromptDialog.vue.d.ts +9 -9
- package/dist/types/components/GrRadio/GrRadio.vue.d.ts +6 -8
- package/dist/types/components/GrRadioGroup/GrRadioGroup.vue.d.ts +1 -1
- package/dist/types/components/GrRating/GrRating.vue.d.ts +1 -1
- package/dist/types/components/GrSegmented/GrSegmented.vue.d.ts +1 -1
- package/dist/types/components/GrSelect/grSelectStyles.d.ts +1 -1
- package/dist/types/components/GrSidebar/GrSidebar.vue.d.ts +7 -7
- package/dist/types/components/GrSidebar/grSidebarStyles.d.ts +4 -4
- package/dist/types/components/GrSlider/GrSlider.vue.d.ts +1 -1
- package/dist/types/components/GrSortableList/grSortableListStyles.d.ts +2 -2
- package/dist/types/components/GrSplitter/GrSplitter.vue.d.ts +1 -1
- package/dist/types/components/GrStatistic/GrStatistic.vue.d.ts +13 -13
- package/dist/types/components/GrSteps/grStepsStyles.d.ts +2 -2
- package/dist/types/components/GrSwitch/GrSwitch.vue.d.ts +1 -1
- package/dist/types/components/GrTabPanels/GrTabPanel.vue.d.ts +3 -3
- package/dist/types/components/GrTabPanels/GrTabPanels.vue.d.ts +3 -3
- package/dist/types/components/GrTable/GrTable.vue.d.ts +13 -13
- package/dist/types/components/GrTextarea/GrTextarea.vue.d.ts +1 -1
- package/dist/types/components/GrTreeSelect/grTreeSelectStyles.d.ts +1 -1
- package/dist/types/components/shared/classTokens.d.ts +8 -0
- package/dist/types/components/shared/numericStep.d.ts +14 -0
- package/dist/types/components/shared/overlayTransition.d.ts +33 -0
- package/dist/web-types.json +292 -218
- package/package.json +2 -2
- package/tokens/foundation.json +41 -1
- package/dist/chunks/classTokens-BzazaERD.js +0 -6
- package/dist/chunks/classTokens-BzazaERD.js.map +0 -1
- package/dist/chunks/config-9PYRZlKE.js.map +0 -1
- package/dist/chunks/config-B4w5gBD0.js.map +0 -1
- package/dist/chunks/config-BEVBsvni2.js.map +0 -1
- package/dist/chunks/config-BN4sXYXn.js.map +0 -1
- package/dist/chunks/config-BViooYNv.js.map +0 -1
- package/dist/chunks/config-B_qi4Fma.js.map +0 -1
- package/dist/chunks/config-Baj7Wvx-.js.map +0 -1
- package/dist/chunks/config-BbY2SKGE.js.map +0 -1
- package/dist/chunks/config-BfsBepkH.js.map +0 -1
- package/dist/chunks/config-Bpt9Xbxm.js.map +0 -1
- package/dist/chunks/config-BsPDQ0dS.js.map +0 -1
- package/dist/chunks/config-BtXRpAtq.js.map +0 -1
- package/dist/chunks/config-BuGlNPE92.js.map +0 -1
- package/dist/chunks/config-C8tVRv8i.js.map +0 -1
- package/dist/chunks/config-CIcynHGr.js.map +0 -1
- package/dist/chunks/config-CN2ULSQL.js.map +0 -1
- package/dist/chunks/config-CN970ZcJ.js.map +0 -1
- package/dist/chunks/config-COvrUfhR.js.map +0 -1
- package/dist/chunks/config-Cl4ST6Qd.js.map +0 -1
- package/dist/chunks/config-Cwd3yjRw.js.map +0 -1
- package/dist/chunks/config-D7zgE_Gr.js.map +0 -1
- package/dist/chunks/config-D94Z9po5.js.map +0 -1
- package/dist/chunks/config-DAX8Deh1.js.map +0 -1
- package/dist/chunks/config-DBmdgoVf.js.map +0 -1
- package/dist/chunks/config-DCFvmHEv.js.map +0 -1
- package/dist/chunks/config-DGWFal5h.js.map +0 -1
- package/dist/chunks/config-DKdlqXiY.js.map +0 -1
- package/dist/chunks/config-DSJY6aEl.js.map +0 -1
- package/dist/chunks/config-DWN4x6_e.js.map +0 -1
- package/dist/chunks/config-Dgj1Q6JY.js.map +0 -1
- package/dist/chunks/config-Dguto_6o.js.map +0 -1
- package/dist/chunks/config-DtgYuGUn2.js.map +0 -1
- package/dist/chunks/config-rkcKArZQ.js.map +0 -1
- package/dist/chunks/config-vSji8w90.js.map +0 -1
- package/dist/chunks/config-zjeAJ4ho2.js.map +0 -1
- package/dist/chunks/context-BfIQv7m12.js.map +0 -1
- package/dist/chunks/generated-CJe6hdiE.js.map +0 -1
- package/dist/chunks/grBadgeStyles-C1S56Alo.js.map +0 -1
- package/dist/chunks/grDropdownMenuStyles-D1LOkdVj.js.map +0 -1
- package/dist/chunks/grInputStyles-CJeMhUe5.js.map +0 -1
- package/dist/chunks/grKbdStyles-CeZhGQHr.js.map +0 -1
- package/dist/chunks/grLinkStyles-BoL8QYcV.js.map +0 -1
- package/dist/chunks/grPopoverStyles-Cke_BZsM.js.map +0 -1
- package/dist/chunks/grRadioStyles-BTjGNhtU.js.map +0 -1
- package/dist/chunks/grSelectStyles-eTz4uPMP.js.map +0 -1
- package/dist/chunks/grTextareaStyles-iOcHuVMM.js.map +0 -1
- package/dist/chunks/useMenuItemsFocus-OyOnIAlr.js.map +0 -1
- package/dist/components/GrAutocomplete/chunks/GrAutocomplete-D9c9BNFg.js.map +0 -1
- package/dist/components/GrBadge/chunks/GrBadge-_9rCHuE1.js.map +0 -1
- package/dist/components/GrBadgeWrap/chunks/GrBadgeWrap-DDoFQscR.js.map +0 -1
- package/dist/components/GrButton/chunks/GrButton-DCz-Wn-V.js.map +0 -1
- package/dist/components/GrButtonGroup/chunks/GrButtonGroup-BQo5VQ_c.js.map +0 -1
- package/dist/components/GrCard/chunks/GrCard-aQIjk6I9.js.map +0 -1
- package/dist/components/GrChip/chunks/GrChip-BnL2FedO.js.map +0 -1
- package/dist/components/GrCommandPalette/chunks/GrCommandPalette-BPsVN_XU.js.map +0 -1
- package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-CwXNLyzk.js.map +0 -1
- package/dist/components/GrContextMenu/chunks/GrContextMenu-BbAJholy.js.map +0 -1
- package/dist/components/GrDataTable/chunks/GrDataTable-NRbrXpdx.js.map +0 -1
- package/dist/components/GrDescriptionList/chunks/GrDescriptionList-1mICfrqX.js.map +0 -1
- package/dist/components/GrDialog/chunks/GrDialog-5Y5K87ss.js.map +0 -1
- package/dist/components/GrDivider/chunks/GrDivider-CAhm9jbE.js.map +0 -1
- package/dist/components/GrDropdown/chunks/GrDropdown-BfTmdPyh.js.map +0 -1
- package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-l5HEqzjr.js.map +0 -1
- package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-BGA_xNVo.js.map +0 -1
- package/dist/components/GrForm/chunks/GrForm-B_Qq_13k.js.map +0 -1
- package/dist/components/GrIcon/chunks/GrIcon-bQwtZtYT.js.map +0 -1
- package/dist/components/GrImageViewer/chunks/GrImageViewer-ng7el4wn.js.map +0 -1
- package/dist/components/GrInputTag/chunks/GrInputTag-UI8kIB_F.js.map +0 -1
- package/dist/components/GrLink/chunks/GrLink-BQb7U4so.js.map +0 -1
- package/dist/components/GrList/chunks/GrList-B5bclmHV.js.map +0 -1
- package/dist/components/GrNumberInput/chunks/GrNumberInput-V2mZvDDC.js.map +0 -1
- package/dist/components/GrPopover/chunks/GrPopover-DDChM1jD.js.map +0 -1
- package/dist/components/GrPromptDialog/chunks/GrPromptDialog-DjF-5oD9.js.map +0 -1
- package/dist/components/GrRadio/chunks/GrRadio-BdhknbO8.js.map +0 -1
- package/dist/components/GrSelect/chunks/GrSelect-BA1wfX3c.js.map +0 -1
- package/dist/components/GrSlider/chunks/GrSlider-s99yAyz6.js.map +0 -1
- package/dist/components/GrStatistic/chunks/GrStatistic-BJQv5aOS.js.map +0 -1
- package/dist/components/GrTable/chunks/GrTable-f3qCWa99.js.map +0 -1
- package/dist/components/GrToaster/chunks/GrToaster-CC49q3a4.js.map +0 -1
- package/dist/components/GrTooltip/chunks/GrTooltip-B6AwE_UX.js.map +0 -1
- package/dist/components/GrTree/chunks/GrTree-J5q8aCya.js.map +0 -1
- package/dist/components/GrTreeSelect/chunks/GrTreeSelect-DEfxWAc3.js.map +0 -1
- /package/dist/chunks/{config-BuGlNPE92.js → config-BuGlNPE9.js} +0 -0
- /package/dist/chunks/{config-DBmdgoVf.js → config-DBmdgoVf2.js} +0 -0
- /package/dist/chunks/{context-BfIQv7m12.js → context-BfIQv7m1.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrBreadcrumbs-CQ44iU2o.js","names":[],"sources":["../../../../src/components/GrBreadcrumbs/GrBreadcrumbs.vue","../../../../src/components/GrBreadcrumbs/GrBreadcrumbs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport GrLink from '../GrLink/GrLink.vue'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n breadcrumbsCurrentClass,\n breadcrumbsEllipsisClass,\n breadcrumbsItemIconClass,\n breadcrumbsLabelClass,\n breadcrumbsListClass,\n breadcrumbsListNowrapClass,\n breadcrumbsListWrapClass,\n breadcrumbsRootClass,\n breadcrumbsSeparatorClass,\n breadcrumbsSizeClassBySize,\n type GrBreadcrumbItem,\n type GrBreadcrumbsLinkComponent,\n type GrBreadcrumbsSize,\n resolveBreadcrumbsFit,\n resolveBreadcrumbsLayout,\n} from './grBreadcrumbsStyles'\n\nexport type { GrBreadcrumbItem, GrBreadcrumbsSize } from './grBreadcrumbsStyles'\n\n/**\n * Путь до текущей страницы (WAI-ARIA breadcrumb): `<nav>` с именем, внутри\n * упорядоченный список ссылок, последний пункт — текущая страница.\n *\n * Ссылки рисует `GrLink`, поэтому роутер подключается тем же способом, что и\n * везде в пакете: `as` + `to`.\n */\nexport interface GrBreadcrumbsProps {\n /** Путь от корня к текущей странице. Последний пункт — текущая страница. */\n items: GrBreadcrumbItem[]\n /** Компонент ссылки для всех пунктов: `RouterLink`, `NuxtLink`, `Link` Inertia. */\n as?: GrBreadcrumbsLinkComponent\n /** Разделитель между пунктами. Декоративен: диктору не читается. */\n separator?: string\n size?: GrBreadcrumbsSize\n /**\n * С какого числа пунктов схлопывать середину в «…». `0`/не задано — показывать\n * путь целиком.\n */\n maxItems?: number\n /** Сколько пунктов оставить в начале при схлопывании. */\n itemsBeforeCollapse?: number\n /** Сколько пунктов оставить в конце при схлопывании. */\n itemsAfterCollapse?: number\n /** Имя лендмарка. Не задано — берётся из локали. */\n ariaLabel?: string\n /** Последний пункт остаётся ссылкой (текущая страница кликабельна). */\n linkCurrent?: boolean\n /** i18n-метка кнопки раскрытия схлопнутого пути. */\n expandLabel?: string\n /**\n * Схлопывать по доступной ширине, а не по числу пунктов. Путь становится\n * однострочным, середина уходит под «…» ровно настолько, насколько не влезает.\n *\n * Без пропа поведение прежнее: список переносится на вторую строку, а порог\n * задаёт `maxItems`. Вместе пропы совместимы — `maxItems` остаётся жёстким\n * потолком, ширина ужимает дальше.\n */\n autoCollapse?: boolean\n}\n\nconst props = withDefaults(defineProps<GrBreadcrumbsProps>(), {\n as: undefined,\n separator: undefined,\n size: undefined,\n maxItems: undefined,\n itemsBeforeCollapse: 1,\n itemsAfterCollapse: 1,\n ariaLabel: undefined,\n linkCurrent: false,\n expandLabel: undefined,\n autoCollapse: false,\n})\n\ndefineSlots<{\n /** Содержимое пункта целиком (иконка и подпись). */\n item?: (props: { item: GrBreadcrumbItem, index: number, isCurrent: boolean }) => unknown\n /** Разделитель между пунктами. */\n separator?: () => unknown\n /** Кнопка раскрытия схлопнутой середины. */\n ellipsis?: (props: { hiddenCount: number, expand: () => void }) => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrBreadcrumbs' })\nconst resolvedSeparator = useGrComponentProp('GrBreadcrumbs', 'separator', () => props.separator, '/')\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.breadcrumbs.label', 'Breadcrumb'))\nconst resolvedExpandLabel = computed(() => props.expandLabel ?? t('gr.breadcrumbs.expand', 'Show hidden path'))\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst listEl = ref<HTMLElement | null>(null)\nconst expanded = ref(false)\n\n/**\n * Схлопывание по ширине: сколько пунктов хвоста влезает.\n *\n * `undefined` — ещё не мерили, показываем путь целиком. Первый кадр в режиме\n * `autoCollapse` намеренно полный: ширины снимаются с него, а посчитать их до\n * рендера неоткуда.\n */\nconst fitAfter = ref<number | undefined>(undefined)\n\n/** Ширины не зависят от контейнера, поэтому живут до смены самого пути. */\nlet measured: { items: number[], separator: number } | null = null\n/**\n * Ширина кнопки «…» узнаётся только когда она отрисована, то есть уже после\n * первого схлопывания. До этого считаем её нулевой: поправка может лишь\n * ужать хвост ещё на пункт, а не вернуть спрятанное, поэтому качелей не будет.\n */\nlet ellipsisWidth = 0\n/** Ширина, на которой считали в прошлый раз: по её смене раскрытый путь сворачивается. */\nlet lastAvailable = 0\n\n// Новый путь — новая страница: раскрытая середина прошлого пути к ней отношения\n// не имеет, а измеренные ширины относятся к прошлым подписям.\nwatch(() => props.items, () => {\n expanded.value = false\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n void nextTick(measure)\n})\n\nconst lastIndex = computed(() => props.items.length - 1)\n\n/**\n * Схлопывание по ширине выражается через тот же `maxItems`: раскладку считает\n * одна функция, а режимы отличаются только тем, откуда взялось число.\n */\nconst autoMaxItems = computed(() => {\n if (!props.autoCollapse || fitAfter.value === undefined) return undefined\n if (fitAfter.value >= props.items.length) return undefined\n\n return props.items.length - 1\n})\n\nconst effectiveMaxItems = computed(() => {\n const limits = [props.maxItems, autoMaxItems.value].filter((value): value is number => typeof value === 'number' && value > 0)\n\n return limits.length > 0 ? Math.min(...limits) : undefined\n})\n\nconst effectiveAfter = computed(() => (\n props.autoCollapse && fitAfter.value !== undefined ? fitAfter.value : props.itemsAfterCollapse\n))\n\nconst entries = computed(() => resolveBreadcrumbsLayout({\n items: props.items,\n maxItems: effectiveMaxItems.value,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n itemsAfterCollapse: effectiveAfter.value,\n expanded: expanded.value,\n}))\n\nfunction isCurrent(index: number): boolean {\n return index === lastIndex.value\n}\n\n/** Ссылкой пункт становится, только если ведёт куда-то и не выключен. */\nfunction isLink(item: GrBreadcrumbItem, index: number): boolean {\n if (item.disabled) return false\n if (isCurrent(index) && !props.linkCurrent) return false\n return item.href !== undefined || item.to !== undefined || props.as !== undefined\n}\n\nfunction widthOf(el: Element | null | undefined): number {\n // `scrollWidth`, а не прямоугольник: у подписи стоит `truncate`, и в узком\n // контейнере прямоугольник вернул бы уже ужатую ширину, а не собственную.\n return el ? (el as HTMLElement).scrollWidth : 0\n}\n\n/**\n * Снять ширины с полного пути и пересчитать, сколько пунктов хвоста влезает.\n *\n * Замер делается один раз на путь: подписи от ширины контейнера не зависят,\n * поэтому `resize` пересчитывает только арифметику.\n */\nfunction measure(): void {\n if (!props.autoCollapse) return\n\n const list = listEl.value\n if (!list) return\n\n const ellipsis = list.querySelector('[data-gr-breadcrumbs-ellipsis-item]')\n if (ellipsis) ellipsisWidth = widthOf(ellipsis)\n\n if (!measured) {\n // Ширины снимаем только с полного пути: спрятанных пунктов в DOM нет.\n if (fitAfter.value !== undefined) return\n\n const wraps = [...list.querySelectorAll('[data-gr-breadcrumbs-item-wrap]')]\n if (wraps.length !== props.items.length) return\n\n measured = {\n items: wraps.map(widthOf),\n separator: widthOf(list.querySelector('[data-gr-breadcrumbs-separator]')),\n }\n }\n\n const available = list.clientWidth\n // jsdom и скрытый контейнер отдают 0 — решать по такой ширине нечего.\n if (available <= 0) return\n\n lastAvailable = available\n\n fitAfter.value = resolveBreadcrumbsFit({\n itemWidths: measured.items,\n separatorWidth: measured.separator,\n ellipsisWidth,\n available,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n gapWidth: listGap(list),\n })\n}\n\n/** Зазор списка в пикселях: он задан классом, а не пропом, поэтому спрашиваем стиль. */\nfunction listGap(list: HTMLElement): number {\n if (typeof getComputedStyle !== 'function') return 0\n\n return Number.parseFloat(getComputedStyle(list).columnGap) || 0\n}\n\n/**\n * Ширина кнопки «…» известна только после того, как она отрисована, то есть\n * после первого схлопывания. Поэтому решение пересчитывается ещё раз: поправка\n * либо ничего не меняет, либо ужимает хвост на пункт. Цикла нет — второй проход\n * оставляет `fitAfter` прежним, и наблюдатель больше не срабатывает.\n */\nwatch(fitAfter, () => void nextTick(measure))\n\nlet observer: ResizeObserver | null = null\n\nwatch(() => props.autoCollapse, (enabled) => {\n if (enabled) {\n void nextTick(measure)\n return\n }\n\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n})\n\nonMounted(() => {\n void nextTick(measure)\n\n // На сервере и в jsdom `ResizeObserver` отсутствует — измерять там нечего.\n if (typeof ResizeObserver === 'undefined') return\n\n observer = new ResizeObserver(() => {\n // Смена ширины — новая раскладка, и раскрытая руками середина относилась к\n // прежней. Свернуть её иначе нечем: в раскрытом пути кнопки «…» нет, то есть\n // поворот телефона оставлял бы путь развёрнутым навсегда. Высота меняется от\n // самого раскрытия (путь переносится на вторую строку) — на неё не реагируем.\n if (expanded.value && listEl.value && listEl.value.clientWidth !== lastAvailable)\n expanded.value = false\n\n measure()\n })\n if (listEl.value) observer.observe(listEl.value)\n})\n\nonBeforeUnmount(() => observer?.disconnect())\n\nasync function expand(): Promise<void> {\n expanded.value = true\n\n // Кнопка исчезает вместе со схлопыванием, и фокус ушёл бы на `<body>`.\n // Переводим его на первый раскрытый пункт — там, где кнопка и стояла. Пункты\n // без ссылки держат `tabindex=\"-1\"` именно ради этого случая.\n await nextTick()\n const before = Math.max(0, Math.min(props.itemsBeforeCollapse, props.items.length))\n const revealed = rootEl.value?.querySelectorAll<HTMLElement>('[data-gr-breadcrumbs-item]')\n revealed?.[before]?.focus()\n}\n</script>\n\n<template>\n <nav\n ref=\"rootEl\"\n data-gr-breadcrumbs\n :class=\"[breadcrumbsRootClass, breadcrumbsSizeClassBySize[resolvedSize]]\"\n :aria-label=\"resolvedAriaLabel\"\n >\n <ol\n ref=\"listEl\"\n data-gr-breadcrumbs-list\n :class=\"[breadcrumbsListClass, autoCollapse && !expanded ? breadcrumbsListNowrapClass : breadcrumbsListWrapClass]\"\n >\n <template v-for=\"(entry, position) in entries\" :key=\"entry.kind === 'item' ? `item-${entry.index}` : 'ellipsis'\">\n <!--\n Разделитель — отдельный элемент списка и помечен `aria-hidden`:\n структуру пути диктору сообщает сам список, а «/» он бы читал вслух.\n -->\n <li\n v-if=\"position > 0\"\n data-gr-breadcrumbs-separator\n :class=\"breadcrumbsSeparatorClass\"\n aria-hidden=\"true\"\n >\n <slot name=\"separator\">\n {{ resolvedSeparator }}\n </slot>\n </li>\n\n <li v-if=\"entry.kind === 'ellipsis'\" data-gr-breadcrumbs-ellipsis-item class=\"min-w-0\">\n <slot name=\"ellipsis\" :hidden-count=\"entry.hiddenCount\" :expand=\"expand\">\n <button\n type=\"button\"\n data-gr-breadcrumbs-ellipsis\n data-testid=\"gr-breadcrumbs-ellipsis\"\n :class=\"breadcrumbsEllipsisClass\"\n :aria-label=\"resolvedExpandLabel\"\n @click=\"expand\"\n >\n …\n </button>\n </slot>\n </li>\n\n <li v-else data-gr-breadcrumbs-item-wrap class=\"min-w-0\">\n <GrLink\n v-if=\"isLink(entry.item, entry.index)\"\n :key=\"`link-${entry.index}`\"\n data-gr-breadcrumbs-item\n :as=\"as\"\n :href=\"entry.item.href\"\n :to=\"entry.item.to\"\n :size=\"resolvedSize\"\n :variant=\"isCurrent(entry.index) ? 'default' : 'muted'\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </GrLink>\n\n <!--\n Текущая страница и выключенный пункт — не ссылки. `aria-current`\n остаётся на текущем: именно он отвечает на вопрос «где я».\n -->\n <span\n v-else\n data-gr-breadcrumbs-item\n :class=\"breadcrumbsCurrentClass\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n :aria-disabled=\"entry.item.disabled ? 'true' : undefined\"\n tabindex=\"-1\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </span>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport GrLink from '../GrLink/GrLink.vue'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n breadcrumbsCurrentClass,\n breadcrumbsEllipsisClass,\n breadcrumbsItemIconClass,\n breadcrumbsLabelClass,\n breadcrumbsListClass,\n breadcrumbsListNowrapClass,\n breadcrumbsListWrapClass,\n breadcrumbsRootClass,\n breadcrumbsSeparatorClass,\n breadcrumbsSizeClassBySize,\n type GrBreadcrumbItem,\n type GrBreadcrumbsLinkComponent,\n type GrBreadcrumbsSize,\n resolveBreadcrumbsFit,\n resolveBreadcrumbsLayout,\n} from './grBreadcrumbsStyles'\n\nexport type { GrBreadcrumbItem, GrBreadcrumbsSize } from './grBreadcrumbsStyles'\n\n/**\n * Путь до текущей страницы (WAI-ARIA breadcrumb): `<nav>` с именем, внутри\n * упорядоченный список ссылок, последний пункт — текущая страница.\n *\n * Ссылки рисует `GrLink`, поэтому роутер подключается тем же способом, что и\n * везде в пакете: `as` + `to`.\n */\nexport interface GrBreadcrumbsProps {\n /** Путь от корня к текущей странице. Последний пункт — текущая страница. */\n items: GrBreadcrumbItem[]\n /** Компонент ссылки для всех пунктов: `RouterLink`, `NuxtLink`, `Link` Inertia. */\n as?: GrBreadcrumbsLinkComponent\n /** Разделитель между пунктами. Декоративен: диктору не читается. */\n separator?: string\n size?: GrBreadcrumbsSize\n /**\n * С какого числа пунктов схлопывать середину в «…». `0`/не задано — показывать\n * путь целиком.\n */\n maxItems?: number\n /** Сколько пунктов оставить в начале при схлопывании. */\n itemsBeforeCollapse?: number\n /** Сколько пунктов оставить в конце при схлопывании. */\n itemsAfterCollapse?: number\n /** Имя лендмарка. Не задано — берётся из локали. */\n ariaLabel?: string\n /** Последний пункт остаётся ссылкой (текущая страница кликабельна). */\n linkCurrent?: boolean\n /** i18n-метка кнопки раскрытия схлопнутого пути. */\n expandLabel?: string\n /**\n * Схлопывать по доступной ширине, а не по числу пунктов. Путь становится\n * однострочным, середина уходит под «…» ровно настолько, насколько не влезает.\n *\n * Без пропа поведение прежнее: список переносится на вторую строку, а порог\n * задаёт `maxItems`. Вместе пропы совместимы — `maxItems` остаётся жёстким\n * потолком, ширина ужимает дальше.\n */\n autoCollapse?: boolean\n}\n\nconst props = withDefaults(defineProps<GrBreadcrumbsProps>(), {\n as: undefined,\n separator: undefined,\n size: undefined,\n maxItems: undefined,\n itemsBeforeCollapse: 1,\n itemsAfterCollapse: 1,\n ariaLabel: undefined,\n linkCurrent: false,\n expandLabel: undefined,\n autoCollapse: false,\n})\n\ndefineSlots<{\n /** Содержимое пункта целиком (иконка и подпись). */\n item?: (props: { item: GrBreadcrumbItem, index: number, isCurrent: boolean }) => unknown\n /** Разделитель между пунктами. */\n separator?: () => unknown\n /** Кнопка раскрытия схлопнутой середины. */\n ellipsis?: (props: { hiddenCount: number, expand: () => void }) => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrBreadcrumbs' })\nconst resolvedSeparator = useGrComponentProp('GrBreadcrumbs', 'separator', () => props.separator, '/')\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.breadcrumbs.label', 'Breadcrumb'))\nconst resolvedExpandLabel = computed(() => props.expandLabel ?? t('gr.breadcrumbs.expand', 'Show hidden path'))\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst listEl = ref<HTMLElement | null>(null)\nconst expanded = ref(false)\n\n/**\n * Схлопывание по ширине: сколько пунктов хвоста влезает.\n *\n * `undefined` — ещё не мерили, показываем путь целиком. Первый кадр в режиме\n * `autoCollapse` намеренно полный: ширины снимаются с него, а посчитать их до\n * рендера неоткуда.\n */\nconst fitAfter = ref<number | undefined>(undefined)\n\n/** Ширины не зависят от контейнера, поэтому живут до смены самого пути. */\nlet measured: { items: number[], separator: number } | null = null\n/**\n * Ширина кнопки «…» узнаётся только когда она отрисована, то есть уже после\n * первого схлопывания. До этого считаем её нулевой: поправка может лишь\n * ужать хвост ещё на пункт, а не вернуть спрятанное, поэтому качелей не будет.\n */\nlet ellipsisWidth = 0\n/** Ширина, на которой считали в прошлый раз: по её смене раскрытый путь сворачивается. */\nlet lastAvailable = 0\n\n// Новый путь — новая страница: раскрытая середина прошлого пути к ней отношения\n// не имеет, а измеренные ширины относятся к прошлым подписям.\nwatch(() => props.items, () => {\n expanded.value = false\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n void nextTick(measure)\n})\n\nconst lastIndex = computed(() => props.items.length - 1)\n\n/**\n * Схлопывание по ширине выражается через тот же `maxItems`: раскладку считает\n * одна функция, а режимы отличаются только тем, откуда взялось число.\n */\nconst autoMaxItems = computed(() => {\n if (!props.autoCollapse || fitAfter.value === undefined) return undefined\n if (fitAfter.value >= props.items.length) return undefined\n\n return props.items.length - 1\n})\n\nconst effectiveMaxItems = computed(() => {\n const limits = [props.maxItems, autoMaxItems.value].filter((value): value is number => typeof value === 'number' && value > 0)\n\n return limits.length > 0 ? Math.min(...limits) : undefined\n})\n\nconst effectiveAfter = computed(() => (\n props.autoCollapse && fitAfter.value !== undefined ? fitAfter.value : props.itemsAfterCollapse\n))\n\nconst entries = computed(() => resolveBreadcrumbsLayout({\n items: props.items,\n maxItems: effectiveMaxItems.value,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n itemsAfterCollapse: effectiveAfter.value,\n expanded: expanded.value,\n}))\n\nfunction isCurrent(index: number): boolean {\n return index === lastIndex.value\n}\n\n/** Ссылкой пункт становится, только если ведёт куда-то и не выключен. */\nfunction isLink(item: GrBreadcrumbItem, index: number): boolean {\n if (item.disabled) return false\n if (isCurrent(index) && !props.linkCurrent) return false\n return item.href !== undefined || item.to !== undefined || props.as !== undefined\n}\n\nfunction widthOf(el: Element | null | undefined): number {\n // `scrollWidth`, а не прямоугольник: у подписи стоит `truncate`, и в узком\n // контейнере прямоугольник вернул бы уже ужатую ширину, а не собственную.\n return el ? (el as HTMLElement).scrollWidth : 0\n}\n\n/**\n * Снять ширины с полного пути и пересчитать, сколько пунктов хвоста влезает.\n *\n * Замер делается один раз на путь: подписи от ширины контейнера не зависят,\n * поэтому `resize` пересчитывает только арифметику.\n */\nfunction measure(): void {\n if (!props.autoCollapse) return\n\n const list = listEl.value\n if (!list) return\n\n const ellipsis = list.querySelector('[data-gr-breadcrumbs-ellipsis-item]')\n if (ellipsis) ellipsisWidth = widthOf(ellipsis)\n\n if (!measured) {\n // Ширины снимаем только с полного пути: спрятанных пунктов в DOM нет.\n if (fitAfter.value !== undefined) return\n\n const wraps = [...list.querySelectorAll('[data-gr-breadcrumbs-item-wrap]')]\n if (wraps.length !== props.items.length) return\n\n measured = {\n items: wraps.map(widthOf),\n separator: widthOf(list.querySelector('[data-gr-breadcrumbs-separator]')),\n }\n }\n\n const available = list.clientWidth\n // jsdom и скрытый контейнер отдают 0 — решать по такой ширине нечего.\n if (available <= 0) return\n\n lastAvailable = available\n\n fitAfter.value = resolveBreadcrumbsFit({\n itemWidths: measured.items,\n separatorWidth: measured.separator,\n ellipsisWidth,\n available,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n gapWidth: listGap(list),\n })\n}\n\n/** Зазор списка в пикселях: он задан классом, а не пропом, поэтому спрашиваем стиль. */\nfunction listGap(list: HTMLElement): number {\n if (typeof getComputedStyle !== 'function') return 0\n\n return Number.parseFloat(getComputedStyle(list).columnGap) || 0\n}\n\n/**\n * Ширина кнопки «…» известна только после того, как она отрисована, то есть\n * после первого схлопывания. Поэтому решение пересчитывается ещё раз: поправка\n * либо ничего не меняет, либо ужимает хвост на пункт. Цикла нет — второй проход\n * оставляет `fitAfter` прежним, и наблюдатель больше не срабатывает.\n */\nwatch(fitAfter, () => void nextTick(measure))\n\nlet observer: ResizeObserver | null = null\n\nwatch(() => props.autoCollapse, (enabled) => {\n if (enabled) {\n void nextTick(measure)\n return\n }\n\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n})\n\nonMounted(() => {\n void nextTick(measure)\n\n // На сервере и в jsdom `ResizeObserver` отсутствует — измерять там нечего.\n if (typeof ResizeObserver === 'undefined') return\n\n observer = new ResizeObserver(() => {\n // Смена ширины — новая раскладка, и раскрытая руками середина относилась к\n // прежней. Свернуть её иначе нечем: в раскрытом пути кнопки «…» нет, то есть\n // поворот телефона оставлял бы путь развёрнутым навсегда. Высота меняется от\n // самого раскрытия (путь переносится на вторую строку) — на неё не реагируем.\n if (expanded.value && listEl.value && listEl.value.clientWidth !== lastAvailable)\n expanded.value = false\n\n measure()\n })\n if (listEl.value) observer.observe(listEl.value)\n})\n\nonBeforeUnmount(() => observer?.disconnect())\n\nasync function expand(): Promise<void> {\n expanded.value = true\n\n // Кнопка исчезает вместе со схлопыванием, и фокус ушёл бы на `<body>`.\n // Переводим его на первый раскрытый пункт — там, где кнопка и стояла. Пункты\n // без ссылки держат `tabindex=\"-1\"` именно ради этого случая.\n await nextTick()\n const before = Math.max(0, Math.min(props.itemsBeforeCollapse, props.items.length))\n const revealed = rootEl.value?.querySelectorAll<HTMLElement>('[data-gr-breadcrumbs-item]')\n revealed?.[before]?.focus()\n}\n</script>\n\n<template>\n <nav\n ref=\"rootEl\"\n data-gr-breadcrumbs\n :class=\"[breadcrumbsRootClass, breadcrumbsSizeClassBySize[resolvedSize]]\"\n :aria-label=\"resolvedAriaLabel\"\n >\n <ol\n ref=\"listEl\"\n data-gr-breadcrumbs-list\n :class=\"[breadcrumbsListClass, autoCollapse && !expanded ? breadcrumbsListNowrapClass : breadcrumbsListWrapClass]\"\n >\n <template v-for=\"(entry, position) in entries\" :key=\"entry.kind === 'item' ? `item-${entry.index}` : 'ellipsis'\">\n <!--\n Разделитель — отдельный элемент списка и помечен `aria-hidden`:\n структуру пути диктору сообщает сам список, а «/» он бы читал вслух.\n -->\n <li\n v-if=\"position > 0\"\n data-gr-breadcrumbs-separator\n :class=\"breadcrumbsSeparatorClass\"\n aria-hidden=\"true\"\n >\n <slot name=\"separator\">\n {{ resolvedSeparator }}\n </slot>\n </li>\n\n <li v-if=\"entry.kind === 'ellipsis'\" data-gr-breadcrumbs-ellipsis-item class=\"min-w-0\">\n <slot name=\"ellipsis\" :hidden-count=\"entry.hiddenCount\" :expand=\"expand\">\n <button\n type=\"button\"\n data-gr-breadcrumbs-ellipsis\n data-testid=\"gr-breadcrumbs-ellipsis\"\n :class=\"breadcrumbsEllipsisClass\"\n :aria-label=\"resolvedExpandLabel\"\n @click=\"expand\"\n >\n …\n </button>\n </slot>\n </li>\n\n <li v-else data-gr-breadcrumbs-item-wrap class=\"min-w-0\">\n <GrLink\n v-if=\"isLink(entry.item, entry.index)\"\n :key=\"`link-${entry.index}`\"\n data-gr-breadcrumbs-item\n :as=\"as\"\n :href=\"entry.item.href\"\n :to=\"entry.item.to\"\n :size=\"resolvedSize\"\n :variant=\"isCurrent(entry.index) ? 'default' : 'muted'\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </GrLink>\n\n <!--\n Текущая страница и выключенный пункт — не ссылки. `aria-current`\n остаётся на текущем: именно он отвечает на вопрос «где я».\n -->\n <span\n v-else\n data-gr-breadcrumbs-item\n :class=\"breadcrumbsCurrentClass\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n :aria-disabled=\"entry.item.disabled ? 'true' : undefined\"\n tabindex=\"-1\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </span>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GrBreadcrumbs-jtSnMEtg.js","names":[],"sources":["../../../../src/components/GrBreadcrumbs/GrBreadcrumbs.vue","../../../../src/components/GrBreadcrumbs/GrBreadcrumbs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport GrLink from '../GrLink/GrLink.vue'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n breadcrumbsCurrentClass,\n breadcrumbsEllipsisClass,\n breadcrumbsItemIconClass,\n breadcrumbsLabelClass,\n breadcrumbsListClass,\n breadcrumbsListNowrapClass,\n breadcrumbsListWrapClass,\n breadcrumbsRootClass,\n breadcrumbsSeparatorClass,\n breadcrumbsSizeClassBySize,\n type GrBreadcrumbItem,\n type GrBreadcrumbsLinkComponent,\n type GrBreadcrumbsSize,\n resolveBreadcrumbsFit,\n resolveBreadcrumbsLayout,\n} from './grBreadcrumbsStyles'\n\nexport type { GrBreadcrumbItem, GrBreadcrumbsSize } from './grBreadcrumbsStyles'\n\n/**\n * Путь до текущей страницы (WAI-ARIA breadcrumb): `<nav>` с именем, внутри\n * упорядоченный список ссылок, последний пункт — текущая страница.\n *\n * Ссылки рисует `GrLink`, поэтому роутер подключается тем же способом, что и\n * везде в пакете: `as` + `to`.\n */\nexport interface GrBreadcrumbsProps {\n /** Путь от корня к текущей странице. Последний пункт — текущая страница. */\n items: GrBreadcrumbItem[]\n /** Компонент ссылки для всех пунктов: `RouterLink`, `NuxtLink`, `Link` Inertia. */\n as?: GrBreadcrumbsLinkComponent\n /** Разделитель между пунктами. Декоративен: диктору не читается. */\n separator?: string\n size?: GrBreadcrumbsSize\n /**\n * С какого числа пунктов схлопывать середину в «…». `0`/не задано — показывать\n * путь целиком.\n */\n maxItems?: number\n /** Сколько пунктов оставить в начале при схлопывании. */\n itemsBeforeCollapse?: number\n /** Сколько пунктов оставить в конце при схлопывании. */\n itemsAfterCollapse?: number\n /** Имя лендмарка. Не задано — берётся из локали. */\n ariaLabel?: string\n /** Последний пункт остаётся ссылкой (текущая страница кликабельна). */\n linkCurrent?: boolean\n /** i18n-метка кнопки раскрытия схлопнутого пути. */\n expandLabel?: string\n /**\n * Схлопывать по доступной ширине, а не по числу пунктов. Путь становится\n * однострочным, середина уходит под «…» ровно настолько, насколько не влезает.\n *\n * Без пропа поведение прежнее: список переносится на вторую строку, а порог\n * задаёт `maxItems`. Вместе пропы совместимы — `maxItems` остаётся жёстким\n * потолком, ширина ужимает дальше.\n */\n autoCollapse?: boolean\n}\n\nconst props = withDefaults(defineProps<GrBreadcrumbsProps>(), {\n as: undefined,\n separator: undefined,\n size: undefined,\n maxItems: undefined,\n itemsBeforeCollapse: 1,\n itemsAfterCollapse: 1,\n ariaLabel: undefined,\n linkCurrent: false,\n expandLabel: undefined,\n autoCollapse: false,\n})\n\ndefineSlots<{\n /** Содержимое пункта целиком (иконка и подпись). */\n item?: (props: { item: GrBreadcrumbItem, index: number, isCurrent: boolean }) => unknown\n /** Разделитель между пунктами. */\n separator?: () => unknown\n /** Кнопка раскрытия схлопнутой середины. */\n ellipsis?: (props: { hiddenCount: number, expand: () => void }) => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrBreadcrumbs' })\nconst resolvedSeparator = useGrComponentProp('GrBreadcrumbs', 'separator', () => props.separator, '/')\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.breadcrumbs.label', 'Breadcrumb'))\nconst resolvedExpandLabel = computed(() => props.expandLabel ?? t('gr.breadcrumbs.expand', 'Show hidden path'))\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst listEl = ref<HTMLElement | null>(null)\nconst expanded = ref(false)\n\n/**\n * Схлопывание по ширине: сколько пунктов хвоста влезает.\n *\n * `undefined` — ещё не мерили, показываем путь целиком. Первый кадр в режиме\n * `autoCollapse` намеренно полный: ширины снимаются с него, а посчитать их до\n * рендера неоткуда.\n */\nconst fitAfter = ref<number | undefined>(undefined)\n\n/** Ширины не зависят от контейнера, поэтому живут до смены самого пути. */\nlet measured: { items: number[], separator: number } | null = null\n/**\n * Ширина кнопки «…» узнаётся только когда она отрисована, то есть уже после\n * первого схлопывания. До этого считаем её нулевой: поправка может лишь\n * ужать хвост ещё на пункт, а не вернуть спрятанное, поэтому качелей не будет.\n */\nlet ellipsisWidth = 0\n/** Ширина, на которой считали в прошлый раз: по её смене раскрытый путь сворачивается. */\nlet lastAvailable = 0\n\n// Новый путь — новая страница: раскрытая середина прошлого пути к ней отношения\n// не имеет, а измеренные ширины относятся к прошлым подписям.\nwatch(() => props.items, () => {\n expanded.value = false\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n void nextTick(measure)\n})\n\nconst lastIndex = computed(() => props.items.length - 1)\n\n/**\n * Схлопывание по ширине выражается через тот же `maxItems`: раскладку считает\n * одна функция, а режимы отличаются только тем, откуда взялось число.\n */\nconst autoMaxItems = computed(() => {\n if (!props.autoCollapse || fitAfter.value === undefined) return undefined\n if (fitAfter.value >= props.items.length) return undefined\n\n return props.items.length - 1\n})\n\nconst effectiveMaxItems = computed(() => {\n const limits = [props.maxItems, autoMaxItems.value].filter((value): value is number => typeof value === 'number' && value > 0)\n\n return limits.length > 0 ? Math.min(...limits) : undefined\n})\n\nconst effectiveAfter = computed(() => (\n props.autoCollapse && fitAfter.value !== undefined ? fitAfter.value : props.itemsAfterCollapse\n))\n\nconst entries = computed(() => resolveBreadcrumbsLayout({\n items: props.items,\n maxItems: effectiveMaxItems.value,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n itemsAfterCollapse: effectiveAfter.value,\n expanded: expanded.value,\n}))\n\nfunction isCurrent(index: number): boolean {\n return index === lastIndex.value\n}\n\n/** Ссылкой пункт становится, только если ведёт куда-то и не выключен. */\nfunction isLink(item: GrBreadcrumbItem, index: number): boolean {\n if (item.disabled) return false\n if (isCurrent(index) && !props.linkCurrent) return false\n return item.href !== undefined || item.to !== undefined || props.as !== undefined\n}\n\nfunction widthOf(el: Element | null | undefined): number {\n // `scrollWidth`, а не прямоугольник: у подписи стоит `truncate`, и в узком\n // контейнере прямоугольник вернул бы уже ужатую ширину, а не собственную.\n return el ? (el as HTMLElement).scrollWidth : 0\n}\n\n/**\n * Снять ширины с полного пути и пересчитать, сколько пунктов хвоста влезает.\n *\n * Замер делается один раз на путь: подписи от ширины контейнера не зависят,\n * поэтому `resize` пересчитывает только арифметику.\n */\nfunction measure(): void {\n if (!props.autoCollapse) return\n\n const list = listEl.value\n if (!list) return\n\n const ellipsis = list.querySelector('[data-gr-breadcrumbs-ellipsis-item]')\n if (ellipsis) ellipsisWidth = widthOf(ellipsis)\n\n if (!measured) {\n // Ширины снимаем только с полного пути: спрятанных пунктов в DOM нет.\n if (fitAfter.value !== undefined) return\n\n const wraps = [...list.querySelectorAll('[data-gr-breadcrumbs-item-wrap]')]\n if (wraps.length !== props.items.length) return\n\n measured = {\n items: wraps.map(widthOf),\n separator: widthOf(list.querySelector('[data-gr-breadcrumbs-separator]')),\n }\n }\n\n const available = list.clientWidth\n // jsdom и скрытый контейнер отдают 0 — решать по такой ширине нечего.\n if (available <= 0) return\n\n lastAvailable = available\n\n fitAfter.value = resolveBreadcrumbsFit({\n itemWidths: measured.items,\n separatorWidth: measured.separator,\n ellipsisWidth,\n available,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n gapWidth: listGap(list),\n })\n}\n\n/** Зазор списка в пикселях: он задан классом, а не пропом, поэтому спрашиваем стиль. */\nfunction listGap(list: HTMLElement): number {\n if (typeof getComputedStyle !== 'function') return 0\n\n return Number.parseFloat(getComputedStyle(list).columnGap) || 0\n}\n\n/**\n * Ширина кнопки «…» известна только после того, как она отрисована, то есть\n * после первого схлопывания. Поэтому решение пересчитывается ещё раз: поправка\n * либо ничего не меняет, либо ужимает хвост на пункт. Цикла нет — второй проход\n * оставляет `fitAfter` прежним, и наблюдатель больше не срабатывает.\n */\nwatch(fitAfter, () => void nextTick(measure))\n\nlet observer: ResizeObserver | null = null\n\nwatch(() => props.autoCollapse, (enabled) => {\n if (enabled) {\n void nextTick(measure)\n return\n }\n\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n})\n\nonMounted(() => {\n void nextTick(measure)\n\n // На сервере и в jsdom `ResizeObserver` отсутствует — измерять там нечего.\n if (typeof ResizeObserver === 'undefined') return\n\n observer = new ResizeObserver(() => {\n // Смена ширины — новая раскладка, и раскрытая руками середина относилась к\n // прежней. Свернуть её иначе нечем: в раскрытом пути кнопки «…» нет, то есть\n // поворот телефона оставлял бы путь развёрнутым навсегда. Высота меняется от\n // самого раскрытия (путь переносится на вторую строку) — на неё не реагируем.\n if (expanded.value && listEl.value && listEl.value.clientWidth !== lastAvailable)\n expanded.value = false\n\n measure()\n })\n if (listEl.value) observer.observe(listEl.value)\n})\n\nonBeforeUnmount(() => observer?.disconnect())\n\nasync function expand(): Promise<void> {\n expanded.value = true\n\n // Кнопка исчезает вместе со схлопыванием, и фокус ушёл бы на `<body>`.\n // Переводим его на первый раскрытый пункт — там, где кнопка и стояла. Пункты\n // без ссылки держат `tabindex=\"-1\"` именно ради этого случая.\n await nextTick()\n const before = Math.max(0, Math.min(props.itemsBeforeCollapse, props.items.length))\n const revealed = rootEl.value?.querySelectorAll<HTMLElement>('[data-gr-breadcrumbs-item]')\n revealed?.[before]?.focus()\n}\n</script>\n\n<template>\n <nav\n ref=\"rootEl\"\n data-gr-breadcrumbs\n :class=\"[breadcrumbsRootClass, breadcrumbsSizeClassBySize[resolvedSize]]\"\n :aria-label=\"resolvedAriaLabel\"\n >\n <ol\n ref=\"listEl\"\n data-gr-breadcrumbs-list\n :class=\"[breadcrumbsListClass, autoCollapse && !expanded ? breadcrumbsListNowrapClass : breadcrumbsListWrapClass]\"\n >\n <template v-for=\"(entry, position) in entries\" :key=\"entry.kind === 'item' ? `item-${entry.index}` : 'ellipsis'\">\n <!--\n Разделитель — отдельный элемент списка и помечен `aria-hidden`:\n структуру пути диктору сообщает сам список, а «/» он бы читал вслух.\n -->\n <li\n v-if=\"position > 0\"\n data-gr-breadcrumbs-separator\n :class=\"breadcrumbsSeparatorClass\"\n aria-hidden=\"true\"\n >\n <slot name=\"separator\">\n {{ resolvedSeparator }}\n </slot>\n </li>\n\n <li v-if=\"entry.kind === 'ellipsis'\" data-gr-breadcrumbs-ellipsis-item class=\"min-w-0\">\n <slot name=\"ellipsis\" :hidden-count=\"entry.hiddenCount\" :expand=\"expand\">\n <button\n type=\"button\"\n data-gr-breadcrumbs-ellipsis\n data-testid=\"gr-breadcrumbs-ellipsis\"\n :class=\"breadcrumbsEllipsisClass\"\n :aria-label=\"resolvedExpandLabel\"\n @click=\"expand\"\n >\n …\n </button>\n </slot>\n </li>\n\n <li v-else data-gr-breadcrumbs-item-wrap class=\"min-w-0\">\n <GrLink\n v-if=\"isLink(entry.item, entry.index)\"\n :key=\"`link-${entry.index}`\"\n data-gr-breadcrumbs-item\n :as=\"as\"\n :href=\"entry.item.href\"\n :to=\"entry.item.to\"\n :size=\"resolvedSize\"\n :variant=\"isCurrent(entry.index) ? 'default' : 'muted'\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </GrLink>\n\n <!--\n Текущая страница и выключенный пункт — не ссылки. `aria-current`\n остаётся на текущем: именно он отвечает на вопрос «где я».\n -->\n <span\n v-else\n data-gr-breadcrumbs-item\n :class=\"breadcrumbsCurrentClass\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n :aria-disabled=\"entry.item.disabled ? 'true' : undefined\"\n tabindex=\"-1\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </span>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport GrLink from '../GrLink/GrLink.vue'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n breadcrumbsCurrentClass,\n breadcrumbsEllipsisClass,\n breadcrumbsItemIconClass,\n breadcrumbsLabelClass,\n breadcrumbsListClass,\n breadcrumbsListNowrapClass,\n breadcrumbsListWrapClass,\n breadcrumbsRootClass,\n breadcrumbsSeparatorClass,\n breadcrumbsSizeClassBySize,\n type GrBreadcrumbItem,\n type GrBreadcrumbsLinkComponent,\n type GrBreadcrumbsSize,\n resolveBreadcrumbsFit,\n resolveBreadcrumbsLayout,\n} from './grBreadcrumbsStyles'\n\nexport type { GrBreadcrumbItem, GrBreadcrumbsSize } from './grBreadcrumbsStyles'\n\n/**\n * Путь до текущей страницы (WAI-ARIA breadcrumb): `<nav>` с именем, внутри\n * упорядоченный список ссылок, последний пункт — текущая страница.\n *\n * Ссылки рисует `GrLink`, поэтому роутер подключается тем же способом, что и\n * везде в пакете: `as` + `to`.\n */\nexport interface GrBreadcrumbsProps {\n /** Путь от корня к текущей странице. Последний пункт — текущая страница. */\n items: GrBreadcrumbItem[]\n /** Компонент ссылки для всех пунктов: `RouterLink`, `NuxtLink`, `Link` Inertia. */\n as?: GrBreadcrumbsLinkComponent\n /** Разделитель между пунктами. Декоративен: диктору не читается. */\n separator?: string\n size?: GrBreadcrumbsSize\n /**\n * С какого числа пунктов схлопывать середину в «…». `0`/не задано — показывать\n * путь целиком.\n */\n maxItems?: number\n /** Сколько пунктов оставить в начале при схлопывании. */\n itemsBeforeCollapse?: number\n /** Сколько пунктов оставить в конце при схлопывании. */\n itemsAfterCollapse?: number\n /** Имя лендмарка. Не задано — берётся из локали. */\n ariaLabel?: string\n /** Последний пункт остаётся ссылкой (текущая страница кликабельна). */\n linkCurrent?: boolean\n /** i18n-метка кнопки раскрытия схлопнутого пути. */\n expandLabel?: string\n /**\n * Схлопывать по доступной ширине, а не по числу пунктов. Путь становится\n * однострочным, середина уходит под «…» ровно настолько, насколько не влезает.\n *\n * Без пропа поведение прежнее: список переносится на вторую строку, а порог\n * задаёт `maxItems`. Вместе пропы совместимы — `maxItems` остаётся жёстким\n * потолком, ширина ужимает дальше.\n */\n autoCollapse?: boolean\n}\n\nconst props = withDefaults(defineProps<GrBreadcrumbsProps>(), {\n as: undefined,\n separator: undefined,\n size: undefined,\n maxItems: undefined,\n itemsBeforeCollapse: 1,\n itemsAfterCollapse: 1,\n ariaLabel: undefined,\n linkCurrent: false,\n expandLabel: undefined,\n autoCollapse: false,\n})\n\ndefineSlots<{\n /** Содержимое пункта целиком (иконка и подпись). */\n item?: (props: { item: GrBreadcrumbItem, index: number, isCurrent: boolean }) => unknown\n /** Разделитель между пунктами. */\n separator?: () => unknown\n /** Кнопка раскрытия схлопнутой середины. */\n ellipsis?: (props: { hiddenCount: number, expand: () => void }) => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrBreadcrumbs' })\nconst resolvedSeparator = useGrComponentProp('GrBreadcrumbs', 'separator', () => props.separator, '/')\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.breadcrumbs.label', 'Breadcrumb'))\nconst resolvedExpandLabel = computed(() => props.expandLabel ?? t('gr.breadcrumbs.expand', 'Show hidden path'))\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst listEl = ref<HTMLElement | null>(null)\nconst expanded = ref(false)\n\n/**\n * Схлопывание по ширине: сколько пунктов хвоста влезает.\n *\n * `undefined` — ещё не мерили, показываем путь целиком. Первый кадр в режиме\n * `autoCollapse` намеренно полный: ширины снимаются с него, а посчитать их до\n * рендера неоткуда.\n */\nconst fitAfter = ref<number | undefined>(undefined)\n\n/** Ширины не зависят от контейнера, поэтому живут до смены самого пути. */\nlet measured: { items: number[], separator: number } | null = null\n/**\n * Ширина кнопки «…» узнаётся только когда она отрисована, то есть уже после\n * первого схлопывания. До этого считаем её нулевой: поправка может лишь\n * ужать хвост ещё на пункт, а не вернуть спрятанное, поэтому качелей не будет.\n */\nlet ellipsisWidth = 0\n/** Ширина, на которой считали в прошлый раз: по её смене раскрытый путь сворачивается. */\nlet lastAvailable = 0\n\n// Новый путь — новая страница: раскрытая середина прошлого пути к ней отношения\n// не имеет, а измеренные ширины относятся к прошлым подписям.\nwatch(() => props.items, () => {\n expanded.value = false\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n void nextTick(measure)\n})\n\nconst lastIndex = computed(() => props.items.length - 1)\n\n/**\n * Схлопывание по ширине выражается через тот же `maxItems`: раскладку считает\n * одна функция, а режимы отличаются только тем, откуда взялось число.\n */\nconst autoMaxItems = computed(() => {\n if (!props.autoCollapse || fitAfter.value === undefined) return undefined\n if (fitAfter.value >= props.items.length) return undefined\n\n return props.items.length - 1\n})\n\nconst effectiveMaxItems = computed(() => {\n const limits = [props.maxItems, autoMaxItems.value].filter((value): value is number => typeof value === 'number' && value > 0)\n\n return limits.length > 0 ? Math.min(...limits) : undefined\n})\n\nconst effectiveAfter = computed(() => (\n props.autoCollapse && fitAfter.value !== undefined ? fitAfter.value : props.itemsAfterCollapse\n))\n\nconst entries = computed(() => resolveBreadcrumbsLayout({\n items: props.items,\n maxItems: effectiveMaxItems.value,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n itemsAfterCollapse: effectiveAfter.value,\n expanded: expanded.value,\n}))\n\nfunction isCurrent(index: number): boolean {\n return index === lastIndex.value\n}\n\n/** Ссылкой пункт становится, только если ведёт куда-то и не выключен. */\nfunction isLink(item: GrBreadcrumbItem, index: number): boolean {\n if (item.disabled) return false\n if (isCurrent(index) && !props.linkCurrent) return false\n return item.href !== undefined || item.to !== undefined || props.as !== undefined\n}\n\nfunction widthOf(el: Element | null | undefined): number {\n // `scrollWidth`, а не прямоугольник: у подписи стоит `truncate`, и в узком\n // контейнере прямоугольник вернул бы уже ужатую ширину, а не собственную.\n return el ? (el as HTMLElement).scrollWidth : 0\n}\n\n/**\n * Снять ширины с полного пути и пересчитать, сколько пунктов хвоста влезает.\n *\n * Замер делается один раз на путь: подписи от ширины контейнера не зависят,\n * поэтому `resize` пересчитывает только арифметику.\n */\nfunction measure(): void {\n if (!props.autoCollapse) return\n\n const list = listEl.value\n if (!list) return\n\n const ellipsis = list.querySelector('[data-gr-breadcrumbs-ellipsis-item]')\n if (ellipsis) ellipsisWidth = widthOf(ellipsis)\n\n if (!measured) {\n // Ширины снимаем только с полного пути: спрятанных пунктов в DOM нет.\n if (fitAfter.value !== undefined) return\n\n const wraps = [...list.querySelectorAll('[data-gr-breadcrumbs-item-wrap]')]\n if (wraps.length !== props.items.length) return\n\n measured = {\n items: wraps.map(widthOf),\n separator: widthOf(list.querySelector('[data-gr-breadcrumbs-separator]')),\n }\n }\n\n const available = list.clientWidth\n // jsdom и скрытый контейнер отдают 0 — решать по такой ширине нечего.\n if (available <= 0) return\n\n lastAvailable = available\n\n fitAfter.value = resolveBreadcrumbsFit({\n itemWidths: measured.items,\n separatorWidth: measured.separator,\n ellipsisWidth,\n available,\n itemsBeforeCollapse: props.itemsBeforeCollapse,\n gapWidth: listGap(list),\n })\n}\n\n/** Зазор списка в пикселях: он задан классом, а не пропом, поэтому спрашиваем стиль. */\nfunction listGap(list: HTMLElement): number {\n if (typeof getComputedStyle !== 'function') return 0\n\n return Number.parseFloat(getComputedStyle(list).columnGap) || 0\n}\n\n/**\n * Ширина кнопки «…» известна только после того, как она отрисована, то есть\n * после первого схлопывания. Поэтому решение пересчитывается ещё раз: поправка\n * либо ничего не меняет, либо ужимает хвост на пункт. Цикла нет — второй проход\n * оставляет `fitAfter` прежним, и наблюдатель больше не срабатывает.\n */\nwatch(fitAfter, () => void nextTick(measure))\n\nlet observer: ResizeObserver | null = null\n\nwatch(() => props.autoCollapse, (enabled) => {\n if (enabled) {\n void nextTick(measure)\n return\n }\n\n measured = null\n ellipsisWidth = 0\n fitAfter.value = undefined\n})\n\nonMounted(() => {\n void nextTick(measure)\n\n // На сервере и в jsdom `ResizeObserver` отсутствует — измерять там нечего.\n if (typeof ResizeObserver === 'undefined') return\n\n observer = new ResizeObserver(() => {\n // Смена ширины — новая раскладка, и раскрытая руками середина относилась к\n // прежней. Свернуть её иначе нечем: в раскрытом пути кнопки «…» нет, то есть\n // поворот телефона оставлял бы путь развёрнутым навсегда. Высота меняется от\n // самого раскрытия (путь переносится на вторую строку) — на неё не реагируем.\n if (expanded.value && listEl.value && listEl.value.clientWidth !== lastAvailable)\n expanded.value = false\n\n measure()\n })\n if (listEl.value) observer.observe(listEl.value)\n})\n\nonBeforeUnmount(() => observer?.disconnect())\n\nasync function expand(): Promise<void> {\n expanded.value = true\n\n // Кнопка исчезает вместе со схлопыванием, и фокус ушёл бы на `<body>`.\n // Переводим его на первый раскрытый пункт — там, где кнопка и стояла. Пункты\n // без ссылки держат `tabindex=\"-1\"` именно ради этого случая.\n await nextTick()\n const before = Math.max(0, Math.min(props.itemsBeforeCollapse, props.items.length))\n const revealed = rootEl.value?.querySelectorAll<HTMLElement>('[data-gr-breadcrumbs-item]')\n revealed?.[before]?.focus()\n}\n</script>\n\n<template>\n <nav\n ref=\"rootEl\"\n data-gr-breadcrumbs\n :class=\"[breadcrumbsRootClass, breadcrumbsSizeClassBySize[resolvedSize]]\"\n :aria-label=\"resolvedAriaLabel\"\n >\n <ol\n ref=\"listEl\"\n data-gr-breadcrumbs-list\n :class=\"[breadcrumbsListClass, autoCollapse && !expanded ? breadcrumbsListNowrapClass : breadcrumbsListWrapClass]\"\n >\n <template v-for=\"(entry, position) in entries\" :key=\"entry.kind === 'item' ? `item-${entry.index}` : 'ellipsis'\">\n <!--\n Разделитель — отдельный элемент списка и помечен `aria-hidden`:\n структуру пути диктору сообщает сам список, а «/» он бы читал вслух.\n -->\n <li\n v-if=\"position > 0\"\n data-gr-breadcrumbs-separator\n :class=\"breadcrumbsSeparatorClass\"\n aria-hidden=\"true\"\n >\n <slot name=\"separator\">\n {{ resolvedSeparator }}\n </slot>\n </li>\n\n <li v-if=\"entry.kind === 'ellipsis'\" data-gr-breadcrumbs-ellipsis-item class=\"min-w-0\">\n <slot name=\"ellipsis\" :hidden-count=\"entry.hiddenCount\" :expand=\"expand\">\n <button\n type=\"button\"\n data-gr-breadcrumbs-ellipsis\n data-testid=\"gr-breadcrumbs-ellipsis\"\n :class=\"breadcrumbsEllipsisClass\"\n :aria-label=\"resolvedExpandLabel\"\n @click=\"expand\"\n >\n …\n </button>\n </slot>\n </li>\n\n <li v-else data-gr-breadcrumbs-item-wrap class=\"min-w-0\">\n <GrLink\n v-if=\"isLink(entry.item, entry.index)\"\n :key=\"`link-${entry.index}`\"\n data-gr-breadcrumbs-item\n :as=\"as\"\n :href=\"entry.item.href\"\n :to=\"entry.item.to\"\n :size=\"resolvedSize\"\n :variant=\"isCurrent(entry.index) ? 'default' : 'muted'\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </GrLink>\n\n <!--\n Текущая страница и выключенный пункт — не ссылки. `aria-current`\n остаётся на текущем: именно он отвечает на вопрос «где я».\n -->\n <span\n v-else\n data-gr-breadcrumbs-item\n :class=\"breadcrumbsCurrentClass\"\n :aria-label=\"entry.item.ariaLabel\"\n :aria-current=\"isCurrent(entry.index) ? 'page' : undefined\"\n :aria-disabled=\"entry.item.disabled ? 'true' : undefined\"\n tabindex=\"-1\"\n >\n <slot name=\"item\" :item=\"entry.item\" :index=\"entry.index\" :is-current=\"isCurrent(entry.index)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n :class=\"[breadcrumbsItemIconClass, iconClass(entry.item.icon)]\"\n aria-hidden=\"true\"\n />\n <span :class=\"breadcrumbsLabelClass\">{{ entry.item.label }}</span>\n </slot>\n </span>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { m as resolveBreadcrumbsLayout, n as grBreadcrumbsSafelist, p as resolveBreadcrumbsFit, t as grBreadcrumbsConfig } from "../../chunks/config-
|
|
2
|
-
import { t as GrBreadcrumbs_default } from "./chunks/GrBreadcrumbs-
|
|
1
|
+
import { m as resolveBreadcrumbsLayout, n as grBreadcrumbsSafelist, p as resolveBreadcrumbsFit, t as grBreadcrumbsConfig } from "../../chunks/config-DcfWZOi5.js";
|
|
2
|
+
import { t as GrBreadcrumbs_default } from "./chunks/GrBreadcrumbs-jtSnMEtg.js";
|
|
3
3
|
export { GrBreadcrumbs_default as GrBreadcrumbs, GrBreadcrumbs_default as default, grBreadcrumbsConfig, grBreadcrumbsSafelist, resolveBreadcrumbsFit, resolveBreadcrumbsLayout };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
|
|
2
2
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
3
3
|
import { t as loader_circle_default } from "../../../chunks/loader-circle-CfVLz7lb.js";
|
|
4
|
-
import { n as useGrButtonGroup } from "../../../chunks/context-
|
|
4
|
+
import { n as useGrButtonGroup } from "../../../chunks/context-BfIQv7m1.js";
|
|
5
5
|
import { a as grButtonClass, i as grButtonBaseClass } from "../../../chunks/grButtonStyles-B_-YRE__.js";
|
|
6
6
|
import { computed, createBlock, createCommentVNode, createElementBlock, defineComponent, markRaw, normalizeClass, openBlock, ref, renderSlot, resolveDynamicComponent, toDisplayString, unref, withCtx } from "vue";
|
|
7
7
|
//#region src/components/GrButton/GrButton.vue?vue&type=script&setup=true&lang.ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrButton-Bw2AH4uX.js","names":[],"sources":["../../../../src/components/GrButton/GrButton.vue","../../../../src/components/GrButton/GrButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, markRaw, ref, type Component } from 'vue'\n\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrButtonGroup } from '../GrButtonGroup/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport type { GrButtonSize, GrButtonTone, GrButtonVariant } from './grButtonStyles'\n\nimport {\n grButtonBaseClass,\n grButtonClass,\n type GrButtonSize,\n type GrButtonTone,\n type GrButtonVariant,\n} from './grButtonStyles'\n\nexport interface GrButtonProps {\n variant?: GrButtonVariant\n tone?: GrButtonTone\n size?: GrButtonSize\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n disabled?: boolean\n square?: boolean\n /** Кнопка на всю ширину контейнера. */\n block?: boolean\n type?: 'button' | 'submit' | 'reset'\n ariaLabel?: string\n /** Полиморфизм: кастомный корневой тег/компонент (например, RouterLink). */\n as?: string | Component\n /** Рендерит кнопку как `<a href>` (если не задан `as`). */\n href?: string\n target?: string\n rel?: string\n external?: boolean\n}\n\nconst props = withDefaults(\n defineProps<GrButtonProps>(),\n {\n // `variant`/`tone`/`size`/`square` настраиваются через `GrConfigProvider`,\n // поэтому их дефолты живут в резолверах ниже, а не здесь: Vue подставил бы\n // дефолт до того, как компонент успеет заглянуть в конфиг.\n variant: undefined,\n tone: undefined,\n size: undefined,\n loading: false,\n loadingText: undefined,\n disabled: false,\n square: undefined,\n block: false,\n type: 'button',\n ariaLabel: undefined,\n as: undefined,\n href: undefined,\n target: undefined,\n rel: undefined,\n external: false,\n },\n)\n\n// Эффективные значения: проп кнопки → группа → `GrConfigProvider` → дефолт.\n// Группа ближе к кнопке, чем глобальный провайдер, поэтому она подставляется\n// как «локальное» значение — и побеждает конфиг, но не собственный проп.\nconst group = useGrButtonGroup()\n\nconst resolvedSize = useGrComponentSize(() => props.size ?? group?.size.value, { component: 'GrButton' })\nconst resolvedVariant = useGrComponentProp('GrButton', 'variant', () => props.variant ?? group?.variant.value, 'primary')\nconst resolvedTone = useGrComponentProp('GrButton', 'tone', () => props.tone ?? group?.tone.value, 'primary')\nconst isSquare = useGrComponentProp('GrButton', 'square', () => props.square, false)\n\nconst { t } = useGranularityTranslations()\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.button.loading', 'Loading…'))\n\n// Полиморфный корень: `as` → `<a href>` → `<button>`.\nconst isLink = computed(() => Boolean(props.as || props.href))\nconst renderAs = computed<string | Component>(() => {\n if (props.as) return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\n// Неинтерактивно при явном `disabled` ИЛИ во время `loading`.\nconst blocked = computed(() => props.disabled || props.loading)\n\n// Ключевое: `loading` НЕ ставит нативный `disabled` (элемент бы выпал из фокуса и\n// скринридер потерял бы контекст) — вместо этого `aria-disabled` + перехват клика.\n// Нативный `disabled` (только у `<button>`) оставляем лишь для явного `disabled`.\nconst nativeDisabled = computed(() => (renderAs.value === 'button' && props.disabled) ? true : undefined)\nconst ariaDisabled = computed(() => (props.loading || (isLink.value && props.disabled)) ? 'true' : undefined)\n\nconst resolvedTarget = computed(() => props.target ?? (props.external ? '_blank' : undefined))\nconst resolvedRel = computed(() => props.rel ?? (resolvedTarget.value === '_blank' ? 'noopener noreferrer' : undefined))\n\nfunction onClickCapture(e: MouseEvent): void {\n // Блокируем и дефолт (submit/навигация), и внешние обработчики (в т.ч. по Enter/Space),\n // сохраняя фокус на элементе.\n if (blocked.value) {\n e.preventDefault()\n e.stopImmediatePropagation()\n }\n}\n\n// Корень динамический (`as` принимает и тег, и компонент), поэтому ref может\n// оказаться как элементом, так и инстансом — например роутерной ссылкой.\nconst rootEl = ref<HTMLElement | { $el?: HTMLElement } | null>(null)\n\n/**\n * Фокус на кнопку из кода. Нужен там, где окно обязано открываться с фокусом\n * на конкретном действии (`GrConfirmDialog`), и потребителю не должно быть\n * важно, тегом или компонентом отрисован корень.\n */\nfunction focus(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.focus?.()\n}\n\nfunction blur(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.blur?.()\n}\n\ndefineExpose({ focus, blur })\n\nconst className = computed(() => {\n return grButtonClass({\n variant: resolvedVariant.value,\n tone: resolvedTone.value,\n size: resolvedSize.value,\n square: isSquare.value,\n disabled: props.disabled,\n block: props.block,\n })\n})\n\ndefineSlots<{\n /** Содержимое кнопки. */\n default?: () => any\n /** Аддон слева: иконка, счётчик. В состоянии загрузки уступает место спиннеру. */\n prefix?: () => any\n /** Аддон справа: шеврон, счётчик. */\n suffix?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"renderAs\"\n ref=\"rootEl\"\n data-gr-button\n :data-gr-variant=\"resolvedVariant\"\n :data-gr-tone=\"resolvedTone\"\n :type=\"renderAs === 'button' ? props.type : undefined\"\n :disabled=\"nativeDisabled\"\n :href=\"isLink && !props.disabled ? props.href : undefined\"\n :target=\"isLink && !props.disabled ? resolvedTarget : undefined\"\n :rel=\"isLink && !props.disabled ? resolvedRel : undefined\"\n :aria-busy=\"props.loading ? 'true' : undefined\"\n :aria-disabled=\"ariaDisabled\"\n :aria-label=\"props.ariaLabel\"\n :tabindex=\"isLink && props.disabled ? -1 : undefined\"\n :class=\"[grButtonBaseClass, className, blocked ? 'cursor-not-allowed' : '']\"\n @click.capture=\"onClickCapture\"\n >\n <!-- Спиннер занимает место префикса: две иконки рядом читались бы как ошибка. -->\n <IconLoader v-if=\"props.loading\" class=\"h-4 w-4 animate-spin\" aria-hidden=\"true\" />\n <slot v-else name=\"prefix\" />\n\n <slot />\n\n <slot name=\"suffix\" />\n\n <span v-if=\"props.loading\" class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, markRaw, ref, type Component } from 'vue'\n\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrButtonGroup } from '../GrButtonGroup/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport type { GrButtonSize, GrButtonTone, GrButtonVariant } from './grButtonStyles'\n\nimport {\n grButtonBaseClass,\n grButtonClass,\n type GrButtonSize,\n type GrButtonTone,\n type GrButtonVariant,\n} from './grButtonStyles'\n\nexport interface GrButtonProps {\n variant?: GrButtonVariant\n tone?: GrButtonTone\n size?: GrButtonSize\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n disabled?: boolean\n square?: boolean\n /** Кнопка на всю ширину контейнера. */\n block?: boolean\n type?: 'button' | 'submit' | 'reset'\n ariaLabel?: string\n /** Полиморфизм: кастомный корневой тег/компонент (например, RouterLink). */\n as?: string | Component\n /** Рендерит кнопку как `<a href>` (если не задан `as`). */\n href?: string\n target?: string\n rel?: string\n external?: boolean\n}\n\nconst props = withDefaults(\n defineProps<GrButtonProps>(),\n {\n // `variant`/`tone`/`size`/`square` настраиваются через `GrConfigProvider`,\n // поэтому их дефолты живут в резолверах ниже, а не здесь: Vue подставил бы\n // дефолт до того, как компонент успеет заглянуть в конфиг.\n variant: undefined,\n tone: undefined,\n size: undefined,\n loading: false,\n loadingText: undefined,\n disabled: false,\n square: undefined,\n block: false,\n type: 'button',\n ariaLabel: undefined,\n as: undefined,\n href: undefined,\n target: undefined,\n rel: undefined,\n external: false,\n },\n)\n\n// Эффективные значения: проп кнопки → группа → `GrConfigProvider` → дефолт.\n// Группа ближе к кнопке, чем глобальный провайдер, поэтому она подставляется\n// как «локальное» значение — и побеждает конфиг, но не собственный проп.\nconst group = useGrButtonGroup()\n\nconst resolvedSize = useGrComponentSize(() => props.size ?? group?.size.value, { component: 'GrButton' })\nconst resolvedVariant = useGrComponentProp('GrButton', 'variant', () => props.variant ?? group?.variant.value, 'primary')\nconst resolvedTone = useGrComponentProp('GrButton', 'tone', () => props.tone ?? group?.tone.value, 'primary')\nconst isSquare = useGrComponentProp('GrButton', 'square', () => props.square, false)\n\nconst { t } = useGranularityTranslations()\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.button.loading', 'Loading…'))\n\n// Полиморфный корень: `as` → `<a href>` → `<button>`.\nconst isLink = computed(() => Boolean(props.as || props.href))\nconst renderAs = computed<string | Component>(() => {\n if (props.as) return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\n// Неинтерактивно при явном `disabled` ИЛИ во время `loading`.\nconst blocked = computed(() => props.disabled || props.loading)\n\n// Ключевое: `loading` НЕ ставит нативный `disabled` (элемент бы выпал из фокуса и\n// скринридер потерял бы контекст) — вместо этого `aria-disabled` + перехват клика.\n// Нативный `disabled` (только у `<button>`) оставляем лишь для явного `disabled`.\nconst nativeDisabled = computed(() => (renderAs.value === 'button' && props.disabled) ? true : undefined)\nconst ariaDisabled = computed(() => (props.loading || (isLink.value && props.disabled)) ? 'true' : undefined)\n\nconst resolvedTarget = computed(() => props.target ?? (props.external ? '_blank' : undefined))\nconst resolvedRel = computed(() => props.rel ?? (resolvedTarget.value === '_blank' ? 'noopener noreferrer' : undefined))\n\nfunction onClickCapture(e: MouseEvent): void {\n // Блокируем и дефолт (submit/навигация), и внешние обработчики (в т.ч. по Enter/Space),\n // сохраняя фокус на элементе.\n if (blocked.value) {\n e.preventDefault()\n e.stopImmediatePropagation()\n }\n}\n\n// Корень динамический (`as` принимает и тег, и компонент), поэтому ref может\n// оказаться как элементом, так и инстансом — например роутерной ссылкой.\nconst rootEl = ref<HTMLElement | { $el?: HTMLElement } | null>(null)\n\n/**\n * Фокус на кнопку из кода. Нужен там, где окно обязано открываться с фокусом\n * на конкретном действии (`GrConfirmDialog`), и потребителю не должно быть\n * важно, тегом или компонентом отрисован корень.\n */\nfunction focus(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.focus?.()\n}\n\nfunction blur(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.blur?.()\n}\n\ndefineExpose({ focus, blur })\n\nconst className = computed(() => {\n return grButtonClass({\n variant: resolvedVariant.value,\n tone: resolvedTone.value,\n size: resolvedSize.value,\n square: isSquare.value,\n disabled: props.disabled,\n block: props.block,\n })\n})\n\ndefineSlots<{\n /** Содержимое кнопки. */\n default?: () => any\n /** Аддон слева: иконка, счётчик. В состоянии загрузки уступает место спиннеру. */\n prefix?: () => any\n /** Аддон справа: шеврон, счётчик. */\n suffix?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"renderAs\"\n ref=\"rootEl\"\n data-gr-button\n :data-gr-variant=\"resolvedVariant\"\n :data-gr-tone=\"resolvedTone\"\n :type=\"renderAs === 'button' ? props.type : undefined\"\n :disabled=\"nativeDisabled\"\n :href=\"isLink && !props.disabled ? props.href : undefined\"\n :target=\"isLink && !props.disabled ? resolvedTarget : undefined\"\n :rel=\"isLink && !props.disabled ? resolvedRel : undefined\"\n :aria-busy=\"props.loading ? 'true' : undefined\"\n :aria-disabled=\"ariaDisabled\"\n :aria-label=\"props.ariaLabel\"\n :tabindex=\"isLink && props.disabled ? -1 : undefined\"\n :class=\"[grButtonBaseClass, className, blocked ? 'cursor-not-allowed' : '']\"\n @click.capture=\"onClickCapture\"\n >\n <!-- Спиннер занимает место префикса: две иконки рядом читались бы как ошибка. -->\n <IconLoader v-if=\"props.loading\" class=\"h-4 w-4 animate-spin\" aria-hidden=\"true\" />\n <slot v-else name=\"prefix\" />\n\n <slot />\n\n <slot name=\"suffix\" />\n\n <span v-if=\"props.loading\" class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </component>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as GrButton_default } from "./chunks/GrButton-
|
|
2
|
-
import { t as grButtonSafelist } from "../../chunks/safelist-
|
|
3
|
-
import { t as grButtonConfig } from "../../chunks/config-
|
|
1
|
+
import { t as GrButton_default } from "./chunks/GrButton-Bw2AH4uX.js";
|
|
2
|
+
import { t as grButtonSafelist } from "../../chunks/safelist-BOq5Li7p.js";
|
|
3
|
+
import { t as grButtonConfig } from "../../chunks/config-BHcS5Cwm.js";
|
|
4
4
|
export { GrButton_default as GrButton, GrButton_default as default, grButtonConfig, grButtonSafelist };
|
package/dist/components/GrButtonGroup/chunks/{GrButtonGroup-BQo5VQ_c.js → GrButtonGroup-CKyiAV8K.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as provideGrButtonGroup } from "../../../chunks/context-
|
|
1
|
+
import { t as provideGrButtonGroup } from "../../../chunks/context-BfIQv7m1.js";
|
|
2
2
|
import { computed, createElementBlock, defineComponent, normalizeClass, openBlock, renderSlot } from "vue";
|
|
3
3
|
import '../styles.css';//#region src/components/GrButtonGroup/GrButtonGroup.vue?vue&type=script&setup=true&lang.ts
|
|
4
4
|
var _hoisted_1 = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrButtonGroup-CKyiAV8K.js","names":[],"sources":["../../../../src/components/GrButtonGroup/GrButtonGroup.vue","../../../../src/components/GrButtonGroup/GrButtonGroup.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton/grButtonStyles'\nimport { provideGrButtonGroup } from './context'\n\nexport type GrButtonGroupOrientation = 'horizontal' | 'vertical'\n\nexport interface GrButtonGroupProps {\n /** Доступное имя группы: без него кнопки читаются как несвязанные. */\n ariaLabel?: string\n orientation?: GrButtonGroupOrientation\n /**\n * Склеивать кнопки в один блок. `false` — обычный ряд с зазором: каждая\n * кнопка сохраняет свои радиусы и границы.\n */\n attached?: boolean\n /** Оформление, общее для кнопок группы. Проп самой кнопки сильнее. */\n size?: GrButtonSize\n variant?: GrButtonVariant\n tone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrButtonGroupProps>(), {\n ariaLabel: undefined,\n orientation: 'horizontal',\n attached: true,\n size: undefined,\n variant: undefined,\n tone: undefined,\n})\n\nprovideGrButtonGroup({\n size: computed(() => props.size),\n variant: computed(() => props.variant),\n tone: computed(() => props.tone),\n})\n\ndefineSlots<{\n /** Кнопки группы. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n data-gr-button-group\n class=\"inline-flex\"\n :class=\"[\n orientation === 'vertical' ? 'flex-col items-stretch' : 'items-stretch',\n attached ? '' : 'gap-2',\n ]\"\n :data-orientation=\"orientation\"\n :data-attached=\"attached ? '' : undefined\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n >\n <slot />\n </div>\n</template>\n\n<style>\n/*\n * Склейка держится на понятии «звено группы» — прямом потомке, который сам\n * кнопка или содержит кнопку. Обёртка (тултип, `<span v-if>`, роутерная\n * ссылка) поэтому не разрывает ряд, а не-кнопочный потомок (разделитель,\n * подпись) в склейку не попадает и скругление себе не забирает.\n *\n * Края считаются от соседства звеньев, а не от `:first-child`/`:last-child`:\n * ведущий край гасится у звена, перед которым уже было звено, ведомый — у\n * звена, за которым звено ещё будет.\n */\n[data-gr-button-group] {\n --gr-button-group-radius: var(--gr-button-radius, 0.375rem);\n}\n\n[data-gr-button-group][data-attached] [data-gr-button] {\n border-radius: var(--gr-button-group-radius);\n position: relative;\n}\n\n/* Кнопка под курсором или с фокусом — поверх соседей: иначе её граница и\n фокус-кольцо срезаются наложением. */\n[data-gr-button-group] [data-gr-button]:hover,\n[data-gr-button-group] [data-gr-button]:focus-visible {\n z-index: 1;\n}\n\n/* ————— Горизонтальная группа. */\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-inline-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-end-start-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-start-end-radius: 0;\n border-end-end-radius: 0;\n}\n\n/* ————— Вертикальная группа: та же логика, другая ось. */\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-block-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton/grButtonStyles'\nimport { provideGrButtonGroup } from './context'\n\nexport type GrButtonGroupOrientation = 'horizontal' | 'vertical'\n\nexport interface GrButtonGroupProps {\n /** Доступное имя группы: без него кнопки читаются как несвязанные. */\n ariaLabel?: string\n orientation?: GrButtonGroupOrientation\n /**\n * Склеивать кнопки в один блок. `false` — обычный ряд с зазором: каждая\n * кнопка сохраняет свои радиусы и границы.\n */\n attached?: boolean\n /** Оформление, общее для кнопок группы. Проп самой кнопки сильнее. */\n size?: GrButtonSize\n variant?: GrButtonVariant\n tone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrButtonGroupProps>(), {\n ariaLabel: undefined,\n orientation: 'horizontal',\n attached: true,\n size: undefined,\n variant: undefined,\n tone: undefined,\n})\n\nprovideGrButtonGroup({\n size: computed(() => props.size),\n variant: computed(() => props.variant),\n tone: computed(() => props.tone),\n})\n\ndefineSlots<{\n /** Кнопки группы. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n data-gr-button-group\n class=\"inline-flex\"\n :class=\"[\n orientation === 'vertical' ? 'flex-col items-stretch' : 'items-stretch',\n attached ? '' : 'gap-2',\n ]\"\n :data-orientation=\"orientation\"\n :data-attached=\"attached ? '' : undefined\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n >\n <slot />\n </div>\n</template>\n\n<style>\n/*\n * Склейка держится на понятии «звено группы» — прямом потомке, который сам\n * кнопка или содержит кнопку. Обёртка (тултип, `<span v-if>`, роутерная\n * ссылка) поэтому не разрывает ряд, а не-кнопочный потомок (разделитель,\n * подпись) в склейку не попадает и скругление себе не забирает.\n *\n * Края считаются от соседства звеньев, а не от `:first-child`/`:last-child`:\n * ведущий край гасится у звена, перед которым уже было звено, ведомый — у\n * звена, за которым звено ещё будет.\n */\n[data-gr-button-group] {\n --gr-button-group-radius: var(--gr-button-radius, 0.375rem);\n}\n\n[data-gr-button-group][data-attached] [data-gr-button] {\n border-radius: var(--gr-button-group-radius);\n position: relative;\n}\n\n/* Кнопка под курсором или с фокусом — поверх соседей: иначе её граница и\n фокус-кольцо срезаются наложением. */\n[data-gr-button-group] [data-gr-button]:hover,\n[data-gr-button-group] [data-gr-button]:focus-visible {\n z-index: 1;\n}\n\n/* ————— Горизонтальная группа. */\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-inline-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-end-start-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-start-end-radius: 0;\n border-end-end-radius: 0;\n}\n\n/* ————— Вертикальная группа: та же логика, другая ось. */\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-block-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAuBA,MAAM,QAAQ;EASd,qBAAqB;GACnB,MAAM,eAAe,MAAM,IAAI;GAC/B,SAAS,eAAe,MAAM,OAAO;GACrC,MAAM,eAAe,MAAM,IAAI;EACjC,CAAC;;uBAUC,mBAaM,OAAA;IAZJ,wBAAA;IACA,OAAK,eAAA,CAAC,eAAa,CACH,QAAA,gBAAW,aAAA,2BAAA,iBAAoE,QAAA,WAAQ,KAAA,OAAA,CAAA,CAAA;IAItG,oBAAkB,QAAA;IAClB,iBAAe,QAAA,WAAQ,KAAQ,KAAA;IAChC,MAAK;IACJ,cAAY,QAAA;OAEb,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,IAAA,UAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as useGrButtonGroup } from "../../chunks/context-
|
|
2
|
-
import { t as GrButtonGroup_default } from "./chunks/GrButtonGroup-
|
|
3
|
-
import { t as grButtonGroupConfig } from "../../chunks/config-
|
|
1
|
+
import { n as useGrButtonGroup } from "../../chunks/context-BfIQv7m1.js";
|
|
2
|
+
import { t as GrButtonGroup_default } from "./chunks/GrButtonGroup-CKyiAV8K.js";
|
|
3
|
+
import { t as grButtonGroupConfig } from "../../chunks/config-DBmdgoVf2.js";
|
|
4
4
|
export { GrButtonGroup_default as GrButtonGroup, GrButtonGroup_default as default, grButtonGroupConfig, useGrButtonGroup };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
|
|
2
|
-
import { a as grCardRootClass, c as sectionDividerBottomClass, i as cardTitleClass, l as sectionDividerTopClass, o as ownHeaderPaddingClass, r as cardDescriptionClass, s as paddingClass } from "../../../chunks/config-
|
|
2
|
+
import { a as grCardRootClass, c as sectionDividerBottomClass, i as cardTitleClass, l as sectionDividerTopClass, o as ownHeaderPaddingClass, r as cardDescriptionClass, s as paddingClass } from "../../../chunks/config-Dpk-eVkS.js";
|
|
3
3
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, markRaw, normalizeClass, openBlock, renderSlot, resolveDynamicComponent, toDisplayString, unref, useId, useSlots, withCtx } from "vue";
|
|
4
4
|
//#region src/components/GrCard/GrCard.vue?vue&type=script&setup=true&lang.ts
|
|
5
5
|
var _hoisted_1 = ["id"];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrCard-DR3ehBt8.js","names":["$slots"],"sources":["../../../../src/components/GrCard/GrCard.vue","../../../../src/components/GrCard/GrCard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button') return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button') return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as grCardSafelist, t as grCardConfig } from "../../chunks/config-
|
|
2
|
-
import { t as GrCard_default } from "./chunks/GrCard-
|
|
1
|
+
import { n as grCardSafelist, t as grCardConfig } from "../../chunks/config-Dpk-eVkS.js";
|
|
2
|
+
import { t as GrCard_default } from "./chunks/GrCard-DR3ehBt8.js";
|
|
3
3
|
export { GrCard_default as GrCard, GrCard_default as default, grCardConfig, grCardSafelist };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { t as GrCheckbox_default } from "./chunks/GrCheckbox-CEcHIsXM.js";
|
|
2
|
-
import { n as grCheckboxSafelist, t as grCheckboxConfig } from "../../chunks/config-
|
|
2
|
+
import { n as grCheckboxSafelist, t as grCheckboxConfig } from "../../chunks/config-DZCUPHPU.js";
|
|
3
3
|
export { GrCheckbox_default as GrCheckbox, GrCheckbox_default as default, grCheckboxConfig, grCheckboxSafelist };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { t as GrCheckboxGroup_default } from "./chunks/GrCheckboxGroup-BOwrVcFr.js";
|
|
2
|
-
import { t as grCheckboxGroupConfig } from "../../chunks/config-
|
|
2
|
+
import { t as grCheckboxGroupConfig } from "../../chunks/config-BuGlNPE9.js";
|
|
3
3
|
export { GrCheckboxGroup_default as GrCheckboxGroup, GrCheckboxGroup_default as default, grCheckboxGroupConfig };
|
|
@@ -2,11 +2,11 @@ import { t as x_default } from "../../../chunks/x-2KXnqxiD.js";
|
|
|
2
2
|
import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
|
|
3
3
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
4
4
|
import { t as GR_CHIP_GROUP_CONTEXT } from "../../../chunks/grChipGroupContext-DZXkACap.js";
|
|
5
|
-
import { a as
|
|
5
|
+
import { a as chipIconSizeClassBySize, f as grChipClass, i as chipIconClass, n as chipCloseClass, s as chipLabelClass, t as chipCloseButtonClass } from "../../../chunks/grChipStyles-3JZApw03.js";
|
|
6
6
|
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, normalizeClass, onBeforeUnmount, openBlock, ref, renderSlot, resolveDynamicComponent, toDisplayString, unref, withCtx, withModifiers } from "vue";
|
|
7
7
|
//#region src/components/GrChip/GrChip.vue?vue&type=script&setup=true&lang.ts
|
|
8
8
|
var _hoisted_1 = ["title"];
|
|
9
|
-
var _hoisted_2 = ["aria-label"];
|
|
9
|
+
var _hoisted_2 = ["aria-label", "tabindex"];
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/components/GrChip/GrChip.vue
|
|
12
12
|
var GrChip_default = /* @__PURE__ */ defineComponent({
|
|
@@ -45,7 +45,8 @@ var GrChip_default = /* @__PURE__ */ defineComponent({
|
|
|
45
45
|
default: false
|
|
46
46
|
},
|
|
47
47
|
ariaLabel: { default: void 0 },
|
|
48
|
-
removeLabel: { default: void 0 }
|
|
48
|
+
removeLabel: { default: void 0 },
|
|
49
|
+
removeTabindex: { default: void 0 }
|
|
49
50
|
},
|
|
50
51
|
emits: ["update:selected", "remove"],
|
|
51
52
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
@@ -150,9 +151,16 @@ var GrChip_default = /* @__PURE__ */ defineComponent({
|
|
|
150
151
|
disabled: () => isDisabled.value,
|
|
151
152
|
el: () => rootEl.value
|
|
152
153
|
}));
|
|
154
|
+
const removeEl = ref(null);
|
|
153
155
|
__expose({
|
|
154
156
|
focus: () => rootEl.value?.focus(),
|
|
155
|
-
blur: () => rootEl.value?.blur()
|
|
157
|
+
blur: () => rootEl.value?.blur(),
|
|
158
|
+
/**
|
|
159
|
+
* Кнопка снятия — цель roving-фокуса у родителя. Отдаётся элементом, а не
|
|
160
|
+
* методом `focusRemove`: кольцу нужен сам узел, оно само решает, когда и
|
|
161
|
+
* куда переносить фокус.
|
|
162
|
+
*/
|
|
163
|
+
removeEl
|
|
156
164
|
});
|
|
157
165
|
return (_ctx, _cache) => {
|
|
158
166
|
return openBlock(), createBlock(resolveDynamicComponent(isInteractive.value ? "button" : "span"), {
|
|
@@ -192,10 +200,13 @@ var GrChip_default = /* @__PURE__ */ defineComponent({
|
|
|
192
200
|
"aria-hidden": "true"
|
|
193
201
|
}, [createVNode(unref(x_default), { class: "h-full w-full" })], 10, _hoisted_1)) : isClosable.value ? (openBlock(), createElementBlock("button", {
|
|
194
202
|
key: 2,
|
|
203
|
+
ref_key: "removeEl",
|
|
204
|
+
ref: removeEl,
|
|
195
205
|
"data-gr-chip-close": "",
|
|
196
206
|
type: "button",
|
|
197
207
|
class: normalizeClass([unref(chipCloseButtonClass), iconSizeClass.value]),
|
|
198
208
|
"aria-label": removeTitle.value,
|
|
209
|
+
tabindex: __props.removeTabindex,
|
|
199
210
|
onMousedown: _cache[0] || (_cache[0] = withModifiers(() => {}, ["prevent", "stop"])),
|
|
200
211
|
onClick: _cache[1] || (_cache[1] = withModifiers(($event) => requestRemove(), ["stop"]))
|
|
201
212
|
}, [createVNode(unref(x_default), { class: "h-full w-full" })], 42, _hoisted_2)) : createCommentVNode("", true)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrChip-Df4orxRH.js","names":["$slots"],"sources":["../../../../src/components/GrChip/GrChip.vue","../../../../src/components/GrChip/GrChip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, ref } from 'vue'\n\nimport IconClose from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\n\nimport type { GrChipValue } from './grChipGroupContext'\nimport { GR_CHIP_GROUP_CONTEXT } from './grChipGroupContext'\nimport type { GrChipRadius, GrChipSize, GrChipTone } from './grChipStyles'\nimport {\n chipCloseButtonClass,\n chipCloseClass,\n chipIconClass,\n chipIconSizeClassBySize,\n chipLabelClass,\n grChipClass,\n} from './grChipStyles'\n\n/**\n * Интерактивный тег: снимаемый, выбираемый, с иконкой.\n *\n * От `GrBadge` отличается не видом, а природой: бейдж — метка, чип — виджет.\n * Поэтому цвета и радиусы взяты у бейджа как есть (в одном ряду они обязаны\n * совпадать), а роль, клавиатура и размеры — свои.\n */\nexport interface GrChipProps {\n /** Значение чипа в группе. Вне `GrChipGroup` не используется. */\n value?: GrChipValue\n /**\n * Подпись. Нужна отдельно от слота: из неё собирается имя кнопки снятия —\n * «Убрать» на двадцати кнопках подряд не даёт выбрать нужную.\n */\n label?: string\n tone?: GrChipTone\n dark?: boolean\n size?: GrChipSize\n radius?: GrChipRadius\n /** Чип становится переключателем: `aria-pressed`, `Enter`/`Space`. */\n selectable?: boolean\n /** Состояние переключателя вне группы. Внутри группы значение ведёт группа. */\n selected?: boolean\n /** Крестик. Внутри виджета он не кнопка — см. блок про роли ниже. */\n closable?: boolean\n disabled?: boolean\n /** Доступное имя, когда подпись не объясняет назначения. */\n ariaLabel?: string\n /** Имя кнопки снятия целиком. Перебивает собранное из `label`. */\n removeLabel?: string\n /**\n * `tabindex` кнопки снятия — для чипа внутри поля ввода.\n *\n * Там таб-стоп принадлежит `<input>`, а ряд чипов ходит стрелками: у\n * `GrInputTag` кольцо оставляет ровно один `0`, у `GrAutocomplete` их нет\n * вовсе. Проп нужен потому, что кольцом управляет родитель — он знает и\n * порядок чипов, и что стоит за краем ряда.\n */\n removeTabindex?: number\n}\n\nexport interface GrChipEmits {\n (e: 'update:selected', value: boolean): void\n (e: 'remove'): void\n}\n\nconst props = withDefaults(defineProps<GrChipProps>(), {\n value: undefined,\n label: undefined,\n // Дефолты живут в резолверах ниже: Vue подставил бы свой раньше, чем\n // компонент заглянет в `GrConfigProvider`.\n tone: undefined,\n dark: undefined,\n size: undefined,\n radius: undefined,\n selectable: false,\n selected: false,\n closable: false,\n disabled: false,\n ariaLabel: undefined,\n removeLabel: undefined,\n removeTabindex: undefined,\n})\n\nconst emit = defineEmits<GrChipEmits>()\n\ndefineSlots<{\n /** Подпись чипа. Внутри выбираемого чипа — только фразовое содержимое. */\n default?: () => unknown\n /** Иконка перед подписью. */\n icon?: () => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst group = inject(GR_CHIP_GROUP_CONTEXT, null)\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst inGroup = computed(() => group !== null && props.value !== undefined)\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled.value ?? false))\nconst isReadonly = computed(() => group?.readonly.value ?? false)\n\n/**\n * Чип — виджет ровно тогда, когда по нему кликают.\n *\n * От этого зависит вся разметка: у виджета роль, `tabindex` и клавиатура, а\n * крестик внутри него перестаёт быть кнопкой.\n */\nconst isInteractive = computed(() => inGroup.value || props.selectable)\n\nconst isSelected = computed(() => {\n if (inGroup.value && props.value !== undefined) return group!.isSelected(props.value)\n return props.selected\n})\n\nconst isClosable = computed(() => {\n if (isReadonly.value || isDisabled.value) return false\n return props.closable || (inGroup.value ? group!.closable.value : false)\n})\n\n// Приоритет: локальный проп → значение группы → `GrConfigProvider` → дефолт.\n// Группа специфичнее конфига, поэтому её значение подаётся как «локальное».\nconst resolvedSize = useGrComponentSize<GrChipSize>(\n () => props.size ?? (inGroup.value ? group!.size.value : undefined),\n { component: 'GrChip' },\n)\nconst resolvedTone = useGrComponentProp(\n 'GrChip',\n 'tone',\n () => props.tone ?? (inGroup.value ? group!.tone.value : undefined),\n 'neutral',\n)\nconst resolvedRadius = useGrComponentProp(\n 'GrChip',\n 'radius',\n () => props.radius ?? (inGroup.value ? group!.radius.value : undefined),\n 'round',\n)\nconst resolvedDark = useGrComponentProp(\n 'GrChip',\n 'dark',\n () => props.dark ?? (inGroup.value ? group!.dark.value : undefined),\n false,\n)\n\nconst rootClass = computed(() => grChipClass({\n tone: resolvedTone.value,\n dark: resolvedDark.value,\n size: resolvedSize.value,\n radius: resolvedRadius.value,\n interactive: isInteractive.value && !isReadonly.value,\n selected: isSelected.value,\n disabled: isDisabled.value,\n}))\n\nconst iconSizeClass = computed(() => chipIconSizeClassBySize[resolvedSize.value])\n\nconst removeTitle = computed(() => {\n if (props.removeLabel) return props.removeLabel\n if (props.label) return t('gr.chip.removeNamed', 'Remove {label}', { label: props.label })\n return t('gr.chip.remove', 'Remove')\n})\n\n/**\n * Роль чипа задаёт группа, а не потребитель.\n *\n * Одиночный переключатель — кнопка с `aria-pressed`; в группе роль зависит от\n * множественности выбора: `radio` в одиночной (образец — `GrSegmented`),\n * `option` во множественной, где контейнер объявлен `listbox` c\n * `aria-multiselectable`.\n */\nconst chipRole = computed(() => {\n if (!inGroup.value) return undefined\n return group!.selection.value === 'single' ? 'radio' : 'option'\n})\n\nconst tabindex = computed(() => {\n if (!isInteractive.value) return undefined\n if (isDisabled.value) return -1\n if (!inGroup.value || props.value === undefined) return 0\n return group!.rovingValue.value === props.value ? 0 : -1\n})\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value) return\n\n if (inGroup.value && props.value !== undefined) {\n group!.toggle(props.value)\n return\n }\n\n if (props.selectable) emit('update:selected', !props.selected)\n}\n\nfunction requestRemove(): void {\n if (!isClosable.value) return\n\n emit('remove')\n if (inGroup.value && props.value !== undefined) group!.requestRemove(props.value)\n}\n\n/**\n * Крестик внутри виджета — не кнопка, поэтому его клик приходит сюда же и\n * разбирается по цели. Тот же приём у `GrTabs`: внутрь роли-виджета вложенная\n * кнопка запрещена (axe: `nested-interactive`), а `<button>` внутри `<button>`\n * невалиден и по контент-модели HTML.\n */\nfunction onRootClick(event: MouseEvent): void {\n if (isDisabled.value) return\n\n if (event.target instanceof Element && event.target.closest('[data-gr-chip-close]')) {\n requestRemove()\n return\n }\n\n toggle()\n}\n\nfunction onRootKeydown(event: KeyboardEvent): void {\n if (isDisabled.value) return\n\n // Навигация принадлежит группе: состав знает только она.\n if (inGroup.value && group!.handleNavigationKeys(event)) return\n\n if (event.key === 'Delete' || event.key === 'Backspace') {\n if (!isClosable.value) return\n event.preventDefault()\n requestRemove()\n }\n}\n\nif (group) {\n const unregister = group.register({\n value: () => props.value as GrChipValue,\n disabled: () => isDisabled.value,\n el: () => rootEl.value,\n })\n onBeforeUnmount(unregister)\n}\n\nconst removeEl = ref<HTMLButtonElement | null>(null)\n\ndefineExpose({\n focus: () => rootEl.value?.focus(),\n blur: () => rootEl.value?.blur(),\n /**\n * Кнопка снятия — цель roving-фокуса у родителя. Отдаётся элементом, а не\n * методом `focusRemove`: кольцу нужен сам узел, оно само решает, когда и\n * куда переносить фокус.\n */\n removeEl,\n})\n</script>\n\n<template>\n <component\n :is=\"isInteractive ? 'button' : 'span'\"\n ref=\"rootEl\"\n data-gr-chip\n :type=\"isInteractive ? 'button' : undefined\"\n :class=\"rootClass\"\n :role=\"chipRole\"\n :data-value=\"value\"\n :aria-label=\"ariaLabel\"\n :aria-checked=\"chipRole === 'radio' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-selected=\"chipRole === 'option' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-pressed=\"isInteractive && !chipRole ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :disabled=\"isInteractive && isDisabled ? true : undefined\"\n :aria-keyshortcuts=\"isInteractive && isClosable ? 'Delete' : undefined\"\n :tabindex=\"tabindex\"\n @click=\"isInteractive ? onRootClick($event) : undefined\"\n @keydown=\"isInteractive ? onRootKeydown($event) : undefined\"\n >\n <span v-if=\"$slots.icon\" data-gr-chip-icon :class=\"[chipIconClass, iconSizeClass]\">\n <slot name=\"icon\" />\n </span>\n\n <span data-gr-chip-label :class=\"chipLabelClass\">\n <slot>{{ label }}</slot>\n </span>\n\n <!--\n Крестик существует в двух видах, и различитель — роль самого чипа.\n Виджет: `<span aria-hidden>` вне таб-порядка, снятие идёт `Delete`/`Backspace`.\n Не виджет: настоящая кнопка со своей остановкой `Tab` и своим именем.\n -->\n <span\n v-if=\"isClosable && isInteractive\"\n data-gr-chip-close\n :class=\"[chipCloseClass, iconSizeClass]\"\n :title=\"removeTitle\"\n aria-hidden=\"true\"\n >\n <IconClose class=\"h-full w-full\" />\n </span>\n\n <button\n v-else-if=\"isClosable\"\n ref=\"removeEl\"\n data-gr-chip-close\n type=\"button\"\n :class=\"[chipCloseButtonClass, iconSizeClass]\"\n :aria-label=\"removeTitle\"\n :tabindex=\"removeTabindex\"\n @mousedown.prevent.stop\n @click.stop=\"requestRemove()\"\n >\n <IconClose class=\"h-full w-full\" />\n </button>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, ref } from 'vue'\n\nimport IconClose from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\n\nimport type { GrChipValue } from './grChipGroupContext'\nimport { GR_CHIP_GROUP_CONTEXT } from './grChipGroupContext'\nimport type { GrChipRadius, GrChipSize, GrChipTone } from './grChipStyles'\nimport {\n chipCloseButtonClass,\n chipCloseClass,\n chipIconClass,\n chipIconSizeClassBySize,\n chipLabelClass,\n grChipClass,\n} from './grChipStyles'\n\n/**\n * Интерактивный тег: снимаемый, выбираемый, с иконкой.\n *\n * От `GrBadge` отличается не видом, а природой: бейдж — метка, чип — виджет.\n * Поэтому цвета и радиусы взяты у бейджа как есть (в одном ряду они обязаны\n * совпадать), а роль, клавиатура и размеры — свои.\n */\nexport interface GrChipProps {\n /** Значение чипа в группе. Вне `GrChipGroup` не используется. */\n value?: GrChipValue\n /**\n * Подпись. Нужна отдельно от слота: из неё собирается имя кнопки снятия —\n * «Убрать» на двадцати кнопках подряд не даёт выбрать нужную.\n */\n label?: string\n tone?: GrChipTone\n dark?: boolean\n size?: GrChipSize\n radius?: GrChipRadius\n /** Чип становится переключателем: `aria-pressed`, `Enter`/`Space`. */\n selectable?: boolean\n /** Состояние переключателя вне группы. Внутри группы значение ведёт группа. */\n selected?: boolean\n /** Крестик. Внутри виджета он не кнопка — см. блок про роли ниже. */\n closable?: boolean\n disabled?: boolean\n /** Доступное имя, когда подпись не объясняет назначения. */\n ariaLabel?: string\n /** Имя кнопки снятия целиком. Перебивает собранное из `label`. */\n removeLabel?: string\n /**\n * `tabindex` кнопки снятия — для чипа внутри поля ввода.\n *\n * Там таб-стоп принадлежит `<input>`, а ряд чипов ходит стрелками: у\n * `GrInputTag` кольцо оставляет ровно один `0`, у `GrAutocomplete` их нет\n * вовсе. Проп нужен потому, что кольцом управляет родитель — он знает и\n * порядок чипов, и что стоит за краем ряда.\n */\n removeTabindex?: number\n}\n\nexport interface GrChipEmits {\n (e: 'update:selected', value: boolean): void\n (e: 'remove'): void\n}\n\nconst props = withDefaults(defineProps<GrChipProps>(), {\n value: undefined,\n label: undefined,\n // Дефолты живут в резолверах ниже: Vue подставил бы свой раньше, чем\n // компонент заглянет в `GrConfigProvider`.\n tone: undefined,\n dark: undefined,\n size: undefined,\n radius: undefined,\n selectable: false,\n selected: false,\n closable: false,\n disabled: false,\n ariaLabel: undefined,\n removeLabel: undefined,\n removeTabindex: undefined,\n})\n\nconst emit = defineEmits<GrChipEmits>()\n\ndefineSlots<{\n /** Подпись чипа. Внутри выбираемого чипа — только фразовое содержимое. */\n default?: () => unknown\n /** Иконка перед подписью. */\n icon?: () => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst group = inject(GR_CHIP_GROUP_CONTEXT, null)\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst inGroup = computed(() => group !== null && props.value !== undefined)\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled.value ?? false))\nconst isReadonly = computed(() => group?.readonly.value ?? false)\n\n/**\n * Чип — виджет ровно тогда, когда по нему кликают.\n *\n * От этого зависит вся разметка: у виджета роль, `tabindex` и клавиатура, а\n * крестик внутри него перестаёт быть кнопкой.\n */\nconst isInteractive = computed(() => inGroup.value || props.selectable)\n\nconst isSelected = computed(() => {\n if (inGroup.value && props.value !== undefined) return group!.isSelected(props.value)\n return props.selected\n})\n\nconst isClosable = computed(() => {\n if (isReadonly.value || isDisabled.value) return false\n return props.closable || (inGroup.value ? group!.closable.value : false)\n})\n\n// Приоритет: локальный проп → значение группы → `GrConfigProvider` → дефолт.\n// Группа специфичнее конфига, поэтому её значение подаётся как «локальное».\nconst resolvedSize = useGrComponentSize<GrChipSize>(\n () => props.size ?? (inGroup.value ? group!.size.value : undefined),\n { component: 'GrChip' },\n)\nconst resolvedTone = useGrComponentProp(\n 'GrChip',\n 'tone',\n () => props.tone ?? (inGroup.value ? group!.tone.value : undefined),\n 'neutral',\n)\nconst resolvedRadius = useGrComponentProp(\n 'GrChip',\n 'radius',\n () => props.radius ?? (inGroup.value ? group!.radius.value : undefined),\n 'round',\n)\nconst resolvedDark = useGrComponentProp(\n 'GrChip',\n 'dark',\n () => props.dark ?? (inGroup.value ? group!.dark.value : undefined),\n false,\n)\n\nconst rootClass = computed(() => grChipClass({\n tone: resolvedTone.value,\n dark: resolvedDark.value,\n size: resolvedSize.value,\n radius: resolvedRadius.value,\n interactive: isInteractive.value && !isReadonly.value,\n selected: isSelected.value,\n disabled: isDisabled.value,\n}))\n\nconst iconSizeClass = computed(() => chipIconSizeClassBySize[resolvedSize.value])\n\nconst removeTitle = computed(() => {\n if (props.removeLabel) return props.removeLabel\n if (props.label) return t('gr.chip.removeNamed', 'Remove {label}', { label: props.label })\n return t('gr.chip.remove', 'Remove')\n})\n\n/**\n * Роль чипа задаёт группа, а не потребитель.\n *\n * Одиночный переключатель — кнопка с `aria-pressed`; в группе роль зависит от\n * множественности выбора: `radio` в одиночной (образец — `GrSegmented`),\n * `option` во множественной, где контейнер объявлен `listbox` c\n * `aria-multiselectable`.\n */\nconst chipRole = computed(() => {\n if (!inGroup.value) return undefined\n return group!.selection.value === 'single' ? 'radio' : 'option'\n})\n\nconst tabindex = computed(() => {\n if (!isInteractive.value) return undefined\n if (isDisabled.value) return -1\n if (!inGroup.value || props.value === undefined) return 0\n return group!.rovingValue.value === props.value ? 0 : -1\n})\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value) return\n\n if (inGroup.value && props.value !== undefined) {\n group!.toggle(props.value)\n return\n }\n\n if (props.selectable) emit('update:selected', !props.selected)\n}\n\nfunction requestRemove(): void {\n if (!isClosable.value) return\n\n emit('remove')\n if (inGroup.value && props.value !== undefined) group!.requestRemove(props.value)\n}\n\n/**\n * Крестик внутри виджета — не кнопка, поэтому его клик приходит сюда же и\n * разбирается по цели. Тот же приём у `GrTabs`: внутрь роли-виджета вложенная\n * кнопка запрещена (axe: `nested-interactive`), а `<button>` внутри `<button>`\n * невалиден и по контент-модели HTML.\n */\nfunction onRootClick(event: MouseEvent): void {\n if (isDisabled.value) return\n\n if (event.target instanceof Element && event.target.closest('[data-gr-chip-close]')) {\n requestRemove()\n return\n }\n\n toggle()\n}\n\nfunction onRootKeydown(event: KeyboardEvent): void {\n if (isDisabled.value) return\n\n // Навигация принадлежит группе: состав знает только она.\n if (inGroup.value && group!.handleNavigationKeys(event)) return\n\n if (event.key === 'Delete' || event.key === 'Backspace') {\n if (!isClosable.value) return\n event.preventDefault()\n requestRemove()\n }\n}\n\nif (group) {\n const unregister = group.register({\n value: () => props.value as GrChipValue,\n disabled: () => isDisabled.value,\n el: () => rootEl.value,\n })\n onBeforeUnmount(unregister)\n}\n\nconst removeEl = ref<HTMLButtonElement | null>(null)\n\ndefineExpose({\n focus: () => rootEl.value?.focus(),\n blur: () => rootEl.value?.blur(),\n /**\n * Кнопка снятия — цель roving-фокуса у родителя. Отдаётся элементом, а не\n * методом `focusRemove`: кольцу нужен сам узел, оно само решает, когда и\n * куда переносить фокус.\n */\n removeEl,\n})\n</script>\n\n<template>\n <component\n :is=\"isInteractive ? 'button' : 'span'\"\n ref=\"rootEl\"\n data-gr-chip\n :type=\"isInteractive ? 'button' : undefined\"\n :class=\"rootClass\"\n :role=\"chipRole\"\n :data-value=\"value\"\n :aria-label=\"ariaLabel\"\n :aria-checked=\"chipRole === 'radio' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-selected=\"chipRole === 'option' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-pressed=\"isInteractive && !chipRole ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :disabled=\"isInteractive && isDisabled ? true : undefined\"\n :aria-keyshortcuts=\"isInteractive && isClosable ? 'Delete' : undefined\"\n :tabindex=\"tabindex\"\n @click=\"isInteractive ? onRootClick($event) : undefined\"\n @keydown=\"isInteractive ? onRootKeydown($event) : undefined\"\n >\n <span v-if=\"$slots.icon\" data-gr-chip-icon :class=\"[chipIconClass, iconSizeClass]\">\n <slot name=\"icon\" />\n </span>\n\n <span data-gr-chip-label :class=\"chipLabelClass\">\n <slot>{{ label }}</slot>\n </span>\n\n <!--\n Крестик существует в двух видах, и различитель — роль самого чипа.\n Виджет: `<span aria-hidden>` вне таб-порядка, снятие идёт `Delete`/`Backspace`.\n Не виджет: настоящая кнопка со своей остановкой `Tab` и своим именем.\n -->\n <span\n v-if=\"isClosable && isInteractive\"\n data-gr-chip-close\n :class=\"[chipCloseClass, iconSizeClass]\"\n :title=\"removeTitle\"\n aria-hidden=\"true\"\n >\n <IconClose class=\"h-full w-full\" />\n </span>\n\n <button\n v-else-if=\"isClosable\"\n ref=\"removeEl\"\n data-gr-chip-close\n type=\"button\"\n :class=\"[chipCloseButtonClass, iconSizeClass]\"\n :aria-label=\"removeTitle\"\n :tabindex=\"removeTabindex\"\n @mousedown.prevent.stop\n @click.stop=\"requestRemove()\"\n >\n <IconClose class=\"h-full w-full\" />\n </button>\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkEA,MAAM,QAAQ;EAkBd,MAAM,OAAO;EASb,MAAM,EAAE,MAAM,2BAA2B;EAEzC,MAAM,QAAQ,OAAO,uBAAuB,IAAI;EAChD,MAAM,SAAS,IAAwB,IAAI;EAE3C,MAAM,UAAU,eAAe,UAAU,QAAQ,MAAM,UAAU,KAAA,CAAS;EAE1E,MAAM,aAAa,eAAe,MAAM,aAAa,OAAO,SAAS,SAAS,MAAM;EACpF,MAAM,aAAa,eAAe,OAAO,SAAS,SAAS,KAAK;;;;;;;EAQhE,MAAM,gBAAgB,eAAe,QAAQ,SAAS,MAAM,UAAU;EAEtE,MAAM,aAAa,eAAe;GAChC,IAAI,QAAQ,SAAS,MAAM,UAAU,KAAA,GAAW,OAAO,MAAO,WAAW,MAAM,KAAK;GACpF,OAAO,MAAM;EACf,CAAC;EAED,MAAM,aAAa,eAAe;GAChC,IAAI,WAAW,SAAS,WAAW,OAAO,OAAO;GACjD,OAAO,MAAM,aAAa,QAAQ,QAAQ,MAAO,SAAS,QAAQ;EACpE,CAAC;EAID,MAAM,eAAe,yBACb,MAAM,SAAS,QAAQ,QAAQ,MAAO,KAAK,QAAQ,KAAA,IACzD,EAAE,WAAW,SAAS,CACxB;EACA,MAAM,eAAe,mBACnB,UACA,cACM,MAAM,SAAS,QAAQ,QAAQ,MAAO,KAAK,QAAQ,KAAA,IACzD,SACF;EACA,MAAM,iBAAiB,mBACrB,UACA,gBACM,MAAM,WAAW,QAAQ,QAAQ,MAAO,OAAO,QAAQ,KAAA,IAC7D,OACF;EACA,MAAM,eAAe,mBACnB,UACA,cACM,MAAM,SAAS,QAAQ,QAAQ,MAAO,KAAK,QAAQ,KAAA,IACzD,KACF;EAEA,MAAM,YAAY,eAAe,YAAY;GAC3C,MAAM,aAAa;GACnB,MAAM,aAAa;GACnB,MAAM,aAAa;GACnB,QAAQ,eAAe;GACvB,aAAa,cAAc,SAAS,CAAC,WAAW;GAChD,UAAU,WAAW;GACrB,UAAU,WAAW;EACvB,CAAC,CAAC;EAEF,MAAM,gBAAgB,eAAe,wBAAwB,aAAa,MAAM;EAEhF,MAAM,cAAc,eAAe;GACjC,IAAI,MAAM,aAAa,OAAO,MAAM;GACpC,IAAI,MAAM,OAAO,OAAO,EAAE,uBAAuB,kBAAkB,EAAE,OAAO,MAAM,MAAM,CAAC;GACzF,OAAO,EAAE,kBAAkB,QAAQ;EACrC,CAAC;;;;;;;;;EAUD,MAAM,WAAW,eAAe;GAC9B,IAAI,CAAC,QAAQ,OAAO,OAAO,KAAA;GAC3B,OAAO,MAAO,UAAU,UAAU,WAAW,UAAU;EACzD,CAAC;EAED,MAAM,WAAW,eAAe;GAC9B,IAAI,CAAC,cAAc,OAAO,OAAO,KAAA;GACjC,IAAI,WAAW,OAAO,OAAO;GAC7B,IAAI,CAAC,QAAQ,SAAS,MAAM,UAAU,KAAA,GAAW,OAAO;GACxD,OAAO,MAAO,YAAY,UAAU,MAAM,QAAQ,IAAI;EACxD,CAAC;EAED,SAAS,SAAe;GACtB,IAAI,WAAW,SAAS,WAAW,OAAO;GAE1C,IAAI,QAAQ,SAAS,MAAM,UAAU,KAAA,GAAW;IAC9C,MAAO,OAAO,MAAM,KAAK;IACzB;GACF;GAEA,IAAI,MAAM,YAAY,KAAK,mBAAmB,CAAC,MAAM,QAAQ;EAC/D;EAEA,SAAS,gBAAsB;GAC7B,IAAI,CAAC,WAAW,OAAO;GAEvB,KAAK,QAAQ;GACb,IAAI,QAAQ,SAAS,MAAM,UAAU,KAAA,GAAW,MAAO,cAAc,MAAM,KAAK;EAClF;;;;;;;EAQA,SAAS,YAAY,OAAyB;GAC5C,IAAI,WAAW,OAAO;GAEtB,IAAI,MAAM,kBAAkB,WAAW,MAAM,OAAO,QAAQ,sBAAsB,GAAG;IACnF,cAAc;IACd;GACF;GAEA,OAAO;EACT;EAEA,SAAS,cAAc,OAA4B;GACjD,IAAI,WAAW,OAAO;GAGtB,IAAI,QAAQ,SAAS,MAAO,qBAAqB,KAAK,GAAG;GAEzD,IAAI,MAAM,QAAQ,YAAY,MAAM,QAAQ,aAAa;IACvD,IAAI,CAAC,WAAW,OAAO;IACvB,MAAM,eAAe;IACrB,cAAc;GAChB;EACF;EAEA,IAAI,OAMF,gBALmB,MAAM,SAAS;GAChC,aAAa,MAAM;GACnB,gBAAgB,WAAW;GAC3B,UAAU,OAAO;EACnB,CACgB,CAAU;EAG5B,MAAM,WAAW,IAA8B,IAAI;EAEnD,SAAa;GACX,aAAa,OAAO,OAAO,MAAM;GACjC,YAAY,OAAO,OAAO,KAAK;;;;;;GAM/B;EACF,CAAC;;uBAIC,YAuDY,wBAtDL,cAAA,QAAa,WAAA,MAAA,GAAA;aACd;IAAJ,KAAI;IACJ,gBAAA;IACC,MAAM,cAAA,QAAa,WAAc,KAAA;IACjC,OAAK,eAAE,UAAA,KAAS;IAChB,MAAM,SAAA;IACN,cAAY,QAAA;IACZ,cAAY,QAAA;IACZ,gBAAc,SAAA,UAAQ,UAAgB,WAAA,QAAU,SAAA,UAAuB,KAAA;IACvE,iBAAe,SAAA,UAAQ,WAAiB,WAAA,QAAU,SAAA,UAAuB,KAAA;IACzE,gBAAc,cAAA,SAAa,CAAK,SAAA,QAAY,WAAA,QAAU,SAAA,UAAuB,KAAA;IAC7E,iBAAe,WAAA,QAAU,SAAY,KAAA;IACrC,UAAU,cAAA,SAAiB,WAAA,QAAU,OAAU,KAAA;IAC/C,qBAAmB,cAAA,SAAiB,WAAA,QAAU,WAAc,KAAA;IAC5D,UAAU,SAAA;IACV,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,cAAA,QAAgB,YAAY,MAAM,IAAI,KAAA;IAC7C,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,cAAA,QAAgB,cAAc,MAAM,IAAI,KAAA;;2BAI3C;KAFKA,KAAAA,OAAO,QAAA,UAAA,GAAnB,mBAEO,QAAA;;MAFkB,qBAAA;MAAmB,OAAK,eAAA,CAAG,MAAA,aAAA,GAAe,cAAA,KAAa,CAAA;SAC9E,WAAoB,KAAA,QAAA,MAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;KAGtB,mBAEO,QAAA;MAFD,sBAAA;MAAoB,OAAK,eAAE,MAAA,cAAA,CAAc;SAC7C,WAAwB,KAAA,QAAA,WAAA,CAAA,SAAA,CAAA,gBAAA,gBAAf,QAAA,KAAK,GAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CAAA;KASR,WAAA,SAAc,cAAA,SAAA,UAAA,GADtB,mBAQO,QAAA;;MANL,sBAAA;MACC,OAAK,eAAA,CAAG,MAAA,cAAA,GAAgB,cAAA,KAAa,CAAA;MACrC,OAAO,YAAA;MACR,eAAY;SAEZ,YAAmC,MAAA,SAAA,GAAA,EAAxB,OAAM,gBAAe,CAAA,CAAA,GAAA,IAAA,UAAA,KAIrB,WAAA,SAAA,UAAA,GADb,mBAYS,UAAA;;eAVH;MAAJ,KAAI;MACJ,sBAAA;MACA,MAAK;MACJ,OAAK,eAAA,CAAG,MAAA,oBAAA,GAAsB,cAAA,KAAa,CAAA;MAC3C,cAAY,YAAA;MACZ,UAAU,QAAA;MACV,aAAS,OAAA,OAAA,OAAA,KAAA,oBAAV,CAAA,GAAuB,CAAA,WAAA,MAAA,CAAA;MACtB,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,cAAa,GAAA,CAAA,MAAA,CAAA;SAE1B,YAAmC,MAAA,SAAA,GAAA,EAAxB,OAAM,gBAAe,CAAA,CAAA,GAAA,IAAA,UAAA,KAAA,mBAAA,IAAA,IAAA"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { t as GrChip_default } from "./chunks/GrChip-Df4orxRH.js";
|
|
2
|
+
import { n as grChipSafelist, t as grChipConfig } from "../../chunks/config-Dv_r92GL.js";
|
|
3
3
|
export { GrChip_default as GrChip, GrChip_default as default, grChipConfig, grChipSafelist };
|
package/dist/components/GrChipGroup/chunks/{GrChipGroup-DefmSdY9.js → GrChipGroup-C78Vcwos.js}
RENAMED
|
@@ -2,9 +2,9 @@ import { a as useGrComponentSize } from "../../../chunks/context-CTbuwcYs.js";
|
|
|
2
2
|
import { n as useGrFormFieldContext } from "../../../chunks/context-DdNIxa1w.js";
|
|
3
3
|
import { useGrFormControl } from "../../../composables/useGrFormControl.js";
|
|
4
4
|
import { t as useFocusWithin } from "../../../chunks/useFocusWithin-BwHE0rzm.js";
|
|
5
|
-
import { t as GR_CHIP_GROUP_CONTEXT } from "../../../chunks/grChipGroupContext-DZXkACap.js";
|
|
6
5
|
import { useRovingFocus } from "../../../composables/useRovingFocus.js";
|
|
7
|
-
import {
|
|
6
|
+
import { t as GR_CHIP_GROUP_CONTEXT } from "../../../chunks/grChipGroupContext-DZXkACap.js";
|
|
7
|
+
import { r as chipGroupRootClass } from "../../../chunks/config-CZPDPJlg.js";
|
|
8
8
|
import { Fragment, computed, createElementBlock, defineComponent, nextTick, normalizeClass, openBlock, provide, ref, renderList, renderSlot, unref } from "vue";
|
|
9
9
|
//#region src/components/GrChipGroup/GrChipGroup.vue?vue&type=script&setup=true&lang.ts
|
|
10
10
|
var _hoisted_1 = [
|