@feugene/granularity 0.45.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +3 -3
  2. package/dist/chunks/{x-circle-BCBURwyX.js → check-circle-Bnrb-CGJ.js} +8 -32
  3. package/dist/chunks/check-circle-Bnrb-CGJ.js.map +1 -0
  4. package/dist/chunks/{config-BqT6PMzO.js → config-B42iJ48O.js} +5 -1
  5. package/dist/chunks/{config-BqT6PMzO.js.map → config-B42iJ48O.js.map} +1 -1
  6. package/dist/chunks/{config-BGCyyXiD.js → config-BAse0laT.js} +5 -1
  7. package/dist/chunks/{config-BGCyyXiD.js.map → config-BAse0laT.js.map} +1 -1
  8. package/dist/chunks/{config-MmPym-Z7.js → config-BLP94dPY.js} +5 -1
  9. package/dist/chunks/{config-MmPym-Z7.js.map → config-BLP94dPY.js.map} +1 -1
  10. package/dist/chunks/{config-CjKpUcmy.js → config-Bdf1bt-m.js} +25 -16
  11. package/dist/chunks/config-Bdf1bt-m.js.map +1 -0
  12. package/dist/chunks/{config-CIkdsWUk.js → config-CIUU9ZpY.js} +4 -1
  13. package/dist/chunks/config-CIUU9ZpY.js.map +1 -0
  14. package/dist/chunks/{config-BhfNgyWL.js → config-DENqOoh0.js} +5 -1
  15. package/dist/chunks/config-DENqOoh0.js.map +1 -0
  16. package/dist/chunks/{config-ChnYtO4o.js → config-bjDf8nBf.js} +16 -1
  17. package/dist/chunks/config-bjDf8nBf.js.map +1 -0
  18. package/dist/chunks/controlState-DoImKciE.js +35 -0
  19. package/dist/chunks/controlState-DoImKciE.js.map +1 -0
  20. package/dist/chunks/{en-DiHzFact.js → en-DjTnfTqM.js} +3 -1
  21. package/dist/chunks/en-DjTnfTqM.js.map +1 -0
  22. package/dist/chunks/{es-1ZL6NtkB.js → es-Bc_t3FI8.js} +3 -1
  23. package/dist/chunks/es-Bc_t3FI8.js.map +1 -0
  24. package/dist/chunks/{es-CeKkMxZ_.js → es-DIFzSXSZ.js} +3 -3
  25. package/dist/chunks/{es-CeKkMxZ_.js.map → es-DIFzSXSZ.js.map} +1 -1
  26. package/dist/chunks/{generated-DAKeOOqm.js → generated-CQ4h6Ieq.js} +28 -0
  27. package/dist/chunks/{generated-DAKeOOqm.js.map → generated-CQ4h6Ieq.js.map} +1 -1
  28. package/dist/chunks/{granular-provider-D_8_l-gM.js → granular-provider-AKukmYva.js} +7 -7
  29. package/dist/chunks/{granular-provider-D_8_l-gM.js.map → granular-provider-AKukmYva.js.map} +1 -1
  30. package/dist/chunks/{ru-Dr2RYn0P.js → ru-Bb-co59W.js} +3 -1
  31. package/dist/chunks/ru-Bb-co59W.js.map +1 -0
  32. package/dist/chunks/x-circle-BigSZy8m.js +26 -0
  33. package/dist/chunks/x-circle-BigSZy8m.js.map +1 -0
  34. package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js → GrAlert-CfEZghSY.js} +2 -1
  35. package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js.map → GrAlert-CfEZghSY.js.map} +1 -1
  36. package/dist/components/GrAlert/index.js +1 -1
  37. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-D396_JrW.js → GrAutocomplete-C-uovdv8.js} +320 -224
  38. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-C-uovdv8.js.map +1 -0
  39. package/dist/components/GrAutocomplete/index.js +1 -1
  40. package/dist/components/GrAutocomplete/styles.css +1 -1
  41. package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js → GrColorPicker-BRM_4lyI.js} +1 -1
  42. package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js.map → GrColorPicker-BRM_4lyI.js.map} +1 -1
  43. package/dist/components/GrColorPicker/index.js +1 -1
  44. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js.map → GrCommandPalette-BJHmkDQv.js.map} +1 -1
  45. package/dist/components/GrCommandPalette/index.js +1 -1
  46. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js → GrConfirmDialog-BzUQwbec.js} +1 -1
  47. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js.map → GrConfirmDialog-BzUQwbec.js.map} +1 -1
  48. package/dist/components/GrConfirmDialog/index.js +1 -1
  49. package/dist/components/GrDataTable/chunks/{GrDataTable-xNSmO_I-.js → GrDataTable-Dp9Fp_P5.js} +606 -499
  50. package/dist/components/GrDataTable/chunks/GrDataTable-Dp9Fp_P5.js.map +1 -0
  51. package/dist/components/GrDataTable/index.js +1 -1
  52. package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js → GrDialogService-Dtq0ZCN5.js} +3 -3
  53. package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js.map → GrDialogService-Dtq0ZCN5.js.map} +1 -1
  54. package/dist/components/GrDialogService/index.js +1 -1
  55. package/dist/components/GrFormField/chunks/GrFormField-DO61vxpS.js.map +1 -1
  56. package/dist/components/GrInput/chunks/{GrInput-TFeBm3gQ.js → GrInput-DV4gMWPR.js} +40 -11
  57. package/dist/components/GrInput/chunks/GrInput-DV4gMWPR.js.map +1 -0
  58. package/dist/components/GrInput/index.js +2 -2
  59. package/dist/components/GrInputTag/chunks/{GrInputTag-Ci8AO1ze.js → GrInputTag-CO0YU-ok.js} +30 -6
  60. package/dist/components/GrInputTag/chunks/GrInputTag-CO0YU-ok.js.map +1 -0
  61. package/dist/components/GrInputTag/index.js +2 -2
  62. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CdlWMGnF.js → GrJsonViewer-D7CyWzhT.js} +2 -2
  63. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CdlWMGnF.js.map → GrJsonViewer-D7CyWzhT.js.map} +1 -1
  64. package/dist/components/GrJsonViewer/index.js +1 -1
  65. package/dist/components/GrNumberInput/chunks/{GrNumberInput-CL5QhOmx.js → GrNumberInput-BI6-vkcs.js} +48 -16
  66. package/dist/components/GrNumberInput/chunks/GrNumberInput-BI6-vkcs.js.map +1 -0
  67. package/dist/components/GrNumberInput/index.js +2 -2
  68. package/dist/components/GrPagination/chunks/{GrPagination-DhbNZHEF.js → GrPagination-BbaF5eXk.js} +10 -7
  69. package/dist/components/GrPagination/chunks/GrPagination-BbaF5eXk.js.map +1 -0
  70. package/dist/components/GrPagination/index.js +2 -2
  71. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js → GrPromptDialog-BEL-QgwE.js} +3 -3
  72. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js.map → GrPromptDialog-BEL-QgwE.js.map} +1 -1
  73. package/dist/components/GrPromptDialog/index.js +1 -1
  74. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js → GrResponseErrorBanner-Bdd5c07x.js} +1 -1
  75. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js.map → GrResponseErrorBanner-Bdd5c07x.js.map} +1 -1
  76. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js → GrResponseErrorBanner-DySe1ym4.js} +1 -1
  77. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js.map → GrResponseErrorBanner-DySe1ym4.js.map} +1 -1
  78. package/dist/components/GrResponseErrorBanner/index.js +2 -2
  79. package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js → GrSelect-0iI4wdR_.js} +3 -3
  80. package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js.map → GrSelect-0iI4wdR_.js.map} +1 -1
  81. package/dist/components/GrSelect/index.js +1 -1
  82. package/dist/components/GrTextarea/chunks/{GrTextarea-BII3w61K.js → GrTextarea-Bfgc0DD2.js} +73 -32
  83. package/dist/components/GrTextarea/chunks/GrTextarea-Bfgc0DD2.js.map +1 -0
  84. package/dist/components/GrTextarea/index.js +2 -2
  85. package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js → GrToaster-CZixNk0l.js} +2 -1
  86. package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js.map → GrToaster-CZixNk0l.js.map} +1 -1
  87. package/dist/components/GrToaster/index.js +1 -1
  88. package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js → GrTransfer-DdfBUf35.js} +2 -2
  89. package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js.map → GrTransfer-DdfBUf35.js.map} +1 -1
  90. package/dist/components/GrTransfer/index.js +1 -1
  91. package/dist/components/GrTree/chunks/{GrTree-DnDGW0xO.js → GrTree-6yZrncJE.js} +52 -18
  92. package/dist/components/GrTree/chunks/GrTree-6yZrncJE.js.map +1 -0
  93. package/dist/components/GrTree/index.js +1 -1
  94. package/dist/components/GrTree/styles.css +1 -1
  95. package/dist/components/GrTreeSections/chunks/{GrTreeSections-D2PQ87mw.js → GrTreeSections-DcmDcLwj.js} +5 -3
  96. package/dist/components/GrTreeSections/chunks/GrTreeSections-DcmDcLwj.js.map +1 -0
  97. package/dist/components/GrTreeSections/index.js +2 -2
  98. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DzheDCuZ.js → GrTreeSelect-B6KoDYiZ.js} +44 -19
  99. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-B6KoDYiZ.js.map +1 -0
  100. package/dist/components/GrTreeSelect/index.js +2 -2
  101. package/dist/granular-provider-node.js +1 -1
  102. package/dist/granular-provider.js +1 -1
  103. package/dist/i18n/all.js +1 -1
  104. package/dist/i18n/index.js +1 -1
  105. package/dist/index.js +30 -30
  106. package/dist/theme.js +1 -1
  107. package/dist/tokens.js +1 -1
  108. package/dist/types/components/GrAutocomplete/composables/useAutocompleteNavigation.d.ts +39 -0
  109. package/dist/types/components/GrAutocomplete/composables/useAutocompletePanel.d.ts +36 -0
  110. package/dist/types/components/GrAutocomplete/composables/useAutocompleteValues.d.ts +28 -0
  111. package/dist/types/components/GrAutocomplete/composables/useAutocompleteVirtual.d.ts +33 -0
  112. package/dist/types/components/GrAutocomplete/composables/useRemoteOptions.d.ts +33 -0
  113. package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +1 -1
  114. package/dist/types/components/GrDataTable/composables/useDataTableColumnOrder.d.ts +45 -0
  115. package/dist/types/components/GrDataTable/composables/useDataTableColumnWidths.d.ts +38 -0
  116. package/dist/types/components/GrDataTable/composables/useDataTableLayout.d.ts +29 -0
  117. package/dist/types/components/GrDataTable/composables/useDataTableRowKeys.d.ts +16 -0
  118. package/dist/types/components/GrDataTable/composables/useDataTableSelection.d.ts +32 -0
  119. package/dist/types/components/GrDataTable/composables/useDataTableSort.d.ts +37 -0
  120. package/dist/types/components/GrFormField/GrFormField.vue.d.ts +7 -1
  121. package/dist/types/components/GrPagination/GrPagination.vue.d.ts +17 -2
  122. package/dist/types/components/GrPagination/grPaginationStyles.d.ts +15 -6
  123. package/dist/types/components/GrPagination/index.d.ts +1 -1
  124. package/dist/types/components/GrTree/grTreeStyles.d.ts +1 -1
  125. package/dist/types/components/GrTreeSections/grTreeSectionsStyles.d.ts +15 -0
  126. package/dist/types/components/shared/controlState.d.ts +36 -0
  127. package/dist/types/i18n/messages/en.d.ts +4 -0
  128. package/dist/types/i18n/messages/es.d.ts +4 -0
  129. package/dist/types/i18n/messages/ru.d.ts +4 -0
  130. package/dist/web-types.json +4 -3
  131. package/package.json +1 -1
  132. package/dist/chunks/config-BhfNgyWL.js.map +0 -1
  133. package/dist/chunks/config-CIkdsWUk.js.map +0 -1
  134. package/dist/chunks/config-ChnYtO4o.js.map +0 -1
  135. package/dist/chunks/config-CjKpUcmy.js.map +0 -1
  136. package/dist/chunks/en-DiHzFact.js.map +0 -1
  137. package/dist/chunks/es-1ZL6NtkB.js.map +0 -1
  138. package/dist/chunks/ru-Dr2RYn0P.js.map +0 -1
  139. package/dist/chunks/x-circle-BCBURwyX.js.map +0 -1
  140. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-D396_JrW.js.map +0 -1
  141. package/dist/components/GrDataTable/chunks/GrDataTable-xNSmO_I-.js.map +0 -1
  142. package/dist/components/GrInput/chunks/GrInput-TFeBm3gQ.js.map +0 -1
  143. package/dist/components/GrInputTag/chunks/GrInputTag-Ci8AO1ze.js.map +0 -1
  144. package/dist/components/GrNumberInput/chunks/GrNumberInput-CL5QhOmx.js.map +0 -1
  145. package/dist/components/GrPagination/chunks/GrPagination-DhbNZHEF.js.map +0 -1
  146. package/dist/components/GrTextarea/chunks/GrTextarea-BII3w61K.js.map +0 -1
  147. package/dist/components/GrTree/chunks/GrTree-DnDGW0xO.js.map +0 -1
  148. package/dist/components/GrTreeSections/chunks/GrTreeSections-D2PQ87mw.js.map +0 -1
  149. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-DzheDCuZ.js.map +0 -1
  150. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js → GrCommandPalette-BJHmkDQv.js} +1 -1
