@qumra/fanar 0.0.26 → 0.0.28
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/ai.js +1 -1
- package/dist/charts.js +1 -1
- package/dist/{chunk-ZYLYQZBE.js → chunk-5E7KR3JO.js} +1 -1
- package/dist/{chunk-XAQJL7FX.js → chunk-EM4MF5B3.js} +1 -1
- package/dist/{chunk-TWZR3X5H.js → chunk-JOHJNMV2.js} +1 -1
- package/dist/{chunk-ZG3I7YUW.js → chunk-QFJSDPEB.js} +1 -1
- package/dist/{chunk-GCIOTDW6.js → chunk-V7VYOWMO.js} +1 -1
- package/dist/{chunk-N6V3LTIS.js → chunk-YJ45RGS6.js} +1 -1
- package/dist/editor.js +1 -1
- package/dist/index.d.ts +56 -3
- package/dist/index.js +1 -1
- package/dist/notifications.js +1 -1
- package/package.json +1 -1
package/dist/editor.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{Tooltip}from"./chunk-GCIOTDW6.js";import{Button,Input}from"./chunk-XAQJL7FX.js";import{Modal}from"./chunk-ZYLYQZBE.js";import{cn}from"./chunk-N6V3LTIS.js";import{useEffect as useEffect4,useMemo as useMemo2,useRef as useRef4,useState as useState6}from"react";import{EditorProvider,useCurrentEditor as useCurrentEditor6}from"@tiptap/react";import{CharacterCount as CharacterCount2}from"@tiptap/extension-character-count";import{Placeholder}from"@tiptap/extension-placeholder";import StarterKit from"@tiptap/starter-kit";import{Color}from"@tiptap/extension-color";import{Highlight}from"@tiptap/extension-highlight";import Image from"@tiptap/extension-image";import ListItem from"@tiptap/extension-list-item";import{Table}from"@tiptap/extension-table";import{TableCell}from"@tiptap/extension-table-cell";import{TableHeader}from"@tiptap/extension-table-header";import{TableRow}from"@tiptap/extension-table-row";import TextAlign from"@tiptap/extension-text-align";import{TextStyle}from"@tiptap/extension-text-style";import ImageResize from"tiptap-extension-resize-image";import TextDirection from"tiptap-text-direction";function contentExtensions(){return[StarterKit.configure({bulletList:{keepMarks:true,keepAttributes:false},orderedList:{keepMarks:true,keepAttributes:false},link:{openOnClick:false,autolink:true,defaultProtocol:"https"},dropcursor:{color:"var(--color-brand)",width:2}}),TextDirection.configure({types:["heading","paragraph"],defaultDirection:"rtl"}),TextAlign.configure({types:["heading","paragraph"]}),TextStyle,Color.configure({types:[TextStyle.name,ListItem.name]}),Highlight.configure({multicolor:true}),Image.configure({inline:true}),ImageResize.configure(),Table.configure({resizable:true}),TableRow,TableHeader,TableCell]}import{useCallback,useId,useMemo,useRef}from"react";import{useCurrentEditor}from"@tiptap/react";import{BubbleMenu}from"@tiptap/react/menus";import{PluginKey}from"@tiptap/pm/state";import{Bold,Code,Highlighter,Italic,Link2,Strikethrough,Underline}from"lucide-react";import{jsx,jsxs}from"react/jsx-runtime";function BubbleButton({onClick,isActive,label,children}){return jsx("button",{type:"button",onClick,"aria-label":label,"aria-pressed":isActive,className:cn("size-7 rounded-xs inline-flex items-center justify-center cursor-pointer transition-colors",isActive?"bg-brand text-white":"text-ink2 hover:bg-hover hover:text-ink"),children})}function EditorBubbleMenu(){const{editor}=useCurrentEditor();const key=useId();const pluginKey=useMemo(()=>new PluginKey(`qumraBubble${key}`),[key]);const menuRef=useRef(null);const onShow=useCallback(()=>{const el=menuRef.current;if(el)el.style.opacity="0"},[]);const onUpdate=useCallback(()=>{const el=menuRef.current;if(el)el.style.opacity="1"},[]);const scrollTarget=useMemo(()=>{if(typeof window==="undefined")return void 0;const dom=editor?.view?.dom;let node=dom?.parentElement??null;while(node){const{overflowY}=getComputedStyle(node);if(overflowY==="auto"||overflowY==="scroll")return node;node=node.parentElement}return void 0},[editor]);if(!editor)return null;const e=editor;return jsx(BubbleMenu,{editor,pluginKey,ref:el=>{menuRef.current=el},options:{placement:"top",offset:8,...scrollTarget?{scrollTarget}:{},onShow,onUpdate},shouldShow:({editor:ed,from,to})=>{if(from===to)return false;if(ed.isActive("image")||ed.isActive("codeBlock"))return false;return true},children:jsxs("div",{className:"flex items-center gap-0.5 p-1 rounded-card border border-line bg-surface shadow-pop",children:[jsx(BubbleButton,{label:"\u0639\u0631\u064A\u0636",onClick:()=>e.chain().focus().toggleBold().run(),isActive:e.isActive("bold"),children:jsx(Bold,{size:14})}),jsx(BubbleButton,{label:"\u0645\u0627\u0626\u0644",onClick:()=>e.chain().focus().toggleItalic().run(),isActive:e.isActive("italic"),children:jsx(Italic,{size:14})}),jsx(BubbleButton,{label:"\u062A\u062D\u062A\u0647 \u062E\u0637",onClick:()=>e.chain().focus().toggleUnderline().run(),isActive:e.isActive("underline"),children:jsx(Underline,{size:14})}),jsx(BubbleButton,{label:"\u064A\u062A\u0634\u0637\u0628",onClick:()=>e.chain().focus().toggleStrike().run(),isActive:e.isActive("strike"),children:jsx(Strikethrough,{size:14})}),jsx("span",{"aria-hidden":"true",className:"w-px h-5 bg-line mx-0.5"}),jsx(BubbleButton,{label:"\u0643\u0648\u062F",onClick:()=>e.chain().focus().toggleCode().run(),isActive:e.isActive("code"),children:jsx(Code,{size:14})}),jsx(BubbleButton,{label:"\u062A\u0638\u0644\u064A\u0644",onClick:()=>e.chain().focus().toggleHighlight().run(),isActive:e.isActive("highlight"),children:jsx(Highlighter,{size:14})}),jsx("span",{"aria-hidden":"true",className:"w-px h-5 bg-line mx-0.5"}),jsx(BubbleButton,{label:"\u0631\u0627\u0628\u0637",isActive:e.isActive("link"),onClick:()=>{const previous=e.getAttributes("link").href||"";const url=window.prompt("\u0631\u0627\u0628\u0637",previous);if(url===null)return;const chain=e.chain().focus().extendMarkRange("link");if(url==="")chain.unsetLink().run();else chain.setLink({href:/^https?:\/\//i.test(url)?url:`https://${url}`}).run()},children:jsx(Link2,{size:14})})]})})}import{useEffect as useEffect2,useRef as useRef3,useState as useState4}from"react";import{useCurrentEditor as useCurrentEditor5}from"@tiptap/react";import{useEffect,useRef as useRef2,useState}from"react";import{jsx as jsx2,jsxs as jsxs2}from"react/jsx-runtime";function useDismiss(open,close){const ref=useRef2(null);useEffect(()=>{if(!open)return;function onDown(e){if(ref.current&&!ref.current.contains(e.target))close()}function onKey(e){if(e.key==="Escape")close()}document.addEventListener("mousedown",onDown);document.addEventListener("keydown",onKey);return()=>{document.removeEventListener("mousedown",onDown);document.removeEventListener("keydown",onKey)}},[open,close]);return ref}var PANEL="absolute z-50 top-[calc(100%+6px)] start-0 bg-surface border border-line rounded-card shadow-panel overflow-clip animate-[fade-in_.14s_ease-out]";function Popover({trigger,children,width,className}){const[open,setOpen]=useState(false);const ref=useDismiss(open,()=>setOpen(false));return jsxs2("div",{ref,className:cn("relative flex",className),children:[trigger({open,toggle:()=>setOpen(v=>!v)}),open&&jsx2("div",{className:cn(PANEL,width??"w-56"),children:children({close:()=>setOpen(false)})})]})}function MenuItem({onClick,icon,children,danger,active}){return jsxs2("button",{type:"button",onClick,className:cn("w-full px-3 py-2 flex items-center gap-2.5 text-start text-ui cursor-pointer transition-colors",danger?"text-red hover:bg-red-bg":"text-ink2 hover:bg-hover",active&&"bg-soft text-brand-ink font-bold"),children:[icon,jsx2("span",{className:"flex-1 min-w-0 truncate",children})]})}function MenuSeparator(){return jsx2("span",{"aria-hidden":"true",className:"block h-px bg-line my-1"})}function ToolbarButton({onClick,isActive,disabled,tooltip,shortcut,children}){return jsx2(Tooltip,{content:jsxs2("span",{className:"flex items-center gap-2",children:[tooltip,shortcut&&jsx2("kbd",{dir:"ltr",className:"px-1 py-px rounded-xs bg-white/15 text-micro font-mono",children:shortcut})]}),children:jsx2("button",{type:"button",onClick,disabled,"aria-label":tooltip,"aria-pressed":isActive,className:cn("size-8 rounded-sm inline-flex items-center justify-center shrink-0 cursor-pointer transition-colors","focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-brand","disabled:opacity-40 disabled:cursor-not-allowed",isActive?"bg-soft text-brand-ink":"text-muted hover:bg-hover hover:text-ink"),children})})}function ToolbarGroup({children}){return jsx2("div",{className:"flex items-center gap-0.5 pe-1 me-1 border-e border-line last:border-e-0 last:pe-0 last:me-0",children})}function ColorGrid({colors,current,onPick,onClear,clearLabel,fallback}){return jsxs2("div",{className:"p-3 flex flex-col gap-2.5",children:[jsx2("div",{className:"grid grid-cols-4 gap-1.5",children:colors.map(color=>jsx2("button",{type:"button",onClick:()=>onPick(color),"aria-label":color,style:{background:color},className:cn("size-8 rounded-sm border cursor-pointer transition-transform hover:scale-110",current.toLowerCase()===color.toLowerCase()?"border-ink ring-2 ring-brand":"border-line")},color))}),jsxs2("div",{className:"flex items-center gap-2.5 pt-2.5 border-t border-line",children:[jsx2("input",{type:"color",value:current||fallback,onChange:e=>onPick(e.target.value),"aria-label":"\u0644\u0648\u0646 \u0645\u062E\u0635\u0651\u0635",className:"size-8 p-0 border-none bg-transparent cursor-pointer"}),jsx2("button",{type:"button",onClick:onClear,className:"text-caption text-muted hover:text-ink cursor-pointer transition-colors",children:clearLabel})]})]})}import{useCurrentEditor as useCurrentEditor2}from"@tiptap/react";import{AlignCenter,AlignLeft,AlignRight,Bold as BoldIcon,Code as CodeIcon,Eraser,Italic as ItalicIcon,List,ListOrdered,Minus,Quote,Redo,Strikethrough as StrikeIcon,Underline as UnderlineIcon,Undo}from"lucide-react";import{Fragment,jsx as jsx3,jsxs as jsxs3}from"react/jsx-runtime";function Bold2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleBold().run(),isActive:editor.isActive("bold"),tooltip:"\u0639\u0631\u064A\u0636",shortcut:"Ctrl+B",children:jsx3(BoldIcon,{size:16})})}function Italic2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleItalic().run(),isActive:editor.isActive("italic"),tooltip:"\u0645\u0627\u0626\u0644",shortcut:"Ctrl+I",children:jsx3(ItalicIcon,{size:16})})}function Underline2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleUnderline().run(),isActive:editor.isActive("underline"),tooltip:"\u062A\u062D\u062A\u0647 \u062E\u0637",shortcut:"Ctrl+U",children:jsx3(UnderlineIcon,{size:16})})}function Strikethrough2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleStrike().run(),isActive:editor.isActive("strike"),tooltip:"\u064A\u062A\u0634\u0637\u0628",shortcut:"Ctrl+Shift+S",children:jsx3(StrikeIcon,{size:16})})}function Code2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleCode().run(),isActive:editor.isActive("code"),tooltip:"\u0643\u0648\u062F",shortcut:"Ctrl+E",children:jsx3(CodeIcon,{size:16})})}function BulletList(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleBulletList().run(),isActive:editor.isActive("bulletList"),tooltip:"\u0642\u0627\u0626\u0645\u0629 \u0646\u0642\u0637\u064A\u0629",shortcut:"Ctrl+Shift+8",children:jsx3(List,{size:16})})}function OrderedList(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleOrderedList().run(),isActive:editor.isActive("orderedList"),tooltip:"\u0642\u0627\u0626\u0645\u0629 \u0645\u0631\u0642\u0651\u0645\u0629",shortcut:"Ctrl+Shift+7",children:jsx3(ListOrdered,{size:16})})}function BlockQuote(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleBlockquote().run(),isActive:editor.isActive("blockquote"),tooltip:"\u0627\u0642\u062A\u0628\u0627\u0633",shortcut:"Ctrl+Shift+B",children:jsx3(Quote,{size:16})})}function HorizontalRule(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().setHorizontalRule().run(),tooltip:"\u0641\u0627\u0635\u0644 \u0623\u0641\u0642\u064A",children:jsx3(Minus,{size:16})})}function ClearMarks(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().unsetAllMarks().run(),tooltip:"\u0645\u0633\u062D \u0627\u0644\u062A\u0646\u0633\u064A\u0642",children:jsx3(Eraser,{size:16})})}function UndoRedo(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsxs3(Fragment,{children:[jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().undo().run(),disabled:!editor.can().chain().focus().undo().run(),tooltip:"\u062A\u0631\u0627\u062C\u0639",shortcut:"Ctrl+Z",children:jsx3(Undo,{size:16})}),jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().redo().run(),disabled:!editor.can().chain().focus().redo().run(),tooltip:"\u0625\u0639\u0627\u062F\u0629",shortcut:"Ctrl+Y",children:jsx3(Redo,{size:16})})]})}function Alignment(){const{editor}=useCurrentEditor2();if(!editor)return null;const items=[{key:"right",tooltip:"\u0645\u062D\u0627\u0630\u0627\u0629 \u064A\u0645\u064A\u0646",Icon:AlignRight},{key:"center",tooltip:"\u062A\u0648\u0633\u064A\u0637",Icon:AlignCenter},{key:"left",tooltip:"\u0645\u062D\u0627\u0630\u0627\u0629 \u0634\u0645\u0627\u0644",Icon:AlignLeft}];return jsx3(Fragment,{children:items.map(({key,tooltip,Icon})=>jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().setTextAlign(key).run(),isActive:editor.isActive({textAlign:key}),disabled:!editor.can().chain().focus().setTextAlign(key).run(),tooltip,children:jsx3(Icon,{size:16})},key))})}function CharacterCount({maxChars}){const{editor}=useCurrentEditor2();if(!editor)return null;const chars=editor.storage.characterCount?.characters()??0;const words=editor.storage.characterCount?.words()??0;const over=maxChars?chars>maxChars:false;const near=maxChars?chars>maxChars*.9:false;return jsxs3("span",{className:cn("flex items-center gap-2 text-caption select-none",over?"text-red font-bold":near?"text-amber-ink font-bold":"text-muted2"),children:[jsxs3("span",{"data-num":true,children:[chars,maxChars?`/${maxChars}`:""," \u062D\u0631\u0641"]}),jsx3("span",{"aria-hidden":"true",className:"text-line",children:"|"}),jsxs3("span",{"data-num":true,children:[words," \u0643\u0644\u0645\u0629"]})]})}import{useState as useState2}from"react";import{useCurrentEditor as useCurrentEditor3}from"@tiptap/react";import{CalendarClock,ChevronDown,Columns,Highlighter as Highlighter2,Image as ImageIcon,Link2 as Link22,Merge,Palette,Plus,Rows,Split,Table as TableIcon,Trash2}from"lucide-react";import{Fragment as Fragment2,jsx as jsx4,jsxs as jsxs4}from"react/jsx-runtime";var HEADINGS=[{level:0,label:"\u0646\u0635 \u0639\u0627\u062F\u064A",size:"text-body"},{level:1,label:"\u0639\u0646\u0648\u0627\u0646 \u0661",size:"text-h2"},{level:2,label:"\u0639\u0646\u0648\u0627\u0646 \u0662",size:"text-h3"},{level:3,label:"\u0639\u0646\u0648\u0627\u0646 \u0663",size:"text-h4"},{level:4,label:"\u0639\u0646\u0648\u0627\u0646 \u0664",size:"text-lead"},{level:5,label:"\u0639\u0646\u0648\u0627\u0646 \u0665",size:"text-body"},{level:6,label:"\u0639\u0646\u0648\u0627\u0646 \u0666",size:"text-ui"}];function HeadingSelector(){const{editor}=useCurrentEditor3();if(!editor)return null;const current=HEADINGS.find(h=>h.level===0?editor.isActive("paragraph"):editor.isActive("heading",{level:h.level}))??HEADINGS[0];return jsx4(Popover,{width:"w-48",trigger:({open,toggle})=>jsxs4("button",{type:"button",onClick:toggle,"aria-haspopup":"menu","aria-expanded":open,className:cn("h-8 px-2.5 rounded-sm inline-flex items-center gap-1.5 text-ui font-bold cursor-pointer transition-colors","focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-brand",open?"bg-soft text-brand-ink":"text-ink2 hover:bg-hover"),children:[jsx4("span",{className:"truncate max-w-24",children:current.label}),jsx4(ChevronDown,{size:14,className:cn("shrink-0 transition-transform",open&&"rotate-180")})]}),children:({close})=>jsx4("div",{role:"menu",className:"py-1",children:HEADINGS.map(h=>{const active=h.level===0?editor.isActive("paragraph"):editor.isActive("heading",{level:h.level});return jsx4("button",{type:"button",role:"menuitem",onClick:()=>{if(h.level===0)editor.chain().focus().setParagraph().run();else editor.chain().focus().toggleHeading({level:h.level}).run();close()},className:cn("w-full px-3 py-2 flex items-center justify-between gap-3 text-start cursor-pointer transition-colors",active?"bg-soft text-brand-ink":"text-ink2 hover:bg-hover"),children:jsx4("span",{className:cn(h.size,active?"font-extrabold":"font-bold"),children:h.label})},h.level)})})})}function normalizeUrl(url){const t=url.trim();if(!t)return"";if(/^(https?:\/\/|mailto:|#)/i.test(t))return t;return`https://${t}`}function Link(){const{editor}=useCurrentEditor3();const[open,setOpen]=useState2(false);const[url,setUrl]=useState2("");if(!editor)return null;function apply(){const chain=editor.chain().focus().extendMarkRange("link");if(url.trim()==="")chain.unsetLink().run();else chain.setLink({href:normalizeUrl(url)}).run();setOpen(false)}return jsxs4(Fragment2,{children:[jsx4(ToolbarButton,{onClick:()=>{setUrl(editor.getAttributes("link").href||"");setOpen(true)},isActive:editor.isActive("link"),tooltip:"\u0631\u0627\u0628\u0637",shortcut:"Ctrl+K",children:jsx4(Link22,{size:16})}),jsx4(Modal,{open,onClose:()=>setOpen(false),title:"\u0625\u0636\u0627\u0641\u0629 \u0631\u0627\u0628\u0637",description:"\u0633\u064A\u0628\u0647 \u0641\u0627\u0636\u064A \u0648\u0627\u0645\u0633\u062D \u0639\u0634\u0627\u0646 \u062A\u0634\u064A\u0644 \u0627\u0644\u0631\u0627\u0628\u0637.",size:"sm",footer:jsxs4(Fragment2,{children:[jsx4(Button,{variant:"outline",onClick:()=>setOpen(false),children:"\u0625\u0644\u063A\u0627\u0621"}),jsx4(Button,{onClick:apply,children:url.trim()?"\u0623\u0636\u0641":"\u0634\u064A\u0644 \u0627\u0644\u0631\u0627\u0628\u0637"})]}),children:jsx4(Input,{label:"\u0627\u0644\u0639\u0646\u0648\u0627\u0646",dir:"ltr",placeholder:"example.com",value:url,onChange:e=>setUrl(e.target.value),onKeyDown:e=>e.key==="Enter"&&apply()})})]})}function ImageTool({onPick}){const{editor}=useCurrentEditor3();const[open,setOpen]=useState2(false);const[src,setSrc]=useState2("");if(!editor)return null;const insert=url=>editor.chain().focus().setImage({src:url}).run();return jsxs4(Fragment2,{children:[jsx4(ToolbarButton,{onClick:()=>onPick?onPick(insert):setOpen(true),isActive:editor.isActive("image"),tooltip:"\u0635\u0648\u0631\u0629",children:jsx4(ImageIcon,{size:16})}),!onPick&&jsx4(Modal,{open,onClose:()=>setOpen(false),title:"\u0625\u062F\u0631\u0627\u062C \u0635\u0648\u0631\u0629",size:"sm",footer:jsxs4(Fragment2,{children:[jsx4(Button,{variant:"outline",onClick:()=>setOpen(false),children:"\u0625\u0644\u063A\u0627\u0621"}),jsx4(Button,{disabled:!src.trim(),onClick:()=>{insert(src.trim());setSrc("");setOpen(false)},children:"\u0623\u062F\u0631\u062C"})]}),children:jsx4(Input,{label:"\u0631\u0627\u0628\u0637 \u0627\u0644\u0635\u0648\u0631\u0629",dir:"ltr",placeholder:"https://\u2026",value:src,onChange:e=>setSrc(e.target.value),hint:"\u0648\u062A\u0642\u062F\u0631 \u0643\u0645\u0627\u0646 \u062A\u0633\u062D\u0628 \u0635\u0648\u0631\u0629 \u0648\u062A\u0641\u0644\u062A\u0647\u0627 \u062C\u0648\u0651\u0647 \u0627\u0644\u0645\u062D\u0631\u0631 \u0645\u0628\u0627\u0634\u0631\u0629\u064B."})})]})}function TableTool(){const{editor}=useCurrentEditor3();if(!editor)return null;const inTable=editor.isActive("table");return jsx4(Popover,{width:"w-56",trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:inTable||open,tooltip:"\u062C\u062F\u0648\u0644",children:jsx4(TableIcon,{size:16})}),children:({close})=>{const run=fn=>()=>{fn();close()};return jsxs4("div",{role:"menu",className:"py-1",children:[jsx4(MenuItem,{icon:jsx4(Plus,{size:14}),onClick:run(()=>editor.chain().focus().insertTable({rows:3,cols:3,withHeaderRow:true}).run()),children:"\u0623\u062F\u0631\u062C \u062C\u062F\u0648\u0644 \u0663\xD7\u0663"}),inTable&&jsxs4(Fragment2,{children:[jsx4(MenuSeparator,{}),jsx4(MenuItem,{icon:jsx4(Rows,{size:14}),onClick:run(()=>editor.chain().focus().addRowBefore().run()),children:"\u0635\u0641 \u0642\u0628\u0644"}),jsx4(MenuItem,{icon:jsx4(Rows,{size:14}),onClick:run(()=>editor.chain().focus().addRowAfter().run()),children:"\u0635\u0641 \u0628\u0639\u062F"}),jsx4(MenuItem,{danger:true,icon:jsx4(Trash2,{size:14}),onClick:run(()=>editor.chain().focus().deleteRow().run()),children:"\u0627\u062D\u0630\u0641 \u0627\u0644\u0635\u0641"}),jsx4(MenuSeparator,{}),jsx4(MenuItem,{icon:jsx4(Columns,{size:14}),onClick:run(()=>editor.chain().focus().addColumnBefore().run()),children:"\u0639\u0645\u0648\u062F \u0642\u0628\u0644"}),jsx4(MenuItem,{icon:jsx4(Columns,{size:14}),onClick:run(()=>editor.chain().focus().addColumnAfter().run()),children:"\u0639\u0645\u0648\u062F \u0628\u0639\u062F"}),jsx4(MenuItem,{danger:true,icon:jsx4(Trash2,{size:14}),onClick:run(()=>editor.chain().focus().deleteColumn().run()),children:"\u0627\u062D\u0630\u0641 \u0627\u0644\u0639\u0645\u0648\u062F"}),jsx4(MenuSeparator,{}),jsx4(MenuItem,{icon:jsx4(Merge,{size:14}),onClick:run(()=>editor.chain().focus().mergeCells().run()),children:"\u0627\u062F\u0645\u062C \u0627\u0644\u062E\u0644\u0627\u064A\u0627"}),jsx4(MenuItem,{icon:jsx4(Split,{size:14}),onClick:run(()=>editor.chain().focus().splitCell().run()),children:"\u0627\u0642\u0633\u0645 \u0627\u0644\u062E\u0644\u064A\u0629"}),jsx4(MenuSeparator,{}),jsx4(MenuItem,{danger:true,icon:jsx4(Trash2,{size:14}),onClick:run(()=>editor.chain().focus().deleteTable().run()),children:"\u0627\u062D\u0630\u0641 \u0627\u0644\u062C\u062F\u0648\u0644"})]})]})}})}var TEXT_COLORS=["#000000","#434343","#666666","#999999","#E03131","#C2255C","#9C36B5","#6741D9","#3B5BDB","#1971C2","#0C8599","#099268","#2F9E44","#66A80F","#F08C00","#E8590C"];var HIGHLIGHT_COLORS=["#FBBF24","#F87171","#FB923C","#A78BFA","#60A5FA","#34D399","#F472B6","#2DD4BF","#FCD34D","#FCA5A5","#FDBA74","#C4B5FD","#93C5FD","#6EE7B7","#F9A8D4","#99F6E4"];function ColorTool(){const{editor}=useCurrentEditor3();if(!editor)return null;const current=editor.getAttributes("textStyle").color||"";return jsx4(Popover,{trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:open,tooltip:"\u0644\u0648\u0646 \u0627\u0644\u0646\u0635",children:jsxs4("span",{className:"flex flex-col items-center gap-0.5",children:[jsx4(Palette,{size:16,style:current?{color:current}:void 0}),jsx4("span",{"aria-hidden":"true",className:"w-4 h-0.5 rounded-full",style:{background:current||"currentColor"}})]})}),children:({close})=>jsx4(ColorGrid,{colors:TEXT_COLORS,current,fallback:"#000000",clearLabel:"\u0634\u064A\u0644 \u0627\u0644\u0644\u0648\u0646",onPick:c=>{editor.chain().focus().setColor(c).run();close()},onClear:()=>{editor.chain().focus().unsetColor().run();close()}})})}function HighlightTool(){const{editor}=useCurrentEditor3();if(!editor)return null;const current=editor.getAttributes("highlight").color||"";return jsx4(Popover,{trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:editor.isActive("highlight")||open,tooltip:"\u062A\u0638\u0644\u064A\u0644",children:jsxs4("span",{className:"flex flex-col items-center gap-0.5",children:[jsx4(Highlighter2,{size:16}),jsx4("span",{"aria-hidden":"true",className:"w-4 h-0.5 rounded-full",style:{background:current||"transparent"}})]})}),children:({close})=>jsx4(ColorGrid,{colors:HIGHLIGHT_COLORS,current,fallback:"#FBBF24",clearLabel:"\u0634\u064A\u0644 \u0627\u0644\u062A\u0638\u0644\u064A\u0644",onPick:c=>{editor.chain().focus().toggleHighlight({color:c}).run();close()},onClear:()=>{editor.chain().focus().unsetHighlight().run();close()}})})}var DATE_FORMATS=[{label:"\u0663\u0661 \u064A\u0648\u0644\u064A\u0648 \u0662\u0660\u0662\u0666",opts:{day:"numeric",month:"long",year:"numeric"}},{label:"\u0663\u0661 \u064A\u0648\u0644 \u0662\u0660\u0662\u0666",opts:{day:"numeric",month:"short",year:"numeric"}},{label:"\u0627\u0644\u062C\u0645\u0639\u0629\u060C \u0663\u0661 \u064A\u0648\u0644\u064A\u0648",opts:{weekday:"long",day:"numeric",month:"long"}},{label:"\u0662\u0660\u0662\u0666/\u0660\u0667/\u0663\u0661",opts:{year:"numeric",month:"2-digit",day:"2-digit"}},{label:"\u0660\u0662:\u0665\u0661 \u0635",opts:{hour:"2-digit",minute:"2-digit"}},{label:"\u0660\u0662:\u0665\u0661:\u0663\u0660 \u0635",opts:{hour:"2-digit",minute:"2-digit",second:"2-digit"}}];function DateTime({locale="ar-EG"}){const{editor}=useCurrentEditor3();if(!editor)return null;return jsx4(Popover,{width:"w-56",trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:open,tooltip:"\u062A\u0627\u0631\u064A\u062E \u0648\u0648\u0642\u062A",children:jsx4(CalendarClock,{size:16})}),children:({close})=>jsx4("div",{role:"menu",className:"py-1",children:DATE_FORMATS.map(f=>{const text=new Intl.DateTimeFormat(locale,f.opts).format(new Date);return jsx4(MenuItem,{onClick:()=>{editor.chain().focus().insertContent(text).run();close()},children:text},f.label)})})})}import{useCallback as useCallback2,useState as useState3}from"react";import{useCurrentEditor as useCurrentEditor4}from"@tiptap/react";import{ChevronDown as ChevronDown2,ChevronUp,Replace,Search}from"lucide-react";import{Fragment as Fragment3,jsx as jsx5,jsxs as jsxs5}from"react/jsx-runtime";function FindReplace(){const{editor}=useCurrentEditor4();const[term,setTerm]=useState3("");const[replacement,setReplacement]=useState3("");const[matches,setMatches]=useState3([]);const[index,setIndex]=useState3(0);const jump=useCallback2(m=>editor?.chain().setTextSelection(m).scrollIntoView().run(),[editor]);const find=useCallback2(value=>{if(!editor||!value.trim()){setMatches([]);setIndex(0);return}const found=[];const needle=value.toLowerCase();editor.state.doc.descendants((node,pos)=>{if(!node.isText)return;const text=node.text?.toLowerCase()??"";let at=text.indexOf(needle);while(at!==-1){found.push({from:pos+at,to:pos+at+value.length});at=text.indexOf(needle,at+1)}});setMatches(found);setIndex(0);if(found[0])jump(found[0])},[editor,jump]);if(!editor)return null;const step=by=>{if(matches.length===0)return;const next=(index+by+matches.length)%matches.length;setIndex(next);jump(matches[next])};const replaceOne=()=>{const m=matches[index];if(!m)return;editor.chain().focus().setTextSelection(m).insertContent(replacement).run();find(term)};const replaceAll=()=>{if(matches.length===0)return;const chain=editor.chain().focus();for(const m of[...matches].sort((a,b)=>b.from-a.from)){chain.setTextSelection(m).insertContent(replacement)}chain.run();find(term)};return jsx5(Popover,{width:"w-72",trigger:({open,toggle})=>jsx5(ToolbarButton,{onClick:toggle,isActive:open,tooltip:"\u0628\u062D\u062B \u0648\u0627\u0633\u062A\u0628\u062F\u0627\u0644",shortcut:"Ctrl+H",children:jsx5(Search,{size:16})}),children:()=>jsxs5("div",{className:"p-3 flex flex-col gap-2.5",children:[jsxs5("div",{className:"flex items-end gap-1.5",children:[jsx5(Input,{autoFocus:true,size:"sm",label:"\u0627\u0628\u062D\u062B \u0639\u0646",hideLabel:true,placeholder:"\u0627\u0628\u062D\u062B \u0639\u0646\u2026",value:term,wrapperClassName:"flex-1 min-w-0",onChange:e=>{setTerm(e.target.value);find(e.target.value)},onKeyDown:e=>{if(e.key!=="Enter")return;e.preventDefault();step(e.shiftKey?-1:1)}}),jsx5(Button,{size:"sm",variant:"outline",iconOnly:true,"aria-label":"\u0627\u0644\u0633\u0627\u0628\u0642",disabled:matches.length===0,onClick:()=>step(-1),icon:jsx5(ChevronUp,{size:14})}),jsx5(Button,{size:"sm",variant:"outline",iconOnly:true,"aria-label":"\u0627\u0644\u062A\u0627\u0644\u064A",disabled:matches.length===0,onClick:()=>step(1),icon:jsx5(ChevronDown2,{size:14})})]}),term.trim()&&jsx5("span",{className:"text-micro text-muted2","aria-live":"polite",children:matches.length>0?jsxs5(Fragment3,{children:[jsx5("span",{"data-num":true,children:index+1})," \u0645\u0646 ",jsx5("span",{"data-num":true,children:matches.length})]}):"\u0645\u0627\u0641\u064A\u0634 \u0646\u062A\u0627\u064A\u062C"}),jsxs5("div",{className:"flex items-end gap-1.5",children:[jsx5(Input,{size:"sm",label:"\u0627\u0633\u062A\u0628\u062F\u0644 \u0628\u0640",hideLabel:true,placeholder:"\u0627\u0633\u062A\u0628\u062F\u0644 \u0628\u0640\u2026",value:replacement,wrapperClassName:"flex-1 min-w-0",onChange:e=>setReplacement(e.target.value),onKeyDown:e=>{if(e.key==="Enter"){e.preventDefault();replaceOne()}}}),jsx5(Button,{size:"sm",variant:"outline",iconOnly:true,"aria-label":"\u0627\u0633\u062A\u0628\u062F\u0644",disabled:matches.length===0,onClick:replaceOne,icon:jsx5(Replace,{size:14})})]}),jsx5(Button,{size:"sm",variant:"soft",block:true,disabled:matches.length===0,onClick:replaceAll,children:"\u0627\u0633\u062A\u0628\u062F\u0644 \u0627\u0644\u0643\u0644"})]})})}import{jsx as jsx6,jsxs as jsxs6}from"react/jsx-runtime";function useEditorTick(){const[,setTick]=useState4(0);const{editor}=useCurrentEditor5();const raf=useRef3(0);useEffect2(()=>{if(!editor)return;const bump=()=>{cancelAnimationFrame(raf.current);raf.current=requestAnimationFrame(()=>setTick(t=>t+1))};editor.on("selectionUpdate",bump);editor.on("transaction",bump);return()=>{cancelAnimationFrame(raf.current);editor.off("selectionUpdate",bump);editor.off("transaction",bump)}},[editor])}function Toolbar({basic,onPickImage,hideImage,locale}){useEditorTick();const{editor}=useCurrentEditor5();if(!editor)return null;if(basic){return jsxs6("div",{className:"w-full border-b border-line px-1.5 py-1 flex flex-wrap items-center gap-0.5",children:[jsx6(ToolbarGroup,{children:jsx6(UndoRedo,{})}),jsx6(ToolbarGroup,{children:jsx6(HeadingSelector,{})}),jsxs6(ToolbarGroup,{children:[jsx6(Bold2,{}),jsx6(Italic2,{}),jsx6(Underline2,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(BulletList,{}),jsx6(OrderedList,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(Link,{}),!hideImage&&jsx6(ImageTool,{onPick:onPickImage}),jsx6(ColorTool,{})]})]})}return jsxs6("div",{className:"w-full border-b border-line px-1.5 py-1.5 flex flex-wrap items-center gap-y-1",children:[jsx6(ToolbarGroup,{children:jsx6(UndoRedo,{})}),jsx6(ToolbarGroup,{children:jsx6(HeadingSelector,{})}),jsxs6(ToolbarGroup,{children:[jsx6(Bold2,{}),jsx6(Italic2,{}),jsx6(Underline2,{}),jsx6(Strikethrough2,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(BulletList,{}),jsx6(OrderedList,{}),jsx6(BlockQuote,{})]}),jsx6(ToolbarGroup,{children:jsx6(Alignment,{})}),jsxs6(ToolbarGroup,{children:[jsx6(Link,{}),!hideImage&&jsx6(ImageTool,{onPick:onPickImage}),jsx6(TableTool,{}),jsx6(DateTime,{locale})]}),jsxs6(ToolbarGroup,{children:[jsx6(ColorTool,{}),jsx6(HighlightTool,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(Code2,{}),jsx6(HorizontalRule,{}),jsx6(ClearMarks,{}),jsx6(FindReplace,{})]})]})}function EditorFooter({maxChars}){return jsx6("div",{className:"border-t border-line px-3 py-1.5 flex justify-end",children:jsx6(CharacterCount,{maxChars})})}import{forwardRef,useEffect as useEffect3,useImperativeHandle,useState as useState5}from"react";import{Extension}from"@tiptap/core";import{PluginKey as PluginKey2}from"@tiptap/pm/state";import{ReactRenderer}from"@tiptap/react";import Suggestion from"@tiptap/suggestion";import{jsx as jsx7,jsxs as jsxs7}from"react/jsx-runtime";var SLASH_ITEMS=[{title:"\u0639\u0646\u0648\u0627\u0646 \u0643\u0628\u064A\u0631",hint:"H1",icon:"H1",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHeading({level:1}).run()},{title:"\u0639\u0646\u0648\u0627\u0646 \u0645\u062A\u0648\u0633\u0637",hint:"H2",icon:"H2",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHeading({level:2}).run()},{title:"\u0639\u0646\u0648\u0627\u0646 \u0635\u063A\u064A\u0631",hint:"H3",icon:"H3",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHeading({level:3}).run()},{title:"\u0642\u0627\u0626\u0645\u0629 \u0646\u0642\u0637\u064A\u0629",icon:"\u2022",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleBulletList().run()},{title:"\u0642\u0627\u0626\u0645\u0629 \u0645\u0631\u0642\u0651\u0645\u0629",icon:"\u0661.",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleOrderedList().run()},{title:"\u0627\u0642\u062A\u0628\u0627\u0633",icon:"\u275D",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleBlockquote().run()},{title:"\u0628\u0644\u0648\u0643 \u0643\u0648\u062F",icon:"</>",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleCodeBlock().run()},{title:"\u062C\u062F\u0648\u0644",hint:"\u0663\xD7\u0663",icon:"\u229E",command:({editor,range})=>editor.chain().focus().deleteRange(range).insertTable({rows:3,cols:3,withHeaderRow:true}).run()},{title:"\u0641\u0627\u0635\u0644 \u0623\u0641\u0642\u064A",icon:"\u2500",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHorizontalRule().run()}];var SlashList=forwardRef(function SlashList2({items,command},ref){const[active,setActive]=useState5(0);useEffect3(()=>setActive(0),[items]);useImperativeHandle(ref,()=>({onKeyDown:({event})=>{if(event.key==="ArrowUp"){setActive(i=>i<=0?items.length-1:i-1);return true}if(event.key==="ArrowDown"){setActive(i=>i>=items.length-1?0:i+1);return true}if(event.key==="Enter"){const item=items[active];if(item)command(item);return true}return false}}));if(items.length===0)return null;return jsx7("div",{className:"w-64 max-h-72 overflow-y-auto rounded-card border border-line bg-surface shadow-pop py-1 animate-[fade-in_.12s_ease-out]",children:items.map((item,i)=>jsxs7("button",{type:"button",onMouseEnter:()=>setActive(i),onClick:()=>command(item),className:cn("w-full px-3 py-2 flex items-center gap-3 text-start cursor-pointer transition-colors",i===active?"bg-soft text-brand-ink":"text-ink2 hover:bg-hover"),children:[jsx7("span",{"aria-hidden":"true",className:"size-7 shrink-0 rounded-sm bg-bg border border-line flex items-center justify-center text-micro font-extrabold",children:item.icon}),jsx7("span",{className:"flex-1 min-w-0 text-ui font-bold truncate",children:item.title}),item.hint&&jsx7("span",{dir:"ltr",className:"text-micro text-muted2 shrink-0",children:item.hint})]},item.title))})});var SlashCommandsPluginKey=new PluginKey2("qumraSlashCommands");var SlashCommands=Extension.create({name:"qumraSlashCommands",addOptions(){return{suggestion:{char:"/",pluginKey:SlashCommandsPluginKey,command:({editor,range,props})=>{props.command({editor,range})}}}},addProseMirrorPlugins(){return[Suggestion({editor:this.editor,...this.options.suggestion})]}});function place(el,rect){const rtl=getComputedStyle(document.documentElement).direction==="rtl";const gap=6;const{offsetHeight:h,offsetWidth:w}=el;const below=window.innerHeight-rect.bottom;const top=below<h+gap&&rect.top>h+gap?rect.top-h-gap:rect.bottom+gap;let left=rtl?rect.right-w:rect.left;left=Math.max(8,Math.min(left,window.innerWidth-w-8));el.style.top=`${top+window.scrollY}px`;el.style.left=`${left+window.scrollX}px`}function createSlashSuggestion(){return{items:({query})=>!query?SLASH_ITEMS:SLASH_ITEMS.filter(i=>i.title.includes(query)||i.icon.toLowerCase().includes(query.toLowerCase())),render:()=>{let component=null;let host=null;const reposition=clientRect=>{const rect=clientRect?.();if(host&&rect)place(host,rect)};return{onStart:props=>{component=new ReactRenderer(SlashList,{props,editor:props.editor});host=document.createElement("div");host.style.position="absolute";host.style.zIndex="60";host.appendChild(component.element);document.body.appendChild(host);reposition(props.clientRect)},onUpdate:props=>{component?.updateProps(props);reposition(props.clientRect)},onKeyDown:props=>{if(props.event.key==="Escape"){host?.remove();return true}const api=component?.ref;return api?.onKeyDown?.(props)??false},onExit:()=>{host?.remove();component?.destroy();host=null;component=null}}}}}import"react";import{mergeAttributes,Node,nodePasteRule}from"@tiptap/core";import{NodeViewWrapper,ReactNodeViewRenderer}from"@tiptap/react";import{jsx as jsx8}from"react/jsx-runtime";var TOKEN_SPAN_RE=/<span\b([^>]*)\bdata-token="([^"]+)"([^>]*)>([\s\S]*?)<\/span>/gi;var ENTITIES={"&":"&","<":"<",">":">",""":'"',"'":"'","'":"'"};function decode(s){return s.replace(/&(amp|lt|gt|quot|#39|apos);/g,m=>ENTITIES[m]??m)}function encode(s){return s.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}var MASK_OPEN="\uE000";var MASK_CLOSE="\uE001";var MASK_RE=/\uE000(\d+)\uE001/g;function fresh(re){return new RegExp(re.source,re.flags.includes("g")?re.flags:`${re.flags}g`)}function wrapTokens(html,pattern){if(!html)return html;const masked=[];const safe=html.replace(TOKEN_SPAN_RE,full=>{const i=masked.push(full)-1;return`${MASK_OPEN}${i}${MASK_CLOSE}`});const wrapped=safe.replace(fresh(pattern),raw=>`<span data-token="${encode(raw)}"></span>`);return wrapped.replace(MASK_RE,(_,i)=>masked[Number(i)])}function textToTokenHtml(text,pattern){if(!text)return"<p></p>";let out="";let cursor=0;for(const m of text.matchAll(fresh(pattern))){const at=m.index??0;if(at>cursor)out+=encode(text.slice(cursor,at));out+=`<span data-token="${encode(m[0])}"></span>`;cursor=at+m[0].length}if(cursor<text.length)out+=encode(text.slice(cursor));return`<p>${out}</p>`}function unwrapTokens(html){if(!html)return html;return html.replace(TOKEN_SPAN_RE,(_,_pre,attr)=>decode(attr))}function createTokenNode({pattern,render}){return Node.create({name:"qumraToken",group:"inline",inline:true,atom:true,selectable:true,addAttributes(){return{raw:{default:"",parseHTML:el=>el.getAttribute("data-token")??"",renderHTML:attrs=>attrs.raw?{"data-token":String(attrs.raw)}:{}}}},parseHTML(){return[{tag:"span[data-token]"}]},renderHTML({HTMLAttributes}){return["span",mergeAttributes({class:"qumra-token"},HTMLAttributes)]},renderText({node}){return String(node.attrs.raw??"")},addNodeView(){return ReactNodeViewRenderer(props=>jsx8(NodeViewWrapper,{as:"span",className:"qumra-token","data-drag-handle":void 0,children:render(String(props.node.attrs.raw??""))}))},addPasteRules(){return[nodePasteRule({find:fresh(pattern),type:this.type,getAttributes:match=>({raw:match[0]})})]}})}import{jsx as jsx9,jsxs as jsxs8}from"react/jsx-runtime";function Editor({content,onChange,placeholder,maxChars,basic,disabled,onPickImage,hideImage,locale="ar-EG",tokens,className}){const extensions=useMemo2(()=>[...contentExtensions(),Placeholder.configure({placeholder:placeholder??""}),CharacterCount2.configure(maxChars?{limit:maxChars}:{}),SlashCommands.configure({suggestion:createSlashSuggestion()}),...tokens?[createTokenNode(tokens)]:[]],[placeholder,maxChars,tokens]);const lastEmitted=useRef4("");const[initialContent]=useState6(()=>tokens?wrapTokens(content||"",tokens.pattern):content||"");const editorProps=useMemo2(()=>({attributes:{class:"qumra-tiptap",dir:"auto"},handleDrop:(view,event,_slice,moved)=>{if(moved||!event.dataTransfer?.files?.length)return false;const file=event.dataTransfer.files[0];if(!file?.type.startsWith("image/"))return false;const reader=new FileReader;reader.onload=()=>{const at=view.posAtCoords({left:event.clientX,top:event.clientY});if(!at)return;const node=view.state.schema.nodes.image.create({src:reader.result});view.dispatch(view.state.tr.insert(at.pos,node))};reader.readAsDataURL(file);return true},handlePaste:(view,event)=>{const items=event.clipboardData?.items;if(!items)return false;for(const item of Array.from(items)){if(!item.type.startsWith("image/"))continue;const file=item.getAsFile();if(!file)continue;const reader=new FileReader;reader.onload=()=>{const node=view.state.schema.nodes.image.create({src:reader.result});view.dispatch(view.state.tr.insert(view.state.selection.from,node))};reader.readAsDataURL(file);return true}return false}}),[]);const handleUpdate=({editor})=>{const html=tokens?unwrapTokens(editor.getHTML()):editor.getHTML();if(html===lastEmitted.current)return;lastEmitted.current=html;onChange(html)};return jsx9("div",{className:cn("relative","bg-surface border border-border rounded-field","focus-within:border-brand transition-colors","[&>*:first-child]:rounded-t-field",disabled&&"opacity-60 pointer-events-none",className),children:jsxs8(EditorProvider,{immediatelyRender:false,extensions,content:initialContent,onUpdate:handleUpdate,slotBefore:!disabled&&jsx9(Toolbar,{basic,onPickImage,hideImage,locale}),slotAfter:!disabled&&jsx9(EditorFooter,{maxChars}),editorProps,children:[jsx9(EditorBubbleMenu,{}),jsx9(SyncContent,{content,disabled,lastEmitted,tokens})]})})}function SyncContent({content,disabled,lastEmitted,tokens}){const{editor}=useCurrentEditor6();useEffect4(()=>{if(!editor)return;const incoming=content||"";const current=tokens?unwrapTokens(editor.getHTML()):editor.getHTML();if(incoming!==current){editor.commands.setContent(tokens?wrapTokens(incoming,tokens.pattern):incoming,{emitUpdate:false});lastEmitted.current=tokens?unwrapTokens(editor.getHTML()):editor.getHTML()}if(editor.isEditable===Boolean(disabled)){editor.setEditable(!disabled,false)}},[content,disabled,editor,lastEmitted,tokens]);return null}import{generateHTML,generateJSON}from"@tiptap/core";function emptyDoc(){return{type:"doc",content:[{type:"paragraph"}]}}function htmlToDoc(html){try{return generateJSON(html?.trim()?html:"<p></p>",contentExtensions())}catch{return emptyDoc()}}function docToHtml(doc){if(!isDoc(doc))return"";try{return generateHTML(doc,contentExtensions())}catch{return""}}function isDoc(value){return!!value&&typeof value==="object"&&!Array.isArray(value)&&value.type==="doc"}import{useEffect as useEffect5,useMemo as useMemo3,useRef as useRef5,useState as useState7}from"react";import{Extension as Extension2,Node as Node2}from"@tiptap/core";import{EditorContent,useEditor}from"@tiptap/react";import{Placeholder as Placeholder2}from"@tiptap/extension-placeholder";import{jsx as jsx10}from"react/jsx-runtime";var SIZES={sm:"min-h-9 text-ui px-3",md:"min-h-11 text-body px-3.5"};var Doc=Node2.create({name:"doc",topNode:true,content:"paragraph"});var Para=Node2.create({name:"paragraph",group:"block",content:"inline*",parseHTML:()=>[{tag:"p"}],renderHTML:()=>["p",0]});var Txt=Node2.create({name:"text",group:"inline"});var SingleLine=Extension2.create({name:"qumraSingleLine",addKeyboardShortcuts(){return{Enter:()=>true,"Shift-Enter":()=>true}}});function TokenInput({value,onChange,tokens,placeholder,disabled,size="md",className,"aria-labelledby":labelledBy}){const extensions=useMemo3(()=>[Doc,Para,Txt,SingleLine,Placeholder2.configure({placeholder:placeholder??""}),...tokens?[createTokenNode(tokens)]:[]],[placeholder,tokens]);const emitted=useRef5(value);const[seed]=useState7(()=>tokens?textToTokenHtml(value,tokens.pattern):`<p>${value}</p>`);const editor=useEditor({immediatelyRender:false,editable:!disabled,extensions,content:seed,editorProps:{attributes:{class:"qumra-token-input",dir:"auto",...labelledBy?{"aria-labelledby":labelledBy}:{}}},onUpdate:({editor:e})=>{const text=e.getText();emitted.current=text;onChange(text)}},[extensions]);useEffect5(()=>{if(!editor)return;if(value===emitted.current||value===editor.getText())return;editor.commands.setContent(tokens?textToTokenHtml(value,tokens.pattern):`<p>${value}</p>`,{emitUpdate:false});emitted.current=value},[editor,value,tokens]);useEffect5(()=>{if(editor&&editor.isEditable===Boolean(disabled))editor.setEditable(!disabled,false)},[editor,disabled]);return jsx10(EditorContent,{editor,className:cn("w-full bg-surface text-ink rounded-field border transition-colors","border-border hover:border-brand focus-within:border-brand","[&_.ProseMirror]:outline-none [&_.ProseMirror]:py-2","[&_.ProseMirror_p]:m-0",SIZES[size],disabled&&"bg-bg text-muted cursor-not-allowed opacity-70",className)})}export{Editor,TokenInput,docToHtml,htmlToDoc,isDoc,textToTokenHtml,unwrapTokens,wrapTokens};
|
|
2
|
+
import{Tooltip}from"./chunk-V7VYOWMO.js";import{Button,Input}from"./chunk-EM4MF5B3.js";import{Modal}from"./chunk-5E7KR3JO.js";import{cn}from"./chunk-YJ45RGS6.js";import{useEffect as useEffect4,useMemo as useMemo2,useRef as useRef4,useState as useState6}from"react";import{EditorProvider,useCurrentEditor as useCurrentEditor6}from"@tiptap/react";import{CharacterCount as CharacterCount2}from"@tiptap/extension-character-count";import{Placeholder}from"@tiptap/extension-placeholder";import StarterKit from"@tiptap/starter-kit";import{Color}from"@tiptap/extension-color";import{Highlight}from"@tiptap/extension-highlight";import Image from"@tiptap/extension-image";import ListItem from"@tiptap/extension-list-item";import{Table}from"@tiptap/extension-table";import{TableCell}from"@tiptap/extension-table-cell";import{TableHeader}from"@tiptap/extension-table-header";import{TableRow}from"@tiptap/extension-table-row";import TextAlign from"@tiptap/extension-text-align";import{TextStyle}from"@tiptap/extension-text-style";import ImageResize from"tiptap-extension-resize-image";import TextDirection from"tiptap-text-direction";function contentExtensions(){return[StarterKit.configure({bulletList:{keepMarks:true,keepAttributes:false},orderedList:{keepMarks:true,keepAttributes:false},link:{openOnClick:false,autolink:true,defaultProtocol:"https"},dropcursor:{color:"var(--color-brand)",width:2}}),TextDirection.configure({types:["heading","paragraph"],defaultDirection:"rtl"}),TextAlign.configure({types:["heading","paragraph"]}),TextStyle,Color.configure({types:[TextStyle.name,ListItem.name]}),Highlight.configure({multicolor:true}),Image.configure({inline:true}),ImageResize.configure(),Table.configure({resizable:true}),TableRow,TableHeader,TableCell]}import{useCallback,useId,useMemo,useRef}from"react";import{useCurrentEditor}from"@tiptap/react";import{BubbleMenu}from"@tiptap/react/menus";import{PluginKey}from"@tiptap/pm/state";import{Bold,Code,Highlighter,Italic,Link2,Strikethrough,Underline}from"lucide-react";import{jsx,jsxs}from"react/jsx-runtime";function BubbleButton({onClick,isActive,label,children}){return jsx("button",{type:"button",onClick,"aria-label":label,"aria-pressed":isActive,className:cn("size-7 rounded-xs inline-flex items-center justify-center cursor-pointer transition-colors",isActive?"bg-brand text-white":"text-ink2 hover:bg-hover hover:text-ink"),children})}function EditorBubbleMenu(){const{editor}=useCurrentEditor();const key=useId();const pluginKey=useMemo(()=>new PluginKey(`qumraBubble${key}`),[key]);const menuRef=useRef(null);const onShow=useCallback(()=>{const el=menuRef.current;if(el)el.style.opacity="0"},[]);const onUpdate=useCallback(()=>{const el=menuRef.current;if(el)el.style.opacity="1"},[]);const scrollTarget=useMemo(()=>{if(typeof window==="undefined")return void 0;const dom=editor?.view?.dom;let node=dom?.parentElement??null;while(node){const{overflowY}=getComputedStyle(node);if(overflowY==="auto"||overflowY==="scroll")return node;node=node.parentElement}return void 0},[editor]);if(!editor)return null;const e=editor;return jsx(BubbleMenu,{editor,pluginKey,ref:el=>{menuRef.current=el},options:{placement:"top",offset:8,...scrollTarget?{scrollTarget}:{},onShow,onUpdate},shouldShow:({editor:ed,from,to})=>{if(from===to)return false;if(ed.isActive("image")||ed.isActive("codeBlock"))return false;return true},children:jsxs("div",{className:"flex items-center gap-0.5 p-1 rounded-card border border-line bg-surface shadow-pop",children:[jsx(BubbleButton,{label:"\u0639\u0631\u064A\u0636",onClick:()=>e.chain().focus().toggleBold().run(),isActive:e.isActive("bold"),children:jsx(Bold,{size:14})}),jsx(BubbleButton,{label:"\u0645\u0627\u0626\u0644",onClick:()=>e.chain().focus().toggleItalic().run(),isActive:e.isActive("italic"),children:jsx(Italic,{size:14})}),jsx(BubbleButton,{label:"\u062A\u062D\u062A\u0647 \u062E\u0637",onClick:()=>e.chain().focus().toggleUnderline().run(),isActive:e.isActive("underline"),children:jsx(Underline,{size:14})}),jsx(BubbleButton,{label:"\u064A\u062A\u0634\u0637\u0628",onClick:()=>e.chain().focus().toggleStrike().run(),isActive:e.isActive("strike"),children:jsx(Strikethrough,{size:14})}),jsx("span",{"aria-hidden":"true",className:"w-px h-5 bg-line mx-0.5"}),jsx(BubbleButton,{label:"\u0643\u0648\u062F",onClick:()=>e.chain().focus().toggleCode().run(),isActive:e.isActive("code"),children:jsx(Code,{size:14})}),jsx(BubbleButton,{label:"\u062A\u0638\u0644\u064A\u0644",onClick:()=>e.chain().focus().toggleHighlight().run(),isActive:e.isActive("highlight"),children:jsx(Highlighter,{size:14})}),jsx("span",{"aria-hidden":"true",className:"w-px h-5 bg-line mx-0.5"}),jsx(BubbleButton,{label:"\u0631\u0627\u0628\u0637",isActive:e.isActive("link"),onClick:()=>{const previous=e.getAttributes("link").href||"";const url=window.prompt("\u0631\u0627\u0628\u0637",previous);if(url===null)return;const chain=e.chain().focus().extendMarkRange("link");if(url==="")chain.unsetLink().run();else chain.setLink({href:/^https?:\/\//i.test(url)?url:`https://${url}`}).run()},children:jsx(Link2,{size:14})})]})})}import{useEffect as useEffect2,useRef as useRef3,useState as useState4}from"react";import{useCurrentEditor as useCurrentEditor5}from"@tiptap/react";import{useEffect,useRef as useRef2,useState}from"react";import{jsx as jsx2,jsxs as jsxs2}from"react/jsx-runtime";function useDismiss(open,close){const ref=useRef2(null);useEffect(()=>{if(!open)return;function onDown(e){if(ref.current&&!ref.current.contains(e.target))close()}function onKey(e){if(e.key==="Escape")close()}document.addEventListener("mousedown",onDown);document.addEventListener("keydown",onKey);return()=>{document.removeEventListener("mousedown",onDown);document.removeEventListener("keydown",onKey)}},[open,close]);return ref}var PANEL="absolute z-50 top-[calc(100%+6px)] start-0 bg-surface border border-line rounded-card shadow-panel overflow-clip animate-[fade-in_.14s_ease-out]";function Popover({trigger,children,width,className}){const[open,setOpen]=useState(false);const ref=useDismiss(open,()=>setOpen(false));return jsxs2("div",{ref,className:cn("relative flex",className),children:[trigger({open,toggle:()=>setOpen(v=>!v)}),open&&jsx2("div",{className:cn(PANEL,width??"w-56"),children:children({close:()=>setOpen(false)})})]})}function MenuItem({onClick,icon,children,danger,active}){return jsxs2("button",{type:"button",onClick,className:cn("w-full px-3 py-2 flex items-center gap-2.5 text-start text-ui cursor-pointer transition-colors",danger?"text-red hover:bg-red-bg":"text-ink2 hover:bg-hover",active&&"bg-soft text-brand-ink font-bold"),children:[icon,jsx2("span",{className:"flex-1 min-w-0 truncate",children})]})}function MenuSeparator(){return jsx2("span",{"aria-hidden":"true",className:"block h-px bg-line my-1"})}function ToolbarButton({onClick,isActive,disabled,tooltip,shortcut,children}){return jsx2(Tooltip,{content:jsxs2("span",{className:"flex items-center gap-2",children:[tooltip,shortcut&&jsx2("kbd",{dir:"ltr",className:"px-1 py-px rounded-xs bg-white/15 text-micro font-mono",children:shortcut})]}),children:jsx2("button",{type:"button",onClick,disabled,"aria-label":tooltip,"aria-pressed":isActive,className:cn("size-8 rounded-sm inline-flex items-center justify-center shrink-0 cursor-pointer transition-colors","focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-brand","disabled:opacity-40 disabled:cursor-not-allowed",isActive?"bg-soft text-brand-ink":"text-muted hover:bg-hover hover:text-ink"),children})})}function ToolbarGroup({children}){return jsx2("div",{className:"flex items-center gap-0.5 pe-1 me-1 border-e border-line last:border-e-0 last:pe-0 last:me-0",children})}function ColorGrid({colors,current,onPick,onClear,clearLabel,fallback}){return jsxs2("div",{className:"p-3 flex flex-col gap-2.5",children:[jsx2("div",{className:"grid grid-cols-4 gap-1.5",children:colors.map(color=>jsx2("button",{type:"button",onClick:()=>onPick(color),"aria-label":color,style:{background:color},className:cn("size-8 rounded-sm border cursor-pointer transition-transform hover:scale-110",current.toLowerCase()===color.toLowerCase()?"border-ink ring-2 ring-brand":"border-line")},color))}),jsxs2("div",{className:"flex items-center gap-2.5 pt-2.5 border-t border-line",children:[jsx2("input",{type:"color",value:current||fallback,onChange:e=>onPick(e.target.value),"aria-label":"\u0644\u0648\u0646 \u0645\u062E\u0635\u0651\u0635",className:"size-8 p-0 border-none bg-transparent cursor-pointer"}),jsx2("button",{type:"button",onClick:onClear,className:"text-caption text-muted hover:text-ink cursor-pointer transition-colors",children:clearLabel})]})]})}import{useCurrentEditor as useCurrentEditor2}from"@tiptap/react";import{AlignCenter,AlignLeft,AlignRight,Bold as BoldIcon,Code as CodeIcon,Eraser,Italic as ItalicIcon,List,ListOrdered,Minus,Quote,Redo,Strikethrough as StrikeIcon,Underline as UnderlineIcon,Undo}from"lucide-react";import{Fragment,jsx as jsx3,jsxs as jsxs3}from"react/jsx-runtime";function Bold2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleBold().run(),isActive:editor.isActive("bold"),tooltip:"\u0639\u0631\u064A\u0636",shortcut:"Ctrl+B",children:jsx3(BoldIcon,{size:16})})}function Italic2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleItalic().run(),isActive:editor.isActive("italic"),tooltip:"\u0645\u0627\u0626\u0644",shortcut:"Ctrl+I",children:jsx3(ItalicIcon,{size:16})})}function Underline2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleUnderline().run(),isActive:editor.isActive("underline"),tooltip:"\u062A\u062D\u062A\u0647 \u062E\u0637",shortcut:"Ctrl+U",children:jsx3(UnderlineIcon,{size:16})})}function Strikethrough2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleStrike().run(),isActive:editor.isActive("strike"),tooltip:"\u064A\u062A\u0634\u0637\u0628",shortcut:"Ctrl+Shift+S",children:jsx3(StrikeIcon,{size:16})})}function Code2(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleCode().run(),isActive:editor.isActive("code"),tooltip:"\u0643\u0648\u062F",shortcut:"Ctrl+E",children:jsx3(CodeIcon,{size:16})})}function BulletList(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleBulletList().run(),isActive:editor.isActive("bulletList"),tooltip:"\u0642\u0627\u0626\u0645\u0629 \u0646\u0642\u0637\u064A\u0629",shortcut:"Ctrl+Shift+8",children:jsx3(List,{size:16})})}function OrderedList(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleOrderedList().run(),isActive:editor.isActive("orderedList"),tooltip:"\u0642\u0627\u0626\u0645\u0629 \u0645\u0631\u0642\u0651\u0645\u0629",shortcut:"Ctrl+Shift+7",children:jsx3(ListOrdered,{size:16})})}function BlockQuote(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().toggleBlockquote().run(),isActive:editor.isActive("blockquote"),tooltip:"\u0627\u0642\u062A\u0628\u0627\u0633",shortcut:"Ctrl+Shift+B",children:jsx3(Quote,{size:16})})}function HorizontalRule(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().setHorizontalRule().run(),tooltip:"\u0641\u0627\u0635\u0644 \u0623\u0641\u0642\u064A",children:jsx3(Minus,{size:16})})}function ClearMarks(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().unsetAllMarks().run(),tooltip:"\u0645\u0633\u062D \u0627\u0644\u062A\u0646\u0633\u064A\u0642",children:jsx3(Eraser,{size:16})})}function UndoRedo(){const{editor}=useCurrentEditor2();if(!editor)return null;return jsxs3(Fragment,{children:[jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().undo().run(),disabled:!editor.can().chain().focus().undo().run(),tooltip:"\u062A\u0631\u0627\u062C\u0639",shortcut:"Ctrl+Z",children:jsx3(Undo,{size:16})}),jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().redo().run(),disabled:!editor.can().chain().focus().redo().run(),tooltip:"\u0625\u0639\u0627\u062F\u0629",shortcut:"Ctrl+Y",children:jsx3(Redo,{size:16})})]})}function Alignment(){const{editor}=useCurrentEditor2();if(!editor)return null;const items=[{key:"right",tooltip:"\u0645\u062D\u0627\u0630\u0627\u0629 \u064A\u0645\u064A\u0646",Icon:AlignRight},{key:"center",tooltip:"\u062A\u0648\u0633\u064A\u0637",Icon:AlignCenter},{key:"left",tooltip:"\u0645\u062D\u0627\u0630\u0627\u0629 \u0634\u0645\u0627\u0644",Icon:AlignLeft}];return jsx3(Fragment,{children:items.map(({key,tooltip,Icon})=>jsx3(ToolbarButton,{onClick:()=>editor.chain().focus().setTextAlign(key).run(),isActive:editor.isActive({textAlign:key}),disabled:!editor.can().chain().focus().setTextAlign(key).run(),tooltip,children:jsx3(Icon,{size:16})},key))})}function CharacterCount({maxChars}){const{editor}=useCurrentEditor2();if(!editor)return null;const chars=editor.storage.characterCount?.characters()??0;const words=editor.storage.characterCount?.words()??0;const over=maxChars?chars>maxChars:false;const near=maxChars?chars>maxChars*.9:false;return jsxs3("span",{className:cn("flex items-center gap-2 text-caption select-none",over?"text-red font-bold":near?"text-amber-ink font-bold":"text-muted2"),children:[jsxs3("span",{"data-num":true,children:[chars,maxChars?`/${maxChars}`:""," \u062D\u0631\u0641"]}),jsx3("span",{"aria-hidden":"true",className:"text-line",children:"|"}),jsxs3("span",{"data-num":true,children:[words," \u0643\u0644\u0645\u0629"]})]})}import{useState as useState2}from"react";import{useCurrentEditor as useCurrentEditor3}from"@tiptap/react";import{CalendarClock,ChevronDown,Columns,Highlighter as Highlighter2,Image as ImageIcon,Link2 as Link22,Merge,Palette,Plus,Rows,Split,Table as TableIcon,Trash2}from"lucide-react";import{Fragment as Fragment2,jsx as jsx4,jsxs as jsxs4}from"react/jsx-runtime";var HEADINGS=[{level:0,label:"\u0646\u0635 \u0639\u0627\u062F\u064A",size:"text-body"},{level:1,label:"\u0639\u0646\u0648\u0627\u0646 \u0661",size:"text-h2"},{level:2,label:"\u0639\u0646\u0648\u0627\u0646 \u0662",size:"text-h3"},{level:3,label:"\u0639\u0646\u0648\u0627\u0646 \u0663",size:"text-h4"},{level:4,label:"\u0639\u0646\u0648\u0627\u0646 \u0664",size:"text-lead"},{level:5,label:"\u0639\u0646\u0648\u0627\u0646 \u0665",size:"text-body"},{level:6,label:"\u0639\u0646\u0648\u0627\u0646 \u0666",size:"text-ui"}];function HeadingSelector(){const{editor}=useCurrentEditor3();if(!editor)return null;const current=HEADINGS.find(h=>h.level===0?editor.isActive("paragraph"):editor.isActive("heading",{level:h.level}))??HEADINGS[0];return jsx4(Popover,{width:"w-48",trigger:({open,toggle})=>jsxs4("button",{type:"button",onClick:toggle,"aria-haspopup":"menu","aria-expanded":open,className:cn("h-8 px-2.5 rounded-sm inline-flex items-center gap-1.5 text-ui font-bold cursor-pointer transition-colors","focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-brand",open?"bg-soft text-brand-ink":"text-ink2 hover:bg-hover"),children:[jsx4("span",{className:"truncate max-w-24",children:current.label}),jsx4(ChevronDown,{size:14,className:cn("shrink-0 transition-transform",open&&"rotate-180")})]}),children:({close})=>jsx4("div",{role:"menu",className:"py-1",children:HEADINGS.map(h=>{const active=h.level===0?editor.isActive("paragraph"):editor.isActive("heading",{level:h.level});return jsx4("button",{type:"button",role:"menuitem",onClick:()=>{if(h.level===0)editor.chain().focus().setParagraph().run();else editor.chain().focus().toggleHeading({level:h.level}).run();close()},className:cn("w-full px-3 py-2 flex items-center justify-between gap-3 text-start cursor-pointer transition-colors",active?"bg-soft text-brand-ink":"text-ink2 hover:bg-hover"),children:jsx4("span",{className:cn(h.size,active?"font-extrabold":"font-bold"),children:h.label})},h.level)})})})}function normalizeUrl(url){const t=url.trim();if(!t)return"";if(/^(https?:\/\/|mailto:|#)/i.test(t))return t;return`https://${t}`}function Link(){const{editor}=useCurrentEditor3();const[open,setOpen]=useState2(false);const[url,setUrl]=useState2("");if(!editor)return null;function apply(){const chain=editor.chain().focus().extendMarkRange("link");if(url.trim()==="")chain.unsetLink().run();else chain.setLink({href:normalizeUrl(url)}).run();setOpen(false)}return jsxs4(Fragment2,{children:[jsx4(ToolbarButton,{onClick:()=>{setUrl(editor.getAttributes("link").href||"");setOpen(true)},isActive:editor.isActive("link"),tooltip:"\u0631\u0627\u0628\u0637",shortcut:"Ctrl+K",children:jsx4(Link22,{size:16})}),jsx4(Modal,{open,onClose:()=>setOpen(false),title:"\u0625\u0636\u0627\u0641\u0629 \u0631\u0627\u0628\u0637",description:"\u0633\u064A\u0628\u0647 \u0641\u0627\u0636\u064A \u0648\u0627\u0645\u0633\u062D \u0639\u0634\u0627\u0646 \u062A\u0634\u064A\u0644 \u0627\u0644\u0631\u0627\u0628\u0637.",size:"sm",footer:jsxs4(Fragment2,{children:[jsx4(Button,{variant:"outline",onClick:()=>setOpen(false),children:"\u0625\u0644\u063A\u0627\u0621"}),jsx4(Button,{onClick:apply,children:url.trim()?"\u0623\u0636\u0641":"\u0634\u064A\u0644 \u0627\u0644\u0631\u0627\u0628\u0637"})]}),children:jsx4(Input,{label:"\u0627\u0644\u0639\u0646\u0648\u0627\u0646",dir:"ltr",placeholder:"example.com",value:url,onChange:e=>setUrl(e.target.value),onKeyDown:e=>e.key==="Enter"&&apply()})})]})}function ImageTool({onPick}){const{editor}=useCurrentEditor3();const[open,setOpen]=useState2(false);const[src,setSrc]=useState2("");if(!editor)return null;const insert=url=>editor.chain().focus().setImage({src:url}).run();return jsxs4(Fragment2,{children:[jsx4(ToolbarButton,{onClick:()=>onPick?onPick(insert):setOpen(true),isActive:editor.isActive("image"),tooltip:"\u0635\u0648\u0631\u0629",children:jsx4(ImageIcon,{size:16})}),!onPick&&jsx4(Modal,{open,onClose:()=>setOpen(false),title:"\u0625\u062F\u0631\u0627\u062C \u0635\u0648\u0631\u0629",size:"sm",footer:jsxs4(Fragment2,{children:[jsx4(Button,{variant:"outline",onClick:()=>setOpen(false),children:"\u0625\u0644\u063A\u0627\u0621"}),jsx4(Button,{disabled:!src.trim(),onClick:()=>{insert(src.trim());setSrc("");setOpen(false)},children:"\u0623\u062F\u0631\u062C"})]}),children:jsx4(Input,{label:"\u0631\u0627\u0628\u0637 \u0627\u0644\u0635\u0648\u0631\u0629",dir:"ltr",placeholder:"https://\u2026",value:src,onChange:e=>setSrc(e.target.value),hint:"\u0648\u062A\u0642\u062F\u0631 \u0643\u0645\u0627\u0646 \u062A\u0633\u062D\u0628 \u0635\u0648\u0631\u0629 \u0648\u062A\u0641\u0644\u062A\u0647\u0627 \u062C\u0648\u0651\u0647 \u0627\u0644\u0645\u062D\u0631\u0631 \u0645\u0628\u0627\u0634\u0631\u0629\u064B."})})]})}function TableTool(){const{editor}=useCurrentEditor3();if(!editor)return null;const inTable=editor.isActive("table");return jsx4(Popover,{width:"w-56",trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:inTable||open,tooltip:"\u062C\u062F\u0648\u0644",children:jsx4(TableIcon,{size:16})}),children:({close})=>{const run=fn=>()=>{fn();close()};return jsxs4("div",{role:"menu",className:"py-1",children:[jsx4(MenuItem,{icon:jsx4(Plus,{size:14}),onClick:run(()=>editor.chain().focus().insertTable({rows:3,cols:3,withHeaderRow:true}).run()),children:"\u0623\u062F\u0631\u062C \u062C\u062F\u0648\u0644 \u0663\xD7\u0663"}),inTable&&jsxs4(Fragment2,{children:[jsx4(MenuSeparator,{}),jsx4(MenuItem,{icon:jsx4(Rows,{size:14}),onClick:run(()=>editor.chain().focus().addRowBefore().run()),children:"\u0635\u0641 \u0642\u0628\u0644"}),jsx4(MenuItem,{icon:jsx4(Rows,{size:14}),onClick:run(()=>editor.chain().focus().addRowAfter().run()),children:"\u0635\u0641 \u0628\u0639\u062F"}),jsx4(MenuItem,{danger:true,icon:jsx4(Trash2,{size:14}),onClick:run(()=>editor.chain().focus().deleteRow().run()),children:"\u0627\u062D\u0630\u0641 \u0627\u0644\u0635\u0641"}),jsx4(MenuSeparator,{}),jsx4(MenuItem,{icon:jsx4(Columns,{size:14}),onClick:run(()=>editor.chain().focus().addColumnBefore().run()),children:"\u0639\u0645\u0648\u062F \u0642\u0628\u0644"}),jsx4(MenuItem,{icon:jsx4(Columns,{size:14}),onClick:run(()=>editor.chain().focus().addColumnAfter().run()),children:"\u0639\u0645\u0648\u062F \u0628\u0639\u062F"}),jsx4(MenuItem,{danger:true,icon:jsx4(Trash2,{size:14}),onClick:run(()=>editor.chain().focus().deleteColumn().run()),children:"\u0627\u062D\u0630\u0641 \u0627\u0644\u0639\u0645\u0648\u062F"}),jsx4(MenuSeparator,{}),jsx4(MenuItem,{icon:jsx4(Merge,{size:14}),onClick:run(()=>editor.chain().focus().mergeCells().run()),children:"\u0627\u062F\u0645\u062C \u0627\u0644\u062E\u0644\u0627\u064A\u0627"}),jsx4(MenuItem,{icon:jsx4(Split,{size:14}),onClick:run(()=>editor.chain().focus().splitCell().run()),children:"\u0627\u0642\u0633\u0645 \u0627\u0644\u062E\u0644\u064A\u0629"}),jsx4(MenuSeparator,{}),jsx4(MenuItem,{danger:true,icon:jsx4(Trash2,{size:14}),onClick:run(()=>editor.chain().focus().deleteTable().run()),children:"\u0627\u062D\u0630\u0641 \u0627\u0644\u062C\u062F\u0648\u0644"})]})]})}})}var TEXT_COLORS=["#000000","#434343","#666666","#999999","#E03131","#C2255C","#9C36B5","#6741D9","#3B5BDB","#1971C2","#0C8599","#099268","#2F9E44","#66A80F","#F08C00","#E8590C"];var HIGHLIGHT_COLORS=["#FBBF24","#F87171","#FB923C","#A78BFA","#60A5FA","#34D399","#F472B6","#2DD4BF","#FCD34D","#FCA5A5","#FDBA74","#C4B5FD","#93C5FD","#6EE7B7","#F9A8D4","#99F6E4"];function ColorTool(){const{editor}=useCurrentEditor3();if(!editor)return null;const current=editor.getAttributes("textStyle").color||"";return jsx4(Popover,{trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:open,tooltip:"\u0644\u0648\u0646 \u0627\u0644\u0646\u0635",children:jsxs4("span",{className:"flex flex-col items-center gap-0.5",children:[jsx4(Palette,{size:16,style:current?{color:current}:void 0}),jsx4("span",{"aria-hidden":"true",className:"w-4 h-0.5 rounded-full",style:{background:current||"currentColor"}})]})}),children:({close})=>jsx4(ColorGrid,{colors:TEXT_COLORS,current,fallback:"#000000",clearLabel:"\u0634\u064A\u0644 \u0627\u0644\u0644\u0648\u0646",onPick:c=>{editor.chain().focus().setColor(c).run();close()},onClear:()=>{editor.chain().focus().unsetColor().run();close()}})})}function HighlightTool(){const{editor}=useCurrentEditor3();if(!editor)return null;const current=editor.getAttributes("highlight").color||"";return jsx4(Popover,{trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:editor.isActive("highlight")||open,tooltip:"\u062A\u0638\u0644\u064A\u0644",children:jsxs4("span",{className:"flex flex-col items-center gap-0.5",children:[jsx4(Highlighter2,{size:16}),jsx4("span",{"aria-hidden":"true",className:"w-4 h-0.5 rounded-full",style:{background:current||"transparent"}})]})}),children:({close})=>jsx4(ColorGrid,{colors:HIGHLIGHT_COLORS,current,fallback:"#FBBF24",clearLabel:"\u0634\u064A\u0644 \u0627\u0644\u062A\u0638\u0644\u064A\u0644",onPick:c=>{editor.chain().focus().toggleHighlight({color:c}).run();close()},onClear:()=>{editor.chain().focus().unsetHighlight().run();close()}})})}var DATE_FORMATS=[{label:"\u0663\u0661 \u064A\u0648\u0644\u064A\u0648 \u0662\u0660\u0662\u0666",opts:{day:"numeric",month:"long",year:"numeric"}},{label:"\u0663\u0661 \u064A\u0648\u0644 \u0662\u0660\u0662\u0666",opts:{day:"numeric",month:"short",year:"numeric"}},{label:"\u0627\u0644\u062C\u0645\u0639\u0629\u060C \u0663\u0661 \u064A\u0648\u0644\u064A\u0648",opts:{weekday:"long",day:"numeric",month:"long"}},{label:"\u0662\u0660\u0662\u0666/\u0660\u0667/\u0663\u0661",opts:{year:"numeric",month:"2-digit",day:"2-digit"}},{label:"\u0660\u0662:\u0665\u0661 \u0635",opts:{hour:"2-digit",minute:"2-digit"}},{label:"\u0660\u0662:\u0665\u0661:\u0663\u0660 \u0635",opts:{hour:"2-digit",minute:"2-digit",second:"2-digit"}}];function DateTime({locale="ar-EG"}){const{editor}=useCurrentEditor3();if(!editor)return null;return jsx4(Popover,{width:"w-56",trigger:({open,toggle})=>jsx4(ToolbarButton,{onClick:toggle,isActive:open,tooltip:"\u062A\u0627\u0631\u064A\u062E \u0648\u0648\u0642\u062A",children:jsx4(CalendarClock,{size:16})}),children:({close})=>jsx4("div",{role:"menu",className:"py-1",children:DATE_FORMATS.map(f=>{const text=new Intl.DateTimeFormat(locale,f.opts).format(new Date);return jsx4(MenuItem,{onClick:()=>{editor.chain().focus().insertContent(text).run();close()},children:text},f.label)})})})}import{useCallback as useCallback2,useState as useState3}from"react";import{useCurrentEditor as useCurrentEditor4}from"@tiptap/react";import{ChevronDown as ChevronDown2,ChevronUp,Replace,Search}from"lucide-react";import{Fragment as Fragment3,jsx as jsx5,jsxs as jsxs5}from"react/jsx-runtime";function FindReplace(){const{editor}=useCurrentEditor4();const[term,setTerm]=useState3("");const[replacement,setReplacement]=useState3("");const[matches,setMatches]=useState3([]);const[index,setIndex]=useState3(0);const jump=useCallback2(m=>editor?.chain().setTextSelection(m).scrollIntoView().run(),[editor]);const find=useCallback2(value=>{if(!editor||!value.trim()){setMatches([]);setIndex(0);return}const found=[];const needle=value.toLowerCase();editor.state.doc.descendants((node,pos)=>{if(!node.isText)return;const text=node.text?.toLowerCase()??"";let at=text.indexOf(needle);while(at!==-1){found.push({from:pos+at,to:pos+at+value.length});at=text.indexOf(needle,at+1)}});setMatches(found);setIndex(0);if(found[0])jump(found[0])},[editor,jump]);if(!editor)return null;const step=by=>{if(matches.length===0)return;const next=(index+by+matches.length)%matches.length;setIndex(next);jump(matches[next])};const replaceOne=()=>{const m=matches[index];if(!m)return;editor.chain().focus().setTextSelection(m).insertContent(replacement).run();find(term)};const replaceAll=()=>{if(matches.length===0)return;const chain=editor.chain().focus();for(const m of[...matches].sort((a,b)=>b.from-a.from)){chain.setTextSelection(m).insertContent(replacement)}chain.run();find(term)};return jsx5(Popover,{width:"w-72",trigger:({open,toggle})=>jsx5(ToolbarButton,{onClick:toggle,isActive:open,tooltip:"\u0628\u062D\u062B \u0648\u0627\u0633\u062A\u0628\u062F\u0627\u0644",shortcut:"Ctrl+H",children:jsx5(Search,{size:16})}),children:()=>jsxs5("div",{className:"p-3 flex flex-col gap-2.5",children:[jsxs5("div",{className:"flex items-end gap-1.5",children:[jsx5(Input,{autoFocus:true,size:"sm",label:"\u0627\u0628\u062D\u062B \u0639\u0646",hideLabel:true,placeholder:"\u0627\u0628\u062D\u062B \u0639\u0646\u2026",value:term,wrapperClassName:"flex-1 min-w-0",onChange:e=>{setTerm(e.target.value);find(e.target.value)},onKeyDown:e=>{if(e.key!=="Enter")return;e.preventDefault();step(e.shiftKey?-1:1)}}),jsx5(Button,{size:"sm",variant:"outline",iconOnly:true,"aria-label":"\u0627\u0644\u0633\u0627\u0628\u0642",disabled:matches.length===0,onClick:()=>step(-1),icon:jsx5(ChevronUp,{size:14})}),jsx5(Button,{size:"sm",variant:"outline",iconOnly:true,"aria-label":"\u0627\u0644\u062A\u0627\u0644\u064A",disabled:matches.length===0,onClick:()=>step(1),icon:jsx5(ChevronDown2,{size:14})})]}),term.trim()&&jsx5("span",{className:"text-micro text-muted2","aria-live":"polite",children:matches.length>0?jsxs5(Fragment3,{children:[jsx5("span",{"data-num":true,children:index+1})," \u0645\u0646 ",jsx5("span",{"data-num":true,children:matches.length})]}):"\u0645\u0627\u0641\u064A\u0634 \u0646\u062A\u0627\u064A\u062C"}),jsxs5("div",{className:"flex items-end gap-1.5",children:[jsx5(Input,{size:"sm",label:"\u0627\u0633\u062A\u0628\u062F\u0644 \u0628\u0640",hideLabel:true,placeholder:"\u0627\u0633\u062A\u0628\u062F\u0644 \u0628\u0640\u2026",value:replacement,wrapperClassName:"flex-1 min-w-0",onChange:e=>setReplacement(e.target.value),onKeyDown:e=>{if(e.key==="Enter"){e.preventDefault();replaceOne()}}}),jsx5(Button,{size:"sm",variant:"outline",iconOnly:true,"aria-label":"\u0627\u0633\u062A\u0628\u062F\u0644",disabled:matches.length===0,onClick:replaceOne,icon:jsx5(Replace,{size:14})})]}),jsx5(Button,{size:"sm",variant:"soft",block:true,disabled:matches.length===0,onClick:replaceAll,children:"\u0627\u0633\u062A\u0628\u062F\u0644 \u0627\u0644\u0643\u0644"})]})})}import{jsx as jsx6,jsxs as jsxs6}from"react/jsx-runtime";function useEditorTick(){const[,setTick]=useState4(0);const{editor}=useCurrentEditor5();const raf=useRef3(0);useEffect2(()=>{if(!editor)return;const bump=()=>{cancelAnimationFrame(raf.current);raf.current=requestAnimationFrame(()=>setTick(t=>t+1))};editor.on("selectionUpdate",bump);editor.on("transaction",bump);return()=>{cancelAnimationFrame(raf.current);editor.off("selectionUpdate",bump);editor.off("transaction",bump)}},[editor])}function Toolbar({basic,onPickImage,hideImage,locale}){useEditorTick();const{editor}=useCurrentEditor5();if(!editor)return null;if(basic){return jsxs6("div",{className:"w-full border-b border-line px-1.5 py-1 flex flex-wrap items-center gap-0.5",children:[jsx6(ToolbarGroup,{children:jsx6(UndoRedo,{})}),jsx6(ToolbarGroup,{children:jsx6(HeadingSelector,{})}),jsxs6(ToolbarGroup,{children:[jsx6(Bold2,{}),jsx6(Italic2,{}),jsx6(Underline2,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(BulletList,{}),jsx6(OrderedList,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(Link,{}),!hideImage&&jsx6(ImageTool,{onPick:onPickImage}),jsx6(ColorTool,{})]})]})}return jsxs6("div",{className:"w-full border-b border-line px-1.5 py-1.5 flex flex-wrap items-center gap-y-1",children:[jsx6(ToolbarGroup,{children:jsx6(UndoRedo,{})}),jsx6(ToolbarGroup,{children:jsx6(HeadingSelector,{})}),jsxs6(ToolbarGroup,{children:[jsx6(Bold2,{}),jsx6(Italic2,{}),jsx6(Underline2,{}),jsx6(Strikethrough2,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(BulletList,{}),jsx6(OrderedList,{}),jsx6(BlockQuote,{})]}),jsx6(ToolbarGroup,{children:jsx6(Alignment,{})}),jsxs6(ToolbarGroup,{children:[jsx6(Link,{}),!hideImage&&jsx6(ImageTool,{onPick:onPickImage}),jsx6(TableTool,{}),jsx6(DateTime,{locale})]}),jsxs6(ToolbarGroup,{children:[jsx6(ColorTool,{}),jsx6(HighlightTool,{})]}),jsxs6(ToolbarGroup,{children:[jsx6(Code2,{}),jsx6(HorizontalRule,{}),jsx6(ClearMarks,{}),jsx6(FindReplace,{})]})]})}function EditorFooter({maxChars}){return jsx6("div",{className:"border-t border-line px-3 py-1.5 flex justify-end",children:jsx6(CharacterCount,{maxChars})})}import{forwardRef,useEffect as useEffect3,useImperativeHandle,useState as useState5}from"react";import{Extension}from"@tiptap/core";import{PluginKey as PluginKey2}from"@tiptap/pm/state";import{ReactRenderer}from"@tiptap/react";import Suggestion from"@tiptap/suggestion";import{jsx as jsx7,jsxs as jsxs7}from"react/jsx-runtime";var SLASH_ITEMS=[{title:"\u0639\u0646\u0648\u0627\u0646 \u0643\u0628\u064A\u0631",hint:"H1",icon:"H1",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHeading({level:1}).run()},{title:"\u0639\u0646\u0648\u0627\u0646 \u0645\u062A\u0648\u0633\u0637",hint:"H2",icon:"H2",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHeading({level:2}).run()},{title:"\u0639\u0646\u0648\u0627\u0646 \u0635\u063A\u064A\u0631",hint:"H3",icon:"H3",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHeading({level:3}).run()},{title:"\u0642\u0627\u0626\u0645\u0629 \u0646\u0642\u0637\u064A\u0629",icon:"\u2022",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleBulletList().run()},{title:"\u0642\u0627\u0626\u0645\u0629 \u0645\u0631\u0642\u0651\u0645\u0629",icon:"\u0661.",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleOrderedList().run()},{title:"\u0627\u0642\u062A\u0628\u0627\u0633",icon:"\u275D",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleBlockquote().run()},{title:"\u0628\u0644\u0648\u0643 \u0643\u0648\u062F",icon:"</>",command:({editor,range})=>editor.chain().focus().deleteRange(range).toggleCodeBlock().run()},{title:"\u062C\u062F\u0648\u0644",hint:"\u0663\xD7\u0663",icon:"\u229E",command:({editor,range})=>editor.chain().focus().deleteRange(range).insertTable({rows:3,cols:3,withHeaderRow:true}).run()},{title:"\u0641\u0627\u0635\u0644 \u0623\u0641\u0642\u064A",icon:"\u2500",command:({editor,range})=>editor.chain().focus().deleteRange(range).setHorizontalRule().run()}];var SlashList=forwardRef(function SlashList2({items,command},ref){const[active,setActive]=useState5(0);useEffect3(()=>setActive(0),[items]);useImperativeHandle(ref,()=>({onKeyDown:({event})=>{if(event.key==="ArrowUp"){setActive(i=>i<=0?items.length-1:i-1);return true}if(event.key==="ArrowDown"){setActive(i=>i>=items.length-1?0:i+1);return true}if(event.key==="Enter"){const item=items[active];if(item)command(item);return true}return false}}));if(items.length===0)return null;return jsx7("div",{className:"w-64 max-h-72 overflow-y-auto rounded-card border border-line bg-surface shadow-pop py-1 animate-[fade-in_.12s_ease-out]",children:items.map((item,i)=>jsxs7("button",{type:"button",onMouseEnter:()=>setActive(i),onClick:()=>command(item),className:cn("w-full px-3 py-2 flex items-center gap-3 text-start cursor-pointer transition-colors",i===active?"bg-soft text-brand-ink":"text-ink2 hover:bg-hover"),children:[jsx7("span",{"aria-hidden":"true",className:"size-7 shrink-0 rounded-sm bg-bg border border-line flex items-center justify-center text-micro font-extrabold",children:item.icon}),jsx7("span",{className:"flex-1 min-w-0 text-ui font-bold truncate",children:item.title}),item.hint&&jsx7("span",{dir:"ltr",className:"text-micro text-muted2 shrink-0",children:item.hint})]},item.title))})});var SlashCommandsPluginKey=new PluginKey2("qumraSlashCommands");var SlashCommands=Extension.create({name:"qumraSlashCommands",addOptions(){return{suggestion:{char:"/",pluginKey:SlashCommandsPluginKey,command:({editor,range,props})=>{props.command({editor,range})}}}},addProseMirrorPlugins(){return[Suggestion({editor:this.editor,...this.options.suggestion})]}});function place(el,rect){const rtl=getComputedStyle(document.documentElement).direction==="rtl";const gap=6;const{offsetHeight:h,offsetWidth:w}=el;const below=window.innerHeight-rect.bottom;const top=below<h+gap&&rect.top>h+gap?rect.top-h-gap:rect.bottom+gap;let left=rtl?rect.right-w:rect.left;left=Math.max(8,Math.min(left,window.innerWidth-w-8));el.style.top=`${top+window.scrollY}px`;el.style.left=`${left+window.scrollX}px`}function createSlashSuggestion(){return{items:({query})=>!query?SLASH_ITEMS:SLASH_ITEMS.filter(i=>i.title.includes(query)||i.icon.toLowerCase().includes(query.toLowerCase())),render:()=>{let component=null;let host=null;const reposition=clientRect=>{const rect=clientRect?.();if(host&&rect)place(host,rect)};return{onStart:props=>{component=new ReactRenderer(SlashList,{props,editor:props.editor});host=document.createElement("div");host.style.position="absolute";host.style.zIndex="60";host.appendChild(component.element);document.body.appendChild(host);reposition(props.clientRect)},onUpdate:props=>{component?.updateProps(props);reposition(props.clientRect)},onKeyDown:props=>{if(props.event.key==="Escape"){host?.remove();return true}const api=component?.ref;return api?.onKeyDown?.(props)??false},onExit:()=>{host?.remove();component?.destroy();host=null;component=null}}}}}import"react";import{mergeAttributes,Node,nodePasteRule}from"@tiptap/core";import{NodeViewWrapper,ReactNodeViewRenderer}from"@tiptap/react";import{jsx as jsx8}from"react/jsx-runtime";var TOKEN_SPAN_RE=/<span\b([^>]*)\bdata-token="([^"]+)"([^>]*)>([\s\S]*?)<\/span>/gi;var ENTITIES={"&":"&","<":"<",">":">",""":'"',"'":"'","'":"'"};function decode(s){return s.replace(/&(amp|lt|gt|quot|#39|apos);/g,m=>ENTITIES[m]??m)}function encode(s){return s.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}var MASK_OPEN="\uE000";var MASK_CLOSE="\uE001";var MASK_RE=/\uE000(\d+)\uE001/g;function fresh(re){return new RegExp(re.source,re.flags.includes("g")?re.flags:`${re.flags}g`)}function wrapTokens(html,pattern){if(!html)return html;const masked=[];const safe=html.replace(TOKEN_SPAN_RE,full=>{const i=masked.push(full)-1;return`${MASK_OPEN}${i}${MASK_CLOSE}`});const wrapped=safe.replace(fresh(pattern),raw=>`<span data-token="${encode(raw)}"></span>`);return wrapped.replace(MASK_RE,(_,i)=>masked[Number(i)])}function textToTokenHtml(text,pattern){if(!text)return"<p></p>";let out="";let cursor=0;for(const m of text.matchAll(fresh(pattern))){const at=m.index??0;if(at>cursor)out+=encode(text.slice(cursor,at));out+=`<span data-token="${encode(m[0])}"></span>`;cursor=at+m[0].length}if(cursor<text.length)out+=encode(text.slice(cursor));return`<p>${out}</p>`}function unwrapTokens(html){if(!html)return html;return html.replace(TOKEN_SPAN_RE,(_,_pre,attr)=>decode(attr))}function createTokenNode({pattern,render}){return Node.create({name:"qumraToken",group:"inline",inline:true,atom:true,selectable:true,addAttributes(){return{raw:{default:"",parseHTML:el=>el.getAttribute("data-token")??"",renderHTML:attrs=>attrs.raw?{"data-token":String(attrs.raw)}:{}}}},parseHTML(){return[{tag:"span[data-token]"}]},renderHTML({HTMLAttributes}){return["span",mergeAttributes({class:"qumra-token"},HTMLAttributes)]},renderText({node}){return String(node.attrs.raw??"")},addNodeView(){return ReactNodeViewRenderer(props=>jsx8(NodeViewWrapper,{as:"span",className:"qumra-token","data-drag-handle":void 0,children:render(String(props.node.attrs.raw??""))}))},addPasteRules(){return[nodePasteRule({find:fresh(pattern),type:this.type,getAttributes:match=>({raw:match[0]})})]}})}import{jsx as jsx9,jsxs as jsxs8}from"react/jsx-runtime";function Editor({content,onChange,placeholder,maxChars,basic,disabled,onPickImage,hideImage,locale="ar-EG",tokens,className}){const extensions=useMemo2(()=>[...contentExtensions(),Placeholder.configure({placeholder:placeholder??""}),CharacterCount2.configure(maxChars?{limit:maxChars}:{}),SlashCommands.configure({suggestion:createSlashSuggestion()}),...tokens?[createTokenNode(tokens)]:[]],[placeholder,maxChars,tokens]);const lastEmitted=useRef4("");const[initialContent]=useState6(()=>tokens?wrapTokens(content||"",tokens.pattern):content||"");const editorProps=useMemo2(()=>({attributes:{class:"qumra-tiptap",dir:"auto"},handleDrop:(view,event,_slice,moved)=>{if(moved||!event.dataTransfer?.files?.length)return false;const file=event.dataTransfer.files[0];if(!file?.type.startsWith("image/"))return false;const reader=new FileReader;reader.onload=()=>{const at=view.posAtCoords({left:event.clientX,top:event.clientY});if(!at)return;const node=view.state.schema.nodes.image.create({src:reader.result});view.dispatch(view.state.tr.insert(at.pos,node))};reader.readAsDataURL(file);return true},handlePaste:(view,event)=>{const items=event.clipboardData?.items;if(!items)return false;for(const item of Array.from(items)){if(!item.type.startsWith("image/"))continue;const file=item.getAsFile();if(!file)continue;const reader=new FileReader;reader.onload=()=>{const node=view.state.schema.nodes.image.create({src:reader.result});view.dispatch(view.state.tr.insert(view.state.selection.from,node))};reader.readAsDataURL(file);return true}return false}}),[]);const handleUpdate=({editor})=>{const html=tokens?unwrapTokens(editor.getHTML()):editor.getHTML();if(html===lastEmitted.current)return;lastEmitted.current=html;onChange(html)};return jsx9("div",{className:cn("relative","bg-surface border border-border rounded-field","focus-within:border-brand transition-colors","[&>*:first-child]:rounded-t-field",disabled&&"opacity-60 pointer-events-none",className),children:jsxs8(EditorProvider,{immediatelyRender:false,extensions,content:initialContent,onUpdate:handleUpdate,slotBefore:!disabled&&jsx9(Toolbar,{basic,onPickImage,hideImage,locale}),slotAfter:!disabled&&jsx9(EditorFooter,{maxChars}),editorProps,children:[jsx9(EditorBubbleMenu,{}),jsx9(SyncContent,{content,disabled,lastEmitted,tokens})]})})}function SyncContent({content,disabled,lastEmitted,tokens}){const{editor}=useCurrentEditor6();useEffect4(()=>{if(!editor)return;const incoming=content||"";const current=tokens?unwrapTokens(editor.getHTML()):editor.getHTML();if(incoming!==current){editor.commands.setContent(tokens?wrapTokens(incoming,tokens.pattern):incoming,{emitUpdate:false});lastEmitted.current=tokens?unwrapTokens(editor.getHTML()):editor.getHTML()}if(editor.isEditable===Boolean(disabled)){editor.setEditable(!disabled,false)}},[content,disabled,editor,lastEmitted,tokens]);return null}import{generateHTML,generateJSON}from"@tiptap/core";function emptyDoc(){return{type:"doc",content:[{type:"paragraph"}]}}function htmlToDoc(html){try{return generateJSON(html?.trim()?html:"<p></p>",contentExtensions())}catch{return emptyDoc()}}function docToHtml(doc){if(!isDoc(doc))return"";try{return generateHTML(doc,contentExtensions())}catch{return""}}function isDoc(value){return!!value&&typeof value==="object"&&!Array.isArray(value)&&value.type==="doc"}import{useEffect as useEffect5,useMemo as useMemo3,useRef as useRef5,useState as useState7}from"react";import{Extension as Extension2,Node as Node2}from"@tiptap/core";import{EditorContent,useEditor}from"@tiptap/react";import{Placeholder as Placeholder2}from"@tiptap/extension-placeholder";import{jsx as jsx10}from"react/jsx-runtime";var SIZES={sm:"min-h-9 text-ui px-3",md:"min-h-11 text-body px-3.5"};var Doc=Node2.create({name:"doc",topNode:true,content:"paragraph"});var Para=Node2.create({name:"paragraph",group:"block",content:"inline*",parseHTML:()=>[{tag:"p"}],renderHTML:()=>["p",0]});var Txt=Node2.create({name:"text",group:"inline"});var SingleLine=Extension2.create({name:"qumraSingleLine",addKeyboardShortcuts(){return{Enter:()=>true,"Shift-Enter":()=>true}}});function TokenInput({value,onChange,tokens,placeholder,disabled,size="md",className,"aria-labelledby":labelledBy}){const extensions=useMemo3(()=>[Doc,Para,Txt,SingleLine,Placeholder2.configure({placeholder:placeholder??""}),...tokens?[createTokenNode(tokens)]:[]],[placeholder,tokens]);const emitted=useRef5(value);const[seed]=useState7(()=>tokens?textToTokenHtml(value,tokens.pattern):`<p>${value}</p>`);const editor=useEditor({immediatelyRender:false,editable:!disabled,extensions,content:seed,editorProps:{attributes:{class:"qumra-token-input",dir:"auto",...labelledBy?{"aria-labelledby":labelledBy}:{}}},onUpdate:({editor:e})=>{const text=e.getText();emitted.current=text;onChange(text)}},[extensions]);useEffect5(()=>{if(!editor)return;if(value===emitted.current||value===editor.getText())return;editor.commands.setContent(tokens?textToTokenHtml(value,tokens.pattern):`<p>${value}</p>`,{emitUpdate:false});emitted.current=value},[editor,value,tokens]);useEffect5(()=>{if(editor&&editor.isEditable===Boolean(disabled))editor.setEditable(!disabled,false)},[editor,disabled]);return jsx10(EditorContent,{editor,className:cn("w-full bg-surface text-ink rounded-field border transition-colors","border-border hover:border-brand focus-within:border-brand","[&_.ProseMirror]:outline-none [&_.ProseMirror]:py-2","[&_.ProseMirror_p]:m-0",SIZES[size],disabled&&"bg-bg text-muted cursor-not-allowed opacity-70",className)})}export{Editor,TokenInput,docToHtml,htmlToDoc,isDoc,textToTokenHtml,unwrapTokens,wrapTokens};
|
package/dist/index.d.ts
CHANGED
|
@@ -261,6 +261,14 @@ declare const TEXT: {
|
|
|
261
261
|
readonly netToYou: readonly ["صافي لك", "Net to you"];
|
|
262
262
|
readonly verifiedAccount: readonly ["حساب موثّق", "Verified account"];
|
|
263
263
|
readonly grabHint: readonly ["عنصر قابل لإعادة الترتيب. اضغط مسافة لمسكه ثم الأسهم لتحريكه.", "Reorderable item. Press space to grab it, then the arrows to move it."];
|
|
264
|
+
/** البديل لمّا المستدعي مايمرّرش `itemLabel` */
|
|
265
|
+
readonly sortItem: readonly ["العنصر", "The item"];
|
|
266
|
+
readonly sortMoving: readonly ["{name} قيد التحريك.", "{name} is moving."];
|
|
267
|
+
readonly sortMovedTo: readonly ["{name} انتقل إلى الموضع {n} من {total}.", "{name} moved to position {n} of {total}."];
|
|
268
|
+
readonly sortSettled: readonly ["{name} استقرّ في الموضع {n}.", "{name} settled at position {n}."];
|
|
269
|
+
readonly sortGrabbed: readonly ["{name} ممسوك. حرّكه بالأسهم.", "{name} grabbed. Move it with the arrows."];
|
|
270
|
+
readonly sortAt: readonly ["{name} في الموضع {n} من {total}.", "{name} is at position {n} of {total}."];
|
|
271
|
+
readonly sortCancelled: readonly ["أُلغي التحريك.", "Move cancelled."];
|
|
264
272
|
readonly notifications: readonly ["الإشعارات", "Notifications"];
|
|
265
273
|
readonly dismiss: readonly ["إخفاء", "Dismiss"];
|
|
266
274
|
readonly unread: readonly ["غير مقروء", "Unread"];
|
|
@@ -313,7 +321,7 @@ type UITextKey = keyof typeof TEXT;
|
|
|
313
321
|
* …
|
|
314
322
|
* aria-label={closeLabel ?? ui.close}
|
|
315
323
|
*/
|
|
316
|
-
declare function useUIText(): Record<"clear" | "select" | "search" | "row" | "from" | "close" | "searchEverything" | "noResults" | "noData" | "searchOrAdd" | "cancel" | "confirm" | "somethingWentWrong" | "selectedCount" | "pickToSelect" | "loadingMore" | "save" | "items" | "all" | "selectedTab" | "selectAll" | "deselectAll" | "now" | "today" | "pickDate" | "time" | "videoPlayer" | "rating" | "activeFilters" | "clearAll" | "remove" | "dropImages" | "chooseFromDevice" | "previousPeriod" | "less" | "more" | "totalSales" | "netToYou" | "verifiedAccount" | "grabHint" | "notifications" | "dismiss" | "unread" | "noNotifications" | "noNotificationsDesc" | "markAllRead" | "viewAllNotifications" | "newNotifications" | "reloadPreview" | "previousMonth" | "nextMonth" | "whatIsThisNumber" | "explainToMe" | "clearSearch" | "alerts" | "whatIsThisOption" | "shouldBeHere" | "closeExplainer" | "cancelRecording" | "sendRecording" | "attachFile" | "recordVoice" | "playbackPosition" | "volume" | "hideSuggestions" | "askShehab" | "shehabThinking" | "undo" | "tryAnotherReply" | "helpfulReply" | "unhelpfulReply" | "aiDisclaimer" | "back10" | "forward10" | "playbackSpeed" | "arabic" | "seeMore" | "pictureInPicture", string>;
|
|
324
|
+
declare function useUIText(): Record<"clear" | "select" | "search" | "row" | "from" | "close" | "searchEverything" | "noResults" | "noData" | "searchOrAdd" | "cancel" | "confirm" | "somethingWentWrong" | "selectedCount" | "pickToSelect" | "loadingMore" | "save" | "items" | "all" | "selectedTab" | "selectAll" | "deselectAll" | "now" | "today" | "pickDate" | "time" | "videoPlayer" | "rating" | "activeFilters" | "clearAll" | "remove" | "dropImages" | "chooseFromDevice" | "previousPeriod" | "less" | "more" | "totalSales" | "netToYou" | "verifiedAccount" | "grabHint" | "sortItem" | "sortMoving" | "sortMovedTo" | "sortSettled" | "sortGrabbed" | "sortAt" | "sortCancelled" | "notifications" | "dismiss" | "unread" | "noNotifications" | "noNotificationsDesc" | "markAllRead" | "viewAllNotifications" | "newNotifications" | "reloadPreview" | "previousMonth" | "nextMonth" | "whatIsThisNumber" | "explainToMe" | "clearSearch" | "alerts" | "whatIsThisOption" | "shouldBeHere" | "closeExplainer" | "cancelRecording" | "sendRecording" | "attachFile" | "recordVoice" | "playbackPosition" | "volume" | "hideSuggestions" | "askShehab" | "shehabThinking" | "undo" | "tryAnotherReply" | "helpfulReply" | "unhelpfulReply" | "aiDisclaimer" | "back10" | "forward10" | "playbackSpeed" | "arabic" | "seeMore" | "pictureInPicture", string>;
|
|
317
325
|
|
|
318
326
|
type FieldSize = 'sm' | 'md' | 'lg';
|
|
319
327
|
interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
@@ -1606,6 +1614,16 @@ interface UseSortableOptions {
|
|
|
1606
1614
|
count: number;
|
|
1607
1615
|
/** يتنادى مرّة واحدة عند الإفلات، وبالفهرسين النهائيين */
|
|
1608
1616
|
onMove: (from: number, to: number) => void;
|
|
1617
|
+
/**
|
|
1618
|
+
* محور الترتيب.
|
|
1619
|
+
*
|
|
1620
|
+
* `y` قائمة رأسية — الافتراضي، وهو اللي المكتبة اتبنت عليه.
|
|
1621
|
+
*
|
|
1622
|
+
* `grid` شبكة بمحورين: الفتحة بتتحدّد بالاحتواء لا بالارتفاع، والأسهم
|
|
1623
|
+
* الأربعة كلها بتحرّك، والبنود بتتوضع بإحداثيّات فتحتها لا بإزاحة.
|
|
1624
|
+
* الشرح الكامل عند `useSortable`.
|
|
1625
|
+
*/
|
|
1626
|
+
axis?: 'y' | 'grid';
|
|
1609
1627
|
disabled?: boolean;
|
|
1610
1628
|
/**
|
|
1611
1629
|
* مسافة التفعيل بالبكسل.
|
|
@@ -1627,9 +1645,37 @@ interface SortableItemProps {
|
|
|
1627
1645
|
'data-dragging'?: string;
|
|
1628
1646
|
'data-grabbed'?: string;
|
|
1629
1647
|
}
|
|
1648
|
+
interface SortableContainerProps {
|
|
1649
|
+
ref: (el: HTMLElement | null) => void;
|
|
1650
|
+
style: CSSProperties;
|
|
1651
|
+
}
|
|
1630
1652
|
interface SortableApi {
|
|
1631
1653
|
/** خصائص البند رقم `index` */
|
|
1632
1654
|
item: (index: number) => SortableItemProps;
|
|
1655
|
+
/**
|
|
1656
|
+
* خصائص الحاوية — **لازمة في `grid`** ومالهاش أثر في `y`.
|
|
1657
|
+
*
|
|
1658
|
+
* الحاوية بتتقاس منها إحداثيّات الفتحات، وبتشيل ارتفاعها بالإيد أثناء
|
|
1659
|
+
* السحبة لأن بنودها كلها بتخرج من التدفّق ساعتها. ولازم تكون
|
|
1660
|
+
* `position: relative` من عند المستهلك — دي خاصّية تخطيط بتخصّه.
|
|
1661
|
+
*/
|
|
1662
|
+
container: () => SortableContainerProps;
|
|
1663
|
+
/**
|
|
1664
|
+
* الفهرس اللي البند هيستقرّ فيه لو سِبت دلوقتي — وهو فهرسه نفسه خارج
|
|
1665
|
+
* السحب.
|
|
1666
|
+
*
|
|
1667
|
+
* بيخلّي المستهلك يعرض **الترتيب الجديد** لا الحاليّ: الرقم على البند،
|
|
1668
|
+
* وشارة «الأول»، وأي حاجة مربوطة بالموضع.
|
|
1669
|
+
*/
|
|
1670
|
+
rank: (index: number) => number;
|
|
1671
|
+
/**
|
|
1672
|
+
* مستطيل الفتحة رقم `index` — نسبةً للحاوية، و`null` خارج السحب.
|
|
1673
|
+
*
|
|
1674
|
+
* `rank` بتقول البند هيقع **فين في الترتيب**، ودي بتقول المكان ده
|
|
1675
|
+
* **فين على الشاشة** — عشان المستهلك يرسم شاغراً في مكان الوقوع.
|
|
1676
|
+
* و`slot(over)` هو الشاغر.
|
|
1677
|
+
*/
|
|
1678
|
+
slot: (index: number) => Box | null;
|
|
1633
1679
|
/** الفهرس المسحوب الآن — `null` لو مافيش سحب */
|
|
1634
1680
|
dragging: number | null;
|
|
1635
1681
|
/** الفهرس الممسوك بالكيبورد */
|
|
@@ -1639,7 +1685,14 @@ interface SortableApi {
|
|
|
1639
1685
|
/** نص يُعرض في منطقة حيّة — الشرح عند `SortableStatus` */
|
|
1640
1686
|
message: string;
|
|
1641
1687
|
}
|
|
1642
|
-
|
|
1688
|
+
/** مستطيل مقيس — بيتخزّن أوّل السحبة ومابيتقاسش تاني */
|
|
1689
|
+
interface Box {
|
|
1690
|
+
left: number;
|
|
1691
|
+
top: number;
|
|
1692
|
+
width: number;
|
|
1693
|
+
height: number;
|
|
1694
|
+
}
|
|
1695
|
+
declare function useSortable({ count, onMove, axis, disabled, threshold, itemLabel, }: UseSortableOptions): SortableApi;
|
|
1643
1696
|
/**
|
|
1644
1697
|
* المنطقة الحيّة.
|
|
1645
1698
|
*
|
|
@@ -2587,4 +2640,4 @@ declare function Skeleton({ variant, width, className, }: {
|
|
|
2587
2640
|
className?: string;
|
|
2588
2641
|
}): react.JSX.Element;
|
|
2589
2642
|
|
|
2590
|
-
export { ANIMATE_SCALE, Accordion, type AccordionItem, Alert, type Animation, type AudioLevel, AudioPlayer, type AudioPlayerProps, Avatar, type AvatarSize, Badge, type BadgeProps, BarChart, type BarSeries, BrowserFrame, type BrowserFrameProps, Button, type ButtonProps, ButtonSize, ButtonVariant, COLOR_SCALE, CONTAINER_SCALE, Calendar, Card, CardHeader, Carousel, type CarouselProps, type Chapter, Checkbox, ChoiceCards, type ChoiceOption, type ChoiceProps, Coach, type CoachApi, type CoachAudio, type CoachHint, type CoachItem, type CoachLine, type CoachOrb, CoachProvider, type CoachProviderProps, type CoachRegion, type CoachWhen, type CoachWhere, ColorField, type ColorToken, type Column, Combobox, type CommandItem, CommandPalette, type Container, Counter, type Currency, DARK_TOKENS, DataTable, type DataTableProps, DateField, type DateFieldProps, DateRangePicker, Drawer, Dropdown, Dropzone, EmptyState, type FieldSize, FileRow, type FilterChip, FilterChips, FunnelChart, type FunnelStage, Gallery, type GalleryImage, type GalleryProps, GoalBar, Heatmap, Input, type InputProps, Lightbox, type LightboxProps, LocaleCtx, type MediaState, Modal, Money, type MoneyProps, MoneyProvider, MultiSelect, NumberStepper, type NumberStepperProps, type Option, PROVIDER_LEVEL_LABEL, PROVIDER_LEVEL_LABEL_EN, PageHeader, ParetoChart, type ParetoItem, Phone, type PhoneFormat, type PhoneParts, type PhoneProps, Picker, type PickerItem, type PickerProps, Product3DViewer, type Product3DViewerProps, Progress, ProviderBadge, type ProviderBadgeProps, type ProviderBadgeSize, type ProviderLevel, ProviderMark, type ProviderMarkProps, RADIUS_SCALE, Radio, RadioGroup, type Radius, type Range, RatingInput, type RatingInputProps, type RunwayItem, SHADOW_SCALE, Scrubber, SearchInput, Select, type SelectProps, type Shadow, type ShareItem, ShareList, Sheet, Skeleton, type SortableApi, type SortableItemProps, SortableStatus, Sparkline, Stars, type StarsProps, StatCard, type StatCardProps, Stepper, type StepperStep, StockRunway, Switch, type SymbolStyle, TEXT_SCALE, TOKENS, type TabItem, Tabs, TechnicalInput, type TechnicalInputProps, type TechnicalKind, TechnicalText, type TextSize, Textarea, type TextareaProps, Timeline, type TimelineStep, Toast, ToastHost, type ToastInput, type ToastItem, type ToastTone, type TokenName, Tone, Tooltip, TrendChart, type UITextKey, type UploadFile, type UploadState, type UseSortableOptions, VerifiedBadge, type VerifiedBadgeProps, VideoPlayer, type VideoPlayerProps, type VideoSuggestion, WaterfallChart, type WaterfallStep, WhatsAppIcon, coachSeconds, currencyName, currencySymbol, daysBetween, formatBytes, formatDate, formatRange, formatTime, isCurrency, normalizeHex, parsePhone, presets, useAudioLevel, useCoach, useCoachOptional, useCurrency, useCurrencySymbol, useMedia, useMoneyLang, useMoneyLocale, useSortable, useToasts, useUIText };
|
|
2643
|
+
export { ANIMATE_SCALE, Accordion, type AccordionItem, Alert, type Animation, type AudioLevel, AudioPlayer, type AudioPlayerProps, Avatar, type AvatarSize, Badge, type BadgeProps, BarChart, type BarSeries, BrowserFrame, type BrowserFrameProps, Button, type ButtonProps, ButtonSize, ButtonVariant, COLOR_SCALE, CONTAINER_SCALE, Calendar, Card, CardHeader, Carousel, type CarouselProps, type Chapter, Checkbox, ChoiceCards, type ChoiceOption, type ChoiceProps, Coach, type CoachApi, type CoachAudio, type CoachHint, type CoachItem, type CoachLine, type CoachOrb, CoachProvider, type CoachProviderProps, type CoachRegion, type CoachWhen, type CoachWhere, ColorField, type ColorToken, type Column, Combobox, type CommandItem, CommandPalette, type Container, Counter, type Currency, DARK_TOKENS, DataTable, type DataTableProps, DateField, type DateFieldProps, DateRangePicker, Drawer, Dropdown, Dropzone, EmptyState, type FieldSize, FileRow, type FilterChip, FilterChips, FunnelChart, type FunnelStage, Gallery, type GalleryImage, type GalleryProps, GoalBar, Heatmap, Input, type InputProps, Lightbox, type LightboxProps, LocaleCtx, type MediaState, Modal, Money, type MoneyProps, MoneyProvider, MultiSelect, NumberStepper, type NumberStepperProps, type Option, PROVIDER_LEVEL_LABEL, PROVIDER_LEVEL_LABEL_EN, PageHeader, ParetoChart, type ParetoItem, Phone, type PhoneFormat, type PhoneParts, type PhoneProps, Picker, type PickerItem, type PickerProps, Product3DViewer, type Product3DViewerProps, Progress, ProviderBadge, type ProviderBadgeProps, type ProviderBadgeSize, type ProviderLevel, ProviderMark, type ProviderMarkProps, RADIUS_SCALE, Radio, RadioGroup, type Radius, type Range, RatingInput, type RatingInputProps, type RunwayItem, SHADOW_SCALE, Scrubber, SearchInput, Select, type SelectProps, type Shadow, type ShareItem, ShareList, Sheet, Skeleton, type SortableApi, type Box as SortableBox, type SortableContainerProps, type SortableItemProps, SortableStatus, Sparkline, Stars, type StarsProps, StatCard, type StatCardProps, Stepper, type StepperStep, StockRunway, Switch, type SymbolStyle, TEXT_SCALE, TOKENS, type TabItem, Tabs, TechnicalInput, type TechnicalInputProps, type TechnicalKind, TechnicalText, type TextSize, Textarea, type TextareaProps, Timeline, type TimelineStep, Toast, ToastHost, type ToastInput, type ToastItem, type ToastTone, type TokenName, Tone, Tooltip, TrendChart, type UITextKey, type UploadFile, type UploadState, type UseSortableOptions, VerifiedBadge, type VerifiedBadgeProps, VideoPlayer, type VideoPlayerProps, type VideoSuggestion, WaterfallChart, type WaterfallStep, WhatsAppIcon, coachSeconds, currencyName, currencySymbol, daysBetween, formatBytes, formatDate, formatRange, formatTime, isCurrency, normalizeHex, parsePhone, presets, useAudioLevel, useCoach, useCoachOptional, useCurrency, useCurrencySymbol, useMedia, useMoneyLang, useMoneyLocale, useSortable, useToasts, useUIText };
|