@feugene/granularity 0.29.1 → 0.31.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 +9 -6
- package/dist/chunks/{config-DO8mjeIo.js → config-CIkdsWUk.js} +6 -2
- package/dist/chunks/config-CIkdsWUk.js.map +1 -0
- package/dist/chunks/{config-Dpk-eVkS.js → config-DUbbGcfw.js} +12 -1
- package/dist/chunks/config-DUbbGcfw.js.map +1 -0
- package/dist/chunks/{grInputStyles-CAk3xKIb.js → grInputStyles-DgQYjJvD.js} +17 -1
- package/dist/chunks/{grInputStyles-CAk3xKIb.js.map → grInputStyles-DgQYjJvD.js.map} +1 -1
- package/dist/chunks/grSelectStyles-Cdtd10eY.js.map +1 -1
- package/dist/chunks/{granular-provider-NtErwzYB.js → granular-provider-yJNX1g1G.js} +2 -2
- package/dist/chunks/{granular-provider-NtErwzYB.js.map → granular-provider-yJNX1g1G.js.map} +1 -1
- package/dist/chunks/renamedProp-BwcN-SJg.js +33 -0
- package/dist/chunks/renamedProp-BwcN-SJg.js.map +1 -0
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-CaHys_A_.js → GrAutocomplete-X6RlmiJQ.js} +1 -1
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-CaHys_A_.js.map → GrAutocomplete-X6RlmiJQ.js.map} +1 -1
- package/dist/components/GrAutocomplete/index.js +1 -1
- package/dist/components/GrBadge/chunks/{GrBadge-BM3f9PME.js → GrBadge-BsoocpF-.js} +4 -2
- package/dist/components/GrBadge/chunks/GrBadge-BsoocpF-.js.map +1 -0
- package/dist/components/GrBadge/index.js +1 -1
- package/dist/components/GrBadge/styles.css +1 -1
- package/dist/components/GrCard/chunks/{GrCard-DR3ehBt8.js → GrCard-BttXz1pQ.js} +19 -6
- package/dist/components/GrCard/chunks/GrCard-BttXz1pQ.js.map +1 -0
- package/dist/components/GrCard/index.js +2 -2
- package/dist/components/GrChip/chunks/{GrChip-Df4orxRH.js → GrChip-C0vU69tf.js} +3 -1
- package/dist/components/GrChip/chunks/GrChip-C0vU69tf.js.map +1 -0
- package/dist/components/GrChip/index.js +1 -1
- package/dist/components/GrCollapse/chunks/{GrCollapse-Bw9_JatF.js → GrCollapse-BlW6ybdL.js} +1 -1
- package/dist/components/GrCollapse/chunks/{GrCollapse-Bw9_JatF.js.map → GrCollapse-BlW6ybdL.js.map} +1 -1
- package/dist/components/GrCollapse/index.js +1 -1
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-CE-xtNP-.js → GrColorPicker-C7ifyQ0R.js} +1 -1
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-CE-xtNP-.js.map → GrColorPicker-C7ifyQ0R.js.map} +1 -1
- package/dist/components/GrColorPicker/index.js +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-BNQDbAsY.js → GrContextMenu-_FKwQvuQ.js} +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-BNQDbAsY.js.map → GrContextMenu-_FKwQvuQ.js.map} +1 -1
- package/dist/components/GrContextMenu/index.js +1 -1
- package/dist/components/GrDialogService/chunks/{GrDialogService-k4SYIv64.js → GrDialogService-6s2cQ-_6.js} +1 -1
- package/dist/components/GrDialogService/chunks/{GrDialogService-k4SYIv64.js.map → GrDialogService-6s2cQ-_6.js.map} +1 -1
- package/dist/components/GrDialogService/index.js +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-Cg7qHV9J.js → GrDropdownMenu-GOzuAXsi.js} +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-Cg7qHV9J.js.map → GrDropdownMenu-GOzuAXsi.js.map} +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenuList-RW5IBvmu.js → GrDropdownMenuList-B33ZzwfB.js} +13 -3
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenuList-RW5IBvmu.js.map → GrDropdownMenuList-B33ZzwfB.js.map} +1 -1
- package/dist/components/GrDropdownMenu/index.js +2 -2
- package/dist/components/GrInput/chunks/{GrInput-BqqoEl1b.js → GrInput-BLywRZUN.js} +10 -6
- package/dist/components/GrInput/chunks/GrInput-BLywRZUN.js.map +1 -0
- package/dist/components/GrInput/index.js +2 -2
- package/dist/components/GrInputTag/chunks/{GrInputTag-5wVcB0zG.js → GrInputTag-Cj4A9Xgs.js} +1 -1
- package/dist/components/GrInputTag/chunks/{GrInputTag-5wVcB0zG.js.map → GrInputTag-Cj4A9Xgs.js.map} +1 -1
- package/dist/components/GrInputTag/index.js +1 -1
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CgwjoUJt.js → GrJsonViewer-Cy2bknHO.js} +1 -1
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CgwjoUJt.js.map → GrJsonViewer-Cy2bknHO.js.map} +1 -1
- package/dist/components/GrJsonViewer/index.js +1 -1
- package/dist/components/GrList/chunks/{GrList-DrXrKU37.js → GrList-DmT4qzLO.js} +1 -1
- package/dist/components/GrList/chunks/{GrList-DrXrKU37.js.map → GrList-DmT4qzLO.js.map} +1 -1
- package/dist/components/GrList/index.js +1 -1
- package/dist/components/GrPagination/chunks/{GrPagination-CX9ZV8mR.js → GrPagination-Cw3R21dp.js} +1 -1
- package/dist/components/GrPagination/chunks/{GrPagination-CX9ZV8mR.js.map → GrPagination-Cw3R21dp.js.map} +1 -1
- package/dist/components/GrPagination/index.js +1 -1
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-D1ADRFxx.js → GrPromptDialog-DLcl1xiq.js} +1 -1
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-D1ADRFxx.js.map → GrPromptDialog-DLcl1xiq.js.map} +1 -1
- package/dist/components/GrPromptDialog/index.js +1 -1
- package/dist/components/GrSelect/chunks/{GrSelect-DKoQu3w9.js → GrSelect-BiUrSSxc.js} +5 -5
- package/dist/components/GrSelect/chunks/GrSelect-BiUrSSxc.js.map +1 -0
- package/dist/components/GrSelect/index.js +1 -1
- package/dist/components/GrSelect/styles.css +1 -1
- package/dist/components/GrSortableList/chunks/{GrSortableList-DGs3Pi2J.js → GrSortableList-HyKX--rO.js} +1 -1
- package/dist/components/GrSortableList/chunks/{GrSortableList-DGs3Pi2J.js.map → GrSortableList-HyKX--rO.js.map} +1 -1
- package/dist/components/GrSortableList/index.js +1 -1
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-CymO68Cv.js → GrTreeSelect-iJnMl2t9.js} +1 -1
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-CymO68Cv.js.map → GrTreeSelect-iJnMl2t9.js.map} +1 -1
- package/dist/components/GrTreeSelect/index.js +1 -1
- package/dist/granular-provider-node.js +1 -1
- package/dist/granular-provider.js +1 -1
- package/dist/index.js +21 -21
- package/dist/types/components/GrCard/GrCard.vue.d.ts +8 -0
- package/dist/types/components/GrCard/grCardStyles.d.ts +9 -0
- package/dist/types/components/GrDropdownMenu/menuModel.d.ts +20 -2
- package/dist/types/components/GrInput/GrInput.vue.d.ts +16 -0
- package/dist/types/components/GrInput/grInputStyles.d.ts +16 -0
- package/dist/types/components/GrSelect/grSelectStyles.d.ts +12 -0
- package/dist/types/components/shared/renamedProp.d.ts +19 -0
- package/dist/web-types.json +14 -1
- package/package.json +2 -2
- package/dist/chunks/config-DO8mjeIo.js.map +0 -1
- package/dist/chunks/config-Dpk-eVkS.js.map +0 -1
- package/dist/components/GrBadge/chunks/GrBadge-BM3f9PME.js.map +0 -1
- package/dist/components/GrCard/chunks/GrCard-DR3ehBt8.js.map +0 -1
- package/dist/components/GrChip/chunks/GrChip-Df4orxRH.js.map +0 -1
- package/dist/components/GrInput/chunks/GrInput-BqqoEl1b.js.map +0 -1
- package/dist/components/GrSelect/chunks/GrSelect-DKoQu3w9.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -21,13 +21,13 @@ import { n as useGrFormFieldContext } from "./chunks/context-DdNIxa1w.js";
|
|
|
21
21
|
import { useGrFormControl } from "./composables/useGrFormControl.js";
|
|
22
22
|
import { useComboboxNavigation } from "./composables/useComboboxNavigation.js";
|
|
23
23
|
import { useRovingFocus } from "./composables/useRovingFocus.js";
|
|
24
|
-
import { t as GrChip_default } from "./components/GrChip/chunks/GrChip-
|
|
24
|
+
import { t as GrChip_default } from "./components/GrChip/chunks/GrChip-C0vU69tf.js";
|
|
25
25
|
import { n as grAutocompleteSafelist, t as grAutocompleteConfig } from "./chunks/config-vYMJ3Cr1.js";
|
|
26
|
-
import { t as GrAutocomplete_default } from "./components/GrAutocomplete/chunks/GrAutocomplete-
|
|
26
|
+
import { t as GrAutocomplete_default } from "./components/GrAutocomplete/chunks/GrAutocomplete-X6RlmiJQ.js";
|
|
27
27
|
import { t as GrSkeleton_default } from "./components/GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js";
|
|
28
28
|
import { n as GrAvatar_default, t as GrAvatarGroup_default } from "./components/GrAvatar/chunks/GrAvatar-CNmLmgcr.js";
|
|
29
29
|
import { c as initialsFrom, n as grAvatarSafelist, t as grAvatarConfig } from "./chunks/config-B3J0alyY.js";
|
|
30
|
-
import { t as GrBadge_default } from "./components/GrBadge/chunks/GrBadge-
|
|
30
|
+
import { t as GrBadge_default } from "./components/GrBadge/chunks/GrBadge-BsoocpF-.js";
|
|
31
31
|
import { t as grBadgeSafelist } from "./chunks/safelist-CtiHPgrj.js";
|
|
32
32
|
import { t as grBadgeConfig } from "./chunks/config-g8-JGZ_Y.js";
|
|
33
33
|
import { n as grBadgeWrapSafelist, o as formatBadgeValue, t as grBadgeWrapConfig } from "./chunks/config-DwABJHEo.js";
|
|
@@ -44,8 +44,8 @@ import { t as grButtonConfig } from "./chunks/config-BHcS5Cwm.js";
|
|
|
44
44
|
import { t as GrButtonGroup_default } from "./components/GrButtonGroup/chunks/GrButtonGroup-CKyiAV8K.js";
|
|
45
45
|
import { t as grButtonGroupConfig } from "./chunks/config-DBmdgoVf2.js";
|
|
46
46
|
import "./components/GrButtonGroup/index.js";
|
|
47
|
-
import { n as grCardSafelist, t as grCardConfig } from "./chunks/config-
|
|
48
|
-
import { t as GrCard_default } from "./components/GrCard/chunks/GrCard-
|
|
47
|
+
import { n as grCardSafelist, t as grCardConfig } from "./chunks/config-DUbbGcfw.js";
|
|
48
|
+
import { t as GrCard_default } from "./components/GrCard/chunks/GrCard-BttXz1pQ.js";
|
|
49
49
|
import { t as GrCheckbox_default } from "./components/GrCheckbox/chunks/GrCheckbox-CEcHIsXM.js";
|
|
50
50
|
import { n as grCheckboxSafelist, t as grCheckboxConfig } from "./chunks/config-DZCUPHPU.js";
|
|
51
51
|
import "./components/GrCheckbox/index.js";
|
|
@@ -59,14 +59,14 @@ import { useAnnouncer } from "./composables/useAnnouncer.js";
|
|
|
59
59
|
import { t as GrCodeBlock_default } from "./components/GrCodeBlock/chunks/GrCodeBlock-Dkvkr91t.js";
|
|
60
60
|
import { n as grCodeBlockSafelist, t as grCodeBlockConfig } from "./chunks/config-DolULhjJ.js";
|
|
61
61
|
import { n as grCollapseSafelist, t as grCollapseConfig } from "./chunks/config-BoUI0t-t.js";
|
|
62
|
-
import { n as GrCollapse_default, t as GrCollapseItem_default } from "./components/GrCollapse/chunks/GrCollapse-
|
|
62
|
+
import { n as GrCollapse_default, t as GrCollapseItem_default } from "./components/GrCollapse/chunks/GrCollapse-BlW6ybdL.js";
|
|
63
63
|
import { n as grIconSafelist, t as grIconConfig } from "./chunks/config-3bQeQvqd.js";
|
|
64
|
-
import { t as GrInput_default } from "./components/GrInput/chunks/GrInput-
|
|
64
|
+
import { t as GrInput_default } from "./components/GrInput/chunks/GrInput-BLywRZUN.js";
|
|
65
65
|
import { useFocusTrap } from "./composables/useFocusTrap.js";
|
|
66
66
|
import { t as GrPopover_default } from "./components/GrPopover/chunks/GrPopover-CofG-Tfe.js";
|
|
67
67
|
import { useDragGesture } from "./composables/useDragGesture.js";
|
|
68
68
|
import { t as GrSlider_default } from "./components/GrSlider/chunks/GrSlider-DJfeEl4h.js";
|
|
69
|
-
import { t as GrColorPicker_default } from "./components/GrColorPicker/chunks/GrColorPicker-
|
|
69
|
+
import { t as GrColorPicker_default } from "./components/GrColorPicker/chunks/GrColorPicker-C7ifyQ0R.js";
|
|
70
70
|
import { n as grColorPickerSafelist, t as grColorPickerConfig } from "./chunks/config-DIDz_E5m.js";
|
|
71
71
|
import { a as GR_KBD_TOKENS, o as findKbdToken, t as GrKbd_default } from "./components/GrKbd/chunks/GrKbd-D2ga1H9i.js";
|
|
72
72
|
import { t as GrModal_default } from "./components/GrModal/chunks/GrModal-CCoWZuIl.js";
|
|
@@ -79,8 +79,8 @@ import { a as extendDefaultParsers, n as coreResponseErrorParsers, r as createRe
|
|
|
79
79
|
import { t as GrConfirmDialog_default } from "./components/GrConfirmDialog/chunks/GrConfirmDialog-B9mIU78E.js";
|
|
80
80
|
import { t as grConfirmDialogConfig } from "./chunks/config-A-bBiotF.js";
|
|
81
81
|
import "./components/GrConfirmDialog/index.js";
|
|
82
|
-
import { a as GrDropdownMenuItem_default, c as GrDropdownMenuDivider_default, o as GrDropdownMenuGroup_default, s as GrDropdownMenuHeader_default, t as GrDropdownMenuList_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenuList-
|
|
83
|
-
import { t as GrContextMenu_default } from "./components/GrContextMenu/chunks/GrContextMenu-
|
|
82
|
+
import { a as GrDropdownMenuItem_default, c as GrDropdownMenuDivider_default, o as GrDropdownMenuGroup_default, s as GrDropdownMenuHeader_default, t as GrDropdownMenuList_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenuList-B33ZzwfB.js";
|
|
83
|
+
import { t as GrContextMenu_default } from "./components/GrContextMenu/chunks/GrContextMenu-_FKwQvuQ.js";
|
|
84
84
|
import { t as grContextMenuConfig } from "./chunks/config-CPSxM7XE.js";
|
|
85
85
|
import { t as GrTable_default } from "./components/GrTable/chunks/GrTable-Zcdz2St_.js";
|
|
86
86
|
import { t as useDragSort } from "./chunks/useDragSort-0l47h4yb.js";
|
|
@@ -99,8 +99,8 @@ import { n as useGrFormContext } from "./chunks/context-Bfrgsluh.js";
|
|
|
99
99
|
import { t as GrFormField_default } from "./components/GrFormField/chunks/GrFormField-DSylU7IU.js";
|
|
100
100
|
import { t as GrTextarea_default } from "./components/GrTextarea/chunks/GrTextarea-KREK75Bu.js";
|
|
101
101
|
import { n as getByPath, o as runFieldRules, r as isEmpty, s as setByPath, t as createGrFormMessageResolver } from "./chunks/validation-5HhpanPP.js";
|
|
102
|
-
import { t as GrPromptDialog_default } from "./components/GrPromptDialog/chunks/GrPromptDialog-
|
|
103
|
-
import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./components/GrDialogService/chunks/GrDialogService-
|
|
102
|
+
import { t as GrPromptDialog_default } from "./components/GrPromptDialog/chunks/GrPromptDialog-DLcl1xiq.js";
|
|
103
|
+
import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./components/GrDialogService/chunks/GrDialogService-6s2cQ-_6.js";
|
|
104
104
|
import { t as grDialogServiceConfig } from "./chunks/config-CjXjhphs.js";
|
|
105
105
|
import { n as grDividerSafelist, t as grDividerConfig } from "./chunks/config-D82r782v.js";
|
|
106
106
|
import { t as GrDivider_default } from "./components/GrDivider/chunks/GrDivider-BXavGcMX.js";
|
|
@@ -109,7 +109,7 @@ import { t as GrDrawer_default } from "./components/GrDrawer/chunks/GrDrawer-B7P
|
|
|
109
109
|
import { t as GrDropdown_default } from "./components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js";
|
|
110
110
|
import { n as grDropdownSafelist, t as grDropdownConfig } from "./chunks/config-uzUuosv7.js";
|
|
111
111
|
import "./components/GrDropdown/index.js";
|
|
112
|
-
import { n as GrDropdownMenuColumn_default, r as GrDropdownMenu_default, t as GrDropdownMenuColumns_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenu-
|
|
112
|
+
import { n as GrDropdownMenuColumn_default, r as GrDropdownMenu_default, t as GrDropdownMenuColumns_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenu-GOzuAXsi.js";
|
|
113
113
|
import { n as grDropdownMenuSafelist, t as grDropdownMenuConfig } from "./chunks/config-_jbgsFpw.js";
|
|
114
114
|
import { t as GrEmptyState_default } from "./components/GrEmptyState/chunks/GrEmptyState-RqsWvgI9.js";
|
|
115
115
|
import { n as grEmptyStateSafelist, t as grEmptyStateConfig } from "./chunks/config-CWtfxkM9.js";
|
|
@@ -128,19 +128,19 @@ import { n as grFormSectionSafelist, t as grFormSectionConfig } from "./chunks/c
|
|
|
128
128
|
import { t as GrFormSection_default } from "./components/GrFormSection/chunks/GrFormSection-ejieOg9H.js";
|
|
129
129
|
import { t as GrImageViewer_default } from "./components/GrImageViewer/chunks/GrImageViewer-CyVN6Zpc.js";
|
|
130
130
|
import { n as grImageViewerSafelist, t as grImageViewerConfig } from "./chunks/config-BDSaD-5p.js";
|
|
131
|
-
import { n as grInputSafelist, t as grInputConfig } from "./chunks/config-
|
|
131
|
+
import { n as grInputSafelist, t as grInputConfig } from "./chunks/config-CIkdsWUk.js";
|
|
132
132
|
import "./components/GrInput/index.js";
|
|
133
133
|
import { n as grInputTagSafelist, t as grInputTagConfig } from "./chunks/config-BqT6PMzO.js";
|
|
134
|
-
import { t as GrInputTag_default } from "./components/GrInputTag/chunks/GrInputTag-
|
|
134
|
+
import { t as GrInputTag_default } from "./components/GrInputTag/chunks/GrInputTag-Cj4A9Xgs.js";
|
|
135
135
|
import { t as GrTree_default } from "./components/GrTree/chunks/GrTree-DC89I4AP.js";
|
|
136
|
-
import { t as GrJsonViewer_default } from "./components/GrJsonViewer/chunks/GrJsonViewer-
|
|
136
|
+
import { t as GrJsonViewer_default } from "./components/GrJsonViewer/chunks/GrJsonViewer-Cy2bknHO.js";
|
|
137
137
|
import { n as grJsonViewerSafelist, t as grJsonViewerConfig } from "./chunks/config-DpAYidyY2.js";
|
|
138
138
|
import { n as grKbdSafelist, t as grKbdConfig } from "./chunks/config-BRESvs9g.js";
|
|
139
139
|
import "./components/GrKbd/index.js";
|
|
140
140
|
import { n as grLinkSafelist, t as grLinkConfig } from "./chunks/config-CQLNjc9X2.js";
|
|
141
141
|
import "./components/GrLink/index.js";
|
|
142
142
|
import { n as grListSafelist, t as grListConfig } from "./chunks/config-D0W8mGFD.js";
|
|
143
|
-
import { n as GrList_default, t as GrListItem_default } from "./components/GrList/chunks/GrList-
|
|
143
|
+
import { n as GrList_default, t as GrListItem_default } from "./components/GrList/chunks/GrList-DmT4qzLO.js";
|
|
144
144
|
import { n as grLoadingSafelist, t as grLoadingConfig } from "./chunks/config-Bjn30smH.js";
|
|
145
145
|
import "./components/GrLoading/index.js";
|
|
146
146
|
import { n as grModalSafelist, t as grModalConfig } from "./chunks/config-mlheIMtV.js";
|
|
@@ -149,9 +149,9 @@ import { t as GrNavbar_default } from "./components/GrNavbar/chunks/GrNavbar-C5E
|
|
|
149
149
|
import { n as grNavbarSafelist, t as grNavbarConfig } from "./chunks/config-2ZHRsdOc.js";
|
|
150
150
|
import { n as grNumberInputSafelist, t as grNumberInputConfig } from "./chunks/config-MmPym-Z72.js";
|
|
151
151
|
import { t as GrNumberInput_default } from "./components/GrNumberInput/chunks/GrNumberInput-DQ59YICu.js";
|
|
152
|
-
import { t as GrSelect_default } from "./components/GrSelect/chunks/GrSelect-
|
|
152
|
+
import { t as GrSelect_default } from "./components/GrSelect/chunks/GrSelect-BiUrSSxc.js";
|
|
153
153
|
import { n as grPaginationSafelist, t as grPaginationConfig } from "./chunks/config-CjKpUcmy.js";
|
|
154
|
-
import { t as GrPagination_default } from "./components/GrPagination/chunks/GrPagination-
|
|
154
|
+
import { t as GrPagination_default } from "./components/GrPagination/chunks/GrPagination-Cw3R21dp.js";
|
|
155
155
|
import { n as grPopoverSafelist, t as grPopoverConfig } from "./chunks/config-BTwYMQaz2.js";
|
|
156
156
|
import "./components/GrPopover/index.js";
|
|
157
157
|
import { n as grProgressBarSafelist, r as GR_TONES, t as grProgressBarConfig } from "./chunks/config-DWL81-aM.js";
|
|
@@ -179,7 +179,7 @@ import "./components/GrSkeleton/index.js";
|
|
|
179
179
|
import { n as grSliderSafelist, t as grSliderConfig } from "./chunks/config-tiUtEn4Q.js";
|
|
180
180
|
import "./components/GrSlider/index.js";
|
|
181
181
|
import { n as grSortableListSafelist, t as grSortableListConfig } from "./chunks/config-CbEbLyDE.js";
|
|
182
|
-
import { t as GrSortableList_default } from "./components/GrSortableList/chunks/GrSortableList-
|
|
182
|
+
import { t as GrSortableList_default } from "./components/GrSortableList/chunks/GrSortableList-HyKX--rO.js";
|
|
183
183
|
import { n as grSplitterSafelist, t as grSplitterConfig } from "./chunks/config-CvbVM4ep.js";
|
|
184
184
|
import { n as sizeFromPointer, t as GrSplitter_default } from "./components/GrSplitter/chunks/GrSplitter-MltjaADn.js";
|
|
185
185
|
import { n as formatStatisticValue, t as GrStatistic_default } from "./components/GrStatistic/chunks/GrStatistic-qHVasK37.js";
|
|
@@ -205,7 +205,7 @@ import { n as grTooltipSafelist, t as grTooltipConfig } from "./chunks/config-BT
|
|
|
205
205
|
import { t as GrTooltip_default } from "./components/GrTooltip/chunks/GrTooltip-uYETdbCD.js";
|
|
206
206
|
import { n as grTreeSafelist, t as grTreeConfig } from "./chunks/config-CDat1wXf.js";
|
|
207
207
|
import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "./chunks/config-T3-DMXYm.js";
|
|
208
|
-
import { t as GrTreeSelect_default } from "./components/GrTreeSelect/chunks/GrTreeSelect-
|
|
208
|
+
import { t as GrTreeSelect_default } from "./components/GrTreeSelect/chunks/GrTreeSelect-iJnMl2t9.js";
|
|
209
209
|
import "./composables/useGrComponentConfig.js";
|
|
210
210
|
import "./composables/useGranularityTranslations.js";
|
|
211
211
|
import { GRANULARITY_THEME_STATE, granularityThemePlugin, initThemeEarly, useTheme } from "./composables/useTheme.js";
|
|
@@ -38,6 +38,14 @@ type __VLS_Slots = {
|
|
|
38
38
|
default?: () => any;
|
|
39
39
|
/** Шапка вместо пропов `title` и `description`. */
|
|
40
40
|
header?: () => any;
|
|
41
|
+
/**
|
|
42
|
+
* Действия справа в собственной шапке карточки: «⋯», «Обновить»,
|
|
43
|
+
* переключатель периода. Включают шапку так же, как `title`.
|
|
44
|
+
*
|
|
45
|
+
* Со слотом `#header` не сочетается: тот заменяет шапку целиком, и всё, что в
|
|
46
|
+
* ней есть, рисует потребитель.
|
|
47
|
+
*/
|
|
48
|
+
actions?: () => any;
|
|
41
49
|
/** Подвал: действия, сводка, пагинация. */
|
|
42
50
|
footer?: () => any;
|
|
43
51
|
};
|
|
@@ -10,6 +10,15 @@ export type GrCardVariant = 'elevated' | 'outlined' | 'ghost';
|
|
|
10
10
|
export declare const surfaceBaseClass = "rounded-[var(--gr-radius-lg)] bg-[var(--gr-card)] text-[var(--gr-card-fg)]";
|
|
11
11
|
export declare const variantClass: Record<GrCardVariant, string>;
|
|
12
12
|
export declare const paddingClass: Record<GrCardPadding, string>;
|
|
13
|
+
/**
|
|
14
|
+
* Строка шапки: заголовок с описанием слева, действия справа.
|
|
15
|
+
*
|
|
16
|
+
* `items-start`, а не `center`: у карточки с описанием шапка выше одной строки,
|
|
17
|
+
* и кнопка, выровненная по центру блока, уезжала бы к описанию, а не к
|
|
18
|
+
* заголовку.
|
|
19
|
+
*/
|
|
20
|
+
export declare const headerRowClass = "flex items-start justify-between gap-3";
|
|
21
|
+
export declare const headerActionsClass = "flex shrink-0 items-center gap-1";
|
|
13
22
|
export declare const sectionDividerTopClass = "border-t border-[var(--gr-brd)]";
|
|
14
23
|
export declare const sectionDividerBottomClass = "border-b border-[var(--gr-brd)]";
|
|
15
24
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Component } from 'vue';
|
|
2
|
-
import type { GrDropdownMenuItemRole } from './GrDropdownMenuItem.vue';
|
|
3
|
-
import type { GrDropdownMenuItemVariant } from './grDropdownMenuStyles';
|
|
2
|
+
import type { GrDropdownMenuItemAlign, GrDropdownMenuItemRole } from './GrDropdownMenuItem.vue';
|
|
3
|
+
import type { GrDropdownMenuHeaderAlign, GrDropdownMenuItemVariant } from './grDropdownMenuStyles';
|
|
4
4
|
/**
|
|
5
5
|
* Декларативная модель меню.
|
|
6
6
|
*
|
|
@@ -26,6 +26,18 @@ export interface GrDropdownMenuAction {
|
|
|
26
26
|
rel?: string;
|
|
27
27
|
/** Шорткат для `target="_blank"` + `rel="noopener noreferrer"`. */
|
|
28
28
|
external?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Чем рендерить пункт: тег или компонент роутера.
|
|
31
|
+
*
|
|
32
|
+
* Без него пункт-ссылка из `items` остаётся обычным `<a>`, то есть в
|
|
33
|
+
* SPA переход идёт перезагрузкой страницы — а обойти это в модели нечем:
|
|
34
|
+
* `itemProps` внутренняя, слота на пункт нет. Проп есть у самого
|
|
35
|
+
* `GrDropdownMenuItem` и у соседей по кольцу (`GrLink`, `GrBreadcrumbs`,
|
|
36
|
+
* `GrSidebarItem`), из этого ряда выпадала только модель меню.
|
|
37
|
+
*/
|
|
38
|
+
as?: string | Component;
|
|
39
|
+
/** Выравнивание содержимого пункта. */
|
|
40
|
+
align?: GrDropdownMenuItemAlign;
|
|
29
41
|
}
|
|
30
42
|
export interface GrDropdownMenuSeparator {
|
|
31
43
|
type: 'divider';
|
|
@@ -34,6 +46,12 @@ export interface GrDropdownMenuSeparator {
|
|
|
34
46
|
export interface GrDropdownMenuSection {
|
|
35
47
|
type: 'group';
|
|
36
48
|
title?: string;
|
|
49
|
+
/** Выравнивание заголовка группы. */
|
|
50
|
+
titleAlign?: GrDropdownMenuHeaderAlign;
|
|
51
|
+
/** Разделители между пунктами группы. */
|
|
52
|
+
dividers?: boolean;
|
|
53
|
+
/** Заголовок капсом. */
|
|
54
|
+
uppercase?: boolean;
|
|
37
55
|
items: GrDropdownMenuAction[];
|
|
38
56
|
}
|
|
39
57
|
export type GrDropdownMenuEntry = GrDropdownMenuAction | GrDropdownMenuSeparator | GrDropdownMenuSection;
|
|
@@ -55,6 +55,19 @@ export interface GrInputProps {
|
|
|
55
55
|
*/
|
|
56
56
|
prefixFixed?: boolean;
|
|
57
57
|
suffixFixed?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Как выглядят аддоны `#prefix`/`#suffix`.
|
|
60
|
+
*
|
|
61
|
+
* `segment` (по умолчанию) — отдельный отсек, отрезанный рамкой и выровненный
|
|
62
|
+
* по ступени размера: так поле с «₽» и поле с «USD» стоят в колонку.
|
|
63
|
+
* `inline` — украшение внутри рамки: ни разделителя, ни своей ширины.
|
|
64
|
+
*
|
|
65
|
+
* Разница не косметическая. Поисковая строка с лупой в сегменте читается
|
|
66
|
+
* составным элементом — полем с приклеенной кнопкой, — а не одним полем;
|
|
67
|
+
* именно поэтому иконку внутри рамки нельзя было выразить аддоном, и
|
|
68
|
+
* потребители отказывались от неё вовсе.
|
|
69
|
+
*/
|
|
70
|
+
addon?: 'segment' | 'inline';
|
|
58
71
|
}
|
|
59
72
|
export interface GrInputEmits {
|
|
60
73
|
(e: 'update:modelValue', value: string): void;
|
|
@@ -110,6 +123,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
110
123
|
suffixMaxWidth: undefined;
|
|
111
124
|
prefixFixed: boolean;
|
|
112
125
|
suffixFixed: boolean;
|
|
126
|
+
addon: string;
|
|
113
127
|
}>>, {
|
|
114
128
|
focus: typeof focus;
|
|
115
129
|
blur: typeof blur;
|
|
@@ -150,6 +164,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
150
164
|
suffixMaxWidth: undefined;
|
|
151
165
|
prefixFixed: boolean;
|
|
152
166
|
suffixFixed: boolean;
|
|
167
|
+
addon: string;
|
|
153
168
|
}>>> & Readonly<{
|
|
154
169
|
onClear?: (() => any) | undefined;
|
|
155
170
|
onBlur?: ((event: FocusEvent) => any) | undefined;
|
|
@@ -186,6 +201,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
186
201
|
passwordToggle: boolean;
|
|
187
202
|
passwordShowLabel: string;
|
|
188
203
|
passwordHideLabel: string;
|
|
204
|
+
addon: "segment" | "inline";
|
|
189
205
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
190
206
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
191
207
|
declare const _default: typeof __VLS_export;
|
|
@@ -61,3 +61,19 @@ export declare function grInputFieldClass(options: {
|
|
|
61
61
|
size: keyof typeof sizes;
|
|
62
62
|
align: keyof typeof textAlign;
|
|
63
63
|
}): string;
|
|
64
|
+
/**
|
|
65
|
+
* Аддон-сегмент: отрезан рамкой и держит ширину не меньше ступени размера — так
|
|
66
|
+
* поле с «₽» и поле с «USD» выстраиваются в колонку, а не пляшут по ширине.
|
|
67
|
+
*/
|
|
68
|
+
export declare const addonSegmentPrefixClass = "border-r border-[var(--gr-brd)] px-2";
|
|
69
|
+
export declare const addonSegmentSuffixClass = "border-l border-[var(--gr-brd)] px-2";
|
|
70
|
+
/**
|
|
71
|
+
* Украшение внутри рамки: ни разделителя, ни своей ширины — лупа в поисковой
|
|
72
|
+
* строке, единица измерения, счётчик.
|
|
73
|
+
*
|
|
74
|
+
* Отдельный режим, а не «сегмент без рамки»: у сегмента ширина выровнена по
|
|
75
|
+
* ступени размера, и иконка в нём висела бы в пустом отсеке. Здесь поле берёт
|
|
76
|
+
* ровно ту ширину, что заняло содержимое, а текст начинается сразу за ним.
|
|
77
|
+
*/
|
|
78
|
+
export declare const addonInlinePrefixClass = "pl-3 pr-2";
|
|
79
|
+
export declare const addonInlineSuffixClass = "pl-2 pr-3";
|
|
@@ -3,6 +3,7 @@ export type GrSelectView = 'default' | 'link';
|
|
|
3
3
|
export type GrSelectSize = GrComponentSize;
|
|
4
4
|
export type GrSelectVariant = 'primary' | 'default' | 'muted' | 'danger';
|
|
5
5
|
export type GrSelectUnderline = 'auto' | 'always' | 'none';
|
|
6
|
+
import type { GrChipTone } from '../GrChip/grChipStyles';
|
|
6
7
|
export type GrSelectOptionsView = 'native' | 'panel';
|
|
7
8
|
/**
|
|
8
9
|
* Тип значения опции. Ограничен примитивами, которые переживают путь через DOM:
|
|
@@ -20,6 +21,17 @@ export type GrSelectOption<TValue extends GrSelectValue = string> = {
|
|
|
20
21
|
value: TValue;
|
|
21
22
|
label: string;
|
|
22
23
|
disabled?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Тон чипа в режиме `tags` — перекрывает `tagTone` для этой опции.
|
|
26
|
+
*
|
|
27
|
+
* Цвет у каждого тега свой — обычная модель (метки, категории, статусы), и
|
|
28
|
+
* без неё потребитель уходил в слот `#value` рисовать выбранное сам, теряя
|
|
29
|
+
* ровно то, что в `tags` сделано правильно: чипы снаружи `role="combobox"`,
|
|
30
|
+
* снятие крестиком, сворачивание в «+N» и клавиатуру.
|
|
31
|
+
*/
|
|
32
|
+
tone?: GrChipTone;
|
|
33
|
+
/** Плотная заливка чипа этой опции — перекрывает `tagDark`. */
|
|
34
|
+
dark?: boolean;
|
|
23
35
|
};
|
|
24
36
|
/** Группа опций: заголовок `label` + вложенные опции `options`. */
|
|
25
37
|
export type GrSelectOptionGroup<TValue extends GrSelectValue = string> = {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Предупреждение о пропе, который переименовали.
|
|
3
|
+
*
|
|
4
|
+
* Незнакомый атрибут Vue не отвергает: он уходит в `$attrs` и садится на
|
|
5
|
+
* корневой узел. Значит переименование пропа проходит у потребителя **молча** —
|
|
6
|
+
* не падают ни типы (`vue-tsc` не проверяет лишние атрибуты: принимать их
|
|
7
|
+
* вправе любой компонент), ни рантайм. Компонент просто рисуется дефолтом, и
|
|
8
|
+
* найти это можно только сверкой шаблона со списком пропов.
|
|
9
|
+
*
|
|
10
|
+
* Так и случилось со сменой `variant` на `tone` у `GrBadge` и `GrChip`: у
|
|
11
|
+
* стороннего пакета тихо разъехались десять мест в шести файлах. Причём
|
|
12
|
+
* `variant` в кольце остаётся законным именем у `GrButton`, `GrCard`, `GrAlert`
|
|
13
|
+
* и десятка других — то есть по аналогии не угадать.
|
|
14
|
+
*
|
|
15
|
+
* Предупреждение живёт только в разработке и ничего не чинит за потребителя:
|
|
16
|
+
* подставлять снятое имя значило бы завести алиас, который после 1.0 останется
|
|
17
|
+
* навсегда.
|
|
18
|
+
*/
|
|
19
|
+
export declare function warnRenamedProp(component: string, attrs: Record<string, unknown>, renames: Readonly<Record<string, string>>): void;
|
package/dist/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
|
|
3
3
|
"name": "@feugene/granularity",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.31.0",
|
|
5
5
|
"framework": "vue",
|
|
6
6
|
"js-types-syntax": "typescript",
|
|
7
7
|
"description-markup": "markdown",
|
|
@@ -1235,6 +1235,10 @@
|
|
|
1235
1235
|
"name": "header",
|
|
1236
1236
|
"description": "Шапка вместо пропов `title` и `description`."
|
|
1237
1237
|
},
|
|
1238
|
+
{
|
|
1239
|
+
"name": "actions",
|
|
1240
|
+
"description": "Действия справа в собственной шапке карточки: «⋯», «Обновить», переключатель периода. Включают шапку так же, как `title`. Со слотом `#header` не сочетается: тот заменяет шапку целиком, и всё, что в ней есть, рисует потребитель."
|
|
1241
|
+
},
|
|
1238
1242
|
{
|
|
1239
1243
|
"name": "footer",
|
|
1240
1244
|
"description": "Подвал: действия, сводка, пагинация."
|
|
@@ -5541,6 +5545,15 @@
|
|
|
5541
5545
|
"kind": "expression",
|
|
5542
5546
|
"type": "GrInputTextAlign | undefined"
|
|
5543
5547
|
}
|
|
5548
|
+
},
|
|
5549
|
+
{
|
|
5550
|
+
"name": "addon",
|
|
5551
|
+
"description": "Как выглядят аддоны `#prefix`/`#suffix`. `segment` (по умолчанию) — отдельный отсек, отрезанный рамкой и выровненный по ступени размера: так поле с «₽» и поле с «USD» стоят в колонку. `inline` — украшение внутри рамки: ни разделителя, ни своей ширины. Разница не косметическая. Поисковая строка с лупой в сегменте читается составным элементом — полем с приклеенной кнопкой, — а не одним полем; именно поэтому иконку внутри рамки нельзя было выразить аддоном, и потребители отказывались от неё вовсе.",
|
|
5552
|
+
"default": "\"segment\"",
|
|
5553
|
+
"value": {
|
|
5554
|
+
"kind": "expression",
|
|
5555
|
+
"type": "\"inline\" | \"segment\" | undefined"
|
|
5556
|
+
}
|
|
5544
5557
|
}
|
|
5545
5558
|
],
|
|
5546
5559
|
"slots": [
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feugene/granularity",
|
|
3
3
|
"description": "Granularity design system package with Vue 3 components, consumed via the `@feugene/unocss-preset-granular` preset.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.31.0",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Evgeniy Fureev",
|
|
@@ -607,7 +607,7 @@
|
|
|
607
607
|
"devDependencies": {
|
|
608
608
|
"@antfu/eslint-config": "^9.1.0",
|
|
609
609
|
"@feugene/fint-i18n": "^0.6.0",
|
|
610
|
-
"@feugene/granularity-test-kit": "^0.
|
|
610
|
+
"@feugene/granularity-test-kit": "^0.7.0",
|
|
611
611
|
"@feugene/unocss-preset-granular": "^0.10.1",
|
|
612
612
|
"@floating-ui/dom": "^1.8.0",
|
|
613
613
|
"@iconify-json/lucide": "^1.2.117",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-DO8mjeIo.js","names":[],"sources":["../../src/components/GrInput/safelist.ts","../../src/components/GrInput/config.ts"],"sourcesContent":["import { splitClassTokens } from '../shared/classTokens'\nimport { invalidClass, shellBaseClass, shellDisabledClass, shellEnabledClass, sizes, states, textAlign } from './grInputStyles'\n\nexport const grInputSafelist = [...new Set([\n ...Object.values(sizes).flatMap(splitClassTokens),\n ...Object.values(textAlign).flatMap(splitClassTokens),\n ...Object.values(states).flatMap(splitClassTokens),\n ...splitClassTokens(invalidClass),\n ...splitClassTokens(shellBaseClass),\n ...splitClassTokens(shellEnabledClass),\n ...splitClassTokens(shellDisabledClass),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\nimport { grInputSafelist } from './safelist'\n\nexport const grInputConfig = defineGranularComponent(import.meta.url, {\n name: 'GrInput',\n safelist: grInputSafelist,\n})\n"],"mappings":";;;;AAGA,IAAa,kBAAkB,CAAC,mBAAG,IAAI,IAAI;CACzC,GAAG,OAAO,OAAO,KAAK,CAAC,CAAC,QAAQ,gBAAgB;CAChD,GAAG,OAAO,OAAO,SAAS,CAAC,CAAC,QAAQ,gBAAgB;CACpD,GAAG,OAAO,OAAO,MAAM,CAAC,CAAC,QAAQ,gBAAgB;CACjD,GAAG,iBAAiB,YAAY;CAChC,GAAG,iBAAiB,cAAc;CAClC,GAAG,iBAAiB,iBAAiB;CACrC,GAAG,iBAAiB,kBAAkB;AACxC,CAAC,CAAC;;;ACRF,IAAa,gBAAgB,wBAAwB,OAAO,KAAK,KAAK;CACpE,MAAM;CACN,UAAU;AACZ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-Dpk-eVkS.js","names":[],"sources":["../../src/components/GrCard/grCardStyles.ts","../../src/components/GrCard/safelist.ts","../../src/components/GrCard/config.ts"],"sourcesContent":["export type GrCardPadding = 'none' | 'sm' | 'md' | 'lg'\nexport type GrCardVariant = 'elevated' | 'outlined' | 'ghost'\n\n/**\n * Классы `GrCard`.\n *\n * `elevated` — дефолт и ровно тот вид, что был у карточки до появления пропов:\n * `GrCollapse` и `GrList` рендерят содержимое внутрь `GrCard`, и любое смещение\n * дефолта поехало бы у них.\n */\n\nexport const surfaceBaseClass = 'rounded-[var(--gr-radius-lg)] bg-[var(--gr-card)] text-[var(--gr-card-fg)]'\n\nexport const variantClass: Record<GrCardVariant, string> = {\n // Тень — токеном, а не утилитой uno-шкалы: у той зашит свой полупрозрачный\n // цвет, темой он не настраивается, и на тёмном фоне тени не получалось вовсе\n // — карточка теряла подъём и держалась на одной рамке. Токен темозависим.\n // Имя утилиты здесь не пишется намеренно: UnoCSS сканирует текст файла и\n // сгенерировал бы класс прямо из комментария.\n elevated: 'border border-[var(--gr-brd)] shadow-[var(--gr-shadow-1)]',\n outlined: 'border border-[var(--gr-brd)]',\n // Карточка внутри карточки: вторая рамка только шумит.\n ghost: '',\n}\n\nexport const paddingClass: Record<GrCardPadding, string> = {\n none: '',\n sm: 'p-3',\n md: 'p-4',\n lg: 'p-6',\n}\n\nexport const sectionDividerTopClass = 'border-t border-[var(--gr-brd)]'\nexport const sectionDividerBottomClass = 'border-b border-[var(--gr-brd)]'\n\n/**\n * Отступ шапки, которую карточка рисует сама из `title`.\n *\n * Не берётся из `padding`: тот описывает **содержимое**, и дефолт `none` у него\n * осмыслен — на `GrCard` стоят `GrCollapse` и `GrList`, а карточка с таблицей\n * хочет её край в край. Заголовок же принадлежит самой карточке, и прижатым к\n * рамке вместе с разделителем он выглядеть не должен ни при каком `padding`.\n *\n * По вертикали отступ меньше горизонтального: шапка — строка, а не блок.\n */\nexport const ownHeaderPaddingClass = 'px-4 py-3'\n\n/**\n * Уровень заголовка карточки. `h1` намеренно нет: его задаёт страница, а\n * карточка — блок внутри уже существующей структуры.\n */\nexport const GR_CARD_HEADING_LEVELS = [2, 3, 4, 5, 6] as const\n\nexport type GrCardHeadingLevel = typeof GR_CARD_HEADING_LEVELS[number]\n\n// `m-0` — у нативного заголовка есть браузерные отступы, и без сброса шапка\n// разъезжается по вертикали.\nexport const cardTitleClass = 'm-0 text-[length:var(--gr-text-sm)] leading-[var(--gr-leading-sm)] font-600'\n\nexport const cardDescriptionClass = 'mt-1 text-[length:var(--gr-text-xs)] leading-[var(--gr-leading-xs)] text-[var(--gr-muted-fg)]'\n\n/** Интерактивная карточка целиком: ссылка или кнопка во всю поверхность. */\nexport const interactiveClass = 'block w-full text-left transition-colors duration-[var(--gr-duration-fast)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]'\n\nexport const hoverClass = 'cursor-pointer hover:bg-[var(--gr-muted)]'\n\nexport function grCardRootClass(options: {\n variant: GrCardVariant\n /** Падинг едет на корень, только пока нет секций — иначе лишняя обёртка. */\n padding: GrCardPadding\n interactive: boolean\n hoverable: boolean\n}): string {\n return [\n surfaceBaseClass,\n variantClass[options.variant],\n paddingClass[options.padding],\n options.interactive ? interactiveClass : '',\n options.interactive || options.hoverable ? hoverClass : '',\n ].filter(Boolean).join(' ')\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n cardDescriptionClass,\n cardTitleClass,\n hoverClass,\n interactiveClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n surfaceBaseClass,\n variantClass,\n} from './grCardStyles'\n\nexport const grCardSafelist = [...new Set([\n ...splitClassTokens(surfaceBaseClass),\n ...Object.values(variantClass).flatMap(splitClassTokens),\n ...Object.values(paddingClass).flatMap(splitClassTokens),\n ...splitClassTokens(ownHeaderPaddingClass),\n ...splitClassTokens(sectionDividerTopClass),\n ...splitClassTokens(sectionDividerBottomClass),\n ...splitClassTokens(interactiveClass),\n ...splitClassTokens(hoverClass),\n ...splitClassTokens(cardTitleClass),\n ...splitClassTokens(cardDescriptionClass),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grCardSafelist } from './safelist'\n\nexport const grCardConfig = defineGranularComponent(import.meta.url, {\n name: 'GrCard',\n safelist: grCardSafelist,\n})\n"],"mappings":";;;;;;;;;;AAWA,IAAa,mBAAmB;AAEhC,IAAa,eAA8C;CAMzD,UAAU;CACV,UAAU;CAEV,OAAO;AACT;AAEA,IAAa,eAA8C;CACzD,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAa,yBAAyB;AACtC,IAAa,4BAA4B;;;;;;;;;;;AAYzC,IAAa,wBAAwB;AAYrC,IAAa,iBAAiB;AAE9B,IAAa,uBAAuB;;AAGpC,IAAa,mBAAmB;AAEhC,IAAa,aAAa;AAE1B,SAAgB,gBAAgB,SAMrB;CACT,OAAO;EACL;EACA,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,QAAQ,cAAc,mBAAmB;EACzC,QAAQ,eAAe,QAAQ,YAAY,aAAa;CAC1D,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC5B;;;AClEA,IAAa,iBAAiB,CAAC,mBAAG,IAAI,IAAI;CACxC,GAAG,iBAAiB,gBAAgB;CACpC,GAAG,OAAO,OAAO,YAAY,CAAC,CAAC,QAAQ,gBAAgB;CACvD,GAAG,OAAO,OAAO,YAAY,CAAC,CAAC,QAAQ,gBAAgB;CACvD,GAAG,iBAAiB,qBAAqB;CACzC,GAAG,iBAAiB,sBAAsB;CAC1C,GAAG,iBAAiB,yBAAyB;CAC7C,GAAG,iBAAiB,gBAAgB;CACpC,GAAG,iBAAiB,UAAU;CAC9B,GAAG,iBAAiB,cAAc;CAClC,GAAG,iBAAiB,oBAAoB;AAC1C,CAAC,CAAC;;;ACrBF,IAAa,eAAe,wBAAwB,OAAO,KAAK,KAAK;CACnE,MAAM;CACN,UAAU;AACZ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GrBadge-BM3f9PME.js","names":[],"sources":["../../../../src/components/GrBadge/GrBadge.vue","../../../../src/components/GrBadge/GrBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nexport type { GrBadgeRadius, GrBadgeSize, GrBadgeTone } from './grBadgeStyles'\n\nimport {\n grBadgeClass,\n type GrBadgeRadius,\n type GrBadgeSize,\n type GrBadgeTone,\n} from './grBadgeStyles'\n\nexport interface GrBadgeProps {\n tone?: GrBadgeTone\n dark?: boolean\n size?: GrBadgeSize\n radius?: GrBadgeRadius\n}\n\nconst props = withDefaults(\n defineProps<GrBadgeProps>(),\n {\n // `tone`/`size`/`radius` настраиваются через `GrConfigProvider`, поэтому\n // их дефолты живут в резолверах ниже, а не в `withDefaults`.\n tone: undefined,\n dark: false,\n size: undefined,\n radius: undefined,\n },\n)\n\n// Эффективные значения: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedTone = useGrComponentProp('GrBadge', 'tone', () => props.tone, 'neutral')\nconst resolvedSize = useGrComponentProp('GrBadge', 'size', () => props.size, 'sm')\nconst resolvedRadius = useGrComponentProp('GrBadge', 'radius', () => props.radius, 'round')\n\nconst className = computed(() => {\n return grBadgeClass({\n tone: resolvedTone.value,\n dark: props.dark,\n size: resolvedSize.value,\n radius: resolvedRadius.value,\n })\n})\n\ndefineSlots<{\n /** Содержимое метки. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <span\n class=\"gr-badge inline-block border whitespace-nowrap leading-none\"\n :class=\"className\"\n >\n <span class=\"gr-badge__label\">\n <span class=\"gr-badge__text\">\n <slot />\n </span>\n </span>\n </span>\n</template>\n\n<style scoped>\n/*\n * Оптически центрируем текст по вертикали независимо от регистра,\n * не уменьшая высоту самого бейджа.\n *\n * Высоту держит обёртка `.gr-badge__label` (`min-height: 1lh` — высота\n * line-box при `leading-none`), а текст (`.gr-badge__text`) обрезается до\n * cap-height и центрируется внутри этой высоты через flex.\n *\n * Обрезка обязана жить на вложенном узле, а не на самом тексте: `text-box-trim`\n * уменьшает line-box, и повесь его прямо на текст — вместе с ним просядет\n * высота контента, а за ней и весь бейдж.\n */\n.gr-badge__label {\n display: flex;\n align-items: center;\n min-height: 1lh;\n}\n\n.gr-badge__text {\n display: block;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n /* Шорткат для браузеров с поддержкой нового синтаксиса. */\n text-box: trim-both cap alphabetic;\n}\n</style>","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nexport type { GrBadgeRadius, GrBadgeSize, GrBadgeTone } from './grBadgeStyles'\n\nimport {\n grBadgeClass,\n type GrBadgeRadius,\n type GrBadgeSize,\n type GrBadgeTone,\n} from './grBadgeStyles'\n\nexport interface GrBadgeProps {\n tone?: GrBadgeTone\n dark?: boolean\n size?: GrBadgeSize\n radius?: GrBadgeRadius\n}\n\nconst props = withDefaults(\n defineProps<GrBadgeProps>(),\n {\n // `tone`/`size`/`radius` настраиваются через `GrConfigProvider`, поэтому\n // их дефолты живут в резолверах ниже, а не в `withDefaults`.\n tone: undefined,\n dark: false,\n size: undefined,\n radius: undefined,\n },\n)\n\n// Эффективные значения: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedTone = useGrComponentProp('GrBadge', 'tone', () => props.tone, 'neutral')\nconst resolvedSize = useGrComponentProp('GrBadge', 'size', () => props.size, 'sm')\nconst resolvedRadius = useGrComponentProp('GrBadge', 'radius', () => props.radius, 'round')\n\nconst className = computed(() => {\n return grBadgeClass({\n tone: resolvedTone.value,\n dark: props.dark,\n size: resolvedSize.value,\n radius: resolvedRadius.value,\n })\n})\n\ndefineSlots<{\n /** Содержимое метки. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <span\n class=\"gr-badge inline-block border whitespace-nowrap leading-none\"\n :class=\"className\"\n >\n <span class=\"gr-badge__label\">\n <span class=\"gr-badge__text\">\n <slot />\n </span>\n </span>\n </span>\n</template>\n\n<style scoped>\n/*\n * Оптически центрируем текст по вертикали независимо от регистра,\n * не уменьшая высоту самого бейджа.\n *\n * Высоту держит обёртка `.gr-badge__label` (`min-height: 1lh` — высота\n * line-box при `leading-none`), а текст (`.gr-badge__text`) обрезается до\n * cap-height и центрируется внутри этой высоты через flex.\n *\n * Обрезка обязана жить на вложенном узле, а не на самом тексте: `text-box-trim`\n * уменьшает line-box, и повесь его прямо на текст — вместе с ним просядет\n * высота контента, а за ней и весь бейдж.\n */\n.gr-badge__label {\n display: flex;\n align-items: center;\n min-height: 1lh;\n}\n\n.gr-badge__text {\n display: block;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n /* Шорткат для браузеров с поддержкой нового синтаксиса. */\n text-box: trim-both cap alphabetic;\n}\n</style>"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAqBA,MAAM,QAAQ;EAad,MAAM,eAAe,mBAAmB,WAAW,cAAc,MAAM,MAAM,SAAS;EACtF,MAAM,eAAe,mBAAmB,WAAW,cAAc,MAAM,MAAM,IAAI;EACjF,MAAM,iBAAiB,mBAAmB,WAAW,gBAAgB,MAAM,QAAQ,OAAO;EAE1F,MAAM,YAAY,eAAe;GAC/B,OAAO,aAAa;IAClB,MAAM,aAAa;IACnB,MAAM,MAAM;IACZ,MAAM,aAAa;IACnB,QAAQ,eAAe;GACzB,CAAC;EACH,CAAC;;uBAUC,mBASO,QAAA,EARH,OAAK,eAAA,CAAC,+DACE,UAAA,KAAS,CAAA,EAAA,GAAA,CAEnB,mBAIO,QAJP,YAIO,CAHL,mBAEO,QAFP,YAEO,CADL,WAAQ,KAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,IAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GrCard-DR3ehBt8.js","names":["$slots"],"sources":["../../../../src/components/GrCard/GrCard.vue","../../../../src/components/GrCard/GrCard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button') return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button') return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDA,MAAM,QAAQ;EAcd,MAAM,OAAO;EAEb,MAAM,QAAQ,SAAS;EAEvB,MAAM,kBAAkB,mBAAmB,UAAU,iBAAiB,MAAM,SAAS,MAAM;EAC3F,MAAM,kBAAkB,mBAAmB,UAAU,iBAAiB,MAAM,SAAS,UAAU;EAE/F,MAAM,gBAAgB,eAAe,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,MAAM,QAAQ,MAAM,SAAS;EAElF,MAAM,UAAU,eAAmC;GACjD,IAAI,MAAM,IACR,OAAO,OAAO,MAAM,OAAO,WAAW,MAAM,KAAK,QAAQ,MAAM,EAAE;GAEnE,IAAI,MAAM,MACR,OAAO;GAET,OAAO,MAAM,YAAY,WAAW;EACtC,CAAC;;;;;;EAOD,MAAM,WAAW,eACf,OAAO,QAAQ,UAAU,YAAY,QAAQ,UAAU,MAAM,KAAA,IAAY,MAAM,IAChF;EAED,MAAM,eAAe,mBAAmB,UAAU,sBAAsB,MAAM,cAAc,CAAC;;;;;;EAO7F,IAAI,wBAAwB;EAE5B,MAAM,aAAa,eAAe;GAChC,IAAI,QAAQ,UAAU,UAAU,OAAO,IAAI,aAAa;GAExD,IAAI,CAAC,yBAAA,OAAA,YAAA,eAAA,QAAA,IAAA,aAAA,cAAqC;IACxC,wBAAwB;IACxB,QAAQ,KACN,mNAGF;GACF;GAEA,OAAO;EACT,CAAC;EAED,MAAM,UAAU,MAAM;EACtB,MAAM,gBAAgB,MAAM;EAI5B,MAAM,eAAe,eAAe,QAAQ,MAAM,MAAM,CAAC;EACzD,MAAM,WAAW,eAAe,CAAC,aAAa,SAAS,QAAQ,MAAM,KAAK,CAAC;EAC3E,MAAM,iBAAiB,eAAe,CAAC,aAAa,SAAS,QAAQ,MAAM,WAAW,CAAC;EACvF,MAAM,kBAAkB,eAAe,SAAS,SAAS,eAAe,KAAK;;;;;;EAO7E,MAAM,cAAc,eAAe,QACjC,MAAM,UAAU,MAAM,UAAU,MAAM,aAAa,gBAAgB,KACrE,CAAC;;;;;EAMD,MAAM,iBAAiB,eAAgB,cAAc,SAAS,SAAS,QAAQ,UAAU,KAAA,CAAU;EACnG,MAAM,kBAAkB,eAAgB,cAAc,SAAS,eAAe,QAAQ,gBAAgB,KAAA,CAAU;EAEhH,MAAM,YAAY,eAAe,gBAAgB;GAC/C,SAAS,gBAAgB;GAEzB,SAAS,YAAY,QAAQ,SAAS,gBAAgB;GACtD,aAAa,cAAc;GAC3B,WAAW,MAAM;EACnB,CAAC,CAAC;EAEF,MAAM,sBAAsB,eAAe,aAAa,gBAAgB,MAAM;;;;;;;EAQ9E,MAAM,cAAc,eAAe,CACjC,aAAa,QAAQ,oBAAoB,QAAQ,uBACjD,yBACF,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC;EAC3B,MAAM,cAAc,eAAe,CAAC,oBAAoB,OAAO,sBAAsB,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC;EAChH,MAAM,mBAAmB,eAAe,CAAC,oBAAoB,OAAO,MAAM,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC;EAE9G,SAAS,QAAQ,OAAyB;GACxC,KAAK,SAAS,KAAK;EACrB;;uBAcE,YA4CY,wBA3CL,QAAA,KAAO,GAAA;IACZ,gBAAA;IACC,MAAM,QAAA,UAAO,WAAA,WAA2B,KAAA;IACxC,MAAM,SAAA;IACN,OAAK,eAAE,UAAA,KAAS;IAChB,mBAAiB,eAAA;IACjB,oBAAkB,gBAAA;IACX;;2BAiCG,CA/BK,YAAA,SAAA,UAAA,GAAhB,mBA+BW,UAAA,EAAA,KAAA,EAAA,GAAA;KA9BE,aAAA,SAAgB,gBAAA,SAAA,UAAA,GAA3B,mBAqBM,OAAA;;MArBsC,uBAAA;MAAqB,OAAK,eAAE,YAAA,KAAW;SACjF,WAmBO,KAAA,QAAA,UAAA,CAAA,SAAA,CAhBG,SAAA,SAAA,UAAA,GAFR,YAQY,wBAPL,WAAA,KAAU,GAAA;;MAEd,IAAI,MAAA,OAAA;MACL,sBAAA;MACC,OAAK,eAAE,MAAA,cAAA,CAAc;;6BAEX,CAAA,gBAAA,gBAAR,QAAA,KAAK,GAAA,CAAA,CAAA,CAAA;;6DAIF,eAAA,SAAA,UAAA,GADR,mBAOI,KAAA;;MALD,IAAI,MAAA,aAAA;MACL,4BAAA;MACC,OAAK,eAAE,MAAA,oBAAA,CAAoB;wBAEzB,QAAA,WAAW,GAAA,IAAA,UAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;KAKpB,mBAEM,OAAA;MAFD,qBAAA;MAAmB,OAAK,eAAE,iBAAA,KAAgB;SAC7C,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA;KAGCA,KAAAA,OAAO,UAAA,UAAA,GAAlB,mBAEM,OAAA;;MAFoB,uBAAA;MAAqB,OAAK,eAAE,YAAA,KAAW;SAC/D,WAAsB,KAAA,QAAA,QAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;cAI1B,WAAe,KAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GrChip-Df4orxRH.js","names":["$slots"],"sources":["../../../../src/components/GrChip/GrChip.vue","../../../../src/components/GrChip/GrChip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, ref } from 'vue'\n\nimport IconClose from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\n\nimport type { GrChipValue } from './grChipGroupContext'\nimport { GR_CHIP_GROUP_CONTEXT } from './grChipGroupContext'\nimport type { GrChipRadius, GrChipSize, GrChipTone } from './grChipStyles'\nimport {\n chipCloseButtonClass,\n chipCloseClass,\n chipIconClass,\n chipIconSizeClassBySize,\n chipLabelClass,\n grChipClass,\n} from './grChipStyles'\n\n/**\n * Интерактивный тег: снимаемый, выбираемый, с иконкой.\n *\n * От `GrBadge` отличается не видом, а природой: бейдж — метка, чип — виджет.\n * Поэтому цвета и радиусы взяты у бейджа как есть (в одном ряду они обязаны\n * совпадать), а роль, клавиатура и размеры — свои.\n */\nexport interface GrChipProps {\n /** Значение чипа в группе. Вне `GrChipGroup` не используется. */\n value?: GrChipValue\n /**\n * Подпись. Нужна отдельно от слота: из неё собирается имя кнопки снятия —\n * «Убрать» на двадцати кнопках подряд не даёт выбрать нужную.\n */\n label?: string\n tone?: GrChipTone\n dark?: boolean\n size?: GrChipSize\n radius?: GrChipRadius\n /** Чип становится переключателем: `aria-pressed`, `Enter`/`Space`. */\n selectable?: boolean\n /** Состояние переключателя вне группы. Внутри группы значение ведёт группа. */\n selected?: boolean\n /** Крестик. Внутри виджета он не кнопка — см. блок про роли ниже. */\n closable?: boolean\n disabled?: boolean\n /** Доступное имя, когда подпись не объясняет назначения. */\n ariaLabel?: string\n /** Имя кнопки снятия целиком. Перебивает собранное из `label`. */\n removeLabel?: string\n /**\n * `tabindex` кнопки снятия — для чипа внутри поля ввода.\n *\n * Там таб-стоп принадлежит `<input>`, а ряд чипов ходит стрелками: у\n * `GrInputTag` кольцо оставляет ровно один `0`, у `GrAutocomplete` их нет\n * вовсе. Проп нужен потому, что кольцом управляет родитель — он знает и\n * порядок чипов, и что стоит за краем ряда.\n */\n removeTabindex?: number\n}\n\nexport interface GrChipEmits {\n (e: 'update:selected', value: boolean): void\n (e: 'remove'): void\n}\n\nconst props = withDefaults(defineProps<GrChipProps>(), {\n value: undefined,\n label: undefined,\n // Дефолты живут в резолверах ниже: Vue подставил бы свой раньше, чем\n // компонент заглянет в `GrConfigProvider`.\n tone: undefined,\n dark: undefined,\n size: undefined,\n radius: undefined,\n selectable: false,\n selected: false,\n closable: false,\n disabled: false,\n ariaLabel: undefined,\n removeLabel: undefined,\n removeTabindex: undefined,\n})\n\nconst emit = defineEmits<GrChipEmits>()\n\ndefineSlots<{\n /** Подпись чипа. Внутри выбираемого чипа — только фразовое содержимое. */\n default?: () => unknown\n /** Иконка перед подписью. */\n icon?: () => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst group = inject(GR_CHIP_GROUP_CONTEXT, null)\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst inGroup = computed(() => group !== null && props.value !== undefined)\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled.value ?? false))\nconst isReadonly = computed(() => group?.readonly.value ?? false)\n\n/**\n * Чип — виджет ровно тогда, когда по нему кликают.\n *\n * От этого зависит вся разметка: у виджета роль, `tabindex` и клавиатура, а\n * крестик внутри него перестаёт быть кнопкой.\n */\nconst isInteractive = computed(() => inGroup.value || props.selectable)\n\nconst isSelected = computed(() => {\n if (inGroup.value && props.value !== undefined) return group!.isSelected(props.value)\n return props.selected\n})\n\nconst isClosable = computed(() => {\n if (isReadonly.value || isDisabled.value) return false\n return props.closable || (inGroup.value ? group!.closable.value : false)\n})\n\n// Приоритет: локальный проп → значение группы → `GrConfigProvider` → дефолт.\n// Группа специфичнее конфига, поэтому её значение подаётся как «локальное».\nconst resolvedSize = useGrComponentSize<GrChipSize>(\n () => props.size ?? (inGroup.value ? group!.size.value : undefined),\n { component: 'GrChip' },\n)\nconst resolvedTone = useGrComponentProp(\n 'GrChip',\n 'tone',\n () => props.tone ?? (inGroup.value ? group!.tone.value : undefined),\n 'neutral',\n)\nconst resolvedRadius = useGrComponentProp(\n 'GrChip',\n 'radius',\n () => props.radius ?? (inGroup.value ? group!.radius.value : undefined),\n 'round',\n)\nconst resolvedDark = useGrComponentProp(\n 'GrChip',\n 'dark',\n () => props.dark ?? (inGroup.value ? group!.dark.value : undefined),\n false,\n)\n\nconst rootClass = computed(() => grChipClass({\n tone: resolvedTone.value,\n dark: resolvedDark.value,\n size: resolvedSize.value,\n radius: resolvedRadius.value,\n interactive: isInteractive.value && !isReadonly.value,\n selected: isSelected.value,\n disabled: isDisabled.value,\n}))\n\nconst iconSizeClass = computed(() => chipIconSizeClassBySize[resolvedSize.value])\n\nconst removeTitle = computed(() => {\n if (props.removeLabel) return props.removeLabel\n if (props.label) return t('gr.chip.removeNamed', 'Remove {label}', { label: props.label })\n return t('gr.chip.remove', 'Remove')\n})\n\n/**\n * Роль чипа задаёт группа, а не потребитель.\n *\n * Одиночный переключатель — кнопка с `aria-pressed`; в группе роль зависит от\n * множественности выбора: `radio` в одиночной (образец — `GrSegmented`),\n * `option` во множественной, где контейнер объявлен `listbox` c\n * `aria-multiselectable`.\n */\nconst chipRole = computed(() => {\n if (!inGroup.value) return undefined\n return group!.selection.value === 'single' ? 'radio' : 'option'\n})\n\nconst tabindex = computed(() => {\n if (!isInteractive.value) return undefined\n if (isDisabled.value) return -1\n if (!inGroup.value || props.value === undefined) return 0\n return group!.rovingValue.value === props.value ? 0 : -1\n})\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value) return\n\n if (inGroup.value && props.value !== undefined) {\n group!.toggle(props.value)\n return\n }\n\n if (props.selectable) emit('update:selected', !props.selected)\n}\n\nfunction requestRemove(): void {\n if (!isClosable.value) return\n\n emit('remove')\n if (inGroup.value && props.value !== undefined) group!.requestRemove(props.value)\n}\n\n/**\n * Крестик внутри виджета — не кнопка, поэтому его клик приходит сюда же и\n * разбирается по цели. Тот же приём у `GrTabs`: внутрь роли-виджета вложенная\n * кнопка запрещена (axe: `nested-interactive`), а `<button>` внутри `<button>`\n * невалиден и по контент-модели HTML.\n */\nfunction onRootClick(event: MouseEvent): void {\n if (isDisabled.value) return\n\n if (event.target instanceof Element && event.target.closest('[data-gr-chip-close]')) {\n requestRemove()\n return\n }\n\n toggle()\n}\n\nfunction onRootKeydown(event: KeyboardEvent): void {\n if (isDisabled.value) return\n\n // Навигация принадлежит группе: состав знает только она.\n if (inGroup.value && group!.handleNavigationKeys(event)) return\n\n if (event.key === 'Delete' || event.key === 'Backspace') {\n if (!isClosable.value) return\n event.preventDefault()\n requestRemove()\n }\n}\n\nif (group) {\n const unregister = group.register({\n value: () => props.value as GrChipValue,\n disabled: () => isDisabled.value,\n el: () => rootEl.value,\n })\n onBeforeUnmount(unregister)\n}\n\nconst removeEl = ref<HTMLButtonElement | null>(null)\n\ndefineExpose({\n focus: () => rootEl.value?.focus(),\n blur: () => rootEl.value?.blur(),\n /**\n * Кнопка снятия — цель roving-фокуса у родителя. Отдаётся элементом, а не\n * методом `focusRemove`: кольцу нужен сам узел, оно само решает, когда и\n * куда переносить фокус.\n */\n removeEl,\n})\n</script>\n\n<template>\n <component\n :is=\"isInteractive ? 'button' : 'span'\"\n ref=\"rootEl\"\n data-gr-chip\n :type=\"isInteractive ? 'button' : undefined\"\n :class=\"rootClass\"\n :role=\"chipRole\"\n :data-value=\"value\"\n :aria-label=\"ariaLabel\"\n :aria-checked=\"chipRole === 'radio' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-selected=\"chipRole === 'option' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-pressed=\"isInteractive && !chipRole ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :disabled=\"isInteractive && isDisabled ? true : undefined\"\n :aria-keyshortcuts=\"isInteractive && isClosable ? 'Delete' : undefined\"\n :tabindex=\"tabindex\"\n @click=\"isInteractive ? onRootClick($event) : undefined\"\n @keydown=\"isInteractive ? onRootKeydown($event) : undefined\"\n >\n <span v-if=\"$slots.icon\" data-gr-chip-icon :class=\"[chipIconClass, iconSizeClass]\">\n <slot name=\"icon\" />\n </span>\n\n <span data-gr-chip-label :class=\"chipLabelClass\">\n <slot>{{ label }}</slot>\n </span>\n\n <!--\n Крестик существует в двух видах, и различитель — роль самого чипа.\n Виджет: `<span aria-hidden>` вне таб-порядка, снятие идёт `Delete`/`Backspace`.\n Не виджет: настоящая кнопка со своей остановкой `Tab` и своим именем.\n -->\n <span\n v-if=\"isClosable && isInteractive\"\n data-gr-chip-close\n :class=\"[chipCloseClass, iconSizeClass]\"\n :title=\"removeTitle\"\n aria-hidden=\"true\"\n >\n <IconClose class=\"h-full w-full\" />\n </span>\n\n <button\n v-else-if=\"isClosable\"\n ref=\"removeEl\"\n data-gr-chip-close\n type=\"button\"\n :class=\"[chipCloseButtonClass, iconSizeClass]\"\n :aria-label=\"removeTitle\"\n :tabindex=\"removeTabindex\"\n @mousedown.prevent.stop\n @click.stop=\"requestRemove()\"\n >\n <IconClose class=\"h-full w-full\" />\n </button>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onBeforeUnmount, ref } from 'vue'\n\nimport IconClose from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\n\nimport type { GrChipValue } from './grChipGroupContext'\nimport { GR_CHIP_GROUP_CONTEXT } from './grChipGroupContext'\nimport type { GrChipRadius, GrChipSize, GrChipTone } from './grChipStyles'\nimport {\n chipCloseButtonClass,\n chipCloseClass,\n chipIconClass,\n chipIconSizeClassBySize,\n chipLabelClass,\n grChipClass,\n} from './grChipStyles'\n\n/**\n * Интерактивный тег: снимаемый, выбираемый, с иконкой.\n *\n * От `GrBadge` отличается не видом, а природой: бейдж — метка, чип — виджет.\n * Поэтому цвета и радиусы взяты у бейджа как есть (в одном ряду они обязаны\n * совпадать), а роль, клавиатура и размеры — свои.\n */\nexport interface GrChipProps {\n /** Значение чипа в группе. Вне `GrChipGroup` не используется. */\n value?: GrChipValue\n /**\n * Подпись. Нужна отдельно от слота: из неё собирается имя кнопки снятия —\n * «Убрать» на двадцати кнопках подряд не даёт выбрать нужную.\n */\n label?: string\n tone?: GrChipTone\n dark?: boolean\n size?: GrChipSize\n radius?: GrChipRadius\n /** Чип становится переключателем: `aria-pressed`, `Enter`/`Space`. */\n selectable?: boolean\n /** Состояние переключателя вне группы. Внутри группы значение ведёт группа. */\n selected?: boolean\n /** Крестик. Внутри виджета он не кнопка — см. блок про роли ниже. */\n closable?: boolean\n disabled?: boolean\n /** Доступное имя, когда подпись не объясняет назначения. */\n ariaLabel?: string\n /** Имя кнопки снятия целиком. Перебивает собранное из `label`. */\n removeLabel?: string\n /**\n * `tabindex` кнопки снятия — для чипа внутри поля ввода.\n *\n * Там таб-стоп принадлежит `<input>`, а ряд чипов ходит стрелками: у\n * `GrInputTag` кольцо оставляет ровно один `0`, у `GrAutocomplete` их нет\n * вовсе. Проп нужен потому, что кольцом управляет родитель — он знает и\n * порядок чипов, и что стоит за краем ряда.\n */\n removeTabindex?: number\n}\n\nexport interface GrChipEmits {\n (e: 'update:selected', value: boolean): void\n (e: 'remove'): void\n}\n\nconst props = withDefaults(defineProps<GrChipProps>(), {\n value: undefined,\n label: undefined,\n // Дефолты живут в резолверах ниже: Vue подставил бы свой раньше, чем\n // компонент заглянет в `GrConfigProvider`.\n tone: undefined,\n dark: undefined,\n size: undefined,\n radius: undefined,\n selectable: false,\n selected: false,\n closable: false,\n disabled: false,\n ariaLabel: undefined,\n removeLabel: undefined,\n removeTabindex: undefined,\n})\n\nconst emit = defineEmits<GrChipEmits>()\n\ndefineSlots<{\n /** Подпись чипа. Внутри выбираемого чипа — только фразовое содержимое. */\n default?: () => unknown\n /** Иконка перед подписью. */\n icon?: () => unknown\n}>()\n\nconst { t } = useGranularityTranslations()\n\nconst group = inject(GR_CHIP_GROUP_CONTEXT, null)\nconst rootEl = ref<HTMLElement | null>(null)\n\nconst inGroup = computed(() => group !== null && props.value !== undefined)\n\nconst isDisabled = computed(() => props.disabled || (group?.disabled.value ?? false))\nconst isReadonly = computed(() => group?.readonly.value ?? false)\n\n/**\n * Чип — виджет ровно тогда, когда по нему кликают.\n *\n * От этого зависит вся разметка: у виджета роль, `tabindex` и клавиатура, а\n * крестик внутри него перестаёт быть кнопкой.\n */\nconst isInteractive = computed(() => inGroup.value || props.selectable)\n\nconst isSelected = computed(() => {\n if (inGroup.value && props.value !== undefined) return group!.isSelected(props.value)\n return props.selected\n})\n\nconst isClosable = computed(() => {\n if (isReadonly.value || isDisabled.value) return false\n return props.closable || (inGroup.value ? group!.closable.value : false)\n})\n\n// Приоритет: локальный проп → значение группы → `GrConfigProvider` → дефолт.\n// Группа специфичнее конфига, поэтому её значение подаётся как «локальное».\nconst resolvedSize = useGrComponentSize<GrChipSize>(\n () => props.size ?? (inGroup.value ? group!.size.value : undefined),\n { component: 'GrChip' },\n)\nconst resolvedTone = useGrComponentProp(\n 'GrChip',\n 'tone',\n () => props.tone ?? (inGroup.value ? group!.tone.value : undefined),\n 'neutral',\n)\nconst resolvedRadius = useGrComponentProp(\n 'GrChip',\n 'radius',\n () => props.radius ?? (inGroup.value ? group!.radius.value : undefined),\n 'round',\n)\nconst resolvedDark = useGrComponentProp(\n 'GrChip',\n 'dark',\n () => props.dark ?? (inGroup.value ? group!.dark.value : undefined),\n false,\n)\n\nconst rootClass = computed(() => grChipClass({\n tone: resolvedTone.value,\n dark: resolvedDark.value,\n size: resolvedSize.value,\n radius: resolvedRadius.value,\n interactive: isInteractive.value && !isReadonly.value,\n selected: isSelected.value,\n disabled: isDisabled.value,\n}))\n\nconst iconSizeClass = computed(() => chipIconSizeClassBySize[resolvedSize.value])\n\nconst removeTitle = computed(() => {\n if (props.removeLabel) return props.removeLabel\n if (props.label) return t('gr.chip.removeNamed', 'Remove {label}', { label: props.label })\n return t('gr.chip.remove', 'Remove')\n})\n\n/**\n * Роль чипа задаёт группа, а не потребитель.\n *\n * Одиночный переключатель — кнопка с `aria-pressed`; в группе роль зависит от\n * множественности выбора: `radio` в одиночной (образец — `GrSegmented`),\n * `option` во множественной, где контейнер объявлен `listbox` c\n * `aria-multiselectable`.\n */\nconst chipRole = computed(() => {\n if (!inGroup.value) return undefined\n return group!.selection.value === 'single' ? 'radio' : 'option'\n})\n\nconst tabindex = computed(() => {\n if (!isInteractive.value) return undefined\n if (isDisabled.value) return -1\n if (!inGroup.value || props.value === undefined) return 0\n return group!.rovingValue.value === props.value ? 0 : -1\n})\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value) return\n\n if (inGroup.value && props.value !== undefined) {\n group!.toggle(props.value)\n return\n }\n\n if (props.selectable) emit('update:selected', !props.selected)\n}\n\nfunction requestRemove(): void {\n if (!isClosable.value) return\n\n emit('remove')\n if (inGroup.value && props.value !== undefined) group!.requestRemove(props.value)\n}\n\n/**\n * Крестик внутри виджета — не кнопка, поэтому его клик приходит сюда же и\n * разбирается по цели. Тот же приём у `GrTabs`: внутрь роли-виджета вложенная\n * кнопка запрещена (axe: `nested-interactive`), а `<button>` внутри `<button>`\n * невалиден и по контент-модели HTML.\n */\nfunction onRootClick(event: MouseEvent): void {\n if (isDisabled.value) return\n\n if (event.target instanceof Element && event.target.closest('[data-gr-chip-close]')) {\n requestRemove()\n return\n }\n\n toggle()\n}\n\nfunction onRootKeydown(event: KeyboardEvent): void {\n if (isDisabled.value) return\n\n // Навигация принадлежит группе: состав знает только она.\n if (inGroup.value && group!.handleNavigationKeys(event)) return\n\n if (event.key === 'Delete' || event.key === 'Backspace') {\n if (!isClosable.value) return\n event.preventDefault()\n requestRemove()\n }\n}\n\nif (group) {\n const unregister = group.register({\n value: () => props.value as GrChipValue,\n disabled: () => isDisabled.value,\n el: () => rootEl.value,\n })\n onBeforeUnmount(unregister)\n}\n\nconst removeEl = ref<HTMLButtonElement | null>(null)\n\ndefineExpose({\n focus: () => rootEl.value?.focus(),\n blur: () => rootEl.value?.blur(),\n /**\n * Кнопка снятия — цель roving-фокуса у родителя. Отдаётся элементом, а не\n * методом `focusRemove`: кольцу нужен сам узел, оно само решает, когда и\n * куда переносить фокус.\n */\n removeEl,\n})\n</script>\n\n<template>\n <component\n :is=\"isInteractive ? 'button' : 'span'\"\n ref=\"rootEl\"\n data-gr-chip\n :type=\"isInteractive ? 'button' : undefined\"\n :class=\"rootClass\"\n :role=\"chipRole\"\n :data-value=\"value\"\n :aria-label=\"ariaLabel\"\n :aria-checked=\"chipRole === 'radio' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-selected=\"chipRole === 'option' ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-pressed=\"isInteractive && !chipRole ? (isSelected ? 'true' : 'false') : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :disabled=\"isInteractive && isDisabled ? true : undefined\"\n :aria-keyshortcuts=\"isInteractive && isClosable ? 'Delete' : undefined\"\n :tabindex=\"tabindex\"\n @click=\"isInteractive ? onRootClick($event) : undefined\"\n @keydown=\"isInteractive ? onRootKeydown($event) : undefined\"\n >\n <span v-if=\"$slots.icon\" data-gr-chip-icon :class=\"[chipIconClass, iconSizeClass]\">\n <slot name=\"icon\" />\n </span>\n\n <span data-gr-chip-label :class=\"chipLabelClass\">\n <slot>{{ label }}</slot>\n </span>\n\n <!--\n Крестик существует в двух видах, и различитель — роль самого чипа.\n Виджет: `<span aria-hidden>` вне таб-порядка, снятие идёт `Delete`/`Backspace`.\n Не виджет: настоящая кнопка со своей остановкой `Tab` и своим именем.\n -->\n <span\n v-if=\"isClosable && isInteractive\"\n data-gr-chip-close\n :class=\"[chipCloseClass, iconSizeClass]\"\n :title=\"removeTitle\"\n aria-hidden=\"true\"\n >\n <IconClose class=\"h-full w-full\" />\n </span>\n\n <button\n v-else-if=\"isClosable\"\n ref=\"removeEl\"\n data-gr-chip-close\n type=\"button\"\n :class=\"[chipCloseButtonClass, iconSizeClass]\"\n :aria-label=\"removeTitle\"\n :tabindex=\"removeTabindex\"\n @mousedown.prevent.stop\n @click.stop=\"requestRemove()\"\n >\n <IconClose class=\"h-full w-full\" />\n </button>\n </component>\n</template>\n"],"mappings":"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"}
|