@pixerate/editor-react 0.16.0 → 0.18.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 +4 -2
- package/dist/canvas/index.cjs +1094 -143
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +277 -3
- package/dist/canvas/index.d.ts +277 -3
- package/dist/canvas/index.js +976 -0
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-34HEZX7J.js +2144 -0
- package/dist/chunk-34HEZX7J.js.map +1 -0
- package/dist/chunk-I3E4KSA2.js +515 -0
- package/dist/chunk-I3E4KSA2.js.map +1 -0
- package/dist/{chunk-XTFR3IMK.js → chunk-ZU54BMDC.js} +473 -160
- package/dist/chunk-ZU54BMDC.js.map +1 -0
- package/dist/generation/index.cjs +290 -0
- package/dist/generation/index.cjs.map +1 -1
- package/dist/generation/index.d.cts +66 -2
- package/dist/generation/index.d.ts +66 -2
- package/dist/generation/index.js +7 -1
- package/dist/image-editor/index.cjs +490 -187
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +34 -2
- package/dist/image-editor/index.d.ts +34 -2
- package/dist/image-editor/index.js +5 -1
- package/dist/index.cjs +2792 -823
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +188 -7
- package/dist/index.d.ts +188 -7
- package/dist/index.js +600 -158
- package/dist/index.js.map +1 -1
- package/dist/spreadsheet/index.cjs +1099 -142
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +156 -8
- package/dist/spreadsheet/index.d.ts +156 -8
- package/dist/spreadsheet/index.js +15 -3
- package/dist/tokens/index.cjs +395 -0
- package/dist/tokens/index.cjs.map +1 -0
- package/dist/tokens/index.d.cts +54 -0
- package/dist/tokens/index.d.ts +54 -0
- package/dist/tokens/index.js +375 -0
- package/dist/tokens/index.js.map +1 -0
- package/package.json +10 -2
- package/dist/chunk-7SPRQZ6H.js +0 -216
- package/dist/chunk-7SPRQZ6H.js.map +0 -1
- package/dist/chunk-FYIPXHAE.js +0 -1169
- package/dist/chunk-FYIPXHAE.js.map +0 -1
- package/dist/chunk-XTFR3IMK.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FormulaHints,
|
|
3
|
+
NameManager,
|
|
4
|
+
SheetTabs,
|
|
5
|
+
SpreadsheetConditionalFormatPanel,
|
|
3
6
|
SpreadsheetContextMenu,
|
|
7
|
+
SpreadsheetDataValidationPanel,
|
|
4
8
|
SpreadsheetEditor,
|
|
5
9
|
SpreadsheetGroupRow,
|
|
10
|
+
SpreadsheetValidationDialog,
|
|
6
11
|
useFillHandle,
|
|
7
12
|
useSpreadsheetClipboard,
|
|
8
|
-
useSpreadsheetEditor
|
|
9
|
-
|
|
13
|
+
useSpreadsheetEditor,
|
|
14
|
+
useSpreadsheetViewport
|
|
15
|
+
} from "./chunk-34HEZX7J.js";
|
|
10
16
|
import {
|
|
11
17
|
AdjustmentLayersPanel,
|
|
12
18
|
ControlSlider,
|
|
13
19
|
CurvesEditor,
|
|
14
20
|
Histogram,
|
|
15
21
|
ImageEditor,
|
|
22
|
+
RefineEdgePanel,
|
|
23
|
+
SelectionOptionsBar,
|
|
16
24
|
useImageEditor,
|
|
17
25
|
useImageHistogram
|
|
18
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-ZU54BMDC.js";
|
|
19
27
|
import {
|
|
20
28
|
CommandPalette,
|
|
21
29
|
useCommandPalette,
|
|
@@ -27,11 +35,14 @@ import {
|
|
|
27
35
|
useAutosave
|
|
28
36
|
} from "./chunk-XWFU2CSG.js";
|
|
29
37
|
import {
|
|
38
|
+
AssetMentionChips,
|
|
39
|
+
GenerationHistory,
|
|
30
40
|
GenerationSettings,
|
|
31
41
|
JobProgress,
|
|
32
42
|
useGenerationPlan,
|
|
43
|
+
useGenerationRecords,
|
|
33
44
|
useJobProgress
|
|
34
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-I3E4KSA2.js";
|
|
35
46
|
|
|
36
47
|
// src/hooks/usePromptEditor.ts
|
|
37
48
|
import { useMemo, useEffect, useRef } from "react";
|
|
@@ -576,7 +587,8 @@ function useHistoryShortcuts(manager, options = {}) {
|
|
|
576
587
|
// src/hooks/useFileImport.ts
|
|
577
588
|
import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef6, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
578
589
|
import {
|
|
579
|
-
FileImportController
|
|
590
|
+
FileImportController,
|
|
591
|
+
summarizeImportStructure
|
|
580
592
|
} from "@pixerate/editor";
|
|
581
593
|
function useFileImport(editor, options = {}) {
|
|
582
594
|
const editorRef = useRef6(editor);
|
|
@@ -592,18 +604,73 @@ function useFileImport(editor, options = {}) {
|
|
|
592
604
|
controller.setOptions(options);
|
|
593
605
|
});
|
|
594
606
|
const state = useSyncExternalStore3(controller.subscribe, controller.getState, controller.getState);
|
|
607
|
+
const structureSummary = useMemo3(() => summarizeImportStructure(state.lastOutcomes), [state.lastOutcomes]);
|
|
595
608
|
return {
|
|
596
609
|
...state,
|
|
610
|
+
structureSummary,
|
|
597
611
|
accept: controller.accept,
|
|
598
612
|
openFilePicker: controller.openFilePicker,
|
|
599
613
|
importFiles: controller.importFiles
|
|
600
614
|
};
|
|
601
615
|
}
|
|
602
616
|
|
|
617
|
+
// src/hooks/useDocxExport.ts
|
|
618
|
+
import { useEffect as useEffect6, useMemo as useMemo4, useRef as useRef7, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
619
|
+
import {
|
|
620
|
+
DocxExportController
|
|
621
|
+
} from "@pixerate/editor/export";
|
|
622
|
+
function useDocxExport(editor, options = {}) {
|
|
623
|
+
const editorRef = useRef7(editor);
|
|
624
|
+
editorRef.current = editor;
|
|
625
|
+
const controller = useMemo4(
|
|
626
|
+
() => new DocxExportController(() => {
|
|
627
|
+
const current = editorRef.current;
|
|
628
|
+
return current && !current.isDestroyed ? current : null;
|
|
629
|
+
}, options),
|
|
630
|
+
[]
|
|
631
|
+
);
|
|
632
|
+
useEffect6(() => {
|
|
633
|
+
controller.setOptions(options);
|
|
634
|
+
});
|
|
635
|
+
const state = useSyncExternalStore4(controller.subscribe, controller.getState, controller.getState);
|
|
636
|
+
return {
|
|
637
|
+
...state,
|
|
638
|
+
download: (fileName) => controller.download(fileName),
|
|
639
|
+
exportBlob: () => controller.exportBlob()
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// src/components/ExportDocxButton.tsx
|
|
644
|
+
import { jsx } from "react/jsx-runtime";
|
|
645
|
+
var ExportDocxButton = ({
|
|
646
|
+
editor,
|
|
647
|
+
className = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-50",
|
|
648
|
+
children = "Export to Word",
|
|
649
|
+
onExported,
|
|
650
|
+
...options
|
|
651
|
+
}) => {
|
|
652
|
+
const docx = useDocxExport(editor, options);
|
|
653
|
+
return /* @__PURE__ */ jsx(
|
|
654
|
+
"button",
|
|
655
|
+
{
|
|
656
|
+
type: "button",
|
|
657
|
+
className,
|
|
658
|
+
disabled: !editor || docx.isExporting,
|
|
659
|
+
"aria-busy": docx.isExporting || void 0,
|
|
660
|
+
title: docx.error ? `Export failed: ${docx.error.message}` : void 0,
|
|
661
|
+
onClick: async () => {
|
|
662
|
+
const report = await docx.download();
|
|
663
|
+
if (report) onExported?.(report);
|
|
664
|
+
},
|
|
665
|
+
children
|
|
666
|
+
}
|
|
667
|
+
);
|
|
668
|
+
};
|
|
669
|
+
|
|
603
670
|
// src/hooks/useAgentToolProvider.ts
|
|
604
|
-
import { useEffect as
|
|
671
|
+
import { useEffect as useEffect7 } from "react";
|
|
605
672
|
function useAgentToolProvider(registry, provider) {
|
|
606
|
-
|
|
673
|
+
useEffect7(() => {
|
|
607
674
|
if (!registry || !provider) return;
|
|
608
675
|
return registry.register(provider);
|
|
609
676
|
}, [registry, provider]);
|
|
@@ -613,17 +680,17 @@ function useAgentToolProvider(registry, provider) {
|
|
|
613
680
|
import {
|
|
614
681
|
EditorContent as TipTapEditorContent
|
|
615
682
|
} from "@tiptap/react";
|
|
616
|
-
import { jsx } from "react/jsx-runtime";
|
|
683
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
617
684
|
var EditorContent = ({
|
|
618
685
|
className,
|
|
619
686
|
editor,
|
|
620
687
|
...props
|
|
621
688
|
}) => {
|
|
622
|
-
return /* @__PURE__ */
|
|
689
|
+
return /* @__PURE__ */ jsx2("div", { className, children: /* @__PURE__ */ jsx2(TipTapEditorContent, { editor, ...props }) });
|
|
623
690
|
};
|
|
624
691
|
|
|
625
692
|
// src/components/BubbleMenu.tsx
|
|
626
|
-
import { useEffect as
|
|
693
|
+
import { useEffect as useEffect8, useRef as useRef8, useState as useState4 } from "react";
|
|
627
694
|
import { createPortal } from "react-dom";
|
|
628
695
|
import {
|
|
629
696
|
BubbleMenuPlugin
|
|
@@ -637,12 +704,12 @@ var BubbleMenu = ({
|
|
|
637
704
|
pluginKey = "bubbleMenu",
|
|
638
705
|
updateDelay
|
|
639
706
|
}) => {
|
|
640
|
-
const menuEl =
|
|
707
|
+
const menuEl = useRef8(null);
|
|
641
708
|
const [mounted, setMounted] = useState4(false);
|
|
642
709
|
if (!menuEl.current && typeof document !== "undefined") {
|
|
643
710
|
menuEl.current = document.createElement("div");
|
|
644
711
|
}
|
|
645
|
-
|
|
712
|
+
useEffect8(() => {
|
|
646
713
|
if (!editor || !menuEl.current || editor.isDestroyed) {
|
|
647
714
|
return;
|
|
648
715
|
}
|
|
@@ -673,14 +740,14 @@ var BubbleMenu = ({
|
|
|
673
740
|
};
|
|
674
741
|
|
|
675
742
|
// src/components/TemplateRenderer.tsx
|
|
676
|
-
import { useMemo as
|
|
743
|
+
import { useMemo as useMemo5 } from "react";
|
|
677
744
|
import {
|
|
678
745
|
describeConditionalTag,
|
|
679
746
|
evaluatePromptTokens,
|
|
680
747
|
formatConditionalTag,
|
|
681
748
|
resolveTemplates
|
|
682
749
|
} from "@pixerate/editor";
|
|
683
|
-
import { jsx as
|
|
750
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
684
751
|
var TemplateRenderer = ({
|
|
685
752
|
content,
|
|
686
753
|
templates = [],
|
|
@@ -692,14 +759,14 @@ var TemplateRenderer = ({
|
|
|
692
759
|
onTemplateClick,
|
|
693
760
|
onVariableClick
|
|
694
761
|
}) => {
|
|
695
|
-
const displayText =
|
|
762
|
+
const displayText = useMemo5(() => {
|
|
696
763
|
if (!resolve || templates.length === 0) return content;
|
|
697
764
|
return resolveTemplates(content, templates, { bindings });
|
|
698
765
|
}, [content, templates, resolve, bindings]);
|
|
699
|
-
const tokens =
|
|
766
|
+
const tokens = useMemo5(() => {
|
|
700
767
|
return evaluatePromptTokens(displayText, values);
|
|
701
768
|
}, [displayText, values]);
|
|
702
|
-
return /* @__PURE__ */
|
|
769
|
+
return /* @__PURE__ */ jsx3("div", { className, children: tokens.map((token, index) => {
|
|
703
770
|
if (token.type === "template") {
|
|
704
771
|
const colors = templateColorMap?.get(token.value) || {
|
|
705
772
|
from: "#f43f5e",
|
|
@@ -709,7 +776,7 @@ var TemplateRenderer = ({
|
|
|
709
776
|
"--color-from": colors.from,
|
|
710
777
|
"--color-to": colors.to
|
|
711
778
|
};
|
|
712
|
-
return /* @__PURE__ */
|
|
779
|
+
return /* @__PURE__ */ jsx3(
|
|
713
780
|
"span",
|
|
714
781
|
{
|
|
715
782
|
style,
|
|
@@ -728,7 +795,7 @@ var TemplateRenderer = ({
|
|
|
728
795
|
token.defaultValue !== void 0 ? `Default: ${token.defaultValue || "(empty)"}` : void 0
|
|
729
796
|
].filter(Boolean).join("\n");
|
|
730
797
|
if (token.resolvedValue !== void 0) {
|
|
731
|
-
return /* @__PURE__ */
|
|
798
|
+
return /* @__PURE__ */ jsx3(
|
|
732
799
|
"span",
|
|
733
800
|
{
|
|
734
801
|
onClick: () => onVariableClick?.(token.value),
|
|
@@ -750,7 +817,7 @@ var TemplateRenderer = ({
|
|
|
750
817
|
title: details,
|
|
751
818
|
children: [
|
|
752
819
|
`{${token.value}`,
|
|
753
|
-
token.defaultValue !== void 0 && /* @__PURE__ */
|
|
820
|
+
token.defaultValue !== void 0 && /* @__PURE__ */ jsx3("span", { className: "opacity-60", children: `|${token.defaultValue}` }),
|
|
754
821
|
"}"
|
|
755
822
|
]
|
|
756
823
|
},
|
|
@@ -758,7 +825,7 @@ var TemplateRenderer = ({
|
|
|
758
825
|
);
|
|
759
826
|
}
|
|
760
827
|
if (token.type === "conditional" && token.conditional) {
|
|
761
|
-
return /* @__PURE__ */
|
|
828
|
+
return /* @__PURE__ */ jsx3(
|
|
762
829
|
"span",
|
|
763
830
|
{
|
|
764
831
|
"data-conditional": token.conditional,
|
|
@@ -770,7 +837,7 @@ var TemplateRenderer = ({
|
|
|
770
837
|
);
|
|
771
838
|
}
|
|
772
839
|
if (token.type === "instruction") {
|
|
773
|
-
return /* @__PURE__ */
|
|
840
|
+
return /* @__PURE__ */ jsx3(
|
|
774
841
|
"span",
|
|
775
842
|
{
|
|
776
843
|
className: "inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs italic font-medium rounded-md border border-rose-400/40 bg-rose-400/15 text-rose-600 dark:text-rose-300",
|
|
@@ -780,17 +847,17 @@ var TemplateRenderer = ({
|
|
|
780
847
|
index
|
|
781
848
|
);
|
|
782
849
|
}
|
|
783
|
-
return /* @__PURE__ */
|
|
850
|
+
return /* @__PURE__ */ jsx3("span", { children: token.value }, index);
|
|
784
851
|
}) });
|
|
785
852
|
};
|
|
786
853
|
|
|
787
854
|
// src/components/VariableForm.tsx
|
|
788
|
-
import { useId, useMemo as
|
|
855
|
+
import { useId, useMemo as useMemo6, useState as useState5 } from "react";
|
|
789
856
|
import {
|
|
790
857
|
compactVariableValues,
|
|
791
858
|
getVariableFormFields
|
|
792
859
|
} from "@pixerate/editor";
|
|
793
|
-
import { jsx as
|
|
860
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
794
861
|
var VariableForm = ({
|
|
795
862
|
content,
|
|
796
863
|
templates,
|
|
@@ -805,7 +872,7 @@ var VariableForm = ({
|
|
|
805
872
|
() => defaultValues ?? {}
|
|
806
873
|
);
|
|
807
874
|
const entered = values ?? internal;
|
|
808
|
-
const fields =
|
|
875
|
+
const fields = useMemo6(
|
|
809
876
|
() => getVariableFormFields(content, { templates, bindings }),
|
|
810
877
|
[content, templates, bindings]
|
|
811
878
|
);
|
|
@@ -815,7 +882,7 @@ var VariableForm = ({
|
|
|
815
882
|
onChange?.(compactVariableValues(next), next);
|
|
816
883
|
};
|
|
817
884
|
if (fields.length === 0) return null;
|
|
818
|
-
return /* @__PURE__ */
|
|
885
|
+
return /* @__PURE__ */ jsx4("form", { className, onSubmit: (event) => event.preventDefault(), children: fields.map((field) => {
|
|
819
886
|
const id = `${idPrefix}-${field.name}`;
|
|
820
887
|
if (field.conditionOnly) {
|
|
821
888
|
return /* @__PURE__ */ jsxs2(
|
|
@@ -825,7 +892,7 @@ var VariableForm = ({
|
|
|
825
892
|
className: "flex items-center gap-2",
|
|
826
893
|
"data-variable-field": field.name,
|
|
827
894
|
children: [
|
|
828
|
-
/* @__PURE__ */
|
|
895
|
+
/* @__PURE__ */ jsx4(
|
|
829
896
|
"input",
|
|
830
897
|
{
|
|
831
898
|
id,
|
|
@@ -835,7 +902,7 @@ var VariableForm = ({
|
|
|
835
902
|
onChange: (event) => update(field.name, event.target.checked ? "true" : "")
|
|
836
903
|
}
|
|
837
904
|
),
|
|
838
|
-
/* @__PURE__ */
|
|
905
|
+
/* @__PURE__ */ jsx4("span", { children: field.label })
|
|
839
906
|
]
|
|
840
907
|
},
|
|
841
908
|
field.name
|
|
@@ -850,9 +917,9 @@ var VariableForm = ({
|
|
|
850
917
|
children: [
|
|
851
918
|
/* @__PURE__ */ jsxs2("span", { className: "font-medium", children: [
|
|
852
919
|
field.label,
|
|
853
|
-
field.required && /* @__PURE__ */
|
|
920
|
+
field.required && /* @__PURE__ */ jsx4("span", { className: "text-rose-500", "aria-hidden": "true", children: " *" })
|
|
854
921
|
] }),
|
|
855
|
-
/* @__PURE__ */
|
|
922
|
+
/* @__PURE__ */ jsx4(
|
|
856
923
|
"input",
|
|
857
924
|
{
|
|
858
925
|
id,
|
|
@@ -876,7 +943,7 @@ var VariableForm = ({
|
|
|
876
943
|
import { useId as useId2, useState as useState7 } from "react";
|
|
877
944
|
|
|
878
945
|
// src/hooks/useMergePreview.ts
|
|
879
|
-
import { useCallback as useCallback5, useMemo as
|
|
946
|
+
import { useCallback as useCallback5, useMemo as useMemo7, useState as useState6 } from "react";
|
|
880
947
|
import {
|
|
881
948
|
extractVariables,
|
|
882
949
|
matchFields,
|
|
@@ -891,15 +958,15 @@ function useMergePreview(options) {
|
|
|
891
958
|
const [overrides, setOverrides] = useState6({});
|
|
892
959
|
const [index, setIndexState] = useState6(0);
|
|
893
960
|
const [result, setResult] = useState6(null);
|
|
894
|
-
const source =
|
|
961
|
+
const source = useMemo7(
|
|
895
962
|
() => parseDataSource(sourceText, parseOptions),
|
|
896
963
|
[sourceText, parseOptions]
|
|
897
964
|
);
|
|
898
|
-
const variables =
|
|
965
|
+
const variables = useMemo7(
|
|
899
966
|
() => extractVariables(template, { templates, bindings }).map((v) => v.name),
|
|
900
967
|
[template, templates, bindings]
|
|
901
968
|
);
|
|
902
|
-
const mapping =
|
|
969
|
+
const mapping = useMemo7(() => {
|
|
903
970
|
const merged = {
|
|
904
971
|
...matchFields(variables, source.fields).mapping
|
|
905
972
|
};
|
|
@@ -913,7 +980,7 @@ function useMergePreview(options) {
|
|
|
913
980
|
const count = source.records.length;
|
|
914
981
|
const current = count === 0 ? 0 : Math.min(index, count - 1);
|
|
915
982
|
const record = source.records[current];
|
|
916
|
-
const values =
|
|
983
|
+
const values = useMemo7(
|
|
917
984
|
() => record ? recordToValues(record, mapping) : {},
|
|
918
985
|
[record, mapping]
|
|
919
986
|
);
|
|
@@ -974,7 +1041,7 @@ function useMergePreview(options) {
|
|
|
974
1041
|
}
|
|
975
1042
|
|
|
976
1043
|
// src/components/MergePreview.tsx
|
|
977
|
-
import { Fragment, jsx as
|
|
1044
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
978
1045
|
function downloadText(text, fileName, type) {
|
|
979
1046
|
if (typeof document === "undefined" || typeof URL.createObjectURL !== "function") {
|
|
980
1047
|
return;
|
|
@@ -1023,8 +1090,8 @@ var MergePreview = ({
|
|
|
1023
1090
|
};
|
|
1024
1091
|
return /* @__PURE__ */ jsxs3("div", { className, "data-merge-preview": "", children: [
|
|
1025
1092
|
/* @__PURE__ */ jsxs3("label", { htmlFor: `${id}-source`, className: "flex flex-col gap-1", children: [
|
|
1026
|
-
/* @__PURE__ */
|
|
1027
|
-
/* @__PURE__ */
|
|
1093
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium", children: "Data source (CSV, TSV or JSON)" }),
|
|
1094
|
+
/* @__PURE__ */ jsx5(
|
|
1028
1095
|
"textarea",
|
|
1029
1096
|
{
|
|
1030
1097
|
id: `${id}-source`,
|
|
@@ -1038,7 +1105,7 @@ var MergePreview = ({
|
|
|
1038
1105
|
)
|
|
1039
1106
|
] }),
|
|
1040
1107
|
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1041
|
-
/* @__PURE__ */
|
|
1108
|
+
/* @__PURE__ */ jsx5(
|
|
1042
1109
|
"input",
|
|
1043
1110
|
{
|
|
1044
1111
|
type: "file",
|
|
@@ -1051,18 +1118,18 @@ var MergePreview = ({
|
|
|
1051
1118
|
}
|
|
1052
1119
|
}
|
|
1053
1120
|
),
|
|
1054
|
-
/* @__PURE__ */
|
|
1121
|
+
/* @__PURE__ */ jsx5("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
1122
|
] }),
|
|
1056
|
-
source.warnings.length > 0 && merge.sourceText.trim() !== "" && /* @__PURE__ */
|
|
1123
|
+
source.warnings.length > 0 && merge.sourceText.trim() !== "" && /* @__PURE__ */ jsx5("ul", { "data-merge-warnings": "", className: "text-amber-600 text-xs", children: source.warnings.map((warning, i) => /* @__PURE__ */ jsx5("li", { children: warning.message }, i)) }),
|
|
1057
1124
|
merge.variables.length > 0 && /* @__PURE__ */ jsxs3("fieldset", { className: "flex flex-col gap-1", children: [
|
|
1058
|
-
/* @__PURE__ */
|
|
1125
|
+
/* @__PURE__ */ jsx5("legend", { className: "font-medium", children: "Field mapping" }),
|
|
1059
1126
|
merge.variables.map((variable) => /* @__PURE__ */ jsxs3(
|
|
1060
1127
|
"label",
|
|
1061
1128
|
{
|
|
1062
1129
|
className: "flex items-center gap-2",
|
|
1063
1130
|
"data-merge-mapping": variable,
|
|
1064
1131
|
children: [
|
|
1065
|
-
/* @__PURE__ */
|
|
1132
|
+
/* @__PURE__ */ jsx5("span", { className: "min-w-24 font-mono", children: `{${variable}}` }),
|
|
1066
1133
|
/* @__PURE__ */ jsxs3(
|
|
1067
1134
|
"select",
|
|
1068
1135
|
{
|
|
@@ -1071,8 +1138,8 @@ var MergePreview = ({
|
|
|
1071
1138
|
onChange: (event) => merge.setFieldMapping(variable, event.target.value || null),
|
|
1072
1139
|
className: "px-1 py-0.5 rounded-md border border-violet-400/40 bg-transparent",
|
|
1073
1140
|
children: [
|
|
1074
|
-
/* @__PURE__ */
|
|
1075
|
-
source.fields.map((field) => /* @__PURE__ */
|
|
1141
|
+
/* @__PURE__ */ jsx5("option", { value: "", children: "(none)" }),
|
|
1142
|
+
source.fields.map((field) => /* @__PURE__ */ jsx5("option", { value: field, children: field }, field))
|
|
1076
1143
|
]
|
|
1077
1144
|
}
|
|
1078
1145
|
)
|
|
@@ -1082,7 +1149,7 @@ var MergePreview = ({
|
|
|
1082
1149
|
))
|
|
1083
1150
|
] }),
|
|
1084
1151
|
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
|
|
1085
|
-
/* @__PURE__ */
|
|
1152
|
+
/* @__PURE__ */ jsx5(
|
|
1086
1153
|
"button",
|
|
1087
1154
|
{
|
|
1088
1155
|
type: "button",
|
|
@@ -1092,8 +1159,8 @@ var MergePreview = ({
|
|
|
1092
1159
|
children: "Prev"
|
|
1093
1160
|
}
|
|
1094
1161
|
),
|
|
1095
|
-
/* @__PURE__ */
|
|
1096
|
-
/* @__PURE__ */
|
|
1162
|
+
/* @__PURE__ */ jsx5("span", { "data-merge-position": "", children: merge.count === 0 ? "No records" : `Record ${merge.index + 1} of ${merge.count}` }),
|
|
1163
|
+
/* @__PURE__ */ jsx5(
|
|
1097
1164
|
"button",
|
|
1098
1165
|
{
|
|
1099
1166
|
type: "button",
|
|
@@ -1104,7 +1171,7 @@ var MergePreview = ({
|
|
|
1104
1171
|
}
|
|
1105
1172
|
)
|
|
1106
1173
|
] }),
|
|
1107
|
-
/* @__PURE__ */
|
|
1174
|
+
/* @__PURE__ */ jsx5("div", { "data-merge-output": "", children: /* @__PURE__ */ jsx5(
|
|
1108
1175
|
TemplateRenderer,
|
|
1109
1176
|
{
|
|
1110
1177
|
content,
|
|
@@ -1116,7 +1183,7 @@ var MergePreview = ({
|
|
|
1116
1183
|
}
|
|
1117
1184
|
) }),
|
|
1118
1185
|
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1119
|
-
/* @__PURE__ */
|
|
1186
|
+
/* @__PURE__ */ jsx5(
|
|
1120
1187
|
"button",
|
|
1121
1188
|
{
|
|
1122
1189
|
type: "button",
|
|
@@ -1131,9 +1198,9 @@ var MergePreview = ({
|
|
|
1131
1198
|
}
|
|
1132
1199
|
),
|
|
1133
1200
|
result && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
1134
|
-
/* @__PURE__ */
|
|
1135
|
-
/* @__PURE__ */
|
|
1136
|
-
/* @__PURE__ */
|
|
1201
|
+
/* @__PURE__ */ jsx5("span", { "data-merge-result": "", children: `${result.outputs.length} merged${result.skipped.length ? `, ${result.skipped.length} skipped` : ""}${result.truncated ? " (stopped early)" : ""}` }),
|
|
1202
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "data-merge-copy": "", onClick: copy, children: copied ? "Copied" : "Copy" }),
|
|
1203
|
+
/* @__PURE__ */ jsx5(
|
|
1137
1204
|
"button",
|
|
1138
1205
|
{
|
|
1139
1206
|
type: "button",
|
|
@@ -1142,7 +1209,7 @@ var MergePreview = ({
|
|
|
1142
1209
|
children: "Download .txt"
|
|
1143
1210
|
}
|
|
1144
1211
|
),
|
|
1145
|
-
/* @__PURE__ */
|
|
1212
|
+
/* @__PURE__ */ jsx5(
|
|
1146
1213
|
"button",
|
|
1147
1214
|
{
|
|
1148
1215
|
type: "button",
|
|
@@ -1153,7 +1220,7 @@ var MergePreview = ({
|
|
|
1153
1220
|
)
|
|
1154
1221
|
] })
|
|
1155
1222
|
] }),
|
|
1156
|
-
result && /* @__PURE__ */
|
|
1223
|
+
result && /* @__PURE__ */ jsx5(
|
|
1157
1224
|
"textarea",
|
|
1158
1225
|
{
|
|
1159
1226
|
readOnly: true,
|
|
@@ -1168,16 +1235,16 @@ var MergePreview = ({
|
|
|
1168
1235
|
};
|
|
1169
1236
|
|
|
1170
1237
|
// src/hooks/useOutline.ts
|
|
1171
|
-
import { useMemo as
|
|
1238
|
+
import { useMemo as useMemo8, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
1172
1239
|
import { createOutlineStore } from "@pixerate/editor";
|
|
1173
1240
|
function useOutline(editor) {
|
|
1174
|
-
const store =
|
|
1175
|
-
return
|
|
1241
|
+
const store = useMemo8(() => createOutlineStore(editor), [editor]);
|
|
1242
|
+
return useSyncExternalStore5(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
1176
1243
|
}
|
|
1177
1244
|
|
|
1178
1245
|
// src/components/OutlinePanel.tsx
|
|
1179
1246
|
import { navigateToHeading } from "@pixerate/editor";
|
|
1180
|
-
import { jsx as
|
|
1247
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1181
1248
|
var OutlinePanel = ({
|
|
1182
1249
|
editor,
|
|
1183
1250
|
title = "Outline",
|
|
@@ -1192,10 +1259,10 @@ var OutlinePanel = ({
|
|
|
1192
1259
|
const { headings, activeId } = useOutline(editor);
|
|
1193
1260
|
const visible = headings.filter((h) => h.level <= maxLevel);
|
|
1194
1261
|
return /* @__PURE__ */ jsxs4("nav", { className, "aria-label": "Document outline", "data-outline-panel": "", children: [
|
|
1195
|
-
title != null && /* @__PURE__ */
|
|
1196
|
-
visible.length === 0 ? /* @__PURE__ */
|
|
1262
|
+
title != null && /* @__PURE__ */ jsx6("div", { className: "pixerate-outline-title", children: title }),
|
|
1263
|
+
visible.length === 0 ? /* @__PURE__ */ jsx6("div", { className: "pixerate-outline-empty", children: emptyState }) : /* @__PURE__ */ jsx6("ul", { role: "list", style: { listStyle: "none", margin: 0, padding: 0 }, children: visible.map((heading) => {
|
|
1197
1264
|
const active = heading.id === activeId;
|
|
1198
|
-
return /* @__PURE__ */
|
|
1265
|
+
return /* @__PURE__ */ jsx6("li", { "data-level": heading.level, children: /* @__PURE__ */ jsx6(
|
|
1199
1266
|
"button",
|
|
1200
1267
|
{
|
|
1201
1268
|
type: "button",
|
|
@@ -1216,6 +1283,168 @@ var OutlinePanel = ({
|
|
|
1216
1283
|
] });
|
|
1217
1284
|
};
|
|
1218
1285
|
|
|
1286
|
+
// src/hooks/useParagraphStyles.ts
|
|
1287
|
+
import { useMemo as useMemo9, useSyncExternalStore as useSyncExternalStore6 } from "react";
|
|
1288
|
+
import {
|
|
1289
|
+
createParagraphStylesStore,
|
|
1290
|
+
getStyleRegistry
|
|
1291
|
+
} from "@pixerate/editor";
|
|
1292
|
+
function useParagraphStyles(editor) {
|
|
1293
|
+
const store = useMemo9(() => createParagraphStylesStore(editor), [editor]);
|
|
1294
|
+
const snapshot = useSyncExternalStore6(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
1295
|
+
return useMemo9(() => {
|
|
1296
|
+
const registry = getStyleRegistry(editor);
|
|
1297
|
+
const live = () => editor && !editor.isDestroyed ? editor : null;
|
|
1298
|
+
return {
|
|
1299
|
+
...snapshot,
|
|
1300
|
+
registry,
|
|
1301
|
+
currentStyle: snapshot.currentStyleId && registry?.get(snapshot.currentStyleId) || null,
|
|
1302
|
+
apply: (id) => !!live()?.chain().focus().setParagraphStyle(id).run(),
|
|
1303
|
+
clear: () => !!live()?.chain().focus().clearParagraphStyle().run(),
|
|
1304
|
+
updateFromSelection: (id) => !!live()?.chain().focus().updateParagraphStyleFromSelection(id).run(),
|
|
1305
|
+
createFromSelection: (name, options) => {
|
|
1306
|
+
const e = live();
|
|
1307
|
+
if (!e || !registry) return null;
|
|
1308
|
+
const id = options?.id ?? registry.newId(name.trim());
|
|
1309
|
+
const ok = e.chain().focus().createParagraphStyleFromSelection(name, { ...options, id }).run();
|
|
1310
|
+
return ok ? id : null;
|
|
1311
|
+
},
|
|
1312
|
+
applyCharacterStyle: (id) => !!live()?.chain().focus().setCharacterStyle(id).run()
|
|
1313
|
+
};
|
|
1314
|
+
}, [snapshot, editor]);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
// src/components/StylesGallery.tsx
|
|
1318
|
+
import { useState as useState8 } from "react";
|
|
1319
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1320
|
+
var camel = (property) => property.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
1321
|
+
var keepSelection = (event) => event.preventDefault();
|
|
1322
|
+
var StylesGallery = ({
|
|
1323
|
+
editor,
|
|
1324
|
+
variant = "dropdown",
|
|
1325
|
+
showAllStyles = false,
|
|
1326
|
+
showActions = true,
|
|
1327
|
+
preview = true,
|
|
1328
|
+
className = "relative inline-flex flex-wrap items-center gap-1 text-sm",
|
|
1329
|
+
itemClassName = "rounded px-2 py-1 text-left text-xs text-foreground hover:bg-muted",
|
|
1330
|
+
activeItemClassName = "bg-primary/10 text-primary",
|
|
1331
|
+
onChange
|
|
1332
|
+
}) => {
|
|
1333
|
+
const styles = useParagraphStyles(editor);
|
|
1334
|
+
const [open, setOpen] = useState8(false);
|
|
1335
|
+
const [creating, setCreating] = useState8(false);
|
|
1336
|
+
const [name, setName] = useState8("");
|
|
1337
|
+
const list = showAllStyles ? styles.styles : styles.gallery;
|
|
1338
|
+
const current = styles.currentStyle;
|
|
1339
|
+
const expanded = variant === "gallery" || open;
|
|
1340
|
+
const close = () => {
|
|
1341
|
+
if (variant === "dropdown") setOpen(false);
|
|
1342
|
+
setCreating(false);
|
|
1343
|
+
setName("");
|
|
1344
|
+
};
|
|
1345
|
+
const previewStyle = (id) => {
|
|
1346
|
+
if (!preview || !styles.registry) return void 0;
|
|
1347
|
+
return Object.fromEntries(
|
|
1348
|
+
Object.entries(styles.registry.previewDeclarations(id)).map(([k, v]) => [camel(k), v])
|
|
1349
|
+
);
|
|
1350
|
+
};
|
|
1351
|
+
const apply = (id) => {
|
|
1352
|
+
if (styles.apply(id)) onChange?.({ type: "apply", id });
|
|
1353
|
+
close();
|
|
1354
|
+
};
|
|
1355
|
+
const create = (event) => {
|
|
1356
|
+
event.preventDefault();
|
|
1357
|
+
const id = name.trim() ? styles.createFromSelection(name) : null;
|
|
1358
|
+
if (id) onChange?.({ type: "create", id });
|
|
1359
|
+
close();
|
|
1360
|
+
};
|
|
1361
|
+
return /* @__PURE__ */ jsxs5("div", { className, role: "group", "aria-label": "Paragraph styles", "data-styles-gallery": variant, children: [
|
|
1362
|
+
variant === "dropdown" && /* @__PURE__ */ jsxs5(
|
|
1363
|
+
"button",
|
|
1364
|
+
{
|
|
1365
|
+
type: "button",
|
|
1366
|
+
className: itemClassName,
|
|
1367
|
+
"aria-haspopup": "listbox",
|
|
1368
|
+
"aria-expanded": open,
|
|
1369
|
+
disabled: !editor || !styles.registry,
|
|
1370
|
+
onMouseDown: keepSelection,
|
|
1371
|
+
onClick: () => setOpen((value) => !value),
|
|
1372
|
+
children: [
|
|
1373
|
+
current?.name ?? "Styles",
|
|
1374
|
+
" \u25BE"
|
|
1375
|
+
]
|
|
1376
|
+
}
|
|
1377
|
+
),
|
|
1378
|
+
expanded && /* @__PURE__ */ jsxs5(
|
|
1379
|
+
"div",
|
|
1380
|
+
{
|
|
1381
|
+
className: variant === "dropdown" ? "absolute left-0 top-full z-20 mt-1 flex min-w-[12rem] flex-col gap-0.5 rounded-md border border-border bg-background p-1 shadow-md" : "flex flex-wrap items-center gap-1",
|
|
1382
|
+
children: [
|
|
1383
|
+
/* @__PURE__ */ jsx7("div", { role: "listbox", "aria-label": "Styles", className: variant === "dropdown" ? "flex flex-col gap-0.5" : "flex flex-wrap gap-1", children: list.map((style) => {
|
|
1384
|
+
const active = style.id === styles.currentStyleId;
|
|
1385
|
+
return /* @__PURE__ */ jsx7(
|
|
1386
|
+
"button",
|
|
1387
|
+
{
|
|
1388
|
+
type: "button",
|
|
1389
|
+
role: "option",
|
|
1390
|
+
"aria-selected": active,
|
|
1391
|
+
"data-style-id": style.id,
|
|
1392
|
+
className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
|
|
1393
|
+
style: previewStyle(style.id),
|
|
1394
|
+
onMouseDown: keepSelection,
|
|
1395
|
+
onClick: () => apply(style.id),
|
|
1396
|
+
children: style.name
|
|
1397
|
+
},
|
|
1398
|
+
style.id
|
|
1399
|
+
);
|
|
1400
|
+
}) }),
|
|
1401
|
+
showActions && /* @__PURE__ */ jsxs5("div", { className: variant === "dropdown" ? "mt-1 flex flex-col gap-0.5 border-t border-border pt-1" : "flex items-center gap-1", children: [
|
|
1402
|
+
/* @__PURE__ */ jsx7(
|
|
1403
|
+
"button",
|
|
1404
|
+
{
|
|
1405
|
+
type: "button",
|
|
1406
|
+
className: itemClassName,
|
|
1407
|
+
disabled: !current,
|
|
1408
|
+
onMouseDown: keepSelection,
|
|
1409
|
+
onClick: () => {
|
|
1410
|
+
if (current && styles.updateFromSelection(current.id)) {
|
|
1411
|
+
onChange?.({ type: "update", id: current.id });
|
|
1412
|
+
}
|
|
1413
|
+
close();
|
|
1414
|
+
},
|
|
1415
|
+
children: current ? `Update ${current.name} to match selection` : "Update to match selection"
|
|
1416
|
+
}
|
|
1417
|
+
),
|
|
1418
|
+
creating ? /* @__PURE__ */ jsxs5("form", { className: "flex items-center gap-1", onSubmit: create, children: [
|
|
1419
|
+
/* @__PURE__ */ jsx7(
|
|
1420
|
+
"input",
|
|
1421
|
+
{
|
|
1422
|
+
"aria-label": "New style name",
|
|
1423
|
+
className: "w-32 rounded border border-border bg-background px-1 py-0.5 text-xs",
|
|
1424
|
+
value: name,
|
|
1425
|
+
autoFocus: true,
|
|
1426
|
+
onChange: (event) => setName(event.target.value)
|
|
1427
|
+
}
|
|
1428
|
+
),
|
|
1429
|
+
/* @__PURE__ */ jsx7("button", { type: "submit", className: itemClassName, disabled: !name.trim(), children: "Create" })
|
|
1430
|
+
] }) : /* @__PURE__ */ jsx7(
|
|
1431
|
+
"button",
|
|
1432
|
+
{
|
|
1433
|
+
type: "button",
|
|
1434
|
+
className: itemClassName,
|
|
1435
|
+
disabled: !editor || !styles.registry,
|
|
1436
|
+
onMouseDown: keepSelection,
|
|
1437
|
+
onClick: () => setCreating(true),
|
|
1438
|
+
children: "New style from selection"
|
|
1439
|
+
}
|
|
1440
|
+
)
|
|
1441
|
+
] })
|
|
1442
|
+
]
|
|
1443
|
+
}
|
|
1444
|
+
)
|
|
1445
|
+
] });
|
|
1446
|
+
};
|
|
1447
|
+
|
|
1219
1448
|
// src/index.ts
|
|
1220
1449
|
import {
|
|
1221
1450
|
DirtyTracker as DirtyTracker2,
|
|
@@ -1228,10 +1457,10 @@ import {
|
|
|
1228
1457
|
} from "@pixerate/editor";
|
|
1229
1458
|
|
|
1230
1459
|
// src/slots.tsx
|
|
1231
|
-
import { createContext, useContext, useMemo as
|
|
1232
|
-
import { jsx as
|
|
1460
|
+
import { createContext, useContext, useMemo as useMemo10 } from "react";
|
|
1461
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1233
1462
|
var defaultSlots = {
|
|
1234
|
-
Button: (props) => /* @__PURE__ */
|
|
1463
|
+
Button: (props) => /* @__PURE__ */ jsx8(
|
|
1235
1464
|
"button",
|
|
1236
1465
|
{
|
|
1237
1466
|
type: "button",
|
|
@@ -1241,26 +1470,26 @@ var defaultSlots = {
|
|
|
1241
1470
|
children: props.children
|
|
1242
1471
|
}
|
|
1243
1472
|
),
|
|
1244
|
-
Tooltip: (props) => /* @__PURE__ */
|
|
1245
|
-
NodeHeader: (props) => /* @__PURE__ */
|
|
1246
|
-
/* @__PURE__ */
|
|
1473
|
+
Tooltip: (props) => /* @__PURE__ */ jsx8("div", { className: `pixerate-tooltip-container ${props.className || ""}`, title: String(props.content), children: props.children }),
|
|
1474
|
+
NodeHeader: (props) => /* @__PURE__ */ jsxs6("div", { className: `pixerate-node-header flex items-center justify-between ${props.className || ""}`, children: [
|
|
1475
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
1247
1476
|
props.icon,
|
|
1248
|
-
/* @__PURE__ */
|
|
1477
|
+
/* @__PURE__ */ jsx8("span", { className: "font-semibold", children: props.title })
|
|
1249
1478
|
] }),
|
|
1250
|
-
props.onClose && /* @__PURE__ */
|
|
1479
|
+
props.onClose && /* @__PURE__ */ jsx8("button", { type: "button", onClick: props.onClose, className: "opacity-70 hover:opacity-100", children: "\xD7" })
|
|
1251
1480
|
] })
|
|
1252
1481
|
};
|
|
1253
1482
|
var EditorSlotsContext = createContext(defaultSlots);
|
|
1254
1483
|
function EditorSlotsProvider({ slots, children }) {
|
|
1255
|
-
const mergedSlots =
|
|
1256
|
-
return /* @__PURE__ */
|
|
1484
|
+
const mergedSlots = useMemo10(() => ({ ...defaultSlots, ...slots }), [slots]);
|
|
1485
|
+
return /* @__PURE__ */ jsx8(EditorSlotsContext.Provider, { value: mergedSlots, children });
|
|
1257
1486
|
}
|
|
1258
1487
|
function useEditorSlots() {
|
|
1259
1488
|
return useContext(EditorSlotsContext);
|
|
1260
1489
|
}
|
|
1261
1490
|
|
|
1262
1491
|
// src/review/useReview.ts
|
|
1263
|
-
import { useCallback as useCallback6, useMemo as
|
|
1492
|
+
import { useCallback as useCallback6, useMemo as useMemo11, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
1264
1493
|
import {
|
|
1265
1494
|
getCommentStore,
|
|
1266
1495
|
getTrackChangesStore
|
|
@@ -1287,8 +1516,8 @@ function useComments(source) {
|
|
|
1287
1516
|
[store]
|
|
1288
1517
|
);
|
|
1289
1518
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
|
|
1290
|
-
const snapshot =
|
|
1291
|
-
return
|
|
1519
|
+
const snapshot = useSyncExternalStore7(subscribe, getSnapshot, getSnapshot);
|
|
1520
|
+
return useMemo11(() => ({ ...snapshot, store }), [snapshot, store]);
|
|
1292
1521
|
}
|
|
1293
1522
|
function useTrackChanges(editor) {
|
|
1294
1523
|
const store = getTrackChangesStore(editor ?? null);
|
|
@@ -1297,8 +1526,8 @@ function useTrackChanges(editor) {
|
|
|
1297
1526
|
[store]
|
|
1298
1527
|
);
|
|
1299
1528
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
|
|
1300
|
-
const snapshot =
|
|
1301
|
-
return
|
|
1529
|
+
const snapshot = useSyncExternalStore7(subscribe, getSnapshot, getSnapshot);
|
|
1530
|
+
return useMemo11(() => {
|
|
1302
1531
|
const run = (fn) => () => {
|
|
1303
1532
|
if (editor && !editor.isDestroyed) fn(editor);
|
|
1304
1533
|
};
|
|
@@ -1312,18 +1541,21 @@ function useTrackChanges(editor) {
|
|
|
1312
1541
|
acceptAll: run((e) => e.commands.acceptAllChanges()),
|
|
1313
1542
|
rejectAll: run((e) => e.commands.rejectAllChanges()),
|
|
1314
1543
|
next: run((e) => e.chain().focus().selectNextChange().run()),
|
|
1315
|
-
previous: run((e) => e.chain().focus().selectPreviousChange().run())
|
|
1544
|
+
previous: run((e) => e.chain().focus().selectPreviousChange().run()),
|
|
1545
|
+
select: (id) => run((e) => e.chain().focus().selectChange(id).run())(),
|
|
1546
|
+
acceptMove: (id) => run((e) => e.commands.acceptMove(id))(),
|
|
1547
|
+
rejectMove: (id) => run((e) => e.commands.rejectMove(id))()
|
|
1316
1548
|
};
|
|
1317
1549
|
}, [snapshot, editor]);
|
|
1318
1550
|
}
|
|
1319
1551
|
|
|
1320
1552
|
// src/review/CommentsPanel.tsx
|
|
1321
|
-
import { useState as
|
|
1553
|
+
import { useState as useState9 } from "react";
|
|
1322
1554
|
import {
|
|
1323
1555
|
formatReviewTime,
|
|
1324
1556
|
getCommentAuthor
|
|
1325
1557
|
} from "@pixerate/editor";
|
|
1326
|
-
import { jsx as
|
|
1558
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1327
1559
|
var buttonClass = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
|
|
1328
1560
|
var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
|
|
1329
1561
|
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";
|
|
@@ -1337,18 +1569,18 @@ var CommentsPanel = ({
|
|
|
1337
1569
|
emptyMessage = "No comments yet. Select text and add a comment."
|
|
1338
1570
|
}) => {
|
|
1339
1571
|
const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
|
|
1340
|
-
const [showResolved, setShowResolved] =
|
|
1572
|
+
const [showResolved, setShowResolved] = useState9(showResolvedInitial);
|
|
1341
1573
|
const author = authorProp ?? getCommentAuthor(editor) ?? { id: "anonymous", name: "Anonymous" };
|
|
1342
1574
|
const visible = threads.filter((t) => showResolved || !t.resolved);
|
|
1343
1575
|
const resolvedCount = threads.filter((t) => t.resolved).length;
|
|
1344
|
-
return /* @__PURE__ */
|
|
1345
|
-
/* @__PURE__ */
|
|
1346
|
-
/* @__PURE__ */
|
|
1576
|
+
return /* @__PURE__ */ jsxs7("aside", { className, "aria-label": "Comments", children: [
|
|
1577
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1578
|
+
/* @__PURE__ */ jsxs7("span", { className: "text-xs font-medium text-muted-foreground", children: [
|
|
1347
1579
|
threads.length - resolvedCount,
|
|
1348
1580
|
" open",
|
|
1349
1581
|
resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
|
|
1350
1582
|
] }),
|
|
1351
|
-
resolvedCount > 0 && /* @__PURE__ */
|
|
1583
|
+
resolvedCount > 0 && /* @__PURE__ */ jsx9(
|
|
1352
1584
|
"button",
|
|
1353
1585
|
{
|
|
1354
1586
|
type: "button",
|
|
@@ -1359,7 +1591,7 @@ var CommentsPanel = ({
|
|
|
1359
1591
|
}
|
|
1360
1592
|
)
|
|
1361
1593
|
] }),
|
|
1362
|
-
visible.length === 0 ? /* @__PURE__ */
|
|
1594
|
+
visible.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ jsx9("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ jsx9(
|
|
1363
1595
|
CommentThreadCard,
|
|
1364
1596
|
{
|
|
1365
1597
|
thread,
|
|
@@ -1381,7 +1613,7 @@ var CommentThreadCard = ({
|
|
|
1381
1613
|
author,
|
|
1382
1614
|
formatTime
|
|
1383
1615
|
}) => {
|
|
1384
|
-
const [draft, setDraft] =
|
|
1616
|
+
const [draft, setDraft] = useState9("");
|
|
1385
1617
|
const isDraft = thread.body === "";
|
|
1386
1618
|
const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
|
|
1387
1619
|
const live = editor && !editor.isDestroyed ? editor : null;
|
|
@@ -1407,7 +1639,7 @@ var CommentThreadCard = ({
|
|
|
1407
1639
|
setDraft("");
|
|
1408
1640
|
};
|
|
1409
1641
|
const stop = (e) => e.stopPropagation();
|
|
1410
|
-
return /* @__PURE__ */
|
|
1642
|
+
return /* @__PURE__ */ jsxs7(
|
|
1411
1643
|
"li",
|
|
1412
1644
|
{
|
|
1413
1645
|
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" : ""}`,
|
|
@@ -1423,24 +1655,24 @@ var CommentThreadCard = ({
|
|
|
1423
1655
|
}
|
|
1424
1656
|
},
|
|
1425
1657
|
children: [
|
|
1426
|
-
/* @__PURE__ */
|
|
1427
|
-
/* @__PURE__ */
|
|
1428
|
-
/* @__PURE__ */
|
|
1658
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
1659
|
+
/* @__PURE__ */ jsx9("span", { className: "font-medium", children: thread.author.name }),
|
|
1660
|
+
/* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
|
|
1429
1661
|
] }),
|
|
1430
|
-
quote && /* @__PURE__ */
|
|
1431
|
-
thread.orphaned && /* @__PURE__ */
|
|
1432
|
-
thread.resolved && /* @__PURE__ */
|
|
1433
|
-
!isDraft && /* @__PURE__ */
|
|
1434
|
-
thread.replies.length > 0 && /* @__PURE__ */
|
|
1435
|
-
/* @__PURE__ */
|
|
1436
|
-
/* @__PURE__ */
|
|
1662
|
+
quote && /* @__PURE__ */ jsx9("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
|
|
1663
|
+
thread.orphaned && /* @__PURE__ */ jsx9("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
|
|
1664
|
+
thread.resolved && /* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
|
|
1665
|
+
!isDraft && /* @__PURE__ */ jsx9("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
|
|
1666
|
+
thread.replies.length > 0 && /* @__PURE__ */ jsx9("ul", { className: "flex flex-col gap-2 border-l border-border pl-3", role: "list", children: thread.replies.map((reply) => /* @__PURE__ */ jsxs7("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
|
|
1667
|
+
/* @__PURE__ */ jsxs7("span", { className: "text-xs", children: [
|
|
1668
|
+
/* @__PURE__ */ jsx9("span", { className: "font-medium", children: reply.author.name }),
|
|
1437
1669
|
" ",
|
|
1438
|
-
/* @__PURE__ */
|
|
1670
|
+
/* @__PURE__ */ jsx9("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
|
|
1439
1671
|
] }),
|
|
1440
|
-
/* @__PURE__ */
|
|
1672
|
+
/* @__PURE__ */ jsx9("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
|
|
1441
1673
|
] }, reply.id)) }),
|
|
1442
|
-
(active || isDraft) && !thread.resolved && /* @__PURE__ */
|
|
1443
|
-
/* @__PURE__ */
|
|
1674
|
+
(active || isDraft) && !thread.resolved && /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1", onClick: stop, children: [
|
|
1675
|
+
/* @__PURE__ */ jsx9(
|
|
1444
1676
|
"textarea",
|
|
1445
1677
|
{
|
|
1446
1678
|
className: textareaClass,
|
|
@@ -1458,9 +1690,9 @@ var CommentThreadCard = ({
|
|
|
1458
1690
|
}
|
|
1459
1691
|
}
|
|
1460
1692
|
),
|
|
1461
|
-
/* @__PURE__ */
|
|
1462
|
-
isDraft && /* @__PURE__ */
|
|
1463
|
-
/* @__PURE__ */
|
|
1693
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex justify-end gap-1", children: [
|
|
1694
|
+
isDraft && /* @__PURE__ */ jsx9("button", { type: "button", className: buttonClass, onClick: remove, children: "Cancel" }),
|
|
1695
|
+
/* @__PURE__ */ jsx9(
|
|
1464
1696
|
"button",
|
|
1465
1697
|
{
|
|
1466
1698
|
type: "button",
|
|
@@ -1472,9 +1704,9 @@ var CommentThreadCard = ({
|
|
|
1472
1704
|
)
|
|
1473
1705
|
] })
|
|
1474
1706
|
] }),
|
|
1475
|
-
!isDraft && /* @__PURE__ */
|
|
1476
|
-
/* @__PURE__ */
|
|
1477
|
-
/* @__PURE__ */
|
|
1707
|
+
!isDraft && /* @__PURE__ */ jsxs7("div", { className: "flex justify-end gap-1", onClick: stop, children: [
|
|
1708
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: buttonClass, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
|
|
1709
|
+
/* @__PURE__ */ jsx9(
|
|
1478
1710
|
"button",
|
|
1479
1711
|
{
|
|
1480
1712
|
type: "button",
|
|
@@ -1490,7 +1722,7 @@ var CommentThreadCard = ({
|
|
|
1490
1722
|
};
|
|
1491
1723
|
|
|
1492
1724
|
// src/review/ReviewToolbar.tsx
|
|
1493
|
-
import { jsx as
|
|
1725
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1494
1726
|
var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
|
|
1495
1727
|
var buttonClass2 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
1496
1728
|
var ReviewToolbar = ({
|
|
@@ -1503,8 +1735,8 @@ var ReviewToolbar = ({
|
|
|
1503
1735
|
const count = review.changes.length;
|
|
1504
1736
|
const current = review.currentChange;
|
|
1505
1737
|
const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
|
|
1506
|
-
return /* @__PURE__ */
|
|
1507
|
-
/* @__PURE__ */
|
|
1738
|
+
return /* @__PURE__ */ jsxs8("div", { className, role: "toolbar", "aria-label": "Review", children: [
|
|
1739
|
+
/* @__PURE__ */ jsx10(
|
|
1508
1740
|
"button",
|
|
1509
1741
|
{
|
|
1510
1742
|
type: "button",
|
|
@@ -1515,8 +1747,8 @@ var ReviewToolbar = ({
|
|
|
1515
1747
|
children: review.enabled ? "Tracking on" : "Track changes"
|
|
1516
1748
|
}
|
|
1517
1749
|
),
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1750
|
+
/* @__PURE__ */ jsx10("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
1751
|
+
/* @__PURE__ */ jsx10(
|
|
1520
1752
|
"button",
|
|
1521
1753
|
{
|
|
1522
1754
|
type: "button",
|
|
@@ -1527,8 +1759,8 @@ var ReviewToolbar = ({
|
|
|
1527
1759
|
children: "\u2039"
|
|
1528
1760
|
}
|
|
1529
1761
|
),
|
|
1530
|
-
/* @__PURE__ */
|
|
1531
|
-
/* @__PURE__ */
|
|
1762
|
+
/* @__PURE__ */ jsx10("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` }),
|
|
1763
|
+
/* @__PURE__ */ jsx10(
|
|
1532
1764
|
"button",
|
|
1533
1765
|
{
|
|
1534
1766
|
type: "button",
|
|
@@ -1539,7 +1771,7 @@ var ReviewToolbar = ({
|
|
|
1539
1771
|
children: "\u203A"
|
|
1540
1772
|
}
|
|
1541
1773
|
),
|
|
1542
|
-
showDescription && current && /* @__PURE__ */
|
|
1774
|
+
showDescription && current && /* @__PURE__ */ jsxs8(
|
|
1543
1775
|
"span",
|
|
1544
1776
|
{
|
|
1545
1777
|
className: descriptionClassName,
|
|
@@ -1551,8 +1783,8 @@ var ReviewToolbar = ({
|
|
|
1551
1783
|
]
|
|
1552
1784
|
}
|
|
1553
1785
|
),
|
|
1554
|
-
/* @__PURE__ */
|
|
1555
|
-
/* @__PURE__ */
|
|
1786
|
+
/* @__PURE__ */ jsx10("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
1787
|
+
/* @__PURE__ */ jsx10(
|
|
1556
1788
|
"button",
|
|
1557
1789
|
{
|
|
1558
1790
|
type: "button",
|
|
@@ -1562,7 +1794,7 @@ var ReviewToolbar = ({
|
|
|
1562
1794
|
children: "Accept"
|
|
1563
1795
|
}
|
|
1564
1796
|
),
|
|
1565
|
-
/* @__PURE__ */
|
|
1797
|
+
/* @__PURE__ */ jsx10(
|
|
1566
1798
|
"button",
|
|
1567
1799
|
{
|
|
1568
1800
|
type: "button",
|
|
@@ -1572,18 +1804,18 @@ var ReviewToolbar = ({
|
|
|
1572
1804
|
children: "Reject"
|
|
1573
1805
|
}
|
|
1574
1806
|
),
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
/* @__PURE__ */
|
|
1807
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: buttonClass2, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
|
|
1808
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: buttonClass2, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
|
|
1577
1809
|
] });
|
|
1578
1810
|
};
|
|
1579
1811
|
|
|
1580
1812
|
// src/review/CommentButton.tsx
|
|
1581
|
-
import { jsx as
|
|
1813
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1582
1814
|
var CommentButton = ({
|
|
1583
1815
|
editor,
|
|
1584
1816
|
className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
|
|
1585
1817
|
children = "Comment"
|
|
1586
|
-
}) => /* @__PURE__ */
|
|
1818
|
+
}) => /* @__PURE__ */ jsx11(
|
|
1587
1819
|
"button",
|
|
1588
1820
|
{
|
|
1589
1821
|
type: "button",
|
|
@@ -1595,13 +1827,13 @@ var CommentButton = ({
|
|
|
1595
1827
|
);
|
|
1596
1828
|
|
|
1597
1829
|
// src/review/useDocumentCompare.ts
|
|
1598
|
-
import { useCallback as useCallback7, useMemo as
|
|
1830
|
+
import { useCallback as useCallback7, useMemo as useMemo12, useRef as useRef9, useState as useState10 } from "react";
|
|
1599
1831
|
import {
|
|
1600
1832
|
applyDocumentComparison
|
|
1601
1833
|
} from "@pixerate/editor";
|
|
1602
1834
|
function useDocumentCompare(editor, options) {
|
|
1603
|
-
const [summary, setSummary] =
|
|
1604
|
-
const defaults =
|
|
1835
|
+
const [summary, setSummary] = useState10(null);
|
|
1836
|
+
const defaults = useRef9(options);
|
|
1605
1837
|
defaults.current = options;
|
|
1606
1838
|
const compare = useCallback7(
|
|
1607
1839
|
(original, revised, overrides) => {
|
|
@@ -1616,11 +1848,58 @@ function useDocumentCompare(editor, options) {
|
|
|
1616
1848
|
[editor]
|
|
1617
1849
|
);
|
|
1618
1850
|
const clear = useCallback7(() => setSummary(null), []);
|
|
1619
|
-
return
|
|
1851
|
+
return useMemo12(() => ({ summary, compare, clear }), [summary, compare, clear]);
|
|
1620
1852
|
}
|
|
1621
1853
|
|
|
1854
|
+
// src/review/TrackedChangesList.tsx
|
|
1855
|
+
import { trackedChangeLabel } from "@pixerate/editor";
|
|
1856
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1857
|
+
var buttonClass3 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
|
|
1858
|
+
var TrackedChangesList = ({
|
|
1859
|
+
editor,
|
|
1860
|
+
className = "flex flex-col gap-1 text-sm",
|
|
1861
|
+
itemClassName = "flex items-center gap-2 rounded px-2 py-1 hover:bg-muted/50",
|
|
1862
|
+
activeItemClassName = "bg-primary/10",
|
|
1863
|
+
emptyState = "No tracked changes."
|
|
1864
|
+
}) => {
|
|
1865
|
+
const review = useTrackChanges(editor);
|
|
1866
|
+
if (review.changes.length === 0) {
|
|
1867
|
+
return /* @__PURE__ */ jsx12("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ jsx12("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
|
|
1868
|
+
}
|
|
1869
|
+
return /* @__PURE__ */ jsx12("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
|
|
1870
|
+
const active = change.id === review.currentChangeId;
|
|
1871
|
+
return /* @__PURE__ */ jsxs9(
|
|
1872
|
+
"li",
|
|
1873
|
+
{
|
|
1874
|
+
className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
|
|
1875
|
+
"data-change-type": change.type,
|
|
1876
|
+
"data-change-id": change.id,
|
|
1877
|
+
children: [
|
|
1878
|
+
/* @__PURE__ */ jsxs9(
|
|
1879
|
+
"button",
|
|
1880
|
+
{
|
|
1881
|
+
type: "button",
|
|
1882
|
+
className: "min-w-0 flex-1 truncate text-left text-xs",
|
|
1883
|
+
title: `${change.author.name}: ${change.description}`,
|
|
1884
|
+
onClick: () => review.select(change.id),
|
|
1885
|
+
children: [
|
|
1886
|
+
/* @__PURE__ */ jsx12("span", { className: "font-medium", children: trackedChangeLabel(change) }),
|
|
1887
|
+
change.author.name ? ` \xB7 ${change.author.name}` : "",
|
|
1888
|
+
/* @__PURE__ */ jsx12("span", { className: "block truncate text-muted-foreground", children: change.description })
|
|
1889
|
+
]
|
|
1890
|
+
}
|
|
1891
|
+
),
|
|
1892
|
+
/* @__PURE__ */ jsx12("button", { type: "button", className: buttonClass3, onClick: () => review.accept(change.id), children: "Accept" }),
|
|
1893
|
+
/* @__PURE__ */ jsx12("button", { type: "button", className: buttonClass3, onClick: () => review.reject(change.id), children: "Reject" })
|
|
1894
|
+
]
|
|
1895
|
+
},
|
|
1896
|
+
`${change.type}:${change.id}`
|
|
1897
|
+
);
|
|
1898
|
+
}) });
|
|
1899
|
+
};
|
|
1900
|
+
|
|
1622
1901
|
// src/find-replace/useFindReplace.ts
|
|
1623
|
-
import { useCallback as useCallback8, useMemo as
|
|
1902
|
+
import { useCallback as useCallback8, useMemo as useMemo13, useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
1624
1903
|
import {
|
|
1625
1904
|
EMPTY_FIND_REPLACE_SNAPSHOT,
|
|
1626
1905
|
getFindReplaceStore
|
|
@@ -1634,8 +1913,8 @@ function useFindReplace(editor) {
|
|
|
1634
1913
|
[store]
|
|
1635
1914
|
);
|
|
1636
1915
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_FIND_REPLACE_SNAPSHOT;
|
|
1637
|
-
const snapshot =
|
|
1638
|
-
return
|
|
1916
|
+
const snapshot = useSyncExternalStore8(subscribe, getSnapshot, getSnapshot);
|
|
1917
|
+
return useMemo13(() => {
|
|
1639
1918
|
const run = (fn) => {
|
|
1640
1919
|
if (editor && !editor.isDestroyed && store) fn(editor);
|
|
1641
1920
|
};
|
|
@@ -1659,12 +1938,12 @@ function useFindReplace(editor) {
|
|
|
1659
1938
|
}
|
|
1660
1939
|
|
|
1661
1940
|
// src/find-replace/FindReplaceBar.tsx
|
|
1662
|
-
import { useEffect as
|
|
1941
|
+
import { useEffect as useEffect9, useRef as useRef10, useState as useState11 } from "react";
|
|
1663
1942
|
import { FIND_OPTION_TOGGLES, formatFindStatus } from "@pixerate/editor";
|
|
1664
|
-
import { jsx as
|
|
1943
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1665
1944
|
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
|
|
1667
|
-
var toggleClass = (on) => `${
|
|
1945
|
+
var buttonClass4 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
1946
|
+
var toggleClass = (on) => `${buttonClass4} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
|
|
1668
1947
|
var isMod = (e) => e.metaKey || e.ctrlKey;
|
|
1669
1948
|
var FindReplaceBar = ({
|
|
1670
1949
|
editor,
|
|
@@ -1674,10 +1953,10 @@ var FindReplaceBar = ({
|
|
|
1674
1953
|
onClose
|
|
1675
1954
|
}) => {
|
|
1676
1955
|
const find = useFindReplace(editor);
|
|
1677
|
-
const findInput =
|
|
1678
|
-
const [moreOpen, setMoreOpen] =
|
|
1956
|
+
const findInput = useRef10(null);
|
|
1957
|
+
const [moreOpen, setMoreOpen] = useState11(false);
|
|
1679
1958
|
const visible = find.available && (alwaysOpen || find.open);
|
|
1680
|
-
|
|
1959
|
+
useEffect9(() => {
|
|
1681
1960
|
if (!visible || find.focusRequest === 0) return;
|
|
1682
1961
|
findInput.current?.focus();
|
|
1683
1962
|
findInput.current?.select();
|
|
@@ -1715,20 +1994,20 @@ var FindReplaceBar = ({
|
|
|
1715
1994
|
if (isMod(e)) find.replaceAll();
|
|
1716
1995
|
else find.replace();
|
|
1717
1996
|
};
|
|
1718
|
-
return /* @__PURE__ */
|
|
1719
|
-
/* @__PURE__ */
|
|
1720
|
-
/* @__PURE__ */
|
|
1997
|
+
return /* @__PURE__ */ jsxs10("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
|
|
1998
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
|
|
1999
|
+
/* @__PURE__ */ jsx13(
|
|
1721
2000
|
"button",
|
|
1722
2001
|
{
|
|
1723
2002
|
type: "button",
|
|
1724
|
-
className:
|
|
2003
|
+
className: buttonClass4,
|
|
1725
2004
|
"aria-label": "Toggle replace",
|
|
1726
2005
|
"aria-expanded": showReplace,
|
|
1727
2006
|
onClick: () => find.show(showReplace ? "find" : "replace"),
|
|
1728
2007
|
children: showReplace ? "\u25BE" : "\u25B8"
|
|
1729
2008
|
}
|
|
1730
2009
|
),
|
|
1731
|
-
/* @__PURE__ */
|
|
2010
|
+
/* @__PURE__ */ jsx13(
|
|
1732
2011
|
"input",
|
|
1733
2012
|
{
|
|
1734
2013
|
ref: findInput,
|
|
@@ -1742,7 +2021,7 @@ var FindReplaceBar = ({
|
|
|
1742
2021
|
onKeyDown: onFindKeyDown
|
|
1743
2022
|
}
|
|
1744
2023
|
),
|
|
1745
|
-
FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */
|
|
2024
|
+
FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ jsx13(
|
|
1746
2025
|
"button",
|
|
1747
2026
|
{
|
|
1748
2027
|
type: "button",
|
|
@@ -1755,7 +2034,7 @@ var FindReplaceBar = ({
|
|
|
1755
2034
|
},
|
|
1756
2035
|
t.key
|
|
1757
2036
|
)),
|
|
1758
|
-
/* @__PURE__ */
|
|
2037
|
+
/* @__PURE__ */ jsx13(
|
|
1759
2038
|
"span",
|
|
1760
2039
|
{
|
|
1761
2040
|
className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
|
|
@@ -1765,23 +2044,23 @@ var FindReplaceBar = ({
|
|
|
1765
2044
|
children: status
|
|
1766
2045
|
}
|
|
1767
2046
|
),
|
|
1768
|
-
/* @__PURE__ */
|
|
1769
|
-
/* @__PURE__ */
|
|
1770
|
-
showMoreOptions && /* @__PURE__ */
|
|
2047
|
+
/* @__PURE__ */ jsx13("button", { type: "button", className: buttonClass4, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
|
|
2048
|
+
/* @__PURE__ */ jsx13("button", { type: "button", className: buttonClass4, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
|
|
2049
|
+
showMoreOptions && /* @__PURE__ */ jsx13(
|
|
1771
2050
|
"button",
|
|
1772
2051
|
{
|
|
1773
2052
|
type: "button",
|
|
1774
|
-
className:
|
|
2053
|
+
className: buttonClass4,
|
|
1775
2054
|
"aria-label": "More options",
|
|
1776
2055
|
"aria-expanded": moreOpen,
|
|
1777
2056
|
onClick: () => setMoreOpen((v) => !v),
|
|
1778
2057
|
children: "\u2026"
|
|
1779
2058
|
}
|
|
1780
2059
|
),
|
|
1781
|
-
/* @__PURE__ */
|
|
2060
|
+
/* @__PURE__ */ jsx13("button", { type: "button", className: buttonClass4, "aria-label": "Close find", onClick: close, children: "\xD7" })
|
|
1782
2061
|
] }),
|
|
1783
|
-
showReplace && /* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
2062
|
+
showReplace && /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 pl-7", children: [
|
|
2063
|
+
/* @__PURE__ */ jsx13(
|
|
1785
2064
|
"input",
|
|
1786
2065
|
{
|
|
1787
2066
|
type: "text",
|
|
@@ -1793,21 +2072,21 @@ var FindReplaceBar = ({
|
|
|
1793
2072
|
onKeyDown: onReplaceKeyDown
|
|
1794
2073
|
}
|
|
1795
2074
|
),
|
|
1796
|
-
/* @__PURE__ */
|
|
2075
|
+
/* @__PURE__ */ jsx13(
|
|
1797
2076
|
"button",
|
|
1798
2077
|
{
|
|
1799
2078
|
type: "button",
|
|
1800
|
-
className:
|
|
2079
|
+
className: buttonClass4,
|
|
1801
2080
|
disabled: !hasMatches || find.currentIndex < 0,
|
|
1802
2081
|
onClick: find.replace,
|
|
1803
2082
|
children: "Replace"
|
|
1804
2083
|
}
|
|
1805
2084
|
),
|
|
1806
|
-
/* @__PURE__ */
|
|
1807
|
-
find.lastReplaceCount !== null && /* @__PURE__ */
|
|
2085
|
+
/* @__PURE__ */ jsx13("button", { type: "button", className: buttonClass4, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
|
|
2086
|
+
find.lastReplaceCount !== null && /* @__PURE__ */ jsx13("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
|
|
1808
2087
|
] }),
|
|
1809
|
-
showMoreOptions && moreOpen && /* @__PURE__ */
|
|
1810
|
-
/* @__PURE__ */
|
|
2088
|
+
showMoreOptions && moreOpen && /* @__PURE__ */ jsx13("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__ */ jsxs10("label", { className: "flex items-center gap-1", children: [
|
|
2089
|
+
/* @__PURE__ */ jsx13(
|
|
1811
2090
|
"input",
|
|
1812
2091
|
{
|
|
1813
2092
|
type: "checkbox",
|
|
@@ -1819,8 +2098,152 @@ var FindReplaceBar = ({
|
|
|
1819
2098
|
] }, t.key)) })
|
|
1820
2099
|
] });
|
|
1821
2100
|
};
|
|
2101
|
+
|
|
2102
|
+
// src/tables/useTableMenu.ts
|
|
2103
|
+
import { useMemo as useMemo14, useSyncExternalStore as useSyncExternalStore9 } from "react";
|
|
2104
|
+
import {
|
|
2105
|
+
createTableStore,
|
|
2106
|
+
getTableActionState,
|
|
2107
|
+
runTableAction
|
|
2108
|
+
} from "@pixerate/editor";
|
|
2109
|
+
function useTableMenu(editor) {
|
|
2110
|
+
const store = useMemo14(() => createTableStore(editor), [editor]);
|
|
2111
|
+
const snapshot = useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
2112
|
+
return useMemo14(
|
|
2113
|
+
() => ({
|
|
2114
|
+
...snapshot,
|
|
2115
|
+
run: (action, params) => runTableAction(editor, action, params, { focus: true }),
|
|
2116
|
+
check: (action, params) => getTableActionState(editor, action, params)
|
|
2117
|
+
}),
|
|
2118
|
+
[snapshot, editor]
|
|
2119
|
+
);
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
// src/tables/TableToolbar.tsx
|
|
2123
|
+
import React9 from "react";
|
|
2124
|
+
import { DEFAULT_TABLE_TOOLBAR } from "@pixerate/editor";
|
|
2125
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2126
|
+
var keepSelection2 = (event) => event.preventDefault();
|
|
2127
|
+
var TableToolbar = ({
|
|
2128
|
+
editor,
|
|
2129
|
+
items = DEFAULT_TABLE_TOOLBAR,
|
|
2130
|
+
showWhenOutside = false,
|
|
2131
|
+
className = "flex flex-wrap items-center gap-1 text-xs",
|
|
2132
|
+
buttonClassName = "rounded px-2 py-1 text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent",
|
|
2133
|
+
activeButtonClassName = "bg-primary/10 text-primary",
|
|
2134
|
+
separatorClassName = "mx-1 h-4 w-px bg-border",
|
|
2135
|
+
onAction
|
|
2136
|
+
}) => {
|
|
2137
|
+
const table = useTableMenu(editor);
|
|
2138
|
+
if (!editor || !table.inTable && !showWhenOutside) return null;
|
|
2139
|
+
return /* @__PURE__ */ jsx14("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
|
|
2140
|
+
const status = table.check(item.action, item.params);
|
|
2141
|
+
const enabled = status === true;
|
|
2142
|
+
const active = item.active?.(table);
|
|
2143
|
+
const separator = index > 0 && items[index - 1].group !== item.group;
|
|
2144
|
+
return /* @__PURE__ */ jsxs11(React9.Fragment, { children: [
|
|
2145
|
+
separator && /* @__PURE__ */ jsx14("span", { className: separatorClassName, "aria-hidden": "true" }),
|
|
2146
|
+
/* @__PURE__ */ jsx14(
|
|
2147
|
+
"button",
|
|
2148
|
+
{
|
|
2149
|
+
type: "button",
|
|
2150
|
+
"data-action": item.id,
|
|
2151
|
+
"aria-label": item.title,
|
|
2152
|
+
title: enabled ? item.title : `${item.title}: ${status}`,
|
|
2153
|
+
...item.active ? { "aria-pressed": !!active } : {},
|
|
2154
|
+
disabled: !enabled,
|
|
2155
|
+
className: active ? `${buttonClassName} ${activeButtonClassName}` : buttonClassName,
|
|
2156
|
+
onMouseDown: keepSelection2,
|
|
2157
|
+
onClick: () => {
|
|
2158
|
+
if (table.run(item.action, item.params)) onAction?.(item);
|
|
2159
|
+
},
|
|
2160
|
+
children: item.label
|
|
2161
|
+
}
|
|
2162
|
+
)
|
|
2163
|
+
] }, item.id);
|
|
2164
|
+
}) });
|
|
2165
|
+
};
|
|
2166
|
+
|
|
2167
|
+
// src/tables/InsertTableGrid.tsx
|
|
2168
|
+
import { useState as useState12 } from "react";
|
|
2169
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2170
|
+
var keepSelection3 = (event) => event.preventDefault();
|
|
2171
|
+
var InsertTableGrid = ({
|
|
2172
|
+
editor,
|
|
2173
|
+
rows = 8,
|
|
2174
|
+
cols = 8,
|
|
2175
|
+
withHeaderRow = true,
|
|
2176
|
+
className = "inline-flex flex-col gap-1 rounded-md border border-border bg-background p-2 text-xs shadow-md",
|
|
2177
|
+
cellClassName = "h-4 w-4 rounded-sm border border-border bg-background disabled:opacity-40",
|
|
2178
|
+
activeCellClassName = "border-primary bg-primary/20",
|
|
2179
|
+
onInsert
|
|
2180
|
+
}) => {
|
|
2181
|
+
const table = useTableMenu(editor);
|
|
2182
|
+
const [hover, setHover] = useState12(null);
|
|
2183
|
+
const status = table.actions.insertTable;
|
|
2184
|
+
const disabled = !editor || !status.enabled;
|
|
2185
|
+
const insert = (size) => {
|
|
2186
|
+
if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
|
|
2187
|
+
setHover(null);
|
|
2188
|
+
};
|
|
2189
|
+
return /* @__PURE__ */ jsxs12(
|
|
2190
|
+
"div",
|
|
2191
|
+
{
|
|
2192
|
+
className,
|
|
2193
|
+
role: "group",
|
|
2194
|
+
"aria-label": "Insert table",
|
|
2195
|
+
title: disabled ? status.reason : void 0,
|
|
2196
|
+
"data-insert-table-grid": "",
|
|
2197
|
+
onMouseLeave: () => setHover(null),
|
|
2198
|
+
children: [
|
|
2199
|
+
/* @__PURE__ */ jsx15(
|
|
2200
|
+
"div",
|
|
2201
|
+
{
|
|
2202
|
+
role: "grid",
|
|
2203
|
+
"aria-label": "Table size",
|
|
2204
|
+
style: { display: "grid", gridTemplateColumns: `repeat(${cols}, max-content)`, gap: 2 },
|
|
2205
|
+
children: Array.from({ length: rows * cols }, (_, i) => {
|
|
2206
|
+
const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
|
|
2207
|
+
const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
|
|
2208
|
+
return /* @__PURE__ */ jsx15(
|
|
2209
|
+
"button",
|
|
2210
|
+
{
|
|
2211
|
+
type: "button",
|
|
2212
|
+
"data-rows": size.rows,
|
|
2213
|
+
"data-cols": size.cols,
|
|
2214
|
+
"data-active": active,
|
|
2215
|
+
"aria-label": `${size.rows} \xD7 ${size.cols} table`,
|
|
2216
|
+
disabled,
|
|
2217
|
+
className: active ? `${cellClassName} ${activeCellClassName}` : cellClassName,
|
|
2218
|
+
onMouseDown: keepSelection3,
|
|
2219
|
+
onMouseEnter: () => setHover(size),
|
|
2220
|
+
onFocus: () => setHover(size),
|
|
2221
|
+
onClick: () => insert(size)
|
|
2222
|
+
},
|
|
2223
|
+
i
|
|
2224
|
+
);
|
|
2225
|
+
})
|
|
2226
|
+
}
|
|
2227
|
+
),
|
|
2228
|
+
/* @__PURE__ */ jsx15("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
|
|
2229
|
+
]
|
|
2230
|
+
}
|
|
2231
|
+
);
|
|
2232
|
+
};
|
|
2233
|
+
|
|
2234
|
+
// src/tables/TableBubbleMenu.tsx
|
|
2235
|
+
import { shouldShowTableBubbleMenu } from "@pixerate/editor";
|
|
2236
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
2237
|
+
var TableBubbleMenu = ({
|
|
2238
|
+
editor,
|
|
2239
|
+
children,
|
|
2240
|
+
toolbarProps,
|
|
2241
|
+
pluginKey = "tableBubbleMenu",
|
|
2242
|
+
...rest
|
|
2243
|
+
}) => /* @__PURE__ */ jsx16(BubbleMenu, { editor, pluginKey, shouldShow: shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ jsx16(TableToolbar, { editor, ...toolbarProps }) });
|
|
1822
2244
|
export {
|
|
1823
2245
|
AdjustmentLayersPanel,
|
|
2246
|
+
AssetMentionChips,
|
|
1824
2247
|
BubbleMenu,
|
|
1825
2248
|
CommandPalette,
|
|
1826
2249
|
CommentButton,
|
|
@@ -1830,21 +2253,35 @@ export {
|
|
|
1830
2253
|
DirtyTracker2 as DirtyTracker,
|
|
1831
2254
|
EditorContent,
|
|
1832
2255
|
EditorSlotsProvider,
|
|
2256
|
+
ExportDocxButton,
|
|
1833
2257
|
FindReplaceBar,
|
|
1834
2258
|
FormulaHints,
|
|
2259
|
+
GenerationHistory,
|
|
1835
2260
|
GenerationSettings,
|
|
1836
2261
|
Histogram,
|
|
1837
2262
|
HistoryManager2 as HistoryManager,
|
|
1838
2263
|
ImageEditor,
|
|
2264
|
+
InsertTableGrid,
|
|
1839
2265
|
JobProgress,
|
|
1840
2266
|
MergePreview,
|
|
2267
|
+
NameManager,
|
|
1841
2268
|
OutlinePanel,
|
|
1842
2269
|
RecoveryPrompt,
|
|
2270
|
+
RefineEdgePanel,
|
|
1843
2271
|
ReviewToolbar,
|
|
2272
|
+
SelectionOptionsBar,
|
|
2273
|
+
SheetTabs,
|
|
2274
|
+
SpreadsheetConditionalFormatPanel,
|
|
1844
2275
|
SpreadsheetContextMenu,
|
|
2276
|
+
SpreadsheetDataValidationPanel,
|
|
1845
2277
|
SpreadsheetEditor,
|
|
1846
2278
|
SpreadsheetGroupRow,
|
|
2279
|
+
SpreadsheetValidationDialog,
|
|
2280
|
+
StylesGallery,
|
|
2281
|
+
TableBubbleMenu,
|
|
2282
|
+
TableToolbar,
|
|
1847
2283
|
TemplateRenderer,
|
|
2284
|
+
TrackedChangesList,
|
|
1848
2285
|
VariableForm,
|
|
1849
2286
|
bindDirtyToHistory2 as bindDirtyToHistory,
|
|
1850
2287
|
createDirtyTracker,
|
|
@@ -1857,12 +2294,14 @@ export {
|
|
|
1857
2294
|
useComments,
|
|
1858
2295
|
useDismissGuard,
|
|
1859
2296
|
useDocumentCompare,
|
|
2297
|
+
useDocxExport,
|
|
1860
2298
|
useEditor2 as useEditor,
|
|
1861
2299
|
useEditorSlots,
|
|
1862
2300
|
useFileImport,
|
|
1863
2301
|
useFillHandle,
|
|
1864
2302
|
useFindReplace,
|
|
1865
2303
|
useGenerationPlan,
|
|
2304
|
+
useGenerationRecords,
|
|
1866
2305
|
useHistory,
|
|
1867
2306
|
useHistoryDirty,
|
|
1868
2307
|
useHistoryShortcuts,
|
|
@@ -1872,10 +2311,13 @@ export {
|
|
|
1872
2311
|
useMergePreview,
|
|
1873
2312
|
useNavigationGuard,
|
|
1874
2313
|
useOutline,
|
|
2314
|
+
useParagraphStyles,
|
|
1875
2315
|
usePromptEditor,
|
|
1876
2316
|
useRegisterCommands,
|
|
1877
2317
|
useSpreadsheetClipboard,
|
|
1878
2318
|
useSpreadsheetEditor,
|
|
2319
|
+
useSpreadsheetViewport,
|
|
2320
|
+
useTableMenu,
|
|
1879
2321
|
useTrackChanges,
|
|
1880
2322
|
withoutDirty
|
|
1881
2323
|
};
|