@pixerate/editor-react 0.14.0 → 0.16.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 +6 -1
- package/dist/canvas/index.cjs +352 -118
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +112 -8
- package/dist/canvas/index.d.ts +112 -8
- package/dist/canvas/index.js +258 -19
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-4ZC2WCUO.js +196 -0
- package/dist/chunk-4ZC2WCUO.js.map +1 -0
- package/dist/chunk-7SPRQZ6H.js +216 -0
- package/dist/chunk-7SPRQZ6H.js.map +1 -0
- package/dist/{chunk-25S5EHH4.js → chunk-FYIPXHAE.js} +22 -13
- package/dist/chunk-FYIPXHAE.js.map +1 -0
- package/dist/{chunk-TL27COKM.js → chunk-XTFR3IMK.js} +683 -286
- package/dist/chunk-XTFR3IMK.js.map +1 -0
- package/dist/chunk-XWFU2CSG.js +167 -0
- package/dist/chunk-XWFU2CSG.js.map +1 -0
- package/dist/commands/index.cjs +232 -0
- package/dist/commands/index.cjs.map +1 -0
- package/dist/commands/index.d.cts +69 -0
- package/dist/commands/index.d.ts +69 -0
- package/dist/commands/index.js +13 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/generation/index.cjs +235 -0
- package/dist/generation/index.cjs.map +1 -0
- package/dist/generation/index.d.cts +60 -0
- package/dist/generation/index.d.ts +60 -0
- package/dist/generation/index.js +13 -0
- package/dist/generation/index.js.map +1 -0
- package/dist/image-editor/index.cjs +688 -299
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +65 -5
- package/dist/image-editor/index.d.ts +65 -5
- package/dist/image-editor/index.js +13 -3
- package/dist/index.cjs +2200 -683
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +201 -23
- package/dist/index.d.ts +201 -23
- package/dist/index.js +743 -129
- package/dist/index.js.map +1 -1
- package/dist/persistence/index.cjs +191 -0
- package/dist/persistence/index.cjs.map +1 -0
- package/dist/persistence/index.d.cts +77 -0
- package/dist/persistence/index.d.ts +77 -0
- package/dist/persistence/index.js +9 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/spreadsheet/index.cjs +17 -10
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +9 -7
- package/dist/spreadsheet/index.d.ts +9 -7
- package/dist/spreadsheet/index.js +1 -1
- package/package.json +26 -2
- package/dist/chunk-25S5EHH4.js.map +0 -1
- package/dist/chunk-TL27COKM.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -6,11 +6,32 @@ import {
|
|
|
6
6
|
useFillHandle,
|
|
7
7
|
useSpreadsheetClipboard,
|
|
8
8
|
useSpreadsheetEditor
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FYIPXHAE.js";
|
|
10
10
|
import {
|
|
11
|
+
AdjustmentLayersPanel,
|
|
12
|
+
ControlSlider,
|
|
13
|
+
CurvesEditor,
|
|
14
|
+
Histogram,
|
|
11
15
|
ImageEditor,
|
|
12
|
-
useImageEditor
|
|
13
|
-
|
|
16
|
+
useImageEditor,
|
|
17
|
+
useImageHistogram
|
|
18
|
+
} from "./chunk-XTFR3IMK.js";
|
|
19
|
+
import {
|
|
20
|
+
CommandPalette,
|
|
21
|
+
useCommandPalette,
|
|
22
|
+
useCommandShortcuts,
|
|
23
|
+
useRegisterCommands
|
|
24
|
+
} from "./chunk-4ZC2WCUO.js";
|
|
25
|
+
import {
|
|
26
|
+
RecoveryPrompt,
|
|
27
|
+
useAutosave
|
|
28
|
+
} from "./chunk-XWFU2CSG.js";
|
|
29
|
+
import {
|
|
30
|
+
GenerationSettings,
|
|
31
|
+
JobProgress,
|
|
32
|
+
useGenerationPlan,
|
|
33
|
+
useJobProgress
|
|
34
|
+
} from "./chunk-7SPRQZ6H.js";
|
|
14
35
|
|
|
15
36
|
// src/hooks/usePromptEditor.ts
|
|
16
37
|
import { useMemo, useEffect, useRef } from "react";
|
|
@@ -406,7 +427,7 @@ function useDismissGuard({
|
|
|
406
427
|
}
|
|
407
428
|
|
|
408
429
|
// src/hooks/useHistory.ts
|
|
409
|
-
import { useSyncExternalStore, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
430
|
+
import { useSyncExternalStore, useRef as useRef4, useCallback as useCallback3, useMemo as useMemo2 } from "react";
|
|
410
431
|
import {
|
|
411
432
|
HistoryManager,
|
|
412
433
|
createHistoryManager
|
|
@@ -428,6 +449,7 @@ function useHistory(managerOrOptions) {
|
|
|
428
449
|
() => manager.getState(),
|
|
429
450
|
() => manager.getState()
|
|
430
451
|
);
|
|
452
|
+
const entries = useMemo2(() => manager.getEntries(), [manager, state]);
|
|
431
453
|
const undo = useCallback3(() => manager.undo(), [manager]);
|
|
432
454
|
const redo = useCallback3(() => manager.redo(), [manager]);
|
|
433
455
|
const clear = useCallback3(() => manager.clear(), [manager]);
|
|
@@ -443,60 +465,105 @@ function useHistory(managerOrOptions) {
|
|
|
443
465
|
(name, fn) => manager.batch(name, fn),
|
|
444
466
|
[manager]
|
|
445
467
|
);
|
|
468
|
+
const goTo = useCallback3((index) => manager.goTo(index), [manager]);
|
|
469
|
+
const mark = useCallback3(() => manager.mark(), [manager]);
|
|
470
|
+
const revertTo = useCallback3(
|
|
471
|
+
(m) => manager.revertTo(m),
|
|
472
|
+
[manager]
|
|
473
|
+
);
|
|
474
|
+
const beginGesture = useCallback3(
|
|
475
|
+
(key) => manager.beginGesture(key),
|
|
476
|
+
[manager]
|
|
477
|
+
);
|
|
478
|
+
const endGesture = useCallback3(() => manager.endGesture(), [manager]);
|
|
446
479
|
return {
|
|
447
480
|
...state,
|
|
448
481
|
manager,
|
|
482
|
+
entries,
|
|
449
483
|
undo,
|
|
450
484
|
redo,
|
|
451
485
|
clear,
|
|
452
486
|
execute,
|
|
453
487
|
executeMerged,
|
|
454
|
-
batch
|
|
488
|
+
batch,
|
|
489
|
+
goTo,
|
|
490
|
+
mark,
|
|
491
|
+
revertTo,
|
|
492
|
+
beginGesture,
|
|
493
|
+
endGesture
|
|
455
494
|
};
|
|
456
495
|
}
|
|
457
496
|
|
|
497
|
+
// src/hooks/useHistoryDirty.ts
|
|
498
|
+
import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef5, useState as useState3, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
499
|
+
import {
|
|
500
|
+
DirtyTracker,
|
|
501
|
+
bindDirtyToHistory
|
|
502
|
+
} from "@pixerate/editor";
|
|
503
|
+
function useHistoryDirty(options) {
|
|
504
|
+
const getValueRef = useRef5(options.getValue);
|
|
505
|
+
getValueRef.current = options.getValue;
|
|
506
|
+
const [tracker] = useState3(
|
|
507
|
+
() => options.tracker ?? new DirtyTracker(options.getValue(), {
|
|
508
|
+
isEqual: options.isEqual,
|
|
509
|
+
normalize: options.normalize
|
|
510
|
+
})
|
|
511
|
+
);
|
|
512
|
+
const bindingRef = useRef5(null);
|
|
513
|
+
useEffect3(() => {
|
|
514
|
+
const binding = bindDirtyToHistory({
|
|
515
|
+
history: options.history,
|
|
516
|
+
getValue: () => getValueRef.current(),
|
|
517
|
+
tracker
|
|
518
|
+
});
|
|
519
|
+
bindingRef.current = binding;
|
|
520
|
+
return () => {
|
|
521
|
+
binding.destroy();
|
|
522
|
+
if (bindingRef.current === binding) bindingRef.current = null;
|
|
523
|
+
};
|
|
524
|
+
}, [options.history, tracker]);
|
|
525
|
+
const isDirty = useSyncExternalStore2(
|
|
526
|
+
useCallback4((onChange) => tracker.subscribe(onChange), [tracker]),
|
|
527
|
+
() => tracker.dirty,
|
|
528
|
+
() => tracker.dirty
|
|
529
|
+
);
|
|
530
|
+
const markClean = useCallback4(
|
|
531
|
+
() => tracker.markClean(getValueRef.current()),
|
|
532
|
+
[tracker]
|
|
533
|
+
);
|
|
534
|
+
const suppress = useCallback4(
|
|
535
|
+
(fn) => bindingRef.current ? bindingRef.current.suppress(fn) : tracker.suppress(fn),
|
|
536
|
+
[tracker]
|
|
537
|
+
);
|
|
538
|
+
const refresh = useCallback4(
|
|
539
|
+
() => tracker.update(getValueRef.current()),
|
|
540
|
+
[tracker]
|
|
541
|
+
);
|
|
542
|
+
return { isDirty, markClean, suppress, refresh, tracker };
|
|
543
|
+
}
|
|
544
|
+
|
|
458
545
|
// src/hooks/useHistoryShortcuts.ts
|
|
459
|
-
import { useEffect as
|
|
546
|
+
import { useEffect as useEffect4 } from "react";
|
|
547
|
+
import { matchHistoryShortcut } from "@pixerate/editor/commands";
|
|
460
548
|
function useHistoryShortcuts(manager, options = {}) {
|
|
461
549
|
const {
|
|
462
550
|
enabled = true,
|
|
463
551
|
target,
|
|
464
552
|
ignoreEditableElements = true
|
|
465
553
|
} = options;
|
|
466
|
-
|
|
554
|
+
useEffect4(() => {
|
|
467
555
|
if (!enabled) return;
|
|
468
556
|
const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
|
|
469
557
|
if (!eventTarget) return;
|
|
470
558
|
const handleKeyDown = (event) => {
|
|
471
559
|
const e = event;
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const isInput = tagName === "input" || tagName === "textarea";
|
|
480
|
-
const isContentEditable = targetEl.isContentEditable || targetEl.getAttribute?.("contenteditable") === "true";
|
|
481
|
-
if (isInput || isContentEditable) {
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
const key = e.key.toLowerCase();
|
|
487
|
-
if (key === "z" && !e.shiftKey) {
|
|
488
|
-
if (manager.getState().canUndo) {
|
|
489
|
-
e.preventDefault();
|
|
490
|
-
manager.undo();
|
|
491
|
-
}
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
const isRedoKey = key === "z" && e.shiftKey || !isMac && key === "y" && !e.shiftKey;
|
|
495
|
-
if (isRedoKey) {
|
|
496
|
-
if (manager.getState().canRedo) {
|
|
497
|
-
e.preventDefault();
|
|
498
|
-
manager.redo();
|
|
499
|
-
}
|
|
560
|
+
const action = matchHistoryShortcut(e, { allowInEditable: !ignoreEditableElements });
|
|
561
|
+
if (action === "undo" && manager.getState().canUndo) {
|
|
562
|
+
e.preventDefault();
|
|
563
|
+
manager.undo();
|
|
564
|
+
} else if (action === "redo" && manager.getState().canRedo) {
|
|
565
|
+
e.preventDefault();
|
|
566
|
+
manager.redo();
|
|
500
567
|
}
|
|
501
568
|
};
|
|
502
569
|
eventTarget.addEventListener("keydown", handleKeyDown);
|
|
@@ -507,24 +574,24 @@ function useHistoryShortcuts(manager, options = {}) {
|
|
|
507
574
|
}
|
|
508
575
|
|
|
509
576
|
// src/hooks/useFileImport.ts
|
|
510
|
-
import { useEffect as
|
|
577
|
+
import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef6, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
511
578
|
import {
|
|
512
579
|
FileImportController
|
|
513
580
|
} from "@pixerate/editor";
|
|
514
581
|
function useFileImport(editor, options = {}) {
|
|
515
|
-
const editorRef =
|
|
582
|
+
const editorRef = useRef6(editor);
|
|
516
583
|
editorRef.current = editor;
|
|
517
|
-
const controller =
|
|
584
|
+
const controller = useMemo3(
|
|
518
585
|
() => new FileImportController(() => {
|
|
519
586
|
const current = editorRef.current;
|
|
520
587
|
return current && !current.isDestroyed ? current : null;
|
|
521
588
|
}, options),
|
|
522
589
|
[]
|
|
523
590
|
);
|
|
524
|
-
|
|
591
|
+
useEffect5(() => {
|
|
525
592
|
controller.setOptions(options);
|
|
526
593
|
});
|
|
527
|
-
const state =
|
|
594
|
+
const state = useSyncExternalStore3(controller.subscribe, controller.getState, controller.getState);
|
|
528
595
|
return {
|
|
529
596
|
...state,
|
|
530
597
|
accept: controller.accept,
|
|
@@ -534,9 +601,9 @@ function useFileImport(editor, options = {}) {
|
|
|
534
601
|
}
|
|
535
602
|
|
|
536
603
|
// src/hooks/useAgentToolProvider.ts
|
|
537
|
-
import { useEffect as
|
|
604
|
+
import { useEffect as useEffect6 } from "react";
|
|
538
605
|
function useAgentToolProvider(registry, provider) {
|
|
539
|
-
|
|
606
|
+
useEffect6(() => {
|
|
540
607
|
if (!registry || !provider) return;
|
|
541
608
|
return registry.register(provider);
|
|
542
609
|
}, [registry, provider]);
|
|
@@ -556,7 +623,7 @@ var EditorContent = ({
|
|
|
556
623
|
};
|
|
557
624
|
|
|
558
625
|
// src/components/BubbleMenu.tsx
|
|
559
|
-
import { useEffect as
|
|
626
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState4 } from "react";
|
|
560
627
|
import { createPortal } from "react-dom";
|
|
561
628
|
import {
|
|
562
629
|
BubbleMenuPlugin
|
|
@@ -570,12 +637,12 @@ var BubbleMenu = ({
|
|
|
570
637
|
pluginKey = "bubbleMenu",
|
|
571
638
|
updateDelay
|
|
572
639
|
}) => {
|
|
573
|
-
const menuEl =
|
|
574
|
-
const [mounted, setMounted] =
|
|
640
|
+
const menuEl = useRef7(null);
|
|
641
|
+
const [mounted, setMounted] = useState4(false);
|
|
575
642
|
if (!menuEl.current && typeof document !== "undefined") {
|
|
576
643
|
menuEl.current = document.createElement("div");
|
|
577
644
|
}
|
|
578
|
-
|
|
645
|
+
useEffect7(() => {
|
|
579
646
|
if (!editor || !menuEl.current || editor.isDestroyed) {
|
|
580
647
|
return;
|
|
581
648
|
}
|
|
@@ -606,13 +673,14 @@ var BubbleMenu = ({
|
|
|
606
673
|
};
|
|
607
674
|
|
|
608
675
|
// src/components/TemplateRenderer.tsx
|
|
609
|
-
import { useMemo as
|
|
676
|
+
import { useMemo as useMemo4 } from "react";
|
|
610
677
|
import {
|
|
678
|
+
describeConditionalTag,
|
|
611
679
|
evaluatePromptTokens,
|
|
680
|
+
formatConditionalTag,
|
|
612
681
|
resolveTemplates
|
|
613
682
|
} from "@pixerate/editor";
|
|
614
683
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
615
|
-
var CONDITIONAL_PREFIX = { if: "?", unless: "!", end: "/" };
|
|
616
684
|
var TemplateRenderer = ({
|
|
617
685
|
content,
|
|
618
686
|
templates = [],
|
|
@@ -624,11 +692,11 @@ var TemplateRenderer = ({
|
|
|
624
692
|
onTemplateClick,
|
|
625
693
|
onVariableClick
|
|
626
694
|
}) => {
|
|
627
|
-
const displayText =
|
|
695
|
+
const displayText = useMemo4(() => {
|
|
628
696
|
if (!resolve || templates.length === 0) return content;
|
|
629
697
|
return resolveTemplates(content, templates, { bindings });
|
|
630
698
|
}, [content, templates, resolve, bindings]);
|
|
631
|
-
const tokens =
|
|
699
|
+
const tokens = useMemo4(() => {
|
|
632
700
|
return evaluatePromptTokens(displayText, values);
|
|
633
701
|
}, [displayText, values]);
|
|
634
702
|
return /* @__PURE__ */ jsx2("div", { className, children: tokens.map((token, index) => {
|
|
@@ -695,8 +763,8 @@ var TemplateRenderer = ({
|
|
|
695
763
|
{
|
|
696
764
|
"data-conditional": token.conditional,
|
|
697
765
|
className: "inline-flex items-center px-1 py-0.5 mx-0.5 text-xs font-medium rounded-md border border-amber-400/40 bg-amber-400/15 text-amber-700 dark:text-amber-300",
|
|
698
|
-
title: token
|
|
699
|
-
children:
|
|
766
|
+
title: describeConditionalTag(token),
|
|
767
|
+
children: formatConditionalTag(token)
|
|
700
768
|
},
|
|
701
769
|
index
|
|
702
770
|
);
|
|
@@ -717,7 +785,7 @@ var TemplateRenderer = ({
|
|
|
717
785
|
};
|
|
718
786
|
|
|
719
787
|
// src/components/VariableForm.tsx
|
|
720
|
-
import { useId, useMemo as
|
|
788
|
+
import { useId, useMemo as useMemo5, useState as useState5 } from "react";
|
|
721
789
|
import {
|
|
722
790
|
compactVariableValues,
|
|
723
791
|
getVariableFormFields
|
|
@@ -733,11 +801,11 @@ var VariableForm = ({
|
|
|
733
801
|
className = "flex flex-col gap-3 text-sm"
|
|
734
802
|
}) => {
|
|
735
803
|
const idPrefix = useId();
|
|
736
|
-
const [internal, setInternal] =
|
|
804
|
+
const [internal, setInternal] = useState5(
|
|
737
805
|
() => defaultValues ?? {}
|
|
738
806
|
);
|
|
739
807
|
const entered = values ?? internal;
|
|
740
|
-
const fields =
|
|
808
|
+
const fields = useMemo5(
|
|
741
809
|
() => getVariableFormFields(content, { templates, bindings }),
|
|
742
810
|
[content, templates, bindings]
|
|
743
811
|
);
|
|
@@ -804,17 +872,312 @@ var VariableForm = ({
|
|
|
804
872
|
}) });
|
|
805
873
|
};
|
|
806
874
|
|
|
875
|
+
// src/components/MergePreview.tsx
|
|
876
|
+
import { useId as useId2, useState as useState7 } from "react";
|
|
877
|
+
|
|
878
|
+
// src/hooks/useMergePreview.ts
|
|
879
|
+
import { useCallback as useCallback5, useMemo as useMemo6, useState as useState6 } from "react";
|
|
880
|
+
import {
|
|
881
|
+
extractVariables,
|
|
882
|
+
matchFields,
|
|
883
|
+
mergeRecords,
|
|
884
|
+
parseDataSource,
|
|
885
|
+
recordToValues,
|
|
886
|
+
serializeMergeOutputs
|
|
887
|
+
} from "@pixerate/editor";
|
|
888
|
+
function useMergePreview(options) {
|
|
889
|
+
const { template, templates, bindings, parseOptions } = options;
|
|
890
|
+
const [sourceText, setSourceTextState] = useState6(options.initialSource ?? "");
|
|
891
|
+
const [overrides, setOverrides] = useState6({});
|
|
892
|
+
const [index, setIndexState] = useState6(0);
|
|
893
|
+
const [result, setResult] = useState6(null);
|
|
894
|
+
const source = useMemo6(
|
|
895
|
+
() => parseDataSource(sourceText, parseOptions),
|
|
896
|
+
[sourceText, parseOptions]
|
|
897
|
+
);
|
|
898
|
+
const variables = useMemo6(
|
|
899
|
+
() => extractVariables(template, { templates, bindings }).map((v) => v.name),
|
|
900
|
+
[template, templates, bindings]
|
|
901
|
+
);
|
|
902
|
+
const mapping = useMemo6(() => {
|
|
903
|
+
const merged = {
|
|
904
|
+
...matchFields(variables, source.fields).mapping
|
|
905
|
+
};
|
|
906
|
+
for (const [variable, field] of Object.entries(overrides)) {
|
|
907
|
+
if (variables.includes(variable) && (field === null || source.fields.includes(field))) {
|
|
908
|
+
merged[variable] = field;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
return merged;
|
|
912
|
+
}, [variables, source.fields, overrides]);
|
|
913
|
+
const count = source.records.length;
|
|
914
|
+
const current = count === 0 ? 0 : Math.min(index, count - 1);
|
|
915
|
+
const record = source.records[current];
|
|
916
|
+
const values = useMemo6(
|
|
917
|
+
() => record ? recordToValues(record, mapping) : {},
|
|
918
|
+
[record, mapping]
|
|
919
|
+
);
|
|
920
|
+
const setSourceText = useCallback5((text) => {
|
|
921
|
+
setSourceTextState(text);
|
|
922
|
+
setIndexState(0);
|
|
923
|
+
setResult(null);
|
|
924
|
+
}, []);
|
|
925
|
+
const loadFile = useCallback5(
|
|
926
|
+
async (file) => setSourceText(await file.text()),
|
|
927
|
+
[setSourceText]
|
|
928
|
+
);
|
|
929
|
+
const setIndex = useCallback5(
|
|
930
|
+
(next) => setIndexState(Math.max(0, Math.min(next, count - 1))),
|
|
931
|
+
[count]
|
|
932
|
+
);
|
|
933
|
+
const setFieldMapping = useCallback5((variable, field) => {
|
|
934
|
+
setOverrides((previous) => ({ ...previous, [variable]: field }));
|
|
935
|
+
setResult(null);
|
|
936
|
+
}, []);
|
|
937
|
+
const resetMapping = useCallback5(() => setOverrides({}), []);
|
|
938
|
+
const merge = useCallback5(() => {
|
|
939
|
+
const merged = mergeRecords(template, source, {
|
|
940
|
+
templates,
|
|
941
|
+
bindings,
|
|
942
|
+
mapping,
|
|
943
|
+
skipIf: options.skipIf,
|
|
944
|
+
separator: options.separator,
|
|
945
|
+
maxOutputs: options.maxOutputs
|
|
946
|
+
});
|
|
947
|
+
setResult(merged);
|
|
948
|
+
return merged;
|
|
949
|
+
}, [template, source, templates, bindings, mapping, options.skipIf, options.separator, options.maxOutputs]);
|
|
950
|
+
const serialize = useCallback5(
|
|
951
|
+
(format) => result ? serializeMergeOutputs(result.outputs, format, options.separator) : "",
|
|
952
|
+
[result, options.separator]
|
|
953
|
+
);
|
|
954
|
+
return {
|
|
955
|
+
sourceText,
|
|
956
|
+
setSourceText,
|
|
957
|
+
loadFile,
|
|
958
|
+
source,
|
|
959
|
+
variables,
|
|
960
|
+
mapping,
|
|
961
|
+
setFieldMapping,
|
|
962
|
+
resetMapping,
|
|
963
|
+
index: current,
|
|
964
|
+
count,
|
|
965
|
+
setIndex,
|
|
966
|
+
next: () => setIndex(current + 1),
|
|
967
|
+
prev: () => setIndex(current - 1),
|
|
968
|
+
record,
|
|
969
|
+
values,
|
|
970
|
+
merge,
|
|
971
|
+
result,
|
|
972
|
+
serialize
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// src/components/MergePreview.tsx
|
|
977
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
978
|
+
function downloadText(text, fileName, type) {
|
|
979
|
+
if (typeof document === "undefined" || typeof URL.createObjectURL !== "function") {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
const url = URL.createObjectURL(new Blob([text], { type }));
|
|
983
|
+
const link = document.createElement("a");
|
|
984
|
+
link.href = url;
|
|
985
|
+
link.download = fileName;
|
|
986
|
+
link.click();
|
|
987
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
988
|
+
}
|
|
989
|
+
var MergePreview = ({
|
|
990
|
+
content,
|
|
991
|
+
templates,
|
|
992
|
+
bindings,
|
|
993
|
+
templateColorMap,
|
|
994
|
+
defaultSource,
|
|
995
|
+
parseOptions,
|
|
996
|
+
skipIf,
|
|
997
|
+
separator,
|
|
998
|
+
maxOutputs,
|
|
999
|
+
onMerge,
|
|
1000
|
+
downloadName = "merged",
|
|
1001
|
+
className = "flex flex-col gap-3 text-sm"
|
|
1002
|
+
}) => {
|
|
1003
|
+
const id = useId2();
|
|
1004
|
+
const merge = useMergePreview({
|
|
1005
|
+
template: content,
|
|
1006
|
+
templates,
|
|
1007
|
+
bindings,
|
|
1008
|
+
initialSource: defaultSource,
|
|
1009
|
+
parseOptions,
|
|
1010
|
+
skipIf,
|
|
1011
|
+
separator,
|
|
1012
|
+
maxOutputs
|
|
1013
|
+
});
|
|
1014
|
+
const [copied, setCopied] = useState7(false);
|
|
1015
|
+
const { source, result } = merge;
|
|
1016
|
+
const copy = async () => {
|
|
1017
|
+
try {
|
|
1018
|
+
await navigator.clipboard.writeText(merge.serialize("text"));
|
|
1019
|
+
setCopied(true);
|
|
1020
|
+
} catch {
|
|
1021
|
+
setCopied(false);
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
return /* @__PURE__ */ jsxs3("div", { className, "data-merge-preview": "", children: [
|
|
1025
|
+
/* @__PURE__ */ jsxs3("label", { htmlFor: `${id}-source`, className: "flex flex-col gap-1", children: [
|
|
1026
|
+
/* @__PURE__ */ jsx4("span", { className: "font-medium", children: "Data source (CSV, TSV or JSON)" }),
|
|
1027
|
+
/* @__PURE__ */ jsx4(
|
|
1028
|
+
"textarea",
|
|
1029
|
+
{
|
|
1030
|
+
id: `${id}-source`,
|
|
1031
|
+
"data-merge-source": "",
|
|
1032
|
+
value: merge.sourceText,
|
|
1033
|
+
rows: 5,
|
|
1034
|
+
spellCheck: false,
|
|
1035
|
+
onChange: (event) => merge.setSourceText(event.target.value),
|
|
1036
|
+
className: "px-2 py-1 font-mono text-xs rounded-md border border-violet-400/40 bg-transparent"
|
|
1037
|
+
}
|
|
1038
|
+
)
|
|
1039
|
+
] }),
|
|
1040
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1041
|
+
/* @__PURE__ */ jsx4(
|
|
1042
|
+
"input",
|
|
1043
|
+
{
|
|
1044
|
+
type: "file",
|
|
1045
|
+
accept: ".csv,.tsv,.txt,.json,text/csv,application/json",
|
|
1046
|
+
"aria-label": "Load data source file",
|
|
1047
|
+
"data-merge-file": "",
|
|
1048
|
+
onChange: (event) => {
|
|
1049
|
+
const file = event.target.files?.[0];
|
|
1050
|
+
if (file) void merge.loadFile(file);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
),
|
|
1054
|
+
/* @__PURE__ */ jsx4("span", { "data-merge-summary": "", className: "opacity-70", children: `${source.records.length} record${source.records.length === 1 ? "" : "s"} \xB7 ${source.fields.length} field${source.fields.length === 1 ? "" : "s"}` })
|
|
1055
|
+
] }),
|
|
1056
|
+
source.warnings.length > 0 && merge.sourceText.trim() !== "" && /* @__PURE__ */ jsx4("ul", { "data-merge-warnings": "", className: "text-amber-600 text-xs", children: source.warnings.map((warning, i) => /* @__PURE__ */ jsx4("li", { children: warning.message }, i)) }),
|
|
1057
|
+
merge.variables.length > 0 && /* @__PURE__ */ jsxs3("fieldset", { className: "flex flex-col gap-1", children: [
|
|
1058
|
+
/* @__PURE__ */ jsx4("legend", { className: "font-medium", children: "Field mapping" }),
|
|
1059
|
+
merge.variables.map((variable) => /* @__PURE__ */ jsxs3(
|
|
1060
|
+
"label",
|
|
1061
|
+
{
|
|
1062
|
+
className: "flex items-center gap-2",
|
|
1063
|
+
"data-merge-mapping": variable,
|
|
1064
|
+
children: [
|
|
1065
|
+
/* @__PURE__ */ jsx4("span", { className: "min-w-24 font-mono", children: `{${variable}}` }),
|
|
1066
|
+
/* @__PURE__ */ jsxs3(
|
|
1067
|
+
"select",
|
|
1068
|
+
{
|
|
1069
|
+
value: merge.mapping[variable] ?? "",
|
|
1070
|
+
"aria-label": `Field for ${variable}`,
|
|
1071
|
+
onChange: (event) => merge.setFieldMapping(variable, event.target.value || null),
|
|
1072
|
+
className: "px-1 py-0.5 rounded-md border border-violet-400/40 bg-transparent",
|
|
1073
|
+
children: [
|
|
1074
|
+
/* @__PURE__ */ jsx4("option", { value: "", children: "(none)" }),
|
|
1075
|
+
source.fields.map((field) => /* @__PURE__ */ jsx4("option", { value: field, children: field }, field))
|
|
1076
|
+
]
|
|
1077
|
+
}
|
|
1078
|
+
)
|
|
1079
|
+
]
|
|
1080
|
+
},
|
|
1081
|
+
variable
|
|
1082
|
+
))
|
|
1083
|
+
] }),
|
|
1084
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
|
|
1085
|
+
/* @__PURE__ */ jsx4(
|
|
1086
|
+
"button",
|
|
1087
|
+
{
|
|
1088
|
+
type: "button",
|
|
1089
|
+
"data-merge-prev": "",
|
|
1090
|
+
onClick: merge.prev,
|
|
1091
|
+
disabled: merge.index <= 0,
|
|
1092
|
+
children: "Prev"
|
|
1093
|
+
}
|
|
1094
|
+
),
|
|
1095
|
+
/* @__PURE__ */ jsx4("span", { "data-merge-position": "", children: merge.count === 0 ? "No records" : `Record ${merge.index + 1} of ${merge.count}` }),
|
|
1096
|
+
/* @__PURE__ */ jsx4(
|
|
1097
|
+
"button",
|
|
1098
|
+
{
|
|
1099
|
+
type: "button",
|
|
1100
|
+
"data-merge-next": "",
|
|
1101
|
+
onClick: merge.next,
|
|
1102
|
+
disabled: merge.index >= merge.count - 1,
|
|
1103
|
+
children: "Next"
|
|
1104
|
+
}
|
|
1105
|
+
)
|
|
1106
|
+
] }),
|
|
1107
|
+
/* @__PURE__ */ jsx4("div", { "data-merge-output": "", children: /* @__PURE__ */ jsx4(
|
|
1108
|
+
TemplateRenderer,
|
|
1109
|
+
{
|
|
1110
|
+
content,
|
|
1111
|
+
templates,
|
|
1112
|
+
bindings,
|
|
1113
|
+
templateColorMap,
|
|
1114
|
+
resolve: !!templates && templates.length > 0,
|
|
1115
|
+
values: merge.values
|
|
1116
|
+
}
|
|
1117
|
+
) }),
|
|
1118
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1119
|
+
/* @__PURE__ */ jsx4(
|
|
1120
|
+
"button",
|
|
1121
|
+
{
|
|
1122
|
+
type: "button",
|
|
1123
|
+
"data-merge-all": "",
|
|
1124
|
+
disabled: merge.count === 0,
|
|
1125
|
+
onClick: () => {
|
|
1126
|
+
const merged = merge.merge();
|
|
1127
|
+
setCopied(false);
|
|
1128
|
+
onMerge?.(merged);
|
|
1129
|
+
},
|
|
1130
|
+
children: "Merge all"
|
|
1131
|
+
}
|
|
1132
|
+
),
|
|
1133
|
+
result && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
1134
|
+
/* @__PURE__ */ jsx4("span", { "data-merge-result": "", children: `${result.outputs.length} merged${result.skipped.length ? `, ${result.skipped.length} skipped` : ""}${result.truncated ? " (stopped early)" : ""}` }),
|
|
1135
|
+
/* @__PURE__ */ jsx4("button", { type: "button", "data-merge-copy": "", onClick: copy, children: copied ? "Copied" : "Copy" }),
|
|
1136
|
+
/* @__PURE__ */ jsx4(
|
|
1137
|
+
"button",
|
|
1138
|
+
{
|
|
1139
|
+
type: "button",
|
|
1140
|
+
"data-merge-download": "text",
|
|
1141
|
+
onClick: () => downloadText(merge.serialize("text"), `${downloadName}.txt`, "text/plain"),
|
|
1142
|
+
children: "Download .txt"
|
|
1143
|
+
}
|
|
1144
|
+
),
|
|
1145
|
+
/* @__PURE__ */ jsx4(
|
|
1146
|
+
"button",
|
|
1147
|
+
{
|
|
1148
|
+
type: "button",
|
|
1149
|
+
"data-merge-download": "json",
|
|
1150
|
+
onClick: () => downloadText(merge.serialize("json"), `${downloadName}.json`, "application/json"),
|
|
1151
|
+
children: "Download .json"
|
|
1152
|
+
}
|
|
1153
|
+
)
|
|
1154
|
+
] })
|
|
1155
|
+
] }),
|
|
1156
|
+
result && /* @__PURE__ */ jsx4(
|
|
1157
|
+
"textarea",
|
|
1158
|
+
{
|
|
1159
|
+
readOnly: true,
|
|
1160
|
+
"aria-label": "Merged output",
|
|
1161
|
+
"data-merge-text": "",
|
|
1162
|
+
rows: 6,
|
|
1163
|
+
value: merge.serialize("text"),
|
|
1164
|
+
className: "px-2 py-1 font-mono text-xs rounded-md border border-violet-400/40 bg-transparent"
|
|
1165
|
+
}
|
|
1166
|
+
)
|
|
1167
|
+
] });
|
|
1168
|
+
};
|
|
1169
|
+
|
|
807
1170
|
// src/hooks/useOutline.ts
|
|
808
|
-
import { useMemo as
|
|
1171
|
+
import { useMemo as useMemo7, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
809
1172
|
import { createOutlineStore } from "@pixerate/editor";
|
|
810
1173
|
function useOutline(editor) {
|
|
811
|
-
const store =
|
|
812
|
-
return
|
|
1174
|
+
const store = useMemo7(() => createOutlineStore(editor), [editor]);
|
|
1175
|
+
return useSyncExternalStore4(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
813
1176
|
}
|
|
814
1177
|
|
|
815
1178
|
// src/components/OutlinePanel.tsx
|
|
816
1179
|
import { navigateToHeading } from "@pixerate/editor";
|
|
817
|
-
import { jsx as
|
|
1180
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
818
1181
|
var OutlinePanel = ({
|
|
819
1182
|
editor,
|
|
820
1183
|
title = "Outline",
|
|
@@ -828,11 +1191,11 @@ var OutlinePanel = ({
|
|
|
828
1191
|
}) => {
|
|
829
1192
|
const { headings, activeId } = useOutline(editor);
|
|
830
1193
|
const visible = headings.filter((h) => h.level <= maxLevel);
|
|
831
|
-
return /* @__PURE__ */
|
|
832
|
-
title != null && /* @__PURE__ */
|
|
833
|
-
visible.length === 0 ? /* @__PURE__ */
|
|
1194
|
+
return /* @__PURE__ */ jsxs4("nav", { className, "aria-label": "Document outline", "data-outline-panel": "", children: [
|
|
1195
|
+
title != null && /* @__PURE__ */ jsx5("div", { className: "pixerate-outline-title", children: title }),
|
|
1196
|
+
visible.length === 0 ? /* @__PURE__ */ jsx5("div", { className: "pixerate-outline-empty", children: emptyState }) : /* @__PURE__ */ jsx5("ul", { role: "list", style: { listStyle: "none", margin: 0, padding: 0 }, children: visible.map((heading) => {
|
|
834
1197
|
const active = heading.id === activeId;
|
|
835
|
-
return /* @__PURE__ */
|
|
1198
|
+
return /* @__PURE__ */ jsx5("li", { "data-level": heading.level, children: /* @__PURE__ */ jsx5(
|
|
836
1199
|
"button",
|
|
837
1200
|
{
|
|
838
1201
|
type: "button",
|
|
@@ -855,18 +1218,20 @@ var OutlinePanel = ({
|
|
|
855
1218
|
|
|
856
1219
|
// src/index.ts
|
|
857
1220
|
import {
|
|
858
|
-
DirtyTracker,
|
|
1221
|
+
DirtyTracker as DirtyTracker2,
|
|
859
1222
|
createDirtyTracker,
|
|
860
1223
|
defaultIsEqual,
|
|
861
1224
|
HistoryManager as HistoryManager2,
|
|
862
|
-
createHistoryManager as createHistoryManager2
|
|
1225
|
+
createHistoryManager as createHistoryManager2,
|
|
1226
|
+
bindDirtyToHistory as bindDirtyToHistory2,
|
|
1227
|
+
withoutDirty
|
|
863
1228
|
} from "@pixerate/editor";
|
|
864
1229
|
|
|
865
1230
|
// src/slots.tsx
|
|
866
|
-
import { createContext, useContext, useMemo as
|
|
867
|
-
import { jsx as
|
|
1231
|
+
import { createContext, useContext, useMemo as useMemo8 } from "react";
|
|
1232
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
868
1233
|
var defaultSlots = {
|
|
869
|
-
Button: (props) => /* @__PURE__ */
|
|
1234
|
+
Button: (props) => /* @__PURE__ */ jsx6(
|
|
870
1235
|
"button",
|
|
871
1236
|
{
|
|
872
1237
|
type: "button",
|
|
@@ -876,26 +1241,26 @@ var defaultSlots = {
|
|
|
876
1241
|
children: props.children
|
|
877
1242
|
}
|
|
878
1243
|
),
|
|
879
|
-
Tooltip: (props) => /* @__PURE__ */
|
|
880
|
-
NodeHeader: (props) => /* @__PURE__ */
|
|
881
|
-
/* @__PURE__ */
|
|
1244
|
+
Tooltip: (props) => /* @__PURE__ */ jsx6("div", { className: `pixerate-tooltip-container ${props.className || ""}`, title: String(props.content), children: props.children }),
|
|
1245
|
+
NodeHeader: (props) => /* @__PURE__ */ jsxs5("div", { className: `pixerate-node-header flex items-center justify-between ${props.className || ""}`, children: [
|
|
1246
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
882
1247
|
props.icon,
|
|
883
|
-
/* @__PURE__ */
|
|
1248
|
+
/* @__PURE__ */ jsx6("span", { className: "font-semibold", children: props.title })
|
|
884
1249
|
] }),
|
|
885
|
-
props.onClose && /* @__PURE__ */
|
|
1250
|
+
props.onClose && /* @__PURE__ */ jsx6("button", { type: "button", onClick: props.onClose, className: "opacity-70 hover:opacity-100", children: "\xD7" })
|
|
886
1251
|
] })
|
|
887
1252
|
};
|
|
888
1253
|
var EditorSlotsContext = createContext(defaultSlots);
|
|
889
1254
|
function EditorSlotsProvider({ slots, children }) {
|
|
890
|
-
const mergedSlots =
|
|
891
|
-
return /* @__PURE__ */
|
|
1255
|
+
const mergedSlots = useMemo8(() => ({ ...defaultSlots, ...slots }), [slots]);
|
|
1256
|
+
return /* @__PURE__ */ jsx6(EditorSlotsContext.Provider, { value: mergedSlots, children });
|
|
892
1257
|
}
|
|
893
1258
|
function useEditorSlots() {
|
|
894
1259
|
return useContext(EditorSlotsContext);
|
|
895
1260
|
}
|
|
896
1261
|
|
|
897
1262
|
// src/review/useReview.ts
|
|
898
|
-
import { useCallback as
|
|
1263
|
+
import { useCallback as useCallback6, useMemo as useMemo9, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
899
1264
|
import {
|
|
900
1265
|
getCommentStore,
|
|
901
1266
|
getTrackChangesStore
|
|
@@ -917,23 +1282,23 @@ function isCommentStore(value) {
|
|
|
917
1282
|
}
|
|
918
1283
|
function useComments(source) {
|
|
919
1284
|
const store = isCommentStore(source) ? source : getCommentStore(source);
|
|
920
|
-
const subscribe =
|
|
1285
|
+
const subscribe = useCallback6(
|
|
921
1286
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
922
1287
|
[store]
|
|
923
1288
|
);
|
|
924
1289
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
|
|
925
|
-
const snapshot =
|
|
926
|
-
return
|
|
1290
|
+
const snapshot = useSyncExternalStore5(subscribe, getSnapshot, getSnapshot);
|
|
1291
|
+
return useMemo9(() => ({ ...snapshot, store }), [snapshot, store]);
|
|
927
1292
|
}
|
|
928
1293
|
function useTrackChanges(editor) {
|
|
929
1294
|
const store = getTrackChangesStore(editor ?? null);
|
|
930
|
-
const subscribe =
|
|
1295
|
+
const subscribe = useCallback6(
|
|
931
1296
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
932
1297
|
[store]
|
|
933
1298
|
);
|
|
934
1299
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
|
|
935
|
-
const snapshot =
|
|
936
|
-
return
|
|
1300
|
+
const snapshot = useSyncExternalStore5(subscribe, getSnapshot, getSnapshot);
|
|
1301
|
+
return useMemo9(() => {
|
|
937
1302
|
const run = (fn) => () => {
|
|
938
1303
|
if (editor && !editor.isDestroyed) fn(editor);
|
|
939
1304
|
};
|
|
@@ -953,12 +1318,12 @@ function useTrackChanges(editor) {
|
|
|
953
1318
|
}
|
|
954
1319
|
|
|
955
1320
|
// src/review/CommentsPanel.tsx
|
|
956
|
-
import { useState as
|
|
1321
|
+
import { useState as useState8 } from "react";
|
|
957
1322
|
import {
|
|
958
1323
|
formatReviewTime,
|
|
959
1324
|
getCommentAuthor
|
|
960
1325
|
} from "@pixerate/editor";
|
|
961
|
-
import { jsx as
|
|
1326
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
962
1327
|
var buttonClass = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
|
|
963
1328
|
var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
|
|
964
1329
|
var textareaClass = "w-full resize-y rounded-md border border-input bg-background p-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary";
|
|
@@ -972,18 +1337,18 @@ var CommentsPanel = ({
|
|
|
972
1337
|
emptyMessage = "No comments yet. Select text and add a comment."
|
|
973
1338
|
}) => {
|
|
974
1339
|
const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
|
|
975
|
-
const [showResolved, setShowResolved] =
|
|
1340
|
+
const [showResolved, setShowResolved] = useState8(showResolvedInitial);
|
|
976
1341
|
const author = authorProp ?? getCommentAuthor(editor) ?? { id: "anonymous", name: "Anonymous" };
|
|
977
1342
|
const visible = threads.filter((t) => showResolved || !t.resolved);
|
|
978
1343
|
const resolvedCount = threads.filter((t) => t.resolved).length;
|
|
979
|
-
return /* @__PURE__ */
|
|
980
|
-
/* @__PURE__ */
|
|
981
|
-
/* @__PURE__ */
|
|
1344
|
+
return /* @__PURE__ */ jsxs6("aside", { className, "aria-label": "Comments", children: [
|
|
1345
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1346
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-xs font-medium text-muted-foreground", children: [
|
|
982
1347
|
threads.length - resolvedCount,
|
|
983
1348
|
" open",
|
|
984
1349
|
resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
|
|
985
1350
|
] }),
|
|
986
|
-
resolvedCount > 0 && /* @__PURE__ */
|
|
1351
|
+
resolvedCount > 0 && /* @__PURE__ */ jsx7(
|
|
987
1352
|
"button",
|
|
988
1353
|
{
|
|
989
1354
|
type: "button",
|
|
@@ -994,7 +1359,7 @@ var CommentsPanel = ({
|
|
|
994
1359
|
}
|
|
995
1360
|
)
|
|
996
1361
|
] }),
|
|
997
|
-
visible.length === 0 ? /* @__PURE__ */
|
|
1362
|
+
visible.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ jsx7("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ jsx7(
|
|
998
1363
|
CommentThreadCard,
|
|
999
1364
|
{
|
|
1000
1365
|
thread,
|
|
@@ -1016,7 +1381,7 @@ var CommentThreadCard = ({
|
|
|
1016
1381
|
author,
|
|
1017
1382
|
formatTime
|
|
1018
1383
|
}) => {
|
|
1019
|
-
const [draft, setDraft] =
|
|
1384
|
+
const [draft, setDraft] = useState8("");
|
|
1020
1385
|
const isDraft = thread.body === "";
|
|
1021
1386
|
const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
|
|
1022
1387
|
const live = editor && !editor.isDestroyed ? editor : null;
|
|
@@ -1042,7 +1407,7 @@ var CommentThreadCard = ({
|
|
|
1042
1407
|
setDraft("");
|
|
1043
1408
|
};
|
|
1044
1409
|
const stop = (e) => e.stopPropagation();
|
|
1045
|
-
return /* @__PURE__ */
|
|
1410
|
+
return /* @__PURE__ */ jsxs6(
|
|
1046
1411
|
"li",
|
|
1047
1412
|
{
|
|
1048
1413
|
className: `flex flex-col gap-2 rounded-md border bg-background p-3 cursor-pointer ${active ? "border-primary ring-1 ring-primary" : "border-border"} ${thread.resolved ? "opacity-70" : ""}`,
|
|
@@ -1058,24 +1423,24 @@ var CommentThreadCard = ({
|
|
|
1058
1423
|
}
|
|
1059
1424
|
},
|
|
1060
1425
|
children: [
|
|
1061
|
-
/* @__PURE__ */
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
1426
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
1427
|
+
/* @__PURE__ */ jsx7("span", { className: "font-medium", children: thread.author.name }),
|
|
1428
|
+
/* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
|
|
1064
1429
|
] }),
|
|
1065
|
-
quote && /* @__PURE__ */
|
|
1066
|
-
thread.orphaned && /* @__PURE__ */
|
|
1067
|
-
thread.resolved && /* @__PURE__ */
|
|
1068
|
-
!isDraft && /* @__PURE__ */
|
|
1069
|
-
thread.replies.length > 0 && /* @__PURE__ */
|
|
1070
|
-
/* @__PURE__ */
|
|
1071
|
-
/* @__PURE__ */
|
|
1430
|
+
quote && /* @__PURE__ */ jsx7("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
|
|
1431
|
+
thread.orphaned && /* @__PURE__ */ jsx7("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
|
|
1432
|
+
thread.resolved && /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
|
|
1433
|
+
!isDraft && /* @__PURE__ */ jsx7("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
|
|
1434
|
+
thread.replies.length > 0 && /* @__PURE__ */ jsx7("ul", { className: "flex flex-col gap-2 border-l border-border pl-3", role: "list", children: thread.replies.map((reply) => /* @__PURE__ */ jsxs6("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
|
|
1435
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-xs", children: [
|
|
1436
|
+
/* @__PURE__ */ jsx7("span", { className: "font-medium", children: reply.author.name }),
|
|
1072
1437
|
" ",
|
|
1073
|
-
/* @__PURE__ */
|
|
1438
|
+
/* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
|
|
1074
1439
|
] }),
|
|
1075
|
-
/* @__PURE__ */
|
|
1440
|
+
/* @__PURE__ */ jsx7("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
|
|
1076
1441
|
] }, reply.id)) }),
|
|
1077
|
-
(active || isDraft) && !thread.resolved && /* @__PURE__ */
|
|
1078
|
-
/* @__PURE__ */
|
|
1442
|
+
(active || isDraft) && !thread.resolved && /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-1", onClick: stop, children: [
|
|
1443
|
+
/* @__PURE__ */ jsx7(
|
|
1079
1444
|
"textarea",
|
|
1080
1445
|
{
|
|
1081
1446
|
className: textareaClass,
|
|
@@ -1093,9 +1458,9 @@ var CommentThreadCard = ({
|
|
|
1093
1458
|
}
|
|
1094
1459
|
}
|
|
1095
1460
|
),
|
|
1096
|
-
/* @__PURE__ */
|
|
1097
|
-
isDraft && /* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
1461
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex justify-end gap-1", children: [
|
|
1462
|
+
isDraft && /* @__PURE__ */ jsx7("button", { type: "button", className: buttonClass, onClick: remove, children: "Cancel" }),
|
|
1463
|
+
/* @__PURE__ */ jsx7(
|
|
1099
1464
|
"button",
|
|
1100
1465
|
{
|
|
1101
1466
|
type: "button",
|
|
@@ -1107,9 +1472,9 @@ var CommentThreadCard = ({
|
|
|
1107
1472
|
)
|
|
1108
1473
|
] })
|
|
1109
1474
|
] }),
|
|
1110
|
-
!isDraft && /* @__PURE__ */
|
|
1111
|
-
/* @__PURE__ */
|
|
1112
|
-
/* @__PURE__ */
|
|
1475
|
+
!isDraft && /* @__PURE__ */ jsxs6("div", { className: "flex justify-end gap-1", onClick: stop, children: [
|
|
1476
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: buttonClass, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
|
|
1477
|
+
/* @__PURE__ */ jsx7(
|
|
1113
1478
|
"button",
|
|
1114
1479
|
{
|
|
1115
1480
|
type: "button",
|
|
@@ -1125,7 +1490,7 @@ var CommentThreadCard = ({
|
|
|
1125
1490
|
};
|
|
1126
1491
|
|
|
1127
1492
|
// src/review/ReviewToolbar.tsx
|
|
1128
|
-
import { jsx as
|
|
1493
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1129
1494
|
var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
|
|
1130
1495
|
var buttonClass2 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
1131
1496
|
var ReviewToolbar = ({
|
|
@@ -1138,8 +1503,8 @@ var ReviewToolbar = ({
|
|
|
1138
1503
|
const count = review.changes.length;
|
|
1139
1504
|
const current = review.currentChange;
|
|
1140
1505
|
const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
|
|
1141
|
-
return /* @__PURE__ */
|
|
1142
|
-
/* @__PURE__ */
|
|
1506
|
+
return /* @__PURE__ */ jsxs7("div", { className, role: "toolbar", "aria-label": "Review", children: [
|
|
1507
|
+
/* @__PURE__ */ jsx8(
|
|
1143
1508
|
"button",
|
|
1144
1509
|
{
|
|
1145
1510
|
type: "button",
|
|
@@ -1150,8 +1515,8 @@ var ReviewToolbar = ({
|
|
|
1150
1515
|
children: review.enabled ? "Tracking on" : "Track changes"
|
|
1151
1516
|
}
|
|
1152
1517
|
),
|
|
1153
|
-
/* @__PURE__ */
|
|
1154
|
-
/* @__PURE__ */
|
|
1518
|
+
/* @__PURE__ */ jsx8("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
1519
|
+
/* @__PURE__ */ jsx8(
|
|
1155
1520
|
"button",
|
|
1156
1521
|
{
|
|
1157
1522
|
type: "button",
|
|
@@ -1162,8 +1527,8 @@ var ReviewToolbar = ({
|
|
|
1162
1527
|
children: "\u2039"
|
|
1163
1528
|
}
|
|
1164
1529
|
),
|
|
1165
|
-
/* @__PURE__ */
|
|
1166
|
-
/* @__PURE__ */
|
|
1530
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-[4rem] text-center text-xs text-muted-foreground", "aria-live": "polite", children: count === 0 ? "No changes" : current ? `${index} of ${count}` : `${count} changes` }),
|
|
1531
|
+
/* @__PURE__ */ jsx8(
|
|
1167
1532
|
"button",
|
|
1168
1533
|
{
|
|
1169
1534
|
type: "button",
|
|
@@ -1174,7 +1539,7 @@ var ReviewToolbar = ({
|
|
|
1174
1539
|
children: "\u203A"
|
|
1175
1540
|
}
|
|
1176
1541
|
),
|
|
1177
|
-
showDescription && current && /* @__PURE__ */
|
|
1542
|
+
showDescription && current && /* @__PURE__ */ jsxs7(
|
|
1178
1543
|
"span",
|
|
1179
1544
|
{
|
|
1180
1545
|
className: descriptionClassName,
|
|
@@ -1186,8 +1551,8 @@ var ReviewToolbar = ({
|
|
|
1186
1551
|
]
|
|
1187
1552
|
}
|
|
1188
1553
|
),
|
|
1189
|
-
/* @__PURE__ */
|
|
1190
|
-
/* @__PURE__ */
|
|
1554
|
+
/* @__PURE__ */ jsx8("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
1555
|
+
/* @__PURE__ */ jsx8(
|
|
1191
1556
|
"button",
|
|
1192
1557
|
{
|
|
1193
1558
|
type: "button",
|
|
@@ -1197,7 +1562,7 @@ var ReviewToolbar = ({
|
|
|
1197
1562
|
children: "Accept"
|
|
1198
1563
|
}
|
|
1199
1564
|
),
|
|
1200
|
-
/* @__PURE__ */
|
|
1565
|
+
/* @__PURE__ */ jsx8(
|
|
1201
1566
|
"button",
|
|
1202
1567
|
{
|
|
1203
1568
|
type: "button",
|
|
@@ -1207,18 +1572,18 @@ var ReviewToolbar = ({
|
|
|
1207
1572
|
children: "Reject"
|
|
1208
1573
|
}
|
|
1209
1574
|
),
|
|
1210
|
-
/* @__PURE__ */
|
|
1211
|
-
/* @__PURE__ */
|
|
1575
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: buttonClass2, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
|
|
1576
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: buttonClass2, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
|
|
1212
1577
|
] });
|
|
1213
1578
|
};
|
|
1214
1579
|
|
|
1215
1580
|
// src/review/CommentButton.tsx
|
|
1216
|
-
import { jsx as
|
|
1581
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1217
1582
|
var CommentButton = ({
|
|
1218
1583
|
editor,
|
|
1219
1584
|
className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
|
|
1220
1585
|
children = "Comment"
|
|
1221
|
-
}) => /* @__PURE__ */
|
|
1586
|
+
}) => /* @__PURE__ */ jsx9(
|
|
1222
1587
|
"button",
|
|
1223
1588
|
{
|
|
1224
1589
|
type: "button",
|
|
@@ -1228,41 +1593,290 @@ var CommentButton = ({
|
|
|
1228
1593
|
children
|
|
1229
1594
|
}
|
|
1230
1595
|
);
|
|
1596
|
+
|
|
1597
|
+
// src/review/useDocumentCompare.ts
|
|
1598
|
+
import { useCallback as useCallback7, useMemo as useMemo10, useRef as useRef8, useState as useState9 } from "react";
|
|
1599
|
+
import {
|
|
1600
|
+
applyDocumentComparison
|
|
1601
|
+
} from "@pixerate/editor";
|
|
1602
|
+
function useDocumentCompare(editor, options) {
|
|
1603
|
+
const [summary, setSummary] = useState9(null);
|
|
1604
|
+
const defaults = useRef8(options);
|
|
1605
|
+
defaults.current = options;
|
|
1606
|
+
const compare = useCallback7(
|
|
1607
|
+
(original, revised, overrides) => {
|
|
1608
|
+
if (!editor || editor.isDestroyed) return null;
|
|
1609
|
+
const result = applyDocumentComparison(editor, original, revised, {
|
|
1610
|
+
...defaults.current,
|
|
1611
|
+
...overrides
|
|
1612
|
+
});
|
|
1613
|
+
setSummary(result.summary);
|
|
1614
|
+
return result.summary;
|
|
1615
|
+
},
|
|
1616
|
+
[editor]
|
|
1617
|
+
);
|
|
1618
|
+
const clear = useCallback7(() => setSummary(null), []);
|
|
1619
|
+
return useMemo10(() => ({ summary, compare, clear }), [summary, compare, clear]);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
// src/find-replace/useFindReplace.ts
|
|
1623
|
+
import { useCallback as useCallback8, useMemo as useMemo11, useSyncExternalStore as useSyncExternalStore6 } from "react";
|
|
1624
|
+
import {
|
|
1625
|
+
EMPTY_FIND_REPLACE_SNAPSHOT,
|
|
1626
|
+
getFindReplaceStore
|
|
1627
|
+
} from "@pixerate/editor";
|
|
1628
|
+
var noopUnsubscribe2 = () => {
|
|
1629
|
+
};
|
|
1630
|
+
function useFindReplace(editor) {
|
|
1631
|
+
const store = getFindReplaceStore(editor ?? null);
|
|
1632
|
+
const subscribe = useCallback8(
|
|
1633
|
+
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
|
|
1634
|
+
[store]
|
|
1635
|
+
);
|
|
1636
|
+
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_FIND_REPLACE_SNAPSHOT;
|
|
1637
|
+
const snapshot = useSyncExternalStore6(subscribe, getSnapshot, getSnapshot);
|
|
1638
|
+
return useMemo11(() => {
|
|
1639
|
+
const run = (fn) => {
|
|
1640
|
+
if (editor && !editor.isDestroyed && store) fn(editor);
|
|
1641
|
+
};
|
|
1642
|
+
return {
|
|
1643
|
+
...snapshot,
|
|
1644
|
+
available: !!store,
|
|
1645
|
+
matchCount: snapshot.matches.length,
|
|
1646
|
+
show: (mode = "find") => run((e) => e.commands.openFindReplace({ mode })),
|
|
1647
|
+
close: () => run((e) => e.commands.closeFindReplace()),
|
|
1648
|
+
setQuery: (query) => run((e) => e.commands.setSearch({ query })),
|
|
1649
|
+
setReplacement: (replacement) => run((e) => e.commands.setSearch({ replacement })),
|
|
1650
|
+
setOptions: (options) => run((e) => e.commands.setSearch({ options })),
|
|
1651
|
+
toggleOption: (option) => run((e) => e.commands.setSearch({ options: { [option]: !snapshot.options[option] } })),
|
|
1652
|
+
next: () => run((e) => e.commands.findNext()),
|
|
1653
|
+
previous: () => run((e) => e.commands.findPrevious()),
|
|
1654
|
+
replace: () => run((e) => e.commands.replaceCurrent()),
|
|
1655
|
+
replaceAll: () => run((e) => e.commands.replaceAll()),
|
|
1656
|
+
clear: () => run((e) => e.commands.clearSearch())
|
|
1657
|
+
};
|
|
1658
|
+
}, [snapshot, editor, store]);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
// src/find-replace/FindReplaceBar.tsx
|
|
1662
|
+
import { useEffect as useEffect8, useRef as useRef9, useState as useState10 } from "react";
|
|
1663
|
+
import { FIND_OPTION_TOGGLES, formatFindStatus } from "@pixerate/editor";
|
|
1664
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1665
|
+
var inputClass = "min-w-0 flex-1 rounded border border-input bg-background px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring";
|
|
1666
|
+
var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
1667
|
+
var toggleClass = (on) => `${buttonClass3} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
|
|
1668
|
+
var isMod = (e) => e.metaKey || e.ctrlKey;
|
|
1669
|
+
var FindReplaceBar = ({
|
|
1670
|
+
editor,
|
|
1671
|
+
className = "flex flex-col gap-1 rounded-md border border-border bg-background p-1 text-sm shadow-sm",
|
|
1672
|
+
alwaysOpen = false,
|
|
1673
|
+
showMoreOptions = true,
|
|
1674
|
+
onClose
|
|
1675
|
+
}) => {
|
|
1676
|
+
const find = useFindReplace(editor);
|
|
1677
|
+
const findInput = useRef9(null);
|
|
1678
|
+
const [moreOpen, setMoreOpen] = useState10(false);
|
|
1679
|
+
const visible = find.available && (alwaysOpen || find.open);
|
|
1680
|
+
useEffect8(() => {
|
|
1681
|
+
if (!visible || find.focusRequest === 0) return;
|
|
1682
|
+
findInput.current?.focus();
|
|
1683
|
+
findInput.current?.select();
|
|
1684
|
+
}, [visible, find.focusRequest]);
|
|
1685
|
+
if (!visible) return null;
|
|
1686
|
+
const showReplace = find.mode === "replace";
|
|
1687
|
+
const status = formatFindStatus(find);
|
|
1688
|
+
const hasMatches = find.matchCount > 0;
|
|
1689
|
+
const close = () => {
|
|
1690
|
+
find.close();
|
|
1691
|
+
editor?.commands.focus();
|
|
1692
|
+
onClose?.();
|
|
1693
|
+
};
|
|
1694
|
+
const onBarKeyDown = (e) => {
|
|
1695
|
+
if (e.key === "Escape") {
|
|
1696
|
+
e.preventDefault();
|
|
1697
|
+
close();
|
|
1698
|
+
} else if (isMod(e) && (e.key === "f" || e.key === "F")) {
|
|
1699
|
+
e.preventDefault();
|
|
1700
|
+
find.show("find");
|
|
1701
|
+
} else if (isMod(e) && (e.key === "h" || e.key === "H")) {
|
|
1702
|
+
e.preventDefault();
|
|
1703
|
+
find.show("replace");
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
const onFindKeyDown = (e) => {
|
|
1707
|
+
if (e.key !== "Enter") return;
|
|
1708
|
+
e.preventDefault();
|
|
1709
|
+
if (e.shiftKey) find.previous();
|
|
1710
|
+
else find.next();
|
|
1711
|
+
};
|
|
1712
|
+
const onReplaceKeyDown = (e) => {
|
|
1713
|
+
if (e.key !== "Enter") return;
|
|
1714
|
+
e.preventDefault();
|
|
1715
|
+
if (isMod(e)) find.replaceAll();
|
|
1716
|
+
else find.replace();
|
|
1717
|
+
};
|
|
1718
|
+
return /* @__PURE__ */ jsxs8("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
|
|
1719
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1", children: [
|
|
1720
|
+
/* @__PURE__ */ jsx10(
|
|
1721
|
+
"button",
|
|
1722
|
+
{
|
|
1723
|
+
type: "button",
|
|
1724
|
+
className: buttonClass3,
|
|
1725
|
+
"aria-label": "Toggle replace",
|
|
1726
|
+
"aria-expanded": showReplace,
|
|
1727
|
+
onClick: () => find.show(showReplace ? "find" : "replace"),
|
|
1728
|
+
children: showReplace ? "\u25BE" : "\u25B8"
|
|
1729
|
+
}
|
|
1730
|
+
),
|
|
1731
|
+
/* @__PURE__ */ jsx10(
|
|
1732
|
+
"input",
|
|
1733
|
+
{
|
|
1734
|
+
ref: findInput,
|
|
1735
|
+
type: "text",
|
|
1736
|
+
className: inputClass,
|
|
1737
|
+
placeholder: "Find",
|
|
1738
|
+
"aria-label": "Find",
|
|
1739
|
+
"aria-invalid": !!find.error,
|
|
1740
|
+
value: find.query,
|
|
1741
|
+
onChange: (e) => find.setQuery(e.target.value),
|
|
1742
|
+
onKeyDown: onFindKeyDown
|
|
1743
|
+
}
|
|
1744
|
+
),
|
|
1745
|
+
FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ jsx10(
|
|
1746
|
+
"button",
|
|
1747
|
+
{
|
|
1748
|
+
type: "button",
|
|
1749
|
+
className: toggleClass(!!find.options[t.key]),
|
|
1750
|
+
"aria-label": t.label,
|
|
1751
|
+
title: t.label,
|
|
1752
|
+
"aria-pressed": !!find.options[t.key],
|
|
1753
|
+
onClick: () => find.toggleOption(t.key),
|
|
1754
|
+
children: t.short
|
|
1755
|
+
},
|
|
1756
|
+
t.key
|
|
1757
|
+
)),
|
|
1758
|
+
/* @__PURE__ */ jsx10(
|
|
1759
|
+
"span",
|
|
1760
|
+
{
|
|
1761
|
+
className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
|
|
1762
|
+
"aria-live": "polite",
|
|
1763
|
+
role: find.error ? "alert" : "status",
|
|
1764
|
+
"data-testid": "find-status",
|
|
1765
|
+
children: status
|
|
1766
|
+
}
|
|
1767
|
+
),
|
|
1768
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: buttonClass3, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
|
|
1769
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: buttonClass3, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
|
|
1770
|
+
showMoreOptions && /* @__PURE__ */ jsx10(
|
|
1771
|
+
"button",
|
|
1772
|
+
{
|
|
1773
|
+
type: "button",
|
|
1774
|
+
className: buttonClass3,
|
|
1775
|
+
"aria-label": "More options",
|
|
1776
|
+
"aria-expanded": moreOpen,
|
|
1777
|
+
onClick: () => setMoreOpen((v) => !v),
|
|
1778
|
+
children: "\u2026"
|
|
1779
|
+
}
|
|
1780
|
+
),
|
|
1781
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: buttonClass3, "aria-label": "Close find", onClick: close, children: "\xD7" })
|
|
1782
|
+
] }),
|
|
1783
|
+
showReplace && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1 pl-7", children: [
|
|
1784
|
+
/* @__PURE__ */ jsx10(
|
|
1785
|
+
"input",
|
|
1786
|
+
{
|
|
1787
|
+
type: "text",
|
|
1788
|
+
className: inputClass,
|
|
1789
|
+
placeholder: "Replace",
|
|
1790
|
+
"aria-label": "Replace",
|
|
1791
|
+
value: find.replacement,
|
|
1792
|
+
onChange: (e) => find.setReplacement(e.target.value),
|
|
1793
|
+
onKeyDown: onReplaceKeyDown
|
|
1794
|
+
}
|
|
1795
|
+
),
|
|
1796
|
+
/* @__PURE__ */ jsx10(
|
|
1797
|
+
"button",
|
|
1798
|
+
{
|
|
1799
|
+
type: "button",
|
|
1800
|
+
className: buttonClass3,
|
|
1801
|
+
disabled: !hasMatches || find.currentIndex < 0,
|
|
1802
|
+
onClick: find.replace,
|
|
1803
|
+
children: "Replace"
|
|
1804
|
+
}
|
|
1805
|
+
),
|
|
1806
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: buttonClass3, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
|
|
1807
|
+
find.lastReplaceCount !== null && /* @__PURE__ */ jsx10("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
|
|
1808
|
+
] }),
|
|
1809
|
+
showMoreOptions && moreOpen && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pl-7 text-xs text-muted-foreground", children: FIND_OPTION_TOGGLES.filter((t) => t.advanced).map((t) => /* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-1", children: [
|
|
1810
|
+
/* @__PURE__ */ jsx10(
|
|
1811
|
+
"input",
|
|
1812
|
+
{
|
|
1813
|
+
type: "checkbox",
|
|
1814
|
+
checked: !!find.options[t.key],
|
|
1815
|
+
onChange: () => find.toggleOption(t.key)
|
|
1816
|
+
}
|
|
1817
|
+
),
|
|
1818
|
+
t.label
|
|
1819
|
+
] }, t.key)) })
|
|
1820
|
+
] });
|
|
1821
|
+
};
|
|
1231
1822
|
export {
|
|
1823
|
+
AdjustmentLayersPanel,
|
|
1232
1824
|
BubbleMenu,
|
|
1825
|
+
CommandPalette,
|
|
1233
1826
|
CommentButton,
|
|
1234
1827
|
CommentsPanel,
|
|
1235
|
-
|
|
1828
|
+
ControlSlider,
|
|
1829
|
+
CurvesEditor,
|
|
1830
|
+
DirtyTracker2 as DirtyTracker,
|
|
1236
1831
|
EditorContent,
|
|
1237
1832
|
EditorSlotsProvider,
|
|
1833
|
+
FindReplaceBar,
|
|
1238
1834
|
FormulaHints,
|
|
1835
|
+
GenerationSettings,
|
|
1836
|
+
Histogram,
|
|
1239
1837
|
HistoryManager2 as HistoryManager,
|
|
1240
1838
|
ImageEditor,
|
|
1839
|
+
JobProgress,
|
|
1840
|
+
MergePreview,
|
|
1241
1841
|
OutlinePanel,
|
|
1842
|
+
RecoveryPrompt,
|
|
1242
1843
|
ReviewToolbar,
|
|
1243
1844
|
SpreadsheetContextMenu,
|
|
1244
1845
|
SpreadsheetEditor,
|
|
1245
1846
|
SpreadsheetGroupRow,
|
|
1246
1847
|
TemplateRenderer,
|
|
1247
1848
|
VariableForm,
|
|
1849
|
+
bindDirtyToHistory2 as bindDirtyToHistory,
|
|
1248
1850
|
createDirtyTracker,
|
|
1249
1851
|
createHistoryManager2 as createHistoryManager,
|
|
1250
1852
|
defaultIsEqual,
|
|
1251
1853
|
useAgentToolProvider,
|
|
1854
|
+
useAutosave,
|
|
1855
|
+
useCommandPalette,
|
|
1856
|
+
useCommandShortcuts,
|
|
1252
1857
|
useComments,
|
|
1253
1858
|
useDismissGuard,
|
|
1859
|
+
useDocumentCompare,
|
|
1254
1860
|
useEditor2 as useEditor,
|
|
1255
1861
|
useEditorSlots,
|
|
1256
1862
|
useFileImport,
|
|
1257
1863
|
useFillHandle,
|
|
1864
|
+
useFindReplace,
|
|
1865
|
+
useGenerationPlan,
|
|
1258
1866
|
useHistory,
|
|
1867
|
+
useHistoryDirty,
|
|
1259
1868
|
useHistoryShortcuts,
|
|
1260
1869
|
useImageEditor,
|
|
1870
|
+
useImageHistogram,
|
|
1871
|
+
useJobProgress,
|
|
1872
|
+
useMergePreview,
|
|
1261
1873
|
useNavigationGuard,
|
|
1262
1874
|
useOutline,
|
|
1263
1875
|
usePromptEditor,
|
|
1876
|
+
useRegisterCommands,
|
|
1264
1877
|
useSpreadsheetClipboard,
|
|
1265
1878
|
useSpreadsheetEditor,
|
|
1266
|
-
useTrackChanges
|
|
1879
|
+
useTrackChanges,
|
|
1880
|
+
withoutDirty
|
|
1267
1881
|
};
|
|
1268
1882
|
//# sourceMappingURL=index.js.map
|