@feugene/granularity 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/GrTree.css +1 -1
  2. package/dist/chunks/config-1uSYl98Y2.js.map +1 -0
  3. package/dist/chunks/config-BIRO0vDJ.js.map +1 -0
  4. package/dist/chunks/config-BWiPnygb.js +5 -0
  5. package/dist/chunks/config-BWiPnygb.js.map +1 -0
  6. package/dist/chunks/config-BXtAmU3s2.js.map +1 -0
  7. package/dist/chunks/config-CGHLoBlH.js.map +1 -0
  8. package/dist/chunks/config-CrG1XiE72.js.map +1 -0
  9. package/dist/chunks/config-DUcu1D682.js.map +1 -0
  10. package/dist/chunks/config-Dlm49Jp5.js +5 -0
  11. package/dist/chunks/config-Dlm49Jp5.js.map +1 -0
  12. package/dist/chunks/config-DnvPqu4g2.js.map +1 -0
  13. package/dist/chunks/config-DpqOnJiz.js.map +1 -0
  14. package/dist/chunks/config-JpHA4Xx02.js.map +1 -0
  15. package/dist/chunks/config-LGrZIdaZ.js.map +1 -0
  16. package/dist/chunks/config-eXB87DOi2.js +9 -0
  17. package/dist/chunks/config-eXB87DOi2.js.map +1 -0
  18. package/dist/chunks/context-DdNIxa1w.js +9 -0
  19. package/dist/chunks/context-DdNIxa1w.js.map +1 -0
  20. package/dist/chunks/{en-BdtiS2d3.js → en-CfkDa4GX.js} +8 -2
  21. package/dist/chunks/{en-BdtiS2d3.js.map → en-CfkDa4GX.js.map} +1 -1
  22. package/dist/chunks/{es-DBhctWg-.js → es-CgaLnFYx.js} +3 -3
  23. package/dist/chunks/{es-DBhctWg-.js.map → es-CgaLnFYx.js.map} +1 -1
  24. package/dist/chunks/{es-BGRMZbe9.js → es-FkgECuCm.js} +8 -2
  25. package/dist/chunks/{es-BGRMZbe9.js.map → es-FkgECuCm.js.map} +1 -1
  26. package/dist/chunks/grModalEscStack-BXk-9mv7.js +43 -0
  27. package/dist/chunks/grModalEscStack-BXk-9mv7.js.map +1 -0
  28. package/dist/chunks/{ru-BFCnOiML.js → ru-Bl8CxpEa.js} +8 -2
  29. package/dist/chunks/{ru-BFCnOiML.js.map → ru-Bl8CxpEa.js.map} +1 -1
  30. package/dist/chunks/{shared-ChvcQgDl.js → shared-B6Ay2081.js} +17 -11
  31. package/dist/chunks/shared-B6Ay2081.js.map +1 -0
  32. package/dist/chunks/{transition-TLFw4KBn.js → useScrollLock-K7kaP2Ud.js} +52 -1
  33. package/dist/chunks/useScrollLock-K7kaP2Ud.js.map +1 -0
  34. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BWYKCsHd.js → GrConfirmDialog-D8CkOtqv.js} +1 -1
  35. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BWYKCsHd.js.map → GrConfirmDialog-D8CkOtqv.js.map} +1 -1
  36. package/dist/components/GrConfirmDialog/index.js +2 -2
  37. package/dist/components/GrDataTable/chunks/{GrDataTable-ptbARmJ3.js → GrDataTable-Ds5OeGat.js} +42 -16
  38. package/dist/components/GrDataTable/chunks/GrDataTable-Ds5OeGat.js.map +1 -0
  39. package/dist/components/GrDataTable/index.js +1 -1
  40. package/dist/components/GrDialog/chunks/{GrDialog-5DAS-1Lb.js → GrDialog-Ctucxju9.js} +2 -2
  41. package/dist/components/GrDialog/chunks/{GrDialog-5DAS-1Lb.js.map → GrDialog-Ctucxju9.js.map} +1 -1
  42. package/dist/components/GrDialog/index.js +1 -1
  43. package/dist/components/GrDialogService/chunks/{GrDialogService-DY_fmaMu.js → GrDialogService-CU1Fbonc.js} +2 -2
  44. package/dist/components/GrDialogService/chunks/{GrDialogService-DY_fmaMu.js.map → GrDialogService-CU1Fbonc.js.map} +1 -1
  45. package/dist/components/GrDialogService/index.js +1 -1
  46. package/dist/components/GrDivider/chunks/GrDivider-5bcE-BB4.js +54 -0
  47. package/dist/components/GrDivider/chunks/GrDivider-5bcE-BB4.js.map +1 -0
  48. package/dist/components/GrDivider/index.js +3 -0
  49. package/dist/components/GrDrawer/chunks/{GrDrawer-D1kzsjXN.js → GrDrawer-SLGKCY2A.js} +37 -13
  50. package/dist/components/GrDrawer/chunks/GrDrawer-SLGKCY2A.js.map +1 -0
  51. package/dist/components/GrDrawer/index.js +2 -2
  52. package/dist/components/GrDropdown/chunks/{GrDropdown-BXb5Cxxf.js → GrDropdown-BnDMYP8v.js} +90 -4
  53. package/dist/components/GrDropdown/chunks/GrDropdown-BnDMYP8v.js.map +1 -0
  54. package/dist/components/GrDropdown/index.js +1 -1
  55. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DFEJLPcV.js → GrDropdownMenu--g9Vofcq.js} +1 -1
  56. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DFEJLPcV.js.map → GrDropdownMenu--g9Vofcq.js.map} +1 -1
  57. package/dist/components/GrDropdownMenu/index.js +1 -1
  58. package/dist/components/GrFormField/chunks/GrFormField-DnfMHx_U.js +73 -0
  59. package/dist/components/GrFormField/chunks/GrFormField-DnfMHx_U.js.map +1 -0
  60. package/dist/components/GrFormField/index.js +3 -2
  61. package/dist/components/GrImageViewer/chunks/{GrImageViewer-OCUIrNh2.js → GrImageViewer-Dla9IBkd.js} +311 -222
  62. package/dist/components/GrImageViewer/chunks/GrImageViewer-Dla9IBkd.js.map +1 -0
  63. package/dist/components/GrImageViewer/index.js +1 -1
  64. package/dist/components/GrInput/chunks/GrInput-B8dd3JaA.js +334 -0
  65. package/dist/components/GrInput/chunks/GrInput-B8dd3JaA.js.map +1 -0
  66. package/dist/components/GrInput/index.js +1 -1
  67. package/dist/components/GrKbd/chunks/GrKbd-BEoYxWhE.js +22 -0
  68. package/dist/components/GrKbd/chunks/GrKbd-BEoYxWhE.js.map +1 -0
  69. package/dist/components/GrKbd/index.js +3 -0
  70. package/dist/components/GrModal/chunks/{GrModal-BkjW9jZS.js → GrModal-C0GZrHN3.js} +3 -56
  71. package/dist/components/GrModal/chunks/GrModal-C0GZrHN3.js.map +1 -0
  72. package/dist/components/GrModal/index.js +1 -1
  73. package/dist/components/GrNumberInput/chunks/{GrNumberInput-CldPIWQx.js → GrNumberInput-DxCEvL7V.js} +93 -11
  74. package/dist/components/GrNumberInput/chunks/GrNumberInput-DxCEvL7V.js.map +1 -0
  75. package/dist/components/GrNumberInput/index.js +1 -1
  76. package/dist/components/GrPagination/chunks/{GrPagination-Bu9wv6it.js → GrPagination-mlyfLjQY.js} +1 -1
  77. package/dist/components/GrPagination/chunks/{GrPagination-Bu9wv6it.js.map → GrPagination-mlyfLjQY.js.map} +1 -1
  78. package/dist/components/GrPagination/index.js +2 -2
  79. package/dist/components/GrProgressBar/index.js +1 -1
  80. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-TmWXbpEP.js → GrPromptDialog-C-_BMNuY.js} +3 -3
  81. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-TmWXbpEP.js.map → GrPromptDialog-C-_BMNuY.js.map} +1 -1
  82. package/dist/components/GrPromptDialog/index.js +1 -1
  83. package/dist/components/GrRadio/chunks/{GrRadio-CPTixXaY.js → GrRadio-Dr-pvs_9.js} +1 -1
  84. package/dist/components/GrRadio/chunks/{GrRadio-CPTixXaY.js.map → GrRadio-Dr-pvs_9.js.map} +1 -1
  85. package/dist/components/GrRadio/index.js +2 -2
  86. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-vKZCbkCp.js → GrRadioGroup-nOdvfV_g.js} +1 -1
  87. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-vKZCbkCp.js.map → GrRadioGroup-nOdvfV_g.js.map} +1 -1
  88. package/dist/components/GrRadioGroup/index.js +1 -1
  89. package/dist/components/GrSelect/chunks/{GrSelect-RShK21lK.js → GrSelect-BVCmitqa.js} +147 -27
  90. package/dist/components/GrSelect/chunks/GrSelect-BVCmitqa.js.map +1 -0
  91. package/dist/components/GrSelect/index.js +1 -1
  92. package/dist/components/GrSidebar/index.js +1 -1
  93. package/dist/components/GrTabPanels/chunks/GrTabPanels-DbKybwe-.js +68 -0
  94. package/dist/components/GrTabPanels/chunks/GrTabPanels-DbKybwe-.js.map +1 -0
  95. package/dist/components/GrTabPanels/index.js +3 -0
  96. package/dist/components/GrTabs/chunks/{GrTabs-Z-FDJUr_.js → GrTabs-DsLwWoRz.js} +6 -1
  97. package/dist/components/GrTabs/chunks/GrTabs-DsLwWoRz.js.map +1 -0
  98. package/dist/components/GrTabs/index.js +1 -1
  99. package/dist/components/GrTextarea/chunks/{GrTextarea-D56YxhKq.js → GrTextarea-CKukGlNl.js} +15 -5
  100. package/dist/components/GrTextarea/chunks/GrTextarea-CKukGlNl.js.map +1 -0
  101. package/dist/components/GrTextarea/index.js +2 -2
  102. package/dist/components/GrToaster/chunks/{GrToaster-eI8YvnIo.js → GrToaster-L2cu6cSR.js} +1 -1
  103. package/dist/components/GrToaster/chunks/{GrToaster-eI8YvnIo.js.map → GrToaster-L2cu6cSR.js.map} +1 -1
  104. package/dist/components/GrToaster/index.js +2 -2
  105. package/dist/components/GrTree/chunks/{GrTree-D3ODe2dB.js → GrTree-B2_yW6g1.js} +107 -8
  106. package/dist/components/GrTree/chunks/GrTree-B2_yW6g1.js.map +1 -0
  107. package/dist/components/GrTree/index.js +2 -2
  108. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-B2xBKs5Q.js → GrTreeSelect-0aM62xyu.js} +3 -3
  109. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-B2xBKs5Q.js.map → GrTreeSelect-0aM62xyu.js.map} +1 -1
  110. package/dist/components/GrTreeSelect/index.js +2 -2
  111. package/dist/granular-provider-node.js +2 -2
  112. package/dist/granular-provider.js +1 -1
  113. package/dist/i18n/all.js +1 -1
  114. package/dist/i18n/index.js +1 -1
  115. package/dist/index.js +40 -33
  116. package/dist/index.js.map +1 -1
  117. package/dist/styles/base.css +30 -8
  118. package/dist/styles/preflight.css +5 -1
  119. package/dist/types/src/components/GrDataTable/GrDataTable.vue.d.ts +28 -4
  120. package/dist/types/src/components/GrDivider/GrDivider.vue.d.ts +58 -0
  121. package/dist/types/src/components/GrDivider/config.d.ts +1 -0
  122. package/dist/types/src/components/GrDivider/index.d.ts +4 -0
  123. package/dist/types/src/components/GrDrawer/GrDrawer.vue.d.ts +4 -4
  124. package/dist/types/src/components/GrDropdown/GrDropdown.vue.d.ts +7 -0
  125. package/dist/types/src/components/GrDropdownMenu/GrDropdownMenu.vue.d.ts +6 -0
  126. package/dist/types/src/components/GrFormField/GrFormField.vue.d.ts +15 -2
  127. package/dist/types/src/components/GrFormField/context.d.ts +20 -0
  128. package/dist/types/src/components/GrFormField/index.d.ts +1 -0
  129. package/dist/types/src/components/GrImageViewer/GrImageViewer.vue.d.ts +4 -0
  130. package/dist/types/src/components/GrImageViewer/composables/useViewerKeyboard.d.ts +20 -0
  131. package/dist/types/src/components/GrImageViewer/composables/useWheelGesture.d.ts +16 -0
  132. package/dist/types/src/components/GrImageViewer/composables/useZoomPan.d.ts +50 -0
  133. package/dist/types/src/components/GrInput/GrInput.vue.d.ts +41 -2
  134. package/dist/types/src/components/GrKbd/GrKbd.vue.d.ts +46 -0
  135. package/dist/types/src/components/GrKbd/config.d.ts +1 -0
  136. package/dist/types/src/components/GrKbd/index.d.ts +4 -0
  137. package/dist/types/src/components/GrNumberInput/GrNumberInput.vue.d.ts +16 -0
  138. package/dist/types/src/components/GrSelect/GrSelect.vue.d.ts +2 -2
  139. package/dist/types/src/components/GrTabPanels/GrTabPanel.vue.d.ts +46 -0
  140. package/dist/types/src/components/GrTabPanels/GrTabPanels.vue.d.ts +51 -0
  141. package/dist/types/src/components/GrTabPanels/config.d.ts +5 -0
  142. package/dist/types/src/components/GrTabPanels/context.d.ts +9 -0
  143. package/dist/types/src/components/GrTabPanels/index.d.ts +6 -0
  144. package/dist/types/src/components/GrTabs/GrTabs.vue.d.ts +6 -0
  145. package/dist/types/src/components/GrTree/grTreeInteractionContext.d.ts +2 -0
  146. package/dist/types/src/composables/internal/useScrollLock.d.ts +24 -0
  147. package/dist/types/src/granular-provider/shared.d.ts +3 -0
  148. package/dist/types/src/i18n/messages/en.d.ts +10 -0
  149. package/dist/types/src/i18n/messages/es.d.ts +10 -0
  150. package/dist/types/src/i18n/messages/ru.d.ts +10 -0
  151. package/dist/types/src/index.d.ts +3 -0
  152. package/dist/web-types.json +275 -26
  153. package/package.json +13 -1
  154. package/dist/chunks/config-1uSYl98Y.js.map +0 -1
  155. package/dist/chunks/config-BIRO0vDJ2.js.map +0 -1
  156. package/dist/chunks/config-BXtAmU3s.js.map +0 -1
  157. package/dist/chunks/config-CGHLoBlH2.js.map +0 -1
  158. package/dist/chunks/config-CrG1XiE7.js.map +0 -1
  159. package/dist/chunks/config-DUcu1D68.js.map +0 -1
  160. package/dist/chunks/config-DnvPqu4g.js.map +0 -1
  161. package/dist/chunks/config-DpqOnJiz2.js.map +0 -1
  162. package/dist/chunks/config-JpHA4Xx0.js.map +0 -1
  163. package/dist/chunks/config-LGrZIdaZ2.js.map +0 -1
  164. package/dist/chunks/shared-ChvcQgDl.js.map +0 -1
  165. package/dist/chunks/transition-TLFw4KBn.js.map +0 -1
  166. package/dist/components/GrDataTable/chunks/GrDataTable-ptbARmJ3.js.map +0 -1
  167. package/dist/components/GrDrawer/chunks/GrDrawer-D1kzsjXN.js.map +0 -1
  168. package/dist/components/GrDropdown/chunks/GrDropdown-BXb5Cxxf.js.map +0 -1
  169. package/dist/components/GrFormField/chunks/GrFormField-BujNQrw8.js +0 -35
  170. package/dist/components/GrFormField/chunks/GrFormField-BujNQrw8.js.map +0 -1
  171. package/dist/components/GrImageViewer/chunks/GrImageViewer-OCUIrNh2.js.map +0 -1
  172. package/dist/components/GrInput/chunks/GrInput-C8pOJgCi.js +0 -188
  173. package/dist/components/GrInput/chunks/GrInput-C8pOJgCi.js.map +0 -1
  174. package/dist/components/GrModal/chunks/GrModal-BkjW9jZS.js.map +0 -1
  175. package/dist/components/GrNumberInput/chunks/GrNumberInput-CldPIWQx.js.map +0 -1
  176. package/dist/components/GrSelect/chunks/GrSelect-RShK21lK.js.map +0 -1
  177. package/dist/components/GrTabs/chunks/GrTabs-Z-FDJUr_.js.map +0 -1
  178. package/dist/components/GrTextarea/chunks/GrTextarea-D56YxhKq.js.map +0 -1
  179. package/dist/components/GrTree/chunks/GrTree-D3ODe2dB.js.map +0 -1
  180. /package/dist/chunks/{config-1uSYl98Y.js → config-1uSYl98Y2.js} +0 -0
  181. /package/dist/chunks/{config-BIRO0vDJ2.js → config-BIRO0vDJ.js} +0 -0
  182. /package/dist/chunks/{config-BXtAmU3s.js → config-BXtAmU3s2.js} +0 -0
  183. /package/dist/chunks/{config-CGHLoBlH2.js → config-CGHLoBlH.js} +0 -0
  184. /package/dist/chunks/{config-CrG1XiE7.js → config-CrG1XiE72.js} +0 -0
  185. /package/dist/chunks/{config-DUcu1D68.js → config-DUcu1D682.js} +0 -0
  186. /package/dist/chunks/{config-DnvPqu4g.js → config-DnvPqu4g2.js} +0 -0
  187. /package/dist/chunks/{config-DpqOnJiz2.js → config-DpqOnJiz.js} +0 -0
  188. /package/dist/chunks/{config-JpHA4Xx0.js → config-JpHA4Xx02.js} +0 -0
  189. /package/dist/chunks/{config-LGrZIdaZ2.js → config-LGrZIdaZ.js} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { t as useGranularityTranslations } from "../../../chunks/granularityI18n-DoV7Ca2m.js";
