"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import {
  AlignCenter,
  AlignJustify,
  AlignLeft,
  AlignRight,
  AtSign,
  Bold,
  ChevronDown,
  Code,
  FileCode,
  HelpCircle,
  Image as ImageIcon,
  Italic,
  Link,
  List,
  ListChecks,
  ListOrdered,
  Maximize2,
  MessageCircle,
  Minus,
  MoreVertical,
  Quote,
  Strikethrough,
  Table as TableIcon,
  Underline
} from "lucide-react";
import { cva } from "class-variance-authority";
import { cn } from "@open-mercato/shared/lib/utils";
import {
  sanitizeHtmlRichText,
  sanitizeRichTextHref,
  sanitizeRichTextPasteContent
} from "@open-mercato/ui/backend/utils/richTextSanitizer";
import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger
} from "./tooltip.js";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle
} from "./dialog.js";
import { Input } from "./input.js";
import { Button } from "./button.js";
const RICH_EDITOR_COLOR_PALETTE = {
  gray: "#7b7b7b",
  black: "#171717",
  white: "#ffffff",
  blue: "#6366f1",
  orange: "#f59e0b",
  red: "#ef4444",
  green: "#22c55e",
  yellow: "#f6b51e",
  purple: "#7d52f4",
  sky: "#47c2ff",
  pink: "#fb4ba3",
  teal: "#22d3bb"
};
const COLOR_KEYS = [
  "gray",
  "black",
  "white",
  "blue",
  "orange",
  "red",
  "green",
  "yellow",
  "purple",
  "sky",
  "pink",
  "teal"
];
const COLOR_LABELS_EN = {
  gray: "Gray",
  black: "Black",
  white: "White",
  blue: "Blue",
  orange: "Orange",
  red: "Red",
  green: "Green",
  yellow: "Yellow",
  purple: "Purple",
  sky: "Sky",
  pink: "Pink",
  teal: "Teal"
};
const ALIGN_ICONS = {
  left: AlignLeft,
  center: AlignCenter,
  right: AlignRight,
  justify: AlignJustify
};
const FONT_SIZE_OPTIONS = ["12px", "14px", "16px", "18px", "20px", "24px"];
const EMPTY_SELECTION_STATE = {
  bold: false,
  italic: false,
  underline: false,
  strikethrough: false,
  unorderedList: false,
  orderedList: false,
  blockquote: false,
  code: false,
  heading: "",
  align: "left"
};
const RichEditorContext = React.createContext(null);
function useRichEditorContext(component) {
  const ctx = React.useContext(RichEditorContext);
  if (!ctx) {
    throw new Error(`${component} must be rendered inside <RichEditor>`);
  }
  return ctx;
}
const DEFAULT_LABELS = {
  bold: "Bold",
  italic: "Italic",
  underline: "Underline",
  strikethrough: "Strikethrough",
  unorderedList: "Bullet list",
  orderedList: "Numbered list",
  checklist: "Checklist",
  blockquote: "Quote",
  code: "Code",
  inlineCode: "Inline code",
  codeBlock: "Code block",
  horizontalRule: "Horizontal rule",
  image: "Image",
  imageUrlPrompt: "Enter image URL",
  table: "Table",
  heading: "Header",
  heading1: "Heading 1",
  heading2: "Heading 2",
  heading3: "Heading 3",
  paragraph: "Paragraph",
  link: "Link",
  linkUrlPrompt: "Enter URL",
  color: "Text color",
  textColor: "Color",
  fontSize: "Font size",
  align: "Align",
  alignLeft: "Align left",
  alignCenter: "Align center",
  alignRight: "Align right",
  alignJustify: "Justify",
  comment: "Add comment",
  mention: "Mention",
  more: "More",
  help: "Help",
  fullscreen: "Toggle fullscreen",
  placeholder: "Placeholder text...",
  colors: COLOR_LABELS_EN
};
function deriveSelectionState() {
  if (typeof document === "undefined" || !document.queryCommandState) {
    return EMPTY_SELECTION_STATE;
  }
  try {
    const block = document.queryCommandValue?.("formatBlock") ?? "";
    const lower = String(block).toLowerCase().replace(/[<>]/g, "");
    const heading = lower === "h1" || lower === "h2" || lower === "h3" ? lower : "";
    const align = document.queryCommandState("justifyCenter") ? "center" : document.queryCommandState("justifyRight") ? "right" : document.queryCommandState("justifyFull") ? "justify" : "left";
    return {
      bold: document.queryCommandState("bold"),
      italic: document.queryCommandState("italic"),
      underline: document.queryCommandState("underline"),
      strikethrough: document.queryCommandState("strikeThrough"),
      unorderedList: document.queryCommandState("insertUnorderedList"),
      orderedList: document.queryCommandState("insertOrderedList"),
      blockquote: lower === "blockquote",
      code: lower === "pre",
      heading,
      align
    };
  } catch {
    return EMPTY_SELECTION_STATE;
  }
}
const RichEditor = React.memo(
  function RichEditor2({
    value = "",
    onChange,
    variant = "standard",
    placeholder,
    minRows = 4,
    disabled = false,
    className,
    contentClassName,
    labels: labelsProp,
    onComment,
    onMention,
    moreMenu,
    onFullscreen,
    onImageInsert,
    maxLength,
    children,
    id,
    name,
    "aria-invalid": ariaInvalid
  }) {
    const labels = React.useMemo(
      () => ({
        ...DEFAULT_LABELS,
        ...labelsProp ?? {},
        colors: { ...DEFAULT_LABELS.colors, ...labelsProp?.colors ?? {} }
      }),
      [labelsProp]
    );
    const editorRef = React.useRef(null);
    const applyingExternal = React.useRef(false);
    const typingRef = React.useRef(false);
    const savedSelectionRef = React.useRef(null);
    const [selection, setSelection] = React.useState(EMPTY_SELECTION_STATE);
    const [promptDialog, setPromptDialog] = React.useState(null);
    React.useEffect(() => {
      const el = editorRef.current;
      if (!el) return;
      const sanitizedValue = sanitizeHtmlRichText(value);
      if (!typingRef.current && el.innerHTML !== sanitizedValue) {
        applyingExternal.current = true;
        el.innerHTML = sanitizedValue;
        requestAnimationFrame(() => {
          applyingExternal.current = false;
        });
      }
    }, [value]);
    const refreshSelectionState = React.useCallback(() => {
      setSelection(deriveSelectionState());
    }, []);
    const exec = React.useCallback(
      (command, arg) => {
        const el = editorRef.current;
        if (!el || disabled) return;
        el.focus();
        try {
          document.execCommand("styleWithCSS", false, "true");
        } catch {
        }
        try {
          document.execCommand(command, false, arg);
        } catch {
        }
        refreshSelectionState();
      },
      [disabled, refreshSelectionState]
    );
    const requestUrlPrompt = React.useCallback(
      (request) => {
        if (typeof window !== "undefined") {
          const sel = window.getSelection();
          if (sel && sel.rangeCount > 0 && editorRef.current?.contains(sel.anchorNode)) {
            savedSelectionRef.current = sel.getRangeAt(0).cloneRange();
          } else {
            savedSelectionRef.current = null;
          }
        }
        setPromptDialog({ ...request, value: "" });
      },
      []
    );
    const ctx = React.useMemo(
      () => ({ exec, selection, disabled, requestUrlPrompt }),
      [exec, selection, disabled, requestUrlPrompt]
    );
    React.useEffect(() => {
      if (typeof document === "undefined") return;
      const onSelectionChange = () => {
        if (!editorRef.current) return;
        const sel = window.getSelection();
        if (!sel || !sel.anchorNode) return;
        if (!editorRef.current.contains(sel.anchorNode)) return;
        refreshSelectionState();
      };
      document.addEventListener("selectionchange", onSelectionChange);
      return () => {
        document.removeEventListener("selectionchange", onSelectionChange);
      };
    }, [refreshSelectionState]);
    const onKeyDown = React.useCallback(
      (e) => {
        const isMod = e.metaKey || e.ctrlKey;
        if (!isMod) return;
        const k = e.key.toLowerCase();
        if (k === "b") {
          e.preventDefault();
          exec("bold");
        } else if (k === "i") {
          e.preventDefault();
          exec("italic");
        } else if (k === "u") {
          e.preventDefault();
          exec("underline");
        }
      },
      [exec]
    );
    const onPaste = React.useCallback(
      (e) => {
        const html = e.clipboardData.getData("text/html");
        const text = e.clipboardData.getData("text/plain");
        const sanitizedPaste = sanitizeRichTextPasteContent(html, text);
        if (!sanitizedPaste) return;
        e.preventDefault();
        exec(sanitizedPaste.command, sanitizedPaste.value);
      },
      [exec]
    );
    const onBlur = React.useCallback(() => {
      const el = editorRef.current;
      if (!el) return;
      typingRef.current = false;
      const sanitized = sanitizeHtmlRichText(el.innerHTML);
      if (el.innerHTML !== sanitized) {
        applyingExternal.current = true;
        el.innerHTML = sanitized;
        requestAnimationFrame(() => {
          applyingExternal.current = false;
        });
      }
      onChange(sanitized);
    }, [onChange]);
    const presetItems = usePresetToolbarItems({
      variant,
      labels,
      onComment,
      onMention,
      onFullscreen,
      onImageInsert,
      exec,
      selection,
      requestUrlPrompt
    });
    const plaintextLength = React.useMemo(() => {
      if (!maxLength) return 0;
      if (typeof document === "undefined") return 0;
      const tmp = document.createElement("div");
      tmp.innerHTML = sanitizeHtmlRichText(value);
      return (tmp.textContent ?? "").length;
    }, [value, maxLength]);
    return /* @__PURE__ */ jsx(RichEditorContext.Provider, { value: ctx, children: /* @__PURE__ */ jsxs(TooltipProvider, { delayDuration: 400, children: [
      /* @__PURE__ */ jsx(
        "div",
        {
          className: cn("w-full space-y-2", disabled && "opacity-60", className),
          "data-slot": "rich-editor",
          "data-disabled": disabled ? "true" : "false",
          "aria-invalid": ariaInvalid,
          children: variant === "custom" ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
            /* @__PURE__ */ jsx(RichEditorAutoToolbar, { items: presetItems, labels, moreMenu }),
            /* @__PURE__ */ jsxs("div", { className: "relative", children: [
              /* @__PURE__ */ jsx(
                RichEditorContent,
                {
                  ref: editorRef,
                  placeholder: placeholder ?? labels.placeholder,
                  minRows,
                  disabled,
                  className: contentClassName,
                  onKeyDown,
                  onPaste,
                  onBlur,
                  onInput: () => {
                    if (!applyingExternal.current) typingRef.current = true;
                  },
                  id,
                  name
                }
              ),
              maxLength ? /* @__PURE__ */ jsxs(
                "span",
                {
                  className: cn(
                    "pointer-events-none absolute bottom-2 right-3 select-none text-xs leading-4 text-muted-foreground",
                    plaintextLength > maxLength && "text-destructive"
                  ),
                  "data-slot": "rich-editor-counter",
                  "aria-live": "polite",
                  children: [
                    plaintextLength,
                    "/",
                    maxLength
                  ]
                }
              ) : null
            ] })
          ] })
        }
      ),
      promptDialog !== null ? /* @__PURE__ */ jsx(
        Dialog,
        {
          open: true,
          onOpenChange: (open) => {
            if (!open) setPromptDialog(null);
          },
          children: /* @__PURE__ */ jsxs(
            DialogContent,
            {
              className: "sm:max-w-md",
              onKeyDown: (e) => {
                if (e.key === "Enter" && promptDialog) {
                  e.preventDefault();
                  const url = sanitizeRichTextHref(promptDialog.value);
                  const onConfirm = promptDialog.onConfirm;
                  setPromptDialog(null);
                  if (!url) return;
                  const el = editorRef.current;
                  const range = savedSelectionRef.current;
                  if (el) {
                    el.focus();
                    if (range) {
                      const sel = window.getSelection();
                      sel?.removeAllRanges();
                      sel?.addRange(range);
                    }
                  }
                  onConfirm(url);
                }
              },
              children: [
                /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: promptDialog?.title ?? "" }) }),
                /* @__PURE__ */ jsx(
                  Input,
                  {
                    autoFocus: true,
                    type: "url",
                    value: promptDialog?.value ?? "",
                    placeholder: promptDialog?.placeholder ?? "https://\u2026",
                    onChange: (e) => {
                      const next = e.target.value;
                      setPromptDialog((prev) => prev ? { ...prev, value: next } : prev);
                    }
                  }
                ),
                /* @__PURE__ */ jsxs(DialogFooter, { children: [
                  /* @__PURE__ */ jsx(
                    Button,
                    {
                      type: "button",
                      variant: "outline",
                      onClick: () => setPromptDialog(null),
                      children: "Cancel"
                    }
                  ),
                  /* @__PURE__ */ jsx(
                    Button,
                    {
                      type: "button",
                      onClick: () => {
                        if (!promptDialog) return;
                        const url = sanitizeRichTextHref(promptDialog.value);
                        const onConfirm = promptDialog.onConfirm;
                        setPromptDialog(null);
                        if (!url) return;
                        const el = editorRef.current;
                        const range = savedSelectionRef.current;
                        if (el) {
                          el.focus();
                          if (range) {
                            const sel = window.getSelection();
                            sel?.removeAllRanges();
                            sel?.addRange(range);
                          }
                        }
                        onConfirm(url);
                      },
                      children: "OK"
                    }
                  )
                ] })
              ]
            }
          )
        }
      ) : null
    ] }) });
  },
  (prev, next) => prev.value === next.value && prev.disabled === next.disabled && prev.variant === next.variant && prev.maxLength === next.maxLength
);
RichEditor.displayName = "RichEditor";
const RichEditorToolbar = React.forwardRef(
  ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
    "div",
    {
      ref,
      role: "toolbar",
      "aria-label": "Rich text formatting",
      className: cn(
        // Figma 166331:4006 reference: standalone card with rounded-8 + border + shadow-xs.
        // 2px outer padding, 2px gap between items.
        "flex w-fit max-w-full flex-wrap items-center gap-0.5 overflow-x-auto rounded-lg border border-border bg-card p-0.5 shadow-xs",
        className
      ),
      "data-slot": "rich-editor-toolbar",
      ...props,
      children
    }
  )
);
RichEditorToolbar.displayName = "RichEditorToolbar";
const richEditorItemVariants = cva(
  // Figma Rich Editor Items (166251 family): 28×h, rounded-6, bg-white default,
  // bg-weak-50 (= bg-muted token) on hover, on toggle-active (data-active=true,
  // e.g. Bold inside a bold selection), and on dropdown-open
  // (data-state=open from Radix PopoverTrigger). Text / icon colours move from
  // sub-600 (= text-muted-foreground, #5c5c5c) in the default state to
  // strong-950 (= text-foreground, #171717) in the active / open states per
  // Figma 166261:22214 / 166261:22217 reference cells.
  "group/rich-editor-item inline-flex h-7 shrink-0 items-center justify-center rounded-md bg-transparent text-sm font-medium leading-5 text-muted-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-40 data-[active=true]:bg-muted data-[active=true]:text-foreground data-[state=open]:bg-muted data-[state=open]:text-foreground",
  {
    variants: {
      type: {
        // Figma 166251:2698 — pl-[10px] pr-[4px] py-[4px], gap-[2px].
        text: "min-w-0 gap-0.5 pl-2.5 pr-1 py-1 tracking-[-0.084px] [&_svg]:size-4",
        // Figma 166251:2700 — square icon button p-[4px].
        icon: "aspect-square p-1 [&_svg]:size-4",
        // Figma 166251:3337 — icon + caret p-[4px] gap-[2px].
        dropdown: "gap-0.5 p-1 [&_svg]:size-4",
        // Figma 166331:4437 — color swatch + caret pl-[8px] pr-[4px] py-[4px].
        color: "gap-0.5 pl-2 pr-1 py-1 [&_svg]:size-4"
      }
    },
    defaultVariants: { type: "icon" }
  }
);
const RichEditorButton = React.forwardRef(
  ({ className, type, active, tooltipLabel, children, onMouseDown, ...props }, ref) => {
    const button = /* @__PURE__ */ jsx(
      "button",
      {
        ref,
        type: "button",
        onMouseDown: (e) => {
          e.preventDefault();
          onMouseDown?.(e);
        },
        "data-active": active ? "true" : "false",
        "aria-pressed": active,
        className: cn(richEditorItemVariants({ type }), className),
        ...props,
        children
      }
    );
    if (!tooltipLabel) return button;
    return /* @__PURE__ */ jsxs(Tooltip, { children: [
      /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: button }),
      /* @__PURE__ */ jsx(TooltipContent, { side: "top", sideOffset: 6, children: tooltipLabel })
    ] });
  }
);
RichEditorButton.displayName = "RichEditorButton";
const RichEditorIconButton = React.forwardRef(
  ({ icon, ariaLabel, command, commandArg, onActivate, active, onClick, ...props }, ref) => {
    const { exec, disabled } = useRichEditorContext("RichEditorIconButton");
    return /* @__PURE__ */ jsx(
      RichEditorButton,
      {
        ref,
        type: "icon",
        active,
        "aria-label": ariaLabel,
        disabled: disabled || props.disabled,
        onClick: (e) => {
          if (command) exec(command, commandArg);
          onActivate?.();
          onClick?.(e);
        },
        ...props,
        children: /* @__PURE__ */ jsx("span", { "data-slot": "rich-editor-item-icon", "aria-hidden": "true", children: icon })
      }
    );
  }
);
RichEditorIconButton.displayName = "RichEditorIconButton";
const RichEditorTextDropdown = React.forwardRef(
  ({ label, ariaLabel, menu, onActivate, ...props }, ref) => {
    const { disabled } = useRichEditorContext("RichEditorTextDropdown");
    const button = /* @__PURE__ */ jsxs(
      RichEditorButton,
      {
        ref,
        type: "text",
        "aria-label": ariaLabel,
        disabled: disabled || props.disabled,
        onClick: onActivate,
        ...props,
        children: [
          /* @__PURE__ */ jsx("span", { className: "truncate", children: label }),
          /* @__PURE__ */ jsx(ChevronDown, { className: "opacity-60 transition-transform group-data-[state=open]/rich-editor-item:rotate-180", "aria-hidden": "true" })
        ]
      }
    );
    if (!menu) return button;
    return /* @__PURE__ */ jsxs(Popover, { children: [
      /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: button }),
      /* @__PURE__ */ jsx(PopoverContent, { align: "start", sideOffset: 6, className: "w-44 p-1", children: menu })
    ] });
  }
);
RichEditorTextDropdown.displayName = "RichEditorTextDropdown";
const RichEditorDropdownButton = React.forwardRef(
  ({ icon, ariaLabel, menu, showChevron, ...props }, ref) => {
    const { disabled } = useRichEditorContext("RichEditorDropdownButton");
    return /* @__PURE__ */ jsxs(Popover, { children: [
      /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
        RichEditorButton,
        {
          ref,
          type: "dropdown",
          "aria-label": ariaLabel,
          disabled: disabled || props.disabled,
          ...props,
          children: [
            /* @__PURE__ */ jsx("span", { "data-slot": "rich-editor-item-icon", "aria-hidden": "true", children: icon }),
            showChevron === false ? null : /* @__PURE__ */ jsx(ChevronDown, { className: "opacity-60 transition-transform group-data-[state=open]/rich-editor-item:rotate-180", "aria-hidden": "true" })
          ]
        }
      ) }),
      /* @__PURE__ */ jsx(PopoverContent, { align: "start", sideOffset: 6, className: "w-44 p-1", children: menu })
    ] });
  }
);
RichEditorDropdownButton.displayName = "RichEditorDropdownButton";
const RichEditorColorButton = React.forwardRef(
  ({ colorValue, ariaLabel, command = "foreColor", onSelect, colorLabels, palette = COLOR_KEYS, ...props }, ref) => {
    const { exec, disabled } = useRichEditorContext("RichEditorColorButton");
    const [lastSelected, setLastSelected] = React.useState(null);
    const effectiveValue = colorValue ?? lastSelected;
    const swatchColor = effectiveValue ? RICH_EDITOR_COLOR_PALETTE[effectiveValue] : RICH_EDITOR_COLOR_PALETTE.blue;
    return /* @__PURE__ */ jsxs(Popover, { children: [
      /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
        RichEditorButton,
        {
          ref,
          type: "color",
          "aria-label": ariaLabel,
          disabled: disabled || props.disabled,
          ...props,
          children: [
            /* @__PURE__ */ jsx(
              "span",
              {
                className: "inline-block size-4 shrink-0 rounded-full border border-black/10",
                style: { backgroundColor: swatchColor },
                "data-slot": "rich-editor-color-swatch",
                "aria-hidden": "true"
              }
            ),
            /* @__PURE__ */ jsx(ChevronDown, { className: "opacity-60 transition-transform group-data-[state=open]/rich-editor-item:rotate-180", "aria-hidden": "true" })
          ]
        }
      ) }),
      /* @__PURE__ */ jsx(PopoverContent, { align: "start", sideOffset: 6, className: "w-36 p-1", children: /* @__PURE__ */ jsx(
        RichEditorColorPalette,
        {
          value: effectiveValue,
          labels: colorLabels,
          palette,
          onChange: (key) => {
            if (key) exec(command, RICH_EDITOR_COLOR_PALETTE[key]);
            setLastSelected(key);
            onSelect?.(key);
          }
        }
      ) })
    ] });
  }
);
RichEditorColorButton.displayName = "RichEditorColorButton";
function RichEditorColorPalette({ value, onChange, labels, palette, className }) {
  const resolvedLabels = { ...COLOR_LABELS_EN, ...labels ?? {} };
  const keys = palette && palette.length > 0 ? palette : COLOR_KEYS;
  return /* @__PURE__ */ jsx(
    "div",
    {
      className: cn("flex flex-col gap-0.5", className),
      "data-slot": "rich-editor-color-palette",
      role: "listbox",
      "aria-label": "Color palette",
      children: keys.map((key) => {
        const isActive = value === key;
        return /* @__PURE__ */ jsxs(
          "button",
          {
            type: "button",
            role: "option",
            "aria-selected": isActive,
            "aria-label": resolvedLabels[key],
            onMouseDown: (e) => e.preventDefault(),
            onClick: () => onChange?.(key),
            className: cn(
              "flex items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors hover:bg-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-ring/40",
              isActive && "font-medium text-foreground"
            ),
            "data-color-key": key,
            children: [
              /* @__PURE__ */ jsx(
                "span",
                {
                  className: "size-4 shrink-0 rounded-full border border-black/10",
                  style: { backgroundColor: RICH_EDITOR_COLOR_PALETTE[key] },
                  "aria-hidden": "true"
                }
              ),
              /* @__PURE__ */ jsx("span", { className: "truncate", children: resolvedLabels[key] })
            ]
          },
          key
        );
      })
    }
  );
}
const RichEditorMenuItem = React.forwardRef(
  ({ className, icon, children, destructive, onMouseDown, ...props }, ref) => /* @__PURE__ */ jsxs(
    "button",
    {
      ref,
      type: "button",
      role: "menuitem",
      onMouseDown: (e) => {
        e.preventDefault();
        onMouseDown?.(e);
      },
      className: cn(
        "flex w-full cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50",
        destructive && "text-destructive hover:bg-destructive/10",
        className
      ),
      "data-slot": "rich-editor-menu-item",
      ...props,
      children: [
        icon ? /* @__PURE__ */ jsx(
          "span",
          {
            className: "inline-flex size-4 shrink-0 items-center justify-center text-muted-foreground [&_svg]:size-4",
            "data-slot": "rich-editor-menu-item-icon",
            "aria-hidden": "true",
            children: icon
          }
        ) : null,
        /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children })
      ]
    }
  )
);
RichEditorMenuItem.displayName = "RichEditorMenuItem";
function RichEditorDivider({ className }) {
  return /* @__PURE__ */ jsx(
    "span",
    {
      role: "separator",
      "aria-orientation": "vertical",
      className: cn("mx-px inline-block h-4 w-px shrink-0 bg-border", className),
      "data-slot": "rich-editor-divider"
    }
  );
}
const RichEditorContent = React.forwardRef(
  ({ className, placeholder, minRows = 4, disabled, onBlur, onInput, onKeyDown, onPaste, id, name, ...props }, ref) => {
    const minHeight = `${Math.max(1, minRows) * 1.5}rem`;
    return /* @__PURE__ */ jsx(
      "div",
      {
        ref,
        contentEditable: !disabled,
        suppressContentEditableWarning: true,
        spellCheck: true,
        role: "textbox",
        "aria-multiline": "true",
        "data-slot": "rich-editor-content",
        "data-placeholder": placeholder ?? "",
        "data-name": name,
        id,
        className: cn(
          // Figma reference: content lives in its own bordered card with rounded-8 + shadow-xs,
          // visually separated from the toolbar by the small vertical gap from the parent
          // wrapper's `space-y-2`.
          "w-full max-w-none rounded-lg border border-border bg-card px-3 py-3 text-sm leading-6 text-foreground shadow-xs focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40",
          // The project does not include `@tailwindcss/typography`, so we have to
          // re-implement the rich text rendering ourselves via descendant-arbitrary
          // selectors. Cover every tag the toolbar can produce so the user sees
          // the formatting instantly after each execCommand.
          "[&_h1]:mt-4 [&_h1]:mb-2 [&_h1]:text-2xl [&_h1]:font-bold",
          "[&_h2]:mt-3 [&_h2]:mb-2 [&_h2]:text-xl [&_h2]:font-semibold",
          "[&_h3]:mt-3 [&_h3]:mb-1 [&_h3]:text-lg [&_h3]:font-semibold",
          "[&_p]:my-1",
          "[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-6",
          "[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-6",
          "[&_li]:my-0.5",
          // Task list checklist override — when <ul data-task-list> we drop the
          // disc bullet so the <input type=checkbox> child stands alone.
          "[&_ul[data-task-list]]:list-none [&_ul[data-task-list]]:pl-0",
          "[&_ul[data-task-list]_input[type=checkbox]]:mr-2",
          "[&_blockquote]:my-2 [&_blockquote]:border-l-4 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:italic [&_blockquote]:text-muted-foreground",
          "[&_pre]:my-2 [&_pre]:rounded [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:font-mono [&_pre]:text-xs",
          "[&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:font-mono [&_code]:text-xs",
          "[&_a]:text-primary [&_a]:underline",
          "[&_hr]:my-3 [&_hr]:border-border",
          "[&_img]:my-2 [&_img]:h-auto [&_img]:max-w-full [&_img]:rounded",
          "[&_table]:my-2 [&_table]:border-collapse",
          "[&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1",
          "[&_th]:border [&_th]:border-border [&_th]:bg-muted [&_th]:px-2 [&_th]:py-1",
          "data-[placeholder]:before:pointer-events-none data-[placeholder]:empty:before:content-[attr(data-placeholder)] data-[placeholder]:empty:before:text-muted-foreground",
          className
        ),
        style: { minHeight },
        onBlur,
        onInput,
        onKeyDown,
        onPaste,
        ...props
      }
    );
  }
);
RichEditorContent.displayName = "RichEditorContent";
function renderToolbarItem(item) {
  switch (item.kind) {
    case "divider":
      return /* @__PURE__ */ jsx(RichEditorDivider, {}, item.key);
    case "iconButton":
      return /* @__PURE__ */ jsx(
        RichEditorIconButton,
        {
          icon: item.icon,
          ariaLabel: item.ariaLabel,
          tooltipLabel: item.tooltipLabel,
          active: item.active,
          command: item.command,
          commandArg: item.commandArg,
          onActivate: item.onActivate
        },
        item.key
      );
    case "textDropdown":
      return /* @__PURE__ */ jsx(
        RichEditorTextDropdown,
        {
          ariaLabel: item.ariaLabel,
          label: item.label,
          menu: item.menu
        },
        item.key
      );
    case "dropdownButton":
      return /* @__PURE__ */ jsx(
        RichEditorDropdownButton,
        {
          icon: item.icon,
          ariaLabel: item.ariaLabel,
          menu: item.menu,
          showChevron: item.showChevron
        },
        item.key
      );
    case "colorButton":
      return /* @__PURE__ */ jsx(
        RichEditorColorButton,
        {
          ariaLabel: item.ariaLabel,
          colorLabels: item.colorLabels
        },
        item.key
      );
  }
}
function trimTrailingDividers(items) {
  let end = items.length;
  while (end > 0 && items[end - 1].kind === "divider") end -= 1;
  return items.slice(0, end);
}
function trimLeadingDividers(items) {
  let start = 0;
  while (start < items.length && items[start].kind === "divider") start += 1;
  return items.slice(start);
}
function usePresetToolbarItems({
  variant,
  labels,
  onComment,
  onMention,
  onFullscreen,
  onImageInsert,
  exec,
  selection,
  requestUrlPrompt
}) {
  const onLink = React.useCallback(() => {
    requestUrlPrompt({
      kind: "link",
      title: labels.linkUrlPrompt,
      placeholder: "https://example.com",
      onConfirm: (url) => exec("createLink", url)
    });
  }, [requestUrlPrompt, exec, labels.linkUrlPrompt]);
  const onImage = React.useCallback(() => {
    if (onImageInsert) {
      onImageInsert();
      return;
    }
    requestUrlPrompt({
      kind: "image",
      title: labels.imageUrlPrompt,
      placeholder: "https://example.com/image.png",
      onConfirm: (url) => exec("insertImage", url)
    });
  }, [requestUrlPrompt, exec, labels.imageUrlPrompt, onImageInsert]);
  const onInsertTable = React.useCallback(() => {
    const html = '<table style="border-collapse:collapse;width:100%"><tbody><tr><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td></tr><tr><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td></tr><tr><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td><td style="border:1px solid #ebebeb;padding:8px">&nbsp;</td></tr></tbody></table><p>&nbsp;</p>';
    exec("insertHTML", html);
  }, [exec]);
  const onInsertChecklist = React.useCallback(() => {
    const html = '<ul data-task-list="true" style="list-style:none;padding-left:0"><li><label><input type="checkbox" /> </label></li></ul>';
    exec("insertHTML", html);
  }, [exec]);
  const onInsertInlineCode = React.useCallback(() => {
    const selectionText = typeof window !== "undefined" ? window.getSelection()?.toString() ?? "" : "";
    if (!selectionText) {
      exec("insertHTML", "<code>&nbsp;</code>");
      return;
    }
    exec("insertHTML", `<code>${selectionText}</code>`);
  }, [exec]);
  const showHeading = variant === "full" || variant === "standard";
  const showFontSize = variant === "full";
  const showColor = variant === "full";
  const showStrike = variant === "full";
  const showHr = variant === "full";
  const showQuoteAndCode = variant === "full";
  const showImageTable = variant === "full";
  const showChecklist = variant === "full";
  const showOrdered = variant === "full" || variant === "standard" || variant === "basic";
  const showAlign = variant === "full";
  const showComment = variant === "full";
  const commentHandler = onComment ?? (() => exec("insertText", "[comment: ]"));
  const showMention = variant === "full";
  const mentionHandler = onMention ?? (() => exec("insertText", "@"));
  const showLink = variant === "full" || variant === "standard" || variant === "basic";
  const showLists = variant !== "minimal";
  const showHelp = variant === "full";
  const showFullscreen = variant === "full" && onFullscreen !== void 0;
  const keyboardShortcutsHelp = /* @__PURE__ */ jsxs("div", { className: "flex w-64 flex-col gap-1 p-1 text-sm", role: "menu", children: [
    /* @__PURE__ */ jsx("div", { className: "px-2 py-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Keyboard" }),
    /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded px-2 py-1 hover:bg-muted", children: [
      /* @__PURE__ */ jsx("span", { children: labels.bold }),
      /* @__PURE__ */ jsx("kbd", { className: "rounded border bg-card px-1.5 py-0.5 text-xs", children: "\u2318 B" })
    ] }),
    /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded px-2 py-1 hover:bg-muted", children: [
      /* @__PURE__ */ jsx("span", { children: labels.italic }),
      /* @__PURE__ */ jsx("kbd", { className: "rounded border bg-card px-1.5 py-0.5 text-xs", children: "\u2318 I" })
    ] }),
    /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded px-2 py-1 hover:bg-muted", children: [
      /* @__PURE__ */ jsx("span", { children: labels.underline }),
      /* @__PURE__ */ jsx("kbd", { className: "rounded border bg-card px-1.5 py-0.5 text-xs", children: "\u2318 U" })
    ] })
  ] });
  const headingMenu = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", role: "menu", children: [
    /* @__PURE__ */ jsx(
      "button",
      {
        type: "button",
        role: "menuitem",
        className: "cursor-pointer rounded px-2 py-1 text-left text-sm hover:bg-muted",
        onMouseDown: (e) => e.preventDefault(),
        onClick: () => exec("formatBlock", "<p>"),
        children: labels.paragraph
      }
    ),
    /* @__PURE__ */ jsx(
      "button",
      {
        type: "button",
        role: "menuitem",
        className: "cursor-pointer rounded px-2 py-1 text-left text-lg font-semibold hover:bg-muted",
        onMouseDown: (e) => e.preventDefault(),
        onClick: () => exec("formatBlock", "<h1>"),
        children: labels.heading1
      }
    ),
    /* @__PURE__ */ jsx(
      "button",
      {
        type: "button",
        role: "menuitem",
        className: "cursor-pointer rounded px-2 py-1 text-left text-base font-semibold hover:bg-muted",
        onMouseDown: (e) => e.preventDefault(),
        onClick: () => exec("formatBlock", "<h2>"),
        children: labels.heading2
      }
    ),
    /* @__PURE__ */ jsx(
      "button",
      {
        type: "button",
        role: "menuitem",
        className: "cursor-pointer rounded px-2 py-1 text-left text-sm font-semibold hover:bg-muted",
        onMouseDown: (e) => e.preventDefault(),
        onClick: () => exec("formatBlock", "<h3>"),
        children: labels.heading3
      }
    )
  ] });
  const headingLabel = (() => {
    switch (selection.heading) {
      case "h1":
        return labels.heading1;
      case "h2":
        return labels.heading2;
      case "h3":
        return labels.heading3;
      default:
        return labels.heading;
    }
  })();
  const fontSizeMenu = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", role: "menu", children: FONT_SIZE_OPTIONS.map((size) => /* @__PURE__ */ jsx(
    "button",
    {
      type: "button",
      role: "menuitem",
      className: "cursor-pointer rounded px-2 py-1 text-left text-sm hover:bg-muted",
      onMouseDown: (e) => e.preventDefault(),
      onClick: () => {
        exec("removeFormat");
        const px = parseInt(size, 10);
        if (px > 0) {
          exec("insertHTML", `<span style="font-size:${px}px">${window.getSelection()?.toString() ?? ""}</span>`);
        }
      },
      children: size
    },
    size
  )) });
  const alignMenu = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", role: "menu", children: ["left", "center", "right", "justify"].map((option) => {
    const Icon = ALIGN_ICONS[option];
    const command = option === "justify" ? "justifyFull" : `justify${option[0].toUpperCase()}${option.slice(1)}`;
    const label = option === "left" ? labels.alignLeft : option === "center" ? labels.alignCenter : option === "right" ? labels.alignRight : labels.alignJustify;
    return /* @__PURE__ */ jsxs(
      "button",
      {
        type: "button",
        role: "menuitem",
        className: "flex cursor-pointer items-center gap-2 rounded px-2 py-1 text-left text-sm hover:bg-muted",
        onMouseDown: (e) => e.preventDefault(),
        onClick: () => exec(command),
        children: [
          /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": "true" }),
          /* @__PURE__ */ jsx("span", { children: label })
        ]
      },
      option
    );
  }) });
  const AlignActiveIcon = ALIGN_ICONS[selection.align];
  if (variant === "custom") return [];
  const items = [];
  if (showHeading) {
    items.push({ kind: "textDropdown", key: "heading", ariaLabel: labels.heading, label: headingLabel, menu: headingMenu });
    items.push({ kind: "divider", key: "d-heading" });
  }
  if (showFontSize) {
    items.push({ kind: "textDropdown", key: "fontSize", ariaLabel: labels.fontSize, label: "14px", menu: fontSizeMenu });
    items.push({ kind: "divider", key: "d-fontSize" });
  }
  if (showColor) {
    items.push({ kind: "colorButton", key: "color", ariaLabel: labels.color, colorLabels: labels.colors });
    items.push({ kind: "divider", key: "d-color" });
  }
  items.push({ kind: "iconButton", key: "bold", icon: /* @__PURE__ */ jsx(Bold, {}), command: "bold", ariaLabel: labels.bold, tooltipLabel: labels.bold, active: selection.bold });
  items.push({ kind: "iconButton", key: "italic", icon: /* @__PURE__ */ jsx(Italic, {}), command: "italic", ariaLabel: labels.italic, tooltipLabel: labels.italic, active: selection.italic });
  items.push({ kind: "iconButton", key: "underline", icon: /* @__PURE__ */ jsx(Underline, {}), command: "underline", ariaLabel: labels.underline, tooltipLabel: labels.underline, active: selection.underline });
  if (showStrike) {
    items.push({ kind: "iconButton", key: "strike", icon: /* @__PURE__ */ jsx(Strikethrough, {}), command: "strikeThrough", ariaLabel: labels.strikethrough, tooltipLabel: labels.strikethrough, active: selection.strikethrough });
  }
  if (showLists) {
    items.push({ kind: "divider", key: "d-lists" });
    items.push({ kind: "iconButton", key: "ul", icon: /* @__PURE__ */ jsx(List, {}), command: "insertUnorderedList", ariaLabel: labels.unorderedList, tooltipLabel: labels.unorderedList, active: selection.unorderedList });
    if (showOrdered) {
      items.push({ kind: "iconButton", key: "ol", icon: /* @__PURE__ */ jsx(ListOrdered, {}), command: "insertOrderedList", ariaLabel: labels.orderedList, tooltipLabel: labels.orderedList, active: selection.orderedList });
    }
  }
  if (showHr || showQuoteAndCode) {
    items.push({ kind: "divider", key: "d-structure" });
    if (showHr) {
      items.push({ kind: "iconButton", key: "hr", icon: /* @__PURE__ */ jsx(Minus, {}), ariaLabel: labels.horizontalRule, tooltipLabel: labels.horizontalRule, onActivate: () => exec("insertHorizontalRule") });
    }
    if (showQuoteAndCode) {
      items.push({ kind: "iconButton", key: "quote", icon: /* @__PURE__ */ jsx(Quote, {}), ariaLabel: labels.blockquote, tooltipLabel: labels.blockquote, active: selection.blockquote, onActivate: () => exec("formatBlock", selection.blockquote ? "<p>" : "<blockquote>") });
      items.push({ kind: "iconButton", key: "inlineCode", icon: /* @__PURE__ */ jsx(Code, {}), ariaLabel: labels.inlineCode, tooltipLabel: labels.inlineCode, onActivate: onInsertInlineCode });
      items.push({ kind: "iconButton", key: "codeBlock", icon: /* @__PURE__ */ jsx(FileCode, {}), ariaLabel: labels.codeBlock, tooltipLabel: labels.codeBlock, active: selection.code, onActivate: () => exec("formatBlock", selection.code ? "<p>" : "<pre>") });
    }
  }
  if (showImageTable) {
    items.push({ kind: "divider", key: "d-media" });
    items.push({ kind: "iconButton", key: "image", icon: /* @__PURE__ */ jsx(ImageIcon, {}), ariaLabel: labels.image, tooltipLabel: labels.image, onActivate: onImage });
    items.push({ kind: "iconButton", key: "table", icon: /* @__PURE__ */ jsx(TableIcon, {}), ariaLabel: labels.table, tooltipLabel: labels.table, onActivate: onInsertTable });
  }
  if (showChecklist) {
    items.push({ kind: "iconButton", key: "checklist", icon: /* @__PURE__ */ jsx(ListChecks, {}), ariaLabel: labels.checklist, tooltipLabel: labels.checklist, onActivate: onInsertChecklist });
  }
  if (showAlign) {
    items.push({ kind: "divider", key: "d-align" });
    items.push({ kind: "dropdownButton", key: "align", icon: /* @__PURE__ */ jsx(AlignActiveIcon, {}), ariaLabel: labels.align, menu: alignMenu });
  }
  if (showLink || showComment || showMention) {
    items.push({ kind: "divider", key: "d-anchors" });
  }
  if (showComment) {
    items.push({ kind: "iconButton", key: "comment", icon: /* @__PURE__ */ jsx(MessageCircle, {}), ariaLabel: labels.comment, tooltipLabel: labels.comment, onActivate: commentHandler });
  }
  if (showLink) {
    items.push({ kind: "iconButton", key: "link", icon: /* @__PURE__ */ jsx(Link, {}), ariaLabel: labels.link, tooltipLabel: labels.link, onActivate: onLink });
  }
  if (showMention) {
    items.push({ kind: "iconButton", key: "mention", icon: /* @__PURE__ */ jsx(AtSign, {}), ariaLabel: labels.mention, tooltipLabel: labels.mention, onActivate: mentionHandler });
  }
  if (showHelp || showFullscreen) {
    items.push({ kind: "divider", key: "d-trailing" });
    if (showHelp) {
      items.push({ kind: "dropdownButton", key: "help", icon: /* @__PURE__ */ jsx(HelpCircle, {}), ariaLabel: labels.help, menu: keyboardShortcutsHelp, showChevron: false });
    }
    if (showFullscreen && onFullscreen) {
      items.push({ kind: "iconButton", key: "fullscreen", icon: /* @__PURE__ */ jsx(Maximize2, {}), ariaLabel: labels.fullscreen, tooltipLabel: labels.fullscreen, onActivate: onFullscreen });
    }
  }
  return trimTrailingDividers(items);
}
function RichEditorAutoToolbar({
  items,
  labels,
  moreMenu
}) {
  const measureRef = React.useRef(null);
  const containerRef = React.useRef(null);
  const [firstHidden, setFirstHidden] = React.useState(null);
  React.useLayoutEffect(() => {
    if (typeof window === "undefined") return;
    if (typeof ResizeObserver === "undefined") return;
    const container = containerRef.current;
    const measureEl = measureRef.current;
    if (!container || !measureEl) return;
    const measure = () => {
      const containerWidth = container.clientWidth;
      if (containerWidth === 0) return;
      const allEls = Array.from(measureEl.children);
      if (allEls.length === 0) return;
      const moreEl = allEls[allEls.length - 1];
      const itemEls = allEls.slice(0, -1);
      const moreReserved = moreEl.offsetWidth + 4;
      const containerPadding = 4;
      let totalWidth = 0;
      for (const el of itemEls) totalWidth += el.offsetWidth + 2;
      if (totalWidth + containerPadding <= containerWidth + 2) {
        setFirstHidden(null);
        return;
      }
      let accumulated = 0;
      for (let i = 0; i < itemEls.length; i++) {
        accumulated += itemEls[i].offsetWidth + 2;
        if (accumulated > containerWidth - moreReserved - containerPadding) {
          setFirstHidden(i);
          return;
        }
      }
      setFirstHidden(null);
    };
    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(container);
    return () => ro.disconnect();
  }, [items]);
  const visibleItems = firstHidden === null ? items : trimTrailingDividers(items.slice(0, firstHidden));
  const hiddenItems = firstHidden === null ? [] : trimLeadingDividers(items.slice(firstHidden));
  const hasOverflow = hiddenItems.length > 0;
  const showMoreButton = hasOverflow || !!moreMenu;
  return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
    /* @__PURE__ */ jsxs(
      "div",
      {
        ref: measureRef,
        "aria-hidden": "true",
        className: "pointer-events-none invisible absolute left-0 top-0 flex flex-row flex-nowrap items-center gap-0.5",
        children: [
          items.map(renderToolbarItem),
          /* @__PURE__ */ jsx(RichEditorDropdownButton, { icon: /* @__PURE__ */ jsx(MoreVertical, {}), ariaLabel: labels.more, showChevron: false, menu: /* @__PURE__ */ jsx("div", {}) })
        ]
      }
    ),
    /* @__PURE__ */ jsxs(RichEditorToolbar, { ref: containerRef, className: "w-full flex-nowrap overflow-hidden", children: [
      visibleItems.map(renderToolbarItem),
      showMoreButton ? /* @__PURE__ */ jsx(
        RichEditorDropdownButton,
        {
          icon: /* @__PURE__ */ jsx(MoreVertical, {}),
          ariaLabel: labels.more,
          showChevron: false,
          menu: /* @__PURE__ */ jsxs("div", { className: "flex max-w-[320px] flex-row flex-wrap items-center gap-0.5 p-1", children: [
            moreMenu ? /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsx("div", { className: "w-full", children: moreMenu }),
              hiddenItems.length > 0 ? /* @__PURE__ */ jsx("div", { className: "my-1 h-px w-full bg-border" }) : null
            ] }) : null,
            hiddenItems.map(renderToolbarItem)
          ] })
        }
      ) : null
    ] })
  ] });
}
export {
  RICH_EDITOR_COLOR_PALETTE,
  RichEditor,
  RichEditorColorButton,
  RichEditorColorPalette,
  RichEditorContent,
  RichEditorDivider,
  RichEditorDropdownButton,
  RichEditorIconButton,
  RichEditorMenuItem,
  RichEditorTextDropdown,
  RichEditorToolbar,
  richEditorItemVariants
};
//# sourceMappingURL=rich-editor.js.map
