use-chisel 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -0
- package/dist/hosted-entry.js +4 -4
- package/dist/index.js +1 -1
- package/dist/review/snapshot-upload.d.ts +2 -0
- package/dist/review-content-entry.d.ts +1 -0
- package/dist/review-content-entry.js +9 -3
- package/dist/review-entry.d.ts +1 -0
- package/dist/review-entry.js +4 -3
- package/dist/workspace/breakpoints.d.ts +3 -0
- package/dist/workspace/comment-box.d.ts +4 -1
- package/dist/workspace/comments.d.ts +22 -0
- package/dist/workspace/project-controls.d.ts +20 -0
- package/dist/workspace/review-links.d.ts +4 -0
- package/dist/workspace/workspace.d.ts +9 -1
- package/dist/workspace-entry.d.ts +2 -1
- package/dist/workspace-entry.js +19 -9
- package/package.json +5 -4
- package/src/review/workspace-design.css +11 -3
package/dist/review-entry.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use client";import{forwardRef as
|
|
2
|
-
`).map(a=>({type:"paragraph",children:[{text:a}]}))}}function
|
|
3
|
-
`)}function K(e){let a=e.content.slice();for(;a.length;){let o=a[a.length-1],t=o.children.slice();for(;t.length;){let l=t[t.length-1],u="type"in l?l.text||l.url:l.text,f=u.trimEnd();if(f)return t[t.length-1]=f===u?l:{...l,text:f},a[a.length-1]={...o,children:t},{...e,content:a};t.pop()}a.pop()}return A("")}function oe(e,a,o){let t=e;for(let l of[...a].sort((u,f)=>u-f))if(!(l<=t)){if(!o.has(l))break;t=l}return t}var Z=["image/jpeg","image/png","image/gif","image/webp","image/avif","image/bmp"],ke=["video/mp4","video/webm","video/quicktime"],we=[...Z,...ke].join(",");function Pe(e){let a=Z.includes(e.type);return!a&&!ke.includes(e.type)?"Choose a JPG, PNG, GIF, WebP, AVIF, BMP, MP4, WebM, or MOV file.":!Number.isSafeInteger(e.size)||e.size<=0?"This file is empty or invalid.":e.size>(a?5242880:20971520)?`${a?"Images must be 5 MB":"Videos must be 20 MB"} or smaller.`:null}import{useEffect as Je,useRef as ye,useState as Ae}from"react";import{createEditor as Qe,Editor as h,Element as q,Node as $e,Path as _e,Range as ue,Transforms as y}from"slate";import{withHistory as je}from"slate-history";import{Editable as Ye,Slate as ea,withReact as aa,ReactEditor as Be}from"slate-react";import{Fragment as Re,jsx as S,jsxs as Fe}from"react/jsx-runtime";function de(e){return e.content.length?e.content.map(a=>({type:"paragraph",children:a.children.length?a.children.map(o=>"type"in o&&o.type==="link"?{type:"link",url:o.url,children:[{text:o.text||o.url}]}:{...o}):[{text:""}]})):[{type:"paragraph",children:[{text:""}]}]}function De(e){return{version:1,content:e.map(a=>({type:"paragraph",children:q.isElement(a)?a.children.map(o=>q.isElement(o)?{type:"link",url:o.url,text:$e.string(o)}:{...o}):[{text:a.text}]}))}}function le(e){return/^(https?:\/\/|mailto:)[^\s]+$/i.test(e)}function ta(e,a){if(!e.selection){let o=window.getSelection(),t=o&&Be.toSlateRange(e,o,{exactMatch:!1,suppressThrow:!0});y.select(e,t??h.end(e,[]))}h.marks(e)?.[a]?h.removeMark(e,a):h.addMark(e,a,!0)}function Me(){let e=aa(je(Qe()),"application/x-chisel-review-fragment"),{isInline:a,insertText:o,insertData:t,insertBreak:l}=e;e.isInline=c=>c.type==="link"||a(c);function u(c,i){h.above(e,{at:c,match:p=>q.isElement(p)&&p.type==="link"})||(y.wrapNodes(e,{type:"link",url:i,children:[]},{at:c,split:!0}),y.collapse(e,{edge:"end"}))}function f(){if(!e.selection||!ue.isCollapsed(e.selection))return;let c=h.above(e,{match:d=>q.isElement(d)&&d.type==="paragraph"});if(!c)return;let i=e.selection.anchor,r=h.string(e,{anchor:h.start(e,c[1]),focus:i}).match(/\S+$/)?.[0];if(!r||!le(r))return;let I=h.before(e,i,{distance:r.length,unit:"offset"});if(I){u({anchor:I,focus:i},r);let d=h.above(e,{match:s=>q.isElement(s)&&s.type==="link"});d&&e.selection&&h.isEnd(e,e.selection.anchor,d[1])&&y.select(e,h.start(e,_e.next(d[1])))}}return e.insertText=c=>{if(Be.isComposing(e)){o(c);return}c===" "&&f();let i={"*":"bold",_:"italic","~":"strikethrough","`":"code"}[c];if(i&&e.selection&&ue.isCollapsed(e.selection)){let p=h.above(e,{match:r=>q.isElement(r)&&r.type==="paragraph"});if(p){let r=e.selection.anchor,I=h.string(e,{anchor:h.start(e,p[1]),focus:r}),d=I.lastIndexOf(c),s=I.slice(d+1);if(d>=0&&(!d||/[\s*_~`]/.test(I[d-1]))&&s&&s.trim()===s){let m=h.before(e,r,{distance:s.length,unit:"offset"}),x=m&&h.before(e,m,{unit:"offset"});if(m&&x){y.select(e,{anchor:m,focus:r}),h.addMark(e,i,!0),y.collapse(e,{edge:"end"}),y.delete(e,{at:{anchor:x,focus:m}}),h.removeMark(e,i);return}}}}o(c)},e.insertBreak=()=>{f(),l()},e.insertData=c=>{let i=c.getData("text/plain");le(i)?e.selection&&!ue.isCollapsed(e.selection)?u(e.selection,i):y.insertNodes(e,[{type:"link",url:i,children:[{text:i}]},{text:""}]):t(c)},e}function oa({attributes:e,children:a,element:o}){return o.type==="link"?S("a",{...e,href:le(o.url)?o.url:void 0,onClick:t=>t.preventDefault(),children:a}):S("p",{...e,children:a})}function ua({attributes:e,children:a,leaf:o}){let t=S(Re,{children:a});return o.bold&&(t=S("strong",{children:t})),o.italic&&(t=S("em",{children:t})),o.strikethrough&&(t=S("s",{children:t})),o.code&&(t=S("code",{children:t})),S("span",{...e,children:t})}function J({onFiles:e,disabled:a}){let o=ye(null);return Fe(Re,{children:[S("input",{ref:o,type:"file",accept:we,multiple:!0,hidden:!0,onChange:t=>{e(t.target.files),t.target.value=""}}),S("button",{type:"button",className:"review-retry-upload","aria-label":"Attach image or video",title:"Images up to 5 MB \xB7 Videos up to 20 MB",disabled:a,onClick:()=>o.current?.click(),children:S(E,{size:16,strokeWidth:1.75})})]})}function z({text:e,defaultBody:a,disabled:o,label:t,placeholder:l,autoFocus:u,onChange:f,onSubmit:c,onFiles:i,uploading:p}){let[r]=Ae(Me),[I]=Ae(()=>de(a??A(e))),d=ye(e);return Je(()=>{if(e===d.current)return;let s=d.current;d.current=e,s&&e.startsWith(s)?y.insertText(r,e.slice(s.length),{at:h.end(r,[])}):(h.withoutNormalizing(r,()=>{y.removeNodes(r,{at:[],match:(m,x)=>x.length===1}),y.insertNodes(r,de(A(e)),{at:[0]}),y.deselect(r)}),e||(r.history={undos:[],redos:[]}))},[r,e]),Fe(ea,{editor:r,initialValue:I,onChange:s=>{if(!r.operations.some(x=>x.type!=="set_selection"))return;let m=De(s);d.current=Se(m),f(d.current,m)},children:[S(Ye,{className:"review-composer-editor",role:"textbox","aria-multiline":"true","aria-label":t,placeholder:l,readOnly:o,autoFocus:u,renderElement:oa,renderLeaf:ua,onKeyDown:s=>{if(s.nativeEvent.isComposing)return;let m=s.metaKey||s.ctrlKey;if(s.key==="Enter"){s.preventDefault(),m?r.insertBreak():c();return}let x=m?{b:"bold",i:"italic",e:"code",...s.shiftKey?{s:"strikethrough"}:{}}[s.key.toLowerCase()]:void 0;x&&(s.preventDefault(),ta(r,x))}}),i&&S("div",{className:"chisel-attachment-controls",children:S(J,{onFiles:i,disabled:o||p})})]})}import{useEffect as da,useRef as la,useState as ra}from"react";import{Fragment as be,jsx as k,jsxs as Q}from"react/jsx-runtime";function sa({src:e,name:a,mimeType:o,onError:t,close:l}){let u=la(null);return da(()=>{u.current?.showModal()},[]),k("dialog",{ref:u,className:"review-media-lightbox","aria-label":`Preview ${a}`,onCancel:f=>{f.preventDefault(),l()},onClick:f=>{f.target===f.currentTarget&&l()},children:Q("div",{className:"review-media-lightbox-content",children:[Q("header",{children:[k("span",{children:a}),k("a",{href:e,download:a,"aria-label":`Download ${a}`,children:"Download"}),k("button",{type:"button","aria-label":"Close preview",onClick:l,children:k(v,{size:20})})]}),o.startsWith("image/")?k("img",{src:e,alt:a,onError:t}):k("video",{src:e,controls:!0,autoPlay:!0,playsInline:!0,"aria-label":a,onError:t})]})})}function $({src:e,name:a,mimeType:o,onError:t}){let[l,u]=ra(!1);return Q(be,{children:[k("button",{type:"button",className:"review-media-thumbnail","aria-label":`Preview ${a}`,onClick:()=>u(!0),children:o.startsWith("image/")?k("img",{src:e,alt:a,loading:"lazy",onError:t}):Q(be,{children:[k("video",{src:e,muted:!0,playsInline:!0,preload:"metadata","aria-hidden":"true",onError:t}),k("span",{className:"review-media-play","aria-hidden":"true",children:k(W,{size:20,fill:"currentColor"})})]})}),l&&k(sa,{src:e,name:a,mimeType:o,onError:t,close:()=>u(!1)})]})}import{Fragment as La,jsx as n,jsxs as M}from"react/jsx-runtime";function ve({body:e}){return n("div",{className:"review-comment-body",children:e.content.map((a,o)=>n("p",{children:a.children.map((t,l)=>{if("type"in t&&t.type==="link")return n("a",{href:/^(https?:|mailto:)/i.test(t.url)?t.url:void 0,target:"_blank",rel:"noopener noreferrer",children:t.text||t.url},l);if(!("text"in t))return null;let u=n(La,{children:t.text});return"bold"in t&&t.bold&&(u=n("strong",{children:u})),"italic"in t&&t.italic&&(u=n("em",{children:u})),"strikethrough"in t&&t.strikethrough&&(u=n("s",{children:u})),"code"in t&&t.code&&(u=n("code",{children:u})),n("span",{children:u},l)})},o))})}function fa({attachment:e,loadMedia:a}){let[o,t]=N(e.previewUrl??""),[l,u]=N(!1),[f,c]=N(0),i=B(0);U(()=>{if(e.previewUrl){t(e.previewUrl);return}t("");let r=!0,I=!1,d=new AbortController;async function s(){if(!(I||document.visibilityState==="hidden")){I=!0;try{let C=await a(e.id,d.signal);r&&(t(C),u(!1),i.current=Date.now()+240*1e3)}catch{r&&u(!0)}finally{I=!1}}}function m(){Date.now()>=i.current&&s()}s();let x=window.setInterval(m,60*1e3);return window.addEventListener("focus",m),document.addEventListener("visibilitychange",m),()=>{r=!1,d.abort(),window.clearInterval(x),window.removeEventListener("focus",m),document.removeEventListener("visibilitychange",m)}},[e.id,e.previewUrl,f,a]);function p(){u(!0),Date.now()>=i.current&&c(r=>r+1)}return M("figure",{className:"review-attachment",children:[o&&!l?n($,{src:o,name:e.name,mimeType:e.mimeType,onError:p}):n("div",{className:"review-attachment-placeholder",role:"status",children:l?n("button",{type:"button",className:"review-retry-upload",onClick:()=>c(r=>r+1),children:"Retry attachment"}):"Loading attachment\u2026"}),n("figcaption",{children:e.name})]})}function ia(e){let a=Math.max(0,Math.floor((Date.now()-Date.parse(e))/6e4));return a<1?"Just now":a<60?`${a}m`:a<1440?`${Math.floor(a/60)}h`:new Date(e).toLocaleDateString(void 0,{month:"short",day:"numeric"})}function ca({comment:e,activity:a,loadMedia:o,editable:t,editing:l,saving:u,onStartEdit:f,onCancelEdit:c,onSaveEdit:i,onDraftChange:p,onEditStyles:r}){let[I,d]=N(e.text),s=B(e.body??A(e.text)),m=B(!1);U(()=>{l||(d(e.text),s.current=e.body??A(e.text))},[l,e.text,e.body]);async function x(){if(!(u||m.current||!I.trim()&&!e.attachments?.length)){m.current=!0;try{await i(I.trimEnd(),K(s.current))&&p(!1)}finally{m.current=!1}}}return M("article",{className:"review-comment","data-activity":a,children:[n("span",{className:"review-comment-avatar",children:e.authorImage?n("img",{src:e.authorImage,alt:""}):e.author.slice(0,1).toUpperCase()}),M("div",{className:"review-comment-content",children:[M("header",{className:"review-comment-header",children:[n("span",{className:"review-comment-author",children:e.author}),e.pending?n("span",{className:"review-comment-time",role:"status",children:"Sending\u2026"}):n("time",{className:"review-comment-time",dateTime:e.date,title:new Date(e.date).toLocaleString(),children:ia(e.date)}),t&&!l&&n("button",{type:"button",className:"review-comment-edit","aria-label":"Edit comment",title:"Edit comment",disabled:u,onClick:f,children:n(G,{size:16})})]}),l?M("form",{className:"review-inline-edit",onSubmit:C=>{C.preventDefault(),x()},children:[n(z,{text:I,defaultBody:s.current,disabled:u,label:"Edit comment",placeholder:"Edit comment\u2026",autoFocus:!0,onSubmit:()=>{x()},onChange:(C,R)=>{d(C),s.current=R,p(C!==e.text||JSON.stringify(R)!==JSON.stringify(e.body??A(e.text)))}}),M("div",{className:"review-inline-edit-actions",children:[r&&n("button",{type:"button",disabled:u,onClick:r,children:"Edit styles"}),n("button",{type:"button",disabled:u,onClick:c,children:"Cancel"}),n("button",{type:"submit",disabled:u||!I.trim()&&!e.attachments?.length,children:"Save"})]})]}):n(ve,{body:e.body??A(e.text)}),e.attachments?.length>0&&n("div",{className:"review-attachments",children:e.attachments.map(C=>n(fa,{attachment:C,loadMedia:o},C.id))})]})]})}function na(e){let a=e.useAttachments(e.disabled,e.existingAttachments?.length??0),o=B(e.defaultBody??A(e.text)),t=B(!1);U(()=>(e.onAttachmentDraftChange?.(a.uploading||a.attachments.length>0),()=>e.onAttachmentDraftChange?.(!1)),[a.uploading,a.attachments.length,e.onAttachmentDraftChange]);async function l(){if(!(e.disabled||a.blocked||t.current||!e.text.trim()&&!a.attachments.length&&!e.existingAttachments?.length)){t.current=!0;try{await e.onSubmit(e.text.trimEnd(),K(o.current),a.tokens,a.previews)&&a.clear()}finally{t.current=!1}}}return n("form",{className:"review-composer chisel-review-composer","aria-label":e.commentId?"Edit comment":"New comment",onSubmit:u=>{u.preventDefault(),l()},onPasteCapture:u=>{u.clipboardData.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.clipboardData.files))},onDragOver:u=>{u.dataTransfer.types.includes("Files")&&u.preventDefault()},onDropCapture:u=>{u.dataTransfer.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.dataTransfer.files))},children:e.renderContent(M("div",{className:"chisel-composer-input",children:[n(z,{text:e.text,defaultBody:e.defaultBody,disabled:e.disabled,label:"Comment",placeholder:"Leave a comment\u2026",autoFocus:!0,onSubmit:()=>{l()},onChange:(u,f)=>{o.current=f,e.onText(u)}}),a.previewsUI,a.controls]}),a.attachments.length>0||!!e.existingAttachments?.length,a.blocked,n(J,{onFiles:a.upload,disabled:e.disabled||a.uploading}))})}function pa(e){let a=e.useAttachments(e.saving),o=B(A(e.reply)),t=B(!1);U(()=>(e.onAttachmentDraftChange?.(a.uploading||a.attachments.length>0),()=>e.onAttachmentDraftChange?.(!1)),[a.uploading,a.attachments.length,e.onAttachmentDraftChange]);async function l(){if(!(e.saving||a.blocked||t.current||!e.reply.trim()&&!a.attachments.length)){t.current=!0;try{await e.onReply(e.reply.trimEnd(),K(o.current),a.tokens,a.previews)&&(o.current=A(""),a.clear())}finally{t.current=!1}}}return M("form",{className:"review-composer chisel-review-reply","aria-label":"Reply to thread",hidden:e.submittingReply,onSubmit:u=>{u.preventDefault(),l()},onPasteCapture:u=>{u.clipboardData.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.clipboardData.files))},onDragOver:u=>{u.dataTransfer.types.includes("Files")&&u.preventDefault()},onDropCapture:u=>{u.dataTransfer.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.dataTransfer.files))},children:[n("span",{className:"feedback-avatar feedback-reply-avatar",children:e.replyAuthor?.image?n("img",{src:e.replyAuthor.image,alt:""}):(e.replyAuthor?.name||"You").slice(0,1).toUpperCase()}),M("div",{className:"chisel-reply-field",children:[n(z,{text:e.reply,disabled:e.saving,label:"Reply",placeholder:"Write a reply\u2026",onFiles:a.upload,uploading:a.uploading,onSubmit:()=>{l()},onChange:(u,f)=>{o.current=f,e.onReplyText(u)}}),a.previewsUI,a.controls,n("button",{type:"submit",className:"chisel-reply-submit","aria-label":"Reply",disabled:e.saving||a.blocked||!e.reply.trim()&&!a.attachments.length,children:n(H,{size:16,strokeWidth:1.75})})]})]})}function ma(e){let a=e.comment,[o,t]=N(null),l=B(!1),u=B(e.onEditDraftChange);u.current=e.onEditDraftChange,U(()=>()=>{u.current?.(!1)},[]);function f(d){l.current=d,e.onEditDraftChange?.(d)}async function c(d){d&&e.onBeginEdit&&!await e.onBeginEdit()||!d&&l.current&&e.onDiscardEdit&&!await e.onDiscardEdit()||(f(!1),t(d))}function i(d,s){return n(ca,{comment:d,activity:s?a.rootActivity:d.activity,loadMedia:e.loadMedia,editable:!!(e.expanded&&e.onEdit&&e.userId&&d.authorId===e.userId&&!d.pending),editing:o===d.id,saving:e.saving,onEditStyles:s?e.onEditStyles:void 0,onStartEdit:()=>{c(d.id)},onCancelEdit:()=>{c(null)},onDraftChange:f,onSaveEdit:async(m,x)=>{let C=await e.onEdit?.(s?null:d.id,m,x);return C&&(f(!1),t(null)),!!C}},d.id)}let p=B(null),r=B(new Set),I=B(a.readActivity??0);return U(()=>{if(!e.expanded||!p.current||a.pending||a.readActivity===null)return;let d=[a.rootActivity,...a.replies.map(x=>x.activity)],s=new IntersectionObserver(x=>{if(document.visibilityState!=="visible")return;for(let R of x)R.isIntersecting&&R.intersectionRatio>0&&r.current.add(Number(R.target.dataset.activity));let C=oe(Math.max(I.current,a.readActivity??0),d,r.current);C>I.current&&(I.current=C,e.onRead(a.id,C))},{threshold:0});function m(){if(s.disconnect(),document.visibilityState==="visible")for(let x of p.current?.querySelectorAll("[data-activity]")??[])s.observe(x)}return m(),document.addEventListener("visibilitychange",m),()=>{s.disconnect(),document.removeEventListener("visibilitychange",m)}},[a,e.expanded,e.onRead]),M("div",{className:"chisel-review-thread-content",children:[M("div",{ref:p,className:"review-thread",children:[i(a,!0),e.expanded&&a.replies.map(d=>i(d,!1))]}),e.expanded?!o&&n(pa,{...e}):n("button",{type:"button",className:"chisel-expand-thread",onClick:e.onExpand,children:a.replies.length?`${a.replies.length} ${a.replies.length===1?"reply":"replies"}`:"Reply\u2026"})]})}import{useCallback as Te,useRef as qe}from"react";function Ia(e,a){let o=qe(new Map),t=qe(!1),l=Te(async()=>{if(!t.current){t.current=!0;try{for(;o.current.size;){let[f,c]=o.current.entries().next().value;try{await e(f,c)}catch(i){if([400,403,404].includes(i.status??0)){o.current.delete(f);continue}throw i}o.current.get(f)===c&&o.current.delete(f),a(f,c)}}catch{}finally{t.current=!1}}},[e,a]),u=Te((f,c)=>{o.current.set(f,Math.max(c,o.current.get(f)??0)),l()},[l]);return{flush:l,markDisplayed:u}}import{useEffect as xa,useRef as re,useState as se}from"react";import{jsx as b,jsxs as fe}from"react/jsx-runtime";function Ca(e=!1,a=0,o){let[t,l]=se([]),[u,f]=se(!1),[c,i]=se(""),p=re(!0),r=re(!1),I=re(new Map),d=L=>o.discard(L);xa(()=>(p.current=!0,()=>{p.current=!1;for(let L of I.current.values())URL.revokeObjectURL(L.preview),d(L).catch(()=>{})}),[]);function s(){p.current&&l([...I.current.values()].map(L=>({...L})))}function m(){for(let L of I.current.values())URL.revokeObjectURL(L.preview);I.current.clear(),p.current&&(l([]),i(""))}async function x(L){let g=I.current.get(L);if(!(!g||r.current||e)){r.current=!0,f(!0);try{await d(g),I.current.delete(L),URL.revokeObjectURL(g.preview),s(),i("")}catch(D){p.current&&i(D instanceof Error?D.message:"The attachment could not be removed.")}finally{r.current=!1,p.current&&f(!1)}}}async function C(L){for(let g of L){if(!p.current)return;let D=g.status==="failed";g.status="uploading",s();try{g.token=await o.send(g,D,()=>p.current),g.status="ready"}catch(w){g.status="failed",p.current&&i(w instanceof Error?w.message:"The upload failed. Your comment is still here.")}finally{p.current||await d(g).catch(()=>{})}s()}}async function R(L){if(!L?.length||r.current||e)return;let g=Array.from(L),D=g.map(w=>Pe(w)).find(Boolean);if(D){i(D);return}if(a+I.current.size+g.length>20){i("Attach up to 20 files per comment.");return}r.current=!0,f(!0),i("");try{let w=await o.userId();if(!w)throw new Error("Sign in again to attach files.");if(!p.current)return;let ee=g.map(T=>{let ae=crypto.randomUUID(),ie={id:ae,name:T.name,mimeType:T.type,size:T.size,file:T,bucket:Z.includes(T.type)?"chisel-review-images":"chisel-review-videos",path:`${w}/${ae}`,preview:URL.createObjectURL(T),stored:!1,status:"uploading"};return I.current.set(ae,ie),ie});s(),await C(ee)}catch(w){p.current&&i(w instanceof Error?w.message:"The upload failed. Your comment is still here.")}finally{r.current=!1,p.current&&f(!1)}}async function _(){if(!(r.current||e)){r.current=!0,f(!0),i("");try{await C([...I.current.values()].filter(L=>L.status==="failed"))}finally{r.current=!1,p.current&&f(!1)}}}let X=t.some(L=>L.status==="failed"),j=fe("div",{className:"chisel-attachment-controls",children:[u&&b("span",{role:"status",children:"Uploading\u2026"}),X&&fe("button",{type:"button",className:"review-retry-upload",disabled:u||e,onClick:()=>{_()},children:[b(V,{size:16,strokeWidth:1.75}),"Retry upload"]}),c&&b("span",{className:"chisel-attachment-error",role:"alert",children:c})]}),Y=t.length>0&&b("div",{className:"chisel-attachment-previews",children:t.map(L=>fe("div",{className:"chisel-attachment-preview","data-state":L.status,children:[b($,{src:L.preview,name:L.name,mimeType:L.mimeType}),b("span",{title:L.name,children:L.name}),b("button",{type:"button","aria-label":`Remove ${L.name}`,disabled:u||e,onClick:()=>{x(L.id)},children:b(v,{size:16,strokeWidth:1.75})})]},L.id))});return{attachments:t,uploading:u,blocked:u||X,controls:j,previewsUI:Y,clear:m,upload:R,previews:t.map(({id:L,name:g,mimeType:D,size:w,preview:ee})=>({id:L,name:g,mimeType:D,size:w,previewUrl:ee})),tokens:t.flatMap(L=>L.token?[L.token]:[])}}export{J as ReviewAttachmentButton,ve as ReviewBody,na as ReviewComposer,z as ReviewEditor,ma as ReviewThread,de as bodyToEditor,Me as createReviewEditor,oe as displayedActivity,De as editorToBody,Ia as useReadQueue,Ca as useReviewAttachments};
|
|
1
|
+
"use client";import{forwardRef as Ze,createElement as Je}from"react";var xe=e=>e?.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();function Ce(e,a,o=[]){if(a==null)throw new Error("[lucide]: iconNode is required when icon name is used");return{name:xe(e),size:24,node:a,...o.length>0?{aliases:o}:{}}}var he=e=>{let a="",o=!1;for(let t of e){if(t==="-"||t==="_"||t<=" "){o=a.length>0;continue}a.length===0?a+=t.toLowerCase():a+=o?t.toUpperCase():t,o=!1}return a};var ge=e=>{let a=he(e);return a.charAt(0).toUpperCase()+a.slice(1)};import{forwardRef as Ke,createElement as ye}from"react";var G=(...e)=>e.filter((a,o,t)=>!!a&&a.trim()!==""&&t.indexOf(a)===o).join(" ").trim();var v={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"};function de(e){return e!=null}function Se(e,a={}){let o=a.attributeNames??{},t=d=>o[d]??d,l=e.size??e.width??v.width,u=e.size??e.height??v.height,r=e.aliases?.filter(d=>typeof d=="string"&&d.trim()!=="").map(d=>`lucide-${d}`)??[],c=[...e.name?[`lucide-${e.name}`]:[],...r],i=a.className?.split(" ").filter(Boolean)??[],L=a.includeDefaultClasses===!1?G(...i):G("lucide",...c,...i),s=a.absoluteStrokeWidth?Number(a.strokeWidth??v["stroke-width"])*Number(e.size??e.width??v.width)/Number(a.size??a.width??v.width):a.strokeWidth??v["stroke-width"];return["svg",{...Object.entries(v).reduce((d,[f,n])=>(d[t(f)]=n,d),{}),..."color"in a&&a.color&&{[t("stroke")]:a.color},..."size"in a&&de(a.size)&&{[t("width")]:a.size,[t("height")]:a.size},..."width"in a&&de(a.width)&&{[t("width")]:a.width},..."height"in a&&de(a.height)&&{[t("height")]:a.height},[t("stroke-width")]:s,...L&&{[t("class")]:L},[t("viewBox")]:`0 0 ${l} ${u}`,...a.hasA11yProp===!1?{[t("aria-hidden")]:"true"}:{},..."attributes"in a&&a.attributes},e.node.map(d=>{let[f,n,x]=d,h=a.nonScalingStroke?{[t("vector-effect")]:"non-scaling-stroke",...n}:n;return x?[f,h,x]:[f,h]})]}function ke(e,a={}){return Se(e,{...a,attributeNames:{...a.attributeNames,class:"className","stroke-width":"strokeWidth","stroke-linecap":"strokeLinecap","stroke-linejoin":"strokeLinejoin","vector-effect":"vectorEffect"}})}var we=e=>{for(let a in e)if(a.startsWith("aria-")||a==="role"||a==="title")return!0;return!1};import{createContext as ze,useContext as Ne,useMemo as Va,createElement as za}from"react";var Xe=ze({});var Pe=()=>Ne(Xe);var Ae=Ke(({color:e,size:a,width:o,height:t,strokeWidth:l,absoluteStrokeWidth:u,nonScalingStroke:r,className:c="",children:i,iconNode:L=[],icon:s={node:L,aliases:[],size:24},...m},d)=>{let{size:f=24,strokeWidth:n=2,absoluteStrokeWidth:x=!1,nonScalingStroke:h=!1,color:R="currentColor",className:S=""}=Pe()??{},F=!!i||we(m),[ae,te,I=[]]=ke(s,{color:e??R,width:o??a??f,height:t??a??f,strokeWidth:l??n,absoluteStrokeWidth:u??x,nonScalingStroke:r??h,className:G(S,c),hasA11yProp:F,attributes:m});return ye(ae,{ref:d,...te},[...I.map(([g,b])=>ye(g,b)),...Array.isArray(i)?i:[i]])});function k(e,a=[],o=[]){let t=typeof e=="string"?Ce(e,a,o):e,l=Ze(({className:u,...r},c)=>Je(Ae,{ref:c,icon:t,className:u,...r}));return t.name&&(l.displayName=ge(t.name)),l}var Qe={name:"arrow-up",size:24,node:[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]},W=k(Qe);var $e={name:"download",size:24,node:[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]]},V=k($e);var _e={name:"paperclip",size:24,node:[["path",{d:"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551",key:"1miecu"}]]},z=k(_e);var je={name:"pencil",size:24,node:[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]]},N=k(je);var Ye={name:"play",size:24,node:[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]]},X=k(Ye);var ea={name:"rotate-cw",size:24,node:[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]]},K=k(ea);var aa={name:"x",size:24,node:[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]},q=k(aa);import{useEffect as U,useRef as y,useState as Q}from"react";function D(e){return{version:1,content:e.split(`
|
|
2
|
+
`).map(a=>({type:"paragraph",children:[{text:a}]}))}}function $(e){return e.content.map(a=>a.children.map(o=>"type"in o?o.text||o.url:o.text).join("")).join(`
|
|
3
|
+
`)}function _(e){let a=e.content.slice();for(;a.length;){let o=a[a.length-1],t=o.children.slice();for(;t.length;){let l=t[t.length-1],u="type"in l?l.text||l.url:l.text,r=u.trimEnd();if(r)return t[t.length-1]=r===u?l:{...l,text:r},a[a.length-1]={...o,children:t},{...e,content:a};t.pop()}a.pop()}return D("")}function le(e){try{let a=JSON.parse(localStorage.getItem(e)??"null");return a?.version===1&&Date.now()-a.time<7*864e5?a.value:null}catch{return null}}function H(e,a){try{return a===null?localStorage.removeItem(e):localStorage.setItem(e,JSON.stringify({version:1,time:Date.now(),value:a})),!0}catch{return!1}}function re(e,a,o){let t=e;for(let l of[...a].sort((u,r)=>u-r))if(!(l<=t)){if(!o.has(l))break;t=l}return t}var j=["image/jpeg","image/png","image/gif","image/webp","image/avif","image/bmp"],Be=["video/mp4","video/webm","video/quicktime"],De=[...j,...Be].join(",");function Me(e){let a=j.includes(e.type);return!a&&!Be.includes(e.type)?"Choose a JPG, PNG, GIF, WebP, AVIF, BMP, MP4, WebM, or MOV file.":!Number.isSafeInteger(e.size)||e.size<=0?"This file is empty or invalid.":e.size>(a?5242880:20971520)?`${a?"Images must be 5 MB":"Videos must be 20 MB"} or smaller.`:null}import{useEffect as ta,useRef as Re,useState as be}from"react";import{createEditor as oa,Editor as C,Element as E,Node as ua,Path as da,Range as se,Transforms as M}from"slate";import{withHistory as la}from"slate-history";import{Editable as ra,Slate as sa,withReact as fa,ReactEditor as Fe}from"slate-react";import{Fragment as qe,jsx as w,jsxs as Ue}from"react/jsx-runtime";function fe(e){return e.content.length?e.content.map(a=>({type:"paragraph",children:a.children.length?a.children.map(o=>"type"in o&&o.type==="link"?{type:"link",url:o.url,children:[{text:o.text||o.url}]}:{...o}):[{text:""}]})):[{type:"paragraph",children:[{text:""}]}]}function ve(e){return{version:1,content:e.map(a=>({type:"paragraph",children:E.isElement(a)?a.children.map(o=>E.isElement(o)?{type:"link",url:o.url,text:ua.string(o)}:{...o}):[{text:a.text}]}))}}function ie(e){return/^(https?:\/\/|mailto:)[^\s]+$/i.test(e)}function ia(e,a){if(!e.selection){let o=window.getSelection(),t=o&&Fe.toSlateRange(e,o,{exactMatch:!1,suppressThrow:!0});M.select(e,t??C.end(e,[]))}C.marks(e)?.[a]?C.removeMark(e,a):C.addMark(e,a,!0)}function Te(){let e=fa(la(oa()),"application/x-chisel-review-fragment"),{isInline:a,insertText:o,insertData:t,insertBreak:l}=e;e.isInline=c=>c.type==="link"||a(c);function u(c,i){C.above(e,{at:c,match:L=>E.isElement(L)&&L.type==="link"})||(M.wrapNodes(e,{type:"link",url:i,children:[]},{at:c,split:!0}),M.collapse(e,{edge:"end"}))}function r(){if(!e.selection||!se.isCollapsed(e.selection))return;let c=C.above(e,{match:d=>E.isElement(d)&&d.type==="paragraph"});if(!c)return;let i=e.selection.anchor,s=C.string(e,{anchor:C.start(e,c[1]),focus:i}).match(/\S+$/)?.[0];if(!s||!ie(s))return;let m=C.before(e,i,{distance:s.length,unit:"offset"});if(m){u({anchor:m,focus:i},s);let d=C.above(e,{match:f=>E.isElement(f)&&f.type==="link"});d&&e.selection&&C.isEnd(e,e.selection.anchor,d[1])&&M.select(e,C.start(e,da.next(d[1])))}}return e.insertText=c=>{if(Fe.isComposing(e)){o(c);return}c===" "&&r();let i={"*":"bold",_:"italic","~":"strikethrough","`":"code"}[c];if(i&&e.selection&&se.isCollapsed(e.selection)){let L=C.above(e,{match:s=>E.isElement(s)&&s.type==="paragraph"});if(L){let s=e.selection.anchor,m=C.string(e,{anchor:C.start(e,L[1]),focus:s}),d=m.lastIndexOf(c),f=m.slice(d+1);if(d>=0&&(!d||/[\s*_~`]/.test(m[d-1]))&&f&&f.trim()===f){let n=C.before(e,s,{distance:f.length,unit:"offset"}),x=n&&C.before(e,n,{unit:"offset"});if(n&&x){M.select(e,{anchor:n,focus:s}),C.addMark(e,i,!0),M.collapse(e,{edge:"end"}),M.delete(e,{at:{anchor:x,focus:n}}),C.removeMark(e,i);return}}}}o(c)},e.insertBreak=()=>{r(),l()},e.insertData=c=>{let i=c.getData("text/plain");ie(i)?e.selection&&!se.isCollapsed(e.selection)?u(e.selection,i):M.insertNodes(e,[{type:"link",url:i,children:[{text:i}]},{text:""}]):t(c)},e}function ca({attributes:e,children:a,element:o}){return o.type==="link"?w("a",{...e,href:ie(o.url)?o.url:void 0,onClick:t=>t.preventDefault(),children:a}):w("p",{...e,children:a})}function na({attributes:e,children:a,leaf:o}){let t=w(qe,{children:a});return o.bold&&(t=w("strong",{children:t})),o.italic&&(t=w("em",{children:t})),o.strikethrough&&(t=w("s",{children:t})),o.code&&(t=w("code",{children:t})),w("span",{...e,children:t})}function Z({onFiles:e,disabled:a}){let o=Re(null);return Ue(qe,{children:[w("input",{ref:o,type:"file",accept:De,multiple:!0,hidden:!0,onChange:t=>{e(t.target.files),t.target.value=""}}),w("button",{type:"button",className:"review-retry-upload","aria-label":"Attach image or video",title:"Images up to 5 MB \xB7 Videos up to 20 MB",disabled:a,onClick:()=>o.current?.click(),children:w(z,{size:16,strokeWidth:1.75})})]})}function J({text:e,defaultBody:a,disabled:o,label:t,placeholder:l,autoFocus:u,onChange:r,onSubmit:c,onFiles:i,uploading:L}){let[s]=be(Te),[m]=be(()=>fe(a??D(e))),d=Re(e);return ta(()=>{if(e===d.current)return;let f=d.current;d.current=e,f&&e.startsWith(f)?M.insertText(s,e.slice(f.length),{at:C.end(s,[])}):(C.withoutNormalizing(s,()=>{M.removeNodes(s,{at:[],match:(n,x)=>x.length===1}),M.insertNodes(s,fe(D(e)),{at:[0]}),M.deselect(s)}),e||(s.history={undos:[],redos:[]}))},[s,e]),Ue(sa,{editor:s,initialValue:m,onChange:f=>{if(!s.operations.some(x=>x.type!=="set_selection"))return;let n=ve(f);d.current=$(n),r(d.current,n)},children:[w(ra,{className:"review-composer-editor",role:"textbox","aria-multiline":"true","aria-label":t,placeholder:l,readOnly:o,autoFocus:u,renderElement:ca,renderLeaf:na,onKeyDown:f=>{if(f.nativeEvent.isComposing)return;let n=f.metaKey||f.ctrlKey;if(f.key==="Enter"){f.preventDefault(),n?s.insertBreak():c();return}let x=n?{b:"bold",i:"italic",e:"code",...f.shiftKey?{s:"strikethrough"}:{}}[f.key.toLowerCase()]:void 0;x&&(f.preventDefault(),ia(s,x))}}),i&&w("div",{className:"chisel-attachment-controls",children:w(Z,{onFiles:i,disabled:o||L})})]})}import{useEffect as pa,useRef as ma,useState as La}from"react";import{Fragment as Oe,jsx as P,jsxs as Y}from"react/jsx-runtime";function Ia({src:e,name:a,mimeType:o,onError:t,close:l}){let u=ma(null);return pa(()=>{u.current?.showModal()},[]),P("dialog",{ref:u,className:"review-media-lightbox","aria-label":`Preview ${a}`,onCancel:r=>{r.preventDefault(),l()},onClick:r=>{r.target===r.currentTarget&&l()},children:Y("div",{className:"review-media-lightbox-content",children:[Y("header",{children:[P("span",{children:a}),P("a",{href:e,download:a,"aria-label":`Download ${a}`,title:"Download",children:P(V,{size:20,"aria-hidden":"true"})}),P("button",{type:"button","aria-label":"Close preview",onClick:l,children:P(q,{size:20})})]}),o.startsWith("image/")?P("img",{src:e,alt:a,onError:t}):P("video",{src:e,controls:!0,autoPlay:!0,playsInline:!0,"aria-label":a,onError:t})]})})}function ee({src:e,name:a,mimeType:o,onError:t}){let[l,u]=La(!1);return Y(Oe,{children:[P("button",{type:"button",className:"review-media-thumbnail","aria-label":`Preview ${a}`,onClick:()=>u(!0),children:o.startsWith("image/")?P("img",{src:e,alt:a,loading:"lazy",onError:t}):Y(Oe,{children:[P("video",{src:e,muted:!0,playsInline:!0,preload:"metadata","aria-hidden":"true",onError:t}),P("span",{className:"review-media-play","aria-hidden":"true",children:P(X,{size:20,fill:"currentColor"})})]})}),l&&P(Ia,{src:e,name:a,mimeType:o,onError:t,close:()=>u(!1)})]})}import{Fragment as ka,jsx as p,jsxs as A}from"react/jsx-runtime";function ce(e,a,o){if(e)try{let t=le(e);if(t?.text===a&&$(t.body)===a)return t.body}catch{}return o??D(a)}function ne(e,a,o,t=!1){e&&H(e,t||a.trim()?{text:a,body:o}:null)}function He({body:e}){return p("div",{className:"review-comment-body",children:e.content.map((a,o)=>p("p",{children:a.children.map((t,l)=>{if("type"in t&&t.type==="link")return p("a",{href:/^(https?:|mailto:)/i.test(t.url)?t.url:void 0,target:"_blank",rel:"noopener noreferrer",children:t.text||t.url},l);if(!("text"in t))return null;let u=p(ka,{children:t.text});return"bold"in t&&t.bold&&(u=p("strong",{children:u})),"italic"in t&&t.italic&&(u=p("em",{children:u})),"strikethrough"in t&&t.strikethrough&&(u=p("s",{children:u})),"code"in t&&t.code&&(u=p("code",{children:u})),p("span",{children:u},l)})},o))})}function xa({attachment:e,loadMedia:a}){let[o,t]=Q(e.previewUrl??""),[l,u]=Q(!1),[r,c]=Q(0),i=y(0);U(()=>{if(e.previewUrl){t(e.previewUrl);return}t("");let s=!0,m=!1,d=new AbortController;async function f(){if(!(m||document.visibilityState==="hidden")){m=!0;try{let h=await a(e.id,d.signal);s&&(t(h),u(!1),i.current=Date.now()+240*1e3)}catch{s&&u(!0)}finally{m=!1}}}function n(){Date.now()>=i.current&&f()}f();let x=window.setInterval(n,60*1e3);return window.addEventListener("focus",n),document.addEventListener("visibilitychange",n),()=>{s=!1,d.abort(),window.clearInterval(x),window.removeEventListener("focus",n),document.removeEventListener("visibilitychange",n)}},[e.id,e.previewUrl,r,a]);function L(){u(!0),Date.now()>=i.current&&c(s=>s+1)}return A("figure",{className:"review-attachment",children:[o&&!l?p(ee,{src:o,name:e.name,mimeType:e.mimeType,onError:L}):p("div",{className:"review-attachment-placeholder",role:"status",children:l?p("button",{type:"button",className:"review-retry-upload",onClick:()=>c(s=>s+1),children:"Retry attachment"}):"Loading attachment\u2026"}),p("figcaption",{children:e.name})]})}function Ee(e){let a=Math.max(0,Math.floor((Date.now()-Date.parse(e))/6e4));return a<1?"Just now":a<60?`${a}m`:a<1440?`${Math.floor(a/60)}h`:new Date(e).toLocaleDateString(void 0,{month:"short",day:"numeric"})}function Ca({comment:e,activity:a,loadMedia:o,editable:t,editing:l,saving:u,onStartEdit:r,onCancelEdit:c,onSaveEdit:i,onDraftChange:L,onEditStyles:s,draftKey:m}){let[d,f]=Q(e.text),n=y(e.body??D(e.text)),x=y(!1),h=y(!1);U(()=>{l?L(d!==e.text||JSON.stringify(n.current)!==JSON.stringify(e.body??D(e.text))):h.current&&m&&H(m,null),h.current=l},[l]),U(()=>{l||(f(e.text),n.current=e.body??D(e.text))},[l,e.text,e.body]);async function R(){if(!(u||x.current||!d.trim()&&!e.attachments?.length)){x.current=!0;try{await i(d.trimEnd(),_(n.current))&&(m&&H(m,null),L(!1))}finally{x.current=!1}}}return A("article",{className:"review-comment","data-activity":a,children:[p("span",{className:"review-comment-avatar",children:e.authorImage?p("img",{src:e.authorImage,alt:""}):e.author.slice(0,1).toUpperCase()}),A("div",{className:"review-comment-content",children:[A("header",{className:"review-comment-header",children:[p("span",{className:"review-comment-author",children:e.author}),e.pending?p("span",{className:"review-comment-time",role:"status",children:"Sending\u2026"}):p("time",{className:"review-comment-time",dateTime:e.date,title:new Date(e.date).toLocaleString(),children:Ee(e.date)}),t&&!l&&p("button",{type:"button",className:"review-comment-edit","aria-label":"Edit comment",title:"Edit comment",disabled:u,onClick:()=>{let S=m?le(m):null;S&&typeof S.text=="string"&&(f(S.text),n.current=ce(m,S.text)),r()},children:p(N,{size:16})})]}),l?A("form",{className:"review-inline-edit",onSubmit:S=>{S.preventDefault(),R()},children:[p(J,{text:d,defaultBody:n.current,disabled:u,label:"Edit comment",placeholder:"Edit comment\u2026",autoFocus:!0,onSubmit:()=>{R()},onChange:(S,F)=>{f(S),n.current=F,ne(m,S,F,!0),L(S!==e.text||JSON.stringify(F)!==JSON.stringify(e.body??D(e.text)))}}),A("div",{className:"review-inline-edit-actions",children:[s&&p("button",{type:"button",disabled:u,onClick:s,children:"Edit styles"}),p("button",{type:"button",disabled:u,onClick:c,children:"Cancel"}),p("button",{type:"submit",disabled:u||!d.trim()&&!e.attachments?.length,children:"Save"})]})]}):p(He,{body:e.body??D(e.text)}),e.attachments?.length>0&&p("div",{className:"review-attachments",children:e.attachments.map(S=>p(xa,{attachment:S,loadMedia:o},S.id))})]})]})}function ha(e){let a=e.useAttachments(e.disabled,e.existingAttachments?.length??0),o=y(ce(e.draftKey,e.text,e.defaultBody)),t=y(!1);U(()=>(e.onAttachmentDraftChange?.(a.uploading||a.attachments.length>0),()=>e.onAttachmentDraftChange?.(!1)),[a.uploading,a.attachments.length,e.onAttachmentDraftChange]);async function l(){if(!(e.disabled||a.blocked||t.current||!e.text.trim()&&!a.attachments.length&&!e.existingAttachments?.length)){t.current=!0;try{await e.onSubmit(e.text.trimEnd(),_(o.current),a.tokens,a.previews)&&(e.draftKey&&H(e.draftKey,null),a.clear())}finally{t.current=!1}}}return p("form",{className:"review-composer chisel-review-composer","aria-label":e.commentId?"Edit comment":"New comment",onSubmit:u=>{u.preventDefault(),l()},onPasteCapture:u=>{u.clipboardData.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.clipboardData.files))},onDragOver:u=>{u.dataTransfer.types.includes("Files")&&u.preventDefault()},onDropCapture:u=>{u.dataTransfer.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.dataTransfer.files))},children:e.renderContent(A("div",{className:"chisel-composer-input",children:[p(J,{text:e.text,defaultBody:o.current,disabled:e.disabled,label:"Comment",placeholder:"Leave a comment\u2026",autoFocus:!0,onSubmit:()=>{l()},onChange:(u,r)=>{o.current=r,ne(e.draftKey,u,r),e.onText(u)}}),a.previewsUI,a.controls]}),a.attachments.length>0||!!e.existingAttachments?.length,a.blocked,p(Z,{onFiles:a.upload,disabled:e.disabled||a.uploading}))})}function ga(e){let a=e.useAttachments(e.saving),o=y(ce(e.draftKey,e.reply)),t=y(!1);U(()=>(e.onAttachmentDraftChange?.(a.uploading||a.attachments.length>0),()=>e.onAttachmentDraftChange?.(!1)),[a.uploading,a.attachments.length,e.onAttachmentDraftChange]);async function l(){if(!(e.saving||a.blocked||t.current||!e.reply.trim()&&!a.attachments.length)){t.current=!0;try{await e.onReply(e.reply.trimEnd(),_(o.current),a.tokens,a.previews)&&(e.draftKey&&H(e.draftKey,null),o.current=D(""),a.clear())}finally{t.current=!1}}}return A("form",{className:"review-composer chisel-review-reply","aria-label":"Reply to thread",hidden:e.submittingReply,onSubmit:u=>{u.preventDefault(),l()},onPasteCapture:u=>{u.clipboardData.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.clipboardData.files))},onDragOver:u=>{u.dataTransfer.types.includes("Files")&&u.preventDefault()},onDropCapture:u=>{u.dataTransfer.files.length&&(u.preventDefault(),u.stopPropagation(),a.upload(u.dataTransfer.files))},children:[p("span",{className:"feedback-avatar feedback-reply-avatar",children:e.replyAuthor?.image?p("img",{src:e.replyAuthor.image,alt:""}):(e.replyAuthor?.name||"You").slice(0,1).toUpperCase()}),A("div",{className:"chisel-reply-field",children:[p(J,{text:e.reply,defaultBody:o.current,disabled:e.saving,label:"Reply",placeholder:"Write a reply\u2026",onSubmit:()=>{l()},onChange:(u,r)=>{o.current=r,ne(e.draftKey,u,r),e.onReplyText(u)}}),a.previewsUI,a.controls,p("div",{className:"chisel-attachment-controls",children:p(Z,{onFiles:a.upload,disabled:e.saving||a.uploading})}),p("button",{type:"submit",className:"chisel-reply-submit","aria-label":"Reply",disabled:e.saving||a.blocked||!e.reply.trim()&&!a.attachments.length,children:p(W,{size:16,strokeWidth:1.75})})]})]})}function Sa(e){let a=e.comment,[o,t]=Q(null),l=y(!1),u=y(e.onEditDraftChange);u.current=e.onEditDraftChange,U(()=>()=>{u.current?.(!1)},[]);function r(d){l.current=d,e.onEditDraftChange?.(d)}async function c(d){d&&e.onBeginEdit&&!await e.onBeginEdit()||!d&&l.current&&e.onDiscardEdit&&!await e.onDiscardEdit()||(r(!1),t(d))}function i(d,f){return p(Ca,{draftKey:e.draftKey?`${e.draftKey}:edit:${d.id}`:void 0,comment:d,activity:f?a.rootActivity:d.activity,loadMedia:e.loadMedia,editable:!!(e.expanded&&e.onEdit&&e.userId&&d.authorId===e.userId&&!d.pending),editing:o===d.id,saving:e.saving,onEditStyles:f?e.onEditStyles:void 0,onStartEdit:()=>{c(d.id)},onCancelEdit:()=>{c(null)},onDraftChange:r,onSaveEdit:async(n,x)=>{let h=await e.onEdit?.(f?null:d.id,n,x);return h&&(r(!1),t(null)),!!h}},d.id)}let L=y(null),s=y(new Set),m=y(a.readActivity??0);return U(()=>{if(!e.expanded||!L.current||a.pending||a.readActivity===null)return;let d=[a.rootActivity,...a.replies.map(x=>x.activity)],f=new IntersectionObserver(x=>{if(document.visibilityState!=="visible")return;for(let R of x)R.isIntersecting&&R.intersectionRatio>0&&s.current.add(Number(R.target.dataset.activity));let h=re(Math.max(m.current,a.readActivity??0),d,s.current);h>m.current&&(m.current=h,e.onRead(a.id,h))},{threshold:0});function n(){if(f.disconnect(),document.visibilityState==="visible")for(let x of L.current?.querySelectorAll("[data-activity]")??[])f.observe(x)}return n(),document.addEventListener("visibilitychange",n),()=>{f.disconnect(),document.removeEventListener("visibilitychange",n)}},[a,e.expanded,e.onRead]),A("div",{className:"chisel-review-thread-content",children:[e.expanded&&a.context&&A("p",{className:"review-capture-context",children:[a.context.width," \xD7 ",a.context.height,"px \xB7 ",a.breakpoint??"desktop",a.context.deployment?` \xB7 ${a.context.deployment}`:"",A("time",{dateTime:a.context.capturedAt,title:new Date(a.context.capturedAt).toLocaleString(),children:[" \xB7 ",Ee(a.context.capturedAt)]})]}),A("div",{ref:L,className:"review-thread",children:[i(a,!0),e.expanded&&a.replies.map(d=>i(d,!1))]}),e.expanded?!o&&p(ga,{...e}):p("button",{type:"button",className:"chisel-expand-thread",onClick:e.onExpand,children:a.replies.length?`${a.replies.length} ${a.replies.length===1?"reply":"replies"}`:"Reply\u2026"})]})}import{useCallback as Ge,useRef as We}from"react";function wa(e,a){let o=We(new Map),t=We(!1),l=Ge(async()=>{if(!t.current){t.current=!0;try{for(;o.current.size;){let[r,c]=o.current.entries().next().value;try{await e(r,c)}catch(i){if([400,403,404].includes(i.status??0)){o.current.delete(r);continue}throw i}o.current.get(r)===c&&o.current.delete(r),a(r,c)}}catch{}finally{t.current=!1}}},[e,a]),u=Ge((r,c)=>{o.current.set(r,Math.max(c,o.current.get(r)??0)),l()},[l]);return{flush:l,markDisplayed:u}}import{useEffect as Pa,useRef as pe,useState as me}from"react";import{jsx as T,jsxs as Le}from"react/jsx-runtime";function ya(e=!1,a=0,o){let[t,l]=me([]),[u,r]=me(!1),[c,i]=me(""),L=pe(!0),s=pe(!1),m=pe(new Map),d=I=>o.discard(I);Pa(()=>(L.current=!0,()=>{L.current=!1;for(let I of m.current.values())URL.revokeObjectURL(I.preview),d(I).catch(()=>{})}),[]);function f(){L.current&&l([...m.current.values()].map(I=>({...I})))}function n(){for(let I of m.current.values())URL.revokeObjectURL(I.preview);m.current.clear(),L.current&&(l([]),i(""))}async function x(I){let g=m.current.get(I);if(!(!g||s.current||e)){s.current=!0,r(!0);try{await d(g),m.current.delete(I),URL.revokeObjectURL(g.preview),f(),i("")}catch(b){L.current&&i(b instanceof Error?b.message:"The attachment could not be removed.")}finally{s.current=!1,L.current&&r(!1)}}}async function h(I){for(let g of I){if(!L.current)return;let b=g.status==="failed";g.status="uploading",f();try{g.token=await o.send(g,b,()=>L.current),g.status="ready"}catch(B){g.status="failed",L.current&&i(B instanceof Error?B.message:"The upload failed. Your comment is still here.")}finally{L.current||await d(g).catch(()=>{})}f()}}async function R(I){if(!I?.length||s.current||e)return;let g=Array.from(I),b=g.map(B=>Me(B)).find(Boolean);if(b){i(b);return}if(a+m.current.size+g.length>20){i("Attach up to 20 files per comment.");return}s.current=!0,r(!0),i("");try{let B=await o.userId();if(!B)throw new Error("Sign in again to attach files.");if(!L.current)return;let oe=g.map(O=>{let ue=crypto.randomUUID(),Ie={id:ue,name:O.name,mimeType:O.type,size:O.size,file:O,bucket:j.includes(O.type)?"chisel-review-images":"chisel-review-videos",path:`${B}/${ue}`,preview:URL.createObjectURL(O),stored:!1,status:"uploading"};return m.current.set(ue,Ie),Ie});f(),await h(oe)}catch(B){L.current&&i(B instanceof Error?B.message:"The upload failed. Your comment is still here.")}finally{s.current=!1,L.current&&r(!1)}}async function S(){if(!(s.current||e)){s.current=!0,r(!0),i("");try{await h([...m.current.values()].filter(I=>I.status==="failed"))}finally{s.current=!1,L.current&&r(!1)}}}let F=t.some(I=>I.status==="failed"),ae=Le("div",{className:"chisel-attachment-controls",children:[u&&T("span",{role:"status",children:"Uploading\u2026"}),F&&Le("button",{type:"button",className:"review-retry-upload",disabled:u||e,onClick:()=>{S()},children:[T(K,{size:16,strokeWidth:1.75}),"Retry upload"]}),c&&T("span",{className:"chisel-attachment-error",role:"alert",children:c})]}),te=t.length>0&&T("div",{className:"chisel-attachment-previews",children:t.map(I=>Le("div",{className:"chisel-attachment-preview","data-state":I.status,children:[T(ee,{src:I.preview,name:I.name,mimeType:I.mimeType}),T("span",{title:I.name,children:I.name}),T("button",{type:"button","aria-label":`Remove ${I.name}`,disabled:u||e,onClick:()=>{x(I.id)},children:T(q,{size:16,strokeWidth:1.75})})]},I.id))});return{attachments:t,uploading:u,blocked:u||F,controls:ae,previewsUI:te,clear:n,upload:R,previews:t.map(({id:I,name:g,mimeType:b,size:B,preview:oe})=>({id:I,name:g,mimeType:b,size:B,previewUrl:oe})),tokens:t.flatMap(I=>I.token?[I.token]:[])}}var Ve=new WeakMap;async function Aa(e,a,o){let t=Ve.get(e);if(!t){let u=await a.userId();if(!u)throw new Error("Sign in again to save the snapshot.");let r=crypto.randomUUID();t={id:r,name:e.name,mimeType:e.type,size:e.size,file:e,bucket:"chisel-review-images",path:`${u}/${r}`,preview:"",stored:!1,status:"uploading"},Ve.set(e,t)}let l=t.token??await a.send(t,t.stored,()=>!0);if(!l)throw new Error("The snapshot upload was incomplete.");t.token=l,await o(l)}export{Z as ReviewAttachmentButton,He as ReviewBody,ha as ReviewComposer,J as ReviewEditor,Sa as ReviewThread,fe as bodyToEditor,Te as createReviewEditor,re as displayedActivity,ve as editorToBody,Aa as uploadSnapshot,wa as useReadQueue,ya as useReviewAttachments};
|
|
4
4
|
/*! Bundled license information:
|
|
5
5
|
|
|
6
6
|
lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs:
|
|
@@ -16,6 +16,7 @@ lucide-react/dist/esm/context.mjs:
|
|
|
16
16
|
lucide-react/dist/esm/Icon.mjs:
|
|
17
17
|
lucide-react/dist/esm/createLucideIcon.mjs:
|
|
18
18
|
lucide-react/dist/esm/icons/arrow-up.mjs:
|
|
19
|
+
lucide-react/dist/esm/icons/download.mjs:
|
|
19
20
|
lucide-react/dist/esm/icons/paperclip.mjs:
|
|
20
21
|
lucide-react/dist/esm/icons/pencil.mjs:
|
|
21
22
|
lucide-react/dist/esm/icons/play.mjs:
|
|
@@ -7,11 +7,12 @@ export type WorkspaceComposerProps = {
|
|
|
7
7
|
onText(value: string): void;
|
|
8
8
|
disabled: boolean;
|
|
9
9
|
commentId?: string;
|
|
10
|
+
draftKey?: string;
|
|
10
11
|
onAttachmentDraftChange?(hasDraft: boolean): void;
|
|
11
12
|
onSubmit(text: string, body?: unknown, attachmentTokens?: string[], attachments?: WorkspaceAttachment[]): Promise<boolean>;
|
|
12
13
|
renderContent(editor: ReactNode, hasAttachments?: boolean, uploading?: boolean, actions?: ReactNode): ReactNode;
|
|
13
14
|
};
|
|
14
|
-
export default function CommentBox({ target, text, onText, onCancel, onPost, style, changes, editing, commentId, renderComposer, hasExistingAttachments, onDraftChange, hidden }: {
|
|
15
|
+
export default function CommentBox({ target, text, onText, onCancel, onPost, style, changes, editing, commentId, renderComposer, hasExistingAttachments, onDraftChange, hidden, draftKey, onDiscard }: {
|
|
15
16
|
target: Element | null;
|
|
16
17
|
text: string;
|
|
17
18
|
onText(value: string): void;
|
|
@@ -25,4 +26,6 @@ export default function CommentBox({ target, text, onText, onCancel, onPost, sty
|
|
|
25
26
|
commentId?: string;
|
|
26
27
|
renderComposer?: (props: WorkspaceComposerProps) => ReactNode;
|
|
27
28
|
onDraftChange?(hasDraft: boolean): void;
|
|
29
|
+
draftKey?: string;
|
|
30
|
+
onDiscard?(): Promise<boolean>;
|
|
28
31
|
}): import("react").JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StyleChange } from "./style-changes";
|
|
2
|
+
import type { PreviewBreakpoint } from "./breakpoints";
|
|
2
3
|
export type CommentArea = {
|
|
3
4
|
x: number;
|
|
4
5
|
y: number;
|
|
@@ -28,6 +29,13 @@ export type WorkspaceAttachment = {
|
|
|
28
29
|
size: number;
|
|
29
30
|
previewUrl?: string;
|
|
30
31
|
};
|
|
32
|
+
export type CommentContext = {
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
url: string;
|
|
36
|
+
capturedAt: string;
|
|
37
|
+
deployment?: string;
|
|
38
|
+
};
|
|
31
39
|
export type WorkspaceReply = {
|
|
32
40
|
id?: string;
|
|
33
41
|
text: string;
|
|
@@ -42,6 +50,12 @@ export type WorkspaceReply = {
|
|
|
42
50
|
export type WorkspaceComment = CommentAnchor & {
|
|
43
51
|
id: string;
|
|
44
52
|
path: string;
|
|
53
|
+
breakpoint?: PreviewBreakpoint;
|
|
54
|
+
context?: CommentContext;
|
|
55
|
+
status?: "open" | "ready" | "resolved";
|
|
56
|
+
statusBy?: string;
|
|
57
|
+
statusAt?: string;
|
|
58
|
+
reviewRoundId?: string;
|
|
45
59
|
text: string;
|
|
46
60
|
author: string;
|
|
47
61
|
authorId?: string;
|
|
@@ -82,6 +96,14 @@ export type CommentMutation = {
|
|
|
82
96
|
type: "resolve";
|
|
83
97
|
id: string;
|
|
84
98
|
resolved: boolean;
|
|
99
|
+
} | {
|
|
100
|
+
type: "status";
|
|
101
|
+
id: string;
|
|
102
|
+
status: "open" | "ready" | "resolved";
|
|
103
|
+
} | {
|
|
104
|
+
type: "snapshot";
|
|
105
|
+
id: string;
|
|
106
|
+
attachmentTokens: string[];
|
|
85
107
|
};
|
|
86
108
|
export type CommentStore = {
|
|
87
109
|
list(): Promise<WorkspaceComment[]>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ReviewProject = {
|
|
2
|
+
siteId: string;
|
|
3
|
+
name: string;
|
|
4
|
+
role: string;
|
|
5
|
+
reviewURL: string | null;
|
|
6
|
+
reviewers: {
|
|
7
|
+
email: string;
|
|
8
|
+
role: string;
|
|
9
|
+
}[];
|
|
10
|
+
round: {
|
|
11
|
+
id: string;
|
|
12
|
+
deployment: string;
|
|
13
|
+
reviewURL: string;
|
|
14
|
+
createdAt: string;
|
|
15
|
+
outstanding: number;
|
|
16
|
+
approvals: number;
|
|
17
|
+
approvedByMe: boolean;
|
|
18
|
+
} | null;
|
|
19
|
+
};
|
|
20
|
+
export type ManageReview = (action: string, payload?: Record<string, unknown>) => Promise<ReviewProject>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WorkspaceComment } from "./comments";
|
|
2
|
+
export declare function publicReviewURL(value: string): string | null;
|
|
3
|
+
export declare function commentURL(base: string, comment: WorkspaceComment): string;
|
|
4
|
+
export declare function feedbackMarkdown(comments: WorkspaceComment[], base: string): string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { type WorkspaceComposerProps } from "./comment-box";
|
|
3
|
+
import type { ManageReview } from "./project-controls";
|
|
3
4
|
import { type WorkspaceAttachment, type WorkspaceComment as Comment, type CommentStore } from "./comments";
|
|
4
5
|
export type WorkspaceUser = {
|
|
5
6
|
id: string;
|
|
@@ -26,6 +27,7 @@ export type WorkspaceThreadProps = {
|
|
|
26
27
|
saving: boolean;
|
|
27
28
|
canResolve: boolean;
|
|
28
29
|
submittingReply?: boolean;
|
|
30
|
+
draftKey?: string;
|
|
29
31
|
userId?: string;
|
|
30
32
|
onEdit?(replyId: string | null, text: string, body: unknown): Promise<boolean>;
|
|
31
33
|
onEditDraftChange?(hasDraft: boolean): void;
|
|
@@ -45,7 +47,7 @@ export type WorkspaceCommentUI = {
|
|
|
45
47
|
renderThread(props: WorkspaceThreadProps): ReactNode;
|
|
46
48
|
};
|
|
47
49
|
export declare function elementSelector(element: Element): string;
|
|
48
|
-
export default function ChiselWorkspace({ user, validateSession, signOut, commentStore, canManageComments, getReviewLink, collaboration, commentUI }: {
|
|
50
|
+
export default function ChiselWorkspace({ user, validateSession, signOut, commentStore, canManageComments, getReviewLink, collaboration, commentUI, projectId, manageReview, accountURL, agentURL, saveSnapshot, getAttachmentURL }: {
|
|
49
51
|
user: WorkspaceUser;
|
|
50
52
|
validateSession: () => Promise<boolean>;
|
|
51
53
|
signOut: () => Promise<void>;
|
|
@@ -54,4 +56,10 @@ export default function ChiselWorkspace({ user, validateSession, signOut, commen
|
|
|
54
56
|
getReviewLink?: (rotate?: boolean) => Promise<string>;
|
|
55
57
|
collaboration?: WorkspaceCollaboration;
|
|
56
58
|
commentUI?: WorkspaceCommentUI;
|
|
59
|
+
projectId?: string;
|
|
60
|
+
manageReview?: ManageReview;
|
|
61
|
+
accountURL?: string;
|
|
62
|
+
agentURL?: string;
|
|
63
|
+
saveSnapshot?: (id: string, file: File) => Promise<void>;
|
|
64
|
+
getAttachmentURL?: (id: string) => Promise<string>;
|
|
57
65
|
}): import("react").JSX.Element;
|
|
@@ -2,5 +2,6 @@ export { default as ChiselWorkspace } from "./workspace/workspace";
|
|
|
2
2
|
export type { WorkspaceUser, WorkspaceCollaboration, WorkspaceCommentUI, WorkspaceThreadProps } from "./workspace/workspace";
|
|
3
3
|
export { ChiselPreview } from "./workspace/preview";
|
|
4
4
|
export { ChiselWorkspaceStyles } from "./workspace/styles";
|
|
5
|
-
export type { CommentStore, CommentMutation, CommentArea, WorkspaceComment, WorkspaceReply, WorkspaceAttachment } from "./workspace/comments";
|
|
5
|
+
export type { CommentStore, CommentMutation, CommentArea, CommentContext, WorkspaceComment, WorkspaceReply, WorkspaceAttachment } from "./workspace/comments";
|
|
6
|
+
export type { ManageReview, ReviewProject } from "./workspace/project-controls";
|
|
6
7
|
export type { WorkspaceComposerProps } from "./workspace/comment-box";
|