@iris-ui-kit/react 0.3.0 → 0.3.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.
@@ -0,0 +1,942 @@
1
+ 'use client'
2
+ import { useStore, useStoreSelector } from './chunk-RZNYIFV2.js';
3
+ import * as React3 from 'react';
4
+ import { createGridCore, createGridPaginationProjection, createGridColumnsFeature, createGridClipboardFeature, createGridFilteringFeature, createGridEditingFeature, createGridExpansionFeature, createGridPaginationFeature, createGridRangeFeature, createGridSelectionFeature, createGridRowsFeature, createGridSortingFeature, createGridVirtualFeature } from '@iris-ui-kit/core/grid';
5
+ import { mergeFormFilters, filterTableRows, resolveTableColumnValue, createTableSortComparator, createTableMultiSortComparator, sortTableRows } from '@iris-ui-kit/core';
6
+
7
+ function useGridCore(options = {}) {
8
+ const coreRef = React3.useRef(null);
9
+ const ownershipRef = React3.useRef(null);
10
+ if (coreRef.current === null) {
11
+ const core2 = createGridCore(options);
12
+ const ownership2 = { committed: false };
13
+ coreRef.current = core2;
14
+ ownershipRef.current = ownership2;
15
+ queueMicrotask(() => {
16
+ if (!ownership2.committed) core2.destroy();
17
+ });
18
+ }
19
+ const core = coreRef.current;
20
+ const ownership = ownershipRef.current;
21
+ const lifecycleGeneration = React3.useRef(0);
22
+ React3.useInsertionEffect(() => {
23
+ ownership.committed = true;
24
+ }, [core, ownership]);
25
+ React3.useEffect(() => {
26
+ const generation = ++lifecycleGeneration.current;
27
+ core.ready();
28
+ return () => {
29
+ queueMicrotask(() => {
30
+ if (lifecycleGeneration.current === generation) core.destroy();
31
+ });
32
+ };
33
+ }, [core]);
34
+ return core;
35
+ }
36
+
37
+ // src/grid/legacyGridOptions.ts
38
+ function toGridColumnsOptions(props) {
39
+ return {
40
+ visibility: props.columnVisibility,
41
+ visibilityControlled: true,
42
+ onVisibilityChange: props.onColumnVisibilityChange,
43
+ order: props.columnOrder,
44
+ orderControlled: true,
45
+ onOrderChange: props.onColumnOrderChange,
46
+ widths: props.columnWidths,
47
+ defaultWidths: props.defaultColumnWidths,
48
+ onWidthsChange: props.onColumnWidthsChange,
49
+ pinned: props.pinnedColumns,
50
+ onPinnedChange: props.onColumnPinnedChange
51
+ };
52
+ }
53
+ function toGridRowsOptions(props) {
54
+ const rows = props.data ?? [];
55
+ return {
56
+ initialRows: props.keepSource ? [...rows] : rows,
57
+ options: {
58
+ ...props.rowKeyField === void 0 ? {} : { rowKeyField: props.rowKeyField },
59
+ ...props.getRowKey === void 0 ? {} : { getRowKey: props.getRowKey },
60
+ ...props.getChildren === void 0 ? {} : { getChildren: props.getChildren },
61
+ ...props.setChildren === void 0 ? {} : { setChildren: props.setChildren },
62
+ onBeforeRowsChange: props.beforeChange,
63
+ onRowsChange: props.onChange
64
+ }
65
+ };
66
+ }
67
+ function toGridSelectionOptions(props) {
68
+ return {
69
+ mode: props.selectable === "single" ? "single" : "multiple",
70
+ value: props.selection,
71
+ defaultValue: props.defaultSelection,
72
+ onChange: props.onSelectionChange
73
+ };
74
+ }
75
+ function toGridExpansionOptions(props) {
76
+ return {
77
+ mode: "multiple",
78
+ defaultValue: (props.defaultExpandedRowKeys ?? []).map(String),
79
+ onChange: props.onChange
80
+ };
81
+ }
82
+ function toGridPaginationOptions(props) {
83
+ const state = props.state;
84
+ const onChange = state ? (change) => {
85
+ props.request?.({ page: change.page, pageSize: change.pageSize });
86
+ props.proxyConfig?.onPageChange?.(change.page, change.pageSize);
87
+ } : void 0;
88
+ return {
89
+ page: state?.page,
90
+ pageSize: state?.pageSize,
91
+ total: state?.total,
92
+ defaultPage: props.proxyConfig?.defaultPage,
93
+ defaultPageSize: props.proxyConfig?.pageSize,
94
+ onChange
95
+ };
96
+ }
97
+ function toGridSortingOptions(props) {
98
+ return {
99
+ leafColumns: props.columns,
100
+ sort: props.sort,
101
+ defaultSort: props.defaultSort,
102
+ onSortChange: props.onSortChange,
103
+ multiSort: props.multiSort,
104
+ multiSortState: props.multiSortState,
105
+ defaultMultiSort: props.defaultMultiSort,
106
+ onMultiSortChange: props.onMultiSortChange,
107
+ formulaTables: props.formulaTables
108
+ };
109
+ }
110
+ function toGridFilteringOptions(props) {
111
+ return {
112
+ columns: props.columns,
113
+ getValue: props.getValue,
114
+ filters: props.filters,
115
+ defaultFilters: props.defaultFilters,
116
+ onFiltersChange: props.onFiltersChange,
117
+ filterValues: props.filterValues,
118
+ defaultFilterValues: props.defaultFilterValues,
119
+ onFilterValuesChange: props.onFilterValuesChange,
120
+ controlled: true,
121
+ formFilters: props.formFilters,
122
+ query: props.query,
123
+ proxy: Boolean(props.proxy),
124
+ remote: props.remoteFilter
125
+ };
126
+ }
127
+ function useGridFeature(core, name, modelMethod, create) {
128
+ const feature = React3.useRef(null);
129
+ if (feature.current === null) feature.current = create();
130
+ if (!core.hasFeature(name)) core.use(feature.current);
131
+ return core.invoke(modelMethod);
132
+ }
133
+
134
+ // src/grid/useGridColumns.ts
135
+ var EMPTY_VISIBILITY = {};
136
+ var EMPTY_ORDER = [];
137
+ var EMPTY_WIDTHS = {};
138
+ var EMPTY_PINNED = {};
139
+ function visibilitySignature(visibility) {
140
+ return visibility ? JSON.stringify(Object.keys(visibility).map((key) => [key, visibility[key]])) : "";
141
+ }
142
+ function cloneColumnsState(state) {
143
+ return {
144
+ visibility: { ...state.visibility },
145
+ order: [...state.order],
146
+ widths: { ...state.widths },
147
+ pinned: { ...state.pinned }
148
+ };
149
+ }
150
+ function useGridColumns(core, options = {}) {
151
+ const latest = React3.useRef(options);
152
+ latest.current = options;
153
+ const model = useGridFeature(
154
+ core,
155
+ "columns",
156
+ "getColumnsModel",
157
+ () => createGridColumnsFeature({
158
+ defaultVisibility: options.visibility ?? options.defaultVisibility,
159
+ defaultOrder: options.order ?? options.defaultOrder,
160
+ defaultWidths: options.widths ?? options.defaultWidths,
161
+ defaultPinned: options.pinned ?? options.defaultPinned,
162
+ onVisibilityChange: (visibility) => latest.current.onVisibilityChange?.(visibility),
163
+ onOrderChange: (order) => latest.current.onOrderChange?.(order),
164
+ onWidthsChange: (widths) => latest.current.onWidthsChange?.(widths),
165
+ onPinnedChange: (key, side) => latest.current.onPinnedChange?.(key, side)
166
+ })
167
+ );
168
+ const internal = useStore(model.store);
169
+ const visibilityControlled = options.visibilityControlled ?? options.visibility !== void 0;
170
+ const orderControlled = options.orderControlled ?? options.order !== void 0;
171
+ const widthsControlled = options.widths !== void 0;
172
+ const pinnedControlled = options.pinned !== void 0;
173
+ const visibilityVersion = visibilitySignature(
174
+ visibilityControlled ? options.visibility : void 0
175
+ );
176
+ const lastUncontrolledVisibility = React3.useRef({
177
+ ...options.defaultVisibility ?? EMPTY_VISIBILITY
178
+ });
179
+ const lastUncontrolledOrder = React3.useRef([...options.defaultOrder ?? EMPTY_ORDER]);
180
+ const lastUncontrolledWidths = React3.useRef({
181
+ ...options.defaultWidths ?? EMPTY_WIDTHS
182
+ });
183
+ const lastUncontrolledPinned = React3.useRef({
184
+ ...options.defaultPinned ?? EMPTY_PINNED
185
+ });
186
+ const wasVisibilityControlled = React3.useRef(visibilityControlled);
187
+ const wasOrderControlled = React3.useRef(orderControlled);
188
+ const wasWidthsControlled = React3.useRef(widthsControlled);
189
+ const wasPinnedControlled = React3.useRef(pinnedControlled);
190
+ const enteringVisibilityControlled = visibilityControlled && !wasVisibilityControlled.current;
191
+ const enteringOrderControlled = orderControlled && !wasOrderControlled.current;
192
+ const enteringWidthsControlled = widthsControlled && !wasWidthsControlled.current;
193
+ const enteringPinnedControlled = pinnedControlled && !wasPinnedControlled.current;
194
+ if (enteringVisibilityControlled || enteringOrderControlled || enteringWidthsControlled || enteringPinnedControlled) {
195
+ const liveState = model.store.getState();
196
+ if (enteringVisibilityControlled) {
197
+ lastUncontrolledVisibility.current = { ...liveState.visibility };
198
+ }
199
+ if (enteringOrderControlled) lastUncontrolledOrder.current = [...liveState.order];
200
+ if (enteringWidthsControlled) lastUncontrolledWidths.current = { ...liveState.widths };
201
+ if (enteringPinnedControlled) lastUncontrolledPinned.current = { ...liveState.pinned };
202
+ }
203
+ if (!visibilityControlled && !wasVisibilityControlled.current) {
204
+ lastUncontrolledVisibility.current = { ...internal.visibility };
205
+ }
206
+ if (!orderControlled && !wasOrderControlled.current) {
207
+ lastUncontrolledOrder.current = [...internal.order];
208
+ }
209
+ if (!widthsControlled && !wasWidthsControlled.current) {
210
+ lastUncontrolledWidths.current = { ...internal.widths };
211
+ }
212
+ if (!pinnedControlled && !wasPinnedControlled.current) {
213
+ lastUncontrolledPinned.current = { ...internal.pinned };
214
+ }
215
+ const state = cloneColumnsState({
216
+ visibility: visibilityControlled ? { ...options.visibility ?? EMPTY_VISIBILITY } : wasVisibilityControlled.current ? lastUncontrolledVisibility.current : internal.visibility,
217
+ order: orderControlled ? [...options.order ?? EMPTY_ORDER] : wasOrderControlled.current ? lastUncontrolledOrder.current : internal.order,
218
+ // Removing a controlled order must restore the last uncontrolled/default
219
+ // snapshot rather than exposing a rejected controlled proposal. Widths
220
+ // use the same handoff policy below.
221
+ // Removing a controlled width map must restore the last uncontrolled or
222
+ // default snapshot immediately; otherwise one render leaks the rejected
223
+ // controlled widths before the silent model rebase runs.
224
+ widths: widthsControlled ? { ...options.widths } : wasWidthsControlled.current ? lastUncontrolledWidths.current : internal.widths,
225
+ pinned: pinnedControlled ? { ...options.pinned } : wasPinnedControlled.current ? lastUncontrolledPinned.current : internal.pinned
226
+ });
227
+ React3.useEffect(() => {
228
+ if (visibilityControlled) model.syncVisibility(options.visibility ?? {});
229
+ else if (wasVisibilityControlled.current)
230
+ model.syncVisibility(lastUncontrolledVisibility.current);
231
+ wasVisibilityControlled.current = visibilityControlled;
232
+ }, [model, options.visibility, visibilityControlled, visibilityVersion]);
233
+ React3.useEffect(() => {
234
+ if (orderControlled) model.syncOrder(options.order ?? []);
235
+ else if (wasOrderControlled.current) model.syncOrder(lastUncontrolledOrder.current);
236
+ wasOrderControlled.current = orderControlled;
237
+ }, [model, options.order, orderControlled]);
238
+ React3.useEffect(() => {
239
+ if (widthsControlled) model.syncWidths(options.widths ?? {});
240
+ else if (wasWidthsControlled.current) model.syncWidths(lastUncontrolledWidths.current);
241
+ wasWidthsControlled.current = widthsControlled;
242
+ }, [model, options.widths, widthsControlled]);
243
+ React3.useEffect(() => {
244
+ if (pinnedControlled) model.syncPinned(options.pinned ?? {});
245
+ else if (wasPinnedControlled.current) model.syncPinned(lastUncontrolledPinned.current);
246
+ wasPinnedControlled.current = pinnedControlled;
247
+ }, [model, options.pinned, pinnedControlled]);
248
+ const rebaseVisibility = React3.useCallback(() => {
249
+ if (latest.current.visibilityControlled ?? latest.current.visibility !== void 0) {
250
+ model.syncVisibility(latest.current.visibility ?? {});
251
+ } else if (wasVisibilityControlled.current) {
252
+ model.syncVisibility(lastUncontrolledVisibility.current);
253
+ }
254
+ }, [model]);
255
+ const rebaseOrder = React3.useCallback(() => {
256
+ if (latest.current.orderControlled ?? latest.current.order !== void 0) {
257
+ model.syncOrder(latest.current.order ?? []);
258
+ }
259
+ }, [model]);
260
+ const rebaseWidths = React3.useCallback(() => {
261
+ if (latest.current.widths !== void 0) model.syncWidths(latest.current.widths);
262
+ else if (wasWidthsControlled.current) model.syncWidths(lastUncontrolledWidths.current);
263
+ }, [model]);
264
+ const rebasePinned = React3.useCallback(() => {
265
+ if (latest.current.pinned !== void 0) model.syncPinned(latest.current.pinned);
266
+ else if (wasPinnedControlled.current) model.syncPinned(lastUncontrolledPinned.current);
267
+ }, [model]);
268
+ const setVisibility = React3.useCallback(
269
+ (visibility) => {
270
+ rebaseVisibility();
271
+ model.setVisibility(visibility);
272
+ },
273
+ [model, rebaseVisibility]
274
+ );
275
+ const toggleVisibility = React3.useCallback(
276
+ (key) => {
277
+ rebaseVisibility();
278
+ model.toggleVisibility(key);
279
+ },
280
+ [model, rebaseVisibility]
281
+ );
282
+ const setOrder = React3.useCallback(
283
+ (order) => {
284
+ rebaseOrder();
285
+ model.setOrder(order);
286
+ },
287
+ [model, rebaseOrder]
288
+ );
289
+ const clearOrder = React3.useCallback(() => {
290
+ rebaseOrder();
291
+ model.setOrder(void 0);
292
+ }, [model, rebaseOrder]);
293
+ const setWidths = React3.useCallback(
294
+ (widths) => {
295
+ rebaseWidths();
296
+ model.setWidths(widths);
297
+ },
298
+ [model, rebaseWidths]
299
+ );
300
+ const setWidth = React3.useCallback(
301
+ (key, width) => {
302
+ rebaseWidths();
303
+ model.setWidth(key, width);
304
+ },
305
+ [model, rebaseWidths]
306
+ );
307
+ const resetWidths = React3.useCallback(() => {
308
+ rebaseWidths();
309
+ model.setWidths({});
310
+ }, [model, rebaseWidths]);
311
+ const setPinned = React3.useCallback(
312
+ (key, side) => {
313
+ rebasePinned();
314
+ model.setPinned(key, side);
315
+ },
316
+ [model, rebasePinned]
317
+ );
318
+ return {
319
+ model,
320
+ state,
321
+ controlled: {
322
+ visibility: visibilityControlled,
323
+ order: orderControlled,
324
+ widths: widthsControlled,
325
+ pinned: pinnedControlled
326
+ },
327
+ setVisibility,
328
+ toggleVisibility,
329
+ setOrder,
330
+ clearOrder,
331
+ setWidths,
332
+ setWidth,
333
+ resetWidths,
334
+ setPinned
335
+ };
336
+ }
337
+ function defaultValue(row, column) {
338
+ return row[column.dataIndex ?? column.key];
339
+ }
340
+ function defaultSetValue(row, column, value) {
341
+ return { ...row, [column.dataIndex ?? column.key]: value };
342
+ }
343
+ function resolveCommitOptions(options) {
344
+ if (typeof options === "function") return options();
345
+ return options ?? {};
346
+ }
347
+ function useGridClipboard(core, options) {
348
+ const latest = React3.useRef(options);
349
+ latest.current = options;
350
+ const model = useGridFeature(
351
+ core,
352
+ "clipboard",
353
+ "getClipboardModel",
354
+ () => createGridClipboardFeature({
355
+ getRows: () => latest.current.getRows?.() ?? core.invoke("getRows"),
356
+ getColumns: () => latest.current.getColumns(),
357
+ rowKeyField: latest.current.rowKeyField,
358
+ overflowRows: (context) => latest.current.overflowRows?.(context),
359
+ resolveValue: (row, column) => {
360
+ const resolve = latest.current.resolveValue;
361
+ return resolve ? resolve(row, column) : defaultValue(row, column);
362
+ },
363
+ parseValue: (text, row, column) => {
364
+ const parse = latest.current.parseValue;
365
+ return parse ? parse(text, row, column) : text;
366
+ },
367
+ setValue: (row, column, value) => latest.current.setValue?.(row, column, value) ?? defaultSetValue(row, column, value),
368
+ isCellEditable: (row, column, rowIndex, columnIndex) => latest.current.isCellEditable?.(row, column, rowIndex, columnIndex) ?? true,
369
+ reconcileRows: (sourceRows, previousRows, rows) => latest.current.reconcileRows?.(sourceRows, previousRows, rows) ?? rows,
370
+ commitOptions: () => resolveCommitOptions(latest.current.commitOptions),
371
+ onCopy: (change) => latest.current.onCopy?.(change),
372
+ onPaste: (change) => latest.current.onPaste?.(change)
373
+ })
374
+ );
375
+ const serialize = React3.useCallback(
376
+ (format, copyWithFormat) => model.serialize(
377
+ format ?? latest.current.copyFormat ?? "tsv",
378
+ copyWithFormat ?? latest.current.copyWithFormat ?? false
379
+ ),
380
+ [model]
381
+ );
382
+ const paste = React3.useCallback(
383
+ (text, range) => model.paste(text, range),
384
+ [model]
385
+ );
386
+ return { core, model, serialize, paste };
387
+ }
388
+ function cloneFilters(filters) {
389
+ return { ...filters ?? {} };
390
+ }
391
+ function cloneFilterValues(filterValues) {
392
+ return Object.fromEntries(
393
+ Object.entries(filterValues ?? {}).map(([key, values]) => [key, [...values]])
394
+ );
395
+ }
396
+ function useGridFiltering(core, data, options) {
397
+ const latest = React3.useRef(options);
398
+ latest.current = options;
399
+ const filtersControlled = options.controlled === true || options.filters !== void 0;
400
+ const valuesControlled = options.controlled === true || options.filterValues !== void 0;
401
+ const model = useGridFeature(
402
+ core,
403
+ "filtering",
404
+ "getFilteringModel",
405
+ () => createGridFilteringFeature({
406
+ defaultFilters: filtersControlled ? options.filters ?? {} : options.defaultFilters,
407
+ defaultFilterValues: valuesControlled ? options.filterValues ?? {} : options.defaultFilterValues,
408
+ onFiltersChange: (next) => latest.current.onFiltersChange?.(next),
409
+ onFilterValuesChange: (next) => latest.current.onFilterValuesChange?.(next)
410
+ })
411
+ );
412
+ const internalState = useStore(model.store);
413
+ const filtersSignature = JSON.stringify(options.filters);
414
+ const filterValuesSignature = JSON.stringify(options.filterValues);
415
+ const wasFiltersControlled = React3.useRef(filtersControlled);
416
+ const uncontrolledFilters = React3.useRef({});
417
+ const hasUncontrolledFilters = React3.useRef(!filtersControlled);
418
+ const lastControlledFilters = React3.useRef(cloneFilters(options.filters));
419
+ const wasFilterValuesControlled = React3.useRef(valuesControlled);
420
+ const uncontrolledFilterValues = React3.useRef({});
421
+ const hasUncontrolledFilterValues = React3.useRef(!valuesControlled);
422
+ const lastControlledFilterValues = React3.useRef(
423
+ cloneFilterValues(options.filterValues)
424
+ );
425
+ const leavingFiltersControlled = wasFiltersControlled.current && !filtersControlled;
426
+ const leavingFilterValuesControlled = wasFilterValuesControlled.current && !valuesControlled;
427
+ if (!filtersControlled && !leavingFiltersControlled) {
428
+ uncontrolledFilters.current = cloneFilters(internalState.filters);
429
+ hasUncontrolledFilters.current = true;
430
+ }
431
+ if (!valuesControlled && !leavingFilterValuesControlled) {
432
+ uncontrolledFilterValues.current = cloneFilterValues(internalState.filterValues);
433
+ hasUncontrolledFilterValues.current = true;
434
+ }
435
+ if (filtersControlled && !wasFiltersControlled.current) {
436
+ uncontrolledFilters.current = cloneFilters(internalState.filters);
437
+ hasUncontrolledFilters.current = true;
438
+ }
439
+ if (valuesControlled && !wasFilterValuesControlled.current) {
440
+ uncontrolledFilterValues.current = cloneFilterValues(internalState.filterValues);
441
+ hasUncontrolledFilterValues.current = true;
442
+ }
443
+ if (filtersControlled) lastControlledFilters.current = cloneFilters(options.filters);
444
+ if (valuesControlled) {
445
+ lastControlledFilterValues.current = cloneFilterValues(options.filterValues);
446
+ }
447
+ const filters = cloneFilters(
448
+ filtersControlled ? options.filters : leavingFiltersControlled ? hasUncontrolledFilters.current ? uncontrolledFilters.current : lastControlledFilters.current : internalState.filters
449
+ );
450
+ const filterValues = cloneFilterValues(
451
+ valuesControlled ? options.filterValues : leavingFilterValuesControlled ? hasUncontrolledFilterValues.current ? uncontrolledFilterValues.current : lastControlledFilterValues.current : internalState.filterValues
452
+ );
453
+ React3.useEffect(() => {
454
+ if (filtersControlled) {
455
+ const next = cloneFilters(options.filters);
456
+ lastControlledFilters.current = cloneFilters(next);
457
+ model.syncFilters(next);
458
+ } else if (wasFiltersControlled.current) {
459
+ const restore = hasUncontrolledFilters.current ? uncontrolledFilters.current : lastControlledFilters.current;
460
+ uncontrolledFilters.current = cloneFilters(restore);
461
+ hasUncontrolledFilters.current = true;
462
+ model.syncFilters(restore);
463
+ }
464
+ wasFiltersControlled.current = filtersControlled;
465
+ }, [filtersControlled, model, options.filters, filtersSignature]);
466
+ React3.useEffect(() => {
467
+ if (valuesControlled) {
468
+ const next = cloneFilterValues(options.filterValues);
469
+ lastControlledFilterValues.current = cloneFilterValues(next);
470
+ model.syncFilterValues(next);
471
+ } else if (wasFilterValuesControlled.current) {
472
+ const restore = hasUncontrolledFilterValues.current ? uncontrolledFilterValues.current : lastControlledFilterValues.current;
473
+ uncontrolledFilterValues.current = cloneFilterValues(restore);
474
+ hasUncontrolledFilterValues.current = true;
475
+ model.syncFilterValues(restore);
476
+ }
477
+ wasFilterValuesControlled.current = valuesControlled;
478
+ }, [model, options.filterValues, valuesControlled, filterValuesSignature]);
479
+ const filteredData = React3.useMemo(() => {
480
+ if (options.remote) return data;
481
+ const merged = options.proxy ? { ...filters } : mergeFormFilters(filters, options.formFilters ?? {});
482
+ for (const [key, value] of Object.entries(options.query?.filters ?? {})) {
483
+ if (value !== "") merged[key] = value;
484
+ }
485
+ return filterTableRows(data, options.columns, {
486
+ getValue: options.getValue,
487
+ filters: merged,
488
+ filterValues,
489
+ additionalFilterValues: options.query?.inValues ? [options.query.inValues] : void 0,
490
+ filterRules: options.query?.rules
491
+ });
492
+ }, [
493
+ data,
494
+ filterValues,
495
+ filters,
496
+ options.columns,
497
+ options.formFilters,
498
+ options.getValue,
499
+ options.proxy,
500
+ options.query,
501
+ options.remote
502
+ ]);
503
+ return { core, model, filters, filterValues, filteredData };
504
+ }
505
+ function useGridEditing(core, options) {
506
+ const latest = React3.useRef(options);
507
+ latest.current = options;
508
+ const model = useGridFeature(
509
+ core,
510
+ "editing",
511
+ "getEditingModel",
512
+ () => createGridEditingFeature({
513
+ getRowKey: (row, index) => latest.current.getRowKey(row, index),
514
+ getRowIndex: (rowKey, row, rootRows) => latest.current.getRowIndex?.(rowKey, row, rootRows),
515
+ getRules: (columnKey) => latest.current.getRules?.(columnKey),
516
+ getValue: (row, columnKey) => {
517
+ const getValue = latest.current.getValue;
518
+ return getValue ? getValue(row, columnKey) : row[columnKey];
519
+ },
520
+ setValue: (row, columnKey, value) => latest.current.setValue?.(row, columnKey, value) ?? { ...row, [columnKey]: value },
521
+ coerce: (draft, row, columnKey) => {
522
+ const coerce = latest.current.coerce;
523
+ return coerce ? coerce(draft, row, columnKey) : draft;
524
+ },
525
+ validate: (value, row, columnKey) => latest.current.validate?.(value, row, columnKey) ?? null,
526
+ isEditable: (row, columnKey) => latest.current.isEditable?.(row, columnKey) ?? true,
527
+ missingRowMessage: options.missingRowMessage,
528
+ commitOptions: () => {
529
+ const configured = latest.current.commitOptions;
530
+ return typeof configured === "function" ? configured() : configured ?? {};
531
+ },
532
+ onStateChange: (state2) => latest.current.onStateChange?.(state2),
533
+ onValidation: (validation) => latest.current.onValidation?.(validation),
534
+ onCommit: (commit) => latest.current.onCommit?.(commit)
535
+ })
536
+ );
537
+ const state = useStoreSelector(model.store, () => model.getState());
538
+ return {
539
+ core,
540
+ model,
541
+ state,
542
+ startCellEdit: (rowKey, columnKey, initialDraft) => model.start(rowKey, columnKey, initialDraft),
543
+ setCellDraft: (value) => model.setDraft(value),
544
+ cancelCellEdit: () => model.cancelEdit(),
545
+ commitCellEdit: (value) => model.commitEdit(value),
546
+ isCellEditing: (rowKey, columnKey) => model.isEditing(rowKey, columnKey)
547
+ };
548
+ }
549
+ function useGridExpansion(core, options = {}) {
550
+ const latest = React3.useRef(options);
551
+ latest.current = options;
552
+ const model = useGridFeature(
553
+ core,
554
+ "expansion",
555
+ "getExpansionModel",
556
+ () => createGridExpansionFeature({
557
+ mode: options.mode,
558
+ defaultExpanded: options.defaultValue,
559
+ getKeys: () => latest.current.getKeys?.() ?? [],
560
+ onChange: (keys) => latest.current.onChange?.(keys)
561
+ })
562
+ );
563
+ const expandedKeys = useStore(model.store);
564
+ return { core, model, expandedKeys: [...expandedKeys] };
565
+ }
566
+ function controlledState(options) {
567
+ return {
568
+ ...options.page !== void 0 ? { page: options.page } : {},
569
+ ...options.pageSize !== void 0 ? { pageSize: options.pageSize } : {},
570
+ ...options.total !== void 0 ? { total: options.total } : {}
571
+ };
572
+ }
573
+ function useGridPagination(core, options = {}) {
574
+ const latest = React3.useRef(options);
575
+ latest.current = options;
576
+ const model = useGridFeature(
577
+ core,
578
+ "pagination",
579
+ "getPaginationModel",
580
+ () => createGridPaginationFeature({
581
+ defaultPage: options.page ?? options.defaultPage,
582
+ defaultPageSize: options.pageSize ?? options.defaultPageSize,
583
+ defaultTotal: options.total ?? options.defaultTotal,
584
+ onChange: (change) => latest.current.onChange?.(change)
585
+ })
586
+ );
587
+ const internal = useStore(model.store);
588
+ const projectionRef = React3.useRef(null);
589
+ if (projectionRef.current === null) {
590
+ projectionRef.current = createGridPaginationProjection(model, controlledState(options));
591
+ }
592
+ const projection = projectionRef.current;
593
+ const controlled = options.page !== void 0 || options.pageSize !== void 0 || options.total !== void 0;
594
+ const controlledProps = controlledState(options);
595
+ const pagination = projection.project(internal, controlledProps);
596
+ React3.useEffect(() => {
597
+ projection.sync(controlledState(options));
598
+ return () => projection.dispose();
599
+ }, [options.page, options.pageSize, options.total, projection]);
600
+ const rebase = React3.useCallback(() => {
601
+ projection.sync(controlledState(latest.current));
602
+ }, [projection]);
603
+ const setPage = React3.useCallback(
604
+ (page) => {
605
+ rebase();
606
+ model.setPage(page);
607
+ },
608
+ [model, rebase]
609
+ );
610
+ const setPageSize = React3.useCallback(
611
+ (pageSize) => {
612
+ rebase();
613
+ model.setPageSize(pageSize);
614
+ },
615
+ [model, rebase]
616
+ );
617
+ const setPagination = React3.useCallback(
618
+ (page, pageSize) => {
619
+ rebase();
620
+ model.set(page, pageSize);
621
+ },
622
+ [model, rebase]
623
+ );
624
+ return { model, pagination, controlled, setPage, setPageSize, setPagination };
625
+ }
626
+ function useGridRange(core, options = {}) {
627
+ const latest = React3.useRef(options);
628
+ latest.current = options;
629
+ const model = useGridFeature(
630
+ core,
631
+ "range",
632
+ "getRangeModel",
633
+ () => createGridRangeFeature({
634
+ onChange: (change) => latest.current.onChange?.(change)
635
+ })
636
+ );
637
+ const state = React3.useSyncExternalStore(model.subscribe, model.getState, model.getState);
638
+ const range = React3.useMemo(() => model.getRange(), [model, state]);
639
+ return { core, model, state, range };
640
+ }
641
+ function sameKeys(left, right) {
642
+ return left.length === right.length && left.every(
643
+ (key, index) => key === right[index] || key !== key && right[index] !== right[index]
644
+ );
645
+ }
646
+ function useGridSelection(core, options = {}) {
647
+ const latest = React3.useRef(options);
648
+ latest.current = options;
649
+ const model = useGridFeature(
650
+ core,
651
+ "selection",
652
+ "getSelectionModel",
653
+ () => createGridSelectionFeature({
654
+ mode: options.mode,
655
+ defaultSelected: options.value ?? options.defaultValue,
656
+ getKeys: () => latest.current.getKeys?.() ?? [],
657
+ onChange: (keys) => latest.current.onChange?.(keys)
658
+ })
659
+ );
660
+ const internalSelection = useStore(model.store);
661
+ const controlled = options.value !== void 0;
662
+ const wasControlled = React3.useRef(controlled);
663
+ const uncontrolledSnapshot = React3.useRef([]);
664
+ const hasUncontrolledSnapshot = React3.useRef(!controlled);
665
+ const lastControlledSnapshot = React3.useRef([...options.value ?? []]);
666
+ const leavingControlled = wasControlled.current && !controlled;
667
+ if (controlled && !wasControlled.current) {
668
+ uncontrolledSnapshot.current = [...model.store.getState()];
669
+ hasUncontrolledSnapshot.current = true;
670
+ }
671
+ if (!controlled && !leavingControlled) {
672
+ uncontrolledSnapshot.current = [...internalSelection];
673
+ hasUncontrolledSnapshot.current = true;
674
+ }
675
+ if (controlled) lastControlledSnapshot.current = [...options.value ?? []];
676
+ const uncontrolledValue = leavingControlled ? hasUncontrolledSnapshot.current ? uncontrolledSnapshot.current : lastControlledSnapshot.current : internalSelection;
677
+ React3.useEffect(() => {
678
+ if (controlled) {
679
+ const next = options.value ?? [];
680
+ lastControlledSnapshot.current = [...next];
681
+ if (!sameKeys(model.get(), next)) model.sync(next);
682
+ } else if (wasControlled.current) {
683
+ const next = hasUncontrolledSnapshot.current ? uncontrolledSnapshot.current : lastControlledSnapshot.current;
684
+ if (!hasUncontrolledSnapshot.current) {
685
+ uncontrolledSnapshot.current = [...next];
686
+ hasUncontrolledSnapshot.current = true;
687
+ }
688
+ if (!sameKeys(model.get(), next)) model.sync(next);
689
+ }
690
+ wasControlled.current = controlled;
691
+ }, [controlled, model, options.value ? [...options.value] : void 0]);
692
+ const rebase = React3.useCallback(() => {
693
+ if (latest.current.value !== void 0) model.sync(latest.current.value);
694
+ }, [model]);
695
+ return {
696
+ core,
697
+ model,
698
+ selection: [...controlled ? options.value ?? [] : uncontrolledValue],
699
+ controlled,
700
+ rebase
701
+ };
702
+ }
703
+ function useGridRows(core, initialRows, options = {}) {
704
+ const latest = React3.useRef(options);
705
+ latest.current = options;
706
+ const model = useGridFeature(
707
+ core,
708
+ "rows",
709
+ "getRowsModel",
710
+ () => createGridRowsFeature({
711
+ defaultRows: initialRows,
712
+ cloneDefaultRows: options.cloneDefaultRows,
713
+ rowKeyField: options.rowKeyField,
714
+ getRowKey: (row, index) => latest.current.getRowKey?.(row, index),
715
+ getChildren: options.getChildren ? (row) => latest.current.getChildren?.(row) : void 0,
716
+ setChildren: options.setChildren ? (row, children) => latest.current.setChildren?.(row, children) : void 0,
717
+ onBeforeRowsChange: (transaction) => latest.current.onBeforeRowsChange?.(transaction),
718
+ onRowsChange: (transaction) => latest.current.onRowsChange?.(transaction)
719
+ })
720
+ );
721
+ const rows = useStoreSelector(model.store, (current) => [...current]);
722
+ return { model, rows };
723
+ }
724
+ function cloneSort(sort) {
725
+ return sort ? { ...sort } : null;
726
+ }
727
+ function cloneSorts(sorts) {
728
+ return sorts.map((sort) => ({ ...sort }));
729
+ }
730
+ function useGridSorting(core, data, options) {
731
+ const latest = React3.useRef(options);
732
+ latest.current = options;
733
+ const model = useGridFeature(
734
+ core,
735
+ "sorting",
736
+ "getSortingModel",
737
+ () => createGridSortingFeature({
738
+ mode: options.multiSort ? "multiple" : "single",
739
+ defaultSort: options.sort !== void 0 ? options.sort : options.defaultSort,
740
+ defaultMultiSort: options.multiSortState !== void 0 ? options.multiSortState : options.defaultMultiSort,
741
+ onSortChange: (next) => latest.current.onSortChange?.(next),
742
+ onMultiSortChange: (next) => latest.current.onMultiSortChange?.(next)
743
+ })
744
+ );
745
+ const internalState = useStore(model.store);
746
+ const sortControlled = options.sort !== void 0;
747
+ const multiControlled = options.multiSortState !== void 0;
748
+ const sortSignature = JSON.stringify(options.sort);
749
+ const multiSortSignature = JSON.stringify(options.multiSortState);
750
+ const wasSortControlled = React3.useRef(sortControlled);
751
+ const uncontrolledSort = React3.useRef(null);
752
+ const hasUncontrolledSort = React3.useRef(!sortControlled);
753
+ const lastControlledSort = React3.useRef(cloneSort(options.sort ?? null));
754
+ const wasMultiSortControlled = React3.useRef(multiControlled);
755
+ const uncontrolledMultiSort = React3.useRef([]);
756
+ const hasUncontrolledMultiSort = React3.useRef(!multiControlled);
757
+ const lastControlledMultiSort = React3.useRef(
758
+ cloneSorts(options.multiSortState ?? [])
759
+ );
760
+ const leavingSortControlled = wasSortControlled.current && !sortControlled;
761
+ const leavingMultiSortControlled = wasMultiSortControlled.current && !multiControlled;
762
+ const enteringSortControlled = sortControlled && !wasSortControlled.current;
763
+ const enteringMultiSortControlled = multiControlled && !wasMultiSortControlled.current;
764
+ if (enteringSortControlled || enteringMultiSortControlled) {
765
+ const liveState = model.store.getState();
766
+ if (enteringSortControlled) {
767
+ uncontrolledSort.current = cloneSort(liveState.sort);
768
+ hasUncontrolledSort.current = true;
769
+ }
770
+ if (enteringMultiSortControlled) {
771
+ uncontrolledMultiSort.current = cloneSorts(liveState.multiSort);
772
+ hasUncontrolledMultiSort.current = true;
773
+ }
774
+ }
775
+ if (!sortControlled && !leavingSortControlled) {
776
+ uncontrolledSort.current = cloneSort(internalState.sort);
777
+ hasUncontrolledSort.current = true;
778
+ }
779
+ if (!multiControlled && !leavingMultiSortControlled) {
780
+ uncontrolledMultiSort.current = cloneSorts(internalState.multiSort);
781
+ hasUncontrolledMultiSort.current = true;
782
+ }
783
+ if (sortControlled) lastControlledSort.current = cloneSort(options.sort ?? null);
784
+ if (multiControlled) {
785
+ lastControlledMultiSort.current = cloneSorts(options.multiSortState ?? []);
786
+ }
787
+ const sortState = sortControlled ? cloneSort(options.sort ?? null) : cloneSort(
788
+ leavingSortControlled ? hasUncontrolledSort.current ? uncontrolledSort.current : lastControlledSort.current : internalState.sort
789
+ );
790
+ const multiSortState = multiControlled ? cloneSorts(options.multiSortState ?? []) : cloneSorts(
791
+ leavingMultiSortControlled ? hasUncontrolledMultiSort.current ? uncontrolledMultiSort.current : lastControlledMultiSort.current : internalState.multiSort
792
+ );
793
+ React3.useEffect(() => {
794
+ if (sortControlled) {
795
+ const next = options.sort ?? null;
796
+ lastControlledSort.current = cloneSort(next);
797
+ model.syncSort(next);
798
+ } else if (wasSortControlled.current) {
799
+ const restore = hasUncontrolledSort.current ? uncontrolledSort.current : lastControlledSort.current;
800
+ if (!hasUncontrolledSort.current) {
801
+ uncontrolledSort.current = cloneSort(restore);
802
+ hasUncontrolledSort.current = true;
803
+ }
804
+ model.syncSort(restore);
805
+ }
806
+ wasSortControlled.current = sortControlled;
807
+ }, [model, options.sort, sortControlled, sortSignature]);
808
+ React3.useEffect(() => {
809
+ if (multiControlled) {
810
+ const next = cloneSorts(options.multiSortState ?? []);
811
+ lastControlledMultiSort.current = cloneSorts(next);
812
+ model.syncMultiSort(next);
813
+ } else if (wasMultiSortControlled.current) {
814
+ const restore = hasUncontrolledMultiSort.current ? uncontrolledMultiSort.current : lastControlledMultiSort.current;
815
+ uncontrolledMultiSort.current = cloneSorts(restore);
816
+ hasUncontrolledMultiSort.current = true;
817
+ model.syncMultiSort(restore);
818
+ }
819
+ wasMultiSortControlled.current = multiControlled;
820
+ }, [model, multiControlled, options.multiSortState, multiSortSignature]);
821
+ const setSort = React3.useCallback(
822
+ (next) => {
823
+ if (latest.current.sort !== void 0) model.syncSort(latest.current.sort ?? null);
824
+ model.setSort(next);
825
+ },
826
+ [model]
827
+ );
828
+ const cycleSort = React3.useCallback(
829
+ (column) => {
830
+ if (!column.sortable) return;
831
+ if (latest.current.sort !== void 0) model.syncSort(latest.current.sort ?? null);
832
+ model.cycleSort(column.key);
833
+ },
834
+ [model]
835
+ );
836
+ const setMultiSort = React3.useCallback(
837
+ (next) => {
838
+ if (latest.current.multiSortState !== void 0) {
839
+ model.syncMultiSort(latest.current.multiSortState);
840
+ }
841
+ model.setMultiSort(next);
842
+ },
843
+ [model]
844
+ );
845
+ const cycleMultiSort = React3.useCallback(
846
+ (column) => {
847
+ if (!column.sortable) return;
848
+ if (latest.current.multiSortState !== void 0) {
849
+ model.syncMultiSort(latest.current.multiSortState);
850
+ }
851
+ model.cycleMultiSort(column.key);
852
+ },
853
+ [model]
854
+ );
855
+ const getValue = React3.useCallback(
856
+ (row, column) => {
857
+ if (column.sortBy !== void 0) return row[column.sortBy];
858
+ return resolveTableColumnValue(row, column, options.formulaTables);
859
+ },
860
+ [options.formulaTables]
861
+ );
862
+ const sortComparator = React3.useMemo(
863
+ () => createTableSortComparator(sortState, options.leafColumns, getValue),
864
+ [getValue, options.leafColumns, sortState]
865
+ );
866
+ const multiSortComparator = React3.useMemo(
867
+ () => createTableMultiSortComparator(multiSortState, options.leafColumns, getValue),
868
+ [getValue, options.leafColumns, multiSortState]
869
+ );
870
+ const sortedData = React3.useMemo(
871
+ () => sortTableRows(data, options.leafColumns, {
872
+ mode: options.multiSort ? "multiple" : "single",
873
+ sort: sortState,
874
+ multiSort: multiSortState,
875
+ getValue
876
+ }),
877
+ [data, getValue, multiSortState, options.leafColumns, options.multiSort, sortState]
878
+ );
879
+ return {
880
+ core,
881
+ model,
882
+ sortState,
883
+ cycleSort,
884
+ setSort,
885
+ sortComparator,
886
+ sortedData,
887
+ multiSortState,
888
+ cycleMultiSort,
889
+ setMultiSort,
890
+ multiSortComparator
891
+ };
892
+ }
893
+ var useIsomorphicLayoutEffect = typeof window === "undefined" || typeof document === "undefined" ? React3.useEffect : React3.useLayoutEffect;
894
+ function useGridVirtual(core, options) {
895
+ const latest = React3.useRef(options);
896
+ latest.current = options;
897
+ const model = useGridFeature(
898
+ core,
899
+ "virtual",
900
+ "getVirtualModel",
901
+ () => createGridVirtualFeature({
902
+ count: options.items.length,
903
+ estimateSize: (index) => {
904
+ const estimate = latest.current.estimateSize;
905
+ return typeof estimate === "function" ? estimate(index) : estimate;
906
+ },
907
+ viewportSize: options.viewportSize,
908
+ scrollOffset: options.scrollOffset,
909
+ buffer: options.buffer,
910
+ fixedSize: typeof options.estimateSize === "number" ? options.estimateSize : null,
911
+ getItemKey: (index) => {
912
+ const item = latest.current.items[index];
913
+ const keyOf = latest.current.getItemKey;
914
+ return item !== void 0 && keyOf ? keyOf(item, index) : index;
915
+ },
916
+ onRangeChange: (change) => latest.current.onRangeChange?.(change)
917
+ })
918
+ );
919
+ useIsomorphicLayoutEffect(() => {
920
+ model.setCount(options.items.length);
921
+ }, [model, options.items, options.getItemKey]);
922
+ useIsomorphicLayoutEffect(() => {
923
+ model.setBuffer(options.buffer ?? 0);
924
+ }, [model, options.buffer]);
925
+ useIsomorphicLayoutEffect(() => {
926
+ model.setEstimateSize(
927
+ options.estimateSize,
928
+ typeof options.estimateSize === "number" ? options.estimateSize : null
929
+ );
930
+ }, [model, options.estimateSize]);
931
+ useIsomorphicLayoutEffect(() => {
932
+ if (options.viewportSize !== void 0) model.setViewportSize(options.viewportSize);
933
+ }, [model, options.viewportSize]);
934
+ useIsomorphicLayoutEffect(() => {
935
+ if (options.scrollOffset !== void 0) model.setScroll(options.scrollOffset);
936
+ }, [model, options.scrollOffset]);
937
+ return { model };
938
+ }
939
+
940
+ export { toGridColumnsOptions, toGridExpansionOptions, toGridFilteringOptions, toGridPaginationOptions, toGridRowsOptions, toGridSelectionOptions, toGridSortingOptions, useGridClipboard, useGridColumns, useGridCore, useGridEditing, useGridExpansion, useGridFiltering, useGridPagination, useGridRange, useGridRows, useGridSelection, useGridSorting, useGridVirtual };
941
+ //# sourceMappingURL=chunk-3772LKJP.js.map
942
+ //# sourceMappingURL=chunk-3772LKJP.js.map