@faststore/sdk
Advanced tools
Comparing version 1.3.11 to 1.3.12
@@ -6,2 +6,10 @@ # Change Log | ||
## 1.3.12 (2021-12-02) | ||
**Note:** Version bump only for package @faststore/sdk | ||
## 1.3.11 (2021-12-02) | ||
@@ -8,0 +16,0 @@ |
@@ -79,2 +79,4 @@ 'use strict'; | ||
const equals = (s1, s2) => format(s1).href === format(s2).href; | ||
const removeFacet = (state, facet) => { | ||
@@ -165,64 +167,78 @@ const { | ||
}; | ||
const useSearchState = initialState => { | ||
const [state, dispatch] = React.useReducer(reducer, initialState, initialize); | ||
return React.useMemo(() => ({ | ||
state, | ||
setSort: sort => dispatch({ | ||
type: 'setSort', | ||
payload: sort | ||
}), | ||
setTerm: term => dispatch({ | ||
type: 'setTerm', | ||
payload: term | ||
}), | ||
setPage: page => dispatch({ | ||
type: 'setPage', | ||
payload: page | ||
}), | ||
setFacet: (facet, unique = false) => dispatch({ | ||
type: 'setFacet', | ||
payload: { | ||
facet, | ||
unique | ||
} | ||
}), | ||
removeFacet: facet => dispatch({ | ||
type: 'removeFacet', | ||
payload: facet | ||
}), | ||
toggleFacet: facet => dispatch({ | ||
type: 'toggleFacet', | ||
payload: facet | ||
}), | ||
toggleFacets: facets => dispatch({ | ||
type: 'toggleFacets', | ||
payload: facets | ||
}) | ||
}), [state]); | ||
const dispatcher = (onChange, state) => action => { | ||
const newState = reducer(state, action); | ||
if (!equals(newState, state)) { | ||
onChange(format(newState)); | ||
} | ||
}; | ||
const useSearchState = (initialState, onChange) => { | ||
const state = React.useMemo(() => initialize(initialState), [initialState]); | ||
return React.useMemo(() => { | ||
const dispatch = dispatcher(onChange, state); | ||
return { | ||
state, | ||
setSort: sort => dispatch({ | ||
type: 'setSort', | ||
payload: sort | ||
}), | ||
setTerm: term => dispatch({ | ||
type: 'setTerm', | ||
payload: term | ||
}), | ||
setPage: page => dispatch({ | ||
type: 'setPage', | ||
payload: page | ||
}), | ||
setFacet: (facet, unique = false) => dispatch({ | ||
type: 'setFacet', | ||
payload: { | ||
facet, | ||
unique | ||
} | ||
}), | ||
removeFacet: facet => dispatch({ | ||
type: 'removeFacet', | ||
payload: facet | ||
}), | ||
toggleFacet: facet => dispatch({ | ||
type: 'toggleFacet', | ||
payload: facet | ||
}), | ||
toggleFacets: facets => dispatch({ | ||
type: 'toggleFacets', | ||
payload: facets | ||
}) | ||
}; | ||
}, [onChange, state]); | ||
}; | ||
const format = params => { | ||
const map = []; | ||
const query = []; | ||
const url = new URL(params.base, 'http://localhost'); | ||
const { | ||
page, | ||
selectedFacets, | ||
sort, | ||
term | ||
} = params; | ||
if (params.term !== null) { | ||
map.push('term'); | ||
query.push(params.term); | ||
if (term !== null) { | ||
url.searchParams.set('q', term); | ||
} | ||
for (const facet of params.selectedFacets) { | ||
map.push(facet.key); | ||
query.push(facet.value); | ||
const facets = new Set(); | ||
for (const facet of selectedFacets) { | ||
url.searchParams.append(facet.key, facet.value); | ||
facets.add(facet.key); | ||
} | ||
map.push('sort'); | ||
query.push(params.sort); | ||
if (typeof params.page === 'number') { | ||
map.push('page'); | ||
query.push(params.page.toString()); | ||
if (selectedFacets.length > 0) { | ||
url.searchParams.set('facets', Array.from(facets).join(',')); | ||
} | ||
const url = new URL(`${params.base}${query.join('/')}`, 'http://localhost'); | ||
url.searchParams.set('map', map.join(',')); | ||
url.searchParams.set('sort', sort); | ||
url.searchParams.set('page', page.toString()); | ||
return url; | ||
@@ -234,44 +250,27 @@ }; | ||
}) => { | ||
var _searchParams$get; | ||
var _searchParams$get, _searchParams$get2, _searchParams$get3, _searchParams$get$spl, _searchParams$get4; | ||
const spath = pathname.split('/').slice(1); | ||
const smap = (_searchParams$get = searchParams.get('map')) == null ? void 0 : _searchParams$get.split(','); | ||
if (smap === undefined) { | ||
throw new SDKError(`Cannot parse selected facets from window.location. Please add a 'map' querystring to the page`); | ||
} | ||
if (smap.length > spath.length) { | ||
throw new SDKError(`Invalid map querystring. There are more map params than segments on the path: (map: ${smap.join(',')}, pathname: ${pathname}). `); | ||
} | ||
const nfacets = smap.length; | ||
const offset = spath.length - nfacets; | ||
let state = initialize({ | ||
base: `/${spath.slice(0, offset).join('/')}` | ||
base: pathname, | ||
term: (_searchParams$get = searchParams.get('q')) != null ? _searchParams$get : null, | ||
sort: (_searchParams$get2 = searchParams.get('sort')) != null ? _searchParams$get2 : undefined, | ||
page: Number((_searchParams$get3 = searchParams.get('page')) != null ? _searchParams$get3 : 0) | ||
}); | ||
const facets = (_searchParams$get$spl = (_searchParams$get4 = searchParams.get('facets')) == null ? void 0 : _searchParams$get4.split(',')) != null ? _searchParams$get$spl : []; | ||
for (let it = 0; it < nfacets; it++) { | ||
const key = smap[it]; | ||
const value = spath[it + offset]; | ||
const action = key === 'sort' ? { | ||
type: 'setSort', | ||
payload: value | ||
} : key === 'term' ? { | ||
type: 'setTerm', | ||
payload: value | ||
} : key === 'page' ? { | ||
type: 'setPage', | ||
payload: Number(value) | ||
} : { | ||
type: 'setFacet', | ||
payload: { | ||
facet: { | ||
key, | ||
value | ||
}, | ||
unique: false | ||
} | ||
}; | ||
state = reducer(state, action); | ||
for (const facet of facets) { | ||
const values = searchParams.getAll(facet); | ||
for (const value of values) { | ||
state = reducer(state, { | ||
type: 'setFacet', | ||
payload: { | ||
facet: { | ||
key: facet, | ||
value | ||
}, | ||
unique: false | ||
} | ||
}); | ||
} | ||
} | ||
@@ -301,4 +300,3 @@ | ||
const [pages, dispatch] = React.useReducer(reducer$1, initialPage, () => [initialPage]); | ||
return React.useMemo(() => ({ | ||
pages, | ||
const actions = React.useMemo(() => ({ | ||
addPrevPage: () => dispatch({ | ||
@@ -310,3 +308,7 @@ type: 'addPrev' | ||
}) | ||
}), [pages]); | ||
}), []); | ||
return { | ||
pages, | ||
...actions | ||
}; | ||
}; | ||
@@ -324,3 +326,3 @@ | ||
...searchActions | ||
} = useSearchState(rest); | ||
} = useSearchState(rest, onChange); | ||
const { | ||
@@ -330,5 +332,2 @@ pages, | ||
} = useSearchInfiniteState(state.page); | ||
React.useEffect(() => { | ||
onChange(format(state)); | ||
}, [onChange, state]); | ||
const value = React.useMemo(() => ({ | ||
@@ -335,0 +334,0 @@ state, |
@@ -1,2 +0,2 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),a=(e=t)&&"object"==typeof e&&"default"in e?e.default:e,s=require("idb-keyval");class r extends Error{constructor(e){super("[sdk]: "+e)}}const n=new Set(["price_desc","price_asc","orders_desc","name_desc","name_asc","release_desc","discount_desc","score_desc"]),o=({sort:e="score_desc",selectedFacets:t=[],term:a=null,base:s="/",page:r=0}={})=>({sort:e,selectedFacets:t,term:a,base:s.endsWith("/")?s:s+"/",page:r}),c=(e,t)=>{const{value:a}=t,s=e.selectedFacets.findIndex(e=>e.value===a);if(s<0)throw new r(`Cannot remove ${a} from search params`);return{...e,selectedFacets:e.selectedFacets.filter((e,t)=>0===t||t!==s)}},i=(e,t,a)=>{if(!0===a){const a=e.selectedFacets.findIndex(e=>e.key===t.key);if(a>-1)return{...e,selectedFacets:e.selectedFacets.map((e,s)=>s===a?t:e)}}return{...e,selectedFacets:[...e.selectedFacets,t]}},l=(e,t)=>void 0!==e.selectedFacets.find(e=>e.key===t.key&&e.value===t.value)?c(e,t):i(e,t,!1),d=(e,t)=>{switch(t.type){case"setSort":if(!n.has(t.payload))throw new r(`Sort param ${t.payload} is unknown`);return e.sort===t.payload?e:{...e,sort:t.payload};case"setTerm":return e.term===t.payload?e:{...e,term:t.payload};case"setPage":return e.page===t.payload?e:{...e,page:t.payload};case"setFacet":return i(e,t.payload.facet,t.payload.unique);case"removeFacet":return c(e,t.payload);case"toggleFacet":return l(e,t.payload);case"toggleFacets":return((e,t)=>t.reduce((e,t)=>l(e,t),e))(e,t.payload);default:throw new r("Uknown action of search state machine")}},u=e=>{const t=[],a=[];null!==e.term&&(t.push("term"),a.push(e.term));for(const s of e.selectedFacets)t.push(s.key),a.push(s.value);t.push("sort"),a.push(e.sort),"number"==typeof e.page&&(t.push("page"),a.push(e.page.toString()));const s=new URL(`${e.base}${a.join("/")}`,"http://localhost");return s.searchParams.set("map",t.join(",")),s},p=(e,t)=>{switch(t.type){case"addPrev":return[e[0]-1,...e];case"addNext":const t=Number(e[e.length-1])+1;return[...e,t];default:throw new r("Unknown action for infinite search")}},m=t.createContext(void 0),y=e=>{var a;const s=t.useContext(e);if(void 0!==s)return s;throw new r((null!=(a=e.displayName)?a:"Context")+" needs to be on the React tree")},h=()=>y(m),g=e=>{const{pathname:t,search:a}=u(e);return`${t}${a}`},v=t.createContext(void 0);v.displayName="UIContext";const f={displayMinicart:!1},w=()=>({}),x=(e,a)=>{const[r,n]=t.useState(()=>{return{payload:(e=a,"function"==typeof e?a():a),state:"initial"};var e});return t.useEffect(()=>{let t=!1;return(async()=>{if("initial"===r.state){var a;const o=null!=(a=await(async e=>{try{const t=await s.get(e);return null!=t?t:null}catch(e){return null}})(e))?a:r.payload;t||n({payload:o,state:"hydrated"})}else t||(async(e,t)=>{try{await s.set(e,t)}catch(e){}})(e,r.payload)})(),()=>{t=!0}},[r.payload,r.state,e]),t.useMemo(()=>[r.payload,e=>n({state:"hydrated",payload:e})],[r.payload])},C=t.createContext(void 0);C.displayName="StoreSessionContext";const S={currency:{code:"USD",symbol:"$"},country:"USA",locale:"en",postalCode:null,channel:null,user:null},P=t.createContext(void 0);P.displayName="StoreCartContext";const E={id:"",items:{}},I=(e,t,a)=>({...e,items:{...e.items,[t]:a}}),F=({children:e,onItemAdd:s,initialCart:n,onItemRemove:o,onItemUpdate:c,namespace:i="main"})=>{const l=i+"::store::cart",[d,u]=x(l,{...E,...n}),p=t.useMemo(()=>{const e=Object.values(d.items);return{...d,setCart:e=>{const t={...e,items:e.items.reduce((e,t)=>(e[t.id]=t,e),{})};u(t)},addItem:e=>{if(!e.id)throw new r("You must provide an `id` for items");if(e.quantity<0)throw new r("Item quantity needs to be higher than zero");const t=d.items[e.id],a=t?{...e,quantity:t.quantity+e.quantity}:e,n=t?c:s;u(I(d,a.id,a)),null==n||n(a,t)},updateItemQuantity:(e,t)=>{const a=d.items[e];if(!a)throw new r("Item with id not found: "+e);const s={...a,quantity:t};u(I(d,e,s)),null==c||c(s,a)},removeItem:e=>{const t=d.items[e];u(((e,t)=>{const{[t]:a,...s}=e.items;return{...e,items:s}})(d,e)),null==o||o(t)},emptyCart:()=>u({...d,items:{}}),getItem:e=>d.items[e],inCart:e=>Boolean(d.items[e]),items:e,isEmpty:0===e.length}},[d,s,o,c,u]);return a.createElement(P.Provider,{value:p},e)},M=t.createContext(void 0);M.displayName="StoreCartValidatorContext";const N=async()=>null;let _=Promise.resolve();const b=({children:e,onValidateCart:s=N})=>{const{items:r,id:n,setCart:o}=y(P),c=t.useMemo(()=>({id:n,items:r}),[n,r]),[i,l]=t.useState(!1);return t.useEffect(()=>{let e=!1;return _=_.then(async()=>{if(e)return;l(!0);const t=await s(c);e||(l(!1),null!=t&&o(t))}),()=>{e=!0}},[c,s,o]),a.createElement(M.Provider,{value:i},e)};exports.ANALYTICS_EVENT_TYPE="AnalyticsEvent",exports.CartProvider=({mode:e="pure",onValidateCart:t,children:s,...r})=>a.createElement(F,Object.assign({},r),"optimistic"===e?a.createElement(b,{onValidateCart:t},s):s),exports.STORE_EVENT_PREFIX="store:",exports.SearchProvider=({children:e,itemsPerPage:s,onChange:r,...n})=>{const{state:c,...i}=(e=>{const[a,s]=t.useReducer(d,e,o);return t.useMemo(()=>({state:a,setSort:e=>s({type:"setSort",payload:e}),setTerm:e=>s({type:"setTerm",payload:e}),setPage:e=>s({type:"setPage",payload:e}),setFacet:(e,t=!1)=>s({type:"setFacet",payload:{facet:e,unique:t}}),removeFacet:e=>s({type:"removeFacet",payload:e}),toggleFacet:e=>s({type:"toggleFacet",payload:e}),toggleFacets:e=>s({type:"toggleFacets",payload:e})}),[a])})(n),{pages:l,...y}=(e=>{const[a,s]=t.useReducer(p,e,()=>[e]);return t.useMemo(()=>({pages:a,addPrevPage:()=>s({type:"addPrev"}),addNextPage:()=>s({type:"addNext"})}),[a])})(c.page);t.useEffect(()=>{r(u(c))},[r,c]);const h=t.useMemo(()=>({state:c,...i,pages:l,...y,itemsPerPage:s}),[y,s,l,i,c]);return a.createElement(m.Provider,{value:h},e)},exports.SessionContext=C,exports.SessionProvider=({children:e,initialState:s,namespace:r="main"})=>{const[n,o]=x(r+"::store::session",()=>({...S,...s})),c=t.useMemo(()=>({...n,setSession:e=>o({...n,...e})}),[n,o]);return a.createElement(C.Provider,{value:c},e)},exports.UIContext=v,exports.UIProvider=({children:e,actions:s={},effects:r=w,initialState:n={}})=>{const[o,c]=t.useReducer((e=>{const t={OPEN_MINICART:e=>({...e,displayMinicart:!0}),CLOSE_MINICART:e=>({...e,displayMinicart:!1}),...e};return(e,{type:a,data:s})=>{const r=t[a];if("function"==typeof r)return r(e,s);throw new Error("Unknown UI state")}})(s),{...f,...n}),i=t.useMemo(()=>({...r(c),openMinicart:()=>c({type:"OPEN_MINICART"}),closeMinicart:()=>c({type:"CLOSE_MINICART"})}),[r]),l=t.useMemo(()=>({...o,...i}),[i,o]);return a.createElement(v.Provider,{value:l},e)},exports.formatSearchState=u,exports.initSearchState=o,exports.parseSearchState=({pathname:e,searchParams:t})=>{var a;const s=e.split("/").slice(1),n=null==(a=t.get("map"))?void 0:a.split(",");if(void 0===n)throw new r("Cannot parse selected facets from window.location. Please add a 'map' querystring to the page");if(n.length>s.length)throw new r(`Invalid map querystring. There are more map params than segments on the path: (map: ${n.join(",")}, pathname: ${e}). `);const c=n.length,i=s.length-c;let l=o({base:"/"+s.slice(0,i).join("/")});for(let e=0;e<c;e++){const t=n[e],a=s[e+i],r="sort"===t?{type:"setSort",payload:a}:"term"===t?{type:"setTerm",payload:a}:"page"===t?{type:"setPage",payload:Number(a)}:{type:"setFacet",payload:{facet:{key:t,value:a},unique:!1}};l=d(l,r)}return l},exports.sendAnalyticsEvent=e=>{try{window.postMessage((e=>({type:"AnalyticsEvent",data:{...e,type:"store:"+e.type}}))(e),window.origin)}catch(e){console.error(e)}},exports.useAnalyticsEvent=e=>{const a=t.useCallback(t=>{try{if("AnalyticsEvent"!==t.data.type)return;e({...(a=t.data).data,type:a.data.type.slice("store:".length,a.data.type.length)})}catch(e){console.error("Something went wrong while running Analytics handler")}var a},[e]);t.useEffect(()=>(window.addEventListener("message",a),()=>window.removeEventListener("message",a)),[a])},exports.useCart=()=>{const e=y(P),s=a.useContext(M);return t.useMemo(()=>({...e,isValidating:Boolean(s)}),[e,s])},exports.useGlobalUIState=()=>y(v),exports.usePagination=e=>{const{pages:a,itemsPerPage:s,state:r}=h(),n=Math.ceil(e/s),o=Number(a[a.length-1])+1,c=a[0]-1;return t.useMemo(()=>({next:o<n&&{cursor:o,link:g({...r,page:o})},prev:c>-1&&{cursor:c,link:g({...r,page:c})}}),[o,c,r,n])},exports.useSearch=h,exports.useSession=()=>y(C),exports.useStorage=x; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),a=(e=t)&&"object"==typeof e&&"default"in e?e.default:e,s=require("idb-keyval");class r extends Error{constructor(e){super("[sdk]: "+e)}}const n=new Set(["price_desc","price_asc","orders_desc","name_desc","name_asc","release_desc","discount_desc","score_desc"]),o=({sort:e="score_desc",selectedFacets:t=[],term:a=null,base:s="/",page:r=0}={})=>({sort:e,selectedFacets:t,term:a,base:s.endsWith("/")?s:s+"/",page:r}),c=(e,t)=>{const{value:a}=t,s=e.selectedFacets.findIndex(e=>e.value===a);if(s<0)throw new r(`Cannot remove ${a} from search params`);return{...e,selectedFacets:e.selectedFacets.filter((e,t)=>0===t||t!==s)}},i=(e,t,a)=>{if(!0===a){const a=e.selectedFacets.findIndex(e=>e.key===t.key);if(a>-1)return{...e,selectedFacets:e.selectedFacets.map((e,s)=>s===a?t:e)}}return{...e,selectedFacets:[...e.selectedFacets,t]}},l=(e,t)=>void 0!==e.selectedFacets.find(e=>e.key===t.key&&e.value===t.value)?c(e,t):i(e,t,!1),d=(e,t)=>{switch(t.type){case"setSort":if(!n.has(t.payload))throw new r(`Sort param ${t.payload} is unknown`);return e.sort===t.payload?e:{...e,sort:t.payload};case"setTerm":return e.term===t.payload?e:{...e,term:t.payload};case"setPage":return e.page===t.payload?e:{...e,page:t.payload};case"setFacet":return i(e,t.payload.facet,t.payload.unique);case"removeFacet":return c(e,t.payload);case"toggleFacet":return l(e,t.payload);case"toggleFacets":return((e,t)=>t.reduce((e,t)=>l(e,t),e))(e,t.payload);default:throw new r("Uknown action of search state machine")}},u=e=>{const t=new URL(e.base,"http://localhost"),{page:a,selectedFacets:s,sort:r,term:n}=e;null!==n&&t.searchParams.set("q",n);const o=new Set;for(const e of s)t.searchParams.append(e.key,e.value),o.add(e.key);return s.length>0&&t.searchParams.set("facets",Array.from(o).join(",")),t.searchParams.set("sort",r),t.searchParams.set("page",a.toString()),t},p=(e,t)=>{switch(t.type){case"addPrev":return[e[0]-1,...e];case"addNext":const t=Number(e[e.length-1])+1;return[...e,t];default:throw new r("Unknown action for infinite search")}},m=t.createContext(void 0),y=e=>{var a;const s=t.useContext(e);if(void 0!==s)return s;throw new r((null!=(a=e.displayName)?a:"Context")+" needs to be on the React tree")},h=()=>y(m),g=e=>{const{pathname:t,search:a}=u(e);return`${t}${a}`},v=t.createContext(void 0);v.displayName="UIContext";const f={displayMinicart:!1},w=()=>({}),x=(e,a)=>{const[r,n]=t.useState(()=>{return{payload:(e=a,"function"==typeof e?a():a),state:"initial"};var e});return t.useEffect(()=>{let t=!1;return(async()=>{if("initial"===r.state){var a;const o=null!=(a=await(async e=>{try{const t=await s.get(e);return null!=t?t:null}catch(e){return null}})(e))?a:r.payload;t||n({payload:o,state:"hydrated"})}else t||(async(e,t)=>{try{await s.set(e,t)}catch(e){}})(e,r.payload)})(),()=>{t=!0}},[r.payload,r.state,e]),t.useMemo(()=>[r.payload,e=>n({state:"hydrated",payload:e})],[r.payload])},C=t.createContext(void 0);C.displayName="StoreSessionContext";const P={currency:{code:"USD",symbol:"$"},country:"USA",locale:"en",postalCode:null,channel:null,user:null},S=t.createContext(void 0);S.displayName="StoreCartContext";const E={id:"",items:{}},F=(e,t,a)=>({...e,items:{...e.items,[t]:a}}),I=({children:e,onItemAdd:s,initialCart:n,onItemRemove:o,onItemUpdate:c,namespace:i="main"})=>{const l=i+"::store::cart",[d,u]=x(l,{...E,...n}),p=t.useMemo(()=>{const e=Object.values(d.items);return{...d,setCart:e=>{const t={...e,items:e.items.reduce((e,t)=>(e[t.id]=t,e),{})};u(t)},addItem:e=>{if(!e.id)throw new r("You must provide an `id` for items");if(e.quantity<0)throw new r("Item quantity needs to be higher than zero");const t=d.items[e.id],a=t?{...e,quantity:t.quantity+e.quantity}:e,n=t?c:s;u(F(d,a.id,a)),null==n||n(a,t)},updateItemQuantity:(e,t)=>{const a=d.items[e];if(!a)throw new r("Item with id not found: "+e);const s={...a,quantity:t};u(F(d,e,s)),null==c||c(s,a)},removeItem:e=>{const t=d.items[e];u(((e,t)=>{const{[t]:a,...s}=e.items;return{...e,items:s}})(d,e)),null==o||o(t)},emptyCart:()=>u({...d,items:{}}),getItem:e=>d.items[e],inCart:e=>Boolean(d.items[e]),items:e,isEmpty:0===e.length}},[d,s,o,c,u]);return a.createElement(S.Provider,{value:p},e)},M=t.createContext(void 0);M.displayName="StoreCartValidatorContext";const N=async()=>null;let _=Promise.resolve();const b=({children:e,onValidateCart:s=N})=>{const{items:r,id:n,setCart:o}=y(S),c=t.useMemo(()=>({id:n,items:r}),[n,r]),[i,l]=t.useState(!1);return t.useEffect(()=>{let e=!1;return _=_.then(async()=>{if(e)return;l(!0);const t=await s(c);e||(l(!1),null!=t&&o(t))}),()=>{e=!0}},[c,s,o]),a.createElement(M.Provider,{value:i},e)};exports.ANALYTICS_EVENT_TYPE="AnalyticsEvent",exports.CartProvider=({mode:e="pure",onValidateCart:t,children:s,...r})=>a.createElement(I,Object.assign({},r),"optimistic"===e?a.createElement(b,{onValidateCart:t},s):s),exports.STORE_EVENT_PREFIX="store:",exports.SearchProvider=({children:e,itemsPerPage:s,onChange:r,...n})=>{const{state:c,...i}=((e,a)=>{const s=t.useMemo(()=>o(e),[e]);return t.useMemo(()=>{const e=((e,t)=>a=>{const s=d(t,a);var r;r=t,u(s).href!==u(r).href&&e(u(s))})(a,s);return{state:s,setSort:t=>e({type:"setSort",payload:t}),setTerm:t=>e({type:"setTerm",payload:t}),setPage:t=>e({type:"setPage",payload:t}),setFacet:(t,a=!1)=>e({type:"setFacet",payload:{facet:t,unique:a}}),removeFacet:t=>e({type:"removeFacet",payload:t}),toggleFacet:t=>e({type:"toggleFacet",payload:t}),toggleFacets:t=>e({type:"toggleFacets",payload:t})}},[a,s])})(n,r),{pages:l,...y}=(e=>{const[a,s]=t.useReducer(p,e,()=>[e]);return{pages:a,...t.useMemo(()=>({addPrevPage:()=>s({type:"addPrev"}),addNextPage:()=>s({type:"addNext"})}),[])}})(c.page),h=t.useMemo(()=>({state:c,...i,pages:l,...y,itemsPerPage:s}),[y,s,l,i,c]);return a.createElement(m.Provider,{value:h},e)},exports.SessionContext=C,exports.SessionProvider=({children:e,initialState:s,namespace:r="main"})=>{const[n,o]=x(r+"::store::session",()=>({...P,...s})),c=t.useMemo(()=>({...n,setSession:e=>o({...n,...e})}),[n,o]);return a.createElement(C.Provider,{value:c},e)},exports.UIContext=v,exports.UIProvider=({children:e,actions:s={},effects:r=w,initialState:n={}})=>{const[o,c]=t.useReducer((e=>{const t={OPEN_MINICART:e=>({...e,displayMinicart:!0}),CLOSE_MINICART:e=>({...e,displayMinicart:!1}),...e};return(e,{type:a,data:s})=>{const r=t[a];if("function"==typeof r)return r(e,s);throw new Error("Unknown UI state")}})(s),{...f,...n}),i=t.useMemo(()=>({...r(c),openMinicart:()=>c({type:"OPEN_MINICART"}),closeMinicart:()=>c({type:"CLOSE_MINICART"})}),[r]),l=t.useMemo(()=>({...o,...i}),[i,o]);return a.createElement(v.Provider,{value:l},e)},exports.formatSearchState=u,exports.initSearchState=o,exports.parseSearchState=({pathname:e,searchParams:t})=>{var a,s,r,n,c;let i=o({base:e,term:null!=(a=t.get("q"))?a:null,sort:null!=(s=t.get("sort"))?s:void 0,page:Number(null!=(r=t.get("page"))?r:0)});const l=null!=(n=null==(c=t.get("facets"))?void 0:c.split(","))?n:[];for(const e of l){const a=t.getAll(e);for(const t of a)i=d(i,{type:"setFacet",payload:{facet:{key:e,value:t},unique:!1}})}return i},exports.sendAnalyticsEvent=e=>{try{window.postMessage((e=>({type:"AnalyticsEvent",data:{...e,type:"store:"+e.type}}))(e),window.origin)}catch(e){console.error(e)}},exports.useAnalyticsEvent=e=>{const a=t.useCallback(t=>{try{if("AnalyticsEvent"!==t.data.type)return;e({...(a=t.data).data,type:a.data.type.slice("store:".length,a.data.type.length)})}catch(e){console.error("Something went wrong while running Analytics handler")}var a},[e]);t.useEffect(()=>(window.addEventListener("message",a),()=>window.removeEventListener("message",a)),[a])},exports.useCart=()=>{const e=y(S),s=a.useContext(M);return t.useMemo(()=>({...e,isValidating:Boolean(s)}),[e,s])},exports.useGlobalUIState=()=>y(v),exports.usePagination=e=>{const{pages:a,itemsPerPage:s,state:r}=h(),n=Math.ceil(e/s),o=Number(a[a.length-1])+1,c=a[0]-1;return t.useMemo(()=>({next:o<n&&{cursor:o,link:g({...r,page:o})},prev:c>-1&&{cursor:c,link:g({...r,page:c})}}),[o,c,r,n])},exports.useSearch=h,exports.useSession=()=>y(C),exports.useStorage=x; | ||
//# sourceMappingURL=sdk.cjs.production.min.js.map |
@@ -72,2 +72,4 @@ import React, { useCallback, useEffect, useMemo, useReducer, createContext, useContext as useContext$1, useState } from 'react'; | ||
const equals = (s1, s2) => format(s1).href === format(s2).href; | ||
const removeFacet = (state, facet) => { | ||
@@ -158,64 +160,78 @@ const { | ||
}; | ||
const useSearchState = initialState => { | ||
const [state, dispatch] = useReducer(reducer, initialState, initialize); | ||
return useMemo(() => ({ | ||
state, | ||
setSort: sort => dispatch({ | ||
type: 'setSort', | ||
payload: sort | ||
}), | ||
setTerm: term => dispatch({ | ||
type: 'setTerm', | ||
payload: term | ||
}), | ||
setPage: page => dispatch({ | ||
type: 'setPage', | ||
payload: page | ||
}), | ||
setFacet: (facet, unique = false) => dispatch({ | ||
type: 'setFacet', | ||
payload: { | ||
facet, | ||
unique | ||
} | ||
}), | ||
removeFacet: facet => dispatch({ | ||
type: 'removeFacet', | ||
payload: facet | ||
}), | ||
toggleFacet: facet => dispatch({ | ||
type: 'toggleFacet', | ||
payload: facet | ||
}), | ||
toggleFacets: facets => dispatch({ | ||
type: 'toggleFacets', | ||
payload: facets | ||
}) | ||
}), [state]); | ||
const dispatcher = (onChange, state) => action => { | ||
const newState = reducer(state, action); | ||
if (!equals(newState, state)) { | ||
onChange(format(newState)); | ||
} | ||
}; | ||
const useSearchState = (initialState, onChange) => { | ||
const state = useMemo(() => initialize(initialState), [initialState]); | ||
return useMemo(() => { | ||
const dispatch = dispatcher(onChange, state); | ||
return { | ||
state, | ||
setSort: sort => dispatch({ | ||
type: 'setSort', | ||
payload: sort | ||
}), | ||
setTerm: term => dispatch({ | ||
type: 'setTerm', | ||
payload: term | ||
}), | ||
setPage: page => dispatch({ | ||
type: 'setPage', | ||
payload: page | ||
}), | ||
setFacet: (facet, unique = false) => dispatch({ | ||
type: 'setFacet', | ||
payload: { | ||
facet, | ||
unique | ||
} | ||
}), | ||
removeFacet: facet => dispatch({ | ||
type: 'removeFacet', | ||
payload: facet | ||
}), | ||
toggleFacet: facet => dispatch({ | ||
type: 'toggleFacet', | ||
payload: facet | ||
}), | ||
toggleFacets: facets => dispatch({ | ||
type: 'toggleFacets', | ||
payload: facets | ||
}) | ||
}; | ||
}, [onChange, state]); | ||
}; | ||
const format = params => { | ||
const map = []; | ||
const query = []; | ||
const url = new URL(params.base, 'http://localhost'); | ||
const { | ||
page, | ||
selectedFacets, | ||
sort, | ||
term | ||
} = params; | ||
if (params.term !== null) { | ||
map.push('term'); | ||
query.push(params.term); | ||
if (term !== null) { | ||
url.searchParams.set('q', term); | ||
} | ||
for (const facet of params.selectedFacets) { | ||
map.push(facet.key); | ||
query.push(facet.value); | ||
const facets = new Set(); | ||
for (const facet of selectedFacets) { | ||
url.searchParams.append(facet.key, facet.value); | ||
facets.add(facet.key); | ||
} | ||
map.push('sort'); | ||
query.push(params.sort); | ||
if (typeof params.page === 'number') { | ||
map.push('page'); | ||
query.push(params.page.toString()); | ||
if (selectedFacets.length > 0) { | ||
url.searchParams.set('facets', Array.from(facets).join(',')); | ||
} | ||
const url = new URL(`${params.base}${query.join('/')}`, 'http://localhost'); | ||
url.searchParams.set('map', map.join(',')); | ||
url.searchParams.set('sort', sort); | ||
url.searchParams.set('page', page.toString()); | ||
return url; | ||
@@ -227,44 +243,27 @@ }; | ||
}) => { | ||
var _searchParams$get; | ||
var _searchParams$get, _searchParams$get2, _searchParams$get3, _searchParams$get$spl, _searchParams$get4; | ||
const spath = pathname.split('/').slice(1); | ||
const smap = (_searchParams$get = searchParams.get('map')) == null ? void 0 : _searchParams$get.split(','); | ||
if (smap === undefined) { | ||
throw new SDKError(`Cannot parse selected facets from window.location. Please add a 'map' querystring to the page`); | ||
} | ||
if (smap.length > spath.length) { | ||
throw new SDKError(`Invalid map querystring. There are more map params than segments on the path: (map: ${smap.join(',')}, pathname: ${pathname}). `); | ||
} | ||
const nfacets = smap.length; | ||
const offset = spath.length - nfacets; | ||
let state = initialize({ | ||
base: `/${spath.slice(0, offset).join('/')}` | ||
base: pathname, | ||
term: (_searchParams$get = searchParams.get('q')) != null ? _searchParams$get : null, | ||
sort: (_searchParams$get2 = searchParams.get('sort')) != null ? _searchParams$get2 : undefined, | ||
page: Number((_searchParams$get3 = searchParams.get('page')) != null ? _searchParams$get3 : 0) | ||
}); | ||
const facets = (_searchParams$get$spl = (_searchParams$get4 = searchParams.get('facets')) == null ? void 0 : _searchParams$get4.split(',')) != null ? _searchParams$get$spl : []; | ||
for (let it = 0; it < nfacets; it++) { | ||
const key = smap[it]; | ||
const value = spath[it + offset]; | ||
const action = key === 'sort' ? { | ||
type: 'setSort', | ||
payload: value | ||
} : key === 'term' ? { | ||
type: 'setTerm', | ||
payload: value | ||
} : key === 'page' ? { | ||
type: 'setPage', | ||
payload: Number(value) | ||
} : { | ||
type: 'setFacet', | ||
payload: { | ||
facet: { | ||
key, | ||
value | ||
}, | ||
unique: false | ||
} | ||
}; | ||
state = reducer(state, action); | ||
for (const facet of facets) { | ||
const values = searchParams.getAll(facet); | ||
for (const value of values) { | ||
state = reducer(state, { | ||
type: 'setFacet', | ||
payload: { | ||
facet: { | ||
key: facet, | ||
value | ||
}, | ||
unique: false | ||
} | ||
}); | ||
} | ||
} | ||
@@ -294,4 +293,3 @@ | ||
const [pages, dispatch] = useReducer(reducer$1, initialPage, () => [initialPage]); | ||
return useMemo(() => ({ | ||
pages, | ||
const actions = useMemo(() => ({ | ||
addPrevPage: () => dispatch({ | ||
@@ -303,3 +301,7 @@ type: 'addPrev' | ||
}) | ||
}), [pages]); | ||
}), []); | ||
return { | ||
pages, | ||
...actions | ||
}; | ||
}; | ||
@@ -317,3 +319,3 @@ | ||
...searchActions | ||
} = useSearchState(rest); | ||
} = useSearchState(rest, onChange); | ||
const { | ||
@@ -323,5 +325,2 @@ pages, | ||
} = useSearchInfiniteState(state.page); | ||
useEffect(() => { | ||
onChange(format(state)); | ||
}, [onChange, state]); | ||
const value = useMemo(() => ({ | ||
@@ -328,0 +327,0 @@ state, |
export declare const useSearchInfiniteState: (initialPage: number) => { | ||
pages: number[]; | ||
addPrevPage: () => void; | ||
addNextPage: () => void; | ||
pages: number[]; | ||
}; | ||
export declare type UseSearchInfiniteState = ReturnType<typeof useSearchInfiniteState>; |
@@ -58,4 +58,10 @@ export declare type SearchSort = 'price_desc' | 'price_asc' | 'orders_desc' | 'name_desc' | 'name_asc' | 'release_desc' | 'discount_desc' | 'score_desc'; | ||
export declare const reducer: (state: State, action: Action) => State; | ||
export declare const useSearchState: (initialState: Partial<State>) => { | ||
state: State; | ||
export declare const useSearchState: (initialState: Partial<State>, onChange: (url: URL) => void) => { | ||
state: { | ||
sort: SearchSort; | ||
selectedFacets: Facet[]; | ||
term: string | null; | ||
base: string; | ||
page: number; | ||
}; | ||
setSort: (sort: SearchSort) => void; | ||
@@ -62,0 +68,0 @@ setTerm: (term: string | null) => void; |
{ | ||
"name": "@faststore/sdk", | ||
"version": "1.3.11", | ||
"version": "1.3.12", | ||
"description": "Hooks for creating your next component library", | ||
@@ -57,3 +57,3 @@ "license": "MIT", | ||
}, | ||
"gitHead": "78dbef94bcf54ce137dc364d1b66ec9423bb55bd" | ||
"gitHead": "98754db41816ecaca9f103df86cd085b011b744a" | ||
} |
@@ -1,2 +0,1 @@ | ||
import { SDKError } from '../utils/error' | ||
import { initialize, reducer } from './useSearchState' | ||
@@ -6,27 +5,23 @@ import type { State as SearchState, SearchSort } from './useSearchState' | ||
export const format = (params: SearchState): URL => { | ||
const map: string[] = [] | ||
const query: string[] = [] | ||
const url = new URL(params.base, 'http://localhost') | ||
const { page, selectedFacets, sort, term } = params | ||
if (params.term !== null) { | ||
map.push('term') | ||
query.push(params.term) | ||
if (term !== null) { | ||
url.searchParams.set('q', term) | ||
} | ||
for (const facet of params.selectedFacets) { | ||
map.push(facet.key) | ||
query.push(facet.value) | ||
const facets = new Set<string>() | ||
for (const facet of selectedFacets) { | ||
url.searchParams.append(facet.key, facet.value) | ||
facets.add(facet.key) | ||
} | ||
map.push('sort') | ||
query.push(params.sort) | ||
if (typeof params.page === 'number') { | ||
map.push('page') | ||
query.push(params.page.toString()) | ||
if (selectedFacets.length > 0) { | ||
url.searchParams.set('facets', Array.from(facets).join(',')) | ||
} | ||
const url = new URL(`${params.base}${query.join('/')}`, 'http://localhost') | ||
url.searchParams.set('sort', sort) | ||
url.searchParams.set('page', page.toString()) | ||
url.searchParams.set('map', map.join(',')) | ||
return url | ||
@@ -36,50 +31,20 @@ } | ||
export const parse = ({ pathname, searchParams }: URL): SearchState => { | ||
const spath = pathname.split('/').slice(1) | ||
const smap = searchParams.get('map')?.split(',') | ||
if (smap === undefined) { | ||
throw new SDKError( | ||
`Cannot parse selected facets from window.location. Please add a 'map' querystring to the page` | ||
) | ||
} | ||
if (smap.length > spath.length) { | ||
throw new SDKError( | ||
`Invalid map querystring. There are more map params than segments on the path: (map: ${smap.join( | ||
',' | ||
)}, pathname: ${pathname}). ` | ||
) | ||
} | ||
const nfacets = smap.length | ||
const offset = spath.length - nfacets | ||
let state = initialize({ | ||
base: `/${spath.slice(0, offset).join('/')}`, | ||
base: pathname, | ||
term: searchParams.get('q') ?? null, | ||
sort: (searchParams.get('sort') as SearchSort) ?? undefined, | ||
page: Number(searchParams.get('page') ?? 0), | ||
}) | ||
for (let it = 0; it < nfacets; it++) { | ||
const key = smap[it] | ||
const value = spath[it + offset] | ||
const action = | ||
key === 'sort' | ||
? { | ||
type: 'setSort' as const, | ||
payload: value as SearchSort, | ||
} | ||
: key === 'term' | ||
? { | ||
type: 'setTerm' as const, | ||
payload: value, | ||
} | ||
: key === 'page' | ||
? { | ||
type: 'setPage' as const, | ||
payload: Number(value), | ||
} | ||
: { | ||
type: 'setFacet' as const, | ||
payload: { facet: { key, value }, unique: false }, | ||
} | ||
const facets = searchParams.get('facets')?.split(',') ?? [] | ||
state = reducer(state, action) | ||
for (const facet of facets) { | ||
const values = searchParams.getAll(facet) | ||
for (const value of values) { | ||
state = reducer(state, { | ||
type: 'setFacet' as const, | ||
payload: { facet: { key: facet, value }, unique: false }, | ||
}) | ||
} | ||
} | ||
@@ -86,0 +51,0 @@ |
@@ -38,12 +38,13 @@ /* eslint-disable no-case-declarations */ | ||
return useMemo( | ||
const actions = useMemo( | ||
() => ({ | ||
pages, | ||
addPrevPage: () => dispatch({ type: 'addPrev' }), | ||
addNextPage: () => dispatch({ type: 'addNext' }), | ||
}), | ||
[pages] | ||
[] | ||
) | ||
return { pages, ...actions } | ||
} | ||
export type UseSearchInfiniteState = ReturnType<typeof useSearchInfiniteState> |
@@ -1,3 +0,4 @@ | ||
import { useMemo, useReducer } from 'react' | ||
import { useMemo } from 'react' | ||
import { format } from './serializer' | ||
import { SDKError } from '../utils/error' | ||
@@ -96,2 +97,4 @@ | ||
const equals = (s1: State, s2: State) => format(s1).href === format(s2).href | ||
const removeFacet = (state: State, facet: Facet): State => { | ||
@@ -205,7 +208,22 @@ const { value } = facet | ||
export const useSearchState = (initialState: Partial<State>) => { | ||
const [state, dispatch] = useReducer(reducer, initialState, initialize) | ||
const dispatcher = (onChange: (url: URL) => void, state: State) => ( | ||
action: Action | ||
) => { | ||
const newState = reducer(state, action) | ||
return useMemo( | ||
() => ({ | ||
if (!equals(newState, state)) { | ||
onChange(format(newState)) | ||
} | ||
} | ||
export const useSearchState = ( | ||
initialState: Partial<State>, | ||
onChange: (url: URL) => void | ||
) => { | ||
const state = useMemo(() => initialize(initialState), [initialState]) | ||
return useMemo(() => { | ||
const dispatch = dispatcher(onChange, state) | ||
return { | ||
state, | ||
@@ -228,7 +246,6 @@ setSort: (sort: SearchSort) => | ||
dispatch({ type: 'toggleFacets', payload: facets }), | ||
}), | ||
[state] | ||
) | ||
} | ||
}, [onChange, state]) | ||
} | ||
export type UseSearchState = ReturnType<typeof useSearchState> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
276505
3589