@pixerate/editor-react 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -348,6 +348,105 @@ function useDismissGuard({
348
348
  };
349
349
  }
350
350
 
351
+ // src/hooks/useHistory.ts
352
+ import { useSyncExternalStore, useMemo as useMemo2, useCallback as useCallback3 } from "react";
353
+ import {
354
+ HistoryManager,
355
+ createHistoryManager
356
+ } from "@pixerate/editor";
357
+ function useHistory(managerOrOptions) {
358
+ const manager = useMemo2(() => {
359
+ if (managerOrOptions instanceof HistoryManager) {
360
+ return managerOrOptions;
361
+ }
362
+ return createHistoryManager(managerOrOptions);
363
+ }, [managerOrOptions]);
364
+ const state = useSyncExternalStore(
365
+ useCallback3(
366
+ (onStoreChange) => manager.subscribe(onStoreChange),
367
+ [manager]
368
+ ),
369
+ () => manager.getState(),
370
+ () => manager.getState()
371
+ );
372
+ const undo = useCallback3(() => manager.undo(), [manager]);
373
+ const redo = useCallback3(() => manager.redo(), [manager]);
374
+ const clear = useCallback3(() => manager.clear(), [manager]);
375
+ const execute = useCallback3(
376
+ (cmd) => manager.execute(cmd),
377
+ [manager]
378
+ );
379
+ const executeMerged = useCallback3(
380
+ (cmd, opts) => manager.executeMerged(cmd, opts),
381
+ [manager]
382
+ );
383
+ const batch = useCallback3(
384
+ (name, fn) => manager.batch(name, fn),
385
+ [manager]
386
+ );
387
+ return {
388
+ ...state,
389
+ manager,
390
+ undo,
391
+ redo,
392
+ clear,
393
+ execute,
394
+ executeMerged,
395
+ batch
396
+ };
397
+ }
398
+
399
+ // src/hooks/useHistoryShortcuts.ts
400
+ import { useEffect as useEffect3 } from "react";
401
+ function useHistoryShortcuts(manager, options = {}) {
402
+ const {
403
+ enabled = true,
404
+ target,
405
+ ignoreEditableElements = true
406
+ } = options;
407
+ useEffect3(() => {
408
+ if (!enabled) return;
409
+ const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
410
+ if (!eventTarget) return;
411
+ const handleKeyDown = (event) => {
412
+ const e = event;
413
+ const isMac = typeof navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
414
+ const modifier = isMac ? e.metaKey : e.ctrlKey;
415
+ if (!modifier) return;
416
+ if (ignoreEditableElements && typeof document !== "undefined") {
417
+ const targetEl = e.target || document.activeElement;
418
+ if (targetEl && targetEl.tagName) {
419
+ const tagName = targetEl.tagName.toLowerCase();
420
+ const isInput = tagName === "input" || tagName === "textarea";
421
+ const isContentEditable = targetEl.isContentEditable || targetEl.getAttribute?.("contenteditable") === "true";
422
+ if (isInput || isContentEditable) {
423
+ return;
424
+ }
425
+ }
426
+ }
427
+ const key = e.key.toLowerCase();
428
+ if (key === "z" && !e.shiftKey) {
429
+ if (manager.getState().canUndo) {
430
+ e.preventDefault();
431
+ manager.undo();
432
+ }
433
+ return;
434
+ }
435
+ const isRedoKey = key === "z" && e.shiftKey || !isMac && key === "y" && !e.shiftKey;
436
+ if (isRedoKey) {
437
+ if (manager.getState().canRedo) {
438
+ e.preventDefault();
439
+ manager.redo();
440
+ }
441
+ }
442
+ };
443
+ eventTarget.addEventListener("keydown", handleKeyDown);
444
+ return () => {
445
+ eventTarget.removeEventListener("keydown", handleKeyDown);
446
+ };
447
+ }, [manager, enabled, target, ignoreEditableElements]);
448
+ }
449
+
351
450
  // src/components/EditorContent.tsx
