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