@feugene/granularity 0.45.0 → 0.47.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 (150) hide show
  1. package/README.md +3 -3
  2. package/dist/chunks/{x-circle-BCBURwyX.js → check-circle-Bnrb-CGJ.js} +8 -32
  3. package/dist/chunks/check-circle-Bnrb-CGJ.js.map +1 -0
  4. package/dist/chunks/{config-BqT6PMzO.js → config-B42iJ48O.js} +5 -1
  5. package/dist/chunks/{config-BqT6PMzO.js.map → config-B42iJ48O.js.map} +1 -1
  6. package/dist/chunks/{config-BGCyyXiD.js → config-BAse0laT.js} +5 -1
  7. package/dist/chunks/{config-BGCyyXiD.js.map → config-BAse0laT.js.map} +1 -1
  8. package/dist/chunks/{config-MmPym-Z7.js → config-BLP94dPY.js} +5 -1
  9. package/dist/chunks/{config-MmPym-Z7.js.map → config-BLP94dPY.js.map} +1 -1
  10. package/dist/chunks/{config-CjKpUcmy.js → config-Bdf1bt-m.js} +25 -16
  11. package/dist/chunks/config-Bdf1bt-m.js.map +1 -0
  12. package/dist/chunks/{config-CIkdsWUk.js → config-CIUU9ZpY.js} +4 -1
  13. package/dist/chunks/config-CIUU9ZpY.js.map +1 -0
  14. package/dist/chunks/{config-BhfNgyWL.js → config-DENqOoh0.js} +5 -1
  15. package/dist/chunks/config-DENqOoh0.js.map +1 -0
  16. package/dist/chunks/{config-ChnYtO4o.js → config-bjDf8nBf.js} +16 -1
  17. package/dist/chunks/config-bjDf8nBf.js.map +1 -0
  18. package/dist/chunks/controlState-DoImKciE.js +35 -0
  19. package/dist/chunks/controlState-DoImKciE.js.map +1 -0
  20. package/dist/chunks/{en-DiHzFact.js → en-DjTnfTqM.js} +3 -1
  21. package/dist/chunks/en-DjTnfTqM.js.map +1 -0
  22. package/dist/chunks/{es-1ZL6NtkB.js → es-Bc_t3FI8.js} +3 -1
  23. package/dist/chunks/es-Bc_t3FI8.js.map +1 -0
  24. package/dist/chunks/{es-CeKkMxZ_.js → es-DIFzSXSZ.js} +3 -3
  25. package/dist/chunks/{es-CeKkMxZ_.js.map → es-DIFzSXSZ.js.map} +1 -1
  26. package/dist/chunks/{generated-DAKeOOqm.js → generated-CQ4h6Ieq.js} +28 -0
  27. package/dist/chunks/{generated-DAKeOOqm.js.map → generated-CQ4h6Ieq.js.map} +1 -1
  28. package/dist/chunks/{granular-provider-D_8_l-gM.js → granular-provider-AKukmYva.js} +7 -7
  29. package/dist/chunks/{granular-provider-D_8_l-gM.js.map → granular-provider-AKukmYva.js.map} +1 -1
  30. package/dist/chunks/{ru-Dr2RYn0P.js → ru-Bb-co59W.js} +3 -1
  31. package/dist/chunks/ru-Bb-co59W.js.map +1 -0
  32. package/dist/chunks/x-circle-BigSZy8m.js +26 -0
  33. package/dist/chunks/x-circle-BigSZy8m.js.map +1 -0
  34. package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js → GrAlert-CfEZghSY.js} +2 -1
  35. package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js.map → GrAlert-CfEZghSY.js.map} +1 -1
  36. package/dist/components/GrAlert/index.js +1 -1
  37. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-D396_JrW.js → GrAutocomplete-C-uovdv8.js} +320 -224
  38. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-C-uovdv8.js.map +1 -0
  39. package/dist/components/GrAutocomplete/index.js +1 -1
  40. package/dist/components/GrAutocomplete/styles.css +1 -1
  41. package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js → GrColorPicker-BRM_4lyI.js} +1 -1
  42. package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js.map → GrColorPicker-BRM_4lyI.js.map} +1 -1
  43. package/dist/components/GrColorPicker/index.js +1 -1
  44. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js.map → GrCommandPalette-BJHmkDQv.js.map} +1 -1
  45. package/dist/components/GrCommandPalette/index.js +1 -1
  46. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js → GrConfirmDialog-BzUQwbec.js} +1 -1
  47. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js.map → GrConfirmDialog-BzUQwbec.js.map} +1 -1
  48. package/dist/components/GrConfirmDialog/index.js +1 -1
  49. package/dist/components/GrDataTable/chunks/{GrDataTable-xNSmO_I-.js → GrDataTable-Dp9Fp_P5.js} +606 -499
  50. package/dist/components/GrDataTable/chunks/GrDataTable-Dp9Fp_P5.js.map +1 -0
  51. package/dist/components/GrDataTable/index.js +1 -1
  52. package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js → GrDialogService-Dtq0ZCN5.js} +3 -3
  53. package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js.map → GrDialogService-Dtq0ZCN5.js.map} +1 -1
  54. package/dist/components/GrDialogService/index.js +1 -1
  55. package/dist/components/GrFormField/chunks/GrFormField-DO61vxpS.js.map +1 -1
  56. package/dist/components/GrInput/chunks/{GrInput-TFeBm3gQ.js → GrInput-DV4gMWPR.js} +40 -11
  57. package/dist/components/GrInput/chunks/GrInput-DV4gMWPR.js.map +1 -0
  58. package/dist/components/GrInput/index.js +2 -2
  59. package/dist/components/GrInputTag/chunks/{GrInputTag-Ci8AO1ze.js → GrInputTag-CO0YU-ok.js} +30 -6
  60. package/dist/components/GrInputTag/chunks/GrInputTag-CO0YU-ok.js.map +1 -0
  61. package/dist/components/GrInputTag/index.js +2 -2
  62. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CdlWMGnF.js → GrJsonViewer-D7CyWzhT.js} +2 -2
  63. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CdlWMGnF.js.map → GrJsonViewer-D7CyWzhT.js.map} +1 -1
  64. package/dist/components/GrJsonViewer/index.js +1 -1
  65. package/dist/components/GrNumberInput/chunks/{GrNumberInput-CL5QhOmx.js → GrNumberInput-BI6-vkcs.js} +48 -16
  66. package/dist/components/GrNumberInput/chunks/GrNumberInput-BI6-vkcs.js.map +1 -0
  67. package/dist/components/GrNumberInput/index.js +2 -2
  68. package/dist/components/GrPagination/chunks/{GrPagination-DhbNZHEF.js → GrPagination-BbaF5eXk.js} +10 -7
  69. package/dist/components/GrPagination/chunks/GrPagination-BbaF5eXk.js.map +1 -0
  70. package/dist/components/GrPagination/index.js +2 -2
  71. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js → GrPromptDialog-BEL-QgwE.js} +3 -3
  72. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js.map → GrPromptDialog-BEL-QgwE.js.map} +1 -1
  73. package/dist/components/GrPromptDialog/index.js +1 -1
  74. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js → GrResponseErrorBanner-Bdd5c07x.js} +1 -1
  75. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js.map → GrResponseErrorBanner-Bdd5c07x.js.map} +1 -1
  76. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js → GrResponseErrorBanner-DySe1ym4.js} +1 -1
  77. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js.map → GrResponseErrorBanner-DySe1ym4.js.map} +1 -1
  78. package/dist/components/GrResponseErrorBanner/index.js +2 -2
  79. package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js → GrSelect-0iI4wdR_.js} +3 -3
  80. package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js.map → GrSelect-0iI4wdR_.js.map} +1 -1
  81. package/dist/components/GrSelect/index.js +1 -1
  82. package/dist/components/GrTextarea/chunks/{GrTextarea-BII3w61K.js → GrTextarea-Bfgc0DD2.js} +73 -32
  83. package/dist/components/GrTextarea/chunks/GrTextarea-Bfgc0DD2.js.map +1 -0
  84. package/dist/components/GrTextarea/index.js +2 -2
  85. package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js → GrToaster-CZixNk0l.js} +2 -1
  86. package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js.map → GrToaster-CZixNk0l.js.map} +1 -1
  87. package/dist/components/GrToaster/index.js +1 -1
  88. package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js → GrTransfer-DdfBUf35.js} +2 -2
  89. package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js.map → GrTransfer-DdfBUf35.js.map} +1 -1
  90. package/dist/components/GrTransfer/index.js +1 -1
  91. package/dist/components/GrTree/chunks/{GrTree-DnDGW0xO.js → GrTree-6yZrncJE.js} +52 -18
  92. package/dist/components/GrTree/chunks/GrTree-6yZrncJE.js.map +1 -0
  93. package/dist/components/GrTree/index.js +1 -1
  94. package/dist/components/GrTree/styles.css +1 -1
  95. package/dist/components/GrTreeSections/chunks/{GrTreeSections-D2PQ87mw.js → GrTreeSections-DcmDcLwj.js} +5 -3
  96. package/dist/components/GrTreeSections/chunks/GrTreeSections-DcmDcLwj.js.map +1 -0
  97. package/dist/components/GrTreeSections/index.js +2 -2
  98. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DzheDCuZ.js → GrTreeSelect-B6KoDYiZ.js} +44 -19
  99. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-B6KoDYiZ.js.map +1 -0
  100. package/dist/components/GrTreeSelect/index.js +2 -2
  101. package/dist/granular-provider-node.js +1 -1
  102. package/dist/granular-provider.js +1 -1
  103. package/dist/i18n/all.js +1 -1
  104. package/dist/i18n/index.js +1 -1
  105. package/dist/index.js +30 -30
  106. package/dist/theme.js +1 -1
  107. package/dist/tokens.js +1 -1
  108. package/dist/types/components/GrAutocomplete/composables/useAutocompleteNavigation.d.ts +39 -0
  109. package/dist/types/components/GrAutocomplete/composables/useAutocompletePanel.d.ts +36 -0
  110. package/dist/types/components/GrAutocomplete/composables/useAutocompleteValues.d.ts +28 -0
  111. package/dist/types/components/GrAutocomplete/composables/useAutocompleteVirtual.d.ts +33 -0
  112. package/dist/types/components/GrAutocomplete/composables/useRemoteOptions.d.ts +33 -0
  113. package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +1 -1
  114. package/dist/types/components/GrDataTable/composables/useDataTableColumnOrder.d.ts +45 -0
  115. package/dist/types/components/GrDataTable/composables/useDataTableColumnWidths.d.ts +38 -0
  116. package/dist/types/components/GrDataTable/composables/useDataTableLayout.d.ts +29 -0
  117. package/dist/types/components/GrDataTable/composables/useDataTableRowKeys.d.ts +16 -0
  118. package/dist/types/components/GrDataTable/composables/useDataTableSelection.d.ts +32 -0
  119. package/dist/types/components/GrDataTable/composables/useDataTableSort.d.ts +37 -0
  120. package/dist/types/components/GrFormField/GrFormField.vue.d.ts +7 -1
  121. package/dist/types/components/GrPagination/GrPagination.vue.d.ts +17 -2
  122. package/dist/types/components/GrPagination/grPaginationStyles.d.ts +15 -6
  123. package/dist/types/components/GrPagination/index.d.ts +1 -1
  124. package/dist/types/components/GrTree/grTreeStyles.d.ts +1 -1
  125. package/dist/types/components/GrTreeSections/grTreeSectionsStyles.d.ts +15 -0
  126. package/dist/types/components/shared/controlState.d.ts +36 -0
  127. package/dist/types/i18n/messages/en.d.ts +4 -0
  128. package/dist/types/i18n/messages/es.d.ts +4 -0
  129. package/dist/types/i18n/messages/ru.d.ts +4 -0
  130. package/dist/web-types.json +4 -3
  131. package/package.json +1 -1
  132. package/dist/chunks/config-BhfNgyWL.js.map +0 -1
  133. package/dist/chunks/config-CIkdsWUk.js.map +0 -1
  134. package/dist/chunks/config-ChnYtO4o.js.map +0 -1
  135. package/dist/chunks/config-CjKpUcmy.js.map +0 -1
  136. package/dist/chunks/en-DiHzFact.js.map +0 -1
  137. package/dist/chunks/es-1ZL6NtkB.js.map +0 -1
  138. package/dist/chunks/ru-Dr2RYn0P.js.map +0 -1
  139. package/dist/chunks/x-circle-BCBURwyX.js.map +0 -1
  140. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-D396_JrW.js.map +0 -1
  141. package/dist/components/GrDataTable/chunks/GrDataTable-xNSmO_I-.js.map +0 -1
  142. package/dist/components/GrInput/chunks/GrInput-TFeBm3gQ.js.map +0 -1
  143. package/dist/components/GrInputTag/chunks/GrInputTag-Ci8AO1ze.js.map +0 -1
  144. package/dist/components/GrNumberInput/chunks/GrNumberInput-CL5QhOmx.js.map +0 -1
  145. package/dist/components/GrPagination/chunks/GrPagination-DhbNZHEF.js.map +0 -1
  146. package/dist/components/GrTextarea/chunks/GrTextarea-BII3w61K.js.map +0 -1
  147. package/dist/components/GrTree/chunks/GrTree-DnDGW0xO.js.map +0 -1
  148. package/dist/components/GrTreeSections/chunks/GrTreeSections-D2PQ87mw.js.map +0 -1
  149. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-DzheDCuZ.js.map +0 -1
  150. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js → GrCommandPalette-BJHmkDQv.js} +1 -1