352
451
  import {
353
452
  EditorContent as TipTapEditorContent
@@ -362,7 +461,7 @@ var EditorContent = ({
362
461
  };
363
462
 
364
463
  // src/components/BubbleMenu.tsx
365
- import { useEffect as useEffect3, useRef as useRef4, useState as useState3 } from "react";
464
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState3 } from "react";
366
465
  import { createPortal } from "react-dom";
367
466
  import {
368
467
  BubbleMenuPlugin
@@ -381,7 +480,7 @@ var BubbleMenu = ({
381
480
  if (!menuEl.current && typeof document !== "undefined") {
382
481
  menuEl.current = document.createElement("div");
383
482
  }
384
- useEffect3(() => {
483
+ useEffect4(() => {
385
484
  if (!editor || !menuEl.current || editor.isDestroyed) {
386
485
  return;
387
486
  }
@@ -412,7 +511,7 @@ var BubbleMenu = ({
412
511
  };
413
512
 
414
513
  // src/components/TemplateRenderer.tsx
415
- import { useMemo as useMemo2 } from "react";
514
+ import { useMemo as useMemo3 } from "react";
416
515
  import {
417
516
  tokenizePrompt,
418
517
  resolveTemplates
@@ -427,11 +526,11 @@ var TemplateRenderer = ({
427
526
  onTemplateClick,
428
527
  onVariableClick
429
528
  }) => {
430
- const displayText = useMemo2(() => {
529
+ const displayText = useMemo3(() => {
431
530
  if (!resolve || templates.length === 0) return content;
432
531
  return resolveTemplates(content, templates);
433
532
  }, [content, templates, resolve]);
434
- const tokens = useMemo2(() => {
533
+ const tokens = useMemo3(() => {
435
534
  return tokenizePrompt(displayText);
436
535
  }, [displayText]);
437
536
  return /* @__PURE__ */ jsx2("div", { className, children: tokens.map((token, index) => {
@@ -487,11 +586,13 @@ var TemplateRenderer = ({
487
586
  import {
488
587
  DirtyTracker,
489
588
  createDirtyTracker,
490
- defaultIsEqual
589
+ defaultIsEqual,
590
+ HistoryManager as HistoryManager2,
591
+ createHistoryManager as createHistoryManager2
491
592
  } from "@pixerate/editor";
492
593
 
493
594
  // src/spreadsheet/useSpreadsheetEditor.ts
494
- import { useState as useState4, useMemo as useMemo3, useCallback as useCallback3 } from "react";
595
+ import { useState as useState4, useMemo as useMemo4, useCallback as useCallback4 } from "react";
495
596
  import {
496
597
  SpreadsheetController
497
598
  } from "@pixerate/editor";
@@ -509,7 +610,7 @@ function useSpreadsheetEditor(options = {}) {
509
610
  const [selectedRange, setSelectedRange] = useState4(null);
510
611
  const [editingCell, setEditingCell] = useState4(null);
511
612
  const [draftValue, setDraftValue] = useState4("");
512
- const controller = useMemo3(() => {
613
+ const controller = useMemo4(() => {
513
614
  return new SpreadsheetController({
514
615
  ...options,
515
616
  onDocumentChange: (updated) => {
@@ -526,82 +627,82 @@ function useSpreadsheetEditor(options = {}) {
526
627
  }
527
628
  });
528
629
  }, []);
529
- const setCellValue = useCallback3((rowId, colId, raw) => {
630
+ const setCellValue = useCallback4((rowId, colId, raw) => {
530
631
  controller.setCellValue(rowId, colId, raw);
531
632
  setDoc({ ...controller.document });
532
633
  }, [controller]);
533
- const selectCell = useCallback3((row, col, extendSelection = false) => {
634
+ const selectCell = useCallback4((row, col, extendSelection = false) => {
534
635
  controller.selectCell(row, col, extendSelection);
535
636
  setActiveCell(controller.activeCell);
536
637
  setSelectedRange(controller.selectedRange);
537
638
  }, [controller]);
538
- const selectRange = useCallback3((range) => {
639
+ const selectRange = useCallback4((range) => {
539
640
  controller.selectRange(range);
540
641
  setSelectedRange(controller.selectedRange);
541
642
  }, [controller]);
542
- const startEditing = useCallback3((row, col, initialVal) => {
643
+ const startEditing = useCallback4((row, col, initialVal) => {
543
644
  controller.startEditing(row, col, initialVal);
544
645
  setActiveCell(controller.activeCell);
545
646
  setEditingCell(controller.editingCell);
546
647
  setDraftValue(controller.draftValue);
547
648
  }, [controller]);
548
- const commitEditing = useCallback3((val) => {
649
+ const commitEditing = useCallback4((val) => {
549
650
  controller.commitEditing(val);
550
651
  setEditingCell(null);
551
652
  setDraftValue("");
552
653
  setDoc({ ...controller.document });
553
654
  }, [controller]);
554
- const cancelEditing = useCallback3(() => {
655
+ const cancelEditing = useCallback4(() => {
555
656
  controller.cancelEditing();
556
657
  setEditingCell(null);
557
658
  setDraftValue("");
558
659
  }, [controller]);
559
- const moveCursor = useCallback3((dir, extend = false) => {
660
+ const moveCursor = useCallback4((dir, extend = false) => {
560
661
  controller.moveCursor(dir, extend);
561
662
  setActiveCell(controller.activeCell);
562
663
  setSelectedRange(controller.selectedRange);
563
664
  }, [controller]);
564
- const insertColumn = useCallback3((index, config) => {
665
+ const insertColumn = useCallback4((index, config) => {
565
666
  controller.insertColumn(index, config);
566
667
  setDoc({ ...controller.document });
567
668
  }, [controller]);
568
- const deleteColumn = useCallback3((colId) => {
669
+ const deleteColumn = useCallback4((colId) => {
569
670
  controller.deleteColumn(colId);
570
671
  setDoc({ ...controller.document });
571
672
  }, [controller]);
572
- const insertRow = useCallback3((index, config) => {
673
+ const insertRow = useCallback4((index, config) => {
573
674
  controller.insertRow(index, config);
574
675
  setDoc({ ...controller.document });
575
676
  }, [controller]);
576
- const deleteRow = useCallback3((rowId) => {
677
+ const deleteRow = useCallback4((rowId) => {
577
678
  controller.deleteRow(rowId);
578
679
  setDoc({ ...controller.document });
579
680
  }, [controller]);
580
- const setColumnWidth = useCallback3((colId, width) => {
681
+ const setColumnWidth = useCallback4((colId, width) => {
581
682
  controller.setColumnWidth(colId, width);
582
683
  setDoc({ ...controller.document });
583
684
  }, [controller]);
584
- const autoFitColumnWidth = useCallback3((colId, customWidth) => {
685
+ const autoFitColumnWidth = useCallback4((colId, customWidth) => {
585
686
  controller.autoFitColumnWidth(colId, customWidth);
586
687
  setDoc({ ...controller.document });
587
688
  }, [controller]);
588
- const registerDataSource = useCallback3((ds) => {
689
+ const registerDataSource = useCallback4((ds) => {
589
690
  controller.registerDataSource(ds);
590
691
  setDoc({ ...controller.document });
591
692
  }, [controller]);
592
- const setPrimaryDataSource = useCallback3((id) => {
693
+ const setPrimaryDataSource = useCallback4((id) => {
593
694
  controller.setPrimaryDataSource(id);
594
695
  setDoc({ ...controller.document });
595
696
  }, [controller]);
596
- const recalculateAll = useCallback3(() => {
697
+ const recalculateAll = useCallback4(() => {
597
698
  controller.recalculateAll();
598
699
  setDoc({ ...controller.document });
599
700
  }, [controller]);
600
- const undo = useCallback3(() => {
701
+ const undo = useCallback4(() => {
601
702
  controller.undo();
602
703
  setDoc({ ...controller.document });
603
704
  }, [controller]);
604
- const redo = useCallback3(() => {
705
+ const redo = useCallback4(() => {
605
706
  controller.redo();
606
707
  setDoc({ ...controller.document });
607
708
  }, [controller]);
@@ -654,7 +755,7 @@ function useSpreadsheetEditor(options = {}) {
654
755
  }
655
756
 
656
757
  // src/spreadsheet/SpreadsheetEditor.tsx
657
- import { useRef as useRef5, useState as useState5, useMemo as useMemo4, useEffect as useEffect4, useCallback as useCallback4 } from "react";
758
+ import { useRef as useRef5, useState as useState5, useMemo as useMemo5, useEffect as useEffect5, useCallback as useCallback5 } from "react";
658
759
  import {
659
760
  indexToColName
660
761
  } from "@pixerate/editor";
@@ -674,31 +775,31 @@ var SpreadsheetEditor = ({
674
775
  const [hoveredColId, setHoveredColId] = useState5(null);
675
776
  const [resizeStartX, setResizeStartX] = useState5(0);
676
777
  const [resizeStartWidth, setResizeStartWidth] = useState5(0);
677
- const activeRawValue = useMemo4(() => {
778
+ const activeRawValue = useMemo5(() => {
678
779
  if (!state.activeCell) return "";
679
780
  const row = state.document.rows[state.activeCell.row];
680
781
  const col = state.document.columns[state.activeCell.col];
681
782
  if (!row || !col) return "";
682
783
  return state.getCell(row.id, col.id).raw;
683
784
  }, [state.activeCell, state.document]);
684
- const coordLabel = useMemo4(() => {
785
+ const coordLabel = useMemo5(() => {
685
786
  if (!state.activeCell) return "--";
686
787
  const colName = indexToColName(state.activeCell.col);
687
788
  return `${colName}${state.activeCell.row + 1}`;
688
789
  }, [state.activeCell]);
689
- const handleCellClick = useCallback4((rIdx, cIdx, e) => {
790
+ const handleCellClick = useCallback5((rIdx, cIdx, e) => {
690
791
  if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {
691
792
  state.commitEditing();
692
793
  }
693
794
  state.selectCell(rIdx, cIdx, e.shiftKey);
694
795
  }, [state]);
695
- const handleCellDblClick = useCallback4((rIdx, cIdx) => {
796
+ const handleCellDblClick = useCallback5((rIdx, cIdx) => {
696
797
  if (readOnly) return;
697
798
  const col = state.document.columns[cIdx];
698
799
  if (col?.readOnly) return;
699
800
  state.startEditing(rIdx, cIdx);
700
801
  }, [readOnly, state]);
701
- const handleKeyDown = useCallback4((e) => {
802
+ const handleKeyDown = useCallback5((e) => {
702
803
  if (state.editingCell) {
703
804
  if (e.key === "Enter") {
704
805
  e.preventDefault();
@@ -762,7 +863,7 @@ var SpreadsheetEditor = ({
762
863
  }
763
864
  }
764
865
  }, [readOnly, state]);
765
- useEffect4(() => {
866
+ useEffect5(() => {
766
867
  if (!resizingColId) return;
767
868
  if (typeof document !== "undefined") {
768
869
  document.body.style.cursor = "col-resize";
@@ -816,7 +917,7 @@ var SpreadsheetEditor = ({
816
917
  window.removeEventListener("mouseup", handleMouseUp);
817
918
  };
818
919
  }, [resizingColId, resizeStartX, resizeStartWidth, state, onColumnResize]);
819
- const measureElementContentWidth = useCallback4((el, container) => {
920
+ const measureElementContentWidth = useCallback5((el, container) => {
820
921
  if (typeof document === "undefined") return 0;
821
922
  let maxW = el.scrollWidth || 0;
822
923
  const firstChild = el.firstElementChild;
@@ -864,7 +965,7 @@ var SpreadsheetEditor = ({
864
965
  }
865
966
  return maxW;
866
967
  }, []);
867
- const autoFitColumn = useCallback4((colId, colIndex) => {
968
+ const autoFitColumn = useCallback5((colId, colIndex) => {
868
969
  const col = state.document.columns.find((c) => c.id === colId);
869
970
  if (!col) return;
870
971
  let calculatedWidth = 0;
@@ -901,12 +1002,12 @@ var SpreadsheetEditor = ({
901
1002
  onColumnResize(updatedCol.id, updatedCol.width || 130);
902
1003
  }
903
1004
  }, [state, measureElementContentWidth, onColumnResize]);
904
- const handleResizeDblClick = useCallback4((colId, colIndex, e) => {
1005
+ const handleResizeDblClick = useCallback5((colId, colIndex, e) => {
905
1006
  e.preventDefault();
906
1007
  e.stopPropagation();
907
1008
  autoFitColumn(colId, colIndex);
908
1009
  }, [autoFitColumn]);
909
- const handleHeaderDblClick = useCallback4((colId, colIndex, e) => {
1010
+ const handleHeaderDblClick = useCallback5((colId, colIndex, e) => {
910
1011
  const target = e.currentTarget;
911
1012
  if (target) {
912
1013
  const rect = target.getBoundingClientRect();
@@ -1093,12 +1194,16 @@ export {
1093
1194
  BubbleMenu,
1094
1195
  DirtyTracker,
1095
1196
  EditorContent,
1197
+ HistoryManager2 as HistoryManager,
1096
1198
  SpreadsheetEditor,
1097
1199
  TemplateRenderer,
1098
1200
  createDirtyTracker,
1201
+ createHistoryManager2 as createHistoryManager,
1099
1202
  defaultIsEqual,
1100
1203
  useDismissGuard,
1101
1204
  useEditor2 as useEditor,
1205
+ useHistory,
1206
+ useHistoryShortcuts,
1102
1207
  useNavigationGuard,
1103
1208
  usePromptEditor,
1104
1209
  useSpreadsheetEditor