@growupsell/react 1.0.0-alpha.2 → 1.0.0-alpha.4

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/index.d.ts CHANGED
@@ -40,6 +40,14 @@ type GrowupsellProviderProps = {
40
40
  * the instance, disposes it after a real unmount. Always renders its children.
41
41
  */
42
42
  declare function GrowupsellProvider(props: GrowupsellProviderProps): ReactElement;
43
+ /**
44
+ * The instance, or null outside a provider: for shared UI (header, footer) that must still render
45
+ * when the app could not mount one (e.g. the business did not resolve). Render the parts that use
46
+ * other hooks only when it is not null.
47
+ */
48
+ declare function useGrowupsell(options: {
49
+ optional: true;
50
+ }): GrowupsellStores | null;
43
51
  /** The instance: `useGrowupsell().cart.add(...)`. Throws outside a provider. Stable for the mount. */
44
52
  declare function useGrowupsell(): GrowupsellStores;
45
53
 
package/dist/index.js CHANGED
@@ -212,9 +212,11 @@ function GrowupsellProvider(props) {
212
212
  }, [stores, hydrate]);
213
213
  return /* @__PURE__ */ jsx(GrowupsellContext.Provider, { value: stores, children });
214
214
  }
215
- function useGrowupsell() {
215
+ function useGrowupsell(options) {
216
216
  const stores = useContext(GrowupsellContext);
217
- if (!stores) throw new Error("useGrowupsell must be used inside <GrowupsellProvider>");
217
+ if (!stores && !options?.optional) {
218
+ throw new Error("useGrowupsell must be used inside <GrowupsellProvider>");
219
+ }
218
220
  return stores;
219
221
  }
220
222
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useStore.ts","../src/shallowEqual.ts","../src/provider.tsx","../src/host.ts","../src/useOwned.ts","../src/storeHooks.ts","../src/events.ts","../src/derived.ts","../src/screens.ts"],"sourcesContent":["import type { Store } from '@growupsell/commerce/stores';\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\n\nexport type EqualityFn<T> = (a: T, b: T) => boolean;\n\ntype Selector<T, S> = (state: T) => S;\n\n/** What the last commit of a hook instance rendered. Written only in an effect. */\ninterface Committed<T, S> {\n store: Store<T>;\n selection: S;\n}\n\n/** Re-renders only when `isEqual(previous, next)` is false. Default `Object.is`. */\nexport function useStore<T>(store: Store<T>): T;\nexport function useStore<T, S>(\n store: Store<T>,\n selector: (state: T) => S,\n isEqual?: EqualityFn<S>,\n): S;\nexport function useStore<T, S>(\n store: Store<T>,\n selector?: Selector<T, S>,\n isEqual: EqualityFn<S> = Object.is,\n): S {\n const committed = useRef<Committed<T, S> | null>(null);\n\n // One memo per [store, selector, isEqual] (React's `useSyncExternalStoreWithSelector`\n // pattern): a render React throws away also throws its memo away, so it cannot change what\n // the committed tree compares against. The memo reuses its selection for the same snapshot,\n // and the previous selection (the committed one first) when `isEqual` says the new one equals\n // it. That keeps the value `useSyncExternalStore` sees stable, so inline selectors never loop.\n const [getSelection, getServerSelection] = useMemo(() => {\n const memoised = (read: () => T) => {\n let last: { snapshot: T; selection: S } | null = null;\n return () => {\n const snapshot = read();\n if (last && Object.is(last.snapshot, snapshot)) return last.selection;\n const next = selector ? selector(snapshot) : (snapshot as unknown as S);\n const previous = last ?? (committed.current?.store === store ? committed.current : null);\n const selection = previous && isEqual(previous.selection, next) ? previous.selection : next;\n last = { snapshot, selection };\n return selection;\n };\n };\n return [memoised(store.getSnapshot), memoised(store.getServerSnapshot)];\n }, [store, selector, isEqual]);\n\n const selection = useSyncExternalStore(store.subscribe, getSelection, getServerSelection);\n useEffect(() => {\n committed.current = { store, selection };\n });\n return selection;\n}\n\n/** `useStore` with an optional selector, for hooks whose own overloads type the result. */\nexport const select = useStore as <T, S>(\n store: Store<T>,\n selector?: (state: T) => S,\n isEqual?: EqualityFn<S>,\n) => S;\n","const isPlain = (value: object) => {\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\n/**\n * One level deep, `Object.is` per value. For selectors that build an object or array: plain\n * objects (same keys), arrays (same items in order), `Date` (same time), `Map` (same keys and\n * values) and `Set` (same members). Any other object (a class instance, a RegExp) is equal only\n * to itself.\n */\nexport function shallowEqual<T>(a: T, b: T): boolean {\n if (Object.is(a, b)) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;\n const left: object = a;\n const right: object = b;\n if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) {\n if (!isPlain(left) || !isPlain(right)) return false;\n } else if (left instanceof Date) {\n return left.getTime() === (right as Date).getTime();\n } else if (left instanceof Map) {\n const other = right as Map<unknown, unknown>;\n if (left.size !== other.size) return false;\n for (const [key, value] of left) {\n if (!other.has(key) || !Object.is(value, other.get(key))) return false;\n }\n return true;\n } else if (left instanceof Set) {\n const other = right as Set<unknown>;\n if (left.size !== other.size) return false;\n for (const value of left) if (!other.has(value)) return false;\n return true;\n } else if (!Array.isArray(left) && !isPlain(left)) {\n return false;\n }\n const leftRecord = left as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n const keys = Object.keys(leftRecord);\n if (keys.length !== Object.keys(rightRecord).length) return false;\n return keys.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(rightRecord, key) &&\n Object.is(leftRecord[key], rightRecord[key]),\n );\n}\n","import {\n createGrowupsellStores,\n type GrowupsellStores,\n type GrowupsellStoresOptions,\n} from '@growupsell/commerce/stores';\nimport {\n createContext,\n useContext,\n useEffect,\n useInsertionEffect,\n useRef,\n type ReactElement,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { host, rethrowAsync } from './host';\nimport { useOwned } from './useOwned';\n\nexport type GrowupsellProviderProps =\n | {\n /** An instance the app created and owns: never disposed by the provider. */\n stores: GrowupsellStores;\n options?: never;\n /** Call `stores.hydrate()` after the first commit. Default true. */\n hydrate?: boolean;\n children?: ReactNode;\n }\n | {\n /**\n * Read once per mount: the provider creates the instance on the first render and disposes\n * it after a real unmount. To switch business, change the provider's `key`. Function\n * options (`onUnauthorized`, `onError`, `merchantToken`) always call the latest prop.\n */\n options: GrowupsellStoresOptions;\n stores?: never;\n hydrate?: boolean;\n children?: ReactNode;\n };\n\nconst GrowupsellContext = createContext<GrowupsellStores | null>(null);\n\n/** Options that identify the instance: changing them needs a new provider (`key`). */\nconst IDENTITY_OPTIONS = ['baseURL', 'businessId', 'platform'] as const;\n\n/** The provider creates at most one instance per mount. */\nconst ONCE: readonly unknown[] = [];\nconst disposeInstance = (stores: GrowupsellStores | null) => stores?.dispose();\n\n/** Replaces the function options with forwarders to the latest props. */\nfunction forwarding(\n options: GrowupsellStoresOptions,\n latest: RefObject<GrowupsellStoresOptions | undefined>,\n): GrowupsellStoresOptions {\n return {\n ...options,\n onUnauthorized: (event) => latest.current?.onUnauthorized?.(event),\n onError: (error) => (latest.current?.onError ?? rethrowAsync)(error),\n merchantToken: () => latest.current?.merchantToken?.() ?? null,\n };\n}\n\n/**\n * Holds one `GrowupsellStores` per mount, hydrates it after the first commit and, when it created\n * the instance, disposes it after a real unmount. Always renders its children.\n */\nexport function GrowupsellProvider(props: GrowupsellProviderProps): ReactElement {\n const { hydrate = true, children } = props;\n const latest = useRef<GrowupsellStoresOptions | undefined>(props.options);\n useInsertionEffect(() => {\n latest.current = props.options;\n });\n\n // Created during the first render: creation does no I/O, so it is safe on the server too.\n // Disposed after a real unmount; an instance created in a render React threw away is disposed\n // at the next commit (`useOwned`).\n const created = useOwned(\n () =>\n props.stores || !props.options\n ? null\n : createGrowupsellStores(forwarding(props.options, latest)),\n ONCE,\n disposeInstance,\n );\n const stores = props.stores ?? created;\n if (!stores) {\n throw new Error('<GrowupsellProvider> needs either `stores` or `options`.');\n }\n\n const initial = useRef(props.options);\n const warned = useRef(false);\n useEffect(() => {\n const first = initial.current;\n const now = props.options;\n if (!first || !now || warned.current) return;\n if (IDENTITY_OPTIONS.some((key) => !Object.is(first[key], now[key]))) {\n warned.current = true;\n host.console.error(\n \"<GrowupsellProvider>: baseURL, businessId and platform are read once. Change the provider's `key` to switch them.\",\n );\n }\n });\n\n // After the first commit, never on the server. Once per instance (StrictMode re-runs effects).\n const hydratedFor = useRef<GrowupsellStores | null>(null);\n useEffect(() => {\n if (!hydrate || hydratedFor.current === stores) return;\n hydratedFor.current = stores;\n void stores.hydrate();\n }, [stores, hydrate]);\n\n return <GrowupsellContext.Provider value={stores}>{children}</GrowupsellContext.Provider>;\n}\n\n/** The instance: `useGrowupsell().cart.add(...)`. Throws outside a provider. Stable for the mount. */\nexport function useGrowupsell(): GrowupsellStores {\n const stores = useContext(GrowupsellContext);\n if (!stores) throw new Error('useGrowupsell must be used inside <GrowupsellProvider>');\n return stores;\n}\n","/** The globals the adapter uses, through `globalThis`: it compiles without DOM or Node types (ADR-009). */\nexport const host = globalThis as unknown as {\n setTimeout(handler: () => void, ms: number): unknown;\n clearTimeout(id: unknown): void;\n console: { error(...data: unknown[]): void };\n};\n\n/** The default for listener and storage errors, as in commerce: rethrown on a later tick. */\nexport function rethrowAsync(error: unknown): void {\n host.setTimeout(() => {\n throw error;\n }, 0);\n}\n","/**\n * `useOwned`: a value a component creates during render and disposes when it is done with it\n * (the provider's instance, per-screen stores). Creating in render keeps the first render, on\n * the server too, able to show the value (creation does no I/O). What makes that safe:\n *\n * - **Mounted** is tracked in an insertion effect. Insertion effects run once per real mount,\n * also in a hidden `<Activity>`, and their cleanup runs once per real unmount: StrictMode's\n * effect double-invoke and `<Activity mode=\"hidden\">` do not touch them (layout and passive\n * effects are disconnected and run again instead). So hiding a subtree keeps its values.\n * - **Created but never mounted** (React threw the render away: StrictMode's second call of a\n * state initializer, a suspended or interrupted render) is disposed at the next commit of any\n * `useOwned`. Those values are held weakly, so the server, which never commits, keeps none.\n * - **Disposed while mounted** (a sweep that ran before a slow render committed, in another\n * root) is replaced in the passive effect, with a re-render.\n * - A real unmount or a new key disposes the old value after a tick, cancelled if the same value\n * mounts again meanwhile (Fast Refresh runs the cleanup and the setup again).\n */\nimport { useEffect, useInsertionEffect, useReducer, useRef, useState } from 'react';\nimport { host } from './host';\n\ninterface Owned<T> {\n value: T;\n readonly key: readonly unknown[];\n readonly dispose: (value: T) => void;\n mounted: boolean;\n disposed: boolean;\n /** The dispose an unmount scheduled; undefined when none is pending. */\n timer: unknown;\n /** Its entry in `unmounted` while not mounted. */\n ref: WeakReference | null;\n}\n\ninterface WeakReference {\n deref(): object | undefined;\n}\n\n/** Values created in render that no commit has mounted yet. Weak: a server render keeps none. */\nconst unmounted = new Set<WeakReference>();\nconst owners = new WeakMap<object, Owned<unknown>>();\nlet pruneAt = 64;\n\nconst weakly = (value: object): WeakReference =>\n typeof WeakRef === 'function' ? new WeakRef(value) : { deref: () => value };\n\nfunction own<T>(value: T, key: readonly unknown[], dispose: (value: T) => void): Owned<T> {\n const entry: Owned<T> = {\n value,\n key,\n dispose,\n mounted: false,\n disposed: false,\n timer: undefined,\n ref: null,\n };\n if (typeof value === 'object' && value !== null) {\n entry.ref = weakly(value);\n owners.set(value, entry as Owned<unknown>);\n unmounted.add(entry.ref);\n if (unmounted.size >= pruneAt) {\n for (const ref of unmounted) if (ref.deref() === undefined) unmounted.delete(ref);\n pruneAt = Math.max(64, unmounted.size * 2);\n }\n }\n return entry;\n}\n\nfunction release(entry: Owned<unknown>): void {\n if (entry.timer !== undefined) host.clearTimeout(entry.timer);\n entry.timer = undefined;\n if (entry.disposed) return;\n entry.disposed = true;\n entry.dispose(entry.value);\n}\n\n/** Disposes every value created in a render that never committed. */\nexport function disposeUnmounted(): void {\n for (const ref of unmounted) {\n unmounted.delete(ref);\n const value = ref.deref();\n const entry = value === undefined ? undefined : owners.get(value);\n if (entry && !entry.mounted) release(entry);\n }\n}\n\nconst sameKey = (a: readonly unknown[], b: readonly unknown[]) =>\n a.length === b.length && a.every((part, i) => Object.is(part, b[i]));\n\n/**\n * One value per `key` (compared part by part), created with `create` during render and disposed\n * with `dispose` after the component is done with it. A new key creates the new value in the\n * same render; the old one is disposed after the commit.\n */\nexport function useOwned<T>(\n create: () => T,\n key: readonly unknown[],\n dispose: (value: T) => void,\n): T {\n const [state, setState] = useState(() => own(create(), key, dispose));\n let entry = state;\n if (!sameKey(entry.key, key)) {\n // React's \"adjust state when a prop changes\": re-renders at once with the new value.\n entry = own(create(), key, dispose);\n setState(entry);\n }\n\n const latestCreate = useRef(create);\n const [, rerender] = useReducer((n: number) => n + 1, 0);\n\n useInsertionEffect(() => {\n latestCreate.current = create;\n });\n\n useInsertionEffect(() => {\n entry.mounted = true;\n if (entry.timer !== undefined) host.clearTimeout(entry.timer);\n entry.timer = undefined;\n if (entry.ref) unmounted.delete(entry.ref);\n return () => {\n if (!entry.disposed && entry.timer === undefined) {\n entry.timer = host.setTimeout(() => release(entry as Owned<unknown>), 0);\n }\n };\n }, [entry]);\n\n useEffect(() => {\n if (entry.disposed) {\n entry.value = latestCreate.current();\n entry.disposed = false;\n rerender();\n }\n // Every insertion effect of this commit has run: what is still unmounted never will be.\n disposeUnmounted();\n }, [entry]);\n\n return entry.value;\n}\n","import type {\n AuthState,\n BusinessState,\n CartState,\n CatalogState,\n CheckoutState,\n GrowupsellStores,\n Identity,\n ReferralState,\n SessionState,\n Store,\n ThemeConfigState,\n WishlistState,\n} from '@growupsell/commerce/stores';\nimport { useGrowupsell } from './provider';\nimport { select, useStore, type EqualityFn } from './useStore';\n\n/** A hook over one store of the instance: the whole snapshot, or a memoised selection. */\nexport interface StoreHook<T> {\n (): T;\n <S>(selector: (state: T) => S, isEqual?: EqualityFn<S>): S;\n}\n\nfunction storeHook<T>(pick: (stores: GrowupsellStores) => Store<T>): StoreHook<T> {\n return function useStoreOfInstance<S>(selector?: (state: T) => S, isEqual?: EqualityFn<S>) {\n return select(pick(useGrowupsell()), selector, isEqual);\n } as StoreHook<T>;\n}\n\nexport const useSession: StoreHook<SessionState> = storeHook((s) => s.session);\nexport const useAuth: StoreHook<AuthState> = storeHook((s) => s.auth);\nexport const useCart: StoreHook<CartState> = storeHook((s) => s.cart);\nexport const useWishlist: StoreHook<WishlistState> = storeHook((s) => s.wishlist);\nexport const useCheckout: StoreHook<CheckoutState> = storeHook((s) => s.checkout);\nexport const useBusiness: StoreHook<BusinessState> = storeHook((s) => s.business);\nexport const useCatalog: StoreHook<CatalogState> = storeHook((s) => s.catalog);\nexport const useThemeConfig: StoreHook<ThemeConfigState> = storeHook((s) => s.themeConfig);\nexport const useReferral: StoreHook<ReferralState> = storeHook((s) => s.referral);\nexport const useIdentity: StoreHook<Identity> = storeHook((s) => s.identity);\n\n/** False on the server and in the first client render; true once stored logins are read. */\nexport function useHydrated(): boolean {\n return useStore(useGrowupsell().hydrated);\n}\n","import type { GrowupsellEvent } from '@growupsell/commerce/stores';\nimport { useEffect, useInsertionEffect, useRef } from 'react';\nimport { useGrowupsell } from './provider';\n\n/** Subscribes after mount (never on the server); always calls the latest `listener`. */\nexport function useGrowupsellEvent<K extends GrowupsellEvent['type']>(\n type: K,\n listener: (event: Extract<GrowupsellEvent, { type: K }>) => void,\n): void {\n const stores = useGrowupsell();\n const latest = useRef(listener);\n useInsertionEffect(() => {\n latest.current = listener;\n });\n useEffect(() => stores.events.on(type, (event) => latest.current(event)), [stores, type]);\n}\n","import type { CheckoutPreview, PaymentOptions } from '@growupsell/commerce/rules';\nimport {\n checkoutPreviewFor,\n paymentOptionsFor,\n type GrowupsellStores,\n type Store,\n} from '@growupsell/commerce/stores';\nimport { useMemo } from 'react';\nimport { useGrowupsell } from './provider';\nimport { shallowEqual } from './shallowEqual';\nimport { useStore } from './useStore';\n\ntype Snapshots<Sources extends readonly Store<unknown>[]> = {\n [I in keyof Sources]: Sources[I] extends Store<infer T> ? T : never;\n};\n\n/**\n * A read-only `Store` over several stores: `compute` runs again only when one of their snapshots\n * changed. The server snapshot is computed from their server snapshots. No logic of its own:\n * `compute` is a commerce selector.\n */\nfunction combine<Sources extends readonly Store<unknown>[], R>(\n sources: Sources,\n compute: (...snapshots: Snapshots<Sources>) => R,\n): Store<R> {\n const memo = (read: (store: Store<unknown>) => unknown) => {\n let last: { inputs: unknown[]; value: R } | null = null;\n return () => {\n const inputs = sources.map(read);\n if (last && inputs.every((input, i) => Object.is(input, last!.inputs[i]))) return last.value;\n last = { inputs, value: compute(...(inputs as Snapshots<Sources>)) };\n return last.value;\n };\n };\n return {\n getSnapshot: memo((store) => store.getSnapshot()),\n getServerSnapshot: memo((store) => store.getServerSnapshot()),\n subscribe(listener) {\n const offs = sources.map((store) => store.subscribe(listener));\n return () => offs.forEach((off) => off());\n },\n };\n}\n\nfunction useDerived<R>(build: (stores: GrowupsellStores) => Store<R>): R {\n const stores = useGrowupsell();\n // One derived store per instance (`build` is a module-level constant).\n const derived = useMemo(() => build(stores), [build, stores]);\n return useStore(derived, (value) => value, shallowEqual);\n}\n\nconst previewStore = (s: GrowupsellStores) =>\n combine([s.cart, s.checkout, s.auth] as const, checkoutPreviewFor);\n\nconst paymentOptionsStore = (s: GrowupsellStores) =>\n combine([s.cart, s.checkout, s.auth, s.business] as const, (cart, checkout, auth, business) =>\n paymentOptionsFor(cart, checkout, auth, business.features),\n );\n\n/** `checkoutPreviewFor(cart, checkout, auth)`; re-renders only when the preview changes (shallow). */\nexport function useCheckoutPreview(): CheckoutPreview | null {\n return useDerived(previewStore);\n}\n\n/** `paymentOptionsFor(cart, checkout, auth, business.features)`; same rule. */\nexport function usePaymentOptions(): PaymentOptions | null {\n return useDerived(paymentOptionsStore);\n}\n","import { parseListingQuery } from '@growupsell/commerce/rules';\nimport type {\n ListingInput,\n ListingState,\n ListingStore,\n ProductDetailInput,\n ProductDetailState,\n ProductDetailStore,\n SearchSuggestionsOptions,\n SearchSuggestionsState,\n SearchSuggestionsStore,\n} from '@growupsell/commerce/stores';\nimport { useEffect, useRef } from 'react';\nimport { useGrowupsell } from './provider';\nimport { useOwned } from './useOwned';\nimport { select, type EqualityFn } from './useStore';\n\n/**\n * Per-screen stores are created during render (no I/O, so the server renders them too, never\n * subscribed and collected with the request's instance) and disposed after unmount (`useOwned`).\n */\nconst disposeStore = (store: { dispose(): void }) => store.dispose();\n\n/**\n * One listing per mount. A later `input.query` change calls `applyQuery` once (no search when\n * equal), with `input.categoryId` as its category when the query names none, so the app can keep\n * the category in its path. A later `input.categoryId` change alone calls `setCategory` (which\n * clears the old category's filters), unless the query names its own category. `pageSize` is\n * read once.\n */\nexport function useListing(input?: ListingInput): [ListingState, ListingStore];\nexport function useListing<S>(\n input: ListingInput | undefined,\n selector: (state: ListingState) => S,\n isEqual?: EqualityFn<S>,\n): [S, ListingStore];\nexport function useListing<S>(\n input?: ListingInput,\n selector?: (state: ListingState) => S,\n isEqual?: EqualityFn<S>,\n): [S | ListingState, ListingStore] {\n const stores = useGrowupsell();\n const store = useOwned(() => stores.createListing(input), [stores], disposeStore);\n\n // Route changes after mount, applied once per commit from both inputs together; the values at\n // creation are already in the store. `input.query` is read through `queryKey`: a new but\n // equal object is no change.\n const queryKey = JSON.stringify(input?.query ?? null);\n const categoryId = input?.categoryId ?? null;\n const applied = useRef({ store, queryKey, categoryId });\n useEffect(() => {\n const last = applied.current;\n applied.current = { store, queryKey, categoryId };\n // A new store was created from this input.\n if (last.store !== store) return;\n const query = input?.query ?? {};\n // A category in the query wins; else the app keeps it in its path (`categoryId`).\n const ownCategory = parseListingQuery(query).categoryId !== null;\n if (last.queryKey !== queryKey) {\n // The query is the whole criteria: its filters belong to the category it comes with.\n const asIs = ownCategory || categoryId === null;\n store.applyQuery(asIs ? query : { ...query, category: String(categoryId) });\n } else if (last.categoryId !== categoryId && !ownCategory) {\n // Same query, other category: its filters belonged to the old one (ADR-025).\n store.setCategory(categoryId);\n }\n }, [store, queryKey, categoryId]);\n\n return [select(store, selector, isEqual), store];\n}\n\n/** Keyed on `productId`: a new id creates a new store; `selectedVariantIds` and `initial` are read at creation. */\nexport function useProductDetail(\n input: ProductDetailInput,\n): [ProductDetailState, ProductDetailStore];\nexport function useProductDetail<S>(\n input: ProductDetailInput,\n selector: (state: ProductDetailState) => S,\n isEqual?: EqualityFn<S>,\n): [S, ProductDetailStore];\nexport function useProductDetail<S>(\n input: ProductDetailInput,\n selector?: (state: ProductDetailState) => S,\n isEqual?: EqualityFn<S>,\n): [S | ProductDetailState, ProductDetailStore] {\n const stores = useGrowupsell();\n const store = useOwned(\n () => stores.createProductDetail(input),\n [stores, input.productId],\n disposeStore,\n );\n return [select(store, selector, isEqual), store];\n}\n\n/** One per mount; `options` read once. */\nexport function useSearchSuggestions(\n options?: SearchSuggestionsOptions,\n): [SearchSuggestionsState, SearchSuggestionsStore];\nexport function useSearchSuggestions<S>(\n options: SearchSuggestionsOptions | undefined,\n selector: (state: SearchSuggestionsState) => S,\n isEqual?: EqualityFn<S>,\n): [S, SearchSuggestionsStore];\nexport function useSearchSuggestions<S>(\n options?: SearchSuggestionsOptions,\n selector?: (state: SearchSuggestionsState) => S,\n isEqual?: EqualityFn<S>,\n): [S | SearchSuggestionsState, SearchSuggestionsStore] {\n const stores = useGrowupsell();\n const store = useOwned(() => stores.createSearchSuggestions(options), [stores], disposeStore);\n return [select(store, selector, isEqual), store];\n}\n"],"mappings":"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","names":["selection","useEffect","useInsertionEffect","useRef","useEffect","useRef","useRef","useEffect","useRef","useInsertionEffect","useEffect","useEffect","useInsertionEffect","useRef","useRef","useInsertionEffect","useEffect","useMemo","useMemo","useEffect","useRef","useRef","useEffect"]}
1
+ {"version":3,"sources":["../src/useStore.ts","../src/shallowEqual.ts","../src/provider.tsx","../src/host.ts","../src/useOwned.ts","../src/storeHooks.ts","../src/events.ts","../src/derived.ts","../src/screens.ts"],"sourcesContent":["import type { Store } from '@growupsell/commerce/stores';\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\n\nexport type EqualityFn<T> = (a: T, b: T) => boolean;\n\ntype Selector<T, S> = (state: T) => S;\n\n/** What the last commit of a hook instance rendered. Written only in an effect. */\ninterface Committed<T, S> {\n store: Store<T>;\n selection: S;\n}\n\n/** Re-renders only when `isEqual(previous, next)` is false. Default `Object.is`. */\nexport function useStore<T>(store: Store<T>): T;\nexport function useStore<T, S>(\n store: Store<T>,\n selector: (state: T) => S,\n isEqual?: EqualityFn<S>,\n): S;\nexport function useStore<T, S>(\n store: Store<T>,\n selector?: Selector<T, S>,\n isEqual: EqualityFn<S> = Object.is,\n): S {\n const committed = useRef<Committed<T, S> | null>(null);\n\n // One memo per [store, selector, isEqual] (React's `useSyncExternalStoreWithSelector`\n // pattern): a render React throws away also throws its memo away, so it cannot change what\n // the committed tree compares against. The memo reuses its selection for the same snapshot,\n // and the previous selection (the committed one first) when `isEqual` says the new one equals\n // it. That keeps the value `useSyncExternalStore` sees stable, so inline selectors never loop.\n const [getSelection, getServerSelection] = useMemo(() => {\n const memoised = (read: () => T) => {\n let last: { snapshot: T; selection: S } | null = null;\n return () => {\n const snapshot = read();\n if (last && Object.is(last.snapshot, snapshot)) return last.selection;\n const next = selector ? selector(snapshot) : (snapshot as unknown as S);\n const previous = last ?? (committed.current?.store === store ? committed.current : null);\n const selection = previous && isEqual(previous.selection, next) ? previous.selection : next;\n last = { snapshot, selection };\n return selection;\n };\n };\n return [memoised(store.getSnapshot), memoised(store.getServerSnapshot)];\n }, [store, selector, isEqual]);\n\n const selection = useSyncExternalStore(store.subscribe, getSelection, getServerSelection);\n useEffect(() => {\n committed.current = { store, selection };\n });\n return selection;\n}\n\n/** `useStore` with an optional selector, for hooks whose own overloads type the result. */\nexport const select = useStore as <T, S>(\n store: Store<T>,\n selector?: (state: T) => S,\n isEqual?: EqualityFn<S>,\n) => S;\n","const isPlain = (value: object) => {\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\n/**\n * One level deep, `Object.is` per value. For selectors that build an object or array: plain\n * objects (same keys), arrays (same items in order), `Date` (same time), `Map` (same keys and\n * values) and `Set` (same members). Any other object (a class instance, a RegExp) is equal only\n * to itself.\n */\nexport function shallowEqual<T>(a: T, b: T): boolean {\n if (Object.is(a, b)) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;\n const left: object = a;\n const right: object = b;\n if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) {\n if (!isPlain(left) || !isPlain(right)) return false;\n } else if (left instanceof Date) {\n return left.getTime() === (right as Date).getTime();\n } else if (left instanceof Map) {\n const other = right as Map<unknown, unknown>;\n if (left.size !== other.size) return false;\n for (const [key, value] of left) {\n if (!other.has(key) || !Object.is(value, other.get(key))) return false;\n }\n return true;\n } else if (left instanceof Set) {\n const other = right as Set<unknown>;\n if (left.size !== other.size) return false;\n for (const value of left) if (!other.has(value)) return false;\n return true;\n } else if (!Array.isArray(left) && !isPlain(left)) {\n return false;\n }\n const leftRecord = left as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n const keys = Object.keys(leftRecord);\n if (keys.length !== Object.keys(rightRecord).length) return false;\n return keys.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(rightRecord, key) &&\n Object.is(leftRecord[key], rightRecord[key]),\n );\n}\n","import {\n createGrowupsellStores,\n type GrowupsellStores,\n type GrowupsellStoresOptions,\n} from '@growupsell/commerce/stores';\nimport {\n createContext,\n useContext,\n useEffect,\n useInsertionEffect,\n useRef,\n type ReactElement,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { host, rethrowAsync } from './host';\nimport { useOwned } from './useOwned';\n\nexport type GrowupsellProviderProps =\n | {\n /** An instance the app created and owns: never disposed by the provider. */\n stores: GrowupsellStores;\n options?: never;\n /** Call `stores.hydrate()` after the first commit. Default true. */\n hydrate?: boolean;\n children?: ReactNode;\n }\n | {\n /**\n * Read once per mount: the provider creates the instance on the first render and disposes\n * it after a real unmount. To switch business, change the provider's `key`. Function\n * options (`onUnauthorized`, `onError`, `merchantToken`) always call the latest prop.\n */\n options: GrowupsellStoresOptions;\n stores?: never;\n hydrate?: boolean;\n children?: ReactNode;\n };\n\nconst GrowupsellContext = createContext<GrowupsellStores | null>(null);\n\n/** Options that identify the instance: changing them needs a new provider (`key`). */\nconst IDENTITY_OPTIONS = ['baseURL', 'businessId', 'platform'] as const;\n\n/** The provider creates at most one instance per mount. */\nconst ONCE: readonly unknown[] = [];\nconst disposeInstance = (stores: GrowupsellStores | null) => stores?.dispose();\n\n/** Replaces the function options with forwarders to the latest props. */\nfunction forwarding(\n options: GrowupsellStoresOptions,\n latest: RefObject<GrowupsellStoresOptions | undefined>,\n): GrowupsellStoresOptions {\n return {\n ...options,\n onUnauthorized: (event) => latest.current?.onUnauthorized?.(event),\n onError: (error) => (latest.current?.onError ?? rethrowAsync)(error),\n merchantToken: () => latest.current?.merchantToken?.() ?? null,\n };\n}\n\n/**\n * Holds one `GrowupsellStores` per mount, hydrates it after the first commit and, when it created\n * the instance, disposes it after a real unmount. Always renders its children.\n */\nexport function GrowupsellProvider(props: GrowupsellProviderProps): ReactElement {\n const { hydrate = true, children } = props;\n const latest = useRef<GrowupsellStoresOptions | undefined>(props.options);\n useInsertionEffect(() => {\n latest.current = props.options;\n });\n\n // Created during the first render: creation does no I/O, so it is safe on the server too.\n // Disposed after a real unmount; an instance created in a render React threw away is disposed\n // at the next commit (`useOwned`).\n const created = useOwned(\n () =>\n props.stores || !props.options\n ? null\n : createGrowupsellStores(forwarding(props.options, latest)),\n ONCE,\n disposeInstance,\n );\n const stores = props.stores ?? created;\n if (!stores) {\n throw new Error('<GrowupsellProvider> needs either `stores` or `options`.');\n }\n\n const initial = useRef(props.options);\n const warned = useRef(false);\n useEffect(() => {\n const first = initial.current;\n const now = props.options;\n if (!first || !now || warned.current) return;\n if (IDENTITY_OPTIONS.some((key) => !Object.is(first[key], now[key]))) {\n warned.current = true;\n host.console.error(\n \"<GrowupsellProvider>: baseURL, businessId and platform are read once. Change the provider's `key` to switch them.\",\n );\n }\n });\n\n // After the first commit, never on the server. Once per instance (StrictMode re-runs effects).\n const hydratedFor = useRef<GrowupsellStores | null>(null);\n useEffect(() => {\n if (!hydrate || hydratedFor.current === stores) return;\n hydratedFor.current = stores;\n void stores.hydrate();\n }, [stores, hydrate]);\n\n return <GrowupsellContext.Provider value={stores}>{children}</GrowupsellContext.Provider>;\n}\n\n/**\n * The instance, or null outside a provider: for shared UI (header, footer) that must still render\n * when the app could not mount one (e.g. the business did not resolve). Render the parts that use\n * other hooks only when it is not null.\n */\nexport function useGrowupsell(options: { optional: true }): GrowupsellStores | null;\n/** The instance: `useGrowupsell().cart.add(...)`. Throws outside a provider. Stable for the mount. */\nexport function useGrowupsell(): GrowupsellStores;\nexport function useGrowupsell(options?: { optional?: boolean }): GrowupsellStores | null {\n const stores = useContext(GrowupsellContext);\n if (!stores && !options?.optional) {\n throw new Error('useGrowupsell must be used inside <GrowupsellProvider>');\n }\n return stores;\n}\n","/** The globals the adapter uses, through `globalThis`: it compiles without DOM or Node types (ADR-009). */\nexport const host = globalThis as unknown as {\n setTimeout(handler: () => void, ms: number): unknown;\n clearTimeout(id: unknown): void;\n console: { error(...data: unknown[]): void };\n};\n\n/** The default for listener and storage errors, as in commerce: rethrown on a later tick. */\nexport function rethrowAsync(error: unknown): void {\n host.setTimeout(() => {\n throw error;\n }, 0);\n}\n","/**\n * `useOwned`: a value a component creates during render and disposes when it is done with it\n * (the provider's instance, per-screen stores). Creating in render keeps the first render, on\n * the server too, able to show the value (creation does no I/O). What makes that safe:\n *\n * - **Mounted** is tracked in an insertion effect. Insertion effects run once per real mount,\n * also in a hidden `<Activity>`, and their cleanup runs once per real unmount: StrictMode's\n * effect double-invoke and `<Activity mode=\"hidden\">` do not touch them (layout and passive\n * effects are disconnected and run again instead). So hiding a subtree keeps its values.\n * - **Created but never mounted** (React threw the render away: StrictMode's second call of a\n * state initializer, a suspended or interrupted render) is disposed at the next commit of any\n * `useOwned`. Those values are held weakly, so the server, which never commits, keeps none.\n * - **Disposed while mounted** (a sweep that ran before a slow render committed, in another\n * root) is replaced in the passive effect, with a re-render.\n * - A real unmount or a new key disposes the old value after a tick, cancelled if the same value\n * mounts again meanwhile (Fast Refresh runs the cleanup and the setup again).\n */\nimport { useEffect, useInsertionEffect, useReducer, useRef, useState } from 'react';\nimport { host } from './host';\n\ninterface Owned<T> {\n value: T;\n readonly key: readonly unknown[];\n readonly dispose: (value: T) => void;\n mounted: boolean;\n disposed: boolean;\n /** The dispose an unmount scheduled; undefined when none is pending. */\n timer: unknown;\n /** Its entry in `unmounted` while not mounted. */\n ref: WeakReference | null;\n}\n\ninterface WeakReference {\n deref(): object | undefined;\n}\n\n/** Values created in render that no commit has mounted yet. Weak: a server render keeps none. */\nconst unmounted = new Set<WeakReference>();\nconst owners = new WeakMap<object, Owned<unknown>>();\nlet pruneAt = 64;\n\nconst weakly = (value: object): WeakReference =>\n typeof WeakRef === 'function' ? new WeakRef(value) : { deref: () => value };\n\nfunction own<T>(value: T, key: readonly unknown[], dispose: (value: T) => void): Owned<T> {\n const entry: Owned<T> = {\n value,\n key,\n dispose,\n mounted: false,\n disposed: false,\n timer: undefined,\n ref: null,\n };\n if (typeof value === 'object' && value !== null) {\n entry.ref = weakly(value);\n owners.set(value, entry as Owned<unknown>);\n unmounted.add(entry.ref);\n if (unmounted.size >= pruneAt) {\n for (const ref of unmounted) if (ref.deref() === undefined) unmounted.delete(ref);\n pruneAt = Math.max(64, unmounted.size * 2);\n }\n }\n return entry;\n}\n\nfunction release(entry: Owned<unknown>): void {\n if (entry.timer !== undefined) host.clearTimeout(entry.timer);\n entry.timer = undefined;\n if (entry.disposed) return;\n entry.disposed = true;\n entry.dispose(entry.value);\n}\n\n/** Disposes every value created in a render that never committed. */\nexport function disposeUnmounted(): void {\n for (const ref of unmounted) {\n unmounted.delete(ref);\n const value = ref.deref();\n const entry = value === undefined ? undefined : owners.get(value);\n if (entry && !entry.mounted) release(entry);\n }\n}\n\nconst sameKey = (a: readonly unknown[], b: readonly unknown[]) =>\n a.length === b.length && a.every((part, i) => Object.is(part, b[i]));\n\n/**\n * One value per `key` (compared part by part), created with `create` during render and disposed\n * with `dispose` after the component is done with it. A new key creates the new value in the\n * same render; the old one is disposed after the commit.\n */\nexport function useOwned<T>(\n create: () => T,\n key: readonly unknown[],\n dispose: (value: T) => void,\n): T {\n const [state, setState] = useState(() => own(create(), key, dispose));\n let entry = state;\n if (!sameKey(entry.key, key)) {\n // React's \"adjust state when a prop changes\": re-renders at once with the new value.\n entry = own(create(), key, dispose);\n setState(entry);\n }\n\n const latestCreate = useRef(create);\n const [, rerender] = useReducer((n: number) => n + 1, 0);\n\n useInsertionEffect(() => {\n latestCreate.current = create;\n });\n\n useInsertionEffect(() => {\n entry.mounted = true;\n if (entry.timer !== undefined) host.clearTimeout(entry.timer);\n entry.timer = undefined;\n if (entry.ref) unmounted.delete(entry.ref);\n return () => {\n if (!entry.disposed && entry.timer === undefined) {\n entry.timer = host.setTimeout(() => release(entry as Owned<unknown>), 0);\n }\n };\n }, [entry]);\n\n useEffect(() => {\n if (entry.disposed) {\n entry.value = latestCreate.current();\n entry.disposed = false;\n rerender();\n }\n // Every insertion effect of this commit has run: what is still unmounted never will be.\n disposeUnmounted();\n }, [entry]);\n\n return entry.value;\n}\n","import type {\n AuthState,\n BusinessState,\n CartState,\n CatalogState,\n CheckoutState,\n GrowupsellStores,\n Identity,\n ReferralState,\n SessionState,\n Store,\n ThemeConfigState,\n WishlistState,\n} from '@growupsell/commerce/stores';\nimport { useGrowupsell } from './provider';\nimport { select, useStore, type EqualityFn } from './useStore';\n\n/** A hook over one store of the instance: the whole snapshot, or a memoised selection. */\nexport interface StoreHook<T> {\n (): T;\n <S>(selector: (state: T) => S, isEqual?: EqualityFn<S>): S;\n}\n\nfunction storeHook<T>(pick: (stores: GrowupsellStores) => Store<T>): StoreHook<T> {\n return function useStoreOfInstance<S>(selector?: (state: T) => S, isEqual?: EqualityFn<S>) {\n return select(pick(useGrowupsell()), selector, isEqual);\n } as StoreHook<T>;\n}\n\nexport const useSession: StoreHook<SessionState> = storeHook((s) => s.session);\nexport const useAuth: StoreHook<AuthState> = storeHook((s) => s.auth);\nexport const useCart: StoreHook<CartState> = storeHook((s) => s.cart);\nexport const useWishlist: StoreHook<WishlistState> = storeHook((s) => s.wishlist);\nexport const useCheckout: StoreHook<CheckoutState> = storeHook((s) => s.checkout);\nexport const useBusiness: StoreHook<BusinessState> = storeHook((s) => s.business);\nexport const useCatalog: StoreHook<CatalogState> = storeHook((s) => s.catalog);\nexport const useThemeConfig: StoreHook<ThemeConfigState> = storeHook((s) => s.themeConfig);\nexport const useReferral: StoreHook<ReferralState> = storeHook((s) => s.referral);\nexport const useIdentity: StoreHook<Identity> = storeHook((s) => s.identity);\n\n/** False on the server and in the first client render; true once stored logins are read. */\nexport function useHydrated(): boolean {\n return useStore(useGrowupsell().hydrated);\n}\n","import type { GrowupsellEvent } from '@growupsell/commerce/stores';\nimport { useEffect, useInsertionEffect, useRef } from 'react';\nimport { useGrowupsell } from './provider';\n\n/** Subscribes after mount (never on the server); always calls the latest `listener`. */\nexport function useGrowupsellEvent<K extends GrowupsellEvent['type']>(\n type: K,\n listener: (event: Extract<GrowupsellEvent, { type: K }>) => void,\n): void {\n const stores = useGrowupsell();\n const latest = useRef(listener);\n useInsertionEffect(() => {\n latest.current = listener;\n });\n useEffect(() => stores.events.on(type, (event) => latest.current(event)), [stores, type]);\n}\n","import type { CheckoutPreview, PaymentOptions } from '@growupsell/commerce/rules';\nimport {\n checkoutPreviewFor,\n paymentOptionsFor,\n type GrowupsellStores,\n type Store,\n} from '@growupsell/commerce/stores';\nimport { useMemo } from 'react';\nimport { useGrowupsell } from './provider';\nimport { shallowEqual } from './shallowEqual';\nimport { useStore } from './useStore';\n\ntype Snapshots<Sources extends readonly Store<unknown>[]> = {\n [I in keyof Sources]: Sources[I] extends Store<infer T> ? T : never;\n};\n\n/**\n * A read-only `Store` over several stores: `compute` runs again only when one of their snapshots\n * changed. The server snapshot is computed from their server snapshots. No logic of its own:\n * `compute` is a commerce selector.\n */\nfunction combine<Sources extends readonly Store<unknown>[], R>(\n sources: Sources,\n compute: (...snapshots: Snapshots<Sources>) => R,\n): Store<R> {\n const memo = (read: (store: Store<unknown>) => unknown) => {\n let last: { inputs: unknown[]; value: R } | null = null;\n return () => {\n const inputs = sources.map(read);\n if (last && inputs.every((input, i) => Object.is(input, last!.inputs[i]))) return last.value;\n last = { inputs, value: compute(...(inputs as Snapshots<Sources>)) };\n return last.value;\n };\n };\n return {\n getSnapshot: memo((store) => store.getSnapshot()),\n getServerSnapshot: memo((store) => store.getServerSnapshot()),\n subscribe(listener) {\n const offs = sources.map((store) => store.subscribe(listener));\n return () => offs.forEach((off) => off());\n },\n };\n}\n\nfunction useDerived<R>(build: (stores: GrowupsellStores) => Store<R>): R {\n const stores = useGrowupsell();\n // One derived store per instance (`build` is a module-level constant).\n const derived = useMemo(() => build(stores), [build, stores]);\n return useStore(derived, (value) => value, shallowEqual);\n}\n\nconst previewStore = (s: GrowupsellStores) =>\n combine([s.cart, s.checkout, s.auth] as const, checkoutPreviewFor);\n\nconst paymentOptionsStore = (s: GrowupsellStores) =>\n combine([s.cart, s.checkout, s.auth, s.business] as const, (cart, checkout, auth, business) =>\n paymentOptionsFor(cart, checkout, auth, business.features),\n );\n\n/** `checkoutPreviewFor(cart, checkout, auth)`; re-renders only when the preview changes (shallow). */\nexport function useCheckoutPreview(): CheckoutPreview | null {\n return useDerived(previewStore);\n}\n\n/** `paymentOptionsFor(cart, checkout, auth, business.features)`; same rule. */\nexport function usePaymentOptions(): PaymentOptions | null {\n return useDerived(paymentOptionsStore);\n}\n","import { parseListingQuery } from '@growupsell/commerce/rules';\nimport type {\n ListingInput,\n ListingState,\n ListingStore,\n ProductDetailInput,\n ProductDetailState,\n ProductDetailStore,\n SearchSuggestionsOptions,\n SearchSuggestionsState,\n SearchSuggestionsStore,\n} from '@growupsell/commerce/stores';\nimport { useEffect, useRef } from 'react';\nimport { useGrowupsell } from './provider';\nimport { useOwned } from './useOwned';\nimport { select, type EqualityFn } from './useStore';\n\n/**\n * Per-screen stores are created during render (no I/O, so the server renders them too, never\n * subscribed and collected with the request's instance) and disposed after unmount (`useOwned`).\n */\nconst disposeStore = (store: { dispose(): void }) => store.dispose();\n\n/**\n * One listing per mount. A later `input.query` change calls `applyQuery` once (no search when\n * equal), with `input.categoryId` as its category when the query names none, so the app can keep\n * the category in its path. A later `input.categoryId` change alone calls `setCategory` (which\n * clears the old category's filters), unless the query names its own category. `pageSize` is\n * read once.\n */\nexport function useListing(input?: ListingInput): [ListingState, ListingStore];\nexport function useListing<S>(\n input: ListingInput | undefined,\n selector: (state: ListingState) => S,\n isEqual?: EqualityFn<S>,\n): [S, ListingStore];\nexport function useListing<S>(\n input?: ListingInput,\n selector?: (state: ListingState) => S,\n isEqual?: EqualityFn<S>,\n): [S | ListingState, ListingStore] {\n const stores = useGrowupsell();\n const store = useOwned(() => stores.createListing(input), [stores], disposeStore);\n\n // Route changes after mount, applied once per commit from both inputs together; the values at\n // creation are already in the store. `input.query` is read through `queryKey`: a new but\n // equal object is no change.\n const queryKey = JSON.stringify(input?.query ?? null);\n const categoryId = input?.categoryId ?? null;\n const applied = useRef({ store, queryKey, categoryId });\n useEffect(() => {\n const last = applied.current;\n applied.current = { store, queryKey, categoryId };\n // A new store was created from this input.\n if (last.store !== store) return;\n const query = input?.query ?? {};\n // A category in the query wins; else the app keeps it in its path (`categoryId`).\n const ownCategory = parseListingQuery(query).categoryId !== null;\n if (last.queryKey !== queryKey) {\n // The query is the whole criteria: its filters belong to the category it comes with.\n const asIs = ownCategory || categoryId === null;\n store.applyQuery(asIs ? query : { ...query, category: String(categoryId) });\n } else if (last.categoryId !== categoryId && !ownCategory) {\n // Same query, other category: its filters belonged to the old one (ADR-025).\n store.setCategory(categoryId);\n }\n }, [store, queryKey, categoryId]);\n\n return [select(store, selector, isEqual), store];\n}\n\n/** Keyed on `productId`: a new id creates a new store; `selectedVariantIds` and `initial` are read at creation. */\nexport function useProductDetail(\n input: ProductDetailInput,\n): [ProductDetailState, ProductDetailStore];\nexport function useProductDetail<S>(\n input: ProductDetailInput,\n selector: (state: ProductDetailState) => S,\n isEqual?: EqualityFn<S>,\n): [S, ProductDetailStore];\nexport function useProductDetail<S>(\n input: ProductDetailInput,\n selector?: (state: ProductDetailState) => S,\n isEqual?: EqualityFn<S>,\n): [S | ProductDetailState, ProductDetailStore] {\n const stores = useGrowupsell();\n const store = useOwned(\n () => stores.createProductDetail(input),\n [stores, input.productId],\n disposeStore,\n );\n return [select(store, selector, isEqual), store];\n}\n\n/** One per mount; `options` read once. */\nexport function useSearchSuggestions(\n options?: SearchSuggestionsOptions,\n): [SearchSuggestionsState, SearchSuggestionsStore];\nexport function useSearchSuggestions<S>(\n options: SearchSuggestionsOptions | undefined,\n selector: (state: SearchSuggestionsState) => S,\n isEqual?: EqualityFn<S>,\n): [S, SearchSuggestionsStore];\nexport function useSearchSuggestions<S>(\n options?: SearchSuggestionsOptions,\n selector?: (state: SearchSuggestionsState) => S,\n isEqual?: EqualityFn<S>,\n): [S | SearchSuggestionsState, SearchSuggestionsStore] {\n const stores = useGrowupsell();\n const store = useOwned(() => stores.createSearchSuggestions(options), [stores], disposeStore);\n return [select(store, selector, isEqual), store];\n}\n"],"mappings":";;;AACA,SAAS,WAAW,SAAS,QAAQ,4BAA4B;AAmB1D,SAAS,SACd,OACA,UACA,UAAyB,OAAO,IAC7B;AACH,QAAM,YAAY,OAA+B,IAAI;AAOrD,QAAM,CAAC,cAAc,kBAAkB,IAAI,QAAQ,MAAM;AACvD,UAAM,WAAW,CAAC,SAAkB;AAClC,UAAI,OAA6C;AACjD,aAAO,MAAM;AACX,cAAM,WAAW,KAAK;AACtB,YAAI,QAAQ,OAAO,GAAG,KAAK,UAAU,QAAQ,EAAG,QAAO,KAAK;AAC5D,cAAM,OAAO,WAAW,SAAS,QAAQ,IAAK;AAC9C,cAAM,WAAW,SAAS,UAAU,SAAS,UAAU,QAAQ,UAAU,UAAU;AACnF,cAAMA,aAAY,YAAY,QAAQ,SAAS,WAAW,IAAI,IAAI,SAAS,YAAY;AACvF,eAAO,EAAE,UAAU,WAAAA,WAAU;AAC7B,eAAOA;AAAA,MACT;AAAA,IACF;AACA,WAAO,CAAC,SAAS,MAAM,WAAW,GAAG,SAAS,MAAM,iBAAiB,CAAC;AAAA,EACxE,GAAG,CAAC,OAAO,UAAU,OAAO,CAAC;AAE7B,QAAM,YAAY,qBAAqB,MAAM,WAAW,cAAc,kBAAkB;AACxF,YAAU,MAAM;AACd,cAAU,UAAU,EAAE,OAAO,UAAU;AAAA,EACzC,CAAC;AACD,SAAO;AACT;AAGO,IAAM,SAAS;;;ACxDtB,IAAM,UAAU,CAAC,UAAkB;AACjC,QAAM,QAAiB,OAAO,eAAe,KAAK;AAClD,SAAO,UAAU,OAAO,aAAa,UAAU;AACjD;AAQO,SAAS,aAAgB,GAAM,GAAe;AACnD,MAAI,OAAO,GAAG,GAAG,CAAC,EAAG,QAAO;AAC5B,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,MAAM,QAAQ,MAAM,KAAM,QAAO;AACvF,QAAM,OAAe;AACrB,QAAM,QAAgB;AACtB,MAAI,OAAO,eAAe,IAAI,MAAM,OAAO,eAAe,KAAK,GAAG;AAChE,QAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,EAAG,QAAO;AAAA,EAChD,WAAW,gBAAgB,MAAM;AAC/B,WAAO,KAAK,QAAQ,MAAO,MAAe,QAAQ;AAAA,EACpD,WAAW,gBAAgB,KAAK;AAC9B,UAAM,QAAQ;AACd,QAAI,KAAK,SAAS,MAAM,KAAM,QAAO;AACrC,eAAW,CAAC,KAAK,KAAK,KAAK,MAAM;AAC/B,UAAI,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,GAAG,OAAO,MAAM,IAAI,GAAG,CAAC,EAAG,QAAO;AAAA,IACnE;AACA,WAAO;AAAA,EACT,WAAW,gBAAgB,KAAK;AAC9B,UAAM,QAAQ;AACd,QAAI,KAAK,SAAS,MAAM,KAAM,QAAO;AACrC,eAAW,SAAS,KAAM,KAAI,CAAC,MAAM,IAAI,KAAK,EAAG,QAAO;AACxD,WAAO;AAAA,EACT,WAAW,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG;AACjD,WAAO;AAAA,EACT;AACA,QAAM,aAAa;AACnB,QAAM,cAAc;AACpB,QAAM,OAAO,OAAO,KAAK,UAAU;AACnC,MAAI,KAAK,WAAW,OAAO,KAAK,WAAW,EAAE,OAAQ,QAAO;AAC5D,SAAO,KAAK;AAAA,IACV,CAAC,QACC,OAAO,UAAU,eAAe,KAAK,aAAa,GAAG,KACrD,OAAO,GAAG,WAAW,GAAG,GAAG,YAAY,GAAG,CAAC;AAAA,EAC/C;AACF;;;AC5CA;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,UAAAC;AAAA,OAIK;;;ACbA,IAAM,OAAO;AAOb,SAAS,aAAa,OAAsB;AACjD,OAAK,WAAW,MAAM;AACpB,UAAM;AAAA,EACR,GAAG,CAAC;AACN;;;ACKA,SAAS,aAAAC,YAAW,oBAAoB,YAAY,UAAAC,SAAQ,gBAAgB;AAoB5E,IAAM,YAAY,oBAAI,IAAmB;AACzC,IAAM,SAAS,oBAAI,QAAgC;AACnD,IAAI,UAAU;AAEd,IAAM,SAAS,CAAC,UACd,OAAO,YAAY,aAAa,IAAI,QAAQ,KAAK,IAAI,EAAE,OAAO,MAAM,MAAM;AAE5E,SAAS,IAAO,OAAU,KAAyB,SAAuC;AACxF,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,IACV,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AACA,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,UAAM,MAAM,OAAO,KAAK;AACxB,WAAO,IAAI,OAAO,KAAuB;AACzC,cAAU,IAAI,MAAM,GAAG;AACvB,QAAI,UAAU,QAAQ,SAAS;AAC7B,iBAAW,OAAO,UAAW,KAAI,IAAI,MAAM,MAAM,OAAW,WAAU,OAAO,GAAG;AAChF,gBAAU,KAAK,IAAI,IAAI,UAAU,OAAO,CAAC;AAAA,IAC3C;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAA6B;AAC5C,MAAI,MAAM,UAAU,OAAW,MAAK,aAAa,MAAM,KAAK;AAC5D,QAAM,QAAQ;AACd,MAAI,MAAM,SAAU;AACpB,QAAM,WAAW;AACjB,QAAM,QAAQ,MAAM,KAAK;AAC3B;AAGO,SAAS,mBAAyB;AACvC,aAAW,OAAO,WAAW;AAC3B,cAAU,OAAO,GAAG;AACpB,UAAM,QAAQ,IAAI,MAAM;AACxB,UAAM,QAAQ,UAAU,SAAY,SAAY,OAAO,IAAI,KAAK;AAChE,QAAI,SAAS,CAAC,MAAM,QAAS,SAAQ,KAAK;AAAA,EAC5C;AACF;AAEA,IAAM,UAAU,CAAC,GAAuB,MACtC,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;AAO9D,SAAS,SACd,QACA,KACA,SACG;AACH,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,MAAM,IAAI,OAAO,GAAG,KAAK,OAAO,CAAC;AACpE,MAAI,QAAQ;AACZ,MAAI,CAAC,QAAQ,MAAM,KAAK,GAAG,GAAG;AAE5B,YAAQ,IAAI,OAAO,GAAG,KAAK,OAAO;AAClC,aAAS,KAAK;AAAA,EAChB;AAEA,QAAM,eAAeC,QAAO,MAAM;AAClC,QAAM,CAAC,EAAE,QAAQ,IAAI,WAAW,CAAC,MAAc,IAAI,GAAG,CAAC;AAEvD,qBAAmB,MAAM;AACvB,iBAAa,UAAU;AAAA,EACzB,CAAC;AAED,qBAAmB,MAAM;AACvB,UAAM,UAAU;AAChB,QAAI,MAAM,UAAU,OAAW,MAAK,aAAa,MAAM,KAAK;AAC5D,UAAM,QAAQ;AACd,QAAI,MAAM,IAAK,WAAU,OAAO,MAAM,GAAG;AACzC,WAAO,MAAM;AACX,UAAI,CAAC,MAAM,YAAY,MAAM,UAAU,QAAW;AAChD,cAAM,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAuB,GAAG,CAAC;AAAA,MACzE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,EAAAC,WAAU,MAAM;AACd,QAAI,MAAM,UAAU;AAClB,YAAM,QAAQ,aAAa,QAAQ;AACnC,YAAM,WAAW;AACjB,eAAS;AAAA,IACX;AAEA,qBAAiB;AAAA,EACnB,GAAG,CAAC,KAAK,CAAC;AAEV,SAAO,MAAM;AACf;;;AFzBS;AAvET,IAAM,oBAAoB,cAAuC,IAAI;AAGrE,IAAM,mBAAmB,CAAC,WAAW,cAAc,UAAU;AAG7D,IAAM,OAA2B,CAAC;AAClC,IAAM,kBAAkB,CAAC,WAAoC,QAAQ,QAAQ;AAG7E,SAAS,WACP,SACA,QACyB;AACzB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,gBAAgB,CAAC,UAAU,OAAO,SAAS,iBAAiB,KAAK;AAAA,IACjE,SAAS,CAAC,WAAW,OAAO,SAAS,WAAW,cAAc,KAAK;AAAA,IACnE,eAAe,MAAM,OAAO,SAAS,gBAAgB,KAAK;AAAA,EAC5D;AACF;AAMO,SAAS,mBAAmB,OAA8C;AAC/E,QAAM,EAAE,UAAU,MAAM,SAAS,IAAI;AACrC,QAAM,SAASC,QAA4C,MAAM,OAAO;AACxE,EAAAC,oBAAmB,MAAM;AACvB,WAAO,UAAU,MAAM;AAAA,EACzB,CAAC;AAKD,QAAM,UAAU;AAAA,IACd,MACE,MAAM,UAAU,CAAC,MAAM,UACnB,OACA,uBAAuB,WAAW,MAAM,SAAS,MAAM,CAAC;AAAA,IAC9D;AAAA,IACA;AAAA,EACF;AACA,QAAM,SAAS,MAAM,UAAU;AAC/B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AAEA,QAAM,UAAUD,QAAO,MAAM,OAAO;AACpC,QAAM,SAASA,QAAO,KAAK;AAC3B,EAAAE,WAAU,MAAM;AACd,UAAM,QAAQ,QAAQ;AACtB,UAAM,MAAM,MAAM;AAClB,QAAI,CAAC,SAAS,CAAC,OAAO,OAAO,QAAS;AACtC,QAAI,iBAAiB,KAAK,CAAC,QAAQ,CAAC,OAAO,GAAG,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG;AACpE,aAAO,UAAU;AACjB,WAAK,QAAQ;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,cAAcF,QAAgC,IAAI;AACxD,EAAAE,WAAU,MAAM;AACd,QAAI,CAAC,WAAW,YAAY,YAAY,OAAQ;AAChD,gBAAY,UAAU;AACtB,SAAK,OAAO,QAAQ;AAAA,EACtB,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAO,QAAS,UAAS;AAC9D;AAUO,SAAS,cAAc,SAA2D;AACvF,QAAM,SAAS,WAAW,iBAAiB;AAC3C,MAAI,CAAC,UAAU,CAAC,SAAS,UAAU;AACjC,UAAM,IAAI,MAAM,wDAAwD;AAAA,EAC1E;AACA,SAAO;AACT;;;AGxGA,SAAS,UAAa,MAA4D;AAChF,SAAO,SAAS,mBAAsB,UAA4B,SAAyB;AACzF,WAAO,OAAO,KAAK,cAAc,CAAC,GAAG,UAAU,OAAO;AAAA,EACxD;AACF;AAEO,IAAM,aAAsC,UAAU,CAAC,MAAM,EAAE,OAAO;AACtE,IAAM,UAAgC,UAAU,CAAC,MAAM,EAAE,IAAI;AAC7D,IAAM,UAAgC,UAAU,CAAC,MAAM,EAAE,IAAI;AAC7D,IAAM,cAAwC,UAAU,CAAC,MAAM,EAAE,QAAQ;AACzE,IAAM,cAAwC,UAAU,CAAC,MAAM,EAAE,QAAQ;AACzE,IAAM,cAAwC,UAAU,CAAC,MAAM,EAAE,QAAQ;AACzE,IAAM,aAAsC,UAAU,CAAC,MAAM,EAAE,OAAO;AACtE,IAAM,iBAA8C,UAAU,CAAC,MAAM,EAAE,WAAW;AAClF,IAAM,cAAwC,UAAU,CAAC,MAAM,EAAE,QAAQ;AACzE,IAAM,cAAmC,UAAU,CAAC,MAAM,EAAE,QAAQ;AAGpE,SAAS,cAAuB;AACrC,SAAO,SAAS,cAAc,EAAE,QAAQ;AAC1C;;;AC1CA,SAAS,aAAAC,YAAW,sBAAAC,qBAAoB,UAAAC,eAAc;AAI/C,SAAS,mBACd,MACA,UACM;AACN,QAAM,SAAS,cAAc;AAC7B,QAAM,SAASC,QAAO,QAAQ;AAC9B,EAAAC,oBAAmB,MAAM;AACvB,WAAO,UAAU;AAAA,EACnB,CAAC;AACD,EAAAC,WAAU,MAAM,OAAO,OAAO,GAAG,MAAM,CAAC,UAAU,OAAO,QAAQ,KAAK,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC;AAC1F;;;ACdA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,WAAAC,gBAAe;AAcxB,SAAS,QACP,SACA,SACU;AACV,QAAM,OAAO,CAAC,SAA6C;AACzD,QAAI,OAA+C;AACnD,WAAO,MAAM;AACX,YAAM,SAAS,QAAQ,IAAI,IAAI;AAC/B,UAAI,QAAQ,OAAO,MAAM,CAAC,OAAO,MAAM,OAAO,GAAG,OAAO,KAAM,OAAO,CAAC,CAAC,CAAC,EAAG,QAAO,KAAK;AACvF,aAAO,EAAE,QAAQ,OAAO,QAAQ,GAAI,MAA6B,EAAE;AACnE,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AACA,SAAO;AAAA,IACL,aAAa,KAAK,CAAC,UAAU,MAAM,YAAY,CAAC;AAAA,IAChD,mBAAmB,KAAK,CAAC,UAAU,MAAM,kBAAkB,CAAC;AAAA,IAC5D,UAAU,UAAU;AAClB,YAAM,OAAO,QAAQ,IAAI,CAAC,UAAU,MAAM,UAAU,QAAQ,CAAC;AAC7D,aAAO,MAAM,KAAK,QAAQ,CAAC,QAAQ,IAAI,CAAC;AAAA,IAC1C;AAAA,EACF;AACF;AAEA,SAAS,WAAc,OAAkD;AACvE,QAAM,SAAS,cAAc;AAE7B,QAAM,UAAUC,SAAQ,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,MAAM,CAAC;AAC5D,SAAO,SAAS,SAAS,CAAC,UAAU,OAAO,YAAY;AACzD;AAEA,IAAM,eAAe,CAAC,MACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,GAAY,kBAAkB;AAEnE,IAAM,sBAAsB,CAAC,MAC3B;AAAA,EAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ;AAAA,EAAY,CAAC,MAAM,UAAU,MAAM,aAChF,kBAAkB,MAAM,UAAU,MAAM,SAAS,QAAQ;AAC3D;AAGK,SAAS,qBAA6C;AAC3D,SAAO,WAAW,YAAY;AAChC;AAGO,SAAS,oBAA2C;AACzD,SAAO,WAAW,mBAAmB;AACvC;;;ACnEA,SAAS,yBAAyB;AAYlC,SAAS,aAAAC,YAAW,UAAAC,eAAc;AASlC,IAAM,eAAe,CAAC,UAA+B,MAAM,QAAQ;AAe5D,SAAS,WACd,OACA,UACA,SACkC;AAClC,QAAM,SAAS,cAAc;AAC7B,QAAM,QAAQ,SAAS,MAAM,OAAO,cAAc,KAAK,GAAG,CAAC,MAAM,GAAG,YAAY;AAKhF,QAAM,WAAW,KAAK,UAAU,OAAO,SAAS,IAAI;AACpD,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,UAAUC,QAAO,EAAE,OAAO,UAAU,WAAW,CAAC;AACtD,EAAAC,WAAU,MAAM;AACd,UAAM,OAAO,QAAQ;AACrB,YAAQ,UAAU,EAAE,OAAO,UAAU,WAAW;AAEhD,QAAI,KAAK,UAAU,MAAO;AAC1B,UAAM,QAAQ,OAAO,SAAS,CAAC;AAE/B,UAAM,cAAc,kBAAkB,KAAK,EAAE,eAAe;AAC5D,QAAI,KAAK,aAAa,UAAU;AAE9B,YAAM,OAAO,eAAe,eAAe;AAC3C,YAAM,WAAW,OAAO,QAAQ,EAAE,GAAG,OAAO,UAAU,OAAO,UAAU,EAAE,CAAC;AAAA,IAC5E,WAAW,KAAK,eAAe,cAAc,CAAC,aAAa;AAEzD,YAAM,YAAY,UAAU;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,OAAO,UAAU,UAAU,CAAC;AAEhC,SAAO,CAAC,OAAO,OAAO,UAAU,OAAO,GAAG,KAAK;AACjD;AAWO,SAAS,iBACd,OACA,UACA,SAC8C;AAC9C,QAAM,SAAS,cAAc;AAC7B,QAAM,QAAQ;AAAA,IACZ,MAAM,OAAO,oBAAoB,KAAK;AAAA,IACtC,CAAC,QAAQ,MAAM,SAAS;AAAA,IACxB;AAAA,EACF;AACA,SAAO,CAAC,OAAO,OAAO,UAAU,OAAO,GAAG,KAAK;AACjD;AAWO,SAAS,qBACd,SACA,UACA,SACsD;AACtD,QAAM,SAAS,cAAc;AAC7B,QAAM,QAAQ,SAAS,MAAM,OAAO,wBAAwB,OAAO,GAAG,CAAC,MAAM,GAAG,YAAY;AAC5F,SAAO,CAAC,OAAO,OAAO,UAAU,OAAO,GAAG,KAAK;AACjD;","names":["selection","useEffect","useInsertionEffect","useRef","useEffect","useRef","useRef","useEffect","useRef","useInsertionEffect","useEffect","useEffect","useInsertionEffect","useRef","useRef","useInsertionEffect","useEffect","useMemo","useMemo","useEffect","useRef","useRef","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growupsell/react",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.4",
4
4
  "description": "React adapter for @growupsell/commerce: provider and hooks. Works on web and React Native.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -24,7 +24,7 @@
24
24
  "test": "vitest run"
25
25
  },
26
26
  "dependencies": {
27
- "@growupsell/commerce": "1.0.0-alpha.2"
27
+ "@growupsell/commerce": "1.0.0-alpha.4"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": "^18.0.0 || ^19.0.0"