@feugene/granularity 0.11.0 → 0.12.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.
Files changed (189) hide show
  1. package/dist/GrTree.css +1 -1
  2. package/dist/chunks/config-1uSYl98Y2.js.map +1 -0
  3. package/dist/chunks/config-BIRO0vDJ.js.map +1 -0
  4. package/dist/chunks/config-BWiPnygb.js +5 -0
  5. package/dist/chunks/config-BWiPnygb.js.map +1 -0
  6. package/dist/chunks/config-BXtAmU3s2.js.map +1 -0
  7. package/dist/chunks/config-CGHLoBlH.js.map +1 -0
  8. package/dist/chunks/config-CrG1XiE72.js.map +1 -0
  9. package/dist/chunks/config-DUcu1D682.js.map +1 -0
  10. package/dist/chunks/config-Dlm49Jp5.js +5 -0
  11. package/dist/chunks/config-Dlm49Jp5.js.map +1 -0
  12. package/dist/chunks/config-DnvPqu4g2.js.map +1 -0
  13. package/dist/chunks/config-DpqOnJiz.js.map +1 -0
  14. package/dist/chunks/config-JpHA4Xx02.js.map +1 -0
  15. package/dist/chunks/config-LGrZIdaZ.js.map +1 -0
  16. package/dist/chunks/config-eXB87DOi2.js +9 -0
  17. package/dist/chunks/config-eXB87DOi2.js.map +1 -0
  18. package/dist/chunks/context-DdNIxa1w.js +9 -0
  19. package/dist/chunks/context-DdNIxa1w.js.map +1 -0
  20. package/dist/chunks/{en-BdtiS2d3.js → en-CfkDa4GX.js} +8 -2
  21. package/dist/chunks/{en-BdtiS2d3.js.map → en-CfkDa4GX.js.map} +1 -1
  22. package/dist/chunks/{es-DBhctWg-.js → es-CgaLnFYx.js} +3 -3
  23. package/dist/chunks/{es-DBhctWg-.js.map → es-CgaLnFYx.js.map} +1 -1
  24. package/dist/chunks/{es-BGRMZbe9.js → es-FkgECuCm.js} +8 -2
  25. package/dist/chunks/{es-BGRMZbe9.js.map → es-FkgECuCm.js.map} +1 -1
  26. package/dist/chunks/grModalEscStack-BXk-9mv7.js +43 -0
  27. package/dist/chunks/grModalEscStack-BXk-9mv7.js.map +1 -0
  28. package/dist/chunks/{ru-BFCnOiML.js → ru-Bl8CxpEa.js} +8 -2
  29. package/dist/chunks/{ru-BFCnOiML.js.map → ru-Bl8CxpEa.js.map} +1 -1
  30. package/dist/chunks/{shared-ChvcQgDl.js → shared-B6Ay2081.js} +17 -11
  31. package/dist/chunks/shared-B6Ay2081.js.map +1 -0
  32. package/dist/chunks/{transition-TLFw4KBn.js → useScrollLock-K7kaP2Ud.js} +52 -1
  33. package/dist/chunks/useScrollLock-K7kaP2Ud.js.map +1 -0
  34. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BWYKCsHd.js → GrConfirmDialog-D8CkOtqv.js} +1 -1
  35. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BWYKCsHd.js.map → GrConfirmDialog-D8CkOtqv.js.map} +1 -1
  36. package/dist/components/GrConfirmDialog/index.js +2 -2
  37. package/dist/components/GrDataTable/chunks/{GrDataTable-ptbARmJ3.js → GrDataTable-Ds5OeGat.js} +42 -16
  38. package/dist/components/GrDataTable/chunks/GrDataTable-Ds5OeGat.js.map +1 -0
  39. package/dist/components/GrDataTable/index.js +1 -1
  40. package/dist/components/GrDialog/chunks/{GrDialog-5DAS-1Lb.js → GrDialog-Ctucxju9.js} +2 -2
  41. package/dist/components/GrDialog/chunks/{GrDialog-5DAS-1Lb.js.map → GrDialog-Ctucxju9.js.map} +1 -1
  42. package/dist/components/GrDialog/index.js +1 -1
  43. package/dist/components/GrDialogService/chunks/{GrDialogService-DY_fmaMu.js → GrDialogService-CU1Fbonc.js} +2 -2
  44. package/dist/components/GrDialogService/chunks/{GrDialogService-DY_fmaMu.js.map → GrDialogService-CU1Fbonc.js.map} +1 -1
  45. package/dist/components/GrDialogService/index.js +1 -1
  46. package/dist/components/GrDivider/chunks/GrDivider-5bcE-BB4.js +54 -0
  47. package/dist/components/GrDivider/chunks/GrDivider-5bcE-BB4.js.map +1 -0
  48. package/dist/components/GrDivider/index.js +3 -0
  49. package/dist/components/GrDrawer/chunks/{GrDrawer-D1kzsjXN.js → GrDrawer-SLGKCY2A.js} +37 -13
  50. package/dist/components/GrDrawer/chunks/GrDrawer-SLGKCY2A.js.map +1 -0
  51. package/dist/components/GrDrawer/index.js +2 -2
  52. package/dist/components/GrDropdown/chunks/{GrDropdown-BXb5Cxxf.js → GrDropdown-BnDMYP8v.js} +90 -4
  53. package/dist/components/GrDropdown/chunks/GrDropdown-BnDMYP8v.js.map +1 -0
  54. package/dist/components/GrDropdown/index.js +1 -1
  55. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DFEJLPcV.js → GrDropdownMenu--g9Vofcq.js} +1 -1
  56. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DFEJLPcV.js.map → GrDropdownMenu--g9Vofcq.js.map} +1 -1
  57. package/dist/components/GrDropdownMenu/index.js +1 -1
  58. package/dist/components/GrFormField/chunks/GrFormField-DnfMHx_U.js +73 -0
  59. package/dist/components/GrFormField/chunks/GrFormField-DnfMHx_U.js.map +1 -0
  60. package/dist/components/GrFormField/index.js +3 -2
  61. package/dist/components/GrImageViewer/chunks/{GrImageViewer-OCUIrNh2.js → GrImageViewer-Dla9IBkd.js} +311 -222
  62. package/dist/components/GrImageViewer/chunks/GrImageViewer-Dla9IBkd.js.map +1 -0
  63. package/dist/components/GrImageViewer/index.js +1 -1
  64. package/dist/components/GrInput/chunks/GrInput-B8dd3JaA.js +334 -0
  65. package/dist/components/GrInput/chunks/GrInput-B8dd3JaA.js.map +1 -0
  66. package/dist/components/GrInput/index.js +1 -1
  67. package/dist/components/GrKbd/chunks/GrKbd-BEoYxWhE.js +22 -0
  68. package/dist/components/GrKbd/chunks/GrKbd-BEoYxWhE.js.map +1 -0
  69. package/dist/components/GrKbd/index.js +3 -0
  70. package/dist/components/GrModal/chunks/{GrModal-BkjW9jZS.js → GrModal-C0GZrHN3.js} +3 -56
  71. package/dist/components/GrModal/chunks/GrModal-C0GZrHN3.js.map +1 -0
  72. package/dist/components/GrModal/index.js +1 -1
  73. package/dist/components/GrNumberInput/chunks/{GrNumberInput-CldPIWQx.js → GrNumberInput-DxCEvL7V.js} +93 -11
  74. package/dist/components/GrNumberInput/chunks/GrNumberInput-DxCEvL7V.js.map +1 -0
  75. package/dist/components/GrNumberInput/index.js +1 -1
  76. package/dist/components/GrPagination/chunks/{GrPagination-Bu9wv6it.js → GrPagination-mlyfLjQY.js} +1 -1
  77. package/dist/components/GrPagination/chunks/{GrPagination-Bu9wv6it.js.map → GrPagination-mlyfLjQY.js.map} +1 -1
  78. package/dist/components/GrPagination/index.js +2 -2
  79. package/dist/components/GrProgressBar/index.js +1 -1
  80. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-TmWXbpEP.js → GrPromptDialog-C-_BMNuY.js} +3 -3
  81. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-TmWXbpEP.js.map → GrPromptDialog-C-_BMNuY.js.map} +1 -1
  82. package/dist/components/GrPromptDialog/index.js +1 -1
  83. package/dist/components/GrRadio/chunks/{GrRadio-CPTixXaY.js → GrRadio-Dr-pvs_9.js} +1 -1
  84. package/dist/components/GrRadio/chunks/{GrRadio-CPTixXaY.js.map → GrRadio-Dr-pvs_9.js.map} +1 -1
  85. package/dist/components/GrRadio/index.js +2 -2
  86. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-vKZCbkCp.js → GrRadioGroup-nOdvfV_g.js} +1 -1
  87. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-vKZCbkCp.js.map → GrRadioGroup-nOdvfV_g.js.map} +1 -1
  88. package/dist/components/GrRadioGroup/index.js +1 -1
  89. package/dist/components/GrSelect/chunks/{GrSelect-RShK21lK.js → GrSelect-BVCmitqa.js} +147 -27
  90. package/dist/components/GrSelect/chunks/GrSelect-BVCmitqa.js.map +1 -0
  91. package/dist/components/GrSelect/index.js +1 -1
  92. package/dist/components/GrSidebar/index.js +1 -1
  93. package/dist/components/GrTabPanels/chunks/GrTabPanels-DbKybwe-.js +68 -0
  94. package/dist/components/GrTabPanels/chunks/GrTabPanels-DbKybwe-.js.map +1 -0
  95. package/dist/components/GrTabPanels/index.js +3 -0
  96. package/dist/components/GrTabs/chunks/{GrTabs-Z-FDJUr_.js → GrTabs-DsLwWoRz.js} +6 -1
  97. package/dist/components/GrTabs/chunks/GrTabs-DsLwWoRz.js.map +1 -0
  98. package/dist/components/GrTabs/index.js +1 -1
  99. package/dist/components/GrTextarea/chunks/{GrTextarea-D56YxhKq.js → GrTextarea-CKukGlNl.js} +15 -5
  100. package/dist/components/GrTextarea/chunks/GrTextarea-CKukGlNl.js.map +1 -0
  101. package/dist/components/GrTextarea/index.js +2 -2
  102. package/dist/components/GrToaster/chunks/{GrToaster-eI8YvnIo.js → GrToaster-L2cu6cSR.js} +1 -1
  103. package/dist/components/GrToaster/chunks/{GrToaster-eI8YvnIo.js.map → GrToaster-L2cu6cSR.js.map} +1 -1
  104. package/dist/components/GrToaster/index.js +2 -2
  105. package/dist/components/GrTree/chunks/{GrTree-D3ODe2dB.js → GrTree-B2_yW6g1.js} +107 -8
  106. package/dist/components/GrTree/chunks/GrTree-B2_yW6g1.js.map +1 -0
  107. package/dist/components/GrTree/index.js +2 -2
  108. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-B2xBKs5Q.js → GrTreeSelect-0aM62xyu.js} +3 -3
  109. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-B2xBKs5Q.js.map → GrTreeSelect-0aM62xyu.js.map} +1 -1
  110. package/dist/components/GrTreeSelect/index.js +2 -2
  111. package/dist/granular-provider-node.js +2 -2
  112. package/dist/granular-provider.js +1 -1
  113. package/dist/i18n/all.js +1 -1
  114. package/dist/i18n/index.js +1 -1
  115. package/dist/index.js +40 -33
  116. package/dist/index.js.map +1 -1
  117. package/dist/styles/base.css +30 -8
  118. package/dist/styles/preflight.css +5 -1
  119. package/dist/types/src/components/GrDataTable/GrDataTable.vue.d.ts +28 -4
  120. package/dist/types/src/components/GrDivider/GrDivider.vue.d.ts +58 -0
  121. package/dist/types/src/components/GrDivider/config.d.ts +1 -0
  122. package/dist/types/src/components/GrDivider/index.d.ts +4 -0
  123. package/dist/types/src/components/GrDrawer/GrDrawer.vue.d.ts +4 -4
  124. package/dist/types/src/components/GrDropdown/GrDropdown.vue.d.ts +7 -0
  125. package/dist/types/src/components/GrDropdownMenu/GrDropdownMenu.vue.d.ts +6 -0
  126. package/dist/types/src/components/GrFormField/GrFormField.vue.d.ts +15 -2
  127. package/dist/types/src/components/GrFormField/context.d.ts +20 -0
  128. package/dist/types/src/components/GrFormField/index.d.ts +1 -0
  129. package/dist/types/src/components/GrImageViewer/GrImageViewer.vue.d.ts +4 -0
  130. package/dist/types/src/components/GrImageViewer/composables/useViewerKeyboard.d.ts +20 -0
  131. package/dist/types/src/components/GrImageViewer/composables/useWheelGesture.d.ts +16 -0
  132. package/dist/types/src/components/GrImageViewer/composables/useZoomPan.d.ts +50 -0
  133. package/dist/types/src/components/GrInput/GrInput.vue.d.ts +41 -2
  134. package/dist/types/src/components/GrKbd/GrKbd.vue.d.ts +46 -0
  135. package/dist/types/src/components/GrKbd/config.d.ts +1 -0
  136. package/dist/types/src/components/GrKbd/index.d.ts +4 -0
  137. package/dist/types/src/components/GrNumberInput/GrNumberInput.vue.d.ts +16 -0
  138. package/dist/types/src/components/GrSelect/GrSelect.vue.d.ts +2 -2
  139. package/dist/types/src/components/GrTabPanels/GrTabPanel.vue.d.ts +46 -0
  140. package/dist/types/src/components/GrTabPanels/GrTabPanels.vue.d.ts +51 -0
  141. package/dist/types/src/components/GrTabPanels/config.d.ts +5 -0
  142. package/dist/types/src/components/GrTabPanels/context.d.ts +9 -0
  143. package/dist/types/src/components/GrTabPanels/index.d.ts +6 -0
  144. package/dist/types/src/components/GrTabs/GrTabs.vue.d.ts +6 -0
  145. package/dist/types/src/components/GrTree/grTreeInteractionContext.d.ts +2 -0
  146. package/dist/types/src/composables/internal/useScrollLock.d.ts +24 -0
  147. package/dist/types/src/granular-provider/shared.d.ts +3 -0
  148. package/dist/types/src/i18n/messages/en.d.ts +10 -0
  149. package/dist/types/src/i18n/messages/es.d.ts +10 -0
  150. package/dist/types/src/i18n/messages/ru.d.ts +10 -0
  151. package/dist/types/src/index.d.ts +3 -0
  152. package/dist/web-types.json +275 -26
  153. package/package.json +13 -1
  154. package/dist/chunks/config-1uSYl98Y.js.map +0 -1
  155. package/dist/chunks/config-BIRO0vDJ2.js.map +0 -1
  156. package/dist/chunks/config-BXtAmU3s.js.map +0 -1
  157. package/dist/chunks/config-CGHLoBlH2.js.map +0 -1
  158. package/dist/chunks/config-CrG1XiE7.js.map +0 -1
  159. package/dist/chunks/config-DUcu1D68.js.map +0 -1
  160. package/dist/chunks/config-DnvPqu4g.js.map +0 -1
  161. package/dist/chunks/config-DpqOnJiz2.js.map +0 -1
  162. package/dist/chunks/config-JpHA4Xx0.js.map +0 -1
  163. package/dist/chunks/config-LGrZIdaZ2.js.map +0 -1
  164. package/dist/chunks/shared-ChvcQgDl.js.map +0 -1
  165. package/dist/chunks/transition-TLFw4KBn.js.map +0 -1
  166. package/dist/components/GrDataTable/chunks/GrDataTable-ptbARmJ3.js.map +0 -1
  167. package/dist/components/GrDrawer/chunks/GrDrawer-D1kzsjXN.js.map +0 -1
  168. package/dist/components/GrDropdown/chunks/GrDropdown-BXb5Cxxf.js.map +0 -1
  169. package/dist/components/GrFormField/chunks/GrFormField-BujNQrw8.js +0 -35
  170. package/dist/components/GrFormField/chunks/GrFormField-BujNQrw8.js.map +0 -1
  171. package/dist/components/GrImageViewer/chunks/GrImageViewer-OCUIrNh2.js.map +0 -1
  172. package/dist/components/GrInput/chunks/GrInput-C8pOJgCi.js +0 -188
  173. package/dist/components/GrInput/chunks/GrInput-C8pOJgCi.js.map +0 -1
  174. package/dist/components/GrModal/chunks/GrModal-BkjW9jZS.js.map +0 -1
  175. package/dist/components/GrNumberInput/chunks/GrNumberInput-CldPIWQx.js.map +0 -1
  176. package/dist/components/GrSelect/chunks/GrSelect-RShK21lK.js.map +0 -1
  177. package/dist/components/GrTabs/chunks/GrTabs-Z-FDJUr_.js.map +0 -1
  178. package/dist/components/GrTextarea/chunks/GrTextarea-D56YxhKq.js.map +0 -1
  179. package/dist/components/GrTree/chunks/GrTree-D3ODe2dB.js.map +0 -1
  180. /package/dist/chunks/{config-1uSYl98Y.js → config-1uSYl98Y2.js} +0 -0
  181. /package/dist/chunks/{config-BIRO0vDJ2.js → config-BIRO0vDJ.js} +0 -0
  182. /package/dist/chunks/{config-BXtAmU3s.js → config-BXtAmU3s2.js} +0 -0
  183. /package/dist/chunks/{config-CGHLoBlH2.js → config-CGHLoBlH.js} +0 -0
  184. /package/dist/chunks/{config-CrG1XiE7.js → config-CrG1XiE72.js} +0 -0
  185. /package/dist/chunks/{config-DUcu1D68.js → config-DUcu1D682.js} +0 -0
  186. /package/dist/chunks/{config-DnvPqu4g.js → config-DnvPqu4g2.js} +0 -0
  187. /package/dist/chunks/{config-DpqOnJiz2.js → config-DpqOnJiz.js} +0 -0
  188. /package/dist/chunks/{config-JpHA4Xx0.js → config-JpHA4Xx02.js} +0 -0
  189. /package/dist/chunks/{config-LGrZIdaZ2.js → config-LGrZIdaZ.js} +0 -0
