@farmzone/fz-react-ui 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,6 +30,16 @@ var zustand = require('zustand');
30
30
  var middleware = require('zustand/middleware');
31
31
  var uuid = require('uuid');
32
32
  var heic2any = require('heic2any');
33
+ var react = require('@tiptap/react');
34
+ var core = require('@tiptap/core');
35
+ var StarterKit = require('@tiptap/starter-kit');
36
+ var TextAlign = require('@tiptap/extension-text-align');
37
+ var extensionImage = require('@tiptap/extension-image');
38
+ var extensionTextStyle = require('@tiptap/extension-text-style');
39
+ var extensionHeading = require('@tiptap/extension-heading');
40
+ var extensionPlaceholder = require('@tiptap/extension-placeholder');
41
+ var Mention = require('@tiptap/extension-mention');
42
+ var extensionTable = require('@tiptap/extension-table');
33
43
 
34
44
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
35
45
 
@@ -63,6 +73,9 @@ var useEmblaCarousel__default = /*#__PURE__*/_interopDefault(useEmblaCarousel);
63
73
  var dayjs__default = /*#__PURE__*/_interopDefault(dayjs);
64
74
  var customParseFormat__default = /*#__PURE__*/_interopDefault(customParseFormat);
65
75
  var heic2any__default = /*#__PURE__*/_interopDefault(heic2any);
76
+ var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
77
+ var TextAlign__default = /*#__PURE__*/_interopDefault(TextAlign);
78
+ var Mention__default = /*#__PURE__*/_interopDefault(Mention);
66
79
 
67
80
  // src/lib/variants.ts
68
81
  function cn(...inputs) {
@@ -9597,6 +9610,1010 @@ function Sidebar(props) {
9597
9610
  }
9598
9611
  );
9599
9612
  }
