@zvndev/yable-react 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  var yableCore = require('@zvndev/yable-core');
4
4
  var React3 = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
+ var reactDom = require('react-dom');
6
7
  var rowDragging = require('@zvndev/yable-core/features/rowDragging');
7
8
 
8
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -10,6 +11,113 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
11
  var React3__default = /*#__PURE__*/_interopDefault(React3);
11
12
 
12
13
  // src/index.ts
14
+ var YableContext = React3.createContext({});
15
+ function useYableDefaults() {
16
+ return React3.useContext(YableContext);
17
+ }
18
+ function YableProvider({
19
+ children,
20
+ config,
21
+ tableProfile,
22
+ defaultColumnDef,
23
+ striped,
24
+ stickyHeader,
25
+ bordered,
26
+ compact,
27
+ theme,
28
+ direction,
29
+ ariaLabel
30
+ }) {
31
+ const tableProps = {};
32
+ if (striped !== void 0) tableProps.striped = striped;
33
+ if (stickyHeader !== void 0) tableProps.stickyHeader = stickyHeader;
34
+ if (bordered !== void 0) tableProps.bordered = bordered;
35
+ if (compact !== void 0) tableProps.compact = compact;
36
+ if (theme !== void 0) tableProps.theme = theme;
37
+ if (direction !== void 0) tableProps.direction = direction;
38
+ if (ariaLabel !== void 0) tableProps.ariaLabel = ariaLabel;
39
+ const value = {
40
+ config,
41
+ tableProfile,
42
+ tableProps: Object.keys(tableProps).length > 0 ? tableProps : void 0,
43
+ defaultColumnDef
44
+ };
45
+ return /* @__PURE__ */ jsxRuntime.jsx(YableContext.Provider, { value, children });
46
+ }
47
+
48
+ // src/config.ts
49
+ function createYableConfig(config) {
50
+ return config;
51
+ }
52
+ function resolveYableProfile(config, profileName = "default") {
53
+ const base = pickProfileFields(config);
54
+ const named = profileName === "default" ? void 0 : config?.profiles?.[profileName];
55
+ return {
56
+ name: profileName,
57
+ table: { ...base.table, ...named?.table },
58
+ columns: {
59
+ default: { ...base.columns?.default, ...named?.columns?.default },
60
+ byId: { ...base.columns?.byId, ...named?.columns?.byId }
61
+ },
62
+ rows: { ...base.rows, ...named?.rows },
63
+ cells: {
64
+ default: { ...base.cells?.default, ...named?.cells?.default },
65
+ named: { ...base.cells?.named, ...named?.cells?.named },
66
+ byColumn: { ...base.cells?.byColumn, ...named?.cells?.byColumn }
67
+ }
68
+ };
69
+ }
70
+ function getYableDefaultColumnDef(profile) {
71
+ const next = {
72
+ ...profile?.columns?.default
73
+ };
74
+ return Object.keys(next).length > 0 ? next : void 0;
75
+ }
76
+ function applyYableConfigToColumns(columns, profile) {
77
+ if (!profile) return columns;
78
+ return columns.map((columnDef) => applyColumnConfig(columnDef, profile));
79
+ }
80
+ function applyColumnConfig(columnDef, profile) {
81
+ const columnId = getColumnId(columnDef);
82
+ const explicit = columnDef;
83
+ const cellNames = normalizeCellConfigNames(explicit.cellConfig);
84
+ const namedCellConfig = cellNames.reduce(
85
+ (acc, name) => ({ ...acc, ...profile.cells?.named?.[name] }),
86
+ {}
87
+ );
88
+ const defaultCell = profile.cells?.default;
89
+ const columnCell = columnId ? profile.cells?.byColumn?.[columnId] : void 0;
90
+ const columnConfig = columnId ? profile.columns?.byId?.[columnId] : void 0;
91
+ const children = "columns" in columnDef && columnDef.columns ? { columns: columnDef.columns.map((child) => applyColumnConfig(child, profile)) } : void 0;
92
+ return {
93
+ ...defaultCell,
94
+ ...namedCellConfig,
95
+ ...columnCell,
96
+ ...columnConfig,
97
+ ...columnDef,
98
+ ...children
99
+ };
100
+ }
101
+ function pickProfileFields(config) {
102
+ if (!config) return {};
103
+ return {
104
+ table: config.table,
105
+ columns: config.columns,
106
+ rows: config.rows,
107
+ cells: config.cells
108
+ };
109
+ }
110
+ function getColumnId(columnDef) {
111
+ if ("id" in columnDef && columnDef.id) return String(columnDef.id);
112
+ if ("accessorKey" in columnDef && columnDef.accessorKey) return String(columnDef.accessorKey);
113
+ return void 0;
114
+ }
115
+ function normalizeCellConfigNames(value) {
116
+ if (!value) return [];
117
+ return Array.isArray(value) ? value : [value];
118
+ }
119
+
120
+ // src/useTable.ts
13
121
  function shallowEqual(a, b) {
14
122
  if (a === b) return true;
15
123
  const keysA = Object.keys(a);
@@ -22,6 +130,32 @@ function shallowEqual(a, b) {
22
130
  return true;
23
131
  }
24
132
  function useTable(options) {
133
+ const providerDefaults = useYableDefaults();
134
+ const optionsWithDefaults = React3.useMemo(() => {
135
+ const profile = resolveYableProfile(
136
+ options.config ?? providerDefaults.config,
137
+ options.configProfile ?? providerDefaults.tableProfile
138
+ );
139
+ const profileDefaultColumnDef = getYableDefaultColumnDef(profile);
140
+ const configuredColumns = applyYableConfigToColumns(options.columns, profile);
141
+ const defaultColumnDef = {
142
+ ...profileDefaultColumnDef,
143
+ ...providerDefaults.defaultColumnDef,
144
+ ...options.defaultColumnDef
145
+ };
146
+ return {
147
+ ...options,
148
+ columns: configuredColumns,
149
+ rowClassName: options.rowClassName ?? profile.rows?.className,
150
+ rowStyle: options.rowStyle ?? profile.rows?.style,
151
+ defaultColumnDef: Object.keys(defaultColumnDef).length > 0 ? defaultColumnDef : void 0
152
+ };
153
+ }, [
154
+ options,
155
+ providerDefaults.config,
156
+ providerDefaults.defaultColumnDef,
157
+ providerDefaults.tableProfile
158
+ ]);
25
159
  const [state, setState] = React3.useState(() => ({
26
160
  sorting: [],
27
161
  columnFilters: [],
@@ -61,14 +195,14 @@ function useTable(options) {
61
195
  }));
62
196
  const stateRef = React3.useRef(state);
63
197
  stateRef.current = state;
64
- const prevOptionsRef = React3.useRef(options);
198
+ const prevOptionsRef = React3.useRef(optionsWithDefaults);
65
199
  const stableOptions = React3.useMemo(() => {
66
- if (shallowEqual(prevOptionsRef.current, options)) {
200
+ if (shallowEqual(prevOptionsRef.current, optionsWithDefaults)) {
67
201
  return prevOptionsRef.current;
68
202
  }
69
- prevOptionsRef.current = options;
70
- return options;
71
- }, [options]);
203
+ prevOptionsRef.current = optionsWithDefaults;
204
+ return optionsWithDefaults;
205
+ }, [optionsWithDefaults]);
72
206
  const onStateChangeRef = React3.useRef(options.onStateChange);
73
207
  onStateChangeRef.current = options.onStateChange;
74
208
  const resolvedState = React3.useMemo(
@@ -78,17 +212,14 @@ function useTable(options) {
78
212
  }),
79
213
  [state, stableOptions.state]
80
214
  );
81
- const onStateChange = React3.useCallback(
82
- (updater) => {
83
- const latest = onStateChangeRef.current;
84
- if (latest) {
85
- latest(updater);
86
- } else {
87
- setState((prev) => yableCore.functionalUpdate(updater, prev));
88
- }
89
- },
90
- []
91
- );
215
+ const onStateChange = React3.useCallback((updater) => {
216
+ const latest = onStateChangeRef.current;
217
+ if (latest) {
218
+ latest(updater);
219
+ } else {
220
+ setState((prev) => yableCore.functionalUpdate(updater, prev));
221
+ }
222
+ }, []);
92
223
  const resolvedOptions = React3.useMemo(
93
224
  () => ({
94
225
  ...stableOptions,
@@ -101,13 +232,41 @@ function useTable(options) {
101
232
  if (!tableRef.current) {
102
233
  tableRef.current = yableCore.createTable(resolvedOptions);
103
234
  } else {
104
- tableRef.current.setOptions((prev) => ({
105
- ...prev,
106
- ...resolvedOptions,
107
- state: resolvedState,
108
- onStateChange
109
- }));
235
+ tableRef.current.setOptions(
236
+ (prev) => ({
237
+ ...prev,
238
+ ...resolvedOptions,
239
+ state: resolvedState,
240
+ onStateChange
241
+ })
242
+ );
110
243
  }
244
+ React3.useEffect(() => {
245
+ const table = tableRef.current;
246
+ if (!table) return;
247
+ const unsubscribers = [
248
+ options.onCellClick && table.events.on("cell:click", options.onCellClick),
249
+ options.onCellDoubleClick && table.events.on("cell:dblclick", options.onCellDoubleClick),
250
+ options.onCellContextMenu && table.events.on("cell:contextmenu", options.onCellContextMenu),
251
+ options.onRowClick && table.events.on("row:click", options.onRowClick),
252
+ options.onRowDoubleClick && table.events.on("row:dblclick", options.onRowDoubleClick),
253
+ options.onRowContextMenu && table.events.on("row:contextmenu", options.onRowContextMenu),
254
+ options.onHeaderClick && table.events.on("header:click", options.onHeaderClick),
255
+ options.onHeaderContextMenu && table.events.on("header:contextmenu", options.onHeaderContextMenu)
256
+ ].filter((unsubscribe) => Boolean(unsubscribe));
257
+ return () => {
258
+ unsubscribers.forEach((unsubscribe) => unsubscribe());
259
+ };
260
+ }, [
261
+ options.onCellClick,
262
+ options.onCellContextMenu,
263
+ options.onCellDoubleClick,
264
+ options.onHeaderClick,
265
+ options.onHeaderContextMenu,
266
+ options.onRowClick,
267
+ options.onRowContextMenu,
268
+ options.onRowDoubleClick
269
+ ]);
111
270
  React3.useEffect(() => {
112
271
  return () => {
113
272
  if (tableRef.current) {
@@ -117,6 +276,311 @@ function useTable(options) {
117
276
  }, []);
118
277
  return tableRef.current;
119
278
  }
279
+ function useServerTable({
280
+ fetchData,
281
+ updateRow,
282
+ initialRows = [],
283
+ initialCursor = null,
284
+ initialHasMore = true,
285
+ initialRowCount,
286
+ initialPageCount,
287
+ initialSorting = [],
288
+ initialColumnFilters = [],
289
+ initialGlobalFilter = "",
290
+ initialPagination = { pageIndex: 0, pageSize: 50 },
291
+ autoLoad = true,
292
+ getRowId,
293
+ ...tableOptions
294
+ }) {
295
+ const [rows, setRows] = React3.useState(initialRows);
296
+ const [cursor, setCursor] = React3.useState(initialCursor);
297
+ const [hasMore, setHasMore] = React3.useState(initialHasMore);
298
+ const [rowCount, setRowCount] = React3.useState(initialRowCount);
299
+ const [pageCount, setPageCount] = React3.useState(initialPageCount);
300
+ const [sorting, setSorting] = React3.useState(initialSorting);
301
+ const [columnFilters, setColumnFilters] = React3.useState(initialColumnFilters);
302
+ const [globalFilter, setGlobalFilter] = React3.useState(initialGlobalFilter);
303
+ const [pagination, setPagination] = React3.useState(initialPagination);
304
+ const [loading, setLoading] = React3.useState(false);
305
+ const [error, setError] = React3.useState(null);
306
+ const abortRef = React3.useRef(null);
307
+ const cursorRef = React3.useRef(cursor);
308
+ const fetchDataRef = React3.useRef(fetchData);
309
+ const updateRowRef = React3.useRef(updateRow);
310
+ const resolveRowId = React3.useCallback(
311
+ (row, index) => getRowId?.(row, index) ?? String(row.id ?? index),
312
+ [getRowId]
313
+ );
314
+ const runFetch = React3.useCallback(
315
+ async (mode) => {
316
+ abortRef.current?.abort();
317
+ const abort = new AbortController();
318
+ abortRef.current = abort;
319
+ setLoading(true);
320
+ setError(null);
321
+ try {
322
+ const result = await fetchDataRef.current({
323
+ sorting,
324
+ columnFilters,
325
+ globalFilter,
326
+ pagination,
327
+ cursor: mode === "append" ? cursorRef.current : null,
328
+ signal: abort.signal
329
+ });
330
+ if (abort.signal.aborted) return;
331
+ setRows((prev) => mode === "append" ? [...prev, ...result.rows] : result.rows);
332
+ setCursor(result.cursor ?? null);
333
+ setHasMore((prev) => result.hasMore ?? prev);
334
+ setRowCount((prev) => result.rowCount ?? prev);
335
+ setPageCount((prev) => result.pageCount ?? prev);
336
+ } catch (nextError) {
337
+ if (!abort.signal.aborted) setError(nextError);
338
+ } finally {
339
+ if (!abort.signal.aborted) setLoading(false);
340
+ }
341
+ },
342
+ [columnFilters, globalFilter, pagination, sorting]
343
+ );
344
+ const refresh = React3.useCallback(() => runFetch("replace"), [runFetch]);
345
+ const loadMore = React3.useCallback(async () => {
346
+ if (!hasMore || loading) return;
347
+ await runFetch("append");
348
+ }, [hasMore, loading, runFetch]);
349
+ const patchRow = React3.useCallback(
350
+ async (rowId, patch) => {
351
+ const previousRow = rows.find((row, index) => resolveRowId(row, index) === rowId);
352
+ setRows(
353
+ (prev) => prev.map((row, index) => resolveRowId(row, index) === rowId ? { ...row, ...patch } : row)
354
+ );
355
+ if (!updateRowRef.current) return;
356
+ const abort = new AbortController();
357
+ try {
358
+ const result = await updateRowRef.current({
359
+ rowId,
360
+ patch,
361
+ previousRow,
362
+ signal: abort.signal
363
+ });
364
+ if (!result) return;
365
+ setRows(
366
+ (prev) => prev.map(
367
+ (row, index) => resolveRowId(row, index) === rowId ? { ...row, ...result } : row
368
+ )
369
+ );
370
+ } catch (nextError) {
371
+ setError(nextError);
372
+ if (previousRow) {
373
+ setRows(
374
+ (prev) => prev.map((row, index) => resolveRowId(row, index) === rowId ? previousRow : row)
375
+ );
376
+ }
377
+ }
378
+ },
379
+ [resolveRowId, rows]
380
+ );
381
+ React3.useEffect(() => {
382
+ fetchDataRef.current = fetchData;
383
+ }, [fetchData]);
384
+ React3.useEffect(() => {
385
+ updateRowRef.current = updateRow;
386
+ }, [updateRow]);
387
+ React3.useEffect(() => {
388
+ if (!autoLoad) return;
389
+ void refresh();
390
+ }, [autoLoad, refresh]);
391
+ React3.useEffect(() => {
392
+ cursorRef.current = cursor;
393
+ }, [cursor]);
394
+ React3.useEffect(() => () => abortRef.current?.abort(), []);
395
+ const table = useTable({
396
+ ...tableOptions,
397
+ data: rows,
398
+ getRowId: resolveRowId,
399
+ manualSorting: true,
400
+ manualFiltering: true,
401
+ manualPagination: true,
402
+ rowCount,
403
+ pageCount,
404
+ state: {
405
+ sorting,
406
+ columnFilters,
407
+ globalFilter,
408
+ pagination
409
+ },
410
+ onSortingChange: (updater) => {
411
+ setSorting((prev) => yableCore.functionalUpdate(updater, prev));
412
+ setCursor(null);
413
+ setHasMore(true);
414
+ },
415
+ onColumnFiltersChange: (updater) => {
416
+ setColumnFilters((prev) => yableCore.functionalUpdate(updater, prev));
417
+ setCursor(null);
418
+ setHasMore(true);
419
+ },
420
+ onGlobalFilterChange: (updater) => {
421
+ setGlobalFilter((prev) => yableCore.functionalUpdate(updater, prev));
422
+ setCursor(null);
423
+ setHasMore(true);
424
+ },
425
+ onPaginationChange: (updater) => {
426
+ setPagination((prev) => yableCore.functionalUpdate(updater, prev));
427
+ setCursor(null);
428
+ setHasMore(true);
429
+ }
430
+ });
431
+ return React3.useMemo(
432
+ () => ({
433
+ table,
434
+ rows,
435
+ loading,
436
+ error,
437
+ cursor,
438
+ hasMore,
439
+ rowCount,
440
+ pageCount,
441
+ sorting,
442
+ columnFilters,
443
+ globalFilter,
444
+ pagination,
445
+ refresh,
446
+ loadMore,
447
+ updateRow: patchRow
448
+ }),
449
+ [
450
+ table,
451
+ rows,
452
+ loading,
453
+ error,
454
+ cursor,
455
+ hasMore,
456
+ rowCount,
457
+ pageCount,
458
+ sorting,
459
+ columnFilters,
460
+ globalFilter,
461
+ pagination,
462
+ refresh,
463
+ loadMore,
464
+ patchRow
465
+ ]
466
+ );
467
+ }
468
+ var DEFAULT_PERSISTED_KEYS = [
469
+ "columnVisibility",
470
+ "columnOrder",
471
+ "columnSizing",
472
+ "columnPinning"
473
+ ];
474
+ function resolveStorage(custom) {
475
+ if (custom) return custom;
476
+ if (typeof window !== "undefined") {
477
+ try {
478
+ return window.localStorage;
479
+ } catch {
480
+ return void 0;
481
+ }
482
+ }
483
+ return void 0;
484
+ }
485
+ function pick(obj, keys) {
486
+ const result = {};
487
+ for (const k of keys) {
488
+ if (k in obj) {
489
+ result[k] = obj[k];
490
+ }
491
+ }
492
+ return result;
493
+ }
494
+ function readState(storage, key, version, persistedKeys) {
495
+ if (!storage) return {};
496
+ try {
497
+ const raw = storage.getItem(key);
498
+ if (!raw) return {};
499
+ const envelope = JSON.parse(raw);
500
+ if (envelope.version !== version) {
501
+ storage.removeItem(key);
502
+ return {};
503
+ }
504
+ return pick(envelope.state, persistedKeys);
505
+ } catch {
506
+ if (typeof console !== "undefined") {
507
+ console.warn(`[yable] Failed to read persisted state for key "${key}"`);
508
+ }
509
+ return {};
510
+ }
511
+ }
512
+ function writeState(storage, key, version, state) {
513
+ if (!storage) return;
514
+ try {
515
+ const envelope = { version, state };
516
+ storage.setItem(key, JSON.stringify(envelope));
517
+ } catch {
518
+ if (typeof console !== "undefined") {
519
+ console.warn(`[yable] Failed to persist state for key "${key}" (storage may be full)`);
520
+ }
521
+ }
522
+ }
523
+ function useTablePersistence(options) {
524
+ const {
525
+ key,
526
+ persistedKeys = DEFAULT_PERSISTED_KEYS,
527
+ debounce: debounceMs = 100,
528
+ version = 0,
529
+ storage: customStorage
530
+ } = options;
531
+ const storage = React3.useMemo(() => resolveStorage(customStorage), [customStorage]);
532
+ const initialState = React3.useMemo(
533
+ () => readState(storage, key, version, persistedKeys),
534
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally read only on mount
535
+ []
536
+ );
537
+ const [state, setState] = React3.useState(initialState);
538
+ const timerRef = React3.useRef(null);
539
+ const keyRef = React3.useRef(key);
540
+ keyRef.current = key;
541
+ const versionRef = React3.useRef(version);
542
+ versionRef.current = version;
543
+ const persistedKeysRef = React3.useRef(persistedKeys);
544
+ persistedKeysRef.current = persistedKeys;
545
+ const debounceRef = React3.useRef(debounceMs);
546
+ debounceRef.current = debounceMs;
547
+ const storageRef = React3.useRef(storage);
548
+ storageRef.current = storage;
549
+ const onStateChange = React3.useCallback((updater) => {
550
+ setState((prev) => {
551
+ const next = yableCore.functionalUpdate(updater, prev);
552
+ if (timerRef.current !== null) {
553
+ clearTimeout(timerRef.current);
554
+ }
555
+ timerRef.current = setTimeout(() => {
556
+ const sliced = pick(
557
+ next,
558
+ persistedKeysRef.current
559
+ );
560
+ writeState(storageRef.current, keyRef.current, versionRef.current, sliced);
561
+ timerRef.current = null;
562
+ }, debounceRef.current);
563
+ return next;
564
+ });
565
+ }, []);
566
+ React3.useEffect(() => {
567
+ return () => {
568
+ if (timerRef.current !== null) {
569
+ clearTimeout(timerRef.current);
570
+ }
571
+ };
572
+ }, []);
573
+ const clearPersistedState = React3.useCallback(() => {
574
+ const s = storageRef.current;
575
+ if (s) {
576
+ try {
577
+ s.removeItem(keyRef.current);
578
+ } catch {
579
+ }
580
+ }
581
+ }, []);
582
+ return { initialState, state, onStateChange, clearPersistedState };
583
+ }
120
584
  var EMPTY_RESULT = {
121
585
  virtualRows: [],
122
586
  totalHeight: 0,
@@ -130,11 +594,14 @@ function useVirtualization({
130
594
  overscan = 5,
131
595
  estimateRowHeight: _estimateRowHeight,
132
596
  pretextHeights,
133
- pretextPrefixSums
597
+ pretextPrefixSums,
598
+ columnSizingHash
134
599
  }) {
135
600
  const hasPretextHeights = !!(pretextHeights && pretextPrefixSums && pretextHeights.length >= totalRows);
136
601
  const isFixedHeight = typeof rowHeight === "number" && !hasPretextHeights;
137
602
  const heightCacheRef = React3.useRef(/* @__PURE__ */ new Map());
603
+ const heightCacheVersionRef = React3.useRef(0);
604
+ const [heightCacheVersion, setHeightCacheVersion] = React3.useState(0);
138
605
  const getRowHeight = React3.useCallback(
139
606
  (index) => {
140
607
  if (hasPretextHeights) return pretextHeights[index];
@@ -145,7 +612,9 @@ function useVirtualization({
145
612
  heightCacheRef.current.set(index, height);
146
613
  return height;
147
614
  },
148
- [rowHeight, isFixedHeight, hasPretextHeights, pretextHeights]
615
+ // heightCacheVersion forces a new callback identity after cache invalidation
616
+ // eslint-disable-next-line react-hooks/exhaustive-deps
617
+ [rowHeight, isFixedHeight, hasPretextHeights, pretextHeights, heightCacheVersion]
149
618
  );
150
619
  const [scrollState, setScrollState] = React3.useState({ scrollTop: 0, containerHeight: 0 });
151
620
  const rafRef = React3.useRef(null);
@@ -192,12 +661,24 @@ function useVirtualization({
192
661
  resizeObserver.disconnect();
193
662
  }
194
663
  };
195
- }, [containerRef]);
664
+ }, [containerRef, totalRows]);
196
665
  React3.useEffect(() => {
197
666
  if (!isFixedHeight) {
198
667
  heightCacheRef.current.clear();
199
668
  }
200
669
  }, [totalRows, isFixedHeight]);
670
+ React3.useEffect(() => {
671
+ if (!isFixedHeight && columnSizingHash !== void 0) {
672
+ heightCacheRef.current.clear();
673
+ heightCacheVersionRef.current += 1;
674
+ setHeightCacheVersion(heightCacheVersionRef.current);
675
+ }
676
+ }, [columnSizingHash]);
677
+ const invalidateRowHeights = React3.useCallback(() => {
678
+ heightCacheRef.current.clear();
679
+ heightCacheVersionRef.current += 1;
680
+ setHeightCacheVersion(heightCacheVersionRef.current);
681
+ }, []);
201
682
  const scrollTo = React3.useCallback(
202
683
  (index) => {
203
684
  const container = containerRef.current;
@@ -234,10 +715,18 @@ function useVirtualization({
234
715
  total += getRowHeight(i);
235
716
  }
236
717
  return total;
237
- }, [totalRows, rowHeight, isFixedHeight, getRowHeight, hasPretextHeights, pretextPrefixSums]);
718
+ }, [
719
+ totalRows,
720
+ rowHeight,
721
+ isFixedHeight,
722
+ getRowHeight,
723
+ hasPretextHeights,
724
+ pretextPrefixSums,
725
+ heightCacheVersion
726
+ ]);
238
727
  const { scrollTop, containerHeight } = scrollState;
239
728
  if (totalRows === 0) {
240
- return { ...EMPTY_RESULT, scrollTo };
729
+ return { ...EMPTY_RESULT, scrollTo, invalidateRowHeights };
241
730
  }
242
731
  if (containerHeight === 0) {
243
732
  return {
@@ -245,7 +734,8 @@ function useVirtualization({
245
734
  totalHeight,
246
735
  startIndex: 0,
247
736
  endIndex: 0,
248
- scrollTo
737
+ scrollTo,
738
+ invalidateRowHeights
249
739
  };
250
740
  }
251
741
  let startIndex = 0;
@@ -341,7 +831,8 @@ function useVirtualization({
341
831
  totalHeight,
342
832
  startIndex: overscanStart,
343
833
  endIndex: overscanEnd,
344
- scrollTo
834
+ scrollTo,
835
+ invalidateRowHeights
345
836
  };
346
837
  }
347
838
  function binarySearchOffsets(offsets, target) {
@@ -361,14 +852,20 @@ function useColumnVirtualization({
361
852
  containerRef,
362
853
  columns,
363
854
  overscan = 2,
364
- enabled = true
855
+ enabled = true,
856
+ sizingKey
365
857
  }) {
366
858
  const [scrollState, setScrollState] = React3.useState({
367
859
  scrollLeft: 0,
368
860
  containerWidth: 0
369
861
  });
370
862
  const rafRef = React3.useRef(null);
371
- const sizes = React3.useMemo(() => columns.map((column) => column.getSize()), [columns]);
863
+ const sizes = React3.useMemo(
864
+ () => columns.map((column) => column.getSize()),
865
+ // `sizingKey` is an explicit invalidation hook for stable Column objects whose getSize value changed.
866
+ // eslint-disable-next-line react-hooks/exhaustive-deps
867
+ [columns, sizingKey]
868
+ );
372
869
  const offsets = React3.useMemo(() => {
373
870
  const next = new Array(columns.length + 1);
374
871
  next[0] = 0;
@@ -946,12 +1443,12 @@ function getRegisteredCellTypes() {
946
1443
 
947
1444
  // src/hooks/useAutoMeasurements.ts
948
1445
  var NON_DATA_COLUMN_IDS = /* @__PURE__ */ new Set(["select", "expand", "drag", "actions"]);
949
- function getColumnId(col) {
1446
+ function getColumnId2(col) {
950
1447
  const id = col.id ?? col.accessorKey;
951
1448
  return typeof id === "string" ? id : void 0;
952
1449
  }
953
1450
  function defaultShouldMeasure(col) {
954
- const id = getColumnId(col);
1451
+ const id = getColumnId2(col);
955
1452
  if (!id) return false;
956
1453
  if (id.startsWith("_")) return false;
957
1454
  if (NON_DATA_COLUMN_IDS.has(id)) return false;
@@ -976,11 +1473,11 @@ function useAutoMeasurements({
976
1473
  getColumnWidth = defaultGetColumnWidth,
977
1474
  shouldMeasureColumn = defaultShouldMeasure
978
1475
  }) {
979
- const widthKey = columns.map((c) => `${getColumnId(c) ?? "?"}:${getColumnWidth(c)}`).join("|");
1476
+ const widthKey = columns.map((c) => `${getColumnId2(c) ?? "?"}:${getColumnWidth(c)}`).join("|");
980
1477
  return React3.useMemo(() => {
981
1478
  const result = [];
982
1479
  for (const col of columns) {
983
- const id = getColumnId(col);
1480
+ const id = getColumnId2(col);
984
1481
  if (!id) continue;
985
1482
  if (!shouldMeasureColumn(col)) continue;
986
1483
  const recipe = resolveMeasureRecipe(col, defaultRecipe);
@@ -1299,16 +1796,170 @@ function FloatingFilter({ column }) {
1299
1796
  }
1300
1797
  ) });
1301
1798
  }
1302
- var DRAG_MIME = "application/yable-column";
1799
+ var REORDER_TRANSITION = "transform 180ms cubic-bezier(0.2, 0, 0, 1)";
1800
+ function transformAt(i, d) {
1801
+ if (i === d.fromIndex) return 0;
1802
+ if (d.toIndex > d.fromIndex) return i > d.fromIndex && i < d.toIndex ? -d.width : 0;
1803
+ return i >= d.toIndex && i < d.fromIndex ? d.width : 0;
1804
+ }
1303
1805
  function TableHeader({
1304
1806
  table,
1305
1807
  floatingFilters = false
1306
1808
  }) {
1307
1809
  const headerGroups = table.getHeaderGroups();
1308
1810
  const visibleColumns = table.getVisibleLeafColumns();
1309
- return /* @__PURE__ */ jsxRuntime.jsxs("thead", { className: "yable-thead", children: [
1310
- headerGroups.map((headerGroup) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "yable-header-row", children: headerGroup.headers.map((header) => /* @__PURE__ */ jsxRuntime.jsx(HeaderCell, { header, table }, header.id)) }, headerGroup.id)),
1311
- floatingFilters && visibleColumns.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "yable-header-row yable-header-row--filters", children: visibleColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(FloatingFilterCell, { column }, `${column.id}-filter`)) })
1811
+ const theadRef = React3.useRef(null);
1812
+ const reorderEndRef = React3.useRef(0);
1813
+ const [drag, setDrag] = React3.useState(null);
1814
+ const commitReorder = React3.useCallback(
1815
+ (d) => {
1816
+ if (d.toIndex === d.fromIndex || d.toIndex === d.fromIndex + 1) return;
1817
+ const order = table.getState().columnOrder;
1818
+ const base = order && order.length > 0 ? [...order] : d.layout.map((l) => l.id);
1819
+ const targetId = d.toIndex < d.layout.length ? d.layout[d.toIndex].id : null;
1820
+ const next = base.filter((id) => id !== d.columnId);
1821
+ let insertAt = targetId ? next.indexOf(targetId) : next.length;
1822
+ if (insertAt === -1) insertAt = next.length;
1823
+ next.splice(insertAt, 0, d.columnId);
1824
+ table.setColumnOrder(next);
1825
+ },
1826
+ [table]
1827
+ );
1828
+ const beginReorder = React3.useCallback(
1829
+ (e, columnId) => {
1830
+ if (e.button !== 0) return;
1831
+ const thead = theadRef.current;
1832
+ if (!thead) return;
1833
+ const startX = e.clientX;
1834
+ const startY = e.clientY;
1835
+ const layout = [];
1836
+ let top = 0;
1837
+ let height = 0;
1838
+ for (const c of visibleColumns) {
1839
+ const th = thead.querySelector(`th[data-column-id="${CSS.escape(c.id)}"]`);
1840
+ if (!th) return;
1841
+ const r = th.getBoundingClientRect();
1842
+ layout.push({ id: c.id, left: r.left, width: r.width });
1843
+ if (c.id === columnId) {
1844
+ top = r.top;
1845
+ height = r.height;
1846
+ }
1847
+ }
1848
+ const fromIndex = layout.findIndex((l) => l.id === columnId);
1849
+ if (fromIndex < 0) return;
1850
+ const src = layout[fromIndex];
1851
+ const bodyRoot = thead.closest("table");
1852
+ const applyBody = (d) => {
1853
+ if (!bodyRoot) return;
1854
+ visibleColumns.forEach((col, i) => {
1855
+ if (col.getIsPinned()) return;
1856
+ const tx = transformAt(i, d);
1857
+ bodyRoot.querySelectorAll(`td[data-column-id="${CSS.escape(col.id)}"]`).forEach((td) => {
1858
+ td.style.transition = REORDER_TRANSITION;
1859
+ td.style.opacity = i === d.fromIndex ? "0" : "";
1860
+ td.style.transform = i !== d.fromIndex && tx ? `translateX(${tx}px)` : "";
1861
+ });
1862
+ });
1863
+ };
1864
+ const clearBody = () => {
1865
+ bodyRoot?.querySelectorAll("td[data-column-id]").forEach((td) => {
1866
+ td.style.transform = "";
1867
+ td.style.transition = "";
1868
+ td.style.opacity = "";
1869
+ });
1870
+ };
1871
+ let started = false;
1872
+ let latest = {
1873
+ columnId,
1874
+ fromIndex,
1875
+ toIndex: fromIndex,
1876
+ pointerX: startX,
1877
+ grabOffsetX: startX - src.left,
1878
+ width: src.width,
1879
+ top,
1880
+ height,
1881
+ layout
1882
+ };
1883
+ const computeToIndex = (x) => {
1884
+ let t = layout.findIndex((l) => x < l.left + l.width / 2);
1885
+ if (t === -1) t = layout.length;
1886
+ return t;
1887
+ };
1888
+ const onMove = (ev) => {
1889
+ if (!started) {
1890
+ if (Math.abs(ev.clientX - startX) < 4 && Math.abs(ev.clientY - startY) < 4) return;
1891
+ started = true;
1892
+ table.setColumnDragActive(true);
1893
+ document.body.style.userSelect = "none";
1894
+ document.body.style.cursor = "grabbing";
1895
+ }
1896
+ latest = { ...latest, pointerX: ev.clientX, toIndex: computeToIndex(ev.clientX) };
1897
+ setDrag(latest);
1898
+ applyBody(latest);
1899
+ };
1900
+ const finish = () => {
1901
+ window.removeEventListener("pointermove", onMove);
1902
+ window.removeEventListener("pointerup", finish);
1903
+ window.removeEventListener("pointercancel", finish);
1904
+ if (started) {
1905
+ commitReorder(latest);
1906
+ reorderEndRef.current = Date.now();
1907
+ table.setColumnDragActive(false);
1908
+ document.body.style.userSelect = "";
1909
+ document.body.style.cursor = "";
1910
+ clearBody();
1911
+ }
1912
+ setDrag(null);
1913
+ };
1914
+ window.addEventListener("pointermove", onMove);
1915
+ window.addEventListener("pointerup", finish);
1916
+ window.addEventListener("pointercancel", finish);
1917
+ },
1918
+ [visibleColumns, table, commitReorder]
1919
+ );
1920
+ const transformFor = React3.useCallback(
1921
+ (columnId) => {
1922
+ if (!drag) return 0;
1923
+ const i = visibleColumns.findIndex((c) => c.id === columnId);
1924
+ if (i < 0) return 0;
1925
+ return transformAt(i, drag);
1926
+ },
1927
+ [drag, visibleColumns]
1928
+ );
1929
+ const dragColumn = drag ? visibleColumns.find((c) => c.id === drag.columnId) : null;
1930
+ return /* @__PURE__ */ jsxRuntime.jsxs("thead", { className: "yable-thead", ref: theadRef, children: [
1931
+ headerGroups.map((headerGroup) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "yable-header-row", children: headerGroup.headers.map((header) => /* @__PURE__ */ jsxRuntime.jsx(
1932
+ HeaderCell,
1933
+ {
1934
+ header,
1935
+ table,
1936
+ onReorderPointerDown: beginReorder,
1937
+ dragTransform: transformFor(header.column.id),
1938
+ isDragSource: drag?.columnId === header.column.id,
1939
+ dragActive: drag !== null,
1940
+ reorderEndRef
1941
+ },
1942
+ header.id
1943
+ )) }, headerGroup.id)),
1944
+ floatingFilters && visibleColumns.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "yable-header-row yable-header-row--filters", children: visibleColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(FloatingFilterCell, { column }, `${column.id}-filter`)) }),
1945
+ drag && dragColumn && typeof document !== "undefined" && reactDom.createPortal(
1946
+ /* @__PURE__ */ jsxRuntime.jsx(
1947
+ "div",
1948
+ {
1949
+ className: "yable-col-drag-ghost",
1950
+ "aria-hidden": "true",
1951
+ style: {
1952
+ position: "fixed",
1953
+ top: drag.top,
1954
+ left: drag.pointerX - drag.grabOffsetX,
1955
+ width: drag.width,
1956
+ height: drag.height
1957
+ },
1958
+ children: typeof dragColumn.columnDef.header === "string" ? dragColumn.columnDef.header : dragColumn.id
1959
+ }
1960
+ ),
1961
+ document.body
1962
+ )
1312
1963
  ] });
1313
1964
  }
1314
1965
  function FloatingFilterCell({
@@ -1337,7 +1988,12 @@ function FloatingFilterCell({
1337
1988
  }
1338
1989
  function HeaderCell({
1339
1990
  header,
1340
- table
1991
+ table,
1992
+ onReorderPointerDown,
1993
+ dragTransform,
1994
+ isDragSource,
1995
+ dragActive,
1996
+ reorderEndRef
1341
1997
  }) {
1342
1998
  const column = header.column;
1343
1999
  const canSort = column.getCanSort();
@@ -1345,6 +2001,7 @@ function HeaderCell({
1345
2001
  const sortIndex = column.getSortIndex();
1346
2002
  const canResize = column.getCanResize();
1347
2003
  const canReorder = column.getCanReorder() && !header.isPlaceholder;
2004
+ const pinned = column.getIsPinned();
1348
2005
  const headerContent = header.isPlaceholder ? null : typeof column.columnDef.header === "function" ? column.columnDef.header(header.getContext()) : column.columnDef.header ?? header.id;
1349
2006
  const style = React3.useMemo(() => {
1350
2007
  const s = {
@@ -1352,18 +2009,19 @@ function HeaderCell({
1352
2009
  minWidth: column.columnDef.minSize,
1353
2010
  maxWidth: column.columnDef.maxSize
1354
2011
  };
1355
- const pinned2 = column.getIsPinned();
1356
- if (pinned2) {
2012
+ if (pinned) {
1357
2013
  s.position = "sticky";
1358
- if (pinned2 === "left") {
2014
+ if (pinned === "left") {
1359
2015
  s.left = header.getStart("left");
1360
2016
  } else {
1361
2017
  s.right = header.getStart("right");
1362
2018
  }
1363
2019
  }
2020
+ if (!pinned && !isDragSource && dragTransform !== 0) {
2021
+ s.transform = `translateX(${dragTransform}px)`;
2022
+ }
1364
2023
  return s;
1365
- }, [header, column]);
1366
- const pinned = column.getIsPinned();
2024
+ }, [header, column, pinned, isDragSource, dragTransform]);
1367
2025
  const lastResizeEndRef = React3.useRef(0);
1368
2026
  const startResize = React3.useCallback(
1369
2027
  (e) => {
@@ -1383,124 +2041,66 @@ function HeaderCell({
1383
2041
  const handleResizeClick = React3.useCallback((e) => {
1384
2042
  e.stopPropagation();
1385
2043
  }, []);
1386
- const [dragOver, setDragOver] = React3.useState(null);
1387
- const handleDragStart = React3.useCallback(
2044
+ const handleContentPointerDown = React3.useCallback(
1388
2045
  (e) => {
1389
- if (!canReorder) return;
1390
- const target = e.target;
1391
- if (target && target.closest(".yable-resize-handle")) {
1392
- e.preventDefault();
1393
- return;
1394
- }
1395
- e.stopPropagation();
1396
- e.dataTransfer.effectAllowed = "move";
1397
- try {
1398
- e.dataTransfer.setData(DRAG_MIME, column.id);
1399
- e.dataTransfer.setData("text/plain", column.id);
1400
- } catch {
1401
- }
1402
- },
1403
- [canReorder, column.id]
1404
- );
1405
- const handleDragOver = React3.useCallback(
1406
- (e) => {
1407
- if (!canReorder) return;
1408
- const types = e.dataTransfer.types;
1409
- let isYableDrag = false;
1410
- for (let i = 0; i < types.length; i++) {
1411
- if (types[i] === DRAG_MIME) {
1412
- isYableDrag = true;
1413
- break;
1414
- }
1415
- }
1416
- if (!isYableDrag) return;
1417
- e.preventDefault();
1418
- e.dataTransfer.dropEffect = "move";
1419
- const rect = e.currentTarget.getBoundingClientRect();
1420
- const midpoint = rect.left + rect.width / 2;
1421
- setDragOver(e.clientX < midpoint ? "left" : "right");
1422
- },
1423
- [canReorder]
1424
- );
1425
- const handleDragLeave = React3.useCallback((e) => {
1426
- const next = e.relatedTarget;
1427
- if (next && e.currentTarget.contains(next)) return;
1428
- setDragOver(null);
1429
- }, []);
1430
- const handleDragEnd = React3.useCallback(() => {
1431
- setDragOver(null);
1432
- }, []);
1433
- const handleDrop = React3.useCallback(
1434
- (e) => {
1435
- if (!canReorder) return;
1436
- e.preventDefault();
1437
- e.stopPropagation();
1438
- const sourceId = e.dataTransfer.getData(DRAG_MIME);
1439
- const rect = e.currentTarget.getBoundingClientRect();
1440
- const insertAfter = e.clientX >= rect.left + rect.width / 2;
1441
- setDragOver(null);
1442
- if (!sourceId || sourceId === column.id) return;
1443
- const state = table.getState();
1444
- const allLeafs = table.getAllLeafColumns();
1445
- const baseOrder = state.columnOrder && state.columnOrder.length > 0 ? state.columnOrder : allLeafs.map((c) => c.id);
1446
- const next = [];
1447
- const seen = /* @__PURE__ */ new Set();
1448
- for (const id of baseOrder) {
1449
- if (allLeafs.some((c) => c.id === id)) {
1450
- next.push(id);
1451
- seen.add(id);
1452
- }
1453
- }
1454
- for (const c of allLeafs) {
1455
- if (!seen.has(c.id)) {
1456
- next.push(c.id);
1457
- seen.add(c.id);
1458
- }
1459
- }
1460
- const fromIdx = next.indexOf(sourceId);
1461
- if (fromIdx === -1) return;
1462
- next.splice(fromIdx, 1);
1463
- let toIdx = next.indexOf(column.id);
1464
- if (toIdx === -1) return;
1465
- if (insertAfter) toIdx += 1;
1466
- next.splice(toIdx, 0, sourceId);
1467
- table.setColumnOrder(next);
2046
+ if (!canReorder || pinned) return;
2047
+ onReorderPointerDown(e, column.id);
1468
2048
  },
1469
- [canReorder, column.id, table]
2049
+ [canReorder, pinned, onReorderPointerDown, column.id]
1470
2050
  );
1471
2051
  const handleHeaderClick = React3.useCallback(
1472
2052
  (e) => {
2053
+ table.events.emit("header:click", {
2054
+ column,
2055
+ header,
2056
+ originalEvent: e
2057
+ });
1473
2058
  if (!canSort) return;
1474
2059
  if (Date.now() - lastResizeEndRef.current < 250) return;
2060
+ if (Date.now() - reorderEndRef.current < 250) return;
1475
2061
  const handler = column.getToggleSortingHandler();
1476
2062
  if (handler) handler(e);
1477
2063
  },
1478
- [canSort, column]
2064
+ [canSort, column, header, table.events, reorderEndRef]
2065
+ );
2066
+ const handleHeaderContextMenu = React3.useCallback(
2067
+ (e) => {
2068
+ table.events.emit("header:contextmenu", {
2069
+ column,
2070
+ header,
2071
+ originalEvent: e
2072
+ });
2073
+ },
2074
+ [column, header, table.events]
1479
2075
  );
1480
2076
  return /* @__PURE__ */ jsxRuntime.jsxs(
1481
2077
  "th",
1482
2078
  {
1483
2079
  className: "yable-th",
1484
2080
  style,
2081
+ "data-column-id": column.id,
1485
2082
  "data-sortable": canSort || void 0,
1486
2083
  "data-pinned": pinned || void 0,
1487
- "data-reorderable": canReorder || void 0,
1488
- "data-drag-over": dragOver || void 0,
2084
+ "data-reorderable": canReorder && !pinned || void 0,
2085
+ "data-reordering": dragActive && !pinned || void 0,
2086
+ "data-drag-source": isDragSource || void 0,
1489
2087
  "aria-sort": sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : canSort ? "none" : void 0,
1490
2088
  role: "columnheader",
1491
2089
  colSpan: header.colSpan,
1492
- draggable: canReorder || void 0,
1493
2090
  onClick: handleHeaderClick,
1494
- onDragStart: canReorder ? handleDragStart : void 0,
1495
- onDragOver: canReorder ? handleDragOver : void 0,
1496
- onDragLeave: canReorder ? handleDragLeave : void 0,
1497
- onDragEnd: canReorder ? handleDragEnd : void 0,
1498
- onDrop: canReorder ? handleDrop : void 0,
2091
+ onContextMenu: handleHeaderContextMenu,
1499
2092
  children: [
1500
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "yable-th-content", children: [
1501
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: headerContent }),
1502
- canSort && /* @__PURE__ */ jsxRuntime.jsx(SortIndicator, { direction: sortDirection, index: sortIndex > 0 ? sortIndex : void 0 })
1503
- ] }),
2093
+ /* @__PURE__ */ jsxRuntime.jsxs(
2094
+ "div",
2095
+ {
2096
+ className: "yable-th-content",
2097
+ onPointerDown: canReorder && !pinned ? handleContentPointerDown : void 0,
2098
+ children: [
2099
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: headerContent }),
2100
+ canSort && /* @__PURE__ */ jsxRuntime.jsx(SortIndicator, { direction: sortDirection, index: sortIndex > 0 ? sortIndex : void 0 })
2101
+ ]
2102
+ }
2103
+ ),
1504
2104
  canResize && /* @__PURE__ */ jsxRuntime.jsx(
1505
2105
  "div",
1506
2106
  {
@@ -1508,9 +2108,7 @@ function HeaderCell({
1508
2108
  "data-resizing": column.getIsResizing() || void 0,
1509
2109
  onMouseDown: startResize,
1510
2110
  onTouchStart: startResize,
1511
- onClick: handleResizeClick,
1512
- draggable: false,
1513
- onDragStart: (e) => e.preventDefault()
2111
+ onClick: handleResizeClick
1514
2112
  }
1515
2113
  )
1516
2114
  ]
@@ -1608,6 +2206,7 @@ function TableCell({
1608
2206
  const isAlwaysEditable = cell.getIsAlwaysEditable();
1609
2207
  const pinned = column.getIsPinned();
1610
2208
  const keyboardNavigationEnabled = table.options.enableKeyboardNavigation !== false;
2209
+ const cellSelectionEnabled = table.options.enableCellSelection !== false && column.columnDef.enableCellSelection !== false;
1611
2210
  const style = {
1612
2211
  width: column.getSize(),
1613
2212
  minWidth: column.columnDef.minSize,
@@ -1692,6 +2291,7 @@ function TableCell({
1692
2291
  const handleMouseDown = React3.useCallback(
1693
2292
  (e) => {
1694
2293
  if (e.button !== 0) return;
2294
+ if (!cellSelectionEnabled) return;
1695
2295
  const clickTarget = e.target;
1696
2296
  if (isInteractiveClickTarget(clickTarget)) return;
1697
2297
  e.preventDefault();
@@ -1699,16 +2299,22 @@ function TableCell({
1699
2299
  table.startCellRangeSelection({ rowIndex, columnIndex }, { extend: e.shiftKey });
1700
2300
  e.currentTarget.focus({ preventScroll: true });
1701
2301
  },
1702
- [columnIndex, rowIndex, table]
2302
+ [cellSelectionEnabled, columnIndex, rowIndex, table]
1703
2303
  );
1704
2304
  const handleMouseEnter = React3.useCallback(() => {
2305
+ if (!cellSelectionEnabled) return;
1705
2306
  if (!table.getState().cellSelection?.isDragging) return;
1706
2307
  table.updateCellRangeSelection({ rowIndex, columnIndex });
1707
- }, [columnIndex, rowIndex, table]);
2308
+ }, [cellSelectionEnabled, columnIndex, rowIndex, table]);
1708
2309
  const handleMouseUp = React3.useCallback(() => {
1709
2310
  if (!table.getState().cellSelection?.isDragging) return;
1710
2311
  table.endCellRangeSelection();
1711
2312
  }, [table]);
2313
+ const cellClassNameDef = column.columnDef.cellClassName;
2314
+ const userClassName = typeof cellClassNameDef === "function" ? cellClassNameDef(cell.getContext()) : cellClassNameDef;
2315
+ const cellStyleDef = column.columnDef.cellStyle;
2316
+ const userStyle = typeof cellStyleDef === "function" ? cellStyleDef(cell.getContext()) : cellStyleDef;
2317
+ const mergedStyle = userStyle ? { ...style, ...userStyle } : style;
1712
2318
  const classNames = [
1713
2319
  "yable-td",
1714
2320
  isFocused && "yable-cell--focused",
@@ -1716,13 +2322,14 @@ function TableCell({
1716
2322
  selectionEdges?.top && "yable-cell--selection-top",
1717
2323
  selectionEdges?.right && "yable-cell--selection-right",
1718
2324
  selectionEdges?.bottom && "yable-cell--selection-bottom",
1719
- selectionEdges?.left && "yable-cell--selection-left"
2325
+ selectionEdges?.left && "yable-cell--selection-left",
2326
+ userClassName
1720
2327
  ].filter(Boolean).join(" ");
1721
2328
  return /* @__PURE__ */ jsxRuntime.jsxs(
1722
2329
  "td",
1723
2330
  {
1724
2331
  className: classNames,
1725
- style,
2332
+ style: mergedStyle,
1726
2333
  "data-editing": isEditing || void 0,
1727
2334
  "data-focused": isFocused || void 0,
1728
2335
  "data-pinned": pinned || void 0,
@@ -1862,7 +2469,38 @@ var CellErrorBoundary = class extends React3__default.default.Component {
1862
2469
  return this.props.children;
1863
2470
  }
1864
2471
  };
1865
- function TableBody({ table, clickableRows }) {
2472
+ function MasterDetail({
2473
+ row,
2474
+ table,
2475
+ colSpan,
2476
+ renderDetailPanel,
2477
+ animationClass
2478
+ }) {
2479
+ const renderer = renderDetailPanel ?? table.options.renderDetailPanel;
2480
+ if (!renderer) return null;
2481
+ const content = renderer(row);
2482
+ if (content == null) return null;
2483
+ const classes = [
2484
+ "yable-detail-row",
2485
+ "yable-detail-row--animated",
2486
+ animationClass
2487
+ ].filter(Boolean).join(" ");
2488
+ return /* @__PURE__ */ jsxRuntime.jsx(
2489
+ "tr",
2490
+ {
2491
+ className: classes,
2492
+ "data-detail-for": row.id,
2493
+ role: "row",
2494
+ "aria-label": `Details for row ${row.id}`,
2495
+ children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "yable-detail-cell", colSpan, role: "cell", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "yable-detail-panel", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "yable-detail-panel-inner", children: content }) }) })
2496
+ }
2497
+ );
2498
+ }
2499
+ function TableBody({
2500
+ table,
2501
+ clickableRows,
2502
+ colgroup
2503
+ }) {
1866
2504
  const rows = table.getRowModel().rows;
1867
2505
  const visibleColumns = table.getVisibleLeafColumns();
1868
2506
  const activeCell = table.getState().editing.activeCell;
@@ -1871,6 +2509,7 @@ function TableBody({ table, clickableRows }) {
1871
2509
  range: null,
1872
2510
  isDragging: false
1873
2511
  };
2512
+ const pendingValues = table.getState().editing.pendingValues ?? {};
1874
2513
  const options = table.options;
1875
2514
  const enableVirtualization = options.enableVirtualization ?? false;
1876
2515
  const scrollContainerRef = React3.useRef(null);
@@ -1879,6 +2518,19 @@ function TableBody({ table, clickableRows }) {
1879
2518
  const estimateRowHeight = options.estimateRowHeight;
1880
2519
  const pretextHeights = options.pretextHeights ?? null;
1881
2520
  const pretextPrefixSums = options.pretextPrefixSums ?? null;
2521
+ const columnSizing = table.getState().columnSizing;
2522
+ const columnSizingHash = React3.useMemo(() => {
2523
+ const entries = Object.entries(columnSizing);
2524
+ if (entries.length === 0) return 0;
2525
+ let h = 0;
2526
+ for (const [key, value] of entries) {
2527
+ for (let i = 0; i < key.length; i++) {
2528
+ h = h * 31 + key.charCodeAt(i) | 0;
2529
+ }
2530
+ h = h * 31 + (value | 0) | 0;
2531
+ }
2532
+ return h;
2533
+ }, [columnSizing]);
1882
2534
  const { virtualRows, totalHeight } = useVirtualization({
1883
2535
  containerRef: scrollContainerRef,
1884
2536
  totalRows: rows.length,
@@ -1886,7 +2538,8 @@ function TableBody({ table, clickableRows }) {
1886
2538
  overscan,
1887
2539
  estimateRowHeight,
1888
2540
  pretextHeights,
1889
- pretextPrefixSums
2541
+ pretextPrefixSums,
2542
+ columnSizingHash
1890
2543
  });
1891
2544
  const cellSelectionKey = cellSelection.range ? `${cellSelection.range.start.rowIndex}:${cellSelection.range.start.columnIndex}:${cellSelection.range.end.rowIndex}:${cellSelection.range.end.columnIndex}:${cellSelection.isDragging ? "dragging" : "idle"}` : `none:${cellSelection.isDragging ? "dragging" : "idle"}`;
1892
2545
  React3.useEffect(() => {
@@ -1900,24 +2553,40 @@ function TableBody({ table, clickableRows }) {
1900
2553
  window.removeEventListener("mouseup", handleWindowMouseUp);
1901
2554
  };
1902
2555
  }, [table]);
2556
+ const renderRow = (row, rowIndex, pinnedPosition) => /* @__PURE__ */ jsxRuntime.jsx(
2557
+ MemoizedTableRow,
2558
+ {
2559
+ row,
2560
+ table,
2561
+ rowIndex,
2562
+ visibleColumns,
2563
+ isSelected: row.getIsSelected(),
2564
+ isExpanded: row.getIsExpanded(),
2565
+ activeColumnId: activeCell?.rowId === row.id ? activeCell.columnId : void 0,
2566
+ focusedColumnIndex: focusedCell?.rowIndex === rowIndex ? focusedCell.columnIndex : null,
2567
+ hasFocusedCell: focusedCell !== null,
2568
+ cellSelectionKey,
2569
+ pendingValuesKey: getPendingValuesKey(pendingValues[row.id]),
2570
+ clickable: clickableRows,
2571
+ pinnedPosition
2572
+ },
2573
+ row.id
2574
+ );
1903
2575
  if (!enableVirtualization) {
1904
- return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "yable-tbody", children: rows.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
1905
- MemoizedTableRow,
1906
- {
1907
- row,
1908
- table,
1909
- rowIndex,
1910
- visibleColumns,
1911
- isSelected: row.getIsSelected(),
1912
- isExpanded: row.getIsExpanded(),
1913
- activeColumnId: activeCell?.rowId === row.id ? activeCell.columnId : void 0,
1914
- focusedColumnIndex: focusedCell?.rowIndex === rowIndex ? focusedCell.columnIndex : null,
1915
- hasFocusedCell: focusedCell !== null,
1916
- cellSelectionKey,
1917
- clickable: clickableRows
1918
- },
1919
- row.id
1920
- )) });
2576
+ const rowPinning = table.getState().rowPinning;
2577
+ const hasPinnedRows = (rowPinning.top?.length ?? 0) > 0 || (rowPinning.bottom?.length ?? 0) > 0;
2578
+ if (hasPinnedRows) {
2579
+ const topRows = table.getTopRows();
2580
+ const centerRows = table.getCenterRows();
2581
+ const bottomRows = table.getBottomRows();
2582
+ let visualIndex = 0;
2583
+ return /* @__PURE__ */ jsxRuntime.jsxs("tbody", { className: "yable-tbody", children: [
2584
+ topRows.map((row) => renderRow(row, visualIndex++, "top")),
2585
+ centerRows.map((row) => renderRow(row, visualIndex++)),
2586
+ bottomRows.map((row) => renderRow(row, visualIndex++, "bottom"))
2587
+ ] });
2588
+ }
2589
+ return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "yable-tbody", children: rows.map((row, rowIndex) => renderRow(row, rowIndex)) });
1921
2590
  }
1922
2591
  const hasPretextData = !!(pretextHeights && pretextPrefixSums);
1923
2592
  const fixedRowHeight = typeof rowHeight === "number" && !hasPretextData ? rowHeight : void 0;
@@ -1937,7 +2606,7 @@ function TableBody({ table, clickableRows }) {
1937
2606
  {
1938
2607
  className: "yable-virtual-spacer",
1939
2608
  style: { height: totalHeight, position: "relative" },
1940
- children: /* @__PURE__ */ jsxRuntime.jsx(
2609
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1941
2610
  "table",
1942
2611
  {
1943
2612
  style: {
@@ -1948,35 +2617,39 @@ function TableBody({ table, clickableRows }) {
1948
2617
  tableLayout: "fixed",
1949
2618
  borderCollapse: "collapse"
1950
2619
  },
1951
- children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: virtualRows.map((vRow) => {
1952
- const row = rows[vRow.index];
1953
- if (!row) return null;
1954
- return /* @__PURE__ */ jsxRuntime.jsx(
1955
- MemoizedTableRow,
1956
- {
1957
- row,
1958
- table,
1959
- rowIndex: vRow.index,
1960
- visibleColumns,
1961
- isSelected: row.getIsSelected(),
1962
- isExpanded: row.getIsExpanded(),
1963
- activeColumnId: activeCell?.rowId === row.id ? activeCell.columnId : void 0,
1964
- focusedColumnIndex: focusedCell?.rowIndex === vRow.index ? focusedCell.columnIndex : null,
1965
- hasFocusedCell: focusedCell !== null,
1966
- cellSelectionKey,
1967
- clickable: clickableRows,
1968
- virtualStyle: {
1969
- position: "absolute",
1970
- top: 0,
1971
- left: 0,
1972
- width: "100%",
1973
- height: vRow.size,
1974
- transform: `translateY(${vRow.start}px)`
1975
- }
1976
- },
1977
- row.id
1978
- );
1979
- }) })
2620
+ children: [
2621
+ colgroup,
2622
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: virtualRows.map((vRow) => {
2623
+ const row = rows[vRow.index];
2624
+ if (!row) return null;
2625
+ return /* @__PURE__ */ jsxRuntime.jsx(
2626
+ MemoizedTableRow,
2627
+ {
2628
+ row,
2629
+ table,
2630
+ rowIndex: vRow.index,
2631
+ visibleColumns,
2632
+ isSelected: row.getIsSelected(),
2633
+ isExpanded: row.getIsExpanded(),
2634
+ activeColumnId: activeCell?.rowId === row.id ? activeCell.columnId : void 0,
2635
+ focusedColumnIndex: focusedCell?.rowIndex === vRow.index ? focusedCell.columnIndex : null,
2636
+ hasFocusedCell: focusedCell !== null,
2637
+ cellSelectionKey,
2638
+ pendingValuesKey: getPendingValuesKey(pendingValues[row.id]),
2639
+ clickable: clickableRows,
2640
+ virtualStyle: {
2641
+ position: "absolute",
2642
+ top: 0,
2643
+ left: 0,
2644
+ width: "100%",
2645
+ height: vRow.size,
2646
+ transform: `translateY(${vRow.start}px)`
2647
+ }
2648
+ },
2649
+ row.id
2650
+ );
2651
+ }) })
2652
+ ]
1980
2653
  }
1981
2654
  )
1982
2655
  }
@@ -1995,13 +2668,18 @@ function TableRowInner({
1995
2668
  focusedColumnIndex,
1996
2669
  hasFocusedCell,
1997
2670
  cellSelectionKey: _cellSelectionKey,
2671
+ pendingValuesKey: _pendingValuesKey,
1998
2672
  clickable,
2673
+ pinnedPosition,
1999
2674
  virtualStyle
2000
2675
  }) {
2001
2676
  const allCells = row.getAllCells();
2002
2677
  const visibleCells = visibleColumns.map((column) => allCells.find((cell) => cell.column.id === column.id)).filter((cell) => cell != null);
2003
2678
  const handleClick = React3.useCallback(
2004
2679
  (e) => {
2680
+ if (table.options.enableRowClickSelection && row.getCanSelect() && !isInteractiveClickTarget2(e.target)) {
2681
+ row.toggleSelected();
2682
+ }
2005
2683
  if (clickable) {
2006
2684
  table.events.emit("row:click", {
2007
2685
  row,
@@ -2009,7 +2687,7 @@ function TableRowInner({
2009
2687
  });
2010
2688
  }
2011
2689
  },
2012
- [clickable, table.events, row]
2690
+ [clickable, table, row]
2013
2691
  );
2014
2692
  const handleDoubleClick = React3.useCallback(
2015
2693
  (e) => {
@@ -2031,15 +2709,26 @@ function TableRowInner({
2031
2709
  );
2032
2710
  const selectionEnabled = Boolean(table.options.enableRowSelection);
2033
2711
  const expansionEnabled = Boolean(table.options.enableExpanding);
2712
+ const rowClassNameDef = table.options.rowClassName;
2713
+ const userRowClassName = typeof rowClassNameDef === "function" ? rowClassNameDef(row) : rowClassNameDef;
2714
+ const rowStyleDef = table.options.rowStyle;
2715
+ const userRowStyle = typeof rowStyleDef === "function" ? rowStyleDef(row) : rowStyleDef;
2716
+ const mergedRowStyle = userRowStyle ? { ...virtualStyle, ...userRowStyle } : virtualStyle;
2717
+ const rowClassName = [
2718
+ "yable-tr",
2719
+ pinnedPosition && `yable-tr--pinned-${pinnedPosition}`,
2720
+ userRowClassName
2721
+ ].filter(Boolean).join(" ");
2034
2722
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2035
2723
  /* @__PURE__ */ jsxRuntime.jsx(
2036
2724
  "tr",
2037
2725
  {
2038
- className: "yable-tr",
2039
- style: virtualStyle,
2726
+ className: rowClassName,
2727
+ style: mergedRowStyle,
2040
2728
  "data-selected": isSelected || void 0,
2041
2729
  "data-expanded": isExpanded || void 0,
2042
2730
  "data-clickable": clickable || void 0,
2731
+ "data-pinned-row": pinnedPosition,
2043
2732
  "data-row-id": row.id,
2044
2733
  "data-row-index": rowIndex,
2045
2734
  "aria-selected": selectionEnabled ? isSelected : void 0,
@@ -2071,7 +2760,7 @@ function TableRowInner({
2071
2760
  })
2072
2761
  }
2073
2762
  ),
2074
- isExpanded && /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "yable-expand-row", children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "yable-td", colSpan: visibleColumns.length, children: typeof row._renderExpanded === "function" ? row._renderExpanded() : null }) })
2763
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsx(MasterDetail, { row, table, colSpan: visibleColumns.length })
2075
2764
  ] });
2076
2765
  }
2077
2766
  function areRowPropsEqual(prev, next) {
@@ -2082,10 +2771,12 @@ function areRowPropsEqual(prev, next) {
2082
2771
  if (prev.isSelected !== next.isSelected) return false;
2083
2772
  if (prev.isExpanded !== next.isExpanded) return false;
2084
2773
  if (prev.clickable !== next.clickable) return false;
2774
+ if (prev.pinnedPosition !== next.pinnedPosition) return false;
2085
2775
  if (prev.activeColumnId !== next.activeColumnId) return false;
2086
2776
  if (prev.focusedColumnIndex !== next.focusedColumnIndex) return false;
2087
2777
  if (prev.hasFocusedCell !== next.hasFocusedCell) return false;
2088
2778
  if (prev.cellSelectionKey !== next.cellSelectionKey) return false;
2779
+ if (prev.pendingValuesKey !== next.pendingValuesKey) return false;
2089
2780
  if (prev.virtualStyle !== next.virtualStyle) {
2090
2781
  if (!prev.virtualStyle || !next.virtualStyle) return false;
2091
2782
  if (prev.virtualStyle.transform !== next.virtualStyle.transform) return false;
@@ -2095,6 +2786,16 @@ function areRowPropsEqual(prev, next) {
2095
2786
  return true;
2096
2787
  }
2097
2788
  var MemoizedTableRow = React3__default.default.memo(TableRowInner, areRowPropsEqual);
2789
+ function getPendingValuesKey(values) {
2790
+ if (!values) return "";
2791
+ return Object.keys(values).sort().map((key) => `${key}:${String(values[key])}`).join("|");
2792
+ }
2793
+ function isInteractiveClickTarget2(target) {
2794
+ if (!(target instanceof HTMLElement)) return false;
2795
+ return Boolean(
2796
+ target.closest('input, textarea, select, button, a[href], [contenteditable="true"]')
2797
+ );
2798
+ }
2098
2799
  function TableFooter({ table }) {
2099
2800
  const footerGroups = table.getFooterGroups();
2100
2801
  if (!footerGroups.length) return null;
@@ -2382,29 +3083,73 @@ function StatusBar({
2382
3083
  ] });
2383
3084
  }
2384
3085
  function SearchIcon() {
2385
- return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "yable-sidebar-search-icon", width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: [
2386
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "6.25", cy: "6.25", r: "4.25", stroke: "currentColor", strokeWidth: "1.5" }),
2387
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.5 9.5L12.5 12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
2388
- ] });
3086
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3087
+ "svg",
3088
+ {
3089
+ className: "yable-sidebar-search-icon",
3090
+ width: "13",
3091
+ height: "13",
3092
+ viewBox: "0 0 14 14",
3093
+ fill: "none",
3094
+ "aria-hidden": "true",
3095
+ children: [
3096
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "6.25", cy: "6.25", r: "4.25", stroke: "currentColor", strokeWidth: "1.5" }),
3097
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.5 9.5L12.5 12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
3098
+ ]
3099
+ }
3100
+ );
2389
3101
  }
2390
3102
  function VisibilityIcon({ visible }) {
2391
3103
  if (visible) {
2392
3104
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: [
2393
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 7s2.5-4 6-4 6 4 6 4-2.5 4-6 4-6-4-6-4z", stroke: "currentColor", strokeWidth: "1.2", strokeLinejoin: "round" }),
3105
+ /* @__PURE__ */ jsxRuntime.jsx(
3106
+ "path",
3107
+ {
3108
+ d: "M1 7s2.5-4 6-4 6 4 6 4-2.5 4-6 4-6-4-6-4z",
3109
+ stroke: "currentColor",
3110
+ strokeWidth: "1.2",
3111
+ strokeLinejoin: "round"
3112
+ }
3113
+ ),
2394
3114
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "7", cy: "7", r: "2", stroke: "currentColor", strokeWidth: "1.2" })
2395
3115
  ] });
2396
3116
  }
2397
3117
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: [
2398
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 7s2.5-4 6-4 6 4 6 4-2.5 4-6 4-6-4-6-4z", stroke: "currentColor", strokeWidth: "1.2", strokeLinejoin: "round", opacity: "0.3" }),
2399
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "2", y1: "2", x2: "12", y2: "12", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", opacity: "0.5" })
3118
+ /* @__PURE__ */ jsxRuntime.jsx(
3119
+ "path",
3120
+ {
3121
+ d: "M1 7s2.5-4 6-4 6 4 6 4-2.5 4-6 4-6-4-6-4z",
3122
+ stroke: "currentColor",
3123
+ strokeWidth: "1.2",
3124
+ strokeLinejoin: "round",
3125
+ opacity: "0.3"
3126
+ }
3127
+ ),
3128
+ /* @__PURE__ */ jsxRuntime.jsx(
3129
+ "line",
3130
+ {
3131
+ x1: "2",
3132
+ y1: "2",
3133
+ x2: "12",
3134
+ y2: "12",
3135
+ stroke: "currentColor",
3136
+ strokeWidth: "1.2",
3137
+ strokeLinecap: "round",
3138
+ opacity: "0.5"
3139
+ }
3140
+ )
2400
3141
  ] });
2401
3142
  }
2402
- function ColumnsPanel({
2403
- table
2404
- }) {
3143
+ function ColumnsPanel({ table }) {
2405
3144
  const [search, setSearch] = React3.useState("");
2406
3145
  const [draggedId, setDraggedId] = React3.useState(null);
2407
- const columns = table.getAllLeafColumns();
3146
+ const allColumns = table.getAllLeafColumns();
3147
+ const columnOrder = table.getState().columnOrder;
3148
+ const columns = columnOrder && columnOrder.length > 0 ? [...allColumns].sort((a, b) => {
3149
+ const ia = columnOrder.indexOf(a.id);
3150
+ const ib = columnOrder.indexOf(b.id);
3151
+ return (ia === -1 ? Number.MAX_SAFE_INTEGER : ia) - (ib === -1 ? Number.MAX_SAFE_INTEGER : ib);
3152
+ }) : allColumns;
2408
3153
  const visibleCount = columns.filter((c) => c.getIsVisible()).length;
2409
3154
  const filteredColumns = search ? columns.filter((col) => {
2410
3155
  const header = typeof col.columnDef.header === "string" ? col.columnDef.header : col.id;
@@ -2831,6 +3576,7 @@ function ContextMenu({
2831
3576
  y,
2832
3577
  onClose,
2833
3578
  table,
3579
+ targetColumnId,
2834
3580
  customItems
2835
3581
  }) {
2836
3582
  const menuRef = React3.useRef(null);
@@ -2874,6 +3620,17 @@ function ContextMenu({
2874
3620
  },
2875
3621
  [onClose]
2876
3622
  );
3623
+ const resolveSortColumn = () => {
3624
+ if (targetColumnId) {
3625
+ const column = table.getColumn(targetColumnId);
3626
+ if (column) return column;
3627
+ }
3628
+ const focused = table.getFocusedCell();
3629
+ if (focused) {
3630
+ return table.getVisibleLeafColumns()[focused.columnIndex];
3631
+ }
3632
+ return void 0;
3633
+ };
2877
3634
  const defaultItems = [
2878
3635
  {
2879
3636
  id: "copy",
@@ -2922,14 +3679,14 @@ function ContextMenu({
2922
3679
  id: "sort-asc",
2923
3680
  label: "Sort Ascending",
2924
3681
  action: () => {
2925
- table.setSorting([]);
3682
+ resolveSortColumn()?.toggleSorting(false);
2926
3683
  }
2927
3684
  },
2928
3685
  {
2929
3686
  id: "sort-desc",
2930
3687
  label: "Sort Descending",
2931
3688
  action: () => {
2932
- table.setSorting([]);
3689
+ resolveSortColumn()?.toggleSorting(true);
2933
3690
  }
2934
3691
  },
2935
3692
  {
@@ -3021,11 +3778,13 @@ function useContextMenu() {
3021
3778
  const [x, setX] = React3.useState(0);
3022
3779
  const [y, setY] = React3.useState(0);
3023
3780
  const [targetTable, setTargetTable] = React3.useState(null);
3781
+ const [targetColumnId, setTargetColumnId] = React3.useState(void 0);
3024
3782
  const open = React3.useCallback(
3025
- (clientX, clientY, table) => {
3783
+ (clientX, clientY, table, columnId) => {
3026
3784
  setX(clientX);
3027
3785
  setY(clientY);
3028
3786
  setTargetTable(table);
3787
+ setTargetColumnId(columnId);
3029
3788
  setIsOpen(true);
3030
3789
  },
3031
3790
  []
@@ -3033,6 +3792,7 @@ function useContextMenu() {
3033
3792
  const close = React3.useCallback(() => {
3034
3793
  setIsOpen(false);
3035
3794
  setTargetTable(null);
3795
+ setTargetColumnId(void 0);
3036
3796
  }, []);
3037
3797
  React3.useEffect(() => {
3038
3798
  if (!isOpen) return;
@@ -3047,7 +3807,7 @@ function useContextMenu() {
3047
3807
  document.removeEventListener("click", handleClick);
3048
3808
  };
3049
3809
  }, [isOpen, close]);
3050
- return { isOpen, x, y, targetTable, open, close };
3810
+ return { isOpen, x, y, targetTable, targetColumnId, open, close };
3051
3811
  }
3052
3812
  function useKeyboardNavigation(table, options = {}) {
3053
3813
  const {
@@ -3255,11 +4015,13 @@ function filterHeaderGroups(groups, visibleColumnIds) {
3255
4015
  }
3256
4016
  function Table({
3257
4017
  table,
3258
- stickyHeader,
3259
- striped,
3260
- bordered,
3261
- compact,
3262
- theme,
4018
+ stickyHeader: stickyHeaderProp,
4019
+ striped: stripedProp,
4020
+ bordered: borderedProp,
4021
+ compact: compactProp,
4022
+ theme: themeProp,
4023
+ config,
4024
+ configProfile,
3263
4025
  clickableRows,
3264
4026
  footer,
3265
4027
  loading,
@@ -3273,21 +4035,43 @@ function Table({
3273
4035
  renderLoading,
3274
4036
  children,
3275
4037
  className,
3276
- direction,
4038
+ direction: directionProp,
3277
4039
  statusBar,
3278
4040
  statusBarPanels,
3279
4041
  sidebar,
3280
- sidebarPanels = ["columns", "filters"],
4042
+ sidebarPanels,
3281
4043
  defaultSidebarPanel,
3282
4044
  floatingFilters,
3283
4045
  columnVirtualization,
3284
4046
  columnVirtualizationOverscan,
3285
- ariaLabel,
4047
+ ariaLabel: ariaLabelProp,
3286
4048
  ...rest
3287
4049
  }) {
4050
+ const providerDefaults = useYableDefaults();
4051
+ const { tableProps: providerTableProps } = providerDefaults;
4052
+ const profile = resolveYableProfile(
4053
+ config ?? providerDefaults.config,
4054
+ configProfile ?? providerDefaults.tableProfile
4055
+ );
4056
+ const profileTableProps = profile.table;
4057
+ const stickyHeader = stickyHeaderProp ?? profileTableProps?.stickyHeader ?? providerTableProps?.stickyHeader;
4058
+ const striped = stripedProp ?? profileTableProps?.striped ?? providerTableProps?.striped;
4059
+ const bordered = borderedProp ?? profileTableProps?.bordered ?? providerTableProps?.bordered;
4060
+ const compact = compactProp ?? profileTableProps?.compact ?? providerTableProps?.compact;
4061
+ const theme = themeProp ?? profileTableProps?.theme ?? providerTableProps?.theme;
4062
+ const direction = directionProp ?? profileTableProps?.direction ?? providerTableProps?.direction;
4063
+ const ariaLabel = ariaLabelProp ?? profileTableProps?.ariaLabel ?? providerTableProps?.ariaLabel;
4064
+ const resolvedClickableRows = clickableRows ?? profileTableProps?.clickableRows;
4065
+ const resolvedStatusBar = statusBar ?? profileTableProps?.statusBar;
4066
+ const resolvedSidebar = sidebar ?? profileTableProps?.sidebar;
4067
+ const resolvedSidebarPanels = sidebarPanels ?? profileTableProps?.sidebarPanels ?? ["columns", "filters"];
4068
+ const resolvedDefaultSidebarPanel = defaultSidebarPanel ?? profileTableProps?.defaultSidebarPanel;
4069
+ const resolvedFloatingFilters = floatingFilters ?? profileTableProps?.floatingFilters;
4070
+ const resolvedColumnVirtualization = columnVirtualization ?? profileTableProps?.columnVirtualization;
4071
+ const resolvedColumnVirtualizationOverscan = columnVirtualizationOverscan ?? profileTableProps?.columnVirtualizationOverscan;
3288
4072
  const [sidebarOpen, setSidebarOpen] = React3.useState(false);
3289
4073
  const [sidebarPanel, setSidebarPanel] = React3.useState(
3290
- defaultSidebarPanel ?? "columns"
4074
+ resolvedDefaultSidebarPanel ?? "columns"
3291
4075
  );
3292
4076
  const containerRef = React3.useRef(null);
3293
4077
  const horizontalScrollRef = React3.useRef(null);
@@ -3311,12 +4095,14 @@ function Table({
3311
4095
  const allVisibleColumns = table.getVisibleLeafColumns();
3312
4096
  const hasPinnedColumns = table.getLeftVisibleLeafColumns().length > 0 || table.getRightVisibleLeafColumns().length > 0;
3313
4097
  const hasGroupedHeaders = table.getHeaderGroups().length > 1;
3314
- const canVirtualizeColumns = Boolean(columnVirtualization) && !hasPinnedColumns && !hasGroupedHeaders && allVisibleColumns.length > 0;
4098
+ const canVirtualizeColumns = Boolean(resolvedColumnVirtualization) && !hasPinnedColumns && !hasGroupedHeaders && allVisibleColumns.length > 0;
4099
+ const allVisibleColumnSizeSignature = allVisibleColumns.map((column) => `${column.id}:${column.getSize()}`).join("|");
3315
4100
  const columnVirtualState = useColumnVirtualization({
3316
4101
  containerRef: horizontalScrollRef,
3317
4102
  columns: allVisibleColumns,
3318
- overscan: columnVirtualizationOverscan ?? 2,
3319
- enabled: canVirtualizeColumns
4103
+ overscan: resolvedColumnVirtualizationOverscan ?? 2,
4104
+ enabled: canVirtualizeColumns,
4105
+ sizingKey: allVisibleColumnSizeSignature
3320
4106
  });
3321
4107
  const renderTable = React3.useMemo(() => {
3322
4108
  if (!canVirtualizeColumns || !columnVirtualState.isVirtualized) {
@@ -3391,24 +4177,47 @@ function Table({
3391
4177
  const handleContextMenu = React3.useCallback(
3392
4178
  (e) => {
3393
4179
  e.preventDefault();
3394
- contextMenu.open(e.clientX, e.clientY, table);
4180
+ const targetEl = e.target?.closest?.("[data-column-id]");
4181
+ const targetColumnId = targetEl?.getAttribute("data-column-id") ?? void 0;
4182
+ contextMenu.open(e.clientX, e.clientY, table, targetColumnId);
3395
4183
  },
3396
4184
  [contextMenu, table]
3397
4185
  );
3398
- const tableNode = /* @__PURE__ */ jsxRuntime.jsxs(
3399
- "table",
3400
- {
3401
- className: "yable-table",
3402
- style: columnVirtualState.isVirtualized ? {
4186
+ const visibleLeafColumns = renderTable.getVisibleLeafColumns();
4187
+ const visibleColumnTotalSize = visibleLeafColumns.reduce(
4188
+ (sum, column) => sum + column.getSize(),
4189
+ 0
4190
+ );
4191
+ const colgroup = visibleLeafColumns.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx("colgroup", { children: visibleLeafColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("col", { style: { width: col.getSize() } }, col.id)) });
4192
+ const outerTableStyle = React3.useMemo(() => {
4193
+ if (columnVirtualState.isVirtualized) {
4194
+ return {
3403
4195
  width: columnVirtualState.visibleWidth,
3404
4196
  minWidth: columnVirtualState.visibleWidth,
3405
4197
  marginLeft: columnVirtualState.startOffset,
3406
4198
  tableLayout: "fixed"
3407
- } : void 0,
4199
+ };
4200
+ }
4201
+ return {
4202
+ minWidth: visibleColumnTotalSize || void 0,
4203
+ tableLayout: "fixed"
4204
+ };
4205
+ }, [
4206
+ columnVirtualState.isVirtualized,
4207
+ columnVirtualState.visibleWidth,
4208
+ columnVirtualState.startOffset,
4209
+ visibleColumnTotalSize
4210
+ ]);
4211
+ const tableNode = /* @__PURE__ */ jsxRuntime.jsxs(
4212
+ "table",
4213
+ {
4214
+ className: "yable-table",
4215
+ style: outerTableStyle,
3408
4216
  "data-column-virtualized": columnVirtualState.isVirtualized || void 0,
3409
4217
  children: [
3410
- /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { table: renderTable, floatingFilters }),
3411
- /* @__PURE__ */ jsxRuntime.jsx(TableBody, { table: renderTable, clickableRows }),
4218
+ colgroup,
4219
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { table: renderTable, floatingFilters: resolvedFloatingFilters }),
4220
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { table: renderTable, clickableRows: resolvedClickableRows, colgroup }),
3412
4221
  footer && /* @__PURE__ */ jsxRuntime.jsx(TableFooter, { table: renderTable })
3413
4222
  ]
3414
4223
  }
@@ -3474,18 +4283,43 @@ function Table({
3474
4283
  }
3475
4284
  ))
3476
4285
  ] }),
3477
- sidebar && /* @__PURE__ */ jsxRuntime.jsx(
4286
+ resolvedSidebar && !sidebarOpen && /* @__PURE__ */ jsxRuntime.jsx(
4287
+ "button",
4288
+ {
4289
+ type: "button",
4290
+ className: "yable-sidebar-trigger",
4291
+ "aria-label": "Open tool panel",
4292
+ title: "Open tool panel",
4293
+ onClick: () => setSidebarOpen(true),
4294
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
4295
+ /* @__PURE__ */ jsxRuntime.jsx(
4296
+ "rect",
4297
+ {
4298
+ x: "3",
4299
+ y: "4",
4300
+ width: "18",
4301
+ height: "16",
4302
+ rx: "2",
4303
+ stroke: "currentColor",
4304
+ strokeWidth: "2"
4305
+ }
4306
+ ),
4307
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "14", y1: "4", x2: "14", y2: "20", stroke: "currentColor", strokeWidth: "2" })
4308
+ ] })
4309
+ }
4310
+ ),
4311
+ resolvedSidebar && /* @__PURE__ */ jsxRuntime.jsx(
3478
4312
  Sidebar,
3479
4313
  {
3480
4314
  table,
3481
4315
  open: sidebarOpen,
3482
4316
  onClose: () => setSidebarOpen(false),
3483
- panels: sidebarPanels,
4317
+ panels: resolvedSidebarPanels,
3484
4318
  activePanel: sidebarPanel,
3485
4319
  onPanelChange: setSidebarPanel
3486
4320
  }
3487
4321
  ),
3488
- statusBar && /* @__PURE__ */ jsxRuntime.jsx(StatusBar, { table, panels: statusBarPanels }),
4322
+ resolvedStatusBar && /* @__PURE__ */ jsxRuntime.jsx(StatusBar, { table, panels: statusBarPanels }),
3489
4323
  children,
3490
4324
  contextMenu.isOpen && /* @__PURE__ */ jsxRuntime.jsx(
3491
4325
  ContextMenu,
@@ -3493,7 +4327,8 @@ function Table({
3493
4327
  x: contextMenu.x,
3494
4328
  y: contextMenu.y,
3495
4329
  onClose: contextMenu.close,
3496
- table
4330
+ table,
4331
+ targetColumnId: contextMenu.targetColumnId
3497
4332
  }
3498
4333
  ),
3499
4334
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4421,33 +5256,6 @@ function TreeToggle({
4421
5256
  }
4422
5257
  );
4423
5258
  }
4424
- function MasterDetail({
4425
- row,
4426
- table,
4427
- colSpan,
4428
- renderDetailPanel,
4429
- animationClass
4430
- }) {
4431
- const renderer = renderDetailPanel ?? table.options.renderDetailPanel;
4432
- if (!renderer) return null;
4433
- const content = renderer(row);
4434
- if (content == null) return null;
4435
- const classes = [
4436
- "yable-detail-row",
4437
- "yable-detail-row--animated",
4438
- animationClass
4439
- ].filter(Boolean).join(" ");
4440
- return /* @__PURE__ */ jsxRuntime.jsx(
4441
- "tr",
4442
- {
4443
- className: classes,
4444
- "data-detail-for": row.id,
4445
- role: "row",
4446
- "aria-label": `Details for row ${row.id}`,
4447
- children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "yable-detail-cell", colSpan, role: "cell", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "yable-detail-panel", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "yable-detail-panel-inner", children: content }) }) })
4448
- }
4449
- );
4450
- }
4451
5259
  function ExpandIcon({
4452
5260
  isExpanded,
4453
5261
  onClick,
@@ -5416,6 +6224,236 @@ function useTheme(options = {}) {
5416
6224
  containerRef
5417
6225
  };
5418
6226
  }
6227
+ function selectColumn(options = {}) {
6228
+ const { id = "_select", size = 40, headerAriaLabel = "Select all rows" } = options;
6229
+ return {
6230
+ id,
6231
+ header: ({ table }) => /* @__PURE__ */ jsxRuntime.jsx("label", { className: "yable-checkbox-hitbox", onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(
6232
+ "input",
6233
+ {
6234
+ type: "checkbox",
6235
+ className: "yable-checkbox",
6236
+ checked: table.getIsAllPageRowsSelected(),
6237
+ ref: (el) => {
6238
+ if (el)
6239
+ el.indeterminate = table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected();
6240
+ },
6241
+ onChange: () => table.toggleAllPageRowsSelected(),
6242
+ "aria-label": headerAriaLabel
6243
+ }
6244
+ ) }),
6245
+ cell: ({ row }) => /* @__PURE__ */ jsxRuntime.jsx("label", { className: "yable-checkbox-hitbox", onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(
6246
+ "input",
6247
+ {
6248
+ type: "checkbox",
6249
+ className: "yable-checkbox",
6250
+ checked: row.getIsSelected(),
6251
+ disabled: !row.getCanSelect(),
6252
+ onChange: row.getToggleSelectedHandler(),
6253
+ "aria-label": "Select row"
6254
+ }
6255
+ ) }),
6256
+ size,
6257
+ enableSorting: true,
6258
+ sortingFn: (rowA, rowB) => Number(rowA.getIsSelected()) - Number(rowB.getIsSelected()),
6259
+ enableColumnFilter: false,
6260
+ enableResizing: false,
6261
+ enableReorder: false,
6262
+ enableHiding: false,
6263
+ lockVisible: true
6264
+ };
6265
+ }
6266
+
6267
+ // src/presets/rowNumberColumn.tsx
6268
+ function rowNumberColumn(options = {}) {
6269
+ const { id = "_rowNumber", header = "#", size = 50, startFrom = 1 } = options;
6270
+ return {
6271
+ id,
6272
+ header,
6273
+ cell: ({ row }) => row.index + startFrom,
6274
+ size,
6275
+ enableSorting: false,
6276
+ enableColumnFilter: false,
6277
+ enableResizing: false,
6278
+ enableReorder: false,
6279
+ lockVisible: true
6280
+ };
6281
+ }
6282
+ function actionsColumn(options) {
6283
+ const { id = "_actions", header = "", size = 100, actions } = options;
6284
+ return {
6285
+ id,
6286
+ header,
6287
+ cell: (ctx) => {
6288
+ const items = typeof actions === "function" ? actions(ctx.row) : actions;
6289
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "yable-cell-actions", children: items.filter((a) => !a.hidden || !a.hidden(ctx.row)).map((action, i) => /* @__PURE__ */ jsxRuntime.jsx(
6290
+ "button",
6291
+ {
6292
+ type: "button",
6293
+ className: "yable-action-btn",
6294
+ disabled: action.disabled?.(ctx.row),
6295
+ onClick: (e) => {
6296
+ e.stopPropagation();
6297
+ action.onClick(ctx.row);
6298
+ },
6299
+ title: action.label,
6300
+ children: action.icon ?? action.label
6301
+ },
6302
+ i
6303
+ )) });
6304
+ },
6305
+ size,
6306
+ enableSorting: false,
6307
+ enableColumnFilter: false,
6308
+ enableResizing: false,
6309
+ enableReorder: false
6310
+ };
6311
+ }
6312
+ function expandColumn(options = {}) {
6313
+ const { id = "_expand", size = 40 } = options;
6314
+ return {
6315
+ id,
6316
+ header: () => null,
6317
+ cell: ({ row }) => {
6318
+ if (!row.getCanExpand()) return null;
6319
+ return /* @__PURE__ */ jsxRuntime.jsx(
6320
+ "button",
6321
+ {
6322
+ type: "button",
6323
+ className: "yable-expand-btn",
6324
+ onClick: (e) => {
6325
+ e.stopPropagation();
6326
+ row.toggleExpanded();
6327
+ },
6328
+ "aria-expanded": row.getIsExpanded(),
6329
+ "aria-label": row.getIsExpanded() ? "Collapse row" : "Expand row",
6330
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6331
+ "span",
6332
+ {
6333
+ className: "yable-expand-icon",
6334
+ style: {
6335
+ display: "inline-block",
6336
+ transform: row.getIsExpanded() ? "rotate(90deg)" : "rotate(0deg)",
6337
+ transition: "transform 150ms ease"
6338
+ },
6339
+ children: "\u25B6"
6340
+ }
6341
+ )
6342
+ }
6343
+ );
6344
+ },
6345
+ size,
6346
+ enableSorting: false,
6347
+ enableColumnFilter: false,
6348
+ enableResizing: false,
6349
+ enableReorder: false,
6350
+ lockVisible: true
6351
+ };
6352
+ }
6353
+ function CellStack({ children, gap = 2 }) {
6354
+ return /* @__PURE__ */ jsxRuntime.jsx(
6355
+ "div",
6356
+ {
6357
+ className: "yable-cell-stack",
6358
+ style: {
6359
+ display: "flex",
6360
+ flexDirection: "column",
6361
+ gap
6362
+ },
6363
+ children
6364
+ }
6365
+ );
6366
+ }
6367
+ function CellRow({ children, gap = 6, align = "center", justify = "start" }) {
6368
+ const justifyMap = {
6369
+ start: "flex-start",
6370
+ center: "center",
6371
+ end: "flex-end",
6372
+ between: "space-between"
6373
+ };
6374
+ return /* @__PURE__ */ jsxRuntime.jsx(
6375
+ "div",
6376
+ {
6377
+ className: "yable-cell-row",
6378
+ style: {
6379
+ display: "flex",
6380
+ flexDirection: "row",
6381
+ alignItems: align === "baseline" ? "baseline" : align === "start" ? "flex-start" : align === "end" ? "flex-end" : "center",
6382
+ justifyContent: justifyMap[justify] || "flex-start",
6383
+ gap
6384
+ },
6385
+ children
6386
+ }
6387
+ );
6388
+ }
6389
+ function CellWithIcon({ icon, children, gap = 6, iconSize }) {
6390
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6391
+ "div",
6392
+ {
6393
+ className: "yable-cell-with-icon",
6394
+ style: {
6395
+ display: "flex",
6396
+ flexDirection: "row",
6397
+ alignItems: "center",
6398
+ gap
6399
+ },
6400
+ children: [
6401
+ /* @__PURE__ */ jsxRuntime.jsx(
6402
+ "span",
6403
+ {
6404
+ className: "yable-cell-icon",
6405
+ style: {
6406
+ display: "inline-flex",
6407
+ alignItems: "center",
6408
+ justifyContent: "center",
6409
+ flexShrink: 0,
6410
+ ...iconSize ? { width: iconSize, height: iconSize } : {}
6411
+ },
6412
+ children: icon
6413
+ }
6414
+ ),
6415
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "yable-cell-icon-content", style: { minWidth: 0 }, children })
6416
+ ]
6417
+ }
6418
+ );
6419
+ }
6420
+ function CellText({
6421
+ children,
6422
+ variant = "primary",
6423
+ bold,
6424
+ truncate,
6425
+ size = "md"
6426
+ }) {
6427
+ const fontSizeMap = { sm: "0.75rem", md: "0.875rem", lg: "1rem" };
6428
+ return /* @__PURE__ */ jsxRuntime.jsx(
6429
+ "span",
6430
+ {
6431
+ className: `yable-cell-text yable-cell-text--${variant}`,
6432
+ style: {
6433
+ fontSize: fontSizeMap[size],
6434
+ fontWeight: bold ? 600 : void 0,
6435
+ color: variant === "secondary" ? "var(--yable-text-secondary, #6b7280)" : variant === "muted" ? "var(--yable-text-muted, #9ca3af)" : void 0,
6436
+ ...truncate ? {
6437
+ overflow: "hidden",
6438
+ textOverflow: "ellipsis",
6439
+ whiteSpace: "nowrap"
6440
+ } : {}
6441
+ },
6442
+ children
6443
+ }
6444
+ );
6445
+ }
6446
+
6447
+ // src/utils/mergeEditChanges.ts
6448
+ function mergeEditChanges(data, changes, getRowId = (_, i) => String(i)) {
6449
+ const changeKeys = Object.keys(changes);
6450
+ if (changeKeys.length === 0) return data;
6451
+ return data.map((row, i) => {
6452
+ const id = getRowId(row, i);
6453
+ const patch = changes[id];
6454
+ return patch ? { ...row, ...patch } : row;
6455
+ });
6456
+ }
5419
6457
 
5420
6458
  Object.defineProperty(exports, "CommitError", {
5421
6459
  enumerable: true,
@@ -5509,10 +6547,14 @@ exports.CellLink = CellLink;
5509
6547
  exports.CellNumeric = CellNumeric;
5510
6548
  exports.CellProgress = CellProgress;
5511
6549
  exports.CellRating = CellRating;
6550
+ exports.CellRow = CellRow;
5512
6551
  exports.CellSelect = CellSelect;
6552
+ exports.CellStack = CellStack;
5513
6553
  exports.CellStatus = CellStatus;
5514
6554
  exports.CellStatusBadge = CellStatusBadge;
6555
+ exports.CellText = CellText;
5515
6556
  exports.CellToggle = CellToggle;
6557
+ exports.CellWithIcon = CellWithIcon;
5516
6558
  exports.ColumnsPanel = ColumnsPanel;
5517
6559
  exports.ContextMenu = ContextMenu;
5518
6560
  exports.ContextMenuItem = ContextMenuItem;
@@ -5544,9 +6586,19 @@ exports.TableHeader = TableHeader;
5544
6586
  exports.TableProvider = TableProvider;
5545
6587
  exports.Tooltip = Tooltip;
5546
6588
  exports.TreeToggle = TreeToggle;
6589
+ exports.YableProvider = YableProvider;
6590
+ exports.actionsColumn = actionsColumn;
6591
+ exports.applyYableConfigToColumns = applyYableConfigToColumns;
6592
+ exports.createYableConfig = createYableConfig;
6593
+ exports.expandColumn = expandColumn;
5547
6594
  exports.getMeasureRecipeForCellType = getMeasureRecipeForCellType;
5548
6595
  exports.getRegisteredCellTypes = getRegisteredCellTypes;
6596
+ exports.getYableDefaultColumnDef = getYableDefaultColumnDef;
6597
+ exports.mergeEditChanges = mergeEditChanges;
5549
6598
  exports.resolveMeasureRecipe = resolveMeasureRecipe;
6599
+ exports.resolveYableProfile = resolveYableProfile;
6600
+ exports.rowNumberColumn = rowNumberColumn;
6601
+ exports.selectColumn = selectColumn;
5550
6602
  exports.useAutoMeasurements = useAutoMeasurements;
5551
6603
  exports.useCellFlash = useCellFlash;
5552
6604
  exports.useClipboard = useClipboard;
@@ -5558,11 +6610,14 @@ exports.usePretextMeasurement = usePretextMeasurement;
5558
6610
  exports.usePrintLayout = usePrintLayout;
5559
6611
  exports.useRowAnimation = useRowAnimation;
5560
6612
  exports.useRowDrag = useRowDrag;
6613
+ exports.useServerTable = useServerTable;
5561
6614
  exports.useTable = useTable;
5562
6615
  exports.useTableContext = useTableContext;
6616
+ exports.useTablePersistence = useTablePersistence;
5563
6617
  exports.useTableRowHeights = useTableRowHeights;
5564
6618
  exports.useTheme = useTheme;
5565
6619
  exports.useTooltip = useTooltip;
5566
6620
  exports.useVirtualization = useVirtualization;
6621
+ exports.useYableDefaults = useYableDefaults;
5567
6622
  //# sourceMappingURL=index.cjs.map
5568
6623
  //# sourceMappingURL=index.cjs.map