@underverse-ui/underverse 0.2.76 → 0.2.78

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
@@ -159,6 +159,7 @@ __export(index_exports, {
159
159
  ToastProvider: () => Toast_default,
160
160
  Tooltip: () => Tooltip,
161
161
  TranslationProvider: () => TranslationProvider,
162
+ UEditor: () => UEditor_default,
162
163
  UnderverseProvider: () => UnderverseProvider,
163
164
  VARIANT_STYLES_ALERT: () => VARIANT_STYLES_ALERT,
164
165
  VARIANT_STYLES_BTN: () => VARIANT_STYLES_BTN,
@@ -3239,7 +3240,7 @@ var Tooltip = ({
3239
3240
  children,
3240
3241
  content,
3241
3242
  placement = "top",
3242
- delay = { open: 700, close: 300 },
3243
+ delay = { open: 200, close: 300 },
3243
3244
  className,
3244
3245
  disabled = false,
3245
3246
  variant = "default"
@@ -15304,6 +15305,1511 @@ function useSmartLocale() {
15304
15305
  }
15305
15306
  }
15306
15307
 
15308
+ // ../../components/ui/UEditor/UEditor.tsx
15309
+ var import_react44 = require("react");
15310
+ var import_next_intl6 = require("next-intl");
15311
+ var import_react45 = require("@tiptap/react");
15312
+
15313
+ // ../../components/ui/UEditor/extensions.ts
15314
+ var import_extension_document = __toESM(require("@tiptap/extension-document"), 1);
15315
+ var import_extension_paragraph = __toESM(require("@tiptap/extension-paragraph"), 1);
15316
+ var import_extension_text = __toESM(require("@tiptap/extension-text"), 1);
15317
+ var import_extension_bold = __toESM(require("@tiptap/extension-bold"), 1);
15318
+ var import_extension_italic = __toESM(require("@tiptap/extension-italic"), 1);
15319
+ var import_extension_strike = __toESM(require("@tiptap/extension-strike"), 1);
15320
+ var import_extension_underline = __toESM(require("@tiptap/extension-underline"), 1);
15321
+ var import_extension_heading = __toESM(require("@tiptap/extension-heading"), 1);
15322
+ var import_extension_bullet_list = __toESM(require("@tiptap/extension-bullet-list"), 1);
15323
+ var import_extension_ordered_list = __toESM(require("@tiptap/extension-ordered-list"), 1);
15324
+ var import_extension_list_item = __toESM(require("@tiptap/extension-list-item"), 1);
15325
+ var import_extension_task_list = __toESM(require("@tiptap/extension-task-list"), 1);
15326
+ var import_extension_task_item = __toESM(require("@tiptap/extension-task-item"), 1);
15327
+ var import_extension_blockquote = __toESM(require("@tiptap/extension-blockquote"), 1);
15328
+ var import_extension_code = __toESM(require("@tiptap/extension-code"), 1);
15329
+ var import_extension_code_block_lowlight = __toESM(require("@tiptap/extension-code-block-lowlight"), 1);
15330
+ var import_extension_history = __toESM(require("@tiptap/extension-history"), 1);
15331
+ var import_extension_placeholder = __toESM(require("@tiptap/extension-placeholder"), 1);
15332
+ var import_extension_link = __toESM(require("@tiptap/extension-link"), 1);
15333
+ var import_extension_image = __toESM(require("@tiptap/extension-image"), 1);
15334
+ var import_extension_text_style = require("@tiptap/extension-text-style");
15335
+ var import_extension_color = __toESM(require("@tiptap/extension-color"), 1);
15336
+ var import_extension_highlight = __toESM(require("@tiptap/extension-highlight"), 1);
15337
+ var import_extension_text_align = __toESM(require("@tiptap/extension-text-align"), 1);
15338
+ var import_extension_table = require("@tiptap/extension-table");
15339
+ var import_extension_table_row = __toESM(require("@tiptap/extension-table-row"), 1);
15340
+ var import_extension_table_cell = __toESM(require("@tiptap/extension-table-cell"), 1);
15341
+ var import_extension_table_header = __toESM(require("@tiptap/extension-table-header"), 1);
15342
+ var import_extension_character_count = __toESM(require("@tiptap/extension-character-count"), 1);
15343
+ var import_extension_typography = __toESM(require("@tiptap/extension-typography"), 1);
15344
+ var import_extension_subscript = __toESM(require("@tiptap/extension-subscript"), 1);
15345
+ var import_extension_superscript = __toESM(require("@tiptap/extension-superscript"), 1);
15346
+ var import_extension_horizontal_rule = __toESM(require("@tiptap/extension-horizontal-rule"), 1);
15347
+ var import_lowlight = require("lowlight");
15348
+
15349
+ // ../../components/ui/UEditor/slash-command.tsx
15350
+ var import_core = require("@tiptap/core");
15351
+ var import_suggestion = __toESM(require("@tiptap/suggestion"), 1);
15352
+ var import_react38 = require("@tiptap/react");
15353
+ var import_react39 = require("react");
15354
+ var import_lucide_react33 = require("lucide-react");
15355
+ var import_tippy = __toESM(require("tippy.js"), 1);
15356
+ var import_jsx_runtime68 = require("react/jsx-runtime");
15357
+ var CommandList = (0, import_react39.forwardRef)((props, ref) => {
15358
+ const [selectedIndex, setSelectedIndex] = (0, import_react39.useState)(0);
15359
+ const listRef = (0, import_react39.useRef)(null);
15360
+ (0, import_react39.useEffect)(() => {
15361
+ setSelectedIndex(0);
15362
+ }, [props.items]);
15363
+ (0, import_react39.useEffect)(() => {
15364
+ const selectedElement = listRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
15365
+ selectedElement?.scrollIntoView({ block: "nearest" });
15366
+ }, [selectedIndex, props.items]);
15367
+ (0, import_react39.useImperativeHandle)(ref, () => ({
15368
+ onKeyDown: ({ event }) => {
15369
+ if (event.key === "ArrowUp") {
15370
+ setSelectedIndex((prev) => (prev + props.items.length - 1) % props.items.length);
15371
+ return true;
15372
+ }
15373
+ if (event.key === "ArrowDown") {
15374
+ setSelectedIndex((prev) => (prev + 1) % props.items.length);
15375
+ return true;
15376
+ }
15377
+ if (event.key === "Enter") {
15378
+ const item = props.items[selectedIndex];
15379
+ if (item) {
15380
+ props.command(item);
15381
+ }
15382
+ return true;
15383
+ }
15384
+ return false;
15385
+ }
15386
+ }));
15387
+ if (props.items.length === 0) {
15388
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: "No results" });
15389
+ }
15390
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { ref: listRef, className: "w-72 max-h-80 overflow-y-auto bg-card border border-border rounded-2xl shadow-lg", children: [
15391
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Basic Blocks" }) }),
15392
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "p-1", children: props.items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
15393
+ "button",
15394
+ {
15395
+ type: "button",
15396
+ "data-index": index,
15397
+ onClick: () => props.command(item),
15398
+ className: cn(
15399
+ "flex items-center w-full px-3 py-2.5 rounded-lg transition-colors group",
15400
+ selectedIndex === index ? "bg-accent" : "hover:bg-accent/50"
15401
+ ),
15402
+ children: [
15403
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
15404
+ "div",
15405
+ {
15406
+ className: cn(
15407
+ "flex items-center justify-center w-10 h-10 rounded-lg mr-3 transition-colors",
15408
+ selectedIndex === index ? "bg-primary/10" : "bg-muted/50 group-hover:bg-muted"
15409
+ ),
15410
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(item.icon, { className: cn("w-5 h-5", selectedIndex === index ? "text-primary" : "text-muted-foreground") })
15411
+ }
15412
+ ),
15413
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "text-left", children: [
15414
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: cn("text-sm font-medium", selectedIndex === index && "text-primary"), children: item.title }),
15415
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "text-xs text-muted-foreground", children: item.description })
15416
+ ] })
15417
+ ]
15418
+ },
15419
+ item.title
15420
+ )) })
15421
+ ] });
15422
+ });
15423
+ CommandList.displayName = "CommandList";
15424
+ var getSuggestionItems = ({ query }) => {
15425
+ return [
15426
+ {
15427
+ icon: import_lucide_react33.Type,
15428
+ title: "Text",
15429
+ description: "Start writing with plain text",
15430
+ command: ({ editor, range }) => {
15431
+ editor.chain().focus().deleteRange(range).setParagraph().run();
15432
+ }
15433
+ },
15434
+ {
15435
+ icon: import_lucide_react33.Heading1,
15436
+ title: "Heading 1",
15437
+ description: "Large section heading",
15438
+ command: ({ editor, range }) => {
15439
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
15440
+ }
15441
+ },
15442
+ {
15443
+ icon: import_lucide_react33.Heading2,
15444
+ title: "Heading 2",
15445
+ description: "Medium section heading",
15446
+ command: ({ editor, range }) => {
15447
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
15448
+ }
15449
+ },
15450
+ {
15451
+ icon: import_lucide_react33.Heading3,
15452
+ title: "Heading 3",
15453
+ description: "Small section heading",
15454
+ command: ({ editor, range }) => {
15455
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
15456
+ }
15457
+ },
15458
+ {
15459
+ icon: import_lucide_react33.List,
15460
+ title: "Bullet List",
15461
+ description: "Create a simple bullet list",
15462
+ command: ({ editor, range }) => {
15463
+ editor.chain().focus().deleteRange(range).toggleBulletList().run();
15464
+ }
15465
+ },
15466
+ {
15467
+ icon: import_lucide_react33.ListOrdered,
15468
+ title: "Numbered List",
15469
+ description: "Create a list with numbering",
15470
+ command: ({ editor, range }) => {
15471
+ editor.chain().focus().deleteRange(range).toggleOrderedList().run();
15472
+ }
15473
+ },
15474
+ {
15475
+ icon: import_lucide_react33.ListTodo,
15476
+ title: "Todo List",
15477
+ description: "Track tasks with a todo list",
15478
+ command: ({ editor, range }) => {
15479
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
15480
+ }
15481
+ },
15482
+ {
15483
+ icon: import_lucide_react33.Quote,
15484
+ title: "Quote",
15485
+ description: "Capture a quote",
15486
+ command: ({ editor, range }) => {
15487
+ editor.chain().focus().deleteRange(range).toggleBlockquote().run();
15488
+ }
15489
+ },
15490
+ {
15491
+ icon: import_lucide_react33.FileCode,
15492
+ title: "Code Block",
15493
+ description: "Display code with syntax highlighting",
15494
+ command: ({ editor, range }) => {
15495
+ editor.chain().focus().deleteRange(range).toggleCodeBlock().run();
15496
+ }
15497
+ },
15498
+ {
15499
+ icon: import_lucide_react33.Minus,
15500
+ title: "Divider",
15501
+ description: "Visually divide blocks",
15502
+ command: ({ editor, range }) => {
15503
+ editor.chain().focus().deleteRange(range).setHorizontalRule().run();
15504
+ }
15505
+ },
15506
+ {
15507
+ icon: import_lucide_react33.Table,
15508
+ title: "Table",
15509
+ description: "Insert a table",
15510
+ command: ({ editor, range }) => {
15511
+ editor.chain().focus().deleteRange(range).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
15512
+ }
15513
+ }
15514
+ ].filter((item) => item.title.toLowerCase().includes(query.toLowerCase()));
15515
+ };
15516
+ var SlashCommand = import_core.Extension.create({
15517
+ name: "slashCommand",
15518
+ addProseMirrorPlugins() {
15519
+ return [
15520
+ (0, import_suggestion.default)({
15521
+ editor: this.editor,
15522
+ char: "/",
15523
+ command: ({ editor, range, props }) => {
15524
+ props.command({ editor, range });
15525
+ },
15526
+ items: getSuggestionItems,
15527
+ render: () => {
15528
+ let component;
15529
+ let popup;
15530
+ return {
15531
+ onStart: (props) => {
15532
+ component = new import_react38.ReactRenderer(CommandList, {
15533
+ props,
15534
+ editor: props.editor
15535
+ });
15536
+ if (!props.clientRect) {
15537
+ return;
15538
+ }
15539
+ popup = (0, import_tippy.default)("body", {
15540
+ getReferenceClientRect: props.clientRect,
15541
+ appendTo: () => document.body,
15542
+ content: component.element,
15543
+ showOnCreate: true,
15544
+ interactive: true,
15545
+ trigger: "manual",
15546
+ placement: "bottom-start"
15547
+ });
15548
+ },
15549
+ onUpdate(props) {
15550
+ component?.updateProps(props);
15551
+ if (!props.clientRect) {
15552
+ return;
15553
+ }
15554
+ popup?.[0]?.setProps({
15555
+ getReferenceClientRect: props.clientRect
15556
+ });
15557
+ },
15558
+ onKeyDown(props) {
15559
+ if (props.event.key === "Escape") {
15560
+ popup?.[0]?.hide();
15561
+ return true;
15562
+ }
15563
+ return component?.ref?.onKeyDown(props) ?? false;
15564
+ },
15565
+ onExit() {
15566
+ popup?.[0]?.destroy();
15567
+ component?.destroy();
15568
+ }
15569
+ };
15570
+ }
15571
+ })
15572
+ ];
15573
+ }
15574
+ });
15575
+
15576
+ // ../../components/ui/UEditor/extensions.ts
15577
+ var lowlight = (0, import_lowlight.createLowlight)(import_lowlight.common);
15578
+ function buildUEditorExtensions({ placeholder, maxCharacters }) {
15579
+ return [
15580
+ import_extension_document.default,
15581
+ import_extension_paragraph.default,
15582
+ import_extension_text.default,
15583
+ import_extension_bold.default,
15584
+ import_extension_italic.default,
15585
+ import_extension_strike.default,
15586
+ import_extension_underline.default,
15587
+ import_extension_subscript.default,
15588
+ import_extension_superscript.default,
15589
+ import_extension_heading.default.configure({
15590
+ levels: [1, 2, 3]
15591
+ }),
15592
+ import_extension_bullet_list.default.configure({
15593
+ HTMLAttributes: {
15594
+ class: "list-disc pl-6 my-2 space-y-1"
15595
+ }
15596
+ }),
15597
+ import_extension_ordered_list.default.configure({
15598
+ HTMLAttributes: {
15599
+ class: "list-decimal pl-6 my-2 space-y-1"
15600
+ }
15601
+ }),
15602
+ import_extension_list_item.default.configure({
15603
+ HTMLAttributes: {
15604
+ class: "pl-1"
15605
+ }
15606
+ }),
15607
+ import_extension_task_list.default,
15608
+ import_extension_task_item.default.configure({
15609
+ nested: true
15610
+ }),
15611
+ import_extension_blockquote.default.configure({
15612
+ HTMLAttributes: {
15613
+ class: "border-l-4 border-primary pl-4 py-2 my-4 bg-muted/30 rounded-r-lg italic text-muted-foreground"
15614
+ }
15615
+ }),
15616
+ import_extension_code.default.configure({
15617
+ HTMLAttributes: {
15618
+ class: "px-1.5 py-0.5 rounded bg-muted font-mono text-sm"
15619
+ }
15620
+ }),
15621
+ import_extension_code_block_lowlight.default.configure({
15622
+ lowlight,
15623
+ HTMLAttributes: {
15624
+ class: "rounded-lg bg-[#1e1e1e] p-4 font-mono text-sm overflow-x-auto"
15625
+ }
15626
+ }),
15627
+ import_extension_horizontal_rule.default,
15628
+ import_extension_link.default.configure({
15629
+ openOnClick: false,
15630
+ HTMLAttributes: {
15631
+ class: "text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer"
15632
+ }
15633
+ }),
15634
+ import_extension_image.default.configure({
15635
+ HTMLAttributes: {
15636
+ class: "rounded-lg max-w-full h-auto my-4"
15637
+ }
15638
+ }),
15639
+ import_extension_text_style.TextStyle,
15640
+ import_extension_color.default,
15641
+ import_extension_highlight.default.configure({
15642
+ multicolor: true
15643
+ }),
15644
+ import_extension_text_align.default.configure({
15645
+ types: ["heading", "paragraph"]
15646
+ }),
15647
+ import_extension_table.Table.configure({
15648
+ resizable: true,
15649
+ HTMLAttributes: {
15650
+ class: "border-collapse w-full my-4"
15651
+ }
15652
+ }),
15653
+ import_extension_table_row.default,
15654
+ import_extension_table_cell.default.configure({
15655
+ HTMLAttributes: {
15656
+ class: "border border-border p-2 min-w-[100px]"
15657
+ }
15658
+ }),
15659
+ import_extension_table_header.default.configure({
15660
+ HTMLAttributes: {
15661
+ class: "border border-border p-2 bg-muted font-semibold min-w-[100px]"
15662
+ }
15663
+ }),
15664
+ import_extension_character_count.default.configure({
15665
+ limit: maxCharacters
15666
+ }),
15667
+ import_extension_typography.default,
15668
+ import_extension_history.default,
15669
+ import_extension_placeholder.default.configure({
15670
+ placeholder,
15671
+ emptyEditorClass: "is-editor-empty",
15672
+ emptyNodeClass: "is-empty"
15673
+ }),
15674
+ SlashCommand
15675
+ ];
15676
+ }
15677
+
15678
+ // ../../components/ui/UEditor/toolbar.tsx
15679
+ var import_react42 = __toESM(require("react"), 1);
15680
+ var import_next_intl3 = require("next-intl");
15681
+ var import_lucide_react36 = require("lucide-react");
15682
+
15683
+ // ../../components/ui/UEditor/colors.tsx
15684
+ var import_react40 = require("react");
15685
+ var import_next_intl = require("next-intl");
15686
+ var import_lucide_react34 = require("lucide-react");
15687
+ var import_jsx_runtime69 = require("react/jsx-runtime");
15688
+ var useEditorColors = () => {
15689
+ const t = (0, import_next_intl.useTranslations)("UEditor");
15690
+ const textColors = (0, import_react40.useMemo)(
15691
+ () => [
15692
+ { name: t("colors.default"), color: "inherit", cssClass: "text-foreground" },
15693
+ { name: t("colors.muted"), color: "var(--muted-foreground)", cssClass: "text-muted-foreground" },
15694
+ { name: t("colors.primary"), color: "var(--primary)", cssClass: "text-primary" },
15695
+ { name: t("colors.secondary"), color: "var(--secondary)", cssClass: "text-secondary" },
15696
+ { name: t("colors.success"), color: "var(--success)", cssClass: "text-success" },
15697
+ { name: t("colors.warning"), color: "var(--warning)", cssClass: "text-warning" },
15698
+ { name: t("colors.destructive"), color: "var(--destructive)", cssClass: "text-destructive" },
15699
+ { name: t("colors.info"), color: "var(--info)", cssClass: "text-info" }
15700
+ ],
15701
+ [t]
15702
+ );
15703
+ const highlightColors = (0, import_react40.useMemo)(
15704
+ () => [
15705
+ { name: t("colors.default"), color: "", cssClass: "" },
15706
+ { name: t("colors.muted"), color: "var(--muted)", cssClass: "bg-muted" },
15707
+ { name: t("colors.primary"), color: "color-mix(in oklch, var(--primary) 20%, transparent)", cssClass: "bg-primary/20" },
15708
+ { name: t("colors.secondary"), color: "color-mix(in oklch, var(--secondary) 20%, transparent)", cssClass: "bg-secondary/20" },
15709
+ { name: t("colors.success"), color: "color-mix(in oklch, var(--success) 20%, transparent)", cssClass: "bg-success/20" },
15710
+ { name: t("colors.warning"), color: "color-mix(in oklch, var(--warning) 20%, transparent)", cssClass: "bg-warning/20" },
15711
+ { name: t("colors.destructive"), color: "color-mix(in oklch, var(--destructive) 20%, transparent)", cssClass: "bg-destructive/20" },
15712
+ { name: t("colors.info"), color: "color-mix(in oklch, var(--info) 20%, transparent)", cssClass: "bg-info/20" },
15713
+ { name: t("colors.accent"), color: "var(--accent)", cssClass: "bg-accent" }
15714
+ ],
15715
+ [t]
15716
+ );
15717
+ return { textColors, highlightColors };
15718
+ };
15719
+ var EditorColorPalette = ({
15720
+ colors,
15721
+ currentColor,
15722
+ onSelect,
15723
+ label
15724
+ }) => /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "p-2", children: [
15725
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider px-2", children: label }),
15726
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "grid grid-cols-4 gap-1.5 mt-2", children: colors.map((c) => /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
15727
+ "button",
15728
+ {
15729
+ type: "button",
15730
+ onMouseDown: (e) => e.preventDefault(),
15731
+ onClick: () => onSelect(c.color),
15732
+ className: cn(
15733
+ "flex items-center justify-center w-9 h-9 rounded-lg border-2 transition-all hover:scale-105",
15734
+ currentColor === c.color ? "border-primary ring-2 ring-primary/20" : "border-border/50 hover:border-primary/50"
15735
+ ),
15736
+ style: { backgroundColor: c.color || "transparent" },
15737
+ title: c.name,
15738
+ children: [
15739
+ c.color === "" && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react34.X, { className: "w-4 h-4 text-muted-foreground" }),
15740
+ c.color === "inherit" && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-xs font-medium", children: "A" })
15741
+ ]
15742
+ },
15743
+ c.name
15744
+ )) })
15745
+ ] });
15746
+
15747
+ // ../../components/ui/UEditor/inputs.tsx
15748
+ var import_react41 = require("react");
15749
+ var import_next_intl2 = require("next-intl");
15750
+ var import_lucide_react35 = require("lucide-react");
15751
+ var import_jsx_runtime70 = require("react/jsx-runtime");
15752
+ var LinkInput = ({
15753
+ onSubmit,
15754
+ onCancel,
15755
+ initialUrl = ""
15756
+ }) => {
15757
+ const t = (0, import_next_intl2.useTranslations)("UEditor");
15758
+ const [url, setUrl] = (0, import_react41.useState)(initialUrl);
15759
+ const inputRef = (0, import_react41.useRef)(null);
15760
+ (0, import_react41.useEffect)(() => {
15761
+ inputRef.current?.focus();
15762
+ inputRef.current?.select();
15763
+ }, []);
15764
+ const handleSubmit = (e) => {
15765
+ e.preventDefault();
15766
+ if (url) {
15767
+ onSubmit(url.startsWith("http") ? url : `https://${url}`);
15768
+ }
15769
+ };
15770
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("form", { onSubmit: handleSubmit, className: "flex items-center gap-2 p-2", children: [
15771
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
15772
+ "input",
15773
+ {
15774
+ ref: inputRef,
15775
+ type: "text",
15776
+ value: url,
15777
+ onChange: (e) => setUrl(e.target.value),
15778
+ placeholder: t("linkInput.placeholder"),
15779
+ className: "flex-1 px-3 py-2 text-sm bg-muted/50 border-0 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20"
15780
+ }
15781
+ ),
15782
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("button", { type: "submit", className: "p-2 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(import_lucide_react35.Check, { className: "w-4 h-4" }) }),
15783
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("button", { type: "button", onClick: onCancel, className: "p-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(import_lucide_react35.X, { className: "w-4 h-4" }) })
15784
+ ] });
15785
+ };
15786
+ var ImageInput = ({ onSubmit, onCancel }) => {
15787
+ const t = (0, import_next_intl2.useTranslations)("UEditor");
15788
+ const [url, setUrl] = (0, import_react41.useState)("");
15789
+ const [alt, setAlt] = (0, import_react41.useState)("");
15790
+ const inputRef = (0, import_react41.useRef)(null);
15791
+ (0, import_react41.useEffect)(() => {
15792
+ inputRef.current?.focus();
15793
+ }, []);
15794
+ const handleSubmit = (e) => {
15795
+ e.preventDefault();
15796
+ if (url) {
15797
+ onSubmit(url, alt);
15798
+ }
15799
+ };
15800
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("form", { onSubmit: handleSubmit, className: "p-3 space-y-3", children: [
15801
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { children: [
15802
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.urlLabel") }),
15803
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
15804
+ "input",
15805
+ {
15806
+ ref: inputRef,
15807
+ type: "text",
15808
+ value: url,
15809
+ onChange: (e) => setUrl(e.target.value),
15810
+ placeholder: t("imageInput.urlPlaceholder"),
15811
+ className: "w-full mt-1 px-3 py-2 text-sm bg-muted/50 border-0 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20"
15812
+ }
15813
+ )
15814
+ ] }),
15815
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { children: [
15816
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.altLabel") }),
15817
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
15818
+ "input",
15819
+ {
15820
+ type: "text",
15821
+ value: alt,
15822
+ onChange: (e) => setAlt(e.target.value),
15823
+ placeholder: t("imageInput.altPlaceholder"),
15824
+ className: "w-full mt-1 px-3 py-2 text-sm bg-muted/50 border-0 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20"
15825
+ }
15826
+ )
15827
+ ] }),
15828
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "flex gap-2", children: [
15829
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
15830
+ "button",
15831
+ {
15832
+ type: "submit",
15833
+ disabled: !url,
15834
+ className: "flex-1 py-2 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50",
15835
+ children: t("imageInput.addBtn")
15836
+ }
15837
+ ),
15838
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("button", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: t("imageInput.cancelBtn") })
15839
+ ] })
15840
+ ] });
15841
+ };
15842
+
15843
+ // ../../components/ui/UEditor/toolbar.tsx
15844
+ var import_jsx_runtime71 = require("react/jsx-runtime");
15845
+ var ToolbarButton = import_react42.default.forwardRef(({ onClick, active, disabled, children, title, className }, ref) => {
15846
+ const button = /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15847
+ "button",
15848
+ {
15849
+ ref,
15850
+ type: "button",
15851
+ onMouseDown: (e) => e.preventDefault(),
15852
+ onClick,
15853
+ disabled,
15854
+ className: cn(
15855
+ "flex items-center justify-center w-8 h-8 rounded-lg transition-all duration-200",
15856
+ "hover:bg-accent hover:scale-105",
15857
+ "focus:outline-none focus:ring-2 focus:ring-primary/20",
15858
+ "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:scale-100",
15859
+ active ? "bg-primary/10 text-primary shadow-sm" : "text-muted-foreground hover:text-foreground",
15860
+ className
15861
+ ),
15862
+ children
15863
+ }
15864
+ );
15865
+ if (title) {
15866
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(Tooltip, { content: title, placement: "top", delay: { open: 500, close: 0 }, children: button });
15867
+ }
15868
+ return button;
15869
+ });
15870
+ ToolbarButton.displayName = "ToolbarButton";
15871
+ var ToolbarDivider = () => /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" });
15872
+ var EditorToolbar = ({ editor, variant }) => {
15873
+ const t = (0, import_next_intl3.useTranslations)("UEditor");
15874
+ const { textColors, highlightColors } = useEditorColors();
15875
+ const [showImageInput, setShowImageInput] = (0, import_react42.useState)(false);
15876
+ if (variant === "minimal") {
15877
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "flex items-center gap-1 p-2 border-b bg-muted/30", children: [
15878
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Bold, { className: "w-4 h-4" }) }),
15879
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15880
+ ToolbarButton,
15881
+ {
15882
+ onClick: () => editor.chain().focus().toggleItalic().run(),
15883
+ active: editor.isActive("italic"),
15884
+ title: t("toolbar.italic"),
15885
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Italic, { className: "w-4 h-4" })
15886
+ }
15887
+ ),
15888
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15889
+ ToolbarButton,
15890
+ {
15891
+ onClick: () => editor.chain().focus().toggleBulletList().run(),
15892
+ active: editor.isActive("bulletList"),
15893
+ title: t("toolbar.bulletList"),
15894
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.List, { className: "w-4 h-4" })
15895
+ }
15896
+ )
15897
+ ] });
15898
+ }
15899
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "flex flex-wrap items-center gap-1 p-2 border-b bg-linear-to-r from-muted/30 to-transparent", children: [
15900
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
15901
+ DropdownMenu,
15902
+ {
15903
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
15904
+ }, title: t("toolbar.textStyle"), className: "px-2 w-auto gap-1", children: [
15905
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Type, { className: "w-4 h-4" }),
15906
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
15907
+ ] }),
15908
+ children: [
15909
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DropdownMenuItem, { icon: import_lucide_react36.Type, label: t("toolbar.normal"), onClick: () => editor.chain().focus().setParagraph().run(), active: editor.isActive("paragraph") }),
15910
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15911
+ DropdownMenuItem,
15912
+ {
15913
+ icon: import_lucide_react36.Heading1,
15914
+ label: t("toolbar.heading1"),
15915
+ onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
15916
+ active: editor.isActive("heading", { level: 1 }),
15917
+ shortcut: "Ctrl+Alt+1"
15918
+ }
15919
+ ),
15920
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15921
+ DropdownMenuItem,
15922
+ {
15923
+ icon: import_lucide_react36.Heading2,
15924
+ label: t("toolbar.heading2"),
15925
+ onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
15926
+ active: editor.isActive("heading", { level: 2 }),
15927
+ shortcut: "Ctrl+Alt+2"
15928
+ }
15929
+ ),
15930
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15931
+ DropdownMenuItem,
15932
+ {
15933
+ icon: import_lucide_react36.Heading3,
15934
+ label: t("toolbar.heading3"),
15935
+ onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
15936
+ active: editor.isActive("heading", { level: 3 }),
15937
+ shortcut: "Ctrl+Alt+3"
15938
+ }
15939
+ )
15940
+ ]
15941
+ }
15942
+ ),
15943
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarDivider, {}),
15944
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Bold, { className: "w-4 h-4" }) }),
15945
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15946
+ ToolbarButton,
15947
+ {
15948
+ onClick: () => editor.chain().focus().toggleItalic().run(),
15949
+ active: editor.isActive("italic"),
15950
+ title: t("toolbar.italic"),
15951
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Italic, { className: "w-4 h-4" })
15952
+ }
15953
+ ),
15954
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15955
+ ToolbarButton,
15956
+ {
15957
+ onClick: () => editor.chain().focus().toggleUnderline().run(),
15958
+ active: editor.isActive("underline"),
15959
+ title: t("toolbar.underline"),
15960
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Underline, { className: "w-4 h-4" })
15961
+ }
15962
+ ),
15963
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15964
+ ToolbarButton,
15965
+ {
15966
+ onClick: () => editor.chain().focus().toggleStrike().run(),
15967
+ active: editor.isActive("strike"),
15968
+ title: t("toolbar.strike"),
15969
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Strikethrough, { className: "w-4 h-4" })
15970
+ }
15971
+ ),
15972
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Code, { className: "w-4 h-4" }) }),
15973
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarDivider, {}),
15974
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15975
+ DropdownMenu,
15976
+ {
15977
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
15978
+ }, title: t("colors.textColor"), children: [
15979
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Palette, { className: "w-4 h-4" }),
15980
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
15981
+ ] }),
15982
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
15983
+ EditorColorPalette,
15984
+ {
15985
+ colors: textColors,
15986
+ currentColor: editor.getAttributes("textStyle").color || "inherit",
15987
+ onSelect: (color) => {
15988
+ if (color === "inherit") {
15989
+ editor.chain().focus().unsetColor().run();
15990
+ } else {
15991
+ editor.chain().focus().setColor(color).run();
15992
+ }
15993
+ },
15994
+ label: t("colors.textColor")
15995
+ }
15996
+ )
15997
+ }
15998
+ ),
15999
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16000
+ DropdownMenu,
16001
+ {
16002
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
16003
+ }, active: editor.isActive("highlight"), title: t("colors.highlight"), children: [
16004
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Highlighter, { className: "w-4 h-4" }),
16005
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
16006
+ ] }),
16007
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16008
+ EditorColorPalette,
16009
+ {
16010
+ colors: highlightColors,
16011
+ currentColor: editor.getAttributes("highlight").color || "",
16012
+ onSelect: (color) => {
16013
+ if (color === "") {
16014
+ editor.chain().focus().unsetHighlight().run();
16015
+ } else {
16016
+ editor.chain().focus().toggleHighlight({ color }).run();
16017
+ }
16018
+ },
16019
+ label: t("colors.highlight")
16020
+ }
16021
+ )
16022
+ }
16023
+ ),
16024
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarDivider, {}),
16025
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
16026
+ DropdownMenu,
16027
+ {
16028
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
16029
+ }, title: t("toolbar.alignment"), children: [
16030
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.AlignLeft, { className: "w-4 h-4" }),
16031
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
16032
+ ] }),
16033
+ children: [
16034
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16035
+ DropdownMenuItem,
16036
+ {
16037
+ icon: import_lucide_react36.AlignLeft,
16038
+ label: t("toolbar.alignLeft"),
16039
+ onClick: () => editor.chain().focus().setTextAlign("left").run(),
16040
+ active: editor.isActive({ textAlign: "left" })
16041
+ }
16042
+ ),
16043
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16044
+ DropdownMenuItem,
16045
+ {
16046
+ icon: import_lucide_react36.AlignCenter,
16047
+ label: t("toolbar.alignCenter"),
16048
+ onClick: () => editor.chain().focus().setTextAlign("center").run(),
16049
+ active: editor.isActive({ textAlign: "center" })
16050
+ }
16051
+ ),
16052
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16053
+ DropdownMenuItem,
16054
+ {
16055
+ icon: import_lucide_react36.AlignRight,
16056
+ label: t("toolbar.alignRight"),
16057
+ onClick: () => editor.chain().focus().setTextAlign("right").run(),
16058
+ active: editor.isActive({ textAlign: "right" })
16059
+ }
16060
+ ),
16061
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16062
+ DropdownMenuItem,
16063
+ {
16064
+ icon: import_lucide_react36.AlignJustify,
16065
+ label: t("toolbar.justify"),
16066
+ onClick: () => editor.chain().focus().setTextAlign("justify").run(),
16067
+ active: editor.isActive({ textAlign: "justify" })
16068
+ }
16069
+ )
16070
+ ]
16071
+ }
16072
+ ),
16073
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarDivider, {}),
16074
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
16075
+ DropdownMenu,
16076
+ {
16077
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
16078
+ }, title: t("toolbar.bulletList"), children: [
16079
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.List, { className: "w-4 h-4" }),
16080
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
16081
+ ] }),
16082
+ children: [
16083
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16084
+ DropdownMenuItem,
16085
+ {
16086
+ icon: import_lucide_react36.List,
16087
+ label: t("toolbar.bulletList"),
16088
+ onClick: () => editor.chain().focus().toggleBulletList().run(),
16089
+ active: editor.isActive("bulletList"),
16090
+ shortcut: "Ctrl+Shift+8"
16091
+ }
16092
+ ),
16093
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16094
+ DropdownMenuItem,
16095
+ {
16096
+ icon: import_lucide_react36.ListOrdered,
16097
+ label: t("toolbar.orderedList"),
16098
+ onClick: () => editor.chain().focus().toggleOrderedList().run(),
16099
+ active: editor.isActive("orderedList"),
16100
+ shortcut: "Ctrl+Shift+7"
16101
+ }
16102
+ ),
16103
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16104
+ DropdownMenuItem,
16105
+ {
16106
+ icon: import_lucide_react36.ListTodo,
16107
+ label: t("toolbar.taskList"),
16108
+ onClick: () => editor.chain().focus().toggleTaskList().run(),
16109
+ active: editor.isActive("taskList"),
16110
+ shortcut: "Ctrl+Shift+9"
16111
+ }
16112
+ )
16113
+ ]
16114
+ }
16115
+ ),
16116
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
16117
+ DropdownMenu,
16118
+ {
16119
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
16120
+ }, title: t("toolbar.quote"), children: [
16121
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Quote, { className: "w-4 h-4" }),
16122
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
16123
+ ] }),
16124
+ children: [
16125
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16126
+ DropdownMenuItem,
16127
+ {
16128
+ icon: import_lucide_react36.Quote,
16129
+ label: t("toolbar.quote"),
16130
+ onClick: () => editor.chain().focus().toggleBlockquote().run(),
16131
+ active: editor.isActive("blockquote"),
16132
+ shortcut: "Ctrl+Shift+B"
16133
+ }
16134
+ ),
16135
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16136
+ DropdownMenuItem,
16137
+ {
16138
+ icon: import_lucide_react36.FileCode,
16139
+ label: t("toolbar.codeBlock"),
16140
+ onClick: () => editor.chain().focus().toggleCodeBlock().run(),
16141
+ active: editor.isActive("codeBlock"),
16142
+ shortcut: "Ctrl+Alt+C"
16143
+ }
16144
+ )
16145
+ ]
16146
+ }
16147
+ ),
16148
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16149
+ DropdownMenu,
16150
+ {
16151
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
16152
+ }, title: t("toolbar.image"), children: [
16153
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Image, { className: "w-4 h-4" }),
16154
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
16155
+ ] }),
16156
+ children: showImageInput ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16157
+ ImageInput,
16158
+ {
16159
+ onSubmit: (url, alt) => {
16160
+ editor.chain().focus().setImage({ src: url, alt }).run();
16161
+ setShowImageInput(false);
16162
+ },
16163
+ onCancel: () => setShowImageInput(false)
16164
+ }
16165
+ ) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DropdownMenuItem, { icon: import_lucide_react36.Link, label: t("imageInput.addFromUrl"), onClick: () => setShowImageInput(true) })
16166
+ }
16167
+ ),
16168
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
16169
+ DropdownMenu,
16170
+ {
16171
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(ToolbarButton, { onClick: () => {
16172
+ }, title: t("toolbar.table"), children: [
16173
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Table, { className: "w-4 h-4" }),
16174
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.ChevronDown, { className: "w-3 h-3" })
16175
+ ] }),
16176
+ children: [
16177
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DropdownMenuItem, { icon: import_lucide_react36.Table, label: t("tableMenu.insert3x3"), onClick: () => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run() }),
16178
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "my-1 border-t" }),
16179
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16180
+ DropdownMenuItem,
16181
+ {
16182
+ icon: import_lucide_react36.ArrowDown,
16183
+ label: t("tableMenu.addColumnBefore"),
16184
+ onClick: () => editor.chain().focus().addColumnBefore().run(),
16185
+ disabled: !editor.can().addColumnBefore()
16186
+ }
16187
+ ),
16188
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16189
+ DropdownMenuItem,
16190
+ {
16191
+ icon: import_lucide_react36.ArrowDown,
16192
+ label: t("tableMenu.addColumnAfter"),
16193
+ onClick: () => editor.chain().focus().addColumnAfter().run(),
16194
+ disabled: !editor.can().addColumnAfter()
16195
+ }
16196
+ ),
16197
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16198
+ DropdownMenuItem,
16199
+ {
16200
+ icon: import_lucide_react36.ArrowRight,
16201
+ label: t("tableMenu.addRowBefore"),
16202
+ onClick: () => editor.chain().focus().addRowBefore().run(),
16203
+ disabled: !editor.can().addRowBefore()
16204
+ }
16205
+ ),
16206
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16207
+ DropdownMenuItem,
16208
+ {
16209
+ icon: import_lucide_react36.ArrowRight,
16210
+ label: t("tableMenu.addRowAfter"),
16211
+ onClick: () => editor.chain().focus().addRowAfter().run(),
16212
+ disabled: !editor.can().addRowAfter()
16213
+ }
16214
+ ),
16215
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "my-1 border-t" }),
16216
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16217
+ DropdownMenuItem,
16218
+ {
16219
+ icon: import_lucide_react36.Trash2,
16220
+ label: t("tableMenu.deleteColumn"),
16221
+ onClick: () => editor.chain().focus().deleteColumn().run(),
16222
+ disabled: !editor.can().deleteColumn()
16223
+ }
16224
+ ),
16225
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(DropdownMenuItem, { icon: import_lucide_react36.Trash2, label: t("tableMenu.deleteRow"), onClick: () => editor.chain().focus().deleteRow().run(), disabled: !editor.can().deleteRow() }),
16226
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
16227
+ DropdownMenuItem,
16228
+ {
16229
+ icon: import_lucide_react36.Trash2,
16230
+ label: t("tableMenu.deleteTable"),
16231
+ onClick: () => editor.chain().focus().deleteTable().run(),
16232
+ disabled: !editor.can().deleteTable()
16233
+ }
16234
+ )
16235
+ ]
16236
+ }
16237
+ ),
16238
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarDivider, {}),
16239
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleSubscript().run(), active: editor.isActive("subscript"), title: t("toolbar.subscript"), children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Subscript, { className: "w-4 h-4" }) }),
16240
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleSuperscript().run(), active: editor.isActive("superscript"), title: t("toolbar.superscript"), children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Superscript, { className: "w-4 h-4" }) }),
16241
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarDivider, {}),
16242
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().undo().run(), disabled: !editor.can().undo(), title: t("toolbar.undo"), children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Undo, { className: "w-4 h-4" }) }),
16243
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().redo().run(), disabled: !editor.can().redo(), title: t("toolbar.redo"), children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_lucide_react36.Redo, { className: "w-4 h-4" }) })
16244
+ ] });
16245
+ };
16246
+
16247
+ // ../../components/ui/UEditor/menus.tsx
16248
+ var import_react43 = require("react");
16249
+ var import_react_dom9 = require("react-dom");
16250
+ var import_next_intl4 = require("next-intl");
16251
+ var import_lucide_react37 = require("lucide-react");
16252
+ var import_jsx_runtime72 = require("react/jsx-runtime");
16253
+ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
16254
+ const t = (0, import_next_intl4.useTranslations)("UEditor");
16255
+ const [selectedIndex, setSelectedIndex] = (0, import_react43.useState)(0);
16256
+ const menuRef = (0, import_react43.useRef)(null);
16257
+ const allCommands = (0, import_react43.useMemo)(
16258
+ () => [
16259
+ {
16260
+ icon: import_lucide_react37.Type,
16261
+ label: t("slashCommand.text"),
16262
+ description: t("slashCommand.textDesc"),
16263
+ action: () => editor.chain().focus().setParagraph().run()
16264
+ },
16265
+ {
16266
+ icon: import_lucide_react37.Heading1,
16267
+ label: t("slashCommand.heading1"),
16268
+ description: t("slashCommand.heading1Desc"),
16269
+ action: () => editor.chain().focus().toggleHeading({ level: 1 }).run()
16270
+ },
16271
+ {
16272
+ icon: import_lucide_react37.Heading2,
16273
+ label: t("slashCommand.heading2"),
16274
+ description: t("slashCommand.heading2Desc"),
16275
+ action: () => editor.chain().focus().toggleHeading({ level: 2 }).run()
16276
+ },
16277
+ {
16278
+ icon: import_lucide_react37.Heading3,
16279
+ label: t("slashCommand.heading3"),
16280
+ description: t("slashCommand.heading3Desc"),
16281
+ action: () => editor.chain().focus().toggleHeading({ level: 3 }).run()
16282
+ },
16283
+ {
16284
+ icon: import_lucide_react37.List,
16285
+ label: t("slashCommand.bulletList"),
16286
+ description: t("slashCommand.bulletListDesc"),
16287
+ action: () => editor.chain().focus().toggleBulletList().run()
16288
+ },
16289
+ {
16290
+ icon: import_lucide_react37.ListOrdered,
16291
+ label: t("slashCommand.orderedList"),
16292
+ description: t("slashCommand.orderedListDesc"),
16293
+ action: () => editor.chain().focus().toggleOrderedList().run()
16294
+ },
16295
+ {
16296
+ icon: import_lucide_react37.ListTodo,
16297
+ label: t("slashCommand.todoList"),
16298
+ description: t("slashCommand.todoListDesc"),
16299
+ action: () => editor.chain().focus().toggleTaskList().run()
16300
+ },
16301
+ {
16302
+ icon: import_lucide_react37.Quote,
16303
+ label: t("slashCommand.quote"),
16304
+ description: t("slashCommand.quoteDesc"),
16305
+ action: () => editor.chain().focus().toggleBlockquote().run()
16306
+ },
16307
+ {
16308
+ icon: import_lucide_react37.FileCode,
16309
+ label: t("slashCommand.codeBlock"),
16310
+ description: t("slashCommand.codeBlockDesc"),
16311
+ action: () => editor.chain().focus().toggleCodeBlock().run()
16312
+ },
16313
+ {
16314
+ icon: import_lucide_react37.Minus,
16315
+ label: t("slashCommand.divider"),
16316
+ description: t("slashCommand.dividerDesc"),
16317
+ action: () => editor.chain().focus().setHorizontalRule().run()
16318
+ },
16319
+ {
16320
+ icon: import_lucide_react37.Table,
16321
+ label: t("slashCommand.table"),
16322
+ description: t("slashCommand.tableDesc"),
16323
+ action: () => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
16324
+ }
16325
+ ],
16326
+ [editor, t]
16327
+ );
16328
+ const commands = (0, import_react43.useMemo)(() => {
16329
+ if (!filterText) return allCommands;
16330
+ const lowerFilter = filterText.toLowerCase();
16331
+ return allCommands.filter((cmd) => cmd.label.toLowerCase().includes(lowerFilter) || cmd.description.toLowerCase().includes(lowerFilter));
16332
+ }, [allCommands, filterText]);
16333
+ (0, import_react43.useEffect)(() => {
16334
+ setSelectedIndex(0);
16335
+ }, [filterText]);
16336
+ (0, import_react43.useEffect)(() => {
16337
+ const selectedElement = menuRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
16338
+ selectedElement?.scrollIntoView({ block: "nearest" });
16339
+ }, [selectedIndex]);
16340
+ const selectCommand = (0, import_react43.useCallback)(
16341
+ (index) => {
16342
+ const command = commands[index];
16343
+ if (command) {
16344
+ command.action();
16345
+ onClose();
16346
+ }
16347
+ },
16348
+ [commands, onClose]
16349
+ );
16350
+ (0, import_react43.useEffect)(() => {
16351
+ const handleKeyDown = (e) => {
16352
+ if (commands.length === 0) return;
16353
+ if (e.key === "ArrowDown") {
16354
+ e.preventDefault();
16355
+ setSelectedIndex((prev) => (prev + 1) % commands.length);
16356
+ } else if (e.key === "ArrowUp") {
16357
+ e.preventDefault();
16358
+ setSelectedIndex((prev) => (prev - 1 + commands.length) % commands.length);
16359
+ } else if (e.key === "Enter") {
16360
+ e.preventDefault();
16361
+ selectCommand(selectedIndex);
16362
+ } else if (e.key === "Escape") {
16363
+ e.preventDefault();
16364
+ onClose();
16365
+ }
16366
+ };
16367
+ document.addEventListener("keydown", handleKeyDown);
16368
+ return () => document.removeEventListener("keydown", handleKeyDown);
16369
+ }, [commands, selectedIndex, selectCommand, onClose]);
16370
+ if (commands.length === 0) {
16371
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-72 p-4 text-center text-muted-foreground text-sm", children: t("slashCommand.noResults") });
16372
+ }
16373
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { ref: menuRef, className: "w-72 max-h-80 overflow-y-auto", children: [
16374
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("slashCommand.basicBlocks") }) }),
16375
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "p-1", children: commands.map((cmd, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
16376
+ "button",
16377
+ {
16378
+ type: "button",
16379
+ "data-index": index,
16380
+ onMouseDown: (e) => e.preventDefault(),
16381
+ onClick: () => selectCommand(index),
16382
+ onMouseEnter: () => setSelectedIndex(index),
16383
+ className: cn(
16384
+ "flex items-center w-full px-3 py-2.5 rounded-lg transition-colors group",
16385
+ selectedIndex === index ? "bg-accent" : "hover:bg-accent/50"
16386
+ ),
16387
+ children: [
16388
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16389
+ "div",
16390
+ {
16391
+ className: cn(
16392
+ "flex items-center justify-center w-10 h-10 rounded-lg mr-3 transition-colors",
16393
+ selectedIndex === index ? "bg-primary/10" : "bg-muted/50 group-hover:bg-muted"
16394
+ ),
16395
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(cmd.icon, { className: cn("w-5 h-5", selectedIndex === index ? "text-primary" : "text-muted-foreground") })
16396
+ }
16397
+ ),
16398
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "text-left", children: [
16399
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: cn("text-sm font-medium", selectedIndex === index && "text-primary"), children: cmd.label }),
16400
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "text-xs text-muted-foreground", children: cmd.description })
16401
+ ] })
16402
+ ]
16403
+ },
16404
+ cmd.label
16405
+ )) })
16406
+ ] });
16407
+ };
16408
+ var FloatingMenuContent = ({ editor }) => {
16409
+ const t = (0, import_next_intl4.useTranslations)("UEditor");
16410
+ const [showCommands, setShowCommands] = (0, import_react43.useState)(false);
16411
+ if (showCommands) {
16412
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
16413
+ }
16414
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
16415
+ "button",
16416
+ {
16417
+ type: "button",
16418
+ onClick: () => setShowCommands(true),
16419
+ className: "flex items-center gap-1 px-2 py-1.5 rounded-lg hover:bg-accent transition-all group",
16420
+ children: [
16421
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Plus, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
16422
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
16423
+ ]
16424
+ }
16425
+ );
16426
+ };
16427
+ var BubbleMenuContent = ({ editor }) => {
16428
+ const t = (0, import_next_intl4.useTranslations)("UEditor");
16429
+ const { textColors, highlightColors } = useEditorColors();
16430
+ const [showLinkInput, setShowLinkInput] = (0, import_react43.useState)(false);
16431
+ const [showEditorColorPalette, setShowEditorColorPalette] = (0, import_react43.useState)(false);
16432
+ if (showLinkInput) {
16433
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16434
+ LinkInput,
16435
+ {
16436
+ initialUrl: editor.getAttributes("link").href || "",
16437
+ onSubmit: (url) => {
16438
+ editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
16439
+ },
16440
+ onCancel: () => setShowLinkInput(false)
16441
+ }
16442
+ );
16443
+ }
16444
+ if (showEditorColorPalette) {
16445
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "w-48", children: [
16446
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16447
+ EditorColorPalette,
16448
+ {
16449
+ colors: textColors,
16450
+ currentColor: editor.getAttributes("textStyle").color || "inherit",
16451
+ onSelect: (color) => {
16452
+ if (color === "inherit") {
16453
+ editor.chain().focus().unsetColor().run();
16454
+ } else {
16455
+ editor.chain().focus().setColor(color).run();
16456
+ }
16457
+ },
16458
+ label: t("colors.textColor")
16459
+ }
16460
+ ),
16461
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "border-t my-1" }),
16462
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16463
+ EditorColorPalette,
16464
+ {
16465
+ colors: highlightColors,
16466
+ currentColor: editor.getAttributes("highlight").color || "",
16467
+ onSelect: (color) => {
16468
+ if (color === "") {
16469
+ editor.chain().focus().unsetHighlight().run();
16470
+ } else {
16471
+ editor.chain().focus().toggleHighlight({ color }).run();
16472
+ }
16473
+ },
16474
+ label: t("colors.highlight")
16475
+ }
16476
+ ),
16477
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "p-2 border-t", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16478
+ "button",
16479
+ {
16480
+ type: "button",
16481
+ onClick: () => setShowEditorColorPalette(false),
16482
+ className: "w-full py-1.5 text-sm rounded-lg hover:bg-muted transition-colors",
16483
+ children: t("colors.done")
16484
+ }
16485
+ ) })
16486
+ ] });
16487
+ }
16488
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex items-center gap-0.5 p-1", children: [
16489
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Bold, { className: "w-4 h-4" }) }),
16490
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Italic, { className: "w-4 h-4" }) }),
16491
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16492
+ ToolbarButton,
16493
+ {
16494
+ onClick: () => editor.chain().focus().toggleUnderline().run(),
16495
+ active: editor.isActive("underline"),
16496
+ title: t("toolbar.underline"),
16497
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Underline, { className: "w-4 h-4" })
16498
+ }
16499
+ ),
16500
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Strikethrough, { className: "w-4 h-4" }) }),
16501
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Code, { className: "w-4 h-4" }) }),
16502
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
16503
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ToolbarButton, { onClick: () => setShowLinkInput(true), active: editor.isActive("link"), title: t("toolbar.link"), children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Link, { className: "w-4 h-4" }) }),
16504
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ToolbarButton, { onClick: () => setShowEditorColorPalette(true), title: t("colors.textColor"), children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Palette, { className: "w-4 h-4" }) }),
16505
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
16506
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16507
+ ToolbarButton,
16508
+ {
16509
+ onClick: () => editor.chain().focus().toggleSubscript().run(),
16510
+ active: editor.isActive("subscript"),
16511
+ title: t("toolbar.subscript"),
16512
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Subscript, { className: "w-4 h-4" })
16513
+ }
16514
+ ),
16515
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16516
+ ToolbarButton,
16517
+ {
16518
+ onClick: () => editor.chain().focus().toggleSuperscript().run(),
16519
+ active: editor.isActive("superscript"),
16520
+ title: t("toolbar.superscript"),
16521
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react37.Superscript, { className: "w-4 h-4" })
16522
+ }
16523
+ )
16524
+ ] });
16525
+ };
16526
+ var CustomBubbleMenu = ({ editor }) => {
16527
+ const [isVisible, setIsVisible] = (0, import_react43.useState)(false);
16528
+ const [position, setPosition] = (0, import_react43.useState)({ top: 0, left: 0 });
16529
+ const menuRef = (0, import_react43.useRef)(null);
16530
+ (0, import_react43.useEffect)(() => {
16531
+ const updatePosition = () => {
16532
+ const { state, view } = editor;
16533
+ const { from, to, empty } = state.selection;
16534
+ if (empty || !view.hasFocus()) {
16535
+ setIsVisible(false);
16536
+ return;
16537
+ }
16538
+ const start = view.coordsAtPos(from);
16539
+ const end = view.coordsAtPos(to);
16540
+ const left = (start.left + end.left) / 2;
16541
+ const top = start.top - 10;
16542
+ setPosition({ top, left });
16543
+ setIsVisible(true);
16544
+ };
16545
+ const handleBlur = () => setIsVisible(false);
16546
+ editor.on("selectionUpdate", updatePosition);
16547
+ editor.on("focus", updatePosition);
16548
+ editor.on("blur", handleBlur);
16549
+ return () => {
16550
+ editor.off("selectionUpdate", updatePosition);
16551
+ editor.off("focus", updatePosition);
16552
+ editor.off("blur", handleBlur);
16553
+ };
16554
+ }, [editor]);
16555
+ if (!isVisible) return null;
16556
+ return (0, import_react_dom9.createPortal)(
16557
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16558
+ "div",
16559
+ {
16560
+ ref: menuRef,
16561
+ className: "fixed z-50 flex rounded-2xl border border-border bg-card text-card-foreground shadow-lg backdrop-blur-sm overflow-hidden animate-in fade-in-0 zoom-in-95",
16562
+ style: {
16563
+ top: `${position.top}px`,
16564
+ left: `${position.left}px`,
16565
+ transform: "translate(-50%, -100%)"
16566
+ },
16567
+ onMouseDown: (e) => e.preventDefault(),
16568
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(BubbleMenuContent, { editor })
16569
+ }
16570
+ ),
16571
+ document.body
16572
+ );
16573
+ };
16574
+ var CustomFloatingMenu = ({ editor }) => {
16575
+ const [isVisible, setIsVisible] = (0, import_react43.useState)(false);
16576
+ const [position, setPosition] = (0, import_react43.useState)({ top: 0, left: 0 });
16577
+ (0, import_react43.useEffect)(() => {
16578
+ const updatePosition = () => {
16579
+ const { state, view } = editor;
16580
+ const { $from, empty } = state.selection;
16581
+ const isEmptyTextBlock = $from.parent.isTextblock && $from.parent.type.name === "paragraph" && $from.parent.textContent === "" && empty;
16582
+ if (!isEmptyTextBlock || !view.hasFocus()) {
16583
+ setIsVisible(false);
16584
+ return;
16585
+ }
16586
+ const coords = view.coordsAtPos($from.pos);
16587
+ setPosition({ top: coords.top - 10, left: coords.left });
16588
+ setIsVisible(true);
16589
+ };
16590
+ const handleBlur = () => setIsVisible(false);
16591
+ editor.on("selectionUpdate", updatePosition);
16592
+ editor.on("focus", updatePosition);
16593
+ editor.on("blur", handleBlur);
16594
+ editor.on("update", updatePosition);
16595
+ return () => {
16596
+ editor.off("selectionUpdate", updatePosition);
16597
+ editor.off("focus", updatePosition);
16598
+ editor.off("blur", handleBlur);
16599
+ editor.off("update", updatePosition);
16600
+ };
16601
+ }, [editor]);
16602
+ if (!isVisible) return null;
16603
+ return (0, import_react_dom9.createPortal)(
16604
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
16605
+ "div",
16606
+ {
16607
+ className: "fixed z-50 rounded-2xl border border-border bg-card text-card-foreground shadow-lg backdrop-blur-sm overflow-hidden animate-in fade-in-0 slide-in-from-bottom-2",
16608
+ style: {
16609
+ top: `${position.top}px`,
16610
+ left: `${position.left}px`,
16611
+ transform: "translate(-50%, -100%)"
16612
+ },
16613
+ onMouseDown: (e) => e.preventDefault(),
16614
+ children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(FloatingMenuContent, { editor })
16615
+ }
16616
+ ),
16617
+ document.body
16618
+ );
16619
+ };
16620
+
16621
+ // ../../components/ui/UEditor/CharacterCount.tsx
16622
+ var import_next_intl5 = require("next-intl");
16623
+ var import_jsx_runtime73 = require("react/jsx-runtime");
16624
+ var CharacterCountDisplay = ({ editor, maxCharacters }) => {
16625
+ const t = (0, import_next_intl5.useTranslations)("UEditor");
16626
+ const storage = editor.storage;
16627
+ const characterCount = storage.characterCount?.characters?.() ?? 0;
16628
+ const wordCount = storage.characterCount?.words?.() ?? 0;
16629
+ const percentage = maxCharacters ? Math.round(characterCount / maxCharacters * 100) : 0;
16630
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "flex items-center gap-3 px-3 py-2 text-xs text-muted-foreground border-t bg-muted/20", children: [
16631
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { children: [
16632
+ wordCount,
16633
+ " ",
16634
+ t("words")
16635
+ ] }),
16636
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { children: [
16637
+ characterCount,
16638
+ " ",
16639
+ t("characters")
16640
+ ] }),
16641
+ maxCharacters && /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: cn(percentage > 90 && "text-destructive", percentage > 100 && "font-bold"), children: [
16642
+ characterCount,
16643
+ "/",
16644
+ maxCharacters
16645
+ ] })
16646
+ ] });
16647
+ };
16648
+
16649
+ // ../../components/ui/UEditor/UEditor.tsx
16650
+ var import_jsx_runtime74 = require("react/jsx-runtime");
16651
+ var UEditor = ({
16652
+ content = "",
16653
+ onChange,
16654
+ onHtmlChange,
16655
+ onJsonChange,
16656
+ placeholder,
16657
+ className,
16658
+ editable = true,
16659
+ autofocus = false,
16660
+ showToolbar = true,
16661
+ showBubbleMenu = true,
16662
+ showFloatingMenu = false,
16663
+ showCharacterCount = true,
16664
+ maxCharacters,
16665
+ minHeight = "200px",
16666
+ maxHeight = "auto",
16667
+ variant = "default"
16668
+ }) => {
16669
+ const t = (0, import_next_intl6.useTranslations)("UEditor");
16670
+ const effectivePlaceholder = placeholder ?? t("placeholder");
16671
+ const extensions = (0, import_react44.useMemo)(
16672
+ () => buildUEditorExtensions({ placeholder: effectivePlaceholder, maxCharacters }),
16673
+ [effectivePlaceholder, maxCharacters]
16674
+ );
16675
+ const editor = (0, import_react45.useEditor)({
16676
+ immediatelyRender: false,
16677
+ extensions,
16678
+ content,
16679
+ editable,
16680
+ autofocus,
16681
+ editorProps: {
16682
+ handleDOMEvents: {
16683
+ keydown: (_view, event) => {
16684
+ if (!(event instanceof KeyboardEvent)) return false;
16685
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
16686
+ event.stopPropagation();
16687
+ }
16688
+ return false;
16689
+ }
16690
+ },
16691
+ attributes: {
16692
+ class: cn(
16693
+ "prose prose-sm sm:prose dark:prose-invert max-w-none",
16694
+ "focus:outline-none",
16695
+ "px-4 py-4",
16696
+ "[&_.is-editor-empty]:before:content-[attr(data-placeholder)]",
16697
+ "[&_.is-editor-empty]:before:text-muted-foreground/50",
16698
+ "[&_.is-editor-empty]:before:float-left",
16699
+ "[&_.is-editor-empty]:before:pointer-events-none",
16700
+ "[&_.is-editor-empty]:before:h-0",
16701
+ "[&_ul[data-type='taskList']]:list-none",
16702
+ "[&_ul[data-type='taskList']]:pl-0",
16703
+ "[&_ul[data-type='taskList']_li]:flex",
16704
+ "[&_ul[data-type='taskList']_li]:items-start",
16705
+ "[&_ul[data-type='taskList']_li]:gap-2",
16706
+ "[&_ul[data-type='taskList']_li>label]:mt-0.5",
16707
+ "[&_ul[data-type='taskList']_li>label>input]:w-4",
16708
+ "[&_ul[data-type='taskList']_li>label>input]:h-4",
16709
+ "[&_ul[data-type='taskList']_li>label>input]:rounded",
16710
+ "[&_ul[data-type='taskList']_li>label>input]:border-2",
16711
+ "[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
16712
+ "[&_ul[data-type='taskList']_li>label>input]:accent-primary",
16713
+ "[&_pre]:!bg-[#1e1e1e]",
16714
+ "[&_pre]:!text-[#d4d4d4]",
16715
+ "[&_pre_code]:!bg-transparent",
16716
+ "[&_hr]:border-t-2",
16717
+ "[&_hr]:border-primary/30",
16718
+ "[&_hr]:my-8",
16719
+ "[&_h1]:text-3xl",
16720
+ "[&_h1]:font-bold",
16721
+ "[&_h1]:mt-6",
16722
+ "[&_h1]:mb-4",
16723
+ "[&_h1]:text-foreground",
16724
+ "[&_h2]:text-2xl",
16725
+ "[&_h2]:font-semibold",
16726
+ "[&_h2]:mt-5",
16727
+ "[&_h2]:mb-3",
16728
+ "[&_h2]:text-foreground",
16729
+ "[&_h3]:text-xl",
16730
+ "[&_h3]:font-semibold",
16731
+ "[&_h3]:mt-4",
16732
+ "[&_h3]:mb-2",
16733
+ "[&_h3]:text-foreground",
16734
+ "[&_ul:not([data-type='taskList'])]:list-disc",
16735
+ "[&_ul:not([data-type='taskList'])]:pl-6",
16736
+ "[&_ul:not([data-type='taskList'])]:my-3",
16737
+ "[&_ol]:list-decimal",
16738
+ "[&_ol]:pl-6",
16739
+ "[&_ol]:my-3",
16740
+ "[&_li]:my-1",
16741
+ "[&_li]:pl-1",
16742
+ "[&_li_p]:my-0",
16743
+ "[&_blockquote]:border-l-4",
16744
+ "[&_blockquote]:border-primary",
16745
+ "[&_blockquote]:pl-4",
16746
+ "[&_blockquote]:py-2",
16747
+ "[&_blockquote]:my-4",
16748
+ "[&_blockquote]:bg-muted/30",
16749
+ "[&_blockquote]:rounded-r-lg",
16750
+ "[&_blockquote]:italic",
16751
+ "[&_blockquote]:text-muted-foreground",
16752
+ "[&_blockquote_p]:my-0"
16753
+ )
16754
+ }
16755
+ },
16756
+ onUpdate: ({ editor: editor2 }) => {
16757
+ const html = editor2.getHTML();
16758
+ onChange?.(html);
16759
+ onHtmlChange?.(html);
16760
+ onJsonChange?.(editor2.getJSON());
16761
+ }
16762
+ });
16763
+ (0, import_react44.useEffect)(() => {
16764
+ if (editor && content !== editor.getHTML()) {
16765
+ if (editor.isEmpty && content) {
16766
+ editor.commands.setContent(content);
16767
+ }
16768
+ }
16769
+ }, [content, editor]);
16770
+ if (!editor) {
16771
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
16772
+ "div",
16773
+ {
16774
+ className: cn("w-full rounded-lg border bg-background flex items-center justify-center text-muted-foreground", className),
16775
+ style: { minHeight },
16776
+ children: t("loading")
16777
+ }
16778
+ );
16779
+ }
16780
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
16781
+ "div",
16782
+ {
16783
+ className: cn(
16784
+ "group relative flex flex-col rounded-2xl md:rounded-3xl border border-border bg-card text-card-foreground overflow-hidden",
16785
+ "transition-[transform,box-shadow,border-color,background-color] duration-300 ease-soft",
16786
+ "shadow-sm focus-within:shadow-md focus-within:border-primary/15",
16787
+ "backdrop-blur-sm",
16788
+ variant === "notion" && "hover:shadow-md",
16789
+ className
16790
+ ),
16791
+ children: [
16792
+ editable && showToolbar && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(EditorToolbar, { editor, variant }),
16793
+ editable && showBubbleMenu && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(CustomBubbleMenu, { editor }),
16794
+ editable && showFloatingMenu && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(CustomFloatingMenu, { editor }),
16795
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
16796
+ import_react45.EditorContent,
16797
+ {
16798
+ editor,
16799
+ className: "flex-1 overflow-y-auto",
16800
+ style: {
16801
+ minHeight,
16802
+ maxHeight
16803
+ }
16804
+ }
16805
+ ),
16806
+ showCharacterCount && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(CharacterCountDisplay, { editor, maxCharacters })
16807
+ ]
16808
+ }
16809
+ );
16810
+ };
16811
+ var UEditor_default = UEditor;
16812
+
15307
16813
  // src/index.ts
15308
16814
  var underverseMessages = { en: en_default, vi: vi_default, ko: ko_default, ja: ja_default };
15309
16815
  function getUnderverseMessages(locale = "en") {
@@ -15440,6 +16946,7 @@ function getUnderverseMessages(locale = "en") {
15440
16946
  ToastProvider,
15441
16947
  Tooltip,
15442
16948
  TranslationProvider,
16949
+ UEditor,
15443
16950
  UnderverseProvider,
15444
16951
  VARIANT_STYLES_ALERT,
15445
16952
  VARIANT_STYLES_BTN,