@feugene/granularity 0.49.0 → 0.50.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 (368) hide show
  1. package/README.md +3 -3
  2. package/dist/chunks/chevron-up-BhW6hi8L.js +23 -0
  3. package/dist/chunks/chevron-up-BhW6hi8L.js.map +1 -0
  4. package/dist/chunks/{config-E1cTyRVV.js → config-8n1VR0ju.js} +1 -1
  5. package/dist/chunks/{config-E1cTyRVV.js.map → config-8n1VR0ju.js.map} +1 -1
  6. package/dist/chunks/{config-DIDz_E5m.js → config-B34mkd53.js} +66 -1
  7. package/dist/chunks/config-B34mkd53.js.map +1 -0
  8. package/dist/chunks/{config-B5SBUa6u.js → config-B7qZqiUB.js} +28 -1
  9. package/dist/chunks/config-B7qZqiUB.js.map +1 -0
  10. package/dist/chunks/config-BBrPUEye.js +8 -0
  11. package/dist/chunks/config-BBrPUEye.js.map +1 -0
  12. package/dist/chunks/{config-CT4lP6S4.js → config-BOCzHqWh.js} +2 -2
  13. package/dist/chunks/{config-CT4lP6S4.js.map → config-BOCzHqWh.js.map} +1 -1
  14. package/dist/chunks/{config-iemgzS4x.js → config-BP1ktzwh.js} +2 -24
  15. package/dist/chunks/config-BP1ktzwh.js.map +1 -0
  16. package/dist/chunks/config-BTxmdRzT.js +28 -0
  17. package/dist/chunks/config-BTxmdRzT.js.map +1 -0
  18. package/dist/chunks/{config-CjWOTgLL.js → config-Bk52xd5l.js} +12 -5
  19. package/dist/chunks/config-Bk52xd5l.js.map +1 -0
  20. package/dist/chunks/{config-D3HOuHDe.js → config-C3SqBqSQ.js} +3 -1
  21. package/dist/chunks/config-C3SqBqSQ.js.map +1 -0
  22. package/dist/chunks/{config-2ZHRsdOc.js → config-C3uqd-sW.js} +1 -1
  23. package/dist/chunks/config-C3uqd-sW.js.map +1 -0
  24. package/dist/chunks/{config-BXRmsn3t.js → config-CPhcZzHi.js} +72 -10
  25. package/dist/chunks/config-CPhcZzHi.js.map +1 -0
  26. package/dist/chunks/config-CWtfxkM9.js.map +1 -1
  27. package/dist/chunks/{config--t2dxj0t.js → config-CmLTCmY9.js} +2 -2
  28. package/dist/chunks/{config--t2dxj0t.js.map → config-CmLTCmY9.js.map} +1 -1
  29. package/dist/chunks/{config-BAse0laT.js → config-CvtqB4ki.js} +8 -3
  30. package/dist/chunks/config-CvtqB4ki.js.map +1 -0
  31. package/dist/chunks/{config-BcXX7S7B.js → config-D-JgqV0J.js} +5 -1
  32. package/dist/chunks/{config-BcXX7S7B.js.map → config-D-JgqV0J.js.map} +1 -1
  33. package/dist/chunks/{config-BHLMTJaR.js → config-D1oVht-E.js} +8 -3
  34. package/dist/chunks/config-D1oVht-E.js.map +1 -0
  35. package/dist/chunks/{config-B42iJ48O.js → config-DG41PD9i.js} +13 -1
  36. package/dist/chunks/config-DG41PD9i.js.map +1 -0
  37. package/dist/chunks/{config-Bs1HwUcx.js → config-DPJ3jtiB.js} +12 -2
  38. package/dist/chunks/config-DPJ3jtiB.js.map +1 -0
  39. package/dist/chunks/{config-tNqtapcT.js → config-DpqjlCfB.js} +2 -2
  40. package/dist/chunks/{config-tNqtapcT.js.map → config-DpqjlCfB.js.map} +1 -1
  41. package/dist/chunks/{config-DNDgp9bB.js → config-DpzFoSIh.js} +64 -2
  42. package/dist/chunks/config-DpzFoSIh.js.map +1 -0
  43. package/dist/chunks/config-SPugeaHT.js +37 -0
  44. package/dist/chunks/config-SPugeaHT.js.map +1 -0
  45. package/dist/chunks/{en-CsQUoBS2.js → en-mIFywnV2.js} +22 -6
  46. package/dist/chunks/en-mIFywnV2.js.map +1 -0
  47. package/dist/chunks/{es-9nbkPvdA.js → es-CvthYwtB.js} +22 -6
  48. package/dist/chunks/es-CvthYwtB.js.map +1 -0
  49. package/dist/chunks/{es-DrUz5J6I.js → es-DlGd6Mrj.js} +3 -3
  50. package/dist/chunks/{es-DrUz5J6I.js.map → es-DlGd6Mrj.js.map} +1 -1
  51. package/dist/chunks/{generated-CxvC5O0V.js → generated-Cx4C7GRN.js} +84 -0
  52. package/dist/chunks/{generated-CxvC5O0V.js.map → generated-Cx4C7GRN.js.map} +1 -1
  53. package/dist/chunks/{grPopoverStyles-CYAeO3Ov.js → grPopoverStyles-CncEkiPu.js} +1 -1
  54. package/dist/chunks/{grPopoverStyles-CYAeO3Ov.js.map → grPopoverStyles-CncEkiPu.js.map} +1 -1
  55. package/dist/chunks/{grSelectStyles-D9EQ-pgK.js → grSelectStyles-Cam-IG9s.js} +3 -2
  56. package/dist/chunks/grSelectStyles-Cam-IG9s.js.map +1 -0
  57. package/dist/chunks/{grSliderStyles-kaz6VXZ3.js → grSliderStyles-CqzV0hll.js} +1 -1
  58. package/dist/chunks/grSliderStyles-CqzV0hll.js.map +1 -0
  59. package/dist/chunks/{config-CbEbLyDE.js → grSortableListStyles-CxieDmpe.js} +1 -27
  60. package/dist/chunks/grSortableListStyles-CxieDmpe.js.map +1 -0
  61. package/dist/chunks/grTableStyles-CPSxDTOW.js +66 -0
  62. package/dist/chunks/grTableStyles-CPSxDTOW.js.map +1 -0
  63. package/dist/chunks/{config-CMNfZO7S.js → grTabsStyles-DIz2VdIm.js} +1 -36
  64. package/dist/chunks/grTabsStyles-DIz2VdIm.js.map +1 -0
  65. package/dist/chunks/grTooltipStyles-CtbGEEGV.js +24 -0
  66. package/dist/chunks/grTooltipStyles-CtbGEEGV.js.map +1 -0
  67. package/dist/chunks/{granular-provider-B6xomapW.js → granular-provider-cv5vaM1a.js} +21 -19
  68. package/dist/chunks/granular-provider-cv5vaM1a.js.map +1 -0
  69. package/dist/chunks/hotkeySequence-BTHIM_5A.js +46 -0
  70. package/dist/chunks/hotkeySequence-BTHIM_5A.js.map +1 -0
  71. package/dist/chunks/{keyboard-DE2yhz_b.js → keyboard-BiFSgWLt.js} +70 -1
  72. package/dist/chunks/keyboard-BiFSgWLt.js.map +1 -0
  73. package/dist/chunks/optionPanel-DvY7Tv_4.js +182 -0
  74. package/dist/chunks/optionPanel-DvY7Tv_4.js.map +1 -0
  75. package/dist/chunks/overlayListPanel-D91jBCHU.js +21 -0
  76. package/dist/chunks/overlayListPanel-D91jBCHU.js.map +1 -0
  77. package/dist/chunks/{overlayStack-DH4Z7am1.js → overlayStack-DCkCgXZP.js} +1 -1
  78. package/dist/chunks/{overlayStack-DH4Z7am1.js.map → overlayStack-DCkCgXZP.js.map} +1 -1
  79. package/dist/chunks/{overlayPanelSurface-BKeMhRx4.js → overlayTransition-C0FDMx7Q.js} +24 -24
  80. package/dist/chunks/overlayTransition-C0FDMx7Q.js.map +1 -0
  81. package/dist/chunks/{ru-88i1WG0b.js → ru-CQKDR-kD.js} +22 -6
  82. package/dist/chunks/ru-CQKDR-kD.js.map +1 -0
  83. package/dist/chunks/{useMenuItemsFocus-B7Bl_aFA.js → useMenuItemsFocus-C031blYS.js} +1 -1
  84. package/dist/chunks/{useMenuItemsFocus-B7Bl_aFA.js.map → useMenuItemsFocus-C031blYS.js.map} +1 -1
  85. package/dist/chunks/{useModalOverlay-ACRkflzx.js → useModalOverlay-CKCQkGdB.js} +1 -1
  86. package/dist/chunks/{useModalOverlay-ACRkflzx.js.map → useModalOverlay-CKCQkGdB.js.map} +1 -1
  87. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-Chhw65pI.js → GrAutocomplete-Cyr1-ENw.js} +181 -123
  88. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-Cyr1-ENw.js.map +1 -0
  89. package/dist/components/GrAutocomplete/index.js +2 -2
  90. package/dist/components/GrAutocomplete/styles.css +1 -1
  91. package/dist/components/GrCarousel/chunks/{GrCarousel-ByuughtI.js → GrCarousel-CBj-PEPB.js} +186 -37
  92. package/dist/components/GrCarousel/chunks/GrCarousel-CBj-PEPB.js.map +1 -0
  93. package/dist/components/GrCarousel/index.js +2 -2
  94. package/dist/components/GrCarousel/styles.css +1 -1
  95. package/dist/components/GrCheckbox/chunks/{GrCheckbox-Dp201frb.js → GrCheckbox-B4NJc7Ur.js} +2 -1
  96. package/dist/components/GrCheckbox/chunks/GrCheckbox-B4NJc7Ur.js.map +1 -0
  97. package/dist/components/GrCheckbox/index.js +1 -1
  98. package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-IpqG5qwm.js → GrCheckboxGroup-qZHpNFCX.js} +1 -1
  99. package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-IpqG5qwm.js.map → GrCheckboxGroup-qZHpNFCX.js.map} +1 -1
  100. package/dist/components/GrCheckboxGroup/index.js +1 -1
  101. package/dist/components/GrColorPicker/chunks/{GrColorPicker-BRM_4lyI.js → GrColorPicker-vGSgpUV9.js} +353 -38
  102. package/dist/components/GrColorPicker/chunks/GrColorPicker-vGSgpUV9.js.map +1 -0
  103. package/dist/components/GrColorPicker/index.js +2 -2
  104. package/dist/components/GrColorPicker/styles.css +1 -1
  105. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BJHmkDQv.js → GrCommandPalette-CAHgj0Aa.js} +23 -7
  106. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-CAHgj0Aa.js.map +1 -0
  107. package/dist/components/GrCommandPalette/index.js +1 -1
  108. package/dist/components/GrCommandPalette/styles.css +1 -1
  109. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BzUQwbec.js → GrConfirmDialog-dg021BMd.js} +1 -1
  110. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BzUQwbec.js.map → GrConfirmDialog-dg021BMd.js.map} +1 -1
  111. package/dist/components/GrConfirmDialog/index.js +1 -1
  112. package/dist/components/GrContextMenu/chunks/{GrContextMenu-RpxMHQXH.js → GrContextMenu-bQ1Vvy2c.js} +3 -3
  113. package/dist/components/GrContextMenu/chunks/{GrContextMenu-RpxMHQXH.js.map → GrContextMenu-bQ1Vvy2c.js.map} +1 -1
  114. package/dist/components/GrContextMenu/index.js +1 -1
  115. package/dist/components/GrDataTable/chunks/{GrDataTable-DQxYYgQk.js → GrDataTable-Bb2jWnRG.js} +576 -136
  116. package/dist/components/GrDataTable/chunks/GrDataTable-Bb2jWnRG.js.map +1 -0
  117. package/dist/components/GrDataTable/index.js +2 -2
  118. package/dist/components/GrDelta/chunks/{GrDelta-CgTvfoIN.js → GrDelta-BSv1KdMy.js} +0 -0
  119. package/dist/components/GrDelta/chunks/{GrDelta-CgTvfoIN.js.map → GrDelta-BSv1KdMy.js.map} +1 -1
  120. package/dist/components/GrDelta/index.js +2 -2
  121. package/dist/components/GrDialog/chunks/{GrDialog-DDz_OEhk.js → GrDialog-C9Zu72jB.js} +1 -1
  122. package/dist/components/GrDialog/chunks/{GrDialog-DDz_OEhk.js.map → GrDialog-C9Zu72jB.js.map} +1 -1
  123. package/dist/components/GrDialog/index.js +1 -1
  124. package/dist/components/GrDialogService/chunks/{GrDialogService-Dtq0ZCN5.js → GrDialogService-DLBifO61.js} +2 -2
  125. package/dist/components/GrDialogService/chunks/{GrDialogService-Dtq0ZCN5.js.map → GrDialogService-DLBifO61.js.map} +1 -1
  126. package/dist/components/GrDialogService/index.js +1 -1
  127. package/dist/components/GrDrawer/chunks/{GrDrawer-CNpSMuN-.js → GrDrawer-DOcRTE8G.js} +1 -1
  128. package/dist/components/GrDrawer/chunks/{GrDrawer-CNpSMuN-.js.map → GrDrawer-DOcRTE8G.js.map} +1 -1
  129. package/dist/components/GrDrawer/index.js +1 -1
  130. package/dist/components/GrDropdown/chunks/{GrDropdown-cLZuZMEY.js → GrDropdown-kxwmgfSe.js} +2 -2
  131. package/dist/components/GrDropdown/chunks/{GrDropdown-cLZuZMEY.js.map → GrDropdown-kxwmgfSe.js.map} +1 -1
  132. package/dist/components/GrDropdown/index.js +2 -2
  133. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-Dxkz_ry4.js → GrDropdownMenu--VoK3VY0.js} +3 -34
  134. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu--VoK3VY0.js.map +1 -0
  135. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-CkM3BFPL.js +34 -0
  136. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-CkM3BFPL.js.map +1 -0
  137. package/dist/components/GrDropdownMenu/index.js +2 -1
  138. package/dist/components/GrEmptyState/chunks/{GrEmptyState-BbvwE-E0.js → GrEmptyState-Bz6-_ED4.js} +42 -6
  139. package/dist/components/GrEmptyState/chunks/GrEmptyState-Bz6-_ED4.js.map +1 -0
  140. package/dist/components/GrEmptyState/index.js +1 -1
  141. package/dist/components/GrFileUpload/chunks/{GrFileUpload-BwMR71zN.js → GrFileUpload-Bgdfnkd8.js} +5 -2
  142. package/dist/components/GrFileUpload/chunks/GrFileUpload-Bgdfnkd8.js.map +1 -0
  143. package/dist/components/GrFileUpload/index.js +1 -1
  144. package/dist/components/GrFormFile/chunks/{GrFormFile-Dlxx-9zi.js → GrFormFile-Ctq1isz-.js} +78 -11
  145. package/dist/components/GrFormFile/chunks/GrFormFile-Ctq1isz-.js.map +1 -0
  146. package/dist/components/GrFormFile/index.js +2 -2
  147. package/dist/components/GrFormFile/styles.css +1 -1
  148. package/dist/components/GrImageViewer/chunks/{GrImageViewer-DK-iVHHC.js → GrImageViewer-Bnql_dNP.js} +1 -1
  149. package/dist/components/GrImageViewer/chunks/{GrImageViewer-DK-iVHHC.js.map → GrImageViewer-Bnql_dNP.js.map} +1 -1
  150. package/dist/components/GrImageViewer/index.js +1 -1
  151. package/dist/components/GrInput/chunks/{GrInput-DV4gMWPR.js → GrInput-CoaFLpaU.js} +43 -22
  152. package/dist/components/GrInput/chunks/GrInput-CoaFLpaU.js.map +1 -0
  153. package/dist/components/GrInput/index.js +1 -1
  154. package/dist/components/GrInputTag/chunks/{GrInputTag-qnRdAZnn.js → GrInputTag-BzzNRBe3.js} +245 -18
  155. package/dist/components/GrInputTag/chunks/GrInputTag-BzzNRBe3.js.map +1 -0
  156. package/dist/components/GrInputTag/index.js +2 -2
  157. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-D7CyWzhT.js → GrJsonViewer-B6ZJ3GFH.js} +2 -2
  158. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-D7CyWzhT.js.map → GrJsonViewer-B6ZJ3GFH.js.map} +1 -1
  159. package/dist/components/GrJsonViewer/index.js +1 -1
  160. package/dist/components/GrKbd/chunks/{GrKbd-BNMeoaLV.js → GrKbd-D2rHDkQv.js} +42 -37
  161. package/dist/components/GrKbd/chunks/GrKbd-D2rHDkQv.js.map +1 -0
  162. package/dist/components/GrKbd/index.js +1 -1
  163. package/dist/components/GrModal/chunks/{GrModal-Cm0mtSXk.js → GrModal-SHb1U2qx.js} +1 -1
  164. package/dist/components/GrModal/chunks/{GrModal-Cm0mtSXk.js.map → GrModal-SHb1U2qx.js.map} +1 -1
  165. package/dist/components/GrModal/index.js +1 -1
  166. package/dist/components/GrNavbar/chunks/{GrNavbar-BRGuksiy.js → GrNavbar-IEIHC5Vt.js} +10 -4
  167. package/dist/components/GrNavbar/chunks/GrNavbar-IEIHC5Vt.js.map +1 -0
  168. package/dist/components/GrNavbar/index.js +2 -2
  169. package/dist/components/GrNumberInput/chunks/{GrNumberInput-BI6-vkcs.js → GrNumberInput-CmnUDaKi.js} +2 -22
  170. package/dist/components/GrNumberInput/chunks/{GrNumberInput-BI6-vkcs.js.map → GrNumberInput-CmnUDaKi.js.map} +1 -1
  171. package/dist/components/GrNumberInput/index.js +1 -1
  172. package/dist/components/GrPagination/chunks/{GrPagination-CMrLPzvL.js → GrPagination-AMbn5D8I.js} +1 -1
  173. package/dist/components/GrPagination/chunks/{GrPagination-CMrLPzvL.js.map → GrPagination-AMbn5D8I.js.map} +1 -1
  174. package/dist/components/GrPagination/index.js +1 -1
  175. package/dist/components/GrPopover/chunks/{GrPopover-CcWvr1ZA.js → GrPopover-DjVxt8bf.js} +3 -3
  176. package/dist/components/GrPopover/chunks/{GrPopover-CcWvr1ZA.js.map → GrPopover-DjVxt8bf.js.map} +1 -1
  177. package/dist/components/GrPopover/index.js +2 -2
  178. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-BEL-QgwE.js → GrPromptDialog-BhbIZP1f.js} +3 -3
  179. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-BEL-QgwE.js.map → GrPromptDialog-BhbIZP1f.js.map} +1 -1
  180. package/dist/components/GrPromptDialog/index.js +1 -1
  181. package/dist/components/GrSelect/chunks/{GrSelect-DvSq-nV-.js → GrSelect-B-ykrHpL.js} +24 -180
  182. package/dist/components/GrSelect/chunks/GrSelect-B-ykrHpL.js.map +1 -0
  183. package/dist/components/GrSelect/index.js +2 -2
  184. package/dist/components/GrSelect/styles.css +1 -1
  185. package/dist/components/GrSidebar/chunks/GrSidebar-jVvoLGDO.js +543 -0
  186. package/dist/components/GrSidebar/chunks/GrSidebar-jVvoLGDO.js.map +1 -0
  187. package/dist/components/GrSidebar/index.js +2 -2
  188. package/dist/components/GrSlider/chunks/{GrSlider-CO8N9SF6.js → GrSlider-DF2Cq0rV.js} +29 -4
  189. package/dist/components/GrSlider/chunks/GrSlider-DF2Cq0rV.js.map +1 -0
  190. package/dist/components/GrSlider/index.js +2 -2
  191. package/dist/components/GrSortableList/chunks/{GrSortableList-NKriuGm_.js → GrSortableList-ChH9nQBv.js} +1 -1
  192. package/dist/components/GrSortableList/chunks/{GrSortableList-NKriuGm_.js.map → GrSortableList-ChH9nQBv.js.map} +1 -1
  193. package/dist/components/GrSortableList/index.js +2 -2
  194. package/dist/components/GrTabPanels/chunks/GrTabPanels-BDt5oVdd.js +30 -0
  195. package/dist/components/GrTabPanels/chunks/GrTabPanels-BDt5oVdd.js.map +1 -0
  196. package/dist/components/GrTabPanels/chunks/GrTabPanels-BJvAflnA.js +83 -0
  197. package/dist/components/GrTabPanels/chunks/GrTabPanels-BJvAflnA.js.map +1 -0
  198. package/dist/components/GrTabPanels/index.js +2 -1
  199. package/dist/components/GrTable/chunks/{GrTable-CKJ-HrsN.js → GrTable-BQitSDep.js} +52 -16
  200. package/dist/components/GrTable/chunks/GrTable-BQitSDep.js.map +1 -0
  201. package/dist/components/GrTable/index.js +2 -2
  202. package/dist/components/GrTabs/chunks/{GrTabs-s9RzC1WX.js → GrTabs-DVC6nfWB.js} +1 -1
  203. package/dist/components/GrTabs/chunks/{GrTabs-s9RzC1WX.js.map → GrTabs-DVC6nfWB.js.map} +1 -1
  204. package/dist/components/GrTabs/index.js +2 -2
  205. package/dist/components/GrTabsWithPanels/chunks/GrTabsWithPanels-BYtuzouj.js +98 -0
  206. package/dist/components/GrTabsWithPanels/chunks/GrTabsWithPanels-BYtuzouj.js.map +1 -0
  207. package/dist/components/GrTabsWithPanels/index.js +3 -0
  208. package/dist/components/GrTextarea/chunks/{GrTextarea-Bfgc0DD2.js → GrTextarea-BFwyqcHB.js} +22 -5
  209. package/dist/components/GrTextarea/chunks/GrTextarea-BFwyqcHB.js.map +1 -0
  210. package/dist/components/GrTextarea/index.js +1 -1
  211. package/dist/components/GrToaster/chunks/{GrToaster-CZixNk0l.js → GrToaster-OzT1VKcp.js} +163 -32
  212. package/dist/components/GrToaster/chunks/GrToaster-OzT1VKcp.js.map +1 -0
  213. package/dist/components/GrToaster/index.js +2 -2
  214. package/dist/components/GrToaster/styles.css +1 -1
  215. package/dist/components/GrTooltip/chunks/{GrTooltip-DkMMM0uq.js → GrTooltip-BDcFycvW.js} +26 -13
  216. package/dist/components/GrTooltip/chunks/GrTooltip-BDcFycvW.js.map +1 -0
  217. package/dist/components/GrTooltip/index.js +2 -2
  218. package/dist/components/GrTransfer/chunks/{GrTransfer-DdfBUf35.js → GrTransfer-CV7BL5UK.js} +114 -12
  219. package/dist/components/GrTransfer/chunks/GrTransfer-CV7BL5UK.js.map +1 -0
  220. package/dist/components/GrTransfer/index.js +1 -1
  221. package/dist/components/GrTransfer/styles.css +1 -1
  222. package/dist/components/GrTree/chunks/{GrTree-6yZrncJE.js → GrTree-DpgaP8hk.js} +39 -1
  223. package/dist/components/GrTree/chunks/GrTree-DpgaP8hk.js.map +1 -0
  224. package/dist/components/GrTree/index.js +1 -1
  225. package/dist/components/GrTree/styles.css +1 -1
  226. package/dist/components/GrTreeSections/chunks/{GrTreeSections-DcmDcLwj.js → GrTreeSections-BeOj__44.js} +1 -1
  227. package/dist/components/GrTreeSections/chunks/{GrTreeSections-DcmDcLwj.js.map → GrTreeSections-BeOj__44.js.map} +1 -1
  228. package/dist/components/GrTreeSections/index.js +1 -1
  229. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-B6KoDYiZ.js → GrTreeSelect-BHq-T8wH.js} +113 -14
  230. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-BHq-T8wH.js.map +1 -0
  231. package/dist/components/GrTreeSelect/index.js +2 -2
  232. package/dist/composables/useFloating.js +1 -1
  233. package/dist/composables/useHotkeys.js +89 -0
  234. package/dist/composables/useHotkeys.js.map +1 -0
  235. package/dist/composables/useOverlayLayer.js +1 -1
  236. package/dist/directives/hotkey.js +19 -46
  237. package/dist/directives/hotkey.js.map +1 -1
  238. package/dist/granular-provider-node.js +1 -1
  239. package/dist/granular-provider.js +1 -1
  240. package/dist/i18n/all.js +1 -1
  241. package/dist/i18n/index.js +1 -1
  242. package/dist/index.js +71 -63
  243. package/dist/theme.js +1 -1
  244. package/dist/tokens.js +1 -1
  245. package/dist/types/components/GrAutocomplete/GrAutocomplete.vue.d.ts +4 -4
  246. package/dist/types/components/GrAutocomplete/composables/useAutocompleteNavigation.d.ts +12 -3
  247. package/dist/types/components/GrAutocomplete/composables/useAutocompletePanel.d.ts +12 -2
  248. package/dist/types/components/GrAutocomplete/composables/useAutocompleteValues.d.ts +7 -4
  249. package/dist/types/components/GrAutocomplete/composables/useRemoteOptions.d.ts +4 -4
  250. package/dist/types/components/GrAutocomplete/grAutocompleteStyles.d.ts +15 -1
  251. package/dist/types/components/GrAutocomplete/index.d.ts +1 -1
  252. package/dist/types/components/GrCarousel/GrCarousel.vue.d.ts +29 -1
  253. package/dist/types/components/GrCarousel/composables/useCarouselSwipe.d.ts +5 -0
  254. package/dist/types/components/GrCarousel/grCarouselContext.d.ts +21 -0
  255. package/dist/types/components/GrCarousel/grCarouselStyles.d.ts +39 -9
  256. package/dist/types/components/GrCheckbox/GrCheckbox.vue.d.ts +13 -0
  257. package/dist/types/components/GrColorPicker/GrColorPicker.vue.d.ts +18 -2
  258. package/dist/types/components/GrColorPicker/color.d.ts +13 -1
  259. package/dist/types/components/GrColorPicker/colorArea.d.ts +59 -0
  260. package/dist/types/components/GrColorPicker/defaults.d.ts +3 -1
  261. package/dist/types/components/GrColorPicker/eyeDropper.d.ts +21 -0
  262. package/dist/types/components/GrColorPicker/grColorPickerStyles.d.ts +42 -0
  263. package/dist/types/components/GrCommandPalette/GrCommandPalette.vue.d.ts +10 -1
  264. package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +41 -1
  265. package/dist/types/components/GrDataTable/composables/useDataTableGridNavigation.d.ts +53 -0
  266. package/dist/types/components/GrDataTable/grDataTableStyles.d.ts +8 -0
  267. package/dist/types/components/GrDataTable/index.d.ts +1 -1
  268. package/dist/types/components/GrDelta/grDeltaStyles.d.ts +10 -3
  269. package/dist/types/components/GrEmptyState/GrEmptyState.vue.d.ts +11 -2
  270. package/dist/types/components/GrEmptyState/grEmptyStateStyles.d.ts +10 -0
  271. package/dist/types/components/GrEmptyState/index.d.ts +1 -1
  272. package/dist/types/components/GrFileUpload/GrFileUpload.vue.d.ts +2 -1
  273. package/dist/types/components/GrFormFile/GrFormFile.vue.d.ts +10 -0
  274. package/dist/types/components/GrInput/GrInput.vue.d.ts +15 -0
  275. package/dist/types/components/GrInputTag/GrInputTag.vue.d.ts +16 -0
  276. package/dist/types/components/GrInputTag/grInputTagStyles.d.ts +11 -0
  277. package/dist/types/components/GrKbd/GrKbd.vue.d.ts +14 -0
  278. package/dist/types/components/GrNavbar/GrNavbar.vue.d.ts +18 -0
  279. package/dist/types/components/GrNavbar/grNavbarStyles.d.ts +10 -1
  280. package/dist/types/components/GrNavbar/index.d.ts +1 -0
  281. package/dist/types/components/GrSelect/composables/useSelectPanelItems.d.ts +8 -34
  282. package/dist/types/components/GrSelect/composables/useSelectVirtualization.d.ts +7 -0
  283. package/dist/types/components/GrSelect/grSelectStyles.d.ts +1 -1
  284. package/dist/types/components/GrSidebar/GrSidebar.vue.d.ts +20 -0
  285. package/dist/types/components/GrSidebar/GrSidebarItem.vue.d.ts +39 -5
  286. package/dist/types/components/GrSidebar/grSidebarStyles.d.ts +32 -0
  287. package/dist/types/components/GrSidebar/index.d.ts +1 -1
  288. package/dist/types/components/GrSidebar/sidebarContext.d.ts +23 -1
  289. package/dist/types/components/GrSlider/GrSlider.vue.d.ts +39 -1
  290. package/dist/types/components/GrSlider/grSliderStyles.d.ts +1 -1
  291. package/dist/types/components/GrTabPanels/context.d.ts +6 -0
  292. package/dist/types/components/GrTable/GrTable.vue.d.ts +37 -0
  293. package/dist/types/components/GrTable/grTableStyles.d.ts +16 -7
  294. package/dist/types/components/GrTabsWithPanels/GrTabsWithPanels.vue.d.ts +77 -0
  295. package/dist/types/components/GrTabsWithPanels/config.d.ts +1 -0
  296. package/dist/types/components/GrTabsWithPanels/index.d.ts +4 -0
  297. package/dist/types/components/GrTextarea/GrTextarea.vue.d.ts +19 -1
  298. package/dist/types/components/GrToaster/GrToaster.vue.d.ts +12 -0
  299. package/dist/types/components/GrToaster/grToasterStyles.d.ts +26 -0
  300. package/dist/types/components/GrTooltip/GrTooltip.vue.d.ts +22 -0
  301. package/dist/types/components/GrTransfer/GrTransfer.vue.d.ts +23 -0
  302. package/dist/types/components/GrTreeSelect/grTreeSelectStyles.d.ts +1 -1
  303. package/dist/types/components/GrTreeSelect/grTreeSelectTypes.d.ts +20 -0
  304. package/dist/types/components/shared/hotkey.d.ts +8 -9
  305. package/dist/types/components/shared/optionPanel.d.ts +100 -0
  306. package/dist/types/components/shared/overlayListPanel.d.ts +18 -0
  307. package/dist/types/composables/useHotkeys.d.ts +43 -0
  308. package/dist/types/granular-provider/shared.d.ts +1 -0
  309. package/dist/types/i18n/messages/en.d.ts +28 -0
  310. package/dist/types/i18n/messages/es.d.ts +28 -0
  311. package/dist/types/i18n/messages/ru.d.ts +28 -0
  312. package/dist/types/index.d.ts +3 -0
  313. package/dist/types/internal/hotkeySequence.d.ts +22 -0
  314. package/dist/types/internal/keyboard.d.ts +45 -0
  315. package/dist/web-types.json +463 -26
  316. package/package.json +9 -1
  317. package/dist/chunks/config-2ZHRsdOc.js.map +0 -1
  318. package/dist/chunks/config-B42iJ48O.js.map +0 -1
  319. package/dist/chunks/config-B5SBUa6u.js.map +0 -1
  320. package/dist/chunks/config-BAse0laT.js.map +0 -1
  321. package/dist/chunks/config-BHLMTJaR.js.map +0 -1
  322. package/dist/chunks/config-BXRmsn3t.js.map +0 -1
  323. package/dist/chunks/config-Bs1HwUcx.js.map +0 -1
  324. package/dist/chunks/config-CMNfZO7S.js.map +0 -1
  325. package/dist/chunks/config-CbEbLyDE.js.map +0 -1
  326. package/dist/chunks/config-CjWOTgLL.js.map +0 -1
  327. package/dist/chunks/config-D3HOuHDe.js.map +0 -1
  328. package/dist/chunks/config-DIDz_E5m.js.map +0 -1
  329. package/dist/chunks/config-DNDgp9bB.js.map +0 -1
  330. package/dist/chunks/config-iemgzS4x.js.map +0 -1
  331. package/dist/chunks/en-CsQUoBS2.js.map +0 -1
  332. package/dist/chunks/es-9nbkPvdA.js.map +0 -1
  333. package/dist/chunks/grSelectStyles-D9EQ-pgK.js.map +0 -1
  334. package/dist/chunks/grSliderStyles-kaz6VXZ3.js.map +0 -1
  335. package/dist/chunks/grTableStyles-DkQPMfx9.js +0 -39
  336. package/dist/chunks/grTableStyles-DkQPMfx9.js.map +0 -1
  337. package/dist/chunks/granular-provider-B6xomapW.js.map +0 -1
  338. package/dist/chunks/keyboard-DE2yhz_b.js.map +0 -1
  339. package/dist/chunks/overlayPanelSurface-BKeMhRx4.js.map +0 -1
  340. package/dist/chunks/ru-88i1WG0b.js.map +0 -1
  341. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-Chhw65pI.js.map +0 -1
  342. package/dist/components/GrCarousel/chunks/GrCarousel-ByuughtI.js.map +0 -1
  343. package/dist/components/GrCheckbox/chunks/GrCheckbox-Dp201frb.js.map +0 -1
  344. package/dist/components/GrColorPicker/chunks/GrColorPicker-BRM_4lyI.js.map +0 -1
  345. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-BJHmkDQv.js.map +0 -1
  346. package/dist/components/GrDataTable/chunks/GrDataTable-DQxYYgQk.js.map +0 -1
  347. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-Dxkz_ry4.js.map +0 -1
  348. package/dist/components/GrEmptyState/chunks/GrEmptyState-BbvwE-E0.js.map +0 -1
  349. package/dist/components/GrFileUpload/chunks/GrFileUpload-BwMR71zN.js.map +0 -1
  350. package/dist/components/GrFormFile/chunks/GrFormFile-Dlxx-9zi.js.map +0 -1
  351. package/dist/components/GrInput/chunks/GrInput-DV4gMWPR.js.map +0 -1
  352. package/dist/components/GrInputTag/chunks/GrInputTag-qnRdAZnn.js.map +0 -1
  353. package/dist/components/GrKbd/chunks/GrKbd-BNMeoaLV.js.map +0 -1
  354. package/dist/components/GrNavbar/chunks/GrNavbar-BRGuksiy.js.map +0 -1
  355. package/dist/components/GrSelect/chunks/GrSelect-DvSq-nV-.js.map +0 -1
  356. package/dist/components/GrSidebar/chunks/GrSidebar-DoKLlHSw.js +0 -264
  357. package/dist/components/GrSidebar/chunks/GrSidebar-DoKLlHSw.js.map +0 -1
  358. package/dist/components/GrSlider/chunks/GrSlider-CO8N9SF6.js.map +0 -1
  359. package/dist/components/GrTabPanels/chunks/GrTabPanels-5zsbqS1v.js +0 -92
  360. package/dist/components/GrTabPanels/chunks/GrTabPanels-5zsbqS1v.js.map +0 -1
  361. package/dist/components/GrTable/chunks/GrTable-CKJ-HrsN.js.map +0 -1
  362. package/dist/components/GrTextarea/chunks/GrTextarea-Bfgc0DD2.js.map +0 -1
  363. package/dist/components/GrToaster/chunks/GrToaster-CZixNk0l.js.map +0 -1
  364. package/dist/components/GrTooltip/chunks/GrTooltip-DkMMM0uq.js.map +0 -1
  365. package/dist/components/GrTransfer/chunks/GrTransfer-DdfBUf35.js.map +0 -1
  366. package/dist/components/GrTree/chunks/GrTree-6yZrncJE.js.map +0 -1
  367. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-B6KoDYiZ.js.map +0 -1
  368. package/dist/types/components/GrAutocomplete/composables/useAutocompleteVirtual.d.ts +0 -33
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrDataTable-Bb2jWnRG.js","names":["$slots"],"sources":["../../../../src/components/GrDataTable/composables/useDataTableRowKeys.ts","../../../../src/components/GrDataTable/grDataTableSort.ts","../../../../src/components/GrDataTable/composables/useDataTableSort.ts","../../../../src/components/GrDataTable/composables/useDataTableSelection.ts","../../../../src/components/GrDataTable/composables/useDataTableColumnOrder.ts","../../../../src/components/GrDataTable/composables/useDataTableColumnWidths.ts","../../../../src/components/GrDataTable/composables/useDataTableLayout.ts","../../../../src/components/GrDataTable/composables/useDataTableExpansion.ts","../../../../src/components/GrDataTable/composables/useDataTableGridNavigation.ts","../../../../src/components/GrDataTable/GrDataTable.vue","../../../../src/components/GrDataTable/GrDataTable.vue"],"sourcesContent":["import type { GrDataTableRowKey } from '../GrDataTable.vue'\n\n/**\n * Ключ строки: значение из данных, а при его отсутствии — синтетический.\n *\n * Без синтетического строка получила бы `String(undefined ?? '')` — **один и\n * тот же** ключ на всю таблицу: Vue переиспользовал бы DOM не по назначению, а\n * выбор одной строки помечал бы выбранными все. Ключ привязан к идентичности\n * объекта, поэтому переживает сортировку и не зависит от индекса.\n */\nexport interface UseDataTableRowKeysOptions<TRow extends Record<string, unknown>> {\n rowKey: () => GrDataTableRowKey<TRow>\n}\n\nexport interface DataTableRowKeys<TRow extends Record<string, unknown>> {\n rowKeyValue: (row: TRow) => string | number\n}\n\nexport function useDataTableRowKeys<TRow extends Record<string, unknown>>(\n options: UseDataTableRowKeysOptions<TRow>,\n): DataTableRowKeys<TRow> {\n const syntheticKeys = new WeakMap<object, string>()\n let syntheticKeyCounter = 0\n // Предупреждение одно на таблицу: строк без ключа обычно весь набор, и на\n // каждую пришлось бы по записи в консоли.\n let missingKeyWarned = false\n\n function syntheticRowKey(row: TRow): string {\n const existing = syntheticKeys.get(row)\n if (existing !== undefined)\n return existing\n\n syntheticKeyCounter += 1\n const generated = `gr-row-${syntheticKeyCounter}`\n syntheticKeys.set(row, generated)\n\n if (!missingKeyWarned && __GR_DEV__) {\n missingKeyWarned = true\n console.warn(\n `[GrDataTable] У строки нет значения по ключу \"${String(options.rowKey())}\". `\n + 'Задайте `rowKey` (поле или функцию) — иначе выбор строк и переиспользование '\n + 'DOM работают по синтетическому ключу, который не переживёт перезагрузку данных.',\n )\n }\n\n return generated\n }\n\n function rowKeyValue(row: TRow): string | number {\n const rk = options.rowKey()\n if (typeof rk === 'function')\n return rk(row)\n\n const value = (row as Record<string, unknown>)[rk as string]\n if (typeof value === 'string' && value !== '')\n return value\n if (typeof value === 'number')\n return value\n\n return syntheticRowKey(row)\n }\n\n return { rowKeyValue }\n}\n","/**\n * Сравнение значений ячеек для сортировки `GrDataTable`.\n *\n * Логика вынесена из SFC: у неё есть крайние случаи, которые дешевле проверить\n * прямым вызовом, чем через монтирование таблицы.\n *\n * Прежняя реализация приводила значение к числу через `Number(value)`, а он\n * считает нулём и `null`, и пустую строку: пустые ячейки оседали в середине\n * числового ряда, между отрицательными и положительными. Здесь пустое значение —\n * отдельная категория, и она всегда в конце, независимо от направления.\n */\n\nexport type GrDataTableSortDir = 'asc' | 'desc'\n\n/** Пустое значение ячейки: нечего сравнивать, место таким — в конце списка. */\nexport function isEmptyCell(value: unknown): boolean {\n if (value === null || value === undefined)\n return true\n\n return typeof value === 'string' && value.trim() === ''\n}\n\n/**\n * Число, с которым имеет смысл сравнивать: сам `number`, числовая строка, `Date`\n * (по таймстампу), `boolean` (`false` < `true`). Иначе — `null`, и сравнение\n * уходит в строковую ветку.\n */\nfunction toComparableNumber(value: unknown): number | null {\n if (typeof value === 'number')\n return Number.isFinite(value) ? value : null\n\n if (typeof value === 'boolean')\n return value ? 1 : 0\n\n if (typeof value === 'bigint')\n return Number(value)\n\n if (value instanceof Date) {\n const time = value.getTime()\n return Number.isNaN(time) ? null : time\n }\n\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (trimmed === '')\n return null\n\n const parsed = Number(trimmed)\n return Number.isFinite(parsed) ? parsed : null\n }\n\n return null\n}\n\n/**\n * Сравнивает два значения ячейки. Возвращает готовую разницу с учётом `dir` —\n * кроме пустых значений: они всегда в конце, иначе «пустые» в `desc` уезжали бы\n * наверх и таблица выглядела бы сломанной.\n */\nexport function compareCells(\n a: unknown,\n b: unknown,\n dir: GrDataTableSortDir,\n locale?: string,\n): number {\n const aEmpty = isEmptyCell(a)\n const bEmpty = isEmptyCell(b)\n if (aEmpty || bEmpty)\n return aEmpty && bEmpty ? 0 : (aEmpty ? 1 : -1)\n\n const aNum = toComparableNumber(a)\n const bNum = toComparableNumber(b)\n\n const result = aNum !== null && bNum !== null\n ? aNum - bNum\n : String(a).localeCompare(String(b), locale, { sensitivity: 'base', numeric: true })\n\n return dir === 'asc' ? result : -result\n}\n\n/**\n * Новый отсортированный массив. Исходный не мутируется: `rows` приходят пропом,\n * сортировка на месте меняла бы данные потребителя.\n */\nexport function sortRows<TRow extends Record<string, unknown>>(\n rows: readonly TRow[],\n key: string,\n dir: GrDataTableSortDir,\n locale?: string,\n): TRow[] {\n return [...rows].sort((a, b) => compareCells(a[key], b[key], dir, locale))\n}\n","import type { ComputedRef } from 'vue'\nimport { computed, ref } from 'vue'\n\nimport type { GrDataColumn, GrDataTableSortCycle } from '../GrDataTable.vue'\nimport type { GrDataTableSortDir } from '../grDataTableSort'\nimport { sortRows } from '../grDataTableSort'\n\n/**\n * Сортировка `GrDataTable`: состояние, порядок строк и обход состояний по клику.\n *\n * Модель эмитов не знает — о смене сообщает колбэком `onSortChange`, а\n * `update:sortKey`/`update:sortDir`/`sortChange` остаются заботой компонента.\n * Так же устроен `GrTree`: модель отдельно, эмиты связывает SFC.\n *\n * Сравнение значений, включая пустые и смешанные типы, живёт в\n * `grDataTableSort.ts` и здесь только вызывается.\n */\nexport interface UseDataTableSortOptions<TRow extends Record<string, unknown>> {\n rows: () => TRow[]\n /** Контролируемый ключ. `undefined` — компонент помнит порядок сам. */\n sortKey: () => string | undefined\n /** Контролируемое направление. */\n sortDir: () => GrDataTableSortDir | undefined\n initialSortKey: () => string | undefined\n initialSortDir: () => GrDataTableSortDir\n /** Внешняя сортировка: `rows` приходят уже отсортированными. */\n externalSort: () => boolean\n sortCycle: () => GrDataTableSortCycle\n /** Язык сравнения строк; не задан — сравнение по умолчанию рантайма. */\n locale: () => string | undefined\n onSortChange: (key: string, dir: GrDataTableSortDir) => void\n}\n\nexport interface DataTableSort<TRow extends Record<string, unknown>> {\n currentSortKey: ComputedRef<string>\n currentSortDir: ComputedRef<GrDataTableSortDir>\n sortedRows: ComputedRef<TRow[]>\n toggleSort: (col: GrDataColumn<TRow>) => void\n clearSort: () => void\n ariaSortFor: (col: GrDataColumn<TRow>) => 'ascending' | 'descending' | 'none' | undefined\n}\n\nexport function useDataTableSort<TRow extends Record<string, unknown>>(\n options: UseDataTableSortOptions<TRow>,\n): DataTableSort<TRow> {\n // Uncontrolled-состояние; в controlled-режиме перекрывается пропами.\n const internalSortKey = ref<string>(options.initialSortKey() ?? '')\n const internalSortDir = ref<GrDataTableSortDir>(options.initialSortDir())\n\n const isSortKeyControlled = computed(() => options.sortKey() !== undefined)\n const isSortDirControlled = computed(() => options.sortDir() !== undefined)\n\n const currentSortKey = computed(() => options.sortKey() ?? internalSortKey.value)\n const currentSortDir = computed<GrDataTableSortDir>(() => options.sortDir() ?? internalSortDir.value)\n\n function applySort(key: string, dir: GrDataTableSortDir): void {\n if (!isSortKeyControlled.value)\n internalSortKey.value = key\n if (!isSortDirControlled.value)\n internalSortDir.value = dir\n\n options.onSortChange(key, dir)\n }\n\n const sortedRows = computed(() => {\n // Внешняя сортировка: `rows` уже отсортированы потребителем — не трогаем.\n if (options.externalSort())\n return [...options.rows()]\n\n const key = currentSortKey.value\n if (!key)\n return [...options.rows()]\n\n return sortRows(options.rows(), key, currentSortDir.value, options.locale())\n })\n\n function toggleSort(col: GrDataColumn<TRow>): void {\n if (!col.sortable)\n return\n\n if (currentSortKey.value !== col.key) {\n applySort(col.key, 'asc')\n return\n }\n\n if (currentSortDir.value === 'asc') {\n applySort(col.key, 'desc')\n return\n }\n\n // Третье состояние: сортировка снимается, порядок возвращается к исходному.\n if (options.sortCycle() === 'asc-desc-none') {\n applySort('', 'asc')\n return\n }\n\n applySort(col.key, 'asc')\n }\n\n function clearSort(): void {\n applySort('', 'asc')\n }\n\n function ariaSortFor(col: GrDataColumn<TRow>): 'ascending' | 'descending' | 'none' | undefined {\n if (!col.sortable)\n return undefined\n if (currentSortKey.value !== col.key)\n return 'none'\n return currentSortDir.value === 'asc' ? 'ascending' : 'descending'\n }\n\n return { currentSortKey, currentSortDir, sortedRows, toggleSort, clearSort, ariaSortFor }\n}\n","import type { ComputedRef } from 'vue'\nimport { computed, ref } from 'vue'\n\n/**\n * Выбор строк `GrDataTable`.\n *\n * Считается по **видимым и выбираемым** строкам: они же дают состояние\n * галочки в шапке. Ключи строк, которых сейчас в наборе нет (отфильтрованы,\n * на другой странице), из выбора не выпадают — «снять все» убирает только\n * видимые.\n *\n * Как и сортировка, эмитов не знает: наружу сообщает `onSelectedChange`.\n */\nexport interface UseDataTableSelectionOptions<TRow extends Record<string, unknown>> {\n /** Строки в текущем порядке — уже отсортированные. */\n rows: () => TRow[]\n /** Контролируемый список ключей. `undefined` — компонент помнит выбор сам. */\n selected: () => Array<string | number> | undefined\n selectableRow: () => ((row: TRow) => boolean) | undefined\n rowKeyValue: (row: TRow) => string | number\n onSelectedChange: (keys: Array<string | number>) => void\n}\n\nexport interface DataTableSelection<TRow extends Record<string, unknown>> {\n selectedKeys: ComputedRef<Set<string | number>>\n isRowSelectable: (row: TRow) => boolean\n isRowSelected: (row: TRow) => boolean\n /** Видимые выбираемые строки: по их числу шапка гасит «выбрать все». */\n selectableRows: ComputedRef<TRow[]>\n allSelected: ComputedRef<boolean>\n someSelected: ComputedRef<boolean>\n toggleRow: (row: TRow) => void\n toggleAll: () => void\n}\n\nexport function useDataTableSelection<TRow extends Record<string, unknown>>(\n options: UseDataTableSelectionOptions<TRow>,\n): DataTableSelection<TRow> {\n const internalSelected = ref<Array<string | number>>([])\n const isSelectedControlled = computed(() => options.selected() !== undefined)\n\n const selectedKeys = computed<Set<string | number>>(\n () => new Set(options.selected() ?? internalSelected.value),\n )\n\n function isRowSelectable(row: TRow): boolean {\n const predicate = options.selectableRow()\n return predicate ? predicate(row) : true\n }\n\n function isRowSelected(row: TRow): boolean {\n return selectedKeys.value.has(options.rowKeyValue(row))\n }\n\n /** «Выбрать все» работает по видимым и выбираемым строкам — они же считают состояние шапки. */\n const selectableRows = computed(() => options.rows().filter(isRowSelectable))\n\n const allSelected = computed(() =>\n selectableRows.value.length > 0 && selectableRows.value.every(isRowSelected),\n )\n const someSelected = computed(() =>\n selectableRows.value.some(isRowSelected) && !allSelected.value,\n )\n\n function emitSelected(next: Set<string | number>): void {\n if (!isSelectedControlled.value)\n internalSelected.value = [...next]\n\n options.onSelectedChange([...next])\n }\n\n function toggleRow(row: TRow): void {\n if (!isRowSelectable(row))\n return\n\n const key = options.rowKeyValue(row)\n const next = new Set(selectedKeys.value)\n if (next.has(key))\n next.delete(key)\n else\n next.add(key)\n emitSelected(next)\n }\n\n function toggleAll(): void {\n const next = new Set(selectedKeys.value)\n\n if (allSelected.value) {\n // Снимаем выбор только с видимых строк, сохраняя внешние ключи.\n for (const row of selectableRows.value) next.delete(options.rowKeyValue(row))\n emitSelected(next)\n return\n }\n\n for (const row of selectableRows.value) next.add(options.rowKeyValue(row))\n emitSelected(next)\n }\n\n return {\n selectedKeys,\n isRowSelectable,\n isRowSelected,\n selectableRows,\n allSelected,\n someSelected,\n toggleRow,\n toggleAll,\n }\n}\n","import type { ComputedRef } from 'vue'\nimport { computed, nextTick, ref } from 'vue'\n\nimport { useDragSort } from '../../../composables/useDragSort'\nimport { useRovingFocus } from '../../../composables/useRovingFocus'\nimport { insertionIndex, moveItem } from '../../../composables/internal/dragSortGeometry'\nimport type { GrDataColumn } from '../GrDataTable.vue'\nimport { columnDropAfterClass, columnDropBeforeClass } from '../grDataTableStyles'\n\n/**\n * Порядок колонок `GrDataTable`: перестановка указателем и с клавиатуры.\n *\n * Закреплённые колонки стоят своими группами у своих краёв, и перенос через\n * границу группы запрещён — иначе «закреплена слева» перестало бы означать\n * «слева». Отсюда `pinGroupOf` и проверка `sameGroup` в каждом пути переноса.\n *\n * Карты элементов приходят снаружи: их наполняет шаблон, и они же нужны\n * модулям ширины и раскладки — владеть ими единолично этот модуль не может.\n */\nexport interface UseDataTableColumnOrderOptions<TRow extends Record<string, unknown>> {\n columns: () => GrDataColumn<TRow>[]\n /** Контролируемый порядок. `undefined` — компонент помнит порядок сам. */\n columnOrder: () => string[] | undefined\n reorderableColumns: () => boolean\n loading: () => boolean\n /** Заголовочные ячейки по ключу колонки — цель перетаскивания. */\n headerCellEls: Map<string, HTMLElement>\n /** Ручки переноса по ключу колонки — кольцо роверного фокуса. */\n columnHandleEls: Map<string, HTMLElement>\n onOrderChange: (order: string[], moved: { key: string, from: number, to: number }) => void\n /** Объявление в живой регион: перенос указателем без него беззвучен. */\n announceMove: (label: string, position: number, count: number) => void\n}\n\nexport interface DataTableColumnOrder<TRow extends Record<string, unknown>> {\n orderedColumns: ComputedRef<GrDataColumn<TRow>[]>\n columnKeys: ComputedRef<string[]>\n pinGroupOf: (col: GrDataColumn<TRow>) => number\n indexOfColumn: (key: string) => number\n draggingColumnKey: ComputedRef<string | null>\n columnDropClass: (index: number) => string\n onColumnHandleKeydown: (event: KeyboardEvent, key: string) => Promise<void>\n /** Жест и кольцо фокуса отдаются целиком: шаблон зовёт их собственный API. */\n columnSort: ReturnType<typeof useDragSort<string, number>>\n columnRoving: ReturnType<typeof useRovingFocus<string>>\n}\n\nexport function useDataTableColumnOrder<TRow extends Record<string, unknown>>(\n options: UseDataTableColumnOrderOptions<TRow>,\n): DataTableColumnOrder<TRow> {\n /** Uncontrolled-состояние; в controlled-режиме перекрывается пропом `columnOrder`. */\n const internalColumnOrder = ref<string[]>(options.columns().map(col => String(col.key)))\n\n /**\n * Колонки в пользовательском порядке.\n *\n * Состав задаёт `columns`, порядок — только порядок: ключ, которого в наборе\n * нет, игнорируется, а колонка, которой нет в порядке (её только что\n * добавили), встаёт в конец. Иначе правка `columns` теряла бы колонки молча.\n */\n const orderedColumns = computed<GrDataColumn<TRow>[]>(() => {\n const order = options.columnOrder() ?? internalColumnOrder.value\n const remaining = new Map(options.columns().map(col => [String(col.key), col]))\n const ordered: GrDataColumn<TRow>[] = []\n\n for (const key of order) {\n const col = remaining.get(key)\n if (!col)\n continue\n\n remaining.delete(key)\n ordered.push(col)\n }\n\n for (const col of options.columns()) {\n if (remaining.has(String(col.key)))\n ordered.push(col)\n }\n\n // Закреплённые колонки стоят своими группами у своих краёв — иначе\n // «закреплена слева» не означало бы «слева». Сортировка устойчивая, поэтому\n // внутри группы порядок остаётся пользовательским.\n return ordered.sort((a, b) => pinGroupOf(a) - pinGroupOf(b))\n })\n\n /** Группа закрепления: 0 — слева, 1 — обычная колонка, 2 — справа. */\n function pinGroupOf(col: GrDataColumn<TRow>): number {\n if (col.pinned === 'left')\n return 0\n if (col.pinned === 'right')\n return 2\n\n return 1\n }\n\n const columnKeys = computed(() => orderedColumns.value.map(col => String(col.key)))\n\n function indexOfColumn(key: string): number {\n return columnKeys.value.indexOf(key)\n }\n\n function sameGroup(from: number, to: number): boolean {\n const cols = orderedColumns.value\n if (!cols[from] || !cols[to])\n return false\n\n return pinGroupOf(cols[from]) === pinGroupOf(cols[to])\n }\n\n function applyColumnMove(from: number, to: number): void {\n const keys = columnKeys.value\n if (from < 0 || to < 0 || to >= keys.length || from === to)\n return\n if (!sameGroup(from, to))\n return\n\n const key = keys[from]\n // Подпись берётся до перестановки: `orderedColumns` — computed, и после\n // записи порядка по индексу `from` стоит уже другая колонка.\n const label = orderedColumns.value[from]?.label ?? key\n const next = moveItem(keys, from, to)\n\n internalColumnOrder.value = next\n options.onOrderChange(next, { key, from, to })\n options.announceMove(label, to + 1, keys.length)\n }\n\n const columnSort = useDragSort<string, number>({\n items: () => columnKeys.value,\n elementFor: key => options.headerCellEls.get(key) ?? null,\n orientation: () => 'horizontal',\n disabled: () => !options.reorderableColumns() || options.loading(),\n resolveTarget: (hit, source) => {\n const to = insertionIndex(hit, indexOfColumn(source), columnKeys.value.length)\n\n // Через границу закрепления не переносим: группы у краёв постоянны.\n return sameGroup(indexOfColumn(source), to) ? to : null\n },\n onDrop: (source, to) => applyColumnMove(indexOfColumn(source), to),\n })\n\n /**\n * Кольцо роверного фокуса по ручкам: одна остановка `Tab` на всю шапку.\n * Иначе таблица из десяти колонок добавляла бы десять таб-стопов подряд.\n */\n const columnRoving = useRovingFocus<string>({\n items: () => (options.reorderableColumns() ? columnKeys.value : []),\n elementFor: key => options.columnHandleEls.get(key) ?? null,\n orientation: () => 'horizontal',\n wrap: () => false,\n })\n\n async function onColumnHandleKeydown(event: KeyboardEvent, key: string): Promise<void> {\n if (!options.reorderableColumns())\n return\n\n // `Shift` со стрелкой двигает колонку, голая стрелка — фокус между ручками.\n // Раскладка та же, что у переноса узла в `GrTree`.\n if (event.shiftKey && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {\n event.preventDefault()\n\n const from = indexOfColumn(key)\n applyColumnMove(from, event.key === 'ArrowLeft' ? from - 1 : from + 1)\n\n // Шапка перерисовывается: без возврата фокуса следующий `Shift` было бы\n // некуда адресовать.\n await nextTick()\n await columnRoving.focusKey(key)\n return\n }\n\n columnRoving.handleNavigationKeys(event)\n }\n\n const draggingColumnKey = computed(() => (columnSort.mode.value === null ? null : columnSort.source.value))\n\n /** Полоса места вставки — на колонке-соседе, со стороны движения. */\n function columnDropClass(index: number): string {\n const target = columnSort.target.value\n if (!columnSort.isActive.value || target === null || target !== index)\n return ''\n\n const active = columnSort.source.value === null ? -1 : indexOfColumn(columnSort.source.value)\n if (index === active)\n return ''\n\n return target < active ? columnDropBeforeClass : columnDropAfterClass\n }\n\n return {\n orderedColumns,\n columnKeys,\n pinGroupOf,\n indexOfColumn,\n draggingColumnKey,\n columnDropClass,\n onColumnHandleKeydown,\n columnSort,\n columnRoving,\n }\n}\n","import type { ComputedRef, Ref } from 'vue'\nimport { computed, ref } from 'vue'\n\nimport { useDragGesture } from '../../../composables/useDragGesture'\nimport type { GrDataColumn } from '../GrDataTable.vue'\n\n/** Уже колонки не бывает: в неё перестаёт помещаться даже стрелка сортировки. */\nexport const MIN_COLUMN_WIDTH = 48\n\n/** Шаг клавиатуры и крупный шаг — как у `GrSplitter`. */\nconst RESIZE_STEP = 16\nconst RESIZE_BIG_STEP = 48\n\n/**\n * Ширина колонок `GrDataTable`: протяжка ручки, клавиатура и сброс к авторазметке.\n *\n * Измеренные ширины сюда **приходят снаружи** (`setMeasuredWidths`): замер —\n * дело раскладки, которая ходит в DOM после отрисовки, а здесь они только\n * читаются, чтобы ручка называла значение с первого рендера.\n */\nexport interface UseDataTableColumnWidthsOptions<TRow extends Record<string, unknown>> {\n /** Колонки в текущем порядке — по ним считается минимальная ширина таблицы. */\n orderedColumns: () => GrDataColumn<TRow>[]\n /** Контролируемые ширины. `undefined` — компонент помнит их сам. */\n columnWidths: () => Record<string, number> | undefined\n resizableColumns: () => boolean\n loading: () => boolean\n /** Заголовочные ячейки: стартовая ширина протяжки берётся замером. */\n headerCellEls: Map<string, HTMLElement>\n onWidthsChange: (widths: Record<string, number>) => void\n onColumnResize: (key: string, width: number) => void\n announceWidth: (label: string, width: number) => void\n}\n\nexport interface DataTableColumnWidths<TRow extends Record<string, unknown>> {\n columnWidths: ComputedRef<Record<string, number>>\n measuredColumnWidths: Ref<Record<string, number>>\n setMeasuredWidths: (widths: Record<string, number>) => void\n widthOf: (col: GrDataColumn<TRow>) => string | number | undefined\n tableMinWidth: ComputedRef<number | undefined>\n resizingKey: Ref<string | null>\n onResizerPointerDown: (event: PointerEvent, key: string) => void\n onResizerKeydown: (event: KeyboardEvent, key: string) => void\n /** Сброс к авторазметке — двойной клик по ручке в шаблоне. */\n resetColumnWidth: (key: string) => void\n resizerValue: (col: GrDataColumn<TRow>) => number\n}\n\nexport function useDataTableColumnWidths<TRow extends Record<string, unknown>>(\n options: UseDataTableColumnWidthsOptions<TRow>,\n): DataTableColumnWidths<TRow> {\n const internalColumnWidths = ref<Record<string, number>>({})\n const columnWidths = computed(() => options.columnWidths() ?? internalColumnWidths.value)\n\n /** Фактические ширины шапки: заполняются замером раскладки. */\n const measuredColumnWidths = ref<Record<string, number>>({})\n\n function setMeasuredWidths(widths: Record<string, number>): void {\n measuredColumnWidths.value = widths\n }\n\n /** Ширина колонки: заданная пользователем сильнее объявленной в `columns`. */\n function widthOf(col: GrDataColumn<TRow>): string | number | undefined {\n return columnWidths.value[String(col.key)] ?? col.width\n }\n\n /**\n * Сумма заданных ширин — минимальная ширина таблицы.\n *\n * Без неё фиксированная раскладка вписывает таблицу в контейнер и делит место\n * пропорционально: колонка, которую пользователь растянул, ужимается обратно, а\n * горизонтальной прокрутки — той самой, ради которой закрепляют колонки, — не\n * возникает. Считается, только когда ширина известна у **всех** колонок: с\n * одной неизвестной сумма врала бы.\n */\n const tableMinWidth = computed<number | undefined>(() => {\n const cols = options.orderedColumns()\n if (cols.length === 0)\n return undefined\n\n let total = 0\n for (const col of cols) {\n const width = widthOf(col)\n if (typeof width !== 'number')\n return undefined\n\n total += width\n }\n\n return total\n })\n\n const resizingKey = ref<string | null>(null)\n let pendingResizeKey: string | null = null\n let resizeStartX = 0\n let resizeStartWidth = 0\n let widthBeforeResize: number | undefined\n\n function commitWidths(next: Record<string, number>): void {\n internalColumnWidths.value = next\n options.onWidthsChange(next)\n }\n\n function setColumnWidth(key: string, width: number): void {\n commitWidths({ ...columnWidths.value, [key]: Math.max(MIN_COLUMN_WIDTH, Math.round(width)) })\n }\n\n function announceWidth(key: string): void {\n const col = options.orderedColumns().find(item => String(item.key) === key)\n if (!col)\n return\n\n options.announceWidth(col.label, columnWidths.value[key] ?? 0)\n }\n\n const resizeGesture = useDragGesture({\n disabled: () => !options.resizableColumns() || options.loading(),\n onStart: (event) => {\n const key = pendingResizeKey\n const el = key === null ? null : options.headerCellEls.get(key)\n if (key === null || !el)\n return false\n\n resizeStartX = event.clientX\n // Стартовая ширина — измеренная, а не объявленная: колонка могла жить на\n // авторазметке, и тянуть её надо от того, что видно.\n resizeStartWidth = el.getBoundingClientRect().width\n widthBeforeResize = columnWidths.value[key]\n resizingKey.value = key\n },\n onMove: (event) => {\n if (resizingKey.value === null)\n return\n\n // Против выделения текста заголовка во время протяжки.\n event.preventDefault()\n setColumnWidth(resizingKey.value, resizeStartWidth + (event.clientX - resizeStartX))\n },\n onEnd: () => {\n const key = resizingKey.value\n resizingKey.value = null\n if (key === null)\n return\n\n options.onColumnResize(key, columnWidths.value[key] ?? Math.round(resizeStartWidth))\n announceWidth(key)\n },\n onCancel: () => {\n const key = resizingKey.value\n resizingKey.value = null\n if (key === null)\n return\n\n // Оборванный жест возвращает ширину, которая была до нажатия.\n const next = { ...columnWidths.value }\n if (widthBeforeResize === undefined)\n delete next[key]\n else next[key] = widthBeforeResize\n\n commitWidths(next)\n },\n })\n\n function onResizerPointerDown(event: PointerEvent, key: string): void {\n pendingResizeKey = key\n resizeGesture.start(event)\n }\n\n /** Сброс к авторазметке: колонка снова считается по содержимому. */\n function resetColumnWidth(key: string): void {\n if (columnWidths.value[key] === undefined)\n return\n\n const next = { ...columnWidths.value }\n delete next[key]\n\n commitWidths(next)\n options.onColumnResize(key, 0)\n }\n\n function resizeByKeyboard(key: string, delta: number): void {\n const measured = options.headerCellEls.get(key)?.getBoundingClientRect().width ?? MIN_COLUMN_WIDTH\n const current = columnWidths.value[key] ?? measured\n\n setColumnWidth(key, current + delta)\n options.onColumnResize(key, columnWidths.value[key] ?? current)\n announceWidth(key)\n }\n\n function onResizerKeydown(event: KeyboardEvent, key: string): void {\n if (!options.resizableColumns() || options.loading())\n return\n\n const step = event.shiftKey ? RESIZE_BIG_STEP : RESIZE_STEP\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault()\n resizeByKeyboard(key, event.key === 'ArrowLeft' ? -step : step)\n return\n }\n\n // Отдельной клавиши «авто» в паттерне нет, поэтому её роль берёт `Enter` —\n // тот же смысл, что двойной клик по ручке.\n if (event.key === 'Enter') {\n event.preventDefault()\n resetColumnWidth(key)\n }\n }\n\n /**\n * Ручка ресайза — фокусируемый `separator`, а значит обязана называть текущее\n * значение с первого рендера, до всякого перетаскивания. Заданной ширины у\n * колонки может не быть вовсе (авторазметка), поэтому за значением идём к\n * измеренной; до замера остаётся объявленная в `columns`, а её тоже может не\n * быть — тогда минимум.\n */\n function resizerValue(col: GrDataColumn<TRow>): number {\n const key = String(col.key)\n const declared = typeof col.width === 'number' ? col.width : undefined\n\n return columnWidths.value[key] ?? measuredColumnWidths.value[key] ?? declared ?? MIN_COLUMN_WIDTH\n }\n\n return {\n columnWidths,\n measuredColumnWidths,\n setMeasuredWidths,\n widthOf,\n tableMinWidth,\n resizingKey,\n onResizerPointerDown,\n onResizerKeydown,\n resetColumnWidth,\n resizerValue,\n }\n}\n","import type { ComputedRef } from 'vue'\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\n\nimport type { GrDataColumn } from '../GrDataTable.vue'\nimport {\n columnPinnedClass,\n columnPinnedLeftEdgeClass,\n columnPinnedRightEdgeClass,\n} from '../grDataTableStyles'\n\n/** Служебная колонка выбора в реестре ячеек: своего ключа у неё нет. */\nexport const SELECT_COLUMN_KEY = '__select__'\n\n/**\n * Раскладка закреплённых колонок: смещения липких ячеек и замер шапки.\n *\n * Единственный модуль таблицы, который целиком про DOM. Смещения нельзя\n * вычислить из пропов: колонка может жить на авторазметке, и её ширина\n * известна только после отрисовки — отсюда замер, а не `computed`.\n */\nexport interface UseDataTableLayoutOptions<TRow extends Record<string, unknown>> {\n orderedColumns: () => GrDataColumn<TRow>[]\n columnKeys: () => string[]\n selectable: () => boolean\n resizableColumns: () => boolean\n headerCellEls: Map<string, HTMLElement>\n /** Пересчитать раскладку заново при смене этих значений. */\n watchSources: () => unknown\n /** Измеренные ширины уезжают модулю ширин: ручка ресайза называет по ним значение. */\n onMeasuredWidths: (widths: Record<string, number>) => void\n}\n\nexport interface DataTableLayout<TRow extends Record<string, unknown>> {\n hasPinnedLeft: ComputedRef<boolean>\n pinnedStyleOf: (col: GrDataColumn<TRow>) => Record<string, string> | undefined\n pinnedCellClass: (col: GrDataColumn<TRow>, index: number) => string[]\n measureLayout: () => void\n}\n\nexport function useDataTableLayout<TRow extends Record<string, unknown>>(\n options: UseDataTableLayoutOptions<TRow>,\n): DataTableLayout<TRow> {\n const hasPinnedLeft = computed(() => options.orderedColumns().some(col => col.pinned === 'left'))\n const pinnedOffsets = ref<Record<string, number>>({})\n\n /**\n * Смещения липких колонок считаются по **измеренным** ширинам соседей: колонка\n * может жить на авторазметке, и тогда взять смещение больше неоткуда. Отсюда же\n * порядок: замер после отрисовки, а не в вычислении.\n */\n function measurePinnedOffsets(): void {\n const next: Record<string, number> = {}\n const cols = options.orderedColumns()\n\n let left = options.selectable() && hasPinnedLeft.value\n ? options.headerCellEls.get(SELECT_COLUMN_KEY)?.getBoundingClientRect().width ?? 0\n : 0\n\n for (const col of cols) {\n if (col.pinned !== 'left')\n continue\n\n next[String(col.key)] = left\n left += options.headerCellEls.get(String(col.key))?.getBoundingClientRect().width ?? 0\n }\n\n let right = 0\n for (let index = cols.length - 1; index >= 0; index -= 1) {\n const col = cols[index]\n if (col.pinned !== 'right')\n continue\n\n next[String(col.key)] = right\n right += options.headerCellEls.get(String(col.key))?.getBoundingClientRect().width ?? 0\n }\n\n pinnedOffsets.value = next\n }\n\n function measureColumnWidths(): void {\n if (!options.resizableColumns())\n return\n\n const next: Record<string, number> = {}\n\n for (const col of options.orderedColumns()) {\n const key = String(col.key)\n const width = options.headerCellEls.get(key)?.getBoundingClientRect().width\n\n if (width)\n next[key] = Math.round(width)\n }\n\n options.onMeasuredWidths(next)\n }\n\n function measureLayout(): void {\n measurePinnedOffsets()\n measureColumnWidths()\n }\n\n function pinnedStyleOf(col: GrDataColumn<TRow>): Record<string, string> | undefined {\n if (!col.pinned)\n return undefined\n\n const offset = pinnedOffsets.value[String(col.key)] ?? 0\n\n return col.pinned === 'left' ? { left: `${offset}px` } : { right: `${offset}px` }\n }\n\n /** Тень рисует только крайняя колонка группы — иначе полос было бы столько же, сколько колонок. */\n function pinnedEdgeClass(col: GrDataColumn<TRow>, index: number): string {\n const cols = options.orderedColumns()\n if (col.pinned === 'left')\n return cols[index + 1]?.pinned === 'left' ? '' : columnPinnedLeftEdgeClass\n if (col.pinned === 'right')\n return cols[index - 1]?.pinned === 'right' ? '' : columnPinnedRightEdgeClass\n\n return ''\n }\n\n function pinnedCellClass(col: GrDataColumn<TRow>, index: number): string[] {\n if (!col.pinned)\n return []\n\n return [columnPinnedClass, pinnedEdgeClass(col, index)]\n }\n\n /**\n * Ширину колонки меняет не только правка пропов: окно, шрифт и содержимое\n * ячейки двигают её сами. `ResizeObserver` — единственный способ узнать об этом;\n * в jsdom и на сервере его нет, там хватает пересчёта по изменению данных.\n */\n let layoutObserver: ResizeObserver | null = null\n\n onMounted(() => {\n measureLayout()\n\n if (typeof ResizeObserver === 'undefined')\n return\n\n layoutObserver = new ResizeObserver(() => measureLayout())\n const el = options.headerCellEls.get(SELECT_COLUMN_KEY)\n ?? options.headerCellEls.get(options.columnKeys()[0])\n if (el?.parentElement)\n layoutObserver.observe(el.parentElement)\n })\n\n onUnmounted(() => {\n layoutObserver?.disconnect()\n layoutObserver = null\n })\n\n watch(options.watchSources, () => void nextTick(measureLayout))\n\n return { hasPinnedLeft, pinnedStyleOf, pinnedCellClass, measureLayout }\n}\n","import type { ComputedRef } from 'vue'\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\n\nexport type GrDataTableDetailState = 'idle' | 'loading' | 'error' | 'ready'\n\nexport type GrDataTableRowKey = string | number\n\n/** Подгрузка подробностей строки. `signal` обязателен: строку сворачивают чаще, чем ждут. */\nexport type GrDataTableLoadDetail<TRow> = (row: TRow, signal: AbortSignal) => Promise<unknown>\n\n/**\n * Раскрытие строк `GrDataTable`: состояние второго яруса и его подгрузка.\n *\n * Всё хранится **по ключу строки**, а не по индексу: сортировка и смена\n * страницы переставляют строки, и привязка к позиции показывала бы подробности\n * соседа.\n *\n * Асинхронность здесь по образцу `GrAutocomplete/useRemoteOptions`, а не\n * `useTree`: у дерева ленивая загрузка живёт колбэком без пути ошибки — не\n * позвал потребитель `resolve`, и узел грузится вечно. Строка обязана уметь\n * показать отказ и дать повтор.\n */\nexport interface UseDataTableExpansionOptions<TRow extends Record<string, unknown>> {\n /** Контролируемый список. `undefined` — состояние помнит компонент. */\n expandedKeys: () => GrDataTableRowKey[] | undefined\n /** Идентичность набора: её смена сбрасывает кэш подробностей. */\n rows: () => TRow[]\n expandableRow: () => ((row: TRow) => boolean) | undefined\n loadDetail: () => GrDataTableLoadDetail<TRow> | undefined\n /** Раскрыта не больше одной строки. */\n accordion: () => boolean\n rowKeyValue: (row: TRow) => GrDataTableRowKey\n onExpandedChange: (keys: GrDataTableRowKey[]) => void\n onExpand: (row: TRow, key: GrDataTableRowKey) => void\n onCollapse: (row: TRow, key: GrDataTableRowKey) => void\n onDetailLoadError: (row: TRow, key: GrDataTableRowKey, error: unknown) => void\n}\n\nexport interface DataTableExpansion<TRow extends Record<string, unknown>> {\n expandedKeys: ComputedRef<Set<GrDataTableRowKey>>\n isRowExpandable: (row: TRow) => boolean\n isRowExpanded: (row: TRow) => boolean\n toggleRow: (row: TRow) => void\n collapseAll: () => void\n detailStateOf: (row: TRow) => GrDataTableDetailState\n detailDataOf: (row: TRow) => unknown\n /** Повтор после отказа — и он же ручной перезапрос. */\n retryDetail: (row: TRow) => void\n /** Сбросить загруженное: у ключа либо целиком. */\n invalidateDetail: (key?: GrDataTableRowKey) => void\n}\n\nexport function useDataTableExpansion<TRow extends Record<string, unknown>>(\n options: UseDataTableExpansionOptions<TRow>,\n): DataTableExpansion<TRow> {\n const internalExpanded = ref<GrDataTableRowKey[]>([])\n const isExpandedControlled = computed(() => options.expandedKeys() !== undefined)\n\n const expandedKeys = computed<Set<GrDataTableRowKey>>(\n () => new Set(options.expandedKeys() ?? internalExpanded.value),\n )\n\n const states = ref(new Map<GrDataTableRowKey, GrDataTableDetailState>())\n const data = ref(new Map<GrDataTableRowKey, unknown>())\n\n /**\n * Летящие запросы по ключу. Счётчик поколений отдельно от контроллера: ответ,\n * стартовавший раньше и пришедший позже, обязан проиграть последнему, а\n * `abort()` сам по себе этого не гарантирует — промис уже мог разрешиться.\n */\n const inflight = new Map<GrDataTableRowKey, AbortController>()\n const generation = new Map<GrDataTableRowKey, number>()\n\n function setState(key: GrDataTableRowKey, state: GrDataTableDetailState): void {\n const next = new Map(states.value)\n next.set(key, state)\n states.value = next\n }\n\n function cancel(key: GrDataTableRowKey): void {\n inflight.get(key)?.abort()\n inflight.delete(key)\n // Поколение сдвигается вместе с отменой: иначе `finally` уже летящего\n // запроса вернул бы строку из `idle` обратно в `ready`.\n generation.set(key, (generation.get(key) ?? 0) + 1)\n }\n\n function isRowExpandable(row: TRow): boolean {\n const predicate = options.expandableRow()\n return predicate ? predicate(row) : true\n }\n\n function isRowExpanded(row: TRow): boolean {\n return expandedKeys.value.has(options.rowKeyValue(row))\n }\n\n function detailStateOf(row: TRow): GrDataTableDetailState {\n return states.value.get(options.rowKeyValue(row)) ?? 'idle'\n }\n\n function detailDataOf(row: TRow): unknown {\n return data.value.get(options.rowKeyValue(row))\n }\n\n async function load(row: TRow, key: GrDataTableRowKey): Promise<void> {\n const loadDetail = options.loadDetail()\n if (!loadDetail)\n return\n\n cancel(key)\n const controller = new AbortController()\n inflight.set(key, controller)\n const seq = generation.get(key) ?? 0\n setState(key, 'loading')\n\n try {\n const result = await loadDetail(row, controller.signal)\n if (seq !== generation.get(key))\n return\n\n const next = new Map(data.value)\n next.set(key, result)\n data.value = next\n setState(key, 'ready')\n }\n catch (error) {\n if (seq !== generation.get(key) || controller.signal.aborted)\n return\n\n setState(key, 'error')\n options.onDetailLoadError(row, key, error)\n }\n finally {\n if (inflight.get(key) === controller)\n inflight.delete(key)\n }\n }\n\n function commit(keys: GrDataTableRowKey[]): void {\n if (!isExpandedControlled.value)\n internalExpanded.value = keys\n\n options.onExpandedChange(keys)\n }\n\n function toggleRow(row: TRow): void {\n if (!isRowExpandable(row))\n return\n\n const key = options.rowKeyValue(row)\n\n if (expandedKeys.value.has(key)) {\n // Свернули до ответа — запрос больше не нужен: строки, которой он\n // предназначался, на экране нет.\n cancel(key)\n if (states.value.get(key) === 'loading')\n setState(key, 'idle')\n\n commit([...expandedKeys.value].filter(item => item !== key))\n options.onCollapse(row, key)\n return\n }\n\n const next = options.accordion() ? [key] : [...expandedKeys.value, key]\n commit(next)\n options.onExpand(row, key)\n\n // Загруженное держится, пока строка жива: повторное раскрытие запроса не шлёт.\n if (options.loadDetail() && states.value.get(key) !== 'ready')\n void load(row, key)\n }\n\n function collapseAll(): void {\n for (const key of expandedKeys.value) cancel(key)\n commit([])\n }\n\n function retryDetail(row: TRow): void {\n void load(row, options.rowKeyValue(row))\n }\n\n function invalidateDetail(key?: GrDataTableRowKey): void {\n if (key === undefined) {\n for (const item of inflight.keys()) cancel(item)\n states.value = new Map()\n data.value = new Map()\n return\n }\n\n cancel(key)\n const nextStates = new Map(states.value)\n nextStates.delete(key)\n states.value = nextStates\n\n const nextData = new Map(data.value)\n nextData.delete(key)\n data.value = nextData\n }\n\n /**\n * Смена идентичности набора сбрасывает загруженное — то же правило, что у\n * виртуализатора: мутация массива на месте сохраняет, замена сбрасывает.\n * Иначе строка показывала бы подробности прошлого набора данных.\n */\n watch(() => options.rows(), () => invalidateDetail())\n\n onBeforeUnmount(() => {\n for (const key of inflight.keys()) cancel(key)\n })\n\n return {\n expandedKeys,\n isRowExpandable,\n isRowExpanded,\n toggleRow,\n collapseAll,\n detailStateOf,\n detailDataOf,\n retryDetail,\n invalidateDetail,\n }\n}\n","import type { ComputedRef } from 'vue'\nimport { computed, nextTick } from 'vue'\n\nimport { useRovingFocus } from '../../../composables/useRovingFocus'\n\n/**\n * Клавиатура по ячейкам: паттерн `grid` из WAI-ARIA APG.\n *\n * Своей арифметики здесь нет — её ведёт `useRovingFocus` в режиме `grid`. Этот\n * модуль отвечает за то, чего примитив знать не может: как адресуется ячейка\n * таблицы, что делать на краю окна виртуализации и куда прокрутить, прежде чем\n * фокусировать.\n *\n * **Кольцо не замкнуто.** У списка зацикливание уместно, у сетки нет: строка\n * ниже последней — это не первая, а «дальше некуда», и в виртуальном списке\n * именно на этом краю начинается подгрузка.\n *\n * **Набор — отрисованное окно, а не вся таблица.** У десяти тысяч строк на шесть\n * колонок ключей было бы шестьдесят тысяч, и пересобирались бы они при каждом\n * чтении. Шаг за край окна разбирается до примитива (`windowStep`): список\n * прокручивается, и фокус уходит в строку, появившуюся следующим кадром.\n */\n\n/** Строка шапки адресуется как `-1`: в наборе она первая, но строкой данных не является. */\nexport const HEADER_ROW_INDEX = -1\n\n/** Ключ ячейки. Строка вместо пары чисел — примитив сравнивает ключи по `===`. */\nexport type GrGridCellKey = string\n\nexport function gridCellKey(row: number, column: number): GrGridCellKey {\n return `${row}:${column}`\n}\n\nexport function parseGridCellKey(key: GrGridCellKey): { row: number, column: number } {\n const [row, column] = key.split(':')\n return { row: Number(row), column: Number(column) }\n}\n\nexport interface UseDataTableGridNavigationOptions {\n /** Включена ли навигация по ячейкам. Выключенная не занимает ни одной клавиши. */\n enabled: () => boolean\n /** Ширина сетки со служебными колонками. */\n columns: () => number\n /** Индексы отрисованных строк в порядке показа. При виртуализации — только окно. */\n renderedRows: () => number[]\n /** Сколько всего строк: по нему считается край при виртуализации. */\n totalRows: () => number\n /** Узлы ячеек по ключу. Заполняется `:ref` самой таблицы. */\n cellEls: Map<GrGridCellKey, HTMLElement>\n /**\n * Прокрутить список к строке. Есть только при виртуализации: без неё строка\n * уже в разметке, и доводить до экрана её незачем.\n */\n scrollToRow?: (index: number) => void\n}\n\n/** Что внутри ячейки может принять фокус. Порядок обхода — документный. */\nconst FOCUSABLE = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(',')\n\nexport interface DataTableGridNavigation {\n /** Ключ ячейки, держащей остановку `Tab`. */\n rovingKey: ComputedRef<GrGridCellKey | undefined>\n tabindexFor: (row: number, column: number) => 0 | -1\n setActive: (row: number, column: number) => void\n /** Обработчик `keydown` на таблице. Возвращает `true`, если клавиша разобрана. */\n onKeydown: (event: KeyboardEvent) => boolean\n}\n\nexport function useDataTableGridNavigation(\n options: UseDataTableGridNavigationOptions,\n): DataTableGridNavigation {\n /**\n * Ячейки окна плюс шапка, по строкам. Порядок обязан совпадать с показом:\n * примитив считает соседа сдвигом по этому массиву.\n */\n const cellKeys = computed<GrGridCellKey[]>(() => {\n if (!options.enabled())\n return []\n\n const width = options.columns()\n const rows = [HEADER_ROW_INDEX, ...options.renderedRows()]\n\n return rows.flatMap(row => Array.from({ length: width }, (_, column) => gridCellKey(row, column)))\n })\n\n const roving = useRovingFocus<GrGridCellKey>({\n items: () => cellKeys.value,\n elementFor: key => options.cellEls.get(key),\n orientation: () => 'grid',\n columns: () => options.columns(),\n // Сетка по краям не зацикливается: строка ниже последней — не первая.\n wrap: () => false,\n // Строка могла появиться в разметке только что — ждём кадр, иначе фокус\n // уйдёт в узел, которого ещё нет.\n beforeFocus: key => (options.cellEls.has(key) ? undefined : nextTick()),\n })\n\n /**\n * Шаг за край **окна** при виртуализации.\n *\n * Примитиву это доверить нельзя, и не из-за его устройства: шапка всегда\n * стоит в наборе первой, поэтому стрелка вверх из первой отрисованной строки\n * уходит в шапку — а должна уводить к строке выше окна. Край набора и край\n * таблицы здесь разные вещи, и различить их может только тот, кто знает\n * общее число строк.\n *\n * Возвращает строку, к которой надо прокрутить, или `null` — тогда клавишу\n * разбирает примитив.\n */\n function windowStep(event: KeyboardEvent): number | null {\n if (!options.scrollToRow || (event.key !== 'ArrowDown' && event.key !== 'ArrowUp'))\n return null\n\n const active = roving.rovingKey.value\n if (!active)\n return null\n\n const { row } = parseGridCellKey(active)\n const rendered = options.renderedRows()\n if (rendered.length === 0)\n return null\n\n if (event.key === 'ArrowDown') {\n const last = rendered.at(-1)!\n // Не на нижнем крае окна — шаг обычный.\n if (row !== last)\n return null\n\n return last + 1 < options.totalRows() ? last + 1 : null\n }\n\n const first = rendered[0]\n // Из шапки вверх идти некуда, и прокручивать список тем более незачем.\n if (row !== first)\n return null\n\n return first > 0 ? first - 1 : null\n }\n\n /** Ячейка, в которой сейчас фокус (или которая его держит). */\n function activeCell(): HTMLElement | undefined {\n const key = roving.rovingKey.value\n return key ? options.cellEls.get(key) : undefined\n }\n\n /**\n * Вход в ячейку: `Enter` или `F2` отдают фокус тому, что внутри.\n *\n * Без этого шага паттерн неполон, а не «упрощён»: сетка забирает `Tab` себе,\n * и кнопка сортировки, чекбокс или ссылка в ячейке иначе становятся\n * недостижимы с клавиатуры вовсе.\n */\n function enterCell(event: KeyboardEvent): boolean {\n if (event.key !== 'Enter' && event.key !== 'F2')\n return false\n\n const cell = activeCell()\n // Фокус уже внутри — клавиша принадлежит содержимому, а не сетке.\n if (!cell || (document.activeElement && document.activeElement !== cell && cell.contains(document.activeElement)))\n return false\n\n const target = cell.querySelector<HTMLElement>(FOCUSABLE)\n if (!target)\n return false\n\n event.preventDefault()\n target.focus()\n return true\n }\n\n /** Выход из ячейки: `Escape` возвращает фокус самой ячейке. */\n function leaveCell(event: KeyboardEvent): boolean {\n if (event.key !== 'Escape')\n return false\n\n const cell = activeCell()\n if (!cell || !document.activeElement || document.activeElement === cell || !cell.contains(document.activeElement))\n return false\n\n event.preventDefault()\n cell.focus()\n return true\n }\n\n return {\n rovingKey: roving.rovingKey,\n tabindexFor: (row, column) => (options.enabled() ? roving.tabindexFor(gridCellKey(row, column)) : -1),\n setActive: (row, column) => roving.setActive(gridCellKey(row, column)),\n onKeydown: (event) => {\n if (!options.enabled())\n return false\n\n if (enterCell(event) || leaveCell(event))\n return true\n\n const row = windowStep(event)\n if (row !== null) {\n event.preventDefault()\n options.scrollToRow?.(row)\n // Строка появится в разметке следующим кадром — тогда и фокусируем.\n const { column } = parseGridCellKey(roving.rovingKey.value!)\n void nextTick(() => roving.focusKey(gridCellKey(row, column)))\n return true\n }\n\n return roving.handleNavigationKeys(event)\n },\n }\n}\n","<script setup lang=\"ts\" generic=\"TRow extends Record<string, unknown> = Record<string, unknown>\">\nimport type { Component } from 'vue'\nimport { computed, nextTick, onMounted, ref, useId, watch, watchEffect } from 'vue'\n\nimport GrTable from '../GrTable/GrTable.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport GrCheckbox from '../GrCheckbox/GrCheckbox.vue'\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport GrDropdownMenu from '../GrDropdownMenu/GrDropdownMenu.vue'\nimport type { GrDropdownMenuAction, GrDropdownMenuEntry } from '../GrDropdownMenu/menuModel'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useVirtualList } from '../../composables/useVirtualList'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrDataTableSortDir } from './grDataTableSort'\nimport { useDataTableRowKeys } from './composables/useDataTableRowKeys'\nimport { useDataTableSort } from './composables/useDataTableSort'\nimport { useDataTableSelection } from './composables/useDataTableSelection'\nimport { useDataTableColumnOrder } from './composables/useDataTableColumnOrder'\nimport { MIN_COLUMN_WIDTH, useDataTableColumnWidths } from './composables/useDataTableColumnWidths'\nimport { SELECT_COLUMN_KEY, useDataTableLayout } from './composables/useDataTableLayout'\nimport { useDataTableExpansion } from './composables/useDataTableExpansion'\nimport {\n gridCellKey,\n HEADER_ROW_INDEX,\n useDataTableGridNavigation,\n} from './composables/useDataTableGridNavigation'\nimport {\n type GrDataTableSize,\n cellPaddings,\n columnDraggingClass,\n detailCellClass,\n detailContentClass,\n detailErrorClass,\n detailPaddings,\n detailRowClass,\n expandButtonClass,\n expandColumnWidths,\n expandIconClass,\n expandIconOpenClass,\n columnHandleActiveClass,\n columnHandleClass,\n columnMenuTriggerClass,\n columnPinnedClass,\n columnResizerClass,\n columnResizerHoverClass,\n columnResizerLineActiveClass,\n columnResizerLineClass,\n headerGaps,\n headerTextSizes,\n placeholderPaddings,\n rowHeightEstimates,\n rowSelectedClass,\n selectCheckboxSizes,\n selectColumnWidths,\n sortIconSizes,\n spinnerSizes,\n summaryRowClass,\n} from './grDataTableStyles'\n\nimport IconArrowUp from '~icons/lucide/arrow-up'\nimport IconGripVertical from '~icons/lucide/grip-vertical'\nimport IconLoaderCircle from '~icons/lucide/loader-circle'\nimport IconArrowDown from '~icons/lucide/arrow-down'\nimport IconChevronRight from '~icons/lucide/chevron-right'\nimport IconEllipsisVertical from '~icons/lucide/ellipsis-vertical'\nimport IconArrowLeftToLine from '~icons/lucide/arrow-left-to-line'\nimport IconArrowRightToLine from '~icons/lucide/arrow-right-to-line'\nimport IconPinOff from '~icons/lucide/pin-off'\n\n/**\n * Ключ колонки. Собственные поля строки подсказываются автодополнением, но\n * произвольная строка тоже допустима: колонка может быть вычисляемой и жить\n * только в слоте `#cell-<key>`.\n */\nexport type GrDataColumnKey<TRow extends Record<string, unknown> = Record<string, unknown>>\n = | Extract<keyof TRow, string>\n | (string & {})\n\nexport type GrDataColumn<TRow extends Record<string, unknown> = Record<string, unknown>> = {\n key: GrDataColumnKey<TRow>\n label: string\n /**\n * Заголовок колонки сортирует.\n *\n * Сортируется **переданный массив `rows`**, и только он. Над серверной\n * пагинацией это врёт: «максимальное списание» покажет максимум по текущей\n * странице, а прочитается как максимум по журналу. Данные приходят\n * постранично — включайте `externalSort` и сортируйте запросом.\n */\n sortable?: boolean\n align?: 'left' | 'center' | 'right'\n /**\n * Ширина колонки: число — пиксели, строка — как есть (`'40%'`, `'12rem'`).\n *\n * Уезжает в заголовочную ячейку: при фиксированной раскладке ширины колонок\n * задаёт первая строка таблицы, а это и есть `<thead>`.\n */\n width?: string | number\n /**\n * Колонка липнет к краю при горизонтальной прокрутке.\n *\n * Закреплённые колонки всегда стоят своей группой у своего края — перенос\n * колонки из группы в группу запрещён, иначе «закреплена слева» перестало бы\n * означать «слева».\n */\n pinned?: GrColumnPinSide\n}\n\n/** Край, к которому липнет колонка. */\nexport type GrColumnPinSide = 'left' | 'right'\n\n/**\n * Закрепление, выбранное пользователем. `null` — не «как в конфиге», а\n * «откреплена»: без него снять закрепление, объявленное у колонки, было бы\n * нечем — отсутствие ключа означает «решает конфиг».\n */\nexport type GrColumnPin = GrColumnPinSide | null\n\n/**\n * Значения итоговой строки по ключам колонок.\n *\n * Не строка набора: у итога нет ключа, он не сортируется и не выбирается.\n * Колонка, для которой значения нет, остаётся пустой ячейкой — заполнять все\n * колонки итог не обязан.\n */\nexport type GrDataTableSummary<TRow extends Record<string, unknown> = Record<string, unknown>>\n = Partial<Record<GrDataColumnKey<TRow>, unknown>>\n\nexport type GrDataTableRowKey<TRow extends Record<string, unknown> = Record<string, unknown>>\n = | string\n | ((row: TRow) => string | number)\n\n/** Порядок обхода состояний сортировки по клику на заголовок. */\nexport type GrDataTableSortCycle = 'asc-desc' | 'asc-desc-none'\n\nexport interface GrDataTableProps<TRow extends Record<string, unknown> = Record<string, unknown>> {\n rows: TRow[]\n columns: GrDataColumn<TRow>[]\n /** Ключ строки или функция-резолвер. По умолчанию — поле `'id'`. */\n rowKey?: GrDataTableRowKey<TRow>\n /** Ключ колонки для начальной сортировки (uncontrolled-режим). */\n initialSortKey?: string\n /** Направление начальной сортировки (uncontrolled-режим). */\n initialSortDir?: GrDataTableSortDir\n /** Контролируемый ключ сортировки: `v-model:sortKey`. Задаёт controlled-режим. */\n sortKey?: string\n /** Контролируемое направление сортировки: `v-model:sortDir`. */\n sortDir?: GrDataTableSortDir\n /** Клик по заголовку: `asc → desc` или `asc → desc → без сортировки`. */\n sortCycle?: GrDataTableSortCycle\n /**\n * Внешняя сортировка (например серверная): компонент НЕ сортирует `rows`\n * сам, а только сообщает о смене через `update:sortKey`/`update:sortDir`/\n * `sortChange`. `rows` при этом должны приходить уже отсортированными.\n */\n externalSort?: boolean\n /**\n * Выбор строк: добавляет ведущую колонку с чекбоксами (+ «выбрать все» в шапке).\n * Выбранные ключи строк — через `v-model:selected`.\n */\n selectable?: boolean\n /** Контролируемый список выбранных ключей строк: `v-model:selected`. */\n selected?: Array<string | number>\n /** Предикат «строку можно выбрать». Невыбираемые строки не попадают и в «выбрать все». */\n selectableRow?: (row: TRow) => boolean\n /**\n * Состояние загрузки: тело таблицы заменяется строкой-индикатором.\n * `empty`-состояние при этом не показывается.\n */\n loading?: boolean\n /** Текст индикатора загрузки. i18n: fallback `gr.dataTable.loading`. */\n loadingText?: string\n /** Текст пустого состояния. i18n: fallback `gr.dataTable.empty`; слот `#empty` сильнее. */\n emptyText?: string\n /** Класс строки: общий для всех либо вычисляемый по строке. */\n rowClass?: string | ((row: TRow, index: number) => string | undefined)\n /** Произвольные атрибуты строки (`data-*`, `title`, …). */\n rowProps?: (row: TRow, index: number) => Record<string, unknown> | undefined\n /**\n * Итоговая строка в `<tfoot>`: значения по ключам колонок.\n *\n * Встаёт по той же колоночной сетке, что и тело, — с теми же паддингами,\n * выравниванием, ширинами и закреплением. Собранная руками в `#footer`, она\n * этих классов не получает (`GrTable` их принципиально не даёт) и разъезжается\n * с телом на первой же смене `size`.\n *\n * Итог не суммируется компонентом: что считать итогом — знает приложение.\n * Оформление ячейки — слот `#summary-<key>`.\n *\n * `null` равнозначен отсутствию: `totals ?? null` — обычная запись там, где\n * итог считается не всегда.\n */\n summaryRow?: GrDataTableSummary<TRow> | null\n /**\n * Размер таблицы: кегль, паддинги ячеек, стрелки сортировки и чекбоксы.\n * Прокидывается в `GrTable`.\n */\n size?: GrDataTableSize\n // Прокси к GrTable:\n caption?: string\n ariaLabel?: string\n ariaLabelledby?: string\n regionLabel?: string\n /** Прилипающий заголовок при вертикальном скролле (нужен `maxHeight`). */\n stickyHeader?: boolean\n /**\n * Виртуализация строк: в DOM живёт только окно вокруг вьюпорта. Высоту окна\n * задаёт `maxHeight`, без него окна прокрутки не существует.\n *\n * Включает фиксированную раскладку таблицы: ширина колонки считается по\n * содержимому всех строк, а в DOM их только окно — без фиксации колонки\n * прыгали бы на каждой прокрутке. Ширины стоит задать через `width` у\n * колонок, иначе фиксированная раскладка делит место поровну.\n */\n virtual?: boolean\n /** Максимальная высота таблицы (вертикальный скролл). Число — в пикселях. */\n maxHeight?: string | number\n /**\n * Пользовательский порядок колонок: в шапке появляется ручка переноса.\n * Колонка тянется указателем и двигается `Shift`+`←`/`→` с клавиатуры.\n */\n reorderableColumns?: boolean\n /**\n * Контролируемый порядок колонок — ключи в нужном порядке (`v-model:columnOrder`).\n * Не задан — порядок компонент помнит сам, начиная с порядка `columns`.\n */\n columnOrder?: string[]\n /**\n * Пользовательская ширина колонок: у правого края заголовка появляется ручка.\n * Тянется указателем, с клавиатуры — стрелками (паттерн window splitter).\n *\n * Включает фиксированную раскладку таблицы: без неё браузер пересчитывает\n * ширины по содержимому и заданная пользователем пропадает.\n */\n resizableColumns?: boolean\n /**\n * Контролируемые ширины в пикселях по ключу колонки (`v-model:columnWidths`).\n * Не заданы — ширины компонент помнит сам.\n */\n columnWidths?: Record<string, number>\n /**\n * Закрепление колонок задаёт пользователь: в шапке появляется меню с\n * «закрепить слева / справа / открепить».\n *\n * Без пропа `pinned` у колонки остаётся тем, чем был, — объявлением в\n * конфиге, которое меняется только кодом.\n */\n pinnableColumns?: boolean\n /**\n * Контролируемое закрепление по ключу колонки (`v-model:pinnedColumns`).\n * Не задано — компонент помнит его сам, начиная с `pinned` у колонок.\n */\n pinnedColumns?: Record<string, GrColumnPin>\n /**\n * Клавиатура по ячейкам: паттерн `grid` из WAI-ARIA APG.\n *\n * Вся таблица становится **одной** остановкой `Tab`, внутрь ведут стрелки, а\n * в содержимое ячейки — `Enter` или `F2`. Поэтому проп отдельный, а не\n * поведение по умолчанию: он переставляет таб-порядок у всех, кто таблицу\n * уже поставил.\n */\n cellNavigation?: boolean\n /**\n * Второй ярус строки: колонка с кнопкой раскрытия и блок подробностей под\n * строкой. Содержимое рисует слот `#detail`.\n */\n expandable?: boolean\n /** Контролируемый список раскрытых ключей (`v-model:expandedKeys`). */\n expandedKeys?: Array<string | number>\n /** У какой строки есть второй ярус. Остальные кнопки не получают. */\n expandableRow?: (row: TRow) => boolean\n /**\n * Подгрузка подробностей в момент раскрытия. Без неё содержимое берётся из\n * самой строки. `signal` обязателен: строку сворачивают чаще, чем ждут.\n */\n loadDetail?: (row: TRow, signal: AbortSignal) => Promise<unknown>\n /** Раскрыта не больше одной строки. */\n accordion?: boolean\n /**\n * Рисовать ли служебную колонку с собственной кнопкой раскрытия.\n *\n * `false` — колонки нет, и раскрытием управляет разметка потребителя: слоты\n * ячеек получают `expanded` и `toggleExpand`, чтобы кнопку можно было\n * поставить в свой столбец действий рядом с остальными. Тогда `aria-expanded`\n * и доступное имя ложатся на неё же — компоненту их вешать не на что.\n */\n expandColumn?: boolean\n}\n\nexport interface GrDataTableEmits<TRow extends Record<string, unknown> = Record<string, unknown>> {\n (e: 'update:sortKey', value: string): void\n (e: 'update:sortDir', value: GrDataTableSortDir): void\n (e: 'sortChange', value: { key: string, dir: GrDataTableSortDir }): void\n (e: 'update:selected', value: Array<string | number>): void\n (e: 'rowClick', payload: { row: TRow, index: number, event: MouseEvent }): void\n (e: 'update:columnOrder', value: string[]): void\n (e: 'columnReorder', payload: { key: string, from: number, to: number }): void\n (e: 'update:columnWidths', value: Record<string, number>): void\n (e: 'columnResize', payload: { key: string, width: number }): void\n (e: 'update:pinnedColumns', value: Record<string, GrColumnPin>): void\n (e: 'columnPin', payload: { key: string, pinned: GrColumnPin }): void\n (e: 'update:expandedKeys', value: Array<string | number>): void\n (e: 'expand', payload: { row: TRow, key: string | number }): void\n (e: 'collapse', payload: { row: TRow, key: string | number }): void\n (e: 'detailLoadError', payload: { row: TRow, key: string | number, error: unknown }): void\n}\n\n/**\n * `GrDataTable` — data-таблица поверх `GrTable` с сортировкой по клику\n * на заголовок и scoped-слотами ячеек (`#cell-<key>`), `#header-<key>`,\n * `#caption`, `#footer`, `#empty`, `#loading`.\n *\n * Итоговая строка объявляется пропом `summaryRow` и оформляется слотами\n * `#summary-<key>`: она встаёт по той же колоночной сетке, что и тело.\n *\n * `#footer` — для свободной разметки под итогом: несколько строк, примечание,\n * `colspan`. Рендерится внутрь того же `<tfoot>`, то есть его содержимое тоже\n * строки таблицы (`<tr><td>`), а скоуп отдаёт `columns` (в текущем порядке) и\n * `totalColumns` (со служебными колонками выбора и раскрытия).\n *\n * Сортировка, включая крайние случаи с пустыми и смешанными значениями, живёт\n * в `grDataTableSort.ts` — см. `docs/components/GrDataTable.md`.\n */\nconst props = withDefaults(defineProps<GrDataTableProps<TRow>>(), {\n rowKey: 'id' as GrDataTableRowKey<TRow>,\n initialSortKey: undefined,\n initialSortDir: 'asc',\n sortKey: undefined,\n sortDir: undefined,\n sortCycle: 'asc-desc',\n externalSort: false,\n selectable: false,\n selected: undefined,\n selectableRow: undefined,\n loading: false,\n loadingText: undefined,\n emptyText: undefined,\n rowClass: undefined,\n rowProps: undefined,\n summaryRow: undefined,\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n stickyHeader: false,\n maxHeight: undefined,\n virtual: false,\n reorderableColumns: false,\n columnOrder: undefined,\n resizableColumns: false,\n columnWidths: undefined,\n pinnableColumns: false,\n pinnedColumns: undefined,\n cellNavigation: false,\n expandable: false,\n expandedKeys: undefined,\n expandableRow: undefined,\n loadDetail: undefined,\n accordion: false,\n expandColumn: true,\n})\n\n// Раньше остальных проверок: таблица читает `rows` уже в setup, и гард,\n// стоящий в хвосте, до предупреждения бы не дожил.\nif (__GR_DEV__) {\n watchEffect(() => {\n if (!Array.isArray(props.rows)) {\n console.warn(\n `[granularity] GrDataTable: обязательный проп \\`rows\\` должен быть массивом — получено ${String(props.rows)}.`,\n )\n }\n\n if (!Array.isArray(props.columns)) {\n console.warn(\n `[granularity] GrDataTable: обязательный проп \\`columns\\` должен быть массивом — получено ${String(props.columns)}.`,\n )\n }\n })\n}\n\nconst emit = defineEmits<GrDataTableEmits<TRow>>()\n\nconst { t, locale } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.dataTable.loading', 'Loading…'))\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.dataTable.empty', 'No data'))\n\nconst {\n currentSortKey,\n currentSortDir,\n sortedRows,\n toggleSort,\n clearSort,\n ariaSortFor,\n} = useDataTableSort<TRow>({\n rows: () => props.rows,\n sortKey: () => props.sortKey,\n sortDir: () => props.sortDir,\n initialSortKey: () => props.initialSortKey,\n initialSortDir: () => props.initialSortDir,\n externalSort: () => props.externalSort,\n sortCycle: () => props.sortCycle,\n locale: () => locale.value,\n onSortChange: (key, dir) => {\n emit('update:sortKey', key)\n emit('update:sortDir', dir)\n emit('sortChange', { key, dir })\n },\n})\n\nfunction cellAlign(col: GrDataColumn<TRow>): string {\n if (col.align === 'right')\n return 'text-right'\n if (col.align === 'center')\n return 'text-center'\n return 'text-left'\n}\n\nconst { rowKeyValue } = useDataTableRowKeys<TRow>({ rowKey: () => props.rowKey })\n\n/**\n * Подсказка «что сделает нажатие» — visually hidden текстом **после** подписи\n * колонки, а не `aria-label`'ом на кнопке. `aria-label` подменял бы собой имя\n * `<th>`, и AT при переходе по ячейкам вместо «Название» читала бы\n * «Отсортировано по Название по возрастанию, нажмите…». Текущее состояние\n * сортировки при этом объявляет `aria-sort` на самом `<th>`.\n */\nfunction sortHint(col: GrDataColumn<TRow>): string {\n if (currentSortKey.value !== col.key)\n return t('gr.dataTable.sortAsc', 'Activate to sort ascending')\n\n if (currentSortDir.value === 'asc')\n return t('gr.dataTable.sortDesc', 'Activate to sort descending')\n\n return props.sortCycle === 'asc-desc-none'\n ? t('gr.dataTable.sortNone', 'Activate to remove sorting')\n : t('gr.dataTable.sortAsc', 'Activate to sort ascending')\n}\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrDataTable' })\n\nconst cellClass = computed(() => cellPaddings[resolvedSize.value])\nconst placeholderClass = computed(() => placeholderPaddings[resolvedSize.value])\nconst headerTextClass = computed(() => headerTextSizes[resolvedSize.value])\nconst headerGapClass = computed(() => headerGaps[resolvedSize.value])\nconst selectColumnClass = computed(() => selectColumnWidths[resolvedSize.value])\nconst spinnerClass = computed(() => spinnerSizes[resolvedSize.value])\nconst sortIconSize = computed(() => sortIconSizes[resolvedSize.value])\nconst checkboxSize = computed(() => selectCheckboxSizes[resolvedSize.value])\n\n/**\n * Номер строки и полное их число объявляем только при виртуализации: иначе\n * диктор считает строки по разметке, а там всего окно. Заголовок — строка\n * первая, поэтому строки набора начинаются со второй.\n */\n/**\n * Итог показывается, только когда набор на экране: «Итого 1 234» над спиннером —\n * утверждение о том, чего ещё не показали. Пустой набор при этом итог не гасит:\n * «Итого 0» под «нет данных» осмысленно, и считает его потребитель.\n *\n * Предикат один на всех: шаблон, `aria-rowcount` и номер строки обязаны сходиться,\n * иначе диктор объявит строку, которой в разметке нет.\n */\nconst hasSummary = computed(() => props.summaryRow != null && !props.loading)\n\nconst ariaRowCount = computed(() => (\n props.virtual ? sortedRows.value.length + 1 + (hasSummary.value ? 1 : 0) : undefined\n))\n\nfunction ariaRowIndex(index: number): number | undefined {\n return props.virtual ? index + 2 : undefined\n}\n\n/** Итог идёт следующим номером за последней строкой набора. */\nconst summaryAriaRowIndex = computed(() => (\n props.virtual ? sortedRows.value.length + 2 : undefined\n))\n\nconst isEmpty = computed(() => sortedRows.value.length === 0)\n\n/**\n * Значение итога по ключу колонки. Как и `cellValue`, отдаёт сырое: отсутствие\n * ключа даёт пустую ячейку, а ноль — это значение, а не пустота.\n */\nfunction summaryValue(key: string): unknown {\n return (props.summaryRow as Record<string, unknown> | undefined)?.[key]\n}\n\n// Общее число колонок с учётом ведущей чекбокс-колонки — для `colspan`\n// строк loading/empty.\n/**\n * Раскрытие выключено при виртуализации целиком — см. предупреждение ниже.\n * Объявлено здесь, а не рядом с ним: от него зависит `colspan` служебных строк.\n */\nconst expandEnabled = computed(() => props.expandable)\n\n/** Своя колонка с кнопкой: её может не быть, если кнопку ставит потребитель. */\nconst expandColumnVisible = computed(() => expandEnabled.value && props.expandColumn)\n\nconst totalColumns = computed(() => (\n props.columns.length + (props.selectable ? 1 : 0) + (expandColumnVisible.value ? 1 : 0)\n))\n\n// ————— Порядок колонок.\n\n/**\n * Карты живут в компоненте, а не в модуле: наполняет их шаблон, а читают все\n * три колоночных модуля — порядок тянет за ячейку, ширина её замеряет,\n * раскладка считает по ней смещения закрепления.\n */\nconst headerCellEls = new Map<string, HTMLElement>()\nconst columnHandleEls = new Map<string, HTMLElement>()\n\nfunction registerEl(store: Map<string, HTMLElement>, key: string, el: unknown): void {\n if (el instanceof HTMLElement) {\n store.set(key, el)\n return\n }\n\n // Перестановка размонтирует старую ячейку уже после того, как встала новая:\n // снимаем запись, только если она протухла.\n const previous = store.get(key)\n if (previous && !previous.isConnected)\n store.delete(key)\n}\n\n/**\n * Закрепление, выбранное пользователем, поверх объявленного в конфиге колонки.\n *\n * Отсутствие ключа означает «решает конфиг», а `null` — «откреплена»: без\n * различия снять закрепление, объявленное у колонки, было бы нечем.\n */\nconst pinnedState = ref<Record<string, GrColumnPin>>({})\nconst pinnedOverrides = computed(() => props.pinnedColumns ?? pinnedState.value)\n\n/**\n * Колонки с уже разрешённым закреплением.\n *\n * Дальше по компоненту `col.pinned` читают порядок, раскладка и все три яруса\n * ячеек. Разрешать выбор пользователя в каждом из этих мест значило бы завести\n * четыре места, где он может разойтись, — поэтому он разрешается один раз\n * здесь, а ниже по течению ничего не знает о том, откуда взялось значение.\n */\nconst resolvedColumns = computed<GrDataColumn<TRow>[]>(() => props.columns.map((col) => {\n const key = String(col.key)\n if (!(key in pinnedOverrides.value))\n return col\n\n return { ...col, pinned: pinnedOverrides.value[key] ?? undefined }\n}))\n\nconst {\n orderedColumns,\n columnKeys,\n draggingColumnKey,\n columnDropClass,\n onColumnHandleKeydown,\n columnSort,\n columnRoving,\n} = useDataTableColumnOrder<TRow>({\n columns: () => resolvedColumns.value,\n columnOrder: () => props.columnOrder,\n reorderableColumns: () => props.reorderableColumns,\n loading: () => props.loading,\n headerCellEls,\n columnHandleEls,\n onOrderChange: (order, moved) => {\n emit('update:columnOrder', order)\n emit('columnReorder', moved)\n },\n announceMove: (label, position, count) => {\n announce(t('gr.dataTable.columnMoved', 'Column {label} moved to position {position} of {count}', {\n label,\n position,\n count,\n }))\n },\n})\n\n/**\n * Ширина меню колонки.\n *\n * Панель ужимается по содержимому, и самой длинной подписи не хватало пяти\n * пикселей: «Закрепить справа» переносилось на вторую строку. Ширина задана\n * явно и с запасом — она обязана держать все три локали, а не ту, на которой\n * её замерили.\n */\nconst COLUMN_MENU_WIDTH = 240\n\n/**\n * Пункты меню колонки.\n *\n * Три состояния закрепления — это выбор одного из трёх, поэтому пункты\n * `menuitemradio` с `checked`, а не три команды: так диктор называет текущее\n * положение сам, и «открепить» у незакреплённой колонки видно выключенным, а\n * не пропадает.\n */\nfunction columnMenuItems(col: GrDataColumn<TRow>): GrDropdownMenuEntry[] {\n const current = col.pinned ?? null\n\n const item = (pinned: GrColumnPin, label: string, icon: Component): GrDropdownMenuAction => ({\n key: pinned ?? 'none',\n label,\n icon,\n role: 'menuitemradio',\n checked: current === pinned,\n })\n\n return [\n item('left', t('gr.dataTable.pinLeft', 'Pin to the left'), IconArrowLeftToLine),\n item('right', t('gr.dataTable.pinRight', 'Pin to the right'), IconArrowRightToLine),\n item(null, t('gr.dataTable.unpin', 'Unpin'), IconPinOff),\n ]\n}\n\nfunction columnMenuLabel(col: GrDataColumn<TRow>): string {\n return t('gr.dataTable.columnMenu', 'Options for column {label}', { label: col.label })\n}\n\nfunction onColumnMenuSelect(col: GrDataColumn<TRow>, item: GrDropdownMenuAction): void {\n const pinned: GrColumnPin = item.key === 'left' || item.key === 'right' ? item.key : null\n if ((col.pinned ?? null) === pinned)\n return\n\n pinColumn(String(col.key), pinned)\n\n announce(pinned === 'left'\n ? t('gr.dataTable.columnPinnedLeft', 'Column {label} pinned to the left', { label: col.label })\n : pinned === 'right'\n ? t('gr.dataTable.columnPinnedRight', 'Column {label} pinned to the right', { label: col.label })\n : t('gr.dataTable.columnUnpinned', 'Column {label} unpinned', { label: col.label }))\n}\n\nfunction pinColumn(key: string, pinned: GrColumnPin): void {\n const next = { ...pinnedOverrides.value, [key]: pinned }\n\n pinnedState.value = next\n emit('update:pinnedColumns', next)\n emit('columnPin', { key, pinned })\n}\n\nconst {\n columnWidths,\n setMeasuredWidths,\n widthOf,\n tableMinWidth,\n resizingKey,\n onResizerPointerDown,\n onResizerKeydown,\n resetColumnWidth,\n resizerValue,\n} = useDataTableColumnWidths<TRow>({\n orderedColumns: () => orderedColumns.value,\n columnWidths: () => props.columnWidths,\n resizableColumns: () => props.resizableColumns,\n loading: () => props.loading,\n headerCellEls,\n onWidthsChange: widths => emit('update:columnWidths', widths),\n onColumnResize: (key, width) => emit('columnResize', { key, width }),\n announceWidth: (label, width) => {\n announce(t('gr.dataTable.columnResized', 'Column {label} is {width} pixels wide', { label, width }))\n },\n})\n\nconst { hasPinnedLeft, pinnedStyleOf, pinnedCellClass } = useDataTableLayout<TRow>({\n orderedColumns: () => orderedColumns.value,\n columnKeys: () => columnKeys.value,\n selectable: () => props.selectable,\n resizableColumns: () => props.resizableColumns,\n headerCellEls,\n watchSources: () => [orderedColumns.value, columnWidths.value, props.loading, props.rows.length] as const,\n onMeasuredWidths: setMeasuredWidths,\n})\n\nconst tableProps = computed(() => ({\n size: resolvedSize.value,\n ariaLabel: props.ariaLabel,\n ariaLabelledby: props.ariaLabelledby,\n regionLabel: props.regionLabel,\n stickyHeader: props.stickyHeader,\n maxHeight: props.maxHeight,\n rowCount: ariaRowCount.value,\n // Пользовательская ширина требует фиксированной раскладки: на авторазметке\n // браузер пересчитывает колонки по содержимому, и заданная ширина пропадает.\n fixedLayout: props.virtual || props.resizableColumns,\n tableMinWidth: tableMinWidth.value,\n}))\n\nfunction columnHandleLabel(col: GrDataColumn<TRow>): string {\n return t('gr.dataTable.moveColumn', 'Move column {label}', { label: col.label })\n}\n\nfunction resizerLabel(col: GrDataColumn<TRow>): string {\n return t('gr.dataTable.resizeColumn', 'Width of column {label}', { label: col.label })\n}\n\n// ————— Ширина колонок.\n\n/** Уже колонки не бывает: в неё перестаёт помещаться даже стрелка сортировки. */\n\n/**\n * Живой регион существует с первого рендера и пуст, пока объявлять нечего.\n * Регион, который появляется уже с текстом, часть AT не объявляет вовсе —\n * а именно так вело себя `role=\"status\"` внутри строки загрузки.\n */\nconst liveMessage = computed(() => {\n if (props.loading)\n return resolvedLoadingText.value\n if (isEmpty.value)\n return resolvedEmptyText.value\n return ''\n})\n\n/**\n * В режиме сетки регион таблицы не рендерится, и объявлять состояние некому —\n * берёт на себя общий объявитель. Вне режима ничего не меняется: там регион на\n * месте, и второе объявление было бы дублем.\n */\nwatch(liveMessage, (next) => {\n if (props.cellNavigation && next)\n announce(next)\n})\n\nfunction cellValue(row: TRow, key: string): unknown {\n return (row as Record<string, unknown>)[key]\n}\n\nfunction rowClassName(row: TRow, index: number): string | undefined {\n const source = props.rowClass\n return typeof source === 'function' ? source(row, index) : source\n}\n\nfunction onRowClick(row: TRow, index: number, event: MouseEvent): void {\n emit('rowClick', { row, index, event })\n}\n\n// ————— Выбор строк.\n// Uncontrolled-режим, как у сортировки выше: без `v-model:selected` чекбоксы\n// рисовались, кликались и никогда не отмечались — состояние выбора целиком\n// выводилось из пропа, а внутреннего не было вовсе.\nconst {\n isRowSelectable,\n isRowSelected,\n selectableRows,\n allSelected,\n someSelected,\n toggleRow,\n toggleAll,\n} = useDataTableSelection<TRow>({\n rows: () => sortedRows.value,\n selected: () => props.selected,\n selectableRow: () => props.selectableRow,\n rowKeyValue,\n onSelectedChange: keys => emit('update:selected', keys),\n})\n\nconst expandDetailId = useId()\n\nconst {\n isRowExpandable,\n isRowExpanded,\n toggleRow: toggleRowExpanded,\n detailStateOf,\n detailDataOf,\n retryDetail,\n invalidateDetail,\n} = useDataTableExpansion<TRow>({\n expandedKeys: () => props.expandedKeys,\n rows: () => props.rows,\n expandableRow: () => props.expandableRow,\n loadDetail: () => props.loadDetail,\n accordion: () => props.accordion,\n rowKeyValue,\n onExpandedChange: keys => emit('update:expandedKeys', keys),\n onExpand: (row, key) => {\n emit('expand', { row, key })\n announce(t('gr.dataTable.detailExpanded', 'Row details shown'))\n },\n onCollapse: (row, key) => {\n emit('collapse', { row, key })\n announce(t('gr.dataTable.detailCollapsed', 'Row details hidden'))\n },\n onDetailLoadError: (row, key, error) => emit('detailLoadError', { row, key, error }),\n})\n\n/** Id строки подробностей: адресат `aria-controls` у кнопки. */\nfunction detailRowId(row: TRow): string {\n return `${expandDetailId}-${rowKeyValue(row)}`\n}\n\n// ————— Императивный API.\nconst tableRef = ref<InstanceType<typeof GrTable> | null>(null)\nconst rootId = useId()\n\nfunction rootEl(): HTMLElement | null {\n return (tableRef.value?.$el as HTMLElement | undefined) ?? null\n}\n\n/** Скролл-контейнер таблицы — он же элемент с `maxHeight`. */\nfunction scrollEl(): HTMLElement | null {\n const root = rootEl()\n return root?.matches('[data-gr-table-scroll]') ? root : root?.querySelector('[data-gr-table-scroll]') ?? null\n}\n\n/**\n * Виртуализация строк.\n *\n * Распорки здесь не псевдоэлементы, как у списочных компонентов: `<tbody>`\n * игнорирует `padding`, а псевдоэлемент внутри группы строк не образует строку\n * с управляемой высотой. Поэтому срезанное держат две служебные `<tr>` — той же\n * формы, что строки загрузки и пустоты у `GrTable`.\n */\nconst scrollContainer = ref<HTMLElement | null>(null)\n\nonMounted(() => {\n scrollContainer.value = scrollEl()\n})\n\nconst virtualizer = useVirtualList({\n container: scrollContainer,\n count: () => (props.virtual ? sortedRows.value.length : 0),\n // Сортировка и замена rows раздают индексы заново — замеры сбрасываются.\n source: () => sortedRows.value,\n itemSize: () => rowHeightEstimates[resolvedSize.value],\n // Скролл-контейнер живёт в `GrTable` и до монтирования недоступен: окно\n // первого рендера считается от объявленной высоты.\n viewportSize: () => (typeof props.maxHeight === 'number' ? props.maxHeight : undefined),\n})\n\n/** Строки к отрисовке вместе с их абсолютной позицией в наборе. */\nconst renderedRows = computed(() => {\n const rows = sortedRows.value\n if (!props.virtual)\n return rows.map((row, index) => ({ row, index }))\n\n const { start, end } = virtualizer.range.value\n return rows.slice(start, end).map((row, offset) => ({ row, index: start + offset }))\n})\n\n/**\n * Порядок ячеек в строке: раскрытие, выбор, колонки. Шапка и тело рисуют его\n * одинаково, поэтому индекс колонки в сетке считается один раз здесь.\n */\nconst serviceColumnCount = computed(() =>\n (expandColumnVisible.value ? 1 : 0) + (props.selectable ? 1 : 0),\n)\n\nconst expandColumnIndex = 0\nconst selectColumnIndex = computed(() => (expandColumnVisible.value ? 1 : 0))\nconst dataColumnIndex = (index: number): number => serviceColumnCount.value + index\n\n/** Узлы ячеек по ключу сетки. Заполняется `:ref` в разметке. */\nconst cellEls = new Map<string, HTMLElement>()\n\n/**\n * Индексы отрисованных строк. При виртуализации это окно, без неё — весь\n * набор: сетке нужно то, что действительно есть в разметке.\n */\nconst renderedRowIndexes = computed(() => renderedRows.value.map(item => item.index))\n\nconst grid = useDataTableGridNavigation({\n enabled: () => props.cellNavigation,\n columns: () => totalColumns.value,\n renderedRows: () => renderedRowIndexes.value,\n totalRows: () => sortedRows.value.length,\n cellEls,\n scrollToRow: props.virtual ? (index: number) => virtualizer.scrollToIndex(index) : undefined,\n})\n\nfunction registerCell(row: number, column: number, el: unknown): void {\n registerEl(cellEls, gridCellKey(row, column), el)\n}\n\n/**\n * Остановка `Tab` у контролов внутри ячеек.\n *\n * При навигации по ячейкам их в таб-порядке быть не должно: `Tab` принадлежит\n * сетке целиком, а до кнопки добираются стрелкой до ячейки и `Enter`. Иначе\n * остановок было бы столько же, сколько контролов, — то есть паттерн не\n * выполнялся бы вовсе.\n */\nconst cellControlTabindex = computed(() => (props.cellNavigation ? -1 : undefined))\n\nconst spacerBefore = computed(() => (props.virtual ? virtualizer.offset.value : 0))\nconst spacerAfter = computed(() => (props.virtual ? virtualizer.offsetEnd.value : 0))\n\n/** Ширина колонки: число трактуем как пиксели. */\nfunction columnWidthStyle(width: string | number | undefined): Record<string, string> | undefined {\n if (width === undefined)\n return undefined\n return { width: typeof width === 'number' ? `${width}px` : width }\n}\n\nfunction scrollToRow(key: string | number, options?: ScrollIntoViewOptions): boolean {\n // Ключ строки — произвольная строка от потребителя, в селектор её не подставить:\n // сравниваем через `dataset`, а не собираем `[data-row-key=\"…\"]` конкатенацией.\n const target = String(key)\n\n // Строки вне окна в DOM нет: без прокрутки виртуального списка поиск по\n // `dataset` вернул бы `undefined`, и метод молча отвечал бы «не нашёл».\n if (props.virtual) {\n const index = sortedRows.value.findIndex(row => String(rowKeyValue(row)) === target)\n if (index < 0)\n return false\n\n virtualizer.scrollToIndex(index)\n void nextTick(() => {\n // Вызов опциональный: отложенный `scrollIntoView` некому поймать, а в\n // среде без него (jsdom) это дало бы необработанный отказ промиса.\n findRowEl(target)?.scrollIntoView?.(options ?? { block: 'nearest' })\n })\n return true\n }\n\n const row = findRowEl(target)\n if (!row)\n return false\n\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\nfunction findRowEl(rowKey: string): HTMLElement | undefined {\n // Ключ строки — произвольная строка от потребителя, в селектор её не\n // подставить: сравниваем через `dataset`, а не собираем селектор конкатенацией.\n const rows = rootEl()?.querySelectorAll<HTMLElement>('[data-gr-datatable-row]') ?? []\n return Array.prototype.find.call(rows, (el: HTMLElement) => el.dataset.rowKey === rowKey) as HTMLElement | undefined\n}\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl()?.scrollTo(options)\n}\n\ndefineExpose({\n /** Прокрутить к строке по её ключу. `false` — строки нет в DOM. */\n scrollToRow,\n /** Прокрутить скролл-контейнер таблицы. */\n scrollTo,\n /** Снять сортировку (эквивалент третьего состояния). */\n clearSort,\n /** Отметить/снять все выбираемые строки. */\n toggleAll,\n /**\n * Сбросить загруженные подробности: у одной строки либо у всех.\n * Нужен, когда запись изменилась на сервере, — само по себе раскрытие\n * держит загруженное, пока строка жива.\n */\n invalidateDetail,\n})\n\n/**\n * Три семейства слотов по ключу колонки — `#cell-<key>` (`{ row, index }`),\n * `#header-<key>` (`{ column }`) и `#summary-<key>` (`{ value, column }`) —\n * попадают под общую индексную сигнатуру, а не под шаблонные.\n *\n * Шаблонные (`` `cell-${string}` ``) сужали бы тип слотов строже\n * `InternalSlots`, и дженерик-компонент переставал приниматься `h()`: ломался\n * бы рендер-функцией, оставаясь рабочим в шаблоне. Цена — пропсы этих трёх\n * семейств не типизированы; они описаны здесь и на странице компонента.\n */\ndefineSlots<{\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Содержимое, пока едут данные. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Подвал под таблицей: пагинация, счётчик, итоги во всю ширину. */\n footer?: (props: { columns: GrDataColumn<TRow>[], totalColumns: number }) => any\n [byColumn: string]: ((props?: any) => any) | undefined\n}>()\n</script>\n\n<template>\n <GrTable\n v-bind=\"tableProps\"\n ref=\"tableRef\"\n row-groups\n data-gr-datatable\n :role=\"cellNavigation ? 'grid' : 'table'\"\n @keydown=\"grid.onKeydown\"\n >\n <!-- Caption рендерится всегда (у `GrTable` он `sr-only`): в нём живёт\n постоянный live-регион, иначе объявлять загрузку было бы нечему. -->\n <template #caption>\n <slot name=\"caption\">\n {{ caption }}\n </slot>\n <!--\n В режиме сетки своего региона у таблицы нет: `role=\"grid\"` не допускает\n потомков, кроме строк и групп, — любой лишний узел внутри роняет\n `aria-required-children` как critical. Там загрузку и пустоту объявляет\n общий объявитель пакета (см. `watch` рядом с `liveMessage`).\n -->\n <span\n v-if=\"!cellNavigation\"\n :id=\"`${rootId}-live`\"\n data-gr-datatable-live\n role=\"status\"\n aria-live=\"polite\"\n >{{ liveMessage }}</span>\n </template>\n\n <template #header>\n <tr data-gr-datatable-header :aria-rowindex=\"virtual ? 1 : undefined\">\n <!-- Пустой заголовок служебной колонки: подписи у неё нет, но место\n занять обязана, иначе шапка съедет относительно тела. -->\n <th\n v-if=\"expandColumnVisible\"\n :ref=\"el => registerCell(HEADER_ROW_INDEX, expandColumnIndex, el)\"\n data-gr-datatable-expand-head\n scope=\"col\"\n :class=\"[expandColumnWidths[resolvedSize], cellClass]\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(HEADER_ROW_INDEX, expandColumnIndex) : undefined\"\n @focus=\"grid.setActive(HEADER_ROW_INDEX, expandColumnIndex)\"\n />\n <th\n v-if=\"selectable\"\n :ref=\"(el) => { registerEl(headerCellEls, SELECT_COLUMN_KEY, el); registerCell(HEADER_ROW_INDEX, selectColumnIndex, el) }\"\n class=\"text-left\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(HEADER_ROW_INDEX, selectColumnIndex) : undefined\"\n :class=\"[\n selectColumnClass,\n cellClass,\n hasPinnedLeft ? columnPinnedClass : '',\n ]\"\n :style=\"hasPinnedLeft ? { left: '0px' } : undefined\"\n scope=\"col\"\n @focus=\"grid.setActive(HEADER_ROW_INDEX, selectColumnIndex)\"\n >\n <GrCheckbox\n data-gr-datatable-select-all\n :tabindex=\"cellControlTabindex\"\n :model-value=\"allSelected\"\n :indeterminate=\"someSelected\"\n :size=\"checkboxSize\"\n :disabled=\"loading || selectableRows.length === 0\"\n :aria-label=\"t('gr.dataTable.selectAll', 'Select all rows')\"\n @update:model-value=\"toggleAll\"\n />\n </th>\n <th\n v-for=\"(col, colIndex) in orderedColumns\"\n :key=\"col.key\"\n :ref=\"(el) => { registerEl(headerCellEls, String(col.key), el); registerCell(HEADER_ROW_INDEX, dataColumnIndex(colIndex), el) }\"\n class=\"font-700\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(HEADER_ROW_INDEX, dataColumnIndex(colIndex)) : undefined\"\n :data-column-key=\"col.key\"\n :class=\"[\n headerTextClass,\n cellClass,\n cellAlign(col),\n reorderableColumns || resizableColumns || pinnableColumns ? 'group relative' : '',\n draggingColumnKey === String(col.key) ? columnDraggingClass : '',\n columnDropClass(colIndex),\n ...pinnedCellClass(col, colIndex),\n ]\"\n :style=\"{ ...columnWidthStyle(widthOf(col)), ...pinnedStyleOf(col) }\"\n :aria-sort=\"ariaSortFor(col)\"\n scope=\"col\"\n @focus=\"grid.setActive(HEADER_ROW_INDEX, dataColumnIndex(colIndex))\"\n >\n <div class=\"inline-flex items-center\" :class=\"headerGapClass\">\n <button\n v-if=\"reorderableColumns\"\n :ref=\"el => registerEl(columnHandleEls, String(col.key), el)\"\n type=\"button\"\n data-gr-datatable-column-handle\n :class=\"[columnHandleClass, columnSort.isActive.value ? columnHandleActiveClass : '']\"\n :tabindex=\"cellNavigation ? -1 : columnRoving.tabindexFor(String(col.key))\"\n :aria-label=\"columnHandleLabel(col)\"\n :disabled=\"loading\"\n @pointerdown=\"columnSort.startFrom(String(col.key))($event)\"\n @keydown=\"onColumnHandleKeydown($event, String(col.key))\"\n @focus=\"columnRoving.setActive(String(col.key))\"\n @click.stop\n >\n <IconGripVertical class=\"block\" aria-hidden=\"true\" />\n </button>\n <button\n v-if=\"col.sortable\"\n type=\"button\"\n data-gr-datatable-sort\n :tabindex=\"cellControlTabindex\"\n class=\"inline-flex items-center text-[var(--gr-muted-fg)] hover:text-[var(--gr-fg)] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)] rounded-[var(--gr-radius-sm)]\"\n :class=\"headerGapClass\"\n @click=\"toggleSort(col)\"\n >\n <span>\n <slot :name=\"`header-${col.key}`\" :column=\"col\">\n {{ col.label }}\n </slot>\n </span>\n <span class=\"sr-only\">{{ sortHint(col) }}</span>\n <span class=\"inline-flex\" aria-hidden=\"true\">\n <GrIcon v-if=\"currentSortKey === col.key && currentSortDir === 'asc'\" :size=\"sortIconSize\">\n <IconArrowUp />\n </GrIcon>\n <GrIcon v-else-if=\"currentSortKey === col.key && currentSortDir === 'desc'\" :size=\"sortIconSize\">\n <IconArrowDown />\n </GrIcon>\n </span>\n </button>\n <span v-else class=\"text-[var(--gr-muted-fg)]\">\n <slot :name=\"`header-${col.key}`\" :column=\"col\">\n {{ col.label }}\n </slot>\n </span>\n </div>\n\n <GrDropdownMenu\n v-if=\"pinnableColumns\"\n data-gr-datatable-column-menu\n :items=\"columnMenuItems(col)\"\n placement=\"bottom-end\"\n :width=\"COLUMN_MENU_WIDTH\"\n :aria-label=\"columnMenuLabel(col)\"\n @select=\"onColumnMenuSelect(col, $event)\"\n >\n <template #trigger=\"{ triggerProps }\">\n <button\n v-bind=\"triggerProps\"\n type=\"button\"\n data-gr-datatable-column-menu-trigger\n :tabindex=\"cellControlTabindex\"\n :class=\"columnMenuTriggerClass\"\n :aria-label=\"columnMenuLabel(col)\"\n :disabled=\"loading\"\n @click.stop\n >\n <IconEllipsisVertical class=\"block\" aria-hidden=\"true\" />\n </button>\n </template>\n </GrDropdownMenu>\n\n <span\n v-if=\"resizableColumns\"\n data-gr-datatable-column-resizer\n role=\"separator\"\n :tabindex=\"cellNavigation ? -1 : 0\"\n aria-orientation=\"vertical\"\n :class=\"columnResizerClass\"\n :aria-label=\"resizerLabel(col)\"\n :aria-valuenow=\"resizerValue(col)\"\n :aria-valuemin=\"MIN_COLUMN_WIDTH\"\n :aria-valuetext=\"`${resizerValue(col)}px`\"\n @pointerdown=\"onResizerPointerDown($event, String(col.key))\"\n @keydown=\"onResizerKeydown($event, String(col.key))\"\n @dblclick=\"resetColumnWidth(String(col.key))\"\n @click.stop\n >\n <span\n :class=\"[\n columnResizerLineClass,\n columnResizerHoverClass,\n resizingKey === String(col.key) ? columnResizerLineActiveClass : '',\n ]\"\n aria-hidden=\"true\"\n />\n </span>\n </th>\n </tr>\n </template>\n\n <tbody v-if=\"loading\">\n <tr data-gr-datatable-loading>\n <td :colspan=\"totalColumns\" class=\"text-center text-[var(--gr-muted-fg)]\" :class=\"placeholderClass\">\n <slot name=\"loading\">\n <span class=\"inline-flex items-center gap-2\">\n <IconLoaderCircle class=\"block animate-spin\" :class=\"spinnerClass\" aria-hidden=\"true\" />\n <span>{{ resolvedLoadingText }}</span>\n </span>\n </slot>\n </td>\n </tr>\n </tbody>\n\n <tbody v-else-if=\"isEmpty\">\n <tr data-gr-datatable-empty>\n <td :colspan=\"totalColumns\" class=\"text-center text-[var(--gr-muted-fg)]\" :class=\"placeholderClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n </tbody>\n\n <template v-else>\n <!--\n Распорки виртуального списка. У таблицы они строки, а не псевдоэлементы:\n `<tbody>` игнорирует `padding`, а псевдоэлемент внутри группы строк не\n образует строку с управляемой высотой. Форма та же, что у служебных\n строк загрузки и пустоты, а группа вокруг — потому что тело собрано\n группами: строка вне группы не встала бы в таблицу вовсе.\n -->\n <tbody v-if=\"virtual && spacerBefore > 0\" data-gr-table-off-grid>\n <tr\n aria-hidden=\"true\"\n data-gr-datatable-spacer=\"before\"\n data-gr-table-off-grid\n :style=\"{ pointerEvents: 'none' }\"\n >\n <td :colspan=\"totalColumns\" :style=\"{ height: `${spacerBefore}px`, padding: '0', border: '0' }\" />\n </tr>\n </tbody>\n\n <!--\n Строка и её второй ярус лежат в одной группе, и замер виртуализатора\n висит на группе, а не на строке: иначе высота подробностей в него не\n попадает и распорка разъезжается молча. `ResizeObserver` примитива при\n этом следит за той же группой, поэтому раскрытие и подгрузка деталей\n уточняют высоту сами, без отдельного уведомления.\n -->\n <tbody\n v-for=\"{ row, index } in renderedRows\"\n :key=\"rowKeyValue(row)\"\n :ref=\"(el) => virtual && virtualizer.measure(index, el as Element | null)\"\n data-gr-datatable-row-group\n >\n <tr\n class=\"border-t border-[var(--gr-brd)]\"\n :class=\"[\n isRowSelected(row) ? rowSelectedClass : '',\n rowClassName(row, index),\n ]\"\n data-gr-datatable-row\n :data-row-key=\"rowKeyValue(row)\"\n :data-selected=\"selectable && isRowSelected(row) ? 'true' : undefined\"\n :aria-rowindex=\"ariaRowIndex(index)\"\n v-bind=\"rowProps?.(row, index)\"\n @click=\"onRowClick(row, index, $event)\"\n >\n <td\n v-if=\"expandColumnVisible\"\n :ref=\"el => registerCell(index, expandColumnIndex, el)\"\n data-gr-datatable-expand-cell\n class=\"text-left\"\n :class=\"[expandColumnWidths[resolvedSize], cellClass]\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(index, expandColumnIndex) : undefined\"\n @focus=\"grid.setActive(index, expandColumnIndex)\"\n >\n <!-- `.stop` на кнопке, а не на ячейке: гасить навигационный клик есть\n смысл только там, где стоит контрол. Иначе ячейка строки без\n второго яруса становится мёртвой зоной. -->\n <button\n v-if=\"isRowExpandable(row)\"\n type=\"button\"\n data-gr-datatable-expand\n :tabindex=\"cellControlTabindex\"\n :class=\"[expandButtonClass, checkboxSize === 'xs' ? 'h-5 w-5' : 'h-6 w-6']\"\n :aria-expanded=\"isRowExpanded(row)\"\n :aria-controls=\"detailRowId(row)\"\n :aria-label=\"isRowExpanded(row)\n ? t('gr.dataTable.collapseRow', 'Hide details')\n : t('gr.dataTable.expandRow', 'Show details')\"\n @click.stop=\"toggleRowExpanded(row)\"\n >\n <slot name=\"expand-icon\" :expanded=\"isRowExpanded(row)\" :row=\"row\">\n <IconChevronRight :class=\"[expandIconClass, isRowExpanded(row) ? expandIconOpenClass : '']\" />\n </slot>\n </button>\n </td>\n\n <td\n v-if=\"selectable\"\n :ref=\"el => registerCell(index, selectColumnIndex, el)\"\n class=\"text-left\"\n :class=\"[\n selectColumnClass,\n cellClass,\n hasPinnedLeft ? columnPinnedClass : '',\n hasPinnedLeft && isRowSelected(row) ? rowSelectedClass : '',\n ]\"\n :style=\"hasPinnedLeft ? { left: '0px' } : undefined\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(index, selectColumnIndex) : undefined\"\n @focus=\"grid.setActive(index, selectColumnIndex)\"\n >\n <!-- `.stop` на самом чекбоксе, а не на ячейке: гасить навигационный\n клик есть смысл только там, где стоит контрол выбора. Иначе\n служебная ячейка невыбираемой строки становится мёртвой зоной. -->\n <GrCheckbox\n v-if=\"isRowSelectable(row)\"\n data-gr-datatable-select-row\n :tabindex=\"cellControlTabindex\"\n :model-value=\"isRowSelected(row)\"\n :size=\"checkboxSize\"\n :aria-label=\"t('gr.dataTable.selectRow', 'Select row')\"\n @click.stop\n @update:model-value=\"toggleRow(row)\"\n />\n </td>\n <td\n v-for=\"(col, colIndex) in orderedColumns\"\n :key=\"col.key\"\n :ref=\"el => registerCell(index, dataColumnIndex(colIndex), el)\"\n :class=\"[\n cellClass,\n cellAlign(col),\n ...pinnedCellClass(col, colIndex),\n col.pinned && isRowSelected(row) ? rowSelectedClass : '',\n ]\"\n :style=\"{ ...columnWidthStyle(widthOf(col)), ...pinnedStyleOf(col) }\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(index, dataColumnIndex(colIndex)) : undefined\"\n @focus=\"grid.setActive(index, dataColumnIndex(colIndex))\"\n >\n <slot\n :name=\"`cell-${col.key}`\"\n :row=\"row\"\n :index=\"index\"\n :expanded=\"isRowExpanded(row)\"\n :toggle-expand=\"() => toggleRowExpanded(row)\"\n >\n <span>{{ cellValue(row, col.key) }}</span>\n </slot>\n </td>\n </tr>\n\n <!--\n Второй ярус идёт отдельной `<tr>` следом за своей строкой.\n `data-gr-table-off-grid` снимает с неё полосатость и подсветку и\n выключает её из счёта чётности соседей: она не строка набора.\n `aria-rowindex` ей тоже не положен по той же причине.\n -->\n <tr\n v-if=\"isRowExpanded(row)\"\n :id=\"detailRowId(row)\"\n data-gr-datatable-detail\n data-gr-table-off-grid\n :class=\"detailRowClass\"\n >\n <td :colspan=\"totalColumns\" :class=\"[detailCellClass, detailPaddings[resolvedSize]]\">\n <div :class=\"detailContentClass\">\n <div v-if=\"detailStateOf(row) === 'loading'\" data-gr-datatable-detail-loading>\n <slot name=\"detail-loading\" :row=\"row\">\n <GrSkeleton :count=\"2\" />\n </slot>\n </div>\n\n <div v-else-if=\"detailStateOf(row) === 'error'\" :class=\"detailErrorClass\" data-gr-datatable-detail-error>\n <slot name=\"detail-error\" :row=\"row\" :retry=\"() => retryDetail(row)\">\n <span>{{ t('gr.dataTable.detailError', 'Could not load details') }}</span>\n <GrButton size=\"xs\" tone=\"danger\" variant=\"outline\" @click=\"retryDetail(row)\">\n {{ t('gr.dataTable.detailRetry', 'Retry') }}\n </GrButton>\n </slot>\n </div>\n\n <slot\n v-else\n name=\"detail\"\n :row=\"row\"\n :index=\"index\"\n :data=\"detailDataOf(row)\"\n :state=\"detailStateOf(row)\"\n />\n </div>\n </td>\n </tr>\n </tbody>\n\n <tbody v-if=\"virtual && spacerAfter > 0\" data-gr-table-off-grid>\n <tr\n aria-hidden=\"true\"\n data-gr-datatable-spacer=\"after\"\n data-gr-table-off-grid\n :style=\"{ pointerEvents: 'none' }\"\n >\n <td :colspan=\"totalColumns\" :style=\"{ height: `${spacerAfter}px`, padding: '0', border: '0' }\" />\n </tr>\n </tbody>\n </template>\n\n <template v-if=\"$slots.footer || hasSummary\" #footer>\n <!--\n Итог зеркалит ячейку тела теми же функциями, а не своими классами: у\n `GrTable` ячейки `<tfoot>` не оформлены принципиально, и собранная руками\n строка разъезжается с телом на первой же смене `size`. Индекс колонки\n обязателен — по нему `pinnedEdgeClass` находит край группы.\n -->\n <tr\n v-if=\"hasSummary\"\n data-gr-datatable-summary\n :class=\"summaryRowClass\"\n :aria-rowindex=\"summaryAriaRowIndex\"\n >\n <td\n v-if=\"selectable\"\n :class=\"[\n selectColumnClass,\n cellClass,\n hasPinnedLeft ? columnPinnedClass : '',\n ]\"\n :style=\"hasPinnedLeft ? { left: '0px' } : undefined\"\n />\n <td\n v-for=\"(col, colIndex) in orderedColumns\"\n :key=\"col.key\"\n :data-column-key=\"col.key\"\n :class=\"[cellClass, cellAlign(col), ...pinnedCellClass(col, colIndex)]\"\n :style=\"{ ...columnWidthStyle(widthOf(col)), ...pinnedStyleOf(col) }\"\n >\n <slot :name=\"`summary-${col.key}`\" :value=\"summaryValue(col.key)\" :column=\"col\">\n <span>{{ summaryValue(col.key) }}</span>\n </slot>\n </td>\n </tr>\n\n <slot name=\"footer\" :columns=\"orderedColumns\" :total-columns=\"totalColumns\" />\n </template>\n </GrTable>\n</template>\n","<script setup lang=\"ts\" generic=\"TRow extends Record<string, unknown> = Record<string, unknown>\">\nimport type { Component } from 'vue'\nimport { computed, nextTick, onMounted, ref, useId, watch, watchEffect } from 'vue'\n\nimport GrTable from '../GrTable/GrTable.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport GrCheckbox from '../GrCheckbox/GrCheckbox.vue'\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport GrDropdownMenu from '../GrDropdownMenu/GrDropdownMenu.vue'\nimport type { GrDropdownMenuAction, GrDropdownMenuEntry } from '../GrDropdownMenu/menuModel'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useVirtualList } from '../../composables/useVirtualList'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrDataTableSortDir } from './grDataTableSort'\nimport { useDataTableRowKeys } from './composables/useDataTableRowKeys'\nimport { useDataTableSort } from './composables/useDataTableSort'\nimport { useDataTableSelection } from './composables/useDataTableSelection'\nimport { useDataTableColumnOrder } from './composables/useDataTableColumnOrder'\nimport { MIN_COLUMN_WIDTH, useDataTableColumnWidths } from './composables/useDataTableColumnWidths'\nimport { SELECT_COLUMN_KEY, useDataTableLayout } from './composables/useDataTableLayout'\nimport { useDataTableExpansion } from './composables/useDataTableExpansion'\nimport {\n gridCellKey,\n HEADER_ROW_INDEX,\n useDataTableGridNavigation,\n} from './composables/useDataTableGridNavigation'\nimport {\n type GrDataTableSize,\n cellPaddings,\n columnDraggingClass,\n detailCellClass,\n detailContentClass,\n detailErrorClass,\n detailPaddings,\n detailRowClass,\n expandButtonClass,\n expandColumnWidths,\n expandIconClass,\n expandIconOpenClass,\n columnHandleActiveClass,\n columnHandleClass,\n columnMenuTriggerClass,\n columnPinnedClass,\n columnResizerClass,\n columnResizerHoverClass,\n columnResizerLineActiveClass,\n columnResizerLineClass,\n headerGaps,\n headerTextSizes,\n placeholderPaddings,\n rowHeightEstimates,\n rowSelectedClass,\n selectCheckboxSizes,\n selectColumnWidths,\n sortIconSizes,\n spinnerSizes,\n summaryRowClass,\n} from './grDataTableStyles'\n\nimport IconArrowUp from '~icons/lucide/arrow-up'\nimport IconGripVertical from '~icons/lucide/grip-vertical'\nimport IconLoaderCircle from '~icons/lucide/loader-circle'\nimport IconArrowDown from '~icons/lucide/arrow-down'\nimport IconChevronRight from '~icons/lucide/chevron-right'\nimport IconEllipsisVertical from '~icons/lucide/ellipsis-vertical'\nimport IconArrowLeftToLine from '~icons/lucide/arrow-left-to-line'\nimport IconArrowRightToLine from '~icons/lucide/arrow-right-to-line'\nimport IconPinOff from '~icons/lucide/pin-off'\n\n/**\n * Ключ колонки. Собственные поля строки подсказываются автодополнением, но\n * произвольная строка тоже допустима: колонка может быть вычисляемой и жить\n * только в слоте `#cell-<key>`.\n */\nexport type GrDataColumnKey<TRow extends Record<string, unknown> = Record<string, unknown>>\n = | Extract<keyof TRow, string>\n | (string & {})\n\nexport type GrDataColumn<TRow extends Record<string, unknown> = Record<string, unknown>> = {\n key: GrDataColumnKey<TRow>\n label: string\n /**\n * Заголовок колонки сортирует.\n *\n * Сортируется **переданный массив `rows`**, и только он. Над серверной\n * пагинацией это врёт: «максимальное списание» покажет максимум по текущей\n * странице, а прочитается как максимум по журналу. Данные приходят\n * постранично — включайте `externalSort` и сортируйте запросом.\n */\n sortable?: boolean\n align?: 'left' | 'center' | 'right'\n /**\n * Ширина колонки: число — пиксели, строка — как есть (`'40%'`, `'12rem'`).\n *\n * Уезжает в заголовочную ячейку: при фиксированной раскладке ширины колонок\n * задаёт первая строка таблицы, а это и есть `<thead>`.\n */\n width?: string | number\n /**\n * Колонка липнет к краю при горизонтальной прокрутке.\n *\n * Закреплённые колонки всегда стоят своей группой у своего края — перенос\n * колонки из группы в группу запрещён, иначе «закреплена слева» перестало бы\n * означать «слева».\n */\n pinned?: GrColumnPinSide\n}\n\n/** Край, к которому липнет колонка. */\nexport type GrColumnPinSide = 'left' | 'right'\n\n/**\n * Закрепление, выбранное пользователем. `null` — не «как в конфиге», а\n * «откреплена»: без него снять закрепление, объявленное у колонки, было бы\n * нечем — отсутствие ключа означает «решает конфиг».\n */\nexport type GrColumnPin = GrColumnPinSide | null\n\n/**\n * Значения итоговой строки по ключам колонок.\n *\n * Не строка набора: у итога нет ключа, он не сортируется и не выбирается.\n * Колонка, для которой значения нет, остаётся пустой ячейкой — заполнять все\n * колонки итог не обязан.\n */\nexport type GrDataTableSummary<TRow extends Record<string, unknown> = Record<string, unknown>>\n = Partial<Record<GrDataColumnKey<TRow>, unknown>>\n\nexport type GrDataTableRowKey<TRow extends Record<string, unknown> = Record<string, unknown>>\n = | string\n | ((row: TRow) => string | number)\n\n/** Порядок обхода состояний сортировки по клику на заголовок. */\nexport type GrDataTableSortCycle = 'asc-desc' | 'asc-desc-none'\n\nexport interface GrDataTableProps<TRow extends Record<string, unknown> = Record<string, unknown>> {\n rows: TRow[]\n columns: GrDataColumn<TRow>[]\n /** Ключ строки или функция-резолвер. По умолчанию — поле `'id'`. */\n rowKey?: GrDataTableRowKey<TRow>\n /** Ключ колонки для начальной сортировки (uncontrolled-режим). */\n initialSortKey?: string\n /** Направление начальной сортировки (uncontrolled-режим). */\n initialSortDir?: GrDataTableSortDir\n /** Контролируемый ключ сортировки: `v-model:sortKey`. Задаёт controlled-режим. */\n sortKey?: string\n /** Контролируемое направление сортировки: `v-model:sortDir`. */\n sortDir?: GrDataTableSortDir\n /** Клик по заголовку: `asc → desc` или `asc → desc → без сортировки`. */\n sortCycle?: GrDataTableSortCycle\n /**\n * Внешняя сортировка (например серверная): компонент НЕ сортирует `rows`\n * сам, а только сообщает о смене через `update:sortKey`/`update:sortDir`/\n * `sortChange`. `rows` при этом должны приходить уже отсортированными.\n */\n externalSort?: boolean\n /**\n * Выбор строк: добавляет ведущую колонку с чекбоксами (+ «выбрать все» в шапке).\n * Выбранные ключи строк — через `v-model:selected`.\n */\n selectable?: boolean\n /** Контролируемый список выбранных ключей строк: `v-model:selected`. */\n selected?: Array<string | number>\n /** Предикат «строку можно выбрать». Невыбираемые строки не попадают и в «выбрать все». */\n selectableRow?: (row: TRow) => boolean\n /**\n * Состояние загрузки: тело таблицы заменяется строкой-индикатором.\n * `empty`-состояние при этом не показывается.\n */\n loading?: boolean\n /** Текст индикатора загрузки. i18n: fallback `gr.dataTable.loading`. */\n loadingText?: string\n /** Текст пустого состояния. i18n: fallback `gr.dataTable.empty`; слот `#empty` сильнее. */\n emptyText?: string\n /** Класс строки: общий для всех либо вычисляемый по строке. */\n rowClass?: string | ((row: TRow, index: number) => string | undefined)\n /** Произвольные атрибуты строки (`data-*`, `title`, …). */\n rowProps?: (row: TRow, index: number) => Record<string, unknown> | undefined\n /**\n * Итоговая строка в `<tfoot>`: значения по ключам колонок.\n *\n * Встаёт по той же колоночной сетке, что и тело, — с теми же паддингами,\n * выравниванием, ширинами и закреплением. Собранная руками в `#footer`, она\n * этих классов не получает (`GrTable` их принципиально не даёт) и разъезжается\n * с телом на первой же смене `size`.\n *\n * Итог не суммируется компонентом: что считать итогом — знает приложение.\n * Оформление ячейки — слот `#summary-<key>`.\n *\n * `null` равнозначен отсутствию: `totals ?? null` — обычная запись там, где\n * итог считается не всегда.\n */\n summaryRow?: GrDataTableSummary<TRow> | null\n /**\n * Размер таблицы: кегль, паддинги ячеек, стрелки сортировки и чекбоксы.\n * Прокидывается в `GrTable`.\n */\n size?: GrDataTableSize\n // Прокси к GrTable:\n caption?: string\n ariaLabel?: string\n ariaLabelledby?: string\n regionLabel?: string\n /** Прилипающий заголовок при вертикальном скролле (нужен `maxHeight`). */\n stickyHeader?: boolean\n /**\n * Виртуализация строк: в DOM живёт только окно вокруг вьюпорта. Высоту окна\n * задаёт `maxHeight`, без него окна прокрутки не существует.\n *\n * Включает фиксированную раскладку таблицы: ширина колонки считается по\n * содержимому всех строк, а в DOM их только окно — без фиксации колонки\n * прыгали бы на каждой прокрутке. Ширины стоит задать через `width` у\n * колонок, иначе фиксированная раскладка делит место поровну.\n */\n virtual?: boolean\n /** Максимальная высота таблицы (вертикальный скролл). Число — в пикселях. */\n maxHeight?: string | number\n /**\n * Пользовательский порядок колонок: в шапке появляется ручка переноса.\n * Колонка тянется указателем и двигается `Shift`+`←`/`→` с клавиатуры.\n */\n reorderableColumns?: boolean\n /**\n * Контролируемый порядок колонок — ключи в нужном порядке (`v-model:columnOrder`).\n * Не задан — порядок компонент помнит сам, начиная с порядка `columns`.\n */\n columnOrder?: string[]\n /**\n * Пользовательская ширина колонок: у правого края заголовка появляется ручка.\n * Тянется указателем, с клавиатуры — стрелками (паттерн window splitter).\n *\n * Включает фиксированную раскладку таблицы: без неё браузер пересчитывает\n * ширины по содержимому и заданная пользователем пропадает.\n */\n resizableColumns?: boolean\n /**\n * Контролируемые ширины в пикселях по ключу колонки (`v-model:columnWidths`).\n * Не заданы — ширины компонент помнит сам.\n */\n columnWidths?: Record<string, number>\n /**\n * Закрепление колонок задаёт пользователь: в шапке появляется меню с\n * «закрепить слева / справа / открепить».\n *\n * Без пропа `pinned` у колонки остаётся тем, чем был, — объявлением в\n * конфиге, которое меняется только кодом.\n */\n pinnableColumns?: boolean\n /**\n * Контролируемое закрепление по ключу колонки (`v-model:pinnedColumns`).\n * Не задано — компонент помнит его сам, начиная с `pinned` у колонок.\n */\n pinnedColumns?: Record<string, GrColumnPin>\n /**\n * Клавиатура по ячейкам: паттерн `grid` из WAI-ARIA APG.\n *\n * Вся таблица становится **одной** остановкой `Tab`, внутрь ведут стрелки, а\n * в содержимое ячейки — `Enter` или `F2`. Поэтому проп отдельный, а не\n * поведение по умолчанию: он переставляет таб-порядок у всех, кто таблицу\n * уже поставил.\n */\n cellNavigation?: boolean\n /**\n * Второй ярус строки: колонка с кнопкой раскрытия и блок подробностей под\n * строкой. Содержимое рисует слот `#detail`.\n */\n expandable?: boolean\n /** Контролируемый список раскрытых ключей (`v-model:expandedKeys`). */\n expandedKeys?: Array<string | number>\n /** У какой строки есть второй ярус. Остальные кнопки не получают. */\n expandableRow?: (row: TRow) => boolean\n /**\n * Подгрузка подробностей в момент раскрытия. Без неё содержимое берётся из\n * самой строки. `signal` обязателен: строку сворачивают чаще, чем ждут.\n */\n loadDetail?: (row: TRow, signal: AbortSignal) => Promise<unknown>\n /** Раскрыта не больше одной строки. */\n accordion?: boolean\n /**\n * Рисовать ли служебную колонку с собственной кнопкой раскрытия.\n *\n * `false` — колонки нет, и раскрытием управляет разметка потребителя: слоты\n * ячеек получают `expanded` и `toggleExpand`, чтобы кнопку можно было\n * поставить в свой столбец действий рядом с остальными. Тогда `aria-expanded`\n * и доступное имя ложатся на неё же — компоненту их вешать не на что.\n */\n expandColumn?: boolean\n}\n\nexport interface GrDataTableEmits<TRow extends Record<string, unknown> = Record<string, unknown>> {\n (e: 'update:sortKey', value: string): void\n (e: 'update:sortDir', value: GrDataTableSortDir): void\n (e: 'sortChange', value: { key: string, dir: GrDataTableSortDir }): void\n (e: 'update:selected', value: Array<string | number>): void\n (e: 'rowClick', payload: { row: TRow, index: number, event: MouseEvent }): void\n (e: 'update:columnOrder', value: string[]): void\n (e: 'columnReorder', payload: { key: string, from: number, to: number }): void\n (e: 'update:columnWidths', value: Record<string, number>): void\n (e: 'columnResize', payload: { key: string, width: number }): void\n (e: 'update:pinnedColumns', value: Record<string, GrColumnPin>): void\n (e: 'columnPin', payload: { key: string, pinned: GrColumnPin }): void\n (e: 'update:expandedKeys', value: Array<string | number>): void\n (e: 'expand', payload: { row: TRow, key: string | number }): void\n (e: 'collapse', payload: { row: TRow, key: string | number }): void\n (e: 'detailLoadError', payload: { row: TRow, key: string | number, error: unknown }): void\n}\n\n/**\n * `GrDataTable` — data-таблица поверх `GrTable` с сортировкой по клику\n * на заголовок и scoped-слотами ячеек (`#cell-<key>`), `#header-<key>`,\n * `#caption`, `#footer`, `#empty`, `#loading`.\n *\n * Итоговая строка объявляется пропом `summaryRow` и оформляется слотами\n * `#summary-<key>`: она встаёт по той же колоночной сетке, что и тело.\n *\n * `#footer` — для свободной разметки под итогом: несколько строк, примечание,\n * `colspan`. Рендерится внутрь того же `<tfoot>`, то есть его содержимое тоже\n * строки таблицы (`<tr><td>`), а скоуп отдаёт `columns` (в текущем порядке) и\n * `totalColumns` (со служебными колонками выбора и раскрытия).\n *\n * Сортировка, включая крайние случаи с пустыми и смешанными значениями, живёт\n * в `grDataTableSort.ts` — см. `docs/components/GrDataTable.md`.\n */\nconst props = withDefaults(defineProps<GrDataTableProps<TRow>>(), {\n rowKey: 'id' as GrDataTableRowKey<TRow>,\n initialSortKey: undefined,\n initialSortDir: 'asc',\n sortKey: undefined,\n sortDir: undefined,\n sortCycle: 'asc-desc',\n externalSort: false,\n selectable: false,\n selected: undefined,\n selectableRow: undefined,\n loading: false,\n loadingText: undefined,\n emptyText: undefined,\n rowClass: undefined,\n rowProps: undefined,\n summaryRow: undefined,\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n stickyHeader: false,\n maxHeight: undefined,\n virtual: false,\n reorderableColumns: false,\n columnOrder: undefined,\n resizableColumns: false,\n columnWidths: undefined,\n pinnableColumns: false,\n pinnedColumns: undefined,\n cellNavigation: false,\n expandable: false,\n expandedKeys: undefined,\n expandableRow: undefined,\n loadDetail: undefined,\n accordion: false,\n expandColumn: true,\n})\n\n// Раньше остальных проверок: таблица читает `rows` уже в setup, и гард,\n// стоящий в хвосте, до предупреждения бы не дожил.\nif (__GR_DEV__) {\n watchEffect(() => {\n if (!Array.isArray(props.rows)) {\n console.warn(\n `[granularity] GrDataTable: обязательный проп \\`rows\\` должен быть массивом — получено ${String(props.rows)}.`,\n )\n }\n\n if (!Array.isArray(props.columns)) {\n console.warn(\n `[granularity] GrDataTable: обязательный проп \\`columns\\` должен быть массивом — получено ${String(props.columns)}.`,\n )\n }\n })\n}\n\nconst emit = defineEmits<GrDataTableEmits<TRow>>()\n\nconst { t, locale } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.dataTable.loading', 'Loading…'))\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.dataTable.empty', 'No data'))\n\nconst {\n currentSortKey,\n currentSortDir,\n sortedRows,\n toggleSort,\n clearSort,\n ariaSortFor,\n} = useDataTableSort<TRow>({\n rows: () => props.rows,\n sortKey: () => props.sortKey,\n sortDir: () => props.sortDir,\n initialSortKey: () => props.initialSortKey,\n initialSortDir: () => props.initialSortDir,\n externalSort: () => props.externalSort,\n sortCycle: () => props.sortCycle,\n locale: () => locale.value,\n onSortChange: (key, dir) => {\n emit('update:sortKey', key)\n emit('update:sortDir', dir)\n emit('sortChange', { key, dir })\n },\n})\n\nfunction cellAlign(col: GrDataColumn<TRow>): string {\n if (col.align === 'right')\n return 'text-right'\n if (col.align === 'center')\n return 'text-center'\n return 'text-left'\n}\n\nconst { rowKeyValue } = useDataTableRowKeys<TRow>({ rowKey: () => props.rowKey })\n\n/**\n * Подсказка «что сделает нажатие» — visually hidden текстом **после** подписи\n * колонки, а не `aria-label`'ом на кнопке. `aria-label` подменял бы собой имя\n * `<th>`, и AT при переходе по ячейкам вместо «Название» читала бы\n * «Отсортировано по Название по возрастанию, нажмите…». Текущее состояние\n * сортировки при этом объявляет `aria-sort` на самом `<th>`.\n */\nfunction sortHint(col: GrDataColumn<TRow>): string {\n if (currentSortKey.value !== col.key)\n return t('gr.dataTable.sortAsc', 'Activate to sort ascending')\n\n if (currentSortDir.value === 'asc')\n return t('gr.dataTable.sortDesc', 'Activate to sort descending')\n\n return props.sortCycle === 'asc-desc-none'\n ? t('gr.dataTable.sortNone', 'Activate to remove sorting')\n : t('gr.dataTable.sortAsc', 'Activate to sort ascending')\n}\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrDataTable' })\n\nconst cellClass = computed(() => cellPaddings[resolvedSize.value])\nconst placeholderClass = computed(() => placeholderPaddings[resolvedSize.value])\nconst headerTextClass = computed(() => headerTextSizes[resolvedSize.value])\nconst headerGapClass = computed(() => headerGaps[resolvedSize.value])\nconst selectColumnClass = computed(() => selectColumnWidths[resolvedSize.value])\nconst spinnerClass = computed(() => spinnerSizes[resolvedSize.value])\nconst sortIconSize = computed(() => sortIconSizes[resolvedSize.value])\nconst checkboxSize = computed(() => selectCheckboxSizes[resolvedSize.value])\n\n/**\n * Номер строки и полное их число объявляем только при виртуализации: иначе\n * диктор считает строки по разметке, а там всего окно. Заголовок — строка\n * первая, поэтому строки набора начинаются со второй.\n */\n/**\n * Итог показывается, только когда набор на экране: «Итого 1 234» над спиннером —\n * утверждение о том, чего ещё не показали. Пустой набор при этом итог не гасит:\n * «Итого 0» под «нет данных» осмысленно, и считает его потребитель.\n *\n * Предикат один на всех: шаблон, `aria-rowcount` и номер строки обязаны сходиться,\n * иначе диктор объявит строку, которой в разметке нет.\n */\nconst hasSummary = computed(() => props.summaryRow != null && !props.loading)\n\nconst ariaRowCount = computed(() => (\n props.virtual ? sortedRows.value.length + 1 + (hasSummary.value ? 1 : 0) : undefined\n))\n\nfunction ariaRowIndex(index: number): number | undefined {\n return props.virtual ? index + 2 : undefined\n}\n\n/** Итог идёт следующим номером за последней строкой набора. */\nconst summaryAriaRowIndex = computed(() => (\n props.virtual ? sortedRows.value.length + 2 : undefined\n))\n\nconst isEmpty = computed(() => sortedRows.value.length === 0)\n\n/**\n * Значение итога по ключу колонки. Как и `cellValue`, отдаёт сырое: отсутствие\n * ключа даёт пустую ячейку, а ноль — это значение, а не пустота.\n */\nfunction summaryValue(key: string): unknown {\n return (props.summaryRow as Record<string, unknown> | undefined)?.[key]\n}\n\n// Общее число колонок с учётом ведущей чекбокс-колонки — для `colspan`\n// строк loading/empty.\n/**\n * Раскрытие выключено при виртуализации целиком — см. предупреждение ниже.\n * Объявлено здесь, а не рядом с ним: от него зависит `colspan` служебных строк.\n */\nconst expandEnabled = computed(() => props.expandable)\n\n/** Своя колонка с кнопкой: её может не быть, если кнопку ставит потребитель. */\nconst expandColumnVisible = computed(() => expandEnabled.value && props.expandColumn)\n\nconst totalColumns = computed(() => (\n props.columns.length + (props.selectable ? 1 : 0) + (expandColumnVisible.value ? 1 : 0)\n))\n\n// ————— Порядок колонок.\n\n/**\n * Карты живут в компоненте, а не в модуле: наполняет их шаблон, а читают все\n * три колоночных модуля — порядок тянет за ячейку, ширина её замеряет,\n * раскладка считает по ней смещения закрепления.\n */\nconst headerCellEls = new Map<string, HTMLElement>()\nconst columnHandleEls = new Map<string, HTMLElement>()\n\nfunction registerEl(store: Map<string, HTMLElement>, key: string, el: unknown): void {\n if (el instanceof HTMLElement) {\n store.set(key, el)\n return\n }\n\n // Перестановка размонтирует старую ячейку уже после того, как встала новая:\n // снимаем запись, только если она протухла.\n const previous = store.get(key)\n if (previous && !previous.isConnected)\n store.delete(key)\n}\n\n/**\n * Закрепление, выбранное пользователем, поверх объявленного в конфиге колонки.\n *\n * Отсутствие ключа означает «решает конфиг», а `null` — «откреплена»: без\n * различия снять закрепление, объявленное у колонки, было бы нечем.\n */\nconst pinnedState = ref<Record<string, GrColumnPin>>({})\nconst pinnedOverrides = computed(() => props.pinnedColumns ?? pinnedState.value)\n\n/**\n * Колонки с уже разрешённым закреплением.\n *\n * Дальше по компоненту `col.pinned` читают порядок, раскладка и все три яруса\n * ячеек. Разрешать выбор пользователя в каждом из этих мест значило бы завести\n * четыре места, где он может разойтись, — поэтому он разрешается один раз\n * здесь, а ниже по течению ничего не знает о том, откуда взялось значение.\n */\nconst resolvedColumns = computed<GrDataColumn<TRow>[]>(() => props.columns.map((col) => {\n const key = String(col.key)\n if (!(key in pinnedOverrides.value))\n return col\n\n return { ...col, pinned: pinnedOverrides.value[key] ?? undefined }\n}))\n\nconst {\n orderedColumns,\n columnKeys,\n draggingColumnKey,\n columnDropClass,\n onColumnHandleKeydown,\n columnSort,\n columnRoving,\n} = useDataTableColumnOrder<TRow>({\n columns: () => resolvedColumns.value,\n columnOrder: () => props.columnOrder,\n reorderableColumns: () => props.reorderableColumns,\n loading: () => props.loading,\n headerCellEls,\n columnHandleEls,\n onOrderChange: (order, moved) => {\n emit('update:columnOrder', order)\n emit('columnReorder', moved)\n },\n announceMove: (label, position, count) => {\n announce(t('gr.dataTable.columnMoved', 'Column {label} moved to position {position} of {count}', {\n label,\n position,\n count,\n }))\n },\n})\n\n/**\n * Ширина меню колонки.\n *\n * Панель ужимается по содержимому, и самой длинной подписи не хватало пяти\n * пикселей: «Закрепить справа» переносилось на вторую строку. Ширина задана\n * явно и с запасом — она обязана держать все три локали, а не ту, на которой\n * её замерили.\n */\nconst COLUMN_MENU_WIDTH = 240\n\n/**\n * Пункты меню колонки.\n *\n * Три состояния закрепления — это выбор одного из трёх, поэтому пункты\n * `menuitemradio` с `checked`, а не три команды: так диктор называет текущее\n * положение сам, и «открепить» у незакреплённой колонки видно выключенным, а\n * не пропадает.\n */\nfunction columnMenuItems(col: GrDataColumn<TRow>): GrDropdownMenuEntry[] {\n const current = col.pinned ?? null\n\n const item = (pinned: GrColumnPin, label: string, icon: Component): GrDropdownMenuAction => ({\n key: pinned ?? 'none',\n label,\n icon,\n role: 'menuitemradio',\n checked: current === pinned,\n })\n\n return [\n item('left', t('gr.dataTable.pinLeft', 'Pin to the left'), IconArrowLeftToLine),\n item('right', t('gr.dataTable.pinRight', 'Pin to the right'), IconArrowRightToLine),\n item(null, t('gr.dataTable.unpin', 'Unpin'), IconPinOff),\n ]\n}\n\nfunction columnMenuLabel(col: GrDataColumn<TRow>): string {\n return t('gr.dataTable.columnMenu', 'Options for column {label}', { label: col.label })\n}\n\nfunction onColumnMenuSelect(col: GrDataColumn<TRow>, item: GrDropdownMenuAction): void {\n const pinned: GrColumnPin = item.key === 'left' || item.key === 'right' ? item.key : null\n if ((col.pinned ?? null) === pinned)\n return\n\n pinColumn(String(col.key), pinned)\n\n announce(pinned === 'left'\n ? t('gr.dataTable.columnPinnedLeft', 'Column {label} pinned to the left', { label: col.label })\n : pinned === 'right'\n ? t('gr.dataTable.columnPinnedRight', 'Column {label} pinned to the right', { label: col.label })\n : t('gr.dataTable.columnUnpinned', 'Column {label} unpinned', { label: col.label }))\n}\n\nfunction pinColumn(key: string, pinned: GrColumnPin): void {\n const next = { ...pinnedOverrides.value, [key]: pinned }\n\n pinnedState.value = next\n emit('update:pinnedColumns', next)\n emit('columnPin', { key, pinned })\n}\n\nconst {\n columnWidths,\n setMeasuredWidths,\n widthOf,\n tableMinWidth,\n resizingKey,\n onResizerPointerDown,\n onResizerKeydown,\n resetColumnWidth,\n resizerValue,\n} = useDataTableColumnWidths<TRow>({\n orderedColumns: () => orderedColumns.value,\n columnWidths: () => props.columnWidths,\n resizableColumns: () => props.resizableColumns,\n loading: () => props.loading,\n headerCellEls,\n onWidthsChange: widths => emit('update:columnWidths', widths),\n onColumnResize: (key, width) => emit('columnResize', { key, width }),\n announceWidth: (label, width) => {\n announce(t('gr.dataTable.columnResized', 'Column {label} is {width} pixels wide', { label, width }))\n },\n})\n\nconst { hasPinnedLeft, pinnedStyleOf, pinnedCellClass } = useDataTableLayout<TRow>({\n orderedColumns: () => orderedColumns.value,\n columnKeys: () => columnKeys.value,\n selectable: () => props.selectable,\n resizableColumns: () => props.resizableColumns,\n headerCellEls,\n watchSources: () => [orderedColumns.value, columnWidths.value, props.loading, props.rows.length] as const,\n onMeasuredWidths: setMeasuredWidths,\n})\n\nconst tableProps = computed(() => ({\n size: resolvedSize.value,\n ariaLabel: props.ariaLabel,\n ariaLabelledby: props.ariaLabelledby,\n regionLabel: props.regionLabel,\n stickyHeader: props.stickyHeader,\n maxHeight: props.maxHeight,\n rowCount: ariaRowCount.value,\n // Пользовательская ширина требует фиксированной раскладки: на авторазметке\n // браузер пересчитывает колонки по содержимому, и заданная ширина пропадает.\n fixedLayout: props.virtual || props.resizableColumns,\n tableMinWidth: tableMinWidth.value,\n}))\n\nfunction columnHandleLabel(col: GrDataColumn<TRow>): string {\n return t('gr.dataTable.moveColumn', 'Move column {label}', { label: col.label })\n}\n\nfunction resizerLabel(col: GrDataColumn<TRow>): string {\n return t('gr.dataTable.resizeColumn', 'Width of column {label}', { label: col.label })\n}\n\n// ————— Ширина колонок.\n\n/** Уже колонки не бывает: в неё перестаёт помещаться даже стрелка сортировки. */\n\n/**\n * Живой регион существует с первого рендера и пуст, пока объявлять нечего.\n * Регион, который появляется уже с текстом, часть AT не объявляет вовсе —\n * а именно так вело себя `role=\"status\"` внутри строки загрузки.\n */\nconst liveMessage = computed(() => {\n if (props.loading)\n return resolvedLoadingText.value\n if (isEmpty.value)\n return resolvedEmptyText.value\n return ''\n})\n\n/**\n * В режиме сетки регион таблицы не рендерится, и объявлять состояние некому —\n * берёт на себя общий объявитель. Вне режима ничего не меняется: там регион на\n * месте, и второе объявление было бы дублем.\n */\nwatch(liveMessage, (next) => {\n if (props.cellNavigation && next)\n announce(next)\n})\n\nfunction cellValue(row: TRow, key: string): unknown {\n return (row as Record<string, unknown>)[key]\n}\n\nfunction rowClassName(row: TRow, index: number): string | undefined {\n const source = props.rowClass\n return typeof source === 'function' ? source(row, index) : source\n}\n\nfunction onRowClick(row: TRow, index: number, event: MouseEvent): void {\n emit('rowClick', { row, index, event })\n}\n\n// ————— Выбор строк.\n// Uncontrolled-режим, как у сортировки выше: без `v-model:selected` чекбоксы\n// рисовались, кликались и никогда не отмечались — состояние выбора целиком\n// выводилось из пропа, а внутреннего не было вовсе.\nconst {\n isRowSelectable,\n isRowSelected,\n selectableRows,\n allSelected,\n someSelected,\n toggleRow,\n toggleAll,\n} = useDataTableSelection<TRow>({\n rows: () => sortedRows.value,\n selected: () => props.selected,\n selectableRow: () => props.selectableRow,\n rowKeyValue,\n onSelectedChange: keys => emit('update:selected', keys),\n})\n\nconst expandDetailId = useId()\n\nconst {\n isRowExpandable,\n isRowExpanded,\n toggleRow: toggleRowExpanded,\n detailStateOf,\n detailDataOf,\n retryDetail,\n invalidateDetail,\n} = useDataTableExpansion<TRow>({\n expandedKeys: () => props.expandedKeys,\n rows: () => props.rows,\n expandableRow: () => props.expandableRow,\n loadDetail: () => props.loadDetail,\n accordion: () => props.accordion,\n rowKeyValue,\n onExpandedChange: keys => emit('update:expandedKeys', keys),\n onExpand: (row, key) => {\n emit('expand', { row, key })\n announce(t('gr.dataTable.detailExpanded', 'Row details shown'))\n },\n onCollapse: (row, key) => {\n emit('collapse', { row, key })\n announce(t('gr.dataTable.detailCollapsed', 'Row details hidden'))\n },\n onDetailLoadError: (row, key, error) => emit('detailLoadError', { row, key, error }),\n})\n\n/** Id строки подробностей: адресат `aria-controls` у кнопки. */\nfunction detailRowId(row: TRow): string {\n return `${expandDetailId}-${rowKeyValue(row)}`\n}\n\n// ————— Императивный API.\nconst tableRef = ref<InstanceType<typeof GrTable> | null>(null)\nconst rootId = useId()\n\nfunction rootEl(): HTMLElement | null {\n return (tableRef.value?.$el as HTMLElement | undefined) ?? null\n}\n\n/** Скролл-контейнер таблицы — он же элемент с `maxHeight`. */\nfunction scrollEl(): HTMLElement | null {\n const root = rootEl()\n return root?.matches('[data-gr-table-scroll]') ? root : root?.querySelector('[data-gr-table-scroll]') ?? null\n}\n\n/**\n * Виртуализация строк.\n *\n * Распорки здесь не псевдоэлементы, как у списочных компонентов: `<tbody>`\n * игнорирует `padding`, а псевдоэлемент внутри группы строк не образует строку\n * с управляемой высотой. Поэтому срезанное держат две служебные `<tr>` — той же\n * формы, что строки загрузки и пустоты у `GrTable`.\n */\nconst scrollContainer = ref<HTMLElement | null>(null)\n\nonMounted(() => {\n scrollContainer.value = scrollEl()\n})\n\nconst virtualizer = useVirtualList({\n container: scrollContainer,\n count: () => (props.virtual ? sortedRows.value.length : 0),\n // Сортировка и замена rows раздают индексы заново — замеры сбрасываются.\n source: () => sortedRows.value,\n itemSize: () => rowHeightEstimates[resolvedSize.value],\n // Скролл-контейнер живёт в `GrTable` и до монтирования недоступен: окно\n // первого рендера считается от объявленной высоты.\n viewportSize: () => (typeof props.maxHeight === 'number' ? props.maxHeight : undefined),\n})\n\n/** Строки к отрисовке вместе с их абсолютной позицией в наборе. */\nconst renderedRows = computed(() => {\n const rows = sortedRows.value\n if (!props.virtual)\n return rows.map((row, index) => ({ row, index }))\n\n const { start, end } = virtualizer.range.value\n return rows.slice(start, end).map((row, offset) => ({ row, index: start + offset }))\n})\n\n/**\n * Порядок ячеек в строке: раскрытие, выбор, колонки. Шапка и тело рисуют его\n * одинаково, поэтому индекс колонки в сетке считается один раз здесь.\n */\nconst serviceColumnCount = computed(() =>\n (expandColumnVisible.value ? 1 : 0) + (props.selectable ? 1 : 0),\n)\n\nconst expandColumnIndex = 0\nconst selectColumnIndex = computed(() => (expandColumnVisible.value ? 1 : 0))\nconst dataColumnIndex = (index: number): number => serviceColumnCount.value + index\n\n/** Узлы ячеек по ключу сетки. Заполняется `:ref` в разметке. */\nconst cellEls = new Map<string, HTMLElement>()\n\n/**\n * Индексы отрисованных строк. При виртуализации это окно, без неё — весь\n * набор: сетке нужно то, что действительно есть в разметке.\n */\nconst renderedRowIndexes = computed(() => renderedRows.value.map(item => item.index))\n\nconst grid = useDataTableGridNavigation({\n enabled: () => props.cellNavigation,\n columns: () => totalColumns.value,\n renderedRows: () => renderedRowIndexes.value,\n totalRows: () => sortedRows.value.length,\n cellEls,\n scrollToRow: props.virtual ? (index: number) => virtualizer.scrollToIndex(index) : undefined,\n})\n\nfunction registerCell(row: number, column: number, el: unknown): void {\n registerEl(cellEls, gridCellKey(row, column), el)\n}\n\n/**\n * Остановка `Tab` у контролов внутри ячеек.\n *\n * При навигации по ячейкам их в таб-порядке быть не должно: `Tab` принадлежит\n * сетке целиком, а до кнопки добираются стрелкой до ячейки и `Enter`. Иначе\n * остановок было бы столько же, сколько контролов, — то есть паттерн не\n * выполнялся бы вовсе.\n */\nconst cellControlTabindex = computed(() => (props.cellNavigation ? -1 : undefined))\n\nconst spacerBefore = computed(() => (props.virtual ? virtualizer.offset.value : 0))\nconst spacerAfter = computed(() => (props.virtual ? virtualizer.offsetEnd.value : 0))\n\n/** Ширина колонки: число трактуем как пиксели. */\nfunction columnWidthStyle(width: string | number | undefined): Record<string, string> | undefined {\n if (width === undefined)\n return undefined\n return { width: typeof width === 'number' ? `${width}px` : width }\n}\n\nfunction scrollToRow(key: string | number, options?: ScrollIntoViewOptions): boolean {\n // Ключ строки — произвольная строка от потребителя, в селектор её не подставить:\n // сравниваем через `dataset`, а не собираем `[data-row-key=\"…\"]` конкатенацией.\n const target = String(key)\n\n // Строки вне окна в DOM нет: без прокрутки виртуального списка поиск по\n // `dataset` вернул бы `undefined`, и метод молча отвечал бы «не нашёл».\n if (props.virtual) {\n const index = sortedRows.value.findIndex(row => String(rowKeyValue(row)) === target)\n if (index < 0)\n return false\n\n virtualizer.scrollToIndex(index)\n void nextTick(() => {\n // Вызов опциональный: отложенный `scrollIntoView` некому поймать, а в\n // среде без него (jsdom) это дало бы необработанный отказ промиса.\n findRowEl(target)?.scrollIntoView?.(options ?? { block: 'nearest' })\n })\n return true\n }\n\n const row = findRowEl(target)\n if (!row)\n return false\n\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\nfunction findRowEl(rowKey: string): HTMLElement | undefined {\n // Ключ строки — произвольная строка от потребителя, в селектор её не\n // подставить: сравниваем через `dataset`, а не собираем селектор конкатенацией.\n const rows = rootEl()?.querySelectorAll<HTMLElement>('[data-gr-datatable-row]') ?? []\n return Array.prototype.find.call(rows, (el: HTMLElement) => el.dataset.rowKey === rowKey) as HTMLElement | undefined\n}\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl()?.scrollTo(options)\n}\n\ndefineExpose({\n /** Прокрутить к строке по её ключу. `false` — строки нет в DOM. */\n scrollToRow,\n /** Прокрутить скролл-контейнер таблицы. */\n scrollTo,\n /** Снять сортировку (эквивалент третьего состояния). */\n clearSort,\n /** Отметить/снять все выбираемые строки. */\n toggleAll,\n /**\n * Сбросить загруженные подробности: у одной строки либо у всех.\n * Нужен, когда запись изменилась на сервере, — само по себе раскрытие\n * держит загруженное, пока строка жива.\n */\n invalidateDetail,\n})\n\n/**\n * Три семейства слотов по ключу колонки — `#cell-<key>` (`{ row, index }`),\n * `#header-<key>` (`{ column }`) и `#summary-<key>` (`{ value, column }`) —\n * попадают под общую индексную сигнатуру, а не под шаблонные.\n *\n * Шаблонные (`` `cell-${string}` ``) сужали бы тип слотов строже\n * `InternalSlots`, и дженерик-компонент переставал приниматься `h()`: ломался\n * бы рендер-функцией, оставаясь рабочим в шаблоне. Цена — пропсы этих трёх\n * семейств не типизированы; они описаны здесь и на странице компонента.\n */\ndefineSlots<{\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Содержимое, пока едут данные. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Подвал под таблицей: пагинация, счётчик, итоги во всю ширину. */\n footer?: (props: { columns: GrDataColumn<TRow>[], totalColumns: number }) => any\n [byColumn: string]: ((props?: any) => any) | undefined\n}>()\n</script>\n\n<template>\n <GrTable\n v-bind=\"tableProps\"\n ref=\"tableRef\"\n row-groups\n data-gr-datatable\n :role=\"cellNavigation ? 'grid' : 'table'\"\n @keydown=\"grid.onKeydown\"\n >\n <!-- Caption рендерится всегда (у `GrTable` он `sr-only`): в нём живёт\n постоянный live-регион, иначе объявлять загрузку было бы нечему. -->\n <template #caption>\n <slot name=\"caption\">\n {{ caption }}\n </slot>\n <!--\n В режиме сетки своего региона у таблицы нет: `role=\"grid\"` не допускает\n потомков, кроме строк и групп, — любой лишний узел внутри роняет\n `aria-required-children` как critical. Там загрузку и пустоту объявляет\n общий объявитель пакета (см. `watch` рядом с `liveMessage`).\n -->\n <span\n v-if=\"!cellNavigation\"\n :id=\"`${rootId}-live`\"\n data-gr-datatable-live\n role=\"status\"\n aria-live=\"polite\"\n >{{ liveMessage }}</span>\n </template>\n\n <template #header>\n <tr data-gr-datatable-header :aria-rowindex=\"virtual ? 1 : undefined\">\n <!-- Пустой заголовок служебной колонки: подписи у неё нет, но место\n занять обязана, иначе шапка съедет относительно тела. -->\n <th\n v-if=\"expandColumnVisible\"\n :ref=\"el => registerCell(HEADER_ROW_INDEX, expandColumnIndex, el)\"\n data-gr-datatable-expand-head\n scope=\"col\"\n :class=\"[expandColumnWidths[resolvedSize], cellClass]\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(HEADER_ROW_INDEX, expandColumnIndex) : undefined\"\n @focus=\"grid.setActive(HEADER_ROW_INDEX, expandColumnIndex)\"\n />\n <th\n v-if=\"selectable\"\n :ref=\"(el) => { registerEl(headerCellEls, SELECT_COLUMN_KEY, el); registerCell(HEADER_ROW_INDEX, selectColumnIndex, el) }\"\n class=\"text-left\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(HEADER_ROW_INDEX, selectColumnIndex) : undefined\"\n :class=\"[\n selectColumnClass,\n cellClass,\n hasPinnedLeft ? columnPinnedClass : '',\n ]\"\n :style=\"hasPinnedLeft ? { left: '0px' } : undefined\"\n scope=\"col\"\n @focus=\"grid.setActive(HEADER_ROW_INDEX, selectColumnIndex)\"\n >\n <GrCheckbox\n data-gr-datatable-select-all\n :tabindex=\"cellControlTabindex\"\n :model-value=\"allSelected\"\n :indeterminate=\"someSelected\"\n :size=\"checkboxSize\"\n :disabled=\"loading || selectableRows.length === 0\"\n :aria-label=\"t('gr.dataTable.selectAll', 'Select all rows')\"\n @update:model-value=\"toggleAll\"\n />\n </th>\n <th\n v-for=\"(col, colIndex) in orderedColumns\"\n :key=\"col.key\"\n :ref=\"(el) => { registerEl(headerCellEls, String(col.key), el); registerCell(HEADER_ROW_INDEX, dataColumnIndex(colIndex), el) }\"\n class=\"font-700\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(HEADER_ROW_INDEX, dataColumnIndex(colIndex)) : undefined\"\n :data-column-key=\"col.key\"\n :class=\"[\n headerTextClass,\n cellClass,\n cellAlign(col),\n reorderableColumns || resizableColumns || pinnableColumns ? 'group relative' : '',\n draggingColumnKey === String(col.key) ? columnDraggingClass : '',\n columnDropClass(colIndex),\n ...pinnedCellClass(col, colIndex),\n ]\"\n :style=\"{ ...columnWidthStyle(widthOf(col)), ...pinnedStyleOf(col) }\"\n :aria-sort=\"ariaSortFor(col)\"\n scope=\"col\"\n @focus=\"grid.setActive(HEADER_ROW_INDEX, dataColumnIndex(colIndex))\"\n >\n <div class=\"inline-flex items-center\" :class=\"headerGapClass\">\n <button\n v-if=\"reorderableColumns\"\n :ref=\"el => registerEl(columnHandleEls, String(col.key), el)\"\n type=\"button\"\n data-gr-datatable-column-handle\n :class=\"[columnHandleClass, columnSort.isActive.value ? columnHandleActiveClass : '']\"\n :tabindex=\"cellNavigation ? -1 : columnRoving.tabindexFor(String(col.key))\"\n :aria-label=\"columnHandleLabel(col)\"\n :disabled=\"loading\"\n @pointerdown=\"columnSort.startFrom(String(col.key))($event)\"\n @keydown=\"onColumnHandleKeydown($event, String(col.key))\"\n @focus=\"columnRoving.setActive(String(col.key))\"\n @click.stop\n >\n <IconGripVertical class=\"block\" aria-hidden=\"true\" />\n </button>\n <button\n v-if=\"col.sortable\"\n type=\"button\"\n data-gr-datatable-sort\n :tabindex=\"cellControlTabindex\"\n class=\"inline-flex items-center text-[var(--gr-muted-fg)] hover:text-[var(--gr-fg)] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)] rounded-[var(--gr-radius-sm)]\"\n :class=\"headerGapClass\"\n @click=\"toggleSort(col)\"\n >\n <span>\n <slot :name=\"`header-${col.key}`\" :column=\"col\">\n {{ col.label }}\n </slot>\n </span>\n <span class=\"sr-only\">{{ sortHint(col) }}</span>\n <span class=\"inline-flex\" aria-hidden=\"true\">\n <GrIcon v-if=\"currentSortKey === col.key && currentSortDir === 'asc'\" :size=\"sortIconSize\">\n <IconArrowUp />\n </GrIcon>\n <GrIcon v-else-if=\"currentSortKey === col.key && currentSortDir === 'desc'\" :size=\"sortIconSize\">\n <IconArrowDown />\n </GrIcon>\n </span>\n </button>\n <span v-else class=\"text-[var(--gr-muted-fg)]\">\n <slot :name=\"`header-${col.key}`\" :column=\"col\">\n {{ col.label }}\n </slot>\n </span>\n </div>\n\n <GrDropdownMenu\n v-if=\"pinnableColumns\"\n data-gr-datatable-column-menu\n :items=\"columnMenuItems(col)\"\n placement=\"bottom-end\"\n :width=\"COLUMN_MENU_WIDTH\"\n :aria-label=\"columnMenuLabel(col)\"\n @select=\"onColumnMenuSelect(col, $event)\"\n >\n <template #trigger=\"{ triggerProps }\">\n <button\n v-bind=\"triggerProps\"\n type=\"button\"\n data-gr-datatable-column-menu-trigger\n :tabindex=\"cellControlTabindex\"\n :class=\"columnMenuTriggerClass\"\n :aria-label=\"columnMenuLabel(col)\"\n :disabled=\"loading\"\n @click.stop\n >\n <IconEllipsisVertical class=\"block\" aria-hidden=\"true\" />\n </button>\n </template>\n </GrDropdownMenu>\n\n <span\n v-if=\"resizableColumns\"\n data-gr-datatable-column-resizer\n role=\"separator\"\n :tabindex=\"cellNavigation ? -1 : 0\"\n aria-orientation=\"vertical\"\n :class=\"columnResizerClass\"\n :aria-label=\"resizerLabel(col)\"\n :aria-valuenow=\"resizerValue(col)\"\n :aria-valuemin=\"MIN_COLUMN_WIDTH\"\n :aria-valuetext=\"`${resizerValue(col)}px`\"\n @pointerdown=\"onResizerPointerDown($event, String(col.key))\"\n @keydown=\"onResizerKeydown($event, String(col.key))\"\n @dblclick=\"resetColumnWidth(String(col.key))\"\n @click.stop\n >\n <span\n :class=\"[\n columnResizerLineClass,\n columnResizerHoverClass,\n resizingKey === String(col.key) ? columnResizerLineActiveClass : '',\n ]\"\n aria-hidden=\"true\"\n />\n </span>\n </th>\n </tr>\n </template>\n\n <tbody v-if=\"loading\">\n <tr data-gr-datatable-loading>\n <td :colspan=\"totalColumns\" class=\"text-center text-[var(--gr-muted-fg)]\" :class=\"placeholderClass\">\n <slot name=\"loading\">\n <span class=\"inline-flex items-center gap-2\">\n <IconLoaderCircle class=\"block animate-spin\" :class=\"spinnerClass\" aria-hidden=\"true\" />\n <span>{{ resolvedLoadingText }}</span>\n </span>\n </slot>\n </td>\n </tr>\n </tbody>\n\n <tbody v-else-if=\"isEmpty\">\n <tr data-gr-datatable-empty>\n <td :colspan=\"totalColumns\" class=\"text-center text-[var(--gr-muted-fg)]\" :class=\"placeholderClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n </tbody>\n\n <template v-else>\n <!--\n Распорки виртуального списка. У таблицы они строки, а не псевдоэлементы:\n `<tbody>` игнорирует `padding`, а псевдоэлемент внутри группы строк не\n образует строку с управляемой высотой. Форма та же, что у служебных\n строк загрузки и пустоты, а группа вокруг — потому что тело собрано\n группами: строка вне группы не встала бы в таблицу вовсе.\n -->\n <tbody v-if=\"virtual && spacerBefore > 0\" data-gr-table-off-grid>\n <tr\n aria-hidden=\"true\"\n data-gr-datatable-spacer=\"before\"\n data-gr-table-off-grid\n :style=\"{ pointerEvents: 'none' }\"\n >\n <td :colspan=\"totalColumns\" :style=\"{ height: `${spacerBefore}px`, padding: '0', border: '0' }\" />\n </tr>\n </tbody>\n\n <!--\n Строка и её второй ярус лежат в одной группе, и замер виртуализатора\n висит на группе, а не на строке: иначе высота подробностей в него не\n попадает и распорка разъезжается молча. `ResizeObserver` примитива при\n этом следит за той же группой, поэтому раскрытие и подгрузка деталей\n уточняют высоту сами, без отдельного уведомления.\n -->\n <tbody\n v-for=\"{ row, index } in renderedRows\"\n :key=\"rowKeyValue(row)\"\n :ref=\"(el) => virtual && virtualizer.measure(index, el as Element | null)\"\n data-gr-datatable-row-group\n >\n <tr\n class=\"border-t border-[var(--gr-brd)]\"\n :class=\"[\n isRowSelected(row) ? rowSelectedClass : '',\n rowClassName(row, index),\n ]\"\n data-gr-datatable-row\n :data-row-key=\"rowKeyValue(row)\"\n :data-selected=\"selectable && isRowSelected(row) ? 'true' : undefined\"\n :aria-rowindex=\"ariaRowIndex(index)\"\n v-bind=\"rowProps?.(row, index)\"\n @click=\"onRowClick(row, index, $event)\"\n >\n <td\n v-if=\"expandColumnVisible\"\n :ref=\"el => registerCell(index, expandColumnIndex, el)\"\n data-gr-datatable-expand-cell\n class=\"text-left\"\n :class=\"[expandColumnWidths[resolvedSize], cellClass]\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(index, expandColumnIndex) : undefined\"\n @focus=\"grid.setActive(index, expandColumnIndex)\"\n >\n <!-- `.stop` на кнопке, а не на ячейке: гасить навигационный клик есть\n смысл только там, где стоит контрол. Иначе ячейка строки без\n второго яруса становится мёртвой зоной. -->\n <button\n v-if=\"isRowExpandable(row)\"\n type=\"button\"\n data-gr-datatable-expand\n :tabindex=\"cellControlTabindex\"\n :class=\"[expandButtonClass, checkboxSize === 'xs' ? 'h-5 w-5' : 'h-6 w-6']\"\n :aria-expanded=\"isRowExpanded(row)\"\n :aria-controls=\"detailRowId(row)\"\n :aria-label=\"isRowExpanded(row)\n ? t('gr.dataTable.collapseRow', 'Hide details')\n : t('gr.dataTable.expandRow', 'Show details')\"\n @click.stop=\"toggleRowExpanded(row)\"\n >\n <slot name=\"expand-icon\" :expanded=\"isRowExpanded(row)\" :row=\"row\">\n <IconChevronRight :class=\"[expandIconClass, isRowExpanded(row) ? expandIconOpenClass : '']\" />\n </slot>\n </button>\n </td>\n\n <td\n v-if=\"selectable\"\n :ref=\"el => registerCell(index, selectColumnIndex, el)\"\n class=\"text-left\"\n :class=\"[\n selectColumnClass,\n cellClass,\n hasPinnedLeft ? columnPinnedClass : '',\n hasPinnedLeft && isRowSelected(row) ? rowSelectedClass : '',\n ]\"\n :style=\"hasPinnedLeft ? { left: '0px' } : undefined\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(index, selectColumnIndex) : undefined\"\n @focus=\"grid.setActive(index, selectColumnIndex)\"\n >\n <!-- `.stop` на самом чекбоксе, а не на ячейке: гасить навигационный\n клик есть смысл только там, где стоит контрол выбора. Иначе\n служебная ячейка невыбираемой строки становится мёртвой зоной. -->\n <GrCheckbox\n v-if=\"isRowSelectable(row)\"\n data-gr-datatable-select-row\n :tabindex=\"cellControlTabindex\"\n :model-value=\"isRowSelected(row)\"\n :size=\"checkboxSize\"\n :aria-label=\"t('gr.dataTable.selectRow', 'Select row')\"\n @click.stop\n @update:model-value=\"toggleRow(row)\"\n />\n </td>\n <td\n v-for=\"(col, colIndex) in orderedColumns\"\n :key=\"col.key\"\n :ref=\"el => registerCell(index, dataColumnIndex(colIndex), el)\"\n :class=\"[\n cellClass,\n cellAlign(col),\n ...pinnedCellClass(col, colIndex),\n col.pinned && isRowSelected(row) ? rowSelectedClass : '',\n ]\"\n :style=\"{ ...columnWidthStyle(widthOf(col)), ...pinnedStyleOf(col) }\"\n :tabindex=\"cellNavigation ? grid.tabindexFor(index, dataColumnIndex(colIndex)) : undefined\"\n @focus=\"grid.setActive(index, dataColumnIndex(colIndex))\"\n >\n <slot\n :name=\"`cell-${col.key}`\"\n :row=\"row\"\n :index=\"index\"\n :expanded=\"isRowExpanded(row)\"\n :toggle-expand=\"() => toggleRowExpanded(row)\"\n >\n <span>{{ cellValue(row, col.key) }}</span>\n </slot>\n </td>\n </tr>\n\n <!--\n Второй ярус идёт отдельной `<tr>` следом за своей строкой.\n `data-gr-table-off-grid` снимает с неё полосатость и подсветку и\n выключает её из счёта чётности соседей: она не строка набора.\n `aria-rowindex` ей тоже не положен по той же причине.\n -->\n <tr\n v-if=\"isRowExpanded(row)\"\n :id=\"detailRowId(row)\"\n data-gr-datatable-detail\n data-gr-table-off-grid\n :class=\"detailRowClass\"\n >\n <td :colspan=\"totalColumns\" :class=\"[detailCellClass, detailPaddings[resolvedSize]]\">\n <div :class=\"detailContentClass\">\n <div v-if=\"detailStateOf(row) === 'loading'\" data-gr-datatable-detail-loading>\n <slot name=\"detail-loading\" :row=\"row\">\n <GrSkeleton :count=\"2\" />\n </slot>\n </div>\n\n <div v-else-if=\"detailStateOf(row) === 'error'\" :class=\"detailErrorClass\" data-gr-datatable-detail-error>\n <slot name=\"detail-error\" :row=\"row\" :retry=\"() => retryDetail(row)\">\n <span>{{ t('gr.dataTable.detailError', 'Could not load details') }}</span>\n <GrButton size=\"xs\" tone=\"danger\" variant=\"outline\" @click=\"retryDetail(row)\">\n {{ t('gr.dataTable.detailRetry', 'Retry') }}\n </GrButton>\n </slot>\n </div>\n\n <slot\n v-else\n name=\"detail\"\n :row=\"row\"\n :index=\"index\"\n :data=\"detailDataOf(row)\"\n :state=\"detailStateOf(row)\"\n />\n </div>\n </td>\n </tr>\n </tbody>\n\n <tbody v-if=\"virtual && spacerAfter > 0\" data-gr-table-off-grid>\n <tr\n aria-hidden=\"true\"\n data-gr-datatable-spacer=\"after\"\n data-gr-table-off-grid\n :style=\"{ pointerEvents: 'none' }\"\n >\n <td :colspan=\"totalColumns\" :style=\"{ height: `${spacerAfter}px`, padding: '0', border: '0' }\" />\n </tr>\n </tbody>\n </template>\n\n <template v-if=\"$slots.footer || hasSummary\" #footer>\n <!--\n Итог зеркалит ячейку тела теми же функциями, а не своими классами: у\n `GrTable` ячейки `<tfoot>` не оформлены принципиально, и собранная руками\n строка разъезжается с телом на первой же смене `size`. Индекс колонки\n обязателен — по нему `pinnedEdgeClass` находит край группы.\n -->\n <tr\n v-if=\"hasSummary\"\n data-gr-datatable-summary\n :class=\"summaryRowClass\"\n :aria-rowindex=\"summaryAriaRowIndex\"\n >\n <td\n v-if=\"selectable\"\n :class=\"[\n selectColumnClass,\n cellClass,\n hasPinnedLeft ? columnPinnedClass : '',\n ]\"\n :style=\"hasPinnedLeft ? { left: '0px' } : undefined\"\n />\n <td\n v-for=\"(col, colIndex) in orderedColumns\"\n :key=\"col.key\"\n :data-column-key=\"col.key\"\n :class=\"[cellClass, cellAlign(col), ...pinnedCellClass(col, colIndex)]\"\n :style=\"{ ...columnWidthStyle(widthOf(col)), ...pinnedStyleOf(col) }\"\n >\n <slot :name=\"`summary-${col.key}`\" :value=\"summaryValue(col.key)\" :column=\"col\">\n <span>{{ summaryValue(col.key) }}</span>\n </slot>\n </td>\n </tr>\n\n <slot name=\"footer\" :columns=\"orderedColumns\" :total-columns=\"totalColumns\" />\n </template>\n </GrTable>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrDataTable_default } from "./chunks/GrDataTable-DQxYYgQk.js";
2
- import { n as grDataTableSafelist, t as grDataTableConfig } from "../../chunks/config-Bs1HwUcx.js";
1
+ import { t as GrDataTable_default } from "./chunks/GrDataTable-Bb2jWnRG.js";
2
+ import { n as grDataTableSafelist, t as grDataTableConfig } from "../../chunks/config-DPJ3jtiB.js";
3
3
  export { GrDataTable_default as GrDataTable, GrDataTable_default as default, grDataTableConfig, grDataTableSafelist };