@@ -2,9 +2,10 @@ import { vClickOutside } from "../../../directives/clickOutside.js";
2
2
  import { t as useFloating } from "../../../chunks/useFloating-DtM6TyE4.js";
3
3
  import { t as useEscapeToClose } from "../../../chunks/useEscapeToClose-C2t_S1gh.js";
4
4
  import { n as grDropdownOriginClass, r as grDropdownWidthClass, t as grDropdownContentClass } from "../../../chunks/grDropdownStyles-B_-DKytw.js";
5
- import { Teleport, Transition, computed, createBlock, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, ref, renderSlot, unref, vShow, watch, withCtx, withDirectives } from "vue";
5
+ import { Teleport, Transition, computed, createBlock, createElementBlock, createElementVNode, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, openBlock, ref, renderSlot, unref, useId, vShow, watch, withCtx, withDirectives } from "vue";
6
6
  //#region src/components/GrDropdown/GrDropdown.vue?vue&type=script&setup=true&lang.ts
7
7
  var _hoisted_1 = { "data-gr-dropdown": "" };
8
+ var _hoisted_2 = ["id"];
8
9
  //#endregion
9
10
  //#region src/components/GrDropdown/GrDropdown.vue
10
11
  var GrDropdown_default = /* @__PURE__ */ defineComponent({
@@ -25,6 +26,84 @@ var GrDropdown_default = /* @__PURE__ */ defineComponent({
25
26
  const rootEl = ref(null);
26
27
  const panelEl = ref(null);
27
28
  const clickOutsideExclude = [() => panelEl.value];
29
+ const panelId = useId();
30
+ let triggerFocusEl = null;
31
+ function panelItems() {
32
+ const root = panelEl.value;
33
+ if (!root) return [];
34
+ return Array.from(root.querySelectorAll("[role=\"menuitem\"], a[href], button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])")).filter((el) => el.offsetParent !== null || el === document.activeElement);
35
+ }
36
+ function focusItemAt(index) {
37
+ const items = panelItems();
38
+ if (items.length === 0) return;
39
+ items[(index + items.length) % items.length]?.focus();
40
+ }
41
+ async function openWithFocus(first) {
42
+ triggerFocusEl = document.activeElement ?? null;
43
+ open.value = true;
44
+ await nextTick();
45
+ focusItemAt(first ? 0 : -1);
46
+ }
47
+ function returnFocusToTrigger() {
48
+ const target = triggerFocusEl;
49
+ triggerFocusEl = null;
50
+ target?.focus?.();
51
+ }
52
+ /**
53
+ * Пропсы для реального фокусируемого триггера (кнопки). Консьюмер биндит их на
54
+ * элемент внутри слота `#trigger`: `<button v-bind="triggerProps">`. Даёт
55
+ * `aria-haspopup`/`aria-expanded`/`aria-controls` и клавиатуру (Enter/Space/стрелки).
56
+ */
57
+ const triggerProps = computed(() => ({
58
+ "aria-haspopup": "menu",
59
+ "aria-expanded": open.value,
60
+ "aria-controls": open.value ? panelId : void 0,
61
+ "onKeydown": onTriggerKeydown
62
+ }));
63
+ function onTriggerKeydown(event) {
64
+ switch (event.key) {
65
+ case "Enter":
66
+ case " ":
67
+ case "ArrowDown":
68
+ event.preventDefault();
69
+ openWithFocus(true);
70
+ break;
71
+ case "ArrowUp":
72
+ event.preventDefault();
73
+ openWithFocus(false);
74
+ break;
75
+ case "Escape":
76
+ if (open.value) {
77
+ event.preventDefault();
78
+ close();
79
+ }
80
+ break;
81
+ }
82
+ }
83
+ function onPanelKeydown(event) {
84
+ const currentIndex = panelItems().indexOf(document.activeElement);
85
+ switch (event.key) {
86
+ case "ArrowDown":
87
+ event.preventDefault();
88
+ focusItemAt(currentIndex + 1);
89
+ break;
90
+ case "ArrowUp":
91
+ event.preventDefault();
92
+ focusItemAt(currentIndex - 1);
93
+ break;
94
+ case "Home":
95
+ event.preventDefault();
96
+ focusItemAt(0);
97
+ break;
98
+ case "End":
99
+ event.preventDefault();
100
+ focusItemAt(-1);
101
+ break;
102
+ case "Tab":
103
+ close();
104
+ break;
105
+ }
106
+ }
28
107
  const placementByAlign = {
29
108
  left: "bottom-start",
30
109
  right: "bottom-end",
@@ -38,7 +117,9 @@ var GrDropdown_default = /* @__PURE__ */ defineComponent({
38
117
  open.value = !open.value;
39
118
  }
40
119
  function close() {
120
+ const wasOpen = open.value;
41
121
  open.value = false;
122
+ if (wasOpen) returnFocusToTrigger();
42
123
  }
43
124
  useEscapeToClose(open, close);
44
125
  watch(() => props.align, () => {
@@ -62,7 +143,8 @@ var GrDropdown_default = /* @__PURE__ */ defineComponent({
62
143
  }, [renderSlot(_ctx.$slots, "trigger", {
63
144
  open: open.value,
64
145
  toggle,
65
- close
146
+ close,
147
+ triggerProps: triggerProps.value
66
148
  })])), [[unref(vClickOutside), {
67
149
  handler: close,
68
150
  enabled: open.value,
@@ -76,16 +158,20 @@ var GrDropdown_default = /* @__PURE__ */ defineComponent({
76
158
  "leave-to-class": "transform opacity-0 scale-95"
77
159
  }, {
78
160
  default: withCtx(() => [withDirectives(createElementVNode("div", {
161
+ id: unref(panelId),
79
162
  ref_key: "panelEl",
80
163
  ref: panelEl,
81
164
  "data-gr-dropdown-panel": "",
165
+ role: "menu",
166
+ tabindex: "-1",
82
167
  class: normalizeClass(panelClasses.value),
83
168
  style: normalizeStyle(unref(floatingStyle)),
84
- onClick: onContentClick
169
+ onClick: onContentClick,
170
+ onKeydown: onPanelKeydown
85
171
  }, [createElementVNode("div", {
86
172
  "data-gr-dropdown-content": "",
87
173
  class: normalizeClass(contentClasses.value)
88
- }, [renderSlot(_ctx.$slots, "content", { close })], 2)], 6), [[vShow, open.value]])]),
174
+ }, [renderSlot(_ctx.$slots, "content", { close })], 2)], 46, _hoisted_2), [[vShow, open.value]])]),
89
175
  _: 3
90
176
  })], 8, ["to"]))]);