@@ -14,6 +14,34 @@ import { C as sortIconSizes, S as selectColumnWidths, T as summaryRowClass, _ as
14
14
  import { t as arrow_up_default } from "../../../chunks/arrow-up-C_G4jg8M.js";
15
15
  import { t as grip_vertical_default } from "../../../chunks/grip-vertical-lRha2S7q.js";
16
16
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, markRaw, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, watch, watchEffect, withCtx, withModifiers } from "vue";
17
+ //#region src/components/GrDataTable/composables/useDataTableRowKeys.ts
18
+ function useDataTableRowKeys(options) {
19
+ const syntheticKeys = /* @__PURE__ */ new WeakMap();
20
+ let syntheticKeyCounter = 0;
21
+ let missingKeyWarned = false;
22
+ function syntheticRowKey(row) {
23
+ const existing = syntheticKeys.get(row);
24
+ if (existing !== void 0) return existing;
25
+ syntheticKeyCounter += 1;
26
+ const generated = `gr-row-${syntheticKeyCounter}`;
27
+ syntheticKeys.set(row, generated);
28
+ if (!missingKeyWarned && process.env.NODE_ENV !== "production") {
29
+ missingKeyWarned = true;
30
+ console.warn(`[GrDataTable] У строки нет значения по ключу "${String(options.rowKey())}". Задайте \`rowKey\` (поле или функцию) — иначе выбор строк и переиспользование DOM работают по синтетическому ключу, который не переживёт перезагрузку данных.`);
31
+ }
32
+ return generated;
33
+ }
34
+ function rowKeyValue(row) {
35
+ const rk = options.rowKey();
36
+ if (typeof rk === "function") return rk(row);
37
+ const value = row[rk];
38
+ if (typeof value === "string" && value !== "") return value;
39
+ if (typeof value === "number") return value;
40
+ return syntheticRowKey(row);
41
+ }
42
+ return { rowKeyValue };
43
+ }
44
+ //#endregion
17
45
  //#region src/components/GrDataTable/grDataTableSort.ts
18
46
  /** Пустое значение ячейки: нечего сравнивать, место таким — в конце списка. */
