@ryuzaki13/react-foundation-lib 1.2.9 → 1.2.11
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.
- package/README.md +3 -1
- package/dist/table/cellSelection.d.ts +27 -0
- package/dist/table/cellSelection.d.ts.map +1 -0
- package/dist/table/index.d.ts +1 -0
- package/dist/table/index.d.ts.map +1 -1
- package/dist/table/index.js +84 -30
- package/dist/table/index.js.map +1 -1
- package/dist/table/selection.d.ts +4 -0
- package/dist/table/selection.d.ts.map +1 -1
- package/dist/table/types.d.ts +33 -0
- package/dist/table/types.d.ts.map +1 -1
- package/dist/table/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/docs/odataAndTables.mdx +2 -2
package/README.md
CHANGED
|
@@ -414,6 +414,8 @@ Pipeline — runtime форматирования ячейки. Он прини
|
|
|
414
414
|
| `normalizeTableColumnWidth`, `normalizeTableColumnSizing`, `patchTableColumnWidth`, `removeTableColumnWidth` | Column sizing с min width, default `60`. |
|
|
415
415
|
| `pruneTableRowSelection`, `toggleTableRowSelection` | `none`, `single`, `multi`; single не снимается повторным кликом. |
|
|
416
416
|
| `useTableRowSelection` | Hook поверх selection helpers. |
|
|
417
|
+
| `pruneTableCellSelection`, `toggleTableCellSelection` | Детерминированный выбор координат `rowId + columnId`. |
|
|
418
|
+
| `shouldActivateTableCellSelection` | Direct либо безопасная активация по Ctrl/Command без Shift/Alt. |
|
|
417
419
|
| `resolveTableColumnFormattingContextFromODataColumn` | OData column -> pipeline context; numeric types force measure. |
|
|
418
420
|
| `createTableColumnVisibilityFromODataMetadata` | Стартовая visibility; code скрывается, если есть text-пара. |
|
|
419
421
|
| `createTableColumnsFromODataMetadata` | Генерация TanStack columns из metadata. |
|
|
@@ -421,7 +423,7 @@ Pipeline — runtime форматирования ячейки. Он прини
|
|
|
421
423
|
| `resolveStableColumnId` | `id` или строковый `accessorKey`. |
|
|
422
424
|
| `getTableColumnMeta`, `getTableColumnFormattingMeta`, `resolveTableLength`, `isTableInteractiveElement` | Маленькие runtime helpers для таблиц. |
|
|
423
425
|
|
|
424
|
-
Тесты: [`columnLayout.test.ts`](./src/table/columnLayout.test.ts), [`columnOrder.test.ts`](./src/table/columnOrder.test.ts), [`columnSizing.test.ts`](./src/table/columnSizing.test.ts), [`selection.test.ts`](./src/table/selection.test.ts), [`odataAdapter.test.ts`](./src/table/odataAdapter.test.ts), [`utils.test.ts`](./src/table/utils.test.ts).
|
|
426
|
+
Тесты: [`columnLayout.test.ts`](./src/table/columnLayout.test.ts), [`columnOrder.test.ts`](./src/table/columnOrder.test.ts), [`columnSizing.test.ts`](./src/table/columnSizing.test.ts), [`selection.test.ts`](./src/table/selection.test.ts), [`cellSelection.test.ts`](./src/table/cellSelection.test.ts), [`odataAdapter.test.ts`](./src/table/odataAdapter.test.ts), [`utils.test.ts`](./src/table/utils.test.ts).
|
|
425
427
|
|
|
426
428
|
### `tree-table`
|
|
427
429
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type TableCellCoordinates, type TableCellSelectionActivationMode, type TableCellSelectionMode, type TableCellSelectionState, type TableSelectionModifierEvent } from "./types";
|
|
2
|
+
/** Проверяет равенство двух наборов координат без зависимости от порядка. */
|
|
3
|
+
export declare function areTableCellSelectionsEqual(left: TableCellSelectionState, right: TableCellSelectionState): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Оставляет только доступные координаты и приводит их к порядку строк/колонок.
|
|
6
|
+
*
|
|
7
|
+
* Функция не мутирует входные массивы. В `single` последняя координата в
|
|
8
|
+
* детерминированном порядке становится единственным выбранным значением.
|
|
9
|
+
*/
|
|
10
|
+
export declare function pruneTableCellSelection(selection: TableCellSelectionState | undefined, availableRowIds: readonly string[], availableColumnIds: readonly string[], selectionMode: TableCellSelectionMode): TableCellCoordinates[];
|
|
11
|
+
/**
|
|
12
|
+
* Вычисляет следующее состояние после активации ячейки.
|
|
13
|
+
*
|
|
14
|
+
* Одиночный выбор допускает явное снятие повторной активацией, а `multi`
|
|
15
|
+
* переключает только переданную координату.
|
|
16
|
+
*/
|
|
17
|
+
export declare function toggleTableCellSelection(selection: TableCellSelectionState, cell: TableCellCoordinates, selectionMode: TableCellSelectionMode): TableCellCoordinates[];
|
|
18
|
+
/** Нормализует способ активации ячейки на внешней config-boundary. */
|
|
19
|
+
export declare function normalizeTableCellSelectionActivationMode(value: unknown, fallback?: TableCellSelectionActivationMode): TableCellSelectionActivationMode;
|
|
20
|
+
/**
|
|
21
|
+
* Проверяет, должно ли событие активировать выбор ячейки.
|
|
22
|
+
*
|
|
23
|
+
* Для `primary-modifier` принимается Ctrl или Command, но не комбинации с
|
|
24
|
+
* Shift/Alt: они зарезервированы браузером, ОС и стандартными selection-flow.
|
|
25
|
+
*/
|
|
26
|
+
export declare function shouldActivateTableCellSelection(event: TableSelectionModifierEvent, activationMode: TableCellSelectionActivationMode): boolean;
|
|
27
|
+
//# sourceMappingURL=cellSelection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cellSelection.d.ts","sourceRoot":"","sources":["../../src/table/cellSelection.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,gCAAgC,EACrC,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,MAAM,SAAS,CAAC;AASjB,6EAA6E;AAC7E,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAOlH;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACtC,SAAS,EAAE,uBAAuB,GAAG,SAAS,EAC9C,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,kBAAkB,EAAE,SAAS,MAAM,EAAE,EACrC,aAAa,EAAE,sBAAsB,GACnC,oBAAoB,EAAE,CAqCxB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACvC,SAAS,EAAE,uBAAuB,EAClC,IAAI,EAAE,oBAAoB,EAC1B,aAAa,EAAE,sBAAsB,GACnC,oBAAoB,EAAE,CAaxB;AAED,sEAAsE;AACtE,wBAAgB,yCAAyC,CACxD,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,gCAA2C,GACnD,gCAAgC,CAIlC;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAC/C,KAAK,EAAE,2BAA2B,EAClC,cAAc,EAAE,gCAAgC,GAC9C,OAAO,CAMT"}
|
package/dist/table/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/table/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/table/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,SAAS,CAAC"}
|
package/dist/table/index.js
CHANGED
|
@@ -61,40 +61,78 @@ function v(e, t) {
|
|
|
61
61
|
return n;
|
|
62
62
|
}
|
|
63
63
|
//#endregion
|
|
64
|
+
//#region src/table/cellSelection.ts
|
|
65
|
+
var y = /* @__PURE__ */ new Set(["direct", "primary-modifier"]);
|
|
66
|
+
function b(e) {
|
|
67
|
+
return `${encodeURIComponent(e.rowId)}::${encodeURIComponent(e.columnId)}`;
|
|
68
|
+
}
|
|
69
|
+
function x(e, t) {
|
|
70
|
+
if (e.length !== t.length) return !1;
|
|
71
|
+
let n = new Set(t.map(b));
|
|
72
|
+
return e.every((e) => n.has(b(e)));
|
|
73
|
+
}
|
|
74
|
+
function S(e, t, n, r) {
|
|
75
|
+
if (r === "none" || !e?.length) return [];
|
|
76
|
+
let i = new Map(t.map((e, t) => [e, t])), a = new Map(n.map((e, t) => [e, t])), o = /* @__PURE__ */ new Set(), s = e.filter((e) => {
|
|
77
|
+
if (!(i.has(e.rowId) && a.has(e.columnId))) return !1;
|
|
78
|
+
let t = b(e);
|
|
79
|
+
return !o.has(t) && (o.add(t), !0);
|
|
80
|
+
}).sort((e, t) => {
|
|
81
|
+
let n = (i.get(e.rowId) ?? 0) - (i.get(t.rowId) ?? 0);
|
|
82
|
+
return n === 0 ? (a.get(e.columnId) ?? 0) - (a.get(t.columnId) ?? 0) : n;
|
|
83
|
+
});
|
|
84
|
+
if (r === "single") {
|
|
85
|
+
let e = s.at(-1);
|
|
86
|
+
return e ? [e] : [];
|
|
87
|
+
}
|
|
88
|
+
return s;
|
|
89
|
+
}
|
|
90
|
+
function C(e, t, n) {
|
|
91
|
+
if (n === "none") return [];
|
|
92
|
+
let r = b(t), i = e.some((e) => b(e) === r);
|
|
93
|
+
return n === "single" ? i ? [] : [t] : i ? e.filter((e) => b(e) !== r) : [...e, t];
|
|
94
|
+
}
|
|
95
|
+
function w(e, t = "direct") {
|
|
96
|
+
return typeof e == "string" && y.has(e) ? e : t;
|
|
97
|
+
}
|
|
98
|
+
function T(e, t) {
|
|
99
|
+
return t === "direct" || (e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey;
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
64
102
|
//#region src/table/odataAdapter.ts
|
|
65
|
-
function
|
|
103
|
+
function E(e) {
|
|
66
104
|
let { role: t, type: n } = e;
|
|
67
105
|
return {
|
|
68
106
|
role: n === "decimal" || n === "float" || n === "double" || n === "int" || n === "byte" ? "measure" : t,
|
|
69
107
|
type: n
|
|
70
108
|
};
|
|
71
109
|
}
|
|
72
|
-
function
|
|
110
|
+
function D(e) {
|
|
73
111
|
return e.role === "measure" ? "right" : "left";
|
|
74
112
|
}
|
|
75
|
-
function
|
|
113
|
+
function O(e, t) {
|
|
76
114
|
return e.semanticType !== "code" || !e.linkedColumnId || t.get(e.linkedColumnId)?.semanticType !== "text";
|
|
77
115
|
}
|
|
78
|
-
function
|
|
116
|
+
function k(e) {
|
|
79
117
|
if (typeof e.id == "string" && e.id.trim()) return e.id;
|
|
80
118
|
if ("accessorKey" in e && typeof e.accessorKey == "string" && e.accessorKey.trim()) return e.accessorKey;
|
|
81
119
|
}
|
|
82
|
-
function
|
|
120
|
+
function A(e, t) {
|
|
83
121
|
return e.map((e) => "columns" in e && Array.isArray(e.columns) && e.columns.length > 0 ? {
|
|
84
122
|
...e,
|
|
85
|
-
columns:
|
|
123
|
+
columns: A(e.columns, t)
|
|
86
124
|
} : t(e));
|
|
87
125
|
}
|
|
88
|
-
function
|
|
126
|
+
function j(e, t) {
|
|
89
127
|
let n = new Map(e.map((e) => [e.id, e]));
|
|
90
128
|
return Object.fromEntries(e.map((e) => {
|
|
91
|
-
let r = t?.resolveVisible?.(e) ??
|
|
129
|
+
let r = t?.resolveVisible?.(e) ?? O(e, n);
|
|
92
130
|
return [e.id, r];
|
|
93
131
|
}));
|
|
94
132
|
}
|
|
95
|
-
function
|
|
133
|
+
function M(e, t) {
|
|
96
134
|
return e.map((e) => {
|
|
97
|
-
let n =
|
|
135
|
+
let n = E(e), r = D(n), i = t?.resolveFormatting?.(e);
|
|
98
136
|
return {
|
|
99
137
|
id: e.id,
|
|
100
138
|
accessorKey: e.id,
|
|
@@ -111,17 +149,17 @@ function T(e, t) {
|
|
|
111
149
|
};
|
|
112
150
|
});
|
|
113
151
|
}
|
|
114
|
-
function
|
|
152
|
+
function N(e, t, n) {
|
|
115
153
|
let r = new Map(t.map((e) => [e.id, e]));
|
|
116
|
-
return
|
|
117
|
-
let t =
|
|
154
|
+
return A(e, (e) => {
|
|
155
|
+
let t = k(e);
|
|
118
156
|
if (!t) return e;
|
|
119
157
|
let i = n?.resolveMetadataColumn?.({
|
|
120
158
|
columnId: t,
|
|
121
159
|
metadataColumnsById: r
|
|
122
160
|
}) ?? r.get(t);
|
|
123
161
|
if (!i || e.meta?.formatting?.role && e.meta.formatting.type) return e;
|
|
124
|
-
let a =
|
|
162
|
+
let a = E(i);
|
|
125
163
|
return {
|
|
126
164
|
...e,
|
|
127
165
|
meta: {
|
|
@@ -138,21 +176,36 @@ function E(e, t, n) {
|
|
|
138
176
|
}
|
|
139
177
|
//#endregion
|
|
140
178
|
//#region src/table/selection.ts
|
|
141
|
-
|
|
179
|
+
var P = /* @__PURE__ */ new Set([
|
|
180
|
+
"none",
|
|
181
|
+
"single",
|
|
182
|
+
"multi"
|
|
183
|
+
]);
|
|
184
|
+
function F(e) {
|
|
142
185
|
return Object.keys(e).filter((t) => e[t]);
|
|
143
186
|
}
|
|
144
|
-
function
|
|
187
|
+
function I(e, t) {
|
|
188
|
+
let n = F(e), r = F(t);
|
|
189
|
+
return n.length === r.length && n.every((e) => t[e]);
|
|
190
|
+
}
|
|
191
|
+
function L(e, t = "none") {
|
|
192
|
+
return typeof e == "string" && P.has(e) ? e : t;
|
|
193
|
+
}
|
|
194
|
+
function R(e, t, n) {
|
|
145
195
|
if (n === "none") return {};
|
|
146
|
-
let r = new Set(t), i =
|
|
196
|
+
let r = new Set(t), i = F(e).filter((e) => r.has(e));
|
|
147
197
|
if (n === "single") {
|
|
148
198
|
let e = i.at(-1);
|
|
149
199
|
return e ? { [e]: !0 } : {};
|
|
150
200
|
}
|
|
151
201
|
return Object.fromEntries(i.map((e) => [e, !0]));
|
|
152
202
|
}
|
|
153
|
-
function
|
|
203
|
+
function z(e, t, n) {
|
|
154
204
|
if (n === "none") return {};
|
|
155
|
-
if (n === "single")
|
|
205
|
+
if (n === "single") {
|
|
206
|
+
let n = F(e);
|
|
207
|
+
return n.length === 1 && n[0] === t ? e : { [t]: !0 };
|
|
208
|
+
}
|
|
156
209
|
if (e[t]) {
|
|
157
210
|
let n = { ...e };
|
|
158
211
|
return delete n[t], n;
|
|
@@ -164,14 +217,14 @@ function k(e, t, n) {
|
|
|
164
217
|
}
|
|
165
218
|
//#endregion
|
|
166
219
|
//#region src/table/useTableRowSelection.ts
|
|
167
|
-
function
|
|
220
|
+
function B({ availableRowIds: e, rowById: t, selectionMode: n, selectedRowIds: c, onRowSelectionChange: l }) {
|
|
168
221
|
let [u, d] = s({}), f = o(!1), p = r((e, t) => {
|
|
169
222
|
let n = Object.keys(e).filter((t) => e[t]), r = Object.keys(t).filter((e) => t[e]);
|
|
170
223
|
return n.length === r.length && n.every((e) => t[e]);
|
|
171
224
|
}, []), m = a((e) => {
|
|
172
|
-
d((t) =>
|
|
225
|
+
d((t) => R(t, e, n));
|
|
173
226
|
}), h = a((e, t) => {
|
|
174
|
-
let r =
|
|
227
|
+
let r = R(Object.fromEntries(e.map((e) => [e, !0])), t, n);
|
|
175
228
|
d((e) => p(e, r) ? e : (f.current = !0, r));
|
|
176
229
|
}), g = a((e) => {
|
|
177
230
|
if (!l) return;
|
|
@@ -203,27 +256,28 @@ function A({ availableRowIds: e, rowById: t, selectionMode: n, selectedRowIds: c
|
|
|
203
256
|
rowSelection: u,
|
|
204
257
|
setRowSelection: d,
|
|
205
258
|
activateRowSelection: r((e, t) => {
|
|
206
|
-
n === "none" || !t || d((t) =>
|
|
259
|
+
n === "none" || !t || d((t) => z(t, e, n));
|
|
207
260
|
}, [n])
|
|
208
261
|
};
|
|
209
262
|
}
|
|
210
263
|
//#endregion
|
|
211
264
|
//#region src/table/utils.ts
|
|
212
|
-
|
|
265
|
+
var V = (/* @__PURE__ */ "button.a.input.select.textarea.label.summary.audio[controls].video[controls].[contenteditable]:not([contenteditable=\"false\"]).[tabindex]:not(td):not(th):not(tr).[draggable=\"true\"].[role=\"button\"].[role=\"link\"].[role=\"checkbox\"].[role=\"radio\"].[role=\"switch\"].[role=\"menu\"].[role=\"menuitem\"].[role=\"menuitemcheckbox\"].[role=\"menuitemradio\"].[role=\"listbox\"].[role=\"option\"].[role=\"tab\"].[role=\"tablist\"].[role=\"tree\"].[role=\"treeitem\"].[role=\"slider\"].[role=\"spinbutton\"].[role=\"textbox\"].[role=\"searchbox\"].[role=\"combobox\"]".split(".")).join(", ");
|
|
266
|
+
function H(e) {
|
|
213
267
|
return e.meta;
|
|
214
268
|
}
|
|
215
|
-
function
|
|
269
|
+
function U(e) {
|
|
216
270
|
return e.meta?.formatting;
|
|
217
271
|
}
|
|
218
|
-
function
|
|
272
|
+
function W(e) {
|
|
219
273
|
return typeof e == "number" ? `${e}em` : e;
|
|
220
274
|
}
|
|
221
|
-
function
|
|
275
|
+
function G(e, t) {
|
|
222
276
|
if (!(e instanceof HTMLElement)) return !1;
|
|
223
|
-
let n =
|
|
224
|
-
return !!e.closest(
|
|
277
|
+
let n = t ? `${V}, ${t}` : V;
|
|
278
|
+
return !!e.closest(n);
|
|
225
279
|
}
|
|
226
280
|
//#endregion
|
|
227
|
-
export { m as DEFAULT_TABLE_COLUMN_MIN_WIDTH, l as buildTableColumnLayout,
|
|
281
|
+
export { m as DEFAULT_TABLE_COLUMN_MIN_WIDTH, x as areTableCellSelectionsEqual, I as areTableRowSelectionsEqual, l as buildTableColumnLayout, j as createTableColumnVisibilityFromODataMetadata, M as createTableColumnsFromODataMetadata, N as enrichTableColumnsWithODataFormatting, U as getTableColumnFormattingMeta, H as getTableColumnMeta, G as isTableInteractiveElement, w as normalizeTableCellSelectionActivationMode, u as normalizeTableColumnOrder, g as normalizeTableColumnSizing, h as normalizeTableColumnWidth, L as normalizeTableSelectionMode, _ as patchTableColumnWidth, S as pruneTableCellSelection, R as pruneTableRowSelection, v as removeTableColumnWidth, f as reorderTableHeaderColumns, p as resolveReorderedTableHeaderColumns, k as resolveStableColumnId, E as resolveTableColumnFormattingContextFromODataColumn, c as resolveTableColumnOrder, W as resolveTableLength, T as shouldActivateTableCellSelection, C as toggleTableCellSelection, z as toggleTableRowSelection, B as useTableRowSelection };
|
|
228
282
|
|
|
229
283
|
//# sourceMappingURL=index.js.map
|
package/dist/table/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/table/columnLayout.ts","../../src/table/columnOrder.ts","../../src/table/columnSizing.ts","../../src/table/odataAdapter.ts","../../src/table/selection.ts","../../src/table/useTableRowSelection.ts","../../src/table/utils.ts"],"sourcesContent":["import { appendMissingIds, filterAndDeduplicateIds } from \"../array\";\n\nexport type TableColumnLayoutItem<TColumnId extends string = string, TWidth = number> = {\n\tid: TColumnId;\n\twidth: TWidth;\n};\n\nexport type ResolveTableColumnOrderArgs<TColumnId extends string = string> = {\n\tids: readonly TColumnId[];\n\torder?: readonly string[];\n};\n\nexport type BuildTableColumnLayoutArgs<TColumnId extends string = string, TWidth = number> = {\n\tids: readonly TColumnId[];\n\tgetWidth: (id: TColumnId) => TWidth;\n};\n\n/**\n * Возвращает порядок колонок как в AnalyticalTable: сначала сохранённый order,\n * затем новые или отсутствующие в order id. Ширины при этом остаются привязаны\n * к columnId, а не к визуальной позиции.\n */\nexport function resolveTableColumnOrder<TColumnId extends string>({ ids, order }: ResolveTableColumnOrderArgs<TColumnId>): TColumnId[] {\n\treturn appendMissingIds(filterAndDeduplicateIds(order, ids), ids);\n}\n\n/**\n * Строит layout колонок из уже вычисленного порядка и функции ширины по id.\n */\nexport function buildTableColumnLayout<TColumnId extends string, TWidth>({\n\tids,\n\tgetWidth\n}: BuildTableColumnLayoutArgs<TColumnId, TWidth>): TableColumnLayoutItem<TColumnId, TWidth>[] {\n\treturn ids.map((id) => ({\n\t\tid,\n\t\twidth: getWidth(id)\n\t}));\n}\n","import { arraysEqual } from \"../array\";\n\nexport type ReorderTableHeaderColumnsArgs = {\n\torder: readonly string[];\n\theaderIds: readonly string[];\n\tlockedIds?: readonly string[];\n\tpinnedIds?: readonly string[];\n\tactiveId: string;\n\toverId: string;\n};\n\nexport type TableColumnOrderState = string[];\n\nexport function normalizeTableColumnOrder(order: readonly string[] | undefined): TableColumnOrderState {\n\treturn Array.from(new Set((order ?? []).filter((columnId) => columnId.trim().length > 0)));\n}\n\nfunction moveItem<T>(items: readonly T[], fromIndex: number, toIndex: number): T[] {\n\tconst nextItems = [...items];\n\tconst [item] = nextItems.splice(fromIndex, 1);\n\n\tif (item === undefined) {\n\t\treturn nextItems;\n\t}\n\n\tnextItems.splice(toIndex, 0, item);\n\treturn nextItems;\n}\n\n/**\n * Переставляет только верхнеуровневые колонки табличной шапки.\n *\n * Ограничения:\n * - дочерние колонки групп не являются самостоятельными draggable-элементами;\n * - locked-колонки остаются в фиксированном порядке;\n * - pinned-колонки не переносятся между закреплённой и обычной зонами.\n */\nexport function reorderTableHeaderColumns(args: ReorderTableHeaderColumnsArgs): string[] {\n\tconst { activeId, overId, order } = args;\n\tif (!activeId || !overId || activeId === overId) return [...order];\n\n\tconst headerSet = new Set(args.headerIds);\n\tif (!headerSet.has(activeId) || !headerSet.has(overId)) return [...order];\n\n\tconst lockedSet = new Set(args.lockedIds ?? []);\n\tif (lockedSet.has(activeId) || lockedSet.has(overId)) return [...order];\n\n\tconst pinnedSet = new Set(args.pinnedIds ?? []);\n\tif (pinnedSet.has(activeId) || pinnedSet.has(overId)) return [...order];\n\n\tconst nextOrder = [...order];\n\tif (!nextOrder.includes(activeId)) {\n\t\tnextOrder.push(activeId);\n\t}\n\tif (!nextOrder.includes(overId)) {\n\t\tnextOrder.push(overId);\n\t}\n\n\tconst fromIndex = nextOrder.indexOf(activeId);\n\tconst toIndex = nextOrder.indexOf(overId);\n\tif (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) return nextOrder;\n\n\treturn moveItem(nextOrder, fromIndex, toIndex);\n}\n\nexport function resolveReorderedTableHeaderColumns(args: ReorderTableHeaderColumnsArgs): string[] | null {\n\tconst nextOrder = reorderTableHeaderColumns(args);\n\n\treturn arraysEqual(nextOrder, args.order) ? null : nextOrder;\n}\n","export type TableColumnSizingState = Record<string, number>;\n\nexport const DEFAULT_TABLE_COLUMN_MIN_WIDTH = 60;\n\nexport function normalizeTableColumnWidth(px: number, minWidth: number = DEFAULT_TABLE_COLUMN_MIN_WIDTH): number {\n\tconst normalizedMinWidth = Number.isFinite(minWidth) && minWidth > 0 ? Math.floor(minWidth) : DEFAULT_TABLE_COLUMN_MIN_WIDTH;\n\tconst normalizedWidth = Number.isFinite(px) ? Math.floor(px) : normalizedMinWidth;\n\n\treturn Math.max(normalizedMinWidth, normalizedWidth);\n}\n\nexport function normalizeTableColumnSizing(\n\tstate: Readonly<Record<string, number>> | undefined,\n\tminWidth: number = DEFAULT_TABLE_COLUMN_MIN_WIDTH\n): TableColumnSizingState {\n\tconst nextState: TableColumnSizingState = {};\n\n\tfor (const [columnId, width] of Object.entries(state ?? {})) {\n\t\tif (typeof columnId !== \"string\" || columnId.trim().length === 0 || !Number.isFinite(width)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tnextState[columnId] = normalizeTableColumnWidth(width, minWidth);\n\t}\n\n\treturn nextState;\n}\n\nexport function patchTableColumnWidth(\n\tstate: Readonly<Record<string, number>>,\n\tcolumnId: string,\n\twidth: number,\n\tminWidth: number = DEFAULT_TABLE_COLUMN_MIN_WIDTH\n): TableColumnSizingState {\n\tif (columnId.trim().length === 0) {\n\t\treturn normalizeTableColumnSizing(state, minWidth);\n\t}\n\n\treturn {\n\t\t...normalizeTableColumnSizing(state, minWidth),\n\t\t[columnId]: normalizeTableColumnWidth(width, minWidth)\n\t};\n}\n\nexport function removeTableColumnWidth(state: Readonly<Record<string, number>>, columnId: string): TableColumnSizingState {\n\tconst nextState: TableColumnSizingState = {};\n\n\tfor (const [key, width] of Object.entries(state)) {\n\t\tif (key !== columnId) {\n\t\t\tnextState[key] = width;\n\t\t}\n\t}\n\n\treturn nextState;\n}\n","import type { FormattersPipelineTypedValueContext } from \"../formatters/pipeline\";\nimport type { EntityColumnProperty } from \"../odata-service\";\nimport type { TableColumnAlign, TableColumnDef, TableColumnFormattingMetaInput } from \"./types\";\n\n/**\n * Опции генерации колонок по OData metadata.\n */\nexport interface CreateTableColumnsFromODataMetadataOptions {\n\t/**\n\t * Позволяет переопределить заголовок колонки.\n\t */\n\tresolveHeader?: (column: EntityColumnProperty) => string;\n\t/**\n\t * Позволяет сразу навесить formatting-конфиг на generated column.\n\t *\n\t * `id`, `role` и `type` будут автоматически получены из metadata.\n\t */\n\tresolveFormatting?: (column: EntityColumnProperty) => TableColumnFormattingMetaInput | undefined;\n}\n\n/**\n * Опции обогащения уже существующих колонок данными OData metadata.\n */\nexport interface EnrichTableColumnsWithODataFormattingOptions {\n\t/**\n\t * Позволяет подменить стратегию поиска metadata по колонке.\n\t */\n\tresolveMetadataColumn?: (args: {\n\t\tcolumnId: string;\n\t\tmetadataColumnsById: ReadonlyMap<string, EntityColumnProperty>;\n\t}) => EntityColumnProperty | undefined;\n}\n\n/**\n * Опции построения стартовой карты видимости колонок по OData metadata.\n */\nexport interface CreateTableColumnVisibilityFromODataMetadataOptions {\n\t/**\n\t * Позволяет явно переопределить стартовую видимость колонки.\n\t */\n\tresolveVisible?: (column: EntityColumnProperty) => boolean;\n}\n\n/**\n * Возвращает typed-formatting контекст по metadata OData-колонки.\n */\nexport function resolveTableColumnFormattingContextFromODataColumn(column: EntityColumnProperty): FormattersPipelineTypedValueContext {\n\tconst { role, type } = column;\n\tconst forceMeasure = type === \"decimal\" || type === \"float\" || type === \"double\" || type === \"int\" || type === \"byte\";\n\n\treturn {\n\t\trole: forceMeasure ? \"measure\" : role,\n\t\ttype: type\n\t};\n}\n\n/**\n * Создаёт базовое выравнивание по семантике OData-колонки.\n *\n * NOTE: \"не аналитические\" все поля возвращают как \"dimension\"...\n */\nfunction resolveTableColumnAlignFromODataColumn(columnContext: FormattersPipelineTypedValueContext): TableColumnAlign {\n\treturn columnContext.role === \"measure\" ? \"right\" : \"left\";\n}\n\n/**\n * Определяет видимость metadata-колонки по умолчанию.\n *\n * Кодовые поля скрываются только если у них есть явная text-пара,\n * чтобы экран по умолчанию показывал человекочитаемое значение.\n */\nfunction resolveMetadataColumnVisibleByDefault(\n\tcolumn: EntityColumnProperty,\n\tmetadataColumnsById: ReadonlyMap<string, EntityColumnProperty>\n): boolean {\n\tif (column.semanticType !== \"code\" || !column.linkedColumnId) {\n\t\treturn true;\n\t}\n\n\tconst linkedColumn = metadataColumnsById.get(column.linkedColumnId);\n\n\treturn linkedColumn?.semanticType !== \"text\";\n}\n\n/**\n * Определяет стабильный идентификатор колонки для сопоставления с metadata.\n */\nexport function resolveStableColumnId<TData extends object>(column: TableColumnDef<TData>): string | undefined {\n\tif (typeof column.id === \"string\" && column.id.trim()) {\n\t\treturn column.id;\n\t}\n\n\tif (\"accessorKey\" in column && typeof column.accessorKey === \"string\" && column.accessorKey.trim()) {\n\t\treturn column.accessorKey;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Рекурсивно обходит только leaf-колонки.\n */\nfunction mapLeafTableColumns<TData extends object>(\n\tcolumns: readonly TableColumnDef<TData>[],\n\tmapper: (column: TableColumnDef<TData>) => TableColumnDef<TData>\n): TableColumnDef<TData>[] {\n\treturn columns.map((column) => {\n\t\tif (\"columns\" in column && Array.isArray(column.columns) && column.columns.length > 0) {\n\t\t\treturn {\n\t\t\t\t...column,\n\t\t\t\tcolumns: mapLeafTableColumns(column.columns as TableColumnDef<TData>[], mapper)\n\t\t\t};\n\t\t}\n\n\t\treturn mapper(column);\n\t});\n}\n\n/**\n * Строит стартовую карту видимости колонок из metadata OData-сущности.\n *\n * Возвращает visibility-state для TanStack Table, не удаляя сами колонки\n * из результата build-режима.\n */\nexport function createTableColumnVisibilityFromODataMetadata(\n\tmetadataColumns: readonly EntityColumnProperty[],\n\toptions?: CreateTableColumnVisibilityFromODataMetadataOptions\n): Record<string, boolean> {\n\tconst metadataColumnsById = new Map(metadataColumns.map((column) => [column.id, column]));\n\n\treturn Object.fromEntries(\n\t\tmetadataColumns.map((column) => {\n\t\t\tconst visible = options?.resolveVisible?.(column) ?? resolveMetadataColumnVisibleByDefault(column, metadataColumnsById);\n\n\t\t\treturn [column.id, visible];\n\t\t})\n\t);\n}\n\n/**\n * Создаёт базовые generic-колонки из metadata OData-сущности.\n */\nexport function createTableColumnsFromODataMetadata<TData extends object = Record<string, unknown>>(\n\tmetadataColumns: readonly EntityColumnProperty[],\n\toptions?: CreateTableColumnsFromODataMetadataOptions\n): TableColumnDef<TData>[] {\n\treturn metadataColumns.map((metadataColumn) => {\n\t\t// NOTE: Ячейка сама определит выравнивание, `align` только для переопределения\n\t\tconst columnContext = resolveTableColumnFormattingContextFromODataColumn(metadataColumn);\n\t\tconst align = resolveTableColumnAlignFromODataColumn(columnContext);\n\t\tconst resolvedFormatting = options?.resolveFormatting?.(metadataColumn);\n\n\t\treturn {\n\t\t\tid: metadataColumn.id,\n\t\t\taccessorKey: metadataColumn.id,\n\t\t\theader: options?.resolveHeader?.(metadataColumn) ?? metadataColumn.label ?? metadataColumn.id,\n\t\t\tmeta: {\n\t\t\t\talign,\n\t\t\t\tformatting: {\n\t\t\t\t\t...resolvedFormatting,\n\t\t\t\t\tid: metadataColumn.id,\n\t\t\t\t\trole: columnContext.role,\n\t\t\t\t\ttype: columnContext.type\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}) as TableColumnDef<TData>[];\n}\n\n/**\n * Дозаполняет уже существующие колонки typed-formatting контекстом из OData metadata.\n */\nexport function enrichTableColumnsWithODataFormatting<TData extends object>(\n\tcolumns: readonly TableColumnDef<TData>[],\n\tmetadataColumns: readonly EntityColumnProperty[],\n\toptions?: EnrichTableColumnsWithODataFormattingOptions\n): TableColumnDef<TData>[] {\n\tconst metadataColumnsById = new Map(metadataColumns.map((column) => [column.id, column]));\n\n\treturn mapLeafTableColumns(columns, (column) => {\n\t\tconst columnId = resolveStableColumnId(column);\n\t\tif (!columnId) {\n\t\t\treturn column;\n\t\t}\n\n\t\tconst metadataColumn =\n\t\t\toptions?.resolveMetadataColumn?.({\n\t\t\t\tcolumnId,\n\t\t\t\tmetadataColumnsById\n\t\t\t}) ?? metadataColumnsById.get(columnId);\n\n\t\tif (!metadataColumn) {\n\t\t\treturn column;\n\t\t}\n\n\t\tif (column.meta?.formatting?.role && column.meta.formatting.type) {\n\t\t\treturn column;\n\t\t}\n\t\tconst columnContext = resolveTableColumnFormattingContextFromODataColumn(metadataColumn);\n\n\t\treturn {\n\t\t\t...column,\n\t\t\tmeta: {\n\t\t\t\t...column.meta,\n\t\t\t\tformatting: {\n\t\t\t\t\t...column.meta?.formatting,\n\t\t\t\t\tid: columnId,\n\t\t\t\t\trole: columnContext.role,\n\t\t\t\t\ttype: columnContext.type\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n","import { RowSelectionState } from \"@tanstack/react-table\";\n\nimport { TableSelectionMode } from \"./types\";\n\n/**\n * Возвращает только активные идентификаторы выбранных строк.\n */\nfunction getSelectedRowIds(selection: RowSelectionState): string[] {\n\treturn Object.keys(selection).filter((rowId) => selection[rowId]);\n}\n\n/**\n * Нормализует состояние выбора относительно списка доступных строк и текущего режима.\n */\nexport function pruneTableRowSelection(\n\tselection: RowSelectionState,\n\tavailableRowIds: readonly string[],\n\tselectionMode: TableSelectionMode\n): RowSelectionState {\n\tif (selectionMode === \"none\") {\n\t\treturn {};\n\t}\n\n\tconst availableRowIdSet = new Set(availableRowIds);\n\tconst selectedRowIds = getSelectedRowIds(selection).filter((rowId) => availableRowIdSet.has(rowId));\n\n\tif (selectionMode === \"single\") {\n\t\tconst lastSelectedRowId = selectedRowIds.at(-1);\n\n\t\treturn lastSelectedRowId ? { [lastSelectedRowId]: true } : {};\n\t}\n\n\treturn Object.fromEntries(selectedRowIds.map((rowId) => [rowId, true]));\n}\n\n/**\n * Вычисляет следующее состояние выбора после активации строки пользователем.\n *\n * Семантика:\n * - `none` не хранит выбор;\n * - `single` всегда оставляет только одну строку и не снимает выбор повторным кликом;\n * - `multi` переключает строку как toggle.\n */\nexport function toggleTableRowSelection(selection: RowSelectionState, rowId: string, selectionMode: TableSelectionMode): RowSelectionState {\n\tif (selectionMode === \"none\") {\n\t\treturn {};\n\t}\n\n\tif (selectionMode === \"single\") {\n\t\treturn selection[rowId] ? selection : { [rowId]: true };\n\t}\n\n\tif (selection[rowId]) {\n\t\tconst nextSelection = { ...selection };\n\n\t\tdelete nextSelection[rowId];\n\n\t\treturn nextSelection;\n\t}\n\n\treturn {\n\t\t...selection,\n\t\t[rowId]: true\n\t};\n}\n","import { useCallback, useEffect, useEffectEvent, useRef, useState } from \"react\";\n\nimport { RowSelectionState } from \"@tanstack/react-table\";\n\nimport { pruneTableRowSelection, toggleTableRowSelection } from \"./selection\";\nimport { TableSelectionMode } from \"./types\";\n\ninterface UseTableRowSelectionParams<TData extends object> {\n\tavailableRowIds: readonly string[];\n\trowById: Map<string, TData>;\n\tselectionMode: TableSelectionMode;\n\tselectedRowIds?: readonly string[];\n\tonRowSelectionChange?: (rows: TData[]) => void;\n}\n\n/**\n * Общая модель выбора строк для плоской и древовидной таблиц.\n */\nexport function useTableRowSelection<TData extends object>({\n\tavailableRowIds,\n\trowById,\n\tselectionMode,\n\tselectedRowIds,\n\tonRowSelectionChange\n}: UseTableRowSelectionParams<TData>) {\n\tconst [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\tconst shouldSkipNextSelectionEmitRef = useRef(false);\n\n\t/**\n\t * Сравнивает состояния выбора без лишних перерисовок.\n\t */\n\tconst areSelectionsEqual = useCallback((left: RowSelectionState, right: RowSelectionState) => {\n\t\tconst leftRowIds = Object.keys(left).filter((rowId) => left[rowId]);\n\t\tconst rightRowIds = Object.keys(right).filter((rowId) => right[rowId]);\n\n\t\tif (leftRowIds.length !== rightRowIds.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn leftRowIds.every((rowId) => right[rowId]);\n\n\t\t/*\n\n Более оптимизированная версия, но для текущего случая может быть практически незначительной\n\n let leftCount = 0;\n\t\tlet rightCount = 0;\n\n\t\tfor (const rowId of Object.keys(left)) {\n\t\t\tif (!left[rowId]) continue;\n\t\t\tleftCount += 1;\n\t\t\tif (!right[rowId]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfor (const rowId of Object.keys(right)) {\n\t\t\tif (right[rowId]) {\n\t\t\t\trightCount += 1;\n\t\t\t}\n\t\t}\n\n\t\tif (leftCount !== rightCount) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\n */\n\t}, []);\n\n\tconst syncRowSelectionState = useEffectEvent((nextAvailableRowIds: readonly string[]) => {\n\t\tsetRowSelection((currentSelection) => pruneTableRowSelection(currentSelection, nextAvailableRowIds, selectionMode));\n\t});\n\n\tconst syncControlledRowSelectionState = useEffectEvent(\n\t\t(nextSelectedRowIds: readonly string[], nextAvailableRowIds: readonly string[]) => {\n\t\t\tconst nextSelection = pruneTableRowSelection(\n\t\t\t\tObject.fromEntries(nextSelectedRowIds.map((rowId) => [rowId, true])),\n\t\t\t\tnextAvailableRowIds,\n\t\t\t\tselectionMode\n\t\t\t);\n\n\t\t\tsetRowSelection((currentSelection) => {\n\t\t\t\tif (areSelectionsEqual(currentSelection, nextSelection)) {\n\t\t\t\t\treturn currentSelection;\n\t\t\t\t}\n\n\t\t\t\t// Пропускаем следующий emit, потому что это синхронизация от внешнего controlled-состояния,\n\t\t\t\t// а не пользовательское изменение выбора внутри таблицы.\n\t\t\t\tshouldSkipNextSelectionEmitRef.current = true;\n\n\t\t\t\treturn nextSelection;\n\t\t\t});\n\t\t}\n\t);\n\n\tconst emitRowSelectionChange = useEffectEvent((currentSelection: RowSelectionState) => {\n\t\tif (!onRowSelectionChange) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst selectedRows: TData[] = [];\n\n\t\tfor (const rowId of Object.keys(currentSelection)) {\n\t\t\tif (!currentSelection[rowId]) continue;\n\n\t\t\tconst row = rowById.get(rowId);\n\t\t\tif (row) {\n\t\t\t\tselectedRows.push(row);\n\t\t\t}\n\t\t}\n\n\t\tonRowSelectionChange(selectedRows);\n\t});\n\n\tuseEffect(() => {\n\t\tif (selectedRowIds !== undefined) {\n\t\t\tsyncControlledRowSelectionState(selectedRowIds, availableRowIds);\n\t\t\treturn;\n\t\t}\n\n\t\tsyncRowSelectionState(availableRowIds);\n\t}, [availableRowIds, selectedRowIds, selectionMode]);\n\n\tuseEffect(() => {\n\t\tif (shouldSkipNextSelectionEmitRef.current) {\n\t\t\tshouldSkipNextSelectionEmitRef.current = false;\n\t\t\treturn;\n\t\t}\n\n\t\temitRowSelectionChange(rowSelection);\n\t}, [rowSelection]);\n\n\t/**\n\t * Применяет изменение выбора при активации конкретной строки.\n\t */\n\tconst activateRowSelection = useCallback(\n\t\t(rowId: string, canSelect: boolean) => {\n\t\t\tif (selectionMode === \"none\" || !canSelect) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetRowSelection((currentSelection) => toggleTableRowSelection(currentSelection, rowId, selectionMode));\n\t\t},\n\t\t[selectionMode]\n\t);\n\n\treturn {\n\t\trowSelection,\n\t\tsetRowSelection,\n\t\tactivateRowSelection\n\t};\n}\n","import { TableColumnDef, TableColumnFormattingMeta, TableColumnMeta } from \"./types\";\n\n/**\n * Возвращает метаданные колонки таблицы.\n */\nexport function getTableColumnMeta<TData extends object>(column: TableColumnDef<TData>): TableColumnMeta | undefined {\n\treturn column.meta;\n}\n\n/**\n * Возвращает форматирующий блок метаданных колонки.\n */\nexport function getTableColumnFormattingMeta<TData extends object>(column: TableColumnDef<TData>): TableColumnFormattingMeta | undefined {\n\treturn column.meta?.formatting;\n}\n\n/**\n * Нормализует размер таблицы.\n *\n * Числовое значение трактуется как `em`, чтобы разметка масштабировалась вместе со шрифтом.\n */\nexport function resolveTableLength(length: string | number): string {\n\tif (typeof length === \"number\") {\n\t\treturn `${length}em`;\n\t}\n\n\treturn length;\n}\n\n/**\n * Определяет, пришёл ли клик из интерактивного элемента внутри таблицы.\n */\nexport function isTableInteractiveElement(target: EventTarget | null, extraSelector?: string): boolean {\n\tif (!(target instanceof HTMLElement)) {\n\t\treturn false;\n\t}\n\n\tconst baseSelector = 'button, a, input, select, textarea, [role=\"button\"], [role=\"link\"]';\n\tconst selector = extraSelector ? `${baseSelector}, ${extraSelector}` : baseSelector;\n\n\treturn Boolean(target.closest(selector));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/table/columnLayout.ts","../../src/table/columnOrder.ts","../../src/table/columnSizing.ts","../../src/table/cellSelection.ts","../../src/table/odataAdapter.ts","../../src/table/selection.ts","../../src/table/useTableRowSelection.ts","../../src/table/utils.ts"],"sourcesContent":["import { appendMissingIds, filterAndDeduplicateIds } from \"../array\";\n\nexport type TableColumnLayoutItem<TColumnId extends string = string, TWidth = number> = {\n\tid: TColumnId;\n\twidth: TWidth;\n};\n\nexport type ResolveTableColumnOrderArgs<TColumnId extends string = string> = {\n\tids: readonly TColumnId[];\n\torder?: readonly string[];\n};\n\nexport type BuildTableColumnLayoutArgs<TColumnId extends string = string, TWidth = number> = {\n\tids: readonly TColumnId[];\n\tgetWidth: (id: TColumnId) => TWidth;\n};\n\n/**\n * Возвращает порядок колонок как в AnalyticalTable: сначала сохранённый order,\n * затем новые или отсутствующие в order id. Ширины при этом остаются привязаны\n * к columnId, а не к визуальной позиции.\n */\nexport function resolveTableColumnOrder<TColumnId extends string>({ ids, order }: ResolveTableColumnOrderArgs<TColumnId>): TColumnId[] {\n\treturn appendMissingIds(filterAndDeduplicateIds(order, ids), ids);\n}\n\n/**\n * Строит layout колонок из уже вычисленного порядка и функции ширины по id.\n */\nexport function buildTableColumnLayout<TColumnId extends string, TWidth>({\n\tids,\n\tgetWidth\n}: BuildTableColumnLayoutArgs<TColumnId, TWidth>): TableColumnLayoutItem<TColumnId, TWidth>[] {\n\treturn ids.map((id) => ({\n\t\tid,\n\t\twidth: getWidth(id)\n\t}));\n}\n","import { arraysEqual } from \"../array\";\n\nexport type ReorderTableHeaderColumnsArgs = {\n\torder: readonly string[];\n\theaderIds: readonly string[];\n\tlockedIds?: readonly string[];\n\tpinnedIds?: readonly string[];\n\tactiveId: string;\n\toverId: string;\n};\n\nexport type TableColumnOrderState = string[];\n\nexport function normalizeTableColumnOrder(order: readonly string[] | undefined): TableColumnOrderState {\n\treturn Array.from(new Set((order ?? []).filter((columnId) => columnId.trim().length > 0)));\n}\n\nfunction moveItem<T>(items: readonly T[], fromIndex: number, toIndex: number): T[] {\n\tconst nextItems = [...items];\n\tconst [item] = nextItems.splice(fromIndex, 1);\n\n\tif (item === undefined) {\n\t\treturn nextItems;\n\t}\n\n\tnextItems.splice(toIndex, 0, item);\n\treturn nextItems;\n}\n\n/**\n * Переставляет только верхнеуровневые колонки табличной шапки.\n *\n * Ограничения:\n * - дочерние колонки групп не являются самостоятельными draggable-элементами;\n * - locked-колонки остаются в фиксированном порядке;\n * - pinned-колонки не переносятся между закреплённой и обычной зонами.\n */\nexport function reorderTableHeaderColumns(args: ReorderTableHeaderColumnsArgs): string[] {\n\tconst { activeId, overId, order } = args;\n\tif (!activeId || !overId || activeId === overId) return [...order];\n\n\tconst headerSet = new Set(args.headerIds);\n\tif (!headerSet.has(activeId) || !headerSet.has(overId)) return [...order];\n\n\tconst lockedSet = new Set(args.lockedIds ?? []);\n\tif (lockedSet.has(activeId) || lockedSet.has(overId)) return [...order];\n\n\tconst pinnedSet = new Set(args.pinnedIds ?? []);\n\tif (pinnedSet.has(activeId) || pinnedSet.has(overId)) return [...order];\n\n\tconst nextOrder = [...order];\n\tif (!nextOrder.includes(activeId)) {\n\t\tnextOrder.push(activeId);\n\t}\n\tif (!nextOrder.includes(overId)) {\n\t\tnextOrder.push(overId);\n\t}\n\n\tconst fromIndex = nextOrder.indexOf(activeId);\n\tconst toIndex = nextOrder.indexOf(overId);\n\tif (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) return nextOrder;\n\n\treturn moveItem(nextOrder, fromIndex, toIndex);\n}\n\nexport function resolveReorderedTableHeaderColumns(args: ReorderTableHeaderColumnsArgs): string[] | null {\n\tconst nextOrder = reorderTableHeaderColumns(args);\n\n\treturn arraysEqual(nextOrder, args.order) ? null : nextOrder;\n}\n","export type TableColumnSizingState = Record<string, number>;\n\nexport const DEFAULT_TABLE_COLUMN_MIN_WIDTH = 60;\n\nexport function normalizeTableColumnWidth(px: number, minWidth: number = DEFAULT_TABLE_COLUMN_MIN_WIDTH): number {\n\tconst normalizedMinWidth = Number.isFinite(minWidth) && minWidth > 0 ? Math.floor(minWidth) : DEFAULT_TABLE_COLUMN_MIN_WIDTH;\n\tconst normalizedWidth = Number.isFinite(px) ? Math.floor(px) : normalizedMinWidth;\n\n\treturn Math.max(normalizedMinWidth, normalizedWidth);\n}\n\nexport function normalizeTableColumnSizing(\n\tstate: Readonly<Record<string, number>> | undefined,\n\tminWidth: number = DEFAULT_TABLE_COLUMN_MIN_WIDTH\n): TableColumnSizingState {\n\tconst nextState: TableColumnSizingState = {};\n\n\tfor (const [columnId, width] of Object.entries(state ?? {})) {\n\t\tif (typeof columnId !== \"string\" || columnId.trim().length === 0 || !Number.isFinite(width)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tnextState[columnId] = normalizeTableColumnWidth(width, minWidth);\n\t}\n\n\treturn nextState;\n}\n\nexport function patchTableColumnWidth(\n\tstate: Readonly<Record<string, number>>,\n\tcolumnId: string,\n\twidth: number,\n\tminWidth: number = DEFAULT_TABLE_COLUMN_MIN_WIDTH\n): TableColumnSizingState {\n\tif (columnId.trim().length === 0) {\n\t\treturn normalizeTableColumnSizing(state, minWidth);\n\t}\n\n\treturn {\n\t\t...normalizeTableColumnSizing(state, minWidth),\n\t\t[columnId]: normalizeTableColumnWidth(width, minWidth)\n\t};\n}\n\nexport function removeTableColumnWidth(state: Readonly<Record<string, number>>, columnId: string): TableColumnSizingState {\n\tconst nextState: TableColumnSizingState = {};\n\n\tfor (const [key, width] of Object.entries(state)) {\n\t\tif (key !== columnId) {\n\t\t\tnextState[key] = width;\n\t\t}\n\t}\n\n\treturn nextState;\n}\n","import {\n\ttype TableCellCoordinates,\n\ttype TableCellSelectionActivationMode,\n\ttype TableCellSelectionMode,\n\ttype TableCellSelectionState,\n\ttype TableSelectionModifierEvent\n} from \"./types\";\n\nconst TABLE_CELL_SELECTION_ACTIVATION_MODES: ReadonlySet<TableCellSelectionActivationMode> = new Set([\"direct\", \"primary-modifier\"]);\n\n/** Строит collision-safe identity координат для дедупликации и сравнения. */\nfunction buildTableCellKey(cell: TableCellCoordinates): string {\n\treturn `${encodeURIComponent(cell.rowId)}::${encodeURIComponent(cell.columnId)}`;\n}\n\n/** Проверяет равенство двух наборов координат без зависимости от порядка. */\nexport function areTableCellSelectionsEqual(left: TableCellSelectionState, right: TableCellSelectionState): boolean {\n\tif (left.length !== right.length) {\n\t\treturn false;\n\t}\n\n\tconst rightKeys = new Set(right.map(buildTableCellKey));\n\treturn left.every((cell) => rightKeys.has(buildTableCellKey(cell)));\n}\n\n/**\n * Оставляет только доступные координаты и приводит их к порядку строк/колонок.\n *\n * Функция не мутирует входные массивы. В `single` последняя координата в\n * детерминированном порядке становится единственным выбранным значением.\n */\nexport function pruneTableCellSelection(\n\tselection: TableCellSelectionState | undefined,\n\tavailableRowIds: readonly string[],\n\tavailableColumnIds: readonly string[],\n\tselectionMode: TableCellSelectionMode\n): TableCellCoordinates[] {\n\tif (selectionMode === \"none\" || !selection?.length) {\n\t\treturn [];\n\t}\n\n\tconst rowOrder = new Map(availableRowIds.map((rowId, index) => [rowId, index]));\n\tconst columnOrder = new Map(availableColumnIds.map((columnId, index) => [columnId, index]));\n\tconst seen = new Set<string>();\n\tconst nextSelection = selection\n\t\t.filter((cell) => {\n\t\t\tif (!(rowOrder.has(cell.rowId) && columnOrder.has(cell.columnId))) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst key = buildTableCellKey(cell);\n\t\t\tif (seen.has(key)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tseen.add(key);\n\t\t\treturn true;\n\t\t})\n\t\t.sort((left, right) => {\n\t\t\tconst rowDelta = (rowOrder.get(left.rowId) ?? 0) - (rowOrder.get(right.rowId) ?? 0);\n\t\t\tif (rowDelta !== 0) {\n\t\t\t\treturn rowDelta;\n\t\t\t}\n\n\t\t\treturn (columnOrder.get(left.columnId) ?? 0) - (columnOrder.get(right.columnId) ?? 0);\n\t\t});\n\n\tif (selectionMode === \"single\") {\n\t\tconst lastCell = nextSelection.at(-1);\n\t\treturn lastCell ? [lastCell] : [];\n\t}\n\n\treturn nextSelection;\n}\n\n/**\n * Вычисляет следующее состояние после активации ячейки.\n *\n * Одиночный выбор допускает явное снятие повторной активацией, а `multi`\n * переключает только переданную координату.\n */\nexport function toggleTableCellSelection(\n\tselection: TableCellSelectionState,\n\tcell: TableCellCoordinates,\n\tselectionMode: TableCellSelectionMode\n): TableCellCoordinates[] {\n\tif (selectionMode === \"none\") {\n\t\treturn [];\n\t}\n\n\tconst cellKey = buildTableCellKey(cell);\n\tconst hasCell = selection.some((item) => buildTableCellKey(item) === cellKey);\n\n\tif (selectionMode === \"single\") {\n\t\treturn hasCell ? [] : [cell];\n\t}\n\n\treturn hasCell ? selection.filter((item) => buildTableCellKey(item) !== cellKey) : [...selection, cell];\n}\n\n/** Нормализует способ активации ячейки на внешней config-boundary. */\nexport function normalizeTableCellSelectionActivationMode(\n\tvalue: unknown,\n\tfallback: TableCellSelectionActivationMode = \"direct\"\n): TableCellSelectionActivationMode {\n\treturn typeof value === \"string\" && TABLE_CELL_SELECTION_ACTIVATION_MODES.has(value as TableCellSelectionActivationMode)\n\t\t? (value as TableCellSelectionActivationMode)\n\t\t: fallback;\n}\n\n/**\n * Проверяет, должно ли событие активировать выбор ячейки.\n *\n * Для `primary-modifier` принимается Ctrl или Command, но не комбинации с\n * Shift/Alt: они зарезервированы браузером, ОС и стандартными selection-flow.\n */\nexport function shouldActivateTableCellSelection(\n\tevent: TableSelectionModifierEvent,\n\tactivationMode: TableCellSelectionActivationMode\n): boolean {\n\tif (activationMode === \"direct\") {\n\t\treturn true;\n\t}\n\n\treturn (event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey;\n}\n","import type { FormattersPipelineTypedValueContext } from \"../formatters/pipeline\";\nimport type { EntityColumnProperty } from \"../odata-service\";\nimport type { TableColumnAlign, TableColumnDef, TableColumnFormattingMetaInput } from \"./types\";\n\n/**\n * Опции генерации колонок по OData metadata.\n */\nexport interface CreateTableColumnsFromODataMetadataOptions {\n\t/**\n\t * Позволяет переопределить заголовок колонки.\n\t */\n\tresolveHeader?: (column: EntityColumnProperty) => string;\n\t/**\n\t * Позволяет сразу навесить formatting-конфиг на generated column.\n\t *\n\t * `id`, `role` и `type` будут автоматически получены из metadata.\n\t */\n\tresolveFormatting?: (column: EntityColumnProperty) => TableColumnFormattingMetaInput | undefined;\n}\n\n/**\n * Опции обогащения уже существующих колонок данными OData metadata.\n */\nexport interface EnrichTableColumnsWithODataFormattingOptions {\n\t/**\n\t * Позволяет подменить стратегию поиска metadata по колонке.\n\t */\n\tresolveMetadataColumn?: (args: {\n\t\tcolumnId: string;\n\t\tmetadataColumnsById: ReadonlyMap<string, EntityColumnProperty>;\n\t}) => EntityColumnProperty | undefined;\n}\n\n/**\n * Опции построения стартовой карты видимости колонок по OData metadata.\n */\nexport interface CreateTableColumnVisibilityFromODataMetadataOptions {\n\t/**\n\t * Позволяет явно переопределить стартовую видимость колонки.\n\t */\n\tresolveVisible?: (column: EntityColumnProperty) => boolean;\n}\n\n/**\n * Возвращает typed-formatting контекст по metadata OData-колонки.\n */\nexport function resolveTableColumnFormattingContextFromODataColumn(column: EntityColumnProperty): FormattersPipelineTypedValueContext {\n\tconst { role, type } = column;\n\tconst forceMeasure = type === \"decimal\" || type === \"float\" || type === \"double\" || type === \"int\" || type === \"byte\";\n\n\treturn {\n\t\trole: forceMeasure ? \"measure\" : role,\n\t\ttype: type\n\t};\n}\n\n/**\n * Создаёт базовое выравнивание по семантике OData-колонки.\n *\n * NOTE: \"не аналитические\" все поля возвращают как \"dimension\"...\n */\nfunction resolveTableColumnAlignFromODataColumn(columnContext: FormattersPipelineTypedValueContext): TableColumnAlign {\n\treturn columnContext.role === \"measure\" ? \"right\" : \"left\";\n}\n\n/**\n * Определяет видимость metadata-колонки по умолчанию.\n *\n * Кодовые поля скрываются только если у них есть явная text-пара,\n * чтобы экран по умолчанию показывал человекочитаемое значение.\n */\nfunction resolveMetadataColumnVisibleByDefault(\n\tcolumn: EntityColumnProperty,\n\tmetadataColumnsById: ReadonlyMap<string, EntityColumnProperty>\n): boolean {\n\tif (column.semanticType !== \"code\" || !column.linkedColumnId) {\n\t\treturn true;\n\t}\n\n\tconst linkedColumn = metadataColumnsById.get(column.linkedColumnId);\n\n\treturn linkedColumn?.semanticType !== \"text\";\n}\n\n/**\n * Определяет стабильный идентификатор колонки для сопоставления с metadata.\n */\nexport function resolveStableColumnId<TData extends object>(column: TableColumnDef<TData>): string | undefined {\n\tif (typeof column.id === \"string\" && column.id.trim()) {\n\t\treturn column.id;\n\t}\n\n\tif (\"accessorKey\" in column && typeof column.accessorKey === \"string\" && column.accessorKey.trim()) {\n\t\treturn column.accessorKey;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Рекурсивно обходит только leaf-колонки.\n */\nfunction mapLeafTableColumns<TData extends object>(\n\tcolumns: readonly TableColumnDef<TData>[],\n\tmapper: (column: TableColumnDef<TData>) => TableColumnDef<TData>\n): TableColumnDef<TData>[] {\n\treturn columns.map((column) => {\n\t\tif (\"columns\" in column && Array.isArray(column.columns) && column.columns.length > 0) {\n\t\t\treturn {\n\t\t\t\t...column,\n\t\t\t\tcolumns: mapLeafTableColumns(column.columns as TableColumnDef<TData>[], mapper)\n\t\t\t};\n\t\t}\n\n\t\treturn mapper(column);\n\t});\n}\n\n/**\n * Строит стартовую карту видимости колонок из metadata OData-сущности.\n *\n * Возвращает visibility-state для TanStack Table, не удаляя сами колонки\n * из результата build-режима.\n */\nexport function createTableColumnVisibilityFromODataMetadata(\n\tmetadataColumns: readonly EntityColumnProperty[],\n\toptions?: CreateTableColumnVisibilityFromODataMetadataOptions\n): Record<string, boolean> {\n\tconst metadataColumnsById = new Map(metadataColumns.map((column) => [column.id, column]));\n\n\treturn Object.fromEntries(\n\t\tmetadataColumns.map((column) => {\n\t\t\tconst visible = options?.resolveVisible?.(column) ?? resolveMetadataColumnVisibleByDefault(column, metadataColumnsById);\n\n\t\t\treturn [column.id, visible];\n\t\t})\n\t);\n}\n\n/**\n * Создаёт базовые generic-колонки из metadata OData-сущности.\n */\nexport function createTableColumnsFromODataMetadata<TData extends object = Record<string, unknown>>(\n\tmetadataColumns: readonly EntityColumnProperty[],\n\toptions?: CreateTableColumnsFromODataMetadataOptions\n): TableColumnDef<TData>[] {\n\treturn metadataColumns.map((metadataColumn) => {\n\t\t// NOTE: Ячейка сама определит выравнивание, `align` только для переопределения\n\t\tconst columnContext = resolveTableColumnFormattingContextFromODataColumn(metadataColumn);\n\t\tconst align = resolveTableColumnAlignFromODataColumn(columnContext);\n\t\tconst resolvedFormatting = options?.resolveFormatting?.(metadataColumn);\n\n\t\treturn {\n\t\t\tid: metadataColumn.id,\n\t\t\taccessorKey: metadataColumn.id,\n\t\t\theader: options?.resolveHeader?.(metadataColumn) ?? metadataColumn.label ?? metadataColumn.id,\n\t\t\tmeta: {\n\t\t\t\talign,\n\t\t\t\tformatting: {\n\t\t\t\t\t...resolvedFormatting,\n\t\t\t\t\tid: metadataColumn.id,\n\t\t\t\t\trole: columnContext.role,\n\t\t\t\t\ttype: columnContext.type\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}) as TableColumnDef<TData>[];\n}\n\n/**\n * Дозаполняет уже существующие колонки typed-formatting контекстом из OData metadata.\n */\nexport function enrichTableColumnsWithODataFormatting<TData extends object>(\n\tcolumns: readonly TableColumnDef<TData>[],\n\tmetadataColumns: readonly EntityColumnProperty[],\n\toptions?: EnrichTableColumnsWithODataFormattingOptions\n): TableColumnDef<TData>[] {\n\tconst metadataColumnsById = new Map(metadataColumns.map((column) => [column.id, column]));\n\n\treturn mapLeafTableColumns(columns, (column) => {\n\t\tconst columnId = resolveStableColumnId(column);\n\t\tif (!columnId) {\n\t\t\treturn column;\n\t\t}\n\n\t\tconst metadataColumn =\n\t\t\toptions?.resolveMetadataColumn?.({\n\t\t\t\tcolumnId,\n\t\t\t\tmetadataColumnsById\n\t\t\t}) ?? metadataColumnsById.get(columnId);\n\n\t\tif (!metadataColumn) {\n\t\t\treturn column;\n\t\t}\n\n\t\tif (column.meta?.formatting?.role && column.meta.formatting.type) {\n\t\t\treturn column;\n\t\t}\n\t\tconst columnContext = resolveTableColumnFormattingContextFromODataColumn(metadataColumn);\n\n\t\treturn {\n\t\t\t...column,\n\t\t\tmeta: {\n\t\t\t\t...column.meta,\n\t\t\t\tformatting: {\n\t\t\t\t\t...column.meta?.formatting,\n\t\t\t\t\tid: columnId,\n\t\t\t\t\trole: columnContext.role,\n\t\t\t\t\ttype: columnContext.type\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n","import { RowSelectionState } from \"@tanstack/react-table\";\n\nimport { TableSelectionMode } from \"./types\";\n\nconst TABLE_SELECTION_MODES: ReadonlySet<TableSelectionMode> = new Set([\"none\", \"single\", \"multi\"]);\n\n/**\n * Возвращает только активные идентификаторы выбранных строк.\n */\nfunction getSelectedRowIds(selection: RowSelectionState): string[] {\n\treturn Object.keys(selection).filter((rowId) => selection[rowId]);\n}\n\n/** Проверяет равенство активных row-selection идентификаторов без учёта порядка ключей. */\nexport function areTableRowSelectionsEqual(left: RowSelectionState, right: RowSelectionState): boolean {\n\tconst leftRowIds = getSelectedRowIds(left);\n\tconst rightRowIds = getSelectedRowIds(right);\n\n\tif (leftRowIds.length !== rightRowIds.length) {\n\t\treturn false;\n\t}\n\n\treturn leftRowIds.every((rowId) => right[rowId]);\n}\n\n/** Нормализует неизвестное значение режима выбора строк на внешней config-boundary. */\nexport function normalizeTableSelectionMode(value: unknown, fallback: TableSelectionMode = \"none\"): TableSelectionMode {\n\treturn typeof value === \"string\" && TABLE_SELECTION_MODES.has(value as TableSelectionMode) ? (value as TableSelectionMode) : fallback;\n}\n\n/**\n * Нормализует состояние выбора относительно списка доступных строк и текущего режима.\n */\nexport function pruneTableRowSelection(\n\tselection: RowSelectionState,\n\tavailableRowIds: readonly string[],\n\tselectionMode: TableSelectionMode\n): RowSelectionState {\n\tif (selectionMode === \"none\") {\n\t\treturn {};\n\t}\n\n\tconst availableRowIdSet = new Set(availableRowIds);\n\tconst selectedRowIds = getSelectedRowIds(selection).filter((rowId) => availableRowIdSet.has(rowId));\n\n\tif (selectionMode === \"single\") {\n\t\tconst lastSelectedRowId = selectedRowIds.at(-1);\n\n\t\treturn lastSelectedRowId ? { [lastSelectedRowId]: true } : {};\n\t}\n\n\treturn Object.fromEntries(selectedRowIds.map((rowId) => [rowId, true]));\n}\n\n/**\n * Вычисляет следующее состояние выбора после активации строки пользователем.\n *\n * Семантика:\n * - `none` не хранит выбор;\n * - `single` всегда оставляет только одну строку и не снимает выбор повторным кликом;\n * - `multi` переключает строку как toggle.\n */\nexport function toggleTableRowSelection(selection: RowSelectionState, rowId: string, selectionMode: TableSelectionMode): RowSelectionState {\n\tif (selectionMode === \"none\") {\n\t\treturn {};\n\t}\n\n\tif (selectionMode === \"single\") {\n\t\tconst selectedRowIds = getSelectedRowIds(selection);\n\t\treturn selectedRowIds.length === 1 && selectedRowIds[0] === rowId ? selection : { [rowId]: true };\n\t}\n\n\tif (selection[rowId]) {\n\t\tconst nextSelection = { ...selection };\n\n\t\tdelete nextSelection[rowId];\n\n\t\treturn nextSelection;\n\t}\n\n\treturn {\n\t\t...selection,\n\t\t[rowId]: true\n\t};\n}\n","import { useCallback, useEffect, useEffectEvent, useRef, useState } from \"react\";\n\nimport { RowSelectionState } from \"@tanstack/react-table\";\n\nimport { pruneTableRowSelection, toggleTableRowSelection } from \"./selection\";\nimport { TableSelectionMode } from \"./types\";\n\ninterface UseTableRowSelectionParams<TData extends object> {\n\tavailableRowIds: readonly string[];\n\trowById: Map<string, TData>;\n\tselectionMode: TableSelectionMode;\n\tselectedRowIds?: readonly string[];\n\tonRowSelectionChange?: (rows: TData[]) => void;\n}\n\n/**\n * Общая модель выбора строк для плоской и древовидной таблиц.\n */\nexport function useTableRowSelection<TData extends object>({\n\tavailableRowIds,\n\trowById,\n\tselectionMode,\n\tselectedRowIds,\n\tonRowSelectionChange\n}: UseTableRowSelectionParams<TData>) {\n\tconst [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\tconst shouldSkipNextSelectionEmitRef = useRef(false);\n\n\t/**\n\t * Сравнивает состояния выбора без лишних перерисовок.\n\t */\n\tconst areSelectionsEqual = useCallback((left: RowSelectionState, right: RowSelectionState) => {\n\t\tconst leftRowIds = Object.keys(left).filter((rowId) => left[rowId]);\n\t\tconst rightRowIds = Object.keys(right).filter((rowId) => right[rowId]);\n\n\t\tif (leftRowIds.length !== rightRowIds.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn leftRowIds.every((rowId) => right[rowId]);\n\n\t\t/*\n\n Более оптимизированная версия, но для текущего случая может быть практически незначительной\n\n let leftCount = 0;\n\t\tlet rightCount = 0;\n\n\t\tfor (const rowId of Object.keys(left)) {\n\t\t\tif (!left[rowId]) continue;\n\t\t\tleftCount += 1;\n\t\t\tif (!right[rowId]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfor (const rowId of Object.keys(right)) {\n\t\t\tif (right[rowId]) {\n\t\t\t\trightCount += 1;\n\t\t\t}\n\t\t}\n\n\t\tif (leftCount !== rightCount) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\n */\n\t}, []);\n\n\tconst syncRowSelectionState = useEffectEvent((nextAvailableRowIds: readonly string[]) => {\n\t\tsetRowSelection((currentSelection) => pruneTableRowSelection(currentSelection, nextAvailableRowIds, selectionMode));\n\t});\n\n\tconst syncControlledRowSelectionState = useEffectEvent(\n\t\t(nextSelectedRowIds: readonly string[], nextAvailableRowIds: readonly string[]) => {\n\t\t\tconst nextSelection = pruneTableRowSelection(\n\t\t\t\tObject.fromEntries(nextSelectedRowIds.map((rowId) => [rowId, true])),\n\t\t\t\tnextAvailableRowIds,\n\t\t\t\tselectionMode\n\t\t\t);\n\n\t\t\tsetRowSelection((currentSelection) => {\n\t\t\t\tif (areSelectionsEqual(currentSelection, nextSelection)) {\n\t\t\t\t\treturn currentSelection;\n\t\t\t\t}\n\n\t\t\t\t// Пропускаем следующий emit, потому что это синхронизация от внешнего controlled-состояния,\n\t\t\t\t// а не пользовательское изменение выбора внутри таблицы.\n\t\t\t\tshouldSkipNextSelectionEmitRef.current = true;\n\n\t\t\t\treturn nextSelection;\n\t\t\t});\n\t\t}\n\t);\n\n\tconst emitRowSelectionChange = useEffectEvent((currentSelection: RowSelectionState) => {\n\t\tif (!onRowSelectionChange) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst selectedRows: TData[] = [];\n\n\t\tfor (const rowId of Object.keys(currentSelection)) {\n\t\t\tif (!currentSelection[rowId]) continue;\n\n\t\t\tconst row = rowById.get(rowId);\n\t\t\tif (row) {\n\t\t\t\tselectedRows.push(row);\n\t\t\t}\n\t\t}\n\n\t\tonRowSelectionChange(selectedRows);\n\t});\n\n\tuseEffect(() => {\n\t\tif (selectedRowIds !== undefined) {\n\t\t\tsyncControlledRowSelectionState(selectedRowIds, availableRowIds);\n\t\t\treturn;\n\t\t}\n\n\t\tsyncRowSelectionState(availableRowIds);\n\t}, [availableRowIds, selectedRowIds, selectionMode]);\n\n\tuseEffect(() => {\n\t\tif (shouldSkipNextSelectionEmitRef.current) {\n\t\t\tshouldSkipNextSelectionEmitRef.current = false;\n\t\t\treturn;\n\t\t}\n\n\t\temitRowSelectionChange(rowSelection);\n\t}, [rowSelection]);\n\n\t/**\n\t * Применяет изменение выбора при активации конкретной строки.\n\t */\n\tconst activateRowSelection = useCallback(\n\t\t(rowId: string, canSelect: boolean) => {\n\t\t\tif (selectionMode === \"none\" || !canSelect) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetRowSelection((currentSelection) => toggleTableRowSelection(currentSelection, rowId, selectionMode));\n\t\t},\n\t\t[selectionMode]\n\t);\n\n\treturn {\n\t\trowSelection,\n\t\tsetRowSelection,\n\t\tactivateRowSelection\n\t};\n}\n","import { TableColumnDef, TableColumnFormattingMeta, TableColumnMeta } from \"./types\";\n\n/**\n * Интерактивные descendants, действие которых таблица не должна подменять\n * выбором строки или ячейки.\n *\n * `td`, `th` и `tr` намеренно исключены из tabindex-ветки: сама таблица может\n * использовать roving tabindex для selection, не превращая ячейку в nested control.\n */\nconst TABLE_INTERACTIVE_ELEMENT_SELECTOR = [\n\t\"button\",\n\t\"a\",\n\t\"input\",\n\t\"select\",\n\t\"textarea\",\n\t\"label\",\n\t\"summary\",\n\t\"audio[controls]\",\n\t\"video[controls]\",\n\t'[contenteditable]:not([contenteditable=\"false\"])',\n\t\"[tabindex]:not(td):not(th):not(tr)\",\n\t'[draggable=\"true\"]',\n\t'[role=\"button\"]',\n\t'[role=\"link\"]',\n\t'[role=\"checkbox\"]',\n\t'[role=\"radio\"]',\n\t'[role=\"switch\"]',\n\t'[role=\"menu\"]',\n\t'[role=\"menuitem\"]',\n\t'[role=\"menuitemcheckbox\"]',\n\t'[role=\"menuitemradio\"]',\n\t'[role=\"listbox\"]',\n\t'[role=\"option\"]',\n\t'[role=\"tab\"]',\n\t'[role=\"tablist\"]',\n\t'[role=\"tree\"]',\n\t'[role=\"treeitem\"]',\n\t'[role=\"slider\"]',\n\t'[role=\"spinbutton\"]',\n\t'[role=\"textbox\"]',\n\t'[role=\"searchbox\"]',\n\t'[role=\"combobox\"]'\n].join(\", \");\n\n/**\n * Возвращает метаданные колонки таблицы.\n */\nexport function getTableColumnMeta<TData extends object>(column: TableColumnDef<TData>): TableColumnMeta | undefined {\n\treturn column.meta;\n}\n\n/**\n * Возвращает форматирующий блок метаданных колонки.\n */\nexport function getTableColumnFormattingMeta<TData extends object>(column: TableColumnDef<TData>): TableColumnFormattingMeta | undefined {\n\treturn column.meta?.formatting;\n}\n\n/**\n * Нормализует размер таблицы.\n *\n * Числовое значение трактуется как `em`, чтобы разметка масштабировалась вместе со шрифтом.\n */\nexport function resolveTableLength(length: string | number): string {\n\tif (typeof length === \"number\") {\n\t\treturn `${length}em`;\n\t}\n\n\treturn length;\n}\n\n/**\n * Определяет, пришёл ли клик из интерактивного элемента внутри таблицы.\n */\nexport function isTableInteractiveElement(target: EventTarget | null, extraSelector?: string): boolean {\n\tif (!(target instanceof HTMLElement)) {\n\t\treturn false;\n\t}\n\n\tconst selector = extraSelector ? `${TABLE_INTERACTIVE_ELEMENT_SELECTOR}, ${extraSelector}` : TABLE_INTERACTIVE_ELEMENT_SELECTOR;\n\n\treturn Boolean(target.closest(selector));\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { RowSelectionState } from "@tanstack/react-table";
|
|
2
2
|
import { TableSelectionMode } from "./types";
|
|
3
|
+
/** Проверяет равенство активных row-selection идентификаторов без учёта порядка ключей. */
|
|
4
|
+
export declare function areTableRowSelectionsEqual(left: RowSelectionState, right: RowSelectionState): boolean;
|
|
5
|
+
/** Нормализует неизвестное значение режима выбора строк на внешней config-boundary. */
|
|
6
|
+
export declare function normalizeTableSelectionMode(value: unknown, fallback?: TableSelectionMode): TableSelectionMode;
|
|
3
7
|
/**
|
|
4
8
|
* Нормализует состояние выбора относительно списка доступных строк и текущего режима.
|
|
5
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/table/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/table/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAW7C,2FAA2F;AAC3F,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CASrG;AAED,uFAAuF;AACvF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,GAAE,kBAA2B,GAAG,kBAAkB,CAErH;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACrC,SAAS,EAAE,iBAAiB,EAC5B,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,aAAa,EAAE,kBAAkB,GAC/B,iBAAiB,CAenB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,GAAG,iBAAiB,CAsBzI"}
|
package/dist/table/types.d.ts
CHANGED
|
@@ -4,6 +4,39 @@ import { type FormattersPipelineRuntimeField } from "../formatters/pipeline";
|
|
|
4
4
|
* Режим выбора строк таблицы.
|
|
5
5
|
*/
|
|
6
6
|
export type TableSelectionMode = "none" | "single" | "multi";
|
|
7
|
+
/**
|
|
8
|
+
* Режим выбора ячеек таблицы.
|
|
9
|
+
*
|
|
10
|
+
* Отдельное имя сохраняет назначение настройки, хотя допустимая кардинальность
|
|
11
|
+
* совпадает с режимами выбора строк.
|
|
12
|
+
*/
|
|
13
|
+
export type TableCellSelectionMode = TableSelectionMode;
|
|
14
|
+
/**
|
|
15
|
+
* Способ активации выбора ячейки пользовательским событием.
|
|
16
|
+
*
|
|
17
|
+
* `primary-modifier` означает Ctrl в Windows/Linux и Command в macOS. Такой
|
|
18
|
+
* контракт не привязывает consumer к конкретной платформе или клавиатуре.
|
|
19
|
+
*/
|
|
20
|
+
export type TableCellSelectionActivationMode = "direct" | "primary-modifier";
|
|
21
|
+
/** Устойчивые координаты выбранной ячейки без привязки к DOM или TanStack Row. */
|
|
22
|
+
export type TableCellCoordinates = Readonly<{
|
|
23
|
+
rowId: string;
|
|
24
|
+
columnId: string;
|
|
25
|
+
}>;
|
|
26
|
+
/** Сериализуемое состояние выбора ячеек. */
|
|
27
|
+
export type TableCellSelectionState = readonly TableCellCoordinates[];
|
|
28
|
+
/**
|
|
29
|
+
* Минимальный event-like контракт для проверки клавиш-модификаторов.
|
|
30
|
+
*
|
|
31
|
+
* Структурный тип позволяет использовать один helper для React mouse/keyboard
|
|
32
|
+
* events и для unit-тестов без зависимости алгоритма от DOM-классов.
|
|
33
|
+
*/
|
|
34
|
+
export type TableSelectionModifierEvent = Readonly<{
|
|
35
|
+
ctrlKey: boolean;
|
|
36
|
+
metaKey: boolean;
|
|
37
|
+
shiftKey: boolean;
|
|
38
|
+
altKey: boolean;
|
|
39
|
+
}>;
|
|
7
40
|
/**
|
|
8
41
|
* Выравнивание содержимого ячейки таблицы.
|
|
9
42
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/table/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,KAAK,4BAA4B,GAAG,IAAI,CACvC,8BAA8B,EAC9B,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,iBAAiB,GAAG,4BAA4B,CACzE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,4BAA4B,GACnE,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;AAEvE;;;GAGG;AACH,MAAM,MAAM,8BAA8B,GAAG,4BAA4B,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC;IAEvC;;OAEG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAEzB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,UAAU,CAAC,EAAE,yBAAyB,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,SAAS,MAAM,EAAE,MAAM,GAAG,OAAO,IAAI,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG;IAC/F,IAAI,CAAC,EAAE,eAAe,CAAC;CACvB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/table/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,GAAG,kBAAkB,CAAC;AAE7E,kFAAkF;AAClF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,4CAA4C;AAC5C,MAAM,MAAM,uBAAuB,GAAG,SAAS,oBAAoB,EAAE,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CAChB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,KAAK,4BAA4B,GAAG,IAAI,CACvC,8BAA8B,EAC9B,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,iBAAiB,GAAG,4BAA4B,CACzE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,4BAA4B,GACnE,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;AAEvE;;;GAGG;AACH,MAAM,MAAM,8BAA8B,GAAG,4BAA4B,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC;IAEvC;;OAEG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAEzB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,UAAU,CAAC,EAAE,yBAAyB,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,SAAS,MAAM,EAAE,MAAM,GAAG,OAAO,IAAI,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG;IAC/F,IAAI,CAAC,EAAE,eAAe,CAAC;CACvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/table/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/table/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA4CrF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,SAAS,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,eAAe,GAAG,SAAS,CAEnH;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,SAAS,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,yBAAyB,GAAG,SAAS,CAEvI;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAMlE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAQrG"}
|
package/package.json
CHANGED
|
@@ -107,10 +107,10 @@ import { buildTableColumnLayout, createTableColumnsFromODataMetadata, useTableRo
|
|
|
107
107
|
| Layout | `resolveTableColumnOrder`, `buildTableColumnLayout`, `TableColumnLayoutItem`, `BuildTableColumnLayoutArgs`. |
|
|
108
108
|
| Order | `normalizeTableColumnOrder`, `reorderTableHeaderColumns`, `resolveReorderedTableHeaderColumns`, `TableColumnOrderState`. |
|
|
109
109
|
| Sizing | `DEFAULT_TABLE_COLUMN_MIN_WIDTH`, `normalizeTableColumnWidth`, `normalizeTableColumnSizing`, `patchTableColumnWidth`, `removeTableColumnWidth`, `TableColumnSizingState`. |
|
|
110
|
-
| Selection |
|
|
110
|
+
| Selection | Row/cell modes, pruning/toggle helpers, `shouldActivateTableCellSelection`, `useTableRowSelection`. |
|
|
111
111
|
| Metadata | `getTableColumnMeta`, `getTableColumnFormattingMeta`, `resolveTableLength`, `isTableInteractiveElement`. |
|
|
112
112
|
|
|
113
|
-
`useTableRowSelection` синхронизирует selection state с TanStack Table. Передавайте устойчивый `getRowId` на business identity, не array index: изменяемая сортировка/фильтрация иначе свяжет selection с неверной строкой.
|
|
113
|
+
`useTableRowSelection` синхронизирует selection state с TanStack Table. Передавайте устойчивый `getRowId` на business identity, не array index: изменяемая сортировка/фильтрация иначе свяжет selection с неверной строкой. Cell-selection хранит координаты `rowId + columnId`; режим `primary-modifier` активируется безопасным Ctrl/Command без Shift/Alt.
|
|
114
114
|
|
|
115
115
|
### Metadata-driven OData adapter
|
|
116
116
|
|