91
177
  };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrDropdown-BnDMYP8v.js","names":[],"sources":["../../../../src/components/GrDropdown/GrDropdown.vue","../../../../src/components/GrDropdown/GrDropdown.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, watch } from 'vue'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/internal/useFloating'\nimport { useEscapeToClose } from '../../composables/internal/useEscapeToClose'\nimport {\n grDropdownContentClass,\n grDropdownOriginClass,\n grDropdownWidthClass,\n type GrDropdownAlign,\n type GrDropdownWidth,\n} from './grDropdownStyles'\n\nexport interface GrDropdownProps {\n /** Выравнивание панели относительно триггера. */\n align?: GrDropdownAlign\n /** Ширина панели (tailwind-токены `w-*` или `auto`). */\n width?: GrDropdownWidth\n /** Закрывать панель по клику внутри content. */\n closeOnContentClick?: boolean\n /** Дополнительные классы контейнера content. */\n contentClass?: string\n /** Куда телепортировать панель (`body` по умолчанию). */\n teleportTo?: string | HTMLElement\n}\n\nconst props = withDefaults(defineProps<GrDropdownProps>(), {\n align: 'right',\n width: '48',\n closeOnContentClick: true,\n contentClass: '',\n teleportTo: 'body',\n})\n\nconst open = ref(false)\nconst rootEl = ref<HTMLElement | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\nconst clickOutsideExclude = [() => panelEl.value]\n\nconst panelId = useId()\n\n// Элемент триггера, которому вернём фокус при закрытии (клавиатурный сценарий).\nlet triggerFocusEl: HTMLElement | null = null\n\n// Фокусируемые пункты панели для клавиатурной навигации (roving-фокус).\nfunction panelItems(): HTMLElement[] {\n const root = panelEl.value\n if (!root)\n return []\n const selector = '[role=\"menuitem\"], a[href], button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n return Array.from(root.querySelectorAll<HTMLElement>(selector)).filter(el => el.offsetParent !== null || el === document.activeElement)\n}\n\nfunction focusItemAt(index: number): void {\n const items = panelItems()\n if (items.length === 0)\n return\n const clamped = (index + items.length) % items.length\n items[clamped]?.focus()\n}\n\nasync function openWithFocus(first: boolean): Promise<void> {\n triggerFocusEl = (document.activeElement as HTMLElement) ?? null\n open.value = true\n await nextTick()\n focusItemAt(first ? 0 : -1)\n}\n\nfunction returnFocusToTrigger(): void {\n const target = triggerFocusEl\n triggerFocusEl = null\n target?.focus?.()\n}\n\n/**\n * Пропсы для реального фокусируемого триггера (кнопки). Консьюмер биндит их на\n * элемент внутри слота `#trigger`: `<button v-bind=\"triggerProps\">`. Даёт\n * `aria-haspopup`/`aria-expanded`/`aria-controls` и клавиатуру (Enter/Space/стрелки).\n */\nconst triggerProps = computed(() => ({\n 'aria-haspopup': 'menu' as const,\n 'aria-expanded': open.value,\n 'aria-controls': open.value ? panelId : undefined,\n 'onKeydown': onTriggerKeydown,\n}))\n\nfunction onTriggerKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Enter':\n case ' ':\n case 'ArrowDown':\n event.preventDefault()\n void openWithFocus(true)\n break\n case 'ArrowUp':\n event.preventDefault()\n void openWithFocus(false)\n break\n case 'Escape':\n if (open.value) {\n event.preventDefault()\n close()\n }\n break\n }\n}\n\nfunction onPanelKeydown(event: KeyboardEvent): void {\n const items = panelItems()\n const currentIndex = items.indexOf(document.activeElement as HTMLElement)\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n focusItemAt(currentIndex + 1)\n break\n case 'ArrowUp':\n event.preventDefault()\n focusItemAt(currentIndex - 1)\n break\n case 'Home':\n event.preventDefault()\n focusItemAt(0)\n break\n case 'End':\n event.preventDefault()\n focusItemAt(-1)\n break\n case 'Tab':\n close()\n break\n }\n}\n\n// `align='right'` — правый край панели совпадает с правым краем триггера (bottom-end);\n// `align='left'` — левые края (bottom-start); `align='center'` — floating-ui сам\n// центрирует панель под триггером при обычном `'bottom'` без суффикса.\nconst placementByAlign: Record<GrDropdownAlign, 'bottom-start' | 'bottom-end' | 'bottom'> = {\n left: 'bottom-start',\n right: 'bottom-end',\n center: 'bottom',\n}\n\nconst { floatingStyle, resolvedPlacement, update: updateFloatingPosition } = useFloating(\n rootEl,\n panelEl,\n open,\n {\n placement: () => placementByAlign[props.align],\n zIndexVar: '--gr-z-dropdown',\n },\n)\n\nfunction toggle(): void {\n open.value = !open.value\n}\n\nfunction close(): void {\n const wasOpen = open.value\n open.value = false\n // Возвращаем фокус на триггер только если панель была открыта с клавиатуры.\n if (wasOpen)\n returnFocusToTrigger()\n}\n\nuseEscapeToClose(open, close)\n\nwatch(\n () => props.align,\n () => {\n if (open.value) updateFloatingPosition()\n },\n)\n\nconst widthClass = computed(() => grDropdownWidthClass(props.width))\n\nconst contentClasses = computed(() => grDropdownContentClass(props.contentClass))\n\nconst panelClasses = computed(() => {\n return [widthClass.value, grDropdownOriginClass(resolvedPlacement.value)].filter(Boolean)\n})\n\nfunction onContentClick(): void {\n if (props.closeOnContentClick) {\n close()\n }\n}\n</script>\n\n<template>\n <div data-gr-dropdown>\n <div\n ref=\"rootEl\"\n v-click-outside=\"{ handler: close, enabled: open, exclude: clickOutsideExclude }\"\n data-gr-dropdown-trigger\n class=\"inline-block max-w-full\"\n @click=\"toggle\"\n >\n <slot name=\"trigger\" :open=\"open\" :toggle=\"toggle\" :close=\"close\" :triggerProps=\"triggerProps\" />\n </div>\n\n <teleport :to=\"teleportTo\">\n <transition\n enter-active-class=\"transition ease-out duration-150\"\n enter-from-class=\"transform opacity-0 scale-95\"\n enter-to-class=\"transform opacity-100 scale-100\"\n leave-active-class=\"transition ease-in duration-100\"\n leave-from-class=\"transform opacity-100 scale-100\"\n leave-to-class=\"transform opacity-0 scale-95\"\n >\n <div\n v-show=\"open\"\n :id=\"panelId\"\n ref=\"panelEl\"\n data-gr-dropdown-panel\n role=\"menu\"\n tabindex=\"-1\"\n :class=\"panelClasses\"\n :style=\"floatingStyle\"\n @click=\"onContentClick\"\n @keydown=\"onPanelKeydown\"\n >\n <div data-gr-dropdown-content :class=\"contentClasses\">\n <slot name=\"content\" :close=\"close\" />\n </div>\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, watch } from 'vue'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/internal/useFloating'\nimport { useEscapeToClose } from '../../composables/internal/useEscapeToClose'\nimport {\n grDropdownContentClass,\n grDropdownOriginClass,\n grDropdownWidthClass,\n type GrDropdownAlign,\n type GrDropdownWidth,\n} from './grDropdownStyles'\n\nexport interface GrDropdownProps {\n /** Выравнивание панели относительно триггера. */\n align?: GrDropdownAlign\n /** Ширина панели (tailwind-токены `w-*` или `auto`). */\n width?: GrDropdownWidth\n /** Закрывать панель по клику внутри content. */\n closeOnContentClick?: boolean\n /** Дополнительные классы контейнера content. */\n contentClass?: string\n /** Куда телепортировать панель (`body` по умолчанию). */\n teleportTo?: string | HTMLElement\n}\n\nconst props = withDefaults(defineProps<GrDropdownProps>(), {\n align: 'right',\n width: '48',\n closeOnContentClick: true,\n contentClass: '',\n teleportTo: 'body',\n})\n\nconst open = ref(false)\nconst rootEl = ref<HTMLElement | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\nconst clickOutsideExclude = [() => panelEl.value]\n\nconst panelId = useId()\n\n// Элемент триггера, которому вернём фокус при закрытии (клавиатурный сценарий).\nlet triggerFocusEl: HTMLElement | null = null\n\n// Фокусируемые пункты панели для клавиатурной навигации (roving-фокус).\nfunction panelItems(): HTMLElement[] {\n const root = panelEl.value\n if (!root)\n return []\n const selector = '[role=\"menuitem\"], a[href], button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n return Array.from(root.querySelectorAll<HTMLElement>(selector)).filter(el => el.offsetParent !== null || el === document.activeElement)\n}\n\nfunction focusItemAt(index: number): void {\n const items = panelItems()\n if (items.length === 0)\n return\n const clamped = (index + items.length) % items.length\n items[clamped]?.focus()\n}\n\nasync function openWithFocus(first: boolean): Promise<void> {\n triggerFocusEl = (document.activeElement as HTMLElement) ?? null\n open.value = true\n await nextTick()\n focusItemAt(first ? 0 : -1)\n}\n\nfunction returnFocusToTrigger(): void {\n const target = triggerFocusEl\n triggerFocusEl = null\n target?.focus?.()\n}\n\n/**\n * Пропсы для реального фокусируемого триггера (кнопки). Консьюмер биндит их на\n * элемент внутри слота `#trigger`: `<button v-bind=\"triggerProps\">`. Даёт\n * `aria-haspopup`/`aria-expanded`/`aria-controls` и клавиатуру (Enter/Space/стрелки).\n */\nconst triggerProps = computed(() => ({\n 'aria-haspopup': 'menu' as const,\n 'aria-expanded': open.value,\n 'aria-controls': open.value ? panelId : undefined,\n 'onKeydown': onTriggerKeydown,\n}))\n\nfunction onTriggerKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Enter':\n case ' ':\n case 'ArrowDown':\n event.preventDefault()\n void openWithFocus(true)\n break\n case 'ArrowUp':\n event.preventDefault()\n void openWithFocus(false)\n break\n case 'Escape':\n if (open.value) {\n event.preventDefault()\n close()\n }\n break\n }\n}\n\nfunction onPanelKeydown(event: KeyboardEvent): void {\n const items = panelItems()\n const currentIndex = items.indexOf(document.activeElement as HTMLElement)\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n focusItemAt(currentIndex + 1)\n break\n case 'ArrowUp':\n event.preventDefault()\n focusItemAt(currentIndex - 1)\n break\n case 'Home':\n event.preventDefault()\n focusItemAt(0)\n break\n case 'End':\n event.preventDefault()\n focusItemAt(-1)\n break\n case 'Tab':\n close()\n break\n }\n}\n\n// `align='right'` — правый край панели совпадает с правым краем триггера (bottom-end);\n// `align='left'` — левые края (bottom-start); `align='center'` — floating-ui сам\n// центрирует панель под триггером при обычном `'bottom'` без суффикса.\nconst placementByAlign: Record<GrDropdownAlign, 'bottom-start' | 'bottom-end' | 'bottom'> = {\n left: 'bottom-start',\n right: 'bottom-end',\n center: 'bottom',\n}\n\nconst { floatingStyle, resolvedPlacement, update: updateFloatingPosition } = useFloating(\n rootEl,\n panelEl,\n open,\n {\n placement: () => placementByAlign[props.align],\n zIndexVar: '--gr-z-dropdown',\n },\n)\n\nfunction toggle(): void {\n open.value = !open.value\n}\n\nfunction close(): void {\n const wasOpen = open.value\n open.value = false\n // Возвращаем фокус на триггер только если панель была открыта с клавиатуры.\n if (wasOpen)\n returnFocusToTrigger()\n}\n\nuseEscapeToClose(open, close)\n\nwatch(\n () => props.align,\n () => {\n if (open.value) updateFloatingPosition()\n },\n)\n\nconst widthClass = computed(() => grDropdownWidthClass(props.width))\n\nconst contentClasses = computed(() => grDropdownContentClass(props.contentClass))\n\nconst panelClasses = computed(() => {\n return [widthClass.value, grDropdownOriginClass(resolvedPlacement.value)].filter(Boolean)\n})\n\nfunction onContentClick(): void {\n if (props.closeOnContentClick) {\n close()\n }\n}\n</script>\n\n<template>\n <div data-gr-dropdown>\n <div\n ref=\"rootEl\"\n v-click-outside=\"{ handler: close, enabled: open, exclude: clickOutsideExclude }\"\n data-gr-dropdown-trigger\n class=\"inline-block max-w-full\"\n @click=\"toggle\"\n >\n <slot name=\"trigger\" :open=\"open\" :toggle=\"toggle\" :close=\"close\" :triggerProps=\"triggerProps\" />\n </div>\n\n <teleport :to=\"teleportTo\">\n <transition\n enter-active-class=\"transition ease-out duration-150\"\n enter-from-class=\"transform opacity-0 scale-95\"\n enter-to-class=\"transform opacity-100 scale-100\"\n leave-active-class=\"transition ease-in duration-100\"\n leave-from-class=\"transform opacity-100 scale-100\"\n leave-to-class=\"transform opacity-0 scale-95\"\n >\n <div\n v-show=\"open\"\n :id=\"panelId\"\n ref=\"panelEl\"\n data-gr-dropdown-panel\n role=\"menu\"\n tabindex=\"-1\"\n :class=\"panelClasses\"\n :style=\"floatingStyle\"\n @click=\"onContentClick\"\n @keydown=\"onPanelKeydown\"\n >\n <div data-gr-dropdown-content :class=\"contentClasses\">\n <slot name=\"content\" :close=\"close\" />\n </div>\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrDropdown_default } from "./chunks/GrDropdown-BXb5Cxxf.js";
1
+ import { t as GrDropdown_default } from "./chunks/GrDropdown-BnDMYP8v.js";
2
2
  import { n as grDropdownSafelist, t as grDropdownConfig } from "../../chunks/config-C49QUoJL.js";
3
3
  export { GrDropdown_default as GrDropdown, GrDropdown_default as default, grDropdownConfig, grDropdownSafelist };
@@ -1,4 +1,4 @@
1
- import { t as GrDropdown_default } from "../../GrDropdown/chunks/GrDropdown-BXb5Cxxf.js";
1
+ import { t as GrDropdown_default } from "../../GrDropdown/chunks/GrDropdown-BnDMYP8v.js";
2
2
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, guardReactiveProps, mergeProps, normalizeClass, normalizeProps, openBlock, renderSlot, resolveDynamicComponent, toDisplayString, unref, useAttrs, useSlots, withCtx } from "vue";
3
3
  //#endregion
