@gp-grid/react 0.7.2 → 0.8.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.js CHANGED
@@ -1,1662 +1 @@
1
- import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
2
- import { GridCore, GridCore as GridCore$1, buildCellClasses, calculateScaledColumnPositions, createClientDataSource, createClientDataSource as createClientDataSource$1, createDataSourceFromArray, createDataSourceFromArray as createDataSourceFromArray$1, createMutableClientDataSource, createServerDataSource, getTotalWidth, injectStyles, isCellActive, isCellEditing, isCellInFillPreview, isCellSelected } from "gp-grid-core";
3
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
-
5
- //#region src/components/TextFilterContent.tsx
6
- const MAX_VALUES_FOR_LIST = 100;
7
- const OPERATORS$2 = [
8
- {
9
- value: "contains",
10
- label: "Contains"
11
- },
12
- {
13
- value: "notContains",
14
- label: "Does not contain"
15
- },
16
- {
17
- value: "equals",
18
- label: "Equals"
19
- },
20
- {
21
- value: "notEquals",
22
- label: "Does not equal"
23
- },
24
- {
25
- value: "startsWith",
26
- label: "Starts with"
27
- },
28
- {
29
- value: "endsWith",
30
- label: "Ends with"
31
- },
32
- {
33
- value: "blank",
34
- label: "Is blank"
35
- },
36
- {
37
- value: "notBlank",
38
- label: "Is not blank"
39
- }
40
- ];
41
- function TextFilterContent({ distinctValues, currentFilter, onApply, onClose }) {
42
- const valueToString = useCallback((v) => {
43
- if (Array.isArray(v)) return v.join(", ");
44
- return String(v ?? "");
45
- }, []);
46
- const uniqueValues = useMemo(() => {
47
- const values = distinctValues.filter((v) => v != null && v !== "" && !(Array.isArray(v) && v.length === 0)).map((v) => valueToString(v));
48
- return Array.from(new Set(values)).sort((a, b) => {
49
- const numA = parseFloat(a);
50
- const numB = parseFloat(b);
51
- if (!isNaN(numA) && !isNaN(numB)) return numA - numB;
52
- return a.localeCompare(b, void 0, {
53
- numeric: true,
54
- sensitivity: "base"
55
- });
56
- });
57
- }, [distinctValues, valueToString]);
58
- const hasTooManyValues = uniqueValues.length > MAX_VALUES_FOR_LIST;
59
- const [mode, setMode] = useState(useMemo(() => {
60
- if (!currentFilter?.conditions[0]) return hasTooManyValues ? "condition" : "values";
61
- const cond = currentFilter.conditions[0];
62
- if (cond.selectedValues && cond.selectedValues.size > 0) return "values";
63
- return "condition";
64
- }, [currentFilter, hasTooManyValues]));
65
- const initialSelected = useMemo(() => {
66
- if (!currentFilter?.conditions[0]) return /* @__PURE__ */ new Set();
67
- return currentFilter.conditions[0].selectedValues ?? /* @__PURE__ */ new Set();
68
- }, [currentFilter]);
69
- const initialIncludeBlanks = useMemo(() => {
70
- if (!currentFilter?.conditions[0]) return true;
71
- return currentFilter.conditions[0].includeBlank ?? true;
72
- }, [currentFilter]);
73
- const [searchText, setSearchText] = useState("");
74
- const [selectedValues, setSelectedValues] = useState(initialSelected);
75
- const [includeBlanks, setIncludeBlanks] = useState(initialIncludeBlanks);
76
- const [conditions, setConditions] = useState(useMemo(() => {
77
- if (!currentFilter?.conditions.length) return [{
78
- operator: "contains",
79
- value: "",
80
- nextOperator: "and"
81
- }];
82
- const cond = currentFilter.conditions[0];
83
- if (cond.selectedValues && cond.selectedValues.size > 0) return [{
84
- operator: "contains",
85
- value: "",
86
- nextOperator: "and"
87
- }];
88
- const defaultCombination = currentFilter.combination ?? "and";
89
- return currentFilter.conditions.map((c) => {
90
- const tc = c;
91
- return {
92
- operator: tc.operator,
93
- value: tc.value ?? "",
94
- nextOperator: tc.nextOperator ?? defaultCombination
95
- };
96
- });
97
- }, [currentFilter]));
98
- const displayValues = useMemo(() => {
99
- if (!searchText) return uniqueValues;
100
- const lower = searchText.toLowerCase();
101
- return uniqueValues.filter((v) => v.toLowerCase().includes(lower));
102
- }, [uniqueValues, searchText]);
103
- const hasBlanks = useMemo(() => {
104
- return distinctValues.some((v) => v == null || v === "");
105
- }, [distinctValues]);
106
- const allSelected = useMemo(() => {
107
- return displayValues.every((v) => selectedValues.has(v)) && (!hasBlanks || includeBlanks);
108
- }, [
109
- displayValues,
110
- selectedValues,
111
- hasBlanks,
112
- includeBlanks
113
- ]);
114
- const handleSelectAll = useCallback(() => {
115
- setSelectedValues(new Set(displayValues));
116
- if (hasBlanks) setIncludeBlanks(true);
117
- }, [displayValues, hasBlanks]);
118
- const handleDeselectAll = useCallback(() => {
119
- setSelectedValues(/* @__PURE__ */ new Set());
120
- setIncludeBlanks(false);
121
- }, []);
122
- const handleValueToggle = useCallback((value) => {
123
- setSelectedValues((prev) => {
124
- const next = new Set(prev);
125
- if (next.has(value)) next.delete(value);
126
- else next.add(value);
127
- return next;
128
- });
129
- }, []);
130
- const updateCondition = useCallback((index, updates) => {
131
- setConditions((prev) => {
132
- const next = [...prev];
133
- next[index] = {
134
- ...next[index],
135
- ...updates
136
- };
137
- return next;
138
- });
139
- }, []);
140
- const addCondition = useCallback(() => {
141
- setConditions((prev) => [...prev, {
142
- operator: "contains",
143
- value: "",
144
- nextOperator: "and"
145
- }]);
146
- }, []);
147
- const removeCondition = useCallback((index) => {
148
- setConditions((prev) => prev.filter((_, i) => i !== index));
149
- }, []);
150
- const handleApply = useCallback(() => {
151
- if (mode === "values") {
152
- if (uniqueValues.every((v) => selectedValues.has(v)) && (!hasBlanks || includeBlanks)) {
153
- onApply(null);
154
- return;
155
- }
156
- onApply({
157
- conditions: [{
158
- type: "text",
159
- operator: "equals",
160
- selectedValues,
161
- includeBlank: includeBlanks
162
- }],
163
- combination: "and"
164
- });
165
- } else {
166
- const validConditions = conditions.filter((c) => {
167
- if (c.operator === "blank" || c.operator === "notBlank") return true;
168
- return c.value.trim() !== "";
169
- });
170
- if (validConditions.length === 0) {
171
- onApply(null);
172
- return;
173
- }
174
- onApply({
175
- conditions: validConditions.map((c) => ({
176
- type: "text",
177
- operator: c.operator,
178
- value: c.value,
179
- nextOperator: c.nextOperator
180
- })),
181
- combination: "and"
182
- });
183
- }
184
- }, [
185
- mode,
186
- uniqueValues,
187
- selectedValues,
188
- includeBlanks,
189
- hasBlanks,
190
- conditions,
191
- onApply
192
- ]);
193
- const handleClear = useCallback(() => {
194
- onApply(null);
195
- }, [onApply]);
196
- return /* @__PURE__ */ jsxs("div", {
197
- className: "gp-grid-filter-content gp-grid-filter-text",
198
- children: [
199
- !hasTooManyValues && /* @__PURE__ */ jsxs("div", {
200
- className: "gp-grid-filter-mode-toggle",
201
- children: [/* @__PURE__ */ jsx("button", {
202
- type: "button",
203
- className: mode === "values" ? "active" : "",
204
- onClick: () => setMode("values"),
205
- children: "Values"
206
- }), /* @__PURE__ */ jsx("button", {
207
- type: "button",
208
- className: mode === "condition" ? "active" : "",
209
- onClick: () => setMode("condition"),
210
- children: "Condition"
211
- })]
212
- }),
213
- hasTooManyValues && mode === "condition" && /* @__PURE__ */ jsxs("div", {
214
- className: "gp-grid-filter-info",
215
- children: [
216
- "Too many unique values (",
217
- uniqueValues.length,
218
- "). Use conditions to filter."
219
- ]
220
- }),
221
- mode === "values" && /* @__PURE__ */ jsxs(Fragment, { children: [
222
- /* @__PURE__ */ jsx("input", {
223
- className: "gp-grid-filter-search",
224
- type: "text",
225
- placeholder: "Search...",
226
- value: searchText,
227
- onChange: (e) => setSearchText(e.target.value),
228
- autoFocus: true
229
- }),
230
- /* @__PURE__ */ jsxs("div", {
231
- className: "gp-grid-filter-actions",
232
- children: [/* @__PURE__ */ jsx("button", {
233
- type: "button",
234
- onClick: handleSelectAll,
235
- disabled: allSelected,
236
- children: "Select All"
237
- }), /* @__PURE__ */ jsx("button", {
238
- type: "button",
239
- onClick: handleDeselectAll,
240
- children: "Deselect All"
241
- })]
242
- }),
243
- /* @__PURE__ */ jsxs("div", {
244
- className: "gp-grid-filter-list",
245
- children: [hasBlanks && /* @__PURE__ */ jsxs("label", {
246
- className: "gp-grid-filter-option",
247
- children: [/* @__PURE__ */ jsx("input", {
248
- type: "checkbox",
249
- checked: includeBlanks,
250
- onChange: () => setIncludeBlanks(!includeBlanks)
251
- }), /* @__PURE__ */ jsx("span", {
252
- className: "gp-grid-filter-blank",
253
- children: "(Blanks)"
254
- })]
255
- }), displayValues.map((value) => /* @__PURE__ */ jsxs("label", {
256
- className: "gp-grid-filter-option",
257
- children: [/* @__PURE__ */ jsx("input", {
258
- type: "checkbox",
259
- checked: selectedValues.has(value),
260
- onChange: () => handleValueToggle(value)
261
- }), /* @__PURE__ */ jsx("span", { children: value })]
262
- }, value))]
263
- })
264
- ] }),
265
- mode === "condition" && /* @__PURE__ */ jsxs(Fragment, { children: [conditions.map((cond, index) => /* @__PURE__ */ jsxs("div", {
266
- className: "gp-grid-filter-condition",
267
- children: [index > 0 && /* @__PURE__ */ jsxs("div", {
268
- className: "gp-grid-filter-combination",
269
- children: [/* @__PURE__ */ jsx("button", {
270
- type: "button",
271
- className: conditions[index - 1]?.nextOperator === "and" ? "active" : "",
272
- onClick: () => updateCondition(index - 1, { nextOperator: "and" }),
273
- children: "AND"
274
- }), /* @__PURE__ */ jsx("button", {
275
- type: "button",
276
- className: conditions[index - 1]?.nextOperator === "or" ? "active" : "",
277
- onClick: () => updateCondition(index - 1, { nextOperator: "or" }),
278
- children: "OR"
279
- })]
280
- }), /* @__PURE__ */ jsxs("div", {
281
- className: "gp-grid-filter-row",
282
- children: [
283
- /* @__PURE__ */ jsx("select", {
284
- value: cond.operator,
285
- onChange: (e) => updateCondition(index, { operator: e.target.value }),
286
- autoFocus: index === 0,
287
- children: OPERATORS$2.map((op) => /* @__PURE__ */ jsx("option", {
288
- value: op.value,
289
- children: op.label
290
- }, op.value))
291
- }),
292
- cond.operator !== "blank" && cond.operator !== "notBlank" && /* @__PURE__ */ jsx("input", {
293
- type: "text",
294
- value: cond.value,
295
- onChange: (e) => updateCondition(index, { value: e.target.value }),
296
- placeholder: "Value",
297
- className: "gp-grid-filter-text-input"
298
- }),
299
- conditions.length > 1 && /* @__PURE__ */ jsx("button", {
300
- type: "button",
301
- className: "gp-grid-filter-remove",
302
- onClick: () => removeCondition(index),
303
- children: "×"
304
- })
305
- ]
306
- })]
307
- }, index)), /* @__PURE__ */ jsx("button", {
308
- type: "button",
309
- className: "gp-grid-filter-add",
310
- onClick: addCondition,
311
- children: "+ Add condition"
312
- })] }),
313
- /* @__PURE__ */ jsxs("div", {
314
- className: "gp-grid-filter-buttons",
315
- children: [/* @__PURE__ */ jsx("button", {
316
- type: "button",
317
- className: "gp-grid-filter-btn-clear",
318
- onClick: handleClear,
319
- children: "Clear"
320
- }), /* @__PURE__ */ jsx("button", {
321
- type: "button",
322
- className: "gp-grid-filter-btn-apply",
323
- onClick: handleApply,
324
- children: "Apply"
325
- })]
326
- })
327
- ]
328
- });
329
- }
330
-
331
- //#endregion
332
- //#region src/components/NumberFilterContent.tsx
333
- const OPERATORS$1 = [
334
- {
335
- value: "=",
336
- label: "="
337
- },
338
- {
339
- value: "!=",
340
- label: "≠"
341
- },
342
- {
343
- value: ">",
344
- label: ">"
345
- },
346
- {
347
- value: "<",
348
- label: "<"
349
- },
350
- {
351
- value: ">=",
352
- label: "≥"
353
- },
354
- {
355
- value: "<=",
356
- label: "≤"
357
- },
358
- {
359
- value: "between",
360
- label: "↔"
361
- },
362
- {
363
- value: "blank",
364
- label: "Is blank"
365
- },
366
- {
367
- value: "notBlank",
368
- label: "Not blank"
369
- }
370
- ];
371
- function NumberFilterContent({ currentFilter, onApply, onClose }) {
372
- const [conditions, setConditions] = useState(useMemo(() => {
373
- if (!currentFilter?.conditions.length) return [{
374
- operator: "=",
375
- value: "",
376
- valueTo: "",
377
- nextOperator: "and"
378
- }];
379
- const defaultCombination = currentFilter.combination ?? "and";
380
- return currentFilter.conditions.map((c) => {
381
- const cond = c;
382
- return {
383
- operator: cond.operator,
384
- value: cond.value != null ? String(cond.value) : "",
385
- valueTo: cond.valueTo != null ? String(cond.valueTo) : "",
386
- nextOperator: cond.nextOperator ?? defaultCombination
387
- };
388
- });
389
- }, [currentFilter]));
390
- const updateCondition = useCallback((index, updates) => {
391
- setConditions((prev) => {
392
- const next = [...prev];
393
- next[index] = {
394
- ...next[index],
395
- ...updates
396
- };
397
- return next;
398
- });
399
- }, []);
400
- const addCondition = useCallback(() => {
401
- setConditions((prev) => [...prev, {
402
- operator: "=",
403
- value: "",
404
- valueTo: "",
405
- nextOperator: "and"
406
- }]);
407
- }, []);
408
- const removeCondition = useCallback((index) => {
409
- setConditions((prev) => prev.filter((_, i) => i !== index));
410
- }, []);
411
- const handleApply = useCallback(() => {
412
- const validConditions = conditions.filter((c) => {
413
- if (c.operator === "blank" || c.operator === "notBlank") return true;
414
- if (c.operator === "between") return c.value !== "" && c.valueTo !== "";
415
- return c.value !== "";
416
- });
417
- if (validConditions.length === 0) {
418
- onApply(null);
419
- return;
420
- }
421
- onApply({
422
- conditions: validConditions.map((c) => ({
423
- type: "number",
424
- operator: c.operator,
425
- value: c.value ? parseFloat(c.value) : void 0,
426
- valueTo: c.valueTo ? parseFloat(c.valueTo) : void 0,
427
- nextOperator: c.nextOperator
428
- })),
429
- combination: "and"
430
- });
431
- }, [conditions, onApply]);
432
- const handleClear = useCallback(() => {
433
- onApply(null);
434
- }, [onApply]);
435
- return /* @__PURE__ */ jsxs("div", {
436
- className: "gp-grid-filter-content gp-grid-filter-number",
437
- children: [
438
- conditions.map((cond, index) => /* @__PURE__ */ jsxs("div", {
439
- className: "gp-grid-filter-condition",
440
- children: [index > 0 && /* @__PURE__ */ jsxs("div", {
441
- className: "gp-grid-filter-combination",
442
- children: [/* @__PURE__ */ jsx("button", {
443
- type: "button",
444
- className: conditions[index - 1]?.nextOperator === "and" ? "active" : "",
445
- onClick: () => updateCondition(index - 1, { nextOperator: "and" }),
446
- children: "AND"
447
- }), /* @__PURE__ */ jsx("button", {
448
- type: "button",
449
- className: conditions[index - 1]?.nextOperator === "or" ? "active" : "",
450
- onClick: () => updateCondition(index - 1, { nextOperator: "or" }),
451
- children: "OR"
452
- })]
453
- }), /* @__PURE__ */ jsxs("div", {
454
- className: "gp-grid-filter-row",
455
- children: [
456
- /* @__PURE__ */ jsx("select", {
457
- value: cond.operator,
458
- onChange: (e) => updateCondition(index, { operator: e.target.value }),
459
- children: OPERATORS$1.map((op) => /* @__PURE__ */ jsx("option", {
460
- value: op.value,
461
- children: op.label
462
- }, op.value))
463
- }),
464
- cond.operator !== "blank" && cond.operator !== "notBlank" && /* @__PURE__ */ jsx("input", {
465
- type: "number",
466
- value: cond.value,
467
- onChange: (e) => updateCondition(index, { value: e.target.value }),
468
- placeholder: "Value"
469
- }),
470
- cond.operator === "between" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
471
- className: "gp-grid-filter-to",
472
- children: "to"
473
- }), /* @__PURE__ */ jsx("input", {
474
- type: "number",
475
- value: cond.valueTo,
476
- onChange: (e) => updateCondition(index, { valueTo: e.target.value }),
477
- placeholder: "Value"
478
- })] }),
479
- conditions.length > 1 && /* @__PURE__ */ jsx("button", {
480
- type: "button",
481
- className: "gp-grid-filter-remove",
482
- onClick: () => removeCondition(index),
483
- children: "×"
484
- })
485
- ]
486
- })]
487
- }, index)),
488
- /* @__PURE__ */ jsx("button", {
489
- type: "button",
490
- className: "gp-grid-filter-add",
491
- onClick: addCondition,
492
- children: "+ Add condition"
493
- }),
494
- /* @__PURE__ */ jsxs("div", {
495
- className: "gp-grid-filter-buttons",
496
- children: [/* @__PURE__ */ jsx("button", {
497
- type: "button",
498
- className: "gp-grid-filter-btn-clear",
499
- onClick: handleClear,
500
- children: "Clear"
501
- }), /* @__PURE__ */ jsx("button", {
502
- type: "button",
503
- className: "gp-grid-filter-btn-apply",
504
- onClick: handleApply,
505
- children: "Apply"
506
- })]
507
- })
508
- ]
509
- });
510
- }
511
-
512
- //#endregion
513
- //#region src/components/DateFilterContent.tsx
514
- const OPERATORS = [
515
- {
516
- value: "=",
517
- label: "="
518
- },
519
- {
520
- value: "!=",
521
- label: "≠"
522
- },
523
- {
524
- value: ">",
525
- label: ">"
526
- },
527
- {
528
- value: "<",
529
- label: "<"
530
- },
531
- {
532
- value: "between",
533
- label: "↔"
534
- },
535
- {
536
- value: "blank",
537
- label: "Is blank"
538
- },
539
- {
540
- value: "notBlank",
541
- label: "Not blank"
542
- }
543
- ];
544
- function formatDateForInput(date) {
545
- if (!date) return "";
546
- const d = typeof date === "string" ? new Date(date) : date;
547
- if (isNaN(d.getTime())) return "";
548
- return d.toISOString().split("T")[0];
549
- }
550
- function DateFilterContent({ currentFilter, onApply, onClose }) {
551
- const [conditions, setConditions] = useState(useMemo(() => {
552
- if (!currentFilter?.conditions.length) return [{
553
- operator: "=",
554
- value: "",
555
- valueTo: "",
556
- nextOperator: "and"
557
- }];
558
- const defaultCombination = currentFilter.combination ?? "and";
559
- return currentFilter.conditions.map((c) => {
560
- const cond = c;
561
- return {
562
- operator: cond.operator,
563
- value: formatDateForInput(cond.value),
564
- valueTo: formatDateForInput(cond.valueTo),
565
- nextOperator: cond.nextOperator ?? defaultCombination
566
- };
567
- });
568
- }, [currentFilter]));
569
- const updateCondition = useCallback((index, updates) => {
570
- setConditions((prev) => {
571
- const next = [...prev];
572
- next[index] = {
573
- ...next[index],
574
- ...updates
575
- };
576
- return next;
577
- });
578
- }, []);
579
- const addCondition = useCallback(() => {
580
- setConditions((prev) => [...prev, {
581
- operator: "=",
582
- value: "",
583
- valueTo: "",
584
- nextOperator: "and"
585
- }]);
586
- }, []);
587
- const removeCondition = useCallback((index) => {
588
- setConditions((prev) => prev.filter((_, i) => i !== index));
589
- }, []);
590
- const handleApply = useCallback(() => {
591
- const validConditions = conditions.filter((c) => {
592
- if (c.operator === "blank" || c.operator === "notBlank") return true;
593
- if (c.operator === "between") return c.value !== "" && c.valueTo !== "";
594
- return c.value !== "";
595
- });
596
- if (validConditions.length === 0) {
597
- onApply(null);
598
- return;
599
- }
600
- onApply({
601
- conditions: validConditions.map((c) => ({
602
- type: "date",
603
- operator: c.operator,
604
- value: c.value || void 0,
605
- valueTo: c.valueTo || void 0,
606
- nextOperator: c.nextOperator
607
- })),
608
- combination: "and"
609
- });
610
- }, [conditions, onApply]);
611
- const handleClear = useCallback(() => {
612
- onApply(null);
613
- }, [onApply]);
614
- return /* @__PURE__ */ jsxs("div", {
615
- className: "gp-grid-filter-content gp-grid-filter-date",
616
- children: [
617
- conditions.map((cond, index) => /* @__PURE__ */ jsxs("div", {
618
- className: "gp-grid-filter-condition",
619
- children: [index > 0 && /* @__PURE__ */ jsxs("div", {
620
- className: "gp-grid-filter-combination",
621
- children: [/* @__PURE__ */ jsx("button", {
622
- type: "button",
623
- className: conditions[index - 1]?.nextOperator === "and" ? "active" : "",
624
- onClick: () => updateCondition(index - 1, { nextOperator: "and" }),
625
- children: "AND"
626
- }), /* @__PURE__ */ jsx("button", {
627
- type: "button",
628
- className: conditions[index - 1]?.nextOperator === "or" ? "active" : "",
629
- onClick: () => updateCondition(index - 1, { nextOperator: "or" }),
630
- children: "OR"
631
- })]
632
- }), /* @__PURE__ */ jsxs("div", {
633
- className: "gp-grid-filter-row",
634
- children: [
635
- /* @__PURE__ */ jsx("select", {
636
- value: cond.operator,
637
- onChange: (e) => updateCondition(index, { operator: e.target.value }),
638
- children: OPERATORS.map((op) => /* @__PURE__ */ jsx("option", {
639
- value: op.value,
640
- children: op.label
641
- }, op.value))
642
- }),
643
- cond.operator !== "blank" && cond.operator !== "notBlank" && /* @__PURE__ */ jsx("input", {
644
- type: "date",
645
- value: cond.value,
646
- onChange: (e) => updateCondition(index, { value: e.target.value })
647
- }),
648
- cond.operator === "between" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
649
- className: "gp-grid-filter-to",
650
- children: "to"
651
- }), /* @__PURE__ */ jsx("input", {
652
- type: "date",
653
- value: cond.valueTo,
654
- onChange: (e) => updateCondition(index, { valueTo: e.target.value })
655
- })] }),
656
- conditions.length > 1 && /* @__PURE__ */ jsx("button", {
657
- type: "button",
658
- className: "gp-grid-filter-remove",
659
- onClick: () => removeCondition(index),
660
- children: "×"
661
- })
662
- ]
663
- })]
664
- }, index)),
665
- /* @__PURE__ */ jsx("button", {
666
- type: "button",
667
- className: "gp-grid-filter-add",
668
- onClick: addCondition,
669
- children: "+ Add condition"
670
- }),
671
- /* @__PURE__ */ jsxs("div", {
672
- className: "gp-grid-filter-buttons",
673
- children: [/* @__PURE__ */ jsx("button", {
674
- type: "button",
675
- className: "gp-grid-filter-btn-clear",
676
- onClick: handleClear,
677
- children: "Clear"
678
- }), /* @__PURE__ */ jsx("button", {
679
- type: "button",
680
- className: "gp-grid-filter-btn-apply",
681
- onClick: handleApply,
682
- children: "Apply"
683
- })]
684
- })
685
- ]
686
- });
687
- }
688
-
689
- //#endregion
690
- //#region src/components/FilterPopup.tsx
691
- function FilterPopup({ column, colIndex, anchorRect, distinctValues, currentFilter, onApply, onClose }) {
692
- const popupRef = useRef(null);
693
- useEffect(() => {
694
- const handleClickOutside = (e) => {
695
- const target = e.target;
696
- if (target.closest(".gp-grid-filter-icon")) return;
697
- if (popupRef.current && !popupRef.current.contains(target)) onClose();
698
- };
699
- const handleKeyDown = (e) => {
700
- if (e.key === "Escape") onClose();
701
- };
702
- requestAnimationFrame(() => {
703
- document.addEventListener("mousedown", handleClickOutside);
704
- document.addEventListener("keydown", handleKeyDown);
705
- });
706
- return () => {
707
- document.removeEventListener("mousedown", handleClickOutside);
708
- document.removeEventListener("keydown", handleKeyDown);
709
- };
710
- }, [onClose]);
711
- const handleApply = useCallback((filter) => {
712
- onApply(column.colId ?? column.field, filter);
713
- onClose();
714
- }, [
715
- column,
716
- onApply,
717
- onClose
718
- ]);
719
- const popupStyle = {
720
- position: "fixed",
721
- top: anchorRect.top + anchorRect.height + 4,
722
- left: anchorRect.left,
723
- minWidth: Math.max(200, anchorRect.width),
724
- zIndex: 1e4
725
- };
726
- const dataType = column.cellDataType;
727
- const isTextType = dataType === "text" || dataType === "object";
728
- const isNumberType = dataType === "number";
729
- const isDateType = dataType === "date" || dataType === "dateString" || dataType === "dateTime" || dataType === "dateTimeString";
730
- return /* @__PURE__ */ jsxs("div", {
731
- ref: popupRef,
732
- className: "gp-grid-filter-popup",
733
- style: popupStyle,
734
- children: [
735
- /* @__PURE__ */ jsxs("div", {
736
- className: "gp-grid-filter-header",
737
- children: ["Filter: ", column.headerName ?? column.field]
738
- }),
739
- isTextType && /* @__PURE__ */ jsx(TextFilterContent, {
740
- distinctValues,
741
- currentFilter,
742
- onApply: handleApply,
743
- onClose
744
- }),
745
- isNumberType && /* @__PURE__ */ jsx(NumberFilterContent, {
746
- currentFilter,
747
- onApply: handleApply,
748
- onClose
749
- }),
750
- isDateType && /* @__PURE__ */ jsx(DateFilterContent, {
751
- currentFilter,
752
- onApply: handleApply,
753
- onClose
754
- }),
755
- !isTextType && !isNumberType && !isDateType && /* @__PURE__ */ jsx(TextFilterContent, {
756
- distinctValues,
757
- currentFilter,
758
- onApply: handleApply,
759
- onClose
760
- })
761
- ]
762
- });
763
- }
764
-
765
- //#endregion
766
- //#region src/gridState/reducer.ts
767
- function createInitialState(args) {
768
- return {
769
- slots: /* @__PURE__ */ new Map(),
770
- activeCell: null,
771
- selectionRange: null,
772
- editingCell: null,
773
- contentWidth: 0,
774
- contentHeight: args?.initialHeight ?? 0,
775
- viewportWidth: args?.initialWidth ?? 0,
776
- headers: /* @__PURE__ */ new Map(),
777
- filterPopup: null,
778
- isLoading: false,
779
- error: null,
780
- totalRows: 0,
781
- visibleRowRange: null,
782
- hoverPosition: null
783
- };
784
- }
785
- /**
786
- * Apply a single instruction to mutable slot maps and return other state changes.
787
- * This allows batching multiple slot operations efficiently.
788
- */
789
- function applyInstruction(instruction, slots, headers) {
790
- switch (instruction.type) {
791
- case "CREATE_SLOT":
792
- slots.set(instruction.slotId, {
793
- slotId: instruction.slotId,
794
- rowIndex: -1,
795
- rowData: {},
796
- translateY: 0
797
- });
798
- return null;
799
- case "DESTROY_SLOT":
800
- slots.delete(instruction.slotId);
801
- return null;
802
- case "ASSIGN_SLOT": {
803
- const existing = slots.get(instruction.slotId);
804
- if (existing) slots.set(instruction.slotId, {
805
- ...existing,
806
- rowIndex: instruction.rowIndex,
807
- rowData: instruction.rowData
808
- });
809
- return null;
810
- }
811
- case "MOVE_SLOT": {
812
- const existing = slots.get(instruction.slotId);
813
- if (existing) slots.set(instruction.slotId, {
814
- ...existing,
815
- translateY: instruction.translateY
816
- });
817
- return null;
818
- }
819
- case "SET_ACTIVE_CELL": return { activeCell: instruction.position };
820
- case "SET_SELECTION_RANGE": return { selectionRange: instruction.range };
821
- case "UPDATE_VISIBLE_RANGE": return { visibleRowRange: {
822
- start: instruction.start,
823
- end: instruction.end
824
- } };
825
- case "SET_HOVER_POSITION": return { hoverPosition: instruction.position };
826
- case "START_EDIT": return { editingCell: {
827
- row: instruction.row,
828
- col: instruction.col,
829
- initialValue: instruction.initialValue
830
- } };
831
- case "STOP_EDIT": return { editingCell: null };
832
- case "SET_CONTENT_SIZE": return {
833
- contentWidth: instruction.width,
834
- contentHeight: instruction.height,
835
- viewportWidth: instruction.viewportWidth
836
- };
837
- case "UPDATE_HEADER":
838
- headers.set(instruction.colIndex, {
839
- column: instruction.column,
840
- sortDirection: instruction.sortDirection,
841
- sortIndex: instruction.sortIndex,
842
- sortable: instruction.sortable,
843
- filterable: instruction.filterable,
844
- hasFilter: instruction.hasFilter
845
- });
846
- return null;
847
- case "OPEN_FILTER_POPUP": return { filterPopup: {
848
- isOpen: true,
849
- colIndex: instruction.colIndex,
850
- column: instruction.column,
851
- anchorRect: instruction.anchorRect,
852
- distinctValues: instruction.distinctValues,
853
- currentFilter: instruction.currentFilter
854
- } };
855
- case "CLOSE_FILTER_POPUP": return { filterPopup: null };
856
- case "DATA_LOADING": return {
857
- isLoading: true,
858
- error: null
859
- };
860
- case "DATA_LOADED": return {
861
- isLoading: false,
862
- totalRows: instruction.totalRows
863
- };
864
- case "DATA_ERROR": return {
865
- isLoading: false,
866
- error: instruction.error
867
- };
868
- case "ROWS_ADDED":
869
- case "ROWS_REMOVED": return { totalRows: instruction.totalRows };
870
- case "ROWS_UPDATED":
871
- case "TRANSACTION_PROCESSED": return null;
872
- default: return null;
873
- }
874
- }
875
- function gridReducer(state, action) {
876
- if (action.type === "RESET") return createInitialState();
877
- const { instructions } = action;
878
- if (instructions.length === 0) return state;
879
- const newSlots = new Map(state.slots);
880
- const newHeaders = new Map(state.headers);
881
- let stateChanges = {};
882
- for (const instruction of instructions) {
883
- const changes = applyInstruction(instruction, newSlots, newHeaders);
884
- if (changes) stateChanges = {
885
- ...stateChanges,
886
- ...changes
887
- };
888
- }
889
- return {
890
- ...state,
891
- ...stateChanges,
892
- slots: newSlots,
893
- headers: newHeaders
894
- };
895
- }
896
-
897
- //#endregion
898
- //#region src/hooks/useInputHandler.ts
899
- const AUTO_SCROLL_INTERVAL = 16;
900
- /**
901
- * Find the slot for a given row index
902
- */
903
- function findSlotForRow(slots, rowIndex) {
904
- for (const slot of slots.values()) if (slot.rowIndex === rowIndex) return slot;
905
- return null;
906
- }
907
- /**
908
- * Scroll a cell into view if needed
909
- */
910
- function scrollCellIntoView(core, container, row, rowHeight, headerHeight, slots) {
911
- const slot = findSlotForRow(slots, row);
912
- const cellViewportTop = (slot ? slot.translateY : headerHeight + row * rowHeight) - container.scrollTop;
913
- const cellViewportBottom = cellViewportTop + rowHeight;
914
- const visibleTop = headerHeight;
915
- const visibleBottom = container.clientHeight;
916
- if (cellViewportTop < visibleTop) container.scrollTop = core.getScrollTopForRow(row);
917
- else if (cellViewportBottom > visibleBottom) {
918
- const visibleDataHeight = container.clientHeight - headerHeight;
919
- const rowsInView = Math.floor(visibleDataHeight / rowHeight);
920
- const targetRow = Math.max(0, row - rowsInView + 1);
921
- container.scrollTop = core.getScrollTopForRow(targetRow);
922
- }
923
- }
924
- /**
925
- * Hook for managing all input handling using core's InputHandler
926
- */
927
- function useInputHandler(coreRef, containerRef, columns, options) {
928
- const { activeCell, selectionRange, editingCell, filterPopupOpen, rowHeight, headerHeight, columnPositions, visibleColumnsWithIndices, slots } = options;
929
- const autoScrollRef = useRef(null);
930
- const [dragState, setDragState] = useState({
931
- isDragging: false,
932
- dragType: null,
933
- fillSourceRange: null,
934
- fillTarget: null
935
- });
936
- useEffect(() => {
937
- const core = coreRef.current;
938
- if (core?.input) core.input.updateDeps({
939
- getHeaderHeight: () => headerHeight,
940
- getRowHeight: () => rowHeight,
941
- getColumnPositions: () => columnPositions,
942
- getColumnCount: () => visibleColumnsWithIndices.length,
943
- getOriginalColumnIndex: (visibleIndex) => {
944
- const info = visibleColumnsWithIndices[visibleIndex];
945
- return info ? info.originalIndex : visibleIndex;
946
- }
947
- });
948
- }, [
949
- coreRef,
950
- headerHeight,
951
- rowHeight,
952
- columnPositions,
953
- visibleColumnsWithIndices
954
- ]);
955
- const startAutoScroll = useCallback((dx, dy) => {
956
- if (autoScrollRef.current) clearInterval(autoScrollRef.current);
957
- autoScrollRef.current = setInterval(() => {
958
- const container = containerRef.current;
959
- if (container) {
960
- container.scrollTop += dy;
961
- container.scrollLeft += dx;
962
- }
963
- }, AUTO_SCROLL_INTERVAL);
964
- }, [containerRef]);
965
- const stopAutoScroll = useCallback(() => {
966
- if (autoScrollRef.current) {
967
- clearInterval(autoScrollRef.current);
968
- autoScrollRef.current = null;
969
- }
970
- }, []);
971
- const getContainerBounds = useCallback(() => {
972
- const container = containerRef.current;
973
- if (!container) return null;
974
- const rect = container.getBoundingClientRect();
975
- return {
976
- top: rect.top,
977
- left: rect.left,
978
- width: rect.width,
979
- height: rect.height,
980
- scrollTop: container.scrollTop,
981
- scrollLeft: container.scrollLeft
982
- };
983
- }, [containerRef]);
984
- const toPointerEventData = (e) => ({
985
- clientX: e.clientX,
986
- clientY: e.clientY,
987
- button: e.button,
988
- shiftKey: e.shiftKey,
989
- ctrlKey: e.ctrlKey,
990
- metaKey: e.metaKey
991
- });
992
- const startGlobalDragListeners = useCallback(() => {
993
- const handleMouseMove = (e) => {
994
- const core = coreRef.current;
995
- const bounds = getContainerBounds();
996
- if (!core?.input || !bounds) return;
997
- const result = core.input.handleDragMove(toPointerEventData(e), bounds);
998
- if (result) {
999
- if (result.autoScroll) startAutoScroll(result.autoScroll.dx, result.autoScroll.dy);
1000
- else stopAutoScroll();
1001
- setDragState(core.input.getDragState());
1002
- }
1003
- };
1004
- const handleMouseUp = () => {
1005
- const core = coreRef.current;
1006
- if (core?.input) {
1007
- core.input.handleDragEnd();
1008
- setDragState(core.input.getDragState());
1009
- }
1010
- stopAutoScroll();
1011
- document.removeEventListener("mousemove", handleMouseMove);
1012
- document.removeEventListener("mouseup", handleMouseUp);
1013
- };
1014
- document.addEventListener("mousemove", handleMouseMove);
1015
- document.addEventListener("mouseup", handleMouseUp);
1016
- }, [
1017
- coreRef,
1018
- getContainerBounds,
1019
- startAutoScroll,
1020
- stopAutoScroll
1021
- ]);
1022
- const handleCellMouseDown = useCallback((rowIndex, colIndex, e) => {
1023
- const core = coreRef.current;
1024
- if (!core?.input) return;
1025
- const result = core.input.handleCellMouseDown(rowIndex, colIndex, toPointerEventData(e));
1026
- if (result.focusContainer) containerRef.current?.focus();
1027
- if (result.startDrag === "selection") {
1028
- core.input.startSelectionDrag();
1029
- setDragState(core.input.getDragState());
1030
- startGlobalDragListeners();
1031
- }
1032
- }, [
1033
- coreRef,
1034
- containerRef,
1035
- startGlobalDragListeners
1036
- ]);
1037
- const handleCellDoubleClick = useCallback((rowIndex, colIndex) => {
1038
- const core = coreRef.current;
1039
- if (!core?.input) return;
1040
- core.input.handleCellDoubleClick(rowIndex, colIndex);
1041
- }, [coreRef]);
1042
- const handleFillHandleMouseDown = useCallback((e) => {
1043
- const core = coreRef.current;
1044
- if (!core?.input) return;
1045
- const result = core.input.handleFillHandleMouseDown(activeCell, selectionRange, toPointerEventData(e));
1046
- if (result.preventDefault) e.preventDefault();
1047
- if (result.stopPropagation) e.stopPropagation();
1048
- if (result.startDrag === "fill") {
1049
- setDragState(core.input.getDragState());
1050
- startGlobalDragListeners();
1051
- }
1052
- }, [
1053
- coreRef,
1054
- activeCell,
1055
- selectionRange,
1056
- startGlobalDragListeners
1057
- ]);
1058
- const handleHeaderClick = useCallback((colIndex, e) => {
1059
- const core = coreRef.current;
1060
- if (!core?.input) return;
1061
- const column = columns[colIndex];
1062
- if (!column) return;
1063
- const colId = column.colId ?? column.field;
1064
- core.input.handleHeaderClick(colId, e.shiftKey);
1065
- }, [coreRef, columns]);
1066
- const handleKeyDown = useCallback((e) => {
1067
- const core = coreRef.current;
1068
- const container = containerRef.current;
1069
- if (!core?.input) return;
1070
- const result = core.input.handleKeyDown({
1071
- key: e.key,
1072
- shiftKey: e.shiftKey,
1073
- ctrlKey: e.ctrlKey,
1074
- metaKey: e.metaKey
1075
- }, activeCell, editingCell, filterPopupOpen);
1076
- if (result.preventDefault) e.preventDefault();
1077
- if (result.scrollToCell && container) scrollCellIntoView(core, container, result.scrollToCell.row, rowHeight, headerHeight, slots);
1078
- }, [
1079
- coreRef,
1080
- containerRef,
1081
- activeCell,
1082
- editingCell,
1083
- filterPopupOpen,
1084
- rowHeight,
1085
- headerHeight,
1086
- slots
1087
- ]);
1088
- const handleWheel = useCallback((e, wheelDampening) => {
1089
- const core = coreRef.current;
1090
- const container = containerRef.current;
1091
- if (!core?.input || !container) return;
1092
- const dampened = core.input.handleWheel(e.deltaY, e.deltaX, wheelDampening);
1093
- if (dampened) {
1094
- e.preventDefault();
1095
- container.scrollTop += dampened.dy;
1096
- container.scrollLeft += dampened.dx;
1097
- }
1098
- }, [coreRef, containerRef]);
1099
- useEffect(() => {
1100
- return () => {
1101
- stopAutoScroll();
1102
- };
1103
- }, [stopAutoScroll]);
1104
- return {
1105
- handleCellMouseDown,
1106
- handleCellDoubleClick,
1107
- handleFillHandleMouseDown,
1108
- handleHeaderClick,
1109
- handleKeyDown,
1110
- handleWheel,
1111
- dragState
1112
- };
1113
- }
1114
-
1115
- //#endregion
1116
- //#region src/renderers/cellRenderer.tsx
1117
- /**
1118
- * Get cell value from row data, supporting dot-notation for nested fields
1119
- */
1120
- function getCellValue(rowData, field) {
1121
- const parts = field.split(".");
1122
- let value = rowData;
1123
- for (const part of parts) {
1124
- if (value == null || typeof value !== "object") return null;
1125
- value = value[part];
1126
- }
1127
- return value ?? null;
1128
- }
1129
- /**
1130
- * Render cell content based on column configuration and renderer registries
1131
- */
1132
- function renderCell(options) {
1133
- const { column, rowData, rowIndex, colIndex, isActive, isSelected, isEditing, cellRenderers, globalCellRenderer } = options;
1134
- const value = getCellValue(rowData, column.field);
1135
- const params = {
1136
- value,
1137
- rowData,
1138
- column,
1139
- rowIndex,
1140
- colIndex,
1141
- isActive,
1142
- isSelected,
1143
- isEditing
1144
- };
1145
- if (column.cellRenderer && typeof column.cellRenderer === "string") {
1146
- const renderer = cellRenderers[column.cellRenderer];
1147
- if (renderer) return renderer(params);
1148
- }
1149
- if (globalCellRenderer) return globalCellRenderer(params);
1150
- return value == null ? "" : String(value);
1151
- }
1152
-
1153
- //#endregion
1154
- //#region src/renderers/editRenderer.tsx
1155
- /**
1156
- * Render edit cell content based on column configuration and renderer registries
1157
- */
1158
- function renderEditCell(options) {
1159
- const { column, rowData, rowIndex, colIndex, initialValue, coreRef, editRenderers, globalEditRenderer } = options;
1160
- const core = coreRef.current;
1161
- if (!core) return null;
1162
- const params = {
1163
- value: getCellValue(rowData, column.field),
1164
- rowData,
1165
- column,
1166
- rowIndex,
1167
- colIndex,
1168
- isActive: true,
1169
- isSelected: true,
1170
- isEditing: true,
1171
- initialValue,
1172
- onValueChange: (newValue) => core.updateEditValue(newValue),
1173
- onCommit: () => core.commitEdit(),
1174
- onCancel: () => core.cancelEdit()
1175
- };
1176
- if (column.editRenderer && typeof column.editRenderer === "string") {
1177
- const renderer = editRenderers[column.editRenderer];
1178
- if (renderer) return renderer(params);
1179
- }
1180
- if (globalEditRenderer) return globalEditRenderer(params);
1181
- return /* @__PURE__ */ jsx("input", {
1182
- className: "gp-grid-edit-input",
1183
- type: "text",
1184
- defaultValue: initialValue == null ? "" : String(initialValue),
1185
- autoFocus: true,
1186
- onFocus: (e) => e.target.select(),
1187
- onChange: (e) => core.updateEditValue(e.target.value),
1188
- onKeyDown: (e) => {
1189
- e.stopPropagation();
1190
- if (e.key === "Enter") core.commitEdit();
1191
- else if (e.key === "Escape") core.cancelEdit();
1192
- else if (e.key === "Tab") {
1193
- e.preventDefault();
1194
- core.commitEdit();
1195
- core.selection.moveFocus(e.shiftKey ? "left" : "right", false);
1196
- }
1197
- },
1198
- onBlur: () => core.commitEdit()
1199
- });
1200
- }
1201
-
1202
- //#endregion
1203
- //#region src/renderers/headerRenderer.tsx
1204
- /**
1205
- * Render header content based on column configuration and renderer registries
1206
- */
1207
- function renderHeader(options) {
1208
- const { column, colIndex, sortDirection, sortIndex, sortable, filterable, hasFilter, coreRef, containerRef, headerRenderers, globalHeaderRenderer } = options;
1209
- const core = coreRef.current;
1210
- const params = {
1211
- column,
1212
- colIndex,
1213
- sortDirection,
1214
- sortIndex,
1215
- sortable,
1216
- filterable,
1217
- hasFilter,
1218
- onSort: (direction, addToExisting) => {
1219
- if (core && sortable) core.setSort(column.colId ?? column.field, direction, addToExisting);
1220
- },
1221
- onFilterClick: () => {
1222
- if (core && filterable) {
1223
- const headerCell = containerRef.current?.querySelector(`[data-col-index="${colIndex}"]`);
1224
- if (headerCell) {
1225
- const rect = headerCell.getBoundingClientRect();
1226
- core.openFilterPopup(colIndex, {
1227
- top: rect.top,
1228
- left: rect.left,
1229
- width: rect.width,
1230
- height: rect.height
1231
- });
1232
- }
1233
- }
1234
- }
1235
- };
1236
- if (column.headerRenderer && typeof column.headerRenderer === "string") {
1237
- const renderer = headerRenderers[column.headerRenderer];
1238
- if (renderer) return renderer(params);
1239
- }
1240
- if (globalHeaderRenderer) return globalHeaderRenderer(params);
1241
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
1242
- className: "gp-grid-header-text",
1243
- children: column.headerName ?? column.field
1244
- }), /* @__PURE__ */ jsxs("span", {
1245
- className: "gp-grid-header-icons",
1246
- children: [sortable && /* @__PURE__ */ jsxs("span", {
1247
- className: "gp-grid-sort-arrows",
1248
- children: [/* @__PURE__ */ jsxs("span", {
1249
- className: "gp-grid-sort-arrows-stack",
1250
- children: [/* @__PURE__ */ jsx("svg", {
1251
- className: `gp-grid-sort-arrow-up${sortDirection === "asc" ? " active" : ""}`,
1252
- width: "8",
1253
- height: "6",
1254
- viewBox: "0 0 8 6",
1255
- children: /* @__PURE__ */ jsx("path", {
1256
- d: "M4 0L8 6H0L4 0Z",
1257
- fill: "currentColor"
1258
- })
1259
- }), /* @__PURE__ */ jsx("svg", {
1260
- className: `gp-grid-sort-arrow-down${sortDirection === "desc" ? " active" : ""}`,
1261
- width: "8",
1262
- height: "6",
1263
- viewBox: "0 0 8 6",
1264
- children: /* @__PURE__ */ jsx("path", {
1265
- d: "M4 6L0 0H8L4 6Z",
1266
- fill: "currentColor"
1267
- })
1268
- })]
1269
- }), sortIndex !== void 0 && sortIndex > 0 && /* @__PURE__ */ jsx("span", {
1270
- className: "gp-grid-sort-index",
1271
- children: sortIndex
1272
- })]
1273
- }), filterable && /* @__PURE__ */ jsx("span", {
1274
- className: `gp-grid-filter-icon${hasFilter ? " active" : ""}`,
1275
- onMouseDown: (e) => {
1276
- e.stopPropagation();
1277
- e.preventDefault();
1278
- params.onFilterClick();
1279
- },
1280
- onClick: (e) => {
1281
- e.stopPropagation();
1282
- },
1283
- children: /* @__PURE__ */ jsx("svg", {
1284
- width: "16",
1285
- height: "16",
1286
- viewBox: "0 0 24 24",
1287
- fill: "currentColor",
1288
- children: /* @__PURE__ */ jsx("path", { d: "M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" })
1289
- })
1290
- })]
1291
- })] });
1292
- }
1293
-
1294
- //#endregion
1295
- //#region src/Grid.tsx
1296
- /**
1297
- * Grid component
1298
- * @param props - Grid component props
1299
- * @returns Grid React component
1300
- */
1301
- function Grid(props) {
1302
- injectStyles();
1303
- const { columns, dataSource: providedDataSource, rowData, rowHeight, headerHeight = rowHeight, overscan = 3, sortingEnabled = true, darkMode = false, wheelDampening = .1, cellRenderers = {}, editRenderers = {}, headerRenderers = {}, cellRenderer, editRenderer, headerRenderer, initialWidth, initialHeight, gridRef, highlighting } = props;
1304
- const containerRef = useRef(null);
1305
- const coreRef = useRef(null);
1306
- const prevDataSourceRef = useRef(null);
1307
- const hasInitializedRef = useRef(false);
1308
- const [state, dispatch] = useReducer(gridReducer, {
1309
- initialWidth,
1310
- initialHeight
1311
- }, createInitialState);
1312
- const totalHeaderHeight = headerHeight;
1313
- const dataSourceCacheRef = useRef(null);
1314
- const cache = dataSourceCacheRef.current;
1315
- if (!cache || cache.providedDataSource !== providedDataSource || cache.rowData !== rowData) {
1316
- if (cache?.ownsDataSource) cache.dataSource.destroy?.();
1317
- if (providedDataSource) dataSourceCacheRef.current = {
1318
- dataSource: providedDataSource,
1319
- ownsDataSource: false,
1320
- providedDataSource,
1321
- rowData
1322
- };
1323
- else if (rowData) dataSourceCacheRef.current = {
1324
- dataSource: createDataSourceFromArray$1(rowData),
1325
- ownsDataSource: true,
1326
- providedDataSource,
1327
- rowData
1328
- };
1329
- else dataSourceCacheRef.current = {
1330
- dataSource: createClientDataSource$1([]),
1331
- ownsDataSource: true,
1332
- providedDataSource,
1333
- rowData
1334
- };
1335
- }
1336
- const { dataSource, ownsDataSource } = dataSourceCacheRef.current;
1337
- useEffect(() => {
1338
- return () => {
1339
- if (dataSourceCacheRef.current?.ownsDataSource) {
1340
- dataSourceCacheRef.current.dataSource.destroy?.();
1341
- dataSourceCacheRef.current = null;
1342
- }
1343
- };
1344
- }, []);
1345
- useEffect(() => {
1346
- const prevDataSource = prevDataSourceRef.current;
1347
- if (prevDataSource && prevDataSource !== dataSource) dispatch({ type: "RESET" });
1348
- prevDataSourceRef.current = dataSource;
1349
- }, [dataSource]);
1350
- const visibleColumnsWithIndices = useMemo(() => columns.map((col, index) => ({
1351
- column: col,
1352
- originalIndex: index
1353
- })).filter(({ column }) => !column.hidden), [columns]);
1354
- const { positions: columnPositions, widths: columnWidths } = useMemo(() => calculateScaledColumnPositions(visibleColumnsWithIndices.map((v) => v.column), state.viewportWidth), [visibleColumnsWithIndices, state.viewportWidth]);
1355
- const totalWidth = getTotalWidth(columnPositions);
1356
- const { handleCellMouseDown, handleCellDoubleClick, handleFillHandleMouseDown, handleHeaderClick, handleKeyDown, handleWheel, dragState } = useInputHandler(coreRef, containerRef, columns, {
1357
- activeCell: state.activeCell,
1358
- selectionRange: state.selectionRange,
1359
- editingCell: state.editingCell,
1360
- filterPopupOpen: state.filterPopup?.isOpen ?? false,
1361
- rowHeight,
1362
- headerHeight: totalHeaderHeight,
1363
- columnPositions,
1364
- visibleColumnsWithIndices,
1365
- slots: state.slots
1366
- });
1367
- useEffect(() => {
1368
- if (hasInitializedRef.current) dispatch({ type: "RESET" });
1369
- hasInitializedRef.current = true;
1370
- const core = new GridCore$1({
1371
- columns,
1372
- dataSource,
1373
- rowHeight,
1374
- headerHeight: totalHeaderHeight,
1375
- overscan,
1376
- sortingEnabled,
1377
- highlighting
1378
- });
1379
- coreRef.current = core;
1380
- core.input.updateDeps({
1381
- getHeaderHeight: () => totalHeaderHeight,
1382
- getRowHeight: () => rowHeight,
1383
- getColumnPositions: () => columnPositions,
1384
- getColumnCount: () => visibleColumnsWithIndices.length,
1385
- getOriginalColumnIndex: (visibleIndex) => {
1386
- const info = visibleColumnsWithIndices[visibleIndex];
1387
- return info ? info.originalIndex : visibleIndex;
1388
- }
1389
- });
1390
- if (gridRef) gridRef.current = { core };
1391
- const unsubscribe = core.onBatchInstruction((instructions) => {
1392
- dispatch({
1393
- type: "BATCH_INSTRUCTIONS",
1394
- instructions
1395
- });
1396
- });
1397
- core.initialize();
1398
- const container = containerRef.current;
1399
- if (container) core.setViewport(container.scrollTop, container.scrollLeft, container.clientWidth, container.clientHeight);
1400
- return () => {
1401
- unsubscribe();
1402
- core.destroy();
1403
- coreRef.current = null;
1404
- if (gridRef) gridRef.current = null;
1405
- };
1406
- }, [
1407
- columns,
1408
- dataSource,
1409
- rowHeight,
1410
- totalHeaderHeight,
1411
- overscan,
1412
- sortingEnabled,
1413
- gridRef,
1414
- highlighting
1415
- ]);
1416
- useEffect(() => {
1417
- const mutableDataSource = dataSource;
1418
- if (mutableDataSource.subscribe) return mutableDataSource.subscribe(() => {
1419
- coreRef.current?.refresh();
1420
- });
1421
- }, [dataSource]);
1422
- const handleScroll = useCallback(() => {
1423
- const container = containerRef.current;
1424
- const core = coreRef.current;
1425
- if (!container || !core) return;
1426
- core.setViewport(container.scrollTop, container.scrollLeft, container.clientWidth, container.clientHeight);
1427
- }, []);
1428
- useEffect(() => {
1429
- const container = containerRef.current;
1430
- const core = coreRef.current;
1431
- if (!container || !core) return;
1432
- if (typeof ResizeObserver === "undefined") {
1433
- handleScroll();
1434
- return;
1435
- }
1436
- const resizeObserver = new ResizeObserver(() => {
1437
- core.setViewport(container.scrollTop, container.scrollLeft, container.clientWidth, container.clientHeight);
1438
- });
1439
- resizeObserver.observe(container);
1440
- handleScroll();
1441
- return () => resizeObserver.disconnect();
1442
- }, [handleScroll]);
1443
- useEffect(() => {
1444
- const container = containerRef.current;
1445
- if (!container) return;
1446
- const wheelHandler = (e) => {
1447
- handleWheel(e, wheelDampening);
1448
- };
1449
- container.addEventListener("wheel", wheelHandler, { passive: false });
1450
- return () => container.removeEventListener("wheel", wheelHandler);
1451
- }, [handleWheel, wheelDampening]);
1452
- const handleFilterApply = useCallback((colId, filter) => {
1453
- const core = coreRef.current;
1454
- if (core) core.setFilter(colId, filter);
1455
- }, []);
1456
- const handleFilterPopupClose = useCallback(() => {
1457
- const core = coreRef.current;
1458
- if (core) core.closeFilterPopup();
1459
- }, []);
1460
- const handleCellMouseEnter = useCallback((rowIndex, colIndex) => {
1461
- coreRef.current?.input.handleCellMouseEnter(rowIndex, colIndex);
1462
- }, []);
1463
- const handleCellMouseLeave = useCallback(() => {
1464
- coreRef.current?.input.handleCellMouseLeave();
1465
- }, []);
1466
- const slotsArray = useMemo(() => Array.from(state.slots.values()), [state.slots]);
1467
- const fillHandlePosition = useMemo(() => {
1468
- const { activeCell, selectionRange, slots } = state;
1469
- if (!activeCell && !selectionRange) return null;
1470
- let row, col;
1471
- let minCol, maxCol;
1472
- if (selectionRange) {
1473
- row = Math.max(selectionRange.startRow, selectionRange.endRow);
1474
- col = Math.max(selectionRange.startCol, selectionRange.endCol);
1475
- minCol = Math.min(selectionRange.startCol, selectionRange.endCol);
1476
- maxCol = Math.max(selectionRange.startCol, selectionRange.endCol);
1477
- } else if (activeCell) {
1478
- row = activeCell.row;
1479
- col = activeCell.col;
1480
- minCol = col;
1481
- maxCol = col;
1482
- } else return null;
1483
- for (let c = minCol; c <= maxCol; c++) {
1484
- const column = columns[c];
1485
- if (!column || column.hidden) continue;
1486
- if (column.editable !== true) return null;
1487
- }
1488
- const visibleIndex = visibleColumnsWithIndices.findIndex((v) => v.originalIndex === col);
1489
- if (visibleIndex === -1) return null;
1490
- let cellTop = null;
1491
- for (const slot of slots.values()) if (slot.rowIndex === row) {
1492
- cellTop = slot.translateY;
1493
- break;
1494
- }
1495
- if (cellTop === null) return null;
1496
- const cellLeft = columnPositions[visibleIndex] ?? 0;
1497
- const cellWidth = columnWidths[visibleIndex] ?? 0;
1498
- return {
1499
- top: cellTop + rowHeight - 5,
1500
- left: cellLeft + cellWidth - 20
1501
- };
1502
- }, [
1503
- state.activeCell,
1504
- state.selectionRange,
1505
- state.slots,
1506
- rowHeight,
1507
- columnPositions,
1508
- columnWidths,
1509
- columns,
1510
- visibleColumnsWithIndices
1511
- ]);
1512
- return /* @__PURE__ */ jsxs("div", {
1513
- ref: containerRef,
1514
- className: `gp-grid-container${darkMode ? " gp-grid-container--dark" : ""}`,
1515
- style: {
1516
- width: "100%",
1517
- height: "100%",
1518
- overflow: "auto",
1519
- position: "relative"
1520
- },
1521
- onScroll: handleScroll,
1522
- onKeyDown: handleKeyDown,
1523
- tabIndex: 0,
1524
- children: [/* @__PURE__ */ jsxs("div", {
1525
- style: {
1526
- width: Math.max(state.contentWidth, totalWidth),
1527
- height: Math.max(state.contentHeight, totalHeaderHeight),
1528
- position: "relative",
1529
- minWidth: "100%"
1530
- },
1531
- children: [
1532
- /* @__PURE__ */ jsx("div", {
1533
- className: "gp-grid-header",
1534
- style: {
1535
- position: "sticky",
1536
- top: 0,
1537
- left: 0,
1538
- height: headerHeight,
1539
- width: Math.max(state.contentWidth, totalWidth),
1540
- minWidth: "100%"
1541
- },
1542
- children: visibleColumnsWithIndices.map(({ column, originalIndex }, visibleIndex) => {
1543
- const headerInfo = state.headers.get(originalIndex);
1544
- return /* @__PURE__ */ jsx("div", {
1545
- className: "gp-grid-header-cell",
1546
- "data-col-index": originalIndex,
1547
- style: {
1548
- position: "absolute",
1549
- left: `${columnPositions[visibleIndex]}px`,
1550
- top: 0,
1551
- width: `${columnWidths[visibleIndex]}px`,
1552
- height: `${headerHeight}px`,
1553
- background: "transparent"
1554
- },
1555
- onClick: (e) => handleHeaderClick(originalIndex, e),
1556
- children: renderHeader({
1557
- column,
1558
- colIndex: originalIndex,
1559
- sortDirection: headerInfo?.sortDirection,
1560
- sortIndex: headerInfo?.sortIndex,
1561
- sortable: headerInfo?.sortable ?? true,
1562
- filterable: headerInfo?.filterable ?? true,
1563
- hasFilter: headerInfo?.hasFilter ?? false,
1564
- coreRef,
1565
- containerRef,
1566
- headerRenderers,
1567
- globalHeaderRenderer: headerRenderer
1568
- })
1569
- }, column.colId ?? column.field);
1570
- })
1571
- }),
1572
- slotsArray.map((slot) => {
1573
- if (slot.rowIndex < 0) return null;
1574
- return /* @__PURE__ */ jsx("div", {
1575
- className: ["gp-grid-row", ...coreRef.current?.highlight?.computeRowClasses(slot.rowIndex, slot.rowData) ?? []].filter(Boolean).join(" "),
1576
- style: {
1577
- position: "absolute",
1578
- top: 0,
1579
- left: 0,
1580
- transform: `translateY(${slot.translateY}px)`,
1581
- width: `${Math.max(state.contentWidth, totalWidth)}px`,
1582
- height: `${rowHeight}px`
1583
- },
1584
- children: visibleColumnsWithIndices.map(({ column, originalIndex }, visibleIndex) => {
1585
- const isEditing = isCellEditing(slot.rowIndex, originalIndex, state.editingCell);
1586
- const active = isCellActive(slot.rowIndex, originalIndex, state.activeCell);
1587
- const selected = isCellSelected(slot.rowIndex, originalIndex, state.selectionRange);
1588
- return /* @__PURE__ */ jsx("div", {
1589
- className: [buildCellClasses(active, selected, isEditing, isCellInFillPreview(slot.rowIndex, originalIndex, dragState.dragType === "fill", dragState.fillSourceRange, dragState.fillTarget)), ...coreRef.current?.highlight?.computeCombinedCellClasses(slot.rowIndex, originalIndex, column, slot.rowData) ?? []].filter(Boolean).join(" "),
1590
- style: {
1591
- position: "absolute",
1592
- left: `${columnPositions[visibleIndex]}px`,
1593
- top: 0,
1594
- width: `${columnWidths[visibleIndex]}px`,
1595
- height: `${rowHeight}px`
1596
- },
1597
- onMouseDown: (e) => handleCellMouseDown(slot.rowIndex, originalIndex, e),
1598
- onDoubleClick: () => handleCellDoubleClick(slot.rowIndex, originalIndex),
1599
- onMouseEnter: () => handleCellMouseEnter(slot.rowIndex, originalIndex),
1600
- onMouseLeave: handleCellMouseLeave,
1601
- children: isEditing && state.editingCell ? renderEditCell({
1602
- column,
1603
- rowData: slot.rowData,
1604
- rowIndex: slot.rowIndex,
1605
- colIndex: originalIndex,
1606
- initialValue: state.editingCell.initialValue,
1607
- coreRef,
1608
- editRenderers,
1609
- globalEditRenderer: editRenderer
1610
- }) : renderCell({
1611
- column,
1612
- rowData: slot.rowData,
1613
- rowIndex: slot.rowIndex,
1614
- colIndex: originalIndex,
1615
- isActive: active,
1616
- isSelected: selected,
1617
- isEditing,
1618
- cellRenderers,
1619
- globalCellRenderer: cellRenderer
1620
- })
1621
- }, `${slot.slotId}-${originalIndex}`);
1622
- })
1623
- }, slot.slotId);
1624
- }),
1625
- fillHandlePosition && !state.editingCell && /* @__PURE__ */ jsx("div", {
1626
- className: "gp-grid-fill-handle",
1627
- style: {
1628
- position: "absolute",
1629
- top: fillHandlePosition.top,
1630
- left: fillHandlePosition.left,
1631
- zIndex: 200
1632
- },
1633
- onMouseDown: handleFillHandleMouseDown
1634
- }),
1635
- state.isLoading && /* @__PURE__ */ jsxs("div", {
1636
- className: "gp-grid-loading",
1637
- children: [/* @__PURE__ */ jsx("div", { className: "gp-grid-loading-spinner" }), "Loading..."]
1638
- }),
1639
- state.error && /* @__PURE__ */ jsxs("div", {
1640
- className: "gp-grid-error",
1641
- children: ["Error: ", state.error]
1642
- }),
1643
- !state.isLoading && !state.error && state.totalRows === 0 && /* @__PURE__ */ jsx("div", {
1644
- className: "gp-grid-empty",
1645
- children: "No data to display"
1646
- })
1647
- ]
1648
- }), state.filterPopup?.isOpen && state.filterPopup.column && state.filterPopup.anchorRect && /* @__PURE__ */ jsx(FilterPopup, {
1649
- column: state.filterPopup.column,
1650
- colIndex: state.filterPopup.colIndex,
1651
- anchorRect: state.filterPopup.anchorRect,
1652
- distinctValues: state.filterPopup.distinctValues,
1653
- currentFilter: state.filterPopup.currentFilter,
1654
- onApply: handleFilterApply,
1655
- onClose: handleFilterPopupClose
1656
- })]
1657
- });
1658
- }
1659
-
1660
- //#endregion
1661
- export { Grid, GridCore, createClientDataSource, createDataSourceFromArray, createMutableClientDataSource, createServerDataSource };
1662
- //# sourceMappingURL=index.js.map
1
+ import e,{useCallback as t,useEffect as n,useMemo as r,useReducer as i,useRef as a,useState as o}from"react";import{GridCore as s,GridCore as c,buildCellClasses as l,calculateScaledColumnPositions as u,createClientDataSource as d,createClientDataSource as f,createDataSourceFromArray as p,createDataSourceFromArray as m,createMutableClientDataSource as h,createMutableClientDataSource as g,createServerDataSource as _,getTotalWidth as v,injectStyles as y,isCellActive as b,isCellEditing as x,isCellInFillPreview as S,isCellSelected as C}from"@gp-grid/core";import{Fragment as w,jsx as T,jsxs as E}from"react/jsx-runtime";const D=[{value:`contains`,label:`Contains`},{value:`notContains`,label:`Does not contain`},{value:`equals`,label:`Equals`},{value:`notEquals`,label:`Does not equal`},{value:`startsWith`,label:`Starts with`},{value:`endsWith`,label:`Ends with`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Is not blank`}];function O({distinctValues:e,currentFilter:n,onApply:i,onClose:a}){let s=t(e=>Array.isArray(e)?e.join(`, `):String(e??``),[]),c=r(()=>{let t=e.filter(e=>e!=null&&e!==``&&!(Array.isArray(e)&&e.length===0)).map(e=>s(e));return Array.from(new Set(t)).sort((e,t)=>{let n=parseFloat(e),r=parseFloat(t);return!isNaN(n)&&!isNaN(r)?n-r:e.localeCompare(t,void 0,{numeric:!0,sensitivity:`base`})})},[e,s]),l=c.length>100,[u,d]=o(r(()=>{if(!n?.conditions[0])return l?`condition`:`values`;let e=n.conditions[0];return e.selectedValues&&e.selectedValues.size>0?`values`:`condition`},[n,l])),f=r(()=>n?.conditions[0]?n.conditions[0].selectedValues??new Set:new Set,[n]),p=r(()=>n?.conditions[0]?n.conditions[0].includeBlank??!0:!0,[n]),[m,h]=o(``),[g,_]=o(f),[v,y]=o(p),[b,x]=o(r(()=>{if(!n?.conditions.length)return[{operator:`contains`,value:``,nextOperator:`and`}];let e=n.conditions[0];if(e.selectedValues&&e.selectedValues.size>0)return[{operator:`contains`,value:``,nextOperator:`and`}];let t=n.combination??`and`;return n.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value??``,nextOperator:n.nextOperator??t}})},[n])),S=r(()=>{if(!m)return c;let e=m.toLowerCase();return c.filter(t=>t.toLowerCase().includes(e))},[c,m]),C=r(()=>e.some(e=>e==null||e===``),[e]),O=r(()=>S.every(e=>g.has(e))&&(!C||v),[S,g,C,v]),k=t(()=>{_(new Set(S)),C&&y(!0)},[S,C]),A=t(()=>{_(new Set),y(!1)},[]),j=t(e=>{_(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),M=t((e,t)=>{x(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),N=t(()=>{x(e=>[...e,{operator:`contains`,value:``,nextOperator:`and`}])},[]),ee=t(e=>{x(t=>t.filter((t,n)=>n!==e))},[]),P=t(()=>{if(u===`values`){if(c.every(e=>g.has(e))&&(!C||v)){i(null);return}i({conditions:[{type:`text`,operator:`equals`,selectedValues:g,includeBlank:v}],combination:`and`})}else{let e=b.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.value.trim()!==``);if(e.length===0){i(null);return}i({conditions:e.map(e=>({type:`text`,operator:e.operator,value:e.value,nextOperator:e.nextOperator})),combination:`and`})}},[u,c,g,v,C,b,i]),F=t(()=>{i(null)},[i]);return E(`div`,{className:`gp-grid-filter-content gp-grid-filter-text`,children:[!l&&E(`div`,{className:`gp-grid-filter-mode-toggle`,children:[T(`button`,{type:`button`,className:u===`values`?`active`:``,onClick:()=>d(`values`),children:`Values`}),T(`button`,{type:`button`,className:u===`condition`?`active`:``,onClick:()=>d(`condition`),children:`Condition`})]}),l&&u===`condition`&&E(`div`,{className:`gp-grid-filter-info`,children:[`Too many unique values (`,c.length,`). Use conditions to filter.`]}),u===`values`&&E(w,{children:[T(`input`,{className:`gp-grid-filter-search`,type:`text`,placeholder:`Search...`,value:m,onChange:e=>h(e.target.value),autoFocus:!0}),E(`div`,{className:`gp-grid-filter-actions`,children:[T(`button`,{type:`button`,onClick:k,disabled:O,children:`Select All`}),T(`button`,{type:`button`,onClick:A,children:`Deselect All`})]}),E(`div`,{className:`gp-grid-filter-list`,children:[C&&E(`label`,{className:`gp-grid-filter-option`,children:[T(`input`,{type:`checkbox`,checked:v,onChange:()=>y(!v)}),T(`span`,{className:`gp-grid-filter-blank`,children:`(Blanks)`})]}),S.map(e=>E(`label`,{className:`gp-grid-filter-option`,children:[T(`input`,{type:`checkbox`,checked:g.has(e),onChange:()=>j(e)}),T(`span`,{children:e})]},e))]})]}),u===`condition`&&E(w,{children:[b.map((e,t)=>E(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&E(`div`,{className:`gp-grid-filter-combination`,children:[T(`button`,{type:`button`,className:b[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>M(t-1,{nextOperator:`and`}),children:`AND`}),T(`button`,{type:`button`,className:b[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>M(t-1,{nextOperator:`or`}),children:`OR`})]}),E(`div`,{className:`gp-grid-filter-row`,children:[T(`select`,{value:e.operator,onChange:e=>M(t,{operator:e.target.value}),autoFocus:t===0,children:D.map(e=>T(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&T(`input`,{type:`text`,value:e.value,onChange:e=>M(t,{value:e.target.value}),placeholder:`Value`,className:`gp-grid-filter-text-input`}),b.length>1&&T(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>ee(t),children:`×`})]})]},t)),T(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:N,children:`+ Add condition`})]}),E(`div`,{className:`gp-grid-filter-buttons`,children:[T(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:F,children:`Clear`}),T(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:P,children:`Apply`})]})]})}const k=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`>=`,label:`≥`},{value:`<=`,label:`≤`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}];function A({currentFilter:e,onApply:n,onClose:i}){let[a,s]=o(r(()=>{if(!e?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let t=e.combination??`and`;return e.conditions.map(e=>{let n=e;return{operator:n.operator,value:n.value==null?``:String(n.value),valueTo:n.valueTo==null?``:String(n.valueTo),nextOperator:n.nextOperator??t}})},[e])),c=t((e,t)=>{s(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),l=t(()=>{s(e=>[...e,{operator:`=`,value:``,valueTo:``,nextOperator:`and`}])},[]),u=t(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),d=t(()=>{let e=a.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){n(null);return}n({conditions:e.map(e=>({type:`number`,operator:e.operator,value:e.value?parseFloat(e.value):void 0,valueTo:e.valueTo?parseFloat(e.valueTo):void 0,nextOperator:e.nextOperator})),combination:`and`})},[a,n]),f=t(()=>{n(null)},[n]);return E(`div`,{className:`gp-grid-filter-content gp-grid-filter-number`,children:[a.map((e,t)=>E(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&E(`div`,{className:`gp-grid-filter-combination`,children:[T(`button`,{type:`button`,className:a[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>c(t-1,{nextOperator:`and`}),children:`AND`}),T(`button`,{type:`button`,className:a[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>c(t-1,{nextOperator:`or`}),children:`OR`})]}),E(`div`,{className:`gp-grid-filter-row`,children:[T(`select`,{value:e.operator,onChange:e=>c(t,{operator:e.target.value}),children:k.map(e=>T(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&T(`input`,{type:`number`,value:e.value,onChange:e=>c(t,{value:e.target.value}),placeholder:`Value`}),e.operator===`between`&&E(w,{children:[T(`span`,{className:`gp-grid-filter-to`,children:`to`}),T(`input`,{type:`number`,value:e.valueTo,onChange:e=>c(t,{valueTo:e.target.value}),placeholder:`Value`})]}),a.length>1&&T(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>u(t),children:`×`})]})]},t)),T(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:l,children:`+ Add condition`}),E(`div`,{className:`gp-grid-filter-buttons`,children:[T(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:f,children:`Clear`}),T(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:d,children:`Apply`})]})]})}const j=[{value:`=`,label:`=`},{value:`!=`,label:`≠`},{value:`>`,label:`>`},{value:`<`,label:`<`},{value:`between`,label:`↔`},{value:`blank`,label:`Is blank`},{value:`notBlank`,label:`Not blank`}];function M(e){if(!e)return``;let t=typeof e==`string`?new Date(e):e;return isNaN(t.getTime())?``:t.toISOString().split(`T`)[0]}function N({currentFilter:e,onApply:n,onClose:i}){let[a,s]=o(r(()=>{if(!e?.conditions.length)return[{operator:`=`,value:``,valueTo:``,nextOperator:`and`}];let t=e.combination??`and`;return e.conditions.map(e=>{let n=e;return{operator:n.operator,value:M(n.value),valueTo:M(n.valueTo),nextOperator:n.nextOperator??t}})},[e])),c=t((e,t)=>{s(n=>{let r=[...n];return r[e]={...r[e],...t},r})},[]),l=t(()=>{s(e=>[...e,{operator:`=`,value:``,valueTo:``,nextOperator:`and`}])},[]),u=t(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),d=t(()=>{let e=a.filter(e=>e.operator===`blank`||e.operator===`notBlank`?!0:e.operator===`between`?e.value!==``&&e.valueTo!==``:e.value!==``);if(e.length===0){n(null);return}n({conditions:e.map(e=>({type:`date`,operator:e.operator,value:e.value||void 0,valueTo:e.valueTo||void 0,nextOperator:e.nextOperator})),combination:`and`})},[a,n]),f=t(()=>{n(null)},[n]);return E(`div`,{className:`gp-grid-filter-content gp-grid-filter-date`,children:[a.map((e,t)=>E(`div`,{className:`gp-grid-filter-condition`,children:[t>0&&E(`div`,{className:`gp-grid-filter-combination`,children:[T(`button`,{type:`button`,className:a[t-1]?.nextOperator===`and`?`active`:``,onClick:()=>c(t-1,{nextOperator:`and`}),children:`AND`}),T(`button`,{type:`button`,className:a[t-1]?.nextOperator===`or`?`active`:``,onClick:()=>c(t-1,{nextOperator:`or`}),children:`OR`})]}),E(`div`,{className:`gp-grid-filter-row`,children:[T(`select`,{value:e.operator,onChange:e=>c(t,{operator:e.target.value}),children:j.map(e=>T(`option`,{value:e.value,children:e.label},e.value))}),e.operator!==`blank`&&e.operator!==`notBlank`&&T(`input`,{type:`date`,value:e.value,onChange:e=>c(t,{value:e.target.value})}),e.operator===`between`&&E(w,{children:[T(`span`,{className:`gp-grid-filter-to`,children:`to`}),T(`input`,{type:`date`,value:e.valueTo,onChange:e=>c(t,{valueTo:e.target.value})})]}),a.length>1&&T(`button`,{type:`button`,className:`gp-grid-filter-remove`,onClick:()=>u(t),children:`×`})]})]},t)),T(`button`,{type:`button`,className:`gp-grid-filter-add`,onClick:l,children:`+ Add condition`}),E(`div`,{className:`gp-grid-filter-buttons`,children:[T(`button`,{type:`button`,className:`gp-grid-filter-btn-clear`,onClick:f,children:`Clear`}),T(`button`,{type:`button`,className:`gp-grid-filter-btn-apply`,onClick:d,children:`Apply`})]})]})}function ee({column:e,colIndex:r,anchorRect:i,distinctValues:o,currentFilter:s,onApply:c,onClose:l}){let u=a(null);n(()=>{let e=e=>{let t=e.target;t.closest(`.gp-grid-filter-icon`)||u.current&&!u.current.contains(t)&&l()},t=e=>{e.key===`Escape`&&l()};return requestAnimationFrame(()=>{document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t)}),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t)}},[l]);let d=t(t=>{c(e.colId??e.field,t),l()},[e,c,l]),f={position:`fixed`,top:i.top+i.height+4,left:i.left,minWidth:Math.max(200,i.width),zIndex:1e4},p=e.cellDataType,m=p===`text`||p===`object`,h=p===`number`,g=p===`date`||p===`dateString`||p===`dateTime`||p===`dateTimeString`;return E(`div`,{ref:u,className:`gp-grid-filter-popup`,style:f,children:[E(`div`,{className:`gp-grid-filter-header`,children:[`Filter: `,e.headerName??e.field]}),m&&T(O,{distinctValues:o,currentFilter:s,onApply:d,onClose:l}),h&&T(A,{currentFilter:s,onApply:d,onClose:l}),g&&T(N,{currentFilter:s,onApply:d,onClose:l}),!m&&!h&&!g&&T(O,{distinctValues:o,currentFilter:s,onApply:d,onClose:l})]})}function P(e){return{slots:new Map,activeCell:null,selectionRange:null,editingCell:null,contentWidth:0,contentHeight:e?.initialHeight??0,viewportWidth:e?.initialWidth??0,headers:new Map,filterPopup:null,isLoading:!1,error:null,totalRows:0,visibleRowRange:null,hoverPosition:null}}function F(e,t,n){switch(e.type){case`CREATE_SLOT`:return t.set(e.slotId,{slotId:e.slotId,rowIndex:-1,rowData:{},translateY:0}),null;case`DESTROY_SLOT`:return t.delete(e.slotId),null;case`ASSIGN_SLOT`:{let n=t.get(e.slotId);return n&&t.set(e.slotId,{...n,rowIndex:e.rowIndex,rowData:e.rowData}),null}case`MOVE_SLOT`:{let n=t.get(e.slotId);return n&&t.set(e.slotId,{...n,translateY:e.translateY}),null}case`SET_ACTIVE_CELL`:return{activeCell:e.position};case`SET_SELECTION_RANGE`:return{selectionRange:e.range};case`UPDATE_VISIBLE_RANGE`:return{visibleRowRange:{start:e.start,end:e.end}};case`SET_HOVER_POSITION`:return{hoverPosition:e.position};case`START_EDIT`:return{editingCell:{row:e.row,col:e.col,initialValue:e.initialValue}};case`STOP_EDIT`:return{editingCell:null};case`SET_CONTENT_SIZE`:return{contentWidth:e.width,contentHeight:e.height,viewportWidth:e.viewportWidth};case`UPDATE_HEADER`:return n.set(e.colIndex,{column:e.column,sortDirection:e.sortDirection,sortIndex:e.sortIndex,sortable:e.sortable,filterable:e.filterable,hasFilter:e.hasFilter}),null;case`OPEN_FILTER_POPUP`:return{filterPopup:{isOpen:!0,colIndex:e.colIndex,column:e.column,anchorRect:e.anchorRect,distinctValues:e.distinctValues,currentFilter:e.currentFilter}};case`CLOSE_FILTER_POPUP`:return{filterPopup:null};case`DATA_LOADING`:return{isLoading:!0,error:null};case`DATA_LOADED`:return{isLoading:!1,totalRows:e.totalRows};case`DATA_ERROR`:return{isLoading:!1,error:e.error};case`ROWS_ADDED`:case`ROWS_REMOVED`:return{totalRows:e.totalRows};case`ROWS_UPDATED`:case`TRANSACTION_PROCESSED`:return null;default:return null}}function te(e,t){if(t.type===`RESET`)return P();let{instructions:n}=t;if(n.length===0)return e;let r=new Map(e.slots),i=new Map(e.headers),a={};for(let e of n){let t=F(e,r,i);t&&(a={...a,...t})}return{...e,...a,slots:r,headers:i}}function ne(e,t){for(let n of e.values())if(n.rowIndex===t)return n;return null}function re(e,t,n,r,i,a){let o=ne(a,n),s=(o?o.translateY:i+n*r)-t.scrollTop,c=s+r,l=i,u=t.clientHeight;if(s<l)t.scrollTop=e.getScrollTopForRow(n);else if(c>u){let a=t.clientHeight-i,o=Math.floor(a/r),s=Math.max(0,n-o+1);t.scrollTop=e.getScrollTopForRow(s)}}function ie(e,r,i,s){let{activeCell:c,selectionRange:l,editingCell:u,filterPopupOpen:d,rowHeight:f,headerHeight:p,columnPositions:m,visibleColumnsWithIndices:h,slots:g}=s,_=a(null),[v,y]=o({isDragging:!1,dragType:null,fillSourceRange:null,fillTarget:null});n(()=>{let t=e.current;t?.input&&t.input.updateDeps({getHeaderHeight:()=>p,getRowHeight:()=>f,getColumnPositions:()=>m,getColumnCount:()=>h.length,getOriginalColumnIndex:e=>{let t=h[e];return t?t.originalIndex:e}})},[e,p,f,m,h]);let b=t((e,t)=>{_.current&&clearInterval(_.current),_.current=setInterval(()=>{let n=r.current;n&&(n.scrollTop+=t,n.scrollLeft+=e)},16)},[r]),x=t(()=>{_.current&&=(clearInterval(_.current),null)},[]),S=t(()=>{let e=r.current;if(!e)return null;let t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height,scrollTop:e.scrollTop,scrollLeft:e.scrollLeft}},[r]),C=e=>({clientX:e.clientX,clientY:e.clientY,button:e.button,shiftKey:e.shiftKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey}),w=t(()=>{let t=t=>{let n=e.current,r=S();if(!n?.input||!r)return;let i=n.input.handleDragMove(C(t),r);i&&(i.autoScroll?b(i.autoScroll.dx,i.autoScroll.dy):x(),y(n.input.getDragState()))},n=()=>{let r=e.current;r?.input&&(r.input.handleDragEnd(),y(r.input.getDragState())),x(),document.removeEventListener(`mousemove`,t),document.removeEventListener(`mouseup`,n)};document.addEventListener(`mousemove`,t),document.addEventListener(`mouseup`,n)},[e,S,b,x]),T=t((t,n,i)=>{let a=e.current;if(!a?.input)return;let o=a.input.handleCellMouseDown(t,n,C(i));o.focusContainer&&r.current?.focus(),o.startDrag===`selection`&&(a.input.startSelectionDrag(),y(a.input.getDragState()),w())},[e,r,w]),E=t((t,n)=>{let r=e.current;r?.input&&r.input.handleCellDoubleClick(t,n)},[e]),D=t(t=>{let n=e.current;if(!n?.input)return;let r=n.input.handleFillHandleMouseDown(c,l,C(t));r.preventDefault&&t.preventDefault(),r.stopPropagation&&t.stopPropagation(),r.startDrag===`fill`&&(y(n.input.getDragState()),w())},[e,c,l,w]),O=t((t,n)=>{let r=e.current;if(!r?.input)return;let a=i[t];if(!a)return;let o=a.colId??a.field;r.input.handleHeaderClick(o,n.shiftKey)},[e,i]),k=t(t=>{let n=e.current,i=r.current;if(!n?.input)return;let a=n.input.handleKeyDown({key:t.key,shiftKey:t.shiftKey,ctrlKey:t.ctrlKey,metaKey:t.metaKey},c,u,d);a.preventDefault&&t.preventDefault(),a.scrollToCell&&i&&re(n,i,a.scrollToCell.row,f,p,g)},[e,r,c,u,d,f,p,g]),A=t((t,n)=>{let i=e.current,a=r.current;if(!i?.input||!a)return;let o=i.input.handleWheel(t.deltaY,t.deltaX,n);o&&(t.preventDefault(),a.scrollTop+=o.dy,a.scrollLeft+=o.dx)},[e,r]);return n(()=>()=>{x()},[x]),{handleCellMouseDown:T,handleCellDoubleClick:E,handleFillHandleMouseDown:D,handleHeaderClick:O,handleKeyDown:k,handleWheel:A,dragState:v}}function I(e,t){let n=t.split(`.`),r=e;for(let e of n){if(typeof r!=`object`||!r)return null;r=r[e]}return r??null}function ae(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,isActive:a,isSelected:o,isEditing:s,cellRenderers:c,globalCellRenderer:l}=e,u=I(n,t.field),d={value:u,rowData:n,column:t,rowIndex:r,colIndex:i,isActive:a,isSelected:o,isEditing:s};if(t.cellRenderer&&typeof t.cellRenderer==`string`){let e=c[t.cellRenderer];if(e)return e(d)}return l?l(d):u==null?``:String(u)}function oe(e){let{column:t,rowData:n,rowIndex:r,colIndex:i,initialValue:a,coreRef:o,editRenderers:s,globalEditRenderer:c}=e,l=o.current;if(!l)return null;let u={value:I(n,t.field),rowData:n,column:t,rowIndex:r,colIndex:i,isActive:!0,isSelected:!0,isEditing:!0,initialValue:a,onValueChange:e=>l.updateEditValue(e),onCommit:()=>l.commitEdit(),onCancel:()=>l.cancelEdit()};if(t.editRenderer&&typeof t.editRenderer==`string`){let e=s[t.editRenderer];if(e)return e(u)}return c?c(u):T(`input`,{className:`gp-grid-edit-input`,type:`text`,defaultValue:a==null?``:String(a),autoFocus:!0,onFocus:e=>e.target.select(),onChange:e=>l.updateEditValue(e.target.value),onKeyDown:e=>{e.stopPropagation(),e.key===`Enter`?l.commitEdit():e.key===`Escape`?l.cancelEdit():e.key===`Tab`&&(e.preventDefault(),l.commitEdit(),l.selection.moveFocus(e.shiftKey?`left`:`right`,!1))},onBlur:()=>l.commitEdit()})}function se(e){let{column:t,colIndex:n,sortDirection:r,sortIndex:i,sortable:a,filterable:o,hasFilter:s,coreRef:c,containerRef:l,headerRenderers:u,globalHeaderRenderer:d}=e,f=c.current,p={column:t,colIndex:n,sortDirection:r,sortIndex:i,sortable:a,filterable:o,hasFilter:s,onSort:(e,n)=>{f&&a&&f.setSort(t.colId??t.field,e,n)},onFilterClick:()=>{if(f&&o){let e=l.current?.querySelector(`[data-col-index="${n}"]`);if(e){let t=e.getBoundingClientRect();f.openFilterPopup(n,{top:t.top,left:t.left,width:t.width,height:t.height})}}}};if(t.headerRenderer&&typeof t.headerRenderer==`string`){let e=u[t.headerRenderer];if(e)return e(p)}return d?d(p):E(w,{children:[T(`span`,{className:`gp-grid-header-text`,children:t.headerName??t.field}),E(`span`,{className:`gp-grid-header-icons`,children:[a&&E(`span`,{className:`gp-grid-sort-arrows`,children:[E(`span`,{className:`gp-grid-sort-arrows-stack`,children:[T(`svg`,{className:`gp-grid-sort-arrow-up${r===`asc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`,children:T(`path`,{d:`M4 0L8 6H0L4 0Z`,fill:`currentColor`})}),T(`svg`,{className:`gp-grid-sort-arrow-down${r===`desc`?` active`:``}`,width:`8`,height:`6`,viewBox:`0 0 8 6`,children:T(`path`,{d:`M4 6L0 0H8L4 6Z`,fill:`currentColor`})})]}),i!==void 0&&i>0&&T(`span`,{className:`gp-grid-sort-index`,children:i})]}),o&&T(`span`,{className:`gp-grid-filter-icon${s?` active`:``}`,onMouseDown:e=>{e.stopPropagation(),e.preventDefault(),p.onFilterClick()},onClick:e=>{e.stopPropagation()},children:T(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`currentColor`,children:T(`path`,{d:`M4 4h16l-6 8v5l-4 2v-7L4 4z`})})})]})]})}function L(o){y();let{columns:s,dataSource:d,rowData:p,rowHeight:h,headerHeight:g=h,overscan:_=3,sortingEnabled:D=!0,darkMode:O=!1,wheelDampening:k=.1,cellRenderers:A={},editRenderers:j={},headerRenderers:M={},cellRenderer:N,editRenderer:F,headerRenderer:ne,initialWidth:re,initialHeight:I,gridRef:L,highlighting:R,getRowId:ce,onCellValueChanged:le,loadingComponent:ue}=o,z=a(null),B=a(null),V=a(null),de=a(!1),[H,fe]=i(te,{initialWidth:re,initialHeight:I},P),U=g,W=a(null),G=W.current;(!G||G.providedDataSource!==d||G.rowData!==p)&&(G&&p&&p.length>1e4&&console.warn(`[gp-grid] rowData prop changed with ${p.length} rows — this triggers a full rebuild. Use useGridData() for efficient updates.`),G?.ownsDataSource&&G.dataSource.destroy?.(),d?W.current={dataSource:d,ownsDataSource:!1,providedDataSource:d,rowData:p}:p?W.current={dataSource:m(p),ownsDataSource:!0,providedDataSource:d,rowData:p}:W.current={dataSource:f([]),ownsDataSource:!0,providedDataSource:d,rowData:p});let{dataSource:K,ownsDataSource:pe}=W.current;n(()=>()=>{W.current?.ownsDataSource&&(W.current.dataSource.destroy?.(),W.current=null)},[]);let me=a(ce);me.current=ce;let q=a(le);q.current=le;let he=a(K);he.current=K;let J=r(()=>s.map((e,t)=>({column:e,originalIndex:t})).filter(({column:e})=>!e.hidden),[s]),{positions:Y,widths:X}=r(()=>u(J.map(e=>e.column),H.viewportWidth),[J,H.viewportWidth]),Z=v(Y),{handleCellMouseDown:ge,handleCellDoubleClick:_e,handleFillHandleMouseDown:ve,handleHeaderClick:ye,handleKeyDown:be,handleWheel:xe,dragState:Q}=ie(B,z,s,{activeCell:H.activeCell,selectionRange:H.selectionRange,editingCell:H.editingCell,filterPopupOpen:H.filterPopup?.isOpen??!1,rowHeight:h,headerHeight:U,columnPositions:Y,visibleColumnsWithIndices:J,slots:H.slots});n(()=>{de.current&&fe({type:`RESET`}),de.current=!0;let e=new c({columns:s,dataSource:he.current,rowHeight:h,headerHeight:U,overscan:_,sortingEnabled:D,highlighting:R,getRowId:me.current,onCellValueChanged:q.current?e=>q.current?.(e):void 0});B.current=e,e.input.updateDeps({getHeaderHeight:()=>U,getRowHeight:()=>h,getColumnPositions:()=>Y,getColumnCount:()=>J.length,getOriginalColumnIndex:e=>{let t=J[e];return t?t.originalIndex:e}}),L&&(L.current={core:e});let t=e.onBatchInstruction(e=>{fe({type:`BATCH_INSTRUCTIONS`,instructions:e})});e.initialize();let n=z.current;return n&&e.setViewport(n.scrollTop,n.scrollLeft,n.clientWidth,n.clientHeight),()=>{t(),e.destroy(),B.current=null,L&&(L.current=null)}},[s,h,U,_,D,L,R]),n(()=>{let e=B.current;if(!e)return;let t=V.current;if(!t||t===K){V.current=K;return}V.current=K,e.setDataSource(K)},[K]),n(()=>{let e=K;if(e.subscribe)return e.subscribe(()=>{B.current?.refreshFromTransaction()})},[K]);let $=t(()=>{let e=z.current,t=B.current;!e||!t||t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)},[]);n(()=>{let e=z.current,t=B.current;if(!e||!t)return;if(typeof ResizeObserver>`u`){$();return}let n=new ResizeObserver(()=>{t.setViewport(e.scrollTop,e.scrollLeft,e.clientWidth,e.clientHeight)});return n.observe(e),$(),()=>n.disconnect()},[$]),n(()=>{let e=z.current;if(!e)return;let t=e=>{xe(e,k)};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[xe,k]);let Se=t((e,t)=>{let n=B.current;n&&n.setFilter(e,t)},[]),Ce=t(()=>{let e=B.current;e&&e.closeFilterPopup()},[]),we=t((e,t)=>{B.current?.input.handleCellMouseEnter(e,t)},[]),Te=t(()=>{B.current?.input.handleCellMouseLeave()},[]),Ee=r(()=>Array.from(H.slots.values()),[H.slots]),De=r(()=>{let{activeCell:e,selectionRange:t,slots:n}=H;if(!e&&!t)return null;let r,i,a,o;if(t)r=Math.max(t.startRow,t.endRow),i=Math.max(t.startCol,t.endCol),a=Math.min(t.startCol,t.endCol),o=Math.max(t.startCol,t.endCol);else if(e)r=e.row,i=e.col,a=i,o=i;else return null;for(let e=a;e<=o;e++){let t=s[e];if(!(!t||t.hidden)&&t.editable!==!0)return null}let c=J.findIndex(e=>e.originalIndex===i);if(c===-1)return null;let l=null;for(let e of n.values())if(e.rowIndex===r){l=e.translateY;break}if(l===null)return null;let u=Y[c]??0,d=X[c]??0;return{top:l+h-5,left:u+d-20}},[H.activeCell,H.selectionRange,H.slots,h,Y,X,s,J]);return E(`div`,{ref:z,className:`gp-grid-container${O?` gp-grid-container--dark`:``}`,style:{width:`100%`,height:`100%`,overflow:`auto`,position:`relative`},onScroll:$,onKeyDown:be,tabIndex:0,children:[E(`div`,{style:{width:Math.max(H.contentWidth,Z),height:Math.max(H.contentHeight,U),position:`relative`,minWidth:`100%`},children:[T(`div`,{className:`gp-grid-header${H.isLoading?` gp-grid-header--loading`:``}`,style:{position:`sticky`,top:0,left:0,height:g,width:Math.max(H.contentWidth,Z),minWidth:`100%`},children:J.map(({column:e,originalIndex:t},n)=>{let r=H.headers.get(t);return T(`div`,{className:`gp-grid-header-cell`,"data-col-index":t,style:{position:`absolute`,left:`${Y[n]}px`,top:0,width:`${X[n]}px`,height:`${g}px`,background:`transparent`},onClick:e=>ye(t,e),children:se({column:e,colIndex:t,sortDirection:r?.sortDirection,sortIndex:r?.sortIndex,sortable:r?.sortable??!0,filterable:r?.filterable??!0,hasFilter:r?.hasFilter??!1,coreRef:B,containerRef:z,headerRenderers:M,globalHeaderRenderer:ne})},e.colId??e.field)})}),Ee.map(e=>e.rowIndex<0?null:T(`div`,{className:[`gp-grid-row`,...B.current?.highlight?.computeRowClasses(e.rowIndex,e.rowData)??[]].filter(Boolean).join(` `),style:{position:`absolute`,top:0,left:0,transform:`translateY(${e.translateY}px)`,width:`${Math.max(H.contentWidth,Z)}px`,height:`${h}px`},children:J.map(({column:t,originalIndex:n},r)=>{let i=x(e.rowIndex,n,H.editingCell),a=b(e.rowIndex,n,H.activeCell),o=C(e.rowIndex,n,H.selectionRange);return T(`div`,{className:[l(a,o,i,S(e.rowIndex,n,Q.dragType===`fill`,Q.fillSourceRange,Q.fillTarget)),...B.current?.highlight?.computeCombinedCellClasses(e.rowIndex,n,t,e.rowData)??[]].filter(Boolean).join(` `),style:{position:`absolute`,left:`${Y[r]}px`,top:0,width:`${X[r]}px`,height:`${h}px`},onMouseDown:t=>ge(e.rowIndex,n,t),onDoubleClick:()=>_e(e.rowIndex,n),onMouseEnter:()=>we(e.rowIndex,n),onMouseLeave:Te,children:i&&H.editingCell?oe({column:t,rowData:e.rowData,rowIndex:e.rowIndex,colIndex:n,initialValue:H.editingCell.initialValue,coreRef:B,editRenderers:j,globalEditRenderer:F}):ae({column:t,rowData:e.rowData,rowIndex:e.rowIndex,colIndex:n,isActive:a,isSelected:o,isEditing:i,cellRenderers:A,globalCellRenderer:N})},`${e.slotId}-${n}`)})},e.slotId)),De&&!H.editingCell&&T(`div`,{className:`gp-grid-fill-handle`,style:{position:`absolute`,top:De.top,left:De.left,zIndex:200},onMouseDown:ve}),H.isLoading&&E(w,{children:[T(`div`,{className:`gp-grid-loading-overlay`}),ue?e.createElement(ue,{isLoading:!0}):T(`div`,{className:`gp-grid-loading`,children:T(`div`,{className:`gp-grid-loading-spinner`})})]}),H.error&&E(`div`,{className:`gp-grid-error`,children:[`Error: `,H.error]}),!H.isLoading&&!H.error&&H.totalRows===0&&T(`div`,{className:`gp-grid-empty`,children:`No data to display`})]}),H.filterPopup?.isOpen&&H.filterPopup.column&&H.filterPopup.anchorRect&&T(ee,{column:H.filterPopup.column,colIndex:H.filterPopup.colIndex,anchorRect:H.filterPopup.anchorRect,distinctValues:H.filterPopup.distinctValues,currentFilter:H.filterPopup.currentFilter,onApply:Se,onClose:Ce})]})}const R=(e,t)=>{let n=r(()=>g(e,{getRowId:t.getRowId,debounceMs:t.debounceMs??0,useWorker:t.useWorker,parallelSort:t.parallelSort}),[]);return{dataSource:n,updateRow:n.updateRow,addRows:n.addRows,removeRows:n.removeRows,updateCell:n.updateCell,clear:n.clear,getRowById:n.getRowById,getTotalRowCount:n.getTotalRowCount,flushTransactions:n.flushTransactions}};export{L as Grid,s as GridCore,d as createClientDataSource,p as createDataSourceFromArray,h as createMutableClientDataSource,_ as createServerDataSource,R as useGridData};