2
2
  import { t as _plugin_vue_export_helper_default } from "../../../chunks/_plugin-vue_export-helper-BOaGB7Aw.js";
3
- import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveComponent, shallowRef, toDisplayString, toValue, unref, watch, withCtx, withModifiers } from "vue";
3
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, nextTick, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveComponent, shallowRef, toDisplayString, toValue, unref, watch, withCtx, withModifiers } from "vue";
4
4
  import '../../../GrTree.css';//#region src/components/GrTree/grTreeDataAdapter.ts
5
5
  var DEFAULT_CHILDREN_KEY = "children";
6
6
  var DEFAULT_LABEL_KEY = "label";
@@ -61,6 +61,7 @@ function createGrTreeDataAdapter(options) {
61
61
  //#region src/components/GrTree/grTreeInteractionContext.ts
62
62
  function createGrTreeInteractionContext(options, emitters) {
63
63
  const hoveredKey = ref(void 0);
64
+ const focusedKey = ref(void 0);
64
65
  const draggingNode = shallowRef(null);
65
66
  const dropTarget = shallowRef(null);
66
67
  function canDrag(node) {
@@ -78,6 +79,7 @@ function createGrTreeInteractionContext(options, emitters) {
78
79
  }
79
80
  return {
80
81
  hoveredKey,
82
+ focusedKey,
81
83
  draggingNode,
82
84
  dropTarget,
83
85
  canDrag,
@@ -345,7 +347,13 @@ function createGrTreeStore(options) {
345
347
  //#endregion
346
348
  //#region src/components/GrTree/GrTree.vue?vue&type=script&setup=true&lang.ts
347
349
  var _hoisted_1 = ["data-gr-tree", "role"];
348
- var _hoisted_2 = ["aria-level", "aria-expanded"];
350
+ var _hoisted_2 = [
351
+ "data-gr-tree-node-key",
352
+ "aria-level",
353
+ "aria-expanded",
354
+ "aria-selected",
355
+ "tabindex"
356
+ ];
349
357
  var _hoisted_3 = [
350
358
  "onClick",
351
359
  "onDrop",
@@ -361,7 +369,7 @@ var _hoisted_4 = [
361
369
  var _hoisted_5 = ["aria-label", "onClick"];
362
370
  var _hoisted_6 = { class: "gr-tree__label" };
363
371
  var _hoisted_7 = { class: "gr-tree__label" };
364
- var DEFAULT_BRANCH_LINE_COLOR = "var(--gr-tree-branch-line-default-color, #e2e8f0)";
372
+ var DEFAULT_BRANCH_LINE_COLOR = "var(--gr-tree-branch-line-default-color, var(--brd))";
365
373
  //#endregion
366
374
  //#region src/components/GrTree/GrTree.vue
367
375
  var GrTree_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -511,7 +519,9 @@ var GrTree_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
511
519
  const collapseLabel = computed(() => treeProps.collapseLabel ?? t("gr.tree.collapse", "Collapse"));
512
520
  const currentKey = treeStore.currentKey;
513
521
  const hoveredKey = interactionContext.hoveredKey;
522
+ const focusedKey = interactionContext.focusedKey;
514
523
  const dropTarget = interactionContext.dropTarget;
524
+ const treeRootEl = ref(null);
515
525
  const visibleRows = computed(() => {
516
526
  if (props.internalRows) return props.internalRows;
517
527
  const { roots } = treeStore.treeModel.value;
@@ -537,8 +547,92 @@ var GrTree_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
537
547
  });
538
548
  function onRowClick(node) {
539
549
  treeStore.setCurrentKey(node.key);
550
+ focusedKey.value = node.key;
540
551
  interactionContext.emitNodeClick(node.data, node);
541
552
  }
553
+ const flatVisibleRows = computed(() => {
554
+ const out = [];
555
+ const walk = (rows) => {
556
+ for (const row of rows) {
557
+ out.push({
558
+ node: row.node,
559
+ isLeaf: row.isLeaf,
560
+ isExpanded: row.isExpanded
561
+ });
562
+ if (row.children.length) walk(row.children);
563
+ }
564
+ };
565
+ walk(visibleRows.value);
566
+ return out;
567
+ });
568
+ function isRovingItem(key) {
569
+ return focusedKey.value === key;
570
+ }
571
+ function focusRow(key) {
572
+ focusedKey.value = key;
573
+ nextTick(() => {
574
+ const root = treeRootEl.value;
575
+ if (!root) return;
576
+ const target = String(key);
577
+ Array.from(root.querySelectorAll("[data-gr-tree-node-key]")).find((node) => node.getAttribute("data-gr-tree-node-key") === target)?.focus();
578
+ });
579
+ }
580
+ function onTreeKeydown(event) {
581
+ if (props.internalNested) return;
582
+ const rows = flatVisibleRows.value;
583
+ if (rows.length === 0) return;
584
+ const idx = Math.max(0, rows.findIndex((r) => r.node.key === focusedKey.value));
585
+ const cur = rows[idx];
586
+ switch (event.key) {
587
+ case "ArrowDown":
588
+ event.preventDefault();
589
+ if (idx < rows.length - 1) focusRow(rows[idx + 1].node.key);
590
+ break;
591
+ case "ArrowUp":
592
+ event.preventDefault();
593
+ if (idx > 0) focusRow(rows[idx - 1].node.key);
594
+ break;
595
+ case "ArrowRight":
596
+ event.preventDefault();
597
+ if (!cur.isLeaf) {
598
+ if (!cur.isExpanded) toggleExpand(cur.node);
599
+ else if (idx < rows.length - 1) focusRow(rows[idx + 1].node.key);
600
+ }
601
+ break;
602
+ case "ArrowLeft":
603
+ event.preventDefault();
604
+ if (!cur.isLeaf && cur.isExpanded) toggleExpand(cur.node);
605
+ else if (cur.node.parent && rows.some((r) => r.node.key === cur.node.parent.key)) focusRow(cur.node.parent.key);
606
+ break;
607
+ case "Home":
608
+ event.preventDefault();
609
+ focusRow(rows[0].node.key);
610
+ break;
611
+ case "End":
612
+ event.preventDefault();
613
+ focusRow(rows[rows.length - 1].node.key);
614
+ break;
615
+ case "Enter":
616
+ case " ":
617
+ event.preventDefault();
618
+ onRowClick(cur.node);
619
+ break;
620
+ }
621
+ }
622
+ function normalizeFocusedKey() {
623
+ if (props.internalNested) return;
624
+ const rows = flatVisibleRows.value;
625
+ if (rows.length === 0) {
626
+ focusedKey.value = void 0;
627
+ return;
628
+ }
629
+ if (focusedKey.value !== void 0 && rows.some((r) => r.node.key === focusedKey.value)) return;
630
+ focusedKey.value = currentKey.value != null && rows.some((r) => r.node.key === currentKey.value) ? currentKey.value : rows[0].node.key;
631
+ }
632
+ if (!props.internalNested) {
633
+ normalizeFocusedKey();
634
+ watch(flatVisibleRows, normalizeFocusedKey, { flush: "sync" });
635
+ }
542
636
  function onRowMouseEnter(node) {
543
637
  hoveredKey.value = node.key;
544
638
  }
@@ -651,16 +745,22 @@ var GrTree_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
651
745
  return (_ctx, _cache) => {
652
746
  const _component_GrTree = resolveComponent("GrTree", true);
653
747
  return openBlock(), createElementBlock("div", {
748
+ ref_key: "treeRootEl",
749
+ ref: treeRootEl,
654
750
  "data-gr-tree": props.internalNested ? void 0 : "",
655
751
  class: normalizeClass(props.internalNested ? "gr-tree__children" : "gr-tree"),
656
- role: props.internalNested ? "group" : "tree"
752
+ role: props.internalNested ? "group" : "tree",
753
+ onKeydown: onTreeKeydown
657
754
  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(visibleRows.value, (row) => {
658
755
  return openBlock(), createElementBlock("div", {
659
756
  key: row.node.key,
660
757
  "data-gr-tree-node": "",
758
+ "data-gr-tree-node-key": row.node.key,
661
759
  role: "treeitem",
662
760
  "aria-level": row.node.level,
663
- "aria-expanded": row.isLeaf ? void 0 : row.isExpanded
761
+ "aria-expanded": row.isLeaf ? void 0 : row.isExpanded,
762
+ "aria-selected": unref(currentKey) === row.node.key ? "true" : "false",
763
+ tabindex: isRovingItem(row.node.key) ? 0 : -1
664
764
  }, [createElementVNode("div", {
665
765
  "data-gr-tree-row": "",
666
766
  class: normalizeClass(["gr-tree__row py-2 px-2", [
@@ -671,7 +771,6 @@ var GrTree_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
671
771
  unref(dropTarget)?.key === row.node.key && unref(dropTarget).allowed && unref(dropTarget).type === "next" ? "gr-tree__row--drop-next" : "",
672
772
  resolveNodeClass(unref(treeProps).rowClass, row)
673
773
  ]]),
674
- tabindex: "0",
675
774
  onClick: ($event) => onRowClick(row.node),
676
775
  onDrop: ($event) => onDrop($event, row.node),
677
776
  onDragover: ($event) => onDragOver($event, row.node, $event.currentTarget),
@@ -731,9 +830,9 @@ var GrTree_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE_
731
830
  "internal-store",
732
831
  "internal-interaction-context"
733
832
  ])], 6)) : createCommentVNode("", true)], 8, _hoisted_2);
734
- }), 128))], 10, _hoisted_1);
833
+ }), 128))], 42, _hoisted_1);
735
834
  };
736
835
  }
737
- }), [["__scopeId", "data-v-e05489c9"]]);
836
+ }), [["__scopeId", "data-v-afef9198"]]);
738
837
  //#endregion
