@brainfish-ai/components 0.28.7 → 0.28.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,18 @@
1
- import*as e from"react";import t,{useCallback as n,useEffect as r,useRef as a,useState as s,useImperativeHandle as l}from"react";import{u as o,E as i,b as c,R as m}from"../chunks/suggestion-card.D6e8iM9D.js";import '../knowledge-review.css';export{S as SuggestionCard}from"../chunks/suggestion-card.D6e8iM9D.js";import d from"html-react-parser";import{CaretDown as u,CaretUp as f,Lightbulb as g,Backspace as p,CheckCircle as h,HandsClapping as b}from"@phosphor-icons/react";import{Card as E,CardHeader as A,CardTitle as x,CardContent as v}from"../components/ui/card.js";import{ScrollArea as N}from"../components/ui/scroll-area.js";import{Spinner as k}from"../components/ui/spinner.js";import{B as w,a as y}from"../chunks/button.D_2SonNs.js";import{Tooltip as C,TooltipTrigger as j,TooltipContent as R}from"../components/ui/tooltip.js";import{Popover as I,PopoverTrigger as L,PopoverContent as z}from"../components/ui/popover.js";import{DropdownMenu as B,DropdownMenuTrigger as D,DropdownMenuContent as O,DropdownMenuItem as P}from"../components/ui/dropdown-menu.js";import{ButtonGroup as T}from"../components/ui/button-group.js";import{c as F}from"../chunks/utils.C6Qu-kwd.js";import{S as $}from"../chunks/status-badge.BLB0pWDn.js";function _({fetchDiffForItem:e}){const{selectedItem:t,setLoadedDiffDoc:a,setLoadingDiff:s}=o(),l=n(async(t,n)=>{s(!0),a(null);try{const r=await e(t);if(n.aborted)return;a(r)}catch(r){if(n.aborted)return;console.error("Failed to fetch diff:",r),a(null)}finally{n.aborted||s(!1)}},[e,a,s]),i=t?.id;return r(()=>{if(!i)return a(null),void s(!1);const e=new AbortController;return l(i,e.signal),()=>{e.abort()}},[i,l]),null}const q="Why is Brainfish suggesting this?",M=e.forwardRef(function({title:t,isNew:n,suggestionsCount:r,sourceIcon:a,sourceDescription:s,currentArticleIndex:l,totalArticles:o,displayTotalArticles:c,showActionButtons:m=!0,onNextArticle:d,onPreviousArticle:b,onRejectAllSuggestions:E,onAcceptAllSuggestions:A,onAcceptAndPublish:x,breadcrumb:v,onOpenArticleLink:N,onSourceLinkClick:k,suggestionReasonBody:S,className:_,...M},W){const G=e.useRef(null),[K,H]=e.useState(!1),J=o>0&&l<o-1,Q=l>0,U=0===o?0:l+1,V=c??o,X=V>0;let Y;return n?Y=/* @__PURE__ */e.createElement($,{variant:"success"},"New"):r&&(Y=/* @__PURE__ */e.createElement(i,{count:r})),/* @__PURE__ */e.createElement("div",{ref:W,className:F("flex flex-col gap-4",_),...M},/* @__PURE__ */e.createElement("div",{className:"flex justify-between items-center"},/* @__PURE__ */e.createElement("h1",{className:"heading-lg"},t,N&&v&&/* @__PURE__ */e.createElement(w,{variant:"link",size:"sm",onClick:N,"aria-label":"Open article",className:"block px-0 text-subtle text-xs"},v)),/* @__PURE__ */e.createElement("div",{className:"flex items-center"},/* @__PURE__ */e.createElement("p",{className:"text-xs text-foreground"},/* @__PURE__ */e.createElement("span",{"aria-hidden":"true"},X?`${U}/${V}`:"0"),/* @__PURE__ */e.createElement("span",{className:"sr-only","aria-live":"polite"},X?`Article ${U} of ${V}`:"No articles")),/* @__PURE__ */e.createElement(C,null,/* @__PURE__ */e.createElement(j,{asChild:!0},/* @__PURE__ */e.createElement(w,{variant:"ghost",size:"icon",disabled:!J,onClick:d,"aria-label":"Go to next article"},
2
- /* @__PURE__ */e.createElement(u,{"aria-hidden":"true"}))),/* @__PURE__ */e.createElement(R,{side:"bottom",bgColor:"--bfc-foreground",className:"text-background"},"Next Article")),/* @__PURE__ */e.createElement(C,null,/* @__PURE__ */e.createElement(j,{asChild:!0},/* @__PURE__ */e.createElement(w,{variant:"ghost",size:"icon",disabled:!Q,onClick:b,"aria-label":"Go to previous article"},
3
- /* @__PURE__ */e.createElement(f,{"aria-hidden":"true"}))),/* @__PURE__ */e.createElement(R,{side:"top",bgColor:"--bfc-foreground",className:"text-background"},"Previous Article")))),/* @__PURE__ */e.createElement("div",{className:"flex-1 px-2 pb-2 flex justify-between items-center"},/* @__PURE__ */e.createElement("div",{className:"flex items-center gap-2"},Y,s&&(k?/* @__PURE__ */e.createElement(w,{variant:"link",onClick:k,"aria-label":"Open source",className:"[&_svg]:size-4 text-xs text-subtle gap-1"},a&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 flex items-center"},a),
4
- /* @__PURE__ */e.createElement("span",null,s)):/* @__PURE__ */e.createElement("span",{className:"[&_svg]:size-4 flex items-center gap-1 text-xs text-subtle"},a&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 flex items-center"},a),s))),m&&/* @__PURE__ */e.createElement(T,{orientation:"horizontal",rounded:!1,"aria-label":"Suggestion actions",className:"gap-1"},S&&/* @__PURE__ */e.createElement(I,{open:K,onOpenChange:H},/* @__PURE__ */e.createElement(L,{asChild:!0},/* @__PURE__ */e.createElement(w,{variant:"ghost","aria-label":q},/* @__PURE__ */e.createElement(g,{"aria-hidden":"true"}),"Why")),/* @__PURE__ */e.createElement(z,{align:"start",side:"bottom",className:"z-above-modal shadow-md dark:shadow-md-invert border-dark-300"},
5
- /* @__PURE__ */e.createElement("div",{className:"font-bold text-sm"},q),
6
- /* @__PURE__ */e.createElement("div",{className:"text-sm text-subtle mt-1"},S))),/* @__PURE__ */e.createElement(w,{variant:"ghost",onClick:E},/* @__PURE__ */e.createElement(p,{"aria-hidden":"true"}),"Reject"),x?/* @__PURE__ */e.createElement(B,null,/* @__PURE__ */e.createElement("div",{ref:G,className:F("flex items-center rounded border border-border bg-primary",y)},
7
- /* @__PURE__ */e.createElement(w,{variant:"default",elevation:"shadow",className:"gap-1 rounded-none border-0 bg-transparent shadow-none",onClick:A},
8
- /* @__PURE__ */e.createElement(h,{"aria-hidden":"true"}),"Accept as draft"),
9
- /* @__PURE__ */e.createElement("span",{className:"h-full w-px self-stretch bg-foreground","aria-hidden":"true"}),
10
- /* @__PURE__ */e.createElement(D,{asChild:!0},/* @__PURE__ */e.createElement(w,{variant:"default",size:"icon",className:"size-9 rounded-none border-0 bg-transparent shadow-none","aria-label":"More accept options"},
11
- /* @__PURE__ */e.createElement(u,{className:"size-4","aria-hidden":"true"})))),/* @__PURE__ */e.createElement(O,{align:"end",className:"z-above-modal border-none shadow-md dark:shadow-md-invert mt-1"},
12
- /* @__PURE__ */e.createElement(P,{onClick:x},/* @__PURE__ */e.createElement(h,{"aria-hidden":"true"}),"Accept & publish"))):/* @__PURE__ */e.createElement(w,{variant:"default",elevation:"shadow",onClick:A},/* @__PURE__ */e.createElement(h,{"aria-hidden":"true"}),"Accept as draft"))))});function W(e){const t=e.querySelectorAll("del + ins"),n=e.querySelectorAll("ins:not(del + ins)"),r=e.querySelectorAll("del"),a=Array.from(r).filter(e=>"INS"!==e.nextElementSibling?.tagName);return t.length+n.length+a.length}function G({diffTitle:e,items:l,isLoading:i,totalItemsCount:c,showActionButtons:m=!0,children:u,sourceIcon:f,sourceDescription:g}){const{selectedItem:p,setSelectedItem:h,loadedDiffDoc:w,loadingDiff:S,onApproveAllSuggestions:y,onRejectAllSuggestions:C,onAcceptAndPublish:j,onOpenArticleLink:R,onSourceLinkClick:I,breadcrumb:L,suggestionReasonBody:z}=o(),B=l.length>0,D=i??!B,O=D&&!B,P=!D&&!B,T=S?"":d(w?.diffTitle??e??""),F=S?/* @__PURE__ */t.createElement("div",{className:"text-muted-foreground"},"Loading diff…"):w?.diffContent,$=S?0:(_=w?.diffTitle??e)&&"undefined"!=typeof DOMParser?W((new DOMParser).parseFromString(_,"text/html")):0;var _;const q=a(null),[G,K]=s(0);r(()=>{if(S||!w)return void K(0);const e=q.current;if(!e)return;const t=requestAnimationFrame(()=>{var t;K((t=e)?W(t):0)});return()=>cancelAnimationFrame(t)},[S,w]);const H=$+G,J=l.length,Q=c??J,U=p?Math.max(0,l.findIndex(e=>e.id===p.id)):0,V=n(()=>{U<J-1&&h(l[U+1]??null)},[U,l,h,J]),X=n(()=>{U>0&&h(l[U-1]??null)},[U,l,h]),Y=p?.icon??f,Z=p?.description??g;/* @__PURE__ */
13
- return t.createElement(E,{className:"py-6 pl-4","data-name":"knowledge-reviews"},/* @__PURE__ */t.createElement(N,{className:"h-[calc(var(--knowledge-review-scroll-height)-50px)] pr-8"},/* @__PURE__ */t.createElement(A,{className:"p-0"},B&&/* @__PURE__ */t.createElement(x,{className:"border-b border-dark-300 mb-6 pb-2 font-normal"},/* @__PURE__ */t.createElement(M,{title:T,isNew:w?.isNew??!1,suggestionsCount:H,sourceIcon:Y,sourceDescription:Z,currentArticleIndex:U,totalArticles:J,displayTotalArticles:Q,showActionButtons:m,onNextArticle:V,onPreviousArticle:X,onRejectAllSuggestions:C,onAcceptAllSuggestions:y,onAcceptAndPublish:j,onOpenArticleLink:R,onSourceLinkClick:I,breadcrumb:L,suggestionReasonBody:z}))),/* @__PURE__ */t.createElement(v,{className:"p-0 [&_ol]:!pl-16 [&_ul]:!pl-16"},/* @__PURE__ */t.createElement("div",{"aria-hidden":"true",className:"sr-only",hidden:!0},u),O?/* @__PURE__ */t.createElement("div",{className:"flex flex-col items-center justify-center gap-4 text-center h-[50dvh] text-muted-foreground"},/* @__PURE__ */t.createElement(k,{className:"size-8"}),/* @__PURE__ */t.createElement("p",{className:"text-base font-medium"},"Loading suggestions...")):P?/* @__PURE__ */t.createElement("div",{className:"flex flex-col items-center justify-center gap-4 text-center h-[50dvh]"},/* @__PURE__ */t.createElement(b,{className:"text-muted-foreground",size:32,weight:"fill"}),/* @__PURE__ */t.createElement("p",{className:"text-base font-medium text-foreground"},"All up to date. Well done, mate.")):/* @__PURE__ */t.createElement("div",{ref:q,className:"pl-12"},F))))}const K="--knowledge-review-scroll-height",H=t.forwardRef(function({diffTitle:e="Knowledge Review",children:n,items:s,isLoading:i,totalItemsCount:c,showActionButtons:d=!0,className:u,onApproveAllSuggestions:f,onRejectAllSuggestions:g,onOpenArticleLink:p,onAcceptAndPublish:h,onSourceLinkClick:b,breadcrumb:A,sourceIcon:x,sourceDescription:w,suggestionReasonBody:S,...y},C){const j=a(null),{selectedItem:R,setSelectedItem:I}=o();l(C,()=>({selectedItem:R,setSelectedItem:I}),[R,I]),r(()=>{const e=j.current;if(!e)return;const t=()=>{const{height:t}=e.getBoundingClientRect();e.style.setProperty(K,`${t}px`)};if(t(),"function"!=typeof ResizeObserver)return;const n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[]);const L=i??0===s.length,z=L&&0===s.length;/* @__PURE__ */
14
- return t.createElement(E,{className:F("h-full",u)},/* @__PURE__ */t.createElement(v,{className:"p-4 lg:p-8 h-full"},/* @__PURE__ */t.createElement("div",{ref:j,className:"grid xs:max-lg:grid-cols-1 lg:grid-cols-[1fr_4fr] gap-6 min-h-96 h-full",style:{[K]:"100px"},...y},
15
- /* @__PURE__ */t.createElement(N,{className:"h-[calc(var(--knowledge-review-scroll-height))] min-w-80 lg:block hidden"},z?/* @__PURE__ */t.createElement("div",{className:"flex h-full min-h-96 items-center justify-center text-muted-foreground"},/* @__PURE__ */t.createElement(k,{className:"size-6"})):/* @__PURE__ */t.createElement(m,{items:s})),
16
- /* @__PURE__ */t.createElement(G,{diffTitle:e,items:s,isLoading:L,totalItemsCount:c,showActionButtons:d,sourceIcon:x,sourceDescription:w},n))))}),J=t.forwardRef(function(e,n){const{items:r,onApproveAllSuggestions:a,onRejectAllSuggestions:s,onAcceptAndPublish:l,onOpenArticleLink:o,onSourceLinkClick:i,breadcrumb:m,suggestionReasonBody:d}=e;/* @__PURE__ */
17
- return t.createElement(c,{defaultSelectedItem:r.find(e=>e.isSelected)??null,onApproveAllSuggestions:a,onRejectAllSuggestions:s,onAcceptAndPublish:l,onOpenArticleLink:o,onSourceLinkClick:i,breadcrumb:m,suggestionReasonBody:d},
18
- /* @__PURE__ */t.createElement(H,{...e,ref:n}))});export{_ as KnowledgeReviewDiffLoader,G as KnowledgeReviewPanel,J as KnowledgeReviewScene,c as ReviewsSelectionProvider,o as useReviewsSelection};
1
+ import*as e from"react";import t,{useCallback as n,useEffect as l,useRef as r,useState as a,useImperativeHandle as s}from"react";import{u as o,E as c,b as i,R as m}from"../chunks/suggestion-card.DAwWcW7V.js";import '../knowledge-review.css';export{S as SuggestionCard}from"../chunks/suggestion-card.DAwWcW7V.js";import d from"html-react-parser";import{CaretDown as u,CaretUp as p,Lightbulb as f,Backspace as g,CheckCircle as h,Globe as A,LockKey as b,HandsClapping as E}from"@phosphor-icons/react";import{Card as x,CardHeader as N,CardTitle as v,CardContent as k}from"../components/ui/card.js";import{ScrollArea as w}from"../components/ui/scroll-area.js";import{Spinner as y}from"../components/ui/spinner.js";import{B as C,a as I}from"../chunks/button.D_2SonNs.js";import{Tooltip as j,TooltipTrigger as P,TooltipContent as R}from"../components/ui/tooltip.js";import{Popover as L,PopoverTrigger as z,PopoverContent as B}from"../components/ui/popover.js";import{DropdownMenu as D,DropdownMenuTrigger as O,DropdownMenuContent as T,DropdownMenuItem as F}from"../components/ui/dropdown-menu.js";import{ButtonGroup as $}from"../components/ui/button-group.js";import{c as _}from"../chunks/utils.C6Qu-kwd.js";import{S as q}from"../chunks/status-badge.BLB0pWDn.js";function M({fetchDiffForItem:e}){const{selectedItem:t,setLoadedDiffDoc:r,setLoadingDiff:a}=o(),s=n(async(t,n)=>{a(!0),r(null);try{const l=await e(t);if(n.aborted)return;r(l)}catch(l){if(n.aborted)return;console.error("Failed to fetch diff:",l),r(null)}finally{n.aborted||a(!1)}},[e,r,a]),c=t?.id;return l(()=>{if(!c)return r(null),void a(!1);const e=new AbortController;return s(c,e.signal),()=>{e.abort()}},[c,s]),null}function W({title:t,breadcrumb:n,onOpenArticleLink:l,currentArticleIndex:r,totalArticles:a,displayTotalArticles:s,onNextArticle:o,onPreviousArticle:c}){const i=a>0&&r<a-1,m=r>0,d=0===a?0:r+1,f=s??a,g=f>0;/* @__PURE__ */
2
+ return e.createElement("div",{className:"flex justify-between items-center"},/* @__PURE__ */e.createElement("h1",{className:"heading-lg"},t,l&&n&&/* @__PURE__ */e.createElement(C,{variant:"link",size:"sm",onClick:l,"aria-label":"Open article",className:"block px-0 text-subtle text-xs"},n)),/* @__PURE__ */e.createElement("div",{className:"flex items-center"},/* @__PURE__ */e.createElement("p",{className:"text-xs text-foreground pr-2"},/* @__PURE__ */e.createElement("span",{"aria-hidden":"true"},g?`${d}/${f}`:"0"),/* @__PURE__ */e.createElement("span",{className:"sr-only","aria-live":"polite"},g?`Article ${d} of ${f}`:"No articles")),/* @__PURE__ */e.createElement(j,null,/* @__PURE__ */e.createElement(P,{asChild:!0},/* @__PURE__ */e.createElement(C,{variant:"ghost",size:"icon",disabled:!i,onClick:o,"aria-label":"Go to next article"},
3
+ /* @__PURE__ */e.createElement(u,{"aria-hidden":"true"}))),/* @__PURE__ */e.createElement(R,{side:"bottom",bgColor:"--bfc-foreground",className:"text-background"},"Next Article")),/* @__PURE__ */e.createElement(j,null,/* @__PURE__ */e.createElement(P,{asChild:!0},/* @__PURE__ */e.createElement(C,{variant:"ghost",size:"icon",disabled:!m,onClick:c,"aria-label":"Go to previous article"},
4
+ /* @__PURE__ */e.createElement(p,{"aria-hidden":"true"}))),/* @__PURE__ */e.createElement(R,{side:"top",bgColor:"--bfc-foreground",className:"text-background"},"Previous Article"))))}function G({isNew:t,suggestionsCount:n,sourceIcon:l,sourceDescription:r,onSourceLinkClick:a,showActionButtons:s=!0,suggestionReasonBody:o,hideAcceptAndPublishPublic:i=!1,onAcceptAndPublish:m,onRejectAll:d,onAcceptAll:p,onAcceptAndPublishAction:E}){const[x,N]=e.useState(!1);let v;return t?v=/* @__PURE__ */e.createElement(q,{variant:"success"},"New"):n&&(v=/* @__PURE__ */e.createElement(c,{count:n})),/* @__PURE__ */e.createElement("div",{className:"flex-1 px-2 pb-2 flex justify-between items-center"},/* @__PURE__ */e.createElement("div",{className:"flex items-center gap-2"},v,r&&(a?/* @__PURE__ */e.createElement(C,{variant:"link",onClick:a,"aria-label":"Open source",className:"[&_svg]:size-4 text-xs text-subtle gap-1"},l&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 flex items-center"},l),
5
+ /* @__PURE__ */e.createElement("span",null,r)):/* @__PURE__ */e.createElement("span",{className:"[&_svg]:size-4 flex items-center gap-1 text-xs text-subtle"},l&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 flex items-center"},l),r))),s&&/* @__PURE__ */e.createElement($,{orientation:"horizontal",rounded:!1,"aria-label":"Suggestion actions",className:"gap-1"},o&&/* @__PURE__ */e.createElement(L,{open:x,onOpenChange:N},/* @__PURE__ */e.createElement(z,{asChild:!0},/* @__PURE__ */e.createElement(C,{variant:"ghost","aria-label":K},/* @__PURE__ */e.createElement(f,{"aria-hidden":"true"}),"Why")),/* @__PURE__ */e.createElement(B,{align:"start",side:"bottom",className:"z-above-modal shadow-md dark:shadow-md-invert border-dark-300"},
6
+ /* @__PURE__ */e.createElement("div",{className:"font-bold text-sm"},K),
7
+ /* @__PURE__ */e.createElement("div",{className:"text-sm text-subtle mt-1"},o))),/* @__PURE__ */e.createElement(C,{variant:"ghost",onClick:()=>{d()}},/* @__PURE__ */e.createElement(g,{"aria-hidden":"true"}),t?"Reject":"Reject all"),m?/* @__PURE__ */e.createElement(D,null,/* @__PURE__ */e.createElement("div",{className:_("flex items-center rounded border border-border bg-primary",I)},/* @__PURE__ */e.createElement(C,{variant:"default",elevation:"shadow",className:"gap-1 rounded-none border-0 bg-transparent shadow-none",onClick:()=>{p()}},
8
+ /* @__PURE__ */e.createElement(h,{"aria-hidden":"true"}),t?"Accept as draft":"Accept all as draft"),/* @__PURE__ */e.createElement("span",{className:"h-full w-px self-stretch bg-foreground","aria-hidden":"true"}),/* @__PURE__ */e.createElement(O,{asChild:!0},/* @__PURE__ */e.createElement(C,{variant:"default",size:"icon",className:"size-9 rounded-none border-0 bg-transparent shadow-none","aria-label":"More accept options"},
9
+ /* @__PURE__ */e.createElement(u,{className:"size-4","aria-hidden":"true"})))),/* @__PURE__ */e.createElement(T,{align:"end",className:"z-above-modal border-none shadow-md dark:shadow-md-invert mt-1 "},!i&&/* @__PURE__ */e.createElement(F,{className:"p-3",onClick:()=>{E("public")}},/* @__PURE__ */e.createElement(A,{"aria-hidden":"true"}),t?"Accept & publish publicly":"Accept all & publish publicly"),
10
+ /* @__PURE__ */e.createElement(F,{className:"p-3",onClick:()=>{E("internal")}},/* @__PURE__ */e.createElement(b,{"aria-hidden":"true"}),t?"Accept & publish internally":"Accept all & publish internally"))):/* @__PURE__ */e.createElement(C,{variant:"default",elevation:"shadow",onClick:()=>{p()}},/* @__PURE__ */e.createElement(h,{"aria-hidden":"true"}),t?"Accept as draft":"Accept all as draft")))}const K="Why is Brainfish suggesting this?",H=e.forwardRef(function({title:t,isNew:n,suggestionsCount:l,sourceIcon:r,sourceDescription:a,currentArticleIndex:s,totalArticles:c,displayTotalArticles:i,showActionButtons:m=!0,onNextArticle:d,onPreviousArticle:u,className:p,...f},g){const{onApproveAllSuggestions:h,onRejectAllSuggestions:A,onAcceptAndPublish:b,onApplyAllInEditor:E,onRejectAllInEditor:x,onOpenArticleLink:N,onSourceLinkClick:v,breadcrumb:k,suggestionReasonBody:w,hideAcceptAndPublishPublic:y=!1}=o(),C=e.useCallback(async()=>{x&&await x(),A()},[x,A]),I=e.useCallback(async()=>{E&&await E(),h()},[E,h]),S=e.useCallback(async e=>{b&&(E&&await E(),b(e))},[E,b]);/* @__PURE__ */
11
+ return e.createElement("div",{ref:g,className:_("flex flex-col gap-4",p),...f},/* @__PURE__ */e.createElement(W,{title:t,breadcrumb:k,onOpenArticleLink:N,currentArticleIndex:s,totalArticles:c,displayTotalArticles:i,onNextArticle:d,onPreviousArticle:u}),/* @__PURE__ */e.createElement(G,{isNew:n,suggestionsCount:l,sourceIcon:r,sourceDescription:a,onSourceLinkClick:v,showActionButtons:m,suggestionReasonBody:w,hideAcceptAndPublishPublic:y,onAcceptAndPublish:b,onRejectAll:C,onAcceptAll:I,onAcceptAndPublishAction:S}))});function J(e){const t=e.querySelectorAll("del + ins"),n=e.querySelectorAll("ins:not(del + ins)"),l=e.querySelectorAll("del"),r=Array.from(l).filter(e=>"INS"!==e.nextElementSibling?.tagName);return t.length+n.length+r.length}function Q({diffTitle:e,items:s,isLoading:c,totalItemsCount:i,showActionButtons:m=!0,children:u,sourceIcon:p,sourceDescription:f}){const{selectedItem:g,setSelectedItem:h,loadedDiffDoc:A,loadingDiff:b}=o(),C=s.length>0,I=c??!C,S=I&&!C,j=!I&&!C,P=b?"":d(A?.diffTitle??e??""),R=b?/* @__PURE__ */t.createElement("div",{className:"text-muted-foreground"},"Loading diff…"):A?.diffContent,L=b?0:(z=A?.diffTitle??e)&&"undefined"!=typeof DOMParser?J((new DOMParser).parseFromString(z,"text/html")):0;var z;const B=r(null),[D,O]=a(0);l(()=>{if(b||!A)return void O(0);const e=B.current;if(!e)return;const t=requestAnimationFrame(()=>{var t;O((t=e)?J(t):0)});return()=>cancelAnimationFrame(t)},[b,A]);const T=L+D,F=s.length,$=i??F,_=g?Math.max(0,s.findIndex(e=>e.id===g.id)):0,q=n(()=>{_<F-1&&h(s[_+1]??null)},[_,s,h,F]),M=n(()=>{_>0&&h(s[_-1]??null)},[_,s,h]),W=g?.icon??p,G=g?.description??f;/* @__PURE__ */
12
+ return t.createElement(x,{className:"py-6 pl-4","data-name":"knowledge-reviews"},/* @__PURE__ */t.createElement(w,{className:"h-[calc(var(--knowledge-review-scroll-height)-50px)] pr-8"},/* @__PURE__ */t.createElement(N,{className:"p-0"},C&&/* @__PURE__ */t.createElement(v,{className:"border-b border-dark-300 mb-6 pb-2 font-normal"},/* @__PURE__ */t.createElement(H,{title:P,isNew:A?.isNew??!1,suggestionsCount:T,sourceIcon:W,sourceDescription:G,currentArticleIndex:_,totalArticles:F,displayTotalArticles:$,showActionButtons:m,onNextArticle:q,onPreviousArticle:M}))),/* @__PURE__ */t.createElement(k,{className:"p-0 [&_ol]:!pl-16 [&_ul]:!pl-16"},/* @__PURE__ */t.createElement("div",{"aria-hidden":"true",className:"sr-only",hidden:!0},u),S?/* @__PURE__ */t.createElement("div",{className:"flex flex-col items-center justify-center gap-4 text-center h-[50dvh] text-muted-foreground"},/* @__PURE__ */t.createElement(y,{className:"size-8"}),/* @__PURE__ */t.createElement("p",{className:"text-base font-medium"},"Loading suggestions...")):j?/* @__PURE__ */t.createElement("div",{className:"flex flex-col items-center justify-center gap-4 text-center h-[50dvh]"},/* @__PURE__ */t.createElement(E,{className:"text-muted-foreground",size:32,weight:"fill"}),/* @__PURE__ */t.createElement("p",{className:"text-base font-medium text-foreground"},"All up to date. Well done, mate.")):/* @__PURE__ */t.createElement("div",{ref:B,className:"pl-12"},R))))}const U="--knowledge-review-scroll-height",V=t.forwardRef(function({diffTitle:e="Knowledge Review",children:n,items:a,isLoading:c,totalItemsCount:i,showActionButtons:d=!0,className:u,onApproveAllSuggestions:p,onRejectAllSuggestions:f,onOpenArticleLink:g,onAcceptAndPublish:h,onApplyAllInEditor:A,onRejectAllInEditor:b,onSourceLinkClick:E,breadcrumb:N,sourceIcon:v,sourceDescription:C,suggestionReasonBody:I,hideAcceptAndPublishPublic:S,...j},P){const R=r(null),{selectedItem:L,setSelectedItem:z}=o();s(P,()=>({selectedItem:L,setSelectedItem:z}),[L,z]),l(()=>{const e=R.current;if(!e)return;const t=()=>{const{height:t}=e.getBoundingClientRect();e.style.setProperty(U,`${t}px`)};if(t(),"function"!=typeof ResizeObserver)return;const n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[]);const B=c??0===a.length,D=B&&0===a.length;/* @__PURE__ */
13
+ return t.createElement(x,{className:_("h-full",u)},/* @__PURE__ */t.createElement(k,{className:"p-4 lg:p-8 h-full"},/* @__PURE__ */t.createElement("div",{ref:R,className:"grid xs:max-lg:grid-cols-1 lg:grid-cols-[1fr_4fr] gap-6 min-h-96 h-full",style:{[U]:"100px"},...j},
14
+ /* @__PURE__ */t.createElement(w,{className:"h-[calc(var(--knowledge-review-scroll-height))] min-w-80 lg:block hidden"},D?/* @__PURE__ */t.createElement("div",{className:"flex h-full min-h-96 items-center justify-center text-muted-foreground"},/* @__PURE__ */t.createElement(y,{className:"size-6"})):/* @__PURE__ */t.createElement(m,{items:a})),
15
+ /* @__PURE__ */t.createElement(Q,{diffTitle:e,items:a,isLoading:B,totalItemsCount:i,showActionButtons:d,sourceIcon:v,sourceDescription:C},n))))}),X=t.forwardRef(function(e,n){const{items:l,onApproveAllSuggestions:r,onRejectAllSuggestions:a,onAcceptAndPublish:s,onApplyAllInEditor:o,onRejectAllInEditor:c,onOpenArticleLink:m,onSourceLinkClick:d,breadcrumb:u,suggestionReasonBody:p,hideAcceptAndPublishPublic:f}=e;/* @__PURE__ */
16
+ return t.createElement(i,{defaultSelectedItem:l.find(e=>e.isSelected)??null,onApproveAllSuggestions:r,onRejectAllSuggestions:a,onAcceptAndPublish:s,onApplyAllInEditor:o,onRejectAllInEditor:c,onOpenArticleLink:m,onSourceLinkClick:d,breadcrumb:u,suggestionReasonBody:p,hideAcceptAndPublishPublic:f},
17
+ /* @__PURE__ */t.createElement(V,{...e,ref:n}))});export{M as KnowledgeReviewDiffLoader,Q as KnowledgeReviewPanel,X as KnowledgeReviewScene,i as ReviewsSelectionProvider,o as useReviewsSelection};
19
18
  //# sourceMappingURL=knowledge-review.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"knowledge-review.js","sources":["../../../src/scenes/knowledge-review/diff-loader.tsx","../../../src/scenes/knowledge-review/suggestions-header/suggestions-header.tsx","../../../src/lib/countSuggestions.ts","../../../src/scenes/knowledge-review/knowledge-review-panel.tsx","../../../src/scenes/knowledge-review/scene.tsx"],"sourcesContent":["import { useCallback, useEffect } from 'react';\n\nimport type { LoadedDiffDoc } from './context';\nimport { useReviewsSelection } from './context';\n\nexport type KnowledgeReviewDiffLoaderProps = {\n /** Called when selectedItem changes. Return diff payload or null. */\n fetchDiffForItem: (itemId: string) => Promise<LoadedDiffDoc | null>;\n};\n\n/**\n * Listens to selectedItem from context and fetches diff via the provided callback.\n * Owns loading state and context updates; host (Storybook or Platform) supplies fetch logic.\n */\nexport function KnowledgeReviewDiffLoader({ fetchDiffForItem }: KnowledgeReviewDiffLoaderProps) {\n const { selectedItem, setLoadedDiffDoc, setLoadingDiff } = useReviewsSelection();\n\n const loadDiffForItem = useCallback(\n async (itemId: string, signal: AbortSignal) => {\n setLoadingDiff(true);\n setLoadedDiffDoc(null);\n\n try {\n const doc = await fetchDiffForItem(itemId);\n if (signal.aborted) return;\n setLoadedDiffDoc(doc);\n } catch (error) {\n if (signal.aborted) return;\n console.error('Failed to fetch diff:', error);\n setLoadedDiffDoc(null);\n } finally {\n if (!signal.aborted) {\n setLoadingDiff(false);\n }\n }\n },\n [fetchDiffForItem, setLoadedDiffDoc, setLoadingDiff],\n );\n\n const selectedId = selectedItem?.id;\n\n useEffect(() => {\n if (!selectedId) {\n setLoadedDiffDoc(null);\n setLoadingDiff(false);\n\n return;\n }\n\n const abortController = new AbortController();\n void loadDiffForItem(selectedId, abortController.signal);\n\n return () => {\n abortController.abort();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedId, loadDiffForItem]);\n\n return null;\n}\n","import { CaretDown, CaretUp, Backspace, CheckCircle, Lightbulb } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nimport { EditCount } from '../review-list/edit-count';\n\nimport { Button } from '@/components/ui/button';\nimport { brandShadowEffect } from '@/lib/styles';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { ButtonGroup } from '@/components/ui/button-group';\nimport { cn } from '@/lib/utils';\nimport { StatusBadge } from '@/components/convos/status-badge';\n\nexport interface SuggestionsHeaderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n title: React.ReactNode;\n isNew: boolean;\n suggestionsCount: number;\n sourceIcon: React.ReactNode;\n sourceDescription: string | null;\n currentArticleIndex: number;\n totalArticles: number;\n displayTotalArticles?: number;\n showActionButtons?: boolean;\n onNextArticle: () => void;\n onPreviousArticle: () => void;\n onRejectAllSuggestions: () => void;\n onAcceptAllSuggestions: () => void;\n onAcceptAndPublish?: () => void;\n breadcrumb?: string;\n onOpenArticleLink?: () => void;\n onSourceLinkClick?: () => void;\n suggestionReasonBody?: string;\n}\n\nexport const REASON_TITLE = 'Why is Brainfish suggesting this?';\n\nexport const SuggestionsHeader = React.forwardRef<HTMLDivElement, SuggestionsHeaderProps>(function SuggestionsHeader(\n {\n title,\n isNew,\n suggestionsCount,\n sourceIcon,\n sourceDescription,\n currentArticleIndex,\n totalArticles,\n displayTotalArticles,\n showActionButtons = true,\n onNextArticle,\n onPreviousArticle,\n onRejectAllSuggestions,\n onAcceptAllSuggestions,\n onAcceptAndPublish,\n breadcrumb,\n onOpenArticleLink,\n onSourceLinkClick,\n suggestionReasonBody,\n className,\n ...props\n },\n ref,\n) {\n const splitButtonRef = React.useRef<HTMLDivElement>(null);\n const [whyOpen, setWhyOpen] = React.useState(false);\n const hasNextArticle = totalArticles > 0 && currentArticleIndex < totalArticles - 1;\n const hasPreviousArticle = currentArticleIndex > 0;\n const currentArticle = totalArticles === 0 ? 0 : currentArticleIndex + 1;\n const totalArticlesForDisplay = displayTotalArticles ?? totalArticles;\n const hasDisplayArticles = totalArticlesForDisplay > 0;\n\n let status: React.ReactNode | undefined;\n if (isNew) {\n status = <StatusBadge variant=\"success\">New</StatusBadge>;\n } else if (suggestionsCount) {\n status = <EditCount count={suggestionsCount} />;\n }\n\n return (\n <div ref={ref} className={cn('flex flex-col gap-4', className)} {...props}>\n {/* Header + Navigation */}\n <div className=\"flex justify-between items-center\">\n <h1 className=\"heading-lg\">\n {title}\n {/* Breadcrumbs */}\n {onOpenArticleLink && breadcrumb && (\n <Button\n variant=\"link\"\n size=\"sm\"\n onClick={onOpenArticleLink}\n aria-label=\"Open article\"\n className=\"block px-0 text-subtle text-xs\"\n >\n {breadcrumb}\n </Button>\n )}\n </h1>\n {/* up/down carets */}\n <div className=\"flex items-center\">\n <p className=\"text-xs text-foreground\">\n <span aria-hidden=\"true\">{hasDisplayArticles ? `${currentArticle}/${totalArticlesForDisplay}` : '0'}</span>\n <span className=\"sr-only\" aria-live=\"polite\">\n {hasDisplayArticles ? `Article ${currentArticle} of ${totalArticlesForDisplay}` : 'No articles'}\n </span>\n </p>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n disabled={!hasNextArticle}\n onClick={onNextArticle}\n aria-label=\"Go to next article\"\n >\n <CaretDown aria-hidden=\"true\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" bgColor=\"--bfc-foreground\" className=\"text-background\">\n Next Article\n </TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n disabled={!hasPreviousArticle}\n onClick={onPreviousArticle}\n aria-label=\"Go to previous article\"\n >\n <CaretUp aria-hidden=\"true\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" bgColor=\"--bfc-foreground\" className=\"text-background\">\n Previous Article\n </TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n {/* Status, Source + Actions */}\n <div className=\"flex-1 px-2 pb-2 flex justify-between items-center\">\n <div className=\"flex items-center gap-2\">\n {status}\n {sourceDescription &&\n (onSourceLinkClick ? (\n <Button\n variant=\"link\"\n onClick={onSourceLinkClick}\n aria-label=\"Open source\"\n className=\"[&_svg]:size-4 text-xs text-subtle gap-1\"\n >\n {sourceIcon && <span className=\"shrink-0 flex items-center\">{sourceIcon}</span>}\n <span>{sourceDescription}</span>\n </Button>\n ) : (\n <span className=\"[&_svg]:size-4 flex items-center gap-1 text-xs text-subtle\">\n {sourceIcon && <span className=\"shrink-0 flex items-center\">{sourceIcon}</span>}\n {sourceDescription}\n </span>\n ))}\n </div>\n {showActionButtons && (\n <ButtonGroup orientation=\"horizontal\" rounded={false} aria-label=\"Suggestion actions\" className=\"gap-1\">\n {suggestionReasonBody && (\n <Popover open={whyOpen} onOpenChange={setWhyOpen}>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" aria-label={REASON_TITLE}>\n <Lightbulb aria-hidden=\"true\" />\n Why\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n side=\"bottom\"\n className=\"z-above-modal shadow-md dark:shadow-md-invert border-dark-300\"\n >\n <div className=\"font-bold text-sm\">{REASON_TITLE}</div>\n <div className=\"text-sm text-subtle mt-1\">{suggestionReasonBody}</div>\n </PopoverContent>\n </Popover>\n )}\n <Button variant=\"ghost\" onClick={onRejectAllSuggestions}>\n <Backspace aria-hidden=\"true\" />\n Reject\n </Button>\n {onAcceptAndPublish ? (\n <DropdownMenu>\n <div\n ref={splitButtonRef}\n className={cn('flex items-center rounded border border-border bg-primary', brandShadowEffect)}\n >\n <Button\n variant=\"default\"\n elevation=\"shadow\"\n className=\"gap-1 rounded-none border-0 bg-transparent shadow-none\"\n onClick={onAcceptAllSuggestions}\n >\n <CheckCircle aria-hidden=\"true\" />\n Accept as draft\n </Button>\n <span className=\"h-full w-px self-stretch bg-foreground\" aria-hidden=\"true\" />\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"default\"\n size=\"icon\"\n className=\"size-9 rounded-none border-0 bg-transparent shadow-none\"\n aria-label=\"More accept options\"\n >\n <CaretDown className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n </div>\n <DropdownMenuContent\n align=\"end\"\n className=\"z-above-modal border-none shadow-md dark:shadow-md-invert mt-1\"\n >\n <DropdownMenuItem onClick={onAcceptAndPublish}>\n <CheckCircle aria-hidden=\"true\" />\n Accept & publish\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n <Button variant=\"default\" elevation=\"shadow\" onClick={onAcceptAllSuggestions}>\n <CheckCircle aria-hidden=\"true\" />\n Accept as draft\n </Button>\n )}\n </ButtonGroup>\n )}\n </div>\n </div>\n );\n});\n","function countSuggestionsInRoot(root: Document | Element): number {\n const adjacentPairs = root.querySelectorAll('del + ins');\n const standaloneIns = root.querySelectorAll('ins:not(del + ins)');\n const allDel = root.querySelectorAll('del');\n const standaloneDel = Array.from(allDel).filter((del) => del.nextElementSibling?.tagName !== 'INS');\n\n return adjacentPairs.length + standaloneIns.length + standaloneDel.length;\n}\n\n/** Count suggestions in an HTML string (for title or raw HTML content). */\nexport const countSuggestions = (htmlString: string) => {\n if (!htmlString || typeof DOMParser === 'undefined') {\n return 0;\n }\n const parser = new DOMParser();\n const doc = parser.parseFromString(htmlString, 'text/html');\n\n return countSuggestionsInRoot(doc);\n};\n\n/** Count suggestions inside a DOM element (for rendered ReactNode body content). */\nexport const countSuggestionsInElement = (element: Element | null) => {\n if (!element) return 0;\n\n return countSuggestionsInRoot(element);\n};\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport parse from 'html-react-parser';\nimport { HandsClapping } from '@phosphor-icons/react';\n\nimport { useReviewsSelection } from './context';\nimport { SuggestionsHeader } from './suggestions-header';\nimport type { ReviewListItemProps } from './review-list';\n\nimport { countSuggestions, countSuggestionsInElement } from '@/lib/countSuggestions';\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { Spinner } from '@/components/ui/spinner';\n\nexport type KnowledgeReviewPanelProps = {\n diffTitle: string;\n items: ReviewListItemProps[];\n isLoading?: boolean;\n totalItemsCount?: number;\n showActionButtons?: boolean;\n children?: React.ReactNode;\n sourceIcon: React.ReactNode;\n sourceDescription: string | null;\n};\n\n/**\n * Panel that shows the selected diff (title + content), suggestion count, and article nav.\n * Must be used inside ReviewsSelectionProvider. Expects --knowledge-review-scroll-height\n * to be set by a parent for ScrollArea height.\n */\nexport function KnowledgeReviewPanel({\n diffTitle,\n items,\n isLoading,\n totalItemsCount,\n showActionButtons = true,\n children,\n sourceIcon,\n sourceDescription,\n}: KnowledgeReviewPanelProps) {\n const {\n selectedItem,\n setSelectedItem,\n loadedDiffDoc,\n loadingDiff,\n onApproveAllSuggestions,\n onRejectAllSuggestions,\n onAcceptAndPublish,\n onOpenArticleLink,\n onSourceLinkClick,\n breadcrumb,\n suggestionReasonBody,\n } = useReviewsSelection();\n\n const hasItems = items.length > 0;\n const resolvedIsLoading = isLoading ?? !hasItems;\n const isLoadingState = resolvedIsLoading && !hasItems;\n const isEmptyState = !resolvedIsLoading && !hasItems;\n\n const title = loadingDiff ? '' : parse(loadedDiffDoc?.diffTitle ?? diffTitle ?? '');\n const body = loadingDiff ? <div className=\"text-muted-foreground\">Loading diff…</div> : loadedDiffDoc?.diffContent;\n\n const titleSuggestionsCount = loadingDiff ? 0 : countSuggestions(loadedDiffDoc?.diffTitle ?? diffTitle);\n\n const bodyRef = useRef<HTMLDivElement>(null);\n const [bodySuggestionsCount, setBodySuggestionsCount] = useState(0);\n useEffect(() => {\n if (loadingDiff || !loadedDiffDoc) {\n setBodySuggestionsCount(0);\n\n return;\n }\n const el = bodyRef.current;\n if (!el) return;\n const id = requestAnimationFrame(() => {\n setBodySuggestionsCount(countSuggestionsInElement(el));\n });\n\n return () => cancelAnimationFrame(id);\n }, [loadingDiff, loadedDiffDoc]);\n\n const suggestionsCount = titleSuggestionsCount + bodySuggestionsCount;\n\n const totalArticles = items.length;\n const totalArticlesForDisplay = totalItemsCount ?? totalArticles;\n const currentArticleIndex = selectedItem\n ? Math.max(\n 0,\n items.findIndex((i) => i.id === selectedItem.id),\n )\n : 0;\n\n const onNextArticle = useCallback(() => {\n if (currentArticleIndex < totalArticles - 1) {\n setSelectedItem(items[currentArticleIndex + 1] ?? null);\n }\n }, [currentArticleIndex, items, setSelectedItem, totalArticles]);\n\n const onPreviousArticle = useCallback(() => {\n if (currentArticleIndex > 0) {\n setSelectedItem(items[currentArticleIndex - 1] ?? null);\n }\n }, [currentArticleIndex, items, setSelectedItem]);\n\n const headerSourceIcon = selectedItem?.icon ?? sourceIcon;\n const headerSourceDescription = selectedItem?.description ?? sourceDescription;\n\n return (\n <Card className=\"py-6 pl-4\" data-name=\"knowledge-reviews\">\n <ScrollArea className=\"h-[calc(var(--knowledge-review-scroll-height)-50px)] pr-8\">\n <CardHeader className=\"p-0\">\n {hasItems && (\n <CardTitle className=\"border-b border-dark-300 mb-6 pb-2 font-normal\">\n <SuggestionsHeader\n title={title}\n isNew={loadedDiffDoc?.isNew ?? false}\n suggestionsCount={suggestionsCount}\n sourceIcon={headerSourceIcon}\n sourceDescription={headerSourceDescription}\n currentArticleIndex={currentArticleIndex}\n totalArticles={totalArticles}\n displayTotalArticles={totalArticlesForDisplay}\n showActionButtons={showActionButtons}\n onNextArticle={onNextArticle}\n onPreviousArticle={onPreviousArticle}\n onRejectAllSuggestions={onRejectAllSuggestions}\n onAcceptAllSuggestions={onApproveAllSuggestions}\n onAcceptAndPublish={onAcceptAndPublish}\n onOpenArticleLink={onOpenArticleLink}\n onSourceLinkClick={onSourceLinkClick}\n breadcrumb={breadcrumb}\n suggestionReasonBody={suggestionReasonBody}\n />\n </CardTitle>\n )}\n </CardHeader>\n <CardContent className=\"p-0 [&_ol]:!pl-16 [&_ul]:!pl-16\">\n {/* Mount point for children (e.g. KnowledgeReviewDiffLoader). Kept in DOM so its effects run; hidden because it has no UI. */}\n <div aria-hidden=\"true\" className=\"sr-only\" hidden>\n {children}\n </div>\n {isLoadingState ? (\n <div className=\"flex flex-col items-center justify-center gap-4 text-center h-[50dvh] text-muted-foreground\">\n <Spinner className=\"size-8\" />\n <p className=\"text-base font-medium\">Loading suggestions...</p>\n </div>\n ) : isEmptyState ? (\n <div className=\"flex flex-col items-center justify-center gap-4 text-center h-[50dvh]\">\n <HandsClapping className=\"text-muted-foreground\" size={32} weight=\"fill\" />\n <p className=\"text-base font-medium text-foreground\">All up to date. Well done, mate.</p>\n </div>\n ) : (\n <div ref={bodyRef} className=\"pl-12\">\n {body}\n </div>\n )}\n </CardContent>\n </ScrollArea>\n </Card>\n );\n}\n","import React, { useEffect, useImperativeHandle, useRef } from 'react';\n\nimport { useReviewsSelection } from './context';\nimport { ReviewList, ReviewListItemProps, ReviewsSelectionProvider } from './review-list';\nimport { KnowledgeReviewPanel } from './knowledge-review-panel';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { Spinner } from '@/components/ui/spinner';\nimport { cn } from '@/lib/utils';\n\nimport './knowledge-review.css';\n\nconst SCROLL_HEIGHT_VAR = '--knowledge-review-scroll-height';\n\nexport type KnowledgeReviewSceneHandle = {\n selectedItem: ReviewListItemProps | null;\n setSelectedItem: (item: ReviewListItemProps | null) => void;\n};\n\nexport type KnowledgeReviewSceneProps = {\n diffTitle?: string;\n children: React.ReactNode;\n items: ReviewListItemProps[];\n isLoading?: boolean;\n /** Total number of review list items available (can exceed currently loaded `items.length`). */\n totalItemsCount?: number;\n /** Controls visibility of the Reject / Accept action buttons in the review header. */\n showActionButtons?: boolean;\n className?: string;\n onApproveAllSuggestions: () => void;\n onRejectAllSuggestions: () => void;\n onAcceptAndPublish?: () => void;\n onOpenArticleLink?: () => void;\n onSourceLinkClick?: () => void;\n breadcrumb?: string;\n sourceIcon: React.ReactNode;\n sourceDescription: string | null;\n suggestionReasonBody?: string;\n};\n\nconst KnowledgeReviewSceneInner = React.forwardRef<KnowledgeReviewSceneHandle, KnowledgeReviewSceneProps>(\n function KnowledgeReviewSceneInner(\n {\n diffTitle = 'Knowledge Review',\n children,\n items,\n isLoading,\n totalItemsCount,\n showActionButtons = true,\n className,\n onApproveAllSuggestions,\n onRejectAllSuggestions,\n onOpenArticleLink,\n onAcceptAndPublish,\n onSourceLinkClick,\n breadcrumb,\n sourceIcon,\n sourceDescription,\n suggestionReasonBody,\n ...props\n },\n ref,\n ) {\n const innerRef = useRef<HTMLDivElement>(null);\n const { selectedItem, setSelectedItem } = useReviewsSelection();\n\n useImperativeHandle(\n ref,\n () => ({\n selectedItem,\n setSelectedItem,\n }),\n [selectedItem, setSelectedItem],\n );\n\n useEffect(() => {\n const cardEl = innerRef.current;\n if (!cardEl) return;\n\n const updateHeight = () => {\n const { height } = cardEl.getBoundingClientRect();\n cardEl.style.setProperty(SCROLL_HEIGHT_VAR, `${height}px`);\n };\n\n updateHeight();\n\n if (typeof ResizeObserver !== 'function') {\n return;\n }\n\n const observer = new ResizeObserver(updateHeight);\n observer.observe(cardEl);\n\n return () => observer.disconnect();\n }, []);\n\n const resolvedIsLoading = isLoading ?? items.length === 0;\n const isLoadingItems = resolvedIsLoading && items.length === 0;\n\n return (\n <Card className={cn('h-full', className)}>\n <CardContent className=\"p-4 lg:p-8 h-full\">\n <div\n ref={innerRef}\n className=\"grid xs:max-lg:grid-cols-1 lg:grid-cols-[1fr_4fr] gap-6 min-h-96 h-full\"\n style={{ [SCROLL_HEIGHT_VAR]: '100px' } as React.CSSProperties}\n {...props}\n >\n <ScrollArea className=\"h-[calc(var(--knowledge-review-scroll-height))] min-w-80 lg:block hidden\">\n {isLoadingItems ? (\n <div className=\"flex h-full min-h-96 items-center justify-center text-muted-foreground\">\n <Spinner className=\"size-6\" />\n </div>\n ) : (\n <ReviewList items={items} />\n )}\n </ScrollArea>\n <KnowledgeReviewPanel\n diffTitle={diffTitle}\n items={items}\n isLoading={resolvedIsLoading}\n totalItemsCount={totalItemsCount}\n showActionButtons={showActionButtons}\n sourceIcon={sourceIcon}\n sourceDescription={sourceDescription}\n >\n {children}\n </KnowledgeReviewPanel>\n </div>\n </CardContent>\n </Card>\n );\n },\n);\n\nexport const KnowledgeReviewScene = React.forwardRef<KnowledgeReviewSceneHandle, KnowledgeReviewSceneProps>(\n function KnowledgeReviewScene(props, ref) {\n const {\n items,\n onApproveAllSuggestions,\n onRejectAllSuggestions,\n onAcceptAndPublish,\n onOpenArticleLink,\n onSourceLinkClick,\n breadcrumb,\n suggestionReasonBody,\n } = props;\n\n return (\n <ReviewsSelectionProvider\n defaultSelectedItem={items.find((m) => m.isSelected) ?? null}\n onApproveAllSuggestions={onApproveAllSuggestions}\n onRejectAllSuggestions={onRejectAllSuggestions}\n onAcceptAndPublish={onAcceptAndPublish}\n onOpenArticleLink={onOpenArticleLink}\n onSourceLinkClick={onSourceLinkClick}\n breadcrumb={breadcrumb}\n suggestionReasonBody={suggestionReasonBody}\n >\n <KnowledgeReviewSceneInner {...props} ref={ref} />\n </ReviewsSelectionProvider>\n );\n },\n);\n"],"names":["KnowledgeReviewDiffLoader","fetchDiffForItem","selectedItem","setLoadedDiffDoc","setLoadingDiff","useReviewsSelection","loadDiffForItem","useCallback","async","itemId","signal","doc","aborted","error","console","selectedId","id","useEffect","abortController","AbortController","abort","REASON_TITLE","SuggestionsHeader","React","forwardRef","title","isNew","suggestionsCount","sourceIcon","sourceDescription","currentArticleIndex","totalArticles","displayTotalArticles","showActionButtons","onNextArticle","onPreviousArticle","onRejectAllSuggestions","onAcceptAllSuggestions","onAcceptAndPublish","breadcrumb","onOpenArticleLink","onSourceLinkClick","suggestionReasonBody","className","props","ref","splitButtonRef","useRef","whyOpen","setWhyOpen","useState","hasNextArticle","hasPreviousArticle","currentArticle","totalArticlesForDisplay","hasDisplayArticles","status","createElement","StatusBadge","variant","EditCount","count","cn","Button","size","onClick","Tooltip","TooltipTrigger","asChild","disabled","CaretDown","TooltipContent","side","bgColor","CaretUp","ButtonGroup","orientation","rounded","Popover","open","onOpenChange","PopoverTrigger","Lightbulb","PopoverContent","align","Backspace","DropdownMenu","brandShadowEffect","elevation","CheckCircle","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuItem","countSuggestionsInRoot","root","adjacentPairs","querySelectorAll","standaloneIns","allDel","standaloneDel","Array","from","filter","del","nextElementSibling","tagName","length","KnowledgeReviewPanel","diffTitle","items","isLoading","totalItemsCount","children","setSelectedItem","loadedDiffDoc","loadingDiff","onApproveAllSuggestions","hasItems","resolvedIsLoading","isLoadingState","isEmptyState","parse","body","diffContent","titleSuggestionsCount","htmlString","DOMParser","parseFromString","bodyRef","bodySuggestionsCount","setBodySuggestionsCount","el","current","requestAnimationFrame","element","cancelAnimationFrame","Math","max","findIndex","i","headerSourceIcon","icon","headerSourceDescription","description","Card","ScrollArea","CardHeader","CardTitle","CardContent","hidden","Spinner","HandsClapping","weight","SCROLL_HEIGHT_VAR","KnowledgeReviewSceneInner","innerRef","useImperativeHandle","cardEl","updateHeight","height","getBoundingClientRect","style","setProperty","ResizeObserver","observer","observe","disconnect","isLoadingItems","ReviewList","KnowledgeReviewScene","ReviewsSelectionProvider","defaultSelectedItem","find","m","isSelected"],"mappings":"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"}
1
+ {"version":3,"file":"knowledge-review.js","sources":["../../../src/scenes/knowledge-review/diff-loader.tsx","../../../src/scenes/knowledge-review/suggestions-header/suggestions-header-title-nav.tsx","../../../src/scenes/knowledge-review/suggestions-header/suggestions-header-toolbar.tsx","../../../src/scenes/knowledge-review/suggestions-header/suggestions-header.tsx","../../../src/lib/countSuggestions.ts","../../../src/scenes/knowledge-review/knowledge-review-panel.tsx","../../../src/scenes/knowledge-review/scene.tsx"],"sourcesContent":["import { useCallback, useEffect } from 'react';\n\nimport type { LoadedDiffDoc } from './context';\nimport { useReviewsSelection } from './context';\n\nexport type KnowledgeReviewDiffLoaderProps = {\n /** Called when selectedItem changes. Return diff payload or null. */\n fetchDiffForItem: (itemId: string) => Promise<LoadedDiffDoc | null>;\n};\n\n/**\n * Listens to selectedItem from context and fetches diff via the provided callback.\n * Owns loading state and context updates; host (Storybook or Platform) supplies fetch logic.\n */\nexport function KnowledgeReviewDiffLoader({ fetchDiffForItem }: KnowledgeReviewDiffLoaderProps) {\n const { selectedItem, setLoadedDiffDoc, setLoadingDiff } = useReviewsSelection();\n\n const loadDiffForItem = useCallback(\n async (itemId: string, signal: AbortSignal) => {\n setLoadingDiff(true);\n setLoadedDiffDoc(null);\n\n try {\n const doc = await fetchDiffForItem(itemId);\n if (signal.aborted) return;\n setLoadedDiffDoc(doc);\n } catch (error) {\n if (signal.aborted) return;\n console.error('Failed to fetch diff:', error);\n setLoadedDiffDoc(null);\n } finally {\n if (!signal.aborted) {\n setLoadingDiff(false);\n }\n }\n },\n [fetchDiffForItem, setLoadedDiffDoc, setLoadingDiff],\n );\n\n const selectedId = selectedItem?.id;\n\n useEffect(() => {\n if (!selectedId) {\n setLoadedDiffDoc(null);\n setLoadingDiff(false);\n\n return;\n }\n\n const abortController = new AbortController();\n void loadDiffForItem(selectedId, abortController.signal);\n\n return () => {\n abortController.abort();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedId, loadDiffForItem]);\n\n return null;\n}\n","import { CaretDown, CaretUp } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\n\nexport interface SuggestionsHeaderTitleNavProps {\n title: React.ReactNode;\n breadcrumb?: string;\n onOpenArticleLink?: () => void;\n currentArticleIndex: number;\n totalArticles: number;\n displayTotalArticles?: number;\n onNextArticle: () => void;\n onPreviousArticle: () => void;\n}\n\nexport function SuggestionsHeaderTitleNav({\n title,\n breadcrumb,\n onOpenArticleLink,\n currentArticleIndex,\n totalArticles,\n displayTotalArticles,\n onNextArticle,\n onPreviousArticle,\n}: SuggestionsHeaderTitleNavProps) {\n const hasNextArticle = totalArticles > 0 && currentArticleIndex < totalArticles - 1;\n const hasPreviousArticle = currentArticleIndex > 0;\n const currentArticle = totalArticles === 0 ? 0 : currentArticleIndex + 1;\n const totalArticlesForDisplay = displayTotalArticles ?? totalArticles;\n const hasDisplayArticles = totalArticlesForDisplay > 0;\n\n return (\n <div className=\"flex justify-between items-center\">\n <h1 className=\"heading-lg\">\n {title}\n {onOpenArticleLink && breadcrumb && (\n <Button\n variant=\"link\"\n size=\"sm\"\n onClick={onOpenArticleLink}\n aria-label=\"Open article\"\n className=\"block px-0 text-subtle text-xs\"\n >\n {breadcrumb}\n </Button>\n )}\n </h1>\n <div className=\"flex items-center\">\n <p className=\"text-xs text-foreground pr-2\">\n <span aria-hidden=\"true\">{hasDisplayArticles ? `${currentArticle}/${totalArticlesForDisplay}` : '0'}</span>\n <span className=\"sr-only\" aria-live=\"polite\">\n {hasDisplayArticles ? `Article ${currentArticle} of ${totalArticlesForDisplay}` : 'No articles'}\n </span>\n </p>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n disabled={!hasNextArticle}\n onClick={onNextArticle}\n aria-label=\"Go to next article\"\n >\n <CaretDown aria-hidden=\"true\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" bgColor=\"--bfc-foreground\" className=\"text-background\">\n Next Article\n </TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n disabled={!hasPreviousArticle}\n onClick={onPreviousArticle}\n aria-label=\"Go to previous article\"\n >\n <CaretUp aria-hidden=\"true\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" bgColor=\"--bfc-foreground\" className=\"text-background\">\n Previous Article\n </TooltipContent>\n </Tooltip>\n </div>\n </div>\n );\n}\n","import { CaretDown, Backspace, CheckCircle, Lightbulb, Globe, LockKey } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nimport type { AcceptAndPublishVisibility } from '../context';\nimport { REASON_TITLE } from '../suggestions-header';\nimport { EditCount } from '../review-list/edit-count';\n\nimport { Button } from '@/components/ui/button';\nimport { brandShadowEffect } from '@/lib/styles';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { ButtonGroup } from '@/components/ui/button-group';\nimport { cn } from '@/lib/utils';\nimport { StatusBadge } from '@/components/convos/status-badge';\n\nexport interface SuggestionsHeaderToolbarProps {\n isNew: boolean;\n suggestionsCount: number;\n sourceIcon: React.ReactNode;\n sourceDescription: string | null;\n onSourceLinkClick?: () => void;\n showActionButtons?: boolean;\n suggestionReasonBody?: string;\n hideAcceptAndPublishPublic?: boolean;\n onAcceptAndPublish?: (visibility: AcceptAndPublishVisibility) => void;\n onRejectAll: () => void | Promise<void>;\n onAcceptAll: () => void | Promise<void>;\n onAcceptAndPublishAction: (visibility: AcceptAndPublishVisibility) => void | Promise<void>;\n}\n\nexport function SuggestionsHeaderToolbar({\n isNew,\n suggestionsCount,\n sourceIcon,\n sourceDescription,\n onSourceLinkClick,\n showActionButtons = true,\n suggestionReasonBody,\n hideAcceptAndPublishPublic = false,\n onAcceptAndPublish,\n onRejectAll,\n onAcceptAll,\n onAcceptAndPublishAction,\n}: SuggestionsHeaderToolbarProps) {\n const [whyOpen, setWhyOpen] = React.useState(false);\n\n let status: React.ReactNode | undefined;\n if (isNew) {\n status = <StatusBadge variant=\"success\">New</StatusBadge>;\n } else if (suggestionsCount) {\n status = <EditCount count={suggestionsCount} />;\n }\n\n return (\n <div className=\"flex-1 px-2 pb-2 flex justify-between items-center\">\n <div className=\"flex items-center gap-2\">\n {status}\n {sourceDescription &&\n (onSourceLinkClick ? (\n <Button\n variant=\"link\"\n onClick={onSourceLinkClick}\n aria-label=\"Open source\"\n className=\"[&_svg]:size-4 text-xs text-subtle gap-1\"\n >\n {sourceIcon && <span className=\"shrink-0 flex items-center\">{sourceIcon}</span>}\n <span>{sourceDescription}</span>\n </Button>\n ) : (\n <span className=\"[&_svg]:size-4 flex items-center gap-1 text-xs text-subtle\">\n {sourceIcon && <span className=\"shrink-0 flex items-center\">{sourceIcon}</span>}\n {sourceDescription}\n </span>\n ))}\n </div>\n {showActionButtons && (\n <ButtonGroup orientation=\"horizontal\" rounded={false} aria-label=\"Suggestion actions\" className=\"gap-1\">\n {suggestionReasonBody && (\n <Popover open={whyOpen} onOpenChange={setWhyOpen}>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" aria-label={REASON_TITLE}>\n <Lightbulb aria-hidden=\"true\" />\n Why\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n side=\"bottom\"\n className=\"z-above-modal shadow-md dark:shadow-md-invert border-dark-300\"\n >\n <div className=\"font-bold text-sm\">{REASON_TITLE}</div>\n <div className=\"text-sm text-subtle mt-1\">{suggestionReasonBody}</div>\n </PopoverContent>\n </Popover>\n )}\n <Button variant=\"ghost\" onClick={() => void onRejectAll()}>\n <Backspace aria-hidden=\"true\" />\n {isNew ? 'Reject' : 'Reject all'}\n </Button>\n {onAcceptAndPublish ? (\n <DropdownMenu>\n <div className={cn('flex items-center rounded border border-border bg-primary', brandShadowEffect)}>\n <Button\n variant=\"default\"\n elevation=\"shadow\"\n className=\"gap-1 rounded-none border-0 bg-transparent shadow-none\"\n onClick={() => void onAcceptAll()}\n >\n <CheckCircle aria-hidden=\"true\" />\n {isNew ? 'Accept as draft' : 'Accept all as draft'}\n </Button>\n <span className=\"h-full w-px self-stretch bg-foreground\" aria-hidden=\"true\" />\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"default\"\n size=\"icon\"\n className=\"size-9 rounded-none border-0 bg-transparent shadow-none\"\n aria-label=\"More accept options\"\n >\n <CaretDown className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n </div>\n <DropdownMenuContent\n align=\"end\"\n className=\"z-above-modal border-none shadow-md dark:shadow-md-invert mt-1 \"\n >\n {!hideAcceptAndPublishPublic && (\n <DropdownMenuItem className=\"p-3\" onClick={() => void onAcceptAndPublishAction('public')}>\n <Globe aria-hidden=\"true\" />\n {isNew ? 'Accept & publish publicly' : 'Accept all & publish publicly'}\n </DropdownMenuItem>\n )}\n <DropdownMenuItem className=\"p-3\" onClick={() => void onAcceptAndPublishAction('internal')}>\n <LockKey aria-hidden=\"true\" />\n {isNew ? 'Accept & publish internally' : 'Accept all & publish internally'}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n <Button variant=\"default\" elevation=\"shadow\" onClick={() => void onAcceptAll()}>\n <CheckCircle aria-hidden=\"true\" />\n {isNew ? 'Accept as draft' : 'Accept all as draft'}\n </Button>\n )}\n </ButtonGroup>\n )}\n </div>\n );\n}\n","import * as React from 'react';\n\nimport { useReviewsSelection } from '../context';\nimport type { AcceptAndPublishVisibility } from '../context';\nimport { SuggestionsHeaderTitleNav } from './suggestions-header-title-nav';\nimport { SuggestionsHeaderToolbar } from './suggestions-header-toolbar';\n\nimport { cn } from '@/lib/utils';\n\nexport interface SuggestionsHeaderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n title: React.ReactNode;\n isNew: boolean;\n suggestionsCount: number;\n sourceIcon: React.ReactNode;\n sourceDescription: string | null;\n currentArticleIndex: number;\n totalArticles: number;\n displayTotalArticles?: number;\n showActionButtons?: boolean;\n onNextArticle: () => void;\n onPreviousArticle: () => void;\n}\n\nexport const REASON_TITLE = 'Why is Brainfish suggesting this?';\n\nexport const SuggestionsHeader = React.forwardRef<HTMLDivElement, SuggestionsHeaderProps>(function SuggestionsHeader(\n {\n title,\n isNew,\n suggestionsCount,\n sourceIcon,\n sourceDescription,\n currentArticleIndex,\n totalArticles,\n displayTotalArticles,\n showActionButtons = true,\n onNextArticle,\n onPreviousArticle,\n className,\n ...props\n },\n ref,\n) {\n const {\n onApproveAllSuggestions,\n onRejectAllSuggestions,\n onAcceptAndPublish,\n onApplyAllInEditor,\n onRejectAllInEditor,\n onOpenArticleLink,\n onSourceLinkClick,\n breadcrumb,\n suggestionReasonBody,\n hideAcceptAndPublishPublic = false,\n } = useReviewsSelection();\n\n const handleRejectAll = React.useCallback(async () => {\n if (onRejectAllInEditor) await onRejectAllInEditor();\n onRejectAllSuggestions();\n }, [onRejectAllInEditor, onRejectAllSuggestions]);\n\n const handleAcceptAll = React.useCallback(async () => {\n if (onApplyAllInEditor) await onApplyAllInEditor();\n onApproveAllSuggestions();\n }, [onApplyAllInEditor, onApproveAllSuggestions]);\n\n const handleAcceptAndPublish = React.useCallback(\n async (visibility: AcceptAndPublishVisibility) => {\n if (!onAcceptAndPublish) return;\n if (onApplyAllInEditor) await onApplyAllInEditor();\n onAcceptAndPublish(visibility);\n },\n [onApplyAllInEditor, onAcceptAndPublish],\n );\n\n return (\n <div ref={ref} className={cn('flex flex-col gap-4', className)} {...props}>\n <SuggestionsHeaderTitleNav\n title={title}\n breadcrumb={breadcrumb}\n onOpenArticleLink={onOpenArticleLink}\n currentArticleIndex={currentArticleIndex}\n totalArticles={totalArticles}\n displayTotalArticles={displayTotalArticles}\n onNextArticle={onNextArticle}\n onPreviousArticle={onPreviousArticle}\n />\n <SuggestionsHeaderToolbar\n isNew={isNew}\n suggestionsCount={suggestionsCount}\n sourceIcon={sourceIcon}\n sourceDescription={sourceDescription}\n onSourceLinkClick={onSourceLinkClick}\n showActionButtons={showActionButtons}\n suggestionReasonBody={suggestionReasonBody}\n hideAcceptAndPublishPublic={hideAcceptAndPublishPublic}\n onAcceptAndPublish={onAcceptAndPublish}\n onRejectAll={handleRejectAll}\n onAcceptAll={handleAcceptAll}\n onAcceptAndPublishAction={handleAcceptAndPublish}\n />\n </div>\n );\n});\n","function countSuggestionsInRoot(root: Document | Element): number {\n const adjacentPairs = root.querySelectorAll('del + ins');\n const standaloneIns = root.querySelectorAll('ins:not(del + ins)');\n const allDel = root.querySelectorAll('del');\n const standaloneDel = Array.from(allDel).filter((del) => del.nextElementSibling?.tagName !== 'INS');\n\n return adjacentPairs.length + standaloneIns.length + standaloneDel.length;\n}\n\n/** Count suggestions in an HTML string (for title or raw HTML content). */\nexport const countSuggestions = (htmlString: string) => {\n if (!htmlString || typeof DOMParser === 'undefined') {\n return 0;\n }\n const parser = new DOMParser();\n const doc = parser.parseFromString(htmlString, 'text/html');\n\n return countSuggestionsInRoot(doc);\n};\n\n/** Count suggestions inside a DOM element (for rendered ReactNode body content). */\nexport const countSuggestionsInElement = (element: Element | null) => {\n if (!element) return 0;\n\n return countSuggestionsInRoot(element);\n};\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport parse from 'html-react-parser';\nimport { HandsClapping } from '@phosphor-icons/react';\n\nimport { useReviewsSelection } from './context';\nimport { SuggestionsHeader } from './suggestions-header';\nimport type { ReviewListItemProps } from './review-list';\n\nimport { countSuggestions, countSuggestionsInElement } from '@/lib/countSuggestions';\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { Spinner } from '@/components/ui/spinner';\n\nexport type KnowledgeReviewPanelProps = {\n diffTitle: string;\n items: ReviewListItemProps[];\n isLoading?: boolean;\n totalItemsCount?: number;\n showActionButtons?: boolean;\n children?: React.ReactNode;\n sourceIcon: React.ReactNode;\n sourceDescription: string | null;\n};\n\n/**\n * Panel that shows the selected diff (title + content), suggestion count, and article nav.\n * Must be used inside ReviewsSelectionProvider. Expects --knowledge-review-scroll-height\n * to be set by a parent for ScrollArea height.\n */\nexport function KnowledgeReviewPanel({\n diffTitle,\n items,\n isLoading,\n totalItemsCount,\n showActionButtons = true,\n children,\n sourceIcon,\n sourceDescription,\n}: KnowledgeReviewPanelProps) {\n const { selectedItem, setSelectedItem, loadedDiffDoc, loadingDiff } = useReviewsSelection();\n\n const hasItems = items.length > 0;\n const resolvedIsLoading = isLoading ?? !hasItems;\n const isLoadingState = resolvedIsLoading && !hasItems;\n const isEmptyState = !resolvedIsLoading && !hasItems;\n\n const title = loadingDiff ? '' : parse(loadedDiffDoc?.diffTitle ?? diffTitle ?? '');\n const body = loadingDiff ? <div className=\"text-muted-foreground\">Loading diff…</div> : loadedDiffDoc?.diffContent;\n\n const titleSuggestionsCount = loadingDiff ? 0 : countSuggestions(loadedDiffDoc?.diffTitle ?? diffTitle);\n\n const bodyRef = useRef<HTMLDivElement>(null);\n const [bodySuggestionsCount, setBodySuggestionsCount] = useState(0);\n useEffect(() => {\n if (loadingDiff || !loadedDiffDoc) {\n setBodySuggestionsCount(0);\n\n return;\n }\n const el = bodyRef.current;\n if (!el) return;\n const id = requestAnimationFrame(() => {\n setBodySuggestionsCount(countSuggestionsInElement(el));\n });\n\n return () => cancelAnimationFrame(id);\n }, [loadingDiff, loadedDiffDoc]);\n\n const suggestionsCount = titleSuggestionsCount + bodySuggestionsCount;\n\n const totalArticles = items.length;\n const totalArticlesForDisplay = totalItemsCount ?? totalArticles;\n const currentArticleIndex = selectedItem\n ? Math.max(\n 0,\n items.findIndex((i) => i.id === selectedItem.id),\n )\n : 0;\n\n const onNextArticle = useCallback(() => {\n if (currentArticleIndex < totalArticles - 1) {\n setSelectedItem(items[currentArticleIndex + 1] ?? null);\n }\n }, [currentArticleIndex, items, setSelectedItem, totalArticles]);\n\n const onPreviousArticle = useCallback(() => {\n if (currentArticleIndex > 0) {\n setSelectedItem(items[currentArticleIndex - 1] ?? null);\n }\n }, [currentArticleIndex, items, setSelectedItem]);\n\n const headerSourceIcon = selectedItem?.icon ?? sourceIcon;\n const headerSourceDescription = selectedItem?.description ?? sourceDescription;\n\n return (\n <Card className=\"py-6 pl-4\" data-name=\"knowledge-reviews\">\n <ScrollArea className=\"h-[calc(var(--knowledge-review-scroll-height)-50px)] pr-8\">\n <CardHeader className=\"p-0\">\n {hasItems && (\n <CardTitle className=\"border-b border-dark-300 mb-6 pb-2 font-normal\">\n <SuggestionsHeader\n title={title}\n isNew={loadedDiffDoc?.isNew ?? false}\n suggestionsCount={suggestionsCount}\n sourceIcon={headerSourceIcon}\n sourceDescription={headerSourceDescription}\n currentArticleIndex={currentArticleIndex}\n totalArticles={totalArticles}\n displayTotalArticles={totalArticlesForDisplay}\n showActionButtons={showActionButtons}\n onNextArticle={onNextArticle}\n onPreviousArticle={onPreviousArticle}\n />\n </CardTitle>\n )}\n </CardHeader>\n <CardContent className=\"p-0 [&_ol]:!pl-16 [&_ul]:!pl-16\">\n {/* Mount point for children (e.g. KnowledgeReviewDiffLoader). Kept in DOM so its effects run; hidden because it has no UI. */}\n <div aria-hidden=\"true\" className=\"sr-only\" hidden>\n {children}\n </div>\n {isLoadingState ? (\n <div className=\"flex flex-col items-center justify-center gap-4 text-center h-[50dvh] text-muted-foreground\">\n <Spinner className=\"size-8\" />\n <p className=\"text-base font-medium\">Loading suggestions...</p>\n </div>\n ) : isEmptyState ? (\n <div className=\"flex flex-col items-center justify-center gap-4 text-center h-[50dvh]\">\n <HandsClapping className=\"text-muted-foreground\" size={32} weight=\"fill\" />\n <p className=\"text-base font-medium text-foreground\">All up to date. Well done, mate.</p>\n </div>\n ) : (\n <div ref={bodyRef} className=\"pl-12\">\n {body}\n </div>\n )}\n </CardContent>\n </ScrollArea>\n </Card>\n );\n}\n","import React, { useEffect, useImperativeHandle, useRef } from 'react';\n\nimport { useReviewsSelection, type AcceptAndPublishVisibility } from './context';\nimport { ReviewList, ReviewListItemProps, ReviewsSelectionProvider } from './review-list';\nimport { KnowledgeReviewPanel } from './knowledge-review-panel';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { Spinner } from '@/components/ui/spinner';\nimport { cn } from '@/lib/utils';\n\nimport './knowledge-review.css';\n\nconst SCROLL_HEIGHT_VAR = '--knowledge-review-scroll-height';\n\nexport type KnowledgeReviewSceneHandle = {\n selectedItem: ReviewListItemProps | null;\n setSelectedItem: (item: ReviewListItemProps | null) => void;\n};\n\nexport type KnowledgeReviewSceneProps = {\n diffTitle?: string;\n children: React.ReactNode;\n items: ReviewListItemProps[];\n isLoading?: boolean;\n /** Total number of review list items available (can exceed currently loaded `items.length`). */\n totalItemsCount?: number;\n /** Controls visibility of the Reject / Accept action buttons in the review header. */\n showActionButtons?: boolean;\n className?: string;\n onApproveAllSuggestions: () => void;\n onRejectAllSuggestions: () => void;\n onAcceptAndPublish?: (visibility: AcceptAndPublishVisibility) => void;\n /** Bulk-apply against the live editor doc (new editor only). Runs before the server callback. */\n onApplyAllInEditor?: () => Promise<void> | void;\n /** Bulk-reject against the live editor doc (new editor only). Runs before the server callback. */\n onRejectAllInEditor?: () => Promise<void> | void;\n onOpenArticleLink?: () => void;\n onSourceLinkClick?: () => void;\n breadcrumb?: string;\n sourceIcon: React.ReactNode;\n sourceDescription: string | null;\n suggestionReasonBody?: string;\n hideAcceptAndPublishPublic?: boolean;\n};\n\nconst KnowledgeReviewSceneInner = React.forwardRef<KnowledgeReviewSceneHandle, KnowledgeReviewSceneProps>(\n function KnowledgeReviewSceneInner(\n {\n diffTitle = 'Knowledge Review',\n children,\n items,\n isLoading,\n totalItemsCount,\n showActionButtons = true,\n className,\n onApproveAllSuggestions,\n onRejectAllSuggestions,\n onOpenArticleLink,\n onAcceptAndPublish,\n onApplyAllInEditor,\n onRejectAllInEditor,\n onSourceLinkClick,\n breadcrumb,\n sourceIcon,\n sourceDescription,\n suggestionReasonBody,\n hideAcceptAndPublishPublic,\n ...props\n },\n ref,\n ) {\n const innerRef = useRef<HTMLDivElement>(null);\n const { selectedItem, setSelectedItem } = useReviewsSelection();\n\n useImperativeHandle(\n ref,\n () => ({\n selectedItem,\n setSelectedItem,\n }),\n [selectedItem, setSelectedItem],\n );\n\n useEffect(() => {\n const cardEl = innerRef.current;\n if (!cardEl) return;\n\n const updateHeight = () => {\n const { height } = cardEl.getBoundingClientRect();\n cardEl.style.setProperty(SCROLL_HEIGHT_VAR, `${height}px`);\n };\n\n updateHeight();\n\n if (typeof ResizeObserver !== 'function') {\n return;\n }\n\n const observer = new ResizeObserver(updateHeight);\n observer.observe(cardEl);\n\n return () => observer.disconnect();\n }, []);\n\n const resolvedIsLoading = isLoading ?? items.length === 0;\n const isLoadingItems = resolvedIsLoading && items.length === 0;\n\n return (\n <Card className={cn('h-full', className)}>\n <CardContent className=\"p-4 lg:p-8 h-full\">\n <div\n ref={innerRef}\n className=\"grid xs:max-lg:grid-cols-1 lg:grid-cols-[1fr_4fr] gap-6 min-h-96 h-full\"\n style={{ [SCROLL_HEIGHT_VAR]: '100px' } as React.CSSProperties}\n {...props}\n >\n <ScrollArea className=\"h-[calc(var(--knowledge-review-scroll-height))] min-w-80 lg:block hidden\">\n {isLoadingItems ? (\n <div className=\"flex h-full min-h-96 items-center justify-center text-muted-foreground\">\n <Spinner className=\"size-6\" />\n </div>\n ) : (\n <ReviewList items={items} />\n )}\n </ScrollArea>\n <KnowledgeReviewPanel\n diffTitle={diffTitle}\n items={items}\n isLoading={resolvedIsLoading}\n totalItemsCount={totalItemsCount}\n showActionButtons={showActionButtons}\n sourceIcon={sourceIcon}\n sourceDescription={sourceDescription}\n >\n {children}\n </KnowledgeReviewPanel>\n </div>\n </CardContent>\n </Card>\n );\n },\n);\n\nexport const KnowledgeReviewScene = React.forwardRef<KnowledgeReviewSceneHandle, KnowledgeReviewSceneProps>(\n function KnowledgeReviewScene(props, ref) {\n const {\n items,\n onApproveAllSuggestions,\n onRejectAllSuggestions,\n onAcceptAndPublish,\n onApplyAllInEditor,\n onRejectAllInEditor,\n onOpenArticleLink,\n onSourceLinkClick,\n breadcrumb,\n suggestionReasonBody,\n hideAcceptAndPublishPublic,\n } = props;\n\n return (\n <ReviewsSelectionProvider\n defaultSelectedItem={items.find((m) => m.isSelected) ?? null}\n onApproveAllSuggestions={onApproveAllSuggestions}\n onRejectAllSuggestions={onRejectAllSuggestions}\n onAcceptAndPublish={onAcceptAndPublish}\n onApplyAllInEditor={onApplyAllInEditor}\n onRejectAllInEditor={onRejectAllInEditor}\n onOpenArticleLink={onOpenArticleLink}\n onSourceLinkClick={onSourceLinkClick}\n breadcrumb={breadcrumb}\n suggestionReasonBody={suggestionReasonBody}\n hideAcceptAndPublishPublic={hideAcceptAndPublishPublic}\n >\n <KnowledgeReviewSceneInner {...props} ref={ref} />\n </ReviewsSelectionProvider>\n );\n },\n);\n"],"names":["KnowledgeReviewDiffLoader","fetchDiffForItem","selectedItem","setLoadedDiffDoc","setLoadingDiff","useReviewsSelection","loadDiffForItem","useCallback","async","itemId","signal","doc","aborted","error","console","selectedId","id","useEffect","abortController","AbortController","abort","SuggestionsHeaderTitleNav","title","breadcrumb","onOpenArticleLink","currentArticleIndex","totalArticles","displayTotalArticles","onNextArticle","onPreviousArticle","hasNextArticle","hasPreviousArticle","currentArticle","totalArticlesForDisplay","hasDisplayArticles","React","createElement","className","Button","variant","size","onClick","Tooltip","TooltipTrigger","asChild","disabled","CaretDown","TooltipContent","side","bgColor","CaretUp","SuggestionsHeaderToolbar","isNew","suggestionsCount","sourceIcon","sourceDescription","onSourceLinkClick","showActionButtons","suggestionReasonBody","hideAcceptAndPublishPublic","onAcceptAndPublish","onRejectAll","onAcceptAll","onAcceptAndPublishAction","whyOpen","setWhyOpen","useState","status","StatusBadge","EditCount","count","ButtonGroup","orientation","rounded","Popover","open","onOpenChange","PopoverTrigger","REASON_TITLE","Lightbulb","PopoverContent","align","Backspace","DropdownMenu","cn","brandShadowEffect","elevation","CheckCircle","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuItem","Globe","LockKey","SuggestionsHeader","forwardRef","props","ref","onApproveAllSuggestions","onRejectAllSuggestions","onApplyAllInEditor","onRejectAllInEditor","handleRejectAll","handleAcceptAll","handleAcceptAndPublish","visibility","countSuggestionsInRoot","root","adjacentPairs","querySelectorAll","standaloneIns","allDel","standaloneDel","Array","from","filter","del","nextElementSibling","tagName","length","KnowledgeReviewPanel","diffTitle","items","isLoading","totalItemsCount","children","setSelectedItem","loadedDiffDoc","loadingDiff","hasItems","resolvedIsLoading","isLoadingState","isEmptyState","parse","body","diffContent","titleSuggestionsCount","htmlString","DOMParser","parseFromString","bodyRef","useRef","bodySuggestionsCount","setBodySuggestionsCount","el","current","requestAnimationFrame","element","cancelAnimationFrame","Math","max","findIndex","i","headerSourceIcon","icon","headerSourceDescription","description","Card","ScrollArea","CardHeader","CardTitle","CardContent","hidden","Spinner","HandsClapping","weight","SCROLL_HEIGHT_VAR","KnowledgeReviewSceneInner","innerRef","useImperativeHandle","cardEl","updateHeight","height","getBoundingClientRect","style","setProperty","ResizeObserver","observer","observe","disconnect","isLoadingItems","ReviewList","KnowledgeReviewScene","ReviewsSelectionProvider","defaultSelectedItem","find","m","isSelected"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -35,6 +35,9 @@ import * as SwitchPrimitives from '@radix-ui/react-switch';
35
35
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
36
36
  import { VariantProps } from 'class-variance-authority';
37
37
 
38
+ /** Passed to `onAcceptAndPublish` from the split Accept dropdown (public vs internal). */
39
+ export declare type AcceptAndPublishVisibility = 'public' | 'internal';
40
+
38
41
  export declare function Accordion({ ...props }: React_2.ComponentProps<typeof AccordionPrimitive.Root>): React_2.JSX.Element;
39
42
 
40
43
  export declare function AccordionContent({ className, children, ...props }: React_2.ComponentProps<typeof AccordionPrimitive.Content>): React_2.JSX.Element;
@@ -1816,14 +1819,17 @@ export declare type ReviewsProviderProps = {
1816
1819
  defaultSelectedItem?: ReviewListItemProps | null;
1817
1820
  onApproveAllSuggestions: () => void;
1818
1821
  onRejectAllSuggestions: () => void;
1819
- onAcceptAndPublish?: () => void;
1822
+ onAcceptAndPublish?: (visibility: AcceptAndPublishVisibility) => void;
1823
+ onApplyAllInEditor?: () => Promise<void> | void;
1824
+ onRejectAllInEditor?: () => Promise<void> | void;
1820
1825
  onOpenArticleLink?: () => void;
1821
1826
  onSourceLinkClick?: () => void;
1822
1827
  breadcrumb?: string;
1823
1828
  suggestionReasonBody?: string;
1829
+ hideAcceptAndPublishPublic?: boolean;
1824
1830
  };
1825
1831
 
1826
- export declare function ReviewsSelectionProvider({ children, defaultSelectedItem, onApproveAllSuggestions, onRejectAllSuggestions, onAcceptAndPublish, onOpenArticleLink, onSourceLinkClick, breadcrumb, suggestionReasonBody, }: ReviewsProviderProps): default_2.JSX.Element;
1832
+ export declare function ReviewsSelectionProvider({ children, defaultSelectedItem, onApproveAllSuggestions, onRejectAllSuggestions, onAcceptAndPublish, onApplyAllInEditor, onRejectAllInEditor, onOpenArticleLink, onSourceLinkClick, breadcrumb, suggestionReasonBody, hideAcceptAndPublishPublic, }: ReviewsProviderProps): default_2.JSX.Element;
1827
1833
 
1828
1834
  declare type ReviewsSelectionValue = {
1829
1835
  selectedItem: ReviewListItemProps | null;
@@ -1834,11 +1840,15 @@ declare type ReviewsSelectionValue = {
1834
1840
  setLoadingDiff: (loading: boolean) => void;
1835
1841
  onApproveAllSuggestions: () => void;
1836
1842
  onRejectAllSuggestions: () => void;
1837
- onAcceptAndPublish?: () => void;
1843
+ onAcceptAndPublish?: (visibility: AcceptAndPublishVisibility) => void;
1844
+ onApplyAllInEditor?: () => Promise<void> | void;
1845
+ onRejectAllInEditor?: () => Promise<void> | void;
1838
1846
  onOpenArticleLink?: () => void;
1839
1847
  onSourceLinkClick?: () => void;
1840
1848
  breadcrumb?: string;
1841
1849
  suggestionReasonBody?: string;
1850
+ /** When true, omit the "publish publicly" item from the Accept & publish menu. */
1851
+ hideAcceptAndPublishPublic?: boolean;
1842
1852
  };
1843
1853
 
1844
1854
  declare function RightSidebar({ children, scrollable }: {
@@ -1,6 +1,9 @@
1
1
  import { default as default_2 } from 'react';
2
2
  import * as React_2 from 'react';
3
3
 
4
+ /** Passed to `onAcceptAndPublish` from the split Accept dropdown (public vs internal). */
5
+ export declare type AcceptAndPublishVisibility = 'public' | 'internal';
6
+
4
7
  /**
5
8
  * Listens to selectedItem from context and fetches diff via the provided callback.
6
9
  * Owns loading state and context updates; host (Storybook or Platform) supplies fetch logic.
@@ -49,13 +52,18 @@ export declare type KnowledgeReviewSceneProps = {
49
52
  className?: string;
50
53
  onApproveAllSuggestions: () => void;
51
54
  onRejectAllSuggestions: () => void;
52
- onAcceptAndPublish?: () => void;
55
+ onAcceptAndPublish?: (visibility: AcceptAndPublishVisibility) => void;
56
+ /** Bulk-apply against the live editor doc (new editor only). Runs before the server callback. */
57
+ onApplyAllInEditor?: () => Promise<void> | void;
58
+ /** Bulk-reject against the live editor doc (new editor only). Runs before the server callback. */
59
+ onRejectAllInEditor?: () => Promise<void> | void;
53
60
  onOpenArticleLink?: () => void;
54
61
  onSourceLinkClick?: () => void;
55
62
  breadcrumb?: string;
56
63
  sourceIcon: default_2.ReactNode;
57
64
  sourceDescription: string | null;
58
65
  suggestionReasonBody?: string;
66
+ hideAcceptAndPublishPublic?: boolean;
59
67
  };
60
68
 
61
69
  export declare type LoadedDiffDoc = {
@@ -91,14 +99,17 @@ declare type ReviewsProviderProps = {
91
99
  defaultSelectedItem?: ReviewListItemProps | null;
92
100
  onApproveAllSuggestions: () => void;
93
101
  onRejectAllSuggestions: () => void;
94
- onAcceptAndPublish?: () => void;
102
+ onAcceptAndPublish?: (visibility: AcceptAndPublishVisibility) => void;
103
+ onApplyAllInEditor?: () => Promise<void> | void;
104
+ onRejectAllInEditor?: () => Promise<void> | void;
95
105
  onOpenArticleLink?: () => void;
96
106
  onSourceLinkClick?: () => void;
97
107
  breadcrumb?: string;
98
108
  suggestionReasonBody?: string;
109
+ hideAcceptAndPublishPublic?: boolean;
99
110
  };
100
111
 
101
- export declare function ReviewsSelectionProvider({ children, defaultSelectedItem, onApproveAllSuggestions, onRejectAllSuggestions, onAcceptAndPublish, onOpenArticleLink, onSourceLinkClick, breadcrumb, suggestionReasonBody, }: ReviewsProviderProps): default_2.JSX.Element;
112
+ export declare function ReviewsSelectionProvider({ children, defaultSelectedItem, onApproveAllSuggestions, onRejectAllSuggestions, onAcceptAndPublish, onApplyAllInEditor, onRejectAllInEditor, onOpenArticleLink, onSourceLinkClick, breadcrumb, suggestionReasonBody, hideAcceptAndPublishPublic, }: ReviewsProviderProps): default_2.JSX.Element;
102
113
 
103
114
  declare type ReviewsSelectionValue = {
104
115
  selectedItem: ReviewListItemProps | null;
@@ -109,11 +120,15 @@ declare type ReviewsSelectionValue = {
109
120
  setLoadingDiff: (loading: boolean) => void;
110
121
  onApproveAllSuggestions: () => void;
111
122
  onRejectAllSuggestions: () => void;
112
- onAcceptAndPublish?: () => void;
123
+ onAcceptAndPublish?: (visibility: AcceptAndPublishVisibility) => void;
124
+ onApplyAllInEditor?: () => Promise<void> | void;
125
+ onRejectAllInEditor?: () => Promise<void> | void;
113
126
  onOpenArticleLink?: () => void;
114
127
  onSourceLinkClick?: () => void;
115
128
  breadcrumb?: string;
116
129
  suggestionReasonBody?: string;
130
+ /** When true, omit the "publish publicly" item from the Accept & publish menu. */
131
+ hideAcceptAndPublishPublic?: boolean;
117
132
  };
118
133
 
119
134
  /**
@@ -0,0 +1,10 @@
1
+ import { default as default_2 } from 'react';
2
+
3
+ export declare function MetricCardGroup({ children, className }: MetricCardGroupProps): default_2.JSX.Element;
4
+
5
+ export declare interface MetricCardGroupProps {
6
+ children: default_2.ReactNode;
7
+ className?: string;
8
+ }
9
+
10
+ export { }
@@ -0,0 +1,15 @@
1
+ import { default as default_2 } from 'react';
2
+
3
+ export declare const description = "A card to display plan allocation and usage status";
4
+
5
+ export declare function PlanUsageCard({ title, current, limit, subtitle, className }: PlanUsageCardProps): default_2.JSX.Element;
6
+
7
+ export declare interface PlanUsageCardProps {
8
+ title: string;
9
+ current: number;
10
+ limit?: number;
11
+ subtitle?: string;
12
+ className?: string;
13
+ }
14
+
15
+ export { }