@@ -1,3 +1,4 @@
1
+ import { n as alert_triangle_default, t as check_circle_default } from "../../../chunks/check-circle-Bnrb-CGJ.js";
1
2
  import { t as x_default } from "../../../chunks/x-2KXnqxiD.js";
2
3
  import { a as useGrComponentSize, s as useGrThemeAttrs } from "../../../chunks/context-CPMRfwVr.js";
3
4
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
@@ -14,10 +15,11 @@ import { t as useControlAddons } from "../../../chunks/useControlAddons-asUr10Pf
14
15
  import { n as panelPopTransition } from "../../../chunks/overlayPanelSurface-BKeMhRx4.js";
15
16
  import { t as check_default } from "../../../chunks/check-BZI24Qs4.js";
16
17
  import { t as chevron_down_default } from "../../../chunks/chevron-down-CQS2OG_s.js";
17
- import { t as GrInput_default } from "../../GrInput/chunks/GrInput-TFeBm3gQ.js";
18
- import { t as GrTree_default } from "../../GrTree/chunks/GrTree-DnDGW0xO.js";
19
- import { a as grTreeSelectStateClass, i as grTreeSelectPanelClass, o as paddingX, r as grTreeSelectClass, s as trailingZoneWidth } from "../../../chunks/config-BGCyyXiD.js";
20
- import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, nextTick, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, useSlots, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
18
+ import { a as controlStateTextKey, i as controlStateIconColors, n as controlStateFallbackText, r as controlStateIconClass, t as controlSignalState } from "../../../chunks/controlState-DoImKciE.js";
19
+ import { t as GrInput_default } from "../../GrInput/chunks/GrInput-DV4gMWPR.js";
20
+ import { t as GrTree_default } from "../../GrTree/chunks/GrTree-6yZrncJE.js";
21
+ import { a as grTreeSelectStateClass, i as grTreeSelectPanelClass, o as paddingX, r as grTreeSelectClass, s as trailingZoneWidth } from "../../../chunks/config-BAse0laT.js";
22
+ import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, nextTick, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useId, useSlots, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
21
23
  //#region src/components/GrTreeSelect/GrTreeSelect.vue?vue&type=script&setup=true&lang.ts
22
24
  var _hoisted_1 = ["name", "value"];
23
25
  var _hoisted_2 = { class: "relative" };
@@ -33,25 +35,26 @@ var _hoisted_3 = [
33
35
  "aria-describedby",
34
36
  "aria-label"
35
37
  ];
