@pixerate/editor-react 0.3.12 → 0.4.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,10 +31,15 @@ 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
35
  EditorContent: () => EditorContent,
35
36
  SpreadsheetEditor: () => SpreadsheetEditor,
36
37
  TemplateRenderer: () => TemplateRenderer,
38
+ createDirtyTracker: () => import_editor6.createDirtyTracker,
39
+ defaultIsEqual: () => import_editor6.defaultIsEqual,
40
+ useDismissGuard: () => useDismissGuard,
37
41
  useEditor: () => useEditor2,
42
+ useNavigationGuard: () => useNavigationGuard,
38
43
  usePromptEditor: () => usePromptEditor,
39
44
  useSpreadsheetEditor: () => useSpreadsheetEditor
40
45
  });
@@ -263,19 +268,140 @@ function useEditor2(options = {}) {
263
268
  });
264
269
  }
265
270
 
271
+ // src/hooks/useNavigationGuard.ts
272
+ var import_react4 = require("react");
273
+ function useNavigationGuard({
274
+ isDirty,
275
+ enabled = true,
276
+ onNavigate,
277
+ onBlocked
278
+ }) {
279
+ const [showConfirm, setShowConfirm] = (0, import_react4.useState)(false);
280
+ const [pendingUrl, setPendingUrl] = (0, import_react4.useState)(null);
281
+ const onNavigateRef = (0, import_react4.useRef)(onNavigate);
282
+ onNavigateRef.current = onNavigate;
283
+ const onBlockedRef = (0, import_react4.useRef)(onBlocked);
284
+ onBlockedRef.current = onBlocked;
285
+ (0, import_react4.useEffect)(() => {
286
+ if (typeof window === "undefined") return;
287
+ if (!enabled || !isDirty) return;
288
+ const handleBeforeUnload = (e) => {
289
+ e.preventDefault();
290
+ e.returnValue = "";
291
+ };
292
+ window.addEventListener("beforeunload", handleBeforeUnload);
293
+ return () => {
294
+ window.removeEventListener("beforeunload", handleBeforeUnload);
295
+ };
296
+ }, [enabled, isDirty]);
297
+ (0, import_react4.useEffect)(() => {
298
+ if (typeof document === "undefined" || typeof window === "undefined")
299
+ return;
300
+ if (!enabled || !isDirty) return;
301
+ const handleClick = (e) => {
302
+ const target = e.target;
303
+ const anchor = target?.closest?.("a");
304
+ if (!anchor) return;
305
+ if (anchor.target === "_blank") return;
306
+ const isInternal = anchor.host === window.location.host;
307
+ if (!isInternal) return;
308
+ if (anchor.pathname === window.location.pathname && anchor.search === window.location.search) {
309
+ return;
310
+ }
311
+ e.preventDefault();
312
+ e.stopPropagation();
313
+ const href = anchor.href;
314
+ setPendingUrl(href);
315
+ setShowConfirm(true);
316
+ onBlockedRef.current?.(href);
317
+ };
318
+ document.addEventListener("click", handleClick, { capture: true });
319
+ return () => {
320
+ document.removeEventListener("click", handleClick, { capture: true });
321
+ };
322
+ }, [enabled, isDirty]);
323
+ const confirmLeave = (0, import_react4.useCallback)(() => {
324
+ setShowConfirm(false);
325
+ if (pendingUrl) {
326
+ if (onNavigateRef.current) {
327
+ onNavigateRef.current(pendingUrl);
328
+ } else if (typeof window !== "undefined") {
329
+ window.location.href = pendingUrl;
330
+ }
331
+ }
332
+ }, [pendingUrl]);
333
+ const cancelLeave = (0, import_react4.useCallback)(() => {
334
+ setShowConfirm(false);
335
+ setPendingUrl(null);
336
+ }, []);
337
+ return {
338
+ showConfirm,
339
+ setShowConfirm,
340
+ pendingUrl,
341
+ confirmLeave,
342
+ cancelLeave
343
+ };
344
+ }
345
+
346
+ // src/hooks/useDismissGuard.ts
347
+ var import_react5 = require("react");
348
+ function useDismissGuard({
349
+ isDirty,
350
+ enabled = true,
351
+ onDismiss
352
+ }) {
353
+ const [showConfirm, setShowConfirm] = (0, import_react5.useState)(false);
354
+ const onDismissRef = (0, import_react5.useRef)(onDismiss);
355
+ onDismissRef.current = onDismiss;
356
+ const requestDismiss = (0, import_react5.useCallback)(() => {
357
+ if (enabled && isDirty) {
358
+ setShowConfirm(true);
359
+ } else {
360
+ onDismissRef.current?.();
361
+ }
362
+ }, [enabled, isDirty]);
363
+ const confirmDismiss = (0, import_react5.useCallback)(() => {
364
+ setShowConfirm(false);
365
+ onDismissRef.current?.();
366
+ }, []);
367
+ const cancelDismiss = (0, import_react5.useCallback)(() => {
368
+ setShowConfirm(false);
369
+ }, []);
370
+ const handleKeyDown = (0, import_react5.useCallback)(
371
+ (event) => {
372
+ if (event.key === "Escape") {
373
+ if (event.defaultPrevented) return false;
374
+ event.preventDefault();
375
+ requestDismiss();
376
+ return true;
377
+ }
378
+ return false;
379
+ },
380
+ [requestDismiss]
381
+ );
382
+ return {
383
+ showConfirm,
384
+ setShowConfirm,
385
+ requestDismiss,
386
+ confirmDismiss,
387
+ cancelDismiss,
388
+ handleKeyDown
389
+ };
390
+ }
391
+
266
392
  // src/components/EditorContent.tsx
