@feugene/granularity 0.31.0 → 0.32.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/README.md +0 -1
- package/dist/chunks/adapter-CAOxmn2G.js.map +1 -1
- package/dist/chunks/{config-BHcS5Cwm.js → config-87fszqnD.js} +1 -1
- package/dist/chunks/{config-BHcS5Cwm.js.map → config-87fszqnD.js.map} +1 -1
- package/dist/chunks/config-A-bBiotF.js.map +1 -1
- package/dist/chunks/config-B3J0alyY.js.map +1 -1
- package/dist/chunks/config-BhfNgyWL.js.map +1 -1
- package/dist/chunks/config-Bjn30smH.js.map +1 -1
- package/dist/chunks/config-BqT6PMzO.js.map +1 -1
- package/dist/chunks/config-C0Ea9ePP.js.map +1 -1
- package/dist/chunks/config-C0Eu8jpG.js.map +1 -1
- package/dist/chunks/config-CDat1wXf.js.map +1 -1
- package/dist/chunks/config-CQLNjc9X2.js.map +1 -1
- package/dist/chunks/config-CbEbLyDE.js.map +1 -1
- package/dist/chunks/{config-jyr6AIZt2.js → config-CuQmUkMw2.js} +2 -2
- package/dist/chunks/{config-jyr6AIZt2.js.map → config-CuQmUkMw2.js.map} +1 -1
- package/dist/chunks/config-DeyT9dJl.js.map +1 -1
- package/dist/chunks/config-DnF472Ox.js.map +1 -1
- package/dist/chunks/config-DwABJHEo.js.map +1 -1
- package/dist/chunks/{config-tiUtEn4Q.js → config-E1cTyRVV.js} +1 -1
- package/dist/chunks/{config-tiUtEn4Q.js.map → config-E1cTyRVV.js.map} +1 -1
- package/dist/chunks/config-MmPym-Z72.js.map +1 -1
- package/dist/chunks/config-T3-DMXYm.js.map +1 -1
- package/dist/chunks/config-Yy67uWHY.js.map +1 -1
- package/dist/chunks/config-_jbgsFpw.js.map +1 -1
- package/dist/chunks/config-g8-JGZ_Y.js.map +1 -1
- package/dist/chunks/config-mlheIMtV.js.map +1 -1
- package/dist/chunks/config-rLkc9Zn2.js.map +1 -1
- package/dist/chunks/config-uzUuosv7.js.map +1 -1
- package/dist/chunks/context-CTbuwcYs.js.map +1 -1
- package/dist/chunks/deltaTone-B5OoS1vo.js.map +1 -1
- package/dist/chunks/es-Do2CNrC2.js.map +1 -1
- package/dist/chunks/fileValidation-D5TFBhbv.js.map +1 -1
- package/dist/chunks/focusables-BkzK42SQ.js.map +1 -1
- package/dist/chunks/{generated-DJ2dJ__C.js → generated-CSyPsWtM.js} +1 -1
- package/dist/chunks/{generated-DJ2dJ__C.js.map → generated-CSyPsWtM.js.map} +1 -1
- package/dist/chunks/grBadgeStyles-D8Mz73B5.js.map +1 -1
- package/dist/chunks/{grButtonStyles-B_-YRE__.js → grButtonStyles-B3wRWW_i.js} +4 -4
- package/dist/chunks/grButtonStyles-B3wRWW_i.js.map +1 -0
- package/dist/chunks/grLinkStyles-FME_qMpi.js.map +1 -1
- package/dist/chunks/grLoadingStyles-CnQaf5ry.js.map +1 -1
- package/dist/chunks/{grRadioStyles-D4gnU65n.js → grRadioStyles-DGL2QLy6.js} +1 -1
- package/dist/chunks/{grRadioStyles-D4gnU65n.js.map → grRadioStyles-DGL2QLy6.js.map} +1 -1
- package/dist/chunks/grSelectStyles-Cdtd10eY.js.map +1 -1
- package/dist/chunks/{grSliderStyles-B5uNxNJq.js → grSliderStyles-kaz6VXZ3.js} +9 -1
- package/dist/chunks/grSliderStyles-kaz6VXZ3.js.map +1 -0
- package/dist/chunks/{granular-provider-yJNX1g1G.js → granular-provider-Da2CJO6j.js} +3 -3
- package/dist/chunks/{granular-provider-yJNX1g1G.js.map → granular-provider-Da2CJO6j.js.map} +1 -1
- package/dist/chunks/granularityI18n-BC5zsj_d.js.map +1 -1
- package/dist/chunks/icon-Dag2tIMs.js.map +1 -1
- package/dist/chunks/inert-DIHCCn_1.js.map +1 -1
- package/dist/chunks/keyboard-DE2yhz_b.js.map +1 -1
- package/dist/chunks/numericStep-Bq2lj4ew.js.map +1 -1
- package/dist/chunks/optionFilter-DYw9XPPx.js.map +1 -1
- package/dist/chunks/{overlayStack-C8cfsqXa.js → overlayStack-0CZS99Da.js} +40 -6
- package/dist/chunks/overlayStack-0CZS99Da.js.map +1 -0
- package/dist/chunks/portalRoot-CVhCgdG6.js.map +1 -1
- package/dist/chunks/renamedProp-BwcN-SJg.js.map +1 -1
- package/dist/chunks/{safelist-BOq5Li7p.js → safelist-DxkMj5IW.js} +1 -1
- package/dist/chunks/{safelist-BOq5Li7p.js.map → safelist-DxkMj5IW.js.map} +1 -1
- package/dist/chunks/slotNodes-DxNXpC7v.js.map +1 -1
- package/dist/chunks/useControlAddons-asUr10Pf.js.map +1 -1
- package/dist/chunks/useControlledOpen-DV3SqLTP.js.map +1 -1
- package/dist/chunks/useDragSort-0l47h4yb.js.map +1 -1
- package/dist/chunks/useFilePreviews-DnwgdyBs.js.map +1 -1
- package/dist/chunks/useFocusWithin-BwHE0rzm.js.map +1 -1
- package/dist/chunks/{useModalOverlay-Cv5hF63W.js → useModalOverlay-D__CqLGn.js} +3 -0
- package/dist/chunks/useModalOverlay-D__CqLGn.js.map +1 -0
- package/dist/chunks/usePortalTarget-C0p-mhaM.js.map +1 -1
- package/dist/chunks/validation-5HhpanPP.js.map +1 -1
- package/dist/components/GrAlert/chunks/GrAlert-FAVf-ksH.js.map +1 -1
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-X6RlmiJQ.js → GrAutocomplete-rYEY15UI.js} +1 -1
- package/dist/components/GrAutocomplete/chunks/GrAutocomplete-rYEY15UI.js.map +1 -0
- package/dist/components/GrAutocomplete/index.js +1 -1
- package/dist/components/GrAutocomplete/styles.css +1 -1
- package/dist/components/GrAvatar/chunks/GrAvatar-CNmLmgcr.js.map +1 -1
- package/dist/components/GrBadge/chunks/{GrBadge-BsoocpF-.js → GrBadge-D2MfThPz.js} +1 -1
- package/dist/components/GrBadge/chunks/GrBadge-D2MfThPz.js.map +1 -0
- package/dist/components/GrBadge/index.js +1 -1
- package/dist/components/GrBadge/styles.css +1 -1
- package/dist/components/GrBadgeWrap/chunks/GrBadgeWrap-B-A3PRkE.js.map +1 -1
- package/dist/components/GrBottomNav/chunks/GrBottomNav-wtFatLjB.js.map +1 -1
- package/dist/components/GrBreadcrumbs/chunks/GrBreadcrumbs-DRDNan_n.js.map +1 -1
- package/dist/components/GrButton/chunks/{GrButton-Bw2AH4uX.js → GrButton-7GP0zObj.js} +1 -1
- package/dist/components/GrButton/chunks/GrButton-7GP0zObj.js.map +1 -0
- package/dist/components/GrButton/index.js +3 -3
- package/dist/components/GrButtonGroup/chunks/GrButtonGroup-CKyiAV8K.js.map +1 -1
- package/dist/components/GrCard/chunks/GrCard-BttXz1pQ.js.map +1 -1
- package/dist/components/GrCheckbox/chunks/GrCheckbox-CEcHIsXM.js.map +1 -1
- package/dist/components/GrCheckboxGroup/chunks/GrCheckboxGroup-BOwrVcFr.js.map +1 -1
- package/dist/components/GrChip/chunks/GrChip-C0vU69tf.js.map +1 -1
- package/dist/components/GrChipGroup/chunks/GrChipGroup-C78Vcwos.js.map +1 -1
- package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-Dkvkr91t.js → GrCodeBlock-Dp0eEBTZ.js} +1 -1
- package/dist/components/GrCodeBlock/chunks/GrCodeBlock-Dp0eEBTZ.js.map +1 -0
- package/dist/components/GrCodeBlock/index.js +1 -1
- package/dist/components/GrCollapse/chunks/GrCollapse-BlW6ybdL.js.map +1 -1
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-C7ifyQ0R.js → GrColorPicker-p2XH_8cE.js} +2 -2
- package/dist/components/GrColorPicker/chunks/GrColorPicker-p2XH_8cE.js.map +1 -0
- package/dist/components/GrColorPicker/index.js +1 -1
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-C5abL2Y7.js → GrCommandPalette-BXbh3q7O.js} +2 -2
- package/dist/components/GrCommandPalette/chunks/GrCommandPalette-BXbh3q7O.js.map +1 -0
- package/dist/components/GrCommandPalette/index.js +1 -1
- package/dist/components/GrCommandPalette/styles.css +1 -1
- package/dist/components/GrConfigProvider/chunks/GrConfigProvider-BF7R3hgg.js.map +1 -1
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-B9mIU78E.js → GrConfirmDialog-CUP43q__.js} +3 -3
- package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-CUP43q__.js.map +1 -0
- package/dist/components/GrConfirmDialog/index.js +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-_FKwQvuQ.js → GrContextMenu-ClkVjdcP.js} +1 -1
- package/dist/components/GrContextMenu/chunks/GrContextMenu-ClkVjdcP.js.map +1 -0
- package/dist/components/GrContextMenu/index.js +1 -1
- package/dist/components/GrDataTable/chunks/{GrDataTable-C8a9_nCg.js → GrDataTable-CAGgRk27.js} +5 -3
- package/dist/components/GrDataTable/chunks/GrDataTable-CAGgRk27.js.map +1 -0
- package/dist/components/GrDataTable/index.js +1 -1
- package/dist/components/GrDelta/chunks/GrDelta-BZwkgQW-.js.map +1 -1
- package/dist/components/GrDescriptionList/chunks/GrDescriptionList-BMeCgFV3.js.map +1 -1
- package/dist/components/GrDialog/chunks/{GrDialog-bOUDYfmh.js → GrDialog-BiMJ9_T4.js} +2 -2
- package/dist/components/GrDialog/chunks/{GrDialog-bOUDYfmh.js.map → GrDialog-BiMJ9_T4.js.map} +1 -1
- package/dist/components/GrDialog/index.js +1 -1
- package/dist/components/GrDialogService/chunks/{GrDialogService-6s2cQ-_6.js → GrDialogService-BxNK6crD.js} +4 -4
- package/dist/components/GrDialogService/chunks/GrDialogService-BxNK6crD.js.map +1 -0
- package/dist/components/GrDialogService/index.js +1 -1
- package/dist/components/GrDivider/chunks/GrDivider-BXavGcMX.js.map +1 -1
- package/dist/components/GrDrawer/chunks/{GrDrawer-B7PiAcbU.js → GrDrawer-Ce2l3zaG.js} +6 -5
- package/dist/components/GrDrawer/chunks/GrDrawer-Ce2l3zaG.js.map +1 -0
- package/dist/components/GrDrawer/index.js +1 -1
- package/dist/components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js.map +1 -1
- package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-GOzuAXsi.js.map +1 -1
- package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-B33ZzwfB.js.map +1 -1
- package/dist/components/GrFilePreview/chunks/GrFilePreview-C9Z7hMK8.js.map +1 -1
- package/dist/components/GrFileUpload/chunks/GrFileUpload-NsHkRRIa.js.map +1 -1
- package/dist/components/GrForm/chunks/GrForm-CrnfCsgj.js.map +1 -1
- package/dist/components/GrFormField/chunks/GrFormField-DSylU7IU.js.map +1 -1
- package/dist/components/GrFormFile/chunks/{GrFormFile-CYtXU9HV.js → GrFormFile-B1jGZyIj.js} +2 -2
- package/dist/components/GrFormFile/chunks/GrFormFile-B1jGZyIj.js.map +1 -0
- package/dist/components/GrFormFile/index.js +1 -1
- package/dist/components/GrFormFile/styles.css +1 -1
- package/dist/components/GrIcon/chunks/GrIcon-Dmf0c9ba.js.map +1 -1
- package/dist/components/GrImageViewer/chunks/{GrImageViewer-CyVN6Zpc.js → GrImageViewer-CG4vUBg_.js} +4 -3
- package/dist/components/GrImageViewer/chunks/GrImageViewer-CG4vUBg_.js.map +1 -0
- package/dist/components/GrImageViewer/index.js +1 -1
- package/dist/components/GrInput/chunks/GrInput-BLywRZUN.js.map +1 -1
- package/dist/components/GrInputTag/chunks/GrInputTag-Cj4A9Xgs.js.map +1 -1
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-Cy2bknHO.js → GrJsonViewer-BCZ7lE2k.js} +2 -2
- package/dist/components/GrJsonViewer/chunks/GrJsonViewer-BCZ7lE2k.js.map +1 -0
- package/dist/components/GrJsonViewer/index.js +1 -1
- package/dist/components/GrKbd/chunks/GrKbd-D2ga1H9i.js.map +1 -1
- package/dist/components/GrLink/chunks/GrLink-DYXw3W9w.js.map +1 -1
- package/dist/components/GrList/chunks/{GrList-DmT4qzLO.js → GrList-B_CRJB4c.js} +1 -1
- package/dist/components/GrList/chunks/GrList-B_CRJB4c.js.map +1 -0
- package/dist/components/GrList/index.js +1 -1
- package/dist/components/GrList/styles.css +1 -1
- package/dist/components/GrModal/chunks/{GrModal-CCoWZuIl.js → GrModal-D0mf1SAx.js} +3 -2
- package/dist/components/GrModal/chunks/GrModal-D0mf1SAx.js.map +1 -0
- package/dist/components/GrModal/index.js +1 -1
- package/dist/components/GrNavbar/chunks/{GrNavbar-C5EjMKaC.js → GrNavbar-_rtHKwTf.js} +1 -1
- package/dist/components/GrNavbar/chunks/{GrNavbar-C5EjMKaC.js.map → GrNavbar-_rtHKwTf.js.map} +1 -1
- package/dist/components/GrNavbar/index.js +1 -1
- package/dist/components/GrNumberInput/chunks/GrNumberInput-DQ59YICu.js.map +1 -1
- package/dist/components/GrPagination/chunks/{GrPagination-Cw3R21dp.js → GrPagination-B_kAhoAV.js} +2 -2
- package/dist/components/GrPagination/chunks/{GrPagination-Cw3R21dp.js.map → GrPagination-B_kAhoAV.js.map} +1 -1
- package/dist/components/GrPagination/index.js +1 -1
- package/dist/components/GrPopover/chunks/{GrPopover-CofG-Tfe.js → GrPopover-faJanmGs.js} +1 -1
- package/dist/components/GrPopover/chunks/GrPopover-faJanmGs.js.map +1 -0
- package/dist/components/GrPopover/index.js +1 -1
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-DLcl1xiq.js → GrPromptDialog-C6QGC7QJ.js} +4 -4
- package/dist/components/GrPromptDialog/chunks/GrPromptDialog-C6QGC7QJ.js.map +1 -0
- package/dist/components/GrPromptDialog/index.js +1 -1
- package/dist/components/GrRadio/chunks/{GrRadio-C_rESc5g.js → GrRadio-Aq3v8XgG.js} +1 -1
- package/dist/components/GrRadio/chunks/GrRadio-Aq3v8XgG.js.map +1 -0
- package/dist/components/GrRadio/index.js +2 -2
- package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CdQO4G-U.js → GrRadioGroup-y9LVdTWh.js} +1 -1
- package/dist/components/GrRadioGroup/chunks/GrRadioGroup-y9LVdTWh.js.map +1 -0
- package/dist/components/GrRadioGroup/index.js +1 -1
- package/dist/components/GrRating/chunks/GrRating-IEiTOdnF.js.map +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-C_skObtv.js → GrResponseErrorBanner-CBVRpgIG.js} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-C_skObtv.js.map → GrResponseErrorBanner-CBVRpgIG.js.map} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DudGc9LO.js → GrResponseErrorBanner-DMeOWlzj.js} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-DMeOWlzj.js.map +1 -0
- package/dist/components/GrResponseErrorBanner/index.js +2 -2
- package/dist/components/GrSegmented/chunks/GrSegmented-CB-VR-yL.js.map +1 -1
- package/dist/components/GrSelect/chunks/{GrSelect-BiUrSSxc.js → GrSelect-gCeRFgQo.js} +1 -1
- package/dist/components/GrSelect/chunks/GrSelect-gCeRFgQo.js.map +1 -0
- package/dist/components/GrSelect/index.js +1 -1
- package/dist/components/GrSelect/styles.css +1 -1
- package/dist/components/GrSidebar/chunks/{GrSidebar-B8EQIlfW.js → GrSidebar-alkwBUzL.js} +1 -1
- package/dist/components/GrSidebar/chunks/GrSidebar-alkwBUzL.js.map +1 -0
- package/dist/components/GrSidebar/index.js +1 -1
- package/dist/components/GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js.map +1 -1
- package/dist/components/GrSlider/chunks/{GrSlider-DJfeEl4h.js → GrSlider-DTTrZTHK.js} +3 -3
- package/dist/components/GrSlider/chunks/GrSlider-DTTrZTHK.js.map +1 -0
- package/dist/components/GrSlider/index.js +2 -2
- package/dist/components/GrSortableList/chunks/GrSortableList-HyKX--rO.js.map +1 -1
- package/dist/components/GrSplitter/chunks/GrSplitter-MltjaADn.js.map +1 -1
- package/dist/components/GrStatistic/chunks/GrStatistic-qHVasK37.js.map +1 -1
- package/dist/components/GrSteps/chunks/GrSteps-C2jxpZoN.js.map +1 -1
- package/dist/components/GrSwitch/chunks/{GrSwitch-g_OOSkh7.js → GrSwitch-7Oe5QfQZ.js} +1 -1
- package/dist/components/GrSwitch/chunks/GrSwitch-7Oe5QfQZ.js.map +1 -0
- package/dist/components/GrSwitch/index.js +1 -1
- package/dist/components/GrTabPanels/chunks/GrTabPanels-BZQS8-JM.js.map +1 -1
- package/dist/components/GrTable/chunks/GrTable-Zcdz2St_.js.map +1 -1
- package/dist/components/GrTextarea/chunks/{GrTextarea-KREK75Bu.js → GrTextarea-DinXG12-.js} +10 -10
- package/dist/components/GrTextarea/chunks/GrTextarea-DinXG12-.js.map +1 -0
- package/dist/components/GrTextarea/index.js +1 -1
- package/dist/components/GrTimeline/chunks/GrTimeline-BiHpArsg.js.map +1 -1
- package/dist/components/GrToaster/chunks/{GrToaster-Dp7-4B8k.js → GrToaster-COXIBKzq.js} +2 -2
- package/dist/components/GrToaster/chunks/GrToaster-COXIBKzq.js.map +1 -0
- package/dist/components/GrToaster/index.js +1 -1
- package/dist/components/GrToaster/styles.css +1 -1
- package/dist/components/GrTooltip/chunks/GrTooltip-uYETdbCD.js.map +1 -1
- package/dist/components/GrTree/chunks/{GrTree-DC89I4AP.js → GrTree-Ci6CZfKR.js} +5 -5
- package/dist/components/GrTree/chunks/GrTree-Ci6CZfKR.js.map +1 -0
- package/dist/components/GrTree/index.js +1 -1
- package/dist/components/GrTree/styles.css +1 -1
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-iJnMl2t9.js → GrTreeSelect-BHwgGJcT.js} +1 -1
- package/dist/components/GrTreeSelect/chunks/GrTreeSelect-BHwgGJcT.js.map +1 -0
- package/dist/components/GrTreeSelect/index.js +1 -1
- package/dist/composables/useAnnouncer.js.map +1 -1
- package/dist/composables/useComboboxNavigation.js.map +1 -1
- package/dist/composables/useDragGesture.js.map +1 -1
- package/dist/composables/useFloating.js +2 -22
- package/dist/composables/useFloating.js.map +1 -1
- package/dist/composables/useFocusTrap.js.map +1 -1
- package/dist/composables/useOverlayLayer.js +10 -3
- package/dist/composables/useOverlayLayer.js.map +1 -1
- package/dist/composables/useRovingFocus.js.map +1 -1
- package/dist/composables/useTheme.js.map +1 -1
- package/dist/composables/useToast.js.map +1 -1
- package/dist/composables/useVirtualList.js.map +1 -1
- package/dist/directives/autofocus.js.map +1 -1
- package/dist/directives/autosize.js.map +1 -1
- package/dist/directives/clickOutside.js.map +1 -1
- package/dist/directives/dropzone.js.map +1 -1
- package/dist/directives/hotkey.js.map +1 -1
- package/dist/directives/loading.js.map +1 -1
- package/dist/granular-provider-node.js +1 -1
- package/dist/granular-provider.js +1 -1
- package/dist/index.js +37 -37
- package/dist/testing.js +2 -2
- package/dist/testing.js.map +1 -1
- package/dist/theme-apply.js.map +1 -1
- package/dist/theme.js +1 -1
- package/dist/theme.js.map +1 -1
- package/dist/tokens.js +1 -1
- package/dist/types/components/GrCodeBlock/tokenizeJson.d.ts +1 -3
- package/dist/types/components/GrImageViewer/GrImageViewer.vue.d.ts +1 -1
- package/dist/types/components/GrInput/GrInput.vue.d.ts +24 -24
- package/dist/types/components/GrSlider/grSliderStyles.d.ts +9 -1
- package/dist/types/components/GrTabPanels/GrTabPanel.vue.d.ts +3 -3
- package/dist/types/composables/internal/overlayStack.d.ts +30 -0
- package/dist/types/composables/internal/useModalOverlay.d.ts +14 -0
- package/dist/types/composables/useOverlayLayer.d.ts +8 -0
- package/dist/vue/index.js.map +1 -1
- package/dist/web-types.json +1 -1
- package/package.json +3 -3
- package/dist/chunks/grButtonStyles-B_-YRE__.js.map +0 -1
- package/dist/chunks/grSliderStyles-B5uNxNJq.js.map +0 -1
- package/dist/chunks/overlayStack-C8cfsqXa.js.map +0 -1
- package/dist/chunks/useModalOverlay-Cv5hF63W.js.map +0 -1
- package/dist/components/GrAutocomplete/chunks/GrAutocomplete-X6RlmiJQ.js.map +0 -1
- package/dist/components/GrBadge/chunks/GrBadge-BsoocpF-.js.map +0 -1
- package/dist/components/GrButton/chunks/GrButton-Bw2AH4uX.js.map +0 -1
- package/dist/components/GrCodeBlock/chunks/GrCodeBlock-Dkvkr91t.js.map +0 -1
- package/dist/components/GrColorPicker/chunks/GrColorPicker-C7ifyQ0R.js.map +0 -1
- package/dist/components/GrCommandPalette/chunks/GrCommandPalette-C5abL2Y7.js.map +0 -1
- package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-B9mIU78E.js.map +0 -1
- package/dist/components/GrContextMenu/chunks/GrContextMenu-_FKwQvuQ.js.map +0 -1
- package/dist/components/GrDataTable/chunks/GrDataTable-C8a9_nCg.js.map +0 -1
- package/dist/components/GrDialogService/chunks/GrDialogService-6s2cQ-_6.js.map +0 -1
- package/dist/components/GrDrawer/chunks/GrDrawer-B7PiAcbU.js.map +0 -1
- package/dist/components/GrFormFile/chunks/GrFormFile-CYtXU9HV.js.map +0 -1
- package/dist/components/GrImageViewer/chunks/GrImageViewer-CyVN6Zpc.js.map +0 -1
- package/dist/components/GrJsonViewer/chunks/GrJsonViewer-Cy2bknHO.js.map +0 -1
- package/dist/components/GrList/chunks/GrList-DmT4qzLO.js.map +0 -1
- package/dist/components/GrModal/chunks/GrModal-CCoWZuIl.js.map +0 -1
- package/dist/components/GrPopover/chunks/GrPopover-CofG-Tfe.js.map +0 -1
- package/dist/components/GrPromptDialog/chunks/GrPromptDialog-DLcl1xiq.js.map +0 -1
- package/dist/components/GrRadio/chunks/GrRadio-C_rESc5g.js.map +0 -1
- package/dist/components/GrRadioGroup/chunks/GrRadioGroup-CdQO4G-U.js.map +0 -1
- package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-DudGc9LO.js.map +0 -1
- package/dist/components/GrSelect/chunks/GrSelect-BiUrSSxc.js.map +0 -1
- package/dist/components/GrSidebar/chunks/GrSidebar-B8EQIlfW.js.map +0 -1
- package/dist/components/GrSlider/chunks/GrSlider-DJfeEl4h.js.map +0 -1
- package/dist/components/GrSwitch/chunks/GrSwitch-g_OOSkh7.js.map +0 -1
- package/dist/components/GrTextarea/chunks/GrTextarea-KREK75Bu.js.map +0 -1
- package/dist/components/GrToaster/chunks/GrToaster-Dp7-4B8k.js.map +0 -1
- package/dist/components/GrTree/chunks/GrTree-DC89I4AP.js.map +0 -1
- package/dist/components/GrTreeSelect/chunks/GrTreeSelect-iJnMl2t9.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-Yy67uWHY.js","names":[],"sources":["../../src/components/GrSwitch/grSwitchStyles.ts","../../src/components/GrSwitch/safelist.ts","../../src/components/GrSwitch/config.ts"],"sourcesContent":["import type { GrComponentSize } from '../shared/sizes'\n\nexport type GrSwitchSize = GrComponentSize\n\n/** Сторона подписи относительно дорожки — логическая, не физическая (RTL). */\nexport const GR_SWITCH_LABEL_POSITIONS = ['start', 'end'] as const\nexport type GrSwitchLabelPosition = typeof GR_SWITCH_LABEL_POSITIONS[number]\n\ntype GrSwitchThumbClassOptions = {\n
|
|
1
|
+
{"version":3,"file":"config-Yy67uWHY.js","names":[],"sources":["../../src/components/GrSwitch/grSwitchStyles.ts","../../src/components/GrSwitch/safelist.ts","../../src/components/GrSwitch/config.ts"],"sourcesContent":["import type { GrComponentSize } from '../shared/sizes'\n\nexport type GrSwitchSize = GrComponentSize\n\n/** Сторона подписи относительно дорожки — логическая, не физическая (RTL). */\nexport const GR_SWITCH_LABEL_POSITIONS = ['start', 'end'] as const\nexport type GrSwitchLabelPosition = typeof GR_SWITCH_LABEL_POSITIONS[number]\n\ntype GrSwitchThumbClassOptions = {\n checked: boolean\n size: GrSwitchSize\n}\n\nexport const rootBase = 'inline-flex items-center gap-2 select-none disabled:cursor-not-allowed'\n\n/** `start` разворачивает ряд, а не меняет порядок узлов: DOM-порядок читает диктор. */\nexport const rootLabelPositions: Record<GrSwitchLabelPosition, string> = {\n start: 'flex-row-reverse',\n end: '',\n}\n\nexport const trackBase\n = 'relative inline-flex shrink-0 items-center rounded-[var(--gr-radius-full)] border border-[var(--gr-switch-track-brd)] transition-colors duration-[var(--gr-duration-fast)]'\n\nexport const trackSizes: Record<GrSwitchSize, string> = {\n xs: 'h-4 w-7',\n sm: 'h-5 w-9',\n md: 'h-6 w-11',\n lg: 'h-7 w-14',\n}\n\nexport const thumbBase\n = 'inline-flex shrink-0 items-center justify-center rounded-[var(--gr-radius-full)] bg-[var(--gr-card)] shadow-[var(--gr-shadow-1)] transition-transform duration-[var(--gr-duration-fast)]'\n\nexport const thumbSizes: Record<GrSwitchSize, string> = {\n xs: 'h-3 w-3',\n sm: 'h-4 w-4',\n md: 'h-5 w-5',\n lg: 'h-6 w-6',\n}\n\n/** Спиннер загрузки живёт в бегунке, поэтому мельче его на ступень. */\nexport const thumbSpinnerSizes: Record<GrSwitchSize, string> = {\n xs: 'h-2 w-2',\n sm: 'h-2.5 w-2.5',\n md: 'h-3 w-3',\n lg: 'h-4 w-4',\n}\n\nexport const thumbSpinnerBase = 'animate-spin text-[var(--gr-muted-fg)]'\n\n/**\n * Сдвиг бегунка по горизонтали.\n *\n * Бегунок — обычный флекс-ребёнок дорожки, поэтому сдвиг отсчитывается от её\n * **content-box**, а он на 2px уже внешнего размера: рамка по 1px с каждой\n * стороны. Отсюда и весь расчёт.\n *\n * Зазор по вертикали задан геометрией и равен 1px на всех ступенях\n * (`(content-height − thumb) / 2`, дорожка центрирует бегунок сама). Значит и по\n * горизонтали он обязан быть 1px: иначе бегунок в покое выглядит вдавленным\n * внутрь, а в крайнем положении прижатым к краю — именно так и было, зазоры\n * расходились на 1–2px у `xs`, `sm` и `lg`.\n *\n * | ступень | дорожка | content | бегунок | покой | крайнее |\n * | --- | --- | --- | --- | --- | --- |\n * | `xs` | 28 | 26 | 12 | 1 | 13 |\n * | `sm` | 36 | 34 | 16 | 1 | 17 |\n * | `md` | 44 | 42 | 20 | 1 | 21 |\n * | `lg` | 56 | 54 | 24 | 1 | 29 |\n *\n * Крайнее положение — `content − thumb − зазор`. Гейт на эту арифметику живёт в\n * `__tests__/GrSwitch.test.ts`: он считает её заново из `trackSizes`/`thumbSizes`,\n * поэтому смена любой ступени размера сразу покажет разъехавшийся зазор.\n */\nexport const thumbTranslations: Record<GrSwitchSize, { checked: string, unchecked: string }> = {\n xs: {\n checked: 'translate-x-[13px]',\n unchecked: 'translate-x-[1px]',\n },\n sm: {\n checked: 'translate-x-[17px]',\n unchecked: 'translate-x-[1px]',\n },\n md: {\n checked: 'translate-x-[21px]',\n unchecked: 'translate-x-[1px]',\n },\n lg: {\n checked: 'translate-x-[29px]',\n unchecked: 'translate-x-[1px]',\n },\n}\n\nexport const labelBase = 'text-[var(--gr-muted-fg)]'\n\n/**\n * Недоступность гасится токеном, а не `opacity`: прозрачность разбавляет\n * выверенные на AA токены текста и роняет контраст подписи.\n */\nexport const labelDisabledClass = 'text-[var(--gr-disabled-fg)]'\n\nexport const labelSizes: Record<GrSwitchSize, string> = {\n xs: 'text-[length:var(--gr-text-xs)] leading-[var(--gr-leading-xs)]',\n sm: 'text-[length:var(--gr-text-sm)] leading-[var(--gr-leading-sm)]',\n md: 'text-[length:var(--gr-text-sm)] leading-[var(--gr-leading-sm)]',\n lg: 'text-[length:var(--gr-text-base)] leading-[var(--gr-leading-base)]',\n}\n\nexport function grSwitchRootClass(labelPosition: GrSwitchLabelPosition): string {\n return [rootBase, rootLabelPositions[labelPosition]].filter(Boolean).join(' ')\n}\n\nexport function grSwitchTrackClass(size: GrSwitchSize): string {\n return [trackBase, trackSizes[size]].join(' ')\n}\n\nexport function grSwitchThumbClass(options: GrSwitchThumbClassOptions): string {\n return [\n thumbBase,\n thumbSizes[options.size],\n thumbTranslations[options.size][options.checked ? 'checked' : 'unchecked'],\n ].join(' ')\n}\n\nexport function grSwitchSpinnerClass(size: GrSwitchSize): string {\n return [thumbSpinnerBase, thumbSpinnerSizes[size]].join(' ')\n}\n\nexport function grSwitchLabelClass(size: GrSwitchSize, disabled = false): string {\n return [disabled ? labelDisabledClass : labelBase, labelSizes[size]].join(' ')\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n labelBase,\n labelDisabledClass,\n labelSizes,\n rootBase,\n rootLabelPositions,\n thumbBase,\n thumbSizes,\n thumbSpinnerBase,\n thumbSpinnerSizes,\n thumbTranslations,\n trackBase,\n trackSizes,\n} from './grSwitchStyles'\n\nexport const grSwitchClassTokens = {\n rootBase: splitClassTokens(rootBase),\n rootLabelPositions: Object.values(rootLabelPositions).flatMap(splitClassTokens),\n trackBase: splitClassTokens(trackBase),\n trackSizes: Object.values(trackSizes).flatMap(splitClassTokens),\n thumbBase: splitClassTokens(thumbBase),\n thumbSizes: Object.values(thumbSizes).flatMap(splitClassTokens),\n thumbSpinner: [\n ...splitClassTokens(thumbSpinnerBase),\n ...Object.values(thumbSpinnerSizes).flatMap(splitClassTokens),\n ],\n thumbTranslations: Object.values(thumbTranslations).flatMap(({ checked, unchecked }) => {\n return [...splitClassTokens(checked), ...splitClassTokens(unchecked)]\n }),\n labelBase: [...splitClassTokens(labelBase), ...splitClassTokens(labelDisabledClass)],\n labelSizes: Object.values(labelSizes).flatMap(splitClassTokens),\n} as const\n\nexport const grSwitchSafelist = [...new Set([\n ...grSwitchClassTokens.rootBase,\n ...grSwitchClassTokens.rootLabelPositions,\n ...grSwitchClassTokens.trackBase,\n ...grSwitchClassTokens.trackSizes,\n ...grSwitchClassTokens.thumbBase,\n ...grSwitchClassTokens.thumbSizes,\n ...grSwitchClassTokens.thumbSpinner,\n ...grSwitchClassTokens.thumbTranslations,\n ...grSwitchClassTokens.labelBase,\n ...grSwitchClassTokens.labelSizes,\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grSwitchSafelist } from './safelist'\n\nexport const grSwitchConfig = defineGranularComponent(import.meta.url, {\n name: 'GrSwitch',\n safelist: grSwitchSafelist,\n})\n"],"mappings":";;;AAaA,IAAa,WAAW;;AAGxB,IAAa,qBAA4D;CACvE,OAAO;CACP,KAAK;AACP;AAEA,IAAa,YACT;AAEJ,IAAa,aAA2C;CACtD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAa,YACT;AAEJ,IAAa,aAA2C;CACtD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;AAGA,IAAa,oBAAkD;CAC7D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAa,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;AA0BhC,IAAa,oBAAkF;CAC7F,IAAI;EACF,SAAS;EACT,WAAW;CACb;CACA,IAAI;EACF,SAAS;EACT,WAAW;CACb;CACA,IAAI;EACF,SAAS;EACT,WAAW;CACb;CACA,IAAI;EACF,SAAS;EACT,WAAW;CACb;AACF;AAEA,IAAa,YAAY;;;;;AAMzB,IAAa,qBAAqB;AAElC,IAAa,aAA2C;CACtD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,SAAgB,kBAAkB,eAA8C;CAC9E,OAAO,CAAC,UAAU,mBAAmB,cAAc,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC/E;AAEA,SAAgB,mBAAmB,MAA4B;CAC7D,OAAO,CAAC,WAAW,WAAW,KAAK,CAAC,CAAC,KAAK,GAAG;AAC/C;AAEA,SAAgB,mBAAmB,SAA4C;CAC7E,OAAO;EACL;EACA,WAAW,QAAQ;EACnB,kBAAkB,QAAQ,KAAK,CAAC,QAAQ,UAAU,YAAY;CAChE,CAAC,CAAC,KAAK,GAAG;AACZ;AAEA,SAAgB,qBAAqB,MAA4B;CAC/D,OAAO,CAAC,kBAAkB,kBAAkB,KAAK,CAAC,CAAC,KAAK,GAAG;AAC7D;AAEA,SAAgB,mBAAmB,MAAoB,WAAW,OAAe;CAC/E,OAAO,CAAC,WAAW,qBAAqB,WAAW,WAAW,KAAK,CAAC,CAAC,KAAK,GAAG;AAC/E;;;ACnHA,IAAa,sBAAsB;CACjC,UAAU,iBAAiB,QAAQ;CACnC,oBAAoB,OAAO,OAAO,kBAAkB,CAAC,CAAC,QAAQ,gBAAgB;CAC9E,WAAW,iBAAiB,SAAS;CACrC,YAAY,OAAO,OAAO,UAAU,CAAC,CAAC,QAAQ,gBAAgB;CAC9D,WAAW,iBAAiB,SAAS;CACrC,YAAY,OAAO,OAAO,UAAU,CAAC,CAAC,QAAQ,gBAAgB;CAC9D,cAAc,CACZ,GAAG,iBAAiB,gBAAgB,GACpC,GAAG,OAAO,OAAO,iBAAiB,CAAC,CAAC,QAAQ,gBAAgB,CAC9D;CACA,mBAAmB,OAAO,OAAO,iBAAiB,CAAC,CAAC,SAAS,EAAE,SAAS,gBAAgB;EACtF,OAAO,CAAC,GAAG,iBAAiB,OAAO,GAAG,GAAG,iBAAiB,SAAS,CAAC;CACtE,CAAC;CACD,WAAW,CAAC,GAAG,iBAAiB,SAAS,GAAG,GAAG,iBAAiB,kBAAkB,CAAC;CACnF,YAAY,OAAO,OAAO,UAAU,CAAC,CAAC,QAAQ,gBAAgB;AAChE;AAEA,IAAa,mBAAmB,CAAC,mBAAG,IAAI,IAAI;CAC1C,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;AACzB,CAAC,CAAC;;;ACzCF,IAAa,iBAAiB,wBAAwB,OAAO,KAAK,KAAK;CACrE,MAAM;CACN,UAAU;AACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-_jbgsFpw.js","names":[],"sources":["../../src/components/GrDropdownMenu/safelist.ts","../../src/components/GrDropdownMenu/config.ts"],"sourcesContent":["import { splitClassTokens } from '../shared/classTokens'\n\nimport {\n
|
|
1
|
+
{"version":3,"file":"config-_jbgsFpw.js","names":[],"sources":["../../src/components/GrDropdownMenu/safelist.ts","../../src/components/GrDropdownMenu/config.ts"],"sourcesContent":["import { splitClassTokens } from '../shared/classTokens'\n\nimport {\n alignClass,\n borderBottomClass,\n borderEdgeClass,\n borderTopClass,\n colsClass,\n columnBaseClass,\n columnsBaseClass,\n dividerClass,\n dividerInsetClass,\n dividersClass,\n headerClass,\n itemBaseClass,\n itemDisabledClass,\n itemIndicatorClass,\n itemInteractiveClass,\n itemShortcutClass,\n itemVariantClass,\n listBaseClass,\n textAlignClass,\n} from './grDropdownMenuStyles'\n\n/**\n * Классы каталога живут в `.ts`-хелпере, а его бандлер волен вынести в общий\n * `dist/chunks/` — вне области скана компонента. Симптом промаха тут особенно\n * незаметный: размеры пунктов на месте, а выравнивание, колонки и цвета\n * пропали. Гейт — `src/__tests__/safelist.test.ts`.\n */\nexport const grDropdownMenuSafelist = [...new Set([\n ...Object.values(alignClass).flatMap(splitClassTokens),\n ...Object.values(textAlignClass).flatMap(splitClassTokens),\n ...Object.values(colsClass).flatMap(splitClassTokens),\n ...Object.values(itemVariantClass).flatMap(splitClassTokens),\n ...splitClassTokens(itemBaseClass),\n ...splitClassTokens(itemInteractiveClass),\n ...splitClassTokens(itemDisabledClass),\n ...splitClassTokens(itemIndicatorClass),\n ...splitClassTokens(itemShortcutClass),\n ...splitClassTokens(headerClass),\n ...splitClassTokens(listBaseClass),\n ...splitClassTokens(dividersClass),\n ...splitClassTokens(borderEdgeClass),\n ...splitClassTokens(borderTopClass),\n ...splitClassTokens(borderBottomClass),\n ...splitClassTokens(columnsBaseClass),\n ...splitClassTokens(columnBaseClass),\n ...splitClassTokens(dividerClass),\n ...splitClassTokens(dividerInsetClass),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grDropdownMenuSafelist } from './safelist'\n\nexport const grDropdownMenuConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDropdownMenu',\n dependencies: ['GrDropdown'],\n safelist: grDropdownMenuSafelist,\n})\n"],"mappings":";;;;;;;;;;AA8BA,IAAa,yBAAyB,CAAC,mBAAG,IAAI,IAAI;CAChD,GAAG,OAAO,OAAO,UAAU,CAAC,CAAC,QAAQ,gBAAgB;CACrD,GAAG,OAAO,OAAO,cAAc,CAAC,CAAC,QAAQ,gBAAgB;CACzD,GAAG,OAAO,OAAO,SAAS,CAAC,CAAC,QAAQ,gBAAgB;CACpD,GAAG,OAAO,OAAO,gBAAgB,CAAC,CAAC,QAAQ,gBAAgB;CAC3D,GAAG,iBAAiB,aAAa;CACjC,GAAG,iBAAiB,oBAAoB;CACxC,GAAG,iBAAiB,iBAAiB;CACrC,GAAG,iBAAiB,kBAAkB;CACtC,GAAG,iBAAiB,iBAAiB;CACrC,GAAG,iBAAiB,WAAW;CAC/B,GAAG,iBAAiB,aAAa;CACjC,GAAG,iBAAiB,aAAa;CACjC,GAAG,iBAAiB,eAAe;CACnC,GAAG,iBAAiB,cAAc;CAClC,GAAG,iBAAiB,iBAAiB;CACrC,GAAG,iBAAiB,gBAAgB;CACpC,GAAG,iBAAiB,eAAe;CACnC,GAAG,iBAAiB,YAAY;CAChC,GAAG,iBAAiB,iBAAiB;AACvC,CAAC,CAAC;;;AC9CF,IAAa,uBAAuB,wBAAwB,OAAO,KAAK,KAAK;CAC3E,MAAM;CACN,cAAc,CAAC,YAAY;CAC3B,UAAU;AACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-g8-JGZ_Y.js","names":[],"sources":["../../src/components/GrBadge/config.ts"],"sourcesContent":["import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grBadgeSafelist } from './safelist'\n\nexport const grBadgeConfig = defineGranularComponent(import.meta.url, {\n name: 'GrBadge',\n safelist: grBadgeSafelist,\n tokenDefinitionsRef: {\n light: { url: './themes/light.css', selector: ':root' },\n dark: { url: './themes/dark.css', as: '.dark, [data-theme=\"dark\"]' },\n },\n})"],"mappings":";;;AAIA,IAAa,gBAAgB,wBAAwB,OAAO,KAAK,KAAK;CACpE,MAAM;CACN,UAAU;CACV,qBAAqB;EACnB,OAAO;GAAE,KAAK;GAAsB,UAAU;EAAQ;EACtD,MAAM;GAAE,KAAK;GAAqB,IAAI;EAA6B;CACrE;AACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"config-g8-JGZ_Y.js","names":[],"sources":["../../src/components/GrBadge/config.ts"],"sourcesContent":["import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grBadgeSafelist } from './safelist'\n\nexport const grBadgeConfig = defineGranularComponent(import.meta.url, {\n name: 'GrBadge',\n safelist: grBadgeSafelist,\n tokenDefinitionsRef: {\n light: { url: './themes/light.css', selector: ':root' },\n dark: { url: './themes/dark.css', as: '.dark, [data-theme=\"dark\"]' },\n },\n})\n"],"mappings":";;;AAIA,IAAa,gBAAgB,wBAAwB,OAAO,KAAK,KAAK;CACpE,MAAM;CACN,UAAU;CACV,qBAAqB;EACnB,OAAO;GAAE,KAAK;GAAsB,UAAU;EAAQ;EACtD,MAAM;GAAE,KAAK;GAAqB,IAAI;EAA6B;CACrE;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-mlheIMtV.js","names":[],"sources":["../../src/components/GrModal/safelist.ts","../../src/components/GrModal/config.ts"],"sourcesContent":["import { flattenTransitionTokens, splitClassTokens } from '../shared/classTokens'\nimport {\n layoutByScroll,\n overlay,\n overlayTransition,\n panelBase,\n panelBodyScrollClass,\n panelHeightBySize,\n panelSectionClass,\n panelOverflowByScroll,\n panelRadiusBySize,\n panelTransition,\n panelWidthBySize,\n root,\n shellBase,\n shellByScroll,\n shellPaddingBySize,\n} from './grModalStyles'\n\ntype GrModalClassTokens = {\n root: readonly string[]\n shell: readonly string[]\n layout: readonly string[]\n overlay: readonly string[]\n overlayTransition: readonly string[]\n panelBase: readonly string[]\n panelTransition: readonly string[]\n panelWidth: readonly string[]\n panelRadius: readonly string[]\n panelHeight: readonly string[]\n}\n\nexport const grModalClassTokens: GrModalClassTokens = {\n root: splitClassTokens(root),\n shell: [\n ...splitClassTokens(shellBase),\n ...Object.values(shellPaddingBySize).flatMap(splitClassTokens),\n ...Object.values(shellByScroll).flatMap(splitClassTokens),\n ],\n layout: Object.values(layoutByScroll).flatMap(splitClassTokens),\n overlay: splitClassTokens(overlay),\n overlayTransition: flattenTransitionTokens(overlayTransition),\n panelBase: [\n ...splitClassTokens(panelBase),\n ...Object.values(panelOverflowByScroll).flatMap(splitClassTokens),\n ...splitClassTokens(panelBodyScrollClass),\n ...splitClassTokens(panelSectionClass),\n ],\n panelTransition: flattenTransitionTokens(panelTransition),\n panelWidth: Object.values(panelWidthBySize).flatMap(splitClassTokens),\n panelRadius: Object.values(panelRadiusBySize).flatMap(splitClassTokens),\n panelHeight: Object.values(panelHeightBySize).flatMap(v => splitClassTokens(v ?? '')),\n}\n\nexport const grModalSafelist = [...new Set([\n ...grModalClassTokens.root,\n ...grModalClassTokens.shell,\n ...grModalClassTokens.layout,\n ...grModalClassTokens.overlay,\n ...grModalClassTokens.overlayTransition,\n ...grModalClassTokens.panelBase,\n ...grModalClassTokens.panelTransition,\n ...grModalClassTokens.panelWidth,\n ...grModalClassTokens.panelRadius,\n ...grModalClassTokens.panelHeight,\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grModalSafelist } from './safelist'\n\nexport const grModalConfig = defineGranularComponent(import.meta.url, {\n name: 'GrModal',\n safelist: grModalSafelist,\n})"],"mappings":";;;;AAgCA,IAAa,qBAAyC;CACpD,MAAM,iBAAiB,IAAI;CAC3B,OAAO;EACL,GAAG,iBAAiB,SAAS;EAC7B,GAAG,OAAO,OAAO,kBAAkB,CAAC,CAAC,QAAQ,gBAAgB;EAC7D,GAAG,OAAO,OAAO,aAAa,CAAC,CAAC,QAAQ,gBAAgB;CAC1D;CACA,QAAQ,OAAO,OAAO,cAAc,CAAC,CAAC,QAAQ,gBAAgB;CAC9D,SAAS,iBAAiB,OAAO;CACjC,mBAAmB,wBAAwB,iBAAiB;CAC5D,WAAW;EACT,GAAG,iBAAiB,SAAS;EAC7B,GAAG,OAAO,OAAO,qBAAqB,CAAC,CAAC,QAAQ,gBAAgB;EAChE,GAAG,iBAAiB,oBAAoB;EACxC,GAAG,iBAAiB,iBAAiB;CACvC;CACA,iBAAiB,wBAAwB,eAAe;CACxD,YAAY,OAAO,OAAO,gBAAgB,CAAC,CAAC,QAAQ,gBAAgB;CACpE,aAAa,OAAO,OAAO,iBAAiB,CAAC,CAAC,QAAQ,gBAAgB;CACtE,aAAa,OAAO,OAAO,iBAAiB,CAAC,CAAC,SAAQ,MAAK,iBAAiB,KAAK,EAAE,CAAC;AACtF;AAEA,IAAa,kBAAkB,CAAC,mBAAG,IAAI,IAAI;CACzC,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;AACxB,CAAC,CAAC;;;AC7DF,IAAa,gBAAgB,wBAAwB,OAAO,KAAK,KAAK;CACpE,MAAM;CACN,UAAU;AACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"config-mlheIMtV.js","names":[],"sources":["../../src/components/GrModal/safelist.ts","../../src/components/GrModal/config.ts"],"sourcesContent":["import { flattenTransitionTokens, splitClassTokens } from '../shared/classTokens'\nimport {\n layoutByScroll,\n overlay,\n overlayTransition,\n panelBase,\n panelBodyScrollClass,\n panelHeightBySize,\n panelSectionClass,\n panelOverflowByScroll,\n panelRadiusBySize,\n panelTransition,\n panelWidthBySize,\n root,\n shellBase,\n shellByScroll,\n shellPaddingBySize,\n} from './grModalStyles'\n\ntype GrModalClassTokens = {\n root: readonly string[]\n shell: readonly string[]\n layout: readonly string[]\n overlay: readonly string[]\n overlayTransition: readonly string[]\n panelBase: readonly string[]\n panelTransition: readonly string[]\n panelWidth: readonly string[]\n panelRadius: readonly string[]\n panelHeight: readonly string[]\n}\n\nexport const grModalClassTokens: GrModalClassTokens = {\n root: splitClassTokens(root),\n shell: [\n ...splitClassTokens(shellBase),\n ...Object.values(shellPaddingBySize).flatMap(splitClassTokens),\n ...Object.values(shellByScroll).flatMap(splitClassTokens),\n ],\n layout: Object.values(layoutByScroll).flatMap(splitClassTokens),\n overlay: splitClassTokens(overlay),\n overlayTransition: flattenTransitionTokens(overlayTransition),\n panelBase: [\n ...splitClassTokens(panelBase),\n ...Object.values(panelOverflowByScroll).flatMap(splitClassTokens),\n ...splitClassTokens(panelBodyScrollClass),\n ...splitClassTokens(panelSectionClass),\n ],\n panelTransition: flattenTransitionTokens(panelTransition),\n panelWidth: Object.values(panelWidthBySize).flatMap(splitClassTokens),\n panelRadius: Object.values(panelRadiusBySize).flatMap(splitClassTokens),\n panelHeight: Object.values(panelHeightBySize).flatMap(v => splitClassTokens(v ?? '')),\n}\n\nexport const grModalSafelist = [...new Set([\n ...grModalClassTokens.root,\n ...grModalClassTokens.shell,\n ...grModalClassTokens.layout,\n ...grModalClassTokens.overlay,\n ...grModalClassTokens.overlayTransition,\n ...grModalClassTokens.panelBase,\n ...grModalClassTokens.panelTransition,\n ...grModalClassTokens.panelWidth,\n ...grModalClassTokens.panelRadius,\n ...grModalClassTokens.panelHeight,\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grModalSafelist } from './safelist'\n\nexport const grModalConfig = defineGranularComponent(import.meta.url, {\n name: 'GrModal',\n safelist: grModalSafelist,\n})\n"],"mappings":";;;;AAgCA,IAAa,qBAAyC;CACpD,MAAM,iBAAiB,IAAI;CAC3B,OAAO;EACL,GAAG,iBAAiB,SAAS;EAC7B,GAAG,OAAO,OAAO,kBAAkB,CAAC,CAAC,QAAQ,gBAAgB;EAC7D,GAAG,OAAO,OAAO,aAAa,CAAC,CAAC,QAAQ,gBAAgB;CAC1D;CACA,QAAQ,OAAO,OAAO,cAAc,CAAC,CAAC,QAAQ,gBAAgB;CAC9D,SAAS,iBAAiB,OAAO;CACjC,mBAAmB,wBAAwB,iBAAiB;CAC5D,WAAW;EACT,GAAG,iBAAiB,SAAS;EAC7B,GAAG,OAAO,OAAO,qBAAqB,CAAC,CAAC,QAAQ,gBAAgB;EAChE,GAAG,iBAAiB,oBAAoB;EACxC,GAAG,iBAAiB,iBAAiB;CACvC;CACA,iBAAiB,wBAAwB,eAAe;CACxD,YAAY,OAAO,OAAO,gBAAgB,CAAC,CAAC,QAAQ,gBAAgB;CACpE,aAAa,OAAO,OAAO,iBAAiB,CAAC,CAAC,QAAQ,gBAAgB;CACtE,aAAa,OAAO,OAAO,iBAAiB,CAAC,CAAC,SAAQ,MAAK,iBAAiB,KAAK,EAAE,CAAC;AACtF;AAEA,IAAa,kBAAkB,CAAC,mBAAG,IAAI,IAAI;CACzC,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;CACtB,GAAG,mBAAmB;AACxB,CAAC,CAAC;;;AC7DF,IAAa,gBAAgB,wBAAwB,OAAO,KAAK,KAAK;CACpE,MAAM;CACN,UAAU;AACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-rLkc9Zn2.js","names":[],"sources":["../../src/components/GrSegmented/grSegmentedStyles.ts","../../src/components/GrSegmented/safelist.ts","../../src/components/GrSegmented/config.ts"],"sourcesContent":["import type { GrComponentSize } from '../shared/sizes'\n\nimport type { Component } from 'vue'\nexport type GrSegmentedVariant = 'pills' | 'button'\nexport type GrSegmentedSize = GrComponentSize\n\n/** Направление ряда сегментов. Вертикаль — боковые фильтры. */\nexport const GR_SEGMENTED_ORIENTATIONS = ['horizontal', 'vertical'] as const\nexport type GrSegmentedOrientation = typeof GR_SEGMENTED_ORIENTATIONS[number]\nexport type GrSegmentedValue = string | number\nexport type GrSegmentedOption = {\n value: GrSegmentedValue\n label?: string\n icon?: Component\n disabled?: boolean\n /**\n * Сегмент занят: вместо иконки крутится спиннер, выбор не принимается.\n * От `disabled` отличается смыслом — сегмент доступен, но сейчас работает.\n */\n loading?: boolean\n /**\n * Доступное имя сегмента. Обязательно для icon-only опций: иконка декоративна\n * (`aria-hidden`), и без этого у сегмента нет имени вовсе — скринридер объявит\n * пустую кнопку. Когда есть `label`, имя берётся из него, и поле не нужно.\n */\n ariaLabel?: string\n}\nexport const rootBaseClass =\n 'relative inline-grid min-w-0 items-stretch rounded-[var(--gr-segmented-radius)] p-[var(--gr-segmented-padding)] transition-colors duration-[var(--gr-duration-fast)]'\n\n/** Направление потока: остальную раскладку задают `gridTemplate*` в стиле корня. */\nexport const rootOrientationClassMap: Record<GrSegmentedOrientation, string> = {\n horizontal: 'grid-flow-col',\n vertical: 'grid-flow-row',\n}\nexport const rootVariantClassMap: Record<GrSegmentedVariant, string> = {\n pills: 'border border-[var(--gr-segmented-track-brd)] bg-[var(--gr-segmented-track-bg)] text-[var(--gr-segmented-item-color)]',\n button: 'border border-[var(--gr-segmented-track-brd)] bg-[var(--gr-segmented-track-bg)] text-[var(--gr-segmented-item-color)] shadow-[var(--gr-segmented-track-shadow)]',\n}\nexport const rootBlockClass = 'w-full'\nexport const rootDisabledClass = 'text-[var(--gr-disabled-fg)]'\nexport const indicatorBaseClass =\n 'pointer-events-none absolute left-0 top-0 rounded-[calc(var(--gr-segmented-radius)-var(--gr-segmented-padding))] transition-[transform,width,height,opacity] ease-[var(--gr-ease-out)]'\nexport const indicatorVariantClassMap: Record<GrSegmentedVariant, string> = {\n pills: 'border border-[var(--gr-segmented-indicator-brd)] bg-[var(--gr-segmented-indicator-bg)] shadow-[var(--gr-segmented-indicator-shadow)]',\n button: 'border border-[var(--gr-segmented-indicator-brd)] bg-[var(--gr-segmented-indicator-bg)] shadow-[var(--gr-segmented-indicator-shadow)]',\n}\nexport const itemBaseClass =\n 'group/segmented-item relative z-[1] inline-flex min-h-[var(--gr-segmented-min-height)] min-w-0 items-center justify-center gap-2 rounded-[calc(var(--gr-segmented-radius)-var(--gr-segmented-padding))] px-[var(--gr-segmented-item-px)] py-[var(--gr-segmented-item-py)] text-[length:var(--gr-segmented-font-size)] leading-[var(--gr-segmented-line-height)] font-[var(--gr-segmented-font-weight)] text-[var(--gr-segmented-item-color)] transition-colors duration-[var(--gr-duration-fast)] select-none focus:outline-none focus-visible:shadow-[0_0_0_2px_var(--gr-ring),0_0_0_4px_var(--gr-bg)]'\nexport const itemVariantClassMap: Record<GrSegmentedVariant, string> = {\n pills: '',\n button: '',\n}\nexport const itemSelectedClass = 'text-[var(--gr-segmented-item-selected-color)]'\n/**\n * Недоступный сегмент гасится токеном, а не `opacity`: прозрачность разбавляет\n * выверенные на AA токены текста и роняет контраст подписи.\n */\nexport const itemDisabledClass = 'cursor-not-allowed text-[var(--gr-disabled-fg)]'\nexport const itemEnabledClass = 'cursor-pointer hover:text-[var(--gr-segmented-item-hover-color)]'\nexport const itemLabelClass = 'truncate'\nexport const itemIconClass = 'h-4 w-4 shrink-0'\nexport const itemSpinnerClass = 'h-4 w-4 shrink-0 animate-spin'\nexport const iconOnlyClass = 'gap-0'\nconst rootSizeStyles: Record<GrSegmentedSize, Record<string, string>> = {\n xs: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '10px',\n '--gr-segmented-item-py': '4px',\n '--gr-segmented-font-size': '0.75rem',\n '--gr-segmented-line-height': '1rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '24px',\n },\n sm: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '12px',\n '--gr-segmented-item-py': '6px',\n '--gr-segmented-font-size': '0.75rem',\n '--gr-segmented-line-height': '1rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '28px',\n },\n md: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '14px',\n '--gr-segmented-item-py': '8px',\n '--gr-segmented-font-size': '0.875rem',\n '--gr-segmented-line-height': '1.25rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '40px',\n },\n lg: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '16px',\n '--gr-segmented-item-py': '10px',\n '--gr-segmented-font-size': '0.9375rem',\n '--gr-segmented-line-height': '1.25rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '46px',\n },\n}\nconst rootVariantStyles: Record<GrSegmentedVariant, Record<string, string>> = {\n pills: {\n '--gr-segmented-track-bg': 'var(--gr-muted)',\n '--gr-segmented-track-brd': 'var(--gr-brd)',\n '--gr-segmented-track-shadow': 'none',\n '--gr-segmented-indicator-bg': 'var(--gr-card)',\n '--gr-segmented-indicator-brd': 'color-mix(in srgb, var(--gr-card) 84%, var(--gr-brd) 16%)',\n '--gr-segmented-indicator-shadow': 'var(--gr-shadow-1), var(--gr-segmented-indicator-highlight-shadow, 0 0 0 0 transparent)',\n '--gr-segmented-item-color': 'var(--gr-muted-fg)',\n '--gr-segmented-item-selected-color': 'var(--gr-fg)',\n '--gr-segmented-item-hover-color': 'var(--gr-fg)',\n },\n button: {\n '--gr-segmented-track-bg': 'var(--gr-card)',\n '--gr-segmented-track-brd': 'var(--gr-brd)',\n '--gr-segmented-track-shadow': 'var(--gr-shadow-1)',\n '--gr-segmented-indicator-bg': 'var(--gr-primary)',\n '--gr-segmented-indicator-brd': 'color-mix(in srgb, var(--gr-primary) 88%, var(--gr-brd) 12%)',\n '--gr-segmented-indicator-shadow': 'var(--gr-shadow-2)',\n '--gr-segmented-item-color': 'var(--gr-muted-fg)',\n '--gr-segmented-item-selected-color': 'var(--gr-primary-fg)',\n '--gr-segmented-item-hover-color': 'var(--gr-fg)',\n },\n}\nexport function grSegmentedRootClass(options: {\n variant: GrSegmentedVariant\n orientation: GrSegmentedOrientation\n block: boolean\n disabled: boolean\n}): string {\n return [\n rootBaseClass,\n rootOrientationClassMap[options.orientation],\n rootVariantClassMap[options.variant],\n options.block ? rootBlockClass : '',\n options.disabled ? rootDisabledClass : '',\n ].filter(Boolean).join(' ')\n}\n/**\n * Радиус дорожки в вертикали — пилюля **одной строки**, а не всей колонки.\n * `9999px` выверен под короткий горизонтальный ряд; на высокой колонке он\n * превращает дорожку в эллипс. Формула повторяет высоту сегмента, поэтому\n * скругление у колонки ровно такое же, как у ряда, и сегменты внутри остаются\n * пилюлями: они считают свой радиус от этого же значения.\n */\nconst verticalRadiusStyle = {\n '--gr-segmented-radius': 'calc(var(--gr-segmented-min-height) / 2 + var(--gr-segmented-padding))',\n}\n\nexport function grSegmentedRootStyle(options: {\n variant: GrSegmentedVariant\n size: GrSegmentedSize\n orientation: GrSegmentedOrientation\n}): Record<string, string> {\n return {\n ...rootSizeStyles[options.size],\n ...rootVariantStyles[options.variant],\n ...(options.orientation === 'vertical' ? verticalRadiusStyle : {}),\n }\n}\nexport function grSegmentedIndicatorClass(variant: GrSegmentedVariant): string {\n return [indicatorBaseClass, indicatorVariantClassMap[variant]].join(' ')\n}\nexport function grSegmentedItemClass(options: {\n variant: GrSegmentedVariant\n selected: boolean\n disabled: boolean\n iconOnly: boolean\n}): string {\n return [\n itemBaseClass,\n itemVariantClassMap[options.variant],\n options.selected ? itemSelectedClass : '',\n options.disabled ? itemDisabledClass : itemEnabledClass,\n options.iconOnly ? iconOnlyClass : '',\n ].filter(Boolean).join(' ')\n}\nexport const grSegmentedItemLabelClass = itemLabelClass\nexport const grSegmentedItemIconClass = itemIconClass\nexport const grSegmentedItemSpinnerClass = itemSpinnerClass\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n iconOnlyClass,\n indicatorBaseClass,\n indicatorVariantClassMap,\n itemBaseClass,\n itemDisabledClass,\n itemEnabledClass,\n itemIconClass,\n itemLabelClass,\n itemSpinnerClass,\n itemSelectedClass,\n itemVariantClassMap,\n rootBaseClass,\n rootBlockClass,\n rootDisabledClass,\n rootOrientationClassMap,\n rootVariantClassMap,\n} from './grSegmentedStyles'\n\nexport const grSegmentedClassTokens = {\n rootBaseClass: splitClassTokens(rootBaseClass),\n rootOrientationClassMap: Object.values(rootOrientationClassMap).flatMap(splitClassTokens),\n rootVariantClassMap: Object.values(rootVariantClassMap).flatMap(splitClassTokens),\n rootBlockClass: splitClassTokens(rootBlockClass),\n rootDisabledClass: splitClassTokens(rootDisabledClass),\n indicatorBaseClass: splitClassTokens(indicatorBaseClass),\n indicatorVariantClassMap: Object.values(indicatorVariantClassMap).flatMap(splitClassTokens),\n itemBaseClass: splitClassTokens(itemBaseClass),\n itemVariantClassMap: Object.values(itemVariantClassMap).flatMap(splitClassTokens),\n itemSelectedClass: splitClassTokens(itemSelectedClass),\n itemDisabledClass: splitClassTokens(itemDisabledClass),\n itemEnabledClass: splitClassTokens(itemEnabledClass),\n itemLabelClass: splitClassTokens(itemLabelClass),\n itemIconClass: splitClassTokens(itemIconClass),\n itemSpinnerClass: splitClassTokens(itemSpinnerClass),\n iconOnlyClass: splitClassTokens(iconOnlyClass),\n} as const\n\nexport const grSegmentedSafelist = [...new Set([\n ...grSegmentedClassTokens.rootBaseClass,\n ...grSegmentedClassTokens.rootOrientationClassMap,\n ...grSegmentedClassTokens.rootVariantClassMap,\n ...grSegmentedClassTokens.rootBlockClass,\n ...grSegmentedClassTokens.rootDisabledClass,\n ...grSegmentedClassTokens.indicatorBaseClass,\n ...grSegmentedClassTokens.indicatorVariantClassMap,\n ...grSegmentedClassTokens.itemBaseClass,\n ...grSegmentedClassTokens.itemVariantClassMap,\n ...grSegmentedClassTokens.itemSelectedClass,\n ...grSegmentedClassTokens.itemDisabledClass,\n ...grSegmentedClassTokens.itemEnabledClass,\n ...grSegmentedClassTokens.itemLabelClass,\n ...grSegmentedClassTokens.itemIconClass,\n ...grSegmentedClassTokens.itemSpinnerClass,\n ...grSegmentedClassTokens.iconOnlyClass,\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grSegmentedSafelist } from './safelist'\n\nexport const grSegmentedConfig = defineGranularComponent(import.meta.url, {\n name: 'GrSegmented',\n safelist: grSegmentedSafelist,\n tokenDefinitions: {\n light: {\n selector: ':root',\n tokens: {'gr-segmented-indicator-highlight-shadow': '0 0 0 0 transparent'}\n },\n dark: {\n selector: '.dark',\n tokens: {'gr-segmented-indicator-highlight-shadow': '0 0 0 1px rgba(248, 250, 252, 0.08)'}\n },\n }\n})"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-rLkc9Zn2.js","names":[],"sources":["../../src/components/GrSegmented/grSegmentedStyles.ts","../../src/components/GrSegmented/safelist.ts","../../src/components/GrSegmented/config.ts"],"sourcesContent":["import type { GrComponentSize } from '../shared/sizes'\n\nimport type { Component } from 'vue'\n\nexport type GrSegmentedVariant = 'pills' | 'button'\nexport type GrSegmentedSize = GrComponentSize\n\n/** Направление ряда сегментов. Вертикаль — боковые фильтры. */\nexport const GR_SEGMENTED_ORIENTATIONS = ['horizontal', 'vertical'] as const\nexport type GrSegmentedOrientation = typeof GR_SEGMENTED_ORIENTATIONS[number]\nexport type GrSegmentedValue = string | number\nexport type GrSegmentedOption = {\n value: GrSegmentedValue\n label?: string\n icon?: Component\n disabled?: boolean\n /**\n * Сегмент занят: вместо иконки крутится спиннер, выбор не принимается.\n * От `disabled` отличается смыслом — сегмент доступен, но сейчас работает.\n */\n loading?: boolean\n /**\n * Доступное имя сегмента. Обязательно для icon-only опций: иконка декоративна\n * (`aria-hidden`), и без этого у сегмента нет имени вовсе — скринридер объявит\n * пустую кнопку. Когда есть `label`, имя берётся из него, и поле не нужно.\n */\n ariaLabel?: string\n}\nexport const rootBaseClass\n = 'relative inline-grid min-w-0 items-stretch rounded-[var(--gr-segmented-radius)] p-[var(--gr-segmented-padding)] transition-colors duration-[var(--gr-duration-fast)]'\n\n/** Направление потока: остальную раскладку задают `gridTemplate*` в стиле корня. */\nexport const rootOrientationClassMap: Record<GrSegmentedOrientation, string> = {\n horizontal: 'grid-flow-col',\n vertical: 'grid-flow-row',\n}\nexport const rootVariantClassMap: Record<GrSegmentedVariant, string> = {\n pills: 'border border-[var(--gr-segmented-track-brd)] bg-[var(--gr-segmented-track-bg)] text-[var(--gr-segmented-item-color)]',\n button: 'border border-[var(--gr-segmented-track-brd)] bg-[var(--gr-segmented-track-bg)] text-[var(--gr-segmented-item-color)] shadow-[var(--gr-segmented-track-shadow)]',\n}\nexport const rootBlockClass = 'w-full'\nexport const rootDisabledClass = 'text-[var(--gr-disabled-fg)]'\nexport const indicatorBaseClass\n = 'pointer-events-none absolute left-0 top-0 rounded-[calc(var(--gr-segmented-radius)-var(--gr-segmented-padding))] transition-[transform,width,height,opacity] ease-[var(--gr-ease-out)]'\nexport const indicatorVariantClassMap: Record<GrSegmentedVariant, string> = {\n pills: 'border border-[var(--gr-segmented-indicator-brd)] bg-[var(--gr-segmented-indicator-bg)] shadow-[var(--gr-segmented-indicator-shadow)]',\n button: 'border border-[var(--gr-segmented-indicator-brd)] bg-[var(--gr-segmented-indicator-bg)] shadow-[var(--gr-segmented-indicator-shadow)]',\n}\nexport const itemBaseClass\n = 'group/segmented-item relative z-[1] inline-flex min-h-[var(--gr-segmented-min-height)] min-w-0 items-center justify-center gap-2 rounded-[calc(var(--gr-segmented-radius)-var(--gr-segmented-padding))] px-[var(--gr-segmented-item-px)] py-[var(--gr-segmented-item-py)] text-[length:var(--gr-segmented-font-size)] leading-[var(--gr-segmented-line-height)] font-[var(--gr-segmented-font-weight)] text-[var(--gr-segmented-item-color)] transition-colors duration-[var(--gr-duration-fast)] select-none focus:outline-none focus-visible:shadow-[0_0_0_2px_var(--gr-ring),0_0_0_4px_var(--gr-bg)]'\nexport const itemVariantClassMap: Record<GrSegmentedVariant, string> = {\n pills: '',\n button: '',\n}\nexport const itemSelectedClass = 'text-[var(--gr-segmented-item-selected-color)]'\n/**\n * Недоступный сегмент гасится токеном, а не `opacity`: прозрачность разбавляет\n * выверенные на AA токены текста и роняет контраст подписи.\n */\nexport const itemDisabledClass = 'cursor-not-allowed text-[var(--gr-disabled-fg)]'\nexport const itemEnabledClass = 'cursor-pointer hover:text-[var(--gr-segmented-item-hover-color)]'\nexport const itemLabelClass = 'truncate'\nexport const itemIconClass = 'h-4 w-4 shrink-0'\nexport const itemSpinnerClass = 'h-4 w-4 shrink-0 animate-spin'\nexport const iconOnlyClass = 'gap-0'\nconst rootSizeStyles: Record<GrSegmentedSize, Record<string, string>> = {\n xs: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '10px',\n '--gr-segmented-item-py': '4px',\n '--gr-segmented-font-size': '0.75rem',\n '--gr-segmented-line-height': '1rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '24px',\n },\n sm: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '12px',\n '--gr-segmented-item-py': '6px',\n '--gr-segmented-font-size': '0.75rem',\n '--gr-segmented-line-height': '1rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '28px',\n },\n md: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '14px',\n '--gr-segmented-item-py': '8px',\n '--gr-segmented-font-size': '0.875rem',\n '--gr-segmented-line-height': '1.25rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '40px',\n },\n lg: {\n '--gr-segmented-radius': '9999px',\n '--gr-segmented-padding': '4px',\n '--gr-segmented-item-px': '16px',\n '--gr-segmented-item-py': '10px',\n '--gr-segmented-font-size': '0.9375rem',\n '--gr-segmented-line-height': '1.25rem',\n '--gr-segmented-font-weight': '600',\n '--gr-segmented-min-height': '46px',\n },\n}\nconst rootVariantStyles: Record<GrSegmentedVariant, Record<string, string>> = {\n pills: {\n '--gr-segmented-track-bg': 'var(--gr-muted)',\n '--gr-segmented-track-brd': 'var(--gr-brd)',\n '--gr-segmented-track-shadow': 'none',\n '--gr-segmented-indicator-bg': 'var(--gr-card)',\n '--gr-segmented-indicator-brd': 'color-mix(in srgb, var(--gr-card) 84%, var(--gr-brd) 16%)',\n '--gr-segmented-indicator-shadow': 'var(--gr-shadow-1), var(--gr-segmented-indicator-highlight-shadow, 0 0 0 0 transparent)',\n '--gr-segmented-item-color': 'var(--gr-muted-fg)',\n '--gr-segmented-item-selected-color': 'var(--gr-fg)',\n '--gr-segmented-item-hover-color': 'var(--gr-fg)',\n },\n button: {\n '--gr-segmented-track-bg': 'var(--gr-card)',\n '--gr-segmented-track-brd': 'var(--gr-brd)',\n '--gr-segmented-track-shadow': 'var(--gr-shadow-1)',\n '--gr-segmented-indicator-bg': 'var(--gr-primary)',\n '--gr-segmented-indicator-brd': 'color-mix(in srgb, var(--gr-primary) 88%, var(--gr-brd) 12%)',\n '--gr-segmented-indicator-shadow': 'var(--gr-shadow-2)',\n '--gr-segmented-item-color': 'var(--gr-muted-fg)',\n '--gr-segmented-item-selected-color': 'var(--gr-primary-fg)',\n '--gr-segmented-item-hover-color': 'var(--gr-fg)',\n },\n}\nexport function grSegmentedRootClass(options: {\n variant: GrSegmentedVariant\n orientation: GrSegmentedOrientation\n block: boolean\n disabled: boolean\n}): string {\n return [\n rootBaseClass,\n rootOrientationClassMap[options.orientation],\n rootVariantClassMap[options.variant],\n options.block ? rootBlockClass : '',\n options.disabled ? rootDisabledClass : '',\n ].filter(Boolean).join(' ')\n}\n/**\n * Радиус дорожки в вертикали — пилюля **одной строки**, а не всей колонки.\n * `9999px` выверен под короткий горизонтальный ряд; на высокой колонке он\n * превращает дорожку в эллипс. Формула повторяет высоту сегмента, поэтому\n * скругление у колонки ровно такое же, как у ряда, и сегменты внутри остаются\n * пилюлями: они считают свой радиус от этого же значения.\n */\nconst verticalRadiusStyle = {\n '--gr-segmented-radius': 'calc(var(--gr-segmented-min-height) / 2 + var(--gr-segmented-padding))',\n}\n\nexport function grSegmentedRootStyle(options: {\n variant: GrSegmentedVariant\n size: GrSegmentedSize\n orientation: GrSegmentedOrientation\n}): Record<string, string> {\n return {\n ...rootSizeStyles[options.size],\n ...rootVariantStyles[options.variant],\n ...(options.orientation === 'vertical' ? verticalRadiusStyle : {}),\n }\n}\nexport function grSegmentedIndicatorClass(variant: GrSegmentedVariant): string {\n return [indicatorBaseClass, indicatorVariantClassMap[variant]].join(' ')\n}\nexport function grSegmentedItemClass(options: {\n variant: GrSegmentedVariant\n selected: boolean\n disabled: boolean\n iconOnly: boolean\n}): string {\n return [\n itemBaseClass,\n itemVariantClassMap[options.variant],\n options.selected ? itemSelectedClass : '',\n options.disabled ? itemDisabledClass : itemEnabledClass,\n options.iconOnly ? iconOnlyClass : '',\n ].filter(Boolean).join(' ')\n}\nexport const grSegmentedItemLabelClass = itemLabelClass\nexport const grSegmentedItemIconClass = itemIconClass\nexport const grSegmentedItemSpinnerClass = itemSpinnerClass\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n iconOnlyClass,\n indicatorBaseClass,\n indicatorVariantClassMap,\n itemBaseClass,\n itemDisabledClass,\n itemEnabledClass,\n itemIconClass,\n itemLabelClass,\n itemSpinnerClass,\n itemSelectedClass,\n itemVariantClassMap,\n rootBaseClass,\n rootBlockClass,\n rootDisabledClass,\n rootOrientationClassMap,\n rootVariantClassMap,\n} from './grSegmentedStyles'\n\nexport const grSegmentedClassTokens = {\n rootBaseClass: splitClassTokens(rootBaseClass),\n rootOrientationClassMap: Object.values(rootOrientationClassMap).flatMap(splitClassTokens),\n rootVariantClassMap: Object.values(rootVariantClassMap).flatMap(splitClassTokens),\n rootBlockClass: splitClassTokens(rootBlockClass),\n rootDisabledClass: splitClassTokens(rootDisabledClass),\n indicatorBaseClass: splitClassTokens(indicatorBaseClass),\n indicatorVariantClassMap: Object.values(indicatorVariantClassMap).flatMap(splitClassTokens),\n itemBaseClass: splitClassTokens(itemBaseClass),\n itemVariantClassMap: Object.values(itemVariantClassMap).flatMap(splitClassTokens),\n itemSelectedClass: splitClassTokens(itemSelectedClass),\n itemDisabledClass: splitClassTokens(itemDisabledClass),\n itemEnabledClass: splitClassTokens(itemEnabledClass),\n itemLabelClass: splitClassTokens(itemLabelClass),\n itemIconClass: splitClassTokens(itemIconClass),\n itemSpinnerClass: splitClassTokens(itemSpinnerClass),\n iconOnlyClass: splitClassTokens(iconOnlyClass),\n} as const\n\nexport const grSegmentedSafelist = [...new Set([\n ...grSegmentedClassTokens.rootBaseClass,\n ...grSegmentedClassTokens.rootOrientationClassMap,\n ...grSegmentedClassTokens.rootVariantClassMap,\n ...grSegmentedClassTokens.rootBlockClass,\n ...grSegmentedClassTokens.rootDisabledClass,\n ...grSegmentedClassTokens.indicatorBaseClass,\n ...grSegmentedClassTokens.indicatorVariantClassMap,\n ...grSegmentedClassTokens.itemBaseClass,\n ...grSegmentedClassTokens.itemVariantClassMap,\n ...grSegmentedClassTokens.itemSelectedClass,\n ...grSegmentedClassTokens.itemDisabledClass,\n ...grSegmentedClassTokens.itemEnabledClass,\n ...grSegmentedClassTokens.itemLabelClass,\n ...grSegmentedClassTokens.itemIconClass,\n ...grSegmentedClassTokens.itemSpinnerClass,\n ...grSegmentedClassTokens.iconOnlyClass,\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grSegmentedSafelist } from './safelist'\n\nexport const grSegmentedConfig = defineGranularComponent(import.meta.url, {\n name: 'GrSegmented',\n safelist: grSegmentedSafelist,\n tokenDefinitions: {\n light: {\n selector: ':root',\n tokens: { 'gr-segmented-indicator-highlight-shadow': '0 0 0 0 transparent' },\n },\n dark: {\n selector: '.dark',\n tokens: { 'gr-segmented-indicator-highlight-shadow': '0 0 0 1px rgba(248, 250, 252, 0.08)' },\n },\n },\n})\n"],"mappings":";;;AA4BA,IAAa,gBACT;;AAGJ,IAAa,0BAAkE;CAC7E,YAAY;CACZ,UAAU;AACZ;AACA,IAAa,sBAA0D;CACrE,OAAO;CACP,QAAQ;AACV;AACA,IAAa,iBAAiB;AAC9B,IAAa,oBAAoB;AACjC,IAAa,qBACT;AACJ,IAAa,2BAA+D;CAC1E,OAAO;CACP,QAAQ;AACV;AACA,IAAa,gBACT;AACJ,IAAa,sBAA0D;CACrE,OAAO;CACP,QAAQ;AACV;AACA,IAAa,oBAAoB;;;;;AAKjC,IAAa,oBAAoB;AACjC,IAAa,mBAAmB;AAChC,IAAa,iBAAiB;AAC9B,IAAa,gBAAgB;AAC7B,IAAa,mBAAmB;AAChC,IAAa,gBAAgB;AAC7B,IAAM,iBAAkE;CACtE,IAAI;EACF,yBAAyB;EACzB,0BAA0B;EAC1B,0BAA0B;EAC1B,0BAA0B;EAC1B,4BAA4B;EAC5B,8BAA8B;EAC9B,8BAA8B;EAC9B,6BAA6B;CAC/B;CACA,IAAI;EACF,yBAAyB;EACzB,0BAA0B;EAC1B,0BAA0B;EAC1B,0BAA0B;EAC1B,4BAA4B;EAC5B,8BAA8B;EAC9B,8BAA8B;EAC9B,6BAA6B;CAC/B;CACA,IAAI;EACF,yBAAyB;EACzB,0BAA0B;EAC1B,0BAA0B;EAC1B,0BAA0B;EAC1B,4BAA4B;EAC5B,8BAA8B;EAC9B,8BAA8B;EAC9B,6BAA6B;CAC/B;CACA,IAAI;EACF,yBAAyB;EACzB,0BAA0B;EAC1B,0BAA0B;EAC1B,0BAA0B;EAC1B,4BAA4B;EAC5B,8BAA8B;EAC9B,8BAA8B;EAC9B,6BAA6B;CAC/B;AACF;AACA,IAAM,oBAAwE;CAC5E,OAAO;EACL,2BAA2B;EAC3B,4BAA4B;EAC5B,+BAA+B;EAC/B,+BAA+B;EAC/B,gCAAgC;EAChC,mCAAmC;EACnC,6BAA6B;EAC7B,sCAAsC;EACtC,mCAAmC;CACrC;CACA,QAAQ;EACN,2BAA2B;EAC3B,4BAA4B;EAC5B,+BAA+B;EAC/B,+BAA+B;EAC/B,gCAAgC;EAChC,mCAAmC;EACnC,6BAA6B;EAC7B,sCAAsC;EACtC,mCAAmC;CACrC;AACF;AACA,SAAgB,qBAAqB,SAK1B;CACT,OAAO;EACL;EACA,wBAAwB,QAAQ;EAChC,oBAAoB,QAAQ;EAC5B,QAAQ,QAAQ,iBAAiB;EACjC,QAAQ,WAAW,oBAAoB;CACzC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC5B;;;;;;;;AAQA,IAAM,sBAAsB,EAC1B,yBAAyB,yEAC3B;AAEA,SAAgB,qBAAqB,SAIV;CACzB,OAAO;EACL,GAAG,eAAe,QAAQ;EAC1B,GAAG,kBAAkB,QAAQ;EAC7B,GAAI,QAAQ,gBAAgB,aAAa,sBAAsB,CAAC;CAClE;AACF;AACA,SAAgB,0BAA0B,SAAqC;CAC7E,OAAO,CAAC,oBAAoB,yBAAyB,QAAQ,CAAC,CAAC,KAAK,GAAG;AACzE;AACA,SAAgB,qBAAqB,SAK1B;CACT,OAAO;EACL;EACA,oBAAoB,QAAQ;EAC5B,QAAQ,WAAW,oBAAoB;EACvC,QAAQ,WAAW,oBAAoB;EACvC,QAAQ,WAAW,gBAAgB;CACrC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC5B;AACA,IAAa,4BAA4B;AACzC,IAAa,2BAA2B;AACxC,IAAa,8BAA8B;;;ACtK3C,IAAa,yBAAyB;CACpC,eAAe,iBAAiB,aAAa;CAC7C,yBAAyB,OAAO,OAAO,uBAAuB,CAAC,CAAC,QAAQ,gBAAgB;CACxF,qBAAqB,OAAO,OAAO,mBAAmB,CAAC,CAAC,QAAQ,gBAAgB;CAChF,gBAAgB,iBAAiB,cAAc;CAC/C,mBAAmB,iBAAiB,iBAAiB;CACrD,oBAAoB,iBAAiB,kBAAkB;CACvD,0BAA0B,OAAO,OAAO,wBAAwB,CAAC,CAAC,QAAQ,gBAAgB;CAC1F,eAAe,iBAAiB,aAAa;CAC7C,qBAAqB,OAAO,OAAO,mBAAmB,CAAC,CAAC,QAAQ,gBAAgB;CAChF,mBAAmB,iBAAiB,iBAAiB;CACrD,mBAAmB,iBAAiB,iBAAiB;CACrD,kBAAkB,iBAAiB,gBAAgB;CACnD,gBAAgB,iBAAiB,cAAc;CAC/C,eAAe,iBAAiB,aAAa;CAC7C,kBAAkB,iBAAiB,gBAAgB;CACnD,eAAe,iBAAiB,aAAa;AAC/C;AAEA,IAAa,sBAAsB,CAAC,mBAAG,IAAI,IAAI;CAC7C,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;CAC1B,GAAG,uBAAuB;AAC5B,CAAC,CAAC;;;ACpDF,IAAa,oBAAoB,wBAAwB,OAAO,KAAK,KAAK;CACxE,MAAM;CACN,UAAU;CACV,kBAAkB;EAChB,OAAO;GACL,UAAU;GACV,QAAQ,EAAE,2CAA2C,sBAAsB;EAC7E;EACA,MAAM;GACJ,UAAU;GACV,QAAQ,EAAE,2CAA2C,sCAAsC;EAC7F;CACF;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-uzUuosv7.js","names":[],"sources":["../../src/components/GrDropdown/safelist.ts","../../src/components/GrDropdown/config.ts"],"sourcesContent":["import { flattenTransitionTokens, splitClassTokens } from '../shared/classTokens'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport {\n dropdownContentBaseClass,\n originClassByPlacement,\n} from './grDropdownStyles'\n\n// И динамические токены (`resolvedPlacement`), и литералы отделки панели:\n// `grDropdownStyles.ts` уезжает в общий `dist/chunks/`, вне области скана\n// компонента — гейт `src/__tests__/safelist.test.ts`.\nexport const grDropdownSafelist = [...new Set([\n ...Object.values(originClassByPlacement).flatMap(v => splitClassTokens(v ?? '')),\n ...splitClassTokens(dropdownContentBaseClass),\n // Набор перехода панели общий на пять компонентов и живёт безадресным\n // модулем в `shared/`: в `dist` он лежит в общем чанке, который пресет не\n // сканирует, поэтому объявить его обязан каждый потребитель.\n ...flattenTransitionTokens(panelPopTransition),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grDropdownSafelist } from './safelist'\n\nexport const grDropdownConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDropdown',\n safelist: grDropdownSafelist,\n})"],"mappings":";;;;;AAUA,IAAa,qBAAqB,CAAC,mBAAG,IAAI,IAAI;CAC5C,GAAG,OAAO,OAAO,sBAAsB,CAAC,CAAC,SAAQ,MAAK,iBAAiB,KAAK,EAAE,CAAC;CAC/E,GAAG,iBAAiB,wBAAwB;CAI5C,GAAG,wBAAwB,kBAAkB;AAC/C,CAAC,CAAC;;;ACbF,IAAa,mBAAmB,wBAAwB,OAAO,KAAK,KAAK;CACvE,MAAM;CACN,UAAU;AACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"config-uzUuosv7.js","names":[],"sources":["../../src/components/GrDropdown/safelist.ts","../../src/components/GrDropdown/config.ts"],"sourcesContent":["import { flattenTransitionTokens, splitClassTokens } from '../shared/classTokens'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport {\n dropdownContentBaseClass,\n originClassByPlacement,\n} from './grDropdownStyles'\n\n// И динамические токены (`resolvedPlacement`), и литералы отделки панели:\n// `grDropdownStyles.ts` уезжает в общий `dist/chunks/`, вне области скана\n// компонента — гейт `src/__tests__/safelist.test.ts`.\nexport const grDropdownSafelist = [...new Set([\n ...Object.values(originClassByPlacement).flatMap(v => splitClassTokens(v ?? '')),\n ...splitClassTokens(dropdownContentBaseClass),\n // Набор перехода панели общий на пять компонентов и живёт безадресным\n // модулем в `shared/`: в `dist` он лежит в общем чанке, который пресет не\n // сканирует, поэтому объявить его обязан каждый потребитель.\n ...flattenTransitionTokens(panelPopTransition),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grDropdownSafelist } from './safelist'\n\nexport const grDropdownConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDropdown',\n safelist: grDropdownSafelist,\n})\n"],"mappings":";;;;;AAUA,IAAa,qBAAqB,CAAC,mBAAG,IAAI,IAAI;CAC5C,GAAG,OAAO,OAAO,sBAAsB,CAAC,CAAC,SAAQ,MAAK,iBAAiB,KAAK,EAAE,CAAC;CAC/E,GAAG,iBAAiB,wBAAwB;CAI5C,GAAG,wBAAwB,kBAAkB;AAC/C,CAAC,CAAC;;;ACbF,IAAa,mBAAmB,wBAAwB,OAAO,KAAK,KAAK;CACvE,MAAM;CACN,UAAU;AACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-CTbuwcYs.js","names":[],"sources":["../../src/components/GrConfigProvider/context.ts"],"sourcesContent":["import { computed, getCurrentInstance, inject, type ComputedRef, type InjectionKey } from 'vue'\n\nimport type { GrComponentDefaultsRegistry } from '../../composables/useGrComponentConfig'\n\n/**\n * Контекст `GrConfigProvider` — глобальные дефолты для вложенных GR-компонентов:\n * размер контролов и per-component дефолтные пропсы.\n *\n * Компоненты читают его через {@link useGrConfig} (или хелперы ниже) и используют\n * как fallback, когда соответствующий проп не задан на самом компоненте. Провайдер\n * можно вкладывать — дочерний мержится поверх родительского.\n */\n\n/**\n * Размеры, которыми оперирует провайдер. Это «размеры контролов» — общий\n * знаменатель формных компонентов, а не объединение всех size-шкал пакета\n * (у оверлеев есть свои `xl`/`full`, у слайдера нет `xs`).\n */\nexport const GR_COMPONENT_SIZES = ['xs', 'sm', 'md', 'lg'] as const\n\nexport type GrComponentSize = typeof GR_COMPONENT_SIZES[number]\n\n/**\n * Реестр компонентов с настраиваемыми через конфиг пропами.\n *\n * Объявлен в `composables/useGrComponentConfig` — там же, куда его дополняют\n * и компоненты пакета, и companion-пакеты. Здесь только реэкспорт для тех, кто\n * работает с контекстом провайдера напрямую.\n */\nexport type { GrComponentDefaultsRegistry }\n\n/** Имя компонента, у которого есть настраиваемые через конфиг пропы. */\nexport type GrConfigurableComponent = keyof GrComponentDefaultsRegistry\n\n/**\n * Дефолтные пропсы по имени компонента: `{ GrButton: { variant: 'secondary' } }`.\n *\n * Набор ключей закрыт реестром, а не `Record<string, unknown>`: через конфиг\n * должны настраиваться только «оформительские» пропы. Пустить туда что угодно —\n * значит разрешить задать глобальный `modelValue` или обработчик и получить баг,\n * который ищется часами.\n */\nexport type GrComponentDefaults = {\n [TComponent in GrConfigurableComponent]?: Partial<GrComponentDefaultsRegistry[TComponent]>\n}\n\ntype GrDefaultsOf<TComponent extends GrConfigurableComponent> = Partial<GrComponentDefaultsRegistry[TComponent]>\n\nexport interface GrConfigContext {\n /** Дефолтный размер контролов (если проп `size` не задан на компоненте). */\n size: ComputedRef<GrComponentSize | undefined>\n /** Дефолтные пропсы по компонентам. */\n componentDefaults: ComputedRef<GrComponentDefaults>\n /**\n * Тема поддерева (`data-theme`). Необязательна: тип публичный, и контекст\n * строят руками — например хост императивных диалогов.\n */\n theme?: ComputedRef<string | undefined>\n /**\n * Куда монтируются оверлеи поддерева (`usePortalTarget`). Необязательно, как\n * и `theme`: контекст строят руками — например хост императивных диалогов.\n */\n portalTarget?: ComputedRef<string | HTMLElement | undefined>\n}\n\nexport const GR_CONFIG_KEY: InjectionKey<GrConfigContext> = Symbol('gr-config')\n\n/**\n * Пустой конфиг: когда провайдера в дереве нет, всё разрешается в `undefined`,\n * а компоненты падают на собственные дефолты.\n *\n * `computed` здесь не роскошь: контекст типизирован рефами, и потребитель вправе\n * прогнать `size` через `unref()` или `watch()`. Плоский объект `{ value: … }`\n * не пройдёт проверку `isRef`, и такой код молча получит сам объект вместо\n * значения — поэтому «просто константа» тут не подходит.\n *\n * А вот пустые значения заморожены, и это не педантизм: `computed` без\n * зависимостей вычисляется один раз и отдаёт **один и тот же** объект всем\n * компонентам без провайдера. Незамороженный, он позволил бы одному потребителю\n * записать в него ключ и тем самым подменить дефолты всему приложению.\n */\nconst EMPTY_COMPONENT_DEFAULTS: GrComponentDefaults = Object.freeze({})\n\nconst EMPTY_CONFIG: GrConfigContext = {\n size: computed(() => undefined),\n componentDefaults: computed(() => EMPTY_COMPONENT_DEFAULTS),\n theme: computed(() => undefined),\n portalTarget: computed(() => undefined),\n}\n\n/** Возвращает ближайший `GrConfigProvider` или пустой конфиг, если провайдера нет. */\nexport function useGrConfig(): GrConfigContext {\n return inject(GR_CONFIG_KEY, EMPTY_CONFIG)\n}\n\n/**\n * Источник конфига для {@link resolveGrConfig}: сам контекст, `AppContext` или\n * инстанс компонента — у двух последних читается `provides`.\n */\nexport type GrConfigSource = GrConfigContext | { provides?: Record<symbol | string, unknown> }\n\nfunction isGrConfigContext(source: unknown): source is GrConfigContext {\n return typeof (source as GrConfigContext | null)?.componentDefaults?.value === 'object'\n}\n\n/**\n * Конфиг там, где `inject` недоступен — вне `setup`: в директивах, императивных\n * сервисах, утилитах. Порядок: явный контекст → `provides` источника → `inject`\n * (если есть активный инстанс) → пустой конфиг.\n *\n * Важно понимать границу: `provides` у `AppContext` содержит только то, что\n * роздано через `app.provide()`. Значения от `<GrConfigProvider>` живут в дереве\n * компонентов, и достать их можно лишь оттуда, где это дерево ещё есть — то есть\n * захватом в `setup`. Просто передать `appContext` в отрыве от дерева\n * недостаточно; см. `SPEC-GrConfig-resolver.md`.\n */\nexport function resolveGrConfig(source?: GrConfigSource | null): GrConfigContext {\n if (isGrConfigContext(source)) return source\n\n const provides = source?.provides\n if (provides) {\n const fromProvides = provides[GR_CONFIG_KEY as symbol] as GrConfigContext | undefined\n return isGrConfigContext(fromProvides) ? fromProvides : EMPTY_CONFIG\n }\n\n if (getCurrentInstance()) return inject(GR_CONFIG_KEY, EMPTY_CONFIG)\n\n return EMPTY_CONFIG\n}\n\nexport type UseGrComponentSizeOptions<TSize extends string> = {\n /**\n * Имя компонента, чтобы учесть точечный `componentDefaults[Component].size`.\n * Без него читается только глобальный `size` провайдера.\n */\n component?: GrConfigurableComponent\n /** Размер, когда ни проп, ни конфиг ничего не дали. По умолчанию `md`. */\n fallback?: TSize\n /**\n * Размеры, которые компонент реально умеет. Значение из конфига вне этого\n * списка игнорируется в пользу `fallback`.\n *\n * Обязателен для компонентов, у которых size-шкала уже общей (`GrSlider`,\n * `GrRating`, `GrSwitch`, `GrLink`, `GrStatistic` не знают про `xs`): без него\n * `<GrConfigProvider size=\"xs\">` дал бы `sizeMap['xs'] === undefined`, то есть\n * компонент без размерных классов — молча, без ошибки сборки.\n */\n supported?: readonly TSize[]\n}\n\n// Предупреждаем один раз на уникальную пару «размер + список поддерживаемых»,\n// иначе список из сотни контролов зальёт консоль одинаковыми сообщениями.\nconst warnedUnsupportedSizes = new Set<string>()\n\n/** Сброс дедупликации предупреждений. Внутреннее API — нужно тестам. */\nexport function resetUnsupportedSizeWarnings(): void {\n warnedUnsupportedSizes.clear()\n}\n\nfunction warnUnsupportedSize(size: string, supported: readonly string[]): void {\n const key = `${size}|${supported.join(',')}`\n if (warnedUnsupportedSizes.has(key)) return\n warnedUnsupportedSizes.add(key)\n\n console.warn(\n `[granularity] GrConfigProvider size=\"${size}\" is not supported by this component `\n + `(supported: ${supported.join(', ')}); falling back to its own default.`,\n )\n}\n\n/**\n * Эффективный размер компонента. Приоритет:\n * локальный проп → `componentDefaults[Component].size` → глобальный `size`\n * провайдера → `fallback`. Точечная настройка компонента должна побеждать\n * общую — иначе `componentDefaults` нельзя было бы использовать как исключение\n * из глобального правила.\n *\n * Передавайте `size` геттером, чтобы сохранить реактивность.\n *\n * Локальный проп не проверяется по `supported`: он уже сужен типом пропа самого\n * компонента, и передать туда лишнее — явная ошибка вызывающего кода. Проверка\n * нужна конфигу: это глобальный канал, который не знает, кто его читает.\n */\nexport function useGrComponentSize<TSize extends string = GrComponentSize>(\n localSize: () => TSize | undefined,\n options: UseGrComponentSizeOptions<TSize> = {},\n): ComputedRef<TSize> {\n // Все size-шкалы пакета содержат `md`, поэтому он безопасен как общий дефолт.\n const { component, fallback = 'md' as TSize, supported } = options\n const config = useGrConfig()\n\n return computed(() => {\n const local = localSize()\n if (local !== undefined) return local\n\n const fromComponentDefaults = component\n ? (config.componentDefaults.value[component] as { size?: TSize } | undefined)?.size\n : undefined\n\n const fromConfig = fromComponentDefaults ?? config.size.value\n if (fromConfig === undefined) return fallback\n\n if (supported && !supported.includes(fromConfig as TSize)) {\n // Текст предупреждения и его дедуп живут прямо под гардом, а не в общей\n // функции: `__GR_DEV__` разворачивается в условие на сборке, бандлер\n // потребителя сворачивает его в `false` и выкидывает ветку целиком.\n // Почему не рантайм-хелпер — в `vite.config.ts`, у самого `define`.\n if (__GR_DEV__)\n warnUnsupportedSize(fromConfig, supported)\n return fallback\n }\n\n return fromConfig as TSize\n })\n}\n\n/** Дефолтные пропсы конкретного компонента из ближайшего провайдера. */\nexport function useGrComponentDefaults<TComponent extends GrConfigurableComponent>(\n name: TComponent,\n): ComputedRef<GrDefaultsOf<TComponent>> {\n const config = useGrConfig()\n return computed(() => (config.componentDefaults.value[name] ?? EMPTY_COMPONENT_DEFAULTS) as GrDefaultsOf<TComponent>)\n}\n\n/**\n * Эффективное значение «оформительского» пропа: локальный проп →\n * `componentDefaults[Component][prop]` → собственный дефолт компонента.\n *\n * Обязательное условие на стороне компонента: у такого пропа в `withDefaults`\n * должен стоять `undefined`, а «настоящий» дефолт — переехать сюда, в `fallback`.\n * Иначе конфиг не сработает никогда: Vue отдаёт `props.x` уже с подставленным\n * дефолтом, и отличить «пользователь передал значение» от «сработал дефолт»\n * изнутри компонента невозможно.\n */\nexport function useGrComponentProp<\n TComponent extends GrConfigurableComponent,\n TProp extends keyof GrDefaultsOf<TComponent>,\n>(\n component: TComponent,\n prop: TProp,\n localValue: () => GrDefaultsOf<TComponent>[TProp],\n fallback: NonNullable<GrDefaultsOf<TComponent>[TProp]>,\n): ComputedRef<NonNullable<GrDefaultsOf<TComponent>[TProp]>> {\n const config = useGrConfig()\n\n return computed(() => {\n const local = localValue()\n if (local !== undefined) return local as NonNullable<GrDefaultsOf<TComponent>[TProp]>\n\n // Промежуточная аннотация (а не `as`) нужна, чтобы TS не разворачивал\n // `GrComponentDefaults[TComponent]` в объединение всех блоков — по нему\n // generic-ключ `TProp` уже не проиндексировать.\n const defaults: GrDefaultsOf<TComponent> | undefined = config.componentDefaults.value[component]\n return defaults?.[prop] ?? fallback\n })\n}\n\n/**\n * Атрибут темы для **телепортируемого** корня панели.\n *\n * Панель уезжает в `body`, то есть вне DOM-поддерева провайдера, и `data-theme`\n * с его обёртки на неё не наследуется. В дереве компонентов она при этом\n * остаётся внутри — `inject` работает, — поэтому тему панель ставит себе сама.\n * Без этого «тёмный остров» ломался бы на первом же открытом дропдауне.\n *\n * ```vue\n * <teleport to=\"body\">\n * <div v-bind=\"themeAttrs\">…</div>\n * </teleport>\n * ```\n */\nexport function useGrThemeAttrs(): ComputedRef<{ 'data-theme'?: string }> {\n const config = useGrConfig()\n return computed(() => {\n const theme = config.theme?.value\n return theme ? { 'data-theme': theme } : {}\n })\n}\n"],"mappings":";;AAiEA,IAAa,gBAA+C,OAAO,WAAW;;;;;;;;;;;;;;;AAgB9E,IAAM,2BAAgD,OAAO,OAAO,CAAC,CAAC;AAEtE,IAAM,eAAgC;CACpC,MAAM,eAAe,KAAA,CAAS;CAC9B,mBAAmB,eAAe,wBAAwB;CAC1D,OAAO,eAAe,KAAA,CAAS;CAC/B,cAAc,eAAe,KAAA,CAAS;AACxC;;AAGA,SAAgB,cAA+B;CAC7C,OAAO,OAAO,eAAe,YAAY;AAC3C;AAQA,SAAS,kBAAkB,QAA4C;CACrE,OAAO,OAAQ,QAAmC,mBAAmB,UAAU;AACjF;;;;;;;;;;;;AAaA,SAAgB,gBAAgB,QAAiD;CAC/E,IAAI,kBAAkB,MAAM,GAAG,OAAO;CAEtC,MAAM,WAAW,QAAQ;CACzB,IAAI,UAAU;EACZ,MAAM,eAAe,SAAS;EAC9B,OAAO,kBAAkB,YAAY,IAAI,eAAe;CAC1D;CAEA,IAAI,mBAAmB,GAAG,OAAO,OAAO,eAAe,YAAY;CAEnE,OAAO;AACT;AAwBA,IAAM,yCAAyB,IAAI,IAAY;AAO/C,SAAS,oBAAoB,MAAc,WAAoC;CAC7E,MAAM,MAAM,GAAG,KAAK,GAAG,UAAU,KAAK,GAAG;CACzC,IAAI,uBAAuB,IAAI,GAAG,GAAG;CACrC,uBAAuB,IAAI,GAAG;CAE9B,QAAQ,KACN,wCAAwC,KAAK,mDAC5B,UAAU,KAAK,IAAI,EAAE,oCACxC;AACF;;;;;;;;;;;;;;AAeA,SAAgB,mBACd,WACA,UAA4C,CAAC,GACzB;CAEpB,MAAM,EAAE,WAAW,WAAW,MAAe,cAAc;CAC3D,MAAM,SAAS,YAAY;CAE3B,OAAO,eAAe;EACpB,MAAM,QAAQ,UAAU;EACxB,IAAI,UAAU,KAAA,GAAW,OAAO;EAMhC,MAAM,cAJwB,YACzB,OAAO,kBAAkB,MAAM,UAAU,EAAmC,OAC7E,KAAA,MAEwC,OAAO,KAAK;EACxD,IAAI,eAAe,KAAA,GAAW,OAAO;EAErC,IAAI,aAAa,CAAC,UAAU,SAAS,UAAmB,GAAG;GAKzD,IAAA,OAAA,YAAA,eAAA,QAAA,IAAA,aAAA,cACE,oBAAoB,YAAY,SAAS;GAC3C,OAAO;EACT;EAEA,OAAO;CACT,CAAC;AACH;;AAGA,SAAgB,uBACd,MACuC;CACvC,MAAM,SAAS,YAAY;CAC3B,OAAO,eAAgB,OAAO,kBAAkB,MAAM,SAAS,wBAAqD;AACtH;;;;;;;;;;;AAYA,SAAgB,mBAId,WACA,MACA,YACA,UAC2D;CAC3D,MAAM,SAAS,YAAY;CAE3B,OAAO,eAAe;EACpB,MAAM,QAAQ,WAAW;EACzB,IAAI,UAAU,KAAA,GAAW,OAAO;EAMhC,OADuD,OAAO,kBAAkB,MAAM,UAC/E,GAAW,SAAS;CAC7B,CAAC;AACH;;;;;;;;;;;;;;;AAgBA,SAAgB,kBAA0D;CACxE,MAAM,SAAS,YAAY;CAC3B,OAAO,eAAe;EACpB,MAAM,QAAQ,OAAO,OAAO;EAC5B,OAAO,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;CAC5C,CAAC;AACH"}
|
|
1
|
+
{"version":3,"file":"context-CTbuwcYs.js","names":[],"sources":["../../src/components/GrConfigProvider/context.ts"],"sourcesContent":["import { computed, getCurrentInstance, inject, type ComputedRef, type InjectionKey } from 'vue'\n\nimport type { GrComponentDefaultsRegistry } from '../../composables/useGrComponentConfig'\n\n/**\n * Контекст `GrConfigProvider` — глобальные дефолты для вложенных GR-компонентов:\n * размер контролов и per-component дефолтные пропсы.\n *\n * Компоненты читают его через {@link useGrConfig} (или хелперы ниже) и используют\n * как fallback, когда соответствующий проп не задан на самом компоненте. Провайдер\n * можно вкладывать — дочерний мержится поверх родительского.\n */\n\n/**\n * Размеры, которыми оперирует провайдер. Это «размеры контролов» — общий\n * знаменатель формных компонентов, а не объединение всех size-шкал пакета\n * (у оверлеев есть свои `xl`/`full`, у слайдера нет `xs`).\n */\nexport const GR_COMPONENT_SIZES = ['xs', 'sm', 'md', 'lg'] as const\n\nexport type GrComponentSize = typeof GR_COMPONENT_SIZES[number]\n\n/**\n * Реестр компонентов с настраиваемыми через конфиг пропами.\n *\n * Объявлен в `composables/useGrComponentConfig` — там же, куда его дополняют\n * и компоненты пакета, и companion-пакеты. Здесь только реэкспорт для тех, кто\n * работает с контекстом провайдера напрямую.\n */\nexport type { GrComponentDefaultsRegistry }\n\n/** Имя компонента, у которого есть настраиваемые через конфиг пропы. */\nexport type GrConfigurableComponent = keyof GrComponentDefaultsRegistry\n\n/**\n * Дефолтные пропсы по имени компонента: `{ GrButton: { variant: 'secondary' } }`.\n *\n * Набор ключей закрыт реестром, а не `Record<string, unknown>`: через конфиг\n * должны настраиваться только «оформительские» пропы. Пустить туда что угодно —\n * значит разрешить задать глобальный `modelValue` или обработчик и получить баг,\n * который ищется часами.\n */\nexport type GrComponentDefaults = {\n [TComponent in GrConfigurableComponent]?: Partial<GrComponentDefaultsRegistry[TComponent]>\n}\n\ntype GrDefaultsOf<TComponent extends GrConfigurableComponent> = Partial<GrComponentDefaultsRegistry[TComponent]>\n\nexport interface GrConfigContext {\n /** Дефолтный размер контролов (если проп `size` не задан на компоненте). */\n size: ComputedRef<GrComponentSize | undefined>\n /** Дефолтные пропсы по компонентам. */\n componentDefaults: ComputedRef<GrComponentDefaults>\n /**\n * Тема поддерева (`data-theme`). Необязательна: тип публичный, и контекст\n * строят руками — например хост императивных диалогов.\n */\n theme?: ComputedRef<string | undefined>\n /**\n * Куда монтируются оверлеи поддерева (`usePortalTarget`). Необязательно, как\n * и `theme`: контекст строят руками — например хост императивных диалогов.\n */\n portalTarget?: ComputedRef<string | HTMLElement | undefined>\n}\n\nexport const GR_CONFIG_KEY: InjectionKey<GrConfigContext> = Symbol('gr-config')\n\n/**\n * Пустой конфиг: когда провайдера в дереве нет, всё разрешается в `undefined`,\n * а компоненты падают на собственные дефолты.\n *\n * `computed` здесь не роскошь: контекст типизирован рефами, и потребитель вправе\n * прогнать `size` через `unref()` или `watch()`. Плоский объект `{ value: … }`\n * не пройдёт проверку `isRef`, и такой код молча получит сам объект вместо\n * значения — поэтому «просто константа» тут не подходит.\n *\n * А вот пустые значения заморожены, и это не педантизм: `computed` без\n * зависимостей вычисляется один раз и отдаёт **один и тот же** объект всем\n * компонентам без провайдера. Незамороженный, он позволил бы одному потребителю\n * записать в него ключ и тем самым подменить дефолты всему приложению.\n */\nconst EMPTY_COMPONENT_DEFAULTS: GrComponentDefaults = Object.freeze({})\n\nconst EMPTY_CONFIG: GrConfigContext = {\n size: computed(() => undefined),\n componentDefaults: computed(() => EMPTY_COMPONENT_DEFAULTS),\n theme: computed(() => undefined),\n portalTarget: computed(() => undefined),\n}\n\n/** Возвращает ближайший `GrConfigProvider` или пустой конфиг, если провайдера нет. */\nexport function useGrConfig(): GrConfigContext {\n return inject(GR_CONFIG_KEY, EMPTY_CONFIG)\n}\n\n/**\n * Источник конфига для {@link resolveGrConfig}: сам контекст, `AppContext` или\n * инстанс компонента — у двух последних читается `provides`.\n */\nexport type GrConfigSource = GrConfigContext | { provides?: Record<symbol | string, unknown> }\n\nfunction isGrConfigContext(source: unknown): source is GrConfigContext {\n return typeof (source as GrConfigContext | null)?.componentDefaults?.value === 'object'\n}\n\n/**\n * Конфиг там, где `inject` недоступен — вне `setup`: в директивах, императивных\n * сервисах, утилитах. Порядок: явный контекст → `provides` источника → `inject`\n * (если есть активный инстанс) → пустой конфиг.\n *\n * Важно понимать границу: `provides` у `AppContext` содержит только то, что\n * роздано через `app.provide()`. Значения от `<GrConfigProvider>` живут в дереве\n * компонентов, и достать их можно лишь оттуда, где это дерево ещё есть — то есть\n * захватом в `setup`. Просто передать `appContext` в отрыве от дерева\n * недостаточно; см. `SPEC-GrConfig-resolver.md`.\n */\nexport function resolveGrConfig(source?: GrConfigSource | null): GrConfigContext {\n if (isGrConfigContext(source))\n return source\n\n const provides = source?.provides\n if (provides) {\n const fromProvides = provides[GR_CONFIG_KEY as symbol] as GrConfigContext | undefined\n return isGrConfigContext(fromProvides) ? fromProvides : EMPTY_CONFIG\n }\n\n if (getCurrentInstance())\n return inject(GR_CONFIG_KEY, EMPTY_CONFIG)\n\n return EMPTY_CONFIG\n}\n\nexport type UseGrComponentSizeOptions<TSize extends string> = {\n /**\n * Имя компонента, чтобы учесть точечный `componentDefaults[Component].size`.\n * Без него читается только глобальный `size` провайдера.\n */\n component?: GrConfigurableComponent\n /** Размер, когда ни проп, ни конфиг ничего не дали. По умолчанию `md`. */\n fallback?: TSize\n /**\n * Размеры, которые компонент реально умеет. Значение из конфига вне этого\n * списка игнорируется в пользу `fallback`.\n *\n * Обязателен для компонентов, у которых size-шкала уже общей (`GrSlider`,\n * `GrRating`, `GrSwitch`, `GrLink`, `GrStatistic` не знают про `xs`): без него\n * `<GrConfigProvider size=\"xs\">` дал бы `sizeMap['xs'] === undefined`, то есть\n * компонент без размерных классов — молча, без ошибки сборки.\n */\n supported?: readonly TSize[]\n}\n\n// Предупреждаем один раз на уникальную пару «размер + список поддерживаемых»,\n// иначе список из сотни контролов зальёт консоль одинаковыми сообщениями.\nconst warnedUnsupportedSizes = new Set<string>()\n\n/** Сброс дедупликации предупреждений. Внутреннее API — нужно тестам. */\nexport function resetUnsupportedSizeWarnings(): void {\n warnedUnsupportedSizes.clear()\n}\n\nfunction warnUnsupportedSize(size: string, supported: readonly string[]): void {\n const key = `${size}|${supported.join(',')}`\n if (warnedUnsupportedSizes.has(key))\n return\n warnedUnsupportedSizes.add(key)\n\n console.warn(\n `[granularity] GrConfigProvider size=\"${size}\" is not supported by this component `\n + `(supported: ${supported.join(', ')}); falling back to its own default.`,\n )\n}\n\n/**\n * Эффективный размер компонента. Приоритет:\n * локальный проп → `componentDefaults[Component].size` → глобальный `size`\n * провайдера → `fallback`. Точечная настройка компонента должна побеждать\n * общую — иначе `componentDefaults` нельзя было бы использовать как исключение\n * из глобального правила.\n *\n * Передавайте `size` геттером, чтобы сохранить реактивность.\n *\n * Локальный проп не проверяется по `supported`: он уже сужен типом пропа самого\n * компонента, и передать туда лишнее — явная ошибка вызывающего кода. Проверка\n * нужна конфигу: это глобальный канал, который не знает, кто его читает.\n */\nexport function useGrComponentSize<TSize extends string = GrComponentSize>(\n localSize: () => TSize | undefined,\n options: UseGrComponentSizeOptions<TSize> = {},\n): ComputedRef<TSize> {\n // Все size-шкалы пакета содержат `md`, поэтому он безопасен как общий дефолт.\n const { component, fallback = 'md' as TSize, supported } = options\n const config = useGrConfig()\n\n return computed(() => {\n const local = localSize()\n if (local !== undefined)\n return local\n\n const fromComponentDefaults = component\n ? (config.componentDefaults.value[component] as { size?: TSize } | undefined)?.size\n : undefined\n\n const fromConfig = fromComponentDefaults ?? config.size.value\n if (fromConfig === undefined)\n return fallback\n\n if (supported && !supported.includes(fromConfig as TSize)) {\n // Текст предупреждения и его дедуп живут прямо под гардом, а не в общей\n // функции: `__GR_DEV__` разворачивается в условие на сборке, бандлер\n // потребителя сворачивает его в `false` и выкидывает ветку целиком.\n // Почему не рантайм-хелпер — в `vite.config.ts`, у самого `define`.\n if (__GR_DEV__)\n warnUnsupportedSize(fromConfig, supported)\n return fallback\n }\n\n return fromConfig as TSize\n })\n}\n\n/** Дефолтные пропсы конкретного компонента из ближайшего провайдера. */\nexport function useGrComponentDefaults<TComponent extends GrConfigurableComponent>(\n name: TComponent,\n): ComputedRef<GrDefaultsOf<TComponent>> {\n const config = useGrConfig()\n return computed(() => (config.componentDefaults.value[name] ?? EMPTY_COMPONENT_DEFAULTS) as GrDefaultsOf<TComponent>)\n}\n\n/**\n * Эффективное значение «оформительского» пропа: локальный проп →\n * `componentDefaults[Component][prop]` → собственный дефолт компонента.\n *\n * Обязательное условие на стороне компонента: у такого пропа в `withDefaults`\n * должен стоять `undefined`, а «настоящий» дефолт — переехать сюда, в `fallback`.\n * Иначе конфиг не сработает никогда: Vue отдаёт `props.x` уже с подставленным\n * дефолтом, и отличить «пользователь передал значение» от «сработал дефолт»\n * изнутри компонента невозможно.\n */\nexport function useGrComponentProp<\n TComponent extends GrConfigurableComponent,\n TProp extends keyof GrDefaultsOf<TComponent>,\n>(\n component: TComponent,\n prop: TProp,\n localValue: () => GrDefaultsOf<TComponent>[TProp],\n fallback: NonNullable<GrDefaultsOf<TComponent>[TProp]>,\n): ComputedRef<NonNullable<GrDefaultsOf<TComponent>[TProp]>> {\n const config = useGrConfig()\n\n return computed(() => {\n const local = localValue()\n if (local !== undefined)\n return local as NonNullable<GrDefaultsOf<TComponent>[TProp]>\n\n // Промежуточная аннотация (а не `as`) нужна, чтобы TS не разворачивал\n // `GrComponentDefaults[TComponent]` в объединение всех блоков — по нему\n // generic-ключ `TProp` уже не проиндексировать.\n const defaults: GrDefaultsOf<TComponent> | undefined = config.componentDefaults.value[component]\n return defaults?.[prop] ?? fallback\n })\n}\n\n/**\n * Атрибут темы для **телепортируемого** корня панели.\n *\n * Панель уезжает в `body`, то есть вне DOM-поддерева провайдера, и `data-theme`\n * с его обёртки на неё не наследуется. В дереве компонентов она при этом\n * остаётся внутри — `inject` работает, — поэтому тему панель ставит себе сама.\n * Без этого «тёмный остров» ломался бы на первом же открытом дропдауне.\n *\n * ```vue\n * <teleport to=\"body\">\n * <div v-bind=\"themeAttrs\">…</div>\n * </teleport>\n * ```\n */\nexport function useGrThemeAttrs(): ComputedRef<{ 'data-theme'?: string }> {\n const config = useGrConfig()\n return computed(() => {\n const theme = config.theme?.value\n return theme ? { 'data-theme': theme } : {}\n })\n}\n"],"mappings":";;AAiEA,IAAa,gBAA+C,OAAO,WAAW;;;;;;;;;;;;;;;AAgB9E,IAAM,2BAAgD,OAAO,OAAO,CAAC,CAAC;AAEtE,IAAM,eAAgC;CACpC,MAAM,eAAe,KAAA,CAAS;CAC9B,mBAAmB,eAAe,wBAAwB;CAC1D,OAAO,eAAe,KAAA,CAAS;CAC/B,cAAc,eAAe,KAAA,CAAS;AACxC;;AAGA,SAAgB,cAA+B;CAC7C,OAAO,OAAO,eAAe,YAAY;AAC3C;AAQA,SAAS,kBAAkB,QAA4C;CACrE,OAAO,OAAQ,QAAmC,mBAAmB,UAAU;AACjF;;;;;;;;;;;;AAaA,SAAgB,gBAAgB,QAAiD;CAC/E,IAAI,kBAAkB,MAAM,GAC1B,OAAO;CAET,MAAM,WAAW,QAAQ;CACzB,IAAI,UAAU;EACZ,MAAM,eAAe,SAAS;EAC9B,OAAO,kBAAkB,YAAY,IAAI,eAAe;CAC1D;CAEA,IAAI,mBAAmB,GACrB,OAAO,OAAO,eAAe,YAAY;CAE3C,OAAO;AACT;AAwBA,IAAM,yCAAyB,IAAI,IAAY;AAO/C,SAAS,oBAAoB,MAAc,WAAoC;CAC7E,MAAM,MAAM,GAAG,KAAK,GAAG,UAAU,KAAK,GAAG;CACzC,IAAI,uBAAuB,IAAI,GAAG,GAChC;CACF,uBAAuB,IAAI,GAAG;CAE9B,QAAQ,KACN,wCAAwC,KAAK,mDAC5B,UAAU,KAAK,IAAI,EAAE,oCACxC;AACF;;;;;;;;;;;;;;AAeA,SAAgB,mBACd,WACA,UAA4C,CAAC,GACzB;CAEpB,MAAM,EAAE,WAAW,WAAW,MAAe,cAAc;CAC3D,MAAM,SAAS,YAAY;CAE3B,OAAO,eAAe;EACpB,MAAM,QAAQ,UAAU;EACxB,IAAI,UAAU,KAAA,GACZ,OAAO;EAMT,MAAM,cAJwB,YACzB,OAAO,kBAAkB,MAAM,UAAU,EAAmC,OAC7E,KAAA,MAEwC,OAAO,KAAK;EACxD,IAAI,eAAe,KAAA,GACjB,OAAO;EAET,IAAI,aAAa,CAAC,UAAU,SAAS,UAAmB,GAAG;GAKzD,IAAA,OAAA,YAAA,eAAA,QAAA,IAAA,aAAA,cACE,oBAAoB,YAAY,SAAS;GAC3C,OAAO;EACT;EAEA,OAAO;CACT,CAAC;AACH;;AAGA,SAAgB,uBACd,MACuC;CACvC,MAAM,SAAS,YAAY;CAC3B,OAAO,eAAgB,OAAO,kBAAkB,MAAM,SAAS,wBAAqD;AACtH;;;;;;;;;;;AAYA,SAAgB,mBAId,WACA,MACA,YACA,UAC2D;CAC3D,MAAM,SAAS,YAAY;CAE3B,OAAO,eAAe;EACpB,MAAM,QAAQ,WAAW;EACzB,IAAI,UAAU,KAAA,GACZ,OAAO;EAMT,OADuD,OAAO,kBAAkB,MAAM,UAC/E,GAAW,SAAS;CAC7B,CAAC;AACH;;;;;;;;;;;;;;;AAgBA,SAAgB,kBAA0D;CACxE,MAAM,SAAS,YAAY;CAC3B,OAAO,eAAe;EACpB,MAAM,QAAQ,OAAO,OAAO;EAC5B,OAAO,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;CAC5C,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deltaTone-B5OoS1vo.js","names":[],"sources":["../../src/components/GrDelta/deltaTone.ts"],"sourcesContent":["/**\n * Выбор тона для величины со знаком.\n *\n * Чистая функция, а не `switch` внутри компонента: ровно этот `switch`\n * расходился по приложениям копиями, и в одной из них нулевое движение\n * красилось зелёным — как поступление.\n */\n\n/** Что считать хорошим ростом. */\nexport type GrDeltaPolarity\n /** Рост — успех: выручка, конверсия, число подписок. */\n = | 'positive-good'\n /** Рост — проблема: себестоимость, время отклика, отток. */\n | 'negative-good'\n /** Знак ничего не говорит о качестве: сальдо, смещение, разница координат. */\n | 'none'\n\nexport type GrDeltaTone = 'success' | 'danger' | 'neutral'\n\n/**\n * Тон величины по её знаку и полярности.\n *\n * Ноль нейтрален при любой полярности: «не изменилось» — третье состояние, и\n * двумя цветами его не выразить. `null` величины нет вовсе — тона у неё тоже\n * нет, это решает вызывающий.\n */\nexport function deltaTone(value: number, polarity: GrDeltaPolarity = 'positive-good'): GrDeltaTone {\n if (polarity === 'none' || value === 0 || Number.isNaN(value))
|
|
1
|
+
{"version":3,"file":"deltaTone-B5OoS1vo.js","names":[],"sources":["../../src/components/GrDelta/deltaTone.ts"],"sourcesContent":["/**\n * Выбор тона для величины со знаком.\n *\n * Чистая функция, а не `switch` внутри компонента: ровно этот `switch`\n * расходился по приложениям копиями, и в одной из них нулевое движение\n * красилось зелёным — как поступление.\n */\n\n/** Что считать хорошим ростом. */\nexport type GrDeltaPolarity\n /** Рост — успех: выручка, конверсия, число подписок. */\n = | 'positive-good'\n /** Рост — проблема: себестоимость, время отклика, отток. */\n | 'negative-good'\n /** Знак ничего не говорит о качестве: сальдо, смещение, разница координат. */\n | 'none'\n\nexport type GrDeltaTone = 'success' | 'danger' | 'neutral'\n\n/**\n * Тон величины по её знаку и полярности.\n *\n * Ноль нейтрален при любой полярности: «не изменилось» — третье состояние, и\n * двумя цветами его не выразить. `null` величины нет вовсе — тона у неё тоже\n * нет, это решает вызывающий.\n */\nexport function deltaTone(value: number, polarity: GrDeltaPolarity = 'positive-good'): GrDeltaTone {\n if (polarity === 'none' || value === 0 || Number.isNaN(value))\n return 'neutral'\n\n const good = polarity === 'positive-good' ? value > 0 : value < 0\n\n return good ? 'success' : 'danger'\n}\n\n/** Направление стрелки. Ноль стрелки не получает: двигаться было некуда. */\nexport function deltaDirection(value: number): 'up' | 'down' | 'flat' {\n if (Number.isNaN(value) || value === 0)\n return 'flat'\n return value > 0 ? 'up' : 'down'\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,UAAU,OAAe,WAA4B,iBAA8B;CACjG,IAAI,aAAa,UAAU,UAAU,KAAK,OAAO,MAAM,KAAK,GAC1D,OAAO;CAIT,QAFa,aAAa,kBAAkB,QAAQ,IAAI,QAAQ,KAElD,YAAY;AAC5B;;AAGA,SAAgB,eAAe,OAAuC;CACpE,IAAI,OAAO,MAAM,KAAK,KAAK,UAAU,GACnC,OAAO;CACT,OAAO,QAAQ,IAAI,OAAO;AAC5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"es-Do2CNrC2.js","names":[],"sources":["../../src/i18n/messages/const.ts","../../src/i18n/messages/en.ts","../../src/i18n/messages/ru.ts","../../src/i18n/messages/es.ts"],"sourcesContent":["export const GRANULARITY_I18N_BLOCK = 'gr'","import type { LocaleLoaderCollection } from '@feugene/fint-i18n/core'\nimport { GRANULARITY_I18N_BLOCK } from
|
|
1
|
+
{"version":3,"file":"es-Do2CNrC2.js","names":[],"sources":["../../src/i18n/messages/const.ts","../../src/i18n/messages/en.ts","../../src/i18n/messages/ru.ts","../../src/i18n/messages/es.ts"],"sourcesContent":["export const GRANULARITY_I18N_BLOCK = 'gr'\n","import type { LocaleLoaderCollection } from '@feugene/fint-i18n/core'\nimport { GRANULARITY_I18N_BLOCK } from './const'\n\n/**\n * English locale loaders for the playground app.\n *\n * Exported separately from other locales so that consumers (and bundlers)\n * can import only the languages they actually need — see the\n * \"Authoring localization packages\" guide in the docs.\n */\nexport const en = {\n en: {\n [GRANULARITY_I18N_BLOCK]: () => import('../locales/en.json'),\n },\n} satisfies LocaleLoaderCollection\n\nexport default en\n","import type { LocaleLoaderCollection } from '@feugene/fint-i18n/core'\nimport { GRANULARITY_I18N_BLOCK } from './const'\n\nexport const ru = {\n ru: {\n [GRANULARITY_I18N_BLOCK]: () => import('../locales/ru.json'),\n },\n} satisfies LocaleLoaderCollection\n\nexport default ru\n","import type { LocaleLoaderCollection } from '@feugene/fint-i18n/core'\nimport { GRANULARITY_I18N_BLOCK } from './const'\n\nexport const es = {\n es: {\n [GRANULARITY_I18N_BLOCK]: () => import('../locales/es.json'),\n },\n} satisfies LocaleLoaderCollection\n\nexport default es\n"],"mappings":";AAAA,IAAa,yBAAyB;;;;;;;;;;ACUtC,IAAa,KAAK,EAChB,IAAI,GAAA,aAC8B,OAAO,oBACzC,EACF;;;ACXA,IAAa,KAAK,EAChB,IAAI,GAAA,aAC8B,OAAO,oBACzC,EACF;;;ACJA,IAAa,KAAK,EAChB,IAAI,GAAA,aAC8B,OAAO,oBACzC,EACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileValidation-D5TFBhbv.js","names":[],"sources":["../../src/fileValidation/FileValidationError.ts","../../src/fileValidation/runFileValidators.ts","../../src/fileValidation/matchAccept.ts","../../src/fileValidation/i18n.ts","../../src/fileValidation/acceptValidator.ts","../../src/fileValidation/allowedExtensionsValidator.ts","../../src/fileValidation/allowedMimeTypesValidator.ts","../../src/fileValidation/maxCountValidator.ts","../../src/fileValidation/maxFileSize.ts","../../src/fileValidation/maxTotalSizeBytesValidator.ts"],"sourcesContent":["import type { FileValidationIssue, FileValidationIssueCode } from './types'\n\nexport class FileValidationError extends Error {\n code: FileValidationIssueCode\n file?: File\n issues: FileValidationIssue[]\n\n constructor(issues: FileValidationIssue[], files?: File[], message?: string) {\n super(message ?? issues[0]?.message ?? 'File validation failed')\n this.name = 'FileValidationError'\n\n this.issues = issues\n this.code = issues[0]?.code ?? 'accept'\n\n const firstFileName = issues[0]?.fileName\n const byName = firstFileName && files ? files.find(f => f.name === firstFileName) : undefined\n // Fallback to the first file if the named one isn't present in `files`\n // (e.g. aggregate issue like `maxTotalSize` has no `fileName`, or names diverged).\n this.file = byName ?? files?.[0]\n }\n}","import type { FileValidationIssue, FileValidator, FileValidatorContext } from './types'\n\nexport function normalizeFiles(files: File[], multiple: boolean): File[] {\n const list = [...files]\n return multiple ? list : list.slice(0, 1)\n}\n\nfunction isPromiseLike<T>(value: unknown): value is PromiseLike<T> {\n return !!value && typeof (value as any).then === 'function'\n}\n\nexport type RunFileValidatorsResult = { files: File[]; issues: FileValidationIssue[] }\n\nexport function runFileValidators(\n files: File[],\n validators: FileValidator[] | undefined,\n context: FileValidatorContext,\n): RunFileValidatorsResult | Promise<RunFileValidatorsResult> {\n const picked = normalizeFiles(files, context.multiple)\n\n const issues: FileValidationIssue[] = []\n\n const list = validators ?? []\n for (let i = 0; i < list.length; i++) {\n const validator = list[i]\n if (!validator) continue\n\n const res = validator({ files: picked, context })\n\n if (isPromiseLike<FileValidationIssue[]>(res)) {\n return (async () => {\n const first = await res\n if (Array.isArray(first) && first.length > 0) issues.push(...first)\n\n for (let j = i + 1; j < list.length; j++) {\n const nextValidator = list[j]\n if (!nextValidator) continue\n\n const nextRes = nextValidator({ files: picked, context })\n const next = isPromiseLike<FileValidationIssue[]>(nextRes) ? await nextRes : nextRes\n if (Array.isArray(next) && next.length > 0) issues.push(...next)\n }\n\n return { files: picked, issues }\n })()\n }\n\n if (Array.isArray(res) && res.length > 0) issues.push(...res)\n }\n\n return { files: picked, issues }\n}","function parseAccept(accept: string | undefined): string[] {\n if (!accept) return []\n\n return accept\n .split(',')\n .map(s => s.trim())\n .filter(Boolean)\n}\n\nexport function matchAccept(file: File, accept: string | undefined): boolean {\n const tokens = parseAccept(accept)\n if (!tokens.length) return true\n\n const fileName = file.name.toLowerCase()\n const fileType = (file.type || '').toLowerCase()\n\n for (const rawToken of tokens) {\n const token = rawToken.toLowerCase()\n\n // Extension match, e.g. \".png\".\n if (token.startsWith('.')) {\n if (fileName.endsWith(token)) return true\n continue\n }\n\n // Mime group match, e.g. \"image/*\".\n if (token.endsWith('/*')) {\n if (!fileType) continue\n const prefix = token.slice(0, -1) // keep trailing '/'\n if (fileType.startsWith(prefix)) return true\n continue\n }\n\n // Exact mime match, e.g. \"image/png\".\n if (!fileType) continue\n if (fileType === token) return true\n }\n\n return false\n}","import type { FileValidationIssue, FileValidationIssueCode } from './types'\n\n/**\n * Неймспейс ключей перевода встроенных валидаторов.\n *\n * Ключ выводится из `code`, поэтому новый встроенный валидатор получает перевод\n * автоматически — достаточно завести строку в `i18n/locales/*.json`.\n */\nexport const FILE_VALIDATION_I18N_NAMESPACE = 'gr.fileValidation'\n\nexport function fileValidationI18nKey(code: FileValidationIssueCode): string {\n return `${FILE_VALIDATION_I18N_NAMESPACE}.${code}`\n}\n\n/**\n * Текст ошибки валидации для показа пользователю.\n *\n * Порядок: явный `i18nKey` → ключ, выведенный из `code` → английский `message`.\n *\n * `i18nKey` существует отдельно от `code` не для симметрии: `code` — это ветка\n * для обработчика на стороне потребителя, и два разных по смыслу сообщения\n * могут делить один `code` (так у `allowedMimeTypesValidator`: обычный\n * запрещённый тип и fallback-тип — оба `mimeType`). Формулировка при этом нужна\n * разная, и различает их именно ключ.\n *\n * `message` остаётся обязательным полем типа и работает как безопасный fallback:\n * валидатор потребителя, ничего не знающий про i18n, продолжает показываться.\n */\nexport function resolveFileValidationMessage(\n issue: FileValidationIssue,\n t: (key: string, fallback: string, params?: Record<string, unknown>) => string,\n): string {\n const key = issue.i18nKey ?? fileValidationI18nKey(issue.code)\n\n // Числа уходят в перевод как есть. Форматировать их — работа переводчика\n // приложения: у него есть локаль и свои правила, а вторая реализация `Intl`\n // внутри UI-библиотеки однажды разошлась бы с ней в мелочах.\n return t(key, issue.message, issue.i18nParams)\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nimport { matchAccept } from './matchAccept'\n\nexport function acceptValidator(accept: string | undefined): FileValidator {\n if (!accept) return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n if (matchAccept(file, accept)) continue\n\n issues.push({\n fileName: file.name,\n code: 'accept',\n message: `File \"${file.name}\" does not match accept=\"${accept}\"`,\n i18nParams: { fileName: file.name, accept },\n })\n }\n\n return issues\n }\n}","import type { FileValidationIssue, FileValidator } from './types'\n\nfunction normalizeExtensions(exts: string[] | undefined): string[] {\n return (exts ?? [])\n .map(s => s.trim().toLowerCase())\n .filter(Boolean)\n .map(s => (s.startsWith('.') ? s.slice(1) : s))\n}\n\nfunction fileExtensionLower(fileName: string): string {\n const i = fileName.lastIndexOf('.')\n if (i < 0) return ''\n return fileName.slice(i + 1).toLowerCase()\n}\n\nexport function allowedExtensionsValidator(exts: string[]): FileValidator {\n const allowedExt = normalizeExtensions(exts)\n if (allowedExt.length === 0) return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n const ext = fileExtensionLower(file.name)\n if (!ext) continue\n\n if (!allowedExt.includes(ext)) {\n issues.push({\n fileName: file.name,\n code: 'extension',\n message: `File \"${file.name}\" has disallowed extension \".${ext}\"`,\n i18nParams: { fileName: file.name, extension: ext },\n })\n }\n }\n\n return issues\n }\n}","import type { FileValidationIssue, FileValidator } from './types'\n\nimport { fileValidationI18nKey } from './i18n'\n\nexport type AllowedMimeTypesValidatorOptions = {\n /**\n * Если `true`, то для fallback-типа (`''`/`application/octet-stream`) валидация по MIME пропускается,\n * предполагая проверку расширения отдельным валидатором.\n */\n allowFallbackByExtension?: boolean\n}\n\nfunction isFallbackType(type: string): boolean {\n return type === '' || type === 'application/octet-stream'\n}\n\nexport function allowedMimeTypesValidator(\n allowed: string[],\n options: AllowedMimeTypesValidatorOptions = {},\n): FileValidator {\n const allowedMime = (allowed ?? []).map(s => s.trim().toLowerCase()).filter(Boolean)\n if (allowedMime.length === 0) return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n const fileType = (file.type || '').toLowerCase()\n\n if (isFallbackType(fileType)) {\n // Legacy behavior in GR: fallback types are not rejected by MIME allow-list.\n // If consumer needs strictness, it can explicitly forbid fallback types.\n if (options.allowFallbackByExtension === false) {\n issues.push({\n fileName: file.name,\n code: 'mimeType',\n message: `File \"${file.name}\" has fallback mime type \"${fileType}\"`,\n // Тот же `code`, что и у запрещённого типа ниже — ветка обработчика\n // одна, — но формулировка другая, поэтому ключ задан явно.\n i18nKey: fileValidationI18nKey('mimeTypeFallback'),\n i18nParams: { fileName: file.name, mimeType: fileType },\n })\n }\n\n continue\n }\n\n if (!allowedMime.includes(fileType)) {\n issues.push({\n fileName: file.name,\n code: 'mimeType',\n message: `File \"${file.name}\" has disallowed mime type \"${fileType}\"`,\n i18nParams: { fileName: file.name, mimeType: fileType },\n })\n }\n }\n\n return issues\n }\n}","import type { FileValidationIssue, FileValidator } from './types'\n\n/**\n * Ограничение количества файлов в наборе.\n *\n * Валидатором, а не проверкой внутри компонента: тогда ограничение одинаково\n * работает и на выборе через диалог, и на перетаскивании, и его сообщение\n * проходит тем же путём локализации, что и остальные.\n */\nexport function maxCountValidator(maxCount: number | undefined): FileValidator {\n if (typeof maxCount !== 'number' || !Number.isFinite(maxCount) || maxCount <= 0) return () => []\n\n const limit = Math.floor(maxCount)\n\n return ({ files }): FileValidationIssue[] => {\n if (files.length <= limit) return []\n\n const issue: FileValidationIssue = {\n code: 'maxCount',\n message: `Too many files selected (${files.length}), maxCount=${limit}`,\n i18nParams: { count: files.length, maxCount: limit },\n meta: { count: files.length, maxCount: limit },\n }\n\n return [issue]\n }\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nexport interface MaxFileSizeOptions {\n /** Предел в байтах. */\n bytes?: number\n /** Предел в мегабайтах — sugar к `bytes` (1 МБ = 1024 × 1024). */\n mb?: number\n}\n\nfunction normalizeLimit(value: number | undefined): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined\n}\n\n/**\n * Ограничение размера **одного** файла. Суммарный размер набора — отдельный\n * валидатор `maxTotalSizeBytesValidator`.\n *\n * Предел задаётся либо в байтах, либо в мегабайтах. Если заданы оба, берётся\n * меньший: молча игнорировать один из двух объявленных пределов хуже, чем\n * применить строгий.\n */\nexport function maxFileSize(options: MaxFileSizeOptions): FileValidator {\n const fromBytes = normalizeLimit(options.bytes)\n const fromMb = normalizeLimit(options.mb)\n const limits = [fromBytes, fromMb === undefined ? undefined : fromMb * 1024 * 1024]\n .filter((value): value is number => value !== undefined)\n\n if (!limits.length) return () => []\n\n const maxBytes = Math.min(...limits)\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n if (file.size <= maxBytes) continue\n\n issues.push({\n fileName: file.name,\n code: 'maxFileSize',\n message: `File \"${file.name}\" is too large (${file.size} bytes), maxBytes=${maxBytes}`,\n i18nParams: { fileName: file.name, size: file.size, maxBytes },\n meta: { maxBytes },\n })\n }\n\n return issues\n }\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nexport function maxTotalSizeBytesValidator(maxBytes: number | undefined): FileValidator {\n if (typeof maxBytes !== 'number' || !Number.isFinite(maxBytes) || maxBytes <= 0) return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const total = files.reduce((acc, f) => acc + (Number(f.size) || 0), 0)\n if (total <= maxBytes) return []\n\n const issue: FileValidationIssue = {\n code: 'maxTotalSize',\n message: `Total files size is too large (${total} bytes), maxTotalSizeBytes=${maxBytes}`,\n i18nParams: { total, maxBytes },\n meta: { total, maxBytes },\n }\n\n return [issue]\n }\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fileValidation-D5TFBhbv.js","names":[],"sources":["../../src/fileValidation/FileValidationError.ts","../../src/fileValidation/runFileValidators.ts","../../src/fileValidation/matchAccept.ts","../../src/fileValidation/i18n.ts","../../src/fileValidation/acceptValidator.ts","../../src/fileValidation/allowedExtensionsValidator.ts","../../src/fileValidation/allowedMimeTypesValidator.ts","../../src/fileValidation/maxCountValidator.ts","../../src/fileValidation/maxFileSize.ts","../../src/fileValidation/maxTotalSizeBytesValidator.ts"],"sourcesContent":["import type { FileValidationIssue, FileValidationIssueCode } from './types'\n\nexport class FileValidationError extends Error {\n code: FileValidationIssueCode\n file?: File\n issues: FileValidationIssue[]\n\n constructor(issues: FileValidationIssue[], files?: File[], message?: string) {\n super(message ?? issues[0]?.message ?? 'File validation failed')\n this.name = 'FileValidationError'\n\n this.issues = issues\n this.code = issues[0]?.code ?? 'accept'\n\n const firstFileName = issues[0]?.fileName\n const byName = firstFileName && files ? files.find(f => f.name === firstFileName) : undefined\n // Fallback to the first file if the named one isn't present in `files`\n // (e.g. aggregate issue like `maxTotalSize` has no `fileName`, or names diverged).\n this.file = byName ?? files?.[0]\n }\n}\n","import type { FileValidationIssue, FileValidator, FileValidatorContext } from './types'\n\nexport function normalizeFiles(files: File[], multiple: boolean): File[] {\n const list = [...files]\n return multiple ? list : list.slice(0, 1)\n}\n\nfunction isPromiseLike<T>(value: unknown): value is PromiseLike<T> {\n return !!value && typeof (value as any).then === 'function'\n}\n\nexport type RunFileValidatorsResult = { files: File[], issues: FileValidationIssue[] }\n\nexport function runFileValidators(\n files: File[],\n validators: FileValidator[] | undefined,\n context: FileValidatorContext,\n): RunFileValidatorsResult | Promise<RunFileValidatorsResult> {\n const picked = normalizeFiles(files, context.multiple)\n\n const issues: FileValidationIssue[] = []\n\n const list = validators ?? []\n for (let i = 0; i < list.length; i++) {\n const validator = list[i]\n if (!validator)\n continue\n\n const res = validator({ files: picked, context })\n\n if (isPromiseLike<FileValidationIssue[]>(res)) {\n return (async () => {\n const first = await res\n if (Array.isArray(first) && first.length > 0)\n issues.push(...first)\n\n for (let j = i + 1; j < list.length; j++) {\n const nextValidator = list[j]\n if (!nextValidator)\n continue\n\n const nextRes = nextValidator({ files: picked, context })\n const next = isPromiseLike<FileValidationIssue[]>(nextRes) ? await nextRes : nextRes\n if (Array.isArray(next) && next.length > 0)\n issues.push(...next)\n }\n\n return { files: picked, issues }\n })()\n }\n\n if (Array.isArray(res) && res.length > 0)\n issues.push(...res)\n }\n\n return { files: picked, issues }\n}\n","function parseAccept(accept: string | undefined): string[] {\n if (!accept)\n return []\n\n return accept\n .split(',')\n .map(s => s.trim())\n .filter(Boolean)\n}\n\nexport function matchAccept(file: File, accept: string | undefined): boolean {\n const tokens = parseAccept(accept)\n if (!tokens.length)\n return true\n\n const fileName = file.name.toLowerCase()\n const fileType = (file.type || '').toLowerCase()\n\n for (const rawToken of tokens) {\n const token = rawToken.toLowerCase()\n\n // Extension match, e.g. \".png\".\n if (token.startsWith('.')) {\n if (fileName.endsWith(token))\n return true\n continue\n }\n\n // Mime group match, e.g. \"image/*\".\n if (token.endsWith('/*')) {\n if (!fileType)\n continue\n const prefix = token.slice(0, -1) // keep trailing '/'\n if (fileType.startsWith(prefix))\n return true\n continue\n }\n\n // Exact mime match, e.g. \"image/png\".\n if (!fileType)\n continue\n if (fileType === token)\n return true\n }\n\n return false\n}\n","import type { FileValidationIssue, FileValidationIssueCode } from './types'\n\n/**\n * Неймспейс ключей перевода встроенных валидаторов.\n *\n * Ключ выводится из `code`, поэтому новый встроенный валидатор получает перевод\n * автоматически — достаточно завести строку в `i18n/locales/*.json`.\n */\nexport const FILE_VALIDATION_I18N_NAMESPACE = 'gr.fileValidation'\n\nexport function fileValidationI18nKey(code: FileValidationIssueCode): string {\n return `${FILE_VALIDATION_I18N_NAMESPACE}.${code}`\n}\n\n/**\n * Текст ошибки валидации для показа пользователю.\n *\n * Порядок: явный `i18nKey` → ключ, выведенный из `code` → английский `message`.\n *\n * `i18nKey` существует отдельно от `code` не для симметрии: `code` — это ветка\n * для обработчика на стороне потребителя, и два разных по смыслу сообщения\n * могут делить один `code` (так у `allowedMimeTypesValidator`: обычный\n * запрещённый тип и fallback-тип — оба `mimeType`). Формулировка при этом нужна\n * разная, и различает их именно ключ.\n *\n * `message` остаётся обязательным полем типа и работает как безопасный fallback:\n * валидатор потребителя, ничего не знающий про i18n, продолжает показываться.\n */\nexport function resolveFileValidationMessage(\n issue: FileValidationIssue,\n t: (key: string, fallback: string, params?: Record<string, unknown>) => string,\n): string {\n const key = issue.i18nKey ?? fileValidationI18nKey(issue.code)\n\n // Числа уходят в перевод как есть. Форматировать их — работа переводчика\n // приложения: у него есть локаль и свои правила, а вторая реализация `Intl`\n // внутри UI-библиотеки однажды разошлась бы с ней в мелочах.\n return t(key, issue.message, issue.i18nParams)\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nimport { matchAccept } from './matchAccept'\n\nexport function acceptValidator(accept: string | undefined): FileValidator {\n if (!accept)\n return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n if (matchAccept(file, accept))\n continue\n\n issues.push({\n fileName: file.name,\n code: 'accept',\n message: `File \"${file.name}\" does not match accept=\"${accept}\"`,\n i18nParams: { fileName: file.name, accept },\n })\n }\n\n return issues\n }\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nfunction normalizeExtensions(exts: string[] | undefined): string[] {\n return (exts ?? [])\n .map(s => s.trim().toLowerCase())\n .filter(Boolean)\n .map(s => (s.startsWith('.') ? s.slice(1) : s))\n}\n\nfunction fileExtensionLower(fileName: string): string {\n const i = fileName.lastIndexOf('.')\n if (i < 0)\n return ''\n return fileName.slice(i + 1).toLowerCase()\n}\n\nexport function allowedExtensionsValidator(exts: string[]): FileValidator {\n const allowedExt = normalizeExtensions(exts)\n if (allowedExt.length === 0)\n return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n const ext = fileExtensionLower(file.name)\n if (!ext)\n continue\n\n if (!allowedExt.includes(ext)) {\n issues.push({\n fileName: file.name,\n code: 'extension',\n message: `File \"${file.name}\" has disallowed extension \".${ext}\"`,\n i18nParams: { fileName: file.name, extension: ext },\n })\n }\n }\n\n return issues\n }\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nimport { fileValidationI18nKey } from './i18n'\n\nexport type AllowedMimeTypesValidatorOptions = {\n /**\n * Если `true`, то для fallback-типа (`''`/`application/octet-stream`) валидация по MIME пропускается,\n * предполагая проверку расширения отдельным валидатором.\n */\n allowFallbackByExtension?: boolean\n}\n\nfunction isFallbackType(type: string): boolean {\n return type === '' || type === 'application/octet-stream'\n}\n\nexport function allowedMimeTypesValidator(\n allowed: string[],\n options: AllowedMimeTypesValidatorOptions = {},\n): FileValidator {\n const allowedMime = (allowed ?? []).map(s => s.trim().toLowerCase()).filter(Boolean)\n if (allowedMime.length === 0)\n return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n const fileType = (file.type || '').toLowerCase()\n\n if (isFallbackType(fileType)) {\n // Legacy behavior in GR: fallback types are not rejected by MIME allow-list.\n // If consumer needs strictness, it can explicitly forbid fallback types.\n if (options.allowFallbackByExtension === false) {\n issues.push({\n fileName: file.name,\n code: 'mimeType',\n message: `File \"${file.name}\" has fallback mime type \"${fileType}\"`,\n // Тот же `code`, что и у запрещённого типа ниже — ветка обработчика\n // одна, — но формулировка другая, поэтому ключ задан явно.\n i18nKey: fileValidationI18nKey('mimeTypeFallback'),\n i18nParams: { fileName: file.name, mimeType: fileType },\n })\n }\n\n continue\n }\n\n if (!allowedMime.includes(fileType)) {\n issues.push({\n fileName: file.name,\n code: 'mimeType',\n message: `File \"${file.name}\" has disallowed mime type \"${fileType}\"`,\n i18nParams: { fileName: file.name, mimeType: fileType },\n })\n }\n }\n\n return issues\n }\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\n/**\n * Ограничение количества файлов в наборе.\n *\n * Валидатором, а не проверкой внутри компонента: тогда ограничение одинаково\n * работает и на выборе через диалог, и на перетаскивании, и его сообщение\n * проходит тем же путём локализации, что и остальные.\n */\nexport function maxCountValidator(maxCount: number | undefined): FileValidator {\n if (typeof maxCount !== 'number' || !Number.isFinite(maxCount) || maxCount <= 0)\n return () => []\n\n const limit = Math.floor(maxCount)\n\n return ({ files }): FileValidationIssue[] => {\n if (files.length <= limit)\n return []\n\n const issue: FileValidationIssue = {\n code: 'maxCount',\n message: `Too many files selected (${files.length}), maxCount=${limit}`,\n i18nParams: { count: files.length, maxCount: limit },\n meta: { count: files.length, maxCount: limit },\n }\n\n return [issue]\n }\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nexport interface MaxFileSizeOptions {\n /** Предел в байтах. */\n bytes?: number\n /** Предел в мегабайтах — sugar к `bytes` (1 МБ = 1024 × 1024). */\n mb?: number\n}\n\nfunction normalizeLimit(value: number | undefined): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined\n}\n\n/**\n * Ограничение размера **одного** файла. Суммарный размер набора — отдельный\n * валидатор `maxTotalSizeBytesValidator`.\n *\n * Предел задаётся либо в байтах, либо в мегабайтах. Если заданы оба, берётся\n * меньший: молча игнорировать один из двух объявленных пределов хуже, чем\n * применить строгий.\n */\nexport function maxFileSize(options: MaxFileSizeOptions): FileValidator {\n const fromBytes = normalizeLimit(options.bytes)\n const fromMb = normalizeLimit(options.mb)\n const limits = [fromBytes, fromMb === undefined ? undefined : fromMb * 1024 * 1024]\n .filter((value): value is number => value !== undefined)\n\n if (!limits.length)\n return () => []\n\n const maxBytes = Math.min(...limits)\n\n return ({ files }): FileValidationIssue[] => {\n const issues: FileValidationIssue[] = []\n\n for (const file of files) {\n if (file.size <= maxBytes)\n continue\n\n issues.push({\n fileName: file.name,\n code: 'maxFileSize',\n message: `File \"${file.name}\" is too large (${file.size} bytes), maxBytes=${maxBytes}`,\n i18nParams: { fileName: file.name, size: file.size, maxBytes },\n meta: { maxBytes },\n })\n }\n\n return issues\n }\n}\n","import type { FileValidationIssue, FileValidator } from './types'\n\nexport function maxTotalSizeBytesValidator(maxBytes: number | undefined): FileValidator {\n if (typeof maxBytes !== 'number' || !Number.isFinite(maxBytes) || maxBytes <= 0)\n return () => []\n\n return ({ files }): FileValidationIssue[] => {\n const total = files.reduce((acc, f) => acc + (Number(f.size) || 0), 0)\n if (total <= maxBytes)\n return []\n\n const issue: FileValidationIssue = {\n code: 'maxTotalSize',\n message: `Total files size is too large (${total} bytes), maxTotalSizeBytes=${maxBytes}`,\n i18nParams: { total, maxBytes },\n meta: { total, maxBytes },\n }\n\n return [issue]\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focusables-BkzK42SQ.js","names":[],"sources":["../../src/composables/internal/focusables.ts"],"sourcesContent":["/**\n * Что пакет считает фокусируемым.\n *\n * Один источник правды на ловушку фокуса, roving-навигацию и «первый элемент\n * панели». До него каждый компонент собирал свой селектор: у `GrDropdown` в\n * список не попадали `select` и `textarea`, а фильтр видимости стоял на\n * `offsetParent !== null` — он врёт на `position: fixed` (у таких элементов\n * `offsetParent` всегда `null`), то есть на панелях самих оверлеев.\n */\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n 'iframe',\n 'audio[controls]',\n 'video[controls]',\n '[contenteditable]:not([contenteditable=\"false\"])',\n '[tabindex]',\n].join(',')\n\n/**\n * Видимость.\n *\n * В браузере спрашиваем `checkVisibility()` — он единственный учитывает скрытых\n * предков, `content-visibility` и `display: contents`. В jsdom его нет и\n * раскладки тоже нет, поэтому там остаётся проверка собственных стилей: этого\n * достаточно, чтобы тесты видели ту же логику, а не пустой список.\n */\nfunction isVisible(element: HTMLElement): boolean {\n if (element.hidden)
|
|
1
|
+
{"version":3,"file":"focusables-BkzK42SQ.js","names":[],"sources":["../../src/composables/internal/focusables.ts"],"sourcesContent":["/**\n * Что пакет считает фокусируемым.\n *\n * Один источник правды на ловушку фокуса, roving-навигацию и «первый элемент\n * панели». До него каждый компонент собирал свой селектор: у `GrDropdown` в\n * список не попадали `select` и `textarea`, а фильтр видимости стоял на\n * `offsetParent !== null` — он врёт на `position: fixed` (у таких элементов\n * `offsetParent` всегда `null`), то есть на панелях самих оверлеев.\n */\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n 'iframe',\n 'audio[controls]',\n 'video[controls]',\n '[contenteditable]:not([contenteditable=\"false\"])',\n '[tabindex]',\n].join(',')\n\n/**\n * Видимость.\n *\n * В браузере спрашиваем `checkVisibility()` — он единственный учитывает скрытых\n * предков, `content-visibility` и `display: contents`. В jsdom его нет и\n * раскладки тоже нет, поэтому там остаётся проверка собственных стилей: этого\n * достаточно, чтобы тесты видели ту же логику, а не пустой список.\n */\nfunction isVisible(element: HTMLElement): boolean {\n if (element.hidden)\n return false\n\n if (typeof element.checkVisibility === 'function')\n return element.checkVisibility({ contentVisibilityAuto: true, visibilityProperty: true })\n\n const style = element.ownerDocument.defaultView?.getComputedStyle(element)\n if (!style)\n return true\n return style.display !== 'none' && style.visibility !== 'hidden'\n}\n\n/** Элемент внутри `inert`-поддерева не фокусируем — браузер его не отдаёт. */\nfunction isInert(element: HTMLElement): boolean {\n return element.closest('[inert]') !== null\n}\n\nexport function isFocusable(element: HTMLElement): boolean {\n if (!element.matches(FOCUSABLE_SELECTOR))\n return false\n if (element.hasAttribute('disabled'))\n return false\n if (element.getAttribute('aria-hidden') === 'true')\n return false\n return !isInert(element) && isVisible(element)\n}\n\n/** Участвует ли элемент в таб-порядке (`tabindex=\"-1\"` — нет). */\nexport function isTabbable(element: HTMLElement): boolean {\n if (!isFocusable(element))\n return false\n return Number.parseInt(element.getAttribute('tabindex') ?? '0', 10) >= 0\n}\n\n/**\n * Фокусируемые внутри корня, в порядке документа.\n *\n * `tabbableOnly` (по умолчанию) оставляет только участников таб-порядка — это\n * то, что нужно циклу Tab. Полный список нужен «первому фокусируемому» при\n * открытии: панель с `tabindex=\"-1\"` фокусируется программно.\n */\nexport function getFocusableElements(\n root: HTMLElement | null | undefined,\n options: { tabbableOnly?: boolean } = {},\n): HTMLElement[] {\n if (!root)\n return []\n\n const tabbableOnly = options.tabbableOnly ?? true\n const matches = Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR))\n\n return matches.filter(element => (tabbableOnly ? isTabbable(element) : isFocusable(element)))\n}\n\n/**\n * Фокусируемые сразу в нескольких корнях, в порядке документа.\n *\n * Нужен ловушке: панель селекта, открытого внутри модалки, телепортирована в\n * `body` и лежит вне DOM-поддерева окна, но для пользователя это продолжение\n * того же слоя.\n */\nexport function getFocusableElementsIn(roots: (HTMLElement | null | undefined)[]): HTMLElement[] {\n const unique = new Set<HTMLElement>()\n\n for (const root of roots) {\n for (const element of getFocusableElements(root)) unique.add(element)\n }\n\n return Array.from(unique).sort((left, right) => {\n const position = left.compareDocumentPosition(right)\n if (position & Node.DOCUMENT_POSITION_FOLLOWING)\n return -1\n if (position & Node.DOCUMENT_POSITION_PRECEDING)\n return 1\n return 0\n })\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAM,qBAAqB;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,GAAG;;;;;;;;;AAUV,SAAS,UAAU,SAA+B;CAChD,IAAI,QAAQ,QACV,OAAO;CAET,IAAI,OAAO,QAAQ,oBAAoB,YACrC,OAAO,QAAQ,gBAAgB;EAAE,uBAAuB;EAAM,oBAAoB;CAAK,CAAC;CAE1F,MAAM,QAAQ,QAAQ,cAAc,aAAa,iBAAiB,OAAO;CACzE,IAAI,CAAC,OACH,OAAO;CACT,OAAO,MAAM,YAAY,UAAU,MAAM,eAAe;AAC1D;;AAGA,SAAS,QAAQ,SAA+B;CAC9C,OAAO,QAAQ,QAAQ,SAAS,MAAM;AACxC;AAEA,SAAgB,YAAY,SAA+B;CACzD,IAAI,CAAC,QAAQ,QAAQ,kBAAkB,GACrC,OAAO;CACT,IAAI,QAAQ,aAAa,UAAU,GACjC,OAAO;CACT,IAAI,QAAQ,aAAa,aAAa,MAAM,QAC1C,OAAO;CACT,OAAO,CAAC,QAAQ,OAAO,KAAK,UAAU,OAAO;AAC/C;;AAGA,SAAgB,WAAW,SAA+B;CACxD,IAAI,CAAC,YAAY,OAAO,GACtB,OAAO;CACT,OAAO,OAAO,SAAS,QAAQ,aAAa,UAAU,KAAK,KAAK,EAAE,KAAK;AACzE;;;;;;;;AASA,SAAgB,qBACd,MACA,UAAsC,CAAC,GACxB;CACf,IAAI,CAAC,MACH,OAAO,CAAC;CAEV,MAAM,eAAe,QAAQ,gBAAgB;CAG7C,OAFgB,MAAM,KAAK,KAAK,iBAA8B,kBAAkB,CAEzE,CAAA,CAAQ,QAAO,YAAY,eAAe,WAAW,OAAO,IAAI,YAAY,OAAO,CAAE;AAC9F;;;;;;;;AASA,SAAgB,uBAAuB,OAA0D;CAC/F,MAAM,yBAAS,IAAI,IAAiB;CAEpC,KAAK,MAAM,QAAQ,OACjB,KAAK,MAAM,WAAW,qBAAqB,IAAI,GAAG,OAAO,IAAI,OAAO;CAGtE,OAAO,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM,MAAM,UAAU;EAC9C,MAAM,WAAW,KAAK,wBAAwB,KAAK;EACnD,IAAI,WAAW,KAAK,6BAClB,OAAO;EACT,IAAI,WAAW,KAAK,6BAClB,OAAO;EACT,OAAO;CACT,CAAC;AACH"}
|
|
@@ -2987,7 +2987,7 @@ var grComponentTokens = [
|
|
|
2987
2987
|
"owner": "GrSlider",
|
|
2988
2988
|
"name": "--gr-slider-rail",
|
|
2989
2989
|
"kind": "hook",
|
|
2990
|
-
"default": "
|
|
2990
|
+
"default": "var(--gr-brd)",
|
|
2991
2991
|
"description": "Цвет непройденной части трека."
|
|
2992
2992
|
},
|
|
2993
2993
|
{
|