@pixerate/editor-react 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -31,14 +31,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BubbleMenu: () => BubbleMenu,
34
- DirtyTracker: () => import_editor6.DirtyTracker,
34
+ DirtyTracker: () => import_editor7.DirtyTracker,
35
35
  EditorContent: () => EditorContent,
36
+ HistoryManager: () => import_editor7.HistoryManager,
36
37
  SpreadsheetEditor: () => SpreadsheetEditor,
37
38
  TemplateRenderer: () => TemplateRenderer,
38
- createDirtyTracker: () => import_editor6.createDirtyTracker,
39
- defaultIsEqual: () => import_editor6.defaultIsEqual,
39
+ createDirtyTracker: () => import_editor7.createDirtyTracker,
40
+ createHistoryManager: () => import_editor7.createHistoryManager,
41
+ defaultIsEqual: () => import_editor7.defaultIsEqual,
40
42
  useDismissGuard: () => useDismissGuard,
41
43
  useEditor: () => useEditor2,
44
+ useHistory: () => useHistory,
45
+ useHistoryShortcuts: () => useHistoryShortcuts,
42
46
  useNavigationGuard: () => useNavigationGuard,
43
47
  usePromptEditor: () => usePromptEditor,
44
48
  useSpreadsheetEditor: () => useSpreadsheetEditor
@@ -389,19 +393,115 @@ function useDismissGuard({
389
393
  };
390
394
  }
391
395
 
396
+ // src/hooks/useHistory.ts
397
+ var import_react6 = require("react");
398
+ var import_editor3 = require("@pixerate/editor");
399
+ function useHistory(managerOrOptions) {
400
+ const manager = (0, import_react6.useMemo)(() => {
401
+ if (managerOrOptions instanceof import_editor3.HistoryManager) {
402
+ return managerOrOptions;
403
+ }
404
+ return (0, import_editor3.createHistoryManager)(managerOrOptions);
405
+ }, [managerOrOptions]);
406
+ const state = (0, import_react6.useSyncExternalStore)(
407
+ (0, import_react6.useCallback)(
408
+ (onStoreChange) => manager.subscribe(onStoreChange),
409
+ [manager]
410
+ ),
411
+ () => manager.getState(),
412
+ () => manager.getState()
413
+ );
414
+ const undo = (0, import_react6.useCallback)(() => manager.undo(), [manager]);
415
+ const redo = (0, import_react6.useCallback)(() => manager.redo(), [manager]);
416
+ const clear = (0, import_react6.useCallback)(() => manager.clear(), [manager]);
417
+ const execute = (0, import_react6.useCallback)(
418
+ (cmd) => manager.execute(cmd),
419
+ [manager]
420
+ );
421
+ const executeMerged = (0, import_react6.useCallback)(
422
+ (cmd, opts) => manager.executeMerged(cmd, opts),
423
+ [manager]
424
+ );
425
+ const batch = (0, import_react6.useCallback)(
426
+ (name, fn) => manager.batch(name, fn),
427
+ [manager]
428
+ );
429
+ return {
430
+ ...state,
431
+ manager,
432
+ undo,
433
+ redo,
434
+ clear,
435
+ execute,
436
+ executeMerged,
437
+ batch
438
+ };
439
+ }
440
+
441
+ // src/hooks/useHistoryShortcuts.ts
442
+ var import_react7 = require("react");
443
+ function useHistoryShortcuts(manager, options = {}) {
444
+ const {
445
+ enabled = true,
446
+ target,
447
+ ignoreEditableElements = true
448
+ } = options;
449
+ (0, import_react7.useEffect)(() => {
450
+ if (!enabled) return;
451
+ const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
452
+ if (!eventTarget) return;
453
+ const handleKeyDown = (event) => {
454
+ const e = event;
455
+ const isMac = typeof navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
456
+ const modifier = isMac ? e.metaKey : e.ctrlKey;
457
+ if (!modifier) return;
458
+ if (ignoreEditableElements && typeof document !== "undefined") {
459
+ const targetEl = e.target || document.activeElement;
460
+ if (targetEl && targetEl.tagName) {
461
+ const tagName = targetEl.tagName.toLowerCase();
462
+ const isInput = tagName === "input" || tagName === "textarea";
463
+ const isContentEditable = targetEl.isContentEditable || targetEl.getAttribute?.("contenteditable") === "true";
464
+ if (isInput || isContentEditable) {
465
+ return;
466
+ }
467
+ }
468
+ }
469
+ const key = e.key.toLowerCase();
470
+ if (key === "z" && !e.shiftKey) {
471
+ if (manager.getState().canUndo) {
472
+ e.preventDefault();
473
+ manager.undo();
474
+ }
475
+ return;
476
+ }
477
+ const isRedoKey = key === "z" && e.shiftKey || !isMac && key === "y" && !e.shiftKey;
478
+ if (isRedoKey) {
479
+ if (manager.getState().canRedo) {
480
+ e.preventDefault();
481
+ manager.redo();
482
+ }
483
+ }
484
+ };
485
+ eventTarget.addEventListener("keydown", handleKeyDown);
486
+ return () => {
487
+ eventTarget.removeEventListener("keydown", handleKeyDown);
488
+ };
489
+ }, [manager, enabled, target, ignoreEditableElements]);
490
+ }
491
+
392
492
  // src/components/EditorContent.tsx
