@pixerate/editor-react 0.13.0 → 0.14.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/README.md +3 -3
- package/dist/canvas/index.cjs +180 -68
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +36 -6
- package/dist/canvas/index.d.ts +36 -6
- package/dist/canvas/index.js +113 -1
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-MHTAR3RS.js → chunk-25S5EHH4.js} +84 -27
- package/dist/chunk-25S5EHH4.js.map +1 -0
- package/dist/image-editor/index.d.cts +3 -3
- package/dist/image-editor/index.d.ts +3 -3
- package/dist/index.cjs +94 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -17
- package/dist/index.d.ts +26 -17
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/dist/spreadsheet/index.cjs +78 -21
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +8 -9
- package/dist/spreadsheet/index.d.ts +8 -9
- package/dist/spreadsheet/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-MHTAR3RS.js.map +0 -1
|
@@ -68,8 +68,12 @@ function useSpreadsheetEditor(options = {}) {
|
|
|
68
68
|
const [activeCell, setActiveCell] = (0, import_react.useState)(controller.activeCell);
|
|
69
69
|
const [selectedRange, setSelectedRange] = (0, import_react.useState)(controller.selectedRange);
|
|
70
70
|
const [editingCell, setEditingCell] = (0, import_react.useState)(null);
|
|
71
|
-
const [draftValue,
|
|
71
|
+
const [draftValue, setDraftState] = (0, import_react.useState)("");
|
|
72
72
|
settersRef.current = { setDoc, setActiveCell, setSelectedRange };
|
|
73
|
+
const setDraftValue = (0, import_react.useCallback)((value) => {
|
|
74
|
+
controller.draftValue = value;
|
|
75
|
+
setDraftState(value);
|
|
76
|
+
}, [controller]);
|
|
73
77
|
const setCellValue = (0, import_react.useCallback)((rowId, colId, raw) => {
|
|
74
78
|
controller.setCellValue(rowId, colId, raw);
|
|
75
79
|
setDoc({ ...controller.document });
|
|
@@ -203,15 +207,30 @@ function useSpreadsheetEditor(options = {}) {
|
|
|
203
207
|
|
|
204
208
|
// src/spreadsheet/SpreadsheetEditor.tsx
|
|
205
209
|
var import_react5 = require("react");
|
|
206
|
-
var
|
|
210
|
+
var import_spreadsheet5 = require("@pixerate/editor/spreadsheet");
|
|
207
211
|
|
|
208
212
|
// src/spreadsheet/SpreadsheetContextMenu.tsx
|
|
209
213
|
var import_react2 = __toESM(require("react"), 1);
|
|
214
|
+
var import_spreadsheet2 = require("@pixerate/editor/spreadsheet");
|
|
210
215
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
216
|
+
var VIEWPORT_MARGIN = 4;
|
|
211
217
|
var SpreadsheetContextMenu = ({ items, x, y, onClose }) => {
|
|
212
218
|
const menuRef = (0, import_react2.useRef)(null);
|
|
213
219
|
const onCloseRef = (0, import_react2.useRef)(onClose);
|
|
214
220
|
onCloseRef.current = onClose;
|
|
221
|
+
const [position, setPosition] = (0, import_react2.useState)({ x, y });
|
|
222
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
223
|
+
const menu = menuRef.current;
|
|
224
|
+
if (!menu || typeof window === "undefined") return;
|
|
225
|
+
const { width, height } = menu.getBoundingClientRect();
|
|
226
|
+
const next = (0, import_spreadsheet2.clampMenuPosition)(
|
|
227
|
+
{ x, y },
|
|
228
|
+
{ width, height },
|
|
229
|
+
{ width: window.innerWidth, height: window.innerHeight },
|
|
230
|
+
VIEWPORT_MARGIN
|
|
231
|
+
);
|
|
232
|
+
setPosition((prev) => prev.x === next.x && prev.y === next.y ? prev : next);
|
|
233
|
+
}, [x, y, items]);
|
|
215
234
|
(0, import_react2.useEffect)(() => {
|
|
216
235
|
const handlePointer = (e) => {
|
|
217
236
|
if (!menuRef.current?.contains(e.target)) onCloseRef.current();
|
|
@@ -233,7 +252,13 @@ var SpreadsheetContextMenu = ({ items, x, y, onClose }) => {
|
|
|
233
252
|
role: "menu",
|
|
234
253
|
"aria-label": "Table actions",
|
|
235
254
|
className: "fixed z-50 min-w-[14rem] rounded-md border border-border bg-popover py-1 text-xs text-popover-foreground shadow-lg",
|
|
236
|
-
style: {
|
|
255
|
+
style: {
|
|
256
|
+
left: position.x,
|
|
257
|
+
top: position.y,
|
|
258
|
+
maxHeight: `calc(100vh - ${VIEWPORT_MARGIN * 2}px)`,
|
|
259
|
+
overflowY: "auto",
|
|
260
|
+
background: "var(--popover, var(--background, #fff))"
|
|
261
|
+
},
|
|
237
262
|
onContextMenu: (e) => e.preventDefault(),
|
|
238
263
|
onKeyDown: (e) => e.stopPropagation(),
|
|
239
264
|
children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react2.default.Fragment, { children: [
|
|
@@ -270,7 +295,7 @@ var SpreadsheetGroupRow = ({
|
|
|
270
295
|
}) => {
|
|
271
296
|
const labelColId = columns.some((c) => c.column.id === groupColId) ? groupColId : columns[0]?.column.id;
|
|
272
297
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("tr", { className: "border-b border-border bg-muted/40 font-semibold", "data-group-key": group.key, style: { height: 28 }, children: [
|
|
273
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "w-12 min-w-[3rem] sticky left-0 z-10 bg-muted
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "w-12 min-w-[3rem] sticky left-0 z-10 bg-muted border-r border-border text-center", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
274
299
|
"button",
|
|
275
300
|
{
|
|
276
301
|
type: "button",
|
|
@@ -302,7 +327,7 @@ var SpreadsheetGroupRow = ({
|
|
|
302
327
|
|
|
303
328
|
// src/spreadsheet/useSpreadsheetTableInteractions.ts
|
|
304
329
|
var import_react3 = require("react");
|
|
305
|
-
var
|
|
330
|
+
var import_spreadsheet3 = require("@pixerate/editor/spreadsheet");
|
|
306
331
|
function gridHasFocus(grid) {
|
|
307
332
|
if (!grid || typeof document === "undefined") return false;
|
|
308
333
|
const active = document.activeElement;
|
|
@@ -343,7 +368,8 @@ function useSpreadsheetClipboard(gridRef, state, readOnly) {
|
|
|
343
368
|
setTimeout(() => {
|
|
344
369
|
if (copiedRef.current) return;
|
|
345
370
|
const s = stateRef.current;
|
|
346
|
-
navigator.clipboard?.writeText(s.exportToTsv(s.selectedRange))
|
|
371
|
+
Promise.resolve(navigator.clipboard?.writeText(s.exportToTsv(s.selectedRange))).catch(() => {
|
|
372
|
+
});
|
|
347
373
|
}, 0);
|
|
348
374
|
}, []);
|
|
349
375
|
return { copyShortcutFallback };
|
|
@@ -369,19 +395,19 @@ function useFillHandle(state) {
|
|
|
369
395
|
e.preventDefault();
|
|
370
396
|
e.stopPropagation();
|
|
371
397
|
const range = stateRef.current.selectedRange;
|
|
372
|
-
if (range) setDrag({ source: (0,
|
|
398
|
+
if (range) setDrag({ source: (0, import_spreadsheet3.normalizeRange)(range), target: null });
|
|
373
399
|
}, []);
|
|
374
400
|
const extendFill = (0, import_react3.useCallback)((row, col) => {
|
|
375
401
|
const current = dragRef.current;
|
|
376
402
|
if (!current) return;
|
|
377
|
-
setDrag({ source: current.source, target: (0,
|
|
403
|
+
setDrag({ source: current.source, target: (0, import_spreadsheet3.computeFillTarget)(current.source, { row, col }) });
|
|
378
404
|
}, []);
|
|
379
405
|
return { fillTarget: drag?.target ?? null, isFilling: dragging, startFill, extendFill };
|
|
380
406
|
}
|
|
381
407
|
|
|
382
408
|
// src/spreadsheet/FormulaHints.tsx
|
|
383
409
|
var import_react4 = require("react");
|
|
384
|
-
var
|
|
410
|
+
var import_spreadsheet4 = require("@pixerate/editor/spreadsheet");
|
|
385
411
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
386
412
|
var FormulaHints = ({ inputRef, value, onAccept, limit = 8 }) => {
|
|
387
413
|
const [caret, setCaret] = (0, import_react4.useState)(null);
|
|
@@ -391,7 +417,7 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8 }) => {
|
|
|
391
417
|
const [position, setPosition] = (0, import_react4.useState)(null);
|
|
392
418
|
const pendingCaret = (0, import_react4.useRef)(null);
|
|
393
419
|
const hints = (0, import_react4.useMemo)(
|
|
394
|
-
() => (0,
|
|
420
|
+
() => (0, import_spreadsheet4.getFormulaHints)(value, caret ?? value.length, { limit }),
|
|
395
421
|
[value, caret, limit]
|
|
396
422
|
);
|
|
397
423
|
const suggestions = dismissed ? [] : hints.suggestions;
|
|
@@ -403,7 +429,7 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8 }) => {
|
|
|
403
429
|
const { suggestions: list, value: current, caret: at, onAccept: commit } = latest.current;
|
|
404
430
|
const suggestion = list[index];
|
|
405
431
|
if (!suggestion) return;
|
|
406
|
-
const next = (0,
|
|
432
|
+
const next = (0, import_spreadsheet4.applyFormulaSuggestion)(current, at ?? current.length, suggestion.name);
|
|
407
433
|
pendingCaret.current = next.caret;
|
|
408
434
|
commit(next.value);
|
|
409
435
|
};
|
|
@@ -543,6 +569,20 @@ function frozenCellStyle(viewRow, viewCol) {
|
|
|
543
569
|
background: "var(--background, #fff)"
|
|
544
570
|
};
|
|
545
571
|
}
|
|
572
|
+
var coordKey = (cell) => cell ? `${(0, import_spreadsheet5.indexToColName)(cell.col)}${cell.row + 1}` : "";
|
|
573
|
+
function spillBorderStyle(range, row, col) {
|
|
574
|
+
const line = "1px solid color-mix(in srgb, var(--primary, #6366f1) 60%, transparent)";
|
|
575
|
+
return {
|
|
576
|
+
position: "absolute",
|
|
577
|
+
inset: 0,
|
|
578
|
+
pointerEvents: "none",
|
|
579
|
+
zIndex: 5,
|
|
580
|
+
borderTop: row === range.startRow ? line : void 0,
|
|
581
|
+
borderBottom: row === range.endRow ? line : void 0,
|
|
582
|
+
borderLeft: col === range.startCol ? line : void 0,
|
|
583
|
+
borderRight: col === range.endCol ? line : void 0
|
|
584
|
+
};
|
|
585
|
+
}
|
|
546
586
|
var SpreadsheetEditor = ({
|
|
547
587
|
state: externalState,
|
|
548
588
|
readOnly = false,
|
|
@@ -573,10 +613,10 @@ var SpreadsheetEditor = ({
|
|
|
573
613
|
if (readOnly) return;
|
|
574
614
|
e.preventDefault();
|
|
575
615
|
if (state.editingCell) state.commitEditing();
|
|
576
|
-
if (!state.selectedRange || !(0,
|
|
616
|
+
if (!state.selectedRange || !(0, import_spreadsheet5.rangeContains)(state.selectedRange, rIdx, cIdx)) {
|
|
577
617
|
state.selectCell(rIdx, cIdx);
|
|
578
618
|
}
|
|
579
|
-
setMenu({ x: e.clientX, y: e.clientY, items: (0,
|
|
619
|
+
setMenu({ x: e.clientX, y: e.clientY, items: (0, import_spreadsheet5.getSpreadsheetMenuItems)(state.controller, { row: rIdx, col: cIdx }) });
|
|
580
620
|
}, [readOnly, state]);
|
|
581
621
|
const activeRawValue = (0, import_react5.useMemo)(() => {
|
|
582
622
|
if (!state.activeCell) return "";
|
|
@@ -585,9 +625,15 @@ var SpreadsheetEditor = ({
|
|
|
585
625
|
if (!row || !col) return "";
|
|
586
626
|
return state.getCell(row.id, col.id).raw;
|
|
587
627
|
}, [state.activeCell, state.document]);
|
|
628
|
+
const activeSpill = (0, import_react5.useMemo)(
|
|
629
|
+
() => state.activeCell ? state.controller.getSpillAt(state.activeCell.row, state.activeCell.col) : null,
|
|
630
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
631
|
+
[state.controller, state.activeCell, state.document]
|
|
632
|
+
);
|
|
633
|
+
const spillFormula = activeSpill && !activeRawValue && activeSpill.key !== coordKey(state.activeCell) ? activeSpill.formula : "";
|
|
588
634
|
const coordLabel = (0, import_react5.useMemo)(() => {
|
|
589
635
|
if (!state.activeCell) return "--";
|
|
590
|
-
const colName = (0,
|
|
636
|
+
const colName = (0, import_spreadsheet5.indexToColName)(state.activeCell.col);
|
|
591
637
|
return `${colName}${state.activeCell.row + 1}`;
|
|
592
638
|
}, [state.activeCell]);
|
|
593
639
|
const [formulaDraft, setFormulaDraft] = (0, import_react5.useState)(null);
|
|
@@ -634,7 +680,10 @@ var SpreadsheetEditor = ({
|
|
|
634
680
|
e.preventDefault();
|
|
635
681
|
state.commitEditing();
|
|
636
682
|
state.moveCursor(e.shiftKey ? "left" : "right");
|
|
683
|
+
} else {
|
|
684
|
+
return;
|
|
637
685
|
}
|
|
686
|
+
gridRef.current?.focus();
|
|
638
687
|
return;
|
|
639
688
|
}
|
|
640
689
|
if (!state.activeCell) return;
|
|
@@ -682,6 +731,7 @@ var SpreadsheetEditor = ({
|
|
|
682
731
|
} else if (!readOnly && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
683
732
|
const col = state.document.columns[state.activeCell.col];
|
|
684
733
|
if (!col?.readOnly) {
|
|
734
|
+
e.preventDefault();
|
|
685
735
|
state.startEditing(state.activeCell.row, state.activeCell.col, e.key);
|
|
686
736
|
}
|
|
687
737
|
}
|
|
@@ -874,7 +924,9 @@ var SpreadsheetEditor = ({
|
|
|
874
924
|
placeholder: "Enter a value or formula (e.g. =SUM(A1:A5))",
|
|
875
925
|
"aria-label": "Formula bar",
|
|
876
926
|
readOnly: formulaBarReadOnly,
|
|
877
|
-
|
|
927
|
+
"data-spill-formula": !state.editingCell && formulaDraft === null && spillFormula ? "true" : void 0,
|
|
928
|
+
style: !state.editingCell && formulaDraft === null && spillFormula ? { color: "var(--muted-foreground, #94a3b8)" } : void 0,
|
|
929
|
+
value: state.editingCell ? state.draftValue : formulaDraft ?? (activeRawValue || spillFormula),
|
|
878
930
|
onFocus: () => {
|
|
879
931
|
if (!state.editingCell) setFormulaDraft(activeRawValue);
|
|
880
932
|
},
|
|
@@ -909,8 +961,8 @@ var SpreadsheetEditor = ({
|
|
|
909
961
|
)
|
|
910
962
|
] }),
|
|
911
963
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "relative flex-1 overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("table", { className: "border-collapse table-fixed w-max min-w-full", children: [
|
|
912
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tr", { className: "h-7 bg-muted
|
|
913
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { className: "w-12 min-w-[3rem] sticky left-0 z-30 bg-muted
|
|
964
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tr", { className: "h-7 bg-muted sticky top-0 z-20 border-b border-border shadow-xs", children: [
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { className: "w-12 min-w-[3rem] sticky left-0 z-30 bg-muted border-r border-border text-center text-[10px] text-muted-foreground font-medium", children: "#" }),
|
|
914
966
|
view.columns.map(({ column: col, index: cIdx, frozen, stickyLeft }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
915
967
|
"th",
|
|
916
968
|
{
|
|
@@ -996,7 +1048,7 @@ var SpreadsheetEditor = ({
|
|
|
996
1048
|
);
|
|
997
1049
|
}
|
|
998
1050
|
const displayRowIndex = viewRow.index;
|
|
999
|
-
const selection = state.selectedRange ? (0,
|
|
1051
|
+
const selection = state.selectedRange ? (0, import_spreadsheet5.normalizeRange)(state.selectedRange) : null;
|
|
1000
1052
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1001
1053
|
"tr",
|
|
1002
1054
|
{
|
|
@@ -1007,7 +1059,7 @@ var SpreadsheetEditor = ({
|
|
|
1007
1059
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1008
1060
|
"td",
|
|
1009
1061
|
{
|
|
1010
|
-
className: "w-12 min-w-[3rem] sticky left-0 z-10 bg-muted
|
|
1062
|
+
className: "w-12 min-w-[3rem] sticky left-0 z-10 bg-muted border-r border-border text-center text-[10px] text-muted-foreground font-mono select-none",
|
|
1011
1063
|
style: viewRow.frozen ? { top: COLUMN_HEADER_HEIGHT + viewRow.stickyTop, zIndex: 15 } : void 0,
|
|
1012
1064
|
children: displayRowIndex + 1
|
|
1013
1065
|
}
|
|
@@ -1023,8 +1075,8 @@ var SpreadsheetEditor = ({
|
|
|
1023
1075
|
const selected = isCellSelected(rIdx, cIdx);
|
|
1024
1076
|
const active = isActiveCell(rIdx, cIdx);
|
|
1025
1077
|
const isEditing = state.editingCell?.row === rIdx && state.editingCell?.col === cIdx;
|
|
1026
|
-
const inFillPreview = !!fillTarget && !selected && (0,
|
|
1027
|
-
const showFillHandle = !readOnly && !isEditing && !!selection && (span.merge ? (0,
|
|
1078
|
+
const inFillPreview = !!fillTarget && !selected && (0, import_spreadsheet5.rangeContains)(fillTarget, displayRowIndex, viewCol.index);
|
|
1079
|
+
const showFillHandle = !readOnly && !isEditing && !!selection && (span.merge ? (0, import_spreadsheet5.rangeContains)(span.merge, selection.endRow, selection.endCol) : selection.endRow === rIdx && selection.endCol === cIdx);
|
|
1028
1080
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1029
1081
|
"td",
|
|
1030
1082
|
{
|
|
@@ -1054,6 +1106,10 @@ var SpreadsheetEditor = ({
|
|
|
1054
1106
|
value: state.draftValue,
|
|
1055
1107
|
onChange: (e) => state.setDraftValue(e.target.value),
|
|
1056
1108
|
onBlur: () => state.commitEditing(),
|
|
1109
|
+
onFocus: (e) => {
|
|
1110
|
+
const end = e.currentTarget.value.length;
|
|
1111
|
+
e.currentTarget.setSelectionRange(end, end);
|
|
1112
|
+
},
|
|
1057
1113
|
autoFocus: true
|
|
1058
1114
|
}
|
|
1059
1115
|
),
|
|
@@ -1066,6 +1122,7 @@ var SpreadsheetEditor = ({
|
|
|
1066
1122
|
children: cell.error || (cell.value ?? "")
|
|
1067
1123
|
}
|
|
1068
1124
|
),
|
|
1125
|
+
activeSpill && (0, import_spreadsheet5.rangeContains)(activeSpill.range, rIdx, cIdx) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", className: "spreadsheet-spill-border", style: spillBorderStyle(activeSpill.range, rIdx, cIdx) }),
|
|
1069
1126
|
showFillHandle && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1070
1127
|
"div",
|
|
1071
1128
|
{
|