@dismissible/react-client 0.3.0 → 0.3.2-canary.2.38782c4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- (function(a,u){typeof exports=="object"&&typeof module!="undefined"?u(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],u):(a=typeof globalThis!="undefined"?globalThis:a||self,u(a.DismissibleClient={},a.React.jsxRuntime,a.React))})(this,function(a,u,l){"use strict";var Te=Object.defineProperty,Ue=Object.defineProperties;var qe=Object.getOwnPropertyDescriptors;var W=Object.getOwnPropertySymbols;var de=Object.prototype.hasOwnProperty,he=Object.prototype.propertyIsEnumerable;var fe=(a,u,l)=>u in a?Te(a,u,{enumerable:!0,configurable:!0,writable:!0,value:l}):a[u]=l,p=(a,u)=>{for(var l in u||(u={}))de.call(u,l)&&fe(a,l,u[l]);if(W)for(var l of W(u))he.call(u,l)&&fe(a,l,u[l]);return a},S=(a,u)=>Ue(a,qe(u));var Y=(a,u)=>{var l={};for(var C in a)de.call(a,C)&&u.indexOf(C)<0&&(l[C]=a[C]);if(a!=null&&W)for(var C of W(a))u.indexOf(C)<0&&he.call(a,C)&&(l[C]=a[C]);return l};var O=(a,u,l)=>new Promise((C,L)=>{var V=I=>{try{T(l.next(I))}catch(k){L(k)}},B=I=>{try{T(l.throw(I))}catch(k){L(k)}},T=I=>I.done?C(I.value):Promise.resolve(I.value).then(V,B);T((l=l.apply(a,u)).next())});const C=/\{[^{}]+\}/g,L=()=>{var e,r;return typeof process=="object"&&Number.parseInt((r=(e=process==null?void 0:process.versions)==null?void 0:e.node)==null?void 0:r.substring(0,2))>=18&&process.versions.undici};function V(){return Math.random().toString(36).slice(2,11)}function B(e){let U=p({},e),{baseUrl:r="",Request:t=globalThis.Request,fetch:n=globalThis.fetch,querySerializer:i,bodySerializer:s,headers:o,requestInitExt:d=void 0}=U,h=Y(U,["baseUrl","Request","fetch","querySerializer","bodySerializer","headers","requestInitExt"]);d=L()?d:void 0,r=te(r);const g=[];function E(f,c){return O(this,null,function*(){var ue;const ce=c||{},{baseUrl:A,fetch:D=n,Request:H=t,headers:x,params:$={},parseAs:F="json",querySerializer:z,bodySerializer:m=s!=null?s:ye,body:y}=ce,j=Y(ce,["baseUrl","fetch","Request","headers","params","parseAs","querySerializer","bodySerializer","body"]);let R=r;A&&(R=(ue=te(A))!=null?ue:r);let K=typeof i=="function"?i:Z(i);z&&(K=typeof z=="function"?z:Z(p(p({},typeof i=="object"?i:{}),z)));const Q=y===void 0?void 0:m(y,ee(o,x,$.header)),De=ee(Q===void 0||Q instanceof FormData?{}:{"Content-Type":"application/json"},o,x,$.header),$e=S(p(p({redirect:"follow"},h),j),{body:Q,headers:De});let J,M,q=new t(be(f,{baseUrl:R,params:$,querySerializer:K}),$e),b;for(const v in j)v in q||(q[v]=j[v]);if(g.length){J=V(),M=Object.freeze({baseUrl:R,fetch:D,parseAs:F,querySerializer:K,bodySerializer:m});for(const v of g)if(v&&typeof v=="object"&&typeof v.onRequest=="function"){const w=yield v.onRequest({request:q,schemaPath:f,params:$,options:M,id:J});if(w)if(w instanceof t)q=w;else if(w instanceof Response){b=w;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!b){try{b=yield D(q,d)}catch(v){let w=v;if(g.length)for(let P=g.length-1;P>=0;P--){const _=g[P];if(_&&typeof _=="object"&&typeof _.onError=="function"){const N=yield _.onError({request:q,error:w,schemaPath:f,params:$,options:M,id:J});if(N){if(N instanceof Response){w=void 0,b=N;break}if(N instanceof Error){w=N;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(w)throw w}if(g.length)for(let v=g.length-1;v>=0;v--){const w=g[v];if(w&&typeof w=="object"&&typeof w.onResponse=="function"){const P=yield w.onResponse({request:q,response:b,schemaPath:f,params:$,options:M,id:J});if(P){if(!(P instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");b=P}}}}if(b.status===204||q.method==="HEAD"||b.headers.get("Content-Length")==="0")return b.ok?{data:void 0,response:b}:{error:void 0,response:b};if(b.ok)return F==="stream"?{data:b.body,response:b}:{data:yield b[F](),response:b};let X=yield b.text();try{X=JSON.parse(X)}catch(v){}return{error:X,response:b}})}return{request(f,c,A){return E(c,S(p({},A),{method:f.toUpperCase()}))},GET(f,c){return E(f,S(p({},c),{method:"GET"}))},PUT(f,c){return E(f,S(p({},c),{method:"PUT"}))},POST(f,c){return E(f,S(p({},c),{method:"POST"}))},DELETE(f,c){return E(f,S(p({},c),{method:"DELETE"}))},OPTIONS(f,c){return E(f,S(p({},c),{method:"OPTIONS"}))},HEAD(f,c){return E(f,S(p({},c),{method:"HEAD"}))},PATCH(f,c){return E(f,S(p({},c),{method:"PATCH"}))},TRACE(f,c){return E(f,S(p({},c),{method:"TRACE"}))},use(...f){for(const c of f)if(c){if(typeof c!="object"||!("onRequest"in c||"onResponse"in c||"onError"in c))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");g.push(c)}},eject(...f){for(const c of f){const A=g.indexOf(c);A!==-1&&g.splice(A,1)}}}}function T(e,r,t){if(r==null)return"";if(typeof r=="object")throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");return`${e}=${(t==null?void 0:t.allowReserved)===!0?r:encodeURIComponent(r)}`}function I(e,r,t){if(!r||typeof r!="object")return"";const n=[],i={simple:",",label:".",matrix:";"}[t.style]||"&";if(t.style!=="deepObject"&&t.explode===!1){for(const d in r)n.push(d,t.allowReserved===!0?r[d]:encodeURIComponent(r[d]));const o=n.join(",");switch(t.style){case"form":return`${e}=${o}`;case"label":return`.${o}`;case"matrix":return`;${e}=${o}`;default:return o}}for(const o in r){const d=t.style==="deepObject"?`${e}[${o}]`:o;n.push(T(d,r[o],t))}const s=n.join(i);return t.style==="label"||t.style==="matrix"?`${i}${s}`:s}function k(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const s={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",o=(t.allowReserved===!0?r:r.map(d=>encodeURIComponent(d))).join(s);switch(t.style){case"simple":return o;case"label":return`.${o}`;case"matrix":return`;${e}=${o}`;default:return`${e}=${o}`}}const n={simple:",",label:".",matrix:";"}[t.style]||"&",i=[];for(const s of r)t.style==="simple"||t.style==="label"?i.push(t.allowReserved===!0?s:encodeURIComponent(s)):i.push(T(e,s,t));return t.style==="label"||t.style==="matrix"?`${n}${i.join(n)}`:i.join(n)}function Z(e){return function(t){const n=[];if(t&&typeof t=="object")for(const i in t){const s=t[i];if(s!=null){if(Array.isArray(s)){if(s.length===0)continue;n.push(k(i,s,S(p({style:"form",explode:!0},e==null?void 0:e.array),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}if(typeof s=="object"){n.push(I(i,s,S(p({style:"deepObject",explode:!0},e==null?void 0:e.object),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}n.push(T(i,s,e))}}return n.join("&")}}function me(e,r){var n;let t=e;for(const i of(n=e.match(C))!=null?n:[]){let s=i.substring(1,i.length-1),o=!1,d="simple";if(s.endsWith("*")&&(o=!0,s=s.substring(0,s.length-1)),s.startsWith(".")?(d="label",s=s.substring(1)):s.startsWith(";")&&(d="matrix",s=s.substring(1)),!r||r[s]===void 0||r[s]===null)continue;const h=r[s];if(Array.isArray(h)){t=t.replace(i,k(s,h,{style:d,explode:o}));continue}if(typeof h=="object"){t=t.replace(i,I(s,h,{style:d,explode:o}));continue}if(d==="matrix"){t=t.replace(i,`;${T(s,h)}`);continue}t=t.replace(i,d==="label"?`.${encodeURIComponent(h)}`:encodeURIComponent(h))}return t}function ye(e,r){var t,n;return e instanceof FormData?e:r&&(r.get instanceof Function?(t=r.get("Content-Type"))!=null?t:r.get("content-type"):(n=r["Content-Type"])!=null?n:r["content-type"])==="application/x-www-form-urlencoded"?new URLSearchParams(e).toString():JSON.stringify(e)}function be(e,r){var i,s;let t=`${r.baseUrl}${e}`;(i=r.params)!=null&&i.path&&(t=me(t,r.params.path));let n=r.querySerializer((s=r.params.query)!=null?s:{});return n.startsWith("?")&&(n=n.substring(1)),n&&(t+=`?${n}`),t}function ee(...e){const r=new Headers;for(const t of e){if(!t||typeof t!="object")continue;const n=t instanceof Headers?t.entries():Object.entries(t);for(const[i,s]of n)if(s===null)r.delete(i);else if(Array.isArray(s))for(const o of s)r.append(i,o);else s!==void 0&&r.set(i,s)}return r}function te(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const pe={baseUrl:"http://localhost:3200"},ge={development:{baseUrl:"http://localhost:3200"},staging:{baseUrl:"https://api.staging.dismissible.io"},production:{baseUrl:"https://api.dismissible.io"}},we=()=>ge["production"]||pe,re=(e,r,t)=>{try{const n=`${r}_${e}`,i=localStorage.getItem(n);if(!i)return null;const{data:s,timestamp:o}=JSON.parse(i);return t&&Date.now()-o>t?(localStorage.removeItem(n),null):s}catch(n){return null}},se=(e,r,t)=>{try{const n=`${t}_${e}`,i={data:r,timestamp:Date.now()};localStorage.setItem(n,JSON.stringify(i))}catch(n){console.warn("Failed to cache dismissible item:",n)}},ne=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},G=l.createContext(null),ie=()=>l.useContext(G),ve="dismissible",oe=(e,r={})=>{var z;const{initialData:t,enableCache:n=!0,cachePrefix:i=ve,cacheExpiration:s}=r,o=ie(),d=l.useMemo(()=>{const m=we(),y=(o==null?void 0:o.baseUrl)||m.baseUrl;return B({baseUrl:y,headers:{}})},[o]),h=l.useMemo(()=>!!(o!=null&&o.jwt)?`${e}-auth`:e,[e,o==null?void 0:o.jwt]),g=l.useRef({enableCache:n,cachePrefix:i,cacheExpiration:s}),E=l.useRef(e),U=l.useRef(h),[f,c]=l.useState(!1),[A,D]=l.useState(null),[H,x]=l.useState(()=>{if(t)return t;if(n){const m=re(h,i,s);if(m)return m}}),$=l.useCallback(()=>O(this,null,function*(){var m;if(n){const y=re(h,i,s);if(y!=null&&y.dismissedAt){x(y),c(!1);return}}c(!0),D(null);try{const y=o!=null&&o.getAuthHeaders?yield o.getAuthHeaders():{},{data:j,error:R}=yield d.GET("/v1/dismissible/{itemId}",{params:{path:{itemId:e}},headers:y});if(R)throw new Error(((m=R==null?void 0:R.error)==null?void 0:m.message)||"Failed to fetch dismissible item");x(j.data),n&&j.data&&se(h,j.data,i)}catch(y){D(y instanceof Error?y:new Error("Unknown error occurred"))}finally{c(!1)}}),[e,h,n,i,s,d,o]);l.useEffect(()=>{const m=E.current!==e,y=U.current!==h;m||y?(E.current=e,U.current=h,$()):t||$()},[e,h,t]),l.useEffect(()=>{const m=g.current;(m.enableCache!==n||m.cachePrefix!==i||m.cacheExpiration!==s)&&(m.cachePrefix!==i&&ne(h,m.cachePrefix),!n&&m.enableCache&&ne(h,i),g.current={enableCache:n,cachePrefix:i,cacheExpiration:s},$())},[n,i,s,h]);const F=l.useCallback(()=>O(this,null,function*(){var m;D(null);try{const y=o!=null&&o.getAuthHeaders?yield o.getAuthHeaders():{},{data:j,error:R}=yield d.DELETE("/v1/dismissible/{itemId}",{params:{path:{itemId:e}},headers:y});if(R)throw new Error(((m=R==null?void 0:R.error)==null?void 0:m.message)||"Failed to dismiss item");x(j.data),n&&j.data&&se(h,j.data,i)}catch(y){throw D(y instanceof Error?y:new Error("Failed to dismiss item")),y}}),[h,n,i,d,o]);return{dismissedOn:(z=H==null?void 0:H.dismissedAt)!=null?z:null,dismiss:F,isLoading:f,error:A,item:H}},Ee=()=>u.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),Ce=({error:e})=>u.jsxs("div",{className:"dismissible-error",role:"alert",children:["Error loading dismissible item: ",e.message]}),Re=({id:e,onDismiss:r,ariaLabel:t})=>u.jsx("button",{id:e,className:"dismissible-button",onClick:r,"aria-label":t,type:"button",children:"×"}),Se=({id:e,children:r,onDismiss:t,LoadingComponent:n=Ee,ErrorComponent:i=Ce,DismissButtonComponent:s=Re,enableCache:o,cachePrefix:d,cacheExpiration:h,ignoreErrors:g=!1})=>{const{dismissedOn:E,isLoading:U,error:f,dismiss:c}=oe(e,{enableCache:o,cachePrefix:d,cacheExpiration:h}),[A,D]=l.useState(!1),H=()=>O(this,null,function*(){D(!0);try{yield c(),t==null||t()}catch(x){D(!1)}});return U&&n?u.jsx(n,{id:e}):U&&!n?null:f&&i&&!g?u.jsx(i,{id:e,error:f}):E||A?null:u.jsxs("div",{className:"dismissible-container",children:[u.jsx("div",{className:"dismissible-content",children:r}),s?u.jsx(s,{id:e,onDismiss:H,ariaLabel:`Dismiss ${e}`}):null]})},ae=e=>O(this,null,function*(){if(typeof e=="function")try{const r=e();return yield Promise.resolve(r)}catch(r){console.warn("Failed to resolve JWT from function:",r);return}return e}),le=e=>O(this,null,function*(){const r=yield ae(e);return r?{Authorization:`Bearer ${r}`}:{}}),je=e=>{const r=e.split(".");return r.length===3&&r.every(t=>t.length>0)},Ae=({jwt:e,baseUrl:r,children:t})=>{const n=l.useMemo(()=>({jwt:e,baseUrl:r,getAuthHeaders:()=>O(this,null,function*(){return yield le(e)})}),[e,r]);return u.jsx(G.Provider,{value:n,children:t})},Ie="0.3.0";a.Dismissible=Se,a.DismissibleContext=G,a.DismissibleProvider=Ae,a.VERSION=Ie,a.getAuthHeaders=le,a.isValidJwtFormat=je,a.resolveJwt=ae,a.useDismissibleContext=ie,a.useDismissibleItem=oe,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
1
+ (function(a,d){typeof exports=="object"&&typeof module!="undefined"?d(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],d):(a=typeof globalThis!="undefined"?globalThis:a||self,d(a.DismissibleClient={},a.React.jsxRuntime,a.React))})(this,function(a,d,o){"use strict";var Ue=Object.defineProperty,qe=Object.defineProperties;var Oe=Object.getOwnPropertyDescriptors;var V=Object.getOwnPropertySymbols;var he=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var me=(a,d,o)=>d in a?Ue(a,d,{enumerable:!0,configurable:!0,writable:!0,value:o}):a[d]=o,y=(a,d)=>{for(var o in d||(d={}))he.call(d,o)&&me(a,o,d[o]);if(V)for(var o of V(d))be.call(d,o)&&me(a,o,d[o]);return a},S=(a,d)=>qe(a,Oe(d));var ee=(a,d)=>{var o={};for(var C in a)he.call(a,C)&&d.indexOf(C)<0&&(o[C]=a[C]);if(a!=null&&V)for(var C of V(a))d.indexOf(C)<0&&be.call(a,C)&&(o[C]=a[C]);return o};var H=(a,d,o)=>new Promise((C,M)=>{var B=I=>{try{$(o.next(I))}catch(k){M(k)}},G=I=>{try{$(o.throw(I))}catch(k){M(k)}},$=I=>I.done?C(I.value):Promise.resolve(I.value).then(B,G);$((o=o.apply(a,d)).next())});const C=/\{[^{}]+\}/g,M=()=>{var e,r;return typeof process=="object"&&Number.parseInt((r=(e=process==null?void 0:process.versions)==null?void 0:e.node)==null?void 0:r.substring(0,2))>=18&&process.versions.undici};function B(){return Math.random().toString(36).slice(2,11)}function G(e){let x=y({},e),{baseUrl:r="",Request:t=globalThis.Request,fetch:i=globalThis.fetch,querySerializer:n,bodySerializer:s,headers:c,requestInitExt:m=void 0}=x,p=ee(x,["baseUrl","Request","fetch","querySerializer","bodySerializer","headers","requestInitExt"]);m=M()?m:void 0,r=se(r);const h=[];function v(l,u){return H(this,null,function*(){var de;const fe=u||{},{baseUrl:R,fetch:A=i,Request:j=t,headers:T,params:D={},parseAs:P="json",querySerializer:F,bodySerializer:N=s!=null?s:pe,body:f,middleware:E=[]}=fe,U=ee(fe,["baseUrl","fetch","Request","headers","params","parseAs","querySerializer","bodySerializer","body","middleware"]);let Q=r;R&&(Q=(de=se(R))!=null?de:r);let X=typeof n=="function"?n:te(n);F&&(X=typeof F=="function"?F:te(y(y({},typeof n=="object"?n:{}),F)));const Y=f===void 0?void 0:N(f,re(c,T,D.header)),Ae=re(Y===void 0||Y instanceof FormData?{}:{"Content-Type":"application/json"},c,T,D.header),q=[...h,...E],Te=S(y(y({redirect:"follow"},p),U),{body:Y,headers:Ae});let J,_,O=new j(we(l,{baseUrl:Q,params:D,querySerializer:X}),Te),b;for(const g in U)g in O||(O[g]=U[g]);if(q.length){J=B(),_=Object.freeze({baseUrl:Q,fetch:A,parseAs:P,querySerializer:X,bodySerializer:N});for(const g of q)if(g&&typeof g=="object"&&typeof g.onRequest=="function"){const w=yield g.onRequest({request:O,schemaPath:l,params:D,options:_,id:J});if(w)if(w instanceof j)O=w;else if(w instanceof Response){b=w;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!b){try{b=yield A(O,m)}catch(g){let w=g;if(q.length)for(let z=q.length-1;z>=0;z--){const W=q[z];if(W&&typeof W=="object"&&typeof W.onError=="function"){const L=yield W.onError({request:O,error:w,schemaPath:l,params:D,options:_,id:J});if(L){if(L instanceof Response){w=void 0,b=L;break}if(L instanceof Error){w=L;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(w)throw w}if(q.length)for(let g=q.length-1;g>=0;g--){const w=q[g];if(w&&typeof w=="object"&&typeof w.onResponse=="function"){const z=yield w.onResponse({request:O,response:b,schemaPath:l,params:D,options:_,id:J});if(z){if(!(z instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");b=z}}}}if(b.status===204||O.method==="HEAD"||b.headers.get("Content-Length")==="0")return b.ok?{data:void 0,response:b}:{error:void 0,response:b};if(b.ok)return P==="stream"?{data:b.body,response:b}:{data:yield b[P](),response:b};let Z=yield b.text();try{Z=JSON.parse(Z)}catch(g){}return{error:Z,response:b}})}return{request(l,u,R){return v(u,S(y({},R),{method:l.toUpperCase()}))},GET(l,u){return v(l,S(y({},u),{method:"GET"}))},PUT(l,u){return v(l,S(y({},u),{method:"PUT"}))},POST(l,u){return v(l,S(y({},u),{method:"POST"}))},DELETE(l,u){return v(l,S(y({},u),{method:"DELETE"}))},OPTIONS(l,u){return v(l,S(y({},u),{method:"OPTIONS"}))},HEAD(l,u){return v(l,S(y({},u),{method:"HEAD"}))},PATCH(l,u){return v(l,S(y({},u),{method:"PATCH"}))},TRACE(l,u){return v(l,S(y({},u),{method:"TRACE"}))},use(...l){for(const u of l)if(u){if(typeof u!="object"||!("onRequest"in u||"onResponse"in u||"onError"in u))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");h.push(u)}},eject(...l){for(const u of l){const R=h.indexOf(u);R!==-1&&h.splice(R,1)}}}}function $(e,r,t){if(r==null)return"";if(typeof r=="object")throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");return`${e}=${(t==null?void 0:t.allowReserved)===!0?r:encodeURIComponent(r)}`}function I(e,r,t){if(!r||typeof r!="object")return"";const i=[],n={simple:",",label:".",matrix:";"}[t.style]||"&";if(t.style!=="deepObject"&&t.explode===!1){for(const m in r)i.push(m,t.allowReserved===!0?r[m]:encodeURIComponent(r[m]));const c=i.join(",");switch(t.style){case"form":return`${e}=${c}`;case"label":return`.${c}`;case"matrix":return`;${e}=${c}`;default:return c}}for(const c in r){const m=t.style==="deepObject"?`${e}[${c}]`:c;i.push($(m,r[c],t))}const s=i.join(n);return t.style==="label"||t.style==="matrix"?`${n}${s}`:s}function k(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const s={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",c=(t.allowReserved===!0?r:r.map(m=>encodeURIComponent(m))).join(s);switch(t.style){case"simple":return c;case"label":return`.${c}`;case"matrix":return`;${e}=${c}`;default:return`${e}=${c}`}}const i={simple:",",label:".",matrix:";"}[t.style]||"&",n=[];for(const s of r)t.style==="simple"||t.style==="label"?n.push(t.allowReserved===!0?s:encodeURIComponent(s)):n.push($(e,s,t));return t.style==="label"||t.style==="matrix"?`${i}${n.join(i)}`:n.join(i)}function te(e){return function(t){const i=[];if(t&&typeof t=="object")for(const n in t){const s=t[n];if(s!=null){if(Array.isArray(s)){if(s.length===0)continue;i.push(k(n,s,S(y({style:"form",explode:!0},e==null?void 0:e.array),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}if(typeof s=="object"){i.push(I(n,s,S(y({style:"deepObject",explode:!0},e==null?void 0:e.object),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}i.push($(n,s,e))}}return i.join("&")}}function ye(e,r){var i;let t=e;for(const n of(i=e.match(C))!=null?i:[]){let s=n.substring(1,n.length-1),c=!1,m="simple";if(s.endsWith("*")&&(c=!0,s=s.substring(0,s.length-1)),s.startsWith(".")?(m="label",s=s.substring(1)):s.startsWith(";")&&(m="matrix",s=s.substring(1)),!r||r[s]===void 0||r[s]===null)continue;const p=r[s];if(Array.isArray(p)){t=t.replace(n,k(s,p,{style:m,explode:c}));continue}if(typeof p=="object"){t=t.replace(n,I(s,p,{style:m,explode:c}));continue}if(m==="matrix"){t=t.replace(n,`;${$(s,p)}`);continue}t=t.replace(n,m==="label"?`.${encodeURIComponent(p)}`:encodeURIComponent(p))}return t}function pe(e,r){var t,i;return e instanceof FormData?e:r&&(r.get instanceof Function?(t=r.get("Content-Type"))!=null?t:r.get("content-type"):(i=r["Content-Type"])!=null?i:r["content-type"])==="application/x-www-form-urlencoded"?new URLSearchParams(e).toString():JSON.stringify(e)}function we(e,r){var n,s;let t=`${r.baseUrl}${e}`;(n=r.params)!=null&&n.path&&(t=ye(t,r.params.path));let i=r.querySerializer((s=r.params.query)!=null?s:{});return i.startsWith("?")&&(i=i.substring(1)),i&&(t+=`?${i}`),t}function re(...e){const r=new Headers;for(const t of e){if(!t||typeof t!="object")continue;const i=t instanceof Headers?t.entries():Object.entries(t);for(const[n,s]of i)if(s===null)r.delete(n);else if(Array.isArray(s))for(const c of s)r.append(n,c);else s!==void 0&&r.set(n,s)}return r}function se(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const ge={baseUrl:"http://localhost:3001"},ve={development:{baseUrl:"http://localhost:3001"},staging:{baseUrl:"https://api.staging.dismissible.io"},production:{baseUrl:"https://api.dismissible.io"}},Ee=()=>ve["production"]||ge,ne=(e,r,t)=>{try{const i=`${r}_${e}`,n=localStorage.getItem(i);if(!n)return null;const{data:s,timestamp:c}=JSON.parse(n);return t&&Date.now()-c>t?(localStorage.removeItem(i),null):s}catch(i){return null}},ie=(e,r,t)=>{try{const i=`${t}_${e}`,n={data:r,timestamp:Date.now()};localStorage.setItem(i,JSON.stringify(n))}catch(i){console.warn("Failed to cache dismissible item:",i)}},oe=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},K=o.createContext(null),ae=()=>{const e=o.useContext(K);if(!e)throw new Error("useDismissibleContext must be used within a DismissibleProvider");return e},Ce="dismissible",ce=(e,r={})=>{var N;const{initialData:t,enableCache:i=!0,cachePrefix:n=Ce,cacheExpiration:s}=r,c=ae(),{userId:m}=c,p=o.useMemo(()=>{const f=Ee(),E=c.baseUrl||f.baseUrl;return G({baseUrl:E,headers:{}})},[c]),h=o.useMemo(()=>`${m}-${e}`,[m,e]),v=o.useRef({enableCache:i,cachePrefix:n,cacheExpiration:s}),x=o.useRef(e),l=o.useRef(h),[u,R]=o.useState(!1),[A,j]=o.useState(null),[T,D]=o.useState(()=>{if(t)return t;if(i){const f=ne(h,n,s);if(f)return f}}),P=o.useCallback(()=>H(this,null,function*(){if(i){const f=ne(h,n,s);if(f!=null&&f.dismissedAt){D(f),R(!1);return}}R(!0),j(null);try{const f=yield c.getAuthHeaders(),{data:E,error:U}=yield p.GET("/v1/user/{userId}/dismissible-item/{itemId}",{params:{path:{userId:m,itemId:e}},headers:f});if(U||!E)throw new Error("Failed to fetch dismissible item");D(E.data),i&&ie(h,E.data,n)}catch(f){j(f instanceof Error?f:new Error("Unknown error occurred"))}finally{R(!1)}}),[e,m,h,i,n,s,p,c]);o.useEffect(()=>{const f=x.current!==e,E=l.current!==h;f||E?(x.current=e,l.current=h,P()):t||P()},[e,h,t]),o.useEffect(()=>{const f=v.current;(f.enableCache!==i||f.cachePrefix!==n||f.cacheExpiration!==s)&&(f.cachePrefix!==n&&oe(h,f.cachePrefix),!i&&f.enableCache&&oe(h,n),v.current={enableCache:i,cachePrefix:n,cacheExpiration:s},P())},[i,n,s,h]);const F=o.useCallback(()=>H(this,null,function*(){j(null);try{const f=yield c.getAuthHeaders(),{data:E,error:U}=yield p.DELETE("/v1/user/{userId}/dismissible-item/{itemId}",{params:{path:{userId:m,itemId:e}},headers:f});if(U||!E)throw new Error("Failed to dismiss item");D(E.data),i&&ie(h,E.data,n)}catch(f){throw j(f instanceof Error?f:new Error("Failed to dismiss item")),f}}),[e,m,h,i,n,p,c]);return{dismissedOn:(N=T==null?void 0:T.dismissedAt)!=null?N:null,dismiss:F,isLoading:u,error:A,item:T}},Re=()=>d.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),Se=({error:e})=>d.jsxs("div",{className:"dismissible-error",role:"alert",children:["Error loading dismissible item: ",e.message]}),Ie=({id:e,onDismiss:r,ariaLabel:t})=>d.jsx("button",{id:e,className:"dismissible-button",onClick:r,"aria-label":t,type:"button",children:"×"}),De=({id:e,children:r,onDismiss:t,LoadingComponent:i=Re,ErrorComponent:n=Se,DismissButtonComponent:s=Ie,enableCache:c,cachePrefix:m,cacheExpiration:p,ignoreErrors:h=!1})=>{const{dismissedOn:v,isLoading:x,error:l,dismiss:u}=ce(e,{enableCache:c,cachePrefix:m,cacheExpiration:p}),[R,A]=o.useState(!1);o.useEffect(()=>{A(!1)},[e]);const j=()=>H(this,null,function*(){A(!0);try{yield u(),t==null||t()}catch(T){A(!1)}});return x&&i?d.jsx(i,{id:e}):x&&!i?null:l&&n&&!h?d.jsx(n,{id:e,error:l}):v||R?null:d.jsxs("div",{className:"dismissible-container",children:[d.jsx("div",{className:"dismissible-content",children:r}),s?d.jsx(s,{id:e,onDismiss:j,ariaLabel:`Dismiss ${e}`}):null]})},le=e=>H(this,null,function*(){if(typeof e=="function")try{const r=e();return yield Promise.resolve(r)}catch(r){console.warn("Failed to resolve JWT from function:",r);return}return e}),ue=e=>H(this,null,function*(){const r=yield le(e);return r?{Authorization:`Bearer ${r}`}:{}}),je=e=>{const r=e.split(".");return r.length===3&&r.every(t=>t.length>0)},$e=({userId:e,jwt:r,baseUrl:t,children:i})=>{const n=o.useMemo(()=>({userId:e,jwt:r,baseUrl:t,getAuthHeaders:()=>H(this,null,function*(){return yield ue(r)})}),[e,r,t]);return d.jsx(K.Provider,{value:n,children:i})},xe="0.3.1";a.Dismissible=De,a.DismissibleContext=K,a.DismissibleProvider=$e,a.VERSION=xe,a.getAuthHeaders=ue,a.isValidJwtFormat=je,a.resolveJwt=le,a.useDismissibleContext=ae,a.useDismissibleItem=ce,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
@@ -1,5 +1,5 @@
1
1
  import { components } from '../generated/contract';
2
- type DismissibleItem = components["schemas"]["DismissibleResponseDto"];
2
+ type DismissibleItem = components["schemas"]["DismissibleItemResponseDto"];
3
3
  export type IDismissibleItem = DismissibleItem;
4
4
  export interface UseDismissibleItemOptions {
5
5
  /** Initial data for the dismissible item */
@@ -23,12 +23,13 @@ export declare const useDismissibleItem: (id: string, options?: UseDismissibleIt
23
23
  isLoading: boolean;
24
24
  error: Error | null;
25
25
  item: {
26
- key: string;
27
- id: string;
28
- accountId: string;
26
+ itemId: string;
27
+ userId: string;
29
28
  createdAt: string;
30
- dismissedAt?: string | null;
31
- expiresAt?: string | null;
29
+ dismissedAt?: string;
30
+ metadata?: {
31
+ [key: string]: unknown;
32
+ };
32
33
  } | undefined;
33
34
  };
34
35
  export {};
@@ -7,8 +7,8 @@
7
7
  * - Please do NOT modify this file.
8
8
  */
9
9
 
10
- const PACKAGE_VERSION = '2.10.3'
11
- const INTEGRITY_CHECKSUM = 'f5825c521429caf22a4dd13b66e243af'
10
+ const PACKAGE_VERSION = '2.12.4'
11
+ const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82'
12
12
  const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
13
13
  const activeClientIds = new Set()
14
14
 
@@ -71,11 +71,6 @@ addEventListener('message', async function (event) {
71
71
  break
72
72
  }
73
73
 
74
- case 'MOCK_DEACTIVATE': {
75
- activeClientIds.delete(clientId)
76
- break
77
- }
78
-
79
74
  case 'CLIENT_CLOSED': {
80
75
  activeClientIds.delete(clientId)
81
76
 
@@ -94,6 +89,8 @@ addEventListener('message', async function (event) {
94
89
  })
95
90
 
96
91
  addEventListener('fetch', function (event) {
92
+ const requestInterceptedAt = Date.now()
93
+
97
94
  // Bypass navigation requests.
98
95
  if (event.request.mode === 'navigate') {
99
96
  return
@@ -110,23 +107,29 @@ addEventListener('fetch', function (event) {
110
107
 
111
108
  // Bypass all requests when there are no active clients.
112
109
  // Prevents the self-unregistered worked from handling requests
113
- // after it's been deleted (still remains active until the next reload).
110
+ // after it's been terminated (still remains active until the next reload).
114
111
  if (activeClientIds.size === 0) {
115
112
  return
116
113
  }
117
114
 
118
115
  const requestId = crypto.randomUUID()
119
- event.respondWith(handleRequest(event, requestId))
116
+ event.respondWith(handleRequest(event, requestId, requestInterceptedAt))
120
117
  })
121
118
 
122
119
  /**
123
120
  * @param {FetchEvent} event
124
121
  * @param {string} requestId
122
+ * @param {number} requestInterceptedAt
125
123
  */
126
- async function handleRequest(event, requestId) {
124
+ async function handleRequest(event, requestId, requestInterceptedAt) {
127
125
  const client = await resolveMainClient(event)
128
126
  const requestCloneForEvents = event.request.clone()
129
- const response = await getResponse(event, client, requestId)
127
+ const response = await getResponse(
128
+ event,
129
+ client,
130
+ requestId,
131
+ requestInterceptedAt,
132
+ )
130
133
 
131
134
  // Send back the response clone for the "response:*" life-cycle events.
132
135
  // Ensure MSW is active and ready to handle the message, otherwise
@@ -202,9 +205,10 @@ async function resolveMainClient(event) {
202
205
  * @param {FetchEvent} event
203
206
  * @param {Client | undefined} client
204
207
  * @param {string} requestId
208
+ * @param {number} requestInterceptedAt
205
209
  * @returns {Promise<Response>}
206
210
  */
207
- async function getResponse(event, client, requestId) {
211
+ async function getResponse(event, client, requestId, requestInterceptedAt) {
208
212
  // Clone the request because it might've been already used
209
213
  // (i.e. its body has been read and sent to the client).
210
214
  const requestClone = event.request.clone()
@@ -255,6 +259,7 @@ async function getResponse(event, client, requestId) {
255
259
  type: 'REQUEST',
256
260
  payload: {
257
261
  id: requestId,
262
+ interceptedAt: requestInterceptedAt,
258
263
  ...serializedRequest,
259
264
  },
260
265
  },
package/dist/root.d.ts CHANGED
@@ -9,4 +9,4 @@ export * from './contexts/DismissibleContext';
9
9
  export * from './contexts/DismissibleProvider';
10
10
  export * from './types/dismissible.types';
11
11
  export * from './utils/auth.utils';
12
- export declare const VERSION = "0.3.0";
12
+ export declare const VERSION = "0.3.1";
@@ -9,6 +9,8 @@ export type JwtToken = string | (() => string) | (() => Promise<string>);
9
9
  * Configuration options for the DismissibleProvider
10
10
  */
11
11
  export interface DismissibleProviderProps {
12
+ /** User ID for the current user - required for all API calls */
13
+ userId: string;
12
14
  /** JWT token for authentication - can be static string or function */
13
15
  jwt?: JwtToken;
14
16
  /** Base URL for API requests - overrides default configuration */
@@ -20,6 +22,8 @@ export interface DismissibleProviderProps {
20
22
  * Context value provided by DismissibleProvider
21
23
  */
22
24
  export interface DismissibleContextValue {
25
+ /** User ID for the current user - required for all API calls */
26
+ userId: string;
23
27
  /** JWT token for authentication */
24
28
  jwt?: JwtToken;
25
29
  /** Base URL for API requests */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dismissible/react-client",
3
- "version": "0.3.0",
3
+ "version": "0.3.2-canary.2.38782c4",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -16,12 +16,18 @@
16
16
  "require": "./dist/dismissible-client.umd.js"
17
17
  }
18
18
  },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
19
22
  "scripts": {
20
23
  "dev": "vite",
21
24
  "build": "vite build",
25
+ "commit": "cz",
26
+ "commitlint": "commitlint --from HEAD~1 --to HEAD --verbose",
22
27
  "lint": "eslint \"{.storybook,src,test}/**/*.{ts,tsx}\" --fix",
23
28
  "format": "prettier --write \"src/**/*.{ts,tsx}\"",
24
29
  "preview": "vite preview",
30
+ "release": "semantic-release",
25
31
  "test": "vitest run --config vitest.config.ts",
26
32
  "test:watch": "vitest --config vitest.config.ts",
27
33
  "storybook": "storybook dev -p 6006",
@@ -29,49 +35,63 @@
29
35
  "build-storybook": "storybook build",
30
36
  "script": "ts-node -r tsconfig-paths/register --project tsconfig.json",
31
37
  "generate:clean": "rm -rf ./src/generated/contract/*",
32
- "generate:api": "npm run generate:clean && npx openapi-typescript http://localhost:3200/docs-yaml -o ./src/generated/contract/index.d.ts"
38
+ "generate:api": "npm run generate:clean && npx openapi-typescript http://localhost:3001/docs-yaml -o ./src/generated/contract/index.d.ts"
33
39
  },
34
40
  "dependencies": {
35
- "openapi-fetch": "^0.14.0"
41
+ "openapi-fetch": "^0.15.0"
36
42
  },
37
43
  "peerDependencies": {
38
- "react": ">=18.0.0",
39
- "react-dom": ">=18.0.0"
44
+ "react": "^18.0.0 || ^19.0.0",
45
+ "react-dom": "^18.0.0 || ^19.0.0"
40
46
  },
41
47
  "devDependencies": {
42
- "@babel/core": "^7.28.0",
43
- "@babel/preset-env": "^7.28.0",
44
- "@babel/preset-typescript": "^7.27.1",
45
- "@storybook/addon-a11y": "^9.0.15",
46
- "@storybook/addon-docs": "^9.0.15",
47
- "@storybook/react-vite": "^9.0.15",
48
- "@testing-library/jest-dom": "^6.6.3",
48
+ "@babel/core": "^7.28.5",
49
+ "@babel/preset-env": "^7.28.5",
50
+ "@babel/preset-typescript": "^7.28.5",
51
+ "@commitlint/cli": "^19.8.1",
52
+ "@commitlint/config-conventional": "^19.8.1",
53
+ "@semantic-release/changelog": "^6.0.3",
54
+ "@semantic-release/git": "^10.0.1",
55
+ "@semantic-release/github": "^10.3.5",
56
+ "@semantic-release/npm": "^12.0.2",
57
+ "@storybook/addon-a11y": "^9.1.16",
58
+ "@storybook/addon-docs": "^9.1.16",
59
+ "@storybook/react-vite": "^9.1.16",
60
+ "@testing-library/jest-dom": "^6.9.1",
49
61
  "@testing-library/react": "^16.3.0",
50
- "@types/node": "^24.0.10",
51
- "@types/react": "^18.3.23",
52
- "@types/react-dom": "^18.3.7",
53
- "@typescript-eslint/eslint-plugin": "^8.36.0",
54
- "@typescript-eslint/parser": "^8.36.0",
55
- "@vitejs/plugin-react": "^4.0.3",
56
- "core-js": "^3.44.0",
57
- "eslint": "^8.45.0",
62
+ "@types/node": "^25.0.2",
63
+ "@types/react": "^19.2.7",
64
+ "@types/react-dom": "^19.2.3",
65
+ "@typescript-eslint/eslint-plugin": "^8.49.0",
66
+ "@typescript-eslint/parser": "^8.49.0",
67
+ "@vitejs/plugin-react": "^4.7.0",
68
+ "commitizen": "^4.3.1",
69
+ "core-js": "^3.47.0",
70
+ "cz-conventional-changelog": "^3.3.0",
71
+ "eslint": "^8.57.1",
58
72
  "eslint-plugin-react": "^7.37.5",
59
73
  "eslint-plugin-react-hooks": "^5.2.0",
60
- "eslint-plugin-storybook": "^9.0.15",
74
+ "eslint-plugin-storybook": "^9.1.16",
61
75
  "happy-dom": "^18.0.1",
62
- "msw": "^2.10.3",
63
- "msw-storybook-addon": "^2.0.5",
64
- "openapi-typescript": "^7.8.0",
65
- "prettier": "^3.0.0",
66
- "react": "^18.3.1",
67
- "react-dom": "^18.3.1",
68
- "storybook": "^9.0.15",
76
+ "msw": "^2.12.4",
77
+ "msw-storybook-addon": "^2.0.6",
78
+ "openapi-typescript": "^7.10.1",
79
+ "prettier": "^3.7.4",
80
+ "react": "^19.2.3",
81
+ "react-dom": "^19.2.3",
82
+ "semantic-release": "^24.2.7",
83
+ "storybook": "^9.1.16",
69
84
  "ts-node": "^10.9.2",
70
- "typescript": "^5.8.3",
71
- "vite": "^5.0.10",
85
+ "typescript": "^5.9.3",
86
+ "vite": "^5.4.21",
72
87
  "vite-plugin-dts": "^4.5.4",
73
88
  "vitest": "^3.2.4"
74
89
  },
90
+ "config": {
91
+ "commitizen": {
92
+ "path": "cz-conventional-changelog"
93
+ }
94
+ },
75
95
  "eslintConfig": {
76
96
  "extends": [
77
97
  "plugin:storybook/recommended",