@dismissible/react-client 0.3.2 → 1.0.0-canary.4.a9fb4a5

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(l,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):(l=typeof globalThis!="undefined"?globalThis:l||self,u(l.DismissibleClient={},l.React.jsxRuntime,l.React))})(this,function(l,u,a){"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=(l,u,a)=>u in l?Te(l,u,{enumerable:!0,configurable:!0,writable:!0,value:a}):l[u]=a,p=(l,u)=>{for(var a in u||(u={}))de.call(u,a)&&fe(l,a,u[a]);if(W)for(var a of W(u))he.call(u,a)&&fe(l,a,u[a]);return l},S=(l,u)=>Ue(l,qe(u));var Y=(l,u)=>{var a={};for(var C in l)de.call(l,C)&&u.indexOf(C)<0&&(a[C]=l[C]);if(l!=null&&W)for(var C of W(l))u.indexOf(C)<0&&he.call(l,C)&&(a[C]=l[C]);return a};var O=(l,u,a)=>new Promise((C,L)=>{var V=D=>{try{T(a.next(D))}catch(k){L(k)}},B=D=>{try{T(a.throw(D))}catch(k){L(k)}},T=D=>D.done?C(D.value):Promise.resolve(D.value).then(V,B);T((a=a.apply(l,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:I=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:I,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 I(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 D(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(D(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,D(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=a.createContext(null),ie=()=>a.useContext(G),ve="dismissible",oe=(e,r={})=>{var z;const{initialData:t,enableCache:n=!0,cachePrefix:i=ve,cacheExpiration:s}=r,o=ie(),d=a.useMemo(()=>{const m=we(),y=(o==null?void 0:o.baseUrl)||m.baseUrl;return B({baseUrl:y,headers:{}})},[o]),h=a.useMemo(()=>!!(o!=null&&o.jwt)?`${e}-auth`:e,[e,o==null?void 0:o.jwt]),g=a.useRef({enableCache:n,cachePrefix:i,cacheExpiration:s}),E=a.useRef(e),U=a.useRef(h),[f,c]=a.useState(!1),[A,I]=a.useState(null),[H,x]=a.useState(()=>{if(t)return t;if(n){const m=re(h,i,s);if(m)return m}}),$=a.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),I(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){I(y instanceof Error?y:new Error("Unknown error occurred"))}finally{c(!1)}}),[e,h,n,i,s,d,o]);a.useEffect(()=>{const m=E.current!==e,y=U.current!==h;m||y?(E.current=e,U.current=h,$()):t||$()},[e,h,t]),a.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=a.useCallback(()=>O(this,null,function*(){var m;I(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 I(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,I]=a.useState(!1);a.useEffect(()=>{I(!1)},[e]);const H=()=>O(this,null,function*(){I(!0);try{yield c(),t==null||t()}catch(x){I(!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=a.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.1";l.Dismissible=Se,l.DismissibleContext=G,l.DismissibleProvider=Ae,l.VERSION=Ie,l.getAuthHeaders=le,l.isValidJwtFormat=je,l.resolveJwt=ae,l.useDismissibleContext=ie,l.useDismissibleItem=oe,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
1
+ (function(c,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):(c=typeof globalThis!="undefined"?globalThis:c||self,d(c.DismissibleClient={},c.React.jsxRuntime,c.React))})(this,(function(c,d,o){"use strict";var je=Object.defineProperty,$e=Object.defineProperties;var Te=Object.getOwnPropertyDescriptors;var Q=Object.getOwnPropertySymbols;var me=Object.prototype.hasOwnProperty,ye=Object.prototype.propertyIsEnumerable;var he=(c,d,o)=>d in c?je(c,d,{enumerable:!0,configurable:!0,writable:!0,value:o}):c[d]=o,g=(c,d)=>{for(var o in d||(d={}))me.call(d,o)&&he(c,o,d[o]);if(Q)for(var o of Q(d))ye.call(d,o)&&he(c,o,d[o]);return c},x=(c,d)=>$e(c,Te(d));var te=(c,d)=>{var o={};for(var R in c)me.call(c,R)&&d.indexOf(R)<0&&(o[R]=c[R]);if(c!=null&&Q)for(var R of Q(c))d.indexOf(R)<0&&ye.call(c,R)&&(o[R]=c[R]);return o};var q=(c,d,o)=>new Promise((R,J)=>{var V=j=>{try{H(o.next(j))}catch(F){J(F)}},X=j=>{try{H(o.throw(j))}catch(F){J(F)}},H=j=>j.done?R(j.value):Promise.resolve(j.value).then(V,X);H((o=o.apply(c,d)).next())});const R=/\{[^{}]+\}/g,J=()=>{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 X(e){let I=g({},e),{baseUrl:r="",Request:t=globalThis.Request,fetch:n=globalThis.fetch,querySerializer:i,bodySerializer:s,headers:a,requestInitExt:h=void 0}=I,b=te(I,["baseUrl","Request","fetch","querySerializer","bodySerializer","headers","requestInitExt"]);h=J()?h:void 0,r=ne(r);const m=[];function C(u,l){return q(this,null,function*(){var de;const fe=l||{},{baseUrl:A,fetch:$=n,Request:L=t,headers:D,params:S={},parseAs:U="json",querySerializer:T,bodySerializer:W=s!=null?s:we,body:_,middleware:f=[]}=fe,p=te(fe,["baseUrl","fetch","Request","headers","params","parseAs","querySerializer","bodySerializer","body","middleware"]);let y=r;A&&(y=(de=ne(A))!=null?de:r);let k=typeof i=="function"?i:re(i);T&&(k=typeof T=="function"?T:re(g(g({},typeof i=="object"?i:{}),T)));const N=_===void 0?void 0:W(_,se(a,D,S.header)),Ae=se(N===void 0||N instanceof FormData?{}:{"Content-Type":"application/json"},a,D,S.header),P=[...m,...f],De=x(g(g({redirect:"follow"},b),p),{body:N,headers:Ae});let B,G,O=new L(pe(u,{baseUrl:y,params:S,querySerializer:k}),De),w;for(const E in p)E in O||(O[E]=p[E]);if(P.length){B=V(),G=Object.freeze({baseUrl:y,fetch:$,parseAs:U,querySerializer:k,bodySerializer:W});for(const E of P)if(E&&typeof E=="object"&&typeof E.onRequest=="function"){const v=yield E.onRequest({request:O,schemaPath:u,params:S,options:G,id:B});if(v)if(v instanceof L)O=v;else if(v instanceof Response){w=v;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!w){try{w=yield $(O,h)}catch(E){let v=E;if(P.length)for(let z=P.length-1;z>=0;z--){const K=P[z];if(K&&typeof K=="object"&&typeof K.onError=="function"){const M=yield K.onError({request:O,error:v,schemaPath:u,params:S,options:G,id:B});if(M){if(M instanceof Response){v=void 0,w=M;break}if(M instanceof Error){v=M;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(v)throw v}if(P.length)for(let E=P.length-1;E>=0;E--){const v=P[E];if(v&&typeof v=="object"&&typeof v.onResponse=="function"){const z=yield v.onResponse({request:O,response:w,schemaPath:u,params:S,options:G,id:B});if(z){if(!(z instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");w=z}}}}if(w.status===204||O.method==="HEAD"||w.headers.get("Content-Length")==="0")return w.ok?{data:void 0,response:w}:{error:void 0,response:w};if(w.ok)return U==="stream"?{data:w.body,response:w}:{data:yield w[U](),response:w};let ee=yield w.text();try{ee=JSON.parse(ee)}catch(E){}return{error:ee,response:w}})}return{request(u,l,A){return C(l,x(g({},A),{method:u.toUpperCase()}))},GET(u,l){return C(u,x(g({},l),{method:"GET"}))},PUT(u,l){return C(u,x(g({},l),{method:"PUT"}))},POST(u,l){return C(u,x(g({},l),{method:"POST"}))},DELETE(u,l){return C(u,x(g({},l),{method:"DELETE"}))},OPTIONS(u,l){return C(u,x(g({},l),{method:"OPTIONS"}))},HEAD(u,l){return C(u,x(g({},l),{method:"HEAD"}))},PATCH(u,l){return C(u,x(g({},l),{method:"PATCH"}))},TRACE(u,l){return C(u,x(g({},l),{method:"TRACE"}))},use(...u){for(const l of u)if(l){if(typeof l!="object"||!("onRequest"in l||"onResponse"in l||"onError"in l))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");m.push(l)}},eject(...u){for(const l of u){const A=m.indexOf(l);A!==-1&&m.splice(A,1)}}}}function H(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 j(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 h in r)n.push(h,t.allowReserved===!0?r[h]:encodeURIComponent(r[h]));const a=n.join(",");switch(t.style){case"form":return`${e}=${a}`;case"label":return`.${a}`;case"matrix":return`;${e}=${a}`;default:return a}}for(const a in r){const h=t.style==="deepObject"?`${e}[${a}]`:a;n.push(H(h,r[a],t))}const s=n.join(i);return t.style==="label"||t.style==="matrix"?`${i}${s}`:s}function F(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const s={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",a=(t.allowReserved===!0?r:r.map(h=>encodeURIComponent(h))).join(s);switch(t.style){case"simple":return a;case"label":return`.${a}`;case"matrix":return`;${e}=${a}`;default:return`${e}=${a}`}}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(H(e,s,t));return t.style==="label"||t.style==="matrix"?`${n}${i.join(n)}`:i.join(n)}function re(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(F(i,s,x(g({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(j(i,s,x(g({style:"deepObject",explode:!0},e==null?void 0:e.object),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}n.push(H(i,s,e))}}return n.join("&")}}function be(e,r){var n;let t=e;for(const i of(n=e.match(R))!=null?n:[]){let s=i.substring(1,i.length-1),a=!1,h="simple";if(s.endsWith("*")&&(a=!0,s=s.substring(0,s.length-1)),s.startsWith(".")?(h="label",s=s.substring(1)):s.startsWith(";")&&(h="matrix",s=s.substring(1)),!r||r[s]===void 0||r[s]===null)continue;const b=r[s];if(Array.isArray(b)){t=t.replace(i,F(s,b,{style:h,explode:a}));continue}if(typeof b=="object"){t=t.replace(i,j(s,b,{style:h,explode:a}));continue}if(h==="matrix"){t=t.replace(i,`;${H(s,b)}`);continue}t=t.replace(i,h==="label"?`.${encodeURIComponent(b)}`:encodeURIComponent(b))}return t}function we(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 pe(e,r){var i,s;let t=`${r.baseUrl}${e}`;(i=r.params)!=null&&i.path&&(t=be(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 se(...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 a of s)r.append(i,a);else s!==void 0&&r.set(i,s)}return r}function ne(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const ie=(e,r,t)=>{try{const n=`${r}_${e}`,i=localStorage.getItem(n);if(!i)return null;const{data:s,timestamp:a}=JSON.parse(i);return t&&Date.now()-a>t?(localStorage.removeItem(n),null):s}catch(n){return null}},Y=(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)}},oe=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},Z=o.createContext(null),ae=()=>{const e=o.useContext(Z);if(!e)throw new Error("useDismissibleContext must be used within a DismissibleProvider");return e},ge="dismissible",ce=(e,r={})=>{const{initialData:t,enableCache:n=!0,cachePrefix:i=ge,cacheExpiration:s}=r,a=ae(),{userId:h}=a,b=o.useMemo(()=>X({baseUrl:a.baseUrl,headers:{}}),[a.baseUrl]),m=o.useMemo(()=>`${h}-${e}`,[h,e]),C=o.useRef({enableCache:n,cachePrefix:i,cacheExpiration:s}),I=o.useRef(e),u=o.useRef(m),l=o.useRef(null),[A,$]=o.useState(!1),[L,D]=o.useState(),[S,U]=o.useState(()=>{if(t)return t;if(n){const f=ie(m,i,s);if(f)return f}}),T=o.useCallback(()=>q(null,null,function*(){var p;if(n){const y=ie(m,i,s);if(y!=null&&y.dismissedAt){U(y),$(!1);return}}(p=l.current)==null||p.abort();const f=new AbortController;l.current=f,$(!0),D(void 0);try{const y=yield a.getAuthHeaders(),{data:k,error:N}=yield b.GET("/v1/users/{userId}/items/{itemId}",{params:{path:{userId:h,itemId:e}},headers:y,signal:f.signal});if(N||!k)throw new Error("Failed to fetch dismissible item");U(k.data),n&&Y(m,k.data,i)}catch(y){if(y instanceof Error&&y.name==="AbortError")return;D(y instanceof Error?y:new Error("Unknown error occurred"))}finally{$(!1)}}),[e,h,m,n,i,s,b,a]);o.useEffect(()=>{const f=I.current!==e,p=u.current!==m;f||p?(I.current=e,u.current=m,T()):t||T()},[e,m,t,T]),o.useEffect(()=>()=>{var f;(f=l.current)==null||f.abort()},[]),o.useEffect(()=>{const f=C.current;(f.enableCache!==n||f.cachePrefix!==i||f.cacheExpiration!==s)&&(f.cachePrefix!==i&&oe(m,f.cachePrefix),!n&&f.enableCache&&oe(m,f.cachePrefix),C.current={enableCache:n,cachePrefix:i,cacheExpiration:s},T())},[n,i,s,m,T]);const W=o.useCallback(()=>q(null,null,function*(){D(void 0);try{const f=yield a.getAuthHeaders(),{data:p,error:y}=yield b.DELETE("/v1/users/{userId}/items/{itemId}",{params:{path:{userId:h,itemId:e}},headers:f});if(y||!p)throw new Error("Failed to dismiss item");U(p.data),n&&Y(m,p.data,i)}catch(f){throw D(f instanceof Error?f:new Error("Failed to dismiss item")),f}}),[e,h,m,n,i,b,a]),_=o.useCallback(()=>q(null,null,function*(){D(void 0);try{const f=yield a.getAuthHeaders(),{data:p,error:y}=yield b.POST("/v1/users/{userId}/items/{itemId}",{params:{path:{userId:h,itemId:e}},headers:f});if(y||!p)throw new Error("Failed to restore item");U(p.data),n&&Y(m,p.data,i)}catch(f){throw D(f instanceof Error?f:new Error("Failed to restore item")),f}}),[e,h,m,n,i,b,a]);return{dismissedAt:S==null?void 0:S.dismissedAt,dismiss:W,restore:_,isLoading:A,error:L,item:S}},ve=()=>d.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),Ee=()=>d.jsx("div",{className:"dismissible-error",role:"alert",children:"Unable to load content. Please try again later."}),Ce=({onDismiss:e,ariaLabel:r})=>d.jsx("button",{className:"dismissible-button",onClick:e,"aria-label":r,type:"button",children:"×"}),Re=({itemId:e,children:r,onDismiss:t,LoadingComponent:n=ve,ErrorComponent:i=Ee,DismissButtonComponent:s=Ce,enableCache:a,cachePrefix:h,cacheExpiration:b,ignoreErrors:m=!1})=>{const{dismissedAt:C,isLoading:I,error:u,dismiss:l}=ce(e,{enableCache:a,cachePrefix:h,cacheExpiration:b}),[A,$]=o.useState(!1),[L,D]=o.useState(e);e!==L&&(D(e),$(!1));const S=()=>q(null,null,function*(){$(!0);try{yield l(),t==null||t()}catch(U){$(!1)}});return I&&n?d.jsx(n,{itemId:e}):I&&!n?null:u&&i&&!m?d.jsx(i,{itemId:e,error:u}):C||A?null:d.jsxs("div",{className:"dismissible-container",children:[d.jsx("div",{className:"dismissible-content",children:r}),s?d.jsx(s,{onDismiss:S,ariaLabel:`Dismiss ${e}`}):null]})},le=e=>q(null,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=>q(null,null,function*(){const r=yield le(e);return r?{Authorization:`Bearer ${r}`}:{}}),Se=e=>{try{const r=new URL(e),t=r.hostname==="localhost"||r.hostname==="127.0.0.1"||r.hostname==="[::1]",n=r.protocol==="https:";return{isSecure:n||t,isLocalhost:t,isHttps:n}}catch(r){return{isSecure:!1,isLocalhost:!1,isHttps:!1}}},xe=({userId:e,jwt:r,baseUrl:t,children:n})=>{const{isSecure:i}=Se(t);i||console.warn(`[dismissible] Insecure baseUrl "${t}". Use https:// in production (or localhost for development). JWT tokens may be exposed over insecure connections.`);const s=o.useMemo(()=>({userId:e,jwt:r,baseUrl:t,getAuthHeaders:()=>q(null,null,function*(){return yield ue(r)})}),[e,r,t]);return d.jsx(Z.Provider,{value:s,children:n})};c.Dismissible=Re,c.DismissibleContext=Z,c.DismissibleProvider=xe,c.getAuthHeaders=ue,c.resolveJwt=le,c.useDismissibleContext=ae,c.useDismissibleItem=ce,Object.defineProperty(c,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 */
@@ -11,24 +11,25 @@ export interface UseDismissibleItemOptions {
11
11
  /** Cache expiration time in milliseconds (default: never expires) */
12
12
  cacheExpiration?: number;
13
13
  }
14
+ export interface UseDismissibleItemResponse {
15
+ /** The date when the item was dismissed, or undefined if not dismissed */
16
+ dismissedAt?: IDismissibleItem["dismissedAt"];
17
+ /** Function to dismiss the item */
18
+ dismiss: () => Promise<void>;
19
+ /** Function to restore the item */
20
+ restore: () => Promise<void>;
21
+ /** Loading state */
22
+ isLoading: boolean;
23
+ /** Error state */
24
+ error?: Error;
25
+ /** The dismissible item data */
26
+ item?: IDismissibleItem;
27
+ }
14
28
  /**
15
29
  * Hook for managing dismissible items
16
30
  * @param id - The ID of the dismissible item
17
31
  * @param options - Configuration options for the hook
18
- * @returns Object with dismissedOn, dismiss and restore functions
32
+ * @returns Object with dismissedAt, dismiss and restore functions
19
33
  */
20
- export declare const useDismissibleItem: (id: string, options?: UseDismissibleItemOptions) => {
21
- dismissedOn: string | null;
22
- dismiss: () => Promise<void>;
23
- isLoading: boolean;
24
- error: Error | null;
25
- item: {
26
- key: string;
27
- id: string;
28
- accountId: string;
29
- createdAt: string;
30
- dismissedAt?: string | null;
31
- expiresAt?: string | null;
32
- } | undefined;
33
- };
34
+ export declare const useDismissibleItem: (itemId: string, options?: UseDismissibleItemOptions) => UseDismissibleItemResponse;
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
  },
@@ -1 +1 @@
1
- .dismissible-container{position:relative;display:inline-block;width:100%}.dismissible-content{width:100%}.dismissible-button{position:absolute;top:8px;right:8px;background:#0000001a;border:none;border-radius:50%;width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:16px;line-height:1;color:#666;transition:all .2s ease}.dismissible-button:hover{background:#0003;color:#333}.dismissible-button:focus{outline:2px solid #007bff;outline-offset:2px}.dismissible-button:active{transform:scale(.95)}.dismissible-loading{padding:16px;text-align:center;color:#666;font-style:italic}.dismissible-error{padding:16px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c33;font-size:14px}@media (max-width: 768px){.dismissible-button{width:32px;height:32px;font-size:18px}}
1
+ .dismissible-container{position:relative;display:inline-block;width:100%}.dismissible-content{width:100%}.dismissible-button{position:absolute;top:8px;right:8px;background:#0000001a;border:none;border-radius:50%;width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:16px;line-height:1;color:#666;transition:all .2s ease}.dismissible-button:hover{background:#0003;color:#333}.dismissible-button:focus{outline:2px solid #007bff;outline-offset:2px}.dismissible-button:active{transform:scale(.95)}.dismissible-loading{padding:16px;text-align:center;color:#666;font-style:italic}.dismissible-error{padding:16px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c33;font-size:14px}@media(max-width:768px){.dismissible-button{width:32px;height:32px;font-size:18px}}
package/dist/root.d.ts CHANGED
@@ -1,12 +1,6 @@
1
- /**
2
- * Dismissible React Component Library
3
- *
4
- * This library provides React components for implementing dismissible UI elements
5
- */
6
1
  export * from './components/Dismissible';
7
2
  export * from './hooks/useDismissibleItem';
8
3
  export * from './contexts/DismissibleContext';
9
4
  export * from './contexts/DismissibleProvider';
10
5
  export * from './types/dismissible.types';
11
6
  export * from './utils/auth.utils';
12
- export declare const VERSION = "0.3.1";
@@ -9,10 +9,12 @@ 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
- /** Base URL for API requests - overrides default configuration */
15
- baseUrl?: string;
16
+ /** Base URL for API requests */
17
+ baseUrl: string;
16
18
  /** Child components */
17
19
  children: React.ReactNode;
18
20
  }
@@ -20,10 +22,12 @@ 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 */
26
- baseUrl?: string;
30
+ baseUrl: string;
27
31
  /** Helper function to get authentication headers */
28
32
  getAuthHeaders: () => Promise<AuthHeaders>;
29
33
  }
@@ -11,9 +11,3 @@ export declare const resolveJwt: (jwt: JwtToken | undefined) => Promise<string |
11
11
  * @returns Promise that resolves to headers object with Authorization header if JWT is available
12
12
  */
13
13
  export declare const getAuthHeaders: (jwt?: JwtToken) => Promise<AuthHeaders>;
14
- /**
15
- * Validates that a JWT token is properly formatted
16
- * @param token - The JWT token to validate
17
- * @returns True if token appears to be a valid JWT format
18
- */
19
- export declare const isValidJwtFormat: (token: string) => boolean;
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@dismissible/react-client",
3
- "version": "0.3.2",
3
+ "version": "1.0.0-canary.4.a9fb4a5",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
7
- "README.md"
7
+ "LICENSE",
8
+ "README.md",
9
+ "CHANGELOG.md"
8
10
  ],
9
11
  "main": "./dist/dismissible-client.umd.js",
10
12
  "module": "./dist/dismissible-client.es.js",
@@ -16,67 +18,85 @@
16
18
  "require": "./dist/dismissible-client.umd.js"
17
19
  }
18
20
  },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
19
24
  "scripts": {
20
- "dev": "vite",
21
25
  "build": "vite build",
22
- "lint": "eslint \"{.storybook,src,test}/**/*.{ts,tsx}\" --fix",
23
- "format": "prettier --write \"src/**/*.{ts,tsx}\"",
26
+ "dev": "vite",
27
+ "commit": "cz",
28
+ "commitlint": "commitlint --from HEAD~1 --to HEAD --verbose",
29
+ "format": "npm run prettier:fix && npm run lint:fix",
30
+ "generate:clean": "rm -rf ./src/generated/contract/*",
31
+ "generate:api": "npm run generate:clean && npx openapi-typescript http://localhost:3001/docs-yaml -o ./src/generated/contract/index.d.ts",
32
+ "lint": "eslint \"{.storybook,src,test}/**/*.{ts,tsx}\"",
33
+ "lint:fix": "eslint \"{.storybook,src,test}/**/*.{ts,tsx}\" --fix",
34
+ "prettier": "prettier --check \"src/**/*.{ts,tsx}\" \".github/**/*.{yaml,yml}\"",
35
+ "prettier:fix": "prettier --write \"src/**/*.{ts,tsx}\" \".github/**/*.{yaml,yml}\"",
24
36
  "preview": "vite preview",
25
- "test": "vitest run --config vitest.config.ts",
26
- "test:watch": "vitest --config vitest.config.ts",
37
+ "release": "semantic-release",
38
+ "script": "ts-node -r tsconfig-paths/register --project tsconfig.json",
27
39
  "storybook": "storybook dev -p 6006",
28
40
  "storybook:staging": "MODE=staging storybook dev -p 6006",
29
- "build-storybook": "storybook build",
30
- "script": "ts-node -r tsconfig-paths/register --project tsconfig.json",
31
- "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"
41
+ "storybook:build": "storybook build",
42
+ "test": "vitest run --config vitest.config.ts",
43
+ "test:watch": "vitest --config vitest.config.ts",
44
+ "validate": "npm run prettier && npm run lint && npm run test"
33
45
  },
34
46
  "dependencies": {
35
- "openapi-fetch": "^0.14.0"
47
+ "openapi-fetch": "^0.15.0"
36
48
  },
37
49
  "peerDependencies": {
38
- "react": ">=18.0.0",
39
- "react-dom": ">=18.0.0"
50
+ "react": "^18.0.0 || ^19.0.0",
51
+ "react-dom": "^18.0.0 || ^19.0.0"
40
52
  },
41
53
  "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",
49
- "@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",
54
+ "@babel/core": "^7.28.5",
55
+ "@babel/preset-env": "^7.28.5",
56
+ "@babel/preset-typescript": "^7.28.5",
57
+ "@commitlint/cli": "^20.2.0",
58
+ "@commitlint/config-conventional": "^20.2.0",
59
+ "@semantic-release/changelog": "^6.0.3",
60
+ "@semantic-release/git": "^10.0.1",
61
+ "@semantic-release/github": "^12.0.2",
62
+ "@semantic-release/npm": "^13.1.3",
63
+ "@storybook/addon-a11y": "^10.1.10",
64
+ "@storybook/addon-docs": "^10.1.10",
65
+ "@storybook/react-vite": "^10.1.10",
66
+ "@testing-library/jest-dom": "^6.9.1",
67
+ "@testing-library/react": "^16.3.1",
68
+ "@types/node": "^25.0.3",
69
+ "@types/react": "^19.2.7",
70
+ "@types/react-dom": "^19.2.3",
71
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
72
+ "@typescript-eslint/parser": "^8.50.0",
73
+ "@vitejs/plugin-react": "^5.1.2",
74
+ "commitizen": "^4.3.1",
75
+ "core-js": "^3.47.0",
76
+ "cz-conventional-changelog": "^3.3.0",
77
+ "eslint": "^9.39.2",
58
78
  "eslint-plugin-react": "^7.37.5",
59
- "eslint-plugin-react-hooks": "^5.2.0",
60
- "eslint-plugin-storybook": "^9.0.15",
61
- "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",
79
+ "eslint-plugin-react-hooks": "^7.0.1",
80
+ "eslint-plugin-storybook": "^10.1.10",
81
+ "happy-dom": "^20.0.11",
82
+ "msw": "^2.12.4",
83
+ "msw-storybook-addon": "^2.0.6",
84
+ "openapi-typescript": "^7.10.1",
85
+ "prettier": "^3.7.4",
86
+ "react": "^19.2.3",
87
+ "react-dom": "^19.2.3",
88
+ "semantic-release": "^25.0.2",
89
+ "storybook": "^10.1.10",
69
90
  "ts-node": "^10.9.2",
70
- "typescript": "^5.8.3",
71
- "vite": "^5.0.10",
91
+ "typescript": "^5.9.3",
92
+ "vite": "^7.3.0",
72
93
  "vite-plugin-dts": "^4.5.4",
73
- "vitest": "^3.2.4"
94
+ "vitest": "^4.0.16"
74
95
  },
75
- "eslintConfig": {
76
- "extends": [
77
- "plugin:storybook/recommended",
78
- "plugin:storybook/recommended"
79
- ]
96
+ "config": {
97
+ "commitizen": {
98
+ "path": "cz-conventional-changelog"
99
+ }
80
100
  },
81
101
  "msw": {
82
102
  "workerDirectory": [