19
47
  function isEmptyCell(value) {
@@ -66,6 +94,448 @@ function sortRows(rows, key, dir, locale) {
66
94
  return [...rows].sort((a, b) => compareCells(a[key], b[key], dir, locale));
67
95
  }
68
96
  //#endregion
97
+ //#region src/components/GrDataTable/composables/useDataTableSort.ts
98
+ function useDataTableSort(options) {
99
+ const internalSortKey = ref(options.initialSortKey() ?? "");
100
+ const internalSortDir = ref(options.initialSortDir());
101
+ const isSortKeyControlled = computed(() => options.sortKey() !== void 0);
102
+ const isSortDirControlled = computed(() => options.sortDir() !== void 0);
103
+ const currentSortKey = computed(() => options.sortKey() ?? internalSortKey.value);
104
+ const currentSortDir = computed(() => options.sortDir() ?? internalSortDir.value);
105
+ function applySort(key, dir) {
106
+ if (!isSortKeyControlled.value) internalSortKey.value = key;
107
+ if (!isSortDirControlled.value) internalSortDir.value = dir;
108
+ options.onSortChange(key, dir);
109
+ }
110
+ const sortedRows = computed(() => {
111
+ if (options.externalSort()) return [...options.rows()];
112
+ const key = currentSortKey.value;
113
+ if (!key) return [...options.rows()];
114
+ return sortRows(options.rows(), key, currentSortDir.value, options.locale());
115
+ });
116
+ function toggleSort(col) {
117
+ if (!col.sortable) return;
118
+ if (currentSortKey.value !== col.key) {
119
+ applySort(col.key, "asc");
120
+ return;
121
+ }
122
+ if (currentSortDir.value === "asc") {
123
+ applySort(col.key, "desc");
124
+ return;
125
+ }
126
+ if (options.sortCycle() === "asc-desc-none") {
127
+ applySort("", "asc");
128
+ return;
129
+ }
130
+ applySort(col.key, "asc");
131
+ }
132
+ function clearSort() {
133
+ applySort("", "asc");
134
+ }
135
+ function ariaSortFor(col) {
136
+ if (!col.sortable) return void 0;
137
+ if (currentSortKey.value !== col.key) return "none";
138
+ return currentSortDir.value === "asc" ? "ascending" : "descending";
139
+ }
140
+ return {
141
+ currentSortKey,
142
+ currentSortDir,
143
+ sortedRows,
144
+ toggleSort,
145
+ clearSort,
146
+ ariaSortFor
147
+ };
148
+ }
149
+ //#endregion
150
+ //#region src/components/GrDataTable/composables/useDataTableSelection.ts
151
+ function useDataTableSelection(options) {
152
+ const internalSelected = ref([]);
153
+ const isSelectedControlled = computed(() => options.selected() !== void 0);
154
+ const selectedKeys = computed(() => new Set(options.selected() ?? internalSelected.value));
155
+ function isRowSelectable(row) {
156
+ const predicate = options.selectableRow();
157
+ return predicate ? predicate(row) : true;
158
+ }
159
+ function isRowSelected(row) {
160
+ return selectedKeys.value.has(options.rowKeyValue(row));
161
+ }
162
+ /** «Выбрать все» работает по видимым и выбираемым строкам — они же считают состояние шапки. */
163
+ const selectableRows = computed(() => options.rows().filter(isRowSelectable));
164
+ const allSelected = computed(() => selectableRows.value.length > 0 && selectableRows.value.every(isRowSelected));
165
+ const someSelected = computed(() => selectableRows.value.some(isRowSelected) && !allSelected.value);
166
+ function emitSelected(next) {
167
+ if (!isSelectedControlled.value) internalSelected.value = [...next];
168
+ options.onSelectedChange([...next]);
169
+ }
170
+ function toggleRow(row) {
171
+ if (!isRowSelectable(row)) return;
172
+ const key = options.rowKeyValue(row);
173
+ const next = new Set(selectedKeys.value);
174
+ if (next.has(key)) next.delete(key);
175
+ else next.add(key);
176
+ emitSelected(next);
177
+ }
178
+ function toggleAll() {
179
+ const next = new Set(selectedKeys.value);
180
+ if (allSelected.value) {
181
+ for (const row of selectableRows.value) next.delete(options.rowKeyValue(row));
182
+ emitSelected(next);
183
+ return;
184
+ }
185
+ for (const row of selectableRows.value) next.add(options.rowKeyValue(row));
186
+ emitSelected(next);
187
+ }
188
+ return {
189
+ selectedKeys,
190
+ isRowSelectable,
191
+ isRowSelected,
192
+ selectableRows,
193
+ allSelected,
194
+ someSelected,
195
+ toggleRow,
196
+ toggleAll
197
+ };
198
+ }
199
+ //#endregion
200
+ //#region src/components/GrDataTable/composables/useDataTableColumnOrder.ts
201
+ function useDataTableColumnOrder(options) {
202
+ /** Uncontrolled-состояние; в controlled-режиме перекрывается пропом `columnOrder`. */
203
+ const internalColumnOrder = ref(options.columns().map((col) => String(col.key)));
204
+ /**
205
+ * Колонки в пользовательском порядке.
206
+ *
207
+ * Состав задаёт `columns`, порядок — только порядок: ключ, которого в наборе
208
+ * нет, игнорируется, а колонка, которой нет в порядке (её только что
209
+ * добавили), встаёт в конец. Иначе правка `columns` теряла бы колонки молча.
210
+ */
211
+ const orderedColumns = computed(() => {
212
+ const order = options.columnOrder() ?? internalColumnOrder.value;
213
+ const remaining = new Map(options.columns().map((col) => [String(col.key), col]));
214
+ const ordered = [];
215
+ for (const key of order) {
216
+ const col = remaining.get(key);
217
+ if (!col) continue;
218
+ remaining.delete(key);
219
+ ordered.push(col);
220
+ }
221
+ for (const col of options.columns()) if (remaining.has(String(col.key))) ordered.push(col);
222
+ return ordered.sort((a, b) => pinGroupOf(a) - pinGroupOf(b));
223
+ });
224
+ /** Группа закрепления: 0 — слева, 1 — обычная колонка, 2 — справа. */
225
+ function pinGroupOf(col) {
226
+ if (col.pinned === "left") return 0;
227
+ if (col.pinned === "right") return 2;
228
+ return 1;
229
+ }
230
+ const columnKeys = computed(() => orderedColumns.value.map((col) => String(col.key)));
231
+ function indexOfColumn(key) {
232
+ return columnKeys.value.indexOf(key);
233
+ }
234
+ function sameGroup(from, to) {
235
+ const cols = orderedColumns.value;
236
+ if (!cols[from] || !cols[to]) return false;
237
+ return pinGroupOf(cols[from]) === pinGroupOf(cols[to]);
238
+ }
239
+ function applyColumnMove(from, to) {
240
+ const keys = columnKeys.value;
241
+ if (from < 0 || to < 0 || to >= keys.length || from === to) return;
242
+ if (!sameGroup(from, to)) return;
243
+ const key = keys[from];
244
+ const label = orderedColumns.value[from]?.label ?? key;
245
+ const next = moveItem(keys, from, to);
246
+ internalColumnOrder.value = next;
247
+ options.onOrderChange(next, {
248
+ key,
249
+ from,
250
+ to
251
+ });
252
+ options.announceMove(label, to + 1, keys.length);
253
+ }
254
+ const columnSort = useDragSort({
255
+ items: () => columnKeys.value,
256
+ elementFor: (key) => options.headerCellEls.get(key) ?? null,
257
+ orientation: () => "horizontal",
258
+ disabled: () => !options.reorderableColumns() || options.loading(),
259
+ resolveTarget: (hit, source) => {
260
+ const to = insertionIndex(hit, indexOfColumn(source), columnKeys.value.length);
261
+ return sameGroup(indexOfColumn(source), to) ? to : null;
262
+ },
263
+ onDrop: (source, to) => applyColumnMove(indexOfColumn(source), to)
264
+ });
265
+ /**
266
+ * Кольцо роверного фокуса по ручкам: одна остановка `Tab` на всю шапку.
267
+ * Иначе таблица из десяти колонок добавляла бы десять таб-стопов подряд.
268
+ */
269
+ const columnRoving = useRovingFocus({
270
+ items: () => options.reorderableColumns() ? columnKeys.value : [],
271
+ elementFor: (key) => options.columnHandleEls.get(key) ?? null,
272
+ orientation: () => "horizontal",
273
+ wrap: () => false
274
+ });
275
+ async function onColumnHandleKeydown(event, key) {
276
+ if (!options.reorderableColumns()) return;
277
+ if (event.shiftKey && (event.key === "ArrowLeft" || event.key === "ArrowRight")) {
278
+ event.preventDefault();
279
+ const from = indexOfColumn(key);
280
+ applyColumnMove(from, event.key === "ArrowLeft" ? from - 1 : from + 1);
281
+ await nextTick();
282
+ await columnRoving.focusKey(key);
283
+ return;
284
+ }
285
+ columnRoving.handleNavigationKeys(event);
286
+ }
287
+ const draggingColumnKey = computed(() => columnSort.mode.value === null ? null : columnSort.source.value);
288
+ /** Полоса места вставки — на колонке-соседе, со стороны движения. */
289
+ function columnDropClass(index) {
290
+ const target = columnSort.target.value;
291
+ if (!columnSort.isActive.value || target === null || target !== index) return "";
292
+ const active = columnSort.source.value === null ? -1 : indexOfColumn(columnSort.source.value);
293
+ if (index === active) return "";
294
+ return target < active ? columnDropBeforeClass : columnDropAfterClass;
295
+ }
296
+ return {
297
+ orderedColumns,
298
+ columnKeys,
299
+ pinGroupOf,
300
+ indexOfColumn,
301
+ draggingColumnKey,
302
+ columnDropClass,
303
+ onColumnHandleKeydown,
304
+ columnSort,
305
+ columnRoving
306
+ };
307
+ }
308
+ /** Шаг клавиатуры и крупный шаг — как у `GrSplitter`. */
309
+ var RESIZE_STEP = 16;
310
+ var RESIZE_BIG_STEP = 48;
311
+ function useDataTableColumnWidths(options) {
312
+ const internalColumnWidths = ref({});
313
+ const columnWidths = computed(() => options.columnWidths() ?? internalColumnWidths.value);
314
+ /** Фактические ширины шапки: заполняются замером раскладки. */
315
+ const measuredColumnWidths = ref({});
316
+ function setMeasuredWidths(widths) {
317
+ measuredColumnWidths.value = widths;
318
+ }
319
+ /** Ширина колонки: заданная пользователем сильнее объявленной в `columns`. */
320
+ function widthOf(col) {
321
+ return columnWidths.value[String(col.key)] ?? col.width;
322
+ }
323
+ /**
324
+ * Сумма заданных ширин — минимальная ширина таблицы.
325
+ *
326
+ * Без неё фиксированная раскладка вписывает таблицу в контейнер и делит место
327
+ * пропорционально: колонка, которую пользователь растянул, ужимается обратно, а
328
+ * горизонтальной прокрутки — той самой, ради которой закрепляют колонки, — не
329
+ * возникает. Считается, только когда ширина известна у **всех** колонок: с
330
+ * одной неизвестной сумма врала бы.
331
+ */
332
+ const tableMinWidth = computed(() => {
333
+ const cols = options.orderedColumns();
334
+ if (cols.length === 0) return void 0;
335
+ let total = 0;
336
+ for (const col of cols) {
337
+ const width = widthOf(col);
338
+ if (typeof width !== "number") return void 0;
339
+ total += width;
340
+ }
341
+ return total;
342
+ });
343
+ const resizingKey = ref(null);
344
+ let pendingResizeKey = null;
345
+ let resizeStartX = 0;
346
+ let resizeStartWidth = 0;
347
+ let widthBeforeResize;
348
+ function commitWidths(next) {
349
+ internalColumnWidths.value = next;
350
+ options.onWidthsChange(next);
351
+ }
352
+ function setColumnWidth(key, width) {
353
+ commitWidths({
354
+ ...columnWidths.value,
355
+ [key]: Math.max(48, Math.round(width))
356
+ });
357
+ }
358
+ function announceWidth(key) {
359
+ const col = options.orderedColumns().find((item) => String(item.key) === key);
360
+ if (!col) return;
361
+ options.announceWidth(col.label, columnWidths.value[key] ?? 0);
362
+ }
363
+ const resizeGesture = useDragGesture({
364
+ disabled: () => !options.resizableColumns() || options.loading(),
365
+ onStart: (event) => {
366
+ const key = pendingResizeKey;
367
+ const el = key === null ? null : options.headerCellEls.get(key);
368
+ if (key === null || !el) return false;
369
+ resizeStartX = event.clientX;
370
+ resizeStartWidth = el.getBoundingClientRect().width;
371
+ widthBeforeResize = columnWidths.value[key];
372
+ resizingKey.value = key;
373
+ },
374
+ onMove: (event) => {
375
+ if (resizingKey.value === null) return;
376
+ event.preventDefault();
377
+ setColumnWidth(resizingKey.value, resizeStartWidth + (event.clientX - resizeStartX));
378
+ },
379
+ onEnd: () => {
380
+ const key = resizingKey.value;
381
+ resizingKey.value = null;
382
+ if (key === null) return;
383
+ options.onColumnResize(key, columnWidths.value[key] ?? Math.round(resizeStartWidth));
384
+ announceWidth(key);
385
+ },
386
+ onCancel: () => {
387
+ const key = resizingKey.value;
388
+ resizingKey.value = null;
389
+ if (key === null) return;
390
+ const next = { ...columnWidths.value };
391
+ if (widthBeforeResize === void 0) delete next[key];
392
+ else next[key] = widthBeforeResize;
393
+ commitWidths(next);
394
+ }
395
+ });
396
+ function onResizerPointerDown(event, key) {
397
+ pendingResizeKey = key;
398
+ resizeGesture.start(event);
399
+ }
400
+ /** Сброс к авторазметке: колонка снова считается по содержимому. */
401
+ function resetColumnWidth(key) {
402
+ if (columnWidths.value[key] === void 0) return;
403
+ const next = { ...columnWidths.value };
404
+ delete next[key];
405
+ commitWidths(next);
406
+ options.onColumnResize(key, 0);
407
+ }
408
+ function resizeByKeyboard(key, delta) {
409
+ const measured = options.headerCellEls.get(key)?.getBoundingClientRect().width ?? 48;
410
+ const current = columnWidths.value[key] ?? measured;
411
+ setColumnWidth(key, current + delta);
412
+ options.onColumnResize(key, columnWidths.value[key] ?? current);
413
+ announceWidth(key);
414
+ }
415
+ function onResizerKeydown(event, key) {
416
+ if (!options.resizableColumns() || options.loading()) return;
417
+ const step = event.shiftKey ? RESIZE_BIG_STEP : RESIZE_STEP;
418
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
419
+ event.preventDefault();
420
+ resizeByKeyboard(key, event.key === "ArrowLeft" ? -step : step);
421
+ return;
422
+ }
423
+ if (event.key === "Enter") {
424
+ event.preventDefault();
425
+ resetColumnWidth(key);
426
+ }
427
+ }
428
+ /**
429
+ * Ручка ресайза — фокусируемый `separator`, а значит обязана называть текущее
430
+ * значение с первого рендера, до всякого перетаскивания. Заданной ширины у
431
+ * колонки может не быть вовсе (авторазметка), поэтому за значением идём к
432
+ * измеренной; до замера остаётся объявленная в `columns`, а её тоже может не
433
+ * быть — тогда минимум.
434
+ */
435
+ function resizerValue(col) {
436
+ const key = String(col.key);
437
+ const declared = typeof col.width === "number" ? col.width : void 0;
438
+ return columnWidths.value[key] ?? measuredColumnWidths.value[key] ?? declared ?? 48;
439
+ }
440
+ return {
441
+ columnWidths,
442
+ measuredColumnWidths,
443
+ setMeasuredWidths,
444
+ widthOf,
445
+ tableMinWidth,
446
+ resizingKey,
447
+ onResizerPointerDown,
448
+ onResizerKeydown,
449
+ resetColumnWidth,
450
+ resizerValue
451
+ };
452
+ }
453
+ //#endregion
454
+ //#region src/components/GrDataTable/composables/useDataTableLayout.ts
455
+ /** Служебная колонка выбора в реестре ячеек: своего ключа у неё нет. */
456
+ var SELECT_COLUMN_KEY = "__select__";
457
+ function useDataTableLayout(options) {
458
+ const hasPinnedLeft = computed(() => options.orderedColumns().some((col) => col.pinned === "left"));
459
+ const pinnedOffsets = ref({});
460
+ /**
461
+ * Смещения липких колонок считаются по **измеренным** ширинам соседей: колонка
462
+ * может жить на авторазметке, и тогда взять смещение больше неоткуда. Отсюда же
463
+ * порядок: замер после отрисовки, а не в вычислении.
464
+ */
465
+ function measurePinnedOffsets() {
466
+ const next = {};
467
+ const cols = options.orderedColumns();
468
+ let left = options.selectable() && hasPinnedLeft.value ? options.headerCellEls.get("__select__")?.getBoundingClientRect().width ?? 0 : 0;
469
+ for (const col of cols) {
470
+ if (col.pinned !== "left") continue;
471
+ next[String(col.key)] = left;
472
+ left += options.headerCellEls.get(String(col.key))?.getBoundingClientRect().width ?? 0;
473
+ }
474
+ let right = 0;
475
+ for (let index = cols.length - 1; index >= 0; index -= 1) {
476
+ const col = cols[index];
477
+ if (col.pinned !== "right") continue;
478
+ next[String(col.key)] = right;
479
+ right += options.headerCellEls.get(String(col.key))?.getBoundingClientRect().width ?? 0;
480
+ }
481
+ pinnedOffsets.value = next;
482
+ }
483
+ function measureColumnWidths() {
484
+ if (!options.resizableColumns()) return;
485
+ const next = {};
486
+ for (const col of options.orderedColumns()) {
487
+ const key = String(col.key);
488
+ const width = options.headerCellEls.get(key)?.getBoundingClientRect().width;
489
+ if (width) next[key] = Math.round(width);
490
+ }
491
+ options.onMeasuredWidths(next);
492
+ }
493
+ function measureLayout() {
494
+ measurePinnedOffsets();
495
+ measureColumnWidths();
496
+ }
497
+ function pinnedStyleOf(col) {
498
+ if (!col.pinned) return void 0;
499
+ const offset = pinnedOffsets.value[String(col.key)] ?? 0;
500
+ return col.pinned === "left" ? { left: `${offset}px` } : { right: `${offset}px` };
501
+ }
502
+ /** Тень рисует только крайняя колонка группы — иначе полос было бы столько же, сколько колонок. */
503
+ function pinnedEdgeClass(col, index) {
504
+ const cols = options.orderedColumns();
505
+ if (col.pinned === "left") return cols[index + 1]?.pinned === "left" ? "" : columnPinnedLeftEdgeClass;
506
+ if (col.pinned === "right") return cols[index - 1]?.pinned === "right" ? "" : columnPinnedRightEdgeClass;
507
+ return "";
508
+ }
509
+ function pinnedCellClass(col, index) {
510
+ if (!col.pinned) return [];
511
+ return [columnPinnedClass, pinnedEdgeClass(col, index)];
512
+ }
513
+ /**
514
+ * Ширину колонки меняет не только правка пропов: окно, шрифт и содержимое
515
+ * ячейки двигают её сами. `ResizeObserver` — единственный способ узнать об этом;
516
+ * в jsdom и на сервере его нет, там хватает пересчёта по изменению данных.
517
+ */
518
+ let layoutObserver = null;
519
+ onMounted(() => {
520
+ measureLayout();
521
+ if (typeof ResizeObserver === "undefined") return;
522
+ layoutObserver = new ResizeObserver(() => measureLayout());
523
+ const el = options.headerCellEls.get("__select__") ?? options.headerCellEls.get(options.columnKeys()[0]);
524
+ if (el?.parentElement) layoutObserver.observe(el.parentElement);
525
+ });
526
+ onUnmounted(() => {
527
+ layoutObserver?.disconnect();
528
+ layoutObserver = null;
529
+ });
530
+ watch(options.watchSources, () => void nextTick(measureLayout));
531
+ return {
532
+ hasPinnedLeft,
533
+ pinnedStyleOf,
534
+ pinnedCellClass,
535
+ measureLayout
536
+ };
537
+ }
538
+ //#endregion
69
539
  //#region ~icons/lucide/arrow-down
