@qumra/fanar 0.0.28 → 0.0.30

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 CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{BarChart,ChoiceCards,DataTable,Money,TrendChart,isCurrency}from"./chunk-QFJSDPEB.js";import{Button,Input,Textarea}from"./chunk-EM4MF5B3.js";import{Badge,Card,StatCard,formatTime}from"./chunk-JOHJNMV2.js";import{Alert,Modal}from"./chunk-5E7KR3JO.js";import{cn,useUIText}from"./chunk-YJ45RGS6.js";import{useEffect,useRef,useState}from"react";import{Bot,Check,Copy,ExternalLink,RotateCcw,ThumbsDown,ThumbsUp,TriangleAlert}from"lucide-react";import{Fragment,jsx,jsxs}from"react/jsx-runtime";function AiAvatar({state="idle",level,size="md",icon:Icon=Bot}){const ring=useRef(null);useEffect(()=>{if(state!=="speaking"||!level)return;let raf=0;const loop=()=>{const v=level.current??0;if(ring.current){ring.current.style.transform=`scale(${1+v**1.6*.9})`;ring.current.style.opacity=String(Math.min(.45,v))}raf=requestAnimationFrame(loop)};raf=requestAnimationFrame(loop);const el=ring.current;return()=>{cancelAnimationFrame(raf);if(el)el.style.opacity="0"}},[state,level]);const box={sm:"size-8",md:"size-9",lg:"size-12"}[size];const px={sm:16,md:18,lg:24}[size];return jsxs("span",{className:"relative inline-flex shrink-0",children:[jsx("span",{ref:ring,"aria-hidden":"true",className:cn("absolute inset-0 rounded-sm bg-brand opacity-0",box),style:{transition:"transform 90ms linear, opacity 90ms linear"}}),jsx("span",{"aria-hidden":"true",className:cn("relative rounded-sm bg-soft border border-soft2 flex items-center justify-center",box,state==="thinking"&&"animate-pulse"),children:jsx(Icon,{size:px,strokeWidth:2,className:"text-brand"})})]})}function AiThinking({label}){const ui=useUIText();return jsxs("span",{role:"status","aria-live":"polite",className:"flex items-center gap-2.5",children:[jsx(AiAvatar,{size:"sm",state:"thinking"}),jsxs("span",{className:"flex items-center gap-2 py-2.5 px-3.5 rounded-card bg-bg border border-line",children:[jsx("span",{"aria-hidden":"true",className:"flex items-center gap-1",children:[0,1,2].map(i=>jsx("span",{className:"size-1.5 rounded-full bg-muted2 animate-bounce",style:{animationDelay:`${i*140}ms`,animationDuration:"900ms"}},i))}),jsx("span",{className:"text-caption text-muted",children:label??ui.shehabThinking})]})]})}function AiToolCall({icon:Icon,title,detail,state="done",onUndo,undoLabel}){const ui=useUIText();const tone={running:"bg-bg border-line text-muted",done:"bg-green-bg2 border-green-line text-green",failed:"bg-red-bg border-red-line text-red",reverted:"bg-bg border-line text-muted2"}[state];const off=state==="reverted";return jsxs("div",{className:cn("flex items-start gap-2.5 p-3 rounded-card border",tone),children:[jsx("span",{"aria-hidden":"true",className:"shrink-0 mt-0.5",children:state==="failed"?jsx(TriangleAlert,{size:15}):off?jsx(RotateCcw,{size:15}):state==="done"?jsx(Check,{size:15}):Icon?jsx(Icon,{size:15}):jsx("span",{className:"block size-3.5 rounded-full border-2 border-current border-t-transparent animate-spin"})}),jsxs("span",{className:"flex flex-col gap-1 min-w-0 flex-1",children:[jsx("span",{className:cn("text-ui font-bold",off?"text-muted":"text-ink"),children:title}),detail&&jsx("span",{className:cn("text-caption leading-[1.7]",off?"text-muted2 line-through":"text-ink2"),children:detail})]}),onUndo&&state==="done"&&jsx("button",{type:"button",onClick:onUndo,className:"shrink-0 text-caption font-bold text-brand-ink cursor-pointer hover:underline underline-offset-4",children:undoLabel??ui.undo})]})}function AiSources({sources,label}){const ui=useUIText();if(sources.length===0)return null;return jsxs("span",{className:"flex items-center gap-1.5 flex-wrap",children:[jsx("span",{className:"text-micro text-muted2",children:label??ui.from}),sources.map(s=>{const inner=jsxs(Fragment,{children:[s.label,jsx(ExternalLink,{size:10,"aria-hidden":"true"})]});const cls="inline-flex items-center gap-1 h-6 px-2 rounded-full bg-soft text-brand-ink text-micro font-bold no-underline cursor-pointer transition-colors hover:bg-soft2";return s.href?jsx("a",{href:s.href,className:cls,children:inner},s.id):jsx("button",{type:"button",onClick:s.onOpen,className:cls,children:inner},s.id)})]})}function AiMessage({role,children,streaming,sources,copyText,onRetry,onFeedback,tools,fill}){const ui=useUIText();const[copied,setCopied]=useState(false);const[vote,setVote]=useState(null);const user=role==="user";const actionable=!user&&!streaming&&(copyText||onRetry||onFeedback);return jsxs("div",{className:cn("flex gap-2.5",fill?"w-full":"max-w-[88%]",user?"self-end":"self-start"),children:[!user&&jsx(AiAvatar,{size:"sm"}),jsxs("div",{className:cn("flex flex-col gap-2 min-w-0",fill&&"flex-1"),children:[jsxs("div",{dir:"auto",className:cn("py-2.5 px-3.5 rounded-card text-ui leading-[1.85] whitespace-pre-line",user?"bg-brand text-white":"bg-bg text-ink border border-line"),children:[children,streaming&&jsx("span",{"aria-hidden":"true",className:"inline-block w-[2px] h-[1em] align-[-2px] ms-0.5 bg-brand animate-pulse"})]}),tools,sources&&sources.length>0&&!streaming&&jsx(AiSources,{sources}),actionable&&jsxs("div",{className:"flex items-center gap-0.5",children:[copyText&&jsx(ActionBtn,{label:copied?"\u0627\u062A\u0646\u0633\u062E":"\u0646\u0633\u062E",onClick:()=>{navigator.clipboard?.writeText(copyText);setCopied(true);setTimeout(()=>setCopied(false),1400)},children:copied?jsx(Check,{size:13,className:"text-green"}):jsx(Copy,{size:13})}),onRetry&&jsx(ActionBtn,{label:ui.tryAnotherReply,onClick:onRetry,children:jsx(RotateCcw,{size:13})}),onFeedback&&jsxs(Fragment,{children:[jsx(ActionBtn,{label:ui.helpfulReply,active:vote==="up",onClick:()=>{setVote("up");onFeedback("up")},children:jsx(ThumbsUp,{size:13})}),jsx(ActionBtn,{label:ui.unhelpfulReply,active:vote==="down",onClick:()=>{setVote("down");onFeedback("down")},children:jsx(ThumbsDown,{size:13})})]})]})]})]})}function ActionBtn({onClick,label,active,children}){return jsx("button",{type:"button",onClick,"aria-label":label,title:label,"aria-pressed":active,className:cn("size-7 rounded-xs inline-flex items-center justify-center cursor-pointer transition-colors",active?"bg-soft text-brand-ink":"text-muted2 hover:bg-hover hover:text-ink"),children})}function AiDisclaimer({children}){const ui=useUIText();return jsx("span",{className:"block text-center text-micro leading-[1.7] text-muted2 [text-wrap:pretty]",children:children??ui.aiDisclaimer})}import{useEffect as useEffect3,useRef as useRef3}from"react";import{ArrowUp,Mic,Paperclip,Square,Trash2}from"lucide-react";import{useCallback,useEffect as useEffect2,useRef as useRef2,useState as useState2}from"react";function useStreamingText({speed=18}={}){const[shown,setShown]=useState2("");const[streaming,setStreaming]=useState2(false);const full=useRef2("");const timer=useRef2(void 0);const stopTimer=useCallback(()=>{clearInterval(timer.current);timer.current=void 0},[]);useEffect2(()=>stopTimer,[stopTimer]);const run=useCallback(()=>{if(timer.current)return;timer.current=setInterval(()=>{setShown(s=>{if(s.length>=full.current.length){stopTimer();setStreaming(false);return s}return full.current.slice(0,s.length+1)})},speed)},[speed,stopTimer]);const start=useCallback(text=>{stopTimer();full.current=text;setShown("");setStreaming(true);run()},[run,stopTimer]);const push=useCallback(chunk=>{full.current+=chunk;setStreaming(true);run()},[run]);const stop=useCallback(()=>{stopTimer();full.current=shown;setStreaming(false)},[shown,stopTimer]);const finish=useCallback(()=>{stopTimer();setShown(full.current);setStreaming(false)},[stopTimer]);const reset=useCallback(()=>{stopTimer();full.current="";setShown("");setStreaming(false)},[stopTimer]);return{text:shown,streaming,start,push,stop,finish,reset}}function useMicLevel(){const level=useRef2(0);const[recording,setRecording]=useState2(false);const[seconds,setSeconds]=useState2(0);const[denied,setDenied]=useState2(false);const stream=useRef2(null);const ctx=useRef2(null);const raf=useRef2(0);const tick=useRef2(void 0);const stop=useCallback(()=>{cancelAnimationFrame(raf.current);clearInterval(tick.current);stream.current?.getTracks().forEach(t=>t.stop());void ctx.current?.close();stream.current=null;ctx.current=null;level.current=0;setRecording(false);setSeconds(0)},[]);useEffect2(()=>stop,[stop]);const start=useCallback(async()=>{if(recording)return;try{const media=await navigator.mediaDevices.getUserMedia({audio:true});const Ctx=window.AudioContext??window.webkitAudioContext;if(!Ctx)throw new Error("\u0645\u0627\u0641\u064A\u0634 Web Audio");const c=new Ctx;const src=c.createMediaStreamSource(media);const analyser=c.createAnalyser();analyser.fftSize=512;analyser.smoothingTimeConstant=.7;src.connect(analyser);stream.current=media;ctx.current=c;setDenied(false);setRecording(true);setSeconds(0);const data=new Uint8Array(analyser.frequencyBinCount);const loop=()=>{analyser.getByteTimeDomainData(data);let sum=0;for(let i=0;i<data.length;i++){const v=(data[i]-128)/128;sum+=v*v}level.current=Math.min(1,Math.sqrt(sum/data.length)*3);raf.current=requestAnimationFrame(loop)};raf.current=requestAnimationFrame(loop);tick.current=setInterval(()=>setSeconds(s=>s+1),1e3)}catch{setDenied(true);setRecording(false)}},[recording]);return{level,recording,seconds,start,stop,denied}}import{jsx as jsx2,jsxs as jsxs2}from"react/jsx-runtime";function AiPromptChips({prompts,onPick}){if(prompts.length===0)return null;return jsx2("div",{className:"flex gap-2 overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",children:prompts.map(p=>jsx2("button",{type:"button",dir:"auto",onClick:()=>onPick(p),className:"shrink-0 h-8 px-3 rounded-full border border-border bg-surface text-caption font-bold text-ink2 whitespace-nowrap cursor-pointer transition-colors hover:border-brand hover:text-brand-ink",children:p},p))})}function LiveBars({level,count=28}){const bars=useRef3([]);const history=useRef3(Array.from({length:count},()=>0));useEffect3(()=>{let raf=0;let last=0;const loop=t=>{if(t-last>60){last=t;history.current=[...history.current.slice(1),level.current??0];for(let i=0;i<bars.current.length;i++){const el=bars.current[i];if(el)el.style.height=`${Math.max(10,(history.current[i]??0)*100)}%`}}raf=requestAnimationFrame(loop)};raf=requestAnimationFrame(loop);return()=>cancelAnimationFrame(raf)},[level]);return jsx2("span",{dir:"ltr","aria-hidden":"true",className:"flex-1 min-w-0 h-7 flex items-center gap-0.5",children:Array.from({length:count},(_,i)=>jsx2("span",{ref:el=>{bars.current[i]=el},className:"flex-1 rounded-full bg-brand",style:{height:"10%",transition:"height 70ms linear"}},i))})}function AiComposer({value,onChange,onSend,placeholder,busy,onStop,onVoice,onAttach,disabled,className}){const ui=useUIText();const mic=useMicLevel();const area=useRef3(null);useEffect3(()=>{const el=area.current;if(!el)return;el.style.height="auto";el.style.height=`${Math.min(el.scrollHeight,120)}px`},[value]);function submit(){const text=value.trim();if(!text||busy)return;onSend(text)}if(mic.recording){return jsxs2("div",{className:cn("flex items-center gap-3 h-14 px-3 rounded-lg bg-surface border border-brand",className),children:[jsx2("button",{type:"button",onClick:mic.stop,"aria-label":ui.cancelRecording,className:"size-9 rounded-sm shrink-0 flex items-center justify-center text-muted cursor-pointer transition-colors hover:bg-red-bg hover:text-red",children:jsx2(Trash2,{size:17,"aria-hidden":"true"})}),jsx2(LiveBars,{level:mic.level}),jsx2("span",{"data-num":true,className:"text-ui font-bold text-ink2 shrink-0 tabular-nums",children:formatTime(mic.seconds)}),jsx2("button",{type:"button",onClick:()=>{const s=mic.seconds;mic.stop();onVoice?.(s)},"aria-label":ui.sendRecording,className:"size-9 rounded-sm shrink-0 flex items-center justify-center bg-brand text-white cursor-pointer transition-colors hover:bg-brand-hover",children:jsx2(ArrowUp,{size:17,strokeWidth:2.4,"aria-hidden":"true"})})]})}const canSend=value.trim().length>0;return jsxs2("div",{className:cn("flex flex-col gap-1.5",className),children:[jsxs2("div",{className:cn("flex items-end gap-2 p-2 ps-3.5 rounded-lg bg-surface border border-border","focus-within:border-brand transition-colors",disabled&&"opacity-60 pointer-events-none"),children:[jsx2("label",{htmlFor:"ai-composer",className:"sr-only",children:placeholder??ui.askShehab}),jsx2("textarea",{id:"ai-composer",ref:area,rows:1,value,disabled,placeholder:placeholder??ui.askShehab,onChange:e=>onChange(e.target.value),onKeyDown:e=>{if(e.key==="Enter"&&!e.shiftKey){e.preventDefault();submit()}},className:"flex-1 min-w-0 py-2 bg-transparent border-none outline-none resize-none text-body text-ink placeholder:text-muted2"}),jsxs2("span",{className:"flex items-center gap-0.5 shrink-0",children:[onAttach&&jsx2("button",{type:"button",onClick:onAttach,"aria-label":ui.attachFile,className:"size-9 rounded-sm flex items-center justify-center text-muted cursor-pointer transition-colors hover:bg-hover hover:text-ink",children:jsx2(Paperclip,{size:17,"aria-hidden":"true"})}),onVoice&&!canSend&&!busy&&jsx2("button",{type:"button",onClick:()=>void mic.start(),"aria-label":ui.recordVoice,className:"size-9 rounded-sm flex items-center justify-center text-muted cursor-pointer transition-colors hover:bg-hover hover:text-ink",children:jsx2(Mic,{size:17,"aria-hidden":"true"})}),jsx2("button",{type:"button",onClick:busy?onStop:submit,disabled:!busy&&!canSend,"aria-label":busy?"\u0623\u0648\u0642\u0641 \u0627\u0644\u062A\u0648\u0644\u064A\u062F":"\u0625\u0631\u0633\u0627\u0644",className:cn("size-9 rounded-sm flex items-center justify-center shrink-0 transition-colors",busy?"bg-ink2 text-surface cursor-pointer hover:bg-ink":canSend?"bg-brand text-white cursor-pointer hover:bg-brand-hover":"bg-soft text-brand-ink/40 cursor-not-allowed"),children:busy?jsx2(Square,{size:13,fill:"currentColor","aria-hidden":"true"}):jsx2(ArrowUp,{size:17,strokeWidth:2.4,"aria-hidden":"true"})})]})]}),mic.denied&&jsx2("span",{className:"text-caption text-red",children:"\u0627\u0644\u0645\u064A\u0643\u0631\u0648\u0641\u0648\u0646 \u0645\u0631\u0641\u0648\u0636 \u2014 \u0627\u0633\u0645\u062D \u0644\u0644\u0645\u0648\u0642\u0639 \u0628\u0627\u0644\u0648\u0635\u0648\u0644 \u0644\u0644\u0645\u064A\u0643\u0631\u0648\u0641\u0648\u0646 \u0645\u0646 \u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0627\u0644\u0645\u062A\u0635\u0641\u0651\u062D."})]})}import{useState as useState5}from"react";import{useState as useState3}from"react";import{ArrowRight,Check as Check2,MessageSquarePlus}from"lucide-react";import{OTHER_PREFIX}from"@qumra/jawab-ai";import{jsx as jsx3,jsxs as jsxs3}from"react/jsx-runtime";function AskCard({block,onAnswer,live=true}){const[at,setAt]=useState3(0);const[picked,setPicked]=useState3({});const[other,setOther]=useState3({});const[notes,setNotes]=useState3({});const[noting,setNoting]=useState3({});const[sent,setSent]=useState3(null);const answerable=live&&Boolean(onAnswer)&&!sent;const total=block.questions.length;const q=block.questions[at];const last=at===total-1;function toggle(question,value){setPicked(prev=>{const cur=prev[question.key]??[];if(!question.multi)return{...prev,[question.key]:[value]};return{...prev,[question.key]:cur.includes(value)?cur.filter(v=>v!==value):[...cur,value]}})}function valuesFor(question){const base=picked[question.key]??[];const typed=other[question.key]?.trim();return typed?[...base,OTHER_PREFIX+typed]:base}function labelsFor(question){return valuesFor(question).map(v=>v.startsWith(OTHER_PREFIX)?v.slice(OTHER_PREFIX.length):question.options.find(o=>o.value===v)?.label??v)}const answered=valuesFor(q).length>0;const canGo=q.required===false||answered;function submit(){const result={answers:{},values:{}};const notesOut={};for(const question of block.questions){const values=valuesFor(question);if(values.length===0)continue;result.values[question.key]=values;result.answers[question.label]=labelsFor(question).join("\u060C ");const note=notes[question.key]?.trim();if(note)notesOut[question.label]={notes:note}}if(Object.keys(notesOut).length)result.annotations=notesOut;setSent(result);onAnswer?.(block.id,result)}if(sent){return jsxs3("div",{className:"flex flex-col gap-3 p-4 rounded-card border border-line bg-bg",children:[block.questions.map(question=>jsxs3("div",{className:"flex flex-col gap-1.5",children:[jsx3("span",{className:"text-caption text-muted [text-wrap:pretty]",children:question.label}),jsx3(Picked,{labels:(sent.answers[question.label]??"").split("\u060C ").filter(Boolean),note:sent.annotations?.[question.label]?.notes})]},question.key)),jsxs3("span",{className:"flex items-center gap-1.5 text-caption font-bold text-green",children:[jsx3(Check2,{size:13,strokeWidth:2.6,"aria-hidden":"true"}),"\u0627\u062A\u0628\u0639\u062A"]})]})}return jsxs3("div",{className:"flex flex-col gap-3.5 p-4 rounded-card border border-soft2 bg-tint",children:[jsxs3("span",{className:"flex items-center justify-between gap-3",children:[q.header?jsx3("span",{className:"px-2 h-5 rounded-mark bg-soft text-brand-ink text-micro font-extrabold flex items-center",children:q.header}):jsx3("span",{}),total>1&&jsxs3("span",{className:"flex items-center gap-2 shrink-0",children:[jsx3("span",{"aria-hidden":"true",className:"flex items-center gap-1",children:block.questions.map((qq,i)=>jsx3("span",{className:cn("size-1.5 rounded-full transition-colors",i===at?"bg-brand":i<at?"bg-brand/40":"bg-border/40")},qq.key))}),jsxs3("span",{"data-num":true,className:"text-micro font-bold text-muted whitespace-nowrap",children:[at+1," \u0645\u0646 ",total]})]})]}),jsxs3("div",{className:"flex flex-col gap-2",children:[jsx3("span",{className:"text-ui font-extrabold text-ink [text-wrap:pretty]",children:q.label}),q.hint&&jsx3("span",{className:"text-caption leading-[1.7] text-muted",children:q.hint}),jsx3(ChoiceCards,{name:`${block.id}-${q.key}`,multiple:q.multi,disabled:!answerable,value:q.multi?picked[q.key]??[]:picked[q.key]?.[0]??null,onChange:v=>toggle(q,v),options:q.options.map(o=>({value:o.value,label:o.label,meta:o.description}))}),q.other!==false&&jsx3(Input,{size:"sm",value:other[q.key]??"",onChange:e=>setOther(p=>({...p,[q.key]:e.target.value})),disabled:!answerable,placeholder:q.other?.placeholder??"\u0623\u0648 \u0627\u0643\u062A\u0628 \u0625\u062C\u0627\u0628\u062A\u0643\u2026","aria-label":`\u0625\u062C\u0627\u0628\u0629 \u0623\u062E\u0631\u0649 \u0639\u0644\u0649: ${q.label}`}),noting[q.key]?jsx3(Textarea,{rows:2,value:notes[q.key]??"",onChange:e=>setNotes(p=>({...p,[q.key]:e.target.value})),disabled:!answerable,placeholder:"\u062D\u0627\u062C\u0629 \u062A\u062D\u0628\u0651 \u062A\u0642\u0648\u0644\u0647\u0627 \u0645\u0639 \u0627\u062E\u062A\u064A\u0627\u0631\u0643\u2026","aria-label":`\u0645\u0644\u0627\u062D\u0638\u0629 \u0639\u0644\u0649: ${q.label}`}):answerable&&jsxs3("button",{type:"button",onClick:()=>setNoting(p=>({...p,[q.key]:true})),className:"self-start inline-flex items-center gap-1.5 text-micro font-bold text-muted hover:text-brand cursor-pointer transition-colors",children:[jsx3(MessageSquarePlus,{size:13,"aria-hidden":"true"}),"\u0636\u064A\u0641 \u0645\u0644\u0627\u062D\u0638\u0629"]})]}),answerable&&jsxs3("span",{className:"flex items-center gap-2.5",children:[at>0&&jsx3(Button,{size:"sm",variant:"ghost",onClick:()=>setAt(i=>i-1),children:"\u0631\u062C\u0648\u0639"}),last?jsx3(Button,{size:"sm",onClick:submit,disabled:!canGo,children:block.submitLabel??"\u0627\u0628\u0639\u062A"}):jsx3(Button,{size:"sm",onClick:()=>setAt(i=>i+1),disabled:!canGo,iconEnd:jsx3(ArrowRight,{size:13,className:"rtl:rotate-180","aria-hidden":"true"}),children:"\u0627\u0644\u062A\u0627\u0644\u064A"}),!canGo&&jsx3("span",{className:"text-micro text-muted2",children:"\u0627\u062E\u062A\u0627\u0631 \u0625\u062C\u0627\u0628\u0629 \u0627\u0644\u0623\u0648\u0644"})]})]})}function Picked({labels,note}){if(labels.length===0)return jsx3("span",{className:"text-caption text-muted2",children:"\u0627\u062A\u062E\u0637\u0651\u0649"});return jsxs3("span",{className:"flex flex-col gap-1.5",children:[jsx3("span",{className:"flex flex-wrap gap-1.5",children:labels.map((l,i)=>jsxs3("span",{className:"inline-flex items-center gap-1 h-6 px-2 rounded-mark bg-soft text-brand-ink text-caption font-bold",children:[jsx3(Check2,{size:11,strokeWidth:3,"aria-hidden":"true"}),l]},i))}),note&&jsx3("span",{className:"text-micro leading-[1.7] text-muted border-s-2 border-line ps-2",children:note})]})}import{useEffect as useEffect4,useState as useState4}from"react";import{Check as Check3,Copy as Copy2,RotateCcw as RotateCcw2,Sparkles,X}from"lucide-react";import{Fragment as Fragment2,jsx as jsx4,jsxs as jsxs4}from"react/jsx-runtime";function DraftPanel({draft:source,basis,label,onInsert,onClose,insertLabel="\u0623\u062F\u0631\u0650\u062C",className}){const[attempt,setAttempt]=useState4(0);const[done,setDone]=useState4(false);const{text,streaming,start,finish}=useStreamingText({speed:12});const dynamic=typeof source==="function";useEffect4(()=>{start(dynamic?source(attempt):source)},[attempt,source]);return jsxs4("div",{className:cn("flex flex-col gap-2.5 p-3.5 rounded-card bg-bg border border-line","basis-full order-last w-full",className),children:[jsxs4("span",{className:"flex items-start justify-between gap-3",children:[jsxs4("span",{className:"flex flex-col gap-0.5 min-w-0",children:[jsxs4("span",{className:"flex items-center gap-1.5 text-caption font-extrabold text-ink",children:[jsx4(Sparkles,{size:13,className:"text-brand shrink-0","aria-hidden":"true"}),label]}),jsx4("span",{className:"text-micro leading-[1.65] text-muted",children:basis})]}),onClose&&jsx4("button",{type:"button",onClick:onClose,"aria-label":"\u0625\u063A\u0644\u0627\u0642",className:"shrink-0 size-6 rounded-mark flex items-center justify-center text-muted2 hover:bg-hover hover:text-ink cursor-pointer transition-colors",children:jsx4(X,{size:14,"aria-hidden":"true"})})]}),text===""&&streaming?jsx4(AiThinking,{label:"\u0628\u064A\u0643\u062A\u0628\u2026"}):jsxs4("span",{className:"block text-caption leading-[1.9] text-ink whitespace-pre-wrap [text-wrap:pretty]","aria-live":"polite",children:[text,streaming&&jsx4("span",{"aria-hidden":"true",className:"inline-block w-[2px] h-[1em] align-[-0.15em] ms-0.5 bg-brand animate-pulse"})]}),jsx4("span",{className:"flex items-center gap-2 flex-wrap",children:streaming?jsx4(Button,{size:"sm",variant:"outline",onClick:finish,children:"\u0627\u0639\u0631\u0636\u0647\u0627 \u0643\u0644\u0647\u0627"}):jsxs4(Fragment2,{children:[onInsert&&jsx4(Button,{size:"sm",onClick:()=>{onInsert(text);setDone(true);onClose?.()},icon:jsx4(Check3,{size:13,"aria-hidden":"true"}),children:insertLabel}),jsx4(Button,{size:"sm",variant:"outline",onClick:()=>navigator.clipboard?.writeText(text),icon:jsx4(Copy2,{size:13,"aria-hidden":"true"}),children:"\u0627\u0646\u0633\u062E"}),dynamic&&jsx4(Button,{size:"sm",variant:"ghost",onClick:()=>setAttempt(a=>a+1),icon:jsx4(RotateCcw2,{size:13,"aria-hidden":"true"}),children:"\u0627\u0643\u062A\u0628 \u063A\u064A\u0631\u0647\u0627"})]})}),!streaming&&!done&&jsx4(AiDisclaimer,{children:"\u0645\u0645\u0643\u0646 \u064A\u063A\u0644\u0637 \u2014 \u0627\u0642\u0631\u0627\u0647\u0627 \u0642\u0628\u0644 \u0645\u0627 \u062A\u0646\u0634\u0631\u0647\u0627."})]})}function AiDraft({size="sm",...panel}){const[open,setOpen]=useState4(false);if(!open){return jsx4(Button,{variant:"outline",size,onClick:()=>setOpen(true),icon:jsx4(Sparkles,{size:size==="sm"?13:15,"aria-hidden":"true"}),className:panel.className,children:panel.label})}return jsx4(DraftPanel,{...panel,onClose:()=>setOpen(false)})}import{Fragment as Fragment3,jsx as jsx5}from"react/jsx-runtime";function Markdown({md}){const chunks=md.split(/\n{2,}/);return jsx5(Fragment3,{children:chunks.map((chunk,i)=>{const lines=chunk.split("\n");const bullets=lines.every(l=>/^\s*[-•]\s+/.test(l));const numbers=lines.every(l=>/^\s*\d+[.)]\s+/.test(l));if(bullets||numbers){const items=lines.map(l=>l.replace(/^\s*(?:[-•]|\d+[.)])\s+/,""));const List=numbers?"ol":"ul";return jsx5(List,{className:numbers?"my-2 ps-5 list-decimal marker:text-muted2 flex flex-col gap-1":"my-2 ps-5 list-disc marker:text-muted2 flex flex-col gap-1",children:items.map((it,j)=>jsx5("li",{children:inline(it)},j))},i)}return jsx5("p",{className:"my-2 first:mt-0 last:mb-0 [text-wrap:pretty]",children:inline(chunk)},i)})})}var TOKEN=/(`[^`\n]+`)|(\*\*[^*\n]+\*\*)|(\*[^*\n]+\*)/g;function inline(src){const out=[];let last=0;let m;TOKEN.lastIndex=0;while((m=TOKEN.exec(src))!==null){if(m.index>last)out.push(src.slice(last,m.index));const[full]=m;const key=`${m.index}`;if(full.startsWith("`")){out.push(jsx5("code",{dir:"ltr",className:"px-1 py-px rounded-mark bg-hover text-[0.9em] font-mono text-brand-ink",children:full.slice(1,-1)},key))}else if(full.startsWith("**")){out.push(jsx5("strong",{className:"font-extrabold text-ink",children:full.slice(2,-2)},key))}else{out.push(jsx5("em",{className:"not-italic font-bold",children:full.slice(1,-1)},key))}last=m.index+full.length}if(last<src.length)out.push(src.slice(last));return out}import{Fragment as Fragment4,jsx as jsx6,jsxs as jsxs5}from"react/jsx-runtime";var TONE={good:"green",warn:"amber",bad:"red",plain:"neutral"};var NOTICE_TONE={info:"brand",warn:"amber",danger:"red"};function major(a){return a.minor/10**(a.decimals??2)}function TextBlockView({block}){if(!block.md)return null;return jsx6("div",{className:"text-body leading-[1.95] text-ink2",children:jsx6(Markdown,{md:block.md})})}function MetricBlockView({block}){return jsx6("div",{className:"grid gap-2.5 grid-cols-[repeat(auto-fit,minmax(9.5rem,1fr))]",children:block.items.map((m,i)=>jsx6(StatCard,{tone:TONE[m.tone??"plain"]??"neutral",label:m.label,value:m.amount?jsx6(Money,{value:major(m.amount),currency:isCurrency(m.amount.currency)?m.amount.currency:void 0,compact:true,trimZeros:true}):m.value,hint:m.delta!==void 0?deltaHint(m.delta,m.deltaBasis):void 0},i))})}function deltaHint(delta,basis){const up=delta>0;const flat=delta===0;return jsxs5("span",{className:cn("font-bold",flat?"text-muted2":up?"text-green":"text-red"),children:[flat?"=":up?"\u25B2":"\u25BC"," ",Math.abs(delta),"\u066A",basis?` ${basis}`:""]})}function TableBlockView({block}){const rows=block.rows.map((cells,i)=>{const row={__key:String(i)};block.cols.forEach((c,j)=>{row[c.key]=cells[j]??null});return row});const columns=block.cols.map(c=>({key:c.key,header:c.label,end:c.align==="end",cell:row=>renderCell(row[c.key],c)}));return jsxs5("span",{className:"flex flex-col gap-1.5",children:[block.caption&&jsx6("span",{className:"text-micro text-muted2",children:block.caption}),jsx6(DataTable,{columns,rows,rowKey:r=>r.__key,grid:block.cols.map(c=>c.align==="end"?"1fr":"1.6fr").join("_"),minWidth:block.cols.length*120,mobileCard:row=>jsx6("span",{className:"flex flex-col gap-1",children:block.cols.map(c=>jsxs5("span",{className:"flex items-baseline justify-between gap-3",children:[jsx6("span",{className:"text-micro text-muted2",children:c.label}),jsx6("span",{className:"text-caption text-ink",children:renderCell(row[c.key],c)})]},c.key))})})]})}function renderCell(v,col){if(v===null||v==="")return jsx6("span",{className:"text-muted2",children:"\u2014"});switch(col.format){case"money":return typeof v==="number"?jsx6(Money,{value:v,trimZeros:true}):v;case"badge":return jsx6(Badge,{size:"sm",children:v});case"number":return jsx6("span",{"data-num":true,children:v});default:return v}}function CardsBlockView({block,intents}){return jsx6("div",{className:"grid gap-2.5 grid-cols-[repeat(auto-fill,minmax(13rem,1fr))]",children:block.items.map(c=>jsx6(Card,{children:jsxs5("span",{className:"flex gap-3 items-start",children:[c.img&&jsx6("img",{src:c.img,alt:"",className:"size-12 rounded-sm object-cover bg-hover shrink-0"}),jsxs5("span",{className:"flex flex-col gap-1 min-w-0",children:[jsx6("span",{className:"text-ui font-bold text-ink truncate",children:c.title}),c.subtitle&&jsx6("span",{className:"text-micro text-muted",children:c.subtitle}),c.badge&&jsx6("span",{children:jsx6(Badge,{size:"sm",tone:"brand",children:c.badge})}),c.action&&jsx6(ActionButton,{action:c.action,intents,size:"sm"})]})]})},c.id))})}function ChartBlockView({block}){const labels=block.series.map(p=>String(p.x));const values=block.series.map(p=>p.y);const money=block.unit?.kind==="money";const fmt=v=>block.unit?.kind==="percent"?`${v}\u066A`:v.toLocaleString("ar-EG");if(block.kind==="bar"){return jsx6(BarChart,{labels,series:[{label:"",values}],formatValue:fmt})}return jsx6(TrendChart,{labels:axisLabels(labels),values,pointLabels:labels,formatValue:money?v=>v.toLocaleString("ar-EG"):fmt,height:170})}function axisLabels(all){if(all.length<=3)return all;return[all[0],all[Math.floor(all.length/2)],all[all.length-1]]}function ActionBlockView({block,intents}){const runnable=block.items.filter(a=>intents[a.intent]);if(runnable.length===0)return null;return jsx6("span",{className:"flex flex-wrap gap-2",children:runnable.map((a,i)=>jsx6(ActionButton,{action:a,intents},i))})}function ActionButton({action,intents,size="sm"}){const[asking,setAsking]=useState5(false);const run=intents[action.intent];if(!run)return null;function fire(){setAsking(false);run(action.args)}return jsxs5(Fragment4,{children:[jsx6(Button,{size,variant:action.style==="quiet"?"outline":"primary",onClick:()=>action.confirm?setAsking(true):fire(),children:action.label}),jsx6(Modal,{open:asking,title:action.label,description:action.confirm,onClose:()=>setAsking(false),size:"sm",footer:jsxs5(Fragment4,{children:[jsx6(Button,{variant:"outline",onClick:()=>setAsking(false),children:"\u0625\u0644\u063A\u0627\u0621"}),jsx6(Button,{onClick:fire,children:action.label})]})})]})}function ToolBlockView({block,intents}){const undo=block.undo;const run=undo?intents[undo.intent]:void 0;return jsx6(AiToolCall,{title:block.title,detail:block.detail,state:block.state,onUndo:run&&undo?()=>run(undo.args):void 0,undoLabel:undo?.label})}function NoticeBlockView({block}){return jsx6(Alert,{tone:NOTICE_TONE[block.tone],children:block.text})}function ChipsBlockView({block,onSend}){if(!onSend)return null;const byLabel=new Map(block.items.map(c=>[c.label,c.send]));return jsx6(AiPromptChips,{prompts:block.items.map(c=>c.label),onPick:label=>onSend(byLabel.get(label)??label)})}function BlockView({block,intents,onSend,onInsertDraft,onAnswer,live=true}){switch(block.type){case"text":return jsx6(TextBlockView,{block});case"metric":return jsx6(MetricBlockView,{block});case"table":return jsx6(TableBlockView,{block});case"cards":return jsx6(CardsBlockView,{block,intents});case"chart":return jsx6(ChartBlockView,{block});case"action":return jsx6(ActionBlockView,{block,intents});case"tool":return jsx6(ToolBlockView,{block,intents});case"notice":return jsx6(NoticeBlockView,{block});case"chips":return jsx6(ChipsBlockView,{block,onSend});case"ask":return jsx6(AskCard,{block,onAnswer,live});case"draft":return jsx6(DraftPanel,{draft:block.text,basis:block.basis,label:"\u0645\u0633\u0648\u0651\u062F\u0629",onInsert:onInsertDraft});default:return null}}import{jsx as jsx7,jsxs as jsxs6}from"react/jsx-runtime";var NO_INTENTS={};function ReplyView({reply,streaming,intents=NO_INTENTS,onSend,onInsertDraft,onAnswer,live=true,onRetry,onFeedback,className}){return jsx7(AiMessage,{role:"assistant",fill:true,streaming,sources:reply.sources,copyText:plainText(reply),onRetry,onFeedback,children:jsxs6("span",{className:cn("flex flex-col gap-3",className),children:[reply.blocks.map((block,i)=>jsx7(BlockView,{block,intents,onSend,onInsertDraft,onAnswer,live},i)),reply.disclaimer!==false&&!streaming&&jsx7(AiDisclaimer,{})]})})}function plainText(reply){const parts=[];for(const b of reply.blocks){switch(b.type){case"text":parts.push(b.md);break;case"metric":parts.push(b.items.map(m=>`${m.label}: ${m.value}`).join(" \xB7 "));break;case"table":parts.push([b.cols.map(c=>c.label).join(" "),...b.rows.map(r=>r.map(c=>c??"").join(" "))].join("\n"));break;case"cards":parts.push(b.items.map(c=>c.title).join("\n"));break;case"draft":parts.push(b.text);break;case"tool":parts.push(b.detail?`${b.title} \u2014 ${b.detail}`:b.title);break;case"notice":parts.push(b.text);break;case"ask":parts.push(b.questions.map(q=>q.label).join("\n"));break;case"chart":case"action":case"chips":break}}return parts.filter(Boolean).join("\n\n")}import{useCallback as useCallback2,useEffect as useEffect5,useRef as useRef4,useState as useState6}from"react";import{parseEvent,parseSSE,reduce}from"@qumra/jawab-ai";function useReplyStream(url,init){const[reply,setReply]=useState6(null);const[streaming,setStreaming]=useState6(false);const[error,setError]=useState6(null);const abort=useRef4(null);const lastInput=useRef4("");useEffect5(()=>()=>abort.current?.abort(),[]);const stop=useCallback2(()=>{abort.current?.abort();abort.current=null;setStreaming(false)},[]);const send=useCallback2(text=>{const question=text.trim();if(!question)return;abort.current?.abort();const ctrl=new AbortController;abort.current=ctrl;lastInput.current=question;setError(null);setReply(null);setStreaming(true);void(async()=>{try{const res=await fetch(url,{method:"POST",headers:{"content-type":"application/json",accept:"text/event-stream"},body:JSON.stringify({input:question}),signal:ctrl.signal,...init});if(!res.ok||!res.body){throw new StreamError("http_"+res.status,`\u0627\u0644\u062E\u0627\u062F\u0645 \u0631\u062C\u0651\u0639 ${res.status}`)}const decoder=new TextDecoder;const readerStream=res.body.getReader();let rest="";let state=null;for(;;){const{done,value}=await readerStream.read();if(done)break;rest+=decoder.decode(value,{stream:true});const{events,rest:tail}=parseSSE(rest);rest=tail;for(const raw of events){const ev=parseEvent(raw);if(!ev)continue;if(ev.e==="error")throw new StreamError(ev.code,ev.message);state=reduce(state,ev);setReply(state);if(ev.e==="done")break}}setStreaming(false)}catch(e){if(ctrl.signal.aborted)return;const se=e;setError({code:se.code??"unknown",message:se.message??"\u0627\u0644\u0627\u062A\u0635\u0627\u0644 \u0627\u062A\u0642\u0637\u0639.",lastInput:lastInput.current});setStreaming(false)}})()},[url,init]);return{reply,streaming,error,send,stop}}var StreamError=class extends Error{code;constructor(code,message){super(message);this.name="StreamError";this.code=code}};export{AiAvatar,AiComposer,AiDisclaimer,AiDraft,AiMessage,AiPromptChips,AiSources,AiThinking,AiToolCall,AskCard,DraftPanel,ReplyView,useMicLevel,useReplyStream,useStreamingText};
2
+ import{BarChart,ChoiceCards,DataTable,Money,TrendChart,isCurrency}from"./chunk-QFJSDPEB.js";import{Button,Input,Textarea}from"./chunk-EM4MF5B3.js";import{Badge,Card,StatCard,formatTime}from"./chunk-JOHJNMV2.js";import{Alert,Modal}from"./chunk-4ZNTBLVW.js";import{cn,useUIText}from"./chunk-YJ45RGS6.js";import{useEffect,useRef,useState}from"react";import{Bot,Check,Copy,ExternalLink,RotateCcw,ThumbsDown,ThumbsUp,TriangleAlert}from"lucide-react";import{Fragment,jsx,jsxs}from"react/jsx-runtime";function AiAvatar({state="idle",level,size="md",icon:Icon=Bot}){const ring=useRef(null);useEffect(()=>{if(state!=="speaking"||!level)return;let raf=0;const loop=()=>{const v=level.current??0;if(ring.current){ring.current.style.transform=`scale(${1+v**1.6*.9})`;ring.current.style.opacity=String(Math.min(.45,v))}raf=requestAnimationFrame(loop)};raf=requestAnimationFrame(loop);const el=ring.current;return()=>{cancelAnimationFrame(raf);if(el)el.style.opacity="0"}},[state,level]);const box={sm:"size-8",md:"size-9",lg:"size-12"}[size];const px={sm:16,md:18,lg:24}[size];return jsxs("span",{className:"relative inline-flex shrink-0",children:[jsx("span",{ref:ring,"aria-hidden":"true",className:cn("absolute inset-0 rounded-sm bg-brand opacity-0",box),style:{transition:"transform 90ms linear, opacity 90ms linear"}}),jsx("span",{"aria-hidden":"true",className:cn("relative rounded-sm bg-soft border border-soft2 flex items-center justify-center",box,state==="thinking"&&"animate-pulse"),children:jsx(Icon,{size:px,strokeWidth:2,className:"text-brand"})})]})}function AiThinking({label}){const ui=useUIText();return jsxs("span",{role:"status","aria-live":"polite",className:"flex items-center gap-2.5",children:[jsx(AiAvatar,{size:"sm",state:"thinking"}),jsxs("span",{className:"flex items-center gap-2 py-2.5 px-3.5 rounded-card bg-bg border border-line",children:[jsx("span",{"aria-hidden":"true",className:"flex items-center gap-1",children:[0,1,2].map(i=>jsx("span",{className:"size-1.5 rounded-full bg-muted2 animate-bounce",style:{animationDelay:`${i*140}ms`,animationDuration:"900ms"}},i))}),jsx("span",{className:"text-caption text-muted",children:label??ui.shehabThinking})]})]})}function AiToolCall({icon:Icon,title,detail,state="done",onUndo,undoLabel}){const ui=useUIText();const tone={running:"bg-bg border-line text-muted",done:"bg-green-bg2 border-green-line text-green",failed:"bg-red-bg border-red-line text-red",reverted:"bg-bg border-line text-muted2"}[state];const off=state==="reverted";return jsxs("div",{className:cn("flex items-start gap-2.5 p-3 rounded-card border",tone),children:[jsx("span",{"aria-hidden":"true",className:"shrink-0 mt-0.5",children:state==="failed"?jsx(TriangleAlert,{size:15}):off?jsx(RotateCcw,{size:15}):state==="done"?jsx(Check,{size:15}):Icon?jsx(Icon,{size:15}):jsx("span",{className:"block size-3.5 rounded-full border-2 border-current border-t-transparent animate-spin"})}),jsxs("span",{className:"flex flex-col gap-1 min-w-0 flex-1",children:[jsx("span",{className:cn("text-ui font-bold",off?"text-muted":"text-ink"),children:title}),detail&&jsx("span",{className:cn("text-caption leading-[1.7]",off?"text-muted2 line-through":"text-ink2"),children:detail})]}),onUndo&&state==="done"&&jsx("button",{type:"button",onClick:onUndo,className:"shrink-0 text-caption font-bold text-brand-ink cursor-pointer hover:underline underline-offset-4",children:undoLabel??ui.undo})]})}function AiSources({sources,label}){const ui=useUIText();if(sources.length===0)return null;return jsxs("span",{className:"flex items-center gap-1.5 flex-wrap",children:[jsx("span",{className:"text-micro text-muted2",children:label??ui.from}),sources.map(s=>{const inner=jsxs(Fragment,{children:[s.label,jsx(ExternalLink,{size:10,"aria-hidden":"true"})]});const cls="inline-flex items-center gap-1 h-6 px-2 rounded-full bg-soft text-brand-ink text-micro font-bold no-underline cursor-pointer transition-colors hover:bg-soft2";return s.href?jsx("a",{href:s.href,className:cls,children:inner},s.id):jsx("button",{type:"button",onClick:s.onOpen,className:cls,children:inner},s.id)})]})}function AiMessage({role,children,streaming,sources,copyText,onRetry,onFeedback,tools,fill}){const ui=useUIText();const[copied,setCopied]=useState(false);const[vote,setVote]=useState(null);const user=role==="user";const actionable=!user&&!streaming&&(copyText||onRetry||onFeedback);return jsxs("div",{className:cn("flex gap-2.5",fill?"w-full":"max-w-[88%]",user?"self-end":"self-start"),children:[!user&&jsx(AiAvatar,{size:"sm"}),jsxs("div",{className:cn("flex flex-col gap-2 min-w-0",fill&&"flex-1"),children:[jsxs("div",{dir:"auto",className:cn("py-2.5 px-3.5 rounded-card text-ui leading-[1.85] whitespace-pre-line",user?"bg-brand text-white":"bg-bg text-ink border border-line"),children:[children,streaming&&jsx("span",{"aria-hidden":"true",className:"inline-block w-[2px] h-[1em] align-[-2px] ms-0.5 bg-brand animate-pulse"})]}),tools,sources&&sources.length>0&&!streaming&&jsx(AiSources,{sources}),actionable&&jsxs("div",{className:"flex items-center gap-0.5",children:[copyText&&jsx(ActionBtn,{label:copied?"\u0627\u062A\u0646\u0633\u062E":"\u0646\u0633\u062E",onClick:()=>{navigator.clipboard?.writeText(copyText);setCopied(true);setTimeout(()=>setCopied(false),1400)},children:copied?jsx(Check,{size:13,className:"text-green"}):jsx(Copy,{size:13})}),onRetry&&jsx(ActionBtn,{label:ui.tryAnotherReply,onClick:onRetry,children:jsx(RotateCcw,{size:13})}),onFeedback&&jsxs(Fragment,{children:[jsx(ActionBtn,{label:ui.helpfulReply,active:vote==="up",onClick:()=>{setVote("up");onFeedback("up")},children:jsx(ThumbsUp,{size:13})}),jsx(ActionBtn,{label:ui.unhelpfulReply,active:vote==="down",onClick:()=>{setVote("down");onFeedback("down")},children:jsx(ThumbsDown,{size:13})})]})]})]})]})}function ActionBtn({onClick,label,active,children}){return jsx("button",{type:"button",onClick,"aria-label":label,title:label,"aria-pressed":active,className:cn("size-7 rounded-xs inline-flex items-center justify-center cursor-pointer transition-colors",active?"bg-soft text-brand-ink":"text-muted2 hover:bg-hover hover:text-ink"),children})}function AiDisclaimer({children}){const ui=useUIText();return jsx("span",{className:"block text-center text-micro leading-[1.7] text-muted2 [text-wrap:pretty]",children:children??ui.aiDisclaimer})}import{useEffect as useEffect3,useRef as useRef3}from"react";import{ArrowUp,Mic,Paperclip,Square,Trash2}from"lucide-react";import{useCallback,useEffect as useEffect2,useRef as useRef2,useState as useState2}from"react";function useStreamingText({speed=18}={}){const[shown,setShown]=useState2("");const[streaming,setStreaming]=useState2(false);const full=useRef2("");const timer=useRef2(void 0);const stopTimer=useCallback(()=>{clearInterval(timer.current);timer.current=void 0},[]);useEffect2(()=>stopTimer,[stopTimer]);const run=useCallback(()=>{if(timer.current)return;timer.current=setInterval(()=>{setShown(s=>{if(s.length>=full.current.length){stopTimer();setStreaming(false);return s}return full.current.slice(0,s.length+1)})},speed)},[speed,stopTimer]);const start=useCallback(text=>{stopTimer();full.current=text;setShown("");setStreaming(true);run()},[run,stopTimer]);const push=useCallback(chunk=>{full.current+=chunk;setStreaming(true);run()},[run]);const stop=useCallback(()=>{stopTimer();full.current=shown;setStreaming(false)},[shown,stopTimer]);const finish=useCallback(()=>{stopTimer();setShown(full.current);setStreaming(false)},[stopTimer]);const reset=useCallback(()=>{stopTimer();full.current="";setShown("");setStreaming(false)},[stopTimer]);return{text:shown,streaming,start,push,stop,finish,reset}}function useMicLevel(){const level=useRef2(0);const[recording,setRecording]=useState2(false);const[seconds,setSeconds]=useState2(0);const[denied,setDenied]=useState2(false);const stream=useRef2(null);const ctx=useRef2(null);const raf=useRef2(0);const tick=useRef2(void 0);const stop=useCallback(()=>{cancelAnimationFrame(raf.current);clearInterval(tick.current);stream.current?.getTracks().forEach(t=>t.stop());void ctx.current?.close();stream.current=null;ctx.current=null;level.current=0;setRecording(false);setSeconds(0)},[]);useEffect2(()=>stop,[stop]);const start=useCallback(async()=>{if(recording)return;try{const media=await navigator.mediaDevices.getUserMedia({audio:true});const Ctx=window.AudioContext??window.webkitAudioContext;if(!Ctx)throw new Error("\u0645\u0627\u0641\u064A\u0634 Web Audio");const c=new Ctx;const src=c.createMediaStreamSource(media);const analyser=c.createAnalyser();analyser.fftSize=512;analyser.smoothingTimeConstant=.7;src.connect(analyser);stream.current=media;ctx.current=c;setDenied(false);setRecording(true);setSeconds(0);const data=new Uint8Array(analyser.frequencyBinCount);const loop=()=>{analyser.getByteTimeDomainData(data);let sum=0;for(let i=0;i<data.length;i++){const v=(data[i]-128)/128;sum+=v*v}level.current=Math.min(1,Math.sqrt(sum/data.length)*3);raf.current=requestAnimationFrame(loop)};raf.current=requestAnimationFrame(loop);tick.current=setInterval(()=>setSeconds(s=>s+1),1e3)}catch{setDenied(true);setRecording(false)}},[recording]);return{level,recording,seconds,start,stop,denied}}import{jsx as jsx2,jsxs as jsxs2}from"react/jsx-runtime";function AiPromptChips({prompts,onPick}){if(prompts.length===0)return null;return jsx2("div",{className:"flex gap-2 overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",children:prompts.map(p=>jsx2("button",{type:"button",dir:"auto",onClick:()=>onPick(p),className:"shrink-0 h-8 px-3 rounded-full border border-border bg-surface text-caption font-bold text-ink2 whitespace-nowrap cursor-pointer transition-colors hover:border-brand hover:text-brand-ink",children:p},p))})}function LiveBars({level,count=28}){const bars=useRef3([]);const history=useRef3(Array.from({length:count},()=>0));useEffect3(()=>{let raf=0;let last=0;const loop=t=>{if(t-last>60){last=t;history.current=[...history.current.slice(1),level.current??0];for(let i=0;i<bars.current.length;i++){const el=bars.current[i];if(el)el.style.height=`${Math.max(10,(history.current[i]??0)*100)}%`}}raf=requestAnimationFrame(loop)};raf=requestAnimationFrame(loop);return()=>cancelAnimationFrame(raf)},[level]);return jsx2("span",{dir:"ltr","aria-hidden":"true",className:"flex-1 min-w-0 h-7 flex items-center gap-0.5",children:Array.from({length:count},(_,i)=>jsx2("span",{ref:el=>{bars.current[i]=el},className:"flex-1 rounded-full bg-brand",style:{height:"10%",transition:"height 70ms linear"}},i))})}function AiComposer({value,onChange,onSend,placeholder,busy,onStop,onVoice,onAttach,disabled,className}){const ui=useUIText();const mic=useMicLevel();const area=useRef3(null);useEffect3(()=>{const el=area.current;if(!el)return;el.style.height="auto";el.style.height=`${Math.min(el.scrollHeight,120)}px`},[value]);function submit(){const text=value.trim();if(!text||busy)return;onSend(text)}if(mic.recording){return jsxs2("div",{className:cn("flex items-center gap-3 h-14 px-3 rounded-lg bg-surface border border-brand",className),children:[jsx2("button",{type:"button",onClick:mic.stop,"aria-label":ui.cancelRecording,className:"size-9 rounded-sm shrink-0 flex items-center justify-center text-muted cursor-pointer transition-colors hover:bg-red-bg hover:text-red",children:jsx2(Trash2,{size:17,"aria-hidden":"true"})}),jsx2(LiveBars,{level:mic.level}),jsx2("span",{"data-num":true,className:"text-ui font-bold text-ink2 shrink-0 tabular-nums",children:formatTime(mic.seconds)}),jsx2("button",{type:"button",onClick:()=>{const s=mic.seconds;mic.stop();onVoice?.(s)},"aria-label":ui.sendRecording,className:"size-9 rounded-sm shrink-0 flex items-center justify-center bg-brand text-white cursor-pointer transition-colors hover:bg-brand-hover",children:jsx2(ArrowUp,{size:17,strokeWidth:2.4,"aria-hidden":"true"})})]})}const canSend=value.trim().length>0;return jsxs2("div",{className:cn("flex flex-col gap-1.5",className),children:[jsxs2("div",{className:cn("flex items-end gap-2 p-2 ps-3.5 rounded-lg bg-surface border border-border","focus-within:border-brand transition-colors",disabled&&"opacity-60 pointer-events-none"),children:[jsx2("label",{htmlFor:"ai-composer",className:"sr-only",children:placeholder??ui.askShehab}),jsx2("textarea",{id:"ai-composer",ref:area,rows:1,value,disabled,placeholder:placeholder??ui.askShehab,onChange:e=>onChange(e.target.value),onKeyDown:e=>{if(e.key==="Enter"&&!e.shiftKey){e.preventDefault();submit()}},className:"flex-1 min-w-0 py-2 bg-transparent border-none outline-none resize-none text-body text-ink placeholder:text-muted2"}),jsxs2("span",{className:"flex items-center gap-0.5 shrink-0",children:[onAttach&&jsx2("button",{type:"button",onClick:onAttach,"aria-label":ui.attachFile,className:"size-9 rounded-sm flex items-center justify-center text-muted cursor-pointer transition-colors hover:bg-hover hover:text-ink",children:jsx2(Paperclip,{size:17,"aria-hidden":"true"})}),onVoice&&!canSend&&!busy&&jsx2("button",{type:"button",onClick:()=>void mic.start(),"aria-label":ui.recordVoice,className:"size-9 rounded-sm flex items-center justify-center text-muted cursor-pointer transition-colors hover:bg-hover hover:text-ink",children:jsx2(Mic,{size:17,"aria-hidden":"true"})}),jsx2("button",{type:"button",onClick:busy?onStop:submit,disabled:!busy&&!canSend,"aria-label":busy?"\u0623\u0648\u0642\u0641 \u0627\u0644\u062A\u0648\u0644\u064A\u062F":"\u0625\u0631\u0633\u0627\u0644",className:cn("size-9 rounded-sm flex items-center justify-center shrink-0 transition-colors",busy?"bg-ink2 text-surface cursor-pointer hover:bg-ink":canSend?"bg-brand text-white cursor-pointer hover:bg-brand-hover":"bg-soft text-brand-ink/40 cursor-not-allowed"),children:busy?jsx2(Square,{size:13,fill:"currentColor","aria-hidden":"true"}):jsx2(ArrowUp,{size:17,strokeWidth:2.4,"aria-hidden":"true"})})]})]}),mic.denied&&jsx2("span",{className:"text-caption text-red",children:"\u0627\u0644\u0645\u064A\u0643\u0631\u0648\u0641\u0648\u0646 \u0645\u0631\u0641\u0648\u0636 \u2014 \u0627\u0633\u0645\u062D \u0644\u0644\u0645\u0648\u0642\u0639 \u0628\u0627\u0644\u0648\u0635\u0648\u0644 \u0644\u0644\u0645\u064A\u0643\u0631\u0648\u0641\u0648\u0646 \u0645\u0646 \u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0627\u0644\u0645\u062A\u0635\u0641\u0651\u062D."})]})}import{useState as useState5}from"react";import{useState as useState3}from"react";import{ArrowRight,Check as Check2,MessageSquarePlus}from"lucide-react";import{OTHER_PREFIX}from"@qumra/jawab-ai";import{jsx as jsx3,jsxs as jsxs3}from"react/jsx-runtime";function AskCard({block,onAnswer,live=true}){const[at,setAt]=useState3(0);const[picked,setPicked]=useState3({});const[other,setOther]=useState3({});const[notes,setNotes]=useState3({});const[noting,setNoting]=useState3({});const[sent,setSent]=useState3(null);const answerable=live&&Boolean(onAnswer)&&!sent;const total=block.questions.length;const q=block.questions[at];const last=at===total-1;function toggle(question,value){setPicked(prev=>{const cur=prev[question.key]??[];if(!question.multi)return{...prev,[question.key]:[value]};return{...prev,[question.key]:cur.includes(value)?cur.filter(v=>v!==value):[...cur,value]}})}function valuesFor(question){const base=picked[question.key]??[];const typed=other[question.key]?.trim();return typed?[...base,OTHER_PREFIX+typed]:base}function labelsFor(question){return valuesFor(question).map(v=>v.startsWith(OTHER_PREFIX)?v.slice(OTHER_PREFIX.length):question.options.find(o=>o.value===v)?.label??v)}const answered=valuesFor(q).length>0;const canGo=q.required===false||answered;function submit(){const result={answers:{},values:{}};const notesOut={};for(const question of block.questions){const values=valuesFor(question);if(values.length===0)continue;result.values[question.key]=values;result.answers[question.label]=labelsFor(question).join("\u060C ");const note=notes[question.key]?.trim();if(note)notesOut[question.label]={notes:note}}if(Object.keys(notesOut).length)result.annotations=notesOut;setSent(result);onAnswer?.(block.id,result)}if(sent){return jsxs3("div",{className:"flex flex-col gap-3 p-4 rounded-card border border-line bg-bg",children:[block.questions.map(question=>jsxs3("div",{className:"flex flex-col gap-1.5",children:[jsx3("span",{className:"text-caption text-muted [text-wrap:pretty]",children:question.label}),jsx3(Picked,{labels:(sent.answers[question.label]??"").split("\u060C ").filter(Boolean),note:sent.annotations?.[question.label]?.notes})]},question.key)),jsxs3("span",{className:"flex items-center gap-1.5 text-caption font-bold text-green",children:[jsx3(Check2,{size:13,strokeWidth:2.6,"aria-hidden":"true"}),"\u0627\u062A\u0628\u0639\u062A"]})]})}return jsxs3("div",{className:"flex flex-col gap-3.5 p-4 rounded-card border border-soft2 bg-tint",children:[jsxs3("span",{className:"flex items-center justify-between gap-3",children:[q.header?jsx3("span",{className:"px-2 h-5 rounded-mark bg-soft text-brand-ink text-micro font-extrabold flex items-center",children:q.header}):jsx3("span",{}),total>1&&jsxs3("span",{className:"flex items-center gap-2 shrink-0",children:[jsx3("span",{"aria-hidden":"true",className:"flex items-center gap-1",children:block.questions.map((qq,i)=>jsx3("span",{className:cn("size-1.5 rounded-full transition-colors",i===at?"bg-brand":i<at?"bg-brand/40":"bg-border/40")},qq.key))}),jsxs3("span",{"data-num":true,className:"text-micro font-bold text-muted whitespace-nowrap",children:[at+1," \u0645\u0646 ",total]})]})]}),jsxs3("div",{className:"flex flex-col gap-2",children:[jsx3("span",{className:"text-ui font-extrabold text-ink [text-wrap:pretty]",children:q.label}),q.hint&&jsx3("span",{className:"text-caption leading-[1.7] text-muted",children:q.hint}),jsx3(ChoiceCards,{name:`${block.id}-${q.key}`,multiple:q.multi,disabled:!answerable,value:q.multi?picked[q.key]??[]:picked[q.key]?.[0]??null,onChange:v=>toggle(q,v),options:q.options.map(o=>({value:o.value,label:o.label,meta:o.description}))}),q.other!==false&&jsx3(Input,{size:"sm",value:other[q.key]??"",onChange:e=>setOther(p=>({...p,[q.key]:e.target.value})),disabled:!answerable,placeholder:q.other?.placeholder??"\u0623\u0648 \u0627\u0643\u062A\u0628 \u0625\u062C\u0627\u0628\u062A\u0643\u2026","aria-label":`\u0625\u062C\u0627\u0628\u0629 \u0623\u062E\u0631\u0649 \u0639\u0644\u0649: ${q.label}`}),noting[q.key]?jsx3(Textarea,{rows:2,value:notes[q.key]??"",onChange:e=>setNotes(p=>({...p,[q.key]:e.target.value})),disabled:!answerable,placeholder:"\u062D\u0627\u062C\u0629 \u062A\u062D\u0628\u0651 \u062A\u0642\u0648\u0644\u0647\u0627 \u0645\u0639 \u0627\u062E\u062A\u064A\u0627\u0631\u0643\u2026","aria-label":`\u0645\u0644\u0627\u062D\u0638\u0629 \u0639\u0644\u0649: ${q.label}`}):answerable&&jsxs3("button",{type:"button",onClick:()=>setNoting(p=>({...p,[q.key]:true})),className:"self-start inline-flex items-center gap-1.5 text-micro font-bold text-muted hover:text-brand cursor-pointer transition-colors",children:[jsx3(MessageSquarePlus,{size:13,"aria-hidden":"true"}),"\u0636\u064A\u0641 \u0645\u0644\u0627\u062D\u0638\u0629"]})]}),answerable&&jsxs3("span",{className:"flex items-center gap-2.5",children:[at>0&&jsx3(Button,{size:"sm",variant:"ghost",onClick:()=>setAt(i=>i-1),children:"\u0631\u062C\u0648\u0639"}),last?jsx3(Button,{size:"sm",onClick:submit,disabled:!canGo,children:block.submitLabel??"\u0627\u0628\u0639\u062A"}):jsx3(Button,{size:"sm",onClick:()=>setAt(i=>i+1),disabled:!canGo,iconEnd:jsx3(ArrowRight,{size:13,className:"rtl:rotate-180","aria-hidden":"true"}),children:"\u0627\u0644\u062A\u0627\u0644\u064A"}),!canGo&&jsx3("span",{className:"text-micro text-muted2",children:"\u0627\u062E\u062A\u0627\u0631 \u0625\u062C\u0627\u0628\u0629 \u0627\u0644\u0623\u0648\u0644"})]})]})}function Picked({labels,note}){if(labels.length===0)return jsx3("span",{className:"text-caption text-muted2",children:"\u0627\u062A\u062E\u0637\u0651\u0649"});return jsxs3("span",{className:"flex flex-col gap-1.5",children:[jsx3("span",{className:"flex flex-wrap gap-1.5",children:labels.map((l,i)=>jsxs3("span",{className:"inline-flex items-center gap-1 h-6 px-2 rounded-mark bg-soft text-brand-ink text-caption font-bold",children:[jsx3(Check2,{size:11,strokeWidth:3,"aria-hidden":"true"}),l]},i))}),note&&jsx3("span",{className:"text-micro leading-[1.7] text-muted border-s-2 border-line ps-2",children:note})]})}import{useEffect as useEffect4,useState as useState4}from"react";import{Check as Check3,Copy as Copy2,RotateCcw as RotateCcw2,Sparkles,X}from"lucide-react";import{Fragment as Fragment2,jsx as jsx4,jsxs as jsxs4}from"react/jsx-runtime";function DraftPanel({draft:source,basis,label,onInsert,onClose,insertLabel="\u0623\u062F\u0631\u0650\u062C",className}){const[attempt,setAttempt]=useState4(0);const[done,setDone]=useState4(false);const{text,streaming,start,finish}=useStreamingText({speed:12});const dynamic=typeof source==="function";useEffect4(()=>{start(dynamic?source(attempt):source)},[attempt,source]);return jsxs4("div",{className:cn("flex flex-col gap-2.5 p-3.5 rounded-card bg-bg border border-line","basis-full order-last w-full",className),children:[jsxs4("span",{className:"flex items-start justify-between gap-3",children:[jsxs4("span",{className:"flex flex-col gap-0.5 min-w-0",children:[jsxs4("span",{className:"flex items-center gap-1.5 text-caption font-extrabold text-ink",children:[jsx4(Sparkles,{size:13,className:"text-brand shrink-0","aria-hidden":"true"}),label]}),jsx4("span",{className:"text-micro leading-[1.65] text-muted",children:basis})]}),onClose&&jsx4("button",{type:"button",onClick:onClose,"aria-label":"\u0625\u063A\u0644\u0627\u0642",className:"shrink-0 size-6 rounded-mark flex items-center justify-center text-muted2 hover:bg-hover hover:text-ink cursor-pointer transition-colors",children:jsx4(X,{size:14,"aria-hidden":"true"})})]}),text===""&&streaming?jsx4(AiThinking,{label:"\u0628\u064A\u0643\u062A\u0628\u2026"}):jsxs4("span",{className:"block text-caption leading-[1.9] text-ink whitespace-pre-wrap [text-wrap:pretty]","aria-live":"polite",children:[text,streaming&&jsx4("span",{"aria-hidden":"true",className:"inline-block w-[2px] h-[1em] align-[-0.15em] ms-0.5 bg-brand animate-pulse"})]}),jsx4("span",{className:"flex items-center gap-2 flex-wrap",children:streaming?jsx4(Button,{size:"sm",variant:"outline",onClick:finish,children:"\u0627\u0639\u0631\u0636\u0647\u0627 \u0643\u0644\u0647\u0627"}):jsxs4(Fragment2,{children:[onInsert&&jsx4(Button,{size:"sm",onClick:()=>{onInsert(text);setDone(true);onClose?.()},icon:jsx4(Check3,{size:13,"aria-hidden":"true"}),children:insertLabel}),jsx4(Button,{size:"sm",variant:"outline",onClick:()=>navigator.clipboard?.writeText(text),icon:jsx4(Copy2,{size:13,"aria-hidden":"true"}),children:"\u0627\u0646\u0633\u062E"}),dynamic&&jsx4(Button,{size:"sm",variant:"ghost",onClick:()=>setAttempt(a=>a+1),icon:jsx4(RotateCcw2,{size:13,"aria-hidden":"true"}),children:"\u0627\u0643\u062A\u0628 \u063A\u064A\u0631\u0647\u0627"})]})}),!streaming&&!done&&jsx4(AiDisclaimer,{children:"\u0645\u0645\u0643\u0646 \u064A\u063A\u0644\u0637 \u2014 \u0627\u0642\u0631\u0627\u0647\u0627 \u0642\u0628\u0644 \u0645\u0627 \u062A\u0646\u0634\u0631\u0647\u0627."})]})}function AiDraft({size="sm",...panel}){const[open,setOpen]=useState4(false);if(!open){return jsx4(Button,{variant:"outline",size,onClick:()=>setOpen(true),icon:jsx4(Sparkles,{size:size==="sm"?13:15,"aria-hidden":"true"}),className:panel.className,children:panel.label})}return jsx4(DraftPanel,{...panel,onClose:()=>setOpen(false)})}import{Fragment as Fragment3,jsx as jsx5}from"react/jsx-runtime";function Markdown({md}){const chunks=md.split(/\n{2,}/);return jsx5(Fragment3,{children:chunks.map((chunk,i)=>{const lines=chunk.split("\n");const bullets=lines.every(l=>/^\s*[-•]\s+/.test(l));const numbers=lines.every(l=>/^\s*\d+[.)]\s+/.test(l));if(bullets||numbers){const items=lines.map(l=>l.replace(/^\s*(?:[-•]|\d+[.)])\s+/,""));const List=numbers?"ol":"ul";return jsx5(List,{className:numbers?"my-2 ps-5 list-decimal marker:text-muted2 flex flex-col gap-1":"my-2 ps-5 list-disc marker:text-muted2 flex flex-col gap-1",children:items.map((it,j)=>jsx5("li",{children:inline(it)},j))},i)}return jsx5("p",{className:"my-2 first:mt-0 last:mb-0 [text-wrap:pretty]",children:inline(chunk)},i)})})}var TOKEN=/(`[^`\n]+`)|(\*\*[^*\n]+\*\*)|(\*[^*\n]+\*)/g;function inline(src){const out=[];let last=0;let m;TOKEN.lastIndex=0;while((m=TOKEN.exec(src))!==null){if(m.index>last)out.push(src.slice(last,m.index));const[full]=m;const key=`${m.index}`;if(full.startsWith("`")){out.push(jsx5("code",{dir:"ltr",className:"px-1 py-px rounded-mark bg-hover text-[0.9em] font-mono text-brand-ink",children:full.slice(1,-1)},key))}else if(full.startsWith("**")){out.push(jsx5("strong",{className:"font-extrabold text-ink",children:full.slice(2,-2)},key))}else{out.push(jsx5("em",{className:"not-italic font-bold",children:full.slice(1,-1)},key))}last=m.index+full.length}if(last<src.length)out.push(src.slice(last));return out}import{Fragment as Fragment4,jsx as jsx6,jsxs as jsxs5}from"react/jsx-runtime";var TONE={good:"green",warn:"amber",bad:"red",plain:"neutral"};var NOTICE_TONE={info:"brand",warn:"amber",danger:"red"};function major(a){return a.minor/10**(a.decimals??2)}function TextBlockView({block}){if(!block.md)return null;return jsx6("div",{className:"text-body leading-[1.95] text-ink2",children:jsx6(Markdown,{md:block.md})})}function MetricBlockView({block}){return jsx6("div",{className:"grid gap-2.5 grid-cols-[repeat(auto-fit,minmax(9.5rem,1fr))]",children:block.items.map((m,i)=>jsx6(StatCard,{tone:TONE[m.tone??"plain"]??"neutral",label:m.label,value:m.amount?jsx6(Money,{value:major(m.amount),currency:isCurrency(m.amount.currency)?m.amount.currency:void 0,compact:true,trimZeros:true}):m.value,hint:m.delta!==void 0?deltaHint(m.delta,m.deltaBasis):void 0},i))})}function deltaHint(delta,basis){const up=delta>0;const flat=delta===0;return jsxs5("span",{className:cn("font-bold",flat?"text-muted2":up?"text-green":"text-red"),children:[flat?"=":up?"\u25B2":"\u25BC"," ",Math.abs(delta),"\u066A",basis?` ${basis}`:""]})}function TableBlockView({block}){const rows=block.rows.map((cells,i)=>{const row={__key:String(i)};block.cols.forEach((c,j)=>{row[c.key]=cells[j]??null});return row});const columns=block.cols.map(c=>({key:c.key,header:c.label,end:c.align==="end",cell:row=>renderCell(row[c.key],c)}));return jsxs5("span",{className:"flex flex-col gap-1.5",children:[block.caption&&jsx6("span",{className:"text-micro text-muted2",children:block.caption}),jsx6(DataTable,{columns,rows,rowKey:r=>r.__key,grid:block.cols.map(c=>c.align==="end"?"1fr":"1.6fr").join("_"),minWidth:block.cols.length*120,mobileCard:row=>jsx6("span",{className:"flex flex-col gap-1",children:block.cols.map(c=>jsxs5("span",{className:"flex items-baseline justify-between gap-3",children:[jsx6("span",{className:"text-micro text-muted2",children:c.label}),jsx6("span",{className:"text-caption text-ink",children:renderCell(row[c.key],c)})]},c.key))})})]})}function renderCell(v,col){if(v===null||v==="")return jsx6("span",{className:"text-muted2",children:"\u2014"});switch(col.format){case"money":return typeof v==="number"?jsx6(Money,{value:v,trimZeros:true}):v;case"badge":return jsx6(Badge,{size:"sm",children:v});case"number":return jsx6("span",{"data-num":true,children:v});default:return v}}function CardsBlockView({block,intents}){return jsx6("div",{className:"grid gap-2.5 grid-cols-[repeat(auto-fill,minmax(13rem,1fr))]",children:block.items.map(c=>jsx6(Card,{children:jsxs5("span",{className:"flex gap-3 items-start",children:[c.img&&jsx6("img",{src:c.img,alt:"",className:"size-12 rounded-sm object-cover bg-hover shrink-0"}),jsxs5("span",{className:"flex flex-col gap-1 min-w-0",children:[jsx6("span",{className:"text-ui font-bold text-ink truncate",children:c.title}),c.subtitle&&jsx6("span",{className:"text-micro text-muted",children:c.subtitle}),c.badge&&jsx6("span",{children:jsx6(Badge,{size:"sm",tone:"brand",children:c.badge})}),c.action&&jsx6(ActionButton,{action:c.action,intents,size:"sm"})]})]})},c.id))})}function ChartBlockView({block}){const labels=block.series.map(p=>String(p.x));const values=block.series.map(p=>p.y);const money=block.unit?.kind==="money";const fmt=v=>block.unit?.kind==="percent"?`${v}\u066A`:v.toLocaleString("ar-EG");if(block.kind==="bar"){return jsx6(BarChart,{labels,series:[{label:"",values}],formatValue:fmt})}return jsx6(TrendChart,{labels:axisLabels(labels),values,pointLabels:labels,formatValue:money?v=>v.toLocaleString("ar-EG"):fmt,height:170})}function axisLabels(all){if(all.length<=3)return all;return[all[0],all[Math.floor(all.length/2)],all[all.length-1]]}function ActionBlockView({block,intents}){const runnable=block.items.filter(a=>intents[a.intent]);if(runnable.length===0)return null;return jsx6("span",{className:"flex flex-wrap gap-2",children:runnable.map((a,i)=>jsx6(ActionButton,{action:a,intents},i))})}function ActionButton({action,intents,size="sm"}){const[asking,setAsking]=useState5(false);const run=intents[action.intent];if(!run)return null;function fire(){setAsking(false);run(action.args)}return jsxs5(Fragment4,{children:[jsx6(Button,{size,variant:action.style==="quiet"?"outline":"primary",onClick:()=>action.confirm?setAsking(true):fire(),children:action.label}),jsx6(Modal,{open:asking,title:action.label,description:action.confirm,onClose:()=>setAsking(false),size:"sm",footer:jsxs5(Fragment4,{children:[jsx6(Button,{variant:"outline",onClick:()=>setAsking(false),children:"\u0625\u0644\u063A\u0627\u0621"}),jsx6(Button,{onClick:fire,children:action.label})]})})]})}function ToolBlockView({block,intents}){const undo=block.undo;const run=undo?intents[undo.intent]:void 0;return jsx6(AiToolCall,{title:block.title,detail:block.detail,state:block.state,onUndo:run&&undo?()=>run(undo.args):void 0,undoLabel:undo?.label})}function NoticeBlockView({block}){return jsx6(Alert,{tone:NOTICE_TONE[block.tone],children:block.text})}function ChipsBlockView({block,onSend}){if(!onSend)return null;const byLabel=new Map(block.items.map(c=>[c.label,c.send]));return jsx6(AiPromptChips,{prompts:block.items.map(c=>c.label),onPick:label=>onSend(byLabel.get(label)??label)})}function BlockView({block,intents,onSend,onInsertDraft,onAnswer,live=true}){switch(block.type){case"text":return jsx6(TextBlockView,{block});case"metric":return jsx6(MetricBlockView,{block});case"table":return jsx6(TableBlockView,{block});case"cards":return jsx6(CardsBlockView,{block,intents});case"chart":return jsx6(ChartBlockView,{block});case"action":return jsx6(ActionBlockView,{block,intents});case"tool":return jsx6(ToolBlockView,{block,intents});case"notice":return jsx6(NoticeBlockView,{block});case"chips":return jsx6(ChipsBlockView,{block,onSend});case"ask":return jsx6(AskCard,{block,onAnswer,live});case"draft":return jsx6(DraftPanel,{draft:block.text,basis:block.basis,label:"\u0645\u0633\u0648\u0651\u062F\u0629",onInsert:onInsertDraft});default:return null}}import{jsx as jsx7,jsxs as jsxs6}from"react/jsx-runtime";var NO_INTENTS={};function ReplyView({reply,streaming,intents=NO_INTENTS,onSend,onInsertDraft,onAnswer,live=true,onRetry,onFeedback,className}){return jsx7(AiMessage,{role:"assistant",fill:true,streaming,sources:reply.sources,copyText:plainText(reply),onRetry,onFeedback,children:jsxs6("span",{className:cn("flex flex-col gap-3",className),children:[reply.blocks.map((block,i)=>jsx7(BlockView,{block,intents,onSend,onInsertDraft,onAnswer,live},i)),reply.disclaimer!==false&&!streaming&&jsx7(AiDisclaimer,{})]})})}function plainText(reply){const parts=[];for(const b of reply.blocks){switch(b.type){case"text":parts.push(b.md);break;case"metric":parts.push(b.items.map(m=>`${m.label}: ${m.value}`).join(" \xB7 "));break;case"table":parts.push([b.cols.map(c=>c.label).join(" "),...b.rows.map(r=>r.map(c=>c??"").join(" "))].join("\n"));break;case"cards":parts.push(b.items.map(c=>c.title).join("\n"));break;case"draft":parts.push(b.text);break;case"tool":parts.push(b.detail?`${b.title} \u2014 ${b.detail}`:b.title);break;case"notice":parts.push(b.text);break;case"ask":parts.push(b.questions.map(q=>q.label).join("\n"));break;case"chart":case"action":case"chips":break}}return parts.filter(Boolean).join("\n\n")}import{useCallback as useCallback2,useEffect as useEffect5,useRef as useRef4,useState as useState6}from"react";import{parseEvent,parseSSE,reduce}from"@qumra/jawab-ai";function useReplyStream(url,init){const[reply,setReply]=useState6(null);const[streaming,setStreaming]=useState6(false);const[error,setError]=useState6(null);const abort=useRef4(null);const lastInput=useRef4("");useEffect5(()=>()=>abort.current?.abort(),[]);const stop=useCallback2(()=>{abort.current?.abort();abort.current=null;setStreaming(false)},[]);const send=useCallback2(text=>{const question=text.trim();if(!question)return;abort.current?.abort();const ctrl=new AbortController;abort.current=ctrl;lastInput.current=question;setError(null);setReply(null);setStreaming(true);void(async()=>{try{const res=await fetch(url,{method:"POST",headers:{"content-type":"application/json",accept:"text/event-stream"},body:JSON.stringify({input:question}),signal:ctrl.signal,...init});if(!res.ok||!res.body){throw new StreamError("http_"+res.status,`\u0627\u0644\u062E\u0627\u062F\u0645 \u0631\u062C\u0651\u0639 ${res.status}`)}const decoder=new TextDecoder;const readerStream=res.body.getReader();let rest="";let state=null;for(;;){const{done,value}=await readerStream.read();if(done)break;rest+=decoder.decode(value,{stream:true});const{events,rest:tail}=parseSSE(rest);rest=tail;for(const raw of events){const ev=parseEvent(raw);if(!ev)continue;if(ev.e==="error")throw new StreamError(ev.code,ev.message);state=reduce(state,ev);setReply(state);if(ev.e==="done")break}}setStreaming(false)}catch(e){if(ctrl.signal.aborted)return;const se=e;setError({code:se.code??"unknown",message:se.message??"\u0627\u0644\u0627\u062A\u0635\u0627\u0644 \u0627\u062A\u0642\u0637\u0639.",lastInput:lastInput.current});setStreaming(false)}})()},[url,init]);return{reply,streaming,error,send,stop}}var StreamError=class extends Error{code;constructor(code,message){super(message);this.name="StreamError";this.code=code}};export{AiAvatar,AiComposer,AiDisclaimer,AiDraft,AiMessage,AiPromptChips,AiSources,AiThinking,AiToolCall,AskCard,DraftPanel,ReplyView,useMicLevel,useReplyStream,useStreamingText};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{TONE_SOFT,cn,useUIText}from"./chunk-YJ45RGS6.js";import{useEffect,useId}from"react";import{AlertTriangle,CheckCircle2,Info,X,XCircle}from"lucide-react";import{jsx,jsxs}from"react/jsx-runtime";function Sheet({open,title,onClose,action,children,closeLabel}){const ui=useUIText();useEffect(()=>{if(!open)return;function onKey(e){if(e.key==="Escape")onClose()}document.addEventListener("keydown",onKey);return()=>document.removeEventListener("keydown",onKey)},[open,onClose]);if(!open)return null;return jsxs("div",{className:"fixed inset-0 z-50 flex flex-col justify-end",role:"dialog","aria-modal":"true","aria-label":title,children:[jsx("button",{type:"button","aria-label":closeLabel??ui.close,onClick:onClose,className:"flex-1 bg-black/50 backdrop-blur-[3px] cursor-default animate-[fade-in_0.2s_ease-out]"}),jsxs("div",{className:cn("bg-surface rounded-t-section max-h-[82dvh] flex flex-col overflow-clip shadow-sheet","animate-[sheet-up_0.26s_cubic-bezier(.22,.61,.36,1)]","pb-[env(safe-area-inset-bottom)]"),children:[jsx("button",{type:"button",onClick:onClose,"aria-label":closeLabel??ui.close,className:"shrink-0 pt-3 pb-1.5 flex justify-center cursor-grab active:cursor-grabbing",children:jsx("span",{"aria-hidden":"true",className:"h-1.5 w-11 rounded-full bg-border"})}),jsxs("div",{className:"shrink-0 flex items-center justify-between gap-3 px-5 pb-3",children:[jsx("span",{className:"text-h4 font-black tracking-tight",children:title}),jsxs("span",{className:"flex items-center gap-3",children:[action,jsx("button",{type:"button",onClick:onClose,"aria-label":closeLabel??ui.close,className:"size-9 rounded-full bg-bg flex items-center justify-center text-muted active:bg-hover active:scale-95 transition-transform cursor-pointer",children:jsx(X,{size:17,strokeWidth:2.4,"aria-hidden":"true"})})]})]}),jsx("div",{className:"flex-1 min-h-0 overflow-y-auto px-3 pb-4 flex flex-col overscroll-contain",children})]})]})}function Modal({open,title,description,onClose,footer,children,size="md",bodyClassName,closeLabel}){const ui=useUIText();const titleId=useId();useEffect(()=>{if(!open)return;function onKey(e){if(e.key==="Escape")onClose()}document.addEventListener("keydown",onKey);return()=>document.removeEventListener("keydown",onKey)},[open,onClose]);if(!open)return null;const widths={sm:"max-w-md",md:"max-w-xl",lg:"max-w-3xl"};return jsxs("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-4",role:"dialog","aria-modal":"true","aria-labelledby":titleId,children:[jsx("button",{type:"button","aria-label":closeLabel??ui.close,onClick:onClose,className:"absolute inset-0 bg-black/45 backdrop-blur-[2px] cursor-default"}),jsxs("div",{className:cn("relative w-full bg-surface rounded-lg border border-line flex flex-col max-h-[85dvh] animate-qfade shadow-modal",widths[size]),children:[jsxs("header",{className:"shrink-0 flex items-start justify-between gap-4 p-5 border-b border-line",children:[jsxs("div",{className:"flex flex-col gap-1 min-w-0",children:[jsx("h2",{id:titleId,className:"text-h4 font-extrabold text-ink m-0",children:title}),description&&jsx("p",{className:"text-ui text-muted m-0",children:description})]}),jsx("button",{type:"button",onClick:onClose,"aria-label":closeLabel??ui.close,className:"shrink-0 size-8 rounded-sm flex items-center justify-center text-muted hover:bg-hover hover:text-ink transition-colors cursor-pointer",children:jsx(X,{size:17,"aria-hidden":"true"})})]}),children&&jsx("div",{className:cn("flex-1 min-h-0 overflow-y-auto p-5",bodyClassName),children}),footer&&jsx("footer",{className:"shrink-0 flex items-center justify-end gap-2.5 p-5 border-t border-line",children:footer})]})]})}function Drawer({open,title,description,onClose,footer,children,bodyClassName,closeLabel}){const ui=useUIText();const titleId=useId();useEffect(()=>{if(!open)return;function onKey(e){if(e.key==="Escape")onClose()}document.addEventListener("keydown",onKey);return()=>document.removeEventListener("keydown",onKey)},[open,onClose]);if(!open)return null;return jsxs("div",{className:"fixed inset-0 z-50 flex",role:"dialog","aria-modal":"true","aria-labelledby":titleId,children:[jsx("button",{type:"button","aria-label":closeLabel??ui.close,onClick:onClose,className:"flex-1 bg-black/45 backdrop-blur-[2px] cursor-default"}),jsxs("aside",{className:"w-full sm:w-[420px] bg-surface border-s border-line flex flex-col animate-qfade",children:[jsxs("header",{className:"shrink-0 h-16 px-4 border-b border-line flex items-center justify-between gap-3",children:[jsxs("span",{className:"flex flex-col gap-0.5 min-w-0",children:[jsx("span",{id:titleId,className:"text-lead font-extrabold truncate",children:title}),description&&jsx("span",{className:"text-caption text-muted truncate",children:description})]}),jsx("button",{type:"button",onClick:onClose,"aria-label":closeLabel??ui.close,className:"shrink-0 size-8 rounded-sm flex items-center justify-center text-muted hover:bg-hover hover:text-ink transition-colors cursor-pointer",children:jsx(X,{size:17,"aria-hidden":"true"})})]}),children&&jsx("div",{className:cn("flex-1 min-h-0 overflow-y-auto",bodyClassName??"p-4"),children}),footer&&jsx("footer",{className:"shrink-0 p-4 border-t border-line flex gap-2.5",children:footer})]})]})}var ALERT_ICON={neutral:Info,brand:Info,amber:AlertTriangle,green:CheckCircle2,red:XCircle,violet:Info};var ALERT_BORDER={neutral:"border-line",brand:"border-soft2",amber:"border-amber-line",green:"border-green-line",red:"border-red-line",violet:"border-violet-line"};function Alert({tone="brand",title,children,actions}){const Icon=ALERT_ICON[tone];const urgent=tone==="red"||tone==="amber";return jsxs("div",{role:urgent?"alert":"status",className:cn("flex items-start gap-3 p-4 rounded-card border",TONE_SOFT[tone],ALERT_BORDER[tone]),children:[jsx(Icon,{size:18,strokeWidth:2,"aria-hidden":"true"}),jsxs("div",{className:"flex flex-col gap-1.5 flex-1 min-w-0",children:[title&&jsx("span",{className:"text-body font-extrabold",children:title}),children&&jsx("span",{className:"text-ui leading-[1.7] opacity-90 [text-wrap:pretty]",children}),actions&&jsx("span",{className:"flex items-center gap-2 mt-1",children:actions})]})]})}function Toast({children,action,icon}){return jsxs("div",{role:"status","aria-live":"polite",className:"flex items-center gap-3 px-4 py-3.5 rounded-card bg-brand-900 shadow-toast animate-[fade-in_0.18s_ease-out]",children:[icon??jsx(CheckCircle2,{size:17,className:"text-brand-100 shrink-0","aria-hidden":"true"}),jsx("span",{className:"text-body font-bold text-white flex-1",children}),action]})}function EmptyState({icon:Icon,title,description,action}){return jsxs("div",{className:"flex flex-col items-center justify-center gap-2.5 py-12 px-5 text-center",children:[Icon&&jsx("span",{"aria-hidden":"true",className:"size-12 rounded-card bg-hover flex items-center justify-center text-muted mb-1",children:jsx(Icon,{size:21})}),jsx("span",{className:"text-lead font-extrabold text-ink",children:title}),description&&jsx("span",{className:"text-ui leading-[1.75] text-muted max-w-note [text-wrap:pretty]",children:description}),action&&jsx("span",{className:"mt-1",children:action})]})}export{Sheet,Modal,Drawer,Alert,Toast,EmptyState};
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{cn,useUIText}from"./chunk-YJ45RGS6.js";import{cloneElement,isValidElement,useCallback,useEffect,useId,useRef,useState}from"react";import{createPortal}from"react-dom";import{AlertTriangle,CheckCircle2,Info,Loader2,X,XCircle}from"lucide-react";import{jsx,jsxs}from"react/jsx-runtime";function useToasts(){const[toasts,setToasts]=useState([]);const seq=useRef(0);const timers=useRef(new Map);const dismiss=useCallback(id=>{const t=timers.current.get(id);if(t)clearTimeout(t);timers.current.delete(id);setToasts(prev=>prev.filter(x=>x.id!==id))},[]);const push=useCallback(input=>{const id=++seq.current;const duration=input.duration??(input.actionLabel?6500:3800);setToasts(prev=>[...prev.slice(-3),{...input,id}]);if(duration>0&&!input.pending){timers.current.set(id,setTimeout(()=>dismiss(id),duration))}return id},[dismiss]);const update=useCallback((id,patch)=>{setToasts(prev=>prev.map(t=>t.id===id?{...t,...patch}:t))},[]);const clear=useCallback(()=>{timers.current.forEach(clearTimeout);timers.current.clear();setToasts([])},[]);return{toasts,push,dismiss,update,clear}}var TOAST_ICON={neutral:Info,brand:Info,green:CheckCircle2,amber:AlertTriangle,red:XCircle};var TOAST_ACCENT={neutral:"text-muted2",brand:"text-brand-100",green:"text-mint",amber:"text-amber",red:"text-red-100"};function ToastHost({toasts,onDismiss,closeLabel}){const ui=useUIText();if(toasts.length===0)return null;return jsx("div",{role:"region","aria-label":ui.alerts,className:"fixed z-[60] bottom-4 inset-x-4 sm:inset-x-auto sm:start-5 sm:w-[360px] flex flex-col gap-2 pointer-events-none",children:toasts.map(t=>{const Icon=TOAST_ICON[t.tone];return jsxs("div",{role:t.tone==="red"?"alert":"status",className:"pointer-events-auto flex items-start gap-3 p-3.5 rounded-card bg-night text-white shadow-toast animate-[toast-in_.22s_cubic-bezier(.22,.61,.36,1)]",children:[jsx("span",{"aria-hidden":"true",className:cn("shrink-0 mt-0.5",TOAST_ACCENT[t.tone]),children:t.pending?jsx(Loader2,{size:17,className:"animate-spin"}):jsx(Icon,{size:17})}),jsxs("span",{className:"flex-1 min-w-0 flex flex-col gap-0.5",children:[jsx("span",{className:"text-ui font-bold leading-snug",children:t.title}),t.description&&jsx("span",{className:"text-caption leading-[1.6] text-white/65",children:t.description})]}),t.actionLabel&&jsx("button",{type:"button",onClick:()=>{t.onAction?.();onDismiss(t.id)},className:"shrink-0 text-ui font-extrabold text-mint cursor-pointer hover:underline underline-offset-4",children:t.actionLabel}),jsx("button",{type:"button",onClick:()=>onDismiss(t.id),"aria-label":closeLabel??ui.close,className:"shrink-0 text-white/40 hover:text-white cursor-pointer transition-colors",children:jsx(X,{size:15,"aria-hidden":"true"})})]},t.id)})})}function Tooltip({content,children,side="top"}){const[open,setOpen]=useState(false);const anchor=useRef(null);const tip=useRef(null);const id=useId();const GAP=7;const EDGE=8;const place=useCallback(()=>{const el=tip.current;const host=anchor.current;if(!el||!host)return;const r=host.getBoundingClientRect();const w=el.offsetWidth;const h=el.offsetHeight;const vw=document.documentElement.clientWidth;const vh=document.documentElement.clientHeight;const left=Math.min(Math.max(r.left+r.width/2-w/2,EDGE),Math.max(EDGE,vw-EDGE-w));const above=side==="top"?r.top-GAP-h>=EDGE:r.bottom+GAP+h>vh-EDGE;const top=above?r.top-GAP-h:r.bottom+GAP;el.style.left=`${left}px`;el.style.top=`${Math.min(Math.max(top,EDGE),Math.max(EDGE,vh-EDGE-h))}px`;el.style.visibility="visible"},[side]);useEffect(()=>{if(!open)return;window.addEventListener("scroll",place,{capture:true,passive:true});window.addEventListener("resize",place,{passive:true});return()=>{window.removeEventListener("scroll",place,{capture:true});window.removeEventListener("resize",place)}},[open,place]);const mount=useCallback(el=>{tip.current=el;if(el)place()},[place]);const described=isValidElement(children)?cloneElement(children,{"aria-describedby":open?id:void 0}):children;return jsxs("span",{ref:anchor,className:"relative inline-flex",onMouseEnter:()=>setOpen(true),onMouseLeave:()=>setOpen(false),onFocus:()=>setOpen(true),onBlur:()=>setOpen(false),children:[described,open&&typeof document!=="undefined"&&createPortal(jsx("span",{id,role:"tooltip",ref:mount,style:{visibility:"hidden",left:0,top:0},className:cn("fixed z-[60] w-max max-w-[220px] px-2.5 py-1.5 rounded-xs","bg-night text-white text-caption leading-[1.6] text-center shadow-tip","animate-[fade-in_.12s_ease-out] pointer-events-none"),children:content}),document.body)]})}export{useToasts,ToastHost,Tooltip};
2
+ import{cn,useUIText}from"./chunk-YJ45RGS6.js";import{cloneElement,isValidElement,useCallback,useEffect,useId,useRef,useState}from"react";import{createPortal}from"react-dom";import{AlertTriangle,CheckCircle2,Info,Loader2,X,XCircle}from"lucide-react";import{jsx,jsxs}from"react/jsx-runtime";function useToasts(){const[toasts,setToasts]=useState([]);const seq=useRef(0);const timers=useRef(new Map);const dismiss=useCallback(id=>{const t=timers.current.get(id);if(t)clearTimeout(t);timers.current.delete(id);setToasts(prev=>prev.filter(x=>x.id!==id))},[]);const push=useCallback(input=>{const id=++seq.current;const duration=input.duration??(input.actionLabel?6500:3800);setToasts(prev=>[...prev.slice(-3),{...input,id}]);if(duration>0&&!input.pending){timers.current.set(id,setTimeout(()=>dismiss(id),duration))}return id},[dismiss]);const update=useCallback((id,patch)=>{setToasts(prev=>prev.map(t=>t.id===id?{...t,...patch}:t))},[]);const clear=useCallback(()=>{timers.current.forEach(clearTimeout);timers.current.clear();setToasts([])},[]);return{toasts,push,dismiss,update,clear}}var TOAST_ICON={neutral:Info,brand:Info,green:CheckCircle2,amber:AlertTriangle,red:XCircle};var TOAST_ACCENT={neutral:"text-muted2",brand:"text-brand-100",green:"text-mint",amber:"text-amber",red:"text-red-100"};function ToastHost({toasts,onDismiss,closeLabel}){const ui=useUIText();if(toasts.length===0)return null;return jsx("div",{role:"region","aria-label":ui.alerts,className:"fixed z-[60] bottom-4 inset-x-4 sm:inset-x-auto sm:start-5 sm:w-[360px] flex flex-col gap-2 pointer-events-none",children:toasts.map(t=>{const Icon=TOAST_ICON[t.tone];return jsxs("div",{role:t.tone==="red"?"alert":"status",className:"pointer-events-auto flex items-start gap-3 p-3.5 rounded-card bg-night text-white shadow-toast animate-[toast-in_.22s_cubic-bezier(.22,.61,.36,1)]",children:[jsx("span",{"aria-hidden":"true",className:cn("shrink-0 mt-0.5",TOAST_ACCENT[t.tone]),children:t.pending?jsx(Loader2,{size:17,className:"animate-spin"}):jsx(Icon,{size:17})}),jsxs("span",{className:"flex-1 min-w-0 flex flex-col gap-0.5",children:[jsx("span",{className:"text-ui font-bold leading-snug",children:t.title}),t.description&&jsx("span",{className:"text-caption leading-[1.6] text-white/65",children:t.description})]}),t.actionLabel&&jsx("button",{type:"button",onClick:()=>{t.onAction?.();onDismiss(t.id)},className:"shrink-0 text-ui font-extrabold text-mint cursor-pointer hover:underline underline-offset-4",children:t.actionLabel}),jsx("button",{type:"button",onClick:()=>onDismiss(t.id),"aria-label":closeLabel??ui.close,className:"shrink-0 text-white/40 hover:text-white cursor-pointer transition-colors",children:jsx(X,{size:15,"aria-hidden":"true"})})]},t.id)})})}function Tooltip({content,children,side="top",size="sm"}){const[open,setOpen]=useState(false);const anchor=useRef(null);const tip=useRef(null);const id=useId();const GAP=7;const EDGE=8;const place=useCallback(()=>{const el=tip.current;const host=anchor.current;if(!el||!host)return;const r=host.getBoundingClientRect();const w=el.offsetWidth;const h=el.offsetHeight;const vw=document.documentElement.clientWidth;const vh=document.documentElement.clientHeight;const left=Math.min(Math.max(r.left+r.width/2-w/2,EDGE),Math.max(EDGE,vw-EDGE-w));const above=side==="top"?r.top-GAP-h>=EDGE:r.bottom+GAP+h>vh-EDGE;const top=above?r.top-GAP-h:r.bottom+GAP;el.style.left=`${left}px`;el.style.top=`${Math.min(Math.max(top,EDGE),Math.max(EDGE,vh-EDGE-h))}px`;el.style.visibility="visible"},[side]);useEffect(()=>{if(!open)return;window.addEventListener("scroll",place,{capture:true,passive:true});window.addEventListener("resize",place,{passive:true});return()=>{window.removeEventListener("scroll",place,{capture:true});window.removeEventListener("resize",place)}},[open,place]);const mount=useCallback(el=>{tip.current=el;if(el)place()},[place]);const described=isValidElement(children)?cloneElement(children,{"aria-describedby":open?id:void 0}):children;return jsxs("span",{ref:anchor,className:"relative inline-flex",onMouseEnter:()=>setOpen(true),onMouseLeave:()=>setOpen(false),onFocus:()=>setOpen(true),onBlur:()=>setOpen(false),children:[described,open&&typeof document!=="undefined"&&createPortal(jsx("span",{id,role:"tooltip",ref:mount,style:{visibility:"hidden",left:0,top:0},className:cn("fixed z-[60] w-max rounded-xs","bg-night text-white text-caption leading-[1.6] shadow-tip","animate-[fade-in_.12s_ease-out] pointer-events-none",size==="md"?"max-w-xs px-3 py-2 text-start":"max-w-[220px] px-2.5 py-1.5 text-center"),children:content}),document.body)]})}export{useToasts,ToastHost,Tooltip};
package/dist/editor.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
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={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'","&apos;":"'"};function decode(s){return s.replace(/&(amp|lt|gt|quot|#39|apos);/g,m=>ENTITIES[m]??m)}function encode(s){return s.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}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-HSZOC7QG.js";import{Button,Input}from"./chunk-EM4MF5B3.js";import{Modal}from"./chunk-4ZNTBLVW.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={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'","&apos;":"'"};function decode(s){return s.replace(/&(amp|lt|gt|quot|#39|apos);/g,m=>ENTITIES[m]??m)}function encode(s){return s.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}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
@@ -1092,7 +1092,7 @@ declare function Sheet({ open, title, onClose, action, children, closeLabel, }:
1092
1092
  children: ReactNode;
1093
1093
  closeLabel?: string;
1094
1094
  }): react.JSX.Element | null;
1095
- declare function Modal({ open, title, description, onClose, footer, children, size, closeLabel, }: {
1095
+ declare function Modal({ open, title, description, onClose, footer, children, size, bodyClassName, closeLabel, }: {
1096
1096
  open: boolean;
1097
1097
  title: ReactNode;
1098
1098
  description?: ReactNode;
@@ -1100,6 +1100,14 @@ declare function Modal({ open, title, description, onClose, footer, children, si
1100
1100
  footer?: ReactNode;
1101
1101
  children?: ReactNode;
1102
1102
  size?: 'sm' | 'md' | 'lg';
1103
+ /**
1104
+ * يُضاف لجسم النافذة — نفس `Sheet`.
1105
+ *
1106
+ * لمحتوى فيه جزء ثابت وجزء يمرّر (بحث فوق قايمة): `flex flex-col` هنا
1107
+ * يخلّي الجسم **سقفاً صريحاً** لأبنائه، فالقايمة بـ`flex-auto min-h-0`
1108
+ * تاخد المتبقّي بالظبط بدل سقف رقميّ يتخمَّن. الشرح عند `Picker`.
1109
+ */
1110
+ bodyClassName?: string;
1103
1111
  closeLabel?: string;
1104
1112
  }): react.JSX.Element | null;
1105
1113
  /** بيفتح من inline-end — الشمال في العربي واليمين في الإنجليزي، لوحده */
@@ -1326,10 +1334,23 @@ declare function ToastHost({ toasts, onDismiss, closeLabel, }: {
1326
1334
  * بتحطّها على العنصر الحقيقيّ لا على غلافه، لأن الغلاف مش هو اللي
1327
1335
  * بيتركّز عليه.
1328
1336
  */
1329
- declare function Tooltip({ content, children, side, }: {
1337
+ declare function Tooltip({ content, children, side, size, }: {
1330
1338
  content: ReactNode;
1331
1339
  children: ReactNode;
1332
1340
  side?: 'top' | 'bottom';
1341
+ /**
1342
+ * `sm` لكلمتين على زرّ أيقونة، و`md` لفقرة شرح.
1343
+ *
1344
+ * ── ⚠️ ليه مقاسين لا عرض حرّ ─────────────────────────────────────────
1345
+ * ٢٢٠ بكسل متوسّطة كانت على مقاس «بيحذف نهائياً». وشرح رقم في كارت
1346
+ * («الطلبات المدفوعة اللي اتسلّمت… بلا شحن ولا ضريبة») بيطلع فيها
1347
+ * خمس سطور متوسّطة — والفقرة المتوسّطة بتتقري مسنّنة، كل سطر بيبدأ من
1348
+ * مكان. فـ`md` أعرض (`max-w-xs`، ٣٢٠) وبتبدأ من أوّل السطر وبحشوة
1349
+ * أوسع: فقرة تتقري لا شارة.
1350
+ *
1351
+ * والعرض من السلّم لا رقم حرّ — نفس قاعدة ٦.
1352
+ */
1353
+ size?: 'sm' | 'md';
1333
1354
  }): react.JSX.Element;
1334
1355
 
1335
1356
  interface Option {