267
- var import_react4 = require("@tiptap/react");
393
+ var import_react6 = require("@tiptap/react");
268
394
  var import_jsx_runtime = require("react/jsx-runtime");
269
395
  var EditorContent = ({
270
396
  className,
271
397
  editor,
272
398
  ...props
273
399
  }) => {
274
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react4.EditorContent, { editor, ...props }) });
400
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react6.EditorContent, { editor, ...props }) });
275
401
  };
276
402
 
277
403
  // src/components/BubbleMenu.tsx
278
- var import_react5 = require("react");
404
+ var import_react7 = require("react");
279
405
  var import_react_dom = require("react-dom");
280
406
  var import_extension_bubble_menu = require("@tiptap/extension-bubble-menu");
281
407
  var BubbleMenu = ({
@@ -287,12 +413,12 @@ var BubbleMenu = ({
287
413
  pluginKey = "bubbleMenu",
288
414
  updateDelay
289
415
  }) => {
290
- const menuEl = (0, import_react5.useRef)(null);
291
- const [mounted, setMounted] = (0, import_react5.useState)(false);
416
+ const menuEl = (0, import_react7.useRef)(null);
417
+ const [mounted, setMounted] = (0, import_react7.useState)(false);
292
418
  if (!menuEl.current && typeof document !== "undefined") {
293
419
  menuEl.current = document.createElement("div");
294
420
  }
295
- (0, import_react5.useEffect)(() => {
421
+ (0, import_react7.useEffect)(() => {
296
422
  if (!editor || !menuEl.current || editor.isDestroyed) {
297
423
  return;
298
424
  }
@@ -323,7 +449,7 @@ var BubbleMenu = ({
323
449
  };
324
450
 
325
451
  // src/components/TemplateRenderer.tsx
326
- var import_react6 = require("react");
452
+ var import_react8 = require("react");
327
453
  var import_editor3 = require("@pixerate/editor");
328
454
  var import_jsx_runtime2 = require("react/jsx-runtime");
329
455
  var TemplateRenderer = ({
@@ -335,11 +461,11 @@ var TemplateRenderer = ({
335
461
  onTemplateClick,
336
462
  onVariableClick
337
463
  }) => {
338
- const displayText = (0, import_react6.useMemo)(() => {
464
+ const displayText = (0, import_react8.useMemo)(() => {
339
465
  if (!resolve || templates.length === 0) return content;
340
466
  return (0, import_editor3.resolveTemplates)(content, templates);
341
467
  }, [content, templates, resolve]);
342
- const tokens = (0, import_react6.useMemo)(() => {
468
+ const tokens = (0, import_react8.useMemo)(() => {
343
469
  return (0, import_editor3.tokenizePrompt)(displayText);
344
470
  }, [displayText]);
345
471
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className, children: tokens.map((token, index) => {
@@ -391,11 +517,14 @@ var TemplateRenderer = ({
391
517
  }) });
392
518
  };
393
519
 
520
+ // src/index.ts
521
+ var import_editor6 = require("@pixerate/editor");
522
+
394
523
  // src/spreadsheet/useSpreadsheetEditor.ts
395
- var import_react7 = require("react");
524
+ var import_react9 = require("react");
396
525
  var import_editor4 = require("@pixerate/editor");
397
526
  function useSpreadsheetEditor(options = {}) {
398
- const [doc, setDoc] = (0, import_react7.useState)(() => ({
527
+ const [doc, setDoc] = (0, import_react9.useState)(() => ({
399
528
  id: options.document?.id || `sheet_${Date.now()}`,
400
529
  name: options.document?.name || "Sheet 1",
401
530
  columns: options.document?.columns || [],
@@ -404,11 +533,11 @@ function useSpreadsheetEditor(options = {}) {
404
533
  createdAt: options.document?.createdAt || Date.now(),
405
534
  updatedAt: options.document?.updatedAt || Date.now()
406
535
  }));
407
- const [activeCell, setActiveCell] = (0, import_react7.useState)(null);
408
- const [selectedRange, setSelectedRange] = (0, import_react7.useState)(null);
409
- const [editingCell, setEditingCell] = (0, import_react7.useState)(null);
410
- const [draftValue, setDraftValue] = (0, import_react7.useState)("");
411
- const controller = (0, import_react7.useMemo)(() => {
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)(() => {
412
541
  return new import_editor4.SpreadsheetController({
413
542
  ...options,
414
543
  onDocumentChange: (updated) => {
@@ -425,82 +554,82 @@ function useSpreadsheetEditor(options = {}) {
425
554
  }
426
555
  });
427
556
  }, []);
428
- const setCellValue = (0, import_react7.useCallback)((rowId, colId, raw) => {
557
+ const setCellValue = (0, import_react9.useCallback)((rowId, colId, raw) => {
429
558
  controller.setCellValue(rowId, colId, raw);
430
559
  setDoc({ ...controller.document });
431
560
  }, [controller]);
432
- const selectCell = (0, import_react7.useCallback)((row, col, extendSelection = false) => {
561
+ const selectCell = (0, import_react9.useCallback)((row, col, extendSelection = false) => {
433
562
  controller.selectCell(row, col, extendSelection);
434
563
  setActiveCell(controller.activeCell);
435
564
  setSelectedRange(controller.selectedRange);
436
565
  }, [controller]);
437
- const selectRange = (0, import_react7.useCallback)((range) => {
566
+ const selectRange = (0, import_react9.useCallback)((range) => {
438
567
  controller.selectRange(range);
439
568
  setSelectedRange(controller.selectedRange);
440
569
  }, [controller]);
441
- const startEditing = (0, import_react7.useCallback)((row, col, initialVal) => {
570
+ const startEditing = (0, import_react9.useCallback)((row, col, initialVal) => {
442
571
  controller.startEditing(row, col, initialVal);
443
572
  setActiveCell(controller.activeCell);
444
573
  setEditingCell(controller.editingCell);
445
574
  setDraftValue(controller.draftValue);
446
575
  }, [controller]);
447
- const commitEditing = (0, import_react7.useCallback)((val) => {
576
+ const commitEditing = (0, import_react9.useCallback)((val) => {
448
577
  controller.commitEditing(val);
449
578
  setEditingCell(null);
450
579
  setDraftValue("");
451
580
  setDoc({ ...controller.document });
452
581
  }, [controller]);
453
- const cancelEditing = (0, import_react7.useCallback)(() => {
582
+ const cancelEditing = (0, import_react9.useCallback)(() => {
454
583
  controller.cancelEditing();
455
584
  setEditingCell(null);
456
585
  setDraftValue("");
457
586
  }, [controller]);
458
- const moveCursor = (0, import_react7.useCallback)((dir, extend = false) => {
587
+ const moveCursor = (0, import_react9.useCallback)((dir, extend = false) => {
459
588
  controller.moveCursor(dir, extend);
460
589
  setActiveCell(controller.activeCell);
461
590
  setSelectedRange(controller.selectedRange);
462
591
  }, [controller]);
463
- const insertColumn = (0, import_react7.useCallback)((index, config) => {
592
+ const insertColumn = (0, import_react9.useCallback)((index, config) => {
464
593
  controller.insertColumn(index, config);
465
594
  setDoc({ ...controller.document });
466
595
  }, [controller]);
467
- const deleteColumn = (0, import_react7.useCallback)((colId) => {
596
+ const deleteColumn = (0, import_react9.useCallback)((colId) => {
468
597
  controller.deleteColumn(colId);
469
598
  setDoc({ ...controller.document });
470
599
  }, [controller]);
471
- const insertRow = (0, import_react7.useCallback)((index, config) => {
600
+ const insertRow = (0, import_react9.useCallback)((index, config) => {
472
601
  controller.insertRow(index, config);
473
602
  setDoc({ ...controller.document });
474
603
  }, [controller]);
475
- const deleteRow = (0, import_react7.useCallback)((rowId) => {
604
+ const deleteRow = (0, import_react9.useCallback)((rowId) => {
476
605
  controller.deleteRow(rowId);
477
606
  setDoc({ ...controller.document });
478
607
  }, [controller]);
479
- const setColumnWidth = (0, import_react7.useCallback)((colId, width) => {
608
+ const setColumnWidth = (0, import_react9.useCallback)((colId, width) => {
480
609
  controller.setColumnWidth(colId, width);
481
610
  setDoc({ ...controller.document });
482
611
  }, [controller]);
483
- const autoFitColumnWidth = (0, import_react7.useCallback)((colId, customWidth) => {
612
+ const autoFitColumnWidth = (0, import_react9.useCallback)((colId, customWidth) => {
484
613
  controller.autoFitColumnWidth(colId, customWidth);
485
614
  setDoc({ ...controller.document });
486
615
  }, [controller]);
487
- const registerDataSource = (0, import_react7.useCallback)((ds) => {
616
+ const registerDataSource = (0, import_react9.useCallback)((ds) => {
488
617
  controller.registerDataSource(ds);
489
618
  setDoc({ ...controller.document });
490
619
  }, [controller]);
491
- const setPrimaryDataSource = (0, import_react7.useCallback)((id) => {
620
+ const setPrimaryDataSource = (0, import_react9.useCallback)((id) => {
492
621
  controller.setPrimaryDataSource(id);
493
622
  setDoc({ ...controller.document });
494
623
  }, [controller]);
495
- const recalculateAll = (0, import_react7.useCallback)(() => {
624
+ const recalculateAll = (0, import_react9.useCallback)(() => {
496
625
  controller.recalculateAll();
497
626
  setDoc({ ...controller.document });
498
627
  }, [controller]);
499
- const undo = (0, import_react7.useCallback)(() => {
628
+ const undo = (0, import_react9.useCallback)(() => {
500
629
  controller.undo();
501
630
  setDoc({ ...controller.document });
502
631
  }, [controller]);
503
- const redo = (0, import_react7.useCallback)(() => {
632
+ const redo = (0, import_react9.useCallback)(() => {
504
633
  controller.redo();
505
634
  setDoc({ ...controller.document });
506
635
  }, [controller]);
@@ -553,7 +682,7 @@ function useSpreadsheetEditor(options = {}) {
553
682
  }
554
683
 
555
684
  // src/spreadsheet/SpreadsheetEditor.tsx
556
- var import_react8 = require("react");
685
+ var import_react10 = require("react");
557
686
  var import_editor5 = require("@pixerate/editor");
558
687
  var import_jsx_runtime3 = require("react/jsx-runtime");
559
688
  var SpreadsheetEditor = ({
@@ -566,36 +695,36 @@ var SpreadsheetEditor = ({
566
695
  }) => {
567
696
  const defaultState = useSpreadsheetEditor();
568
697
  const state = externalState || defaultState;
569
- const gridRef = (0, import_react8.useRef)(null);
570
- const [resizingColId, setResizingColId] = (0, import_react8.useState)(null);
571
- const [hoveredColId, setHoveredColId] = (0, import_react8.useState)(null);
572
- const [resizeStartX, setResizeStartX] = (0, import_react8.useState)(0);
573
- const [resizeStartWidth, setResizeStartWidth] = (0, import_react8.useState)(0);
574
- const activeRawValue = (0, import_react8.useMemo)(() => {
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)(() => {
575
704
  if (!state.activeCell) return "";
576
705
  const row = state.document.rows[state.activeCell.row];
577
706
  const col = state.document.columns[state.activeCell.col];
578
707
  if (!row || !col) return "";
579
708
  return state.getCell(row.id, col.id).raw;
580
709
  }, [state.activeCell, state.document]);
581
- const coordLabel = (0, import_react8.useMemo)(() => {
710
+ const coordLabel = (0, import_react10.useMemo)(() => {
582
711
  if (!state.activeCell) return "--";
583
712
  const colName = (0, import_editor5.indexToColName)(state.activeCell.col);
584
713
  return `${colName}${state.activeCell.row + 1}`;
585
714
  }, [state.activeCell]);
586
- const handleCellClick = (0, import_react8.useCallback)((rIdx, cIdx, e) => {
715
+ const handleCellClick = (0, import_react10.useCallback)((rIdx, cIdx, e) => {
587
716
  if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {
588
717
  state.commitEditing();
589
718
  }
590
719
  state.selectCell(rIdx, cIdx, e.shiftKey);
591
720
  }, [state]);
592
- const handleCellDblClick = (0, import_react8.useCallback)((rIdx, cIdx) => {
721
+ const handleCellDblClick = (0, import_react10.useCallback)((rIdx, cIdx) => {
593
722
  if (readOnly) return;
594
723
  const col = state.document.columns[cIdx];
595
724
  if (col?.readOnly) return;
596
725
  state.startEditing(rIdx, cIdx);
597
726
  }, [readOnly, state]);
598
- const handleKeyDown = (0, import_react8.useCallback)((e) => {
727
+ const handleKeyDown = (0, import_react10.useCallback)((e) => {
599
728
  if (state.editingCell) {
600
729
  if (e.key === "Enter") {
601
730
  e.preventDefault();
@@ -659,7 +788,7 @@ var SpreadsheetEditor = ({
659
788
  }
660
789
  }
661
790
  }, [readOnly, state]);
662
- (0, import_react8.useEffect)(() => {
791
+ (0, import_react10.useEffect)(() => {
663
792
  if (!resizingColId) return;
664
793
  if (typeof document !== "undefined") {
665
794
  document.body.style.cursor = "col-resize";
@@ -713,7 +842,7 @@ var SpreadsheetEditor = ({
713
842
  window.removeEventListener("mouseup", handleMouseUp);
714
843
  };
715
844
  }, [resizingColId, resizeStartX, resizeStartWidth, state, onColumnResize]);
716
- const measureElementContentWidth = (0, import_react8.useCallback)((el, container) => {
845
+ const measureElementContentWidth = (0, import_react10.useCallback)((el, container) => {
717
846
  if (typeof document === "undefined") return 0;
718
847
  let maxW = el.scrollWidth || 0;
719
848
  const firstChild = el.firstElementChild;
@@ -761,7 +890,7 @@ var SpreadsheetEditor = ({
761
890
  }
762
891
  return maxW;
763
892
  }, []);
764
- const autoFitColumn = (0, import_react8.useCallback)((colId, colIndex) => {
893
+ const autoFitColumn = (0, import_react10.useCallback)((colId, colIndex) => {
765
894
  const col = state.document.columns.find((c) => c.id === colId);
766
895
  if (!col) return;
767
896
  let calculatedWidth = 0;
@@ -798,12 +927,12 @@ var SpreadsheetEditor = ({
798
927
  onColumnResize(updatedCol.id, updatedCol.width || 130);
799
928
  }
800
929
  }, [state, measureElementContentWidth, onColumnResize]);
801
- const handleResizeDblClick = (0, import_react8.useCallback)((colId, colIndex, e) => {
930
+ const handleResizeDblClick = (0, import_react10.useCallback)((colId, colIndex, e) => {
802
931
  e.preventDefault();
803
932
  e.stopPropagation();
804
933
  autoFitColumn(colId, colIndex);
805
934
  }, [autoFitColumn]);
806
- const handleHeaderDblClick = (0, import_react8.useCallback)((colId, colIndex, e) => {
935
+ const handleHeaderDblClick = (0, import_react10.useCallback)((colId, colIndex, e) => {
807
936
  const target = e.currentTarget;
808
937
  if (target) {
809
938
  const rect = target.getBoundingClientRect();
@@ -989,10 +1118,15 @@ var SpreadsheetEditor = ({
989
1118
  // Annotate the CommonJS export names for ESM import in node:
990
1119
  0 && (module.exports = {
991
1120
  BubbleMenu,
1121
+ DirtyTracker,
992
1122
  EditorContent,
993
1123
  SpreadsheetEditor,
994
1124
  TemplateRenderer,
1125
+ createDirtyTracker,
1126
+ defaultIsEqual,
1127
+ useDismissGuard,
995
1128
  useEditor,
1129
+ useNavigationGuard,
996
1130
  usePromptEditor,
997
1131
  useSpreadsheetEditor
998
1132
  });