use-chisel 0.1.9 → 0.1.11
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 Je,createElement as Qe}from"react";var Ce=e=>e?.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();function he(e,a,o=[]){if(a==null)throw new Error("[lucide]: iconNode is required when icon name is used");return{name:Ce(e),size:24,node:a,...o.length>0?{aliases:o}:{}}}var ge=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 Se=e=>{let a=ge(e);return a.charAt(0).toUpperCase()+a.slice(1)};import{forwardRef as Ze,createElement as Ae}from"react";var W=(...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 re(e){return e!=null}function ke(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}`)??[],n=[...e.name?[`lucide-${e.name}`]:[],...r],i=a.className?.split(" ").filter(Boolean)??[],I=a.includeDefaultClasses===!1?W(...i):W("lucide",...n,...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,c])=>(d[t(f)]=c,d),{}),..."color"in a&&a.color&&{[t("stroke")]:a.color},..."size"in a&&re(a.size)&&{[t("width")]:a.size,[t("height")]:a.size},..."width"in a&&re(a.width)&&{[t("width")]:a.width},..."height"in a&&re(a.height)&&{[t("height")]:a.height},[t("stroke-width")]:s,...I&&{[t("class")]:I},[t("viewBox")]:`0 0 ${l} ${u}`,...a.hasA11yProp===!1?{[t("aria-hidden")]:"true"}:{},..."attributes"in a&&a.attributes},e.node.map(d=>{let[f,c,x]=d,g=a.nonScalingStroke?{[t("vector-effect")]:"non-scaling-stroke",...c}:c;return x?[f,g,x]:[f,g]})]}function we(e,a={}){return ke(e,{...a,attributeNames:{...a.attributeNames,class:"className","stroke-width":"strokeWidth","stroke-linecap":"strokeLinecap","stroke-linejoin":"strokeLinejoin","vector-effect":"vectorEffect"}})}var Pe=e=>{for(let a in e)if(a.startsWith("aria-")||a==="role"||a==="title")return!0;return!1};import{createContext as Ne,useContext as Xe,useMemo as za,createElement as Na}from"react";var Ke=Ne({});var ye=()=>Xe(Ke);var Be=Ze(({color:e,size:a,width:o,height:t,strokeWidth:l,absoluteStrokeWidth:u,nonScalingStroke:r,className:n="",children:i,iconNode:I=[],icon:s={node:I,aliases:[],size:24},...L},d)=>{let{size:f=24,strokeWidth:c=2,absoluteStrokeWidth:x=!1,nonScalingStroke:g=!1,color:b="currentColor",className:O=""}=ye()??{},S=!!i||Pe(L),[F,oe,ue=[]]=we(s,{color:e??b,width:o??a??f,height:t??a??f,strokeWidth:l??c,absoluteStrokeWidth:u??x,nonScalingStroke:r??g,className:W(O,n),hasA11yProp:S,attributes:L});return Ae(F,{ref:d,...oe},[...ue.map(([p,h])=>Ae(p,h)),...Array.isArray(i)?i:[i]])});function k(e,a=[],o=[]){let t=typeof e=="string"?he(e,a,o):e,l=Je(({className:u,...r},n)=>Qe(Be,{ref:n,icon:t,className:u,...r}));return t.name&&(l.displayName=Se(t.name)),l}var $e={name:"arrow-up",size:24,node:[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]},V=k($e);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"}]]},z=k(_e);var je={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"}]]},N=k(je);var Ye={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"}]]},X=k(Ye);var ea={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"}]]},K=k(ea);var aa={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"}]]},Z=k(aa);var ta={name:"x",size:24,node:[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]},q=k(ta);import{useEffect as U,useRef as y,useState as $}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 j(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 se(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 E(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 fe(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 Y=["image/jpeg","image/png","image/gif","image/webp","image/avif","image/bmp"],De=["video/mp4","video/webm","video/quicktime"],Me=[...Y,...De].join(",");function be(e){let a=Y.includes(e.type);return!a&&!De.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 oa,useRef as Fe,useState as Re}from"react";import{createEditor as ua,Editor as C,Element as G,Node as da,Path as la,Range as ie,Transforms as M}from"slate";import{withHistory as ra}from"slate-history";import{Editable as sa,Slate as fa,withReact as ia,ReactEditor as ve}from"slate-react";import{Fragment as Ue,jsx as w,jsxs as Oe}from"react/jsx-runtime";function ce(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 Te(e){return{version:1,content:e.map(a=>({type:"paragraph",children:G.isElement(a)?a.children.map(o=>G.isElement(o)?{type:"link",url:o.url,text:da.string(o)}:{...o}):[{text:a.text}]}))}}function ne(e){return/^(https?:\/\/|mailto:)[^\s]+$/i.test(e)}function ca(e,a){if(!e.selection){let o=window.getSelection(),t=o&&ve.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 qe(){let e=ia(ra(ua()),"application/x-chisel-review-fragment"),{isInline:a,insertText:o,insertData:t,insertBreak:l}=e;e.isInline=n=>n.type==="link"||a(n);function u(n,i){C.above(e,{at:n,match:I=>G.isElement(I)&&I.type==="link"})||(M.wrapNodes(e,{type:"link",url:i,children:[]},{at:n,split:!0}),M.collapse(e,{edge:"end"}))}function r(){if(!e.selection||!ie.isCollapsed(e.selection))return;let n=C.above(e,{match:d=>G.isElement(d)&&d.type==="paragraph"});if(!n)return;let i=e.selection.anchor,s=C.string(e,{anchor:C.start(e,n[1]),focus:i}).match(/\S+$/)?.[0];if(!s||!ne(s))return;let L=C.before(e,i,{distance:s.length,unit:"offset"});if(L){u({anchor:L,focus:i},s);let d=C.above(e,{match:f=>G.isElement(f)&&f.type==="link"});d&&e.selection&&C.isEnd(e,e.selection.anchor,d[1])&&M.select(e,C.start(e,la.next(d[1])))}}return e.insertText=n=>{if(ve.isComposing(e)){o(n);return}n===" "&&r();let i={"*":"bold",_:"italic","~":"strikethrough","`":"code"}[n];if(i&&e.selection&&ie.isCollapsed(e.selection)){let I=C.above(e,{match:s=>G.isElement(s)&&s.type==="paragraph"});if(I){let s=e.selection.anchor,L=C.string(e,{anchor:C.start(e,I[1]),focus:s}),d=L.lastIndexOf(n),f=L.slice(d+1);if(d>=0&&(!d||/[\s*_~`]/.test(L[d-1]))&&f&&f.trim()===f){let c=C.before(e,s,{distance:f.length,unit:"offset"}),x=c&&C.before(e,c,{unit:"offset"});if(c&&x){M.select(e,{anchor:c,focus:s}),C.addMark(e,i,!0),M.collapse(e,{edge:"end"}),M.delete(e,{at:{anchor:x,focus:c}}),C.removeMark(e,i);return}}}}o(n)},e.insertBreak=()=>{r(),l()},e.insertData=n=>{let i=n.getData("text/plain");ne(i)?e.selection&&!ie.isCollapsed(e.selection)?u(e.selection,i):M.insertNodes(e,[{type:"link",url:i,children:[{text:i}]},{text:""}]):t(n)},e}function na({attributes:e,children:a,element:o}){return o.type==="link"?w("a",{...e,href:ne(o.url)?o.url:void 0,onClick:t=>t.preventDefault(),children:a}):w("p",{...e,children:a})}function pa({attributes:e,children:a,leaf:o}){let t=w(Ue,{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 J({onFiles:e,disabled:a}){let o=Fe(null);return Oe(Ue,{children:[w("input",{ref:o,type:"file",accept:Me,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(N,{size:16,strokeWidth:1.75})})]})}function Q({text:e,defaultBody:a,disabled:o,label:t,placeholder:l,autoFocus:u,onChange:r,onSubmit:n,onFiles:i,uploading:I}){let[s]=Re(qe),[L]=Re(()=>ce(a??D(e))),d=Fe(e);return oa(()=>{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:(c,x)=>x.length===1}),M.insertNodes(s,ce(D(e)),{at:[0]}),M.deselect(s)}),e||(s.history={undos:[],redos:[]}))},[s,e]),Oe(fa,{editor:s,initialValue:L,onChange:f=>{if(!s.operations.some(x=>x.type!=="set_selection"))return;let c=Te(f);d.current=_(c),r(d.current,c)},children:[w(sa,{className:"review-composer-editor",role:"textbox","aria-multiline":"true","aria-label":t,placeholder:l,readOnly:o,autoFocus:u,renderElement:na,renderLeaf:pa,onKeyDown:f=>{if(f.nativeEvent.isComposing)return;let c=f.metaKey||f.ctrlKey;if(f.key==="Enter"){f.preventDefault(),c?s.insertBreak():n();return}let x=c?{b:"bold",i:"italic",e:"code",...f.shiftKey?{s:"strikethrough"}:{}}[f.key.toLowerCase()]:void 0;x&&(f.preventDefault(),ca(s,x))}}),i&&w("div",{className:"chisel-attachment-controls",children:w(J,{onFiles:i,disabled:o||I})})]})}import{useEffect as ma,useRef as La,useState as Ia}from"react";import{Fragment as He,jsx as P,jsxs as ee}from"react/jsx-runtime";function xa({src:e,name:a,mimeType:o,onError:t,close:l}){let u=La(null);return ma(()=>{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:ee("div",{className:"review-media-lightbox-content",children:[ee("header",{children:[P("span",{children:a}),P("a",{href:e,download:a,"aria-label":`Download ${a}`,title:"Download",children:P(z,{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 ae({src:e,name:a,mimeType:o,onError:t}){let[l,u]=Ia(!1);return ee(He,{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}):ee(He,{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(K,{size:20,fill:"currentColor"})})]})}),l&&P(xa,{src:e,name:a,mimeType:o,onError:t,close:()=>u(!1)})]})}import{Fragment as wa,jsx as m,jsxs as A}from"react/jsx-runtime";function pe(e,a,o){if(e)try{let t=se(e);if(t?.text===a&&_(t.body)===a)return t.body}catch{}return o??D(a)}function me(e,a,o,t=!1){e&&E(e,t||a.trim()?{text:a,body:o}:null)}function Ee({body:e}){return m("div",{className:"review-comment-body",children:e.content.map((a,o)=>m("p",{children:a.children.map((t,l)=>{if("type"in t&&t.type==="link")return m("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=m(wa,{children:t.text});return"bold"in t&&t.bold&&(u=m("strong",{children:u})),"italic"in t&&t.italic&&(u=m("em",{children:u})),"strikethrough"in t&&t.strikethrough&&(u=m("s",{children:u})),"code"in t&&t.code&&(u=m("code",{children:u})),m("span",{children:u},l)})},o))})}function Ca({attachment:e,loadMedia:a}){let[o,t]=$(e.previewUrl??""),[l,u]=$(!1),[r,n]=$(0),i=y(0);U(()=>{if(e.previewUrl){t(e.previewUrl);return}t("");let s=!0,L=!1,d=new AbortController;async function f(){if(!(L||document.visibilityState==="hidden")){L=!0;try{let g=await a(e.id,d.signal);s&&(t(g),u(!1),i.current=Date.now()+240*1e3)}catch{s&&u(!0)}finally{L=!1}}}function c(){Date.now()>=i.current&&f()}f();let x=window.setInterval(c,60*1e3);return window.addEventListener("focus",c),document.addEventListener("visibilitychange",c),()=>{s=!1,d.abort(),window.clearInterval(x),window.removeEventListener("focus",c),document.removeEventListener("visibilitychange",c)}},[e.id,e.previewUrl,r,a]);function I(){u(!0),Date.now()>=i.current&&n(s=>s+1)}return A("figure",{className:"review-attachment",children:[o&&!l?m(ae,{src:o,name:e.name,mimeType:e.mimeType,onError:I}):m("div",{className:"review-attachment-placeholder",role:"status",children:l?m("button",{type:"button",className:"review-retry-upload",onClick:()=>n(s=>s+1),children:"Retry attachment"}):"Loading attachment\u2026"}),m("figcaption",{children:e.name})]})}function Ge(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 ha({comment:e,activity:a,loadMedia:o,editable:t,editing:l,saving:u,onStartEdit:r,onCancelEdit:n,onSaveEdit:i,onDraftChange:I,onEditStyles:s,draftKey:L}){let[d,f]=$(e.text),c=y(e.body??D(e.text)),x=y(!1),g=l&&!(u&&x.current),b=y(!1);U(()=>{l?I(d!==e.text||JSON.stringify(c.current)!==JSON.stringify(e.body??D(e.text))):b.current&&L&&E(L,null),b.current=l},[l]),U(()=>{l||(f(e.text),c.current=e.body??D(e.text))},[l,e.text,e.body]);async function O(){if(!(u||x.current||!d.trim()&&!e.attachments?.length)){x.current=!0;try{await i(d.trimEnd(),j(c.current))&&(L&&E(L,null),I(!1))}finally{x.current=!1}}}return A("article",{className:"review-comment","data-activity":a,children:[m("span",{className:"review-comment-avatar",children:e.authorImage?m("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:[m("span",{className:"review-comment-author",children:e.author}),e.pending?m("span",{className:"review-comment-time",role:"status",children:"Sending\u2026"}):m("time",{className:"review-comment-time",dateTime:e.date,title:new Date(e.date).toLocaleString(),children:Ge(e.date)}),t&&!l&&m("button",{type:"button",className:"review-comment-edit","aria-label":"Edit comment",title:"Edit comment",disabled:u,onClick:()=>{let S=L?se(L):null;S&&typeof S.text=="string"&&(f(S.text),c.current=pe(L,S.text)),r()},children:m(X,{size:16})})]}),g?A("form",{className:"review-inline-edit",onSubmit:S=>{S.preventDefault(),O()},children:[m(Q,{text:d,defaultBody:c.current,disabled:u,label:"Edit comment",placeholder:"Edit comment\u2026",autoFocus:!0,onSubmit:()=>{O()},onChange:(S,F)=>{f(S),c.current=F,me(L,S,F,!0),I(S!==e.text||JSON.stringify(F)!==JSON.stringify(e.body??D(e.text)))}}),A("div",{className:"review-inline-edit-actions",children:[s&&m("button",{type:"button",disabled:u,onClick:s,children:"Edit styles"}),m("button",{type:"button",disabled:u,onClick:n,children:"Cancel"}),m("button",{type:"submit",disabled:u||!d.trim()&&!e.attachments?.length,children:"Save"})]})]}):m(Ee,{body:e.body??D(e.text)}),e.attachments?.length>0&&m("div",{className:"review-attachments",children:e.attachments.map(S=>m(Ca,{attachment:S,loadMedia:o},S.id))})]})]})}function ga(e){let a=e.useAttachments(e.disabled,e.existingAttachments?.length??0),o=y(pe(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(),j(o.current),a.tokens,a.previews)&&(e.draftKey&&E(e.draftKey,null),a.clear())}finally{t.current=!1}}}return m("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:[m(Q,{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,me(e.draftKey,u,r),e.onText(u)}}),a.previewsUI,a.controls]}),a.attachments.length>0||!!e.existingAttachments?.length,a.blocked,m(J,{onFiles:a.upload,disabled:e.disabled||a.uploading}))})}function Sa(e){let a=e.useAttachments(e.saving),o=y(pe(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(),j(o.current),a.tokens,a.previews)&&(e.draftKey&&E(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:[m("span",{className:"feedback-avatar feedback-reply-avatar",children:e.replyAuthor?.image?m("img",{src:e.replyAuthor.image,alt:""}):(e.replyAuthor?.name||"You").slice(0,1).toUpperCase()}),A("div",{className:"chisel-reply-field",children:[m(Q,{text:e.reply,defaultBody:o.current,disabled:e.saving,label:"Reply",placeholder:"Write a reply\u2026",onSubmit:()=>{l()},onChange:(u,r)=>{o.current=r,me(e.draftKey,u,r),e.onReplyText(u)}}),a.previewsUI,a.controls,m("div",{className:"chisel-attachment-controls",children:m(J,{onFiles:a.upload,disabled:e.saving||a.uploading})}),m("button",{type:"submit",className:"chisel-reply-submit","aria-label":"Reply",disabled:e.saving||a.blocked||!e.reply.trim()&&!a.attachments.length,children:m(V,{size:16,strokeWidth:1.75})})]})]})}function ka(e){let a=e.comment,[o,t]=$(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 n(d){d&&e.onBeginEdit&&!await e.onBeginEdit()||!d&&l.current&&e.onDiscardEdit&&!await e.onDiscardEdit()||(r(!1),t(d))}function i(d,f){return m(ha,{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:()=>{n(d.id)},onCancelEdit:()=>{n(null)},onDraftChange:r,onSaveEdit:async(c,x)=>{let g=await e.onEdit?.(f?null:d.id,c,x);return g&&(r(!1),t(null)),!!g}},d.id)}let I=y(null),s=y(new Set),L=y(a.readActivity??0);return U(()=>{if(!e.expanded||!I.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 b of x)b.isIntersecting&&b.intersectionRatio>0&&s.current.add(Number(b.target.dataset.activity));let g=fe(Math.max(L.current,a.readActivity??0),d,s.current);g>L.current&&(L.current=g,e.onRead(a.id,g))},{threshold:0});function c(){if(f.disconnect(),document.visibilityState==="visible")for(let x of I.current?.querySelectorAll("[data-activity]")??[])f.observe(x)}return c(),document.addEventListener("visibilitychange",c),()=>{f.disconnect(),document.removeEventListener("visibilitychange",c)}},[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 ",Ge(a.context.capturedAt)]})]}),A("div",{ref:I,className:"review-thread",children:[i(a,!0),e.expanded&&a.replies.map(d=>i(d,!1))]}),e.expanded?!o&&m(Sa,{...e}):m("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 We,useRef as Ve}from"react";function Pa(e,a){let o=Ve(new Map),t=Ve(!1),l=We(async()=>{if(!t.current){t.current=!0;try{for(;o.current.size;){let[r,n]=o.current.entries().next().value;try{await e(r,n)}catch(i){if([400,403,404].includes(i.status??0)){o.current.delete(r);continue}throw i}o.current.get(r)===n&&o.current.delete(r),a(r,n)}}catch{}finally{t.current=!1}}},[e,a]),u=We((r,n)=>{o.current.set(r,Math.max(n,o.current.get(r)??0)),l()},[l]);return{flush:l,markDisplayed:u}}import{useEffect as ya,useRef as te,useState as Le}from"react";import{jsx as T,jsxs as Ie}from"react/jsx-runtime";function Aa(e=!1,a=0,o){let[t,l]=Le([]),[u,r]=Le(!1),[n,i]=Le(""),I=te(!0),s=te(!1),L=te(new Map),d=te(null),f=p=>o.discard(p);ya(()=>(I.current=!0,()=>{I.current=!1;for(let p of L.current.values())URL.revokeObjectURL(p.preview),f(p).catch(()=>{})}),[]);function c(){I.current&&l([...L.current.values()].filter(p=>p.id!==d.current).map(p=>({...p})))}function x(){for(let p of L.current.values())URL.revokeObjectURL(p.preview);L.current.clear(),I.current&&(l([]),i(""))}async function g(p){let h=L.current.get(p);if(!(!h||s.current||e)){s.current=!0,r(!0),d.current=p,c();try{await f(h),L.current.delete(p),URL.revokeObjectURL(h.preview),c(),i("")}catch(R){I.current&&i(R instanceof Error?R.message:"The attachment could not be removed.")}finally{d.current=null,s.current=!1,c(),I.current&&r(!1)}}}async function b(p){for(let h of p){if(!I.current)return;let R=h.status==="failed";h.status="uploading",c();try{h.token=await o.send(h,R,()=>I.current),h.status="ready"}catch(B){h.status="failed",I.current&&i(B instanceof Error?B.message:"The upload failed. Your comment is still here.")}finally{I.current||await f(h).catch(()=>{})}c()}}async function O(p){if(!p?.length||s.current||e)return;let h=Array.from(p),R=h.map(B=>be(B)).find(Boolean);if(R){i(R);return}if(a+L.current.size+h.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(!I.current)return;let de=h.map(H=>{let le=crypto.randomUUID(),xe={id:le,name:H.name,mimeType:H.type,size:H.size,file:H,bucket:Y.includes(H.type)?"chisel-review-images":"chisel-review-videos",path:`${B}/${le}`,preview:URL.createObjectURL(H),stored:!1,status:"uploading"};return L.current.set(le,xe),xe});c(),await b(de)}catch(B){I.current&&i(B instanceof Error?B.message:"The upload failed. Your comment is still here.")}finally{s.current=!1,I.current&&r(!1)}}async function S(){if(!(s.current||e)){s.current=!0,r(!0),i("");try{await b([...L.current.values()].filter(p=>p.status==="failed"))}finally{s.current=!1,I.current&&r(!1)}}}let F=t.some(p=>p.status==="failed"),oe=Ie("div",{className:"chisel-attachment-controls",children:[u&&T("span",{role:"status",children:"Uploading\u2026"}),F&&Ie("button",{type:"button",className:"review-retry-upload",disabled:u||e,onClick:()=>{S()},children:[T(Z,{size:16,strokeWidth:1.75}),"Retry upload"]}),n&&T("span",{className:"chisel-attachment-error",role:"alert",children:n})]}),ue=t.length>0&&T("div",{className:"chisel-attachment-previews",children:t.map(p=>Ie("div",{className:"chisel-attachment-preview","data-state":p.status,children:[T(ae,{src:p.preview,name:p.name,mimeType:p.mimeType}),T("span",{title:p.name,children:p.name}),T("button",{type:"button","aria-label":`Remove ${p.name}`,disabled:u||e,onClick:()=>{g(p.id)},children:T(q,{size:16,strokeWidth:1.75})})]},p.id))});return{attachments:t,uploading:u,blocked:u||F,controls:oe,previewsUI:ue,clear:x,upload:O,previews:t.map(({id:p,name:h,mimeType:R,size:B,preview:de})=>({id:p,name:h,mimeType:R,size:B,previewUrl:de})),tokens:t.flatMap(p=>p.token?[p.token]:[])}}var ze=new WeakMap;async function Ba(e,a,o){let t=ze.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"},ze.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{J as ReviewAttachmentButton,Ee as ReviewBody,ga as ReviewComposer,Q as ReviewEditor,ka as ReviewThread,ce as bodyToEditor,qe as createReviewEditor,fe as displayedActivity,Te as editorToBody,Ba as uploadSnapshot,Pa as useReadQueue,Aa 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";
|