react-shared-states 1.0.7 → 1.0.8

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/dist/main.min.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /*!
2
- * react-shared-states v1.0.7
2
+ * react-shared-states v1.0.8
3
3
  * (c) Hichem Taboukouyout
4
4
  * Released under the MIT License.
5
5
  * Github: github.com/HichemTab-tech/react-shared-states
6
6
  */
7
7
 
8
- (function(b,d){typeof exports=="object"&&typeof module<"u"?d(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],d):(b=typeof globalThis<"u"?globalThis:b||self,d(b.ReactSharedStates={},b.React))})(this,function(b,d){"use strict";var C={exports:{}},j={};/**
8
+ (function(h,g){typeof exports=="object"&&typeof module<"u"?g(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],g):(h=typeof globalThis<"u"?globalThis:h||self,g(h.ReactSharedStates={},h.React))})(this,function(h,g){"use strict";var M={exports:{}},V={};/**
9
9
  * @license React
10
10
  * react-jsx-runtime.production.js
11
11
  *
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * This source code is licensed under the MIT license found in the
15
15
  * LICENSE file in the root directory of this source tree.
16
- */var G;function y(){if(G)return j;G=1;var s=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function r(t,o,f){var x=null;if(f!==void 0&&(x=""+f),o.key!==void 0&&(x=""+o.key),"key"in o){f={};for(var _ in o)_!=="key"&&(f[_]=o[_])}else f=o;return o=f.ref,{$$typeof:s,type:t,key:x,ref:o!==void 0?o:null,props:f}}return j.Fragment=e,j.jsx=r,j.jsxs=r,j}var L={};/**
16
+ */var J;function se(){if(J)return V;J=1;var a=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function r(t,s,f){var o=null;if(f!==void 0&&(o=""+f),s.key!==void 0&&(o=""+s.key),"key"in s){f={};for(var A in s)A!=="key"&&(f[A]=s[A])}else f=s;return s=f.ref,{$$typeof:a,type:t,key:o,ref:s!==void 0?s:null,props:f}}return V.Fragment=e,V.jsx=r,V.jsxs=r,V}var C={};/**
17
17
  * @license React
18
18
  * react-jsx-runtime.development.js
19
19
  *
@@ -21,9 +21,9 @@
21
21
  *
22
22
  * This source code is licensed under the MIT license found in the
23
23
  * LICENSE file in the root directory of this source tree.
24
- */var J;function k(){return J||(J=1,process.env.NODE_ENV!=="production"&&function(){function s(n){if(n==null)return null;if(typeof n=="function")return n.$$typeof===Pe?null:n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case F:return"Fragment";case ve:return"Profiler";case Ee:return"StrictMode";case Re:return"Suspense";case Te:return"SuspenseList";case we:return"Activity"}if(typeof n=="object")switch(typeof n.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),n.$$typeof){case pe:return"Portal";case xe:return(n.displayName||"Context")+".Provider";case me:return(n._context.displayName||"Context")+".Consumer";case _e:var a=n.render;return n=n.displayName,n||(n=a.displayName||a.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case Ae:return a=n.displayName||null,a!==null?a:s(n.type)||"Memo";case B:a=n._payload,n=n._init;try{return s(n(a))}catch{}}return null}function e(n){return""+n}function r(n){try{e(n);var a=!1}catch{a=!0}if(a){a=console;var u=a.error,S=typeof Symbol=="function"&&Symbol.toStringTag&&n[Symbol.toStringTag]||n.constructor.name||"Object";return u.call(a,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",S),e(n)}}function t(n){if(n===F)return"<>";if(typeof n=="object"&&n!==null&&n.$$typeof===B)return"<...>";try{var a=s(n);return a?"<"+a+">":"<...>"}catch{return"<...>"}}function o(){var n=Y.A;return n===null?null:n.getOwner()}function f(){return Error("react-stack-top-frame")}function x(n){if(H.call(n,"key")){var a=Object.getOwnPropertyDescriptor(n,"key").get;if(a&&a.isReactWarning)return!1}return n.key!==void 0}function _(n,a){function u(){Z||(Z=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",a))}u.isReactWarning=!0,Object.defineProperty(n,"key",{get:u,configurable:!0})}function h(){var n=s(this.type);return Q[n]||(Q[n]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),n=this.props.ref,n!==void 0?n:null}function w(n,a,u,S,P,A,I,W){return u=A.ref,n={$$typeof:R,type:n,key:a,props:A,_owner:P},(u!==void 0?u:null)!==null?Object.defineProperty(n,"ref",{enumerable:!1,get:h}):Object.defineProperty(n,"ref",{enumerable:!1,value:null}),n._store={},Object.defineProperty(n._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(n,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(n,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:I}),Object.defineProperty(n,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:W}),Object.freeze&&(Object.freeze(n.props),Object.freeze(n)),n}function g(n,a,u,S,P,A,I,W){var p=a.children;if(p!==void 0)if(S)if(Oe(p)){for(S=0;S<p.length;S++)l(p[S]);Object.freeze&&Object.freeze(p)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else l(p);if(H.call(a,"key")){p=s(n);var O=Object.keys(a).filter(function(je){return je!=="key"});S=0<O.length?"{key: someKey, "+O.join(": ..., ")+": ...}":"{key: someKey}",$[p+S]||(O=0<O.length?"{"+O.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
24
+ */var z;function ae(){return z||(z=1,process.env.NODE_ENV!=="production"&&function(){function a(n){if(n==null)return null;if(typeof n=="function")return n.$$typeof===ye?null:n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case c:return"Fragment";case Re:return"Profiler";case _:return"StrictMode";case Pe:return"Suspense";case Oe:return"SuspenseList";case Le:return"Activity"}if(typeof n=="object")switch(typeof n.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),n.$$typeof){case d:return"Portal";case Ae:return(n.displayName||"Context")+".Provider";case Te:return(n._context.displayName||"Context")+".Consumer";case we:var i=n.render;return n=n.displayName,n||(n=i.displayName||i.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case je:return i=n.displayName||null,i!==null?i:a(n.type)||"Memo";case K:i=n._payload,n=n._init;try{return a(n(i))}catch{}}return null}function e(n){return""+n}function r(n){try{e(n);var i=!1}catch{i=!0}if(i){i=console;var b=i.error,p=typeof Symbol=="function"&&Symbol.toStringTag&&n[Symbol.toStringTag]||n.constructor.name||"Object";return b.call(i,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",p),e(n)}}function t(n){if(n===c)return"<>";if(typeof n=="object"&&n!==null&&n.$$typeof===K)return"<...>";try{var i=a(n);return i?"<"+i+">":"<...>"}catch{return"<...>"}}function s(){var n=D.A;return n===null?null:n.getOwner()}function f(){return Error("react-stack-top-frame")}function o(n){if(q.call(n,"key")){var i=Object.getOwnPropertyDescriptor(n,"key").get;if(i&&i.isReactWarning)return!1}return n.key!==void 0}function A(n,i){function b(){$||($=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",i))}b.isReactWarning=!0,Object.defineProperty(n,"key",{get:b,configurable:!0})}function L(){var n=a(this.type);return ee[n]||(ee[n]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),n=this.props.ref,n!==void 0?n:null}function O(n,i,b,p,j,w,W,U){return b=w.ref,n={$$typeof:S,type:n,key:i,props:w,_owner:j},(b!==void 0?b:null)!==null?Object.defineProperty(n,"ref",{enumerable:!1,get:L}):Object.defineProperty(n,"ref",{enumerable:!1,value:null}),n._store={},Object.defineProperty(n._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(n,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(n,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:W}),Object.defineProperty(n,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:U}),Object.freeze&&(Object.freeze(n.props),Object.freeze(n)),n}function P(n,i,b,p,j,w,W,U){var v=i.children;if(v!==void 0)if(p)if(Ve(v)){for(p=0;p<v.length;p++)u(v[p]);Object.freeze&&Object.freeze(v)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else u(v);if(q.call(i,"key")){v=a(n);var y=Object.keys(i).filter(function(Ce){return Ce!=="key"});p=0<y.length?"{key: someKey, "+y.join(": ..., ")+": ...}":"{key: someKey}",ne[v+p]||(y=0<y.length?"{"+y.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
25
25
  let props = %s;
26
26
  <%s {...props} />
27
27
  React keys must be passed directly to JSX without using spread:
28
28
  let props = %s;
29
- <%s key={someKey} {...props} />`,S,p,O,p),$[p+S]=!0)}if(p=null,u!==void 0&&(r(u),p=""+u),x(a)&&(r(a.key),p=""+a.key),"key"in a){u={};for(var U in a)U!=="key"&&(u[U]=a[U])}else u=a;return p&&_(u,typeof n=="function"?n.displayName||n.name||"Unknown":n),w(n,p,A,P,o(),u,I,W)}function l(n){typeof n=="object"&&n!==null&&n.$$typeof===R&&n._store&&(n._store.validated=1)}var c=d,R=Symbol.for("react.transitional.element"),pe=Symbol.for("react.portal"),F=Symbol.for("react.fragment"),Ee=Symbol.for("react.strict_mode"),ve=Symbol.for("react.profiler"),me=Symbol.for("react.consumer"),xe=Symbol.for("react.context"),_e=Symbol.for("react.forward_ref"),Re=Symbol.for("react.suspense"),Te=Symbol.for("react.suspense_list"),Ae=Symbol.for("react.memo"),B=Symbol.for("react.lazy"),we=Symbol.for("react.activity"),Pe=Symbol.for("react.client.reference"),Y=c.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,H=Object.prototype.hasOwnProperty,Oe=Array.isArray,D=console.createTask?console.createTask:function(){return null};c={react_stack_bottom_frame:function(n){return n()}};var Z,Q={},K=c.react_stack_bottom_frame.bind(c,f)(),q=D(t(f)),$={};L.Fragment=F,L.jsx=function(n,a,u,S,P){var A=1e4>Y.recentlyCreatedOwnerStacks++;return g(n,a,u,!1,S,P,A?Error("react-stack-top-frame"):K,A?D(t(n)):q)},L.jsxs=function(n,a,u,S,P){var A=1e4>Y.recentlyCreatedOwnerStacks++;return g(n,a,u,!0,S,P,A?Error("react-stack-top-frame"):K,A?D(t(n)):q)}}()),L}var z;function ee(){return z||(z=1,process.env.NODE_ENV==="production"?C.exports=y():C.exports=k()),C.exports}var te=ee();const X=d.createContext(void 0),re=({children:s,scopeName:e})=>{if(e&&e.includes("//"))throw new Error("scopeName cannot contain '//'");return e||(e=d.useMemo(()=>Math.random().toString(36).substring(2,15),[])),te.jsx(X.Provider,{value:{scopeName:e},children:s})},ne=()=>d.useContext(X);b.isDevMode=!1;const se=s=>{b.isDevMode=s},M=(...s)=>{b.isDevMode&&console.log("%c[react-shared-states]","color: #007acc; font-weight: bold",...s)},T=s=>{if(!s)throw new Error("Value is empty");return s};class i{data=new Map;defaultValue(){return{}}addListener(e,r,t){this.data.has(i.prefix(e,r))||this.data.set(i.prefix(e,r),{...this.defaultValue,listeners:[]}),this.data.get(i.prefix(e,r)).listeners.push(t)}removeListener(e,r,t){this.data.has(i.prefix(e,r))&&(this.data.get(i.prefix(e,r)).listeners=this.data.get(i.prefix(e,r)).listeners.filter(o=>o!==t))}callListeners(e,r){this.data.has(i.prefix(e,r))&&this.data.get(i.prefix(e,r)).listeners.forEach(t=>t())}init(e,r,t){this.data.has(i.prefix(e,r))||this.data.set(i.prefix(e,r),{...t,listeners:[]})}clearAll(e=!1){e||this.data.forEach(r=>{r.listeners.forEach(t=>t())}),this.data.clear()}clear(e,r,t=!1){t||this.callListeners(e,r),this.data.delete(i.prefix(e,r))}get(e,r){let t=this.has(e,r);if(t)return this.data.get(t)}setValue(e,r,t){this.data.has(i.prefix(e,r))&&this.data.set(i.prefix(e,r),{...this.data.get(i.prefix(e,r)),...t})}has(e,r){return this.data.has(i.prefix(e,r))?i.prefix(e,r):this.data.has(i.prefix(e,"_global"))?i.prefix(e,"_global"):void 0}static prefix(e,r){if(e.includes("//"))throw new Error("key cannot contain '//'");return`${r}//${e}`}static extractPrefix(e){return e.split("//")}useEffect(e,r,t=null){d.useEffect(()=>()=>{t?.(),M(`[${i.prefix(e,r)}]`,"unmount effect"),this.data.get(i.prefix(e,r)).listeners?.length===0&&this.clear(e,r)},[])}}class N{constructor(e){this.sharedData=e}get(e,r){e=T(e);const t=r||"_global";return this.sharedData.get(e,t)}set(e,r,t){e=T(e);const o=t||"_global";this.sharedData.setValue(e,o,r)}clearAll(){this.sharedData.clearAll()}clearScope(e){const r=e||"_global";this.sharedData.data.forEach((t,o)=>{const[f]=i.extractPrefix(o);if(f===r){this.sharedData.clear(o,f);return}})}clear(e,r){const t=r||"_global";this.sharedData.clear(e,t)}has(e,r="_global"){const t=r||"_global";return!!this.sharedData.has(e,t)}getAll(){const e={};return this.sharedData.data.forEach((r,t)=>{const[o,f]=i.extractPrefix(t);e[o]=e[o]||{},e[o][f]=r}),e}}const V=s=>{const e=ne();return{prefix:s??e?.scopeName??"_global"}};class ae extends i{defaultValue(){return{value:void 0}}init(e,r,t){super.init(e,r,{value:t})}setValue(e,r,t){super.setValue(e,r,{value:t})}removeListener(e,r,t){super.removeListener(e,r,t)}}class oe extends N{get(e,r="_global"){e=T(e);const t=r||"_global";return v.get(e,t)?.value}set(e,r,t="_global"){e=T(e);const o=t||"_global";v.setValue(e,o,{value:r})}}const v=new ae,ie=new oe(v),ce=(s,e,r)=>{s=T(s);const{prefix:t}=V(r);v.init(s,t,e);const o=d.useMemo(()=>h=>(v.init(s,t,e),v.addListener(s,t,h),()=>{v.removeListener(s,t,h)}),[]),f=d.useMemo(()=>()=>v.get(s,t)?.value,[]),x=d.useSyncExternalStore(o,f),_=h=>{const w=typeof h=="function"?h(v.get(s,t)?.value):h;w!==x&&(v.setValue(s,t,w),v.callListeners(s,t))};return v.useEffect(s,t),[x,_]};class le extends i{defaultValue(){return{fnState:{results:void 0,isLoading:!1,error:void 0}}}init(e,r){super.init(e,r,this.defaultValue())}setValue(e,r,t){super.setValue(e,r,t)}}class ue extends N{get(e,r="_global"){e=T(e);const t=r||"_global";return m.get(e,t)?.fnState}set(e,r,t="_global"){e=T(e);const o=t||"_global";m.setValue(e,o,r)}}const m=new le,fe=new ue(m),de=(s,e,r)=>{s=T(s);const{prefix:t}=V(r);m.init(s,t);const o=d.useMemo(()=>h=>(m.init(s,t),m.addListener(s,t,h),()=>{m.removeListener(s,t,h)}),[]),f=d.useMemo(()=>()=>m.get(s,t).fnState,[]),x=d.useSyncExternalStore(o,f),_=async(h,...w)=>{const g=m.get(s,t);if(!h&&(g.fnState.isLoading||g.fnState.results!==void 0))return g.fnState;g.fnState={...g.fnState,isLoading:!0,error:void 0},g.listeners.forEach(l=>l());try{const l=await e(...w);g.fnState={results:l,isLoading:!1,error:void 0}}catch(l){g.fnState={...g.fnState,isLoading:!1,error:l}}g.listeners.forEach(l=>l())};return m.useEffect(s,t),{state:x,trigger:(...h)=>{_(!1,...h)},forceTrigger:(...h)=>{_(!0,...h)},clear:()=>{m.clear(s,t),m.init(s,t)}}};class he extends i{defaultValue(){return{fnState:{data:void 0,isLoading:!1,error:void 0,subscribed:!1}}}init(e,r){super.init(e,r,this.defaultValue())}setValue(e,r,t){super.setValue(e,r,t)}useEffect(e,r){d.useEffect(()=>()=>{M(`[${i.prefix(e,r)}]`,"unmount effect2"),this.get(e,r)?.listeners.length===0&&this.unsubscribe(e,r)},[]),super.useEffect(e,r)}async unsubscribe(e,r){const t=this.get(e,r);t&&(t.unsubscribe&&(t.unsubscribe(),t.unsubscribe=void 0),t.fnState.subscribed=!1)}}class be extends N{get(e,r="_global"){e=T(e);const t=r||"_global";return E.get(e,t)?.fnState}set(e,r,t="_global"){e=T(e);const o=t||"_global";E.setValue(e,o,r)}}const E=new he,ge=new be(E),Se=(s,e,r)=>{s=T(s);const{prefix:t}=V(r);E.init(s,t);const o=d.useMemo(()=>l=>(E.init(s,t),E.addListener(s,t,l),()=>{E.removeListener(s,t,l)}),[]),f=d.useMemo(()=>()=>E.get(s,t).fnState,[]),x=d.useSyncExternalStore(o,f),_=l=>{const c=E.get(s,t);c.fnState={...c.fnState,data:l},c.listeners.forEach(R=>R())},h=l=>{const c=E.get(s,t);c.fnState={...c.fnState,isLoading:!1,data:void 0,error:l},c.listeners.forEach(R=>R())},w=()=>{const l=E.get(s,t);l.fnState={...l.fnState,isLoading:!1},l.listeners.forEach(c=>c())},g=async l=>{const c=E.get(s,t);if(l&&(await E.unsubscribe(s,t),c.fnState={...c.fnState,isLoading:!1,data:void 0,error:void 0,subscribed:!1}),c.fnState.subscribed)return c.fnState;M("triggered !!"),c.fnState={...c.fnState,isLoading:!0,error:void 0},c.listeners.forEach(R=>R());try{c.unsubscribe=await e(_,h,w),c.fnState.subscribed=!0}catch(R){c.fnState={...c.fnState,isLoading:!1,error:R}}c.listeners.forEach(R=>R())};return E.useEffect(s,t),{state:x,trigger:()=>{g(!1)},forceTrigger:()=>{g(!0)},unsubscribe:()=>{E.unsubscribe(s,t)}}};b.SharedStatesProvider=re,b.setDevMode=se,b.sharedFunctionsApi=fe,b.sharedStatesApi=ie,b.sharedSubscriptionsApi=ge,b.useSharedFunction=de,b.useSharedState=ce,b.useSharedSubscription=Se,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})});
29
+ <%s key={someKey} {...props} />`,p,v,y,v),ne[v+p]=!0)}if(v=null,b!==void 0&&(r(b),v=""+b),o(i)&&(r(i.key),v=""+i.key),"key"in i){b={};for(var G in i)G!=="key"&&(b[G]=i[G])}else b=i;return v&&A(b,typeof n=="function"?n.displayName||n.name||"Unknown":n),O(n,v,w,j,s(),b,W,U)}function u(n){typeof n=="object"&&n!==null&&n.$$typeof===S&&n._store&&(n._store.validated=1)}var m=g,S=Symbol.for("react.transitional.element"),d=Symbol.for("react.portal"),c=Symbol.for("react.fragment"),_=Symbol.for("react.strict_mode"),Re=Symbol.for("react.profiler"),Te=Symbol.for("react.consumer"),Ae=Symbol.for("react.context"),we=Symbol.for("react.forward_ref"),Pe=Symbol.for("react.suspense"),Oe=Symbol.for("react.suspense_list"),je=Symbol.for("react.memo"),K=Symbol.for("react.lazy"),Le=Symbol.for("react.activity"),ye=Symbol.for("react.client.reference"),D=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,q=Object.prototype.hasOwnProperty,Ve=Array.isArray,I=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(n){return n()}};var $,ee={},te=m.react_stack_bottom_frame.bind(m,f)(),re=I(t(f)),ne={};C.Fragment=c,C.jsx=function(n,i,b,p,j){var w=1e4>D.recentlyCreatedOwnerStacks++;return P(n,i,b,!1,p,j,w?Error("react-stack-top-frame"):te,w?I(t(n)):re)},C.jsxs=function(n,i,b,p,j){var w=1e4>D.recentlyCreatedOwnerStacks++;return P(n,i,b,!0,p,j,w?Error("react-stack-top-frame"):te,w?I(t(n)):re)}}()),C}var X;function oe(){return X||(X=1,process.env.NODE_ENV==="production"?M.exports=se():M.exports=ae()),M.exports}var ie=oe();h.isDevMode=!1;const ce=a=>{h.isDevMode=a},N=(...a)=>{h.isDevMode&&console.log("%c[react-shared-states]","color: #007acc; font-weight: bold",...a)},T=a=>{if(!a)throw new Error("Value is empty");return a},F=()=>Math.random().toString(36).substring(2,15),B=g.createContext(void 0),le=({children:a,scopeName:e})=>{if(e&&e.includes("//"))throw new Error("scopeName cannot contain '//'");return e||(e=g.useMemo(()=>F(),[])),ie.jsx(B.Provider,{value:{scopeName:e},children:a})},ue=()=>g.useContext(B);class l{data=new Map;defaultValue(){return{}}addListener(e,r,t){this.data.has(l.prefix(e,r))||this.data.set(l.prefix(e,r),{...this.defaultValue,listeners:[]}),this.data.get(l.prefix(e,r)).listeners.push(t)}removeListener(e,r,t){this.data.has(l.prefix(e,r))&&(this.data.get(l.prefix(e,r)).listeners=this.data.get(l.prefix(e,r)).listeners.filter(s=>s!==t))}callListeners(e,r){this.data.has(l.prefix(e,r))&&this.data.get(l.prefix(e,r)).listeners.forEach(t=>t())}init(e,r,t){this.data.has(l.prefix(e,r))||this.data.set(l.prefix(e,r),{...t,listeners:[]})}clearAll(e=!1){e||this.data.forEach(r=>{r.listeners.forEach(t=>t())}),this.data.clear()}clear(e,r,t=!1){t||this.callListeners(e,r),this.data.delete(l.prefix(e,r))}get(e,r){let t=this.has(e,r);if(t)return this.data.get(t)}setValue(e,r,t){this.data.has(l.prefix(e,r))&&this.data.set(l.prefix(e,r),{...this.data.get(l.prefix(e,r)),...t})}has(e,r){return this.data.has(l.prefix(e,r))?l.prefix(e,r):this.data.has(l.prefix(e,"_global"))?l.prefix(e,"_global"):void 0}static prefix(e,r){if(e.includes("//"))throw new Error("key cannot contain '//'");return`${r}//${e}`}static extractPrefix(e){return e.split("//")}useEffect(e,r,t=null){g.useEffect(()=>()=>{t?.(),N(`[${l.prefix(e,r)}]`,"unmount effect"),this.data.get(l.prefix(e,r)).listeners?.length===0&&this.clear(e,r)},[])}}class Y{constructor(e){this.sharedData=e}get(e,r){e=T(e);const t=r||"_global";return this.sharedData.get(e,t)}set(e,r,t){e=T(e);const s=t||"_global";this.sharedData.setValue(e,s,r)}clearAll(){this.sharedData.clearAll()}clearScope(e){const r=e||"_global";this.sharedData.data.forEach((t,s)=>{const[f]=l.extractPrefix(s);if(f===r){this.sharedData.clear(s,f);return}})}resolve(e){const{key:r,prefix:t}=e;return this.get(r,t)}clear(e,r){let t,s;typeof e=="string"?(t=e,s=r||"_global"):(t=e.key,s=e.prefix),this.sharedData.clear(t,s)}has(e,r="_global"){const t=r||"_global";return!!this.sharedData.has(e,t)}getAll(){const e={};return this.sharedData.data.forEach((r,t)=>{const[s,f]=l.extractPrefix(t);e[s]=e[s]||{},e[s][f]=r}),e}}const k=a=>{const e=ue();return{prefix:a??e?.scopeName??"_global"}};class fe extends l{defaultValue(){return{value:void 0}}init(e,r,t){super.init(e,r,{value:t})}setValue(e,r,t){super.setValue(e,r,{value:t})}removeListener(e,r,t){super.removeListener(e,r,t)}}class H extends Y{get(e,r="_global"){e=T(e);const t=r||"_global";return R.get(e,t)?.value}set(e,r,t="_global"){e=T(e);const s=t||"_global";R.setValue(e,s,{value:r})}}const R=new fe,de=new H(R),he=(a,e)=>{const r=e??e??"_global";return{key:F(),prefix:r,initialValue:a}};function be(a,e,r){let t,s,f=r;if(typeof a!="string"){const{key:u,initialValue:m,prefix:S}=a;t=u,s=m,f=S}else t=T(a),s=e;const{prefix:o}=k(f);R.init(t,o,s);const A=g.useMemo(()=>u=>(R.init(t,o,e),R.addListener(t,o,u),()=>{R.removeListener(t,o,u)}),[]),L=g.useMemo(()=>()=>R.get(t,o)?.value,[]),O=g.useSyncExternalStore(A,L),P=u=>{const m=typeof u=="function"?u(R.get(t,o)?.value):u;m!==O&&(R.setValue(t,o,m),R.callListeners(t,o))};return R.useEffect(t,o),[O,P]}class Se extends l{defaultValue(){return{fnState:{results:void 0,isLoading:!1,error:void 0}}}init(e,r){super.init(e,r,this.defaultValue())}setValue(e,r,t){super.setValue(e,r,t)}}class Z extends Y{get(e,r="_global"){e=T(e);const t=r||"_global";return x.get(e,t)?.fnState}set(e,r,t="_global"){e=T(e);const s=t||"_global";x.setValue(e,s,r)}}const x=new Se,ge=new Z(x),pe=(a,e)=>{const r=e??e??"_global";return{key:F(),prefix:r,fn:a}};function ve(a,e,r){let t,s,f=r;if(typeof a!="string"){const{key:u,fn:m,prefix:S}=a;t=u,s=m,f=S}else t=T(a),s=e;const{prefix:o}=k(f);x.init(t,o);const A=g.useMemo(()=>u=>(x.init(t,o),x.addListener(t,o,u),()=>{x.removeListener(t,o,u)}),[]),L=g.useMemo(()=>()=>x.get(t,o).fnState,[]),O=g.useSyncExternalStore(A,L),P=async(u,...m)=>{const S=x.get(t,o);if(!u&&(S.fnState.isLoading||S.fnState.results!==void 0))return S.fnState;S.fnState={...S.fnState,isLoading:!0,error:void 0},S.listeners.forEach(d=>d());try{const d=await s(...m);S.fnState={results:d,isLoading:!1,error:void 0}}catch(d){S.fnState={...S.fnState,isLoading:!1,error:d}}S.listeners.forEach(d=>d())};return x.useEffect(t,o),{state:O,trigger:(...u)=>{P(!1,...u)},forceTrigger:(...u)=>{P(!0,...u)},clear:()=>{const u=x.get(t,o);u&&(u.fnState=x.defaultValue().fnState,x.callListeners(t,o))}}}class Ee extends l{defaultValue(){return{fnState:{data:void 0,isLoading:!1,error:void 0,subscribed:!1}}}init(e,r){super.init(e,r,this.defaultValue())}setValue(e,r,t){super.setValue(e,r,t)}useEffect(e,r){g.useEffect(()=>()=>{N(`[${l.prefix(e,r)}]`,"unmount effect2"),this.get(e,r)?.listeners.length===0&&this.unsubscribe(e,r)},[]),super.useEffect(e,r)}async unsubscribe(e,r){const t=this.get(e,r);t&&(t.unsubscribe&&(t.unsubscribe(),t.unsubscribe=void 0),t.fnState={...t.fnState,subscribed:!1},this.callListeners(e,r))}}class Q extends Y{get(e,r="_global"){e=T(e);const t=r||"_global";return E.get(e,t)?.fnState}set(e,r,t="_global"){e=T(e);const s=t||"_global";E.setValue(e,s,r)}}const E=new Ee,me=new Q(E),xe=(a,e)=>{const r=e??e??"_global";return{key:F(),prefix:r,subscriber:a}};function _e(a,e,r){let t,s,f=r;if(typeof a!="string"){const{key:d,subscriber:c,prefix:_}=a;t=d,s=c,f=_}else t=T(a),s=e;const{prefix:o}=k(f);E.init(t,o);const A=g.useMemo(()=>d=>(E.init(t,o),E.addListener(t,o,d),()=>{E.removeListener(t,o,d)}),[]),L=g.useMemo(()=>()=>E.get(t,o).fnState,[]),O=g.useSyncExternalStore(A,L),P=d=>{const c=E.get(t,o);c.fnState={...c.fnState,data:d},c.listeners.forEach(_=>_())},u=d=>{const c=E.get(t,o);c.fnState={...c.fnState,isLoading:!1,data:void 0,error:d},c.listeners.forEach(_=>_())},m=()=>{const d=E.get(t,o);d.fnState={...d.fnState,isLoading:!1},d.listeners.forEach(c=>c())},S=async d=>{const c=E.get(t,o);if(d&&(await E.unsubscribe(t,o),c.fnState={...c.fnState,isLoading:!1,data:void 0,error:void 0,subscribed:!1}),c.fnState.subscribed)return c.fnState;N("triggered !!"),c.fnState={...c.fnState,isLoading:!0,error:void 0},c.listeners.forEach(_=>_());try{c.unsubscribe=await s(P,u,m),c.fnState.subscribed=!0}catch(_){c.fnState={...c.fnState,isLoading:!1,error:_}}c.listeners.forEach(_=>_())};return E.useEffect(t,o),{state:O,trigger:()=>{S(!1)},forceTrigger:()=>{S(!0)},unsubscribe:()=>{E.unsubscribe(t,o)}}}h.SharedFunctionsApi=Z,h.SharedStatesApi=H,h.SharedStatesProvider=le,h.SharedSubscriptionsApi=Q,h.createSharedFunction=pe,h.createSharedState=he,h.createSharedSubscription=xe,h.setDevMode=ce,h.sharedFunctionsApi=ge,h.sharedStatesApi=de,h.sharedSubscriptionsApi=me,h.useSharedFunction=ve,h.useSharedState=be,h.useSharedSubscription=_e,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
package/dist/types.d.ts CHANGED
@@ -4,4 +4,7 @@ export type Prefix = "_global" | ({} & string);
4
4
  export interface DataMapValue {
5
5
  listeners: AFunction[];
6
6
  }
7
- export type NonEmptyString<T extends string> = '' extends T ? never : T;
7
+ export interface SharedCreated {
8
+ key: string;
9
+ prefix: string;
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-shared-states",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "type": "module",
5
5
  "description": "Global state made as simple as useState, with zero config, built-in async caching, and automatic scoping.",
6
6
  "keywords": [
@@ -26,10 +26,13 @@
26
26
  },
27
27
  "homepage": "https://github.com/HichemTab-tech/react-shared-states#readme",
28
28
  "devDependencies": {
29
+ "@testing-library/dom": "^10.4.1",
30
+ "@testing-library/react": "^16.3.0",
29
31
  "@types/node": "^24.3.0",
30
32
  "@types/react": "^19.1.11",
31
33
  "@types/react-dom": "^19.1.7",
32
34
  "@vitejs/plugin-react": "^5.0.1",
35
+ "jsdom": "^26.1.0",
33
36
  "react": "^19.1.1",
34
37
  "react-dom": "^19.1.1",
35
38
  "typescript": "^5.9.2",
@@ -39,8 +42,9 @@
39
42
  "vitest": "^3.2.4"
40
43
  },
41
44
  "scripts": {
45
+ "tsc": "tsc",
42
46
  "bump": "node scripts/bumper.js",
43
- "build": "vite build",
47
+ "build": "tsc && vite build",
44
48
  "test": "vitest",
45
49
  "preview": "vite preview",
46
50
  "dev:demo": "vite --config demo/vite.config.demo.ts",
@@ -0,0 +1,358 @@
1
+ import {describe, it, expect, beforeEach, vi, afterEach} from 'vitest'
2
+ import React from 'react'
3
+ import {render, screen, fireEvent, act, cleanup} from '@testing-library/react'
4
+ import {
5
+ createSharedFunction,
6
+ createSharedState, createSharedSubscription,
7
+ SharedStatesProvider,
8
+ useSharedFunction,
9
+ useSharedState,
10
+ useSharedSubscription
11
+ } from "../src";
12
+ import type {SubscriberEvents} from "../src/hooks/use-shared-subscription";
13
+
14
+ // Mocking random to have predictable keys for created states/functions/subscriptions
15
+ vi.mock('../src/lib/utils', async (importActual) => {
16
+ const actual = await importActual<typeof import('../src/lib/utils')>();
17
+ let count = 0;
18
+ // noinspection JSUnusedGlobalSymbols
19
+ return {
20
+ ...actual,
21
+ random: () => `test-key-${count++}`,
22
+ };
23
+ });
24
+
25
+ beforeEach(() => {
26
+ cleanup();
27
+ // Reset the mocked random key counter
28
+ vi.clearAllMocks();
29
+ });
30
+ afterEach(() => {
31
+ vi.useRealTimers();
32
+ })
33
+
34
+ describe('useSharedState', () => {
35
+ it('should share state between two components', () => {
36
+ const TestComponent1 = () => {
37
+ const [count] = useSharedState('count', 0);
38
+ return <span data-testid="value1">{count}</span>;
39
+ };
40
+
41
+ const TestComponent2 = () => {
42
+ const [count, setCount] = useSharedState('count', 0);
43
+ return (
44
+ <div>
45
+ <span data-testid="value2">{count}</span>
46
+ <button onClick={() => setCount(c => c + 1)}>inc</button>
47
+ </div>
48
+ );
49
+ };
50
+
51
+ render(
52
+ <>
53
+ <TestComponent1/>
54
+ <TestComponent2/>
55
+ </>
56
+ );
57
+
58
+ expect(screen.getByTestId('value1').textContent).toBe('0');
59
+ expect(screen.getByTestId('value2').textContent).toBe('0');
60
+
61
+ act(() => {
62
+ fireEvent.click(screen.getByText('inc'));
63
+ });
64
+
65
+ expect(screen.getByTestId('value1').textContent).toBe('1');
66
+ expect(screen.getByTestId('value2').textContent).toBe('1');
67
+ });
68
+
69
+ it('should isolate state with SharedStatesProvider', () => {
70
+ const TestComponent = () => {
71
+ const [count, setCount] = useSharedState('count', 0);
72
+ return (
73
+ <div>
74
+ <span>{count}</span>
75
+ <button onClick={() => setCount(c => c + 1)}>inc</button>
76
+ </div>
77
+ );
78
+ };
79
+
80
+ render(
81
+ <div>
82
+ <div data-testid="scope1">
83
+ <SharedStatesProvider scopeName="scope1">
84
+ <TestComponent/>
85
+ </SharedStatesProvider>
86
+ </div>
87
+ <div data-testid="scope2">
88
+ <SharedStatesProvider scopeName="scope2">
89
+ <TestComponent/>
90
+ </SharedStatesProvider>
91
+ </div>
92
+ </div>
93
+ );
94
+
95
+ const scope1Button = screen.getAllByText('inc')[0];
96
+ const scope2Button = screen.getAllByText('inc')[1];
97
+
98
+ act(() => {
99
+ fireEvent.click(scope1Button);
100
+ });
101
+
102
+ expect(screen.getByTestId('scope1').textContent).toContain('1');
103
+ expect(screen.getByTestId('scope2').textContent).toContain('0');
104
+
105
+ act(() => {
106
+ fireEvent.click(scope2Button);
107
+ fireEvent.click(scope2Button);
108
+ });
109
+
110
+ expect(screen.getByTestId('scope1').textContent).toContain('1');
111
+ expect(screen.getByTestId('scope2').textContent).toContain('2');
112
+ });
113
+
114
+ it('should work with createSharedState', () => {
115
+ const sharedCounter = createSharedState(10);
116
+
117
+ const TestComponent1 = () => {
118
+ const [count] = useSharedState(sharedCounter);
119
+ return <span data-testid="value1">{count}</span>;
120
+ };
121
+
122
+ const TestComponent2 = () => {
123
+ const [count, setCount] = useSharedState(sharedCounter);
124
+ return <button onClick={() => setCount(count + 5)}>inc</button>;
125
+ };
126
+
127
+ render(
128
+ <>
129
+ <TestComponent1/>
130
+ <TestComponent2/>
131
+ </>
132
+ );
133
+
134
+ expect(screen.getByTestId('value1').textContent).toBe('10');
135
+
136
+ act(() => {
137
+ fireEvent.click(screen.getByText('inc'));
138
+ });
139
+
140
+ expect(screen.getByTestId('value1').textContent).toBe('15');
141
+ });
142
+ });
143
+
144
+ describe('useSharedFunction', () => {
145
+ const mockApiCall = vi.fn((...args: any[]) => new Promise(resolve => setTimeout(() => resolve(`result: ${args.join(',')}`), 100)));
146
+
147
+ beforeEach(() => {
148
+ mockApiCall.mockClear();
149
+ vi.useFakeTimers();
150
+ });
151
+
152
+ const TestComponent = ({fnKey, sharedFn}: { fnKey: string, sharedFn?: any }) => {
153
+ const {state, trigger, forceTrigger, clear} = sharedFn ? useSharedFunction(sharedFn) : useSharedFunction(fnKey, mockApiCall);
154
+ return (
155
+ <div>
156
+ {state.isLoading && <span>Loading...</span>}
157
+ {state.error as any && <span>{String(state.error)}</span>}
158
+ {state.results && <span data-testid="result">{String(state.results)}</span>}
159
+ <button onClick={() => trigger('arg1')}>trigger</button>
160
+ <button onClick={() => forceTrigger('arg2')}>force</button>
161
+ <button onClick={() => clear()}>clear</button>
162
+ </div>
163
+ );
164
+ };
165
+
166
+ it('should handle async function lifecycle', async () => {
167
+ render(<TestComponent fnKey="test-fn"/>);
168
+
169
+ // Initial state
170
+ expect(screen.queryByText('Loading...')).toBeNull();
171
+ expect(screen.queryByTestId('result')).toBeNull();
172
+
173
+ // Trigger
174
+ act(() => {
175
+ fireEvent.click(screen.getByText('trigger'));
176
+ });
177
+ expect(screen.getByText('Loading...')).toBeDefined();
178
+
179
+ // Resolve
180
+ await act(async () => {
181
+ await vi.advanceTimersByTimeAsync(100);
182
+ });
183
+ expect(screen.queryByText('Loading...')).toBeNull();
184
+ expect(screen.getByTestId('result').textContent).toBe('result: arg1');
185
+ expect(mockApiCall).toHaveBeenCalledTimes(1);
186
+ expect(mockApiCall).toHaveBeenCalledWith('arg1');
187
+ });
188
+
189
+ it('should not trigger if already running or has data', async () => {
190
+ render(<TestComponent fnKey="test-fn"/>);
191
+ act(() => {
192
+ fireEvent.click(screen.getByText('trigger'));
193
+ });
194
+ await act(async () => {
195
+ await vi.advanceTimersByTimeAsync(100);
196
+ });
197
+ expect(mockApiCall).toHaveBeenCalledTimes(1);
198
+
199
+ // Trigger again, should not call mockApiCall
200
+ act(() => {
201
+ fireEvent.click(screen.getByText('trigger'));
202
+ });
203
+ expect(mockApiCall).toHaveBeenCalledTimes(1);
204
+ });
205
+
206
+ it('should force trigger', async () => {
207
+ render(<TestComponent fnKey="test-fn"/>);
208
+ act(() => {
209
+ fireEvent.click(screen.getByText('trigger'));
210
+ });
211
+ await act(async () => {
212
+ await vi.advanceTimersByTimeAsync(100);
213
+ });
214
+ expect(mockApiCall).toHaveBeenCalledTimes(1);
215
+
216
+ // Force trigger
217
+ act(() => {
218
+ fireEvent.click(screen.getByText('force'));
219
+ });
220
+ expect(screen.getByText('Loading...')).toBeDefined();
221
+ await act(async () => {
222
+ await vi.advanceTimersByTimeAsync(100);
223
+ });
224
+ expect(mockApiCall).toHaveBeenCalledTimes(2);
225
+ expect(mockApiCall).toHaveBeenCalledWith('arg2');
226
+ expect(screen.getByTestId('result').textContent).toBe('result: arg2');
227
+ });
228
+
229
+ it('should clear state', async () => {
230
+ render(<TestComponent fnKey="test-fn"/>);
231
+ act(() => {
232
+ fireEvent.click(screen.getByText('trigger'));
233
+ });
234
+ await act(async () => {
235
+ await vi.advanceTimersByTimeAsync(100);
236
+ });
237
+ expect(screen.getByTestId('result')).toBeDefined();
238
+
239
+ act(() => {
240
+ fireEvent.click(screen.getByText('clear'));
241
+ });
242
+ expect(screen.queryByTestId('result')).toBeNull();
243
+ });
244
+
245
+ it('should work with createSharedFunction', async () => {
246
+ const sharedFunction = createSharedFunction(mockApiCall);
247
+ render(<TestComponent fnKey="unused" sharedFn={sharedFunction}/>);
248
+
249
+ act(() => {
250
+ fireEvent.click(screen.getByText('trigger'));
251
+ });
252
+ await act(async () => {
253
+ await vi.advanceTimersByTimeAsync(100);
254
+ });
255
+ expect(mockApiCall).toHaveBeenCalledTimes(1);
256
+ expect(screen.getByTestId('result').textContent).toBe('result: arg1');
257
+ });
258
+ });
259
+
260
+ describe('useSharedSubscription', () => {
261
+ let mockSubscriber: (set: SubscriberEvents.Set<any>, onError: SubscriberEvents.OnError, onCompletion: SubscriberEvents.OnCompletion) => () => void;
262
+ const mockUnsubscribe = vi.fn();
263
+
264
+ beforeEach(() => {
265
+ mockUnsubscribe.mockClear();
266
+ mockSubscriber = vi.fn((set, _onError, onCompletion) => {
267
+ // Simulate async subscription
268
+ const timeout = setTimeout(() => {
269
+ set('initial data');
270
+ onCompletion();
271
+ }, 100);
272
+ return () => {
273
+ clearTimeout(timeout);
274
+ mockUnsubscribe();
275
+ };
276
+ });
277
+ vi.useFakeTimers();
278
+ });
279
+
280
+ const TestComponent = ({subKey, sharedSub}: { subKey: string, sharedSub?: any }) => {
281
+ const {state, trigger, unsubscribe} = sharedSub ? useSharedSubscription(sharedSub) : useSharedSubscription(subKey, mockSubscriber);
282
+ return (
283
+ <div>
284
+ {state.isLoading && <span>Loading...</span>}
285
+ {state.error && <span>{String(state.error)}</span>}
286
+ {state.data && <span data-testid="data">{String(state.data)}</span>}
287
+ <span>Subscribed: {String(state.subscribed)}</span>
288
+ <button onClick={() => trigger()}>subscribe</button>
289
+ <button onClick={() => unsubscribe()}>unsubscribe</button>
290
+ </div>
291
+ );
292
+ };
293
+
294
+ it('should handle subscription lifecycle', async () => {
295
+ render(<TestComponent subKey="test-sub"/>);
296
+
297
+ // Initial state
298
+ expect(screen.getByText('Subscribed: false')).toBeDefined();
299
+
300
+ // Trigger subscription
301
+ act(() => {
302
+ fireEvent.click(screen.getByText('subscribe'));
303
+ });
304
+ expect(screen.getByText('Loading...')).toBeDefined();
305
+
306
+ // Subscription completes
307
+ await act(async () => {
308
+ await vi.advanceTimersByTimeAsync(100);
309
+ });
310
+ expect(screen.queryByText('Loading...')).toBeNull();
311
+ expect(screen.getByTestId('data').textContent).toBe('initial data');
312
+ expect(screen.getByText('Subscribed: true')).toBeDefined();
313
+ expect(mockSubscriber).toHaveBeenCalledTimes(1);
314
+ });
315
+
316
+ it('should unsubscribe', async () => {
317
+ render(<TestComponent subKey="test-sub"/>);
318
+ act(() => {
319
+ fireEvent.click(screen.getByText('subscribe'));
320
+ });
321
+ await act(async () => {
322
+ await vi.advanceTimersByTimeAsync(100);
323
+ });
324
+
325
+ act(() => {
326
+ fireEvent.click(screen.getByText('unsubscribe'));
327
+ });
328
+ expect(mockUnsubscribe).toHaveBeenCalledTimes(1);
329
+ expect(screen.getByText('Subscribed: false')).toBeDefined();
330
+ });
331
+
332
+ it('should automatically unsubscribe on unmount', async () => {
333
+ const {unmount} = render(<TestComponent subKey="test-sub"/>);
334
+ act(() => {
335
+ fireEvent.click(screen.getByText('subscribe'));
336
+ });
337
+ await act(async () => {
338
+ await vi.advanceTimersByTimeAsync(100);
339
+ });
340
+
341
+ unmount();
342
+ expect(mockUnsubscribe).toHaveBeenCalledTimes(1);
343
+ });
344
+
345
+ it('should work with createSharedSubscription', async () => {
346
+ const sharedSubscription = createSharedSubscription(mockSubscriber);
347
+ render(<TestComponent subKey="unused" sharedSub={sharedSubscription}/>);
348
+
349
+ act(() => {
350
+ fireEvent.click(screen.getByText('subscribe'));
351
+ });
352
+ await act(async () => {
353
+ await vi.advanceTimersByTimeAsync(100);
354
+ });
355
+ expect(mockSubscriber).toHaveBeenCalledTimes(1);
356
+ expect(screen.getByTestId('data').textContent).toBe('initial data');
357
+ });
358
+ });
@@ -0,0 +1,8 @@
1
+ import { defineConfig, mergeConfig } from 'vitest/config'
2
+ import viteConfig from './vite.config'
3
+
4
+ export default mergeConfig(viteConfig, defineConfig({
5
+ test: {
6
+ environment: "jsdom",
7
+ },
8
+ }))