393
- var import_react6 = require("@tiptap/react");
493
+ var import_react8 = require("@tiptap/react");
394
494
  var import_jsx_runtime = require("react/jsx-runtime");
395
495
  var EditorContent = ({
396
496
  className,
397
497
  editor,
398
498
  ...props
399
499
  }) => {
400
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react6.EditorContent, { editor, ...props }) });
500
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react8.EditorContent, { editor, ...props }) });
401
501
  };
402
502
 
403
503
  // src/components/BubbleMenu.tsx
404
- var import_react7 = require("react");
504
+ var import_react9 = require("react");
405
505
  var import_react_dom = require("react-dom");
406
506
  var import_extension_bubble_menu = require("@tiptap/extension-bubble-menu");
407
507
  var BubbleMenu = ({
@@ -413,12 +513,12 @@ var BubbleMenu = ({
413
513
  pluginKey = "bubbleMenu",
414
514
  updateDelay
415
515
  }) => {
416
- const menuEl = (0, import_react7.useRef)(null);
417
- const [mounted, setMounted] = (0, import_react7.useState)(false);
516
+ const menuEl = (0, import_react9.useRef)(null);
517
+ const [mounted, setMounted] = (0, import_react9.useState)(false);
418
518
  if (!menuEl.current && typeof document !== "undefined") {
419
519
  menuEl.current = document.createElement("div");
420
520
  }
421
- (0, import_react7.useEffect)(() => {
521
+ (0, import_react9.useEffect)(() => {
422
522
  if (!editor || !menuEl.current || editor.isDestroyed) {
423
523
  return;
424
524
  }
@@ -449,8 +549,8 @@ var BubbleMenu = ({
449
549
  };
450
550
 
451
551
  // src/components/TemplateRenderer.tsx
452
- var import_react8 = require("react");
453
- var import_editor3 = require("@pixerate/editor");
552
+ var import_react10 = require("react");
553
+ var import_editor4 = require("@pixerate/editor");
454
554
  var import_jsx_runtime2 = require("react/jsx-runtime");
455
555
  var TemplateRenderer = ({
456
556
  content,
@@ -461,12 +561,12 @@ var TemplateRenderer = ({
461
561
  onTemplateClick,
462
562
  onVariableClick
463
563
  }) => {
464
- const displayText = (0, import_react8.useMemo)(() => {
564
+ const displayText = (0, import_react10.useMemo)(() => {
465
565
  if (!resolve || templates.length === 0) return content;
466
- return (0, import_editor3.resolveTemplates)(content, templates);
566
+ return (0, import_editor4.resolveTemplates)(content, templates);
467
567
  }, [content, templates, resolve]);
468
- const tokens = (0, import_react8.useMemo)(() => {
469
- return (0, import_editor3.tokenizePrompt)(displayText);
568
+ const tokens = (0, import_react10.useMemo)(() => {
569
+ return (0, import_editor4.tokenizePrompt)(displayText);
470
570
  }, [displayText]);
471
571
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className, children: tokens.map((token, index) => {
472
572
  if (token.type === "template") {
@@ -518,13 +618,13 @@ var TemplateRenderer = ({
518
618
  };
519
619
 
520
620
  // src/index.ts
521
- var import_editor6 = require("@pixerate/editor");
621
+ var import_editor7 = require("@pixerate/editor");
522
622
 
523
623
  // src/spreadsheet/useSpreadsheetEditor.ts
524
- var import_react9 = require("react");
525
- var import_editor4 = require("@pixerate/editor");
624
+ var import_react11 = require("react");
625
+ var import_editor5 = require("@pixerate/editor");
526
626
  function useSpreadsheetEditor(options = {}) {
527
- const [doc, setDoc] = (0, import_react9.useState)(() => ({
627
+ const [doc, setDoc] = (0, import_react11.useState)(() => ({
528
628
  id: options.document?.id || `sheet_${Date.now()}`,
529
629
  name: options.document?.name || "Sheet 1",
530
630
  columns: options.document?.columns || [],
@@ -533,12 +633,12 @@ function useSpreadsheetEditor(options = {}) {
533
633
  createdAt: options.document?.createdAt || Date.now(),
534
634
  updatedAt: options.document?.updatedAt || Date.now()
535
635
  }));
536
- const [activeCell, setActiveCell] = (0, import_react9.useState)(null);
537
- const [selectedRange, setSelectedRange] = (0, import_react9.useState)(null);
538
- const [editingCell, setEditingCell] = (0, import_react9.useState)(null);
539
- const [draftValue, setDraftValue] = (0, import_react9.useState)("");
540
- const controller = (0, import_react9.useMemo)(() => {
541
- return new import_editor4.SpreadsheetController({
636
+ const [activeCell, setActiveCell] = (0, import_react11.useState)(null);
637
+ const [selectedRange, setSelectedRange] = (0, import_react11.useState)(null);
638
+ const [editingCell, setEditingCell] = (0, import_react11.useState)(null);
639
+ const [draftValue, setDraftValue] = (0, import_react11.useState)("");
640
+ const controller = (0, import_react11.useMemo)(() => {
641
+ return new import_editor5.SpreadsheetController({
542
642
  ...options,
543
643
  onDocumentChange: (updated) => {
544
644
  setDoc({ ...updated });
@@ -554,82 +654,82 @@ function useSpreadsheetEditor(options = {}) {
554
654
  }
555
655
  });
556
656
  }, []);
557
- const setCellValue = (0, import_react9.useCallback)((rowId, colId, raw) => {
657
+ const setCellValue = (0, import_react11.useCallback)((rowId, colId, raw) => {
558
658
  controller.setCellValue(rowId, colId, raw);
559
659
  setDoc({ ...controller.document });
560
660
  }, [controller]);
561
- const selectCell = (0, import_react9.useCallback)((row, col, extendSelection = false) => {
661
+ const selectCell = (0, import_react11.useCallback)((row, col, extendSelection = false) => {
562
662
  controller.selectCell(row, col, extendSelection);
563
663
  setActiveCell(controller.activeCell);
564
664
  setSelectedRange(controller.selectedRange);
565
665
  }, [controller]);
566
- const selectRange = (0, import_react9.useCallback)((range) => {
666
+ const selectRange = (0, import_react11.useCallback)((range) => {
567
667
  controller.selectRange(range);
568
668
  setSelectedRange(controller.selectedRange);
569
669
  }, [controller]);
570
- const startEditing = (0, import_react9.useCallback)((row, col, initialVal) => {
670
+ const startEditing = (0, import_react11.useCallback)((row, col, initialVal) => {
571
671
  controller.startEditing(row, col, initialVal);
572
672
  setActiveCell(controller.activeCell);
573
673
  setEditingCell(controller.editingCell);
574
674
  setDraftValue(controller.draftValue);
575
675
  }, [controller]);
576
- const commitEditing = (0, import_react9.useCallback)((val) => {
676
+ const commitEditing = (0, import_react11.useCallback)((val) => {
577
677
  controller.commitEditing(val);
578
678
  setEditingCell(null);
579
679
  setDraftValue("");
580
680
  setDoc({ ...controller.document });
581
681
  }, [controller]);
582
- const cancelEditing = (0, import_react9.useCallback)(() => {
682
+ const cancelEditing = (0, import_react11.useCallback)(() => {
583
683
  controller.cancelEditing();
584
684
  setEditingCell(null);
585
685
  setDraftValue("");
586
686
  }, [controller]);
587
- const moveCursor = (0, import_react9.useCallback)((dir, extend = false) => {
687
+ const moveCursor = (0, import_react11.useCallback)((dir, extend = false) => {
588
688
  controller.moveCursor(dir, extend);
589
689
  setActiveCell(controller.activeCell);
590
690
  setSelectedRange(controller.selectedRange);
591
691
  }, [controller]);
592
- const insertColumn = (0, import_react9.useCallback)((index, config) => {
692
+ const insertColumn = (0, import_react11.useCallback)((index, config) => {
593
693
  controller.insertColumn(index, config);
594
694
  setDoc({ ...controller.document });
595
695
  }, [controller]);
596
- const deleteColumn = (0, import_react9.useCallback)((colId) => {
696
+ const deleteColumn = (0, import_react11.useCallback)((colId) => {
597
697
  controller.deleteColumn(colId);
598
698
  setDoc({ ...controller.document });
599
699
  }, [controller]);
600
- const insertRow = (0, import_react9.useCallback)((index, config) => {
700
+ const insertRow = (0, import_react11.useCallback)((index, config) => {
601
701
  controller.insertRow(index, config);
602
702
  setDoc({ ...controller.document });
603
703
  }, [controller]);
604
- const deleteRow = (0, import_react9.useCallback)((rowId) => {
704
+ const deleteRow = (0, import_react11.useCallback)((rowId) => {
605
705
  controller.deleteRow(rowId);
606
706
  setDoc({ ...controller.document });
607
707
  }, [controller]);
608
- const setColumnWidth = (0, import_react9.useCallback)((colId, width) => {
708
+ const setColumnWidth = (0, import_react11.useCallback)((colId, width) => {
609
709
  controller.setColumnWidth(colId, width);
610
710
  setDoc({ ...controller.document });
611
711
  }, [controller]);
612
- const autoFitColumnWidth = (0, import_react9.useCallback)((colId, customWidth) => {
712
+ const autoFitColumnWidth = (0, import_react11.useCallback)((colId, customWidth) => {
613
713
  controller.autoFitColumnWidth(colId, customWidth);
614
714
  setDoc({ ...controller.document });
615
715
  }, [controller]);
616
- const registerDataSource = (0, import_react9.useCallback)((ds) => {
716
+ const registerDataSource = (0, import_react11.useCallback)((ds) => {
617
717
  controller.registerDataSource(ds);
618
718
  setDoc({ ...controller.document });
619
719
  }, [controller]);
620
- const setPrimaryDataSource = (0, import_react9.useCallback)((id) => {
720
+ const setPrimaryDataSource = (0, import_react11.useCallback)((id) => {
621
721
  controller.setPrimaryDataSource(id);
622
722
  setDoc({ ...controller.document });
623
723
  }, [controller]);
624
- const recalculateAll = (0, import_react9.useCallback)(() => {
724
+ const recalculateAll = (0, import_react11.useCallback)(() => {
625
725
  controller.recalculateAll();
626
726
  setDoc({ ...controller.document });
627
727
  }, [controller]);
628
- const undo = (0, import_react9.useCallback)(() => {
728
+ const undo = (0, import_react11.useCallback)(() => {
629
729
  controller.undo();
630
730
  setDoc({ ...controller.document });
631
731
  }, [controller]);
632
- const redo = (0, import_react9.useCallback)(() => {
732
+ const redo = (0, import_react11.useCallback)(() => {
633
733
  controller.redo();
634
734
  setDoc({ ...controller.document });
635
735
  }, [controller]);
@@ -682,8 +782,8 @@ function useSpreadsheetEditor(options = {}) {
682
782
  }
683
783
 
684
784
  // src/spreadsheet/SpreadsheetEditor.tsx
685
- var import_react10 = require("react");
686
- var import_editor5 = require("@pixerate/editor");
785
+ var import_react12 = require("react");
786
+ var import_editor6 = require("@pixerate/editor");
687
787
  var import_jsx_runtime3 = require("react/jsx-runtime");
688
788
  var SpreadsheetEditor = ({
689
789
  state: externalState,
@@ -695,36 +795,36 @@ var SpreadsheetEditor = ({
695
795
  }) => {
696
796
  const defaultState = useSpreadsheetEditor();
697
797
  const state = externalState || defaultState;
698
- const gridRef = (0, import_react10.useRef)(null);
699
- const [resizingColId, setResizingColId] = (0, import_react10.useState)(null);
700
- const [hoveredColId, setHoveredColId] = (0, import_react10.useState)(null);
701
- const [resizeStartX, setResizeStartX] = (0, import_react10.useState)(0);
702
- const [resizeStartWidth, setResizeStartWidth] = (0, import_react10.useState)(0);
703
- const activeRawValue = (0, import_react10.useMemo)(() => {
798
+ const gridRef = (0, import_react12.useRef)(null);
799
+ const [resizingColId, setResizingColId] = (0, import_react12.useState)(null);
800
+ const [hoveredColId, setHoveredColId] = (0, import_react12.useState)(null);
801
+ const [resizeStartX, setResizeStartX] = (0, import_react12.useState)(0);
802
+ const [resizeStartWidth, setResizeStartWidth] = (0, import_react12.useState)(0);
803
+ const activeRawValue = (0, import_react12.useMemo)(() => {
704
804
  if (!state.activeCell) return "";
705
805
  const row = state.document.rows[state.activeCell.row];
706
806
  const col = state.document.columns[state.activeCell.col];
707
807
  if (!row || !col) return "";
708
808
  return state.getCell(row.id, col.id).raw;
709
809
  }, [state.activeCell, state.document]);
710
- const coordLabel = (0, import_react10.useMemo)(() => {
810
+ const coordLabel = (0, import_react12.useMemo)(() => {
711
811
  if (!state.activeCell) return "--";
712
- const colName = (0, import_editor5.indexToColName)(state.activeCell.col);
812
+ const colName = (0, import_editor6.indexToColName)(state.activeCell.col);
713
813
  return `${colName}${state.activeCell.row + 1}`;
714
814
  }, [state.activeCell]);
715
- const handleCellClick = (0, import_react10.useCallback)((rIdx, cIdx, e) => {
815
+ const handleCellClick = (0, import_react12.useCallback)((rIdx, cIdx, e) => {
716
816
  if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {
717
817
  state.commitEditing();
718
818
  }
719
819
  state.selectCell(rIdx, cIdx, e.shiftKey);
720
820
  }, [state]);
721
- const handleCellDblClick = (0, import_react10.useCallback)((rIdx, cIdx) => {
821
+ const handleCellDblClick = (0, import_react12.useCallback)((rIdx, cIdx) => {
722
822
  if (readOnly) return;
723
823
  const col = state.document.columns[cIdx];
724
824
  if (col?.readOnly) return;
725
825
  state.startEditing(rIdx, cIdx);
726
826
  }, [readOnly, state]);
727
- const handleKeyDown = (0, import_react10.useCallback)((e) => {
827
+ const handleKeyDown = (0, import_react12.useCallback)((e) => {
728
828
  if (state.editingCell) {
729
829
  if (e.key === "Enter") {
730
830
  e.preventDefault();
@@ -788,7 +888,7 @@ var SpreadsheetEditor = ({
788
888
  }
789
889
  }
790
890
  }, [readOnly, state]);
791
- (0, import_react10.useEffect)(() => {
891
+ (0, import_react12.useEffect)(() => {
792
892
  if (!resizingColId) return;
793
893
  if (typeof document !== "undefined") {
794
894
  document.body.style.cursor = "col-resize";
@@ -842,7 +942,7 @@ var SpreadsheetEditor = ({
842
942
  window.removeEventListener("mouseup", handleMouseUp);
843
943
  };
844
944
  }, [resizingColId, resizeStartX, resizeStartWidth, state, onColumnResize]);
845
- const measureElementContentWidth = (0, import_react10.useCallback)((el, container) => {
945
+ const measureElementContentWidth = (0, import_react12.useCallback)((el, container) => {
846
946
  if (typeof document === "undefined") return 0;
847
947
  let maxW = el.scrollWidth || 0;
848
948
  const firstChild = el.firstElementChild;
@@ -890,7 +990,7 @@ var SpreadsheetEditor = ({
890
990
  }
891
991
  return maxW;
892
992
  }, []);
893
- const autoFitColumn = (0, import_react10.useCallback)((colId, colIndex) => {
993
+ const autoFitColumn = (0, import_react12.useCallback)((colId, colIndex) => {
894
994
  const col = state.document.columns.find((c) => c.id === colId);
895
995
  if (!col) return;
896
996
  let calculatedWidth = 0;
@@ -927,12 +1027,12 @@ var SpreadsheetEditor = ({
927
1027
  onColumnResize(updatedCol.id, updatedCol.width || 130);
928
1028
  }
929
1029
  }, [state, measureElementContentWidth, onColumnResize]);
930
- const handleResizeDblClick = (0, import_react10.useCallback)((colId, colIndex, e) => {
1030
+ const handleResizeDblClick = (0, import_react12.useCallback)((colId, colIndex, e) => {
931
1031
  e.preventDefault();
932
1032
  e.stopPropagation();
933
1033
  autoFitColumn(colId, colIndex);
934
1034
  }, [autoFitColumn]);
935
- const handleHeaderDblClick = (0, import_react10.useCallback)((colId, colIndex, e) => {
1035
+ const handleHeaderDblClick = (0, import_react12.useCallback)((colId, colIndex, e) => {
936
1036
  const target = e.currentTarget;
937
1037
  if (target) {
938
1038
  const rect = target.getBoundingClientRect();
@@ -1120,12 +1220,16 @@ var SpreadsheetEditor = ({
1120
1220
  BubbleMenu,
1121
1221
  DirtyTracker,
1122
1222
  EditorContent,
1223
+ HistoryManager,
1123
1224
  SpreadsheetEditor,
1124
1225
  TemplateRenderer,
1125
1226
  createDirtyTracker,
1227
+ createHistoryManager,
1126
1228
  defaultIsEqual,
1127
1229
  useDismissGuard,
1128
1230
  useEditor,
1231
+ useHistory,
1232
+ useHistoryShortcuts,
1129
1233
  useNavigationGuard,
1130
1234
  usePromptEditor,
1131
1235
  useSpreadsheetEditor