@youp-grid/react 0.1.0 → 0.2.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/YoupGrid.js +361 -63
- package/dist/index.d.ts +1 -1
- package/dist/styles.css +121 -0
- package/dist/types.d.ts +33 -1
- package/package.json +2 -2
package/dist/YoupGrid.js
CHANGED
|
@@ -18,6 +18,7 @@ export function YoupGrid(props) {
|
|
|
18
18
|
const viewportHeight = normalizeHeight(props.height) ?? 420;
|
|
19
19
|
const loading = props.loading ?? controller.state.remoteRequest?.status === "loading";
|
|
20
20
|
const infiniteScrollLoading = props.infiniteScrollLoading ?? loading;
|
|
21
|
+
const headerRef = useRef(null);
|
|
21
22
|
const bodyRef = useRef(null);
|
|
22
23
|
const lastRowsEndReachedKeyRef = useRef();
|
|
23
24
|
const skipNextBlurCommitRef = useRef(false);
|
|
@@ -31,6 +32,7 @@ export function YoupGrid(props) {
|
|
|
31
32
|
const [columnChooserOpen, setColumnChooserOpen] = useState(false);
|
|
32
33
|
const [columnMenuOpenId, setColumnMenuOpenId] = useState();
|
|
33
34
|
const showRowSelectionColumn = props.showRowSelectionColumn ?? false;
|
|
35
|
+
const gridEditable = (props.editable ?? true) && !props.readOnly;
|
|
34
36
|
const displayRows = rowModel.displayRows;
|
|
35
37
|
const virtualRange = useMemo(() => {
|
|
36
38
|
return getVirtualRange({
|
|
@@ -108,6 +110,44 @@ export function YoupGrid(props) {
|
|
|
108
110
|
return row ? { row, displayIndex: item.index } : undefined;
|
|
109
111
|
})
|
|
110
112
|
.filter((item) => Boolean(item));
|
|
113
|
+
const getCellEditContext = (row, rowIndex, column) => {
|
|
114
|
+
return {
|
|
115
|
+
row: row.original,
|
|
116
|
+
rowNode: row,
|
|
117
|
+
rowId: row.id,
|
|
118
|
+
rowIndex,
|
|
119
|
+
column,
|
|
120
|
+
columnId: column.id,
|
|
121
|
+
value: column.accessor(row.original),
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
const canEditGridCell = (row, rowIndex, column) => {
|
|
125
|
+
if (!gridEditable || column.editable === false) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
return props.canEditCell?.(getCellEditContext(row, rowIndex, column)) ?? true;
|
|
129
|
+
};
|
|
130
|
+
const getGridCellMeta = (row, rowIndex, column) => {
|
|
131
|
+
return (props.getCellMeta?.(getCellEditContext(row, rowIndex, column)) ??
|
|
132
|
+
props.cellMeta?.[`${row.id}:${column.id}`]);
|
|
133
|
+
};
|
|
134
|
+
const createGridCellValueChange = (cell, value) => {
|
|
135
|
+
if (!cell.editable) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
if (Object.is(value, cell.value)) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
row: cell.row.original,
|
|
143
|
+
rowId: cell.row.id,
|
|
144
|
+
rowIndex: cell.rowIndex,
|
|
145
|
+
column: cell.column,
|
|
146
|
+
columnId: cell.column.id,
|
|
147
|
+
value,
|
|
148
|
+
previousValue: cell.value,
|
|
149
|
+
};
|
|
150
|
+
};
|
|
111
151
|
useEffect(() => {
|
|
112
152
|
if (focusedRowIndex >= rowModel.visibleRows.length) {
|
|
113
153
|
setFocusedRowIndex(Math.max(0, rowModel.visibleRows.length - 1));
|
|
@@ -159,7 +199,7 @@ export function YoupGrid(props) {
|
|
|
159
199
|
if (changes.length === 0) {
|
|
160
200
|
return;
|
|
161
201
|
}
|
|
162
|
-
if (source === "edit" || source === "paste" || source === "fill") {
|
|
202
|
+
if (source === "edit" || source === "paste" || source === "fill" || source === "delete") {
|
|
163
203
|
valueHistoryRef.current = pushValueHistoryEntry(valueHistoryRef.current, {
|
|
164
204
|
changes: changes.map((change) => ({
|
|
165
205
|
rowId: change.rowId,
|
|
@@ -170,18 +210,33 @@ export function YoupGrid(props) {
|
|
|
170
210
|
})),
|
|
171
211
|
}, { maxEntries: VALUE_HISTORY_LIMIT });
|
|
172
212
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
213
|
+
const emittedChanges = changes.map((change) => ({
|
|
214
|
+
...change,
|
|
215
|
+
source,
|
|
216
|
+
}));
|
|
217
|
+
for (const change of emittedChanges) {
|
|
218
|
+
props.onCellValueChange?.(change);
|
|
219
|
+
}
|
|
220
|
+
if (source === "paste" || source === "fill") {
|
|
221
|
+
props.onCellsValueChange?.({
|
|
222
|
+
changes: emittedChanges,
|
|
223
|
+
source: source,
|
|
177
224
|
});
|
|
178
225
|
}
|
|
179
226
|
};
|
|
227
|
+
const applyCellValue = (cell, value) => {
|
|
228
|
+
const change = createGridCellValueChange(cell, value);
|
|
229
|
+
if (!change) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
applyCellValueChanges([change], "edit");
|
|
233
|
+
};
|
|
180
234
|
const applyValueHistoryEntry = (entry, source) => {
|
|
181
235
|
applyCellValueChanges(getHistoryEntryValueChanges({
|
|
182
236
|
entry,
|
|
183
237
|
rowModel,
|
|
184
238
|
source,
|
|
239
|
+
canEditCell: canEditGridCell,
|
|
185
240
|
}), source);
|
|
186
241
|
};
|
|
187
242
|
const undoCellValueChange = () => {
|
|
@@ -202,19 +257,28 @@ export function YoupGrid(props) {
|
|
|
202
257
|
applyValueHistoryEntry(result.entry, "redo");
|
|
203
258
|
return true;
|
|
204
259
|
};
|
|
205
|
-
const commitEditingValue = (cell,
|
|
206
|
-
if (
|
|
260
|
+
const commitEditingValue = (cell, reason = "enter") => {
|
|
261
|
+
if (reason === "blur" && skipNextBlurCommitRef.current) {
|
|
207
262
|
skipNextBlurCommitRef.current = false;
|
|
208
263
|
return;
|
|
209
264
|
}
|
|
210
|
-
if (
|
|
265
|
+
if (reason !== "blur") {
|
|
211
266
|
skipNextBlurCommitRef.current = true;
|
|
212
267
|
}
|
|
213
|
-
commitEditingCell({
|
|
268
|
+
const change = commitEditingCell({
|
|
214
269
|
cell,
|
|
215
270
|
rowModel,
|
|
216
|
-
|
|
271
|
+
canEditCell: canEditGridCell,
|
|
217
272
|
});
|
|
273
|
+
if (change) {
|
|
274
|
+
if (!Object.is(change.value, change.previousValue)) {
|
|
275
|
+
applyCellValueChanges([change], "edit");
|
|
276
|
+
}
|
|
277
|
+
props.onCellEditCommit?.({
|
|
278
|
+
...change,
|
|
279
|
+
reason,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
218
282
|
setEditingCell(undefined);
|
|
219
283
|
};
|
|
220
284
|
const setFocusedCell = (cell, extendSelection = false, selectionAnchor) => {
|
|
@@ -245,7 +309,12 @@ export function YoupGrid(props) {
|
|
|
245
309
|
controller.setSelectedRows(currentSelectedRowIds.filter((rowId) => !visibleRowIdSet.has(rowId)));
|
|
246
310
|
};
|
|
247
311
|
return createElement("div", {
|
|
248
|
-
className: [
|
|
312
|
+
className: [
|
|
313
|
+
"youp-grid",
|
|
314
|
+
`youp-grid--density-${density}`,
|
|
315
|
+
!gridEditable ? "youp-grid--read-only" : "",
|
|
316
|
+
props.className,
|
|
317
|
+
].filter(Boolean).join(" "),
|
|
249
318
|
style: gridStyle,
|
|
250
319
|
}, renderColumnToolbar({
|
|
251
320
|
showColumnChooser: props.showColumnChooser ?? true,
|
|
@@ -268,12 +337,16 @@ export function YoupGrid(props) {
|
|
|
268
337
|
}),
|
|
269
338
|
});
|
|
270
339
|
},
|
|
340
|
+
}), renderDisabledReason({
|
|
341
|
+
enabled: !gridEditable,
|
|
342
|
+
reason: props.disabledReason,
|
|
271
343
|
}), createElement("div", {
|
|
272
344
|
className: "youp-grid__viewport",
|
|
273
345
|
role: "grid",
|
|
274
346
|
"aria-rowcount": displayRows.length,
|
|
275
347
|
"aria-colcount": rowModel.visibleColumns.length + (showRowSelectionColumn ? 1 : 0),
|
|
276
348
|
"aria-busy": loading || undefined,
|
|
349
|
+
"aria-readonly": !gridEditable || undefined,
|
|
277
350
|
onCopy: (event) => {
|
|
278
351
|
if (editingCell) {
|
|
279
352
|
return;
|
|
@@ -287,7 +360,7 @@ export function YoupGrid(props) {
|
|
|
287
360
|
});
|
|
288
361
|
},
|
|
289
362
|
onPaste: (event) => {
|
|
290
|
-
if (editingCell) {
|
|
363
|
+
if (editingCell || !gridEditable) {
|
|
291
364
|
return;
|
|
292
365
|
}
|
|
293
366
|
handleGridPaste({
|
|
@@ -296,10 +369,11 @@ export function YoupGrid(props) {
|
|
|
296
369
|
selectionRange,
|
|
297
370
|
rows: rowModel.visibleRows,
|
|
298
371
|
columns: visibleColumns,
|
|
372
|
+
canEditCell: canEditGridCell,
|
|
299
373
|
applyCellValueChanges,
|
|
300
374
|
});
|
|
301
375
|
},
|
|
302
|
-
}, createElement("div", { className: "youp-grid__header", role: "rowgroup" }, hasHeaderGroups
|
|
376
|
+
}, createElement("div", { className: "youp-grid__header", role: "rowgroup", ref: headerRef }, hasHeaderGroups
|
|
303
377
|
? createElement("div", { className: "youp-grid__row youp-grid__row--header-group", role: "row" }, showRowSelectionColumn
|
|
304
378
|
? renderSelectionHeaderGroupCell()
|
|
305
379
|
: undefined, headerGroupLayouts.map((layout) => renderHeaderGroupCell(layout)))
|
|
@@ -345,6 +419,9 @@ export function YoupGrid(props) {
|
|
|
345
419
|
ref: bodyRef,
|
|
346
420
|
style: { height: viewportHeight },
|
|
347
421
|
onScroll: (event) => {
|
|
422
|
+
if (headerRef.current) {
|
|
423
|
+
headerRef.current.style.setProperty("--youp-grid-header-scroll-left", `${event.currentTarget.scrollLeft}px`);
|
|
424
|
+
}
|
|
348
425
|
setScrollTop(event.currentTarget.scrollTop);
|
|
349
426
|
},
|
|
350
427
|
}, rowModel.visibleRows.length === 0 && !props.loading && !props.error
|
|
@@ -383,10 +460,16 @@ export function YoupGrid(props) {
|
|
|
383
460
|
selectionRange,
|
|
384
461
|
fillRange,
|
|
385
462
|
editingCell,
|
|
386
|
-
editable:
|
|
463
|
+
editable: gridEditable,
|
|
464
|
+
disabledReason: props.disabledReason,
|
|
465
|
+
canEditCell: canEditGridCell,
|
|
466
|
+
getCellMeta: getGridCellMeta,
|
|
387
467
|
setRowSelected: (selected) => controller.setRowSelected(row.id, selected),
|
|
388
468
|
setFocusedCell,
|
|
389
469
|
startFillHandle: (event) => {
|
|
470
|
+
if (!gridEditable) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
390
473
|
const sourceRange = normalizeCellRange(selectionRange ?? {
|
|
391
474
|
anchor: focusedCell,
|
|
392
475
|
focus: focusedCell,
|
|
@@ -403,6 +486,7 @@ export function YoupGrid(props) {
|
|
|
403
486
|
targetRange,
|
|
404
487
|
rows: rowModel.visibleRows,
|
|
405
488
|
columns: visibleColumns,
|
|
489
|
+
canEditCell: canEditGridCell,
|
|
406
490
|
applyCellValueChanges,
|
|
407
491
|
});
|
|
408
492
|
const nextSelectionRange = getFillSelectionRange(sourceRange, targetRange);
|
|
@@ -412,6 +496,7 @@ export function YoupGrid(props) {
|
|
|
412
496
|
},
|
|
413
497
|
});
|
|
414
498
|
},
|
|
499
|
+
applyCellValue,
|
|
415
500
|
startEditing: startEditingCell,
|
|
416
501
|
updateEditingDraft: (draftValue) => {
|
|
417
502
|
setEditingCell((current) => current ? { ...current, draftValue } : current);
|
|
@@ -434,6 +519,17 @@ export function YoupGrid(props) {
|
|
|
434
519
|
startEditing: startEditingCell,
|
|
435
520
|
commitEditing: commitEditingValue,
|
|
436
521
|
cancelEditing: cancelEditingCell,
|
|
522
|
+
applyCellValue,
|
|
523
|
+
deleteCellValues: () => {
|
|
524
|
+
deleteGridCellValues({
|
|
525
|
+
focusedCell,
|
|
526
|
+
selectionRange,
|
|
527
|
+
rows: rowModel.visibleRows,
|
|
528
|
+
columns: visibleColumns,
|
|
529
|
+
canEditCell: canEditGridCell,
|
|
530
|
+
applyCellValueChanges,
|
|
531
|
+
});
|
|
532
|
+
},
|
|
437
533
|
undoCellValueChange,
|
|
438
534
|
redoCellValueChange,
|
|
439
535
|
toggleSelected: () => controller.toggleRowSelected(row.id),
|
|
@@ -473,6 +569,12 @@ function renderGridOverlay(context) {
|
|
|
473
569
|
}
|
|
474
570
|
return undefined;
|
|
475
571
|
}
|
|
572
|
+
function renderDisabledReason(context) {
|
|
573
|
+
if (!context.enabled || context.reason == null) {
|
|
574
|
+
return undefined;
|
|
575
|
+
}
|
|
576
|
+
return createElement("div", { className: "youp-grid__disabled-reason", role: "status" }, context.reason);
|
|
577
|
+
}
|
|
476
578
|
function renderAggregationFooter(context) {
|
|
477
579
|
if (!context.enabled) {
|
|
478
580
|
return undefined;
|
|
@@ -761,7 +863,10 @@ function renderRow(context) {
|
|
|
761
863
|
const fillTargeted = context.fillRange
|
|
762
864
|
? isCellInNormalizedRange(context.rowIndex, columnIndex, context.fillRange)
|
|
763
865
|
: false;
|
|
866
|
+
const editable = context.canEditCell(context.row, context.rowIndex, layout.column);
|
|
867
|
+
const meta = context.getCellMeta(context.row, context.rowIndex, layout.column);
|
|
764
868
|
const showFillHandle = !context.editingCell &&
|
|
869
|
+
editable &&
|
|
765
870
|
context.rowIndex === activeRange.endRowIndex &&
|
|
766
871
|
columnIndex === activeRange.endColumnIndex;
|
|
767
872
|
return renderCell({
|
|
@@ -776,9 +881,12 @@ function renderRow(context) {
|
|
|
776
881
|
showFillHandle,
|
|
777
882
|
editing,
|
|
778
883
|
editingCell: context.editingCell,
|
|
779
|
-
editable
|
|
884
|
+
editable,
|
|
885
|
+
disabledReason: context.disabledReason,
|
|
886
|
+
meta,
|
|
780
887
|
setFocusedCell: context.setFocusedCell,
|
|
781
888
|
startFillHandle: context.startFillHandle,
|
|
889
|
+
applyCellValue: context.applyCellValue,
|
|
782
890
|
startEditing: context.startEditing,
|
|
783
891
|
updateEditingDraft: context.updateEditingDraft,
|
|
784
892
|
cancelEditing: context.cancelEditing,
|
|
@@ -826,13 +934,15 @@ function shouldIgnoreRowMouseEvent(event) {
|
|
|
826
934
|
function renderCell(context) {
|
|
827
935
|
const column = context.layout.column;
|
|
828
936
|
const value = column.accessor(context.row.original);
|
|
829
|
-
const editable = context.editable
|
|
937
|
+
const editable = context.editable;
|
|
830
938
|
const cellContext = {
|
|
831
939
|
row: context.row,
|
|
832
940
|
column,
|
|
833
941
|
value,
|
|
834
942
|
editing: context.editing,
|
|
835
943
|
focused: context.focused,
|
|
944
|
+
editable,
|
|
945
|
+
meta: context.meta,
|
|
836
946
|
};
|
|
837
947
|
const cellState = {
|
|
838
948
|
row: context.row,
|
|
@@ -841,10 +951,16 @@ function renderCell(context) {
|
|
|
841
951
|
columnIndex: context.columnIndex,
|
|
842
952
|
value,
|
|
843
953
|
editable,
|
|
954
|
+
meta: context.meta,
|
|
844
955
|
};
|
|
845
956
|
const cellContent = context.renderCell
|
|
846
957
|
? context.renderCell(cellContext)
|
|
847
|
-
:
|
|
958
|
+
: renderDefaultCellContent({
|
|
959
|
+
cell: cellState,
|
|
960
|
+
row: context.row.original,
|
|
961
|
+
disabledReason: context.disabledReason,
|
|
962
|
+
applyCellValue: context.applyCellValue,
|
|
963
|
+
});
|
|
848
964
|
return createElement("div", {
|
|
849
965
|
key: column.id,
|
|
850
966
|
className: getCellClassName([
|
|
@@ -853,10 +969,14 @@ function renderCell(context) {
|
|
|
853
969
|
context.selected ? "youp-grid__cell--range-selected" : "",
|
|
854
970
|
context.fillTargeted ? "youp-grid__cell--fill-target" : "",
|
|
855
971
|
context.editing ? "youp-grid__cell--editing" : "",
|
|
972
|
+
!editable ? "youp-grid__cell--disabled" : "",
|
|
973
|
+
context.meta ? `youp-grid__cell--status-${context.meta.status}` : "",
|
|
856
974
|
].filter(Boolean).join(" "), context.layout),
|
|
857
975
|
role: "gridcell",
|
|
858
976
|
tabIndex: context.focused && !context.editing ? 0 : -1,
|
|
977
|
+
title: getCellTitle(context.meta, context.disabledReason, editable),
|
|
859
978
|
"aria-colindex": context.columnIndex + context.ariaColumnOffset + 1,
|
|
979
|
+
"aria-readonly": !editable || undefined,
|
|
860
980
|
"data-youp-row-index": context.rowIndex,
|
|
861
981
|
"data-youp-column-index": context.columnIndex,
|
|
862
982
|
"data-youp-column-id": column.id,
|
|
@@ -867,34 +987,107 @@ function renderCell(context) {
|
|
|
867
987
|
},
|
|
868
988
|
onDoubleClick: () => {
|
|
869
989
|
if (editable) {
|
|
870
|
-
|
|
990
|
+
if (column.editor === "checkbox") {
|
|
991
|
+
context.applyCellValue(cellState, !Boolean(value));
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
context.startEditing(createEditingCell(cellState, value));
|
|
995
|
+
}
|
|
871
996
|
}
|
|
872
997
|
},
|
|
873
998
|
onKeyDown: (event) => context.onKeyDown(event, cellState),
|
|
874
999
|
}, context.editing
|
|
875
|
-
?
|
|
876
|
-
|
|
1000
|
+
? renderCellEditor({
|
|
1001
|
+
cell: cellState,
|
|
1002
|
+
editingCell: context.editingCell,
|
|
1003
|
+
updateEditingDraft: context.updateEditingDraft,
|
|
1004
|
+
commitEditing: context.commitEditing,
|
|
1005
|
+
onKeyDown: context.onKeyDown,
|
|
1006
|
+
})
|
|
1007
|
+
: cellContent, renderCellStatus(context.meta), !context.editing && context.showFillHandle
|
|
1008
|
+
? createElement("span", {
|
|
1009
|
+
className: "youp-grid__fill-handle",
|
|
1010
|
+
role: "button",
|
|
1011
|
+
"aria-label": "Fill selection",
|
|
1012
|
+
onMouseDown: context.startFillHandle,
|
|
1013
|
+
})
|
|
1014
|
+
: undefined);
|
|
1015
|
+
}
|
|
1016
|
+
function renderDefaultCellContent(context) {
|
|
1017
|
+
if (context.cell.column.editor === "checkbox") {
|
|
1018
|
+
return createElement("input", {
|
|
1019
|
+
className: "youp-grid__cell-checkbox",
|
|
1020
|
+
type: "checkbox",
|
|
1021
|
+
checked: Boolean(context.cell.value),
|
|
1022
|
+
disabled: !context.cell.editable,
|
|
1023
|
+
title: getCellTitle(context.cell.meta, context.disabledReason, context.cell.editable),
|
|
1024
|
+
"aria-label": context.cell.column.headerName,
|
|
1025
|
+
onChange: (event) => {
|
|
1026
|
+
context.applyCellValue(context.cell, event.currentTarget.checked);
|
|
1027
|
+
},
|
|
1028
|
+
onClick: (event) => {
|
|
1029
|
+
event.stopPropagation();
|
|
1030
|
+
},
|
|
1031
|
+
onKeyDown: (event) => {
|
|
1032
|
+
event.stopPropagation();
|
|
1033
|
+
},
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
const text = formatCellValue(context.cell.column, context.row, context.cell.value);
|
|
1037
|
+
const placeholder = context.cell.column.placeholder;
|
|
1038
|
+
const hasPlaceholder = text.length === 0 && Boolean(placeholder);
|
|
1039
|
+
return createElement("span", { className: hasPlaceholder ? "youp-grid__cell-placeholder" : undefined }, hasPlaceholder ? placeholder : text);
|
|
1040
|
+
}
|
|
1041
|
+
function renderCellEditor(context) {
|
|
1042
|
+
if (context.cell.column.editor === "select") {
|
|
1043
|
+
const options = normalizeEditorOptions(context.cell.column.options);
|
|
1044
|
+
return createElement("select", {
|
|
1045
|
+
className: "youp-grid__cell-editor youp-grid__cell-editor--select",
|
|
877
1046
|
value: context.editingCell?.draftValue ?? "",
|
|
878
1047
|
autoFocus: true,
|
|
1048
|
+
disabled: !context.cell.editable,
|
|
879
1049
|
onChange: (event) => {
|
|
880
1050
|
context.updateEditingDraft(event.currentTarget.value);
|
|
881
1051
|
},
|
|
882
1052
|
onBlur: (event) => {
|
|
883
|
-
context.commitEditing(createEditingCell(
|
|
1053
|
+
context.commitEditing(createEditingCell(context.cell, event.currentTarget.value), "blur");
|
|
884
1054
|
},
|
|
885
1055
|
onKeyDown: (event) => {
|
|
886
1056
|
event.stopPropagation();
|
|
887
|
-
context.onKeyDown(event,
|
|
1057
|
+
context.onKeyDown(event, context.cell);
|
|
888
1058
|
},
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
:
|
|
1059
|
+
}, context.cell.column.placeholder
|
|
1060
|
+
? createElement("option", { key: "__placeholder", value: "", disabled: true }, context.cell.column.placeholder)
|
|
1061
|
+
: undefined, options.map((option) => createElement("option", { key: option.inputValue, value: option.inputValue }, option.label)));
|
|
1062
|
+
}
|
|
1063
|
+
return createElement("input", {
|
|
1064
|
+
className: "youp-grid__cell-editor",
|
|
1065
|
+
type: context.cell.column.editor === "number" ? "number" : "text",
|
|
1066
|
+
value: context.editingCell?.draftValue ?? "",
|
|
1067
|
+
placeholder: context.cell.column.placeholder,
|
|
1068
|
+
autoFocus: true,
|
|
1069
|
+
disabled: !context.cell.editable,
|
|
1070
|
+
onChange: (event) => {
|
|
1071
|
+
context.updateEditingDraft(event.currentTarget.value);
|
|
1072
|
+
},
|
|
1073
|
+
onBlur: (event) => {
|
|
1074
|
+
context.commitEditing(createEditingCell(context.cell, event.currentTarget.value), "blur");
|
|
1075
|
+
},
|
|
1076
|
+
onKeyDown: (event) => {
|
|
1077
|
+
event.stopPropagation();
|
|
1078
|
+
context.onKeyDown(event, context.cell);
|
|
1079
|
+
},
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
function renderCellStatus(meta) {
|
|
1083
|
+
if (!meta) {
|
|
1084
|
+
return undefined;
|
|
1085
|
+
}
|
|
1086
|
+
return createElement("span", {
|
|
1087
|
+
className: `youp-grid__cell-status youp-grid__cell-status--${meta.status}`,
|
|
1088
|
+
title: typeof meta.message === "string" ? meta.message : undefined,
|
|
1089
|
+
"aria-hidden": true,
|
|
1090
|
+
});
|
|
898
1091
|
}
|
|
899
1092
|
function renderColumnToolbar(context) {
|
|
900
1093
|
if (!context.showColumnChooser && !context.showCsvExport && !context.showDensityControl) {
|
|
@@ -1161,11 +1354,11 @@ function handleCellKeyDown(context) {
|
|
|
1161
1354
|
}
|
|
1162
1355
|
if (context.event.key === "Enter") {
|
|
1163
1356
|
context.event.preventDefault();
|
|
1164
|
-
context.commitEditing(editingCell);
|
|
1357
|
+
context.commitEditing(editingCell, "enter");
|
|
1165
1358
|
moveFocusedCell({
|
|
1166
1359
|
...context,
|
|
1167
1360
|
nextCell: {
|
|
1168
|
-
rowIndex: clamp(context.cell.rowIndex + 1, 0, context.rowCount - 1),
|
|
1361
|
+
rowIndex: clamp(context.cell.rowIndex + (context.event.shiftKey ? -1 : 1), 0, context.rowCount - 1),
|
|
1169
1362
|
columnIndex: context.cell.columnIndex,
|
|
1170
1363
|
},
|
|
1171
1364
|
});
|
|
@@ -1173,7 +1366,7 @@ function handleCellKeyDown(context) {
|
|
|
1173
1366
|
}
|
|
1174
1367
|
if (context.event.key === "Tab") {
|
|
1175
1368
|
context.event.preventDefault();
|
|
1176
|
-
context.commitEditing(editingCell);
|
|
1369
|
+
context.commitEditing(editingCell, "tab");
|
|
1177
1370
|
moveFocusedCell({
|
|
1178
1371
|
...context,
|
|
1179
1372
|
nextCell: getNextTabCell(context.cell, context.rowCount, context.columnCount, context.event.shiftKey),
|
|
@@ -1184,23 +1377,41 @@ function handleCellKeyDown(context) {
|
|
|
1184
1377
|
}
|
|
1185
1378
|
if (isUndoShortcut(context.event)) {
|
|
1186
1379
|
context.event.preventDefault();
|
|
1187
|
-
context.
|
|
1380
|
+
if (context.cell.editable) {
|
|
1381
|
+
context.undoCellValueChange();
|
|
1382
|
+
}
|
|
1188
1383
|
return;
|
|
1189
1384
|
}
|
|
1190
1385
|
if (isRedoShortcut(context.event)) {
|
|
1191
1386
|
context.event.preventDefault();
|
|
1192
|
-
context.
|
|
1387
|
+
if (context.cell.editable) {
|
|
1388
|
+
context.redoCellValueChange();
|
|
1389
|
+
}
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
if (context.event.key === "Delete") {
|
|
1393
|
+
context.event.preventDefault();
|
|
1394
|
+
context.deleteCellValues();
|
|
1193
1395
|
return;
|
|
1194
1396
|
}
|
|
1195
1397
|
if (context.event.key === "Enter" || context.event.key === "F2") {
|
|
1196
1398
|
if (context.cell.editable) {
|
|
1197
1399
|
context.event.preventDefault();
|
|
1198
|
-
|
|
1400
|
+
if (context.cell.column.editor === "checkbox") {
|
|
1401
|
+
context.applyCellValue(context.cell, !Boolean(context.cell.value));
|
|
1402
|
+
}
|
|
1403
|
+
else {
|
|
1404
|
+
context.startEditing(createEditingCell(context.cell, context.cell.value));
|
|
1405
|
+
}
|
|
1199
1406
|
}
|
|
1200
1407
|
return;
|
|
1201
1408
|
}
|
|
1202
1409
|
if (context.event.key === " ") {
|
|
1203
1410
|
context.event.preventDefault();
|
|
1411
|
+
if (context.cell.column.editor === "checkbox" && context.cell.editable) {
|
|
1412
|
+
context.applyCellValue(context.cell, !Boolean(context.cell.value));
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1204
1415
|
if (context.event.shiftKey) {
|
|
1205
1416
|
context.setFocusedCell(context.cell, true);
|
|
1206
1417
|
}
|
|
@@ -1210,7 +1421,7 @@ function handleCellKeyDown(context) {
|
|
|
1210
1421
|
return;
|
|
1211
1422
|
}
|
|
1212
1423
|
if (isPrintableKey(context.event)) {
|
|
1213
|
-
if (context.cell.editable) {
|
|
1424
|
+
if (context.cell.editable && context.cell.column.editor !== "checkbox") {
|
|
1214
1425
|
context.event.preventDefault();
|
|
1215
1426
|
context.startEditing(createEditingCell(context.cell, context.event.key));
|
|
1216
1427
|
}
|
|
@@ -1372,27 +1583,20 @@ function isEditingCell(editingCell, row, column) {
|
|
|
1372
1583
|
function commitEditingCell(context) {
|
|
1373
1584
|
const row = context.rowModel.visibleRows[context.cell.rowIndex];
|
|
1374
1585
|
const column = context.rowModel.visibleColumns.find((item) => item.id === context.cell.columnId);
|
|
1375
|
-
if (!row || !column) {
|
|
1376
|
-
return;
|
|
1586
|
+
if (!row || !column || !context.canEditCell(row, context.cell.rowIndex, column)) {
|
|
1587
|
+
return undefined;
|
|
1377
1588
|
}
|
|
1378
1589
|
const previousValue = column.accessor(row.original);
|
|
1379
|
-
const value = column.
|
|
1380
|
-
|
|
1381
|
-
:
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
rowIndex: context.cell.rowIndex,
|
|
1390
|
-
column,
|
|
1391
|
-
columnId: column.id,
|
|
1392
|
-
value,
|
|
1393
|
-
previousValue,
|
|
1394
|
-
},
|
|
1395
|
-
], "edit");
|
|
1590
|
+
const value = parseDraftValue(column, row.original, context.cell.draftValue);
|
|
1591
|
+
return {
|
|
1592
|
+
row: row.original,
|
|
1593
|
+
rowId: row.id,
|
|
1594
|
+
rowIndex: context.cell.rowIndex,
|
|
1595
|
+
column,
|
|
1596
|
+
columnId: column.id,
|
|
1597
|
+
value,
|
|
1598
|
+
previousValue,
|
|
1599
|
+
};
|
|
1396
1600
|
}
|
|
1397
1601
|
function handleGridCopy(context) {
|
|
1398
1602
|
const range = context.selectionRange ?? {
|
|
@@ -1433,11 +1637,11 @@ function handleGridPaste(context) {
|
|
|
1433
1637
|
})) {
|
|
1434
1638
|
const row = context.rows[cell.rowIndex];
|
|
1435
1639
|
const column = context.columns[cell.columnIndex];
|
|
1436
|
-
if (!row || !column ||
|
|
1640
|
+
if (!row || !column || !context.canEditCell(row, cell.rowIndex, column)) {
|
|
1437
1641
|
continue;
|
|
1438
1642
|
}
|
|
1439
1643
|
const previousValue = column.accessor(row.original);
|
|
1440
|
-
const value = column
|
|
1644
|
+
const value = parseDraftValue(column, row.original, cell.value);
|
|
1441
1645
|
if (Object.is(value, previousValue)) {
|
|
1442
1646
|
continue;
|
|
1443
1647
|
}
|
|
@@ -1453,6 +1657,37 @@ function handleGridPaste(context) {
|
|
|
1453
1657
|
}
|
|
1454
1658
|
context.applyCellValueChanges(changes, "paste");
|
|
1455
1659
|
}
|
|
1660
|
+
function deleteGridCellValues(context) {
|
|
1661
|
+
const range = normalizeCellRange(context.selectionRange ?? {
|
|
1662
|
+
anchor: context.focusedCell,
|
|
1663
|
+
focus: context.focusedCell,
|
|
1664
|
+
});
|
|
1665
|
+
const changes = [];
|
|
1666
|
+
for (let rowIndex = range.startRowIndex; rowIndex <= range.endRowIndex; rowIndex += 1) {
|
|
1667
|
+
for (let columnIndex = range.startColumnIndex; columnIndex <= range.endColumnIndex; columnIndex += 1) {
|
|
1668
|
+
const row = context.rows[rowIndex];
|
|
1669
|
+
const column = context.columns[columnIndex];
|
|
1670
|
+
if (!row || !column || !context.canEditCell(row, rowIndex, column)) {
|
|
1671
|
+
continue;
|
|
1672
|
+
}
|
|
1673
|
+
const previousValue = column.accessor(row.original);
|
|
1674
|
+
const value = getEmptyCellValue(column, row.original);
|
|
1675
|
+
if (Object.is(value, previousValue)) {
|
|
1676
|
+
continue;
|
|
1677
|
+
}
|
|
1678
|
+
changes.push({
|
|
1679
|
+
row: row.original,
|
|
1680
|
+
rowId: row.id,
|
|
1681
|
+
rowIndex,
|
|
1682
|
+
column,
|
|
1683
|
+
columnId: column.id,
|
|
1684
|
+
value,
|
|
1685
|
+
previousValue,
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
context.applyCellValueChanges(changes, "delete");
|
|
1690
|
+
}
|
|
1456
1691
|
function startFillHandleDrag(context) {
|
|
1457
1692
|
context.event.preventDefault();
|
|
1458
1693
|
context.event.stopPropagation();
|
|
@@ -1499,7 +1734,7 @@ function applyFillHandleValues(context) {
|
|
|
1499
1734
|
})) {
|
|
1500
1735
|
const row = context.rows[cell.rowIndex];
|
|
1501
1736
|
const column = context.columns[cell.columnIndex];
|
|
1502
|
-
if (!row || !column ||
|
|
1737
|
+
if (!row || !column || !context.canEditCell(row, cell.rowIndex, column)) {
|
|
1503
1738
|
continue;
|
|
1504
1739
|
}
|
|
1505
1740
|
const previousValue = column.accessor(row.original);
|
|
@@ -1569,16 +1804,20 @@ function getHistoryEntryValueChanges(context) {
|
|
|
1569
1804
|
if (!row || !column) {
|
|
1570
1805
|
continue;
|
|
1571
1806
|
}
|
|
1807
|
+
const visibleRowIndex = context.rowModel.visibleRows.findIndex((item) => item.id === row.id);
|
|
1808
|
+
const rowIndex = visibleRowIndex >= 0 ? visibleRowIndex : row.index;
|
|
1809
|
+
if (!context.canEditCell(row, rowIndex, column)) {
|
|
1810
|
+
continue;
|
|
1811
|
+
}
|
|
1572
1812
|
const value = context.source === "undo" ? historyChange.previousValue : historyChange.value;
|
|
1573
1813
|
const previousValue = column.accessor(row.original);
|
|
1574
1814
|
if (Object.is(value, previousValue)) {
|
|
1575
1815
|
continue;
|
|
1576
1816
|
}
|
|
1577
|
-
const visibleRowIndex = context.rowModel.visibleRows.findIndex((item) => item.id === row.id);
|
|
1578
1817
|
changes.push({
|
|
1579
1818
|
row: row.original,
|
|
1580
1819
|
rowId: row.id,
|
|
1581
|
-
rowIndex
|
|
1820
|
+
rowIndex,
|
|
1582
1821
|
column,
|
|
1583
1822
|
columnId: column.id,
|
|
1584
1823
|
value,
|
|
@@ -1588,7 +1827,66 @@ function getHistoryEntryValueChanges(context) {
|
|
|
1588
1827
|
return changes;
|
|
1589
1828
|
}
|
|
1590
1829
|
function formatCellValue(column, row, value) {
|
|
1591
|
-
|
|
1830
|
+
if (column.valueFormatter) {
|
|
1831
|
+
return column.valueFormatter(value, row);
|
|
1832
|
+
}
|
|
1833
|
+
if (column.editor === "select") {
|
|
1834
|
+
const option = normalizeEditorOptions(column.options).find((item) => Object.is(item.value, value));
|
|
1835
|
+
if (option) {
|
|
1836
|
+
return option.label;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
return String(value ?? "");
|
|
1840
|
+
}
|
|
1841
|
+
function parseDraftValue(column, row, draftValue) {
|
|
1842
|
+
if (column.valueParser) {
|
|
1843
|
+
return column.valueParser(draftValue, row);
|
|
1844
|
+
}
|
|
1845
|
+
if (column.editor === "number") {
|
|
1846
|
+
return draftValue === "" ? undefined : Number(draftValue);
|
|
1847
|
+
}
|
|
1848
|
+
if (column.editor === "checkbox") {
|
|
1849
|
+
return draftValue === "true";
|
|
1850
|
+
}
|
|
1851
|
+
if (column.editor === "select") {
|
|
1852
|
+
const option = normalizeEditorOptions(column.options).find((item) => item.inputValue === draftValue);
|
|
1853
|
+
return option ? option.value : draftValue;
|
|
1854
|
+
}
|
|
1855
|
+
return draftValue;
|
|
1856
|
+
}
|
|
1857
|
+
function getEmptyCellValue(column, row) {
|
|
1858
|
+
if (column.valueParser) {
|
|
1859
|
+
return column.valueParser("", row);
|
|
1860
|
+
}
|
|
1861
|
+
if (column.editor === "checkbox") {
|
|
1862
|
+
return false;
|
|
1863
|
+
}
|
|
1864
|
+
if (column.editor === "number") {
|
|
1865
|
+
return undefined;
|
|
1866
|
+
}
|
|
1867
|
+
return "";
|
|
1868
|
+
}
|
|
1869
|
+
function normalizeEditorOptions(options) {
|
|
1870
|
+
return (options ?? []).map((option) => {
|
|
1871
|
+
const value = getEditorOptionValue(option);
|
|
1872
|
+
return {
|
|
1873
|
+
value,
|
|
1874
|
+
label: typeof option === "object" ? option.label : String(option),
|
|
1875
|
+
inputValue: String(value),
|
|
1876
|
+
};
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
function getEditorOptionValue(option) {
|
|
1880
|
+
return typeof option === "object" ? option.value : option;
|
|
1881
|
+
}
|
|
1882
|
+
function getCellTitle(meta, disabledReason, editable) {
|
|
1883
|
+
if (typeof meta?.message === "string") {
|
|
1884
|
+
return meta.message;
|
|
1885
|
+
}
|
|
1886
|
+
if (!editable && typeof disabledReason === "string") {
|
|
1887
|
+
return disabledReason;
|
|
1888
|
+
}
|
|
1889
|
+
return undefined;
|
|
1592
1890
|
}
|
|
1593
1891
|
function isPrintableKey(event) {
|
|
1594
1892
|
return event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { YoupGrid } from "./YoupGrid.ts";
|
|
2
2
|
export { useYoupGrid } from "./useYoupGrid.ts";
|
|
3
|
-
export type { YoupGridCellContext, YoupGridController, YoupGridDensity, YoupGridHeaderContext, YoupGridOptions, YoupGridProps, YoupGridRowEvent, YoupGridRowsEndReachedEvent, YoupGridStateChange, } from "./types.ts";
|
|
3
|
+
export type { YoupGridCanEditCellContext, YoupGridCellEditCommit, YoupGridCellEditCommitReason, YoupGridCellContext, YoupGridCellMeta, YoupGridCellMetaStatus, YoupGridCellsValueChange, YoupGridCellsValueChangeSource, YoupGridController, YoupGridDensity, YoupGridHeaderContext, YoupGridOptions, YoupGridProps, YoupGridRowEvent, YoupGridRowsEndReachedEvent, YoupGridStateChange, } from "./types.ts";
|
package/dist/styles.css
CHANGED
|
@@ -64,6 +64,15 @@
|
|
|
64
64
|
background: #fff;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
.youp-grid__disabled-reason {
|
|
68
|
+
padding: 8px 12px;
|
|
69
|
+
border-bottom: 1px solid var(--youp-grid-border);
|
|
70
|
+
color: var(--youp-grid-muted);
|
|
71
|
+
background: #f8fafc;
|
|
72
|
+
font-size: 12px;
|
|
73
|
+
font-weight: 700;
|
|
74
|
+
}
|
|
75
|
+
|
|
67
76
|
.youp-grid__density-control {
|
|
68
77
|
display: inline-flex;
|
|
69
78
|
align-items: center;
|
|
@@ -151,6 +160,15 @@
|
|
|
151
160
|
background: var(--youp-grid-row-hover);
|
|
152
161
|
}
|
|
153
162
|
|
|
163
|
+
.youp-grid__header {
|
|
164
|
+
--youp-grid-header-scroll-left: 0px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.youp-grid__header .youp-grid__cell--header:not(.youp-grid__cell--pinned-left):not(.youp-grid__cell--pinned-right):not(.youp-grid__selection-cell),
|
|
168
|
+
.youp-grid__header .youp-grid__cell--header-group:not(.youp-grid__cell--pinned-left):not(.youp-grid__cell--pinned-right):not(.youp-grid__selection-cell) {
|
|
169
|
+
transform: translateX(calc(-1 * var(--youp-grid-header-scroll-left)));
|
|
170
|
+
}
|
|
171
|
+
|
|
154
172
|
.youp-grid__row--header {
|
|
155
173
|
background: var(--youp-grid-header);
|
|
156
174
|
}
|
|
@@ -268,6 +286,10 @@
|
|
|
268
286
|
white-space: nowrap;
|
|
269
287
|
}
|
|
270
288
|
|
|
289
|
+
.youp-grid--read-only .youp-grid__cell {
|
|
290
|
+
cursor: default;
|
|
291
|
+
}
|
|
292
|
+
|
|
271
293
|
.youp-grid__cell:focus {
|
|
272
294
|
outline: none;
|
|
273
295
|
}
|
|
@@ -289,6 +311,70 @@
|
|
|
289
311
|
box-shadow: inset 0 0 0 1px #0ea5e9;
|
|
290
312
|
}
|
|
291
313
|
|
|
314
|
+
.youp-grid__cell--disabled {
|
|
315
|
+
color: var(--youp-grid-muted);
|
|
316
|
+
background: #f8fafc;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.youp-grid__cell--status-loading {
|
|
320
|
+
background: #eff6ff;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.youp-grid__cell--status-error {
|
|
324
|
+
background: #fef2f2;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.youp-grid__cell--status-warning {
|
|
328
|
+
background: #fffbeb;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.youp-grid__cell--status-success {
|
|
332
|
+
background: #f0fdf4;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.youp-grid__cell-placeholder {
|
|
336
|
+
color: #94a3b8;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.youp-grid__cell-checkbox {
|
|
340
|
+
width: 16px;
|
|
341
|
+
height: 16px;
|
|
342
|
+
margin: 0;
|
|
343
|
+
accent-color: #2563eb;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.youp-grid__cell-checkbox:disabled {
|
|
347
|
+
cursor: not-allowed;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.youp-grid__cell-status {
|
|
351
|
+
position: absolute;
|
|
352
|
+
top: 6px;
|
|
353
|
+
right: 6px;
|
|
354
|
+
z-index: 3;
|
|
355
|
+
width: 7px;
|
|
356
|
+
height: 7px;
|
|
357
|
+
border: 1px solid #fff;
|
|
358
|
+
border-radius: 999px;
|
|
359
|
+
pointer-events: none;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.youp-grid__cell-status--loading {
|
|
363
|
+
background: #2563eb;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.youp-grid__cell-status--error {
|
|
367
|
+
background: #dc2626;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.youp-grid__cell-status--warning {
|
|
371
|
+
background: #d97706;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.youp-grid__cell-status--success {
|
|
375
|
+
background: #16a34a;
|
|
376
|
+
}
|
|
377
|
+
|
|
292
378
|
.youp-grid__cell--focused.youp-grid__cell--fill-target {
|
|
293
379
|
background: #bae6fd;
|
|
294
380
|
}
|
|
@@ -322,6 +408,16 @@
|
|
|
322
408
|
outline: none;
|
|
323
409
|
}
|
|
324
410
|
|
|
411
|
+
.youp-grid__cell-editor--select {
|
|
412
|
+
padding-right: 24px;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.youp-grid__cell-editor:disabled {
|
|
416
|
+
color: var(--youp-grid-muted);
|
|
417
|
+
cursor: not-allowed;
|
|
418
|
+
background: #f1f5f9;
|
|
419
|
+
}
|
|
420
|
+
|
|
325
421
|
.youp-grid__cell--pinned-left,
|
|
326
422
|
.youp-grid__cell--pinned-right {
|
|
327
423
|
position: sticky;
|
|
@@ -363,6 +459,31 @@
|
|
|
363
459
|
background: #e0f2fe;
|
|
364
460
|
}
|
|
365
461
|
|
|
462
|
+
.youp-grid__cell--pinned-left.youp-grid__cell--disabled,
|
|
463
|
+
.youp-grid__cell--pinned-right.youp-grid__cell--disabled {
|
|
464
|
+
background: #f8fafc;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.youp-grid__cell--pinned-left.youp-grid__cell--status-loading,
|
|
468
|
+
.youp-grid__cell--pinned-right.youp-grid__cell--status-loading {
|
|
469
|
+
background: #eff6ff;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.youp-grid__cell--pinned-left.youp-grid__cell--status-error,
|
|
473
|
+
.youp-grid__cell--pinned-right.youp-grid__cell--status-error {
|
|
474
|
+
background: #fef2f2;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.youp-grid__cell--pinned-left.youp-grid__cell--status-warning,
|
|
478
|
+
.youp-grid__cell--pinned-right.youp-grid__cell--status-warning {
|
|
479
|
+
background: #fffbeb;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.youp-grid__cell--pinned-left.youp-grid__cell--status-success,
|
|
483
|
+
.youp-grid__cell--pinned-right.youp-grid__cell--status-success {
|
|
484
|
+
background: #f0fdf4;
|
|
485
|
+
}
|
|
486
|
+
|
|
366
487
|
.youp-grid__cell--focused.youp-grid__cell--left-last {
|
|
367
488
|
box-shadow:
|
|
368
489
|
inset 0 0 0 2px #2563eb,
|
package/dist/types.d.ts
CHANGED
|
@@ -14,7 +14,30 @@ export type YoupGridCellValueChange<TRow> = {
|
|
|
14
14
|
previousValue: unknown;
|
|
15
15
|
source: YoupGridCellValueChangeSource;
|
|
16
16
|
};
|
|
17
|
-
export type YoupGridCellValueChangeSource = "edit" | "paste" | "fill" | "undo" | "redo";
|
|
17
|
+
export type YoupGridCellValueChangeSource = "edit" | "paste" | "fill" | "delete" | "undo" | "redo";
|
|
18
|
+
export type YoupGridCellEditCommitReason = "enter" | "tab" | "blur";
|
|
19
|
+
export type YoupGridCellEditCommit<TRow> = Omit<YoupGridCellValueChange<TRow>, "source"> & {
|
|
20
|
+
reason: YoupGridCellEditCommitReason;
|
|
21
|
+
};
|
|
22
|
+
export type YoupGridCellsValueChangeSource = "paste" | "fill";
|
|
23
|
+
export type YoupGridCellsValueChange<TRow> = {
|
|
24
|
+
changes: YoupGridCellValueChange<TRow>[];
|
|
25
|
+
source: YoupGridCellsValueChangeSource;
|
|
26
|
+
};
|
|
27
|
+
export type YoupGridCellMetaStatus = "loading" | "error" | "warning" | "success";
|
|
28
|
+
export type YoupGridCellMeta = {
|
|
29
|
+
status: YoupGridCellMetaStatus;
|
|
30
|
+
message?: ReactNode;
|
|
31
|
+
};
|
|
32
|
+
export type YoupGridCanEditCellContext<TRow> = {
|
|
33
|
+
row: TRow;
|
|
34
|
+
rowNode: RowNode<TRow>;
|
|
35
|
+
rowId: GridRowId;
|
|
36
|
+
rowIndex: number;
|
|
37
|
+
column: ResolvedColumnDef<TRow>;
|
|
38
|
+
columnId: string;
|
|
39
|
+
value: unknown;
|
|
40
|
+
};
|
|
18
41
|
export type YoupGridDensity = "compact" | "standard" | "comfortable";
|
|
19
42
|
export type YoupGridRowEvent<TRow> = {
|
|
20
43
|
row: TRow;
|
|
@@ -84,6 +107,9 @@ export type YoupGridProps<TRow> = YoupGridOptions<TRow> & {
|
|
|
84
107
|
style?: CSSProperties;
|
|
85
108
|
height?: number | string;
|
|
86
109
|
editable?: boolean;
|
|
110
|
+
readOnly?: boolean;
|
|
111
|
+
canEditCell?: (context: YoupGridCanEditCellContext<TRow>) => boolean;
|
|
112
|
+
disabledReason?: ReactNode;
|
|
87
113
|
showColumnChooser?: boolean;
|
|
88
114
|
showColumnMenu?: boolean;
|
|
89
115
|
showCsvExport?: boolean;
|
|
@@ -100,9 +126,13 @@ export type YoupGridProps<TRow> = YoupGridOptions<TRow> & {
|
|
|
100
126
|
loadingContent?: ReactNode;
|
|
101
127
|
error?: boolean;
|
|
102
128
|
errorContent?: ReactNode;
|
|
129
|
+
cellMeta?: Record<string, YoupGridCellMeta | undefined>;
|
|
130
|
+
getCellMeta?: (context: YoupGridCanEditCellContext<TRow>) => YoupGridCellMeta | undefined;
|
|
103
131
|
renderCell?: (context: YoupGridCellContext<TRow>) => ReactNode;
|
|
104
132
|
renderHeader?: (context: YoupGridHeaderContext<TRow>) => ReactNode;
|
|
105
133
|
onCellValueChange?: (change: YoupGridCellValueChange<TRow>) => void;
|
|
134
|
+
onCellEditCommit?: (commit: YoupGridCellEditCommit<TRow>) => void;
|
|
135
|
+
onCellsValueChange?: (change: YoupGridCellsValueChange<TRow>) => void;
|
|
106
136
|
onRowClick?: (event: YoupGridRowEvent<TRow>) => void;
|
|
107
137
|
onRowDoubleClick?: (event: YoupGridRowEvent<TRow>) => void;
|
|
108
138
|
onRowsEndReached?: (event: YoupGridRowsEndReachedEvent<TRow>) => void;
|
|
@@ -114,6 +144,8 @@ export type YoupGridCellContext<TRow> = {
|
|
|
114
144
|
value: unknown;
|
|
115
145
|
editing: boolean;
|
|
116
146
|
focused: boolean;
|
|
147
|
+
editable: boolean;
|
|
148
|
+
meta?: YoupGridCellMeta;
|
|
117
149
|
};
|
|
118
150
|
export type YoupGridHeaderContext<TRow> = {
|
|
119
151
|
column: ResolvedColumnDef<TRow>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youp-grid/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "React adapter for Youp Grid.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"build": "tsc -p tsconfig.build.json && cp src/styles.css dist/styles.css"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@youp-grid/core": "0.
|
|
31
|
+
"@youp-grid/core": "0.2.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": ">=18.2.0"
|