dinocollab-core 2.0.9 → 2.0.11

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,2 +1,2 @@
1
- import{slicedToArray as r,toConsumableArray as t}from"../_virtual/_rollupPluginBabelHelpers.js";import{useMemo as i,useState as e,useRef as n,useEffect as o,useCallback as a}from"react";import{mfeBridge as u}from"./mfe-bridge.js";import{isBrowser as s}from"./environment.js";import{CART_CHANNELS as l}from"./cart.types.js";var c="mfe_cart_items";function f(a){var f=i((function(){return(null==a?void 0:a.storageKey)||c}),[null==a?void 0:a.storageKey]),g=i((function(){return a.idGetter}),[null==a?void 0:a.idGetter]),S=e([]),m=r(S,2),N=m[0],b=m[1],E=n(!1);return o((function(){if(s()){var r=localStorage.getItem(f);if(r)try{var i=JSON.parse(r);Array.isArray(i)&&(b(i),E.current=!0)}catch(r){console.error("Failed to parse cart from localStorage:",r)}var e=u.subscribe(l.ADD,(function(r){b((function(i){var e,n=g(r),o=i.findIndex((function(r){return g(r)===n}));if(o>=0?(e=t(i))[o]=r:e=[].concat(t(i),[r]),JSON.stringify(e)!==JSON.stringify(i)){if(s()){var a=localStorage.getItem(f);JSON.stringify(e)!==a&&localStorage.setItem(f,JSON.stringify(e))}return u.publish(l.STATE_CHANGE,e),e}return i}))})),n=u.subscribe(l.REMOVE,(function(r){b((function(t){var i=t.filter((function(t){return g(t)!==r.id}));if(JSON.stringify(i)!==JSON.stringify(t)){if(s()){var e=localStorage.getItem(f);JSON.stringify(i)!==e&&localStorage.setItem(f,JSON.stringify(i))}return u.publish(l.STATE_CHANGE,i),i}return t}))})),o=u.subscribe(l.CLEAR,(function(){b([]),s()&&localStorage.removeItem(f),u.publish(l.STATE_CHANGE,[])})),a=u.subscribe(l.UPDATE,(function(r){b((function(t){if(JSON.stringify(r)!==JSON.stringify(t)){if(s()){var i=localStorage.getItem(f);JSON.stringify(r)!==i&&localStorage.setItem(f,JSON.stringify(r))}return u.publish(l.STATE_CHANGE,r),r}return t}))})),c=u.subscribe(l.INIT_REQUEST,(function(){b((function(r){return r.length>0&&u.publish(l.INIT_RESPONSE,r),r}))})),S=u.subscribe(l.INIT_RESPONSE,(function(r){!E.current&&r&&r.length>0&&b((function(t){if(JSON.stringify(r)!==JSON.stringify(t)){if(s()){var i=localStorage.getItem(f);JSON.stringify(r)!==i&&localStorage.setItem(f,JSON.stringify(r))}return E.current=!0,u.publish(l.STATE_CHANGE,r),r}return t}))}));return E.current||u.publish(l.INIT_REQUEST,null),function(){e(),n(),o(),a(),c(),S()}}}),[f,g]),{items:N,totalItems:N.length}}function g(t){var i=e([]),n=r(i,2),a=n[0],f=n[1],g=t||c;return o((function(){if(s()){var r=localStorage.getItem(g);if(r)try{var t=JSON.parse(r);Array.isArray(t)&&f(t)}catch(r){console.error("Failed to parse cart from localStorage:",r)}var i=u.subscribe(l.STATE_CHANGE,(function(r){f(r||[])}));return function(){i()}}}),[g]),{items:a,totalItems:a.length}}function S(){return{addToCart:a((function(r){u.publish(l.ADD,r)}),[]),removeFromCart:a((function(r){u.publish(l.REMOVE,{id:r})}),[]),clearCart:a((function(){u.publish(l.CLEAR,null)}),[]),updateCart:a((function(r){u.publish(l.UPDATE,r)}),[])}}export{S as useMfeCartActions,g as useMfeCartData,f as useMfeCartStore};
1
+ import{slicedToArray as t,toConsumableArray as r}from"../_virtual/_rollupPluginBabelHelpers.js";import{useMemo as n,useState as i,useRef as e,useCallback as u,useEffect as f}from"react";import{mfeBridge as s}from"./mfe-bridge.js";import{isBrowser as o}from"./environment.js";import{CART_CHANNELS as a}from"./cart.types.js";import{CART_STORAGE_KEY as c,MfeCartStorage as l}from"./cart.local-storage.js";function g(g){var E=(null==g?void 0:g.storageKey)||c,b=n((function(){return new l(E)}),[E]),N=n((function(){return g.idGetter}),[null==g?void 0:g.idGetter]),S=i([]),p=t(S,2),v=p[0],m=p[1],y=e(!1),O=e(!1),D=u((function(t){O.current&&s.publish(a.STATE_CHANGE,t)}),[]);return f((function(){if(o()){var t=b.getData();t&&t.length>0&&(m(t),y.current=!0,O.current=!0);var n=s.subscribe(a.ADD,(function(t){m((function(n){var i,e=N(t),u=n.findIndex((function(t){return N(t)===e}));if(u>=0?(i=r(n))[u]=t:i=[].concat(r(n),[t]),JSON.stringify(i)!==JSON.stringify(n)){if(o()){var f=b.getData();JSON.stringify(i)!==JSON.stringify(f)&&b.setData(i,{skipEvent:!0})}return D(i),i}return n}))})),i=s.subscribe(a.REMOVE,(function(t){m((function(r){var n=r.filter((function(r){return N(r)!==t.id}));if(JSON.stringify(n)!==JSON.stringify(r)){if(o()){var i=b.getData();JSON.stringify(n)!==JSON.stringify(i)&&b.setData(n,{skipEvent:!0})}return D(n),n}return r}))})),e=s.subscribe(a.CLEAR,(function(){m([]),o()&&b.removeAll({skipEvent:!0}),D([])})),u=s.subscribe(a.UPDATE,(function(t){m((function(r){if(JSON.stringify(t)!==JSON.stringify(r)){if(o()){var n=b.getData();JSON.stringify(t)!==JSON.stringify(n)&&b.setData(t,{skipEvent:!0})}return D(t),t}return r}))})),f=s.subscribe(a.INIT_REQUEST,(function(){m((function(t){return t.length>0&&s.publish(a.INIT_RESPONSE,t),t}))})),c=s.subscribe(a.INIT_RESPONSE,(function(t){!y.current&&t&&t.length>0&&m((function(r){if(JSON.stringify(t)!==JSON.stringify(r)){if(o()){var n=b.getData();JSON.stringify(t)!==JSON.stringify(n)&&b.setData(t,{skipEvent:!0})}return y.current=!0,O.current=!0,D(t),t}return r}))}));return y.current?O.current=!0:s.publish(a.INIT_REQUEST,null),function(){n(),i(),e(),u(),f(),c()}}}),[E,N,D,b]),{items:v,totalItems:v.length}}function E(r){var e=i([]),u=t(e,2),g=u[0],E=u[1],b=r||c,N=n((function(){return new l(b)}),[b]);return f((function(){if(o()){var t=N.getData();t&&t.length>0&&E(t);var r=s.subscribe(a.STATE_CHANGE,(function(t){E(t||[])}));return function(){r()}}}),[b,N]),{items:g,totalItems:g.length}}function b(){return{addToCart:u((function(t){s.publish(a.ADD,t)}),[]),removeFromCart:u((function(t){s.publish(a.REMOVE,{id:t})}),[]),clearCart:u((function(){s.publish(a.CLEAR,null)}),[]),updateCart:u((function(t){s.publish(a.UPDATE,t)}),[])}}export{b as useMfeCartActions,E as useMfeCartData,g as useMfeCartStore};
2
2
  //# sourceMappingURL=cart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cart.js","sources":["../../src/mfe-shared/cart.tsx"],"sourcesContent":["/**\r\n * cart.tsx - Shared shopping cart system for micro-frontends\r\n *\r\n * This module provides hooks for managing a shared shopping cart across\r\n * multiple micro-frontends. The cart state is synchronized using the\r\n * mfeBridge communication system and persisted in localStorage.\r\n */\r\n\r\nimport { useEffect, useState, useRef, useCallback, useMemo } from 'react'\r\nimport { mfeBridge } from './mfe-bridge'\r\nimport { isBrowser } from './environment'\r\nimport { CART_CHANNELS } from './cart.types'\r\n\r\n/** LocalStorage key for persisting cart items */\r\nconst CART_STORAGE_KEY = 'mfe_cart_items'\r\n\r\nexport interface IMfeCartStoreConfigs<T = any> {\r\n storageKey?: string\r\n idGetter: (item: T) => string\r\n}\r\n\r\n/**\r\n * Hook to manage cart state across microFE\r\n * This hook will:\r\n * - Initialize cart from localStorage\r\n * - Listen for cart events (add, remove, clear, update)\r\n * - Provide current cart state\r\n */\r\nexport function useMfeCartStore<T = any>(configs: IMfeCartStoreConfigs<T>) {\r\n // Use provided storage key or default to CART_STORAGE_KEY\r\n const cartStorageKey = useMemo(() => configs?.storageKey || CART_STORAGE_KEY, [configs?.storageKey])\r\n\r\n // Default idGetter uses ProductId, but can be customized\r\n const getItemId = useMemo(() => configs.idGetter, [configs?.idGetter])\r\n\r\n // State to hold cart items\r\n const [items, setItems] = useState<T[]>([])\r\n\r\n // Mark as initialized\r\n const initialized = useRef(false)\r\n\r\n useEffect(() => {\r\n // Skip localStorage operations in non-browser environments\r\n if (!isBrowser()) {\r\n return\r\n }\r\n\r\n // Restore from localStorage if available\r\n const storedItems = localStorage.getItem(cartStorageKey)\r\n if (storedItems) {\r\n try {\r\n const parsedItems = JSON.parse(storedItems)\r\n if (Array.isArray(parsedItems)) {\r\n setItems(parsedItems)\r\n initialized.current = true\r\n }\r\n } catch (e) {\r\n console.error('Failed to parse cart from localStorage:', e)\r\n }\r\n }\r\n\r\n // Subscribe to cart events\r\n const unsubAdd = mfeBridge.subscribe(CART_CHANNELS.ADD, (payload: T) => {\r\n setItems((prev) => {\r\n const itemId = getItemId(payload)\r\n const existingIndex = prev.findIndex((item) => getItemId(item) === itemId)\r\n\r\n let newItems: T[]\r\n if (existingIndex >= 0) {\r\n // Update existing item\r\n newItems = [...prev]\r\n newItems[existingIndex] = payload\r\n } else {\r\n // Add new item\r\n newItems = [...prev, payload]\r\n }\r\n\r\n if (JSON.stringify(newItems) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = localStorage.getItem(cartStorageKey)\r\n if (JSON.stringify(newItems) !== current) {\r\n localStorage.setItem(cartStorageKey, JSON.stringify(newItems))\r\n }\r\n }\r\n // Notify state change\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, newItems)\r\n return newItems\r\n }\r\n return prev\r\n })\r\n })\r\n\r\n const unsubRemove = mfeBridge.subscribe(CART_CHANNELS.REMOVE, (payload: { id: string }) => {\r\n setItems((prev) => {\r\n const newItems = prev.filter((item) => getItemId(item) !== payload.id)\r\n if (JSON.stringify(newItems) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = localStorage.getItem(cartStorageKey)\r\n if (JSON.stringify(newItems) !== current) {\r\n localStorage.setItem(cartStorageKey, JSON.stringify(newItems))\r\n }\r\n }\r\n // Notify state change\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, newItems)\r\n return newItems\r\n }\r\n return prev\r\n })\r\n })\r\n\r\n const unsubClear = mfeBridge.subscribe(CART_CHANNELS.CLEAR, () => {\r\n setItems([])\r\n if (isBrowser()) {\r\n localStorage.removeItem(cartStorageKey)\r\n }\r\n // Notify state change\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, [])\r\n })\r\n\r\n const unsubUpdate = mfeBridge.subscribe(CART_CHANNELS.UPDATE, (payload: T[]) => {\r\n setItems((prev) => {\r\n if (JSON.stringify(payload) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = localStorage.getItem(cartStorageKey)\r\n if (JSON.stringify(payload) !== current) {\r\n localStorage.setItem(cartStorageKey, JSON.stringify(payload))\r\n }\r\n }\r\n // Notify state change\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, payload)\r\n return payload\r\n }\r\n return prev\r\n })\r\n })\r\n\r\n // Subscribe to init requests from other microFEs\r\n const unsubInitReq = mfeBridge.subscribe(CART_CHANNELS.INIT_REQUEST, () => {\r\n // Use callback to get current state to avoid stale closure\r\n setItems((currentItems) => {\r\n if (currentItems.length > 0) {\r\n mfeBridge.publish(CART_CHANNELS.INIT_RESPONSE, currentItems)\r\n }\r\n return currentItems // No change to state\r\n })\r\n })\r\n\r\n // Subscribe to init responses if state is not available\r\n const unsubInitRes = mfeBridge.subscribe(CART_CHANNELS.INIT_RESPONSE, (payload: T[]) => {\r\n if (!initialized.current && payload && payload.length > 0) {\r\n setItems((prev) => {\r\n if (JSON.stringify(payload) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = localStorage.getItem(cartStorageKey)\r\n if (JSON.stringify(payload) !== current) {\r\n localStorage.setItem(cartStorageKey, JSON.stringify(payload))\r\n }\r\n }\r\n initialized.current = true\r\n // Notify state change\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, payload)\r\n return payload\r\n }\r\n return prev\r\n })\r\n }\r\n })\r\n\r\n // When mounted, send init request (only if no state from localStorage)\r\n if (!initialized.current) {\r\n mfeBridge.publish(CART_CHANNELS.INIT_REQUEST, null)\r\n }\r\n\r\n return () => {\r\n unsubAdd()\r\n unsubRemove()\r\n unsubClear()\r\n unsubUpdate()\r\n unsubInitReq()\r\n unsubInitRes()\r\n }\r\n }, [cartStorageKey, getItemId])\r\n\r\n return { items, totalItems: items.length }\r\n}\r\n\r\n/**\r\n * Simple hook to read cart data without configuration\r\n * Use this when you only need to display cart data and don't need to manage state\r\n * This hook synchronizes with the main cart store through STATE_CHANGE events\r\n */\r\nexport function useMfeCartData<T = any>(storageKey?: string) {\r\n const [items, setItems] = useState<T[]>([])\r\n const cartStorageKey = storageKey || CART_STORAGE_KEY\r\n\r\n useEffect(() => {\r\n // Skip localStorage operations in non-browser environments\r\n if (!isBrowser()) {\r\n return\r\n }\r\n\r\n // Load initial data from localStorage\r\n const storedItems = localStorage.getItem(cartStorageKey)\r\n if (storedItems) {\r\n try {\r\n const parsedItems = JSON.parse(storedItems)\r\n if (Array.isArray(parsedItems)) {\r\n setItems(parsedItems)\r\n }\r\n } catch (e) {\r\n console.error('Failed to parse cart from localStorage:', e)\r\n }\r\n }\r\n\r\n // Simply listen to STATE_CHANGE events from the main store\r\n const unsubStateChange = mfeBridge.subscribe(CART_CHANNELS.STATE_CHANGE, (payload: T[]) => {\r\n setItems(payload || [])\r\n })\r\n\r\n return () => {\r\n unsubStateChange()\r\n }\r\n }, [cartStorageKey])\r\n\r\n return { items, totalItems: items.length }\r\n}\r\n\r\n/**\r\n * Hook to provide cart actions\r\n * This hook will:\r\n * - Only perform actions, not manage state\r\n * - Use mfeEventBridge to communicate with other microFEs\r\n * - Provide add, remove, clear, and update actions\r\n */\r\nexport function useMfeCartActions<T = any>() {\r\n // Add item to cart\r\n const addToCart = useCallback((item: T) => {\r\n mfeBridge.publish(CART_CHANNELS.ADD, item)\r\n }, [])\r\n\r\n // Remove item from cart\r\n const removeFromCart = useCallback((id: string) => {\r\n mfeBridge.publish(CART_CHANNELS.REMOVE, { id })\r\n }, [])\r\n\r\n // Clear cart\r\n const clearCart = useCallback(() => {\r\n mfeBridge.publish(CART_CHANNELS.CLEAR, null)\r\n }, [])\r\n\r\n // Update entire cart\r\n const updateCart = useCallback((items: T[]) => {\r\n mfeBridge.publish(CART_CHANNELS.UPDATE, items)\r\n }, [])\r\n\r\n return {\r\n addToCart,\r\n removeFromCart,\r\n clearCart,\r\n updateCart\r\n }\r\n}\r\n"],"names":["CART_STORAGE_KEY","useMfeCartStore","configs","cartStorageKey","useMemo","storageKey","getItemId","idGetter","_useState","useState","_useState2","_slicedToArray","items","setItems","initialized","useRef","useEffect","isBrowser","storedItems","localStorage","getItem","parsedItems","JSON","parse","Array","isArray","current","e","console","error","unsubAdd","mfeBridge","subscribe","CART_CHANNELS","ADD","payload","prev","newItems","itemId","existingIndex","findIndex","item","_toConsumableArray","concat","stringify","setItem","publish","STATE_CHANGE","unsubRemove","REMOVE","filter","id","unsubClear","CLEAR","removeItem","unsubUpdate","UPDATE","unsubInitReq","INIT_REQUEST","currentItems","length","INIT_RESPONSE","unsubInitRes","totalItems","useMfeCartData","_useState3","_useState4","unsubStateChange","useMfeCartActions","addToCart","useCallback","removeFromCart","clearCart","updateCart"],"mappings":"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"}
