@corva/ui 3.75.0-14 → 3.75.0-16
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/cjs-bundle/components/AttachmentPreview/useStoredAttachments.js +1 -1
- package/cjs-bundle/components/AttachmentPreview/useStoredAttachments.js.map +1 -1
- package/cjs-bundle/components/CommentComposer/useAttachmentUpload.js +1 -1
- package/cjs-bundle/components/CommentComposer/useAttachmentUpload.js.map +1 -1
- package/cjs-bundle/componentsV2/DatePicker/Input/Input.js +1 -1
- package/cjs-bundle/componentsV2/DatePicker/Input/Input.js.map +1 -1
- package/cjs-bundle/componentsV2/DatePicker/utils.js +1 -1
- package/cjs-bundle/componentsV2/DatePicker/utils.js.map +1 -1
- package/cjs-bundle/effects/useSignedURL.js +1 -1
- package/cjs-bundle/effects/useSignedURL.js.map +1 -1
- package/cjs-bundle/utils/signedLinkCache.js +2 -0
- package/cjs-bundle/utils/signedLinkCache.js.map +1 -0
- package/components/AttachmentPreview/useStoredAttachments.d.ts.map +1 -1
- package/components/AttachmentPreview/useStoredAttachments.js +1 -1
- package/components/AttachmentPreview/useStoredAttachments.js.map +1 -1
- package/components/CommentComposer/useAttachmentUpload.d.ts.map +1 -1
- package/components/CommentComposer/useAttachmentUpload.js +1 -1
- package/components/CommentComposer/useAttachmentUpload.js.map +1 -1
- package/components/Drillstring/BHAComponentDetail/constants.d.ts +2 -2
- package/componentsV2/DatePicker/Input/Input.d.ts.map +1 -1
- package/componentsV2/DatePicker/Input/Input.js +1 -1
- package/componentsV2/DatePicker/Input/Input.js.map +1 -1
- package/componentsV2/DatePicker/utils.d.ts +8 -1
- package/componentsV2/DatePicker/utils.d.ts.map +1 -1
- package/componentsV2/DatePicker/utils.js +1 -1
- package/componentsV2/DatePicker/utils.js.map +1 -1
- package/effects/useSignedURL.d.ts +1 -1
- package/effects/useSignedURL.d.ts.map +1 -1
- package/effects/useSignedURL.js +1 -1
- package/effects/useSignedURL.js.map +1 -1
- package/mcp-server/server.mjs +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/utils/__tests__/signedLinkCache.test.d.ts +2 -0
- package/utils/__tests__/signedLinkCache.test.d.ts.map +1 -0
- package/utils/signedLinkCache.d.ts +9 -0
- package/utils/signedLinkCache.d.ts.map +1 -0
- package/utils/signedLinkCache.js +2 -0
- package/utils/signedLinkCache.js.map +1 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/defineProperty"),r=require("@babel/runtime/helpers/slicedToArray"),t=require("@babel/runtime/helpers/asyncToGenerator"),n=require("@babel/runtime/regenerator"),u=require("react"),c=require("./getAttachmentKind.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/defineProperty"),r=require("@babel/runtime/helpers/slicedToArray"),t=require("@babel/runtime/helpers/asyncToGenerator"),n=require("@babel/runtime/regenerator"),u=require("react"),c=require("./getAttachmentKind.js"),i=require("./useStoredAttachment.js"),a=require("../../utils/signedLinkCache.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=o(e),f=o(r),l=o(t),p=o(n);function d(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function m(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?d(Object(t),!0).forEach((function(r){s.default(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):d(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}var b=function(){var e=l.default(p.default.mark((function e(r){return p.default.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,a.getSignedLink(r,"inline");case 3:return e.abrupt("return",e.sent);case 6:return e.prev=6,e.t0=e.catch(0),console.error('Failed to sign attachment "'.concat(r,'"'),e.t0),e.abrupt("return","");case 10:case"end":return e.stop()}}),e,null,[[0,6]])})));return function(r){return e.apply(this,arguments)}}();exports.useStoredAttachments=function(e){var r=u.useState((function(){return function(e){return e.reduce((function(e,r){var t=i.getIsStoredKey(r.name)?a.peekSignedLink(r.name,"inline"):r.url;return t&&(e[r.name]={src:t}),e}),{})}(null!=e?e:[])})),t=f.default(r,2),n=t[0],o=t[1],l=u.useRef(n);l.current=n;var p=u.useMemo((function(){return null!=e?e:[]}),[e]),d=p.map((function(e){return e.name})).join("|");return u.useEffect((function(){var e=p.filter((function(e){return!(e.name in l.current)}));if(e.length){var r=!0,t=function(e,r){return o((function(t){return m(m({},t),{},s.default({},e,m(m({},t[e]),r)))}))};return o((function(r){var t=m({},r);return e.forEach((function(e){var r;t[e.name]=null!==(r=t[e.name])&&void 0!==r?r:{}})),t})),e.forEach((function(e){i.getIsStoredKey(e.name)?b(e.name).then((function(n){r&&n&&t(e.name,{src:n})})):t(e.name,{src:e.url})})),function(){r=!1}}}),[d]),p.reduce((function(e,r){var t=n[r.name];return null!=t&&t.src?(e.push({id:r.url,name:r.name,src:t.src,kind:c.getAttachmentKind(r),size:r.size}),e):e}),[])};
|
|
2
2
|
//# sourceMappingURL=useStoredAttachments.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStoredAttachments.js","sources":["../../../../src/components/AttachmentPreview/useStoredAttachments.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { AttachmentPreviewItem } from './AttachmentPreview.types';\nimport { getAttachmentKind } from './getAttachmentKind';\nimport { getIsStoredKey, type StoredAttachment } from './useStoredAttachment';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useStoredAttachments.js","sources":["../../../../src/components/AttachmentPreview/useStoredAttachments.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { AttachmentPreviewItem } from './AttachmentPreview.types';\nimport { getAttachmentKind } from './getAttachmentKind';\nimport { getIsStoredKey, type StoredAttachment } from './useStoredAttachment';\n\nimport { getSignedLink, peekSignedLink } from '~/utils/signedLinkCache';\n\ntype SignedLinks = Record<string, { src?: string }>;\n\nconst signStoredLink = async (name: string) => {\n try {\n return await getSignedLink(name, 'inline');\n } catch (error) {\n console.error(`Failed to sign attachment \"${name}\"`, error);\n\n return '';\n }\n};\n\nconst seedLinks = (attachments: StoredAttachment[]): SignedLinks =>\n attachments.reduce<SignedLinks>((acc, attachment) => {\n const src = getIsStoredKey(attachment.name)\n ? peekSignedLink(attachment.name, 'inline')\n : attachment.url;\n if (src) acc[attachment.name] = { src };\n\n return acc;\n }, {});\n\n/**\n * Signs a whole list of stored attachments — the hook-per-file `useStoredAttachment`\n * can't cover a list whose length changes between renders.\n */\nexport const useStoredAttachments = (\n attachments?: StoredAttachment[] | null\n): AttachmentPreviewItem[] => {\n const [links, setLinks] = useState<SignedLinks>(() => seedLinks(attachments ?? []));\n const linksRef = useRef(links);\n linksRef.current = links;\n\n const list = useMemo(() => attachments ?? [], [attachments]);\n const key = list.map(attachment => attachment.name).join('|');\n\n useEffect(() => {\n const pending = list.filter(attachment => !(attachment.name in linksRef.current));\n if (!pending.length) return undefined;\n\n let isActive = true;\n\n const applyLink = (name: string, patch: SignedLinks[string]) =>\n setLinks(prev => ({ ...prev, [name]: { ...prev[name], ...patch } }));\n\n // Claim the names up front so a re-render mid-flight does not ask again.\n setLinks(prev => {\n const claimed = { ...prev };\n\n pending.forEach(attachment => {\n claimed[attachment.name] = claimed[attachment.name] ?? {};\n });\n\n return claimed;\n });\n\n pending.forEach(attachment => {\n // A linked attachment already carries a url that works; only a key of ours needs signing.\n if (!getIsStoredKey(attachment.name)) {\n applyLink(attachment.name, { src: attachment.url });\n\n return;\n }\n\n signStoredLink(attachment.name).then(src => {\n if (isActive && src) applyLink(attachment.name, { src });\n });\n });\n\n return () => {\n isActive = false;\n };\n // `key` tracks the list contents; `list` itself is a fresh array on every render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n return list.reduce<AttachmentPreviewItem[]>((acc, attachment) => {\n const link = links[attachment.name];\n if (!link?.src) return acc;\n\n acc.push({\n id: attachment.url,\n name: attachment.name,\n src: link.src,\n kind: getAttachmentKind(attachment),\n size: attachment.size,\n });\n return acc;\n }, []);\n};\n"],"names":["signStoredLink","_ref","_asyncToGenerator","_regeneratorRuntime","mark","name","wrap","_context","prev","next","getSignedLink","abrupt","sent","t0","console","error","stop","_callee","_x","apply","this","arguments","attachments","_useState","useState","reduce","acc","attachment","src","getIsStoredKey","peekSignedLink","url","seedLinks","_useState2","_slicedToArray","links","setLinks","linksRef","useRef","current","list","useMemo","key","map","join","useEffect","pending","filter","length","isActive","applyLink","patch","_objectSpread","claimed","forEach","_claimed$attachment$n","then","link","push","id","kind","getAttachmentKind","size"],"mappings":"kkCAUA,IAAMA,EAAc,WAAA,IAAAC,EAAAC,EAAAA,QAAAC,EAAAA,QAAAC,MAAG,WAAOC,GAAY,OAAAF,UAAAG,MAAA,SAAAC,GAAA,OAAA,OAAAA,EAAAC,KAAAD,EAAAE,MAAA,KAAA,EAAA,OAAAF,EAAAC,KAAA,EAAAD,EAAAE,KAAA,EAEzBC,EAAaA,cAACL,EAAM,UAAS,KAAA,EAAA,OAAAE,EAAAI,OAAA,SAAAJ,EAAAK,MAAA,KAAA,EAEkB,OAFlBL,EAAAC,KAAA,EAAAD,EAAAM,GAAAN,EAAA,MAAA,GAE1CO,QAAQC,MAAoCV,8BAAAA,OAAAA,EAAe,KAAAE,EAAAM,IAACN,EAAAI,OAAA,SAErD,IAAE,KAAA,GAAA,IAAA,MAAA,OAAAJ,EAAAS,OAAA,GAAAC,EAAA,KAAA,CAAA,CAAA,EAAA,IAEZ,KAAA,OAAA,SARmBC,GAAA,OAAAjB,EAAAkB,MAAAC,KAAAC,UAAA,CAAA,CAAA,gCAwBgB,SAClCC,GAEA,IAAAC,EAA0BC,EAAAA,UAAsB,WAAA,OAjBhC,SAACF,GAA+B,OAChDA,EAAYG,QAAoB,SAACC,EAAKC,GACpC,IAAMC,EAAMC,EAAAA,eAAeF,EAAWtB,MAClCyB,EAAAA,eAAeH,EAAWtB,KAAM,UAChCsB,EAAWI,IAGf,OAFIH,IAAKF,EAAIC,EAAWtB,MAAQ,CAAEuB,IAAAA,IAE3BF,CACR,GAAE,CAAE,EAAC,CASgDM,CAAUV,QAAAA,EAAe,OAAIW,EAAAC,EAAAA,QAAAX,EAAA,GAA5EY,EAAKF,EAAA,GAAEG,EAAQH,EAAA,GAChBI,EAAWC,SAAOH,GACxBE,EAASE,QAAUJ,EAEnB,IAAMK,EAAOC,EAAAA,SAAQ,WAAA,OAAMnB,QAAAA,EAAe,KAAI,CAACA,IACzCoB,EAAMF,EAAKG,KAAI,SAAAhB,GAAU,OAAIA,EAAWtB,IAAI,IAAEuC,KAAK,KA0CzD,OAxCAC,EAAAA,WAAU,WACR,IAAMC,EAAUN,EAAKO,QAAO,SAAApB,GAAU,QAAMA,EAAWtB,QAAQgC,EAASE,YACxE,GAAKO,EAAQE,OAAb,CAEA,IAAIC,GAAW,EAETC,EAAY,SAAC7C,EAAc8C,GAA0B,OACzDf,GAAS,SAAA5B,GAAI,OAAUA,EAAAA,EAAAA,CAAAA,EAAAA,mBAAOH,EAAI+C,EAAAA,EAAA,CAAA,EAAQ5C,EAAKH,IAAU8C,IAAK,GAAM,EA0BtE,OAvBAf,GAAS,SAAA5B,GACP,IAAM6C,EAAe7C,EAAAA,CAAAA,EAAAA,GAMrB,OAJAsC,EAAQQ,SAAQ,SAAA3B,GAAc,IAAA4B,EAC5BF,EAAQ1B,EAAWtB,MAAgC,QAAxBgD,EAAAA,EAAQ1B,EAAWtB,aAAK,IAAAkD,EAAAA,EAAI,CAAA,CACzD,IAEOF,CACT,IAEAP,EAAQQ,SAAQ,SAAA3B,GAETE,EAAcA,eAACF,EAAWtB,MAM/BL,EAAe2B,EAAWtB,MAAMmD,MAAK,SAAA5B,GAC/BqB,GAAYrB,GAAKsB,EAAUvB,EAAWtB,KAAM,CAAEuB,IAAAA,GACpD,IAPEsB,EAAUvB,EAAWtB,KAAM,CAAEuB,IAAKD,EAAWI,KAQjD,IAEO,WACLkB,GAAW,EAhCwB,CAoCvC,GAAG,CAACP,IAEGF,EAAKf,QAAgC,SAACC,EAAKC,GAChD,IAAM8B,EAAOtB,EAAMR,EAAWtB,MAC9B,OAAKoD,SAAAA,EAAM7B,KAEXF,EAAIgC,KAAK,CACPC,GAAIhC,EAAWI,IACf1B,KAAMsB,EAAWtB,KACjBuB,IAAK6B,EAAK7B,IACVgC,KAAMC,EAAiBA,kBAAClC,GACxBmC,KAAMnC,EAAWmC,OAEZpC,GATgBA,CAUxB,GAAE,GACL"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/toConsumableArray"),r=require("@babel/runtime/helpers/asyncToGenerator"),n=require("@babel/runtime/helpers/defineProperty"),t=require("@babel/runtime/helpers/slicedToArray"),u=require("@babel/runtime/regenerator"),i=require("react"),l=require("react-s3-uploader/s3upload"),o=require("../AttachmentPreview/getAttachmentKind.js"),a=require("../AttachFileButton/AttachFileButton.js"),c=require("../../clients/jsonApi/index.js"),f=require("../../utils/links.js");function
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/toConsumableArray"),r=require("@babel/runtime/helpers/asyncToGenerator"),n=require("@babel/runtime/helpers/defineProperty"),t=require("@babel/runtime/helpers/slicedToArray"),u=require("@babel/runtime/regenerator"),i=require("react"),l=require("react-s3-uploader/s3upload"),o=require("../AttachmentPreview/getAttachmentKind.js"),a=require("../AttachFileButton/AttachFileButton.js"),c=require("../../clients/jsonApi/index.js"),f=require("../../utils/links.js"),s=require("../../utils/signedLinkCache.js");function d(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var p=d(e),v=d(r),m=d(n),h=d(t),g=d(u),b=d(l);function U(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function k(e){for(var r=1;r<arguments.length;r++){var n=null!=arguments[r]?arguments[r]:{};r%2?U(Object(n),!0).forEach((function(r){m.default(e,r,n[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):U(Object(n)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))}))}return e}var w=function(e){return e.type.startsWith("image/")?"image":e.type.startsWith("video/")?"video":"file"},y=function(e){return(e/1048576).toFixed(1)},j=function(e){return{id:e.url,name:e.name,file:null,previewUrl:"",isUploading:!1,error:null,uploaded:e}},C=0,O=function(){return"attachment-".concat(C+=1)};exports.DEFAULT_MAX_ATTACHMENTS=10,exports.useAttachmentUpload=function(e){var r,n,t=e.value,u=e.onChange,l=e.onError,d=e.maxSizeBytes,m=e.maxFiles,U=void 0===m?10:m,C=e.accept,A=void 0===C?a.ACCEPTED_ATTACHMENT_TYPES:C,S=i.useState([]),E=h.default(S,2),L=E[0],R=E[1],F=i.useRef(null),x=i.useRef(new Map),P=i.useRef(new Map),q=i.useRef([]),T=i.useRef(u),z=i.useRef(l);T.current=u,z.current=l;var M=i.useRef([]),D=i.useCallback((function(e){var r=e(q.current);q.current=r,R(r),M.current=function(e){return e.map((function(e){return e.uploaded})).filter(Boolean)}(r),T.current(M.current)}),[]),B=i.useCallback((function(e,r){return D((function(n){return n.map((function(n){return n.id===e?k(k({},n),r):n}))}))}),[D]),_=i.useCallback((function(e){var r,n;null===(r=x.current.get(e))||void 0===r||r.abortUpload(),x.current.delete(e),P.current.set(e,(null!==(n=P.current.get(e))&&void 0!==n?n:0)+1)}),[]),W=i.useCallback((function(e){null!=e&&e.previewUrl&&URL.revokeObjectURL(e.previewUrl)}),[]),K=i.useCallback((function(){var e,r,n;null===(e=z.current)||void 0===e||e.call(z,null!==(r=null===(n=q.current.find((function(e){return e.error})))||void 0===n?void 0:n.error)&&void 0!==r?r:null)}),[]);i.useEffect((function(){return function(){x.current.forEach((function(e){return e.abortUpload()})),x.current.clear(),q.current.forEach((function(e){e.previewUrl&&URL.revokeObjectURL(e.previewUrl)}))}}),[]);var N=i.useCallback((function(e,r){var n,t=(null!==(n=P.current.get(e))&&void 0!==n?n:0)+1;P.current.set(e,t);var u,i,l=function(){return P.current.get(e)===t},o=function(r){var n;l()&&(B(e,{isUploading:!1,error:r}),null===(n=z.current)||void 0===n||n.call(z,r))},a="",f=new b.default({files:[r],preprocess:function(e,r){return r(e)},onProgress:function(){},getSignedUrl:(i=v.default(g.default.mark((function e(r,n){var t;return g.default.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,c.getS3SignedUrl(r.name,r.type);case 3:t=e.sent,a=t.file_name,n(k(k({},t),{},{signedUrl:t.signed_url})),e.next=11;break;case 8:e.prev=8,e.t0=e.catch(0),o((null===e.t0||void 0===e.t0?void 0:e.t0.message)||"Failed to upload the file");case 11:case"end":return e.stop()}}),e,null,[[0,8]])}))),function(e,r){return i.apply(this,arguments)}),onFinishS3Put:(u=v.default(g.default.mark((function n(){var t;return g.default.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return n.prev=0,n.next=3,s.getSignedLink(a);case 3:if(t=n.sent,l()){n.next=6;break}return n.abrupt("return");case 6:x.current.delete(e),B(e,{isUploading:!1,error:null,uploaded:{url:t,name:a,size:r.size}}),K(),n.next=14;break;case 11:n.prev=11,n.t0=n.catch(0),o((null===n.t0||void 0===n.t0?void 0:n.t0.message)||"Failed to upload the file");case 14:case"end":return n.stop()}}),n,null,[[0,11]])}))),function(){return u.apply(this,arguments)}),onError:function(e){return o(e||"Failed to upload the file")}});x.current.set(e,f)}),[B,K]),Y=i.useCallback((function(e){var r,n=f.getUrlFileName(e);n&&(q.current.length>=U?null===(r=z.current)||void 0===r||r.call(z,"You can attach up to ".concat(U," files.")):q.current.some((function(r){var n;return(null===(n=r.uploaded)||void 0===n?void 0:n.url)===e}))||D((function(r){return[].concat(p.default(r),[{id:O(),name:n,file:null,previewUrl:e,isUploading:!1,error:null,uploaded:{url:e,name:n}}])})))}),[D,U]),H=i.useCallback((function(e){var r,n,t,u,i=e.filter((function(e){return function(e,r){return r.split(",").map((function(e){return e.trim().toLowerCase()})).filter(Boolean).some((function(r){if(r.startsWith("."))return e.name.toLowerCase().endsWith(r);if(r.endsWith("/*")){var n=e.type.toLowerCase();return n?n.startsWith(r.slice(0,-1)):o.getAttachmentKind({name:e.name})===r.slice(0,-1)}return e.type.toLowerCase()===r}))}(e,A)})),l=i.length<e.length?1===e.length?"That file type is not supported.":"Some files were skipped — unsupported file type.":null,a="You can attach up to ".concat(U," files."),c=U-q.current.length;if(!i.length||c<=0){var f;null===(f=z.current)||void 0===f||f.call(z,i.length?a:l)}else{var s=i.slice(0,c),v=s.map((function(e){var r=w(e),n=!!d&&e.size>d;return{id:O(),name:e.name,file:e,previewUrl:"file"===r?"":URL.createObjectURL(e),isUploading:!n,error:n?"File is too large (".concat(y(e.size)," MB). Maximum size is ").concat(y(d)," MB."):null,uploaded:null}}));D((function(e){return[].concat(p.default(e),p.default(v))}));var m=i.length>s.length?a:null;null===(r=z.current)||void 0===r||r.call(z,null!==(n=null!==(t=null===(u=q.current.find((function(e){return e.error})))||void 0===u?void 0:u.error)&&void 0!==t?t:l)&&void 0!==n?n:m),v.filter((function(e){return!e.error})).forEach((function(e){return N(e.id,e.file)}))}}),[D,U,d,N,A]),I=i.useCallback((function(e){var r,n=Array.from(null!==(r=e.target.files)&&void 0!==r?r:[]);F.current&&(F.current.value=""),n.length&&H(n)}),[H]),G=i.useCallback((function(){var e;return null===(e=F.current)||void 0===e?void 0:e.click()}),[]),X=i.useCallback((function(e){var r=String(e);_(r),W(q.current.find((function(e){return e.id===r}))),D((function(e){return e.filter((function(e){return e.id!==r}))})),K()}),[_,W,D,K]),J=i.useCallback((function(e){var r=String(e),n=q.current.find((function(e){return e.id===r}));null!=n&&n.file&&(_(r),B(r,{isUploading:!0,error:null}),K(),N(r,n.file))}),[_,B,N,K]),Q=i.useCallback((function(e){return D((function(r){var n=new Map(r.map((function(e){return[e.id,e]}))),t=e.map((function(e){return n.get(String(e))})).filter(Boolean),u=r.filter((function(r){return!e.some((function(e){return String(e)===r.id}))}));return[].concat(p.default(t),p.default(u))}))}),[D]),V=i.useCallback((function(){var e;q.current.forEach((function(e){_(e.id),W(e)})),D((function(){return[]})),null===(e=z.current)||void 0===e||e.call(z,null)}),[_,D,W]);i.useEffect((function(){var e,r,n;(r=M.current,n=t,r.length===n.length&&r.every((function(e,r){return e.url===n[r].url})))||(q.current.forEach((function(e){_(e.id),e.previewUrl&&URL.revokeObjectURL(e.previewUrl)})),q.current=t.map(j),M.current=t,R(q.current),null===(e=z.current)||void 0===e||e.call(z,null))}),[t,_]);var Z=i.useState((function(){return t.reduce((function(e,r){var n=s.peekSignedLink(r.name,"inline");return n&&(e[r.name]=n),e}),{})})),$=h.default(Z,2),ee=$[0],re=$[1],ne=i.useRef(ee);ne.current=ee;var te=L.filter((function(e){return!e.file&&!e.previewUrl&&e.uploaded})).map((function(e){return e.uploaded.name})).join("|");return i.useEffect((function(){var e=te.split("|").filter((function(e){return e&&!(e in ne.current)}));if(e.length){var r=!0;return Promise.all(e.map((function(e){return s.getSignedLink(e,"inline").then((function(r){return[e,r]})).catch((function(r){return console.error('Failed to sign stored attachment "'.concat(e,'"'),r),[e,""]}))}))).then((function(e){r&&re((function(r){return k(k({},r),Object.fromEntries(e))}))})),function(){r=!1}}}),[te]),{items:L.reduce((function(e,r){var n;if(r.file)return e.push({id:r.id,name:r.name,src:r.previewUrl,kind:w(r.file),size:r.file.size,isUploading:r.isUploading,hideDownload:!0,error:null!==(n=r.error)&&void 0!==n?n:void 0}),e;var t=r.uploaded,u=o.getAttachmentKind(t),i=r.previewUrl||ee[t.name];return"file"===u||i?(e.push({id:r.id,name:t.name,src:i,kind:u,size:t.size,hideDownload:!0}),e):e}),[]),fileInputRef:F,openFileDialog:G,handleFileSelect:I,addFiles:H,addLinkedImage:Y,removeAttachment:X,handleRetry:J,reorderAttachments:Q,clearAttachments:V,isUploading:L.some((function(e){return e.isUploading})),error:null!==(r=null===(n=L.find((function(e){return e.error})))||void 0===n?void 0:n.error)&&void 0!==r?r:null,count:L.length,isFull:L.length>=U,maxFiles:U}};
|
|
2
2
|
//# sourceMappingURL=useAttachmentUpload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAttachmentUpload.js","sources":["../../../../src/components/CommentComposer/useAttachmentUpload.ts"],"sourcesContent":["import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport S3Upload from 'react-s3-uploader/s3upload';\n\nimport type {\n AttachmentKind,\n AttachmentPreviewItem,\n} from '../AttachmentPreview/AttachmentPreview.types';\nimport { getAttachmentKind } from '../AttachmentPreview/getAttachmentKind';\nimport { ACCEPTED_ATTACHMENT_TYPES } from '../AttachFileButton';\n\nimport { getS3SignedUrl, getS3DownloadLink } from '~/clients/jsonApi';\nimport { getUrlFileName } from '~/utils/links';\n\nexport type UploadedAttachment = {\n url: string;\n name: string;\n size?: number;\n};\n\ntype UseAttachmentUploadOptions = {\n value: UploadedAttachment[];\n onChange: (attachments: UploadedAttachment[]) => void;\n onError?: (message: string | null) => void;\n maxSizeBytes?: number;\n maxFiles?: number;\n /** Mirrors the file input's `accept`; also gates drag-and-drop. */\n accept?: string;\n};\n\n/** A picked or already-stored file, in the order the user arranged it. */\ntype Entry = {\n id: string;\n name: string;\n /** Set while the file is local; cleared entries come from `value`. */\n file: File | null;\n previewUrl: string;\n isUploading: boolean;\n error: string | null;\n uploaded: UploadedAttachment | null;\n};\n\nexport const DEFAULT_MAX_ATTACHMENTS = 10;\n\n/** Same rules the file input enforces via `accept`, so drag-and-drop can't smuggle a type past it. */\nconst isAcceptedType = (file: File, accept: string) =>\n accept\n .split(',')\n .map(rule => rule.trim().toLowerCase())\n .filter(Boolean)\n .some(rule => {\n if (rule.startsWith('.')) return file.name.toLowerCase().endsWith(rule);\n if (rule.endsWith('/*')) {\n const type = file.type.toLowerCase();\n if (type) return type.startsWith(rule.slice(0, -1));\n\n return getAttachmentKind({ name: file.name }) === rule.slice(0, -1);\n }\n\n return file.type.toLowerCase() === rule;\n });\n\nconst getFileKind = (file: File): AttachmentKind => {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type.startsWith('video/')) return 'video';\n return 'file';\n};\n\nconst formatMb = (bytes: number) => (bytes / (1024 * 1024)).toFixed(1);\n\nconst getUploaded = (entries: Entry[]) =>\n entries.map(entry => entry.uploaded).filter(Boolean) as UploadedAttachment[];\n\nconst isSameList = (a: UploadedAttachment[], b: UploadedAttachment[]) =>\n a.length === b.length && a.every((item, index) => item.url === b[index].url);\n\nconst toStoredEntry = (attachment: UploadedAttachment): Entry => ({\n id: attachment.url,\n name: attachment.name,\n file: null,\n previewUrl: '',\n isUploading: false,\n error: null,\n uploaded: attachment,\n});\n\nlet entrySeq = 0;\nconst nextEntryId = () => {\n entrySeq += 1;\n return `attachment-${entrySeq}`;\n};\n\nexport const useAttachmentUpload = ({\n value,\n onChange,\n onError,\n maxSizeBytes,\n maxFiles = DEFAULT_MAX_ATTACHMENTS,\n accept = ACCEPTED_ATTACHMENT_TYPES,\n}: UseAttachmentUploadOptions) => {\n const [entries, setEntries] = useState<Entry[]>([]);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadersRef = useRef(new Map<string, S3Upload>());\n // Bumped per attempt so a superseded upload can't write state for a restarted entry.\n const sessionsRef = useRef(new Map<string, number>());\n // Mutations are driven from async upload callbacks, so the latest list lives in a ref.\n const entriesRef = useRef<Entry[]>([]);\n const onChangeRef = useRef(onChange);\n const onErrorRef = useRef(onError);\n\n onChangeRef.current = onChange;\n onErrorRef.current = onError;\n\n // What we last handed the parent. A `value` that still matches it is our own change echoing\n // back; anything else is a parent-driven reset we must adopt.\n const emittedRef = useRef<UploadedAttachment[]>([]);\n\n const commit = useCallback((updater: (prev: Entry[]) => Entry[]) => {\n const next = updater(entriesRef.current);\n entriesRef.current = next;\n setEntries(next);\n emittedRef.current = getUploaded(next);\n onChangeRef.current(emittedRef.current);\n }, []);\n\n const patchEntry = useCallback(\n (id: string, patch: Partial<Entry>) =>\n commit(prev => prev.map(entry => (entry.id === id ? { ...entry, ...patch } : entry))),\n [commit]\n );\n\n const abortUpload = useCallback((id: string) => {\n uploadersRef.current.get(id)?.abortUpload();\n uploadersRef.current.delete(id);\n // Bump, never delete: deleting would let the next attempt reuse session 1, so a callback\n // still in flight from the aborted attempt would pass `isCurrent` and clobber it.\n sessionsRef.current.set(id, (sessionsRef.current.get(id) ?? 0) + 1);\n }, []);\n\n const releasePreview = useCallback((entry?: Entry) => {\n if (entry?.previewUrl) URL.revokeObjectURL(entry.previewUrl);\n }, []);\n\n // The banner is shared by every tile, so recompute it rather than clear it — one file\n // succeeding must not hide a sibling that is still failing.\n const syncError = useCallback(() => {\n onErrorRef.current?.(entriesRef.current.find(entry => entry.error)?.error ?? null);\n }, []);\n\n useEffect(\n () => () => {\n uploadersRef.current.forEach(uploader => uploader.abortUpload());\n uploadersRef.current.clear();\n entriesRef.current.forEach(entry => {\n if (entry.previewUrl) URL.revokeObjectURL(entry.previewUrl);\n });\n },\n []\n );\n\n const startUpload = useCallback(\n (id: string, file: File) => {\n const session = (sessionsRef.current.get(id) ?? 0) + 1;\n sessionsRef.current.set(id, session);\n // A superseded upload must not write state for an entry that is gone or restarted.\n const isCurrent = () => sessionsRef.current.get(id) === session;\n\n const fail = (message: string) => {\n if (!isCurrent()) return;\n patchEntry(id, { isUploading: false, error: message });\n onErrorRef.current?.(message);\n };\n\n let storedKey = '';\n\n const uploader = new S3Upload({\n files: [file],\n preprocess: (target: File, next: (file: File) => void) => next(target),\n onProgress: () => {},\n getSignedUrl: async (\n target: File,\n callback: (data: { signedUrl: string; [key: string]: unknown }) => void\n ) => {\n try {\n const data = await getS3SignedUrl(target.name, target.type);\n storedKey = data.file_name;\n callback({ ...data, signedUrl: data.signed_url });\n } catch (e) {\n fail((e as Error)?.message || 'Failed to upload the file');\n }\n },\n onFinishS3Put: async () => {\n try {\n const { url } = await getS3DownloadLink(storedKey);\n if (!isCurrent()) return;\n\n uploadersRef.current.delete(id);\n patchEntry(id, {\n isUploading: false,\n error: null,\n uploaded: { url, name: storedKey, size: file.size },\n });\n syncError();\n } catch (e) {\n fail((e as Error)?.message || 'Failed to upload the file');\n }\n },\n onError: (message: string) => fail(message || 'Failed to upload the file'),\n });\n\n uploadersRef.current.set(id, uploader);\n },\n [patchEntry, syncError]\n );\n\n /** Nothing is uploaded: a comment attachment is a url, so the link itself is the attachment. */\n const addLinkedImage = useCallback(\n (url: string) => {\n const name = getUrlFileName(url);\n\n if (!name) return;\n if (entriesRef.current.length >= maxFiles) {\n onErrorRef.current?.(`You can attach up to ${maxFiles} files.`);\n\n return;\n }\n\n if (entriesRef.current.some(entry => entry.uploaded?.url === url)) return;\n\n commit(prev => [\n ...prev,\n {\n id: nextEntryId(),\n name,\n file: null,\n previewUrl: url,\n isUploading: false,\n error: null,\n uploaded: { url, name },\n },\n ]);\n },\n [commit, maxFiles]\n );\n\n const addFiles = useCallback(\n (files: File[]) => {\n const supported = files.filter(file => isAcceptedType(file, accept));\n const skipped = supported.length < files.length;\n // One banner, one message: report the most actionable reason once, at the end. Reporting\n // as we go would let a later call overwrite an earlier warning on a mixed drop.\n const unsupported = skipped\n ? (files.length === 1 && 'That file type is not supported.') ||\n 'Some files were skipped — unsupported file type.'\n : null;\n const tooMany = `You can attach up to ${maxFiles} files.`;\n\n const room = maxFiles - entriesRef.current.length;\n if (!supported.length || room <= 0) {\n onErrorRef.current?.(supported.length ? tooMany : unsupported);\n return;\n }\n\n const accepted = supported.slice(0, room);\n const added: Entry[] = accepted.map(file => {\n const kind = getFileKind(file);\n const isTooLarge = !!maxSizeBytes && file.size > maxSizeBytes;\n\n return {\n id: nextEntryId(),\n name: file.name,\n file,\n previewUrl: kind === 'file' ? '' : URL.createObjectURL(file),\n isUploading: !isTooLarge,\n error: isTooLarge\n ? `File is too large (${formatMb(file.size)} MB). Maximum size is ${formatMb(\n maxSizeBytes as number\n )} MB.`\n : null,\n uploaded: null,\n };\n });\n\n commit(prev => [...prev, ...added]);\n\n const overflow = supported.length > accepted.length ? tooMany : null;\n onErrorRef.current?.(\n entriesRef.current.find(entry => entry.error)?.error ?? unsupported ?? overflow\n );\n\n added\n .filter(entry => !entry.error)\n .forEach(entry => startUpload(entry.id, entry.file as File));\n },\n [commit, maxFiles, maxSizeBytes, startUpload, accept]\n );\n\n const handleFileSelect = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const files = Array.from(event.target.files ?? []);\n // Reset the input so re-picking the same file still fires a change event.\n if (fileInputRef.current) fileInputRef.current.value = '';\n if (files.length) addFiles(files);\n },\n [addFiles]\n );\n\n const openFileDialog = useCallback(() => fileInputRef.current?.click(), []);\n\n const removeAttachment = useCallback(\n (id: AttachmentPreviewItem['id']) => {\n const key = String(id);\n abortUpload(key);\n releasePreview(entriesRef.current.find(entry => entry.id === key));\n commit(prev => prev.filter(entry => entry.id !== key));\n syncError();\n },\n [abortUpload, releasePreview, commit, syncError]\n );\n\n const handleRetry = useCallback(\n (id: AttachmentPreviewItem['id']) => {\n const key = String(id);\n const entry = entriesRef.current.find(item => item.id === key);\n if (!entry?.file) return;\n\n abortUpload(key);\n patchEntry(key, { isUploading: true, error: null });\n syncError();\n startUpload(key, entry.file);\n },\n [abortUpload, patchEntry, startUpload, syncError]\n );\n\n const reorderAttachments = useCallback(\n (orderedIds: AttachmentPreviewItem['id'][]) =>\n commit(prev => {\n const byId = new Map(prev.map(entry => [entry.id, entry]));\n const reordered = orderedIds.map(id => byId.get(String(id))).filter(Boolean) as Entry[];\n // Unlisted ids (a race with a removal) keep their place at the end.\n const missing = prev.filter(entry => !orderedIds.some(id => String(id) === entry.id));\n return [...reordered, ...missing];\n }),\n [commit]\n );\n\n const clearAttachments = useCallback(() => {\n entriesRef.current.forEach(entry => {\n abortUpload(entry.id);\n releasePreview(entry);\n });\n commit(() => []);\n onErrorRef.current?.(null);\n }, [abortUpload, commit, releasePreview]);\n\n // Adopt a value we didn't produce — an edit form's initial attachments, or a parent-side reset.\n // Compared against what we emitted, not against the current entries: a failed-only or\n // mid-upload list emits `[]` too, and treating that as \"in sync\" would strand those tiles\n // on screen and let a late upload write itself back into freshly reset parent state.\n useEffect(() => {\n if (isSameList(emittedRef.current, value)) return;\n\n entriesRef.current.forEach(entry => {\n abortUpload(entry.id);\n if (entry.previewUrl) URL.revokeObjectURL(entry.previewUrl);\n });\n entriesRef.current = value.map(toStoredEntry);\n emittedRef.current = value;\n setEntries(entriesRef.current);\n onErrorRef.current?.(null);\n }, [value, abortUpload]);\n\n // A stored url has expired by now, so re-sign it for the preview.\n const [storedSrcs, setStoredSrcs] = useState<Record<string, string>>({});\n const storedSrcsRef = useRef(storedSrcs);\n storedSrcsRef.current = storedSrcs;\n\n const storedNames = entries\n // A linked image carries its own url, so there is no key of ours to sign.\n .filter(entry => !entry.file && !entry.previewUrl && entry.uploaded)\n .map(entry => (entry.uploaded as UploadedAttachment).name)\n .join('|');\n\n useEffect(() => {\n const pending = storedNames.split('|').filter(name => name && !(name in storedSrcsRef.current));\n if (!pending.length) return undefined;\n\n let isActive = true;\n Promise.all(\n pending.map(name =>\n getS3DownloadLink(name, 'inline')\n .then(({ url }: { url: string }) => [name, url] as const)\n .catch(error => {\n console.error(`Failed to sign stored attachment \"${name}\"`, error);\n\n return [name, ''] as const;\n })\n )\n ).then(resolved => {\n if (isActive) setStoredSrcs(prev => ({ ...prev, ...Object.fromEntries(resolved) }));\n });\n\n return () => {\n isActive = false;\n };\n }, [storedNames]);\n\n const items = entries.reduce<AttachmentPreviewItem[]>((acc, entry) => {\n if (entry.file) {\n acc.push({\n id: entry.id,\n name: entry.name,\n src: entry.previewUrl,\n kind: getFileKind(entry.file),\n size: entry.file.size,\n isUploading: entry.isUploading,\n hideDownload: true,\n error: entry.error ?? undefined,\n });\n return acc;\n }\n\n const stored = entry.uploaded as UploadedAttachment;\n const kind = getAttachmentKind(stored);\n // A linked image is already a url; only one of ours has an S3 key worth signing.\n const src = entry.previewUrl || storedSrcs[stored.name];\n // A thumbnail without its signed url would paint as a broken image, so hold it back.\n if (kind !== 'file' && !src) return acc;\n\n acc.push({ id: entry.id, name: stored.name, src, kind, size: stored.size, hideDownload: true });\n return acc;\n }, []);\n\n return {\n items,\n fileInputRef,\n openFileDialog,\n handleFileSelect,\n addFiles,\n addLinkedImage,\n removeAttachment,\n handleRetry,\n reorderAttachments,\n clearAttachments,\n isUploading: entries.some(entry => entry.isUploading),\n error: entries.find(entry => entry.error)?.error ?? null,\n count: entries.length,\n isFull: entries.length >= maxFiles,\n maxFiles,\n };\n};\n"],"names":["getFileKind","file","type","startsWith","formatMb","bytes","toFixed","toStoredEntry","attachment","id","url","name","previewUrl","isUploading","error","uploaded","entrySeq","nextEntryId","concat","_ref","_entries$find$error","_entries$find","value","onChange","onError","maxSizeBytes","_ref$maxFiles","maxFiles","_ref$accept","accept","ACCEPTED_ATTACHMENT_TYPES","useState","_useState2","_slicedToArray","_useState","entries","setEntries","fileInputRef","useRef","uploadersRef","Map","sessionsRef","entriesRef","onChangeRef","onErrorRef","current","emittedRef","commit","useCallback","updater","next","map","entry","filter","Boolean","getUploaded","patchEntry","patch","prev","abortUpload","_uploadersRef$current","_sessionsRef$current$","get","delete","set","releasePreview","URL","revokeObjectURL","syncError","_onErrorRef$current","_entriesRef$current$f","_entriesRef$current$f2","find","useEffect","forEach","uploader","clear","startUpload","_sessionsRef$current$2","session","_onFinishS3Put","_getSignedUrl","isCurrent","fail","message","_onErrorRef$current2","storedKey","S3Upload","files","preprocess","target","onProgress","getSignedUrl","_asyncToGenerator","_regeneratorRuntime","mark","_callee","callback","_data","wrap","_context","getS3SignedUrl","data","sent","file_name","signedUrl","signed_url","t0","stop","_x","_x2","apply","this","arguments","onFinishS3Put","_callee2","_yield$getS3DownloadL","_context2","getS3DownloadLink","abrupt","size","addLinkedImage","_onErrorRef$current3","getUrlFileName","length","some","_entry$uploaded","_toConsumableArray","addFiles","_onErrorRef$current5","_ref2","_entriesRef$current$f3","_entriesRef$current$f4","supported","split","rule","trim","toLowerCase","endsWith","slice","getAttachmentKind","isAcceptedType","unsupported","tooMany","room","_onErrorRef$current4","accepted","added","kind","isTooLarge","createObjectURL","overflow","handleFileSelect","event","_event$target$files","Array","from","openFileDialog","_fileInputRef$current","click","removeAttachment","key","String","handleRetry","item","reorderAttachments","orderedIds","byId","reordered","missing","clearAttachments","_onErrorRef$current6","_onErrorRef$current7","a","b","every","index","_useState3","_useState4","storedSrcs","setStoredSrcs","storedSrcsRef","storedNames","join","pending","isActive","Promise","all","then","_ref3","catch","console","resolved","_objectSpread","Object","fromEntries","items","reduce","acc","_entry$error","push","src","hideDownload","undefined","stored","count","isFull"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAttachmentUpload.js","sources":["../../../../src/components/CommentComposer/useAttachmentUpload.ts"],"sourcesContent":["import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport S3Upload from 'react-s3-uploader/s3upload';\n\nimport type {\n AttachmentKind,\n AttachmentPreviewItem,\n} from '../AttachmentPreview/AttachmentPreview.types';\nimport { getAttachmentKind } from '../AttachmentPreview/getAttachmentKind';\nimport { ACCEPTED_ATTACHMENT_TYPES } from '../AttachFileButton';\n\nimport { getS3SignedUrl } from '~/clients/jsonApi';\nimport { getUrlFileName } from '~/utils/links';\nimport { getSignedLink, peekSignedLink } from '~/utils/signedLinkCache';\n\nexport type UploadedAttachment = {\n url: string;\n name: string;\n size?: number;\n};\n\ntype UseAttachmentUploadOptions = {\n value: UploadedAttachment[];\n onChange: (attachments: UploadedAttachment[]) => void;\n onError?: (message: string | null) => void;\n maxSizeBytes?: number;\n maxFiles?: number;\n /** Mirrors the file input's `accept`; also gates drag-and-drop. */\n accept?: string;\n};\n\n/** A picked or already-stored file, in the order the user arranged it. */\ntype Entry = {\n id: string;\n name: string;\n /** Set while the file is local; cleared entries come from `value`. */\n file: File | null;\n previewUrl: string;\n isUploading: boolean;\n error: string | null;\n uploaded: UploadedAttachment | null;\n};\n\nexport const DEFAULT_MAX_ATTACHMENTS = 10;\n\n/** Same rules the file input enforces via `accept`, so drag-and-drop can't smuggle a type past it. */\nconst isAcceptedType = (file: File, accept: string) =>\n accept\n .split(',')\n .map(rule => rule.trim().toLowerCase())\n .filter(Boolean)\n .some(rule => {\n if (rule.startsWith('.')) return file.name.toLowerCase().endsWith(rule);\n if (rule.endsWith('/*')) {\n const type = file.type.toLowerCase();\n if (type) return type.startsWith(rule.slice(0, -1));\n\n return getAttachmentKind({ name: file.name }) === rule.slice(0, -1);\n }\n\n return file.type.toLowerCase() === rule;\n });\n\nconst getFileKind = (file: File): AttachmentKind => {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type.startsWith('video/')) return 'video';\n return 'file';\n};\n\nconst formatMb = (bytes: number) => (bytes / (1024 * 1024)).toFixed(1);\n\nconst getUploaded = (entries: Entry[]) =>\n entries.map(entry => entry.uploaded).filter(Boolean) as UploadedAttachment[];\n\nconst isSameList = (a: UploadedAttachment[], b: UploadedAttachment[]) =>\n a.length === b.length && a.every((item, index) => item.url === b[index].url);\n\nconst toStoredEntry = (attachment: UploadedAttachment): Entry => ({\n id: attachment.url,\n name: attachment.name,\n file: null,\n previewUrl: '',\n isUploading: false,\n error: null,\n uploaded: attachment,\n});\n\nlet entrySeq = 0;\nconst nextEntryId = () => {\n entrySeq += 1;\n return `attachment-${entrySeq}`;\n};\n\nexport const useAttachmentUpload = ({\n value,\n onChange,\n onError,\n maxSizeBytes,\n maxFiles = DEFAULT_MAX_ATTACHMENTS,\n accept = ACCEPTED_ATTACHMENT_TYPES,\n}: UseAttachmentUploadOptions) => {\n const [entries, setEntries] = useState<Entry[]>([]);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadersRef = useRef(new Map<string, S3Upload>());\n // Bumped per attempt so a superseded upload can't write state for a restarted entry.\n const sessionsRef = useRef(new Map<string, number>());\n // Mutations are driven from async upload callbacks, so the latest list lives in a ref.\n const entriesRef = useRef<Entry[]>([]);\n const onChangeRef = useRef(onChange);\n const onErrorRef = useRef(onError);\n\n onChangeRef.current = onChange;\n onErrorRef.current = onError;\n\n // What we last handed the parent. A `value` that still matches it is our own change echoing\n // back; anything else is a parent-driven reset we must adopt.\n const emittedRef = useRef<UploadedAttachment[]>([]);\n\n const commit = useCallback((updater: (prev: Entry[]) => Entry[]) => {\n const next = updater(entriesRef.current);\n entriesRef.current = next;\n setEntries(next);\n emittedRef.current = getUploaded(next);\n onChangeRef.current(emittedRef.current);\n }, []);\n\n const patchEntry = useCallback(\n (id: string, patch: Partial<Entry>) =>\n commit(prev => prev.map(entry => (entry.id === id ? { ...entry, ...patch } : entry))),\n [commit]\n );\n\n const abortUpload = useCallback((id: string) => {\n uploadersRef.current.get(id)?.abortUpload();\n uploadersRef.current.delete(id);\n // Bump, never delete: deleting would let the next attempt reuse session 1, so a callback\n // still in flight from the aborted attempt would pass `isCurrent` and clobber it.\n sessionsRef.current.set(id, (sessionsRef.current.get(id) ?? 0) + 1);\n }, []);\n\n const releasePreview = useCallback((entry?: Entry) => {\n if (entry?.previewUrl) URL.revokeObjectURL(entry.previewUrl);\n }, []);\n\n // The banner is shared by every tile, so recompute it rather than clear it — one file\n // succeeding must not hide a sibling that is still failing.\n const syncError = useCallback(() => {\n onErrorRef.current?.(entriesRef.current.find(entry => entry.error)?.error ?? null);\n }, []);\n\n useEffect(\n () => () => {\n uploadersRef.current.forEach(uploader => uploader.abortUpload());\n uploadersRef.current.clear();\n entriesRef.current.forEach(entry => {\n if (entry.previewUrl) URL.revokeObjectURL(entry.previewUrl);\n });\n },\n []\n );\n\n const startUpload = useCallback(\n (id: string, file: File) => {\n const session = (sessionsRef.current.get(id) ?? 0) + 1;\n sessionsRef.current.set(id, session);\n // A superseded upload must not write state for an entry that is gone or restarted.\n const isCurrent = () => sessionsRef.current.get(id) === session;\n\n const fail = (message: string) => {\n if (!isCurrent()) return;\n patchEntry(id, { isUploading: false, error: message });\n onErrorRef.current?.(message);\n };\n\n let storedKey = '';\n\n const uploader = new S3Upload({\n files: [file],\n preprocess: (target: File, next: (file: File) => void) => next(target),\n onProgress: () => {},\n getSignedUrl: async (\n target: File,\n callback: (data: { signedUrl: string; [key: string]: unknown }) => void\n ) => {\n try {\n const data = await getS3SignedUrl(target.name, target.type);\n storedKey = data.file_name;\n callback({ ...data, signedUrl: data.signed_url });\n } catch (e) {\n fail((e as Error)?.message || 'Failed to upload the file');\n }\n },\n onFinishS3Put: async () => {\n try {\n const url = await getSignedLink(storedKey);\n if (!isCurrent()) return;\n\n uploadersRef.current.delete(id);\n patchEntry(id, {\n isUploading: false,\n error: null,\n uploaded: { url, name: storedKey, size: file.size },\n });\n syncError();\n } catch (e) {\n fail((e as Error)?.message || 'Failed to upload the file');\n }\n },\n onError: (message: string) => fail(message || 'Failed to upload the file'),\n });\n\n uploadersRef.current.set(id, uploader);\n },\n [patchEntry, syncError]\n );\n\n /** Nothing is uploaded: a comment attachment is a url, so the link itself is the attachment. */\n const addLinkedImage = useCallback(\n (url: string) => {\n const name = getUrlFileName(url);\n\n if (!name) return;\n if (entriesRef.current.length >= maxFiles) {\n onErrorRef.current?.(`You can attach up to ${maxFiles} files.`);\n\n return;\n }\n\n if (entriesRef.current.some(entry => entry.uploaded?.url === url)) return;\n\n commit(prev => [\n ...prev,\n {\n id: nextEntryId(),\n name,\n file: null,\n previewUrl: url,\n isUploading: false,\n error: null,\n uploaded: { url, name },\n },\n ]);\n },\n [commit, maxFiles]\n );\n\n const addFiles = useCallback(\n (files: File[]) => {\n const supported = files.filter(file => isAcceptedType(file, accept));\n const skipped = supported.length < files.length;\n // One banner, one message: report the most actionable reason once, at the end. Reporting\n // as we go would let a later call overwrite an earlier warning on a mixed drop.\n const unsupported = skipped\n ? (files.length === 1 && 'That file type is not supported.') ||\n 'Some files were skipped — unsupported file type.'\n : null;\n const tooMany = `You can attach up to ${maxFiles} files.`;\n\n const room = maxFiles - entriesRef.current.length;\n if (!supported.length || room <= 0) {\n onErrorRef.current?.(supported.length ? tooMany : unsupported);\n return;\n }\n\n const accepted = supported.slice(0, room);\n const added: Entry[] = accepted.map(file => {\n const kind = getFileKind(file);\n const isTooLarge = !!maxSizeBytes && file.size > maxSizeBytes;\n\n return {\n id: nextEntryId(),\n name: file.name,\n file,\n previewUrl: kind === 'file' ? '' : URL.createObjectURL(file),\n isUploading: !isTooLarge,\n error: isTooLarge\n ? `File is too large (${formatMb(file.size)} MB). Maximum size is ${formatMb(\n maxSizeBytes as number\n )} MB.`\n : null,\n uploaded: null,\n };\n });\n\n commit(prev => [...prev, ...added]);\n\n const overflow = supported.length > accepted.length ? tooMany : null;\n onErrorRef.current?.(\n entriesRef.current.find(entry => entry.error)?.error ?? unsupported ?? overflow\n );\n\n added\n .filter(entry => !entry.error)\n .forEach(entry => startUpload(entry.id, entry.file as File));\n },\n [commit, maxFiles, maxSizeBytes, startUpload, accept]\n );\n\n const handleFileSelect = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const files = Array.from(event.target.files ?? []);\n // Reset the input so re-picking the same file still fires a change event.\n if (fileInputRef.current) fileInputRef.current.value = '';\n if (files.length) addFiles(files);\n },\n [addFiles]\n );\n\n const openFileDialog = useCallback(() => fileInputRef.current?.click(), []);\n\n const removeAttachment = useCallback(\n (id: AttachmentPreviewItem['id']) => {\n const key = String(id);\n abortUpload(key);\n releasePreview(entriesRef.current.find(entry => entry.id === key));\n commit(prev => prev.filter(entry => entry.id !== key));\n syncError();\n },\n [abortUpload, releasePreview, commit, syncError]\n );\n\n const handleRetry = useCallback(\n (id: AttachmentPreviewItem['id']) => {\n const key = String(id);\n const entry = entriesRef.current.find(item => item.id === key);\n if (!entry?.file) return;\n\n abortUpload(key);\n patchEntry(key, { isUploading: true, error: null });\n syncError();\n startUpload(key, entry.file);\n },\n [abortUpload, patchEntry, startUpload, syncError]\n );\n\n const reorderAttachments = useCallback(\n (orderedIds: AttachmentPreviewItem['id'][]) =>\n commit(prev => {\n const byId = new Map(prev.map(entry => [entry.id, entry]));\n const reordered = orderedIds.map(id => byId.get(String(id))).filter(Boolean) as Entry[];\n // Unlisted ids (a race with a removal) keep their place at the end.\n const missing = prev.filter(entry => !orderedIds.some(id => String(id) === entry.id));\n return [...reordered, ...missing];\n }),\n [commit]\n );\n\n const clearAttachments = useCallback(() => {\n entriesRef.current.forEach(entry => {\n abortUpload(entry.id);\n releasePreview(entry);\n });\n commit(() => []);\n onErrorRef.current?.(null);\n }, [abortUpload, commit, releasePreview]);\n\n // Adopt a value we didn't produce — an edit form's initial attachments, or a parent-side reset.\n // Compared against what we emitted, not against the current entries: a failed-only or\n // mid-upload list emits `[]` too, and treating that as \"in sync\" would strand those tiles\n // on screen and let a late upload write itself back into freshly reset parent state.\n useEffect(() => {\n if (isSameList(emittedRef.current, value)) return;\n\n entriesRef.current.forEach(entry => {\n abortUpload(entry.id);\n if (entry.previewUrl) URL.revokeObjectURL(entry.previewUrl);\n });\n entriesRef.current = value.map(toStoredEntry);\n emittedRef.current = value;\n setEntries(entriesRef.current);\n onErrorRef.current?.(null);\n }, [value, abortUpload]);\n\n // A stored url has expired by now, so re-sign it for the preview.\n const [storedSrcs, setStoredSrcs] = useState<Record<string, string>>(() =>\n value.reduce<Record<string, string>>((acc, attachment) => {\n const src = peekSignedLink(attachment.name, 'inline');\n if (src) acc[attachment.name] = src;\n\n return acc;\n }, {})\n );\n const storedSrcsRef = useRef(storedSrcs);\n storedSrcsRef.current = storedSrcs;\n\n const storedNames = entries\n // A linked image carries its own url, so there is no key of ours to sign.\n .filter(entry => !entry.file && !entry.previewUrl && entry.uploaded)\n .map(entry => (entry.uploaded as UploadedAttachment).name)\n .join('|');\n\n useEffect(() => {\n const pending = storedNames.split('|').filter(name => name && !(name in storedSrcsRef.current));\n if (!pending.length) return undefined;\n\n let isActive = true;\n Promise.all(\n pending.map(name =>\n getSignedLink(name, 'inline')\n .then(url => [name, url] as const)\n .catch(error => {\n console.error(`Failed to sign stored attachment \"${name}\"`, error);\n\n return [name, ''] as const;\n })\n )\n ).then(resolved => {\n if (isActive) setStoredSrcs(prev => ({ ...prev, ...Object.fromEntries(resolved) }));\n });\n\n return () => {\n isActive = false;\n };\n }, [storedNames]);\n\n const items = entries.reduce<AttachmentPreviewItem[]>((acc, entry) => {\n if (entry.file) {\n acc.push({\n id: entry.id,\n name: entry.name,\n src: entry.previewUrl,\n kind: getFileKind(entry.file),\n size: entry.file.size,\n isUploading: entry.isUploading,\n hideDownload: true,\n error: entry.error ?? undefined,\n });\n return acc;\n }\n\n const stored = entry.uploaded as UploadedAttachment;\n const kind = getAttachmentKind(stored);\n // A linked image is already a url; only one of ours has an S3 key worth signing.\n const src = entry.previewUrl || storedSrcs[stored.name];\n // A thumbnail without its signed url would paint as a broken image, so hold it back.\n if (kind !== 'file' && !src) return acc;\n\n acc.push({ id: entry.id, name: stored.name, src, kind, size: stored.size, hideDownload: true });\n return acc;\n }, []);\n\n return {\n items,\n fileInputRef,\n openFileDialog,\n handleFileSelect,\n addFiles,\n addLinkedImage,\n removeAttachment,\n handleRetry,\n reorderAttachments,\n clearAttachments,\n isUploading: entries.some(entry => entry.isUploading),\n error: entries.find(entry => entry.error)?.error ?? null,\n count: entries.length,\n isFull: entries.length >= maxFiles,\n maxFiles,\n };\n};\n"],"names":["getFileKind","file","type","startsWith","formatMb","bytes","toFixed","toStoredEntry","attachment","id","url","name","previewUrl","isUploading","error","uploaded","entrySeq","nextEntryId","concat","_ref","_entries$find$error","_entries$find","value","onChange","onError","maxSizeBytes","_ref$maxFiles","maxFiles","_ref$accept","accept","ACCEPTED_ATTACHMENT_TYPES","useState","_useState2","_slicedToArray","_useState","entries","setEntries","fileInputRef","useRef","uploadersRef","Map","sessionsRef","entriesRef","onChangeRef","onErrorRef","current","emittedRef","commit","useCallback","updater","next","map","entry","filter","Boolean","getUploaded","patchEntry","patch","prev","abortUpload","_uploadersRef$current","_sessionsRef$current$","get","delete","set","releasePreview","URL","revokeObjectURL","syncError","_onErrorRef$current","_entriesRef$current$f","_entriesRef$current$f2","find","useEffect","forEach","uploader","clear","startUpload","_sessionsRef$current$2","session","_onFinishS3Put","_getSignedUrl","isCurrent","fail","message","_onErrorRef$current2","storedKey","S3Upload","files","preprocess","target","onProgress","getSignedUrl","_asyncToGenerator","_regeneratorRuntime","mark","_callee","callback","_data","wrap","_context","getS3SignedUrl","data","sent","file_name","signedUrl","signed_url","t0","stop","_x","_x2","apply","this","arguments","onFinishS3Put","_callee2","_context2","getSignedLink","abrupt","size","addLinkedImage","_onErrorRef$current3","getUrlFileName","length","some","_entry$uploaded","_toConsumableArray","addFiles","_onErrorRef$current5","_ref2","_entriesRef$current$f3","_entriesRef$current$f4","supported","split","rule","trim","toLowerCase","endsWith","slice","getAttachmentKind","isAcceptedType","unsupported","tooMany","room","_onErrorRef$current4","accepted","added","kind","isTooLarge","createObjectURL","overflow","handleFileSelect","event","_event$target$files","Array","from","openFileDialog","_fileInputRef$current","click","removeAttachment","key","String","handleRetry","item","reorderAttachments","orderedIds","byId","reordered","missing","clearAttachments","_onErrorRef$current6","_onErrorRef$current7","a","b","every","index","_useState3","reduce","acc","src","peekSignedLink","_useState4","storedSrcs","setStoredSrcs","storedSrcsRef","storedNames","join","pending","isActive","Promise","all","then","catch","console","resolved","_objectSpread","Object","fromEntries","items","_entry$error","push","hideDownload","undefined","stored","count","isFull"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var s=require("@babel/runtime/helpers/slicedToArray"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var s=require("@babel/runtime/helpers/slicedToArray"),e=require("@babel/runtime/helpers/toConsumableArray"),o=require("react"),c=require("moment"),n=require("../../TextInputNext/TextInputNext.js"),i=require("../../TextInput/TextInput.js"),r=require("../utils.js"),u=require("../../../icons/iconParkIcons.js");require("../../../icons/customIcons/icons/AddMessage.js"),require("../../../icons/customIcons/icons/DragOne.js"),require("../../../icons/customIcons/icons/Attention.js"),require("../../../icons/customIcons/icons/Collapse.js"),require("../../../icons/customIcons/icons/Dashboard.js"),require("../../../icons/customIcons/icons/Expand.js"),require("../../../icons/customIcons/icons/FolderClosed.js"),require("../../../icons/customIcons/icons/FolderClosedFilled.js"),require("../../../icons/customIcons/icons/FolderOpened.js"),require("../../../icons/customIcons/icons/GreaterOrEqual.js"),require("../../../icons/customIcons/icons/LessOrEqual.js"),require("../../../icons/customIcons/icons/Search.js"),require("../../../icons/customIcons/icons/SearchOne.js"),require("../../../icons/customIcons/icons/Wellhub.js"),require("../../../icons/customIcons/icons/MultiRuler.js"),require("../../../icons/customIcons/icons/Checkbox.js"),require("../../../icons/customIcons/icons/CheckboxChecked.js"),require("../../../icons/customIcons/icons/CheckboxIndeterminate.js"),require("../../../icons/customIcons/icons/Radio.js"),require("../../../icons/customIcons/icons/RadioChecked.js"),require("../../../icons/customIcons/icons/SimulFrac.js"),require("../../../icons/customIcons/icons/ZipperFrac.js"),require("../../../icons/customIcons/icons/CautionFilled.js"),require("../../../icons/customIcons/icons/InfoRounded.js"),require("../../../icons/customIcons/icons/FlameFilled.js"),require("../../../icons/customIcons/icons/MoreApp.js"),require("../../../icons/customIcons/icons/Pad.js"),require("../../../icons/customIcons/icons/DrilloutUnit.js"),require("../../../icons/customIcons/icons/FracFleet.js"),require("../../../icons/customIcons/icons/Global.js"),require("../../../icons/customIcons/icons/Program.js"),require("../../../icons/customIcons/icons/Rig.js"),require("../../../icons/customIcons/icons/Well.js"),require("../../../icons/customIcons/icons/Gap.js"),require("../../../icons/customIcons/icons/Pin.js"),require("../../../icons/customIcons/icons/CloseOneFilled.js"),require("../../../icons/customIcons/icons/AttentionFilled.js"),require("../../../icons/customIcons/icons/CheckOneFilled.js"),require("../../../icons/customIcons/icons/Archive.js"),require("../../../icons/customIcons/icons/ArchiveCancel.js"),require("../../../icons/customIcons/icons/Unarchive.js"),require("../../../icons/customIcons/icons/Archived.js"),require("../../../icons/customIcons/icons/InterventionUnit.js"),require("../../../icons/customIcons/icons/CloudDelete.js"),require("../../../icons/customIcons/icons/Lasso.js"),require("../../../icons/customIcons/icons/Radius.js"),require("../../../icons/customIcons/icons/ErrorOps.js"),require("../../../icons/customIcons/icons/DataTypeOps.js"),require("../../../icons/customIcons/icons/FalsePositiveOps.js"),require("../../../icons/customIcons/icons/CalibrationOps.js"),require("../../../icons/customIcons/icons/CriticalOps.js"),require("../../../icons/customIcons/icons/Company.js"),require("../../../icons/customIcons/icons/ArchiveOne.js"),require("../../../icons/customIcons/icons/ParseBotFusion.js"),require("../../../icons/customIcons/icons/Connect.js"),require("../../../icons/customIcons/icons/PuzzleOne.js"),require("../../../icons/customIcons/icons/Feed.js"),require("../../../icons/customIcons/icons/Prompt.js"),require("../../../icons/customIcons/icons/Companies.js"),require("../../../icons/customIcons/icons/ClipboardAi.js"),require("../../../icons/customIcons/icons/Key.js"),require("../../../icons/customIcons/icons/AtSignCrossed.js"),require("../../../icons/customIcons/icons/MappingManual.js"),require("../../../icons/customIcons/icons/Mapping.js"),require("../../../icons/customIcons/icons/Metrics.js"),require("../../../icons/customIcons/icons/Drops.js"),require("../../../icons/customIcons/icons/ClipboardSearch.js"),require("../../../icons/customIcons/icons/Template.js"),require("../../../icons/customIcons/icons/ClipboardMetrics.js"),require("../../../icons/customIcons/icons/ClipboardBuilder.js"),require("../../../icons/customIcons/icons/UnitConversion.js"),require("../../../icons/customIcons/icons/NPT.js"),require("../../../icons/customIcons/icons/GuidedFrac.js");var t=require("react/jsx-runtime");function a(s){return s&&"object"==typeof s&&"default"in s?s:{default:s}}var l=a(s),m=a(e),I=a(c),j=function(s,e){return(Array.isArray(s)?s:[s]).filter((function(s){return!!s})).map((function(s){return I.default(s).format(e)})).join(" - ")},q=function(s,e,o){var c=I.default(s,[e].concat(m.default(r.InputParseFormats[o]||[])),!0);return c.isValid()?c.toDate():void 0},d=o.forwardRef((function(s,e){var c=s.value,a=s.label,m=s.open,I=s.className,d=s.testId,p=s.format,f=s.placeholder,C=s.range,b=s.readOnly,v=s.type,h=s.setValue,x=s.focusOnClear,F=s.labelPlacement,O=s.size,g=s.elementsClassNames,y=s.isNext,A=s.isOpen,P=s.clearable,k=p||r.getDefaultFormat(v,C),T=o.useState(j(c,k)),M=l.default(T,2),D=M[0],N=M[1],R=o.useState(c),S=l.default(R,2),z=S[0],B=S[1],E=o.useRef(D);if(z!==c){var G=j(c,k);N(G),B(c),E.current=G}var U=o.useCallback((function(s){if(""===s.trim())return null==h||h(void 0),N(""),void(E.current="");var e=r.autocompleteValue({type:v,range:C,value:s,prevValue:E.current});if(E.current=e,N(e),C){var o=e.split(/[-–—]/).map((function(s){return q(s.trim(),k,v)})).filter((function(s){return!!s}));if(2===o.length){var c=r.getMinDate(o[0],o[1]),n=r.getMaxDate(o[0],o[1]);c&&n&&(null==h||h([c,n]))}}else{var i=q(e,k,v);i&&(null==h||h(i))}}),[k,C,h,v]),V=o.useCallback((function(s){s.target.select(),m()}),[m]),L=o.useCallback((function(){N(j(c,k)),E.current=""}),[c,k]),W=o.useCallback((function(){null==h||h(void 0),N("")}),[h]);return y?t.jsx(n.TextInputNext,{value:D,inputContainerRef:e,label:a,onFocus:V,onBlur:L,className:I,testId:d,suffix:t.jsx(u.CalendarThreeIcon,{}),placeholder:f,onChange:U,readOnly:b,clearable:P,focusOnClear:x,labelPlacement:F,size:O,elementsClassNames:g}):t.jsx(i.TextInput,{value:D,ref:e,label:a,onFocus:m,onBlur:L,forceLabelShrink:A,className:I,testId:d,suffix:t.jsx(u.CalendarThreeIcon,{}),placeholder:f,onChange:U,readOnly:b,onClear:P?W:void 0,focusOnClear:x})}));exports.Input=d;
|
|
2
2
|
//# sourceMappingURL=Input.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","sources":["../../../../../src/componentsV2/DatePicker/Input/Input.tsx"],"sourcesContent":["import { forwardRef, ReactNode, useCallback, useState } from 'react';\nimport moment from 'moment';\n\nimport { TextInputNext, TextInputNextProps } from '../../TextInputNext';\nimport { TextInput } from '../../TextInput';\nimport {\n
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../../../../src/componentsV2/DatePicker/Input/Input.tsx"],"sourcesContent":["import { FocusEventHandler, forwardRef, ReactNode, useCallback, useRef, useState } from 'react';\nimport moment from 'moment';\n\nimport { TextInputNext, TextInputNextProps } from '../../TextInputNext';\nimport { TextInput } from '../../TextInput';\nimport {\n autocompleteValue,\n DatePickerChangeHandler,\n DatePickerType,\n getDefaultFormat,\n getMaxDate,\n getMinDate,\n InputParseFormats,\n} from '../utils';\n\nimport { CalendarThreeIcon } from '~/icons';\n\nexport type InputProps = {\n value?: Date | [Date, Date];\n setValue?: (value: Date | [Date, Date] | undefined) => void;\n label?: ReactNode;\n placeholder?: string;\n open: () => void;\n type: DatePickerType;\n format?: string;\n range?: boolean;\n readOnly?: boolean;\n focusOnClear?: boolean;\n labelPlacement?: TextInputNextProps['labelPlacement'];\n size?: TextInputNextProps['size'];\n elementsClassNames?: TextInputNextProps['elementsClassNames'];\n clearable?: TextInputNextProps['clearable'];\n\n className?: string;\n testId?: string;\n\n // Remove when next becomes baseline\n isOpen: boolean;\n isNext: boolean;\n};\n\nconst formatValue = (value: Date | [Date, Date] | undefined, format: string) =>\n (Array.isArray(value) ? value : [value])\n .filter(item => !!item)\n .map(item => moment(item).format(format))\n .join(' - ');\n\nconst parseStringDate = (value: string, format: string, type: DatePickerType) => {\n const parsedMoment = moment(value, [format, ...(InputParseFormats[type] || [])], true);\n\n return parsedMoment.isValid() ? parsedMoment.toDate() : undefined;\n};\n\nexport const Input = forwardRef<HTMLDivElement, InputProps>(\n (\n {\n value,\n label,\n open,\n className,\n testId,\n format,\n placeholder,\n range,\n readOnly,\n type,\n setValue,\n focusOnClear,\n labelPlacement,\n size,\n elementsClassNames,\n isNext,\n isOpen,\n clearable,\n },\n ref\n ) => {\n const actualFormat = format || getDefaultFormat(type, range);\n const [inputValue, setInputValue] = useState(formatValue(value, actualFormat));\n const [prevValue, setPrevValue] = useState(value);\n const prevInputValueRef = useRef(inputValue);\n\n // Value changed - reconstructing input value\n if (prevValue !== value) {\n const newInputValue = formatValue(value, actualFormat);\n setInputValue(newInputValue);\n setPrevValue(value);\n prevInputValueRef.current = newInputValue;\n }\n\n const onChange = useCallback(\n (typedValue: string) => {\n if (typedValue.trim() === '') {\n setValue?.(undefined);\n setInputValue('');\n prevInputValueRef.current = '';\n return;\n }\n\n const newValue = autocompleteValue({\n type,\n range,\n value: typedValue,\n prevValue: prevInputValueRef.current,\n });\n\n prevInputValueRef.current = newValue;\n\n setInputValue(newValue);\n if (range) {\n // Splitting by hyphen, or en dash, or em dash\n const dateParts = newValue\n .split(/[-–—]/)\n .map(part => parseStringDate(part.trim(), actualFormat, type))\n .filter(part => !!part);\n\n if (dateParts.length === 2) {\n const minDate = getMinDate(dateParts[0], dateParts[1]);\n const maxDate = getMaxDate(dateParts[0], dateParts[1]);\n\n if (minDate && maxDate) {\n (setValue as DatePickerChangeHandler<true>)?.([minDate, maxDate]);\n }\n }\n } else {\n const maybeDate = parseStringDate(newValue, actualFormat, type);\n\n if (maybeDate) {\n (setValue as DatePickerChangeHandler<false>)?.(maybeDate);\n }\n }\n },\n [actualFormat, range, setValue, type]\n );\n\n const onFocus = useCallback<FocusEventHandler<HTMLInputElement>>(\n e => {\n e.target.select();\n open();\n },\n [open]\n );\n\n const onBlur = useCallback(() => {\n setInputValue(formatValue(value, actualFormat));\n prevInputValueRef.current = '';\n }, [value, actualFormat]);\n\n const onClear = useCallback(() => {\n setValue?.(undefined);\n setInputValue('');\n }, [setValue]);\n\n if (isNext) {\n return (\n <TextInputNext\n value={inputValue}\n inputContainerRef={ref}\n label={label}\n onFocus={onFocus}\n onBlur={onBlur}\n className={className}\n testId={testId}\n suffix={<CalendarThreeIcon />}\n placeholder={placeholder}\n onChange={onChange}\n readOnly={readOnly}\n clearable={clearable}\n focusOnClear={focusOnClear}\n labelPlacement={labelPlacement}\n size={size}\n elementsClassNames={elementsClassNames}\n />\n );\n }\n\n return (\n <TextInput\n value={inputValue}\n ref={ref as never}\n label={label}\n onFocus={open}\n onBlur={onBlur}\n forceLabelShrink={isOpen}\n className={className}\n testId={testId}\n suffix={<CalendarThreeIcon />}\n placeholder={placeholder}\n onChange={onChange}\n readOnly={readOnly}\n onClear={clearable ? onClear : undefined}\n focusOnClear={focusOnClear}\n />\n );\n }\n);\n"],"names":["formatValue","value","format","Array","isArray","filter","item","map","moment","join","parseStringDate","type","parsedMoment","concat","_toConsumableArray","InputParseFormats","isValid","toDate","undefined","Input","forwardRef","_ref","ref","label","open","className","testId","placeholder","range","readOnly","setValue","focusOnClear","labelPlacement","size","elementsClassNames","isNext","isOpen","clearable","actualFormat","getDefaultFormat","useState","_useState2","_slicedToArray","_useState","inputValue","setInputValue","_useState4","_useState3","prevValue","setPrevValue","prevInputValueRef","useRef","newInputValue","current","onChange","useCallback","typedValue","trim","newValue","autocompleteValue","dateParts","split","part","length","minDate","getMinDate","maxDate","getMaxDate","maybeDate","onFocus","e","target","select","onBlur","onClear","_jsx","TextInputNext","inputContainerRef","suffix","CalendarThreeIcon","TextInput","forceLabelShrink"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}Object.defineProperty(exports,"__esModule",{value:!0});var e=t(require("moment")),l={date:"DD MMM YYYY",dateTime:"DD MMM YYYY hh:mm A",month:"MMMM YYYY"},
|
|
1
|
+
"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}Object.defineProperty(exports,"__esModule",{value:!0});var e=t(require("moment")),l={date:"DD MMM YYYY",dateTime:"DD MMM YYYY hh:mm A",month:"MMMM YYYY"},n={date:"DD/MM/YYYY",dateTime:"DD/MM/YYYY hh:mm A",month:"MMM YYYY"},r=["D","M","Y","h","m","s","S"],i=[].concat(r,["A"]),a=new RegExp("^([^".concat(i.join(""),"]+)"),"gi"),o={month:"MM/YYYY",date:"DD/MM/YYYY",dateTime:"DD/MM/YYYY hh:mm A"},u={month:[o.month,"MMMM YYYY","MMM YYYY"],date:[o.date,"D/M/YYYY"],dateTime:[o.dateTime,"D/M/YYYY hh:mm A"]},Y=function(t,e){return!!t&&!!e&&t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()};exports.DefaultFormatByType=l,exports.DefaultFormatByTypeRange=n,exports.InputAutocompleteFormats=o,exports.InputParseFormats=u,exports.MonthOptions=[{id:1,title:"Jan",fullTitle:"January"},{id:2,title:"Feb",fullTitle:"February"},{id:3,title:"Mar",fullTitle:"March"},{id:4,title:"Apr",fullTitle:"April"},{id:5,title:"May",fullTitle:"May"},{id:6,title:"Jun",fullTitle:"June"},{id:7,title:"Jul",fullTitle:"July"},{id:8,title:"Aug",fullTitle:"August"},{id:9,title:"Sep",fullTitle:"September"},{id:10,title:"Oct",fullTitle:"October"},{id:11,title:"Nov",fullTitle:"November"},{id:12,title:"Dec",fullTitle:"December"}],exports.applyOffsetSeconds=function(t,l){return e.default(t).startOf("day").add(l,"seconds").toDate()},exports.autocompleteValue=function(t){var e=t.value,l=t.type,n=t.range,i=t.prevValue,u=o[l],Y=n?"".concat(u," - ").concat(u):u,M=e.toLocaleLowerCase().replace(/([ap])m/gi,"$1");if(e.length<=i.length||!function(t,e){return e.length<=t.length&&e.split("").every((function(e,l){var n,i=t[l];if(r.includes(i))return null==(n=e)?void 0:n.match(/\d/);if("A"===i){var a=e.toLocaleLowerCase();return"a"===a||"p"===a}return i===e}))}(Y,M)||Y.length<=M.length)return e;var c=function(t,e){var l;return(null===(l=t.substring(e).match(a))||void 0===l?void 0:l[0])||""}(Y,M.length);return"".concat(e).concat(c)},exports.getDefaultFormat=function(t,e){return(e?n:l)[t]},exports.getMaxDate=function(t,e){return t&&e?t>e?t:e:t||e},exports.getMinDate=function(t,e){return t&&e?t<e?t:e:t||e},exports.isSameDay=function(t,e){return Y(t,e)&&(null==t?void 0:t.getDate())===(null==e?void 0:e.getDate())},exports.isSameMonth=Y;
|
|
2
2
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../src/componentsV2/DatePicker/utils.tsx"],"sourcesContent":["import moment from 'moment';\n\nexport type DatePickerType = 'date' | 'dateTime' | 'month';\n\nexport type DatePickerValue<IsRange extends boolean | undefined = false> = IsRange extends\n | undefined\n | false\n ? Date | undefined\n : [Date, Date] | undefined;\n\nexport type DatePickerChangeHandler<IsRange extends boolean | undefined = false> = (\n value: DatePickerValue<IsRange>\n) => void;\n\n// startDate - initial state, no start date selected\n// startTime - start date selected, no time selected\n// endDate - start done, no end date selected\n// endTime - end date selected, no time selected\nexport type RangeSelectionStep = 'startDate' | 'startTime' | 'endDate' | 'endTime';\n\nexport const applyOffsetSeconds = (date: Date, offset: number) =>\n moment(date).startOf('day').add(offset, 'seconds').toDate();\n\nexport const DefaultFormatByType: Record<DatePickerType, string> = {\n date: 'DD MMM YYYY',\n dateTime: 'DD MMM YYYY hh:mm A',\n month: 'MMMM YYYY',\n};\n\nexport const DefaultFormatByTypeRange: Record<DatePickerType, string> = {\n date: 'DD/MM/YYYY',\n dateTime: 'DD/MM/YYYY hh:mm A',\n month: 'MMM YYYY',\n};\n\nexport const getDefaultFormat = (type: DatePickerType, range?: boolean) => {\n const map = range ? DefaultFormatByTypeRange : DefaultFormatByType;\n return map[type];\n};\n\nexport const
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../src/componentsV2/DatePicker/utils.tsx"],"sourcesContent":["import moment from 'moment';\n\nexport type DatePickerType = 'date' | 'dateTime' | 'month';\n\nexport type DatePickerValue<IsRange extends boolean | undefined = false> = IsRange extends\n | undefined\n | false\n ? Date | undefined\n : [Date, Date] | undefined;\n\nexport type DatePickerChangeHandler<IsRange extends boolean | undefined = false> = (\n value: DatePickerValue<IsRange>\n) => void;\n\n// startDate - initial state, no start date selected\n// startTime - start date selected, no time selected\n// endDate - start done, no end date selected\n// endTime - end date selected, no time selected\nexport type RangeSelectionStep = 'startDate' | 'startTime' | 'endDate' | 'endTime';\n\nexport const applyOffsetSeconds = (date: Date, offset: number) =>\n moment(date).startOf('day').add(offset, 'seconds').toDate();\n\nexport const DefaultFormatByType: Record<DatePickerType, string> = {\n date: 'DD MMM YYYY',\n dateTime: 'DD MMM YYYY hh:mm A',\n month: 'MMMM YYYY',\n};\n\nexport const DefaultFormatByTypeRange: Record<DatePickerType, string> = {\n date: 'DD/MM/YYYY',\n dateTime: 'DD/MM/YYYY hh:mm A',\n month: 'MMM YYYY',\n};\n\nexport const getDefaultFormat = (type: DatePickerType, range?: boolean) => {\n const map = range ? DefaultFormatByTypeRange : DefaultFormatByType;\n return map[type];\n};\n\nconst NumericLetters = ['D', 'M', 'Y', 'h', 'm', 's', 'S'];\nconst AllLetters = [...NumericLetters, 'A'];\nconst GetSeparatorRegex = new RegExp(`^([^${AllLetters.join('')}]+)`, 'gi');\n\n// These formats should be composed only of `AllLetters` as placeholders only\nexport const InputAutocompleteFormats: Record<DatePickerType, string> = {\n month: 'MM/YYYY',\n date: 'DD/MM/YYYY',\n dateTime: 'DD/MM/YYYY hh:mm A',\n};\n\nexport const InputParseFormats: Record<DatePickerType, string[]> = {\n month: [InputAutocompleteFormats.month, 'MMMM YYYY', 'MMM YYYY'],\n date: [InputAutocompleteFormats.date, 'D/M/YYYY'],\n dateTime: [InputAutocompleteFormats.dateTime, 'D/M/YYYY hh:mm A'],\n};\n\nconst isDigit = (symbol?: string) => symbol?.match(/\\d/);\n\nconst isInFormatSoFar = (format: string, value: string) => {\n if (value.length <= format.length) {\n const valueArr = value.split('');\n\n return valueArr.every((valueChar, pos) => {\n const formatChar = format[pos];\n\n if (NumericLetters.includes(formatChar)) {\n return isDigit(valueChar);\n }\n\n if (formatChar === 'A') {\n const lcChar = valueChar.toLocaleLowerCase();\n return lcChar === 'a' || lcChar === 'p';\n }\n\n return formatChar === valueChar;\n });\n }\n\n return false;\n};\n\nconst getSeparator = (format: string, startIndex: number) => {\n return format.substring(startIndex).match(GetSeparatorRegex)?.[0] || '';\n};\n\nexport const autocompleteValue = ({\n value,\n type,\n range,\n prevValue,\n}: {\n type: DatePickerType;\n range?: boolean;\n value: string;\n prevValue: string;\n}) => {\n const formatPart = InputAutocompleteFormats[type];\n const format = range ? `${formatPart} - ${formatPart}` : formatPart;\n\n const preparedValue = value.toLocaleLowerCase().replace(/([ap])m/gi, '$1');\n\n if (\n value.length <= prevValue.length ||\n !isInFormatSoFar(format, preparedValue) ||\n format.length <= preparedValue.length\n ) {\n return value;\n }\n\n // Only autocomplete if user types something\n // Check if conforms to format so far\n // Adding separators if needed\n const separator = getSeparator(format, preparedValue.length);\n\n return `${value}${separator}`;\n};\n\nexport const isSameMonth = (a?: Date, b?: Date) =>\n !!a && !!b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();\n\nexport const isSameDay = (a?: Date, b?: Date) => isSameMonth(a, b) && a?.getDate() === b?.getDate();\n\nexport const getMinDate = (a?: Date, b?: Date) => {\n if (a && b) {\n return a < b ? a : b;\n }\n\n return a || b;\n};\n\nexport const getMaxDate = (a?: Date, b?: Date) => {\n if (a && b) {\n return a > b ? a : b;\n }\n\n return a || b;\n};\n\nexport const MonthOptions = [\n { id: 1, title: 'Jan', fullTitle: 'January' },\n { id: 2, title: 'Feb', fullTitle: 'February' },\n { id: 3, title: 'Mar', fullTitle: 'March' },\n { id: 4, title: 'Apr', fullTitle: 'April' },\n { id: 5, title: 'May', fullTitle: 'May' },\n { id: 6, title: 'Jun', fullTitle: 'June' },\n { id: 7, title: 'Jul', fullTitle: 'July' },\n { id: 8, title: 'Aug', fullTitle: 'August' },\n { id: 9, title: 'Sep', fullTitle: 'September' },\n { id: 10, title: 'Oct', fullTitle: 'October' },\n { id: 11, title: 'Nov', fullTitle: 'November' },\n { id: 12, title: 'Dec', fullTitle: 'December' },\n];\n\nexport type DatePickerCalendarView = 'year' | 'month';\n"],"names":["DefaultFormatByType","date","dateTime","month","DefaultFormatByTypeRange","NumericLetters","AllLetters","concat","GetSeparatorRegex","RegExp","join","InputAutocompleteFormats","InputParseFormats","isSameMonth","a","b","getFullYear","getMonth","id","title","fullTitle","offset","moment","startOf","add","toDate","_ref","value","type","range","prevValue","formatPart","format","preparedValue","toLocaleLowerCase","replace","length","split","every","valueChar","pos","symbol","formatChar","includes","match","lcChar","isInFormatSoFar","separator","startIndex","_format$substring$mat","substring","getSeparator","getDate"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("@babel/runtime/helpers/slicedToArray"),
|
|
1
|
+
"use strict";var e=require("@babel/runtime/helpers/slicedToArray"),n=require("react"),t=require("../utils/signedLinkCache.js");function r(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i=r(e);module.exports=function(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"attachment",u=n.useState((function(){return e&&t.peekSignedLink(e,r)||""})),c=i.default(u,2),o=c[0],a=c[1];return n.useEffect((function(){var n=!0;return a(e&&t.peekSignedLink(e,r)||""),e&&t.getSignedLink(e,r).then((function(e){n&&a(e)})).catch((function(e){console.error(e),n&&a("")})),function(){n=!1}}),[e,r]),o};
|
|
2
2
|
//# sourceMappingURL=useSignedURL.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSignedURL.js","sources":["../../../src/effects/useSignedURL.js"],"sourcesContent":["import { useState, useEffect } from 'react';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useSignedURL.js","sources":["../../../src/effects/useSignedURL.js"],"sourcesContent":["import { useState, useEffect } from 'react';\n\nimport { getSignedLink, peekSignedLink } from '~/utils/signedLinkCache';\n\nfunction useSignedURL(fileName, contentDisposition = 'attachment') {\n const [signedURL, setSignedURL] = useState(\n () => (fileName && peekSignedLink(fileName, contentDisposition)) || ''\n );\n\n useEffect(() => {\n let isActive = true;\n\n // Drop the previous link right away: keeping it would describe the new file with the old URL.\n setSignedURL((fileName && peekSignedLink(fileName, contentDisposition)) || '');\n\n if (fileName) {\n getSignedLink(fileName, contentDisposition)\n .then(url => {\n if (isActive) setSignedURL(url);\n })\n .catch(error => {\n console.error(error);\n if (isActive) setSignedURL('');\n });\n }\n\n return () => {\n isActive = false;\n };\n }, [fileName, contentDisposition]);\n\n return signedURL;\n}\n\nexport default useSignedURL;\n"],"names":["fileName","contentDisposition","_useState","useState","peekSignedLink","_useState2","_slicedToArray","signedURL","setSignedURL","useEffect","isActive","getSignedLink","then","url","catch","error","console"],"mappings":"iOAIA,SAAsBA,GAA6C,IAAnCC,yDAAqB,aACnDC,EAAkCC,EAAAA,UAChC,WAAA,OAAOH,GAAYI,EAAcA,eAACJ,EAAUC,IAAwB,MACrEI,EAAAC,EAAAA,QAAAJ,EAAA,GAFMK,EAASF,EAAA,GAAEG,EAAYH,EAAA,GA0B9B,OAtBAI,EAAAA,WAAU,WACR,IAAIC,GAAW,EAgBf,OAbAF,EAAcR,GAAYI,EAAcA,eAACJ,EAAUC,IAAwB,IAEvED,GACFW,EAAAA,cAAcX,EAAUC,GACrBW,MAAK,SAAAC,GACAH,GAAUF,EAAaK,EAC7B,IACCC,OAAM,SAAAC,GACLC,QAAQD,MAAMA,GACVL,GAAUF,EAAa,GAC7B,IAGG,WACLE,GAAW,EAEf,GAAG,CAACV,EAAUC,IAEPM,CACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../clients/jsonApi/index.js"),t=new Map,n=function(e,t){return"".concat(t,":").concat(e)};exports.getSignedLink=function(r){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"attachment",o=n(r,i),a=t.get(o);if(a&&a.expiresAt>Date.now())return a.promise;var s={expiresAt:Date.now()+72e4,promise:e.getS3DownloadLink(r,i).then((function(e){var t=e.url;return s.url=t,t}))};return s.promise.catch((function(){t.get(o)===s&&t.delete(o)})),t.set(o,s),s.promise},exports.peekSignedLink=function(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"attachment",i=t.get(n(e,r));return i&&i.expiresAt>Date.now()?i.url:void 0};
|
|
2
|
+
//# sourceMappingURL=signedLinkCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signedLinkCache.js","sources":["../../../src/utils/signedLinkCache.ts"],"sourcesContent":["import { getS3DownloadLink } from '~/clients/jsonApi';\n\n/** Any Content-Disposition value the API accepts, usually plain 'attachment' or 'inline'. */\ntype Disposition = string;\n\n// S3 signs download links for fifteen minutes; leave the last recipient time to fetch.\nconst TTL_MS = 12 * 60 * 1000;\n\ntype CacheEntry = { promise: Promise<string>; url?: string; expiresAt: number };\n\nconst cache = new Map<string, CacheEntry>();\n\nconst toKey = (fileName: string, disposition: Disposition) => `${disposition}:${fileName}`;\n\n/** Cached `getS3DownloadLink`: remounts reuse the same url, so the browser HTTP cache holds. */\nexport const getSignedLink = (\n fileName: string,\n disposition: Disposition = 'attachment'\n): Promise<string> => {\n const key = toKey(fileName, disposition);\n const cached = cache.get(key);\n if (cached && cached.expiresAt > Date.now()) return cached.promise;\n\n const entry: CacheEntry = {\n expiresAt: Date.now() + TTL_MS,\n promise: getS3DownloadLink(fileName, disposition).then(({ url }: { url: string }) => {\n entry.url = url;\n\n return url;\n }),\n };\n entry.promise.catch(() => {\n if (cache.get(key) === entry) cache.delete(key);\n });\n cache.set(key, entry);\n\n return entry.promise;\n};\n\n/** The cached link when already resolved, for synchronous initial state. */\nexport const peekSignedLink = (\n fileName: string,\n disposition: Disposition = 'attachment'\n): string | undefined => {\n const cached = cache.get(toKey(fileName, disposition));\n\n return cached && cached.expiresAt > Date.now() ? cached.url : undefined;\n};\n\nexport const clearSignedLinkCache = (): void => cache.clear();\n"],"names":["cache","Map","toKey","fileName","disposition","key","cached","get","expiresAt","Date","now","promise","entry","getS3DownloadLink","then","_ref","url","catch","delete","set","undefined"],"mappings":"iHAUMA,EAAQ,IAAIC,IAEZC,EAAQ,SAACC,EAAkBC,GAAwB,MAAQA,GAAAA,OAAAA,cAAeD,EAAQ,wBAG3D,SAC3BA,GAEoB,IADpBC,yDAA2B,aAErBC,EAAMH,EAAMC,EAAUC,GACtBE,EAASN,EAAMO,IAAIF,GACzB,GAAIC,GAAUA,EAAOE,UAAYC,KAAKC,MAAO,OAAOJ,EAAOK,QAE3D,IAAMC,EAAoB,CACxBJ,UAAWC,KAAKC,MAlBL,KAmBXC,QAASE,EAAiBA,kBAACV,EAAUC,GAAaU,MAAK,SAA8BC,GAAA,IAA3BC,IAAAA,IAGxD,OAFAJ,EAAMI,IAAMA,EAELA,MAQX,OALAJ,EAAMD,QAAQM,OAAM,WACdjB,EAAMO,IAAIF,KAASO,GAAOZ,EAAMkB,OAAOb,EAC7C,IACAL,EAAMmB,IAAId,EAAKO,GAERA,EAAMD,OACf,yBAG8B,SAC5BR,GAEuB,IADvBC,yDAA2B,aAErBE,EAASN,EAAMO,IAAIL,EAAMC,EAAUC,IAEzC,OAAOE,GAAUA,EAAOE,UAAYC,KAAKC,MAAQJ,EAAOU,SAAMI,CAChE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStoredAttachments.d.ts","sourceRoot":"","sources":["../../../src/components/AttachmentPreview/useStoredAttachments.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"useStoredAttachments.d.ts","sourceRoot":"","sources":["../../../src/components/AttachmentPreview/useStoredAttachments.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AA0B9E;;;GAGG;AACH,eAAO,MAAM,oBAAoB,iBACjB,gBAAgB,EAAE,GAAG,IAAI,KACtC,qBAAqB,EA6DvB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import r from"@babel/runtime/helpers/defineProperty";import e from"@babel/runtime/helpers/slicedToArray";import n from"@babel/runtime/helpers/asyncToGenerator";import t from"@babel/runtime/regenerator";import{useState as o,useRef as
|
|
1
|
+
import r from"@babel/runtime/helpers/defineProperty";import e from"@babel/runtime/helpers/slicedToArray";import n from"@babel/runtime/helpers/asyncToGenerator";import t from"@babel/runtime/regenerator";import{useState as o,useRef as u,useMemo as c,useEffect as i}from"react";import{getAttachmentKind as a}from"./getAttachmentKind.js";import{getIsStoredKey as f}from"./useStoredAttachment.js";import{getSignedLink as m,peekSignedLink as s}from"../../utils/signedLinkCache.js";function p(r,e){var n=Object.keys(r);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(r);e&&(t=t.filter((function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable}))),n.push.apply(n,t)}return n}function l(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?p(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):p(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}var b=function(){var r=n(t.mark((function r(e){return t.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return r.prev=0,r.next=3,m(e,"inline");case 3:return r.abrupt("return",r.sent);case 6:return r.prev=6,r.t0=r.catch(0),console.error('Failed to sign attachment "'.concat(e,'"'),r.t0),r.abrupt("return","");case 10:case"end":return r.stop()}}),r,null,[[0,6]])})));return function(e){return r.apply(this,arguments)}}(),h=function(n){var t=o((function(){return function(r){return r.reduce((function(r,e){var n=f(e.name)?s(e.name,"inline"):e.url;return n&&(r[e.name]={src:n}),r}),{})}(null!=n?n:[])})),m=e(t,2),p=m[0],h=m[1],v=u(p);v.current=p;var O=c((function(){return null!=n?n:[]}),[n]),j=O.map((function(r){return r.name})).join("|");return i((function(){var e=O.filter((function(r){return!(r.name in v.current)}));if(e.length){var n=!0,t=function(e,n){return h((function(t){return l(l({},t),{},r({},e,l(l({},t[e]),n)))}))};return h((function(r){var n=l({},r);return e.forEach((function(r){var e;n[r.name]=null!==(e=n[r.name])&&void 0!==e?e:{}})),n})),e.forEach((function(r){f(r.name)?b(r.name).then((function(e){n&&e&&t(r.name,{src:e})})):t(r.name,{src:r.url})})),function(){n=!1}}}),[j]),O.reduce((function(r,e){var n=p[e.name];return null!=n&&n.src?(r.push({id:e.url,name:e.name,src:n.src,kind:a(e),size:e.size}),r):r}),[])};export{h as useStoredAttachments};
|
|
2
2
|
//# sourceMappingURL=useStoredAttachments.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStoredAttachments.js","sources":["../../../src/components/AttachmentPreview/useStoredAttachments.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { AttachmentPreviewItem } from './AttachmentPreview.types';\nimport { getAttachmentKind } from './getAttachmentKind';\nimport { getIsStoredKey, type StoredAttachment } from './useStoredAttachment';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useStoredAttachments.js","sources":["../../../src/components/AttachmentPreview/useStoredAttachments.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { AttachmentPreviewItem } from './AttachmentPreview.types';\nimport { getAttachmentKind } from './getAttachmentKind';\nimport { getIsStoredKey, type StoredAttachment } from './useStoredAttachment';\n\nimport { getSignedLink, peekSignedLink } from '~/utils/signedLinkCache';\n\ntype SignedLinks = Record<string, { src?: string }>;\n\nconst signStoredLink = async (name: string) => {\n try {\n return await getSignedLink(name, 'inline');\n } catch (error) {\n console.error(`Failed to sign attachment \"${name}\"`, error);\n\n return '';\n }\n};\n\nconst seedLinks = (attachments: StoredAttachment[]): SignedLinks =>\n attachments.reduce<SignedLinks>((acc, attachment) => {\n const src = getIsStoredKey(attachment.name)\n ? peekSignedLink(attachment.name, 'inline')\n : attachment.url;\n if (src) acc[attachment.name] = { src };\n\n return acc;\n }, {});\n\n/**\n * Signs a whole list of stored attachments — the hook-per-file `useStoredAttachment`\n * can't cover a list whose length changes between renders.\n */\nexport const useStoredAttachments = (\n attachments?: StoredAttachment[] | null\n): AttachmentPreviewItem[] => {\n const [links, setLinks] = useState<SignedLinks>(() => seedLinks(attachments ?? []));\n const linksRef = useRef(links);\n linksRef.current = links;\n\n const list = useMemo(() => attachments ?? [], [attachments]);\n const key = list.map(attachment => attachment.name).join('|');\n\n useEffect(() => {\n const pending = list.filter(attachment => !(attachment.name in linksRef.current));\n if (!pending.length) return undefined;\n\n let isActive = true;\n\n const applyLink = (name: string, patch: SignedLinks[string]) =>\n setLinks(prev => ({ ...prev, [name]: { ...prev[name], ...patch } }));\n\n // Claim the names up front so a re-render mid-flight does not ask again.\n setLinks(prev => {\n const claimed = { ...prev };\n\n pending.forEach(attachment => {\n claimed[attachment.name] = claimed[attachment.name] ?? {};\n });\n\n return claimed;\n });\n\n pending.forEach(attachment => {\n // A linked attachment already carries a url that works; only a key of ours needs signing.\n if (!getIsStoredKey(attachment.name)) {\n applyLink(attachment.name, { src: attachment.url });\n\n return;\n }\n\n signStoredLink(attachment.name).then(src => {\n if (isActive && src) applyLink(attachment.name, { src });\n });\n });\n\n return () => {\n isActive = false;\n };\n // `key` tracks the list contents; `list` itself is a fresh array on every render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n return list.reduce<AttachmentPreviewItem[]>((acc, attachment) => {\n const link = links[attachment.name];\n if (!link?.src) return acc;\n\n acc.push({\n id: attachment.url,\n name: attachment.name,\n src: link.src,\n kind: getAttachmentKind(attachment),\n size: attachment.size,\n });\n return acc;\n }, []);\n};\n"],"names":["signStoredLink","_ref","_asyncToGenerator","_regeneratorRuntime","mark","name","wrap","_context","prev","next","getSignedLink","abrupt","sent","t0","console","error","stop","_callee","_x","apply","this","arguments","useStoredAttachments","attachments","_useState","useState","reduce","acc","attachment","src","getIsStoredKey","peekSignedLink","url","seedLinks","_useState2","_slicedToArray","links","setLinks","linksRef","useRef","current","list","useMemo","key","map","join","useEffect","pending","filter","length","isActive","applyLink","patch","_objectSpread","claimed","forEach","_claimed$attachment$n","then","link","push","id","kind","getAttachmentKind","size"],"mappings":"0hCAUA,IAAMA,EAAc,WAAA,IAAAC,EAAAC,EAAAC,EAAAC,MAAG,WAAOC,GAAY,OAAAF,EAAAG,MAAA,SAAAC,GAAA,OAAA,OAAAA,EAAAC,KAAAD,EAAAE,MAAA,KAAA,EAAA,OAAAF,EAAAC,KAAA,EAAAD,EAAAE,KAAA,EAEzBC,EAAcL,EAAM,UAAS,KAAA,EAAA,OAAAE,EAAAI,OAAA,SAAAJ,EAAAK,MAAA,KAAA,EAEkB,OAFlBL,EAAAC,KAAA,EAAAD,EAAAM,GAAAN,EAAA,MAAA,GAE1CO,QAAQC,MAAoCV,8BAAAA,OAAAA,EAAe,KAAAE,EAAAM,IAACN,EAAAI,OAAA,SAErD,IAAE,KAAA,GAAA,IAAA,MAAA,OAAAJ,EAAAS,OAAA,GAAAC,EAAA,KAAA,CAAA,CAAA,EAAA,IAEZ,KAAA,OAAA,SARmBC,GAAA,OAAAjB,EAAAkB,MAAAC,KAAAC,UAAA,CAAA,CAAA,GAwBPC,EAAuB,SAClCC,GAEA,IAAAC,EAA0BC,GAAsB,WAAA,OAjBhC,SAACF,GAA+B,OAChDA,EAAYG,QAAoB,SAACC,EAAKC,GACpC,IAAMC,EAAMC,EAAeF,EAAWvB,MAClC0B,EAAeH,EAAWvB,KAAM,UAChCuB,EAAWI,IAGf,OAFIH,IAAKF,EAAIC,EAAWvB,MAAQ,CAAEwB,IAAAA,IAE3BF,CACR,GAAE,CAAE,EAAC,CASgDM,CAAUV,QAAAA,EAAe,OAAIW,EAAAC,EAAAX,EAAA,GAA5EY,EAAKF,EAAA,GAAEG,EAAQH,EAAA,GAChBI,EAAWC,EAAOH,GACxBE,EAASE,QAAUJ,EAEnB,IAAMK,EAAOC,GAAQ,WAAA,OAAMnB,QAAAA,EAAe,KAAI,CAACA,IACzCoB,EAAMF,EAAKG,KAAI,SAAAhB,GAAU,OAAIA,EAAWvB,IAAI,IAAEwC,KAAK,KA0CzD,OAxCAC,GAAU,WACR,IAAMC,EAAUN,EAAKO,QAAO,SAAApB,GAAU,QAAMA,EAAWvB,QAAQiC,EAASE,YACxE,GAAKO,EAAQE,OAAb,CAEA,IAAIC,GAAW,EAETC,EAAY,SAAC9C,EAAc+C,GAA0B,OACzDf,GAAS,SAAA7B,GAAI,OAAUA,EAAAA,EAAAA,CAAAA,EAAAA,WAAOH,EAAIgD,EAAAA,EAAA,CAAA,EAAQ7C,EAAKH,IAAU+C,IAAK,GAAM,EA0BtE,OAvBAf,GAAS,SAAA7B,GACP,IAAM8C,EAAe9C,EAAAA,CAAAA,EAAAA,GAMrB,OAJAuC,EAAQQ,SAAQ,SAAA3B,GAAc,IAAA4B,EAC5BF,EAAQ1B,EAAWvB,MAAgC,QAAxBiD,EAAAA,EAAQ1B,EAAWvB,aAAK,IAAAmD,EAAAA,EAAI,CAAA,CACzD,IAEOF,CACT,IAEAP,EAAQQ,SAAQ,SAAA3B,GAETE,EAAeF,EAAWvB,MAM/BL,EAAe4B,EAAWvB,MAAMoD,MAAK,SAAA5B,GAC/BqB,GAAYrB,GAAKsB,EAAUvB,EAAWvB,KAAM,CAAEwB,IAAAA,GACpD,IAPEsB,EAAUvB,EAAWvB,KAAM,CAAEwB,IAAKD,EAAWI,KAQjD,IAEO,WACLkB,GAAW,EAhCwB,CAoCvC,GAAG,CAACP,IAEGF,EAAKf,QAAgC,SAACC,EAAKC,GAChD,IAAM8B,EAAOtB,EAAMR,EAAWvB,MAC9B,OAAKqD,SAAAA,EAAM7B,KAEXF,EAAIgC,KAAK,CACPC,GAAIhC,EAAWI,IACf3B,KAAMuB,EAAWvB,KACjBwB,IAAK6B,EAAK7B,IACVgC,KAAMC,EAAkBlC,GACxBmC,KAAMnC,EAAWmC,OAEZpC,GATgBA,CAUxB,GAAE,GACL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAttachmentUpload.d.ts","sourceRoot":"","sources":["../../../src/components/CommentComposer/useAttachmentUpload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA4C,MAAM,OAAO,CAAC;AAG9E,OAAO,KAAK,EAEV,qBAAqB,EACtB,MAAM,8CAA8C,CAAC;
|
|
1
|
+
{"version":3,"file":"useAttachmentUpload.d.ts","sourceRoot":"","sources":["../../../src/components/CommentComposer/useAttachmentUpload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA4C,MAAM,OAAO,CAAC;AAG9E,OAAO,KAAK,EAEV,qBAAqB,EACtB,MAAM,8CAA8C,CAAC;AAQtD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAChC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,EAAE,CAAC,WAAW,EAAE,kBAAkB,EAAE,KAAK,IAAI,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAkD1C,eAAO,MAAM,mBAAmB,kEAO7B,0BAA0B;;;;8BAwMjB,WAAW,CAAC,gBAAgB,CAAC;sBApD7B,IAAI,EAAE;0BA7BR,MAAM;2BA6FP,qBAAqB,CAAC,IAAI,CAAC;sBAW3B,qBAAqB,CAAC,IAAI,CAAC;qCAcnB,qBAAqB,CAAC,IAAI,CAAC,EAAE;;;;;;;CA0H7C,CAAC"}
|