36
- var _hoisted_4 = ["aria-label"];
37
- var _hoisted_5 = {
38
- key: 2,
38
+ var _hoisted_4 = ["id"];
39
+ var _hoisted_5 = ["aria-label"];
40
+ var _hoisted_6 = {
41
+ key: 4,
39
42
  "data-testid": "gr-tree-select-chevron",
40
43
  "data-gr-tree-select-chevron": "",
41
44
  class: "absolute top-1/2 -translate-y-1/2 right-3 text-[var(--gr-muted-fg)] pointer-events-none"
42
45
  };
43
- var _hoisted_6 = {
46
+ var _hoisted_7 = {
44
47
  key: 0,
45
48
  class: "p-2 border-b border-[var(--gr-brd)]"
46
49
  };
47
- var _hoisted_7 = { class: "flex items-center gap-2 min-w-0" };
48
- var _hoisted_8 = {
50
+ var _hoisted_8 = { class: "flex items-center gap-2 min-w-0" };
51
+ var _hoisted_9 = {
49
52
  key: 0,
50
53
  "data-gr-tree-select-check": "",
51
54
  class: "inline-block h-4 w-4 shrink-0",
52
55
  "aria-hidden": "true"
53
56
  };
54
- var _hoisted_9 = { class: "truncate" };
57
+ var _hoisted_10 = { class: "truncate" };
55
58
  //#endregion
56
59
  //#region src/components/GrTreeSelect/GrTreeSelect.vue
57
60
  var GrTreeSelect_default = /* @__PURE__ */ defineComponent({
@@ -161,8 +164,18 @@ var GrTreeSelect_default = /* @__PURE__ */ defineComponent({
161
164
  const treeId = `gr-tree-select-tree-${useId()}`;
162
165
  const field = useGrFormFieldContext();
163
166
  const fieldId = computed(() => field?.id.value);
164
- const describedBy = computed(() => field?.describedById.value);
167
+ const stateTextId = useId();
165
168
  const { disabled: isDisabled, invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props);
169
+ /**
170
+ * Небуквенный признак состояния: иконка для глаз, скрытая подпись для
171
+ * скринридера. Разбор — `shared/controlState`. Встаёт левее крестика и
172
+ * шеврона: правый край триггера занят одним из них всегда.
173
+ */
174
+ const signalState = computed(() => controlSignalState(props.state, isInvalid.value));
175
+ const stateIcon = computed(() => signalState.value === "success" ? check_circle_default : alert_triangle_default);
176
+ const stateIconClass = computed(() => signalState.value ? `${controlStateIconClass} ${controlStateIconColors[signalState.value]}` : "");
177
+ const stateText = computed(() => signalState.value ? t(controlStateTextKey[signalState.value], controlStateFallbackText[signalState.value]) : "");
178
+ const describedBy = computed(() => [field?.describedById.value, signalState.value ? stateTextId : void 0].filter(Boolean).join(" ") || void 0);
166
179
  function focus() {
167
180
  triggerEl.value?.focus();
168
181
  }
@@ -492,8 +505,20 @@ var GrTreeSelect_default = /* @__PURE__ */ defineComponent({
492
505
  onFocus: onTriggerFocus,
493
506
  onKeydown: onTriggerKeydown
494
507
  }, null, 46, _hoisted_3),
495
- __props.clearable && hasSelection.value && !__props.disabled && !unref(isReadonly) ? (openBlock(), createElementBlock("button", {
508
+ signalState.value ? (openBlock(), createElementBlock("span", {
496
509
  key: 1,
510
+ "data-gr-tree-select-state": "",
511
+ class: normalizeClass(["absolute top-1/2 -translate-y-1/2 right-9", stateIconClass.value]),
512
+ "aria-hidden": "true"
513
+ }, [(openBlock(), createBlock(resolveDynamicComponent(stateIcon.value), { class: "h-4 w-4" }))], 2)) : createCommentVNode("", true),
514
+ signalState.value ? (openBlock(), createElementBlock("span", {
515
+ key: 2,
516
+ id: unref(stateTextId),
517
+ "data-gr-tree-select-state-text": "",
518
+ class: "sr-only"
519
+ }, toDisplayString(stateText.value), 9, _hoisted_4)) : createCommentVNode("", true),
520
+ __props.clearable && hasSelection.value && !__props.disabled && !unref(isReadonly) ? (openBlock(), createElementBlock("button", {
521
+ key: 3,
497
522
  "data-testid": "gr-tree-select-clear",
498
523
  "data-gr-tree-select-clear": "",
499
524
  type: "button",
@@ -503,12 +528,12 @@ var GrTreeSelect_default = /* @__PURE__ */ defineComponent({
503
528
  }, [createVNode(unref(x_default), {
504
529
  class: "inline-block h-4 w-4",
505
530
  "aria-hidden": "true"
506
- })], 8, _hoisted_4)) : (openBlock(), createElementBlock("span", _hoisted_5, [createVNode(unref(chevron_down_default), {
531
+ })], 8, _hoisted_5)) : (openBlock(), createElementBlock("span", _hoisted_6, [createVNode(unref(chevron_down_default), {
507
532
  class: normalizeClass(["inline-block h-4 w-4 transition-transform duration-[var(--gr-duration-fast)]", unref(open) ? "rotate-180" : ""]),
508
533
  "aria-hidden": "true"
509
534
  }, null, 8, ["class"])])),
510
535
  unref(hasSuffix) ? (openBlock(), createElementBlock("div", {
511
- key: 3,
536
+ key: 5,
512
537
  ref_key: "suffixEl",
513
538
  ref: suffixEl,
514
539
  "data-gr-tree-select-suffix": "",
@@ -517,7 +542,7 @@ var GrTreeSelect_default = /* @__PURE__ */ defineComponent({
517
542
  "aria-hidden": "true"
518
543
  }, [renderSlot(_ctx.$slots, "suffix")], 6)) : createCommentVNode("", true),
519
544
  _ctx.$slots.value ? (openBlock(), createElementBlock("div", {
520
- key: 4,
545
+ key: 6,
521
546
  class: "absolute inset-y-0 left-3 right-9 flex items-center pointer-events-none",
522
547
  style: normalizeStyle(valueOverlayStyle.value)
523
548
  }, [renderSlot(_ctx.$slots, "value", {
@@ -547,7 +572,7 @@ var GrTreeSelect_default = /* @__PURE__ */ defineComponent({
547
572
  "data-gr-overlay-root": "",
548
573
  style: unref(floatingStyle),
549
574
  onKeydown: onPanelKeydown
550
- }), [createElementVNode("div", { class: normalizeClass(panelClasses.value) }, [__props.filterable ? (openBlock(), createElementBlock("div", _hoisted_6, [createVNode(GrInput_default, {
575
+ }), [createElementVNode("div", { class: normalizeClass(panelClasses.value) }, [__props.filterable ? (openBlock(), createElementBlock("div", _hoisted_7, [createVNode(GrInput_default, {
551
576
  ref_key: "filterInputRef",
552
577
  ref: filterInputRef,
553
578
  modelValue: filterValue.value,
@@ -601,10 +626,10 @@ var GrTreeSelect_default = /* @__PURE__ */ defineComponent({
601
626
  node,
602
627
  data,
603
628
  selected: selectedKeySet.value.has(node.key)
604
- }, () => [createElementVNode("div", _hoisted_7, [!checkboxMode.value ? (openBlock(), createElementBlock("span", _hoisted_8, [selectedKeySet.value.has(node.key) ? (openBlock(), createBlock(unref(check_default), {
629
+ }, () => [createElementVNode("div", _hoisted_8, [!checkboxMode.value ? (openBlock(), createElementBlock("span", _hoisted_9, [selectedKeySet.value.has(node.key) ? (openBlock(), createBlock(unref(check_default), {
605
630
  key: 0,
606
631
  class: "block h-4 w-4 text-[var(--gr-primary-text)]"
607
- })) : createCommentVNode("", true)])) : createCommentVNode("", true), createElementVNode("span", _hoisted_9, toDisplayString(node.label), 1)])])]),
632
+ })) : createCommentVNode("", true)])) : createCommentVNode("", true), createElementVNode("span", _hoisted_10, toDisplayString(node.label), 1)])])]),
608
633
  _: 3
609
634
  }, 8, [
610
635
  "size",
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrTreeSelect-B6KoDYiZ.js","names":["$slots"],"sources":["../../../../src/components/GrTreeSelect/GrTreeSelect.vue","../../../../src/components/GrTreeSelect/GrTreeSelect.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends Record<string, any> = any\">\nimport { computed, nextTick, ref, useId, useSlots, watch } from 'vue'\n\nimport { usePortalTarget } from '../../composables/usePortalTarget'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/useFloating'\nimport { useOverlayLayer } from '../../composables/useOverlayLayer'\nimport { useControlAddons } from '../../composables/internal/useControlAddons'\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useGrComponentSize, useGrThemeAttrs } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n controlSignalState,\n controlStateFallbackText,\n controlStateIconClass,\n controlStateIconColors,\n controlStateTextKey,\n} from '../shared/controlState'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrTree, {\n type GrTreeInstance,\n type GrTreeKey,\n type GrTreeNode,\n} from '../GrTree'\nimport type { GrInputSize } from '../GrInput/GrInput.vue'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport type { GrTreeSelectModelValue, GrTreeSelectProps } from './grTreeSelectTypes'\nimport { grTreeSelectClass, grTreeSelectPanelClass, grTreeSelectStateClass, paddingX, trailingZoneWidth } from './grTreeSelectStyles'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconChevronDown from '~icons/lucide/chevron-down'\nimport IconCheckCircle from '~icons/lucide/check-circle'\nimport IconAlertTriangle from '~icons/lucide/alert-triangle'\nimport IconLoaderCircle from '~icons/lucide/loader-circle'\nimport IconX from '~icons/lucide/x'\n\nexport interface GrTreeSelectEmits<T extends Record<string, any> = any> {\n (e: 'update:modelValue', value: GrTreeSelectModelValue): void\n (e: 'change', value: GrTreeSelectModelValue): void\n /** Панель открылась/закрылась (`v-model:open`). */\n (e: 'update:open', value: boolean): void\n (e: 'clear'): void\n (e: 'nodeClick', data: T, node: GrTreeNode<T>): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrTreeSelectProps<T>>(),\n {\n props: () => ({\n children: 'children',\n label: 'label',\n }),\n nodeKey: 'id' as any,\n defaultExpandedKeys: () => [],\n disabled: false,\n placeholder: undefined,\n size: undefined,\n loading: false,\n invalid: false,\n readonly: false,\n required: false,\n ariaLabel: undefined,\n state: 'default',\n multiple: false,\n showCheckbox: false,\n checkStrictly: false,\n clearable: false,\n open: undefined,\n name: undefined,\n valueDisplay: 'label',\n filterable: false,\n filterPlaceholder: undefined,\n filterInputmode: undefined,\n filterNodeMethod: undefined,\n closeOnSelect: undefined,\n dropdownMaxHeight: 320,\n virtual: false,\n prefixMinWidth: undefined,\n prefixMaxWidth: undefined,\n suffixMinWidth: undefined,\n suffixMaxWidth: undefined,\n prefixFixed: false,\n suffixFixed: false,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<GrTreeSelectEmits<T>>()\n\ndefineSlots<{\n /** Рендер значения внутри триггера (вместо дефолтного текста). */\n value?: (props: { value: GrTreeSelectModelValue, labels: string[], displayValue: string, pathLabels?: string[] }) => any\n /** Рендер строки дерева. */\n node?: (props: { node: GrTreeNode<T>, data: T, selected: boolean }) => any\n /** Содержимое пустого состояния (когда нет данных). */\n empty?: () => any\n /** Содержимое панели, пока данные едут. */\n loading?: () => any\n /** Аддон слева от значения: иконка, код валюты, метка. */\n prefix?: () => any\n /** Аддон справа от значения, перед крестиком и шевроном. */\n suffix?: () => any\n}>()\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst triggerEl = ref<HTMLInputElement | null>(null)\nconst treeId = `gr-tree-select-tree-${useId()}`\n\n// Контекст `GrFormField` + общий контракт форм-контрола.\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst stateTextId = useId()\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\n/**\n * Небуквенный признак состояния: иконка для глаз, скрытая подпись для\n * скринридера. Разбор — `shared/controlState`. Встаёт левее крестика и\n * шеврона: правый край триггера занят одним из них всегда.\n */\nconst signalState = computed(() => controlSignalState(props.state, isInvalid.value))\nconst stateIcon = computed(() => (signalState.value === 'success' ? IconCheckCircle : IconAlertTriangle))\nconst stateIconClass = computed(() => (signalState.value\n ? `${controlStateIconClass} ${controlStateIconColors[signalState.value]}`\n : ''))\nconst stateText = computed(() => (signalState.value\n ? t(controlStateTextKey[signalState.value], controlStateFallbackText[signalState.value])\n : ''))\n\nconst describedBy = computed(() =>\n [field?.describedById.value, signalState.value ? stateTextId : undefined]\n .filter(Boolean)\n .join(' ') || undefined,\n)\n\nfunction focus(): void {\n triggerEl.value?.focus()\n}\n\nfunction blur(): void {\n triggerEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\nconst filterInputRef = ref<InstanceType<typeof GrInput> | null>(null)\nconst treeRef = ref<GrTreeInstance | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\n\n// Панель телепортирована в `body`, то есть лежит вне корня, но для пользователя\n// она часть контрола: без неё уход фокуса в панель читался бы как `blur`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n containers: () => [panelEl.value],\n})\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hadPointerDownOnTrigger = false\n\n// Имя `open` сохранено: читатели работают с computed-Ref.\nconst { open, setOpen: setOpenState } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\nconst filterValue = ref('')\n\nconst { floatingStyle } = useFloating(rootEl, panelEl, open, {\n placement: 'bottom-start',\n matchWidth: true,\n zIndexVar: '--gr-z-dropdown',\n})\n\nconst closeOnSelectResolved = computed(() => {\n return props.closeOnSelect ?? !props.multiple\n})\n\nfunction getChildrenKey() {\n return props.props.children ?? 'children'\n}\n\nfunction getLabelKey() {\n return props.props.label ?? 'label'\n}\n\nfunction nodeLabel(data: T): string {\n const key = getLabelKey() as keyof T\n const v = data[key]\n return v == null ? '' : String(v)\n}\n\nfunction nodeChildren(data: T): T[] {\n const key = getChildrenKey() as keyof T\n const v = data[key]\n return Array.isArray(v) ? (v as any) : []\n}\n\nfunction nodeKeyOf(data: T, index: number, parentKey: GrTreeKey | undefined): GrTreeKey {\n const keyName = props.nodeKey as keyof T\n const v = data[keyName]\n if (v != null)\n return v as GrTreeKey\n\n return parentKey == null ? index : `${String(parentKey)}:${index}`\n}\n\nconst labelByKey = computed(() => {\n const map = new Map<GrTreeKey, string>()\n\n const walk = (items: T[], parentKey: GrTreeKey | undefined) => {\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n const key = nodeKeyOf(item, i, parentKey)\n map.set(key, nodeLabel(item))\n walk(nodeChildren(item), key)\n }\n }\n\n walk(props.data ?? [], undefined)\n return map\n})\n\nconst pathLabelsByKey = computed(() => {\n const map = new Map<GrTreeKey, string[]>()\n\n const walk = (items: T[], parentKey: GrTreeKey | undefined, parentPath: string[]) => {\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n const key = nodeKeyOf(item, i, parentKey)\n const label = nodeLabel(item)\n const path = [...parentPath, label]\n map.set(key, path)\n walk(nodeChildren(item), key, path)\n }\n }\n\n walk(props.data ?? [], undefined, [])\n return map\n})\n\nconst selectedKeys = computed<GrTreeKey[]>(() => {\n if (props.multiple) {\n return Array.isArray(props.modelValue) ? props.modelValue : []\n }\n\n const v = props.modelValue\n if (v == null || Array.isArray(v))\n return []\n return [v]\n})\n\nconst selectedKeySet = computed(() => new Set(selectedKeys.value))\n\nconst selectedLabels = computed(() => {\n const map = labelByKey.value\n return selectedKeys.value.map(k => map.get(k) ?? String(k))\n})\n\nconst selectedPathLabels = computed<string[] | undefined>(() => {\n if (props.multiple)\n return undefined\n\n const key = selectedKeys.value[0]\n if (key == null)\n return undefined\n\n const path = pathLabelsByKey.value.get(key)\n if (path?.length)\n return path\n\n const labels = selectedLabels.value\n return labels.length ? [labels[0]] : undefined\n})\n\nconst displayValue = computed(() => {\n const labels = selectedLabels.value\n if (labels.length === 0)\n return ''\n\n if (!props.multiple) {\n if (props.valueDisplay === 'path') {\n const path = selectedPathLabels.value\n if (path?.length)\n return path.join(' / ')\n }\n return labels[0]\n }\n\n if (labels.length === 1)\n return labels[0]\n return `${labels[0]} +${labels.length - 1}`\n})\n\nconst hasSelection = computed(() => selectedKeys.value.length > 0)\n\n/** Дерево рендерится только когда есть что показать — ссылаться иначе не на что. */\nconst hasTree = computed(() => !props.loading && (props.data?.length ?? 0) > 0)\n\nconst resolvedFilterPlaceholder = computed(() => {\n return props.filterPlaceholder ?? t('gr.treeSelect.filterPlaceholder', 'Search…')\n})\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTreeSelect' })\n\nconst className = computed(() => {\n return grTreeSelectClass({\n size: resolvedSize.value,\n state: props.state,\n invalid: isInvalid.value,\n disabled: isDisabled.value,\n })\n})\n\nconst panelClasses = computed(() => {\n return grTreeSelectPanelClass\n})\n\nconst ADDON_MIN_WIDTH_BY_SIZE: Record<GrInputSize, string> = {\n xs: '2rem',\n sm: '2.25rem',\n md: '2.5rem',\n lg: '3rem',\n}\n\nconst slots = useSlots()\n\nconst {\n hasPrefix,\n hasSuffix,\n prefixEl,\n suffixEl,\n prefixStyle,\n suffixStyle,\n fieldPadding: triggerStyle,\n} = useControlAddons(() => props, {\n defaultMinWidth: () => ADDON_MIN_WIDTH_BY_SIZE[resolvedSize.value],\n paddingX: () => paddingX[resolvedSize.value],\n // Место под крестик и шеврон уже отдано классом `pr-9`, но инлайн-паддинг\n // перекрывает класс целиком — с суффиксом эту зону приходится вернуть числом.\n trailingReserve: () => (slots.suffix ? trailingZoneWidth : '0px'),\n})\n\n// Слот `value` рисуется поверх поля и обязан жить в тех же границах, что и\n// текст под ним. Без аддонов границы задаёт класс — стиль остаётся пустым.\nconst valueOverlayStyle = computed(() => ({\n left: hasPrefix.value ? triggerStyle.value.paddingLeft : undefined,\n right: hasSuffix.value ? triggerStyle.value.paddingRight : undefined,\n}))\n\nfunction setOpen(next: boolean) {\n if (isDisabled.value || isReadonly.value)\n return\n\n setOpenState(next)\n}\n\nfunction onClickOutside(): void {\n setOpen(false)\n}\n\nfunction openDropdown(): void {\n setOpen(true)\n}\n\n/**\n * Стек слоёв возвращает фокус на триггер сразу после закрытия, а у триггера\n * открытие висит на `focus`. Без флага `Escape` из дерева закрывал бы панель и\n * тем же движением открывал её заново.\n */\nlet suppressFocusOpen = false\n\nfunction closeDropdown(): void {\n suppressFocusOpen = true\n setOpen(false)\n setTimeout(() => {\n suppressFocusOpen = false\n }, 0)\n}\n\nfunction toggleDropdown(): void {\n setOpen(!open.value)\n}\n\n// Клик по триггеру сам переключает панель через `@click`; флаг гасит открытие\n// по приходящему следом `focus`, иначе один клик открыл бы и тут же закрыл.\nfunction onTriggerPointerDown(): void {\n hadPointerDownOnTrigger = true\n setTimeout(() => {\n hadPointerDownOnTrigger = false\n }, 0)\n}\n\nfunction onTriggerFocus(): void {\n if (hadPointerDownOnTrigger || suppressFocusOpen)\n return\n openDropdown()\n}\n\n// Возврат фокуса на триггер — из контракта слоя, а не руками через `nextTick`.\nuseOverlayLayer(open, closeDropdown, { root: panelEl })\n\nwatch(\n open,\n async (isOpen) => {\n if (!isOpen) {\n if (filterValue.value.trim().length > 0)\n filterValue.value = ''\n return\n }\n\n // Подсветка дерева идёт за значением: панель могли открыть после того, как\n // значение сменили снаружи.\n if (!props.multiple) {\n const v = props.modelValue\n if (v != null && !Array.isArray(v))\n treeRef.value?.setCurrentKey(v)\n }\n\n if (props.filterable) {\n await nextTick()\n filterInputRef.value?.focus()\n }\n },\n { immediate: true },\n)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (props.multiple)\n return\n if (v == null || Array.isArray(v)) {\n treeRef.value?.setCurrentKey(undefined)\n return\n }\n treeRef.value?.setCurrentKey(v)\n },\n)\n\nwatch(\n filterValue,\n (v) => {\n treeRef.value?.filter(v)\n },\n)\n\nfunction emitModel(next: GrTreeSelectModelValue) {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction clear(): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n const next: GrTreeSelectModelValue = props.multiple ? [] : null\n emitModel(next)\n emit('clear')\n if (!props.multiple)\n treeRef.value?.setCurrentKey(undefined)\n}\n\n/**\n * Отдаёт клавиатуру дереву. Панель под `v-show`, поэтому дерево уже в DOM, но\n * скрытый элемент сфокусировать нельзя — сначала открытие, потом кадр, потом\n * фокус. Дальше работают клавиши `GrTree`, а `Escape` возвращает фокус на\n * триггер силами общего стека слоёв.\n */\nasync function focusTree(): Promise<boolean> {\n if (!open.value)\n return false\n\n await nextTick()\n return treeRef.value?.focus() ?? false\n}\n\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (isDisabled.value)\n return\n\n if (e.key === 'Escape') {\n e.preventDefault()\n closeDropdown()\n return\n }\n\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDropdown()\n\n // При `filterable` фокус уходит в поле поиска (см. watch на `open`), и\n // дальше в дерево ведёт стрелка уже оттуда.\n if (!props.filterable)\n void focusTree()\n }\n}\n\n/** Стрелка из поля поиска — единственный путь из фильтра в дерево. */\nfunction onFilterKeydown(e: KeyboardEvent): void {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp')\n return\n\n e.preventDefault()\n void focusTree()\n}\n\n/** `Tab` уводит из панели — оставлять её открытой за спиной незачем. */\nfunction onPanelKeydown(e: KeyboardEvent): void {\n if (e.key === 'Tab')\n closeDropdown()\n}\n\n// Чекбоксы осмысленны только в множественном выборе: одиночный уже подсвечен\n// текущим узлом.\nconst checkboxMode = computed(() => props.multiple && props.showCheckbox)\n\n// В режиме чекбоксов каскад по родителям и детям считает `GrTree`, а не копия\n// его логики здесь: значение приходит обратно одним `update:checkedKeys`.\nfunction onCheckedKeys(keys: GrTreeKey[]): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n emitModel([...keys])\n}\n\nfunction onNodeClick(data: T, node: GrTreeNode<T>): void {\n emit('nodeClick', data, node)\n\n if (isDisabled.value)\n return\n\n if (checkboxMode.value) {\n // Клик по строке — тот же переключатель отметки, что и сам чекбокс;\n // значение придёт через `update:checkedKeys`, поэтому здесь не эмитим.\n treeRef.value?.setChecked(node.key, !selectedKeySet.value.has(node.key))\n return\n }\n\n if (props.multiple) {\n const next = new Set(selectedKeySet.value)\n if (next.has(node.key))\n next.delete(node.key)\n else\n next.add(node.key)\n emitModel([...next])\n\n if (closeOnSelectResolved.value) {\n closeDropdown()\n }\n return\n }\n\n emitModel(node.key)\n if (closeOnSelectResolved.value) {\n closeDropdown()\n }\n}\n\n// Телепорт включается только ПОСЛЕ монтирования: иначе первый клиентский\n// рендер не совпадает с серверным и ломается гидрация (см. композабл).\nconst { target: portalTarget, enabled: teleportEnabled } = usePortalTarget()\n\n// Тема поддерева на телепортированную панель: в DOM она уезжает в `body`, то\n// есть вне обёртки провайдера, и `data-theme` с неё не наследуется. В дереве\n// компонентов панель остаётся внутри — `inject` доходит, и тему она ставит себе\n// сама.\nconst themeAttrs = useGrThemeAttrs()\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n v-click-outside=\"{ handler: onClickOutside, enabled: open, exclude: clickOutsideExclude }\"\n data-gr-tree-select\n class=\"relative\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <!-- Нативная форма: hidden на каждый выбранный ключ. -->\n <template v-if=\"name\">\n <input\n v-for=\"key in selectedKeys\"\n :key=\"`hidden-${String(key)}`\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(key)\"\n >\n </template>\n <div class=\"relative\">\n <div\n v-if=\"hasPrefix\"\n ref=\"prefixEl\"\n data-gr-tree-select-prefix\n class=\"absolute inset-y-px left-px flex items-center justify-center rounded-l-[var(--gr-radius-control)] border-r border-[var(--gr-brd)] px-2 text-[var(--gr-muted-fg)] pointer-events-none select-none truncate\"\n :style=\"prefixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"prefix\" />\n </div>\n\n <input\n :id=\"fieldId\"\n ref=\"triggerEl\"\n data-testid=\"gr-tree-select-trigger\"\n data-gr-tree-select-trigger\n type=\"text\"\n :value=\"displayValue\"\n :placeholder=\"placeholder\"\n :disabled=\"isDisabled\"\n readonly\n role=\"combobox\"\n aria-readonly=\"true\"\n aria-haspopup=\"tree\"\n :aria-expanded=\"open ? 'true' : 'false'\"\n :aria-controls=\"open && hasTree ? treeId : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-label=\"ariaLabel\"\n class=\"w-full rounded-[var(--gr-radius-control)] border placeholder:text-[var(--gr-muted-fg)] transition-colors duration-[var(--gr-duration-fast)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :class=\"[className, $slots.value ? 'text-transparent placeholder:text-transparent' : '']\"\n :style=\"triggerStyle\"\n @pointerdown=\"onTriggerPointerDown\"\n @click=\"toggleDropdown\"\n @focus=\"onTriggerFocus\"\n @keydown=\"onTriggerKeydown\"\n >\n\n <span\n v-if=\"signalState\"\n data-gr-tree-select-state\n class=\"absolute top-1/2 -translate-y-1/2 right-9\"\n :class=\"stateIconClass\"\n aria-hidden=\"true\"\n >\n <component :is=\"stateIcon\" class=\"h-4 w-4\" />\n </span>\n\n <span v-if=\"signalState\" :id=\"stateTextId\" data-gr-tree-select-state-text class=\"sr-only\">{{ stateText }}</span>\n\n <button\n v-if=\"clearable && hasSelection && !disabled && !isReadonly\"\n data-testid=\"gr-tree-select-clear\"\n data-gr-tree-select-clear\n type=\"button\"\n class=\"absolute top-1/2 -translate-y-1/2 right-3 h-6 w-6 inline-flex items-center justify-center rounded-[var(--gr-radius-control)] text-[var(--gr-muted-fg)] hover:text-[var(--gr-fg)] hover:bg-[color-mix(in_srgb,var(--gr-muted)_25%,transparent)]\"\n :aria-label=\"t('gr.common.clear', 'Clear')\"\n @click.stop=\"clear\"\n >\n <IconX class=\"inline-block h-4 w-4\" aria-hidden=\"true\" />\n </button>\n\n <span\n v-else\n data-testid=\"gr-tree-select-chevron\"\n data-gr-tree-select-chevron\n class=\"absolute top-1/2 -translate-y-1/2 right-3 text-[var(--gr-muted-fg)] pointer-events-none\"\n >\n <IconChevronDown\n class=\"inline-block h-4 w-4 transition-transform duration-[var(--gr-duration-fast)]\"\n :class=\"open ? 'rotate-180' : ''\"\n aria-hidden=\"true\"\n />\n </span>\n\n <div\n v-if=\"hasSuffix\"\n ref=\"suffixEl\"\n data-gr-tree-select-suffix\n class=\"absolute inset-y-px right-9 flex items-center justify-center border-l border-[var(--gr-brd)] px-2 text-[var(--gr-muted-fg)] pointer-events-none select-none truncate\"\n :class=\"suffixFixed ? '[direction:rtl]' : ''\"\n :style=\"suffixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"suffix\" />\n </div>\n\n <div\n v-if=\"$slots.value\"\n class=\"absolute inset-y-0 left-3 right-9 flex items-center pointer-events-none\"\n :style=\"valueOverlayStyle\"\n >\n <slot\n name=\"value\"\n :value=\"modelValue\"\n :labels=\"selectedLabels\"\n :display-value=\"displayValue\"\n :path-labels=\"selectedPathLabels\"\n />\n </div>\n </div>\n\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <transition\n :enter-active-class=\"panelPopTransition.enter\"\n :enter-from-class=\"panelPopTransition.enterFrom\"\n :enter-to-class=\"panelPopTransition.enterTo\"\n :leave-active-class=\"panelPopTransition.leave\"\n :leave-from-class=\"panelPopTransition.leaveFrom\"\n :leave-to-class=\"panelPopTransition.leaveTo\"\n >\n <div\n v-show=\"open\"\n ref=\"panelEl\"\n data-testid=\"gr-tree-select-panel\"\n v-bind=\"themeAttrs\"\n data-gr-tree-select-panel\n data-gr-overlay-root\n :style=\"floatingStyle\"\n @keydown=\"onPanelKeydown\"\n >\n <div :class=\"panelClasses\">\n <div v-if=\"filterable\" class=\"p-2 border-b border-[var(--gr-brd)]\">\n <GrInput\n ref=\"filterInputRef\"\n v-model=\"filterValue\"\n data-testid=\"gr-tree-select-filter\"\n data-gr-tree-select-filter\n type=\"search\"\n :inputmode=\"filterInputmode\"\n :placeholder=\"resolvedFilterPlaceholder\"\n size=\"sm\"\n @keydown=\"onFilterKeydown\"\n />\n </div>\n\n <!--\n Скроллер один. При виртуализации его берёт на себя дерево: своя\n высота нужна ему, чтобы посчитать окно, а вложенный скроллер поверх\n дал бы вторую полосу прокрутки на том же списке.\n -->\n <div\n class=\"p-1\"\n :class=\"virtual ? '' : 'overflow-auto'\"\n :style=\"virtual ? undefined : { maxHeight: `${dropdownMaxHeight}px` }\"\n >\n <div\n v-if=\"loading\"\n data-gr-tree-select-loading\n role=\"status\"\n :class=\"grTreeSelectStateClass\"\n >\n <slot name=\"loading\">\n <IconLoaderCircle class=\"block h-4 w-4 animate-spin\" aria-hidden=\"true\" />\n <span>{{ t('gr.treeSelect.loading', 'Loading…') }}</span>\n </slot>\n </div>\n\n <div v-else-if=\"(data?.length ?? 0) === 0\" :class=\"grTreeSelectStateClass\">\n <slot name=\"empty\">\n {{ t('gr.treeSelect.empty', 'No data') }}\n </slot>\n </div>\n\n <GrTree\n v-else\n :id=\"treeId\"\n ref=\"treeRef\"\n :size=\"resolvedSize\"\n :data=\"data\"\n :props=\"props.props\"\n :node-key=\"nodeKey as any\"\n :default-expanded-keys=\"defaultExpandedKeys\"\n :filter-node-method=\"filterNodeMethod\"\n :highlight-current=\"!multiple\"\n :virtual=\"virtual\"\n :max-height=\"dropdownMaxHeight\"\n :show-checkbox=\"checkboxMode\"\n :check-strictly=\"checkStrictly\"\n :checked-keys=\"selectedKeys\"\n @node-click=\"onNodeClick\"\n @update:checked-keys=\"onCheckedKeys\"\n >\n <template #default=\"{ node, data }\">\n <slot\n name=\"node\"\n :node=\"node\"\n :data=\"data\"\n :selected=\"selectedKeySet.has(node.key)\"\n >\n <div class=\"flex items-center gap-2 min-w-0\">\n <!-- Чекбокс дерева уже показывает отметку: вторая галочка\n рядом читалась бы как ошибка. -->\n <span\n v-if=\"!checkboxMode\"\n data-gr-tree-select-check\n class=\"inline-block h-4 w-4 shrink-0\"\n aria-hidden=\"true\"\n >\n <IconCheck v-if=\"selectedKeySet.has(node.key)\" class=\"block h-4 w-4 text-[var(--gr-primary-text)]\" />\n </span>\n <span class=\"truncate\">{{ node.label }}</span>\n </div>\n </slot>\n </template>\n </GrTree>\n </div>\n </div>\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n","<script setup lang=\"ts\" generic=\"T extends Record<string, any> = any\">\nimport { computed, nextTick, ref, useId, useSlots, watch } from 'vue'\n\nimport { usePortalTarget } from '../../composables/usePortalTarget'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/useFloating'\nimport { useOverlayLayer } from '../../composables/useOverlayLayer'\nimport { useControlAddons } from '../../composables/internal/useControlAddons'\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useGrComponentSize, useGrThemeAttrs } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n controlSignalState,\n controlStateFallbackText,\n controlStateIconClass,\n controlStateIconColors,\n controlStateTextKey,\n} from '../shared/controlState'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrTree, {\n type GrTreeInstance,\n type GrTreeKey,\n type GrTreeNode,\n} from '../GrTree'\nimport type { GrInputSize } from '../GrInput/GrInput.vue'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport type { GrTreeSelectModelValue, GrTreeSelectProps } from './grTreeSelectTypes'\nimport { grTreeSelectClass, grTreeSelectPanelClass, grTreeSelectStateClass, paddingX, trailingZoneWidth } from './grTreeSelectStyles'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconChevronDown from '~icons/lucide/chevron-down'\nimport IconCheckCircle from '~icons/lucide/check-circle'\nimport IconAlertTriangle from '~icons/lucide/alert-triangle'\nimport IconLoaderCircle from '~icons/lucide/loader-circle'\nimport IconX from '~icons/lucide/x'\n\nexport interface GrTreeSelectEmits<T extends Record<string, any> = any> {\n (e: 'update:modelValue', value: GrTreeSelectModelValue): void\n (e: 'change', value: GrTreeSelectModelValue): void\n /** Панель открылась/закрылась (`v-model:open`). */\n (e: 'update:open', value: boolean): void\n (e: 'clear'): void\n (e: 'nodeClick', data: T, node: GrTreeNode<T>): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrTreeSelectProps<T>>(),\n {\n props: () => ({\n children: 'children',\n label: 'label',\n }),\n nodeKey: 'id' as any,\n defaultExpandedKeys: () => [],\n disabled: false,\n placeholder: undefined,\n size: undefined,\n loading: false,\n invalid: false,\n readonly: false,\n required: false,\n ariaLabel: undefined,\n state: 'default',\n multiple: false,\n showCheckbox: false,\n checkStrictly: false,\n clearable: false,\n open: undefined,\n name: undefined,\n valueDisplay: 'label',\n filterable: false,\n filterPlaceholder: undefined,\n filterInputmode: undefined,\n filterNodeMethod: undefined,\n closeOnSelect: undefined,\n dropdownMaxHeight: 320,\n virtual: false,\n prefixMinWidth: undefined,\n prefixMaxWidth: undefined,\n suffixMinWidth: undefined,\n suffixMaxWidth: undefined,\n prefixFixed: false,\n suffixFixed: false,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<GrTreeSelectEmits<T>>()\n\ndefineSlots<{\n /** Рендер значения внутри триггера (вместо дефолтного текста). */\n value?: (props: { value: GrTreeSelectModelValue, labels: string[], displayValue: string, pathLabels?: string[] }) => any\n /** Рендер строки дерева. */\n node?: (props: { node: GrTreeNode<T>, data: T, selected: boolean }) => any\n /** Содержимое пустого состояния (когда нет данных). */\n empty?: () => any\n /** Содержимое панели, пока данные едут. */\n loading?: () => any\n /** Аддон слева от значения: иконка, код валюты, метка. */\n prefix?: () => any\n /** Аддон справа от значения, перед крестиком и шевроном. */\n suffix?: () => any\n}>()\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst triggerEl = ref<HTMLInputElement | null>(null)\nconst treeId = `gr-tree-select-tree-${useId()}`\n\n// Контекст `GrFormField` + общий контракт форм-контрола.\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst stateTextId = useId()\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\n/**\n * Небуквенный признак состояния: иконка для глаз, скрытая подпись для\n * скринридера. Разбор — `shared/controlState`. Встаёт левее крестика и\n * шеврона: правый край триггера занят одним из них всегда.\n */\nconst signalState = computed(() => controlSignalState(props.state, isInvalid.value))\nconst stateIcon = computed(() => (signalState.value === 'success' ? IconCheckCircle : IconAlertTriangle))\nconst stateIconClass = computed(() => (signalState.value\n ? `${controlStateIconClass} ${controlStateIconColors[signalState.value]}`\n : ''))\nconst stateText = computed(() => (signalState.value\n ? t(controlStateTextKey[signalState.value], controlStateFallbackText[signalState.value])\n : ''))\n\nconst describedBy = computed(() =>\n [field?.describedById.value, signalState.value ? stateTextId : undefined]\n .filter(Boolean)\n .join(' ') || undefined,\n)\n\nfunction focus(): void {\n triggerEl.value?.focus()\n}\n\nfunction blur(): void {\n triggerEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\nconst filterInputRef = ref<InstanceType<typeof GrInput> | null>(null)\nconst treeRef = ref<GrTreeInstance | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\n\n// Панель телепортирована в `body`, то есть лежит вне корня, но для пользователя\n// она часть контрола: без неё уход фокуса в панель читался бы как `blur`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n containers: () => [panelEl.value],\n})\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hadPointerDownOnTrigger = false\n\n// Имя `open` сохранено: читатели работают с computed-Ref.\nconst { open, setOpen: setOpenState } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\nconst filterValue = ref('')\n\nconst { floatingStyle } = useFloating(rootEl, panelEl, open, {\n placement: 'bottom-start',\n matchWidth: true,\n zIndexVar: '--gr-z-dropdown',\n})\n\nconst closeOnSelectResolved = computed(() => {\n return props.closeOnSelect ?? !props.multiple\n})\n\nfunction getChildrenKey() {\n return props.props.children ?? 'children'\n}\n\nfunction getLabelKey() {\n return props.props.label ?? 'label'\n}\n\nfunction nodeLabel(data: T): string {\n const key = getLabelKey() as keyof T\n const v = data[key]\n return v == null ? '' : String(v)\n}\n\nfunction nodeChildren(data: T): T[] {\n const key = getChildrenKey() as keyof T\n const v = data[key]\n return Array.isArray(v) ? (v as any) : []\n}\n\nfunction nodeKeyOf(data: T, index: number, parentKey: GrTreeKey | undefined): GrTreeKey {\n const keyName = props.nodeKey as keyof T\n const v = data[keyName]\n if (v != null)\n return v as GrTreeKey\n\n return parentKey == null ? index : `${String(parentKey)}:${index}`\n}\n\nconst labelByKey = computed(() => {\n const map = new Map<GrTreeKey, string>()\n\n const walk = (items: T[], parentKey: GrTreeKey | undefined) => {\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n const key = nodeKeyOf(item, i, parentKey)\n map.set(key, nodeLabel(item))\n walk(nodeChildren(item), key)\n }\n }\n\n walk(props.data ?? [], undefined)\n return map\n})\n\nconst pathLabelsByKey = computed(() => {\n const map = new Map<GrTreeKey, string[]>()\n\n const walk = (items: T[], parentKey: GrTreeKey | undefined, parentPath: string[]) => {\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n const key = nodeKeyOf(item, i, parentKey)\n const label = nodeLabel(item)\n const path = [...parentPath, label]\n map.set(key, path)\n walk(nodeChildren(item), key, path)\n }\n }\n\n walk(props.data ?? [], undefined, [])\n return map\n})\n\nconst selectedKeys = computed<GrTreeKey[]>(() => {\n if (props.multiple) {\n return Array.isArray(props.modelValue) ? props.modelValue : []\n }\n\n const v = props.modelValue\n if (v == null || Array.isArray(v))\n return []\n return [v]\n})\n\nconst selectedKeySet = computed(() => new Set(selectedKeys.value))\n\nconst selectedLabels = computed(() => {\n const map = labelByKey.value\n return selectedKeys.value.map(k => map.get(k) ?? String(k))\n})\n\nconst selectedPathLabels = computed<string[] | undefined>(() => {\n if (props.multiple)\n return undefined\n\n const key = selectedKeys.value[0]\n if (key == null)\n return undefined\n\n const path = pathLabelsByKey.value.get(key)\n if (path?.length)\n return path\n\n const labels = selectedLabels.value\n return labels.length ? [labels[0]] : undefined\n})\n\nconst displayValue = computed(() => {\n const labels = selectedLabels.value\n if (labels.length === 0)\n return ''\n\n if (!props.multiple) {\n if (props.valueDisplay === 'path') {\n const path = selectedPathLabels.value\n if (path?.length)\n return path.join(' / ')\n }\n return labels[0]\n }\n\n if (labels.length === 1)\n return labels[0]\n return `${labels[0]} +${labels.length - 1}`\n})\n\nconst hasSelection = computed(() => selectedKeys.value.length > 0)\n\n/** Дерево рендерится только когда есть что показать — ссылаться иначе не на что. */\nconst hasTree = computed(() => !props.loading && (props.data?.length ?? 0) > 0)\n\nconst resolvedFilterPlaceholder = computed(() => {\n return props.filterPlaceholder ?? t('gr.treeSelect.filterPlaceholder', 'Search…')\n})\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTreeSelect' })\n\nconst className = computed(() => {\n return grTreeSelectClass({\n size: resolvedSize.value,\n state: props.state,\n invalid: isInvalid.value,\n disabled: isDisabled.value,\n })\n})\n\nconst panelClasses = computed(() => {\n return grTreeSelectPanelClass\n})\n\nconst ADDON_MIN_WIDTH_BY_SIZE: Record<GrInputSize, string> = {\n xs: '2rem',\n sm: '2.25rem',\n md: '2.5rem',\n lg: '3rem',\n}\n\nconst slots = useSlots()\n\nconst {\n hasPrefix,\n hasSuffix,\n prefixEl,\n suffixEl,\n prefixStyle,\n suffixStyle,\n fieldPadding: triggerStyle,\n} = useControlAddons(() => props, {\n defaultMinWidth: () => ADDON_MIN_WIDTH_BY_SIZE[resolvedSize.value],\n paddingX: () => paddingX[resolvedSize.value],\n // Место под крестик и шеврон уже отдано классом `pr-9`, но инлайн-паддинг\n // перекрывает класс целиком — с суффиксом эту зону приходится вернуть числом.\n trailingReserve: () => (slots.suffix ? trailingZoneWidth : '0px'),\n})\n\n// Слот `value` рисуется поверх поля и обязан жить в тех же границах, что и\n// текст под ним. Без аддонов границы задаёт класс — стиль остаётся пустым.\nconst valueOverlayStyle = computed(() => ({\n left: hasPrefix.value ? triggerStyle.value.paddingLeft : undefined,\n right: hasSuffix.value ? triggerStyle.value.paddingRight : undefined,\n}))\n\nfunction setOpen(next: boolean) {\n if (isDisabled.value || isReadonly.value)\n return\n\n setOpenState(next)\n}\n\nfunction onClickOutside(): void {\n setOpen(false)\n}\n\nfunction openDropdown(): void {\n setOpen(true)\n}\n\n/**\n * Стек слоёв возвращает фокус на триггер сразу после закрытия, а у триггера\n * открытие висит на `focus`. Без флага `Escape` из дерева закрывал бы панель и\n * тем же движением открывал её заново.\n */\nlet suppressFocusOpen = false\n\nfunction closeDropdown(): void {\n suppressFocusOpen = true\n setOpen(false)\n setTimeout(() => {\n suppressFocusOpen = false\n }, 0)\n}\n\nfunction toggleDropdown(): void {\n setOpen(!open.value)\n}\n\n// Клик по триггеру сам переключает панель через `@click`; флаг гасит открытие\n// по приходящему следом `focus`, иначе один клик открыл бы и тут же закрыл.\nfunction onTriggerPointerDown(): void {\n hadPointerDownOnTrigger = true\n setTimeout(() => {\n hadPointerDownOnTrigger = false\n }, 0)\n}\n\nfunction onTriggerFocus(): void {\n if (hadPointerDownOnTrigger || suppressFocusOpen)\n return\n openDropdown()\n}\n\n// Возврат фокуса на триггер — из контракта слоя, а не руками через `nextTick`.\nuseOverlayLayer(open, closeDropdown, { root: panelEl })\n\nwatch(\n open,\n async (isOpen) => {\n if (!isOpen) {\n if (filterValue.value.trim().length > 0)\n filterValue.value = ''\n return\n }\n\n // Подсветка дерева идёт за значением: панель могли открыть после того, как\n // значение сменили снаружи.\n if (!props.multiple) {\n const v = props.modelValue\n if (v != null && !Array.isArray(v))\n treeRef.value?.setCurrentKey(v)\n }\n\n if (props.filterable) {\n await nextTick()\n filterInputRef.value?.focus()\n }\n },\n { immediate: true },\n)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (props.multiple)\n return\n if (v == null || Array.isArray(v)) {\n treeRef.value?.setCurrentKey(undefined)\n return\n }\n treeRef.value?.setCurrentKey(v)\n },\n)\n\nwatch(\n filterValue,\n (v) => {\n treeRef.value?.filter(v)\n },\n)\n\nfunction emitModel(next: GrTreeSelectModelValue) {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction clear(): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n const next: GrTreeSelectModelValue = props.multiple ? [] : null\n emitModel(next)\n emit('clear')\n if (!props.multiple)\n treeRef.value?.setCurrentKey(undefined)\n}\n\n/**\n * Отдаёт клавиатуру дереву. Панель под `v-show`, поэтому дерево уже в DOM, но\n * скрытый элемент сфокусировать нельзя — сначала открытие, потом кадр, потом\n * фокус. Дальше работают клавиши `GrTree`, а `Escape` возвращает фокус на\n * триггер силами общего стека слоёв.\n */\nasync function focusTree(): Promise<boolean> {\n if (!open.value)\n return false\n\n await nextTick()\n return treeRef.value?.focus() ?? false\n}\n\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (isDisabled.value)\n return\n\n if (e.key === 'Escape') {\n e.preventDefault()\n closeDropdown()\n return\n }\n\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDropdown()\n\n // При `filterable` фокус уходит в поле поиска (см. watch на `open`), и\n // дальше в дерево ведёт стрелка уже оттуда.\n if (!props.filterable)\n void focusTree()\n }\n}\n\n/** Стрелка из поля поиска — единственный путь из фильтра в дерево. */\nfunction onFilterKeydown(e: KeyboardEvent): void {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp')\n return\n\n e.preventDefault()\n void focusTree()\n}\n\n/** `Tab` уводит из панели — оставлять её открытой за спиной незачем. */\nfunction onPanelKeydown(e: KeyboardEvent): void {\n if (e.key === 'Tab')\n closeDropdown()\n}\n\n// Чекбоксы осмысленны только в множественном выборе: одиночный уже подсвечен\n// текущим узлом.\nconst checkboxMode = computed(() => props.multiple && props.showCheckbox)\n\n// В режиме чекбоксов каскад по родителям и детям считает `GrTree`, а не копия\n// его логики здесь: значение приходит обратно одним `update:checkedKeys`.\nfunction onCheckedKeys(keys: GrTreeKey[]): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n emitModel([...keys])\n}\n\nfunction onNodeClick(data: T, node: GrTreeNode<T>): void {\n emit('nodeClick', data, node)\n\n if (isDisabled.value)\n return\n\n if (checkboxMode.value) {\n // Клик по строке — тот же переключатель отметки, что и сам чекбокс;\n // значение придёт через `update:checkedKeys`, поэтому здесь не эмитим.\n treeRef.value?.setChecked(node.key, !selectedKeySet.value.has(node.key))\n return\n }\n\n if (props.multiple) {\n const next = new Set(selectedKeySet.value)\n if (next.has(node.key))\n next.delete(node.key)\n else\n next.add(node.key)\n emitModel([...next])\n\n if (closeOnSelectResolved.value) {\n closeDropdown()\n }\n return\n }\n\n emitModel(node.key)\n if (closeOnSelectResolved.value) {\n closeDropdown()\n }\n}\n\n// Телепорт включается только ПОСЛЕ монтирования: иначе первый клиентский\n// рендер не совпадает с серверным и ломается гидрация (см. композабл).\nconst { target: portalTarget, enabled: teleportEnabled } = usePortalTarget()\n\n// Тема поддерева на телепортированную панель: в DOM она уезжает в `body`, то\n// есть вне обёртки провайдера, и `data-theme` с неё не наследуется. В дереве\n// компонентов панель остаётся внутри — `inject` доходит, и тему она ставит себе\n// сама.\nconst themeAttrs = useGrThemeAttrs()\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n v-click-outside=\"{ handler: onClickOutside, enabled: open, exclude: clickOutsideExclude }\"\n data-gr-tree-select\n class=\"relative\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <!-- Нативная форма: hidden на каждый выбранный ключ. -->\n <template v-if=\"name\">\n <input\n v-for=\"key in selectedKeys\"\n :key=\"`hidden-${String(key)}`\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(key)\"\n >\n </template>\n <div class=\"relative\">\n <div\n v-if=\"hasPrefix\"\n ref=\"prefixEl\"\n data-gr-tree-select-prefix\n class=\"absolute inset-y-px left-px flex items-center justify-center rounded-l-[var(--gr-radius-control)] border-r border-[var(--gr-brd)] px-2 text-[var(--gr-muted-fg)] pointer-events-none select-none truncate\"\n :style=\"prefixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"prefix\" />\n </div>\n\n <input\n :id=\"fieldId\"\n ref=\"triggerEl\"\n data-testid=\"gr-tree-select-trigger\"\n data-gr-tree-select-trigger\n type=\"text\"\n :value=\"displayValue\"\n :placeholder=\"placeholder\"\n :disabled=\"isDisabled\"\n readonly\n role=\"combobox\"\n aria-readonly=\"true\"\n aria-haspopup=\"tree\"\n :aria-expanded=\"open ? 'true' : 'false'\"\n :aria-controls=\"open && hasTree ? treeId : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-label=\"ariaLabel\"\n class=\"w-full rounded-[var(--gr-radius-control)] border placeholder:text-[var(--gr-muted-fg)] transition-colors duration-[var(--gr-duration-fast)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :class=\"[className, $slots.value ? 'text-transparent placeholder:text-transparent' : '']\"\n :style=\"triggerStyle\"\n @pointerdown=\"onTriggerPointerDown\"\n @click=\"toggleDropdown\"\n @focus=\"onTriggerFocus\"\n @keydown=\"onTriggerKeydown\"\n >\n\n <span\n v-if=\"signalState\"\n data-gr-tree-select-state\n class=\"absolute top-1/2 -translate-y-1/2 right-9\"\n :class=\"stateIconClass\"\n aria-hidden=\"true\"\n >\n <component :is=\"stateIcon\" class=\"h-4 w-4\" />\n </span>\n\n <span v-if=\"signalState\" :id=\"stateTextId\" data-gr-tree-select-state-text class=\"sr-only\">{{ stateText }}</span>\n\n <button\n v-if=\"clearable && hasSelection && !disabled && !isReadonly\"\n data-testid=\"gr-tree-select-clear\"\n data-gr-tree-select-clear\n type=\"button\"\n class=\"absolute top-1/2 -translate-y-1/2 right-3 h-6 w-6 inline-flex items-center justify-center rounded-[var(--gr-radius-control)] text-[var(--gr-muted-fg)] hover:text-[var(--gr-fg)] hover:bg-[color-mix(in_srgb,var(--gr-muted)_25%,transparent)]\"\n :aria-label=\"t('gr.common.clear', 'Clear')\"\n @click.stop=\"clear\"\n >\n <IconX class=\"inline-block h-4 w-4\" aria-hidden=\"true\" />\n </button>\n\n <span\n v-else\n data-testid=\"gr-tree-select-chevron\"\n data-gr-tree-select-chevron\n class=\"absolute top-1/2 -translate-y-1/2 right-3 text-[var(--gr-muted-fg)] pointer-events-none\"\n >\n <IconChevronDown\n class=\"inline-block h-4 w-4 transition-transform duration-[var(--gr-duration-fast)]\"\n :class=\"open ? 'rotate-180' : ''\"\n aria-hidden=\"true\"\n />\n </span>\n\n <div\n v-if=\"hasSuffix\"\n ref=\"suffixEl\"\n data-gr-tree-select-suffix\n class=\"absolute inset-y-px right-9 flex items-center justify-center border-l border-[var(--gr-brd)] px-2 text-[var(--gr-muted-fg)] pointer-events-none select-none truncate\"\n :class=\"suffixFixed ? '[direction:rtl]' : ''\"\n :style=\"suffixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"suffix\" />\n </div>\n\n <div\n v-if=\"$slots.value\"\n class=\"absolute inset-y-0 left-3 right-9 flex items-center pointer-events-none\"\n :style=\"valueOverlayStyle\"\n >\n <slot\n name=\"value\"\n :value=\"modelValue\"\n :labels=\"selectedLabels\"\n :display-value=\"displayValue\"\n :path-labels=\"selectedPathLabels\"\n />\n </div>\n </div>\n\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <transition\n :enter-active-class=\"panelPopTransition.enter\"\n :enter-from-class=\"panelPopTransition.enterFrom\"\n :enter-to-class=\"panelPopTransition.enterTo\"\n :leave-active-class=\"panelPopTransition.leave\"\n :leave-from-class=\"panelPopTransition.leaveFrom\"\n :leave-to-class=\"panelPopTransition.leaveTo\"\n >\n <div\n v-show=\"open\"\n ref=\"panelEl\"\n data-testid=\"gr-tree-select-panel\"\n v-bind=\"themeAttrs\"\n data-gr-tree-select-panel\n data-gr-overlay-root\n :style=\"floatingStyle\"\n @keydown=\"onPanelKeydown\"\n >\n <div :class=\"panelClasses\">\n <div v-if=\"filterable\" class=\"p-2 border-b border-[var(--gr-brd)]\">\n <GrInput\n ref=\"filterInputRef\"\n v-model=\"filterValue\"\n data-testid=\"gr-tree-select-filter\"\n data-gr-tree-select-filter\n type=\"search\"\n :inputmode=\"filterInputmode\"\n :placeholder=\"resolvedFilterPlaceholder\"\n size=\"sm\"\n @keydown=\"onFilterKeydown\"\n />\n </div>\n\n <!--\n Скроллер один. При виртуализации его берёт на себя дерево: своя\n высота нужна ему, чтобы посчитать окно, а вложенный скроллер поверх\n дал бы вторую полосу прокрутки на том же списке.\n -->\n <div\n class=\"p-1\"\n :class=\"virtual ? '' : 'overflow-auto'\"\n :style=\"virtual ? undefined : { maxHeight: `${dropdownMaxHeight}px` }\"\n >\n <div\n v-if=\"loading\"\n data-gr-tree-select-loading\n role=\"status\"\n :class=\"grTreeSelectStateClass\"\n >\n <slot name=\"loading\">\n <IconLoaderCircle class=\"block h-4 w-4 animate-spin\" aria-hidden=\"true\" />\n <span>{{ t('gr.treeSelect.loading', 'Loading…') }}</span>\n </slot>\n </div>\n\n <div v-else-if=\"(data?.length ?? 0) === 0\" :class=\"grTreeSelectStateClass\">\n <slot name=\"empty\">\n {{ t('gr.treeSelect.empty', 'No data') }}\n </slot>\n </div>\n\n <GrTree\n v-else\n :id=\"treeId\"\n ref=\"treeRef\"\n :size=\"resolvedSize\"\n :data=\"data\"\n :props=\"props.props\"\n :node-key=\"nodeKey as any\"\n :default-expanded-keys=\"defaultExpandedKeys\"\n :filter-node-method=\"filterNodeMethod\"\n :highlight-current=\"!multiple\"\n :virtual=\"virtual\"\n :max-height=\"dropdownMaxHeight\"\n :show-checkbox=\"checkboxMode\"\n :check-strictly=\"checkStrictly\"\n :checked-keys=\"selectedKeys\"\n @node-click=\"onNodeClick\"\n @update:checked-keys=\"onCheckedKeys\"\n >\n <template #default=\"{ node, data }\">\n <slot\n name=\"node\"\n :node=\"node\"\n :data=\"data\"\n :selected=\"selectedKeySet.has(node.key)\"\n >\n <div class=\"flex items-center gap-2 min-w-0\">\n <!-- Чекбокс дерева уже показывает отметку: вторая галочка\n рядом читалась бы как ошибка. -->\n <span\n v-if=\"!checkboxMode\"\n data-gr-tree-select-check\n class=\"inline-block h-4 w-4 shrink-0\"\n aria-hidden=\"true\"\n >\n <IconCheck v-if=\"selectedKeySet.has(node.key)\" class=\"block h-4 w-4 text-[var(--gr-primary-text)]\" />\n </span>\n <span class=\"truncate\">{{ node.label }}</span>\n </div>\n </slot>\n </template>\n </GrTree>\n </div>\n </div>\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "../../chunks/config-BGCyyXiD.js";
2
- import { t as GrTreeSelect_default } from "./chunks/GrTreeSelect-DzheDCuZ.js";
1
+ import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "../../chunks/config-BAse0laT.js";
2
+ import { t as GrTreeSelect_default } from "./chunks/GrTreeSelect-B6KoDYiZ.js";
3
3
  export { GrTreeSelect_default as GrTreeSelect, GrTreeSelect_default as default, grTreeSelectConfig, grTreeSelectSafelist };
@@ -1,2 +1,2 @@
1
- import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-D_8_l-gM.js";
1
+ import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-AKukmYva.js";
2
2
  export { GRANULARITY_PROVIDER_ID, createGranularityProvider, granularityProvider as default, granularityProvider, granularityComponentConfigs, granularityDefaultThemes, granularityThemeNames };
@@ -1,2 +1,2 @@
1
- import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-D_8_l-gM.js";
1
+ import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-AKukmYva.js";
2
2
  export { GRANULARITY_PROVIDER_ID, createGranularityProvider, granularityProvider as default, granularityProvider, granularityComponentConfigs, granularityDefaultThemes, granularityThemeNames };
package/dist/i18n/all.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as ru, r as en, t as es } from "../chunks/es-CeKkMxZ_.js";
1
+ import { n as ru, r as en, t as es } from "../chunks/es-DIFzSXSZ.js";
2
2
  //#region src/i18n/all.ts
3
3
  var all = [
4
4
  en,
@@ -1,3 +1,3 @@
1
1
  import { t as GRANULARITY_I18N_KEY } from "../chunks/adapter-CAOxmn2G.js";
2
- import { i as GRANULARITY_I18N_BLOCK, n as ru, r as en, t as es } from "../chunks/es-CeKkMxZ_.js";
2
+ import { i as GRANULARITY_I18N_BLOCK, n as ru, r as en, t as es } from "../chunks/es-DIFzSXSZ.js";
3
3
  export { GRANULARITY_I18N_BLOCK, GRANULARITY_I18N_KEY, en, es, ru };
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { t as GrAffix_default } from "./components/GrAffix/chunks/GrAffix-CWtC7y
2
2
  import { n as grAffixSafelist, t as grAffixConfig } from "./chunks/config-Dg0bSoGw.js";
3
3
  import { a as useGrComponentSize, i as useGrComponentProp, n as resolveGrConfig, o as useGrConfig, r as useGrComponentDefaults, s as useGrThemeAttrs } from "./chunks/context-CPMRfwVr.js";
4
4
  import { n as useGranularityTranslations } from "./chunks/granularityI18n-BC5zsj_d.js";
5
- import { t as GrAlert_default } from "./components/GrAlert/chunks/GrAlert-D72y1IEh.js";
5
+ import { t as GrAlert_default } from "./components/GrAlert/chunks/GrAlert-CfEZghSY.js";
6
6
  import { t as grAlertConfig } from "./chunks/config-BNu8lFQB.js";
7
7
  import "./components/GrAlert/index.js";
8
8
  import { t as usePortalTarget } from "./chunks/usePortalTarget-BhrRgdqW.js";
@@ -18,14 +18,14 @@ import { createLoading, vLoading } from "./directives/loading.js";
18
18
  import { useFloating } from "./composables/useFloating.js";
19
19
  import { useOverlayLayer } from "./composables/useOverlayLayer.js";
20
20
  import { useDismissible } from "./composables/useDismissible.js";
21
+ import { t as GrAutocomplete_default } from "./components/GrAutocomplete/chunks/GrAutocomplete-C-uovdv8.js";
21
22
  import { useVirtualList } from "./composables/useVirtualList.js";
23
+ import { useComboboxNavigation } from "./composables/useComboboxNavigation.js";
22
24
  import { n as useGrFormFieldContext } from "./chunks/context-DdNIxa1w.js";
23
25
  import { useGrFormControl } from "./composables/useGrFormControl.js";
24
- import { useComboboxNavigation } from "./composables/useComboboxNavigation.js";
25
26
  import { useRovingFocus } from "./composables/useRovingFocus.js";
26
27
  import { t as GrChip_default } from "./components/GrChip/chunks/GrChip-CKqyzYcv.js";
27
28
  import { n as grAutocompleteSafelist, t as grAutocompleteConfig } from "./chunks/config-BHLMTJaR.js";
28
- import { t as GrAutocomplete_default } from "./components/GrAutocomplete/chunks/GrAutocomplete-D396_JrW.js";
29
29
  import { t as GrSkeleton_default } from "./components/GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js";
30
30
  import { n as GrAvatar_default, t as GrAvatarGroup_default } from "./components/GrAvatar/chunks/GrAvatar-dWEXiCJG.js";
31
31
  import { c as initialsFrom, n as grAvatarSafelist, t as grAvatarConfig } from "./chunks/config-B3J0alyY.js";
@@ -63,29 +63,29 @@ import { t as GrChipGroup_default } from "./components/GrChipGroup/chunks/GrChip
63
63
  import { n as grCollapseSafelist, t as grCollapseConfig } from "./chunks/config-BoUI0t-t.js";
64
64
  import { n as GrCollapse_default, t as GrCollapseItem_default } from "./components/GrCollapse/chunks/GrCollapse-DWH3QAnU.js";
65
65
  import { n as grIconSafelist, t as grIconConfig } from "./chunks/config-3bQeQvqd.js";
66
- import { t as GrInput_default } from "./components/GrInput/chunks/GrInput-TFeBm3gQ.js";
66
+ import { t as GrInput_default } from "./components/GrInput/chunks/GrInput-DV4gMWPR.js";
67
67
  import { t as useFocusTrap } from "./chunks/useFocusTrap-D9bIPNF6.js";
68
68
  import { t as GrPopover_default } from "./components/GrPopover/chunks/GrPopover-CcWvr1ZA.js";
69
69
  import { t as GrSlider_default } from "./components/GrSlider/chunks/GrSlider-CO8N9SF6.js";
70
- import { t as GrColorPicker_default } from "./components/GrColorPicker/chunks/GrColorPicker-9mTR-YZ_.js";
70
+ import { t as GrColorPicker_default } from "./components/GrColorPicker/chunks/GrColorPicker-BRM_4lyI.js";
71
71
  import { n as grColorPickerSafelist, t as grColorPickerConfig } from "./chunks/config-DIDz_E5m.js";
72
72
  import { a as GR_KBD_TOKENS, o as findKbdToken, t as GrKbd_default } from "./components/GrKbd/chunks/GrKbd-BNMeoaLV.js";
73
73
  import { t as GrModal_default } from "./components/GrModal/chunks/GrModal-Cm0mtSXk.js";
74
- import { t as GrCommandPalette_default } from "./components/GrCommandPalette/chunks/GrCommandPalette-Ha4s3DMT.js";
74
+ import { t as GrCommandPalette_default } from "./components/GrCommandPalette/chunks/GrCommandPalette-BJHmkDQv.js";
75
75
  import { n as grCommandPaletteSafelist, t as grCommandPaletteConfig } from "./chunks/config-D0NzGYaE.js";
76
76
  import { t as GrConfigProvider_default } from "./components/GrConfigProvider/chunks/GrConfigProvider-t9x2UToH.js";
77
77
  import { t as grConfigProviderConfig } from "./chunks/config-B7W9VlZ7.js";
78
78
  import { i as GrDialogFooter_default, n as GrDialogHeader_default, r as GrDialogCloseButton_default, t as GrDialog_default } from "./components/GrDialog/chunks/GrDialog-DDz_OEhk.js";
79
- import { a as extendDefaultParsers, n as coreResponseErrorParsers, r as createResponseErrorClassifier, s as normalizeError, t as GrResponseErrorBanner_default } from "./components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-NEEJZ8zi.js";
80
- import { t as GrConfirmDialog_default } from "./components/GrConfirmDialog/chunks/GrConfirmDialog-e15nFI8M.js";
79
+ import { a as extendDefaultParsers, n as coreResponseErrorParsers, r as createResponseErrorClassifier, s as normalizeError, t as GrResponseErrorBanner_default } from "./components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-Bdd5c07x.js";
80
+ import { t as GrConfirmDialog_default } from "./components/GrConfirmDialog/chunks/GrConfirmDialog-BzUQwbec.js";
81
81
  import { t as grConfirmDialogConfig } from "./chunks/config-A-bBiotF.js";
82
82
  import "./components/GrConfirmDialog/index.js";
83
83
  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";
84
84
  import { t as GrContextMenu_default } from "./components/GrContextMenu/chunks/GrContextMenu-RpxMHQXH.js";
85
85
  import { t as grContextMenuConfig } from "./chunks/config-CsCUuukB.js";
86
86
  import { t as GrTable_default } from "./components/GrTable/chunks/GrTable-iwzHvlMC.js";
87
+ import { t as GrDataTable_default } from "./components/GrDataTable/chunks/GrDataTable-Dp9Fp_P5.js";
87
88
  import { useDragSort } from "./composables/useDragSort.js";
88
- import { t as GrDataTable_default } from "./components/GrDataTable/chunks/GrDataTable-xNSmO_I-.js";
89
89
  import { n as grDataTableSafelist, t as grDataTableConfig } from "./chunks/config-DeyT9dJl.js";
90
90
  import { t as GrDelta_default } from "./components/GrDelta/chunks/GrDelta-CgTvfoIN.js";
91
91
  import { n as grValueSafelist, t as grValueConfig } from "./chunks/config-Z5LeUXys.js";
@@ -98,10 +98,10 @@ import { t as grDialogSafelist } from "./chunks/safelist-Y3zrlhOa.js";
98
98
  import "./components/GrDialog/index.js";
99
99
  import { n as useGrFormContext } from "./chunks/context-Bfrgsluh.js";
100
100
  import { t as GrFormField_default } from "./components/GrFormField/chunks/GrFormField-DO61vxpS.js";
101
- import { t as GrTextarea_default } from "./components/GrTextarea/chunks/GrTextarea-BII3w61K.js";
101
+ import { t as GrTextarea_default } from "./components/GrTextarea/chunks/GrTextarea-Bfgc0DD2.js";
102
102
  import { n as getByPath, o as runFieldRules, r as isEmpty, s as setByPath, t as createGrFormMessageResolver } from "./chunks/validation-BDjqsuGB.js";
103
- import { t as GrPromptDialog_default } from "./components/GrPromptDialog/chunks/GrPromptDialog-8RxQsOQ_.js";
104
- import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./components/GrDialogService/chunks/GrDialogService-BmXiYmUp.js";
103
+ import { t as GrPromptDialog_default } from "./components/GrPromptDialog/chunks/GrPromptDialog-BEL-QgwE.js";
104
+ import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./components/GrDialogService/chunks/GrDialogService-Dtq0ZCN5.js";
105
105
  import { t as grDialogServiceConfig } from "./chunks/config-CjXjhphs.js";
106
106
  import { n as grDividerSafelist, t as grDividerConfig } from "./chunks/config-D82r782v.js";
107
107
  import { t as GrDivider_default } from "./components/GrDivider/chunks/GrDivider-DxA-zV25.js";
@@ -129,12 +129,12 @@ import { n as grFormSectionSafelist, t as grFormSectionConfig } from "./chunks/c
129
129
  import { t as GrFormSection_default } from "./components/GrFormSection/chunks/GrFormSection-DV1S6R_N.js";
130
130
  import { t as GrImageViewer_default } from "./components/GrImageViewer/chunks/GrImageViewer-DK-iVHHC.js";
131
131
  import { n as grImageViewerSafelist, t as grImageViewerConfig } from "./chunks/config-DjRhIB5g.js";
132
- import { n as grInputSafelist, t as grInputConfig } from "./chunks/config-CIkdsWUk.js";
133
- import { n as grInputTagSafelist, t as grInputTagConfig } from "./chunks/config-BqT6PMzO.js";
134
- import { t as GrInputTag_default } from "./components/GrInputTag/chunks/GrInputTag-Ci8AO1ze.js";
132
+ import { n as grInputSafelist, t as grInputConfig } from "./chunks/config-CIUU9ZpY.js";
133
+ import { n as grInputTagSafelist, t as grInputTagConfig } from "./chunks/config-B42iJ48O.js";
134
+ import { t as GrInputTag_default } from "./components/GrInputTag/chunks/GrInputTag-CO0YU-ok.js";
135
135
  import { t as useTree } from "./chunks/useTree-BebEiBcL.js";
136
- import { n as grTreeViewVars, t as GrTree_default } from "./components/GrTree/chunks/GrTree-DnDGW0xO.js";
137
- import { t as GrJsonViewer_default } from "./components/GrJsonViewer/chunks/GrJsonViewer-CdlWMGnF.js";
136
+ import { n as grTreeViewVars, t as GrTree_default } from "./components/GrTree/chunks/GrTree-6yZrncJE.js";
137
+ import { t as GrJsonViewer_default } from "./components/GrJsonViewer/chunks/GrJsonViewer-D7CyWzhT.js";
138
138
  import { n as grJsonViewerSafelist, t as grJsonViewerConfig } from "./chunks/config-DpAYidyY.js";
139
139
  import { n as grKbdSafelist, t as grKbdConfig } from "./chunks/config-Ca8qr8Q3.js";
140
140
  import "./components/GrKbd/index.js";
@@ -148,11 +148,11 @@ import { n as grModalSafelist, t as grModalConfig } from "./chunks/config-DZv2N7
148
148
  import "./components/GrModal/index.js";
149
149
  import { t as GrNavbar_default } from "./components/GrNavbar/chunks/GrNavbar-BRGuksiy.js";
150
150
  import { n as grNavbarSafelist, t as grNavbarConfig } from "./chunks/config-2ZHRsdOc.js";
151
- import { n as grNumberInputSafelist, t as grNumberInputConfig } from "./chunks/config-MmPym-Z7.js";
152
- import { t as GrNumberInput_default } from "./components/GrNumberInput/chunks/GrNumberInput-CL5QhOmx.js";
153
- import { t as GrSelect_default } from "./components/GrSelect/chunks/GrSelect-Do1iAyp1.js";
154
- import { n as grPaginationSafelist, t as grPaginationConfig } from "./chunks/config-CjKpUcmy.js";
155
- import { t as GrPagination_default } from "./components/GrPagination/chunks/GrPagination-DhbNZHEF.js";
151
+ import { n as grNumberInputSafelist, t as grNumberInputConfig } from "./chunks/config-BLP94dPY.js";
152
+ import { t as GrNumberInput_default } from "./components/GrNumberInput/chunks/GrNumberInput-BI6-vkcs.js";
153
+ import { t as GrSelect_default } from "./components/GrSelect/chunks/GrSelect-0iI4wdR_.js";
154
+ import { n as grPaginationSafelist, t as grPaginationConfig } from "./chunks/config-Bdf1bt-m.js";
155
+ import { t as GrPagination_default } from "./components/GrPagination/chunks/GrPagination-BbaF5eXk.js";
156
156
  import { n as grPopoverSafelist, t as grPopoverConfig } from "./chunks/config-tNqtapcT.js";
157
157
  import "./components/GrPopover/index.js";
158
158
  import { n as grProgressBarSafelist, t as grProgressBarConfig } from "./chunks/config-hnoZvcIM.js";
@@ -168,7 +168,7 @@ import { t as GrRadioGroup_default } from "./components/GrRadioGroup/chunks/GrRa
168
168
  import { t as grRadioGroupConfig } from "./chunks/config-QaIc_gRa.js";
169
169
  import { n as grRatingSafelist, t as grRatingConfig } from "./chunks/config-DRbojEzO.js";
170
170
  import { t as GrRating_default } from "./components/GrRating/chunks/GrRating-DTriyyqG.js";
171
- import { n as GrFormErrorBanner_default, r as GrUploadErrorBanner_default, t as useResponseError } from "./components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-ZvBvEQDZ.js";
171
+ import { n as GrFormErrorBanner_default, r as GrUploadErrorBanner_default, t as useResponseError } from "./components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-DySe1ym4.js";
172
172
  import { t as useScrollSpy } from "./chunks/useScrollSpy-CIJpw0RI.js";
173
173
  import { t as GrScrollSpy_default } from "./components/GrScrollSpy/chunks/GrScrollSpy-CQCH3zLC.js";
174
174
  import { n as grScrollSpySafelist, t as grScrollSpyConfig } from "./chunks/config-BkQ2jvXv.js";
@@ -198,22 +198,22 @@ import { n as GrTabPanels_default, t as GrTabPanel_default } from "./components/
198
198
  import { t as grTabPanelsConfig } from "./chunks/config-eXB87DOi.js";
199
199
  import { n as grTabsSafelist, t as grTabsConfig } from "./chunks/config-CMNfZO7S.js";
200
200
  import { t as GrTabs_default } from "./components/GrTabs/chunks/GrTabs-s9RzC1WX.js";
201
- import { n as grTextareaSafelist, t as grTextareaConfig } from "./chunks/config-BhfNgyWL.js";
201
+ import { n as grTextareaSafelist, t as grTextareaConfig } from "./chunks/config-DENqOoh0.js";
202
202
  import "./components/GrTextarea/index.js";
203
203
  import { n as GrTimeline_default, t as GrTimelineItem_default } from "./components/GrTimeline/chunks/GrTimeline-Bs60huw0.js";
204
204
  import { n as grTimelineSafelist, t as grTimelineConfig } from "./chunks/config-Bd7QfiGj.js";
205
205
  import { GRANULARITY_TOAST_STATE, granularityToastPlugin, useToast } from "./composables/useToast.js";
206
206
  import { n as grToasterSafelist, t as grToasterConfig } from "./chunks/config-B5SBUa6u.js";
207
- import { t as GrToaster_default } from "./components/GrToaster/chunks/GrToaster-D-sV-9of.js";
207
+ import { t as GrToaster_default } from "./components/GrToaster/chunks/GrToaster-CZixNk0l.js";
208
208
  import { n as grTooltipSafelist, t as grTooltipConfig } from "./chunks/config-iemgzS4x.js";
209
209
  import { t as GrTooltip_default } from "./components/GrTooltip/chunks/GrTooltip-DkMMM0uq.js";
210
210
  import { n as grTransferSafelist, t as grTransferConfig } from "./chunks/config-DmED6aJV.js";
211
- import { t as GrTransfer_default } from "./components/GrTransfer/chunks/GrTransfer-8FA78ny6.js";
211
+ import { t as GrTransfer_default } from "./components/GrTransfer/chunks/GrTransfer-DdfBUf35.js";
212
212
  import { n as grTreeSafelist, t as grTreeConfig } from "./chunks/config-CDat1wXf.js";
213
- import { n as grTreeSectionsSafelist, t as grTreeSectionsConfig } from "./chunks/config-ChnYtO4o.js";
214
- import { t as GrTreeSections_default } from "./components/GrTreeSections/chunks/GrTreeSections-D2PQ87mw.js";
215
- import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "./chunks/config-BGCyyXiD.js";
216
- import { t as GrTreeSelect_default } from "./components/GrTreeSelect/chunks/GrTreeSelect-DzheDCuZ.js";
213
+ import { n as grTreeSectionsSafelist, t as grTreeSectionsConfig } from "./chunks/config-bjDf8nBf.js";
214
+ import { t as GrTreeSections_default } from "./components/GrTreeSections/chunks/GrTreeSections-DcmDcLwj.js";
215
+ import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "./chunks/config-BAse0laT.js";
216
+ import { t as GrTreeSelect_default } from "./components/GrTreeSelect/chunks/GrTreeSelect-B6KoDYiZ.js";
217
217
  import "./composables/useGrComponentConfig.js";
218
218
  import "./composables/useGranularityTranslations.js";
219
219
  import { GRANULARITY_THEME_STATE, granularityThemePlugin, initThemeEarly, useTheme } from "./composables/useTheme.js";
package/dist/theme.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as grThemeTokens, n as grDerivedTokens, t as grComponentTokens } from "./chunks/generated-DAKeOOqm.js";
1
+ import { a as grThemeTokens, n as grDerivedTokens, t as grComponentTokens } from "./chunks/generated-CQ4h6Ieq.js";
2
2
  //#region src/theme/color.ts
3
3
  function parseHex(value) {
4
4
  const match = value.trim().match(/^#([\da-f]{3}|[\da-f]{6})$/i);
package/dist/tokens.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as grThemeTokens, i as grThemeNames, n as grDerivedTokens, r as grFoundationTokens, t as grComponentTokens } from "./chunks/generated-DAKeOOqm.js";
1
+ import { a as grThemeTokens, i as grThemeNames, n as grDerivedTokens, r as grFoundationTokens, t as grComponentTokens } from "./chunks/generated-CQ4h6Ieq.js";
2
2
  export { grComponentTokens, grDerivedTokens, grFoundationTokens, grThemeNames, grThemeTokens };
@@ -0,0 +1,39 @@
1
+ import type { ComputedRef, Ref } from 'vue';
2
+ import type { GrAutocompleteOption, GrAutocompleteValue } from '../GrAutocomplete.vue';
3
+ /**
4
+ * Клавиатурная навигация ходит и по опциям, и по варианту «добавить своё»:
5
+ * иначе при непустом списке Enter всегда уходил бы в активную опцию, и
6
+ * закоммитить произвольное значение с клавиатуры было бы нечем.
7
+ */
8
+ export type GrAutocompleteNavigableItem<TValue extends GrAutocompleteValue> = {
9
+ kind: 'add';
10
+ } | {
11
+ kind: 'option';
12
+ option: GrAutocompleteOption<TValue>;
13
+ index: number;
14
+ };
15
+ export interface UseAutocompleteNavigationOptions<TValue extends GrAutocompleteValue> {
16
+ effectiveOptions: ComputedRef<GrAutocompleteOption<TValue>[]>;
17
+ canAddCustom: ComputedRef<boolean>;
18
+ selectedValues: ComputedRef<TValue[]>;
19
+ open: Ref<boolean>;
20
+ virtual: () => boolean;
21
+ /** Сдвиг окна из-за строки «Add …» — из модуля виртуализации. */
22
+ addOffset: ComputedRef<number>;
23
+ scrollToIndex: (index: number) => void;
24
+ optionDomId: (index: number) => string;
25
+ addOptionDomId: ComputedRef<string>;
26
+ }
27
+ export interface AutocompleteNavigation<TValue extends GrAutocompleteValue> {
28
+ navigableItems: ComputedRef<Array<GrAutocompleteNavigableItem<TValue>>>;
29
+ isSelected: (value: TValue) => boolean;
30
+ navigableIndexOf: (value: TValue) => number;
31
+ activeIndex: Ref<number>;
32
+ activeItem: ComputedRef<GrAutocompleteNavigableItem<TValue> | undefined>;
33
+ activeDescendantId: ComputedRef<string | undefined>;
34
+ activeValue: ComputedRef<TValue | undefined>;
35
+ initActiveIndex: () => void;
36
+ resetActive: () => void;
37
+ handleNavigationKeys: (event: KeyboardEvent) => boolean;
38
+ }
39
+ export declare function useAutocompleteNavigation<TValue extends GrAutocompleteValue>(options: UseAutocompleteNavigationOptions<TValue>): AutocompleteNavigation<TValue>;
@@ -0,0 +1,36 @@
1
+ import type { ComputedRef, Ref } from 'vue';
2
+ import type { GrAutocompleteOption, GrAutocompleteValue } from '../GrAutocomplete.vue';
3
+ /**
4
+ * Состав панели `GrAutocomplete`: что показывать под запросом.
5
+ *
6
+ * Три решения, которые легко перепутать между собой. При `fetchOptions`
7
+ * локальный матчер выключается — он отсеял бы то, что сервер уже прислал в
8
+ * ответ на этот же запрос. Ниже `minQueryLength` список пуст, а не «прошлый»:
9
+ * показывать старый набор под подсказкой «введите ещё N» значит
10
+ * дезинформировать. А «Add …» не предлагается, если такое значение или подпись
11
+ * уже есть среди опций.
12
+ */
13
+ export interface UseAutocompletePanelOptions<TValue extends GrAutocompleteValue> {
14
+ optionsResolved: ComputedRef<GrAutocompleteOption<TValue>[]>;
15
+ /** Введённый текст без нормализации: тримит уже сам модуль. */
16
+ query: Ref<string>;
17
+ /** Пользователь начал ввод — до этого single-режим показывает весь список. */
18
+ dirty: Ref<boolean>;
19
+ filterable: () => boolean;
20
+ filter: () => ((option: GrAutocompleteOption<TValue>, query: string) => boolean) | undefined;
21
+ fetchOptions: () => unknown;
22
+ multiple: () => boolean;
23
+ minQueryLength: () => number;
24
+ allowCustomValue: () => boolean;
25
+ selectedValues: ComputedRef<TValue[]>;
26
+ modelSingle: ComputedRef<TValue | ''>;
27
+ isLoading: ComputedRef<boolean>;
28
+ }
29
+ export interface AutocompletePanel<TValue extends GrAutocompleteValue> {
30
+ searchQuery: ComputedRef<string>;
31
+ belowMinQuery: ComputedRef<boolean>;
32
+ effectiveOptions: ComputedRef<GrAutocompleteOption<TValue>[]>;
33
+ canAddCustom: ComputedRef<boolean>;
34
+ showEmpty: ComputedRef<boolean>;
35
+ }
36
+ export declare function useAutocompletePanel<TValue extends GrAutocompleteValue>(options: UseAutocompletePanelOptions<TValue>): AutocompletePanel<TValue>;