@feugene/granularity 0.5.1 → 0.7.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/{adapter-K6zZTzBi.js.map → adapter-CRyH4YC8.js.map} +1 -1
- package/dist/chunks/{config-Cgk5ti-b.js.map → config-3SftO0uG.js.map} +1 -1
- package/dist/chunks/{config-BN-B2K4r.js.map → config-B44QVIge.js.map} +1 -1
- package/dist/chunks/{config-C-GVBa19.js.map → config-B8rC_K97.js.map} +1 -1
- package/dist/chunks/{config-DEv4m-ZP.js.map → config-BXffa3ta.js.map} +1 -1
- package/dist/chunks/{config-CUgvsjZx.js.map → config-BhvNm4Pp.js.map} +1 -1
- package/dist/chunks/{config-BNOf_qjD.js.map → config-C0b_3LJV.js.map} +1 -1
- package/dist/chunks/config-C0rHS1-l.js.map +1 -0
- package/dist/chunks/{config-fCcRwjIB.js.map → config-C4qAA0Sb.js.map} +1 -1
- package/dist/chunks/{config-XwI6t8cn.js.map → config-C5TN9J2Z.js.map} +1 -1
- package/dist/chunks/config-CVnluhKO.js.map +1 -0
- package/dist/chunks/{config-DUtUkSzc.js.map → config-CjEplP6D.js.map} +1 -1
- package/dist/chunks/{config-D19pyP4D.js.map → config-CtomKf-k.js.map} +1 -1
- package/dist/chunks/{config-BvuQUBtZ.js.map → config-CxCAfXZ1.js.map} +1 -1
- package/dist/chunks/{config-BDiLiqSk.js.map → config-D1DI3roo.js.map} +1 -1
- package/dist/chunks/{config-CgjOJ3aF.js.map → config-D27BL0H9.js.map} +1 -1
- package/dist/chunks/config-D32znLtV2.js.map +1 -0
- package/dist/chunks/{config-YSOeh6cy.js.map → config-D6Af6WZw.js.map} +1 -1
- package/dist/chunks/{config-BulF0Bf-.js.map → config-D98m8iyz.js.map} +1 -1
- package/dist/chunks/config-DDLoUczC.js.map +1 -0
- package/dist/chunks/{config-CFcv0hjb.js.map → config-DQOSlWvp.js.map} +1 -1
- package/dist/chunks/{config-ndXqsz5A.js.map → config-DbqFk-IW.js.map} +1 -1
- package/dist/chunks/{config-CdHY0Z7L.js.map → config-DnsISjD8.js.map} +1 -1
- package/dist/chunks/{config-BFZN9-vt.js.map → config-DudL02ag.js.map} +1 -1
- package/dist/chunks/{config-DgRJlF00.js.map → config-Dusr9jcE.js.map} +1 -1
- package/dist/chunks/{config-CWvHiaqr2.js.map → config-DxqMXzNV2.js.map} +1 -1
- package/dist/chunks/config-Mp9DJ9Mq2.js.map +1 -0
- package/dist/chunks/{config-R0jaXatX.js → config-XoANT5mU.js} +1 -1
- package/dist/chunks/{config-R0jaXatX.js.map → config-XoANT5mU.js.map} +1 -1
- package/dist/chunks/config-ZJVOVgqR.js +22 -0
- package/dist/chunks/config-ZJVOVgqR.js.map +1 -0
- package/dist/chunks/{config-CM7nbATU2.js.map → config-rxFL-6yF2.js.map} +1 -1
- package/dist/chunks/{config-bpQYM5O-.js.map → config-wo-ncgTH.js.map} +1 -1
- package/dist/chunks/{en-BeJa78lP.js → en-QNZhjmSJ.js} +18 -1
- package/dist/chunks/en-QNZhjmSJ.js.map +1 -0
- package/dist/chunks/{es-axYOwwWD.js → es-C1c5XsIK.js} +18 -1
- package/dist/chunks/es-C1c5XsIK.js.map +1 -0
- package/dist/chunks/{es-BPqm7rLm.js → es-CKLPuE0h.js} +3 -3
- package/dist/chunks/{es-BPqm7rLm.js.map → es-CKLPuE0h.js.map} +1 -1
- package/dist/chunks/{grSelectStyles-daEeDlBn.js.map → grSelectStyles-DTAYNzxn.js.map} +1 -1
- package/dist/chunks/grStyle-5EMYYctb.js +19 -0
- package/dist/chunks/grStyle-5EMYYctb.js.map +1 -0
- package/dist/chunks/granularityI18n-CXa_uN7f.js +46 -0
- package/dist/chunks/granularityI18n-CXa_uN7f.js.map +1 -0
- package/dist/chunks/{ru-Dqh-2C00.js → ru-DcF7ciz0.js} +18 -1
- package/dist/chunks/ru-DcF7ciz0.js.map +1 -0
- package/dist/chunks/{shared-CyCPkimZ.js → shared-BkIIEolF.js} +37 -30
- package/dist/chunks/shared-BkIIEolF.js.map +1 -0
- package/dist/components/GrFileUpload/chunks/{GrFileUpload-u01j9S0t.js → GrFileUpload-DYRERhI2.js} +258 -37
- package/dist/components/GrFileUpload/chunks/GrFileUpload-DYRERhI2.js.map +1 -0
- package/dist/components/GrFileUpload/index.js +3 -3
- package/dist/components/GrFormField/chunks/{GrFormField-C6PfAs4u.js.map → GrFormField-C1oWTT_0.js.map} +1 -1
- package/dist/components/GrFormField/index.js +2 -2
- package/dist/components/GrFormFile/chunks/{GrFormFile-DdM8Bc2B.js.map → GrFormFile-deDPicM2.js.map} +1 -1
- package/dist/components/GrFormFile/index.js +2 -2
- package/dist/components/GrFormSection/chunks/{GrFormSection-5djEaQZQ.js.map → GrFormSection-CWBk2EUm.js.map} +1 -1
- package/dist/components/GrFormSection/index.js +2 -2
- package/dist/components/GrImageViewer/chunks/{GrImageViewer-CjSnohW7.js.map → GrImageViewer-Cpj5zyZQ.js.map} +1 -1
- package/dist/components/GrImageViewer/index.js +2 -2
- package/dist/components/GrInput/chunks/{GrInput-ghxaTf6d.js.map → GrInput-CfO2RsM-.js.map} +1 -1
- package/dist/components/GrInput/index.js +2 -2
- package/dist/components/GrInputTag/chunks/{GrInputTag-B0x4U0Yk.js → GrInputTag-G_VYJPF9.js} +1 -1
- package/dist/components/GrInputTag/chunks/{GrInputTag-B0x4U0Yk.js.map → GrInputTag-G_VYJPF9.js.map} +1 -1
- package/dist/components/GrInputTag/index.js +2 -2
- package/dist/components/GrLink/chunks/{GrLink-DvvNkP0M.js → GrLink-BLPigqij.js} +1 -1
- package/dist/components/GrLink/chunks/{GrLink-DvvNkP0M.js.map → GrLink-BLPigqij.js.map} +1 -1
- package/dist/components/GrLink/index.js +2 -2
- package/dist/components/GrList/chunks/{GrList--Ib4zLNw.js.map → GrList-BPjQf-72.js.map} +1 -1
- package/dist/components/GrList/index.js +2 -2
- package/dist/components/GrLoading/index.js +1 -1
- package/dist/components/GrModal/index.js +1 -1
- package/dist/components/GrNavbar/chunks/{GrNavbar-nIyuiVj1.js → GrNavbar-BoVuSZ-V.js} +1 -1
- package/dist/components/GrNavbar/chunks/{GrNavbar-nIyuiVj1.js.map → GrNavbar-BoVuSZ-V.js.map} +1 -1
- package/dist/components/GrNavbar/index.js +2 -2
- package/dist/components/GrNumberInput/chunks/{GrNumberInput-B0mPLjdv.js → GrNumberInput-ECtFCIKV.js} +1 -1
- package/dist/components/GrNumberInput/chunks/{GrNumberInput-B0mPLjdv.js.map → GrNumberInput-ECtFCIKV.js.map} +1 -1
- package/dist/components/GrNumberInput/index.js +2 -2
- package/dist/components/GrPagination/chunks/{GrPagination-C_rxGwfY.js → GrPagination-DW44c2-a.js} +2 -2
- package/dist/components/GrPagination/chunks/{GrPagination-C_rxGwfY.js.map → GrPagination-DW44c2-a.js.map} +1 -1
- package/dist/components/GrPagination/index.js +2 -2
- package/dist/components/GrProgressBar/chunks/{GrProgressBar-MvMnzsJl.js → GrProgressBar-hQQK8cYh.js} +1 -1
- package/dist/components/GrProgressBar/chunks/{GrProgressBar-MvMnzsJl.js.map → GrProgressBar-hQQK8cYh.js.map} +1 -1
- package/dist/components/GrProgressBar/index.js +2 -2
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-DKhbN6ji.js → GrPromptDialog-CUMW6_58.js} +2 -2
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-DKhbN6ji.js.map → GrPromptDialog-CUMW6_58.js.map} +1 -1
- package/dist/components/GrPromptDialog/index.js +2 -2
- package/dist/components/GrRadio/chunks/{GrRadio-BxBs3WHq.js → GrRadio-B_t_ZNVl.js} +1 -1
- package/dist/components/GrRadio/chunks/{GrRadio-BxBs3WHq.js.map → GrRadio-B_t_ZNVl.js.map} +1 -1
- package/dist/components/GrRadio/index.js +2 -2
- package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CEAfJQ6A.js → GrRadioGroup-CVlgpUBr.js} +1 -1
- package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CEAfJQ6A.js.map → GrRadioGroup-CVlgpUBr.js.map} +1 -1
- package/dist/components/GrRadioGroup/index.js +2 -2
- package/dist/components/GrSegmented/chunks/{GrSegmented-Bwn2qOY4.js → GrSegmented-BPl1koHc.js} +1 -1
- package/dist/components/GrSegmented/chunks/{GrSegmented-Bwn2qOY4.js.map → GrSegmented-BPl1koHc.js.map} +1 -1
- package/dist/components/GrSegmented/index.js +2 -2
- package/dist/components/GrSelect/chunks/{GrSelect-BMMT5MrT.js → GrSelect-C3NAfTqL.js} +2 -2
- package/dist/components/GrSelect/chunks/{GrSelect-BMMT5MrT.js.map → GrSelect-C3NAfTqL.js.map} +1 -1
- package/dist/components/GrSelect/index.js +2 -2
- package/dist/components/GrSidebar/chunks/{GrSidebar-CSZ3RpFB.js.map → GrSidebar-DVucgcfV.js.map} +1 -1
- package/dist/components/GrSidebar/index.js +2 -2
- package/dist/components/GrSkeleton/chunks/{GrSkeleton-DKXkqWDa.js.map → GrSkeleton-CDTvCSoH.js.map} +1 -1
- package/dist/components/GrSkeleton/index.js +2 -2
- package/dist/components/GrSwitch/chunks/{GrSwitch-CdBxwV3k.js → GrSwitch-Bnamgqb2.js} +1 -1
- package/dist/components/GrSwitch/chunks/{GrSwitch-CdBxwV3k.js.map → GrSwitch-Bnamgqb2.js.map} +1 -1
- package/dist/components/GrSwitch/index.js +2 -2
- package/dist/components/GrTable/index.js +1 -1
- package/dist/components/GrTabs/chunks/{GrTabs-BpF8AAUz.js.map → GrTabs-CiGmcmvm.js.map} +1 -1
- package/dist/components/GrTabs/index.js +2 -2
- package/dist/components/GrTextarea/chunks/{GrTextarea-DFS9ZkrA.js → GrTextarea-VBSc6A7D.js} +1 -1
- package/dist/components/GrTextarea/chunks/{GrTextarea-DFS9ZkrA.js.map → GrTextarea-VBSc6A7D.js.map} +1 -1
- package/dist/components/GrTextarea/index.js +2 -2
- package/dist/components/GrToaster/chunks/{GrToaster-3Mf0Moxt.js → GrToaster-I1e-zCpf.js} +1 -1
- package/dist/components/GrToaster/chunks/{GrToaster-3Mf0Moxt.js.map → GrToaster-I1e-zCpf.js.map} +1 -1
- package/dist/components/GrToaster/index.js +2 -2
- package/dist/components/GrTooltip/chunks/{GrTooltip-BvmsukLW.js.map → GrTooltip-CrV1gI_c.js.map} +1 -1
- package/dist/components/GrTooltip/index.js +2 -2
- package/dist/components/GrTree/chunks/{GrTree-C2kN-O4Q.js.map → GrTree-Dlev9oBd.js.map} +1 -1
- package/dist/components/GrTree/index.js +2 -2
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-N-oPAOFj.js → GrTreeSelect-DkAIksRW.js} +4 -4
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-N-oPAOFj.js.map → GrTreeSelect-DkAIksRW.js.map} +1 -1
- package/dist/components/GrTreeSelect/index.js +2 -2
- package/dist/directives/loading.js +15 -0
- package/dist/directives/loading.js.map +1 -1
- package/dist/granular-provider-node.js +2 -2
- package/dist/granular-provider.js +1 -1
- package/dist/i18n/all.js +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/index.js +1032 -58
- package/dist/index.js.map +1 -1
- package/dist/types/src/components/GrFileUpload/GrFileUpload.vue.d.ts +58 -5
- package/dist/types/src/components/GrFileUpload/index.d.ts +4 -0
- package/dist/types/src/components/GrFileUpload/uploadState.d.ts +38 -0
- package/dist/types/src/components/GrFileUpload/uploadViaXhr.d.ts +33 -0
- package/dist/types/src/components/GrImageViewer/GrImageViewer.vue.d.ts +1 -1
- package/dist/types/src/components/GrInput/GrInput.vue.d.ts +1 -1
- package/dist/types/src/components/GrNumberInput/GrNumberInput.vue.d.ts +1 -1
- package/dist/types/src/components/GrResponseErrorBanner/GrFormErrorBanner.vue.d.ts +70 -0
- package/dist/types/src/components/GrResponseErrorBanner/GrResponseErrorBanner.vue.d.ts +96 -0
- package/dist/types/src/components/GrResponseErrorBanner/GrUploadErrorBanner.vue.d.ts +73 -0
- package/dist/types/src/components/GrResponseErrorBanner/config.d.ts +1 -0
- package/dist/types/src/components/GrResponseErrorBanner/index.d.ts +10 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/abortErrorParser.d.ts +15 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/createResponseErrorClassifier.d.ts +28 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/fileValidationParser.d.ts +12 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/httpStatusParser.d.ts +15 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/index.d.ts +11 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/jsonApiErrorParser.d.ts +17 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/laravelValidationParser.d.ts +15 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/networkErrorParser.d.ts +14 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/normalizeError.d.ts +19 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/plainMessageParser.d.ts +15 -0
- package/dist/types/src/components/GrResponseErrorBanner/parsers/problemDetailsParser.d.ts +17 -0
- package/dist/types/src/components/GrResponseErrorBanner/responseError.defaults.d.ts +18 -0
- package/dist/types/src/components/GrResponseErrorBanner/responseError.types.d.ts +115 -0
- package/dist/types/src/components/GrResponseErrorBanner/useResponseError.d.ts +62 -0
- package/dist/types/src/components/GrTextarea/GrTextarea.vue.d.ts +1 -1
- package/dist/types/src/components/GrToaster/GrToaster.vue.d.ts +1 -1
- package/dist/types/src/granular-provider/shared.d.ts +1 -0
- package/dist/types/src/i18n/messages/en.d.ts +32 -0
- package/dist/types/src/i18n/messages/es.d.ts +32 -0
- package/dist/types/src/i18n/messages/ru.d.ts +32 -0
- package/dist/types/src/index.d.ts +1 -0
- package/package.json +1 -1
- package/dist/chunks/config-BGmiXpR82.js.map +0 -1
- package/dist/chunks/config-CA9XwYnZ2.js.map +0 -1
- package/dist/chunks/config-CsMIhZfM.js.map +0 -1
- package/dist/chunks/config-CwLoozAz2.js.map +0 -1
- package/dist/chunks/config-DCQO6H6h.js.map +0 -1
- package/dist/chunks/config-Da90XGsi.js +0 -38
- package/dist/chunks/config-Da90XGsi.js.map +0 -1
- package/dist/chunks/en-BeJa78lP.js.map +0 -1
- package/dist/chunks/es-axYOwwWD.js.map +0 -1
- package/dist/chunks/granularityI18n-GCqUz_lo.js +0 -26
- package/dist/chunks/granularityI18n-GCqUz_lo.js.map +0 -1
- package/dist/chunks/ru-Dqh-2C00.js.map +0 -1
- package/dist/chunks/shared-CyCPkimZ.js.map +0 -1
- package/dist/components/GrFileUpload/chunks/GrFileUpload-u01j9S0t.js.map +0 -1
- /package/dist/chunks/{adapter-K6zZTzBi.js → adapter-CRyH4YC8.js} +0 -0
- /package/dist/chunks/{config-Cgk5ti-b.js → config-3SftO0uG.js} +0 -0
- /package/dist/chunks/{config-BN-B2K4r.js → config-B44QVIge.js} +0 -0
- /package/dist/chunks/{config-C-GVBa19.js → config-B8rC_K97.js} +0 -0
- /package/dist/chunks/{config-DEv4m-ZP.js → config-BXffa3ta.js} +0 -0
- /package/dist/chunks/{config-CUgvsjZx.js → config-BhvNm4Pp.js} +0 -0
- /package/dist/chunks/{config-BNOf_qjD.js → config-C0b_3LJV.js} +0 -0
- /package/dist/chunks/{config-CA9XwYnZ2.js → config-C0rHS1-l.js} +0 -0
- /package/dist/chunks/{config-fCcRwjIB.js → config-C4qAA0Sb.js} +0 -0
- /package/dist/chunks/{config-XwI6t8cn.js → config-C5TN9J2Z.js} +0 -0
- /package/dist/chunks/{config-BGmiXpR82.js → config-CVnluhKO.js} +0 -0
- /package/dist/chunks/{config-DUtUkSzc.js → config-CjEplP6D.js} +0 -0
- /package/dist/chunks/{config-D19pyP4D.js → config-CtomKf-k.js} +0 -0
- /package/dist/chunks/{config-BvuQUBtZ.js → config-CxCAfXZ1.js} +0 -0
- /package/dist/chunks/{config-BDiLiqSk.js → config-D1DI3roo.js} +0 -0
- /package/dist/chunks/{config-CgjOJ3aF.js → config-D27BL0H9.js} +0 -0
- /package/dist/chunks/{config-DCQO6H6h.js → config-D32znLtV2.js} +0 -0
- /package/dist/chunks/{config-YSOeh6cy.js → config-D6Af6WZw.js} +0 -0
- /package/dist/chunks/{config-BulF0Bf-.js → config-D98m8iyz.js} +0 -0
- /package/dist/chunks/{config-CwLoozAz2.js → config-DDLoUczC.js} +0 -0
- /package/dist/chunks/{config-CFcv0hjb.js → config-DQOSlWvp.js} +0 -0
- /package/dist/chunks/{config-ndXqsz5A.js → config-DbqFk-IW.js} +0 -0
- /package/dist/chunks/{config-CdHY0Z7L.js → config-DnsISjD8.js} +0 -0
- /package/dist/chunks/{config-BFZN9-vt.js → config-DudL02ag.js} +0 -0
- /package/dist/chunks/{config-DgRJlF00.js → config-Dusr9jcE.js} +0 -0
- /package/dist/chunks/{config-CWvHiaqr2.js → config-DxqMXzNV2.js} +0 -0
- /package/dist/chunks/{config-CsMIhZfM.js → config-Mp9DJ9Mq2.js} +0 -0
- /package/dist/chunks/{config-CM7nbATU2.js → config-rxFL-6yF2.js} +0 -0
- /package/dist/chunks/{config-bpQYM5O-.js → config-wo-ncgTH.js} +0 -0
- /package/dist/chunks/{grSelectStyles-daEeDlBn.js → grSelectStyles-DTAYNzxn.js} +0 -0
- /package/dist/components/GrFormField/chunks/{GrFormField-C6PfAs4u.js → GrFormField-C1oWTT_0.js} +0 -0
- /package/dist/components/GrFormFile/chunks/{GrFormFile-DdM8Bc2B.js → GrFormFile-deDPicM2.js} +0 -0
- /package/dist/components/GrFormSection/chunks/{GrFormSection-5djEaQZQ.js → GrFormSection-CWBk2EUm.js} +0 -0
- /package/dist/components/GrImageViewer/chunks/{GrImageViewer-CjSnohW7.js → GrImageViewer-Cpj5zyZQ.js} +0 -0
- /package/dist/components/GrInput/chunks/{GrInput-ghxaTf6d.js → GrInput-CfO2RsM-.js} +0 -0
- /package/dist/components/GrList/chunks/{GrList--Ib4zLNw.js → GrList-BPjQf-72.js} +0 -0
- /package/dist/components/GrSidebar/chunks/{GrSidebar-CSZ3RpFB.js → GrSidebar-DVucgcfV.js} +0 -0
- /package/dist/components/GrSkeleton/chunks/{GrSkeleton-DKXkqWDa.js → GrSkeleton-CDTvCSoH.js} +0 -0
- /package/dist/components/GrTabs/chunks/{GrTabs-BpF8AAUz.js → GrTabs-CiGmcmvm.js} +0 -0
- /package/dist/components/GrTooltip/chunks/{GrTooltip-BvmsukLW.js → GrTooltip-CrV1gI_c.js} +0 -0
- /package/dist/components/GrTree/chunks/{GrTree-C2kN-O4Q.js → GrTree-Dlev9oBd.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrProgressBar-
|
|
1
|
+
{"version":3,"file":"GrProgressBar-hQQK8cYh.js","names":[],"sources":["../../../../src/components/GrProgressBar/GrProgressBar.vue","../../../../src/components/GrProgressBar/GrProgressBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { grProgressBarFillClass, type GrProgressBarTone } from './grStyle'\n\n/**\n * GrProgressBar — линейный индикатор прогресса.\n *\n * @prop value — текущее значение `0..100`; выходящие за границы значения клампятся, `NaN` → `0`.\n * @prop ariaLabel — метка для скринридера (обязательна, если рядом нет видимого заголовка).\n * @prop tone — цветовая тональность заливки (CSS-переменная из `tokens.css`).\n */\nexport interface GrProgressBarProps {\n value: number\n ariaLabel?: string\n tone?: GrProgressBarTone\n}\n\nconst props = withDefaults(defineProps<GrProgressBarProps>(), {\n ariaLabel: undefined,\n tone: 'primary',\n})\n\nconst safe = computed(() => {\n if (Number.isNaN(props.value))\n return 0\n return Math.min(100, Math.max(0, props.value))\n})\n\nconst fillClassName = computed(() => grProgressBarFillClass(props.tone))\n</script>\n\n<template>\n <div\n data-ds-progress-bar\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"safe\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n class=\"h-2 w-full rounded-full bg-[var(--muted)] border border-[var(--brd)] overflow-hidden\"\n >\n <div\n data-ds-progress-bar-fill\n class=\"h-full\"\n :class=\"fillClassName\"\n :style=\"{ width: `${safe}%` }\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { grProgressBarFillClass, type GrProgressBarTone } from './grStyle'\n\n/**\n * GrProgressBar — линейный индикатор прогресса.\n *\n * @prop value — текущее значение `0..100`; выходящие за границы значения клампятся, `NaN` → `0`.\n * @prop ariaLabel — метка для скринридера (обязательна, если рядом нет видимого заголовка).\n * @prop tone — цветовая тональность заливки (CSS-переменная из `tokens.css`).\n */\nexport interface GrProgressBarProps {\n value: number\n ariaLabel?: string\n tone?: GrProgressBarTone\n}\n\nconst props = withDefaults(defineProps<GrProgressBarProps>(), {\n ariaLabel: undefined,\n tone: 'primary',\n})\n\nconst safe = computed(() => {\n if (Number.isNaN(props.value))\n return 0\n return Math.min(100, Math.max(0, props.value))\n})\n\nconst fillClassName = computed(() => grProgressBarFillClass(props.tone))\n</script>\n\n<template>\n <div\n data-ds-progress-bar\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"safe\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n class=\"h-2 w-full rounded-full bg-[var(--muted)] border border-[var(--brd)] overflow-hidden\"\n >\n <div\n data-ds-progress-bar-fill\n class=\"h-full\"\n :class=\"fillClassName\"\n :style=\"{ width: `${safe}%` }\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAkBA,MAAM,QAAQ;EAKd,MAAM,OAAO,eAAe;AAC1B,OAAI,OAAO,MAAM,MAAM,MAAM,CAC3B,QAAO;AACT,UAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,MAAM,MAAM,CAAA;IAC9C;EAED,MAAM,gBAAgB,eAAe,uBAAuB,MAAM,KAAK,CAAA;;uBAIrE,mBAeM,OAAA;IAdJ,wBAAA;IACA,MAAK;IACJ,cAAY,QAAA;IACZ,iBAAe,KAAA;IAChB,iBAAc;IACd,iBAAc;IACd,OAAM;OAEN,mBAKE,OAAA;IAJA,6BAAA;IACA,OAAK,eAAA,CAAC,UACE,cAAA,MAAa,CAAA;IACpB,OAAK,eAAA,EAAA,OAAA,GAAc,KAAA,MAAI,IAAA,CAAA"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { t as GrProgressBar_default } from "./chunks/GrProgressBar-hQQK8cYh.js";
|
|
2
|
+
import { n as grProgressBarSafelist, t as grProgressBarConfig } from "../../chunks/config-ZJVOVgqR.js";
|
|
3
3
|
export { GrProgressBar_default as GrProgressBar, GrProgressBar_default as default, grProgressBarConfig, grProgressBarSafelist };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as GrButton_default } from "../../GrButton/chunks/GrButton-BmGdp8-4.js";
|
|
2
2
|
import { t as GrDialog_default } from "../../GrDialog/chunks/GrDialog-gObmaVEl.js";
|
|
3
|
-
import { t as GrFormField_default } from "../../GrFormField/chunks/GrFormField-
|
|
4
|
-
import { t as GrInput_default } from "../../GrInput/chunks/GrInput-
|
|
3
|
+
import { t as GrFormField_default } from "../../GrFormField/chunks/GrFormField-C1oWTT_0.js";
|
|
4
|
+
import { t as GrInput_default } from "../../GrInput/chunks/GrInput-CfO2RsM-.js";
|
|
5
5
|
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, ref, renderSlot, toDisplayString, watch, withCtx } from "vue";
|
|
6
6
|
//#region src/components/GrPromptDialog/GrPromptDialog.vue?vue&type=script&setup=true&lang.ts
|
|
7
7
|
var _hoisted_1 = { class: "grid gap-4" };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrPromptDialog-DKhbN6ji.js","names":[],"sources":["../../../../src/components/GrPromptDialog/GrPromptDialog.vue","../../../../src/components/GrPromptDialog/GrPromptDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrPromptDialog — DS-примитив диалога ввода значения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Поведение `required=true` (по умолчанию): пустое значение подсвечивается\n * ошибкой только после первого «касания» (blur или попытка confirm),\n * чтобы не шуметь при открытии.\n */\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrFormField from '../GrFormField/GrFormField.vue'\nimport GrInput from '../GrInput/GrInput.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrPromptDialogProps {\n modelValue: boolean\n value: string\n title?: string\n description?: string\n label?: string\n placeholder?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n /** Текст ошибки для пустого значения при `required=true` (i18n). */\n requiredErrorText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n required?: boolean\n}\n\nconst props = withDefaults(defineProps<GrPromptDialogProps>(), {\n title: 'Prompt',\n description: undefined,\n label: 'Value',\n placeholder: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n requiredErrorText: 'Enter a value.',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n required: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'update:value', value: string): void\n (e: 'confirm', value: string): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst valueModel = computed({\n get: () => props.value,\n set: (v: string) => emit('update:value', v),\n})\n\nconst touched = ref(false)\nconst inputRef = ref<InstanceType<typeof GrInput> | null>(null)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (v) touched.value = false\n },\n)\n\nconst canConfirm = computed(() => {\n if (!props.required) return true\n return valueModel.value.trim().length > 0\n})\n\nconst error = computed(() => {\n if (!props.required) return undefined\n if (!touched.value) return undefined\n return valueModel.value.trim().length > 0\n ? undefined\n : props.requiredErrorText\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n if (!canConfirm.value) {\n touched.value = true\n inputRef.value?.focus()\n return\n }\n\n emit('confirm', valueModel.value)\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <GrFormField :label=\"label\" :error=\"error\" for-id=\"ds-prompt-input\">\n <GrInput\n id=\"ds-prompt-input\"\n ref=\"inputRef\"\n v-model=\"valueModel\"\n data-testid=\"ds-prompt-input\"\n :placeholder=\"placeholder\"\n :invalid=\"!!error\"\n @blur=\"touched = true\"\n />\n </GrFormField>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-prompt-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-prompt-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :disabled=\"required && touched && !canConfirm\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrPromptDialog — DS-примитив диалога ввода значения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Поведение `required=true` (по умолчанию): пустое значение подсвечивается\n * ошибкой только после первого «касания» (blur или попытка confirm),\n * чтобы не шуметь при открытии.\n */\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrFormField from '../GrFormField/GrFormField.vue'\nimport GrInput from '../GrInput/GrInput.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrPromptDialogProps {\n modelValue: boolean\n value: string\n title?: string\n description?: string\n label?: string\n placeholder?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n /** Текст ошибки для пустого значения при `required=true` (i18n). */\n requiredErrorText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n required?: boolean\n}\n\nconst props = withDefaults(defineProps<GrPromptDialogProps>(), {\n title: 'Prompt',\n description: undefined,\n label: 'Value',\n placeholder: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n requiredErrorText: 'Enter a value.',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n required: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'update:value', value: string): void\n (e: 'confirm', value: string): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst valueModel = computed({\n get: () => props.value,\n set: (v: string) => emit('update:value', v),\n})\n\nconst touched = ref(false)\nconst inputRef = ref<InstanceType<typeof GrInput> | null>(null)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (v) touched.value = false\n },\n)\n\nconst canConfirm = computed(() => {\n if (!props.required) return true\n return valueModel.value.trim().length > 0\n})\n\nconst error = computed(() => {\n if (!props.required) return undefined\n if (!touched.value) return undefined\n return valueModel.value.trim().length > 0\n ? undefined\n : props.requiredErrorText\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n if (!canConfirm.value) {\n touched.value = true\n inputRef.value?.focus()\n return\n }\n\n emit('confirm', valueModel.value)\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <GrFormField :label=\"label\" :error=\"error\" for-id=\"ds-prompt-input\">\n <GrInput\n id=\"ds-prompt-input\"\n ref=\"inputRef\"\n v-model=\"valueModel\"\n data-testid=\"ds-prompt-input\"\n :placeholder=\"placeholder\"\n :invalid=\"!!error\"\n @blur=\"touched = true\"\n />\n </GrFormField>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-prompt-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-prompt-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :disabled=\"required && touched && !canConfirm\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDA,MAAM,QAAQ;EAuBd,MAAM,OAAO;EAOb,MAAM,OAAO,SAAS;GACpB,WAAW,MAAM;GACjB,MAAM,MAAe,KAAK,qBAAqB,EAAE;GAClD,CAAA;EAED,MAAM,aAAa,SAAS;GAC1B,WAAW,MAAM;GACjB,MAAM,MAAc,KAAK,gBAAgB,EAAE;GAC5C,CAAA;EAED,MAAM,UAAU,IAAI,MAAK;EACzB,MAAM,WAAW,IAAyC,KAAI;AAE9D,cACQ,MAAM,aACX,MAAM;AACL,OAAI,EAAG,SAAQ,QAAQ;IAE3B;EAEA,MAAM,aAAa,eAAe;AAChC,OAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,UAAO,WAAW,MAAM,MAAM,CAAC,SAAS;IACzC;EAED,MAAM,QAAQ,eAAe;AAC3B,OAAI,CAAC,MAAM,SAAU,QAAO,KAAA;AAC5B,OAAI,CAAC,QAAQ,MAAO,QAAO,KAAA;AAC3B,UAAO,WAAW,MAAM,MAAM,CAAC,SAAS,IACpC,KAAA,IACA,MAAM;IACX;EAED,SAAS,WAAiB;AACxB,QAAK,SAAQ;AACb,QAAK,qBAAqB,MAAK;;EAGjC,SAAS,YAAkB;AACzB,OAAI,CAAC,WAAW,OAAO;AACrB,YAAQ,QAAQ;AAChB,aAAS,OAAO,OAAM;AACtB;;AAGF,QAAK,WAAW,WAAW,MAAK;AAChC,QAAK,qBAAqB,MAAK;;;uBAK/B,YAoDW,kBAAA;gBAnDA,KAAA;sEAAI,QAAA;IACZ,OAAO,QAAA;IACP,MAAM,QAAA;IACN,qBAAmB,QAAA;IACnB,gBAAc,QAAA;IACd,eAAa,QAAA;IACb,qBAAmB,QAAA;IACnB,iBAAe,QAAA;IACf,iBAAe,QAAA;IACf,eAAa,QAAA;IACb,eAAa,QAAA;;IAsBH,QAAM,cAiBR,CAhBP,WAgBO,KAAA,QAAA,UAAA,EAAA,QAAA,CAfL,mBAcM,OAdN,YAcM,CAbJ,YAEW,kBAAA;KAFD,eAAY;KAAmB,SAAQ;KAAW,MAAM,QAAA;KAAa,SAAO;;4BACpE,CAAA,gBAAA,gBAAb,QAAA,WAAU,EAAA,EAAA,CAAA,CAAA;;qBAEf,YASW,kBAAA;KART,eAAY;KACX,SAAS,QAAA;KACT,MAAM,QAAA;KACN,MAAM,QAAA;KACN,UAAU,QAAA,YAAY,QAAA,SAAO,CAAK,WAAA;KAClC,SAAO;;4BAES,CAAA,gBAAA,gBAAd,QAAA,YAAW,EAAA,EAAA,CAAA,CAAA;;;;;;;;2BAhBhB,CAlBN,mBAkBM,OAlBN,YAkBM,CAjBJ,WAIO,KAAA,QAAA,WAAA,EAAA,QAAA,CAHM,QAAA,eAAA,WAAA,EAAX,mBAEM,OAFN,YAEM,gBADD,QAAA,YAAW,EAAA,EAAA,IAAA,mBAAA,IAAA,KAAA,CAAA,CAAA,EAIlB,YAUc,qBAAA;KAVA,OAAO,QAAA;KAAQ,OAAO,MAAA;KAAO,UAAO;;4BAS9C,CARF,YAQE,iBAAA;MAPA,IAAG;eACC;MAAJ,KAAI;kBACK,WAAA;8EAAU,QAAA;MACnB,eAAY;MACX,aAAa,QAAA;MACb,SAAO,CAAA,CAAI,MAAA;MACX,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO"}
|
|
1
|
+
{"version":3,"file":"GrPromptDialog-CUMW6_58.js","names":[],"sources":["../../../../src/components/GrPromptDialog/GrPromptDialog.vue","../../../../src/components/GrPromptDialog/GrPromptDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrPromptDialog — DS-примитив диалога ввода значения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Поведение `required=true` (по умолчанию): пустое значение подсвечивается\n * ошибкой только после первого «касания» (blur или попытка confirm),\n * чтобы не шуметь при открытии.\n */\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrFormField from '../GrFormField/GrFormField.vue'\nimport GrInput from '../GrInput/GrInput.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrPromptDialogProps {\n modelValue: boolean\n value: string\n title?: string\n description?: string\n label?: string\n placeholder?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n /** Текст ошибки для пустого значения при `required=true` (i18n). */\n requiredErrorText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n required?: boolean\n}\n\nconst props = withDefaults(defineProps<GrPromptDialogProps>(), {\n title: 'Prompt',\n description: undefined,\n label: 'Value',\n placeholder: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n requiredErrorText: 'Enter a value.',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n required: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'update:value', value: string): void\n (e: 'confirm', value: string): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst valueModel = computed({\n get: () => props.value,\n set: (v: string) => emit('update:value', v),\n})\n\nconst touched = ref(false)\nconst inputRef = ref<InstanceType<typeof GrInput> | null>(null)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (v) touched.value = false\n },\n)\n\nconst canConfirm = computed(() => {\n if (!props.required) return true\n return valueModel.value.trim().length > 0\n})\n\nconst error = computed(() => {\n if (!props.required) return undefined\n if (!touched.value) return undefined\n return valueModel.value.trim().length > 0\n ? undefined\n : props.requiredErrorText\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n if (!canConfirm.value) {\n touched.value = true\n inputRef.value?.focus()\n return\n }\n\n emit('confirm', valueModel.value)\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <GrFormField :label=\"label\" :error=\"error\" for-id=\"ds-prompt-input\">\n <GrInput\n id=\"ds-prompt-input\"\n ref=\"inputRef\"\n v-model=\"valueModel\"\n data-testid=\"ds-prompt-input\"\n :placeholder=\"placeholder\"\n :invalid=\"!!error\"\n @blur=\"touched = true\"\n />\n </GrFormField>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-prompt-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-prompt-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :disabled=\"required && touched && !canConfirm\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrPromptDialog — DS-примитив диалога ввода значения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Поведение `required=true` (по умолчанию): пустое значение подсвечивается\n * ошибкой только после первого «касания» (blur или попытка confirm),\n * чтобы не шуметь при открытии.\n */\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrFormField from '../GrFormField/GrFormField.vue'\nimport GrInput from '../GrInput/GrInput.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrPromptDialogProps {\n modelValue: boolean\n value: string\n title?: string\n description?: string\n label?: string\n placeholder?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n /** Текст ошибки для пустого значения при `required=true` (i18n). */\n requiredErrorText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n required?: boolean\n}\n\nconst props = withDefaults(defineProps<GrPromptDialogProps>(), {\n title: 'Prompt',\n description: undefined,\n label: 'Value',\n placeholder: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n requiredErrorText: 'Enter a value.',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n required: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'update:value', value: string): void\n (e: 'confirm', value: string): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst valueModel = computed({\n get: () => props.value,\n set: (v: string) => emit('update:value', v),\n})\n\nconst touched = ref(false)\nconst inputRef = ref<InstanceType<typeof GrInput> | null>(null)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (v) touched.value = false\n },\n)\n\nconst canConfirm = computed(() => {\n if (!props.required) return true\n return valueModel.value.trim().length > 0\n})\n\nconst error = computed(() => {\n if (!props.required) return undefined\n if (!touched.value) return undefined\n return valueModel.value.trim().length > 0\n ? undefined\n : props.requiredErrorText\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n if (!canConfirm.value) {\n touched.value = true\n inputRef.value?.focus()\n return\n }\n\n emit('confirm', valueModel.value)\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <GrFormField :label=\"label\" :error=\"error\" for-id=\"ds-prompt-input\">\n <GrInput\n id=\"ds-prompt-input\"\n ref=\"inputRef\"\n v-model=\"valueModel\"\n data-testid=\"ds-prompt-input\"\n :placeholder=\"placeholder\"\n :invalid=\"!!error\"\n @blur=\"touched = true\"\n />\n </GrFormField>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-prompt-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-prompt-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :disabled=\"required && touched && !canConfirm\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDA,MAAM,QAAQ;EAuBd,MAAM,OAAO;EAOb,MAAM,OAAO,SAAS;GACpB,WAAW,MAAM;GACjB,MAAM,MAAe,KAAK,qBAAqB,EAAE;GAClD,CAAA;EAED,MAAM,aAAa,SAAS;GAC1B,WAAW,MAAM;GACjB,MAAM,MAAc,KAAK,gBAAgB,EAAE;GAC5C,CAAA;EAED,MAAM,UAAU,IAAI,MAAK;EACzB,MAAM,WAAW,IAAyC,KAAI;AAE9D,cACQ,MAAM,aACX,MAAM;AACL,OAAI,EAAG,SAAQ,QAAQ;IAE3B;EAEA,MAAM,aAAa,eAAe;AAChC,OAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,UAAO,WAAW,MAAM,MAAM,CAAC,SAAS;IACzC;EAED,MAAM,QAAQ,eAAe;AAC3B,OAAI,CAAC,MAAM,SAAU,QAAO,KAAA;AAC5B,OAAI,CAAC,QAAQ,MAAO,QAAO,KAAA;AAC3B,UAAO,WAAW,MAAM,MAAM,CAAC,SAAS,IACpC,KAAA,IACA,MAAM;IACX;EAED,SAAS,WAAiB;AACxB,QAAK,SAAQ;AACb,QAAK,qBAAqB,MAAK;;EAGjC,SAAS,YAAkB;AACzB,OAAI,CAAC,WAAW,OAAO;AACrB,YAAQ,QAAQ;AAChB,aAAS,OAAO,OAAM;AACtB;;AAGF,QAAK,WAAW,WAAW,MAAK;AAChC,QAAK,qBAAqB,MAAK;;;uBAK/B,YAoDW,kBAAA;gBAnDA,KAAA;sEAAI,QAAA;IACZ,OAAO,QAAA;IACP,MAAM,QAAA;IACN,qBAAmB,QAAA;IACnB,gBAAc,QAAA;IACd,eAAa,QAAA;IACb,qBAAmB,QAAA;IACnB,iBAAe,QAAA;IACf,iBAAe,QAAA;IACf,eAAa,QAAA;IACb,eAAa,QAAA;;IAsBH,QAAM,cAiBR,CAhBP,WAgBO,KAAA,QAAA,UAAA,EAAA,QAAA,CAfL,mBAcM,OAdN,YAcM,CAbJ,YAEW,kBAAA;KAFD,eAAY;KAAmB,SAAQ;KAAW,MAAM,QAAA;KAAa,SAAO;;4BACpE,CAAA,gBAAA,gBAAb,QAAA,WAAU,EAAA,EAAA,CAAA,CAAA;;qBAEf,YASW,kBAAA;KART,eAAY;KACX,SAAS,QAAA;KACT,MAAM,QAAA;KACN,MAAM,QAAA;KACN,UAAU,QAAA,YAAY,QAAA,SAAO,CAAK,WAAA;KAClC,SAAO;;4BAES,CAAA,gBAAA,gBAAd,QAAA,YAAW,EAAA,EAAA,CAAA,CAAA;;;;;;;;2BAhBhB,CAlBN,mBAkBM,OAlBN,YAkBM,CAjBJ,WAIO,KAAA,QAAA,WAAA,EAAA,QAAA,CAHM,QAAA,eAAA,WAAA,EAAX,mBAEM,OAFN,YAEM,gBADD,QAAA,YAAW,EAAA,EAAA,IAAA,mBAAA,IAAA,KAAA,CAAA,CAAA,EAIlB,YAUc,qBAAA;KAVA,OAAO,QAAA;KAAQ,OAAO,MAAA;KAAO,UAAO;;4BAS9C,CARF,YAQE,iBAAA;MAPA,IAAG;eACC;MAAJ,KAAI;kBACK,WAAA;8EAAU,QAAA;MACnB,eAAY;MACX,aAAa,QAAA;MACb,SAAO,CAAA,CAAI,MAAA;MACX,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as GrPromptDialog_default } from "./chunks/GrPromptDialog-
|
|
2
|
-
import { t as grPromptDialogConfig } from "../../chunks/config-
|
|
1
|
+
import { t as GrPromptDialog_default } from "./chunks/GrPromptDialog-CUMW6_58.js";
|
|
2
|
+
import { t as grPromptDialogConfig } from "../../chunks/config-B8rC_K97.js";
|
|
3
3
|
export { GrPromptDialog_default as GrPromptDialog, GrPromptDialog_default as default, grPromptDialogConfig };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as grRadioDotBaseClass, i as grRadioControlClass, o as grRadioDotClass, r as grRadioButtonClass, s as grRadioRootClass } from "../../../chunks/config-
|
|
1
|
+
import { a as grRadioDotBaseClass, i as grRadioControlClass, o as grRadioDotClass, r as grRadioButtonClass, s as grRadioRootClass } from "../../../chunks/config-BXffa3ta.js";
|
|
2
2
|
import { computed, createElementBlock, createElementVNode, defineComponent, inject, normalizeClass, openBlock, renderSlot, unref, withKeys, withModifiers } from "vue";
|
|
3
3
|
//#region src/components/GrRadio/grRadioGroupContext.ts
|
|
4
4
|
var GR_RADIO_GROUP_CONTEXT = Symbol("GR_RADIO_GROUP_CONTEXT");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrRadio-BxBs3WHq.js","names":[],"sources":["../../../../src/components/GrRadio/grRadioGroupContext.ts","../../../../src/components/GrRadio/GrRadio.vue","../../../../src/components/GrRadio/GrRadio.vue"],"sourcesContent":["import type { ComputedRef, InjectionKey } from 'vue'\n\nimport type { GrButtonSize } from '../GrButton/grButtonStyles'\n\nexport type GrRadioGroupContext = {\n modelValue: ComputedRef<string>\n name: ComputedRef<string | undefined>\n disabled: ComputedRef<boolean>\n size: ComputedRef<GrButtonSize>\n setValue: (value: string) => void\n}\n\nexport const GR_RADIO_GROUP_CONTEXT: InjectionKey<GrRadioGroupContext> = Symbol('GR_RADIO_GROUP_CONTEXT')","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\n\nimport {\n grRadioButtonClass,\n grRadioControlClass,\n grRadioDotBaseClass,\n grRadioDotClass,\n grRadioRootClass,\n type GrRadioVariant,\n} from './grRadioStyles'\nimport { GR_RADIO_GROUP_CONTEXT } from './grRadioGroupContext'\n\n/**\n * GrRadio — одиночный элемент группы выбора.\n *\n * Может работать автономно (через `v-model`) либо внутри `GrRadioGroup`\n * (тогда `modelValue`/`disabled`/`size`/`name` приходят через `inject`).\n *\n * @prop value — значение этого элемента, сравнивается с `modelValue` группы.\n * @prop variant — визуальное представление: `radiobox` (круг+dot) или `button` (стиль `GrButton`).\n */\nexport interface GrRadioProps {\n value: string\n modelValue?: string\n disabled?: boolean\n name?: string\n required?: boolean\n form?: string\n id?: string\n size?: GrButtonSize\n variant?: GrRadioVariant\n buttonVariant?: GrButtonVariant\n buttonTone?: GrButtonTone\n selectedButtonVariant?: GrButtonVariant\n selectedButtonTone?: GrButtonTone\n ariaLabel?: string\n}\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrRadioProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n required: false,\n form: undefined,\n id: undefined,\n size: undefined,\n variant: 'radiobox',\n buttonVariant: 'outline',\n buttonTone: 'neutral',\n selectedButtonVariant: 'primary',\n selectedButtonTone: 'primary',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst group = inject(GR_RADIO_GROUP_CONTEXT, null)\n\nconst resolvedModelValue = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n return group?.modelValue.value ?? ''\n})\n\nconst resolvedDisabled = computed(() => {\n if (props.disabled !== undefined)\n return props.disabled\n\n return group?.disabled.value ?? false\n})\n\nconst resolvedName = computed(() => {\n if (props.name)\n return props.name\n\n return group?.name.value\n})\n\nconst resolvedSize = computed<GrButtonSize>(() => {\n if (props.size)\n return props.size\n\n return group?.size.value ?? 'md'\n})\n\nconst checked = computed(() => resolvedModelValue.value === props.value)\n\nconst buttonClassName = computed(() => {\n return grRadioButtonClass({\n checked: checked.value,\n disabled: resolvedDisabled.value,\n size: resolvedSize.value,\n buttonVariant: props.buttonVariant,\n buttonTone: props.buttonTone,\n selectedButtonVariant: props.selectedButtonVariant,\n selectedButtonTone: props.selectedButtonTone,\n })\n})\n\nconst rootClassName = computed(() => grRadioRootClass(resolvedDisabled.value))\nconst controlClassName = computed(() => grRadioControlClass(checked.value))\nconst dotClassName = computed(() => grRadioDotClass(checked.value))\n\nfunction setValue(next: string): void {\n if (resolvedDisabled.value)\n return\n\n if (props.modelValue !== undefined) {\n emit('update:modelValue', next)\n return\n }\n\n group?.setValue(next)\n}\n\nfunction onButtonClick(): void {\n setValue(props.value)\n}\n</script>\n\n<template>\n <div\n v-if=\"variant === 'button'\"\n data-ds-button\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"buttonClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot />\n </div>\n\n <div\n v-else\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n class=\"inline-flex items-center gap-2 select-none focus-visible:outline-none focus-visible:rounded-[8px] focus-visible:shadow-[0_0_0_2px_var(--ring),0_0_0_4px_var(--bg)]\"\n :class=\"rootClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <span\n data-ds-radio-control\n aria-hidden=\"true\"\n class=\"h-4 w-4 rounded-full border flex items-center justify-center transition-colors duration-150\"\n :class=\"controlClassName\"\n >\n <span\n data-ds-radio-dot\n :class=\"[grRadioDotBaseClass, dotClassName]\"\n />\n </span>\n\n <span class=\"text-sm text-[var(--muted-fg)]\">\n <slot />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\n\nimport {\n grRadioButtonClass,\n grRadioControlClass,\n grRadioDotBaseClass,\n grRadioDotClass,\n grRadioRootClass,\n type GrRadioVariant,\n} from './grRadioStyles'\nimport { GR_RADIO_GROUP_CONTEXT } from './grRadioGroupContext'\n\n/**\n * GrRadio — одиночный элемент группы выбора.\n *\n * Может работать автономно (через `v-model`) либо внутри `GrRadioGroup`\n * (тогда `modelValue`/`disabled`/`size`/`name` приходят через `inject`).\n *\n * @prop value — значение этого элемента, сравнивается с `modelValue` группы.\n * @prop variant — визуальное представление: `radiobox` (круг+dot) или `button` (стиль `GrButton`).\n */\nexport interface GrRadioProps {\n value: string\n modelValue?: string\n disabled?: boolean\n name?: string\n required?: boolean\n form?: string\n id?: string\n size?: GrButtonSize\n variant?: GrRadioVariant\n buttonVariant?: GrButtonVariant\n buttonTone?: GrButtonTone\n selectedButtonVariant?: GrButtonVariant\n selectedButtonTone?: GrButtonTone\n ariaLabel?: string\n}\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrRadioProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n required: false,\n form: undefined,\n id: undefined,\n size: undefined,\n variant: 'radiobox',\n buttonVariant: 'outline',\n buttonTone: 'neutral',\n selectedButtonVariant: 'primary',\n selectedButtonTone: 'primary',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst group = inject(GR_RADIO_GROUP_CONTEXT, null)\n\nconst resolvedModelValue = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n return group?.modelValue.value ?? ''\n})\n\nconst resolvedDisabled = computed(() => {\n if (props.disabled !== undefined)\n return props.disabled\n\n return group?.disabled.value ?? false\n})\n\nconst resolvedName = computed(() => {\n if (props.name)\n return props.name\n\n return group?.name.value\n})\n\nconst resolvedSize = computed<GrButtonSize>(() => {\n if (props.size)\n return props.size\n\n return group?.size.value ?? 'md'\n})\n\nconst checked = computed(() => resolvedModelValue.value === props.value)\n\nconst buttonClassName = computed(() => {\n return grRadioButtonClass({\n checked: checked.value,\n disabled: resolvedDisabled.value,\n size: resolvedSize.value,\n buttonVariant: props.buttonVariant,\n buttonTone: props.buttonTone,\n selectedButtonVariant: props.selectedButtonVariant,\n selectedButtonTone: props.selectedButtonTone,\n })\n})\n\nconst rootClassName = computed(() => grRadioRootClass(resolvedDisabled.value))\nconst controlClassName = computed(() => grRadioControlClass(checked.value))\nconst dotClassName = computed(() => grRadioDotClass(checked.value))\n\nfunction setValue(next: string): void {\n if (resolvedDisabled.value)\n return\n\n if (props.modelValue !== undefined) {\n emit('update:modelValue', next)\n return\n }\n\n group?.setValue(next)\n}\n\nfunction onButtonClick(): void {\n setValue(props.value)\n}\n</script>\n\n<template>\n <div\n v-if=\"variant === 'button'\"\n data-ds-button\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"buttonClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot />\n </div>\n\n <div\n v-else\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n class=\"inline-flex items-center gap-2 select-none focus-visible:outline-none focus-visible:rounded-[8px] focus-visible:shadow-[0_0_0_2px_var(--ring),0_0_0_4px_var(--bg)]\"\n :class=\"rootClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <span\n data-ds-radio-control\n aria-hidden=\"true\"\n class=\"h-4 w-4 rounded-full border flex items-center justify-center transition-colors duration-150\"\n :class=\"controlClassName\"\n >\n <span\n data-ds-radio-dot\n :class=\"[grRadioDotBaseClass, dotClassName]\"\n />\n </span>\n\n <span class=\"text-sm text-[var(--muted-fg)]\">\n <slot />\n </span>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GrRadio-B_t_ZNVl.js","names":[],"sources":["../../../../src/components/GrRadio/grRadioGroupContext.ts","../../../../src/components/GrRadio/GrRadio.vue","../../../../src/components/GrRadio/GrRadio.vue"],"sourcesContent":["import type { ComputedRef, InjectionKey } from 'vue'\n\nimport type { GrButtonSize } from '../GrButton/grButtonStyles'\n\nexport type GrRadioGroupContext = {\n modelValue: ComputedRef<string>\n name: ComputedRef<string | undefined>\n disabled: ComputedRef<boolean>\n size: ComputedRef<GrButtonSize>\n setValue: (value: string) => void\n}\n\nexport const GR_RADIO_GROUP_CONTEXT: InjectionKey<GrRadioGroupContext> = Symbol('GR_RADIO_GROUP_CONTEXT')","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\n\nimport {\n grRadioButtonClass,\n grRadioControlClass,\n grRadioDotBaseClass,\n grRadioDotClass,\n grRadioRootClass,\n type GrRadioVariant,\n} from './grRadioStyles'\nimport { GR_RADIO_GROUP_CONTEXT } from './grRadioGroupContext'\n\n/**\n * GrRadio — одиночный элемент группы выбора.\n *\n * Может работать автономно (через `v-model`) либо внутри `GrRadioGroup`\n * (тогда `modelValue`/`disabled`/`size`/`name` приходят через `inject`).\n *\n * @prop value — значение этого элемента, сравнивается с `modelValue` группы.\n * @prop variant — визуальное представление: `radiobox` (круг+dot) или `button` (стиль `GrButton`).\n */\nexport interface GrRadioProps {\n value: string\n modelValue?: string\n disabled?: boolean\n name?: string\n required?: boolean\n form?: string\n id?: string\n size?: GrButtonSize\n variant?: GrRadioVariant\n buttonVariant?: GrButtonVariant\n buttonTone?: GrButtonTone\n selectedButtonVariant?: GrButtonVariant\n selectedButtonTone?: GrButtonTone\n ariaLabel?: string\n}\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrRadioProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n required: false,\n form: undefined,\n id: undefined,\n size: undefined,\n variant: 'radiobox',\n buttonVariant: 'outline',\n buttonTone: 'neutral',\n selectedButtonVariant: 'primary',\n selectedButtonTone: 'primary',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst group = inject(GR_RADIO_GROUP_CONTEXT, null)\n\nconst resolvedModelValue = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n return group?.modelValue.value ?? ''\n})\n\nconst resolvedDisabled = computed(() => {\n if (props.disabled !== undefined)\n return props.disabled\n\n return group?.disabled.value ?? false\n})\n\nconst resolvedName = computed(() => {\n if (props.name)\n return props.name\n\n return group?.name.value\n})\n\nconst resolvedSize = computed<GrButtonSize>(() => {\n if (props.size)\n return props.size\n\n return group?.size.value ?? 'md'\n})\n\nconst checked = computed(() => resolvedModelValue.value === props.value)\n\nconst buttonClassName = computed(() => {\n return grRadioButtonClass({\n checked: checked.value,\n disabled: resolvedDisabled.value,\n size: resolvedSize.value,\n buttonVariant: props.buttonVariant,\n buttonTone: props.buttonTone,\n selectedButtonVariant: props.selectedButtonVariant,\n selectedButtonTone: props.selectedButtonTone,\n })\n})\n\nconst rootClassName = computed(() => grRadioRootClass(resolvedDisabled.value))\nconst controlClassName = computed(() => grRadioControlClass(checked.value))\nconst dotClassName = computed(() => grRadioDotClass(checked.value))\n\nfunction setValue(next: string): void {\n if (resolvedDisabled.value)\n return\n\n if (props.modelValue !== undefined) {\n emit('update:modelValue', next)\n return\n }\n\n group?.setValue(next)\n}\n\nfunction onButtonClick(): void {\n setValue(props.value)\n}\n</script>\n\n<template>\n <div\n v-if=\"variant === 'button'\"\n data-ds-button\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"buttonClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot />\n </div>\n\n <div\n v-else\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n class=\"inline-flex items-center gap-2 select-none focus-visible:outline-none focus-visible:rounded-[8px] focus-visible:shadow-[0_0_0_2px_var(--ring),0_0_0_4px_var(--bg)]\"\n :class=\"rootClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <span\n data-ds-radio-control\n aria-hidden=\"true\"\n class=\"h-4 w-4 rounded-full border flex items-center justify-center transition-colors duration-150\"\n :class=\"controlClassName\"\n >\n <span\n data-ds-radio-dot\n :class=\"[grRadioDotBaseClass, dotClassName]\"\n />\n </span>\n\n <span class=\"text-sm text-[var(--muted-fg)]\">\n <slot />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\n\nimport {\n grRadioButtonClass,\n grRadioControlClass,\n grRadioDotBaseClass,\n grRadioDotClass,\n grRadioRootClass,\n type GrRadioVariant,\n} from './grRadioStyles'\nimport { GR_RADIO_GROUP_CONTEXT } from './grRadioGroupContext'\n\n/**\n * GrRadio — одиночный элемент группы выбора.\n *\n * Может работать автономно (через `v-model`) либо внутри `GrRadioGroup`\n * (тогда `modelValue`/`disabled`/`size`/`name` приходят через `inject`).\n *\n * @prop value — значение этого элемента, сравнивается с `modelValue` группы.\n * @prop variant — визуальное представление: `radiobox` (круг+dot) или `button` (стиль `GrButton`).\n */\nexport interface GrRadioProps {\n value: string\n modelValue?: string\n disabled?: boolean\n name?: string\n required?: boolean\n form?: string\n id?: string\n size?: GrButtonSize\n variant?: GrRadioVariant\n buttonVariant?: GrButtonVariant\n buttonTone?: GrButtonTone\n selectedButtonVariant?: GrButtonVariant\n selectedButtonTone?: GrButtonTone\n ariaLabel?: string\n}\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrRadioProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n required: false,\n form: undefined,\n id: undefined,\n size: undefined,\n variant: 'radiobox',\n buttonVariant: 'outline',\n buttonTone: 'neutral',\n selectedButtonVariant: 'primary',\n selectedButtonTone: 'primary',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst group = inject(GR_RADIO_GROUP_CONTEXT, null)\n\nconst resolvedModelValue = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n return group?.modelValue.value ?? ''\n})\n\nconst resolvedDisabled = computed(() => {\n if (props.disabled !== undefined)\n return props.disabled\n\n return group?.disabled.value ?? false\n})\n\nconst resolvedName = computed(() => {\n if (props.name)\n return props.name\n\n return group?.name.value\n})\n\nconst resolvedSize = computed<GrButtonSize>(() => {\n if (props.size)\n return props.size\n\n return group?.size.value ?? 'md'\n})\n\nconst checked = computed(() => resolvedModelValue.value === props.value)\n\nconst buttonClassName = computed(() => {\n return grRadioButtonClass({\n checked: checked.value,\n disabled: resolvedDisabled.value,\n size: resolvedSize.value,\n buttonVariant: props.buttonVariant,\n buttonTone: props.buttonTone,\n selectedButtonVariant: props.selectedButtonVariant,\n selectedButtonTone: props.selectedButtonTone,\n })\n})\n\nconst rootClassName = computed(() => grRadioRootClass(resolvedDisabled.value))\nconst controlClassName = computed(() => grRadioControlClass(checked.value))\nconst dotClassName = computed(() => grRadioDotClass(checked.value))\n\nfunction setValue(next: string): void {\n if (resolvedDisabled.value)\n return\n\n if (props.modelValue !== undefined) {\n emit('update:modelValue', next)\n return\n }\n\n group?.setValue(next)\n}\n\nfunction onButtonClick(): void {\n setValue(props.value)\n}\n</script>\n\n<template>\n <div\n v-if=\"variant === 'button'\"\n data-ds-button\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"buttonClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot />\n </div>\n\n <div\n v-else\n data-ds-radio\n role=\"radio\"\n :aria-checked=\"checked ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n class=\"inline-flex items-center gap-2 select-none focus-visible:outline-none focus-visible:rounded-[8px] focus-visible:shadow-[0_0_0_2px_var(--ring),0_0_0_4px_var(--bg)]\"\n :class=\"rootClassName\"\n @click=\"onButtonClick\"\n @keydown.space.prevent=\"onButtonClick\"\n @keydown.enter.prevent=\"onButtonClick\"\n >\n <input\n :id=\"id\"\n type=\"radio\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :required=\"required\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n >\n\n <span\n data-ds-radio-control\n aria-hidden=\"true\"\n class=\"h-4 w-4 rounded-full border flex items-center justify-center transition-colors duration-150\"\n :class=\"controlClassName\"\n >\n <span\n data-ds-radio-dot\n :class=\"[grRadioDotBaseClass, dotClassName]\"\n />\n </span>\n\n <span class=\"text-sm text-[var(--muted-fg)]\">\n <slot />\n </span>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as grRadioSafelist, t as grRadioConfig } from "../../chunks/config-
|
|
2
|
-
import { n as GR_RADIO_GROUP_CONTEXT, t as GrRadio_default } from "./chunks/GrRadio-
|
|
1
|
+
import { n as grRadioSafelist, t as grRadioConfig } from "../../chunks/config-BXffa3ta.js";
|
|
2
|
+
import { n as GR_RADIO_GROUP_CONTEXT, t as GrRadio_default } from "./chunks/GrRadio-B_t_ZNVl.js";
|
|
3
3
|
export { GR_RADIO_GROUP_CONTEXT, GrRadio_default as GrRadio, GrRadio_default as default, grRadioConfig, grRadioSafelist };
|
package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CEAfJQ6A.js → GrRadioGroup-CVlgpUBr.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as GrButtonGroup_default } from "../../GrButtonGroup/chunks/GrButtonGroup-CBj4tpms.js";
|
|
2
|
-
import { n as GR_RADIO_GROUP_CONTEXT, t as GrRadio_default } from "../../GrRadio/chunks/GrRadio-
|
|
2
|
+
import { n as GR_RADIO_GROUP_CONTEXT, t as GrRadio_default } from "../../GrRadio/chunks/GrRadio-B_t_ZNVl.js";
|
|
3
3
|
import { Fragment, computed, createBlock, createElementBlock, createTextVNode, defineComponent, openBlock, provide, renderList, renderSlot, toDisplayString, withCtx } from "vue";
|
|
4
4
|
//#region src/components/GrRadioGroup/GrRadioGroup.vue?vue&type=script&setup=true&lang.ts
|
|
5
5
|
var _hoisted_1 = ["aria-label", "aria-disabled"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrRadioGroup-
|
|
1
|
+
{"version":3,"file":"GrRadioGroup-CVlgpUBr.js","names":["$slots"],"sources":["../../../../src/components/GrRadioGroup/GrRadioGroup.vue","../../../../src/components/GrRadioGroup/GrRadioGroup.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\n\nimport type { GrButtonSize } from '../GrButton'\nimport GrButtonGroup from '../GrButtonGroup/GrButtonGroup.vue'\nimport GrRadio from '../GrRadio/GrRadio.vue'\nimport { GR_RADIO_GROUP_CONTEXT } from '../GrRadio'\n\nexport type GrRadioGroupVariant = 'radiobox' | 'button'\nexport interface GrRadioGroupOption { value: string, label: string }\n\n/**\n * GrRadioGroup — контейнер группы `GrRadio`.\n *\n * Может работать как через слот (ручной рендер `GrRadio`), так и через проп `options`.\n * Предоставляет дочерним `GrRadio` общий `modelValue`/`disabled`/`size`/`name` через `inject`.\n */\nexport interface GrRadioGroupProps {\n modelValue: string\n options?: GrRadioGroupOption[]\n name?: string\n disabled?: boolean\n variant?: GrRadioGroupVariant\n size?: GrButtonSize\n ariaLabel?: string\n}\n\nconst props = withDefaults(defineProps<GrRadioGroupProps>(), {\n options: undefined,\n name: undefined,\n disabled: false,\n variant: 'radiobox',\n size: 'md',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nfunction setValue(next: string): void {\n if (props.disabled)\n return\n emit('update:modelValue', next)\n}\n\nprovide(GR_RADIO_GROUP_CONTEXT, {\n modelValue: computed(() => props.modelValue),\n name: computed(() => props.name),\n disabled: computed(() => props.disabled),\n size: computed(() => props.size),\n setValue,\n})\n</script>\n\n<template>\n <div\n data-ds-radio-group\n role=\"radiogroup\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n >\n <template v-if=\"$slots.default\">\n <GrButtonGroup v-if=\"variant === 'button'\">\n <slot />\n </GrButtonGroup>\n <div v-else class=\"grid gap-2\">\n <slot />\n </div>\n </template>\n <template v-else>\n <GrButtonGroup v-if=\"variant === 'button'\">\n <GrRadio\n v-for=\"opt in options ?? []\"\n :key=\"opt.value\"\n :value=\"opt.value\"\n variant=\"button\"\n :size=\"size\"\n >\n {{ opt.label }}\n </GrRadio>\n </GrButtonGroup>\n <div v-else class=\"grid gap-2\">\n <GrRadio v-for=\"opt in options ?? []\" :key=\"opt.value\" :value=\"opt.value\">\n {{ opt.label }}\n </GrRadio>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide } from 'vue'\n\nimport type { GrButtonSize } from '../GrButton'\nimport GrButtonGroup from '../GrButtonGroup/GrButtonGroup.vue'\nimport GrRadio from '../GrRadio/GrRadio.vue'\nimport { GR_RADIO_GROUP_CONTEXT } from '../GrRadio'\n\nexport type GrRadioGroupVariant = 'radiobox' | 'button'\nexport interface GrRadioGroupOption { value: string, label: string }\n\n/**\n * GrRadioGroup — контейнер группы `GrRadio`.\n *\n * Может работать как через слот (ручной рендер `GrRadio`), так и через проп `options`.\n * Предоставляет дочерним `GrRadio` общий `modelValue`/`disabled`/`size`/`name` через `inject`.\n */\nexport interface GrRadioGroupProps {\n modelValue: string\n options?: GrRadioGroupOption[]\n name?: string\n disabled?: boolean\n variant?: GrRadioGroupVariant\n size?: GrButtonSize\n ariaLabel?: string\n}\n\nconst props = withDefaults(defineProps<GrRadioGroupProps>(), {\n options: undefined,\n name: undefined,\n disabled: false,\n variant: 'radiobox',\n size: 'md',\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nfunction setValue(next: string): void {\n if (props.disabled)\n return\n emit('update:modelValue', next)\n}\n\nprovide(GR_RADIO_GROUP_CONTEXT, {\n modelValue: computed(() => props.modelValue),\n name: computed(() => props.name),\n disabled: computed(() => props.disabled),\n size: computed(() => props.size),\n setValue,\n})\n</script>\n\n<template>\n <div\n data-ds-radio-group\n role=\"radiogroup\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n >\n <template v-if=\"$slots.default\">\n <GrButtonGroup v-if=\"variant === 'button'\">\n <slot />\n </GrButtonGroup>\n <div v-else class=\"grid gap-2\">\n <slot />\n </div>\n </template>\n <template v-else>\n <GrButtonGroup v-if=\"variant === 'button'\">\n <GrRadio\n v-for=\"opt in options ?? []\"\n :key=\"opt.value\"\n :value=\"opt.value\"\n variant=\"button\"\n :size=\"size\"\n >\n {{ opt.label }}\n </GrRadio>\n </GrButtonGroup>\n <div v-else class=\"grid gap-2\">\n <GrRadio v-for=\"opt in options ?? []\" :key=\"opt.value\" :value=\"opt.value\">\n {{ opt.label }}\n </GrRadio>\n </div>\n </template>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BA,MAAM,QAAQ;EASd,MAAM,OAAO;EAIb,SAAS,SAAS,MAAoB;AACpC,OAAI,MAAM,SACR;AACF,QAAK,qBAAqB,KAAI;;AAGhC,UAAQ,wBAAwB;GAC9B,YAAY,eAAe,MAAM,WAAW;GAC5C,MAAM,eAAe,MAAM,KAAK;GAChC,UAAU,eAAe,MAAM,SAAS;GACxC,MAAM,eAAe,MAAM,KAAK;GAChC;GACD,CAAA;;uBAIC,mBAgCM,OAAA;IA/BJ,uBAAA;IACA,MAAK;IACJ,cAAY,QAAA;IACZ,iBAAe,QAAA,WAAQ,SAAY,KAAA;OAEpBA,KAAAA,OAAO,WAAA,WAAA,EAAvB,mBAOW,UAAA,EAAA,KAAA,GAAA,EAAA,CANY,QAAA,YAAO,YAAA,WAAA,EAA5B,YAEgB,uBAAA,EAAA,KAAA,GAAA,EAAA;2BADN,CAAR,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA;;uBAEV,mBAEM,OAFN,YAEM,CADJ,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA,EAAA,EAAA,GAAA,KAAA,WAAA,EAGZ,mBAiBW,UAAA,EAAA,KAAA,GAAA,EAAA,CAhBY,QAAA,YAAO,YAAA,WAAA,EAA5B,YAUgB,uBAAA,EAAA,KAAA,GAAA,EAAA;2BARgB,EAAA,UAAA,KAAA,EAD9B,mBAQU,UAAA,MAAA,WAPM,QAAA,WAAO,EAAA,GAAd,QAAG;yBADZ,YAQU,iBAAA;MANP,KAAK,IAAI;MACT,OAAO,IAAI;MACZ,SAAQ;MACP,MAAM,QAAA;;6BAEQ,CAAA,gBAAA,gBAAZ,IAAI,MAAK,EAAA,EAAA,CAAA,CAAA;;;;;uBAGhB,mBAIM,OAJN,YAIM,EAAA,UAAA,KAAA,EAHJ,mBAEU,UAAA,MAAA,WAFa,QAAA,WAAO,EAAA,GAAd,QAAG;wBAAnB,YAEU,iBAAA;KAF6B,KAAK,IAAI;KAAQ,OAAO,IAAI;;4BAClD,CAAA,gBAAA,gBAAZ,IAAI,MAAK,EAAA,EAAA,CAAA,CAAA"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as GrRadioGroup_default } from "./chunks/GrRadioGroup-
|
|
2
|
-
import { t as grRadioGroupConfig } from "../../chunks/config-
|
|
1
|
+
import { t as GrRadioGroup_default } from "./chunks/GrRadioGroup-CVlgpUBr.js";
|
|
2
|
+
import { t as grRadioGroupConfig } from "../../chunks/config-D27BL0H9.js";
|
|
3
3
|
export { GrRadioGroup_default as GrRadioGroup, GrRadioGroup_default as default, grRadioGroupConfig };
|
package/dist/components/GrSegmented/chunks/{GrSegmented-Bwn2qOY4.js → GrSegmented-BPl1koHc.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as grSegmentedItemIconClass, c as grSegmentedRootStyle, i as grSegmentedItemClass, o as grSegmentedItemLabelClass, r as grSegmentedIndicatorClass, s as grSegmentedRootClass } from "../../../chunks/config-
|
|
1
|
+
import { a as grSegmentedItemIconClass, c as grSegmentedRootStyle, i as grSegmentedItemClass, o as grSegmentedItemLabelClass, r as grSegmentedIndicatorClass, s as grSegmentedRootClass } from "../../../chunks/config-BhvNm4Pp.js";
|
|
2
2
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, getCurrentInstance, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, watch } from "vue";
|
|
3
3
|
//#region src/components/GrSegmented/GrSegmented.vue?vue&type=script&setup=true&lang.ts
|
|
4
4
|
var _hoisted_1 = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrSegmented-Bwn2qOY4.js","names":[],"sources":["../../../../src/components/GrSegmented/GrSegmented.vue","../../../../src/components/GrSegmented/GrSegmented.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport type { ComponentPublicInstance } from 'vue'\n\nimport {\n grSegmentedIndicatorClass,\n grSegmentedItemClass,\n grSegmentedItemIconClass,\n grSegmentedItemLabelClass,\n grSegmentedRootClass,\n grSegmentedRootStyle,\n type GrSegmentedOption,\n type GrSegmentedSize,\n type GrSegmentedValue,\n type GrSegmentedVariant,\n} from './grSegmentedStyles'\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\ntype IndicatorGeometry = {\n width: number\n height: number\n x: number\n y: number\n}\n\n/**\n * Пропсы публичного DS-примитива «Segmented».\n */\nexport interface GrSegmentedProps {\n modelValue: GrSegmentedValue\n options: GrSegmentedOption[]\n variant?: GrSegmentedVariant\n size?: GrSegmentedSize\n /** Длительность анимации индикатора в мс. */\n indicatorDuration?: number\n /** Растягивать сегмент на всю ширину контейнера. */\n block?: boolean\n disabled?: boolean\n /** Имя скрытых radio-inputs для интеграции с нативной формой. */\n name?: string\n ariaLabel?: string\n}\n\nconst props = withDefaults(\n defineProps<GrSegmentedProps>(),\n {\n variant: 'pills',\n size: 'md',\n indicatorDuration: 300,\n block: false,\n disabled: false,\n name: undefined,\n ariaLabel: undefined,\n },\n)\n\nconst emit = defineEmits<{\n (event: 'update:modelValue', value: GrSegmentedValue): void\n (event: 'change', value: GrSegmentedValue, option: GrSegmentedOption): void\n}>()\n\nconst instance = getCurrentInstance()\nconst fallbackName = `ds-segmented-${instance?.uid ?? Math.random()}`\n\nconst rootRef = ref<HTMLElement | null>(null)\nconst itemRefs = ref(new Map<string, HTMLElement>())\nconst indicatorGeometry = ref<IndicatorGeometry | null>(null)\nconst indicatorReady = ref(false)\n\nlet resizeObserver: ResizeObserver | null = null\nlet observedRoot: HTMLElement | null = null\nlet observedItem: HTMLElement | null = null\nlet scheduled = false\n\nconst selectedIndex = computed(() => props.options.findIndex(option => option.value === props.modelValue))\nconst selectedOption = computed(() => props.options[selectedIndex.value] ?? null)\nconst enabledOptions = computed(() => props.options.filter(option => !resolveOptionDisabled(option)))\nconst indicatorDuration = computed(() => Math.max(0, Math.round(props.indicatorDuration)))\nconst rootClassName = computed(() => grSegmentedRootClass({\n variant: props.variant,\n block: props.block,\n disabled: props.disabled,\n}))\nconst rootStyle = computed<Record<string, string>>(() => ({\n ...grSegmentedRootStyle({\n variant: props.variant,\n size: props.size,\n }),\n gridTemplateColumns: props.options.length > 0\n ? props.options.map(() => props.block ? 'minmax(0,1fr)' : 'minmax(0,max-content)').join(' ')\n : 'none',\n}))\nconst indicatorClassName = computed(() => grSegmentedIndicatorClass(props.variant))\nconst resolvedName = computed(() => props.name ?? fallbackName)\nconst hasIndicator = computed(() => selectedIndex.value !== -1 && indicatorGeometry.value !== null)\n\nconst indicatorStyle = computed<Record<string, string>>(() => {\n const geometry = indicatorGeometry.value\n if (!geometry) {\n return {\n opacity: '0',\n width: '0px',\n height: '0px',\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: 'translate3d(0px, 0px, 0px)',\n }\n }\n\n return {\n opacity: indicatorReady.value ? '1' : '0',\n width: `${geometry.width}px`,\n height: `${geometry.height}px`,\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: `translate3d(${geometry.x}px, ${geometry.y}px, 0)`,\n }\n})\n\nfunction getOptionKey(value: GrSegmentedValue): string {\n return String(value)\n}\n\nfunction resolveOptionDisabled(option: GrSegmentedOption): boolean {\n return props.disabled || Boolean(option.disabled)\n}\n\nfunction isOptionSelected(option: GrSegmentedOption): boolean {\n return option.value === props.modelValue\n}\n\nfunction isIconOnlyOption(option: GrSegmentedOption): boolean {\n return Boolean(option.icon) && !option.label\n}\n\nfunction isFocusableOption(option: GrSegmentedOption, index: number): boolean {\n if (resolveOptionDisabled(option)) {\n return false\n }\n\n if (isOptionSelected(option)) {\n return true\n }\n\n if (selectedIndex.value !== -1) {\n return false\n }\n\n return enabledOptions.value[0]?.value === props.options[index]?.value\n}\n\nfunction setItemRef(value: GrSegmentedValue, element: Element | ComponentPublicInstance | null): void {\n const key = getOptionKey(value)\n\n if (!(element instanceof HTMLElement)) {\n itemRefs.value.delete(key)\n return\n }\n\n itemRefs.value.set(key, element)\n}\n\nfunction isSameGeometry(left: IndicatorGeometry | null, right: IndicatorGeometry | null): boolean {\n if (left === right) {\n return true\n }\n\n if (!left || !right) {\n return false\n }\n\n return left.width === right.width\n && left.height === right.height\n && left.x === right.x\n && left.y === right.y\n}\n\nfunction measureIndicator(): void {\n const root = rootRef.value\n const option = selectedOption.value\n if (!root || !option) {\n if (indicatorGeometry.value !== null)\n indicatorGeometry.value = null\n\n if (indicatorReady.value)\n indicatorReady.value = false\n\n return\n }\n\n const selectedItem = itemRefs.value.get(getOptionKey(option.value))\n if (!selectedItem) {\n return\n }\n\n const rootRect = root.getBoundingClientRect()\n const itemRect = selectedItem.getBoundingClientRect()\n\n const nextGeometry = {\n width: Math.max(Math.round(itemRect.width), 0),\n height: Math.max(Math.round(itemRect.height), 0),\n x: Math.round(itemRect.left - rootRect.left),\n y: Math.max(Math.round(itemRect.top - rootRect.top) - 1, 0),\n } satisfies IndicatorGeometry\n\n if (!isSameGeometry(indicatorGeometry.value, nextGeometry)) {\n indicatorGeometry.value = nextGeometry\n }\n\n const nextReady = nextGeometry.width > 0 && nextGeometry.height > 0\n if (indicatorReady.value !== nextReady) {\n indicatorReady.value = nextReady\n }\n}\n\nfunction refreshObserver(): void {\n if (typeof ResizeObserver === 'undefined') {\n return\n }\n\n const root = rootRef.value\n const option = selectedOption.value\n const selectedItem = option\n ? itemRefs.value.get(getOptionKey(option.value)) ?? null\n : null\n\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => scheduleMeasure())\n }\n\n if (!root) {\n resizeObserver.disconnect()\n observedRoot = null\n observedItem = null\n return\n }\n\n if (observedRoot === root && observedItem === selectedItem) {\n return\n }\n\n resizeObserver.disconnect()\n resizeObserver.observe(root)\n\n if (selectedItem) {\n resizeObserver.observe(selectedItem)\n }\n\n observedRoot = root\n observedItem = selectedItem\n}\n\nfunction scheduleMeasure(): void {\n if (scheduled) {\n return\n }\n\n scheduled = true\n void nextTick(() => {\n scheduled = false\n measureIndicator()\n refreshObserver()\n })\n}\n\nfunction emitValue(option: GrSegmentedOption): void {\n if (resolveOptionDisabled(option) || option.value === props.modelValue) {\n return\n }\n\n emit('update:modelValue', option.value)\n emit('change', option.value, option)\n}\n\nfunction getNextEnabledIndex(startIndex: number, direction: 1 | -1): number {\n if (props.options.length === 0) {\n return -1\n }\n\n let cursor = startIndex\n for (let step = 0; step < props.options.length; step += 1) {\n cursor = (cursor + direction + props.options.length) % props.options.length\n const option = props.options[cursor]\n if (option && !resolveOptionDisabled(option)) {\n return cursor\n }\n }\n\n return -1\n}\n\nfunction focusIndex(index: number): void {\n const option = props.options[index]\n if (!option) {\n return\n }\n\n itemRefs.value.get(getOptionKey(option.value))?.focus()\n}\n\nfunction onKeydown(event: KeyboardEvent, index: number): void {\n if (props.disabled) {\n return\n }\n\n if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, 1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, -1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'Home') {\n event.preventDefault()\n const firstOption = enabledOptions.value[0]\n if (!firstOption) {\n return\n }\n\n emitValue(firstOption)\n focusIndex(props.options.findIndex(option => option.value === firstOption.value))\n return\n }\n\n if (event.key === 'End') {\n event.preventDefault()\n const lastOption = enabledOptions.value.at(-1)\n if (!lastOption) {\n return\n }\n\n emitValue(lastOption)\n focusIndex(props.options.findIndex(option => option.value === lastOption.value))\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n const option = props.options[index]\n if (option) {\n emitValue(option)\n }\n }\n}\n\nwatch(() => props.modelValue, () => scheduleMeasure())\nwatch(() => props.options, () => scheduleMeasure(), { deep: true })\nwatch(() => props.variant, () => scheduleMeasure())\nwatch(() => props.size, () => scheduleMeasure())\nwatch(() => props.block, () => scheduleMeasure())\n\nonMounted(() => scheduleMeasure())\nonBeforeUnmount(() => {\n resizeObserver?.disconnect()\n observedRoot = null\n observedItem = null\n})\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n data-ds-segmented\n :data-variant=\"variant\"\n role=\"radiogroup\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClassName\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"hasIndicator\"\n data-ds-segmented-indicator\n aria-hidden=\"true\"\n :class=\"indicatorClassName\"\n :style=\"indicatorStyle\"\n />\n\n <button\n v-for=\"(option, index) in options\"\n :key=\"option.value\"\n :ref=\"element => setItemRef(option.value, element)\"\n data-ds-segmented-item\n :data-value=\"String(option.value)\"\n type=\"button\"\n role=\"radio\"\n :aria-checked=\"isOptionSelected(option) ? 'true' : 'false'\"\n :aria-disabled=\"resolveOptionDisabled(option) ? 'true' : undefined\"\n :disabled=\"resolveOptionDisabled(option)\"\n :tabindex=\"isFocusableOption(option, index) ? 0 : -1\"\n :class=\"grSegmentedItemClass({\n variant,\n selected: isOptionSelected(option),\n disabled: resolveOptionDisabled(option),\n iconOnly: isIconOnlyOption(option),\n })\"\n @click=\"emitValue(option)\"\n @keydown=\"onKeydown($event, index)\"\n >\n <input\n type=\"radio\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :name=\"resolvedName\"\n :value=\"option.value\"\n :checked=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot\n :option=\"option\"\n :selected=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n >\n <component\n :is=\"option.icon\"\n v-if=\"option.icon\"\n aria-hidden=\"true\"\n :class=\"grSegmentedItemIconClass\"\n />\n <span v-if=\"option.label\" :class=\"grSegmentedItemLabelClass\">\n {{ option.label }}\n </span>\n </slot>\n </button>\n </div>\n</template>","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport type { ComponentPublicInstance } from 'vue'\n\nimport {\n grSegmentedIndicatorClass,\n grSegmentedItemClass,\n grSegmentedItemIconClass,\n grSegmentedItemLabelClass,\n grSegmentedRootClass,\n grSegmentedRootStyle,\n type GrSegmentedOption,\n type GrSegmentedSize,\n type GrSegmentedValue,\n type GrSegmentedVariant,\n} from './grSegmentedStyles'\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\ntype IndicatorGeometry = {\n width: number\n height: number\n x: number\n y: number\n}\n\n/**\n * Пропсы публичного DS-примитива «Segmented».\n */\nexport interface GrSegmentedProps {\n modelValue: GrSegmentedValue\n options: GrSegmentedOption[]\n variant?: GrSegmentedVariant\n size?: GrSegmentedSize\n /** Длительность анимации индикатора в мс. */\n indicatorDuration?: number\n /** Растягивать сегмент на всю ширину контейнера. */\n block?: boolean\n disabled?: boolean\n /** Имя скрытых radio-inputs для интеграции с нативной формой. */\n name?: string\n ariaLabel?: string\n}\n\nconst props = withDefaults(\n defineProps<GrSegmentedProps>(),\n {\n variant: 'pills',\n size: 'md',\n indicatorDuration: 300,\n block: false,\n disabled: false,\n name: undefined,\n ariaLabel: undefined,\n },\n)\n\nconst emit = defineEmits<{\n (event: 'update:modelValue', value: GrSegmentedValue): void\n (event: 'change', value: GrSegmentedValue, option: GrSegmentedOption): void\n}>()\n\nconst instance = getCurrentInstance()\nconst fallbackName = `ds-segmented-${instance?.uid ?? Math.random()}`\n\nconst rootRef = ref<HTMLElement | null>(null)\nconst itemRefs = ref(new Map<string, HTMLElement>())\nconst indicatorGeometry = ref<IndicatorGeometry | null>(null)\nconst indicatorReady = ref(false)\n\nlet resizeObserver: ResizeObserver | null = null\nlet observedRoot: HTMLElement | null = null\nlet observedItem: HTMLElement | null = null\nlet scheduled = false\n\nconst selectedIndex = computed(() => props.options.findIndex(option => option.value === props.modelValue))\nconst selectedOption = computed(() => props.options[selectedIndex.value] ?? null)\nconst enabledOptions = computed(() => props.options.filter(option => !resolveOptionDisabled(option)))\nconst indicatorDuration = computed(() => Math.max(0, Math.round(props.indicatorDuration)))\nconst rootClassName = computed(() => grSegmentedRootClass({\n variant: props.variant,\n block: props.block,\n disabled: props.disabled,\n}))\nconst rootStyle = computed<Record<string, string>>(() => ({\n ...grSegmentedRootStyle({\n variant: props.variant,\n size: props.size,\n }),\n gridTemplateColumns: props.options.length > 0\n ? props.options.map(() => props.block ? 'minmax(0,1fr)' : 'minmax(0,max-content)').join(' ')\n : 'none',\n}))\nconst indicatorClassName = computed(() => grSegmentedIndicatorClass(props.variant))\nconst resolvedName = computed(() => props.name ?? fallbackName)\nconst hasIndicator = computed(() => selectedIndex.value !== -1 && indicatorGeometry.value !== null)\n\nconst indicatorStyle = computed<Record<string, string>>(() => {\n const geometry = indicatorGeometry.value\n if (!geometry) {\n return {\n opacity: '0',\n width: '0px',\n height: '0px',\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: 'translate3d(0px, 0px, 0px)',\n }\n }\n\n return {\n opacity: indicatorReady.value ? '1' : '0',\n width: `${geometry.width}px`,\n height: `${geometry.height}px`,\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: `translate3d(${geometry.x}px, ${geometry.y}px, 0)`,\n }\n})\n\nfunction getOptionKey(value: GrSegmentedValue): string {\n return String(value)\n}\n\nfunction resolveOptionDisabled(option: GrSegmentedOption): boolean {\n return props.disabled || Boolean(option.disabled)\n}\n\nfunction isOptionSelected(option: GrSegmentedOption): boolean {\n return option.value === props.modelValue\n}\n\nfunction isIconOnlyOption(option: GrSegmentedOption): boolean {\n return Boolean(option.icon) && !option.label\n}\n\nfunction isFocusableOption(option: GrSegmentedOption, index: number): boolean {\n if (resolveOptionDisabled(option)) {\n return false\n }\n\n if (isOptionSelected(option)) {\n return true\n }\n\n if (selectedIndex.value !== -1) {\n return false\n }\n\n return enabledOptions.value[0]?.value === props.options[index]?.value\n}\n\nfunction setItemRef(value: GrSegmentedValue, element: Element | ComponentPublicInstance | null): void {\n const key = getOptionKey(value)\n\n if (!(element instanceof HTMLElement)) {\n itemRefs.value.delete(key)\n return\n }\n\n itemRefs.value.set(key, element)\n}\n\nfunction isSameGeometry(left: IndicatorGeometry | null, right: IndicatorGeometry | null): boolean {\n if (left === right) {\n return true\n }\n\n if (!left || !right) {\n return false\n }\n\n return left.width === right.width\n && left.height === right.height\n && left.x === right.x\n && left.y === right.y\n}\n\nfunction measureIndicator(): void {\n const root = rootRef.value\n const option = selectedOption.value\n if (!root || !option) {\n if (indicatorGeometry.value !== null)\n indicatorGeometry.value = null\n\n if (indicatorReady.value)\n indicatorReady.value = false\n\n return\n }\n\n const selectedItem = itemRefs.value.get(getOptionKey(option.value))\n if (!selectedItem) {\n return\n }\n\n const rootRect = root.getBoundingClientRect()\n const itemRect = selectedItem.getBoundingClientRect()\n\n const nextGeometry = {\n width: Math.max(Math.round(itemRect.width), 0),\n height: Math.max(Math.round(itemRect.height), 0),\n x: Math.round(itemRect.left - rootRect.left),\n y: Math.max(Math.round(itemRect.top - rootRect.top) - 1, 0),\n } satisfies IndicatorGeometry\n\n if (!isSameGeometry(indicatorGeometry.value, nextGeometry)) {\n indicatorGeometry.value = nextGeometry\n }\n\n const nextReady = nextGeometry.width > 0 && nextGeometry.height > 0\n if (indicatorReady.value !== nextReady) {\n indicatorReady.value = nextReady\n }\n}\n\nfunction refreshObserver(): void {\n if (typeof ResizeObserver === 'undefined') {\n return\n }\n\n const root = rootRef.value\n const option = selectedOption.value\n const selectedItem = option\n ? itemRefs.value.get(getOptionKey(option.value)) ?? null\n : null\n\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => scheduleMeasure())\n }\n\n if (!root) {\n resizeObserver.disconnect()\n observedRoot = null\n observedItem = null\n return\n }\n\n if (observedRoot === root && observedItem === selectedItem) {\n return\n }\n\n resizeObserver.disconnect()\n resizeObserver.observe(root)\n\n if (selectedItem) {\n resizeObserver.observe(selectedItem)\n }\n\n observedRoot = root\n observedItem = selectedItem\n}\n\nfunction scheduleMeasure(): void {\n if (scheduled) {\n return\n }\n\n scheduled = true\n void nextTick(() => {\n scheduled = false\n measureIndicator()\n refreshObserver()\n })\n}\n\nfunction emitValue(option: GrSegmentedOption): void {\n if (resolveOptionDisabled(option) || option.value === props.modelValue) {\n return\n }\n\n emit('update:modelValue', option.value)\n emit('change', option.value, option)\n}\n\nfunction getNextEnabledIndex(startIndex: number, direction: 1 | -1): number {\n if (props.options.length === 0) {\n return -1\n }\n\n let cursor = startIndex\n for (let step = 0; step < props.options.length; step += 1) {\n cursor = (cursor + direction + props.options.length) % props.options.length\n const option = props.options[cursor]\n if (option && !resolveOptionDisabled(option)) {\n return cursor\n }\n }\n\n return -1\n}\n\nfunction focusIndex(index: number): void {\n const option = props.options[index]\n if (!option) {\n return\n }\n\n itemRefs.value.get(getOptionKey(option.value))?.focus()\n}\n\nfunction onKeydown(event: KeyboardEvent, index: number): void {\n if (props.disabled) {\n return\n }\n\n if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, 1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, -1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'Home') {\n event.preventDefault()\n const firstOption = enabledOptions.value[0]\n if (!firstOption) {\n return\n }\n\n emitValue(firstOption)\n focusIndex(props.options.findIndex(option => option.value === firstOption.value))\n return\n }\n\n if (event.key === 'End') {\n event.preventDefault()\n const lastOption = enabledOptions.value.at(-1)\n if (!lastOption) {\n return\n }\n\n emitValue(lastOption)\n focusIndex(props.options.findIndex(option => option.value === lastOption.value))\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n const option = props.options[index]\n if (option) {\n emitValue(option)\n }\n }\n}\n\nwatch(() => props.modelValue, () => scheduleMeasure())\nwatch(() => props.options, () => scheduleMeasure(), { deep: true })\nwatch(() => props.variant, () => scheduleMeasure())\nwatch(() => props.size, () => scheduleMeasure())\nwatch(() => props.block, () => scheduleMeasure())\n\nonMounted(() => scheduleMeasure())\nonBeforeUnmount(() => {\n resizeObserver?.disconnect()\n observedRoot = null\n observedItem = null\n})\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n data-ds-segmented\n :data-variant=\"variant\"\n role=\"radiogroup\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClassName\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"hasIndicator\"\n data-ds-segmented-indicator\n aria-hidden=\"true\"\n :class=\"indicatorClassName\"\n :style=\"indicatorStyle\"\n />\n\n <button\n v-for=\"(option, index) in options\"\n :key=\"option.value\"\n :ref=\"element => setItemRef(option.value, element)\"\n data-ds-segmented-item\n :data-value=\"String(option.value)\"\n type=\"button\"\n role=\"radio\"\n :aria-checked=\"isOptionSelected(option) ? 'true' : 'false'\"\n :aria-disabled=\"resolveOptionDisabled(option) ? 'true' : undefined\"\n :disabled=\"resolveOptionDisabled(option)\"\n :tabindex=\"isFocusableOption(option, index) ? 0 : -1\"\n :class=\"grSegmentedItemClass({\n variant,\n selected: isOptionSelected(option),\n disabled: resolveOptionDisabled(option),\n iconOnly: isIconOnlyOption(option),\n })\"\n @click=\"emitValue(option)\"\n @keydown=\"onKeydown($event, index)\"\n >\n <input\n type=\"radio\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :name=\"resolvedName\"\n :value=\"option.value\"\n :checked=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot\n :option=\"option\"\n :selected=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n >\n <component\n :is=\"option.icon\"\n v-if=\"option.icon\"\n aria-hidden=\"true\"\n :class=\"grSegmentedItemIconClass\"\n />\n <span v-if=\"option.label\" :class=\"grSegmentedItemLabelClass\">\n {{ option.label }}\n </span>\n </slot>\n </button>\n </div>\n</template>"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GrSegmented-BPl1koHc.js","names":[],"sources":["../../../../src/components/GrSegmented/GrSegmented.vue","../../../../src/components/GrSegmented/GrSegmented.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport type { ComponentPublicInstance } from 'vue'\n\nimport {\n grSegmentedIndicatorClass,\n grSegmentedItemClass,\n grSegmentedItemIconClass,\n grSegmentedItemLabelClass,\n grSegmentedRootClass,\n grSegmentedRootStyle,\n type GrSegmentedOption,\n type GrSegmentedSize,\n type GrSegmentedValue,\n type GrSegmentedVariant,\n} from './grSegmentedStyles'\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\ntype IndicatorGeometry = {\n width: number\n height: number\n x: number\n y: number\n}\n\n/**\n * Пропсы публичного DS-примитива «Segmented».\n */\nexport interface GrSegmentedProps {\n modelValue: GrSegmentedValue\n options: GrSegmentedOption[]\n variant?: GrSegmentedVariant\n size?: GrSegmentedSize\n /** Длительность анимации индикатора в мс. */\n indicatorDuration?: number\n /** Растягивать сегмент на всю ширину контейнера. */\n block?: boolean\n disabled?: boolean\n /** Имя скрытых radio-inputs для интеграции с нативной формой. */\n name?: string\n ariaLabel?: string\n}\n\nconst props = withDefaults(\n defineProps<GrSegmentedProps>(),\n {\n variant: 'pills',\n size: 'md',\n indicatorDuration: 300,\n block: false,\n disabled: false,\n name: undefined,\n ariaLabel: undefined,\n },\n)\n\nconst emit = defineEmits<{\n (event: 'update:modelValue', value: GrSegmentedValue): void\n (event: 'change', value: GrSegmentedValue, option: GrSegmentedOption): void\n}>()\n\nconst instance = getCurrentInstance()\nconst fallbackName = `ds-segmented-${instance?.uid ?? Math.random()}`\n\nconst rootRef = ref<HTMLElement | null>(null)\nconst itemRefs = ref(new Map<string, HTMLElement>())\nconst indicatorGeometry = ref<IndicatorGeometry | null>(null)\nconst indicatorReady = ref(false)\n\nlet resizeObserver: ResizeObserver | null = null\nlet observedRoot: HTMLElement | null = null\nlet observedItem: HTMLElement | null = null\nlet scheduled = false\n\nconst selectedIndex = computed(() => props.options.findIndex(option => option.value === props.modelValue))\nconst selectedOption = computed(() => props.options[selectedIndex.value] ?? null)\nconst enabledOptions = computed(() => props.options.filter(option => !resolveOptionDisabled(option)))\nconst indicatorDuration = computed(() => Math.max(0, Math.round(props.indicatorDuration)))\nconst rootClassName = computed(() => grSegmentedRootClass({\n variant: props.variant,\n block: props.block,\n disabled: props.disabled,\n}))\nconst rootStyle = computed<Record<string, string>>(() => ({\n ...grSegmentedRootStyle({\n variant: props.variant,\n size: props.size,\n }),\n gridTemplateColumns: props.options.length > 0\n ? props.options.map(() => props.block ? 'minmax(0,1fr)' : 'minmax(0,max-content)').join(' ')\n : 'none',\n}))\nconst indicatorClassName = computed(() => grSegmentedIndicatorClass(props.variant))\nconst resolvedName = computed(() => props.name ?? fallbackName)\nconst hasIndicator = computed(() => selectedIndex.value !== -1 && indicatorGeometry.value !== null)\n\nconst indicatorStyle = computed<Record<string, string>>(() => {\n const geometry = indicatorGeometry.value\n if (!geometry) {\n return {\n opacity: '0',\n width: '0px',\n height: '0px',\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: 'translate3d(0px, 0px, 0px)',\n }\n }\n\n return {\n opacity: indicatorReady.value ? '1' : '0',\n width: `${geometry.width}px`,\n height: `${geometry.height}px`,\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: `translate3d(${geometry.x}px, ${geometry.y}px, 0)`,\n }\n})\n\nfunction getOptionKey(value: GrSegmentedValue): string {\n return String(value)\n}\n\nfunction resolveOptionDisabled(option: GrSegmentedOption): boolean {\n return props.disabled || Boolean(option.disabled)\n}\n\nfunction isOptionSelected(option: GrSegmentedOption): boolean {\n return option.value === props.modelValue\n}\n\nfunction isIconOnlyOption(option: GrSegmentedOption): boolean {\n return Boolean(option.icon) && !option.label\n}\n\nfunction isFocusableOption(option: GrSegmentedOption, index: number): boolean {\n if (resolveOptionDisabled(option)) {\n return false\n }\n\n if (isOptionSelected(option)) {\n return true\n }\n\n if (selectedIndex.value !== -1) {\n return false\n }\n\n return enabledOptions.value[0]?.value === props.options[index]?.value\n}\n\nfunction setItemRef(value: GrSegmentedValue, element: Element | ComponentPublicInstance | null): void {\n const key = getOptionKey(value)\n\n if (!(element instanceof HTMLElement)) {\n itemRefs.value.delete(key)\n return\n }\n\n itemRefs.value.set(key, element)\n}\n\nfunction isSameGeometry(left: IndicatorGeometry | null, right: IndicatorGeometry | null): boolean {\n if (left === right) {\n return true\n }\n\n if (!left || !right) {\n return false\n }\n\n return left.width === right.width\n && left.height === right.height\n && left.x === right.x\n && left.y === right.y\n}\n\nfunction measureIndicator(): void {\n const root = rootRef.value\n const option = selectedOption.value\n if (!root || !option) {\n if (indicatorGeometry.value !== null)\n indicatorGeometry.value = null\n\n if (indicatorReady.value)\n indicatorReady.value = false\n\n return\n }\n\n const selectedItem = itemRefs.value.get(getOptionKey(option.value))\n if (!selectedItem) {\n return\n }\n\n const rootRect = root.getBoundingClientRect()\n const itemRect = selectedItem.getBoundingClientRect()\n\n const nextGeometry = {\n width: Math.max(Math.round(itemRect.width), 0),\n height: Math.max(Math.round(itemRect.height), 0),\n x: Math.round(itemRect.left - rootRect.left),\n y: Math.max(Math.round(itemRect.top - rootRect.top) - 1, 0),\n } satisfies IndicatorGeometry\n\n if (!isSameGeometry(indicatorGeometry.value, nextGeometry)) {\n indicatorGeometry.value = nextGeometry\n }\n\n const nextReady = nextGeometry.width > 0 && nextGeometry.height > 0\n if (indicatorReady.value !== nextReady) {\n indicatorReady.value = nextReady\n }\n}\n\nfunction refreshObserver(): void {\n if (typeof ResizeObserver === 'undefined') {\n return\n }\n\n const root = rootRef.value\n const option = selectedOption.value\n const selectedItem = option\n ? itemRefs.value.get(getOptionKey(option.value)) ?? null\n : null\n\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => scheduleMeasure())\n }\n\n if (!root) {\n resizeObserver.disconnect()\n observedRoot = null\n observedItem = null\n return\n }\n\n if (observedRoot === root && observedItem === selectedItem) {\n return\n }\n\n resizeObserver.disconnect()\n resizeObserver.observe(root)\n\n if (selectedItem) {\n resizeObserver.observe(selectedItem)\n }\n\n observedRoot = root\n observedItem = selectedItem\n}\n\nfunction scheduleMeasure(): void {\n if (scheduled) {\n return\n }\n\n scheduled = true\n void nextTick(() => {\n scheduled = false\n measureIndicator()\n refreshObserver()\n })\n}\n\nfunction emitValue(option: GrSegmentedOption): void {\n if (resolveOptionDisabled(option) || option.value === props.modelValue) {\n return\n }\n\n emit('update:modelValue', option.value)\n emit('change', option.value, option)\n}\n\nfunction getNextEnabledIndex(startIndex: number, direction: 1 | -1): number {\n if (props.options.length === 0) {\n return -1\n }\n\n let cursor = startIndex\n for (let step = 0; step < props.options.length; step += 1) {\n cursor = (cursor + direction + props.options.length) % props.options.length\n const option = props.options[cursor]\n if (option && !resolveOptionDisabled(option)) {\n return cursor\n }\n }\n\n return -1\n}\n\nfunction focusIndex(index: number): void {\n const option = props.options[index]\n if (!option) {\n return\n }\n\n itemRefs.value.get(getOptionKey(option.value))?.focus()\n}\n\nfunction onKeydown(event: KeyboardEvent, index: number): void {\n if (props.disabled) {\n return\n }\n\n if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, 1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, -1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'Home') {\n event.preventDefault()\n const firstOption = enabledOptions.value[0]\n if (!firstOption) {\n return\n }\n\n emitValue(firstOption)\n focusIndex(props.options.findIndex(option => option.value === firstOption.value))\n return\n }\n\n if (event.key === 'End') {\n event.preventDefault()\n const lastOption = enabledOptions.value.at(-1)\n if (!lastOption) {\n return\n }\n\n emitValue(lastOption)\n focusIndex(props.options.findIndex(option => option.value === lastOption.value))\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n const option = props.options[index]\n if (option) {\n emitValue(option)\n }\n }\n}\n\nwatch(() => props.modelValue, () => scheduleMeasure())\nwatch(() => props.options, () => scheduleMeasure(), { deep: true })\nwatch(() => props.variant, () => scheduleMeasure())\nwatch(() => props.size, () => scheduleMeasure())\nwatch(() => props.block, () => scheduleMeasure())\n\nonMounted(() => scheduleMeasure())\nonBeforeUnmount(() => {\n resizeObserver?.disconnect()\n observedRoot = null\n observedItem = null\n})\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n data-ds-segmented\n :data-variant=\"variant\"\n role=\"radiogroup\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClassName\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"hasIndicator\"\n data-ds-segmented-indicator\n aria-hidden=\"true\"\n :class=\"indicatorClassName\"\n :style=\"indicatorStyle\"\n />\n\n <button\n v-for=\"(option, index) in options\"\n :key=\"option.value\"\n :ref=\"element => setItemRef(option.value, element)\"\n data-ds-segmented-item\n :data-value=\"String(option.value)\"\n type=\"button\"\n role=\"radio\"\n :aria-checked=\"isOptionSelected(option) ? 'true' : 'false'\"\n :aria-disabled=\"resolveOptionDisabled(option) ? 'true' : undefined\"\n :disabled=\"resolveOptionDisabled(option)\"\n :tabindex=\"isFocusableOption(option, index) ? 0 : -1\"\n :class=\"grSegmentedItemClass({\n variant,\n selected: isOptionSelected(option),\n disabled: resolveOptionDisabled(option),\n iconOnly: isIconOnlyOption(option),\n })\"\n @click=\"emitValue(option)\"\n @keydown=\"onKeydown($event, index)\"\n >\n <input\n type=\"radio\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :name=\"resolvedName\"\n :value=\"option.value\"\n :checked=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot\n :option=\"option\"\n :selected=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n >\n <component\n :is=\"option.icon\"\n v-if=\"option.icon\"\n aria-hidden=\"true\"\n :class=\"grSegmentedItemIconClass\"\n />\n <span v-if=\"option.label\" :class=\"grSegmentedItemLabelClass\">\n {{ option.label }}\n </span>\n </slot>\n </button>\n </div>\n</template>","<script setup lang=\"ts\">\nimport { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport type { ComponentPublicInstance } from 'vue'\n\nimport {\n grSegmentedIndicatorClass,\n grSegmentedItemClass,\n grSegmentedItemIconClass,\n grSegmentedItemLabelClass,\n grSegmentedRootClass,\n grSegmentedRootStyle,\n type GrSegmentedOption,\n type GrSegmentedSize,\n type GrSegmentedValue,\n type GrSegmentedVariant,\n} from './grSegmentedStyles'\n\nconst hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\ntype IndicatorGeometry = {\n width: number\n height: number\n x: number\n y: number\n}\n\n/**\n * Пропсы публичного DS-примитива «Segmented».\n */\nexport interface GrSegmentedProps {\n modelValue: GrSegmentedValue\n options: GrSegmentedOption[]\n variant?: GrSegmentedVariant\n size?: GrSegmentedSize\n /** Длительность анимации индикатора в мс. */\n indicatorDuration?: number\n /** Растягивать сегмент на всю ширину контейнера. */\n block?: boolean\n disabled?: boolean\n /** Имя скрытых radio-inputs для интеграции с нативной формой. */\n name?: string\n ariaLabel?: string\n}\n\nconst props = withDefaults(\n defineProps<GrSegmentedProps>(),\n {\n variant: 'pills',\n size: 'md',\n indicatorDuration: 300,\n block: false,\n disabled: false,\n name: undefined,\n ariaLabel: undefined,\n },\n)\n\nconst emit = defineEmits<{\n (event: 'update:modelValue', value: GrSegmentedValue): void\n (event: 'change', value: GrSegmentedValue, option: GrSegmentedOption): void\n}>()\n\nconst instance = getCurrentInstance()\nconst fallbackName = `ds-segmented-${instance?.uid ?? Math.random()}`\n\nconst rootRef = ref<HTMLElement | null>(null)\nconst itemRefs = ref(new Map<string, HTMLElement>())\nconst indicatorGeometry = ref<IndicatorGeometry | null>(null)\nconst indicatorReady = ref(false)\n\nlet resizeObserver: ResizeObserver | null = null\nlet observedRoot: HTMLElement | null = null\nlet observedItem: HTMLElement | null = null\nlet scheduled = false\n\nconst selectedIndex = computed(() => props.options.findIndex(option => option.value === props.modelValue))\nconst selectedOption = computed(() => props.options[selectedIndex.value] ?? null)\nconst enabledOptions = computed(() => props.options.filter(option => !resolveOptionDisabled(option)))\nconst indicatorDuration = computed(() => Math.max(0, Math.round(props.indicatorDuration)))\nconst rootClassName = computed(() => grSegmentedRootClass({\n variant: props.variant,\n block: props.block,\n disabled: props.disabled,\n}))\nconst rootStyle = computed<Record<string, string>>(() => ({\n ...grSegmentedRootStyle({\n variant: props.variant,\n size: props.size,\n }),\n gridTemplateColumns: props.options.length > 0\n ? props.options.map(() => props.block ? 'minmax(0,1fr)' : 'minmax(0,max-content)').join(' ')\n : 'none',\n}))\nconst indicatorClassName = computed(() => grSegmentedIndicatorClass(props.variant))\nconst resolvedName = computed(() => props.name ?? fallbackName)\nconst hasIndicator = computed(() => selectedIndex.value !== -1 && indicatorGeometry.value !== null)\n\nconst indicatorStyle = computed<Record<string, string>>(() => {\n const geometry = indicatorGeometry.value\n if (!geometry) {\n return {\n opacity: '0',\n width: '0px',\n height: '0px',\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: 'translate3d(0px, 0px, 0px)',\n }\n }\n\n return {\n opacity: indicatorReady.value ? '1' : '0',\n width: `${geometry.width}px`,\n height: `${geometry.height}px`,\n transitionDuration: `${indicatorDuration.value}ms`,\n transform: `translate3d(${geometry.x}px, ${geometry.y}px, 0)`,\n }\n})\n\nfunction getOptionKey(value: GrSegmentedValue): string {\n return String(value)\n}\n\nfunction resolveOptionDisabled(option: GrSegmentedOption): boolean {\n return props.disabled || Boolean(option.disabled)\n}\n\nfunction isOptionSelected(option: GrSegmentedOption): boolean {\n return option.value === props.modelValue\n}\n\nfunction isIconOnlyOption(option: GrSegmentedOption): boolean {\n return Boolean(option.icon) && !option.label\n}\n\nfunction isFocusableOption(option: GrSegmentedOption, index: number): boolean {\n if (resolveOptionDisabled(option)) {\n return false\n }\n\n if (isOptionSelected(option)) {\n return true\n }\n\n if (selectedIndex.value !== -1) {\n return false\n }\n\n return enabledOptions.value[0]?.value === props.options[index]?.value\n}\n\nfunction setItemRef(value: GrSegmentedValue, element: Element | ComponentPublicInstance | null): void {\n const key = getOptionKey(value)\n\n if (!(element instanceof HTMLElement)) {\n itemRefs.value.delete(key)\n return\n }\n\n itemRefs.value.set(key, element)\n}\n\nfunction isSameGeometry(left: IndicatorGeometry | null, right: IndicatorGeometry | null): boolean {\n if (left === right) {\n return true\n }\n\n if (!left || !right) {\n return false\n }\n\n return left.width === right.width\n && left.height === right.height\n && left.x === right.x\n && left.y === right.y\n}\n\nfunction measureIndicator(): void {\n const root = rootRef.value\n const option = selectedOption.value\n if (!root || !option) {\n if (indicatorGeometry.value !== null)\n indicatorGeometry.value = null\n\n if (indicatorReady.value)\n indicatorReady.value = false\n\n return\n }\n\n const selectedItem = itemRefs.value.get(getOptionKey(option.value))\n if (!selectedItem) {\n return\n }\n\n const rootRect = root.getBoundingClientRect()\n const itemRect = selectedItem.getBoundingClientRect()\n\n const nextGeometry = {\n width: Math.max(Math.round(itemRect.width), 0),\n height: Math.max(Math.round(itemRect.height), 0),\n x: Math.round(itemRect.left - rootRect.left),\n y: Math.max(Math.round(itemRect.top - rootRect.top) - 1, 0),\n } satisfies IndicatorGeometry\n\n if (!isSameGeometry(indicatorGeometry.value, nextGeometry)) {\n indicatorGeometry.value = nextGeometry\n }\n\n const nextReady = nextGeometry.width > 0 && nextGeometry.height > 0\n if (indicatorReady.value !== nextReady) {\n indicatorReady.value = nextReady\n }\n}\n\nfunction refreshObserver(): void {\n if (typeof ResizeObserver === 'undefined') {\n return\n }\n\n const root = rootRef.value\n const option = selectedOption.value\n const selectedItem = option\n ? itemRefs.value.get(getOptionKey(option.value)) ?? null\n : null\n\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => scheduleMeasure())\n }\n\n if (!root) {\n resizeObserver.disconnect()\n observedRoot = null\n observedItem = null\n return\n }\n\n if (observedRoot === root && observedItem === selectedItem) {\n return\n }\n\n resizeObserver.disconnect()\n resizeObserver.observe(root)\n\n if (selectedItem) {\n resizeObserver.observe(selectedItem)\n }\n\n observedRoot = root\n observedItem = selectedItem\n}\n\nfunction scheduleMeasure(): void {\n if (scheduled) {\n return\n }\n\n scheduled = true\n void nextTick(() => {\n scheduled = false\n measureIndicator()\n refreshObserver()\n })\n}\n\nfunction emitValue(option: GrSegmentedOption): void {\n if (resolveOptionDisabled(option) || option.value === props.modelValue) {\n return\n }\n\n emit('update:modelValue', option.value)\n emit('change', option.value, option)\n}\n\nfunction getNextEnabledIndex(startIndex: number, direction: 1 | -1): number {\n if (props.options.length === 0) {\n return -1\n }\n\n let cursor = startIndex\n for (let step = 0; step < props.options.length; step += 1) {\n cursor = (cursor + direction + props.options.length) % props.options.length\n const option = props.options[cursor]\n if (option && !resolveOptionDisabled(option)) {\n return cursor\n }\n }\n\n return -1\n}\n\nfunction focusIndex(index: number): void {\n const option = props.options[index]\n if (!option) {\n return\n }\n\n itemRefs.value.get(getOptionKey(option.value))?.focus()\n}\n\nfunction onKeydown(event: KeyboardEvent, index: number): void {\n if (props.disabled) {\n return\n }\n\n if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, 1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {\n event.preventDefault()\n const nextIndex = getNextEnabledIndex(index, -1)\n if (nextIndex === -1) {\n return\n }\n\n const option = props.options[nextIndex]\n if (option) {\n emitValue(option)\n focusIndex(nextIndex)\n }\n return\n }\n\n if (event.key === 'Home') {\n event.preventDefault()\n const firstOption = enabledOptions.value[0]\n if (!firstOption) {\n return\n }\n\n emitValue(firstOption)\n focusIndex(props.options.findIndex(option => option.value === firstOption.value))\n return\n }\n\n if (event.key === 'End') {\n event.preventDefault()\n const lastOption = enabledOptions.value.at(-1)\n if (!lastOption) {\n return\n }\n\n emitValue(lastOption)\n focusIndex(props.options.findIndex(option => option.value === lastOption.value))\n return\n }\n\n if (event.key === ' ' || event.key === 'Enter') {\n event.preventDefault()\n const option = props.options[index]\n if (option) {\n emitValue(option)\n }\n }\n}\n\nwatch(() => props.modelValue, () => scheduleMeasure())\nwatch(() => props.options, () => scheduleMeasure(), { deep: true })\nwatch(() => props.variant, () => scheduleMeasure())\nwatch(() => props.size, () => scheduleMeasure())\nwatch(() => props.block, () => scheduleMeasure())\n\nonMounted(() => scheduleMeasure())\nonBeforeUnmount(() => {\n resizeObserver?.disconnect()\n observedRoot = null\n observedItem = null\n})\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n data-ds-segmented\n :data-variant=\"variant\"\n role=\"radiogroup\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClassName\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"hasIndicator\"\n data-ds-segmented-indicator\n aria-hidden=\"true\"\n :class=\"indicatorClassName\"\n :style=\"indicatorStyle\"\n />\n\n <button\n v-for=\"(option, index) in options\"\n :key=\"option.value\"\n :ref=\"element => setItemRef(option.value, element)\"\n data-ds-segmented-item\n :data-value=\"String(option.value)\"\n type=\"button\"\n role=\"radio\"\n :aria-checked=\"isOptionSelected(option) ? 'true' : 'false'\"\n :aria-disabled=\"resolveOptionDisabled(option) ? 'true' : undefined\"\n :disabled=\"resolveOptionDisabled(option)\"\n :tabindex=\"isFocusableOption(option, index) ? 0 : -1\"\n :class=\"grSegmentedItemClass({\n variant,\n selected: isOptionSelected(option),\n disabled: resolveOptionDisabled(option),\n iconOnly: isIconOnlyOption(option),\n })\"\n @click=\"emitValue(option)\"\n @keydown=\"onKeydown($event, index)\"\n >\n <input\n type=\"radio\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :name=\"resolvedName\"\n :value=\"option.value\"\n :checked=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n :style=\"hiddenInputStyle\"\n >\n\n <slot\n :option=\"option\"\n :selected=\"isOptionSelected(option)\"\n :disabled=\"resolveOptionDisabled(option)\"\n >\n <component\n :is=\"option.icon\"\n v-if=\"option.icon\"\n aria-hidden=\"true\"\n :class=\"grSegmentedItemIconClass\"\n />\n <span v-if=\"option.label\" :class=\"grSegmentedItemLabelClass\">\n {{ option.label }}\n </span>\n </slot>\n </button>\n </div>\n</template>"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as grSegmentedSafelist, t as grSegmentedConfig } from "../../chunks/config-
|
|
2
|
-
import { t as GrSegmented_default } from "./chunks/GrSegmented-
|
|
1
|
+
import { n as grSegmentedSafelist, t as grSegmentedConfig } from "../../chunks/config-BhvNm4Pp.js";
|
|
2
|
+
import { t as GrSegmented_default } from "./chunks/GrSegmented-BPl1koHc.js";
|
|
3
3
|
export { GrSegmented_default as GrSegmented, GrSegmented_default as default, grSegmentedConfig, grSegmentedSafelist };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { vClickOutside } from "../../../directives/clickOutside.js";
|
|
2
|
-
import { t as GrInput_default } from "../../GrInput/chunks/GrInput-
|
|
3
|
-
import { a as grSelectPanelClasses, i as grSelectNativeClass, n as grSelectLinkNativeLabelClass, o as grSelectTriggerClass, r as grSelectLinkNativeOverlayClass, s as linkBaseClass, t as defaultBaseClass } from "../../../chunks/grSelectStyles-
|
|
2
|
+
import { t as GrInput_default } from "../../GrInput/chunks/GrInput-CfO2RsM-.js";
|
|
3
|
+
import { a as grSelectPanelClasses, i as grSelectNativeClass, n as grSelectLinkNativeLabelClass, o as grSelectTriggerClass, r as grSelectLinkNativeOverlayClass, s as linkBaseClass, t as defaultBaseClass } from "../../../chunks/grSelectStyles-DTAYNzxn.js";
|
|
4
4
|
import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onUnmounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
5
5
|
//#region src/components/GrSelect/GrSelect.vue?vue&type=script&setup=true&lang.ts
|
|
6
6
|
var _hoisted_1 = [
|