70
540
  var _hoisted_1$1 = {
71
541
  viewBox: "0 0 24 24",
@@ -112,6 +582,7 @@ var _hoisted_8 = {
112
582
  var _hoisted_9 = [
113
583
  "aria-label",
114
584
  "aria-valuenow",
585
+ "aria-valuemin",
115
586
  "aria-valuetext",
116
587
  "onPointerdown",
117
588
  "onKeydown",
@@ -150,27 +621,6 @@ var _hoisted_18 = {
150
621
  var _hoisted_19 = ["colspan"];
151
622
  var _hoisted_20 = ["aria-rowindex"];
152
623
  var _hoisted_21 = ["data-column-key"];
153
- /**
154
- * `GrDataTable` — data-таблица поверх `GrTable` с сортировкой по клику
155
- * на заголовок и scoped-слотами ячеек (`#cell-<key>`), `#header-<key>`,
156
- * `#caption`, `#footer`, `#empty`, `#loading`.
157
- *
158
- * Итоговая строка объявляется пропом `summaryRow` и оформляется слотами
159
- * `#summary-<key>`: она встаёт по той же колоночной сетке, что и тело.
160
- *
161
- * `#footer` — для свободной разметки под итогом: несколько строк, примечание,
162
- * `colspan`. Рендерится внутрь того же `<tfoot>`, то есть его содержимое тоже
163
- * строки таблицы (`<tr><td>`), а скоуп отдаёт `columns` (в текущем порядке) и
164
- * `totalColumns` (с колонкой выбора).
165
- *
166
- * Сортировка, включая крайние случаи с пустыми и смешанными значениями, живёт
167
- * в `grDataTableSort.ts` — см. `docs/components/GrDataTable.md`.
168
- */
169
- var MIN_COLUMN_WIDTH = 48;
170
- /** Шаг клавиатуры и крупный шаг — как у `GrSplitter`. */
171
- var RESIZE_STEP = 16;
172
- var RESIZE_BIG_STEP = 48;
173
- var SELECT_COLUMN_KEY = "__select__";
174
624
  //#endregion
175
625
  //#region src/components/GrDataTable/GrDataTable.vue
176
626
  var GrDataTable_default = /* @__PURE__ */ defineComponent({
@@ -262,85 +712,30 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
262
712
  const { announce } = useAnnouncer();
263
713
  const resolvedLoadingText = computed(() => props.loadingText ?? t("gr.dataTable.loading", "Loading…"));
264
714
  const resolvedEmptyText = computed(() => props.emptyText ?? t("gr.dataTable.empty", "No data"));
265
- const internalSortKey = ref(props.initialSortKey ?? "");
266
- const internalSortDir = ref(props.initialSortDir);
267
- const isSortKeyControlled = computed(() => props.sortKey !== void 0);
268
- const isSortDirControlled = computed(() => props.sortDir !== void 0);
269
- const currentSortKey = computed(() => props.sortKey ?? internalSortKey.value);
270
- const currentSortDir = computed(() => props.sortDir ?? internalSortDir.value);
271
- function applySort(key, dir) {
272
- if (!isSortKeyControlled.value) internalSortKey.value = key;
273
- if (!isSortDirControlled.value) internalSortDir.value = dir;
274
- emit("update:sortKey", key);
275
- emit("update:sortDir", dir);
276
- emit("sortChange", {
277
- key,
278
- dir
279
- });
280
- }
281
- const sortedRows = computed(() => {
282
- if (props.externalSort) return [...props.rows];
283
- const key = currentSortKey.value;
284
- if (!key) return [...props.rows];
285
- return sortRows(props.rows, key, currentSortDir.value, locale.value);
286
- });
287
- function toggleSort(col) {
288
- if (!col.sortable) return;
289
- if (currentSortKey.value !== col.key) {
290
- applySort(col.key, "asc");
291
- return;
292
- }
293
- if (currentSortDir.value === "asc") {
294
- applySort(col.key, "desc");
295
- return;
296
- }
297
- if (props.sortCycle === "asc-desc-none") {
298
- applySort("", "asc");
299
- return;
715
+ const { currentSortKey, currentSortDir, sortedRows, toggleSort, clearSort, ariaSortFor } = useDataTableSort({
716
+ rows: () => props.rows,
717
+ sortKey: () => props.sortKey,
718
+ sortDir: () => props.sortDir,
719
+ initialSortKey: () => props.initialSortKey,
720
+ initialSortDir: () => props.initialSortDir,
721
+ externalSort: () => props.externalSort,
722
+ sortCycle: () => props.sortCycle,
723
+ locale: () => locale.value,
724
+ onSortChange: (key, dir) => {
725
+ emit("update:sortKey", key);
726
+ emit("update:sortDir", dir);
727
+ emit("sortChange", {
728
+ key,
729
+ dir
730
+ });
300
731
  }
301
- applySort(col.key, "asc");
302
- }
732
+ });
303
733
  function cellAlign(col) {
304
734
  if (col.align === "right") return "text-right";
305
735
  if (col.align === "center") return "text-center";
306
736
  return "text-left";
307
737
  }
308
- /**
309
- * Синтетические ключи для строк, у которых поле `rowKey` пустое.
310
- *
311
- * Без них строка получила бы `String(undefined ?? '')` — **один и тот же** ключ
312
- * на всю таблицу: Vue переиспользовал бы DOM не по назначению, а выбор одной
313
- * строки помечал бы выбранными все. Ключ привязан к идентичности объекта,
314
- * поэтому переживает сортировку и не зависит от индекса.
315
- */
316
- const syntheticKeys = /* @__PURE__ */ new WeakMap();
317
- let syntheticKeyCounter = 0;
318
- const missingKeyWarned = ref(false);
319
- function syntheticRowKey(row) {
320
- const existing = syntheticKeys.get(row);
321
- if (existing !== void 0) return existing;
322
- syntheticKeyCounter += 1;
323
- const generated = `gr-row-${syntheticKeyCounter}`;
324
- syntheticKeys.set(row, generated);
325
- if (!missingKeyWarned.value && process.env.NODE_ENV !== "production") {
326
- missingKeyWarned.value = true;
327
- console.warn(`[GrDataTable] У строки нет значения по ключу "${String(props.rowKey)}". Задайте \`rowKey\` (поле или функцию) — иначе выбор строк и переиспользование DOM работают по синтетическому ключу, который не переживёт перезагрузку данных.`);
328
- }
329
- return generated;
330
- }
331
- function rowKeyValue(row) {
332
- const rk = props.rowKey;
333
- if (typeof rk === "function") return rk(row);
334
- const value = row[rk];
335
- if (typeof value === "string" && value !== "") return value;
336
- if (typeof value === "number") return value;
337
- return syntheticRowKey(row);
338
- }
339
- function ariaSortFor(col) {
340
- if (!col.sortable) return void 0;
341
- if (currentSortKey.value !== col.key) return "none";
342
- return currentSortDir.value === "asc" ? "ascending" : "descending";
343
- }
738
+ const { rowKeyValue } = useDataTableRowKeys({ rowKey: () => props.rowKey });
344
739
  /**
345
740
  * Подсказка «что сделает нажатие» — visually hidden текстом **после** подписи
346
741
  * колонки, а не `aria-label`'ом на кнопке. `aria-label` подменял бы собой имя
@@ -391,55 +786,72 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
391
786
  return props.summaryRow?.[key];
392
787
  }
393
788
  const totalColumns = computed(() => props.columns.length + (props.selectable ? 1 : 0));
394
- /** Uncontrolled-состояние; в controlled-режиме перекрывается пропом `columnOrder`. */
395
- const internalColumnOrder = ref(props.columns.map((col) => String(col.key)));
396
789
  /**
397
- * Колонки в пользовательском порядке.
398
- *
399
- * Состав задаёт `columns`, порядок только порядок: ключ, которого в наборе
400
- * нет, игнорируется, а колонка, которой нет в порядке (её только что добавили),
401
- * встаёт в конец. Иначе правка `columns` теряла бы колонки молча.
790
+ * Карты живут в компоненте, а не в модуле: наполняет их шаблон, а читают все
791
+ * три колоночных модуля — порядок тянет за ячейку, ширина её замеряет,
792
+ * раскладка считает по ней смещения закрепления.
402
793
  */
403
- const orderedColumns = computed(() => {
404
- const order = props.columnOrder ?? internalColumnOrder.value;
405
- const remaining = new Map(props.columns.map((col) => [String(col.key), col]));
406
- const ordered = [];
407
- for (const key of order) {
408
- const col = remaining.get(key);
409
- if (!col) continue;
410
- remaining.delete(key);
411
- ordered.push(col);
794
+ const headerCellEls = /* @__PURE__ */ new Map();
795
+ const columnHandleEls = /* @__PURE__ */ new Map();
796
+ function registerEl(store, key, el) {
797
+ if (el instanceof HTMLElement) {
798
+ store.set(key, el);
799
+ return;
412
800
  }
413
- for (const col of props.columns) if (remaining.has(String(col.key))) ordered.push(col);
414
- return ordered.sort((a, b) => pinGroupOf(a) - pinGroupOf(b));
415
- });
416
- /** Группа закрепления: 0 — слева, 1 — обычная колонка, 2 — справа. */
417
- function pinGroupOf(col) {
418
- if (col.pinned === "left") return 0;
419
- if (col.pinned === "right") return 2;
420
- return 1;
801
+ const previous = store.get(key);
802
+ if (previous && !previous.isConnected) store.delete(key);
421
803
  }
422
- /**
423
- * Сумма заданных ширин — минимальная ширина таблицы.
424
- *
425
- * Без неё фиксированная раскладка вписывает таблицу в контейнер и делит место
426
- * пропорционально: колонка, которую пользователь растянул, ужимается обратно, а
427
- * горизонтальной прокрутки — той самой, ради которой закрепляют колонки, — не
428
- * возникает. Считается, только когда ширина известна у **всех** колонок: с
429
- * одной неизвестной сумма врала бы.
430
- */
431
- const tableMinWidth = computed(() => {
432
- const cols = orderedColumns.value;
433
- if (cols.length === 0) return void 0;
434
- let total = 0;
435
- for (const col of cols) {
436
- const width = widthOf(col);
437
- if (typeof width !== "number") return void 0;
438
- total += width;
804
+ const { orderedColumns, columnKeys, draggingColumnKey, columnDropClass, onColumnHandleKeydown, columnSort, columnRoving } = useDataTableColumnOrder({
805
+ columns: () => props.columns,
806
+ columnOrder: () => props.columnOrder,
807
+ reorderableColumns: () => props.reorderableColumns,
808
+ loading: () => props.loading,
809
+ headerCellEls,
810
+ columnHandleEls,
811
+ onOrderChange: (order, moved) => {
812
+ emit("update:columnOrder", order);
813
+ emit("columnReorder", moved);
814
+ },
815
+ announceMove: (label, position, count) => {
816
+ announce(t("gr.dataTable.columnMoved", "Column {label} moved to position {position} of {count}", {
817
+ label,
818
+ position,
819
+ count
820
+ }));
439
821
  }
440
- return total;
441
822
  });
442
- const columnKeys = computed(() => orderedColumns.value.map((col) => String(col.key)));
823
+ const { columnWidths, setMeasuredWidths, widthOf, tableMinWidth, resizingKey, onResizerPointerDown, onResizerKeydown, resetColumnWidth, resizerValue } = useDataTableColumnWidths({
824
+ orderedColumns: () => orderedColumns.value,
825
+ columnWidths: () => props.columnWidths,
826
+ resizableColumns: () => props.resizableColumns,
827
+ loading: () => props.loading,
828
+ headerCellEls,
829
+ onWidthsChange: (widths) => emit("update:columnWidths", widths),
830
+ onColumnResize: (key, width) => emit("columnResize", {
831
+ key,
832
+ width
833
+ }),
834
+ announceWidth: (label, width) => {
835
+ announce(t("gr.dataTable.columnResized", "Column {label} is {width} pixels wide", {
836
+ label,
837
+ width
838
+ }));
839
+ }
840
+ });
841
+ const { hasPinnedLeft, pinnedStyleOf, pinnedCellClass } = useDataTableLayout({
842
+ orderedColumns: () => orderedColumns.value,
843
+ columnKeys: () => columnKeys.value,
844
+ selectable: () => props.selectable,
845
+ resizableColumns: () => props.resizableColumns,
846
+ headerCellEls,
847
+ watchSources: () => [
848
+ orderedColumns.value,
849
+ columnWidths.value,
850
+ props.loading,
851
+ props.rows.length
852
+ ],
853
+ onMeasuredWidths: setMeasuredWidths
854
+ });
443
855
  const tableProps = computed(() => ({
444
856
  size: resolvedSize.value,
445
857
  ariaLabel: props.ariaLabel,
@@ -451,288 +863,13 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
451
863
  fixedLayout: props.virtual || props.resizableColumns,
452
864
  tableMinWidth: tableMinWidth.value
453
865
  }));
454
- function indexOfColumn(key) {
455
- return columnKeys.value.indexOf(key);
456
- }
457
- const headerCellEls = /* @__PURE__ */ new Map();
458
- const columnHandleEls = /* @__PURE__ */ new Map();
459
- function registerEl(store, key, el) {
460
- if (el instanceof HTMLElement) {
461
- store.set(key, el);
462
- return;
463
- }
464
- const previous = store.get(key);
465
- if (previous && !previous.isConnected) store.delete(key);
466
- }
467
- function applyColumnMove(from, to) {
468
- const keys = columnKeys.value;
469
- if (from < 0 || to < 0 || to >= keys.length || from === to) return;
470
- if (!sameGroup(from, to)) return;
471
- const key = keys[from];
472
- const label = orderedColumns.value[from]?.label ?? key;
473
- const next = moveItem(keys, from, to);
474
- internalColumnOrder.value = next;
475
- emit("update:columnOrder", next);
476
- emit("columnReorder", {
477
- key,
478
- from,
479
- to
480
- });
481
- announce(t("gr.dataTable.columnMoved", "Column {label} moved to position {position} of {count}", {
482
- label,
483
- position: to + 1,
484
- count: keys.length
485
- }));
486
- }
487
- const columnSort = useDragSort({
488
- items: () => columnKeys.value,
489
- elementFor: (key) => headerCellEls.get(key) ?? null,
490
- orientation: () => "horizontal",
491
- disabled: () => !props.reorderableColumns || props.loading,
492
- resolveTarget: (hit, source) => {
493
- const to = insertionIndex(hit, indexOfColumn(source), columnKeys.value.length);
494
- return sameGroup(indexOfColumn(source), to) ? to : null;
495
- },
496
- onDrop: (source, to) => applyColumnMove(indexOfColumn(source), to)
497
- });
498
- function sameGroup(from, to) {
499
- const cols = orderedColumns.value;
500
- if (!cols[from] || !cols[to]) return false;
501
- return pinGroupOf(cols[from]) === pinGroupOf(cols[to]);
502
- }
503
- /**
504
- * Кольцо роверного фокуса по ручкам: одна остановка `Tab` на всю шапку.
505
- * Иначе таблица из десяти колонок добавляла бы десять таб-стопов подряд.
506
- */
507
- const columnRoving = useRovingFocus({
508
- items: () => props.reorderableColumns ? columnKeys.value : [],
509
- elementFor: (key) => columnHandleEls.get(key) ?? null,
510
- orientation: () => "horizontal",
511
- wrap: () => false
512
- });
513
- async function onColumnHandleKeydown(event, key) {
514
- if (!props.reorderableColumns) return;
515
- if (event.shiftKey && (event.key === "ArrowLeft" || event.key === "ArrowRight")) {
516
- event.preventDefault();
517
- const from = indexOfColumn(key);
518
- applyColumnMove(from, event.key === "ArrowLeft" ? from - 1 : from + 1);
519
- await nextTick();
520
- await columnRoving.focusKey(key);
521
- return;
522
- }
523
- columnRoving.handleNavigationKeys(event);
524
- }
525
- const draggingColumnKey = computed(() => columnSort.mode.value === null ? null : columnSort.source.value);
526
- /** Полоса места вставки — на колонке-соседе, со стороны движения. */
527
- function columnDropClass(index) {
528
- const target = columnSort.target.value;
529
- if (!columnSort.isActive.value || target === null || target !== index) return "";
530
- const active = columnSort.source.value === null ? -1 : indexOfColumn(columnSort.source.value);
531
- if (index === active) return "";
532
- return target < active ? columnDropBeforeClass : columnDropAfterClass;
533
- }
534
866
  function columnHandleLabel(col) {
535
867
  return t("gr.dataTable.moveColumn", "Move column {label}", { label: col.label });
536
868
  }
537
- /** Уже колонки не бывает: в неё перестаёт помещаться даже стрелка сортировки. */
538
- const internalColumnWidths = ref({});
539
- const columnWidths = computed(() => props.columnWidths ?? internalColumnWidths.value);
540
- /** Фактические ширины шапки: заполняются замером, см. `measureLayout`. */
541
- const measuredColumnWidths = ref({});
542
- /** Ширина колонки: заданная пользователем сильнее объявленной в `columns`. */
543
- function widthOf(col) {
544
- return columnWidths.value[String(col.key)] ?? col.width;
545
- }
546
- const resizingKey = ref(null);
547
- let pendingResizeKey = null;
548
- let resizeStartX = 0;
549
- let resizeStartWidth = 0;
550
- let widthBeforeResize;
551
- function setColumnWidth(key, width) {
552
- const next = {
553
- ...columnWidths.value,
554
- [key]: Math.max(MIN_COLUMN_WIDTH, Math.round(width))
555
- };
556
- internalColumnWidths.value = next;
557
- emit("update:columnWidths", next);
558
- }
559
- function announceWidth(key) {
560
- const col = orderedColumns.value.find((item) => String(item.key) === key);
561
- if (!col) return;
562
- announce(t("gr.dataTable.columnResized", "Column {label} is {width} pixels wide", {
563
- label: col.label,
564
- width: columnWidths.value[key] ?? 0
565
- }));
566
- }
567
- const resizeGesture = useDragGesture({
568
- disabled: () => !props.resizableColumns || props.loading,
569
- onStart: (event) => {
570
- const key = pendingResizeKey;
571
- const el = key === null ? null : headerCellEls.get(key);
572
- if (key === null || !el) return false;
573
- resizeStartX = event.clientX;
574
- resizeStartWidth = el.getBoundingClientRect().width;
575
- widthBeforeResize = columnWidths.value[key];
576
- resizingKey.value = key;
577
- },
578
- onMove: (event) => {
579
- if (resizingKey.value === null) return;
580
- event.preventDefault();
581
- setColumnWidth(resizingKey.value, resizeStartWidth + (event.clientX - resizeStartX));
582
- },
583
- onEnd: () => {
584
- const key = resizingKey.value;
585
- resizingKey.value = null;
586
- if (key === null) return;
587
- emit("columnResize", {
588
- key,
589
- width: columnWidths.value[key] ?? Math.round(resizeStartWidth)
590
- });
591
- announceWidth(key);
592
- },
593
- onCancel: () => {
594
- const key = resizingKey.value;
595
- resizingKey.value = null;
596
- if (key === null) return;
597
- const next = { ...columnWidths.value };
598
- if (widthBeforeResize === void 0) delete next[key];
599
- else next[key] = widthBeforeResize;
600
- internalColumnWidths.value = next;
601
- emit("update:columnWidths", next);
602
- }
603
- });
604
- function onResizerPointerDown(event, key) {
605
- pendingResizeKey = key;
606
- resizeGesture.start(event);
607
- }
608
- /** Сброс к авторазметке: колонка снова считается по содержимому. */
609
- function resetColumnWidth(key) {
610
- if (columnWidths.value[key] === void 0) return;
611
- const next = { ...columnWidths.value };
612
- delete next[key];
613
- internalColumnWidths.value = next;
614
- emit("update:columnWidths", next);
615
- emit("columnResize", {
616
- key,
617
- width: 0
618
- });
619
- }
620
- function resizeByKeyboard(key, delta) {
621
- const measured = headerCellEls.get(key)?.getBoundingClientRect().width ?? MIN_COLUMN_WIDTH;
622
- const current = columnWidths.value[key] ?? measured;
623
- setColumnWidth(key, current + delta);
624
- emit("columnResize", {
625
- key,
626
- width: columnWidths.value[key] ?? current
627
- });
628
- announceWidth(key);
629
- }
630
- function onResizerKeydown(event, key) {
631
- if (!props.resizableColumns || props.loading) return;
632
- const step = event.shiftKey ? RESIZE_BIG_STEP : RESIZE_STEP;
633
- if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
634
- event.preventDefault();
635
- resizeByKeyboard(key, event.key === "ArrowLeft" ? -step : step);
636
- return;
637
- }
638
- if (event.key === "Enter") {
639
- event.preventDefault();
640
- resetColumnWidth(key);
641
- }
642
- }
643
869
  function resizerLabel(col) {
644
870
  return t("gr.dataTable.resizeColumn", "Width of column {label}", { label: col.label });
645
871
  }
646
- /**
647
- * Ручка ресайза — фокусируемый `separator`, а значит обязана называть текущее
648
- * значение с первого рендера, до всякого перетаскивания. Заданной ширины у
649
- * колонки может не быть вовсе (авторазметка), поэтому за значением идём к
650
- * измеренной; до замера остаётся объявленная в `columns`, а её тоже может не
651
- * быть — тогда минимум.
652
- */
653
- function resizerValue(col) {
654
- const key = String(col.key);
655
- const declared = typeof col.width === "number" ? col.width : void 0;
656
- return columnWidths.value[key] ?? measuredColumnWidths.value[key] ?? declared ?? MIN_COLUMN_WIDTH;
657
- }
658
- /** Служебная колонка выбора в реестре ячеек: своего ключа у неё нет. */
659
- const hasPinnedLeft = computed(() => orderedColumns.value.some((col) => col.pinned === "left"));
660
- const pinnedOffsets = ref({});
661
- /**
662
- * Смещения липких колонок считаются по **измеренным** ширинам соседей: колонка
663
- * может жить на авторазметке, и тогда взять смещение больше неоткуда. Отсюда же
664
- * порядок: замер после отрисовки, а не в вычислении.
665
- */
666
- function measurePinnedOffsets() {
667
- const next = {};
668
- const cols = orderedColumns.value;
669
- let left = props.selectable && hasPinnedLeft.value ? headerCellEls.get(SELECT_COLUMN_KEY)?.getBoundingClientRect().width ?? 0 : 0;
670
- for (const col of cols) {
671
- if (col.pinned !== "left") continue;
672
- next[String(col.key)] = left;
673
- left += headerCellEls.get(String(col.key))?.getBoundingClientRect().width ?? 0;
674
- }
675
- let right = 0;
676
- for (let index = cols.length - 1; index >= 0; index -= 1) {
677
- const col = cols[index];
678
- if (col.pinned !== "right") continue;
679
- next[String(col.key)] = right;
680
- right += headerCellEls.get(String(col.key))?.getBoundingClientRect().width ?? 0;
681
- }
682
- pinnedOffsets.value = next;
683
- }
684
- function measureColumnWidths() {
685
- if (!props.resizableColumns) return;
686
- const next = {};
687
- for (const col of orderedColumns.value) {
688
- const key = String(col.key);
689
- const width = headerCellEls.get(key)?.getBoundingClientRect().width;
690
- if (width) next[key] = Math.round(width);
691
- }
692
- measuredColumnWidths.value = next;
693
- }
694
- function measureLayout() {
695
- measurePinnedOffsets();
696
- measureColumnWidths();
697
- }
698
- function pinnedStyleOf(col) {
699
- if (!col.pinned) return void 0;
700
- const offset = pinnedOffsets.value[String(col.key)] ?? 0;
701
- return col.pinned === "left" ? { left: `${offset}px` } : { right: `${offset}px` };
702
- }
703
- /** Тень рисует только крайняя колонка группы — иначе полос было бы столько же, сколько колонок. */
704
- function pinnedEdgeClass(col, index) {
705
- if (col.pinned === "left") return orderedColumns.value[index + 1]?.pinned === "left" ? "" : columnPinnedLeftEdgeClass;
706
- if (col.pinned === "right") return orderedColumns.value[index - 1]?.pinned === "right" ? "" : columnPinnedRightEdgeClass;
707
- return "";
708
- }
709
- function pinnedCellClass(col, index) {
710
- if (!col.pinned) return [];
711
- return [columnPinnedClass, pinnedEdgeClass(col, index)];
712
- }
713
- /**
714
- * Ширину колонки меняет не только правка пропов: окно, шрифт и содержимое
715
- * ячейки двигают её сами. `ResizeObserver` — единственный способ узнать об этом;
716
- * в jsdom и на сервере его нет, там хватает пересчёта по изменению данных.
717
- */
718
- let layoutObserver = null;
719
- onMounted(() => {
720
- measureLayout();
721
- if (typeof ResizeObserver === "undefined") return;
722
- layoutObserver = new ResizeObserver(() => measureLayout());
723
- const el = headerCellEls.get(SELECT_COLUMN_KEY) ?? headerCellEls.get(columnKeys.value[0]);
724
- if (el?.parentElement) layoutObserver.observe(el.parentElement);
725
- });
726
- onUnmounted(() => {
727
- layoutObserver?.disconnect();
728
- layoutObserver = null;
729
- });
730
- watch(() => [
731
- orderedColumns.value,
732
- columnWidths.value,
733
- props.loading,
734
- props.rows.length
735
- ], () => void nextTick(measureLayout));
872
+ /** Уже колонки не бывает: в неё перестаёт помещаться даже стрелка сортировки. */
736
873
  /**
737
874
  * Живой регион существует с первого рендера и пуст, пока объявлять нечего.
738
875
  * Регион, который появляется уже с текстом, часть AT не объявляет вовсе —
@@ -757,41 +894,13 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
757
894
  event
758
895
  });
759
896
  }
760
- const internalSelected = ref([]);
761
- const isSelectedControlled = computed(() => props.selected !== void 0);
762
- const selectedKeys = computed(() => new Set(props.selected ?? internalSelected.value));
763
- function isRowSelectable(row) {
764
- return props.selectableRow ? props.selectableRow(row) : true;
765
- }
766
- function isRowSelected(row) {
767
- return selectedKeys.value.has(rowKeyValue(row));
768
- }
769
- /** «Выбрать все» работает по видимым и выбираемым строкам — они же считают состояние шапки. */
770
- const selectableRows = computed(() => sortedRows.value.filter(isRowSelectable));
771
- const allSelected = computed(() => selectableRows.value.length > 0 && selectableRows.value.every(isRowSelected));
772
- const someSelected = computed(() => selectableRows.value.some(isRowSelected) && !allSelected.value);
773
- function emitSelected(next) {
774
- if (!isSelectedControlled.value) internalSelected.value = [...next];
775
- emit("update:selected", [...next]);
776
- }
777
- function toggleRow(row) {
778
- if (!isRowSelectable(row)) return;
779
- const key = rowKeyValue(row);
780
- const next = new Set(selectedKeys.value);
781
- if (next.has(key)) next.delete(key);
782
- else next.add(key);
783
- emitSelected(next);
784
- }
785
- function toggleAll() {
786
- const next = new Set(selectedKeys.value);
787
- if (allSelected.value) {
788
- for (const row of selectableRows.value) next.delete(rowKeyValue(row));
789
- emitSelected(next);
790
- return;
791
- }
792
- for (const row of selectableRows.value) next.add(rowKeyValue(row));
793
- emitSelected(next);
794
- }
897
+ const { isRowSelectable, isRowSelected, selectableRows, allSelected, someSelected, toggleRow, toggleAll } = useDataTableSelection({
898
+ rows: () => sortedRows.value,
899
+ selected: () => props.selected,
900
+ selectableRow: () => props.selectableRow,
901
+ rowKeyValue,
902
+ onSelectedChange: (keys) => emit("update:selected", keys)
903
+ });
795
904
  const tableRef = ref(null);
796
905
  const rootId = useId();
797
906
  function rootEl() {
@@ -864,9 +973,6 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
864
973
  function scrollTo(options) {
865
974
  scrollEl()?.scrollTo(options);
866
975
  }
867
- function clearSort() {
868
- applySort("", "asc");
869
- }
870
976
  __expose({
871
977
  /** Прокрутить к строке по её ключу. `false` — строки нет в DOM. */
872
978
  scrollToRow,
@@ -904,29 +1010,30 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
904
1010
  "aria-rowindex": __props.virtual ? 1 : void 0
905
1011
  }, [__props.selectable ? (openBlock(), createElementBlock("th", {
906
1012
  key: 0,
907
- ref: (el) => registerEl(unref(headerCellEls), SELECT_COLUMN_KEY, el),
1013
+ ref: (el) => registerEl(unref(headerCellEls), unref(SELECT_COLUMN_KEY), el),
908
1014
  class: normalizeClass(["text-left", [
909
1015
  selectColumnClass.value,
910
1016
  cellClass.value,
911
- hasPinnedLeft.value ? unref(columnPinnedClass) : ""
1017
+ unref(hasPinnedLeft) ? unref(columnPinnedClass) : ""
912
1018
  ]]),
913
- style: normalizeStyle(hasPinnedLeft.value ? { left: "0px" } : void 0),
1019
+ style: normalizeStyle(unref(hasPinnedLeft) ? { left: "0px" } : void 0),
914
1020
  scope: "col"
915
1021
  }, [createVNode(GrCheckbox_default, {
916
1022
  "data-gr-datatable-select-all": "",
917
- "model-value": allSelected.value,
918
- indeterminate: someSelected.value,
1023
+ "model-value": unref(allSelected),
1024
+ indeterminate: unref(someSelected),
919
1025
  size: checkboxSize.value,
920
- disabled: __props.loading || selectableRows.value.length === 0,
1026
+ disabled: __props.loading || unref(selectableRows).length === 0,
921
1027
  "aria-label": unref(t)("gr.dataTable.selectAll", "Select all rows"),
922
- "onUpdate:modelValue": toggleAll
1028
+ "onUpdate:modelValue": unref(toggleAll)
923
1029
  }, null, 8, [
924
1030
  "model-value",
925
1031
  "indeterminate",
926
1032
  "size",
927
1033
  "disabled",
928
- "aria-label"
929
- ])], 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(orderedColumns.value, (col, colIndex) => {
1034
+ "aria-label",
1035
+ "onUpdate:modelValue"
1036
+ ])], 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(orderedColumns), (col, colIndex) => {
930
1037
  return openBlock(), createElementBlock("th", {
931
1038
  key: col.key,
932
1039
  ref_for: true,
@@ -936,16 +1043,16 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
936
1043
  cellClass.value,
937
1044
  cellAlign(col),
938
1045
  __props.reorderableColumns || __props.resizableColumns ? "group relative" : "",
939
- draggingColumnKey.value === String(col.key) ? unref(columnDraggingClass) : "",
940
- columnDropClass(colIndex),
941
- ...pinnedCellClass(col, colIndex)
1046
+ unref(draggingColumnKey) === String(col.key) ? unref(columnDraggingClass) : "",
1047
+ unref(columnDropClass)(colIndex),
1048
+ ...unref(pinnedCellClass)(col, colIndex)
942
1049
  ]]),
943
1050
  "data-column-key": col.key,
944
1051
  style: normalizeStyle({
945
- ...columnWidthStyle(widthOf(col)),
946
- ...pinnedStyleOf(col)
1052
+ ...columnWidthStyle(unref(widthOf)(col)),
1053
+ ...unref(pinnedStyleOf)(col)
947
1054
  }),
948
- "aria-sort": ariaSortFor(col),
1055
+ "aria-sort": unref(ariaSortFor)(col),
949
1056
  scope: "col"
950
1057
  }, [createElementVNode("div", { class: normalizeClass(["inline-flex items-center", headerGapClass.value]) }, [__props.reorderableColumns ? (openBlock(), createElementBlock("button", {
951
1058
  key: 0,
@@ -958,7 +1065,7 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
958
1065
  "aria-label": columnHandleLabel(col),
959
1066
  disabled: __props.loading,
960
1067
  onPointerdown: ($event) => unref(columnSort).startFrom(String(col.key))($event),
961
- onKeydown: ($event) => onColumnHandleKeydown($event, String(col.key)),
1068
+ onKeydown: ($event) => unref(onColumnHandleKeydown)($event, String(col.key)),
962
1069
  onFocus: ($event) => unref(columnRoving).setActive(String(col.key)),
963
1070
  onClick: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"]))
964
1071
  }, [createVNode(unref(grip_vertical_default), {
@@ -969,17 +1076,17 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
969
1076
  type: "button",
970
1077
  "data-gr-datatable-sort": "",
971
1078
  class: normalizeClass(["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)]", headerGapClass.value]),
972
- onClick: ($event) => toggleSort(col)
1079
+ onClick: ($event) => unref(toggleSort)(col)
973
1080
  }, [
974
1081
  createElementVNode("span", null, [renderSlot(_ctx.$slots, `header-${col.key}`, { column: col }, () => [createTextVNode(toDisplayString(col.label), 1)])]),
975
1082
  createElementVNode("span", _hoisted_6, toDisplayString(sortHint(col)), 1),
976
- createElementVNode("span", _hoisted_7, [currentSortKey.value === col.key && currentSortDir.value === "asc" ? (openBlock(), createBlock(GrIcon_default, {
1083
+ createElementVNode("span", _hoisted_7, [unref(currentSortKey) === col.key && unref(currentSortDir) === "asc" ? (openBlock(), createBlock(GrIcon_default, {
977
1084
  key: 0,
978
1085
  size: sortIconSize.value
979
1086
  }, {
980
1087
  default: withCtx(() => [createVNode(unref(arrow_up_default))]),
981
1088
  _: 1
982
- }, 8, ["size"])) : currentSortKey.value === col.key && currentSortDir.value === "desc" ? (openBlock(), createBlock(GrIcon_default, {
1089
+ }, 8, ["size"])) : unref(currentSortKey) === col.key && unref(currentSortDir) === "desc" ? (openBlock(), createBlock(GrIcon_default, {
983
1090
  key: 1,
984
1091
  size: sortIconSize.value
985
1092
  }, {
@@ -994,18 +1101,18 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
994
1101
  "aria-orientation": "vertical",
995
1102
  class: normalizeClass(unref(columnResizerClass)),
996
1103
  "aria-label": resizerLabel(col),
997
- "aria-valuenow": resizerValue(col),
998
- "aria-valuemin": MIN_COLUMN_WIDTH,
999
- "aria-valuetext": `${resizerValue(col)}px`,
1000
- onPointerdown: ($event) => onResizerPointerDown($event, String(col.key)),
1001
- onKeydown: ($event) => onResizerKeydown($event, String(col.key)),
1002
- onDblclick: ($event) => resetColumnWidth(String(col.key)),
1104
+ "aria-valuenow": unref(resizerValue)(col),
1105
+ "aria-valuemin": unref(48),
1106
+ "aria-valuetext": `${unref(resizerValue)(col)}px`,
1107
+ onPointerdown: ($event) => unref(onResizerPointerDown)($event, String(col.key)),
1108
+ onKeydown: ($event) => unref(onResizerKeydown)($event, String(col.key)),
1109
+ onDblclick: ($event) => unref(resetColumnWidth)(String(col.key)),
1003
1110
  onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"]))
1004
1111
  }, [createElementVNode("span", {
1005
1112
  class: normalizeClass([
1006
1113
  unref(columnResizerLineClass),
1007
1114
  unref(columnResizerHoverClass),
1008
- resizingKey.value === String(col.key) ? unref(columnResizerLineActiveClass) : ""
1115
+ unref(resizingKey) === String(col.key) ? unref(columnResizerLineActiveClass) : ""
1009
1116
  ]),
1010
1117
  "aria-hidden": "true"
1011
1118
  }, null, 2)], 42, _hoisted_9)) : createCommentVNode("", true)], 14, _hoisted_3);
@@ -1030,48 +1137,48 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
1030
1137
  }, null, 12, _hoisted_16)])) : createCommentVNode("", true),
1031
1138
  (openBlock(true), createElementBlock(Fragment, null, renderList(renderedRows.value, ({ row, index }) => {
1032
1139
  return openBlock(), createElementBlock("tr", mergeProps({
1033
- key: rowKeyValue(row),
1140
+ key: unref(rowKeyValue)(row),
1034
1141
  ref_for: true,
1035
1142
  ref: (el) => __props.virtual && unref(virtualizer).measure(index, el),
1036
- class: ["border-t border-[var(--gr-brd)]", [isRowSelected(row) ? unref(rowSelectedClass) : "", rowClassName(row, index)]],
1143
+ class: ["border-t border-[var(--gr-brd)]", [unref(isRowSelected)(row) ? unref(rowSelectedClass) : "", rowClassName(row, index)]],
1037
1144
  "data-gr-datatable-row": "",
1038
- "data-row-key": rowKeyValue(row),
1039
- "data-selected": __props.selectable && isRowSelected(row) ? "true" : void 0,
1145
+ "data-row-key": unref(rowKeyValue)(row),
1146
+ "data-selected": __props.selectable && unref(isRowSelected)(row) ? "true" : void 0,
1040
1147
  "aria-rowindex": ariaRowIndex(index)
1041
1148
  }, { ref_for: true }, __props.rowProps?.(row, index), { onClick: ($event) => onRowClick(row, index, $event) }), [__props.selectable ? (openBlock(), createElementBlock("td", {
1042
1149
  key: 0,
1043
1150
  class: normalizeClass(["text-left", [
1044
1151
  selectColumnClass.value,
1045
1152
  cellClass.value,
1046
- hasPinnedLeft.value ? unref(columnPinnedClass) : "",
1047
- hasPinnedLeft.value && isRowSelected(row) ? unref(rowSelectedClass) : ""
1153
+ unref(hasPinnedLeft) ? unref(columnPinnedClass) : "",
1154
+ unref(hasPinnedLeft) && unref(isRowSelected)(row) ? unref(rowSelectedClass) : ""
1048
1155
  ]]),
1049
- style: normalizeStyle(hasPinnedLeft.value ? { left: "0px" } : void 0)
1050
- }, [isRowSelectable(row) ? (openBlock(), createBlock(GrCheckbox_default, {
1156
+ style: normalizeStyle(unref(hasPinnedLeft) ? { left: "0px" } : void 0)
1157
+ }, [unref(isRowSelectable)(row) ? (openBlock(), createBlock(GrCheckbox_default, {
1051
1158
  key: 0,
1052
1159
  "data-gr-datatable-select-row": "",
1053
- "model-value": isRowSelected(row),
1160
+ "model-value": unref(isRowSelected)(row),
1054
1161
  size: checkboxSize.value,
1055
1162
  "aria-label": unref(t)("gr.dataTable.selectRow", "Select row"),
1056
1163
  onClick: _cache[2] || (_cache[2] = withModifiers(() => {}, ["stop"])),
1057
- "onUpdate:modelValue": ($event) => toggleRow(row)
1164
+ "onUpdate:modelValue": ($event) => unref(toggleRow)(row)
1058
1165
  }, null, 8, [
1059
1166
  "model-value",
1060
1167
  "size",
1061
1168
  "aria-label",
1062
1169
  "onUpdate:modelValue"
1063
- ])) : createCommentVNode("", true)], 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(orderedColumns.value, (col, colIndex) => {
1170
+ ])) : createCommentVNode("", true)], 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(orderedColumns), (col, colIndex) => {
1064
1171
  return openBlock(), createElementBlock("td", {
1065
1172
  key: col.key,
1066
1173
  class: normalizeClass([
1067
1174
  cellClass.value,
1068
1175
  cellAlign(col),
1069
- ...pinnedCellClass(col, colIndex),
1070
- col.pinned && isRowSelected(row) ? unref(rowSelectedClass) : ""
1176
+ ...unref(pinnedCellClass)(col, colIndex),
1177
+ col.pinned && unref(isRowSelected)(row) ? unref(rowSelectedClass) : ""
1071
1178
  ]),
1072
1179
  style: normalizeStyle({
1073
- ...columnWidthStyle(widthOf(col)),
1074
- ...pinnedStyleOf(col)
1180
+ ...columnWidthStyle(unref(widthOf)(col)),
1181
+ ...unref(pinnedStyleOf)(col)
1075
1182
  })
1076
1183
  }, [renderSlot(_ctx.$slots, `cell-${col.key}`, {
1077
1184
  row,
@@ -1101,28 +1208,28 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
1101
1208
  class: normalizeClass([
1102
1209
  selectColumnClass.value,
1103
1210
  cellClass.value,
1104
- hasPinnedLeft.value ? unref(columnPinnedClass) : ""
1211
+ unref(hasPinnedLeft) ? unref(columnPinnedClass) : ""
1105
1212
  ]),
1106
- style: normalizeStyle(hasPinnedLeft.value ? { left: "0px" } : void 0)
1107
- }, null, 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(orderedColumns.value, (col, colIndex) => {
1213
+ style: normalizeStyle(unref(hasPinnedLeft) ? { left: "0px" } : void 0)
1214
+ }, null, 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(orderedColumns), (col, colIndex) => {
1108
1215
  return openBlock(), createElementBlock("td", {
1109
1216
  key: col.key,
1110
1217
  "data-column-key": col.key,
1111
1218
  class: normalizeClass([
1112
1219
  cellClass.value,
1113
1220
  cellAlign(col),
1114
- ...pinnedCellClass(col, colIndex)
1221
+ ...unref(pinnedCellClass)(col, colIndex)
1115
1222
  ]),
1116
1223
  style: normalizeStyle({
1117
- ...columnWidthStyle(widthOf(col)),
1118
- ...pinnedStyleOf(col)
1224
+ ...columnWidthStyle(unref(widthOf)(col)),
1225
+ ...unref(pinnedStyleOf)(col)
1119
1226
  })
1120
1227
  }, [renderSlot(_ctx.$slots, `summary-${col.key}`, {
1121
1228
  value: summaryValue(col.key),
1122
1229
  column: col
1123
1230
  }, () => [createElementVNode("span", null, toDisplayString(summaryValue(col.key)), 1)])], 14, _hoisted_21);
1124
1231
  }), 128))], 10, _hoisted_20)) : createCommentVNode("", true), renderSlot(_ctx.$slots, "footer", {
1125
- columns: orderedColumns.value,
1232
+ columns: unref(orderedColumns),
1126
1233
  totalColumns: totalColumns.value
1127
1234
  })]),
1128
1235
  key: "0"