1
+ {"version":3,"file":"cart.js","sources":["../../src/mfe-shared/cart.tsx"],"sourcesContent":["/**\r\n * cart.tsx - Shared shopping cart system for micro-frontends\r\n *\r\n * This module provides hooks for managing a shared shopping cart across\r\n * multiple micro-frontends. The cart state is synchronized using the\r\n * mfeBridge communication system and persisted in localStorage.\r\n */\r\n\r\nimport { useEffect, useState, useRef, useCallback, useMemo } from 'react'\r\nimport { mfeBridge } from './mfe-bridge'\r\nimport { isBrowser } from './environment'\r\nimport { CART_CHANNELS } from './cart.types'\r\nimport { MfeCartStorage, CART_STORAGE_KEY } from './cart.local-storage'\r\n\r\nexport interface IMfeCartStoreConfigs<T = any> {\r\n storageKey?: string\r\n idGetter: (item: T) => string\r\n}\r\n\r\n/**\r\n * Hook to manage cart state across microFE\r\n * This hook will:\r\n * - Initialize cart from localStorage\r\n * - Listen for cart events (add, remove, clear, update)\r\n * - Provide current cart state\r\n */\r\nexport function useMfeCartStore<T = any>(configs: IMfeCartStoreConfigs<T>) {\r\n // Use provided storage key or default to CART_STORAGE_KEY\r\n const cartStorageKey = configs?.storageKey || CART_STORAGE_KEY\r\n\r\n // Create CartLocalStorage instance for this storage key\r\n const cartStorage = useMemo(() => new MfeCartStorage<T>(cartStorageKey), [cartStorageKey])\r\n\r\n // Default idGetter uses ProductId, but can be customized\r\n const getItemId = useMemo(() => configs.idGetter, [configs?.idGetter])\r\n\r\n // State to hold cart items\r\n const [items, setItems] = useState<T[]>([])\r\n\r\n // Mark as initialized\r\n const initialized = useRef(false)\r\n\r\n // Ref to track if we're the primary store (to avoid multiple STATE_CHANGE emissions)\r\n const isPrimaryStore = useRef(false)\r\n\r\n // Helper to emit state change only from primary store\r\n const emitStateChange = useCallback((newItems: T[]) => {\r\n if (isPrimaryStore.current) {\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, newItems)\r\n }\r\n }, [])\r\n\r\n useEffect(() => {\r\n // Skip localStorage operations in non-browser environments\r\n if (!isBrowser()) {\r\n return\r\n }\r\n\r\n // Restore from localStorage if available\r\n const storedItems = cartStorage.getData()\r\n if (storedItems && storedItems.length > 0) {\r\n setItems(storedItems)\r\n initialized.current = true\r\n isPrimaryStore.current = true // Mark as primary if we have data\r\n }\r\n\r\n // Subscribe to cart events\r\n const unsubAdd = mfeBridge.subscribe(CART_CHANNELS.ADD, (payload: T) => {\r\n setItems((prev) => {\r\n const itemId = getItemId(payload)\r\n const existingIndex = prev.findIndex((item) => getItemId(item) === itemId)\r\n\r\n let newItems: T[]\r\n if (existingIndex >= 0) {\r\n // Update existing item\r\n newItems = [...prev]\r\n newItems[existingIndex] = payload\r\n } else {\r\n // Add new item\r\n newItems = [...prev, payload]\r\n }\r\n\r\n if (JSON.stringify(newItems) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = cartStorage.getData()\r\n if (JSON.stringify(newItems) !== JSON.stringify(current)) {\r\n // Skip event because we will emit it ourselves\r\n cartStorage.setData(newItems, { skipEvent: true })\r\n }\r\n }\r\n // Emit state change only from primary store\r\n emitStateChange(newItems)\r\n return newItems\r\n }\r\n return prev\r\n })\r\n })\r\n\r\n const unsubRemove = mfeBridge.subscribe(CART_CHANNELS.REMOVE, (payload: { id: string }) => {\r\n setItems((prev) => {\r\n const newItems = prev.filter((item) => getItemId(item) !== payload.id)\r\n if (JSON.stringify(newItems) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = cartStorage.getData()\r\n if (JSON.stringify(newItems) !== JSON.stringify(current)) {\r\n // Skip event because we will emit it ourselves\r\n cartStorage.setData(newItems, { skipEvent: true })\r\n }\r\n }\r\n // Emit state change only from primary store\r\n emitStateChange(newItems)\r\n return newItems\r\n }\r\n return prev\r\n })\r\n })\r\n\r\n const unsubClear = mfeBridge.subscribe(CART_CHANNELS.CLEAR, () => {\r\n setItems([])\r\n if (isBrowser()) {\r\n cartStorage.removeAll({ skipEvent: true })\r\n }\r\n // Emit state change only from primary store\r\n emitStateChange([])\r\n })\r\n\r\n const unsubUpdate = mfeBridge.subscribe(CART_CHANNELS.UPDATE, (payload: T[]) => {\r\n setItems((prev) => {\r\n if (JSON.stringify(payload) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = cartStorage.getData()\r\n if (JSON.stringify(payload) !== JSON.stringify(current)) {\r\n cartStorage.setData(payload, { skipEvent: true })\r\n }\r\n }\r\n // Emit state change only from primary store\r\n emitStateChange(payload)\r\n return payload\r\n }\r\n return prev\r\n })\r\n })\r\n\r\n // Subscribe to init requests from other microFEs\r\n const unsubInitReq = mfeBridge.subscribe(CART_CHANNELS.INIT_REQUEST, () => {\r\n // Use callback to get current state to avoid stale closure\r\n setItems((currentItems) => {\r\n if (currentItems.length > 0) {\r\n mfeBridge.publish(CART_CHANNELS.INIT_RESPONSE, currentItems)\r\n }\r\n return currentItems // No change to state\r\n })\r\n })\r\n\r\n // Subscribe to init responses if state is not available\r\n const unsubInitRes = mfeBridge.subscribe(CART_CHANNELS.INIT_RESPONSE, (payload: T[]) => {\r\n if (!initialized.current && payload && payload.length > 0) {\r\n setItems((prev) => {\r\n if (JSON.stringify(payload) !== JSON.stringify(prev)) {\r\n // Save to localStorage only if value changed\r\n if (isBrowser()) {\r\n const current = cartStorage.getData()\r\n if (JSON.stringify(payload) !== JSON.stringify(current)) {\r\n cartStorage.setData(payload, { skipEvent: true })\r\n }\r\n }\r\n initialized.current = true\r\n isPrimaryStore.current = true // Become primary when receiving init data\r\n // Emit state change only from primary store\r\n emitStateChange(payload)\r\n return payload\r\n }\r\n return prev\r\n })\r\n }\r\n })\r\n\r\n // When mounted, send init request (only if no state from localStorage)\r\n if (!initialized.current) {\r\n mfeBridge.publish(CART_CHANNELS.INIT_REQUEST, null)\r\n } else {\r\n // If we have data, we become the primary store\r\n isPrimaryStore.current = true\r\n }\r\n\r\n return () => {\r\n unsubAdd()\r\n unsubRemove()\r\n unsubClear()\r\n unsubUpdate()\r\n unsubInitReq()\r\n unsubInitRes()\r\n }\r\n }, [cartStorageKey, getItemId, emitStateChange, cartStorage])\r\n\r\n return { items, totalItems: items.length }\r\n}\r\n\r\n/**\r\n * Simple hook to read cart data without configuration\r\n * Use this when you only need to display cart data and don't need to manage state\r\n * This hook synchronizes with the main cart store through STATE_CHANGE events\r\n */\r\nexport function useMfeCartData<T = any>(storageKey?: string) {\r\n const [items, setItems] = useState<T[]>([])\r\n const cartStorageKey = storageKey || CART_STORAGE_KEY\r\n\r\n // Create CartLocalStorage instance for this storage key\r\n const cartStorage = useMemo(() => new MfeCartStorage<T>(cartStorageKey), [cartStorageKey])\r\n\r\n useEffect(() => {\r\n // Skip localStorage operations in non-browser environments\r\n if (!isBrowser()) {\r\n return\r\n }\r\n\r\n // Load initial data from localStorage\r\n const storedItems = cartStorage.getData()\r\n if (storedItems && storedItems.length > 0) {\r\n setItems(storedItems)\r\n }\r\n\r\n // Simply listen to STATE_CHANGE events from the main store\r\n const unsubStateChange = mfeBridge.subscribe(CART_CHANNELS.STATE_CHANGE, (payload: T[]) => {\r\n setItems(payload || [])\r\n })\r\n\r\n return () => {\r\n unsubStateChange()\r\n }\r\n }, [cartStorageKey, cartStorage])\r\n\r\n return { items, totalItems: items.length }\r\n}\r\n\r\n/**\r\n * Hook to provide cart actions\r\n * This hook will:\r\n * - Only perform actions, not manage state\r\n * - Use mfeEventBridge to communicate with other microFEs\r\n * - Provide add, remove, clear, and update actions\r\n */\r\nexport function useMfeCartActions<T = any>() {\r\n // Add item to cart\r\n const addToCart = useCallback((item: T) => {\r\n mfeBridge.publish(CART_CHANNELS.ADD, item)\r\n }, [])\r\n\r\n // Remove item from cart\r\n const removeFromCart = useCallback((id: string) => {\r\n mfeBridge.publish(CART_CHANNELS.REMOVE, { id })\r\n }, [])\r\n\r\n // Clear cart\r\n const clearCart = useCallback(() => {\r\n mfeBridge.publish(CART_CHANNELS.CLEAR, null)\r\n }, [])\r\n\r\n // Update entire cart\r\n const updateCart = useCallback((items: T[]) => {\r\n mfeBridge.publish(CART_CHANNELS.UPDATE, items)\r\n }, [])\r\n\r\n return {\r\n addToCart,\r\n removeFromCart,\r\n clearCart,\r\n updateCart\r\n }\r\n}\r\n"],"names":["useMfeCartStore","configs","cartStorageKey","storageKey","CART_STORAGE_KEY","cartStorage","useMemo","MfeCartStorage","getItemId","idGetter","_useState","useState","_useState2","_slicedToArray","items","setItems","initialized","useRef","isPrimaryStore","emitStateChange","useCallback","newItems","current","mfeBridge","publish","CART_CHANNELS","STATE_CHANGE","useEffect","isBrowser","storedItems","getData","length","unsubAdd","subscribe","ADD","payload","prev","itemId","existingIndex","findIndex","item","_toConsumableArray","concat","JSON","stringify","setData","skipEvent","unsubRemove","REMOVE","filter","id","unsubClear","CLEAR","removeAll","unsubUpdate","UPDATE","unsubInitReq","INIT_REQUEST","currentItems","INIT_RESPONSE","unsubInitRes","totalItems","useMfeCartData","_useState3","_useState4","unsubStateChange","useMfeCartActions","addToCart","removeFromCart","clearCart","updateCart"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{createClass as t,classCallCheck as e,defineProperty as r,asyncToGenerator as a,regenerator as i}from"../_virtual/_rollupPluginBabelHelpers.js";import{fetchDelay as n}from"../utils/helpers.js";import"../utils/dayjs-config.js";import"../utils/query-param.js";import{mfeBridge as o}from"./mfe-bridge.js";import{CART_CHANNELS as s}from"./cart.types.js";var l="mfe_cart_items",u=t((function t(){var u=this,c=arguments.length>0&&void 0!==arguments[0]?arguments[0]:l;e(this,t),r(this,"getDataAsync",(function(){return n(a(i().m((function t(){return i().w((function(t){for(;;)if(0===t.n)return t.a(2,u.getData())}),t)}))),500)})),r(this,"getData",(function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:u.key;try{var e;return JSON.parse(null!==(e=localStorage.getItem(t))&&void 0!==e?e:"[]")}catch(t){return[]}})),r(this,"setData",(function(t,e){var r=(null==e?void 0:e.key)||u.key,a=(null==e?void 0:e.skipEvent)||!1;localStorage.setItem(r,JSON.stringify(t)),a||o.publish(s.STATE_CHANGE,t)})),r(this,"removeAll",(function(t){var e=(null==t?void 0:t.key)||u.key,r=(null==t?void 0:t.skipEvent)||!1;localStorage.removeItem(e),r||o.publish(s.STATE_CHANGE,[])})),this.key=c}));function c(t){return new u(t||l)}export{l as CART_STORAGE_KEY,u as MfeCartStorage,c as createMfeCartStorage,u as default};
2
+ //# sourceMappingURL=cart.local-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart.local-storage.js","sources":["../../src/mfe-shared/cart.local-storage.ts"],"sourcesContent":["import { fetchDelay } from '../utils'\r\nimport { mfeBridge } from './mfe-bridge'\r\nimport { CART_CHANNELS } from './cart.types'\r\n\r\n/** LocalStorage key for persisting cart items */\r\nexport const CART_STORAGE_KEY = 'mfe_cart_items'\r\n\r\nexport interface ICartStorageOptions {\r\n key?: string\r\n skipEvent?: boolean\r\n}\r\n\r\nexport class MfeCartStorage<T = any> {\r\n private key: string\r\n\r\n constructor(key: string = CART_STORAGE_KEY) {\r\n this.key = key\r\n }\r\n\r\n getDataAsync = (): Promise<T[]> => {\r\n return fetchDelay(async () => this.getData(), 500)\r\n }\r\n\r\n getData = (key: string = this.key): T[] => {\r\n try {\r\n return JSON.parse(localStorage.getItem(key) ?? '[]')\r\n } catch (error) {\r\n return []\r\n }\r\n }\r\n\r\n setData = (value: T[], options?: ICartStorageOptions) => {\r\n const key = options?.key || this.key\r\n const skipEvent = options?.skipEvent || false\r\n\r\n // Set new data\r\n localStorage.setItem(key, JSON.stringify(value))\r\n\r\n // Publish STATE_CHANGE event to synchronize with hooks (unless skipped)\r\n if (!skipEvent) {\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, value)\r\n }\r\n }\r\n\r\n removeAll = (options?: ICartStorageOptions) => {\r\n const key = options?.key || this.key\r\n const skipEvent = options?.skipEvent || false\r\n\r\n // Remove data\r\n localStorage.removeItem(key)\r\n\r\n // Publish STATE_CHANGE event to synchronize with hooks (unless skipped)\r\n if (!skipEvent) {\r\n mfeBridge.publish(CART_CHANNELS.STATE_CHANGE, [])\r\n }\r\n }\r\n}\r\n\r\nexport default MfeCartStorage\r\n\r\nexport function createMfeCartStorage<T>(key?: string) {\r\n return new MfeCartStorage<T>(key || CART_STORAGE_KEY)\r\n}\r\n"],"names":["CART_STORAGE_KEY","MfeCartStorage","_createClass","_this","this","key","_classCallCheck","_defineProperty","fetchDelay","_asyncToGenerator","_regenerator","m","_callee","w","_context","n","a","getData","arguments","length","undefined","_localStorage$getItem","JSON","parse","localStorage","getItem","error","value","options","skipEvent","setItem","stringify","mfeBridge","publish","CART_CHANNELS","STATE_CHANGE","removeItem","createMfeCartStorage"],"mappings":"oWAKO,IAAMA,EAAmB,iBAOnBC,EAAcC,GAGzB,SAAAD,IAA0C,IAAAE,EAAAC,KAA9BC,yDAAcL,EAAgBM,OAAAL,GAAAM,uBAI3B,WACb,OAAOC,EAAUC,EAAAC,IAAAC,GAAC,SAAAC,IAAA,OAAAF,IAAAG,GAAA,SAAAC,GAAA,UAAA,IAAAA,EAAAC,EAAA,OAAAD,EAAAE,EAAA,EAAYb,EAAKc,UAAS,GAAAL,EAAA,KAAE,QAC/CL,kBAES,WAAgC,IAA/BF,EAAAa,UAAAC,OAAAD,QAAAE,IAAAF,UAAAE,GAAAF,UAAcf,GAAAA,EAAKE,IAC5B,IAAI,IAAAgB,EACF,OAAOC,KAAKC,MAA+BF,QAA1BA,EAACG,aAAaC,QAAQpB,cAAIgB,EAAAA,EAAI,KAChD,CAAC,MAAOK,GACP,MAAO,EACR,KACFnB,EAESH,KAAA,WAAA,SAACuB,EAAYC,GACrB,IAAMvB,GAAMuB,aAAAA,EAAAA,EAASvB,MAAOF,EAAKE,IAC3BwB,GAAYD,aAAO,EAAPA,EAASC,aAAa,EAGxCL,aAAaM,QAAQzB,EAAKiB,KAAKS,UAAUJ,IAGpCE,GACHG,EAAUC,QAAQC,EAAcC,aAAcR,MAEjDpB,EAAAH,KAAA,aAEW,SAACwB,GACX,IAAMvB,GAAMuB,aAAAA,EAAAA,EAASvB,MAAOF,EAAKE,IAC3BwB,GAAYD,aAAO,EAAPA,EAASC,aAAa,EAGxCL,aAAaY,WAAW/B,GAGnBwB,GACHG,EAAUC,QAAQC,EAAcC,aAAc,OArChD/B,KAAKC,IAAMA,CACb,IA2CI,SAAUgC,EAAwBhC,GACtC,OAAO,IAAIJ,EAAkBI,GAAOL,EACtC"}
@@ -1,2 +1,2 @@
1
- export{mfeBridge}from"./mfe-bridge.js";export{MfeAuthProvider,useMfeAuth}from"./auth.js";export{AUTH_CHANNELS}from"./auth.types.js";export{SsrAuthProvider}from"./auth.ssr.js";export{useMfeCartActions,useMfeCartData,useMfeCartStore}from"./cart.js";export{CART_CHANNELS}from"./cart.types.js";export{SsrCartProvider}from"./cart.ssr.js";export{MfeLink,MfeNavigateProvider,NAVIGATION_CHANNELS,useMfeNavigate}from"./navigation.js";export{isBrowser}from"./environment.js";export{HydrationGuard,useHydration}from"./hydration-helper.js";export{MfeAuthDebugPanel}from"./auth.debug.js";export{MfeCartDebugPanel}from"./cart.debug.js";export{MfeNavigateDebugPanel}from"./navigation.debug.js";
1
+ export{mfeBridge}from"./mfe-bridge.js";export{MfeAuthProvider,useMfeAuth}from"./auth.js";export{AUTH_CHANNELS}from"./auth.types.js";export{SsrAuthProvider}from"./auth.ssr.js";export{useMfeCartActions,useMfeCartData,useMfeCartStore}from"./cart.js";export{CART_CHANNELS}from"./cart.types.js";export{CART_STORAGE_KEY,MfeCartStorage as MfeCartLocalStorage,createMfeCartStorage}from"./cart.local-storage.js";export{SsrCartProvider}from"./cart.ssr.js";export{MfeLink,MfeNavigateProvider,NAVIGATION_CHANNELS,useMfeNavigate}from"./navigation.js";export{isBrowser}from"./environment.js";export{HydrationGuard,useHydration}from"./hydration-helper.js";export{MfeAuthDebugPanel}from"./auth.debug.js";export{MfeCartDebugPanel}from"./cart.debug.js";export{MfeNavigateDebugPanel}from"./navigation.debug.js";
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","sources":["../../src/mfe-shared/navigation.tsx"],"sourcesContent":["import { useEffect, type AnchorHTMLAttributes, type FC } from 'react'\r\nimport { mfeBridge } from './mfe-bridge'\r\nimport { isBrowser } from './environment'\r\n\r\n// Define channels for navigation events\r\nexport const NAVIGATION_CHANNELS = {\r\n NAVIGATE: 'mfe:navigation:navigate'\r\n}\r\n\r\nexport type AppSite = 'client' | 'home' | 'music'\r\n\r\nexport type IMfeNavigateHref = {\r\n primaryHref: string\r\n secondaryHref?: string\r\n}\r\n\r\nexport interface IMfeNavigate {\r\n primaryHref: string\r\n secondaryHref?: string\r\n internal?: boolean\r\n site?: AppSite\r\n options?: any\r\n target?: '_self' | '_blank'\r\n}\r\n\r\nexport /**\r\n * Hook for navigation between micro-frontends\r\n * @returns Navigation utilities\r\n */\r\nconst useMfeNavigate = () => {\r\n const navigate = (params: IMfeNavigate) => {\r\n // Use mfeBridge consistently instead of direct globalThis.dispatchEvent\r\n mfeBridge.publish(NAVIGATION_CHANNELS.NAVIGATE, params)\r\n }\r\n return { navigate }\r\n}\r\n\r\nexport interface IMfeLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {\r\n internal?: boolean\r\n primaryHref: string\r\n secondaryHref?: string\r\n}\r\n\r\nexport const MfeLink: FC<IMfeLinkProps> = (props) => {\r\n const { internal, primaryHref, secondaryHref, onClick, ...rest } = props\r\n const { navigate } = useMfeNavigate()\r\n\r\n const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\r\n if (onClick) onClick(e)\r\n if (e.defaultPrevented) return\r\n if (internal && secondaryHref) {\r\n e.preventDefault()\r\n navigate({ primaryHref, secondaryHref, internal })\r\n return\r\n }\r\n // If not internal or no secondaryHref, let the anchor tag handle it\r\n }\r\n\r\n return <a {...rest} href={primaryHref} onClick={handleClick} />\r\n}\r\n\r\n// Define types to avoid direct imports\r\nexport type NavigateFunction<O = any> = (path: string, options?: O) => void\r\n\r\nexport interface IMfeNavigateProviderProps {\r\n navigate: NavigateFunction\r\n}\r\n\r\nexport const MfeNavigateProvider: FC<IMfeNavigateProviderProps> = ({ navigate }) => {\r\n useEffect(() => {\r\n const unsubscribe = mfeBridge.subscribe(NAVIGATION_CHANNELS.NAVIGATE, (payload: IMfeNavigate) => {\r\n const { primaryHref, secondaryHref, options } = payload\r\n if (!primaryHref) return\r\n // Navigate to secondaryHref if available, otherwise fallback to primaryHref\r\n const url = secondaryHref || primaryHref || '/'\r\n if (options?.target === '_blank') {\r\n // Only open in new window if in browser environment\r\n if (isBrowser()) {\r\n window.open(`${url}`, '_blank')\r\n }\r\n return\r\n }\r\n navigate(url, options)\r\n })\r\n return () => unsubscribe() // Unsubscribe from the event\r\n }, [navigate])\r\n return <></>\r\n}\r\n"],"names":["NAVIGATION_CHANNELS","NAVIGATE","useMfeNavigate","navigate","params","mfeBridge","publish","MfeLink","props","internal","primaryHref","secondaryHref","onClick","rest","_objectWithoutProperties","_excluded","_jsx","_objectSpread","href","e","defaultPrevented","preventDefault","MfeNavigateProvider","_ref","useEffect","unsubscribe","subscribe","payload","options","url","target","isBrowser","window","open","concat"],"mappings":"kVAKaA,EAAsB,CACjCC,SAAU,2BAuBNC,EAAiB,WAKrB,MAAO,CAAEC,SAJQ,SAACC,GAEhBC,EAAUC,QAAQN,EAAoBC,SAAUG,EACjD,EAEH,EAQaG,EAA6B,SAACC,GACzC,IAAQC,EAA2DD,EAA3DC,SAAUC,EAAiDF,EAAjDE,YAAaC,EAAoCH,EAApCG,cAAeC,EAAqBJ,EAArBI,QAAYC,EAAIC,EAAKN,EAAKO,GAChEZ,EAAaD,IAAbC,SAaR,OAAOa,EAAA,IAAAC,EAAAA,KAAOJ,GAAI,GAAA,CAAEK,KAAMR,EAAaE,QAXnB,SAACO,GAEnB,GADIP,GAASA,EAAQO,IACjBA,EAAEC,iBACN,OAAIX,GAAYE,GACdQ,EAAEE,sBACFlB,EAAS,CAAEO,YAAAA,EAAaC,cAAAA,EAAeF,SAAAA,UAFzC,CAMD,IAGH,EASaa,EAAqD,SAAlCC,GAAmD,IAAdpB,EAAQoB,EAARpB,SAkBnE,OAjBAqB,GAAU,WACR,IAAMC,EAAcpB,EAAUqB,UAAU1B,EAAoBC,UAAU,SAAC0B,GACrE,IAAQjB,EAAwCiB,EAAxCjB,YAAaC,EAA2BgB,EAA3BhB,cAAeiB,EAAYD,EAAZC,QACpC,GAAKlB,EAAL,CAEA,IAAMmB,EAAMlB,GAAiBD,GAAe,IACpB,YAApBkB,aAAO,EAAPA,EAASE,QAOb3B,EAAS0B,EAAKD,GALRG,KACFC,OAAOC,KAAIC,GAAAA,OAAIL,GAAO,SANR,CAWpB,IACA,OAAO,WAAA,OAAMJ,GAAa,CAC5B,GAAG,CAACtB,IACGa,OACT"}
1
+ {"version":3,"file":"navigation.js","sources":["../../src/mfe-shared/navigation.tsx"],"sourcesContent":["import { useEffect, type AnchorHTMLAttributes, type FC } from 'react'\r\nimport { mfeBridge } from './mfe-bridge'\r\nimport { isBrowser } from './environment'\r\n\r\n// Define channels for navigation events\r\nexport const NAVIGATION_CHANNELS = {\r\n NAVIGATE: 'mfe:navigation:navigate'\r\n}\r\n\r\nexport type AppSite = 'client' | 'home' | 'music' | 'api'\r\n\r\nexport type IMfeNavigateHref = {\r\n primaryHref: string\r\n secondaryHref?: string\r\n}\r\n\r\nexport interface IMfeNavigate {\r\n primaryHref: string\r\n secondaryHref?: string\r\n internal?: boolean\r\n site?: AppSite\r\n options?: any\r\n target?: '_self' | '_blank'\r\n}\r\n\r\nexport /**\r\n * Hook for navigation between micro-frontends\r\n * @returns Navigation utilities\r\n */\r\nconst useMfeNavigate = () => {\r\n const navigate = (params: IMfeNavigate) => {\r\n // Use mfeBridge consistently instead of direct globalThis.dispatchEvent\r\n mfeBridge.publish(NAVIGATION_CHANNELS.NAVIGATE, params)\r\n }\r\n return { navigate }\r\n}\r\n\r\nexport interface IMfeLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {\r\n internal?: boolean\r\n primaryHref: string\r\n secondaryHref?: string\r\n}\r\n\r\nexport const MfeLink: FC<IMfeLinkProps> = (props) => {\r\n const { internal, primaryHref, secondaryHref, onClick, ...rest } = props\r\n const { navigate } = useMfeNavigate()\r\n\r\n const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\r\n if (onClick) onClick(e)\r\n if (e.defaultPrevented) return\r\n if (internal && secondaryHref) {\r\n e.preventDefault()\r\n navigate({ primaryHref, secondaryHref, internal })\r\n return\r\n }\r\n // If not internal or no secondaryHref, let the anchor tag handle it\r\n }\r\n\r\n return <a {...rest} href={primaryHref} onClick={handleClick} />\r\n}\r\n\r\n// Define types to avoid direct imports\r\nexport type NavigateFunction<O = any> = (path: string, options?: O) => void\r\n\r\nexport interface IMfeNavigateProviderProps {\r\n navigate: NavigateFunction\r\n}\r\n\r\nexport const MfeNavigateProvider: FC<IMfeNavigateProviderProps> = ({ navigate }) => {\r\n useEffect(() => {\r\n const unsubscribe = mfeBridge.subscribe(NAVIGATION_CHANNELS.NAVIGATE, (payload: IMfeNavigate) => {\r\n const { primaryHref, secondaryHref, options } = payload\r\n if (!primaryHref) return\r\n // Navigate to secondaryHref if available, otherwise fallback to primaryHref\r\n const url = secondaryHref || primaryHref || '/'\r\n if (options?.target === '_blank') {\r\n // Only open in new window if in browser environment\r\n if (isBrowser()) {\r\n window.open(`${url}`, '_blank')\r\n }\r\n return\r\n }\r\n navigate(url, options)\r\n })\r\n return () => unsubscribe() // Unsubscribe from the event\r\n }, [navigate])\r\n return <></>\r\n}\r\n"],"names":["NAVIGATION_CHANNELS","NAVIGATE","useMfeNavigate","navigate","params","mfeBridge","publish","MfeLink","props","internal","primaryHref","secondaryHref","onClick","rest","_objectWithoutProperties","_excluded","_jsx","_objectSpread","href","e","defaultPrevented","preventDefault","MfeNavigateProvider","_ref","useEffect","unsubscribe","subscribe","payload","options","url","target","isBrowser","window","open","concat"],"mappings":"kVAKaA,EAAsB,CACjCC,SAAU,2BAuBNC,EAAiB,WAKrB,MAAO,CAAEC,SAJQ,SAACC,GAEhBC,EAAUC,QAAQN,EAAoBC,SAAUG,EACjD,EAEH,EAQaG,EAA6B,SAACC,GACzC,IAAQC,EAA2DD,EAA3DC,SAAUC,EAAiDF,EAAjDE,YAAaC,EAAoCH,EAApCG,cAAeC,EAAqBJ,EAArBI,QAAYC,EAAIC,EAAKN,EAAKO,GAChEZ,EAAaD,IAAbC,SAaR,OAAOa,EAAA,IAAAC,EAAAA,KAAOJ,GAAI,GAAA,CAAEK,KAAMR,EAAaE,QAXnB,SAACO,GAEnB,GADIP,GAASA,EAAQO,IACjBA,EAAEC,iBACN,OAAIX,GAAYE,GACdQ,EAAEE,sBACFlB,EAAS,CAAEO,YAAAA,EAAaC,cAAAA,EAAeF,SAAAA,UAFzC,CAMD,IAGH,EASaa,EAAqD,SAAlCC,GAAmD,IAAdpB,EAAQoB,EAARpB,SAkBnE,OAjBAqB,GAAU,WACR,IAAMC,EAAcpB,EAAUqB,UAAU1B,EAAoBC,UAAU,SAAC0B,GACrE,IAAQjB,EAAwCiB,EAAxCjB,YAAaC,EAA2BgB,EAA3BhB,cAAeiB,EAAYD,EAAZC,QACpC,GAAKlB,EAAL,CAEA,IAAMmB,EAAMlB,GAAiBD,GAAe,IACpB,YAApBkB,aAAO,EAAPA,EAASE,QAOb3B,EAAS0B,EAAKD,GALRG,KACFC,OAAOC,KAAIC,GAAAA,OAAIL,GAAO,SANR,CAWpB,IACA,OAAO,WAAA,OAAMJ,GAAa,CAC5B,GAAG,CAACtB,IACGa,OACT"}
@@ -0,0 +1,16 @@
1
+ /** LocalStorage key for persisting cart items */
2
+ export declare const CART_STORAGE_KEY = "mfe_cart_items";
3
+ export interface ICartStorageOptions {
4
+ key?: string;
5
+ skipEvent?: boolean;
6
+ }
7
+ export declare class MfeCartStorage<T = any> {
8
+ private key;
9
+ constructor(key?: string);
10
+ getDataAsync: () => Promise<T[]>;
11
+ getData: (key?: string) => T[];
12
+ setData: (value: T[], options?: ICartStorageOptions) => void;
13
+ removeAll: (options?: ICartStorageOptions) => void;
14
+ }
15
+ export default MfeCartStorage;
16
+ export declare function createMfeCartStorage<T>(key?: string): MfeCartStorage<T>;
@@ -13,6 +13,7 @@ export { AUTH_CHANNELS } from './auth.types';
13
13
  export { SsrAuthProvider } from './auth.ssr';
14
14
  export { useMfeCartStore, useMfeCartActions, useMfeCartData } from './cart';
15
15
  export { CART_CHANNELS } from './cart.types';
16
+ export { MfeCartStorage as MfeCartLocalStorage, createMfeCartStorage, CART_STORAGE_KEY } from './cart.local-storage';
16
17
  export { SsrCartProvider } from './cart.ssr';
17
18
  export { useMfeNavigate, MfeLink, MfeNavigateProvider } from './navigation';
18
19
  export type { IMfeNavigate, IMfeLinkProps, NavigateFunction, AppSite, IMfeNavigateProviderProps } from './navigation';
@@ -2,7 +2,7 @@ import { type AnchorHTMLAttributes, type FC } from 'react';
2
2
  export declare const NAVIGATION_CHANNELS: {
3
3
  NAVIGATE: string;
4
4
  };
5
- export type AppSite = 'client' | 'home' | 'music';
5
+ export type AppSite = 'client' | 'home' | 'music' | 'api';
6
6
  export type IMfeNavigateHref = {
7
7
  primaryHref: string;
8
8
  secondaryHref?: string;
@@ -6,6 +6,5 @@
6
6
  */
7
7
  export type { IAuthState, IUser } from './auth.types';
8
8
  export type { IMfeAuthProviderProps as IAuthProviderProps, ILoginParams, ILoginResponse } from './auth';
9
- export type { ICartItem } from './cart.types';
10
- export type { AppSite, IMfeNavigate, IMfeNavigateHref, IMfeLinkProps, NavigateFunction, IMfeNavigateProviderProps as IMfeNavigateReactProviderProps } from './navigation';
9
+ export type { AppSite, IMfeNavigate, IMfeNavigateHref, IMfeLinkProps, NavigateFunction, IMfeNavigateProviderProps } from './navigation';
11
10
  export type { IHydrationState } from './hydration-helper';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dinocollab-core",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",