react-glide-table 1.7.0 → 2.0.1
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 +54 -2
- package/dist/compound.cjs +453 -97
- package/dist/compound.d.cts +2 -2
- package/dist/compound.d.ts +2 -2
- package/dist/compound.js +438 -82
- package/dist/core.cjs +399 -12
- package/dist/core.d.cts +40 -4
- package/dist/core.d.ts +40 -4
- package/dist/core.js +391 -12
- package/dist/index.cjs +550 -164
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +522 -144
- package/dist/{types-Cs9MiZs1.d.cts → types-DJOlsDL8.d.cts} +73 -4
- package/dist/{types-Cs9MiZs1.d.ts → types-DJOlsDL8.d.ts} +73 -4
- package/package.json +1 -1
package/dist/core.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import { Row, ColumnDef, Table, Updater, RowSelectionState } from '@tanstack/react-table';
|
|
1
|
+
import { W as CellEditType, c as CellRenderer, C as CellKind, a as CellRenderContext, i as DataTableClassNames, R as RowSelectionMode, g as ColumnFreezeOffset, p as SearchResultItem, q as SearchStatus, l as DataTableProps, k as DataTableLabels, j as DataTableCopyActions, P as PasteMode, o as RowsPastePayload } from './types-DJOlsDL8.js';
|
|
2
|
+
export { B as BuiltinCellKind, b as CellRenderFn, d as ColumnFreezeColumnInput, e as ColumnFreezeEdgeSide, f as ColumnFreezeMeta, h as ColumnFreezeSide, D as DEFAULT_DATA_TABLE_LABELS, I as INLINE_SEARCH_MAX_RESULTS, S as SearchCorpusRow, t as buildColumnFreezeOffsets, u as buildFlatSearchCorpus, v as buildSearchMatchKey, w as buildSearchMatchKeys, x as buildTreeSearchCorpus, y as cellValueToSearchText, z as collectAncestorKeysToExpand, A as collectSearchMatchesInRange, E as createSearchRegex, F as escapeSearchRegex, G as formatSearchResultLabel, H as getColumnFreezeEdgeAttr, J as getColumnFreezeStyle, K as mapSearchResultToVisibleItem, L as mapSearchResultsToVisibleKeys, M as nextSearchIndex, N as nextSearchStride, O as previousSearchIndex, Q as resolveColumnFreezeSide, U as resolveDataTableLabels, V as resolveHeaderFreezeOffset } from './types-DJOlsDL8.js';
|
|
3
|
+
import { Row, ColumnDef, Table, CellContext, Updater, RowSelectionState } from '@tanstack/react-table';
|
|
4
4
|
export { ColumnDef, ColumnResizeMode, ColumnSizingState, RowSelectionState } from '@tanstack/react-table';
|
|
5
5
|
import { Virtualizer, VirtualItem } from '@tanstack/react-virtual';
|
|
6
6
|
import * as react from 'react';
|
|
@@ -36,6 +36,12 @@ declare function getCellEditDraftValue(value: unknown): string;
|
|
|
36
36
|
/** Returns updated data on success; null if parsing fails or the cell is not editable */
|
|
37
37
|
declare function applyCellEdit<T extends Record<string, unknown>>(data: T[], rows: Row<T>[], rowIndex: number, colIndex: number, raw: string): T[] | null;
|
|
38
38
|
|
|
39
|
+
type CellRendererRegistry = Map<string, CellRenderer>;
|
|
40
|
+
/** Later entries with the same `kind` override earlier ones (including builtins). */
|
|
41
|
+
declare function createCellRendererRegistry(customRenderers?: readonly CellRenderer[]): CellRendererRegistry;
|
|
42
|
+
declare function resolveCellRenderer<T extends Record<string, unknown>>(registry: CellRendererRegistry, kind: CellKind | undefined, ctx: CellRenderContext<T>): CellRenderer | undefined;
|
|
43
|
+
declare function formatDefaultCellValue(value: unknown): string | null;
|
|
44
|
+
|
|
39
45
|
type CellPosition = {
|
|
40
46
|
row: number;
|
|
41
47
|
col: number;
|
|
@@ -164,6 +170,10 @@ type DataTableRowContextValue = {
|
|
|
164
170
|
onCommitEdit: (raw?: string) => boolean;
|
|
165
171
|
onCancelEdit: () => void;
|
|
166
172
|
};
|
|
173
|
+
cellRender: {
|
|
174
|
+
registry: CellRendererRegistry;
|
|
175
|
+
commitValue: (rowId: string, columnId: string, value: unknown) => boolean;
|
|
176
|
+
};
|
|
167
177
|
expand: {
|
|
168
178
|
enableExpand: boolean;
|
|
169
179
|
toggleField?: string;
|
|
@@ -284,6 +294,27 @@ declare function useCellEdit<T extends Record<string, unknown>>({ data, rows, on
|
|
|
284
294
|
cancelEdit: () => void;
|
|
285
295
|
};
|
|
286
296
|
|
|
297
|
+
declare const BUILTIN_CELL_RENDERERS: CellRenderer[];
|
|
298
|
+
|
|
299
|
+
type CommitCellValueOptions<T extends Record<string, unknown>> = {
|
|
300
|
+
data: T[];
|
|
301
|
+
rows: Row<T>[];
|
|
302
|
+
rowId: string;
|
|
303
|
+
columnId: string;
|
|
304
|
+
value: unknown;
|
|
305
|
+
onCellChange?: (rowId: string, columnId: string, value: unknown) => void;
|
|
306
|
+
onDataChange?: (data: T[]) => void;
|
|
307
|
+
};
|
|
308
|
+
/**
|
|
309
|
+
* Shared commit path for custom `render` updates and built-in cell kinds.
|
|
310
|
+
* Prefers `onCellChange`; falls back to immutable `onDataChange` patch.
|
|
311
|
+
*/
|
|
312
|
+
declare function commitCellValue<T extends Record<string, unknown>>({ data, rows, rowId, columnId, value, onCellChange, onDataChange, }: CommitCellValueOptions<T>): boolean;
|
|
313
|
+
|
|
314
|
+
declare function ResolvedTableCell<T extends Record<string, unknown>>({ info, }: {
|
|
315
|
+
info: CellContext<T, unknown>;
|
|
316
|
+
}): react.ReactNode;
|
|
317
|
+
|
|
287
318
|
/** Width styles for header/body cells when column sizing is active. */
|
|
288
319
|
declare function getColumnSizeStyle(size: number, options?: {
|
|
289
320
|
force?: boolean;
|
|
@@ -350,6 +381,11 @@ type CopyRowEntry<T extends Record<string, unknown>> = {
|
|
|
350
381
|
/** Tree depth relative to the table root (0 = top-level). */
|
|
351
382
|
depth: number;
|
|
352
383
|
};
|
|
384
|
+
/**
|
|
385
|
+
* Clipboard / Excel paste expects one plain string per cell.
|
|
386
|
+
* Avoids `String(object)` → `[object Object]` and joins arrays with `, `.
|
|
387
|
+
*/
|
|
388
|
+
declare function formatCellValue(value: unknown): string;
|
|
353
389
|
declare function flattenSubtreeRows<T extends Record<string, unknown>>(row: T): T[];
|
|
354
390
|
/**
|
|
355
391
|
* Collects copy rows with tree depth so paste can rebuild parent/child nesting.
|
|
@@ -409,4 +445,4 @@ declare const useConvertTreeData: <T extends Record<string, unknown>>({ data, en
|
|
|
409
445
|
declare function resolveRowSelection(mode: RowSelectionMode, controlledSelection: RowSelectionState | undefined, internalSelection: RowSelectionState): RowSelectionState;
|
|
410
446
|
declare function applySelectionUpdater(mode: RowSelectionMode, updater: Updater<RowSelectionState>, previous: RowSelectionState): RowSelectionState;
|
|
411
447
|
|
|
412
|
-
export { CELL_SELECTION_EDGES_CLASS, type CellSelectionBounds, ColumnFreezeOffset, type ColumnRowSpanMap, type CopyRowEntry, type CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DataTableCopyActions, DataTableLabels, DataTableProps, type DragState, type EditingCell, PasteMode, RowSelectionMode, type RowSpanInfo, RowsPastePayload, SearchResultItem, SearchStatus, type TreeRow, type UseConvertTreeDataParams, type UseGlideTableOptions, type UseGlideTableResult, type UseInlineSearchOptions, type UseInlineSearchResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, flattenSubtreeRows, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, useInlineSearch, writeSelectionToClipboard };
|
|
448
|
+
export { BUILTIN_CELL_RENDERERS, CELL_SELECTION_EDGES_CLASS, CellKind, CellRenderContext, CellRenderer, type CellRendererRegistry, type CellSelectionBounds, ColumnFreezeOffset, type ColumnRowSpanMap, type CopyRowEntry, type CopySelectionMode, DEFAULT_TREE_CHILDREN_FIELD, DEFAULT_TREE_ID_FIELD, DEFAULT_TREE_PARENT_ID_FIELD, DEFAULT_TREE_QTY_FIELD, DataTableCopyActions, DataTableLabels, DataTableProps, type DragState, type EditingCell, PasteMode, ResolvedTableCell, RowSelectionMode, type RowSpanInfo, RowsPastePayload, SearchResultItem, SearchStatus, type TreeRow, type UseConvertTreeDataParams, type UseGlideTableOptions, type UseGlideTableResult, type UseInlineSearchOptions, type UseInlineSearchResult, applyCellEdit, applyFillData, applySelectionUpdater, buildColumnRowSpanMap, buildRowsPastePayload, canExpandRow, collectCopyRowEntries, collectCopyRows, collectFillChanges, collectRowSpanColumns, commitCellValue, createCellRendererRegistry, flattenSubtreeRows, formatCellValue, formatDefaultCellValue, getCellEditDraftValue, getCellSelectionEdgeStyle, getColumnEditType, getColumnSizeStyle, getRowIndexInMergedCell, hasCellSelectionEdges, isCellInSelection, isColumnEditable, isEditablePasteTarget, measureMergedSpanRowHeights, parseCellEditValue, parseClipboardTSV, parseClipboardTSVWithDepths, resolveCellRenderer, resolvePasteColumnIds, resolveRowSelection, resolveRowSpanAt, rowRangeToHeightRatios, serializeCopyRowsToTSV, serializeSelectionToTSV, toggleExpandedRowId, useCellEdit, useCellSelection, useConvertTreeData, useGlideTable, useInlineSearch, writeSelectionToClipboard };
|
package/dist/core.js
CHANGED
|
@@ -97,6 +97,37 @@ function applyCellEdit(data, rows, rowIndex, colIndex, raw) {
|
|
|
97
97
|
return newData;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// src/components/ui/table/features/cell-render/commitCellValue.ts
|
|
101
|
+
function commitCellValue({
|
|
102
|
+
data,
|
|
103
|
+
rows,
|
|
104
|
+
rowId,
|
|
105
|
+
columnId,
|
|
106
|
+
value,
|
|
107
|
+
onCellChange,
|
|
108
|
+
onDataChange
|
|
109
|
+
}) {
|
|
110
|
+
if (!onCellChange && !onDataChange) return true;
|
|
111
|
+
if (onCellChange) {
|
|
112
|
+
onCellChange(rowId, columnId, value);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
const row = rows.find((item) => item.id === rowId);
|
|
116
|
+
if (!row) return false;
|
|
117
|
+
const cell = row.getAllCells().find((item) => item.column.id === columnId) ?? row.getVisibleCells().find((item) => item.column.id === columnId);
|
|
118
|
+
if (!cell) return false;
|
|
119
|
+
const accessorKey = getColumnAccessorKey(cell.column.columnDef);
|
|
120
|
+
if (!accessorKey) return false;
|
|
121
|
+
const dataIndex = row.index;
|
|
122
|
+
if (dataIndex < 0 || dataIndex >= data.length) return false;
|
|
123
|
+
const next = data.map((item) => ({ ...item }));
|
|
124
|
+
const target = next[dataIndex];
|
|
125
|
+
if (!target) return false;
|
|
126
|
+
target[accessorKey] = value;
|
|
127
|
+
onDataChange?.(next);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
100
131
|
// src/components/ui/table/features/cell-edit/useCellEdit.ts
|
|
101
132
|
function useCellEdit({
|
|
102
133
|
data,
|
|
@@ -132,21 +163,23 @@ function useCellEdit({
|
|
|
132
163
|
cancelEdit();
|
|
133
164
|
return true;
|
|
134
165
|
}
|
|
135
|
-
const value = raw ?? draftValueRef.current;
|
|
136
166
|
if (!isColumnEditable(cell.column.columnDef)) {
|
|
137
167
|
cancelEdit();
|
|
138
168
|
return true;
|
|
139
169
|
}
|
|
170
|
+
const value = raw ?? draftValueRef.current;
|
|
140
171
|
const parsed = parseCellEditValue(value, getColumnEditType(cell.column.columnDef));
|
|
141
172
|
if (!parsed.ok) return false;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
173
|
+
const committed = commitCellValue({
|
|
174
|
+
data,
|
|
175
|
+
rows,
|
|
176
|
+
rowId: row.id,
|
|
177
|
+
columnId: cell.column.id,
|
|
178
|
+
value: parsed.value,
|
|
179
|
+
onCellChange,
|
|
180
|
+
onDataChange
|
|
181
|
+
});
|
|
182
|
+
if (!committed) return false;
|
|
150
183
|
cancelEdit();
|
|
151
184
|
return true;
|
|
152
185
|
},
|
|
@@ -175,6 +208,218 @@ function useCellEdit({
|
|
|
175
208
|
};
|
|
176
209
|
}
|
|
177
210
|
|
|
211
|
+
// src/components/ui/table/features/cell-render/builtins.tsx
|
|
212
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
213
|
+
function asString(value) {
|
|
214
|
+
if (value == null) return "";
|
|
215
|
+
return String(value);
|
|
216
|
+
}
|
|
217
|
+
function asStringList(value) {
|
|
218
|
+
if (Array.isArray(value)) {
|
|
219
|
+
return value.map((item) => asString(item)).filter(Boolean);
|
|
220
|
+
}
|
|
221
|
+
if (value == null || value === "") return [];
|
|
222
|
+
return [asString(value)];
|
|
223
|
+
}
|
|
224
|
+
function asDrilldownItems(value) {
|
|
225
|
+
if (!Array.isArray(value)) return [];
|
|
226
|
+
return value.flatMap((item) => {
|
|
227
|
+
if (item == null) return [];
|
|
228
|
+
if (typeof item === "string") return [{ text: item }];
|
|
229
|
+
if (typeof item === "object") {
|
|
230
|
+
const record = item;
|
|
231
|
+
const text = asString(record.text ?? record.label ?? "");
|
|
232
|
+
if (!text) return [];
|
|
233
|
+
const img = record.img ?? record.image;
|
|
234
|
+
return [{ text, ...typeof img === "string" ? { img } : {} }];
|
|
235
|
+
}
|
|
236
|
+
return [{ text: asString(item) }];
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function escapeHtml(text) {
|
|
240
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
241
|
+
}
|
|
242
|
+
function simpleMarkdownToHtml(source) {
|
|
243
|
+
const escaped = escapeHtml(source);
|
|
244
|
+
return escaped.replace(/`([^`]+)`/g, "<code>$1</code>").replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>").replace(/\*([^*]+)\*/g, "<em>$1</em>").replace(/\n/g, "<br />");
|
|
245
|
+
}
|
|
246
|
+
function TextCell({ value }) {
|
|
247
|
+
return asString(value);
|
|
248
|
+
}
|
|
249
|
+
function NumberCell({ value }) {
|
|
250
|
+
if (value == null || value === "") return null;
|
|
251
|
+
return asString(value);
|
|
252
|
+
}
|
|
253
|
+
function BooleanCell({ value, update, cellProps }) {
|
|
254
|
+
const checked = Boolean(value);
|
|
255
|
+
const readonly = Boolean(cellProps?.readonly);
|
|
256
|
+
return /* @__PURE__ */ jsx(
|
|
257
|
+
"input",
|
|
258
|
+
{
|
|
259
|
+
type: "checkbox",
|
|
260
|
+
className: "data-table-cell-boolean",
|
|
261
|
+
checked,
|
|
262
|
+
disabled: readonly,
|
|
263
|
+
"aria-checked": checked,
|
|
264
|
+
onChange: (event) => {
|
|
265
|
+
if (readonly) return;
|
|
266
|
+
update(event.target.checked);
|
|
267
|
+
},
|
|
268
|
+
onClick: (event) => {
|
|
269
|
+
event.stopPropagation();
|
|
270
|
+
},
|
|
271
|
+
onMouseDown: (event) => {
|
|
272
|
+
event.stopPropagation();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
function sanitizeUriHref(raw) {
|
|
278
|
+
const href = raw.trim();
|
|
279
|
+
if (!href) return null;
|
|
280
|
+
if (href.startsWith("/") || href.startsWith("#") || href.startsWith("?") || href.startsWith("./") || href.startsWith("../")) {
|
|
281
|
+
return href;
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
const parsed = new URL(href);
|
|
285
|
+
const protocol = parsed.protocol.toLowerCase();
|
|
286
|
+
if (protocol === "http:" || protocol === "https:" || protocol === "mailto:") {
|
|
287
|
+
return href;
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
} catch {
|
|
291
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(href)) return null;
|
|
292
|
+
return href;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function UriCell({ value }) {
|
|
296
|
+
const raw = asString(value);
|
|
297
|
+
if (!raw) return null;
|
|
298
|
+
const href = sanitizeUriHref(raw);
|
|
299
|
+
if (!href) {
|
|
300
|
+
return /* @__PURE__ */ jsx("span", { className: "data-table-cell-uri", children: raw });
|
|
301
|
+
}
|
|
302
|
+
return /* @__PURE__ */ jsx(
|
|
303
|
+
"a",
|
|
304
|
+
{
|
|
305
|
+
className: "data-table-cell-uri",
|
|
306
|
+
href,
|
|
307
|
+
target: "_blank",
|
|
308
|
+
rel: "noopener noreferrer",
|
|
309
|
+
onClick: (event) => event.stopPropagation(),
|
|
310
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
311
|
+
children: raw
|
|
312
|
+
}
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
function ImageCell({ value }) {
|
|
316
|
+
const urls = asStringList(value);
|
|
317
|
+
if (urls.length === 0) return null;
|
|
318
|
+
return /* @__PURE__ */ jsx("span", { className: "data-table-cell-image", children: urls.map((url, index) => /* @__PURE__ */ jsx(
|
|
319
|
+
"img",
|
|
320
|
+
{
|
|
321
|
+
src: url,
|
|
322
|
+
alt: "",
|
|
323
|
+
className: "data-table-cell-image-item"
|
|
324
|
+
},
|
|
325
|
+
`${index}:${url}`
|
|
326
|
+
)) });
|
|
327
|
+
}
|
|
328
|
+
function BubbleCell({ value }) {
|
|
329
|
+
const items = asStringList(value);
|
|
330
|
+
if (items.length === 0) return null;
|
|
331
|
+
return /* @__PURE__ */ jsx("span", { className: "data-table-cell-bubble", children: items.map((item, index) => /* @__PURE__ */ jsx("span", { className: "data-table-cell-bubble-item", children: item }, `${index}:${item}`)) });
|
|
332
|
+
}
|
|
333
|
+
function MarkdownCell({ value }) {
|
|
334
|
+
const source = asString(value);
|
|
335
|
+
if (!source) return null;
|
|
336
|
+
return /* @__PURE__ */ jsx(
|
|
337
|
+
"span",
|
|
338
|
+
{
|
|
339
|
+
className: "data-table-cell-markdown",
|
|
340
|
+
dangerouslySetInnerHTML: { __html: simpleMarkdownToHtml(source) }
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
function DrilldownCell({ value }) {
|
|
345
|
+
const items = asDrilldownItems(value);
|
|
346
|
+
if (items.length === 0) return null;
|
|
347
|
+
return /* @__PURE__ */ jsx("span", { className: "data-table-cell-drilldown", children: items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
348
|
+
"span",
|
|
349
|
+
{
|
|
350
|
+
className: "data-table-cell-drilldown-item",
|
|
351
|
+
children: [
|
|
352
|
+
item.img ? /* @__PURE__ */ jsx(
|
|
353
|
+
"img",
|
|
354
|
+
{
|
|
355
|
+
src: item.img,
|
|
356
|
+
alt: "",
|
|
357
|
+
className: "data-table-cell-drilldown-image"
|
|
358
|
+
}
|
|
359
|
+
) : null,
|
|
360
|
+
/* @__PURE__ */ jsx("span", { className: "data-table-cell-drilldown-text", children: item.text })
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
`${index}:${item.text}:${item.img ?? ""}`
|
|
364
|
+
)) });
|
|
365
|
+
}
|
|
366
|
+
function LoadingCell() {
|
|
367
|
+
return /* @__PURE__ */ jsx("span", { className: "data-table-cell-loading", "aria-busy": "true" });
|
|
368
|
+
}
|
|
369
|
+
function ProtectedCell() {
|
|
370
|
+
return /* @__PURE__ */ jsx("span", { className: "data-table-cell-protected", "aria-label": "protected", children: "****" });
|
|
371
|
+
}
|
|
372
|
+
function RowIdCell({ value }) {
|
|
373
|
+
return /* @__PURE__ */ jsx("span", { className: "data-table-cell-row-id", children: asString(value) });
|
|
374
|
+
}
|
|
375
|
+
var BUILTIN_RENDER_MAP = {
|
|
376
|
+
text: TextCell,
|
|
377
|
+
number: NumberCell,
|
|
378
|
+
boolean: BooleanCell,
|
|
379
|
+
uri: UriCell,
|
|
380
|
+
image: ImageCell,
|
|
381
|
+
bubble: BubbleCell,
|
|
382
|
+
markdown: MarkdownCell,
|
|
383
|
+
drilldown: DrilldownCell,
|
|
384
|
+
loading: LoadingCell,
|
|
385
|
+
protected: ProtectedCell,
|
|
386
|
+
"row-id": RowIdCell
|
|
387
|
+
};
|
|
388
|
+
var BUILTIN_CELL_RENDERERS = Object.keys(BUILTIN_RENDER_MAP).map((kind) => ({
|
|
389
|
+
kind,
|
|
390
|
+
render: BUILTIN_RENDER_MAP[kind]
|
|
391
|
+
}));
|
|
392
|
+
|
|
393
|
+
// src/components/ui/table/features/cell-render/registry.ts
|
|
394
|
+
function createCellRendererRegistry(customRenderers = []) {
|
|
395
|
+
const registry = /* @__PURE__ */ new Map();
|
|
396
|
+
for (const renderer of BUILTIN_CELL_RENDERERS) {
|
|
397
|
+
registry.set(renderer.kind, renderer);
|
|
398
|
+
}
|
|
399
|
+
for (const renderer of customRenderers) {
|
|
400
|
+
registry.set(renderer.kind, renderer);
|
|
401
|
+
}
|
|
402
|
+
return registry;
|
|
403
|
+
}
|
|
404
|
+
function resolveCellRenderer(registry, kind, ctx) {
|
|
405
|
+
if (!kind) return void 0;
|
|
406
|
+
const renderer = registry.get(kind);
|
|
407
|
+
if (!renderer) return void 0;
|
|
408
|
+
if (renderer.isMatch && !renderer.isMatch(ctx)) {
|
|
409
|
+
return void 0;
|
|
410
|
+
}
|
|
411
|
+
return renderer;
|
|
412
|
+
}
|
|
413
|
+
function formatDefaultCellValue(value) {
|
|
414
|
+
if (value == null) return null;
|
|
415
|
+
if (typeof value === "string") return value;
|
|
416
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
417
|
+
return String(value);
|
|
418
|
+
}
|
|
419
|
+
if (typeof value === "bigint") return value.toString();
|
|
420
|
+
return String(value);
|
|
421
|
+
}
|
|
422
|
+
|
|
178
423
|
// src/components/ui/table/features/cell-selection/useCellSelection.ts
|
|
179
424
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
180
425
|
|
|
@@ -484,9 +729,34 @@ function hasCellSelectionEdges(style) {
|
|
|
484
729
|
}
|
|
485
730
|
|
|
486
731
|
// src/components/ui/table/features/cell-selection/copyData.ts
|
|
732
|
+
function formatPrimitive(value) {
|
|
733
|
+
if (value === null || value === void 0) return "";
|
|
734
|
+
if (typeof value === "string") return value;
|
|
735
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
736
|
+
return String(value);
|
|
737
|
+
}
|
|
738
|
+
return "";
|
|
739
|
+
}
|
|
740
|
+
function formatObjectValue(value) {
|
|
741
|
+
const text = value.text ?? value.label ?? value.name ?? value.title;
|
|
742
|
+
if (text != null && text !== "") {
|
|
743
|
+
return formatCellValue(text);
|
|
744
|
+
}
|
|
745
|
+
try {
|
|
746
|
+
return JSON.stringify(value);
|
|
747
|
+
} catch {
|
|
748
|
+
return "";
|
|
749
|
+
}
|
|
750
|
+
}
|
|
487
751
|
function formatCellValue(value) {
|
|
488
752
|
if (value === null || value === void 0) return "";
|
|
489
|
-
|
|
753
|
+
if (Array.isArray(value)) {
|
|
754
|
+
return value.map((item) => formatCellValue(item)).filter((item) => item.length > 0).join(", ");
|
|
755
|
+
}
|
|
756
|
+
if (typeof value === "object") {
|
|
757
|
+
return formatObjectValue(value);
|
|
758
|
+
}
|
|
759
|
+
return formatPrimitive(value);
|
|
490
760
|
}
|
|
491
761
|
function getNestedValue(row, path) {
|
|
492
762
|
if (!path.includes(".")) return row[path];
|
|
@@ -1110,10 +1380,40 @@ function getColumnFreezeStyle(offset, options) {
|
|
|
1110
1380
|
return {
|
|
1111
1381
|
position: "sticky",
|
|
1112
1382
|
...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
|
|
1113
|
-
zIndex: zBase + offset.stack
|
|
1114
|
-
...options?.isHeader ? { top: options.headerTop ?? 0 } : {}
|
|
1383
|
+
zIndex: zBase + offset.stack
|
|
1115
1384
|
};
|
|
1116
1385
|
}
|
|
1386
|
+
function resolveHeaderFreezeOffset(column, freezeOffsets) {
|
|
1387
|
+
const direct = freezeOffsets.get(column.id);
|
|
1388
|
+
if (direct) return direct;
|
|
1389
|
+
const leaves = typeof column.getLeafColumns === "function" ? column.getLeafColumns() : column.columns && column.columns.length > 0 ? flattenHeaderLeaves(column) : [];
|
|
1390
|
+
if (leaves.length === 0) return void 0;
|
|
1391
|
+
const leafOffsets = [];
|
|
1392
|
+
for (const leaf of leaves) {
|
|
1393
|
+
const offset2 = freezeOffsets.get(leaf.id);
|
|
1394
|
+
if (!offset2) return void 0;
|
|
1395
|
+
leafOffsets.push(offset2);
|
|
1396
|
+
}
|
|
1397
|
+
const side = leafOffsets[0]?.side;
|
|
1398
|
+
if (!side || leafOffsets.some((offset2) => offset2.side !== side)) {
|
|
1399
|
+
return void 0;
|
|
1400
|
+
}
|
|
1401
|
+
const offset = Math.min(...leafOffsets.map((item) => item.offset));
|
|
1402
|
+
const leftmost = leafOffsets[0];
|
|
1403
|
+
const rightmost = leafOffsets[leafOffsets.length - 1];
|
|
1404
|
+
return {
|
|
1405
|
+
side,
|
|
1406
|
+
offset,
|
|
1407
|
+
edgeLeft: leftmost.edgeLeft,
|
|
1408
|
+
edgeRight: rightmost.edgeRight,
|
|
1409
|
+
isEdge: leftmost.edgeLeft || rightmost.edgeRight,
|
|
1410
|
+
stack: Math.max(...leafOffsets.map((item) => item.stack))
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
function flattenHeaderLeaves(column) {
|
|
1414
|
+
if (!column.columns || column.columns.length === 0) return [column];
|
|
1415
|
+
return column.columns.flatMap((child) => flattenHeaderLeaves(child));
|
|
1416
|
+
}
|
|
1117
1417
|
|
|
1118
1418
|
// src/components/ui/table/features/inline-search/inlineSearch.ts
|
|
1119
1419
|
var INLINE_SEARCH_MAX_RESULTS = 1e3;
|
|
@@ -1864,6 +2164,7 @@ function useGlideTable(options) {
|
|
|
1864
2164
|
onDataChange,
|
|
1865
2165
|
onCellChange,
|
|
1866
2166
|
onBatchChange,
|
|
2167
|
+
cellRenderers,
|
|
1867
2168
|
preserveRowSelection = false,
|
|
1868
2169
|
toggleField,
|
|
1869
2170
|
childField,
|
|
@@ -2089,6 +2390,22 @@ function useGlideTable(options) {
|
|
|
2089
2390
|
commitEdit,
|
|
2090
2391
|
cancelEdit
|
|
2091
2392
|
} = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
|
|
2393
|
+
const cellRendererRegistry = useMemo3(
|
|
2394
|
+
() => createCellRendererRegistry(cellRenderers),
|
|
2395
|
+
[cellRenderers]
|
|
2396
|
+
);
|
|
2397
|
+
const commitRenderedCellValue = useCallback4(
|
|
2398
|
+
(rowId, columnId, value) => commitCellValue({
|
|
2399
|
+
data: tableData,
|
|
2400
|
+
rows,
|
|
2401
|
+
rowId,
|
|
2402
|
+
columnId,
|
|
2403
|
+
value,
|
|
2404
|
+
onCellChange,
|
|
2405
|
+
onDataChange
|
|
2406
|
+
}),
|
|
2407
|
+
[onCellChange, onDataChange, rows, tableData]
|
|
2408
|
+
);
|
|
2092
2409
|
const handleCellMouseDownWithCommit = useCallback4(
|
|
2093
2410
|
(rowIndex, colIndex, options2) => {
|
|
2094
2411
|
const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
|
|
@@ -2325,6 +2642,10 @@ function useGlideTable(options) {
|
|
|
2325
2642
|
onCommitEdit: commitEdit,
|
|
2326
2643
|
onCancelEdit: cancelEdit
|
|
2327
2644
|
},
|
|
2645
|
+
cellRender: {
|
|
2646
|
+
registry: cellRendererRegistry,
|
|
2647
|
+
commitValue: commitRenderedCellValue
|
|
2648
|
+
},
|
|
2328
2649
|
expand: {
|
|
2329
2650
|
enableExpand,
|
|
2330
2651
|
toggleField,
|
|
@@ -2371,6 +2692,8 @@ function useGlideTable(options) {
|
|
|
2371
2692
|
startEdit,
|
|
2372
2693
|
commitEdit,
|
|
2373
2694
|
cancelEdit,
|
|
2695
|
+
cellRendererRegistry,
|
|
2696
|
+
commitRenderedCellValue,
|
|
2374
2697
|
enableExpand,
|
|
2375
2698
|
toggleField,
|
|
2376
2699
|
expandedRows,
|
|
@@ -2435,6 +2758,54 @@ function useGlideTable(options) {
|
|
|
2435
2758
|
};
|
|
2436
2759
|
}
|
|
2437
2760
|
|
|
2761
|
+
// src/components/ui/table/features/cell-render/ResolvedTableCell.tsx
|
|
2762
|
+
import { useCallback as useCallback5 } from "react";
|
|
2763
|
+
|
|
2764
|
+
// src/components/ui/table/DataTableContext.tsx
|
|
2765
|
+
import { createContext, use } from "react";
|
|
2766
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
2767
|
+
var DataTableContext = createContext(null);
|
|
2768
|
+
function useDataTableRowContext() {
|
|
2769
|
+
const context = use(DataTableContext);
|
|
2770
|
+
if (!context) {
|
|
2771
|
+
throw new Error("useDataTableRowContext must be used within a DataTableContextProvider");
|
|
2772
|
+
}
|
|
2773
|
+
return context;
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2776
|
+
// src/components/ui/table/features/cell-render/ResolvedTableCell.tsx
|
|
2777
|
+
function ResolvedTableCell({
|
|
2778
|
+
info
|
|
2779
|
+
}) {
|
|
2780
|
+
const { cellRender } = useDataTableRowContext();
|
|
2781
|
+
const { row, column, getValue } = info;
|
|
2782
|
+
const meta = column.columnDef.meta;
|
|
2783
|
+
const value = getValue();
|
|
2784
|
+
const columnId = column.id;
|
|
2785
|
+
const update = useCallback5(
|
|
2786
|
+
(next) => {
|
|
2787
|
+
cellRender.commitValue(row.id, columnId, next);
|
|
2788
|
+
},
|
|
2789
|
+
[cellRender, columnId, row.id]
|
|
2790
|
+
);
|
|
2791
|
+
const ctx = {
|
|
2792
|
+
value,
|
|
2793
|
+
row,
|
|
2794
|
+
index: row.index,
|
|
2795
|
+
columnId,
|
|
2796
|
+
cellProps: meta?.cellProps,
|
|
2797
|
+
update
|
|
2798
|
+
};
|
|
2799
|
+
if (meta?.cellRender) {
|
|
2800
|
+
return meta.cellRender(ctx);
|
|
2801
|
+
}
|
|
2802
|
+
const renderer = resolveCellRenderer(cellRender.registry, meta?.kind, ctx);
|
|
2803
|
+
if (renderer) {
|
|
2804
|
+
return renderer.render(ctx);
|
|
2805
|
+
}
|
|
2806
|
+
return formatDefaultCellValue(value);
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2438
2809
|
// src/components/ui/table/features/column-resize/columnResize.ts
|
|
2439
2810
|
function getColumnSizeStyle(size, options) {
|
|
2440
2811
|
const { force = false, lockMax = false } = options ?? {};
|
|
@@ -2448,6 +2819,7 @@ function getColumnSizeStyle(size, options) {
|
|
|
2448
2819
|
};
|
|
2449
2820
|
}
|
|
2450
2821
|
export {
|
|
2822
|
+
BUILTIN_CELL_RENDERERS,
|
|
2451
2823
|
CELL_SELECTION_EDGES_CLASS,
|
|
2452
2824
|
DEFAULT_DATA_TABLE_LABELS,
|
|
2453
2825
|
DEFAULT_TREE_CHILDREN_FIELD,
|
|
@@ -2455,6 +2827,7 @@ export {
|
|
|
2455
2827
|
DEFAULT_TREE_PARENT_ID_FIELD,
|
|
2456
2828
|
DEFAULT_TREE_QTY_FIELD,
|
|
2457
2829
|
INLINE_SEARCH_MAX_RESULTS,
|
|
2830
|
+
ResolvedTableCell,
|
|
2458
2831
|
applyCellEdit,
|
|
2459
2832
|
applyFillData,
|
|
2460
2833
|
applySelectionUpdater,
|
|
@@ -2473,9 +2846,13 @@ export {
|
|
|
2473
2846
|
collectFillChanges,
|
|
2474
2847
|
collectRowSpanColumns,
|
|
2475
2848
|
collectSearchMatchesInRange,
|
|
2849
|
+
commitCellValue,
|
|
2850
|
+
createCellRendererRegistry,
|
|
2476
2851
|
createSearchRegex,
|
|
2477
2852
|
escapeSearchRegex,
|
|
2478
2853
|
flattenSubtreeRows,
|
|
2854
|
+
formatCellValue,
|
|
2855
|
+
formatDefaultCellValue,
|
|
2479
2856
|
formatSearchResultLabel,
|
|
2480
2857
|
getCellEditDraftValue,
|
|
2481
2858
|
getCellSelectionEdgeStyle,
|
|
@@ -2497,8 +2874,10 @@ export {
|
|
|
2497
2874
|
parseClipboardTSV,
|
|
2498
2875
|
parseClipboardTSVWithDepths,
|
|
2499
2876
|
previousSearchIndex,
|
|
2877
|
+
resolveCellRenderer,
|
|
2500
2878
|
resolveColumnFreezeSide,
|
|
2501
2879
|
resolveDataTableLabels,
|
|
2880
|
+
resolveHeaderFreezeOffset,
|
|
2502
2881
|
resolvePasteColumnIds,
|
|
2503
2882
|
resolveRowSelection,
|
|
2504
2883
|
resolveRowSpanAt,
|