diff --git a/lib/platform-bible-react/dist/experimental.cjs b/lib/platform-bible-react/dist/experimental.cjs index efe5a6cad36..a9e90d1aec7 100644 --- a/lib/platform-bible-react/dist/experimental.cjs +++ b/lib/platform-bible-react/dist/experimental.cjs @@ -1,11 +1,4 @@ -"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./resizable-DLBXOT7I.cjs"),t=require("react/jsx-runtime"),K=require("platform-bible-utils"),B=require("lucide-react"),l=require("react");function Y(r,n=50){const[i,s]=l.useState(n),c=l.useRef(null);return l.useEffect(()=>{s(n)},[r,n]),l.useEffect(()=>{if(i>=r.length)return;const d=c.current,g=new IntersectionObserver(([b])=>{b.isIntersecting&&s(x=>Math.min(x+n,r.length))},{threshold:0});return d&&g.observe(d),()=>g.disconnect()},[i,r.length,n]),{visibleItems:r.slice(0,i),sentinelRef:c,hasMore:ir[n]??n;function M({label:r,resources:n,onSelect:i,showCheckmark:s}){if(n.length!==0)return t.jsxs(t.Fragment,{children:[t.jsx(a.TableRow,{className:"tw:border-0 tw:hover:bg-transparent",children:t.jsx(a.TableCell,{colSpan:4,className:"tw:border-0 tw:pt-4 tw:pb-0",children:t.jsx(a.Label,{className:"tw:text-xs tw:tracking-wider tw:text-muted-foreground tw:uppercase",children:r})})}),n.map(c=>t.jsxs(a.TableRow,{className:i?"tw:cursor-pointer tw:border-0":"tw:pointer-events-none tw:border-0",role:i?"button":void 0,"aria-label":i?c.displayName:void 0,onClick:i?()=>i(c):void 0,onKeyDown:i?d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),i(c))}:void 0,children:[t.jsx(a.TableCell,{className:"tw:w-5 tw:border-0 tw:py-1 tw:pr-1",children:s&&t.jsxs(t.Fragment,{children:[t.jsx(B.Check,{className:"tw:h-3.5 tw:w-3.5","aria-hidden":!0}),t.jsx("span",{className:"tw:sr-only",children:r})]})}),t.jsx(a.TableCell,{className:"tw:border-0 tw:py-1 tw:pr-2 tw:font-normal tw:whitespace-nowrap",children:c.displayName}),t.jsx(a.TableCell,{className:"tw:border-0 tw:py-1 tw:pl-2",children:c.fullName}),t.jsx(a.TableCell,{className:"tw:border-0 tw:py-1 tw:pl-4 tw:text-right tw:text-muted-foreground",children:c.bestLanguageName})]},c.dblEntryUid))]})}function Z(r,n){if(!n)return!0;const i=n.toLowerCase();return r.displayName.toLowerCase().includes(i)||r.fullName.toLowerCase().includes(i)||r.bestLanguageName.toLowerCase().includes(i)}function W({allResources:r,isResourcesLoading:n,resourceType:i,selectedResourceIds:s,localizedStrings:c,allowDeselect:d,onSelect:g}){const[b,x]=l.useState(""),[w,U]=l.useState([]),h=l.useMemo(()=>r.filter(e=>!i||e.type===i).filter(e=>Z(e,b)).filter(e=>w.length===0||w.includes(e.bestLanguageName)),[r,i,b,w]),k=l.useMemo(()=>h.filter(e=>s==null?void 0:s.includes(e.dblEntryUid)),[h,s]),v=l.useMemo(()=>h.filter(e=>e.installed&&!(s!=null&&s.includes(e.dblEntryUid))),[h,s]),L=l.useMemo(()=>h.filter(e=>!e.installed&&!(s!=null&&s.includes(e.dblEntryUid))),[h,s]),{visibleItems:D,sentinelRef:A,hasMore:y}=Y(L),z=l.useMemo(()=>Array.from(new Set(r.map(e=>e.bestLanguageName))).map(e=>({label:e,value:e})),[r]),_=k.length===0&&v.length===0&&L.length===0,N=f(c,"%resourcePicker_title%"),T=f(c,"%resourcePicker_search_placeholder%"),j=f(c,"%resourcePicker_language_filter_any%"),I=f(c,"%resourcePicker_section_already_selected%"),S=f(c,"%resourcePicker_section_installed%"),C=f(c,"%resourcePicker_section_available_to_download%"),q=f(c,"%resourcePicker_no_results%"),m=f(c,"%resourcePicker_showing_count%"),E=l.useMemo(()=>{if(w.length===z.length||w.length===0)return j;if(w.length===1){const e=z.find(u=>u.value===w[0]);if(e)return e.label}return K.formatReplacementString(f(c,"%resourcePicker_language_filter_multipleSelected%"),{selectCount:w.length})},[w,z,j,c]),o=b.length>0||w.length>0;return t.jsxs(t.Fragment,{children:[t.jsx(a.DialogHeader,{className:"tw:px-4 tw:pt-4",children:t.jsx(a.DialogTitle,{children:N})}),t.jsxs("div",{className:"tw:flex tw:gap-2 tw:p-4",children:[t.jsx(a.SearchBar,{value:b,onSearch:x,placeholder:T,isFullWidth:!0}),t.jsx(a.MultiSelectComboBox,{entries:z,selected:w,onChange:U,customSelectedText:E,placeholder:j,variant:"outline"})]}),o&&t.jsx("p",{className:"tw:px-4 tw:pb-1 tw:text-right tw:text-xs tw:text-muted-foreground",children:K.formatReplacementString(m,{filtered:h.length,total:r.length})}),t.jsxs("div",{className:"tw:min-h-0 tw:flex-1 tw:overflow-y-auto tw:px-4 tw:pb-4",children:[n&&t.jsx("p",{className:"tw:py-8 tw:text-center",children:t.jsx(a.Spinner,{})}),_&&!n&&t.jsx("p",{className:"tw:py-8 tw:text-center tw:text-muted-foreground",children:q}),!_&&!n&&t.jsx(a.Table,{children:t.jsxs(a.TableBody,{children:[t.jsx(M,{label:I,resources:k,onSelect:d?g:void 0,showCheckmark:!0}),t.jsx(M,{label:S,resources:v,onSelect:g}),t.jsx(M,{label:C,resources:D,onSelect:g}),y&&t.jsx(a.TableRow,{className:"tw:border-0",children:t.jsx(a.TableCell,{colSpan:4,className:"tw:border-0 tw:p-0",children:t.jsx("div",{ref:A,"aria-hidden":!0})})})]})})]})]})}function J({items:r,renderItem:n,renderDetailContent:i,onItemClick:s,selectedItemId:c,emptyStateMessage:d="No items found",detailRegionLabel:g="Selected item details",isLoading:b=!1,variant:x="text",showSourceLanguage:w=!1,showTransliteration:U=!1,onCharacterPress:h,className:k}){const[v,L]=l.useState(),D=l.useRef(null),A=c??v,y=l.useMemo(()=>v?r.find(o=>o.id===v):void 0,[v,r]),z=l.useMemo(()=>r.map(o=>({id:o.id})),[r]),_=o=>{s==null||s(o),i&&L(o.id===v?void 0:o.id)},N=o=>{const e=r.find(u=>u.id===o.id);e&&_(e)},{listboxRef:T,activeId:j,handleKeyDown:I,focusOption:S}=a.useListbox({options:z,onOptionSelect:N,onCharacterPress:h}),C=()=>{const o=v;L(void 0),o&&requestAnimationFrame(()=>{var e;S(o),(e=T.current)==null||e.focus()})},q=l.useRef(null);if(l.useEffect(()=>{if(!y)return;const o=q.current;if(!o)return;const e=u=>{u.key==="Escape"&&(u.preventDefault(),C())};return o.addEventListener("keydown",e),()=>o.removeEventListener("keydown",e)},[y]),b)return t.jsx("div",{className:a.cn("tw:flex tw:flex-col tw:gap-2 tw:p-2",k),children:Array.from({length:6},(o,e)=>t.jsx(a.Skeleton,{className:a.cn("tw:h-12 tw:w-full tw:rounded",{"tw:h-20":x==="thumbnail"})},e))});if(r.length===0)return t.jsx("div",{className:a.cn("tw:flex tw:items-center tw:justify-center tw:p-8 tw:text-sm tw:text-muted-foreground",k),children:d});const m=t.jsx("ul",{role:"listbox",tabIndex:0,ref:T,"aria-activedescendant":j??void 0,className:"tw:outline-none tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-1 tw:focus:ring-offset-background",onKeyDown:I,children:r.map(o=>{const e=A===o.id;return t.jsx("li",{id:o.id,role:"option","aria-selected":e,tabIndex:-1,onClick:()=>_(o),onKeyDown:u=>{(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),_(o))},className:a.cn("tw:flex tw:cursor-pointer tw:items-center tw:gap-3 tw:p-2 tw:outline-none",{"tw:bg-muted":e,"tw:hover:bg-muted":!e}),children:n?n(o):t.jsx(Q,{item:o,variant:x,showSourceLanguage:w,showTransliteration:U})},o.id)})}),E=i&&y?i(y,C):void 0;return t.jsx("div",{ref:D,className:a.cn("tw:relative tw:flex tw:h-full tw:overflow-hidden",k),children:E?t.jsxs(a.ResizablePanelGroup,{direction:"horizontal",className:"tw:h-full tw:w-full",children:[t.jsx(a.ResizablePanel,{defaultSize:33.3333,minSize:20,children:t.jsx("div",{className:"tw:h-full tw:overflow-y-auto",children:m})}),t.jsx(a.ResizableHandle,{}),t.jsx(a.ResizablePanel,{defaultSize:66.6667,minSize:30,children:t.jsx("div",{ref:q,role:"region","aria-label":g,className:"tw:h-full tw:overflow-y-auto tw:bg-background tw:p-4",children:E})})]}):t.jsx("div",{className:"tw:h-full tw:w-full tw:overflow-y-auto",children:m})})}function Q({item:r,variant:n,showSourceLanguage:i,showTransliteration:s}){return t.jsxs(t.Fragment,{children:[n==="thumbnail"&&r.thumbnailUrl&&t.jsx("img",{src:r.thumbnailUrl,alt:r.thumbnailAlt??r.primaryText,className:"tw:h-14 tw:w-14 tw:shrink-0 tw:rounded tw:object-cover"}),t.jsxs("div",{className:"tw:flex tw:flex-1 tw:items-baseline tw:gap-4 tw:overflow-hidden",children:[t.jsx("span",{className:"tw:shrink-0 tw:truncate tw:text-sm",children:r.primaryText}),i&&r.sourceLanguageText&&t.jsxs("span",{className:"tw:truncate tw:text-sm tw:text-muted-foreground",children:[r.sourceLanguageText,s&&r.transliteration&&t.jsxs("span",{className:"tw:ml-1",children:["(",r.transliteration,")"]})]})]}),t.jsx(a.Separator,{className:"tw:absolute tw:bottom-0 tw:left-0 tw:right-0"})]})}const tt=["%sourceLanguageIndexedList_emptyState%","%sourceLanguageIndexedList_loading%","%sourceLanguageIndexedList_occurrenceCount%","%sourceLanguageIndexedList_strongsCode%","%sourceLanguageIndexedList_filterByDomain%","%sourceLanguageIndexedList_navigationModeTree%","%sourceLanguageIndexedList_navigationModeDropdown%","%sourceLanguageIndexedList_backToList%"];function at({scrRef:r,onClick:n,tooltipContent:i,ariaLabel:s,className:c,testId:d="linked-scr-ref-button"}){if(r==="")return;const g=t.jsx(a.Button,{type:"button",variant:"link",onClick:n,disabled:!n,"aria-label":s,className:a.cn("tw:h-auto tw:p-0 tw:text-start tw:font-mono tw:text-sm",c),"data-testid":d,children:r});return i?t.jsx(a.TooltipProvider,{delayDuration:0,children:t.jsxs(a.Tooltip,{children:[t.jsx(a.TooltipTrigger,{asChild:!0,children:g}),t.jsx(a.TooltipContent,{children:i})]})}):g}const rt=Object.freeze(["%navigationHistory_back_tooltip%","%navigationHistory_forward_tooltip%","%navigationHistory_backList_ariaLabel%","%navigationHistory_forwardList_ariaLabel%"]),P=(r,n)=>r[n]??n;function et({canGoBack:r=!1,canGoForward:n=!1,backItems:i=[],forwardItems:s=[],onNavigate:c,localizedStrings:d={},showKeyboardShortcuts:g=!0,className:b,variant:x="ghost"}){const w=a.isMacOs(),U=a.readDirection(),h=U==="rtl",[k,v]=l.useState(void 0),L=l.useRef(null),D=l.useRef(null),A=P(d,"%navigationHistory_back_tooltip%"),y=P(d,"%navigationHistory_forward_tooltip%"),z=P(d,"%navigationHistory_backList_ariaLabel%"),_=P(d,"%navigationHistory_forwardList_ariaLabel%"),[N,T]=w?["⌘[","⌘]"]:["Alt+←","Alt+→"],j=a.P("left",U)==="back"?N:T,I=j===N?T:N,S=(m,E)=>{const o=m==="back",e=o?r:n,u=o?i:s,F=o?A:y,G=o?z:_,H=o?j:I,O=o?L:D,R=k===m,V=o!==h;return t.jsxs(a.DropdownMenu,{dir:U,open:R,onOpenChange:p=>{p||v(void 0)},children:[t.jsxs(a.Tooltip,{children:[t.jsx(a.TooltipTrigger,{asChild:!0,children:t.jsx(a.DropdownMenuTrigger,{asChild:!0,children:t.jsx("span",{className:"tw:inline-flex",onContextMenu:p=>{p.preventDefault(),u.length>0&&v(m)},children:t.jsx(a.Button,{ref:O,"aria-label":F,"aria-haspopup":"menu","aria-expanded":R,"data-testid":`navigation-history-${m}-button`,className:a.cn(E?"tw:rounded-e-none":"tw:rounded-s-none",b),size:"icon",variant:x,disabled:!e,onClick:()=>c(o?-1:1),onKeyDown:p=>{(p.key==="Enter"||p.key===" "||p.key==="ArrowDown")&&p.stopPropagation()},children:V?t.jsx(B.ArrowLeft,{}):t.jsx(B.ArrowRight,{})})})})}),t.jsx(a.TooltipContent,{children:t.jsxs("p",{children:[F,g&&t.jsxs(t.Fragment,{children:[" ",t.jsx(a.Kbd,{children:H})]})]})})]}),t.jsx(a.DropdownMenuContent,{align:"start","aria-label":G,"aria-labelledby":void 0,onCloseAutoFocus:p=>{var $;p.preventDefault(),($=O.current)==null||$.focus()},children:u.map(p=>t.jsx(a.DropdownMenuItem,{onSelect:()=>c(p.offset),children:p.label},p.offset))})]},m)},C=h?"forward":"back",q=h?"back":"forward";return t.jsx(a.TooltipProvider,{children:t.jsxs(a.ButtonGroup,{"data-testid":"navigation-history-buttons",children:[S(C,!0),S(q,!1)]})})}exports.ALL_BOOK_IDS=a.ALL_BOOK_IDS;exports.ProjectSelector=a.ProjectSelector;exports.Z_INDEX_TOOLTIP=a.Z_INDEX_TOOLTIP;exports.persistDirection=a.persistDirection;exports.readDirection=a.readDirection;exports.LinkedScrRefButton=at;exports.NAVIGATION_HISTORY_BUTTONS_STRING_KEYS=rt;exports.NavigationHistoryButtons=et;exports.RESOURCE_PICKER_DIALOG_STRING_KEYS=X;exports.ResourcePickerDialog=W;exports.SOURCE_LANGUAGE_INDEXED_LIST_STRING_KEYS=tt;exports.SourceLanguageIndexedList=J;function ot(r,n="top"){if(!r||typeof document>"u")return;const i=document.head||document.querySelector("head"),s=i.querySelector(":first-child"),c=document.createElement("style");c.appendChild(document.createTextNode(r)),n==="top"&&s?i.insertBefore(c,s):i.appendChild(c)}ot(`.banded-row:hover { - cursor: pointer; -} - -.banded-row[data-state='selected']:hover { - cursor: default; -} -/* By default the editor is too tall for the footnote editor, even while empty, so this makes it +"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./resizable-DeY5Gh-0.cjs"),t=require("react/jsx-runtime"),K=require("platform-bible-utils"),B=require("lucide-react"),l=require("react");function Y(r,n=50){const[i,s]=l.useState(n),c=l.useRef(null);return l.useEffect(()=>{s(n)},[r,n]),l.useEffect(()=>{if(i>=r.length)return;const d=c.current,g=new IntersectionObserver(([b])=>{b.isIntersecting&&s(x=>Math.min(x+n,r.length))},{threshold:0});return d&&g.observe(d),()=>g.disconnect()},[i,r.length,n]),{visibleItems:r.slice(0,i),sentinelRef:c,hasMore:ir[n]??n;function M({label:r,resources:n,onSelect:i,showCheckmark:s}){if(n.length!==0)return t.jsxs(t.Fragment,{children:[t.jsx(a.TableRow,{className:"tw:border-0 tw:hover:bg-transparent",children:t.jsx(a.TableCell,{colSpan:4,className:"tw:border-0 tw:pt-4 tw:pb-0",children:t.jsx(a.Label,{className:"tw:text-xs tw:tracking-wider tw:text-muted-foreground tw:uppercase",children:r})})}),n.map(c=>t.jsxs(a.TableRow,{className:i?"tw:cursor-pointer tw:border-0":"tw:pointer-events-none tw:border-0",role:i?"button":void 0,"aria-label":i?c.displayName:void 0,onClick:i?()=>i(c):void 0,onKeyDown:i?d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),i(c))}:void 0,children:[t.jsx(a.TableCell,{className:"tw:w-5 tw:border-0 tw:py-1 tw:pr-1",children:s&&t.jsxs(t.Fragment,{children:[t.jsx(B.Check,{className:"tw:h-3.5 tw:w-3.5","aria-hidden":!0}),t.jsx("span",{className:"tw:sr-only",children:r})]})}),t.jsx(a.TableCell,{className:"tw:border-0 tw:py-1 tw:pr-2 tw:font-normal tw:whitespace-nowrap",children:c.displayName}),t.jsx(a.TableCell,{className:"tw:border-0 tw:py-1 tw:pl-2",children:c.fullName}),t.jsx(a.TableCell,{className:"tw:border-0 tw:py-1 tw:pl-4 tw:text-right tw:text-muted-foreground",children:c.bestLanguageName})]},c.dblEntryUid))]})}function Z(r,n){if(!n)return!0;const i=n.toLowerCase();return r.displayName.toLowerCase().includes(i)||r.fullName.toLowerCase().includes(i)||r.bestLanguageName.toLowerCase().includes(i)}function W({allResources:r,isResourcesLoading:n,resourceType:i,selectedResourceIds:s,localizedStrings:c,allowDeselect:d,onSelect:g}){const[b,x]=l.useState(""),[w,U]=l.useState([]),h=l.useMemo(()=>r.filter(e=>!i||e.type===i).filter(e=>Z(e,b)).filter(e=>w.length===0||w.includes(e.bestLanguageName)),[r,i,b,w]),k=l.useMemo(()=>h.filter(e=>s==null?void 0:s.includes(e.dblEntryUid)),[h,s]),v=l.useMemo(()=>h.filter(e=>e.installed&&!(s!=null&&s.includes(e.dblEntryUid))),[h,s]),L=l.useMemo(()=>h.filter(e=>!e.installed&&!(s!=null&&s.includes(e.dblEntryUid))),[h,s]),{visibleItems:D,sentinelRef:A,hasMore:y}=Y(L),z=l.useMemo(()=>Array.from(new Set(r.map(e=>e.bestLanguageName))).map(e=>({label:e,value:e})),[r]),_=k.length===0&&v.length===0&&L.length===0,N=f(c,"%resourcePicker_title%"),T=f(c,"%resourcePicker_search_placeholder%"),j=f(c,"%resourcePicker_language_filter_any%"),I=f(c,"%resourcePicker_section_already_selected%"),S=f(c,"%resourcePicker_section_installed%"),C=f(c,"%resourcePicker_section_available_to_download%"),q=f(c,"%resourcePicker_no_results%"),m=f(c,"%resourcePicker_showing_count%"),E=l.useMemo(()=>{if(w.length===z.length||w.length===0)return j;if(w.length===1){const e=z.find(u=>u.value===w[0]);if(e)return e.label}return K.formatReplacementString(f(c,"%resourcePicker_language_filter_multipleSelected%"),{selectCount:w.length})},[w,z,j,c]),o=b.length>0||w.length>0;return t.jsxs(t.Fragment,{children:[t.jsx(a.DialogHeader,{className:"tw:px-4 tw:pt-4",children:t.jsx(a.DialogTitle,{children:N})}),t.jsxs("div",{className:"tw:flex tw:gap-2 tw:p-4",children:[t.jsx(a.SearchBar,{value:b,onSearch:x,placeholder:T,isFullWidth:!0}),t.jsx(a.MultiSelectComboBox,{entries:z,selected:w,onChange:U,customSelectedText:E,placeholder:j,variant:"outline"})]}),o&&t.jsx("p",{className:"tw:px-4 tw:pb-1 tw:text-right tw:text-xs tw:text-muted-foreground",children:K.formatReplacementString(m,{filtered:h.length,total:r.length})}),t.jsxs("div",{className:"tw:min-h-0 tw:flex-1 tw:overflow-y-auto tw:px-4 tw:pb-4",children:[n&&t.jsx("p",{className:"tw:py-8 tw:text-center",children:t.jsx(a.Spinner,{})}),_&&!n&&t.jsx("p",{className:"tw:py-8 tw:text-center tw:text-muted-foreground",children:q}),!_&&!n&&t.jsx(a.Table,{children:t.jsxs(a.TableBody,{children:[t.jsx(M,{label:I,resources:k,onSelect:d?g:void 0,showCheckmark:!0}),t.jsx(M,{label:S,resources:v,onSelect:g}),t.jsx(M,{label:C,resources:D,onSelect:g}),y&&t.jsx(a.TableRow,{className:"tw:border-0",children:t.jsx(a.TableCell,{colSpan:4,className:"tw:border-0 tw:p-0",children:t.jsx("div",{ref:A,"aria-hidden":!0})})})]})})]})]})}function J({items:r,renderItem:n,renderDetailContent:i,onItemClick:s,selectedItemId:c,emptyStateMessage:d="No items found",detailRegionLabel:g="Selected item details",isLoading:b=!1,variant:x="text",showSourceLanguage:w=!1,showTransliteration:U=!1,onCharacterPress:h,className:k}){const[v,L]=l.useState(),D=l.useRef(null),A=c??v,y=l.useMemo(()=>v?r.find(o=>o.id===v):void 0,[v,r]),z=l.useMemo(()=>r.map(o=>({id:o.id})),[r]),_=o=>{s==null||s(o),i&&L(o.id===v?void 0:o.id)},N=o=>{const e=r.find(u=>u.id===o.id);e&&_(e)},{listboxRef:T,activeId:j,handleKeyDown:I,focusOption:S}=a.useListbox({options:z,onOptionSelect:N,onCharacterPress:h}),C=()=>{const o=v;L(void 0),o&&requestAnimationFrame(()=>{var e;S(o),(e=T.current)==null||e.focus()})},q=l.useRef(null);if(l.useEffect(()=>{if(!y)return;const o=q.current;if(!o)return;const e=u=>{u.key==="Escape"&&(u.preventDefault(),C())};return o.addEventListener("keydown",e),()=>o.removeEventListener("keydown",e)},[y]),b)return t.jsx("div",{className:a.cn("tw:flex tw:flex-col tw:gap-2 tw:p-2",k),children:Array.from({length:6},(o,e)=>t.jsx(a.Skeleton,{className:a.cn("tw:h-12 tw:w-full tw:rounded",{"tw:h-20":x==="thumbnail"})},e))});if(r.length===0)return t.jsx("div",{className:a.cn("tw:flex tw:items-center tw:justify-center tw:p-8 tw:text-sm tw:text-muted-foreground",k),children:d});const m=t.jsx("ul",{role:"listbox",tabIndex:0,ref:T,"aria-activedescendant":j??void 0,className:"tw:outline-none tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-1 tw:focus:ring-offset-background",onKeyDown:I,children:r.map(o=>{const e=A===o.id;return t.jsx("li",{id:o.id,role:"option","aria-selected":e,tabIndex:-1,onClick:()=>_(o),onKeyDown:u=>{(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),_(o))},className:a.cn("tw:flex tw:cursor-pointer tw:items-center tw:gap-3 tw:p-2 tw:outline-none",{"tw:bg-muted":e,"tw:hover:bg-muted":!e}),children:n?n(o):t.jsx(Q,{item:o,variant:x,showSourceLanguage:w,showTransliteration:U})},o.id)})}),E=i&&y?i(y,C):void 0;return t.jsx("div",{ref:D,className:a.cn("tw:relative tw:flex tw:h-full tw:overflow-hidden",k),children:E?t.jsxs(a.ResizablePanelGroup,{direction:"horizontal",className:"tw:h-full tw:w-full",children:[t.jsx(a.ResizablePanel,{defaultSize:33.3333,minSize:20,children:t.jsx("div",{className:"tw:h-full tw:overflow-y-auto",children:m})}),t.jsx(a.ResizableHandle,{}),t.jsx(a.ResizablePanel,{defaultSize:66.6667,minSize:30,children:t.jsx("div",{ref:q,role:"region","aria-label":g,className:"tw:h-full tw:overflow-y-auto tw:bg-background tw:p-4",children:E})})]}):t.jsx("div",{className:"tw:h-full tw:w-full tw:overflow-y-auto",children:m})})}function Q({item:r,variant:n,showSourceLanguage:i,showTransliteration:s}){return t.jsxs(t.Fragment,{children:[n==="thumbnail"&&r.thumbnailUrl&&t.jsx("img",{src:r.thumbnailUrl,alt:r.thumbnailAlt??r.primaryText,className:"tw:h-14 tw:w-14 tw:shrink-0 tw:rounded tw:object-cover"}),t.jsxs("div",{className:"tw:flex tw:flex-1 tw:items-baseline tw:gap-4 tw:overflow-hidden",children:[t.jsx("span",{className:"tw:shrink-0 tw:truncate tw:text-sm",children:r.primaryText}),i&&r.sourceLanguageText&&t.jsxs("span",{className:"tw:truncate tw:text-sm tw:text-muted-foreground",children:[r.sourceLanguageText,s&&r.transliteration&&t.jsxs("span",{className:"tw:ml-1",children:["(",r.transliteration,")"]})]})]}),t.jsx(a.Separator,{className:"tw:absolute tw:bottom-0 tw:left-0 tw:right-0"})]})}const tt=["%sourceLanguageIndexedList_emptyState%","%sourceLanguageIndexedList_loading%","%sourceLanguageIndexedList_occurrenceCount%","%sourceLanguageIndexedList_strongsCode%","%sourceLanguageIndexedList_filterByDomain%","%sourceLanguageIndexedList_navigationModeTree%","%sourceLanguageIndexedList_navigationModeDropdown%","%sourceLanguageIndexedList_backToList%"];function at({scrRef:r,onClick:n,tooltipContent:i,ariaLabel:s,className:c,testId:d="linked-scr-ref-button"}){if(r==="")return;const g=t.jsx(a.Button,{type:"button",variant:"link",onClick:n,disabled:!n,"aria-label":s,className:a.cn("tw:h-auto tw:p-0 tw:text-start tw:font-mono tw:text-sm",c),"data-testid":d,children:r});return i?t.jsx(a.TooltipProvider,{delayDuration:0,children:t.jsxs(a.Tooltip,{children:[t.jsx(a.TooltipTrigger,{asChild:!0,children:g}),t.jsx(a.TooltipContent,{children:i})]})}):g}const rt=Object.freeze(["%navigationHistory_back_tooltip%","%navigationHistory_forward_tooltip%","%navigationHistory_backList_ariaLabel%","%navigationHistory_forwardList_ariaLabel%"]),P=(r,n)=>r[n]??n;function et({canGoBack:r=!1,canGoForward:n=!1,backItems:i=[],forwardItems:s=[],onNavigate:c,localizedStrings:d={},showKeyboardShortcuts:g=!0,className:b,variant:x="ghost"}){const w=a.isMacOs(),U=a.readDirection(),h=U==="rtl",[k,v]=l.useState(void 0),L=l.useRef(null),D=l.useRef(null),A=P(d,"%navigationHistory_back_tooltip%"),y=P(d,"%navigationHistory_forward_tooltip%"),z=P(d,"%navigationHistory_backList_ariaLabel%"),_=P(d,"%navigationHistory_forwardList_ariaLabel%"),[N,T]=w?["⌘[","⌘]"]:["Alt+←","Alt+→"],j=a.P("left",U)==="back"?N:T,I=j===N?T:N,S=(m,E)=>{const o=m==="back",e=o?r:n,u=o?i:s,F=o?A:y,G=o?z:_,H=o?j:I,O=o?L:D,R=k===m,V=o!==h;return t.jsxs(a.DropdownMenu,{dir:U,open:R,onOpenChange:p=>{p||v(void 0)},children:[t.jsxs(a.Tooltip,{children:[t.jsx(a.TooltipTrigger,{asChild:!0,children:t.jsx(a.DropdownMenuTrigger,{asChild:!0,children:t.jsx("span",{className:"tw:inline-flex",onContextMenu:p=>{p.preventDefault(),u.length>0&&v(m)},children:t.jsx(a.Button,{ref:O,"aria-label":F,"aria-haspopup":"menu","aria-expanded":R,"data-testid":`navigation-history-${m}-button`,className:a.cn(E?"tw:rounded-e-none":"tw:rounded-s-none",b),size:"icon",variant:x,disabled:!e,onClick:()=>c(o?-1:1),onKeyDown:p=>{(p.key==="Enter"||p.key===" "||p.key==="ArrowDown")&&p.stopPropagation()},children:V?t.jsx(B.ArrowLeft,{}):t.jsx(B.ArrowRight,{})})})})}),t.jsx(a.TooltipContent,{children:t.jsxs("p",{children:[F,g&&t.jsxs(t.Fragment,{children:[" ",t.jsx(a.Kbd,{children:H})]})]})})]}),t.jsx(a.DropdownMenuContent,{align:"start","aria-label":G,"aria-labelledby":void 0,onCloseAutoFocus:p=>{var $;p.preventDefault(),($=O.current)==null||$.focus()},children:u.map(p=>t.jsx(a.DropdownMenuItem,{onSelect:()=>c(p.offset),children:p.label},p.offset))})]},m)},C=h?"forward":"back",q=h?"back":"forward";return t.jsx(a.TooltipProvider,{children:t.jsxs(a.ButtonGroup,{"data-testid":"navigation-history-buttons",children:[S(C,!0),S(q,!1)]})})}exports.ALL_BOOK_IDS=a.ALL_BOOK_IDS;exports.ProjectSelector=a.ProjectSelector;exports.Z_INDEX_TOOLTIP=a.Z_INDEX_TOOLTIP;exports.persistDirection=a.persistDirection;exports.readDirection=a.readDirection;exports.LinkedScrRefButton=at;exports.NAVIGATION_HISTORY_BUTTONS_STRING_KEYS=rt;exports.NavigationHistoryButtons=et;exports.RESOURCE_PICKER_DIALOG_STRING_KEYS=X;exports.ResourcePickerDialog=W;exports.SOURCE_LANGUAGE_INDEXED_LIST_STRING_KEYS=tt;exports.SourceLanguageIndexedList=J;function ot(r,n="top"){if(!r||typeof document>"u")return;const i=document.head||document.querySelector("head"),s=i.querySelector(":first-child"),c=document.createElement("style");c.appendChild(document.createTextNode(r)),n==="top"&&s?i.insertBefore(c,s):i.appendChild(c)}ot(`/* By default the editor is too tall for the footnote editor, even while empty, so this makes it shorter. */ .footnote-editor .editor-input { min-height: 75px; @@ -24,6 +17,13 @@ .footnote-editor .text-spacing .usfm_p { text-indent: 0; } +.banded-row:hover { + cursor: pointer; +} + +.banded-row[data-state='selected']:hover { + cursor: default; +} /** * This file was automatically generated on installation of the Shadcn/Lexical editor. The default * location of this file has been changed to integrate better with our project structure. diff --git a/lib/platform-bible-react/dist/experimental.js b/lib/platform-bible-react/dist/experimental.js index 1169c9ebbca..f88c7880d7b 100644 --- a/lib/platform-bible-react/dist/experimental.js +++ b/lib/platform-bible-react/dist/experimental.js @@ -1,5 +1,5 @@ -import { s as nt, t as ct, aa as st, a1 as lt, aA as dt, V as wt, Y as pt, R as H, U as P, L as gt, M as ht, K as vt, c as E, az as ut, ay as J, ax as bt, S as mt, B as Z, T as Q, v as tt, w as at, x as rt, r as ft, u as xt, H as kt, I as yt, a2 as zt, J as _t, F as Ut, aK as Lt, z as Nt } from "./resizable-zJhzqhIl.js"; -import { m as Xt, a8 as Jt, aL as Wt, aM as Zt } from "./resizable-zJhzqhIl.js"; +import { s as nt, t as ct, aa as st, a1 as lt, aA as dt, V as wt, Y as pt, R as H, U as P, L as gt, M as ht, K as vt, c as E, az as ut, ay as J, ax as bt, S as mt, B as Z, T as Q, v as tt, w as at, x as rt, r as ft, u as xt, H as kt, I as yt, a2 as zt, J as _t, F as Ut, aK as Lt, z as Nt } from "./resizable-DQRM0ASL.js"; +import { m as Xt, a8 as Jt, aL as Wt, aM as Zt } from "./resizable-DQRM0ASL.js"; import { jsxs as s, Fragment as I, jsx as t } from "react/jsx-runtime"; import { formatReplacementString as W } from "platform-bible-utils"; import { Check as qt, ArrowLeft as Ct, ArrowRight as Et } from "lucide-react"; @@ -487,14 +487,7 @@ function At(a, i = "top") { const o = document.head || document.querySelector("head"), c = o.querySelector(":first-child"), n = document.createElement("style"); n.appendChild(document.createTextNode(a)), i === "top" && c ? o.insertBefore(n, c) : o.appendChild(n); } -At(`.banded-row:hover { - cursor: pointer; -} - -.banded-row[data-state='selected']:hover { - cursor: default; -} -/* By default the editor is too tall for the footnote editor, even while empty, so this makes it +At(`/* By default the editor is too tall for the footnote editor, even while empty, so this makes it shorter. */ .footnote-editor .editor-input { min-height: 75px; @@ -513,6 +506,13 @@ At(`.banded-row:hover { .footnote-editor .text-spacing .usfm_p { text-indent: 0; } +.banded-row:hover { + cursor: pointer; +} + +.banded-row[data-state='selected']:hover { + cursor: default; +} /** * This file was automatically generated on installation of the Shadcn/Lexical editor. The default * location of this file has been changed to integrate better with our project structure. diff --git a/lib/platform-bible-react/dist/index.cjs b/lib/platform-bible-react/dist/index.cjs index cd8c88ec3b2..c452ce63239 100644 --- a/lib/platform-bible-react/dist/index.cjs +++ b/lib/platform-bible-react/dist/index.cjs @@ -1,12 +1,5 @@ -"use strict";var qo=Object.defineProperty;var Ho=(t,r,a)=>r in t?qo(t,r,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[r]=a;var Ot=(t,r,a)=>Ho(t,typeof r!="symbol"?r+"":r,a);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./resizable-DLBXOT7I.cjs"),e=require("react/jsx-runtime"),ht=require("@sillsdev/scripture"),R=require("lucide-react"),M=require("platform-bible-utils"),l=require("react"),D=require("radix-ui"),v=require("lexical"),fr=require("@lexical/rich-text"),Ur=require("react-dom"),Yo=require("@lexical/table"),er=require("class-variance-authority"),ha=require("@lexical/headless"),fa=require("@lexical/html"),It=require("@tanstack/react-table"),Tt=require("@tabler/icons-react"),Xo=require("markdown-to-jsx"),Gt=require("@eten-tech-foundation/platform-editor"),Zo=require("react-hotkeys-hook"),se=require("vaul"),Wo=require("next-themes"),ma=require("sonner");function Jo({className:t,...r}){return e.jsx("textarea",{"data-slot":"textarea",className:n.cn("pr-twp tw:flex tw:field-sizing-content tw:min-h-16 tw:w-full tw:rounded-lg tw:border tw:border-input tw:bg-transparent tw:px-2.5 tw:py-2 tw:text-base tw:transition-colors tw:outline-none tw:placeholder:text-muted-foreground tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:bg-input/50 tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:md:text-sm tw:dark:bg-input/30 tw:dark:disabled:bg-input/80 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40",t),...r})}function va({ref:t,bookId:r,isSelected:a,onSelect:o,onMouseDown:i,section:s,className:c,showCheck:d=!1,localizedBookNames:u,commandValue:w,disabled:p=!1}){const g=l.useRef(!1),f=()=>{p||(g.current||o==null||o(r),setTimeout(()=>{g.current=!1},100))},h=b=>{if(p){b.preventDefault();return}g.current=!0,i?i(b):o==null||o(r)},m=l.useMemo(()=>n.getLocalizedBookName(r,u),[r,u]),k=l.useMemo(()=>n.getLocalizedBookId(r,u),[r,u]);return e.jsx("div",{className:n.cn("tw:mx-1 tw:my-1 tw:border-b-0 tw:border-e-0 tw:border-s-2 tw:border-t-0 tw:border-solid",{"tw:border-s-red-200":s===M.Section.OT,"tw:border-s-purple-200":s===M.Section.NT,"tw:border-s-indigo-200":s===M.Section.DC,"tw:border-s-amber-200":s===M.Section.Extra}),children:e.jsxs(n.CommandItem,{ref:t,value:w||`${r} ${ht.Canon.bookIdToEnglishName(r)}`,onSelect:f,onMouseDown:h,role:"option","aria-selected":a,"aria-disabled":p||void 0,"aria-label":`${ht.Canon.bookIdToEnglishName(r)} (${r.toLocaleUpperCase()})`,disabled:p,className:n.cn(c,p&&"tw:cursor-not-allowed tw:opacity-50"),children:[d&&e.jsx(R.Check,{className:n.cn("tw:me-2 tw:h-4 tw:w-4 tw:shrink-0",a?"tw:opacity-100":"tw:opacity-0")}),e.jsx("span",{className:"tw:min-w-0 tw:flex-1",children:m}),e.jsx("span",{className:"tw:ms-2 tw:shrink-0 tw:text-xs tw:text-muted-foreground",children:k})]})})}function ba(t,r,a){return`${t} ${n.ALL_ENGLISH_BOOK_NAMES[t]}${r?` ${n.getLocalizedBookId(t,r)} ${n.getLocalizedBookName(t,r)}`:""}`}function xa({recentSearches:t,onSearchItemSelect:r,renderItem:a=p=>String(p),getItemKey:o=p=>String(p),ariaLabel:i="Show recent searches",groupHeading:s="Recent",id:c,classNameForItems:d,buttonClassName:u="tw:absolute tw:right-0 tw:top-0 tw:h-full tw:px-3 tw:py-2",buttonVariant:w="ghost"}){const[p,g]=l.useState(!1);if(t.length===0)return;const f=h=>{r(h),g(!1)};return e.jsxs(n.Popover,{open:p,onOpenChange:g,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:w,size:"icon",className:u,"aria-label":i,children:e.jsx(R.Clock,{className:"tw:h-4 tw:w-4"})})}),e.jsx(n.PopoverContent,{id:c,className:"tw:w-[300px] tw:p-0",align:"start",children:e.jsx(n.Command,{children:e.jsx(n.CommandList,{children:e.jsx(n.CommandGroup,{heading:s,children:t.map(h=>e.jsxs(n.CommandItem,{onSelect:()=>f(h),className:n.cn("tw:flex tw:items-center",d),children:[e.jsx(R.Clock,{className:"tw:mr-2 tw:h-4 tw:w-4 tw:opacity-50"}),e.jsx("span",{children:a(h)})]},o(h)))})})})})]})}function Qo(t,r,a=(i,s)=>i===s,o=15){return i=>{const s=t.filter(d=>!a(d,i)),c=[i,...s.slice(0,o-1)];r(c)}}function Be(t,r){return!r||r.book===t.book&&r.chapterNum===t.chapterNum&&r.verseNum===t.verseNum}function tn(t,r,a,o){const i=l.useMemo(()=>n.d(t,r),[t,r]),s=l.useMemo(()=>n.k(t,r),[t,r]),c=l.useMemo(()=>n.C(t,r),[t,r]),d=l.useMemo(()=>n.E(t,r),[t,r]),u=l.useCallback(w=>{w&&o(w)},[o]);return l.useMemo(()=>[{onClick:()=>u(i),disabled:Be(t,i),title:"Previous chapter",icon:a==="ltr"?R.ChevronsLeft:R.ChevronsRight},{onClick:()=>u(c),disabled:Be(t,c),title:"Previous verse",icon:a==="ltr"?R.ChevronLeft:R.ChevronRight},{onClick:()=>u(d),disabled:Be(t,d),title:"Next verse",icon:a==="ltr"?R.ChevronRight:R.ChevronLeft},{onClick:()=>u(s),disabled:Be(t,s),title:"Next chapter",icon:a==="ltr"?R.ChevronsRight:R.ChevronsLeft}],[t,a,u,i,c,d,s])}const Fe={BOOK_ONLY:/^([^:\s]+(?:\s+[^:\s]+)*)$/i,BOOK_CHAPTER:/^([^:\s]+(?:\s+[^:\s]+)*)\s+(\d+)$/i,BOOK_CHAPTER_VERSE:/^([^:\s]+(?:\s+[^:\s]+)*)\s+(\d+):(\d*)$/i},en=[Fe.BOOK_ONLY,Fe.BOOK_CHAPTER,Fe.BOOK_CHAPTER_VERSE];function rn(t){return Fe.BOOK_CHAPTER_VERSE.test(t.trim())}function qr(t,r){return ht.Canon.bookIdToNumber(t)0?!1:r0?!1:ro.chapterNum?!1:a{if(i)return i;const c=s.exec(t.trim());if(c){const[d,u=void 0,w=void 0]=c.slice(1);let p;const g=r.filter(f=>n.doesBookMatchQuery(f,d,a));if(g.length===1&&([p]=g),!p&&u){if(ht.Canon.isBookIdValid(d)){const f=d.toUpperCase();r.includes(f)&&(p=f)}if(!p&&a){const f=Array.from(a.entries()).find(([,h])=>h.localizedId.toLowerCase()===d.toLowerCase());f&&r.includes(f[0])&&([p]=f)}}if(!p&&u){const h=(m=>Object.keys(n.ALL_ENGLISH_BOOK_NAMES).find(k=>n.ALL_ENGLISH_BOOK_NAMES[k].toLowerCase()===m.toLowerCase()))(d);if(h&&r.includes(h)&&(p=h),!p&&a){const m=Array.from(a.entries()).find(([,k])=>k.localizedName.toLowerCase()===d.toLowerCase());m&&r.includes(m[0])&&([p]=m)}}if(p){let f=u?parseInt(u,10):void 0;f&&f>be(p)&&(f=Math.max(be(p),1));const h=w?parseInt(w,10):void 0;return{book:p,chapterNum:f,verseNum:h}}}},void 0);if(o)return o}function ka({count:t,valueBuilder:r,onSelect:a,itemRef:o,isDisabled:i,isDimmed:s,isSelected:c,className:d}){if(!(t<=0))return e.jsx(n.CommandGroup,{children:e.jsx("div",{className:n.cn("tw:grid tw:grid-cols-6 tw:gap-1",d),children:Array.from({length:t},(u,w)=>w+1).map(u=>{const w=(i==null?void 0:i(u))??!1;return e.jsx(n.CommandItem,{value:r(u),onSelect:()=>{w||a(u)},ref:o(u),disabled:w,"aria-disabled":w||void 0,className:n.cn("tw:h-8 tw:w-8 tw:cursor-pointer tw:justify-center tw:rounded-md tw:text-center tw:text-sm",{"tw:bg-primary tw:text-primary-foreground":(c==null?void 0:c(u))??!1},{"tw:bg-muted/50 tw:text-muted-foreground/50":((s==null?void 0:s(u))??!1)&&!w},w&&"tw:cursor-not-allowed tw:opacity-40"),children:u},u)})})})}function Yr({bookId:t,scrRef:r,onChapterSelect:a,setChapterRef:o,isChapterDimmed:i,isChapterDisabled:s,className:c}){if(t)return e.jsx(ka,{count:be(t),valueBuilder:d=>`${t} ${n.ALL_ENGLISH_BOOK_NAMES[t]||""} ${d}`,onSelect:a,itemRef:o,isDisabled:s,isDimmed:i,isSelected:d=>t===r.book&&d===r.chapterNum,className:c})}function Xr({bookId:t,chapterNum:r,endVerse:a,scrRef:o,onVerseSelect:i,setVerseRef:s,isVerseDimmed:c,isVerseDisabled:d,className:u}){if(!(!t||a<=0))return e.jsx(ka,{count:a,valueBuilder:w=>`${t} ${n.ALL_ENGLISH_BOOK_NAMES[t]||""} ${r}:${w}`,onSelect:i,itemRef:s,isDisabled:d,isDimmed:c,isSelected:w=>t===o.book&&r===o.chapterNum&&w===o.verseNum,className:u})}function Ge({scrRef:t,handleSubmit:r,className:a,getActiveBookIds:o,localizedBookNames:i,localizedStrings:s,recentSearches:c,onAddRecentSearch:d,id:u,getEndVerse:w,disableReferencesUpTo:p,submitKeys:g,triggerContent:f,triggerVariant:h="outline",onOpenChange:m,onCloseAutoFocus:k,modal:b=!1,align:C="center",ref:y,disabled:_}){const B=n.readDirection(),[F,E]=l.useState(!1),[P,A]=l.useState(""),[j,V]=l.useState(""),[z,N]=l.useState("books"),[H,U]=l.useState(void 0),[G,I]=l.useState(void 0),[T,Z]=l.useState(void 0),[W,vt]=l.useState(!1),bt=l.useRef(null),Mt=l.useRef(!1),K=l.useRef(void 0),J=l.useRef(void 0),st=l.useRef(void 0),ot=l.useRef(void 0),gt=l.useRef({}),qt=l.useRef({}),et=l.useCallback(x=>{r(x),d&&d(x)},[r,d]),Rt=l.useMemo(()=>o?o():n.ALL_BOOK_IDS,[o]),yt=l.useMemo(()=>({[M.Section.OT]:Rt.filter(q=>ht.Canon.isBookOT(q)),[M.Section.NT]:Rt.filter(q=>ht.Canon.isBookNT(q)),[M.Section.DC]:Rt.filter(q=>ht.Canon.isBookDC(q)),[M.Section.Extra]:Rt.filter(q=>ht.Canon.extraBooks().includes(q))}),[Rt]),Bt=l.useMemo(()=>Object.values(yt).flat(),[yt]),Ht=l.useMemo(()=>{if(!j.trim())return yt;const x={[M.Section.OT]:[],[M.Section.NT]:[],[M.Section.DC]:[],[M.Section.Extra]:[]};return[M.Section.OT,M.Section.NT,M.Section.DC,M.Section.Extra].forEach(tt=>{x[tt]=yt[tt].filter(Dt=>n.doesBookMatchQuery(Dt,j,i))}),x},[yt,j,i]),O=l.useMemo(()=>on(j,Bt,i),[j,Bt,i]),Pt=l.useRef(!1);l.useEffect(()=>{if(!Pt.current){Pt.current=!0;return}m==null||m(F)},[F,m]);const ft=l.useCallback(()=>{if(O){const x=O.chapterNum??1,q=O.verseNum??1;if(p&&or(O.book,x,q,p))return;et({book:O.book,chapterNum:x,verseNum:q}),E(!1),V(""),A("")}},[et,O,p]),xt=l.useCallback(x=>{const q=G??(O==null?void 0:O.book),tt=T??(O==null?void 0:O.chapterNum);!q||!tt||(et({book:q,chapterNum:tt,verseNum:x}),E(!1))},[et,G,T,O]),Vt=l.useCallback(x=>{if(p&&qr(x,p))return;if(be(x)<=1){et({book:x,chapterNum:1,verseNum:1}),E(!1),V("");return}U(x),N("chapters")},[et,p]),te=l.useCallback(x=>{const q=z==="chapters"?H:O==null?void 0:O.book;if(q){if(w&&w(q,x)>1){I(q),Z(x),N("verses"),A("");return}et({book:q,chapterNum:x,verseNum:1}),E(!1)}},[et,z,H,O,w]),Yt=l.useCallback(x=>{et(x),E(!1),V("")},[et]),L=tn(t,Bt,B,r),Y=l.useCallback(()=>{N("books"),U(void 0),I(void 0),Z(void 0),setTimeout(()=>{J.current&&J.current.focus()},0)},[]),rt=l.useCallback(()=>{const x=G;I(void 0),Z(void 0),x?(U(x),N("chapters"),A("")):Y()},[G,Y]),Q=l.useCallback(x=>{E(x),x&&(N("books"),U(void 0),I(void 0),Z(void 0),V(""))},[]);l.useEffect(()=>{_&&Q(!1)},[_,Q]);const[ct,nt]=l.useState(0);l.useEffect(()=>{var x;ct!==0&&((x=J.current)==null||x.focus())},[ct]),l.useImperativeHandle(y,()=>({open:()=>{_||(Q(!0),nt(x=>x+1))}}),[Q,_]);const{otLong:wt,ntLong:lt,dcLong:ut,extraLong:_t}={otLong:s==null?void 0:s["%scripture_section_ot_long%"],ntLong:s==null?void 0:s["%scripture_section_nt_long%"],dcLong:s==null?void 0:s["%scripture_section_dc_long%"],extraLong:s==null?void 0:s["%scripture_section_extra_long%"]},jt=l.useCallback(x=>n.getSectionLongName(x,wt,lt,ut,_t),[wt,lt,ut,_t]),At=l.useCallback(x=>O?!!O.chapterNum&&!x.toString().includes(O.chapterNum.toString()):!1,[O]),Ct=l.useMemo(()=>M.formatScrRef(t,i?n.getLocalizedBookName(t.book,i):"English"),[t,i]),ae=l.useCallback(x=>q=>{gt.current[x]=q},[]),S=l.useCallback(x=>q=>{qt.current[x]=q},[]),Nt=l.useMemo(()=>rn(j),[j]),mt=l.useMemo(()=>!w||!O||!O.chapterNum||!Nt?!1:w(O.book,O.chapterNum)>0,[w,O,Nt]),Xt=l.useCallback(x=>p?qr(x,p):!1,[p]),oe=l.useCallback(x=>q=>p?an(x,q,p):!1,[p]),_e=l.useCallback((x,q)=>tt=>p?or(x,q,tt,p):!1,[p]),je=(s==null?void 0:s["%webView_bookChapterControl_selectChapter%"])??"Select Chapter",Ce=(s==null?void 0:s["%webView_bookChapterControl_selectVerse%"])??"Select Verse",Ie=l.useCallback(x=>{(x.key==="Home"||x.key==="End")&&x.stopPropagation(),g&&g.includes(x.key)&&O&&O.chapterNum!==void 0&&O.verseNum!==void 0&&(x.preventDefault(),x.stopPropagation(),ft())},[g,O,ft]),Ae=l.useCallback(x=>{var ee,ce,ne;if(x.ctrlKey)return;const{isLetter:q,isDigit:tt}=Hr(x.key);if((z==="chapters"||z==="verses")&&(x.key===" "||x.key==="Enter")){const Et=x.target instanceof HTMLElement?x.target:void 0;if(!!(Et!=null&&Et.closest('button, a, input, select, textarea, [role="button"]'))){x.stopPropagation();return}const St=(ee=K.current)==null?void 0:ee.querySelector('[cmdk-item][data-selected="true"]:not([data-disabled="true"])');if(St){x.preventDefault(),x.stopPropagation(),St.click();return}}if((z==="chapters"||z==="verses")&&(q||tt)){x.preventDefault(),x.stopPropagation();return}if(z==="chapters"&&x.key==="Backspace"){x.preventDefault(),x.stopPropagation(),Y();return}if(z==="verses"&&x.key==="Backspace"){x.preventDefault(),x.stopPropagation(),rt();return}const Dt=["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(x.key);if(z==="verses"&&Dt){const Et=G,pt=T;if(!Et||!pt||!w)return;const St=w(Et,pt);if(!St)return;(ce=K.current)==null||ce.focus();const dt=(()=>{if(!P)return 1;const le=P.match(/:(\d+)$/);return le?parseInt(le[1],10):0})();let Ft=dt;const Lt=6;switch(x.key){case"ArrowLeft":dt!==0&&(Ft=dt>1?dt-1:St);break;case"ArrowRight":dt!==0&&(Ft=dt{const le=qt.current[Ft];le&&le.scrollIntoView({block:"nearest",behavior:"smooth"})},0));return}if((z==="chapters"||z==="books"&&O)&&Dt){const Et=z==="chapters"?H:O==null?void 0:O.book;if(!Et)return;z==="chapters"&&((ne=K.current)==null||ne.focus());const pt=(()=>{if(!P)return 1;const Lt=P.match(/(\d+)$/);return Lt?parseInt(Lt[1],10):0})(),St=be(Et);if(!St)return;let dt=pt;const Ft=6;switch(x.key){case"ArrowLeft":pt!==0&&(dt=pt>1?pt-1:St);break;case"ArrowRight":pt!==0&&(dt=pt{const Lt=gt.current[dt];Lt&&Lt.scrollIntoView({block:"nearest",behavior:"smooth"})},0))}},[z,O,Y,rt,H,G,T,w,P]),fe=l.useCallback(x=>{var Dt;if(x.shiftKey||x.key==="Tab"||x.key===" ")return;if(x.key==="Enter"){x.stopPropagation();return}if(x.key==="ArrowUp"||x.key==="ArrowDown"){(Dt=J.current)==null||Dt.focus();return}const{isLetter:q,isDigit:tt}=Hr(x.key);(q||tt)&&(x.preventDefault(),V(ee=>ee+x.key),J.current.focus(),vt(!1))},[]);return l.useLayoutEffect(()=>{const x=setTimeout(()=>{if(F&&z==="books"&&st.current&&ot.current){const q=st.current,tt=ot.current,Dt=tt.offsetTop,ee=q.clientHeight,ce=tt.clientHeight,ne=Dt-ee/2+ce/2;q.scrollTo({top:Math.max(0,ne),behavior:"smooth"}),A(ba(t.book))}},0);return()=>{clearTimeout(x)}},[F,z,j,O,t.book]),l.useLayoutEffect(()=>{if(z==="chapters"&&H){const x=H===t.book,q=x?t.chapterNum:1;A(`${H} ${n.ALL_ENGLISH_BOOK_NAMES[H]||""} ${q}`),setTimeout(()=>{if(st.current)if(x){const tt=gt.current[t.chapterNum];tt&&tt.scrollIntoView({block:"center",behavior:"smooth"})}else st.current.scrollTo({top:0});K.current&&K.current.focus()},0)}},[z,H,O,t.book,t.chapterNum]),l.useLayoutEffect(()=>{if(z==="verses"&&G&&T!==void 0){const x=G===t.book&&T===t.chapterNum,q=x?t.verseNum:1;A(`${G} ${n.ALL_ENGLISH_BOOK_NAMES[G]||""} ${T}:${q}`),setTimeout(()=>{if(st.current)if(x){const tt=qt.current[t.verseNum];tt&&tt.scrollIntoView({block:"center",behavior:"smooth"})}else st.current.scrollTo({top:0});K.current&&K.current.focus()},0)}},[z,G,T,t.book,t.chapterNum,t.verseNum]),e.jsxs(n.Popover,{open:F,onOpenChange:Q,modal:b,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsx(n.Button,{ref:bt,"aria-label":"book-chapter-trigger",variant:h,role:"combobox","aria-expanded":F,disabled:_,className:n.cn("tw:h-8 tw:w-full tw:min-w-16 tw:max-w-48 tw:overflow-hidden tw:px-1",a),onClick:x=>{Mt.current&&(Mt.current=!1,x.preventDefault())},children:f??e.jsx("span",{className:"tw:truncate",children:Ct})})}),e.jsx(n.PopoverContent,{id:u,forceMount:!0,className:"tw:w-[280px] tw:p-0",align:C,onKeyDownCapture:Ae,onKeyDown:x=>x.stopPropagation(),onPointerDownOutside:x=>{const{target:q}=x;F&&bt.current&&q instanceof Node&&bt.current.contains(q)&&(Mt.current=!0,Q(!1))},onCloseAutoFocus:k,children:e.jsxs(n.Command,{ref:K,loop:!0,value:P,onValueChange:A,shouldFilter:!1,children:[z==="books"?e.jsxs("div",{className:"tw:flex tw:items-end",children:[e.jsxs("div",{className:"tw:relative tw:flex-1",children:[e.jsx(n.CommandInput,{ref:J,value:j,onValueChange:V,onKeyDown:Ie,onFocus:()=>vt(!1),className:c&&c.length>0?"tw:!pr-10":""}),c&&c.length>0&&e.jsx(xa,{recentSearches:c,onSearchItemSelect:Yt,renderItem:x=>M.formatScrRef(x,"English"),getItemKey:x=>`${x.book}-${x.chapterNum}-${x.verseNum}`,ariaLabel:s==null?void 0:s["%history_recentSearches_ariaLabel%"],groupHeading:s==null?void 0:s["%history_recent%"]})]}),e.jsx("div",{className:"tw:flex tw:items-center tw:gap-1 tw:border-b tw:pe-2",children:L.map(({onClick:x,disabled:q,title:tt,icon:Dt})=>e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:()=>{vt(!0),x()},disabled:q,className:"tw:h-10 tw:w-4 tw:p-0",title:tt,onKeyDown:fe,children:e.jsx(Dt,{})},tt))})]}):e.jsxs("div",{className:"tw:flex tw:items-center tw:border-b tw:px-3 tw:py-2",children:[e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:z==="verses"?rt:Y,className:"tw:mr-2 tw:h-6 tw:w-6 tw:p-0",tabIndex:-1,children:B==="ltr"?e.jsx(R.ArrowLeft,{className:"tw:h-4 tw:w-4"}):e.jsx(R.ArrowRight,{className:"tw:h-4 tw:w-4"})}),z==="chapters"&&H&&e.jsx("span",{tabIndex:-1,className:"tw:text-sm tw:font-medium",children:n.getLocalizedBookName(H,i)}),z==="verses"&&G&&T!==void 0&&e.jsx("span",{tabIndex:-1,className:"tw:text-sm tw:font-medium",children:`${n.getLocalizedBookName(G,i)} ${T}`}),e.jsx("span",{tabIndex:-1,className:"tw:ms-auto tw:text-sm tw:font-medium tw:text-muted-foreground",children:z==="verses"?Ce:je})]}),!W&&e.jsxs(n.CommandList,{ref:st,children:[z==="books"&&e.jsxs(e.Fragment,{children:[!O&&Object.entries(Ht).map(([x,q])=>{if(q.length!==0)return e.jsx(n.CommandGroup,{heading:jt(x),children:q.map(tt=>e.jsx(va,{bookId:tt,onSelect:Dt=>Vt(Dt),section:M.getSectionForBook(tt),commandValue:`${tt} ${n.ALL_ENGLISH_BOOK_NAMES[tt]}`,ref:tt===t.book?ot:void 0,localizedBookNames:i,disabled:Xt(tt)},tt))},x)}),O&&e.jsx(n.CommandGroup,{children:e.jsx(n.CommandItem,{value:`${O.book} ${n.ALL_ENGLISH_BOOK_NAMES[O.book]} ${O.chapterNum||""}:${O.verseNum||""})}`,onSelect:ft,disabled:!!p&&or(O.book,O.chapterNum??1,O.verseNum??1,p),className:"tw:font-semibold tw:text-primary",children:M.formatScrRef({book:O.book,chapterNum:O.chapterNum??1,verseNum:O.verseNum??1},i?n.getLocalizedBookId(O.book,i):void 0)},"top-match")}),O&&mt&&O.chapterNum&&w&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"tw:mb-2 tw:flex tw:items-center tw:justify-between tw:px-3 tw:text-sm tw:font-medium tw:text-muted-foreground",children:[e.jsx("span",{children:`${n.getLocalizedBookName(O.book,i)} ${O.chapterNum}`}),e.jsx("span",{children:Ce})]}),e.jsx(Xr,{bookId:O.book,chapterNum:O.chapterNum,endVerse:w(O.book,O.chapterNum),scrRef:t,onVerseSelect:xt,setVerseRef:S,isVerseDisabled:_e(O.book,O.chapterNum),className:"tw:px-4 tw:pb-4"})]}),O&&!mt&&be(O.book)>1&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"tw:mb-2 tw:flex tw:items-center tw:justify-between tw:px-3 tw:text-sm tw:font-medium tw:text-muted-foreground",children:[e.jsx("span",{children:n.getLocalizedBookName(O.book,i)}),e.jsx("span",{children:je})]}),e.jsx(Yr,{bookId:O.book,scrRef:t,onChapterSelect:te,setChapterRef:ae,isChapterDimmed:At,isChapterDisabled:oe(O.book),className:"tw:px-4 tw:pb-4"})]})]}),z==="chapters"&&H&&e.jsx(Yr,{bookId:H,scrRef:t,onChapterSelect:te,setChapterRef:ae,isChapterDisabled:oe(H),className:"tw:p-4"}),z==="verses"&&G&&T!==void 0&&w&&e.jsx(Xr,{bookId:G,chapterNum:T,endVerse:w(G,T),scrRef:t,onVerseSelect:xt,setVerseRef:S,isVerseDisabled:_e(G,T),className:"tw:p-4"})]})]})})]})}const nn=Object.freeze(["%scripture_section_ot_long%","%scripture_section_nt_long%","%scripture_section_dc_long%","%scripture_section_extra_long%","%history_recent%","%history_recentSearches_ariaLabel%","%webView_bookChapterControl_selectChapter%","%webView_bookChapterControl_selectVerse%"]);function rr({className:t,...r}){const a=n.readDirection();return e.jsx(D.RadioGroup.Root,{"data-slot":"radio-group",className:n.cn("pr-twp tw:grid tw:w-full tw:gap-2",t),dir:a,...r})}function Re({className:t,...r}){return e.jsx(D.RadioGroup.Item,{"data-slot":"radio-group-item",className:n.cn("pr-twp tw:group/radio-group-item tw:peer tw:relative tw:flex tw:aspect-square tw:size-4 tw:shrink-0 tw:rounded-full tw:border tw:border-input tw:outline-none tw:after:absolute tw:after:-inset-x-3 tw:after:-inset-y-2 tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:aria-invalid:aria-checked:border-primary tw:dark:bg-input/30 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:data-checked:border-primary tw:data-checked:bg-primary tw:data-checked:text-primary-foreground tw:dark:data-checked:bg-primary",t),...r,children:e.jsx(D.RadioGroup.Indicator,{"data-slot":"radio-group-indicator",className:"tw:flex tw:size-4 tw:items-center tw:justify-center",children:e.jsx("span",{className:"tw:absolute tw:top-1/2 tw:start-1/2 tw:size-2 tw:-translate-x-1/2 tw:rtl:translate-x-1/2 tw:-translate-y-1/2 tw:rounded-full tw:bg-primary-foreground"})})})}function sn(t){return typeof t=="string"?t:typeof t=="number"?t.toString():t.label}function mr({id:t,options:r=[],className:a,buttonClassName:o,popoverContentClassName:i,popoverContentStyle:s,value:c,onChange:d=()=>{},getOptionLabel:u=sn,getButtonLabel:w,icon:p=void 0,buttonPlaceholder:g="",textPlaceholder:f="",commandEmptyMessage:h="No option found",buttonVariant:m="outline",alignDropDown:k="start",isDisabled:b=!1,ariaLabel:C,...y}){const[_,B]=l.useState(!1),F=w??u,E=A=>A.length>0&&typeof A[0]=="object"&&"options"in A[0],P=(A,j)=>{const V=u(A),z=typeof A=="object"&&"secondaryLabel"in A?A.secondaryLabel:void 0,N=`${j??""}${V}${z??""}`;return e.jsxs(n.CommandItem,{value:V,onSelect:()=>{d(A),B(!1)},className:"tw:gap-1.5!",children:[e.jsx(R.Check,{className:n.cn("tw:h-4 tw:w-4 tw:shrink-0",{"tw:opacity-0":!c||u(c)!==V})}),e.jsxs("span",{className:"tw:flex-1 tw:overflow-hidden tw:text-ellipsis tw:whitespace-nowrap",children:[V,z&&e.jsxs("span",{className:"tw:text-muted-foreground",children:[" · ",z]})]})]},N)};return e.jsxs(n.Popover,{open:_,onOpenChange:B,...y,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:m,role:"combobox","aria-expanded":_,"aria-label":C,id:t,className:n.cn("tw:flex tw:w-[200px] tw:items-center tw:justify-between tw:overflow-hidden",o??a),disabled:b,children:[e.jsxs("div",{className:"tw:flex tw:min-w-0 tw:flex-1 tw:items-center tw:overflow-hidden",children:[p&&e.jsx("div",{className:"tw:shrink-0 tw:pe-2",children:p}),e.jsx("span",{className:n.cn("tw:min-w-0 tw:overflow-hidden tw:text-ellipsis tw:whitespace-nowrap tw:text-start"),children:c?F(c):g})]}),e.jsx(R.ChevronDown,{className:"tw:ms-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})}),e.jsx(n.PopoverContent,{align:k,className:n.cn("tw:w-[200px] tw:p-0",i),style:s,children:e.jsxs(n.Command,{children:[e.jsx(n.CommandInput,{placeholder:f,className:"tw:text-inherit"}),e.jsx(n.CommandEmpty,{children:h}),e.jsx(n.CommandList,{children:E(r)?r.map(A=>e.jsx(n.CommandGroup,{heading:A.groupHeading,children:A.options.map(j=>P(j,A.groupHeading))},A.groupHeading)):e.jsx(n.CommandGroup,{children:r.map(A=>P(A))})})]})})]})}function ya({startChapter:t,endChapter:r,handleSelectStartChapter:a,handleSelectEndChapter:o,isDisabled:i=!1,chapterCount:s}){const c=l.useMemo(()=>Array.from({length:s},(w,p)=>p+1),[s]),d=w=>{a(w),w>r&&o(w)},u=w=>{o(w),ww.toString(),value:t},"start chapter"),e.jsx(n.Label,{htmlFor:"end-chapters-combobox",children:"to"}),e.jsx(mr,{isDisabled:i,onChange:u,buttonClassName:"tw:ms-2 tw:w-20",options:c,getOptionLabel:w=>w.toString(),value:r},"end chapter")]})}exports.BookSelectionMode=(t=>(t.CurrentBook="current book",t.ChooseBooks="choose books",t))(exports.BookSelectionMode||{});(t=>{t.CURRENT_BOOK="current book",t.CHOOSE_BOOKS="choose books"})(exports.BookSelectionMode||(exports.BookSelectionMode={}));const cn=Object.freeze(["%webView_bookSelector_currentBook%","%webView_bookSelector_choose%","%webView_bookSelector_chooseBooks%"]),nr=(t,r)=>t[r]??r;function ln({handleBookSelectionModeChange:t,currentBookName:r,onSelectBooks:a,selectedBookIds:o,chapterCount:i,endChapter:s,handleSelectEndChapter:c,startChapter:d,handleSelectStartChapter:u,localizedStrings:w}){const p=nr(w,"%webView_bookSelector_currentBook%"),g=nr(w,"%webView_bookSelector_choose%"),f=nr(w,"%webView_bookSelector_chooseBooks%"),[h,m]=l.useState("current book"),k=b=>{m(b),t(b)};return e.jsx(rr,{className:"pr-twp tw:flex",value:h,onValueChange:b=>k(b),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:flex-col tw:gap-4",children:[e.jsxs("div",{className:"tw:grid tw:grid-cols-[25%_25%_50%]",children:[e.jsxs("div",{className:"tw:flex tw:items-center",children:[e.jsx(Re,{value:"current book"}),e.jsx(n.Label,{className:"tw:ms-1",children:p})]}),e.jsx(n.Label,{className:"tw:flex tw:items-center",children:r}),e.jsx("div",{className:"tw:flex tw:items-center tw:justify-end",children:e.jsx(ya,{isDisabled:h==="choose books",handleSelectStartChapter:u,handleSelectEndChapter:c,chapterCount:i,startChapter:d,endChapter:s})})]}),e.jsxs("div",{className:"tw:grid tw:grid-cols-[25%_50%_25%]",children:[e.jsxs("div",{className:"tw:flex tw:items-center",children:[e.jsx(Re,{value:"choose books"}),e.jsx(n.Label,{className:"tw:ms-1",children:f})]}),e.jsx(n.Label,{className:"tw:flex tw:items-center",children:o.map(b=>ht.Canon.bookIdToEnglishName(b)).join(", ")}),e.jsx(n.Button,{disabled:h==="current book",onClick:()=>a(),children:g})]})]})})}const _a=l.createContext(null);function dn(t,r){return{getTheme:function(){return r??null}}}function Qt(){const t=l.useContext(_a);return t==null&&function(r,...a){const o=new URL("https://lexical.dev/docs/error"),i=new URLSearchParams;i.append("code",r);for(const s of a)i.append("v",s);throw o.search=i.toString(),Error(`Minified Lexical error #${r}; visit ${o.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(8),t}const ja=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0,wn=ja?l.useLayoutEffect:l.useEffect,Pe={tag:v.HISTORY_MERGE_TAG};function un({initialConfig:t,children:r}){const a=l.useMemo(()=>{const{theme:o,namespace:i,nodes:s,onError:c,editorState:d,html:u}=t,w=dn(null,o),p=v.createEditor({editable:t.editable,html:u,namespace:i,nodes:s,onError:g=>c(g,p),theme:o});return function(g,f){if(f!==null){if(f===void 0)g.update(()=>{const h=v.$getRoot();if(h.isEmpty()){const m=v.$createParagraphNode();h.append(m);const k=ja?document.activeElement:null;(v.$getSelection()!==null||k!==null&&k===g.getRootElement())&&m.select()}},Pe);else if(f!==null)switch(typeof f){case"string":{const h=g.parseEditorState(f);g.setEditorState(h,Pe);break}case"object":g.setEditorState(f,Pe);break;case"function":g.update(()=>{v.$getRoot().isEmpty()&&f(g)},Pe)}}}(p,d),[p,w]},[]);return wn(()=>{const o=t.editable,[i]=a;i.setEditable(o===void 0||o)},[]),e.jsx(_a.Provider,{value:a,children:r})}const pn=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function gn({ignoreHistoryMergeTagChange:t=!0,ignoreSelectionChange:r=!1,onChange:a}){const[o]=Qt();return pn(()=>{if(a)return o.registerUpdateListener(({editorState:i,dirtyElements:s,dirtyLeaves:c,prevEditorState:d,tags:u})=>{r&&s.size===0&&c.size===0||t&&u.has(v.HISTORY_MERGE_TAG)||d.isEmpty()||a(i,o,u)})},[o,t,r,a]),null}const jr={ltr:"tw:text-left",rtl:"tw:text-right",heading:{h1:"tw:scroll-m-20 tw:text-4xl tw:font-extrabold tw:tracking-tight tw:lg:text-5xl",h2:"tw:scroll-m-20 tw:border-b tw:pb-2 tw:text-3xl tw:font-semibold tw:tracking-tight tw:first:mt-0",h3:"tw:scroll-m-20 tw:text-2xl tw:font-semibold tw:tracking-tight",h4:"tw:scroll-m-20 tw:text-xl tw:font-semibold tw:tracking-tight",h5:"tw:scroll-m-20 tw:text-lg tw:font-semibold tw:tracking-tight",h6:"tw:scroll-m-20 tw:text-base tw:font-semibold tw:tracking-tight"},paragraph:"tw:outline-hidden",quote:"tw:mt-6 tw:border-l-2 tw:pl-6 tw:italic",link:"tw:text-blue-600 tw:hover:underline tw:hover:cursor-pointer",list:{checklist:"tw:relative",listitem:"tw:mx-8",listitemChecked:'tw:relative tw:mx-2 tw:px-6 tw:list-none tw:outline-hidden tw:line-through tw:before:content-[""] tw:before:w-4 tw:before:h-4 tw:before:top-0.5 tw:before:left-0 tw:before:cursor-pointer tw:before:block tw:before:bg-cover tw:before:absolute tw:before:border tw:before:border-primary tw:before:rounded tw:before:bg-primary tw:before:bg-no-repeat tw:after:content-[""] tw:after:cursor-pointer tw:after:border-white tw:after:border-solid tw:after:absolute tw:after:block tw:after:top-[6px] tw:after:w-[3px] tw:after:left-[7px] tw:after:right-[7px] tw:after:h-[6px] tw:after:rotate-45 tw:after:border-r-2 tw:after:border-b-2 tw:after:border-l-0 tw:after:border-t-0',listitemUnchecked:'tw:relative tw:mx-2 tw:px-6 tw:list-none tw:outline-hidden tw:before:content-[""] tw:before:w-4 tw:before:h-4 tw:before:top-0.5 tw:before:left-0 tw:before:cursor-pointer tw:before:block tw:before:bg-cover tw:before:absolute tw:before:border tw:before:border-primary tw:before:rounded',nested:{listitem:"tw:list-none tw:before:hidden tw:after:hidden"},ol:"tw:m-0 tw:p-0 tw:list-decimal tw:[&>li]:mt-2",olDepth:["tw:list-outside tw:!list-decimal","tw:list-outside tw:!list-[upper-roman]","tw:list-outside tw:!list-[lower-roman]","tw:list-outside tw:!list-[upper-alpha]","tw:list-outside tw:!list-[lower-alpha]"],ul:"tw:m-0 tw:p-0 tw:list-outside tw:[&>li]:mt-2",ulDepth:["tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc"]},hashtag:"tw:text-blue-600 tw:bg-blue-100 tw:rounded-md tw:px-1",text:{bold:"tw:font-bold",code:"tw:bg-gray-100 tw:p-1 tw:rounded-md",italic:"tw:italic",strikethrough:"tw:line-through",subscript:"tw:sub",superscript:"tw:sup",underline:"tw:underline",underlineStrikethrough:"tw:underline tw:line-through"},image:"tw:relative tw:inline-block tw:user-select-none tw:cursor-default editor-image",inlineImage:"tw:relative tw:inline-block tw:user-select-none tw:cursor-default inline-editor-image",keyword:"tw:text-purple-900 tw:font-bold",code:"EditorTheme__code",codeHighlight:{atrule:"EditorTheme__tokenAttr",attr:"EditorTheme__tokenAttr",boolean:"EditorTheme__tokenProperty",builtin:"EditorTheme__tokenSelector",cdata:"EditorTheme__tokenComment",char:"EditorTheme__tokenSelector",class:"EditorTheme__tokenFunction","class-name":"EditorTheme__tokenFunction",comment:"EditorTheme__tokenComment",constant:"EditorTheme__tokenProperty",deleted:"EditorTheme__tokenProperty",doctype:"EditorTheme__tokenComment",entity:"EditorTheme__tokenOperator",function:"EditorTheme__tokenFunction",important:"EditorTheme__tokenVariable",inserted:"EditorTheme__tokenSelector",keyword:"EditorTheme__tokenAttr",namespace:"EditorTheme__tokenVariable",number:"EditorTheme__tokenProperty",operator:"EditorTheme__tokenOperator",prolog:"EditorTheme__tokenComment",property:"EditorTheme__tokenProperty",punctuation:"EditorTheme__tokenPunctuation",regex:"EditorTheme__tokenVariable",selector:"EditorTheme__tokenSelector",string:"EditorTheme__tokenSelector",symbol:"EditorTheme__tokenProperty",tag:"EditorTheme__tokenProperty",url:"EditorTheme__tokenOperator",variable:"EditorTheme__tokenVariable"},characterLimit:"tw:!bg-destructive/50",table:"EditorTheme__table tw:w-fit tw:overflow-scroll tw:border-collapse",tableCell:"EditorTheme__tableCell tw:w-24 tw:relative tw:border tw:px-4 tw:py-2 tw:text-left tw:[&[align=center]]:text-center tw:[&[align=right]]:text-right",tableCellActionButton:"EditorTheme__tableCellActionButton tw:bg-background tw:block tw:border-0 tw:rounded-2xl tw:w-5 tw:h-5 tw:text-foreground tw:cursor-pointer",tableCellActionButtonContainer:"EditorTheme__tableCellActionButtonContainer tw:block tw:right-1 tw:top-1.5 tw:absolute tw:z-10 tw:w-5 tw:h-5",tableCellEditing:"EditorTheme__tableCellEditing tw:rounded-sm tw:shadow-sm",tableCellHeader:"EditorTheme__tableCellHeader tw:bg-muted tw:border tw:px-4 tw:py-2 tw:text-left tw:font-bold tw:[&[align=center]]:text-center tw:[&[align=right]]:text-right",tableCellPrimarySelected:"EditorTheme__tableCellPrimarySelected tw:border tw:border-primary tw:border-solid tw:block tw:h-[calc(100%-2px)] tw:w-[calc(100%-2px)] tw:absolute tw:-left-[1px] tw:-top-[1px] tw:z-10 ",tableCellResizer:"EditorTheme__tableCellResizer tw:absolute tw:-right-1 tw:h-full tw:w-2 tw:cursor-ew-resize tw:z-10 tw:top-0",tableCellSelected:"EditorTheme__tableCellSelected tw:bg-muted",tableCellSortedIndicator:"EditorTheme__tableCellSortedIndicator tw:block tw:opacity-50 tw:absolute tw:bottom-0 tw:left-0 tw:w-full tw:h-1 tw:bg-muted",tableResizeRuler:"EditorTheme__tableCellResizeRuler tw:block tw:absolute tw:w-[1px] tw:h-full tw:bg-primary tw:top-0",tableRowStriping:"EditorTheme__tableRowStriping tw:m-0 tw:border-t tw:p-0 tw:even:bg-muted",tableSelected:"EditorTheme__tableSelected tw:ring-2 tw:ring-primary tw:ring-offset-2",tableSelection:"EditorTheme__tableSelection tw:bg-transparent",layoutItem:"tw:border tw:border-dashed tw:px-4 tw:py-2",layoutContainer:"tw:grid tw:gap-2.5 tw:my-2.5 tw:mx-0",autocomplete:"tw:text-muted-foreground",blockCursor:"",embedBlock:{base:"tw:user-select-none",focus:"tw:ring-2 tw:ring-primary tw:ring-offset-2"},hr:'tw:p-0.5 tw:border-none tw:my-1 tw:mx-0 tw:cursor-pointer tw:after:content-[""] tw:after:block tw:after:h-0.5 tw:after:bg-muted tw:selected:ring-2 tw:selected:ring-primary tw:selected:ring-offset-2 tw:selected:user-select-none',indent:"[--lexical-indent-base-value:40px]",mark:"",markOverlap:""},Cr=[fr.HeadingNode,v.ParagraphNode,v.TextNode,fr.QuoteNode],hn=l.createContext(null),ir={didCatch:!1,error:null};class fn extends l.Component{constructor(r){super(r),this.resetErrorBoundary=this.resetErrorBoundary.bind(this),this.state=ir}static getDerivedStateFromError(r){return{didCatch:!0,error:r}}resetErrorBoundary(){const{error:r}=this.state;if(r!==null){for(var a,o,i=arguments.length,s=new Array(i),c=0;c0&&arguments[0]!==void 0?arguments[0]:[],r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[];return t.length!==r.length||t.some((a,o)=>!Object.is(a,r[o]))}function vn({children:t,onError:r}){return e.jsx(fn,{fallback:e.jsx("div",{style:{border:"1px solid #f00",color:"#f00",padding:"8px"},children:"An error was thrown."}),onError:r,children:t})}const bn=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function xn(t){return{initialValueFn:()=>t.isEditable(),subscribe:r=>t.registerEditableListener(r)}}function kn(){return function(t){const[r]=Qt(),a=l.useMemo(()=>t(r),[r,t]),[o,i]=l.useState(()=>a.initialValueFn()),s=l.useRef(o);return bn(()=>{const{initialValueFn:c,subscribe:d}=a,u=c();return s.current!==u&&(s.current=u,i(u)),d(w=>{s.current=w,i(w)})},[a,t]),o}(xn)}function yn(t,r){const a=t.getRootElement();if(a===null)return[];const o=a.getBoundingClientRect(),i=getComputedStyle(a),s=parseFloat(i.paddingLeft)+parseFloat(i.paddingRight),c=Array.from(r.getClientRects());let d,u=c.length;c.sort((w,p)=>{const g=w.top-p.top;return Math.abs(g)<=3?w.left-p.left:g});for(let w=0;wp.top&&d.left+d.width>p.left,f=p.width+s===o.width;g||f?(c.splice(w--,1),u--):d=p}return c}function Ye(t,...r){const a=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const i of r)o.append("v",i);throw a.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${a.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const Ca=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0,_n=Ca&&"documentMode"in document?document.documentMode:null;!(!Ca||!("InputEvent"in window)||_n)&&"getTargetRanges"in new window.InputEvent("input");function Wt(t){return`${t}px`}const jn={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Cn(t,r,a){let o=null,i=null,s=null,c=[];const d=document.createElement("div");function u(){o===null&&Ye(182),i===null&&Ye(183);const{left:g,top:f}=i.getBoundingClientRect(),h=yn(t,r);var m,k;d.isConnected||(k=d,(m=i).insertBefore(k,m.firstChild));let b=!1;for(let C=0;Ch.length;)c.pop();b&&a(c)}function w(){i=null,o=null,s!==null&&s.disconnect(),s=null,d.remove();for(const g of c)g.remove();c=[]}d.style.position="relative";const p=t.registerRootListener(function g(){const f=t.getRootElement();if(f===null)return w();const h=f.parentElement;if(!v.isHTMLElement(h))return w();w(),o=f,i=h,s=new MutationObserver(m=>{const k=t.getRootElement(),b=k&&k.parentElement;if(k!==o||b!==i)return g();for(const C of m)if(!d.contains(C.target))return u()}),s.observe(h,jn),u()});return()=>{p(),w()}}function Zr(t,r,a){if(t.type!=="text"&&v.$isElementNode(r)){const o=r.getDOMSlot(a);return[o.element,o.getFirstChildOffset()+t.offset]}return[v.getDOMTextNode(a)||a,t.offset]}function Nn(t){for(const r of t){const a=r.style;a.background!=="Highlight"&&(a.background="Highlight"),a.color!=="HighlightText"&&(a.color="HighlightText"),a.marginTop!==Wt(-1.5)&&(a.marginTop=Wt(-1.5)),a.paddingTop!==Wt(4)&&(a.paddingTop=Wt(4)),a.paddingBottom!==Wt(0)&&(a.paddingBottom=Wt(0))}}function En(t,r=Nn){let a=null,o=null,i=null,s=null,c=null,d=null,u=()=>{};function w(p){p.read(()=>{const g=v.$getSelection();if(!v.$isRangeSelection(g))return a=null,i=null,s=null,d=null,u(),void(u=()=>{});const[f,h]=function(A){const j=A.getStartEndPoints();return A.isBackward()?[j[1],j[0]]:j}(g),m=f.getNode(),k=m.getKey(),b=f.offset,C=h.getNode(),y=C.getKey(),_=h.offset,B=t.getElementByKey(k),F=t.getElementByKey(y),E=a===null||B!==o||b!==i||k!==a.getKey(),P=s===null||F!==c||_!==d||y!==s.getKey();if((E||P)&&B!==null&&F!==null){const A=function(j,V,z,N,H,U,G){const I=(j._window?j._window.document:document).createRange();return I.setStart(...Zr(V,z,N)),I.setEnd(...Zr(H,U,G)),I}(t,f,m,B,h,C,F);u(),u=Cn(t,A,r)}a=m,o=B,i=b,s=C,c=F,d=_})}return w(t.getEditorState()),v.mergeRegister(t.registerUpdateListener(({editorState:p})=>w(p)),()=>{u()})}function Sn(t,r){let a=null;const o=()=>{const i=getSelection(),s=i&&i.anchorNode,c=t.getRootElement();s!==null&&c!==null&&c.contains(s)?a!==null&&(a(),a=null):a===null&&(a=En(t,r))};return t.registerRootListener(i=>{if(i){const s=i.ownerDocument;return s.addEventListener("selectionchange",o),o(),()=>{a!==null&&a(),s.removeEventListener("selectionchange",o)}}})}function Tn(t){const r=v.$findMatchingParent(t,a=>v.$isElementNode(a)&&!a.isInline());return v.$isElementNode(r)||Ye(4,t.__key),r}function Mn(t){const r=v.$getSelection()||v.$getPreviousSelection();let a;if(v.$isRangeSelection(r))a=v.$caretFromPoint(r.focus,"next");else{if(r!=null){const c=r.getNodes(),d=c[c.length-1];d&&(a=v.$getSiblingCaret(d,"next"))}a=a||v.$getChildCaret(v.$getRoot(),"previous").getFlipped().insert(v.$createParagraphNode())}const o=Rn(t,a),i=v.$getAdjacentChildCaret(o),s=v.$isChildCaret(i)?v.$normalizeCaret(i):o;return v.$setSelectionFromCaretRange(v.$getCollapsedCaretRange(s)),t.getLatest()}function Rn(t,r,a){let o=v.$getCaretInDirection(r,"next");for(let i=o;i;i=v.$splitAtPointCaretNext(i,a))o=i;return v.$isTextPointCaret(o)&&Ye(283),o.insert(t.isInline()?v.$createParagraphNode().append(t):t),v.$getCaretInDirection(v.$getSiblingCaret(t.getLatest(),"next"),r.direction)}function Dn(t){const r=v.$getSelection();if(!v.$isRangeSelection(r))return!1;const a=new Set,o=r.getNodes();for(let i=0;iv.$isElementNode(w)&&!w.isInline());if(d===null)continue;const u=d.getKey();d.canIndent()&&!a.has(u)&&(a.add(u),t(d))}return a.size>0}const On=Symbol.for("preact-signals");function ar(){if(re>1)return void re--;let t,r=!1;for(!function(){let a=Xe;for(Xe=void 0;a!==void 0;)a.S.v===a.v&&(a.S.i=a.i),a=a.o}();Te!==void 0;){let a=Te;for(Te=void 0,Ze++;a!==void 0;){const o=a.u;if(a.u=void 0,a.f&=-3,!(8&a.f)&&Na(a))try{a.c()}catch(i){r||(t=i,r=!0)}a=o}}if(Ze=0,re--,r)throw t}function zn(t){if(re>0)return t();vr=++In,re++;try{return t()}finally{ar()}}let at,Te;function Wr(t){const r=at;at=void 0;try{return t()}finally{at=r}}let Xe,re=0,Ze=0,In=0,vr=0,Ke=0;function Jr(t){if(at===void 0)return;let r=t.n;return r===void 0||r.t!==at?(r={i:0,S:t,p:at.s,n:void 0,t:at,e:void 0,x:void 0,r},at.s!==void 0&&(at.s.n=r),at.s=r,t.n=r,32&at.f&&t.S(r),r):r.i===-1?(r.i=0,r.n!==void 0&&(r.n.p=r.p,r.p!==void 0&&(r.p.n=r.n),r.p=at.s,r.n=void 0,at.s.n=r,at.s=r),r):void 0}function zt(t,r){this.v=t,this.i=0,this.n=void 0,this.t=void 0,this.l=0,this.W=r==null?void 0:r.watched,this.Z=r==null?void 0:r.unwatched,this.name=r==null?void 0:r.name}function De(t,r){return new zt(t,r)}function Na(t){for(let r=t.s;r!==void 0;r=r.n)if(r.S.i!==r.i||!r.S.h()||r.S.i!==r.i)return!0;return!1}function Qr(t){for(let r=t.s;r!==void 0;r=r.n){const a=r.S.n;if(a!==void 0&&(r.r=a),r.S.n=r,r.i=-1,r.n===void 0){t.s=r;break}}}function Ea(t){let r,a=t.s;for(;a!==void 0;){const o=a.p;a.i===-1?(a.S.U(a),o!==void 0&&(o.n=a.n),a.n!==void 0&&(a.n.p=o)):r=a,a.S.n=a.r,a.r!==void 0&&(a.r=void 0),a=o}t.s=r}function de(t,r){zt.call(this,void 0),this.x=t,this.s=void 0,this.g=Ke-1,this.f=4,this.W=r==null?void 0:r.watched,this.Z=r==null?void 0:r.unwatched,this.name=r==null?void 0:r.name}function An(t,r){return new de(t,r)}function Sa(t){const r=t.m;if(t.m=void 0,typeof r=="function"){re++;const a=at;at=void 0;try{r()}catch(o){throw t.f&=-2,t.f|=8,Nr(t),o}finally{at=a,ar()}}}function Nr(t){for(let r=t.s;r!==void 0;r=r.n)r.S.U(r);t.x=void 0,t.s=void 0,Sa(t)}function $n(t){if(at!==this)throw new Error("Out-of-order effect");Ea(this),at=t,this.f&=-2,8&this.f&&Nr(this),ar()}function ve(t,r){this.x=t,this.m=void 0,this.s=void 0,this.u=void 0,this.f=32,this.name=r==null?void 0:r.name}function Jt(t,r){const a=new ve(t,r);try{a.c()}catch(i){throw a.d(),i}const o=a.d.bind(a);return o[Symbol.dispose]=o,o}function ye(t,r={}){const a={};for(const o in t){const i=r[o],s=De(i===void 0?t[o]:i);a[o]=s}return a}zt.prototype.brand=On,zt.prototype.h=function(){return!0},zt.prototype.S=function(t){const r=this.t;r!==t&&t.e===void 0&&(t.x=r,this.t=t,r!==void 0?r.e=t:Wr(()=>{var a;(a=this.W)==null||a.call(this)}))},zt.prototype.U=function(t){if(this.t!==void 0){const r=t.e,a=t.x;r!==void 0&&(r.x=a,t.e=void 0),a!==void 0&&(a.e=r,t.x=void 0),t===this.t&&(this.t=a,a===void 0&&Wr(()=>{var o;(o=this.Z)==null||o.call(this)}))}},zt.prototype.subscribe=function(t){return Jt(()=>{const r=this.value,a=at;at=void 0;try{t(r)}finally{at=a}},{name:"sub"})},zt.prototype.valueOf=function(){return this.value},zt.prototype.toString=function(){return this.value+""},zt.prototype.toJSON=function(){return this.value},zt.prototype.peek=function(){const t=at;at=void 0;try{return this.value}finally{at=t}},Object.defineProperty(zt.prototype,"value",{get(){const t=Jr(this);return t!==void 0&&(t.i=this.i),this.v},set(t){if(t!==this.v){if(Ze>100)throw new Error("Cycle detected");(function(r){re!==0&&Ze===0&&r.l!==vr&&(r.l=vr,Xe={S:r,v:r.v,i:r.i,o:Xe})})(this),this.v=t,this.i++,Ke++,re++;try{for(let r=this.t;r!==void 0;r=r.x)r.t.N()}finally{ar()}}}}),de.prototype=new zt,de.prototype.h=function(){if(this.f&=-3,1&this.f)return!1;if((36&this.f)==32||(this.f&=-5,this.g===Ke))return!0;if(this.g=Ke,this.f|=1,this.i>0&&!Na(this))return this.f&=-2,!0;const t=at;try{Qr(this),at=this;const r=this.x();(16&this.f||this.v!==r||this.i===0)&&(this.v=r,this.f&=-17,this.i++)}catch(r){this.v=r,this.f|=16,this.i++}return at=t,Ea(this),this.f&=-2,!0},de.prototype.S=function(t){if(this.t===void 0){this.f|=36;for(let r=this.s;r!==void 0;r=r.n)r.S.S(r)}zt.prototype.S.call(this,t)},de.prototype.U=function(t){if(this.t!==void 0&&(zt.prototype.U.call(this,t),this.t===void 0)){this.f&=-33;for(let r=this.s;r!==void 0;r=r.n)r.S.U(r)}},de.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(let t=this.t;t!==void 0;t=t.x)t.t.N()}},Object.defineProperty(de.prototype,"value",{get(){if(1&this.f)throw new Error("Cycle detected");const t=Jr(this);if(this.h(),t!==void 0&&(t.i=this.i),16&this.f)throw this.v;return this.v}}),ve.prototype.c=function(){const t=this.S();try{if(8&this.f||this.x===void 0)return;const r=this.x();typeof r=="function"&&(this.m=r)}finally{t()}},ve.prototype.S=function(){if(1&this.f)throw new Error("Cycle detected");this.f|=1,this.f&=-9,Sa(this),Qr(this),re++;const t=at;return at=this,$n.bind(this,t)},ve.prototype.N=function(){2&this.f||(this.f|=2,this.u=Te,Te=this)},ve.prototype.d=function(){this.f|=8,1&this.f||Nr(this)},ve.prototype.dispose=function(){this.d()};v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({defaultSelection:"rootEnd",disabled:!1}),name:"@lexical/extension/AutoFocus",register(t,r,a){const o=a.getOutput();return Jt(()=>o.disabled.value?void 0:t.registerRootListener(i=>{t.focus(()=>{const s=document.activeElement;i===null||s!==null&&i.contains(s)||i.focus({preventScroll:!0})},{defaultSelection:o.defaultSelection.peek()})}))}});function Ta(){const t=v.$getRoot(),r=v.$getSelection(),a=v.$createParagraphNode();t.clear(),t.append(a),r!==null&&a.select(),v.$isRangeSelection(r)&&(r.format=0)}function Ma(t,r=Ta){return t.registerCommand(v.CLEAR_EDITOR_COMMAND,a=>(t.update(r),!0),v.COMMAND_PRIORITY_EDITOR)}v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({$onClear:Ta}),name:"@lexical/extension/ClearEditor",register(t,r,a){const{$onClear:o}=a.getOutput();return Jt(()=>Ma(t,o.value))}});function Bn(t){return(typeof t.nodes=="function"?t.nodes():t.nodes)||[]}const sr=v.createState("format",{parse:t=>typeof t=="number"?t:0});class Ra extends v.DecoratorNode{$config(){return this.config("decorator-text",{extends:v.DecoratorNode,stateConfigs:[{flat:!0,stateConfig:sr}]})}getFormat(){return v.$getState(this,sr)}getFormatFlags(r,a){return v.toggleTextFormatType(this.getFormat(),r,a)}hasFormat(r){const a=v.TEXT_TYPE_TO_FORMAT[r];return(this.getFormat()&a)!==0}setFormat(r){return v.$setState(this,sr,r)}toggleFormat(r){const a=this.getFormat(),o=v.toggleTextFormatType(a,r,null);return this.setFormat(o)}isInline(){return!0}createDOM(){return document.createElement("span")}updateDOM(){return!1}}function Pn(t){return t instanceof Ra}v.defineExtension({name:"@lexical/extension/DecoratorText",nodes:()=>[Ra],register:(t,r,a)=>t.registerCommand(v.FORMAT_TEXT_COMMAND,o=>{const i=v.$getSelection();if(v.$isNodeSelection(i)||v.$isRangeSelection(i))for(const s of i.getNodes())Pn(s)&&s.toggleFormat(o);return!1},v.COMMAND_PRIORITY_LOW)});function Da(t,r){let a;return De(t(),{unwatched(){a&&(a(),a=void 0)},watched(){this.value=t(),a=r(this)}})}const br=v.defineExtension({build:t=>Da(()=>t.getEditorState(),r=>t.registerUpdateListener(a=>{r.value=a.editorState})),name:"@lexical/extension/EditorState"});function it(t,...r){const a=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const i of r)o.append("v",i);throw a.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${a.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}function Oa(t,r){if(t&&r&&!Array.isArray(r)&&typeof t=="object"&&typeof r=="object"){const a=t,o=r;for(const i in o)a[i]=Oa(a[i],o[i]);return t}return r}const Er=0,xr=1,za=2,cr=3,Le=4,me=5,lr=6,Ee=7;function dr(t){return t.id===Er}function Ia(t){return t.id===za}function Ln(t){return function(r){return r.id===xr}(t)||it(305,String(t.id),String(xr)),Object.assign(t,{id:za})}const Vn=new Set;class Fn{constructor(r,a){Ot(this,"builder");Ot(this,"configs");Ot(this,"_dependency");Ot(this,"_peerNameSet");Ot(this,"extension");Ot(this,"state");Ot(this,"_signal");this.builder=r,this.extension=a,this.configs=new Set,this.state={id:Er}}mergeConfigs(){let r=this.extension.config||{};const a=this.extension.mergeConfig?this.extension.mergeConfig.bind(this.extension):v.shallowMergeConfig;for(const o of this.configs)r=a(r,o);return r}init(r){const a=this.state;Ia(a)||it(306,String(a.id));const o={getDependency:this.getInitDependency.bind(this),getDirectDependentNames:this.getDirectDependentNames.bind(this),getPeer:this.getInitPeer.bind(this),getPeerNameSet:this.getPeerNameSet.bind(this)},i={...o,getDependency:this.getDependency.bind(this),getInitResult:this.getInitResult.bind(this),getPeer:this.getPeer.bind(this)},s=function(d,u,w){return Object.assign(d,{config:u,id:cr,registerState:w})}(a,this.mergeConfigs(),o);let c;this.state=s,this.extension.init&&(c=this.extension.init(r,s.config,o)),this.state=function(d,u,w){return Object.assign(d,{id:Le,initResult:u,registerState:w})}(s,c,i)}build(r){const a=this.state;let o;a.id!==Le&&it(307,String(a.id),String(me)),this.extension.build&&(o=this.extension.build(r,a.config,a.registerState));const i={...a.registerState,getOutput:()=>o,getSignal:this.getSignal.bind(this)};this.state=function(s,c,d){return Object.assign(s,{id:me,output:c,registerState:d})}(a,o,i)}register(r,a){this._signal=a;const o=this.state;o.id!==me&&it(308,String(o.id),String(me));const i=this.extension.register&&this.extension.register(r,o.config,o.registerState);return this.state=function(s){return Object.assign(s,{id:lr})}(o),()=>{const s=this.state;s.id!==Ee&&it(309,String(o.id),String(Ee)),this.state=function(c){return Object.assign(c,{id:me})}(s),i&&i()}}afterRegistration(r){const a=this.state;let o;return a.id!==lr&&it(310,String(a.id),String(lr)),this.extension.afterRegistration&&(o=this.extension.afterRegistration(r,a.config,a.registerState)),this.state=function(i){return Object.assign(i,{id:Ee})}(a),o}getSignal(){return this._signal===void 0&&it(311),this._signal}getInitResult(){this.extension.init===void 0&&it(312,this.extension.name);const r=this.state;return function(a){return a.id>=Le}(r)||it(313,String(r.id),String(Le)),r.initResult}getInitPeer(r){const a=this.builder.extensionNameMap.get(r);return a?a.getExtensionInitDependency():void 0}getExtensionInitDependency(){const r=this.state;return function(a){return a.id>=cr}(r)||it(314,String(r.id),String(cr)),{config:r.config}}getPeer(r){const a=this.builder.extensionNameMap.get(r);return a?a.getExtensionDependency():void 0}getInitDependency(r){const a=this.builder.getExtensionRep(r);return a===void 0&&it(315,this.extension.name,r.name),a.getExtensionInitDependency()}getDependency(r){const a=this.builder.getExtensionRep(r);return a===void 0&&it(315,this.extension.name,r.name),a.getExtensionDependency()}getState(){const r=this.state;return function(a){return a.id>=Ee}(r)||it(316,String(r.id),String(Ee)),r}getDirectDependentNames(){return this.builder.incomingEdges.get(this.extension.name)||Vn}getPeerNameSet(){let r=this._peerNameSet;return r||(r=new Set((this.extension.peerDependencies||[]).map(([a])=>a)),this._peerNameSet=r),r}getExtensionDependency(){if(!this._dependency){const r=this.state;(function(a){return a.id>=me})(r)||it(317,this.extension.name),this._dependency={config:r.config,init:r.initResult,output:r.output}}return this._dependency}}const ta={tag:v.HISTORY_MERGE_TAG};function Gn(){const t=v.$getRoot();t.isEmpty()&&t.append(v.$createParagraphNode())}const Kn=v.defineExtension({config:v.safeCast({setOptions:ta,updateOptions:ta}),init:({$initialEditorState:t=Gn})=>({$initialEditorState:t,initialized:!1}),afterRegistration(t,{updateOptions:r,setOptions:a},o){const i=o.getInitResult();if(!i.initialized){i.initialized=!0;const{$initialEditorState:s}=i;if(v.$isEditorState(s))t.setEditorState(s,a);else if(typeof s=="function")t.update(()=>{s(t)},r);else if(s&&(typeof s=="string"||typeof s=="object")){const c=t.parseEditorState(s);t.setEditorState(c,a)}}return()=>{}},name:"@lexical/extension/InitialState",nodes:[v.RootNode,v.TextNode,v.LineBreakNode,v.TabNode,v.ParagraphNode]}),ea=Symbol.for("@lexical/extension/LexicalBuilder");function ra(){}function Un(t){throw t}function Ve(t){return Array.isArray(t)?t:[t]}const wr="0.43.0+prod.esm";class xe{constructor(r){Ot(this,"roots");Ot(this,"extensionNameMap");Ot(this,"outgoingConfigEdges");Ot(this,"incomingEdges");Ot(this,"conflicts");Ot(this,"_sortedExtensionReps");Ot(this,"PACKAGE_VERSION");this.outgoingConfigEdges=new Map,this.incomingEdges=new Map,this.extensionNameMap=new Map,this.conflicts=new Map,this.PACKAGE_VERSION=wr,this.roots=r;for(const a of r)this.addExtension(a)}static fromExtensions(r){const a=[Ve(Kn)];for(const o of r)a.push(Ve(o));return new xe(a)}static maybeFromEditor(r){const a=r[ea];return a&&(a.PACKAGE_VERSION!==wr&&it(292,a.PACKAGE_VERSION,wr),a instanceof xe||it(293)),a}static fromEditor(r){const a=xe.maybeFromEditor(r);return a===void 0&&it(294),a}constructEditor(){const{$initialEditorState:r,onError:a,...o}=this.buildCreateEditorArgs(),i=Object.assign(v.createEditor({...o,...a?{onError:s=>{a(s,i)}}:{}}),{[ea]:this});for(const s of this.sortedExtensionReps())s.build(i);return i}buildEditor(){let r=ra;function a(){try{r()}finally{r=ra}}const o=Object.assign(this.constructEditor(),{dispose:a,[Symbol.dispose]:a});return r=v.mergeRegister(this.registerEditor(o),()=>o.setRootElement(null)),o}hasExtensionByName(r){return this.extensionNameMap.has(r)}getExtensionRep(r){const a=this.extensionNameMap.get(r.name);if(a)return a.extension!==r&&it(295,r.name),a}addEdge(r,a,o){const i=this.outgoingConfigEdges.get(r);i?i.set(a,o):this.outgoingConfigEdges.set(r,new Map([[a,o]]));const s=this.incomingEdges.get(a);s?s.add(r):this.incomingEdges.set(a,new Set([r]))}addExtension(r){this._sortedExtensionReps!==void 0&&it(296);const a=Ve(r),[o]=a;typeof o.name!="string"&&it(297,typeof o.name);let i=this.extensionNameMap.get(o.name);if(i!==void 0&&i.extension!==o&&it(298,o.name),!i){i=new Fn(this,o),this.extensionNameMap.set(o.name,i);const s=this.conflicts.get(o.name);typeof s=="string"&&it(299,o.name,s);for(const c of o.conflictsWith||[])this.extensionNameMap.has(c)&&it(299,o.name,c),this.conflicts.set(c,o.name);for(const c of o.dependencies||[]){const d=Ve(c);this.addEdge(o.name,d[0].name,d.slice(1)),this.addExtension(d)}for(const[c,d]of o.peerDependencies||[])this.addEdge(o.name,c,d?[d]:[])}}sortedExtensionReps(){if(this._sortedExtensionReps)return this._sortedExtensionReps;const r=[],a=(o,i)=>{let s=o.state;if(Ia(s))return;const c=o.extension.name;var d;dr(s)||it(300,c,i||"[unknown]"),dr(d=s)||it(304,String(d.id),String(Er)),s=Object.assign(d,{id:xr}),o.state=s;const u=this.outgoingConfigEdges.get(c);if(u)for(const w of u.keys()){const p=this.extensionNameMap.get(w);p&&a(p,c)}s=Ln(s),o.state=s,r.push(o)};for(const o of this.extensionNameMap.values())dr(o.state)&&a(o);for(const o of r)for(const[i,s]of this.outgoingConfigEdges.get(o.extension.name)||[])if(s.length>0){const c=this.extensionNameMap.get(i);if(c)for(const d of s)c.configs.add(d)}for(const[o,...i]of this.roots)if(i.length>0){const s=this.extensionNameMap.get(o.name);s===void 0&&it(301,o.name);for(const c of i)s.configs.add(c)}return this._sortedExtensionReps=r,this._sortedExtensionReps}registerEditor(r){const a=this.sortedExtensionReps(),o=new AbortController,i=[()=>o.abort()],s=o.signal;for(const c of a){const d=c.register(r,s);d&&i.push(d)}for(const c of a){const d=c.afterRegistration(r);d&&i.push(d)}return v.mergeRegister(...i)}buildCreateEditorArgs(){const r={},a=new Set,o=new Map,i=new Map,s={},c={},d=this.sortedExtensionReps();for(const p of d){const{extension:g}=p;if(g.onError!==void 0&&(r.onError=g.onError),g.disableEvents!==void 0&&(r.disableEvents=g.disableEvents),g.parentEditor!==void 0&&(r.parentEditor=g.parentEditor),g.editable!==void 0&&(r.editable=g.editable),g.namespace!==void 0&&(r.namespace=g.namespace),g.$initialEditorState!==void 0&&(r.$initialEditorState=g.$initialEditorState),g.nodes)for(const f of Bn(g)){if(typeof f!="function"){const h=o.get(f.replace);h&&it(302,g.name,f.replace.name,h.extension.name),o.set(f.replace,p)}a.add(f)}if(g.html){if(g.html.export)for(const[f,h]of g.html.export.entries())i.set(f,h);g.html.import&&Object.assign(s,g.html.import)}g.theme&&Oa(c,g.theme)}Object.keys(c).length>0&&(r.theme=c),a.size&&(r.nodes=[...a]);const u=Object.keys(s).length>0,w=i.size>0;(u||w)&&(r.html={},u&&(r.html.import=s),w&&(r.html.export=i));for(const p of d)p.init(r);return r.onError||(r.onError=Un),r}}const qn=new Set,aa=v.defineExtension({build(t,r,a){const o=a.getDependency(br).output,i=De({watchedNodeKeys:new Map}),s=Da(()=>{},()=>Jt(()=>{const c=s.peek(),{watchedNodeKeys:d}=i.value;let u,w=!1;o.value.read(()=>{if(v.$getSelection())for(const[p,g]of d.entries()){if(g.size===0){d.delete(p);continue}const f=v.$getNodeByKey(p),h=f&&f.isSelected()||!1;w=w||h!==(!!c&&c.has(p)),h&&(u=u||new Set,u.add(p))}}),!w&&u&&c&&u.size===c.size||(s.value=u)}));return{watchNodeKey:function(c){const d=An(()=>(s.value||qn).has(c)),{watchedNodeKeys:u}=i.peek();let w=u.get(c);const p=w!==void 0;return w=w||new Set,w.add(d),p||(u.set(c,w),i.value={watchedNodeKeys:u}),d}}},dependencies:[br],name:"@lexical/extension/NodeSelection"}),Hn=v.createCommand("INSERT_HORIZONTAL_RULE_COMMAND");class ke extends v.DecoratorNode{static getType(){return"horizontalrule"}static clone(r){return new ke(r.__key)}static importJSON(r){return Sr().updateFromJSON(r)}static importDOM(){return{hr:()=>({conversion:Yn,priority:0})}}exportDOM(){return{element:document.createElement("hr")}}createDOM(r){const a=document.createElement("hr");return v.addClassNamesToElement(a,r.theme.hr),a}getTextContent(){return` -`}isInline(){return!1}updateDOM(){return!1}}function Yn(){return{node:Sr()}}function Sr(){return v.$create(ke)}function Xn(t){return t instanceof ke}v.defineExtension({dependencies:[br,aa],name:"@lexical/extension/HorizontalRule",nodes:()=>[ke],register(t,r,a){const{watchNodeKey:o}=a.getDependency(aa).output,i=De({nodeSelections:new Map}),s=t._config.theme.hrSelected??"selected";return v.mergeRegister(t.registerCommand(Hn,c=>{const d=v.$getSelection();if(!v.$isRangeSelection(d))return!1;if(d.focus.getNode()!==null){const u=Sr();Mn(u)}return!0},v.COMMAND_PRIORITY_EDITOR),t.registerCommand(v.CLICK_COMMAND,c=>{if(v.isDOMNode(c.target)){const d=v.$getNodeFromDOMNode(c.target);if(Xn(d))return function(u,w=!1){const p=v.$getSelection(),g=u.isSelected(),f=u.getKey();let h;w&&v.$isNodeSelection(p)?h=p:(h=v.$createNodeSelection(),v.$setSelection(h)),g?h.delete(f):h.add(f)}(d,c.shiftKey),!0}return!1},v.COMMAND_PRIORITY_LOW),t.registerMutationListener(ke,(c,d)=>{zn(()=>{let u=!1;const{nodeSelections:w}=i.peek();for(const[p,g]of c.entries())if(g==="destroyed")w.delete(p),u=!0;else{const f=w.get(p),h=t.getElementByKey(p);f?f.domNode.value=h:(u=!0,w.set(p,{domNode:De(h),selectedSignal:o(p)}))}u&&(i.value={nodeSelections:w})})}),Jt(()=>{const c=[];for(const{domNode:d,selectedSignal:u}of i.value.nodeSelections.values())c.push(Jt(()=>{const w=d.value;w&&(u.value?v.addClassNamesToElement(w,s):v.removeClassNamesFromElement(w,s))}));return v.mergeRegister(...c)}))}});v.defineExtension({build:(t,r)=>ye({inheritEditableFromParent:r.inheritEditableFromParent}),config:v.safeCast({$getParentEditor:function(){const t=v.$getEditor();return xe.fromEditor(t),t},inheritEditableFromParent:!1}),init:(t,r,a)=>{const o=r.$getParentEditor();t.parentEditor=o,t.theme=t.theme||o._config.theme},name:"@lexical/extension/NestedEditor",register:(t,r,a)=>Jt(()=>{const o=t._parentEditor;if(o&&a.getOutput().inheritEditableFromParent.value)return t.setEditable(o.isEditable()),o.registerEditableListener(t.setEditable.bind(t))})});v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({disabled:!1,onReposition:void 0}),name:"@lexical/utils/SelectionAlwaysOnDisplay",register:(t,r,a)=>{const o=a.getOutput();return Jt(()=>{if(!o.disabled.value)return Sn(t,o.onReposition.value)})}});function Aa(t){return t.canBeEmpty()}function Zn(t,r,a=Aa){return v.mergeRegister(t.registerCommand(v.KEY_TAB_COMMAND,o=>{const i=v.$getSelection();if(!v.$isRangeSelection(i))return!1;o.preventDefault();const s=function(c){if(c.getNodes().filter(f=>v.$isBlockElementNode(f)&&f.canIndent()).length>0)return!0;const d=c.anchor,u=c.focus,w=u.isBefore(d)?u:d,p=w.getNode(),g=Tn(p);if(g.canIndent()){const f=g.getKey();let h=v.$createRangeSelection();if(h.anchor.set(f,0,"element"),h.focus.set(f,0,"element"),h=v.$normalizeSelection__EXPERIMENTAL(h),h.anchor.is(w))return!0}return!1}(i)?o.shiftKey?v.OUTDENT_CONTENT_COMMAND:v.INDENT_CONTENT_COMMAND:v.INSERT_TAB_COMMAND;return t.dispatchCommand(s,void 0)},v.COMMAND_PRIORITY_EDITOR),t.registerCommand(v.INDENT_CONTENT_COMMAND,()=>{const o=typeof r=="number"?r:r?r.peek():null,i=v.$getSelection();if(!v.$isRangeSelection(i))return!1;const s=typeof a=="function"?a:a.peek();return Dn(c=>{if(s(c)){const d=c.getIndent()+1;(!o||dye(r),config:v.safeCast({$canIndent:Aa,disabled:!1,maxIndent:null}),name:"@lexical/extension/TabIndentation",register(t,r,a){const{disabled:o,maxIndent:i,$canIndent:s}=a.getOutput();return Jt(()=>{if(!o.value)return Zn(t,i,s)})}});const Wn=v.defineExtension({name:"@lexical/react/ReactProvider"});function Jn(){return v.$getRoot().getTextContent()}function Qn(t,r=!0){if(t)return!1;let a=Jn();return r&&(a=a.trim()),a===""}function ti(t){if(!Qn(t,!1))return!1;const r=v.$getRoot().getChildren(),a=r.length;if(a>1)return!1;for(let o=0;oti(t)}function Ba(t){const r=window.location.origin,a=o=>{if(o.origin!==r)return;const i=t.getRootElement();if(document.activeElement!==i)return;const s=o.data;if(typeof s=="string"){let c;try{c=JSON.parse(s)}catch{return}if(c&&c.protocol==="nuanria_messaging"&&c.type==="request"){const d=c.payload;if(d&&d.functionId==="makeChanges"){const u=d.args;if(u){const[w,p,g,f,h]=u;t.update(()=>{const m=v.$getSelection();if(v.$isRangeSelection(m)){const k=m.anchor;let b=k.getNode(),C=0,y=0;if(v.$isTextNode(b)&&w>=0&&p>=0&&(C=w,y=w+p,m.setTextNodeRange(b,C,b,y)),C===y&&g===""||(m.insertRawText(g),b=k.getNode()),v.$isTextNode(b)){C=f,y=f+h;const _=b.getTextContentSize();C=C>_?_:C,y=y>_?_:y,m.setTextNodeRange(b,C,b,y)}o.stopImmediatePropagation()}})}}}}};return window.addEventListener("message",a,!0),()=>{window.removeEventListener("message",a,!0)}}v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({disabled:typeof window>"u"}),name:"@lexical/dragon",register:(t,r,a)=>Jt(()=>a.getOutput().disabled.value?void 0:Ba(t))});function ei(t,...r){const a=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const i of r)o.append("v",i);throw a.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${a.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const Tr=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function ri({editor:t,ErrorBoundary:r}){return function(a,o){const[i,s]=l.useState(()=>a.getDecorators());return Tr(()=>a.registerDecoratorListener(c=>{Ur.flushSync(()=>{s(c)})}),[a]),l.useEffect(()=>{s(a.getDecorators())},[a]),l.useMemo(()=>{const c=[],d=Object.keys(i);for(let u=0;ua._onError(f),children:e.jsx(l.Suspense,{fallback:null,children:i[w]})}),g=a.getElementByKey(w);g!==null&&c.push(Ur.createPortal(p,g,w))}return c},[o,i,a])}(t,r)}function ai({editor:t,ErrorBoundary:r}){return function(a){const o=xe.maybeFromEditor(a);if(o&&o.hasExtensionByName(Wn.name)){for(const i of["@lexical/plain-text","@lexical/rich-text"])o.hasExtensionByName(i)&&ei(320,i);return!0}return!1}(t)?null:e.jsx(ri,{editor:t,ErrorBoundary:r})}function oa(t){return t.getEditorState().read($a(t.isComposing()))}function oi({contentEditable:t,placeholder:r=null,ErrorBoundary:a}){const[o]=Qt();return function(i){Tr(()=>v.mergeRegister(fr.registerRichText(i),Ba(i)),[i])}(o),e.jsxs(e.Fragment,{children:[t,e.jsx(ni,{content:r}),e.jsx(ai,{editor:o,ErrorBoundary:a})]})}function ni({content:t}){const[r]=Qt(),a=function(i){const[s,c]=l.useState(()=>oa(i));return Tr(()=>{function d(){const u=oa(i);c(u)}return d(),v.mergeRegister(i.registerUpdateListener(()=>{d()}),i.registerEditableListener(()=>{d()}))},[i]),s}(r),o=kn();return a?typeof t=="function"?t(o):t:null}function ii({defaultSelection:t}){const[r]=Qt();return l.useEffect(()=>{r.focus(()=>{const a=document.activeElement,o=r.getRootElement();o===null||a!==null&&o.contains(a)||o.focus({preventScroll:!0})},{defaultSelection:t})},[t,r]),null}const si=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function ci({onClear:t}){const[r]=Qt();return si(()=>Ma(r,t),[r,t]),null}const Pa=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function li({editor:t,ariaActiveDescendant:r,ariaAutoComplete:a,ariaControls:o,ariaDescribedBy:i,ariaErrorMessage:s,ariaExpanded:c,ariaInvalid:d,ariaLabel:u,ariaLabelledBy:w,ariaMultiline:p,ariaOwns:g,ariaRequired:f,autoCapitalize:h,className:m,id:k,role:b="textbox",spellCheck:C=!0,style:y,tabIndex:_,"data-testid":B,...F},E){const[P,A]=l.useState(t.isEditable()),j=l.useCallback(z=>{z&&z.ownerDocument&&z.ownerDocument.defaultView?t.setRootElement(z):t.setRootElement(null)},[t]),V=l.useMemo(()=>function(...z){return N=>{for(const H of z)typeof H=="function"?H(N):H!=null&&(H.current=N)}}(E,j),[j,E]);return Pa(()=>(A(t.isEditable()),t.registerEditableListener(z=>{A(z)})),[t]),e.jsx("div",{"aria-activedescendant":P?r:void 0,"aria-autocomplete":P?a:"none","aria-controls":P?o:void 0,"aria-describedby":i,...s!=null?{"aria-errormessage":s}:{},"aria-expanded":P&&b==="combobox"?!!c:void 0,...d!=null?{"aria-invalid":d}:{},"aria-label":u,"aria-labelledby":w,"aria-multiline":p,"aria-owns":P?g:void 0,"aria-readonly":!P||void 0,"aria-required":f,autoCapitalize:h,className:m,contentEditable:P,"data-testid":B,id:k,ref:V,role:b,spellCheck:C,style:y,tabIndex:_,...F})}const di=l.forwardRef(li);function na(t){return t.getEditorState().read($a(t.isComposing()))}const wi=l.forwardRef(ui);function ui(t,r){const{placeholder:a,...o}=t,[i]=Qt();return e.jsxs(e.Fragment,{children:[e.jsx(di,{editor:i,...o,ref:r}),a!=null&&e.jsx(pi,{editor:i,content:a})]})}function pi({content:t,editor:r}){const a=function(c){const[d,u]=l.useState(()=>na(c));return Pa(()=>{function w(){const p=na(c);u(p)}return w(),v.mergeRegister(c.registerUpdateListener(()=>{w()}),c.registerEditableListener(()=>{w()}))},[c]),d}(r),[o,i]=l.useState(r.isEditable());if(l.useLayoutEffect(()=>(i(r.isEditable()),r.registerEditableListener(c=>{i(c)})),[r]),!a)return null;let s=null;return typeof t=="function"?s=t(o):t!==null&&(s=t),s===null?null:e.jsx("div",{"aria-hidden":!0,children:s})}function gi({placeholder:t,className:r,placeholderClassName:a}){return e.jsx(wi,{className:r??"ContentEditable__root tw:relative tw:block tw:min-h-11 tw:overflow-auto tw:px-3 tw:py-3 tw:text-sm tw:outline-hidden","aria-placeholder":t,placeholder:e.jsx("div",{className:a??"tw:pointer-events-none tw:absolute tw:top-0 tw:select-none tw:overflow-hidden tw:text-ellipsis tw:px-3 tw:py-3 tw:text-sm tw:text-muted-foreground",children:t})})}const La=l.createContext(void 0);function hi({activeEditor:t,$updateToolbar:r,blockType:a,setBlockType:o,showModal:i,children:s}){const c=l.useMemo(()=>({activeEditor:t,$updateToolbar:r,blockType:a,setBlockType:o,showModal:i}),[t,r,a,o,i]);return e.jsx(La.Provider,{value:c,children:s})}function Va(){const t=l.useContext(La);if(!t)throw new Error("useToolbarContext must be used within a ToolbarContext provider");return t}function fi(){const[t,r]=l.useState(void 0),a=l.useCallback(()=>{r(void 0)},[]),o=l.useMemo(()=>{if(t===void 0)return;const{title:s,content:c}=t;return e.jsx(n.Dialog,{open:!0,onOpenChange:a,children:e.jsxs(n.DialogContent,{children:[e.jsx(n.DialogHeader,{children:e.jsx(n.DialogTitle,{children:s})}),c]})})},[t,a]),i=l.useCallback((s,c,d=!1)=>{r({closeOnClickOutside:d,content:c(a),title:s})},[a]);return[o,i]}function mi({children:t}){const[r]=Qt(),[a,o]=l.useState(r),[i,s]=l.useState("paragraph"),[c,d]=fi(),u=()=>{};return l.useEffect(()=>a.registerCommand(v.SELECTION_CHANGE_COMMAND,(w,p)=>(o(p),!1),v.COMMAND_PRIORITY_CRITICAL),[a]),e.jsxs(hi,{activeEditor:a,$updateToolbar:u,blockType:i,setBlockType:s,showModal:d,children:[c,t({blockType:i})]})}function vi(t){const[r]=Qt(),{activeEditor:a}=Va();l.useEffect(()=>a.registerCommand(v.SELECTION_CHANGE_COMMAND,()=>{const o=v.$getSelection();return o&&t(o),!1},v.COMMAND_PRIORITY_CRITICAL),[r,t]),l.useEffect(()=>{a.getEditorState().read(()=>{const o=v.$getSelection();o&&t(o)})},[a,t])}const bi=er.cva("pr-twp tw:group/toggle tw:inline-flex tw:items-center tw:justify-center tw:gap-1 tw:rounded-lg tw:text-sm tw:font-medium tw:whitespace-nowrap tw:transition-all tw:outline-none tw:hover:bg-muted tw:hover:text-foreground tw:focus-visible:border-ring tw:focus-visible:ring-[3px] tw:focus-visible:ring-ring/50 tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-destructive/20 tw:aria-pressed:bg-muted tw:data-[state=on]:bg-muted tw:dark:aria-invalid:ring-destructive/40 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",{variants:{variant:{default:"tw:bg-transparent",outline:"tw:border tw:border-input tw:bg-transparent tw:hover:bg-muted"},size:{default:"tw:h-8 tw:min-w-8 tw:px-2.5 tw:has-data-[icon=inline-end]:pe-2 tw:has-data-[icon=inline-start]:ps-2",sm:"tw:h-7 tw:min-w-7 tw:rounded-[min(var(--tw-radius-md),12px)] tw:px-2.5 tw:text-[0.8rem] tw:has-data-[icon=inline-end]:pe-1.5 tw:has-data-[icon=inline-start]:ps-1.5 tw:[&_svg:not([class*=size-])]:size-3.5",lg:"tw:h-9 tw:min-w-9 tw:px-2.5 tw:has-data-[icon=inline-end]:pe-2 tw:has-data-[icon=inline-start]:ps-2"}},defaultVariants:{variant:"default",size:"default"}}),Fa=l.createContext({size:"default",variant:"default",spacing:0,orientation:"horizontal"});function Mr({className:t,variant:r,size:a,spacing:o=0,orientation:i="horizontal",children:s,...c}){const d=n.readDirection();return e.jsx(D.ToggleGroup.Root,{"data-slot":"toggle-group","data-variant":r,"data-size":a,"data-spacing":o,"data-orientation":i,style:{"--gap":o},className:n.cn("pr-twp tw:group/toggle-group tw:flex tw:w-fit tw:flex-row tw:items-center tw:gap-[--spacing(var(--gap))] tw:rounded-lg tw:data-[size=sm]:rounded-[min(var(--tw-radius-md),10px)] tw:data-vertical:flex-col tw:data-vertical:items-stretch",t),dir:d,...c,children:e.jsx(Fa.Provider,{value:l.useMemo(()=>({variant:r,size:a,spacing:o,orientation:i}),[r,a,o,i]),children:s})})}function Me({className:t,children:r,variant:a="default",size:o="default",...i}){const s=l.useContext(Fa);return e.jsx(D.ToggleGroup.Item,{"data-slot":"toggle-group-item","data-variant":s.variant||a,"data-size":s.size||o,"data-spacing":s.spacing,className:n.cn("tw:shrink-0 tw:group-data-[spacing=0]/toggle-group:rounded-none tw:group-data-[spacing=0]/toggle-group:px-2 tw:focus:z-10 tw:focus-visible:z-10 tw:group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pe-1.5 tw:group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:ps-1.5 tw:group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-s-lg tw:group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg tw:group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-e-lg tw:group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg tw:group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-s-0 tw:group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 tw:group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-s tw:group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",bi({variant:s.variant||a,size:s.size||o}),t),...i,children:r})}const ia=[{format:"bold",icon:R.BoldIcon,label:"Bold"},{format:"italic",icon:R.ItalicIcon,label:"Italic"}];function xi(){const{activeEditor:t}=Va(),[r,a]=l.useState([]),o=l.useCallback(i=>{if(v.$isRangeSelection(i)||Yo.$isTableSelection(i)){const s=[];ia.forEach(({format:c})=>{i.hasFormat(c)&&s.push(c)}),a(c=>c.length!==s.length||!s.every(d=>c.includes(d))?s:c)}},[]);return vi(o),e.jsx(Mr,{type:"multiple",value:r,onValueChange:a,variant:"outline",size:"sm",children:ia.map(({format:i,icon:s,label:c})=>e.jsx(Me,{value:i,"aria-label":c,onClick:()=>{t.dispatchCommand(v.FORMAT_TEXT_COMMAND,i)},children:e.jsx(s,{className:"tw:h-4 tw:w-4"})},i))})}function ki({onClear:t}){const[r]=Qt();l.useEffect(()=>{t&&t(()=>{r.dispatchCommand(v.CLEAR_EDITOR_COMMAND,void 0)})},[r,t])}function yi({placeholder:t="Start typing ...",autoFocus:r=!1,onClear:a}){const[,o]=l.useState(void 0),i=s=>{s!==void 0&&o(s)};return e.jsxs("div",{className:"tw:relative",children:[e.jsx(mi,{children:()=>e.jsx("div",{className:"tw:sticky tw:top-0 tw:z-10 tw:flex tw:gap-2 tw:overflow-auto tw:border-b tw:p-1",children:e.jsx(xi,{})})}),e.jsxs("div",{className:"tw:relative",children:[e.jsx(oi,{contentEditable:e.jsx("div",{ref:i,children:e.jsx(gi,{placeholder:t})}),ErrorBoundary:vn}),r&&e.jsx(ii,{defaultSelection:"rootEnd"}),e.jsx(ki,{onClear:a}),e.jsx(ci,{})]})]})}const _i={namespace:"commentEditor",theme:jr,nodes:Cr,onError:t=>{console.error(t)}};function We({editorState:t,editorSerializedState:r,onChange:a,onSerializedChange:o,placeholder:i="Start typing…",autoFocus:s=!1,onClear:c,className:d}){return e.jsx("div",{className:n.cn("pr-twp tw:overflow-hidden tw:rounded-lg tw:border tw:bg-background tw:shadow",d),children:e.jsx(un,{initialConfig:{..._i,...t?{editorState:t}:{},...r?{editorState:JSON.stringify(r)}:{}},children:e.jsxs(n.TooltipProvider,{children:[e.jsx(yi,{placeholder:i,autoFocus:s,onClear:c}),e.jsx(gn,{ignoreSelectionChange:!0,onChange:u=>{a==null||a(u),o==null||o(u.toJSON())}})]})})})}function Ga(t){const r=t.querySelector('[contenteditable="true"]');if(!r)return!1;r.focus();const a=window.getSelection(),o=document.createRange();return o.selectNodeContents(r),o.collapse(!1),a==null||a.removeAllRanges(),a==null||a.addRange(o),!0}function Ka(t){return t?t.some(r=>r&&"text"in r&&r.text.trim().length>0?!0:!r||!("children"in r)?!1:Ka(r.children)):!1}function Kt(t){var r;return(r=t==null?void 0:t.root)!=null&&r.children?Ka(t.root.children):!1}function ji(t){if(!t||t.trim()==="")throw new Error("Input HTML is empty");const r=ha.createHeadlessEditor({namespace:"EditorUtils",theme:jr,nodes:Cr,onError:o=>{console.error(o)}});let a;if(r.update(()=>{const i=new DOMParser().parseFromString(t,"text/html"),s=fa.$generateNodesFromDOM(r,i);v.$getRoot().clear(),v.$insertNodes(s)},{discrete:!0}),r.getEditorState().read(()=>{a=r.getEditorState().toJSON()}),!a)throw new Error("Failed to convert HTML to editor state");return a}function Je(t){const r=ha.createHeadlessEditor({namespace:"EditorUtils",theme:jr,nodes:Cr,onError:i=>{console.error(i)}}),a=r.parseEditorState(JSON.stringify(t));r.setEditorState(a);let o="";return r.getEditorState().read(()=>{o=fa.$generateHtmlFromNodes(r)}),o=o.replace(/\s+style="[^"]*"/g,"").replace(/\s+class="[^"]*"/g,"").replace(/(.*?)<\/span>/g,"$1").replace(/]*>(.*?)<\/strong><\/b>/g,"$1").replace(/]*>(.*?)<\/b><\/strong>/g,"$1").replace(/]*>(.*?)<\/em><\/i>/g,"$1").replace(/]*>(.*?)<\/i><\/em>/g,"$1").replace(/]*>(.*?)<\/span><\/u>/g,"$1").replace(/]*>(.*?)<\/span><\/s>/g,"$1").replace(//gi,"
"),o}function Rr(t){return["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Home","End"].includes(t.key)?(t.stopPropagation(),!0):!1}const Dr=Object.freeze(["%cancelButton_tooltip%","%acceptButton_tooltip%"]),sa=(t,r)=>t[r]??r;function Or({onCancelClick:t,onAcceptClick:r,canAccept:a=!0,localizedStrings:o={},className:i="tw:h-6 tw:w-6",acceptLabel:s}){const c=sa(o,"%cancelButton_tooltip%"),d=s??sa(o,"%acceptButton_tooltip%");return e.jsxs(n.ButtonGroup,{children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":c,className:i,size:"icon",onClick:t,variant:"secondary",children:e.jsx(R.X,{})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:c})})]})}),e.jsx(n.ButtonGroupSeparator,{}),e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":d,className:i,size:"icon",onClick:r,disabled:!a,children:e.jsx(R.Check,{})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:d})})]})})]})}const Ci="verseText",Ni=Object.freeze(["%conflict_note_description_verseText%","%conflict_note_choose_aria_label%","%conflict_note_stale_notice%","%conflict_note_resolve_failed%","%conflict_note_choose_prompt%","%conflict_note_option_keep_current%","%conflict_note_option_use_other%","%conflict_note_option_combine%","%conflict_note_save_and_resolve%","%conflict_note_save_disabled_tooltip%","%conflict_note_save_warning%","%conflict_note_no_result%","%conflict_note_outcome_used_other%","%conflict_note_outcome_combined%","%conflict_note_summary_unresolved%","%conflict_note_summary_resolved_kept_current%","%conflict_note_summary_resolved_used_other%","%conflict_note_summary_resolved_combined%"]),Ua=["tw:prose tw:max-w-none tw:break-words tw:text-sm tw:font-normal tw:text-foreground","tw:[&>blockquote]:border-s-0 tw:[&>blockquote]:p-0 tw:[&>blockquote]:ps-0 tw:[&>blockquote]:font-normal tw:[&>blockquote]:not-italic tw:[&>blockquote]:text-foreground","tw:prose-quoteless"].join(" ");function qa(t){return(t==null?void 0:t.conflictType)===Ci}function Ha(t){return t==="replaced"?"reject":t==="merged"?"merged":"accept"}function Ue(t,r){return t===""?r["%comment_assign_unassigned%"]??"Unassigned":t==="Team"?r["%comment_assign_team%"]??"Team":t}function zr(t){const r=n.isMacOs();return t.key==="Enter"&&(r&&t.metaKey||!r&&t.ctrlKey)}const Ei={root:{children:[{children:[{detail:0,format:0,mode:"normal",style:"",text:"",type:"text",version:1}],direction:"ltr",format:"",indent:0,type:"paragraph",version:1,textFormat:0,textStyle:""}],direction:"ltr",format:"",indent:0,type:"root",version:1}};function ur(t,r){return t===""?r["%commentEditor_unassigned%"]??"Unassigned":t==="Team"?r["%commentEditor_team%"]??"Team":t}function Si({assignableUsers:t,onSave:r,onClose:a,localizedStrings:o,initialAssignedUser:i}){const[s,c]=l.useState(Ei),[d,u]=l.useState(i),[w,p]=l.useState(!1),g=l.useRef(void 0),f=l.useRef(null);l.useEffect(()=>{let b=!0;const C=f.current;if(!C)return;const y=setTimeout(()=>{b&&Ga(C)},300);return()=>{b=!1,clearTimeout(y)}},[]);const h=l.useCallback(()=>{if(!Kt(s))return;const b=Je(s);r(b,d)},[s,r,d]),m=o["%commentEditor_placeholder%"]??"Type your comment here...",k=o["%commentEditor_assignTo_label%"]??"Assign to";return e.jsxs("div",{className:"pr-twp tw:grid tw:gap-3",children:[e.jsxs("div",{className:"tw:flex tw:items-center tw:justify-between",children:[e.jsx("span",{className:"tw:text-sm tw:font-medium",children:k}),e.jsx(Or,{onCancelClick:a,onAcceptClick:h,canAccept:Kt(s),localizedStrings:o,acceptLabel:o["%commentEditor_saveButton_tooltip%"]})]}),e.jsx("div",{className:"tw:flex tw:items-center tw:gap-2",children:e.jsxs(n.Popover,{open:w,onOpenChange:p,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"outline",className:"tw:flex tw:w-full tw:items-center tw:justify-start tw:gap-2",disabled:t.length===0,children:[e.jsx(R.AtSign,{className:"tw:h-4 tw:w-4"}),e.jsx("span",{children:ur(d!==void 0?d:"",o)})]})}),e.jsx(n.PopoverContent,{className:"tw:w-auto tw:p-0",align:"start",onKeyDown:b=>{b.key==="Escape"&&(b.stopPropagation(),p(!1))},children:e.jsx(n.Command,{children:e.jsx(n.CommandList,{children:t.map(b=>e.jsx(n.CommandItem,{onSelect:()=>{u(b||void 0),p(!1)},className:"tw:flex tw:items-center",children:e.jsx("span",{children:ur(b,o)})},b||"unassigned"))})})})]})}),e.jsx("div",{ref:f,role:"textbox",tabIndex:-1,className:"tw:outline-hidden",onKeyDownCapture:b=>{b.key==="Escape"?(b.preventDefault(),b.stopPropagation(),a()):zr(b)&&(b.preventDefault(),b.stopPropagation(),Kt(s)&&h())},onKeyDown:b=>{Rr(b),(b.key==="Enter"||b.key===" ")&&b.stopPropagation()},children:e.jsx(We,{editorSerializedState:s,onSerializedChange:b=>c(b),placeholder:m,onClear:b=>{g.current=b}})})]})}const Ti=Object.freeze(["%commentEditor_placeholder%","%commentEditor_assignTo_label%","%commentEditor_saveButton_tooltip%","%commentEditor_unassigned%","%commentEditor_team%",...Dr]),Mi=Object.freeze(["%comment_assign_team%","%comment_assign_unassigned%","%comment_assigned_to%","%comment_assigning_to%","%comment_dateAtTime%","%comment_date_today%","%comment_date_yesterday%","%comment_deleteComment%","%comment_editComment%","%comment_replyOrAssign%","%comment_reopenResolved%","%comment_status_resolved%","%comment_status_todo%","%comment_thread_multiple_replies%","%comment_thread_single_reply%","%comment_aria_assign_user%","%comment_aria_submit_comment%","%comment_aria_mark_as_read%","%comment_aria_mark_as_unread%","%comment_aria_resolve_thread%"]),Ya="comment-list";function Ri(t){return t}function Xa({className:t,size:r="default",...a}){return e.jsx("div",{"data-slot":"card","data-size":r,className:n.cn("pr-twp tw:group/card tw:flex tw:flex-col tw:gap-4 tw:overflow-hidden tw:rounded-xl tw:bg-card tw:py-4 tw:text-sm tw:text-card-foreground tw:ring-1 tw:ring-foreground/10 tw:has-data-[slot=card-footer]:pb-0 tw:has-[>img:first-child]:pt-0 tw:data-[size=sm]:gap-3 tw:data-[size=sm]:py-3 tw:data-[size=sm]:has-data-[slot=card-footer]:pb-0 tw:*:[img:first-child]:rounded-t-xl tw:*:[img:last-child]:rounded-b-xl",t),...a})}function Di({className:t,...r}){return e.jsx("div",{"data-slot":"card-header",className:n.cn("pr-twp tw:group/card-header tw:@container/card-header tw:grid tw:auto-rows-min tw:items-start tw:gap-1 tw:rounded-t-xl tw:px-4 tw:group-data-[size=sm]/card:px-3 tw:has-data-[slot=card-action]:grid-cols-[1fr_auto] tw:has-data-[slot=card-description]:grid-rows-[auto_auto] tw:[.border-b]:pb-4 tw:group-data-[size=sm]/card:[.border-b]:pb-3",t),...r})}function Oi({className:t,...r}){return e.jsx("div",{"data-slot":"card-title",className:n.cn("pr-twp tw:font-heading tw:text-base tw:leading-snug tw:font-medium tw:group-data-[size=sm]/card:text-sm",t),...r})}function zi({className:t,...r}){return e.jsx("div",{"data-slot":"card-description",className:n.cn("pr-twp tw:text-sm tw:text-muted-foreground",t),...r})}function Za({className:t,...r}){return e.jsx("div",{"data-slot":"card-content",className:n.cn("pr-twp tw:px-4 tw:group-data-[size=sm]/card:px-3",t),...r})}function Ii({className:t,...r}){return e.jsx("div",{"data-slot":"card-footer",className:n.cn("pr-twp tw:flex tw:items-center tw:rounded-b-xl tw:border-t tw:bg-muted/50 tw:p-4 tw:group-data-[size=sm]/card:p-3",t),...r})}function Wa({className:t,size:r="default",...a}){return e.jsx(D.Avatar.Root,{"data-slot":"avatar","data-size":r,className:n.cn("pr-twp tw:group/avatar tw:relative tw:flex tw:size-8 tw:shrink-0 tw:rounded-full tw:select-none tw:after:absolute tw:after:inset-0 tw:after:rounded-full tw:after:border tw:after:border-border tw:after:mix-blend-darken tw:data-[size=lg]:size-10 tw:data-[size=sm]:size-6 tw:dark:after:mix-blend-lighten",t),...a})}function Ai({className:t,...r}){return e.jsx(D.Avatar.Image,{"data-slot":"avatar-image",className:n.cn("pr-twp tw:aspect-square tw:size-full tw:rounded-full tw:object-cover",t),...r})}function Ja({className:t,...r}){return e.jsx(D.Avatar.Fallback,{"data-slot":"avatar-fallback",className:n.cn("pr-twp tw:flex tw:size-full tw:items-center tw:justify-center tw:rounded-full tw:bg-muted tw:text-sm tw:text-muted-foreground tw:group-data-[size=sm]/avatar:text-xs",t),...r})}function ca({comment:t,isReply:r=!1,localizedStrings:a,isThreadExpanded:o=!1,handleUpdateComment:i,handleDeleteComment:s,onEditingChange:c,canEditOrDelete:d=!1}){const[u,w]=l.useState(!1),[p,g]=l.useState(),f=l.useRef(null);l.useEffect(()=>{if(!u)return;let E=!0;const P=f.current;if(!P)return;const A=setTimeout(()=>{E&&Ga(P)},300);return()=>{E=!1,clearTimeout(A)}},[u]);const h=l.useCallback(E=>{E&&E.stopPropagation(),w(!1),g(void 0),c==null||c(!1)},[c]),m=l.useCallback(async E=>{if(E&&E.stopPropagation(),!p||!i)return;await i(t.id,Je(p))&&(w(!1),g(void 0),c==null||c(!1))},[p,i,t.id,c]),k=l.useMemo(()=>{const E=new Date(t.date),P=M.formatRelativeDate(E,a["%comment_date_today%"],a["%comment_date_yesterday%"]),A=E.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"});return M.formatReplacementString(a["%comment_dateAtTime%"],{date:P,time:A})},[t.date,a]),b=l.useMemo(()=>t.user,[t.user]),C=l.useMemo(()=>t.user.split(" ").map(E=>E[0]).join("").toUpperCase().slice(0,2),[t.user]),y=l.useMemo(()=>M.sanitizeHtml(t.contents),[t.contents]),_=l.useMemo(()=>t.contents.replace(/<[^>]*>/g,"").trim().length>0,[t.contents]),B=!!t.conflictResolutionAction&&!_,F=l.useMemo(()=>{if(o&&d)return e.jsxs(e.Fragment,{children:[e.jsxs(n.DropdownMenuItem,{onClick:E=>{E.stopPropagation(),w(!0),g(ji(t.contents)),c==null||c(!0)},children:[e.jsx(R.Pencil,{className:"tw:me-2 tw:h-4 tw:w-4"}),a["%comment_editComment%"]]}),e.jsxs(n.DropdownMenuItem,{onClick:async E=>{E.stopPropagation(),s&&await s(t.id)},children:[e.jsx(R.Trash2,{className:"tw:me-2 tw:h-4 tw:w-4"}),a["%comment_deleteComment%"]]})]})},[d,o,a,t.contents,t.id,s,c]);return e.jsxs("div",{className:n.cn("tw:flex tw:w-full tw:flex-row tw:items-baseline tw:gap-3 tw:space-y-3",{"tw:text-sm":r}),children:[e.jsx(Wa,{className:"tw:h-8 tw:w-8",children:e.jsx(Ja,{className:"tw:text-xs tw:font-medium",children:C})}),e.jsxs("div",{className:"tw:flex tw:flex-1 tw:flex-col tw:gap-2",children:[e.jsxs("div",{className:"tw:flex tw:w-full tw:flex-row tw:flex-wrap tw:items-baseline tw:gap-x-2",children:[e.jsx("p",{className:"tw:text-sm tw:font-medium",children:b}),e.jsx("p",{className:"tw:text-xs tw:font-normal tw:text-muted-foreground",children:k}),e.jsx("div",{className:"tw:flex-1"}),r&&t.assignedUser!==void 0&&e.jsxs(n.Badge,{variant:"secondary",className:"tw:text-xs tw:font-normal",children:["→ ",Ue(t.assignedUser,a)]})]}),u&&e.jsxs("div",{role:"textbox",tabIndex:-1,className:"tw:flex tw:flex-col tw:gap-2",ref:f,onKeyDownCapture:E=>{E.key==="Escape"?(E.preventDefault(),E.stopPropagation(),h()):zr(E)&&(E.preventDefault(),E.stopPropagation(),Kt(p)&&m())},onKeyDown:E=>{Rr(E),(E.key==="Enter"||E.key===" ")&&E.stopPropagation()},onClick:E=>{E.stopPropagation()},children:[e.jsx(We,{className:n.cn('tw:[&_[data-lexical-editor="true"]>blockquote]:mt-0 tw:[&_[data-lexical-editor="true"]>blockquote]:border-s-0 tw:[&_[data-lexical-editor="true"]>blockquote]:ps-0 tw:[&_[data-lexical-editor="true"]>blockquote]:font-normal tw:[&_[data-lexical-editor="true"]>blockquote]:not-italic tw:[&_[data-lexical-editor="true"]>blockquote]:text-foreground'),editorSerializedState:p,onSerializedChange:E=>g(E)}),e.jsxs("div",{className:"tw:flex tw:flex-row tw:items-start tw:justify-end tw:gap-2",children:[e.jsx(n.Button,{size:"icon",onClick:h,variant:"outline",className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",children:e.jsx(R.X,{})}),e.jsx(n.Button,{size:"icon",onClick:m,className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",disabled:!Kt(p),children:e.jsx(R.ArrowUp,{})})]})]}),!u&&e.jsxs(e.Fragment,{children:[t.status==="Resolved"&&!B&&e.jsx("div",{className:"tw:text-sm tw:italic",children:a["%comment_status_resolved%"]}),t.status==="Todo"&&r&&e.jsx("div",{className:"tw:text-sm tw:italic",children:a["%comment_status_todo%"]}),B?e.jsx("div",{className:"tw:text-sm tw:italic",children:Ha(t.conflictResolutionAction)==="merged"?a["%conflict_note_outcome_combined%"]??"Combined both changes.":a["%conflict_note_outcome_used_other%"]??"Used the other change instead of the current text."}):e.jsx("div",{className:n.cn(Ua,"tw:items-start tw:gap-2",{"tw:line-clamp-3":!o}),dangerouslySetInnerHTML:{__html:y}})]})]}),F&&e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:"ghost",size:"icon",children:e.jsx(R.MoreHorizontal,{})})}),e.jsx(n.DropdownMenuContent,{align:"end",children:F})]})]})}function Qa({show:t,disabled:r=!1,onClick:a,ariaLabel:o}){if(t)return e.jsx(n.Button,{variant:"ghost",size:"icon",disabled:r,className:n.cn("tw:ms-auto","tw:text-primary tw:transition-opacity tw:duration-200 tw:hover:bg-primary/10","tw:opacity-0 tw:group-hover:opacity-100"),onClick:i=>{i.stopPropagation(),a()},"aria-label":o,children:e.jsx(R.Check,{className:"tw:h-4 tw:w-4"})})}const la={root:{children:[{children:[{detail:0,format:0,mode:"normal",style:"",text:"",type:"text",version:1}],direction:"ltr",format:"",indent:0,type:"paragraph",version:1,textFormat:0,textStyle:""}],direction:"ltr",format:"",indent:0,type:"root",version:1}};function to({classNameForVerseText:t,comments:r,localizedStrings:a,isSelected:o=!1,verseRef:i,assignedUser:s,currentUser:c,handleSelectThread:d,threadId:u,thread:w,threadStatus:p,handleAddCommentToThread:g,handleUpdateComment:f,handleDeleteComment:h,handleReadStatusChange:m,assignableUsers:k,canUserAddCommentToThread:b,canUserAssignThreadCallback:C,canUserResolveThreadCallback:y,canUserEditOrDeleteCommentCallback:_,isRead:B=!1,autoReadDelay:F=5,onVerseRefClick:E,initialAssignedUser:P,activeComments:A,rootContentSlot:j,resolveActionSlot:V,spaceRootContentFromReplies:z=!1}){const[N,H]=l.useState(la),[U,G]=l.useState(),[I,T]=l.useState(),Z=o,[W,vt]=l.useState(!1),[bt,Mt]=l.useState(!1),[K,J]=l.useState(!1),[st,ot]=l.useState(!1),[gt,qt]=l.useState(!1),[et,Rt]=l.useState(B),[yt,Bt]=l.useState(!1),Ht=l.useRef(void 0),[O,Pt]=l.useState(new Map);l.useEffect(()=>{let S=!0;return(async()=>{const mt=y?await y(u):!1;S&&qt(mt)})(),()=>{S=!1}},[u,y]),l.useEffect(()=>{let S=!0;if(!o){ot(!1),Pt(new Map);return}return(async()=>{const mt=C?await C(u):!1;S&&ot(mt)})(),()=>{S=!1}},[o,u,C]);const ft=l.useRef("idle");l.useEffect(()=>{if(!o){ft.current!=="idle"&&(G(void 0),T(void 0),ft.current="idle");return}ft.current==="idle"&&(ft.current="pending"),st?ft.current==="pending"&&P!==void 0&&P!==s&&(G(P),ft.current="auto-populated"):ft.current==="auto-populated"&&(G(void 0),ft.current="pending")},[o,P,st,s]);const xt=l.useMemo(()=>A??r.filter(S=>!S.deleted),[A,r]);l.useEffect(()=>{let S=!0;if(!o||!_){Pt(new Map);return}return(async()=>{const mt=new Map;await Promise.all(xt.map(async Xt=>{const oe=await _(Xt.id);S&&mt.set(Xt.id,oe)})),S&&Pt(mt)})(),()=>{S=!1}},[o,xt,_]);const Vt=l.useMemo(()=>xt[0],[xt]),te=l.useRef(null),Yt=l.useRef(void 0),L=l.useCallback(()=>{var S;(S=Yt.current)==null||S.call(Yt),H(la)},[]),Y=l.useCallback(()=>{const S=!et;Rt(S),Bt(!S),m==null||m(u,S)},[et,m,u]);l.useEffect(()=>{vt(!1)},[o]),l.useEffect(()=>{if(o&&!et&&!yt){const S=setTimeout(()=>{Rt(!0),m==null||m(u,!0)},F*1e3);return Ht.current=S,()=>clearTimeout(S)}Ht.current&&(clearTimeout(Ht.current),Ht.current=void 0)},[o,et,yt,F,u,m]);const rt=l.useMemo(()=>({singleReply:a["%comment_thread_single_reply%"],multipleReplies:a["%comment_thread_multiple_replies%"]}),[a]),Q=l.useMemo(()=>{if(s===void 0)return;if(s==="")return a["%comment_assign_unassigned%"]??"Unassigned";const S=Ue(s,a);return M.formatReplacementString(a["%comment_assigned_to%"],{assignedUser:S})},[s,a]),ct=l.useMemo(()=>xt.slice(1),[xt]),nt=l.useMemo(()=>ct.length??0,[ct.length]),wt=l.useMemo(()=>nt>0,[nt]),lt=l.useMemo(()=>W||nt<=2?ct:ct.slice(-2),[ct,nt,W]),ut=l.useMemo(()=>W||nt<=2?0:nt-2,[nt,W]),_t=l.useMemo(()=>nt===1?rt.singleReply:M.formatReplacementString(rt.multipleReplies,{count:nt}),[nt,rt]),jt=l.useMemo(()=>ut===1?rt.singleReply:M.formatReplacementString(rt.multipleReplies,{count:ut}),[ut,rt]);l.useEffect(()=>{!o&&bt&&wt&&Mt(!1)},[o,bt,wt]);const At=l.useCallback(async S=>{S&&S.stopPropagation();const Nt=Kt(N)?Je(N):void 0;if(U!==void 0){await g({threadId:u,contents:Nt,assignedUser:U})&&(T(U),Nt&&L());return}Nt&&await g({threadId:u,contents:Nt})&&L()},[L,N,g,U,u]),Ct=l.useCallback(async S=>{const Nt=Kt(N)?Je(N):void 0,mt=S.status?S.assignedUser:U??S.assignedUser,Xt=await g({...S,contents:Nt,assignedUser:mt});return Xt&&(mt!==void 0&&T(mt),Nt&&L()),Xt},[L,N,g,U]);if(xt.length===0)return;const ae=e.jsx(ca,{comment:Vt,localizedStrings:a,isThreadExpanded:o,threadStatus:p,handleAddCommentToThread:Ct,handleUpdateComment:f,handleDeleteComment:h,onEditingChange:Mt,canEditOrDelete:(!bt&&O.get(Vt.id))??!1,canUserResolveThread:gt});return e.jsx(Xa,{role:"option","aria-selected":o,id:u,className:n.cn("tw:group tw:w-full tw:rounded-none tw:border-none tw:p-4 tw:outline-hidden tw:transition-all tw:duration-200 tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-1 tw:focus:ring-offset-background",{"tw:cursor-pointer tw:hover:shadow-md":!o},{"tw:bg-primary-foreground":!o&&p!=="Resolved"&&et,"tw:bg-background":o&&p!=="Resolved"&&et,"tw:bg-muted":p==="Resolved","tw:bg-accent":!et&&!o&&p!=="Resolved"}),onClick:()=>{d(u)},tabIndex:-1,children:e.jsxs(Za,{className:"tw:flex tw:flex-col tw:gap-2 tw:p-0",children:[e.jsxs("div",{className:"tw:flex tw:flex-col tw:content-center tw:items-start tw:gap-4",children:[e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",children:[Q&&e.jsx(n.Badge,{className:"tw:rounded-sm tw:bg-input tw:text-sm tw:font-normal tw:text-primary tw:hover:bg-input",children:Q}),e.jsx(n.Button,{variant:"ghost",size:"icon",onClick:S=>{S.stopPropagation(),Y()},className:"tw:text-muted-foreground tw:transition tw:hover:text-foreground","aria-label":et?a["%comment_aria_mark_as_unread%"]??"Mark as unread":a["%comment_aria_mark_as_read%"]??"Mark as read",children:et?e.jsx(R.MailOpen,{}):e.jsx(R.Mail,{})}),V===void 0?e.jsx(Qa,{show:gt&&p!=="Resolved",onClick:()=>Ct({threadId:u,status:"Resolved"}),ariaLabel:a["%comment_aria_resolve_thread%"]??"Resolve thread"}):V]}),e.jsx("div",{className:"tw:flex tw:max-w-full tw:flex-wrap tw:items-baseline tw:gap-2",children:e.jsxs("p",{ref:te,className:n.cn("tw:flex-1 tw:overflow-hidden tw:text-ellipsis tw:text-sm tw:font-normal tw:text-muted-foreground",{"tw:overflow-visible tw:text-clip tw:whitespace-normal tw:break-words":Z},{"tw:whitespace-nowrap":!Z}),children:[i&&E?e.jsx(n.Button,{variant:"ghost",size:"sm",className:"tw:h-auto tw:px-1 tw:py-0 tw:text-sm tw:font-normal tw:text-muted-foreground",onClick:S=>{S.stopPropagation(),E(w)},children:i}):i,e.jsxs("span",{className:t,children:[Vt.contextBefore,e.jsx("span",{className:"tw:font-bold",children:Vt.selectedText}),Vt.contextAfter]})]})}),j??ae]}),e.jsxs(e.Fragment,{children:[wt&&!o&&e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-5",children:[e.jsx("div",{className:"tw:w-8",children:e.jsx(n.Separator,{})}),e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:_t})]}),!o&&Kt(N)&&e.jsx(We,{editorSerializedState:N,onSerializedChange:S=>H(S),placeholder:a["%comment_replyOrAssign%"]}),o&&e.jsxs(e.Fragment,{children:[z&<.length>0&&e.jsx("div",{className:"tw:h-2","data-slot":"root-content-reply-gap","aria-hidden":"true"}),ut>0&&e.jsxs("div",{className:"tw:flex tw:cursor-pointer tw:items-center tw:gap-5 tw:py-2",onClick:S=>{S.stopPropagation(),vt(!0)},role:"button",tabIndex:0,onKeyDown:S=>{(S.key==="Enter"||S.key===" ")&&(S.preventDefault(),S.stopPropagation(),vt(!0))},children:[e.jsx("div",{className:"tw:w-8",children:e.jsx(n.Separator,{})}),e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",children:[e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:jt}),W?e.jsx(R.ChevronUp,{}):e.jsx(R.ChevronDown,{})]})]}),lt.map(S=>e.jsx("div",{children:e.jsx(ca,{comment:S,localizedStrings:a,isReply:!0,isThreadExpanded:o,handleUpdateComment:f,handleDeleteComment:h,onEditingChange:Mt,canEditOrDelete:(!bt&&O.get(S.id))??!1})},S.id)),b!==!1&&(!bt||Kt(N))&&e.jsxs("div",{role:"textbox",tabIndex:-1,className:"tw:w-full tw:space-y-2",onClick:S=>S.stopPropagation(),onKeyDownCapture:S=>{zr(S)&&(S.preventDefault(),S.stopPropagation(),(Kt(N)||U!==void 0&&U!==I)&&At())},onKeyDown:S=>{Rr(S),(S.key==="Enter"||S.key===" ")&&S.stopPropagation()},children:[e.jsx(We,{editorSerializedState:N,onSerializedChange:S=>H(S),placeholder:p==="Resolved"?a["%comment_reopenResolved%"]:a["%comment_replyOrAssign%"],autoFocus:!0,onClear:S=>{Yt.current=S}}),e.jsxs("div",{className:"tw:flex tw:flex-row tw:items-center tw:justify-end tw:gap-2",children:[U!==void 0&&(Kt(N)||U!==I)&&e.jsx("span",{className:"tw:flex-1 tw:text-sm tw:text-muted-foreground",children:M.formatReplacementString(a["%comment_assigning_to%"]??"Assigning to: {assignedUser}",{assignedUser:Ue(U,a)})}),e.jsxs(n.Popover,{open:K,onOpenChange:J,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsx(n.Button,{size:"icon",variant:"outline",className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",disabled:!st||!k||k.length===0||!k.includes(c),"aria-label":a["%comment_aria_assign_user%"]??"Assign user",children:e.jsx(R.AtSign,{})})}),e.jsx(n.PopoverContent,{className:"tw:w-auto tw:p-0",align:"end",onKeyDown:S=>{S.key==="Escape"&&(S.stopPropagation(),J(!1))},children:e.jsx(n.Command,{children:e.jsx(n.CommandList,{children:k==null?void 0:k.map(S=>e.jsx(n.CommandItem,{onSelect:()=>{G(S!==s?S:void 0),ft.current="user-selected",T(void 0),J(!1)},className:"tw:flex tw:items-center",children:e.jsx("span",{children:Ue(S,a)})},S||"unassigned"))})})})]}),e.jsx(n.Button,{size:"icon",onClick:At,className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",disabled:!Kt(N)&&(U===void 0||U===I),"aria-label":a["%comment_aria_submit_comment%"]??"Submit comment",children:e.jsx(R.ArrowUp,{})})]})]})]})]})]})})}const $i=n.cn(Ua,"tw:[&>blockquote]:my-0 tw:[&_p]:my-0","tw:[&_u]:font-semibold tw:[&_u]:text-success-foreground tw:[&_u]:no-underline","tw:[&_s]:text-destructive tw:[&_s]:line-through"),Bi=t=>t.replace(/(\s+)(<\/[us]>)/g,"$2$1"),qe=t=>Bi(M.sanitizeHtml(t));function He({html:t}){return e.jsx("div",{className:$i,dangerouslySetInnerHTML:{__html:t}})}function eo({comment:t,localizedStrings:r,availableActions:a="acceptOrReject",resolvedResolution:o,onResolve:i,isResolving:s=!1}){const[c,d]=l.useState("accept"),u=l.useId(),w=l.useId(),p=a==="loading",g=a==="accept",f=a==="none",h=a==="acceptRejectOrMerge",m=g?"accept":c,k=l.useMemo(()=>qe(t.rejectedText??""),[t.rejectedText]),b=l.useMemo(()=>qe(t.acceptedText??""),[t.acceptedText]),C=l.useMemo(()=>qe(t.mergedText??""),[t.mergedText]),y=l.useMemo(()=>M.sanitizeHtml(t.contents),[t.contents]);if(!qa(t))return e.jsx(He,{html:y});const _=I=>{d(I==="reject"||I==="merge"?I:"accept")},B=r["%conflict_note_stale_notice%"]??"The verse was edited after this conflict was recorded, so 'Use the other change' is no longer available. Keep the current text to resolve.",F=h?[{value:"merge",label:r["%conflict_note_option_combine%"]??"Combine both changes",html:C}]:[],E=[{value:"accept",label:r["%conflict_note_option_keep_current%"]??"Keep the current text",html:b},{value:"reject",label:r["%conflict_note_option_use_other%"]??"Use the other change",html:k},...F],P=m==="accept",A=s||P;let j;P?j=r["%conflict_note_save_disabled_tooltip%"]??"Keeping the current text makes no change — resolve the thread with the ✓ to keep it.":s||(j=r["%conflict_note_save_warning%"]??"This can't be undone.");const V=r["%conflict_note_no_result%"]??"No result preview available.",z=e.jsx("p",{className:"tw:text-muted-foreground",children:V}),N=I=>I?e.jsx("p",{className:"tw:whitespace-pre-wrap tw:text-foreground",children:I}):z,H=()=>{const I=o??"accept";return I==="merged"?t.mergedText?e.jsx(He,{html:C}):z:N(I==="reject"?t.rejectedResultText:t.resultText)},U=I=>g&&I.value==="reject",G=I=>{const T=m===I.value,Z=`${w}-${I.value}`,W=U(I);return e.jsxs("label",{htmlFor:Z,"data-slot":"conflict-resolution-option","data-value":I.value,className:n.cn("tw:flex tw:flex-col tw:gap-1 tw:rounded-md tw:border tw:p-2","tw:focus-within:ring-2 tw:focus-within:ring-ring tw:focus-within:ring-offset-1",T?"tw:border-border tw:bg-accent/50":"tw:border-transparent tw:hover:bg-accent/30",W?"tw:cursor-not-allowed tw:opacity-60":"tw:cursor-pointer"),children:[e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",children:[e.jsx(Re,{id:Z,value:I.value,"aria-label":I.label,disabled:W,"aria-describedby":W?u:void 0}),e.jsx("span",{"aria-hidden":!0,className:"tw:font-medium",children:I.label})]}),W&&e.jsx("span",{id:u,className:"tw:sr-only",children:B}),e.jsx(He,{html:I.html})]},I.value)};return e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-3 tw:text-sm",onClick:I=>I.stopPropagation(),children:[e.jsx("p",{children:r["%conflict_note_description_verseText%"]??"Conflicting changes were made to the verse text."}),p&&e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2","data-slot":"conflict-loading",children:[e.jsx(n.Skeleton,{className:"tw:h-8 tw:w-full"}),e.jsx(n.Skeleton,{className:"tw:h-8 tw:w-full"}),e.jsx(n.Skeleton,{className:"tw:h-8 tw:w-24"})]}),!p&&f&&H(),!p&&!f&&e.jsxs(e.Fragment,{children:[e.jsx("p",{children:r["%conflict_note_choose_prompt%"]??"Select which change to keep:"}),e.jsx(rr,{value:m,onValueChange:_,disabled:s,"aria-label":r["%conflict_note_choose_aria_label%"]??"Choose resolution",children:E.map(I=>U(I)?e.jsx(n.TooltipProvider,{delayDuration:0,children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:G(I)}),e.jsx(n.TooltipContent,{children:B})]})},I.value):G(I))}),e.jsx(n.TooltipProvider,{delayDuration:0,children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx("span",{className:"tw:inline-flex tw:self-start",children:e.jsx(n.Button,{size:"sm",disabled:A,onClick:()=>i==null?void 0:i(m),children:r["%conflict_note_save_and_resolve%"]??"Save and resolve"})})}),j&&e.jsx(n.TooltipContent,{children:j})]})})]})]})}const Pi={accept:{key:"%conflict_note_summary_resolved_kept_current%",fallback:"Conflicting edits were resolved. Kept the current text."},reject:{key:"%conflict_note_summary_resolved_used_other%",fallback:"Conflicting edits were resolved. Used the other change."},merged:{key:"%conflict_note_summary_resolved_combined%",fallback:"Conflicting edits were resolved. Combined both changes."}};function Li({comment:t,localizedStrings:r,resolvedResolution:a}){const o=l.useMemo(()=>qe(t.rejectedText??""),[t.rejectedText]);if(a){const{key:s,fallback:c}=Pi[a];return e.jsx("p",{className:"tw:text-sm tw:font-normal tw:text-muted-foreground",children:r[s]??c})}const i=r["%conflict_note_summary_unresolved%"]??"Conflicting edits. Choose which change to keep.";return e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-1",children:[e.jsx("p",{className:"tw:text-sm tw:font-normal tw:text-muted-foreground",children:i}),o?e.jsx(He,{html:o}):void 0]})}function Vi(t){return t==="reject"?"reject":t==="merge"?"merged":"accept"}function Fi({threadId:t,threadStatus:r,isSelected:a,activeComments:o,conflictResolution:i}){const[s,c]=l.useState("loading"),[d,u]=l.useState(!1),[w,p]=l.useState(),g=i==null?void 0:i.getOptions,f=i==null?void 0:i.resolve;l.useEffect(()=>{let y=!0;if(!a){c("loading");return}return(async()=>{let B;try{B=g?await g(t):"none"}catch{B="none"}y&&(c(B),B!=="none"&&p(void 0))})(),()=>{y=!1}},[a,t,r,g]);const h=l.useRef(!1),m=l.useCallback(async y=>{if(!(!f||h.current)){h.current=!0,u(!0);try{await f(t,y)&&(p(Vi(y)),c("none"))}catch{}finally{h.current=!1,u(!1)}}},[f,t]),b=l.useMemo(()=>{if(r==="Resolved"){for(let y=o.length-1;y>=0;y-=1)if(o[y].status==="Resolved")return Ha(o[y].conflictResolutionAction);return"accept"}},[r,o])??w;return{conflictOptions:s,isResolving:d,resolve:m,resolvedResolution:b,showResolveCheck:s!=="loading"&&s!=="none"}}function Gi(t){const{comments:r,localizedStrings:a,isSelected:o=!1,threadId:i,threadStatus:s,conflictResolution:c}=t,d=l.useMemo(()=>r.filter(C=>!C.deleted),[r]),u=l.useMemo(()=>d.find(C=>C.conflictType)??d[0],[d]),{conflictOptions:w,isResolving:p,resolve:g,resolvedResolution:f,showResolveCheck:h}=Fi({threadId:i,threadStatus:s,isSelected:o,activeComments:d,conflictResolution:c}),m=qa(u);let k;m&&u&&(k=o?e.jsx(eo,{comment:u,localizedStrings:a,availableActions:w,resolvedResolution:f,onResolve:g,isResolving:p}):e.jsx(Li,{comment:u,localizedStrings:a,resolvedResolution:f}));let b;return m&&(b=e.jsx(Qa,{show:h,disabled:p,onClick:()=>g("accept"),ariaLabel:a["%comment_aria_resolve_thread%"]??"Resolve thread"})),e.jsx(to,{...t,activeComments:d,rootContentSlot:k,resolveActionSlot:b,spaceRootContentFromReplies:m&&o})}function Ki({className:t="",classNameForVerseText:r,threads:a,currentUser:o,localizedStrings:i,handleAddCommentToThread:s,handleUpdateComment:c,handleDeleteComment:d,handleReadStatusChange:u,assignableUsers:w,canUserAddCommentToThread:p,canUserAssignThreadCallback:g,canUserResolveThreadCallback:f,canUserEditOrDeleteCommentCallback:h,selectedThreadId:m,onSelectedThreadChange:k,onVerseRefClick:b,conflictResolution:C}){const[y,_]=l.useState(new Set),[B,F]=l.useState(),[E,P]=l.useState(),A=l.useCallback(async T=>{const Z=await s(T);return Z!==void 0&&T.assignedUser!==void 0&&T.assignedUser!==""&&P(T.assignedUser),Z},[s]);l.useEffect(()=>{m&&(_(T=>new Set(T).add(m)),F(m))},[m]);const j=a.filter(T=>T.comments.some(Z=>!Z.deleted)),V=j.map(T=>({id:T.id})),z=l.useCallback(T=>{_(Z=>new Set(Z).add(T.id)),F(T.id),k==null||k(T.id)},[k]),N=l.useCallback(T=>{const Z=y.has(T);_(W=>{const vt=new Set(W);return vt.has(T)?vt.delete(T):vt.add(T),vt}),F(T),k==null||k(Z?void 0:T)},[y,k]),{listboxRef:H,activeId:U,handleKeyDown:G}=n.useListbox({options:V,onOptionSelect:z}),I=l.useCallback(T=>{T.key==="Escape"?(B&&y.has(B)&&(_(Z=>{const W=new Set(Z);return W.delete(B),W}),F(void 0),k==null||k(void 0)),T.preventDefault(),T.stopPropagation()):G(T)},[B,y,G,k]);return e.jsx("div",{id:Ya,role:"listbox",tabIndex:0,ref:H,"aria-activedescendant":U??void 0,"aria-label":"Comments",className:n.cn("tw:flex tw:w-full tw:flex-col tw:space-y-3 tw:outline-hidden tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-1 tw:focus:ring-offset-background",t),onKeyDown:I,children:j.map(T=>{const Z={classNameForVerseText:r,comments:T.comments,localizedStrings:i,verseRef:T.verseRef,handleSelectThread:N,threadId:T.id,thread:T,isRead:T.isRead,isSelected:y.has(T.id),currentUser:o,assignedUser:T.assignedUser,threadStatus:T.status,handleAddCommentToThread:A,handleUpdateComment:c,handleDeleteComment:d,handleReadStatusChange:u,assignableUsers:w,canUserAddCommentToThread:p,canUserAssignThreadCallback:g,canUserResolveThreadCallback:f,canUserEditOrDeleteCommentCallback:h,onVerseRefClick:b,initialAssignedUser:E};return e.jsx("div",{className:n.cn({"tw:opacity-60":T.status==="Resolved"}),children:T.type==="Conflict"?e.jsx(Gi,{...Z,conflictResolution:C}):e.jsx(to,{...Z})},T.id)})})}function Ui({table:t}){return e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"outline",size:"sm",className:"tw:ml-auto tw:hidden tw:h-8 tw:lg:flex",children:[e.jsx(R.FilterIcon,{className:"tw:mr-2 tw:h-4 tw:w-4"}),"View"]})}),e.jsxs(n.DropdownMenuContent,{align:"end",className:"tw:w-[150px]",children:[e.jsx(n.DropdownMenuLabel,{children:"Toggle columns"}),e.jsx(n.DropdownMenuSeparator,{}),t.getAllColumns().filter(r=>r.getCanHide()).map(r=>e.jsx(n.DropdownMenuCheckboxItem,{className:"tw:capitalize",checked:r.getIsVisible(),onCheckedChange:a=>r.toggleVisibility(!!a),children:r.id},r.id))]})]})}function ue({...t}){return e.jsx(D.Select.Root,{"data-slot":"select",...t})}function ro({className:t,...r}){return e.jsx(D.Select.Group,{"data-slot":"select-group",className:n.cn("tw:scroll-my-1 tw:p-1",t),...r})}function pe({...t}){return e.jsx(D.Select.Value,{"data-slot":"select-value",...t})}function ge({className:t,size:r="default",children:a,...o}){const i=n.readDirection();return e.jsxs(D.Select.Trigger,{"data-slot":"select-trigger","data-size":r,className:n.cn("pr-twp tw:flex tw:w-fit tw:items-center tw:gap-2 tw:rounded-lg tw:border tw:border-input tw:bg-transparent tw:py-2 tw:pe-2 tw:ps-2.5 tw:text-sm tw:whitespace-nowrap tw:transition-colors tw:outline-none tw:select-none tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:data-placeholder:text-muted-foreground tw:data-[size=default]:h-8 tw:data-[size=sm]:h-7 tw:data-[size=sm]:rounded-[min(var(--tw-radius-md),10px)] tw:*:data-[slot=select-value]:line-clamp-1 tw:*:data-[slot=select-value]:flex tw:*:data-[slot=select-value]:flex-1 tw:*:data-[slot=select-value]:items-center tw:*:data-[slot=select-value]:gap-1.5 tw:*:data-[slot=select-value]:text-start tw:dark:bg-input/30 tw:dark:hover:bg-input/50 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),dir:i,...o,children:[a,e.jsx(D.Select.Icon,{asChild:!0,children:e.jsx(Tt.IconSelector,{className:"tw:pointer-events-none tw:size-4 tw:text-muted-foreground"})})]})}function he({className:t,children:r,position:a="popper",align:o="center",style:i,...s}){const c=n.readDirection();return e.jsx(D.Select.Portal,{children:e.jsxs(D.Select.Content,{"data-slot":"select-content","data-align-trigger":a==="item-aligned",className:n.cn("pr-twp tw:relative tw:max-h-(--radix-select-content-available-height) tw:data-[align-trigger=true]:min-w-(--radix-select-trigger-width) tw:data-[align-trigger=false]:min-w-36 tw:origin-(--radix-select-content-transform-origin) tw:overflow-x-hidden tw:overflow-y-auto tw:rounded-lg tw:bg-popover tw:text-popover-foreground tw:shadow-md tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[align-trigger=true]:animate-none tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",a==="popper"&&"tw:data-[side=bottom]:translate-y-1 tw:data-[side=left]:-translate-x-1 tw:rtl:data-[side=left]:translate-x-1 tw:data-[side=right]:translate-x-1 tw:rtl:data-[side=right]:-translate-x-1 tw:data-[side=top]:-translate-y-1",t),style:{zIndex:n.Z_INDEX_ABOVE_DOCK,...i},position:a,align:o,...s,children:[e.jsx(ao,{}),e.jsx(D.Select.Viewport,{"data-position":a,className:n.cn("tw:data-[position=popper]:h-(--radix-select-trigger-height) tw:data-[position=popper]:w-full tw:data-[position=popper]:min-w-(--radix-select-trigger-width)",a==="popper"&&"tw:"),children:e.jsx("div",{dir:c,children:r})}),e.jsx(oo,{})]})})}function qi({className:t,...r}){return e.jsx(D.Select.Label,{"data-slot":"select-label",className:n.cn("pr-twp tw:px-1.5 tw:py-1 tw:text-xs tw:text-muted-foreground",t),...r})}function Ut({className:t,children:r,...a}){return e.jsxs(D.Select.Item,{"data-slot":"select-item",className:n.cn("pr-twp tw:relative tw:flex tw:w-full tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:py-1 tw:pe-8 tw:ps-1.5 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:not-data-[variant=destructive]:focus:**:text-accent-foreground tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4 tw:*:[span]:last:flex tw:*:[span]:last:items-center tw:*:[span]:last:gap-2",t),...a,children:[e.jsx("span",{className:"tw:pointer-events-none tw:absolute tw:end-2 tw:flex tw:size-4 tw:items-center tw:justify-center",children:e.jsx(D.Select.ItemIndicator,{children:e.jsx(Tt.IconCheck,{className:"tw:pointer-events-none"})})}),e.jsx(D.Select.ItemText,{children:r})]})}function Hi({className:t,...r}){return e.jsx(D.Select.Separator,{"data-slot":"select-separator",className:n.cn("pr-twp tw:pointer-events-none tw:-mx-1 tw:my-1 tw:h-px tw:bg-border",t),...r})}function ao({className:t,...r}){return e.jsx(D.Select.ScrollUpButton,{"data-slot":"select-scroll-up-button",className:n.cn("pr-twp tw:z-10 tw:flex tw:cursor-default tw:items-center tw:justify-center tw:bg-popover tw:py-1 tw:[&_svg:not([class*=size-])]:size-4",t),...r,children:e.jsx(Tt.IconChevronUp,{})})}function oo({className:t,...r}){return e.jsx(D.Select.ScrollDownButton,{"data-slot":"select-scroll-down-button",className:n.cn("pr-twp tw:z-10 tw:flex tw:cursor-default tw:items-center tw:justify-center tw:bg-popover tw:py-1 tw:[&_svg:not([class*=size-])]:size-4",t),...r,children:e.jsx(Tt.IconChevronDown,{})})}function Yi({table:t}){return e.jsx("div",{className:"tw:flex tw:items-center tw:justify-between tw:px-2 tw:pb-3 tw:pt-3",children:e.jsxs("div",{className:"tw:flex tw:items-center tw:space-x-6 tw:lg:space-x-8",children:[e.jsxs("div",{className:"tw:flex-1 tw:text-sm tw:text-muted-foreground",children:[t.getFilteredSelectedRowModel().rows.length," of"," ",t.getFilteredRowModel().rows.length," row(s) selected"]}),e.jsxs("div",{className:"tw:flex tw:items-center tw:space-x-2",children:[e.jsx("p",{className:"tw:text-nowrap tw:text-sm tw:font-medium",children:"Rows per page"}),e.jsxs(ue,{value:`${t.getState().pagination.pageSize}`,onValueChange:r=>{t.setPageSize(Number(r))},children:[e.jsx(ge,{className:"tw:h-8 tw:w-[70px]",children:e.jsx(pe,{placeholder:t.getState().pagination.pageSize})}),e.jsx(he,{side:"top",children:[10,20,30,40,50].map(r=>e.jsx(Ut,{value:`${r}`,children:r},r))})]})]}),e.jsxs("div",{className:"tw:flex tw:w-[100px] tw:items-center tw:justify-center tw:text-sm tw:font-medium",children:["Page ",t.getState().pagination.pageIndex+1," of ",t.getPageCount()]}),e.jsxs("div",{className:"tw:flex tw:items-center tw:space-x-2",children:[e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:hidden tw:h-8 tw:w-8 tw:p-0 tw:lg:flex",onClick:()=>t.setPageIndex(0),disabled:!t.getCanPreviousPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to first page"}),e.jsx(R.ArrowLeftIcon,{className:"tw:h-4 tw:w-4"})]}),e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:h-8 tw:w-8 tw:p-0",onClick:()=>t.previousPage(),disabled:!t.getCanPreviousPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to previous page"}),e.jsx(R.ChevronLeftIcon,{className:"tw:h-4 tw:w-4"})]}),e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:h-8 tw:w-8 tw:p-0",onClick:()=>t.nextPage(),disabled:!t.getCanNextPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to next page"}),e.jsx(R.ChevronRightIcon,{className:"tw:h-4 tw:w-4"})]}),e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:hidden tw:h-8 tw:w-8 tw:p-0 tw:lg:flex",onClick:()=>t.setPageIndex(t.getPageCount()-1),disabled:!t.getCanNextPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to last page"}),e.jsx(R.ArrowRightIcon,{className:"tw:h-4 tw:w-4"})]})]})]})})}function no({columns:t,data:r,enablePagination:a=!1,showPaginationControls:o=!1,showColumnVisibilityControls:i=!1,stickyHeader:s=!1,onRowClickHandler:c=()=>{},id:d,isLoading:u=!1,noResultsMessage:w}){var E;const[p,g]=l.useState([]),[f,h]=l.useState([]),[m,k]=l.useState({}),[b,C]=l.useState({}),y=l.useMemo(()=>r??[],[r]),_=It.useReactTable({data:y,columns:t,getCoreRowModel:It.getCoreRowModel(),...a&&{getPaginationRowModel:It.getPaginationRowModel()},onSortingChange:g,getSortedRowModel:It.getSortedRowModel(),onColumnFiltersChange:h,getFilteredRowModel:It.getFilteredRowModel(),onColumnVisibilityChange:k,onRowSelectionChange:C,state:{sorting:p,columnFilters:f,columnVisibility:m,rowSelection:b}}),B=_.getVisibleFlatColumns();let F;return u?F=Array.from({length:10}).map((j,V)=>`skeleton-row-${V}`).map(j=>e.jsx(n.TableRow,{className:"tw:hover:bg-transparent",children:e.jsx(n.TableCell,{colSpan:B.length??t.length,className:"tw:border-0 tw:p-0",children:e.jsx("div",{className:"tw:w-full tw:py-2",children:e.jsx(n.Skeleton,{className:"tw:h-14 tw:w-full tw:rounded-md"})})})},j)):((E=_.getRowModel().rows)==null?void 0:E.length)>0?F=_.getRowModel().rows.map(P=>e.jsx(n.TableRow,{onClick:()=>c(P,_),"data-state":P.getIsSelected()&&"selected",children:P.getVisibleCells().map(A=>e.jsx(n.TableCell,{children:It.flexRender(A.column.columnDef.cell,A.getContext())},A.id))},P.id)):F=e.jsx(n.TableRow,{children:e.jsx(n.TableCell,{colSpan:t.length,className:"tw:h-24 tw:text-center",children:w})}),e.jsxs("div",{className:"pr-twp",id:d,children:[i&&e.jsx(Ui,{table:_}),e.jsxs(n.Table,{stickyHeader:s,children:[e.jsx(n.TableHeader,{stickyHeader:s,children:_.getHeaderGroups().map(P=>e.jsx(n.TableRow,{children:P.headers.map(A=>e.jsx(n.TableHead,{className:"tw:p-0",children:A.isPlaceholder?void 0:It.flexRender(A.column.columnDef.header,A.getContext())},A.id))},P.id))}),e.jsx(n.TableBody,{children:F})]}),a&&e.jsxs("div",{className:"tw:flex tw:items-center tw:justify-end tw:space-x-2 tw:py-4",children:[e.jsx(n.Button,{variant:"outline",size:"sm",onClick:()=>_.previousPage(),disabled:!_.getCanPreviousPage(),children:"Previous"}),e.jsx(n.Button,{variant:"outline",size:"sm",onClick:()=>_.nextPage(),disabled:!_.getCanNextPage(),children:"Next"})]}),a&&o&&e.jsx(Yi,{table:_})]})}function Xi({id:t,markdown:r,className:a,anchorTarget:o,truncate:i}){const s=l.useMemo(()=>({overrides:{a:{props:{target:o}}}}),[o]);return e.jsx("div",{id:t,className:n.cn("pr-twp tw:prose",{"tw:line-clamp-3 tw:max-h-10 tw:overflow-hidden tw:text-ellipsis tw:break-words":i},a),children:e.jsx(Xo,{options:s,children:r})})}const io=Object.freeze(["%webView_error_dump_header%","%webView_error_dump_info_message%"]),da=(t,r)=>t[r]??r;function so({errorDetails:t,handleCopyNotify:r,localizedStrings:a,id:o}){const i=da(a,"%webView_error_dump_header%"),s=da(a,"%webView_error_dump_info_message%");function c(){navigator.clipboard.writeText(t),r&&r()}return e.jsxs("div",{id:o,className:"tw:inline-flex tw:w-full tw:flex-col tw:items-start tw:justify-start tw:gap-4",children:[e.jsxs("div",{className:"tw:inline-flex tw:items-start tw:justify-start tw:gap-4 tw:self-stretch",children:[e.jsxs("div",{className:"tw:inline-flex tw:flex-1 tw:flex-col tw:items-start tw:justify-start",children:[e.jsx("div",{className:"tw:text-color-text tw:justify-center tw:text-center tw:text-lg tw:font-semibold tw:leading-loose",children:i}),e.jsx("div",{className:"tw:justify-center tw:self-stretch tw:text-sm tw:font-normal tw:leading-tight tw:text-muted-foreground",children:s})]}),e.jsx(n.Button,{variant:"secondary",size:"icon",className:"size-8",onClick:()=>c(),children:e.jsx(R.Copy,{})})]}),e.jsx("div",{className:"tw:prose tw:w-full",children:e.jsx("pre",{className:"tw:text-xs",children:t})})]})}const Zi=Object.freeze([...io,"%webView_error_dump_copied_message%"]);function Wi({errorDetails:t,handleCopyNotify:r,localizedStrings:a,children:o,className:i,id:s}){const[c,d]=l.useState(!1),u=()=>{d(!0),r&&r()},w=p=>{p||d(!1)};return e.jsxs(n.Popover,{onOpenChange:w,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:o}),e.jsxs(n.PopoverContent,{id:s,className:n.cn("tw:min-w-80 tw:max-w-96",i),children:[c&&a["%webView_error_dump_copied_message%"]&&e.jsx(n.Label,{children:a["%webView_error_dump_copied_message%"]}),e.jsx(so,{errorDetails:t,handleCopyNotify:u,localizedStrings:a})]})]})}var co=(t=>(t[t.Check=0]="Check",t[t.Radio=1]="Radio",t))(co||{});function Ji({id:t,label:r,groups:a}){const[o,i]=l.useState(Object.fromEntries(a.map((w,p)=>w.itemType===0?[p,[]]:void 0).filter(w=>!!w))),[s,c]=l.useState({}),d=(w,p)=>{const g=!o[w][p];i(h=>(h[w][p]=g,{...h}));const f=a[w].items[p];f.onUpdate(f.id,g)},u=(w,p)=>{c(f=>(f[w]=p,{...f}));const g=a[w].items.find(f=>f.id===p);g?g.onUpdate(p):console.error(`Could not find dropdown radio item with id '${p}'!`)};return e.jsx("div",{id:t,children:e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"default",children:[e.jsx(R.Filter,{size:16,className:"tw:mr-2 tw:h-4 tw:w-4"}),r,e.jsx(R.ChevronDown,{size:16,className:"tw:ml-2 tw:h-4 tw:w-4"})]})}),e.jsx(n.DropdownMenuContent,{children:a.map((w,p)=>e.jsxs("div",{children:[e.jsx(n.DropdownMenuLabel,{children:w.label}),e.jsx(n.DropdownMenuGroup,{children:w.itemType===0?e.jsx(e.Fragment,{children:w.items.map((g,f)=>e.jsx("div",{children:e.jsx(n.DropdownMenuCheckboxItem,{checked:o[p][f],onCheckedChange:()=>d(p,f),children:g.label})},g.id))}):e.jsx(n.DropdownMenuRadioGroup,{value:s[p],onValueChange:g=>u(p,g),children:w.items.map(g=>e.jsx("div",{children:e.jsx(n.DropdownMenuRadioItem,{value:g.id,children:g.label})},g.id))})}),e.jsx(n.DropdownMenuSeparator,{})]},w.label))})]})})}function Qi({id:t,category:r,downloads:a,languages:o,moreInfoUrl:i,handleMoreInfoLinkClick:s,supportUrl:c,handleSupportLinkClick:d}){const u=new M.NumberFormat("en",{notation:"compact",compactDisplay:"short"}).format(Object.values(a).reduce((p,g)=>p+g,0)),w=()=>{window.scrollTo(0,document.body.scrollHeight)};return e.jsxs("div",{id:t,className:"pr-twp tw:flex tw:items-center tw:justify-center tw:divide-x tw:border-b tw:border-t tw:py-2 tw:text-center",children:[r&&e.jsxs("div",{className:"tw:flex tw:flex-col tw:items-center tw:gap-1 tw:px-4",children:[e.jsx("div",{className:"tw:flex",children:e.jsx("span",{className:"tw:text-xs tw:font-semibold tw:text-foreground",children:r})}),e.jsx("span",{className:"tw:text-xs tw:text-foreground",children:"CATEGORY"})]}),e.jsxs("div",{className:"tw:flex tw:flex-col tw:items-center tw:gap-1 tw:px-4",children:[e.jsxs("div",{className:"tw:flex tw:gap-1",children:[e.jsx(R.User,{className:"tw:h-4 tw:w-4"}),e.jsx("span",{className:"tw:text-xs tw:font-semibold tw:text-foreground",children:u})]}),e.jsx("span",{className:"tw:text-xs tw:text-foreground",children:"USERS"})]}),e.jsxs("div",{className:"tw:flex tw:flex-col tw:items-center tw:gap-1 tw:px-4",children:[e.jsx("div",{className:"tw:flex tw:gap-2",children:o.slice(0,3).map(p=>e.jsx("span",{className:"tw:text-xs tw:font-semibold tw:text-foreground",children:p.toUpperCase()},p))}),o.length>3&&e.jsxs("button",{type:"button",onClick:()=>w(),className:"tw:text-xs tw:text-foreground tw:underline",children:["+",o.length-3," more languages"]})]}),(i||c)&&e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-1 tw:px-4",children:[i&&e.jsx("div",{className:"tw:flex tw:gap-1",children:e.jsxs(n.Button,{onClick:()=>s(),variant:"link",className:"tw:flex tw:h-auto tw:gap-1 tw:py-0 tw:text-xs tw:font-semibold tw:text-foreground",children:["Website",e.jsx(R.Link,{className:"tw:h-4 tw:w-4"})]})}),c&&e.jsx("div",{className:"tw:flex tw:gap-1",children:e.jsxs(n.Button,{onClick:()=>d(),variant:"link",className:"tw:flex tw:h-auto tw:gap-1 tw:py-0 tw:text-xs tw:font-semibold tw:text-foreground",children:["Support",e.jsx(R.CircleHelp,{className:"tw:h-4 tw:w-4"})]})})]})]})}function ts({id:t,versionHistory:r}){const[a,o]=l.useState(!1),i=new Date;function s(d){const u=new Date(d),w=new Date(i.getTime()-u.getTime()),p=w.getUTCFullYear()-1970,g=w.getUTCMonth(),f=w.getUTCDate()-1;let h="";return p>0?h=`${p.toString()} year${p===1?"":"s"} ago`:g>0?h=`${g.toString()} month${g===1?"":"s"} ago`:f===0?h="today":h=`${f.toString()} day${f===1?"":"s"} ago`,h}const c=Object.entries(r).sort((d,u)=>u[0].localeCompare(d[0]));return e.jsxs("div",{className:"pr-twp",id:t,children:[e.jsx("h3",{className:"tw:text-md tw:font-semibold",children:"What`s New"}),e.jsx("ul",{className:"tw:list-disc tw:pl-5 tw:pr-4 tw:text-xs tw:text-foreground",children:(a?c:c.slice(0,5)).map(d=>e.jsxs("div",{className:"tw:mt-3 tw:flex tw:justify-between",children:[e.jsx("div",{className:"tw:text-foreground",children:e.jsx("li",{className:"tw:prose tw:text-xs",children:e.jsx("span",{children:d[1].description})})}),e.jsxs("div",{className:"tw:justify-end tw:text-right",children:[e.jsxs("div",{children:["Version ",d[0]]}),e.jsx("div",{children:s(d[1].date)})]})]},d[0]))}),c.length>5&&e.jsx("button",{type:"button",onClick:()=>o(!a),className:"tw:text-xs tw:text-foreground tw:underline",children:a?"Show Less Version History":"Show All Version History"})]})}function es({id:t,publisherDisplayName:r,fileSize:a,locales:o,versionHistory:i,currentVersion:s}){const c=l.useMemo(()=>M.formatBytes(a),[a]),u=(w=>{const p=new Intl.DisplayNames(M.getCurrentLocale(),{type:"language"});return w.map(g=>p.of(g))})(o);return e.jsx("div",{id:t,className:"pr-twp tw:border-t tw:py-2",children:e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2 tw:divide-y",children:[Object.entries(i).length>0&&e.jsx(ts,{versionHistory:i}),e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2 tw:py-2",children:[e.jsx("h2",{className:"tw:text-md tw:font-semibold",children:"Information"}),e.jsxs("div",{className:"tw:flex tw:items-start tw:justify-between tw:text-xs tw:text-foreground",children:[e.jsxs("p",{className:"tw:flex tw:flex-col tw:justify-start tw:gap-1",children:[e.jsx("span",{children:"Publisher"}),e.jsx("span",{className:"tw:font-semibold",children:r}),e.jsx("span",{children:"Size"}),e.jsx("span",{className:"tw:font-semibold",children:c})]}),e.jsx("div",{className:"tw:flex tw:w-3/4 tw:items-center tw:justify-between tw:text-xs tw:text-foreground",children:e.jsxs("p",{className:"tw:flex tw:flex-col tw:justify-start tw:gap-1",children:[e.jsx("span",{children:"Version"}),e.jsx("span",{className:"tw:font-semibold",children:s}),e.jsx("span",{children:"Languages"}),e.jsx("span",{className:"tw:font-semibold",children:u.join(", ")})]})})]})]})]})})}function rs({entries:t,selected:r,onChange:a,placeholder:o,commandEmptyMessage:i,customSelectedText:s,isDisabled:c,sortSelected:d,icon:u,className:w,badgesPlaceholder:p,id:g}){return e.jsxs("div",{id:g,className:"tw:flex tw:items-center tw:gap-2",children:[e.jsx(n.MultiSelectComboBox,{entries:t,selected:r,onChange:a,placeholder:o,commandEmptyMessage:i,customSelectedText:s,isDisabled:c,sortSelected:d,icon:u,className:w}),r.length>0?e.jsx("div",{className:"tw:flex tw:flex-wrap tw:items-center tw:gap-2",children:r.map(f=>{var h;return e.jsxs(n.Badge,{variant:"muted",className:"tw:flex tw:items-center tw:gap-1",children:[e.jsx(n.Button,{variant:"ghost",size:"icon",className:"tw:h-4 tw:w-4 tw:p-0 tw:hover:bg-transparent",onClick:()=>a(r.filter(m=>m!==f)),children:e.jsx(R.X,{className:"tw:h-3 tw:w-3"})}),(h=t.find(m=>m.value===f))==null?void 0:h.label]},f)})}):e.jsx(n.Label,{children:p})]})}const lo=Object.freeze(["%undoButton_tooltip%","%redoButton_tooltip%"]),wa=(t,r)=>t[r]??r;function wo({onUndoClick:t,onRedoClick:r,canUndo:a=!0,canRedo:o=!0,localizedStrings:i={},showKeyboardShortcuts:s=!0,className:c="tw:h-6 tw:w-6",variant:d="ghost"}){const u=n.isMacOs(),w=wa(i,"%undoButton_tooltip%"),p=wa(i,"%redoButton_tooltip%"),g=d==="secondary"||d==="default";return e.jsxs(n.ButtonGroup,{children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":w,className:c,size:"icon",onClick:t,disabled:!a,variant:d,children:e.jsx(R.Undo,{})})}),e.jsx(n.TooltipContent,{children:e.jsxs("p",{children:[w,s&&e.jsxs(e.Fragment,{children:[" ",e.jsx(n.Kbd,{children:u?"⌘Z":"Ctrl+Z"})]})]})})]})}),r&&g&&e.jsx(n.ButtonGroupSeparator,{}),r&&e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":p,className:c,size:"icon",onClick:r,disabled:!o,variant:d,children:e.jsx(R.Redo,{})})}),e.jsx(n.TooltipContent,{children:e.jsxs("p",{children:[p,s&&e.jsxs(e.Fragment,{children:[" ",e.jsx(n.Kbd,{children:u?"⌘⇧Z":"Ctrl+Y"})]})]})})]})})]})}function uo({children:t,editorRef:r,canUndo:a=!0,canRedo:o=!0}){const i=l.useRef(null);return l.useEffect(()=>{var u;const s=n.isMacOs(),c=((u=i.current)==null?void 0:u.querySelector(".editor-input"))??void 0,d=w=>{var g,f,h,m;if(!c||document.activeElement!==c)return;const p=w.key.toLowerCase();if(s){if(!w.metaKey)return;!w.shiftKey&&p==="z"?(w.preventDefault(),a&&((g=r.current)==null||g.undo())):w.shiftKey&&p==="z"&&(w.preventDefault(),o&&((f=r.current)==null||f.redo()))}else{if(!w.ctrlKey)return;!w.shiftKey&&p==="z"?(w.preventDefault(),a&&((h=r.current)==null||h.undo())):(p==="y"||w.shiftKey&&p==="z")&&(w.preventDefault(),o&&((m=r.current)==null||m.redo()))}};return document.addEventListener("keydown",d),()=>document.removeEventListener("keydown",d)},[o,a,r]),e.jsx("div",{ref:i,children:t})}const as=(t,r,a)=>t==="generated"?e.jsxs(e.Fragment,{children:[e.jsx("p",{children:"+"})," ",r["%footnoteEditor_callerDropdown_item_generated%"]]}):t==="hidden"?e.jsxs(e.Fragment,{children:[e.jsx("p",{children:"-"})," ",r["%footnoteEditor_callerDropdown_item_hidden%"]]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{children:a})," ",r["%footnoteEditor_callerDropdown_item_custom%"]]});function os({callerType:t,updateCallerType:r,customCaller:a,updateCustomCaller:o,localizedStrings:i}){const s=l.useRef(null),c=l.useRef(null),d=l.useRef(!1),[u,w]=l.useState(t),[p,g]=l.useState(a),[f,h]=l.useState(!1);l.useEffect(()=>{w(t)},[t]),l.useEffect(()=>{p!==a&&g(a)},[a]);const m=b=>{d.current=!1,h(b),b||(u!=="custom"||p?(r(u),o(p)):(w(t),g(a)))},k=b=>{var C,y,_,B;b.stopPropagation(),document.activeElement===c.current&&b.key==="ArrowDown"||b.key==="ArrowRight"?((C=s.current)==null||C.focus(),d.current=!0):document.activeElement===s.current&&b.key==="ArrowUp"?((y=c.current)==null||y.focus(),d.current=!1):document.activeElement===s.current&&b.key==="ArrowLeft"&&((_=s.current)==null?void 0:_.selectionStart)===0&&((B=c.current)==null||B.focus(),d.current=!1),u==="custom"&&b.key==="Enter"&&(document.activeElement===c.current||document.activeElement===s.current)&&m(!1)};return e.jsxs(n.DropdownMenu,{open:f,onOpenChange:m,children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:"outline",className:"tw:h-6",children:as(t,i,a)})})}),e.jsx(n.TooltipContent,{children:i["%footnoteEditor_callerDropdown_tooltip%"]})]})}),e.jsxs(n.DropdownMenuContent,{style:{zIndex:n.Z_INDEX_FOOTNOTE_EDITOR},onClick:()=>{d.current&&(d.current=!1)},onKeyDown:k,onMouseMove:()=>{var b;d.current&&((b=s.current)==null||b.focus())},children:[e.jsx(n.DropdownMenuLabel,{children:i["%footnoteEditor_callerDropdown_label%"]}),e.jsx(n.DropdownMenuSeparator,{}),e.jsx(n.DropdownMenuCheckboxItem,{checked:u==="generated",onCheckedChange:()=>w("generated"),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:justify-between",children:[e.jsx("span",{children:i["%footnoteEditor_callerDropdown_item_generated%"]}),e.jsx("span",{className:"tw:w-10 tw:text-center",children:Gt.GENERATOR_NOTE_CALLER})]})}),e.jsx(n.DropdownMenuCheckboxItem,{checked:u==="hidden",onCheckedChange:()=>w("hidden"),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:justify-between",children:[e.jsx("span",{children:i["%footnoteEditor_callerDropdown_item_hidden%"]}),e.jsx("span",{className:"tw:w-10 tw:text-center",children:Gt.HIDDEN_NOTE_CALLER})]})}),e.jsx(n.DropdownMenuCheckboxItem,{ref:c,checked:u==="custom",onCheckedChange:()=>w("custom"),onClick:b=>{var C;b.stopPropagation(),d.current=!0,(C=s.current)==null||C.focus()},onSelect:b=>b.preventDefault(),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:justify-between",children:[e.jsx("span",{children:i["%footnoteEditor_callerDropdown_item_custom%"]}),e.jsx(n.Input,{tabIndex:0,onMouseDown:b=>{b.stopPropagation(),w("custom"),d.current=!0},ref:s,className:"tw:h-auto tw:w-10 tw:p-0 tw:text-center",value:p,onKeyDown:b=>{b.key==="Enter"||b.key==="ArrowUp"||b.key==="ArrowDown"||b.key==="ArrowLeft"||b.key==="ArrowRight"||b.stopPropagation()},maxLength:1,onChange:b=>g(b.target.value)})]})})]})]})}const ns=(t,r)=>t==="f"?e.jsxs(e.Fragment,{children:[e.jsx(R.FunctionSquare,{})," ",r["%footnoteEditor_noteType_footnote_label%"]]}):t==="fe"?e.jsxs(e.Fragment,{children:[e.jsx(R.SquareSigma,{})," ",r["%footnoteEditor_noteType_endNote_label%"]]}):e.jsxs(e.Fragment,{children:[e.jsx(R.SquareX,{})," ",r["%footnoteEditor_noteType_crossReference_label%"]]}),is=(t,r)=>{if(t==="x")return r["%footnoteEditor_noteType_crossReference_label%"];let a=r["%footnoteEditor_noteType_endNote_label%"];return t==="f"&&(a=r["%footnoteEditor_noteType_footnote_label%"]),M.formatReplacementString(r["%footnoteEditor_noteType_tooltip%"]??"",{noteType:a})};function ss({noteType:t,handleNoteTypeChange:r,localizedStrings:a,isTypeSwitchable:o}){return e.jsxs(n.DropdownMenu,{children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:"outline",className:"tw:h-6",children:ns(t,a)})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:is(t,a)})})]})}),e.jsxs(n.DropdownMenuContent,{style:{zIndex:n.Z_INDEX_FOOTNOTE_EDITOR},children:[e.jsx(n.DropdownMenuLabel,{children:a["%footnoteEditor_noteTypeDropdown_label%"]}),e.jsx(n.DropdownMenuSeparator,{}),e.jsxs(n.DropdownMenuCheckboxItem,{disabled:t!=="x"&&!o,checked:t==="x",onCheckedChange:()=>r("x"),className:"tw:gap-2",children:[e.jsx(R.SquareX,{}),e.jsx("span",{children:a["%footnoteEditor_noteType_crossReference_label%"]})]}),e.jsxs(n.DropdownMenuCheckboxItem,{disabled:t==="x"&&!o,checked:t==="f",onCheckedChange:()=>r("f"),className:"tw:gap-2",children:[e.jsx(R.FunctionSquare,{}),e.jsx("span",{children:a["%footnoteEditor_noteType_footnote_label%"]})]}),e.jsxs(n.DropdownMenuCheckboxItem,{disabled:t==="x"&&!o,checked:t==="fe",onCheckedChange:()=>r("fe"),className:"tw:gap-2",children:[e.jsx(R.SquareSigma,{}),e.jsx("span",{children:a["%footnoteEditor_noteType_endNote_label%"]})]})]})]})}const po=Object.freeze(["%markerMenu_deprecated_label%","%markerMenu_disallowed_label%","%markerMenu_noResults%","%markerMenu_searchPlaceholder%","%markerMenu_searchPlaceholder_insert%","%markerMenu_searchPlaceholder_paragraph%"]);function cs({icon:t,className:r}){const a=t??R.Ban;return e.jsx(a,{className:r,size:16})}function ua({item:t,localizedStrings:r}){return e.jsxs(n.CommandItem,{className:"tw:flex tw:gap-2 tw:hover:bg-accent",disabled:t.isDisallowed||t.isDeprecated,onSelect:t.action,children:[e.jsx("div",{className:"tw:w-8 tw:min-w-8",children:t.marker?e.jsx("span",{className:"tw:text-xs",children:t.marker}):e.jsx("div",{children:e.jsx(cs,{icon:t.icon})})}),e.jsxs("div",{children:[e.jsx("p",{className:"tw:text-sm",children:t.title}),t.subtitle&&e.jsx("p",{className:"tw:text-xs tw:text-muted-foreground",children:t.subtitle})]}),(t.isDisallowed||t.isDeprecated)&&e.jsx(n.CommandShortcut,{className:"tw:font-sans",children:t.isDisallowed?r["%markerMenu_disallowed_label%"]:r["%markerMenu_deprecated_label%"]})]})}function go({localizedStrings:t,markerMenuItems:r,searchRef:a,searchPlaceholder:o}){const[i,s]=l.useState(""),[c,d]=l.useMemo(()=>{const u=i.trim().toLowerCase();if(!u){const g=r.filter(f=>!f.isDisallowed);return[g.length>0?g:r,[]]}const w=r.filter(g=>{var h;const f=(h=g.marker)==null?void 0:h.toLowerCase();return g.isDisallowed?f===u:f==null?void 0:f.includes(u)}),p=r.filter(g=>g.title.toLowerCase().includes(u)&&!w.includes(g));return[w,p]},[i,r]);return e.jsxs(n.Command,{className:"tw:p-1",shouldFilter:!1,loop:!0,children:[e.jsx(n.CommandInput,{className:"marker-menu-search",ref:a,value:i,onValueChange:u=>s(u),placeholder:o??t["%markerMenu_searchPlaceholder%"]}),e.jsxs(n.CommandList,{children:[e.jsx(n.CommandEmpty,{children:t["%markerMenu_noResults%"]}),e.jsx(n.CommandGroup,{children:c.map(u=>{var w;return e.jsx(ua,{item:u,localizedStrings:t},`item-${u.marker??((w=u.icon)==null?void 0:w.displayName)}-${u.title.replaceAll(" ","")}`)})}),d.length>0&&e.jsxs(e.Fragment,{children:[c.length>0&&e.jsx(n.CommandSeparator,{alwaysRender:!0}),e.jsx(n.CommandGroup,{children:d.map(u=>{var w;return e.jsx(ua,{item:u,localizedStrings:t},`item-${u.marker??((w=u.icon)==null?void 0:w.displayName)}-${u.title.replaceAll(" ","")}`)})})]})]})]})}function ls(t,r,a,o){if(!o||o==="p")return[];const i=M.usfmMarkers[o];if(!(i!=null&&i.children))return[];const s=[];return Object.entries(i.children).forEach(([,c])=>{s.push(...c.map(d=>({marker:d,title:a[M.usfmMarkers[d].description]??M.usfmMarkers[d].description,action:()=>{var u;(u=t.current)==null||u.insertMarker(d),r()}})))}),s.sort((c,d)=>(c.marker??c.title).localeCompare(d.marker??d.title))}function ds(t){var a;const r=(a=t.attributes)==null?void 0:a.char;r.style&&(r.style==="ft"&&(r.style="xt"),r.style==="fr"&&(r.style="xo"),r.style==="fq"&&(r.style="xq"))}function ws(t){var a;const r=(a=t.attributes)==null?void 0:a.char;r.style&&(r.style==="xt"&&(r.style="ft"),r.style==="xo"&&(r.style="fr"),r.style==="xq"&&(r.style="fq"))}const us={type:"USJ",version:"3.1",content:[{type:"para"}]};function ps({classNameForEditor:t,noteOps:r,onChange:a,onClose:o,scrRef:i,noteKey:s,editorOptions:c,defaultMarkerMenuTrigger:d,localizedStrings:u,parentEditorRef:w}){const p=l.useRef(null),g=l.useRef(null),f=l.useRef(null),h=l.useRef(null);l.useLayoutEffect(()=>{if(!h.current)return;const{width:L}=h.current.getBoundingClientRect();L>0&&(h.current.style.width=`${L}px`)},[]);const[m,k]=l.useState("generated"),[b,C]=l.useState("generated"),[y,_]=l.useState("*"),[B,F]=l.useState("*"),[E,P]=l.useState("f"),[A,j]=l.useState(!1),[V,z]=l.useState(!0),[N,H]=l.useState(!1),U=l.useRef(!1),G=l.useRef(""),[I,T]=l.useState(!1),[Z,W]=l.useState(),[vt,bt]=l.useState(),[Mt,K]=l.useState(),[J,st]=l.useState(),ot=l.useRef(null),gt=l.useMemo(()=>({...c,markerMenuTrigger:d,hasExternalUI:!0,view:{...c.view??Gt.getDefaultViewOptions(),noteMode:"expanded"}}),[c,d]),qt=l.useMemo(()=>ls(p,()=>T(!1),u,J),[u,J]);l.useEffect(()=>{var L;I||(L=p.current)==null||L.focus()},[E,I]),l.useEffect(()=>{var rt,Q;let L;U.current=!1,z(!0);const Y=r==null?void 0:r.at(0);if(Y&&Gt.isInsertEmbedOpOfType("note",Y)){const ct=(rt=Y.insert.note)==null?void 0:rt.caller;let nt="custom";ct===Gt.GENERATOR_NOTE_CALLER?nt="generated":ct===Gt.HIDDEN_NOTE_CALLER?nt="hidden":ct&&(_(ct),F(ct)),k(nt),C(nt),P(((Q=Y.insert.note)==null?void 0:Q.style)??"f"),L=setTimeout(()=>{var wt;(wt=p.current)==null||wt.applyUpdate([Y])},0)}return()=>{L&&clearTimeout(L)}},[r,s]);const et=l.useCallback((L,Y,rt=!1)=>{var ct,nt,wt;const Q=(nt=(ct=p.current)==null?void 0:ct.getNoteOps(0))==null?void 0:nt.at(0);if(Q&&Gt.isInsertEmbedOpOfType("note",Q)){if(Q.insert.note){let lt;L==="custom"?lt=Y:L==="generated"?lt=Gt.GENERATOR_NOTE_CALLER:lt=Gt.HIDDEN_NOTE_CALLER,Q.insert.note.caller=lt}a==null||a([Q]),rt&&w&&s&&((wt=w.current)==null||wt.replaceEmbedUpdate(s,[Q]))}},[s,a,w]),Rt=l.useCallback(()=>{et(m,y,!0),o()},[m,y,o,et]),yt=l.useRef(Rt);l.useLayoutEffect(()=>{yt.current=Rt});const Bt=l.useRef({book:i.book,chapterNum:i.chapterNum});l.useLayoutEffect(()=>{(Bt.current.book!==i.book||Bt.current.chapterNum!==i.chapterNum)&&(Bt.current={book:i.book,chapterNum:i.chapterNum},yt.current())},[i.book,i.chapterNum]);const Ht=()=>{var Y;const L=(Y=g.current)==null?void 0:Y.getElementsByClassName("editor-input")[0];L!=null&&L.textContent&&navigator.clipboard.writeText(L.textContent)},O=l.useCallback(L=>{k(L),et(L,y)},[y,et]),Pt=l.useCallback(L=>{_(L),et(m,L)},[m,et]),ft=L=>{var rt,Q,ct,nt,wt;P(L);const Y=(Q=(rt=p.current)==null?void 0:rt.getNoteOps(0))==null?void 0:Q.at(0);if(Y&&Gt.isInsertEmbedOpOfType("note",Y)){Y.insert.note&&(Y.insert.note.style=L);const lt=(nt=(ct=Y.insert.note)==null?void 0:ct.contents)==null?void 0:nt.ops;E!=="x"&&L==="x"?lt==null||lt.forEach(ut=>ds(ut)):E==="x"&&L!=="x"&&(lt==null||lt.forEach(ut=>ws(ut))),(wt=p.current)==null||wt.applyUpdate([Y,{delete:1}])}},xt=L=>{st(L.contextMarker),H(L.canRedo)},Vt=l.useCallback(L=>{var rt,Q,ct,nt,wt;const Y=(Q=(rt=p.current)==null?void 0:rt.getNoteOps(0))==null?void 0:Q.at(0);if(Y&&Gt.isInsertEmbedOpOfType("note",Y)){L.content.length>1&&setTimeout(()=>{var _t;(_t=p.current)==null||_t.applyUpdate([{retain:2},{delete:1}])},0);const lt=(ct=Y.insert.note)==null?void 0:ct.style,ut=(wt=(nt=Y.insert.note)==null?void 0:nt.contents)==null?void 0:wt.ops;if(lt||j(!1),j(lt==="x"?!!(ut!=null&&ut.every(_t=>{var At,Ct;if(!((At=_t.attributes)!=null&&At.char))return!0;const jt=((Ct=_t.attributes)==null?void 0:Ct.char).style;return jt==="xt"||jt==="xo"||jt==="xq"})):!!(ut!=null&&ut.every(_t=>{var At,Ct;if(!((At=_t.attributes)!=null&&At.char))return!0;const jt=((Ct=_t.attributes)==null?void 0:Ct.char).style;return jt==="ft"||jt==="fr"||jt==="fq"}))),!U.current){U.current=!0,G.current=JSON.stringify(Y),z(!0);return}z(JSON.stringify(Y)===G.current),et(m,y)}else j(!1),z(!0)},[m,y,et]),te=l.useCallback(()=>{const L=window.getSelection();if(f.current&&qt.length&&L&&L.rangeCount>0){const Y=L.getRangeAt(0).getBoundingClientRect(),rt=f.current.getBoundingClientRect();W(Y.left-rt.left),bt(Y.top-rt.top),K(Y.height),T(!0)}},[qt,f]);l.useEffect(()=>{const L=()=>{I&&T(!1)};return window.addEventListener("click",L),()=>{window.removeEventListener("click",L)}},[I]),l.useEffect(()=>{var L;I&&((L=ot.current)==null||L.focus())},[I]),l.useEffect(()=>{var rt;const L=((rt=g.current)==null?void 0:rt.querySelector(".editor-input"))??void 0,Y=Q=>{!I&&L&&document.activeElement===L&&Q.key===d?(Q.preventDefault(),te()):I&&Q.key==="Escape"&&(Q.preventDefault(),T(!1))};return document.addEventListener("keydown",Y),()=>{document.removeEventListener("keydown",Y)}},[I,te,d]);const Yt=u["%footnoteEditor_copyButton_tooltip%"];return e.jsxs(e.Fragment,{children:[e.jsxs("div",{ref:h,className:"footnote-editor tw:grid tw:gap-[12px]",children:[e.jsxs("div",{className:"tw:flex",children:[e.jsxs("div",{className:"tw:flex tw:gap-4",children:[e.jsx(ss,{isTypeSwitchable:A,noteType:E,handleNoteTypeChange:ft,localizedStrings:u}),e.jsx(os,{callerType:m,updateCallerType:O,customCaller:y,updateCustomCaller:Pt,localizedStrings:u})]}),e.jsx("div",{className:"tw:flex tw:w-full tw:justify-end",children:e.jsxs(n.ButtonGroup,{children:[e.jsx(wo,{onUndoClick:()=>{var L;return(L=p.current)==null?void 0:L.undo()},onRedoClick:()=>{var L;return(L=p.current)==null?void 0:L.redo()},canUndo:!V,canRedo:N,localizedStrings:u}),e.jsx(Or,{onCancelClick:o,onAcceptClick:Rt,canAccept:!V||b!==m||m==="custom"&&y!==B,localizedStrings:u,acceptLabel:u["%footnoteEditor_saveButton_tooltip%"]})]})})]}),e.jsxs("div",{ref:g,className:"tw:relative tw:rounded-[6px] tw:border-2 tw:border-ring",children:[e.jsx("div",{className:t,children:e.jsx(uo,{editorRef:p,canUndo:!V,canRedo:N,children:e.jsx(Gt.Editorial,{options:gt,onStateChange:xt,onUsjChange:Vt,defaultUsj:us,onScrRefChange:()=>{},scrRef:i,ref:p})})}),e.jsx("div",{className:"tw:absolute tw:bottom-0 tw:right-0",children:e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":Yt,onClick:Ht,className:"tw:h-6 tw:w-6",variant:"ghost",size:"icon",children:e.jsx(R.Copy,{})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:Yt})})]})})})]})]}),e.jsx("div",{className:"tw:absolute",ref:f,style:{top:0,left:0,height:0,width:0}}),e.jsxs(n.Popover,{open:I,children:[e.jsx(n.PopoverAnchor,{className:"tw:absolute",style:{top:vt,left:Z,height:Mt,width:0,pointerEvents:"none"}}),e.jsx(n.PopoverContent,{className:"tw:w-[500px] tw:p-0",onClick:L=>{L.preventDefault(),L.stopPropagation()},children:e.jsx(go,{markerMenuItems:qt,localizedStrings:u,searchRef:ot})})]})]})}const gs=Object.freeze([...po,...Object.entries(M.usfmMarkers).map(([,t])=>t.description).filter(t=>!!t),"%footnoteEditor_callerDropdown_item_custom%","%footnoteEditor_callerDropdown_item_generated%","%footnoteEditor_callerDropdown_item_hidden%","%footnoteEditor_callerDropdown_label%","%footnoteEditor_callerDropdown_tooltip%","%footnoteEditor_copyButton_tooltip%","%footnoteEditor_noteType_crossReference_label%","%footnoteEditor_noteType_endNote_label%","%footnoteEditor_noteType_footnote_label%","%footnoteEditor_noteType_tooltip%","%footnoteEditor_noteTypeDropdown_label%","%footnoteEditor_saveButton_tooltip%",...lo,...Dr]);function ho(t,r){if(!r||r.length===0)return t??"empty";const a=r.find(i=>typeof i=="string");if(a)return`key-${t??"unknown"}-${a.slice(0,10)}`;const o=typeof r[0]=="string"?"impossible":r[0].marker??"unknown";return`key-${t??"unknown"}-${o}`}function hs(t,r,a=!0,o=void 0){if(!r||r.length===0)return;const i=[],s=[];let c=[];return r.forEach(d=>{typeof d!="string"&&d.marker==="fp"?(c.length>0&&s.push(c),c=[d]):c.push(d)}),c.length>0&&s.push(c),s.map((d,u)=>{const w=u===s.length-1;return e.jsxs("p",{children:[Ir(t,d,a,!0,i),w&&o]},ho(t,d))})}function Ir(t,r,a=!0,o=!0,i=[]){if(!(!r||r.length===0))return r.map(s=>{if(typeof s=="string"){const c=`${t}-text-${s.slice(0,10)}`;if(o){const d=n.cn(`usfm_${t}`);return e.jsx("span",{className:d,children:s},c)}return e.jsxs("span",{className:"tw:inline-flex tw:items-center tw:gap-1 tw:underline tw:decoration-destructive",children:[e.jsx(R.AlertCircle,{className:"tw:h-4 tw:w-4 tw:fill-destructive"}),e.jsx("span",{children:s}),e.jsx(R.AlertCircle,{className:"tw:h-4 tw:w-4 tw:fill-destructive"})]},c)}return fs(s,ho(`${t}\\${s.marker}`,[s]),a,[...i,t??"unknown"])})}function fs(t,r,a,o=[]){const{marker:i}=t;return e.jsxs("span",{children:[i?a&&e.jsx("span",{className:"marker",children:`\\${i} `}):e.jsx(R.AlertCircle,{className:"tw:text-error tw:mr-1 tw:inline-block tw:h-4 tw:w-4","aria-label":"Missing marker"}),Ir(i,t.content,a,!0,[...o,i??"unknown"])]},r)}function fo({footnote:t,layout:r="horizontal",formatCaller:a,showMarkers:o=!0}){const i=a?a(t.caller):t.caller,s=i!==t.caller;let c,d=t.content;Array.isArray(t.content)&&t.content.length>0&&typeof t.content[0]!="string"&&(t.content[0].marker==="fr"||t.content[0].marker==="xo")&&([c,...d]=t.content);const u=o?e.jsx("span",{className:"marker",children:`\\${t.marker} `}):void 0,w=o?e.jsx("span",{className:"marker",children:` \\${t.marker}*`}):void 0,p=i&&e.jsxs("span",{className:n.cn("note-caller tw:inline-block",{formatted:s}),children:[i," "]}),g=c&&e.jsxs(e.Fragment,{children:[Ir(t.marker,[c],o,!1)," "]}),f=r==="horizontal"?"horizontal":"vertical",h=o?"marker-visible":"",m=r==="horizontal"?"tw:col-span-1":"tw:col-span-2 tw:col-start-1 tw:row-start-2",k=n.cn(f,h);return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:n.cn("textual-note-header tw:col-span-1 tw:w-fit tw:text-nowrap",k),children:[u,p]}),e.jsx("div",{className:n.cn("textual-note-header tw:col-span-1 tw:w-fit tw:text-nowrap",k),children:g}),e.jsx("div",{className:n.cn("textual-note-body tw:flex tw:flex-col tw:gap-1",m,k),children:d&&d.length>0&&e.jsx(e.Fragment,{children:hs(t.marker,d,o,w)})})]})}function ms({className:t,classNameForItems:r,footnotes:a,layout:o="horizontal",listId:i,selectedFootnote:s,showMarkers:c=!0,suppressFormatting:d=!1,formatCaller:u,onFootnoteSelected:w}){const p=u??M.getFormatCallerFunction(a,void 0),g=(y,_)=>{w==null||w(y,_,i)},f=s?a.findIndex(y=>y===s):-1,[h,m]=l.useState(f),k=(y,_,B)=>{if(a.length)switch(y.key){case"Enter":case" ":y.preventDefault(),w==null||w(_,B,i);break}},b=y=>{if(a.length)switch(y.key){case"ArrowDown":y.preventDefault(),m(_=>Math.min(_+1,a.length-1));break;case"ArrowUp":y.preventDefault(),m(_=>Math.max(_-1,0));break}},C=l.useRef([]);return l.useEffect(()=>{var y;h>=0&&h{const B=y===s,F=`${i}-${_}`;return e.jsxs(e.Fragment,{children:[e.jsx("li",{ref:E=>{C.current[_]=E},role:"option","aria-selected":B,"data-marker":y.marker,"data-state":B?"selected":void 0,tabIndex:_===h?0:-1,className:n.cn("tw:gap-x-3 tw:gap-y-1 tw:p-2 tw:data-[state=selected]:bg-muted",w&&"tw:hover:bg-muted/50","tw:w-full tw:rounded-sm tw:border-0 tw:bg-transparent tw:shadow-none","tw:focus:outline-hidden tw:focus-visible:outline-hidden","tw:focus-visible:ring-offset-0.5 tw:focus-visible:relative tw:focus-visible:z-10 tw:focus-visible:ring-2 tw:focus-visible:ring-ring","tw:grid tw:grid-flow-col tw:grid-cols-subgrid",o==="horizontal"?"tw:col-span-3":"tw:col-span-2 tw:row-span-2",r),onClick:()=>g(y,_),onKeyDown:E=>k(E,y,_),children:e.jsx(fo,{footnote:y,layout:o,formatCaller:()=>p(y.caller,_),showMarkers:c})},F),_a&&r.push(t.substring(a,i.index)),r.push(e.jsx("strong",{children:i[1]},i.index)),a=o.lastIndex;return a0?r:[t]}function bs({occurrenceData:t,setScriptureReference:r,localizedStrings:a,classNameForText:o}){const i=a["%webView_inventory_occurrences_table_header_reference%"],s=a["%webView_inventory_occurrences_table_header_occurrence%"],c=l.useMemo(()=>{const d=[],u=new Set;return t.forEach(w=>{const p=`${w.reference.book}:${w.reference.chapterNum}:${w.reference.verseNum}:${w.text}`;u.has(p)||(u.add(p),d.push(w))}),d},[t]);return e.jsxs(n.Table,{stickyHeader:!0,children:[e.jsx(n.TableHeader,{stickyHeader:!0,children:e.jsxs(n.TableRow,{children:[e.jsx(n.TableHead,{children:i}),e.jsx(n.TableHead,{children:s})]})}),e.jsx(n.TableBody,{children:c.length>0&&c.map(d=>e.jsxs(n.TableRow,{onClick:()=>{r(d.reference)},children:[e.jsx(n.TableCell,{children:M.formatScrRef(d.reference,"English")}),e.jsx(n.TableCell,{className:o,children:vs(d.text)})]},`${d.reference.book} ${d.reference.chapterNum}:${d.reference.verseNum}-${d.text}`))})]})}function Ar({className:t,...r}){return e.jsx(D.Checkbox.Root,{"data-slot":"checkbox",className:n.cn("pr-twp tw:peer tw:relative tw:flex tw:size-4 tw:shrink-0 tw:items-center tw:justify-center tw:rounded-[4px] tw:border tw:border-input tw:transition-colors tw:outline-none tw:group-has-disabled/field:opacity-50 tw:after:absolute tw:after:-inset-x-3 tw:after:-inset-y-2 tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:aria-invalid:aria-checked:border-primary tw:dark:bg-input/30 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:data-checked:border-primary tw:data-checked:bg-primary tw:data-checked:text-primary-foreground tw:dark:data-checked:bg-primary",t),...r,children:e.jsx(D.Checkbox.Indicator,{"data-slot":"checkbox-indicator",className:"tw:grid tw:place-content-center tw:text-current tw:transition-none tw:[&>svg]:size-3.5",children:e.jsx(Tt.IconCheck,{})})})}const xs=t=>{if(t==="asc")return e.jsx(R.ArrowUpIcon,{className:"tw:h-4 tw:w-4"});if(t==="desc")return e.jsx(R.ArrowDownIcon,{className:"tw:h-4 tw:w-4"})},Oe=(t,r,a)=>e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsxs(n.TooltipTrigger,{className:n.cn("tw:flex tw:w-full tw:justify-start",a),variant:"ghost",onClick:()=>t.toggleSorting(void 0),children:[e.jsx("span",{className:"tw:w-6 tw:max-w-fit tw:flex-1 tw:overflow-hidden tw:text-ellipsis",children:r}),xs(t.getIsSorted())]}),e.jsx(n.TooltipContent,{side:"bottom",children:r})]})}),ks=t=>({accessorKey:"item",accessorFn:r=>r.items[0],header:({column:r})=>Oe(r,t)}),ys=(t,r)=>({accessorKey:`item${r}`,accessorFn:a=>a.items[r],header:({column:a})=>Oe(a,t)}),_s=t=>({accessorKey:"count",header:({column:r})=>Oe(r,t,"tw:justify-end"),cell:({row:r})=>e.jsx("div",{className:"tw:flex tw:justify-end tw:tabular-nums",children:r.getValue("count")})}),pr=(t,r,a,o,i,s)=>{let c=[...a];t.forEach(u=>{r==="approved"?c.includes(u)||c.push(u):c=c.filter(w=>w!==u)}),o(c);let d=[...i];t.forEach(u=>{r==="unapproved"?d.includes(u)||d.push(u):d=d.filter(w=>w!==u)}),s(d)},js=(t,r,a,o,i)=>({accessorKey:"status",header:({column:s})=>Oe(s,t,"tw:justify-center"),cell:({row:s})=>{const c=s.getValue("status"),d=s.getValue("item");return e.jsx("div",{className:"tw:flex tw:justify-center",children:e.jsxs(Mr,{value:c,variant:"outline",type:"single",className:"tw:gap-0",children:[e.jsx(Me,{onClick:u=>{u.stopPropagation(),pr([d],"approved",r,a,o,i)},value:"approved",className:"tw:rounded-e-none tw:border-e-0",children:e.jsx(R.CircleCheckIcon,{})}),e.jsx(Me,{onClick:u=>{u.stopPropagation(),pr([d],"unapproved",r,a,o,i)},value:"unapproved",className:"tw:rounded-none",children:e.jsx(R.CircleXIcon,{})}),e.jsx(Me,{onClick:u=>{u.stopPropagation(),pr([d],"unknown",r,a,o,i)},value:"unknown",className:"tw:rounded-s-none tw:border-s-0",children:e.jsx(R.CircleHelpIcon,{})})]})})}}),Cs=t=>t.split(/(?:\r?\n|\r)|(?=(?:\\(?:v|c|id)))/g),Ns=t=>{const r=/^\\[vc]\s+(\d+)/,a=t.match(r);if(a)return+a[1]},Es=t=>{const r=t.match(/^\\id\s+([A-Za-z]+)/);return r?r[1]:""},mo=(t,r,a)=>a.includes(t)?"unapproved":r.includes(t)?"approved":"unknown",Ss=Object.freeze(["%webView_inventory_all%","%webView_inventory_approved%","%webView_inventory_unapproved%","%webView_inventory_unknown%","%webView_inventory_scope_currentBook%","%webView_inventory_scope_chapter%","%webView_inventory_scope_verse%","%webView_inventory_filter_text%","%webView_inventory_show_additional_items%","%webView_inventory_occurrences_table_header_reference%","%webView_inventory_occurrences_table_header_occurrence%","%webView_inventory_no_results%"]),Ts=(t,r,a)=>{let o=t;return r!=="all"&&(o=o.filter(i=>r==="approved"&&i.status==="approved"||r==="unapproved"&&i.status==="unapproved"||r==="unknown"&&i.status==="unknown")),a!==""&&(o=o.filter(i=>i.items[0].includes(a))),o},Ms=(t,r,a)=>t.map(o=>{const i=M.isString(o.key)?o.key:o.key[0];return{items:M.isString(o.key)?[o.key]:o.key,count:o.count,status:o.status||mo(i,r,a),occurrences:o.occurrences||[]}}),Zt=(t,r)=>t[r]??r;function Rs({inventoryItems:t,setVerseRef:r,localizedStrings:a,additionalItemsLabels:o,approvedItems:i,unapprovedItems:s,scope:c,onScopeChange:d,columns:u,id:w,areInventoryItemsLoading:p=!1,classNameForVerseText:g,onItemSelected:f}){const h=Zt(a,"%webView_inventory_all%"),m=Zt(a,"%webView_inventory_approved%"),k=Zt(a,"%webView_inventory_unapproved%"),b=Zt(a,"%webView_inventory_unknown%"),C=Zt(a,"%webView_inventory_scope_currentBook%"),y=Zt(a,"%webView_inventory_scope_chapter%"),_=Zt(a,"%webView_inventory_scope_verse%"),B=Zt(a,"%webView_inventory_filter_text%"),F=Zt(a,"%webView_inventory_show_additional_items%"),E=Zt(a,"%webView_inventory_no_results%"),[P,A]=l.useState(!1),[j,V]=l.useState("all"),[z,N]=l.useState(""),[H,U]=l.useState([]),G=l.useMemo(()=>{const K=t??[];return K.length===0?[]:Ms(K,i,s)},[t,i,s]),I=l.useMemo(()=>{if(P)return G;const K=[];return G.forEach(J=>{const st=J.items[0],ot=K.find(gt=>gt.items[0]===st);ot?(ot.count+=J.count,ot.occurrences=ot.occurrences.concat(J.occurrences)):K.push({items:[st],count:J.count,occurrences:J.occurrences,status:J.status})}),K},[P,G]),T=l.useMemo(()=>I.length===0?[]:Ts(I,j,z),[I,j,z]),Z=l.useMemo(()=>{var st,ot;if(!P)return u;const K=(st=o==null?void 0:o.tableHeaders)==null?void 0:st.length;if(!K)return u;const J=[];for(let gt=0;gt{T.length===0?U([]):T.length===1&&U(T[0].items)},[T]);const W=(K,J)=>{J.setRowSelection(()=>{const ot={};return ot[K.index]=!0,ot});const st=K.original.items;U(st),f&&st.length>0&&f(st[0])},vt=K=>{if(K==="book"||K==="chapter"||K==="verse")d(K);else throw new Error(`Invalid scope value: ${K}`)},bt=K=>{if(K==="all"||K==="approved"||K==="unapproved"||K==="unknown")V(K);else throw new Error(`Invalid status filter value: ${K}`)},Mt=l.useMemo(()=>{if(I.length===0||H.length===0)return[];const K=I.filter(J=>M.deepEqual(P?J.items:[J.items[0]],H));if(K.length>1)throw new Error("Selected item is not unique");return K.length===0?[]:K[0].occurrences},[H,P,I]);return e.jsx("div",{id:w,className:"pr-twp tw:h-full tw:overflow-auto",children:e.jsxs("div",{className:"tw:flex tw:h-full tw:w-full tw:min-w-min tw:flex-col",children:[e.jsxs("div",{className:"tw:flex tw:items-stretch",style:{contain:"inline-size"},children:[e.jsxs(ue,{onValueChange:K=>bt(K),defaultValue:j,children:[e.jsx(ge,{className:"tw:m-1 tw:w-auto tw:flex-1",children:e.jsx(pe,{placeholder:"Select filter"})}),e.jsxs(he,{children:[e.jsx(Ut,{value:"all",children:h}),e.jsx(Ut,{value:"approved",children:m}),e.jsx(Ut,{value:"unapproved",children:k}),e.jsx(Ut,{value:"unknown",children:b})]})]}),e.jsxs(ue,{onValueChange:K=>vt(K),defaultValue:c,children:[e.jsx(ge,{className:"tw:m-1 tw:w-auto tw:flex-1",children:e.jsx(pe,{placeholder:"Select scope"})}),e.jsxs(he,{children:[e.jsx(Ut,{value:"book",children:C}),e.jsx(Ut,{value:"chapter",children:y}),e.jsx(Ut,{value:"verse",children:_})]})]}),e.jsx(n.Input,{className:"tw:m-1 tw:flex-1 tw:rounded-md tw:border",placeholder:B,value:z,onChange:K=>{N(K.target.value)}}),o&&e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsxs("div",{className:"tw:m-1 tw:flex tw:w-fit tw:min-w-[26px] tw:items-center tw:rounded-md tw:border",children:[e.jsx(Ar,{className:"tw:m-1 tw:shrink-0",checked:P,onCheckedChange:K=>{A(K)}}),e.jsx(n.Label,{className:"tw:m-1 tw:truncate",children:(o==null?void 0:o.checkboxText)??F})]})}),e.jsx(n.TooltipContent,{children:(o==null?void 0:o.checkboxText)??F})]})})]}),e.jsx("div",{className:"tw:m-1 tw:flex-1 tw:overflow-auto tw:rounded-md tw:border",children:e.jsx(no,{columns:Z,data:T,onRowClickHandler:W,stickyHeader:!0,isLoading:p,noResultsMessage:E})}),Mt.length>0&&e.jsx("div",{className:"tw:m-1 tw:flex-1 tw:overflow-auto tw:rounded-md tw:border",children:e.jsx(bs,{classNameForText:g,occurrenceData:Mt,setScriptureReference:r,localizedStrings:a})})]})})}const Ds="16rem",Os="3rem",vo=l.createContext(void 0);function ze(){const t=l.useContext(vo);if(!t)throw new Error("useSidebar must be used within a SidebarProvider.");return t}function bo({defaultOpen:t=!0,open:r,onOpenChange:a,className:o,style:i,children:s,side:c="primary",...d}){const[u,w]=l.useState(t),p=r??u,g=l.useCallback(_=>{const B=typeof _=="function"?_(p):_;a?a(B):w(B)},[a,p]),f=l.useCallback(()=>g(_=>!_),[g]),h=p?"expanded":"collapsed",b=n.readDirection()==="ltr"?c:c==="primary"?"secondary":"primary",C=l.useMemo(()=>({state:h,open:p,setOpen:g,toggleSidebar:f,side:b}),[h,p,g,f,b]),y={"--sidebar-width":Ds,"--sidebar-width-icon":Os,...i};return e.jsx(vo.Provider,{value:C,children:e.jsx("div",{"data-slot":"sidebar-wrapper",style:y,className:n.cn("pr-twp tw:group/sidebar-wrapper tw:flex tw:w-full tw:has-data-[variant=inset]:bg-sidebar",o),...d,children:s})})}function xo({variant:t="sidebar",collapsible:r="offcanvas",className:a,children:o,...i}){const s=ze();return r==="none"?e.jsx("div",{"data-slot":"sidebar",className:n.cn("tw:flex tw:h-full tw:w-(--sidebar-width) tw:flex-col tw:bg-sidebar tw:text-sidebar-foreground",a),...i,children:o}):e.jsxs("div",{className:"tw:group tw:peer tw:hidden tw:text-sidebar-foreground tw:md:block","data-state":s.state,"data-collapsible":s.state==="collapsed"?r:"","data-variant":t,"data-side":s.side,"data-slot":"sidebar",children:[e.jsx("div",{"data-slot":"sidebar-gap",className:n.cn("tw:relative tw:w-(--sidebar-width) tw:bg-transparent tw:transition-[width] tw:duration-200 tw:ease-linear","tw:group-data-[collapsible=offcanvas]:w-0","tw:group-data-[side=secondary]:rotate-180",t==="floating"||t==="inset"?"tw:group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]":"tw:group-data-[collapsible=icon]:w-(--sidebar-width-icon)")}),e.jsx("div",{"data-slot":"sidebar-container","data-side":s.side,className:n.cn("tw:absolute tw:inset-y-0 tw:z-10 tw:hidden tw:h-svh tw:w-(--sidebar-width) tw:transition-[left,right,width] tw:duration-200 tw:ease-linear tw:md:flex",s.side==="primary"?"tw:left-0 tw:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]":"tw:right-0 tw:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",t==="floating"||t==="inset"?"tw:p-2 tw:group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]":"tw:group-data-[collapsible=icon]:w-(--sidebar-width-icon) tw:group-data-[side=primary]:border-e tw:group-data-[side=secondary]:border-s",a),...i,children:e.jsx("div",{"data-sidebar":"sidebar","data-slot":"sidebar-inner",className:"tw:flex tw:size-full tw:flex-col tw:bg-sidebar tw:group-data-[variant=floating]:rounded-lg tw:group-data-[variant=floating]:shadow-sm tw:group-data-[variant=floating]:ring-1 tw:group-data-[variant=floating]:ring-sidebar-border",children:o})})]})}function zs({className:t,onClick:r,...a}){const{toggleSidebar:o,side:i}=ze();return e.jsxs(n.Button,{"data-sidebar":"trigger","data-slot":"sidebar-trigger",variant:"ghost",size:"icon-sm",className:n.cn(t),onClick:s=>{r==null||r(s),o()},...a,children:[i==="primary"?e.jsx(Tt.IconLayoutSidebar,{}):e.jsx(Tt.IconLayoutSidebarRight,{}),e.jsx("span",{className:"tw:sr-only",children:"Toggle Sidebar"})]})}function Is({className:t,...r}){const{toggleSidebar:a}=ze();return e.jsx("button",{type:"button","data-sidebar":"rail","data-slot":"sidebar-rail","aria-label":"Toggle Sidebar",tabIndex:-1,onClick:a,title:"Toggle Sidebar",className:n.cn("tw:absolute tw:inset-y-0 tw:z-20 tw:hidden tw:w-4 tw:transition-all tw:ease-linear tw:group-data-[side=primary]:-right-4 tw:group-data-[side=secondary]:left-0 tw:after:absolute tw:after:inset-y-0 tw:after:start-1/2 tw:after:w-[2px] tw:hover:after:bg-sidebar-border tw:sm:flex tw:ltr:-translate-x-1/2 tw:rtl:translate-x-1/2","tw:in-data-[side=primary]:cursor-w-resize tw:rtl:in-data-[side=primary]:cursor-e-resize tw:in-data-[side=secondary]:cursor-e-resize tw:rtl:in-data-[side=secondary]:cursor-w-resize","tw:[[data-side=primary][data-state=collapsed]_&]:cursor-e-resize tw:rtl:[[data-side=primary][data-state=collapsed]_&]:cursor-w-resize tw:[[data-side=secondary][data-state=collapsed]_&]:cursor-w-resize tw:rtl:[[data-side=secondary][data-state=collapsed]_&]:cursor-e-resize","tw:group-data-[collapsible=offcanvas]:translate-x-0 tw:group-data-[collapsible=offcanvas]:after:start-full tw:hover:group-data-[collapsible=offcanvas]:bg-sidebar","tw:[[data-side=primary][data-collapsible=offcanvas]_&]:-end-2","tw:[[data-side=secondary][data-collapsible=offcanvas]_&]:-start-2",t),...r})}function ko({className:t,...r}){return e.jsx("main",{"data-slot":"sidebar-inset",className:n.cn("tw:relative tw:flex tw:w-full tw:flex-1 tw:flex-col tw:bg-background tw:md:peer-data-[variant=inset]:m-2 tw:md:peer-data-[variant=inset]:ms-0 tw:md:peer-data-[variant=inset]:rounded-xl tw:md:peer-data-[variant=inset]:shadow-sm tw:md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2",t),...r})}function As({className:t,...r}){return e.jsx(n.Input,{"data-slot":"sidebar-input","data-sidebar":"input",className:n.cn("tw:h-8 tw:w-full tw:bg-background tw:shadow-none",t),...r})}function $s({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-header","data-sidebar":"header",className:n.cn("tw:flex tw:flex-col tw:gap-2 tw:p-2",t),...r})}function Bs({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-footer","data-sidebar":"footer",className:n.cn("tw:flex tw:flex-col tw:gap-2 tw:p-2",t),...r})}function Ps({className:t,...r}){return e.jsx(n.Separator,{"data-slot":"sidebar-separator","data-sidebar":"separator",className:n.cn("tw:mx-2 tw:w-auto tw:bg-sidebar-border",t),...r})}function yo({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-content","data-sidebar":"content",className:n.cn("tw:no-scrollbar tw:flex tw:min-h-0 tw:flex-1 tw:flex-col tw:gap-0 tw:overflow-auto tw:group-data-[collapsible=icon]:overflow-hidden",t),...r})}function kr({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-group","data-sidebar":"group",className:n.cn("tw:relative tw:flex tw:w-full tw:min-w-0 tw:flex-col tw:p-2",t),...r})}function yr({className:t,asChild:r=!1,...a}){const o=r?D.Slot.Root:"div";return e.jsx(o,{"data-slot":"sidebar-group-label","data-sidebar":"group-label",className:n.cn("tw:flex tw:h-8 tw:shrink-0 tw:items-center tw:rounded-md tw:px-2 tw:text-xs tw:font-medium tw:text-sidebar-foreground/70 tw:ring-sidebar-ring tw:outline-hidden tw:transition-[margin,opacity] tw:duration-200 tw:ease-linear tw:group-data-[collapsible=icon]:-mt-8 tw:group-data-[collapsible=icon]:opacity-0 tw:focus-visible:ring-2 tw:[&>svg]:size-4 tw:[&>svg]:shrink-0",t),...a})}function Ls({className:t,asChild:r=!1,...a}){const o=r?D.Slot.Root:"button";return e.jsx(o,{"data-slot":"sidebar-group-action","data-sidebar":"group-action",className:n.cn("tw:absolute tw:top-3.5 tw:end-3 tw:flex tw:aspect-square tw:w-5 tw:items-center tw:justify-center tw:rounded-md tw:p-0 tw:text-sidebar-foreground tw:ring-sidebar-ring tw:outline-hidden tw:transition-transform tw:group-data-[collapsible=icon]:hidden tw:after:absolute tw:after:-inset-2 tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:md:after:hidden tw:[&>svg]:size-4 tw:[&>svg]:shrink-0",t),...a})}function _r({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-group-content","data-sidebar":"group-content",className:n.cn("tw:w-full tw:text-sm",t),...r})}function _o({className:t,...r}){return e.jsx("ul",{"data-slot":"sidebar-menu","data-sidebar":"menu",className:n.cn("tw:flex tw:w-full tw:min-w-0 tw:flex-col tw:gap-0",t),...r})}function jo({className:t,...r}){return e.jsx("li",{"data-slot":"sidebar-menu-item","data-sidebar":"menu-item",className:n.cn("tw:group/menu-item tw:relative",t),...r})}const Vs=er.cva("tw:peer/menu-button tw:group/menu-button tw:flex tw:w-full tw:items-center tw:gap-2 tw:overflow-hidden tw:rounded-md tw:p-2 tw:text-start tw:text-sm tw:ring-sidebar-ring tw:outline-hidden tw:transition-[width,height,padding] tw:group-has-data-[sidebar=menu-action]/menu-item:pe-8 tw:group-data-[collapsible=icon]:size-8! tw:group-data-[collapsible=icon]:p-2! tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:active:bg-sidebar-accent tw:active:text-sidebar-accent-foreground tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-disabled:pointer-events-none tw:aria-disabled:opacity-50 tw:data-open:hover:bg-sidebar-accent tw:data-open:hover:text-sidebar-accent-foreground tw:data-active:bg-sidebar-accent tw:data-active:font-medium tw:data-active:text-sidebar-accent-foreground tw:[&_svg]:size-4 tw:[&_svg]:shrink-0 tw:[&>span:last-child]:truncate",{variants:{variant:{default:"tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground",outline:"tw:bg-background tw:shadow-[0_0_0_1px_var(--sidebar-border)] tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:hover:shadow-[0_0_0_1px_var(--sidebar-accent)]"},size:{default:"tw:h-8 tw:text-sm",sm:"tw:h-7 tw:text-xs",lg:"tw:h-12 tw:text-sm tw:group-data-[collapsible=icon]:p-0!"}},defaultVariants:{variant:"default",size:"default"}});function Co({asChild:t=!1,isActive:r=!1,variant:a="default",size:o="default",tooltip:i,className:s,...c}){const d=t?D.Slot.Root:"button",{state:u}=ze(),w=e.jsx(d,{"data-slot":"sidebar-menu-button","data-sidebar":"menu-button","data-size":o,"data-active":r,className:n.cn(Vs({variant:a,size:o}),s),...c});if(!i)return w;const p=typeof i=="string"?{children:i}:i;return e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:w}),e.jsx(n.TooltipContent,{side:"right",align:"center",hidden:u!=="collapsed",...p})]})}function Fs({className:t,asChild:r=!1,showOnHover:a=!1,...o}){const i=r?D.Slot.Root:"button";return e.jsx(i,{"data-slot":"sidebar-menu-action","data-sidebar":"menu-action",className:n.cn("tw:absolute tw:top-1.5 tw:end-1 tw:flex tw:aspect-square tw:w-5 tw:items-center tw:justify-center tw:rounded-md tw:p-0 tw:text-sidebar-foreground tw:ring-sidebar-ring tw:outline-hidden tw:transition-transform tw:group-data-[collapsible=icon]:hidden tw:peer-hover/menu-button:text-sidebar-accent-foreground tw:peer-data-[size=default]/menu-button:top-1.5 tw:peer-data-[size=lg]/menu-button:top-2.5 tw:peer-data-[size=sm]/menu-button:top-1 tw:after:absolute tw:after:-inset-2 tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:md:after:hidden tw:[&>svg]:size-4 tw:[&>svg]:shrink-0",a&&"tw:group-focus-within/menu-item:opacity-100 tw:group-hover/menu-item:opacity-100 tw:peer-data-active/menu-button:text-sidebar-accent-foreground tw:aria-expanded:opacity-100 tw:md:opacity-0",t),...o})}function Gs({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-menu-badge","data-sidebar":"menu-badge",className:n.cn("tw:pointer-events-none tw:absolute tw:end-1 tw:flex tw:h-5 tw:min-w-5 tw:items-center tw:justify-center tw:rounded-md tw:px-1 tw:text-xs tw:font-medium tw:text-sidebar-foreground tw:tabular-nums tw:select-none tw:group-data-[collapsible=icon]:hidden tw:peer-hover/menu-button:text-sidebar-accent-foreground tw:peer-data-[size=default]/menu-button:top-1.5 tw:peer-data-[size=lg]/menu-button:top-2.5 tw:peer-data-[size=sm]/menu-button:top-1 tw:peer-data-active/menu-button:text-sidebar-accent-foreground",t),...r})}function Ks({className:t,showIcon:r=!1,...a}){const[o]=l.useState(()=>`${Math.floor(Math.random()*40)+50}%`),i={"--skeleton-width":o};return e.jsxs("div",{"data-slot":"sidebar-menu-skeleton","data-sidebar":"menu-skeleton",className:n.cn("tw:flex tw:h-8 tw:items-center tw:gap-2 tw:rounded-md tw:px-2",t),...a,children:[r&&e.jsx(n.Skeleton,{className:"tw:size-4 tw:rounded-md","data-sidebar":"menu-skeleton-icon"}),e.jsx(n.Skeleton,{className:"tw:h-4 tw:max-w-(--skeleton-width) tw:flex-1","data-sidebar":"menu-skeleton-text",style:i})]})}function Us({className:t,...r}){return e.jsx("ul",{"data-slot":"sidebar-menu-sub","data-sidebar":"menu-sub",className:n.cn("tw:mx-3.5 tw:flex tw:min-w-0 tw:translate-x-px tw:rtl:-translate-x-px tw:flex-col tw:gap-1 tw:border-s tw:border-sidebar-border tw:px-2.5 tw:py-0.5 tw:group-data-[collapsible=icon]:hidden",t),...r})}function qs({className:t,...r}){return e.jsx("li",{"data-slot":"sidebar-menu-sub-item","data-sidebar":"menu-sub-item",className:n.cn("tw:group/menu-sub-item tw:relative",t),...r})}function Hs({asChild:t=!1,size:r="md",isActive:a=!1,className:o,...i}){const s=t?D.Slot.Root:"a";return e.jsx(s,{"data-slot":"sidebar-menu-sub-button","data-sidebar":"menu-sub-button","data-size":r,"data-active":a,className:n.cn("tw:flex tw:h-7 tw:min-w-0 tw:-translate-x-px tw:rtl:translate-x-px tw:items-center tw:gap-2 tw:overflow-hidden tw:rounded-md tw:px-2 tw:text-sidebar-foreground tw:ring-sidebar-ring tw:outline-hidden tw:group-data-[collapsible=icon]:hidden tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:active:bg-sidebar-accent tw:active:text-sidebar-accent-foreground tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-disabled:pointer-events-none tw:aria-disabled:opacity-50 tw:data-[size=md]:text-sm tw:data-[size=sm]:text-xs tw:data-active:bg-sidebar-accent tw:data-active:text-sidebar-accent-foreground tw:[&>span:last-child]:truncate tw:[&>svg]:size-4 tw:[&>svg]:shrink-0 tw:[&>svg]:text-sidebar-accent-foreground",o),...i})}function No({id:t,extensionLabels:r,projectInfo:a,handleSelectSidebarItem:o,selectedSidebarItem:i,extensionsSidebarGroupLabel:s,projectsSidebarGroupLabel:c,buttonPlaceholderText:d,className:u}){const w=l.useCallback((h,m)=>{o(h,m)},[o]),p=l.useCallback(h=>{const m=a.find(k=>k.projectId===h);return m?m.projectName:h},[a]),g=l.useMemo(()=>a.map(h=>({id:h.projectId,shortName:h.projectName,fullName:h.projectName})),[a]),f=l.useCallback(h=>!i.projectId&&h===i.label,[i]);return e.jsx(xo,{id:t,collapsible:"none",variant:"inset",className:n.cn("tw:w-96 tw:gap-2 tw:overflow-y-auto",u),children:e.jsxs(yo,{children:[e.jsxs(kr,{children:[e.jsx(yr,{className:"tw:text-sm",children:s}),e.jsx(_r,{children:e.jsx(_o,{children:Object.entries(r).map(([h,m])=>e.jsx(jo,{children:e.jsx(Co,{onClick:()=>w(h),isActive:f(h),children:e.jsx("span",{className:"tw:pl-3",children:m})})},h))})})]}),e.jsxs(kr,{children:[e.jsx(yr,{className:"tw:text-sm",children:c}),e.jsx(_r,{className:"tw:pl-3",children:e.jsxs("div",{className:n.cn("tw:flex tw:w-full tw:items-center tw:gap-2 tw:rounded-md tw:px-2 tw:py-1",{"tw:bg-sidebar-accent tw:text-sidebar-accent-foreground":i==null?void 0:i.projectId}),children:[e.jsx(R.ScrollText,{className:"tw:h-4 tw:w-4 tw:shrink-0"}),e.jsx(n.ProjectSelector,{mode:"project",projects:g,openTabs:[],selection:{projectId:(i==null?void 0:i.projectId)??""},onChangeSelection:({projectId:h})=>{if(!h)return;const m=p(h);w(m,h)},buttonVariant:"ghost",buttonClassName:"tw:h-8 tw:w-full tw:flex-1 tw:justify-start tw:font-normal",buttonPlaceholder:d,ariaLabel:c,popoverContentStyle:{zIndex:n.Z_INDEX_OVERLAY}})]})})]})]})})}function Ys({id:t,extensionLabels:r,projectInfo:a,children:o,handleSelectSidebarItem:i,selectedSidebarItem:s,searchValue:c,onSearch:d,extensionsSidebarGroupLabel:u,projectsSidebarGroupLabel:w,buttonPlaceholderText:p}){return e.jsxs("div",{className:"tw:box-border tw:flex tw:h-full tw:flex-col",children:[e.jsx("div",{className:"tw:box-border tw:flex tw:items-center tw:justify-center tw:py-4",children:e.jsx(n.SearchBar,{className:"tw:w-9/12",value:c,onSearch:d,placeholder:"Search app settings, extension settings, and project settings"})}),e.jsxs(bo,{id:t,className:"tw:h-full tw:flex-1 tw:gap-4 tw:overflow-auto tw:border-t",children:[e.jsx(No,{className:"tw:w-1/2 tw:min-w-[140px] tw:max-w-[220px] tw:border-e",extensionLabels:r,projectInfo:a,handleSelectSidebarItem:i,selectedSidebarItem:s,extensionsSidebarGroupLabel:u,projectsSidebarGroupLabel:w,buttonPlaceholderText:p}),e.jsx(ko,{className:"tw:min-w-[215px]",children:o})]})]})}const ie="scrBook",Xs="scrRef",we="source",Zs="details",Ws="Scripture Reference",Js="Scripture Book",Eo="Type",Qs="Details";function tc(t,r){const a=r??!1;return[{accessorFn:o=>`${o.start.book} ${o.start.chapterNum}:${o.start.verseNum}`,id:ie,header:(t==null?void 0:t.scriptureReferenceColumnName)??Ws,cell:o=>{const i=o.row.original;return o.row.getIsGrouped()?ht.Canon.bookIdToEnglishName(i.start.book):o.row.groupingColumnId===ie?M.formatScrRef(i.start):void 0},getGroupingValue:o=>ht.Canon.bookIdToNumber(o.start.book),sortingFn:(o,i)=>M.compareScrRefs(o.original.start,i.original.start),enableGrouping:!0},{accessorFn:o=>M.formatScrRef(o.start),id:Xs,header:void 0,cell:o=>{const i=o.row.original;return o.row.getIsGrouped()?void 0:M.formatScrRef(i.start)},sortingFn:(o,i)=>M.compareScrRefs(o.original.start,i.original.start),enableGrouping:!1},{accessorFn:o=>o.source.displayName,id:we,header:a?(t==null?void 0:t.typeColumnName)??Eo:void 0,cell:o=>a||o.row.getIsGrouped()?o.getValue():void 0,getGroupingValue:o=>o.source.id,sortingFn:(o,i)=>o.original.source.displayName.localeCompare(i.original.source.displayName),enableGrouping:!0},{accessorFn:o=>o.detail,id:Zs,header:(t==null?void 0:t.detailsColumnName)??Qs,cell:o=>o.getValue(),enableGrouping:!1}]}const ec=t=>{if(!("offset"in t.start))throw new Error("No offset available in range start");if(t.end&&!("offset"in t.end))throw new Error("No offset available in range end");const{offset:r}=t.start;let a=0;return t.end&&({offset:a}=t.end),!t.end||M.compareScrRefs(t.start,t.end)===0?`${M.scrRefToBBBCCCVVV(t.start)}+${r}`:`${M.scrRefToBBBCCCVVV(t.start)}+${r}-${M.scrRefToBBBCCCVVV(t.end)}+${a}`},pa=t=>`${ec({start:t.start,end:t.end})} ${t.source.displayName} ${t.detail}`;function rc({sources:t,showColumnHeaders:r=!1,showSourceColumn:a=!1,scriptureReferenceColumnName:o,scriptureBookGroupName:i,typeColumnName:s,detailsColumnName:c,onRowSelected:d,id:u}){const[w,p]=l.useState([]),[g,f]=l.useState([{id:ie,desc:!1}]),[h,m]=l.useState({}),k=l.useMemo(()=>t.flatMap(j=>j.data.map(V=>({...V,source:j.source}))),[t]),b=l.useMemo(()=>tc({scriptureReferenceColumnName:o,typeColumnName:s,detailsColumnName:c},a),[o,s,c,a]);l.useEffect(()=>{w.includes(we)?f([{id:we,desc:!1},{id:ie,desc:!1}]):f([{id:ie,desc:!1}])},[w]);const C=It.useReactTable({data:k,columns:b,state:{grouping:w,sorting:g,rowSelection:h},onGroupingChange:p,onSortingChange:f,onRowSelectionChange:m,getExpandedRowModel:It.getExpandedRowModel(),getGroupedRowModel:It.getGroupedRowModel(),getCoreRowModel:It.getCoreRowModel(),getSortedRowModel:It.getSortedRowModel(),getRowId:pa,autoResetExpanded:!1,enableMultiRowSelection:!1,enableSubRowSelection:!1});l.useEffect(()=>{if(d){const j=C.getSelectedRowModel().rowsById,V=Object.keys(j);if(V.length===1){const z=k.find(N=>pa(N)===V[0])||void 0;z&&d(z)}}},[h,k,d,C]);const y=i??Js,_=s??Eo,B=[{label:"No Grouping",value:[]},{label:`Group by ${y}`,value:[ie]},{label:`Group by ${_}`,value:[we]},{label:`Group by ${y} and ${_}`,value:[ie,we]},{label:`Group by ${_} and ${y}`,value:[we,ie]}],F=j=>{p(JSON.parse(j))},E=(j,V)=>{!j.getIsGrouped()&&!j.getIsSelected()&&j.getToggleSelectedHandler()(V)},P=(j,V)=>j.getIsGrouped()?"":n.cn("banded-row",V%2===0?"even":"odd"),A=(j,V,z)=>{if(!((j==null?void 0:j.length)===0||V.depth{F(j)},children:[e.jsx(ge,{className:"tw:mb-1 tw:mt-2",children:e.jsx(pe,{})}),e.jsx(he,{position:"item-aligned",children:e.jsx(ro,{children:B.map(j=>e.jsx(Ut,{value:JSON.stringify(j.value),children:j.label},j.label))})})]}),e.jsxs(n.Table,{className:"tw:relative tw:flex tw:flex-col tw:overflow-y-auto tw:p-0",children:[r&&e.jsx(n.TableHeader,{children:C.getHeaderGroups().map(j=>e.jsx(n.TableRow,{children:j.headers.filter(V=>V.column.columnDef.header).map(V=>e.jsx(n.TableHead,{colSpan:V.colSpan,className:"tw:sticky top-0",children:V.isPlaceholder?void 0:e.jsxs("div",{children:[V.column.getCanGroup()?e.jsx(n.Button,{variant:"ghost",title:`Toggle grouping by ${V.column.columnDef.header}`,onClick:V.column.getToggleGroupingHandler(),type:"button",children:V.column.getIsGrouped()?"🛑":"👊 "}):void 0," ",It.flexRender(V.column.columnDef.header,V.getContext())]})},V.id))},j.id))}),e.jsx(n.TableBody,{children:C.getRowModel().rows.map((j,V)=>{const z=n.readDirection();return e.jsx(n.TableRow,{"data-state":j.getIsSelected()?"selected":"",className:n.cn(P(j,V)),onClick:N=>E(j,N),children:j.getVisibleCells().map(N=>{if(!(N.getIsPlaceholder()||N.column.columnDef.enableGrouping&&!N.getIsGrouped()&&(N.column.columnDef.id!==we||!a)))return e.jsx(n.TableCell,{className:n.cn(N.column.columnDef.id,"tw:p-[1px]",A(w,j,N)),children:N.getIsGrouped()?e.jsxs(n.Button,{variant:"link",onClick:j.getToggleExpandedHandler(),type:"button",children:[j.getIsExpanded()&&e.jsx(R.ChevronDown,{}),!j.getIsExpanded()&&(z==="ltr"?e.jsx(R.ChevronRight,{}):e.jsx(R.ChevronLeft,{}))," ",It.flexRender(N.column.columnDef.cell,N.getContext())," (",j.subRows.length,")"]}):It.flexRender(N.column.columnDef.cell,N.getContext())},N.id)})},j.id)})})]})]})}function So(t){if(t.length!==ht.Canon.allBookIds.length)throw new Error("availableBookInfo length must match Canon.allBookIds length");return ht.Canon.allBookIds.filter((r,a)=>t[a]==="1"&&!ht.Canon.isObsolete(ht.Canon.bookIdToNumber(r)))}function $r(t,r){return t.filter(a=>{try{return M.getSectionForBook(a)===r}catch{return!1}})}const To=(t,r,a)=>$r(t,r).every(o=>a.includes(o));function Mo({availableBookInfo:t,selectedBookIds:r,onChangeSelectedBookIds:a,localizedStrings:o,localizedBookNames:i}){const s=o["%webView_book_selector_books_selected%"],c=o["%webView_book_selector_select_books%"],d=o["%webView_book_selector_search_books%"],u=o["%webView_book_selector_select_all%"],w=o["%webView_book_selector_clear_all%"],p=o["%webView_book_selector_no_book_found%"],{otLong:g,ntLong:f,dcLong:h,extraLong:m}={otLong:o==null?void 0:o["%scripture_section_ot_long%"],ntLong:o==null?void 0:o["%scripture_section_nt_long%"],dcLong:o==null?void 0:o["%scripture_section_dc_long%"],extraLong:o==null?void 0:o["%scripture_section_extra_long%"]},[k,b]=l.useState(!1),[C,y]=l.useState(""),_=l.useRef(void 0),B=l.useRef(!1),F=l.useMemo(()=>So(t),[t]),E=l.useMemo(()=>{if(!C.trim()){const U={[M.Section.OT]:[],[M.Section.NT]:[],[M.Section.DC]:[],[M.Section.Extra]:[]};return F.forEach(G=>{const I=M.getSectionForBook(G);U[I].push(G)}),U}const N=F.filter(U=>n.doesBookMatchQuery(U,C,i)),H={[M.Section.OT]:[],[M.Section.NT]:[],[M.Section.DC]:[],[M.Section.Extra]:[]};return N.forEach(U=>{const G=M.getSectionForBook(U);H[G].push(U)}),H},[F,C,i]),P=l.useCallback((N,H=!1)=>{if(!H||!_.current){a(r.includes(N)?r.filter(W=>W!==N):[...r,N]),_.current=N;return}const U=F.findIndex(W=>W===_.current),G=F.findIndex(W=>W===N);if(U===-1||G===-1)return;const[I,T]=[Math.min(U,G),Math.max(U,G)],Z=F.slice(I,T+1).map(W=>W);a(r.includes(N)?r.filter(W=>!Z.includes(W)):[...new Set([...r,...Z])])},[r,a,F]),A=N=>{P(N,B.current),B.current=!1},j=(N,H)=>{N.preventDefault(),P(H,N.shiftKey)},V=()=>{a(F.map(N=>N))},z=()=>{a([])};return e.jsxs(n.Popover,{open:k,onOpenChange:N=>{b(N),N||y("")},children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"outline",role:"combobox","aria-expanded":k,className:"tw:max-w-64 tw:justify-between",children:[r.length>0?`${s}: ${r.length}`:c,e.jsx(R.ChevronsUpDown,{className:"tw:ml-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})}),e.jsx(n.PopoverContent,{className:"tw:w-[500px] tw:max-w-[calc(100vw-2rem)] tw:p-0",align:"start",children:e.jsxs(n.Command,{shouldFilter:!1,onKeyDown:N=>{N.key==="Enter"&&(B.current=N.shiftKey)},children:[e.jsx(n.CommandInput,{placeholder:d,value:C,onValueChange:y}),e.jsxs("div",{className:"tw:flex tw:justify-between tw:border-b tw:p-2",children:[e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:V,children:u}),e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:z,children:w})]}),e.jsxs(n.CommandList,{children:[e.jsx(n.CommandEmpty,{children:p}),Object.values(M.Section).map((N,H)=>{const U=E[N];if(U.length!==0)return e.jsxs(l.Fragment,{children:[e.jsx(n.CommandGroup,{heading:n.getSectionLongName(N,g,f,h,m),children:U.map(G=>e.jsx(va,{bookId:G,isSelected:r.includes(G),onSelect:()=>A(G),onMouseDown:I=>j(I,G),section:M.getSectionForBook(G),showCheck:!0,localizedBookNames:i,commandValue:ba(G,i),className:"tw:flex tw:items-center"},G))}),Ho(t),className:n.cn(To(r,t,a)&&!s&&"tw:bg-primary tw:text-primary-foreground tw:hover:bg-primary/70 tw:hover:text-primary-foreground"),disabled:s,children:n.getSectionShortName(t,c,d,u,w)})}const ga=5,gr=6;function Ro({availableBookInfo:t,selectedBookIds:r,onChangeSelectedBookIds:a,localizedStrings:o,localizedBookNames:i}){const s=o["%webView_book_selector_more%"],c=l.useMemo(()=>So(t),[t]),d=l.useCallback(u=>{const w=$r(c,u).map(p=>p);a(To(c,u,r)?r.filter(p=>!w.includes(p)):[...new Set([...r,...w])])},[r,a,c]);return e.jsxs("div",{className:"tw:space-y-2",children:[e.jsx("div",{className:"tw:flex tw:flex-wrap tw:gap-2",children:Object.values(M.Section).map(u=>e.jsx(ac,{section:u,availableBookIds:c,selectedBookIds:r,onToggle:d,localizedStrings:o},u))}),e.jsx(Mo,{availableBookInfo:t,selectedBookIds:r,onChangeSelectedBookIds:a,localizedStrings:o,localizedBookNames:i}),r.length>0&&e.jsxs("div",{className:"tw:mt-2 tw:flex tw:flex-wrap tw:gap-1",children:[r.slice(0,r.length===gr?gr:ga).map(u=>e.jsx(n.Badge,{className:"tw:hover:bg-secondary",variant:"secondary",children:n.getLocalizedBookName(u,i)},u)),r.length>gr&&e.jsx(n.Badge,{className:"tw:hover:bg-secondary",variant:"secondary",children:`+${r.length-ga} ${s}`})]})]})}const Do=Object.freeze(["%webView_book_selector_books_selected%","%webView_book_selector_select_books%","%webView_book_selector_search_books%","%webView_book_selector_select_all%","%webView_book_selector_clear_all%","%webView_book_selector_no_book_found%","%webView_book_selector_more%","%scripture_section_ot_long%","%scripture_section_ot_short%","%scripture_section_nt_long%","%scripture_section_nt_short%","%scripture_section_dc_long%","%scripture_section_dc_short%","%scripture_section_extra_long%","%scripture_section_extra_short%"]),oc=Object.freeze(["%webView_scope_selector_selected_text%","%webView_scope_selector_verse%","%webView_scope_selector_chapter%","%webView_scope_selector_book%","%webView_scope_selector_current_verse%","%webView_scope_selector_current_chapter%","%webView_scope_selector_current_book%","%webView_scope_selector_choose_books%","%webView_scope_selector_scope%","%webView_scope_selector_select_books%","%webView_scope_selector_range%","%webView_scope_selector_select_range%","%webView_scope_selector_range_start%","%webView_scope_selector_range_end%","%webView_scope_selector_ok%","%webView_scope_selector_cancel%","%webView_scope_selector_navigate%",...Do]),kt=(t,r)=>t[r]??r,nc=Object.freeze([" ","-"]);function ic({scope:t,availableScopes:r,onScopeChange:a,availableBookInfo:o,selectedBookIds:i,onSelectedBookIdsChange:s,localizedStrings:c,localizedBookNames:d,id:u,variant:w="radio",rangeStart:p,rangeEnd:g,onRangeStartChange:f,onRangeEndChange:h,currentScrRef:m,onCurrentScrRefChange:k,bookChapterControlLocalizedStrings:b,getEndVerse:C,hideLabel:y=!1,buttonClassName:_}){const B=kt(c,"%webView_scope_selector_selected_text%"),F=kt(c,"%webView_scope_selector_verse%"),E=kt(c,"%webView_scope_selector_chapter%"),P=kt(c,"%webView_scope_selector_book%"),A=kt(c,"%webView_scope_selector_current_verse%"),j=kt(c,"%webView_scope_selector_current_chapter%"),V=kt(c,"%webView_scope_selector_current_book%"),z=kt(c,"%webView_scope_selector_choose_books%"),N=kt(c,"%webView_scope_selector_scope%"),H=kt(c,"%webView_scope_selector_select_books%"),U=kt(c,"%webView_scope_selector_range%"),G=kt(c,"%webView_scope_selector_select_range%"),I=kt(c,"%webView_scope_selector_range_start%"),T=kt(c,"%webView_scope_selector_range_end%"),Z=kt(c,"%webView_scope_selector_ok%"),W=kt(c,"%webView_scope_selector_cancel%"),vt=kt(c,"%webView_scope_selector_navigate%"),bt=$=>{if(!m)return;const X=m.book.toUpperCase();switch($){case"verse":return M.formatScrRef(m,"id");case"chapter":return`${X} ${m.chapterNum}`;case"book":return X;default:return}},Mt=[{value:"selectedText",label:B,id:"scope-selected-text"},{value:"verse",label:F,dropdownLabel:A,scrRefSuffix:bt("verse"),id:"scope-verse"},{value:"chapter",label:E,dropdownLabel:j,scrRefSuffix:bt("chapter"),id:"scope-chapter"},{value:"book",label:P,dropdownLabel:V,scrRefSuffix:bt("book"),id:"scope-book"},{value:"selectedBooks",label:z,id:"scope-selected"},{value:"range",label:U,id:"scope-range"}],K=($,X,$t=!1)=>e.jsxs(e.Fragment,{children:[$,X&&!$t&&e.jsxs("span",{className:"tw:text-muted-foreground",children:[": ",X]})]}),J=r?Mt.filter($=>r.includes($.value)):Mt,st=m??M.defaultScrRef,ot=p??st,gt=g??st,qt=()=>{},et=l.useRef(null),Rt=l.useRef(null),yt=l.useRef(!1),Bt=l.useRef(null),Ht=l.useRef(!1),[O,Pt]=l.useState(void 0),ft=l.useRef(!1),xt=l.useRef(!1),Vt=l.useRef(null),te=l.useCallback($=>{if($){Pt("start"),ft.current=!1;return}Pt(X=>X==="start"?void 0:X),ft.current&&(ft.current=!1,requestAnimationFrame(()=>{var $t;const X=($t=et.current)==null?void 0:$t.querySelector("button");X==null||X.click()}))},[]),Yt=l.useCallback($=>{if($){Pt("end"),xt.current=!1;return}Pt(X=>X==="end"?void 0:X)},[]),L=l.useCallback($=>{f==null||f($),h==null||h($),ft.current=!0},[f,h]),Y=l.useCallback($=>{h==null||h($),xt.current=!0},[h]),rt=l.useCallback($=>{a($),$==="selectedBooks"&&i.length===0&&(m!=null&&m.book)&&s([m.book])},[a,i,m,s]),Q=J.find($=>$.value===t),ct=()=>t==="selectedBooks"&&i.length>0?i.map($=>$.toUpperCase()).join(", "):t==="range"?M.formatScrRefRange(ot,gt,{optionOrLocalizedBookName:"id",endRefOptionOrLocalizedBookName:"id",repeatBookName:!0}):Q?K(Q.label,Q.scrRefSuffix):t,nt=J.filter($=>$.value!=="selectedBooks"&&$.value!=="range"),wt=J.find($=>$.value==="selectedBooks"),lt=J.find($=>$.value==="range"),[ut,_t]=l.useState(!1),[jt,At]=l.useState(void 0),[Ct,ae]=l.useState(void 0),[S,Nt]=l.useState(void 0),[mt,Xt]=l.useState(void 0),[oe,_e]=l.useState([]),je=w==="dropdown"&&jt==="selectedBooks",Ce=e.jsx(Ro,{availableBookInfo:o,selectedBookIds:je?oe:i,onChangeSelectedBookIds:je?_e:s,localizedStrings:c,localizedBookNames:d}),Ie=O==="end",Ae=O==="start",fe="tw:text-muted-foreground",x=w==="dropdown"&&jt==="range",q=x?Nt:L,Dt=x?Xt:h?Y:qt,ee=e.jsxs("div",{className:"tw:flex tw:flex-wrap tw:items-end tw:gap-4",children:[e.jsxs("div",{className:"tw:grid tw:gap-2",children:[e.jsx(n.Label,{htmlFor:"scope-range-start",className:n.cn(Ie&&fe),children:I}),e.jsx(Ge,{id:"scope-range-start",scrRef:x?S??ot:ot,handleSubmit:q,localizedBookNames:d,localizedStrings:b,getEndVerse:C,submitKeys:nc,onOpenChange:te,className:n.cn(Ie&&fe),modal:!0})]}),e.jsxs("div",{ref:et,className:"tw:grid tw:gap-2",children:[e.jsx(n.Label,{htmlFor:"scope-range-end",className:n.cn(Ae&&fe),children:T}),e.jsx(Ge,{id:"scope-range-end",scrRef:x?mt??gt:gt,handleSubmit:Dt,localizedBookNames:d,localizedStrings:b,getEndVerse:C,disableReferencesUpTo:x?S??ot:ot,onOpenChange:Yt,onCloseAutoFocus:$=>{var X;xt.current&&(xt.current=!1,$.preventDefault(),(X=Vt.current)==null||X.focus())},className:n.cn(Ae&&fe),modal:!0,align:"start"})]})]}),ce=l.useRef({}),ne=l.useCallback($=>X=>{ce.current[$]=X},[]),Et=l.useRef(null);l.useEffect(()=>{if(!ut)return;let $=0;const X=requestAnimationFrame(()=>{$=requestAnimationFrame(()=>{var $t;($t=ce.current[t])==null||$t.focus()})});return()=>{cancelAnimationFrame(X),$&&cancelAnimationFrame($)}},[ut,t]);const[pt,St]=l.useState(null),[dt,Ft]=l.useState(null),[Lt,le]=l.useState(null),Fo=200,[Go,Ko]=l.useState(!1);l.useEffect(()=>{if(!Lt||typeof ResizeObserver>"u")return;const $=new ResizeObserver(([X])=>{Ko(X.contentRect.width$.disconnect()},[Lt]);const Vr=l.useCallback($=>{ae($),Nt(ot),Xt(gt),_e(i),_t(!1),At($)},[ot,gt,i]),Fr=l.useCallback(()=>{Ct!==void 0&&(Ct==="range"?(S&&(f==null||f(S)),mt&&(h==null||h(mt))):Ct==="selectedBooks"&&s(oe),rt(Ct),At(void 0),ae(void 0))},[Ct,S,mt,oe,f,h,s,rt]),$e=l.useCallback($=>{$||(At(void 0),ae(void 0))},[]),Gr=l.useCallback($=>{var X;$.preventDefault(),(X=Et.current)==null||X.focus()},[]),Kr=$=>t===$?e.jsx("span",{className:"tw:absolute tw:flex tw:h-3.5 tw:w-3.5 tw:items-center tw:justify-center tw:ltr:left-2 tw:rtl:right-2",children:e.jsx(R.Check,{className:"tw:h-4 tw:w-4"})}):void 0;return e.jsxs("div",{id:u,className:"tw:grid tw:gap-4",children:[e.jsxs("div",{className:"tw:grid tw:gap-2",children:[!y&&e.jsx(n.Label,{children:N}),w==="dropdown"?e.jsxs(n.DropdownMenu,{open:ut,onOpenChange:_t,children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsxs(n.Button,{ref:Et,variant:"outline",role:"combobox",className:n.cn("tw:w-full tw:justify-between tw:overflow-hidden tw:font-normal",_),children:[e.jsx("span",{className:"tw:min-w-0 tw:flex-1 tw:truncate tw:text-start",children:ct()}),e.jsx(R.ChevronDown,{className:"tw:ms-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})}),e.jsx(n.DropdownMenuContent,{ref:le,className:"tw:w-[var(--radix-dropdown-menu-trigger-width)] tw:min-w-[12rem]",align:"start",children:e.jsxs(n.PopoverPortalContainerProvider,{container:Lt,children:[nt.map(({value:$,label:X,dropdownLabel:$t,scrRefSuffix:Ne,id:Uo})=>e.jsxs(n.DropdownMenuItem,{ref:ne($),className:"tw:relative tw:ps-8 data-[highlighted]:tw:bg-accent data-[highlighted]:tw:text-accent-foreground",onSelect:()=>rt($),"data-selected":t===$?"true":void 0,children:[t===$&&e.jsx("span",{className:"tw:absolute tw:flex tw:h-3.5 tw:w-3.5 tw:items-center tw:justify-center tw:ltr:left-2 tw:rtl:right-2",children:e.jsx(R.Check,{className:"tw:h-4 tw:w-4"})}),K($t??X,Ne,Go)]},Uo)),(wt||lt)&&e.jsx(n.DropdownMenuSeparator,{}),wt&&e.jsxs(n.DropdownMenuItem,{ref:ne("selectedBooks"),className:n.cn("tw:relative tw:ps-8","data-[highlighted]:tw:bg-accent data-[highlighted]:tw:text-accent-foreground"),onSelect:()=>Vr("selectedBooks"),"data-selected":t==="selectedBooks"?"true":void 0,children:[Kr("selectedBooks"),`${wt.label}…`]}),lt&&e.jsxs(n.DropdownMenuItem,{ref:ne("range"),className:n.cn("tw:relative tw:ps-8","data-[highlighted]:tw:bg-accent data-[highlighted]:tw:text-accent-foreground"),onSelect:()=>Vr("range"),"data-selected":t==="range"?"true":void 0,children:[Kr("range"),`${lt.label}…`]}),k&&e.jsxs(e.Fragment,{children:[e.jsx(n.DropdownMenuSeparator,{}),e.jsx(n.DropdownMenuLabel,{className:"tw:px-2 tw:py-1.5 tw:text-xs tw:font-medium tw:text-muted-foreground",children:vt}),e.jsx(n.DropdownMenuItem,{ref:Bt,className:"tw:p-0",onSelect:$=>{var X,$t;if($.preventDefault(),yt.current){yt.current=!1;return}Ht.current||($t=(X=Rt.current)==null?void 0:X.querySelector("button"))==null||$t.click()},children:e.jsx("div",{ref:Rt,className:"tw:w-full tw:px-1 tw:pb-1",onPointerDownCapture:$=>{const X=$.target instanceof HTMLElement?$.target:void 0;X!=null&&X.closest("button")&&(yt.current=!0,requestAnimationFrame(()=>{yt.current=!1}))},children:e.jsx(Ge,{id:"scope-navigate",scrRef:m??M.defaultScrRef,handleSubmit:k,localizedBookNames:d,localizedStrings:b,getEndVerse:C,triggerVariant:"ghost",onOpenChange:$=>{Ht.current=$},onCloseAutoFocus:$=>{var X;$.preventDefault(),(X=Bt.current)==null||X.focus()},modal:!0,className:"tw:w-full tw:min-w-0 tw:max-w-none tw:justify-between tw:px-2 tw:font-normal",triggerContent:e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"tw:min-w-0 tw:flex-1 tw:truncate tw:text-start",children:M.formatScrRef(m??M.defaultScrRef,"id")}),e.jsx(R.ChevronDown,{className:"tw:ms-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})})})})]})]})})]}):e.jsx(rr,{value:t,onValueChange:rt,className:"tw:flex tw:flex-col tw:space-y-1",children:J.map(({value:$,label:X,scrRefSuffix:$t,id:Ne})=>e.jsxs("div",{className:"tw:flex tw:items-center",children:[e.jsx(Re,{className:"tw:me-2",value:$,id:Ne}),e.jsx(n.Label,{htmlFor:Ne,children:K(X,$t)})]},Ne))})]}),w==="radio"&&t==="selectedBooks"&&e.jsxs("div",{className:"tw:grid tw:gap-2",children:[e.jsx(n.Label,{children:H}),Ce]}),w==="radio"&&t==="range"&&ee,w==="dropdown"&&wt&&e.jsx(n.Dialog,{open:jt==="selectedBooks",onOpenChange:$e,children:e.jsx(n.DialogContent,{ref:Ft,onCloseAutoFocus:Gr,onEscapeKeyDown:$=>{dt!=null&&dt.querySelector('[data-state="open"]')&&$.preventDefault()},children:e.jsxs(n.PopoverPortalContainerProvider,{container:dt,children:[e.jsx(n.DialogHeader,{className:"tw:pe-8",children:e.jsx(n.DialogTitle,{children:z})}),Ce,e.jsxs(n.DialogFooter,{children:[e.jsx(n.Button,{variant:"outline",onClick:()=>$e(!1),children:W}),e.jsx(n.Button,{onClick:Fr,children:Z})]})]})})}),w==="dropdown"&<&&e.jsx(n.Dialog,{open:jt==="range",onOpenChange:$e,children:e.jsx(n.DialogContent,{ref:St,onCloseAutoFocus:Gr,onEscapeKeyDown:$=>{pt!=null&&pt.querySelector('[data-state="open"]')&&$.preventDefault()},children:e.jsxs(n.PopoverPortalContainerProvider,{container:pt,children:[e.jsx(n.DialogHeader,{className:"tw:pe-8",children:e.jsx(n.DialogTitle,{children:G})}),ee,e.jsxs(n.DialogFooter,{children:[e.jsx(n.Button,{variant:"outline",onClick:()=>$e(!1),children:W}),e.jsx(n.Button,{ref:Vt,onClick:Fr,children:Z})]})]})})})]})}function sc({availableScrollGroupIds:t,scrollGroupId:r,onChangeScrollGroupId:a,localizedStrings:o={},size:i="sm",className:s,id:c,disabled:d}){const u={...n.Ye,...Object.fromEntries(Object.entries(o).map(([p,g])=>[p,p===g&&p in n.Ye?n.Ye[p]:g]))},w=n.readDirection();return e.jsxs(ue,{value:`${r}`,onValueChange:p=>a(p==="undefined"?void 0:parseInt(p,10)),disabled:d,children:[e.jsx(ge,{size:i,className:n.cn("pr-twp tw:w-auto",s),children:e.jsx(pe,{placeholder:u[M.getLocalizeKeyForScrollGroupId(r)]??r})}),e.jsx(he,{id:c,align:w==="rtl"?"end":"start",style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:t.map(p=>e.jsx(Ut,{value:`${p}`,children:u[M.getLocalizeKeyForScrollGroupId(p)]},`${p}`))})]})}function cc({children:t}){return e.jsx("div",{className:"pr-twp tw:grid",children:t})}function lc({primary:t,secondary:r,children:a,isLoading:o=!1,loadingMessage:i}){return e.jsxs("div",{className:"tw:flex tw:items-center tw:justify-between tw:space-x-4 tw:py-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"tw:text-sm tw:font-medium tw:leading-none",children:t}),e.jsx("p",{className:"tw:whitespace-normal tw:break-words tw:text-sm tw:text-muted-foreground",children:r})]}),o?e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:i}):e.jsx("div",{children:a})]})}function dc({primary:t,secondary:r,includeSeparator:a=!1}){return e.jsxs("div",{className:"tw:space-y-4 tw:py-2",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"tw:text-lg tw:font-medium",children:t}),e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:r})]}),a?e.jsx(n.Separator,{}):""]})}function Oo(t,r){var a;return(a=Object.entries(t).find(([,o])=>"menuItem"in o&&o.menuItem===r))==null?void 0:a[0]}function Qe({icon:t,menuLabel:r,leading:a}){return t?e.jsx("img",{className:n.cn("tw:max-h-5 tw:max-w-5",a?"tw:me-2":"tw:ms-2"),src:t,alt:`${a?"Leading":"Trailing"} icon for ${r}`}):void 0}const zo=(t,r,a,o)=>a?Object.entries(t).filter(([s,c])=>"column"in c&&c.column===a||s===a).sort(([,s],[,c])=>s.order-c.order).flatMap(([s])=>r.filter(d=>d.group===s).sort((d,u)=>d.order-u.order).map(d=>e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:"command"in d?e.jsxs(n.DropdownMenuItem,{onClick:()=>{o(d)},children:[d.iconPathBefore&&e.jsx(Qe,{icon:d.iconPathBefore,menuLabel:d.label,leading:!0}),d.label,d.iconPathAfter&&e.jsx(Qe,{icon:d.iconPathAfter,menuLabel:d.label})]},`dropdown-menu-item-${d.label}-${d.command}`):e.jsxs(n.DropdownMenuSub,{children:[e.jsx(n.DropdownMenuSubTrigger,{children:d.label}),e.jsx(n.DropdownMenuPortal,{children:e.jsx(n.DropdownMenuSubContent,{children:zo(t,r,Oo(t,d.id),o)})})]},`dropdown-menu-sub-${d.label}-${d.id}`)}),d.tooltip&&e.jsx(n.TooltipContent,{children:d.tooltip})]},`tooltip-${d.label}-${"command"in d?d.command:d.id}`))):void 0;function tr({onSelectMenuItem:t,menuData:r,tabLabel:a,icon:o,className:i,variant:s,buttonVariant:c="ghost",id:d}){return e.jsxs(n.DropdownMenu,{variant:s,children:[e.jsx(n.DropdownMenuTrigger,{"aria-label":a,className:i,asChild:!0,id:d,children:e.jsx(n.Button,{variant:c,size:"icon",children:o??e.jsx(R.MenuIcon,{})})}),e.jsx(n.DropdownMenuContent,{align:"start",style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:Object.entries(r.columns).filter(([,u])=>typeof u=="object").sort(([,u],[,w])=>typeof u=="boolean"||typeof w=="boolean"?0:u.order-w.order).map(([u],w,p)=>e.jsxs(l.Fragment,{children:[e.jsx(n.DropdownMenuGroup,{children:e.jsx(n.TooltipProvider,{children:zo(r.groups,r.items,u,t)})}),we.jsx("div",{ref:o,className:`tw:sticky tw:top-0 tw:box-border tw:flex tw:h-14 tw:flex-row tw:items-center tw:justify-between tw:gap-2 tw:overflow-clip tw:px-4 tw:py-2 tw:text-foreground tw:@container/toolbar ${r}`,id:t,children:a}));function wc({onSelectProjectMenuItem:t,onSelectViewInfoMenuItem:r,projectMenuData:a,tabViewMenuData:o,id:i,className:s,startAreaChildren:c,centerAreaChildren:d,endAreaChildren:u,menuButtonIcon:w}){return e.jsxs(Io,{className:`tw:w-full tw:border ${s}`,id:i,children:[a&&e.jsx(tr,{onSelectMenuItem:t,menuData:a,tabLabel:"Project",icon:w??e.jsx(R.Menu,{}),buttonVariant:"ghost"}),c&&e.jsx("div",{className:"tw:flex tw:h-full tw:shrink tw:grow-[10] tw:flex-row tw:flex-wrap tw:items-start tw:gap-x-1 tw:gap-y-2 tw:overflow-clip",children:c}),d&&e.jsx("div",{className:"tw:flex tw:h-full tw:shrink tw:grow-[1] tw:basis-0 tw:flex-row tw:flex-wrap tw:items-start tw:justify-center tw:gap-x-1 tw:gap-y-2 tw:overflow-clip tw:@sm:basis-auto",children:d}),e.jsxs("div",{className:"tw:flex tw:h-full tw:shrink tw:grow-[1] tw:flex-row-reverse tw:flex-wrap tw:items-start tw:gap-x-1 tw:gap-y-2 tw:overflow-clip",children:[o&&e.jsx(tr,{onSelectMenuItem:r,menuData:o,tabLabel:"View Info",icon:e.jsx(R.EllipsisVertical,{}),className:"tw:h-full"}),u]})]})}function uc({onSelectProjectMenuItem:t,projectMenuData:r,id:a,className:o,menuButtonIcon:i}){return e.jsx(Io,{className:"tw:pointer-events-none",id:a,children:r&&e.jsx(tr,{onSelectMenuItem:t,menuData:r,tabLabel:"Project",icon:i,className:`tw:pointer-events-auto tw:shadow-lg ${o}`,buttonVariant:"outline"})})}const Br=l.forwardRef(({className:t,...r},a)=>{const o=n.readDirection();return e.jsx(D.Tabs.Root,{orientation:"vertical",ref:a,className:n.cn("tw:flex tw:gap-1 tw:rounded-md tw:text-muted-foreground",t),...r,dir:o})});Br.displayName=D.Tabs.List.displayName;const Pr=l.forwardRef(({className:t,...r},a)=>e.jsx(D.Tabs.List,{ref:a,className:n.cn("tw:flex tw:items-center tw:w-[124px] tw:justify-center tw:rounded-md tw:bg-muted tw:p-1 tw:text-muted-foreground",t),...r}));Pr.displayName=D.Tabs.List.displayName;const Ao=l.forwardRef(({className:t,...r},a)=>e.jsx(D.Tabs.Trigger,{ref:a,...r,className:n.cn("tw:inline-flex tw:w-[116px] tw:cursor-pointer tw:items-center tw:justify-center tw:break-words tw:rounded-sm tw:border-0 tw:bg-muted tw:px-3 tw:py-1.5 tw:text-sm tw:font-medium tw:text-inherit tw:ring-offset-background tw:transition-all tw:hover:text-foreground tw:focus-visible:outline-hidden tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:focus-visible:ring-offset-2 tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:data-[state=active]:bg-background tw:data-[state=active]:text-foreground tw:data-[state=active]:shadow-sm tw:overflow-clip",t)})),Lr=l.forwardRef(({className:t,...r},a)=>e.jsx(D.Tabs.Content,{ref:a,className:n.cn("tw:ms-5 tw:flex-grow tw:text-foreground tw:ring-offset-background tw:focus-visible:outline-hidden tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:focus-visible:ring-offset-2",t),...r}));Lr.displayName=D.Tabs.Content.displayName;function pc({tabList:t,searchValue:r,onSearch:a,searchPlaceholder:o,headerTitle:i,searchClassName:s,id:c}){return e.jsxs("div",{id:c,className:"pr-twp",children:[e.jsxs("div",{className:"tw:sticky tw:top-0 tw:space-y-2 tw:pb-2",children:[i?e.jsx("h1",{children:i}):"",e.jsx(n.SearchBar,{className:s,value:r,onSearch:a,placeholder:o})]}),e.jsxs(Br,{children:[e.jsx(Pr,{children:t.map(d=>e.jsx(Ao,{value:d.value,children:d.value},d.key))}),t.map(d=>e.jsx(Lr,{value:d.value,children:d.content},d.key))]})]})}function gc({className:t,variant:r="default",...a}){const o=l.useMemo(()=>({variant:r}),[r]);return e.jsx(n.MenuContext.Provider,{value:o,children:e.jsx(D.Menubar.Root,{"data-slot":"menubar",className:n.cn("tw:flex tw:h-8 tw:items-center tw:gap-0.5 tw:rounded-lg tw:border tw:p-[3px]",t),...a})})}function hc({...t}){return e.jsx(D.Menubar.Menu,{"data-slot":"menubar-menu",...t})}function fc({...t}){return e.jsx(D.Menubar.Portal,{"data-slot":"menubar-portal",...t})}function mc({className:t,...r}){const a=n.useMenuContext();return e.jsx(D.Menubar.Trigger,{"data-slot":"menubar-trigger",className:n.cn("tw:flex tw:items-center tw:rounded-sm tw:px-1.5 tw:py-[2px] tw:text-sm tw:font-medium tw:outline-hidden tw:select-none tw:hover:bg-muted tw:aria-expanded:bg-muted","pr-twp",n.menuVariants({variant:a.variant,className:t})),...r})}function vc({className:t,align:r="start",alignOffset:a=-4,sideOffset:o=8,...i}){const s=n.useMenuContext();return e.jsx(fc,{children:e.jsx(D.Menubar.Content,{"data-slot":"menubar-content",align:r,alignOffset:a,sideOffset:o,className:n.cn("tw:z-50 tw:min-w-36 tw:origin-(--radix-menubar-content-transform-origin) tw:overflow-hidden tw:rounded-lg tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-md tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150","pr-twp",{"tw:bg-popover":s.variant==="muted"},t),...i})})}function bc({className:t,inset:r,variant:a="default",...o}){const i=n.useMenuContext();return e.jsx(D.Menubar.Item,{"data-slot":"menubar-item","data-inset":r,"data-variant":a,className:n.cn("tw:group/menubar-item tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:not-data-[variant=destructive]:focus:**:text-accent-foreground tw:data-inset:ps-7 tw:data-[variant=destructive]:text-destructive tw:data-[variant=destructive]:focus:bg-destructive/10 tw:data-[variant=destructive]:focus:text-destructive tw:dark:data-[variant=destructive]:focus:bg-destructive/20 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4 tw:data-[variant=destructive]:*:[svg]:text-destructive!",n.menuVariants({variant:i.variant,className:t})),...o})}function xc({className:t,...r}){return e.jsx(D.Menubar.Separator,{"data-slot":"menubar-separator",className:n.cn("tw:-mx-1 tw:my-1 tw:h-px tw:bg-border",t),...r})}function kc({...t}){return e.jsx(D.Menubar.Sub,{"data-slot":"menubar-sub",...t})}function yc({className:t,inset:r,children:a,...o}){const i=n.useMenuContext();return e.jsxs(D.Menubar.SubTrigger,{"data-slot":"menubar-sub-trigger","data-inset":r,className:n.cn("tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-none tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-open:bg-accent tw:data-open:text-accent-foreground tw:[&_svg:not([class*=size-])]:size-4",n.menuVariants({variant:i.variant,className:t})),...o,children:[a,e.jsx(Tt.IconChevronRight,{className:"tw:ms-auto tw:size-4"})]})}function _c({className:t,...r}){const a=n.useMenuContext();return e.jsx(D.Menubar.SubContent,{"data-slot":"menubar-sub-content",className:n.cn("tw:z-50 tw:min-w-32 tw:origin-(--radix-menubar-content-transform-origin) tw:overflow-hidden tw:rounded-lg tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-lg tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",{"tw:bg-popover":a.variant==="muted"},t),...r})}const Se=(t,r)=>{setTimeout(()=>{r.forEach(a=>{var o;(o=t.current)==null||o.dispatchEvent(new KeyboardEvent("keydown",a))})},0)},$o=(t,r,a,o)=>{if(!a)return;const i=Object.entries(t).filter(([s,c])=>"column"in c&&c.column===a||s===a).sort(([,s],[,c])=>s.order-c.order);return i.flatMap(([s],c)=>{const d=r.filter(w=>w.group===s).sort((w,p)=>w.order-p.order).map(w=>e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:"command"in w?e.jsxs(bc,{onClick:()=>{o(w)},children:[w.iconPathBefore&&e.jsx(Qe,{icon:w.iconPathBefore,menuLabel:w.label,leading:!0}),w.label,w.iconPathAfter&&e.jsx(Qe,{icon:w.iconPathAfter,menuLabel:w.label})]},`menubar-item-${w.label}-${w.command}`):e.jsxs(kc,{children:[e.jsx(yc,{children:w.label}),e.jsx(_c,{children:$o(t,r,Oo(t,w.id),o)})]},`menubar-sub-${w.label}-${w.id}`)}),w.tooltip&&e.jsx(n.TooltipContent,{children:w.tooltip})]},`tooltip-${w.label}-${"command"in w?w.command:w.id}`)),u=[...d];return d.length>0&&c{switch(p){case"platform.app":return s;case"platform.window":return c;case"platform.layout":return d;case"platform.help":return u;default:return}};if(Zo.useHotkeys(["alt","alt+p","alt+l","alt+n","alt+h"],(p,g)=>{var m,k,b,C;p.preventDefault();const f={key:"Escape",code:"Escape",keyCode:27,bubbles:!0},h={key:" ",code:"Space",keyCode:32,bubbles:!0};switch(g.hotkey){case"alt":Se(s,[f]);break;case"alt+p":(m=s.current)==null||m.focus(),Se(s,[f,h]);break;case"alt+l":(k=c.current)==null||k.focus(),Se(c,[f,h]);break;case"alt+n":(b=d.current)==null||b.focus(),Se(d,[f,h]);break;case"alt+h":(C=u.current)==null||C.focus(),Se(u,[f,h]);break}}),l.useEffect(()=>{if(!a||!i.current)return;const p=new MutationObserver(h=>{h.forEach(m=>{if(m.attributeName==="data-state"&&m.target instanceof HTMLElement){const k=m.target.getAttribute("data-state");a(k==="open")}})});return i.current.querySelectorAll("[data-state]").forEach(h=>{p.observe(h,{attributes:!0})}),()=>p.disconnect()},[a]),!!t)return e.jsx(gc,{ref:i,className:"pr-twp tw:border-0 tw:bg-transparent",variant:o,children:Object.entries(t.columns).filter(([,p])=>typeof p=="object").sort(([,p],[,g])=>typeof p=="boolean"||typeof g=="boolean"?0:p.order-g.order).map(([p,g])=>e.jsxs(hc,{children:[e.jsx(mc,{ref:w(p),children:typeof g=="object"&&"label"in g&&g.label}),e.jsx(vc,{style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:e.jsx(n.TooltipProvider,{children:$o(t.groups,t.items,p,r)})})]},p))})}function Cc(t){switch(t){case void 0:return;case"darwin":return"tw:ps-[85px]";default:return"tw:pe-[calc(138px+1rem)]"}}function Nc({menuData:t,onOpenChange:r,onSelectMenuItem:a,className:o,id:i,children:s,appMenuAreaChildren:c,configAreaChildren:d,shouldUseAsAppDragArea:u,menubarVariant:w="default"}){const p=l.useRef(void 0);return e.jsx("div",{className:n.cn("tw:border tw:px-4 tw:text-foreground",o),ref:p,style:{position:"relative"},id:i,children:e.jsxs("div",{className:"tw:flex tw:h-full tw:w-full tw:justify-between tw:overflow-hidden",style:u?{WebkitAppRegion:"drag"}:void 0,children:[e.jsx("div",{className:"tw:flex tw:grow tw:basis-0",children:e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",style:u?{WebkitAppRegion:"no-drag"}:void 0,children:[c,t&&e.jsx(jc,{menuData:t,onOpenChange:r,onSelectMenuItem:a,variant:w})]})}),e.jsx("div",{className:"tw:flex tw:items-center tw:gap-2 tw:px-2",style:u?{WebkitAppRegion:"no-drag"}:void 0,children:s}),e.jsx("div",{className:"tw:flex tw:min-w-0 tw:grow tw:basis-0 tw:justify-end",children:e.jsx("div",{className:"tw:flex tw:min-w-0 tw:items-center tw:gap-2 tw:pe-1",style:u?{WebkitAppRegion:"no-drag"}:void 0,children:d})})]})})}const Ec=(t,r)=>t[r]??r;function Sc({knownUiLanguages:t,primaryLanguage:r="en",fallbackLanguages:a=[],onLanguagesChange:o,onPrimaryLanguageChange:i,onFallbackLanguagesChange:s,localizedStrings:c,className:d,id:u}){const w=Ec(c,"%settings_uiLanguageSelector_fallbackLanguages%"),[p,g]=l.useState(!1),f=m=>{i&&i(m),o&&o([m,...a.filter(k=>k!==m)]),s&&a.find(k=>k===m)&&s([...a.filter(k=>k!==m)]),g(!1)},h=(m,k)=>{var C,y,_,B,F,E;const b=k!==m?((y=(C=t[m])==null?void 0:C.uiNames)==null?void 0:y[k])??((B=(_=t[m])==null?void 0:_.uiNames)==null?void 0:B.en):void 0;return b?`${(F=t[m])==null?void 0:F.autonym} (${b})`:(E=t[m])==null?void 0:E.autonym};return e.jsxs("div",{id:u,className:n.cn("pr-twp tw:max-w-sm",d),children:[e.jsxs(ue,{name:"uiLanguage",value:r,onValueChange:f,open:p,onOpenChange:m=>g(m),children:[e.jsx(ge,{children:e.jsx(pe,{})}),e.jsx(he,{style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:Object.keys(t).map(m=>e.jsx(Ut,{value:m,children:h(m,r)},m))})]}),r!=="en"&&e.jsx("div",{className:"tw:pt-3",children:e.jsx(n.Label,{className:"tw:font-normal tw:text-muted-foreground",children:M.formatReplacementString(w,{fallbackLanguages:(a==null?void 0:a.length)>0?a.map(m=>h(m,r)).join(", "):t.en.autonym})})})]})}function Tc({item:t,createLabel:r,createComplexLabel:a}){return r?e.jsx(n.Label,{children:r(t)}):a?e.jsx(n.Label,{children:a(t)}):e.jsx(n.Label,{children:t})}function Bo({id:t,className:r,listItems:a,selectedListItems:o,handleSelectListItem:i,createLabel:s,createComplexLabel:c}){return e.jsx("div",{id:t,className:r,children:a.map(d=>e.jsxs("div",{className:"tw:m-2 tw:flex tw:items-center",children:[e.jsx(Ar,{className:"tw:me-2 tw:align-middle",checked:o.includes(d),onCheckedChange:u=>i(d,u)}),e.jsx(Tc,{item:d,createLabel:s,createComplexLabel:c})]},d))})}const Mc=Bo;function Rc({cardKey:t,isSelected:r,onSelect:a,isDenied:o,isHidden:i=!1,className:s,children:c,selectedButtons:d,hoverButtons:u,dropdownContent:w,additionalContent:p,accentColor:g,showDropdownOnHover:f=!1}){const h=m=>{(m.key==="Enter"||m.key===" ")&&(m.preventDefault(),a())};return e.jsxs("div",{hidden:i,onClick:a,onKeyDown:h,role:"button",tabIndex:0,"aria-pressed":r,className:n.cn("tw:group tw:relative tw:min-w-36 tw:rounded-xl tw:border tw:shadow-none tw:hover:bg-muted/50",{"tw:opacity-50 tw:hover:opacity-100":o&&!r},{"tw:bg-accent":r},{"tw:bg-transparent":!r},s),children:[e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2 tw:p-4",children:[e.jsxs("div",{className:"tw:flex tw:justify-between tw:overflow-hidden",children:[e.jsx("div",{className:"tw:min-w-0 tw:flex-1",children:c}),r&&d,!r&&u&&e.jsx("div",{className:"tw:invisible tw:group-hover:visible",children:u}),!r&&f&&w&&e.jsx("div",{className:"tw:invisible tw:group-hover:visible",children:e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{className:n.cn(g&&"tw:me-1"),asChild:!0,children:e.jsx(n.Button,{className:"tw:m-1 tw:h-6 tw:w-6",variant:"ghost",size:"icon",children:e.jsx(R.MoreVertical,{})})}),e.jsx(n.DropdownMenuContent,{align:"end",children:w})]})}),r&&w&&e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{className:n.cn(g&&"tw:me-1"),asChild:!0,children:e.jsx(n.Button,{className:"tw:m-1 tw:h-6 tw:w-6",variant:"ghost",size:"icon",children:e.jsx(R.MoreVertical,{})})}),e.jsx(n.DropdownMenuContent,{align:"end",children:w})]})]}),p&&e.jsx("div",{className:"tw:w-fit tw:min-w-0 tw:max-w-full tw:overflow-hidden",children:p})]}),g&&e.jsx("div",{className:`tw:absolute tw:right-0 tw:top-0 tw:h-full tw:w-2 tw:rounded-r-xl ${g}`})]},t)}function Dc({message:t,id:r,className:a}){return e.jsx("p",{role:"status","data-testid":r,className:n.cn("tw:text-sm tw:text-muted-foreground",a),children:t})}function Oc({id:t,isDisabled:r=!1,hasError:a=!1,isFullWidth:o=!1,helperText:i,label:s,placeholder:c,isRequired:d=!1,className:u,defaultValue:w,value:p,onChange:g,onFocus:f,onBlur:h}){return e.jsxs("div",{className:n.cn("tw:inline-grid tw:items-center tw:gap-1.5",{"tw:w-full":o}),children:[e.jsx(n.Label,{htmlFor:t,className:n.cn({"tw:text-red-600":a,"tw:hidden":!s}),children:`${s}${d?"*":""}`}),e.jsx(n.Input,{id:t,disabled:r,placeholder:c,required:d,className:n.cn(u,{"tw:border-red-600":a}),defaultValue:w,value:p,onChange:g,onFocus:f,onBlur:h}),e.jsx("p",{className:n.cn({"tw:hidden":!i}),children:i})]})}const zc=er.cva("tw:group/alert tw:relative tw:grid tw:w-full tw:gap-0.5 tw:rounded-lg tw:border tw:px-2.5 tw:py-2 tw:text-start tw:text-sm tw:has-data-[slot=alert-action]:relative tw:has-data-[slot=alert-action]:pe-18 tw:has-[>svg]:grid-cols-[auto_1fr] tw:has-[>svg]:gap-x-2 tw:*:[svg]:row-span-2 tw:*:[svg]:translate-y-0.5 tw:*:[svg]:text-current tw:*:[svg:not([class*=size-])]:size-4 tw:has-[>img]:grid-cols-[auto_1fr] tw:has-[>img]:gap-x-2 tw:*:[img]:row-span-2 tw:*:[img]:translate-y-0.5 tw:*:[img]:text-current tw:*:[img:not([class*=size-])]:size-4",{variants:{variant:{default:"tw:bg-card tw:text-card-foreground",destructive:"tw:bg-card tw:text-destructive tw:*:data-[slot=alert-description]:text-destructive/90 tw:*:[svg]:text-current tw:*:[img]:text-current"}},defaultVariants:{variant:"default"}});function Ic({className:t,variant:r,...a}){return e.jsx("div",{"data-slot":"alert",role:"alert",className:n.cn("pr-twp",zc({variant:r}),t),...a})}function Ac({className:t,...r}){return e.jsx("div",{"data-slot":"alert-title",className:n.cn("tw:font-medium tw:group-has-[>svg]/alert:col-start-2 tw:[&_a]:underline tw:[&_a]:underline-offset-3 tw:[&_a]:hover:text-foreground",t),...r})}function $c({className:t,...r}){return e.jsx("div",{"data-slot":"alert-description",className:n.cn("tw:text-sm tw:text-balance tw:text-muted-foreground tw:md:text-pretty tw:[&_a]:underline tw:[&_a]:underline-offset-3 tw:[&_a]:hover:text-foreground tw:[&_p:not(:last-child)]:mb-4",t),...r})}function Bc({...t}){return e.jsx(D.ContextMenu.Root,{"data-slot":"context-menu",...t})}function Pc({className:t,...r}){return e.jsx(D.ContextMenu.Trigger,{"data-slot":"context-menu-trigger",className:n.cn("tw:select-none",t),...r})}function Lc({...t}){return e.jsx(D.ContextMenu.Group,{"data-slot":"context-menu-group",...t})}function Vc({...t}){return e.jsx(D.ContextMenu.Portal,{"data-slot":"context-menu-portal",...t})}function Fc({...t}){return e.jsx(D.ContextMenu.Sub,{"data-slot":"context-menu-sub",...t})}function Gc({...t}){return e.jsx(D.ContextMenu.RadioGroup,{"data-slot":"context-menu-radio-group",...t})}function Kc({className:t,style:r,...a}){return e.jsx(D.ContextMenu.Portal,{children:e.jsx(D.ContextMenu.Content,{"data-slot":"context-menu-content",className:n.cn("pr-twp tw:max-h-(--radix-context-menu-content-available-height) tw:min-w-36 tw:origin-(--radix-context-menu-content-transform-origin) tw:overflow-x-hidden tw:overflow-y-auto tw:rounded-lg tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-md tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",t),style:{zIndex:n.Z_INDEX_ABOVE_DOCK,...r},...a})})}function Uc({className:t,inset:r,variant:a="default",...o}){return e.jsx(D.ContextMenu.Item,{"data-slot":"context-menu-item","data-inset":r,"data-variant":a,className:n.cn("pr-twp tw:group/context-menu-item tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-[variant=destructive]:text-destructive tw:data-[variant=destructive]:focus:bg-destructive/10 tw:data-[variant=destructive]:focus:text-destructive tw:dark:data-[variant=destructive]:focus:bg-destructive/20 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4 tw:focus:*:[svg]:text-accent-foreground tw:data-[variant=destructive]:*:[svg]:text-destructive",t),...o})}function qc({className:t,inset:r,children:a,...o}){return e.jsxs(D.ContextMenu.SubTrigger,{"data-slot":"context-menu-sub-trigger","data-inset":r,className:n.cn("pr-twp tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-open:bg-accent tw:data-open:text-accent-foreground tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),...o,children:[a,e.jsx(Tt.IconChevronRight,{className:"tw:ms-auto"})]})}function Hc({className:t,style:r,...a}){return e.jsx(D.ContextMenu.SubContent,{"data-slot":"context-menu-sub-content",className:n.cn("pr-twp tw:min-w-32 tw:origin-(--radix-context-menu-content-transform-origin) tw:overflow-hidden tw:rounded-lg tw:border tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-lg tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",t),style:{zIndex:n.Z_INDEX_ABOVE_DOCK,...r},...a})}function Yc({className:t,children:r,checked:a,inset:o,...i}){return e.jsxs(D.ContextMenu.CheckboxItem,{"data-slot":"context-menu-checkbox-item","data-inset":o,className:n.cn("pr-twp tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:py-1 tw:pe-8 tw:ps-1.5 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),checked:a,...i,children:[e.jsx("span",{className:"tw:pointer-events-none tw:absolute tw:end-2",children:e.jsx(D.ContextMenu.ItemIndicator,{children:e.jsx(Tt.IconCheck,{})})}),r]})}function Xc({className:t,children:r,inset:a,...o}){return e.jsxs(D.ContextMenu.RadioItem,{"data-slot":"context-menu-radio-item","data-inset":a,className:n.cn("pr-twp tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:py-1 tw:pe-8 tw:ps-1.5 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),...o,children:[e.jsx("span",{className:"tw:pointer-events-none tw:absolute tw:end-2",children:e.jsx(D.ContextMenu.ItemIndicator,{children:e.jsx(Tt.IconCheck,{})})}),r]})}function Zc({className:t,inset:r,...a}){return e.jsx(D.ContextMenu.Label,{"data-slot":"context-menu-label","data-inset":r,className:n.cn("pr-twp tw:px-1.5 tw:py-1 tw:text-xs tw:font-medium tw:text-muted-foreground tw:data-inset:ps-7",t),...a})}function Wc({className:t,...r}){return e.jsx(D.ContextMenu.Separator,{"data-slot":"context-menu-separator",className:n.cn("pr-twp tw:-mx-1 tw:my-1 tw:h-px tw:bg-border",t),...r})}function Jc({className:t,...r}){return e.jsx("span",{"data-slot":"context-menu-shortcut",className:n.cn("pr-twp tw:ms-auto tw:text-xs tw:tracking-widest tw:text-muted-foreground tw:group-focus/context-menu-item:text-accent-foreground",t),...r})}function Qc({...t}){return e.jsx(se.Drawer.Root,{"data-slot":"drawer",...t})}function tl({...t}){return e.jsx(se.Drawer.Trigger,{"data-slot":"drawer-trigger",...t})}function Po({...t}){return e.jsx(se.Drawer.Portal,{"data-slot":"drawer-portal",...t})}function el({...t}){return e.jsx(se.Drawer.Close,{"data-slot":"drawer-close",...t})}function Lo({className:t,...r}){return e.jsx(se.Drawer.Overlay,{"data-slot":"drawer-overlay",className:n.cn("pr-twp tw:fixed tw:inset-0 tw:z-50 tw:bg-black/10 tw:supports-backdrop-filter:backdrop-blur-xs tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-closed:animate-out tw:data-closed:fade-out-0",t),...r})}function rl({className:t,children:r,hideDrawerHandle:a=!1,...o}){const i=n.readDirection();return e.jsxs(Po,{"data-slot":"drawer-portal",children:[e.jsx(Lo,{}),e.jsxs(se.Drawer.Content,{"data-slot":"drawer-content",className:n.cn("pr-twp tw:group/drawer-content tw:fixed tw:z-50 tw:flex tw:h-auto tw:flex-col tw:bg-popover tw:text-sm tw:text-popover-foreground tw:data-[vaul-drawer-direction=bottom]:inset-x-0 tw:data-[vaul-drawer-direction=bottom]:bottom-0 tw:data-[vaul-drawer-direction=bottom]:mt-24 tw:data-[vaul-drawer-direction=bottom]:max-h-[80vh] tw:data-[vaul-drawer-direction=bottom]:rounded-t-xl tw:data-[vaul-drawer-direction=bottom]:border-t tw:data-[vaul-drawer-direction=left]:inset-y-0 tw:data-[vaul-drawer-direction=left]:left-0 tw:data-[vaul-drawer-direction=left]:w-3/4 tw:data-[vaul-drawer-direction=left]:rounded-r-xl tw:data-[vaul-drawer-direction=left]:border-r tw:data-[vaul-drawer-direction=left]:flex-row tw:data-[vaul-drawer-direction=right]:inset-y-0 tw:data-[vaul-drawer-direction=right]:right-0 tw:data-[vaul-drawer-direction=right]:w-3/4 tw:data-[vaul-drawer-direction=right]:rounded-l-xl tw:data-[vaul-drawer-direction=right]:border-l tw:data-[vaul-drawer-direction=right]:flex-row tw:data-[vaul-drawer-direction=top]:inset-x-0 tw:data-[vaul-drawer-direction=top]:top-0 tw:data-[vaul-drawer-direction=top]:mb-24 tw:data-[vaul-drawer-direction=top]:max-h-[80vh] tw:data-[vaul-drawer-direction=top]:rounded-b-xl tw:data-[vaul-drawer-direction=top]:border-b tw:data-[vaul-drawer-direction=left]:sm:max-w-sm tw:data-[vaul-drawer-direction=right]:sm:max-w-sm",t),dir:"ltr",...o,children:[!a&&e.jsx("div",{className:"tw:hidden tw:shrink-0 tw:rounded-full tw:bg-muted tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:mx-auto tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:mt-4 tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:h-1.5 tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:w-[100px] tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:block tw:group-data-[vaul-drawer-direction=right]/drawer-content:my-auto tw:group-data-[vaul-drawer-direction=right]/drawer-content:ms-4 tw:group-data-[vaul-drawer-direction=right]/drawer-content:h-[100px] tw:group-data-[vaul-drawer-direction=right]/drawer-content:w-1.5 tw:group-data-[vaul-drawer-direction=right]/drawer-content:block"}),e.jsx("div",{className:"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col",dir:i,children:r}),!a&&e.jsx("div",{className:"tw:hidden tw:shrink-0 tw:rounded-full tw:bg-muted tw:group-data-[vaul-drawer-direction=top]/drawer-content:mx-auto tw:group-data-[vaul-drawer-direction=top]/drawer-content:mb-4 tw:group-data-[vaul-drawer-direction=top]/drawer-content:h-1.5 tw:group-data-[vaul-drawer-direction=top]/drawer-content:w-[100px] tw:group-data-[vaul-drawer-direction=top]/drawer-content:block tw:group-data-[vaul-drawer-direction=left]/drawer-content:my-auto tw:group-data-[vaul-drawer-direction=left]/drawer-content:me-4 tw:group-data-[vaul-drawer-direction=left]/drawer-content:h-[100px] tw:group-data-[vaul-drawer-direction=left]/drawer-content:w-1.5 tw:group-data-[vaul-drawer-direction=left]/drawer-content:block"})]})]})}function al({className:t,...r}){return e.jsx("div",{"data-slot":"drawer-header",className:n.cn("pr-twp tw:flex tw:flex-col tw:gap-0.5 tw:p-4 tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center tw:group-data-[vaul-drawer-direction=top]/drawer-content:text-center tw:md:gap-0.5 tw:md:text-start",t),...r})}function ol({className:t,...r}){return e.jsx("div",{"data-slot":"drawer-footer",className:n.cn("pr-twp tw:mt-auto tw:flex tw:flex-col tw:gap-2 tw:p-4",t),...r})}function nl({className:t,...r}){return e.jsx(se.Drawer.Title,{"data-slot":"drawer-title",className:n.cn("pr-twp tw:font-heading tw:text-base tw:font-medium tw:text-foreground",t),...r})}function il({className:t,...r}){return e.jsx(se.Drawer.Description,{"data-slot":"drawer-description",className:n.cn("pr-twp tw:text-sm tw:text-muted-foreground",t),...r})}function sl({className:t,value:r,...a}){return e.jsx(D.Progress.Root,{"data-slot":"progress",className:n.cn("pr-twp tw:relative tw:flex tw:h-1 tw:w-full tw:items-center tw:overflow-x-hidden tw:rounded-full tw:bg-muted",t),...a,children:e.jsx(D.Progress.Indicator,{"data-slot":"progress-indicator",className:"tw:size-full tw:flex-1 tw:bg-primary tw:transition-all",style:{transform:`translateX(-${100-(r||0)}%)`}})})}function cl({...t}){const{theme:r="system"}=Wo.useTheme(),a=r==="light"||r==="dark"||r==="system"?r:"system",o={"--normal-bg":"var(--popover)","--normal-text":"var(--popover-foreground)","--normal-border":"var(--border)","--border-radius":"var(--radius)"};return e.jsx(ma.Toaster,{theme:a,className:"tw:toaster tw:group",icons:{success:e.jsx(Tt.IconCircleCheck,{className:"tw:size-4"}),info:e.jsx(Tt.IconInfoCircle,{className:"tw:size-4"}),warning:e.jsx(Tt.IconAlertTriangle,{className:"tw:size-4"}),error:e.jsx(Tt.IconAlertOctagon,{className:"tw:size-4"}),loading:e.jsx(Tt.IconLoader,{className:"tw:size-4 tw:animate-spin"})},style:o,toastOptions:{classNames:{toast:"cn-toast"}},...t})}function ll({className:t,defaultValue:r,value:a,min:o=0,max:i=100,...s}){const c=n.readDirection(),d=l.useMemo(()=>Array.isArray(a)?a:Array.isArray(r)?r:[o,i],[a,r,o,i]);return e.jsxs(D.Slider.Root,{"data-slot":"slider",defaultValue:r,value:a,min:o,max:i,className:n.cn("pr-twp tw:relative tw:flex tw:w-full tw:touch-none tw:items-center tw:select-none tw:data-disabled:opacity-50 tw:data-vertical:h-full tw:data-vertical:min-h-40 tw:data-vertical:w-auto tw:data-vertical:flex-col",t),dir:c,...s,children:[e.jsx(D.Slider.Track,{"data-slot":"slider-track",className:"tw:relative tw:grow tw:overflow-hidden tw:rounded-full tw:bg-muted tw:data-horizontal:h-1 tw:data-horizontal:w-full tw:data-vertical:h-full tw:data-vertical:w-1",children:e.jsx(D.Slider.Range,{"data-slot":"slider-range",className:"tw:absolute tw:bg-primary tw:select-none tw:data-horizontal:h-full tw:data-vertical:w-full"})}),Array.from({length:d.length},(u,w)=>e.jsx(D.Slider.Thumb,{"data-slot":"slider-thumb",className:"tw:relative tw:block tw:size-3 tw:shrink-0 tw:rounded-full tw:border tw:border-ring tw:bg-white tw:ring-ring/50 tw:transition-[color,box-shadow] tw:select-none tw:after:absolute tw:after:-inset-2 tw:hover:ring-3 tw:focus-visible:ring-3 tw:focus-visible:outline-hidden tw:active:ring-3 tw:disabled:pointer-events-none tw:disabled:opacity-50"},w))]})}function dl({className:t,size:r="default",...a}){return e.jsx(D.Switch.Root,{"data-slot":"switch","data-size":r,className:n.cn("tw:peer pr-twp tw:group/switch tw:relative tw:inline-flex tw:shrink-0 tw:items-center tw:rounded-full tw:border tw:border-transparent tw:transition-all tw:outline-none tw:after:absolute tw:after:-inset-x-3 tw:after:-inset-y-2 tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:data-[size=default]:h-[18.4px] tw:data-[size=default]:w-[32px] tw:data-[size=sm]:h-[14px] tw:data-[size=sm]:w-[24px] tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:data-checked:bg-primary tw:data-unchecked:bg-input tw:dark:data-unchecked:bg-input/80 tw:data-disabled:cursor-not-allowed tw:data-disabled:opacity-50",t),...a,children:e.jsx(D.Switch.Thumb,{"data-slot":"switch-thumb",className:"tw:pointer-events-none tw:block tw:rounded-full tw:bg-background tw:ring-0 tw:transition-transform tw:group-data-[size=default]/switch:size-4 tw:group-data-[size=sm]/switch:size-3 tw:group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] tw:rtl:group-data-[size=default]/switch:data-checked:-translate-x-[calc(100%-2px)] tw:group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] tw:rtl:group-data-[size=sm]/switch:data-checked:-translate-x-[calc(100%-2px)] tw:dark:data-checked:bg-primary-foreground tw:group-data-[size=default]/switch:data-unchecked:translate-x-0 tw:rtl:group-data-[size=default]/switch:data-unchecked:-translate-x-0 tw:group-data-[size=sm]/switch:data-unchecked:translate-x-0 tw:rtl:group-data-[size=sm]/switch:data-unchecked:-translate-x-0 tw:dark:data-unchecked:bg-foreground"})})}function wl({className:t,orientation:r="horizontal",...a}){return e.jsx(D.Tabs.Root,{"data-slot":"tabs","data-orientation":r,className:n.cn("tw:group/tabs tw:flex tw:gap-2 tw:data-horizontal:flex-col",t),...a})}const ul=er.cva("tw:group/tabs-list tw:inline-flex tw:w-fit tw:items-center tw:justify-center tw:rounded-lg tw:p-[3px] tw:text-muted-foreground tw:group-data-horizontal/tabs:h-8 tw:group-data-vertical/tabs:h-fit tw:group-data-vertical/tabs:flex-col tw:data-[variant=line]:rounded-none",{variants:{variant:{default:"tw:bg-muted",line:"tw:gap-1 tw:bg-transparent"}},defaultVariants:{variant:"default"}});function pl({className:t,variant:r="default",...a}){const o=n.readDirection();return e.jsx(D.Tabs.List,{"data-slot":"tabs-list","data-variant":r,className:n.cn("pr-twp",ul({variant:r}),t),dir:o,...a})}function gl({className:t,...r}){return e.jsx(D.Tabs.Trigger,{"data-slot":"tabs-trigger",className:n.cn("pr-twp tw:relative tw:inline-flex tw:h-[calc(100%-1px)] tw:flex-1 tw:items-center tw:justify-center tw:gap-1.5 tw:rounded-md tw:border tw:border-transparent tw:px-1.5 tw:py-0.5 tw:text-sm tw:font-medium tw:whitespace-nowrap tw:text-foreground/60 tw:transition-all tw:group-data-vertical/tabs:w-full tw:group-data-vertical/tabs:justify-start tw:hover:text-foreground tw:focus-visible:border-ring tw:focus-visible:ring-[3px] tw:focus-visible:ring-ring/50 tw:focus-visible:outline-1 tw:focus-visible:outline-ring tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:has-data-[icon=inline-end]:pe-1 tw:has-data-[icon=inline-start]:ps-1 tw:dark:text-muted-foreground tw:dark:hover:text-foreground tw:group-data-[variant=default]/tabs-list:data-active:shadow-sm tw:group-data-[variant=line]/tabs-list:data-active:shadow-none tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4","tw:group-data-[variant=line]/tabs-list:bg-transparent tw:group-data-[variant=line]/tabs-list:data-active:bg-transparent tw:dark:group-data-[variant=line]/tabs-list:data-active:border-transparent tw:dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent","tw:data-active:bg-background tw:data-active:text-foreground tw:dark:data-active:border-input tw:dark:data-active:bg-input/30 tw:dark:data-active:text-foreground","tw:after:absolute tw:after:bg-foreground tw:after:opacity-0 tw:after:transition-opacity tw:group-data-horizontal/tabs:after:inset-x-0 tw:group-data-horizontal/tabs:after:bottom-[-5px] tw:group-data-horizontal/tabs:after:h-0.5 tw:group-data-vertical/tabs:after:inset-y-0 tw:group-data-vertical/tabs:after:-end-1 tw:group-data-vertical/tabs:after:w-0.5 tw:group-data-[variant=line]/tabs-list:data-active:after:opacity-100",t),...r})}function hl({className:t,...r}){return e.jsx(D.Tabs.Content,{"data-slot":"tabs-content",className:n.cn("pr-twp tw:flex-1 tw:text-sm tw:outline-none",t),...r})}const fl=(t,r)=>{l.useEffect(()=>{if(!t)return()=>{};const a=t(r);return()=>{a()}},[t,r])};function ml(t){return{preserveValue:!0,...t}}const Vo=(t,r,a={})=>{const o=l.useRef(r);o.current=r;const i=l.useRef(a);i.current=ml(i.current);const[s,c]=l.useState(()=>o.current),[d,u]=l.useState(!0);return l.useEffect(()=>{let w=!0;return u(!!t),(async()=>{if(t){const p=await t();w&&(c(()=>p),u(!1))}})(),()=>{w=!1,i.current.preserveValue||c(()=>o.current)}},[t]),[s,d]},hr=()=>!1,vl=(t,r)=>{const[a]=Vo(l.useCallback(async()=>{if(!t)return hr;const o=await Promise.resolve(t(r));return async()=>o()},[r,t]),hr,{preserveValue:!1});l.useEffect(()=>()=>{a!==hr&&a()},[a])};function bl(t){l.useEffect(()=>{let r;return t&&(r=document.createElement("style"),r.appendChild(document.createTextNode(t)),document.head.appendChild(r)),()=>{r&&document.head.removeChild(r)}},[t])}function xl(t){const r=l.useMemo(()=>M.collectUsjMarkers(t).slice().sort().join(" "),[t]);return l.useMemo(()=>r?r.split(" "):[],[r])}const kl=()=>{const[t,r]=l.useState(()=>document.body.getBoundingClientRect().height>0);return l.useEffect(()=>{const a=new IntersectionObserver(o=>{const i=o[o.length-1];i&&r(i.isIntersecting)});return a.observe(document.body),()=>{a.disconnect()}},[]),t};exports.Badge=n.Badge;exports.Button=n.Button;exports.ButtonGroup=n.ButtonGroup;exports.ButtonGroupSeparator=n.ButtonGroupSeparator;exports.ButtonGroupText=n.ButtonGroupText;exports.Command=n.Command;exports.CommandEmpty=n.CommandEmpty;exports.CommandGroup=n.CommandGroup;exports.CommandInput=n.CommandInput;exports.CommandItem=n.CommandItem;exports.CommandList=n.CommandList;exports.Dialog=n.Dialog;exports.DialogClose=n.DialogClose;exports.DialogContent=n.DialogContent;exports.DialogDescription=n.DialogDescription;exports.DialogFooter=n.DialogFooter;exports.DialogHeader=n.DialogHeader;exports.DialogOverlay=n.DialogOverlay;exports.DialogPortal=n.DialogPortal;exports.DialogTitle=n.DialogTitle;exports.DialogTrigger=n.DialogTrigger;exports.DropdownMenu=n.DropdownMenu;exports.DropdownMenuCheckboxItem=n.DropdownMenuCheckboxItem;exports.DropdownMenuContent=n.DropdownMenuContent;exports.DropdownMenuGroup=n.DropdownMenuGroup;exports.DropdownMenuItem=n.DropdownMenuItem;exports.DropdownMenuLabel=n.DropdownMenuLabel;exports.DropdownMenuPortal=n.DropdownMenuPortal;exports.DropdownMenuRadioGroup=n.DropdownMenuRadioGroup;exports.DropdownMenuRadioItem=n.DropdownMenuRadioItem;exports.DropdownMenuSeparator=n.DropdownMenuSeparator;exports.DropdownMenuShortcut=n.DropdownMenuShortcut;exports.DropdownMenuSub=n.DropdownMenuSub;exports.DropdownMenuSubContent=n.DropdownMenuSubContent;exports.DropdownMenuSubTrigger=n.DropdownMenuSubTrigger;exports.DropdownMenuTrigger=n.DropdownMenuTrigger;exports.Input=n.Input;exports.Kbd=n.Kbd;exports.KbdGroup=n.KbdGroup;exports.Label=n.Label;exports.MultiSelectComboBox=n.MultiSelectComboBox;exports.Popover=n.Popover;exports.PopoverAnchor=n.PopoverAnchor;exports.PopoverContent=n.PopoverContent;exports.PopoverDescription=n.PopoverDescription;exports.PopoverHeader=n.PopoverHeader;exports.PopoverPortalContainerProvider=n.PopoverPortalContainerProvider;exports.PopoverTitle=n.PopoverTitle;exports.PopoverTrigger=n.PopoverTrigger;exports.ResizableHandle=n.ResizableHandle;exports.ResizablePanel=n.ResizablePanel;exports.ResizablePanelGroup=n.ResizablePanelGroup;exports.SearchBar=n.SearchBar;exports.Separator=n.Separator;exports.Skeleton=n.Skeleton;exports.Spinner=n.Spinner;exports.Table=n.Table;exports.TableBody=n.TableBody;exports.TableCaption=n.TableCaption;exports.TableCell=n.TableCell;exports.TableFooter=n.TableFooter;exports.TableHead=n.TableHead;exports.TableHeader=n.TableHeader;exports.TableRow=n.TableRow;exports.Tooltip=n.Tooltip;exports.TooltipContent=n.TooltipContent;exports.TooltipProvider=n.TooltipProvider;exports.TooltipTrigger=n.TooltipTrigger;exports.Z_INDEX_ABOVE_DOCK=n.Z_INDEX_ABOVE_DOCK;exports.Z_INDEX_FOOTNOTE_EDITOR=n.Z_INDEX_FOOTNOTE_EDITOR;exports.Z_INDEX_MODAL=n.Z_INDEX_MODAL;exports.Z_INDEX_MODAL_BACKDROP=n.Z_INDEX_MODAL_BACKDROP;exports.Z_INDEX_OVERLAY=n.Z_INDEX_OVERLAY;exports.badgeVariants=n.badgeVariants;exports.buttonGroupVariants=n.buttonGroupVariants;exports.buttonVariants=n.buttonVariants;exports.cn=n.cn;exports.isMacOs=n.isMacOs;exports.isWindows=n.isWindows;exports.useListbox=n.useListbox;exports.useTruncationTooltip=n.useTruncationTooltip;Object.defineProperty(exports,"sonner",{enumerable:!0,get:()=>ma.toast});exports.Alert=Ic;exports.AlertDescription=$c;exports.AlertTitle=Ac;exports.Avatar=Wa;exports.AvatarFallback=Ja;exports.AvatarImage=Ai;exports.BOOK_CHAPTER_CONTROL_STRING_KEYS=nn;exports.BOOK_SELECTOR_STRING_KEYS=cn;exports.BookChapterControl=Ge;exports.BookSelector=ln;exports.CANCEL_ACCEPT_BUTTONS_STRING_KEYS=Dr;exports.COMMENT_EDITOR_STRING_KEYS=Ti;exports.COMMENT_LIST_ELEMENT_ID=Ya;exports.COMMENT_LIST_STRING_KEYS=Mi;exports.CONFLICT_NOTE_STRING_KEYS=Ni;exports.CancelAcceptButtons=Or;exports.Card=Xa;exports.CardContent=Za;exports.CardDescription=zi;exports.CardFooter=Ii;exports.CardHeader=Di;exports.CardTitle=Oi;exports.ChapterRangeSelector=ya;exports.Checkbox=Ar;exports.CheckboxGroup=Mc;exports.Checklist=Bo;exports.ComboBox=mr;exports.CommentEditor=Si;exports.CommentList=Ki;exports.ConflictNoteCard=eo;exports.ContextMenu=Bc;exports.ContextMenuCheckboxItem=Yc;exports.ContextMenuContent=Kc;exports.ContextMenuGroup=Lc;exports.ContextMenuItem=Uc;exports.ContextMenuLabel=Zc;exports.ContextMenuPortal=Vc;exports.ContextMenuRadioGroup=Gc;exports.ContextMenuRadioItem=Xc;exports.ContextMenuSeparator=Wc;exports.ContextMenuShortcut=Jc;exports.ContextMenuSub=Fc;exports.ContextMenuSubContent=Hc;exports.ContextMenuSubTrigger=qc;exports.ContextMenuTrigger=Pc;exports.DataTable=no;exports.Drawer=Qc;exports.DrawerClose=el;exports.DrawerContent=rl;exports.DrawerDescription=il;exports.DrawerFooter=ol;exports.DrawerHeader=al;exports.DrawerOverlay=Lo;exports.DrawerPortal=Po;exports.DrawerTitle=nl;exports.DrawerTrigger=tl;exports.DropdownMenuItemType=co;exports.ERROR_DUMP_STRING_KEYS=io;exports.ERROR_POPOVER_STRING_KEYS=Zi;exports.EditorKeyboardShortcuts=uo;exports.EmptyState=Dc;exports.ErrorDump=so;exports.ErrorPopover=Wi;exports.FOOTNOTE_EDITOR_STRING_KEYS=gs;exports.Filter=rs;exports.FilterDropdown=Ji;exports.Footer=es;exports.FootnoteEditor=ps;exports.FootnoteItem=fo;exports.FootnoteList=ms;exports.INVENTORY_STRING_KEYS=Ss;exports.Inventory=Rs;exports.MARKER_MENU_STRING_KEYS=po;exports.MarkdownRenderer=Xi;exports.MarkerMenu=go;exports.MoreInfo=Qi;exports.NavigationContentSearch=pc;exports.Progress=sl;exports.RadioGroup=rr;exports.RadioGroupItem=Re;exports.RecentSearches=xa;exports.ResultsCard=Rc;exports.SCOPE_SELECTOR_STRING_KEYS=oc;exports.SELECT_BOOKS_STRING_KEYS=Do;exports.ScopeSelector=ic;exports.ScriptureResultsViewer=rc;exports.ScrollGroupSelector=sc;exports.Select=ue;exports.SelectBooks=Ro;exports.SelectBooksPicker=Mo;exports.SelectContent=he;exports.SelectGroup=ro;exports.SelectItem=Ut;exports.SelectLabel=qi;exports.SelectScrollDownButton=oo;exports.SelectScrollUpButton=ao;exports.SelectSeparator=Hi;exports.SelectTrigger=ge;exports.SelectValue=pe;exports.SettingsList=cc;exports.SettingsListHeader=dc;exports.SettingsListItem=lc;exports.SettingsSidebar=No;exports.SettingsSidebarContentSearch=Ys;exports.Sidebar=xo;exports.SidebarContent=yo;exports.SidebarFooter=Bs;exports.SidebarGroup=kr;exports.SidebarGroupAction=Ls;exports.SidebarGroupContent=_r;exports.SidebarGroupLabel=yr;exports.SidebarHeader=$s;exports.SidebarInput=As;exports.SidebarInset=ko;exports.SidebarMenu=_o;exports.SidebarMenuAction=Fs;exports.SidebarMenuBadge=Gs;exports.SidebarMenuButton=Co;exports.SidebarMenuItem=jo;exports.SidebarMenuSkeleton=Ks;exports.SidebarMenuSub=Us;exports.SidebarMenuSubButton=Hs;exports.SidebarMenuSubItem=qs;exports.SidebarProvider=bo;exports.SidebarRail=Is;exports.SidebarSeparator=Ps;exports.SidebarTrigger=zs;exports.Slider=ll;exports.Sonner=cl;exports.Switch=dl;exports.TabDropdownMenu=tr;exports.TabFloatingMenu=uc;exports.TabToolbar=wc;exports.Tabs=wl;exports.TabsContent=hl;exports.TabsList=pl;exports.TabsTrigger=gl;exports.TextField=Oc;exports.Textarea=Jo;exports.ToggleGroup=Mr;exports.ToggleGroupItem=Me;exports.Toolbar=Nc;exports.UNDO_REDO_BUTTONS_STRING_KEYS=lo;exports.UiLanguageSelector=Sc;exports.UndoRedoButtons=wo;exports.VerticalTabs=Br;exports.VerticalTabsContent=Lr;exports.VerticalTabsList=Pr;exports.VerticalTabsTrigger=Ao;exports.getBookIdFromUSFM=Es;exports.getCommentThreadElementId=Ri;exports.getInventoryHeader=Oe;exports.getLinesFromUSFM=Cs;exports.getNumberFromUSFM=Ns;exports.getStatusForItem=mo;exports.getToolbarOSReservedSpaceClassName=Cc;exports.inventoryCountColumn=_s;exports.inventoryItemColumn=ks;exports.inventoryStatusColumn=js;exports.useEvent=fl;exports.useEventAsync=vl;exports.useExtraValidMarkers=xl;exports.usePromise=Vo;exports.useRecentSearches=Qo;exports.useSidebar=ze;exports.useStylesheet=bl;exports.useViewVisibility=kl;function yl(t,r="top"){if(!t||typeof document>"u")return;const a=document.head||document.querySelector("head"),o=a.querySelector(":first-child"),i=document.createElement("style");i.appendChild(document.createTextNode(t)),r==="top"&&o?a.insertBefore(i,o):a.appendChild(i)}yl(`.banded-row:hover { - cursor: pointer; -} - -.banded-row[data-state='selected']:hover { - cursor: default; -} -/* By default the editor is too tall for the footnote editor, even while empty, so this makes it +"use strict";var qo=Object.defineProperty;var Ho=(t,r,a)=>r in t?qo(t,r,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[r]=a;var Ot=(t,r,a)=>Ho(t,typeof r!="symbol"?r+"":r,a);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./resizable-DeY5Gh-0.cjs"),e=require("react/jsx-runtime"),ht=require("@sillsdev/scripture"),R=require("lucide-react"),M=require("platform-bible-utils"),l=require("react"),D=require("radix-ui"),v=require("lexical"),fr=require("@lexical/rich-text"),Ur=require("react-dom"),Yo=require("@lexical/table"),er=require("class-variance-authority"),ha=require("@lexical/headless"),fa=require("@lexical/html"),It=require("@tanstack/react-table"),Tt=require("@tabler/icons-react"),Xo=require("markdown-to-jsx"),Gt=require("@eten-tech-foundation/platform-editor"),Zo=require("react-hotkeys-hook"),se=require("vaul"),Wo=require("next-themes"),ma=require("sonner");function Jo({className:t,...r}){return e.jsx("textarea",{"data-slot":"textarea",className:n.cn("pr-twp tw:flex tw:field-sizing-content tw:min-h-16 tw:w-full tw:rounded-lg tw:border tw:border-input tw:bg-transparent tw:px-2.5 tw:py-2 tw:text-base tw:transition-colors tw:outline-none tw:placeholder:text-muted-foreground tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:bg-input/50 tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:md:text-sm tw:dark:bg-input/30 tw:dark:disabled:bg-input/80 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40",t),...r})}function va({ref:t,bookId:r,isSelected:a,onSelect:o,onMouseDown:i,section:s,className:c,showCheck:d=!1,localizedBookNames:u,commandValue:w,disabled:p=!1}){const g=l.useRef(!1),f=()=>{p||(g.current||o==null||o(r),setTimeout(()=>{g.current=!1},100))},h=b=>{if(p){b.preventDefault();return}g.current=!0,i?i(b):o==null||o(r)},m=l.useMemo(()=>n.getLocalizedBookName(r,u),[r,u]),k=l.useMemo(()=>n.getLocalizedBookId(r,u),[r,u]);return e.jsx("div",{className:n.cn("tw:mx-1 tw:my-1 tw:border-b-0 tw:border-e-0 tw:border-s-2 tw:border-t-0 tw:border-solid",{"tw:border-s-red-200":s===M.Section.OT,"tw:border-s-purple-200":s===M.Section.NT,"tw:border-s-indigo-200":s===M.Section.DC,"tw:border-s-amber-200":s===M.Section.Extra}),children:e.jsxs(n.CommandItem,{ref:t,value:w||`${r} ${ht.Canon.bookIdToEnglishName(r)}`,onSelect:f,onMouseDown:h,role:"option","aria-selected":a,"aria-disabled":p||void 0,"aria-label":`${ht.Canon.bookIdToEnglishName(r)} (${r.toLocaleUpperCase()})`,disabled:p,className:n.cn(c,p&&"tw:cursor-not-allowed tw:opacity-50"),children:[d&&e.jsx(R.Check,{className:n.cn("tw:me-2 tw:h-4 tw:w-4 tw:shrink-0",a?"tw:opacity-100":"tw:opacity-0")}),e.jsx("span",{className:"tw:min-w-0 tw:flex-1",children:m}),e.jsx("span",{className:"tw:ms-2 tw:shrink-0 tw:text-xs tw:text-muted-foreground",children:k})]})})}function ba(t,r,a){return`${t} ${n.ALL_ENGLISH_BOOK_NAMES[t]}${r?` ${n.getLocalizedBookId(t,r)} ${n.getLocalizedBookName(t,r)}`:""}`}function xa({recentSearches:t,onSearchItemSelect:r,renderItem:a=p=>String(p),getItemKey:o=p=>String(p),ariaLabel:i="Show recent searches",groupHeading:s="Recent",id:c,classNameForItems:d,buttonClassName:u="tw:absolute tw:right-0 tw:top-0 tw:h-full tw:px-3 tw:py-2",buttonVariant:w="ghost"}){const[p,g]=l.useState(!1);if(t.length===0)return;const f=h=>{r(h),g(!1)};return e.jsxs(n.Popover,{open:p,onOpenChange:g,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:w,size:"icon",className:u,"aria-label":i,children:e.jsx(R.Clock,{className:"tw:h-4 tw:w-4"})})}),e.jsx(n.PopoverContent,{id:c,className:"tw:w-[300px] tw:p-0",align:"start",children:e.jsx(n.Command,{children:e.jsx(n.CommandList,{children:e.jsx(n.CommandGroup,{heading:s,children:t.map(h=>e.jsxs(n.CommandItem,{onSelect:()=>f(h),className:n.cn("tw:flex tw:items-center",d),children:[e.jsx(R.Clock,{className:"tw:mr-2 tw:h-4 tw:w-4 tw:opacity-50"}),e.jsx("span",{children:a(h)})]},o(h)))})})})})]})}function Qo(t,r,a=(i,s)=>i===s,o=15){return i=>{const s=t.filter(d=>!a(d,i)),c=[i,...s.slice(0,o-1)];r(c)}}function Be(t,r){return!r||r.book===t.book&&r.chapterNum===t.chapterNum&&r.verseNum===t.verseNum}function tn(t,r,a,o){const i=l.useMemo(()=>n.d(t,r),[t,r]),s=l.useMemo(()=>n.k(t,r),[t,r]),c=l.useMemo(()=>n.C(t,r),[t,r]),d=l.useMemo(()=>n.E(t,r),[t,r]),u=l.useCallback(w=>{w&&o(w)},[o]);return l.useMemo(()=>[{onClick:()=>u(i),disabled:Be(t,i),title:"Previous chapter",icon:a==="ltr"?R.ChevronsLeft:R.ChevronsRight},{onClick:()=>u(c),disabled:Be(t,c),title:"Previous verse",icon:a==="ltr"?R.ChevronLeft:R.ChevronRight},{onClick:()=>u(d),disabled:Be(t,d),title:"Next verse",icon:a==="ltr"?R.ChevronRight:R.ChevronLeft},{onClick:()=>u(s),disabled:Be(t,s),title:"Next chapter",icon:a==="ltr"?R.ChevronsRight:R.ChevronsLeft}],[t,a,u,i,c,d,s])}const Fe={BOOK_ONLY:/^([^:\s]+(?:\s+[^:\s]+)*)$/i,BOOK_CHAPTER:/^([^:\s]+(?:\s+[^:\s]+)*)\s+(\d+)$/i,BOOK_CHAPTER_VERSE:/^([^:\s]+(?:\s+[^:\s]+)*)\s+(\d+):(\d*)$/i},en=[Fe.BOOK_ONLY,Fe.BOOK_CHAPTER,Fe.BOOK_CHAPTER_VERSE];function rn(t){return Fe.BOOK_CHAPTER_VERSE.test(t.trim())}function qr(t,r){return ht.Canon.bookIdToNumber(t)0?!1:r0?!1:ro.chapterNum?!1:a{if(i)return i;const c=s.exec(t.trim());if(c){const[d,u=void 0,w=void 0]=c.slice(1);let p;const g=r.filter(f=>n.doesBookMatchQuery(f,d,a));if(g.length===1&&([p]=g),!p&&u){if(ht.Canon.isBookIdValid(d)){const f=d.toUpperCase();r.includes(f)&&(p=f)}if(!p&&a){const f=Array.from(a.entries()).find(([,h])=>h.localizedId.toLowerCase()===d.toLowerCase());f&&r.includes(f[0])&&([p]=f)}}if(!p&&u){const h=(m=>Object.keys(n.ALL_ENGLISH_BOOK_NAMES).find(k=>n.ALL_ENGLISH_BOOK_NAMES[k].toLowerCase()===m.toLowerCase()))(d);if(h&&r.includes(h)&&(p=h),!p&&a){const m=Array.from(a.entries()).find(([,k])=>k.localizedName.toLowerCase()===d.toLowerCase());m&&r.includes(m[0])&&([p]=m)}}if(p){let f=u?parseInt(u,10):void 0;f&&f>be(p)&&(f=Math.max(be(p),1));const h=w?parseInt(w,10):void 0;return{book:p,chapterNum:f,verseNum:h}}}},void 0);if(o)return o}function ka({count:t,valueBuilder:r,onSelect:a,itemRef:o,isDisabled:i,isDimmed:s,isSelected:c,className:d}){if(!(t<=0))return e.jsx(n.CommandGroup,{children:e.jsx("div",{className:n.cn("tw:grid tw:grid-cols-6 tw:gap-1",d),children:Array.from({length:t},(u,w)=>w+1).map(u=>{const w=(i==null?void 0:i(u))??!1;return e.jsx(n.CommandItem,{value:r(u),onSelect:()=>{w||a(u)},ref:o(u),disabled:w,"aria-disabled":w||void 0,className:n.cn("tw:h-8 tw:w-8 tw:cursor-pointer tw:justify-center tw:rounded-md tw:text-center tw:text-sm",{"tw:bg-primary tw:text-primary-foreground":(c==null?void 0:c(u))??!1},{"tw:bg-muted/50 tw:text-muted-foreground/50":((s==null?void 0:s(u))??!1)&&!w},w&&"tw:cursor-not-allowed tw:opacity-40"),children:u},u)})})})}function Yr({bookId:t,scrRef:r,onChapterSelect:a,setChapterRef:o,isChapterDimmed:i,isChapterDisabled:s,className:c}){if(t)return e.jsx(ka,{count:be(t),valueBuilder:d=>`${t} ${n.ALL_ENGLISH_BOOK_NAMES[t]||""} ${d}`,onSelect:a,itemRef:o,isDisabled:s,isDimmed:i,isSelected:d=>t===r.book&&d===r.chapterNum,className:c})}function Xr({bookId:t,chapterNum:r,endVerse:a,scrRef:o,onVerseSelect:i,setVerseRef:s,isVerseDimmed:c,isVerseDisabled:d,className:u}){if(!(!t||a<=0))return e.jsx(ka,{count:a,valueBuilder:w=>`${t} ${n.ALL_ENGLISH_BOOK_NAMES[t]||""} ${r}:${w}`,onSelect:i,itemRef:s,isDisabled:d,isDimmed:c,isSelected:w=>t===o.book&&r===o.chapterNum&&w===o.verseNum,className:u})}function Ge({scrRef:t,handleSubmit:r,className:a,getActiveBookIds:o,localizedBookNames:i,localizedStrings:s,recentSearches:c,onAddRecentSearch:d,id:u,getEndVerse:w,disableReferencesUpTo:p,submitKeys:g,triggerContent:f,triggerVariant:h="outline",onOpenChange:m,onCloseAutoFocus:k,modal:b=!1,align:C="center",ref:y,disabled:_}){const B=n.readDirection(),[F,E]=l.useState(!1),[P,A]=l.useState(""),[j,V]=l.useState(""),[z,N]=l.useState("books"),[H,U]=l.useState(void 0),[G,I]=l.useState(void 0),[T,Z]=l.useState(void 0),[W,vt]=l.useState(!1),bt=l.useRef(null),Mt=l.useRef(!1),K=l.useRef(void 0),J=l.useRef(void 0),st=l.useRef(void 0),ot=l.useRef(void 0),gt=l.useRef({}),qt=l.useRef({}),et=l.useCallback(x=>{r(x),d&&d(x)},[r,d]),Rt=l.useMemo(()=>o?o():n.ALL_BOOK_IDS,[o]),yt=l.useMemo(()=>({[M.Section.OT]:Rt.filter(q=>ht.Canon.isBookOT(q)),[M.Section.NT]:Rt.filter(q=>ht.Canon.isBookNT(q)),[M.Section.DC]:Rt.filter(q=>ht.Canon.isBookDC(q)),[M.Section.Extra]:Rt.filter(q=>ht.Canon.extraBooks().includes(q))}),[Rt]),Bt=l.useMemo(()=>Object.values(yt).flat(),[yt]),Ht=l.useMemo(()=>{if(!j.trim())return yt;const x={[M.Section.OT]:[],[M.Section.NT]:[],[M.Section.DC]:[],[M.Section.Extra]:[]};return[M.Section.OT,M.Section.NT,M.Section.DC,M.Section.Extra].forEach(tt=>{x[tt]=yt[tt].filter(Dt=>n.doesBookMatchQuery(Dt,j,i))}),x},[yt,j,i]),O=l.useMemo(()=>on(j,Bt,i),[j,Bt,i]),Pt=l.useRef(!1);l.useEffect(()=>{if(!Pt.current){Pt.current=!0;return}m==null||m(F)},[F,m]);const ft=l.useCallback(()=>{if(O){const x=O.chapterNum??1,q=O.verseNum??1;if(p&&or(O.book,x,q,p))return;et({book:O.book,chapterNum:x,verseNum:q}),E(!1),V(""),A("")}},[et,O,p]),xt=l.useCallback(x=>{const q=G??(O==null?void 0:O.book),tt=T??(O==null?void 0:O.chapterNum);!q||!tt||(et({book:q,chapterNum:tt,verseNum:x}),E(!1))},[et,G,T,O]),Vt=l.useCallback(x=>{if(p&&qr(x,p))return;if(be(x)<=1){et({book:x,chapterNum:1,verseNum:1}),E(!1),V("");return}U(x),N("chapters")},[et,p]),te=l.useCallback(x=>{const q=z==="chapters"?H:O==null?void 0:O.book;if(q){if(w&&w(q,x)>1){I(q),Z(x),N("verses"),A("");return}et({book:q,chapterNum:x,verseNum:1}),E(!1)}},[et,z,H,O,w]),Yt=l.useCallback(x=>{et(x),E(!1),V("")},[et]),L=tn(t,Bt,B,r),Y=l.useCallback(()=>{N("books"),U(void 0),I(void 0),Z(void 0),setTimeout(()=>{J.current&&J.current.focus()},0)},[]),rt=l.useCallback(()=>{const x=G;I(void 0),Z(void 0),x?(U(x),N("chapters"),A("")):Y()},[G,Y]),Q=l.useCallback(x=>{E(x),x&&(N("books"),U(void 0),I(void 0),Z(void 0),V(""))},[]);l.useEffect(()=>{_&&Q(!1)},[_,Q]);const[ct,nt]=l.useState(0);l.useEffect(()=>{var x;ct!==0&&((x=J.current)==null||x.focus())},[ct]),l.useImperativeHandle(y,()=>({open:()=>{_||(Q(!0),nt(x=>x+1))}}),[Q,_]);const{otLong:wt,ntLong:lt,dcLong:ut,extraLong:_t}={otLong:s==null?void 0:s["%scripture_section_ot_long%"],ntLong:s==null?void 0:s["%scripture_section_nt_long%"],dcLong:s==null?void 0:s["%scripture_section_dc_long%"],extraLong:s==null?void 0:s["%scripture_section_extra_long%"]},jt=l.useCallback(x=>n.getSectionLongName(x,wt,lt,ut,_t),[wt,lt,ut,_t]),At=l.useCallback(x=>O?!!O.chapterNum&&!x.toString().includes(O.chapterNum.toString()):!1,[O]),Ct=l.useMemo(()=>M.formatScrRef(t,i?n.getLocalizedBookName(t.book,i):"English"),[t,i]),ae=l.useCallback(x=>q=>{gt.current[x]=q},[]),S=l.useCallback(x=>q=>{qt.current[x]=q},[]),Nt=l.useMemo(()=>rn(j),[j]),mt=l.useMemo(()=>!w||!O||!O.chapterNum||!Nt?!1:w(O.book,O.chapterNum)>0,[w,O,Nt]),Xt=l.useCallback(x=>p?qr(x,p):!1,[p]),oe=l.useCallback(x=>q=>p?an(x,q,p):!1,[p]),_e=l.useCallback((x,q)=>tt=>p?or(x,q,tt,p):!1,[p]),je=(s==null?void 0:s["%webView_bookChapterControl_selectChapter%"])??"Select Chapter",Ce=(s==null?void 0:s["%webView_bookChapterControl_selectVerse%"])??"Select Verse",Ie=l.useCallback(x=>{(x.key==="Home"||x.key==="End")&&x.stopPropagation(),g&&g.includes(x.key)&&O&&O.chapterNum!==void 0&&O.verseNum!==void 0&&(x.preventDefault(),x.stopPropagation(),ft())},[g,O,ft]),Ae=l.useCallback(x=>{var ee,ce,ne;if(x.ctrlKey)return;const{isLetter:q,isDigit:tt}=Hr(x.key);if((z==="chapters"||z==="verses")&&(x.key===" "||x.key==="Enter")){const Et=x.target instanceof HTMLElement?x.target:void 0;if(!!(Et!=null&&Et.closest('button, a, input, select, textarea, [role="button"]'))){x.stopPropagation();return}const St=(ee=K.current)==null?void 0:ee.querySelector('[cmdk-item][data-selected="true"]:not([data-disabled="true"])');if(St){x.preventDefault(),x.stopPropagation(),St.click();return}}if((z==="chapters"||z==="verses")&&(q||tt)){x.preventDefault(),x.stopPropagation();return}if(z==="chapters"&&x.key==="Backspace"){x.preventDefault(),x.stopPropagation(),Y();return}if(z==="verses"&&x.key==="Backspace"){x.preventDefault(),x.stopPropagation(),rt();return}const Dt=["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(x.key);if(z==="verses"&&Dt){const Et=G,pt=T;if(!Et||!pt||!w)return;const St=w(Et,pt);if(!St)return;(ce=K.current)==null||ce.focus();const dt=(()=>{if(!P)return 1;const le=P.match(/:(\d+)$/);return le?parseInt(le[1],10):0})();let Ft=dt;const Lt=6;switch(x.key){case"ArrowLeft":dt!==0&&(Ft=dt>1?dt-1:St);break;case"ArrowRight":dt!==0&&(Ft=dt{const le=qt.current[Ft];le&&le.scrollIntoView({block:"nearest",behavior:"smooth"})},0));return}if((z==="chapters"||z==="books"&&O)&&Dt){const Et=z==="chapters"?H:O==null?void 0:O.book;if(!Et)return;z==="chapters"&&((ne=K.current)==null||ne.focus());const pt=(()=>{if(!P)return 1;const Lt=P.match(/(\d+)$/);return Lt?parseInt(Lt[1],10):0})(),St=be(Et);if(!St)return;let dt=pt;const Ft=6;switch(x.key){case"ArrowLeft":pt!==0&&(dt=pt>1?pt-1:St);break;case"ArrowRight":pt!==0&&(dt=pt{const Lt=gt.current[dt];Lt&&Lt.scrollIntoView({block:"nearest",behavior:"smooth"})},0))}},[z,O,Y,rt,H,G,T,w,P]),fe=l.useCallback(x=>{var Dt;if(x.shiftKey||x.key==="Tab"||x.key===" ")return;if(x.key==="Enter"){x.stopPropagation();return}if(x.key==="ArrowUp"||x.key==="ArrowDown"){(Dt=J.current)==null||Dt.focus();return}const{isLetter:q,isDigit:tt}=Hr(x.key);(q||tt)&&(x.preventDefault(),V(ee=>ee+x.key),J.current.focus(),vt(!1))},[]);return l.useLayoutEffect(()=>{const x=setTimeout(()=>{if(F&&z==="books"&&st.current&&ot.current){const q=st.current,tt=ot.current,Dt=tt.offsetTop,ee=q.clientHeight,ce=tt.clientHeight,ne=Dt-ee/2+ce/2;q.scrollTo({top:Math.max(0,ne),behavior:"smooth"}),A(ba(t.book))}},0);return()=>{clearTimeout(x)}},[F,z,j,O,t.book]),l.useLayoutEffect(()=>{if(z==="chapters"&&H){const x=H===t.book,q=x?t.chapterNum:1;A(`${H} ${n.ALL_ENGLISH_BOOK_NAMES[H]||""} ${q}`),setTimeout(()=>{if(st.current)if(x){const tt=gt.current[t.chapterNum];tt&&tt.scrollIntoView({block:"center",behavior:"smooth"})}else st.current.scrollTo({top:0});K.current&&K.current.focus()},0)}},[z,H,O,t.book,t.chapterNum]),l.useLayoutEffect(()=>{if(z==="verses"&&G&&T!==void 0){const x=G===t.book&&T===t.chapterNum,q=x?t.verseNum:1;A(`${G} ${n.ALL_ENGLISH_BOOK_NAMES[G]||""} ${T}:${q}`),setTimeout(()=>{if(st.current)if(x){const tt=qt.current[t.verseNum];tt&&tt.scrollIntoView({block:"center",behavior:"smooth"})}else st.current.scrollTo({top:0});K.current&&K.current.focus()},0)}},[z,G,T,t.book,t.chapterNum,t.verseNum]),e.jsxs(n.Popover,{open:F,onOpenChange:Q,modal:b,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsx(n.Button,{ref:bt,"aria-label":"book-chapter-trigger",variant:h,role:"combobox","aria-expanded":F,disabled:_,className:n.cn("tw:h-8 tw:w-full tw:min-w-16 tw:max-w-48 tw:overflow-hidden tw:px-1",a),onClick:x=>{Mt.current&&(Mt.current=!1,x.preventDefault())},children:f??e.jsx("span",{className:"tw:truncate",children:Ct})})}),e.jsx(n.PopoverContent,{id:u,forceMount:!0,className:"tw:w-[280px] tw:p-0",align:C,onKeyDownCapture:Ae,onKeyDown:x=>x.stopPropagation(),onPointerDownOutside:x=>{const{target:q}=x;F&&bt.current&&q instanceof Node&&bt.current.contains(q)&&(Mt.current=!0,Q(!1))},onCloseAutoFocus:k,children:e.jsxs(n.Command,{ref:K,loop:!0,value:P,onValueChange:A,shouldFilter:!1,children:[z==="books"?e.jsxs("div",{className:"tw:flex tw:items-end",children:[e.jsxs("div",{className:"tw:relative tw:flex-1",children:[e.jsx(n.CommandInput,{ref:J,value:j,onValueChange:V,onKeyDown:Ie,onFocus:()=>vt(!1),className:c&&c.length>0?"tw:!pr-10":""}),c&&c.length>0&&e.jsx(xa,{recentSearches:c,onSearchItemSelect:Yt,renderItem:x=>M.formatScrRef(x,"English"),getItemKey:x=>`${x.book}-${x.chapterNum}-${x.verseNum}`,ariaLabel:s==null?void 0:s["%history_recentSearches_ariaLabel%"],groupHeading:s==null?void 0:s["%history_recent%"]})]}),e.jsx("div",{className:"tw:flex tw:items-center tw:gap-1 tw:border-b tw:pe-2",children:L.map(({onClick:x,disabled:q,title:tt,icon:Dt})=>e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:()=>{vt(!0),x()},disabled:q,className:"tw:h-10 tw:w-4 tw:p-0",title:tt,onKeyDown:fe,children:e.jsx(Dt,{})},tt))})]}):e.jsxs("div",{className:"tw:flex tw:items-center tw:border-b tw:px-3 tw:py-2",children:[e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:z==="verses"?rt:Y,className:"tw:mr-2 tw:h-6 tw:w-6 tw:p-0",tabIndex:-1,children:B==="ltr"?e.jsx(R.ArrowLeft,{className:"tw:h-4 tw:w-4"}):e.jsx(R.ArrowRight,{className:"tw:h-4 tw:w-4"})}),z==="chapters"&&H&&e.jsx("span",{tabIndex:-1,className:"tw:text-sm tw:font-medium",children:n.getLocalizedBookName(H,i)}),z==="verses"&&G&&T!==void 0&&e.jsx("span",{tabIndex:-1,className:"tw:text-sm tw:font-medium",children:`${n.getLocalizedBookName(G,i)} ${T}`}),e.jsx("span",{tabIndex:-1,className:"tw:ms-auto tw:text-sm tw:font-medium tw:text-muted-foreground",children:z==="verses"?Ce:je})]}),!W&&e.jsxs(n.CommandList,{ref:st,children:[z==="books"&&e.jsxs(e.Fragment,{children:[!O&&Object.entries(Ht).map(([x,q])=>{if(q.length!==0)return e.jsx(n.CommandGroup,{heading:jt(x),children:q.map(tt=>e.jsx(va,{bookId:tt,onSelect:Dt=>Vt(Dt),section:M.getSectionForBook(tt),commandValue:`${tt} ${n.ALL_ENGLISH_BOOK_NAMES[tt]}`,ref:tt===t.book?ot:void 0,localizedBookNames:i,disabled:Xt(tt)},tt))},x)}),O&&e.jsx(n.CommandGroup,{children:e.jsx(n.CommandItem,{value:`${O.book} ${n.ALL_ENGLISH_BOOK_NAMES[O.book]} ${O.chapterNum||""}:${O.verseNum||""})}`,onSelect:ft,disabled:!!p&&or(O.book,O.chapterNum??1,O.verseNum??1,p),className:"tw:font-semibold tw:text-primary",children:M.formatScrRef({book:O.book,chapterNum:O.chapterNum??1,verseNum:O.verseNum??1},i?n.getLocalizedBookId(O.book,i):void 0)},"top-match")}),O&&mt&&O.chapterNum&&w&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"tw:mb-2 tw:flex tw:items-center tw:justify-between tw:px-3 tw:text-sm tw:font-medium tw:text-muted-foreground",children:[e.jsx("span",{children:`${n.getLocalizedBookName(O.book,i)} ${O.chapterNum}`}),e.jsx("span",{children:Ce})]}),e.jsx(Xr,{bookId:O.book,chapterNum:O.chapterNum,endVerse:w(O.book,O.chapterNum),scrRef:t,onVerseSelect:xt,setVerseRef:S,isVerseDisabled:_e(O.book,O.chapterNum),className:"tw:px-4 tw:pb-4"})]}),O&&!mt&&be(O.book)>1&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"tw:mb-2 tw:flex tw:items-center tw:justify-between tw:px-3 tw:text-sm tw:font-medium tw:text-muted-foreground",children:[e.jsx("span",{children:n.getLocalizedBookName(O.book,i)}),e.jsx("span",{children:je})]}),e.jsx(Yr,{bookId:O.book,scrRef:t,onChapterSelect:te,setChapterRef:ae,isChapterDimmed:At,isChapterDisabled:oe(O.book),className:"tw:px-4 tw:pb-4"})]})]}),z==="chapters"&&H&&e.jsx(Yr,{bookId:H,scrRef:t,onChapterSelect:te,setChapterRef:ae,isChapterDisabled:oe(H),className:"tw:p-4"}),z==="verses"&&G&&T!==void 0&&w&&e.jsx(Xr,{bookId:G,chapterNum:T,endVerse:w(G,T),scrRef:t,onVerseSelect:xt,setVerseRef:S,isVerseDisabled:_e(G,T),className:"tw:p-4"})]})]})})]})}const nn=Object.freeze(["%scripture_section_ot_long%","%scripture_section_nt_long%","%scripture_section_dc_long%","%scripture_section_extra_long%","%history_recent%","%history_recentSearches_ariaLabel%","%webView_bookChapterControl_selectChapter%","%webView_bookChapterControl_selectVerse%"]);function rr({className:t,...r}){const a=n.readDirection();return e.jsx(D.RadioGroup.Root,{"data-slot":"radio-group",className:n.cn("pr-twp tw:grid tw:w-full tw:gap-2",t),dir:a,...r})}function Re({className:t,...r}){return e.jsx(D.RadioGroup.Item,{"data-slot":"radio-group-item",className:n.cn("pr-twp tw:group/radio-group-item tw:peer tw:relative tw:flex tw:aspect-square tw:size-4 tw:shrink-0 tw:rounded-full tw:border tw:border-input tw:outline-none tw:after:absolute tw:after:-inset-x-3 tw:after:-inset-y-2 tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:aria-invalid:aria-checked:border-primary tw:dark:bg-input/30 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:data-checked:border-primary tw:data-checked:bg-primary tw:data-checked:text-primary-foreground tw:dark:data-checked:bg-primary",t),...r,children:e.jsx(D.RadioGroup.Indicator,{"data-slot":"radio-group-indicator",className:"tw:flex tw:size-4 tw:items-center tw:justify-center",children:e.jsx("span",{className:"tw:absolute tw:top-1/2 tw:start-1/2 tw:size-2 tw:-translate-x-1/2 tw:rtl:translate-x-1/2 tw:-translate-y-1/2 tw:rounded-full tw:bg-primary-foreground"})})})}function sn(t){return typeof t=="string"?t:typeof t=="number"?t.toString():t.label}function mr({id:t,options:r=[],className:a,buttonClassName:o,popoverContentClassName:i,popoverContentStyle:s,value:c,onChange:d=()=>{},getOptionLabel:u=sn,getButtonLabel:w,icon:p=void 0,buttonPlaceholder:g="",textPlaceholder:f="",commandEmptyMessage:h="No option found",buttonVariant:m="outline",alignDropDown:k="start",isDisabled:b=!1,ariaLabel:C,...y}){const[_,B]=l.useState(!1),F=w??u,E=A=>A.length>0&&typeof A[0]=="object"&&"options"in A[0],P=(A,j)=>{const V=u(A),z=typeof A=="object"&&"secondaryLabel"in A?A.secondaryLabel:void 0,N=`${j??""}${V}${z??""}`;return e.jsxs(n.CommandItem,{value:V,onSelect:()=>{d(A),B(!1)},className:"tw:gap-1.5!",children:[e.jsx(R.Check,{className:n.cn("tw:h-4 tw:w-4 tw:shrink-0",{"tw:opacity-0":!c||u(c)!==V})}),e.jsxs("span",{className:"tw:flex-1 tw:overflow-hidden tw:text-ellipsis tw:whitespace-nowrap",children:[V,z&&e.jsxs("span",{className:"tw:text-muted-foreground",children:[" · ",z]})]})]},N)};return e.jsxs(n.Popover,{open:_,onOpenChange:B,...y,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:m,role:"combobox","aria-expanded":_,"aria-label":C,id:t,className:n.cn("tw:flex tw:w-[200px] tw:items-center tw:justify-between tw:overflow-hidden",o??a),disabled:b,children:[e.jsxs("div",{className:"tw:flex tw:min-w-0 tw:flex-1 tw:items-center tw:overflow-hidden",children:[p&&e.jsx("div",{className:"tw:shrink-0 tw:pe-2",children:p}),e.jsx("span",{className:n.cn("tw:min-w-0 tw:overflow-hidden tw:text-ellipsis tw:whitespace-nowrap tw:text-start"),children:c?F(c):g})]}),e.jsx(R.ChevronDown,{className:"tw:ms-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})}),e.jsx(n.PopoverContent,{align:k,className:n.cn("tw:w-[200px] tw:p-0",i),style:s,children:e.jsxs(n.Command,{children:[e.jsx(n.CommandInput,{placeholder:f,className:"tw:text-inherit"}),e.jsx(n.CommandEmpty,{children:h}),e.jsx(n.CommandList,{children:E(r)?r.map(A=>e.jsx(n.CommandGroup,{heading:A.groupHeading,children:A.options.map(j=>P(j,A.groupHeading))},A.groupHeading)):e.jsx(n.CommandGroup,{children:r.map(A=>P(A))})})]})})]})}function ya({startChapter:t,endChapter:r,handleSelectStartChapter:a,handleSelectEndChapter:o,isDisabled:i=!1,chapterCount:s}){const c=l.useMemo(()=>Array.from({length:s},(w,p)=>p+1),[s]),d=w=>{a(w),w>r&&o(w)},u=w=>{o(w),ww.toString(),value:t},"start chapter"),e.jsx(n.Label,{htmlFor:"end-chapters-combobox",children:"to"}),e.jsx(mr,{isDisabled:i,onChange:u,buttonClassName:"tw:ms-2 tw:w-20",options:c,getOptionLabel:w=>w.toString(),value:r},"end chapter")]})}exports.BookSelectionMode=(t=>(t.CurrentBook="current book",t.ChooseBooks="choose books",t))(exports.BookSelectionMode||{});(t=>{t.CURRENT_BOOK="current book",t.CHOOSE_BOOKS="choose books"})(exports.BookSelectionMode||(exports.BookSelectionMode={}));const cn=Object.freeze(["%webView_bookSelector_currentBook%","%webView_bookSelector_choose%","%webView_bookSelector_chooseBooks%"]),nr=(t,r)=>t[r]??r;function ln({handleBookSelectionModeChange:t,currentBookName:r,onSelectBooks:a,selectedBookIds:o,chapterCount:i,endChapter:s,handleSelectEndChapter:c,startChapter:d,handleSelectStartChapter:u,localizedStrings:w}){const p=nr(w,"%webView_bookSelector_currentBook%"),g=nr(w,"%webView_bookSelector_choose%"),f=nr(w,"%webView_bookSelector_chooseBooks%"),[h,m]=l.useState("current book"),k=b=>{m(b),t(b)};return e.jsx(rr,{className:"pr-twp tw:flex",value:h,onValueChange:b=>k(b),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:flex-col tw:gap-4",children:[e.jsxs("div",{className:"tw:grid tw:grid-cols-[25%_25%_50%]",children:[e.jsxs("div",{className:"tw:flex tw:items-center",children:[e.jsx(Re,{value:"current book"}),e.jsx(n.Label,{className:"tw:ms-1",children:p})]}),e.jsx(n.Label,{className:"tw:flex tw:items-center",children:r}),e.jsx("div",{className:"tw:flex tw:items-center tw:justify-end",children:e.jsx(ya,{isDisabled:h==="choose books",handleSelectStartChapter:u,handleSelectEndChapter:c,chapterCount:i,startChapter:d,endChapter:s})})]}),e.jsxs("div",{className:"tw:grid tw:grid-cols-[25%_50%_25%]",children:[e.jsxs("div",{className:"tw:flex tw:items-center",children:[e.jsx(Re,{value:"choose books"}),e.jsx(n.Label,{className:"tw:ms-1",children:f})]}),e.jsx(n.Label,{className:"tw:flex tw:items-center",children:o.map(b=>ht.Canon.bookIdToEnglishName(b)).join(", ")}),e.jsx(n.Button,{disabled:h==="current book",onClick:()=>a(),children:g})]})]})})}const _a=l.createContext(null);function dn(t,r){return{getTheme:function(){return r??null}}}function Qt(){const t=l.useContext(_a);return t==null&&function(r,...a){const o=new URL("https://lexical.dev/docs/error"),i=new URLSearchParams;i.append("code",r);for(const s of a)i.append("v",s);throw o.search=i.toString(),Error(`Minified Lexical error #${r}; visit ${o.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(8),t}const ja=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0,wn=ja?l.useLayoutEffect:l.useEffect,Pe={tag:v.HISTORY_MERGE_TAG};function un({initialConfig:t,children:r}){const a=l.useMemo(()=>{const{theme:o,namespace:i,nodes:s,onError:c,editorState:d,html:u}=t,w=dn(null,o),p=v.createEditor({editable:t.editable,html:u,namespace:i,nodes:s,onError:g=>c(g,p),theme:o});return function(g,f){if(f!==null){if(f===void 0)g.update(()=>{const h=v.$getRoot();if(h.isEmpty()){const m=v.$createParagraphNode();h.append(m);const k=ja?document.activeElement:null;(v.$getSelection()!==null||k!==null&&k===g.getRootElement())&&m.select()}},Pe);else if(f!==null)switch(typeof f){case"string":{const h=g.parseEditorState(f);g.setEditorState(h,Pe);break}case"object":g.setEditorState(f,Pe);break;case"function":g.update(()=>{v.$getRoot().isEmpty()&&f(g)},Pe)}}}(p,d),[p,w]},[]);return wn(()=>{const o=t.editable,[i]=a;i.setEditable(o===void 0||o)},[]),e.jsx(_a.Provider,{value:a,children:r})}const pn=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function gn({ignoreHistoryMergeTagChange:t=!0,ignoreSelectionChange:r=!1,onChange:a}){const[o]=Qt();return pn(()=>{if(a)return o.registerUpdateListener(({editorState:i,dirtyElements:s,dirtyLeaves:c,prevEditorState:d,tags:u})=>{r&&s.size===0&&c.size===0||t&&u.has(v.HISTORY_MERGE_TAG)||d.isEmpty()||a(i,o,u)})},[o,t,r,a]),null}const jr={ltr:"tw:text-left",rtl:"tw:text-right",heading:{h1:"tw:scroll-m-20 tw:text-4xl tw:font-extrabold tw:tracking-tight tw:lg:text-5xl",h2:"tw:scroll-m-20 tw:border-b tw:pb-2 tw:text-3xl tw:font-semibold tw:tracking-tight tw:first:mt-0",h3:"tw:scroll-m-20 tw:text-2xl tw:font-semibold tw:tracking-tight",h4:"tw:scroll-m-20 tw:text-xl tw:font-semibold tw:tracking-tight",h5:"tw:scroll-m-20 tw:text-lg tw:font-semibold tw:tracking-tight",h6:"tw:scroll-m-20 tw:text-base tw:font-semibold tw:tracking-tight"},paragraph:"tw:outline-hidden",quote:"tw:mt-6 tw:border-l-2 tw:pl-6 tw:italic",link:"tw:text-blue-600 tw:hover:underline tw:hover:cursor-pointer",list:{checklist:"tw:relative",listitem:"tw:mx-8",listitemChecked:'tw:relative tw:mx-2 tw:px-6 tw:list-none tw:outline-hidden tw:line-through tw:before:content-[""] tw:before:w-4 tw:before:h-4 tw:before:top-0.5 tw:before:left-0 tw:before:cursor-pointer tw:before:block tw:before:bg-cover tw:before:absolute tw:before:border tw:before:border-primary tw:before:rounded tw:before:bg-primary tw:before:bg-no-repeat tw:after:content-[""] tw:after:cursor-pointer tw:after:border-white tw:after:border-solid tw:after:absolute tw:after:block tw:after:top-[6px] tw:after:w-[3px] tw:after:left-[7px] tw:after:right-[7px] tw:after:h-[6px] tw:after:rotate-45 tw:after:border-r-2 tw:after:border-b-2 tw:after:border-l-0 tw:after:border-t-0',listitemUnchecked:'tw:relative tw:mx-2 tw:px-6 tw:list-none tw:outline-hidden tw:before:content-[""] tw:before:w-4 tw:before:h-4 tw:before:top-0.5 tw:before:left-0 tw:before:cursor-pointer tw:before:block tw:before:bg-cover tw:before:absolute tw:before:border tw:before:border-primary tw:before:rounded',nested:{listitem:"tw:list-none tw:before:hidden tw:after:hidden"},ol:"tw:m-0 tw:p-0 tw:list-decimal tw:[&>li]:mt-2",olDepth:["tw:list-outside tw:!list-decimal","tw:list-outside tw:!list-[upper-roman]","tw:list-outside tw:!list-[lower-roman]","tw:list-outside tw:!list-[upper-alpha]","tw:list-outside tw:!list-[lower-alpha]"],ul:"tw:m-0 tw:p-0 tw:list-outside tw:[&>li]:mt-2",ulDepth:["tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc","tw:list-outside tw:!list-disc"]},hashtag:"tw:text-blue-600 tw:bg-blue-100 tw:rounded-md tw:px-1",text:{bold:"tw:font-bold",code:"tw:bg-gray-100 tw:p-1 tw:rounded-md",italic:"tw:italic",strikethrough:"tw:line-through",subscript:"tw:sub",superscript:"tw:sup",underline:"tw:underline",underlineStrikethrough:"tw:underline tw:line-through"},image:"tw:relative tw:inline-block tw:user-select-none tw:cursor-default editor-image",inlineImage:"tw:relative tw:inline-block tw:user-select-none tw:cursor-default inline-editor-image",keyword:"tw:text-purple-900 tw:font-bold",code:"EditorTheme__code",codeHighlight:{atrule:"EditorTheme__tokenAttr",attr:"EditorTheme__tokenAttr",boolean:"EditorTheme__tokenProperty",builtin:"EditorTheme__tokenSelector",cdata:"EditorTheme__tokenComment",char:"EditorTheme__tokenSelector",class:"EditorTheme__tokenFunction","class-name":"EditorTheme__tokenFunction",comment:"EditorTheme__tokenComment",constant:"EditorTheme__tokenProperty",deleted:"EditorTheme__tokenProperty",doctype:"EditorTheme__tokenComment",entity:"EditorTheme__tokenOperator",function:"EditorTheme__tokenFunction",important:"EditorTheme__tokenVariable",inserted:"EditorTheme__tokenSelector",keyword:"EditorTheme__tokenAttr",namespace:"EditorTheme__tokenVariable",number:"EditorTheme__tokenProperty",operator:"EditorTheme__tokenOperator",prolog:"EditorTheme__tokenComment",property:"EditorTheme__tokenProperty",punctuation:"EditorTheme__tokenPunctuation",regex:"EditorTheme__tokenVariable",selector:"EditorTheme__tokenSelector",string:"EditorTheme__tokenSelector",symbol:"EditorTheme__tokenProperty",tag:"EditorTheme__tokenProperty",url:"EditorTheme__tokenOperator",variable:"EditorTheme__tokenVariable"},characterLimit:"tw:!bg-destructive/50",table:"EditorTheme__table tw:w-fit tw:overflow-scroll tw:border-collapse",tableCell:"EditorTheme__tableCell tw:w-24 tw:relative tw:border tw:px-4 tw:py-2 tw:text-left tw:[&[align=center]]:text-center tw:[&[align=right]]:text-right",tableCellActionButton:"EditorTheme__tableCellActionButton tw:bg-background tw:block tw:border-0 tw:rounded-2xl tw:w-5 tw:h-5 tw:text-foreground tw:cursor-pointer",tableCellActionButtonContainer:"EditorTheme__tableCellActionButtonContainer tw:block tw:right-1 tw:top-1.5 tw:absolute tw:z-10 tw:w-5 tw:h-5",tableCellEditing:"EditorTheme__tableCellEditing tw:rounded-sm tw:shadow-sm",tableCellHeader:"EditorTheme__tableCellHeader tw:bg-muted tw:border tw:px-4 tw:py-2 tw:text-left tw:font-bold tw:[&[align=center]]:text-center tw:[&[align=right]]:text-right",tableCellPrimarySelected:"EditorTheme__tableCellPrimarySelected tw:border tw:border-primary tw:border-solid tw:block tw:h-[calc(100%-2px)] tw:w-[calc(100%-2px)] tw:absolute tw:-left-[1px] tw:-top-[1px] tw:z-10 ",tableCellResizer:"EditorTheme__tableCellResizer tw:absolute tw:-right-1 tw:h-full tw:w-2 tw:cursor-ew-resize tw:z-10 tw:top-0",tableCellSelected:"EditorTheme__tableCellSelected tw:bg-muted",tableCellSortedIndicator:"EditorTheme__tableCellSortedIndicator tw:block tw:opacity-50 tw:absolute tw:bottom-0 tw:left-0 tw:w-full tw:h-1 tw:bg-muted",tableResizeRuler:"EditorTheme__tableCellResizeRuler tw:block tw:absolute tw:w-[1px] tw:h-full tw:bg-primary tw:top-0",tableRowStriping:"EditorTheme__tableRowStriping tw:m-0 tw:border-t tw:p-0 tw:even:bg-muted",tableSelected:"EditorTheme__tableSelected tw:ring-2 tw:ring-primary tw:ring-offset-2",tableSelection:"EditorTheme__tableSelection tw:bg-transparent",layoutItem:"tw:border tw:border-dashed tw:px-4 tw:py-2",layoutContainer:"tw:grid tw:gap-2.5 tw:my-2.5 tw:mx-0",autocomplete:"tw:text-muted-foreground",blockCursor:"",embedBlock:{base:"tw:user-select-none",focus:"tw:ring-2 tw:ring-primary tw:ring-offset-2"},hr:'tw:p-0.5 tw:border-none tw:my-1 tw:mx-0 tw:cursor-pointer tw:after:content-[""] tw:after:block tw:after:h-0.5 tw:after:bg-muted tw:selected:ring-2 tw:selected:ring-primary tw:selected:ring-offset-2 tw:selected:user-select-none',indent:"[--lexical-indent-base-value:40px]",mark:"",markOverlap:""},Cr=[fr.HeadingNode,v.ParagraphNode,v.TextNode,fr.QuoteNode],hn=l.createContext(null),ir={didCatch:!1,error:null};class fn extends l.Component{constructor(r){super(r),this.resetErrorBoundary=this.resetErrorBoundary.bind(this),this.state=ir}static getDerivedStateFromError(r){return{didCatch:!0,error:r}}resetErrorBoundary(){const{error:r}=this.state;if(r!==null){for(var a,o,i=arguments.length,s=new Array(i),c=0;c0&&arguments[0]!==void 0?arguments[0]:[],r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[];return t.length!==r.length||t.some((a,o)=>!Object.is(a,r[o]))}function vn({children:t,onError:r}){return e.jsx(fn,{fallback:e.jsx("div",{style:{border:"1px solid #f00",color:"#f00",padding:"8px"},children:"An error was thrown."}),onError:r,children:t})}const bn=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function xn(t){return{initialValueFn:()=>t.isEditable(),subscribe:r=>t.registerEditableListener(r)}}function kn(){return function(t){const[r]=Qt(),a=l.useMemo(()=>t(r),[r,t]),[o,i]=l.useState(()=>a.initialValueFn()),s=l.useRef(o);return bn(()=>{const{initialValueFn:c,subscribe:d}=a,u=c();return s.current!==u&&(s.current=u,i(u)),d(w=>{s.current=w,i(w)})},[a,t]),o}(xn)}function yn(t,r){const a=t.getRootElement();if(a===null)return[];const o=a.getBoundingClientRect(),i=getComputedStyle(a),s=parseFloat(i.paddingLeft)+parseFloat(i.paddingRight),c=Array.from(r.getClientRects());let d,u=c.length;c.sort((w,p)=>{const g=w.top-p.top;return Math.abs(g)<=3?w.left-p.left:g});for(let w=0;wp.top&&d.left+d.width>p.left,f=p.width+s===o.width;g||f?(c.splice(w--,1),u--):d=p}return c}function Ye(t,...r){const a=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const i of r)o.append("v",i);throw a.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${a.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const Ca=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0,_n=Ca&&"documentMode"in document?document.documentMode:null;!(!Ca||!("InputEvent"in window)||_n)&&"getTargetRanges"in new window.InputEvent("input");function Wt(t){return`${t}px`}const jn={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Cn(t,r,a){let o=null,i=null,s=null,c=[];const d=document.createElement("div");function u(){o===null&&Ye(182),i===null&&Ye(183);const{left:g,top:f}=i.getBoundingClientRect(),h=yn(t,r);var m,k;d.isConnected||(k=d,(m=i).insertBefore(k,m.firstChild));let b=!1;for(let C=0;Ch.length;)c.pop();b&&a(c)}function w(){i=null,o=null,s!==null&&s.disconnect(),s=null,d.remove();for(const g of c)g.remove();c=[]}d.style.position="relative";const p=t.registerRootListener(function g(){const f=t.getRootElement();if(f===null)return w();const h=f.parentElement;if(!v.isHTMLElement(h))return w();w(),o=f,i=h,s=new MutationObserver(m=>{const k=t.getRootElement(),b=k&&k.parentElement;if(k!==o||b!==i)return g();for(const C of m)if(!d.contains(C.target))return u()}),s.observe(h,jn),u()});return()=>{p(),w()}}function Zr(t,r,a){if(t.type!=="text"&&v.$isElementNode(r)){const o=r.getDOMSlot(a);return[o.element,o.getFirstChildOffset()+t.offset]}return[v.getDOMTextNode(a)||a,t.offset]}function Nn(t){for(const r of t){const a=r.style;a.background!=="Highlight"&&(a.background="Highlight"),a.color!=="HighlightText"&&(a.color="HighlightText"),a.marginTop!==Wt(-1.5)&&(a.marginTop=Wt(-1.5)),a.paddingTop!==Wt(4)&&(a.paddingTop=Wt(4)),a.paddingBottom!==Wt(0)&&(a.paddingBottom=Wt(0))}}function En(t,r=Nn){let a=null,o=null,i=null,s=null,c=null,d=null,u=()=>{};function w(p){p.read(()=>{const g=v.$getSelection();if(!v.$isRangeSelection(g))return a=null,i=null,s=null,d=null,u(),void(u=()=>{});const[f,h]=function(A){const j=A.getStartEndPoints();return A.isBackward()?[j[1],j[0]]:j}(g),m=f.getNode(),k=m.getKey(),b=f.offset,C=h.getNode(),y=C.getKey(),_=h.offset,B=t.getElementByKey(k),F=t.getElementByKey(y),E=a===null||B!==o||b!==i||k!==a.getKey(),P=s===null||F!==c||_!==d||y!==s.getKey();if((E||P)&&B!==null&&F!==null){const A=function(j,V,z,N,H,U,G){const I=(j._window?j._window.document:document).createRange();return I.setStart(...Zr(V,z,N)),I.setEnd(...Zr(H,U,G)),I}(t,f,m,B,h,C,F);u(),u=Cn(t,A,r)}a=m,o=B,i=b,s=C,c=F,d=_})}return w(t.getEditorState()),v.mergeRegister(t.registerUpdateListener(({editorState:p})=>w(p)),()=>{u()})}function Sn(t,r){let a=null;const o=()=>{const i=getSelection(),s=i&&i.anchorNode,c=t.getRootElement();s!==null&&c!==null&&c.contains(s)?a!==null&&(a(),a=null):a===null&&(a=En(t,r))};return t.registerRootListener(i=>{if(i){const s=i.ownerDocument;return s.addEventListener("selectionchange",o),o(),()=>{a!==null&&a(),s.removeEventListener("selectionchange",o)}}})}function Tn(t){const r=v.$findMatchingParent(t,a=>v.$isElementNode(a)&&!a.isInline());return v.$isElementNode(r)||Ye(4,t.__key),r}function Mn(t){const r=v.$getSelection()||v.$getPreviousSelection();let a;if(v.$isRangeSelection(r))a=v.$caretFromPoint(r.focus,"next");else{if(r!=null){const c=r.getNodes(),d=c[c.length-1];d&&(a=v.$getSiblingCaret(d,"next"))}a=a||v.$getChildCaret(v.$getRoot(),"previous").getFlipped().insert(v.$createParagraphNode())}const o=Rn(t,a),i=v.$getAdjacentChildCaret(o),s=v.$isChildCaret(i)?v.$normalizeCaret(i):o;return v.$setSelectionFromCaretRange(v.$getCollapsedCaretRange(s)),t.getLatest()}function Rn(t,r,a){let o=v.$getCaretInDirection(r,"next");for(let i=o;i;i=v.$splitAtPointCaretNext(i,a))o=i;return v.$isTextPointCaret(o)&&Ye(283),o.insert(t.isInline()?v.$createParagraphNode().append(t):t),v.$getCaretInDirection(v.$getSiblingCaret(t.getLatest(),"next"),r.direction)}function Dn(t){const r=v.$getSelection();if(!v.$isRangeSelection(r))return!1;const a=new Set,o=r.getNodes();for(let i=0;iv.$isElementNode(w)&&!w.isInline());if(d===null)continue;const u=d.getKey();d.canIndent()&&!a.has(u)&&(a.add(u),t(d))}return a.size>0}const On=Symbol.for("preact-signals");function ar(){if(re>1)return void re--;let t,r=!1;for(!function(){let a=Xe;for(Xe=void 0;a!==void 0;)a.S.v===a.v&&(a.S.i=a.i),a=a.o}();Te!==void 0;){let a=Te;for(Te=void 0,Ze++;a!==void 0;){const o=a.u;if(a.u=void 0,a.f&=-3,!(8&a.f)&&Na(a))try{a.c()}catch(i){r||(t=i,r=!0)}a=o}}if(Ze=0,re--,r)throw t}function zn(t){if(re>0)return t();vr=++In,re++;try{return t()}finally{ar()}}let at,Te;function Wr(t){const r=at;at=void 0;try{return t()}finally{at=r}}let Xe,re=0,Ze=0,In=0,vr=0,Ke=0;function Jr(t){if(at===void 0)return;let r=t.n;return r===void 0||r.t!==at?(r={i:0,S:t,p:at.s,n:void 0,t:at,e:void 0,x:void 0,r},at.s!==void 0&&(at.s.n=r),at.s=r,t.n=r,32&at.f&&t.S(r),r):r.i===-1?(r.i=0,r.n!==void 0&&(r.n.p=r.p,r.p!==void 0&&(r.p.n=r.n),r.p=at.s,r.n=void 0,at.s.n=r,at.s=r),r):void 0}function zt(t,r){this.v=t,this.i=0,this.n=void 0,this.t=void 0,this.l=0,this.W=r==null?void 0:r.watched,this.Z=r==null?void 0:r.unwatched,this.name=r==null?void 0:r.name}function De(t,r){return new zt(t,r)}function Na(t){for(let r=t.s;r!==void 0;r=r.n)if(r.S.i!==r.i||!r.S.h()||r.S.i!==r.i)return!0;return!1}function Qr(t){for(let r=t.s;r!==void 0;r=r.n){const a=r.S.n;if(a!==void 0&&(r.r=a),r.S.n=r,r.i=-1,r.n===void 0){t.s=r;break}}}function Ea(t){let r,a=t.s;for(;a!==void 0;){const o=a.p;a.i===-1?(a.S.U(a),o!==void 0&&(o.n=a.n),a.n!==void 0&&(a.n.p=o)):r=a,a.S.n=a.r,a.r!==void 0&&(a.r=void 0),a=o}t.s=r}function de(t,r){zt.call(this,void 0),this.x=t,this.s=void 0,this.g=Ke-1,this.f=4,this.W=r==null?void 0:r.watched,this.Z=r==null?void 0:r.unwatched,this.name=r==null?void 0:r.name}function An(t,r){return new de(t,r)}function Sa(t){const r=t.m;if(t.m=void 0,typeof r=="function"){re++;const a=at;at=void 0;try{r()}catch(o){throw t.f&=-2,t.f|=8,Nr(t),o}finally{at=a,ar()}}}function Nr(t){for(let r=t.s;r!==void 0;r=r.n)r.S.U(r);t.x=void 0,t.s=void 0,Sa(t)}function $n(t){if(at!==this)throw new Error("Out-of-order effect");Ea(this),at=t,this.f&=-2,8&this.f&&Nr(this),ar()}function ve(t,r){this.x=t,this.m=void 0,this.s=void 0,this.u=void 0,this.f=32,this.name=r==null?void 0:r.name}function Jt(t,r){const a=new ve(t,r);try{a.c()}catch(i){throw a.d(),i}const o=a.d.bind(a);return o[Symbol.dispose]=o,o}function ye(t,r={}){const a={};for(const o in t){const i=r[o],s=De(i===void 0?t[o]:i);a[o]=s}return a}zt.prototype.brand=On,zt.prototype.h=function(){return!0},zt.prototype.S=function(t){const r=this.t;r!==t&&t.e===void 0&&(t.x=r,this.t=t,r!==void 0?r.e=t:Wr(()=>{var a;(a=this.W)==null||a.call(this)}))},zt.prototype.U=function(t){if(this.t!==void 0){const r=t.e,a=t.x;r!==void 0&&(r.x=a,t.e=void 0),a!==void 0&&(a.e=r,t.x=void 0),t===this.t&&(this.t=a,a===void 0&&Wr(()=>{var o;(o=this.Z)==null||o.call(this)}))}},zt.prototype.subscribe=function(t){return Jt(()=>{const r=this.value,a=at;at=void 0;try{t(r)}finally{at=a}},{name:"sub"})},zt.prototype.valueOf=function(){return this.value},zt.prototype.toString=function(){return this.value+""},zt.prototype.toJSON=function(){return this.value},zt.prototype.peek=function(){const t=at;at=void 0;try{return this.value}finally{at=t}},Object.defineProperty(zt.prototype,"value",{get(){const t=Jr(this);return t!==void 0&&(t.i=this.i),this.v},set(t){if(t!==this.v){if(Ze>100)throw new Error("Cycle detected");(function(r){re!==0&&Ze===0&&r.l!==vr&&(r.l=vr,Xe={S:r,v:r.v,i:r.i,o:Xe})})(this),this.v=t,this.i++,Ke++,re++;try{for(let r=this.t;r!==void 0;r=r.x)r.t.N()}finally{ar()}}}}),de.prototype=new zt,de.prototype.h=function(){if(this.f&=-3,1&this.f)return!1;if((36&this.f)==32||(this.f&=-5,this.g===Ke))return!0;if(this.g=Ke,this.f|=1,this.i>0&&!Na(this))return this.f&=-2,!0;const t=at;try{Qr(this),at=this;const r=this.x();(16&this.f||this.v!==r||this.i===0)&&(this.v=r,this.f&=-17,this.i++)}catch(r){this.v=r,this.f|=16,this.i++}return at=t,Ea(this),this.f&=-2,!0},de.prototype.S=function(t){if(this.t===void 0){this.f|=36;for(let r=this.s;r!==void 0;r=r.n)r.S.S(r)}zt.prototype.S.call(this,t)},de.prototype.U=function(t){if(this.t!==void 0&&(zt.prototype.U.call(this,t),this.t===void 0)){this.f&=-33;for(let r=this.s;r!==void 0;r=r.n)r.S.U(r)}},de.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(let t=this.t;t!==void 0;t=t.x)t.t.N()}},Object.defineProperty(de.prototype,"value",{get(){if(1&this.f)throw new Error("Cycle detected");const t=Jr(this);if(this.h(),t!==void 0&&(t.i=this.i),16&this.f)throw this.v;return this.v}}),ve.prototype.c=function(){const t=this.S();try{if(8&this.f||this.x===void 0)return;const r=this.x();typeof r=="function"&&(this.m=r)}finally{t()}},ve.prototype.S=function(){if(1&this.f)throw new Error("Cycle detected");this.f|=1,this.f&=-9,Sa(this),Qr(this),re++;const t=at;return at=this,$n.bind(this,t)},ve.prototype.N=function(){2&this.f||(this.f|=2,this.u=Te,Te=this)},ve.prototype.d=function(){this.f|=8,1&this.f||Nr(this)},ve.prototype.dispose=function(){this.d()};v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({defaultSelection:"rootEnd",disabled:!1}),name:"@lexical/extension/AutoFocus",register(t,r,a){const o=a.getOutput();return Jt(()=>o.disabled.value?void 0:t.registerRootListener(i=>{t.focus(()=>{const s=document.activeElement;i===null||s!==null&&i.contains(s)||i.focus({preventScroll:!0})},{defaultSelection:o.defaultSelection.peek()})}))}});function Ta(){const t=v.$getRoot(),r=v.$getSelection(),a=v.$createParagraphNode();t.clear(),t.append(a),r!==null&&a.select(),v.$isRangeSelection(r)&&(r.format=0)}function Ma(t,r=Ta){return t.registerCommand(v.CLEAR_EDITOR_COMMAND,a=>(t.update(r),!0),v.COMMAND_PRIORITY_EDITOR)}v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({$onClear:Ta}),name:"@lexical/extension/ClearEditor",register(t,r,a){const{$onClear:o}=a.getOutput();return Jt(()=>Ma(t,o.value))}});function Bn(t){return(typeof t.nodes=="function"?t.nodes():t.nodes)||[]}const sr=v.createState("format",{parse:t=>typeof t=="number"?t:0});class Ra extends v.DecoratorNode{$config(){return this.config("decorator-text",{extends:v.DecoratorNode,stateConfigs:[{flat:!0,stateConfig:sr}]})}getFormat(){return v.$getState(this,sr)}getFormatFlags(r,a){return v.toggleTextFormatType(this.getFormat(),r,a)}hasFormat(r){const a=v.TEXT_TYPE_TO_FORMAT[r];return(this.getFormat()&a)!==0}setFormat(r){return v.$setState(this,sr,r)}toggleFormat(r){const a=this.getFormat(),o=v.toggleTextFormatType(a,r,null);return this.setFormat(o)}isInline(){return!0}createDOM(){return document.createElement("span")}updateDOM(){return!1}}function Pn(t){return t instanceof Ra}v.defineExtension({name:"@lexical/extension/DecoratorText",nodes:()=>[Ra],register:(t,r,a)=>t.registerCommand(v.FORMAT_TEXT_COMMAND,o=>{const i=v.$getSelection();if(v.$isNodeSelection(i)||v.$isRangeSelection(i))for(const s of i.getNodes())Pn(s)&&s.toggleFormat(o);return!1},v.COMMAND_PRIORITY_LOW)});function Da(t,r){let a;return De(t(),{unwatched(){a&&(a(),a=void 0)},watched(){this.value=t(),a=r(this)}})}const br=v.defineExtension({build:t=>Da(()=>t.getEditorState(),r=>t.registerUpdateListener(a=>{r.value=a.editorState})),name:"@lexical/extension/EditorState"});function it(t,...r){const a=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const i of r)o.append("v",i);throw a.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${a.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}function Oa(t,r){if(t&&r&&!Array.isArray(r)&&typeof t=="object"&&typeof r=="object"){const a=t,o=r;for(const i in o)a[i]=Oa(a[i],o[i]);return t}return r}const Er=0,xr=1,za=2,cr=3,Le=4,me=5,lr=6,Ee=7;function dr(t){return t.id===Er}function Ia(t){return t.id===za}function Ln(t){return function(r){return r.id===xr}(t)||it(305,String(t.id),String(xr)),Object.assign(t,{id:za})}const Vn=new Set;class Fn{constructor(r,a){Ot(this,"builder");Ot(this,"configs");Ot(this,"_dependency");Ot(this,"_peerNameSet");Ot(this,"extension");Ot(this,"state");Ot(this,"_signal");this.builder=r,this.extension=a,this.configs=new Set,this.state={id:Er}}mergeConfigs(){let r=this.extension.config||{};const a=this.extension.mergeConfig?this.extension.mergeConfig.bind(this.extension):v.shallowMergeConfig;for(const o of this.configs)r=a(r,o);return r}init(r){const a=this.state;Ia(a)||it(306,String(a.id));const o={getDependency:this.getInitDependency.bind(this),getDirectDependentNames:this.getDirectDependentNames.bind(this),getPeer:this.getInitPeer.bind(this),getPeerNameSet:this.getPeerNameSet.bind(this)},i={...o,getDependency:this.getDependency.bind(this),getInitResult:this.getInitResult.bind(this),getPeer:this.getPeer.bind(this)},s=function(d,u,w){return Object.assign(d,{config:u,id:cr,registerState:w})}(a,this.mergeConfigs(),o);let c;this.state=s,this.extension.init&&(c=this.extension.init(r,s.config,o)),this.state=function(d,u,w){return Object.assign(d,{id:Le,initResult:u,registerState:w})}(s,c,i)}build(r){const a=this.state;let o;a.id!==Le&&it(307,String(a.id),String(me)),this.extension.build&&(o=this.extension.build(r,a.config,a.registerState));const i={...a.registerState,getOutput:()=>o,getSignal:this.getSignal.bind(this)};this.state=function(s,c,d){return Object.assign(s,{id:me,output:c,registerState:d})}(a,o,i)}register(r,a){this._signal=a;const o=this.state;o.id!==me&&it(308,String(o.id),String(me));const i=this.extension.register&&this.extension.register(r,o.config,o.registerState);return this.state=function(s){return Object.assign(s,{id:lr})}(o),()=>{const s=this.state;s.id!==Ee&&it(309,String(o.id),String(Ee)),this.state=function(c){return Object.assign(c,{id:me})}(s),i&&i()}}afterRegistration(r){const a=this.state;let o;return a.id!==lr&&it(310,String(a.id),String(lr)),this.extension.afterRegistration&&(o=this.extension.afterRegistration(r,a.config,a.registerState)),this.state=function(i){return Object.assign(i,{id:Ee})}(a),o}getSignal(){return this._signal===void 0&&it(311),this._signal}getInitResult(){this.extension.init===void 0&&it(312,this.extension.name);const r=this.state;return function(a){return a.id>=Le}(r)||it(313,String(r.id),String(Le)),r.initResult}getInitPeer(r){const a=this.builder.extensionNameMap.get(r);return a?a.getExtensionInitDependency():void 0}getExtensionInitDependency(){const r=this.state;return function(a){return a.id>=cr}(r)||it(314,String(r.id),String(cr)),{config:r.config}}getPeer(r){const a=this.builder.extensionNameMap.get(r);return a?a.getExtensionDependency():void 0}getInitDependency(r){const a=this.builder.getExtensionRep(r);return a===void 0&&it(315,this.extension.name,r.name),a.getExtensionInitDependency()}getDependency(r){const a=this.builder.getExtensionRep(r);return a===void 0&&it(315,this.extension.name,r.name),a.getExtensionDependency()}getState(){const r=this.state;return function(a){return a.id>=Ee}(r)||it(316,String(r.id),String(Ee)),r}getDirectDependentNames(){return this.builder.incomingEdges.get(this.extension.name)||Vn}getPeerNameSet(){let r=this._peerNameSet;return r||(r=new Set((this.extension.peerDependencies||[]).map(([a])=>a)),this._peerNameSet=r),r}getExtensionDependency(){if(!this._dependency){const r=this.state;(function(a){return a.id>=me})(r)||it(317,this.extension.name),this._dependency={config:r.config,init:r.initResult,output:r.output}}return this._dependency}}const ta={tag:v.HISTORY_MERGE_TAG};function Gn(){const t=v.$getRoot();t.isEmpty()&&t.append(v.$createParagraphNode())}const Kn=v.defineExtension({config:v.safeCast({setOptions:ta,updateOptions:ta}),init:({$initialEditorState:t=Gn})=>({$initialEditorState:t,initialized:!1}),afterRegistration(t,{updateOptions:r,setOptions:a},o){const i=o.getInitResult();if(!i.initialized){i.initialized=!0;const{$initialEditorState:s}=i;if(v.$isEditorState(s))t.setEditorState(s,a);else if(typeof s=="function")t.update(()=>{s(t)},r);else if(s&&(typeof s=="string"||typeof s=="object")){const c=t.parseEditorState(s);t.setEditorState(c,a)}}return()=>{}},name:"@lexical/extension/InitialState",nodes:[v.RootNode,v.TextNode,v.LineBreakNode,v.TabNode,v.ParagraphNode]}),ea=Symbol.for("@lexical/extension/LexicalBuilder");function ra(){}function Un(t){throw t}function Ve(t){return Array.isArray(t)?t:[t]}const wr="0.43.0+prod.esm";class xe{constructor(r){Ot(this,"roots");Ot(this,"extensionNameMap");Ot(this,"outgoingConfigEdges");Ot(this,"incomingEdges");Ot(this,"conflicts");Ot(this,"_sortedExtensionReps");Ot(this,"PACKAGE_VERSION");this.outgoingConfigEdges=new Map,this.incomingEdges=new Map,this.extensionNameMap=new Map,this.conflicts=new Map,this.PACKAGE_VERSION=wr,this.roots=r;for(const a of r)this.addExtension(a)}static fromExtensions(r){const a=[Ve(Kn)];for(const o of r)a.push(Ve(o));return new xe(a)}static maybeFromEditor(r){const a=r[ea];return a&&(a.PACKAGE_VERSION!==wr&&it(292,a.PACKAGE_VERSION,wr),a instanceof xe||it(293)),a}static fromEditor(r){const a=xe.maybeFromEditor(r);return a===void 0&&it(294),a}constructEditor(){const{$initialEditorState:r,onError:a,...o}=this.buildCreateEditorArgs(),i=Object.assign(v.createEditor({...o,...a?{onError:s=>{a(s,i)}}:{}}),{[ea]:this});for(const s of this.sortedExtensionReps())s.build(i);return i}buildEditor(){let r=ra;function a(){try{r()}finally{r=ra}}const o=Object.assign(this.constructEditor(),{dispose:a,[Symbol.dispose]:a});return r=v.mergeRegister(this.registerEditor(o),()=>o.setRootElement(null)),o}hasExtensionByName(r){return this.extensionNameMap.has(r)}getExtensionRep(r){const a=this.extensionNameMap.get(r.name);if(a)return a.extension!==r&&it(295,r.name),a}addEdge(r,a,o){const i=this.outgoingConfigEdges.get(r);i?i.set(a,o):this.outgoingConfigEdges.set(r,new Map([[a,o]]));const s=this.incomingEdges.get(a);s?s.add(r):this.incomingEdges.set(a,new Set([r]))}addExtension(r){this._sortedExtensionReps!==void 0&&it(296);const a=Ve(r),[o]=a;typeof o.name!="string"&&it(297,typeof o.name);let i=this.extensionNameMap.get(o.name);if(i!==void 0&&i.extension!==o&&it(298,o.name),!i){i=new Fn(this,o),this.extensionNameMap.set(o.name,i);const s=this.conflicts.get(o.name);typeof s=="string"&&it(299,o.name,s);for(const c of o.conflictsWith||[])this.extensionNameMap.has(c)&&it(299,o.name,c),this.conflicts.set(c,o.name);for(const c of o.dependencies||[]){const d=Ve(c);this.addEdge(o.name,d[0].name,d.slice(1)),this.addExtension(d)}for(const[c,d]of o.peerDependencies||[])this.addEdge(o.name,c,d?[d]:[])}}sortedExtensionReps(){if(this._sortedExtensionReps)return this._sortedExtensionReps;const r=[],a=(o,i)=>{let s=o.state;if(Ia(s))return;const c=o.extension.name;var d;dr(s)||it(300,c,i||"[unknown]"),dr(d=s)||it(304,String(d.id),String(Er)),s=Object.assign(d,{id:xr}),o.state=s;const u=this.outgoingConfigEdges.get(c);if(u)for(const w of u.keys()){const p=this.extensionNameMap.get(w);p&&a(p,c)}s=Ln(s),o.state=s,r.push(o)};for(const o of this.extensionNameMap.values())dr(o.state)&&a(o);for(const o of r)for(const[i,s]of this.outgoingConfigEdges.get(o.extension.name)||[])if(s.length>0){const c=this.extensionNameMap.get(i);if(c)for(const d of s)c.configs.add(d)}for(const[o,...i]of this.roots)if(i.length>0){const s=this.extensionNameMap.get(o.name);s===void 0&&it(301,o.name);for(const c of i)s.configs.add(c)}return this._sortedExtensionReps=r,this._sortedExtensionReps}registerEditor(r){const a=this.sortedExtensionReps(),o=new AbortController,i=[()=>o.abort()],s=o.signal;for(const c of a){const d=c.register(r,s);d&&i.push(d)}for(const c of a){const d=c.afterRegistration(r);d&&i.push(d)}return v.mergeRegister(...i)}buildCreateEditorArgs(){const r={},a=new Set,o=new Map,i=new Map,s={},c={},d=this.sortedExtensionReps();for(const p of d){const{extension:g}=p;if(g.onError!==void 0&&(r.onError=g.onError),g.disableEvents!==void 0&&(r.disableEvents=g.disableEvents),g.parentEditor!==void 0&&(r.parentEditor=g.parentEditor),g.editable!==void 0&&(r.editable=g.editable),g.namespace!==void 0&&(r.namespace=g.namespace),g.$initialEditorState!==void 0&&(r.$initialEditorState=g.$initialEditorState),g.nodes)for(const f of Bn(g)){if(typeof f!="function"){const h=o.get(f.replace);h&&it(302,g.name,f.replace.name,h.extension.name),o.set(f.replace,p)}a.add(f)}if(g.html){if(g.html.export)for(const[f,h]of g.html.export.entries())i.set(f,h);g.html.import&&Object.assign(s,g.html.import)}g.theme&&Oa(c,g.theme)}Object.keys(c).length>0&&(r.theme=c),a.size&&(r.nodes=[...a]);const u=Object.keys(s).length>0,w=i.size>0;(u||w)&&(r.html={},u&&(r.html.import=s),w&&(r.html.export=i));for(const p of d)p.init(r);return r.onError||(r.onError=Un),r}}const qn=new Set,aa=v.defineExtension({build(t,r,a){const o=a.getDependency(br).output,i=De({watchedNodeKeys:new Map}),s=Da(()=>{},()=>Jt(()=>{const c=s.peek(),{watchedNodeKeys:d}=i.value;let u,w=!1;o.value.read(()=>{if(v.$getSelection())for(const[p,g]of d.entries()){if(g.size===0){d.delete(p);continue}const f=v.$getNodeByKey(p),h=f&&f.isSelected()||!1;w=w||h!==(!!c&&c.has(p)),h&&(u=u||new Set,u.add(p))}}),!w&&u&&c&&u.size===c.size||(s.value=u)}));return{watchNodeKey:function(c){const d=An(()=>(s.value||qn).has(c)),{watchedNodeKeys:u}=i.peek();let w=u.get(c);const p=w!==void 0;return w=w||new Set,w.add(d),p||(u.set(c,w),i.value={watchedNodeKeys:u}),d}}},dependencies:[br],name:"@lexical/extension/NodeSelection"}),Hn=v.createCommand("INSERT_HORIZONTAL_RULE_COMMAND");class ke extends v.DecoratorNode{static getType(){return"horizontalrule"}static clone(r){return new ke(r.__key)}static importJSON(r){return Sr().updateFromJSON(r)}static importDOM(){return{hr:()=>({conversion:Yn,priority:0})}}exportDOM(){return{element:document.createElement("hr")}}createDOM(r){const a=document.createElement("hr");return v.addClassNamesToElement(a,r.theme.hr),a}getTextContent(){return` +`}isInline(){return!1}updateDOM(){return!1}}function Yn(){return{node:Sr()}}function Sr(){return v.$create(ke)}function Xn(t){return t instanceof ke}v.defineExtension({dependencies:[br,aa],name:"@lexical/extension/HorizontalRule",nodes:()=>[ke],register(t,r,a){const{watchNodeKey:o}=a.getDependency(aa).output,i=De({nodeSelections:new Map}),s=t._config.theme.hrSelected??"selected";return v.mergeRegister(t.registerCommand(Hn,c=>{const d=v.$getSelection();if(!v.$isRangeSelection(d))return!1;if(d.focus.getNode()!==null){const u=Sr();Mn(u)}return!0},v.COMMAND_PRIORITY_EDITOR),t.registerCommand(v.CLICK_COMMAND,c=>{if(v.isDOMNode(c.target)){const d=v.$getNodeFromDOMNode(c.target);if(Xn(d))return function(u,w=!1){const p=v.$getSelection(),g=u.isSelected(),f=u.getKey();let h;w&&v.$isNodeSelection(p)?h=p:(h=v.$createNodeSelection(),v.$setSelection(h)),g?h.delete(f):h.add(f)}(d,c.shiftKey),!0}return!1},v.COMMAND_PRIORITY_LOW),t.registerMutationListener(ke,(c,d)=>{zn(()=>{let u=!1;const{nodeSelections:w}=i.peek();for(const[p,g]of c.entries())if(g==="destroyed")w.delete(p),u=!0;else{const f=w.get(p),h=t.getElementByKey(p);f?f.domNode.value=h:(u=!0,w.set(p,{domNode:De(h),selectedSignal:o(p)}))}u&&(i.value={nodeSelections:w})})}),Jt(()=>{const c=[];for(const{domNode:d,selectedSignal:u}of i.value.nodeSelections.values())c.push(Jt(()=>{const w=d.value;w&&(u.value?v.addClassNamesToElement(w,s):v.removeClassNamesFromElement(w,s))}));return v.mergeRegister(...c)}))}});v.defineExtension({build:(t,r)=>ye({inheritEditableFromParent:r.inheritEditableFromParent}),config:v.safeCast({$getParentEditor:function(){const t=v.$getEditor();return xe.fromEditor(t),t},inheritEditableFromParent:!1}),init:(t,r,a)=>{const o=r.$getParentEditor();t.parentEditor=o,t.theme=t.theme||o._config.theme},name:"@lexical/extension/NestedEditor",register:(t,r,a)=>Jt(()=>{const o=t._parentEditor;if(o&&a.getOutput().inheritEditableFromParent.value)return t.setEditable(o.isEditable()),o.registerEditableListener(t.setEditable.bind(t))})});v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({disabled:!1,onReposition:void 0}),name:"@lexical/utils/SelectionAlwaysOnDisplay",register:(t,r,a)=>{const o=a.getOutput();return Jt(()=>{if(!o.disabled.value)return Sn(t,o.onReposition.value)})}});function Aa(t){return t.canBeEmpty()}function Zn(t,r,a=Aa){return v.mergeRegister(t.registerCommand(v.KEY_TAB_COMMAND,o=>{const i=v.$getSelection();if(!v.$isRangeSelection(i))return!1;o.preventDefault();const s=function(c){if(c.getNodes().filter(f=>v.$isBlockElementNode(f)&&f.canIndent()).length>0)return!0;const d=c.anchor,u=c.focus,w=u.isBefore(d)?u:d,p=w.getNode(),g=Tn(p);if(g.canIndent()){const f=g.getKey();let h=v.$createRangeSelection();if(h.anchor.set(f,0,"element"),h.focus.set(f,0,"element"),h=v.$normalizeSelection__EXPERIMENTAL(h),h.anchor.is(w))return!0}return!1}(i)?o.shiftKey?v.OUTDENT_CONTENT_COMMAND:v.INDENT_CONTENT_COMMAND:v.INSERT_TAB_COMMAND;return t.dispatchCommand(s,void 0)},v.COMMAND_PRIORITY_EDITOR),t.registerCommand(v.INDENT_CONTENT_COMMAND,()=>{const o=typeof r=="number"?r:r?r.peek():null,i=v.$getSelection();if(!v.$isRangeSelection(i))return!1;const s=typeof a=="function"?a:a.peek();return Dn(c=>{if(s(c)){const d=c.getIndent()+1;(!o||dye(r),config:v.safeCast({$canIndent:Aa,disabled:!1,maxIndent:null}),name:"@lexical/extension/TabIndentation",register(t,r,a){const{disabled:o,maxIndent:i,$canIndent:s}=a.getOutput();return Jt(()=>{if(!o.value)return Zn(t,i,s)})}});const Wn=v.defineExtension({name:"@lexical/react/ReactProvider"});function Jn(){return v.$getRoot().getTextContent()}function Qn(t,r=!0){if(t)return!1;let a=Jn();return r&&(a=a.trim()),a===""}function ti(t){if(!Qn(t,!1))return!1;const r=v.$getRoot().getChildren(),a=r.length;if(a>1)return!1;for(let o=0;oti(t)}function Ba(t){const r=window.location.origin,a=o=>{if(o.origin!==r)return;const i=t.getRootElement();if(document.activeElement!==i)return;const s=o.data;if(typeof s=="string"){let c;try{c=JSON.parse(s)}catch{return}if(c&&c.protocol==="nuanria_messaging"&&c.type==="request"){const d=c.payload;if(d&&d.functionId==="makeChanges"){const u=d.args;if(u){const[w,p,g,f,h]=u;t.update(()=>{const m=v.$getSelection();if(v.$isRangeSelection(m)){const k=m.anchor;let b=k.getNode(),C=0,y=0;if(v.$isTextNode(b)&&w>=0&&p>=0&&(C=w,y=w+p,m.setTextNodeRange(b,C,b,y)),C===y&&g===""||(m.insertRawText(g),b=k.getNode()),v.$isTextNode(b)){C=f,y=f+h;const _=b.getTextContentSize();C=C>_?_:C,y=y>_?_:y,m.setTextNodeRange(b,C,b,y)}o.stopImmediatePropagation()}})}}}}};return window.addEventListener("message",a,!0),()=>{window.removeEventListener("message",a,!0)}}v.defineExtension({build:(t,r,a)=>ye(r),config:v.safeCast({disabled:typeof window>"u"}),name:"@lexical/dragon",register:(t,r,a)=>Jt(()=>a.getOutput().disabled.value?void 0:Ba(t))});function ei(t,...r){const a=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const i of r)o.append("v",i);throw a.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${a.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const Tr=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function ri({editor:t,ErrorBoundary:r}){return function(a,o){const[i,s]=l.useState(()=>a.getDecorators());return Tr(()=>a.registerDecoratorListener(c=>{Ur.flushSync(()=>{s(c)})}),[a]),l.useEffect(()=>{s(a.getDecorators())},[a]),l.useMemo(()=>{const c=[],d=Object.keys(i);for(let u=0;ua._onError(f),children:e.jsx(l.Suspense,{fallback:null,children:i[w]})}),g=a.getElementByKey(w);g!==null&&c.push(Ur.createPortal(p,g,w))}return c},[o,i,a])}(t,r)}function ai({editor:t,ErrorBoundary:r}){return function(a){const o=xe.maybeFromEditor(a);if(o&&o.hasExtensionByName(Wn.name)){for(const i of["@lexical/plain-text","@lexical/rich-text"])o.hasExtensionByName(i)&&ei(320,i);return!0}return!1}(t)?null:e.jsx(ri,{editor:t,ErrorBoundary:r})}function oa(t){return t.getEditorState().read($a(t.isComposing()))}function oi({contentEditable:t,placeholder:r=null,ErrorBoundary:a}){const[o]=Qt();return function(i){Tr(()=>v.mergeRegister(fr.registerRichText(i),Ba(i)),[i])}(o),e.jsxs(e.Fragment,{children:[t,e.jsx(ni,{content:r}),e.jsx(ai,{editor:o,ErrorBoundary:a})]})}function ni({content:t}){const[r]=Qt(),a=function(i){const[s,c]=l.useState(()=>oa(i));return Tr(()=>{function d(){const u=oa(i);c(u)}return d(),v.mergeRegister(i.registerUpdateListener(()=>{d()}),i.registerEditableListener(()=>{d()}))},[i]),s}(r),o=kn();return a?typeof t=="function"?t(o):t:null}function ii({defaultSelection:t}){const[r]=Qt();return l.useEffect(()=>{r.focus(()=>{const a=document.activeElement,o=r.getRootElement();o===null||a!==null&&o.contains(a)||o.focus({preventScroll:!0})},{defaultSelection:t})},[t,r]),null}const si=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function ci({onClear:t}){const[r]=Qt();return si(()=>Ma(r,t),[r,t]),null}const Pa=typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0?l.useLayoutEffect:l.useEffect;function li({editor:t,ariaActiveDescendant:r,ariaAutoComplete:a,ariaControls:o,ariaDescribedBy:i,ariaErrorMessage:s,ariaExpanded:c,ariaInvalid:d,ariaLabel:u,ariaLabelledBy:w,ariaMultiline:p,ariaOwns:g,ariaRequired:f,autoCapitalize:h,className:m,id:k,role:b="textbox",spellCheck:C=!0,style:y,tabIndex:_,"data-testid":B,...F},E){const[P,A]=l.useState(t.isEditable()),j=l.useCallback(z=>{z&&z.ownerDocument&&z.ownerDocument.defaultView?t.setRootElement(z):t.setRootElement(null)},[t]),V=l.useMemo(()=>function(...z){return N=>{for(const H of z)typeof H=="function"?H(N):H!=null&&(H.current=N)}}(E,j),[j,E]);return Pa(()=>(A(t.isEditable()),t.registerEditableListener(z=>{A(z)})),[t]),e.jsx("div",{"aria-activedescendant":P?r:void 0,"aria-autocomplete":P?a:"none","aria-controls":P?o:void 0,"aria-describedby":i,...s!=null?{"aria-errormessage":s}:{},"aria-expanded":P&&b==="combobox"?!!c:void 0,...d!=null?{"aria-invalid":d}:{},"aria-label":u,"aria-labelledby":w,"aria-multiline":p,"aria-owns":P?g:void 0,"aria-readonly":!P||void 0,"aria-required":f,autoCapitalize:h,className:m,contentEditable:P,"data-testid":B,id:k,ref:V,role:b,spellCheck:C,style:y,tabIndex:_,...F})}const di=l.forwardRef(li);function na(t){return t.getEditorState().read($a(t.isComposing()))}const wi=l.forwardRef(ui);function ui(t,r){const{placeholder:a,...o}=t,[i]=Qt();return e.jsxs(e.Fragment,{children:[e.jsx(di,{editor:i,...o,ref:r}),a!=null&&e.jsx(pi,{editor:i,content:a})]})}function pi({content:t,editor:r}){const a=function(c){const[d,u]=l.useState(()=>na(c));return Pa(()=>{function w(){const p=na(c);u(p)}return w(),v.mergeRegister(c.registerUpdateListener(()=>{w()}),c.registerEditableListener(()=>{w()}))},[c]),d}(r),[o,i]=l.useState(r.isEditable());if(l.useLayoutEffect(()=>(i(r.isEditable()),r.registerEditableListener(c=>{i(c)})),[r]),!a)return null;let s=null;return typeof t=="function"?s=t(o):t!==null&&(s=t),s===null?null:e.jsx("div",{"aria-hidden":!0,children:s})}function gi({placeholder:t,className:r,placeholderClassName:a}){return e.jsx(wi,{className:r??"ContentEditable__root tw:relative tw:block tw:min-h-11 tw:overflow-auto tw:px-3 tw:py-3 tw:text-sm tw:outline-hidden","aria-placeholder":t,placeholder:e.jsx("div",{className:a??"tw:pointer-events-none tw:absolute tw:top-0 tw:select-none tw:overflow-hidden tw:text-ellipsis tw:px-3 tw:py-3 tw:text-sm tw:text-muted-foreground",children:t})})}const La=l.createContext(void 0);function hi({activeEditor:t,$updateToolbar:r,blockType:a,setBlockType:o,showModal:i,children:s}){const c=l.useMemo(()=>({activeEditor:t,$updateToolbar:r,blockType:a,setBlockType:o,showModal:i}),[t,r,a,o,i]);return e.jsx(La.Provider,{value:c,children:s})}function Va(){const t=l.useContext(La);if(!t)throw new Error("useToolbarContext must be used within a ToolbarContext provider");return t}function fi(){const[t,r]=l.useState(void 0),a=l.useCallback(()=>{r(void 0)},[]),o=l.useMemo(()=>{if(t===void 0)return;const{title:s,content:c}=t;return e.jsx(n.Dialog,{open:!0,onOpenChange:a,children:e.jsxs(n.DialogContent,{children:[e.jsx(n.DialogHeader,{children:e.jsx(n.DialogTitle,{children:s})}),c]})})},[t,a]),i=l.useCallback((s,c,d=!1)=>{r({closeOnClickOutside:d,content:c(a),title:s})},[a]);return[o,i]}function mi({children:t}){const[r]=Qt(),[a,o]=l.useState(r),[i,s]=l.useState("paragraph"),[c,d]=fi(),u=()=>{};return l.useEffect(()=>a.registerCommand(v.SELECTION_CHANGE_COMMAND,(w,p)=>(o(p),!1),v.COMMAND_PRIORITY_CRITICAL),[a]),e.jsxs(hi,{activeEditor:a,$updateToolbar:u,blockType:i,setBlockType:s,showModal:d,children:[c,t({blockType:i})]})}function vi(t){const[r]=Qt(),{activeEditor:a}=Va();l.useEffect(()=>a.registerCommand(v.SELECTION_CHANGE_COMMAND,()=>{const o=v.$getSelection();return o&&t(o),!1},v.COMMAND_PRIORITY_CRITICAL),[r,t]),l.useEffect(()=>{a.getEditorState().read(()=>{const o=v.$getSelection();o&&t(o)})},[a,t])}const bi=er.cva("pr-twp tw:group/toggle tw:inline-flex tw:items-center tw:justify-center tw:gap-1 tw:rounded-lg tw:text-sm tw:font-medium tw:whitespace-nowrap tw:transition-all tw:outline-none tw:hover:bg-muted tw:hover:text-foreground tw:focus-visible:border-ring tw:focus-visible:ring-[3px] tw:focus-visible:ring-ring/50 tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-destructive/20 tw:aria-pressed:bg-muted tw:data-[state=on]:bg-muted tw:dark:aria-invalid:ring-destructive/40 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",{variants:{variant:{default:"tw:bg-transparent",outline:"tw:border tw:border-input tw:bg-transparent tw:hover:bg-muted"},size:{default:"tw:h-8 tw:min-w-8 tw:px-2.5 tw:has-data-[icon=inline-end]:pe-2 tw:has-data-[icon=inline-start]:ps-2",sm:"tw:h-7 tw:min-w-7 tw:rounded-[min(var(--tw-radius-md),12px)] tw:px-2.5 tw:text-[0.8rem] tw:has-data-[icon=inline-end]:pe-1.5 tw:has-data-[icon=inline-start]:ps-1.5 tw:[&_svg:not([class*=size-])]:size-3.5",lg:"tw:h-9 tw:min-w-9 tw:px-2.5 tw:has-data-[icon=inline-end]:pe-2 tw:has-data-[icon=inline-start]:ps-2"}},defaultVariants:{variant:"default",size:"default"}}),Fa=l.createContext({size:"default",variant:"default",spacing:0,orientation:"horizontal"});function Mr({className:t,variant:r,size:a,spacing:o=0,orientation:i="horizontal",children:s,...c}){const d=n.readDirection();return e.jsx(D.ToggleGroup.Root,{"data-slot":"toggle-group","data-variant":r,"data-size":a,"data-spacing":o,"data-orientation":i,style:{"--gap":o},className:n.cn("pr-twp tw:group/toggle-group tw:flex tw:w-fit tw:flex-row tw:items-center tw:gap-[--spacing(var(--gap))] tw:rounded-lg tw:data-[size=sm]:rounded-[min(var(--tw-radius-md),10px)] tw:data-vertical:flex-col tw:data-vertical:items-stretch",t),dir:d,...c,children:e.jsx(Fa.Provider,{value:l.useMemo(()=>({variant:r,size:a,spacing:o,orientation:i}),[r,a,o,i]),children:s})})}function Me({className:t,children:r,variant:a="default",size:o="default",...i}){const s=l.useContext(Fa);return e.jsx(D.ToggleGroup.Item,{"data-slot":"toggle-group-item","data-variant":s.variant||a,"data-size":s.size||o,"data-spacing":s.spacing,className:n.cn("tw:shrink-0 tw:group-data-[spacing=0]/toggle-group:rounded-none tw:group-data-[spacing=0]/toggle-group:px-2 tw:focus:z-10 tw:focus-visible:z-10 tw:group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pe-1.5 tw:group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:ps-1.5 tw:group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-s-lg tw:group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg tw:group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-e-lg tw:group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg tw:group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-s-0 tw:group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 tw:group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-s tw:group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",bi({variant:s.variant||a,size:s.size||o}),t),...i,children:r})}const ia=[{format:"bold",icon:R.BoldIcon,label:"Bold"},{format:"italic",icon:R.ItalicIcon,label:"Italic"}];function xi(){const{activeEditor:t}=Va(),[r,a]=l.useState([]),o=l.useCallback(i=>{if(v.$isRangeSelection(i)||Yo.$isTableSelection(i)){const s=[];ia.forEach(({format:c})=>{i.hasFormat(c)&&s.push(c)}),a(c=>c.length!==s.length||!s.every(d=>c.includes(d))?s:c)}},[]);return vi(o),e.jsx(Mr,{type:"multiple",value:r,onValueChange:a,variant:"outline",size:"sm",children:ia.map(({format:i,icon:s,label:c})=>e.jsx(Me,{value:i,"aria-label":c,onClick:()=>{t.dispatchCommand(v.FORMAT_TEXT_COMMAND,i)},children:e.jsx(s,{className:"tw:h-4 tw:w-4"})},i))})}function ki({onClear:t}){const[r]=Qt();l.useEffect(()=>{t&&t(()=>{r.dispatchCommand(v.CLEAR_EDITOR_COMMAND,void 0)})},[r,t])}function yi({placeholder:t="Start typing ...",autoFocus:r=!1,onClear:a}){const[,o]=l.useState(void 0),i=s=>{s!==void 0&&o(s)};return e.jsxs("div",{className:"tw:relative",children:[e.jsx(mi,{children:()=>e.jsx("div",{className:"tw:sticky tw:top-0 tw:z-10 tw:flex tw:gap-2 tw:overflow-auto tw:border-b tw:p-1",children:e.jsx(xi,{})})}),e.jsxs("div",{className:"tw:relative",children:[e.jsx(oi,{contentEditable:e.jsx("div",{ref:i,children:e.jsx(gi,{placeholder:t})}),ErrorBoundary:vn}),r&&e.jsx(ii,{defaultSelection:"rootEnd"}),e.jsx(ki,{onClear:a}),e.jsx(ci,{})]})]})}const _i={namespace:"commentEditor",theme:jr,nodes:Cr,onError:t=>{console.error(t)}};function We({editorState:t,editorSerializedState:r,onChange:a,onSerializedChange:o,placeholder:i="Start typing…",autoFocus:s=!1,onClear:c,className:d}){return e.jsx("div",{className:n.cn("pr-twp tw:overflow-hidden tw:rounded-lg tw:border tw:bg-background tw:shadow",d),children:e.jsx(un,{initialConfig:{..._i,...t?{editorState:t}:{},...r?{editorState:JSON.stringify(r)}:{}},children:e.jsxs(n.TooltipProvider,{children:[e.jsx(yi,{placeholder:i,autoFocus:s,onClear:c}),e.jsx(gn,{ignoreSelectionChange:!0,onChange:u=>{a==null||a(u),o==null||o(u.toJSON())}})]})})})}function Ga(t){const r=t.querySelector('[contenteditable="true"]');if(!r)return!1;r.focus();const a=window.getSelection(),o=document.createRange();return o.selectNodeContents(r),o.collapse(!1),a==null||a.removeAllRanges(),a==null||a.addRange(o),!0}function Ka(t){return t?t.some(r=>r&&"text"in r&&r.text.trim().length>0?!0:!r||!("children"in r)?!1:Ka(r.children)):!1}function Kt(t){var r;return(r=t==null?void 0:t.root)!=null&&r.children?Ka(t.root.children):!1}function ji(t){if(!t||t.trim()==="")throw new Error("Input HTML is empty");const r=ha.createHeadlessEditor({namespace:"EditorUtils",theme:jr,nodes:Cr,onError:o=>{console.error(o)}});let a;if(r.update(()=>{const i=new DOMParser().parseFromString(t,"text/html"),s=fa.$generateNodesFromDOM(r,i);v.$getRoot().clear(),v.$insertNodes(s)},{discrete:!0}),r.getEditorState().read(()=>{a=r.getEditorState().toJSON()}),!a)throw new Error("Failed to convert HTML to editor state");return a}function Je(t){const r=ha.createHeadlessEditor({namespace:"EditorUtils",theme:jr,nodes:Cr,onError:i=>{console.error(i)}}),a=r.parseEditorState(JSON.stringify(t));r.setEditorState(a);let o="";return r.getEditorState().read(()=>{o=fa.$generateHtmlFromNodes(r)}),o=o.replace(/\s+style="[^"]*"/g,"").replace(/\s+class="[^"]*"/g,"").replace(/(.*?)<\/span>/g,"$1").replace(/]*>(.*?)<\/strong><\/b>/g,"$1").replace(/]*>(.*?)<\/b><\/strong>/g,"$1").replace(/]*>(.*?)<\/em><\/i>/g,"$1").replace(/]*>(.*?)<\/i><\/em>/g,"$1").replace(/]*>(.*?)<\/span><\/u>/g,"$1").replace(/]*>(.*?)<\/span><\/s>/g,"$1").replace(//gi,"
"),o}function Rr(t){return["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Home","End"].includes(t.key)?(t.stopPropagation(),!0):!1}const Dr=Object.freeze(["%cancelButton_tooltip%","%acceptButton_tooltip%"]),sa=(t,r)=>t[r]??r;function Or({onCancelClick:t,onAcceptClick:r,canAccept:a=!0,localizedStrings:o={},className:i="tw:h-6 tw:w-6",acceptLabel:s}){const c=sa(o,"%cancelButton_tooltip%"),d=s??sa(o,"%acceptButton_tooltip%");return e.jsxs(n.ButtonGroup,{children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":c,className:i,size:"icon",onClick:t,variant:"secondary",children:e.jsx(R.X,{})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:c})})]})}),e.jsx(n.ButtonGroupSeparator,{}),e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":d,className:i,size:"icon",onClick:r,disabled:!a,children:e.jsx(R.Check,{})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:d})})]})})]})}const Ci="verseText",Ni=Object.freeze(["%conflict_note_description_verseText%","%conflict_note_choose_aria_label%","%conflict_note_stale_notice%","%conflict_note_resolve_failed%","%conflict_note_choose_prompt%","%conflict_note_option_keep_current%","%conflict_note_option_use_other%","%conflict_note_option_combine%","%conflict_note_save_and_resolve%","%conflict_note_save_disabled_tooltip%","%conflict_note_save_warning%","%conflict_note_no_result%","%conflict_note_outcome_used_other%","%conflict_note_outcome_combined%","%conflict_note_summary_unresolved%","%conflict_note_summary_resolved_kept_current%","%conflict_note_summary_resolved_used_other%","%conflict_note_summary_resolved_combined%"]),Ua=["tw:prose tw:max-w-none tw:break-words tw:text-sm tw:font-normal tw:text-foreground","tw:[&>blockquote]:border-s-0 tw:[&>blockquote]:p-0 tw:[&>blockquote]:ps-0 tw:[&>blockquote]:font-normal tw:[&>blockquote]:not-italic tw:[&>blockquote]:text-foreground","tw:prose-quoteless"].join(" ");function qa(t){return(t==null?void 0:t.conflictType)===Ci}function Ha(t){return t==="replaced"?"reject":t==="merged"?"merged":"accept"}function Ue(t,r){return t===""?r["%comment_assign_unassigned%"]??"Unassigned":t==="Team"?r["%comment_assign_team%"]??"Team":t}function zr(t){const r=n.isMacOs();return t.key==="Enter"&&(r&&t.metaKey||!r&&t.ctrlKey)}const Ei={root:{children:[{children:[{detail:0,format:0,mode:"normal",style:"",text:"",type:"text",version:1}],direction:"ltr",format:"",indent:0,type:"paragraph",version:1,textFormat:0,textStyle:""}],direction:"ltr",format:"",indent:0,type:"root",version:1}};function ur(t,r){return t===""?r["%commentEditor_unassigned%"]??"Unassigned":t==="Team"?r["%commentEditor_team%"]??"Team":t}function Si({assignableUsers:t,onSave:r,onClose:a,localizedStrings:o,initialAssignedUser:i}){const[s,c]=l.useState(Ei),[d,u]=l.useState(i),[w,p]=l.useState(!1),g=l.useRef(void 0),f=l.useRef(null);l.useEffect(()=>{let b=!0;const C=f.current;if(!C)return;const y=setTimeout(()=>{b&&Ga(C)},300);return()=>{b=!1,clearTimeout(y)}},[]);const h=l.useCallback(()=>{if(!Kt(s))return;const b=Je(s);r(b,d)},[s,r,d]),m=o["%commentEditor_placeholder%"]??"Type your comment here...",k=o["%commentEditor_assignTo_label%"]??"Assign to";return e.jsxs("div",{className:"pr-twp tw:grid tw:gap-3",children:[e.jsxs("div",{className:"tw:flex tw:items-center tw:justify-between",children:[e.jsx("span",{className:"tw:text-sm tw:font-medium",children:k}),e.jsx(Or,{onCancelClick:a,onAcceptClick:h,canAccept:Kt(s),localizedStrings:o,acceptLabel:o["%commentEditor_saveButton_tooltip%"]})]}),e.jsx("div",{className:"tw:flex tw:items-center tw:gap-2",children:e.jsxs(n.Popover,{open:w,onOpenChange:p,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"outline",className:"tw:flex tw:w-full tw:items-center tw:justify-start tw:gap-2",disabled:t.length===0,children:[e.jsx(R.AtSign,{className:"tw:h-4 tw:w-4"}),e.jsx("span",{children:ur(d!==void 0?d:"",o)})]})}),e.jsx(n.PopoverContent,{className:"tw:w-auto tw:p-0",align:"start",onKeyDown:b=>{b.key==="Escape"&&(b.stopPropagation(),p(!1))},children:e.jsx(n.Command,{children:e.jsx(n.CommandList,{children:t.map(b=>e.jsx(n.CommandItem,{onSelect:()=>{u(b||void 0),p(!1)},className:"tw:flex tw:items-center",children:e.jsx("span",{children:ur(b,o)})},b||"unassigned"))})})})]})}),e.jsx("div",{ref:f,role:"textbox",tabIndex:-1,className:"tw:outline-hidden",onKeyDownCapture:b=>{b.key==="Escape"?(b.preventDefault(),b.stopPropagation(),a()):zr(b)&&(b.preventDefault(),b.stopPropagation(),Kt(s)&&h())},onKeyDown:b=>{Rr(b),(b.key==="Enter"||b.key===" ")&&b.stopPropagation()},children:e.jsx(We,{editorSerializedState:s,onSerializedChange:b=>c(b),placeholder:m,onClear:b=>{g.current=b}})})]})}const Ti=Object.freeze(["%commentEditor_placeholder%","%commentEditor_assignTo_label%","%commentEditor_saveButton_tooltip%","%commentEditor_unassigned%","%commentEditor_team%",...Dr]),Mi=Object.freeze(["%comment_assign_team%","%comment_assign_unassigned%","%comment_assigned_to%","%comment_assigning_to%","%comment_dateAtTime%","%comment_date_today%","%comment_date_yesterday%","%comment_deleteComment%","%comment_editComment%","%comment_replyOrAssign%","%comment_reopenResolved%","%comment_status_resolved%","%comment_status_todo%","%comment_thread_multiple_replies%","%comment_thread_single_reply%","%comment_aria_assign_user%","%comment_aria_submit_comment%","%comment_aria_mark_as_read%","%comment_aria_mark_as_unread%","%comment_aria_resolve_thread%"]),Ya="comment-list";function Ri(t){return t}function Xa({className:t,size:r="default",...a}){return e.jsx("div",{"data-slot":"card","data-size":r,className:n.cn("pr-twp tw:group/card tw:flex tw:flex-col tw:gap-4 tw:overflow-hidden tw:rounded-xl tw:bg-card tw:py-4 tw:text-sm tw:text-card-foreground tw:ring-1 tw:ring-foreground/10 tw:has-data-[slot=card-footer]:pb-0 tw:has-[>img:first-child]:pt-0 tw:data-[size=sm]:gap-3 tw:data-[size=sm]:py-3 tw:data-[size=sm]:has-data-[slot=card-footer]:pb-0 tw:*:[img:first-child]:rounded-t-xl tw:*:[img:last-child]:rounded-b-xl",t),...a})}function Di({className:t,...r}){return e.jsx("div",{"data-slot":"card-header",className:n.cn("pr-twp tw:group/card-header tw:@container/card-header tw:grid tw:auto-rows-min tw:items-start tw:gap-1 tw:rounded-t-xl tw:px-4 tw:group-data-[size=sm]/card:px-3 tw:has-data-[slot=card-action]:grid-cols-[1fr_auto] tw:has-data-[slot=card-description]:grid-rows-[auto_auto] tw:[.border-b]:pb-4 tw:group-data-[size=sm]/card:[.border-b]:pb-3",t),...r})}function Oi({className:t,...r}){return e.jsx("div",{"data-slot":"card-title",className:n.cn("pr-twp tw:font-heading tw:text-base tw:leading-snug tw:font-medium tw:group-data-[size=sm]/card:text-sm",t),...r})}function zi({className:t,...r}){return e.jsx("div",{"data-slot":"card-description",className:n.cn("pr-twp tw:text-sm tw:text-muted-foreground",t),...r})}function Za({className:t,...r}){return e.jsx("div",{"data-slot":"card-content",className:n.cn("pr-twp tw:px-4 tw:group-data-[size=sm]/card:px-3",t),...r})}function Ii({className:t,...r}){return e.jsx("div",{"data-slot":"card-footer",className:n.cn("pr-twp tw:flex tw:items-center tw:rounded-b-xl tw:border-t tw:bg-muted/50 tw:p-4 tw:group-data-[size=sm]/card:p-3",t),...r})}function Wa({className:t,size:r="default",...a}){return e.jsx(D.Avatar.Root,{"data-slot":"avatar","data-size":r,className:n.cn("pr-twp tw:group/avatar tw:relative tw:flex tw:size-8 tw:shrink-0 tw:rounded-full tw:select-none tw:after:absolute tw:after:inset-0 tw:after:rounded-full tw:after:border tw:after:border-border tw:after:mix-blend-darken tw:data-[size=lg]:size-10 tw:data-[size=sm]:size-6 tw:dark:after:mix-blend-lighten",t),...a})}function Ai({className:t,...r}){return e.jsx(D.Avatar.Image,{"data-slot":"avatar-image",className:n.cn("pr-twp tw:aspect-square tw:size-full tw:rounded-full tw:object-cover",t),...r})}function Ja({className:t,...r}){return e.jsx(D.Avatar.Fallback,{"data-slot":"avatar-fallback",className:n.cn("pr-twp tw:flex tw:size-full tw:items-center tw:justify-center tw:rounded-full tw:bg-muted tw:text-sm tw:text-muted-foreground tw:group-data-[size=sm]/avatar:text-xs",t),...r})}function ca({comment:t,isReply:r=!1,localizedStrings:a,isThreadExpanded:o=!1,handleUpdateComment:i,handleDeleteComment:s,onEditingChange:c,canEditOrDelete:d=!1}){const[u,w]=l.useState(!1),[p,g]=l.useState(),f=l.useRef(null);l.useEffect(()=>{if(!u)return;let E=!0;const P=f.current;if(!P)return;const A=setTimeout(()=>{E&&Ga(P)},300);return()=>{E=!1,clearTimeout(A)}},[u]);const h=l.useCallback(E=>{E&&E.stopPropagation(),w(!1),g(void 0),c==null||c(!1)},[c]),m=l.useCallback(async E=>{if(E&&E.stopPropagation(),!p||!i)return;await i(t.id,Je(p))&&(w(!1),g(void 0),c==null||c(!1))},[p,i,t.id,c]),k=l.useMemo(()=>{const E=new Date(t.date),P=M.formatRelativeDate(E,a["%comment_date_today%"],a["%comment_date_yesterday%"]),A=E.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"});return M.formatReplacementString(a["%comment_dateAtTime%"],{date:P,time:A})},[t.date,a]),b=l.useMemo(()=>t.user,[t.user]),C=l.useMemo(()=>t.user.split(" ").map(E=>E[0]).join("").toUpperCase().slice(0,2),[t.user]),y=l.useMemo(()=>M.sanitizeHtml(t.contents),[t.contents]),_=l.useMemo(()=>t.contents.replace(/<[^>]*>/g,"").trim().length>0,[t.contents]),B=!!t.conflictResolutionAction&&!_,F=l.useMemo(()=>{if(o&&d)return e.jsxs(e.Fragment,{children:[e.jsxs(n.DropdownMenuItem,{onClick:E=>{E.stopPropagation(),w(!0),g(ji(t.contents)),c==null||c(!0)},children:[e.jsx(R.Pencil,{className:"tw:me-2 tw:h-4 tw:w-4"}),a["%comment_editComment%"]]}),e.jsxs(n.DropdownMenuItem,{onClick:async E=>{E.stopPropagation(),s&&await s(t.id)},children:[e.jsx(R.Trash2,{className:"tw:me-2 tw:h-4 tw:w-4"}),a["%comment_deleteComment%"]]})]})},[d,o,a,t.contents,t.id,s,c]);return e.jsxs("div",{className:n.cn("tw:flex tw:w-full tw:flex-row tw:items-baseline tw:gap-3 tw:space-y-3",{"tw:text-sm":r}),children:[e.jsx(Wa,{className:"tw:h-8 tw:w-8",children:e.jsx(Ja,{className:"tw:text-xs tw:font-medium",children:C})}),e.jsxs("div",{className:"tw:flex tw:flex-1 tw:flex-col tw:gap-2",children:[e.jsxs("div",{className:"tw:flex tw:w-full tw:flex-row tw:flex-wrap tw:items-baseline tw:gap-x-2",children:[e.jsx("p",{className:"tw:text-sm tw:font-medium",children:b}),e.jsx("p",{className:"tw:text-xs tw:font-normal tw:text-muted-foreground",children:k}),e.jsx("div",{className:"tw:flex-1"}),r&&t.assignedUser!==void 0&&e.jsxs(n.Badge,{variant:"secondary",className:"tw:text-xs tw:font-normal",children:["→ ",Ue(t.assignedUser,a)]})]}),u&&e.jsxs("div",{role:"textbox",tabIndex:-1,className:"tw:flex tw:flex-col tw:gap-2",ref:f,onKeyDownCapture:E=>{E.key==="Escape"?(E.preventDefault(),E.stopPropagation(),h()):zr(E)&&(E.preventDefault(),E.stopPropagation(),Kt(p)&&m())},onKeyDown:E=>{Rr(E),(E.key==="Enter"||E.key===" ")&&E.stopPropagation()},onClick:E=>{E.stopPropagation()},children:[e.jsx(We,{className:n.cn('tw:[&_[data-lexical-editor="true"]>blockquote]:mt-0 tw:[&_[data-lexical-editor="true"]>blockquote]:border-s-0 tw:[&_[data-lexical-editor="true"]>blockquote]:ps-0 tw:[&_[data-lexical-editor="true"]>blockquote]:font-normal tw:[&_[data-lexical-editor="true"]>blockquote]:not-italic tw:[&_[data-lexical-editor="true"]>blockquote]:text-foreground'),editorSerializedState:p,onSerializedChange:E=>g(E)}),e.jsxs("div",{className:"tw:flex tw:flex-row tw:items-start tw:justify-end tw:gap-2",children:[e.jsx(n.Button,{size:"icon",onClick:h,variant:"outline",className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",children:e.jsx(R.X,{})}),e.jsx(n.Button,{size:"icon",onClick:m,className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",disabled:!Kt(p),children:e.jsx(R.ArrowUp,{})})]})]}),!u&&e.jsxs(e.Fragment,{children:[t.status==="Resolved"&&!B&&e.jsx("div",{className:"tw:text-sm tw:italic",children:a["%comment_status_resolved%"]}),t.status==="Todo"&&r&&e.jsx("div",{className:"tw:text-sm tw:italic",children:a["%comment_status_todo%"]}),B?e.jsx("div",{className:"tw:text-sm tw:italic",children:Ha(t.conflictResolutionAction)==="merged"?a["%conflict_note_outcome_combined%"]??"Combined both changes.":a["%conflict_note_outcome_used_other%"]??"Used the other change instead of the current text."}):e.jsx("div",{className:n.cn(Ua,"tw:items-start tw:gap-2",{"tw:line-clamp-3":!o}),dangerouslySetInnerHTML:{__html:y}})]})]}),F&&e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:"ghost",size:"icon",children:e.jsx(R.MoreHorizontal,{})})}),e.jsx(n.DropdownMenuContent,{align:"end",children:F})]})]})}function Qa({show:t,disabled:r=!1,onClick:a,ariaLabel:o}){if(t)return e.jsx(n.Button,{variant:"ghost",size:"icon",disabled:r,className:n.cn("tw:ms-auto","tw:text-primary tw:transition-opacity tw:duration-200 tw:hover:bg-primary/10","tw:opacity-0 tw:group-hover:opacity-100"),onClick:i=>{i.stopPropagation(),a()},"aria-label":o,children:e.jsx(R.Check,{className:"tw:h-4 tw:w-4"})})}const la={root:{children:[{children:[{detail:0,format:0,mode:"normal",style:"",text:"",type:"text",version:1}],direction:"ltr",format:"",indent:0,type:"paragraph",version:1,textFormat:0,textStyle:""}],direction:"ltr",format:"",indent:0,type:"root",version:1}};function to({classNameForVerseText:t,comments:r,localizedStrings:a,isSelected:o=!1,verseRef:i,assignedUser:s,currentUser:c,handleSelectThread:d,threadId:u,thread:w,threadStatus:p,handleAddCommentToThread:g,handleUpdateComment:f,handleDeleteComment:h,handleReadStatusChange:m,assignableUsers:k,canUserAddCommentToThread:b,canUserAssignThreadCallback:C,canUserResolveThreadCallback:y,canUserEditOrDeleteCommentCallback:_,isRead:B=!1,autoReadDelay:F=5,onVerseRefClick:E,initialAssignedUser:P,activeComments:A,rootContentSlot:j,resolveActionSlot:V,spaceRootContentFromReplies:z=!1}){const[N,H]=l.useState(la),[U,G]=l.useState(),[I,T]=l.useState(),Z=o,[W,vt]=l.useState(!1),[bt,Mt]=l.useState(!1),[K,J]=l.useState(!1),[st,ot]=l.useState(!1),[gt,qt]=l.useState(!1),[et,Rt]=l.useState(B),[yt,Bt]=l.useState(!1),Ht=l.useRef(void 0),[O,Pt]=l.useState(new Map);l.useEffect(()=>{let S=!0;return(async()=>{const mt=y?await y(u):!1;S&&qt(mt)})(),()=>{S=!1}},[u,y]),l.useEffect(()=>{let S=!0;if(!o){ot(!1),Pt(new Map);return}return(async()=>{const mt=C?await C(u):!1;S&&ot(mt)})(),()=>{S=!1}},[o,u,C]);const ft=l.useRef("idle");l.useEffect(()=>{if(!o){ft.current!=="idle"&&(G(void 0),T(void 0),ft.current="idle");return}ft.current==="idle"&&(ft.current="pending"),st?ft.current==="pending"&&P!==void 0&&P!==s&&(G(P),ft.current="auto-populated"):ft.current==="auto-populated"&&(G(void 0),ft.current="pending")},[o,P,st,s]);const xt=l.useMemo(()=>A??r.filter(S=>!S.deleted),[A,r]);l.useEffect(()=>{let S=!0;if(!o||!_){Pt(new Map);return}return(async()=>{const mt=new Map;await Promise.all(xt.map(async Xt=>{const oe=await _(Xt.id);S&&mt.set(Xt.id,oe)})),S&&Pt(mt)})(),()=>{S=!1}},[o,xt,_]);const Vt=l.useMemo(()=>xt[0],[xt]),te=l.useRef(null),Yt=l.useRef(void 0),L=l.useCallback(()=>{var S;(S=Yt.current)==null||S.call(Yt),H(la)},[]),Y=l.useCallback(()=>{const S=!et;Rt(S),Bt(!S),m==null||m(u,S)},[et,m,u]);l.useEffect(()=>{vt(!1)},[o]),l.useEffect(()=>{if(o&&!et&&!yt){const S=setTimeout(()=>{Rt(!0),m==null||m(u,!0)},F*1e3);return Ht.current=S,()=>clearTimeout(S)}Ht.current&&(clearTimeout(Ht.current),Ht.current=void 0)},[o,et,yt,F,u,m]);const rt=l.useMemo(()=>({singleReply:a["%comment_thread_single_reply%"],multipleReplies:a["%comment_thread_multiple_replies%"]}),[a]),Q=l.useMemo(()=>{if(s===void 0)return;if(s==="")return a["%comment_assign_unassigned%"]??"Unassigned";const S=Ue(s,a);return M.formatReplacementString(a["%comment_assigned_to%"],{assignedUser:S})},[s,a]),ct=l.useMemo(()=>xt.slice(1),[xt]),nt=l.useMemo(()=>ct.length??0,[ct.length]),wt=l.useMemo(()=>nt>0,[nt]),lt=l.useMemo(()=>W||nt<=2?ct:ct.slice(-2),[ct,nt,W]),ut=l.useMemo(()=>W||nt<=2?0:nt-2,[nt,W]),_t=l.useMemo(()=>nt===1?rt.singleReply:M.formatReplacementString(rt.multipleReplies,{count:nt}),[nt,rt]),jt=l.useMemo(()=>ut===1?rt.singleReply:M.formatReplacementString(rt.multipleReplies,{count:ut}),[ut,rt]);l.useEffect(()=>{!o&&bt&&wt&&Mt(!1)},[o,bt,wt]);const At=l.useCallback(async S=>{S&&S.stopPropagation();const Nt=Kt(N)?Je(N):void 0;if(U!==void 0){await g({threadId:u,contents:Nt,assignedUser:U})&&(T(U),Nt&&L());return}Nt&&await g({threadId:u,contents:Nt})&&L()},[L,N,g,U,u]),Ct=l.useCallback(async S=>{const Nt=Kt(N)?Je(N):void 0,mt=S.status?S.assignedUser:U??S.assignedUser,Xt=await g({...S,contents:Nt,assignedUser:mt});return Xt&&(mt!==void 0&&T(mt),Nt&&L()),Xt},[L,N,g,U]);if(xt.length===0)return;const ae=e.jsx(ca,{comment:Vt,localizedStrings:a,isThreadExpanded:o,threadStatus:p,handleAddCommentToThread:Ct,handleUpdateComment:f,handleDeleteComment:h,onEditingChange:Mt,canEditOrDelete:(!bt&&O.get(Vt.id))??!1,canUserResolveThread:gt});return e.jsx(Xa,{role:"option","aria-selected":o,id:u,className:n.cn("tw:group tw:w-full tw:rounded-none tw:border-none tw:p-4 tw:outline-hidden tw:transition-all tw:duration-200 tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-1 tw:focus:ring-offset-background",{"tw:cursor-pointer tw:hover:shadow-md":!o},{"tw:bg-primary-foreground":!o&&p!=="Resolved"&&et,"tw:bg-background":o&&p!=="Resolved"&&et,"tw:bg-muted":p==="Resolved","tw:bg-accent":!et&&!o&&p!=="Resolved"}),onClick:()=>{d(u)},tabIndex:-1,children:e.jsxs(Za,{className:"tw:flex tw:flex-col tw:gap-2 tw:p-0",children:[e.jsxs("div",{className:"tw:flex tw:flex-col tw:content-center tw:items-start tw:gap-4",children:[e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",children:[Q&&e.jsx(n.Badge,{className:"tw:rounded-sm tw:bg-input tw:text-sm tw:font-normal tw:text-primary tw:hover:bg-input",children:Q}),e.jsx(n.Button,{variant:"ghost",size:"icon",onClick:S=>{S.stopPropagation(),Y()},className:"tw:text-muted-foreground tw:transition tw:hover:text-foreground","aria-label":et?a["%comment_aria_mark_as_unread%"]??"Mark as unread":a["%comment_aria_mark_as_read%"]??"Mark as read",children:et?e.jsx(R.MailOpen,{}):e.jsx(R.Mail,{})}),V===void 0?e.jsx(Qa,{show:gt&&p!=="Resolved",onClick:()=>Ct({threadId:u,status:"Resolved"}),ariaLabel:a["%comment_aria_resolve_thread%"]??"Resolve thread"}):V]}),e.jsx("div",{className:"tw:flex tw:max-w-full tw:flex-wrap tw:items-baseline tw:gap-2",children:e.jsxs("p",{ref:te,className:n.cn("tw:flex-1 tw:overflow-hidden tw:text-ellipsis tw:text-sm tw:font-normal tw:text-muted-foreground",{"tw:overflow-visible tw:text-clip tw:whitespace-normal tw:break-words":Z},{"tw:whitespace-nowrap":!Z}),children:[i&&E?e.jsx(n.Button,{variant:"ghost",size:"sm",className:"tw:h-auto tw:px-1 tw:py-0 tw:text-sm tw:font-normal tw:text-muted-foreground",onClick:S=>{S.stopPropagation(),E(w)},children:i}):i,e.jsxs("span",{className:t,children:[Vt.contextBefore,e.jsx("span",{className:"tw:font-bold",children:Vt.selectedText}),Vt.contextAfter]})]})}),j??ae]}),e.jsxs(e.Fragment,{children:[wt&&!o&&e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-5",children:[e.jsx("div",{className:"tw:w-8",children:e.jsx(n.Separator,{})}),e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:_t})]}),!o&&Kt(N)&&e.jsx(We,{editorSerializedState:N,onSerializedChange:S=>H(S),placeholder:a["%comment_replyOrAssign%"]}),o&&e.jsxs(e.Fragment,{children:[z&<.length>0&&e.jsx("div",{className:"tw:h-2","data-slot":"root-content-reply-gap","aria-hidden":"true"}),ut>0&&e.jsxs("div",{className:"tw:flex tw:cursor-pointer tw:items-center tw:gap-5 tw:py-2",onClick:S=>{S.stopPropagation(),vt(!0)},role:"button",tabIndex:0,onKeyDown:S=>{(S.key==="Enter"||S.key===" ")&&(S.preventDefault(),S.stopPropagation(),vt(!0))},children:[e.jsx("div",{className:"tw:w-8",children:e.jsx(n.Separator,{})}),e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",children:[e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:jt}),W?e.jsx(R.ChevronUp,{}):e.jsx(R.ChevronDown,{})]})]}),lt.map(S=>e.jsx("div",{children:e.jsx(ca,{comment:S,localizedStrings:a,isReply:!0,isThreadExpanded:o,handleUpdateComment:f,handleDeleteComment:h,onEditingChange:Mt,canEditOrDelete:(!bt&&O.get(S.id))??!1})},S.id)),b!==!1&&(!bt||Kt(N))&&e.jsxs("div",{role:"textbox",tabIndex:-1,className:"tw:w-full tw:space-y-2",onClick:S=>S.stopPropagation(),onKeyDownCapture:S=>{zr(S)&&(S.preventDefault(),S.stopPropagation(),(Kt(N)||U!==void 0&&U!==I)&&At())},onKeyDown:S=>{Rr(S),(S.key==="Enter"||S.key===" ")&&S.stopPropagation()},children:[e.jsx(We,{editorSerializedState:N,onSerializedChange:S=>H(S),placeholder:p==="Resolved"?a["%comment_reopenResolved%"]:a["%comment_replyOrAssign%"],autoFocus:!0,onClear:S=>{Yt.current=S}}),e.jsxs("div",{className:"tw:flex tw:flex-row tw:items-center tw:justify-end tw:gap-2",children:[U!==void 0&&(Kt(N)||U!==I)&&e.jsx("span",{className:"tw:flex-1 tw:text-sm tw:text-muted-foreground",children:M.formatReplacementString(a["%comment_assigning_to%"]??"Assigning to: {assignedUser}",{assignedUser:Ue(U,a)})}),e.jsxs(n.Popover,{open:K,onOpenChange:J,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsx(n.Button,{size:"icon",variant:"outline",className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",disabled:!st||!k||k.length===0||!k.includes(c),"aria-label":a["%comment_aria_assign_user%"]??"Assign user",children:e.jsx(R.AtSign,{})})}),e.jsx(n.PopoverContent,{className:"tw:w-auto tw:p-0",align:"end",onKeyDown:S=>{S.key==="Escape"&&(S.stopPropagation(),J(!1))},children:e.jsx(n.Command,{children:e.jsx(n.CommandList,{children:k==null?void 0:k.map(S=>e.jsx(n.CommandItem,{onSelect:()=>{G(S!==s?S:void 0),ft.current="user-selected",T(void 0),J(!1)},className:"tw:flex tw:items-center",children:e.jsx("span",{children:Ue(S,a)})},S||"unassigned"))})})})]}),e.jsx(n.Button,{size:"icon",onClick:At,className:"tw:flex tw:items-center tw:justify-center tw:rounded-md",disabled:!Kt(N)&&(U===void 0||U===I),"aria-label":a["%comment_aria_submit_comment%"]??"Submit comment",children:e.jsx(R.ArrowUp,{})})]})]})]})]})]})})}const $i=n.cn(Ua,"tw:[&>blockquote]:my-0 tw:[&_p]:my-0","tw:[&_u]:font-semibold tw:[&_u]:text-success-foreground tw:[&_u]:no-underline","tw:[&_s]:text-destructive tw:[&_s]:line-through"),Bi=t=>t.replace(/(\s+)(<\/[us]>)/g,"$2$1"),qe=t=>Bi(M.sanitizeHtml(t));function He({html:t}){return e.jsx("div",{className:$i,dangerouslySetInnerHTML:{__html:t}})}function eo({comment:t,localizedStrings:r,availableActions:a="acceptOrReject",resolvedResolution:o,onResolve:i,isResolving:s=!1}){const[c,d]=l.useState("accept"),u=l.useId(),w=l.useId(),p=a==="loading",g=a==="accept",f=a==="none",h=a==="acceptRejectOrMerge",m=g?"accept":c,k=l.useMemo(()=>qe(t.rejectedText??""),[t.rejectedText]),b=l.useMemo(()=>qe(t.acceptedText??""),[t.acceptedText]),C=l.useMemo(()=>qe(t.mergedText??""),[t.mergedText]),y=l.useMemo(()=>M.sanitizeHtml(t.contents),[t.contents]);if(!qa(t))return e.jsx(He,{html:y});const _=I=>{d(I==="reject"||I==="merge"?I:"accept")},B=r["%conflict_note_stale_notice%"]??"The verse was edited after this conflict was recorded, so 'Use the other change' is no longer available. Keep the current text to resolve.",F=h?[{value:"merge",label:r["%conflict_note_option_combine%"]??"Combine both changes",html:C}]:[],E=[{value:"accept",label:r["%conflict_note_option_keep_current%"]??"Keep the current text",html:b},{value:"reject",label:r["%conflict_note_option_use_other%"]??"Use the other change",html:k},...F],P=m==="accept",A=s||P;let j;P?j=r["%conflict_note_save_disabled_tooltip%"]??"Keeping the current text makes no change — resolve the thread with the ✓ to keep it.":s||(j=r["%conflict_note_save_warning%"]??"This can't be undone.");const V=r["%conflict_note_no_result%"]??"No result preview available.",z=e.jsx("p",{className:"tw:text-muted-foreground",children:V}),N=I=>I?e.jsx("p",{className:"tw:whitespace-pre-wrap tw:text-foreground",children:I}):z,H=()=>{const I=o??"accept";return I==="merged"?t.mergedText?e.jsx(He,{html:C}):z:N(I==="reject"?t.rejectedResultText:t.resultText)},U=I=>g&&I.value==="reject",G=I=>{const T=m===I.value,Z=`${w}-${I.value}`,W=U(I);return e.jsxs("label",{htmlFor:Z,"data-slot":"conflict-resolution-option","data-value":I.value,className:n.cn("tw:flex tw:flex-col tw:gap-1 tw:rounded-md tw:border tw:p-2","tw:focus-within:ring-2 tw:focus-within:ring-ring tw:focus-within:ring-offset-1",T?"tw:border-border tw:bg-accent/50":"tw:border-transparent tw:hover:bg-accent/30",W?"tw:cursor-not-allowed tw:opacity-60":"tw:cursor-pointer"),children:[e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",children:[e.jsx(Re,{id:Z,value:I.value,"aria-label":I.label,disabled:W,"aria-describedby":W?u:void 0}),e.jsx("span",{"aria-hidden":!0,className:"tw:font-medium",children:I.label})]}),W&&e.jsx("span",{id:u,className:"tw:sr-only",children:B}),e.jsx(He,{html:I.html})]},I.value)};return e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-3 tw:text-sm",onClick:I=>I.stopPropagation(),children:[e.jsx("p",{children:r["%conflict_note_description_verseText%"]??"Conflicting changes were made to the verse text."}),p&&e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2","data-slot":"conflict-loading",children:[e.jsx(n.Skeleton,{className:"tw:h-8 tw:w-full"}),e.jsx(n.Skeleton,{className:"tw:h-8 tw:w-full"}),e.jsx(n.Skeleton,{className:"tw:h-8 tw:w-24"})]}),!p&&f&&H(),!p&&!f&&e.jsxs(e.Fragment,{children:[e.jsx("p",{children:r["%conflict_note_choose_prompt%"]??"Select which change to keep:"}),e.jsx(rr,{value:m,onValueChange:_,disabled:s,"aria-label":r["%conflict_note_choose_aria_label%"]??"Choose resolution",children:E.map(I=>U(I)?e.jsx(n.TooltipProvider,{delayDuration:0,children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:G(I)}),e.jsx(n.TooltipContent,{children:B})]})},I.value):G(I))}),e.jsx(n.TooltipProvider,{delayDuration:0,children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx("span",{className:"tw:inline-flex tw:self-start",children:e.jsx(n.Button,{size:"sm",disabled:A,onClick:()=>i==null?void 0:i(m),children:r["%conflict_note_save_and_resolve%"]??"Save and resolve"})})}),j&&e.jsx(n.TooltipContent,{children:j})]})})]})]})}const Pi={accept:{key:"%conflict_note_summary_resolved_kept_current%",fallback:"Conflicting edits were resolved. Kept the current text."},reject:{key:"%conflict_note_summary_resolved_used_other%",fallback:"Conflicting edits were resolved. Used the other change."},merged:{key:"%conflict_note_summary_resolved_combined%",fallback:"Conflicting edits were resolved. Combined both changes."}};function Li({comment:t,localizedStrings:r,resolvedResolution:a}){const o=l.useMemo(()=>qe(t.rejectedText??""),[t.rejectedText]);if(a){const{key:s,fallback:c}=Pi[a];return e.jsx("p",{className:"tw:text-sm tw:font-normal tw:text-muted-foreground",children:r[s]??c})}const i=r["%conflict_note_summary_unresolved%"]??"Conflicting edits. Choose which change to keep.";return e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-1",children:[e.jsx("p",{className:"tw:text-sm tw:font-normal tw:text-muted-foreground",children:i}),o?e.jsx(He,{html:o}):void 0]})}function Vi(t){return t==="reject"?"reject":t==="merge"?"merged":"accept"}function Fi({threadId:t,threadStatus:r,isSelected:a,activeComments:o,conflictResolution:i}){const[s,c]=l.useState("loading"),[d,u]=l.useState(!1),[w,p]=l.useState(),g=i==null?void 0:i.getOptions,f=i==null?void 0:i.resolve;l.useEffect(()=>{let y=!0;if(!a){c("loading");return}return(async()=>{let B;try{B=g?await g(t):"none"}catch{B="none"}y&&(c(B),B!=="none"&&p(void 0))})(),()=>{y=!1}},[a,t,r,g]);const h=l.useRef(!1),m=l.useCallback(async y=>{if(!(!f||h.current)){h.current=!0,u(!0);try{await f(t,y)&&(p(Vi(y)),c("none"))}catch{}finally{h.current=!1,u(!1)}}},[f,t]),b=l.useMemo(()=>{if(r==="Resolved"){for(let y=o.length-1;y>=0;y-=1)if(o[y].status==="Resolved")return Ha(o[y].conflictResolutionAction);return"accept"}},[r,o])??w;return{conflictOptions:s,isResolving:d,resolve:m,resolvedResolution:b,showResolveCheck:s!=="loading"&&s!=="none"}}function Gi(t){const{comments:r,localizedStrings:a,isSelected:o=!1,threadId:i,threadStatus:s,conflictResolution:c}=t,d=l.useMemo(()=>r.filter(C=>!C.deleted),[r]),u=l.useMemo(()=>d.find(C=>C.conflictType)??d[0],[d]),{conflictOptions:w,isResolving:p,resolve:g,resolvedResolution:f,showResolveCheck:h}=Fi({threadId:i,threadStatus:s,isSelected:o,activeComments:d,conflictResolution:c}),m=qa(u);let k;m&&u&&(k=o?e.jsx(eo,{comment:u,localizedStrings:a,availableActions:w,resolvedResolution:f,onResolve:g,isResolving:p}):e.jsx(Li,{comment:u,localizedStrings:a,resolvedResolution:f}));let b;return m&&(b=e.jsx(Qa,{show:h,disabled:p,onClick:()=>g("accept"),ariaLabel:a["%comment_aria_resolve_thread%"]??"Resolve thread"})),e.jsx(to,{...t,activeComments:d,rootContentSlot:k,resolveActionSlot:b,spaceRootContentFromReplies:m&&o})}function Ki({className:t="",classNameForVerseText:r,threads:a,currentUser:o,localizedStrings:i,handleAddCommentToThread:s,handleUpdateComment:c,handleDeleteComment:d,handleReadStatusChange:u,assignableUsers:w,canUserAddCommentToThread:p,canUserAssignThreadCallback:g,canUserResolveThreadCallback:f,canUserEditOrDeleteCommentCallback:h,selectedThreadId:m,onSelectedThreadChange:k,onVerseRefClick:b,conflictResolution:C}){const[y,_]=l.useState(new Set),[B,F]=l.useState(),[E,P]=l.useState(),A=l.useCallback(async T=>{const Z=await s(T);return Z!==void 0&&T.assignedUser!==void 0&&T.assignedUser!==""&&P(T.assignedUser),Z},[s]);l.useEffect(()=>{m&&(_(T=>new Set(T).add(m)),F(m))},[m]);const j=a.filter(T=>T.comments.some(Z=>!Z.deleted)),V=j.map(T=>({id:T.id})),z=l.useCallback(T=>{_(Z=>new Set(Z).add(T.id)),F(T.id),k==null||k(T.id)},[k]),N=l.useCallback(T=>{const Z=y.has(T);_(W=>{const vt=new Set(W);return vt.has(T)?vt.delete(T):vt.add(T),vt}),F(T),k==null||k(Z?void 0:T)},[y,k]),{listboxRef:H,activeId:U,handleKeyDown:G}=n.useListbox({options:V,onOptionSelect:z}),I=l.useCallback(T=>{T.key==="Escape"?(B&&y.has(B)&&(_(Z=>{const W=new Set(Z);return W.delete(B),W}),F(void 0),k==null||k(void 0)),T.preventDefault(),T.stopPropagation()):G(T)},[B,y,G,k]);return e.jsx("div",{id:Ya,role:"listbox",tabIndex:0,ref:H,"aria-activedescendant":U??void 0,"aria-label":"Comments",className:n.cn("tw:flex tw:w-full tw:flex-col tw:space-y-3 tw:outline-hidden tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-1 tw:focus:ring-offset-background",t),onKeyDown:I,children:j.map(T=>{const Z={classNameForVerseText:r,comments:T.comments,localizedStrings:i,verseRef:T.verseRef,handleSelectThread:N,threadId:T.id,thread:T,isRead:T.isRead,isSelected:y.has(T.id),currentUser:o,assignedUser:T.assignedUser,threadStatus:T.status,handleAddCommentToThread:A,handleUpdateComment:c,handleDeleteComment:d,handleReadStatusChange:u,assignableUsers:w,canUserAddCommentToThread:p,canUserAssignThreadCallback:g,canUserResolveThreadCallback:f,canUserEditOrDeleteCommentCallback:h,onVerseRefClick:b,initialAssignedUser:E};return e.jsx("div",{className:n.cn({"tw:opacity-60":T.status==="Resolved"}),children:T.type==="Conflict"?e.jsx(Gi,{...Z,conflictResolution:C}):e.jsx(to,{...Z})},T.id)})})}function Ui({table:t}){return e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"outline",size:"sm",className:"tw:ml-auto tw:hidden tw:h-8 tw:lg:flex",children:[e.jsx(R.FilterIcon,{className:"tw:mr-2 tw:h-4 tw:w-4"}),"View"]})}),e.jsxs(n.DropdownMenuContent,{align:"end",className:"tw:w-[150px]",children:[e.jsx(n.DropdownMenuLabel,{children:"Toggle columns"}),e.jsx(n.DropdownMenuSeparator,{}),t.getAllColumns().filter(r=>r.getCanHide()).map(r=>e.jsx(n.DropdownMenuCheckboxItem,{className:"tw:capitalize",checked:r.getIsVisible(),onCheckedChange:a=>r.toggleVisibility(!!a),children:r.id},r.id))]})]})}function ue({...t}){return e.jsx(D.Select.Root,{"data-slot":"select",...t})}function ro({className:t,...r}){return e.jsx(D.Select.Group,{"data-slot":"select-group",className:n.cn("tw:scroll-my-1 tw:p-1",t),...r})}function pe({...t}){return e.jsx(D.Select.Value,{"data-slot":"select-value",...t})}function ge({className:t,size:r="default",children:a,...o}){const i=n.readDirection();return e.jsxs(D.Select.Trigger,{"data-slot":"select-trigger","data-size":r,className:n.cn("pr-twp tw:flex tw:w-fit tw:items-center tw:gap-2 tw:rounded-lg tw:border tw:border-input tw:bg-transparent tw:py-2 tw:pe-2 tw:ps-2.5 tw:text-sm tw:whitespace-nowrap tw:transition-colors tw:outline-none tw:select-none tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:data-placeholder:text-muted-foreground tw:data-[size=default]:h-8 tw:data-[size=sm]:h-7 tw:data-[size=sm]:rounded-[min(var(--tw-radius-md),10px)] tw:*:data-[slot=select-value]:line-clamp-1 tw:*:data-[slot=select-value]:flex tw:*:data-[slot=select-value]:flex-1 tw:*:data-[slot=select-value]:items-center tw:*:data-[slot=select-value]:gap-1.5 tw:*:data-[slot=select-value]:text-start tw:dark:bg-input/30 tw:dark:hover:bg-input/50 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),dir:i,...o,children:[a,e.jsx(D.Select.Icon,{asChild:!0,children:e.jsx(Tt.IconSelector,{className:"tw:pointer-events-none tw:size-4 tw:text-muted-foreground"})})]})}function he({className:t,children:r,position:a="popper",align:o="center",style:i,...s}){const c=n.readDirection();return e.jsx(D.Select.Portal,{children:e.jsxs(D.Select.Content,{"data-slot":"select-content","data-align-trigger":a==="item-aligned",className:n.cn("pr-twp tw:relative tw:max-h-(--radix-select-content-available-height) tw:data-[align-trigger=true]:min-w-(--radix-select-trigger-width) tw:data-[align-trigger=false]:min-w-36 tw:origin-(--radix-select-content-transform-origin) tw:overflow-x-hidden tw:overflow-y-auto tw:rounded-lg tw:bg-popover tw:text-popover-foreground tw:shadow-md tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[align-trigger=true]:animate-none tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",a==="popper"&&"tw:data-[side=bottom]:translate-y-1 tw:data-[side=left]:-translate-x-1 tw:rtl:data-[side=left]:translate-x-1 tw:data-[side=right]:translate-x-1 tw:rtl:data-[side=right]:-translate-x-1 tw:data-[side=top]:-translate-y-1",t),style:{zIndex:n.Z_INDEX_ABOVE_DOCK,...i},position:a,align:o,...s,children:[e.jsx(ao,{}),e.jsx(D.Select.Viewport,{"data-position":a,className:n.cn("tw:data-[position=popper]:h-(--radix-select-trigger-height) tw:data-[position=popper]:w-full tw:data-[position=popper]:min-w-(--radix-select-trigger-width)",a==="popper"&&"tw:"),children:e.jsx("div",{dir:c,children:r})}),e.jsx(oo,{})]})})}function qi({className:t,...r}){return e.jsx(D.Select.Label,{"data-slot":"select-label",className:n.cn("pr-twp tw:px-1.5 tw:py-1 tw:text-xs tw:text-muted-foreground",t),...r})}function Ut({className:t,children:r,...a}){return e.jsxs(D.Select.Item,{"data-slot":"select-item",className:n.cn("pr-twp tw:relative tw:flex tw:w-full tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:py-1 tw:pe-8 tw:ps-1.5 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:not-data-[variant=destructive]:focus:**:text-accent-foreground tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4 tw:*:[span]:last:flex tw:*:[span]:last:items-center tw:*:[span]:last:gap-2",t),...a,children:[e.jsx("span",{className:"tw:pointer-events-none tw:absolute tw:end-2 tw:flex tw:size-4 tw:items-center tw:justify-center",children:e.jsx(D.Select.ItemIndicator,{children:e.jsx(Tt.IconCheck,{className:"tw:pointer-events-none"})})}),e.jsx(D.Select.ItemText,{children:r})]})}function Hi({className:t,...r}){return e.jsx(D.Select.Separator,{"data-slot":"select-separator",className:n.cn("pr-twp tw:pointer-events-none tw:-mx-1 tw:my-1 tw:h-px tw:bg-border",t),...r})}function ao({className:t,...r}){return e.jsx(D.Select.ScrollUpButton,{"data-slot":"select-scroll-up-button",className:n.cn("pr-twp tw:z-10 tw:flex tw:cursor-default tw:items-center tw:justify-center tw:bg-popover tw:py-1 tw:[&_svg:not([class*=size-])]:size-4",t),...r,children:e.jsx(Tt.IconChevronUp,{})})}function oo({className:t,...r}){return e.jsx(D.Select.ScrollDownButton,{"data-slot":"select-scroll-down-button",className:n.cn("pr-twp tw:z-10 tw:flex tw:cursor-default tw:items-center tw:justify-center tw:bg-popover tw:py-1 tw:[&_svg:not([class*=size-])]:size-4",t),...r,children:e.jsx(Tt.IconChevronDown,{})})}function Yi({table:t}){return e.jsx("div",{className:"tw:flex tw:items-center tw:justify-between tw:px-2 tw:pb-3 tw:pt-3",children:e.jsxs("div",{className:"tw:flex tw:items-center tw:space-x-6 tw:lg:space-x-8",children:[e.jsxs("div",{className:"tw:flex-1 tw:text-sm tw:text-muted-foreground",children:[t.getFilteredSelectedRowModel().rows.length," of"," ",t.getFilteredRowModel().rows.length," row(s) selected"]}),e.jsxs("div",{className:"tw:flex tw:items-center tw:space-x-2",children:[e.jsx("p",{className:"tw:text-nowrap tw:text-sm tw:font-medium",children:"Rows per page"}),e.jsxs(ue,{value:`${t.getState().pagination.pageSize}`,onValueChange:r=>{t.setPageSize(Number(r))},children:[e.jsx(ge,{className:"tw:h-8 tw:w-[70px]",children:e.jsx(pe,{placeholder:t.getState().pagination.pageSize})}),e.jsx(he,{side:"top",children:[10,20,30,40,50].map(r=>e.jsx(Ut,{value:`${r}`,children:r},r))})]})]}),e.jsxs("div",{className:"tw:flex tw:w-[100px] tw:items-center tw:justify-center tw:text-sm tw:font-medium",children:["Page ",t.getState().pagination.pageIndex+1," of ",t.getPageCount()]}),e.jsxs("div",{className:"tw:flex tw:items-center tw:space-x-2",children:[e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:hidden tw:h-8 tw:w-8 tw:p-0 tw:lg:flex",onClick:()=>t.setPageIndex(0),disabled:!t.getCanPreviousPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to first page"}),e.jsx(R.ArrowLeftIcon,{className:"tw:h-4 tw:w-4"})]}),e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:h-8 tw:w-8 tw:p-0",onClick:()=>t.previousPage(),disabled:!t.getCanPreviousPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to previous page"}),e.jsx(R.ChevronLeftIcon,{className:"tw:h-4 tw:w-4"})]}),e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:h-8 tw:w-8 tw:p-0",onClick:()=>t.nextPage(),disabled:!t.getCanNextPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to next page"}),e.jsx(R.ChevronRightIcon,{className:"tw:h-4 tw:w-4"})]}),e.jsxs(n.Button,{variant:"outline",size:"icon",className:"tw:hidden tw:h-8 tw:w-8 tw:p-0 tw:lg:flex",onClick:()=>t.setPageIndex(t.getPageCount()-1),disabled:!t.getCanNextPage(),children:[e.jsx("span",{className:"tw:sr-only",children:"Go to last page"}),e.jsx(R.ArrowRightIcon,{className:"tw:h-4 tw:w-4"})]})]})]})})}function no({columns:t,data:r,enablePagination:a=!1,showPaginationControls:o=!1,showColumnVisibilityControls:i=!1,stickyHeader:s=!1,onRowClickHandler:c=()=>{},id:d,isLoading:u=!1,noResultsMessage:w}){var E;const[p,g]=l.useState([]),[f,h]=l.useState([]),[m,k]=l.useState({}),[b,C]=l.useState({}),y=l.useMemo(()=>r??[],[r]),_=It.useReactTable({data:y,columns:t,getCoreRowModel:It.getCoreRowModel(),...a&&{getPaginationRowModel:It.getPaginationRowModel()},onSortingChange:g,getSortedRowModel:It.getSortedRowModel(),onColumnFiltersChange:h,getFilteredRowModel:It.getFilteredRowModel(),onColumnVisibilityChange:k,onRowSelectionChange:C,state:{sorting:p,columnFilters:f,columnVisibility:m,rowSelection:b}}),B=_.getVisibleFlatColumns();let F;return u?F=Array.from({length:10}).map((j,V)=>`skeleton-row-${V}`).map(j=>e.jsx(n.TableRow,{className:"tw:hover:bg-transparent",children:e.jsx(n.TableCell,{colSpan:B.length??t.length,className:"tw:border-0 tw:p-0",children:e.jsx("div",{className:"tw:w-full tw:py-2",children:e.jsx(n.Skeleton,{className:"tw:h-14 tw:w-full tw:rounded-md"})})})},j)):((E=_.getRowModel().rows)==null?void 0:E.length)>0?F=_.getRowModel().rows.map(P=>e.jsx(n.TableRow,{onClick:()=>c(P,_),"data-state":P.getIsSelected()&&"selected",children:P.getVisibleCells().map(A=>e.jsx(n.TableCell,{children:It.flexRender(A.column.columnDef.cell,A.getContext())},A.id))},P.id)):F=e.jsx(n.TableRow,{children:e.jsx(n.TableCell,{colSpan:t.length,className:"tw:h-24 tw:text-center",children:w})}),e.jsxs("div",{className:"pr-twp",id:d,children:[i&&e.jsx(Ui,{table:_}),e.jsxs(n.Table,{stickyHeader:s,children:[e.jsx(n.TableHeader,{stickyHeader:s,children:_.getHeaderGroups().map(P=>e.jsx(n.TableRow,{children:P.headers.map(A=>e.jsx(n.TableHead,{className:"tw:p-0",children:A.isPlaceholder?void 0:It.flexRender(A.column.columnDef.header,A.getContext())},A.id))},P.id))}),e.jsx(n.TableBody,{children:F})]}),a&&e.jsxs("div",{className:"tw:flex tw:items-center tw:justify-end tw:space-x-2 tw:py-4",children:[e.jsx(n.Button,{variant:"outline",size:"sm",onClick:()=>_.previousPage(),disabled:!_.getCanPreviousPage(),children:"Previous"}),e.jsx(n.Button,{variant:"outline",size:"sm",onClick:()=>_.nextPage(),disabled:!_.getCanNextPage(),children:"Next"})]}),a&&o&&e.jsx(Yi,{table:_})]})}function Xi({id:t,markdown:r,className:a,anchorTarget:o,truncate:i}){const s=l.useMemo(()=>({overrides:{a:{props:{target:o}}}}),[o]);return e.jsx("div",{id:t,className:n.cn("pr-twp tw:prose",{"tw:line-clamp-3 tw:max-h-10 tw:overflow-hidden tw:text-ellipsis tw:break-words":i},a),children:e.jsx(Xo,{options:s,children:r})})}const io=Object.freeze(["%webView_error_dump_header%","%webView_error_dump_info_message%"]),da=(t,r)=>t[r]??r;function so({errorDetails:t,handleCopyNotify:r,localizedStrings:a,id:o}){const i=da(a,"%webView_error_dump_header%"),s=da(a,"%webView_error_dump_info_message%");function c(){navigator.clipboard.writeText(t),r&&r()}return e.jsxs("div",{id:o,className:"tw:inline-flex tw:w-full tw:flex-col tw:items-start tw:justify-start tw:gap-4",children:[e.jsxs("div",{className:"tw:inline-flex tw:items-start tw:justify-start tw:gap-4 tw:self-stretch",children:[e.jsxs("div",{className:"tw:inline-flex tw:flex-1 tw:flex-col tw:items-start tw:justify-start",children:[e.jsx("div",{className:"tw:text-color-text tw:justify-center tw:text-center tw:text-lg tw:font-semibold tw:leading-loose",children:i}),e.jsx("div",{className:"tw:justify-center tw:self-stretch tw:text-sm tw:font-normal tw:leading-tight tw:text-muted-foreground",children:s})]}),e.jsx(n.Button,{variant:"secondary",size:"icon",className:"size-8",onClick:()=>c(),children:e.jsx(R.Copy,{})})]}),e.jsx("div",{className:"tw:prose tw:w-full",children:e.jsx("pre",{className:"tw:text-xs",children:t})})]})}const Zi=Object.freeze([...io,"%webView_error_dump_copied_message%"]);function Wi({errorDetails:t,handleCopyNotify:r,localizedStrings:a,children:o,className:i,id:s}){const[c,d]=l.useState(!1),u=()=>{d(!0),r&&r()},w=p=>{p||d(!1)};return e.jsxs(n.Popover,{onOpenChange:w,children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:o}),e.jsxs(n.PopoverContent,{id:s,className:n.cn("tw:min-w-80 tw:max-w-96",i),children:[c&&a["%webView_error_dump_copied_message%"]&&e.jsx(n.Label,{children:a["%webView_error_dump_copied_message%"]}),e.jsx(so,{errorDetails:t,handleCopyNotify:u,localizedStrings:a})]})]})}var co=(t=>(t[t.Check=0]="Check",t[t.Radio=1]="Radio",t))(co||{});function Ji({id:t,label:r,groups:a}){const[o,i]=l.useState(Object.fromEntries(a.map((w,p)=>w.itemType===0?[p,[]]:void 0).filter(w=>!!w))),[s,c]=l.useState({}),d=(w,p)=>{const g=!o[w][p];i(h=>(h[w][p]=g,{...h}));const f=a[w].items[p];f.onUpdate(f.id,g)},u=(w,p)=>{c(f=>(f[w]=p,{...f}));const g=a[w].items.find(f=>f.id===p);g?g.onUpdate(p):console.error(`Could not find dropdown radio item with id '${p}'!`)};return e.jsx("div",{id:t,children:e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"default",children:[e.jsx(R.Filter,{size:16,className:"tw:mr-2 tw:h-4 tw:w-4"}),r,e.jsx(R.ChevronDown,{size:16,className:"tw:ml-2 tw:h-4 tw:w-4"})]})}),e.jsx(n.DropdownMenuContent,{children:a.map((w,p)=>e.jsxs("div",{children:[e.jsx(n.DropdownMenuLabel,{children:w.label}),e.jsx(n.DropdownMenuGroup,{children:w.itemType===0?e.jsx(e.Fragment,{children:w.items.map((g,f)=>e.jsx("div",{children:e.jsx(n.DropdownMenuCheckboxItem,{checked:o[p][f],onCheckedChange:()=>d(p,f),children:g.label})},g.id))}):e.jsx(n.DropdownMenuRadioGroup,{value:s[p],onValueChange:g=>u(p,g),children:w.items.map(g=>e.jsx("div",{children:e.jsx(n.DropdownMenuRadioItem,{value:g.id,children:g.label})},g.id))})}),e.jsx(n.DropdownMenuSeparator,{})]},w.label))})]})})}function Qi({id:t,category:r,downloads:a,languages:o,moreInfoUrl:i,handleMoreInfoLinkClick:s,supportUrl:c,handleSupportLinkClick:d}){const u=new M.NumberFormat("en",{notation:"compact",compactDisplay:"short"}).format(Object.values(a).reduce((p,g)=>p+g,0)),w=()=>{window.scrollTo(0,document.body.scrollHeight)};return e.jsxs("div",{id:t,className:"pr-twp tw:flex tw:items-center tw:justify-center tw:divide-x tw:border-b tw:border-t tw:py-2 tw:text-center",children:[r&&e.jsxs("div",{className:"tw:flex tw:flex-col tw:items-center tw:gap-1 tw:px-4",children:[e.jsx("div",{className:"tw:flex",children:e.jsx("span",{className:"tw:text-xs tw:font-semibold tw:text-foreground",children:r})}),e.jsx("span",{className:"tw:text-xs tw:text-foreground",children:"CATEGORY"})]}),e.jsxs("div",{className:"tw:flex tw:flex-col tw:items-center tw:gap-1 tw:px-4",children:[e.jsxs("div",{className:"tw:flex tw:gap-1",children:[e.jsx(R.User,{className:"tw:h-4 tw:w-4"}),e.jsx("span",{className:"tw:text-xs tw:font-semibold tw:text-foreground",children:u})]}),e.jsx("span",{className:"tw:text-xs tw:text-foreground",children:"USERS"})]}),e.jsxs("div",{className:"tw:flex tw:flex-col tw:items-center tw:gap-1 tw:px-4",children:[e.jsx("div",{className:"tw:flex tw:gap-2",children:o.slice(0,3).map(p=>e.jsx("span",{className:"tw:text-xs tw:font-semibold tw:text-foreground",children:p.toUpperCase()},p))}),o.length>3&&e.jsxs("button",{type:"button",onClick:()=>w(),className:"tw:text-xs tw:text-foreground tw:underline",children:["+",o.length-3," more languages"]})]}),(i||c)&&e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-1 tw:px-4",children:[i&&e.jsx("div",{className:"tw:flex tw:gap-1",children:e.jsxs(n.Button,{onClick:()=>s(),variant:"link",className:"tw:flex tw:h-auto tw:gap-1 tw:py-0 tw:text-xs tw:font-semibold tw:text-foreground",children:["Website",e.jsx(R.Link,{className:"tw:h-4 tw:w-4"})]})}),c&&e.jsx("div",{className:"tw:flex tw:gap-1",children:e.jsxs(n.Button,{onClick:()=>d(),variant:"link",className:"tw:flex tw:h-auto tw:gap-1 tw:py-0 tw:text-xs tw:font-semibold tw:text-foreground",children:["Support",e.jsx(R.CircleHelp,{className:"tw:h-4 tw:w-4"})]})})]})]})}function ts({id:t,versionHistory:r}){const[a,o]=l.useState(!1),i=new Date;function s(d){const u=new Date(d),w=new Date(i.getTime()-u.getTime()),p=w.getUTCFullYear()-1970,g=w.getUTCMonth(),f=w.getUTCDate()-1;let h="";return p>0?h=`${p.toString()} year${p===1?"":"s"} ago`:g>0?h=`${g.toString()} month${g===1?"":"s"} ago`:f===0?h="today":h=`${f.toString()} day${f===1?"":"s"} ago`,h}const c=Object.entries(r).sort((d,u)=>u[0].localeCompare(d[0]));return e.jsxs("div",{className:"pr-twp",id:t,children:[e.jsx("h3",{className:"tw:text-md tw:font-semibold",children:"What`s New"}),e.jsx("ul",{className:"tw:list-disc tw:pl-5 tw:pr-4 tw:text-xs tw:text-foreground",children:(a?c:c.slice(0,5)).map(d=>e.jsxs("div",{className:"tw:mt-3 tw:flex tw:justify-between",children:[e.jsx("div",{className:"tw:text-foreground",children:e.jsx("li",{className:"tw:prose tw:text-xs",children:e.jsx("span",{children:d[1].description})})}),e.jsxs("div",{className:"tw:justify-end tw:text-right",children:[e.jsxs("div",{children:["Version ",d[0]]}),e.jsx("div",{children:s(d[1].date)})]})]},d[0]))}),c.length>5&&e.jsx("button",{type:"button",onClick:()=>o(!a),className:"tw:text-xs tw:text-foreground tw:underline",children:a?"Show Less Version History":"Show All Version History"})]})}function es({id:t,publisherDisplayName:r,fileSize:a,locales:o,versionHistory:i,currentVersion:s}){const c=l.useMemo(()=>M.formatBytes(a),[a]),u=(w=>{const p=new Intl.DisplayNames(M.getCurrentLocale(),{type:"language"});return w.map(g=>p.of(g))})(o);return e.jsx("div",{id:t,className:"pr-twp tw:border-t tw:py-2",children:e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2 tw:divide-y",children:[Object.entries(i).length>0&&e.jsx(ts,{versionHistory:i}),e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2 tw:py-2",children:[e.jsx("h2",{className:"tw:text-md tw:font-semibold",children:"Information"}),e.jsxs("div",{className:"tw:flex tw:items-start tw:justify-between tw:text-xs tw:text-foreground",children:[e.jsxs("p",{className:"tw:flex tw:flex-col tw:justify-start tw:gap-1",children:[e.jsx("span",{children:"Publisher"}),e.jsx("span",{className:"tw:font-semibold",children:r}),e.jsx("span",{children:"Size"}),e.jsx("span",{className:"tw:font-semibold",children:c})]}),e.jsx("div",{className:"tw:flex tw:w-3/4 tw:items-center tw:justify-between tw:text-xs tw:text-foreground",children:e.jsxs("p",{className:"tw:flex tw:flex-col tw:justify-start tw:gap-1",children:[e.jsx("span",{children:"Version"}),e.jsx("span",{className:"tw:font-semibold",children:s}),e.jsx("span",{children:"Languages"}),e.jsx("span",{className:"tw:font-semibold",children:u.join(", ")})]})})]})]})]})})}function rs({entries:t,selected:r,onChange:a,placeholder:o,commandEmptyMessage:i,customSelectedText:s,isDisabled:c,sortSelected:d,icon:u,className:w,badgesPlaceholder:p,id:g}){return e.jsxs("div",{id:g,className:"tw:flex tw:items-center tw:gap-2",children:[e.jsx(n.MultiSelectComboBox,{entries:t,selected:r,onChange:a,placeholder:o,commandEmptyMessage:i,customSelectedText:s,isDisabled:c,sortSelected:d,icon:u,className:w}),r.length>0?e.jsx("div",{className:"tw:flex tw:flex-wrap tw:items-center tw:gap-2",children:r.map(f=>{var h;return e.jsxs(n.Badge,{variant:"muted",className:"tw:flex tw:items-center tw:gap-1",children:[e.jsx(n.Button,{variant:"ghost",size:"icon",className:"tw:h-4 tw:w-4 tw:p-0 tw:hover:bg-transparent",onClick:()=>a(r.filter(m=>m!==f)),children:e.jsx(R.X,{className:"tw:h-3 tw:w-3"})}),(h=t.find(m=>m.value===f))==null?void 0:h.label]},f)})}):e.jsx(n.Label,{children:p})]})}const lo=Object.freeze(["%undoButton_tooltip%","%redoButton_tooltip%"]),wa=(t,r)=>t[r]??r;function wo({onUndoClick:t,onRedoClick:r,canUndo:a=!0,canRedo:o=!0,localizedStrings:i={},showKeyboardShortcuts:s=!0,className:c="tw:h-6 tw:w-6",variant:d="ghost"}){const u=n.isMacOs(),w=wa(i,"%undoButton_tooltip%"),p=wa(i,"%redoButton_tooltip%"),g=d==="secondary"||d==="default";return e.jsxs(n.ButtonGroup,{children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":w,className:c,size:"icon",onClick:t,disabled:!a,variant:d,children:e.jsx(R.Undo,{})})}),e.jsx(n.TooltipContent,{children:e.jsxs("p",{children:[w,s&&e.jsxs(e.Fragment,{children:[" ",e.jsx(n.Kbd,{children:u?"⌘Z":"Ctrl+Z"})]})]})})]})}),r&&g&&e.jsx(n.ButtonGroupSeparator,{}),r&&e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":p,className:c,size:"icon",onClick:r,disabled:!o,variant:d,children:e.jsx(R.Redo,{})})}),e.jsx(n.TooltipContent,{children:e.jsxs("p",{children:[p,s&&e.jsxs(e.Fragment,{children:[" ",e.jsx(n.Kbd,{children:u?"⌘⇧Z":"Ctrl+Y"})]})]})})]})})]})}function uo({children:t,editorRef:r,canUndo:a=!0,canRedo:o=!0}){const i=l.useRef(null);return l.useEffect(()=>{var u;const s=n.isMacOs(),c=((u=i.current)==null?void 0:u.querySelector(".editor-input"))??void 0,d=w=>{var g,f,h,m;if(!c||document.activeElement!==c)return;const p=w.key.toLowerCase();if(s){if(!w.metaKey)return;!w.shiftKey&&p==="z"?(w.preventDefault(),a&&((g=r.current)==null||g.undo())):w.shiftKey&&p==="z"&&(w.preventDefault(),o&&((f=r.current)==null||f.redo()))}else{if(!w.ctrlKey)return;!w.shiftKey&&p==="z"?(w.preventDefault(),a&&((h=r.current)==null||h.undo())):(p==="y"||w.shiftKey&&p==="z")&&(w.preventDefault(),o&&((m=r.current)==null||m.redo()))}};return document.addEventListener("keydown",d),()=>document.removeEventListener("keydown",d)},[o,a,r]),e.jsx("div",{ref:i,children:t})}const as=(t,r,a)=>t==="generated"?e.jsxs(e.Fragment,{children:[e.jsx("p",{children:"+"})," ",r["%footnoteEditor_callerDropdown_item_generated%"]]}):t==="hidden"?e.jsxs(e.Fragment,{children:[e.jsx("p",{children:"-"})," ",r["%footnoteEditor_callerDropdown_item_hidden%"]]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{children:a})," ",r["%footnoteEditor_callerDropdown_item_custom%"]]});function os({callerType:t,updateCallerType:r,customCaller:a,updateCustomCaller:o,localizedStrings:i}){const s=l.useRef(null),c=l.useRef(null),d=l.useRef(!1),[u,w]=l.useState(t),[p,g]=l.useState(a),[f,h]=l.useState(!1);l.useEffect(()=>{w(t)},[t]),l.useEffect(()=>{p!==a&&g(a)},[a]);const m=b=>{d.current=!1,h(b),b||(u!=="custom"||p?(r(u),o(p)):(w(t),g(a)))},k=b=>{var C,y,_,B;b.stopPropagation(),document.activeElement===c.current&&b.key==="ArrowDown"||b.key==="ArrowRight"?((C=s.current)==null||C.focus(),d.current=!0):document.activeElement===s.current&&b.key==="ArrowUp"?((y=c.current)==null||y.focus(),d.current=!1):document.activeElement===s.current&&b.key==="ArrowLeft"&&((_=s.current)==null?void 0:_.selectionStart)===0&&((B=c.current)==null||B.focus(),d.current=!1),u==="custom"&&b.key==="Enter"&&(document.activeElement===c.current||document.activeElement===s.current)&&m(!1)};return e.jsxs(n.DropdownMenu,{open:f,onOpenChange:m,children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:"outline",className:"tw:h-6",children:as(t,i,a)})})}),e.jsx(n.TooltipContent,{children:i["%footnoteEditor_callerDropdown_tooltip%"]})]})}),e.jsxs(n.DropdownMenuContent,{style:{zIndex:n.Z_INDEX_FOOTNOTE_EDITOR},onClick:()=>{d.current&&(d.current=!1)},onKeyDown:k,onMouseMove:()=>{var b;d.current&&((b=s.current)==null||b.focus())},children:[e.jsx(n.DropdownMenuLabel,{children:i["%footnoteEditor_callerDropdown_label%"]}),e.jsx(n.DropdownMenuSeparator,{}),e.jsx(n.DropdownMenuCheckboxItem,{checked:u==="generated",onCheckedChange:()=>w("generated"),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:justify-between",children:[e.jsx("span",{children:i["%footnoteEditor_callerDropdown_item_generated%"]}),e.jsx("span",{className:"tw:w-10 tw:text-center",children:Gt.GENERATOR_NOTE_CALLER})]})}),e.jsx(n.DropdownMenuCheckboxItem,{checked:u==="hidden",onCheckedChange:()=>w("hidden"),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:justify-between",children:[e.jsx("span",{children:i["%footnoteEditor_callerDropdown_item_hidden%"]}),e.jsx("span",{className:"tw:w-10 tw:text-center",children:Gt.HIDDEN_NOTE_CALLER})]})}),e.jsx(n.DropdownMenuCheckboxItem,{ref:c,checked:u==="custom",onCheckedChange:()=>w("custom"),onClick:b=>{var C;b.stopPropagation(),d.current=!0,(C=s.current)==null||C.focus()},onSelect:b=>b.preventDefault(),children:e.jsxs("div",{className:"tw:flex tw:w-full tw:justify-between",children:[e.jsx("span",{children:i["%footnoteEditor_callerDropdown_item_custom%"]}),e.jsx(n.Input,{tabIndex:0,onMouseDown:b=>{b.stopPropagation(),w("custom"),d.current=!0},ref:s,className:"tw:h-auto tw:w-10 tw:p-0 tw:text-center",value:p,onKeyDown:b=>{b.key==="Enter"||b.key==="ArrowUp"||b.key==="ArrowDown"||b.key==="ArrowLeft"||b.key==="ArrowRight"||b.stopPropagation()},maxLength:1,onChange:b=>g(b.target.value)})]})})]})]})}const ns=(t,r)=>t==="f"?e.jsxs(e.Fragment,{children:[e.jsx(R.FunctionSquare,{})," ",r["%footnoteEditor_noteType_footnote_label%"]]}):t==="fe"?e.jsxs(e.Fragment,{children:[e.jsx(R.SquareSigma,{})," ",r["%footnoteEditor_noteType_endNote_label%"]]}):e.jsxs(e.Fragment,{children:[e.jsx(R.SquareX,{})," ",r["%footnoteEditor_noteType_crossReference_label%"]]}),is=(t,r)=>{if(t==="x")return r["%footnoteEditor_noteType_crossReference_label%"];let a=r["%footnoteEditor_noteType_endNote_label%"];return t==="f"&&(a=r["%footnoteEditor_noteType_footnote_label%"]),M.formatReplacementString(r["%footnoteEditor_noteType_tooltip%"]??"",{noteType:a})};function ss({noteType:t,handleNoteTypeChange:r,localizedStrings:a,isTypeSwitchable:o}){return e.jsxs(n.DropdownMenu,{children:[e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsx(n.Button,{variant:"outline",className:"tw:h-6",children:ns(t,a)})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:is(t,a)})})]})}),e.jsxs(n.DropdownMenuContent,{style:{zIndex:n.Z_INDEX_FOOTNOTE_EDITOR},children:[e.jsx(n.DropdownMenuLabel,{children:a["%footnoteEditor_noteTypeDropdown_label%"]}),e.jsx(n.DropdownMenuSeparator,{}),e.jsxs(n.DropdownMenuCheckboxItem,{disabled:t!=="x"&&!o,checked:t==="x",onCheckedChange:()=>r("x"),className:"tw:gap-2",children:[e.jsx(R.SquareX,{}),e.jsx("span",{children:a["%footnoteEditor_noteType_crossReference_label%"]})]}),e.jsxs(n.DropdownMenuCheckboxItem,{disabled:t==="x"&&!o,checked:t==="f",onCheckedChange:()=>r("f"),className:"tw:gap-2",children:[e.jsx(R.FunctionSquare,{}),e.jsx("span",{children:a["%footnoteEditor_noteType_footnote_label%"]})]}),e.jsxs(n.DropdownMenuCheckboxItem,{disabled:t==="x"&&!o,checked:t==="fe",onCheckedChange:()=>r("fe"),className:"tw:gap-2",children:[e.jsx(R.SquareSigma,{}),e.jsx("span",{children:a["%footnoteEditor_noteType_endNote_label%"]})]})]})]})}const po=Object.freeze(["%markerMenu_deprecated_label%","%markerMenu_disallowed_label%","%markerMenu_noResults%","%markerMenu_searchPlaceholder%","%markerMenu_searchPlaceholder_insert%","%markerMenu_searchPlaceholder_paragraph%"]);function cs({icon:t,className:r}){const a=t??R.Ban;return e.jsx(a,{className:r,size:16})}function ua({item:t,localizedStrings:r}){return e.jsxs(n.CommandItem,{className:"tw:flex tw:gap-2 tw:hover:bg-accent",disabled:t.isDisallowed||t.isDeprecated,onSelect:t.action,children:[e.jsx("div",{className:"tw:w-8 tw:min-w-8",children:t.marker?e.jsx("span",{className:"tw:text-xs",children:t.marker}):e.jsx("div",{children:e.jsx(cs,{icon:t.icon})})}),e.jsxs("div",{children:[e.jsx("p",{className:"tw:text-sm",children:t.title}),t.subtitle&&e.jsx("p",{className:"tw:text-xs tw:text-muted-foreground",children:t.subtitle})]}),(t.isDisallowed||t.isDeprecated)&&e.jsx(n.CommandShortcut,{className:"tw:font-sans",children:t.isDisallowed?r["%markerMenu_disallowed_label%"]:r["%markerMenu_deprecated_label%"]})]})}function go({localizedStrings:t,markerMenuItems:r,searchRef:a,searchPlaceholder:o}){const[i,s]=l.useState(""),[c,d]=l.useMemo(()=>{const u=i.trim().toLowerCase();if(!u){const g=r.filter(f=>!f.isDisallowed);return[g.length>0?g:r,[]]}const w=r.filter(g=>{var h;const f=(h=g.marker)==null?void 0:h.toLowerCase();return g.isDisallowed?f===u:f==null?void 0:f.includes(u)}),p=r.filter(g=>g.title.toLowerCase().includes(u)&&!w.includes(g));return[w,p]},[i,r]);return e.jsxs(n.Command,{className:"tw:p-1",shouldFilter:!1,loop:!0,children:[e.jsx(n.CommandInput,{className:"marker-menu-search",ref:a,value:i,onValueChange:u=>s(u),placeholder:o??t["%markerMenu_searchPlaceholder%"]}),e.jsxs(n.CommandList,{children:[e.jsx(n.CommandEmpty,{children:t["%markerMenu_noResults%"]}),e.jsx(n.CommandGroup,{children:c.map(u=>{var w;return e.jsx(ua,{item:u,localizedStrings:t},`item-${u.marker??((w=u.icon)==null?void 0:w.displayName)}-${u.title.replaceAll(" ","")}`)})}),d.length>0&&e.jsxs(e.Fragment,{children:[c.length>0&&e.jsx(n.CommandSeparator,{alwaysRender:!0}),e.jsx(n.CommandGroup,{children:d.map(u=>{var w;return e.jsx(ua,{item:u,localizedStrings:t},`item-${u.marker??((w=u.icon)==null?void 0:w.displayName)}-${u.title.replaceAll(" ","")}`)})})]})]})]})}function ls(t,r,a,o){if(!o||o==="p")return[];const i=M.usfmMarkers[o];if(!(i!=null&&i.children))return[];const s=[];return Object.entries(i.children).forEach(([,c])=>{s.push(...c.map(d=>({marker:d,title:a[M.usfmMarkers[d].description]??M.usfmMarkers[d].description,action:()=>{var u;(u=t.current)==null||u.insertMarker(d),r()}})))}),s.sort((c,d)=>(c.marker??c.title).localeCompare(d.marker??d.title))}function ds(t){var a;const r=(a=t.attributes)==null?void 0:a.char;r.style&&(r.style==="ft"&&(r.style="xt"),r.style==="fr"&&(r.style="xo"),r.style==="fq"&&(r.style="xq"))}function ws(t){var a;const r=(a=t.attributes)==null?void 0:a.char;r.style&&(r.style==="xt"&&(r.style="ft"),r.style==="xo"&&(r.style="fr"),r.style==="xq"&&(r.style="fq"))}const us={type:"USJ",version:"3.1",content:[{type:"para"}]};function ps({classNameForEditor:t,noteOps:r,onChange:a,onClose:o,scrRef:i,noteKey:s,editorOptions:c,defaultMarkerMenuTrigger:d,localizedStrings:u,parentEditorRef:w}){const p=l.useRef(null),g=l.useRef(null),f=l.useRef(null),h=l.useRef(null);l.useLayoutEffect(()=>{if(!h.current)return;const{width:L}=h.current.getBoundingClientRect();L>0&&(h.current.style.width=`${L}px`)},[]);const[m,k]=l.useState("generated"),[b,C]=l.useState("generated"),[y,_]=l.useState("*"),[B,F]=l.useState("*"),[E,P]=l.useState("f"),[A,j]=l.useState(!1),[V,z]=l.useState(!0),[N,H]=l.useState(!1),U=l.useRef(!1),G=l.useRef(""),[I,T]=l.useState(!1),[Z,W]=l.useState(),[vt,bt]=l.useState(),[Mt,K]=l.useState(),[J,st]=l.useState(),ot=l.useRef(null),gt=l.useMemo(()=>({...c,markerMenuTrigger:d,hasExternalUI:!0,view:{...c.view??Gt.getDefaultViewOptions(),noteMode:"expanded"}}),[c,d]),qt=l.useMemo(()=>ls(p,()=>T(!1),u,J),[u,J]);l.useEffect(()=>{var L;I||(L=p.current)==null||L.focus()},[E,I]),l.useEffect(()=>{var rt,Q;let L;U.current=!1,z(!0);const Y=r==null?void 0:r.at(0);if(Y&&Gt.isInsertEmbedOpOfType("note",Y)){const ct=(rt=Y.insert.note)==null?void 0:rt.caller;let nt="custom";ct===Gt.GENERATOR_NOTE_CALLER?nt="generated":ct===Gt.HIDDEN_NOTE_CALLER?nt="hidden":ct&&(_(ct),F(ct)),k(nt),C(nt),P(((Q=Y.insert.note)==null?void 0:Q.style)??"f"),L=setTimeout(()=>{var wt;(wt=p.current)==null||wt.applyUpdate([Y])},0)}return()=>{L&&clearTimeout(L)}},[r,s]);const et=l.useCallback((L,Y,rt=!1)=>{var ct,nt,wt;const Q=(nt=(ct=p.current)==null?void 0:ct.getNoteOps(0))==null?void 0:nt.at(0);if(Q&&Gt.isInsertEmbedOpOfType("note",Q)){if(Q.insert.note){let lt;L==="custom"?lt=Y:L==="generated"?lt=Gt.GENERATOR_NOTE_CALLER:lt=Gt.HIDDEN_NOTE_CALLER,Q.insert.note.caller=lt}a==null||a([Q]),rt&&w&&s&&((wt=w.current)==null||wt.replaceEmbedUpdate(s,[Q]))}},[s,a,w]),Rt=l.useCallback(()=>{et(m,y,!0),o()},[m,y,o,et]),yt=l.useRef(Rt);l.useLayoutEffect(()=>{yt.current=Rt});const Bt=l.useRef({book:i.book,chapterNum:i.chapterNum});l.useLayoutEffect(()=>{(Bt.current.book!==i.book||Bt.current.chapterNum!==i.chapterNum)&&(Bt.current={book:i.book,chapterNum:i.chapterNum},yt.current())},[i.book,i.chapterNum]);const Ht=()=>{var Y;const L=(Y=g.current)==null?void 0:Y.getElementsByClassName("editor-input")[0];L!=null&&L.textContent&&navigator.clipboard.writeText(L.textContent)},O=l.useCallback(L=>{k(L),et(L,y)},[y,et]),Pt=l.useCallback(L=>{_(L),et(m,L)},[m,et]),ft=L=>{var rt,Q,ct,nt,wt;P(L);const Y=(Q=(rt=p.current)==null?void 0:rt.getNoteOps(0))==null?void 0:Q.at(0);if(Y&&Gt.isInsertEmbedOpOfType("note",Y)){Y.insert.note&&(Y.insert.note.style=L);const lt=(nt=(ct=Y.insert.note)==null?void 0:ct.contents)==null?void 0:nt.ops;E!=="x"&&L==="x"?lt==null||lt.forEach(ut=>ds(ut)):E==="x"&&L!=="x"&&(lt==null||lt.forEach(ut=>ws(ut))),(wt=p.current)==null||wt.applyUpdate([Y,{delete:1}])}},xt=L=>{st(L.contextMarker),H(L.canRedo)},Vt=l.useCallback(L=>{var rt,Q,ct,nt,wt;const Y=(Q=(rt=p.current)==null?void 0:rt.getNoteOps(0))==null?void 0:Q.at(0);if(Y&&Gt.isInsertEmbedOpOfType("note",Y)){L.content.length>1&&setTimeout(()=>{var _t;(_t=p.current)==null||_t.applyUpdate([{retain:2},{delete:1}])},0);const lt=(ct=Y.insert.note)==null?void 0:ct.style,ut=(wt=(nt=Y.insert.note)==null?void 0:nt.contents)==null?void 0:wt.ops;if(lt||j(!1),j(lt==="x"?!!(ut!=null&&ut.every(_t=>{var At,Ct;if(!((At=_t.attributes)!=null&&At.char))return!0;const jt=((Ct=_t.attributes)==null?void 0:Ct.char).style;return jt==="xt"||jt==="xo"||jt==="xq"})):!!(ut!=null&&ut.every(_t=>{var At,Ct;if(!((At=_t.attributes)!=null&&At.char))return!0;const jt=((Ct=_t.attributes)==null?void 0:Ct.char).style;return jt==="ft"||jt==="fr"||jt==="fq"}))),!U.current){U.current=!0,G.current=JSON.stringify(Y),z(!0);return}z(JSON.stringify(Y)===G.current),et(m,y)}else j(!1),z(!0)},[m,y,et]),te=l.useCallback(()=>{const L=window.getSelection();if(f.current&&qt.length&&L&&L.rangeCount>0){const Y=L.getRangeAt(0).getBoundingClientRect(),rt=f.current.getBoundingClientRect();W(Y.left-rt.left),bt(Y.top-rt.top),K(Y.height),T(!0)}},[qt,f]);l.useEffect(()=>{const L=()=>{I&&T(!1)};return window.addEventListener("click",L),()=>{window.removeEventListener("click",L)}},[I]),l.useEffect(()=>{var L;I&&((L=ot.current)==null||L.focus())},[I]),l.useEffect(()=>{var rt;const L=((rt=g.current)==null?void 0:rt.querySelector(".editor-input"))??void 0,Y=Q=>{!I&&L&&document.activeElement===L&&Q.key===d?(Q.preventDefault(),te()):I&&Q.key==="Escape"&&(Q.preventDefault(),T(!1))};return document.addEventListener("keydown",Y),()=>{document.removeEventListener("keydown",Y)}},[I,te,d]);const Yt=u["%footnoteEditor_copyButton_tooltip%"];return e.jsxs(e.Fragment,{children:[e.jsxs("div",{ref:h,className:"footnote-editor tw:grid tw:gap-[12px]",children:[e.jsxs("div",{className:"tw:flex",children:[e.jsxs("div",{className:"tw:flex tw:gap-4",children:[e.jsx(ss,{isTypeSwitchable:A,noteType:E,handleNoteTypeChange:ft,localizedStrings:u}),e.jsx(os,{callerType:m,updateCallerType:O,customCaller:y,updateCustomCaller:Pt,localizedStrings:u})]}),e.jsx("div",{className:"tw:flex tw:w-full tw:justify-end",children:e.jsxs(n.ButtonGroup,{children:[e.jsx(wo,{onUndoClick:()=>{var L;return(L=p.current)==null?void 0:L.undo()},onRedoClick:()=>{var L;return(L=p.current)==null?void 0:L.redo()},canUndo:!V,canRedo:N,localizedStrings:u}),e.jsx(Or,{onCancelClick:o,onAcceptClick:Rt,canAccept:!V||b!==m||m==="custom"&&y!==B,localizedStrings:u,acceptLabel:u["%footnoteEditor_saveButton_tooltip%"]})]})})]}),e.jsxs("div",{ref:g,className:"tw:relative tw:rounded-[6px] tw:border-2 tw:border-ring",children:[e.jsx("div",{className:t,children:e.jsx(uo,{editorRef:p,canUndo:!V,canRedo:N,children:e.jsx(Gt.Editorial,{options:gt,onStateChange:xt,onUsjChange:Vt,defaultUsj:us,onScrRefChange:()=>{},scrRef:i,ref:p})})}),e.jsx("div",{className:"tw:absolute tw:bottom-0 tw:right-0",children:e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsx(n.Button,{"aria-label":Yt,onClick:Ht,className:"tw:h-6 tw:w-6",variant:"ghost",size:"icon",children:e.jsx(R.Copy,{})})}),e.jsx(n.TooltipContent,{children:e.jsx("p",{children:Yt})})]})})})]})]}),e.jsx("div",{className:"tw:absolute",ref:f,style:{top:0,left:0,height:0,width:0}}),e.jsxs(n.Popover,{open:I,children:[e.jsx(n.PopoverAnchor,{className:"tw:absolute",style:{top:vt,left:Z,height:Mt,width:0,pointerEvents:"none"}}),e.jsx(n.PopoverContent,{className:"tw:w-[500px] tw:p-0",onClick:L=>{L.preventDefault(),L.stopPropagation()},children:e.jsx(go,{markerMenuItems:qt,localizedStrings:u,searchRef:ot})})]})]})}const gs=Object.freeze([...po,...Object.entries(M.usfmMarkers).map(([,t])=>t.description).filter(t=>!!t),"%footnoteEditor_callerDropdown_item_custom%","%footnoteEditor_callerDropdown_item_generated%","%footnoteEditor_callerDropdown_item_hidden%","%footnoteEditor_callerDropdown_label%","%footnoteEditor_callerDropdown_tooltip%","%footnoteEditor_copyButton_tooltip%","%footnoteEditor_noteType_crossReference_label%","%footnoteEditor_noteType_endNote_label%","%footnoteEditor_noteType_footnote_label%","%footnoteEditor_noteType_tooltip%","%footnoteEditor_noteTypeDropdown_label%","%footnoteEditor_saveButton_tooltip%",...lo,...Dr]);function ho(t,r){if(!r||r.length===0)return t??"empty";const a=r.find(i=>typeof i=="string");if(a)return`key-${t??"unknown"}-${a.slice(0,10)}`;const o=typeof r[0]=="string"?"impossible":r[0].marker??"unknown";return`key-${t??"unknown"}-${o}`}function hs(t,r,a=!0,o=void 0){if(!r||r.length===0)return;const i=[],s=[];let c=[];return r.forEach(d=>{typeof d!="string"&&d.marker==="fp"?(c.length>0&&s.push(c),c=[d]):c.push(d)}),c.length>0&&s.push(c),s.map((d,u)=>{const w=u===s.length-1;return e.jsxs("p",{children:[Ir(t,d,a,!0,i),w&&o]},ho(t,d))})}function Ir(t,r,a=!0,o=!0,i=[]){if(!(!r||r.length===0))return r.map(s=>{if(typeof s=="string"){const c=`${t}-text-${s.slice(0,10)}`;if(o){const d=n.cn(`usfm_${t}`);return e.jsx("span",{className:d,children:s},c)}return e.jsxs("span",{className:"tw:inline-flex tw:items-center tw:gap-1 tw:underline tw:decoration-destructive",children:[e.jsx(R.AlertCircle,{className:"tw:h-4 tw:w-4 tw:fill-destructive"}),e.jsx("span",{children:s}),e.jsx(R.AlertCircle,{className:"tw:h-4 tw:w-4 tw:fill-destructive"})]},c)}return fs(s,ho(`${t}\\${s.marker}`,[s]),a,[...i,t??"unknown"])})}function fs(t,r,a,o=[]){const{marker:i}=t;return e.jsxs("span",{children:[i?a&&e.jsx("span",{className:"marker",children:`\\${i} `}):e.jsx(R.AlertCircle,{className:"tw:text-error tw:mr-1 tw:inline-block tw:h-4 tw:w-4","aria-label":"Missing marker"}),Ir(i,t.content,a,!0,[...o,i??"unknown"])]},r)}function fo({footnote:t,layout:r="horizontal",formatCaller:a,showMarkers:o=!0}){const i=a?a(t.caller):t.caller,s=i!==t.caller;let c,d=t.content;Array.isArray(t.content)&&t.content.length>0&&typeof t.content[0]!="string"&&(t.content[0].marker==="fr"||t.content[0].marker==="xo")&&([c,...d]=t.content);const u=o?e.jsx("span",{className:"marker",children:`\\${t.marker} `}):void 0,w=o?e.jsx("span",{className:"marker",children:` \\${t.marker}*`}):void 0,p=i&&e.jsxs("span",{className:n.cn("note-caller tw:inline-block",{formatted:s}),children:[i," "]}),g=c&&e.jsxs(e.Fragment,{children:[Ir(t.marker,[c],o,!1)," "]}),f=r==="horizontal"?"horizontal":"vertical",h=o?"marker-visible":"",m=r==="horizontal"?"tw:col-span-1":"tw:col-span-2 tw:col-start-1 tw:row-start-2",k=n.cn(f,h);return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:n.cn("textual-note-header tw:col-span-1 tw:w-fit tw:text-nowrap",k),children:[u,p]}),e.jsx("div",{className:n.cn("textual-note-header tw:col-span-1 tw:w-fit tw:text-nowrap",k),children:g}),e.jsx("div",{className:n.cn("textual-note-body tw:flex tw:flex-col tw:gap-1",m,k),children:d&&d.length>0&&e.jsx(e.Fragment,{children:hs(t.marker,d,o,w)})})]})}function ms({className:t,classNameForItems:r,footnotes:a,layout:o="horizontal",listId:i,selectedFootnote:s,showMarkers:c=!0,suppressFormatting:d=!1,formatCaller:u,onFootnoteSelected:w}){const p=u??M.getFormatCallerFunction(a,void 0),g=(y,_)=>{w==null||w(y,_,i)},f=s?a.findIndex(y=>y===s):-1,[h,m]=l.useState(f),k=(y,_,B)=>{if(a.length)switch(y.key){case"Enter":case" ":y.preventDefault(),w==null||w(_,B,i);break}},b=y=>{if(a.length)switch(y.key){case"ArrowDown":y.preventDefault(),m(_=>Math.min(_+1,a.length-1));break;case"ArrowUp":y.preventDefault(),m(_=>Math.max(_-1,0));break}},C=l.useRef([]);return l.useEffect(()=>{var y;h>=0&&h{const B=y===s,F=`${i}-${_}`;return e.jsxs(e.Fragment,{children:[e.jsx("li",{ref:E=>{C.current[_]=E},role:"option","aria-selected":B,"data-marker":y.marker,"data-state":B?"selected":void 0,tabIndex:_===h?0:-1,className:n.cn("tw:gap-x-3 tw:gap-y-1 tw:p-2 tw:data-[state=selected]:bg-muted",w&&"tw:hover:bg-muted/50","tw:w-full tw:rounded-sm tw:border-0 tw:bg-transparent tw:shadow-none","tw:focus:outline-hidden tw:focus-visible:outline-hidden","tw:focus-visible:ring-offset-0.5 tw:focus-visible:relative tw:focus-visible:z-10 tw:focus-visible:ring-2 tw:focus-visible:ring-ring","tw:grid tw:grid-flow-col tw:grid-cols-subgrid",o==="horizontal"?"tw:col-span-3":"tw:col-span-2 tw:row-span-2",r),onClick:()=>g(y,_),onKeyDown:E=>k(E,y,_),children:e.jsx(fo,{footnote:y,layout:o,formatCaller:()=>p(y.caller,_),showMarkers:c})},F),_a&&r.push(t.substring(a,i.index)),r.push(e.jsx("strong",{children:i[1]},i.index)),a=o.lastIndex;return a0?r:[t]}function bs({occurrenceData:t,setScriptureReference:r,localizedStrings:a,classNameForText:o}){const i=a["%webView_inventory_occurrences_table_header_reference%"],s=a["%webView_inventory_occurrences_table_header_occurrence%"],c=l.useMemo(()=>{const d=[],u=new Set;return t.forEach(w=>{const p=`${w.reference.book}:${w.reference.chapterNum}:${w.reference.verseNum}:${w.text}`;u.has(p)||(u.add(p),d.push(w))}),d},[t]);return e.jsxs(n.Table,{stickyHeader:!0,children:[e.jsx(n.TableHeader,{stickyHeader:!0,children:e.jsxs(n.TableRow,{children:[e.jsx(n.TableHead,{children:i}),e.jsx(n.TableHead,{children:s})]})}),e.jsx(n.TableBody,{children:c.length>0&&c.map(d=>e.jsxs(n.TableRow,{onClick:()=>{r(d.reference)},children:[e.jsx(n.TableCell,{children:M.formatScrRef(d.reference,"English")}),e.jsx(n.TableCell,{className:o,children:vs(d.text)})]},`${d.reference.book} ${d.reference.chapterNum}:${d.reference.verseNum}-${d.text}`))})]})}function Ar({className:t,...r}){return e.jsx(D.Checkbox.Root,{"data-slot":"checkbox",className:n.cn("pr-twp tw:peer tw:relative tw:flex tw:size-4 tw:shrink-0 tw:items-center tw:justify-center tw:rounded-[4px] tw:border tw:border-input tw:transition-colors tw:outline-none tw:group-has-disabled/field:opacity-50 tw:after:absolute tw:after:-inset-x-3 tw:after:-inset-y-2 tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:disabled:cursor-not-allowed tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:aria-invalid:aria-checked:border-primary tw:dark:bg-input/30 tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:data-checked:border-primary tw:data-checked:bg-primary tw:data-checked:text-primary-foreground tw:dark:data-checked:bg-primary",t),...r,children:e.jsx(D.Checkbox.Indicator,{"data-slot":"checkbox-indicator",className:"tw:grid tw:place-content-center tw:text-current tw:transition-none tw:[&>svg]:size-3.5",children:e.jsx(Tt.IconCheck,{})})})}const xs=t=>{if(t==="asc")return e.jsx(R.ArrowUpIcon,{className:"tw:h-4 tw:w-4"});if(t==="desc")return e.jsx(R.ArrowDownIcon,{className:"tw:h-4 tw:w-4"})},Oe=(t,r,a)=>e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsxs(n.TooltipTrigger,{className:n.cn("tw:flex tw:w-full tw:justify-start",a),variant:"ghost",onClick:()=>t.toggleSorting(void 0),children:[e.jsx("span",{className:"tw:w-6 tw:max-w-fit tw:flex-1 tw:overflow-hidden tw:text-ellipsis",children:r}),xs(t.getIsSorted())]}),e.jsx(n.TooltipContent,{side:"bottom",children:r})]})}),ks=t=>({accessorKey:"item",accessorFn:r=>r.items[0],header:({column:r})=>Oe(r,t)}),ys=(t,r)=>({accessorKey:`item${r}`,accessorFn:a=>a.items[r],header:({column:a})=>Oe(a,t)}),_s=t=>({accessorKey:"count",header:({column:r})=>Oe(r,t,"tw:justify-end"),cell:({row:r})=>e.jsx("div",{className:"tw:flex tw:justify-end tw:tabular-nums",children:r.getValue("count")})}),pr=(t,r,a,o,i,s)=>{let c=[...a];t.forEach(u=>{r==="approved"?c.includes(u)||c.push(u):c=c.filter(w=>w!==u)}),o(c);let d=[...i];t.forEach(u=>{r==="unapproved"?d.includes(u)||d.push(u):d=d.filter(w=>w!==u)}),s(d)},js=(t,r,a,o,i)=>({accessorKey:"status",header:({column:s})=>Oe(s,t,"tw:justify-center"),cell:({row:s})=>{const c=s.getValue("status"),d=s.getValue("item");return e.jsx("div",{className:"tw:flex tw:justify-center",children:e.jsxs(Mr,{value:c,variant:"outline",type:"single",className:"tw:gap-0",children:[e.jsx(Me,{onClick:u=>{u.stopPropagation(),pr([d],"approved",r,a,o,i)},value:"approved",className:"tw:rounded-e-none tw:border-e-0",children:e.jsx(R.CircleCheckIcon,{})}),e.jsx(Me,{onClick:u=>{u.stopPropagation(),pr([d],"unapproved",r,a,o,i)},value:"unapproved",className:"tw:rounded-none",children:e.jsx(R.CircleXIcon,{})}),e.jsx(Me,{onClick:u=>{u.stopPropagation(),pr([d],"unknown",r,a,o,i)},value:"unknown",className:"tw:rounded-s-none tw:border-s-0",children:e.jsx(R.CircleHelpIcon,{})})]})})}}),Cs=t=>t.split(/(?:\r?\n|\r)|(?=(?:\\(?:v|c|id)))/g),Ns=t=>{const r=/^\\[vc]\s+(\d+)/,a=t.match(r);if(a)return+a[1]},Es=t=>{const r=t.match(/^\\id\s+([A-Za-z]+)/);return r?r[1]:""},mo=(t,r,a)=>a.includes(t)?"unapproved":r.includes(t)?"approved":"unknown",Ss=Object.freeze(["%webView_inventory_all%","%webView_inventory_approved%","%webView_inventory_unapproved%","%webView_inventory_unknown%","%webView_inventory_scope_currentBook%","%webView_inventory_scope_chapter%","%webView_inventory_scope_verse%","%webView_inventory_filter_text%","%webView_inventory_show_additional_items%","%webView_inventory_occurrences_table_header_reference%","%webView_inventory_occurrences_table_header_occurrence%","%webView_inventory_no_results%"]),Ts=(t,r,a)=>{let o=t;return r!=="all"&&(o=o.filter(i=>r==="approved"&&i.status==="approved"||r==="unapproved"&&i.status==="unapproved"||r==="unknown"&&i.status==="unknown")),a!==""&&(o=o.filter(i=>i.items[0].includes(a))),o},Ms=(t,r,a)=>t.map(o=>{const i=M.isString(o.key)?o.key:o.key[0];return{items:M.isString(o.key)?[o.key]:o.key,count:o.count,status:o.status||mo(i,r,a),occurrences:o.occurrences||[]}}),Zt=(t,r)=>t[r]??r;function Rs({inventoryItems:t,setVerseRef:r,localizedStrings:a,additionalItemsLabels:o,approvedItems:i,unapprovedItems:s,scope:c,onScopeChange:d,columns:u,id:w,areInventoryItemsLoading:p=!1,classNameForVerseText:g,onItemSelected:f}){const h=Zt(a,"%webView_inventory_all%"),m=Zt(a,"%webView_inventory_approved%"),k=Zt(a,"%webView_inventory_unapproved%"),b=Zt(a,"%webView_inventory_unknown%"),C=Zt(a,"%webView_inventory_scope_currentBook%"),y=Zt(a,"%webView_inventory_scope_chapter%"),_=Zt(a,"%webView_inventory_scope_verse%"),B=Zt(a,"%webView_inventory_filter_text%"),F=Zt(a,"%webView_inventory_show_additional_items%"),E=Zt(a,"%webView_inventory_no_results%"),[P,A]=l.useState(!1),[j,V]=l.useState("all"),[z,N]=l.useState(""),[H,U]=l.useState([]),G=l.useMemo(()=>{const K=t??[];return K.length===0?[]:Ms(K,i,s)},[t,i,s]),I=l.useMemo(()=>{if(P)return G;const K=[];return G.forEach(J=>{const st=J.items[0],ot=K.find(gt=>gt.items[0]===st);ot?(ot.count+=J.count,ot.occurrences=ot.occurrences.concat(J.occurrences)):K.push({items:[st],count:J.count,occurrences:J.occurrences,status:J.status})}),K},[P,G]),T=l.useMemo(()=>I.length===0?[]:Ts(I,j,z),[I,j,z]),Z=l.useMemo(()=>{var st,ot;if(!P)return u;const K=(st=o==null?void 0:o.tableHeaders)==null?void 0:st.length;if(!K)return u;const J=[];for(let gt=0;gt{T.length===0?U([]):T.length===1&&U(T[0].items)},[T]);const W=(K,J)=>{J.setRowSelection(()=>{const ot={};return ot[K.index]=!0,ot});const st=K.original.items;U(st),f&&st.length>0&&f(st[0])},vt=K=>{if(K==="book"||K==="chapter"||K==="verse")d(K);else throw new Error(`Invalid scope value: ${K}`)},bt=K=>{if(K==="all"||K==="approved"||K==="unapproved"||K==="unknown")V(K);else throw new Error(`Invalid status filter value: ${K}`)},Mt=l.useMemo(()=>{if(I.length===0||H.length===0)return[];const K=I.filter(J=>M.deepEqual(P?J.items:[J.items[0]],H));if(K.length>1)throw new Error("Selected item is not unique");return K.length===0?[]:K[0].occurrences},[H,P,I]);return e.jsx("div",{id:w,className:"pr-twp tw:h-full tw:overflow-auto",children:e.jsxs("div",{className:"tw:flex tw:h-full tw:w-full tw:min-w-min tw:flex-col",children:[e.jsxs("div",{className:"tw:flex tw:items-stretch",style:{contain:"inline-size"},children:[e.jsxs(ue,{onValueChange:K=>bt(K),defaultValue:j,children:[e.jsx(ge,{className:"tw:m-1 tw:w-auto tw:flex-1",children:e.jsx(pe,{placeholder:"Select filter"})}),e.jsxs(he,{children:[e.jsx(Ut,{value:"all",children:h}),e.jsx(Ut,{value:"approved",children:m}),e.jsx(Ut,{value:"unapproved",children:k}),e.jsx(Ut,{value:"unknown",children:b})]})]}),e.jsxs(ue,{onValueChange:K=>vt(K),defaultValue:c,children:[e.jsx(ge,{className:"tw:m-1 tw:w-auto tw:flex-1",children:e.jsx(pe,{placeholder:"Select scope"})}),e.jsxs(he,{children:[e.jsx(Ut,{value:"book",children:C}),e.jsx(Ut,{value:"chapter",children:y}),e.jsx(Ut,{value:"verse",children:_})]})]}),e.jsx(n.Input,{className:"tw:m-1 tw:flex-1 tw:rounded-md tw:border",placeholder:B,value:z,onChange:K=>{N(K.target.value)}}),o&&e.jsx(n.TooltipProvider,{children:e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:e.jsxs("div",{className:"tw:m-1 tw:flex tw:w-fit tw:min-w-[26px] tw:items-center tw:rounded-md tw:border",children:[e.jsx(Ar,{className:"tw:m-1 tw:shrink-0",checked:P,onCheckedChange:K=>{A(K)}}),e.jsx(n.Label,{className:"tw:m-1 tw:truncate",children:(o==null?void 0:o.checkboxText)??F})]})}),e.jsx(n.TooltipContent,{children:(o==null?void 0:o.checkboxText)??F})]})})]}),e.jsx("div",{className:"tw:m-1 tw:flex-1 tw:overflow-auto tw:rounded-md tw:border",children:e.jsx(no,{columns:Z,data:T,onRowClickHandler:W,stickyHeader:!0,isLoading:p,noResultsMessage:E})}),Mt.length>0&&e.jsx("div",{className:"tw:m-1 tw:flex-1 tw:overflow-auto tw:rounded-md tw:border",children:e.jsx(bs,{classNameForText:g,occurrenceData:Mt,setScriptureReference:r,localizedStrings:a})})]})})}const Ds="16rem",Os="3rem",vo=l.createContext(void 0);function ze(){const t=l.useContext(vo);if(!t)throw new Error("useSidebar must be used within a SidebarProvider.");return t}function bo({defaultOpen:t=!0,open:r,onOpenChange:a,className:o,style:i,children:s,side:c="primary",...d}){const[u,w]=l.useState(t),p=r??u,g=l.useCallback(_=>{const B=typeof _=="function"?_(p):_;a?a(B):w(B)},[a,p]),f=l.useCallback(()=>g(_=>!_),[g]),h=p?"expanded":"collapsed",b=n.readDirection()==="ltr"?c:c==="primary"?"secondary":"primary",C=l.useMemo(()=>({state:h,open:p,setOpen:g,toggleSidebar:f,side:b}),[h,p,g,f,b]),y={"--sidebar-width":Ds,"--sidebar-width-icon":Os,...i};return e.jsx(vo.Provider,{value:C,children:e.jsx("div",{"data-slot":"sidebar-wrapper",style:y,className:n.cn("pr-twp tw:group/sidebar-wrapper tw:flex tw:w-full tw:has-data-[variant=inset]:bg-sidebar",o),...d,children:s})})}function xo({variant:t="sidebar",collapsible:r="offcanvas",className:a,children:o,...i}){const s=ze();return r==="none"?e.jsx("div",{"data-slot":"sidebar",className:n.cn("tw:flex tw:h-full tw:w-(--sidebar-width) tw:flex-col tw:bg-sidebar tw:text-sidebar-foreground",a),...i,children:o}):e.jsxs("div",{className:"tw:group tw:peer tw:hidden tw:text-sidebar-foreground tw:md:block","data-state":s.state,"data-collapsible":s.state==="collapsed"?r:"","data-variant":t,"data-side":s.side,"data-slot":"sidebar",children:[e.jsx("div",{"data-slot":"sidebar-gap",className:n.cn("tw:relative tw:w-(--sidebar-width) tw:bg-transparent tw:transition-[width] tw:duration-200 tw:ease-linear","tw:group-data-[collapsible=offcanvas]:w-0","tw:group-data-[side=secondary]:rotate-180",t==="floating"||t==="inset"?"tw:group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]":"tw:group-data-[collapsible=icon]:w-(--sidebar-width-icon)")}),e.jsx("div",{"data-slot":"sidebar-container","data-side":s.side,className:n.cn("tw:absolute tw:inset-y-0 tw:z-10 tw:hidden tw:h-svh tw:w-(--sidebar-width) tw:transition-[left,right,width] tw:duration-200 tw:ease-linear tw:md:flex",s.side==="primary"?"tw:left-0 tw:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]":"tw:right-0 tw:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",t==="floating"||t==="inset"?"tw:p-2 tw:group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]":"tw:group-data-[collapsible=icon]:w-(--sidebar-width-icon) tw:group-data-[side=primary]:border-e tw:group-data-[side=secondary]:border-s",a),...i,children:e.jsx("div",{"data-sidebar":"sidebar","data-slot":"sidebar-inner",className:"tw:flex tw:size-full tw:flex-col tw:bg-sidebar tw:group-data-[variant=floating]:rounded-lg tw:group-data-[variant=floating]:shadow-sm tw:group-data-[variant=floating]:ring-1 tw:group-data-[variant=floating]:ring-sidebar-border",children:o})})]})}function zs({className:t,onClick:r,...a}){const{toggleSidebar:o,side:i}=ze();return e.jsxs(n.Button,{"data-sidebar":"trigger","data-slot":"sidebar-trigger",variant:"ghost",size:"icon-sm",className:n.cn(t),onClick:s=>{r==null||r(s),o()},...a,children:[i==="primary"?e.jsx(Tt.IconLayoutSidebar,{}):e.jsx(Tt.IconLayoutSidebarRight,{}),e.jsx("span",{className:"tw:sr-only",children:"Toggle Sidebar"})]})}function Is({className:t,...r}){const{toggleSidebar:a}=ze();return e.jsx("button",{type:"button","data-sidebar":"rail","data-slot":"sidebar-rail","aria-label":"Toggle Sidebar",tabIndex:-1,onClick:a,title:"Toggle Sidebar",className:n.cn("tw:absolute tw:inset-y-0 tw:z-20 tw:hidden tw:w-4 tw:transition-all tw:ease-linear tw:group-data-[side=primary]:-right-4 tw:group-data-[side=secondary]:left-0 tw:after:absolute tw:after:inset-y-0 tw:after:start-1/2 tw:after:w-[2px] tw:hover:after:bg-sidebar-border tw:sm:flex tw:ltr:-translate-x-1/2 tw:rtl:translate-x-1/2","tw:in-data-[side=primary]:cursor-w-resize tw:rtl:in-data-[side=primary]:cursor-e-resize tw:in-data-[side=secondary]:cursor-e-resize tw:rtl:in-data-[side=secondary]:cursor-w-resize","tw:[[data-side=primary][data-state=collapsed]_&]:cursor-e-resize tw:rtl:[[data-side=primary][data-state=collapsed]_&]:cursor-w-resize tw:[[data-side=secondary][data-state=collapsed]_&]:cursor-w-resize tw:rtl:[[data-side=secondary][data-state=collapsed]_&]:cursor-e-resize","tw:group-data-[collapsible=offcanvas]:translate-x-0 tw:group-data-[collapsible=offcanvas]:after:start-full tw:hover:group-data-[collapsible=offcanvas]:bg-sidebar","tw:[[data-side=primary][data-collapsible=offcanvas]_&]:-end-2","tw:[[data-side=secondary][data-collapsible=offcanvas]_&]:-start-2",t),...r})}function ko({className:t,...r}){return e.jsx("main",{"data-slot":"sidebar-inset",className:n.cn("tw:relative tw:flex tw:w-full tw:flex-1 tw:flex-col tw:bg-background tw:md:peer-data-[variant=inset]:m-2 tw:md:peer-data-[variant=inset]:ms-0 tw:md:peer-data-[variant=inset]:rounded-xl tw:md:peer-data-[variant=inset]:shadow-sm tw:md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2",t),...r})}function As({className:t,...r}){return e.jsx(n.Input,{"data-slot":"sidebar-input","data-sidebar":"input",className:n.cn("tw:h-8 tw:w-full tw:bg-background tw:shadow-none",t),...r})}function $s({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-header","data-sidebar":"header",className:n.cn("tw:flex tw:flex-col tw:gap-2 tw:p-2",t),...r})}function Bs({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-footer","data-sidebar":"footer",className:n.cn("tw:flex tw:flex-col tw:gap-2 tw:p-2",t),...r})}function Ps({className:t,...r}){return e.jsx(n.Separator,{"data-slot":"sidebar-separator","data-sidebar":"separator",className:n.cn("tw:mx-2 tw:w-auto tw:bg-sidebar-border",t),...r})}function yo({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-content","data-sidebar":"content",className:n.cn("tw:no-scrollbar tw:flex tw:min-h-0 tw:flex-1 tw:flex-col tw:gap-0 tw:overflow-auto tw:group-data-[collapsible=icon]:overflow-hidden",t),...r})}function kr({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-group","data-sidebar":"group",className:n.cn("tw:relative tw:flex tw:w-full tw:min-w-0 tw:flex-col tw:p-2",t),...r})}function yr({className:t,asChild:r=!1,...a}){const o=r?D.Slot.Root:"div";return e.jsx(o,{"data-slot":"sidebar-group-label","data-sidebar":"group-label",className:n.cn("tw:flex tw:h-8 tw:shrink-0 tw:items-center tw:rounded-md tw:px-2 tw:text-xs tw:font-medium tw:text-sidebar-foreground/70 tw:ring-sidebar-ring tw:outline-hidden tw:transition-[margin,opacity] tw:duration-200 tw:ease-linear tw:group-data-[collapsible=icon]:-mt-8 tw:group-data-[collapsible=icon]:opacity-0 tw:focus-visible:ring-2 tw:[&>svg]:size-4 tw:[&>svg]:shrink-0",t),...a})}function Ls({className:t,asChild:r=!1,...a}){const o=r?D.Slot.Root:"button";return e.jsx(o,{"data-slot":"sidebar-group-action","data-sidebar":"group-action",className:n.cn("tw:absolute tw:top-3.5 tw:end-3 tw:flex tw:aspect-square tw:w-5 tw:items-center tw:justify-center tw:rounded-md tw:p-0 tw:text-sidebar-foreground tw:ring-sidebar-ring tw:outline-hidden tw:transition-transform tw:group-data-[collapsible=icon]:hidden tw:after:absolute tw:after:-inset-2 tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:md:after:hidden tw:[&>svg]:size-4 tw:[&>svg]:shrink-0",t),...a})}function _r({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-group-content","data-sidebar":"group-content",className:n.cn("tw:w-full tw:text-sm",t),...r})}function _o({className:t,...r}){return e.jsx("ul",{"data-slot":"sidebar-menu","data-sidebar":"menu",className:n.cn("tw:flex tw:w-full tw:min-w-0 tw:flex-col tw:gap-0",t),...r})}function jo({className:t,...r}){return e.jsx("li",{"data-slot":"sidebar-menu-item","data-sidebar":"menu-item",className:n.cn("tw:group/menu-item tw:relative",t),...r})}const Vs=er.cva("tw:peer/menu-button tw:group/menu-button tw:flex tw:w-full tw:items-center tw:gap-2 tw:overflow-hidden tw:rounded-md tw:p-2 tw:text-start tw:text-sm tw:ring-sidebar-ring tw:outline-hidden tw:transition-[width,height,padding] tw:group-has-data-[sidebar=menu-action]/menu-item:pe-8 tw:group-data-[collapsible=icon]:size-8! tw:group-data-[collapsible=icon]:p-2! tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:active:bg-sidebar-accent tw:active:text-sidebar-accent-foreground tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-disabled:pointer-events-none tw:aria-disabled:opacity-50 tw:data-open:hover:bg-sidebar-accent tw:data-open:hover:text-sidebar-accent-foreground tw:data-active:bg-sidebar-accent tw:data-active:font-medium tw:data-active:text-sidebar-accent-foreground tw:[&_svg]:size-4 tw:[&_svg]:shrink-0 tw:[&>span:last-child]:truncate",{variants:{variant:{default:"tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground",outline:"tw:bg-background tw:shadow-[0_0_0_1px_var(--sidebar-border)] tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:hover:shadow-[0_0_0_1px_var(--sidebar-accent)]"},size:{default:"tw:h-8 tw:text-sm",sm:"tw:h-7 tw:text-xs",lg:"tw:h-12 tw:text-sm tw:group-data-[collapsible=icon]:p-0!"}},defaultVariants:{variant:"default",size:"default"}});function Co({asChild:t=!1,isActive:r=!1,variant:a="default",size:o="default",tooltip:i,className:s,...c}){const d=t?D.Slot.Root:"button",{state:u}=ze(),w=e.jsx(d,{"data-slot":"sidebar-menu-button","data-sidebar":"menu-button","data-size":o,"data-active":r,className:n.cn(Vs({variant:a,size:o}),s),...c});if(!i)return w;const p=typeof i=="string"?{children:i}:i;return e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:w}),e.jsx(n.TooltipContent,{side:"right",align:"center",hidden:u!=="collapsed",...p})]})}function Fs({className:t,asChild:r=!1,showOnHover:a=!1,...o}){const i=r?D.Slot.Root:"button";return e.jsx(i,{"data-slot":"sidebar-menu-action","data-sidebar":"menu-action",className:n.cn("tw:absolute tw:top-1.5 tw:end-1 tw:flex tw:aspect-square tw:w-5 tw:items-center tw:justify-center tw:rounded-md tw:p-0 tw:text-sidebar-foreground tw:ring-sidebar-ring tw:outline-hidden tw:transition-transform tw:group-data-[collapsible=icon]:hidden tw:peer-hover/menu-button:text-sidebar-accent-foreground tw:peer-data-[size=default]/menu-button:top-1.5 tw:peer-data-[size=lg]/menu-button:top-2.5 tw:peer-data-[size=sm]/menu-button:top-1 tw:after:absolute tw:after:-inset-2 tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:md:after:hidden tw:[&>svg]:size-4 tw:[&>svg]:shrink-0",a&&"tw:group-focus-within/menu-item:opacity-100 tw:group-hover/menu-item:opacity-100 tw:peer-data-active/menu-button:text-sidebar-accent-foreground tw:aria-expanded:opacity-100 tw:md:opacity-0",t),...o})}function Gs({className:t,...r}){return e.jsx("div",{"data-slot":"sidebar-menu-badge","data-sidebar":"menu-badge",className:n.cn("tw:pointer-events-none tw:absolute tw:end-1 tw:flex tw:h-5 tw:min-w-5 tw:items-center tw:justify-center tw:rounded-md tw:px-1 tw:text-xs tw:font-medium tw:text-sidebar-foreground tw:tabular-nums tw:select-none tw:group-data-[collapsible=icon]:hidden tw:peer-hover/menu-button:text-sidebar-accent-foreground tw:peer-data-[size=default]/menu-button:top-1.5 tw:peer-data-[size=lg]/menu-button:top-2.5 tw:peer-data-[size=sm]/menu-button:top-1 tw:peer-data-active/menu-button:text-sidebar-accent-foreground",t),...r})}function Ks({className:t,showIcon:r=!1,...a}){const[o]=l.useState(()=>`${Math.floor(Math.random()*40)+50}%`),i={"--skeleton-width":o};return e.jsxs("div",{"data-slot":"sidebar-menu-skeleton","data-sidebar":"menu-skeleton",className:n.cn("tw:flex tw:h-8 tw:items-center tw:gap-2 tw:rounded-md tw:px-2",t),...a,children:[r&&e.jsx(n.Skeleton,{className:"tw:size-4 tw:rounded-md","data-sidebar":"menu-skeleton-icon"}),e.jsx(n.Skeleton,{className:"tw:h-4 tw:max-w-(--skeleton-width) tw:flex-1","data-sidebar":"menu-skeleton-text",style:i})]})}function Us({className:t,...r}){return e.jsx("ul",{"data-slot":"sidebar-menu-sub","data-sidebar":"menu-sub",className:n.cn("tw:mx-3.5 tw:flex tw:min-w-0 tw:translate-x-px tw:rtl:-translate-x-px tw:flex-col tw:gap-1 tw:border-s tw:border-sidebar-border tw:px-2.5 tw:py-0.5 tw:group-data-[collapsible=icon]:hidden",t),...r})}function qs({className:t,...r}){return e.jsx("li",{"data-slot":"sidebar-menu-sub-item","data-sidebar":"menu-sub-item",className:n.cn("tw:group/menu-sub-item tw:relative",t),...r})}function Hs({asChild:t=!1,size:r="md",isActive:a=!1,className:o,...i}){const s=t?D.Slot.Root:"a";return e.jsx(s,{"data-slot":"sidebar-menu-sub-button","data-sidebar":"menu-sub-button","data-size":r,"data-active":a,className:n.cn("tw:flex tw:h-7 tw:min-w-0 tw:-translate-x-px tw:rtl:translate-x-px tw:items-center tw:gap-2 tw:overflow-hidden tw:rounded-md tw:px-2 tw:text-sidebar-foreground tw:ring-sidebar-ring tw:outline-hidden tw:group-data-[collapsible=icon]:hidden tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:active:bg-sidebar-accent tw:active:text-sidebar-accent-foreground tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-disabled:pointer-events-none tw:aria-disabled:opacity-50 tw:data-[size=md]:text-sm tw:data-[size=sm]:text-xs tw:data-active:bg-sidebar-accent tw:data-active:text-sidebar-accent-foreground tw:[&>span:last-child]:truncate tw:[&>svg]:size-4 tw:[&>svg]:shrink-0 tw:[&>svg]:text-sidebar-accent-foreground",o),...i})}function No({id:t,extensionLabels:r,projectInfo:a,handleSelectSidebarItem:o,selectedSidebarItem:i,extensionsSidebarGroupLabel:s,projectsSidebarGroupLabel:c,buttonPlaceholderText:d,className:u}){const w=l.useCallback((h,m)=>{o(h,m)},[o]),p=l.useCallback(h=>{const m=a.find(k=>k.projectId===h);return m?m.projectName:h},[a]),g=l.useMemo(()=>a.map(h=>({id:h.projectId,shortName:h.projectName,fullName:h.projectName})),[a]),f=l.useCallback(h=>!i.projectId&&h===i.label,[i]);return e.jsx(xo,{id:t,collapsible:"none",variant:"inset",className:n.cn("tw:w-96 tw:gap-2 tw:overflow-y-auto",u),children:e.jsxs(yo,{children:[e.jsxs(kr,{children:[e.jsx(yr,{className:"tw:text-sm",children:s}),e.jsx(_r,{children:e.jsx(_o,{children:Object.entries(r).map(([h,m])=>e.jsx(jo,{children:e.jsx(Co,{onClick:()=>w(h),isActive:f(h),children:e.jsx("span",{className:"tw:pl-3",children:m})})},h))})})]}),e.jsxs(kr,{children:[e.jsx(yr,{className:"tw:text-sm",children:c}),e.jsx(_r,{className:"tw:pl-3",children:e.jsxs("div",{className:n.cn("tw:flex tw:w-full tw:items-center tw:gap-2 tw:rounded-md tw:px-2 tw:py-1",{"tw:bg-sidebar-accent tw:text-sidebar-accent-foreground":i==null?void 0:i.projectId}),children:[e.jsx(R.ScrollText,{className:"tw:h-4 tw:w-4 tw:shrink-0"}),e.jsx(n.ProjectSelector,{mode:"project",projects:g,openTabs:[],selection:{projectId:(i==null?void 0:i.projectId)??""},onChangeSelection:({projectId:h})=>{if(!h)return;const m=p(h);w(m,h)},buttonVariant:"ghost",buttonClassName:"tw:h-8 tw:w-full tw:flex-1 tw:justify-start tw:font-normal",buttonPlaceholder:d,ariaLabel:c,popoverContentStyle:{zIndex:n.Z_INDEX_OVERLAY}})]})})]})]})})}function Ys({id:t,extensionLabels:r,projectInfo:a,children:o,handleSelectSidebarItem:i,selectedSidebarItem:s,searchValue:c,onSearch:d,extensionsSidebarGroupLabel:u,projectsSidebarGroupLabel:w,buttonPlaceholderText:p}){return e.jsxs("div",{className:"tw:box-border tw:flex tw:h-full tw:flex-col",children:[e.jsx("div",{className:"tw:box-border tw:flex tw:items-center tw:justify-center tw:py-4",children:e.jsx(n.SearchBar,{className:"tw:w-9/12",value:c,onSearch:d,placeholder:"Search app settings, extension settings, and project settings"})}),e.jsxs(bo,{id:t,className:"tw:h-full tw:flex-1 tw:gap-4 tw:overflow-auto tw:border-t",children:[e.jsx(No,{className:"tw:w-1/2 tw:min-w-[140px] tw:max-w-[220px] tw:border-e",extensionLabels:r,projectInfo:a,handleSelectSidebarItem:i,selectedSidebarItem:s,extensionsSidebarGroupLabel:u,projectsSidebarGroupLabel:w,buttonPlaceholderText:p}),e.jsx(ko,{className:"tw:min-w-[215px]",children:o})]})]})}const ie="scrBook",Xs="scrRef",we="source",Zs="details",Ws="Scripture Reference",Js="Scripture Book",Eo="Type",Qs="Details";function tc(t,r){const a=r??!1;return[{accessorFn:o=>`${o.start.book} ${o.start.chapterNum}:${o.start.verseNum}`,id:ie,header:(t==null?void 0:t.scriptureReferenceColumnName)??Ws,cell:o=>{const i=o.row.original;return o.row.getIsGrouped()?ht.Canon.bookIdToEnglishName(i.start.book):o.row.groupingColumnId===ie?M.formatScrRef(i.start):void 0},getGroupingValue:o=>ht.Canon.bookIdToNumber(o.start.book),sortingFn:(o,i)=>M.compareScrRefs(o.original.start,i.original.start),enableGrouping:!0},{accessorFn:o=>M.formatScrRef(o.start),id:Xs,header:void 0,cell:o=>{const i=o.row.original;return o.row.getIsGrouped()?void 0:M.formatScrRef(i.start)},sortingFn:(o,i)=>M.compareScrRefs(o.original.start,i.original.start),enableGrouping:!1},{accessorFn:o=>o.source.displayName,id:we,header:a?(t==null?void 0:t.typeColumnName)??Eo:void 0,cell:o=>a||o.row.getIsGrouped()?o.getValue():void 0,getGroupingValue:o=>o.source.id,sortingFn:(o,i)=>o.original.source.displayName.localeCompare(i.original.source.displayName),enableGrouping:!0},{accessorFn:o=>o.detail,id:Zs,header:(t==null?void 0:t.detailsColumnName)??Qs,cell:o=>o.getValue(),enableGrouping:!1}]}const ec=t=>{if(!("offset"in t.start))throw new Error("No offset available in range start");if(t.end&&!("offset"in t.end))throw new Error("No offset available in range end");const{offset:r}=t.start;let a=0;return t.end&&({offset:a}=t.end),!t.end||M.compareScrRefs(t.start,t.end)===0?`${M.scrRefToBBBCCCVVV(t.start)}+${r}`:`${M.scrRefToBBBCCCVVV(t.start)}+${r}-${M.scrRefToBBBCCCVVV(t.end)}+${a}`},pa=t=>`${ec({start:t.start,end:t.end})} ${t.source.displayName} ${t.detail}`;function rc({sources:t,showColumnHeaders:r=!1,showSourceColumn:a=!1,scriptureReferenceColumnName:o,scriptureBookGroupName:i,typeColumnName:s,detailsColumnName:c,onRowSelected:d,id:u}){const[w,p]=l.useState([]),[g,f]=l.useState([{id:ie,desc:!1}]),[h,m]=l.useState({}),k=l.useMemo(()=>t.flatMap(j=>j.data.map(V=>({...V,source:j.source}))),[t]),b=l.useMemo(()=>tc({scriptureReferenceColumnName:o,typeColumnName:s,detailsColumnName:c},a),[o,s,c,a]);l.useEffect(()=>{w.includes(we)?f([{id:we,desc:!1},{id:ie,desc:!1}]):f([{id:ie,desc:!1}])},[w]);const C=It.useReactTable({data:k,columns:b,state:{grouping:w,sorting:g,rowSelection:h},onGroupingChange:p,onSortingChange:f,onRowSelectionChange:m,getExpandedRowModel:It.getExpandedRowModel(),getGroupedRowModel:It.getGroupedRowModel(),getCoreRowModel:It.getCoreRowModel(),getSortedRowModel:It.getSortedRowModel(),getRowId:pa,autoResetExpanded:!1,enableMultiRowSelection:!1,enableSubRowSelection:!1});l.useEffect(()=>{if(d){const j=C.getSelectedRowModel().rowsById,V=Object.keys(j);if(V.length===1){const z=k.find(N=>pa(N)===V[0])||void 0;z&&d(z)}}},[h,k,d,C]);const y=i??Js,_=s??Eo,B=[{label:"No Grouping",value:[]},{label:`Group by ${y}`,value:[ie]},{label:`Group by ${_}`,value:[we]},{label:`Group by ${y} and ${_}`,value:[ie,we]},{label:`Group by ${_} and ${y}`,value:[we,ie]}],F=j=>{p(JSON.parse(j))},E=(j,V)=>{!j.getIsGrouped()&&!j.getIsSelected()&&j.getToggleSelectedHandler()(V)},P=(j,V)=>j.getIsGrouped()?"":n.cn("banded-row",V%2===0?"even":"odd"),A=(j,V,z)=>{if(!((j==null?void 0:j.length)===0||V.depth{F(j)},children:[e.jsx(ge,{className:"tw:mb-1 tw:mt-2",children:e.jsx(pe,{})}),e.jsx(he,{position:"item-aligned",children:e.jsx(ro,{children:B.map(j=>e.jsx(Ut,{value:JSON.stringify(j.value),children:j.label},j.label))})})]}),e.jsxs(n.Table,{className:"tw:relative tw:flex tw:flex-col tw:overflow-y-auto tw:p-0",children:[r&&e.jsx(n.TableHeader,{children:C.getHeaderGroups().map(j=>e.jsx(n.TableRow,{children:j.headers.filter(V=>V.column.columnDef.header).map(V=>e.jsx(n.TableHead,{colSpan:V.colSpan,className:"tw:sticky top-0",children:V.isPlaceholder?void 0:e.jsxs("div",{children:[V.column.getCanGroup()?e.jsx(n.Button,{variant:"ghost",title:`Toggle grouping by ${V.column.columnDef.header}`,onClick:V.column.getToggleGroupingHandler(),type:"button",children:V.column.getIsGrouped()?"🛑":"👊 "}):void 0," ",It.flexRender(V.column.columnDef.header,V.getContext())]})},V.id))},j.id))}),e.jsx(n.TableBody,{children:C.getRowModel().rows.map((j,V)=>{const z=n.readDirection();return e.jsx(n.TableRow,{"data-state":j.getIsSelected()?"selected":"",className:n.cn(P(j,V)),onClick:N=>E(j,N),children:j.getVisibleCells().map(N=>{if(!(N.getIsPlaceholder()||N.column.columnDef.enableGrouping&&!N.getIsGrouped()&&(N.column.columnDef.id!==we||!a)))return e.jsx(n.TableCell,{className:n.cn(N.column.columnDef.id,"tw:p-[1px]",A(w,j,N)),children:N.getIsGrouped()?e.jsxs(n.Button,{variant:"link",onClick:j.getToggleExpandedHandler(),type:"button",children:[j.getIsExpanded()&&e.jsx(R.ChevronDown,{}),!j.getIsExpanded()&&(z==="ltr"?e.jsx(R.ChevronRight,{}):e.jsx(R.ChevronLeft,{}))," ",It.flexRender(N.column.columnDef.cell,N.getContext())," (",j.subRows.length,")"]}):It.flexRender(N.column.columnDef.cell,N.getContext())},N.id)})},j.id)})})]})]})}function So(t){if(t.length!==ht.Canon.allBookIds.length)throw new Error("availableBookInfo length must match Canon.allBookIds length");return ht.Canon.allBookIds.filter((r,a)=>t[a]==="1"&&!ht.Canon.isObsolete(ht.Canon.bookIdToNumber(r)))}function $r(t,r){return t.filter(a=>{try{return M.getSectionForBook(a)===r}catch{return!1}})}const To=(t,r,a)=>$r(t,r).every(o=>a.includes(o));function Mo({availableBookInfo:t,selectedBookIds:r,onChangeSelectedBookIds:a,localizedStrings:o,localizedBookNames:i}){const s=o["%webView_book_selector_books_selected%"],c=o["%webView_book_selector_select_books%"],d=o["%webView_book_selector_search_books%"],u=o["%webView_book_selector_select_all%"],w=o["%webView_book_selector_clear_all%"],p=o["%webView_book_selector_no_book_found%"],{otLong:g,ntLong:f,dcLong:h,extraLong:m}={otLong:o==null?void 0:o["%scripture_section_ot_long%"],ntLong:o==null?void 0:o["%scripture_section_nt_long%"],dcLong:o==null?void 0:o["%scripture_section_dc_long%"],extraLong:o==null?void 0:o["%scripture_section_extra_long%"]},[k,b]=l.useState(!1),[C,y]=l.useState(""),_=l.useRef(void 0),B=l.useRef(!1),F=l.useMemo(()=>So(t),[t]),E=l.useMemo(()=>{if(!C.trim()){const U={[M.Section.OT]:[],[M.Section.NT]:[],[M.Section.DC]:[],[M.Section.Extra]:[]};return F.forEach(G=>{const I=M.getSectionForBook(G);U[I].push(G)}),U}const N=F.filter(U=>n.doesBookMatchQuery(U,C,i)),H={[M.Section.OT]:[],[M.Section.NT]:[],[M.Section.DC]:[],[M.Section.Extra]:[]};return N.forEach(U=>{const G=M.getSectionForBook(U);H[G].push(U)}),H},[F,C,i]),P=l.useCallback((N,H=!1)=>{if(!H||!_.current){a(r.includes(N)?r.filter(W=>W!==N):[...r,N]),_.current=N;return}const U=F.findIndex(W=>W===_.current),G=F.findIndex(W=>W===N);if(U===-1||G===-1)return;const[I,T]=[Math.min(U,G),Math.max(U,G)],Z=F.slice(I,T+1).map(W=>W);a(r.includes(N)?r.filter(W=>!Z.includes(W)):[...new Set([...r,...Z])])},[r,a,F]),A=N=>{P(N,B.current),B.current=!1},j=(N,H)=>{N.preventDefault(),P(H,N.shiftKey)},V=()=>{a(F.map(N=>N))},z=()=>{a([])};return e.jsxs(n.Popover,{open:k,onOpenChange:N=>{b(N),N||y("")},children:[e.jsx(n.PopoverTrigger,{asChild:!0,children:e.jsxs(n.Button,{variant:"outline",role:"combobox","aria-expanded":k,className:"tw:max-w-64 tw:justify-between",children:[r.length>0?`${s}: ${r.length}`:c,e.jsx(R.ChevronsUpDown,{className:"tw:ml-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})}),e.jsx(n.PopoverContent,{className:"tw:w-[500px] tw:max-w-[calc(100vw-2rem)] tw:p-0",align:"start",children:e.jsxs(n.Command,{shouldFilter:!1,onKeyDown:N=>{N.key==="Enter"&&(B.current=N.shiftKey)},children:[e.jsx(n.CommandInput,{placeholder:d,value:C,onValueChange:y}),e.jsxs("div",{className:"tw:flex tw:justify-between tw:border-b tw:p-2",children:[e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:V,children:u}),e.jsx(n.Button,{variant:"ghost",size:"sm",onClick:z,children:w})]}),e.jsxs(n.CommandList,{children:[e.jsx(n.CommandEmpty,{children:p}),Object.values(M.Section).map((N,H)=>{const U=E[N];if(U.length!==0)return e.jsxs(l.Fragment,{children:[e.jsx(n.CommandGroup,{heading:n.getSectionLongName(N,g,f,h,m),children:U.map(G=>e.jsx(va,{bookId:G,isSelected:r.includes(G),onSelect:()=>A(G),onMouseDown:I=>j(I,G),section:M.getSectionForBook(G),showCheck:!0,localizedBookNames:i,commandValue:ba(G,i),className:"tw:flex tw:items-center"},G))}),Ho(t),className:n.cn(To(r,t,a)&&!s&&"tw:bg-primary tw:text-primary-foreground tw:hover:bg-primary/70 tw:hover:text-primary-foreground"),disabled:s,children:n.getSectionShortName(t,c,d,u,w)})}const ga=5,gr=6;function Ro({availableBookInfo:t,selectedBookIds:r,onChangeSelectedBookIds:a,localizedStrings:o,localizedBookNames:i}){const s=o["%webView_book_selector_more%"],c=l.useMemo(()=>So(t),[t]),d=l.useCallback(u=>{const w=$r(c,u).map(p=>p);a(To(c,u,r)?r.filter(p=>!w.includes(p)):[...new Set([...r,...w])])},[r,a,c]);return e.jsxs("div",{className:"tw:space-y-2",children:[e.jsx("div",{className:"tw:flex tw:flex-wrap tw:gap-2",children:Object.values(M.Section).map(u=>e.jsx(ac,{section:u,availableBookIds:c,selectedBookIds:r,onToggle:d,localizedStrings:o},u))}),e.jsx(Mo,{availableBookInfo:t,selectedBookIds:r,onChangeSelectedBookIds:a,localizedStrings:o,localizedBookNames:i}),r.length>0&&e.jsxs("div",{className:"tw:mt-2 tw:flex tw:flex-wrap tw:gap-1",children:[r.slice(0,r.length===gr?gr:ga).map(u=>e.jsx(n.Badge,{className:"tw:hover:bg-secondary",variant:"secondary",children:n.getLocalizedBookName(u,i)},u)),r.length>gr&&e.jsx(n.Badge,{className:"tw:hover:bg-secondary",variant:"secondary",children:`+${r.length-ga} ${s}`})]})]})}const Do=Object.freeze(["%webView_book_selector_books_selected%","%webView_book_selector_select_books%","%webView_book_selector_search_books%","%webView_book_selector_select_all%","%webView_book_selector_clear_all%","%webView_book_selector_no_book_found%","%webView_book_selector_more%","%scripture_section_ot_long%","%scripture_section_ot_short%","%scripture_section_nt_long%","%scripture_section_nt_short%","%scripture_section_dc_long%","%scripture_section_dc_short%","%scripture_section_extra_long%","%scripture_section_extra_short%"]),oc=Object.freeze(["%webView_scope_selector_selected_text%","%webView_scope_selector_verse%","%webView_scope_selector_chapter%","%webView_scope_selector_book%","%webView_scope_selector_current_verse%","%webView_scope_selector_current_chapter%","%webView_scope_selector_current_book%","%webView_scope_selector_choose_books%","%webView_scope_selector_scope%","%webView_scope_selector_select_books%","%webView_scope_selector_range%","%webView_scope_selector_select_range%","%webView_scope_selector_range_start%","%webView_scope_selector_range_end%","%webView_scope_selector_ok%","%webView_scope_selector_cancel%","%webView_scope_selector_navigate%",...Do]),kt=(t,r)=>t[r]??r,nc=Object.freeze([" ","-"]);function ic({scope:t,availableScopes:r,onScopeChange:a,availableBookInfo:o,selectedBookIds:i,onSelectedBookIdsChange:s,localizedStrings:c,localizedBookNames:d,id:u,variant:w="radio",rangeStart:p,rangeEnd:g,onRangeStartChange:f,onRangeEndChange:h,currentScrRef:m,onCurrentScrRefChange:k,bookChapterControlLocalizedStrings:b,getEndVerse:C,hideLabel:y=!1,buttonClassName:_}){const B=kt(c,"%webView_scope_selector_selected_text%"),F=kt(c,"%webView_scope_selector_verse%"),E=kt(c,"%webView_scope_selector_chapter%"),P=kt(c,"%webView_scope_selector_book%"),A=kt(c,"%webView_scope_selector_current_verse%"),j=kt(c,"%webView_scope_selector_current_chapter%"),V=kt(c,"%webView_scope_selector_current_book%"),z=kt(c,"%webView_scope_selector_choose_books%"),N=kt(c,"%webView_scope_selector_scope%"),H=kt(c,"%webView_scope_selector_select_books%"),U=kt(c,"%webView_scope_selector_range%"),G=kt(c,"%webView_scope_selector_select_range%"),I=kt(c,"%webView_scope_selector_range_start%"),T=kt(c,"%webView_scope_selector_range_end%"),Z=kt(c,"%webView_scope_selector_ok%"),W=kt(c,"%webView_scope_selector_cancel%"),vt=kt(c,"%webView_scope_selector_navigate%"),bt=$=>{if(!m)return;const X=m.book.toUpperCase();switch($){case"verse":return M.formatScrRef(m,"id");case"chapter":return`${X} ${m.chapterNum}`;case"book":return X;default:return}},Mt=[{value:"selectedText",label:B,id:"scope-selected-text"},{value:"verse",label:F,dropdownLabel:A,scrRefSuffix:bt("verse"),id:"scope-verse"},{value:"chapter",label:E,dropdownLabel:j,scrRefSuffix:bt("chapter"),id:"scope-chapter"},{value:"book",label:P,dropdownLabel:V,scrRefSuffix:bt("book"),id:"scope-book"},{value:"selectedBooks",label:z,id:"scope-selected"},{value:"range",label:U,id:"scope-range"}],K=($,X,$t=!1)=>e.jsxs(e.Fragment,{children:[$,X&&!$t&&e.jsxs("span",{className:"tw:text-muted-foreground",children:[": ",X]})]}),J=r?Mt.filter($=>r.includes($.value)):Mt,st=m??M.defaultScrRef,ot=p??st,gt=g??st,qt=()=>{},et=l.useRef(null),Rt=l.useRef(null),yt=l.useRef(!1),Bt=l.useRef(null),Ht=l.useRef(!1),[O,Pt]=l.useState(void 0),ft=l.useRef(!1),xt=l.useRef(!1),Vt=l.useRef(null),te=l.useCallback($=>{if($){Pt("start"),ft.current=!1;return}Pt(X=>X==="start"?void 0:X),ft.current&&(ft.current=!1,requestAnimationFrame(()=>{var $t;const X=($t=et.current)==null?void 0:$t.querySelector("button");X==null||X.click()}))},[]),Yt=l.useCallback($=>{if($){Pt("end"),xt.current=!1;return}Pt(X=>X==="end"?void 0:X)},[]),L=l.useCallback($=>{f==null||f($),h==null||h($),ft.current=!0},[f,h]),Y=l.useCallback($=>{h==null||h($),xt.current=!0},[h]),rt=l.useCallback($=>{a($),$==="selectedBooks"&&i.length===0&&(m!=null&&m.book)&&s([m.book])},[a,i,m,s]),Q=J.find($=>$.value===t),ct=()=>t==="selectedBooks"&&i.length>0?i.map($=>$.toUpperCase()).join(", "):t==="range"?M.formatScrRefRange(ot,gt,{optionOrLocalizedBookName:"id",endRefOptionOrLocalizedBookName:"id",repeatBookName:!0}):Q?K(Q.label,Q.scrRefSuffix):t,nt=J.filter($=>$.value!=="selectedBooks"&&$.value!=="range"),wt=J.find($=>$.value==="selectedBooks"),lt=J.find($=>$.value==="range"),[ut,_t]=l.useState(!1),[jt,At]=l.useState(void 0),[Ct,ae]=l.useState(void 0),[S,Nt]=l.useState(void 0),[mt,Xt]=l.useState(void 0),[oe,_e]=l.useState([]),je=w==="dropdown"&&jt==="selectedBooks",Ce=e.jsx(Ro,{availableBookInfo:o,selectedBookIds:je?oe:i,onChangeSelectedBookIds:je?_e:s,localizedStrings:c,localizedBookNames:d}),Ie=O==="end",Ae=O==="start",fe="tw:text-muted-foreground",x=w==="dropdown"&&jt==="range",q=x?Nt:L,Dt=x?Xt:h?Y:qt,ee=e.jsxs("div",{className:"tw:flex tw:flex-wrap tw:items-end tw:gap-4",children:[e.jsxs("div",{className:"tw:grid tw:gap-2",children:[e.jsx(n.Label,{htmlFor:"scope-range-start",className:n.cn(Ie&&fe),children:I}),e.jsx(Ge,{id:"scope-range-start",scrRef:x?S??ot:ot,handleSubmit:q,localizedBookNames:d,localizedStrings:b,getEndVerse:C,submitKeys:nc,onOpenChange:te,className:n.cn(Ie&&fe),modal:!0})]}),e.jsxs("div",{ref:et,className:"tw:grid tw:gap-2",children:[e.jsx(n.Label,{htmlFor:"scope-range-end",className:n.cn(Ae&&fe),children:T}),e.jsx(Ge,{id:"scope-range-end",scrRef:x?mt??gt:gt,handleSubmit:Dt,localizedBookNames:d,localizedStrings:b,getEndVerse:C,disableReferencesUpTo:x?S??ot:ot,onOpenChange:Yt,onCloseAutoFocus:$=>{var X;xt.current&&(xt.current=!1,$.preventDefault(),(X=Vt.current)==null||X.focus())},className:n.cn(Ae&&fe),modal:!0,align:"start"})]})]}),ce=l.useRef({}),ne=l.useCallback($=>X=>{ce.current[$]=X},[]),Et=l.useRef(null);l.useEffect(()=>{if(!ut)return;let $=0;const X=requestAnimationFrame(()=>{$=requestAnimationFrame(()=>{var $t;($t=ce.current[t])==null||$t.focus()})});return()=>{cancelAnimationFrame(X),$&&cancelAnimationFrame($)}},[ut,t]);const[pt,St]=l.useState(null),[dt,Ft]=l.useState(null),[Lt,le]=l.useState(null),Fo=200,[Go,Ko]=l.useState(!1);l.useEffect(()=>{if(!Lt||typeof ResizeObserver>"u")return;const $=new ResizeObserver(([X])=>{Ko(X.contentRect.width$.disconnect()},[Lt]);const Vr=l.useCallback($=>{ae($),Nt(ot),Xt(gt),_e(i),_t(!1),At($)},[ot,gt,i]),Fr=l.useCallback(()=>{Ct!==void 0&&(Ct==="range"?(S&&(f==null||f(S)),mt&&(h==null||h(mt))):Ct==="selectedBooks"&&s(oe),rt(Ct),At(void 0),ae(void 0))},[Ct,S,mt,oe,f,h,s,rt]),$e=l.useCallback($=>{$||(At(void 0),ae(void 0))},[]),Gr=l.useCallback($=>{var X;$.preventDefault(),(X=Et.current)==null||X.focus()},[]),Kr=$=>t===$?e.jsx("span",{className:"tw:absolute tw:flex tw:h-3.5 tw:w-3.5 tw:items-center tw:justify-center tw:ltr:left-2 tw:rtl:right-2",children:e.jsx(R.Check,{className:"tw:h-4 tw:w-4"})}):void 0;return e.jsxs("div",{id:u,className:"tw:grid tw:gap-4",children:[e.jsxs("div",{className:"tw:grid tw:gap-2",children:[!y&&e.jsx(n.Label,{children:N}),w==="dropdown"?e.jsxs(n.DropdownMenu,{open:ut,onOpenChange:_t,children:[e.jsx(n.DropdownMenuTrigger,{asChild:!0,children:e.jsxs(n.Button,{ref:Et,variant:"outline",role:"combobox",className:n.cn("tw:w-full tw:justify-between tw:overflow-hidden tw:font-normal",_),children:[e.jsx("span",{className:"tw:min-w-0 tw:flex-1 tw:truncate tw:text-start",children:ct()}),e.jsx(R.ChevronDown,{className:"tw:ms-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})}),e.jsx(n.DropdownMenuContent,{ref:le,className:"tw:w-[var(--radix-dropdown-menu-trigger-width)] tw:min-w-[12rem]",align:"start",children:e.jsxs(n.PopoverPortalContainerProvider,{container:Lt,children:[nt.map(({value:$,label:X,dropdownLabel:$t,scrRefSuffix:Ne,id:Uo})=>e.jsxs(n.DropdownMenuItem,{ref:ne($),className:"tw:relative tw:ps-8 data-[highlighted]:tw:bg-accent data-[highlighted]:tw:text-accent-foreground",onSelect:()=>rt($),"data-selected":t===$?"true":void 0,children:[t===$&&e.jsx("span",{className:"tw:absolute tw:flex tw:h-3.5 tw:w-3.5 tw:items-center tw:justify-center tw:ltr:left-2 tw:rtl:right-2",children:e.jsx(R.Check,{className:"tw:h-4 tw:w-4"})}),K($t??X,Ne,Go)]},Uo)),(wt||lt)&&e.jsx(n.DropdownMenuSeparator,{}),wt&&e.jsxs(n.DropdownMenuItem,{ref:ne("selectedBooks"),className:n.cn("tw:relative tw:ps-8","data-[highlighted]:tw:bg-accent data-[highlighted]:tw:text-accent-foreground"),onSelect:()=>Vr("selectedBooks"),"data-selected":t==="selectedBooks"?"true":void 0,children:[Kr("selectedBooks"),`${wt.label}…`]}),lt&&e.jsxs(n.DropdownMenuItem,{ref:ne("range"),className:n.cn("tw:relative tw:ps-8","data-[highlighted]:tw:bg-accent data-[highlighted]:tw:text-accent-foreground"),onSelect:()=>Vr("range"),"data-selected":t==="range"?"true":void 0,children:[Kr("range"),`${lt.label}…`]}),k&&e.jsxs(e.Fragment,{children:[e.jsx(n.DropdownMenuSeparator,{}),e.jsx(n.DropdownMenuLabel,{className:"tw:px-2 tw:py-1.5 tw:text-xs tw:font-medium tw:text-muted-foreground",children:vt}),e.jsx(n.DropdownMenuItem,{ref:Bt,className:"tw:p-0",onSelect:$=>{var X,$t;if($.preventDefault(),yt.current){yt.current=!1;return}Ht.current||($t=(X=Rt.current)==null?void 0:X.querySelector("button"))==null||$t.click()},children:e.jsx("div",{ref:Rt,className:"tw:w-full tw:px-1 tw:pb-1",onPointerDownCapture:$=>{const X=$.target instanceof HTMLElement?$.target:void 0;X!=null&&X.closest("button")&&(yt.current=!0,requestAnimationFrame(()=>{yt.current=!1}))},children:e.jsx(Ge,{id:"scope-navigate",scrRef:m??M.defaultScrRef,handleSubmit:k,localizedBookNames:d,localizedStrings:b,getEndVerse:C,triggerVariant:"ghost",onOpenChange:$=>{Ht.current=$},onCloseAutoFocus:$=>{var X;$.preventDefault(),(X=Bt.current)==null||X.focus()},modal:!0,className:"tw:w-full tw:min-w-0 tw:max-w-none tw:justify-between tw:px-2 tw:font-normal",triggerContent:e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"tw:min-w-0 tw:flex-1 tw:truncate tw:text-start",children:M.formatScrRef(m??M.defaultScrRef,"id")}),e.jsx(R.ChevronDown,{className:"tw:ms-2 tw:h-4 tw:w-4 tw:shrink-0 tw:opacity-50"})]})})})})]})]})})]}):e.jsx(rr,{value:t,onValueChange:rt,className:"tw:flex tw:flex-col tw:space-y-1",children:J.map(({value:$,label:X,scrRefSuffix:$t,id:Ne})=>e.jsxs("div",{className:"tw:flex tw:items-center",children:[e.jsx(Re,{className:"tw:me-2",value:$,id:Ne}),e.jsx(n.Label,{htmlFor:Ne,children:K(X,$t)})]},Ne))})]}),w==="radio"&&t==="selectedBooks"&&e.jsxs("div",{className:"tw:grid tw:gap-2",children:[e.jsx(n.Label,{children:H}),Ce]}),w==="radio"&&t==="range"&&ee,w==="dropdown"&&wt&&e.jsx(n.Dialog,{open:jt==="selectedBooks",onOpenChange:$e,children:e.jsx(n.DialogContent,{ref:Ft,onCloseAutoFocus:Gr,onEscapeKeyDown:$=>{dt!=null&&dt.querySelector('[data-state="open"]')&&$.preventDefault()},children:e.jsxs(n.PopoverPortalContainerProvider,{container:dt,children:[e.jsx(n.DialogHeader,{className:"tw:pe-8",children:e.jsx(n.DialogTitle,{children:z})}),Ce,e.jsxs(n.DialogFooter,{children:[e.jsx(n.Button,{variant:"outline",onClick:()=>$e(!1),children:W}),e.jsx(n.Button,{onClick:Fr,children:Z})]})]})})}),w==="dropdown"&<&&e.jsx(n.Dialog,{open:jt==="range",onOpenChange:$e,children:e.jsx(n.DialogContent,{ref:St,onCloseAutoFocus:Gr,onEscapeKeyDown:$=>{pt!=null&&pt.querySelector('[data-state="open"]')&&$.preventDefault()},children:e.jsxs(n.PopoverPortalContainerProvider,{container:pt,children:[e.jsx(n.DialogHeader,{className:"tw:pe-8",children:e.jsx(n.DialogTitle,{children:G})}),ee,e.jsxs(n.DialogFooter,{children:[e.jsx(n.Button,{variant:"outline",onClick:()=>$e(!1),children:W}),e.jsx(n.Button,{ref:Vt,onClick:Fr,children:Z})]})]})})})]})}function sc({availableScrollGroupIds:t,scrollGroupId:r,onChangeScrollGroupId:a,localizedStrings:o={},size:i="sm",className:s,id:c,disabled:d}){const u={...n.Ye,...Object.fromEntries(Object.entries(o).map(([p,g])=>[p,p===g&&p in n.Ye?n.Ye[p]:g]))},w=n.readDirection();return e.jsxs(ue,{value:`${r}`,onValueChange:p=>a(p==="undefined"?void 0:parseInt(p,10)),disabled:d,children:[e.jsx(ge,{size:i,className:n.cn("pr-twp tw:w-auto",s),children:e.jsx(pe,{placeholder:u[M.getLocalizeKeyForScrollGroupId(r)]??r})}),e.jsx(he,{id:c,align:w==="rtl"?"end":"start",style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:t.map(p=>e.jsx(Ut,{value:`${p}`,children:u[M.getLocalizeKeyForScrollGroupId(p)]},`${p}`))})]})}function cc({children:t}){return e.jsx("div",{className:"pr-twp tw:grid",children:t})}function lc({primary:t,secondary:r,children:a,isLoading:o=!1,loadingMessage:i}){return e.jsxs("div",{className:"tw:flex tw:items-center tw:justify-between tw:space-x-4 tw:py-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"tw:text-sm tw:font-medium tw:leading-none",children:t}),e.jsx("p",{className:"tw:whitespace-normal tw:break-words tw:text-sm tw:text-muted-foreground",children:r})]}),o?e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:i}):e.jsx("div",{children:a})]})}function dc({primary:t,secondary:r,includeSeparator:a=!1}){return e.jsxs("div",{className:"tw:space-y-4 tw:py-2",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"tw:text-lg tw:font-medium",children:t}),e.jsx("p",{className:"tw:text-sm tw:text-muted-foreground",children:r})]}),a?e.jsx(n.Separator,{}):""]})}function Oo(t,r){var a;return(a=Object.entries(t).find(([,o])=>"menuItem"in o&&o.menuItem===r))==null?void 0:a[0]}function Qe({icon:t,menuLabel:r,leading:a}){return t?e.jsx("img",{className:n.cn("tw:max-h-5 tw:max-w-5",a?"tw:me-2":"tw:ms-2"),src:t,alt:`${a?"Leading":"Trailing"} icon for ${r}`}):void 0}const zo=(t,r,a,o)=>a?Object.entries(t).filter(([s,c])=>"column"in c&&c.column===a||s===a).sort(([,s],[,c])=>s.order-c.order).flatMap(([s])=>r.filter(d=>d.group===s).sort((d,u)=>d.order-u.order).map(d=>e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:"command"in d?e.jsxs(n.DropdownMenuItem,{onClick:()=>{o(d)},children:[d.iconPathBefore&&e.jsx(Qe,{icon:d.iconPathBefore,menuLabel:d.label,leading:!0}),d.label,d.iconPathAfter&&e.jsx(Qe,{icon:d.iconPathAfter,menuLabel:d.label})]},`dropdown-menu-item-${d.label}-${d.command}`):e.jsxs(n.DropdownMenuSub,{children:[e.jsx(n.DropdownMenuSubTrigger,{children:d.label}),e.jsx(n.DropdownMenuPortal,{children:e.jsx(n.DropdownMenuSubContent,{children:zo(t,r,Oo(t,d.id),o)})})]},`dropdown-menu-sub-${d.label}-${d.id}`)}),d.tooltip&&e.jsx(n.TooltipContent,{children:d.tooltip})]},`tooltip-${d.label}-${"command"in d?d.command:d.id}`))):void 0;function tr({onSelectMenuItem:t,menuData:r,tabLabel:a,icon:o,className:i,variant:s,buttonVariant:c="ghost",id:d}){return e.jsxs(n.DropdownMenu,{variant:s,children:[e.jsx(n.DropdownMenuTrigger,{"aria-label":a,className:i,asChild:!0,id:d,children:e.jsx(n.Button,{variant:c,size:"icon",children:o??e.jsx(R.MenuIcon,{})})}),e.jsx(n.DropdownMenuContent,{align:"start",style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:Object.entries(r.columns).filter(([,u])=>typeof u=="object").sort(([,u],[,w])=>typeof u=="boolean"||typeof w=="boolean"?0:u.order-w.order).map(([u],w,p)=>e.jsxs(l.Fragment,{children:[e.jsx(n.DropdownMenuGroup,{children:e.jsx(n.TooltipProvider,{children:zo(r.groups,r.items,u,t)})}),we.jsx("div",{ref:o,className:`tw:sticky tw:top-0 tw:box-border tw:flex tw:h-14 tw:flex-row tw:items-center tw:justify-between tw:gap-2 tw:overflow-clip tw:px-4 tw:py-2 tw:text-foreground tw:@container/toolbar ${r}`,id:t,children:a}));function wc({onSelectProjectMenuItem:t,onSelectViewInfoMenuItem:r,projectMenuData:a,tabViewMenuData:o,id:i,className:s,startAreaChildren:c,centerAreaChildren:d,endAreaChildren:u,menuButtonIcon:w}){return e.jsxs(Io,{className:`tw:w-full tw:border ${s}`,id:i,children:[a&&e.jsx(tr,{onSelectMenuItem:t,menuData:a,tabLabel:"Project",icon:w??e.jsx(R.Menu,{}),buttonVariant:"ghost"}),c&&e.jsx("div",{className:"tw:flex tw:h-full tw:shrink tw:grow-[10] tw:flex-row tw:flex-wrap tw:items-start tw:gap-x-1 tw:gap-y-2 tw:overflow-clip",children:c}),d&&e.jsx("div",{className:"tw:flex tw:h-full tw:shrink tw:grow-[1] tw:basis-0 tw:flex-row tw:flex-wrap tw:items-start tw:justify-center tw:gap-x-1 tw:gap-y-2 tw:overflow-clip tw:@sm:basis-auto",children:d}),e.jsxs("div",{className:"tw:flex tw:h-full tw:shrink tw:grow-[1] tw:flex-row-reverse tw:flex-wrap tw:items-start tw:gap-x-1 tw:gap-y-2 tw:overflow-clip",children:[o&&e.jsx(tr,{onSelectMenuItem:r,menuData:o,tabLabel:"View Info",icon:e.jsx(R.EllipsisVertical,{}),className:"tw:h-full"}),u]})]})}function uc({onSelectProjectMenuItem:t,projectMenuData:r,id:a,className:o,menuButtonIcon:i}){return e.jsx(Io,{className:"tw:pointer-events-none",id:a,children:r&&e.jsx(tr,{onSelectMenuItem:t,menuData:r,tabLabel:"Project",icon:i,className:`tw:pointer-events-auto tw:shadow-lg ${o}`,buttonVariant:"outline"})})}const Br=l.forwardRef(({className:t,...r},a)=>{const o=n.readDirection();return e.jsx(D.Tabs.Root,{orientation:"vertical",ref:a,className:n.cn("tw:flex tw:gap-1 tw:rounded-md tw:text-muted-foreground",t),...r,dir:o})});Br.displayName=D.Tabs.List.displayName;const Pr=l.forwardRef(({className:t,...r},a)=>e.jsx(D.Tabs.List,{ref:a,className:n.cn("tw:flex tw:items-center tw:w-[124px] tw:justify-center tw:rounded-md tw:bg-muted tw:p-1 tw:text-muted-foreground",t),...r}));Pr.displayName=D.Tabs.List.displayName;const Ao=l.forwardRef(({className:t,...r},a)=>e.jsx(D.Tabs.Trigger,{ref:a,...r,className:n.cn("tw:inline-flex tw:w-[116px] tw:cursor-pointer tw:items-center tw:justify-center tw:break-words tw:rounded-sm tw:border-0 tw:bg-muted tw:px-3 tw:py-1.5 tw:text-sm tw:font-medium tw:text-inherit tw:ring-offset-background tw:transition-all tw:hover:text-foreground tw:focus-visible:outline-hidden tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:focus-visible:ring-offset-2 tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:data-[state=active]:bg-background tw:data-[state=active]:text-foreground tw:data-[state=active]:shadow-sm tw:overflow-clip",t)})),Lr=l.forwardRef(({className:t,...r},a)=>e.jsx(D.Tabs.Content,{ref:a,className:n.cn("tw:ms-5 tw:flex-grow tw:text-foreground tw:ring-offset-background tw:focus-visible:outline-hidden tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:focus-visible:ring-offset-2",t),...r}));Lr.displayName=D.Tabs.Content.displayName;function pc({tabList:t,searchValue:r,onSearch:a,searchPlaceholder:o,headerTitle:i,searchClassName:s,id:c}){return e.jsxs("div",{id:c,className:"pr-twp",children:[e.jsxs("div",{className:"tw:sticky tw:top-0 tw:space-y-2 tw:pb-2",children:[i?e.jsx("h1",{children:i}):"",e.jsx(n.SearchBar,{className:s,value:r,onSearch:a,placeholder:o})]}),e.jsxs(Br,{children:[e.jsx(Pr,{children:t.map(d=>e.jsx(Ao,{value:d.value,children:d.value},d.key))}),t.map(d=>e.jsx(Lr,{value:d.value,children:d.content},d.key))]})]})}function gc({className:t,variant:r="default",...a}){const o=l.useMemo(()=>({variant:r}),[r]);return e.jsx(n.MenuContext.Provider,{value:o,children:e.jsx(D.Menubar.Root,{"data-slot":"menubar",className:n.cn("tw:flex tw:h-8 tw:items-center tw:gap-0.5 tw:rounded-lg tw:border tw:p-[3px]",t),...a})})}function hc({...t}){return e.jsx(D.Menubar.Menu,{"data-slot":"menubar-menu",...t})}function fc({...t}){return e.jsx(D.Menubar.Portal,{"data-slot":"menubar-portal",...t})}function mc({className:t,...r}){const a=n.useMenuContext();return e.jsx(D.Menubar.Trigger,{"data-slot":"menubar-trigger",className:n.cn("tw:flex tw:items-center tw:rounded-sm tw:px-1.5 tw:py-[2px] tw:text-sm tw:font-medium tw:outline-hidden tw:select-none tw:hover:bg-muted tw:aria-expanded:bg-muted","pr-twp",n.menuVariants({variant:a.variant,className:t})),...r})}function vc({className:t,align:r="start",alignOffset:a=-4,sideOffset:o=8,...i}){const s=n.useMenuContext();return e.jsx(fc,{children:e.jsx(D.Menubar.Content,{"data-slot":"menubar-content",align:r,alignOffset:a,sideOffset:o,className:n.cn("tw:z-50 tw:min-w-36 tw:origin-(--radix-menubar-content-transform-origin) tw:overflow-hidden tw:rounded-lg tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-md tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150","pr-twp",{"tw:bg-popover":s.variant==="muted"},t),...i})})}function bc({className:t,inset:r,variant:a="default",...o}){const i=n.useMenuContext();return e.jsx(D.Menubar.Item,{"data-slot":"menubar-item","data-inset":r,"data-variant":a,className:n.cn("tw:group/menubar-item tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:not-data-[variant=destructive]:focus:**:text-accent-foreground tw:data-inset:ps-7 tw:data-[variant=destructive]:text-destructive tw:data-[variant=destructive]:focus:bg-destructive/10 tw:data-[variant=destructive]:focus:text-destructive tw:dark:data-[variant=destructive]:focus:bg-destructive/20 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4 tw:data-[variant=destructive]:*:[svg]:text-destructive!",n.menuVariants({variant:i.variant,className:t})),...o})}function xc({className:t,...r}){return e.jsx(D.Menubar.Separator,{"data-slot":"menubar-separator",className:n.cn("tw:-mx-1 tw:my-1 tw:h-px tw:bg-border",t),...r})}function kc({...t}){return e.jsx(D.Menubar.Sub,{"data-slot":"menubar-sub",...t})}function yc({className:t,inset:r,children:a,...o}){const i=n.useMenuContext();return e.jsxs(D.Menubar.SubTrigger,{"data-slot":"menubar-sub-trigger","data-inset":r,className:n.cn("tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-none tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-open:bg-accent tw:data-open:text-accent-foreground tw:[&_svg:not([class*=size-])]:size-4",n.menuVariants({variant:i.variant,className:t})),...o,children:[a,e.jsx(Tt.IconChevronRight,{className:"tw:ms-auto tw:size-4"})]})}function _c({className:t,...r}){const a=n.useMenuContext();return e.jsx(D.Menubar.SubContent,{"data-slot":"menubar-sub-content",className:n.cn("tw:z-50 tw:min-w-32 tw:origin-(--radix-menubar-content-transform-origin) tw:overflow-hidden tw:rounded-lg tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-lg tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",{"tw:bg-popover":a.variant==="muted"},t),...r})}const Se=(t,r)=>{setTimeout(()=>{r.forEach(a=>{var o;(o=t.current)==null||o.dispatchEvent(new KeyboardEvent("keydown",a))})},0)},$o=(t,r,a,o)=>{if(!a)return;const i=Object.entries(t).filter(([s,c])=>"column"in c&&c.column===a||s===a).sort(([,s],[,c])=>s.order-c.order);return i.flatMap(([s],c)=>{const d=r.filter(w=>w.group===s).sort((w,p)=>w.order-p.order).map(w=>e.jsxs(n.Tooltip,{children:[e.jsx(n.TooltipTrigger,{asChild:!0,children:"command"in w?e.jsxs(bc,{onClick:()=>{o(w)},children:[w.iconPathBefore&&e.jsx(Qe,{icon:w.iconPathBefore,menuLabel:w.label,leading:!0}),w.label,w.iconPathAfter&&e.jsx(Qe,{icon:w.iconPathAfter,menuLabel:w.label})]},`menubar-item-${w.label}-${w.command}`):e.jsxs(kc,{children:[e.jsx(yc,{children:w.label}),e.jsx(_c,{children:$o(t,r,Oo(t,w.id),o)})]},`menubar-sub-${w.label}-${w.id}`)}),w.tooltip&&e.jsx(n.TooltipContent,{children:w.tooltip})]},`tooltip-${w.label}-${"command"in w?w.command:w.id}`)),u=[...d];return d.length>0&&c{switch(p){case"platform.app":return s;case"platform.window":return c;case"platform.layout":return d;case"platform.help":return u;default:return}};if(Zo.useHotkeys(["alt","alt+p","alt+l","alt+n","alt+h"],(p,g)=>{var m,k,b,C;p.preventDefault();const f={key:"Escape",code:"Escape",keyCode:27,bubbles:!0},h={key:" ",code:"Space",keyCode:32,bubbles:!0};switch(g.hotkey){case"alt":Se(s,[f]);break;case"alt+p":(m=s.current)==null||m.focus(),Se(s,[f,h]);break;case"alt+l":(k=c.current)==null||k.focus(),Se(c,[f,h]);break;case"alt+n":(b=d.current)==null||b.focus(),Se(d,[f,h]);break;case"alt+h":(C=u.current)==null||C.focus(),Se(u,[f,h]);break}}),l.useEffect(()=>{if(!a||!i.current)return;const p=new MutationObserver(h=>{h.forEach(m=>{if(m.attributeName==="data-state"&&m.target instanceof HTMLElement){const k=m.target.getAttribute("data-state");a(k==="open")}})});return i.current.querySelectorAll("[data-state]").forEach(h=>{p.observe(h,{attributes:!0})}),()=>p.disconnect()},[a]),!!t)return e.jsx(gc,{ref:i,className:"pr-twp tw:border-0 tw:bg-transparent",variant:o,children:Object.entries(t.columns).filter(([,p])=>typeof p=="object").sort(([,p],[,g])=>typeof p=="boolean"||typeof g=="boolean"?0:p.order-g.order).map(([p,g])=>e.jsxs(hc,{children:[e.jsx(mc,{ref:w(p),children:typeof g=="object"&&"label"in g&&g.label}),e.jsx(vc,{style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:e.jsx(n.TooltipProvider,{children:$o(t.groups,t.items,p,r)})})]},p))})}function Cc(t){switch(t){case void 0:return;case"darwin":return"tw:ps-[85px]";default:return"tw:pe-[calc(138px+1rem)]"}}function Nc({menuData:t,onOpenChange:r,onSelectMenuItem:a,className:o,id:i,children:s,appMenuAreaChildren:c,configAreaChildren:d,shouldUseAsAppDragArea:u,menubarVariant:w="default"}){const p=l.useRef(void 0);return e.jsx("div",{className:n.cn("tw:border tw:px-4 tw:text-foreground",o),ref:p,style:{position:"relative"},id:i,children:e.jsxs("div",{className:"tw:flex tw:h-full tw:w-full tw:justify-between tw:overflow-hidden",style:u?{WebkitAppRegion:"drag"}:void 0,children:[e.jsx("div",{className:"tw:flex tw:grow tw:basis-0",children:e.jsxs("div",{className:"tw:flex tw:items-center tw:gap-2",style:u?{WebkitAppRegion:"no-drag"}:void 0,children:[c,t&&e.jsx(jc,{menuData:t,onOpenChange:r,onSelectMenuItem:a,variant:w})]})}),e.jsx("div",{className:"tw:flex tw:items-center tw:gap-2 tw:px-2",style:u?{WebkitAppRegion:"no-drag"}:void 0,children:s}),e.jsx("div",{className:"tw:flex tw:min-w-0 tw:grow tw:basis-0 tw:justify-end",children:e.jsx("div",{className:"tw:flex tw:min-w-0 tw:items-center tw:gap-2 tw:pe-1",style:u?{WebkitAppRegion:"no-drag"}:void 0,children:d})})]})})}const Ec=(t,r)=>t[r]??r;function Sc({knownUiLanguages:t,primaryLanguage:r="en",fallbackLanguages:a=[],onLanguagesChange:o,onPrimaryLanguageChange:i,onFallbackLanguagesChange:s,localizedStrings:c,className:d,id:u}){const w=Ec(c,"%settings_uiLanguageSelector_fallbackLanguages%"),[p,g]=l.useState(!1),f=m=>{i&&i(m),o&&o([m,...a.filter(k=>k!==m)]),s&&a.find(k=>k===m)&&s([...a.filter(k=>k!==m)]),g(!1)},h=(m,k)=>{var C,y,_,B,F,E;const b=k!==m?((y=(C=t[m])==null?void 0:C.uiNames)==null?void 0:y[k])??((B=(_=t[m])==null?void 0:_.uiNames)==null?void 0:B.en):void 0;return b?`${(F=t[m])==null?void 0:F.autonym} (${b})`:(E=t[m])==null?void 0:E.autonym};return e.jsxs("div",{id:u,className:n.cn("pr-twp tw:max-w-sm",d),children:[e.jsxs(ue,{name:"uiLanguage",value:r,onValueChange:f,open:p,onOpenChange:m=>g(m),children:[e.jsx(ge,{children:e.jsx(pe,{})}),e.jsx(he,{style:{zIndex:n.Z_INDEX_ABOVE_DOCK},children:Object.keys(t).map(m=>e.jsx(Ut,{value:m,children:h(m,r)},m))})]}),r!=="en"&&e.jsx("div",{className:"tw:pt-3",children:e.jsx(n.Label,{className:"tw:font-normal tw:text-muted-foreground",children:M.formatReplacementString(w,{fallbackLanguages:(a==null?void 0:a.length)>0?a.map(m=>h(m,r)).join(", "):t.en.autonym})})})]})}function Tc({item:t,createLabel:r,createComplexLabel:a}){return r?e.jsx(n.Label,{children:r(t)}):a?e.jsx(n.Label,{children:a(t)}):e.jsx(n.Label,{children:t})}function Bo({id:t,className:r,listItems:a,selectedListItems:o,handleSelectListItem:i,createLabel:s,createComplexLabel:c}){return e.jsx("div",{id:t,className:r,children:a.map(d=>e.jsxs("div",{className:"tw:m-2 tw:flex tw:items-center",children:[e.jsx(Ar,{className:"tw:me-2 tw:align-middle",checked:o.includes(d),onCheckedChange:u=>i(d,u)}),e.jsx(Tc,{item:d,createLabel:s,createComplexLabel:c})]},d))})}const Mc=Bo;function Rc({cardKey:t,isSelected:r,onSelect:a,isDenied:o,isHidden:i=!1,className:s,children:c,selectedButtons:d,hoverButtons:u,dropdownContent:w,additionalContent:p,accentColor:g,showDropdownOnHover:f=!1}){const h=m=>{(m.key==="Enter"||m.key===" ")&&(m.preventDefault(),a())};return e.jsxs("div",{hidden:i,onClick:a,onKeyDown:h,role:"button",tabIndex:0,"aria-pressed":r,className:n.cn("tw:group tw:relative tw:min-w-36 tw:rounded-xl tw:border tw:shadow-none tw:hover:bg-muted/50",{"tw:opacity-50 tw:hover:opacity-100":o&&!r},{"tw:bg-accent":r},{"tw:bg-transparent":!r},s),children:[e.jsxs("div",{className:"tw:flex tw:flex-col tw:gap-2 tw:p-4",children:[e.jsxs("div",{className:"tw:flex tw:justify-between tw:overflow-hidden",children:[e.jsx("div",{className:"tw:min-w-0 tw:flex-1",children:c}),r&&d,!r&&u&&e.jsx("div",{className:"tw:invisible tw:group-hover:visible",children:u}),!r&&f&&w&&e.jsx("div",{className:"tw:invisible tw:group-hover:visible",children:e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{className:n.cn(g&&"tw:me-1"),asChild:!0,children:e.jsx(n.Button,{className:"tw:m-1 tw:h-6 tw:w-6",variant:"ghost",size:"icon",children:e.jsx(R.MoreVertical,{})})}),e.jsx(n.DropdownMenuContent,{align:"end",children:w})]})}),r&&w&&e.jsxs(n.DropdownMenu,{children:[e.jsx(n.DropdownMenuTrigger,{className:n.cn(g&&"tw:me-1"),asChild:!0,children:e.jsx(n.Button,{className:"tw:m-1 tw:h-6 tw:w-6",variant:"ghost",size:"icon",children:e.jsx(R.MoreVertical,{})})}),e.jsx(n.DropdownMenuContent,{align:"end",children:w})]})]}),p&&e.jsx("div",{className:"tw:w-fit tw:min-w-0 tw:max-w-full tw:overflow-hidden",children:p})]}),g&&e.jsx("div",{className:`tw:absolute tw:right-0 tw:top-0 tw:h-full tw:w-2 tw:rounded-r-xl ${g}`})]},t)}function Dc({message:t,id:r,className:a}){return e.jsx("p",{role:"status","data-testid":r,className:n.cn("tw:text-sm tw:text-muted-foreground",a),children:t})}function Oc({id:t,isDisabled:r=!1,hasError:a=!1,isFullWidth:o=!1,helperText:i,label:s,placeholder:c,isRequired:d=!1,className:u,defaultValue:w,value:p,onChange:g,onFocus:f,onBlur:h}){return e.jsxs("div",{className:n.cn("tw:inline-grid tw:items-center tw:gap-1.5",{"tw:w-full":o}),children:[e.jsx(n.Label,{htmlFor:t,className:n.cn({"tw:text-red-600":a,"tw:hidden":!s}),children:`${s}${d?"*":""}`}),e.jsx(n.Input,{id:t,disabled:r,placeholder:c,required:d,className:n.cn(u,{"tw:border-red-600":a}),defaultValue:w,value:p,onChange:g,onFocus:f,onBlur:h}),e.jsx("p",{className:n.cn({"tw:hidden":!i}),children:i})]})}const zc=er.cva("tw:group/alert tw:relative tw:grid tw:w-full tw:gap-0.5 tw:rounded-lg tw:border tw:px-2.5 tw:py-2 tw:text-start tw:text-sm tw:has-data-[slot=alert-action]:relative tw:has-data-[slot=alert-action]:pe-18 tw:has-[>svg]:grid-cols-[auto_1fr] tw:has-[>svg]:gap-x-2 tw:*:[svg]:row-span-2 tw:*:[svg]:translate-y-0.5 tw:*:[svg]:text-current tw:*:[svg:not([class*=size-])]:size-4 tw:has-[>img]:grid-cols-[auto_1fr] tw:has-[>img]:gap-x-2 tw:*:[img]:row-span-2 tw:*:[img]:translate-y-0.5 tw:*:[img]:text-current tw:*:[img:not([class*=size-])]:size-4",{variants:{variant:{default:"tw:bg-card tw:text-card-foreground",destructive:"tw:bg-card tw:text-destructive tw:*:data-[slot=alert-description]:text-destructive/90 tw:*:[svg]:text-current tw:*:[img]:text-current"}},defaultVariants:{variant:"default"}});function Ic({className:t,variant:r,...a}){return e.jsx("div",{"data-slot":"alert",role:"alert",className:n.cn("pr-twp",zc({variant:r}),t),...a})}function Ac({className:t,...r}){return e.jsx("div",{"data-slot":"alert-title",className:n.cn("tw:font-medium tw:group-has-[>svg]/alert:col-start-2 tw:[&_a]:underline tw:[&_a]:underline-offset-3 tw:[&_a]:hover:text-foreground",t),...r})}function $c({className:t,...r}){return e.jsx("div",{"data-slot":"alert-description",className:n.cn("tw:text-sm tw:text-balance tw:text-muted-foreground tw:md:text-pretty tw:[&_a]:underline tw:[&_a]:underline-offset-3 tw:[&_a]:hover:text-foreground tw:[&_p:not(:last-child)]:mb-4",t),...r})}function Bc({...t}){return e.jsx(D.ContextMenu.Root,{"data-slot":"context-menu",...t})}function Pc({className:t,...r}){return e.jsx(D.ContextMenu.Trigger,{"data-slot":"context-menu-trigger",className:n.cn("tw:select-none",t),...r})}function Lc({...t}){return e.jsx(D.ContextMenu.Group,{"data-slot":"context-menu-group",...t})}function Vc({...t}){return e.jsx(D.ContextMenu.Portal,{"data-slot":"context-menu-portal",...t})}function Fc({...t}){return e.jsx(D.ContextMenu.Sub,{"data-slot":"context-menu-sub",...t})}function Gc({...t}){return e.jsx(D.ContextMenu.RadioGroup,{"data-slot":"context-menu-radio-group",...t})}function Kc({className:t,style:r,...a}){return e.jsx(D.ContextMenu.Portal,{children:e.jsx(D.ContextMenu.Content,{"data-slot":"context-menu-content",className:n.cn("pr-twp tw:max-h-(--radix-context-menu-content-available-height) tw:min-w-36 tw:origin-(--radix-context-menu-content-transform-origin) tw:overflow-x-hidden tw:overflow-y-auto tw:rounded-lg tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-md tw:ring-1 tw:ring-foreground/10 tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",t),style:{zIndex:n.Z_INDEX_ABOVE_DOCK,...r},...a})})}function Uc({className:t,inset:r,variant:a="default",...o}){return e.jsx(D.ContextMenu.Item,{"data-slot":"context-menu-item","data-inset":r,"data-variant":a,className:n.cn("pr-twp tw:group/context-menu-item tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-[variant=destructive]:text-destructive tw:data-[variant=destructive]:focus:bg-destructive/10 tw:data-[variant=destructive]:focus:text-destructive tw:dark:data-[variant=destructive]:focus:bg-destructive/20 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4 tw:focus:*:[svg]:text-accent-foreground tw:data-[variant=destructive]:*:[svg]:text-destructive",t),...o})}function qc({className:t,inset:r,children:a,...o}){return e.jsxs(D.ContextMenu.SubTrigger,{"data-slot":"context-menu-sub-trigger","data-inset":r,className:n.cn("pr-twp tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:px-1.5 tw:py-1 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-open:bg-accent tw:data-open:text-accent-foreground tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),...o,children:[a,e.jsx(Tt.IconChevronRight,{className:"tw:ms-auto"})]})}function Hc({className:t,style:r,...a}){return e.jsx(D.ContextMenu.SubContent,{"data-slot":"context-menu-sub-content",className:n.cn("pr-twp tw:min-w-32 tw:origin-(--radix-context-menu-content-transform-origin) tw:overflow-hidden tw:rounded-lg tw:border tw:bg-popover tw:p-1 tw:text-popover-foreground tw:shadow-lg tw:duration-100 tw:data-[side=bottom]:slide-in-from-top-2 tw:data-[side=left]:slide-in-from-right-2 tw:data-[side=right]:slide-in-from-left-2 tw:data-[side=top]:slide-in-from-bottom-2 tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-open:zoom-in-95 tw:data-closed:animate-out tw:data-closed:fade-out-0 tw:data-closed:zoom-out-95 tw:animate-none! tw:bg-popover/70 tw:before:-z-1 tw:**:data-[slot$=-item]:focus:bg-foreground/10 tw:**:data-[slot$=-item]:data-highlighted:bg-foreground/10 tw:**:data-[slot$=-separator]:bg-foreground/5 tw:**:data-[slot$=-trigger]:focus:bg-foreground/10 tw:**:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! tw:**:data-[variant=destructive]:focus:bg-foreground/10! tw:**:data-[variant=destructive]:text-accent-foreground! tw:**:data-[variant=destructive]:**:text-accent-foreground! tw:relative tw:before:pointer-events-none tw:before:absolute tw:before:inset-0 tw:before:rounded-[inherit] tw:before:backdrop-blur-2xl tw:before:backdrop-saturate-150",t),style:{zIndex:n.Z_INDEX_ABOVE_DOCK,...r},...a})}function Yc({className:t,children:r,checked:a,inset:o,...i}){return e.jsxs(D.ContextMenu.CheckboxItem,{"data-slot":"context-menu-checkbox-item","data-inset":o,className:n.cn("pr-twp tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:py-1 tw:pe-8 tw:ps-1.5 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),checked:a,...i,children:[e.jsx("span",{className:"tw:pointer-events-none tw:absolute tw:end-2",children:e.jsx(D.ContextMenu.ItemIndicator,{children:e.jsx(Tt.IconCheck,{})})}),r]})}function Xc({className:t,children:r,inset:a,...o}){return e.jsxs(D.ContextMenu.RadioItem,{"data-slot":"context-menu-radio-item","data-inset":a,className:n.cn("pr-twp tw:relative tw:flex tw:cursor-default tw:items-center tw:gap-1.5 tw:rounded-md tw:py-1 tw:pe-8 tw:ps-1.5 tw:text-sm tw:outline-hidden tw:select-none tw:focus:bg-accent tw:focus:text-accent-foreground tw:data-inset:ps-7 tw:data-disabled:pointer-events-none tw:data-disabled:opacity-50 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4",t),...o,children:[e.jsx("span",{className:"tw:pointer-events-none tw:absolute tw:end-2",children:e.jsx(D.ContextMenu.ItemIndicator,{children:e.jsx(Tt.IconCheck,{})})}),r]})}function Zc({className:t,inset:r,...a}){return e.jsx(D.ContextMenu.Label,{"data-slot":"context-menu-label","data-inset":r,className:n.cn("pr-twp tw:px-1.5 tw:py-1 tw:text-xs tw:font-medium tw:text-muted-foreground tw:data-inset:ps-7",t),...a})}function Wc({className:t,...r}){return e.jsx(D.ContextMenu.Separator,{"data-slot":"context-menu-separator",className:n.cn("pr-twp tw:-mx-1 tw:my-1 tw:h-px tw:bg-border",t),...r})}function Jc({className:t,...r}){return e.jsx("span",{"data-slot":"context-menu-shortcut",className:n.cn("pr-twp tw:ms-auto tw:text-xs tw:tracking-widest tw:text-muted-foreground tw:group-focus/context-menu-item:text-accent-foreground",t),...r})}function Qc({...t}){return e.jsx(se.Drawer.Root,{"data-slot":"drawer",...t})}function tl({...t}){return e.jsx(se.Drawer.Trigger,{"data-slot":"drawer-trigger",...t})}function Po({...t}){return e.jsx(se.Drawer.Portal,{"data-slot":"drawer-portal",...t})}function el({...t}){return e.jsx(se.Drawer.Close,{"data-slot":"drawer-close",...t})}function Lo({className:t,...r}){return e.jsx(se.Drawer.Overlay,{"data-slot":"drawer-overlay",className:n.cn("pr-twp tw:fixed tw:inset-0 tw:z-50 tw:bg-black/10 tw:supports-backdrop-filter:backdrop-blur-xs tw:data-open:animate-in tw:data-open:fade-in-0 tw:data-closed:animate-out tw:data-closed:fade-out-0",t),...r})}function rl({className:t,children:r,hideDrawerHandle:a=!1,...o}){const i=n.readDirection();return e.jsxs(Po,{"data-slot":"drawer-portal",children:[e.jsx(Lo,{}),e.jsxs(se.Drawer.Content,{"data-slot":"drawer-content",className:n.cn("pr-twp tw:group/drawer-content tw:fixed tw:z-50 tw:flex tw:h-auto tw:flex-col tw:bg-popover tw:text-sm tw:text-popover-foreground tw:data-[vaul-drawer-direction=bottom]:inset-x-0 tw:data-[vaul-drawer-direction=bottom]:bottom-0 tw:data-[vaul-drawer-direction=bottom]:mt-24 tw:data-[vaul-drawer-direction=bottom]:max-h-[80vh] tw:data-[vaul-drawer-direction=bottom]:rounded-t-xl tw:data-[vaul-drawer-direction=bottom]:border-t tw:data-[vaul-drawer-direction=left]:inset-y-0 tw:data-[vaul-drawer-direction=left]:left-0 tw:data-[vaul-drawer-direction=left]:w-3/4 tw:data-[vaul-drawer-direction=left]:rounded-r-xl tw:data-[vaul-drawer-direction=left]:border-r tw:data-[vaul-drawer-direction=left]:flex-row tw:data-[vaul-drawer-direction=right]:inset-y-0 tw:data-[vaul-drawer-direction=right]:right-0 tw:data-[vaul-drawer-direction=right]:w-3/4 tw:data-[vaul-drawer-direction=right]:rounded-l-xl tw:data-[vaul-drawer-direction=right]:border-l tw:data-[vaul-drawer-direction=right]:flex-row tw:data-[vaul-drawer-direction=top]:inset-x-0 tw:data-[vaul-drawer-direction=top]:top-0 tw:data-[vaul-drawer-direction=top]:mb-24 tw:data-[vaul-drawer-direction=top]:max-h-[80vh] tw:data-[vaul-drawer-direction=top]:rounded-b-xl tw:data-[vaul-drawer-direction=top]:border-b tw:data-[vaul-drawer-direction=left]:sm:max-w-sm tw:data-[vaul-drawer-direction=right]:sm:max-w-sm",t),dir:"ltr",...o,children:[!a&&e.jsx("div",{className:"tw:hidden tw:shrink-0 tw:rounded-full tw:bg-muted tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:mx-auto tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:mt-4 tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:h-1.5 tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:w-[100px] tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:block tw:group-data-[vaul-drawer-direction=right]/drawer-content:my-auto tw:group-data-[vaul-drawer-direction=right]/drawer-content:ms-4 tw:group-data-[vaul-drawer-direction=right]/drawer-content:h-[100px] tw:group-data-[vaul-drawer-direction=right]/drawer-content:w-1.5 tw:group-data-[vaul-drawer-direction=right]/drawer-content:block"}),e.jsx("div",{className:"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col",dir:i,children:r}),!a&&e.jsx("div",{className:"tw:hidden tw:shrink-0 tw:rounded-full tw:bg-muted tw:group-data-[vaul-drawer-direction=top]/drawer-content:mx-auto tw:group-data-[vaul-drawer-direction=top]/drawer-content:mb-4 tw:group-data-[vaul-drawer-direction=top]/drawer-content:h-1.5 tw:group-data-[vaul-drawer-direction=top]/drawer-content:w-[100px] tw:group-data-[vaul-drawer-direction=top]/drawer-content:block tw:group-data-[vaul-drawer-direction=left]/drawer-content:my-auto tw:group-data-[vaul-drawer-direction=left]/drawer-content:me-4 tw:group-data-[vaul-drawer-direction=left]/drawer-content:h-[100px] tw:group-data-[vaul-drawer-direction=left]/drawer-content:w-1.5 tw:group-data-[vaul-drawer-direction=left]/drawer-content:block"})]})]})}function al({className:t,...r}){return e.jsx("div",{"data-slot":"drawer-header",className:n.cn("pr-twp tw:flex tw:flex-col tw:gap-0.5 tw:p-4 tw:group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center tw:group-data-[vaul-drawer-direction=top]/drawer-content:text-center tw:md:gap-0.5 tw:md:text-start",t),...r})}function ol({className:t,...r}){return e.jsx("div",{"data-slot":"drawer-footer",className:n.cn("pr-twp tw:mt-auto tw:flex tw:flex-col tw:gap-2 tw:p-4",t),...r})}function nl({className:t,...r}){return e.jsx(se.Drawer.Title,{"data-slot":"drawer-title",className:n.cn("pr-twp tw:font-heading tw:text-base tw:font-medium tw:text-foreground",t),...r})}function il({className:t,...r}){return e.jsx(se.Drawer.Description,{"data-slot":"drawer-description",className:n.cn("pr-twp tw:text-sm tw:text-muted-foreground",t),...r})}function sl({className:t,value:r,...a}){return e.jsx(D.Progress.Root,{"data-slot":"progress",className:n.cn("pr-twp tw:relative tw:flex tw:h-1 tw:w-full tw:items-center tw:overflow-x-hidden tw:rounded-full tw:bg-muted",t),...a,children:e.jsx(D.Progress.Indicator,{"data-slot":"progress-indicator",className:"tw:size-full tw:flex-1 tw:bg-primary tw:transition-all",style:{transform:`translateX(-${100-(r||0)}%)`}})})}function cl({...t}){const{theme:r="system"}=Wo.useTheme(),a=r==="light"||r==="dark"||r==="system"?r:"system",o={"--normal-bg":"var(--popover)","--normal-text":"var(--popover-foreground)","--normal-border":"var(--border)","--border-radius":"var(--radius)"};return e.jsx(ma.Toaster,{theme:a,className:"tw:toaster tw:group",icons:{success:e.jsx(Tt.IconCircleCheck,{className:"tw:size-4"}),info:e.jsx(Tt.IconInfoCircle,{className:"tw:size-4"}),warning:e.jsx(Tt.IconAlertTriangle,{className:"tw:size-4"}),error:e.jsx(Tt.IconAlertOctagon,{className:"tw:size-4"}),loading:e.jsx(Tt.IconLoader,{className:"tw:size-4 tw:animate-spin"})},style:o,toastOptions:{classNames:{toast:"cn-toast"}},...t})}function ll({className:t,defaultValue:r,value:a,min:o=0,max:i=100,...s}){const c=n.readDirection(),d=l.useMemo(()=>Array.isArray(a)?a:Array.isArray(r)?r:[o,i],[a,r,o,i]);return e.jsxs(D.Slider.Root,{"data-slot":"slider",defaultValue:r,value:a,min:o,max:i,className:n.cn("pr-twp tw:relative tw:flex tw:w-full tw:touch-none tw:items-center tw:select-none tw:data-disabled:opacity-50 tw:data-vertical:h-full tw:data-vertical:min-h-40 tw:data-vertical:w-auto tw:data-vertical:flex-col",t),dir:c,...s,children:[e.jsx(D.Slider.Track,{"data-slot":"slider-track",className:"tw:relative tw:grow tw:overflow-hidden tw:rounded-full tw:bg-muted tw:data-horizontal:h-1 tw:data-horizontal:w-full tw:data-vertical:h-full tw:data-vertical:w-1",children:e.jsx(D.Slider.Range,{"data-slot":"slider-range",className:"tw:absolute tw:bg-primary tw:select-none tw:data-horizontal:h-full tw:data-vertical:w-full"})}),Array.from({length:d.length},(u,w)=>e.jsx(D.Slider.Thumb,{"data-slot":"slider-thumb",className:"tw:relative tw:block tw:size-3 tw:shrink-0 tw:rounded-full tw:border tw:border-ring tw:bg-white tw:ring-ring/50 tw:transition-[color,box-shadow] tw:select-none tw:after:absolute tw:after:-inset-2 tw:hover:ring-3 tw:focus-visible:ring-3 tw:focus-visible:outline-hidden tw:active:ring-3 tw:disabled:pointer-events-none tw:disabled:opacity-50"},w))]})}function dl({className:t,size:r="default",...a}){return e.jsx(D.Switch.Root,{"data-slot":"switch","data-size":r,className:n.cn("tw:peer pr-twp tw:group/switch tw:relative tw:inline-flex tw:shrink-0 tw:items-center tw:rounded-full tw:border tw:border-transparent tw:transition-all tw:outline-none tw:after:absolute tw:after:-inset-x-3 tw:after:-inset-y-2 tw:focus-visible:border-ring tw:focus-visible:ring-3 tw:focus-visible:ring-ring/50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-3 tw:aria-invalid:ring-destructive/20 tw:data-[size=default]:h-[18.4px] tw:data-[size=default]:w-[32px] tw:data-[size=sm]:h-[14px] tw:data-[size=sm]:w-[24px] tw:dark:aria-invalid:border-destructive/50 tw:dark:aria-invalid:ring-destructive/40 tw:data-checked:bg-primary tw:data-unchecked:bg-input tw:dark:data-unchecked:bg-input/80 tw:data-disabled:cursor-not-allowed tw:data-disabled:opacity-50",t),...a,children:e.jsx(D.Switch.Thumb,{"data-slot":"switch-thumb",className:"tw:pointer-events-none tw:block tw:rounded-full tw:bg-background tw:ring-0 tw:transition-transform tw:group-data-[size=default]/switch:size-4 tw:group-data-[size=sm]/switch:size-3 tw:group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] tw:rtl:group-data-[size=default]/switch:data-checked:-translate-x-[calc(100%-2px)] tw:group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] tw:rtl:group-data-[size=sm]/switch:data-checked:-translate-x-[calc(100%-2px)] tw:dark:data-checked:bg-primary-foreground tw:group-data-[size=default]/switch:data-unchecked:translate-x-0 tw:rtl:group-data-[size=default]/switch:data-unchecked:-translate-x-0 tw:group-data-[size=sm]/switch:data-unchecked:translate-x-0 tw:rtl:group-data-[size=sm]/switch:data-unchecked:-translate-x-0 tw:dark:data-unchecked:bg-foreground"})})}function wl({className:t,orientation:r="horizontal",...a}){return e.jsx(D.Tabs.Root,{"data-slot":"tabs","data-orientation":r,className:n.cn("tw:group/tabs tw:flex tw:gap-2 tw:data-horizontal:flex-col",t),...a})}const ul=er.cva("tw:group/tabs-list tw:inline-flex tw:w-fit tw:items-center tw:justify-center tw:rounded-lg tw:p-[3px] tw:text-muted-foreground tw:group-data-horizontal/tabs:h-8 tw:group-data-vertical/tabs:h-fit tw:group-data-vertical/tabs:flex-col tw:data-[variant=line]:rounded-none",{variants:{variant:{default:"tw:bg-muted",line:"tw:gap-1 tw:bg-transparent"}},defaultVariants:{variant:"default"}});function pl({className:t,variant:r="default",...a}){const o=n.readDirection();return e.jsx(D.Tabs.List,{"data-slot":"tabs-list","data-variant":r,className:n.cn("pr-twp",ul({variant:r}),t),dir:o,...a})}function gl({className:t,...r}){return e.jsx(D.Tabs.Trigger,{"data-slot":"tabs-trigger",className:n.cn("pr-twp tw:relative tw:inline-flex tw:h-[calc(100%-1px)] tw:flex-1 tw:items-center tw:justify-center tw:gap-1.5 tw:rounded-md tw:border tw:border-transparent tw:px-1.5 tw:py-0.5 tw:text-sm tw:font-medium tw:whitespace-nowrap tw:text-foreground/60 tw:transition-all tw:group-data-vertical/tabs:w-full tw:group-data-vertical/tabs:justify-start tw:hover:text-foreground tw:focus-visible:border-ring tw:focus-visible:ring-[3px] tw:focus-visible:ring-ring/50 tw:focus-visible:outline-1 tw:focus-visible:outline-ring tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:has-data-[icon=inline-end]:pe-1 tw:has-data-[icon=inline-start]:ps-1 tw:dark:text-muted-foreground tw:dark:hover:text-foreground tw:group-data-[variant=default]/tabs-list:data-active:shadow-sm tw:group-data-[variant=line]/tabs-list:data-active:shadow-none tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4","tw:group-data-[variant=line]/tabs-list:bg-transparent tw:group-data-[variant=line]/tabs-list:data-active:bg-transparent tw:dark:group-data-[variant=line]/tabs-list:data-active:border-transparent tw:dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent","tw:data-active:bg-background tw:data-active:text-foreground tw:dark:data-active:border-input tw:dark:data-active:bg-input/30 tw:dark:data-active:text-foreground","tw:after:absolute tw:after:bg-foreground tw:after:opacity-0 tw:after:transition-opacity tw:group-data-horizontal/tabs:after:inset-x-0 tw:group-data-horizontal/tabs:after:bottom-[-5px] tw:group-data-horizontal/tabs:after:h-0.5 tw:group-data-vertical/tabs:after:inset-y-0 tw:group-data-vertical/tabs:after:-end-1 tw:group-data-vertical/tabs:after:w-0.5 tw:group-data-[variant=line]/tabs-list:data-active:after:opacity-100",t),...r})}function hl({className:t,...r}){return e.jsx(D.Tabs.Content,{"data-slot":"tabs-content",className:n.cn("pr-twp tw:flex-1 tw:text-sm tw:outline-none",t),...r})}const fl=(t,r)=>{l.useEffect(()=>{if(!t)return()=>{};const a=t(r);return()=>{a()}},[t,r])};function ml(t){return{preserveValue:!0,...t}}const Vo=(t,r,a={})=>{const o=l.useRef(r);o.current=r;const i=l.useRef(a);i.current=ml(i.current);const[s,c]=l.useState(()=>o.current),[d,u]=l.useState(!0);return l.useEffect(()=>{let w=!0;return u(!!t),(async()=>{if(t){const p=await t();w&&(c(()=>p),u(!1))}})(),()=>{w=!1,i.current.preserveValue||c(()=>o.current)}},[t]),[s,d]},hr=()=>!1,vl=(t,r)=>{const[a]=Vo(l.useCallback(async()=>{if(!t)return hr;const o=await Promise.resolve(t(r));return async()=>o()},[r,t]),hr,{preserveValue:!1});l.useEffect(()=>()=>{a!==hr&&a()},[a])};function bl(t){l.useEffect(()=>{let r;return t&&(r=document.createElement("style"),r.appendChild(document.createTextNode(t)),document.head.appendChild(r)),()=>{r&&document.head.removeChild(r)}},[t])}function xl(t){const r=l.useMemo(()=>M.collectUsjMarkers(t).slice().sort().join(" "),[t]);return l.useMemo(()=>r?r.split(" "):[],[r])}const kl=()=>{const[t,r]=l.useState(()=>document.body.getBoundingClientRect().height>0);return l.useEffect(()=>{const a=new IntersectionObserver(o=>{const i=o[o.length-1];i&&r(i.isIntersecting)});return a.observe(document.body),()=>{a.disconnect()}},[]),t};exports.Badge=n.Badge;exports.Button=n.Button;exports.ButtonGroup=n.ButtonGroup;exports.ButtonGroupSeparator=n.ButtonGroupSeparator;exports.ButtonGroupText=n.ButtonGroupText;exports.Command=n.Command;exports.CommandEmpty=n.CommandEmpty;exports.CommandGroup=n.CommandGroup;exports.CommandInput=n.CommandInput;exports.CommandItem=n.CommandItem;exports.CommandList=n.CommandList;exports.Dialog=n.Dialog;exports.DialogClose=n.DialogClose;exports.DialogContent=n.DialogContent;exports.DialogDescription=n.DialogDescription;exports.DialogFooter=n.DialogFooter;exports.DialogHeader=n.DialogHeader;exports.DialogOverlay=n.DialogOverlay;exports.DialogPortal=n.DialogPortal;exports.DialogTitle=n.DialogTitle;exports.DialogTrigger=n.DialogTrigger;exports.DropdownMenu=n.DropdownMenu;exports.DropdownMenuCheckboxItem=n.DropdownMenuCheckboxItem;exports.DropdownMenuContent=n.DropdownMenuContent;exports.DropdownMenuGroup=n.DropdownMenuGroup;exports.DropdownMenuItem=n.DropdownMenuItem;exports.DropdownMenuLabel=n.DropdownMenuLabel;exports.DropdownMenuPortal=n.DropdownMenuPortal;exports.DropdownMenuRadioGroup=n.DropdownMenuRadioGroup;exports.DropdownMenuRadioItem=n.DropdownMenuRadioItem;exports.DropdownMenuSeparator=n.DropdownMenuSeparator;exports.DropdownMenuShortcut=n.DropdownMenuShortcut;exports.DropdownMenuSub=n.DropdownMenuSub;exports.DropdownMenuSubContent=n.DropdownMenuSubContent;exports.DropdownMenuSubTrigger=n.DropdownMenuSubTrigger;exports.DropdownMenuTrigger=n.DropdownMenuTrigger;exports.Input=n.Input;exports.Kbd=n.Kbd;exports.KbdGroup=n.KbdGroup;exports.Label=n.Label;exports.MultiSelectComboBox=n.MultiSelectComboBox;exports.Popover=n.Popover;exports.PopoverAnchor=n.PopoverAnchor;exports.PopoverContent=n.PopoverContent;exports.PopoverDescription=n.PopoverDescription;exports.PopoverHeader=n.PopoverHeader;exports.PopoverPortalContainerProvider=n.PopoverPortalContainerProvider;exports.PopoverTitle=n.PopoverTitle;exports.PopoverTrigger=n.PopoverTrigger;exports.ResizableHandle=n.ResizableHandle;exports.ResizablePanel=n.ResizablePanel;exports.ResizablePanelGroup=n.ResizablePanelGroup;exports.SearchBar=n.SearchBar;exports.Separator=n.Separator;exports.Skeleton=n.Skeleton;exports.Spinner=n.Spinner;exports.Table=n.Table;exports.TableBody=n.TableBody;exports.TableCaption=n.TableCaption;exports.TableCell=n.TableCell;exports.TableFooter=n.TableFooter;exports.TableHead=n.TableHead;exports.TableHeader=n.TableHeader;exports.TableRow=n.TableRow;exports.Tooltip=n.Tooltip;exports.TooltipContent=n.TooltipContent;exports.TooltipProvider=n.TooltipProvider;exports.TooltipTrigger=n.TooltipTrigger;exports.Z_INDEX_ABOVE_DOCK=n.Z_INDEX_ABOVE_DOCK;exports.Z_INDEX_FOOTNOTE_EDITOR=n.Z_INDEX_FOOTNOTE_EDITOR;exports.Z_INDEX_MODAL=n.Z_INDEX_MODAL;exports.Z_INDEX_MODAL_BACKDROP=n.Z_INDEX_MODAL_BACKDROP;exports.Z_INDEX_OVERLAY=n.Z_INDEX_OVERLAY;exports.badgeVariants=n.badgeVariants;exports.buttonGroupVariants=n.buttonGroupVariants;exports.buttonVariants=n.buttonVariants;exports.cn=n.cn;exports.isMacOs=n.isMacOs;exports.isWindows=n.isWindows;exports.useListbox=n.useListbox;exports.useTruncationTooltip=n.useTruncationTooltip;Object.defineProperty(exports,"sonner",{enumerable:!0,get:()=>ma.toast});exports.Alert=Ic;exports.AlertDescription=$c;exports.AlertTitle=Ac;exports.Avatar=Wa;exports.AvatarFallback=Ja;exports.AvatarImage=Ai;exports.BOOK_CHAPTER_CONTROL_STRING_KEYS=nn;exports.BOOK_SELECTOR_STRING_KEYS=cn;exports.BookChapterControl=Ge;exports.BookSelector=ln;exports.CANCEL_ACCEPT_BUTTONS_STRING_KEYS=Dr;exports.COMMENT_EDITOR_STRING_KEYS=Ti;exports.COMMENT_LIST_ELEMENT_ID=Ya;exports.COMMENT_LIST_STRING_KEYS=Mi;exports.CONFLICT_NOTE_STRING_KEYS=Ni;exports.CancelAcceptButtons=Or;exports.Card=Xa;exports.CardContent=Za;exports.CardDescription=zi;exports.CardFooter=Ii;exports.CardHeader=Di;exports.CardTitle=Oi;exports.ChapterRangeSelector=ya;exports.Checkbox=Ar;exports.CheckboxGroup=Mc;exports.Checklist=Bo;exports.ComboBox=mr;exports.CommentEditor=Si;exports.CommentList=Ki;exports.ConflictNoteCard=eo;exports.ContextMenu=Bc;exports.ContextMenuCheckboxItem=Yc;exports.ContextMenuContent=Kc;exports.ContextMenuGroup=Lc;exports.ContextMenuItem=Uc;exports.ContextMenuLabel=Zc;exports.ContextMenuPortal=Vc;exports.ContextMenuRadioGroup=Gc;exports.ContextMenuRadioItem=Xc;exports.ContextMenuSeparator=Wc;exports.ContextMenuShortcut=Jc;exports.ContextMenuSub=Fc;exports.ContextMenuSubContent=Hc;exports.ContextMenuSubTrigger=qc;exports.ContextMenuTrigger=Pc;exports.DataTable=no;exports.Drawer=Qc;exports.DrawerClose=el;exports.DrawerContent=rl;exports.DrawerDescription=il;exports.DrawerFooter=ol;exports.DrawerHeader=al;exports.DrawerOverlay=Lo;exports.DrawerPortal=Po;exports.DrawerTitle=nl;exports.DrawerTrigger=tl;exports.DropdownMenuItemType=co;exports.ERROR_DUMP_STRING_KEYS=io;exports.ERROR_POPOVER_STRING_KEYS=Zi;exports.EditorKeyboardShortcuts=uo;exports.EmptyState=Dc;exports.ErrorDump=so;exports.ErrorPopover=Wi;exports.FOOTNOTE_EDITOR_STRING_KEYS=gs;exports.Filter=rs;exports.FilterDropdown=Ji;exports.Footer=es;exports.FootnoteEditor=ps;exports.FootnoteItem=fo;exports.FootnoteList=ms;exports.INVENTORY_STRING_KEYS=Ss;exports.Inventory=Rs;exports.MARKER_MENU_STRING_KEYS=po;exports.MarkdownRenderer=Xi;exports.MarkerMenu=go;exports.MoreInfo=Qi;exports.NavigationContentSearch=pc;exports.Progress=sl;exports.RadioGroup=rr;exports.RadioGroupItem=Re;exports.RecentSearches=xa;exports.ResultsCard=Rc;exports.SCOPE_SELECTOR_STRING_KEYS=oc;exports.SELECT_BOOKS_STRING_KEYS=Do;exports.ScopeSelector=ic;exports.ScriptureResultsViewer=rc;exports.ScrollGroupSelector=sc;exports.Select=ue;exports.SelectBooks=Ro;exports.SelectBooksPicker=Mo;exports.SelectContent=he;exports.SelectGroup=ro;exports.SelectItem=Ut;exports.SelectLabel=qi;exports.SelectScrollDownButton=oo;exports.SelectScrollUpButton=ao;exports.SelectSeparator=Hi;exports.SelectTrigger=ge;exports.SelectValue=pe;exports.SettingsList=cc;exports.SettingsListHeader=dc;exports.SettingsListItem=lc;exports.SettingsSidebar=No;exports.SettingsSidebarContentSearch=Ys;exports.Sidebar=xo;exports.SidebarContent=yo;exports.SidebarFooter=Bs;exports.SidebarGroup=kr;exports.SidebarGroupAction=Ls;exports.SidebarGroupContent=_r;exports.SidebarGroupLabel=yr;exports.SidebarHeader=$s;exports.SidebarInput=As;exports.SidebarInset=ko;exports.SidebarMenu=_o;exports.SidebarMenuAction=Fs;exports.SidebarMenuBadge=Gs;exports.SidebarMenuButton=Co;exports.SidebarMenuItem=jo;exports.SidebarMenuSkeleton=Ks;exports.SidebarMenuSub=Us;exports.SidebarMenuSubButton=Hs;exports.SidebarMenuSubItem=qs;exports.SidebarProvider=bo;exports.SidebarRail=Is;exports.SidebarSeparator=Ps;exports.SidebarTrigger=zs;exports.Slider=ll;exports.Sonner=cl;exports.Switch=dl;exports.TabDropdownMenu=tr;exports.TabFloatingMenu=uc;exports.TabToolbar=wc;exports.Tabs=wl;exports.TabsContent=hl;exports.TabsList=pl;exports.TabsTrigger=gl;exports.TextField=Oc;exports.Textarea=Jo;exports.ToggleGroup=Mr;exports.ToggleGroupItem=Me;exports.Toolbar=Nc;exports.UNDO_REDO_BUTTONS_STRING_KEYS=lo;exports.UiLanguageSelector=Sc;exports.UndoRedoButtons=wo;exports.VerticalTabs=Br;exports.VerticalTabsContent=Lr;exports.VerticalTabsList=Pr;exports.VerticalTabsTrigger=Ao;exports.getBookIdFromUSFM=Es;exports.getCommentThreadElementId=Ri;exports.getInventoryHeader=Oe;exports.getLinesFromUSFM=Cs;exports.getNumberFromUSFM=Ns;exports.getStatusForItem=mo;exports.getToolbarOSReservedSpaceClassName=Cc;exports.inventoryCountColumn=_s;exports.inventoryItemColumn=ks;exports.inventoryStatusColumn=js;exports.useEvent=fl;exports.useEventAsync=vl;exports.useExtraValidMarkers=xl;exports.usePromise=Vo;exports.useRecentSearches=Qo;exports.useSidebar=ze;exports.useStylesheet=bl;exports.useViewVisibility=kl;function yl(t,r="top"){if(!t||typeof document>"u")return;const a=document.head||document.querySelector("head"),o=a.querySelector(":first-child"),i=document.createElement("style");i.appendChild(document.createTextNode(t)),r==="top"&&o?a.insertBefore(i,o):a.appendChild(i)}yl(`/* By default the editor is too tall for the footnote editor, even while empty, so this makes it shorter. */ .footnote-editor .editor-input { min-height: 75px; @@ -25,6 +18,13 @@ .footnote-editor .text-spacing .usfm_p { text-indent: 0; } +.banded-row:hover { + cursor: pointer; +} + +.banded-row[data-state='selected']:hover { + cursor: default; +} /** * This file was automatically generated on installation of the Shadcn/Lexical editor. The default * location of this file has been changed to integrate better with our project structure. diff --git a/lib/platform-bible-react/dist/index.cjs.map b/lib/platform-bible-react/dist/index.cjs.map index 1f15e2bad17..94d6adf1593 100644 --- a/lib/platform-bible-react/dist/index.cjs.map +++ b/lib/platform-bible-react/dist/index.cjs.map @@ -1 +1 @@ -{"version":3,"file":"index.cjs","sources":["../src/components/shadcn-ui/textarea.tsx","../src/components/shared/book-item.component.tsx","../src/components/shared/book-item.utils.ts","../src/components/advanced/recent-searches.component.tsx","../src/components/advanced/book-chapter-control/book-chapter-control.navigation.ts","../src/components/advanced/book-chapter-control/book-chapter-control.utils.ts","../src/components/advanced/book-chapter-control/numbered-item-grid.component.tsx","../src/components/advanced/book-chapter-control/chapter-grid.component.tsx","../src/components/advanced/book-chapter-control/verse-grid.component.tsx","../src/components/advanced/book-chapter-control/book-chapter-control.component.tsx","../src/components/advanced/book-chapter-control/book-chapter-control.types.ts","../src/components/shadcn-ui/radio-group.tsx","../src/components/basics/combo-box.component.tsx","../src/components/basics/chapter-range-selector.component.tsx","../src/components/advanced/book-selector.component.tsx","../../../node_modules/@lexical/react/LexicalComposerContext.prod.mjs","../../../node_modules/@lexical/react/LexicalComposer.prod.mjs","../../../node_modules/@lexical/react/LexicalOnChangePlugin.prod.mjs","../src/components/advanced/editor/themes/editor-theme.ts","../src/components/advanced/editor/nodes.ts","../../../node_modules/react-error-boundary/dist/react-error-boundary.js","../../../node_modules/@lexical/react/LexicalErrorBoundary.prod.mjs","../../../node_modules/@lexical/react/useLexicalEditable.prod.mjs","../../../node_modules/@lexical/selection/LexicalSelection.prod.mjs","../../../node_modules/@lexical/utils/LexicalUtils.prod.mjs","../../../node_modules/@lexical/extension/LexicalExtension.prod.mjs","../../../node_modules/@lexical/react/LexicalReactProviderExtension.prod.mjs","../../../node_modules/@lexical/text/LexicalText.prod.mjs","../../../node_modules/@lexical/dragon/LexicalDragon.prod.mjs","../../../node_modules/@lexical/react/LexicalRichTextPlugin.prod.mjs","../../../node_modules/@lexical/react/LexicalAutoFocusPlugin.prod.mjs","../../../node_modules/@lexical/react/LexicalClearEditorPlugin.prod.mjs","../../../node_modules/@lexical/react/LexicalContentEditable.prod.mjs","../src/components/advanced/editor/editor-ui/content-editable.tsx","../src/components/advanced/editor/context/toolbar-context.tsx","../src/components/advanced/editor/editor-hooks/use-modal.tsx","../src/components/advanced/editor/plugins/toolbar/toolbar-plugin.tsx","../src/components/advanced/editor/editor-hooks/use-update-toolbar.ts","../src/components/shadcn-ui/toggle.tsx","../src/components/shadcn-ui/toggle-group.tsx","../src/components/advanced/editor/plugins/toolbar/font-format-toolbar-plugin.tsx","../src/components/advanced/editor/plugins.tsx","../src/components/advanced/editor/editor.tsx","../src/components/advanced/editor/editor-utils.ts","../src/components/basics/cancel-accept-buttons.component.tsx","../src/components/advanced/comment-list/conflict-note-card.types.ts","../src/components/advanced/comment-list/comment-list.utils.ts","../src/components/advanced/comment-editor/comment-editor.component.tsx","../src/components/advanced/comment-editor/comment-editor.types.ts","../src/components/advanced/comment-list/comment-list.types.ts","../src/components/shadcn-ui/card.tsx","../src/components/shadcn-ui/avatar.tsx","../src/components/advanced/comment-list/comment-item.component.tsx","../src/components/advanced/comment-list/resolve-check-button.component.tsx","../src/components/advanced/comment-list/comment-thread.component.tsx","../src/components/advanced/comment-list/conflict-diff.tsx","../src/components/advanced/comment-list/conflict-note-card.component.tsx","../src/components/advanced/comment-list/conflict-thread-summary.component.tsx","../src/components/advanced/comment-list/use-conflict-resolution.hook.ts","../src/components/advanced/comment-list/conflict-thread.component.tsx","../src/components/advanced/comment-list/comment-list.component.tsx","../src/components/advanced/data-table/data-table-column-toggle.component.tsx","../src/components/shadcn-ui/select.tsx","../src/components/advanced/data-table/data-table-pagination.component.tsx","../src/components/advanced/data-table/data-table.component.tsx","../src/components/advanced/extension-marketplace/markdown-renderer.component.tsx","../src/components/basics/error-dump.component.tsx","../src/components/advanced/error-popover.component.tsx","../src/components/advanced/extension-marketplace/filter-dropdown.component.tsx","../src/components/advanced/extension-marketplace/more-info.component.tsx","../src/components/advanced/extension-marketplace/version-history.component.tsx","../src/components/advanced/extension-marketplace/footer.component.tsx","../src/components/advanced/filter.component.tsx","../src/components/basics/undo-redo-buttons.component.tsx","../src/components/basics/editor-keyboard-shortcuts.component.tsx","../src/components/advanced/footnote-editor/footnote-caller-dropdown.component.tsx","../src/components/advanced/footnote-editor/footnote-type-dropdown.component.tsx","../src/components/advanced/marker-menu.component.tsx","../src/components/advanced/footnote-editor/footnote-editor.utils.ts","../src/components/advanced/footnote-editor/footnote-editor.component.tsx","../src/components/advanced/footnote-editor/footnote-editor.types.ts","../src/components/advanced/footnotes/footnote-item.component.tsx","../src/components/advanced/footnotes/footnote-list.component.tsx","../src/components/advanced/inventory/occurrences-table.component.tsx","../src/components/shadcn-ui/checkbox.tsx","../src/components/advanced/inventory/inventory-columns.tsx","../src/components/advanced/inventory/inventory-utils.ts","../src/components/advanced/inventory/inventory.component.tsx","../src/components/shadcn-ui/sidebar.tsx","../src/components/advanced/settings-components/settings-sidebar.component.tsx","../src/components/advanced/settings-components/settings-sidebar-content-search.component.tsx","../src/components/advanced/scripture-results-viewer/scripture-results-viewer.component.tsx","../src/components/advanced/scope-selector/scope-selector.utils.ts","../src/components/advanced/scope-selector/select-books-picker.component.tsx","../src/components/advanced/scope-selector/section-button.component.tsx","../src/components/advanced/scope-selector/select-books.component.tsx","../src/components/advanced/scope-selector/select-books.types.ts","../src/components/advanced/scope-selector/scope-selector.component.tsx","../src/components/advanced/scroll-group-selector.component.tsx","../src/components/advanced/settings-components/settings-list.component.tsx","../src/components/advanced/menus/menu.util.ts","../src/components/advanced/menus/menu-icon.component.tsx","../src/components/advanced/menus/tab-dropdown-menu.component.tsx","../src/components/advanced/tab-toolbar/tab-toolbar-container.component.tsx","../src/components/advanced/tab-toolbar/tab-toolbar.component.tsx","../src/components/advanced/tab-toolbar/tab-floating-menu.component.tsx","../src/components/basics/tabs-vertical.tsx","../src/components/advanced/tab-navigation-content-search.component.tsx","../src/components/shadcn-ui/menubar.tsx","../src/components/advanced/menus/platform-menubar.component.tsx","../src/components/advanced/toolbar.component.tsx","../src/components/advanced/ui-language-selector.component.tsx","../src/components/basics/smart-label.component.tsx","../src/components/basics/checkbox-group.component.tsx","../src/components/basics/results-card.component.tsx","../src/components/basics/empty-state.component.tsx","../src/components/basics/text-field.component.tsx","../src/components/shadcn-ui/alert.tsx","../src/components/shadcn-ui/context-menu.tsx","../src/components/shadcn-ui/drawer.tsx","../src/components/shadcn-ui/progress.tsx","../src/components/shadcn-ui/sonner.tsx","../src/components/shadcn-ui/slider.tsx","../src/components/shadcn-ui/switch.tsx","../src/components/shadcn-ui/tabs.tsx","../src/hooks/use-event.hook.ts","../src/hooks/use-promise.hook.ts","../src/hooks/use-event-async.hook.ts","../src/hooks/use-stylesheet.hook.ts","../src/hooks/use-extra-valid-markers.hook.ts","../src/hooks/use-view-visibility.hook.ts"],"sourcesContent":["import React from 'react';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\n\n// CUSTOM: Added TSDoc with link to shadcn/ui documentation for this component\n/**\n * Displays a form textarea or a component that looks like a textarea. This component is from Shadcn\n * UI.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/textarea}\n */\nfunction Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {\n return (\n \n );\n}\n\nexport { Textarea };\n","import { CommandItem } from '@/components/shadcn-ui/command';\nimport { getLocalizedBookId, getLocalizedBookName } from '@/components/shared/book.utils';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Canon } from '@sillsdev/scripture';\nimport { Check } from 'lucide-react';\nimport { Section } from 'platform-bible-utils';\nimport { MouseEvent, Ref, useMemo, useRef } from 'react';\n\ntype BookItemProps = {\n /** Forwarded to the underlying CommandItem (a `
` rendered by cmdk). */\n ref?: Ref;\n /** The book ID (e.g., 'GEN', 'EXO') */\n bookId: string;\n /** Whether this book is currently selected */\n isSelected?: boolean;\n /** Callback function to handle book selection/deselection */\n onSelect?: (bookId: string) => void;\n /** Optional custom mouse down handler */\n onMouseDown?: (e: MouseEvent) => void;\n /** The section this book belongs to */\n section: Section;\n /** Additional CSS classes for the wrapper CommandItem */\n className?: string;\n /** Whether to show the check icon (for multiselect mode) */\n showCheck?: boolean;\n /**\n * Optional map of localized book IDs/short names and full names. Key is the (English) book ID,\n * value contains localized versions of the ID and full book name\n */\n localizedBookNames?: Map;\n /** Value to use for Command component matching */\n commandValue?: string;\n /** When true, renders the item as disabled: suppresses onSelect and dims the visuals. */\n disabled?: boolean;\n};\n\n/**\n * A reusable component that represents a single book item in book selectors. The component shows\n * the book's localized name, its ID, and visually indicates its testament (OT/NT/DC/Extra) through\n * color coding.\n *\n * For simple selection, use the `onSelect` prop. For complex interactions (like shift-click range\n * selection), implement custom `onSelect` and `onMouseDown` handlers that manage the logic\n * externally.\n */\nexport function BookItem({\n ref,\n bookId,\n isSelected,\n onSelect,\n onMouseDown,\n section,\n className,\n showCheck = false,\n localizedBookNames,\n commandValue,\n disabled = false,\n}: BookItemProps) {\n const isMouseClick = useRef(false);\n\n const handleSelect = () => {\n if (disabled) return;\n if (!isMouseClick.current) {\n onSelect?.(bookId);\n }\n // Reset the mouse flag after a short delay\n setTimeout(() => {\n isMouseClick.current = false;\n }, 100);\n };\n\n const handleMouseDown = (e: MouseEvent) => {\n if (disabled) {\n e.preventDefault();\n return;\n }\n isMouseClick.current = true;\n\n if (onMouseDown) {\n onMouseDown(e);\n } else {\n // If no custom mouse handler, fall back to calling onSelect\n onSelect?.(bookId);\n }\n };\n\n const bookDisplayName = useMemo(\n () => getLocalizedBookName(bookId, localizedBookNames),\n [bookId, localizedBookNames],\n );\n\n const bookDisplayId = useMemo(\n () => getLocalizedBookId(bookId, localizedBookNames),\n [bookId, localizedBookNames],\n );\n\n return (\n \n \n {showCheck && (\n \n )}\n {bookDisplayName}\n \n {bookDisplayId}\n \n \n
\n );\n}\n","import {\n ALL_ENGLISH_BOOK_NAMES,\n getLocalizedBookId,\n getLocalizedBookName,\n} from '@/components/shared/book.utils';\n\nexport function generateCommandValue(\n bookId: string,\n localizedBookNames?: Map,\n chapter?: number,\n): string {\n return `${bookId} ${ALL_ENGLISH_BOOK_NAMES[bookId]}${localizedBookNames ? ` ${getLocalizedBookId(bookId, localizedBookNames)} ${getLocalizedBookName(bookId, localizedBookNames)}` : ''}${chapter ? ` ${chapter}` : ''}`;\n}\n","import { Clock } from 'lucide-react';\nimport { Button } from '@/components/shadcn-ui/button';\nimport { Command, CommandGroup, CommandItem, CommandList } from '@/components/shadcn-ui/command';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/shadcn-ui/popover';\nimport { useState } from 'react';\nimport { cn } from '@/utils/shadcn-ui/utils';\n\n/** Interface defining the properties for the RecentSearches component */\nexport interface RecentSearchesProps {\n /** Array of recent search items */\n recentSearches: T[];\n /** Callback when a recent search item is selected */\n onSearchItemSelect: (item: T) => void;\n /** Function to render each search item as a string for display */\n renderItem?: (item: T) => string;\n /** Function to create a unique key for each item */\n getItemKey?: (item: T) => string;\n /** Aria label for the recent searches button */\n ariaLabel?: string;\n /** Heading text for the recent searches group */\n groupHeading?: string;\n /** Optional ID for the popover content for accessibility */\n id?: string;\n /** Class name for styling the `CommandItem` for each recent search result */\n classNameForItems?: string;\n /**\n * Class name for the trigger button. Defaults to absolute positioning inside an input field. Pass\n * a custom value to render the button standalone (e.g. `\"tw:h-9 tw:w-9\"`)\n */\n buttonClassName?: string;\n /** Variant for the trigger button. Defaults to `\"ghost\"` */\n buttonVariant?: 'ghost' | 'outline' | 'default' | 'destructive' | 'secondary' | 'link';\n}\n\n/**\n * Generic component that displays a button to show recent searches in a popover. Only renders if\n * there are recent searches available. Works with any data type T.\n */\nexport default function RecentSearches({\n recentSearches,\n onSearchItemSelect,\n renderItem = (item) => String(item),\n getItemKey = (item) => String(item),\n ariaLabel = 'Show recent searches',\n groupHeading = 'Recent',\n id,\n classNameForItems,\n buttonClassName = 'tw:absolute tw:right-0 tw:top-0 tw:h-full tw:px-3 tw:py-2',\n buttonVariant = 'ghost',\n}: RecentSearchesProps) {\n const [isOpen, setIsOpen] = useState(false);\n\n if (recentSearches.length === 0) {\n return undefined;\n }\n\n const handleSearchItemSelect = (item: T) => {\n onSearchItemSelect(item);\n setIsOpen(false);\n };\n\n return (\n \n \n \n \n \n \n \n \n \n \n {recentSearches.map((item) => (\n handleSearchItemSelect(item)}\n className={cn('tw:flex tw:items-center', classNameForItems)}\n >\n \n {renderItem(item)}\n \n ))}\n \n \n \n \n \n );\n}\n\n/** Generic hook for managing recent searches state and operations. */\nexport function useRecentSearches(\n recentSearches: T[],\n setRecentSearches: (items: T[]) => void,\n areItemsEqual: (a: T, b: T) => boolean = (a, b) => a === b,\n maxItems: number = 15,\n) {\n return (item: T) => {\n // Add the current item to recent searches, moving it to the top if it already exists\n const recentSearchesWithoutCurrent = recentSearches.filter(\n (existingItem) => !areItemsEqual(existingItem, item),\n );\n const updatedRecentSearches = [item, ...recentSearchesWithoutCurrent.slice(0, maxItems - 1)];\n setRecentSearches(updatedRecentSearches);\n };\n}\n","import { Direction } from '@/utils/dir-helper.util';\nimport { SerializedVerseRef } from '@sillsdev/scripture';\nimport { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-react';\nimport { ComponentType, useCallback, useMemo } from 'react';\nimport {\n getNextChapterRef,\n getNextVerseRef,\n getPreviousChapterRef,\n getPreviousVerseRef,\n} from 'platform-bible-utils/experimental';\n\nexport interface QuickNavButton {\n onClick: () => void;\n disabled?: boolean;\n title: string;\n icon: ComponentType<{ className?: string }>;\n}\n\n/** Whether stepping to `newRef` would do nothing: there is no target, or it equals `scrRef`. */\nfunction isNoOpNavigation(\n scrRef: SerializedVerseRef,\n newRef: SerializedVerseRef | undefined,\n): boolean {\n return (\n !newRef ||\n (newRef.book === scrRef.book &&\n newRef.chapterNum === scrRef.chapterNum &&\n newRef.verseNum === scrRef.verseNum)\n );\n}\n\nexport function useQuickNavButtons(\n scrRef: SerializedVerseRef,\n availableBooks: string[],\n direction: Direction,\n handleSubmit: (scrRef: SerializedVerseRef) => void,\n): QuickNavButton[] {\n // The buttons pass availableBooks (so navigation honors books-present and rolls across book\n // boundaries the way the keyboard commands do) but intentionally pass no ScriptureBounds — there\n // is no versification source here, so verse navigation keeps its pre-versification\n // floor-at-0 / unbounded-increment behavior within a book. Making the buttons versification-aware\n // to match the keyboard commands is tracked in PT-4143.\n //\n // Each target ref is computed once and reused for both the click handler and the disabled state,\n // so the button is disabled exactly when the step would be a no-op (no target, or the same ref).\n const previousChapterRef = useMemo(\n () => getPreviousChapterRef(scrRef, availableBooks),\n [scrRef, availableBooks],\n );\n const nextChapterRef = useMemo(\n () => getNextChapterRef(scrRef, availableBooks),\n [scrRef, availableBooks],\n );\n const previousVerseRef = useMemo(\n () => getPreviousVerseRef(scrRef, availableBooks),\n [scrRef, availableBooks],\n );\n const nextVerseRef = useMemo(\n () => getNextVerseRef(scrRef, availableBooks),\n [scrRef, availableBooks],\n );\n\n const submitIfChanged = useCallback(\n (newRef: SerializedVerseRef | undefined) => {\n if (newRef) handleSubmit(newRef);\n },\n [handleSubmit],\n );\n\n return useMemo(() => {\n return [\n {\n onClick: () => submitIfChanged(previousChapterRef),\n disabled: isNoOpNavigation(scrRef, previousChapterRef),\n title: 'Previous chapter',\n icon: direction === 'ltr' ? ChevronsLeft : ChevronsRight,\n },\n {\n onClick: () => submitIfChanged(previousVerseRef),\n disabled: isNoOpNavigation(scrRef, previousVerseRef),\n title: 'Previous verse',\n icon: direction === 'ltr' ? ChevronLeft : ChevronRight,\n },\n {\n onClick: () => submitIfChanged(nextVerseRef),\n disabled: isNoOpNavigation(scrRef, nextVerseRef),\n title: 'Next verse',\n icon: direction === 'ltr' ? ChevronRight : ChevronLeft,\n },\n {\n onClick: () => submitIfChanged(nextChapterRef),\n disabled: isNoOpNavigation(scrRef, nextChapterRef),\n title: 'Next chapter',\n icon: direction === 'ltr' ? ChevronsRight : ChevronsLeft,\n },\n ];\n }, [\n scrRef,\n direction,\n submitIfChanged,\n previousChapterRef,\n previousVerseRef,\n nextVerseRef,\n nextChapterRef,\n ]);\n}\n","import { Canon, SerializedVerseRef } from '@sillsdev/scripture';\nimport { getChaptersForBook } from 'platform-bible-utils';\nimport { ALL_ENGLISH_BOOK_NAMES, doesBookMatchQuery } from '@/components/shared/book.utils';\nimport { BookWithOptionalChapterAndVerse } from './book-chapter-control.types';\n\n// Smart parsing regex patterns\nexport const SCRIPTURE_REGEX_PATTERNS = {\n // Matches start of string (`^`), one or more non-colon/space words, optionally followed by space and more words (`([^:\\s]+(?:\\s+[^:\\s]+)*)`), end of string (`$`), case-insensitive (`i`)\n BOOK_ONLY: /^([^:\\s]+(?:\\s+[^:\\s]+)*)$/i,\n // Same as above, but followed by a space and a chapter number (`\\s+(\\d+)`)\n BOOK_CHAPTER: /^([^:\\s]+(?:\\s+[^:\\s]+)*)\\s+(\\d+)$/i,\n // Same as above, but followed by a colon and optionally a verse number (`:(\\d*)`)\n BOOK_CHAPTER_VERSE: /^([^:\\s]+(?:\\s+[^:\\s]+)*)\\s+(\\d+):(\\d*)$/i,\n} as const;\n\nexport const SEARCH_QUERY_FORMATS = [\n SCRIPTURE_REGEX_PATTERNS.BOOK_ONLY,\n SCRIPTURE_REGEX_PATTERNS.BOOK_CHAPTER,\n SCRIPTURE_REGEX_PATTERNS.BOOK_CHAPTER_VERSE,\n];\n\n/**\n * Returns true if the query contains a chapter-verse separator (`:`) following a chapter number.\n * Used to decide whether to switch to verse selection when the user is typing.\n */\nexport function hasChapterVerseSeparator(query: string): boolean {\n return SCRIPTURE_REGEX_PATTERNS.BOOK_CHAPTER_VERSE.test(query.trim());\n}\n\n/** Returns true if `bookId` appears strictly before `lowerBound.book` in canon order. */\nexport function isBookBefore(bookId: string, lowerBound: SerializedVerseRef): boolean {\n return Canon.bookIdToNumber(bookId) < Canon.bookIdToNumber(lowerBound.book);\n}\n\n/**\n * Returns true if the chapter in `bookId` is strictly before `lowerBound`. Chapters in books\n * earlier than `lowerBound.book` are treated as before. Chapters in later books are never before.\n */\nexport function isChapterBefore(\n bookId: string,\n chapterNum: number,\n lowerBound: SerializedVerseRef,\n): boolean {\n const bookCmp = Canon.bookIdToNumber(bookId) - Canon.bookIdToNumber(lowerBound.book);\n if (bookCmp < 0) return true;\n if (bookCmp > 0) return false;\n return chapterNum < lowerBound.chapterNum;\n}\n\n/**\n * Returns true if the verse in `bookId` / `chapterNum` is strictly before `lowerBound`. Verses in\n * earlier books or earlier chapters of the same book are treated as before.\n */\nexport function isVerseBefore(\n bookId: string,\n chapterNum: number,\n verseNum: number,\n lowerBound: SerializedVerseRef,\n): boolean {\n const bookCmp = Canon.bookIdToNumber(bookId) - Canon.bookIdToNumber(lowerBound.book);\n if (bookCmp < 0) return true;\n if (bookCmp > 0) return false;\n if (chapterNum < lowerBound.chapterNum) return true;\n if (chapterNum > lowerBound.chapterNum) return false;\n return verseNum < lowerBound.verseNum;\n}\n\nexport function getKeyCharacterType(key: string) {\n const isLetter = /^[a-zA-Z]$/.test(key);\n const isDigit = /^[0-9]$/.test(key);\n return { isLetter, isDigit };\n}\n\nexport function fetchEndChapter(bookId: string) {\n // getChaptersForBook returns -1 if not found in scrBookData\n // scrBookData only includes OT and NT, so all DC will return -1\n return getChaptersForBook(Canon.bookIdToNumber(bookId));\n}\n\nexport function calculateTopMatch(\n query: string,\n availableBooks: string[],\n localizedBookNames?: Map,\n): BookWithOptionalChapterAndVerse | undefined {\n if (!query.trim() || availableBooks.length === 0) return undefined;\n\n // First try smart parsing with regex patterns\n const topMatch = SEARCH_QUERY_FORMATS.reduce(\n (result: BookWithOptionalChapterAndVerse | undefined, format) => {\n if (result) return result;\n\n const matches = format.exec(query.trim());\n if (matches) {\n const [book, chapter = undefined, verse = undefined] = matches.slice(1);\n\n let validBookId: string | undefined;\n\n // Match for partial book name or id\n\n const allPotentialMatches = availableBooks.filter((bookId) => {\n return doesBookMatchQuery(bookId, book, localizedBookNames);\n });\n\n // Only create a topMatch if exactly one book could match\n if (allPotentialMatches.length === 1) {\n [validBookId] = allPotentialMatches;\n }\n\n // Match for exact book id (English or localized)\n // This is only performed when a chapter number is provided, to prevent edge cases where\n // a search for e.g. `jud` would generate a top match for 'Jude', even though 'Judges' would\n // also be a valid match\n if (!validBookId && chapter) {\n // Check exact English book ID\n if (Canon.isBookIdValid(book)) {\n const bookIdUpperCase = book.toUpperCase();\n if (availableBooks.includes(bookIdUpperCase)) {\n validBookId = bookIdUpperCase;\n }\n }\n\n // Check exact localized book ID\n if (!validBookId && localizedBookNames) {\n const matchingLocalizedBookId = Array.from(localizedBookNames.entries()).find(\n ([, localizedBook]) => localizedBook.localizedId.toLowerCase() === book.toLowerCase(),\n );\n if (matchingLocalizedBookId && availableBooks.includes(matchingLocalizedBookId[0])) {\n [validBookId] = matchingLocalizedBookId;\n }\n }\n }\n\n // Match for exact full book name (English or localized)\n // This is only performed when a chapter number is provided, to prevent edge cases where\n // a search for e.g. `john` only matches `John` but not `1 John`, `2 John` and `3 John`\n if (!validBookId && chapter) {\n // Check exact English book name\n const getBookIdFromEnglishName = (bookName: string): string | undefined => {\n return Object.keys(ALL_ENGLISH_BOOK_NAMES).find(\n (bookId) => ALL_ENGLISH_BOOK_NAMES[bookId].toLowerCase() === bookName.toLowerCase(),\n );\n };\n\n const matchingBookIdForFullName = getBookIdFromEnglishName(book);\n if (matchingBookIdForFullName && availableBooks.includes(matchingBookIdForFullName)) {\n validBookId = matchingBookIdForFullName;\n }\n\n // Check exact localized book name\n if (!validBookId && localizedBookNames) {\n const matchingLocalizedBookName = Array.from(localizedBookNames.entries()).find(\n ([, localizedBook]) =>\n localizedBook.localizedName.toLowerCase() === book.toLowerCase(),\n );\n if (\n matchingLocalizedBookName &&\n availableBooks.includes(matchingLocalizedBookName[0])\n ) {\n [validBookId] = matchingLocalizedBookName;\n }\n }\n }\n\n if (validBookId) {\n let chapterNum = chapter ? parseInt(chapter, 10) : undefined;\n if (chapterNum && chapterNum > fetchEndChapter(validBookId))\n chapterNum = Math.max(fetchEndChapter(validBookId), 1);\n const verseNum = verse ? parseInt(verse, 10) : undefined;\n\n return {\n book: validBookId,\n chapterNum,\n verseNum,\n };\n }\n }\n\n return undefined;\n },\n undefined,\n );\n\n if (topMatch) return topMatch;\n\n return undefined;\n}\n","import { CommandGroup, CommandItem } from '@/components/shadcn-ui/command';\nimport { cn } from '@/utils/shadcn-ui/utils';\n\nexport interface NumberedItemGridProps {\n /** Number of items to render (1..count, inclusive). Returns null if count <= 0. */\n count: number;\n /**\n * Builds the cmdk `value` for item `n`. This string drives cmdk's filtering / matching behavior,\n * so callers must preserve the exact format used by the non-shared components (e.g. `${bookId}\n * ${name} ${chapter}` for chapters or `${bookId} ${name} ${chapterNum}:${verse}` for verses).\n */\n valueBuilder: (n: number) => string;\n /** Callback when item `n` is selected (only fires when not disabled). */\n onSelect: (n: number) => void;\n /** Returns the `ref` callback for item `n` (used for keyboard navigation). */\n itemRef: (n: number) => (element: HTMLDivElement | null) => void;\n /** Whether item `n` is disabled (not selectable). Defaults to false. */\n isDisabled?: (n: number) => boolean;\n /** Whether item `n` should be visually dimmed. Defaults to false. */\n isDimmed?: (n: number) => boolean;\n /** Whether item `n` is the currently-selected item (highlighted). Defaults to false. */\n isSelected?: (n: number) => boolean;\n /** Optional additional class name applied to the grid wrapper. */\n className?: string;\n}\n\n/**\n * Internal helper that renders a 6-column grid of numbered cmdk `CommandItem`s for use by\n * `ChapterGrid` and `VerseGrid`. Encapsulates the shared layout, Tailwind classes, and disabled /\n * dimmed / selected state styling so the two public components only need to supply the per-item\n * differences.\n *\n * Not part of the public `platform-bible-react` API.\n */\nexport function NumberedItemGrid({\n count,\n valueBuilder,\n onSelect,\n itemRef,\n isDisabled,\n isDimmed,\n isSelected,\n className,\n}: NumberedItemGridProps) {\n if (count <= 0) return undefined;\n\n return (\n \n
\n {Array.from({ length: count }, (_, i) => i + 1).map((n) => {\n const disabled = isDisabled?.(n) ?? false;\n return (\n {\n if (disabled) return;\n onSelect(n);\n }}\n ref={itemRef(n)}\n disabled={disabled}\n aria-disabled={disabled || undefined}\n className={cn(\n 'tw:h-8 tw:w-8 tw:cursor-pointer tw:justify-center tw:rounded-md tw:text-center tw:text-sm',\n {\n 'tw:bg-primary tw:text-primary-foreground': isSelected?.(n) ?? false,\n },\n {\n 'tw:bg-muted/50 tw:text-muted-foreground/50':\n (isDimmed?.(n) ?? false) && !disabled,\n },\n disabled && 'tw:cursor-not-allowed tw:opacity-40',\n )}\n >\n {n}\n \n );\n })}\n
\n
\n );\n}\n\nexport default NumberedItemGrid;\n","import { ALL_ENGLISH_BOOK_NAMES } from '@/components/shared/book.utils';\nimport { fetchEndChapter } from './book-chapter-control.utils';\nimport { NumberedItemGrid } from './numbered-item-grid.component';\n\nexport interface ChapterGridProps {\n /** The book ID to render chapters for */\n bookId: string;\n /** Current scripture reference for highlighting */\n scrRef: { book: string; chapterNum: number };\n /** Callback when a chapter is selected */\n onChapterSelect: (chapter: number) => void;\n /** Function to set chapter refs for keyboard navigation */\n setChapterRef: (chapter: number) => (element: HTMLDivElement | null) => void;\n /** Optional function to determine if a chapter should be dimmed */\n isChapterDimmed?: (chapter: number) => boolean;\n /** Optional function to determine if a chapter should be disabled (not selectable). */\n isChapterDisabled?: (chapter: number) => boolean;\n /** Optional additional class name for styling */\n className?: string;\n}\n\n/**\n * Renders a grid of chapter numbers for a given book, with highlighting for the current chapter and\n * optional dimmed chapters based on state logic.\n */\nexport function ChapterGrid({\n bookId,\n scrRef,\n onChapterSelect,\n setChapterRef,\n isChapterDimmed,\n isChapterDisabled,\n className,\n}: ChapterGridProps) {\n if (!bookId) return undefined;\n\n return (\n `${bookId} ${ALL_ENGLISH_BOOK_NAMES[bookId] || ''} ${chapter}`}\n onSelect={onChapterSelect}\n itemRef={setChapterRef}\n isDisabled={isChapterDisabled}\n isDimmed={isChapterDimmed}\n isSelected={(chapter) => bookId === scrRef.book && chapter === scrRef.chapterNum}\n className={className}\n />\n );\n}\n","import { ALL_ENGLISH_BOOK_NAMES } from '@/components/shared/book.utils';\nimport { NumberedItemGrid } from './numbered-item-grid.component';\n\nexport interface VerseGridProps {\n /** The book ID the verses belong to */\n bookId: string;\n /** The chapter number the verses belong to */\n chapterNum: number;\n /** The number of verses to render (from 1 to endVerse, inclusive) */\n endVerse: number;\n /** Current scripture reference for highlighting */\n scrRef: { book: string; chapterNum: number; verseNum: number };\n /** Callback when a verse is selected */\n onVerseSelect: (verse: number) => void;\n /** Function to set verse refs for keyboard navigation */\n setVerseRef: (verse: number) => (element: HTMLDivElement | null) => void;\n /** Optional function to determine if a verse should be dimmed */\n isVerseDimmed?: (verse: number) => boolean;\n /** Optional function to determine if a verse should be disabled (not selectable). */\n isVerseDisabled?: (verse: number) => boolean;\n /** Optional additional class name for styling */\n className?: string;\n}\n\n/**\n * Renders a grid of verse numbers for a given book and chapter, with highlighting for the current\n * verse and optional dimmed verses based on state logic.\n */\nexport function VerseGrid({\n bookId,\n chapterNum,\n endVerse,\n scrRef,\n onVerseSelect,\n setVerseRef,\n isVerseDimmed,\n isVerseDisabled,\n className,\n}: VerseGridProps) {\n if (!bookId || endVerse <= 0) return undefined;\n\n return (\n \n `${bookId} ${ALL_ENGLISH_BOOK_NAMES[bookId] || ''} ${chapterNum}:${verse}`\n }\n onSelect={onVerseSelect}\n itemRef={setVerseRef}\n isDisabled={isVerseDisabled}\n isDimmed={isVerseDimmed}\n isSelected={(verse) =>\n bookId === scrRef.book && chapterNum === scrRef.chapterNum && verse === scrRef.verseNum\n }\n className={className}\n />\n );\n}\n\nexport default VerseGrid;\n","import { BookItem } from '@/components/shared/book-item.component';\nimport { Button } from '@/components/shadcn-ui/button';\nimport {\n Command,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/components/shadcn-ui/command';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/shadcn-ui/popover';\nimport { Direction, readDirection } from '@/utils/dir-helper.util';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Canon, SerializedVerseRef } from '@sillsdev/scripture';\nimport { ArrowLeft, ArrowRight } from 'lucide-react';\nimport { formatScrRef, getSectionForBook, Section } from 'platform-bible-utils';\nimport {\n getSectionLongName,\n getLocalizedBookName,\n getLocalizedBookId,\n ALL_BOOK_IDS,\n ALL_ENGLISH_BOOK_NAMES,\n doesBookMatchQuery,\n} from '@/components/shared/book.utils';\nimport {\n KeyboardEvent,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { generateCommandValue } from '@/components/shared/book-item.utils';\nimport RecentSearches from '../recent-searches.component';\nimport { useQuickNavButtons } from './book-chapter-control.navigation';\nimport { BookChapterControlProps, ViewMode } from './book-chapter-control.types';\nimport {\n calculateTopMatch,\n fetchEndChapter,\n getKeyCharacterType,\n hasChapterVerseSeparator,\n isBookBefore,\n isChapterBefore,\n isVerseBefore,\n} from './book-chapter-control.utils';\nimport { ChapterGrid } from './chapter-grid.component';\nimport { VerseGrid } from './verse-grid.component';\n\n/**\n * `BookChapterControl` is a component that provides an interactive UI for selecting book chapters.\n * It allows users to input a search query to find specific books and chapters, navigate through\n * options with keyboard interactions, and submit selections. The component handles various\n * interactions such as opening and closing the dropdown menu, filtering book lists based on search\n * input, and managing highlighted selections. It also integrates with external handlers for\n * submitting selected references and retrieving active book IDs.\n */\nexport function BookChapterControl({\n scrRef,\n handleSubmit,\n className,\n getActiveBookIds,\n localizedBookNames,\n localizedStrings,\n recentSearches,\n onAddRecentSearch,\n id,\n getEndVerse,\n disableReferencesUpTo,\n submitKeys,\n triggerContent,\n triggerVariant = 'outline',\n onOpenChange,\n onCloseAutoFocus,\n modal = false,\n align = 'center',\n ref,\n disabled,\n}: BookChapterControlProps) {\n const direction: Direction = readDirection();\n\n // Indicates if the Command popover is open or not\n const [isCommandOpen, setIsCommandOpen] = useState(false);\n // The value of the Command, mainly needed for reliable keyboard navigation\n const [commandValue, setCommandValue] = useState('');\n // The value of the Input inside the Command\n const [inputValue, setInputValue] = useState('');\n // The current view mode (books or chapters)\n const [viewMode, setViewMode] = useState('books');\n // The book currently selected for chapter view, if any\n const [selectedBookForChaptersView, setSelectedBookForChaptersView] = useState<\n string | undefined\n >(undefined);\n // The book/chapter currently selected for verse view, if any\n const [selectedBookForVersesView, setSelectedBookForVersesView] = useState(\n undefined,\n );\n const [selectedChapterForVersesView, setSelectedChapterForVersesView] = useState<\n number | undefined\n >(undefined);\n const [isCommandListHidden, setIsCommandListHidden] = useState(false);\n\n // Reference to the PopoverTrigger button. Used by `onPointerDownOutside` to detect\n // clicks on our own trigger while the popover is open — see that handler for the full\n // story. `null` is React's canonical \"not yet attached\" ref value; there's no undefined\n // equivalent in the DOM/ref API.\n // eslint-disable-next-line no-null/no-null\n const triggerRef = useRef(null);\n // Set in `onPointerDownOutside` when we detect a click on our trigger while the popover\n // is open. Consumed in Button's `onClick` to call `event.preventDefault()` before Radix's\n // own `onOpenToggle` handler runs — `composeEventHandlers` skips `onOpenToggle` when\n // `defaultPrevented` is true, so the popover stays closed instead of toggling back open.\n const justClosedByTriggerRef = useRef(false);\n // Reference to the Command component\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const commandRef = useRef(undefined!);\n // Reference to the Input component inside the Command\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const commandInputRef = useRef(undefined!);\n // Reference to the CommandList inside the Command\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const commandListRef = useRef(undefined!);\n // Reference to the selected book item in the CommandList\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const selectedBookItemRef = useRef(undefined!);\n // References to the chapters that are shown as CommandItems\n const chapterRefs = useRef>({});\n // References to the verses that are shown as CommandItems\n const verseRefs = useRef>({});\n\n // Wrapper function to handle submit and add to recent searches\n const handleSubmitAndAddToRecent = useCallback(\n (newScrRef: SerializedVerseRef) => {\n handleSubmit(newScrRef);\n if (onAddRecentSearch) {\n onAddRecentSearch(newScrRef);\n }\n },\n [handleSubmit, onAddRecentSearch],\n );\n\n // #region Available books, filtering and top match logic\n\n const activeBookIds = useMemo(() => {\n return getActiveBookIds ? getActiveBookIds() : ALL_BOOK_IDS;\n }, [getActiveBookIds]);\n\n const availableBooksByType = useMemo(() => {\n const grouped: Record = {\n [Section.OT]: activeBookIds.filter((bookId) => Canon.isBookOT(bookId)),\n [Section.NT]: activeBookIds.filter((bookId) => Canon.isBookNT(bookId)),\n [Section.DC]: activeBookIds.filter((bookId) => Canon.isBookDC(bookId)),\n [Section.Extra]: activeBookIds.filter((bookId) => Canon.extraBooks().includes(bookId)),\n };\n return grouped;\n }, [activeBookIds]);\n\n const availableBooks = useMemo(() => {\n return Object.values(availableBooksByType).flat();\n }, [availableBooksByType]);\n\n // Filter books based on search input\n const filteredBooksByType = useMemo(() => {\n if (!inputValue.trim()) return availableBooksByType;\n\n const filteredBooks: Record = {\n [Section.OT]: [],\n [Section.NT]: [],\n [Section.DC]: [],\n [Section.Extra]: [],\n };\n\n const bookTypes: Section[] = [Section.OT, Section.NT, Section.DC, Section.Extra];\n bookTypes.forEach((type) => {\n filteredBooks[type] = availableBooksByType[type].filter((bookId) => {\n return doesBookMatchQuery(bookId, inputValue, localizedBookNames);\n });\n });\n\n return filteredBooks;\n }, [availableBooksByType, inputValue, localizedBookNames]);\n\n // Get the current top match\n const topMatch = useMemo(\n () => calculateTopMatch(inputValue, availableBooks, localizedBookNames),\n [inputValue, availableBooks, localizedBookNames],\n );\n\n // Surface open/close transitions to the parent. Fires only on the true boolean flip, not on\n // internal back-navigation (verses → chapters → books) which is handled without closing the\n // popover. Skip the initial mount run so callers don't see a spurious `onOpenChange(false)`\n // before any interaction — that phantom close has tripped parent focus-restore logic.\n const didMountRef = useRef(false);\n useEffect(() => {\n if (!didMountRef.current) {\n didMountRef.current = true;\n return;\n }\n onOpenChange?.(isCommandOpen);\n }, [isCommandOpen, onOpenChange]);\n\n // #endregion\n\n // #region Submitting references\n\n const handleTopMatchSelect = useCallback(() => {\n // If we have a top match (smart parsed or single book filter), use its specific chapter/verse\n if (topMatch) {\n const effectiveChapter = topMatch.chapterNum ?? 1;\n const effectiveVerse = topMatch.verseNum ?? 1;\n if (\n disableReferencesUpTo &&\n isVerseBefore(topMatch.book, effectiveChapter, effectiveVerse, disableReferencesUpTo)\n ) {\n return;\n }\n handleSubmitAndAddToRecent({\n book: topMatch.book,\n chapterNum: effectiveChapter,\n verseNum: effectiveVerse,\n });\n setIsCommandOpen(false);\n setInputValue('');\n setCommandValue(''); // Reset command value\n }\n }, [handleSubmitAndAddToRecent, topMatch, disableReferencesUpTo]);\n\n const handleVerseSelect = useCallback(\n (verseNumber: number) => {\n const bookId = selectedBookForVersesView ?? topMatch?.book;\n const chapterNum = selectedChapterForVersesView ?? topMatch?.chapterNum;\n if (!bookId || !chapterNum) return;\n\n handleSubmitAndAddToRecent({\n book: bookId,\n chapterNum,\n verseNum: verseNumber,\n });\n // Don't reset view / selection state here — `handleOpenChange(true)` does that\n // when the popover reopens. Resetting now causes a flicker: the popover's fade-out\n // animation would otherwise render the book list for a frame before unmounting.\n setIsCommandOpen(false);\n },\n [handleSubmitAndAddToRecent, selectedBookForVersesView, selectedChapterForVersesView, topMatch],\n );\n\n const handleBookSelect = useCallback(\n (bookId: string) => {\n if (disableReferencesUpTo && isBookBefore(bookId, disableReferencesUpTo)) return;\n // Check if book has chapters - if not, submit immediately\n const endChapter = fetchEndChapter(bookId);\n if (endChapter <= 1) {\n handleSubmitAndAddToRecent({\n book: bookId,\n chapterNum: 1,\n verseNum: 1,\n });\n setIsCommandOpen(false);\n setInputValue('');\n return;\n }\n\n // Book has multiple chapters - transition to chapter view\n setSelectedBookForChaptersView(bookId);\n setViewMode('chapters');\n },\n [handleSubmitAndAddToRecent, disableReferencesUpTo],\n );\n\n const handleChapterSelect = useCallback(\n (chapterNumber: number) => {\n // Determine which book we're selecting a chapter for\n const bookId = viewMode === 'chapters' ? selectedBookForChaptersView : topMatch?.book;\n if (!bookId) return;\n\n // If verse selection is enabled and the chapter has multiple verses, transition to verse view\n if (getEndVerse) {\n const endVerse = getEndVerse(bookId, chapterNumber);\n if (endVerse > 1) {\n setSelectedBookForVersesView(bookId);\n setSelectedChapterForVersesView(chapterNumber);\n setViewMode('verses');\n setCommandValue('');\n return;\n }\n }\n\n handleSubmitAndAddToRecent({\n book: bookId,\n chapterNum: chapterNumber,\n verseNum: 1,\n });\n // See `handleVerseSelect` — skip the view/selection reset to avoid a flicker\n // back to the book list during the popover's fade-out animation.\n setIsCommandOpen(false);\n },\n [handleSubmitAndAddToRecent, viewMode, selectedBookForChaptersView, topMatch, getEndVerse],\n );\n\n const handleRecentItemSelect = useCallback(\n (item: SerializedVerseRef) => {\n handleSubmitAndAddToRecent(item);\n setIsCommandOpen(false);\n setInputValue('');\n },\n [handleSubmitAndAddToRecent],\n );\n\n // #endregion\n\n // #region Navigation and view changes\n\n // Hook that provides navigation buttons for quick chapter/verse navigation\n const quickNavButtons = useQuickNavButtons(scrRef, availableBooks, direction, handleSubmit);\n\n const handleBackToBooks = useCallback(() => {\n setViewMode('books');\n setSelectedBookForChaptersView(undefined);\n setSelectedBookForVersesView(undefined);\n setSelectedChapterForVersesView(undefined);\n\n // Focus the search input when returning to book view\n setTimeout(() => {\n if (commandInputRef.current) {\n commandInputRef.current.focus();\n }\n }, 0);\n }, []);\n\n const handleBackToChapters = useCallback(() => {\n // Preserve selectedBookForChaptersView for the chapter view; reset verse state\n const previouslySelectedBook = selectedBookForVersesView;\n setSelectedBookForVersesView(undefined);\n setSelectedChapterForVersesView(undefined);\n\n if (previouslySelectedBook) {\n setSelectedBookForChaptersView(previouslySelectedBook);\n setViewMode('chapters');\n setCommandValue('');\n } else {\n handleBackToBooks();\n }\n }, [selectedBookForVersesView, handleBackToBooks]);\n\n // Reset view state when popover opens. Close requests always close the popover —\n // `Escape`, outside-click, and any other Radix-initiated dismiss route through here and\n // the user expects them to dismiss the whole picker. Stepping back through views is the\n // back button's job; trying to double-duty dismiss as \"go up one level\" silently rewinds\n // the user's selection when Radix fires a close for a transient reason (focus blip, click\n // in a non-item padding area, etc.).\n const handleOpenChange = useCallback((shouldCommandBeOpen: boolean) => {\n setIsCommandOpen(shouldCommandBeOpen);\n if (shouldCommandBeOpen) {\n setViewMode('books');\n setSelectedBookForChaptersView(undefined);\n setSelectedBookForVersesView(undefined);\n setSelectedChapterForVersesView(undefined);\n setInputValue('');\n }\n }, []);\n\n // `disabled` on the trigger button only prevents OPENING the popover — it does not affect one\n // that is already open, which would otherwise keep accepting input and submit a reference for a\n // control the UI reports as non-interactive (e.g. the toolbar's navigation target disappearing\n // mid-interaction). Close it when the control becomes disabled.\n useEffect(() => {\n if (disabled) handleOpenChange(false);\n }, [disabled, handleOpenChange]);\n\n // Imperative `open()` goes through handleOpenChange (not setIsCommandOpen directly) so the\n // deferred view-state reset runs: the control deliberately leaves stale chapters/verses view\n // state behind on close (see handleVerseSelect / handleChapterSelect) and only resets it when\n // the popover opens. Callers like the Ctrl+B command can't know what view the control was last\n // left in, and CommandInput only renders in 'books' view — without the reset, focus would no-op.\n //\n // Focusing the search input is driven by this request counter (each `open()` call increments\n // it) rather than a `setTimeout` so the focus effect below runs after the commit that actually\n // rendered the popover's books-view CommandInput, even if that render takes longer than a tick.\n const [focusSearchInputRequestId, setFocusSearchInputRequestId] = useState(0);\n\n useEffect(() => {\n if (focusSearchInputRequestId === 0) return;\n commandInputRef.current?.focus();\n }, [focusSearchInputRequestId]);\n\n useImperativeHandle(\n ref,\n () => ({\n open: () => {\n // Match the trigger button: a disabled control cannot be opened imperatively either\n if (disabled) return;\n handleOpenChange(true);\n setFocusSearchInputRequestId((requestId) => requestId + 1);\n },\n }),\n [handleOpenChange, disabled],\n );\n\n // #endregion\n\n // #region Helper functions and variables\n\n const { otLong, ntLong, dcLong, extraLong } = {\n otLong: localizedStrings?.['%scripture_section_ot_long%'],\n ntLong: localizedStrings?.['%scripture_section_nt_long%'],\n dcLong: localizedStrings?.['%scripture_section_dc_long%'],\n extraLong: localizedStrings?.['%scripture_section_extra_long%'],\n };\n\n const getSectionLabel = useCallback(\n (section: Section): string => {\n return getSectionLongName(section, otLong, ntLong, dcLong, extraLong);\n },\n [otLong, ntLong, dcLong, extraLong],\n );\n\n const doesChapterMatch = useCallback(\n (chapter: number) => {\n if (!topMatch) return false;\n return !!topMatch.chapterNum && !chapter.toString().includes(topMatch.chapterNum.toString());\n },\n [topMatch],\n );\n\n const currentDisplayValue = useMemo(\n () =>\n formatScrRef(\n scrRef,\n localizedBookNames ? getLocalizedBookName(scrRef.book, localizedBookNames) : 'English',\n ),\n [scrRef, localizedBookNames],\n );\n\n const setChapterRef = useCallback((chapter: number) => {\n return (element: HTMLDivElement | null) => {\n chapterRefs.current[chapter] = element;\n };\n }, []);\n\n const setVerseRef = useCallback((verse: number) => {\n return (element: HTMLDivElement | null) => {\n verseRefs.current[verse] = element;\n };\n }, []);\n\n // Whether the current input contains a chapter-verse separator (colon)\n const hasVerseSeparatorInInput = useMemo(\n () => hasChapterVerseSeparator(inputValue),\n [inputValue],\n );\n\n // Whether we should show a verse grid for the current top match\n const shouldShowVerseGridForTopMatch = useMemo(() => {\n if (!getEndVerse || !topMatch || !topMatch.chapterNum) return false;\n if (!hasVerseSeparatorInInput) return false;\n return getEndVerse(topMatch.book, topMatch.chapterNum) > 0;\n }, [getEndVerse, topMatch, hasVerseSeparatorInInput]);\n\n const isBookDisabled = useCallback(\n (bookId: string) =>\n disableReferencesUpTo ? isBookBefore(bookId, disableReferencesUpTo) : false,\n [disableReferencesUpTo],\n );\n\n const makeIsChapterDisabled = useCallback(\n (bookId: string) => (chapter: number) =>\n disableReferencesUpTo ? isChapterBefore(bookId, chapter, disableReferencesUpTo) : false,\n [disableReferencesUpTo],\n );\n\n const makeIsVerseDisabled = useCallback(\n (bookId: string, chapterNum: number) => (verse: number) =>\n disableReferencesUpTo\n ? isVerseBefore(bookId, chapterNum, verse, disableReferencesUpTo)\n : false,\n [disableReferencesUpTo],\n );\n\n const selectChapterTitle =\n localizedStrings?.['%webView_bookChapterControl_selectChapter%'] ?? 'Select Chapter';\n const selectVerseTitle =\n localizedStrings?.['%webView_bookChapterControl_selectVerse%'] ?? 'Select Verse';\n\n // #endregion\n\n // #region Keyboard handling\n\n // Handle keyboard navigation for CommandInput\n const handleInputKeyDown = useCallback(\n (event: KeyboardEvent) => {\n // Override default Home and End key behavior to work normally for cursor movement.\n // Default behavior was to jump to the start/end of the list of items in the Command\n if (event.key === 'Home' || event.key === 'End') {\n event.stopPropagation(); // Prevent Command component from handling these\n }\n\n // Callers can declare extra submit keys (e.g. space and `-` for range pickers). We\n // only submit when the typed input resolves to a fully-qualified reference (book\n // AND chapter AND verse) — a partial match like \"GEN\" or \"GEN 1\" would be ambiguous\n // as an auto-complete from a separator keystroke, so we leave those for the user to\n // finish. When we do submit, consume the keystroke so the character doesn't end up\n // in the input after the popover closes.\n if (\n submitKeys &&\n submitKeys.includes(event.key) &&\n topMatch &&\n topMatch.chapterNum !== undefined &&\n topMatch.verseNum !== undefined\n ) {\n event.preventDefault();\n event.stopPropagation();\n handleTopMatchSelect();\n }\n },\n [submitKeys, topMatch, handleTopMatchSelect],\n );\n\n // Grid-aware keyboard navigation using Command's controlled value\n const handleCommandKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (event.ctrlKey) return;\n\n const { isLetter, isDigit } = getKeyCharacterType(event.key);\n\n // Enter / Space pick the highlighted chapter / verse. cmdk binds Enter natively on\n // the Command root, but a grid picker reads more like \"activate the focused cell\"\n // than an input form, so we centralize both keys here and let the `data-selected`\n // item drive the submit. When focus is on a natively interactive element (the back\n // button), yield: the browser's own activation (click on Enter keydown / Space\n // keyup) should run the button's `onClick`, not submit a grid cell. We still\n // `stopPropagation` so cmdk's Enter handler doesn't ALSO fire in parallel and\n // submit the highlighted chapter while the back button is being pressed.\n if (\n (viewMode === 'chapters' || viewMode === 'verses') &&\n (event.key === ' ' || event.key === 'Enter')\n ) {\n const target = event.target instanceof HTMLElement ? event.target : undefined;\n const isTargetInteractive = !!target?.closest(\n 'button, a, input, select, textarea, [role=\"button\"]',\n );\n if (isTargetInteractive) {\n // Don't preventDefault — browser-native activation (Enter → click, Space →\n // click on keyup) must still reach the button's onClick.\n event.stopPropagation();\n return;\n }\n const highlighted = commandRef.current?.querySelector(\n '[cmdk-item][data-selected=\"true\"]:not([data-disabled=\"true\"])',\n );\n if (highlighted) {\n event.preventDefault();\n event.stopPropagation();\n highlighted.click();\n return;\n }\n }\n\n // Letter / digit keys in chapter or verse view do nothing: the filter input isn't\n // visible there, so forwarding keystrokes to it would silently exit the grid\n // (jumping back to the book list and typing into the hidden input). Users stay\n // on the current page; Backspace is the explicit way back.\n if ((viewMode === 'chapters' || viewMode === 'verses') && (isLetter || isDigit)) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Handle keypresses in chapter viewmode\n if (viewMode === 'chapters') {\n // Handle backspace for going back to books\n if (event.key === 'Backspace') {\n event.preventDefault();\n event.stopPropagation();\n handleBackToBooks();\n return;\n }\n }\n\n // Handle keypresses in verse viewmode\n if (viewMode === 'verses') {\n // Handle backspace for going back to chapters\n if (event.key === 'Backspace') {\n event.preventDefault();\n event.stopPropagation();\n handleBackToChapters();\n return;\n }\n }\n\n // Handle grid navigation for arrow keys in chapter/verse views\n const isGridNav = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key);\n\n if (viewMode === 'verses' && isGridNav) {\n const bookId = selectedBookForVersesView;\n const chapterNum = selectedChapterForVersesView;\n if (!bookId || !chapterNum || !getEndVerse) return;\n\n const maxVerse = getEndVerse(bookId, chapterNum);\n if (!maxVerse) return;\n\n // Arrow keys drive the grid now — pull focus off the back button (the only\n // natively focusable element in this view) so its lingering focus ring doesn't\n // compete visually with the grid's `data-selected` highlight. The Command root\n // has `tabIndex={-1}` (cmdk sets it), so it's a valid focus target and keeps\n // our PopoverContent capture-phase key handling working unchanged.\n commandRef.current?.focus();\n\n const currentVerse = (() => {\n if (!commandValue) return 1;\n const match = commandValue.match(/:(\\d+)$/);\n return match ? parseInt(match[1], 10) : 0;\n })();\n\n let targetVerse = currentVerse;\n const GRID_COLS = 6;\n\n switch (event.key) {\n case 'ArrowLeft':\n if (currentVerse !== 0) targetVerse = currentVerse > 1 ? currentVerse - 1 : maxVerse;\n break;\n case 'ArrowRight':\n if (currentVerse !== 0) targetVerse = currentVerse < maxVerse ? currentVerse + 1 : 1;\n break;\n case 'ArrowUp':\n targetVerse = currentVerse === 0 ? maxVerse : Math.max(1, currentVerse - GRID_COLS);\n break;\n case 'ArrowDown':\n targetVerse = currentVerse === 0 ? 1 : Math.min(maxVerse, currentVerse + GRID_COLS);\n break;\n default:\n return;\n }\n\n if (targetVerse !== currentVerse) {\n event.preventDefault();\n event.stopPropagation();\n\n setCommandValue(\n `${bookId} ${ALL_ENGLISH_BOOK_NAMES[bookId] || ''} ${chapterNum}:${targetVerse}`,\n );\n\n setTimeout(() => {\n const targetElement = verseRefs.current[targetVerse];\n if (targetElement) {\n targetElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }\n }, 0);\n }\n return;\n }\n\n if ((viewMode === 'chapters' || (viewMode === 'books' && topMatch)) && isGridNav) {\n // Extract current chapter from commandValue\n const currentBookId =\n viewMode === 'chapters' ? selectedBookForChaptersView : topMatch?.book;\n if (!currentBookId) return;\n\n // See the verses grid above — pull focus off the back button when arrow\n // navigation starts so its focus ring doesn't shadow the `data-selected`\n // highlight in the grid. Skipped for the `books` + topMatch branch where focus\n // already lives on the CommandInput.\n if (viewMode === 'chapters') {\n commandRef.current?.focus();\n }\n\n // Parse chapter from current command value\n const currentChapter = (() => {\n if (!commandValue) return 1;\n const match = commandValue.match(/(\\d+)$/);\n return match ? parseInt(match[1], 10) : 0;\n })();\n\n const maxChapter = fetchEndChapter(currentBookId);\n\n if (!maxChapter) return;\n\n let targetChapter = currentChapter;\n const GRID_COLS = 6;\n\n switch (event.key) {\n case 'ArrowLeft':\n if (currentChapter !== 0)\n targetChapter = currentChapter > 1 ? currentChapter - 1 : maxChapter;\n break;\n case 'ArrowRight':\n if (currentChapter !== 0)\n targetChapter = currentChapter < maxChapter ? currentChapter + 1 : 1;\n break;\n case 'ArrowUp':\n targetChapter =\n currentChapter === 0 ? maxChapter : Math.max(1, currentChapter - GRID_COLS);\n break;\n case 'ArrowDown':\n targetChapter =\n currentChapter === 0 ? 1 : Math.min(maxChapter, currentChapter + GRID_COLS);\n break;\n default:\n return;\n }\n\n if (targetChapter !== currentChapter) {\n event.preventDefault();\n event.stopPropagation();\n\n // Match ChapterGrid's CommandItem value exactly (no localized parts) — using\n // generateCommandValue here would diverge when localizedBookNames is provided and\n // cmdk wouldn't find a matching item to highlight.\n setCommandValue(\n `${currentBookId} ${ALL_ENGLISH_BOOK_NAMES[currentBookId] || ''} ${targetChapter}`,\n );\n\n // Scroll the target chapter into view using refs\n setTimeout(() => {\n const targetElement = chapterRefs.current[targetChapter];\n if (targetElement) {\n targetElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }\n }, 0);\n }\n }\n },\n [\n viewMode,\n topMatch,\n handleBackToBooks,\n handleBackToChapters,\n selectedBookForChaptersView,\n selectedBookForVersesView,\n selectedChapterForVersesView,\n getEndVerse,\n commandValue,\n ],\n );\n\n const handleQuickNavButtonKeyDown = useCallback((event: KeyboardEvent) => {\n if (event.shiftKey || event.key === 'Tab' || event.key === ' ') return;\n\n // Enter must activate the focused quick-nav button the way any other button\n // would. The browser turns keydown Enter into a click automatically, but cmdk's\n // onKeyDown on the Command root (an ancestor) would fire next and call\n // `event.preventDefault()` in its Enter branch — canceling that click synthesis\n // and submitting the highlighted book list item instead of running the\n // quick-nav handler. Stop propagation here (button onKeyDown runs before the\n // ancestor's) so cmdk never sees the Enter. Do NOT preventDefault — that's\n // what the browser uses to produce the click on the button.\n if (event.key === 'Enter') {\n event.stopPropagation();\n return;\n }\n\n // Up / Down signal the user wants to walk the book list. cmdk's arrow-key\n // handler on the Command root takes care of moving the `data-selected`\n // highlight (the keydown keeps bubbling up past us to reach it), but the\n // quick-nav button's focus ring would otherwise linger and compete with\n // the cmdk highlight. Pull focus to the search input — the visual focus\n // state that a user expects to see during book-list navigation.\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n commandInputRef.current?.focus();\n return;\n }\n\n const { isLetter, isDigit } = getKeyCharacterType(event.key);\n\n if (isLetter || isDigit) {\n event.preventDefault();\n\n setInputValue((prevValue) => prevValue + event.key);\n commandInputRef.current.focus();\n\n setIsCommandListHidden(false);\n }\n }, []);\n\n // #endregion\n\n // #region Auto-scroll\n\n // Auto-scroll to currently selected book when dropdown opens in book view\n useLayoutEffect(() => {\n const scrollTimeout = setTimeout(() => {\n if (\n isCommandOpen &&\n viewMode === 'books' &&\n commandListRef.current &&\n selectedBookItemRef.current\n ) {\n const listElement = commandListRef.current;\n const itemElement = selectedBookItemRef.current;\n\n // Calculate scroll position to center the selected item\n const itemOffsetTop = itemElement.offsetTop;\n const listHeight = listElement.clientHeight;\n const itemHeight = itemElement.clientHeight;\n const scrollPosition = itemOffsetTop - listHeight / 2 + itemHeight / 2;\n\n listElement.scrollTo({\n top: Math.max(0, scrollPosition),\n behavior: 'smooth',\n });\n\n // Set the selected book as the active item for keyboard navigation\n setCommandValue(generateCommandValue(scrRef.book));\n }\n }, 0);\n\n return () => {\n clearTimeout(scrollTimeout);\n };\n }, [isCommandOpen, viewMode, inputValue, topMatch, scrRef.book]);\n\n // Auto-scroll to appropriate chapter\n useLayoutEffect(() => {\n if (viewMode === 'chapters' && selectedBookForChaptersView) {\n // Check if we're entering chapter view for the currently selected book\n const isCurrentlySelectedBook = selectedBookForChaptersView === scrRef.book;\n const initialChapter = isCurrentlySelectedBook ? scrRef.chapterNum : 1;\n\n // Seed commandValue to the starting chapter so arrow-key navigation has a concrete\n // starting point (see handleCommandKeyDown) and cmdk visibly highlights that chapter\n // even when focus is pinned on the PopoverContent wrapper by Radix's FocusScope in\n // modal mode. Format must match ChapterGrid's CommandItem `value`.\n setCommandValue(\n `${selectedBookForChaptersView} ${ALL_ENGLISH_BOOK_NAMES[selectedBookForChaptersView] || ''} ${initialChapter}`,\n );\n\n // Reset scroll position to top, except when viewing the currently selected book\n setTimeout(() => {\n if (commandListRef.current) {\n if (isCurrentlySelectedBook) {\n // Scroll to the currently selected chapter\n const targetElement = chapterRefs.current[scrRef.chapterNum];\n if (targetElement) {\n targetElement.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n } else {\n // Reset to top for other books\n commandListRef.current.scrollTo({ top: 0 });\n }\n }\n\n // Ensure Command component has focus for keyboard navigation\n if (commandRef.current) {\n commandRef.current.focus();\n }\n }, 0);\n }\n }, [viewMode, selectedBookForChaptersView, topMatch, scrRef.book, scrRef.chapterNum]);\n\n // Auto-scroll to appropriate verse\n useLayoutEffect(() => {\n if (\n viewMode === 'verses' &&\n selectedBookForVersesView &&\n selectedChapterForVersesView !== undefined\n ) {\n const isCurrentlySelectedChapter =\n selectedBookForVersesView === scrRef.book &&\n selectedChapterForVersesView === scrRef.chapterNum;\n const initialVerse = isCurrentlySelectedChapter ? scrRef.verseNum : 1;\n\n // Seed commandValue so arrow-key navigation has a concrete starting verse and cmdk\n // highlights it when focus is pinned on the PopoverContent wrapper (modal FocusScope).\n // Format must match VerseGrid's CommandItem `value`.\n setCommandValue(\n `${selectedBookForVersesView} ${ALL_ENGLISH_BOOK_NAMES[selectedBookForVersesView] || ''} ${selectedChapterForVersesView}:${initialVerse}`,\n );\n\n setTimeout(() => {\n if (commandListRef.current) {\n if (isCurrentlySelectedChapter) {\n const targetElement = verseRefs.current[scrRef.verseNum];\n if (targetElement) {\n targetElement.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n } else {\n commandListRef.current.scrollTo({ top: 0 });\n }\n }\n if (commandRef.current) {\n commandRef.current.focus();\n }\n }, 0);\n }\n }, [\n viewMode,\n selectedBookForVersesView,\n selectedChapterForVersesView,\n scrRef.book,\n scrRef.chapterNum,\n scrRef.verseNum,\n ]);\n\n // #endregion\n\n return (\n \n \n {\n // When `onPointerDownOutside` detected our trigger was clicked while the\n // popover was open, it already closed the popover and set this flag. Without\n // this guard, the click event reaches Radix's `onOpenToggle` which sees\n // `open=false` (we already closed it) and toggles it back to `true`, causing\n // the reopen. `event.preventDefault()` makes `composeEventHandlers` skip\n // `onOpenToggle` so the popover stays closed.\n if (justClosedByTriggerRef.current) {\n justClosedByTriggerRef.current = false;\n event.preventDefault();\n }\n }}\n >\n {triggerContent ?? {currentDisplayValue}}\n \n \n event.stopPropagation()}\n // Close-on-trigger-click while open: Radix's built-in DismissableLayer prevents\n // dismissal when the pointer target is the trigger (it treats that as \"user intends\n // to toggle, let the trigger's own onClick handle it\"). But in our controlled\n // Popover the trigger's `onOpenToggle` calls `onOpenChange(!open)` — by the time\n // the click fires, React may have already re-rendered with `open=false` (from a\n // prior close), so `!open = true` and the popover reopens. We intercept here:\n // close the popover early (before Radix's own dismiss path) and set\n // `justClosedByTriggerRef` so the trigger's `onClick` can call `preventDefault()`\n // which makes Radix's `composeEventHandlers` skip `onOpenToggle` entirely.\n //\n // Guard with `isCommandOpen`: PopoverContent stays mounted during the fade-out\n // animation after close, so this handler still fires for trigger clicks made while\n // the popover is animating out. Treating those as \"close\" would set the\n // `justClosedByTriggerRef` interlock and block the legitimate reopen click. Only\n // intercept when the popover is logically open.\n onPointerDownOutside={(event) => {\n const { target } = event;\n if (\n isCommandOpen &&\n triggerRef.current &&\n target instanceof Node &&\n triggerRef.current.contains(target)\n ) {\n // Mark that we're closing due to a trigger click so the subsequent `click`\n // event on the button (which would reopen the popover via Radix's\n // `onOpenToggle`) can be blocked. See `justClosedByTriggerRef`.\n justClosedByTriggerRef.current = true;\n handleOpenChange(false);\n }\n }}\n onCloseAutoFocus={onCloseAutoFocus}\n >\n \n {/* Header: Input (with quick nav buttons) for book view, fixed header for chapter view */}\n {viewMode === 'books' ? (\n
\n
\n setIsCommandListHidden(false)}\n className={recentSearches && recentSearches.length > 0 ? 'tw:!pr-10' : ''}\n />\n {recentSearches && recentSearches.length > 0 && (\n formatScrRef(verseRef, 'English')}\n getItemKey={(verseRef) =>\n `${verseRef.book}-${verseRef.chapterNum}-${verseRef.verseNum}`\n }\n ariaLabel={localizedStrings?.['%history_recentSearches_ariaLabel%']}\n groupHeading={localizedStrings?.['%history_recent%']}\n />\n )}\n
\n {/* Navigation buttons for previous/next chapter/book */}\n
\n {quickNavButtons.map(\n ({ onClick, disabled: isQuickNavDisabled, title, icon: Icon }) => (\n {\n setIsCommandListHidden(true);\n onClick();\n }}\n disabled={isQuickNavDisabled}\n className=\"tw:h-10 tw:w-4 tw:p-0\"\n title={title}\n onKeyDown={handleQuickNavButtonKeyDown}\n >\n \n \n ),\n )}\n
\n
\n ) : (\n
\n \n {direction === 'ltr' ? (\n \n ) : (\n \n )}\n \n {viewMode === 'chapters' && selectedBookForChaptersView && (\n \n {getLocalizedBookName(selectedBookForChaptersView, localizedBookNames)}\n \n )}\n {viewMode === 'verses' &&\n selectedBookForVersesView &&\n selectedChapterForVersesView !== undefined && (\n \n {`${getLocalizedBookName(selectedBookForVersesView, localizedBookNames)} ${selectedChapterForVersesView}`}\n \n )}\n \n {viewMode === 'verses' ? selectVerseTitle : selectChapterTitle}\n \n
\n )}\n\n {/** Body */}\n {!isCommandListHidden && (\n \n {/** Book list mode (also used in case of top matches) */}\n {viewMode === 'books' && (\n <>\n {/* Book List - Show when we don't have a top match */}\n {!topMatch &&\n Object.entries(filteredBooksByType).map(([type, books]) => {\n if (books.length === 0) return undefined;\n\n return (\n // We are mapping over filteredBooksByType, which uses Section as key type\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n \n {books.map((bookId) => (\n \n handleBookSelect(selectedBookId)\n }\n section={getSectionForBook(bookId)}\n commandValue={`${bookId} ${ALL_ENGLISH_BOOK_NAMES[bookId]}`}\n ref={bookId === scrRef.book ? selectedBookItemRef : undefined}\n localizedBookNames={localizedBookNames}\n disabled={isBookDisabled(bookId)}\n />\n ))}\n \n );\n })}\n\n {/* Top match scripture reference */}\n {topMatch && (\n \n \n {formatScrRef(\n {\n book: topMatch.book,\n chapterNum: topMatch.chapterNum ?? 1,\n verseNum: topMatch.verseNum ?? 1,\n },\n localizedBookNames\n ? getLocalizedBookId(topMatch.book, localizedBookNames)\n : undefined,\n )}\n \n \n )}\n\n {/* Verse selector - when chapter-verse separator is present in the input */}\n {topMatch &&\n shouldShowVerseGridForTopMatch &&\n topMatch.chapterNum &&\n getEndVerse && (\n <>\n
\n \n {`${getLocalizedBookName(topMatch.book, localizedBookNames)} ${topMatch.chapterNum}`}\n \n {selectVerseTitle}\n
\n \n \n )}\n\n {/* Chapter Selector - Show when we have a top match without a verse separator */}\n {topMatch &&\n !shouldShowVerseGridForTopMatch &&\n fetchEndChapter(topMatch.book) > 1 && (\n <>\n
\n {getLocalizedBookName(topMatch.book, localizedBookNames)}\n {selectChapterTitle}\n
\n \n \n )}\n \n )}\n\n {/* Basic chapter view mode */}\n {viewMode === 'chapters' && selectedBookForChaptersView && (\n \n )}\n\n {/* Verse view mode */}\n {viewMode === 'verses' &&\n selectedBookForVersesView &&\n selectedChapterForVersesView !== undefined &&\n getEndVerse && (\n \n )}\n
\n )}\n \n \n
\n );\n}\n\nexport default BookChapterControl;\n","import { SerializedVerseRef } from '@sillsdev/scripture';\nimport { LanguageStrings } from 'platform-bible-utils';\nimport { ComponentPropsWithoutRef, ReactNode, Ref } from 'react';\nimport { ButtonProps } from '@/components/shadcn-ui/button';\nimport { Popover as PopoverPrimitive } from 'radix-ui';\n\n/**\n * Object containing all keys used for localization in the BookChapterControl component. If you're\n * using this component in an extension, you can pass it into the useLocalizedStrings hook to easily\n * obtain the localized strings and pass them into the localizedStrings prop of this component\n */\nexport const BOOK_CHAPTER_CONTROL_STRING_KEYS = Object.freeze([\n '%scripture_section_ot_long%',\n '%scripture_section_nt_long%',\n '%scripture_section_dc_long%',\n '%scripture_section_extra_long%',\n '%history_recent%',\n '%history_recentSearches_ariaLabel%',\n '%webView_bookChapterControl_selectChapter%',\n '%webView_bookChapterControl_selectVerse%',\n] as const);\n\n/** Type definition for the localized strings used in the BookChapterControl component */\nexport type BookChapterControlLocalizedStrings = {\n [localizedKey in (typeof BOOK_CHAPTER_CONTROL_STRING_KEYS)[number]]?: string;\n};\n\nexport type BookWithOptionalChapterAndVerse = Omit &\n Partial>;\n\nexport type ViewMode = 'books' | 'chapters' | 'verses';\n\n/**\n * Imperative handle for controlling a {@link BookChapterControl} from outside React — e.g. the\n * `platform.openBookChapterControl` command opening it in response to Ctrl+B\n *\n * @experimental This export is unstable and may change shape or disappear without notice\n */\nexport type BookChapterControlHandle = {\n /**\n * Opens the reference dropdown and focuses its search input, ready for typing. No-op while the\n * control is disabled.\n */\n open: () => void;\n};\n\nexport type BookChapterControlProps = {\n /** The current scripture reference */\n scrRef: SerializedVerseRef;\n /** Callback to handle the submission of a selected reference */\n handleSubmit: (scrRef: SerializedVerseRef) => void;\n /** Optional additional class name for styling */\n className?: string;\n /** Callback to retrieve book IDs that are available in the current context */\n getActiveBookIds?: () => string[];\n /**\n * Optional map of localized book IDs/short names and full names. The key is the standard book ID\n * (e.g., \"2CH\"), the value contains a localized version of the ID and related book name (e.g. {\n * localizedId: '2CR', localizedName: '2 Crónicas' })\n */\n localizedBookNames?: Map;\n /** Optional localized strings for the component */\n localizedStrings?: LanguageStrings;\n /** Array of recent scripture references for quick access */\n recentSearches?: SerializedVerseRef[];\n /** Callback to add a new recent scripture reference */\n onAddRecentSearch?: (scrRef: SerializedVerseRef) => void;\n /** Optional ID for the popover content for accessibility */\n id?: string;\n /**\n * Optional callback returning the number of verses for a given book and chapter. When provided,\n * the control enables verse selection: clicking a chapter transitions to a verse selection\n * sub-screen, and typing a reference with a chapter:verse separator shows a verse grid. When\n * omitted, the control selects `verseNum: 1` after a chapter is chosen (current behavior).\n */\n getEndVerse?: (bookId: string, chapterNum: number) => number;\n /**\n * Optional lower bound. When provided, any reference that comes strictly before this one in canon\n * order is disabled in the UI (books, chapters, and verses). Used to prevent selecting an \"end\"\n * reference that precedes a \"start\" reference (e.g., in a range picker).\n */\n disableReferencesUpTo?: SerializedVerseRef;\n /**\n * Optional list of extra keys that submit the currently-matched reference from the search input\n * (in addition to `Enter`, which always submits). When one of these keys is pressed while the\n * typed input resolves to a valid top-match reference, that match is submitted and the key is\n * consumed (not inserted into the input). Intended for flows where a \"separator\" keystroke\n * implies completion — e.g. a range picker that uses space or `-` to confirm the start of a range\n * and advance to the end.\n */\n submitKeys?: readonly string[];\n /**\n * Optional override for the contents of the trigger button. When provided, this replaces the\n * default current-reference label (`\"MAT 5:3\"`) rendered inside the button — useful when the\n * current reference is already shown elsewhere and the trigger only needs an icon (e.g. an inline\n * \"change reference\" affordance). The Button itself is still the PopoverTrigger; only its inner\n * content is swapped.\n */\n triggerContent?: ReactNode;\n /**\n * Optional Button variant applied to the trigger. Defaults to `\"outline\"` (the standard inline\n * picker look); pass `\"ghost\"` when the control is embedded in a menu / list where a bordered\n * button would feel out of place.\n */\n triggerVariant?: ButtonProps['variant'];\n /**\n * Optional callback fired whenever the control's popover open state changes. Useful when the\n * parent needs to react to the picker opening or closing — e.g. dimming a sibling control while\n * this one is active. Internal back-navigation within the popover (verses → chapters → books)\n * does not toggle this: only true open/close transitions do.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * Optional handler forwarded to the underlying Radix `Popover.Content`. Fires as the popover\n * closes and decides where focus should land next — by default Radix returns focus to the trigger\n * button. Call `event.preventDefault()` and focus a different element when the trigger isn't the\n * right landing spot (e.g. the picker is nested inside a DropdownMenuItem and focus should return\n * to the menu item so arrow-key navigation continues to work).\n */\n onCloseAutoFocus?: ComponentPropsWithoutRef['onCloseAutoFocus'];\n /**\n * Optional flag forwarded to the underlying Radix `Popover.Root`. Defaults to `false`. Set to\n * `true` when the control is opened from inside another focus-trapping primitive (a Radix Dialog\n * or DropdownMenu) — the transient focus blip that happens when the picker transitions between\n * book/chapter/verse views would otherwise collide with the outer scope's focus trap and dismiss\n * the popover. Modal mode gives the popover its own FocusScope that pauses the outer scope while\n * it's open, avoiding the collision.\n */\n modal?: boolean;\n /**\n * Optional alignment for the popover relative to its trigger along the cross-axis. Forwarded to\n * the underlying Radix `Popover.Content`. Defaults to `\"center\"`. Use `\"start\"` when the control\n * sits on the right edge of a constrained container (e.g. the second picker in a range dialog) to\n * keep the popover anchored to the trigger's leading edge rather than spilling off-screen.\n */\n align?: ComponentPropsWithoutRef['align'];\n /**\n * Ref that receives a {@link BookChapterControlHandle} for imperative control\n *\n * @experimental This property is unstable and may change shape or disappear without notice\n */\n ref?: Ref;\n /**\n * When true, the control is disabled (e.g. no target to navigate): the trigger button cannot be\n * clicked, an already-open dropdown closes, and the imperative\n * {@link BookChapterControlHandle.open} is a no-op\n */\n disabled?: boolean;\n};\n","'use client';\n\nimport React from 'react';\nimport { RadioGroup as RadioGroupPrimitive } from 'radix-ui';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\n// CUSTOM: Import direction helper for RTL support\nimport { Direction, readDirection } from '@/utils/dir-helper.util';\n\n/**\n * Radio Group components providing a set of checkable buttons—known as radio buttons—where no more\n * than one of the buttons can be checked at a time. These components are built on Radix UI\n * primitives and styled with Shadcn UI.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/radio-group}\n * @see Radix UI Documentation:\n * {@link https://www.radix-ui.com/primitives/docs/components/radio-group}\n */\nfunction RadioGroup({\n className,\n ...props\n}: React.ComponentProps) {\n // CUSTOM: Read document direction to support RTL layouts\n const dir: Direction = readDirection();\n return (\n \n );\n}\n\n/** @inheritdoc RadioGroup */\nfunction RadioGroupItem({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nexport { RadioGroup, RadioGroupItem };\n","import { type CSSProperties, type ComponentProps, ReactNode, useState } from 'react';\nimport { Check, ChevronDown } from 'lucide-react';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Button, ButtonProps } from '@/components/shadcn-ui/button';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/shadcn-ui/popover';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/components/shadcn-ui/command';\n\nexport type ComboBoxLabelOption = { label: string; secondaryLabel?: string };\nexport type ComboBoxOption = string | number | ComboBoxLabelOption;\n\n/** Represents a group of options with an optional heading */\nexport type ComboBoxGroup = {\n /** The heading text for this group of options */\n groupHeading: string;\n /** The options within this group */\n options: readonly T[];\n};\n\nexport type ComboBoxProps = {\n /** Optional unique identifier */\n id?: string;\n /**\n * List of available options for the dropdown menu. Can be either:\n *\n * - A flat array of options (single group, no heading)\n * - An array of group objects. Each group has a heading and an array of options\n */\n options?: readonly T[] | readonly ComboBoxGroup[];\n /** @deprecated 3 December 2024. Renamed to `buttonClassName` */\n className?: string;\n /** Additional css classes to help with unique styling of the combo box button */\n buttonClassName?: string;\n /** Additional css classes to help with unique styling of the combo box popover */\n popoverContentClassName?: string;\n /**\n * Additional inline styles for the combo box popover. Use for z-index overrides instead of\n * className to avoid being overridden by PopoverContent's inline default z-index.\n */\n popoverContentStyle?: CSSProperties;\n /**\n * The selected value that the combo box currently holds. Must be shallow equal to one of the\n * options entries.\n */\n value?: T;\n /** Triggers when content of textfield is changed */\n onChange?: (newValue: T) => void;\n /** Used to determine the string value for a given option. */\n getOptionLabel?: (option: T) => string;\n /**\n * Used to determine the string value to display on the button for the selected value. If not\n * provided, falls back to `getOptionLabel`.\n */\n getButtonLabel?: (option: T) => string;\n /** Icon to be displayed on the trigger */\n icon?: ReactNode;\n /** Text displayed on button if `value` is undefined */\n buttonPlaceholder?: string;\n /** Placeholder text for text field */\n textPlaceholder?: string;\n /** Text to display when no options match input */\n commandEmptyMessage?: string;\n /** Variant of button */\n buttonVariant?: ButtonProps['variant'];\n /** Control how the popover menu should be aligned. Defaults to start */\n alignDropDown?: 'start' | 'center' | 'end';\n /** Optional boolean to set if trigger should be disabled */\n isDisabled?: boolean;\n /** Optional aria-label for the trigger button for accessibility */\n ariaLabel?: string;\n} & ComponentProps;\n\nfunction getOptionLabelDefault(option: ComboBoxOption): string {\n if (typeof option === 'string') {\n return option;\n }\n if (typeof option === 'number') {\n return option.toString();\n }\n return option.label;\n}\n\n/**\n * Autocomplete input and command palette with a list of suggestions.\n *\n * Thanks to Shadcn for heavy inspiration and documentation\n * https://ui.shadcn.com/docs/components/combobox\n */\nexport function ComboBox({\n id,\n options = [],\n className,\n buttonClassName,\n popoverContentClassName,\n popoverContentStyle,\n value,\n onChange = () => {},\n getOptionLabel = getOptionLabelDefault,\n getButtonLabel,\n icon = undefined,\n buttonPlaceholder = '',\n textPlaceholder = '',\n commandEmptyMessage = 'No option found',\n buttonVariant = 'outline',\n alignDropDown = 'start',\n isDisabled = false,\n ariaLabel,\n ...props\n}: ComboBoxProps) {\n const [open, setOpen] = useState(false);\n\n const buttonLabel = getButtonLabel ?? getOptionLabel;\n\n const isGroupedOptions = (\n groupOptions: readonly T[] | readonly ComboBoxGroup[],\n ): groupOptions is readonly ComboBoxGroup[] => {\n return Boolean(\n groupOptions.length > 0 &&\n typeof groupOptions[0] === 'object' &&\n 'options' in groupOptions[0],\n );\n };\n\n const renderCommandItem = (option: T, groupHeading?: string) => {\n const optionLabel = getOptionLabel(option);\n const secondaryLabel =\n typeof option === 'object' && 'secondaryLabel' in option ? option.secondaryLabel : undefined;\n\n const key = `${groupHeading ?? ''}${optionLabel}${secondaryLabel ?? ''}`;\n\n return (\n {\n onChange(option);\n setOpen(false);\n }}\n className=\"tw:gap-1.5!\"\n >\n \n \n {optionLabel}\n {secondaryLabel && · {secondaryLabel}}\n \n \n );\n };\n\n return (\n \n \n \n
\n {icon &&
{icon}
}\n \n {value ? buttonLabel(value) : buttonPlaceholder}\n \n
\n\n \n \n
\n \n \n \n {commandEmptyMessage}\n \n {isGroupedOptions(options) ? (\n options.map((group) => (\n \n {group.options.map((option) => renderCommandItem(option, group.groupHeading))}\n \n ))\n ) : (\n {options.map((option) => renderCommandItem(option))}\n )}\n \n \n \n
\n );\n}\n\nexport default ComboBox;\n","import { ComboBox } from '@/components/basics/combo-box.component';\nimport { Label } from '@/components/shadcn-ui/label';\nimport { useMemo } from 'react';\n\nexport type ChapterRangeSelectorProps = {\n /** The selected start chapter */\n startChapter: number;\n /** The selected end chapter */\n endChapter: number;\n /** Callback function to handle the selection of the start chapter */\n handleSelectStartChapter: (chapter: number) => void;\n /** Callback function to handle the selection of the end chapter */\n handleSelectEndChapter: (chapter: number) => void;\n /** Flag to disable the component */\n isDisabled?: boolean;\n /** The total number of chapters available */\n chapterCount: number;\n};\n\n/**\n * ChapterRangeSelector is a component that provides a UI for selecting a range of chapters. It\n * consists of two combo boxes for selecting the start and end chapters. The component ensures that\n * the selected start chapter is always less than or equal to the end chapter, and vice versa.\n *\n * @deprecated Jul 18 2025. This component is no longer supported or tested. Use of this component\n * is discouraged and it may be removed in the future.\n * @param {ChapterRangeSelectorProps} props - The props for the component.\n */\n\nexport function ChapterRangeSelector({\n startChapter,\n endChapter,\n handleSelectStartChapter,\n handleSelectEndChapter,\n isDisabled = false,\n chapterCount,\n}: ChapterRangeSelectorProps) {\n const chapterOptions = useMemo(\n () => Array.from({ length: chapterCount }, (_, index) => index + 1),\n [chapterCount],\n );\n\n const onChangeStartChapter = (value: number) => {\n handleSelectStartChapter(value);\n if (value > endChapter) {\n handleSelectEndChapter(value);\n }\n };\n\n const onChangeEndChapter = (value: number) => {\n handleSelectEndChapter(value);\n if (value < startChapter) {\n handleSelectStartChapter(value);\n }\n };\n\n return (\n <>\n \n option.toString()}\n value={startChapter}\n />\n\n \n option.toString()}\n value={endChapter}\n />\n \n );\n}\n\nexport default ChapterRangeSelector;\n","import { Button } from '@/components/shadcn-ui/button';\nimport { Label } from '@/components/shadcn-ui/label';\nimport { RadioGroup, RadioGroupItem } from '@/components/shadcn-ui/radio-group';\nimport { Canon } from '@sillsdev/scripture';\nimport { LocalizedStringValue } from 'platform-bible-utils';\nimport { useState } from 'react';\nimport {\n ChapterRangeSelector,\n ChapterRangeSelectorProps,\n} from '../basics/chapter-range-selector.component';\n\n/** Enumeration of possible book selection modes */\nexport enum BookSelectionMode {\n CurrentBook = 'current book',\n ChooseBooks = 'choose books',\n}\n\nexport namespace BookSelectionMode {\n /** @deprecated Use BookSelectionMode.CurrentBook instead. */\n export const CURRENT_BOOK: BookSelectionMode = BookSelectionMode.CurrentBook;\n /** @deprecated Use BookSelectionMode.ChooseBooks instead. */\n export const CHOOSE_BOOKS: BookSelectionMode = BookSelectionMode.ChooseBooks;\n}\n\n/**\n * Object containing all keys used for localization in this component. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component\n */\nexport const BOOK_SELECTOR_STRING_KEYS = Object.freeze([\n '%webView_bookSelector_currentBook%',\n '%webView_bookSelector_choose%',\n '%webView_bookSelector_chooseBooks%',\n] as const);\n\nexport type BookSelectorLocalizedStrings = {\n [localizedBookSelectorKey in (typeof BOOK_SELECTOR_STRING_KEYS)[number]]?: LocalizedStringValue;\n};\n\n/**\n * Gets the localized value for the provided key\n *\n * @param strings Object containing localized string\n * @param key Key for a localized string\n * @returns The localized value for the provided key, if available. Returns the key if no localized\n * value is available\n */\nconst localizeString = (\n strings: BookSelectorLocalizedStrings,\n key: keyof BookSelectorLocalizedStrings,\n) => {\n return strings[key] ?? key;\n};\n\ntype BookSelectorProps = ChapterRangeSelectorProps & {\n handleBookSelectionModeChange: (newMode: BookSelectionMode) => void;\n currentBookName: string;\n onSelectBooks: () => void;\n selectedBookIds: string[];\n localizedStrings: BookSelectorLocalizedStrings;\n};\n\n/**\n * BookSelector is a component that provides an interactive UI for selecting books. It can be set to\n * either allow the user to select a single book or to choose multiple books. In the former case, it\n * will display the range of chapters in the selected book, and in the latter case it will display a\n * list of the selected books.\n *\n * @deprecated Jul 18 2025. This component is no longer supported or tested and will be removed in a\n * later version. To let users select books, use the `SelectBooks` component instead (or\n * `ScopeSelector` to combine scope and book selection).\n * @param {BookSelectorProps} props\n * @param {function} props.handleBookSelectionModeChange - Callback function to handle changes in\n * book selection mode.\n * @param {string} props.currentBookName - The name of the currently selected book.\n * @param {function} props.onSelectBooks - Callback function to handle book selection.\n * @param {string[]} props.selectedBookIds - An array of book IDs that have been selected.\n * @param {BookSelectorLocalizedStrings} props.localizedStrings - Object containing localized\n * strings for the component.\n */\nexport function BookSelector({\n handleBookSelectionModeChange,\n currentBookName,\n onSelectBooks,\n selectedBookIds,\n chapterCount,\n endChapter,\n handleSelectEndChapter,\n startChapter,\n handleSelectStartChapter,\n localizedStrings,\n}: BookSelectorProps) {\n const currentBookText = localizeString(localizedStrings, '%webView_bookSelector_currentBook%');\n const chooseText = localizeString(localizedStrings, '%webView_bookSelector_choose%');\n const chooseBooksText = localizeString(localizedStrings, '%webView_bookSelector_chooseBooks%');\n\n const [bookSelectionMode, setBookSelectionMode] = useState(\n BookSelectionMode.CurrentBook,\n );\n\n const onSelectionModeChange = (newMode: BookSelectionMode) => {\n setBookSelectionMode(newMode);\n handleBookSelectionModeChange(newMode);\n };\n\n return (\n onSelectionModeChange(value as BookSelectionMode)}\n >\n
\n
\n
\n \n \n
\n \n
\n \n
\n
\n
\n
\n \n \n
\n \n onSelectBooks()}\n >\n {chooseText}\n \n
\n
\n \n );\n}\n\nexport default BookSelector;\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{createContext as n,useContext as e}from\"react\";const r=n(null);function t(n,e){let r=null;return null!=n&&(r=n[1]),{getTheme:function(){return null!=e?e:null!=r?r.getTheme():null}}}function o(){const n=e(r);return null==n&&function(n,...e){const r=new URL(\"https://lexical.dev/docs/error\"),t=new URLSearchParams;t.append(\"code\",n);for(const n of e)t.append(\"v\",n);throw r.search=t.toString(),Error(`Minified Lexical error #${n}; visit ${r.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(8),n}export{r as LexicalComposerContext,t as createLexicalComposerContext,o as useLexicalComposerContext};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{createLexicalComposerContext as e,LexicalComposerContext as t}from\"@lexical/react/LexicalComposerContext\";import{createEditor as o,$getRoot as n,$createParagraphNode as i,$getSelection as r,HISTORY_MERGE_TAG as a}from\"lexical\";import{useLayoutEffect as c,useEffect as l,useMemo as d}from\"react\";import{jsx as s}from\"react/jsx-runtime\";const m=\"undefined\"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,u=m?c:l,p={tag:a};function f({initialConfig:a,children:c}){const l=d(()=>{const{theme:t,namespace:c,nodes:l,onError:d,editorState:s,html:u}=a,f=e(null,t),E=o({editable:a.editable,html:u,namespace:c,nodes:l,onError:e=>d(e,E),theme:t});return function(e,t){if(null===t)return;if(void 0===t)e.update(()=>{const t=n();if(t.isEmpty()){const o=i();t.append(o);const n=m?document.activeElement:null;(null!==r()||null!==n&&n===e.getRootElement())&&o.select()}},p);else if(null!==t)switch(typeof t){case\"string\":{const o=e.parseEditorState(t);e.setEditorState(o,p);break}case\"object\":e.setEditorState(t,p);break;case\"function\":e.update(()=>{n().isEmpty()&&t(e)},p)}}(E,s),[E,f]},[]);return u(()=>{const e=a.editable,[t]=l;t.setEditable(void 0===e||e)},[]),s(t.Provider,{value:l,children:c})}export{f as LexicalComposer};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{useLexicalComposerContext as e}from\"@lexical/react/LexicalComposerContext\";import{HISTORY_MERGE_TAG as t}from\"lexical\";import{useLayoutEffect as o,useEffect as i}from\"react\";const r=\"undefined\"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?o:i;function n({ignoreHistoryMergeTagChange:o=!0,ignoreSelectionChange:i=!1,onChange:n}){const[a]=e();return r(()=>{if(n)return a.registerUpdateListener(({editorState:e,dirtyElements:r,dirtyLeaves:d,prevEditorState:s,tags:c})=>{i&&0===r.size&&0===d.size||o&&c.has(t)||s.isEmpty()||n(e,a,c)})},[a,o,i,n]),null}export{n as OnChangePlugin};\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure. Also,\n * modifications have been made to integrate with our codebase.\n *\n * Original file location: src/components/editor/themes/editor-theme.ts\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\nimport { EditorThemeClasses } from 'lexical';\n\nimport './editor-theme.css';\n\nexport const editorTheme: EditorThemeClasses = {\n ltr: 'tw:text-left',\n rtl: 'tw:text-right',\n heading: {\n h1: 'tw:scroll-m-20 tw:text-4xl tw:font-extrabold tw:tracking-tight tw:lg:text-5xl',\n h2: 'tw:scroll-m-20 tw:border-b tw:pb-2 tw:text-3xl tw:font-semibold tw:tracking-tight tw:first:mt-0',\n h3: 'tw:scroll-m-20 tw:text-2xl tw:font-semibold tw:tracking-tight',\n h4: 'tw:scroll-m-20 tw:text-xl tw:font-semibold tw:tracking-tight',\n h5: 'tw:scroll-m-20 tw:text-lg tw:font-semibold tw:tracking-tight',\n h6: 'tw:scroll-m-20 tw:text-base tw:font-semibold tw:tracking-tight',\n },\n paragraph: 'tw:outline-hidden',\n quote: 'tw:mt-6 tw:border-l-2 tw:pl-6 tw:italic',\n link: 'tw:text-blue-600 tw:hover:underline tw:hover:cursor-pointer',\n list: {\n checklist: 'tw:relative',\n listitem: 'tw:mx-8',\n listitemChecked:\n 'tw:relative tw:mx-2 tw:px-6 tw:list-none tw:outline-hidden tw:line-through tw:before:content-[\"\"] tw:before:w-4 tw:before:h-4 tw:before:top-0.5 tw:before:left-0 tw:before:cursor-pointer tw:before:block tw:before:bg-cover tw:before:absolute tw:before:border tw:before:border-primary tw:before:rounded tw:before:bg-primary tw:before:bg-no-repeat tw:after:content-[\"\"] tw:after:cursor-pointer tw:after:border-white tw:after:border-solid tw:after:absolute tw:after:block tw:after:top-[6px] tw:after:w-[3px] tw:after:left-[7px] tw:after:right-[7px] tw:after:h-[6px] tw:after:rotate-45 tw:after:border-r-2 tw:after:border-b-2 tw:after:border-l-0 tw:after:border-t-0',\n listitemUnchecked:\n 'tw:relative tw:mx-2 tw:px-6 tw:list-none tw:outline-hidden tw:before:content-[\"\"] tw:before:w-4 tw:before:h-4 tw:before:top-0.5 tw:before:left-0 tw:before:cursor-pointer tw:before:block tw:before:bg-cover tw:before:absolute tw:before:border tw:before:border-primary tw:before:rounded',\n nested: {\n listitem: 'tw:list-none tw:before:hidden tw:after:hidden',\n },\n ol: 'tw:m-0 tw:p-0 tw:list-decimal tw:[&>li]:mt-2',\n olDepth: [\n 'tw:list-outside tw:!list-decimal',\n 'tw:list-outside tw:!list-[upper-roman]',\n 'tw:list-outside tw:!list-[lower-roman]',\n 'tw:list-outside tw:!list-[upper-alpha]',\n 'tw:list-outside tw:!list-[lower-alpha]',\n ],\n ul: 'tw:m-0 tw:p-0 tw:list-outside tw:[&>li]:mt-2',\n ulDepth: [\n 'tw:list-outside tw:!list-disc',\n 'tw:list-outside tw:!list-disc',\n 'tw:list-outside tw:!list-disc',\n 'tw:list-outside tw:!list-disc',\n 'tw:list-outside tw:!list-disc',\n ],\n },\n hashtag: 'tw:text-blue-600 tw:bg-blue-100 tw:rounded-md tw:px-1',\n text: {\n bold: 'tw:font-bold',\n code: 'tw:bg-gray-100 tw:p-1 tw:rounded-md',\n italic: 'tw:italic',\n strikethrough: 'tw:line-through',\n subscript: 'tw:sub',\n superscript: 'tw:sup',\n underline: 'tw:underline',\n underlineStrikethrough: 'tw:underline tw:line-through',\n },\n image: 'tw:relative tw:inline-block tw:user-select-none tw:cursor-default editor-image',\n inlineImage:\n 'tw:relative tw:inline-block tw:user-select-none tw:cursor-default inline-editor-image',\n keyword: 'tw:text-purple-900 tw:font-bold',\n code: 'EditorTheme__code',\n codeHighlight: {\n atrule: 'EditorTheme__tokenAttr',\n attr: 'EditorTheme__tokenAttr',\n boolean: 'EditorTheme__tokenProperty',\n builtin: 'EditorTheme__tokenSelector',\n cdata: 'EditorTheme__tokenComment',\n char: 'EditorTheme__tokenSelector',\n class: 'EditorTheme__tokenFunction',\n 'class-name': 'EditorTheme__tokenFunction',\n comment: 'EditorTheme__tokenComment',\n constant: 'EditorTheme__tokenProperty',\n deleted: 'EditorTheme__tokenProperty',\n doctype: 'EditorTheme__tokenComment',\n entity: 'EditorTheme__tokenOperator',\n function: 'EditorTheme__tokenFunction',\n important: 'EditorTheme__tokenVariable',\n inserted: 'EditorTheme__tokenSelector',\n keyword: 'EditorTheme__tokenAttr',\n namespace: 'EditorTheme__tokenVariable',\n number: 'EditorTheme__tokenProperty',\n operator: 'EditorTheme__tokenOperator',\n prolog: 'EditorTheme__tokenComment',\n property: 'EditorTheme__tokenProperty',\n punctuation: 'EditorTheme__tokenPunctuation',\n regex: 'EditorTheme__tokenVariable',\n selector: 'EditorTheme__tokenSelector',\n string: 'EditorTheme__tokenSelector',\n symbol: 'EditorTheme__tokenProperty',\n tag: 'EditorTheme__tokenProperty',\n url: 'EditorTheme__tokenOperator',\n variable: 'EditorTheme__tokenVariable',\n },\n characterLimit: 'tw:!bg-destructive/50',\n table: 'EditorTheme__table tw:w-fit tw:overflow-scroll tw:border-collapse',\n tableCell:\n 'EditorTheme__tableCell tw:w-24 tw:relative tw:border tw:px-4 tw:py-2 tw:text-left tw:[&[align=center]]:text-center tw:[&[align=right]]:text-right',\n tableCellActionButton:\n 'EditorTheme__tableCellActionButton tw:bg-background tw:block tw:border-0 tw:rounded-2xl tw:w-5 tw:h-5 tw:text-foreground tw:cursor-pointer',\n tableCellActionButtonContainer:\n 'EditorTheme__tableCellActionButtonContainer tw:block tw:right-1 tw:top-1.5 tw:absolute tw:z-10 tw:w-5 tw:h-5',\n tableCellEditing: 'EditorTheme__tableCellEditing tw:rounded-sm tw:shadow-sm',\n tableCellHeader:\n 'EditorTheme__tableCellHeader tw:bg-muted tw:border tw:px-4 tw:py-2 tw:text-left tw:font-bold tw:[&[align=center]]:text-center tw:[&[align=right]]:text-right',\n tableCellPrimarySelected:\n 'EditorTheme__tableCellPrimarySelected tw:border tw:border-primary tw:border-solid tw:block tw:h-[calc(100%-2px)] tw:w-[calc(100%-2px)] tw:absolute tw:-left-[1px] tw:-top-[1px] tw:z-10 ',\n tableCellResizer:\n 'EditorTheme__tableCellResizer tw:absolute tw:-right-1 tw:h-full tw:w-2 tw:cursor-ew-resize tw:z-10 tw:top-0',\n tableCellSelected: 'EditorTheme__tableCellSelected tw:bg-muted',\n tableCellSortedIndicator:\n 'EditorTheme__tableCellSortedIndicator tw:block tw:opacity-50 tw:absolute tw:bottom-0 tw:left-0 tw:w-full tw:h-1 tw:bg-muted',\n tableResizeRuler:\n 'EditorTheme__tableCellResizeRuler tw:block tw:absolute tw:w-[1px] tw:h-full tw:bg-primary tw:top-0',\n tableRowStriping: 'EditorTheme__tableRowStriping tw:m-0 tw:border-t tw:p-0 tw:even:bg-muted',\n tableSelected: 'EditorTheme__tableSelected tw:ring-2 tw:ring-primary tw:ring-offset-2',\n tableSelection: 'EditorTheme__tableSelection tw:bg-transparent',\n layoutItem: 'tw:border tw:border-dashed tw:px-4 tw:py-2',\n layoutContainer: 'tw:grid tw:gap-2.5 tw:my-2.5 tw:mx-0',\n autocomplete: 'tw:text-muted-foreground',\n blockCursor: '',\n embedBlock: {\n base: 'tw:user-select-none',\n focus: 'tw:ring-2 tw:ring-primary tw:ring-offset-2',\n },\n hr: 'tw:p-0.5 tw:border-none tw:my-1 tw:mx-0 tw:cursor-pointer tw:after:content-[\"\"] tw:after:block tw:after:h-0.5 tw:after:bg-muted tw:selected:ring-2 tw:selected:ring-primary tw:selected:ring-offset-2 tw:selected:user-select-none',\n indent: '[--lexical-indent-base-value:40px]',\n mark: '',\n markOverlap: '',\n};\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure.\n *\n * Original file location: src/components/blocks/editor-00/nodes.ts\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\nimport { HeadingNode, QuoteNode } from '@lexical/rich-text';\nimport { Klass, LexicalNode, LexicalNodeReplacement, ParagraphNode, TextNode } from 'lexical';\n\nexport const nodes: ReadonlyArray | LexicalNodeReplacement> = [\n HeadingNode,\n ParagraphNode,\n TextNode,\n QuoteNode,\n];\n","'use client';\nimport { createContext, Component, createElement, useContext, useState, useMemo, forwardRef } from 'react';\n\nconst ErrorBoundaryContext = createContext(null);\n\nconst initialState = {\n didCatch: false,\n error: null\n};\nclass ErrorBoundary extends Component {\n constructor(props) {\n super(props);\n this.resetErrorBoundary = this.resetErrorBoundary.bind(this);\n this.state = initialState;\n }\n static getDerivedStateFromError(error) {\n return {\n didCatch: true,\n error\n };\n }\n resetErrorBoundary() {\n const {\n error\n } = this.state;\n if (error !== null) {\n var _this$props$onReset, _this$props;\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n (_this$props$onReset = (_this$props = this.props).onReset) === null || _this$props$onReset === void 0 ? void 0 : _this$props$onReset.call(_this$props, {\n args,\n reason: \"imperative-api\"\n });\n this.setState(initialState);\n }\n }\n componentDidCatch(error, info) {\n var _this$props$onError, _this$props2;\n (_this$props$onError = (_this$props2 = this.props).onError) === null || _this$props$onError === void 0 ? void 0 : _this$props$onError.call(_this$props2, error, info);\n }\n componentDidUpdate(prevProps, prevState) {\n const {\n didCatch\n } = this.state;\n const {\n resetKeys\n } = this.props;\n\n // There's an edge case where if the thing that triggered the error happens to *also* be in the resetKeys array,\n // we'd end up resetting the error boundary immediately.\n // This would likely trigger a second error to be thrown.\n // So we make sure that we don't check the resetKeys on the first call of cDU after the error is set.\n\n if (didCatch && prevState.error !== null && hasArrayChanged(prevProps.resetKeys, resetKeys)) {\n var _this$props$onReset2, _this$props3;\n (_this$props$onReset2 = (_this$props3 = this.props).onReset) === null || _this$props$onReset2 === void 0 ? void 0 : _this$props$onReset2.call(_this$props3, {\n next: resetKeys,\n prev: prevProps.resetKeys,\n reason: \"keys\"\n });\n this.setState(initialState);\n }\n }\n render() {\n const {\n children,\n fallbackRender,\n FallbackComponent,\n fallback\n } = this.props;\n const {\n didCatch,\n error\n } = this.state;\n let childToRender = children;\n if (didCatch) {\n const props = {\n error,\n resetErrorBoundary: this.resetErrorBoundary\n };\n if (typeof fallbackRender === \"function\") {\n childToRender = fallbackRender(props);\n } else if (FallbackComponent) {\n childToRender = createElement(FallbackComponent, props);\n } else if (fallback !== undefined) {\n childToRender = fallback;\n } else {\n throw error;\n }\n }\n return createElement(ErrorBoundaryContext.Provider, {\n value: {\n didCatch,\n error,\n resetErrorBoundary: this.resetErrorBoundary\n }\n }, childToRender);\n }\n}\nfunction hasArrayChanged() {\n let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n return a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]));\n}\n\nfunction assertErrorBoundaryContext(value) {\n if (value == null || typeof value.didCatch !== \"boolean\" || typeof value.resetErrorBoundary !== \"function\") {\n throw new Error(\"ErrorBoundaryContext not found\");\n }\n}\n\nfunction useErrorBoundary() {\n const context = useContext(ErrorBoundaryContext);\n assertErrorBoundaryContext(context);\n const [state, setState] = useState({\n error: null,\n hasError: false\n });\n const memoized = useMemo(() => ({\n resetBoundary: () => {\n context.resetErrorBoundary();\n setState({\n error: null,\n hasError: false\n });\n },\n showBoundary: error => setState({\n error,\n hasError: true\n })\n }), [context.resetErrorBoundary]);\n if (state.hasError) {\n throw state.error;\n }\n return memoized;\n}\n\nfunction withErrorBoundary(component, errorBoundaryProps) {\n const Wrapped = forwardRef((props, ref) => createElement(ErrorBoundary, errorBoundaryProps, createElement(component, {\n ...props,\n ref\n })));\n\n // Format for display in DevTools\n const name = component.displayName || component.name || \"Unknown\";\n Wrapped.displayName = \"withErrorBoundary(\".concat(name, \")\");\n return Wrapped;\n}\n\nexport { ErrorBoundary, ErrorBoundaryContext, useErrorBoundary, withErrorBoundary };\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{ErrorBoundary as r}from\"react-error-boundary\";import{jsx as o}from\"react/jsx-runtime\";function n({children:n,onError:e}){return o(r,{fallback:o(\"div\",{style:{border:\"1px solid #f00\",color:\"#f00\",padding:\"8px\"},children:\"An error was thrown.\"}),onError:e,children:n})}export{n as LexicalErrorBoundary};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{useLexicalComposerContext as e}from\"@lexical/react/LexicalComposerContext\";import{useLayoutEffect as n,useEffect as t,useMemo as i,useState as r,useRef as o}from\"react\";const c=\"undefined\"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?n:t;function u(e){return{initialValueFn:()=>e.isEditable(),subscribe:n=>e.registerEditableListener(n)}}function a(){return function(n){const[t]=e(),u=i(()=>n(t),[t,n]),[a,l]=r(()=>u.initialValueFn()),d=o(a);return c(()=>{const{initialValueFn:e,subscribe:n}=u,t=e();return d.current!==t&&(d.current=t,l(t)),n(e=>{d.current=e,l(e)})},[u,n]),a}(u)}export{a as useLexicalEditable};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{$isTextNode as e,$getEditor as t,$isRootNode as n,$getSelection as o,$isRangeSelection as l,$caretRangeFromSelection as r,$isTokenOrSegmented as s,$isElementNode as i,$getCharacterOffsets as c,$cloneWithPropertiesEphemeral as f,$getNodeByKey as u,$getPreviousSelection as g,$createTextNode as a,$createRangeSelection as d,$findMatchingParent as p,INTERNAL_$isBlock as h,$setSelection as y,$caretFromPoint as m,$isExtendableTextPointCaret as S,$extendCaretToRange as x,$isChildCaret as T,$isDecoratorNode as N,$isRootOrShadowRoot as w,$hasAncestor as C,$isLeafNode as v}from\"lexical\";export{$cloneWithProperties,$selectAll}from\"lexical\";function K(e,...t){const n=new URL(\"https://lexical.dev/docs/error\"),o=new URLSearchParams;o.append(\"code\",e);for(const e of t)o.append(\"v\",e);throw n.search=o.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const E=new Map;function P(e){let t=e;for(;null!=t;){if(t.nodeType===Node.TEXT_NODE)return t;t=t.firstChild}return null}function k(e){const t=e.parentNode;if(null==t)throw new Error(\"Should never happen\");return[t,Array.from(t.childNodes).indexOf(e)]}function I(t,n,o,l,r){const s=n.getKey(),i=l.getKey(),c=document.createRange();let f=t.getElementByKey(s),u=t.getElementByKey(i),g=o,a=r;if(e(n)&&(f=P(f)),e(l)&&(u=P(u)),void 0===n||void 0===l||null===f||null===u)return null;\"BR\"===f.nodeName&&([f,g]=k(f)),\"BR\"===u.nodeName&&([u,a]=k(u));const d=f.firstChild;f===u&&null!=d&&\"BR\"===d.nodeName&&0===g&&0===a&&(a=1);try{c.setStart(f,g),c.setEnd(u,a)}catch(e){return null}return!c.collapsed||g===a&&s===i||(c.setStart(u,a),c.setEnd(f,g)),c}function B(e,t){const n=e.getRootElement();if(null===n)return[];const o=n.getBoundingClientRect(),l=getComputedStyle(n),r=parseFloat(l.paddingLeft)+parseFloat(l.paddingRight),s=Array.from(t.getClientRects());let i,c=s.length;s.sort((e,t)=>{const n=e.top-t.top;return Math.abs(n)<=3?e.left-t.left:n});for(let e=0;et.top&&i.left+i.width>t.left,l=t.width+r===o.width;n||l?(s.splice(e--,1),c--):i=t}return s}function F(e){const t={};if(!e)return t;const n=e.split(\";\");for(const e of n)if(\"\"!==e){const[n,o]=e.split(/:([^]+)/);n&&o&&(t[n.trim()]=o.trim())}return t}function b(e){let t=E.get(e);return void 0===t&&(t=F(e),E.set(e,t)),t}function z(e){let t=\"\";for(const n in e)n&&(t+=`${n}: ${e[n]};`);return t}function R(e){const n=t().getElementByKey(e.getKey());if(null===n)return null;const o=n.ownerDocument.defaultView;return null===o?null:o.getComputedStyle(n)}function O(e){return R(n(e)?e:e.getParentOrThrow())}function A(e){const t=O(e);return null!==t&&\"rtl\"===t.direction}function M(e,t,n=\"self\"){const o=e.getStartEndPoints();if(t.isSelected(e)&&!s(t)&&null!==o){const[l,r]=o,s=e.isBackward(),i=l.getNode(),u=r.getNode(),g=t.is(i),a=t.is(u);if(g||a){const[o,l]=c(e),r=i.is(u),g=t.is(s?u:i),a=t.is(s?i:u);let d,p=0;if(r)p=o>l?l:o,d=o>l?o:l;else if(g){p=s?l:o,d=void 0}else if(a){p=0,d=s?o:l}const h=t.__text.slice(p,d);h!==t.__text&&(\"clone\"===n&&(t=f(t)),t.__text=h)}}return t}function _(e){if(\"text\"===e.type)return e.offset===e.getNode().getTextContentSize();const t=e.getNode();return i(t)||K(177),e.offset===t.getChildrenSize()}function L(t,o,r){let s=o.getNode(),c=r;if(i(s)){const e=s.getDescendantByIndex(o.offset);null!==e&&(s=e)}for(;c>0&&null!==s;){if(i(s)){const e=s.getLastDescendant();null!==e&&(s=e)}let r=s.getPreviousSibling(),f=0;if(null===r){let e=s.getParentOrThrow(),t=e.getPreviousSibling();for(;null===t;){if(e=e.getParent(),null===e){r=null;break}t=e.getPreviousSibling()}null!==e&&(f=e.isInline()?0:2,r=t)}let d=s.getTextContent();\"\"===d&&i(s)&&!s.isInline()&&(d=\"\\n\\n\");const p=d.length;if(!e(s)||c>=p){const e=s.getParent();s.remove(),null==e||0!==e.getChildrenSize()||n(e)||e.remove(),c-=p+f,s=r}else{const n=s.getKey(),r=t.getEditorState().read(()=>{const t=u(n);return e(t)&&t.isSimpleText()?t.getTextContent():null}),i=p-c,f=d.slice(0,i);if(null!==r&&r!==d){const e=g();let t=s;if(s.isSimpleText())s.setTextContent(r);else{const e=a(r);s.replace(e),t=e}if(l(e)&&e.isCollapsed()){const n=e.anchor.offset;t.select(n,n)}}else if(s.isSimpleText()){const e=o.key===n;let t=o.offset;t(\"function\"==typeof l?e[n]=l(o[n],t):null===l?delete e[n]:e[n]=l,e),{...o}),s=z(r);l(t)||e(t)?t.setStyle(s):t.setTextStyle(s),E.set(s,r)}function U(e,t){if(l(e)&&e.isCollapsed()){D(e,t);const n=e.anchor.getNode();i(n)&&n.isEmpty()&&D(n,t)}j(e=>{D(e,t)});const n=e.getNodes();if(n.length>0){const e=new Set;for(const o of n){if(!i(o)||!o.canBeEmpty()||0!==o.getChildrenSize())continue;const n=o.getKey();e.has(n)||(e.add(n),D(o,t))}}}function j(t){const n=o();if(!n)return;const i=new Map,c=e=>i.get(e.getKey())||[0,e.getTextContentSize()];if(l(n))for(const e of r(n).getTextSlices())e&&i.set(e.caret.origin.getKey(),e.getSliceIndices());const f=n.getNodes();for(const n of f){if(!e(n)||!n.canHaveFormat())continue;const[o,l]=c(n);if(l!==o)if(s(n)||0===o&&l===n.getTextContentSize())t(n);else{t(n.splitText(o,l)[0===o?0:1])}}l(n)&&\"text\"===n.anchor.type&&\"text\"===n.focus.type&&n.anchor.key===n.focus.key&&H(n)}function H(e){if(e.isBackward()){const{anchor:t,focus:n}=e,{key:o,offset:l,type:r}=t;t.set(n.key,n.offset,n.type),n.set(o,l,r)}}function V(e,t){const n=e.getFormatType(),o=e.getIndent();n!==t.getFormatType()&&t.setFormat(n),o!==t.getIndent()&&t.setIndent(o)}function W(e,t,n=V){if(null===e)return;const l=e.getStartEndPoints(),r=new Map;let s=null;if(l){const[e,t]=l;s=d(),s.anchor.set(e.key,e.offset,e.type),s.focus.set(t.key,t.offset,t.type);const n=p(e.getNode(),h),o=p(t.getNode(),h);i(n)&&r.set(n.getKey(),n),i(o)&&r.set(o.getKey(),o)}for(const t of e.getNodes())if(i(t)&&h(t))r.set(t.getKey(),t);else if(null===l){const e=p(t,h);i(e)&&r.set(e.getKey(),e)}for(const[e,o]of r){const l=t();n(o,l),o.replace(l,!0),s&&(e===s.anchor.key&&s.anchor.set(l.getKey(),s.anchor.offset,s.anchor.type),e===s.focus.key&&s.focus.set(l.getKey(),s.focus.offset,s.focus.type))}s&&e.is(o())&&y(s)}function X(e){return e.getNode().isAttached()}function q(e){let t=e;for(;null!==t&&!w(t);){const e=t.getLatest(),n=t.getParent();0===e.getChildrenSize()&&t.remove(!0),t=n}}function G(e,t,n=null){const o=e.getStartEndPoints(),l=o?o[0]:null,r=e.getNodes(),s=r.length;if(null!==l&&(0===s||1===s&&\"element\"===l.type&&0===l.getNode().getChildrenSize())){const e=\"text\"===l.type?l.getNode().getParentOrThrow():l.getNode(),o=e.getChildren();let r=t();return r.setFormat(e.getFormatType()),r.setIndent(e.getIndent()),o.forEach(e=>r.append(e)),n&&(r=n.append(r)),void e.replace(r)}let i=null,c=[];for(let o=0;o{t.append(e),p.add(e.getKey()),i(e)&&e.getChildrenKeys().forEach(e=>p.add(e))}),q(l)}}else if(d.has(n.getKey())){i(n)||K(179);const e=o();e.setFormat(n.getFormatType()),e.setIndent(n.getIndent()),f.push(e),n.remove(!0)}}if(null!==r)for(let e=0;e=0;e--){const t=f[e];u.insertAfter(t)}else{const e=u.getFirstChild();if(i(e)&&(u=e),null===e)if(r)u.append(r);else for(let e=0;e=0;e--){const t=f[e];u.insertAfter(t),h=t}const m=g();l(m)&&X(m.anchor)&&X(m.focus)?y(m.clone()):null!==h?h.selectEnd():e.dirty=!0}function Q(e){const t=Y(e);return null!==t&&\"vertical-rl\"===t.writingMode}function Y(e){const t=e.anchor.getNode();return i(t)?R(t):O(t)}function Z(e,t){let n=Q(e)?!t:t;te(e)&&(n=!n);const o=m(e.focus,n?\"previous\":\"next\");if(S(o))return!1;for(const e of x(o)){if(T(e))return!e.origin.isInline();if(!i(e.origin)){if(N(e.origin))return!0;break}}return!1}function ee(e,t,n,o){e.modify(t?\"extend\":\"move\",n,o)}function te(e){const t=Y(e);return null!==t&&\"rtl\"===t.direction}function ne(e,t,n){const o=te(e);let l;l=Q(e)||o?!n:n,ee(e,t,l,\"character\")}function oe(e,t,n){const o=b(e.getStyle());return null!==o&&o[t]||n}function le(t,n,o=\"\"){let r=null;const s=t.getNodes(),i=t.anchor,c=t.focus,f=t.isBackward(),u=f?c.getNode():i.getNode(),g=f?i.getNode():c.getNode(),a=f?c.offset:i.offset,d=f?i.offset:c.offset;if(l(t)&&t.isCollapsed()&&\"\"!==t.style){const e=b(t.style);if(null!==e&&n in e)return e[n]}for(let t=0;tc.length;)s.pop();d&&o(s)}function a(){i=null,r=null,null!==l&&l.disconnect(),l=null,u.remove();for(const t of s)t.remove();s=[]}u.style.position=\"relative\";const f=e.registerRootListener(function n(){const o=e.getRootElement();if(null===o)return a();const s=o.parentElement;if(!t(s))return a();a(),r=o,i=s,l=new MutationObserver(t=>{const o=e.getRootElement(),l=o&&o.parentElement;if(o!==r||l!==i)return n();for(const e of t)if(!u.contains(e.target))return c()}),l.observe(s,q),c()});return()=>{f(),a()}}function Q(t,e,n){if(\"text\"!==t.type&&r(e)){const o=e.getDOMSlot(n);return[o.element,o.getFirstChildOffset()+t.offset]}return[i(n)||n,t.offset]}function X(t){for(const e of t){const t=e.style;\"Highlight\"!==t.background&&(t.background=\"Highlight\"),\"HighlightText\"!==t.color&&(t.color=\"HighlightText\"),t.marginTop!==G(-1.5)&&(t.marginTop=G(-1.5)),t.paddingTop!==G(4)&&(t.paddingTop=G(4)),t.paddingBottom!==G(0)&&(t.paddingBottom=G(0))}}function Y(t,r=X){let i=null,l=null,s=null,u=null,c=null,a=null,f=()=>{};function d(e){e.read(()=>{const e=n();if(!o(e))return i=null,s=null,u=null,a=null,f(),void(f=()=>{});const[d,g]=function(t){const e=t.getStartEndPoints();return t.isBackward()?[e[1],e[0]]:e}(e),p=d.getNode(),m=p.getKey(),h=d.offset,v=g.getNode(),y=v.getKey(),w=g.offset,x=t.getElementByKey(m),E=t.getElementByKey(y),S=null===i||x!==l||h!==s||m!==i.getKey(),C=null===u||E!==c||w!==a||y!==u.getKey();if((S||C)&&null!==x&&null!==E){const e=function(t,e,n,o,r,i,l){const s=(t._window?t._window.document:document).createRange();return s.setStart(...Q(e,n,o)),s.setEnd(...Q(r,i,l)),s}(t,d,p,x,g,v,E);f(),f=J(t,e,r)}i=p,l=x,s=h,u=v,c=E,a=w})}return d(t.getEditorState()),e(t.registerUpdateListener(({editorState:t})=>d(t)),()=>{f()})}function Z(t,e){let n=null;const o=()=>{const o=getSelection(),r=o&&o.anchorNode,i=t.getRootElement();null!==r&&null!==i&&i.contains(r)?null!==n&&(n(),n=null):null===n&&(n=Y(t,e))};return t.registerRootListener(t=>{if(t){const e=t.ownerDocument;return e.addEventListener(\"selectionchange\",o),o(),()=>{null!==n&&n(),e.removeEventListener(\"selectionchange\",o)}}})}const tt=F,et=$,nt=j,ot=V,rt=O,it=W,lt=U,st=D,ut=H,ct=z;function at(t,e){for(const n of e)if(t.type.startsWith(n))return!0;return!1}function ft(t,e){const n=t[Symbol.iterator]();return new Promise((t,o)=>{const r=[],i=()=>{const{done:l,value:s}=n.next();if(l)return t(r);const u=new FileReader;u.addEventListener(\"error\",o),u.addEventListener(\"load\",()=>{const t=u.result;\"string\"==typeof t&&r.push({file:s,result:t}),i()}),at(s,e)?u.readAsDataURL(s):i()};i()})}function dt(t,e){return Array.from(mt(t,e))}function gt(t){return t?t.getAdjacentCaret():null}function pt(t,e){return Array.from(Et(t,e))}function mt(t,e){return vt(\"next\",t,e)}function ht(t,e){const n=a(c(t,e));return n&&n[0]}function vt(t,e,n){const o=x(),i=e||o,s=r(i)?l(i,t):c(i,t),f=wt(i),d=n?S(u(c(n,t)))||ht(n,t):ht(i,t);let g=f;return M({hasNext:t=>null!==t,initial:s,map:t=>({depth:g,node:t.origin}),step:t=>{if(t.isSameNodeCaret(d))return null;C(t)&&g++;const e=a(t);return!e||e[0].isSameNodeCaret(d)?null:(g+=e[1],e[0])}})}function yt(t){const e=a(c(t,\"next\"));return e&&[e[0].origin,e[1]]}function wt(t){let e=-1;for(let n=t;null!==n;n=n.getParent())e++;return e}function xt(t){const e=u(c(t,\"previous\")),n=a(e,\"root\");return n&&n[0].origin}function Et(t,e){return vt(\"previous\",t,e)}function St(t,e){let n=t;for(;null!=n;){if(n instanceof e)return n;n=n.getParent()}return null}function Ct(t){const e=s(t,t=>r(t)&&!t.isInline());return r(e)||k(4,t.__key),e}function At(t,e,n,o){const r=t=>t instanceof e;return t.registerNodeTransform(e,t=>{const e=(t=>{const e=t.getChildren();for(let t=0;tr(t)&&!t.isInline());if(null===u)continue;const c=u.getKey();u.canIndent()&&!i.has(c)&&(i.add(c),t(u))}return i.size>0}function _t(t,e){l(t,\"next\").insert(e)}let Kt=!(st||!et)&&void 0;function kt(t,e=!1){let n=1;if(function(){if(void 0===Kt){const t=document.createElement(\"div\");t.style.cssText=\"position: absolute; opacity: 0; width: 100px; left: -1000px;\",document.body.appendChild(t);const e=t.getBoundingClientRect();t.style.setProperty(\"zoom\",\"2\"),Kt=t.getBoundingClientRect().width===e.width,document.body.removeChild(t)}return Kt}()||e)for(;t;)n*=Number(window.getComputedStyle(t).getPropertyValue(\"zoom\")),t=t.parentElement;return n}function $t(t){return null!==t._parentEditor}function It(t,e){return Ot(t,e,null)}function Ot(t,e,n){let o=!1;for(const i of Ht(t))e(i)?null!==n&&n(i):(o=!0,r(i)&&Ot(i,e,n||(t=>i.insertAfter(t))),i.remove());return o}function Dt(t,e){const n=[],o=Array.from(t).reverse();for(let t=o.pop();void 0!==t;t=o.pop())if(e(t))n.push(t);else if(r(t))for(const e of Ht(t))o.push(e);return n}function Ft(t){return jt(l(t,\"next\"))}function Ht(t){return jt(l(t,\"previous\"))}function jt(t){return M({hasNext:T,initial:t.getAdjacentCaret(),map:t=>t.origin.getLatest(),step:t=>t.getAdjacentCaret()})}function zt(t){R(c(t,\"next\")).splice(1,t.getChildren())}function Ut(t){const e=e=>B(e,t),n=(e,n)=>_(e,t,n);return{$get:e,$set:n,accessors:[e,n],makeGetterMethod:()=>function(){return e(this)},makeSetterMethod:()=>function(t){return n(this,t)},stateConfig:t}}export{Dt as $descendantsMatching,dt as $dfs,mt as $dfsIterator,Tt as $filter,Ft as $firstToLastIterator,gt as $getAdjacentCaret,wt as $getDepth,Ct as $getNearestBlockElementAncestorOrThrow,St as $getNearestNodeOfType,xt as $getNextRightPreorderNode,yt as $getNextSiblingOrParentSibling,Bt as $handleIndentAndOutdent,_t as $insertFirst,Pt as $insertNodeIntoLeaf,bt as $insertNodeToNearestRoot,Lt as $insertNodeToNearestRootAtCaret,$t as $isEditorIsNestedEditor,Ht as $lastToFirstIterator,Nt as $restoreEditorState,pt as $reverseDfs,Et as $reverseDfsIterator,It as $unwrapAndFilterDescendants,zt as $unwrapNode,Rt as $wrapNodeInElement,tt as CAN_USE_BEFORE_INPUT,et as CAN_USE_DOM,nt as IS_ANDROID,ot as IS_ANDROID_CHROME,rt as IS_APPLE,it as IS_APPLE_WEBKIT,lt as IS_CHROME,st as IS_FIREFOX,ut as IS_IOS,ct as IS_SAFARI,kt as calculateZoomLevel,at as isMimeType,Ut as makeStateWrapper,Y as markSelection,ft as mediaFileReader,Mt as objectKlassEquals,J as positionNodeOnRange,At as registerNestedElementResolver,Z as selectionAlwaysOnDisplay};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{defineExtension as t,safeCast as e,CLEAR_EDITOR_COMMAND as n,COMMAND_PRIORITY_EDITOR as i,$getRoot as o,$getSelection as s,$createParagraphNode as r,$isRangeSelection as c,FORMAT_TEXT_COMMAND as a,$isNodeSelection as d,COMMAND_PRIORITY_LOW as u,DecoratorNode as f,$getState as l,toggleTextFormatType as h,$setState as g,TEXT_TYPE_TO_FORMAT as p,createState as m,shallowMergeConfig as v,RootNode as x,TextNode as E,LineBreakNode as y,TabNode as S,ParagraphNode as b,$isEditorState as w,HISTORY_MERGE_TAG as N,createEditor as O,mergeRegister as R,$getNodeByKey as C,$create as D,CLICK_COMMAND as F,isDOMNode as M,$getNodeFromDOMNode as I,addClassNamesToElement as _,createCommand as P,$createNodeSelection as A,$setSelection as j,removeClassNamesFromElement as k,$getEditor as $,KEY_TAB_COMMAND as K,OUTDENT_CONTENT_COMMAND as z,INDENT_CONTENT_COMMAND as L,INSERT_TAB_COMMAND as U,COMMAND_PRIORITY_CRITICAL as T,$isBlockElementNode as B,$createRangeSelection as W,$normalizeSelection__EXPERIMENTAL as G}from\"lexical\";export{configExtension,declarePeerDependency,defineExtension,safeCast,shallowMergeConfig}from\"lexical\";import{$insertNodeToNearestRoot as V,selectionAlwaysOnDisplay as Z,$handleIndentAndOutdent as J,$getNearestBlockElementAncestorOrThrow as H}from\"@lexical/utils\";const q=Symbol.for(\"preact-signals\");function Q(){if(it>1)return void it--;let t,e=!1;for(!function(){let t=nt;for(nt=void 0;void 0!==t;)t.S.v===t.v&&(t.S.i=t.i),t=t.o}();void 0!==tt;){let n=tt;for(tt=void 0,ot++;void 0!==n;){const i=n.u;if(n.u=void 0,n.f&=-3,!(8&n.f)&&ft(n))try{n.c()}catch(n){e||(t=n,e=!0)}n=i}}if(ot=0,it--,e)throw t}function X(t){if(it>0)return t();rt=++st,it++;try{return t()}finally{Q()}}let Y,tt;function et(t){const e=Y;Y=void 0;try{return t()}finally{Y=e}}let nt,it=0,ot=0,st=0,rt=0,ct=0;function at(t){if(void 0===Y)return;let e=t.n;return void 0===e||e.t!==Y?(e={i:0,S:t,p:Y.s,n:void 0,t:Y,e:void 0,x:void 0,r:e},void 0!==Y.s&&(Y.s.n=e),Y.s=e,t.n=e,32&Y.f&&t.S(e),e):-1===e.i?(e.i=0,void 0!==e.n&&(e.n.p=e.p,void 0!==e.p&&(e.p.n=e.n),e.p=Y.s,e.n=void 0,Y.s.n=e,Y.s=e),e):void 0}function dt(t,e){this.v=t,this.i=0,this.n=void 0,this.t=void 0,this.l=0,this.W=null==e?void 0:e.watched,this.Z=null==e?void 0:e.unwatched,this.name=null==e?void 0:e.name}function ut(t,e){return new dt(t,e)}function ft(t){for(let e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function lt(t){for(let e=t.s;void 0!==e;e=e.n){const n=e.S.n;if(void 0!==n&&(e.r=n),e.S.n=e,e.i=-1,void 0===e.n){t.s=e;break}}}function ht(t){let e,n=t.s;for(;void 0!==n;){const t=n.p;-1===n.i?(n.S.U(n),void 0!==t&&(t.n=n.n),void 0!==n.n&&(n.n.p=t)):e=n,n.S.n=n.r,void 0!==n.r&&(n.r=void 0),n=t}t.s=e}function gt(t,e){dt.call(this,void 0),this.x=t,this.s=void 0,this.g=ct-1,this.f=4,this.W=null==e?void 0:e.watched,this.Z=null==e?void 0:e.unwatched,this.name=null==e?void 0:e.name}function pt(t,e){return new gt(t,e)}function mt(t){const e=t.m;if(t.m=void 0,\"function\"==typeof e){it++;const n=Y;Y=void 0;try{e()}catch(e){throw t.f&=-2,t.f|=8,vt(t),e}finally{Y=n,Q()}}}function vt(t){for(let e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,mt(t)}function xt(t){if(Y!==this)throw new Error(\"Out-of-order effect\");ht(this),Y=t,this.f&=-2,8&this.f&&vt(this),Q()}function Et(t,e){this.x=t,this.m=void 0,this.s=void 0,this.u=void 0,this.f=32,this.name=null==e?void 0:e.name}function yt(t,e){const n=new Et(t,e);try{n.c()}catch(t){throw n.d(),t}const i=n.d.bind(n);return i[Symbol.dispose]=i,i}function St(t,e={}){const n={};for(const i in t){const o=e[i],s=ut(void 0===o?t[i]:o);n[i]=s}return n}dt.prototype.brand=q,dt.prototype.h=function(){return!0},dt.prototype.S=function(t){const e=this.t;e!==t&&void 0===t.e&&(t.x=e,this.t=t,void 0!==e?e.e=t:et(()=>{var t;null==(t=this.W)||t.call(this)}))},dt.prototype.U=function(t){if(void 0!==this.t){const e=t.e,n=t.x;void 0!==e&&(e.x=n,t.e=void 0),void 0!==n&&(n.e=e,t.x=void 0),t===this.t&&(this.t=n,void 0===n&&et(()=>{var t;null==(t=this.Z)||t.call(this)}))}},dt.prototype.subscribe=function(t){return yt(()=>{const e=this.value,n=Y;Y=void 0;try{t(e)}finally{Y=n}},{name:\"sub\"})},dt.prototype.valueOf=function(){return this.value},dt.prototype.toString=function(){return this.value+\"\"},dt.prototype.toJSON=function(){return this.value},dt.prototype.peek=function(){const t=Y;Y=void 0;try{return this.value}finally{Y=t}},Object.defineProperty(dt.prototype,\"value\",{get(){const t=at(this);return void 0!==t&&(t.i=this.i),this.v},set(t){if(t!==this.v){if(ot>100)throw new Error(\"Cycle detected\");!function(t){0!==it&&0===ot&&t.l!==rt&&(t.l=rt,nt={S:t,v:t.v,i:t.i,o:nt})}(this),this.v=t,this.i++,ct++,it++;try{for(let t=this.t;void 0!==t;t=t.x)t.t.N()}finally{Q()}}}}),gt.prototype=new dt,gt.prototype.h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===ct)return!0;if(this.g=ct,this.f|=1,this.i>0&&!ft(this))return this.f&=-2,!0;const t=Y;try{lt(this),Y=this;const t=this.x();(16&this.f||this.v!==t||0===this.i)&&(this.v=t,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return Y=t,ht(this),this.f&=-2,!0},gt.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(let t=this.s;void 0!==t;t=t.n)t.S.S(t)}dt.prototype.S.call(this,t)},gt.prototype.U=function(t){if(void 0!==this.t&&(dt.prototype.U.call(this,t),void 0===this.t)){this.f&=-33;for(let t=this.s;void 0!==t;t=t.n)t.S.U(t)}},gt.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(let t=this.t;void 0!==t;t=t.x)t.t.N()}},Object.defineProperty(gt.prototype,\"value\",{get(){if(1&this.f)throw new Error(\"Cycle detected\");const t=at(this);if(this.h(),void 0!==t&&(t.i=this.i),16&this.f)throw this.v;return this.v}}),Et.prototype.c=function(){const t=this.S();try{if(8&this.f)return;if(void 0===this.x)return;const t=this.x();\"function\"==typeof t&&(this.m=t)}finally{t()}},Et.prototype.S=function(){if(1&this.f)throw new Error(\"Cycle detected\");this.f|=1,this.f&=-9,mt(this),lt(this),it++;const t=Y;return Y=this,xt.bind(this,t)},Et.prototype.N=function(){2&this.f||(this.f|=2,this.u=tt,tt=this)},Et.prototype.d=function(){this.f|=8,1&this.f||vt(this)},Et.prototype.dispose=function(){this.d()};const bt=t({build:(t,e,n)=>St(e),config:e({defaultSelection:\"rootEnd\",disabled:!1}),name:\"@lexical/extension/AutoFocus\",register(t,e,n){const i=n.getOutput();return yt(()=>i.disabled.value?void 0:t.registerRootListener(e=>{t.focus(()=>{const t=document.activeElement;null===e||null!==t&&e.contains(t)||e.focus({preventScroll:!0})},{defaultSelection:i.defaultSelection.peek()})}))}});function wt(){const t=o(),e=s(),n=r();t.clear(),t.append(n),null!==e&&n.select(),c(e)&&(e.format=0)}function Nt(t,e=wt){return t.registerCommand(n,n=>(t.update(e),!0),i)}const Ot=t({build:(t,e,n)=>St(e),config:e({$onClear:wt}),name:\"@lexical/extension/ClearEditor\",register(t,e,n){const{$onClear:i}=n.getOutput();return yt(()=>Nt(t,i.value))}});function Rt(t){const e=new Set,n=new Set;for(const i of Ct(t)){const t=\"function\"==typeof i?i:i.replace;e.add(t.getType()),n.add(t)}return{nodes:n,types:e}}function Ct(t){return(\"function\"==typeof t.nodes?t.nodes():t.nodes)||[]}const Dt=m(\"format\",{parse:t=>\"number\"==typeof t?t:0});class Ft extends f{$config(){return this.config(\"decorator-text\",{extends:f,stateConfigs:[{flat:!0,stateConfig:Dt}]})}getFormat(){return l(this,Dt)}getFormatFlags(t,e){return h(this.getFormat(),t,e)}hasFormat(t){const e=p[t];return 0!==(this.getFormat()&e)}setFormat(t){return g(this,Dt,t)}toggleFormat(t){const e=this.getFormat(),n=h(e,t,null);return this.setFormat(n)}isInline(){return!0}createDOM(){return document.createElement(\"span\")}updateDOM(){return!1}}function Mt(t){return t instanceof Ft}function It(t,e,n){const i=e.fontWeight,o=e.textDecoration.split(\" \"),s=\"700\"===i||\"bold\"===i,r=o.includes(\"line-through\"),c=\"italic\"===e.fontStyle,a=o.includes(\"underline\"),d=e.verticalAlign;return s&&!t.hasFormat(\"bold\")&&t.toggleFormat(\"bold\"),r&&!t.hasFormat(\"strikethrough\")&&t.toggleFormat(\"strikethrough\"),c&&!t.hasFormat(\"italic\")&&t.toggleFormat(\"italic\"),a&&!t.hasFormat(\"underline\")&&t.toggleFormat(\"underline\"),\"sub\"!==d||t.hasFormat(\"subscript\")||t.toggleFormat(\"subscript\"),\"super\"!==d||t.hasFormat(\"superscript\")||t.toggleFormat(\"superscript\"),n&&!t.hasFormat(n)&&t.toggleFormat(n),t}function _t(t,e,n=At){for(const[i,o]of Object.entries(n))t.hasFormat(o)&&(e=Pt(e,i));return e}function Pt(t,e){const n=document.createElement(e);return n.appendChild(t),n}const At={b:\"bold\",code:\"code\",em:\"italic\",i:\"italic\",mark:\"highlight\",s:\"strikethrough\",strong:\"bold\",sub:\"subscript\",sup:\"superscript\",u:\"underline\"},jt=t({name:\"@lexical/extension/DecoratorText\",nodes:()=>[Ft],register:(t,e,n)=>t.registerCommand(a,t=>{const e=s();if(d(e)||c(e))for(const n of e.getNodes())Mt(n)&&n.toggleFormat(t);return!1},u)});function kt(t,e){let n;return ut(t(),{unwatched(){n&&(n(),n=void 0)},watched(){this.value=t(),n=e(this)}})}const $t=t({build:t=>kt(()=>t.getEditorState(),e=>t.registerUpdateListener(t=>{e.value=t.editorState})),name:\"@lexical/extension/EditorState\"});function Kt(t,...e){const n=new URL(\"https://lexical.dev/docs/error\"),i=new URLSearchParams;i.append(\"code\",t);for(const t of e)i.append(\"v\",t);throw n.search=i.toString(),Error(`Minified Lexical error #${t}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}function zt(t,e){if(t&&e&&!Array.isArray(e)&&\"object\"==typeof t&&\"object\"==typeof e){const n=t,i=e;for(const t in i)n[t]=zt(n[t],i[t]);return t}return e}const Lt=0,Ut=1,Tt=2,Bt=3,Wt=4,Gt=5,Vt=6,Zt=7;function Jt(t){return t.id===Lt}function Ht(t){return t.id===Tt}function qt(t){return function(t){return t.id===Ut}(t)||Kt(305,String(t.id),String(Ut)),Object.assign(t,{id:Tt})}const Qt=new Set;class Xt{builder;configs;_dependency;_peerNameSet;extension;state;_signal;constructor(t,e){this.builder=t,this.extension=e,this.configs=new Set,this.state={id:Lt}}mergeConfigs(){let t=this.extension.config||{};const e=this.extension.mergeConfig?this.extension.mergeConfig.bind(this.extension):v;for(const n of this.configs)t=e(t,n);return t}init(t){const e=this.state;Ht(e)||Kt(306,String(e.id));const n={getDependency:this.getInitDependency.bind(this),getDirectDependentNames:this.getDirectDependentNames.bind(this),getPeer:this.getInitPeer.bind(this),getPeerNameSet:this.getPeerNameSet.bind(this)},i={...n,getDependency:this.getDependency.bind(this),getInitResult:this.getInitResult.bind(this),getPeer:this.getPeer.bind(this)},o=function(t,e,n){return Object.assign(t,{config:e,id:Bt,registerState:n})}(e,this.mergeConfigs(),n);let s;this.state=o,this.extension.init&&(s=this.extension.init(t,o.config,n)),this.state=function(t,e,n){return Object.assign(t,{id:Wt,initResult:e,registerState:n})}(o,s,i)}build(t){const e=this.state;let n;e.id!==Wt&&Kt(307,String(e.id),String(Gt)),this.extension.build&&(n=this.extension.build(t,e.config,e.registerState));const i={...e.registerState,getOutput:()=>n,getSignal:this.getSignal.bind(this)};this.state=function(t,e,n){return Object.assign(t,{id:Gt,output:e,registerState:n})}(e,n,i)}register(t,e){this._signal=e;const n=this.state;n.id!==Gt&&Kt(308,String(n.id),String(Gt));const i=this.extension.register&&this.extension.register(t,n.config,n.registerState);return this.state=function(t){return Object.assign(t,{id:Vt})}(n),()=>{const t=this.state;t.id!==Zt&&Kt(309,String(n.id),String(Zt)),this.state=function(t){return Object.assign(t,{id:Gt})}(t),i&&i()}}afterRegistration(t){const e=this.state;let n;return e.id!==Vt&&Kt(310,String(e.id),String(Vt)),this.extension.afterRegistration&&(n=this.extension.afterRegistration(t,e.config,e.registerState)),this.state=function(t){return Object.assign(t,{id:Zt})}(e),n}getSignal(){return void 0===this._signal&&Kt(311),this._signal}getInitResult(){void 0===this.extension.init&&Kt(312,this.extension.name);const t=this.state;return function(t){return t.id>=Wt}(t)||Kt(313,String(t.id),String(Wt)),t.initResult}getInitPeer(t){const e=this.builder.extensionNameMap.get(t);return e?e.getExtensionInitDependency():void 0}getExtensionInitDependency(){const t=this.state;return function(t){return t.id>=Bt}(t)||Kt(314,String(t.id),String(Bt)),{config:t.config}}getPeer(t){const e=this.builder.extensionNameMap.get(t);return e?e.getExtensionDependency():void 0}getInitDependency(t){const e=this.builder.getExtensionRep(t);return void 0===e&&Kt(315,this.extension.name,t.name),e.getExtensionInitDependency()}getDependency(t){const e=this.builder.getExtensionRep(t);return void 0===e&&Kt(315,this.extension.name,t.name),e.getExtensionDependency()}getState(){const t=this.state;return function(t){return t.id>=Zt}(t)||Kt(316,String(t.id),String(Zt)),t}getDirectDependentNames(){return this.builder.incomingEdges.get(this.extension.name)||Qt}getPeerNameSet(){let t=this._peerNameSet;return t||(t=new Set((this.extension.peerDependencies||[]).map(([t])=>t)),this._peerNameSet=t),t}getExtensionDependency(){if(!this._dependency){const t=this.state;(function(t){return t.id>=Gt})(t)||Kt(317,this.extension.name),this._dependency={config:t.config,init:t.initResult,output:t.output}}return this._dependency}}const Yt={tag:N};function te(){const t=o();t.isEmpty()&&t.append(r())}const ee=t({config:e({setOptions:Yt,updateOptions:Yt}),init:({$initialEditorState:t=te})=>({$initialEditorState:t,initialized:!1}),afterRegistration(t,{updateOptions:e,setOptions:n},i){const o=i.getInitResult();if(!o.initialized){o.initialized=!0;const{$initialEditorState:i}=o;if(w(i))t.setEditorState(i,n);else if(\"function\"==typeof i)t.update(()=>{i(t)},e);else if(i&&(\"string\"==typeof i||\"object\"==typeof i)){const e=t.parseEditorState(i);t.setEditorState(e,n)}}return()=>{}},name:\"@lexical/extension/InitialState\",nodes:[x,E,y,S,b]}),ne=Symbol.for(\"@lexical/extension/LexicalBuilder\");function ie(...t){return ae.fromExtensions(t).buildEditor()}function oe(){}function se(t){throw t}function re(t){return Array.isArray(t)?t:[t]}const ce=\"0.43.0+prod.esm\";class ae{roots;extensionNameMap;outgoingConfigEdges;incomingEdges;conflicts;_sortedExtensionReps;PACKAGE_VERSION;constructor(t){this.outgoingConfigEdges=new Map,this.incomingEdges=new Map,this.extensionNameMap=new Map,this.conflicts=new Map,this.PACKAGE_VERSION=ce,this.roots=t;for(const e of t)this.addExtension(e)}static fromExtensions(t){const e=[re(ee)];for(const n of t)e.push(re(n));return new ae(e)}static maybeFromEditor(t){const e=t[ne];return e&&(e.PACKAGE_VERSION!==ce&&Kt(292,e.PACKAGE_VERSION,ce),e instanceof ae||Kt(293)),e}static fromEditor(t){const e=ae.maybeFromEditor(t);return void 0===e&&Kt(294),e}constructEditor(){const{$initialEditorState:t,onError:e,...n}=this.buildCreateEditorArgs(),i=Object.assign(O({...n,...e?{onError:t=>{e(t,i)}}:{}}),{[ne]:this});for(const t of this.sortedExtensionReps())t.build(i);return i}buildEditor(){let t=oe;function e(){try{t()}finally{t=oe}}const n=Object.assign(this.constructEditor(),{dispose:e,[Symbol.dispose]:e});return t=R(this.registerEditor(n),()=>n.setRootElement(null)),n}hasExtensionByName(t){return this.extensionNameMap.has(t)}getExtensionRep(t){const e=this.extensionNameMap.get(t.name);if(e)return e.extension!==t&&Kt(295,t.name),e}addEdge(t,e,n){const i=this.outgoingConfigEdges.get(t);i?i.set(e,n):this.outgoingConfigEdges.set(t,new Map([[e,n]]));const o=this.incomingEdges.get(e);o?o.add(t):this.incomingEdges.set(e,new Set([t]))}addExtension(t){void 0!==this._sortedExtensionReps&&Kt(296);const e=re(t),[n]=e;\"string\"!=typeof n.name&&Kt(297,typeof n.name);let i=this.extensionNameMap.get(n.name);if(void 0!==i&&i.extension!==n&&Kt(298,n.name),!i){i=new Xt(this,n),this.extensionNameMap.set(n.name,i);const t=this.conflicts.get(n.name);\"string\"==typeof t&&Kt(299,n.name,t);for(const t of n.conflictsWith||[])this.extensionNameMap.has(t)&&Kt(299,n.name,t),this.conflicts.set(t,n.name);for(const t of n.dependencies||[]){const e=re(t);this.addEdge(n.name,e[0].name,e.slice(1)),this.addExtension(e)}for(const[t,e]of n.peerDependencies||[])this.addEdge(n.name,t,e?[e]:[])}}sortedExtensionReps(){if(this._sortedExtensionReps)return this._sortedExtensionReps;const t=[],e=(n,i)=>{let o=n.state;if(Ht(o))return;const s=n.extension.name;var r;Jt(o)||Kt(300,s,i||\"[unknown]\"),Jt(r=o)||Kt(304,String(r.id),String(Lt)),o=Object.assign(r,{id:Ut}),n.state=o;const c=this.outgoingConfigEdges.get(s);if(c)for(const t of c.keys()){const n=this.extensionNameMap.get(t);n&&e(n,s)}o=qt(o),n.state=o,t.push(n)};for(const t of this.extensionNameMap.values())Jt(t.state)&&e(t);for(const e of t)for(const[t,n]of this.outgoingConfigEdges.get(e.extension.name)||[])if(n.length>0){const e=this.extensionNameMap.get(t);if(e)for(const t of n)e.configs.add(t)}for(const[t,...e]of this.roots)if(e.length>0){const n=this.extensionNameMap.get(t.name);void 0===n&&Kt(301,t.name);for(const t of e)n.configs.add(t)}return this._sortedExtensionReps=t,this._sortedExtensionReps}registerEditor(t){const e=this.sortedExtensionReps(),n=new AbortController,i=[()=>n.abort()],o=n.signal;for(const n of e){const e=n.register(t,o);e&&i.push(e)}for(const n of e){const e=n.afterRegistration(t);e&&i.push(e)}return R(...i)}buildCreateEditorArgs(){const t={},e=new Set,n=new Map,i=new Map,o={},s={},r=this.sortedExtensionReps();for(const c of r){const{extension:r}=c;if(void 0!==r.onError&&(t.onError=r.onError),void 0!==r.disableEvents&&(t.disableEvents=r.disableEvents),void 0!==r.parentEditor&&(t.parentEditor=r.parentEditor),void 0!==r.editable&&(t.editable=r.editable),void 0!==r.namespace&&(t.namespace=r.namespace),void 0!==r.$initialEditorState&&(t.$initialEditorState=r.$initialEditorState),r.nodes)for(const t of Ct(r)){if(\"function\"!=typeof t){const e=n.get(t.replace);e&&Kt(302,r.name,t.replace.name,e.extension.name),n.set(t.replace,c)}e.add(t)}if(r.html){if(r.html.export)for(const[t,e]of r.html.export.entries())i.set(t,e);r.html.import&&Object.assign(o,r.html.import)}r.theme&&zt(s,r.theme)}Object.keys(s).length>0&&(t.theme=s),e.size&&(t.nodes=[...e]);const c=Object.keys(o).length>0,a=i.size>0;(c||a)&&(t.html={},c&&(t.html.import=o),a&&(t.html.export=i));for(const e of r)e.init(t);return t.onError||(t.onError=se),t}}function de(t,e){const n=ae.fromEditor(t).getExtensionRep(e);return void 0===n&&Kt(303,e.name),n.getExtensionDependency()}function ue(t,e){const n=ae.fromEditor(t).extensionNameMap.get(e);return n?n.getExtensionDependency():void 0}function fe(t,e){const n=ue(t,e);return void 0===n&&Kt(291,e),n}const le=new Set,he=t({build(t,e,n){const i=n.getDependency($t).output,o=ut({watchedNodeKeys:new Map}),r=kt(()=>{},()=>yt(()=>{const t=r.peek(),{watchedNodeKeys:e}=o.value;let n,c=!1;i.value.read(()=>{if(s())for(const[i,o]of e.entries()){if(0===o.size){e.delete(i);continue}const s=C(i),r=s&&s.isSelected()||!1;c=c||r!==(!!t&&t.has(i)),r&&(n=n||new Set,n.add(i))}}),!c&&n&&t&&n.size===t.size||(r.value=n)}));return{watchNodeKey:function(t){const e=pt(()=>(r.value||le).has(t)),{watchedNodeKeys:n}=o.peek();let i=n.get(t);const s=void 0!==i;return i=i||new Set,i.add(e),s||(n.set(t,i),o.value={watchedNodeKeys:n}),e}}},dependencies:[$t],name:\"@lexical/extension/NodeSelection\"}),ge=P(\"INSERT_HORIZONTAL_RULE_COMMAND\");class pe extends f{static getType(){return\"horizontalrule\"}static clone(t){return new pe(t.__key)}static importJSON(t){return ve().updateFromJSON(t)}static importDOM(){return{hr:()=>({conversion:me,priority:0})}}exportDOM(){return{element:document.createElement(\"hr\")}}createDOM(t){const e=document.createElement(\"hr\");return _(e,t.theme.hr),e}getTextContent(){return\"\\n\"}isInline(){return!1}updateDOM(){return!1}}function me(){return{node:ve()}}function ve(){return D(pe)}function xe(t){return t instanceof pe}const Ee=t({dependencies:[$t,he],name:\"@lexical/extension/HorizontalRule\",nodes:()=>[pe],register(t,e,n){const{watchNodeKey:o}=n.getDependency(he).output,r=ut({nodeSelections:new Map}),a=t._config.theme.hrSelected??\"selected\";return R(t.registerCommand(ge,t=>{const e=s();if(!c(e))return!1;if(null!==e.focus.getNode()){const t=ve();V(t)}return!0},i),t.registerCommand(F,t=>{if(M(t.target)){const e=I(t.target);if(xe(e))return function(t,e=!1){const n=s(),i=t.isSelected(),o=t.getKey();let r;e&&d(n)?r=n:(r=A(),j(r)),i?r.delete(o):r.add(o)}(e,t.shiftKey),!0}return!1},u),t.registerMutationListener(pe,(e,n)=>{X(()=>{let n=!1;const{nodeSelections:i}=r.peek();for(const[s,r]of e.entries())if(\"destroyed\"===r)i.delete(s),n=!0;else{const e=i.get(s),r=t.getElementByKey(s);e?e.domNode.value=r:(n=!0,i.set(s,{domNode:ut(r),selectedSignal:o(s)}))}n&&(r.value={nodeSelections:i})})}),yt(()=>{const t=[];for(const{domNode:e,selectedSignal:n}of r.value.nodeSelections.values())t.push(yt(()=>{const t=e.value;if(t){n.value?_(t,a):k(t,a)}}));return R(...t)}))}});const ye=t({build:(t,e)=>St({inheritEditableFromParent:e.inheritEditableFromParent}),config:e({$getParentEditor:function(){const t=$();return ae.fromEditor(t),t},inheritEditableFromParent:!1}),init:(t,e,n)=>{const i=e.$getParentEditor();t.parentEditor=i,t.theme=t.theme||i._config.theme},name:\"@lexical/extension/NestedEditor\",register:(t,e,n)=>yt(()=>{const e=t._parentEditor;if(e&&n.getOutput().inheritEditableFromParent.value)return t.setEditable(e.isEditable()),e.registerEditableListener(t.setEditable.bind(t))})}),Se=t({build:(t,e,n)=>St(e),config:e({disabled:!1,onReposition:void 0}),name:\"@lexical/utils/SelectionAlwaysOnDisplay\",register:(t,e,n)=>{const i=n.getOutput();return yt(()=>{if(!i.disabled.value)return Z(t,i.onReposition.value)})}});function be(t){return t.canBeEmpty()}function we(t,e,n=be){return R(t.registerCommand(K,e=>{const n=s();if(!c(n))return!1;e.preventDefault();const i=function(t){if(t.getNodes().filter(t=>B(t)&&t.canIndent()).length>0)return!0;const e=t.anchor,n=t.focus,i=n.isBefore(e)?n:e,o=i.getNode(),s=H(o);if(s.canIndent()){const t=s.getKey();let e=W();if(e.anchor.set(t,0,\"element\"),e.focus.set(t,0,\"element\"),e=G(e),e.anchor.is(i))return!0}return!1}(n)?e.shiftKey?z:L:U;return t.dispatchCommand(i,void 0)},i),t.registerCommand(L,()=>{const t=\"number\"==typeof e?e:e?e.peek():null,i=s();if(!c(i))return!1;const o=\"function\"==typeof n?n:n.peek();return J(e=>{if(o(e)){const n=e.getIndent()+1;(!t||nSt(e),config:e({$canIndent:be,disabled:!1,maxIndent:null}),name:\"@lexical/extension/TabIndentation\",register(t,e,n){const{disabled:i,maxIndent:o,$canIndent:s}=n.getOutput();return yt(()=>{if(!i.value)return we(t,o,s)})}});export{ve as $createHorizontalRuleNode,Mt as $isDecoratorTextNode,xe as $isHorizontalRuleNode,bt as AutoFocusExtension,Ot as ClearEditorExtension,jt as DecoratorTextExtension,Ft as DecoratorTextNode,$t as EditorStateExtension,Ee as HorizontalRuleExtension,pe as HorizontalRuleNode,ge as INSERT_HORIZONTAL_RULE_COMMAND,ee as InitialStateExtension,ae as LexicalBuilder,ye as NestedEditorExtension,he as NodeSelectionExtension,Se as SelectionAlwaysOnDisplayExtension,Ne as TabIndentationExtension,It as applyFormatFromStyle,_t as applyFormatToDom,X as batch,ie as buildEditorFromExtensions,pt as computed,yt as effect,de as getExtensionDependencyFromEditor,Rt as getKnownTypesAndNodes,ue as getPeerDependencyFromEditor,fe as getPeerDependencyFromEditorOrThrow,St as namedSignals,Nt as registerClearEditor,we as registerTabIndentation,ut as signal,et as untracked,kt as watchedSignal};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{defineExtension as e}from\"lexical\";const r=e({name:\"@lexical/react/ReactProvider\"});export{r as ReactProviderExtension};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{$getRoot as t,$isDecoratorNode as e,$isElementNode as n,$isParagraphNode as r,$isTextNode as i,TextNode as o,$createTextNode as l}from\"lexical\";function s(){return t().getTextContent()}function f(t,e=!0){if(t)return!1;let n=s();return e&&(n=n.trim()),\"\"===n}function u(t,e){return()=>f(t,e)}function c(o){if(!f(o,!1))return!1;const l=t().getChildren(),s=l.length;if(s>1)return!1;for(let t=0;tc(t)}function a(t,e){let r=t.getFirstChild(),o=0;t:for(;null!==r;){if(n(r)){const t=r.getFirstChild();if(null!==t){r=t;continue}}else if(i(r)){const t=r.getTextContentSize();if(o+t>e)return{node:r,offset:e-o};o+=t}const t=r.getNextSibling();if(null!==t){r=t;continue}let l=r.getParent();for(;null!==l;){const t=l.getNextSibling();if(null!==t){r=t;continue t}l=l.getParent()}break}return null}function d(t,...e){const n=new URL(\"https://lexical.dev/docs/error\"),r=new URLSearchParams;r.append(\"code\",t);for(const t of e)r.append(\"v\",t);throw n.search=r.toString(),Error(`Minified Lexical error #${t}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}function x(t,e,n,r){const s=t=>t instanceof n,f=t=>{const e=l(t.getTextContent());e.setFormat(t.getFormat()),t.replace(e)};return[t.registerNodeTransform(o,t=>{if(!t.isSimpleText())return;let n,o=t.getPreviousSibling(),l=t.getTextContent(),u=t;if(i(o)){const n=o.getTextContent(),r=e(n+l);if(s(o)){if(null===r||0!==(t=>t.getLatest().__mode)(o))return void f(o);{const e=r.end-n.length;if(e>0){const r=n+l.slice(0,e);if(o.select(),o.setTextContent(r),e===l.length)t.remove();else{const n=l.slice(e);t.setTextContent(n)}return}}}else if(null===r||r.start{const n=t.getTextContent(),r=e(n);if(null===r||0!==r.start)return void f(t);if(n.length>r.end)return void t.splitText(r.end);const o=t.getPreviousSibling();i(o)&&o.isTextEntity()&&(f(o),f(t));const l=t.getNextSibling();i(l)&&l.isTextEntity()&&(f(l),s(t)&&f(t))})]}export{c as $canShowPlaceholder,g as $canShowPlaceholderCurry,a as $findTextIntersectionFromCharacters,f as $isRootTextContentEmpty,u as $isRootTextContentEmptyCurry,s as $rootTextContent,x as registerLexicalTextEntity};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{effect as e,namedSignals as t}from\"@lexical/extension\";import{defineExtension as n,safeCast as o,$getSelection as i,$isRangeSelection as a,$isTextNode as r}from\"lexical\";function s(e){const t=window.location.origin,n=n=>{if(n.origin!==t)return;const o=e.getRootElement();if(document.activeElement!==o)return;const s=n.data;if(\"string\"==typeof s){let t;try{t=JSON.parse(s)}catch(e){return}if(t&&\"nuanria_messaging\"===t.protocol&&\"request\"===t.type){const o=t.payload;if(o&&\"makeChanges\"===o.functionId){const t=o.args;if(t){const[o,s,d,c,g]=t;e.update(()=>{const e=i();if(a(e)){const t=e.anchor;let i=t.getNode(),a=0,l=0;if(r(i)&&o>=0&&s>=0&&(a=o,l=o+s,e.setTextNodeRange(i,a,i,l)),a===l&&\"\"===d||(e.insertRawText(d),i=t.getNode()),r(i)){a=c,l=c+g;const t=i.getTextContentSize();a=a>t?t:a,l=l>t?t:l,e.setTextNodeRange(i,a,i,l)}n.stopImmediatePropagation()}})}}}}};return window.addEventListener(\"message\",n,!0),()=>{window.removeEventListener(\"message\",n,!0)}}const d=n({build:(e,n,o)=>t(n),config:o({disabled:\"undefined\"==typeof window}),name:\"@lexical/dragon\",register:(t,n,o)=>e(()=>o.getOutput().disabled.value?void 0:s(t))});export{d as DragonExtension,s as registerDragonSupport};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{useLexicalComposerContext as r}from\"@lexical/react/LexicalComposerContext\";import{useLexicalEditable as e}from\"@lexical/react/useLexicalEditable\";import{LexicalBuilder as t}from\"@lexical/extension\";import{ReactProviderExtension as o}from\"@lexical/react/ReactProviderExtension\";import{useLayoutEffect as n,useEffect as i,useState as c,useMemo as a,Suspense as l}from\"react\";import{flushSync as s,createPortal as u}from\"react-dom\";import{jsx as d,jsxs as f,Fragment as m}from\"react/jsx-runtime\";import{$canShowPlaceholderCurry as p}from\"@lexical/text\";import{mergeRegister as x}from\"@lexical/utils\";import{registerDragonSupport as E}from\"@lexical/dragon\";import{registerRichText as h}from\"@lexical/rich-text\";function g(r,...e){const t=new URL(\"https://lexical.dev/docs/error\"),o=new URLSearchParams;o.append(\"code\",r);for(const r of e)o.append(\"v\",r);throw t.search=o.toString(),Error(`Minified Lexical error #${r}; visit ${t.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const y=\"undefined\"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?n:i;function w({editor:r,ErrorBoundary:e}){return function(r,e){const[t,o]=c(()=>r.getDecorators());return y(()=>r.registerDecoratorListener(r=>{s(()=>{o(r)})}),[r]),i(()=>{o(r.getDecorators())},[r]),a(()=>{const o=[],n=Object.keys(t);for(let i=0;ir._onError(e),children:d(l,{fallback:null,children:t[c]})}),s=r.getElementByKey(c);null!==s&&o.push(u(a,s,c))}return o},[e,t,r])}(r,e)}function v({editor:r,ErrorBoundary:e}){return function(r){const e=t.maybeFromEditor(r);if(e&&e.hasExtensionByName(o.name)){for(const r of[\"@lexical/plain-text\",\"@lexical/rich-text\"])e.hasExtensionByName(r)&&g(320,r);return!0}return!1}(r)?null:d(w,{editor:r,ErrorBoundary:e})}function B(r){return r.getEditorState().read(p(r.isComposing()))}function L({contentEditable:e,placeholder:t=null,ErrorBoundary:o}){const[n]=r();return function(r){y(()=>x(h(r),E(r)),[r])}(n),f(m,{children:[e,d(b,{content:t}),d(v,{editor:n,ErrorBoundary:o})]})}function b({content:t}){const[o]=r(),n=function(r){const[e,t]=c(()=>B(r));return y(()=>{function e(){const e=B(r);t(e)}return e(),x(r.registerUpdateListener(()=>{e()}),r.registerEditableListener(()=>{e()}))},[r]),e}(o),i=e();return n?\"function\"==typeof t?t(i):t:null}export{L as RichTextPlugin};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{useLexicalComposerContext as e}from\"@lexical/react/LexicalComposerContext\";import{useEffect as t}from\"react\";function o({defaultSelection:o}){const[l]=e();return t(()=>{l.focus(()=>{const e=document.activeElement,t=l.getRootElement();null===t||null!==e&&t.contains(e)||t.focus({preventScroll:!0})},{defaultSelection:o})},[o,l]),null}export{o as AutoFocusPlugin};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{registerClearEditor as o}from\"@lexical/extension\";import{useLexicalComposerContext as e}from\"@lexical/react/LexicalComposerContext\";import{useLayoutEffect as n,useEffect as t}from\"react\";const i=\"undefined\"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?n:t;function r({onClear:n}){const[t]=e();return i(()=>o(t,n),[t,n]),null}export{r as ClearEditorPlugin};\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport{useLexicalComposerContext as e}from\"@lexical/react/LexicalComposerContext\";import{useLayoutEffect as t,useEffect as i,forwardRef as a,useState as r,useCallback as n,useMemo as o}from\"react\";import{jsx as l,jsxs as d,Fragment as c}from\"react/jsx-runtime\";import{$canShowPlaceholderCurry as s}from\"@lexical/text\";import{mergeRegister as u}from\"@lexical/utils\";const m=\"undefined\"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?t:i;function f({editor:e,ariaActiveDescendant:t,ariaAutoComplete:i,ariaControls:a,ariaDescribedBy:d,ariaErrorMessage:c,ariaExpanded:s,ariaInvalid:u,ariaLabel:f,ariaLabelledBy:b,ariaMultiline:p,ariaOwns:x,ariaRequired:E,autoCapitalize:v,className:w,id:y,role:C=\"textbox\",spellCheck:g=!0,style:L,tabIndex:h,\"data-testid\":D,...I},R){const[k,q]=r(e.isEditable()),z=n(t=>{t&&t.ownerDocument&&t.ownerDocument.defaultView?e.setRootElement(t):e.setRootElement(null)},[e]),A=o(()=>function(...e){return t=>{for(const i of e)\"function\"==typeof i?i(t):null!=i&&(i.current=t)}}(R,z),[z,R]);return m(()=>(q(e.isEditable()),e.registerEditableListener(e=>{q(e)})),[e]),l(\"div\",{\"aria-activedescendant\":k?t:void 0,\"aria-autocomplete\":k?i:\"none\",\"aria-controls\":k?a:void 0,\"aria-describedby\":d,...null!=c?{\"aria-errormessage\":c}:{},\"aria-expanded\":k&&\"combobox\"===C?!!s:void 0,...null!=u?{\"aria-invalid\":u}:{},\"aria-label\":f,\"aria-labelledby\":b,\"aria-multiline\":p,\"aria-owns\":k?x:void 0,\"aria-readonly\":!k||void 0,\"aria-required\":E,autoCapitalize:v,className:w,contentEditable:k,\"data-testid\":D,id:y,ref:A,role:C,spellCheck:g,style:L,tabIndex:h,...I})}const b=a(f);function p(e){return e.getEditorState().read(s(e.isComposing()))}const x=a(E);function E(t,i){const{placeholder:a,...r}=t,[n]=e();return d(c,{children:[l(b,{editor:n,...r,ref:i}),null!=a&&l(v,{editor:n,content:a})]})}function v({content:e,editor:i}){const a=function(e){const[t,i]=r(()=>p(e));return m(()=>{function t(){const t=p(e);i(t)}return t(),u(e.registerUpdateListener(()=>{t()}),e.registerEditableListener(()=>{t()}))},[e]),t}(i),[n,o]=r(i.isEditable());if(t(()=>(o(i.isEditable()),i.registerEditableListener(e=>{o(e)})),[i]),!a)return null;let d=null;return\"function\"==typeof e?d=e(n):null!==e&&(d=e),null===d?null:l(\"div\",{\"aria-hidden\":!0,children:d})}export{x as ContentEditable,b as ContentEditableElement};\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure. Also,\n * modifications have been made to integrate with our codebase.\n *\n * Original file location: src/components/editor/editor-ui/content-editable.tsx\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\nimport { ReactNode } from 'react';\nimport { ContentEditable as LexicalContentEditable } from '@lexical/react/LexicalContentEditable';\n\ntype Props = {\n placeholder: string;\n className?: string;\n placeholderClassName?: string;\n};\n\nexport function ContentEditable({\n placeholder,\n className,\n placeholderClassName,\n}: Props): ReactNode {\n return (\n \n {placeholder}\n \n }\n />\n );\n}\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure.\n *\n * Original file location: src/components/editor/context/toolbar-context.tsx\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\n'use client';\n\nimport { createContext, ReactNode, useContext, useMemo } from 'react';\nimport { LexicalEditor } from 'lexical';\n\nconst Context = createContext<\n | {\n activeEditor: LexicalEditor;\n $updateToolbar: () => void;\n blockType: string;\n setBlockType: (blockType: string) => void;\n showModal: (title: string, showModal: (onClose: () => void) => ReactNode) => void;\n }\n | undefined\n>(undefined);\n\nexport function ToolbarContext({\n activeEditor,\n $updateToolbar,\n blockType,\n setBlockType,\n showModal,\n children,\n}: {\n activeEditor: LexicalEditor;\n $updateToolbar: () => void;\n blockType: string;\n setBlockType: (blockType: string) => void;\n showModal: (title: string, showModal: (onClose: () => void) => ReactNode) => void;\n children: ReactNode;\n}) {\n const contextValue = useMemo(\n () => ({\n activeEditor,\n $updateToolbar,\n blockType,\n setBlockType,\n showModal,\n }),\n [activeEditor, $updateToolbar, blockType, setBlockType, showModal],\n );\n\n return {children};\n}\n\nexport function useToolbarContext() {\n const context = useContext(Context);\n if (!context) {\n throw new Error('useToolbarContext must be used within a ToolbarContext provider');\n }\n return context;\n}\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure.\n *\n * Original file location: src/components/editor/editor-hooks/use-modal.tsx\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\nimport { ReactNode, useCallback, useMemo, useState } from 'react';\n\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/shadcn-ui/dialog';\n\nexport function useEditorModal(): [\n ReactNode | undefined,\n (title: string, showModal: (onClose: () => void) => ReactNode) => void,\n] {\n const [modalContent, setModalContent] = useState<\n | {\n closeOnClickOutside: boolean;\n content: ReactNode;\n title: string;\n }\n | undefined\n >(undefined);\n\n const onClose = useCallback(() => {\n setModalContent(undefined);\n }, []);\n\n const modal = useMemo(() => {\n if (modalContent === undefined) {\n return undefined;\n }\n const { title, content } = modalContent;\n return (\n \n \n \n {title}\n \n {content}\n \n \n );\n }, [modalContent, onClose]);\n\n const showModal = useCallback(\n (\n title: string,\n getContent: (onClose: () => void) => ReactNode,\n closeOnClickOutside = false,\n ) => {\n setModalContent({\n closeOnClickOutside,\n content: getContent(onClose),\n title,\n });\n },\n [onClose],\n );\n\n return [modal, showModal];\n}\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure.\n *\n * Original file location: src/components/editor/plugins/toolbar/toolbar-plugin.tsx\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n *\n * Documentation for the Toolbar Plugin-framework:\n * https://shadcn-editor.vercel.app/docs/plugins/toolbar\n */\n\nimport { ReactNode, useEffect, useState } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { COMMAND_PRIORITY_CRITICAL, SELECTION_CHANGE_COMMAND } from 'lexical';\n\nimport { ToolbarContext } from '@/components/advanced/editor/context/toolbar-context';\nimport { useEditorModal } from '@/components/advanced/editor/editor-hooks/use-modal';\n\nexport function ToolbarPlugin({\n children,\n}: {\n children: (props: { blockType: string }) => ReactNode;\n}) {\n const [editor] = useLexicalComposerContext();\n\n const [activeEditor, setActiveEditor] = useState(editor);\n const [blockType, setBlockType] = useState('paragraph');\n\n const [modal, showModal] = useEditorModal();\n\n const $updateToolbar = () => {};\n\n useEffect(() => {\n return activeEditor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n (_payload, newEditor) => {\n setActiveEditor(newEditor);\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n );\n }, [activeEditor]);\n\n return (\n \n {modal}\n\n {children({ blockType })}\n \n );\n}\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure.\n *\n * Original file location: src/components/editor/editor-hooks/use-update-toolbar.ts\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\nimport { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $getSelection,\n BaseSelection,\n COMMAND_PRIORITY_CRITICAL,\n SELECTION_CHANGE_COMMAND,\n} from 'lexical';\n\nimport { useToolbarContext } from '@/components/advanced/editor/context/toolbar-context';\n\nexport function useUpdateToolbarHandler(callback: (selection: BaseSelection) => void) {\n const [editor] = useLexicalComposerContext();\n const { activeEditor } = useToolbarContext();\n\n useEffect(() => {\n return activeEditor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n if (selection) {\n callback(selection);\n }\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n );\n /**\n * We use `editor` (not `activeEditor`) in the dependency array because `activeEditor` can\n * change frequently. Re-registering the command on every `activeEditor` change would be\n * unnecessary. We only need to re-register when the main editor instance or callback changes.\n */\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editor, callback]);\n\n useEffect(() => {\n activeEditor.getEditorState().read(() => {\n const selection = $getSelection();\n if (selection) {\n callback(selection);\n }\n });\n }, [activeEditor, callback]);\n}\n","import React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Toggle as TogglePrimitive } from 'radix-ui';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\n\n// CUSTOM: Added TSDoc with links to shadcn/ui and Radix UI documentation for this export\n/**\n * Variants factory for Toggle button styling. Provides `variant` (default, outline) and `size`\n * (default, sm, lg) options.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/toggle}\n * @see Radix UI Documentation: {@link https://www.radix-ui.com/primitives/docs/components/toggle}\n */\nconst toggleVariants = cva(\n // CUSTOM: Added pr-twp at the front of the base class string to apply Platform.Bible's Tailwind\n // CSS scope isolation; all Toggle and ToggleGroupItem components inherit this via toggleVariants\n 'pr-twp tw:group/toggle tw:inline-flex tw:items-center tw:justify-center tw:gap-1 tw:rounded-lg tw:text-sm tw:font-medium tw:whitespace-nowrap tw:transition-all tw:outline-none tw:hover:bg-muted tw:hover:text-foreground tw:focus-visible:border-ring tw:focus-visible:ring-[3px] tw:focus-visible:ring-ring/50 tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-invalid:border-destructive tw:aria-invalid:ring-destructive/20 tw:aria-pressed:bg-muted tw:data-[state=on]:bg-muted tw:dark:aria-invalid:ring-destructive/40 tw:[&_svg]:pointer-events-none tw:[&_svg]:shrink-0 tw:[&_svg:not([class*=size-])]:size-4',\n {\n variants: {\n variant: {\n default: 'tw:bg-transparent',\n outline: 'tw:border tw:border-input tw:bg-transparent tw:hover:bg-muted',\n },\n size: {\n default:\n 'tw:h-8 tw:min-w-8 tw:px-2.5 tw:has-data-[icon=inline-end]:pe-2 tw:has-data-[icon=inline-start]:ps-2',\n sm: 'tw:h-7 tw:min-w-7 tw:rounded-[min(var(--tw-radius-md),12px)] tw:px-2.5 tw:text-[0.8rem] tw:has-data-[icon=inline-end]:pe-1.5 tw:has-data-[icon=inline-start]:ps-1.5 tw:[&_svg:not([class*=size-])]:size-3.5',\n lg: 'tw:h-9 tw:min-w-9 tw:px-2.5 tw:has-data-[icon=inline-end]:pe-2 tw:has-data-[icon=inline-start]:ps-2',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\n// CUSTOM: Added TSDoc with links to shadcn/ui and Radix UI documentation for this component\n/**\n * A two-state button that can be toggled on or off. Built on Radix UI primitives and styled with\n * Shadcn UI. The `pr-twp` scope class is applied via the `toggleVariants` base class string.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/toggle}\n * @see Radix UI Documentation: {@link https://www.radix-ui.com/primitives/docs/components/toggle}\n */\nfunction Toggle({\n className,\n variant = 'default',\n size = 'default',\n ...props\n}: React.ComponentProps & VariantProps) {\n return (\n \n );\n}\n\nexport { Toggle, toggleVariants };\n","'use client';\n\nimport React from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { ToggleGroup as ToggleGroupPrimitive } from 'radix-ui';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { toggleVariants } from '@/components/shadcn-ui/toggle';\n// CUSTOM: Import readDirection for RTL support in ToggleGroup\nimport { Direction, readDirection } from '@/utils/dir-helper.util';\n\n// CUSTOM: Added @inheritdoc TSDoc pointing to ToggleGroup for documentation inheritance\n/** @inheritdoc ToggleGroup */\nconst ToggleGroupContext = React.createContext<\n VariantProps & {\n spacing?: number;\n orientation?: 'horizontal' | 'vertical';\n }\n>({\n size: 'default',\n variant: 'default',\n spacing: 0,\n orientation: 'horizontal',\n});\n\n// CUSTOM: Added TSDoc with links to shadcn/ui and Radix UI documentation for this component\n/**\n * ToggleGroup components provide a set of two-state buttons that can be toggled on or off. These\n * components are built on Radix UI primitives and styled with Shadcn UI.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/toggle-group}\n * @see Radix UI Documentation: {@link https://www.radix-ui.com/primitives/docs/components/toggle-group}\n */\nfunction ToggleGroup({\n className,\n variant,\n size,\n spacing = 0,\n orientation = 'horizontal',\n children,\n ...props\n}: React.ComponentProps &\n VariantProps & {\n spacing?: number;\n orientation?: 'horizontal' | 'vertical';\n }) {\n // CUSTOM: Read text direction so ToggleGroup passes dir to Radix, enabling RTL support\n const dir: Direction = readDirection();\n return (\n \n {/* CUSTOM: Memoize context value to avoid creating a new object reference on every render,\n which would cause all consumers to re-render unnecessarily (react/jsx-no-constructed-context-values) */}\n ({ variant, size, spacing, orientation }),\n [variant, size, spacing, orientation],\n )}\n >\n {children}\n \n \n );\n}\n\n// CUSTOM: Added @inheritdoc TSDoc pointing to ToggleGroup for documentation inheritance\n/** @inheritdoc ToggleGroup */\nfunction ToggleGroupItem({\n className,\n children,\n variant = 'default',\n size = 'default',\n ...props\n}: React.ComponentProps & VariantProps) {\n const context = React.useContext(ToggleGroupContext);\n\n return (\n \n {children}\n \n );\n}\n\nexport { ToggleGroup, ToggleGroupItem };\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure.\n *\n * Original file location: src/components/editor/plugins/toolbar/font-format-toolbar-plugin.tsx\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n *\n * Documentation for this specific plugin:\n * https://shadcn-editor.vercel.app/docs/plugins/toolbar/font-format-toolbar\n */\n\nimport { useCallback, useState } from 'react';\nimport { $isTableSelection } from '@lexical/table';\nimport { $isRangeSelection, BaseSelection, FORMAT_TEXT_COMMAND } from 'lexical';\nimport { BoldIcon, ItalicIcon } from 'lucide-react';\n\nimport { useToolbarContext } from '@/components/advanced/editor/context/toolbar-context';\nimport { useUpdateToolbarHandler } from '@/components/advanced/editor/editor-hooks/use-update-toolbar';\nimport { ToggleGroup, ToggleGroupItem } from '@/components/shadcn-ui/toggle-group';\n\nconst FORMATS = [\n { format: 'bold', icon: BoldIcon, label: 'Bold' },\n { format: 'italic', icon: ItalicIcon, label: 'Italic' },\n // CUSTOM: TJ removed underline and strikethrough as they are not supported by the current comment\n // data conversion and are not in P9 anyway. We can add these back if we ever get this supported.\n /* { format: 'underline', icon: UnderlineIcon, label: 'Underline' },\n { format: 'strikethrough', icon: StrikethroughIcon, label: 'Strikethrough' }, */\n] as const;\n\nexport function FontFormatToolbarPlugin() {\n const { activeEditor } = useToolbarContext();\n const [activeFormats, setActiveFormats] = useState([]);\n\n const $updateToolbar = useCallback((selection: BaseSelection) => {\n if ($isRangeSelection(selection) || $isTableSelection(selection)) {\n const formats: string[] = [];\n FORMATS.forEach(({ format }) => {\n if (selection.hasFormat(format)) {\n formats.push(format);\n }\n });\n setActiveFormats((prev) => {\n // Only update if formats have changed\n if (prev.length !== formats.length || !formats.every((f) => prev.includes(f))) {\n return formats;\n }\n return prev;\n });\n }\n }, []);\n\n useUpdateToolbarHandler($updateToolbar);\n\n return (\n \n {FORMATS.map(({ format, icon: Icon, label }) => (\n {\n activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, format);\n }}\n >\n \n \n ))}\n \n );\n}\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure. Also,\n * modifications have been made to integrate with our codebase.\n *\n * Original file location: src/components/blocks/editor-00/plugins.tsx\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\nimport { useEffect, useState } from 'react';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';\nimport { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';\nimport { ClearEditorPlugin } from '@lexical/react/LexicalClearEditorPlugin';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { CLEAR_EDITOR_COMMAND } from 'lexical';\n\nimport { ContentEditable } from '@/components/advanced/editor/editor-ui/content-editable';\nimport { ToolbarPlugin } from '@/components/advanced/editor/plugins/toolbar/toolbar-plugin';\nimport { FontFormatToolbarPlugin } from '@/components/advanced/editor/plugins/toolbar/font-format-toolbar-plugin';\n\nfunction ClearEditorBridge({ onClear }: { onClear?: (clearFn: () => void) => void }) {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (onClear) {\n onClear(() => {\n editor.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);\n });\n }\n }, [editor, onClear]);\n\n return undefined;\n}\n\nexport function Plugins({\n placeholder = 'Start typing ...',\n autoFocus = false,\n onClear,\n}: {\n placeholder?: string;\n autoFocus?: boolean;\n onClear?: (clearFn: () => void) => void;\n}) {\n const [, setFloatingAnchorElem] = useState(undefined);\n\n const onRef = (_floatingAnchorElem: HTMLDivElement) => {\n if (_floatingAnchorElem !== undefined) {\n setFloatingAnchorElem(_floatingAnchorElem);\n }\n };\n\n return (\n
\n {/* toolbar plugins */}\n \n {() => (\n
\n \n
\n )}\n
\n\n
\n \n \n
\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n {autoFocus && }\n\n \n \n {/* editor plugins */}\n
\n {/* actions plugins */}\n \n );\n}\n","/**\n * This file was automatically generated on installation of the Shadcn/Lexical editor. The default\n * location of this file has been changed to integrate better with our project structure. Also,\n * modifications have been made to integrate with our codebase.\n *\n * Original file location: src/components/blocks/editor-00/editor.tsx\n *\n * Shadcn/Lexical Editor Documentation: https://shadcn-editor.vercel.app/docs/\n */\n\nimport { InitialConfigType, LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';\nimport { EditorState, SerializedEditorState } from 'lexical';\n\nimport { editorTheme } from '@/components/advanced/editor/themes/editor-theme';\nimport { TooltipProvider } from '@/components/shadcn-ui/tooltip';\nimport { cn } from '@/utils/shadcn-ui/utils';\n\nimport { nodes } from './nodes';\nimport { Plugins } from './plugins';\n\nconst editorConfig: InitialConfigType = {\n namespace: 'commentEditor',\n theme: editorTheme,\n nodes,\n onError: (error: Error) => {\n console.error(error);\n },\n};\n\n/**\n * Shadcn UI based Lexical Editor component\n *\n * Documentation: https://shadcn-editor.vercel.app/docs/\n */\nexport function Editor({\n editorState,\n editorSerializedState,\n onChange,\n onSerializedChange,\n placeholder = 'Start typing…',\n autoFocus = false,\n onClear,\n className,\n}: {\n editorState?: EditorState;\n editorSerializedState?: SerializedEditorState;\n onChange?: (editorState: EditorState) => void;\n onSerializedChange?: (editorSerializedState: SerializedEditorState) => void;\n placeholder?: string;\n autoFocus?: boolean;\n onClear?: (clearFn: () => void) => void;\n className?: string;\n}) {\n return (\n // CUSTOM: Added `className` prop\n \n \n \n \n\n {\n onChange?.(latestEditorState);\n onSerializedChange?.(latestEditorState.toJSON());\n }}\n />\n \n \n \n );\n}\n","import { editorTheme } from '@/components/advanced/editor/themes/editor-theme';\nimport { createHeadlessEditor } from '@lexical/headless';\nimport { $generateHtmlFromNodes, $generateNodesFromDOM } from '@lexical/html';\nimport {\n $getRoot,\n $insertNodes,\n SerializedEditorState,\n SerializedElementNode,\n SerializedLexicalNode,\n SerializedTextNode,\n} from 'lexical';\nimport React from 'react';\nimport { nodes } from './nodes';\n\n/**\n * Focus a content-editable element within a container and move the cursor to the end\n *\n * @param container - The container element to search within\n * @returns True if a content-editable element was found and focused, false otherwise\n */\nexport function focusContentEditable(container: HTMLElement): boolean {\n const contentEditableField = container.querySelector('[contenteditable=\"true\"]');\n if (!contentEditableField) return false;\n\n contentEditableField.focus();\n\n // Move cursor to the end\n const selection = window.getSelection();\n const range = document.createRange();\n range.selectNodeContents(contentEditableField);\n range.collapse(false); // false = collapse to end\n selection?.removeAllRanges();\n selection?.addRange(range);\n\n return true;\n}\n\n/**\n * Recursively check if any children have meaningful editor content\n *\n * @param children - Array of serialized lexical nodes to check\n * @returns True if any child has content, false otherwise\n */\nfunction doChildrenHaveEditorContent(\n children: (SerializedLexicalNode | SerializedElementNode | SerializedTextNode)[] | undefined,\n): boolean {\n if (!children) return false;\n\n return children.some(\n (child: SerializedLexicalNode | SerializedElementNode | SerializedTextNode) => {\n if (child && 'text' in child && child.text.trim().length > 0) return true;\n\n if (!child || !('children' in child)) return false;\n\n return doChildrenHaveEditorContent(child.children);\n },\n );\n}\n\n/**\n * Check if the editor state has any meaningful content\n *\n * @param editorState - SerializedEditorState to check\n * @returns True if the editor has content, false if it's empty\n */\nexport function hasEditorContent(editorState: SerializedEditorState | undefined): boolean {\n if (!editorState?.root?.children) return false;\n return doChildrenHaveEditorContent(editorState.root.children);\n}\n\n/**\n * Convert HTML string to Lexical SerializedEditorState\n *\n * @param html - HTML string to convert\n * @returns SerializedEditorState that can be used with the Editor component\n */\nexport function htmlToEditorState(html: string): SerializedEditorState {\n if (!html || html.trim() === '') {\n throw new Error('Input HTML is empty');\n }\n\n const editor = createHeadlessEditor({\n namespace: 'EditorUtils',\n theme: editorTheme,\n nodes,\n onError: (error: Error) => {\n console.error(error);\n },\n });\n\n let serializedState: SerializedEditorState | undefined;\n\n editor.update(\n () => {\n const parser = new DOMParser();\n const dom = parser.parseFromString(html, 'text/html');\n const generatedNodes = $generateNodesFromDOM(editor, dom);\n\n $getRoot().clear();\n $insertNodes(generatedNodes);\n },\n {\n discrete: true,\n },\n );\n\n editor.getEditorState().read(() => {\n serializedState = editor.getEditorState().toJSON();\n });\n\n if (!serializedState) {\n throw new Error('Failed to convert HTML to editor state');\n }\n\n return serializedState;\n}\n\n/**\n * Convert Lexical SerializedEditorState to HTML string\n *\n * @param editorState - SerializedEditorState to convert\n * @returns HTML string\n */\nexport function editorStateToHtml(editorState: SerializedEditorState): string {\n const editor = createHeadlessEditor({\n namespace: 'EditorUtils',\n theme: editorTheme,\n nodes,\n onError: (error: Error) => {\n console.error(error);\n },\n });\n\n const parsedEditorState = editor.parseEditorState(JSON.stringify(editorState));\n editor.setEditorState(parsedEditorState);\n\n let html = '';\n\n editor.getEditorState().read(() => {\n html = $generateHtmlFromNodes(editor);\n });\n\n // Clean up the HTML to remove Shadcn/Lexical-specific attributes and simplify structure\n html = html\n // Remove style attributes\n .replace(/\\s+style=\"[^\"]*\"/g, '')\n // Remove all class attributes (including Tailwind classes)\n .replace(/\\s+class=\"[^\"]*\"/g, '')\n // Remove empty spans\n .replace(/(.*?)<\\/span>/g, '$1')\n // Simplify nested bold tags (e.g., text -> text)\n .replace(/]*>(.*?)<\\/strong><\\/b>/g, '$1')\n .replace(/]*>(.*?)<\\/b><\\/strong>/g, '$1')\n // Simplify nested italic tags (e.g., text -> text)\n .replace(/]*>(.*?)<\\/em><\\/i>/g, '$1')\n .replace(/]*>(.*?)<\\/i><\\/em>/g, '$1')\n // Simplify nested underline tags (e.g., text -> text)\n .replace(/]*>(.*?)<\\/span><\\/u>/g, '$1')\n // Simplify nested strikethrough tags (e.g., text -> text)\n .replace(/]*>(.*?)<\\/span><\\/s>/g, '$1')\n // Convert all
variants to XML-compatible
for Paratext\n .replace(//gi, '
');\n\n return html;\n}\n\n/**\n * Handle keyboard events for editor navigation to prevent parent listbox from intercepting\n * navigation keys. This should be used on a container wrapping the Editor component.\n *\n * @param event - The keyboard event\n * @returns True if the event was handled (and should be stopped from propagating), false otherwise\n */\nexport function handleEditorKeyNavigation(event: React.KeyboardEvent): boolean {\n // Keys that should be kept within the editor for navigation\n const navigationKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];\n\n if (navigationKeys.includes(event.key)) {\n event.stopPropagation();\n return true;\n }\n\n return false;\n}\n","import { Button } from '@/components/shadcn-ui/button';\nimport { ButtonGroup, ButtonGroupSeparator } from '@/components/shadcn-ui/button-group';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport { Check, X } from 'lucide-react';\n\n/**\n * Object containing all keys used for localization in this component. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component.\n */\nexport const CANCEL_ACCEPT_BUTTONS_STRING_KEYS = Object.freeze([\n '%cancelButton_tooltip%',\n '%acceptButton_tooltip%',\n] as const);\n\nexport type CancelAcceptButtonsLocalizedStrings = {\n [key in (typeof CANCEL_ACCEPT_BUTTONS_STRING_KEYS)[number]]?: string;\n};\n\nconst localizeString = (\n strings: CancelAcceptButtonsLocalizedStrings,\n key: keyof CancelAcceptButtonsLocalizedStrings,\n) => strings[key] ?? key;\n\nexport type CancelAcceptButtonsProps = {\n /** Function to call when Cancel is clicked. */\n onCancelClick: () => void;\n /** Function to call when Accept is clicked. */\n onAcceptClick: () => void;\n /** Whether the Accept button is enabled. */\n canAccept?: boolean;\n /**\n * Localized strings for button tooltips and aria-labels. Falls back to the key itself if not\n * provided.\n */\n localizedStrings?: CancelAcceptButtonsLocalizedStrings;\n /** CSS class name for the buttons. Defaults to \"tw:h-6 tw:w-6\". */\n className?: string;\n /**\n * Optional context-specific label for the accept button (e.g. \"Save Comment\", \"Save Footnote\").\n * When provided, overrides the generic `%acceptButton_tooltip%` localized string.\n */\n acceptLabel?: string;\n};\n\n/**\n * Cancel and Accept buttons with tooltips in a ButtonGroup. Suitable for use in any editor toolbar.\n * Tooltip text defaults to the localization key if no localized strings are provided.\n */\nexport function CancelAcceptButtons({\n onCancelClick,\n onAcceptClick,\n canAccept = true,\n localizedStrings = {},\n className = 'tw:h-6 tw:w-6',\n acceptLabel,\n}: CancelAcceptButtonsProps) {\n const cancelLocalized = localizeString(localizedStrings, '%cancelButton_tooltip%');\n const acceptLocalized = acceptLabel ?? localizeString(localizedStrings, '%acceptButton_tooltip%');\n\n return (\n \n \n \n \n \n \n \n \n \n

{cancelLocalized}

\n
\n
\n
\n \n \n \n \n \n \n \n \n \n

{acceptLocalized}

\n
\n
\n
\n
\n );\n}\n\nexport default CancelAcceptButtons;\n","import { ConflictResolutionOptions, LanguageStrings, LegacyComment } from 'platform-bible-utils';\n\n// Re-export so this module (and the platform-bible-react barrel) stays the import site for the\n// ConflictNoteCard's resolution types. The single definition lives in platform-bible-utils.\nexport type { ConflictResolutionOptions };\n\n/**\n * The conflict card's action state. Extends the backend {@link ConflictResolutionOptions} with a\n * client-only `'loading'` sentinel used while the getConflictResolutionOptions result is in flight,\n * so the card can render a skeleton instead of momentarily flashing the read-only \"resolved\" view.\n * `'loading'` is deliberately NOT part of the platform-bible-utils contract - it never crosses the\n * C#<->TS boundary.\n */\nexport type ConflictCardActions = ConflictResolutionOptions | 'loading';\n\n/**\n * The one conflict type whose root note carries discrete diff/result text and drives the\n * ConflictNoteCard. Shared so the card and the comment thread test the same literal.\n */\nexport const VERSE_TEXT_CONFLICT = 'verseText';\n\n/**\n * The resolution a user picks for a conflict: keep the accepted (winning) side, take the rejected\n * (losing) side, or merge (combine) both sides.\n */\nexport type ConflictResolution = 'accept' | 'reject' | 'merge';\n\n/**\n * How an already-resolved conflict was resolved, derived from the resolution comment's\n * `conflictResolutionAction`:\n *\n * - `'accept'`: resolved by accepting (no text was written); the accepted side stands.\n * - `'reject'`: resolved by rejecting (the rejected side was written into the verse).\n * - `'merged'`: resolved by combining both changes (PT10's \"Combine both changes\" option, or a PT9\n * three-way merge). The card shows the merged verse text (`mergedText`); the outcome itself is\n * stated in prose by CommentItem's resolution-reply banner, not on the card.\n *\n * Distinct from {@link ConflictResolution} (the live accept/reject choice) because it adds the\n * `'merged'` legacy outcome and is only meaningful for a conflict that is already resolved.\n */\nexport type ConflictResolutionOutcome = 'accept' | 'reject' | 'merged';\n\n/**\n * Localization keys used by the ConflictNoteCard. Pass into the useLocalizedStrings hook (in the\n * consuming extension) and forward the result via the localizedStrings prop.\n */\nexport const CONFLICT_NOTE_STRING_KEYS = Object.freeze([\n '%conflict_note_description_verseText%',\n // Accessible name for the resolution radio group (the group has no other visible \n );\n };\n\n return (\n // Contain every click inside the card (selecting an option, pressing Save) so it never bubbles\n // up to toggle the enclosing CommentThread open/closed. The thread toggles on click only, so a\n // single onClick guard at the root is enough; this container is not itself an interactive control\n // and needs no keyboard handler (the thread has no keyboard toggle to intercept).\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events\n
e.stopPropagation()}>\n

\n {localizedStrings['%conflict_note_description_verseText%'] ??\n 'Conflicting changes were made to the verse text.'}\n

\n\n {isLoading && (\n
\n \n \n \n
\n )}\n {!isLoading && isReadOnly && renderResolvedResult()}\n {!isLoading && !isReadOnly && (\n <>\n

\n {localizedStrings['%conflict_note_choose_prompt%'] ?? 'Select which change to keep:'}\n

\n\n {/* The whole group is disabled while resolving. When stale, accept stays enabled\n (it's the only still-valid resolution) and only the reject option below is\n individually disabled. */}\n \n {radioOptions.map((option) => {\n const isStaleReject = isStaleRejectOption(option);\n if (!isStaleReject) return renderOptionCard(option);\n return (\n \n \n {/* asChild so the tooltip wraps the disabled option card and still receives\n pointer events over it */}\n {renderOptionCard(option)}\n {staleNotice}\n \n \n );\n })}\n \n\n {/* Stays mounted (present but disabled) even when stale, so the selection never shifts the\n layout. The tooltip message switches on whether Save is a no-op. */}\n \n \n \n {/* span wrapper so the tooltip still receives pointer events when the button is\n disabled */}\n \n onResolve?.(effectiveResolution)}\n >\n {localizedStrings['%conflict_note_save_and_resolve%'] ?? 'Save and resolve'}\n \n \n \n {saveTooltip && {saveTooltip}}\n \n \n \n )}\n
\n );\n}\n\nexport default ConflictNoteCard;\n","import { LanguageStrings, LegacyComment, LocalizeKey } from 'platform-bible-utils';\nimport { useMemo } from 'react';\nimport { ConflictResolutionOutcome } from './conflict-note-card.types';\nimport { DiffHtml, sanitizeDiffHtml } from './conflict-diff';\n\n/** The localized resolved-outcome sentence for each resolution, keyed by resolvedResolution. */\nconst RESOLVED_SUMMARY: Record =\n {\n accept: {\n key: '%conflict_note_summary_resolved_kept_current%',\n fallback: 'Conflicting edits were resolved. Kept the current text.',\n },\n reject: {\n key: '%conflict_note_summary_resolved_used_other%',\n fallback: 'Conflicting edits were resolved. Used the other change.',\n },\n merged: {\n key: '%conflict_note_summary_resolved_combined%',\n fallback: 'Conflicting edits were resolved. Combined both changes.',\n },\n };\n\n/** Props for {@link ConflictThreadSummary}. */\nexport interface ConflictThreadSummaryProps {\n /** The conflict thread's root note. Unresolved: its `rejectedText` diff is previewed. */\n comment: LegacyComment;\n /** Localized strings (the same set passed to ConflictNoteCard). */\n localizedStrings: LanguageStrings;\n /**\n * How the conflict was resolved, or undefined while unresolved. When set, the summary shows only\n * the matching outcome sentence (no verse text); when undefined, it shows the prompt plus the\n * diff.\n */\n resolvedResolution?: ConflictResolutionOutcome;\n}\n\n/**\n * The collapsed preview of a verseText conflict thread. Replaces the raw PT9 note body (which\n * references an \"in red\" coloring the collapsed view never applied, and never updates after\n * resolution) with a status-aware one-liner. Unresolved: a prompt sentence plus the note's diff\n * rendered with the shared red/green coloring. Resolved: only the outcome sentence, no verse text.\n */\nexport function ConflictThreadSummary({\n comment,\n localizedStrings,\n resolvedResolution,\n}: ConflictThreadSummaryProps) {\n // Hooks must run unconditionally on every render, so this is computed before the early return\n // below even though it's only used in the unresolved branch.\n const diffHtml = useMemo(\n () => sanitizeDiffHtml(comment.rejectedText ?? ''),\n [comment.rejectedText],\n );\n\n if (resolvedResolution) {\n const { key, fallback } = RESOLVED_SUMMARY[resolvedResolution];\n return (\n

\n {localizedStrings[key] ?? fallback}\n

\n );\n }\n\n const prompt =\n localizedStrings['%conflict_note_summary_unresolved%'] ??\n 'Conflicting edits. Choose which change to keep.';\n\n return (\n
\n

{prompt}

\n {diffHtml ? : undefined}\n
\n );\n}\n","import { CommentStatus, LegacyComment } from 'platform-bible-utils';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { ConflictResolutionCallbacks } from './comment-list.types';\nimport {\n ConflictCardActions,\n ConflictResolution,\n ConflictResolutionOutcome,\n} from './conflict-note-card.types';\nimport { actionToOutcome } from './comment-list.utils';\n\n/** Maps a live resolution choice to the already-resolved outcome it produces. */\nfunction resolutionToOutcome(resolution: ConflictResolution): ConflictResolutionOutcome {\n if (resolution === 'reject') return 'reject';\n if (resolution === 'merge') return 'merged';\n return 'accept';\n}\n\n/** Inputs {@link useConflictResolution} needs from the thread it serves. */\nexport interface UseConflictResolutionParams {\n /** The conflict thread's id. */\n threadId: string;\n /** The thread's current status (drives when the resolved outcome is derived). */\n threadStatus?: CommentStatus;\n /** Whether the thread is expanded (the options fetch is deferred until it is). */\n isSelected: boolean;\n /** The thread's non-deleted comments, newest-last (scanned for the resolution stamp). */\n activeComments: LegacyComment[];\n /** The resolve + getOptions callbacks; absent renders a read-only card. */\n conflictResolution?: ConflictResolutionCallbacks;\n}\n\n/** What {@link useConflictResolution} returns to ConflictThread. */\nexport interface UseConflictResolutionResult {\n /** The card's action state, including the `'loading'` sentinel while options are in flight. */\n conflictOptions: ConflictCardActions;\n /** True while a resolve call is in flight. */\n isResolving: boolean;\n /** Applies a resolution; on success optimistically shows the chosen outcome (no result flash). */\n resolve: (resolution: ConflictResolution) => Promise;\n /** How the conflict was resolved (status-aware); `undefined` while it is still unresolved. */\n resolvedResolution: ConflictResolutionOutcome | undefined;\n /** Whether to show the header resolve check (options are loaded AND actually resolvable). */\n showResolveCheck: boolean;\n}\n\n/**\n * Owns all conflict-resolution state and logic for a conflict thread: it fetches the resolution\n * options only once the thread is open (a `'loading'` sentinel renders a skeleton meanwhile, never\n * the read-only view), applies a resolution optimistically so a reject/merge shows the correct\n * result immediately instead of flashing the accepted text, derives the resolved outcome in a\n * status-aware way, and gates the resolve check on real resolvability.\n */\nexport function useConflictResolution({\n threadId,\n threadStatus,\n isSelected,\n activeComments,\n conflictResolution,\n}: UseConflictResolutionParams): UseConflictResolutionResult {\n // Starts 'loading' and is fetched only when the thread is selected, so a card that isn't open\n // never spends a round-trip. 'loading' renders a skeleton, never the read-only \"resolved\" view.\n const [conflictOptions, setConflictOptions] = useState('loading');\n const [isResolving, setIsResolving] = useState(false);\n // Set on a successful resolve so the card shows the chosen result immediately, before the\n // fire-and-forget data update round-trips and flips threadStatus to 'Resolved'.\n const [optimisticOutcome, setOptimisticOutcome] = useState<\n ConflictResolutionOutcome | undefined\n >();\n\n const getOptions = conflictResolution?.getOptions;\n const resolveCallback = conflictResolution?.resolve;\n\n // Fetch the resolution options only when the thread is open; re-run on status change (resolve and\n // reopen both change availability). Degrades to 'none' on any failure so the skeleton never hangs.\n // A fresh resolvable result clears any stale optimistic outcome (a reopened, re-resolvable thread).\n useEffect(() => {\n let isCurrent = true;\n if (!isSelected) {\n setConflictOptions('loading');\n return undefined;\n }\n const check = async () => {\n let options: ConflictCardActions;\n try {\n options = getOptions ? await getOptions(threadId) : 'none';\n } catch {\n options = 'none';\n }\n if (!isCurrent) return;\n setConflictOptions(options);\n if (options !== 'none') setOptimisticOutcome(undefined);\n };\n check();\n return () => {\n isCurrent = false;\n };\n }, [isSelected, threadId, threadStatus, getOptions]);\n\n // Reentrancy guard read/written synchronously so a second click that lands before React re-renders\n // (and disables the button) can't fire a second resolve. `isResolving` state drives the disabled UI;\n // this ref is the source of truth within a single tick.\n const isResolvingRef = useRef(false);\n const resolve = useCallback(\n async (resolution: ConflictResolution) => {\n if (!resolveCallback || isResolvingRef.current) return;\n isResolvingRef.current = true;\n setIsResolving(true);\n try {\n const success = await resolveCallback(threadId, resolution);\n if (success) {\n // Show the chosen result now (optimistic) and lock the controls; the data-update refetch\n // confirms via threadStatus. Prevents the read-only view from flashing the accepted text.\n setOptimisticOutcome(resolutionToOutcome(resolution));\n setConflictOptions('none');\n }\n } catch {\n // A consumer's resolve should report failure by resolving to false, not by throwing. If it\n // throws anyway, swallow it here: resolve() is invoked from un-awaited onClicks, so an\n // uncaught rejection would surface as an unhandled promise rejection. The card simply stays\n // resolvable (success never applied) so the user can retry.\n } finally {\n // Always clear the busy state, even on a rejecting resolve, otherwise the card stays locked\n // in its isResolving state.\n isResolvingRef.current = false;\n setIsResolving(false);\n }\n },\n [resolveCallback, threadId],\n );\n\n // The outcome an already-resolved conflict was resolved with, read off the MOST-RECENT resolution\n // comment's conflictResolutionAction. Only the newest resolution counts: a re-resolve leaves the\n // earlier resolution comment in place (reject -> reopen -> accept keeps the old 'replaced'\n // comment), and an accept stamps no action, so scanning for the first non-accept action found\n // would report the stale reject. Match on the resolution comment (status 'Resolved') instead;\n // absent action on it means accept. Only meaningful once the thread itself is 'Resolved' — while\n // still 'Todo' (a reopened conflict) this stays undefined so the collapsed summary and the card\n // don't contradict the live selector.\n const derivedResolution = useMemo(() => {\n if (threadStatus !== 'Resolved') return undefined;\n for (let i = activeComments.length - 1; i >= 0; i -= 1) {\n if (activeComments[i].status === 'Resolved') {\n return actionToOutcome(activeComments[i].conflictResolutionAction);\n }\n }\n return 'accept';\n }, [threadStatus, activeComments]);\n\n const resolvedResolution = derivedResolution ?? optimisticOutcome;\n\n const showResolveCheck = conflictOptions !== 'loading' && conflictOptions !== 'none';\n\n return { conflictOptions, isResolving, resolve, resolvedResolution, showResolveCheck };\n}\n","import { ReactNode, useMemo } from 'react';\nimport { ConflictThreadProps } from './comment-list.types';\nimport { CommentThread } from './comment-thread.component';\nimport { ConflictNoteCard } from './conflict-note-card.component';\nimport { ConflictThreadSummary } from './conflict-thread-summary.component';\nimport { ResolveCheckButton } from './resolve-check-button.component';\nimport { isVerseTextConflictNote } from './comment-list.utils';\nimport { useConflictResolution } from './use-conflict-resolution.hook';\n\n/**\n * The conflict-thread container. Wraps the conflict-agnostic {@link CommentThread} shell and fills\n * its slots with conflict-specific content:\n *\n * - A verseText conflict shows the resolution UI - the ConflictNoteCard when the thread is open, the\n * collapsed ConflictThreadSummary otherwise - plus a conflict-gated resolve check.\n * - Any other conflict type falls through to the shell's default CommentItem (keeping its\n * author/date/status/menu) and the shell's generic status-resolve check, since a non-verseText\n * conflict is resolved through a plain status change, not resolveConflict.\n *\n * All conflict state and logic live in {@link useConflictResolution}.\n */\nexport function ConflictThread(props: ConflictThreadProps) {\n const {\n comments,\n localizedStrings,\n isSelected = false,\n threadId,\n threadStatus,\n conflictResolution,\n } = props;\n\n const activeComments = useMemo(() => comments.filter((comment) => !comment.deleted), [comments]);\n // The conflict root is not reliably comments[0]: a fragment-merged thread (PT9 FB-22392) tail-\n // appends the older fragment's comments, leaving the genuine root mid-list (see\n // LegacyCommentThread.comments and C# RootCommentId). Only the root carries conflictType and the\n // diff/result fields the card reads, so locate it by that field, not by position.\n const rootComment = useMemo(\n () => activeComments.find((comment) => comment.conflictType) ?? activeComments[0],\n [activeComments],\n );\n\n const { conflictOptions, isResolving, resolve, resolvedResolution, showResolveCheck } =\n useConflictResolution({\n threadId,\n threadStatus,\n isSelected,\n activeComments,\n conflictResolution,\n });\n\n const isVerseText = isVerseTextConflictNote(rootComment);\n\n // verseText conflicts render the resolution UI; other conflict types leave rootContentSlot\n // undefined so the shell renders its default CommentItem (the non-verseText chrome fix).\n let rootContentSlot: ReactNode;\n if (isVerseText && rootComment) {\n rootContentSlot = isSelected ? (\n \n ) : (\n \n );\n }\n\n // For a verseText conflict, override the header check with the conflict-gated resolve.\n // ResolveCheckButton self-gates on `show` (renders nothing when false), and passing the element\n // rather than a bare `false` still overrides the shell's generic status-resolve default — so a\n // non-resolvable verseText conflict shows no ✓. For a non-verseText conflict, leave the slot\n // undefined so the shell renders its generic status-resolve check.\n let resolveActionSlot: ReactNode;\n if (isVerseText) {\n resolveActionSlot = (\n resolve('accept')}\n ariaLabel={localizedStrings['%comment_aria_resolve_thread%'] ?? 'Resolve thread'}\n />\n );\n }\n\n return (\n \n );\n}\n\nexport default ConflictThread;\n","import { ListboxOption, useListbox } from '@/hooks/listbox-keyboard-navigation.hook';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport React, { RefObject, useCallback, useEffect, useState } from 'react';\nimport { AddCommentToThreadOptions, COMMENT_LIST_ELEMENT_ID, CommentListProps } from './comment-list.types';\nimport { CommentThread } from './comment-thread.component';\nimport { ConflictThread } from './conflict-thread.component';\n\n/**\n * Component for rendering a list of comment threads\n *\n * @param CommentListProps Props for the CommentList component\n */\nexport default function CommentList({\n className = '',\n classNameForVerseText,\n threads,\n currentUser,\n localizedStrings,\n handleAddCommentToThread,\n handleUpdateComment,\n handleDeleteComment,\n handleReadStatusChange,\n assignableUsers,\n canUserAddCommentToThread,\n canUserAssignThreadCallback,\n canUserResolveThreadCallback,\n canUserEditOrDeleteCommentCallback,\n selectedThreadId: externalSelectedThreadId,\n onSelectedThreadChange,\n onVerseRefClick,\n conflictResolution,\n}: CommentListProps) {\n const [expandedThreadIds, setExpandedThreadIds] = useState>(new Set());\n const [lastInteractedThreadId, setLastInteractedThreadId] = useState();\n const [lastAssignedUser, setLastAssignedUser] = useState();\n\n const handleAddCommentToThreadWithTracking = useCallback(\n async (options: AddCommentToThreadOptions) => {\n const result = await handleAddCommentToThread(options);\n // result === undefined means the submission failed or produced no output; only update the\n // last assigned user when the submission succeeded and an explicit non-empty assignment was\n // made. Exclude '' (Unassigned) so that selecting \"Unassigned\" doesn't become sticky and\n // silently clear the assignee on other threads via auto-population.\n if (\n result !== undefined &&\n options.assignedUser !== undefined &&\n options.assignedUser !== ''\n ) {\n setLastAssignedUser(options.assignedUser);\n }\n return result;\n },\n [handleAddCommentToThread],\n );\n\n // When external selection changes, add it to expanded set\n useEffect(() => {\n if (externalSelectedThreadId) {\n setExpandedThreadIds((prev) => new Set(prev).add(externalSelectedThreadId));\n setLastInteractedThreadId(externalSelectedThreadId);\n }\n }, [externalSelectedThreadId]);\n\n const activeThreads = threads.filter((thread) =>\n thread.comments.some((comment) => !comment.deleted),\n );\n\n const options: ListboxOption[] = activeThreads.map((thread) => ({ id: thread.id }));\n\n const handleKeyboardSelectThread = useCallback(\n (option: ListboxOption) => {\n setExpandedThreadIds((prev) => new Set(prev).add(option.id));\n setLastInteractedThreadId(option.id);\n onSelectedThreadChange?.(option.id);\n },\n [onSelectedThreadChange],\n );\n\n const handleSelectThread = useCallback(\n (threadId: string) => {\n const isCollapsing = expandedThreadIds.has(threadId);\n setExpandedThreadIds((prev) => {\n const next = new Set(prev);\n if (next.has(threadId)) {\n next.delete(threadId);\n } else {\n next.add(threadId);\n }\n return next;\n });\n setLastInteractedThreadId(threadId);\n onSelectedThreadChange?.(isCollapsing ? undefined : threadId);\n },\n [expandedThreadIds, onSelectedThreadChange],\n );\n\n const { listboxRef, activeId, handleKeyDown } = useListbox({\n options,\n onOptionSelect: handleKeyboardSelectThread,\n });\n\n // Collapse the last interacted thread when Escape is pressed\n const handleKeyDownWithEscape = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === 'Escape') {\n if (lastInteractedThreadId && expandedThreadIds.has(lastInteractedThreadId)) {\n setExpandedThreadIds((prev) => {\n const next = new Set(prev);\n next.delete(lastInteractedThreadId);\n return next;\n });\n setLastInteractedThreadId(undefined);\n onSelectedThreadChange?.(undefined);\n }\n event.preventDefault();\n event.stopPropagation();\n } else {\n handleKeyDown(event);\n }\n },\n [lastInteractedThreadId, expandedThreadIds, handleKeyDown, onSelectedThreadChange],\n );\n\n return (\n }\n aria-activedescendant={activeId ?? undefined}\n aria-label=\"Comments\"\n className={cn(\n 'tw:flex tw:w-full tw:flex-col tw:space-y-3 tw:outline-hidden tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-1 tw:focus:ring-offset-background',\n\n className,\n )}\n onKeyDown={handleKeyDownWithEscape}\n >\n {activeThreads.map((thread) => {\n // The generic shell props both thread variants share. Conflict threads render through\n // ConflictThread (which owns the resolve UI and forwards these slots to the shared\n // CommentThread shell) and additionally receive the conflict-resolution callbacks; every\n // other thread renders CommentThread directly, keeping the shell conflict-agnostic.\n const commonThreadProps = {\n classNameForVerseText,\n comments: thread.comments,\n localizedStrings,\n verseRef: thread.verseRef,\n handleSelectThread,\n threadId: thread.id,\n thread,\n isRead: thread.isRead,\n isSelected: expandedThreadIds.has(thread.id),\n currentUser,\n assignedUser: thread.assignedUser,\n threadStatus: thread.status,\n handleAddCommentToThread: handleAddCommentToThreadWithTracking,\n handleUpdateComment,\n handleDeleteComment,\n handleReadStatusChange,\n assignableUsers,\n canUserAddCommentToThread,\n canUserAssignThreadCallback,\n canUserResolveThreadCallback,\n canUserEditOrDeleteCommentCallback,\n onVerseRefClick,\n initialAssignedUser: lastAssignedUser,\n };\n return (\n \n {thread.type === 'Conflict' ? (\n \n ) : (\n \n )}\n \n );\n })}\n \n );\n}\n","import { FilterIcon } from 'lucide-react';\nimport { Table } from '@tanstack/react-table';\n\nimport { Button } from '@/components/shadcn-ui/button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/shadcn-ui/dropdown-menu';\n\ninterface DataTableViewOptionsProps {\n table: Table;\n}\n\nexport function DataTableViewOptions({ table }: DataTableViewOptionsProps) {\n return (\n \n \n \n \n \n Toggle columns\n \n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n column.toggleVisibility(!!value)}\n >\n {column.id}\n \n );\n })}\n \n \n );\n}\n\nexport default DataTableViewOptions;\n","'use client';\n\nimport React from 'react';\nimport { Select as SelectPrimitive } from 'radix-ui';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { IconSelector, IconCheck, IconChevronUp, IconChevronDown } from '@tabler/icons-react';\n// CUSTOM: Added Direction and readDirection imports for RTL support in SelectTrigger and SelectContent\nimport { type Direction, readDirection } from '@/utils/dir-helper.util';\n// CUSTOM: Added Z_INDEX_ABOVE_DOCK import so SelectContent can render above modal dialogs (see\n// its usage below) — matches the fix already applied to PopoverContent for the same reason.\nimport { Z_INDEX_ABOVE_DOCK } from '@/components/z-index';\n\n/**\n * Select components display a list of options for the user to pick from—triggered by a button.\n * These components are built on Radix UI primitives and styled with Shadcn UI.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/select}\n * @see Radix UI Documentation: {@link https://www.radix-ui.com/primitives/docs/components/select}\n */\n// CUSTOM: Added TSDoc with links to shadcn/ui and Radix UI documentation\nfunction Select({ ...props }: React.ComponentProps) {\n return ;\n}\n\n/** @inheritdoc Select */\nfunction SelectGroup({ className, ...props }: React.ComponentProps) {\n return (\n \n );\n}\n\n/** @inheritdoc Select */\nfunction SelectValue({ ...props }: React.ComponentProps) {\n return ;\n}\n\n// CUSTOM: Defined SelectTriggerProps as a named type alias so extensions composing their\n// own select triggers have a public prop shape to import.\ntype SelectTriggerProps = React.ComponentProps & {\n size?: 'sm' | 'default';\n};\n\n/** @inheritdoc Select */\n// CUSTOM: Lifted the SelectTrigger prop shape out of the function signature into the named\n// SelectTriggerProps type above so it can be exported for downstream composition.\nfunction SelectTrigger({ className, size = 'default', children, ...props }: SelectTriggerProps) {\n // CUSTOM: Added readDirection() call and dir prop for RTL layout support\n const dir: Direction = readDirection();\n return (\n \n {children}\n \n \n \n \n );\n}\n\n/** @inheritdoc Select */\nfunction SelectContent({\n className,\n children,\n // CUSTOM: Restored 'popper' as the default position (was changed to 'item-aligned' by the shadcn\n // upgrade). In 'popper' mode Radix exposes --radix-select-trigger-width, which is required for\n // min-w-(--radix-select-trigger-width) to work. In 'item-aligned' mode that variable is not set,\n // making the popup width unconstrained. Existing callers all expected popper (dropdown) behavior.\n position = 'popper',\n align = 'center',\n // CUSTOM: Destructure style to merge with the shared z-index constant below\n style,\n ...props\n}: React.ComponentProps) {\n // CUSTOM: Added readDirection() call; children wrapped in
for RTL text direction\n const dir: Direction = readDirection();\n return (\n \n \n \n \n {/* CUSTOM: Wrapped children in
so item text renders in correct RTL/LTR direction */}\n
{children}
\n \n \n \n \n );\n}\n\n/** @inheritdoc Select */\n// CUSTOM: Added TSDoc via @inheritdoc\nfunction SelectLabel({ className, ...props }: React.ComponentProps) {\n return (\n \n );\n}\n\n/** @inheritdoc Select */\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n \n {children}\n \n );\n}\n\n/** @inheritdoc Select */\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\n/** @inheritdoc Select */\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n );\n}\n\n/** @inheritdoc Select */\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n );\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n// CUSTOM: Exported SelectTriggerProps as a named type so extensions composing their own\n// select triggers can share the prop shape.\nexport type { SelectTriggerProps };\n","import { ChevronLeftIcon, ChevronRightIcon, ArrowLeftIcon, ArrowRightIcon } from 'lucide-react';\nimport { Table } from '@tanstack/react-table';\n\nimport { Button } from '@/components/shadcn-ui/button';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/shadcn-ui/select';\n\ninterface DataTablePaginationProps {\n table: Table;\n}\n\nexport function DataTablePagination({ table }: DataTablePaginationProps) {\n return (\n
\n
\n
\n {table.getFilteredSelectedRowModel().rows.length} of{' '}\n {table.getFilteredRowModel().rows.length} row(s) selected\n
\n
\n

Rows per page

\n {\n table.setPageSize(Number(value));\n }}\n >\n \n \n \n \n {[10, 20, 30, 40, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n
\n Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}\n
\n
\n table.setPageIndex(0)}\n disabled={!table.getCanPreviousPage()}\n >\n Go to first page\n \n \n table.previousPage()}\n disabled={!table.getCanPreviousPage()}\n >\n Go to previous page\n \n \n table.nextPage()}\n disabled={!table.getCanNextPage()}\n >\n Go to next page\n \n \n table.setPageIndex(table.getPageCount() - 1)}\n disabled={!table.getCanNextPage()}\n >\n Go to last page\n \n \n
\n
\n
\n );\n}\n\nexport default DataTablePagination;\n","import React, { useMemo, useState } from 'react';\n\nimport {\n ColumnFiltersState,\n flexRender,\n getCoreRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n SortingState,\n ColumnDef as TSColumnDef,\n Row as TSRow,\n RowSelectionState as TSRowSelectionState,\n SortDirection as TSSortDirection,\n Table as TSTable,\n useReactTable,\n VisibilityState,\n} from '@tanstack/react-table';\n\nimport { DataTableViewOptions } from '@/components/advanced/data-table/data-table-column-toggle.component';\nimport { DataTablePagination } from '@/components/advanced/data-table/data-table-pagination.component';\nimport { Button } from '@/components/shadcn-ui/button';\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/shadcn-ui/table';\nimport { Skeleton } from '@/components/shadcn-ui/skeleton';\n\nexport type ColumnDef = TSColumnDef;\nexport type RowContents = TSRow;\nexport type TableContents = TSTable;\nexport type SortDirection = TSSortDirection;\nexport type RowSelectionState = TSRowSelectionState;\n\ninterface DataTableProps {\n columns: ColumnDef[];\n data: TData[] | undefined;\n enablePagination?: boolean;\n showPaginationControls?: boolean;\n showColumnVisibilityControls?: boolean;\n stickyHeader?: boolean;\n onRowClickHandler?: (row: RowContents, table: TableContents) => void;\n id?: string;\n isLoading?: boolean;\n noResultsMessage: string;\n}\n\n/**\n * Feature-rich table component that infuses our basic shadcn-based Table component with features\n * from TanStack's React Table library\n */\nexport function DataTable({\n columns,\n data,\n enablePagination = false,\n showPaginationControls = false,\n showColumnVisibilityControls = false,\n stickyHeader = false,\n onRowClickHandler = () => {},\n id,\n isLoading = false,\n noResultsMessage,\n}: DataTableProps) {\n const [sorting, setSorting] = useState([]);\n const [columnFilters, setColumnFilters] = useState([]);\n const [columnVisibility, setColumnVisibility] = useState({});\n const [rowSelection, setRowSelection] = useState({});\n\n const normalizedData = useMemo(() => data ?? [], [data]);\n\n const table = useReactTable({\n data: normalizedData,\n columns,\n getCoreRowModel: getCoreRowModel(),\n ...(enablePagination && { getPaginationRowModel: getPaginationRowModel() }),\n onSortingChange: setSorting,\n getSortedRowModel: getSortedRowModel(),\n onColumnFiltersChange: setColumnFilters,\n getFilteredRowModel: getFilteredRowModel(),\n onColumnVisibilityChange: setColumnVisibility,\n onRowSelectionChange: setRowSelection,\n state: {\n sorting,\n columnFilters,\n columnVisibility,\n rowSelection,\n },\n });\n\n const visibleColumns = table.getVisibleFlatColumns();\n let bodyContent: React.ReactNode;\n\n if (isLoading) {\n const rowCount = 10;\n const skeletonRowIds = Array.from({ length: rowCount }).map((_, idx) => `skeleton-row-${idx}`);\n bodyContent = skeletonRowIds.map((rowId) => (\n \n \n
\n \n
\n
\n
\n ));\n } else if (table.getRowModel().rows?.length > 0) {\n bodyContent = table.getRowModel().rows.map((row) => (\n onRowClickHandler(row, table)}\n key={row.id}\n data-state={row.getIsSelected() && 'selected'}\n >\n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ));\n } else {\n bodyContent = (\n \n \n {noResultsMessage}\n \n \n );\n }\n\n return (\n
\n {showColumnVisibilityControls && }\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? undefined\n : flexRender(header.column.columnDef.header, header.getContext())}\n \n );\n })}\n \n ))}\n \n {bodyContent}\n
\n {enablePagination && (\n
\n table.previousPage()}\n disabled={!table.getCanPreviousPage()}\n >\n Previous\n \n table.nextPage()}\n disabled={!table.getCanNextPage()}\n >\n Next\n \n
\n )}\n {enablePagination && showPaginationControls && }\n
\n );\n}\n\nexport default DataTable;\n","import { cn } from '@/utils/shadcn-ui/utils';\nimport Markdown, { MarkdownToJSX } from 'markdown-to-jsx';\nimport { useMemo } from 'react';\n\ninterface MarkdownRendererProps {\n /** Optional unique identifier */\n id?: string;\n /** The markdown string to render */\n markdown: string;\n className?: string;\n /**\n * The [`target` attribute for `a` html\n * tags](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target). Defaults to not\n * adding a `target` to `a` tags\n */\n anchorTarget?: string;\n /** Optional flag to truncate the content to 3 lines */\n truncate?: boolean;\n}\n\n/**\n * This component renders markdown content given a markdown string. It uses typography styles from\n * the platform.\n *\n * @param MarkdownRendererProps\n * @returns A div containing the rendered markdown content.\n */\nexport function MarkdownRenderer({\n id,\n markdown,\n className,\n anchorTarget,\n truncate,\n}: MarkdownRendererProps) {\n const options: MarkdownToJSX.Options = useMemo(\n () => ({\n overrides: {\n a: {\n props: {\n target: anchorTarget,\n },\n },\n },\n }),\n [anchorTarget],\n );\n return (\n \n {markdown}\n
\n );\n}\n\nexport default MarkdownRenderer;\n","import { Copy } from 'lucide-react';\nimport { Button } from '@/components/shadcn-ui/button';\nimport { LocalizedStringValue } from 'platform-bible-utils';\n\n/**\n * Object containing all keys used for localization in this component. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component\n */\nexport const ERROR_DUMP_STRING_KEYS = Object.freeze([\n '%webView_error_dump_header%',\n '%webView_error_dump_info_message%',\n] as const);\n\nexport type ErrorDumpLocalizedStrings = {\n [localizedInventoryKey in (typeof ERROR_DUMP_STRING_KEYS)[number]]?: LocalizedStringValue;\n};\n\n/**\n * Gets the localized value for the provided key\n *\n * @param strings Object containing localized string\n * @param key Key for a localized string\n * @returns The localized value for the provided key, if available. Returns the key if no localized\n * value is available\n */\nconst localizeString = (\n strings: ErrorDumpLocalizedStrings,\n key: keyof ErrorDumpLocalizedStrings,\n) => {\n return strings[key] ?? key;\n};\n\n/** Interface to store the parameters for the ErrorDump component */\nexport interface ErrorDumpProps {\n /** String containing the error details to show */\n errorDetails: string;\n /** Handler function to notify the frontend when the error is copied */\n handleCopyNotify?: () => void;\n /**\n * List of localized strings to localize the strings in this component. Relevant keys can be found\n * in `ERROR_DUMP_STRING_KEYS`\n */\n localizedStrings: ErrorDumpLocalizedStrings;\n /** Optional id for the root element */\n id?: string;\n}\n\n/** Component to render an error dump */\nexport function ErrorDump({\n errorDetails,\n handleCopyNotify,\n localizedStrings,\n id,\n}: ErrorDumpProps) {\n const headerText = localizeString(localizedStrings, '%webView_error_dump_header%');\n const infoMessage = localizeString(localizedStrings, '%webView_error_dump_info_message%');\n\n function handleCopy() {\n navigator.clipboard.writeText(errorDetails);\n if (handleCopyNotify) {\n handleCopyNotify();\n }\n }\n\n return (\n \n
\n
\n
\n {headerText}\n
\n
\n {infoMessage}\n
\n
\n \n
\n
\n
{errorDetails}
\n
\n
\n );\n}\n","import { PropsWithChildren, useState } from 'react';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { ErrorDump, ErrorDumpProps, ERROR_DUMP_STRING_KEYS } from '../basics/error-dump.component';\nimport { Popover, PopoverContent, PopoverTrigger } from '../shadcn-ui/popover';\nimport { Label } from '../shadcn-ui/label';\n\n/**\n * Object containing all keys used for localization in the ErrorPopover component. This extends\n * ERROR_DUMP_STRING_KEYS with additional keys specific to the ErrorPopover. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component\n */\nexport const ERROR_POPOVER_STRING_KEYS = Object.freeze([\n ...ERROR_DUMP_STRING_KEYS,\n '%webView_error_dump_copied_message%',\n] as const);\n\nexport type ErrorPopoverLocalizedStrings = {\n [localizedKey in (typeof ERROR_POPOVER_STRING_KEYS)[number]]?: string;\n};\n\n/** Interface to store the parameters for the ErrorPopover component */\nexport type ErrorPopoverProps = PropsWithChildren &\n Omit & {\n /**\n * List of localized strings to localize the strings in this component. Relevant keys can be\n * found in `ERROR_POPOVER_STRING_KEYS`\n */\n localizedStrings: ErrorPopoverLocalizedStrings;\n /** Optional CSS classes to insert into the `PopoverContent` */\n className?: string;\n /** Optional ID for the popover content for accessibility */\n id?: string;\n };\n\n/** A popover component that displays detailed error information using the ErrorDump component. */\nexport function ErrorPopover({\n errorDetails,\n handleCopyNotify,\n localizedStrings,\n children,\n className,\n id,\n}: ErrorPopoverProps) {\n const [isCopySuccess, setIsCopySuccess] = useState(false);\n\n const handleCopyWithNotification = () => {\n setIsCopySuccess(true);\n if (handleCopyNotify) {\n handleCopyNotify();\n }\n };\n\n const handleOpenChange = (open: boolean) => {\n if (!open) {\n setIsCopySuccess(false);\n }\n };\n\n return (\n \n {children}\n \n {isCopySuccess && localizedStrings['%webView_error_dump_copied_message%'] && (\n \n )}\n \n \n \n );\n}\n","import {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuGroup,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuRadioGroup,\n} from '@/components/shadcn-ui/dropdown-menu';\nimport { Button } from '@/components/shadcn-ui/button';\nimport { ChevronDown, Filter } from 'lucide-react';\nimport { useState } from 'react';\n\n/** The DropdownMenuItemType enum is used to determine the type of the dropdown item */\nexport enum DropdownMenuItemType {\n Check,\n Radio,\n}\n\nexport type DropdownItem = {\n /** Unique identifier for this dropdown */\n id: string;\n /** The label is the text that will be displayed on the dropdown item. */\n label: string;\n /** The onUpdate function is called when the state of a dropdown item is changed. */\n onUpdate: (id: string, checked?: boolean) => void;\n};\n\nexport type DropdownGroup = {\n /**\n * The label is the text that will be displayed on the dropdown group. It is used to categorize\n * the items in the group.\n */\n label: string;\n /** The itemType determines the DropdownMenuItemType type as either Check or Radio. */\n itemType: DropdownMenuItemType;\n /** The items array contains the items that will be displayed in the dropdown group */\n items: DropdownItem[];\n};\n\nexport type FilterDropdownProps = {\n /** Object unique identifier */\n id?: string;\n /** Label for the trigger button */\n label: string;\n /** The groups array contains the groups that will be displayed in the dropdown */\n groups: DropdownGroup[];\n}; // TODO: extend the props later\n\n/**\n * The FilterDropdown component is a dropdown designed for filtering content. It includes groups of\n * items that can be checkboxes or radio items.\n *\n * @param FilterDropdownProps\n * @returns A filter dropdown.\n */\nexport function FilterDropdown({ id, label, groups }: FilterDropdownProps) {\n // Populates the boolean Arrays for the group indexes that are checkbox groups\n const [checkedStates, setCheckedStates] = useState>(\n Object.fromEntries(\n groups\n .map((group, index) =>\n group.itemType === DropdownMenuItemType.Check ? [index, []] : undefined,\n )\n .filter((entry) => !!entry),\n ),\n );\n const [radioStates, setRadioStates] = useState>({});\n\n const handleCheckboxUpdate = (groupIndex: number, index: number) => {\n const newCheckedState = !checkedStates[groupIndex][index];\n // Update the checked state first\n setCheckedStates((oldCheckedStates) => {\n oldCheckedStates[groupIndex][index] = newCheckedState;\n return { ...oldCheckedStates };\n });\n\n // Calls the `onUpdate()` handler function for the dropdown item\n const item = groups[groupIndex].items[index];\n item.onUpdate(item.id, newCheckedState);\n };\n\n const handleRadioUpdate = (groupIndex: number, value: string) => {\n // Updates the radio state first\n setRadioStates((oldRadioStates) => {\n oldRadioStates[groupIndex] = value;\n return { ...oldRadioStates };\n });\n\n // Calls the `onUpdate()` handler function for the dropdown item\n const currentItem = groups[groupIndex].items.find((item) => item.id === value);\n if (currentItem) {\n currentItem.onUpdate(value);\n } else {\n console.error(`Could not find dropdown radio item with id '${value}'!`);\n }\n };\n\n return (\n
\n {/* TODO: remove this once the DropDown Menu shadcn has an id prop */}\n \n \n \n \n \n {groups.map((group, groupIndex) => (\n
\n {group.label}\n \n {group.itemType === DropdownMenuItemType.Check ? (\n <>\n {group.items.map((item, index) => (\n
\n handleCheckboxUpdate(groupIndex, index)}\n >\n {item.label}\n \n
\n ))}\n \n ) : (\n handleRadioUpdate(groupIndex, value)}\n >\n {group.items.map((item) => (\n
\n {item.label}\n
\n ))}\n \n )}\n
\n \n
\n ))}\n
\n
\n
\n );\n}\n\nexport default FilterDropdown;\n","import { Button } from '@/components/shadcn-ui/button';\nimport { CircleHelp, Link as LucideLink, User } from 'lucide-react';\nimport { NumberFormat } from 'platform-bible-utils';\n\n/** Interface that stores the parameters passed to the More Info component */\ninterface MoreInfoProps {\n /** Optional unique identifier */\n id?: string;\n /** The category of the extension */\n category: string;\n /** The number of downloads for the extension */\n downloads: Record;\n /** The languages supported by the extension */\n languages: string[];\n /** The URL to the more info page of the extension */\n moreInfoUrl: string;\n /** Handler function triggered when the more info (Website) link is clicked */\n handleMoreInfoLinkClick: () => void;\n /** Optional URL to a website link to get support for the extension */\n supportUrl: string;\n /** Handler function triggered when the support link is clicked */\n handleSupportLinkClick: () => void;\n}\n/**\n * This component displays the more info section of the extension which includes the category,\n * number of downloads, languages, and links to the website and support\n *\n * @param MoreInfoProps\n * @returns The more info component that displays the category, number of downloads, languages, and\n * links to the website and support\n */\nexport function MoreInfo({\n id,\n category,\n downloads,\n languages,\n moreInfoUrl,\n handleMoreInfoLinkClick,\n supportUrl,\n handleSupportLinkClick,\n}: MoreInfoProps) {\n /**\n * This constant formats the number of downloads into a more readable format.\n *\n * @example 1000 -> 1K\n *\n * @example 1000000 -> 1M\n *\n * @returns The formatted number of downloads\n */\n const numberFormatted = new NumberFormat('en', {\n notation: 'compact',\n compactDisplay: 'short',\n }).format(Object.values(downloads).reduce((a: number, b: number) => a + b, 0));\n\n /** This function scrolls the window to the bottom of the page. */\n const handleScrollToBottom = () => {\n window.scrollTo(0, document.body.scrollHeight);\n };\n\n // Tailwind v4's `divide-x` adds the divider border to the inline-end of each non-last child (v3\n // added it to the inline-start of each non-first child). Use symmetric horizontal padding\n // (`tw:px-4`) on the children instead of a parent `tw:gap-4` + per-child `tw:ps-4` so dividers\n // stay centered between columns rather than hugging the end of each column's content.\n return (\n \n {category && (\n
\n
\n {category}\n
\n CATEGORY\n
\n )}\n
\n
\n \n {numberFormatted}\n
\n USERS\n
\n
\n
\n {languages.slice(0, 3).map((locale) => (\n \n {locale.toUpperCase()}\n \n ))}\n
\n {languages.length > 3 && (\n handleScrollToBottom()}\n className=\"tw:text-xs tw:text-foreground tw:underline\"\n >\n +{languages.length - 3} more languages\n \n )}\n
\n {(moreInfoUrl || supportUrl) && (\n
\n {moreInfoUrl && (\n
\n handleMoreInfoLinkClick()}\n variant=\"link\"\n className=\"tw:flex tw:h-auto tw:gap-1 tw:py-0 tw:text-xs tw:font-semibold tw:text-foreground\"\n >\n Website\n \n \n
\n )}\n {supportUrl && (\n
\n handleSupportLinkClick()}\n variant=\"link\"\n className=\"tw:flex tw:h-auto tw:gap-1 tw:py-0 tw:text-xs tw:font-semibold tw:text-foreground\"\n >\n Support\n \n \n
\n )}\n
\n )}\n \n );\n}\n","import { useState } from 'react';\n\nexport type VersionInformation = {\n /** Date the version was published */\n date: string;\n /** Description of the changes in the version */\n description: string;\n};\n\n/** Type to store the version history information */\nexport type VersionHistoryType = Record;\n\n/** Interface that stores the parameters passed to the Version History component */\ninterface VersionHistoryProps {\n /** Optional unique identifier */\n id?: string;\n /** Object containing the versions mapped with their information */\n versionHistory: VersionHistoryType;\n}\n\n/**\n * Component to render the version history information shown in the footer component. Lists the 5\n * most recent versions, with the options to show all versions by pressing a button.\n *\n * @param VersionHistoryProps\n * @returns Rendered version history for the Footer component\n */\nexport function VersionHistory({ id, versionHistory }: VersionHistoryProps) {\n const [showAllVersions, setShowAllVersions] = useState(false);\n const currentDate = new Date();\n\n /**\n * Function to format the time string for the version history in the form of 'X year(s) ago'.\n *\n * @param dateString ISO Date string to determine the time string from\n * @returns Formatted time string\n */\n function formatTimeString(dateString: string) {\n const date = new Date(dateString);\n const dateDiff = new Date(currentDate.getTime() - date.getTime());\n const yearDiff = dateDiff.getUTCFullYear() - 1970;\n const monthDiff = dateDiff.getUTCMonth();\n const dayDiff = dateDiff.getUTCDate() - 1;\n\n // Determines how long ago the version was published\n let timeString = '';\n if (yearDiff > 0) {\n timeString = `${yearDiff.toString()} year${yearDiff === 1 ? '' : 's'} ago`;\n } else if (monthDiff > 0) {\n timeString = `${monthDiff.toString()} month${monthDiff === 1 ? '' : 's'} ago`;\n } else if (dayDiff === 0) {\n timeString = 'today';\n } else {\n timeString = `${dayDiff.toString()} day${dayDiff === 1 ? '' : 's'} ago`;\n }\n\n return timeString;\n }\n\n // Sorts the version history by version number\n const sortedEntries = Object.entries(versionHistory).sort((a, b) => b[0].localeCompare(a[0]));\n\n return (\n
\n

What`s New

\n
    \n {(showAllVersions ? sortedEntries : sortedEntries.slice(0, 5)).map((entry) => (\n
    \n
    \n
  • \n {entry[1].description}\n
  • \n
    \n
    \n
    Version {entry[0]}
    \n
    {formatTimeString(entry[1].date)}
    \n
    \n
    \n ))}\n
\n {sortedEntries.length > 5 && (\n setShowAllVersions(!showAllVersions)}\n className=\"tw:text-xs tw:text-foreground tw:underline\"\n >\n {showAllVersions ? 'Show Less Version History' : 'Show All Version History'}\n \n )}\n
\n );\n}\n\nexport default VersionHistory;\n","import { useMemo } from 'react';\nimport { formatBytes, getCurrentLocale } from 'platform-bible-utils';\nimport { VersionHistory, VersionHistoryType } from './version-history.component';\n\n/** Interface to store the parameters passed to the Footer component */\ninterface FooterProps {\n /** Optional unique identifier */\n id?: string;\n /** Name of the publisher */\n publisherDisplayName: string;\n /** Size of the extension file in bytes */\n fileSize: number;\n /** List of language codes supported by the extension */\n locales: string[];\n /** Object containing the version history mapped with their information */\n versionHistory: VersionHistoryType;\n /** Current version of the extension */\n currentVersion: string;\n}\n\n/**\n * Component to render the footer for the extension details which contains information on the\n * publisher, version history, languages, and file size.\n *\n * @param FooterProps\n * @returns The rendered Footer component\n */\nexport function Footer({\n id,\n publisherDisplayName,\n fileSize,\n locales,\n versionHistory,\n currentVersion,\n}: FooterProps) {\n /** Formats the file size into a human-readable format */\n const formattedFileSize = useMemo(() => formatBytes(fileSize), [fileSize]);\n\n /**\n * This function gets the display names of the languages based on the language codes.\n *\n * @param codes The list of language codes\n * @returns The list of language names\n */\n const getLanguageNames = (codes: string[]) => {\n const displayNames = new Intl.DisplayNames(getCurrentLocale(), { type: 'language' });\n return codes.map((code) => displayNames.of(code));\n };\n\n const languageNames = getLanguageNames(locales);\n\n return (\n
\n
\n {Object.entries(versionHistory).length > 0 && (\n \n )}\n
\n

Information

\n
\n

\n Publisher\n {publisherDisplayName}\n Size\n {formattedFileSize}\n

\n
\n

\n Version\n {currentVersion}\n Languages\n {languageNames.join(', ')}\n

\n
\n
\n
\n
\n
\n );\n}\n\nexport default Footer;\n","import { Badge } from '@/components/shadcn-ui/badge';\nimport { Button } from '@/components/shadcn-ui/button';\nimport { Label } from '@/components/shadcn-ui/label';\nimport { X } from 'lucide-react';\nimport { MultiSelectComboBox, MultiSelectComboBoxProps } from './multi-select-combo-box.component';\n\ninterface FilterProps extends MultiSelectComboBoxProps {\n /**\n * Placeholder text that will be displayed when no items are selected. It will appear at the\n * location where the badges would be if any items were selected.\n */\n badgesPlaceholder: string;\n /** Optional id for the component */\n id?: string;\n}\n\n/**\n * This is a variant of the {@link MultiSelectComboBox}, that shows a {@link Badge} component for each\n * selected item in the combo box. Clicking the 'X' icon on the badge will clear the item from the\n * selected options. A placeholder text must be provided through 'badgesPlaceholder'. This will be\n * displayed if no items are selected,\n */\nexport function Filter({\n entries,\n selected,\n onChange,\n placeholder,\n commandEmptyMessage,\n customSelectedText,\n isDisabled,\n sortSelected,\n icon,\n className,\n badgesPlaceholder,\n id,\n}: FilterProps) {\n return (\n
\n \n {selected.length > 0 ? (\n
\n {selected.map((type) => (\n \n onChange(selected.filter((selectedType) => selectedType !== type))}\n >\n \n \n {entries.find((entry) => entry.value === type)?.label}\n \n ))}\n
\n ) : (\n \n )}\n
\n );\n}\n\nexport default Filter;\n","import { Button, type ButtonProps } from '@/components/shadcn-ui/button';\nimport { ButtonGroup, ButtonGroupSeparator } from '@/components/shadcn-ui/button-group';\nimport { Kbd } from '@/components/shadcn-ui/kbd';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport { isMacOs } from '@/utils/platform.util';\nimport { Redo, Undo } from 'lucide-react';\n\n/**\n * Object containing all keys used for localization in this component. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component.\n */\nexport const UNDO_REDO_BUTTONS_STRING_KEYS = Object.freeze([\n '%undoButton_tooltip%',\n '%redoButton_tooltip%',\n] as const);\n\nexport type UndoRedoButtonsLocalizedStrings = {\n [key in (typeof UNDO_REDO_BUTTONS_STRING_KEYS)[number]]?: string;\n};\n\nconst localizeString = (\n strings: UndoRedoButtonsLocalizedStrings,\n key: keyof UndoRedoButtonsLocalizedStrings,\n) => strings[key] ?? key;\n\nexport type UndoRedoButtonsProps = {\n /** Function to call when Undo is clicked. */\n onUndoClick: () => void;\n /** Function to call when Redo is clicked. If undefined, the Redo button is not rendered. */\n onRedoClick?: () => void;\n /** Whether the Undo button is enabled. */\n canUndo?: boolean;\n /** Whether the Redo button is enabled. */\n canRedo?: boolean;\n /** Localized strings for button tooltips. Falls back to the key itself if not provided. */\n localizedStrings?: UndoRedoButtonsLocalizedStrings;\n /**\n * Whether to show OS-specific keyboard shortcut hints in the tooltips. Defaults to `true`. If\n * being used with an `Editorial` component, wrap it in `EditorKeyboardShortcuts` to make the\n * shortcuts functional.\n */\n showKeyboardShortcuts?: boolean;\n /** CSS class name for the buttons. Defaults to \"tw:h-6 tw:w-6\". */\n className?: string;\n /** Variant for the buttons. Defaults to \"ghost\". */\n variant?: ButtonProps['variant'];\n};\n\n/**\n * Undo and (optionally) Redo buttons with tooltips. Suitable for use in any editor toolbar. The\n * Redo button is only rendered when `onRedoClick` is provided. Tooltip text defaults to the\n * localization key if no localized strings are provided. OS-specific keyboard shortcut hints are\n * shown in the tooltips by default; wrap the `Editorial` component in `EditorKeyboardShortcuts` to\n * make those shortcuts functional.\n */\nexport function UndoRedoButtons({\n onUndoClick,\n onRedoClick,\n canUndo = true,\n canRedo = true,\n localizedStrings = {},\n showKeyboardShortcuts = true,\n className = 'tw:h-6 tw:w-6',\n variant = 'ghost',\n}: UndoRedoButtonsProps) {\n const isMac = isMacOs();\n const undoLocalized = localizeString(localizedStrings, '%undoButton_tooltip%');\n const redoLocalized = localizeString(localizedStrings, '%redoButton_tooltip%');\n const getsSeparator = variant === 'secondary' || variant === 'default';\n\n return (\n \n \n \n \n \n \n \n \n \n

\n {undoLocalized}\n {showKeyboardShortcuts && (\n <>\n {' '}\n {isMac ? '⌘Z' : 'Ctrl+Z'}\n \n )}\n

\n
\n
\n
\n {onRedoClick && getsSeparator && }\n {onRedoClick && (\n \n \n \n \n \n \n \n \n

\n {redoLocalized}\n {showKeyboardShortcuts && (\n <>\n {' '}\n {isMac ? '⌘⇧Z' : 'Ctrl+Y'}\n \n )}\n

\n
\n
\n
\n )}\n
\n );\n}\n\nexport default UndoRedoButtons;\n","import { EditorRef } from '@eten-tech-foundation/platform-editor';\nimport { isMacOs } from '@/utils/platform.util';\nimport { MutableRefObject, PropsWithChildren, useEffect, useRef } from 'react';\n\n/** Properties for the `KeyboardShortcutsPlugin` component */\ntype EditorKeyboardShortcutsProps = PropsWithChildren & {\n /** The `editorRef` of the editor that this undo/redo plugin is applied to */\n editorRef: MutableRefObject;\n /** Whether the Undo button is enabled. */\n canUndo?: boolean;\n /** Whether the Redo button is enabled. */\n canRedo?: boolean;\n};\n\n/**\n * Component that provides common undo/redo capability for a scripture `Editorial` component. Must\n * have the `Editorial` component instance as a child of this component.\n */\nexport function EditorKeyboardShortcuts({\n children,\n editorRef,\n canUndo = true,\n canRedo = true,\n}: EditorKeyboardShortcutsProps) {\n // These refs must have default values of `null` to be accepted by the React elements as refs\n // eslint-disable-next-line no-null/no-null\n const divRef = useRef(null);\n\n // Listen for the standard undo/redo shortcuts for the current OS.\n useEffect(() => {\n const isMac = isMacOs();\n const editorInput = divRef.current?.querySelector('.editor-input') ?? undefined;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!editorInput || document.activeElement !== editorInput) return;\n\n const key = event.key.toLowerCase();\n\n if (isMac) {\n if (!event.metaKey) return;\n\n // Undo: ⌘Z\n if (!event.shiftKey && key === 'z') {\n event.preventDefault();\n if (canUndo) {\n editorRef.current?.undo();\n }\n }\n\n // Redo: ⌘⇧Z\n else if (event.shiftKey && key === 'z') {\n event.preventDefault();\n if (canRedo) {\n editorRef.current?.redo();\n }\n }\n } else {\n if (!event.ctrlKey) return;\n\n // Undo: Ctrl+Z\n if (!event.shiftKey && key === 'z') {\n event.preventDefault();\n if (canUndo) {\n editorRef.current?.undo();\n }\n }\n\n // Redo: Ctrl+Y or Ctrl+Shift+Z\n else if (key === 'y' || (event.shiftKey && key === 'z')) {\n event.preventDefault();\n if (canRedo) {\n editorRef.current?.redo();\n }\n }\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [canRedo, canUndo, editorRef]);\n\n return
{children}
;\n}\n","import {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/shadcn-ui/dropdown-menu';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport { Button } from '@/components/shadcn-ui/button';\nimport { GENERATOR_NOTE_CALLER, HIDDEN_NOTE_CALLER } from '@eten-tech-foundation/platform-editor';\nimport { Input } from '@/components/shadcn-ui/input';\nimport { KeyboardEvent, useEffect, useRef, useState } from 'react';\nimport { Z_INDEX_FOOTNOTE_EDITOR } from '@/components/z-index';\nimport { FootnoteCallerType, FootnoteEditorLocalizedStrings } from './footnote-editor.types';\n\ninterface FootnoteCallerDropdownProps {\n /** The caller type value to pass to the dropdown */\n callerType: FootnoteCallerType;\n /** Function to update the caller type */\n updateCallerType: (newCallerType: FootnoteCallerType) => void;\n /** The custom caller to pass to the custom caller input field */\n customCaller: string;\n /** FUnction to update the custom caller */\n updateCustomCaller: (newCustomCaller: string) => void;\n /** Localized strings from the parent component */\n localizedStrings: FootnoteEditorLocalizedStrings;\n}\n\nconst renderCallerButtonContent = (\n callerType: FootnoteCallerType,\n localizedStrings: FootnoteEditorLocalizedStrings,\n customCaller: string,\n) => {\n if (callerType === 'generated') {\n return (\n <>\n

+

{localizedStrings['%footnoteEditor_callerDropdown_item_generated%']}\n \n );\n }\n\n if (callerType === 'hidden') {\n return (\n <>\n

-

{localizedStrings['%footnoteEditor_callerDropdown_item_hidden%']}\n \n );\n }\n\n return (\n <>\n

{customCaller}

{localizedStrings['%footnoteEditor_callerDropdown_item_custom%']}\n \n );\n};\n\nexport function FootnoteCallerDropdown({\n callerType,\n updateCallerType,\n customCaller,\n updateCustomCaller,\n localizedStrings,\n}: FootnoteCallerDropdownProps) {\n // The ref must start with being null to be passed as an element ref\n // eslint-disable-next-line no-null/no-null\n const customCallerInputRef = useRef(null);\n // The ref must start with being null to be passed as an element ref\n // eslint-disable-next-line no-null/no-null\n const customCallerSelectRef = useRef(null);\n // The ref must start with being null to be passed as an element ref\n // eslint-disable-next-line no-null/no-null\n const isCustomCallerInputFocused = useRef(false);\n const [selectedCallerType, setSelectedCallerType] = useState(callerType);\n const [newCustomCaller, setNewCustomCaller] = useState(customCaller);\n const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n\n // If the caller type changes, the selected caller type needs to change also\n useEffect(() => {\n setSelectedCallerType(callerType);\n }, [callerType]);\n\n // If the parent custom caller changes, then the new custom caller should reflect the changes\n useEffect(() => {\n if (newCustomCaller !== customCaller) {\n setNewCustomCaller(customCaller);\n }\n // This can't be triggered when the new custom caller updates because otherwise this will\n // completely prevent the input field from being edited\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [customCaller]);\n\n const handleDropdownOpenChange = (open: boolean) => {\n isCustomCallerInputFocused.current = false;\n setIsDropdownOpen(open);\n if (!open) {\n // This makes it so that if the custom caller is invalid, then reverts back to the previous\n // selected caller\n if (selectedCallerType !== 'custom' || newCustomCaller) {\n updateCallerType(selectedCallerType);\n updateCustomCaller(newCustomCaller);\n } else {\n setSelectedCallerType(callerType);\n setNewCustomCaller(customCaller);\n }\n }\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n event.stopPropagation();\n // Allow to navigate to the input field\n if (\n (document.activeElement === customCallerSelectRef.current && event.key === 'ArrowDown') ||\n event.key === 'ArrowRight'\n ) {\n customCallerInputRef.current?.focus();\n isCustomCallerInputFocused.current = true;\n } else if (document.activeElement === customCallerInputRef.current && event.key === 'ArrowUp') {\n customCallerSelectRef.current?.focus();\n isCustomCallerInputFocused.current = false;\n } else if (\n document.activeElement === customCallerInputRef.current &&\n event.key === 'ArrowLeft' &&\n customCallerInputRef.current?.selectionStart === 0\n ) {\n customCallerSelectRef.current?.focus();\n isCustomCallerInputFocused.current = false;\n }\n\n // Allow the dropdown menu to be submitted if the custom caller is selected when you press enter\n if (\n selectedCallerType === 'custom' &&\n event.key === 'Enter' &&\n (document.activeElement === customCallerSelectRef.current ||\n document.activeElement === customCallerInputRef.current)\n ) {\n handleDropdownOpenChange(false);\n }\n };\n\n return (\n \n \n \n \n \n \n \n \n \n {localizedStrings['%footnoteEditor_callerDropdown_tooltip%']}\n \n \n \n {\n if (isCustomCallerInputFocused.current) isCustomCallerInputFocused.current = false;\n }}\n onKeyDown={handleKeyDown}\n onMouseMove={() => {\n if (isCustomCallerInputFocused.current) customCallerInputRef.current?.focus();\n }}\n >\n \n {localizedStrings['%footnoteEditor_callerDropdown_label%']}\n \n \n setSelectedCallerType('generated')}\n >\n
\n {localizedStrings['%footnoteEditor_callerDropdown_item_generated%']}\n {GENERATOR_NOTE_CALLER}\n
\n \n setSelectedCallerType('hidden')}\n >\n
\n {localizedStrings['%footnoteEditor_callerDropdown_item_hidden%']}\n {HIDDEN_NOTE_CALLER}\n
\n \n setSelectedCallerType('custom')}\n onClick={(event) => {\n event.stopPropagation();\n isCustomCallerInputFocused.current = true;\n customCallerInputRef.current?.focus();\n }}\n onSelect={(event) => event.preventDefault()}\n >\n
\n {localizedStrings['%footnoteEditor_callerDropdown_item_custom%']}\n {\n event.stopPropagation();\n setSelectedCallerType('custom');\n isCustomCallerInputFocused.current = true;\n }}\n ref={customCallerInputRef}\n className=\"tw:h-auto tw:w-10 tw:p-0 tw:text-center\"\n value={newCustomCaller}\n onKeyDown={(event) => {\n if (\n !(\n event.key === 'Enter' ||\n event.key === 'ArrowUp' ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowRight'\n )\n )\n event.stopPropagation();\n }}\n maxLength={1}\n onChange={(event) => setNewCustomCaller(event.target.value)}\n />\n
\n \n \n
\n );\n}\n","import { Button } from '@/components/shadcn-ui/button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/shadcn-ui/dropdown-menu';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport { FunctionSquare, SquareSigma, SquareX } from 'lucide-react';\nimport { formatReplacementString } from 'platform-bible-utils';\nimport { Z_INDEX_FOOTNOTE_EDITOR } from '@/components/z-index';\nimport { FootnoteEditorLocalizedStrings } from './footnote-editor.types';\n\ninterface FootnoteTypeDropdownProps {\n noteType: string;\n handleNoteTypeChange: (newNoteType: string) => void;\n localizedStrings: FootnoteEditorLocalizedStrings;\n isTypeSwitchable: boolean;\n}\n\nconst renderNoteTypeButtonContent = (\n noteType: string,\n localizedStrings: FootnoteEditorLocalizedStrings,\n) => {\n if (noteType === 'f') {\n return (\n <>\n {localizedStrings['%footnoteEditor_noteType_footnote_label%']}\n \n );\n }\n\n if (noteType === 'fe') {\n return (\n <>\n {localizedStrings['%footnoteEditor_noteType_endNote_label%']}\n \n );\n }\n\n return (\n <>\n {localizedStrings['%footnoteEditor_noteType_crossReference_label%']}\n \n );\n};\n\nconst formatNoteTypeTooltip = (\n noteType: string,\n localizedStrings: FootnoteEditorLocalizedStrings,\n) => {\n if (noteType === 'x') {\n return localizedStrings['%footnoteEditor_noteType_crossReference_label%'];\n }\n\n let noteTypeString = localizedStrings['%footnoteEditor_noteType_endNote_label%'];\n if (noteType === 'f') {\n noteTypeString = localizedStrings['%footnoteEditor_noteType_footnote_label%'];\n }\n\n return formatReplacementString(localizedStrings['%footnoteEditor_noteType_tooltip%'] ?? '', {\n noteType: noteTypeString,\n });\n};\n\nexport function FootnoteTypeDropdown({\n noteType,\n handleNoteTypeChange,\n localizedStrings,\n isTypeSwitchable,\n}: FootnoteTypeDropdownProps) {\n return (\n \n \n \n \n \n \n \n \n \n

{formatNoteTypeTooltip(noteType, localizedStrings)}

\n
\n
\n
\n \n \n {localizedStrings['%footnoteEditor_noteTypeDropdown_label%']}\n \n \n handleNoteTypeChange('x')}\n className=\"tw:gap-2\"\n >\n \n {localizedStrings['%footnoteEditor_noteType_crossReference_label%']}\n \n handleNoteTypeChange('f')}\n className=\"tw:gap-2\"\n >\n \n {localizedStrings['%footnoteEditor_noteType_footnote_label%']}\n \n handleNoteTypeChange('fe')}\n className=\"tw:gap-2\"\n >\n \n {localizedStrings['%footnoteEditor_noteType_endNote_label%']}\n \n \n
\n );\n}\n","import { FC, LegacyRef, useMemo, useState } from 'react';\nimport { Ban } from 'lucide-react';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n} from '../shadcn-ui/command';\n\n/**\n * Object containing all keys used for localization in the MarkerMenu component. If you're using\n * this component in an extension, you can pass it into the useLocalizedStrings hook to easily\n * obtain the localized strings and pass them into the localizedStrings prop of this component\n */\nexport const MARKER_MENU_STRING_KEYS = Object.freeze([\n '%markerMenu_deprecated_label%',\n '%markerMenu_disallowed_label%',\n '%markerMenu_noResults%',\n '%markerMenu_searchPlaceholder%',\n // These two keys are not read by this component directly; they are provided here so callers can\n // localize them and pass the result into the optional `searchPlaceholder` prop to override the\n // default search-field placeholder.\n '%markerMenu_searchPlaceholder_insert%',\n '%markerMenu_searchPlaceholder_paragraph%',\n] as const);\n\nexport type MarkerMenuLocalizedStrings = {\n [localizedKey in (typeof MARKER_MENU_STRING_KEYS)[number]]?: string;\n};\n\n/** Interface that includes the properties that the provided icon element should have */\nexport interface MarkerIconProps {\n /** CSS class name to apply to the icon */\n className?: string;\n /** Size in px that the icon should be */\n size?: string | number;\n}\n\n/** Type for the markers that contain all necessary information to be displayed in the list */\nexport interface MarkerMenuItem {\n /** If the item is a marker, then this is the marker code */\n marker?: string;\n /** The main title for the marker or command */\n title: string;\n /** An optional subtitle for the marker */\n subtitle?: string;\n /** Optional name of icon to use instead of the marker */\n icon?: FC;\n /**\n * Whether the command/marker is deprecated. Deprecated items stay visible in the menu (even when\n * the search query is empty) but are rendered disabled so they cannot be selected.\n */\n isDeprecated?: boolean;\n /**\n * Whether the command/marker is disallowed for this project (e.g. blocked while structure is\n * protected). Unlike {@link MarkerMenuItem.isDeprecated}, this flag affects visibility as well as\n * selectability: while the search query is empty, disallowed items are hidden if any allowed\n * items exist (to reduce clutter) but are shown when every item is disallowed (so the menu isn't\n * empty). A non-empty query reveals a disallowed item only on an exact marker-code match or a\n * title match. Whenever a disallowed item is shown it is rendered disabled so it cannot be\n * selected.\n */\n isDisallowed?: boolean;\n /** Function to be triggered when the marker or command is selected */\n action: () => void;\n}\n\n/** Props for the marker menu component */\nexport interface MarkerMenuProps {\n /** Localized strings to pass through for the marker menu */\n localizedStrings: MarkerMenuLocalizedStrings;\n /**\n * A list of the marker menu items which can either be a marker to insert or some basic command\n * actions\n */\n markerMenuItems: MarkerMenuItem[];\n /** Optional ref for the command search input to be able to focus it manually */\n searchRef?: LegacyRef;\n /**\n * Optional placeholder text for the search input. When provided, overrides the default\n * `%markerMenu_searchPlaceholder%` localized string.\n */\n searchPlaceholder?: string;\n}\n\n/** Function to format the marker menu icon and size it accordingly */\nfunction MenuMarkerIcon({ icon, className }: { icon?: FC; className?: string }) {\n const IconComponent = icon ?? Ban;\n return ;\n}\n\n/**\n * Function that renders the marker menu command item for both the marker matches and the title\n * matches\n */\nfunction MarkerMenuCommandItem({\n item,\n localizedStrings,\n}: {\n item: MarkerMenuItem;\n localizedStrings: MarkerMenuLocalizedStrings;\n}) {\n return (\n \n
\n {item.marker ? (\n {item.marker}\n ) : (\n
\n \n
\n )}\n
\n
\n

{item.title}

\n {item.subtitle &&

{item.subtitle}

}\n
\n {(item.isDisallowed || item.isDeprecated) && (\n \n {item.isDisallowed\n ? localizedStrings['%markerMenu_disallowed_label%']\n : localizedStrings['%markerMenu_deprecated_label%']}\n \n )}\n \n );\n}\n\n/** Marker menu component to render the list of markers and a few commands in the scripture editor */\nexport function MarkerMenu({\n localizedStrings,\n markerMenuItems,\n searchRef,\n searchPlaceholder,\n}: MarkerMenuProps) {\n const [commandSearch, setCommandSearch] = useState('');\n\n const [codeMatchItems, titleMatchItems] = useMemo(() => {\n const query = commandSearch.trim().toLowerCase();\n if (!query) {\n // Hide disallowed markers until specifically searched, so the menu isn't cluttered with\n // entries the user cannot insert.\n const allowedItems = markerMenuItems.filter((markerItem) => !markerItem.isDisallowed);\n // ...but when every item is disallowed (e.g. all of a parent's markers are blocked while\n // structure is protected), fall back to showing the disallowed items (disabled) so the menu\n // surfaces the locked options instead of reading as an empty \"No results\" state.\n return [allowedItems.length > 0 ? allowedItems : markerMenuItems, []];\n }\n\n // Marker-code matches first. Disallowed markers require an exact code match (never a substring),\n // so a broad query doesn't surface sibling markers the user cannot use.\n const filteredCodeMatchItems = markerMenuItems.filter((markerItem) => {\n const code = markerItem.marker?.toLowerCase();\n return markerItem.isDisallowed ? code === query : code?.includes(query);\n });\n // Then title matches. A disallowed marker's title match is itself its reveal condition, so it\n // needs no extra gate here.\n const filteredTitleMatchItems = markerMenuItems.filter(\n (markerItem) =>\n markerItem.title.toLowerCase().includes(query) &&\n !filteredCodeMatchItems.includes(markerItem),\n );\n\n return [filteredCodeMatchItems, filteredTitleMatchItems];\n }, [commandSearch, markerMenuItems]);\n\n return (\n \n setCommandSearch(value)}\n placeholder={searchPlaceholder ?? localizedStrings['%markerMenu_searchPlaceholder%']}\n />\n \n {localizedStrings['%markerMenu_noResults%']}\n \n {codeMatchItems.map((item) => (\n \n ))}\n \n {titleMatchItems.length > 0 && (\n <>\n {codeMatchItems.length > 0 && }\n \n {titleMatchItems.map((item) => (\n \n ))}\n \n \n )}\n \n \n );\n}\n","import { EditorRef } from '@eten-tech-foundation/platform-editor';\nimport { LanguageStrings, usfmMarkers } from 'platform-bible-utils';\nimport { MutableRefObject } from 'react';\nimport { MarkerMenuItem } from '../marker-menu.component';\n\n/**\n * Function that generates the inline marker menu items that will update as the cursor location\n * changes. In the future this function will take data from an `.sty` file so that users can define\n * their own markers.\n *\n * @param editorRef The ref for the editor component to be able to insert markers\n * @param parentMarker The current parent marker which is used to determine which markers to include\n * @returns The list of inline marker menu items\n */\nexport function generateInlineMarkerMenuListItems(\n editorRef: MutableRefObject,\n closeMarkersMenu: () => void,\n localizedStrings: LanguageStrings,\n parentMarker?: string,\n): MarkerMenuItem[] {\n // Makes it so that if the parent marker is a paragraph, won't show the marker menu\n if (!parentMarker || parentMarker === 'p') return [];\n\n const markerDetails = usfmMarkers[parentMarker];\n if (!markerDetails?.children) return [];\n\n const markerMenuItems: MarkerMenuItem[] = [];\n Object.entries(markerDetails.children).forEach(([, markers]) => {\n markerMenuItems.push(\n ...markers.map((marker) => {\n return {\n marker,\n title:\n localizedStrings[usfmMarkers[marker].description] ?? usfmMarkers[marker].description,\n action: () => {\n editorRef.current?.insertMarker(marker);\n closeMarkersMenu();\n },\n };\n }),\n );\n });\n return markerMenuItems.sort((a, b) => (a.marker ?? a.title).localeCompare(b.marker ?? b.title));\n}\n","import { Button } from '@/components/shadcn-ui/button';\nimport { ButtonGroup } from '@/components/shadcn-ui/button-group';\nimport { CancelAcceptButtons } from '@/components/basics/cancel-accept-buttons.component';\nimport {\n DeltaOp,\n DeltaOpInsertNoteEmbed,\n Editorial,\n EditorOptions,\n EditorRef,\n GENERATOR_NOTE_CALLER,\n getDefaultViewOptions,\n HIDDEN_NOTE_CALLER,\n isInsertEmbedOpOfType,\n StateChangeSnapshot,\n} from '@eten-tech-foundation/platform-editor';\nimport { Copy } from 'lucide-react';\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n RefObject,\n} from 'react';\nimport '@/components/advanced/footnote-editor/editor-overrides.css';\nimport { SerializedVerseRef } from '@sillsdev/scripture';\nimport {\n Tooltip,\n TooltipProvider,\n TooltipTrigger,\n TooltipContent,\n} from '@/components/shadcn-ui/tooltip';\nimport { UndoRedoButtons } from '@/components/basics/undo-redo-buttons.component';\nimport { Usj } from '@eten-tech-foundation/scripture-utilities';\nimport { Popover, PopoverAnchor, PopoverContent } from '@/components/shadcn-ui/popover';\nimport { EditorKeyboardShortcuts } from '@/components/basics/editor-keyboard-shortcuts.component';\nimport { FootnoteCallerDropdown } from './footnote-caller-dropdown.component';\nimport { FootnoteTypeDropdown } from './footnote-type-dropdown.component';\nimport { FootnoteCallerType, FootnoteEditorLocalizedStrings } from './footnote-editor.types';\nimport { MarkerMenu } from '../marker-menu.component';\nimport { generateInlineMarkerMenuListItems } from './footnote-editor.utils';\n\n/** Interface containing the types of the properties that are passed to the `FootnoteEditor` */\nexport interface FootnoteEditorProps {\n /** Class name for styling the embedded `Editor` component in this editor popover */\n classNameForEditor?: string;\n /** Delta ops for the current note being edited that are applied to the note editorial */\n noteOps: DeltaOpInsertNoteEmbed[] | undefined;\n /** External function to handle closing the footnote editor */\n onClose: () => void;\n /** The scripture reference for the parent editor */\n scrRef: SerializedVerseRef;\n /** The unique note key to identify the note being edited used to apply changes to the note */\n noteKey: string | undefined;\n /** View options of the parent editor */\n editorOptions: EditorOptions;\n /** Trigger key to open the footnote editor marker menu */\n defaultMarkerMenuTrigger: string;\n /** Localized strings to be passed to the footnote editor component */\n localizedStrings: FootnoteEditorLocalizedStrings;\n /**\n * Called on every change to the footnote with the updated note ops. An implementation of this\n * function is required only if the parent does not supply `parentEditorRef` or if some additional\n * logic is needed to handle the changes. The note ops passed in this function are the full ops\n * for the note, not just the changes since the last call.\n */\n onChange?: (noteOps: DeltaOpInsertNoteEmbed[]) => void;\n /**\n * Ref to the parent editor. When provided, the footnote editor will apply changes directly to the\n * parent editor, so the client does not need to handle this in the `onChange` callback.\n */\n parentEditorRef?: RefObject;\n}\n\n/**\n * Function to convert a footnote/endnote type node to a cross-reference type node\n *\n * @param op The node to be converted\n */\nfunction footnoteToCrossReferenceOp(op: DeltaOp) {\n // The built-in type for the delta note ops does not contain the types for the attributes\n // so have to cast it here\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const opCharAttribute = op.attributes?.char as Record;\n if (opCharAttribute.style) {\n if (opCharAttribute.style === 'ft') {\n opCharAttribute.style = 'xt';\n }\n\n if (opCharAttribute.style === 'fr') {\n opCharAttribute.style = 'xo';\n }\n\n if (opCharAttribute.style === 'fq') {\n opCharAttribute.style = 'xq';\n }\n }\n}\n\n/**\n * Function to convert a cross-reference type node to a footnote/endnote type node\n *\n * @param op THe node to be converted\n */\nfunction crossReferenceToFootnoteOp(op: DeltaOp) {\n // The built-in type for the delta note ops does not contain the types for the attributes\n // so have to cast it here\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const opCharAttribute = op.attributes?.char as Record;\n if (opCharAttribute.style) {\n if (opCharAttribute.style === 'xt') {\n opCharAttribute.style = 'ft';\n }\n\n if (opCharAttribute.style === 'xo') {\n opCharAttribute.style = 'fr';\n }\n\n if (opCharAttribute.style === 'xq') {\n opCharAttribute.style = 'fq';\n }\n }\n}\n\n// TODO: Remove this once the new marker menu is implemented with correct logic\n/**\n * This is for a temporary fix to get the markers menu to work by having the default usj include a\n * parent paragraph node\n */\nconst PARAGRAPH_USJ: Usj = {\n type: 'USJ',\n version: '3.1',\n content: [\n {\n type: 'para',\n },\n ],\n};\n\n/**\n * Component to edit footnotes from within the editor component\n *\n * @param FootnoteEditorProps - The properties for the footnote editor component\n */\nexport default function FootnoteEditor({\n classNameForEditor,\n noteOps,\n onChange,\n onClose,\n scrRef,\n noteKey,\n editorOptions,\n defaultMarkerMenuTrigger,\n localizedStrings,\n parentEditorRef,\n}: FootnoteEditorProps) {\n // These refs must have default values of `null` to be accepted by the React elements as refs\n /* eslint-disable no-null/no-null */\n const editorRef = useRef(null);\n const editorParentRef = useRef(null);\n const outerBorderRef = useRef(null);\n const containerRef = useRef(null);\n /* eslint-enable no-null/no-null */\n\n // Lock the container width to its natural rendered width so content changes (e.g. switching\n // language, undo/redo enabling) don't cause the popover to resize while editing.\n // useLayoutEffect fires after DOM layout but before paint, so getBoundingClientRect() returns\n // the natural width. The parent PopoverContent unmounts this component on close, so the effect\n // re-runs fresh on each open.\n useLayoutEffect(() => {\n if (!containerRef.current) return;\n const { width } = containerRef.current.getBoundingClientRect();\n if (width > 0) containerRef.current.style.width = `${width}px`;\n }, []);\n\n const [callerType, setCallerType] = useState('generated');\n const [originalCallerType, setOriginalCallerType] = useState('generated');\n const [customCaller, setCustomCaller] = useState('*');\n const [originalCustomCaller, setOriginalCustomCaller] = useState('*');\n\n const [noteType, setNoteType] = useState('f');\n\n const [isTypeSwitchable, setIsTypeSwitchable] = useState(false);\n // Tracks whether the editor content matches the state when the note was first loaded, so we\n // can disable Undo when there are no user edits left to undo\n const [isAtInitialState, setIsAtInitialState] = useState(true);\n const [canRedo, setCanRedo] = useState(false);\n const hasInitializedEditor = useRef(false);\n const initialNoteOpsJson = useRef('');\n\n // These control the placement of the inline markers menu by setting the location of the anchor\n const [showMarkersMenu, setShowMarkersMenu] = useState(false);\n const [markersMenuAnchorX, setMarkersMenuAnchorX] = useState();\n const [markersMenuAnchorY, setMarkersMenuAnchorY] = useState();\n const [markersMenuAnchorHeight, setMarkersMenuAnchorHeight] = useState();\n\n const [contextMarker, setContextMarker] = useState();\n\n // The refs needs to start out with null for it to work as a element ref\n // eslint-disable-next-line no-null/no-null\n const markerMenuSearchRef = useRef(null);\n\n // Options for the editorial component\n const options = useMemo(\n () => ({\n ...editorOptions,\n markerMenuTrigger: defaultMarkerMenuTrigger,\n hasExternalUI: true,\n view: { ...(editorOptions.view ?? getDefaultViewOptions()), noteMode: 'expanded' },\n }),\n [editorOptions, defaultMarkerMenuTrigger],\n );\n\n const inlineMarkerMenuItems = useMemo(\n () =>\n generateInlineMarkerMenuListItems(\n editorRef,\n () => setShowMarkersMenu(false),\n localizedStrings,\n contextMarker,\n ),\n [localizedStrings, contextMarker],\n );\n\n // Makes it so that the footnote type change tooltip doesn't automatically focus when the\n // component opens by focusing the editor\n useEffect(() => {\n // This needs to be run when the marker menu closes to move the focus back to the editor.\n // The editor shouldn't be focused, however, when the markers menu is first being shown.\n if (!showMarkersMenu) editorRef.current?.focus();\n }, [noteType, showMarkersMenu]);\n\n // When the component loads, applies the note ops to the current editor, gets the note ref and caller\n useEffect(() => {\n let timeout: ReturnType;\n hasInitializedEditor.current = false;\n setIsAtInitialState(true);\n const noteOp = noteOps?.at(0);\n if (noteOp && isInsertEmbedOpOfType('note', noteOp)) {\n const rawCaller = noteOp.insert.note?.caller;\n // Parses the current caller\n let parsedCallerType: FootnoteCallerType = 'custom';\n if (rawCaller === GENERATOR_NOTE_CALLER) {\n parsedCallerType = 'generated';\n } else if (rawCaller === HIDDEN_NOTE_CALLER) {\n parsedCallerType = 'hidden';\n } else if (rawCaller) {\n setCustomCaller(rawCaller);\n setOriginalCustomCaller(rawCaller);\n }\n setCallerType(parsedCallerType);\n setOriginalCallerType(parsedCallerType);\n // Assigns note type\n setNoteType(noteOp.insert.note?.style ?? 'f');\n timeout = setTimeout(() => {\n // Inserts the note node to be edited as an delta operation\n editorRef.current?.applyUpdate([noteOp]);\n }, 0);\n }\n\n return () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n };\n }, [noteOps, noteKey]);\n\n /**\n * Gets the current note op from the editor, applies the given caller, calls onChange, and\n * optionally applies the change to the parent editor via replaceEmbedUpdate.\n */\n const saveCurrentNoteOp = useCallback(\n (\n resolvedCallerType: FootnoteCallerType,\n resolvedCustomCaller: string,\n applyToParent = false,\n ) => {\n const currentNoteOp = editorRef.current?.getNoteOps(0)?.at(0);\n if (currentNoteOp && isInsertEmbedOpOfType('note', currentNoteOp)) {\n if (currentNoteOp.insert.note) {\n let caller: string;\n if (resolvedCallerType === 'custom') {\n caller = resolvedCustomCaller;\n } else if (resolvedCallerType === 'generated') {\n caller = GENERATOR_NOTE_CALLER;\n } else {\n caller = HIDDEN_NOTE_CALLER;\n }\n currentNoteOp.insert.note.caller = caller;\n }\n onChange?.([currentNoteOp]);\n if (applyToParent && parentEditorRef && noteKey) {\n parentEditorRef.current?.replaceEmbedUpdate(noteKey, [currentNoteOp]);\n }\n }\n },\n [noteKey, onChange, parentEditorRef],\n );\n\n const closeAndSave = useCallback(() => {\n saveCurrentNoteOp(callerType, customCaller, true);\n onClose();\n }, [callerType, customCaller, onClose, saveCurrentNoteOp]);\n\n // Keep a stable ref to closeAndSave so the chapter-change effect below only needs to depend on\n // scrRef.book and scrRef.chapterNum (not on caller state that changes during editing).\n const closeAndSaveRef = useRef(closeAndSave);\n useLayoutEffect(() => {\n closeAndSaveRef.current = closeAndSave;\n });\n\n // Close when the book or chapter changes — verse changes don't require closing.\n // useLayoutEffect runs before useEffect, so the save via replaceEmbedUpdate (which is a\n // synchronous discrete Lexical update) completes before the parent editor's useEffect loads\n // the new chapter's content.\n const prevScrRefBookChapter = useRef({ book: scrRef.book, chapterNum: scrRef.chapterNum });\n useLayoutEffect(() => {\n if (\n prevScrRefBookChapter.current.book !== scrRef.book ||\n prevScrRefBookChapter.current.chapterNum !== scrRef.chapterNum\n ) {\n prevScrRefBookChapter.current = { book: scrRef.book, chapterNum: scrRef.chapterNum };\n closeAndSaveRef.current();\n }\n }, [scrRef.book, scrRef.chapterNum]);\n\n const handleCopy = () => {\n const editorInput = editorParentRef.current?.getElementsByClassName('editor-input')[0];\n if (editorInput?.textContent) {\n navigator.clipboard.writeText(editorInput.textContent);\n }\n };\n\n const handleCallerTypeChange = useCallback(\n (newCallerType: FootnoteCallerType) => {\n setCallerType(newCallerType);\n saveCurrentNoteOp(newCallerType, customCaller);\n },\n [customCaller, saveCurrentNoteOp],\n );\n\n const handleCustomCallerChange = useCallback(\n (newCustomCaller: string) => {\n setCustomCaller(newCustomCaller);\n saveCurrentNoteOp(callerType, newCustomCaller);\n },\n [callerType, saveCurrentNoteOp],\n );\n\n const handleNoteTypeChange = (value: string) => {\n setNoteType(value);\n\n // Changes the note type for the current note that is being edited\n const currentNoteOp = editorRef.current?.getNoteOps(0)?.at(0);\n if (currentNoteOp && isInsertEmbedOpOfType('note', currentNoteOp)) {\n if (currentNoteOp.insert.note) currentNoteOp.insert.note.style = value;\n\n // If switching between cross-reference and footnote/endnote, need to switch the nodes inside\n const innerNoteOps = currentNoteOp.insert.note?.contents?.ops;\n if (noteType !== 'x' && value === 'x') {\n innerNoteOps?.forEach((op) => footnoteToCrossReferenceOp(op));\n } else if (noteType === 'x' && value !== 'x') {\n innerNoteOps?.forEach((op) => crossReferenceToFootnoteOp(op));\n }\n\n // Inserts the new footnote/cross-reference and deletes the old one — triggers handleUsjChange\n editorRef.current?.applyUpdate([currentNoteOp, { delete: 1 }]);\n }\n };\n\n const handleStateChange = (state: StateChangeSnapshot) => {\n setContextMarker(state.contextMarker);\n setCanRedo(state.canRedo);\n };\n\n const handleUsjChange = useCallback(\n (usj: Usj) => {\n const noteOp = editorRef.current?.getNoteOps(0)?.at(0);\n if (noteOp && isInsertEmbedOpOfType('note', noteOp)) {\n // Prevents adding additional note nodes or other nodes after the main footnote node\n if (usj.content.length > 1) {\n setTimeout(() => {\n // Retains the first two nodes which are the added paragraph node (for now) and the\n // footnote/cross-reference and deletes the unwanted node that was just inserted\n editorRef.current?.applyUpdate([{ retain: 2 }, { delete: 1 }]);\n }, 0);\n }\n const currentNoteType = noteOp.insert.note?.style;\n const innerNoteOps = noteOp.insert.note?.contents?.ops;\n if (!currentNoteType) setIsTypeSwitchable(false);\n\n if (currentNoteType === 'x') {\n setIsTypeSwitchable(\n !!innerNoteOps?.every((op) => {\n if (!op.attributes?.char) return true;\n // The built-in type for the delta note ops does not contain the types for the attributes\n // so have to cast it here\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const nodeType = (op.attributes?.char as Record).style;\n return nodeType === 'xt' || nodeType === 'xo' || nodeType === 'xq';\n }),\n );\n } else {\n setIsTypeSwitchable(\n !!innerNoteOps?.every((op) => {\n if (!op.attributes?.char) return true;\n // The built-in type for the delta note ops does not contain the types for the attributes\n // so have to cast it here\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const nodeType = (op.attributes?.char as Record).style;\n return nodeType === 'ft' || nodeType === 'fr' || nodeType === 'fq';\n }),\n );\n }\n\n // On the first call after loading a note, snapshot the initial state and skip auto-save\n if (!hasInitializedEditor.current) {\n hasInitializedEditor.current = true;\n initialNoteOpsJson.current = JSON.stringify(noteOp);\n setIsAtInitialState(true);\n return;\n }\n\n // Track whether the user has undone all their edits back to the initial state\n setIsAtInitialState(JSON.stringify(noteOp) === initialNoteOpsJson.current);\n\n // Auto-save on every content change (does not apply to parent editor)\n saveCurrentNoteOp(callerType, customCaller);\n } else {\n setIsTypeSwitchable(false);\n setIsAtInitialState(true);\n }\n },\n [callerType, customCaller, saveCurrentNoteOp],\n );\n\n const showInlineMarkersMenu = useCallback(() => {\n // Only shows the markers menu if there is currently a selection in the editor and there are\n // existing marker menu items to be shown\n const currentSelection = window.getSelection();\n if (\n outerBorderRef.current &&\n inlineMarkerMenuItems.length &&\n currentSelection &&\n currentSelection.rangeCount > 0\n ) {\n const selectionRect = currentSelection.getRangeAt(0).getBoundingClientRect();\n const footnoteEditorRect = outerBorderRef.current.getBoundingClientRect();\n setMarkersMenuAnchorX(selectionRect.left - footnoteEditorRect.left);\n setMarkersMenuAnchorY(selectionRect.top - footnoteEditorRect.top);\n setMarkersMenuAnchorHeight(selectionRect.height);\n setShowMarkersMenu(true);\n }\n }, [inlineMarkerMenuItems, outerBorderRef]);\n\n // Need to add a window listener for click events that will close the markers menu when you click\n // outside. There is another `onClick` listener for the marker menu that prevents click events\n // from being passed to this listener if the marker menu is being clicked. Those click events are\n // handled separately.\n useEffect(() => {\n const clickListener = () => {\n if (showMarkersMenu) setShowMarkersMenu(false);\n };\n\n window.addEventListener('click', clickListener);\n\n return () => {\n window.removeEventListener('click', clickListener);\n };\n }, [showMarkersMenu]);\n\n // When the inline markers menu is showed, makes sure the search input is focused\n useEffect(() => {\n if (showMarkersMenu) {\n markerMenuSearchRef.current?.focus();\n }\n }, [showMarkersMenu]);\n\n // Listens for the marker menu trigger to open the markers menu\n useEffect(() => {\n const editorInput =\n editorParentRef.current?.querySelector('.editor-input') ?? undefined;\n const handleKeyDown = (event: KeyboardEvent) => {\n // Shows the marker menu if it isn't already being shown and if the editor is currently selected\n if (\n !showMarkersMenu &&\n editorInput &&\n document.activeElement === editorInput &&\n event.key === defaultMarkerMenuTrigger\n ) {\n event.preventDefault();\n showInlineMarkersMenu();\n } else if (showMarkersMenu && event.key === 'Escape') {\n event.preventDefault();\n setShowMarkersMenu(false);\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [showMarkersMenu, showInlineMarkersMenu, defaultMarkerMenuTrigger]);\n\n const copyButtonTooltip = localizedStrings['%footnoteEditor_copyButton_tooltip%'];\n\n return (\n <>\n
\n
\n
\n \n \n
\n
\n \n editorRef.current?.undo()}\n onRedoClick={() => editorRef.current?.redo()}\n canUndo={!isAtInitialState}\n canRedo={canRedo}\n localizedStrings={localizedStrings}\n />\n \n \n
\n
\n \n
\n \n {}}\n scrRef={scrRef}\n ref={editorRef}\n />\n \n
\n
\n \n \n \n \n \n \n \n \n

{copyButtonTooltip}

\n
\n
\n
\n
\n
\n \n \n {/** Inline markers menu components */}\n \n \n {\n event.preventDefault();\n event.stopPropagation();\n }}\n >\n \n \n \n \n );\n}\n","import { usfmMarkers } from 'platform-bible-utils';\nimport { CANCEL_ACCEPT_BUTTONS_STRING_KEYS } from '@/components/basics/cancel-accept-buttons.component';\nimport { UNDO_REDO_BUTTONS_STRING_KEYS } from '@/components/basics/undo-redo-buttons.component';\nimport { MARKER_MENU_STRING_KEYS } from '../marker-menu.component';\n\n/**\n * Object containing all keys used for localization in the FootnoteEditor component. If you're using\n * this component in an extension, you can pass it into the useLocalizedStrings hook to easily\n * obtain the localized strings and pass them into the localizedStrings prop of this component\n */\nexport const FOOTNOTE_EDITOR_STRING_KEYS = Object.freeze([\n ...MARKER_MENU_STRING_KEYS,\n ...Object.entries(usfmMarkers)\n .map(([, markerDetails]) => markerDetails.description)\n .filter((item) => !!item),\n '%footnoteEditor_callerDropdown_item_custom%',\n '%footnoteEditor_callerDropdown_item_generated%',\n '%footnoteEditor_callerDropdown_item_hidden%',\n '%footnoteEditor_callerDropdown_label%',\n '%footnoteEditor_callerDropdown_tooltip%',\n '%footnoteEditor_copyButton_tooltip%',\n '%footnoteEditor_noteType_crossReference_label%',\n '%footnoteEditor_noteType_endNote_label%',\n '%footnoteEditor_noteType_footnote_label%',\n '%footnoteEditor_noteType_tooltip%',\n '%footnoteEditor_noteTypeDropdown_label%',\n '%footnoteEditor_saveButton_tooltip%',\n ...UNDO_REDO_BUTTONS_STRING_KEYS,\n ...CANCEL_ACCEPT_BUTTONS_STRING_KEYS,\n] as const);\n\nexport type FootnoteEditorLocalizedStrings = {\n [localizedKey in (typeof FOOTNOTE_EDITOR_STRING_KEYS)[number]]: string;\n};\n\nexport type FootnoteCallerType = 'generated' | 'hidden' | 'custom';\n","import React from 'react';\nimport { MarkerContent, MarkerObject } from '@eten-tech-foundation/scripture-utilities';\nimport { AlertCircle } from 'lucide-react';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { FootnoteItemProps } from './footnotes.types';\n\nfunction makeKey(parentMarker: string | undefined, content?: MarkerContent[]): string {\n if (!content || content.length === 0) return parentMarker ?? 'empty';\n\n const firstString = content.find((part) => typeof part === 'string');\n if (firstString) {\n return `key-${parentMarker ?? 'unknown'}-${firstString.slice(0, 10)}`;\n }\n\n // Fallback: combine markers\n const firstMarker =\n typeof content[0] === 'string' ? 'impossible' : (content[0].marker ?? 'unknown');\n return `key-${parentMarker ?? 'unknown'}-${firstMarker}`;\n}\n\nfunction renderParagraphs(\n parentMarker: string | undefined,\n content?: MarkerContent[],\n showMarkers = true,\n footnoteClosing: React.ReactNode | undefined = undefined,\n): React.ReactNode {\n if (!content || content.length === 0) return undefined;\n\n const markerHierarchy: string[] = [];\n\n const paragraphs: MarkerContent[][] = [];\n let current: MarkerContent[] = [];\n\n content.forEach((part) => {\n if (typeof part !== 'string' && part.marker === 'fp') {\n // End current paragraph before starting new one\n if (current.length > 0) paragraphs.push(current);\n\n // Start new paragraph that *includes* the fp marker itself\n current = [part];\n } else {\n current.push(part);\n }\n });\n\n if (current.length > 0) paragraphs.push(current);\n\n return paragraphs.map((para, i) => {\n const isLast = i === paragraphs.length - 1;\n return (\n

\n {renderContent(parentMarker, para, showMarkers, true, markerHierarchy)}\n {isLast && footnoteClosing}\n

\n );\n });\n}\n\nfunction renderContent(\n parentMarker: string | undefined,\n content?: MarkerContent[],\n showMarkers = true,\n allowUnmarkedText = true,\n markerHierarchy: string[] = [],\n): React.ReactNode {\n if (!content || content.length === 0) return undefined;\n\n return content.map((footnotePart) => {\n if (typeof footnotePart === 'string') {\n // Build a key based on the hierarchy and text\n const key = `${parentMarker}-text-${footnotePart.slice(0, 10)}`;\n if (allowUnmarkedText) {\n const classes = cn(`usfm_${parentMarker}`);\n return (\n \n {footnotePart}\n \n );\n }\n return (\n \n \n {footnotePart}\n \n
\n );\n }\n\n return renderMarkerObject(\n footnotePart,\n makeKey(`${parentMarker}\\\\${footnotePart.marker}`, [footnotePart]),\n showMarkers,\n [...markerHierarchy, parentMarker ?? 'unknown'],\n );\n });\n}\n\nfunction renderMarkerObject(\n markerObj: MarkerObject,\n key: React.Key,\n showMarkers: boolean,\n markerHierarchy: string[] = [],\n): React.ReactNode {\n const { marker } = markerObj;\n\n return (\n \n {marker ? (\n showMarkers && {`\\\\${marker} `}\n ) : (\n \n )}\n {renderContent(marker, markerObj.content, showMarkers, true, [\n ...markerHierarchy,\n marker ?? 'unknown',\n ])}\n \n );\n}\n\n/** `FootnoteItem` is a component that provides a read-only display of a single USFM/JSX footnote. */\nexport function FootnoteItem({\n footnote,\n layout = 'horizontal',\n formatCaller,\n showMarkers = true,\n}: FootnoteItemProps) {\n const caller = formatCaller ? formatCaller(footnote.caller) : footnote.caller;\n const isCallerFormatted = caller !== footnote.caller;\n\n // Split out target reference (first top-level fr/xo, if any)\n let targetRef: MarkerContent | undefined;\n let remainingContent = footnote.content;\n\n if (\n Array.isArray(footnote.content) &&\n footnote.content.length > 0 &&\n typeof footnote.content[0] !== 'string' &&\n (footnote.content[0].marker === 'fr' || footnote.content[0].marker === 'xo')\n ) {\n [targetRef, ...remainingContent] = footnote.content;\n }\n\n const footnoteOpening = showMarkers ? (\n {`\\\\${footnote.marker} `}\n ) : undefined;\n\n const footnoteClosing = showMarkers ? (\n {` \\\\${footnote.marker}*`}\n ) : undefined;\n\n const footnoteCaller = caller && (\n // USFM does not specify a marker for caller, so instead of a usfm_* class, we use a\n // specific class name in case styling is needed.\n \n {caller}{' '}\n \n );\n const footnoteTargetRef = targetRef && (\n <>{renderContent(footnote.marker, [targetRef], showMarkers, false)} \n );\n\n const layoutClass = layout === 'horizontal' ? 'horizontal' : 'vertical';\n const markerClass = showMarkers ? 'marker-visible' : '';\n const footnoteBodyClass =\n layout === 'horizontal' ? 'tw:col-span-1' : 'tw:col-span-2 tw:col-start-1 tw:row-start-2';\n const baseClasses = cn(layoutClass, markerClass);\n\n return (\n <>\n
\n {footnoteOpening}\n {footnoteCaller}\n
\n
\n {footnoteTargetRef}\n
\n \n {remainingContent && remainingContent.length > 0 && (\n <>{renderParagraphs(footnote.marker, remainingContent, showMarkers, footnoteClosing)}\n )}\n \n \n );\n}\n\nexport default FootnoteItem;\n","import { MarkerObject } from '@eten-tech-foundation/scripture-utilities';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Separator } from '@/components/shadcn-ui/separator';\nimport { getFormatCallerFunction } from 'platform-bible-utils';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { FootnoteItem } from './footnote-item.component';\nimport { FootnoteListProps } from './footnotes.types';\n\n/** `FootnoteList` is a component that provides a read-only display of a list of USFM/JSX footnote. */\nexport function FootnoteList({\n className,\n classNameForItems,\n footnotes,\n layout = 'horizontal',\n listId,\n selectedFootnote,\n showMarkers = true,\n suppressFormatting = false,\n formatCaller,\n onFootnoteSelected,\n}: FootnoteListProps) {\n const handleFormatCaller = formatCaller ?? getFormatCallerFunction(footnotes, undefined);\n const handleFootnoteClick = (footnote: MarkerObject, index: number) => {\n onFootnoteSelected?.(footnote, index, listId);\n };\n\n const initialFocusedIndex = selectedFootnote\n ? footnotes.findIndex((f) => f === selectedFootnote)\n : -1;\n\n const [focusedIndex, setFocusedIndex] = useState(initialFocusedIndex);\n\n const handleFootnoteKeyDown = (\n e: React.KeyboardEvent,\n footnote: MarkerObject,\n index: number,\n ) => {\n if (!footnotes.length) return;\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n onFootnoteSelected?.(footnote, index, listId);\n break;\n\n default:\n break;\n }\n };\n\n const handleListKeyDown = (e: React.KeyboardEvent) => {\n if (!footnotes.length) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n setFocusedIndex((prev) => Math.min(prev + 1, footnotes.length - 1));\n break;\n\n case 'ArrowUp':\n e.preventDefault();\n setFocusedIndex((prev) => Math.max(prev - 1, 0));\n break;\n\n default:\n break;\n }\n };\n\n const rowRefs = useRef<(HTMLLIElement | null)[]>([]);\n\n useEffect(() => {\n if (focusedIndex >= 0 && focusedIndex < rowRefs.current.length) {\n rowRefs.current[focusedIndex]?.focus();\n }\n }, [focusedIndex]);\n\n /*\n * TODO(PT-3743): After upgrading to Tailwind v4, move to using @container and @sm/@lg css\n * styling to replace the use of the `layout` variable to distinguish between\n * wide/skinny layouts.\n */\n return (\n \n \n {footnotes.map((footnote, idx) => {\n const isSelected = footnote === selectedFootnote;\n const key = `${listId}-${idx}`;\n return (\n <>\n {\n rowRefs.current[idx] = el;\n }}\n role=\"option\"\n aria-selected={isSelected}\n key={key}\n data-marker={footnote.marker}\n data-state={isSelected ? 'selected' : undefined}\n tabIndex={idx === focusedIndex ? 0 : -1}\n className={cn(\n 'tw:gap-x-3 tw:gap-y-1 tw:p-2 tw:data-[state=selected]:bg-muted',\n onFootnoteSelected && 'tw:hover:bg-muted/50',\n 'tw:w-full tw:rounded-sm tw:border-0 tw:bg-transparent tw:shadow-none',\n 'tw:focus:outline-hidden tw:focus-visible:outline-hidden',\n /* ENHANCE: After considerable fiddling, this set of styles makes a focus ring\n that looks great in Storybook. However, the left edge of the ring is clipped in\n P.B app. These are similar, but not identical to, the customizations made in\n our shadcn table component.\n */\n 'tw:focus-visible:ring-offset-0.5 tw:focus-visible:relative tw:focus-visible:z-10 tw:focus-visible:ring-2 tw:focus-visible:ring-ring',\n 'tw:grid tw:grid-flow-col tw:grid-cols-subgrid',\n layout === 'horizontal' ? 'tw:col-span-3' : 'tw:col-span-2 tw:row-span-2',\n classNameForItems,\n )}\n onClick={() => handleFootnoteClick(footnote, idx)}\n onKeyDown={(e) => handleFootnoteKeyDown(e, footnote, idx)}\n >\n handleFormatCaller(footnote.caller, idx)}\n showMarkers={showMarkers}\n />\n \n {/* Only render separator if not the last item */}\n {idx < footnotes.length - 1 && layout === 'vertical' && (\n \n )}\n \n );\n })}\n \n \n );\n}\n\nexport default FootnoteList;\n","import {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/shadcn-ui/table';\nimport { SerializedVerseRef } from '@sillsdev/scripture';\nimport { formatScrRef, LanguageStrings } from 'platform-bible-utils';\nimport { ReactNode, useMemo } from 'react';\nimport { InventoryItemOccurrence } from './inventory-utils';\n\n/**\n * Convert text with `\\\\word\\\\` markers to React elements with bold formatting.\n *\n * @param text Text containing `\\\\word\\\\` markers for bolding\n * @returns Array of React nodes with text and bold elements\n */\nfunction formatTextWithBold(text: string): ReactNode[] {\n const parts: ReactNode[] = [];\n let lastIndex = 0;\n // Look for text wrapped in double backslashes (e.g., \\\\bolded text\\\\)\n const regex = /\\\\\\\\(.+?)\\\\\\\\/g;\n let match;\n\n // regex.exec() returns null when no match is found\n // eslint-disable-next-line no-null/no-null, no-cond-assign\n while ((match = regex.exec(text)) !== null) {\n // Add text before the match\n if (match.index > lastIndex) {\n parts.push(text.substring(lastIndex, match.index));\n }\n // Add the bold text\n parts.push({match[1]});\n lastIndex = regex.lastIndex;\n }\n\n // Add any remaining text after the last match\n if (lastIndex < text.length) {\n parts.push(text.substring(lastIndex));\n }\n\n return parts.length > 0 ? parts : [text];\n}\n\n/** Props for the OccurrencesTable component */\ntype OccurrencesTableProps = {\n /** Data that contains scriptures references and snippets of scripture */\n occurrenceData: InventoryItemOccurrence[];\n /** Callback function that is executed when the scripture reference is changed */\n setScriptureReference: (scriptureReference: SerializedVerseRef) => void;\n /**\n * Object with all localized strings that the OccurrencesTable needs to work well across multiple\n * languages\n */\n localizedStrings: LanguageStrings;\n /** Class name to apply to the occurrence text */\n classNameForText?: string;\n};\n\n/**\n * Table that shows occurrences of specified inventory item(s). The first column shows the related\n * scripture reference. The second column shows the snippet of scripture that contains the specified\n * inventory item\n */\nexport function OccurrencesTable({\n occurrenceData,\n setScriptureReference,\n localizedStrings,\n classNameForText,\n}: OccurrencesTableProps) {\n const referenceHeaderText =\n localizedStrings['%webView_inventory_occurrences_table_header_reference%'];\n const occurrenceHeaderText =\n localizedStrings['%webView_inventory_occurrences_table_header_occurrence%'];\n\n const occurrences: InventoryItemOccurrence[] = useMemo(() => {\n const uniqueOccurrences: InventoryItemOccurrence[] = [];\n const seen = new Set();\n\n occurrenceData.forEach((occurrence) => {\n const key = `${occurrence.reference.book}:${occurrence.reference.chapterNum}:${occurrence.reference.verseNum}:${occurrence.text}`;\n\n if (!seen.has(key)) {\n seen.add(key);\n uniqueOccurrences.push(occurrence);\n }\n });\n\n return uniqueOccurrences;\n }, [occurrenceData]);\n\n return (\n \n \n \n {referenceHeaderText}\n {occurrenceHeaderText}\n \n \n \n {occurrences.length > 0 &&\n occurrences.map((occurrence) => (\n {\n setScriptureReference(occurrence.reference);\n }}\n >\n {formatScrRef(occurrence.reference, 'English')}\n \n {formatTextWithBold(occurrence.text)}\n \n \n ))}\n \n
\n );\n}\n\nexport default OccurrencesTable;\n","'use client';\n\nimport React from 'react';\nimport { Checkbox as CheckboxPrimitive } from 'radix-ui';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { IconCheck } from '@tabler/icons-react';\n\n/**\n * Checkbox component provides a control that allows the user to toggle between checked and not\n * checked. This component is built on Radix UI primitives and styled with Shadcn UI.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/checkbox}\n * @see Radix UI Documentation: {@link https://www.radix-ui.com/primitives/docs/components/checkbox}\n */\n// CUSTOM: Added TSDoc comment with links to upstream shadcn/ui and Radix UI documentation.\nfunction Checkbox({ className, ...props }: React.ComponentProps) {\n return (\n \n svg]:size-3.5\"\n >\n \n \n \n );\n}\n\nexport { Checkbox };\n","import { ColumnDef, SortDirection } from '@/components/advanced/data-table/data-table.component';\nimport { ToggleGroup, ToggleGroupItem } from '@/components/shadcn-ui/toggle-group';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport { Column } from '@tanstack/react-table';\nimport {\n ArrowDownIcon,\n ArrowUpIcon,\n CircleCheckIcon,\n CircleHelpIcon,\n CircleXIcon,\n} from 'lucide-react';\nimport { ReactNode } from 'react';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { InventoryTableData, Status } from './inventory-utils';\n\n/**\n * Gets an icon that indicates the current sorting direction based on the provided input\n *\n * @param sortDirection Sorting direction. Can be ascending ('asc'), descending ('desc') or false (\n * i.e. not sorted)\n * @returns The appropriate sorting icon for the provided sorting direction\n */\nconst getSortingIcon = (sortDirection: false | SortDirection): ReactNode => {\n if (sortDirection === 'asc') {\n return ;\n }\n if (sortDirection === 'desc') {\n return ;\n }\n return undefined;\n};\n\n/**\n * Generates a responsive column header for inventory columns with tooltip and sorting functionality\n *\n * @param column The column received from ColumnDef.header\n * @param label The label field to display in the header and tooltip\n * @returns A ReactNode representing the header\n */\nexport const getInventoryHeader = (\n column: Column,\n label: string,\n buttonClassName?: string,\n): ReactNode => {\n return (\n \n \n column.toggleSorting(undefined)}\n >\n \n {label}\n \n {getSortingIcon(column.getIsSorted())}\n \n {label}\n \n \n );\n};\n\n/**\n * Function that creates the item column for inventories\n *\n * @param itemLabel Localized label for the item column (e.g. 'Character', 'Repeated Word', etc.)\n * @returns Column that shows the inventory items. Should be used with the DataTable component\n */\nexport const inventoryItemColumn = (itemLabel: string): ColumnDef => {\n return {\n accessorKey: 'item',\n accessorFn: (row: InventoryTableData) => row.items[0],\n header: ({ column }) => getInventoryHeader(column, itemLabel),\n };\n};\n\n/**\n * Function that creates the additional item columns for inventories\n *\n * @param additionalItemLabel Localized label for the additional item column (e.g. 'Preceding\n * Marker')\n * @param additionalItemIndex Index that locates the desired item in the items array of the\n * inventory\n * @returns Column that shows additional inventory items. Should be used with the DataTable\n * component\n */\nexport const inventoryAdditionalItemColumn = (\n additionalItemLabel: string,\n additionalItemIndex: number,\n): ColumnDef => {\n return {\n accessorKey: `item${additionalItemIndex}`,\n accessorFn: (row: InventoryTableData) => row.items[additionalItemIndex],\n header: ({ column }) => getInventoryHeader(column, additionalItemLabel),\n };\n};\n\n/**\n * Function that creates the count column for inventories. Should be used with the DataTable\n * component.\n *\n * @param countLabel Localized label for the count column\n * @returns Column that shows the number of occurrences of the related inventory items\n */\nexport const inventoryCountColumn = (countLabel: string): ColumnDef => {\n return {\n accessorKey: 'count',\n header: ({ column }) => getInventoryHeader(column, countLabel, 'tw:justify-end'),\n cell: ({ row }) => (\n
{row.getValue('count')}
\n ),\n };\n};\n\n/**\n * Function that updates project settings when status for item(s) changes\n *\n * @param changedItems Array of items for which the status is being updated\n * @param newStatus The status that the items are being given\n * @param approvedItems Array of currently approved items\n * @param onApprovedItemsChange Callback function that stores the updated list of approved items\n * @param unapprovedItems Array of currently unapproved items\n * @param onUnapprovedItemsChange Callback function that stores the updated list of unapproved items\n */\nconst statusChangeHandler = (\n changedItems: string[],\n newStatus: Status,\n approvedItems: string[],\n onApprovedItemsChange: (items: string[]) => void,\n unapprovedItems: string[],\n onUnapprovedItemsChange: (items: string[]) => void,\n) => {\n let newApprovedItems: string[] = [...approvedItems];\n changedItems.forEach((item) => {\n if (newStatus === 'approved') {\n if (!newApprovedItems.includes(item)) {\n newApprovedItems.push(item);\n }\n } else {\n newApprovedItems = newApprovedItems.filter((validItem) => validItem !== item);\n }\n });\n onApprovedItemsChange(newApprovedItems);\n\n let newUnapprovedItems: string[] = [...unapprovedItems];\n changedItems.forEach((item) => {\n if (newStatus === 'unapproved') {\n if (!newUnapprovedItems.includes(item)) {\n newUnapprovedItems.push(item);\n }\n } else {\n newUnapprovedItems = newUnapprovedItems.filter((unapprovedItem) => unapprovedItem !== item);\n }\n });\n onUnapprovedItemsChange(newUnapprovedItems);\n};\n\n/**\n * Function that creates the status column for inventories. Should be used with the DataTable\n * component.\n *\n * @param statusLabel Localized label for the status column\n * @param approvedItems Array of approved items, typically as defined in `Settings.xml`\n * @param onApprovedItemsChange Callback function that stores the updated list of approved items\n * @param unapprovedItems Array of unapproved items, typically as defined in `Settings.xml`\n * @param onUnapprovedItemsChange Callback function that stores the updated list of unapproved items\n * @returns Column that shows the status buttons for the related inventory item. The button for the\n * current status of the item is selected\n */\nexport const inventoryStatusColumn = (\n statusLabel: string,\n approvedItems: string[],\n onApprovedItemsChange: (items: string[]) => void,\n unapprovedItems: string[],\n onUnapprovedItemsChange: (items: string[]) => void,\n): ColumnDef => {\n return {\n accessorKey: 'status',\n header: ({ column }) => getInventoryHeader(column, statusLabel, 'tw:justify-center'),\n cell: ({ row }) => {\n const status: Status = row.getValue('status');\n const item: string = row.getValue('item');\n return (\n // Center the status buttons in the cell to match the centered status column header (the\n // ToggleGroup would otherwise sit left-aligned).\n
\n \n {\n event.stopPropagation();\n statusChangeHandler(\n [item],\n 'approved',\n approvedItems,\n onApprovedItemsChange,\n unapprovedItems,\n onUnapprovedItemsChange,\n );\n }}\n value=\"approved\"\n className=\"tw:rounded-e-none tw:border-e-0\"\n >\n \n \n {\n event.stopPropagation();\n statusChangeHandler(\n [item],\n 'unapproved',\n approvedItems,\n onApprovedItemsChange,\n unapprovedItems,\n onUnapprovedItemsChange,\n );\n }}\n value=\"unapproved\"\n className=\"tw:rounded-none\"\n >\n \n \n {\n event.stopPropagation();\n statusChangeHandler(\n [item],\n 'unknown',\n approvedItems,\n onApprovedItemsChange,\n unapprovedItems,\n onUnapprovedItemsChange,\n );\n }}\n value=\"unknown\"\n className=\"tw:rounded-s-none tw:border-s-0\"\n >\n \n \n \n
\n );\n },\n };\n};\n","import { SerializedVerseRef } from '@sillsdev/scripture';\n\n/* #region Types */\n\n/**\n * Status of items that appear in inventories. 'approved' and 'unapproved' items are defined in the\n * project's `Settings.xml`. All other items are defined as 'unknown'\n */\nexport type Status = 'approved' | 'unapproved' | 'unknown';\n\n/** Occurrence of item in inventory. Primarily used by table that shows occurrences */\nexport type InventoryItemOccurrence = {\n /** Reference to scripture where the item appears */\n reference: SerializedVerseRef;\n /** Snippet of scripture that contains the occurrence */\n text: string;\n};\n\n/** Data structure that contains all information on an item that is shown in an inventory */\nexport type InventoryTableData = {\n /**\n * The item (e.g. a character in the characters inventory, a marker in the marker inventory) In\n * most cases the array will only have one element. In case of additional items (e.g. the\n * preceding marker in the markers check), the primary item should be stored in the first index.\n * To show additional items in the inventory, make sure to configure the `additionalItemsLabels`\n * prop for the Inventory component\n */\n items: string[];\n /** The number of times this item occurs in the selected scope */\n count: number;\n /** The status of this item (see documentation for `Status` type for more information) */\n status: Status;\n /** Occurrences of this item in the scripture text for the selected scope */\n occurrences: InventoryItemOccurrence[];\n};\n\n/* #endregion */\n\n/* #region Functions */\n\n/**\n * Splits USFM string into shorter line-like segments\n *\n * @param text A single (likely very large) USFM string\n * @returns An array containing the input text, split into shorter segments\n */\nexport const getLinesFromUSFM = (text: string) => {\n // Splits on (CR)LF, CR, \\v, \\c and \\id\n return text.split(/(?:\\r?\\n|\\r)|(?=(?:\\\\(?:v|c|id)))/g);\n};\n\n/**\n * Extracts chapter or verse number from USFM strings that start with a \\c or \\v marker\n *\n * @param text USFM string that is expected to start with \\c or \\v marker\n * @returns Chapter or verse number if one is found. Else returns 0.\n */\nexport const getNumberFromUSFM = (text: string): number | undefined => {\n // Captures all digits that follow \\v or \\c markers followed by whitespace located at the start of a string\n const regex = /^\\\\[vc]\\s+(\\d+)/;\n const match = text.match(regex);\n\n if (match) {\n return +match[1];\n }\n return undefined;\n};\n\n/**\n * Gets book ID from USFM string that starts with the \\id marker, and returns book number for it\n *\n * @param text USFM string that is expected to start with \\id marker\n * @returns Book number corresponding to the \\id marker in the input text. Returns 0 if no marker is\n * found or the marker is not valid\n */\nexport const getBookIdFromUSFM = (text: string): string => {\n // Captures all digits that follow an \\id marker followed by whitespace located at the start of a string\n const match = text.match(/^\\\\id\\s+([A-Za-z]+)/);\n if (match) {\n return match[1];\n }\n return '';\n};\n\n/**\n * Gets the status for an item, typically used in the Inventory component\n *\n * @param item The item for which the status is being requested\n * @param approvedItems Array of approved items, typically as defined in `Settings.xml`\n * @param unapprovedItems Array of unapproved items, typically as defined in `Settings.xml`\n * @returns The status for the specified item\n */\nexport const getStatusForItem = (\n item: string,\n approvedItems: string[],\n unapprovedItems: string[],\n): Status => {\n if (unapprovedItems.includes(item)) return 'unapproved';\n if (approvedItems.includes(item)) return 'approved';\n return 'unknown';\n};\n\n/* #endregion */\n","import {\n ColumnDef,\n DataTable,\n RowContents,\n RowSelectionState,\n TableContents,\n} from '@/components/advanced/data-table/data-table.component';\nimport { OccurrencesTable } from '@/components/advanced/inventory/occurrences-table.component';\nimport { Checkbox } from '@/components/shadcn-ui/checkbox';\nimport { Input } from '@/components/shadcn-ui/input';\nimport { Label } from '@/components/shadcn-ui/label';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/shadcn-ui/select';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport { Scope } from '@/components/utils/scripture.util';\nimport { SerializedVerseRef } from '@sillsdev/scripture';\nimport { deepEqual, isString, LocalizedStringValue } from 'platform-bible-utils';\nimport { useEffect, useMemo, useState } from 'react';\nimport { inventoryAdditionalItemColumn } from './inventory-columns';\nimport {\n getStatusForItem,\n InventoryItemOccurrence,\n InventoryTableData,\n Status,\n} from './inventory-utils';\n\n/**\n * Represents an item in the inventory with associated text and verse reference.\n *\n * @deprecated 12 January 2026. Use InventorySummaryItem instead for better performance and\n * functionality.\n */\nexport type InventoryItem = {\n /**\n * The label by which the item is shown in the inventory (e.g. the word that is repeated in case\n * of the Repeated Words check). It serves as a unique identifier for the item. It usually is a\n * string, but can be a string[] when there are multiple defining attributes (e.g. when 'show\n * preceding marker' is enabled for the Markers Inventory, the preceding marker will be stored as\n * the second item in the array)\n */\n inventoryText: string | string[];\n /** The snippet of scripture where this occurrence of the `inventoryItem` is found */\n verse: string;\n /** The reference to the location where the `verse` can be found in scripture */\n verseRef: SerializedVerseRef;\n /**\n * Offset used to locate the `inventoryText` (or inventoryText[0] in case of an array) in the\n * `verse` string\n */\n offset: number;\n};\n\n/**\n * Represents a summary item in the inventory with aggregated count and optional detailed\n * occurrences. This type is used for displaying inventory data in a summarized format, where each\n * item shows the total count and can optionally include detailed occurrence information that gets\n * loaded dynamically when the user selects the item.\n */\nexport type InventorySummaryItem = {\n /** The item key (e.g., character, word, etc.) */\n key: string | string[];\n /** Total count of occurrences */\n count: number;\n /** Status of the item */\n status?: Status;\n /** Detailed occurrences - optional, loaded on demand */\n occurrences?: InventoryItemOccurrence[];\n};\n\n/**\n * Object containing all keys used for localization in this component. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component\n */\nexport const INVENTORY_STRING_KEYS = Object.freeze([\n '%webView_inventory_all%',\n '%webView_inventory_approved%',\n '%webView_inventory_unapproved%',\n '%webView_inventory_unknown%',\n '%webView_inventory_scope_currentBook%',\n '%webView_inventory_scope_chapter%',\n '%webView_inventory_scope_verse%',\n '%webView_inventory_filter_text%',\n '%webView_inventory_show_additional_items%',\n '%webView_inventory_occurrences_table_header_reference%',\n '%webView_inventory_occurrences_table_header_occurrence%',\n '%webView_inventory_no_results%',\n] as const);\n\nexport type InventoryLocalizedStrings = {\n [localizedInventoryKey in (typeof INVENTORY_STRING_KEYS)[number]]?: LocalizedStringValue;\n};\n\n/** Status values that the status filter can select from */\ntype StatusFilter = Status | 'all';\n\n/** Text labels for the inventory columns and the control components of additional inventory items */\ntype AdditionalItemsLabels = {\n checkboxText?: string;\n tableHeaders?: string[];\n};\n\n/**\n * Filters data that is shown in the DataTable section of the Inventory\n *\n * @param itemData All inventory items and their related information\n * @param statusFilter Allows filtering by status (i.e. show all items, or only items that are\n * 'approved', 'unapproved' or 'unknown')\n * @param textFilter Allows filtering by text. All items that include the filter text will be\n * selected.\n * @returns Array of items and their related information that are matched by the specified filters\n */\nconst filterItemData = (\n itemData: InventoryTableData[],\n statusFilter: StatusFilter,\n textFilter: string,\n): InventoryTableData[] => {\n let filteredItemData: InventoryTableData[] = itemData;\n\n if (statusFilter !== 'all') {\n filteredItemData = filteredItemData.filter(\n (item) =>\n (statusFilter === 'approved' && item.status === 'approved') ||\n (statusFilter === 'unapproved' && item.status === 'unapproved') ||\n (statusFilter === 'unknown' && item.status === 'unknown'),\n );\n }\n\n if (textFilter !== '')\n filteredItemData = filteredItemData.filter((item) => item.items[0].includes(textFilter));\n\n return filteredItemData;\n};\n\n/**\n * Processes InventorySummaryItem array into InventoryTableData for display\n *\n * @param inventoryItems Summary items with counts and optional occurrences\n * @param approvedItems Array of approved items\n * @param unapprovedItems Array of unapproved items\n * @returns Array of table data for display\n */\nconst processSummaryItems = (\n inventoryItems: InventorySummaryItem[],\n approvedItems: string[],\n unapprovedItems: string[],\n): InventoryTableData[] => {\n return inventoryItems.map((item) => {\n const itemKey = isString(item.key) ? item.key : item.key[0];\n const items = isString(item.key) ? [item.key] : item.key;\n\n return {\n items,\n count: item.count,\n status: item.status || getStatusForItem(itemKey, approvedItems, unapprovedItems),\n occurrences: item.occurrences || [],\n };\n });\n};\n\n/**\n * Gets the localized value for the provided key\n *\n * @param strings Object containing localized string\n * @param key Key for a localized string\n * @returns The localized value for the provided key, if available. Returns the key if no localized\n * value is available\n */\nconst localizeString = (\n strings: InventoryLocalizedStrings,\n key: keyof InventoryLocalizedStrings,\n) => {\n return strings[key] ?? key;\n};\n\n/** Props for the Inventory component */\ntype InventoryProps = {\n /** The inventory items that the inventory should be populated with */\n inventoryItems: InventorySummaryItem[] | undefined;\n /** Callback function that is executed when the scripture reference is changed */\n setVerseRef: (scriptureReference: SerializedVerseRef) => void;\n /**\n * Object with all localized strings that the Inventory needs to work well across multiple\n * languages. When using this component with Platform.Bible, you can import\n * `INVENTORY_STRING_KEYS` from this library, pass it in to the Platform's localization hook, and\n * pass the localized keys that are returned by the hook into this prop.\n */\n localizedStrings: InventoryLocalizedStrings;\n /**\n * Text labels for control elements and additional column headers in case your Inventory has more\n * than one item to show (e.g. The 'Preceding Marker' in the Markers Inventory)\n */\n additionalItemsLabels?: AdditionalItemsLabels;\n /** Array of approved items, typically as defined in `Settings.xml` */\n approvedItems: string[];\n /** Array of unapproved items, typically as defined in `Settings.xml` */\n unapprovedItems: string[];\n /** Scope of scripture that the inventory will operate on */\n scope: Scope;\n /** Callback function that is executed when the scope is changed from the Inventory */\n onScopeChange: (scope: Scope) => void;\n /**\n * Column definitions for the Inventory data table. The most commonly used column definitions are\n * pre-configured for your convenience and can be imported (e.g. inventoryItemColumn,\n * inventoryAdditionalItemColumn inventoryCountColumn, and inventoryStatusColumn). If you need any\n * other columns you can add these yourself\n */\n columns: ColumnDef[];\n /** Unique identifier for the Inventory component */\n id?: string;\n /** Whether the inventory items are still loading */\n areInventoryItemsLoading?: boolean;\n /** Class name to apply to the provided occurrence verse text in the `OccurrencesTable` component */\n classNameForVerseText?: string;\n /** Optional callback that is called when an item is selected. Receives the selected item key. */\n onItemSelected?: (itemKey: string) => void;\n};\n\n/** Inventory component that is used to view and control the status of provided project settings */\nexport function Inventory({\n inventoryItems,\n setVerseRef,\n localizedStrings,\n additionalItemsLabels,\n approvedItems,\n unapprovedItems,\n scope,\n onScopeChange,\n columns,\n id,\n areInventoryItemsLoading = false,\n classNameForVerseText,\n onItemSelected,\n}: InventoryProps) {\n const allItemsText = localizeString(localizedStrings, '%webView_inventory_all%');\n const approvedItemsText = localizeString(localizedStrings, '%webView_inventory_approved%');\n const unapprovedItemsText = localizeString(localizedStrings, '%webView_inventory_unapproved%');\n const unknownItemsText = localizeString(localizedStrings, '%webView_inventory_unknown%');\n const scopeBookText = localizeString(localizedStrings, '%webView_inventory_scope_currentBook%');\n const scopeChapterText = localizeString(localizedStrings, '%webView_inventory_scope_chapter%');\n const scopeVerseText = localizeString(localizedStrings, '%webView_inventory_scope_verse%');\n const filterText = localizeString(localizedStrings, '%webView_inventory_filter_text%');\n const showAdditionalItemsText = localizeString(\n localizedStrings,\n '%webView_inventory_show_additional_items%',\n );\n const noResultsText = localizeString(localizedStrings, '%webView_inventory_no_results%');\n\n const [showAdditionalItems, setShowAdditionalItems] = useState(false);\n const [statusFilter, setStatusFilter] = useState('all');\n const [textFilter, setTextFilter] = useState('');\n const [selectedItem, setSelectedItem] = useState([]);\n\n const tableData: InventoryTableData[] = useMemo(() => {\n const safeInventoryItems = inventoryItems ?? [];\n if (safeInventoryItems.length === 0) return [];\n return processSummaryItems(safeInventoryItems, approvedItems, unapprovedItems);\n }, [inventoryItems, approvedItems, unapprovedItems]);\n\n const reducedTableData: InventoryTableData[] = useMemo(() => {\n if (showAdditionalItems) return tableData;\n\n const newTableData: InventoryTableData[] = [];\n\n tableData.forEach((tableEntry) => {\n const firstItem = tableEntry.items[0];\n\n const existingEntry = newTableData.find(\n (newTableEntry) => newTableEntry.items[0] === firstItem,\n );\n\n if (existingEntry) {\n existingEntry.count += tableEntry.count;\n existingEntry.occurrences = existingEntry.occurrences.concat(tableEntry.occurrences);\n } else {\n newTableData.push({\n items: [firstItem],\n count: tableEntry.count,\n occurrences: tableEntry.occurrences,\n status: tableEntry.status,\n });\n }\n });\n\n return newTableData;\n }, [showAdditionalItems, tableData]);\n\n const filteredTableData: InventoryTableData[] = useMemo(() => {\n if (reducedTableData.length === 0) return [];\n return filterItemData(reducedTableData, statusFilter, textFilter);\n }, [reducedTableData, statusFilter, textFilter]);\n\n const allColumns: ColumnDef[] = useMemo(() => {\n if (!showAdditionalItems) return columns;\n\n const numberOfAdditionalItems = additionalItemsLabels?.tableHeaders?.length;\n if (!numberOfAdditionalItems) return columns;\n\n const additionalColumns: ColumnDef[] = [];\n\n for (let index = 0; index < numberOfAdditionalItems; index++) {\n additionalColumns.push(\n inventoryAdditionalItemColumn(\n additionalItemsLabels?.tableHeaders?.[index] || 'Additional Item',\n index + 1,\n ),\n );\n }\n\n return [...additionalColumns, ...columns];\n }, [additionalItemsLabels?.tableHeaders, columns, showAdditionalItems]);\n\n useEffect(() => {\n if (filteredTableData.length === 0) {\n setSelectedItem([]);\n } else if (filteredTableData.length === 1) {\n setSelectedItem(filteredTableData[0].items);\n }\n }, [filteredTableData]);\n\n const rowClickHandler = (\n row: RowContents,\n table: TableContents,\n ) => {\n table.setRowSelection(() => {\n const newSelection: RowSelectionState = {};\n newSelection[row.index] = true;\n return newSelection;\n });\n\n const selectedItems = row.original.items;\n setSelectedItem(selectedItems);\n\n // Call the callback if provided, passing the first item as the key\n if (onItemSelected && selectedItems.length > 0) {\n onItemSelected(selectedItems[0]);\n }\n };\n\n const handleScopeChange = (value: string) => {\n if (value === 'book' || value === 'chapter' || value === 'verse') {\n onScopeChange(value);\n } else {\n throw new Error(`Invalid scope value: ${value}`);\n }\n };\n\n const handleStatusFilterChange = (value: string) => {\n if (value === 'all' || value === 'approved' || value === 'unapproved' || value === 'unknown') {\n setStatusFilter(value);\n } else {\n throw new Error(`Invalid status filter value: ${value}`);\n }\n };\n\n const occurrenceData: InventoryItemOccurrence[] = useMemo(() => {\n if (reducedTableData.length === 0 || selectedItem.length === 0) return [];\n const occurrence = reducedTableData.filter((tableEntry: InventoryTableData) => {\n return deepEqual(\n showAdditionalItems ? tableEntry.items : [tableEntry.items[0]],\n selectedItem,\n );\n });\n if (occurrence.length > 1) throw new Error('Selected item is not unique');\n if (occurrence.length === 0) return [];\n return occurrence[0].occurrences;\n }, [selectedItem, showAdditionalItems, reducedTableData]);\n\n return (\n
\n
\n {/* contain: inline-size excludes toolbar from wrapper's min-width calculation\n so the checkbox label can truncate before the scrollbar appears */}\n {/* eslint-disable-next-line react/forbid-dom-props */}\n
\n handleStatusFilterChange(value)}\n defaultValue={statusFilter}\n >\n \n \n \n \n {allItemsText}\n {approvedItemsText}\n {unapprovedItemsText}\n {unknownItemsText}\n \n \n \n {\n setTextFilter(event.target.value);\n }}\n />\n {additionalItemsLabels && (\n \n \n \n
\n {\n setShowAdditionalItems(checked);\n }}\n />\n \n
\n
\n \n {additionalItemsLabels?.checkboxText ?? showAdditionalItemsText}\n \n
\n
\n )}\n
\n
\n \n
\n {occurrenceData.length > 0 && (\n
\n \n
\n )}\n
\n
\n );\n}\n\nexport default Inventory;\n","/**\n * CUSTOM: Changes from the original code from Shadcn: Removed uses of useIsMobile, Sheet, and\n * SheetContent. Also removed the parts setting COOKIES.\n */\n\nimport React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Button } from '@/components/shadcn-ui/button';\nimport { Input } from '@/components/shadcn-ui/input';\nimport { Separator } from '@/components/shadcn-ui/separator';\nimport { Skeleton } from '@/components/shadcn-ui/skeleton';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/shadcn-ui/tooltip';\n// CUSTOM: Added PanelRight import so SidebarTrigger can flip its icon based on the active side\nimport { IconLayoutSidebar, IconLayoutSidebarRight } from '@tabler/icons-react';\n// CUSTOM: Added Direction and readDirection imports for RTL-aware side computation\nimport { type Direction, readDirection } from '@/utils/dir-helper.util';\n\nconst SIDEBAR_WIDTH = '16rem';\nconst SIDEBAR_WIDTH_ICON = '3rem';\n// CUSTOM: Commented this out pending a discussion with UX about keyboard shortcuts\n// const SIDEBAR_KEYBOARD_SHORTCUT = 'b';\n\ntype Side = 'primary' | 'secondary';\n\ntype SidebarContextProps = {\n state: 'expanded' | 'collapsed';\n open: boolean;\n setOpen: (open: boolean) => void;\n toggleSidebar: () => void;\n // CUSTOM: 'side' was moved from Sidebar into the context so that SidebarTrigger can flip its icon\n // (PanelLeft vs PanelRight) based on the active side\n side: Side;\n};\n\n// CUSTOM: Use undefined instead of null as createContext default - avoids no-null/no-null lint rule.\n// The useSidebar() guard (if (!context)) works correctly for undefined.\nconst SidebarContext = React.createContext(undefined);\n\n/** @inheritdoc SidebarProvider */\nfunction useSidebar() {\n const context = React.useContext(SidebarContext);\n if (!context) {\n throw new Error('useSidebar must be used within a SidebarProvider.');\n }\n\n return context;\n}\n\n/**\n * Sidebar components providing an accessible sidebar along with all the sub components that can be\n * used to populate and style it. These components are adapted from Shadcn UI.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/sidebar}\n */\n// CUSTOM: Added TSDoc with link to shadcn/ui documentation\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n children,\n // CUSTOM: Added 'side' prop at provider level so direction-aware side can be propagated via context\n side = 'primary',\n ...props\n}: React.ComponentProps<'div'> & {\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** The side of the sidebar. */\n side?: Side;\n}) {\n // This is the internal state of the sidebar.\n // We use openProp and setOpenProp for control from outside the component.\n // CUSTOM: Removed isMobile, openMobile, setOpenMobile state (useIsMobile removed)\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const [_open, _setOpen] = React.useState(defaultOpen);\n const open = openProp ?? _open;\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === 'function' ? value(open) : value;\n if (setOpenProp) {\n setOpenProp(openState);\n } else {\n _setOpen(openState);\n }\n // CUSTOM: Removed cookie-setting logic (not applicable in Platform.Bible)\n },\n [setOpenProp, open],\n );\n\n // Helper to toggle the sidebar.\n // CUSTOM: Removed isMobile branch from toggleSidebar (mobile support removed)\n const toggleSidebar = React.useCallback(() => {\n return setOpen((prevOpen) => !prevOpen);\n }, [setOpen]);\n\n // CUSTOM: Commented out keyboard shortcut pending a discussion with UX about keyboard shortcuts\n // Adds a keyboard shortcut to toggle the sidebar.\n // React.useEffect(() => {\n // const handleKeyDown = (event: KeyboardEvent) => {\n // if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {\n // event.preventDefault();\n // toggleSidebar();\n // }\n // };\n //\n // window.addEventListener('keydown', handleKeyDown);\n // return () => window.removeEventListener('keydown', handleKeyDown);\n // }, [toggleSidebar]);\n\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n // This makes it easier to style the sidebar with Tailwind classes.\n const state = open ? 'expanded' : 'collapsed';\n\n // CUSTOM: Added RTL-aware side computation so 'primary' always maps to the correct physical side\n const dir: Direction = readDirection();\n const oppositeSide: Side = side === 'primary' ? 'secondary' : 'primary';\n const directionAwareSide = dir === 'ltr' ? side : oppositeSide;\n\n const contextValue = React.useMemo(\n () => ({\n state,\n open,\n setOpen,\n toggleSidebar,\n // CUSTOM: Passes direction-aware side into context so SidebarTrigger icon and Sidebar\n // positioning both respond correctly in RTL layouts\n side: directionAwareSide,\n }),\n [state, open, setOpen, toggleSidebar, directionAwareSide],\n );\n\n // CUSTOM: CSS custom properties (--*) are not in React.CSSProperties; 'as React.CSSProperties'\n // is the standard React pattern for passing CSS variables via the style prop. Extracted to a\n // single-line const so the eslint-disable-next-line can target the assertion precisely.\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const wrapperStyle = {\n '--sidebar-width': SIDEBAR_WIDTH,\n '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,\n ...style,\n } as React.CSSProperties;\n\n return (\n \n \n {children}\n \n \n );\n}\n\n/** @inheritdoc SidebarProvider */\n// CUSTOM: Added TSDoc via @inheritdoc\nfunction Sidebar({\n // CUSTOM: Removed 'side' prop from Sidebar - it is now read from context (moved to SidebarProvider)\n variant = 'sidebar',\n collapsible = 'offcanvas',\n className,\n children,\n ...props\n}: React.ComponentProps<'div'> & {\n variant?: 'sidebar' | 'floating' | 'inset';\n collapsible?: 'offcanvas' | 'icon' | 'none';\n}) {\n // CUSTOM: Read side from context instead of accepting it as a prop\n const context = useSidebar();\n\n if (collapsible === 'none') {\n return (\n \n {children}\n \n );\n }\n\n return (\n \n {/* This is what handles the sidebar gap on desktop */}\n \n \n \n {children}\n \n \n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarTrigger({ className, onClick, ...props }: React.ComponentProps) {\n const { toggleSidebar, side } = useSidebar();\n\n return (\n {\n onClick?.(event);\n toggleSidebar();\n }}\n {...props}\n >\n {/* CUSTOM: Renders PanelLeft or PanelRight based on context.side so the icon always points\n toward the sidebar's current position (accounting for RTL direction) */}\n {side === 'primary' ? : }\n Toggle Sidebar\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarRail({ className, ...props }: React.ComponentProps<'button'>) {\n const { toggleSidebar } = useSidebar();\n\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarInset({ className, ...props }: React.ComponentProps<'main'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarInput({ className, ...props }: React.ComponentProps) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarSeparator({ className, ...props }: React.ComponentProps) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarContent({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarGroupLabel({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<'div'> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : 'div';\n\n return (\n svg]:size-4 tw:[&>svg]:shrink-0',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarGroupAction({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<'button'> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : 'button';\n\n return (\n svg]:size-4 tw:[&>svg]:shrink-0',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarGroupContent({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<'ul'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<'li'>) {\n return (\n \n );\n}\n\nconst sidebarMenuButtonVariants = cva(\n 'tw:peer/menu-button tw:group/menu-button tw:flex tw:w-full tw:items-center tw:gap-2 tw:overflow-hidden tw:rounded-md tw:p-2 tw:text-start tw:text-sm tw:ring-sidebar-ring tw:outline-hidden tw:transition-[width,height,padding] tw:group-has-data-[sidebar=menu-action]/menu-item:pe-8 tw:group-data-[collapsible=icon]:size-8! tw:group-data-[collapsible=icon]:p-2! tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:focus-visible:ring-2 tw:active:bg-sidebar-accent tw:active:text-sidebar-accent-foreground tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:aria-disabled:pointer-events-none tw:aria-disabled:opacity-50 tw:data-open:hover:bg-sidebar-accent tw:data-open:hover:text-sidebar-accent-foreground tw:data-active:bg-sidebar-accent tw:data-active:font-medium tw:data-active:text-sidebar-accent-foreground tw:[&_svg]:size-4 tw:[&_svg]:shrink-0 tw:[&>span:last-child]:truncate',\n {\n variants: {\n variant: {\n default: 'tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground',\n // CUSTOM: Updated shadow color values from hsl(var(--...)) to var(--...) to use the\n // updated CSS variable format that includes the color space directly in the variable value\n outline:\n 'tw:bg-background tw:shadow-[0_0_0_1px_var(--sidebar-border)] tw:hover:bg-sidebar-accent tw:hover:text-sidebar-accent-foreground tw:hover:shadow-[0_0_0_1px_var(--sidebar-accent)]',\n },\n size: {\n default: 'tw:h-8 tw:text-sm',\n sm: 'tw:h-7 tw:text-xs',\n lg: 'tw:h-12 tw:text-sm tw:group-data-[collapsible=icon]:p-0!',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuButton({\n asChild = false,\n isActive = false,\n variant = 'default',\n size = 'default',\n tooltip,\n className,\n ...props\n}: React.ComponentProps<'button'> & {\n asChild?: boolean;\n isActive?: boolean;\n tooltip?: string | React.ComponentProps;\n} & VariantProps) {\n const Comp = asChild ? Slot.Root : 'button';\n const { state } = useSidebar();\n\n const button = (\n \n );\n\n if (!tooltip) {\n return button;\n }\n\n // CUSTOM: Avoid reassigning function parameter (no-param-reassign) by using a new const variable\n const resolvedTooltip: React.ComponentProps =\n typeof tooltip === 'string' ? { children: tooltip } : tooltip;\n\n return (\n \n {button}\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuAction({\n className,\n asChild = false,\n showOnHover = false,\n ...props\n}: React.ComponentProps<'button'> & {\n asChild?: boolean;\n showOnHover?: boolean;\n}) {\n const Comp = asChild ? Slot.Root : 'button';\n\n return (\n svg]:size-4 tw:[&>svg]:shrink-0',\n showOnHover &&\n 'tw:group-focus-within/menu-item:opacity-100 tw:group-hover/menu-item:opacity-100 tw:peer-data-active/menu-button:text-sidebar-accent-foreground tw:aria-expanded:opacity-100 tw:md:opacity-0',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuBadge({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuSkeleton({\n className,\n showIcon = false,\n ...props\n}: React.ComponentProps<'div'> & {\n showIcon?: boolean;\n}) {\n // Random width between 50 to 90%.\n const [width] = React.useState(() => {\n return `${Math.floor(Math.random() * 40) + 50}%`;\n });\n // CUSTOM: CSS custom properties (--*) are not in React.CSSProperties; 'as React.CSSProperties'\n // is the standard React pattern for passing CSS variables via the style prop. Extracted to a\n // single-line const so the eslint-disable-next-line can target the assertion precisely.\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const skeletonStyle = { '--skeleton-width': width } as React.CSSProperties;\n\n return (\n \n {showIcon && (\n \n )}\n \n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<'ul'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuSubItem({ className, ...props }: React.ComponentProps<'li'>) {\n return (\n \n );\n}\n\n/** @inheritdoc SidebarProvider */\nfunction SidebarMenuSubButton({\n asChild = false,\n size = 'md',\n isActive = false,\n className,\n ...props\n}: React.ComponentProps<'a'> & {\n asChild?: boolean;\n size?: 'sm' | 'md';\n isActive?: boolean;\n}) {\n const Comp = asChild ? Slot.Root : 'a';\n\n return (\n span:last-child]:truncate tw:[&>svg]:size-4 tw:[&>svg]:shrink-0 tw:[&>svg]:text-sidebar-accent-foreground',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupAction,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarInput,\n SidebarInset,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSkeleton,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n SidebarProvider,\n SidebarRail,\n SidebarSeparator,\n SidebarTrigger,\n useSidebar,\n};\n","import {\n ProjectSelector,\n type ProjectSelectorProject,\n} from '@/components/advanced/project-selector/project-selector.component';\nimport { Z_INDEX_OVERLAY } from '@/components/z-index';\nimport {\n Sidebar,\n SidebarContent,\n SidebarGroup,\n SidebarGroupLabel,\n SidebarGroupContent,\n SidebarMenu,\n SidebarMenuItem,\n SidebarMenuButton,\n} from '@/components/shadcn-ui/sidebar';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { ScrollText } from 'lucide-react';\nimport { useCallback, useMemo } from 'react';\n\nexport type SelectedSettingsSidebarItem = {\n label: string;\n projectId?: string;\n};\n\nexport type ProjectInfo = { projectId: string; projectName: string };\n\nexport type SettingsSidebarProps = {\n /** Optional id for testing */\n id?: string;\n\n /** Extension labels from contribution */\n extensionLabels: Record;\n\n /** Project names and ids */\n projectInfo: ProjectInfo[];\n\n /** Handler for selecting a sidebar item */\n handleSelectSidebarItem: (key: string, projectId?: string) => void;\n\n /** The current selected value in the sidebar */\n selectedSidebarItem: SelectedSettingsSidebarItem;\n\n /** Label for the group of extensions setting groups */\n extensionsSidebarGroupLabel: string;\n\n /** Label for the group of projects settings */\n projectsSidebarGroupLabel: string;\n\n /** Placeholder text for the button */\n buttonPlaceholderText: string;\n\n /** Additional css classes to help with unique styling of the sidebar */\n className?: string;\n};\n\n/**\n * The SettingsSidebar component is a sidebar that displays a list of extension settings and project\n * settings. It can be used to navigate to different settings pages. Must be wrapped in a\n * SidebarProvider component otherwise produces errors.\n *\n * @param props - {@link SettingsSidebarProps} The props for the component.\n */\nexport function SettingsSidebar({\n id,\n extensionLabels,\n projectInfo,\n handleSelectSidebarItem,\n selectedSidebarItem,\n extensionsSidebarGroupLabel,\n projectsSidebarGroupLabel,\n buttonPlaceholderText,\n className,\n}: SettingsSidebarProps) {\n const handleSelectItem = useCallback(\n (item: string, projectId?: string) => {\n handleSelectSidebarItem(item, projectId);\n },\n [handleSelectSidebarItem],\n );\n\n const getProjectNameFromProjectId = useCallback(\n (projectId: string) => {\n const project = projectInfo.find((info) => info.projectId === projectId);\n return project ? project.projectName : projectId;\n },\n [projectInfo],\n );\n\n // Adapt the public `ProjectInfo[]` shape to `ProjectSelectorProject[]` for the canonical\n // trigger. We only have a single name string in the public API, so reuse it\n // as both `shortName` (the trigger label) and `fullName` (the popover row's secondary line).\n // The public prop shape is intentionally preserved so downstream consumers don't need to change.\n const projectSelectorProjects = useMemo(\n () =>\n projectInfo.map((info) => ({\n id: info.projectId,\n shortName: info.projectName,\n fullName: info.projectName,\n })),\n [projectInfo],\n );\n\n const getIsActive: (label: string) => boolean = useCallback(\n (label: string) => !selectedSidebarItem.projectId && label === selectedSidebarItem.label,\n [selectedSidebarItem],\n );\n\n return (\n \n \n \n \n {extensionsSidebarGroupLabel}\n \n \n \n {Object.entries(extensionLabels).map(([key, label]) => (\n \n handleSelectItem(key)}\n isActive={getIsActive(key)}\n >\n {label}\n \n \n ))}\n \n \n \n \n {projectsSidebarGroupLabel}\n \n {/*\n Flex wrapper hosts the leading icon outside the ProjectSelector's\n trigger button. ProjectSelector has no built-in icon slot, and adding one solely for\n this consumer would expand its API. The icon was decorative on the prior ComboBox\n (no click handler), so keeping it adjacent to — rather than inside — the trigger\n preserves the visual affordance without bloating the canonical component.\n\n Open Tabs grouping isn't wired here because the platform-bible-react library is\n intentionally PAPI-free (see CLAUDE.md \"Symlinked Directories\" / lib boundaries).\n `useOpenProjectTabs` lives in the extension layer; passing `openTabs={[]}` makes the\n ProjectSelector fall back to a flat (non-grouped) list. If a future consumer needs\n the grouping, they can pass `openTabs` in via a new prop on this component.\n */}\n \n \n {\n if (!nextId) return;\n const selectedProjectName = getProjectNameFromProjectId(nextId);\n handleSelectItem(selectedProjectName, nextId);\n }}\n buttonVariant=\"ghost\"\n buttonClassName=\"tw:h-8 tw:w-full tw:flex-1 tw:justify-start tw:font-normal\"\n buttonPlaceholder={buttonPlaceholderText}\n ariaLabel={projectsSidebarGroupLabel}\n // TODO: Check if this z-index override is necessary — the PopoverContent default\n // (Z_INDEX_ABOVE_DOCK = 250) may be sufficient since this dropdown portals to body\n popoverContentStyle={{ zIndex: Z_INDEX_OVERLAY }}\n />\n \n \n \n \n \n );\n}\n\nexport default SettingsSidebar;\n","import { SidebarInset, SidebarProvider } from '@/components/shadcn-ui/sidebar';\nimport { PropsWithChildren } from 'react';\nimport { SearchBar } from '@/components/basics/search-bar.component';\nimport { SettingsSidebar, SettingsSidebarProps } from './settings-sidebar.component';\n\nexport type SettingsSidebarContentSearchProps = SettingsSidebarProps &\n PropsWithChildren & {\n /** The search query in the search bar */\n searchValue: string;\n\n /** Handler to run when the value of the search bar changes */\n onSearch: (searchQuery: string) => void;\n };\n\n/**\n * A component that wraps a search bar and a settings sidebar, providing a way to search and\n * navigate to different settings pages.\n *\n * @param {SettingsSidebarContentSearchProps} props - The props for the component.\n * @param {string} props.id - The id of the sidebar.\n */\nexport function SettingsSidebarContentSearch({\n id,\n extensionLabels,\n projectInfo,\n children,\n handleSelectSidebarItem,\n selectedSidebarItem,\n searchValue,\n onSearch,\n extensionsSidebarGroupLabel,\n projectsSidebarGroupLabel,\n buttonPlaceholderText,\n}: SettingsSidebarContentSearchProps) {\n return (\n
\n
\n \n
\n \n \n {children}\n \n
\n );\n}\n\nexport default SettingsSidebarContentSearch;\n","import { Button } from '@/components/shadcn-ui/button';\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/shadcn-ui/select';\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/shadcn-ui/table';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Canon } from '@sillsdev/scripture';\nimport {\n Cell,\n ColumnDef,\n flexRender,\n getCoreRowModel,\n getExpandedRowModel,\n getGroupedRowModel,\n getSortedRowModel,\n GroupingState,\n Row,\n RowSelectionState,\n SortingState,\n useReactTable,\n} from '@tanstack/react-table';\nimport '@/components/advanced/scripture-results-viewer/scripture-results-viewer.component.css';\nimport {\n compareScrRefs,\n formatScrRef,\n ScriptureSelection,\n scrRefToBBBCCCVVV,\n} from 'platform-bible-utils';\nimport { MouseEvent, useEffect, useMemo, useState } from 'react';\nimport { ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { Direction, readDirection } from '@/utils/dir-helper.util';\n\n/**\n * Information (e.g., a checking error or some other type of \"transient\" annotation) about something\n * noteworthy at a specific place in an instance of the Scriptures.\n */\nexport type ScriptureItemDetail = ScriptureSelection & {\n /**\n * Text of the error, note, etc. In the future, we might want to support something more than just\n * text so that a JSX element could be provided with a link or some other controls related to the\n * issue being reported.\n */\n detail: string;\n};\n\n/**\n * A uniquely identifiable source of results that can be displayed in the ScriptureResultsViewer.\n * Generally, the source will be a particular Scripture check, but there may be other types of\n * sources.\n */\nexport type ResultsSource = {\n /**\n * Uniquely identifies the source.\n *\n * @type {string}\n */\n id: string;\n\n /**\n * Name (potentially localized) of the source, suitable for display in the UI.\n *\n * @type {string}\n */\n displayName: string;\n};\n\nexport type ScriptureSrcItemDetail = ScriptureItemDetail & {\n /** Source/type of detail. Can be used for grouping. */\n source: ResultsSource;\n};\n\n/**\n * Represents a set of results keyed by Scripture reference. Generally, the source will be a\n * particular Scripture check, but this type also allows for other types of uniquely identifiable\n * sources.\n */\nexport type ResultsSet = {\n /**\n * The backing source associated with this set of results.\n *\n * @type {ResultsSource}\n */\n source: ResultsSource;\n\n /**\n * Array of Scripture item details (messages keyed by Scripture reference).\n *\n * @type {ScriptureItemDetail[]}\n */\n data: ScriptureItemDetail[];\n};\n\nconst scrBookColId = 'scrBook';\nconst scrRefColId = 'scrRef';\nconst typeColId = 'source';\nconst detailsColId = 'details';\n\nconst defaultScrRefColumnName = 'Scripture Reference';\nconst defaultScrBookGroupName = 'Scripture Book';\nconst defaultTypeColumnName = 'Type';\nconst defaultDetailsColumnName = 'Details';\n\nexport type ScriptureResultsViewerColumnInfo = {\n /** Optional header to display for the Reference column. Default value: 'Scripture Reference'. */\n scriptureReferenceColumnName?: string;\n\n /** Optional text to display to refer to the Scripture book group. Default value: 'Scripture Book'. */\n scriptureBookGroupName?: string;\n\n /** Optional header to display for the Type column. Default value: 'Type'. */\n typeColumnName?: string;\n\n /** Optional header to display for the Details column. Default value: 'Details' */\n detailsColumnName?: string;\n};\n\nexport type ScriptureResultsViewerProps = ScriptureResultsViewerColumnInfo & {\n /** Groups of ScriptureItemDetail objects from particular sources (e.g., Scripture checks) */\n sources: ResultsSet[];\n\n /** Flag indicating whether to display column headers. Default is false. */\n showColumnHeaders?: boolean;\n\n /** Flag indicating whether to display source column. Default is false. */\n showSourceColumn?: boolean;\n\n /** Callback function to notify when a row is selected */\n onRowSelected?: (selectedRow: ScriptureSrcItemDetail | undefined) => void;\n\n /** Optional id attribute for the outermost element */\n id?: string;\n};\n\nfunction getColumns(\n colInfo?: ScriptureResultsViewerColumnInfo,\n showSourceColumn?: boolean,\n): ColumnDef[] {\n const showSrcCol = showSourceColumn ?? false;\n return [\n {\n accessorFn: (row) => `${row.start.book} ${row.start.chapterNum}:${row.start.verseNum}`,\n id: scrBookColId,\n header: colInfo?.scriptureReferenceColumnName ?? defaultScrRefColumnName,\n cell: (info) => {\n const row = info.row.original;\n if (info.row.getIsGrouped()) {\n return Canon.bookIdToEnglishName(row.start.book);\n }\n return info.row.groupingColumnId === scrBookColId ? formatScrRef(row.start) : undefined;\n },\n getGroupingValue: (row) => Canon.bookIdToNumber(row.start.book),\n sortingFn: (a, b) => {\n return compareScrRefs(a.original.start, b.original.start);\n },\n enableGrouping: true,\n },\n {\n accessorFn: (row) => formatScrRef(row.start),\n id: scrRefColId,\n header: undefined,\n cell: (info) => {\n const row = info.row.original;\n return info.row.getIsGrouped() ? undefined : formatScrRef(row.start);\n },\n sortingFn: (a, b) => {\n return compareScrRefs(a.original.start, b.original.start);\n },\n enableGrouping: false,\n },\n {\n accessorFn: (row) => row.source.displayName,\n id: typeColId,\n header: showSrcCol ? (colInfo?.typeColumnName ?? defaultTypeColumnName) : undefined,\n cell: (info) => (showSrcCol || info.row.getIsGrouped() ? info.getValue() : undefined),\n getGroupingValue: (row) => row.source.id,\n sortingFn: (a, b) =>\n a.original.source.displayName.localeCompare(b.original.source.displayName),\n enableGrouping: true,\n },\n {\n accessorFn: (row) => row.detail,\n id: detailsColId,\n header: colInfo?.detailsColumnName ?? defaultDetailsColumnName,\n cell: (info) => info.getValue(),\n enableGrouping: false,\n },\n ];\n}\n\nconst toRefOrRange = (scriptureSelection: ScriptureSelection) => {\n if (!('offset' in scriptureSelection.start))\n throw new Error('No offset available in range start');\n if (scriptureSelection.end && !('offset' in scriptureSelection.end))\n throw new Error('No offset available in range end');\n const { offset: offsetStart } = scriptureSelection.start;\n let offsetEnd: number = 0;\n if (scriptureSelection.end) ({ offset: offsetEnd } = scriptureSelection.end);\n if (\n !scriptureSelection.end ||\n compareScrRefs(scriptureSelection.start, scriptureSelection.end) === 0\n )\n return `${scrRefToBBBCCCVVV(scriptureSelection.start)}+${offsetStart}`;\n return `${scrRefToBBBCCCVVV(scriptureSelection.start)}+${offsetStart}-${scrRefToBBBCCCVVV(scriptureSelection.end)}+${offsetEnd}`;\n};\n\nconst getRowKey = (row: ScriptureSrcItemDetail) =>\n `${toRefOrRange({ start: row.start, end: row.end })} ${row.source.displayName} ${row.detail}`;\n\n/**\n * Component to display a combined list of detailed items from one or more sources, where the items\n * are keyed primarily by Scripture reference. This is particularly useful for displaying a list of\n * results from Scripture checks, but more generally could be used to display any \"results\" from any\n * source(s). The component allows for grouping by Scripture book, source, or both. By default, it\n * displays somewhat \"tree-like\" which allows it to be more horizontally compact and intuitive. But\n * it also has the option of displaying as a traditional table with column headings (with or without\n * the source column showing).\n */\nexport function ScriptureResultsViewer({\n sources,\n showColumnHeaders = false,\n showSourceColumn = false,\n scriptureReferenceColumnName,\n scriptureBookGroupName,\n typeColumnName,\n detailsColumnName,\n onRowSelected,\n id,\n}: ScriptureResultsViewerProps) {\n const [grouping, setGrouping] = useState([]);\n const [sorting, setSorting] = useState([{ id: scrBookColId, desc: false }]);\n const [rowSelection, setRowSelection] = useState({});\n\n const scriptureResults = useMemo(\n () =>\n sources.flatMap((source) => {\n return source.data.map((item) => ({\n ...item,\n source: source.source,\n }));\n }),\n [sources],\n );\n\n const columns = useMemo(\n () =>\n getColumns(\n {\n scriptureReferenceColumnName,\n typeColumnName,\n detailsColumnName,\n },\n showSourceColumn,\n ),\n [scriptureReferenceColumnName, typeColumnName, detailsColumnName, showSourceColumn],\n );\n\n useEffect(() => {\n // Ensure sorting is applied correctly when grouped by type\n if (grouping.includes(typeColId)) {\n setSorting([\n { id: typeColId, desc: false },\n { id: scrBookColId, desc: false },\n ]);\n } else {\n setSorting([{ id: scrBookColId, desc: false }]);\n }\n }, [grouping]);\n\n const table = useReactTable({\n data: scriptureResults,\n columns,\n state: {\n grouping,\n sorting,\n rowSelection,\n },\n onGroupingChange: setGrouping,\n onSortingChange: setSorting,\n onRowSelectionChange: setRowSelection,\n getExpandedRowModel: getExpandedRowModel(),\n getGroupedRowModel: getGroupedRowModel(),\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getRowId: getRowKey,\n autoResetExpanded: false,\n enableMultiRowSelection: false,\n enableSubRowSelection: false,\n });\n\n useEffect(() => {\n if (onRowSelected) {\n const selectedRows = table.getSelectedRowModel().rowsById;\n const keys = Object.keys(selectedRows);\n if (keys.length === 1) {\n const selectedRow = scriptureResults.find((row) => getRowKey(row) === keys[0]) || undefined;\n if (selectedRow) onRowSelected(selectedRow);\n }\n }\n }, [rowSelection, scriptureResults, onRowSelected, table]);\n\n // Define possible grouping options\n const scrBookGroupName = scriptureBookGroupName ?? defaultScrBookGroupName;\n const typeGroupName = typeColumnName ?? defaultTypeColumnName;\n\n const groupingOptions = [\n { label: 'No Grouping', value: [] },\n { label: `Group by ${scrBookGroupName}`, value: [scrBookColId] },\n { label: `Group by ${typeGroupName}`, value: [typeColId] },\n {\n label: `Group by ${scrBookGroupName} and ${typeGroupName}`,\n value: [scrBookColId, typeColId],\n },\n {\n label: `Group by ${typeGroupName} and ${scrBookGroupName}`,\n value: [typeColId, scrBookColId],\n },\n ];\n\n const handleSelectChange = (selectedGrouping: string) => {\n setGrouping(JSON.parse(selectedGrouping));\n };\n\n const handleRowClick = (row: Row, event: MouseEvent) => {\n if (!row.getIsGrouped() && !row.getIsSelected()) {\n row.getToggleSelectedHandler()(event);\n }\n };\n\n const getEvenOrOddBandingStyle = (row: Row, index: number) => {\n if (row.getIsGrouped()) return '';\n // UX has now said they don't think they want banding. I'm leaving in the code to\n // set even and odd styles, but there's nothing in the CSS to style them differently.\n // The \"even\" style used to also have tw:bg-neutral-300 (along with even) to create\n // a visual banding effect. That could be added back in if UX changes the decision.\n return cn('banded-row', index % 2 === 0 ? 'even' : 'odd');\n };\n\n const getIndent = (\n groupingState: GroupingState,\n row: Row,\n cell: Cell,\n ) => {\n if (groupingState?.length === 0 || row.depth < cell.column.getGroupedIndex()) return undefined;\n if (row.getIsGrouped()) {\n switch (row.depth) {\n case 1:\n return 'tw:ps-4';\n default:\n return undefined;\n }\n }\n switch (row.depth) {\n case 1:\n return 'tw:ps-8';\n case 2:\n return 'tw:ps-12';\n default:\n return undefined;\n }\n };\n\n return (\n
\n {!showColumnHeaders && (\n {\n handleSelectChange(value);\n }}\n >\n \n \n \n \n \n {groupingOptions.map((option) => (\n \n {option.label}\n \n ))}\n \n \n \n )}\n \n {showColumnHeaders && (\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers\n .filter((h) => h.column.columnDef.header)\n .map((header) => (\n /* For sticky column headers to work, we probably need to change the default definition of the shadcn Table component. See https://github.com/shadcn-ui/ui/issues/1151 */\n \n {header.isPlaceholder ? undefined : (\n
\n {header.column.getCanGroup() ? (\n \n {header.column.getIsGrouped() ? `🛑` : `👊 `}\n \n ) : undefined}{' '}\n {flexRender(header.column.columnDef.header, header.getContext())}\n
\n )}\n
\n ))}\n
\n ))}\n
\n )}\n \n {table.getRowModel().rows.map((row, rowIndex) => {\n const dir: Direction = readDirection();\n return (\n handleRowClick(row, event)}\n >\n {row.getVisibleCells().map((cell) => {\n if (\n cell.getIsPlaceholder() ||\n (cell.column.columnDef.enableGrouping &&\n !cell.getIsGrouped() &&\n (cell.column.columnDef.id !== typeColId || !showSourceColumn))\n )\n return undefined;\n return (\n \n {(() => {\n if (cell.getIsGrouped()) {\n return (\n \n {row.getIsExpanded() && }\n {!row.getIsExpanded() &&\n (dir === 'ltr' ? : )}{' '}\n {flexRender(cell.column.columnDef.cell, cell.getContext())} (\n {row.subRows.length})\n \n );\n }\n\n // if (cell.getIsAggregated()) {\n // flexRender(\n // cell.column.columnDef.aggregatedCell ?? cell.column.columnDef.cell,\n // cell.getContext(),\n // );\n // }\n\n return flexRender(cell.column.columnDef.cell, cell.getContext());\n })()}\n \n );\n })}\n \n );\n })}\n \n
\n
\n );\n}\n\nexport default ScriptureResultsViewer;\n","import { Canon } from '@sillsdev/scripture';\nimport { getSectionForBook, Section } from 'platform-bible-utils';\n\n/**\n * Derives the list of available, non-obsolete book IDs from the `availableBookInfo` string\n *\n * @param availableBookInfo Information about available books, formatted as a 123 character long\n * string as defined in a project's BooksPresent setting. Index N is '1' when the Nth canon book\n * is available\n * @returns Array of available, non-obsolete book IDs in canon order\n * @throws If `availableBookInfo` length does not match the number of canon books\n */\nexport function getAvailableBookIds(availableBookInfo: string): string[] {\n if (availableBookInfo.length !== Canon.allBookIds.length) {\n throw new Error('availableBookInfo length must match Canon.allBookIds length');\n }\n\n return Canon.allBookIds.filter(\n (bookId, index) =>\n availableBookInfo[index] === '1' && !Canon.isObsolete(Canon.bookIdToNumber(bookId)),\n );\n}\n\n/**\n * Filters an array of book IDs to only include books from a specific section\n *\n * @param bookIds Array of book IDs to filter\n * @param section The section to filter by\n * @returns Array of book IDs that belong to the specified section\n */\nexport function getBooksForSection(bookIds: string[], section: Section) {\n return bookIds.filter((bookId) => {\n try {\n return getSectionForBook(bookId) === section;\n } catch {\n return false;\n }\n });\n}\n\n/**\n * Checks if all books in a given section are included in the selectedBookIds array\n *\n * @param bookIds Array of all available book IDs\n * @param section The section to check\n * @param selectedBookIds Array of currently selected book IDs\n * @returns True if all books from the specified section are selected, false otherwise\n */\nexport const isSectionFullySelected = (\n bookIds: string[],\n section: Section,\n selectedBookIds: string[],\n) => getBooksForSection(bookIds, section).every((bookId) => selectedBookIds.includes(bookId));\n","import { BookItem } from '@/components/shared/book-item.component';\nimport { Button } from '@/components/shadcn-ui/button';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandList,\n CommandSeparator,\n} from '@/components/shadcn-ui/command';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/shadcn-ui/popover';\nimport { ChevronsUpDown } from 'lucide-react';\nimport { getSectionForBook, Section } from 'platform-bible-utils';\nimport { getSectionLongName, doesBookMatchQuery } from '@/components/shared/book.utils';\nimport { Fragment, MouseEvent, useCallback, useMemo, useRef, useState } from 'react';\nimport { generateCommandValue } from '@/components/shared/book-item.utils';\nimport { getAvailableBookIds } from './scope-selector.utils';\nimport { SelectBooksLocalizedStrings } from './select-books.types';\n\ntype SelectBooksPickerProps = {\n /**\n * Information about available books, formatted as a 123 character long string as defined in a\n * projects BooksPresent setting\n */\n availableBookInfo: string;\n /** Array of currently selected book IDs */\n selectedBookIds: string[];\n /** Callback function that is executed when the book selection changes */\n onChangeSelectedBookIds: (books: string[]) => void;\n /**\n * Object containing the localized strings for the component. The picker uses a subset of\n * {@link SelectBooksLocalizedStrings} (the badge and section-button keys are not used here)\n */\n localizedStrings: SelectBooksLocalizedStrings;\n /**\n * Optional map of localized book IDs/short names and full names. Key is the (English) book ID,\n * value contains localized versions of the ID and full book name\n */\n localizedBookNames?: Map;\n};\n\n/**\n * A searchable dropdown (combobox) for picking multiple books from the Bible canon. It provides:\n *\n * - A trigger button summarizing how many books are selected\n * - A searchable list of all available books, grouped by section\n * - \"Select all\" / \"Clear all\" shortcuts\n * - Support for shift-click and shift-Enter range selection\n *\n * This is the standalone picker used by {@link SelectBooks}, which additionally renders section\n * quick-select buttons and badges for the current selection.\n */\nexport function SelectBooksPicker({\n availableBookInfo,\n selectedBookIds,\n onChangeSelectedBookIds,\n localizedStrings,\n localizedBookNames,\n}: SelectBooksPickerProps) {\n const booksSelectedText = localizedStrings['%webView_book_selector_books_selected%'];\n const selectBooksText = localizedStrings['%webView_book_selector_select_books%'];\n const searchBooksText = localizedStrings['%webView_book_selector_search_books%'];\n const selectAllText = localizedStrings['%webView_book_selector_select_all%'];\n const clearAllText = localizedStrings['%webView_book_selector_clear_all%'];\n const noBookFoundText = localizedStrings['%webView_book_selector_no_book_found%'];\n\n const { otLong, ntLong, dcLong, extraLong } = {\n otLong: localizedStrings?.['%scripture_section_ot_long%'],\n ntLong: localizedStrings?.['%scripture_section_nt_long%'],\n dcLong: localizedStrings?.['%scripture_section_dc_long%'],\n extraLong: localizedStrings?.['%scripture_section_extra_long%'],\n };\n\n const [isBooksSelectorOpen, setIsBooksSelectorOpen] = useState(false);\n const [inputValue, setInputValue] = useState('');\n const lastSelectedBookRef = useRef(undefined);\n const lastKeyEventShiftKey = useRef(false);\n\n const availableBookIds = useMemo(\n () => getAvailableBookIds(availableBookInfo),\n [availableBookInfo],\n );\n\n const filteredBooksBySection = useMemo(() => {\n if (!inputValue.trim()) {\n const allBooks: Record = {\n [Section.OT]: [],\n [Section.NT]: [],\n [Section.DC]: [],\n [Section.Extra]: [],\n };\n\n availableBookIds.forEach((bookId) => {\n const section = getSectionForBook(bookId);\n allBooks[section].push(bookId);\n });\n\n return allBooks;\n }\n\n const filteredBooks = availableBookIds.filter((bookId) =>\n doesBookMatchQuery(bookId, inputValue, localizedBookNames),\n );\n\n const matchingBooks: Record = {\n [Section.OT]: [],\n [Section.NT]: [],\n [Section.DC]: [],\n [Section.Extra]: [],\n };\n\n filteredBooks.forEach((bookId) => {\n const section = getSectionForBook(bookId);\n matchingBooks[section].push(bookId);\n });\n\n return matchingBooks;\n }, [availableBookIds, inputValue, localizedBookNames]);\n\n const toggleBook = useCallback(\n (bookId: string, shiftKey = false) => {\n if (!shiftKey || !lastSelectedBookRef.current) {\n onChangeSelectedBookIds(\n selectedBookIds.includes(bookId)\n ? selectedBookIds.filter((id) => id !== bookId)\n : [...selectedBookIds, bookId],\n );\n lastSelectedBookRef.current = bookId;\n return;\n }\n\n const lastIndex = availableBookIds.findIndex((id) => id === lastSelectedBookRef.current);\n const currentIndex = availableBookIds.findIndex((id) => id === bookId);\n\n if (lastIndex === -1 || currentIndex === -1) return;\n\n const [startIndex, endIndex] = [\n Math.min(lastIndex, currentIndex),\n Math.max(lastIndex, currentIndex),\n ];\n const booksInRange = availableBookIds.slice(startIndex, endIndex + 1).map((id) => id);\n\n onChangeSelectedBookIds(\n selectedBookIds.includes(bookId)\n ? selectedBookIds.filter((shortname) => !booksInRange.includes(shortname))\n : [...new Set([...selectedBookIds, ...booksInRange])],\n );\n },\n [selectedBookIds, onChangeSelectedBookIds, availableBookIds],\n );\n\n const handleKeyboardSelect = (bookId: string) => {\n toggleBook(bookId, lastKeyEventShiftKey.current);\n lastKeyEventShiftKey.current = false;\n };\n\n const handleMouseDown = (event: MouseEvent, bookId: string) => {\n event.preventDefault();\n toggleBook(bookId, event.shiftKey);\n };\n\n const handleSelectAll = () => {\n onChangeSelectedBookIds(availableBookIds.map((bookId) => bookId));\n };\n\n const handleClearAll = () => {\n onChangeSelectedBookIds([]);\n };\n\n return (\n {\n setIsBooksSelectorOpen(open);\n if (!open) {\n setInputValue(''); // Reset search when closing\n }\n }}\n >\n \n \n {selectedBookIds.length > 0\n ? `${booksSelectedText}: ${selectedBookIds.length}`\n : selectBooksText}\n \n \n \n {/* Fixed 500px width (clamped to the viewport) so the book grid lays out\n consistently instead of tracking the trigger width — carried over from\n the pre-refactor BookSelector (markers-checklist work). */}\n \n {\n if (e.key === 'Enter') {\n // Store shift state in a ref that will be used by onSelect\n lastKeyEventShiftKey.current = e.shiftKey;\n }\n }}\n >\n \n
\n \n \n
\n \n {noBookFoundText}\n {Object.values(Section).map((section, index) => {\n const sectionBooks = filteredBooksBySection[section];\n\n if (sectionBooks.length === 0) return undefined;\n\n return (\n \n \n {sectionBooks.map((bookId) => (\n handleKeyboardSelect(bookId)}\n onMouseDown={(event) => handleMouseDown(event, bookId)}\n section={getSectionForBook(bookId)}\n showCheck\n localizedBookNames={localizedBookNames}\n commandValue={generateCommandValue(bookId, localizedBookNames)}\n className=\"tw:flex tw:items-center\"\n />\n ))}\n \n {index < Object.values(Section).length - 1 && }\n \n );\n })}\n \n \n
\n \n );\n}\n","import { Button } from '@/components/shadcn-ui/button';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Section } from 'platform-bible-utils';\nimport { getSectionShortName } from '@/components/shared/book.utils';\nimport { getBooksForSection, isSectionFullySelected } from './scope-selector.utils';\nimport { SelectBooksLocalizedStrings } from './select-books.types';\n\n/**\n * A button component that represents a scripture section (testament) in the book selector. The\n * button shows a different state when all books in its section are selected and becomes disabled\n * when no books are available in its section.\n */\nfunction SectionButton({\n section,\n availableBookIds,\n selectedBookIds,\n onToggle,\n localizedStrings,\n}: {\n section: Section;\n availableBookIds: string[];\n selectedBookIds: string[];\n onToggle: (section: Section) => void;\n localizedStrings: SelectBooksLocalizedStrings;\n}) {\n const isDisabled = getBooksForSection(availableBookIds, section).length === 0;\n\n const sectionOtShortText = localizedStrings['%scripture_section_ot_short%'];\n const sectionNtShortText = localizedStrings['%scripture_section_nt_short%'];\n const sectionDcShortText = localizedStrings['%scripture_section_dc_short%'];\n const sectionExtraShortText = localizedStrings['%scripture_section_extra_short%'];\n\n return (\n onToggle(section)}\n className={cn(\n isSectionFullySelected(availableBookIds, section, selectedBookIds) &&\n !isDisabled &&\n 'tw:bg-primary tw:text-primary-foreground tw:hover:bg-primary/70 tw:hover:text-primary-foreground',\n )}\n disabled={isDisabled}\n >\n {getSectionShortName(\n section,\n sectionOtShortText,\n sectionNtShortText,\n sectionDcShortText,\n sectionExtraShortText,\n )}\n \n );\n}\n\nexport default SectionButton;\n","import { Badge } from '@/components/shadcn-ui/badge';\nimport { Section } from 'platform-bible-utils';\nimport { getLocalizedBookName } from '@/components/shared/book.utils';\nimport { useCallback, useMemo } from 'react';\nimport {\n getAvailableBookIds,\n getBooksForSection,\n isSectionFullySelected,\n} from './scope-selector.utils';\nimport { SelectBooksLocalizedStrings } from './select-books.types';\nimport { SelectBooksPicker } from './select-books-picker.component';\nimport SectionButton from './section-button.component';\n\n/** Maximum number of badges to show before collapsing into a \"+X more\" badge */\nconst VISIBLE_BADGES_COUNT = 5;\n/** Maximum number of badges that can be shown without triggering the collapse */\nconst MAX_VISIBLE_BADGES = 6;\n\ntype SelectBooksProps = {\n /**\n * Information about available books, formatted as a 123 character long string as defined in a\n * projects BooksPresent setting\n */\n availableBookInfo: string;\n /** Array of currently selected book IDs */\n selectedBookIds: string[];\n /** Callback function that is executed when the book selection changes */\n onChangeSelectedBookIds: (books: string[]) => void;\n /** Object containing the localized strings for the component */\n localizedStrings: SelectBooksLocalizedStrings;\n /**\n * Optional map of localized book IDs/short names and full names. Key is the (English) book ID,\n * value contains localized versions of the ID and full book name\n */\n localizedBookNames?: Map;\n};\n\n/**\n * A component for selecting multiple books from the Bible canon. It provides:\n *\n * - Quick selection buttons for major sections (OT, NT, DC, Extra)\n * - A searchable dropdown with all available books (see {@link SelectBooksPicker})\n * - Support for shift-click range selection\n * - Visual feedback with badges showing selected books\n */\nexport function SelectBooks({\n availableBookInfo,\n selectedBookIds,\n onChangeSelectedBookIds,\n localizedStrings,\n localizedBookNames,\n}: SelectBooksProps) {\n const moreText = localizedStrings['%webView_book_selector_more%'];\n\n const availableBooksIds = useMemo(\n () => getAvailableBookIds(availableBookInfo),\n [availableBookInfo],\n );\n\n const toggleSection = useCallback(\n (section: Section) => {\n const sectionBooks = getBooksForSection(availableBooksIds, section).map((bookId) => bookId);\n onChangeSelectedBookIds(\n isSectionFullySelected(availableBooksIds, section, selectedBookIds)\n ? selectedBookIds.filter((shortname) => !sectionBooks.includes(shortname))\n : [...new Set([...selectedBookIds, ...sectionBooks])],\n );\n },\n [selectedBookIds, onChangeSelectedBookIds, availableBooksIds],\n );\n\n return (\n
\n
\n {Object.values(Section).map((section) => {\n return (\n \n );\n })}\n
\n\n \n\n {selectedBookIds.length > 0 && (\n
\n {selectedBookIds\n .slice(\n 0,\n selectedBookIds.length === MAX_VISIBLE_BADGES\n ? MAX_VISIBLE_BADGES\n : VISIBLE_BADGES_COUNT,\n )\n .map((bookId) => (\n \n {getLocalizedBookName(bookId, localizedBookNames)}\n \n ))}\n {selectedBookIds.length > MAX_VISIBLE_BADGES && (\n {`+${selectedBookIds.length - VISIBLE_BADGES_COUNT} ${moreText}`}\n )}\n
\n )}\n
\n );\n}\n","import { LocalizedStringValue } from 'platform-bible-utils';\n\n/**\n * Object containing all keys used for localization in the SelectBooks component. If you're using\n * this component in an extension, you can pass it into the useLocalizedStrings hook to easily\n * obtain the localized strings and pass them into the localizedStrings prop of this component\n */\nexport const SELECT_BOOKS_STRING_KEYS = Object.freeze([\n '%webView_book_selector_books_selected%',\n '%webView_book_selector_select_books%',\n '%webView_book_selector_search_books%',\n '%webView_book_selector_select_all%',\n '%webView_book_selector_clear_all%',\n '%webView_book_selector_no_book_found%',\n '%webView_book_selector_more%',\n '%scripture_section_ot_long%',\n '%scripture_section_ot_short%',\n '%scripture_section_nt_long%',\n '%scripture_section_nt_short%',\n '%scripture_section_dc_long%',\n '%scripture_section_dc_short%',\n '%scripture_section_extra_long%',\n '%scripture_section_extra_short%',\n] as const);\n\n/** Type definition for the localized strings used in the SelectBooks component */\nexport type SelectBooksLocalizedStrings = {\n [selectBooksKey in (typeof SELECT_BOOKS_STRING_KEYS)[number]]?: LocalizedStringValue;\n};\n","import { SelectBooks } from '@/components/advanced/scope-selector/select-books.component';\nimport { SELECT_BOOKS_STRING_KEYS } from '@/components/advanced/scope-selector/select-books.types';\nimport { BookChapterControl } from '@/components/advanced/book-chapter-control/book-chapter-control.component';\nimport { BookChapterControlLocalizedStrings } from '@/components/advanced/book-chapter-control/book-chapter-control.types';\nimport { Button } from '@/components/shadcn-ui/button';\nimport {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/components/shadcn-ui/dialog';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/shadcn-ui/dropdown-menu';\nimport { Label } from '@/components/shadcn-ui/label';\nimport { PopoverPortalContainerProvider } from '@/components/shadcn-ui/popover';\nimport { RadioGroup, RadioGroupItem } from '@/components/shadcn-ui/radio-group';\nimport { Scope, ScopeWithRange } from '@/components/utils/scripture.util';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { SerializedVerseRef } from '@sillsdev/scripture';\nimport { Check, ChevronDown } from 'lucide-react';\nimport {\n defaultScrRef,\n formatScrRef,\n formatScrRefRange,\n LocalizedStringValue,\n} from 'platform-bible-utils';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * Object containing all keys used for localization in this component. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component\n */\nexport const SCOPE_SELECTOR_STRING_KEYS = Object.freeze([\n '%webView_scope_selector_selected_text%',\n '%webView_scope_selector_verse%',\n '%webView_scope_selector_chapter%',\n '%webView_scope_selector_book%',\n '%webView_scope_selector_current_verse%',\n '%webView_scope_selector_current_chapter%',\n '%webView_scope_selector_current_book%',\n '%webView_scope_selector_choose_books%',\n '%webView_scope_selector_scope%',\n '%webView_scope_selector_select_books%',\n '%webView_scope_selector_range%',\n '%webView_scope_selector_select_range%',\n '%webView_scope_selector_range_start%',\n '%webView_scope_selector_range_end%',\n '%webView_scope_selector_ok%',\n '%webView_scope_selector_cancel%',\n '%webView_scope_selector_navigate%',\n // The ScopeSelector renders a SelectBooks component, so it also needs its\n // localized strings (these cover the former inline book_selector and\n // scripture_section keys).\n ...SELECT_BOOKS_STRING_KEYS,\n] as const);\n\n/** Type definition for the localized strings used in this component */\nexport type ScopeSelectorLocalizedStrings = {\n [localizedInventoryKey in (typeof SCOPE_SELECTOR_STRING_KEYS)[number]]?: LocalizedStringValue;\n};\n\n/**\n * Gets the localized value for the provided key\n *\n * @param strings Object containing localized string\n * @param key Key for a localized string\n * @returns The localized value for the provided key, if available. Returns the key if no localized\n * value is available\n */\nconst localizeString = (\n strings: ScopeSelectorLocalizedStrings,\n key: keyof ScopeSelectorLocalizedStrings,\n) => {\n return strings[key] ?? key;\n};\n\n/** Visual layout variant for the scope options. */\nexport type ScopeSelectorVariant = 'radio' | 'dropdown';\n\n/**\n * Keys that submit the start reference in the range picker in addition to Enter. Space and `-` are\n * the natural separators a user types between a start and end reference, so we treat them as \"I'm\n * done with the start, take me to the end\" signals.\n */\nconst RANGE_START_SUBMIT_KEYS = Object.freeze([' ', '-']);\n\n/** Props for configuring the ScopeSelector component */\ninterface ScopeSelectorProps {\n /** The current scope selection */\n scope: ScopeWithRange;\n\n /**\n * Optional array of scopes that should be available in the selector. If not provided, all scopes\n * will be shown as defined in the ScopeWithRange type\n */\n availableScopes?: ScopeWithRange[];\n\n /** Callback function that is executed when the user changes the scope selection */\n onScopeChange: (scope: ScopeWithRange) => void;\n\n /**\n * Information about available books, formatted as a 123 character long string as defined in a\n * projects BooksPresent setting\n */\n availableBookInfo: string;\n\n /** Array of currently selected book IDs */\n selectedBookIds: string[];\n\n /** Callback function that is executed when the user changes the book selection */\n onSelectedBookIdsChange: (books: string[]) => void;\n\n /**\n * Object with all localized strings that the component needs to work well across multiple\n * languages. When using this component with Platform.Bible, you can import\n * `SCOPE_SELECTOR_STRING_KEYS` from this library, pass it in to the Platform's localization hook,\n * and pass the localized keys that are returned by the hook into this prop.\n */\n localizedStrings: ScopeSelectorLocalizedStrings;\n /**\n * Optional map of localized book IDs/short names and full names. Key is the (English) book ID,\n * value contains localized versions of the ID and full book name\n */\n localizedBookNames?: Map;\n /** Optional ID that is applied to the root element of this component */\n id?: string;\n\n /**\n * Controls how the scope options are presented. `'radio'` (default) renders a vertical list of\n * radio buttons. `'dropdown'` renders a single Select trigger whose popover contains the\n * options.\n */\n variant?: ScopeSelectorVariant;\n\n /**\n * The start of the verse range. Only used when `scope === 'range'`. Defaults to `defaultScrRef`\n * (GEN 1:1) if neither this nor `currentScrRef` is provided.\n */\n rangeStart?: SerializedVerseRef;\n /**\n * The end of the verse range. Only used when `scope === 'range'`. Every time the user submits a\n * new `rangeStart`, `onRangeEndChange` is also fired with that same reference so the end mirrors\n * the start; the user is free to narrow the end afterward. Defaults to `defaultScrRef` (GEN 1:1)\n * if neither this nor `currentScrRef` is provided.\n */\n rangeEnd?: SerializedVerseRef;\n /** Callback when the range start reference changes. Required to make the range UI functional. */\n onRangeStartChange?: (scrRef: SerializedVerseRef) => void;\n /** Callback when the range end reference changes. Required to make the range UI functional. */\n onRangeEndChange?: (scrRef: SerializedVerseRef) => void;\n /**\n * Optional current scripture reference. When provided and no explicit `rangeStart` or `rangeEnd`\n * is supplied, it is used as the initial value for the range controls.\n */\n currentScrRef?: SerializedVerseRef;\n /**\n * Optional callback fired when the user picks a new scripture reference from the \"Navigate\"\n * footer entry at the bottom of the dropdown variant. Provide this alongside `currentScrRef` (and\n * using `variant=\"dropdown\"`) to surface the footer button — a BookChapterControl picker prefixed\n * with a \"Navigate\" headline and the current reference. Without this callback the footer is not\n * rendered.\n */\n onCurrentScrRefChange?: (scrRef: SerializedVerseRef) => void;\n /**\n * Optional localized strings passed to the range BCV controls. When omitted, the BCV controls\n * will fall back to their internal defaults.\n */\n bookChapterControlLocalizedStrings?: BookChapterControlLocalizedStrings;\n /**\n * Optional callback returning the number of verses for a given book and chapter. When provided,\n * the range BCV controls enable verse selection. See `BookChapterControlProps.getEndVerse`.\n */\n getEndVerse?: (bookId: string, chapterNum: number) => number;\n /**\n * When true, suppresses the \"Scope\" label rendered above the trigger. Useful for compact\n * placements (e.g. inside a tab toolbar) where the trigger speaks for itself and the extra\n * vertical space pushes the trigger off-screen.\n */\n hideLabel?: boolean;\n /**\n * Additional Tailwind classes applied to the trigger button. Use this to control the trigger\n * height in compact contexts (e.g. `'tw:h-8'` to align with other toolbar controls).\n */\n buttonClassName?: string;\n}\n\n/**\n * A component that allows users to select the scope of their search or operation. Available scopes\n * are defined in the ScopeWithRange type. When 'selectedBooks' is chosen as the scope, a\n * SelectBooks component is displayed to allow users to choose specific books. When 'range' is\n * chosen, two BookChapterControl pickers are displayed for selecting the start and end verse of the\n * range.\n */\nexport function ScopeSelector({\n scope,\n availableScopes,\n onScopeChange,\n availableBookInfo,\n selectedBookIds,\n onSelectedBookIdsChange,\n localizedStrings,\n localizedBookNames,\n id,\n variant = 'radio',\n rangeStart,\n rangeEnd,\n onRangeStartChange,\n onRangeEndChange,\n currentScrRef,\n onCurrentScrRefChange,\n bookChapterControlLocalizedStrings,\n getEndVerse,\n hideLabel = false,\n buttonClassName,\n}: ScopeSelectorProps) {\n const selectedTextText = localizeString(\n localizedStrings,\n '%webView_scope_selector_selected_text%',\n );\n const verseText = localizeString(localizedStrings, '%webView_scope_selector_verse%');\n const chapterText = localizeString(localizedStrings, '%webView_scope_selector_chapter%');\n const bookText = localizeString(localizedStrings, '%webView_scope_selector_book%');\n const currentVerseText = localizeString(\n localizedStrings,\n '%webView_scope_selector_current_verse%',\n );\n const currentChapterText = localizeString(\n localizedStrings,\n '%webView_scope_selector_current_chapter%',\n );\n const currentBookText = localizeString(localizedStrings, '%webView_scope_selector_current_book%');\n const chooseBooksText = localizeString(localizedStrings, '%webView_scope_selector_choose_books%');\n const scopeText = localizeString(localizedStrings, '%webView_scope_selector_scope%');\n const selectBooksText = localizeString(localizedStrings, '%webView_scope_selector_select_books%');\n const rangeText = localizeString(localizedStrings, '%webView_scope_selector_range%');\n const selectRangeText = localizeString(localizedStrings, '%webView_scope_selector_select_range%');\n const rangeStartText = localizeString(localizedStrings, '%webView_scope_selector_range_start%');\n const rangeEndText = localizeString(localizedStrings, '%webView_scope_selector_range_end%');\n const okText = localizeString(localizedStrings, '%webView_scope_selector_ok%');\n const cancelText = localizeString(localizedStrings, '%webView_scope_selector_cancel%');\n const navigateText = localizeString(localizedStrings, '%webView_scope_selector_navigate%');\n\n // For the verse / chapter / book scopes we surface the current scripture reference alongside the\n // base label (e.g. \"Verse: GEN 1:1\"). The suffix is kept separate from the base label so the\n // rendering can style it differently (muted foreground). When no `currentScrRef` is provided we\n // fall through to just the bare label.\n const getScrRefSuffix = (scopeValue: Scope): string | undefined => {\n if (!currentScrRef) return undefined;\n const upperBook = currentScrRef.book.toUpperCase();\n switch (scopeValue) {\n case 'verse':\n return formatScrRef(currentScrRef, 'id');\n case 'chapter':\n return `${upperBook} ${currentScrRef.chapterNum}`;\n case 'book':\n return upperBook;\n default:\n return undefined;\n }\n };\n\n // Each option carries a `label` (used in the trigger button) and an optional `dropdownLabel`\n // (used in the dropdown menu items). For verse / chapter / book the dropdown form prefixes\n // \"Current\" so users browsing the menu see the semantics up front; the trigger stays terse\n // so the selected value stays compact (\"Verse: GEN 1:1\" rather than \"Current verse: GEN 1:1\").\n const SCOPE_OPTIONS: Array<{\n value: ScopeWithRange;\n label: string;\n dropdownLabel?: string;\n scrRefSuffix?: string;\n id: string;\n }> = [\n { value: 'selectedText', label: selectedTextText, id: 'scope-selected-text' },\n {\n value: 'verse',\n label: verseText,\n dropdownLabel: currentVerseText,\n scrRefSuffix: getScrRefSuffix('verse'),\n id: 'scope-verse',\n },\n {\n value: 'chapter',\n label: chapterText,\n dropdownLabel: currentChapterText,\n scrRefSuffix: getScrRefSuffix('chapter'),\n id: 'scope-chapter',\n },\n {\n value: 'book',\n label: bookText,\n dropdownLabel: currentBookText,\n scrRefSuffix: getScrRefSuffix('book'),\n id: 'scope-book',\n },\n { value: 'selectedBooks', label: chooseBooksText, id: 'scope-selected' },\n { value: 'range', label: rangeText, id: 'scope-range' },\n ];\n\n // Renders a scope option label with its optional ScrRef suffix styled in muted foreground. Kept\n // inline so every render site (dropdown items, radio labels, trigger content) is visually\n // consistent. `hideScrRef` is true only for the trigger in the dropdown variant when the\n // trigger width is too narrow to fit both the label and the reference — the dropdown menu\n // items and radio labels always show the suffix.\n const renderScopeLabel = (\n label: string,\n scrRefSuffix: string | undefined,\n hideScrRef = false,\n ) => (\n <>\n {label}\n {scrRefSuffix && !hideScrRef && (\n : {scrRefSuffix}\n )}\n \n );\n\n const displayedScopes = availableScopes\n ? SCOPE_OPTIONS.filter((option) => availableScopes.includes(option.value))\n : SCOPE_OPTIONS;\n\n // Both range pickers default to the caller-supplied current scripture reference, falling back\n // to GEN 1:1 when nothing is provided. `rangeStart` / `rangeEnd` always win when explicitly\n // supplied so the component stays controlled.\n const fallbackScrRef = currentScrRef ?? defaultScrRef;\n const resolvedRangeStart = rangeStart ?? fallbackScrRef;\n const resolvedRangeEnd = rangeEnd ?? fallbackScrRef;\n\n const noopScrRefChange = () => {};\n\n // Wrapper around the end BCV, used to find its trigger button so we can programmatically\n // open the end picker after the user submits the start reference. Clicking a DOM node\n // from a callback is a bit blunt, but BCV doesn't expose an imperative API and the\n // trigger is a stable child of this wrapper (a single `\n \n \n \n {simpleScopes.map(({ value, label, dropdownLabel, scrRefSuffix, id: scopeId }) => (\n handleScopeChange(value)}\n data-selected={scope === value ? 'true' : undefined}\n >\n {scope === value && (\n \n \n \n )}\n {renderScopeLabel(dropdownLabel ?? label, scrRefSuffix, isDropdownNarrow)}\n \n ))}\n {(selectedBooksScope || rangeScope) && }\n {selectedBooksScope && (\n openDialogFallback('selectedBooks')}\n data-selected={scope === 'selectedBooks' ? 'true' : undefined}\n >\n {renderDialogLauncherCheck('selectedBooks')}\n {/* Trailing ellipsis — standard affordance for a menu item that opens a\n dialog. */}\n {`${selectedBooksScope.label}…`}\n \n )}\n {rangeScope && (\n openDialogFallback('range')}\n data-selected={scope === 'range' ? 'true' : undefined}\n >\n {renderDialogLauncherCheck('range')}\n {`${rangeScope.label}…`}\n \n )}\n {/* Navigate footer: a \"Navigate\" DropdownMenuLabel headline above a BCV\n styled as a full-width ghost menu-item-looking button showing the\n current reference. Only rendered when the caller wires up\n `onCurrentScrRefChange`, since the footer's whole purpose is to\n change the current ref. The BCV's own Popover portals inside\n `DropdownMenuContent` thanks to the enclosing\n `PopoverPortalContainerProvider`, and the row is wrapped in a\n DropdownMenuItem so arrow-key navigation can reach it alongside the\n other menu entries (see onSelect / pointer-down guard below). */}\n {onCurrentScrRefChange && (\n <>\n \n {/* Match cmdk's `[cmdk-group-heading]` styling used elsewhere in\n the app (see `CommandGroup`): xs muted-foreground medium-weight\n text with compact padding. Applied via className override on\n DropdownMenuLabel so we still get its semantic role while\n visually aligning with in-app command-palette section headings. */}\n \n {navigateText}\n \n {\n // Preserve the open dropdown menu: activating this row should\n // open the BCV popover, not dismiss the outer menu the way a\n // normal menu item would.\n event.preventDefault();\n // Radix fires onSelect for both mouse pointerdown and keyboard\n // Enter/Space. For a mouse click on the BCV button the button's\n // own onClick already opened the popover; re-invoking click()\n // here would toggle it back closed. The capture-phase handler\n // below flags pointer activations so we can skip re-entry in\n // that case; keyboard activations fall through and trigger the\n // BCV via its trigger button.\n if (navBcvPointerActivatedRef.current) {\n navBcvPointerActivatedRef.current = false;\n return;\n }\n // When the BCV popover is already open, Space / Enter on the\n // menu item (or on its descendant trigger button, since React\n // synthetic events bubble through the virtual tree to the\n // DropdownMenuItem) would otherwise re-click the trigger and\n // toggle the popover shut. Treat the activation as a no-op in\n // that state — the picker is already visible.\n if (isNavBcvOpenRef.current) return;\n navBcvWrapperRef.current?.querySelector('button')?.click();\n }}\n >\n {\n // Pointer activations that land inside the BCV button are\n // handled by the button's own onClick; remember that so the\n // subsequent DropdownMenuItem onSelect skips the programmatic\n // re-click. Padding-only clicks fall through to onSelect so\n // the row still opens BCV when the user clicks near the edge.\n const target = e.target instanceof HTMLElement ? e.target : undefined;\n if (!target?.closest('button')) return;\n navBcvPointerActivatedRef.current = true;\n // Guarantee the flag doesn't outlive this gesture: click /\n // onSelect fire synchronously in the same frame as the\n // pointer gesture, so onSelect still sees the true value;\n // if the user cancels the click (drag-away), the RAF reset\n // keeps a later keyboard Enter from being wrongly skipped.\n requestAnimationFrame(() => {\n navBcvPointerActivatedRef.current = false;\n });\n }}\n >\n {\n isNavBcvOpenRef.current = open;\n }}\n onCloseAutoFocus={(event) => {\n // By default Radix Popover restores focus to the BCV trigger\n // button — which lives inside this DropdownMenuItem. The outer\n // DropdownMenu only routes arrow-key navigation to focused\n // DropdownMenuItems, so leaving focus on the nested button\n // dead-ends keyboard navigation (arrow keys would instead\n // render the button's focus ring). Intercept the restore and\n // pull focus up to the menu item so the menu's roving focus\n // picks up from there.\n event.preventDefault();\n navMenuItemRef.current?.focus();\n }}\n // Modal so the picker gets its own FocusScope: opening BCV\n // from inside the modal DropdownMenu would otherwise collide\n // with the dropdown's focus trap whenever BCV's internal\n // view transitions (books → chapters → verses) cause a focus\n // blip, and the dropdown would yank focus out mid-transition\n // causing the popover to close before the user can select\n // a chapter.\n modal\n // Override BCV's default compact trigger into a full-width\n // left-aligned row that looks at home inside a menu list, and\n // drop the button's `tw:font-medium` so the reference reads at\n // normal weight alongside the other menu items. tailwind-merge's\n // last-wins conflict resolution picks these over BCV's defaults.\n className=\"tw:w-full tw:min-w-0 tw:max-w-none tw:justify-between tw:px-2 tw:font-normal\"\n triggerContent={\n <>\n \n {formatScrRef(currentScrRef ?? defaultScrRef, 'id')}\n \n \n \n }\n />\n \n \n \n )}\n \n \n \n ) : (\n \n {displayedScopes.map(({ value, label, scrRefSuffix, id: scopeId }) => (\n
\n \n \n
\n ))}\n \n )}\n \n\n {/* In the radio variant, render the picker inline below the scope chooser. In the dropdown\n variant, the picker lives inside a modal dialog (see the Dialog blocks below). */}\n {variant === 'radio' && scope === 'selectedBooks' && (\n
\n \n {bookSelectorBlock}\n
\n )}\n\n {variant === 'radio' && scope === 'range' && rangeBlock}\n\n {/* Dropdown variant: selectedBooks and range entries always open in a modal dialog\n (no flyout submenu path). `tw:pe-8` on the header reserves space for the\n absolute-positioned close button so it can't overlap a long title. */}\n {variant === 'dropdown' && selectedBooksScope && (\n \n {\n if (booksDialogEl?.querySelector('[data-state=\"open\"]')) {\n event.preventDefault();\n }\n }}\n >\n \n \n {chooseBooksText}\n \n {bookSelectorBlock}\n \n \n \n \n \n \n \n )}\n {variant === 'dropdown' && rangeScope && (\n \n {\n if (rangeDialogEl?.querySelector('[data-state=\"open\"]')) {\n event.preventDefault();\n }\n }}\n >\n \n \n {selectRangeText}\n \n {rangeBlock}\n \n \n \n \n \n \n \n )}\n \n );\n}\n\nexport default ScopeSelector;\n","import {\n getLocalizeKeyForScrollGroupId,\n LanguageStrings,\n ScrollGroupId,\n} from 'platform-bible-utils';\nimport { DEFAULT_SCROLL_GROUP_LOCALIZED_STRINGS } from 'platform-bible-utils/experimental';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/shadcn-ui/select';\nimport { Direction, readDirection } from '@/utils/dir-helper.util';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Z_INDEX_ABOVE_DOCK } from '@/components/z-index';\n\nexport type ScrollGroupSelectorProps = {\n /**\n * List of scroll group ids to show to the user. Either a `ScrollGroupId` or `undefined` for no\n * scroll group\n */\n availableScrollGroupIds: (ScrollGroupId | undefined)[];\n /** Currently selected scroll group id. `undefined` for no scroll group */\n scrollGroupId: ScrollGroupId | undefined;\n /** Callback function run when the user tries to change the scroll group id */\n onChangeScrollGroupId: (newScrollGroupId: ScrollGroupId | undefined) => void;\n /**\n * Localized strings to use for displaying scroll group ids. Must be an object whose keys are\n * `getLocalizeKeyForScrollGroupId(scrollGroupId)` for all scroll group ids (and `undefined` if\n * included) in {@link ScrollGroupSelectorProps.availableScrollGroupIds} and whose values are the\n * localized strings to use for those scroll group ids.\n *\n * Defaults to English localizations of English alphabet for scroll groups 0-25 (e.g. 0 is A) and\n * Ø for `undefined`. Will fill in any that are not provided with these English localizations.\n * Also, if any values match the keys, the English localization will be used. This is useful in\n * case you want to pass in a temporary version of the localized strings while your localized\n * strings load.\n *\n * @example\n *\n * ```typescript\n * const myScrollGroupIdLocalizedStrings = {\n * [getLocalizeKeyForScrollGroupId('undefined')]: 'Ø',\n * [getLocalizeKeyForScrollGroupId(0)]: 'A',\n * [getLocalizeKeyForScrollGroupId(1)]: 'B',\n * [getLocalizeKeyForScrollGroupId(2)]: 'C',\n * [getLocalizeKeyForScrollGroupId(3)]: 'D',\n * [getLocalizeKeyForScrollGroupId(4)]: 'E',\n * };\n * ```\n *\n * @example\n *\n * ```tsx\n * const availableScrollGroupIds = [undefined, 0, 1, 2, 3, 4];\n *\n * const localizeKeys = getLocalizeKeysForScrollGroupIds();\n *\n * const [localizedStrings] = useLocalizedStrings(localizeKeys);\n *\n * ...\n *\n * \n * ```\n */\n localizedStrings?: LanguageStrings;\n\n /** Size of the scroll group dropdown button. Defaults to 'sm' */\n size?: 'default' | 'sm';\n\n /** Additional css classes to help with unique styling */\n className?: string;\n\n /** Optional id for the select element */\n id?: string;\n\n /** When true, the selector is disabled */\n disabled?: boolean;\n};\n\n/** Selector component for choosing a scroll group */\nexport function ScrollGroupSelector({\n availableScrollGroupIds,\n scrollGroupId,\n onChangeScrollGroupId,\n localizedStrings = {},\n size = 'sm',\n className,\n id,\n disabled,\n}: ScrollGroupSelectorProps) {\n const localizedStringsDefaulted = {\n ...DEFAULT_SCROLL_GROUP_LOCALIZED_STRINGS,\n ...Object.fromEntries(\n Object.entries(localizedStrings).map(\n ([localizedStringKey, localizedStringValue]: [string, string]) => [\n localizedStringKey,\n localizedStringKey === localizedStringValue &&\n localizedStringKey in DEFAULT_SCROLL_GROUP_LOCALIZED_STRINGS\n ? DEFAULT_SCROLL_GROUP_LOCALIZED_STRINGS[localizedStringKey]\n : localizedStringValue,\n ],\n ),\n ),\n };\n\n const dir: Direction = readDirection();\n\n return (\n \n onChangeScrollGroupId(\n newScrollGroupString === 'undefined' ? undefined : parseInt(newScrollGroupString, 10),\n )\n }\n disabled={disabled}\n >\n \n \n \n \n {availableScrollGroupIds.map((scrollGroupOptionId) => (\n \n {localizedStringsDefaulted[getLocalizeKeyForScrollGroupId(scrollGroupOptionId)]}\n \n ))}\n \n \n );\n}\n\nexport default ScrollGroupSelector;\n","import { PropsWithChildren } from 'react';\nimport { Separator } from '@/components/shadcn-ui/separator';\n\n/** Props for the SettingsList component, currently just children */\ntype SettingsListProps = PropsWithChildren;\n\n/**\n * SettingsList component is a wrapper for list items. Rendered with a formatted div\n *\n * @deprecated Jul 18 2025. This component is no longer supported or tested. Use of this component\n * is discouraged and it may be removed in the future.\n * @param children To populate the list with\n * @returns Formatted div encompassing the children\n */\nexport function SettingsList({ children }: SettingsListProps) {\n return
{children}
;\n}\n\n/** Props for SettingsListItem component */\ntype SettingsListItemProps = PropsWithChildren & {\n /** Primary text of the list item */\n primary: string;\n\n /** Optional text of the list item */\n secondary?: string | undefined;\n\n /** Optional boolean to display a message if the children aren't loaded yet. Defaults to false */\n isLoading?: boolean;\n\n /** Optional message to display if isLoading */\n loadingMessage?: string;\n};\n\n/**\n * SettingsListItem component is a common list item. Rendered with a formatted div\n *\n * @deprecated Jul 18 2025. This component is no longer supported or tested. Use of this component\n * is discouraged and it may be removed in the future.\n * @param SettingsListItemProps\n * @returns Formatted div encompassing the list item content\n */\nexport function SettingsListItem({\n primary,\n secondary,\n children,\n isLoading = false,\n loadingMessage,\n}: SettingsListItemProps) {\n return (\n
\n
\n

{primary}

\n

\n {secondary}\n

\n
\n\n {isLoading ? (\n

{loadingMessage}

\n ) : (\n
{children}
\n )}\n
\n );\n}\n\n/** Props for SettingsListHeader component */\ntype SettingsListHeaderProps = {\n /** The primary text of the list header */\n primary: string;\n\n /** Optional secondary text of the list header */\n secondary?: string | undefined;\n\n /** Optional boolean to include a separator underneath the secondary text. Defaults to false */\n includeSeparator?: boolean;\n};\n\n/**\n * SettingsListHeader component displays text above the list\n *\n * @deprecated Jul 18 2025. This component is no longer supported or tested. Use of this component\n * is discouraged and it may be removed in the future.\n * @param SettingsListHeaderProps\n * @returns Formatted div with list header content\n */\nexport function SettingsListHeader({\n primary,\n secondary,\n includeSeparator = false,\n}: SettingsListHeaderProps) {\n return (\n
\n
\n

{primary}

\n

{secondary}

\n
\n {includeSeparator ? : ''}\n
\n );\n}\n","import { GroupsInMultiColumnMenu, Localized } from 'platform-bible-utils';\n\n/**\n * Function that looks up the key of a sub-menu group using the value of it's `menuItem` property.\n *\n * @example\n *\n * ```ts\n * const groups = {\n * 'platform.subMenu': { menuItem: 'platform.subMenuId', order: 1 },\n * 'platform.subSubMenu': { menuItem: 'platform.subSubMenuId', order: 2 },\n * };\n * const id = 'platform.subMenuId';\n * const groupKey = getSubMenuGroupKeyForMenuItemId(groups, id);\n * console.log(groupKey); // Output: 'platform.subMenu'\n * ```\n *\n * @param groups The JSON Object containing the group definitions\n * @param id The value of the `menuItem` property of the group to look up\n * @returns The key of the group that has the `menuItem` property with the value of `id` or\n * `undefined` if no such group exists.\n */\nexport function getSubMenuGroupKeyForMenuItemId(\n groups: Localized,\n id: string,\n): string | undefined {\n return Object.entries(groups).find(\n ([, value]) => 'menuItem' in value && value.menuItem === id,\n )?.[0];\n}\n","import { cn } from '@/utils/shadcn-ui/utils';\n\ntype MenuItemIconProps = {\n /** The icon to display */\n icon: string;\n /** The label of the menu item */\n menuLabel: string;\n /** Whether the icon is leading or trailing */\n leading?: boolean;\n};\n\nfunction MenuItemIcon({ icon, menuLabel, leading }: MenuItemIconProps) {\n return icon ? (\n \n ) : undefined;\n}\n\nexport default MenuItemIcon;\n","import {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '@/components/shadcn-ui/dropdown-menu';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport { MenuIcon } from 'lucide-react';\nimport {\n GroupsInMultiColumnMenu,\n Localized,\n MenuItemContainingCommand,\n MenuItemContainingSubmenu,\n MultiColumnMenu,\n} from 'platform-bible-utils';\nimport { Fragment, ReactNode } from 'react';\nimport { Button } from '@/components/shadcn-ui/button';\nimport { Z_INDEX_ABOVE_DOCK } from '@/components/z-index';\nimport { getSubMenuGroupKeyForMenuItemId } from './menu.util';\nimport { SelectMenuItemHandler } from './platform-menubar.component';\nimport MenuItemIcon from './menu-icon.component';\n\nconst getGroupContent = (\n groups: Localized,\n items: Localized<(MenuItemContainingCommand | MenuItemContainingSubmenu)[]>,\n columnOrSubMenuKey: string | undefined,\n onSelectMenuItem: SelectMenuItemHandler,\n) => {\n if (!columnOrSubMenuKey) return undefined;\n\n const sortedGroupsForColumn = Object.entries(groups)\n .filter(\n ([key, group]) =>\n ('column' in group && group.column === columnOrSubMenuKey) || key === columnOrSubMenuKey,\n )\n .sort(([, a], [, b]) => a.order - b.order);\n\n return sortedGroupsForColumn.flatMap(([groupKey]) => {\n const groupItems = items\n .filter((item) => item.group === groupKey)\n .sort((a, b) => a.order - b.order)\n .map((item: Localized) => {\n return (\n \n \n {'command' in item ? (\n {\n // Since the item has a command, we know it is a MenuItemContainingCommand.\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n onSelectMenuItem(item as MenuItemContainingCommand);\n }}\n >\n {item.iconPathBefore && (\n \n )}\n {item.label}\n {item.iconPathAfter && (\n \n )}\n \n ) : (\n \n {item.label}\n\n \n \n {getGroupContent(\n groups,\n items,\n getSubMenuGroupKeyForMenuItemId(groups, item.id),\n onSelectMenuItem,\n )}\n \n \n \n )}\n \n {item.tooltip && {item.tooltip}}\n \n );\n });\n\n return groupItems;\n });\n};\n\nexport type TabDropdownMenuProps = {\n /** The handler to use for menu commands */\n onSelectMenuItem: SelectMenuItemHandler;\n\n /** The menu data to show on the dropdown menu */\n menuData: Localized;\n\n /** Defines a string value that labels the current element */\n tabLabel: string;\n\n /** Optional icon for the dropdown menu trigger. Defaults to hamburger icon. */\n icon?: ReactNode;\n\n /** Additional css class(es) to help with unique styling of the tab dropdown menu */\n className?: string;\n\n /** Style variant for the app menubar component. */\n variant?: 'default' | 'muted';\n\n buttonVariant?: 'default' | 'ghost' | 'outline' | 'secondary';\n\n /** Optional unique identifier */\n id?: string;\n};\n\n/**\n * Dropdown menu designed to be used with Platform.Bible menu data. Column headers are ignored.\n * Column data is separated by a horizontal divider, so groups are not distinguishable. Tooltips are\n * displayed on hovering over menu items, if a tooltip is defined for them.\n *\n * A child component can be passed in to show as an icon on the menu trigger button.\n */\nexport default function TabDropdownMenu({\n onSelectMenuItem,\n menuData,\n tabLabel,\n icon,\n className,\n variant,\n buttonVariant = 'ghost',\n id,\n}: TabDropdownMenuProps) {\n return (\n \n \n \n \n \n {Object.entries(menuData.columns)\n .filter(([, column]) => typeof column === 'object')\n .sort(([, a], [, b]) => {\n if (typeof a === 'boolean' || typeof b === 'boolean') return 0;\n return a.order - b.order;\n })\n .map(([columnKey], index, array) => (\n \n \n \n {getGroupContent(menuData.groups, menuData.items, columnKey, onSelectMenuItem)}\n \n \n\n {index < array.length - 1 && }\n \n ))}\n \n \n );\n}\n","import { Localized, MultiColumnMenu } from 'platform-bible-utils';\nimport React, { PropsWithChildren, ReactNode } from 'react';\nimport { SelectMenuItemHandler } from '../menus/platform-menubar.component';\n\nexport type TabToolbarCommonProps = {\n /**\n * The handler to use for toolbar item commands related to the project menu. Here is a basic\n * example of how to create this:\n *\n * @example\n *\n * ```tsx\n * const projectMenuCommandHandler: SelectMenuItemHandler = async (selectedMenuItem) => {\n * const commandName = selectedMenuItem.command;\n * try {\n * // Assert the more specific type. Assert the more specific type. The menu data should\n * // specify a valid command name here. If not, the error will be caught.\n * // eslint-disable-next-line no-type-assertion/no-type-assertion\n * await papi.commands.sendCommand(commandName as CommandNames);\n * } catch (e) {\n * throw new Error(\n * `handleMenuCommand error: command: ${commandName}. ${JSON.stringify(e)}`,\n * );\n * }\n * };\n * ```\n */\n onSelectProjectMenuItem: SelectMenuItemHandler;\n\n /**\n * Menu data that is used to populate the Menubar component for the project menu. In an extension,\n * the menu data comes from menus.json in the contributions folder. To access that info, use\n * useMemo to get the WebViewMenu.\n */\n projectMenuData?: Localized;\n\n /** Optional unique identifier */\n id?: string;\n\n /** Additional css classes to help with unique styling of the extensible toolbar */\n className?: string;\n\n /** Icon that will be displayed on the Menu Button. Defaults to the hamburger menu icon. */\n menuButtonIcon?: ReactNode;\n};\n\nexport type TabToolbarContainerProps = PropsWithChildren<{\n /** Optional unique identifier */\n id?: string;\n /** Additional css classes to help with unique styling of the extensible toolbar */\n className?: string;\n}>;\n\n/** Wrapper that allows consistent styling for both TabToolbar and TabFloatingMenu. */\nexport const TabToolbarContainer = React.forwardRef(\n ({ id, className, children }, ref) => (\n \n {children}\n \n ),\n);\n\nexport default TabToolbarContainer;\n","import { ReactNode } from 'react';\nimport { Localized, MultiColumnMenu } from 'platform-bible-utils';\nimport { Menu, EllipsisVertical } from 'lucide-react';\nimport TabDropdownMenu from '../menus/tab-dropdown-menu.component';\nimport { SelectMenuItemHandler } from '../menus/platform-menubar.component';\nimport { TabToolbarCommonProps, TabToolbarContainer } from './tab-toolbar-container.component';\n\nexport type TabToolbarProps = TabToolbarCommonProps & {\n /**\n * The handler to use for toolbar item commands related to the tab view menu. Here is a basic\n * example of how to create this from the hello-rock3 extension:\n *\n * @example\n *\n * ```tsx\n * const projectMenuCommandHandler: SelectMenuItemHandler = async (selectedMenuItem) => {\n * const commandName = selectedMenuItem.command;\n * try {\n * // Assert the more specific type. Assert the more specific type. The menu data should\n * // specify a valid command name here. If not, the error will be caught.\n * // eslint-disable-next-line no-type-assertion/no-type-assertion\n * await papi.commands.sendCommand(commandName as CommandNames);\n * } catch (e) {\n * throw new Error(\n * `handleMenuCommand error: command: ${commandName}. ${JSON.stringify(e)}`,\n * );\n * }\n * };\n * ```\n */\n onSelectViewInfoMenuItem: SelectMenuItemHandler;\n\n /** Menu data that is used to populate the Menubar component for the view info menu */\n tabViewMenuData?: Localized;\n\n /**\n * Toolbar children to be put at the start of the the toolbar after the project menu icon (left\n * side in ltr, right side in rtl). Recommended for inner navigation.\n */\n startAreaChildren?: ReactNode;\n\n /** Toolbar children to be put in the center area of the the toolbar. Recommended for tools. */\n centerAreaChildren?: ReactNode;\n\n /**\n * Toolbar children to be put at the end of the the toolbar before the tab view menu icon (right\n * side in ltr, left side in rtl). Recommended for secondary tools and view options.\n */\n endAreaChildren?: ReactNode;\n};\n\n/**\n * Toolbar that holds the project menu icon on one side followed by three different areas/categories\n * for toolbar icons followed by an optional view info menu icon. See the Tab Floating Menu Button\n * component for a menu component that takes up less screen real estate yet is always visible.\n */\nexport function TabToolbar({\n onSelectProjectMenuItem,\n onSelectViewInfoMenuItem,\n projectMenuData,\n tabViewMenuData,\n id,\n className,\n startAreaChildren,\n centerAreaChildren,\n endAreaChildren,\n menuButtonIcon,\n}: TabToolbarProps) {\n return (\n \n {projectMenuData && (\n }\n buttonVariant=\"ghost\"\n />\n )}\n {startAreaChildren && (\n
\n {startAreaChildren}\n
\n )}\n {centerAreaChildren && (\n
\n {centerAreaChildren}\n
\n )}\n
\n {tabViewMenuData && (\n }\n className=\"tw:h-full\"\n />\n )}\n {endAreaChildren}\n
\n
\n );\n}\n\nexport default TabToolbar;\n","import TabDropdownMenu from '../menus/tab-dropdown-menu.component';\nimport { TabToolbarCommonProps, TabToolbarContainer } from './tab-toolbar-container.component';\n\n/**\n * Renders a TabDropdownMenu with a trigger button that looks like the menuButtonIcon or like the\n * default of three stacked horizontal lines (aka the hamburger). The menu \"floats\" over the content\n * so it is always visible. When clicked, it displays a dropdown menu with the projectMenuData.\n */\nexport function TabFloatingMenu({\n onSelectProjectMenuItem,\n projectMenuData,\n id,\n className,\n menuButtonIcon,\n}: TabToolbarCommonProps) {\n return (\n \n {projectMenuData && (\n \n )}\n \n );\n}\n\nexport default TabFloatingMenu;\n","// adapted from: https://github.com/shadcn-ui/ui/discussions/752\n\n'use client';\n\nimport { TabsContentProps, TabsListProps, TabsTriggerProps } from '@/components/shadcn-ui/tabs';\nimport { Direction, readDirection } from '@/utils/dir-helper.util';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Tabs as RadixTabs } from 'radix-ui';\nimport React from 'react';\n\nexport type VerticalTabsProps = React.ComponentPropsWithoutRef & {\n className?: string;\n};\n\nexport type LeftTabsTriggerProps = TabsTriggerProps & {\n value: string;\n ref?: React.Ref;\n};\n\n/**\n * Tabs components provide a set of layered sections of content—known as tab panels–that are\n * displayed one at a time. These components are built on Radix UI primitives and styled with Shadcn\n * UI. See Shadcn UI Documentation: https://ui.shadcn.com/docs/components/tabs See Radix UI\n * Documentation: https://www.radix-ui.com/primitives/docs/components/tabs\n */\nexport const VerticalTabs = React.forwardRef<\n React.ElementRef,\n VerticalTabsProps\n>(({ className, ...props }, ref) => {\n const dir: Direction = readDirection();\n return (\n \n );\n});\n\nVerticalTabs.displayName = RadixTabs.List.displayName;\n\n/** @inheritdoc VerticalTabs */\nexport const VerticalTabsList = React.forwardRef<\n React.ElementRef,\n TabsListProps\n>(({ className, ...props }, ref) => (\n \n));\nVerticalTabsList.displayName = RadixTabs.List.displayName;\n\n/** @inheritdoc VerticalTabs */\nexport const VerticalTabsTrigger = React.forwardRef<\n React.ElementRef,\n LeftTabsTriggerProps\n>(({ className, ...props }, ref) => (\n \n));\n\n/** @inheritdoc VerticalTabs */\nexport const VerticalTabsContent = React.forwardRef<\n React.ElementRef,\n TabsContentProps\n>(({ className, ...props }, ref) => (\n \n));\nVerticalTabsContent.displayName = RadixTabs.Content.displayName;\n","import { SearchBar } from '@/components/basics/search-bar.component';\nimport {\n VerticalTabs,\n VerticalTabsContent,\n VerticalTabsList,\n VerticalTabsTrigger,\n} from '@/components/basics/tabs-vertical';\nimport { ReactNode } from 'react';\n\nexport type TabKeyValueContent = {\n key: string;\n value: string;\n content: ReactNode;\n};\n\nexport type TabNavigationContentSearchProps = {\n /** List of values and keys for each tab this component should provide */\n tabList: TabKeyValueContent[];\n\n /** The search query in the search bar */\n searchValue: string;\n\n /** Handler to run when the value of the search bar changes */\n onSearch: (searchQuery: string) => void;\n\n /** Optional placeholder for the search bar */\n searchPlaceholder?: string;\n\n /** Optional title to include in the header */\n headerTitle?: string;\n\n /** Optional className to modify the search input */\n searchClassName?: string;\n\n /** Optional id for the root element */\n id?: string;\n};\n\n/**\n * TabNavigationContentSearch component provides a vertical tab navigation interface with a search\n * bar at the top. This component allows users to filter content within tabs based on a search\n * query.\n *\n * @param {TabNavigationContentSearchProps} props\n * @param {TabKeyValueContent[]} props.tabList - List of objects containing keys, values, and\n * content for each tab to be displayed.\n * @param {string} props.searchValue - The current value of the search input.\n * @param {function} props.onSearch - Callback function called when the search input changes;\n * receives the new search query as an argument.\n * @param {string} [props.searchPlaceholder] - Optional placeholder text for the search input.\n * @param {string} [props.headerTitle] - Optional title to display above the search input.\n * @param {string} [props.searchClassName] - Optional CSS class name to apply custom styles to the\n * search input.\n * @param {string} [props.id] - Optional id for the root element.\n */\nexport function TabNavigationContentSearch({\n tabList,\n searchValue,\n onSearch,\n searchPlaceholder,\n headerTitle,\n searchClassName,\n id,\n}: TabNavigationContentSearchProps) {\n return (\n
\n
\n {headerTitle ?

{headerTitle}

: ''}\n \n
\n \n \n {tabList.map((tab) => (\n \n {tab.value}\n \n ))}\n \n {tabList.map((tab) => (\n \n {tab.content}\n \n ))}\n \n
\n );\n}\n\nexport default TabNavigationContentSearch;\n","import React from 'react';\nimport { Menubar as MenubarPrimitive } from 'radix-ui';\n\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { IconCheck, IconChevronRight } from '@tabler/icons-react';\n// CUSTOM: Import menu context and variants to support variant prop propagation down the menu tree\nimport {\n MenuContext,\n MenuContextProps,\n menuVariants,\n useMenuContext,\n} from '@/context/menu.context';\n\n/**\n * The Menubar component provides a visually persistent menu that is commonly triggered by a menu\n * bar. This component is built on Radix UI primitives and styled with Shadcn UI.\n *\n * @see Shadcn UI Documentation: {@link https://ui.shadcn.com/docs/components/menubar}\n * @see Radix UI Documentation: {@link https://www.radix-ui.com/primitives/docs/components/menubar}\n */\nfunction Menubar({\n className,\n // CUSTOM: Added variant prop to allow callers to apply visual style variants to all menu items\n variant = 'default',\n ...props\n}: React.ComponentProps & {\n // CUSTOM: variant prop that propagates down the menu tree via context\n variant?: MenuContextProps['variant'];\n}) {\n /* #region CUSTOM provide context to propagate variant to all menu children */\n const contextValue = React.useMemo(\n () => ({\n variant,\n }),\n [variant],\n );\n return (\n \n {/* #endregion CUSTOM */}\n \n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarMenu({ ...props }: React.ComponentProps) {\n return ;\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarGroup({ ...props }: React.ComponentProps) {\n return ;\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarPortal({ ...props }: React.ComponentProps) {\n return ;\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarRadioGroup({ ...props }: React.ComponentProps) {\n return ;\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarTrigger({\n className,\n ...props\n}: React.ComponentProps) {\n // CUSTOM: Read menu context to apply variant-driven styles to the trigger\n const context = useMenuContext();\n return (\n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarContent({\n className,\n align = 'start',\n alignOffset = -4,\n sideOffset = 8,\n ...props\n}: React.ComponentProps) {\n // CUSTOM: Read menu context to apply variant-driven styles to the content panel\n const context = useMenuContext();\n return (\n \n \n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n // CUSTOM: Read menu context to apply variant-driven styles to each menu item\n const context = useMenuContext();\n return (\n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarCheckboxItem({\n className,\n children,\n checked,\n inset,\n ...props\n}: React.ComponentProps & {\n inset?: boolean;\n}) {\n // CUSTOM: Read menu context to apply variant-driven styles to each checkbox item\n const context = useMenuContext();\n return (\n \n \n \n \n \n \n {children}\n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarRadioItem({\n className,\n children,\n inset,\n ...props\n}: React.ComponentProps & {\n inset?: boolean;\n}) {\n // CUSTOM: Read menu context to apply variant-driven styles to each radio item\n const context = useMenuContext();\n return (\n \n \n \n \n \n \n {children}\n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps & {\n inset?: boolean;\n}) {\n return (\n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarSeparator({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarSub({ ...props }: React.ComponentProps) {\n return ;\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps & {\n inset?: boolean;\n}) {\n // CUSTOM: Read menu context to apply variant-driven styles to the sub-trigger\n const context = useMenuContext();\n return (\n \n {children}\n \n \n );\n}\n\n/** @inheritdoc Menubar */\nfunction MenubarSubContent({\n className,\n ...props\n}: React.ComponentProps) {\n // CUSTOM: Read menu context to apply variant-driven styles to the sub-content panel\n const context = useMenuContext();\n return (\n \n );\n}\n\nexport {\n Menubar,\n MenubarPortal,\n MenubarMenu,\n MenubarTrigger,\n MenubarContent,\n MenubarGroup,\n MenubarSeparator,\n MenubarLabel,\n MenubarItem,\n MenubarShortcut,\n MenubarCheckboxItem,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSub,\n MenubarSubTrigger,\n MenubarSubContent,\n};\n","import {\n Menubar,\n MenubarContent,\n MenubarItem,\n MenubarMenu,\n MenubarSeparator,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n} from '@/components/shadcn-ui/menubar';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@/components/shadcn-ui/tooltip';\nimport {\n GroupsInMultiColumnMenu,\n Localized,\n MenuItemContainingCommand,\n MenuItemContainingSubmenu,\n MultiColumnMenu,\n} from 'platform-bible-utils';\nimport { RefObject, useEffect, useRef } from 'react';\nimport { useHotkeys } from 'react-hotkeys-hook';\nimport { Z_INDEX_ABOVE_DOCK } from '@/components/z-index';\nimport { getSubMenuGroupKeyForMenuItemId } from './menu.util';\nimport MenuItemIcon from './menu-icon.component';\n\n/**\n * Callback function that is invoked when a user selects a menu item. Receives the full\n * `MenuItemContainingCommand` object as an argument.\n */\nexport interface SelectMenuItemHandler {\n (selectedMenuItem: MenuItemContainingCommand): void;\n}\n\nconst simulateKeyPress = (ref: RefObject, keys: KeyboardEventInit[]) => {\n setTimeout(() => {\n keys.forEach((key) => {\n ref.current?.dispatchEvent(new KeyboardEvent('keydown', key));\n });\n }, 0);\n};\n\nconst getMenubarContent = (\n groups: Localized,\n items: Localized<(MenuItemContainingCommand | MenuItemContainingSubmenu)[]>,\n columnOrSubMenuKey: string | undefined,\n onSelectMenuItem: SelectMenuItemHandler,\n) => {\n if (!columnOrSubMenuKey) return undefined;\n\n const sortedGroupsForColumn = Object.entries(groups)\n .filter(\n ([key, group]) =>\n ('column' in group && group.column === columnOrSubMenuKey) || key === columnOrSubMenuKey,\n )\n .sort(([, a], [, b]) => a.order - b.order);\n\n return sortedGroupsForColumn.flatMap(([groupKey], index) => {\n const groupItems = items\n .filter((item) => item.group === groupKey)\n .sort((a, b) => a.order - b.order)\n .map((item: Localized) => {\n return (\n \n \n {'command' in item ? (\n {\n // Since the item has a command, we know it is a MenuItemContainingCommand.\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n onSelectMenuItem(item as MenuItemContainingCommand);\n }}\n >\n {item.iconPathBefore && (\n \n )}\n {item.label}\n {item.iconPathAfter && (\n \n )}\n \n ) : (\n \n {item.label}\n \n {getMenubarContent(\n groups,\n items,\n getSubMenuGroupKeyForMenuItemId(groups, item.id),\n onSelectMenuItem,\n )}\n \n \n )}\n \n {item.tooltip && {item.tooltip}}\n \n );\n });\n\n const itemsWithSeparator = [...groupItems];\n if (groupItems.length > 0 && index < sortedGroupsForColumn.length - 1) {\n itemsWithSeparator.push();\n }\n\n return itemsWithSeparator;\n });\n};\n\ntype PlatformMenubarProps = {\n /** Menu data that is used to populate the Menubar component. */\n menuData: Localized;\n\n /** The handler to use for menu commands. */\n onSelectMenuItem: SelectMenuItemHandler;\n\n /**\n * Optional callback function that is executed whenever a menu on the Menubar is opened or closed.\n * Helpful for handling updates to the menu, as changing menu data when the menu is opened is not\n * desirable.\n */\n onOpenChange?: (isOpen: boolean) => void;\n\n /** Style variant for the app menubar component. */\n variant?: 'default' | 'muted';\n};\n\n/** Menubar component tailored to work with Platform.Bible menu data */\nexport function PlatformMenubar({\n menuData,\n onSelectMenuItem,\n onOpenChange,\n variant,\n}: PlatformMenubarProps) {\n // These refs will always be defined — using undefined! avoids a null check on every use\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const menubarRef = useRef(undefined!);\n // Ref is always defined before use; the non-null assertion avoids redundant null checks\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const projectMenuRef = useRef(undefined!);\n // Ref is always defined before use; the non-null assertion avoids redundant null checks\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const windowMenuRef = useRef(undefined!);\n // Ref is always defined before use; the non-null assertion avoids redundant null checks\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const layoutMenuRef = useRef(undefined!);\n // Ref is always defined before use; the non-null assertion avoids redundant null checks\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const helpMenuRef = useRef(undefined!);\n\n const getRefForColumn = (columnKey: string) => {\n switch (columnKey) {\n case 'platform.app':\n return projectMenuRef;\n case 'platform.window':\n return windowMenuRef;\n case 'platform.layout':\n return layoutMenuRef;\n case 'platform.help':\n return helpMenuRef;\n default:\n return undefined;\n }\n };\n\n // This is a quick and dirty way to implement some shortcuts by simulating key presses\n useHotkeys(['alt', 'alt+p', 'alt+l', 'alt+n', 'alt+h'], (event, handler) => {\n event.preventDefault();\n\n const escKey: KeyboardEventInit = { key: 'Escape', code: 'Escape', keyCode: 27, bubbles: true };\n const spaceKey: KeyboardEventInit = { key: ' ', code: 'Space', keyCode: 32, bubbles: true };\n\n switch (handler.hotkey) {\n case 'alt':\n simulateKeyPress(projectMenuRef, [escKey]);\n break;\n case 'alt+p':\n projectMenuRef.current?.focus();\n simulateKeyPress(projectMenuRef, [escKey, spaceKey]);\n break;\n case 'alt+l':\n windowMenuRef.current?.focus();\n simulateKeyPress(windowMenuRef, [escKey, spaceKey]);\n break;\n case 'alt+n':\n layoutMenuRef.current?.focus();\n simulateKeyPress(layoutMenuRef, [escKey, spaceKey]);\n break;\n case 'alt+h':\n helpMenuRef.current?.focus();\n simulateKeyPress(helpMenuRef, [escKey, spaceKey]);\n break;\n default:\n break;\n }\n });\n\n useEffect(() => {\n if (!onOpenChange || !menubarRef.current) return;\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (mutation.attributeName === 'data-state' && mutation.target instanceof HTMLElement) {\n const state = mutation.target.getAttribute('data-state');\n\n if (state === 'open') {\n onOpenChange(true);\n } else {\n onOpenChange(false);\n }\n }\n });\n });\n\n const menubarElement = menubarRef.current;\n const dataStateAttributes = menubarElement.querySelectorAll('[data-state]');\n\n dataStateAttributes.forEach((element) => {\n observer.observe(element, { attributes: true });\n });\n\n return () => observer.disconnect();\n }, [onOpenChange]);\n\n if (!menuData) return undefined;\n\n return (\n \n {Object.entries(menuData.columns)\n .filter(([, column]) => typeof column === 'object')\n .sort(([, a], [, b]) => {\n if (typeof a === 'boolean' || typeof b === 'boolean') return 0;\n return a.order - b.order;\n })\n .map(([columnKey, column]) => (\n \n \n {typeof column === 'object' && 'label' in column && column.label}\n \n \n \n {getMenubarContent(menuData.groups, menuData.items, columnKey, onSelectMenuItem)}\n \n \n \n ))}\n \n );\n}\n\nexport default PlatformMenubar;\n","import {\n SelectMenuItemHandler,\n PlatformMenubar,\n} from '@/components/advanced/menus/platform-menubar.component';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Localized, MultiColumnMenu } from 'platform-bible-utils';\nimport { PropsWithChildren, ReactNode, useRef } from 'react';\n\nexport type ToolbarProps = PropsWithChildren<{\n /** The handler to use for menu commands (and eventually toolbar commands). */\n onSelectMenuItem: SelectMenuItemHandler;\n\n /**\n * Menu data that is used to populate the Menubar component. If empty object, no menus will be\n * shown on the App Menubar\n */\n menuData?: Localized;\n\n /**\n * Optional callback function that is executed whenever a menu on the App Menubar is opened or\n * closed. Helpful for handling updates to the menu, as changing menu data when the menu is opened\n * is not desirable.\n */\n onOpenChange?: (isOpen: boolean) => void;\n\n /** Optional unique identifier */\n id?: string;\n\n /** Additional css classes to help with unique styling of the toolbar */\n className?: string;\n\n /**\n * Whether the toolbar should be used as a draggable area for moving the application. This will\n * add an electron specific style `WebkitAppRegion: 'drag'` to the toolbar in order to make it\n * draggable. See:\n * https://www.electronjs.org/docs/latest/tutorial/custom-title-bar#create-a-custom-title-bar\n */\n shouldUseAsAppDragArea?: boolean;\n\n /** Toolbar children to be put at the start of the toolbar (left side in ltr, right side in rtl) */\n appMenuAreaChildren?: ReactNode;\n\n /** Toolbar children to be put at the end of the toolbar (right side in ltr, left side in rtl) */\n configAreaChildren?: ReactNode;\n\n /** Variant of the menubar */\n menubarVariant?: 'default' | 'muted';\n}>;\n\n/**\n * Get tailwind class for reserved space for the window controls / macos \"traffic lights\". Passing\n * 'darwin' will reserve the necessary space for macos traffic lights at the start, otherwise a\n * different amount of space at the end for the window controls.\n *\n * Apply to the toolbar like: `` or ``\n *\n * @param operatingSystem The os platform: 'darwin' (macos) | anything else\n * @returns The class name to apply to the toolbar if os specific space should be reserved\n */\nexport function getToolbarOSReservedSpaceClassName(\n operatingSystem: string | undefined,\n): string | undefined {\n switch (operatingSystem) {\n case undefined:\n return undefined;\n case 'darwin':\n return 'tw:ps-[85px]';\n default:\n return 'tw:pe-[calc(138px+1rem)]';\n }\n}\n\n/**\n * A customizable toolbar component with a menubar, content area, and configure area.\n *\n * This component is designed to be used in the window title bar of an electron application.\n *\n * @param {ToolbarProps} props - The props for the component.\n */\nexport function Toolbar({\n menuData,\n onOpenChange,\n onSelectMenuItem,\n className,\n id,\n children,\n appMenuAreaChildren,\n configAreaChildren,\n shouldUseAsAppDragArea,\n menubarVariant = 'default',\n}: ToolbarProps) {\n // This ref will always be defined\n // eslint-disable-next-line no-type-assertion/no-type-assertion\n const containerRef = useRef(undefined!);\n\n return (\n \n \n {/* App Menu area */}\n
\n \n {appMenuAreaChildren}\n\n {menuData && (\n \n )}\n
\n \n\n {/* Content area */}\n \n {children}\n \n\n {/* Configure area */}\n
\n \n {configAreaChildren}\n
\n \n \n \n );\n}\n\nexport default Toolbar;\n","import { useState } from 'react';\nimport { LocalizedStringValue, formatReplacementString } from 'platform-bible-utils';\nimport { cn } from '@/utils/shadcn-ui/utils';\nimport { Z_INDEX_ABOVE_DOCK } from '@/components/z-index';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../shadcn-ui/select';\nimport { Label } from '../shadcn-ui/label';\n\n/**\n * Immutable array containing all keys used for localization in this component. If you're using this\n * component in an extension, you can pass it into the useLocalizedStrings hook to easily obtain the\n * localized strings and pass them into the localizedStrings prop of this component\n */\nexport const UI_LANGUAGE_SELECTOR_STRING_KEYS = Object.freeze([\n '%settings_uiLanguageSelector_fallbackLanguages%',\n] as const);\n\nexport type UiLanguageSelectorLocalizedStrings = {\n [localizedUiLanguageSelectorKey in (typeof UI_LANGUAGE_SELECTOR_STRING_KEYS)[number]]?: LocalizedStringValue;\n};\n\n/**\n * Gets the localized value for the provided key\n *\n * @param strings Object containing localized string\n * @param key Key for a localized string\n * @returns The localized value for the provided key, if available. Returns the key if no localized\n * value is available\n */\nconst localizeString = (\n strings: UiLanguageSelectorLocalizedStrings,\n key: keyof UiLanguageSelectorLocalizedStrings,\n) => {\n return strings[key] ?? key;\n};\n\nexport type LanguageInfo = {\n /** The name of the language to be displayed (in its native script) */\n autonym: string;\n /**\n * The name of the language in other languages, so that the language can also be displayed in the\n * current UI language, if known.\n */\n uiNames?: Record;\n /**\n * Other known names of the language (for searching). This can include pejorative names and should\n * never be displayed unless typed by the user.\n */\n otherNames?: string[];\n};\n\nexport type UiLanguageSelectorProps = {\n /** Full set of known languages to display. The keys are valid BCP-47 tags. */\n knownUiLanguages: Record;\n /** IETF BCP-47 language tag of the current primary UI language. `undefined` => 'en' */\n primaryLanguage: string;\n /**\n * Ordered list of fallback language tags to use if the localization key can't be found in the\n * current primary UI language. This list never contains English ('en') because it is the ultimate\n * fallback.\n */\n fallbackLanguages: string[] | undefined;\n /**\n * Handler for when either the primary or the fallback languages change (or both). For this\n * handler, the primary UI language is the first one in the array, followed by the fallback\n * languages in order of decreasing preference.\n */\n onLanguagesChange?: (newUiLanguages: string[]) => void;\n /** Handler for the primary language changes. */\n onPrimaryLanguageChange?: (newPrimaryUiLanguage: string) => void;\n /**\n * Handler for when the fallback languages change. The array contains the fallback languages in\n * order of decreasing preference.\n */\n onFallbackLanguagesChange?: (newFallbackLanguages: string[]) => void;\n /**\n * Map whose keys are localized string keys as contained in UI_LANGUAGE_SELECTOR_STRING_KEYS and\n * whose values are the localized strings (in the current UI language).\n */\n localizedStrings: UiLanguageSelectorLocalizedStrings;\n /** Additional css classes to help with unique styling of the control */\n className?: string;\n /** Optional id for the root element */\n id?: string;\n};\n\n/**\n * A component for selecting the user interface language and managing fallback languages. Allows\n * users to choose a primary UI language and optionally select fallback languages.\n *\n * @param {UiLanguageSelectorProps} props - The props for the component.\n */\nexport function UiLanguageSelector({\n knownUiLanguages,\n primaryLanguage = 'en',\n fallbackLanguages = [],\n onLanguagesChange,\n onPrimaryLanguageChange,\n onFallbackLanguagesChange,\n localizedStrings,\n className,\n id,\n}: UiLanguageSelectorProps) {\n const fallbackLanguagesText = localizeString(\n localizedStrings,\n '%settings_uiLanguageSelector_fallbackLanguages%',\n );\n const [isOpen, setIsOpen] = useState(false);\n\n const handleLanguageChange = (code: string) => {\n if (onPrimaryLanguageChange) onPrimaryLanguageChange(code);\n // REVIEW: Should fallback languages be preserved when primary language changes?\n if (onLanguagesChange)\n onLanguagesChange([code, ...fallbackLanguages.filter((lang) => lang !== code)]);\n if (onFallbackLanguagesChange && fallbackLanguages.find((l) => l === code))\n onFallbackLanguagesChange([...fallbackLanguages.filter((lang) => lang !== code)]);\n setIsOpen(false); // Close the dropdown when a selection is made\n };\n\n /**\n * Gets the display name for the given language. This will typically include the autonym (in the\n * native script), along with the name of the language in the current UI locale if known, with a\n * fallback to the English name (if known).\n *\n * @param {string} lang - The BCP-47 code of the language whose display name is being requested.\n * @param {string} uiLang - The BCP-47 code of the current user-interface language used used to\n * try to look up the name of the language in a form that is likely to be helpful to the user if\n * they do not recognize the autonym.\n * @returns {string} The display name of the language.\n */\n const getLanguageDisplayName = (lang: string, uiLang: string) => {\n const altName =\n uiLang !== lang\n ? (knownUiLanguages[lang]?.uiNames?.[uiLang] ?? knownUiLanguages[lang]?.uiNames?.en)\n : undefined;\n\n return altName\n ? `${knownUiLanguages[lang]?.autonym} (${altName})`\n : knownUiLanguages[lang]?.autonym;\n };\n\n return (\n
\n {/* Language Selector */}\n setIsOpen(open)}\n >\n \n \n \n \n {Object.keys(knownUiLanguages).map((key) => {\n return (\n \n {getLanguageDisplayName(key, primaryLanguage)}\n \n );\n })}\n \n \n\n {/* Fallback Language Button */}\n {primaryLanguage !== 'en' && (\n
\n \n
\n )}\n
\n );\n}\n\nexport default UiLanguageSelector;\n","import { Label } from '@/components/shadcn-ui/label';\nimport { ReactNode } from 'react';\n\ntype SmartLabelProps = {\n item: string;\n createLabel?: (item: string) => string;\n createComplexLabel?: (item: string) => ReactNode;\n};\n\n/** Create labels with text, react elements (e.g. links), or text + react elements */\nfunction SmartLabel({ item, createLabel, createComplexLabel }: SmartLabelProps): ReactNode {\n if (createLabel) {\n return ;\n }\n if (createComplexLabel) {\n return ;\n }\n return ;\n}\n\nexport default SmartLabel;\n","import { Checkbox } from '@/components/shadcn-ui/checkbox';\nimport { ReactNode } from 'react';\nimport SmartLabel from './smart-label.component';\n\n/**\n * @deprecated 2026-06-08 Use {@link CheckboxGroupProps} instead. `ChecklistProps` is kept as the\n * existing export for backward compatibility and will be removed in a future release.\n */\nexport type ChecklistProps = {\n /** Optional string representing the id attribute of the Checklist */\n id?: string;\n /** Optional string representing CSS class name(s) for styling */\n className?: string;\n /** Array of strings representing the checkable items */\n listItems: string[];\n /** Array of strings representing the checked items */\n selectedListItems: string[];\n /**\n * Function that is called when a checkbox item is selected or deselected\n *\n * @param item The string description for this item\n * @param selected True if selected, false if not selected\n */\n handleSelectListItem: (item: string, selected: boolean) => void;\n\n /**\n * Optional function creates a label for a provided checkable item\n *\n * @param item The item for which a label is to be created\n * @returns A string representing the label text for the checkbox associated with that item\n */\n createLabel?: (item: string) => string;\n\n /**\n * Optional function creates a label for a provided checkable item\n *\n * @param item The item for which a label is to be created, including text and any additional\n * elements (e.g. links)\n * @returns A react node representing the label text and any additional elements (e.g. links) for\n * the checkbox associated with that item\n */\n createComplexLabel?: (item: string) => ReactNode;\n};\n\n/**\n * Renders a list of checkboxes. Each checkbox corresponds to an item from the `listItems` array.\n *\n * @deprecated 2026-06-08 Use {@link CheckboxGroup} instead. `Checklist` is kept as the existing\n * export for backward compatibility and will be removed in a future release.\n */\nexport function Checklist({\n id,\n className,\n listItems,\n selectedListItems,\n handleSelectListItem,\n createLabel,\n createComplexLabel,\n}: ChecklistProps) {\n return (\n
\n {listItems.map((item) => (\n
\n handleSelectListItem(item, value)}\n />\n \n
\n ))}\n
\n );\n}\n\nexport default Checklist;\n\n/** Renders a list of checkboxes. Each checkbox corresponds to an item from the `listItems` array. */\nexport const CheckboxGroup = Checklist;\n\n/** Props for {@link CheckboxGroup}. */\nexport type CheckboxGroupProps = ChecklistProps;\n","import { cn } from '@/utils/shadcn-ui/utils';\nimport { MoreVertical } from 'lucide-react';\nimport React, { ReactNode } from 'react';\nimport { Button } from '../shadcn-ui/button';\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '../shadcn-ui/dropdown-menu';\n\n/** Props interface for the ResultsCard base component */\nexport interface ResultsCardProps {\n /** Unique key for the card */\n cardKey: string;\n /** Whether this card is currently selected/focused */\n isSelected: boolean;\n /** Callback function called when the card is clicked */\n onSelect: () => void;\n /** Whether the content of this card are in a denied state */\n isDenied?: boolean;\n /** Whether the card should be hidden */\n isHidden?: boolean;\n /** Additional CSS classes to apply to the card */\n className?: string;\n /** Main content to display on the card */\n children: ReactNode;\n /** Additional buttons to show to the end of the card when selected, before the dropdown menu */\n selectedButtons?: ReactNode;\n /** Additional buttons to show when the card is hovered but not selected */\n hoverButtons?: ReactNode;\n /** Content to show in the dropdown menu when selected */\n dropdownContent?: ReactNode;\n /** Whether to show the dropdown menu button on hover even when not selected. Defaults to false */\n showDropdownOnHover?: boolean;\n /** Additional content to show below the main content */\n additionalContent?: ReactNode;\n /** Color to use for the card's accent border */\n accentColor?: string;\n}\n\n/**\n * ResultsCard is a base component for displaying scripture-related results in a card format, even\n * though it is not based on the Card component. It provides common functionality like selection\n * state, dropdown menus, and expandable content.\n */\nexport function ResultsCard({\n cardKey,\n isSelected,\n onSelect,\n isDenied,\n isHidden = false,\n className,\n children,\n selectedButtons,\n hoverButtons,\n dropdownContent,\n additionalContent,\n accentColor,\n showDropdownOnHover = false,\n}: ResultsCardProps) {\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onSelect();\n }\n };\n\n return (\n