4
4
  //#region src/components/GrDropdownMenu/GrDropdownMenuList.vue
@@ -1 +1 @@
1
- {"version":3,"file":"GrDropdownMenu-DFEJLPcV.js","names":[],"sources":["../../../../src/components/GrDropdownMenu/GrDropdownMenuList.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuList.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenu.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenu.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumn.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumn.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumns.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumns.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuDivider.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuDivider.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuHeader.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuHeader.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuGroup.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuGroup.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuItem.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuListProps {\n dividers?: boolean\n borderTop?: boolean\n borderBottom?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuListProps>(), {\n dividers: false,\n borderTop: false,\n borderBottom: false,\n})\n\nconst className = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n props.borderTop ? 'border-t border-[var(--brd)]' : '',\n props.borderBottom ? 'border-b border-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-list :class=\"className\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuListProps {\n dividers?: boolean\n borderTop?: boolean\n borderBottom?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuListProps>(), {\n dividers: false,\n borderTop: false,\n borderBottom: false,\n})\n\nconst className = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n props.borderTop ? 'border-t border-[var(--brd)]' : '',\n props.borderBottom ? 'border-b border-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-list :class=\"className\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport GrDropdown from '../GrDropdown/GrDropdown.vue'\n\nimport GrDropdownMenuList from './GrDropdownMenuList.vue'\n\nexport type GrDropdownMenuAlign = 'left' | 'right' | 'center'\nexport type GrDropdownMenuWidth = 'auto' | '20' | '48' | '60' | '64' | '80'\n\nexport interface GrDropdownMenuProps {\n /** Выравнивание панели относительно триггера. */\n align?: GrDropdownMenuAlign\n /** Ширина панели. */\n width?: GrDropdownMenuWidth\n /** Закрывать по клику внутри content. */\n closeOnContentClick?: boolean\n /** Дополнительные классы content-контейнера; по умолчанию `p-0`. */\n contentClass?: string\n\n // list wrapper\n /** Разделители между пунктами. */\n dividers?: boolean\n /** Верхний бордер контейнера списка. */\n borderTop?: boolean\n /** Нижний бордер контейнера списка. */\n borderBottom?: boolean\n /** Дополнительные классы для wrapper'а списка. */\n listClass?: string\n}\n\nwithDefaults(defineProps<GrDropdownMenuProps>(), {\n align: 'right',\n width: '48',\n closeOnContentClick: true,\n // В `GrDropdown` есть `p-1`, поэтому здесь по умолчанию обнуляем padding,\n // чтобы пункты меню могли растягиваться до границ.\n contentClass: 'p-0',\n dividers: false,\n borderTop: false,\n borderBottom: false,\n listClass: '',\n})\n</script>\n\n<template>\n <GrDropdown\n data-gr-dropdown-menu\n :align=\"align\"\n :width=\"width\"\n :close-on-content-click=\"closeOnContentClick\"\n :content-class=\"contentClass\"\n >\n <template #trigger=\"slotProps\">\n <slot name=\"trigger\" v-bind=\"slotProps\" />\n </template>\n\n <template #content=\"slotProps\">\n <GrDropdownMenuList\n :dividers=\"dividers\"\n :border-top=\"borderTop\"\n :border-bottom=\"borderBottom\"\n :class=\"listClass\"\n >\n <slot v-bind=\"slotProps\" />\n </GrDropdownMenuList>\n </template>\n </GrDropdown>\n</template>\n","<script setup lang=\"ts\">\nimport GrDropdown from '../GrDropdown/GrDropdown.vue'\n\nimport GrDropdownMenuList from './GrDropdownMenuList.vue'\n\nexport type GrDropdownMenuAlign = 'left' | 'right' | 'center'\nexport type GrDropdownMenuWidth = 'auto' | '20' | '48' | '60' | '64' | '80'\n\nexport interface GrDropdownMenuProps {\n /** Выравнивание панели относительно триггера. */\n align?: GrDropdownMenuAlign\n /** Ширина панели. */\n width?: GrDropdownMenuWidth\n /** Закрывать по клику внутри content. */\n closeOnContentClick?: boolean\n /** Дополнительные классы content-контейнера; по умолчанию `p-0`. */\n contentClass?: string\n\n // list wrapper\n /** Разделители между пунктами. */\n dividers?: boolean\n /** Верхний бордер контейнера списка. */\n borderTop?: boolean\n /** Нижний бордер контейнера списка. */\n borderBottom?: boolean\n /** Дополнительные классы для wrapper'а списка. */\n listClass?: string\n}\n\nwithDefaults(defineProps<GrDropdownMenuProps>(), {\n align: 'right',\n width: '48',\n closeOnContentClick: true,\n // В `GrDropdown` есть `p-1`, поэтому здесь по умолчанию обнуляем padding,\n // чтобы пункты меню могли растягиваться до границ.\n contentClass: 'p-0',\n dividers: false,\n borderTop: false,\n borderBottom: false,\n listClass: '',\n})\n</script>\n\n<template>\n <GrDropdown\n data-gr-dropdown-menu\n :align=\"align\"\n :width=\"width\"\n :close-on-content-click=\"closeOnContentClick\"\n :content-class=\"contentClass\"\n >\n <template #trigger=\"slotProps\">\n <slot name=\"trigger\" v-bind=\"slotProps\" />\n </template>\n\n <template #content=\"slotProps\">\n <GrDropdownMenuList\n :dividers=\"dividers\"\n :border-top=\"borderTop\"\n :border-bottom=\"borderBottom\"\n :class=\"listClass\"\n >\n <slot v-bind=\"slotProps\" />\n </GrDropdownMenuList>\n </template>\n </GrDropdown>\n</template>\n","<script setup lang=\"ts\">\nexport type GrDropdownMenuColumnAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuColumnProps {\n align?: GrDropdownMenuColumnAlign\n}\n\nwithDefaults(defineProps<GrDropdownMenuColumnProps>(), {\n align: 'center',\n})\n\nconst alignClass: Record<GrDropdownMenuColumnAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n}\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-column\n class=\"px-3 py-2 flex items-center\"\n :class=\"alignClass[align]\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nexport type GrDropdownMenuColumnAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuColumnProps {\n align?: GrDropdownMenuColumnAlign\n}\n\nwithDefaults(defineProps<GrDropdownMenuColumnProps>(), {\n align: 'center',\n})\n\nconst alignClass: Record<GrDropdownMenuColumnAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n}\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-column\n class=\"px-3 py-2 flex items-center\"\n :class=\"alignClass[align]\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuColumnsProps {\n cols?: 2 | 3 | 4\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuColumnsProps>(), {\n cols: 2,\n})\n\nconst colsClass = computed(() => {\n return {\n 2: 'grid-cols-2',\n 3: 'grid-cols-3',\n 4: 'grid-cols-4',\n }[props.cols]\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-columns\n class=\"w-full grid divide-x divide-[var(--brd)]\"\n :class=\"colsClass\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuColumnsProps {\n cols?: 2 | 3 | 4\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuColumnsProps>(), {\n cols: 2,\n})\n\nconst colsClass = computed(() => {\n return {\n 2: 'grid-cols-2',\n 3: 'grid-cols-3',\n 4: 'grid-cols-4',\n }[props.cols]\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-columns\n class=\"w-full grid divide-x divide-[var(--brd)]\"\n :class=\"colsClass\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nexport interface GrDropdownMenuDividerProps {\n inset?: boolean\n}\n\nwithDefaults(defineProps<GrDropdownMenuDividerProps>(), {\n inset: false,\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-divider\n role=\"separator\"\n class=\"border-t border-[var(--brd)]\"\n :class=\"inset ? 'mx-2' : ''\"\n />\n</template>\n","<script setup lang=\"ts\">\nexport interface GrDropdownMenuDividerProps {\n inset?: boolean\n}\n\nwithDefaults(defineProps<GrDropdownMenuDividerProps>(), {\n inset: false,\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-divider\n role=\"separator\"\n class=\"border-t border-[var(--brd)]\"\n :class=\"inset ? 'mx-2' : ''\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nexport type GrDropdownMenuHeaderAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuHeaderProps {\n title?: string\n align?: GrDropdownMenuHeaderAlign\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuHeaderProps>(), {\n title: undefined,\n align: 'left',\n uppercase: true,\n})\n\nconst slots = useSlots()\nconst isVisible = computed(() => Boolean(props.title) || Boolean(slots.default))\n\nconst titleAlignClass = computed(() => {\n const map: Record<GrDropdownMenuHeaderAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n }\n return map[props.align]\n})\n</script>\n\n<template>\n <div\n v-if=\"isVisible\"\n data-gr-dropdown-menu-header\n class=\"px-4 py-2 text-[11px] tracking-wide text-[var(--muted-fg)]\"\n :class=\"[titleAlignClass, { uppercase }]\"\n >\n <slot>{{ title }}</slot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nexport type GrDropdownMenuHeaderAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuHeaderProps {\n title?: string\n align?: GrDropdownMenuHeaderAlign\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuHeaderProps>(), {\n title: undefined,\n align: 'left',\n uppercase: true,\n})\n\nconst slots = useSlots()\nconst isVisible = computed(() => Boolean(props.title) || Boolean(slots.default))\n\nconst titleAlignClass = computed(() => {\n const map: Record<GrDropdownMenuHeaderAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n }\n return map[props.align]\n})\n</script>\n\n<template>\n <div\n v-if=\"isVisible\"\n data-gr-dropdown-menu-header\n class=\"px-4 py-2 text-[11px] tracking-wide text-[var(--muted-fg)]\"\n :class=\"[titleAlignClass, { uppercase }]\"\n >\n <slot>{{ title }}</slot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDropdownMenuHeader from './GrDropdownMenuHeader.vue'\nimport type { GrDropdownMenuHeaderAlign } from './GrDropdownMenuHeader.vue'\n\nexport interface GrDropdownMenuGroupProps {\n title?: string\n titleAlign?: GrDropdownMenuHeaderAlign\n dividers?: boolean\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuGroupProps>(), {\n title: undefined,\n titleAlign: 'left',\n dividers: false,\n uppercase: true,\n})\n\nconst itemsClass = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-group class=\"w-full\">\n <GrDropdownMenuHeader\n v-if=\"title\"\n :title=\"title\"\n :align=\"titleAlign\"\n :uppercase=\"uppercase\"\n />\n <div :class=\"itemsClass\">\n <slot />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDropdownMenuHeader from './GrDropdownMenuHeader.vue'\nimport type { GrDropdownMenuHeaderAlign } from './GrDropdownMenuHeader.vue'\n\nexport interface GrDropdownMenuGroupProps {\n title?: string\n titleAlign?: GrDropdownMenuHeaderAlign\n dividers?: boolean\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuGroupProps>(), {\n title: undefined,\n titleAlign: 'left',\n dividers: false,\n uppercase: true,\n})\n\nconst itemsClass = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-group class=\"w-full\">\n <GrDropdownMenuHeader\n v-if=\"title\"\n :title=\"title\"\n :align=\"titleAlign\"\n :uppercase=\"uppercase\"\n />\n <div :class=\"itemsClass\">\n <slot />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport type { Component } from 'vue'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nexport type GrDropdownMenuItemAlign = 'left' | 'center' | 'right'\nexport type GrDropdownMenuItemVariant = 'default' | 'danger'\n\nexport interface GrDropdownMenuItemProps {\n as?: string | Component\n disabled?: boolean\n align?: GrDropdownMenuItemAlign\n variant?: GrDropdownMenuItemVariant\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuItemProps>(), {\n as: 'button',\n disabled: false,\n align: 'left',\n variant: 'default',\n})\n\nconst attrs = useAttrs()\n\nconst isNativeButton = computed(() => props.as === 'button' || props.as === undefined)\n\nconst alignClass = computed(() => {\n const map: Record<GrDropdownMenuItemAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n }\n\n return map[props.align]\n})\n\nconst variantClass = computed(() => {\n if (props.variant === 'danger')\n return 'text-[var(--gr-danger)]'\n\n return 'text-[var(--fg)]'\n})\n\nconst disabledClass = computed(() => {\n if (!props.disabled)\n return ''\n\n return 'cursor-not-allowed opacity-60 pointer-events-none'\n})\n\nconst interactiveClass = computed(() => {\n if (props.disabled)\n return ''\n\n return 'hover:bg-[var(--accent)] hover:text-[var(--accent-fg)]'\n})\n\nconst className = computed(() => {\n return [\n // block/flex + размеры\n 'w-full min-h-[40px] px-4 py-2.5',\n 'flex items-center gap-2',\n // типографика\n 'text-[13px]',\n // взаимодействие\n 'transition-colors duration-150',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n alignClass.value,\n variantClass.value,\n interactiveClass.value,\n disabledClass.value,\n ].filter(Boolean).join(' ')\n})\n\nfunction onClickCapture(e: MouseEvent) {\n if (!props.disabled)\n return\n\n e.preventDefault()\n e.stopPropagation()\n}\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"attrs\"\n data-gr-dropdown-menu-item\n :class=\"className\"\n :type=\"isNativeButton ? (attrs.type as any) ?? 'button' : undefined\"\n :disabled=\"isNativeButton ? disabled : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :tabindex=\"disabled ? -1 : (attrs.tabindex as any)\"\n @click.capture=\"onClickCapture\"\n >\n <slot />\n </component>\n</template>","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport type { Component } from 'vue'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nexport type GrDropdownMenuItemAlign = 'left' | 'center' | 'right'\nexport type GrDropdownMenuItemVariant = 'default' | 'danger'\n\nexport interface GrDropdownMenuItemProps {\n as?: string | Component\n disabled?: boolean\n align?: GrDropdownMenuItemAlign\n variant?: GrDropdownMenuItemVariant\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuItemProps>(), {\n as: 'button',\n disabled: false,\n align: 'left',\n variant: 'default',\n})\n\nconst attrs = useAttrs()\n\nconst isNativeButton = computed(() => props.as === 'button' || props.as === undefined)\n\nconst alignClass = computed(() => {\n const map: Record<GrDropdownMenuItemAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n }\n\n return map[props.align]\n})\n\nconst variantClass = computed(() => {\n if (props.variant === 'danger')\n return 'text-[var(--gr-danger)]'\n\n return 'text-[var(--fg)]'\n})\n\nconst disabledClass = computed(() => {\n if (!props.disabled)\n return ''\n\n return 'cursor-not-allowed opacity-60 pointer-events-none'\n})\n\nconst interactiveClass = computed(() => {\n if (props.disabled)\n return ''\n\n return 'hover:bg-[var(--accent)] hover:text-[var(--accent-fg)]'\n})\n\nconst className = computed(() => {\n return [\n // block/flex + размеры\n 'w-full min-h-[40px] px-4 py-2.5',\n 'flex items-center gap-2',\n // типографика\n 'text-[13px]',\n // взаимодействие\n 'transition-colors duration-150',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n alignClass.value,\n variantClass.value,\n interactiveClass.value,\n disabledClass.value,\n ].filter(Boolean).join(' ')\n})\n\nfunction onClickCapture(e: MouseEvent) {\n if (!props.disabled)\n return\n\n e.preventDefault()\n e.stopPropagation()\n}\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"attrs\"\n data-gr-dropdown-menu-item\n :class=\"className\"\n :type=\"isNativeButton ? (attrs.type as any) ?? 'button' : undefined\"\n :disabled=\"isNativeButton ? disabled : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :tabindex=\"disabled ? -1 : (attrs.tabindex as any)\"\n @click.capture=\"onClickCapture\"\n >\n <slot />\n </component>\n</template>"],"mappings":"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"}
1
+ {"version":3,"file":"GrDropdownMenu--g9Vofcq.js","names":[],"sources":["../../../../src/components/GrDropdownMenu/GrDropdownMenuList.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuList.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenu.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenu.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumn.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumn.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumns.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuColumns.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuDivider.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuDivider.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuHeader.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuHeader.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuGroup.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuGroup.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuItem.vue","../../../../src/components/GrDropdownMenu/GrDropdownMenuItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuListProps {\n dividers?: boolean\n borderTop?: boolean\n borderBottom?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuListProps>(), {\n dividers: false,\n borderTop: false,\n borderBottom: false,\n})\n\nconst className = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n props.borderTop ? 'border-t border-[var(--brd)]' : '',\n props.borderBottom ? 'border-b border-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-list :class=\"className\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuListProps {\n dividers?: boolean\n borderTop?: boolean\n borderBottom?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuListProps>(), {\n dividers: false,\n borderTop: false,\n borderBottom: false,\n})\n\nconst className = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n props.borderTop ? 'border-t border-[var(--brd)]' : '',\n props.borderBottom ? 'border-b border-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-list :class=\"className\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport GrDropdown from '../GrDropdown/GrDropdown.vue'\n\nimport GrDropdownMenuList from './GrDropdownMenuList.vue'\n\nexport type GrDropdownMenuAlign = 'left' | 'right' | 'center'\nexport type GrDropdownMenuWidth = 'auto' | '20' | '48' | '60' | '64' | '80'\n\nexport interface GrDropdownMenuProps {\n /** Выравнивание панели относительно триггера. */\n align?: GrDropdownMenuAlign\n /** Ширина панели. */\n width?: GrDropdownMenuWidth\n /** Закрывать по клику внутри content. */\n closeOnContentClick?: boolean\n /** Дополнительные классы content-контейнера; по умолчанию `p-0`. */\n contentClass?: string\n\n // list wrapper\n /** Разделители между пунктами. */\n dividers?: boolean\n /** Верхний бордер контейнера списка. */\n borderTop?: boolean\n /** Нижний бордер контейнера списка. */\n borderBottom?: boolean\n /** Дополнительные классы для wrapper'а списка. */\n listClass?: string\n}\n\nwithDefaults(defineProps<GrDropdownMenuProps>(), {\n align: 'right',\n width: '48',\n closeOnContentClick: true,\n // В `GrDropdown` есть `p-1`, поэтому здесь по умолчанию обнуляем padding,\n // чтобы пункты меню могли растягиваться до границ.\n contentClass: 'p-0',\n dividers: false,\n borderTop: false,\n borderBottom: false,\n listClass: '',\n})\n</script>\n\n<template>\n <GrDropdown\n data-gr-dropdown-menu\n :align=\"align\"\n :width=\"width\"\n :close-on-content-click=\"closeOnContentClick\"\n :content-class=\"contentClass\"\n >\n <template #trigger=\"slotProps\">\n <slot name=\"trigger\" v-bind=\"slotProps\" />\n </template>\n\n <template #content=\"slotProps\">\n <GrDropdownMenuList\n :dividers=\"dividers\"\n :border-top=\"borderTop\"\n :border-bottom=\"borderBottom\"\n :class=\"listClass\"\n >\n <slot v-bind=\"slotProps\" />\n </GrDropdownMenuList>\n </template>\n </GrDropdown>\n</template>\n","<script setup lang=\"ts\">\nimport GrDropdown from '../GrDropdown/GrDropdown.vue'\n\nimport GrDropdownMenuList from './GrDropdownMenuList.vue'\n\nexport type GrDropdownMenuAlign = 'left' | 'right' | 'center'\nexport type GrDropdownMenuWidth = 'auto' | '20' | '48' | '60' | '64' | '80'\n\nexport interface GrDropdownMenuProps {\n /** Выравнивание панели относительно триггера. */\n align?: GrDropdownMenuAlign\n /** Ширина панели. */\n width?: GrDropdownMenuWidth\n /** Закрывать по клику внутри content. */\n closeOnContentClick?: boolean\n /** Дополнительные классы content-контейнера; по умолчанию `p-0`. */\n contentClass?: string\n\n // list wrapper\n /** Разделители между пунктами. */\n dividers?: boolean\n /** Верхний бордер контейнера списка. */\n borderTop?: boolean\n /** Нижний бордер контейнера списка. */\n borderBottom?: boolean\n /** Дополнительные классы для wrapper'а списка. */\n listClass?: string\n}\n\nwithDefaults(defineProps<GrDropdownMenuProps>(), {\n align: 'right',\n width: '48',\n closeOnContentClick: true,\n // В `GrDropdown` есть `p-1`, поэтому здесь по умолчанию обнуляем padding,\n // чтобы пункты меню могли растягиваться до границ.\n contentClass: 'p-0',\n dividers: false,\n borderTop: false,\n borderBottom: false,\n listClass: '',\n})\n</script>\n\n<template>\n <GrDropdown\n data-gr-dropdown-menu\n :align=\"align\"\n :width=\"width\"\n :close-on-content-click=\"closeOnContentClick\"\n :content-class=\"contentClass\"\n >\n <template #trigger=\"slotProps\">\n <slot name=\"trigger\" v-bind=\"slotProps\" />\n </template>\n\n <template #content=\"slotProps\">\n <GrDropdownMenuList\n :dividers=\"dividers\"\n :border-top=\"borderTop\"\n :border-bottom=\"borderBottom\"\n :class=\"listClass\"\n >\n <slot v-bind=\"slotProps\" />\n </GrDropdownMenuList>\n </template>\n </GrDropdown>\n</template>\n","<script setup lang=\"ts\">\nexport type GrDropdownMenuColumnAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuColumnProps {\n align?: GrDropdownMenuColumnAlign\n}\n\nwithDefaults(defineProps<GrDropdownMenuColumnProps>(), {\n align: 'center',\n})\n\nconst alignClass: Record<GrDropdownMenuColumnAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n}\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-column\n class=\"px-3 py-2 flex items-center\"\n :class=\"alignClass[align]\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nexport type GrDropdownMenuColumnAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuColumnProps {\n align?: GrDropdownMenuColumnAlign\n}\n\nwithDefaults(defineProps<GrDropdownMenuColumnProps>(), {\n align: 'center',\n})\n\nconst alignClass: Record<GrDropdownMenuColumnAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n}\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-column\n class=\"px-3 py-2 flex items-center\"\n :class=\"alignClass[align]\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuColumnsProps {\n cols?: 2 | 3 | 4\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuColumnsProps>(), {\n cols: 2,\n})\n\nconst colsClass = computed(() => {\n return {\n 2: 'grid-cols-2',\n 3: 'grid-cols-3',\n 4: 'grid-cols-4',\n }[props.cols]\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-columns\n class=\"w-full grid divide-x divide-[var(--brd)]\"\n :class=\"colsClass\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport interface GrDropdownMenuColumnsProps {\n cols?: 2 | 3 | 4\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuColumnsProps>(), {\n cols: 2,\n})\n\nconst colsClass = computed(() => {\n return {\n 2: 'grid-cols-2',\n 3: 'grid-cols-3',\n 4: 'grid-cols-4',\n }[props.cols]\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-columns\n class=\"w-full grid divide-x divide-[var(--brd)]\"\n :class=\"colsClass\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nexport interface GrDropdownMenuDividerProps {\n inset?: boolean\n}\n\nwithDefaults(defineProps<GrDropdownMenuDividerProps>(), {\n inset: false,\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-divider\n role=\"separator\"\n class=\"border-t border-[var(--brd)]\"\n :class=\"inset ? 'mx-2' : ''\"\n />\n</template>\n","<script setup lang=\"ts\">\nexport interface GrDropdownMenuDividerProps {\n inset?: boolean\n}\n\nwithDefaults(defineProps<GrDropdownMenuDividerProps>(), {\n inset: false,\n})\n</script>\n\n<template>\n <div\n data-gr-dropdown-menu-divider\n role=\"separator\"\n class=\"border-t border-[var(--brd)]\"\n :class=\"inset ? 'mx-2' : ''\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nexport type GrDropdownMenuHeaderAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuHeaderProps {\n title?: string\n align?: GrDropdownMenuHeaderAlign\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuHeaderProps>(), {\n title: undefined,\n align: 'left',\n uppercase: true,\n})\n\nconst slots = useSlots()\nconst isVisible = computed(() => Boolean(props.title) || Boolean(slots.default))\n\nconst titleAlignClass = computed(() => {\n const map: Record<GrDropdownMenuHeaderAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n }\n return map[props.align]\n})\n</script>\n\n<template>\n <div\n v-if=\"isVisible\"\n data-gr-dropdown-menu-header\n class=\"px-4 py-2 text-[11px] tracking-wide text-[var(--muted-fg)]\"\n :class=\"[titleAlignClass, { uppercase }]\"\n >\n <slot>{{ title }}</slot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nexport type GrDropdownMenuHeaderAlign = 'left' | 'center' | 'right'\n\nexport interface GrDropdownMenuHeaderProps {\n title?: string\n align?: GrDropdownMenuHeaderAlign\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuHeaderProps>(), {\n title: undefined,\n align: 'left',\n uppercase: true,\n})\n\nconst slots = useSlots()\nconst isVisible = computed(() => Boolean(props.title) || Boolean(slots.default))\n\nconst titleAlignClass = computed(() => {\n const map: Record<GrDropdownMenuHeaderAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n }\n return map[props.align]\n})\n</script>\n\n<template>\n <div\n v-if=\"isVisible\"\n data-gr-dropdown-menu-header\n class=\"px-4 py-2 text-[11px] tracking-wide text-[var(--muted-fg)]\"\n :class=\"[titleAlignClass, { uppercase }]\"\n >\n <slot>{{ title }}</slot>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDropdownMenuHeader from './GrDropdownMenuHeader.vue'\nimport type { GrDropdownMenuHeaderAlign } from './GrDropdownMenuHeader.vue'\n\nexport interface GrDropdownMenuGroupProps {\n title?: string\n titleAlign?: GrDropdownMenuHeaderAlign\n dividers?: boolean\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuGroupProps>(), {\n title: undefined,\n titleAlign: 'left',\n dividers: false,\n uppercase: true,\n})\n\nconst itemsClass = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-group class=\"w-full\">\n <GrDropdownMenuHeader\n v-if=\"title\"\n :title=\"title\"\n :align=\"titleAlign\"\n :uppercase=\"uppercase\"\n />\n <div :class=\"itemsClass\">\n <slot />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDropdownMenuHeader from './GrDropdownMenuHeader.vue'\nimport type { GrDropdownMenuHeaderAlign } from './GrDropdownMenuHeader.vue'\n\nexport interface GrDropdownMenuGroupProps {\n title?: string\n titleAlign?: GrDropdownMenuHeaderAlign\n dividers?: boolean\n uppercase?: boolean\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuGroupProps>(), {\n title: undefined,\n titleAlign: 'left',\n dividers: false,\n uppercase: true,\n})\n\nconst itemsClass = computed(() => {\n return [\n 'w-full',\n props.dividers ? 'divide-y divide-[var(--brd)]' : '',\n ].filter(Boolean).join(' ')\n})\n</script>\n\n<template>\n <div data-gr-dropdown-menu-group class=\"w-full\">\n <GrDropdownMenuHeader\n v-if=\"title\"\n :title=\"title\"\n :align=\"titleAlign\"\n :uppercase=\"uppercase\"\n />\n <div :class=\"itemsClass\">\n <slot />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport type { Component } from 'vue'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nexport type GrDropdownMenuItemAlign = 'left' | 'center' | 'right'\nexport type GrDropdownMenuItemVariant = 'default' | 'danger'\n\nexport interface GrDropdownMenuItemProps {\n as?: string | Component\n disabled?: boolean\n align?: GrDropdownMenuItemAlign\n variant?: GrDropdownMenuItemVariant\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuItemProps>(), {\n as: 'button',\n disabled: false,\n align: 'left',\n variant: 'default',\n})\n\nconst attrs = useAttrs()\n\nconst isNativeButton = computed(() => props.as === 'button' || props.as === undefined)\n\nconst alignClass = computed(() => {\n const map: Record<GrDropdownMenuItemAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n }\n\n return map[props.align]\n})\n\nconst variantClass = computed(() => {\n if (props.variant === 'danger')\n return 'text-[var(--gr-danger)]'\n\n return 'text-[var(--fg)]'\n})\n\nconst disabledClass = computed(() => {\n if (!props.disabled)\n return ''\n\n return 'cursor-not-allowed opacity-60 pointer-events-none'\n})\n\nconst interactiveClass = computed(() => {\n if (props.disabled)\n return ''\n\n return 'hover:bg-[var(--accent)] hover:text-[var(--accent-fg)]'\n})\n\nconst className = computed(() => {\n return [\n // block/flex + размеры\n 'w-full min-h-[40px] px-4 py-2.5',\n 'flex items-center gap-2',\n // типографика\n 'text-[13px]',\n // взаимодействие\n 'transition-colors duration-150',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n alignClass.value,\n variantClass.value,\n interactiveClass.value,\n disabledClass.value,\n ].filter(Boolean).join(' ')\n})\n\nfunction onClickCapture(e: MouseEvent) {\n if (!props.disabled)\n return\n\n e.preventDefault()\n e.stopPropagation()\n}\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"attrs\"\n data-gr-dropdown-menu-item\n :class=\"className\"\n :type=\"isNativeButton ? (attrs.type as any) ?? 'button' : undefined\"\n :disabled=\"isNativeButton ? disabled : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :tabindex=\"disabled ? -1 : (attrs.tabindex as any)\"\n @click.capture=\"onClickCapture\"\n >\n <slot />\n </component>\n</template>","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport type { Component } from 'vue'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nexport type GrDropdownMenuItemAlign = 'left' | 'center' | 'right'\nexport type GrDropdownMenuItemVariant = 'default' | 'danger'\n\nexport interface GrDropdownMenuItemProps {\n as?: string | Component\n disabled?: boolean\n align?: GrDropdownMenuItemAlign\n variant?: GrDropdownMenuItemVariant\n}\n\nconst props = withDefaults(defineProps<GrDropdownMenuItemProps>(), {\n as: 'button',\n disabled: false,\n align: 'left',\n variant: 'default',\n})\n\nconst attrs = useAttrs()\n\nconst isNativeButton = computed(() => props.as === 'button' || props.as === undefined)\n\nconst alignClass = computed(() => {\n const map: Record<GrDropdownMenuItemAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n }\n\n return map[props.align]\n})\n\nconst variantClass = computed(() => {\n if (props.variant === 'danger')\n return 'text-[var(--gr-danger)]'\n\n return 'text-[var(--fg)]'\n})\n\nconst disabledClass = computed(() => {\n if (!props.disabled)\n return ''\n\n return 'cursor-not-allowed opacity-60 pointer-events-none'\n})\n\nconst interactiveClass = computed(() => {\n if (props.disabled)\n return ''\n\n return 'hover:bg-[var(--accent)] hover:text-[var(--accent-fg)]'\n})\n\nconst className = computed(() => {\n return [\n // block/flex + размеры\n 'w-full min-h-[40px] px-4 py-2.5',\n 'flex items-center gap-2',\n // типографика\n 'text-[13px]',\n // взаимодействие\n 'transition-colors duration-150',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]',\n alignClass.value,\n variantClass.value,\n interactiveClass.value,\n disabledClass.value,\n ].filter(Boolean).join(' ')\n})\n\nfunction onClickCapture(e: MouseEvent) {\n if (!props.disabled)\n return\n\n e.preventDefault()\n e.stopPropagation()\n}\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"attrs\"\n data-gr-dropdown-menu-item\n :class=\"className\"\n :type=\"isNativeButton ? (attrs.type as any) ?? 'button' : undefined\"\n :disabled=\"isNativeButton ? disabled : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :tabindex=\"disabled ? -1 : (attrs.tabindex as any)\"\n @click.capture=\"onClickCapture\"\n >\n <slot />\n </component>\n</template>"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { a as GrDropdownMenuColumns_default, c as GrDropdownMenuList_default, i as GrDropdownMenuDivider_default, n as GrDropdownMenuGroup_default, o as GrDropdownMenuColumn_default, r as GrDropdownMenuHeader_default, s as GrDropdownMenu_default, t as GrDropdownMenuItem_default } from "./chunks/GrDropdownMenu-DFEJLPcV.js";
1
+ import { a as GrDropdownMenuColumns_default, c as GrDropdownMenuList_default, i as GrDropdownMenuDivider_default, n as GrDropdownMenuGroup_default, o as GrDropdownMenuColumn_default, r as GrDropdownMenuHeader_default, s as GrDropdownMenu_default, t as GrDropdownMenuItem_default } from "./chunks/GrDropdownMenu--g9Vofcq.js";
2
2
  import { t as grDropdownMenuConfig } from "../../chunks/config-Cb2PAlSD.js";
3
3
  export { GrDropdownMenu_default as GrDropdownMenu, GrDropdownMenu_default as default, GrDropdownMenuColumn_default as GrDropdownMenuColumn, GrDropdownMenuColumns_default as GrDropdownMenuColumns, GrDropdownMenuDivider_default as GrDropdownMenuDivider, GrDropdownMenuGroup_default as GrDropdownMenuGroup, GrDropdownMenuHeader_default as GrDropdownMenuHeader, GrDropdownMenuItem_default as GrDropdownMenuItem, GrDropdownMenuList_default as GrDropdownMenuList, grDropdownMenuConfig };
@@ -0,0 +1,73 @@
1
+ import { t as GR_FORM_FIELD_KEY } from "../../../chunks/context-DdNIxa1w.js";
2
+ import { computed, createCommentVNode, createElementBlock, createTextVNode, defineComponent, normalizeClass, openBlock, provide, renderSlot, toDisplayString, unref, useId, useSlots } from "vue";
3
+ //#region src/components/GrFormField/GrFormField.vue?vue&type=script&setup=true&lang.ts
4
+ var _hoisted_1 = { class: "flex flex-col gap-2" };
5
+ var _hoisted_2 = ["for"];
6
+ var _hoisted_3 = {
7
+ key: 0,
8
+ "data-gr-form-field-required": "",
9
+ "aria-hidden": "true",
10
+ class: "text-[var(--gr-danger)]"
11
+ };
12
+ var _hoisted_4 = ["id"];
13
+ var _hoisted_5 = ["id"];
14
+ //#endregion
15
+ //#region src/components/GrFormField/GrFormField.vue
16
+ var GrFormField_default = /* @__PURE__ */ defineComponent({
17
+ __name: "GrFormField",
18
+ props: {
19
+ label: { default: void 0 },
20
+ forId: { default: void 0 },
21
+ error: { default: void 0 },
22
+ hint: { default: void 0 },
23
+ required: {
24
+ type: Boolean,
25
+ default: false
26
+ },
27
+ labelClass: { default: void 0 }
28
+ },
29
+ setup(__props) {
30
+ const props = __props;
31
+ const slots = useSlots();
32
+ const generatedId = useId();
33
+ const fieldId = computed(() => props.forId ?? generatedId);
34
+ const errorId = useId();
35
+ const hintId = useId();
36
+ const hasHint = computed(() => Boolean(props.hint) || Boolean(slots.hint));
37
+ const hasError = computed(() => Boolean(props.error));
38
+ provide(GR_FORM_FIELD_KEY, {
39
+ id: fieldId,
40
+ describedById: computed(() => {
41
+ const ids = [hasHint.value ? hintId : null, hasError.value ? errorId : null].filter(Boolean);
42
+ return ids.length ? ids.join(" ") : void 0;
43
+ }),
44
+ invalid: hasError,
45
+ required: computed(() => props.required)
46
+ });
47
+ return (_ctx, _cache) => {
48
+ return openBlock(), createElementBlock("div", _hoisted_1, [
49
+ props.label ? (openBlock(), createElementBlock("label", {
50
+ key: 0,
51
+ for: fieldId.value,
52
+ class: normalizeClass(["text-sm text-[var(--muted-fg)]", props.labelClass])
53
+ }, [createTextVNode(toDisplayString(props.label) + " ", 1), props.required ? (openBlock(), createElementBlock("span", _hoisted_3, "*")) : createCommentVNode("", true)], 10, _hoisted_2)) : createCommentVNode("", true),
54
+ hasHint.value ? (openBlock(), createElementBlock("p", {
55
+ key: 1,
56
+ id: unref(hintId),
57
+ "data-gr-form-field-hint": "",
58
+ class: "text-xs text-[var(--muted-fg)]"
59
+ }, [renderSlot(_ctx.$slots, "hint", {}, () => [createTextVNode(toDisplayString(props.hint), 1)])], 8, _hoisted_4)) : createCommentVNode("", true),
60
+ renderSlot(_ctx.$slots, "default"),
61
+ hasError.value ? (openBlock(), createElementBlock("div", {
62
+ key: 2,
63
+ id: unref(errorId),
64
+ "data-gr-form-field-error": "",
65
+ role: "alert",
66
+ class: "text-sm text-[var(--gr-danger)]"
67
+ }, toDisplayString(props.error), 9, _hoisted_5)) : createCommentVNode("", true)
68
+ ]);
69
+ };
70
+ }
71
+ });
72
+ //#endregion
73
+ export { GrFormField_default as t };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrFormField-DnfMHx_U.js","names":[],"sources":["../../../../src/components/GrFormField/GrFormField.vue","../../../../src/components/GrFormField/GrFormField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, provide, useId, useSlots } from 'vue'\n\nimport { GR_FORM_FIELD_KEY } from './context'\n\ntype LabelClass = string | string[] | Record<string, boolean>\n\nconst props = withDefaults(\n defineProps<{\n label?: string\n /** Явный id контрола. Если не задан — генерируется автоматически. */\n forId?: string\n error?: string\n /** Подсказка под лейблом/над контролом (можно также через слот `#hint`). */\n hint?: string\n /** Помечает поле обязательным (маркер `*` + `aria-required` у контрола). */\n required?: boolean\n labelClass?: LabelClass\n }>(),\n {\n label: undefined,\n forId: undefined,\n error: undefined,\n hint: undefined,\n required: false,\n labelClass: undefined,\n },\n)\n\nconst slots = useSlots()\n\n// Автогенерация id: контрол внутри читает его через inject и связывается с\n// лейблом (`for`) без ручного дублирования `forId`.\nconst generatedId = useId()\nconst fieldId = computed(() => props.forId ?? generatedId)\n\nconst errorId = useId()\nconst hintId = useId()\n\nconst hasHint = computed(() => Boolean(props.hint) || Boolean(slots.hint))\nconst hasError = computed(() => Boolean(props.error))\n\n// `aria-describedby` контрола: подсказка и/или ошибка.\nconst describedById = computed(() => {\n const ids = [hasHint.value ? hintId : null, hasError.value ? errorId : null].filter(Boolean)\n return ids.length ? ids.join(' ') : undefined\n})\n\nprovide(GR_FORM_FIELD_KEY, {\n id: fieldId,\n describedById,\n invalid: hasError,\n required: computed(() => props.required),\n})\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2\">\n <label\n v-if=\"props.label\"\n :for=\"fieldId\"\n class=\"text-sm text-[var(--muted-fg)]\"\n :class=\"props.labelClass\"\n >\n {{ props.label }}\n <span v-if=\"props.required\" data-gr-form-field-required aria-hidden=\"true\" class=\"text-[var(--gr-danger)]\">*</span>\n </label>\n\n <p\n v-if=\"hasHint\"\n :id=\"hintId\"\n data-gr-form-field-hint\n class=\"text-xs text-[var(--muted-fg)]\"\n >\n <slot name=\"hint\">{{ props.hint }}</slot>\n </p>\n\n <slot />\n\n <div\n v-if=\"hasError\"\n :id=\"errorId\"\n data-gr-form-field-error\n role=\"alert\"\n class=\"text-sm text-[var(--gr-danger)]\"\n >\n {{ props.error }}\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, useId, useSlots } from 'vue'\n\nimport { GR_FORM_FIELD_KEY } from './context'\n\ntype LabelClass = string | string[] | Record<string, boolean>\n\nconst props = withDefaults(\n defineProps<{\n label?: string\n /** Явный id контрола. Если не задан — генерируется автоматически. */\n forId?: string\n error?: string\n /** Подсказка под лейблом/над контролом (можно также через слот `#hint`). */\n hint?: string\n /** Помечает поле обязательным (маркер `*` + `aria-required` у контрола). */\n required?: boolean\n labelClass?: LabelClass\n }>(),\n {\n label: undefined,\n forId: undefined,\n error: undefined,\n hint: undefined,\n required: false,\n labelClass: undefined,\n },\n)\n\nconst slots = useSlots()\n\n// Автогенерация id: контрол внутри читает его через inject и связывается с\n// лейблом (`for`) без ручного дублирования `forId`.\nconst generatedId = useId()\nconst fieldId = computed(() => props.forId ?? generatedId)\n\nconst errorId = useId()\nconst hintId = useId()\n\nconst hasHint = computed(() => Boolean(props.hint) || Boolean(slots.hint))\nconst hasError = computed(() => Boolean(props.error))\n\n// `aria-describedby` контрола: подсказка и/или ошибка.\nconst describedById = computed(() => {\n const ids = [hasHint.value ? hintId : null, hasError.value ? errorId : null].filter(Boolean)\n return ids.length ? ids.join(' ') : undefined\n})\n\nprovide(GR_FORM_FIELD_KEY, {\n id: fieldId,\n describedById,\n invalid: hasError,\n required: computed(() => props.required),\n})\n</script>\n\n<template>\n <div class=\"flex flex-col gap-2\">\n <label\n v-if=\"props.label\"\n :for=\"fieldId\"\n class=\"text-sm text-[var(--muted-fg)]\"\n :class=\"props.labelClass\"\n >\n {{ props.label }}\n <span v-if=\"props.required\" data-gr-form-field-required aria-hidden=\"true\" class=\"text-[var(--gr-danger)]\">*</span>\n </label>\n\n <p\n v-if=\"hasHint\"\n :id=\"hintId\"\n data-gr-form-field-hint\n class=\"text-xs text-[var(--muted-fg)]\"\n >\n <slot name=\"hint\">{{ props.hint }}</slot>\n </p>\n\n <slot />\n\n <div\n v-if=\"hasError\"\n :id=\"errorId\"\n data-gr-form-field-error\n role=\"alert\"\n class=\"text-sm text-[var(--gr-danger)]\"\n >\n {{ props.error }}\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOA,MAAM,QAAQ;EAsBd,MAAM,QAAQ,SAAS;EAIvB,MAAM,cAAc,MAAM;EAC1B,MAAM,UAAU,eAAe,MAAM,SAAS,WAAW;EAEzD,MAAM,UAAU,MAAM;EACtB,MAAM,SAAS,MAAM;EAErB,MAAM,UAAU,eAAe,QAAQ,MAAM,IAAI,KAAK,QAAQ,MAAM,IAAI,CAAC;EACzE,MAAM,WAAW,eAAe,QAAQ,MAAM,KAAK,CAAC;EAQpD,QAAQ,mBAAmB;GACzB,IAAI;GACJ,eAPoB,eAAe;IACnC,MAAM,MAAM,CAAC,QAAQ,QAAQ,SAAS,MAAM,SAAS,QAAQ,UAAU,IAAI,CAAC,CAAC,OAAO,OAAO;IAC3F,OAAO,IAAI,SAAS,IAAI,KAAK,GAAG,IAAI,KAAA;GACtC,CAIE;GACA,SAAS;GACT,UAAU,eAAe,MAAM,QAAQ;EACzC,CAAC;;uBAIC,mBA+BM,OA/BN,YA+BM;IA7BI,MAAM,SAAA,UAAA,GADd,mBAQQ,SAAA;;KANL,KAAK,QAAA;KACN,OAAK,eAAA,CAAC,kCACE,MAAM,UAAU,CAAA;wCAErB,MAAM,KAAK,IAAG,KACjB,CAAA,GAAY,MAAM,YAAA,UAAA,GAAlB,mBAAmH,QAAnH,YAA2G,GAAC,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,IAAA,UAAA,KAAA,mBAAA,IAAA,IAAA;IAItG,QAAA,SAAA,UAAA,GADR,mBAOI,KAAA;;KALD,IAAI,MAAA,MAAA;KACL,2BAAA;KACA,OAAM;QAEN,WAAyC,KAAA,QAAA,QAAA,CAAA,SAAA,CAAA,gBAAA,gBAApB,MAAM,IAAI,GAAA,CAAA,CAAA,CAAA,CAAA,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA;IAGjC,WAAQ,KAAA,QAAA,SAAA;IAGA,SAAA,SAAA,UAAA,GADR,mBAQM,OAAA;;KANH,IAAI,MAAA,OAAA;KACL,4BAAA;KACA,MAAK;KACL,OAAM;uBAEH,MAAM,KAAK,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA"}
@@ -1,3 +1,4 @@
1
- import { t as GrFormField_default } from "./chunks/GrFormField-BujNQrw8.js";
1
+ import { n as useGrFormFieldContext, t as GR_FORM_FIELD_KEY } from "../../chunks/context-DdNIxa1w.js";
2
+ import { t as GrFormField_default } from "./chunks/GrFormField-DnfMHx_U.js";
2
3
  import { t as grFormFieldConfig } from "../../chunks/config-PFg39mYo.js";
3
- export { GrFormField_default as GrFormField, GrFormField_default as default, grFormFieldConfig };
4
+ export { GR_FORM_FIELD_KEY, GrFormField_default as GrFormField, GrFormField_default as default, grFormFieldConfig, useGrFormFieldContext };