9613
+ var LIGHT = {
9614
+ toolbar: {
9615
+ wrapper: "border-b border-gray-200 bg-white",
9616
+ btnIdle: "text-gray-700 hover:bg-gray-100",
9617
+ btnActive: "bg-indigo-100 text-indigo-600",
9618
+ btnDestructive: "text-red-400 hover:bg-red-50 hover:text-red-600",
9619
+ divider: "bg-gray-200",
9620
+ rText: "text-gray-700"
9621
+ },
9622
+ fileList: {
9623
+ wrapper: "border-t border-gray-100",
9624
+ label: "text-gray-400",
9625
+ item: "border border-gray-200 bg-white",
9626
+ itemName: "text-gray-700",
9627
+ itemSize: "text-gray-400",
9628
+ removeBtn: "text-gray-400 hover:bg-gray-100 hover:text-gray-600"
9629
+ },
9630
+ dropZone: {
9631
+ overlay: "border-blue-400 bg-blue-50/80 text-blue-600",
9632
+ subText: "text-blue-400"
9633
+ },
9634
+ mention: {
9635
+ container: "border-gray-200 bg-white",
9636
+ emptyText: "text-gray-400",
9637
+ btnIdle: "text-gray-700 hover:bg-gray-100 hover:text-gray-900",
9638
+ btnSelected: "bg-blue-100 text-blue-900",
9639
+ badgeIdle: "bg-gray-100 text-gray-500",
9640
+ badgeSelected: "bg-blue-200 text-blue-800"
9641
+ }
9642
+ };
9643
+ var DARK = {
9644
+ toolbar: {
9645
+ wrapper: "border-b border-gray-800 bg-gray-900",
9646
+ btnIdle: "text-gray-400 hover:bg-gray-800 hover:text-gray-200",
9647
+ btnActive: "bg-indigo-900/50 text-indigo-400",
9648
+ btnDestructive: "text-red-400 hover:bg-red-900/30 hover:text-red-300",
9649
+ divider: "bg-gray-800",
9650
+ rText: "text-gray-400"
9651
+ },
9652
+ fileList: {
9653
+ wrapper: "border-t border-gray-800",
9654
+ label: "text-gray-500",
9655
+ item: "border border-gray-700 bg-gray-900",
9656
+ itemName: "text-gray-300",
9657
+ itemSize: "text-gray-500",
9658
+ removeBtn: "text-gray-500 hover:bg-gray-800 hover:text-gray-300"
9659
+ },
9660
+ dropZone: {
9661
+ overlay: "border-blue-500 bg-blue-950/80 text-blue-400",
9662
+ subText: "text-blue-500"
9663
+ },
9664
+ mention: {
9665
+ container: "border-gray-700 bg-gray-900",
9666
+ emptyText: "text-gray-500",
9667
+ btnIdle: "text-gray-300 hover:bg-gray-800 hover:text-gray-100",
9668
+ btnSelected: "bg-blue-900/50 text-blue-200",
9669
+ badgeIdle: "bg-gray-800 text-gray-400",
9670
+ badgeSelected: "bg-blue-800 text-blue-200"
9671
+ }
9672
+ };
9673
+ var RICH_EDITOR_THEMES = {
9674
+ light: LIGHT,
9675
+ dark: DARK
9676
+ };
9677
+ var RichEditorThemeContext = React6.createContext(LIGHT);
9678
+ var RichEditorThemeProvider = RichEditorThemeContext.Provider;
9679
+ function useRichEditorTheme() {
9680
+ return React6.useContext(RichEditorThemeContext);
9681
+ }
9682
+ var MentionList = React6.forwardRef((props, ref) => {
9683
+ const { items, command, loading, className } = props;
9684
+ const theme = useRichEditorTheme();
9685
+ const [selectedIndex, setSelectedIndex] = React6.useState(0);
9686
+ const selectedRef = React6.useRef(null);
9687
+ const selectItem = (index) => {
9688
+ const item = items[index];
9689
+ if (item) {
9690
+ command({ id: item.id, label: item.label });
9691
+ }
9692
+ };
9693
+ React6.useEffect(() => setSelectedIndex(0), [items]);
9694
+ React6.useEffect(() => {
9695
+ selectedRef.current?.scrollIntoView({ block: "nearest" });
9696
+ }, [selectedIndex]);
9697
+ React6.useImperativeHandle(ref, () => ({
9698
+ onKeyDown: ({ event }) => {
9699
+ if (event.key === "ArrowUp") {
9700
+ setSelectedIndex((i) => (i + items.length - 1) % Math.max(items.length, 1));
9701
+ return true;
9702
+ }
9703
+ if (event.key === "ArrowDown") {
9704
+ setSelectedIndex((i) => (i + 1) % Math.max(items.length, 1));
9705
+ return true;
9706
+ }
9707
+ if (event.key === "Enter") {
9708
+ selectItem(selectedIndex);
9709
+ return true;
9710
+ }
9711
+ return false;
9712
+ }
9713
+ }));
9714
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("rich-editor-mention-list z-50 overflow-hidden rounded-md border shadow-md", theme.mention.container, className), children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-3 py-2 text-sm", theme.mention.emptyText), children: "\uAC80\uC0C9 \uC911..." }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-3 py-2 text-sm", theme.mention.emptyText), children: "\uAC80\uC0C9 \uACB0\uACFC \uC5C6\uC74C" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-48 overflow-y-auto p-1", children: items.map((item, index) => {
9715
+ const isSelected = index === selectedIndex;
9716
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9717
+ "button",
9718
+ {
9719
+ ref: isSelected ? selectedRef : null,
9720
+ type: "button",
9721
+ onClick: () => selectItem(index),
9722
+ className: cn(
9723
+ "flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pl-2 pr-4 text-sm text-left select-none transition-colors",
9724
+ isSelected ? theme.mention.btnSelected : theme.mention.btnIdle
9725
+ ),
9726
+ children: [
9727
+ /* @__PURE__ */ jsxRuntime.jsx(
9728
+ "span",
9729
+ {
9730
+ className: cn(
9731
+ "flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-[11px] font-semibold",
9732
+ isSelected ? theme.mention.badgeSelected : theme.mention.badgeIdle
9733
+ ),
9734
+ children: item.label[0]?.toUpperCase()
9735
+ }
9736
+ ),
9737
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.label })
9738
+ ]
9739
+ },
9740
+ item.id
9741
+ );
9742
+ }) }) });
9743
+ });
9744
+ MentionList.displayName = "MentionList";
9745
+
9746
+ // src/components/RichEditor/config/extensions.ts
9747
+ function buildExtensions(config) {
9748
+ const { toolbar, mentionUsers = [], onMentionSearch, mentionClassName } = config;
9749
+ const exts = [extensionTextStyle.TextStyleKit, buildMarkResetOnEnter()];
9750
+ const headingLevels = toolbar.heading === false ? [] : Array.isArray(toolbar.heading) ? [...toolbar.heading] : [1, 2, 3, 4];
9751
+ exts.push(
9752
+ StarterKit__default.default.configure({
9753
+ heading: false,
9754
+ bold: toolbar.bold !== false ? {} : false,
9755
+ italic: toolbar.italic !== false ? {} : false,
9756
+ strike: toolbar.strike !== false ? {} : false,
9757
+ code: toolbar.code !== false ? {} : false,
9758
+ bulletList: toolbar.bulletList !== false ? { keepMarks: true, keepAttributes: false } : false,
9759
+ orderedList: toolbar.orderedList !== false ? { keepMarks: true, keepAttributes: false } : false,
9760
+ blockquote: toolbar.blockquote !== false ? {} : false,
9761
+ codeBlock: toolbar.codeBlock !== false ? {
9762
+ HTMLAttributes: {
9763
+ class: "rounded-lg p-4 font-mono text-sm my-4"
9764
+ }
9765
+ } : false
9766
+ })
9767
+ );
9768
+ if (headingLevels.length > 0) {
9769
+ exts.push(extensionHeading.Heading.configure({ levels: headingLevels }));
9770
+ }
9771
+ if (toolbar.textAlign !== false) {
9772
+ exts.push(buildCustomTextAlign());
9773
+ }
9774
+ if (toolbar.image) {
9775
+ exts.push(buildCustomImage());
9776
+ }
9777
+ if (toolbar.placeholder !== void 0) {
9778
+ exts.push(
9779
+ extensionPlaceholder.Placeholder.configure({
9780
+ placeholder: toolbar.placeholder,
9781
+ showOnlyWhenEditable: true
9782
+ })
9783
+ );
9784
+ }
9785
+ if (toolbar.mention) {
9786
+ const ALL_ITEM = { id: "__all__", label: "\uBAA8\uB450" };
9787
+ exts.push(
9788
+ Mention__default.default.configure({
9789
+ HTMLAttributes: { class: "rich-editor-mention" },
9790
+ suggestion: {
9791
+ items: async ({ query }) => {
9792
+ let items;
9793
+ if (onMentionSearch) {
9794
+ items = await onMentionSearch(query);
9795
+ } else {
9796
+ items = mentionUsers.filter(
9797
+ (u) => u.label.toLowerCase().includes(query.toLowerCase())
9798
+ );
9799
+ }
9800
+ return toolbar.mentionAll ? [ALL_ITEM, ...items] : items;
9801
+ },
9802
+ render: () => {
9803
+ let component;
9804
+ let unmount;
9805
+ return {
9806
+ onStart: (props) => {
9807
+ component = new react.ReactRenderer(MentionList, {
9808
+ props: mentionClassName ? { ...props, className: mentionClassName } : props,
9809
+ editor: props.editor
9810
+ });
9811
+ unmount = props.mount(component.element);
9812
+ },
9813
+ onUpdate: (props) => {
9814
+ component.updateProps(
9815
+ mentionClassName ? { ...props, className: mentionClassName } : props
9816
+ );
9817
+ },
9818
+ onKeyDown: ({ event }) => {
9819
+ return component.ref?.onKeyDown({ event }) ?? false;
9820
+ },
9821
+ onExit: () => {
9822
+ unmount?.();
9823
+ component.destroy();
9824
+ }
9825
+ };
9826
+ }
9827
+ }
9828
+ })
9829
+ );
9830
+ }
9831
+ if (toolbar.table) {
9832
+ exts.push(
9833
+ extensionTable.Table.configure({ resizable: true }),
9834
+ extensionTable.TableRow,
9835
+ extensionTable.TableHeader,
9836
+ extensionTable.TableCell
9837
+ );
9838
+ }
9839
+ return exts;
9840
+ }
9841
+ function buildCustomTextAlign() {
9842
+ const CustomTextAlign = TextAlign__default.default.extend({
9843
+ addKeyboardShortcuts() {
9844
+ return {
9845
+ Enter: ({ editor }) => {
9846
+ const isAligned = editor.isActive({ textAlign: "center" }) || editor.isActive({ textAlign: "right" });
9847
+ if (!isAligned) return false;
9848
+ const {
9849
+ state: {
9850
+ selection: { $from }
9851
+ }
9852
+ } = editor;
9853
+ const currentNode = $from.node($from.depth);
9854
+ if (currentNode.textContent.trim() === "") {
9855
+ editor.chain().focus().setTextAlign("left").run();
9856
+ return true;
9857
+ }
9858
+ return false;
9859
+ }
9860
+ };
9861
+ }
9862
+ });
9863
+ return CustomTextAlign.configure({
9864
+ types: ["heading", "paragraph"],
9865
+ alignments: ["left", "center", "right"],
9866
+ defaultAlignment: "left"
9867
+ });
9868
+ }
9869
+ function buildCustomImage() {
9870
+ const CustomImage = extensionImage.Image.extend({
9871
+ addAttributes() {
9872
+ return {
9873
+ ...this.parent?.(),
9874
+ width: {
9875
+ default: null,
9876
+ renderHTML: (attrs) => attrs.width ? { width: attrs.width } : {}
9877
+ },
9878
+ height: {
9879
+ default: null,
9880
+ renderHTML: (attrs) => attrs.height ? { height: attrs.height } : {}
9881
+ },
9882
+ style: {
9883
+ default: null,
9884
+ renderHTML: (attrs) => attrs.style ? { style: attrs.style } : {}
9885
+ }
9886
+ };
9887
+ }
9888
+ });
9889
+ return CustomImage.configure({
9890
+ HTMLAttributes: { class: "max-w-full h-auto rounded-lg my-4" },
9891
+ inline: false,
9892
+ allowBase64: true
9893
+ });
9894
+ }
9895
+ function buildMarkResetOnEnter() {
9896
+ return core.Extension.create({
9897
+ name: "markResetOnEnter",
9898
+ priority: 200,
9899
+ addKeyboardShortcuts() {
9900
+ return {
9901
+ Enter: ({ editor }) => {
9902
+ if (editor.isActive("heading") || editor.isActive("bulletList") || editor.isActive("orderedList") || editor.isActive("blockquote") || editor.isActive("codeBlock")) {
9903
+ return false;
9904
+ }
9905
+ const { $from } = editor.state.selection;
9906
+ const currentNode = $from.node($from.depth);
9907
+ if (currentNode.textContent.trim() === "") return false;
9908
+ const hasMarks = editor.isActive("bold") || editor.isActive("italic") || editor.isActive("strike") || editor.isActive("code");
9909
+ const hasNonDefaultAlign = editor.isActive({ textAlign: "center" }) || editor.isActive({ textAlign: "right" });
9910
+ if (!hasMarks && !hasNonDefaultAlign) return false;
9911
+ editor.chain().splitBlock().unsetAllMarks().setTextAlign("left").run();
9912
+ return true;
9913
+ }
9914
+ };
9915
+ }
9916
+ });
9917
+ }
9918
+
9919
+ // src/components/RichEditor/config/keyboardHandlers.ts
9920
+ function createKeyboardHandler(codeBlockEmptyEnterRef, onSubmitRef) {
9921
+ return (view, event) => {
9922
+ const { editor } = view;
9923
+ if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
9924
+ onSubmitRef?.current?.();
9925
+ return true;
9926
+ }
9927
+ if (event.key !== "Enter") return false;
9928
+ if (!editor) return false;
9929
+ const { state } = view;
9930
+ const { selection } = state;
9931
+ const { $from } = selection;
9932
+ if (editor.isActive("heading")) {
9933
+ event.preventDefault();
9934
+ editor.chain().focus().splitBlock().setParagraph().run();
9935
+ return true;
9936
+ }
9937
+ if (editor.isActive("blockquote")) {
9938
+ let blockquoteNode = null;
9939
+ for (let i = $from.depth; i >= 0; i--) {
9940
+ if ($from.node(i).type.name === "blockquote") {
9941
+ blockquoteNode = $from.node(i);
9942
+ break;
9943
+ }
9944
+ }
9945
+ const currentText = blockquoteNode?.textContent.trim() || "";
9946
+ if (currentText === "") {
9947
+ event.preventDefault();
9948
+ editor.chain().focus().toggleBlockquote().setParagraph().run();
9949
+ return true;
9950
+ }
9951
+ }
9952
+ if (editor.isActive("codeBlock")) {
9953
+ let codeBlockNode = null;
9954
+ for (let i = $from.depth; i >= 0; i--) {
9955
+ const node = $from.node(i);
9956
+ if (node.type.name === "codeBlock") {
9957
+ codeBlockNode = node;
9958
+ break;
9959
+ }
9960
+ }
9961
+ if (codeBlockNode) {
9962
+ const codeBlockText = codeBlockNode.textContent.trim();
9963
+ if (codeBlockText === "") {
9964
+ if (codeBlockEmptyEnterRef.current) {
9965
+ event.preventDefault();
9966
+ codeBlockEmptyEnterRef.current = false;
9967
+ editor.chain().focus().toggleCodeBlock().setParagraph().run();
9968
+ return true;
9969
+ }
9970
+ codeBlockEmptyEnterRef.current = true;
9971
+ return false;
9972
+ }
9973
+ codeBlockEmptyEnterRef.current = false;
9974
+ }
9975
+ } else {
9976
+ codeBlockEmptyEnterRef.current = false;
9977
+ }
9978
+ if (editor.isActive("bulletList")) {
9979
+ const currentNode = $from.node($from.depth);
9980
+ if (currentNode.textContent.trim() === "") {
9981
+ event.preventDefault();
9982
+ editor.chain().focus().lift("bulletList").setParagraph().run();
9983
+ return true;
9984
+ }
9985
+ }
9986
+ if (editor.isActive("orderedList")) {
9987
+ const currentNode = $from.node($from.depth);
9988
+ if (currentNode.textContent.trim() === "") {
9989
+ event.preventDefault();
9990
+ editor.chain().focus().lift("orderedList").setParagraph().run();
9991
+ return true;
9992
+ }
9993
+ }
9994
+ return false;
9995
+ };
9996
+ }
9997
+
9998
+ // src/components/RichEditor/hooks/useRichEditor.ts
9999
+ var DEFAULT_EDITOR_CLASS = "focus:outline-none";
10000
+ function useRichEditor(options = {}) {
10001
+ const {
10002
+ defaultValue,
10003
+ toolbar = {},
10004
+ mentionUsers = [],
10005
+ onMentionSearch,
10006
+ mentionClassName,
10007
+ editable = true,
10008
+ autofocus,
10009
+ editorClassName,
10010
+ additionalExtensions = [],
10011
+ onChange,
10012
+ onSubmit
10013
+ } = options;
10014
+ const codeBlockEmptyEnterRef = React6.useRef(false);
10015
+ const onChangeRef = React6.useRef(onChange);
10016
+ onChangeRef.current = onChange;
10017
+ const onSubmitRef = React6.useRef(onSubmit);
10018
+ onSubmitRef.current = onSubmit;
10019
+ const extensions = [
10020
+ ...buildExtensions({
10021
+ toolbar,
10022
+ mentionUsers,
10023
+ onMentionSearch,
10024
+ mentionClassName
10025
+ }),
10026
+ ...additionalExtensions
10027
+ ];
10028
+ const editor = react.useEditor({
10029
+ extensions,
10030
+ autofocus: autofocus ?? false,
10031
+ editable,
10032
+ editorProps: {
10033
+ attributes: {
10034
+ class: cn(DEFAULT_EDITOR_CLASS, editorClassName)
10035
+ },
10036
+ handleKeyDown: createKeyboardHandler(codeBlockEmptyEnterRef, onSubmitRef)
10037
+ },
10038
+ content: defaultValue ?? "",
10039
+ onUpdate: ({ editor: editor2 }) => {
10040
+ onChangeRef.current?.(editor2.getHTML());
10041
+ }
10042
+ });
10043
+ React6.useEffect(() => {
10044
+ if (editor) editor.setEditable(editable);
10045
+ }, [editor, editable]);
10046
+ return {
10047
+ editor,
10048
+ getHTML: () => editor?.getHTML() ?? "",
10049
+ getJSON: () => editor?.getJSON() ?? {},
10050
+ setContent: (html) => {
10051
+ editor?.commands.setContent(html);
10052
+ },
10053
+ clearContent: () => {
10054
+ editor?.commands.clearContent();
10055
+ },
10056
+ focus: () => {
10057
+ editor?.commands.focus();
10058
+ },
10059
+ isEmpty: editor?.isEmpty ?? true
10060
+ // attachments,
10061
+ // removeAttachment,
10062
+ };
10063
+ }
10064
+ var MAX_COLS = 8;
10065
+ var MAX_ROWS = 8;
10066
+ function TableGridPicker({ editor, onClose }) {
10067
+ const [hover, setHover] = React6.useState({ col: 0, row: 0 });
10068
+ const handleSelect = (col, row) => {
10069
+ editor.chain().focus().insertTable({ rows: row, cols: col, withHeaderRow: true }).run();
10070
+ onClose();
10071
+ };
10072
+ const cols = hover.col || 1;
10073
+ const rows = hover.row || 1;
10074
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1.5", children: [
10075
+ /* @__PURE__ */ jsxRuntime.jsx(
10076
+ "div",
10077
+ {
10078
+ className: "grid gap-1",
10079
+ style: { gridTemplateColumns: `repeat(${MAX_COLS}, 1fr)` },
10080
+ onMouseLeave: () => setHover({ col: 0, row: 0 }),
10081
+ children: Array.from(
10082
+ { length: MAX_ROWS },
10083
+ (_, rowIdx) => Array.from({ length: MAX_COLS }, (_2, colIdx) => {
10084
+ const row = rowIdx + 1;
10085
+ const col = colIdx + 1;
10086
+ const isHighlighted = col <= hover.col && row <= hover.row;
10087
+ return /* @__PURE__ */ jsxRuntime.jsx(
10088
+ "button",
10089
+ {
10090
+ type: "button",
10091
+ "aria-label": `${col}\uC5F4 ${row}\uD589 \uD14C\uC774\uBE14`,
10092
+ className: cn(
10093
+ "size-4 rounded border transition-colors",
10094
+ isHighlighted ? "border-blue-400 bg-blue-100" : "border-gray-200 bg-gray-50"
10095
+ ),
10096
+ onMouseEnter: () => setHover({ col, row }),
10097
+ onClick: () => handleSelect(col, row)
10098
+ },
10099
+ `${row}-${col}`
10100
+ );
10101
+ })
10102
+ )
10103
+ }
10104
+ ),
10105
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center justify-center gap-1.5 text-xs text-gray-500", children: [
10106
+ /* @__PURE__ */ jsxRuntime.jsx(ColIcon, {}),
10107
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 text-center font-medium text-gray-700", children: cols }),
10108
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "\xD7" }),
10109
+ /* @__PURE__ */ jsxRuntime.jsx(RowIcon, {}),
10110
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 text-center font-medium text-gray-700", children: rows })
10111
+ ] })
10112
+ ] });
10113
+ }
10114
+ function ColIcon() {
10115
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", className: "text-gray-400", children: [
10116
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "1", y: "1", width: "5", height: "12", rx: "1", fill: "currentColor", opacity: "0.3" }),
10117
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "8", y: "1", width: "5", height: "12", rx: "1", fill: "currentColor", opacity: "0.15" })
10118
+ ] });
10119
+ }
10120
+ function RowIcon() {
10121
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", className: "text-gray-400", children: [
10122
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "1", y: "1", width: "12", height: "5", rx: "1", fill: "currentColor", opacity: "0.3" }),
10123
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "1", y: "8", width: "12", height: "5", rx: "1", fill: "currentColor", opacity: "0.15" })
10124
+ ] });
10125
+ }
10126
+ function ToolbarButton(props) {
10127
+ const { onMouseDown, active, disabled, title, tooltip, variant = "default", children } = props;
10128
+ const theme = useRichEditorTheme();
10129
+ const btn = /* @__PURE__ */ jsxRuntime.jsx(
10130
+ "button",
10131
+ {
10132
+ type: "button",
10133
+ onMouseDown,
10134
+ disabled,
10135
+ "aria-label": title,
10136
+ className: cn(
10137
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded text-sm transition-colors",
10138
+ "disabled:cursor-not-allowed disabled:opacity-40",
10139
+ variant === "destructive" ? theme.toolbar.btnDestructive : active ? theme.toolbar.btnActive : theme.toolbar.btnIdle
10140
+ ),
10141
+ children
10142
+ }
10143
+ );
10144
+ if (!tooltip) return btn;
10145
+ return /* @__PURE__ */ jsxRuntime.jsx(Tooltip2, { content: tooltip, position: "bottom", asChild: true, children: btn });
10146
+ }
10147
+ function Divider() {
10148
+ const theme = useRichEditorTheme();
10149
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mx-1 h-6 w-px", theme.toolbar.divider) });
10150
+ }
10151
+ function cmd(fn) {
10152
+ return (e) => {
10153
+ e.preventDefault();
10154
+ fn();
10155
+ };
10156
+ }
10157
+ function RichEditorToolbar(props) {
10158
+ const { editor, toolbar = {}, className } = props;
10159
+ const theme = useRichEditorTheme();
10160
+ const [tablePickerOpen, setTablePickerOpen] = React6.useState(false);
10161
+ const stateOrNull = react.useEditorState({
10162
+ editor,
10163
+ selector: ({ editor: e }) => ({
10164
+ isH1: e?.isActive("heading", { level: 1 }) ?? false,
10165
+ isH2: e?.isActive("heading", { level: 2 }) ?? false,
10166
+ isH3: e?.isActive("heading", { level: 3 }) ?? false,
10167
+ isH4: e?.isActive("heading", { level: 4 }) ?? false,
10168
+ isBold: e?.isActive("bold") ?? false,
10169
+ isItalic: e?.isActive("italic") ?? false,
10170
+ isStrike: e?.isActive("strike") ?? false,
10171
+ isCode: e?.isActive("code") ?? false,
10172
+ isAlignLeft: e?.isActive({ textAlign: "left" }) ?? false,
10173
+ isAlignCenter: e?.isActive({ textAlign: "center" }) ?? false,
10174
+ isAlignRight: e?.isActive({ textAlign: "right" }) ?? false,
10175
+ isBulletList: e?.isActive("bulletList") ?? false,
10176
+ isOrderedList: e?.isActive("orderedList") ?? false,
10177
+ isBlockquote: e?.isActive("blockquote") ?? false,
10178
+ isCodeBlock: e?.isActive("codeBlock") ?? false,
10179
+ isTable: e?.isActive("table") ?? false
10180
+ })
10181
+ });
10182
+ if (!editor) return null;
10183
+ const state = stateOrNull ?? {
10184
+ isH1: false,
10185
+ isH2: false,
10186
+ isH3: false,
10187
+ isH4: false,
10188
+ isBold: false,
10189
+ isItalic: false,
10190
+ isStrike: false,
10191
+ isCode: false,
10192
+ isAlignLeft: false,
10193
+ isAlignCenter: false,
10194
+ isAlignRight: false,
10195
+ isBulletList: false,
10196
+ isOrderedList: false,
10197
+ isBlockquote: false,
10198
+ isCodeBlock: false,
10199
+ isTable: false
10200
+ };
10201
+ const showHeadingGroup = toolbar.heading !== false && (Array.isArray(toolbar.heading) ? toolbar.heading.length > 0 : true);
10202
+ const showInlineGroup = toolbar.bold !== false || toolbar.italic !== false || toolbar.strike !== false || toolbar.code !== false;
10203
+ const showAlignGroup = toolbar.textAlign !== false;
10204
+ const showListGroup = toolbar.bulletList !== false || toolbar.orderedList !== false || toolbar.blockquote !== false || toolbar.codeBlock !== false;
10205
+ return /* @__PURE__ */ jsxRuntime.jsxs(
10206
+ "div",
10207
+ {
10208
+ className: cn(
10209
+ "flex flex-wrap items-center gap-0.5 p-2",
10210
+ theme.toolbar.wrapper,
10211
+ className
10212
+ ),
10213
+ children: [
10214
+ showHeadingGroup && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10215
+ (!Array.isArray(toolbar.heading) || toolbar.heading.includes(1)) && /* @__PURE__ */ jsxRuntime.jsx(
10216
+ ToolbarButton,
10217
+ {
10218
+ onMouseDown: cmd(
10219
+ () => editor.chain().focus().toggleHeading({ level: 1 }).run()
10220
+ ),
10221
+ active: state.isH1,
10222
+ title: "\uC81C\uBAA9 1 (H1)",
10223
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading1, { size: 16 })
10224
+ }
10225
+ ),
10226
+ (!Array.isArray(toolbar.heading) || toolbar.heading.includes(2)) && /* @__PURE__ */ jsxRuntime.jsx(
10227
+ ToolbarButton,
10228
+ {
10229
+ onMouseDown: cmd(
10230
+ () => editor.chain().focus().toggleHeading({ level: 2 }).run()
10231
+ ),
10232
+ active: state.isH2,
10233
+ title: "\uC81C\uBAA9 2 (H2)",
10234
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading2, { size: 16 })
10235
+ }
10236
+ ),
10237
+ (!Array.isArray(toolbar.heading) || toolbar.heading.includes(3)) && /* @__PURE__ */ jsxRuntime.jsx(
10238
+ ToolbarButton,
10239
+ {
10240
+ onMouseDown: cmd(
10241
+ () => editor.chain().focus().toggleHeading({ level: 3 }).run()
10242
+ ),
10243
+ active: state.isH3,
10244
+ title: "\uC81C\uBAA9 3 (H3)",
10245
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading3, { size: 16 })
10246
+ }
10247
+ ),
10248
+ (!Array.isArray(toolbar.heading) || toolbar.heading.includes(4)) && /* @__PURE__ */ jsxRuntime.jsx(
10249
+ ToolbarButton,
10250
+ {
10251
+ onMouseDown: cmd(
10252
+ () => editor.chain().focus().toggleHeading({ level: 4 }).run()
10253
+ ),
10254
+ active: state.isH4,
10255
+ title: "\uC81C\uBAA9 4 (H4)",
10256
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading4, { size: 16 })
10257
+ }
10258
+ ),
10259
+ showInlineGroup && /* @__PURE__ */ jsxRuntime.jsx(Divider, {})
10260
+ ] }),
10261
+ toolbar.bold !== false && /* @__PURE__ */ jsxRuntime.jsx(
10262
+ ToolbarButton,
10263
+ {
10264
+ onMouseDown: cmd(() => editor.chain().focus().toggleBold().run()),
10265
+ active: state.isBold,
10266
+ title: "\uAD75\uAC8C (Ctrl+B)",
10267
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bold, { size: 16 })
10268
+ }
10269
+ ),
10270
+ toolbar.italic !== false && /* @__PURE__ */ jsxRuntime.jsx(
10271
+ ToolbarButton,
10272
+ {
10273
+ onMouseDown: cmd(() => editor.chain().focus().toggleItalic().run()),
10274
+ active: state.isItalic,
10275
+ title: "\uAE30\uC6B8\uC784 (Ctrl+I)",
10276
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Italic, { size: 16 })
10277
+ }
10278
+ ),
10279
+ toolbar.strike !== false && /* @__PURE__ */ jsxRuntime.jsx(
10280
+ ToolbarButton,
10281
+ {
10282
+ onMouseDown: cmd(() => editor.chain().focus().toggleStrike().run()),
10283
+ active: state.isStrike,
10284
+ title: "\uCDE8\uC18C\uC120",
10285
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Strikethrough, { size: 16 })
10286
+ }
10287
+ ),
10288
+ toolbar.code !== false && /* @__PURE__ */ jsxRuntime.jsx(
10289
+ ToolbarButton,
10290
+ {
10291
+ onMouseDown: cmd(() => editor.chain().focus().toggleCode().run()),
10292
+ active: state.isCode,
10293
+ title: "\uC778\uB77C\uC778 \uCF54\uB4DC",
10294
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code, { size: 16 })
10295
+ }
10296
+ ),
10297
+ showAlignGroup && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10298
+ showInlineGroup && /* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
10299
+ /* @__PURE__ */ jsxRuntime.jsx(
10300
+ ToolbarButton,
10301
+ {
10302
+ onMouseDown: cmd(
10303
+ () => editor.chain().focus().setTextAlign("left").run()
10304
+ ),
10305
+ active: state.isAlignLeft,
10306
+ title: "\uC67C\uCABD \uC815\uB82C",
10307
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeft, { size: 16 })
10308
+ }
10309
+ ),
10310
+ /* @__PURE__ */ jsxRuntime.jsx(
10311
+ ToolbarButton,
10312
+ {
10313
+ onMouseDown: cmd(
10314
+ () => editor.chain().focus().setTextAlign("center").run()
10315
+ ),
10316
+ active: state.isAlignCenter,
10317
+ title: "\uAC00\uC6B4\uB370 \uC815\uB82C",
10318
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignCenter, { size: 16 })
10319
+ }
10320
+ ),
10321
+ /* @__PURE__ */ jsxRuntime.jsx(
10322
+ ToolbarButton,
10323
+ {
10324
+ onMouseDown: cmd(
10325
+ () => editor.chain().focus().setTextAlign("right").run()
10326
+ ),
10327
+ active: state.isAlignRight,
10328
+ title: "\uC624\uB978\uCABD \uC815\uB82C",
10329
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignRight, { size: 16 })
10330
+ }
10331
+ )
10332
+ ] }),
10333
+ showListGroup && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10334
+ /* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
10335
+ toolbar.bulletList !== false && /* @__PURE__ */ jsxRuntime.jsx(
10336
+ ToolbarButton,
10337
+ {
10338
+ onMouseDown: cmd(
10339
+ () => editor.chain().focus().toggleBulletList().run()
10340
+ ),
10341
+ active: state.isBulletList,
10342
+ title: "\uAE00\uBA38\uB9AC \uAE30\uD638",
10343
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.List, { size: 16 })
10344
+ }
10345
+ ),
10346
+ toolbar.orderedList !== false && /* @__PURE__ */ jsxRuntime.jsx(
10347
+ ToolbarButton,
10348
+ {
10349
+ onMouseDown: cmd(
10350
+ () => editor.chain().focus().toggleOrderedList().run()
10351
+ ),
10352
+ active: state.isOrderedList,
10353
+ title: "\uBC88\uD638 \uBAA9\uB85D",
10354
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListOrdered, { size: 16 })
10355
+ }
10356
+ ),
10357
+ toolbar.blockquote !== false && /* @__PURE__ */ jsxRuntime.jsx(
10358
+ ToolbarButton,
10359
+ {
10360
+ onMouseDown: cmd(
10361
+ () => editor.chain().focus().toggleBlockquote().run()
10362
+ ),
10363
+ active: state.isBlockquote,
10364
+ title: "\uC778\uC6A9\uAD6C",
10365
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Quote, { size: 16 })
10366
+ }
10367
+ ),
10368
+ toolbar.codeBlock !== false && /* @__PURE__ */ jsxRuntime.jsx(
10369
+ ToolbarButton,
10370
+ {
10371
+ onMouseDown: cmd(
10372
+ () => editor.chain().focus().toggleCodeBlock().run()
10373
+ ),
10374
+ active: state.isCodeBlock,
10375
+ title: "\uCF54\uB4DC \uBE14\uB85D",
10376
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { size: 16 })
10377
+ }
10378
+ )
10379
+ ] }),
10380
+ toolbar.table && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10381
+ /* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
10382
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: tablePickerOpen, onOpenChange: setTablePickerOpen, children: [
10383
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10384
+ "button",
10385
+ {
10386
+ type: "button",
10387
+ "aria-label": "\uD14C\uC774\uBE14 \uC0BD\uC785",
10388
+ className: cn(
10389
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded text-sm transition-colors",
10390
+ "disabled:cursor-not-allowed disabled:opacity-40",
10391
+ state.isTable ? theme.toolbar.btnActive : theme.toolbar.btnIdle
10392
+ ),
10393
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Table, { size: 16 })
10394
+ }
10395
+ ) }),
10396
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-auto p-0", align: "start", position: "bottom", children: editor && /* @__PURE__ */ jsxRuntime.jsx(TableGridPicker, { editor, onClose: () => setTablePickerOpen(false) }) })
10397
+ ] }),
10398
+ state.isTable && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10399
+ /* @__PURE__ */ jsxRuntime.jsx(
10400
+ ToolbarButton,
10401
+ {
10402
+ onMouseDown: cmd(() => editor.chain().focus().addRowAfter().run()),
10403
+ title: "\uC544\uB798\uC5D0 \uD589 \uCD94\uAC00",
10404
+ tooltip: "\uD589 \uCD94\uAC00",
10405
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14 })
10406
+ }
10407
+ ),
10408
+ /* @__PURE__ */ jsxRuntime.jsx(
10409
+ ToolbarButton,
10410
+ {
10411
+ onMouseDown: cmd(() => {
10412
+ editor.chain().focus().command(({ tr, dispatch, state: state2 }) => {
10413
+ const { $anchor } = state2.selection;
10414
+ let tableNode = null;
10415
+ let tableStart = 0;
10416
+ for (let depth = $anchor.depth; depth > 0; depth--) {
10417
+ const node = $anchor.node(depth);
10418
+ if (node.type.name === "table") {
10419
+ tableNode = node;
10420
+ tableStart = $anchor.start(depth);
10421
+ break;
10422
+ }
10423
+ }
10424
+ if (!tableNode) return false;
10425
+ let lastRowStart = 0;
10426
+ let lastRowSize = 0;
10427
+ let rowCount = 0;
10428
+ tableNode.forEach((child, offset) => {
10429
+ if (child.type.name !== "tableRow") return;
10430
+ rowCount++;
10431
+ lastRowStart = tableStart + offset;
10432
+ lastRowSize = child.nodeSize;
10433
+ });
10434
+ if (rowCount <= 1) return false;
10435
+ if (dispatch) {
10436
+ dispatch(tr.delete(lastRowStart, lastRowStart + lastRowSize));
10437
+ }
10438
+ return true;
10439
+ }).run();
10440
+ }),
10441
+ title: "\uB9C8\uC9C0\uB9C9 \uD589 \uC0AD\uC81C",
10442
+ tooltip: "\uD589 \uC0AD\uC81C",
10443
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { size: 14 })
10444
+ }
10445
+ ),
10446
+ /* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
10447
+ /* @__PURE__ */ jsxRuntime.jsx(
10448
+ ToolbarButton,
10449
+ {
10450
+ onMouseDown: cmd(() => editor.chain().focus().addColumnAfter().run()),
10451
+ title: "\uC624\uB978\uCABD\uC5D0 \uC5F4 \uCD94\uAC00",
10452
+ tooltip: "\uC5F4 \uCD94\uAC00",
10453
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs font-bold leading-none", theme.toolbar.rText), children: "R+" })
10454
+ }
10455
+ ),
10456
+ /* @__PURE__ */ jsxRuntime.jsx(
10457
+ ToolbarButton,
10458
+ {
10459
+ onMouseDown: cmd(() => editor.chain().focus().deleteColumn().run()),
10460
+ title: "\uD604\uC7AC \uC5F4 \uC0AD\uC81C",
10461
+ tooltip: "\uC5F4 \uC0AD\uC81C",
10462
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs font-bold leading-none", theme.toolbar.rText), children: "R-" })
10463
+ }
10464
+ ),
10465
+ /* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
10466
+ /* @__PURE__ */ jsxRuntime.jsx(
10467
+ ToolbarButton,
10468
+ {
10469
+ onMouseDown: cmd(() => editor.chain().focus().deleteTable().run()),
10470
+ title: "\uD14C\uC774\uBE14 \uC0AD\uC81C",
10471
+ tooltip: "\uD14C\uC774\uBE14 \uC0AD\uC81C",
10472
+ variant: "destructive",
10473
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 14 })
10474
+ }
10475
+ )
10476
+ ] })
10477
+ ] })
10478
+ ]
10479
+ }
10480
+ );
10481
+ }
10482
+ var DEFAULT_TOOLBAR = {
10483
+ heading: [1, 2, 3, 4],
10484
+ bold: true,
10485
+ italic: true,
10486
+ strike: true,
10487
+ textAlign: true,
10488
+ bulletList: true,
10489
+ orderedList: true,
10490
+ blockquote: true,
10491
+ code: true
10492
+ };
10493
+ function RichEditorContent(props) {
10494
+ const { editor, className, editorClassName, minHeight, maxHeight } = props;
10495
+ const style = {};
10496
+ if (minHeight) style.minHeight = typeof minHeight === "number" ? `${minHeight}px` : minHeight;
10497
+ if (maxHeight) {
10498
+ style.maxHeight = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
10499
+ style.overflowY = "auto";
10500
+ }
10501
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("rich-editor-content", className), style, children: /* @__PURE__ */ jsxRuntime.jsx(react.EditorContent, { editor, className: cn("h-full", editorClassName) }) });
10502
+ }
10503
+ var RichEditor = React6.forwardRef(function RichEditor2({
10504
+ value,
10505
+ defaultValue,
10506
+ onChange,
10507
+ toolbar = true,
10508
+ mentionUsers,
10509
+ onMentionSearch,
10510
+ additionalExtensions,
10511
+ onSubmit,
10512
+ theme = "light",
10513
+ placeholder,
10514
+ minHeight,
10515
+ maxHeight,
10516
+ className,
10517
+ bodyClassName,
10518
+ editorClassName,
10519
+ mentionClassName,
10520
+ themeTokens,
10521
+ editable = true,
10522
+ autofocus
10523
+ }, ref) {
10524
+ const showToolbar = toolbar !== false;
10525
+ const toolbarOptions = typeof toolbar === "object" ? toolbar : {};
10526
+ const activeToolbar = {
10527
+ ...DEFAULT_TOOLBAR,
10528
+ ...toolbarOptions,
10529
+ ...placeholder !== void 0 && !toolbarOptions.placeholder ? { placeholder } : {}
10530
+ };
10531
+ const isInternalChangeRef = React6.useRef(false);
10532
+ const handleChange = React6.useCallback(
10533
+ (html) => {
10534
+ isInternalChangeRef.current = true;
10535
+ onChange?.(html);
10536
+ },
10537
+ [onChange]
10538
+ );
10539
+ const { editor } = useRichEditor({
10540
+ defaultValue: value ?? defaultValue,
10541
+ toolbar: activeToolbar,
10542
+ mentionUsers,
10543
+ onMentionSearch,
10544
+ mentionClassName,
10545
+ additionalExtensions,
10546
+ editable,
10547
+ autofocus,
10548
+ editorClassName,
10549
+ onChange: handleChange,
10550
+ onSubmit
10551
+ });
10552
+ React6.useEffect(() => {
10553
+ if (!editor || value === void 0) return;
10554
+ if (isInternalChangeRef.current) {
10555
+ isInternalChangeRef.current = false;
10556
+ return;
10557
+ }
10558
+ if (editor.getHTML() !== value) {
10559
+ editor.commands.setContent(value, { emitUpdate: false });
10560
+ }
10561
+ }, [value, editor]);
10562
+ React6.useImperativeHandle(
10563
+ ref,
10564
+ () => ({
10565
+ getHTML: () => editor?.getHTML() ?? "",
10566
+ getJSON: () => editor?.getJSON() ?? {},
10567
+ setContent: (html) => {
10568
+ editor?.commands.setContent(html);
10569
+ },
10570
+ clearContent: () => {
10571
+ editor?.commands.clearContent();
10572
+ },
10573
+ focus: () => {
10574
+ editor?.commands.focus();
10575
+ },
10576
+ get isEmpty() {
10577
+ return editor?.isEmpty ?? true;
10578
+ },
10579
+ editor
10580
+ }),
10581
+ [editor]
10582
+ );
10583
+ const isToolbarVisible = showToolbar && editable;
10584
+ const baseTheme = RICH_EDITOR_THEMES[theme];
10585
+ const resolvedTheme = themeTokens ? {
10586
+ ...baseTheme,
10587
+ ...themeTokens.toolbar && { toolbar: { ...baseTheme.toolbar, ...themeTokens.toolbar } },
10588
+ ...themeTokens.mention && { mention: { ...baseTheme.mention, ...themeTokens.mention } }
10589
+ } : baseTheme;
10590
+ return /* @__PURE__ */ jsxRuntime.jsx(RichEditorThemeProvider, { value: resolvedTheme, children: /* @__PURE__ */ jsxRuntime.jsxs(
10591
+ "div",
10592
+ {
10593
+ className: cn("overflow-hidden rounded-lg border border-gray-200 shadow-sm flex flex-col relative", className),
10594
+ "data-rich-editor-theme": theme,
10595
+ children: [
10596
+ isToolbarVisible && /* @__PURE__ */ jsxRuntime.jsx(
10597
+ RichEditorToolbar,
10598
+ {
10599
+ editor,
10600
+ toolbar: activeToolbar
10601
+ }
10602
+ ),
10603
+ /* @__PURE__ */ jsxRuntime.jsx(
10604
+ RichEditorContent,
10605
+ {
10606
+ editor,
10607
+ className: cn("p-4", bodyClassName),
10608
+ minHeight,
10609
+ maxHeight
10610
+ }
10611
+ )
10612
+ ]
10613
+ }
10614
+ ) });
10615
+ });
10616
+ var RichEditor_default = RichEditor;
9600
10617
  function useDetailController(params = {}) {
9601
10618
  const { mode: controlledMode, onModeChange } = params;
9602
10619
  const [internalMode, setInternalMode] = React6.useState("read");
@@ -10394,6 +11411,9 @@ exports.PopoverTitle = PopoverTitle;
10394
11411
  exports.PopoverTrigger = PopoverTrigger;
10395
11412
  exports.Radio = Radio;
10396
11413
  exports.RadioGroup = RadioGroup;
11414
+ exports.RichEditor = RichEditor_default;
11415
+ exports.RichEditorContent = RichEditorContent;
11416
+ exports.RichEditorToolbar = RichEditorToolbar;
10397
11417
  exports.ScrollArea = ScrollArea_default;
10398
11418
  exports.ScrollBar = ScrollBar;
10399
11419
  exports.SearchAddress = SearchAddress;
@@ -10445,6 +11465,7 @@ exports.useFilePreviewViewer = useFilePreviewViewer;
10445
11465
  exports.useModal = useModal;
10446
11466
  exports.useMultiTabStore = useMultiTabStore;
10447
11467
  exports.useParams = useParams;
11468
+ exports.useRichEditor = useRichEditor;
10448
11469
  exports.useScrollToTop = useScrollToTop;
10449
11470
  exports.useStableImageSrc = useStableImageSrc;
10450
11471
  exports.useToast = useToast;