739
838
  export { GrTree_default as t };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrTree-B2_yW6g1.js","names":[],"sources":["../../../../src/components/GrTree/grTreeDataAdapter.ts","../../../../src/components/GrTree/grTreeInteractionContext.ts","../../../../src/components/GrTree/grTreeStore.ts","../../../../src/components/GrTree/GrTree.vue","../../../../src/components/GrTree/GrTree.vue"],"sourcesContent":["import type { GrTreeKey } from './grTreeTypes'\nimport type {\n GrTreeDataProps,\n GrTreePropsMap,\n} from './grTreeProps'\n\nconst DEFAULT_CHILDREN_KEY = 'children'\nconst DEFAULT_LABEL_KEY = 'label'\n\nexport type GrTreeDataAdapterOptions<T extends object> = Pick<GrTreeDataProps<T>, 'props' | 'nodeKey'>\n\nexport type GrTreeDataAdapter<T extends object> = {\n hasNodeKey: () => boolean\n getChildrenKey: () => string\n getLabelKey: () => string\n getLabel: (data: T) => string\n getChildren: (data: T) => T[]\n ensureChildren: (data: T) => T[]\n getNodeKey: (data: T, index: number, parentKey: GrTreeKey | undefined) => GrTreeKey\n getExplicitNodeKey: (data: T) => GrTreeKey | undefined\n}\n\nfunction isTreeKey(value: unknown): value is GrTreeKey {\n return typeof value === 'string' || typeof value === 'number'\n}\n\nfunction resolveMapValue(map: GrTreePropsMap | undefined, key: keyof GrTreePropsMap, fallback: string) {\n return map?.[key] ?? fallback\n}\n\nexport function createGrTreeDataAdapter<T extends Record<string, any> = any>(\n options: GrTreeDataAdapterOptions<T>,\n): GrTreeDataAdapter<T> {\n function hasNodeKey() {\n return options.nodeKey != null\n }\n\n function getChildrenKey() {\n return resolveMapValue(options.props, 'children', DEFAULT_CHILDREN_KEY)\n }\n\n function getLabelKey() {\n return resolveMapValue(options.props, 'label', DEFAULT_LABEL_KEY)\n }\n\n function getLabel(data: T): string {\n const key = getLabelKey() as keyof T\n const value = data[key]\n return value == null ? '' : String(value)\n }\n\n function getChildren(data: T): T[] {\n const key = getChildrenKey() as keyof T\n const value = data[key]\n return Array.isArray(value) ? (value as T[]) : []\n }\n\n function ensureChildren(data: T): T[] {\n const key = getChildrenKey()\n const value = (data as Record<string, unknown>)[key]\n if (Array.isArray(value))\n return value as T[]\n\n const children: T[] = []\n ;(data as Record<string, unknown>)[key] = children\n return children\n }\n\n function getExplicitNodeKey(data: T): GrTreeKey | undefined {\n if (options.nodeKey == null)\n return undefined\n\n const keyName = options.nodeKey as keyof T\n const value = data[keyName] as unknown\n return isTreeKey(value) ? value : undefined\n }\n\n function getNodeKey(data: T, index: number, parentKey: GrTreeKey | undefined): GrTreeKey {\n const explicitKey = getExplicitNodeKey(data)\n if (explicitKey != null)\n return explicitKey\n\n return parentKey == null ? index : `${String(parentKey)}:${index}`\n }\n\n return {\n hasNodeKey,\n getChildrenKey,\n getLabelKey,\n getLabel,\n getChildren,\n ensureChildren,\n getNodeKey,\n getExplicitNodeKey,\n }\n}","import type { Ref, ShallowRef } from 'vue'\nimport { ref, shallowRef } from 'vue'\nimport type {\n GrTreeAllowDropType,\n GrTreeKey,\n GrTreeNode,\n GrTreeNodeDropType,\n} from './grTreeTypes'\n\nexport type GrTreeDropTarget = {\n key: GrTreeKey\n type: GrTreeNodeDropType\n allowed: boolean\n}\n\nexport type GrTreeInteractionOptions<T> = {\n draggable?: boolean\n allowDrop?: (draggingNode: GrTreeNode<T>, dropNode: GrTreeNode<T>, type: GrTreeAllowDropType) => boolean\n allowDrag?: (draggingNode: GrTreeNode<T>) => boolean\n}\n\nexport type GrTreeInteractionEmitters<T> = {\n emitNodeClick: (data: T, node: GrTreeNode<T>) => void\n emitNodeExpand: (data: T, node: GrTreeNode<T>) => void\n emitNodeCollapse: (data: T, node: GrTreeNode<T>) => void\n emitNodeDrop: (draggingNode: GrTreeNode<T>, dropNode: GrTreeNode<T>, dropType: GrTreeNodeDropType) => void\n}\n\nexport type GrTreeInteractionContext<T> = {\n hoveredKey: Ref<GrTreeKey | undefined>\n /** Клавиша узла, держащего roving-фокус (единственный tabindex=0 во всём дереве). */\n focusedKey: Ref<GrTreeKey | undefined>\n draggingNode: ShallowRef<GrTreeNode<T> | null>\n dropTarget: ShallowRef<GrTreeDropTarget | null>\n canDrag: (node: GrTreeNode<T>) => boolean\n canDrop: (drag: GrTreeNode<T>, target: GrTreeNode<T>, type: GrTreeAllowDropType) => boolean\n resetDragState: () => void\n emitNodeClick: (data: T, node: GrTreeNode<T>) => void\n emitNodeExpand: (data: T, node: GrTreeNode<T>) => void\n emitNodeCollapse: (data: T, node: GrTreeNode<T>) => void\n emitNodeDrop: (draggingNode: GrTreeNode<T>, dropNode: GrTreeNode<T>, dropType: GrTreeNodeDropType) => void\n}\n\nexport function createGrTreeInteractionContext<T>(\n options: GrTreeInteractionOptions<T>,\n emitters: GrTreeInteractionEmitters<T>,\n): GrTreeInteractionContext<T> {\n const hoveredKey = ref<GrTreeKey | undefined>(undefined)\n const focusedKey = ref<GrTreeKey | undefined>(undefined)\n const draggingNode = shallowRef<GrTreeNode<T> | null>(null)\n const dropTarget = shallowRef<GrTreeDropTarget | null>(null)\n\n function canDrag(node: GrTreeNode<T>): boolean {\n if (!options.draggable)\n return false\n\n if (options.allowDrag)\n return options.allowDrag(node)\n\n return true\n }\n\n function canDrop(drag: GrTreeNode<T>, target: GrTreeNode<T>, type: GrTreeAllowDropType): boolean {\n if (!options.allowDrop)\n return true\n\n return options.allowDrop(drag, target, type)\n }\n\n function resetDragState() {\n draggingNode.value = null\n dropTarget.value = null\n }\n\n return {\n hoveredKey,\n focusedKey,\n draggingNode,\n dropTarget,\n canDrag,\n canDrop,\n resetDragState,\n ...emitters,\n }\n}","import type { ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from 'vue'\nimport { computed, ref, shallowRef, toValue, watch } from 'vue'\nimport type {\n GrTreeKey,\n GrTreeNode,\n GrTreeNodeDropType,\n GrTreeNodeTarget,\n} from './grTreeTypes'\nimport type { GrTreeDataAdapter } from './grTreeDataAdapter'\nimport type { GrTreeDataProps, GrTreeFilterNodeMethod } from './grTreeProps'\n\ntype TreeModel<T extends object> = {\n roots: GrTreeNode<T>[]\n byKey: Map<GrTreeKey, GrTreeNode<T>>\n byData: WeakMap<T, GrTreeNode<T>>\n}\n\ntype FilterInfo = {\n isActive: boolean\n subtreeHasMatch: Map<GrTreeKey, boolean>\n matchedKeys: Set<GrTreeKey>\n autoExpandKeys: Set<GrTreeKey>\n}\n\nexport type GrTreeStoreOptions<T extends object> = {\n data: MaybeRefOrGetter<GrTreeDataProps<T>['data']>\n defaultExpandedKeys?: MaybeRefOrGetter<GrTreeDataProps<T>['defaultExpandedKeys']>\n filterNodeMethod?: MaybeRefOrGetter<GrTreeFilterNodeMethod<T> | undefined>\n adapter: GrTreeDataAdapter<T>\n}\n\nexport type GrTreeStore<T extends object> = {\n filterValue: Ref<string>\n expandedKeys: ShallowRef<Set<GrTreeKey>>\n currentKey: Ref<GrTreeKey | undefined>\n treeModel: ComputedRef<TreeModel<T>>\n filterInfo: ComputedRef<FilterInfo>\n filter: (value: string) => void\n isExpandedKey: (key: GrTreeKey) => boolean\n setExpandedKey: (key: GrTreeKey, expanded: boolean) => void\n toggleExpand: (node: GrTreeNode<T>) => void\n setCurrentKey: (key?: GrTreeKey) => void\n getCurrentKey: () => GrTreeKey | undefined\n getCurrentNode: () => GrTreeNode<T> | undefined\n setCurrentNode: (node?: GrTreeNodeTarget<T>) => boolean\n getNode: (key: GrTreeKey) => GrTreeNode<T> | undefined\n canMoveNode: (node: GrTreeNodeTarget<T>, referenceNode: GrTreeNodeTarget<T>, dropType: GrTreeNodeDropType) => boolean\n moveNode: (node: GrTreeNodeTarget<T>, referenceNode: GrTreeNodeTarget<T>, dropType: GrTreeNodeDropType) => GrTreeNode<T> | undefined\n appendNode: (data: T, parent: GrTreeNodeTarget<T>) => GrTreeNode<T> | undefined\n removeNode: (node: GrTreeNodeTarget<T>) => boolean\n insertNodeBefore: (data: T, referenceNode: GrTreeNodeTarget<T>) => GrTreeNode<T> | undefined\n insertNodeAfter: (data: T, referenceNode: GrTreeNodeTarget<T>) => GrTreeNode<T> | undefined\n}\n\nexport function createGrTreeStore<T extends Record<string, any> = any>(\n options: GrTreeStoreOptions<T>,\n): GrTreeStore<T> {\n const filterValue = ref('')\n const expandedKeys = shallowRef<Set<GrTreeKey>>(new Set())\n const currentKey = ref<GrTreeKey | undefined>(undefined)\n const getData = () => toValue(options.data) ?? []\n const getFilterNodeMethod = () => toValue(options.filterNodeMethod)\n\n watch(\n () => toValue(options.defaultExpandedKeys),\n (keys) => {\n expandedKeys.value = new Set(keys ?? [])\n },\n { immediate: true },\n )\n\n const treeModel = computed<TreeModel<T>>(() => {\n const byKey = new Map<GrTreeKey, GrTreeNode<T>>()\n const byData = new WeakMap<T, GrTreeNode<T>>()\n\n const build = (items: T[], parent: GrTreeNode<T> | undefined, level: number): GrTreeNode<T>[] => {\n return items.map((item, index) => {\n const node: GrTreeNode<T> = {\n key: options.adapter.getNodeKey(item, index, parent?.key),\n label: options.adapter.getLabel(item),\n data: item,\n level,\n parent,\n childNodes: [],\n }\n\n byKey.set(node.key, node)\n byData.set(item, node)\n node.childNodes = build(options.adapter.getChildren(item), node, level + 1)\n\n return node\n })\n }\n\n return {\n roots: build(getData(), undefined, 1),\n byKey,\n byData,\n }\n })\n\n const filterInfo = computed<FilterInfo>(() => {\n const value = filterValue.value\n const isActive = value.trim().length > 0\n const valueLower = value.toLowerCase()\n const subtreeHasMatch = new Map<GrTreeKey, boolean>()\n const matchedKeys = new Set<GrTreeKey>()\n const autoExpandKeys = new Set<GrTreeKey>()\n\n if (!isActive) {\n return {\n isActive,\n subtreeHasMatch,\n matchedKeys,\n autoExpandKeys,\n }\n }\n\n const match = (node: GrTreeNode<T>): boolean => {\n const filterNodeMethod = getFilterNodeMethod()\n if (filterNodeMethod)\n return filterNodeMethod(value, node.data, node)\n\n return node.label.toLowerCase().includes(valueLower)\n }\n\n const walk = (nodes: GrTreeNode<T>[]): boolean => {\n let any = false\n\n for (const node of nodes) {\n const self = match(node)\n const childAny = walk(node.childNodes)\n const has = self || childAny\n\n subtreeHasMatch.set(node.key, has)\n\n if (self)\n matchedKeys.add(node.key)\n\n if (childAny)\n autoExpandKeys.add(node.key)\n\n any ||= has\n }\n\n return any\n }\n\n walk(treeModel.value.roots)\n\n return {\n isActive,\n subtreeHasMatch,\n matchedKeys,\n autoExpandKeys,\n }\n })\n\n function getNode(key: GrTreeKey) {\n return treeModel.value.byKey.get(key)\n }\n\n function findNodeByData(data: T): GrTreeNode<T> | undefined {\n return treeModel.value.byData.get(data)\n }\n\n function isTreeNode(target: GrTreeNodeTarget<T>): target is GrTreeNode<T> {\n return typeof target === 'object'\n && target !== null\n && 'key' in target\n && 'data' in target\n && 'childNodes' in target\n }\n\n function resolveNodeTarget(target?: GrTreeNodeTarget<T>): GrTreeNode<T> | undefined {\n if (target == null)\n return undefined\n\n if (typeof target === 'string' || typeof target === 'number')\n return getNode(target)\n\n if (isTreeNode(target))\n return getNode(target.key) ?? target\n\n const key = options.adapter.getExplicitNodeKey(target)\n if (key != null)\n return getNode(key)\n\n return findNodeByData(target)\n }\n\n function getNodeContainer(node: GrTreeNode<T>) {\n const items = node.parent ? options.adapter.ensureChildren(node.parent.data) : getData()\n\n let index = items.findIndex(item => item === node.data)\n if (index >= 0)\n return { items, index }\n\n const key = options.adapter.getExplicitNodeKey(node.data)\n if (key == null)\n return undefined\n\n index = items.findIndex(item => options.adapter.getExplicitNodeKey(item) === key)\n if (index < 0)\n return undefined\n\n return { items, index }\n }\n\n function isDescendantNode(ancestor: GrTreeNode<T>, node: GrTreeNode<T>) {\n let current = node.parent\n\n while (current) {\n if (current.key === ancestor.key)\n return true\n\n current = current.parent\n }\n\n return false\n }\n\n function canMoveNode(node: GrTreeNodeTarget<T>, referenceNode: GrTreeNodeTarget<T>, dropType: GrTreeNodeDropType) {\n const sourceNode = resolveNodeTarget(node)\n const targetNode = resolveNodeTarget(referenceNode)\n\n if (!sourceNode || !targetNode)\n return false\n\n if (sourceNode.key === targetNode.key)\n return false\n\n if (isDescendantNode(sourceNode, targetNode))\n return false\n\n const sourceContainer = getNodeContainer(sourceNode)\n if (!sourceContainer)\n return false\n\n if (dropType === 'inner')\n return true\n\n return Boolean(getNodeContainer(targetNode))\n }\n\n function sanitizeTreeState() {\n const byKey = treeModel.value.byKey\n\n if (currentKey.value != null && !byKey.has(currentKey.value))\n currentKey.value = undefined\n\n const nextExpandedKeys = new Set(Array.from(expandedKeys.value).filter(key => byKey.has(key)))\n if (nextExpandedKeys.size !== expandedKeys.value.size)\n expandedKeys.value = nextExpandedKeys\n }\n\n function isExpandedKey(key: GrTreeKey): boolean {\n return expandedKeys.value.has(key)\n }\n\n function setExpandedKey(key: GrTreeKey, expanded: boolean) {\n const next = new Set(expandedKeys.value)\n\n if (expanded)\n next.add(key)\n else\n next.delete(key)\n\n expandedKeys.value = next\n }\n\n function toggleExpand(node: GrTreeNode<T>) {\n setExpandedKey(node.key, !isExpandedKey(node.key))\n }\n\n function setCurrentKey(key?: GrTreeKey) {\n currentKey.value = key\n }\n\n function getCurrentKey() {\n return currentKey.value\n }\n\n function getCurrentNode() {\n const key = currentKey.value\n return key == null ? undefined : getNode(key)\n }\n\n function setCurrentNode(node?: GrTreeNodeTarget<T>) {\n if (node == null) {\n currentKey.value = undefined\n return true\n }\n\n const targetNode = resolveNodeTarget(node)\n if (!targetNode)\n return false\n\n currentKey.value = targetNode.key\n return true\n }\n\n function resolveInsertedNode(data: T) {\n const key = options.adapter.getExplicitNodeKey(data)\n if (key != null)\n return getNode(key)\n\n return findNodeByData(data)\n }\n\n function moveNode(node: GrTreeNodeTarget<T>, referenceNode: GrTreeNodeTarget<T>, dropType: GrTreeNodeDropType) {\n const sourceNode = resolveNodeTarget(node)\n const targetNode = resolveNodeTarget(referenceNode)\n\n if (!sourceNode || !targetNode)\n return undefined\n\n if (!canMoveNode(sourceNode, targetNode, dropType))\n return undefined\n\n const sourceContainer = getNodeContainer(sourceNode)\n if (!sourceContainer)\n return undefined\n\n let destinationItems: T[]\n let destinationIndex: number\n\n if (dropType === 'inner') {\n destinationItems = options.adapter.ensureChildren(targetNode.data)\n destinationIndex = destinationItems.length\n }\n else {\n const targetContainer = getNodeContainer(targetNode)\n if (!targetContainer)\n return undefined\n\n destinationItems = targetContainer.items\n destinationIndex = dropType === 'prev'\n ? targetContainer.index\n : targetContainer.index + 1\n }\n\n if (destinationItems === sourceContainer.items && sourceContainer.index < destinationIndex)\n destinationIndex -= 1\n\n const [movedData] = sourceContainer.items.splice(sourceContainer.index, 1)\n destinationItems.splice(destinationIndex, 0, movedData)\n\n if (dropType === 'inner')\n setExpandedKey(targetNode.key, true)\n\n sanitizeTreeState()\n return resolveInsertedNode(movedData)\n }\n\n function appendNode(data: T, parent: GrTreeNodeTarget<T>) {\n const parentNode = resolveNodeTarget(parent)\n if (!parentNode)\n return undefined\n\n options.adapter.ensureChildren(parentNode.data).push(data)\n setExpandedKey(parentNode.key, true)\n sanitizeTreeState()\n return resolveInsertedNode(data)\n }\n\n function removeNode(node: GrTreeNodeTarget<T>) {\n if (!options.adapter.hasNodeKey())\n return false\n\n const targetNode = resolveNodeTarget(node)\n if (!targetNode)\n return false\n\n const container = getNodeContainer(targetNode)\n if (!container)\n return false\n\n container.items.splice(container.index, 1)\n sanitizeTreeState()\n return true\n }\n\n function insertNodeBefore(data: T, referenceNode: GrTreeNodeTarget<T>) {\n const targetNode = resolveNodeTarget(referenceNode)\n if (!targetNode)\n return undefined\n\n const container = getNodeContainer(targetNode)\n if (!container)\n return undefined\n\n container.items.splice(container.index, 0, data)\n sanitizeTreeState()\n return resolveInsertedNode(data)\n }\n\n function insertNodeAfter(data: T, referenceNode: GrTreeNodeTarget<T>) {\n const targetNode = resolveNodeTarget(referenceNode)\n if (!targetNode)\n return undefined\n\n const container = getNodeContainer(targetNode)\n if (!container)\n return undefined\n\n container.items.splice(container.index + 1, 0, data)\n sanitizeTreeState()\n return resolveInsertedNode(data)\n }\n\n function filter(value: string) {\n filterValue.value = value\n }\n\n return {\n filterValue,\n expandedKeys,\n currentKey,\n treeModel,\n filterInfo,\n filter,\n isExpandedKey,\n setExpandedKey,\n toggleExpand,\n setCurrentKey,\n getCurrentKey,\n getCurrentNode,\n setCurrentNode,\n getNode,\n canMoveNode,\n moveNode,\n appendNode,\n removeNode,\n insertNodeBefore,\n insertNodeAfter,\n }\n}","<script setup lang=\"ts\" generic=\"T extends Record<string, any> = any\">\nimport { computed, nextTick, ref, watch } from 'vue'\nimport type {\n GrTreeAllowDropType,\n GrTreeInstance,\n GrTreeNode,\n GrTreeNodeDropType,\n} from './grTreeTypes'\nimport { createGrTreeDataAdapter } from './grTreeDataAdapter'\nimport { createGrTreeInteractionContext } from './grTreeInteractionContext'\nimport { createGrTreeStore } from './grTreeStore'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type {\n GrTreeBranchLineColor,\n GrTreeNodeClass,\n GrTreeProps,\n GrTreeVisibleRow,\n GrTreeVisibleTreeRow,\n} from './grTreeProps'\n\ndefineOptions({\n name: 'GrTree',\n})\n\nconst DEFAULT_BRANCH_LINE_COLOR = 'var(--gr-tree-branch-line-default-color, var(--brd))'\n\nconst props = withDefaults(defineProps<GrTreeProps<T>>(), {\n props: () => ({\n children: 'children',\n label: 'label',\n }),\n nodeKey: 'id' as any,\n defaultExpandedKeys: () => [],\n highlightCurrent: true,\n indent: 0,\n expandIcon: 'i-lucide-chevron-right',\n collapseIcon: 'i-lucide-chevron-right',\n toggleIconRotate: true,\n branchLine: false,\n branchLineColor: undefined,\n branchLineActiveColor: undefined,\n draggable: false,\n dragHandleIcon: 'i-lucide-grip-vertical',\n dragLabel: undefined,\n expandLabel: undefined,\n collapseLabel: undefined,\n rowClass: undefined,\n dragHandleClass: undefined,\n toggleClass: undefined,\n toggleIconClass: undefined,\n toggleSpacerClass: undefined,\n contentClass: undefined,\n internalRows: undefined,\n internalNested: false,\n internalStore: undefined,\n})\n\nconst emit = defineEmits<{\n (event: 'nodeClick', data: T, node: GrTreeNode<T>): void\n (event: 'nodeExpand', data: T, node: GrTreeNode<T>): void\n (event: 'nodeCollapse', data: T, node: GrTreeNode<T>): void\n (event: 'nodeDrop', draggingNode: GrTreeNode<T>, dropNode: GrTreeNode<T>, dropType: GrTreeNodeDropType): void\n}>()\n\ndefineSlots<{\n default?: (props: { node: GrTreeNode<T>; data: T }) => any\n}>()\n\nconst dataAdapter = createGrTreeDataAdapter(props)\nconst treeStore = props.internalStore ?? createGrTreeStore({\n adapter: dataAdapter,\n data: () => props.data,\n defaultExpandedKeys: () => props.defaultExpandedKeys,\n filterNodeMethod: () => props.filterNodeMethod,\n})\nconst interactionContext = props.internalInteractionContext ?? createGrTreeInteractionContext(props, {\n emitNodeClick: (data, node) => emit('nodeClick', data, node),\n emitNodeExpand: (data, node) => emit('nodeExpand', data, node),\n emitNodeCollapse: (data, node) => emit('nodeCollapse', data, node),\n emitNodeDrop: (draggingNode, dropNode, dropType) => emit('nodeDrop', draggingNode, dropNode, dropType),\n})\n\nconst treeProps = props as Readonly<GrTreeProps<T>>\n\nconst { t } = useGranularityTranslations()\nconst dragLabel = computed(() => treeProps.dragLabel ?? t('gr.tree.drag', 'Drag'))\nconst expandLabel = computed(() => treeProps.expandLabel ?? t('gr.tree.expand', 'Expand'))\nconst collapseLabel = computed(() => treeProps.collapseLabel ?? t('gr.tree.collapse', 'Collapse'))\nconst currentKey = treeStore.currentKey\nconst hoveredKey = interactionContext.hoveredKey\nconst focusedKey = interactionContext.focusedKey\nconst dropTarget = interactionContext.dropTarget\n\n// Корневой элемент дерева — область для делегированной клавиатуры (WAI-ARIA tree).\nconst treeRootEl = ref<HTMLElement | null>(null)\n\nconst visibleRows = computed<GrTreeVisibleTreeRow<T>[]>(() => {\n if (props.internalRows)\n return props.internalRows\n\n const { roots } = treeStore.treeModel.value\n const { isActive, subtreeHasMatch, matchedKeys, autoExpandKeys } = treeStore.filterInfo.value\n\n const walk = (nodes: GrTreeNode<T>[]): GrTreeVisibleTreeRow<T>[] => {\n const rows: GrTreeVisibleTreeRow<T>[] = []\n\n for (const node of nodes) {\n if (isActive && !subtreeHasMatch.get(node.key))\n continue\n\n const isLeaf = node.childNodes.length === 0\n const isMatched = matchedKeys.has(node.key)\n const isExpanded = treeStore.isExpandedKey(node.key) || (isActive && autoExpandKeys.has(node.key))\n\n rows.push({\n node,\n isExpanded,\n isLeaf,\n isMatched,\n children: isExpanded ? walk(node.childNodes) : [],\n })\n }\n\n return rows\n }\n\n return walk(roots)\n})\n\nfunction onRowClick(node: GrTreeNode<T>) {\n treeStore.setCurrentKey(node.key)\n focusedKey.value = node.key\n interactionContext.emitNodeClick(node.data, node)\n}\n\n// ————— Клавиатурная навигация по WAI-ARIA tree pattern (только корневой инстанс).\n\ntype FlatRow = { node: GrTreeNode<T>, isLeaf: boolean, isExpanded: boolean }\n\n// Плоский список видимых узлов в порядке отображения (для стрелочной навигации).\nconst flatVisibleRows = computed<FlatRow[]>(() => {\n const out: FlatRow[] = []\n const walk = (rows: GrTreeVisibleTreeRow<T>[]) => {\n for (const row of rows) {\n out.push({ node: row.node, isLeaf: row.isLeaf, isExpanded: row.isExpanded })\n if (row.children.length)\n walk(row.children)\n }\n }\n walk(visibleRows.value)\n return out\n})\n\n// Один узел на всё дерево держит tabindex=0 (roving). `focusedKey` — общий для\n// всех вложенных инстансов, поэтому проверка одинаковая на любом уровне.\nfunction isRovingItem(key: GrTreeNode<T>['key']): boolean {\n return focusedKey.value === key\n}\n\nfunction focusRow(key: GrTreeNode<T>['key']): void {\n focusedKey.value = key\n void nextTick(() => {\n const root = treeRootEl.value\n if (!root)\n return\n const target = String(key)\n const el = Array.from(root.querySelectorAll<HTMLElement>('[data-gr-tree-node-key]'))\n .find(node => node.getAttribute('data-gr-tree-node-key') === target)\n el?.focus()\n })\n}\n\nfunction onTreeKeydown(event: KeyboardEvent): void {\n // Обрабатывает только корневой инстанс; событие всплывает от строки к корню.\n if (props.internalNested)\n return\n\n const rows = flatVisibleRows.value\n if (rows.length === 0)\n return\n\n const idx = Math.max(0, rows.findIndex(r => r.node.key === focusedKey.value))\n const cur = rows[idx]\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n if (idx < rows.length - 1)\n focusRow(rows[idx + 1].node.key)\n break\n case 'ArrowUp':\n event.preventDefault()\n if (idx > 0)\n focusRow(rows[idx - 1].node.key)\n break\n case 'ArrowRight':\n event.preventDefault()\n if (!cur.isLeaf) {\n if (!cur.isExpanded)\n toggleExpand(cur.node)\n else if (idx < rows.length - 1)\n focusRow(rows[idx + 1].node.key)\n }\n break\n case 'ArrowLeft':\n event.preventDefault()\n if (!cur.isLeaf && cur.isExpanded)\n toggleExpand(cur.node)\n else if (cur.node.parent && rows.some(r => r.node.key === cur.node.parent!.key))\n focusRow(cur.node.parent.key)\n break\n case 'Home':\n event.preventDefault()\n focusRow(rows[0].node.key)\n break\n case 'End':\n event.preventDefault()\n focusRow(rows[rows.length - 1].node.key)\n break\n case 'Enter':\n case ' ':\n event.preventDefault()\n onRowClick(cur.node)\n break\n }\n}\n\n// Нормализация roving-фокуса: держим `focusedKey` на видимом узле, чтобы ровно\n// один treeitem всегда имел tabindex=0 (даже после сворачивания родителя). Только корень.\nfunction normalizeFocusedKey(): void {\n if (props.internalNested)\n return\n\n const rows = flatVisibleRows.value\n if (rows.length === 0) {\n focusedKey.value = undefined\n return\n }\n\n const stillVisible = focusedKey.value !== undefined && rows.some(r => r.node.key === focusedKey.value)\n if (stillVisible)\n return\n\n focusedKey.value = (currentKey.value != null && rows.some(r => r.node.key === currentKey.value))\n ? currentKey.value\n : rows[0].node.key\n}\n\nif (!props.internalNested) {\n // Синхронно до первого рендера — чтобы roving tabindex был проставлен сразу.\n normalizeFocusedKey()\n watch(flatVisibleRows, normalizeFocusedKey, { flush: 'sync' })\n}\n\nfunction onRowMouseEnter(node: GrTreeNode<T>) {\n hoveredKey.value = node.key\n}\n\nfunction onRowMouseLeave(node: GrTreeNode<T>) {\n if (hoveredKey.value === node.key)\n hoveredKey.value = undefined\n}\n\nfunction toggleExpand(node: GrTreeNode<T>) {\n const expanded = !treeStore.isExpandedKey(node.key)\n treeStore.toggleExpand(node)\n\n if (expanded)\n interactionContext.emitNodeExpand(node.data, node)\n else\n interactionContext.emitNodeCollapse(node.data, node)\n}\n\n// Drag & drop\nfunction canDrag(node: GrTreeNode<T>): boolean {\n return interactionContext.canDrag(node)\n}\n\nfunction shouldShowDragHandle(node: GrTreeNode<T>): boolean {\n return canDrag(node) && hoveredKey.value === node.key\n}\n\nfunction resolveDropType(evt: DragEvent, el: HTMLElement): GrTreeNodeDropType {\n const rect = el.getBoundingClientRect()\n const y = evt.clientY - rect.top\n const third = rect.height / 3\n if (y < third)\n return 'prev'\n if (y > third * 2)\n return 'next'\n return 'inner'\n}\n\nfunction canDrop(drag: GrTreeNode<T>, target: GrTreeNode<T>, type: GrTreeAllowDropType): boolean {\n return interactionContext.canDrop(drag, target, type)\n}\n\nfunction onDragStart(evt: DragEvent, node: GrTreeNode<T>) {\n if (!canDrag(node)) {\n evt.preventDefault()\n return\n }\n\n interactionContext.draggingNode.value = node\n interactionContext.dropTarget.value = null\n try {\n evt.dataTransfer?.setData('text/plain', String(node.key))\n }\n catch {\n // ignore\n }\n if (evt.dataTransfer)\n evt.dataTransfer.effectAllowed = 'move'\n}\n\nfunction onDragEnd() {\n interactionContext.resetDragState()\n}\n\nfunction onDragOver(evt: DragEvent, node: GrTreeNode<T>, rowEl: HTMLElement) {\n const drag = interactionContext.draggingNode.value\n if (!treeProps.draggable || !drag)\n return\n\n // required for `drop` to fire\n evt.preventDefault()\n\n const type = resolveDropType(evt, rowEl)\n const allowed = treeStore.canMoveNode(drag, node, type) && canDrop(drag, node, type)\n interactionContext.dropTarget.value = { key: node.key, type, allowed }\n if (evt.dataTransfer)\n evt.dataTransfer.dropEffect = allowed ? 'move' : 'none'\n}\n\nfunction onDrop(evt: DragEvent, node: GrTreeNode<T>) {\n const drag = interactionContext.draggingNode.value\n const target = interactionContext.dropTarget.value\n if (!treeProps.draggable || !drag || !target)\n return\n\n evt.preventDefault()\n\n if (target.key === node.key && target.allowed) {\n const movedNode = treeStore.moveNode(drag, node, target.type)\n if (movedNode) {\n const dropNode = treeStore.getNode(node.key) ?? node\n interactionContext.emitNodeDrop(movedNode, dropNode, target.type)\n }\n }\n\n interactionContext.resetDragState()\n}\n\nfunction filter(value: string) {\n treeStore.filter(value)\n}\n\nfunction resolveNodeClass(classValue: GrTreeNodeClass<T> | undefined, row: GrTreeVisibleRow<T>) {\n if (!classValue)\n return undefined\n\n return typeof classValue === 'function'\n ? classValue(row)\n : classValue\n}\n\nfunction resolveBranchLineColorValue(color: GrTreeBranchLineColor<T> | undefined, node: GrTreeNode<T>) {\n if (!color)\n return undefined\n\n return typeof color === 'function'\n ? color(node) ?? undefined\n : color\n}\n\nfunction isBranchLineActive(node: GrTreeNode<T>) {\n const selectedKey = currentKey.value\n\n if (selectedKey == null)\n return false\n\n if (node.key === selectedKey)\n return true\n\n return node.childNodes.some(child => child.key === selectedKey && !treeStore.isExpandedKey(child.key))\n}\n\nfunction resolveBranchLineColor(node: GrTreeNode<T>) {\n const defaultColor = resolveBranchLineColorValue(treeProps.branchLineColor, node) ?? DEFAULT_BRANCH_LINE_COLOR\n\n if (!isBranchLineActive(node))\n return defaultColor\n\n return resolveBranchLineColorValue(treeProps.branchLineActiveColor, node) ?? defaultColor\n}\n\nfunction resolveChildrenWrapStyle(row: GrTreeVisibleTreeRow<T>) {\n if (!treeProps.branchLine)\n return {\n }\n\n return {\n '--gr-tree-branch-line-color': resolveBranchLineColor(row.node),\n }\n}\n\ndefineExpose<GrTreeInstance<T>>({\n appendNode: treeStore.appendNode,\n filter,\n getCurrentNode: treeStore.getCurrentNode,\n setCurrentKey: treeStore.setCurrentKey,\n getCurrentKey: treeStore.getCurrentKey,\n getNode: treeStore.getNode,\n insertNodeAfter: treeStore.insertNodeAfter,\n insertNodeBefore: treeStore.insertNodeBefore,\n removeNode: treeStore.removeNode,\n setCurrentNode: treeStore.setCurrentNode,\n})\n</script>\n\n<template>\n <div\n ref=\"treeRootEl\"\n :data-gr-tree=\"props.internalNested ? undefined : ''\"\n :class=\"props.internalNested ? 'gr-tree__children' : 'gr-tree'\"\n :role=\"props.internalNested ? 'group' : 'tree'\"\n @keydown=\"onTreeKeydown\"\n >\n <div\n v-for=\"row in visibleRows\"\n :key=\"row.node.key\"\n data-gr-tree-node\n :data-gr-tree-node-key=\"row.node.key\"\n role=\"treeitem\"\n :aria-level=\"row.node.level\"\n :aria-expanded=\"row.isLeaf ? undefined : row.isExpanded\"\n :aria-selected=\"currentKey === row.node.key ? 'true' : 'false'\"\n :tabindex=\"isRovingItem(row.node.key) ? 0 : -1\"\n >\n <div\n data-gr-tree-row\n class=\"gr-tree__row py-2 px-2\"\n :class=\"[\n treeProps.highlightCurrent && currentKey === row.node.key ? 'gr-tree__row--current' : '',\n row.isMatched ? 'gr-tree__row--matched' : '',\n dropTarget?.key === row.node.key && dropTarget.allowed && dropTarget.type === 'inner' ? 'gr-tree__row--drop-inner' : '',\n dropTarget?.key === row.node.key && dropTarget.allowed && dropTarget.type === 'prev' ? 'gr-tree__row--drop-prev' : '',\n dropTarget?.key === row.node.key && dropTarget.allowed && dropTarget.type === 'next' ? 'gr-tree__row--drop-next' : '',\n resolveNodeClass(treeProps.rowClass, row),\n ]\"\n @click=\"onRowClick(row.node)\"\n @drop=\"onDrop($event, row.node)\"\n @dragover=\"onDragOver($event, row.node, $event.currentTarget as HTMLElement)\"\n @mouseenter=\"onRowMouseEnter(row.node)\"\n @mouseleave=\"onRowMouseLeave(row.node)\"\n >\n <button\n v-if=\"treeProps.draggable\"\n type=\"button\"\n data-gr-tree-drag-handle\n class=\"gr-tree__drag-handle\"\n :class=\"[\n shouldShowDragHandle(row.node) ? 'gr-tree__drag-handle--visible' : '',\n canDrag(row.node) ? '' : 'gr-tree__drag-handle--disabled',\n resolveNodeClass(treeProps.dragHandleClass, row),\n ]\"\n :aria-label=\"dragLabel\"\n :draggable=\"canDrag(row.node)\"\n @click.stop\n @mousedown.stop\n @dragstart=\"onDragStart($event, row.node)\"\n @dragend=\"onDragEnd\"\n >\n <span class=\"gr-tree__drag-icon\" :class=\"treeProps.dragHandleIcon\" />\n </button>\n\n <button\n v-if=\"!row.isLeaf\"\n data-gr-tree-toggle\n type=\"button\"\n class=\"gr-tree__toggle\"\n :class=\"resolveNodeClass(treeProps.toggleClass, row)\"\n :aria-label=\"row.isExpanded ? collapseLabel : expandLabel\"\n @click.stop=\"toggleExpand(row.node)\"\n >\n <span\n class=\"gr-tree__toggle-icon\"\n :class=\"[\n row.isExpanded ? treeProps.collapseIcon : treeProps.expandIcon,\n row.isExpanded && treeProps.toggleIconRotate ? 'gr-tree__toggle-icon--expanded' : '',\n resolveNodeClass(treeProps.toggleIconClass, row),\n ]\"\n />\n </button>\n <span\n v-else\n class=\"gr-tree__toggle-spacer\"\n :class=\"resolveNodeClass(treeProps.toggleSpacerClass, row)\"\n />\n\n <div class=\"gr-tree__content\" :class=\"resolveNodeClass(treeProps.contentClass, row)\">\n <slot\n :node=\"row.node\"\n :data=\"row.node.data\"\n >\n <span class=\"gr-tree__label\">{{ row.node.label }}</span>\n </slot>\n </div>\n </div>\n\n <div\n v-if=\"row.children.length\"\n class=\"gr-tree__children-wrap ml-6\"\n :class=\"treeProps.branchLine ? 'gr-tree__children-wrap--with-branch' : ''\"\n :style=\"resolveChildrenWrapStyle(row)\"\n >\n <GrTree\n v-bind=\"props\"\n :data=\"[]\"\n :internal-rows=\"row.children\"\n internal-nested\n :internal-store=\"treeStore\"\n :internal-interaction-context=\"interactionContext\"\n >\n <template #default=\"slotProps\">\n <slot v-bind=\"slotProps\">\n <span class=\"gr-tree__label\">{{ slotProps.node.label }}</span>\n </slot>\n </template>\n </GrTree>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.gr-tree {\n --gr-tree-gap: 2px;\n --gr-tree-children-pl: 10px;\n --gr-tree-row-min-height: 28px;\n --gr-tree-row-radius: 8px;\n --gr-tree-row-pr: 8px;\n --gr-tree-row-color: var(--fg);\n --gr-tree-row-hover-bg: color-mix(in srgb, var(--primary, #000) 10%, transparent);\n --gr-tree-row-current-bg: color-mix(in srgb, var(--primary, #000) 5%, transparent);\n --gr-tree-row-current-hover-bg: color-mix(in srgb, var(--primary, #000) 16%, transparent);\n --gr-tree-drag-handle-size: 24px;\n --gr-tree-drag-handle-mr: 0;\n --gr-tree-drag-handle-radius: 6px;\n --gr-tree-drag-handle-color: inherit;\n --gr-tree-drag-handle-opacity: 0.55;\n --gr-tree-drag-handle-hover-bg: color-mix(in srgb, var(--muted, #000) 22%, transparent);\n --gr-tree-drag-handle-hover-color: var(--gr-tree-drag-handle-color);\n --gr-tree-drag-handle-hover-opacity: 0.9;\n --gr-tree-drag-handle-disabled-opacity: 0.25;\n --gr-tree-toggle-size: 24px;\n --gr-tree-toggle-mr: 0;\n --gr-tree-toggle-radius: 6px;\n --gr-tree-toggle-color: inherit;\n --gr-tree-toggle-hover-bg: color-mix(in srgb, var(--muted, #000) 25%, transparent);\n --gr-tree-toggle-hover-color: var(--gr-tree-toggle-color);\n --gr-tree-icon-size: 16px;\n --gr-tree-content-gap: 8px;\n --gr-tree-branch-line-default-color: var(--gr-tree-row-current-bg);\n --gr-tree-branch-line-width: 2px;\n display: flex;\n flex-direction: column;\n gap: var(--gr-tree-gap);\n}\n\n.gr-tree__children {\n display: flex;\n flex-direction: column;\n gap: var(--gr-tree-gap);\n}\n\n.gr-tree__children-wrap {\n --gr-tree-branch-line-color: var(--gr-tree-branch-line-default-color);\n display: flex;\n flex-direction: column;\n gap: var(--gr-tree-gap);\n padding-left: var(--gr-tree-children-pl, 10px);\n border-left: var(--gr-tree-branch-line-width) solid transparent;\n}\n\n.gr-tree__children-wrap--with-branch {\n border-left-color: var(--gr-tree-branch-line-color, var(--gr-tree-branch-line-default-color));\n}\n\n.gr-tree__row {\n position: relative;\n display: flex;\n align-items: center;\n min-height: var(--gr-tree-row-min-height);\n border-radius: var(--gr-tree-row-radius);\n padding-right: var(--gr-tree-row-pr);\n cursor: default;\n user-select: none;\n outline: none;\n color: var(--gr-tree-row-color);\n}\n\n.gr-tree__row:hover {\n background: var(--gr-tree-row-hover-bg);\n}\n\n[data-gr-tree-node] {\n outline: none;\n}\n\n[data-gr-tree-node]:focus-visible > .gr-tree__row {\n outline: 2px solid var(--primary, #000);\n outline-offset: -2px;\n}\n\n.gr-tree__row--current {\n background: var(--gr-tree-row-current-bg);\n}\n\n.gr-tree__row--current:hover {\n background: var(--gr-tree-row-current-hover-bg);\n}\n\n.gr-tree__row--matched .gr-tree__label {\n font-weight: 600;\n}\n\n.gr-tree__drag-handle {\n width: var(--gr-tree-drag-handle-size);\n height: var(--gr-tree-drag-handle-size);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: var(--gr-tree-drag-handle-mr);\n border-radius: var(--gr-tree-drag-handle-radius);\n color: var(--gr-tree-drag-handle-color);\n cursor: grab;\n visibility: hidden;\n pointer-events: none;\n opacity: 0;\n}\n\n.gr-tree__drag-handle--visible {\n visibility: visible;\n pointer-events: auto;\n opacity: var(--gr-tree-drag-handle-opacity);\n}\n\n.gr-tree__drag-handle:hover {\n background: var(--gr-tree-drag-handle-hover-bg);\n color: var(--gr-tree-drag-handle-hover-color);\n opacity: var(--gr-tree-drag-handle-hover-opacity);\n}\n\n.gr-tree__drag-handle:active {\n cursor: grabbing;\n}\n\n.gr-tree__drag-handle--disabled {\n cursor: default;\n opacity: var(--gr-tree-drag-handle-disabled-opacity);\n}\n\n.gr-tree__drag-icon {\n width: var(--gr-tree-icon-size);\n height: var(--gr-tree-icon-size);\n}\n\n.gr-tree__toggle {\n width: var(--gr-tree-toggle-size);\n height: var(--gr-tree-toggle-size);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: var(--gr-tree-toggle-mr);\n border-radius: var(--gr-tree-toggle-radius);\n color: var(--gr-tree-toggle-color);\n}\n\n.gr-tree__toggle:hover {\n background: var(--gr-tree-toggle-hover-bg);\n color: var(--gr-tree-toggle-hover-color);\n}\n\n.gr-tree__toggle-icon {\n width: var(--gr-tree-icon-size);\n height: var(--gr-tree-icon-size);\n transition: transform 120ms ease;\n}\n\n.gr-tree__toggle-icon--expanded {\n transform: rotate(90deg);\n}\n\n.gr-tree__toggle-spacer {\n width: var(--gr-tree-toggle-size);\n height: var(--gr-tree-toggle-size);\n margin-right: var(--gr-tree-toggle-mr);\n display: inline-block;\n}\n\n.gr-tree__content {\n min-width: 0;\n display: flex;\n align-items: center;\n gap: var(--gr-tree-content-gap);\n}\n\n.gr-tree__label {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.gr-tree__row--drop-inner {\n outline: 2px solid color-mix(in srgb, var(--primary, #000) 40%, transparent);\n}\n\n.gr-tree__row--drop-prev::before,\n.gr-tree__row--drop-next::after {\n content: '';\n position: absolute;\n left: 8px;\n right: 8px;\n height: 2px;\n background: color-mix(in srgb, var(--primary, #000) 55%, transparent);\n}\n\n.gr-tree__row--drop-prev::before {\n top: 2px;\n}\n\n.gr-tree__row--drop-next::after {\n bottom: 2px;\n}\n</style>\n","<script setup lang=\"ts\" generic=\"T extends Record<string, any> = any\">\nimport { computed, nextTick, ref, watch } from 'vue'\nimport type {\n GrTreeAllowDropType,\n GrTreeInstance,\n GrTreeNode,\n GrTreeNodeDropType,\n} from './grTreeTypes'\nimport { createGrTreeDataAdapter } from './grTreeDataAdapter'\nimport { createGrTreeInteractionContext } from './grTreeInteractionContext'\nimport { createGrTreeStore } from './grTreeStore'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type {\n GrTreeBranchLineColor,\n GrTreeNodeClass,\n GrTreeProps,\n GrTreeVisibleRow,\n GrTreeVisibleTreeRow,\n} from './grTreeProps'\n\ndefineOptions({\n name: 'GrTree',\n})\n\nconst DEFAULT_BRANCH_LINE_COLOR = 'var(--gr-tree-branch-line-default-color, var(--brd))'\n\nconst props = withDefaults(defineProps<GrTreeProps<T>>(), {\n props: () => ({\n children: 'children',\n label: 'label',\n }),\n nodeKey: 'id' as any,\n defaultExpandedKeys: () => [],\n highlightCurrent: true,\n indent: 0,\n expandIcon: 'i-lucide-chevron-right',\n collapseIcon: 'i-lucide-chevron-right',\n toggleIconRotate: true,\n branchLine: false,\n branchLineColor: undefined,\n branchLineActiveColor: undefined,\n draggable: false,\n dragHandleIcon: 'i-lucide-grip-vertical',\n dragLabel: undefined,\n expandLabel: undefined,\n collapseLabel: undefined,\n rowClass: undefined,\n dragHandleClass: undefined,\n toggleClass: undefined,\n toggleIconClass: undefined,\n toggleSpacerClass: undefined,\n contentClass: undefined,\n internalRows: undefined,\n internalNested: false,\n internalStore: undefined,\n})\n\nconst emit = defineEmits<{\n (event: 'nodeClick', data: T, node: GrTreeNode<T>): void\n (event: 'nodeExpand', data: T, node: GrTreeNode<T>): void\n (event: 'nodeCollapse', data: T, node: GrTreeNode<T>): void\n (event: 'nodeDrop', draggingNode: GrTreeNode<T>, dropNode: GrTreeNode<T>, dropType: GrTreeNodeDropType): void\n}>()\n\ndefineSlots<{\n default?: (props: { node: GrTreeNode<T>; data: T }) => any\n}>()\n\nconst dataAdapter = createGrTreeDataAdapter(props)\nconst treeStore = props.internalStore ?? createGrTreeStore({\n adapter: dataAdapter,\n data: () => props.data,\n defaultExpandedKeys: () => props.defaultExpandedKeys,\n filterNodeMethod: () => props.filterNodeMethod,\n})\nconst interactionContext = props.internalInteractionContext ?? createGrTreeInteractionContext(props, {\n emitNodeClick: (data, node) => emit('nodeClick', data, node),\n emitNodeExpand: (data, node) => emit('nodeExpand', data, node),\n emitNodeCollapse: (data, node) => emit('nodeCollapse', data, node),\n emitNodeDrop: (draggingNode, dropNode, dropType) => emit('nodeDrop', draggingNode, dropNode, dropType),\n})\n\nconst treeProps = props as Readonly<GrTreeProps<T>>\n\nconst { t } = useGranularityTranslations()\nconst dragLabel = computed(() => treeProps.dragLabel ?? t('gr.tree.drag', 'Drag'))\nconst expandLabel = computed(() => treeProps.expandLabel ?? t('gr.tree.expand', 'Expand'))\nconst collapseLabel = computed(() => treeProps.collapseLabel ?? t('gr.tree.collapse', 'Collapse'))\nconst currentKey = treeStore.currentKey\nconst hoveredKey = interactionContext.hoveredKey\nconst focusedKey = interactionContext.focusedKey\nconst dropTarget = interactionContext.dropTarget\n\n// Корневой элемент дерева — область для делегированной клавиатуры (WAI-ARIA tree).\nconst treeRootEl = ref<HTMLElement | null>(null)\n\nconst visibleRows = computed<GrTreeVisibleTreeRow<T>[]>(() => {\n if (props.internalRows)\n return props.internalRows\n\n const { roots } = treeStore.treeModel.value\n const { isActive, subtreeHasMatch, matchedKeys, autoExpandKeys } = treeStore.filterInfo.value\n\n const walk = (nodes: GrTreeNode<T>[]): GrTreeVisibleTreeRow<T>[] => {\n const rows: GrTreeVisibleTreeRow<T>[] = []\n\n for (const node of nodes) {\n if (isActive && !subtreeHasMatch.get(node.key))\n continue\n\n const isLeaf = node.childNodes.length === 0\n const isMatched = matchedKeys.has(node.key)\n const isExpanded = treeStore.isExpandedKey(node.key) || (isActive && autoExpandKeys.has(node.key))\n\n rows.push({\n node,\n isExpanded,\n isLeaf,\n isMatched,\n children: isExpanded ? walk(node.childNodes) : [],\n })\n }\n\n return rows\n }\n\n return walk(roots)\n})\n\nfunction onRowClick(node: GrTreeNode<T>) {\n treeStore.setCurrentKey(node.key)\n focusedKey.value = node.key\n interactionContext.emitNodeClick(node.data, node)\n}\n\n// ————— Клавиатурная навигация по WAI-ARIA tree pattern (только корневой инстанс).\n\ntype FlatRow = { node: GrTreeNode<T>, isLeaf: boolean, isExpanded: boolean }\n\n// Плоский список видимых узлов в порядке отображения (для стрелочной навигации).\nconst flatVisibleRows = computed<FlatRow[]>(() => {\n const out: FlatRow[] = []\n const walk = (rows: GrTreeVisibleTreeRow<T>[]) => {\n for (const row of rows) {\n out.push({ node: row.node, isLeaf: row.isLeaf, isExpanded: row.isExpanded })\n if (row.children.length)\n walk(row.children)\n }\n }\n walk(visibleRows.value)\n return out\n})\n\n// Один узел на всё дерево держит tabindex=0 (roving). `focusedKey` — общий для\n// всех вложенных инстансов, поэтому проверка одинаковая на любом уровне.\nfunction isRovingItem(key: GrTreeNode<T>['key']): boolean {\n return focusedKey.value === key\n}\n\nfunction focusRow(key: GrTreeNode<T>['key']): void {\n focusedKey.value = key\n void nextTick(() => {\n const root = treeRootEl.value\n if (!root)\n return\n const target = String(key)\n const el = Array.from(root.querySelectorAll<HTMLElement>('[data-gr-tree-node-key]'))\n .find(node => node.getAttribute('data-gr-tree-node-key') === target)\n el?.focus()\n })\n}\n\nfunction onTreeKeydown(event: KeyboardEvent): void {\n // Обрабатывает только корневой инстанс; событие всплывает от строки к корню.\n if (props.internalNested)\n return\n\n const rows = flatVisibleRows.value\n if (rows.length === 0)\n return\n\n const idx = Math.max(0, rows.findIndex(r => r.node.key === focusedKey.value))\n const cur = rows[idx]\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n if (idx < rows.length - 1)\n focusRow(rows[idx + 1].node.key)\n break\n case 'ArrowUp':\n event.preventDefault()\n if (idx > 0)\n focusRow(rows[idx - 1].node.key)\n break\n case 'ArrowRight':\n event.preventDefault()\n if (!cur.isLeaf) {\n if (!cur.isExpanded)\n toggleExpand(cur.node)\n else if (idx < rows.length - 1)\n focusRow(rows[idx + 1].node.key)\n }\n break\n case 'ArrowLeft':\n event.preventDefault()\n if (!cur.isLeaf && cur.isExpanded)\n toggleExpand(cur.node)\n else if (cur.node.parent && rows.some(r => r.node.key === cur.node.parent!.key))\n focusRow(cur.node.parent.key)\n break\n case 'Home':\n event.preventDefault()\n focusRow(rows[0].node.key)\n break\n case 'End':\n event.preventDefault()\n focusRow(rows[rows.length - 1].node.key)\n break\n case 'Enter':\n case ' ':\n event.preventDefault()\n onRowClick(cur.node)\n break\n }\n}\n\n// Нормализация roving-фокуса: держим `focusedKey` на видимом узле, чтобы ровно\n// один treeitem всегда имел tabindex=0 (даже после сворачивания родителя). Только корень.\nfunction normalizeFocusedKey(): void {\n if (props.internalNested)\n return\n\n const rows = flatVisibleRows.value\n if (rows.length === 0) {\n focusedKey.value = undefined\n return\n }\n\n const stillVisible = focusedKey.value !== undefined && rows.some(r => r.node.key === focusedKey.value)\n if (stillVisible)\n return\n\n focusedKey.value = (currentKey.value != null && rows.some(r => r.node.key === currentKey.value))\n ? currentKey.value\n : rows[0].node.key\n}\n\nif (!props.internalNested) {\n // Синхронно до первого рендера — чтобы roving tabindex был проставлен сразу.\n normalizeFocusedKey()\n watch(flatVisibleRows, normalizeFocusedKey, { flush: 'sync' })\n}\n\nfunction onRowMouseEnter(node: GrTreeNode<T>) {\n hoveredKey.value = node.key\n}\n\nfunction onRowMouseLeave(node: GrTreeNode<T>) {\n if (hoveredKey.value === node.key)\n hoveredKey.value = undefined\n}\n\nfunction toggleExpand(node: GrTreeNode<T>) {\n const expanded = !treeStore.isExpandedKey(node.key)\n treeStore.toggleExpand(node)\n\n if (expanded)\n interactionContext.emitNodeExpand(node.data, node)\n else\n interactionContext.emitNodeCollapse(node.data, node)\n}\n\n// Drag & drop\nfunction canDrag(node: GrTreeNode<T>): boolean {\n return interactionContext.canDrag(node)\n}\n\nfunction shouldShowDragHandle(node: GrTreeNode<T>): boolean {\n return canDrag(node) && hoveredKey.value === node.key\n}\n\nfunction resolveDropType(evt: DragEvent, el: HTMLElement): GrTreeNodeDropType {\n const rect = el.getBoundingClientRect()\n const y = evt.clientY - rect.top\n const third = rect.height / 3\n if (y < third)\n return 'prev'\n if (y > third * 2)\n return 'next'\n return 'inner'\n}\n\nfunction canDrop(drag: GrTreeNode<T>, target: GrTreeNode<T>, type: GrTreeAllowDropType): boolean {\n return interactionContext.canDrop(drag, target, type)\n}\n\nfunction onDragStart(evt: DragEvent, node: GrTreeNode<T>) {\n if (!canDrag(node)) {\n evt.preventDefault()\n return\n }\n\n interactionContext.draggingNode.value = node\n interactionContext.dropTarget.value = null\n try {\n evt.dataTransfer?.setData('text/plain', String(node.key))\n }\n catch {\n // ignore\n }\n if (evt.dataTransfer)\n evt.dataTransfer.effectAllowed = 'move'\n}\n\nfunction onDragEnd() {\n interactionContext.resetDragState()\n}\n\nfunction onDragOver(evt: DragEvent, node: GrTreeNode<T>, rowEl: HTMLElement) {\n const drag = interactionContext.draggingNode.value\n if (!treeProps.draggable || !drag)\n return\n\n // required for `drop` to fire\n evt.preventDefault()\n\n const type = resolveDropType(evt, rowEl)\n const allowed = treeStore.canMoveNode(drag, node, type) && canDrop(drag, node, type)\n interactionContext.dropTarget.value = { key: node.key, type, allowed }\n if (evt.dataTransfer)\n evt.dataTransfer.dropEffect = allowed ? 'move' : 'none'\n}\n\nfunction onDrop(evt: DragEvent, node: GrTreeNode<T>) {\n const drag = interactionContext.draggingNode.value\n const target = interactionContext.dropTarget.value\n if (!treeProps.draggable || !drag || !target)\n return\n\n evt.preventDefault()\n\n if (target.key === node.key && target.allowed) {\n const movedNode = treeStore.moveNode(drag, node, target.type)\n if (movedNode) {\n const dropNode = treeStore.getNode(node.key) ?? node\n interactionContext.emitNodeDrop(movedNode, dropNode, target.type)\n }\n }\n\n interactionContext.resetDragState()\n}\n\nfunction filter(value: string) {\n treeStore.filter(value)\n}\n\nfunction resolveNodeClass(classValue: GrTreeNodeClass<T> | undefined, row: GrTreeVisibleRow<T>) {\n if (!classValue)\n return undefined\n\n return typeof classValue === 'function'\n ? classValue(row)\n : classValue\n}\n\nfunction resolveBranchLineColorValue(color: GrTreeBranchLineColor<T> | undefined, node: GrTreeNode<T>) {\n if (!color)\n return undefined\n\n return typeof color === 'function'\n ? color(node) ?? undefined\n : color\n}\n\nfunction isBranchLineActive(node: GrTreeNode<T>) {\n const selectedKey = currentKey.value\n\n if (selectedKey == null)\n return false\n\n if (node.key === selectedKey)\n return true\n\n return node.childNodes.some(child => child.key === selectedKey && !treeStore.isExpandedKey(child.key))\n}\n\nfunction resolveBranchLineColor(node: GrTreeNode<T>) {\n const defaultColor = resolveBranchLineColorValue(treeProps.branchLineColor, node) ?? DEFAULT_BRANCH_LINE_COLOR\n\n if (!isBranchLineActive(node))\n return defaultColor\n\n return resolveBranchLineColorValue(treeProps.branchLineActiveColor, node) ?? defaultColor\n}\n\nfunction resolveChildrenWrapStyle(row: GrTreeVisibleTreeRow<T>) {\n if (!treeProps.branchLine)\n return {\n }\n\n return {\n '--gr-tree-branch-line-color': resolveBranchLineColor(row.node),\n }\n}\n\ndefineExpose<GrTreeInstance<T>>({\n appendNode: treeStore.appendNode,\n filter,\n getCurrentNode: treeStore.getCurrentNode,\n setCurrentKey: treeStore.setCurrentKey,\n getCurrentKey: treeStore.getCurrentKey,\n getNode: treeStore.getNode,\n insertNodeAfter: treeStore.insertNodeAfter,\n insertNodeBefore: treeStore.insertNodeBefore,\n removeNode: treeStore.removeNode,\n setCurrentNode: treeStore.setCurrentNode,\n})\n</script>\n\n<template>\n <div\n ref=\"treeRootEl\"\n :data-gr-tree=\"props.internalNested ? undefined : ''\"\n :class=\"props.internalNested ? 'gr-tree__children' : 'gr-tree'\"\n :role=\"props.internalNested ? 'group' : 'tree'\"\n @keydown=\"onTreeKeydown\"\n >\n <div\n v-for=\"row in visibleRows\"\n :key=\"row.node.key\"\n data-gr-tree-node\n :data-gr-tree-node-key=\"row.node.key\"\n role=\"treeitem\"\n :aria-level=\"row.node.level\"\n :aria-expanded=\"row.isLeaf ? undefined : row.isExpanded\"\n :aria-selected=\"currentKey === row.node.key ? 'true' : 'false'\"\n :tabindex=\"isRovingItem(row.node.key) ? 0 : -1\"\n >\n <div\n data-gr-tree-row\n class=\"gr-tree__row py-2 px-2\"\n :class=\"[\n treeProps.highlightCurrent && currentKey === row.node.key ? 'gr-tree__row--current' : '',\n row.isMatched ? 'gr-tree__row--matched' : '',\n dropTarget?.key === row.node.key && dropTarget.allowed && dropTarget.type === 'inner' ? 'gr-tree__row--drop-inner' : '',\n dropTarget?.key === row.node.key && dropTarget.allowed && dropTarget.type === 'prev' ? 'gr-tree__row--drop-prev' : '',\n dropTarget?.key === row.node.key && dropTarget.allowed && dropTarget.type === 'next' ? 'gr-tree__row--drop-next' : '',\n resolveNodeClass(treeProps.rowClass, row),\n ]\"\n @click=\"onRowClick(row.node)\"\n @drop=\"onDrop($event, row.node)\"\n @dragover=\"onDragOver($event, row.node, $event.currentTarget as HTMLElement)\"\n @mouseenter=\"onRowMouseEnter(row.node)\"\n @mouseleave=\"onRowMouseLeave(row.node)\"\n >\n <button\n v-if=\"treeProps.draggable\"\n type=\"button\"\n data-gr-tree-drag-handle\n class=\"gr-tree__drag-handle\"\n :class=\"[\n shouldShowDragHandle(row.node) ? 'gr-tree__drag-handle--visible' : '',\n canDrag(row.node) ? '' : 'gr-tree__drag-handle--disabled',\n resolveNodeClass(treeProps.dragHandleClass, row),\n ]\"\n :aria-label=\"dragLabel\"\n :draggable=\"canDrag(row.node)\"\n @click.stop\n @mousedown.stop\n @dragstart=\"onDragStart($event, row.node)\"\n @dragend=\"onDragEnd\"\n >\n <span class=\"gr-tree__drag-icon\" :class=\"treeProps.dragHandleIcon\" />\n </button>\n\n <button\n v-if=\"!row.isLeaf\"\n data-gr-tree-toggle\n type=\"button\"\n class=\"gr-tree__toggle\"\n :class=\"resolveNodeClass(treeProps.toggleClass, row)\"\n :aria-label=\"row.isExpanded ? collapseLabel : expandLabel\"\n @click.stop=\"toggleExpand(row.node)\"\n >\n <span\n class=\"gr-tree__toggle-icon\"\n :class=\"[\n row.isExpanded ? treeProps.collapseIcon : treeProps.expandIcon,\n row.isExpanded && treeProps.toggleIconRotate ? 'gr-tree__toggle-icon--expanded' : '',\n resolveNodeClass(treeProps.toggleIconClass, row),\n ]\"\n />\n </button>\n <span\n v-else\n class=\"gr-tree__toggle-spacer\"\n :class=\"resolveNodeClass(treeProps.toggleSpacerClass, row)\"\n />\n\n <div class=\"gr-tree__content\" :class=\"resolveNodeClass(treeProps.contentClass, row)\">\n <slot\n :node=\"row.node\"\n :data=\"row.node.data\"\n >\n <span class=\"gr-tree__label\">{{ row.node.label }}</span>\n </slot>\n </div>\n </div>\n\n <div\n v-if=\"row.children.length\"\n class=\"gr-tree__children-wrap ml-6\"\n :class=\"treeProps.branchLine ? 'gr-tree__children-wrap--with-branch' : ''\"\n :style=\"resolveChildrenWrapStyle(row)\"\n >\n <GrTree\n v-bind=\"props\"\n :data=\"[]\"\n :internal-rows=\"row.children\"\n internal-nested\n :internal-store=\"treeStore\"\n :internal-interaction-context=\"interactionContext\"\n >\n <template #default=\"slotProps\">\n <slot v-bind=\"slotProps\">\n <span class=\"gr-tree__label\">{{ slotProps.node.label }}</span>\n </slot>\n </template>\n </GrTree>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.gr-tree {\n --gr-tree-gap: 2px;\n --gr-tree-children-pl: 10px;\n --gr-tree-row-min-height: 28px;\n --gr-tree-row-radius: 8px;\n --gr-tree-row-pr: 8px;\n --gr-tree-row-color: var(--fg);\n --gr-tree-row-hover-bg: color-mix(in srgb, var(--primary, #000) 10%, transparent);\n --gr-tree-row-current-bg: color-mix(in srgb, var(--primary, #000) 5%, transparent);\n --gr-tree-row-current-hover-bg: color-mix(in srgb, var(--primary, #000) 16%, transparent);\n --gr-tree-drag-handle-size: 24px;\n --gr-tree-drag-handle-mr: 0;\n --gr-tree-drag-handle-radius: 6px;\n --gr-tree-drag-handle-color: inherit;\n --gr-tree-drag-handle-opacity: 0.55;\n --gr-tree-drag-handle-hover-bg: color-mix(in srgb, var(--muted, #000) 22%, transparent);\n --gr-tree-drag-handle-hover-color: var(--gr-tree-drag-handle-color);\n --gr-tree-drag-handle-hover-opacity: 0.9;\n --gr-tree-drag-handle-disabled-opacity: 0.25;\n --gr-tree-toggle-size: 24px;\n --gr-tree-toggle-mr: 0;\n --gr-tree-toggle-radius: 6px;\n --gr-tree-toggle-color: inherit;\n --gr-tree-toggle-hover-bg: color-mix(in srgb, var(--muted, #000) 25%, transparent);\n --gr-tree-toggle-hover-color: var(--gr-tree-toggle-color);\n --gr-tree-icon-size: 16px;\n --gr-tree-content-gap: 8px;\n --gr-tree-branch-line-default-color: var(--gr-tree-row-current-bg);\n --gr-tree-branch-line-width: 2px;\n display: flex;\n flex-direction: column;\n gap: var(--gr-tree-gap);\n}\n\n.gr-tree__children {\n display: flex;\n flex-direction: column;\n gap: var(--gr-tree-gap);\n}\n\n.gr-tree__children-wrap {\n --gr-tree-branch-line-color: var(--gr-tree-branch-line-default-color);\n display: flex;\n flex-direction: column;\n gap: var(--gr-tree-gap);\n padding-left: var(--gr-tree-children-pl, 10px);\n border-left: var(--gr-tree-branch-line-width) solid transparent;\n}\n\n.gr-tree__children-wrap--with-branch {\n border-left-color: var(--gr-tree-branch-line-color, var(--gr-tree-branch-line-default-color));\n}\n\n.gr-tree__row {\n position: relative;\n display: flex;\n align-items: center;\n min-height: var(--gr-tree-row-min-height);\n border-radius: var(--gr-tree-row-radius);\n padding-right: var(--gr-tree-row-pr);\n cursor: default;\n user-select: none;\n outline: none;\n color: var(--gr-tree-row-color);\n}\n\n.gr-tree__row:hover {\n background: var(--gr-tree-row-hover-bg);\n}\n\n[data-gr-tree-node] {\n outline: none;\n}\n\n[data-gr-tree-node]:focus-visible > .gr-tree__row {\n outline: 2px solid var(--primary, #000);\n outline-offset: -2px;\n}\n\n.gr-tree__row--current {\n background: var(--gr-tree-row-current-bg);\n}\n\n.gr-tree__row--current:hover {\n background: var(--gr-tree-row-current-hover-bg);\n}\n\n.gr-tree__row--matched .gr-tree__label {\n font-weight: 600;\n}\n\n.gr-tree__drag-handle {\n width: var(--gr-tree-drag-handle-size);\n height: var(--gr-tree-drag-handle-size);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: var(--gr-tree-drag-handle-mr);\n border-radius: var(--gr-tree-drag-handle-radius);\n color: var(--gr-tree-drag-handle-color);\n cursor: grab;\n visibility: hidden;\n pointer-events: none;\n opacity: 0;\n}\n\n.gr-tree__drag-handle--visible {\n visibility: visible;\n pointer-events: auto;\n opacity: var(--gr-tree-drag-handle-opacity);\n}\n\n.gr-tree__drag-handle:hover {\n background: var(--gr-tree-drag-handle-hover-bg);\n color: var(--gr-tree-drag-handle-hover-color);\n opacity: var(--gr-tree-drag-handle-hover-opacity);\n}\n\n.gr-tree__drag-handle:active {\n cursor: grabbing;\n}\n\n.gr-tree__drag-handle--disabled {\n cursor: default;\n opacity: var(--gr-tree-drag-handle-disabled-opacity);\n}\n\n.gr-tree__drag-icon {\n width: var(--gr-tree-icon-size);\n height: var(--gr-tree-icon-size);\n}\n\n.gr-tree__toggle {\n width: var(--gr-tree-toggle-size);\n height: var(--gr-tree-toggle-size);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: var(--gr-tree-toggle-mr);\n border-radius: var(--gr-tree-toggle-radius);\n color: var(--gr-tree-toggle-color);\n}\n\n.gr-tree__toggle:hover {\n background: var(--gr-tree-toggle-hover-bg);\n color: var(--gr-tree-toggle-hover-color);\n}\n\n.gr-tree__toggle-icon {\n width: var(--gr-tree-icon-size);\n height: var(--gr-tree-icon-size);\n transition: transform 120ms ease;\n}\n\n.gr-tree__toggle-icon--expanded {\n transform: rotate(90deg);\n}\n\n.gr-tree__toggle-spacer {\n width: var(--gr-tree-toggle-size);\n height: var(--gr-tree-toggle-size);\n margin-right: var(--gr-tree-toggle-mr);\n display: inline-block;\n}\n\n.gr-tree__content {\n min-width: 0;\n display: flex;\n align-items: center;\n gap: var(--gr-tree-content-gap);\n}\n\n.gr-tree__label {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.gr-tree__row--drop-inner {\n outline: 2px solid color-mix(in srgb, var(--primary, #000) 40%, transparent);\n}\n\n.gr-tree__row--drop-prev::before,\n.gr-tree__row--drop-next::after {\n content: '';\n position: absolute;\n left: 8px;\n right: 8px;\n height: 2px;\n background: color-mix(in srgb, var(--primary, #000) 55%, transparent);\n}\n\n.gr-tree__row--drop-prev::before {\n top: 2px;\n}\n\n.gr-tree__row--drop-next::after {\n bottom: 2px;\n}\n</style>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrTree_default } from "./chunks/GrTree-D3ODe2dB.js";
2
- import { n as grTreeSafelist, t as grTreeConfig } from "../../chunks/config-DpqOnJiz2.js";
1
+ import { t as GrTree_default } from "./chunks/GrTree-B2_yW6g1.js";
2
+ import { n as grTreeSafelist, t as grTreeConfig } from "../../chunks/config-DpqOnJiz.js";
3
3
  export { GrTree_default as GrTree, GrTree_default as default, grTreeConfig, grTreeSafelist };
@@ -1,9 +1,9 @@
1
1
  import { t as useGranularityTranslations } from "../../../chunks/granularityI18n-DoV7Ca2m.js";
2
- import { t as GrInput_default } from "../../GrInput/chunks/GrInput-C8pOJgCi.js";
2
+ import { t as GrInput_default } from "../../GrInput/chunks/GrInput-B8dd3JaA.js";
3
3
  import { vClickOutside } from "../../../directives/clickOutside.js";
4
4
  import { t as useFloating } from "../../../chunks/useFloating-DtM6TyE4.js";
5
- import { t as GrTree_default } from "../../GrTree/chunks/GrTree-D3ODe2dB.js";
6
- import { i as grTreeSelectPanelClass, r as grTreeSelectClass } from "../../../chunks/config-BIRO0vDJ2.js";
5
+ import { t as GrTree_default } from "../../GrTree/chunks/GrTree-B2_yW6g1.js";
6
+ import { i as grTreeSelectPanelClass, r as grTreeSelectClass } from "../../../chunks/config-BIRO0vDJ.js";
7
7
  import { Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onUnmounted, openBlock, ref, renderSlot, toDisplayString, unref, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
8
8
  //#region src/components/GrTreeSelect/GrTreeSelect.vue?vue&type=script&setup=true&lang.ts
9
9
  var _hoisted_1 = { class: "relative" };
@@ -1 +1 @@
1
- {"version":3,"file":"GrTreeSelect-B2xBKs5Q.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, onUnmounted, ref, watch } from 'vue'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/internal/useFloating'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrTree, {\n type GrTreeInstance,\n type GrTreeKey,\n type GrTreeNode,\n} from '../GrTree'\nimport type { GrTreeSelectModelValue, GrTreeSelectProps } from './grTreeSelectTypes'\nimport { grTreeSelectClass, grTreeSelectPanelClass } from './grTreeSelectStyles'\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: 'md',\n invalid: false,\n state: 'default',\n multiple: false,\n clearable: false,\n valueDisplay: 'label',\n filterable: false,\n filterPlaceholder: undefined,\n filterInputmode: undefined,\n filterNodeMethod: undefined,\n closeOnSelect: undefined,\n dropdownMaxHeight: 320,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: GrTreeSelectModelValue): void\n (e: 'change', value: GrTreeSelectModelValue): void\n (e: 'visibleChange', visible: boolean): void\n (e: 'clear'): void\n (e: 'nodeClick', data: T, node: GrTreeNode<T>): void\n}>()\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\nconst rootEl = ref<HTMLElement | null>(null)\nconst triggerEl = ref<HTMLInputElement | null>(null)\nconst filterInputRef = ref<InstanceType<typeof GrInput> | null>(null)\nconst treeRef = ref<GrTreeInstance | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hadPointerDownOnTrigger = false\n\nconst open = ref(false)\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\nconst resolvedFilterPlaceholder = computed(() => {\n return props.filterPlaceholder ?? t('gr.treeSelect.filterPlaceholder', 'Search…')\n})\n\nconst className = computed(() => {\n return grTreeSelectClass({\n size: props.size,\n state: props.state,\n invalid: props.invalid,\n })\n})\n\nconst panelClasses = computed(() => {\n return grTreeSelectPanelClass\n})\n\nfunction setOpen(next: boolean) {\n if (props.disabled)\n return\n\n if (open.value === next)\n return\n\n open.value = next\n emit('visibleChange', next)\n}\n\nfunction onClickOutside(): void {\n setOpen(false)\n}\n\nfunction openDropdown(): void {\n setOpen(true)\n}\n\nfunction closeDropdown(): void {\n setOpen(false)\n}\n\nfunction toggleDropdown(): void {\n setOpen(!open.value)\n}\n\nfunction onTriggerPointerDown(): void {\n hadPointerDownOnTrigger = true\n if (typeof window !== 'undefined') {\n window.setTimeout(() => {\n hadPointerDownOnTrigger = false\n }, 0)\n }\n else {\n // SSR / no window: reset sync\n hadPointerDownOnTrigger = false\n }\n}\n\nfunction onTriggerFocus(): void {\n if (hadPointerDownOnTrigger)\n return\n openDropdown()\n}\n\nfunction closeOnEscape(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n closeDropdown()\n nextTick(() => triggerEl.value?.focus())\n }\n}\n\nwatch(\n open,\n async (isOpen) => {\n if (typeof document === 'undefined')\n return\n\n document.removeEventListener('keydown', closeOnEscape)\n\n if (isOpen)\n document.addEventListener('keydown', closeOnEscape)\n\n if (!isOpen)\n return\n\n // sync tree highlight\n if (!props.multiple) {\n const v = props.modelValue\n if (v != null && !Array.isArray(v))\n treeRef.value?.setCurrentKey(v)\n }\n\n // focus filter input\n if (props.filterable) {\n await nextTick()\n filterInputRef.value?.focus()\n }\n },\n { immediate: true },\n)\n\nonUnmounted(() => {\n if (typeof document === 'undefined')\n return\n document.removeEventListener('keydown', closeOnEscape)\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\nwatch(\n open,\n (isOpen) => {\n if (isOpen)\n return\n if (filterValue.value.trim().length > 0)\n filterValue.value = ''\n },\n)\n\nfunction emitModel(next: GrTreeSelectModelValue) {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction clear(): void {\n if (props.disabled)\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\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (props.disabled)\n return\n\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDropdown()\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n closeDropdown()\n }\n}\n\nfunction onNodeClick(data: T, node: GrTreeNode<T>): void {\n emit('nodeClick', data, node)\n\n if (props.disabled)\n return\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</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 >\n <div class=\"relative\">\n <input\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=\"disabled\"\n readonly\n role=\"combobox\"\n aria-readonly=\"true\"\n :aria-expanded=\"open ? 'true' : 'false'\"\n :aria-invalid=\"invalid ? 'true' : undefined\"\n class=\"w-full rounded-md border bg-[var(--bg)] text-[var(--fg)] placeholder:text-[var(--muted-fg)] transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] disabled:opacity-50 disabled:cursor-not-allowed\"\n :class=\"[className, $slots.value ? 'text-transparent placeholder:text-transparent' : '']\"\n @pointerdown=\"onTriggerPointerDown\"\n @click=\"toggleDropdown\"\n @focus=\"onTriggerFocus\"\n @keydown=\"onTriggerKeydown\"\n >\n\n <button\n v-if=\"clearable && hasSelection\"\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-md text-[var(--muted-fg)] hover:text-[var(--fg)] hover:bg-[color-mix(in_srgb,var(--muted)_25%,transparent)] disabled:opacity-50\"\n :disabled=\"disabled\"\n :aria-label=\"t('gr.common.clear', 'Clear')\"\n @click.stop=\"clear\"\n >\n <span class=\"i-lucide-x inline-block h-4 w-4\" />\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(--muted-fg)] pointer-events-none\"\n >\n <span\n class=\"i-lucide-chevron-down inline-block h-4 w-4 transition-transform duration-150\"\n :class=\"open ? 'rotate-180' : ''\"\n />\n </span>\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 >\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=\"body\">\n <transition\n enter-active-class=\"transition ease-out duration-150\"\n enter-from-class=\"transform opacity-0 scale-95\"\n enter-to-class=\"transform opacity-100 scale-100\"\n leave-active-class=\"transition ease-in duration-100\"\n leave-from-class=\"transform opacity-100 scale-100\"\n leave-to-class=\"transform opacity-0 scale-95\"\n >\n <div\n v-show=\"open\"\n ref=\"panelEl\"\n data-testid=\"gr-tree-select-panel\"\n data-gr-tree-select-panel\n :style=\"floatingStyle\"\n >\n <div :class=\"panelClasses\">\n <div v-if=\"filterable\" class=\"p-2 border-b border-[var(--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 />\n </div>\n\n <div\n class=\"p-1 overflow-auto\"\n :style=\"{ maxHeight: `${dropdownMaxHeight}px` }\"\n >\n <div v-if=\"(data?.length ?? 0) === 0\" class=\"px-3 py-2 text-[13px] text-[var(--muted-fg)]\">\n <slot name=\"empty\">\n {{ t('gr.treeSelect.empty', 'No data') }}\n </slot>\n </div>\n\n <GrTree\n v-else\n ref=\"treeRef\"\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 @node-click=\"onNodeClick\"\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 <span\n class=\"inline-block h-4 w-4 shrink-0\"\n :class=\"selectedKeySet.has(node.key) ? 'i-lucide-check text-[var(--primary)]' : ''\"\n aria-hidden=\"true\"\n />\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, onUnmounted, ref, watch } from 'vue'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/internal/useFloating'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrTree, {\n type GrTreeInstance,\n type GrTreeKey,\n type GrTreeNode,\n} from '../GrTree'\nimport type { GrTreeSelectModelValue, GrTreeSelectProps } from './grTreeSelectTypes'\nimport { grTreeSelectClass, grTreeSelectPanelClass } from './grTreeSelectStyles'\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: 'md',\n invalid: false,\n state: 'default',\n multiple: false,\n clearable: false,\n valueDisplay: 'label',\n filterable: false,\n filterPlaceholder: undefined,\n filterInputmode: undefined,\n filterNodeMethod: undefined,\n closeOnSelect: undefined,\n dropdownMaxHeight: 320,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: GrTreeSelectModelValue): void\n (e: 'change', value: GrTreeSelectModelValue): void\n (e: 'visibleChange', visible: boolean): void\n (e: 'clear'): void\n (e: 'nodeClick', data: T, node: GrTreeNode<T>): void\n}>()\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\nconst rootEl = ref<HTMLElement | null>(null)\nconst triggerEl = ref<HTMLInputElement | null>(null)\nconst filterInputRef = ref<InstanceType<typeof GrInput> | null>(null)\nconst treeRef = ref<GrTreeInstance | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hadPointerDownOnTrigger = false\n\nconst open = ref(false)\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\nconst resolvedFilterPlaceholder = computed(() => {\n return props.filterPlaceholder ?? t('gr.treeSelect.filterPlaceholder', 'Search…')\n})\n\nconst className = computed(() => {\n return grTreeSelectClass({\n size: props.size,\n state: props.state,\n invalid: props.invalid,\n })\n})\n\nconst panelClasses = computed(() => {\n return grTreeSelectPanelClass\n})\n\nfunction setOpen(next: boolean) {\n if (props.disabled)\n return\n\n if (open.value === next)\n return\n\n open.value = next\n emit('visibleChange', next)\n}\n\nfunction onClickOutside(): void {\n setOpen(false)\n}\n\nfunction openDropdown(): void {\n setOpen(true)\n}\n\nfunction closeDropdown(): void {\n setOpen(false)\n}\n\nfunction toggleDropdown(): void {\n setOpen(!open.value)\n}\n\nfunction onTriggerPointerDown(): void {\n hadPointerDownOnTrigger = true\n if (typeof window !== 'undefined') {\n window.setTimeout(() => {\n hadPointerDownOnTrigger = false\n }, 0)\n }\n else {\n // SSR / no window: reset sync\n hadPointerDownOnTrigger = false\n }\n}\n\nfunction onTriggerFocus(): void {\n if (hadPointerDownOnTrigger)\n return\n openDropdown()\n}\n\nfunction closeOnEscape(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n closeDropdown()\n nextTick(() => triggerEl.value?.focus())\n }\n}\n\nwatch(\n open,\n async (isOpen) => {\n if (typeof document === 'undefined')\n return\n\n document.removeEventListener('keydown', closeOnEscape)\n\n if (isOpen)\n document.addEventListener('keydown', closeOnEscape)\n\n if (!isOpen)\n return\n\n // sync tree highlight\n if (!props.multiple) {\n const v = props.modelValue\n if (v != null && !Array.isArray(v))\n treeRef.value?.setCurrentKey(v)\n }\n\n // focus filter input\n if (props.filterable) {\n await nextTick()\n filterInputRef.value?.focus()\n }\n },\n { immediate: true },\n)\n\nonUnmounted(() => {\n if (typeof document === 'undefined')\n return\n document.removeEventListener('keydown', closeOnEscape)\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\nwatch(\n open,\n (isOpen) => {\n if (isOpen)\n return\n if (filterValue.value.trim().length > 0)\n filterValue.value = ''\n },\n)\n\nfunction emitModel(next: GrTreeSelectModelValue) {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction clear(): void {\n if (props.disabled)\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\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (props.disabled)\n return\n\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDropdown()\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n closeDropdown()\n }\n}\n\nfunction onNodeClick(data: T, node: GrTreeNode<T>): void {\n emit('nodeClick', data, node)\n\n if (props.disabled)\n return\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</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 >\n <div class=\"relative\">\n <input\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=\"disabled\"\n readonly\n role=\"combobox\"\n aria-readonly=\"true\"\n :aria-expanded=\"open ? 'true' : 'false'\"\n :aria-invalid=\"invalid ? 'true' : undefined\"\n class=\"w-full rounded-md border bg-[var(--bg)] text-[var(--fg)] placeholder:text-[var(--muted-fg)] transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] disabled:opacity-50 disabled:cursor-not-allowed\"\n :class=\"[className, $slots.value ? 'text-transparent placeholder:text-transparent' : '']\"\n @pointerdown=\"onTriggerPointerDown\"\n @click=\"toggleDropdown\"\n @focus=\"onTriggerFocus\"\n @keydown=\"onTriggerKeydown\"\n >\n\n <button\n v-if=\"clearable && hasSelection\"\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-md text-[var(--muted-fg)] hover:text-[var(--fg)] hover:bg-[color-mix(in_srgb,var(--muted)_25%,transparent)] disabled:opacity-50\"\n :disabled=\"disabled\"\n :aria-label=\"t('gr.common.clear', 'Clear')\"\n @click.stop=\"clear\"\n >\n <span class=\"i-lucide-x inline-block h-4 w-4\" />\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(--muted-fg)] pointer-events-none\"\n >\n <span\n class=\"i-lucide-chevron-down inline-block h-4 w-4 transition-transform duration-150\"\n :class=\"open ? 'rotate-180' : ''\"\n />\n </span>\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 >\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=\"body\">\n <transition\n enter-active-class=\"transition ease-out duration-150\"\n enter-from-class=\"transform opacity-0 scale-95\"\n enter-to-class=\"transform opacity-100 scale-100\"\n leave-active-class=\"transition ease-in duration-100\"\n leave-from-class=\"transform opacity-100 scale-100\"\n leave-to-class=\"transform opacity-0 scale-95\"\n >\n <div\n v-show=\"open\"\n ref=\"panelEl\"\n data-testid=\"gr-tree-select-panel\"\n data-gr-tree-select-panel\n :style=\"floatingStyle\"\n >\n <div :class=\"panelClasses\">\n <div v-if=\"filterable\" class=\"p-2 border-b border-[var(--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 />\n </div>\n\n <div\n class=\"p-1 overflow-auto\"\n :style=\"{ maxHeight: `${dropdownMaxHeight}px` }\"\n >\n <div v-if=\"(data?.length ?? 0) === 0\" class=\"px-3 py-2 text-[13px] text-[var(--muted-fg)]\">\n <slot name=\"empty\">\n {{ t('gr.treeSelect.empty', 'No data') }}\n </slot>\n </div>\n\n <GrTree\n v-else\n ref=\"treeRef\"\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 @node-click=\"onNodeClick\"\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 <span\n class=\"inline-block h-4 w-4 shrink-0\"\n :class=\"selectedKeySet.has(node.key) ? 'i-lucide-check text-[var(--primary)]' : ''\"\n aria-hidden=\"true\"\n />\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
+ {"version":3,"file":"GrTreeSelect-0aM62xyu.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, onUnmounted, ref, watch } from 'vue'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/internal/useFloating'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrTree, {\n type GrTreeInstance,\n type GrTreeKey,\n type GrTreeNode,\n} from '../GrTree'\nimport type { GrTreeSelectModelValue, GrTreeSelectProps } from './grTreeSelectTypes'\nimport { grTreeSelectClass, grTreeSelectPanelClass } from './grTreeSelectStyles'\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: 'md',\n invalid: false,\n state: 'default',\n multiple: false,\n clearable: false,\n valueDisplay: 'label',\n filterable: false,\n filterPlaceholder: undefined,\n filterInputmode: undefined,\n filterNodeMethod: undefined,\n closeOnSelect: undefined,\n dropdownMaxHeight: 320,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: GrTreeSelectModelValue): void\n (e: 'change', value: GrTreeSelectModelValue): void\n (e: 'visibleChange', visible: boolean): void\n (e: 'clear'): void\n (e: 'nodeClick', data: T, node: GrTreeNode<T>): void\n}>()\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\nconst rootEl = ref<HTMLElement | null>(null)\nconst triggerEl = ref<HTMLInputElement | null>(null)\nconst filterInputRef = ref<InstanceType<typeof GrInput> | null>(null)\nconst treeRef = ref<GrTreeInstance | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hadPointerDownOnTrigger = false\n\nconst open = ref(false)\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\nconst resolvedFilterPlaceholder = computed(() => {\n return props.filterPlaceholder ?? t('gr.treeSelect.filterPlaceholder', 'Search…')\n})\n\nconst className = computed(() => {\n return grTreeSelectClass({\n size: props.size,\n state: props.state,\n invalid: props.invalid,\n })\n})\n\nconst panelClasses = computed(() => {\n return grTreeSelectPanelClass\n})\n\nfunction setOpen(next: boolean) {\n if (props.disabled)\n return\n\n if (open.value === next)\n return\n\n open.value = next\n emit('visibleChange', next)\n}\n\nfunction onClickOutside(): void {\n setOpen(false)\n}\n\nfunction openDropdown(): void {\n setOpen(true)\n}\n\nfunction closeDropdown(): void {\n setOpen(false)\n}\n\nfunction toggleDropdown(): void {\n setOpen(!open.value)\n}\n\nfunction onTriggerPointerDown(): void {\n hadPointerDownOnTrigger = true\n if (typeof window !== 'undefined') {\n window.setTimeout(() => {\n hadPointerDownOnTrigger = false\n }, 0)\n }\n else {\n // SSR / no window: reset sync\n hadPointerDownOnTrigger = false\n }\n}\n\nfunction onTriggerFocus(): void {\n if (hadPointerDownOnTrigger)\n return\n openDropdown()\n}\n\nfunction closeOnEscape(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n closeDropdown()\n nextTick(() => triggerEl.value?.focus())\n }\n}\n\nwatch(\n open,\n async (isOpen) => {\n if (typeof document === 'undefined')\n return\n\n document.removeEventListener('keydown', closeOnEscape)\n\n if (isOpen)\n document.addEventListener('keydown', closeOnEscape)\n\n if (!isOpen)\n return\n\n // sync tree highlight\n if (!props.multiple) {\n const v = props.modelValue\n if (v != null && !Array.isArray(v))\n treeRef.value?.setCurrentKey(v)\n }\n\n // focus filter input\n if (props.filterable) {\n await nextTick()\n filterInputRef.value?.focus()\n }\n },\n { immediate: true },\n)\n\nonUnmounted(() => {\n if (typeof document === 'undefined')\n return\n document.removeEventListener('keydown', closeOnEscape)\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\nwatch(\n open,\n (isOpen) => {\n if (isOpen)\n return\n if (filterValue.value.trim().length > 0)\n filterValue.value = ''\n },\n)\n\nfunction emitModel(next: GrTreeSelectModelValue) {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction clear(): void {\n if (props.disabled)\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\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (props.disabled)\n return\n\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDropdown()\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n closeDropdown()\n }\n}\n\nfunction onNodeClick(data: T, node: GrTreeNode<T>): void {\n emit('nodeClick', data, node)\n\n if (props.disabled)\n return\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</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 >\n <div class=\"relative\">\n <input\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=\"disabled\"\n readonly\n role=\"combobox\"\n aria-readonly=\"true\"\n :aria-expanded=\"open ? 'true' : 'false'\"\n :aria-invalid=\"invalid ? 'true' : undefined\"\n class=\"w-full rounded-md border bg-[var(--bg)] text-[var(--fg)] placeholder:text-[var(--muted-fg)] transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] disabled:opacity-50 disabled:cursor-not-allowed\"\n :class=\"[className, $slots.value ? 'text-transparent placeholder:text-transparent' : '']\"\n @pointerdown=\"onTriggerPointerDown\"\n @click=\"toggleDropdown\"\n @focus=\"onTriggerFocus\"\n @keydown=\"onTriggerKeydown\"\n >\n\n <button\n v-if=\"clearable && hasSelection\"\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-md text-[var(--muted-fg)] hover:text-[var(--fg)] hover:bg-[color-mix(in_srgb,var(--muted)_25%,transparent)] disabled:opacity-50\"\n :disabled=\"disabled\"\n :aria-label=\"t('gr.common.clear', 'Clear')\"\n @click.stop=\"clear\"\n >\n <span class=\"i-lucide-x inline-block h-4 w-4\" />\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(--muted-fg)] pointer-events-none\"\n >\n <span\n class=\"i-lucide-chevron-down inline-block h-4 w-4 transition-transform duration-150\"\n :class=\"open ? 'rotate-180' : ''\"\n />\n </span>\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 >\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=\"body\">\n <transition\n enter-active-class=\"transition ease-out duration-150\"\n enter-from-class=\"transform opacity-0 scale-95\"\n enter-to-class=\"transform opacity-100 scale-100\"\n leave-active-class=\"transition ease-in duration-100\"\n leave-from-class=\"transform opacity-100 scale-100\"\n leave-to-class=\"transform opacity-0 scale-95\"\n >\n <div\n v-show=\"open\"\n ref=\"panelEl\"\n data-testid=\"gr-tree-select-panel\"\n data-gr-tree-select-panel\n :style=\"floatingStyle\"\n >\n <div :class=\"panelClasses\">\n <div v-if=\"filterable\" class=\"p-2 border-b border-[var(--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 />\n </div>\n\n <div\n class=\"p-1 overflow-auto\"\n :style=\"{ maxHeight: `${dropdownMaxHeight}px` }\"\n >\n <div v-if=\"(data?.length ?? 0) === 0\" class=\"px-3 py-2 text-[13px] text-[var(--muted-fg)]\">\n <slot name=\"empty\">\n {{ t('gr.treeSelect.empty', 'No data') }}\n </slot>\n </div>\n\n <GrTree\n v-else\n ref=\"treeRef\"\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 @node-click=\"onNodeClick\"\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 <span\n class=\"inline-block h-4 w-4 shrink-0\"\n :class=\"selectedKeySet.has(node.key) ? 'i-lucide-check text-[var(--primary)]' : ''\"\n aria-hidden=\"true\"\n />\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, onUnmounted, ref, watch } from 'vue'\n\nimport { vClickOutside } from '../../directives'\nimport { useFloating } from '../../composables/internal/useFloating'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrTree, {\n type GrTreeInstance,\n type GrTreeKey,\n type GrTreeNode,\n} from '../GrTree'\nimport type { GrTreeSelectModelValue, GrTreeSelectProps } from './grTreeSelectTypes'\nimport { grTreeSelectClass, grTreeSelectPanelClass } from './grTreeSelectStyles'\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: 'md',\n invalid: false,\n state: 'default',\n multiple: false,\n clearable: false,\n valueDisplay: 'label',\n filterable: false,\n filterPlaceholder: undefined,\n filterInputmode: undefined,\n filterNodeMethod: undefined,\n closeOnSelect: undefined,\n dropdownMaxHeight: 320,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: GrTreeSelectModelValue): void\n (e: 'change', value: GrTreeSelectModelValue): void\n (e: 'visibleChange', visible: boolean): void\n (e: 'clear'): void\n (e: 'nodeClick', data: T, node: GrTreeNode<T>): void\n}>()\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\nconst rootEl = ref<HTMLElement | null>(null)\nconst triggerEl = ref<HTMLInputElement | null>(null)\nconst filterInputRef = ref<InstanceType<typeof GrInput> | null>(null)\nconst treeRef = ref<GrTreeInstance | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hadPointerDownOnTrigger = false\n\nconst open = ref(false)\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\nconst resolvedFilterPlaceholder = computed(() => {\n return props.filterPlaceholder ?? t('gr.treeSelect.filterPlaceholder', 'Search…')\n})\n\nconst className = computed(() => {\n return grTreeSelectClass({\n size: props.size,\n state: props.state,\n invalid: props.invalid,\n })\n})\n\nconst panelClasses = computed(() => {\n return grTreeSelectPanelClass\n})\n\nfunction setOpen(next: boolean) {\n if (props.disabled)\n return\n\n if (open.value === next)\n return\n\n open.value = next\n emit('visibleChange', next)\n}\n\nfunction onClickOutside(): void {\n setOpen(false)\n}\n\nfunction openDropdown(): void {\n setOpen(true)\n}\n\nfunction closeDropdown(): void {\n setOpen(false)\n}\n\nfunction toggleDropdown(): void {\n setOpen(!open.value)\n}\n\nfunction onTriggerPointerDown(): void {\n hadPointerDownOnTrigger = true\n if (typeof window !== 'undefined') {\n window.setTimeout(() => {\n hadPointerDownOnTrigger = false\n }, 0)\n }\n else {\n // SSR / no window: reset sync\n hadPointerDownOnTrigger = false\n }\n}\n\nfunction onTriggerFocus(): void {\n if (hadPointerDownOnTrigger)\n return\n openDropdown()\n}\n\nfunction closeOnEscape(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n closeDropdown()\n nextTick(() => triggerEl.value?.focus())\n }\n}\n\nwatch(\n open,\n async (isOpen) => {\n if (typeof document === 'undefined')\n return\n\n document.removeEventListener('keydown', closeOnEscape)\n\n if (isOpen)\n document.addEventListener('keydown', closeOnEscape)\n\n if (!isOpen)\n return\n\n // sync tree highlight\n if (!props.multiple) {\n const v = props.modelValue\n if (v != null && !Array.isArray(v))\n treeRef.value?.setCurrentKey(v)\n }\n\n // focus filter input\n if (props.filterable) {\n await nextTick()\n filterInputRef.value?.focus()\n }\n },\n { immediate: true },\n)\n\nonUnmounted(() => {\n if (typeof document === 'undefined')\n return\n document.removeEventListener('keydown', closeOnEscape)\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\nwatch(\n open,\n (isOpen) => {\n if (isOpen)\n return\n if (filterValue.value.trim().length > 0)\n filterValue.value = ''\n },\n)\n\nfunction emitModel(next: GrTreeSelectModelValue) {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction clear(): void {\n if (props.disabled)\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\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (props.disabled)\n return\n\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n openDropdown()\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n closeDropdown()\n }\n}\n\nfunction onNodeClick(data: T, node: GrTreeNode<T>): void {\n emit('nodeClick', data, node)\n\n if (props.disabled)\n return\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</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 >\n <div class=\"relative\">\n <input\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=\"disabled\"\n readonly\n role=\"combobox\"\n aria-readonly=\"true\"\n :aria-expanded=\"open ? 'true' : 'false'\"\n :aria-invalid=\"invalid ? 'true' : undefined\"\n class=\"w-full rounded-md border bg-[var(--bg)] text-[var(--fg)] placeholder:text-[var(--muted-fg)] transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] disabled:opacity-50 disabled:cursor-not-allowed\"\n :class=\"[className, $slots.value ? 'text-transparent placeholder:text-transparent' : '']\"\n @pointerdown=\"onTriggerPointerDown\"\n @click=\"toggleDropdown\"\n @focus=\"onTriggerFocus\"\n @keydown=\"onTriggerKeydown\"\n >\n\n <button\n v-if=\"clearable && hasSelection\"\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-md text-[var(--muted-fg)] hover:text-[var(--fg)] hover:bg-[color-mix(in_srgb,var(--muted)_25%,transparent)] disabled:opacity-50\"\n :disabled=\"disabled\"\n :aria-label=\"t('gr.common.clear', 'Clear')\"\n @click.stop=\"clear\"\n >\n <span class=\"i-lucide-x inline-block h-4 w-4\" />\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(--muted-fg)] pointer-events-none\"\n >\n <span\n class=\"i-lucide-chevron-down inline-block h-4 w-4 transition-transform duration-150\"\n :class=\"open ? 'rotate-180' : ''\"\n />\n </span>\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 >\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=\"body\">\n <transition\n enter-active-class=\"transition ease-out duration-150\"\n enter-from-class=\"transform opacity-0 scale-95\"\n enter-to-class=\"transform opacity-100 scale-100\"\n leave-active-class=\"transition ease-in duration-100\"\n leave-from-class=\"transform opacity-100 scale-100\"\n leave-to-class=\"transform opacity-0 scale-95\"\n >\n <div\n v-show=\"open\"\n ref=\"panelEl\"\n data-testid=\"gr-tree-select-panel\"\n data-gr-tree-select-panel\n :style=\"floatingStyle\"\n >\n <div :class=\"panelClasses\">\n <div v-if=\"filterable\" class=\"p-2 border-b border-[var(--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 />\n </div>\n\n <div\n class=\"p-1 overflow-auto\"\n :style=\"{ maxHeight: `${dropdownMaxHeight}px` }\"\n >\n <div v-if=\"(data?.length ?? 0) === 0\" class=\"px-3 py-2 text-[13px] text-[var(--muted-fg)]\">\n <slot name=\"empty\">\n {{ t('gr.treeSelect.empty', 'No data') }}\n </slot>\n </div>\n\n <GrTree\n v-else\n ref=\"treeRef\"\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 @node-click=\"onNodeClick\"\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 <span\n class=\"inline-block h-4 w-4 shrink-0\"\n :class=\"selectedKeySet.has(node.key) ? 'i-lucide-check text-[var(--primary)]' : ''\"\n aria-hidden=\"true\"\n />\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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"}