@atomic-solutions/woocommerce-react 0.1.0 → 0.1.1
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/hooks/index.cjs +9 -9
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +3 -3
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/{index-BVhiD2zV.d.ts → index-BhXGpIcv.d.ts} +1374 -1374
- package/dist/{index-DKVISMaw.d.cts → index-CVVP-Gph.d.cts} +1374 -1374
- package/dist/index.cjs +12 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/provider/index.cjs +2 -2
- package/dist/provider/index.cjs.map +1 -1
- package/dist/provider/index.d.cts +3 -3
- package/dist/provider/index.d.ts +3 -3
- package/dist/provider/index.js +1 -1
- package/dist/provider/index.js.map +1 -1
- package/dist/{types-wgwJGLQ-.d.cts → types-BDwpAWoN.d.cts} +14 -14
- package/dist/{types-wgwJGLQ-.d.ts → types-BDwpAWoN.d.ts} +14 -14
- package/package.json +1 -1
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/provider/WooCommerceContext.ts","../../src/hooks/useWooCommerceClient.ts","../../src/constants/stale-times.ts","../../src/hooks/useInfiniteWooQuery.ts","../../src/hooks/products.ts","../../src/events/EventContext.ts","../../src/events/types.ts","../../src/hooks/cart.ts","../../src/hooks/checkout.ts","../../src/hooks/orders.ts","../../src/hooks/queryKeys.ts","../../src/provider/WooCommerceStoreContext.ts","../../src/hooks/useStore.ts","../../src/provider/types.ts","../../src/utils/price.ts","../../src/utils/stock.ts","../../src/utils/image.ts","../../src/hooks/useProductsFeed.ts","../../src/hooks/useProductView.ts","../../src/hooks/useCartView.ts"],"names":["createContext","useContext","useQuery","useQueryClient","useMutation","WooCommerceApiError","suffix","useMemo","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * WooCommerce context\n */\n\nimport { createContext } from 'react';\nimport type { WooCommerceClient } from '@atomic-solutions/woocommerce-utils';\n\nimport type { QueryKeys } from '../hooks/queryKeys';\n\n/**\n * WooCommerce context value\n */\nexport interface WooCommerceContextValue {\n client: WooCommerceClient;\n queryKeys: QueryKeys;\n}\n\n/**\n * WooCommerce context for accessing client and query keys from hooks\n */\nexport const WooCommerceContext = createContext<WooCommerceContextValue | null>(null);\n","/**\n * Hook for accessing WooCommerce client and query keys from context\n */\n\nimport { useContext } from 'react';\nimport type { WooCommerceClient } from '@atomic-solutions/woocommerce-utils';\n\nimport { WooCommerceContext } from '../provider/WooCommerceContext';\nimport type { QueryKeys } from './queryKeys';\n\n/**\n * Get WooCommerce client from context\n *\n * @throws {Error} If used outside of WooCommerceProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useWooCommerceClient();\n *\n * // Use client directly\n * const handleClick = async () => {\n * const products = await client.products.list({ per_page: 10 });\n * };\n *\n * return <button onClick={handleClick}>Load Products</button>;\n * }\n * ```\n */\nexport const useWooCommerceClient = (): WooCommerceClient => {\n const context = useContext(WooCommerceContext);\n\n if (!context) {\n throw new Error(\n 'useWooCommerceClient must be used within WooCommerceProvider. ' +\n 'Wrap your app with <WooCommerceProvider client={client} queryKeys={queryKeys}>.'\n );\n }\n\n return context.client;\n};\n\n/**\n * Get WooCommerce query keys from context\n *\n * @throws {Error} If used outside of WooCommerceProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const queryKeys = useWooCommerceQueryKeys();\n * const queryClient = useQueryClient();\n *\n * // Manually invalidate cart queries\n * const handleInvalidate = () => {\n * queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n * };\n *\n * return <button onClick={handleInvalidate}>Refresh Cart</button>;\n * }\n * ```\n */\nexport const useWooCommerceQueryKeys = (): QueryKeys => {\n const context = useContext(WooCommerceContext);\n\n if (!context) {\n throw new Error(\n 'useWooCommerceQueryKeys must be used within WooCommerceProvider. ' +\n 'Wrap your app with <WooCommerceProvider client={client} queryKeys={queryKeys}>.'\n );\n }\n\n return context.queryKeys;\n};\n","/**\n * Query stale time constants (in milliseconds)\n *\n * staleTime: How long data is considered \"fresh\" before React Query\n * will refetch in the background.\n *\n * gcTime (cacheTime): How long inactive data stays in cache before\n * being garbage collected.\n */\n\n/** 1 minute */\nexport const STALE_TIME_SHORT = 60 * 1000;\n\n/** 5 minutes */\nexport const STALE_TIME_MEDIUM = 5 * 60 * 1000;\n\n/** 1 hour */\nexport const STALE_TIME_LONG = 60 * 60 * 1000;\n\n/** Always refetch */\nexport const STALE_TIME_NONE = 0;\n\n/** 5 minutes cache */\nexport const CACHE_TIME_SHORT = 5 * 60 * 1000;\n\n/** 30 minutes cache */\nexport const CACHE_TIME_MEDIUM = 30 * 60 * 1000;\n\n/** 1 hour cache */\nexport const CACHE_TIME_LONG = 60 * 60 * 1000;\n\n/**\n * Domain-specific stale times\n */\nexport const StaleTimes = {\n /** Cart data - always fresh */\n cart: STALE_TIME_NONE,\n\n /** Checkout data - always fresh */\n checkout: STALE_TIME_NONE,\n\n /** Product list - 1 minute */\n products: STALE_TIME_SHORT,\n\n /** Product detail - 1 minute */\n product: STALE_TIME_SHORT,\n\n /** Product categories - always fresh */\n categories: STALE_TIME_NONE,\n\n /** Orders - always fresh */\n orders: STALE_TIME_NONE,\n\n /** Default for infinite queries - 1 hour */\n infinite: STALE_TIME_LONG,\n} as const;\n\n/**\n * Domain-specific cache times (gcTime)\n */\nexport const CacheTimes = {\n /** Cart data - 5 minutes */\n cart: CACHE_TIME_SHORT,\n\n /** Checkout data - 5 minutes */\n checkout: CACHE_TIME_SHORT,\n\n /** Product list - 30 minutes */\n products: CACHE_TIME_MEDIUM,\n\n /** Product detail - 30 minutes */\n product: CACHE_TIME_MEDIUM,\n\n /** Product categories - 1 hour */\n categories: CACHE_TIME_LONG,\n\n /** Orders - 5 minutes */\n orders: CACHE_TIME_SHORT,\n\n /** Default for infinite queries - 30 minutes */\n infinite: CACHE_TIME_MEDIUM,\n} as const;\n","/**\n * Generic infinite query hook for WooCommerce/WordPress paginated endpoints\n *\n * Handles the common pagination pattern used by WooCommerce and WordPress REST APIs:\n * - Uses `page` and `per_page` params\n * - Returns PaginatedResponse with nextPage/prevPage\n * - Automatically flattens pages into a single array\n */\n\nimport type { PaginatedResponse } from '@atomic-solutions/woocommerce-utils';\nimport { useInfiniteQuery, type InfiniteData } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\n\n/**\n * Base params that all paginated endpoints accept\n */\nexport interface InfiniteQueryParams {\n page?: number;\n per_page?: number;\n [key: string]: unknown;\n}\n\n/**\n * Options for useInfiniteWooQuery\n */\nexport interface UseInfiniteWooQueryOptions<TData, TParams extends InfiniteQueryParams> {\n /** Query key for caching */\n queryKey: readonly unknown[];\n\n /** Function to fetch a page of data */\n queryFn: (params: TParams) => Promise<PaginatedResponse<TData>>;\n\n /** Query parameters (excluding page, which is managed internally) */\n params?: Omit<TParams, 'page'>;\n\n /** Items per page (default: 10) */\n perPage?: number;\n\n /** Stale time in milliseconds (default: 1 hour) */\n staleTime?: number;\n\n /** Enable/disable the query */\n enabled?: boolean;\n}\n\n/**\n * Generic infinite query hook for WooCommerce/WordPress APIs\n *\n * @example\n * ```tsx\n * const { data, fetchNextPage, hasNextPage } = useInfiniteWooQuery({\n * queryKey: ['products', { category: 123 }],\n * queryFn: (params) => client.products.list(params),\n * params: { category: 123 },\n * perPage: 20,\n * });\n *\n * // Flattened array of items\n * const items = data ?? [];\n * ```\n */\nexport const useInfiniteWooQuery = <\n TData,\n TParams extends InfiniteQueryParams = InfiniteQueryParams,\n>({\n queryKey,\n queryFn,\n params,\n perPage = 10,\n staleTime = StaleTimes.infinite,\n enabled,\n}: UseInfiniteWooQueryOptions<TData, TParams>) => {\n const query = useInfiniteQuery<\n PaginatedResponse<TData>,\n Error,\n InfiniteData<PaginatedResponse<TData>>,\n readonly unknown[],\n number\n >({\n queryKey,\n queryFn: ({ pageParam }) =>\n queryFn({\n per_page: perPage,\n ...params,\n page: pageParam,\n } as TParams),\n initialPageParam: 1,\n getNextPageParam: (lastPage) => lastPage.pagination.nextPage,\n getPreviousPageParam: (firstPage) => firstPage.pagination.prevPage,\n staleTime,\n enabled,\n });\n\n // Flatten pages into single array\n const flatData = query.data?.pages.flatMap((page) => page.data) ?? [];\n\n return {\n ...query,\n data: flatData, // Override data with flattened array\n };\n};\n","/**\n * Product hooks\n */\n\nimport type { ProductCategory, ProductParams } from '@atomic-solutions/woocommerce-utils';\nimport { useQuery } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useInfiniteWooQuery } from './useInfiniteWooQuery';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\n// Extended type for tree structure\nexport type ProductCategoryTreeNode = ProductCategory & {\n subCategories?: ProductCategoryTreeNode[];\n};\n\n/**\n * Fetch a single page of products\n */\nexport const useProducts = (params?: ProductParams) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.products.list(params),\n queryFn: () => client.products.list(params),\n staleTime: StaleTimes.products,\n });\n};\n\n/**\n * Fetch products with infinite scroll pagination\n *\n * @example\n * ```tsx\n * const { data, fetchNextPage, hasNextPage } = useInfiniteProducts({\n * category: 123,\n * per_page: 20,\n * });\n *\n * // Flattened products array\n * const products = data ?? [];\n *\n * // Load more\n * <Button onPress={() => fetchNextPage()} disabled={!hasNextPage}>\n * Load More\n * </Button>\n * ```\n */\nexport const useInfiniteProducts = (params?: ProductParams) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useInfiniteWooQuery({\n queryKey: queryKeys.products.list(params),\n queryFn: (p) => client.products.list({ ...p, page: p.page ?? 1 } as ProductParams),\n params,\n perPage: params?.per_page ?? 10,\n });\n};\n\nexport const useProduct = (id: number) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.products.detail(id),\n queryFn: () => client.products.get(id),\n staleTime: StaleTimes.product,\n });\n};\n\nexport const useProductCategories = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.products.categories(),\n queryFn: () => client.products.categories(),\n staleTime: StaleTimes.categories,\n });\n};\n\n/**\n * Simple groupBy implementation to avoid ramda dependency\n */\nconst groupBy = <T>(fn: (item: T) => string, list: T[]): Record<string, T[]> => {\n return list.reduce(\n (acc, item) => {\n const key = fn(item);\n if (!acc[key]) {\n acc[key] = [];\n }\n acc[key].push(item);\n return acc;\n },\n {} as Record<string, T[]>\n );\n};\n\nconst processCategoriesToTree = (data: ProductCategory[]): ProductCategoryTreeNode[] => {\n const rootCategories = data?.filter((item) => item.parent === 0);\n const indexedData = groupBy((item) => String(item.parent), data ?? []);\n\n const processCategory = (item: ProductCategory): ProductCategoryTreeNode => ({\n ...item,\n subCategories: indexedData[item.id]?.map(processCategory),\n });\n\n return rootCategories?.map(processCategory) ?? [];\n};\n\n/**\n * Fetch product categories and process them into a tree structure\n *\n * @example\n * ```tsx\n * const { data, treeData, findById } = useProductCategoryTree();\n *\n * // Flat array of categories\n * const flatCategories = data;\n *\n * // Tree structure of categories\n * const categoryTree = treeData;\n *\n * // Find a specific category by ID\n * const category = findById(123);\n * ```\n */\nexport const useProductCategoryTree = () => {\n const query = useProductCategories();\n\n // Flat data from query\n const flatData = query.data ?? [];\n\n // Process into tree structure\n const treeData = processCategoriesToTree(flatData);\n\n // Helper to find category by ID\n const findById = (id?: number | string) => {\n if (!id) return;\n const numId = typeof id === 'string' ? parseInt(id, 10) : id;\n return flatData.find((item) => item.id === numId);\n };\n\n return {\n ...query,\n data: flatData,\n treeData,\n findById,\n };\n};\n","/**\n * Event context for emitting WooCommerce events\n */\n\nimport { createContext, useContext } from 'react';\n\nimport type { WooCommerceEventHandler } from './types';\n\n/**\n * Context for the event emitter function\n */\nexport const EventContext = createContext<WooCommerceEventHandler | null>(null);\n\n/**\n * Hook to get the event emitter from context\n *\n * Returns null if no onEvent handler is configured (which is valid)\n */\nexport const useEventEmitter = (): WooCommerceEventHandler | null => {\n return useContext(EventContext);\n};\n","/**\n * WooCommerce event types\n *\n * Discriminated union types for all store events.\n * Each event type has both success and error variants with proper type inference.\n */\n\nimport type {\n Cart,\n CartItem,\n Checkout,\n StoreApiOrder,\n WooCommerceApiError,\n} from '@atomic-solutions/woocommerce-utils';\n\n/**\n * All possible event types\n */\nexport type WooCommerceEventType =\n | 'cart:item_added'\n | 'cart:item_removed'\n | 'cart:item_updated'\n | 'cart:coupon_applied'\n | 'cart:coupon_removed'\n | 'cart:customer_updated'\n | 'cart:shipping_selected'\n | 'checkout:processed'\n | 'order:fetched';\n\n/**\n * Base success event structure\n */\ninterface BaseSuccessEvent<T extends WooCommerceEventType, D> {\n type: T;\n status: 'success';\n data: D;\n}\n\n/**\n * Base error event structure\n */\ninterface BaseErrorEvent<T extends WooCommerceEventType> {\n type: T;\n status: 'error';\n error: WooCommerceApiError;\n}\n\n// ============================================================================\n// Cart Events\n// ============================================================================\n\n/** Item added to cart */\nexport type CartItemAddedEvent =\n | BaseSuccessEvent<'cart:item_added', { item: CartItem; cart: Cart }>\n | BaseErrorEvent<'cart:item_added'>;\n\n/** Item removed from cart */\nexport type CartItemRemovedEvent =\n | BaseSuccessEvent<'cart:item_removed', { itemKey: string; cart: Cart }>\n | BaseErrorEvent<'cart:item_removed'>;\n\n/** Cart item quantity updated */\nexport type CartItemUpdatedEvent =\n | BaseSuccessEvent<'cart:item_updated', { item: CartItem; cart: Cart }>\n | BaseErrorEvent<'cart:item_updated'>;\n\n/** Coupon applied to cart */\nexport type CartCouponAppliedEvent =\n | BaseSuccessEvent<'cart:coupon_applied', { code: string; cart: Cart }>\n | BaseErrorEvent<'cart:coupon_applied'>;\n\n/** Coupon removed from cart */\nexport type CartCouponRemovedEvent =\n | BaseSuccessEvent<'cart:coupon_removed', { code: string; cart: Cart }>\n | BaseErrorEvent<'cart:coupon_removed'>;\n\n/** Customer billing/shipping updated */\nexport type CartCustomerUpdatedEvent =\n | BaseSuccessEvent<'cart:customer_updated', { cart: Cart }>\n | BaseErrorEvent<'cart:customer_updated'>;\n\n/** Shipping rate selected */\nexport type CartShippingSelectedEvent =\n | BaseSuccessEvent<'cart:shipping_selected', { cart: Cart }>\n | BaseErrorEvent<'cart:shipping_selected'>;\n\n// ============================================================================\n// Checkout Events\n// ============================================================================\n\n/** Checkout processed (order created) */\nexport type CheckoutProcessedEvent =\n | BaseSuccessEvent<'checkout:processed', { checkout: Checkout }>\n | BaseErrorEvent<'checkout:processed'>;\n\n// ============================================================================\n// Order Events\n// ============================================================================\n\n/** Order fetched */\nexport type OrderFetchedEvent =\n | BaseSuccessEvent<'order:fetched', { order: StoreApiOrder }>\n | BaseErrorEvent<'order:fetched'>;\n\n// ============================================================================\n// Union Type\n// ============================================================================\n\n/**\n * All WooCommerce events\n *\n * Use discriminated union pattern for type inference:\n *\n * @example\n * ```typescript\n * onEvent={(event) => {\n * if (event.type === 'cart:item_added') {\n * if (event.status === 'success') {\n * // TypeScript knows: event.data.item is CartItem\n * console.log(event.data.item.name);\n * } else {\n * // TypeScript knows: event.error is WooCommerceError\n * console.log(event.error.message);\n * }\n * }\n * }}\n * ```\n */\nexport type WooCommerceEvent =\n | CartItemAddedEvent\n | CartItemRemovedEvent\n | CartItemUpdatedEvent\n | CartCouponAppliedEvent\n | CartCouponRemovedEvent\n | CartCustomerUpdatedEvent\n | CartShippingSelectedEvent\n | CheckoutProcessedEvent\n | OrderFetchedEvent;\n\n/**\n * Event handler function type\n */\nexport type WooCommerceEventHandler = (event: WooCommerceEvent) => void;\n\n/**\n * Helper to create success events with type inference\n */\nexport function createSuccessEvent<T extends WooCommerceEventType, D>(\n type: T,\n data: D\n): BaseSuccessEvent<T, D> {\n return { type, status: 'success', data };\n}\n\n/**\n * Helper to create error events with type inference\n */\nexport function createErrorEvent<T extends WooCommerceEventType>(\n type: T,\n error: WooCommerceApiError\n): BaseErrorEvent<T> {\n return { type, status: 'error', error };\n}\n","/**\n * Cart hooks\n */\n\nimport {\n WooCommerceApiError,\n type AddToCartInput,\n type CouponInput,\n type RemoveCartItemInput,\n type SelectShippingRateInput,\n type UpdateCartItemInput,\n type UpdateCustomerInput,\n} from '@atomic-solutions/woocommerce-utils';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useEventEmitter } from '../events/EventContext';\nimport { createErrorEvent, createSuccessEvent } from '../events/types';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\nexport const useCart = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n const query = useQuery({\n queryKey: queryKeys.cart.details(),\n queryFn: () => client.cart.get(),\n staleTime: StaleTimes.cart,\n });\n\n const cart = query.data;\n\n /**\n * Check if a product is in the cart\n */\n const isInCart = (productId: number): boolean => {\n return cart?.items.some((item) => item.id === productId) ?? false;\n };\n\n /**\n * Get cart item by product ID\n */\n const getCartItem = (productId: number) => {\n return cart?.items.find((item) => item.id === productId);\n };\n\n /**\n * Get quantity of a product in cart (0 if not in cart)\n */\n const getQuantity = (productId: number): number => {\n return getCartItem(productId)?.quantity ?? 0;\n };\n\n return {\n ...query,\n isInCart,\n getCartItem,\n getQuantity,\n };\n};\n\nexport const useAddToCart = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.addItem(),\n mutationFn: (input: AddToCartInput) => client.cart.addItem(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n // Find the added item (last item with matching product id)\n const addedItem = cart.items.find((item) => item.id === input.id);\n if (emitEvent && addedItem) {\n emitEvent(createSuccessEvent('cart:item_added', { item: addedItem, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:item_added', wooError));\n }\n },\n });\n};\n\nexport const useUpdateCartItem = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.updateItem(),\n mutationFn: (input: UpdateCartItemInput) => client.cart.updateItem(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n const updatedItem = cart.items.find((item) => item.key === input.key);\n if (emitEvent && updatedItem) {\n emitEvent(createSuccessEvent('cart:item_updated', { item: updatedItem, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:item_updated', wooError));\n }\n },\n });\n};\n\nexport const useRemoveFromCart = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.removeItem(),\n mutationFn: (input: RemoveCartItemInput) => client.cart.removeItem(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:item_removed', { itemKey: input.key, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:item_removed', wooError));\n }\n },\n });\n};\n\nexport const useApplyCoupon = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.applyCoupon(),\n mutationFn: (input: CouponInput) => client.cart.applyCoupon(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:coupon_applied', { code: input.code, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:coupon_applied', wooError));\n }\n },\n });\n};\n\nexport const useRemoveCoupon = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.removeCoupon(),\n mutationFn: (input: CouponInput) => client.cart.removeCoupon(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:coupon_removed', { code: input.code, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:coupon_removed', wooError));\n }\n },\n });\n};\n\nexport const useUpdateCustomer = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.updateCustomer(),\n mutationFn: (input: UpdateCustomerInput) => client.cart.updateCustomer(input),\n onSuccess: (cart) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:customer_updated', { cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:customer_updated', wooError));\n }\n },\n });\n};\n\nexport const useSelectShippingRate = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.selectShippingRate(),\n mutationFn: (input: SelectShippingRateInput) => client.cart.selectShippingRate(input),\n onSuccess: (cart) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:shipping_selected', { cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:shipping_selected', wooError));\n }\n },\n });\n};\n","/**\n * Checkout hooks\n */\n\nimport { WooCommerceApiError, type CheckoutInput } from '@atomic-solutions/woocommerce-utils';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useEventEmitter } from '../events/EventContext';\nimport { createErrorEvent, createSuccessEvent } from '../events/types';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\nexport const useCheckout = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.checkout.details(),\n queryFn: () => client.checkout.get(),\n staleTime: StaleTimes.checkout,\n });\n};\n\nexport const useProcessCheckout = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.checkout.mutations.process(),\n mutationFn: (input: CheckoutInput) => client.checkout.process(input),\n onSuccess: (checkout) => {\n // Invalidate cart and checkout queries\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('checkout:processed', { checkout }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('checkout:processed', wooError));\n }\n },\n });\n};\n","/**\n * Order hooks\n */\n\nimport type { GetOrderInput } from '@atomic-solutions/woocommerce-utils';\nimport { useQuery } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\n/**\n * Fetch a single order by ID\n *\n * Supports both authenticated and guest order lookups:\n * - Authenticated: Just pass the order ID\n * - Guest: Pass billing_email + key for guest order verification\n *\n * @example\n * ```tsx\n * // Authenticated user\n * const { data: order } = useOrder({ id: 123 });\n *\n * // Guest order lookup\n * const { data: order } = useOrder({\n * id: 123,\n * billing_email: 'guest@example.com',\n * key: 'wc_order_abc123',\n * });\n * ```\n */\nexport const useOrder = (input: GetOrderInput) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.orders.detail(input.id, input.billing_email, input.key),\n queryFn: () => client.orders.get(input),\n staleTime: StaleTimes.orders,\n });\n};\n","/**\n * Query keys factory\n */\n\nimport type { ProductParams } from '@atomic-solutions/woocommerce-utils';\n\nexport const createQueryKeys = (prefix: string[] = ['woocommerce']) => ({\n // All keys start with prefix\n all: prefix as readonly string[],\n\n // Products\n products: {\n all: [...prefix, 'products'] as const,\n lists: () => [...prefix, 'products', 'list'] as const,\n list: (params?: ProductParams) => [...prefix, 'products', 'list', params] as const,\n details: () => [...prefix, 'products', 'detail'] as const,\n detail: (id: number) => [...prefix, 'products', 'detail', id] as const,\n categories: () => [...prefix, 'products', 'categories'] as const,\n },\n\n // Cart\n cart: {\n all: [...prefix, 'cart'] as const,\n details: () => [...prefix, 'cart', 'details'] as const,\n // Mutation keys\n mutations: {\n addItem: () => [...prefix, 'cart', 'mutation', 'addItem'] as const,\n updateItem: () => [...prefix, 'cart', 'mutation', 'updateItem'] as const,\n removeItem: () => [...prefix, 'cart', 'mutation', 'removeItem'] as const,\n applyCoupon: () => [...prefix, 'cart', 'mutation', 'applyCoupon'] as const,\n removeCoupon: () => [...prefix, 'cart', 'mutation', 'removeCoupon'] as const,\n updateCustomer: () => [...prefix, 'cart', 'mutation', 'updateCustomer'] as const,\n selectShippingRate: () => [...prefix, 'cart', 'mutation', 'selectShippingRate'] as const,\n },\n },\n\n // Checkout\n checkout: {\n all: [...prefix, 'checkout'] as const,\n details: () => [...prefix, 'checkout', 'details'] as const,\n // Mutation keys\n mutations: {\n process: () => [...prefix, 'checkout', 'mutation', 'process'] as const,\n },\n },\n\n // Orders\n orders: {\n all: [...prefix, 'orders'] as const,\n lists: () => [...prefix, 'orders', 'list'] as const,\n list: (params?: Record<string, unknown>) => [...prefix, 'orders', 'list', params] as const,\n details: () => [...prefix, 'orders', 'detail'] as const,\n detail: (id: number, billing_email?: string, key?: string) =>\n [...prefix, 'orders', 'detail', id, billing_email, key].filter(Boolean) as readonly (\n | string\n | number\n )[],\n },\n});\n\nexport type QueryKeys = ReturnType<typeof createQueryKeys>;\n","import { createContext } from 'react';\n\nimport type { StoreContextValue } from './types';\n\n/**\n * Context for accessing store configuration and state\n *\n * @internal Use the useStore hook instead of accessing this directly\n */\nexport const WooCommerceStoreContext = createContext<StoreContextValue | null>(null);\n\nWooCommerceStoreContext.displayName = 'WooCommerceStoreContext';\n","import { useContext, useMemo } from 'react';\n\nimport type { StoreContextValue, StoreTheme } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\n\n/**\n * Hook to access the store configuration and state\n *\n * Must be used within a WooCommerceStoreProvider\n *\n * @returns Store context value with config, validation state, and utilities\n * @throws Error if used outside of WooCommerceStoreProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { config, isValidated, validationError, revalidate } = useStore();\n *\n * if (!isValidated) {\n * return <Text>Connecting to store...</Text>;\n * }\n *\n * return <Text>Connected to: {config.storeUrl}</Text>;\n * }\n * ```\n */\nexport function useStore(): StoreContextValue {\n const context = useContext(WooCommerceStoreContext);\n\n if (!context) {\n throw new Error('useStore must be used within a WooCommerceStoreProvider');\n }\n\n return context;\n}\n\n/**\n * Hook to access store features configuration\n *\n * @returns Store features configuration\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const features = useStoreFeatures();\n *\n * return (\n * <View>\n * {features.search && <SearchBar />}\n * {features.categories && <CategoryNav />}\n * </View>\n * );\n * }\n * ```\n */\nexport function useStoreFeatures() {\n const { config } = useStore();\n return config.features!;\n}\n\n/**\n * Hook to access store locale/currency configuration\n *\n * @returns Store locale configuration\n *\n * @example\n * ```tsx\n * function PriceDisplay({ price }: { price: number }) {\n * const locale = useStoreLocale();\n * const formatted = formatPrice(price, locale);\n * return <Text>{formatted}</Text>;\n * }\n * ```\n */\nexport function useStoreLocale() {\n const { config } = useStore();\n return config.locale!;\n}\n\n/**\n * Resolved theme values with all required properties\n */\nexport interface ResolvedStoreTheme {\n /** Primary brand color */\n primary: string;\n /** Secondary brand color */\n secondary: string;\n /** Color mode */\n mode: 'light' | 'dark' | 'auto';\n /** Custom fonts */\n fonts: {\n heading: string | undefined;\n body: string | undefined;\n };\n}\n\n/**\n * Default theme values when no theme is configured\n */\nconst DEFAULT_THEME: ResolvedStoreTheme = {\n primary: '#007AFF', // iOS blue\n secondary: '#5856D6', // iOS purple\n mode: 'auto',\n fonts: {\n heading: undefined,\n body: undefined,\n },\n};\n\n/**\n * External theme values that can be merged with store theme\n * This allows integration with external theme providers (e.g., react-native-paper, tamagui)\n */\nexport interface ExternalThemeValues {\n primary?: string;\n secondary?: string;\n mode?: 'light' | 'dark' | 'auto';\n fonts?: {\n heading?: string;\n body?: string;\n };\n}\n\n/**\n * Options for useStoreTheme hook\n */\nexport interface UseStoreThemeOptions {\n /**\n * External theme values to merge with store theme\n * These take precedence over store config values\n *\n * @example\n * ```tsx\n * // With react-native-paper\n * const paperTheme = usePaperTheme();\n * const { theme } = useStoreTheme({\n * externalTheme: {\n * primary: paperTheme.colors.primary,\n * mode: paperTheme.dark ? 'dark' : 'light',\n * },\n * });\n * ```\n */\n externalTheme?: ExternalThemeValues;\n}\n\n/**\n * Return type for useStoreTheme hook\n */\nexport interface UseStoreThemeReturn {\n /** Resolved theme values */\n theme: ResolvedStoreTheme;\n /** Raw store theme config (may have undefined values) */\n storeTheme: StoreTheme | undefined;\n /** Whether external theme was provided */\n hasExternalTheme: boolean;\n}\n\n/**\n * Hook for accessing and merging store theme configuration\n *\n * This hook resolves theme values from multiple sources in order of precedence:\n * 1. External theme (from app's ThemeProvider via options)\n * 2. Store config theme (from WooCommerceStoreProvider)\n * 3. Default theme values\n *\n * Works both with and without WooCommerceStoreProvider context.\n *\n * @example\n * ```tsx\n * // Basic usage - uses store config or defaults\n * function ProductCard({ product }) {\n * const { theme } = useStoreTheme();\n *\n * return (\n * <View style={{ borderColor: theme.primary }}>\n * <Text style={{ fontFamily: theme.fonts.heading }}>\n * {product.name}\n * </Text>\n * </View>\n * );\n * }\n *\n * // Integration with external theme provider\n * function ThemedProductCard({ product }) {\n * const appTheme = useAppTheme(); // Your app's theme hook\n * const { theme } = useStoreTheme({\n * externalTheme: {\n * primary: appTheme.colors.brand,\n * secondary: appTheme.colors.accent,\n * mode: appTheme.isDark ? 'dark' : 'light',\n * },\n * });\n *\n * return (\n * <View style={{ borderColor: theme.primary }}>\n * {product.name}\n * </View>\n * );\n * }\n * ```\n */\nexport function useStoreTheme(options: UseStoreThemeOptions = {}): UseStoreThemeReturn {\n const { externalTheme } = options;\n\n // Get store theme from context (may be undefined if no provider)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeTheme = storeContext?.config?.theme;\n\n // Resolve theme with precedence: external > store config > defaults\n const theme = useMemo<ResolvedStoreTheme>(() => {\n return {\n primary: externalTheme?.primary ?? storeTheme?.primary ?? DEFAULT_THEME.primary,\n secondary: externalTheme?.secondary ?? storeTheme?.secondary ?? DEFAULT_THEME.secondary,\n mode: externalTheme?.mode ?? storeTheme?.mode ?? DEFAULT_THEME.mode,\n fonts: {\n heading:\n externalTheme?.fonts?.heading ??\n storeTheme?.fonts?.heading ??\n DEFAULT_THEME.fonts.heading,\n body: externalTheme?.fonts?.body ?? storeTheme?.fonts?.body ?? DEFAULT_THEME.fonts.body,\n },\n };\n }, [externalTheme, storeTheme]);\n\n return {\n theme,\n storeTheme,\n hasExternalTheme: !!externalTheme,\n };\n}\n\n/**\n * Type guard hook to check if running in a WooCommerceStoreProvider context\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * if (!useIsInStoreContext()) {\n * throw new Error('MyComponent must be used within WooCommerceStoreProvider');\n * }\n * // ... component logic\n * }\n * ```\n */\nexport function useIsInStoreContext(): boolean {\n const context = useContext(WooCommerceStoreContext);\n return context !== null;\n}\n","import type { WooCommerceEventHandler } from '../events/types';\n\n/**\n * Store feature configuration\n */\nexport interface StoreFeatures {\n /** Enable authentication screens (default: false) */\n auth?: boolean;\n /** Enable wishlist functionality (default: false) */\n wishlist?: boolean;\n /** Show product reviews (default: true) */\n reviews?: boolean;\n /** Enable search functionality (default: true) */\n search?: boolean;\n /** Show category navigation (default: true) */\n categories?: boolean;\n}\n\n/**\n * Theme configuration for the store\n */\nexport interface StoreTheme {\n /** Primary brand color (e.g., \"#007AFF\") */\n primary?: string;\n /** Secondary brand color */\n secondary?: string;\n /** Color mode */\n mode?: 'light' | 'dark' | 'auto';\n /** Custom fonts */\n fonts?: {\n heading?: string;\n body?: string;\n };\n}\n\n/**\n * Localization and currency configuration\n */\nexport interface StoreLocale {\n /** BCP 47 locale tag for Intl formatting (e.g., \"en-US\", \"bs-BA\") */\n localeTag?: string;\n /** Currency code (e.g., \"USD\", \"EUR\", \"BAM\") */\n currency?: string;\n /** Currency symbol position */\n currencyPosition?: 'before' | 'after';\n /** Thousands separator (e.g., \",\") */\n thousandsSeparator?: string;\n /** Decimal separator (e.g., \".\") */\n decimalSeparator?: string;\n /** Number of decimal places */\n decimals?: number;\n}\n\n/**\n * Function to transform image URLs (e.g., for custom sizing, CDN, optimization)\n */\nexport type ImageUrlTransformer = (\n url: string,\n size: 'thumbnail' | 'medium' | 'large' | 'full'\n) => string;\n\n/**\n * Rate limiting configuration\n */\nexport interface RateLimitConfig {\n /** Maximum requests per minute (default: 60) */\n requestsPerMinute?: number;\n /** Maximum requests per second (default: 10) */\n requestsPerSecond?: number;\n /** Burst limit for temporary spikes (default: 20) */\n burstLimit?: number;\n}\n\n/**\n * Guardrails configuration to prevent abuse\n */\nexport interface StoreGuardrails {\n /** Validate that the URL is a valid WooCommerce store (default: true) */\n validateStore?: boolean;\n /** Rate limiting configuration */\n rateLimit?: RateLimitConfig;\n /** Optional license key for production usage tracking */\n licenseKey?: string;\n}\n\n/**\n * Store validation result\n */\nexport interface StoreValidationResult {\n /** Whether the store is valid */\n valid: boolean;\n /** Store name (if available) */\n storeName?: string;\n /** Normalized store URL */\n storeUrl?: string;\n /** WooCommerce version (if detectable) */\n wcVersion?: string;\n /** Error message if validation failed */\n error?: string;\n}\n\n/**\n * Main store configuration\n */\nexport interface StoreConfig {\n /**\n * WooCommerce store URL\n * @example \"https://mystore.com\" or \"https://mystore.com/wp-json\"\n */\n storeUrl: string;\n\n /** Feature toggles */\n features?: StoreFeatures;\n\n /** Theme customization */\n theme?: StoreTheme;\n\n /** Localization settings */\n locale?: StoreLocale;\n\n /** Guardrails configuration */\n guardrails?: StoreGuardrails;\n\n /** Event handler for WooCommerce events */\n onEvent?: WooCommerceEventHandler;\n\n /** Enable debug logging (default: false in production) */\n debug?: boolean;\n\n /**\n * Custom image URL transformer for optimization\n * Use this to add CDN prefixes, size suffixes, or custom transformations\n *\n * @example\n * ```ts\n * imageUrlTransformer: (url, size) => {\n * // Add PNG optimization for ma-native\n * if (url.endsWith('.png') && !url.includes('unnamed.png')) {\n * return url.replace('.png', '-300x300.png');\n * }\n * return url;\n * }\n * ```\n */\n imageUrlTransformer?: ImageUrlTransformer;\n\n /** Fallback image URL when products have no images */\n fallbackImageUrl?: string;\n}\n\n/**\n * Store context value available via useStore hook\n */\nexport interface StoreContextValue {\n /** Current store configuration */\n config: StoreConfig;\n /** Whether the store has been validated */\n isValidated: boolean;\n /** Whether validation is in progress */\n isValidating: boolean;\n /** Validation error (if any) */\n validationError?: string;\n /** Store validation result */\n validationResult?: StoreValidationResult;\n /** Re-validate the store connection */\n revalidate: () => Promise<void>;\n}\n\n/**\n * Default store configuration values\n */\nexport const DEFAULT_STORE_CONFIG: Required<\n Pick<StoreConfig, 'features' | 'locale' | 'guardrails' | 'debug'>\n> = {\n features: {\n auth: false,\n wishlist: false,\n reviews: true,\n search: true,\n categories: true,\n },\n locale: {\n localeTag: 'en-US',\n currency: 'USD',\n currencyPosition: 'before',\n thousandsSeparator: ',',\n decimalSeparator: '.',\n decimals: 2,\n },\n guardrails: {\n validateStore: true,\n rateLimit: {\n requestsPerMinute: 60,\n requestsPerSecond: 10,\n burstLimit: 20,\n },\n },\n debug: process.env.NODE_ENV !== 'production',\n};\n","import type { StoreLocale } from '../provider/types';\n\n/**\n * Default locale configuration for price formatting\n */\nconst DEFAULT_LOCALE: Required<StoreLocale> = {\n localeTag: 'en-US',\n currency: 'USD',\n currencyPosition: 'before',\n thousandsSeparator: ',',\n decimalSeparator: '.',\n decimals: 2,\n};\n\n/**\n * Currency symbols for common currencies\n */\nconst CURRENCY_SYMBOLS: Record<string, string> = {\n USD: '$',\n EUR: '€',\n GBP: '£',\n CAD: 'CA$',\n AUD: 'A$',\n JPY: '¥',\n CNY: '¥',\n INR: '₹',\n BRL: 'R$',\n MXN: 'MX$',\n RUB: '₽',\n KRW: '₩',\n CHF: 'CHF',\n SEK: 'kr',\n NOK: 'kr',\n DKK: 'kr',\n PLN: 'zł',\n TRY: '₺',\n ZAR: 'R',\n NZD: 'NZ$',\n SGD: 'S$',\n HKD: 'HK$',\n THB: '฿',\n PHP: '₱',\n // Balkans\n BAM: 'KM',\n RSD: 'din',\n HRK: 'kn',\n MKD: 'ден',\n BGN: 'лв',\n RON: 'lei',\n};\n\n/**\n * Get the currency symbol for a currency code\n *\n * @param currencyCode - ISO 4217 currency code\n * @returns Currency symbol or the code itself if not found\n */\nexport function getCurrencySymbol(currencyCode: string): string {\n return CURRENCY_SYMBOLS[currencyCode.toUpperCase()] ?? currencyCode;\n}\n\n/**\n * Format a number with the specified locale settings\n *\n * @param value - Number to format\n * @param locale - Locale configuration\n * @returns Formatted number string\n */\nfunction formatNumber(value: number, locale: Required<StoreLocale>): string {\n const fixed = value.toFixed(locale.decimals);\n const [integerPart, decimalPart] = fixed.split('.');\n\n // Add thousands separators\n const formattedInteger = integerPart!.replace(/\\B(?=(\\d{3})+(?!\\d))/g, locale.thousandsSeparator);\n\n if (locale.decimals > 0 && decimalPart) {\n return `${formattedInteger}${locale.decimalSeparator}${decimalPart}`;\n }\n\n return formattedInteger;\n}\n\n/**\n * Format a price with currency symbol\n *\n * @param price - Price value (can be string or number)\n * @param locale - Locale configuration (optional)\n * @returns Formatted price string\n *\n * @example\n * formatPrice(99.99) // \"$99.99\"\n * formatPrice(99.99, { currency: \"EUR\", currencyPosition: \"after\" }) // \"99.99€\"\n * formatPrice(\"1234.50\", { currency: \"BAM\" }) // \"KM1,234.50\"\n */\nexport function formatPrice(price: string | number, locale: Partial<StoreLocale> = {}): string {\n const mergedLocale = { ...DEFAULT_LOCALE, ...locale };\n const numericPrice = typeof price === 'string' ? parseFloat(price) : price;\n\n if (isNaN(numericPrice)) {\n return '';\n }\n\n const symbol = getCurrencySymbol(mergedLocale.currency);\n const formattedNumber = formatNumber(numericPrice, mergedLocale);\n\n if (mergedLocale.currencyPosition === 'after') {\n return `${formattedNumber}${symbol}`;\n }\n\n return `${symbol}${formattedNumber}`;\n}\n\n/**\n * Format a price range (e.g., for variable products)\n *\n * @param minPrice - Minimum price\n * @param maxPrice - Maximum price\n * @param locale - Locale configuration\n * @returns Formatted price range string\n *\n * @example\n * formatPriceRange(10, 50) // \"$10.00 - $50.00\"\n * formatPriceRange(10, 10) // \"$10.00\" (same price, no range)\n */\nexport function formatPriceRange(\n minPrice: string | number,\n maxPrice: string | number,\n locale: Partial<StoreLocale> = {}\n): string {\n const min = typeof minPrice === 'string' ? parseFloat(minPrice) : minPrice;\n const max = typeof maxPrice === 'string' ? parseFloat(maxPrice) : maxPrice;\n\n if (isNaN(min) || isNaN(max)) {\n return '';\n }\n\n // If same price, just return single price\n if (min === max) {\n return formatPrice(min, locale);\n }\n\n return `${formatPrice(min, locale)} - ${formatPrice(max, locale)}`;\n}\n\n/**\n * Calculate discount percentage\n *\n * @param regularPrice - Original price\n * @param salePrice - Sale price\n * @returns Discount percentage (0-100) or null if no discount\n *\n * @example\n * calculateDiscount(100, 80) // 20\n * calculateDiscount(50, 50) // null\n */\nexport function calculateDiscount(\n regularPrice: string | number,\n salePrice: string | number\n): number | null {\n const regular = typeof regularPrice === 'string' ? parseFloat(regularPrice) : regularPrice;\n const sale = typeof salePrice === 'string' ? parseFloat(salePrice) : salePrice;\n\n if (isNaN(regular) || isNaN(sale) || regular <= 0 || sale >= regular) {\n return null;\n }\n\n return Math.round(((regular - sale) / regular) * 100);\n}\n\n/**\n * Format a price from WooCommerce Store API (minor units/cents)\n *\n * WooCommerce Store API returns prices as strings in minor units (cents).\n * This function converts and formats them properly.\n *\n * @param priceInMinorUnits - Price in minor units (e.g., \"9999\" for $99.99)\n * @param currencyCode - ISO 4217 currency code (e.g., \"USD\", \"BAM\")\n * @param locale - Additional locale configuration\n * @returns Formatted price string, or \"-\" if invalid\n *\n * @example\n * formatStoreApiPrice(\"9999\", \"USD\") // \"$99.99\"\n * formatStoreApiPrice(\"12345\", \"BAM\") // \"KM123.45\"\n * formatStoreApiPrice(undefined, \"USD\") // \"-\"\n */\nexport function formatStoreApiPrice(\n priceInMinorUnits: string | undefined | null,\n currencyCode: string | undefined | null,\n locale: Partial<Omit<StoreLocale, 'currency'>> = {}\n): string {\n if (!priceInMinorUnits || !currencyCode) {\n return '-';\n }\n\n const cents = parseInt(priceInMinorUnits, 10);\n if (isNaN(cents)) {\n return '-';\n }\n\n const decimalPrice = cents / 100;\n return formatPrice(decimalPrice, { ...locale, currency: currencyCode });\n}\n\n/**\n * Format a discount badge string\n *\n * @param regularPrice - Original price\n * @param salePrice - Sale price\n * @returns Formatted discount string or null\n *\n * @example\n * formatDiscountBadge(100, 80) // \"-20%\"\n * formatDiscountBadge(50, 50) // null\n */\nexport function formatDiscountBadge(\n regularPrice: string | number,\n salePrice: string | number\n): string | null {\n const discount = calculateDiscount(regularPrice, salePrice);\n return discount ? `-${discount}%` : null;\n}\n\n/**\n * Format a price from WooCommerce Store API using Intl.NumberFormat\n *\n * Uses the browser/runtime's Intl.NumberFormat for locale-aware formatting.\n * This is useful when you need formatting that matches the user's locale.\n *\n * @param priceInMinorUnits - Price in minor units (e.g., \"9999\" for $99.99)\n * @param currencyCode - ISO 4217 currency code (e.g., \"USD\", \"BAM\")\n * @param localeTag - BCP 47 locale tag (e.g., \"en-US\", \"bs-BA\")\n * @returns Formatted price string, or \"-\" if invalid\n *\n * @example\n * formatStoreApiPriceIntl(\"9999\", \"USD\", \"en-US\") // \"$99.99\"\n * formatStoreApiPriceIntl(\"9999\", \"BAM\", \"bs-BA\") // \"99,99 KM\"\n * formatStoreApiPriceIntl(undefined, \"USD\") // \"-\"\n */\nexport function formatStoreApiPriceIntl(\n priceInMinorUnits: string | undefined | null,\n currencyCode: string | undefined | null,\n localeTag: string = 'en-US'\n): string {\n if (!priceInMinorUnits || !currencyCode) {\n return '-';\n }\n\n const cents = parseInt(priceInMinorUnits, 10);\n if (isNaN(cents)) {\n return '-';\n }\n\n const decimalPrice = cents / 100;\n\n try {\n const formatter = new Intl.NumberFormat(localeTag, {\n style: 'currency',\n currency: currencyCode,\n });\n return formatter.format(decimalPrice);\n } catch {\n // Fallback to basic formatting if Intl fails\n return formatPrice(decimalPrice, { currency: currencyCode });\n }\n}\n\n/**\n * Parse a WooCommerce price string to number\n * Handles various formats like \"99.99\", \"$99.99\", \"99,99€\"\n *\n * @param priceString - Price string from WooCommerce\n * @returns Parsed number or NaN if invalid\n */\nexport function parseWooCommercePrice(priceString: string): number {\n if (!priceString || typeof priceString !== 'string') {\n return NaN;\n }\n\n // Remove currency symbols and whitespace\n const cleaned = priceString.replace(/[^\\d.,-]/g, '').trim();\n\n // Handle European format (1.234,56 -> 1234.56)\n if (cleaned.includes(',') && cleaned.includes('.')) {\n // Determine which is the decimal separator (last one)\n const lastComma = cleaned.lastIndexOf(',');\n const lastDot = cleaned.lastIndexOf('.');\n\n if (lastComma > lastDot) {\n // European: 1.234,56\n return parseFloat(cleaned.replace(/\\./g, '').replace(',', '.'));\n } else {\n // US: 1,234.56\n return parseFloat(cleaned.replace(/,/g, ''));\n }\n }\n\n // Only comma (could be decimal or thousands)\n if (cleaned.includes(',') && !cleaned.includes('.')) {\n // If comma is in last 3 positions and has 1-2 digits after, treat as decimal\n const commaPos = cleaned.lastIndexOf(',');\n const afterComma = cleaned.length - commaPos - 1;\n\n if (afterComma <= 2) {\n return parseFloat(cleaned.replace(',', '.'));\n }\n // Otherwise treat as thousands separator\n return parseFloat(cleaned.replace(/,/g, ''));\n }\n\n // Standard format or just dots\n return parseFloat(cleaned.replace(/,/g, ''));\n}\n","/**\n * Stock status types from WooCommerce\n */\nexport type StockStatus = 'instock' | 'outofstock' | 'onbackorder';\n\n/**\n * Stock display configuration\n */\nexport interface StockDisplayConfig {\n /** Text to show for in-stock items */\n inStockText?: string;\n /** Text to show for out-of-stock items */\n outOfStockText?: string;\n /** Text to show for backorder items */\n backorderText?: string;\n /** Whether to show quantity when in stock */\n showQuantity?: boolean;\n /** Threshold below which to show \"low stock\" warning */\n lowStockThreshold?: number;\n /** Text template for low stock (use {quantity} placeholder) */\n lowStockText?: string;\n}\n\nconst DEFAULT_CONFIG: Required<StockDisplayConfig> = {\n inStockText: 'In Stock',\n outOfStockText: 'Out of Stock',\n backorderText: 'Available on Backorder',\n showQuantity: false,\n lowStockThreshold: 5,\n lowStockText: 'Only {quantity} left',\n};\n\n/**\n * Get human-readable stock status text\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity (optional)\n * @param config - Display configuration\n * @returns Stock status text\n *\n * @example\n * getStockStatusText('instock') // \"In Stock\"\n * getStockStatusText('instock', 3, { lowStockThreshold: 5 }) // \"Only 3 left\"\n * getStockStatusText('outofstock') // \"Out of Stock\"\n */\nexport function getStockStatusText(\n status: StockStatus,\n quantity?: number | null,\n config: StockDisplayConfig = {}\n): string {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n\n switch (status) {\n case 'instock':\n // Check for low stock\n if (\n quantity !== null &&\n quantity !== undefined &&\n quantity <= mergedConfig.lowStockThreshold &&\n quantity > 0\n ) {\n return mergedConfig.lowStockText.replace('{quantity}', quantity.toString());\n }\n\n // Show quantity if enabled\n if (mergedConfig.showQuantity && quantity !== null && quantity !== undefined) {\n return `${mergedConfig.inStockText} (${quantity})`;\n }\n\n return mergedConfig.inStockText;\n\n case 'outofstock':\n return mergedConfig.outOfStockText;\n\n case 'onbackorder':\n return mergedConfig.backorderText;\n\n default:\n return mergedConfig.inStockText;\n }\n}\n\n/**\n * Check if a product is purchasable based on stock status\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity\n * @param manageStock - Whether stock is managed for this product\n * @returns Whether the product can be purchased\n */\nexport function isPurchasable(\n status: StockStatus,\n quantity?: number | null,\n manageStock = true\n): boolean {\n // Out of stock is never purchasable\n if (status === 'outofstock') {\n return false;\n }\n\n // Backorder is purchasable\n if (status === 'onbackorder') {\n return true;\n }\n\n // In stock - check quantity if managed\n if (manageStock && quantity !== null && quantity !== undefined) {\n return quantity > 0;\n }\n\n return true;\n}\n\n/**\n * Get stock status severity for styling\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity\n * @param lowStockThreshold - Threshold for low stock warning\n * @returns Severity level for styling\n */\nexport function getStockSeverity(\n status: StockStatus,\n quantity?: number | null,\n lowStockThreshold = 5\n): 'success' | 'warning' | 'error' | 'info' {\n switch (status) {\n case 'outofstock':\n return 'error';\n\n case 'onbackorder':\n return 'info';\n\n case 'instock':\n if (\n quantity !== null &&\n quantity !== undefined &&\n quantity <= lowStockThreshold &&\n quantity > 0\n ) {\n return 'warning';\n }\n return 'success';\n\n default:\n return 'info';\n }\n}\n\n/**\n * Check if stock is low based on threshold\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity\n * @param threshold - Low stock threshold (default: 5)\n * @returns Whether stock is considered low\n */\nexport function isLowStock(status: StockStatus, quantity?: number | null, threshold = 5): boolean {\n return (\n status === 'instock' &&\n quantity !== null &&\n quantity !== undefined &&\n quantity <= threshold &&\n quantity > 0\n );\n}\n\n/**\n * Calculate max quantity that can be added to cart\n *\n * @param status - WooCommerce stock status\n * @param stockQuantity - Available stock\n * @param cartQuantity - Quantity already in cart\n * @param maxPurchaseQuantity - Maximum allowed purchase quantity (optional)\n * @returns Maximum quantity that can be added\n */\nexport function getMaxAddToCartQuantity(\n status: StockStatus,\n stockQuantity?: number | null,\n cartQuantity = 0,\n maxPurchaseQuantity?: number | null\n): number {\n // Out of stock - can't add any\n if (status === 'outofstock') {\n return 0;\n }\n\n // Backorder - theoretically unlimited, use max purchase qty or default high number\n if (status === 'onbackorder') {\n return maxPurchaseQuantity ?? 999;\n }\n\n // In stock - limited by available quantity\n let maxQty = stockQuantity ?? 999;\n\n // Apply max purchase quantity if set\n if (maxPurchaseQuantity && maxPurchaseQuantity < maxQty) {\n maxQty = maxPurchaseQuantity;\n }\n\n // Subtract what's already in cart\n return Math.max(0, maxQty - cartQuantity);\n}\n","import type { CartItemImage, ProductImage } from '@atomic-solutions/woocommerce-utils';\n\nexport type { CartItemImage, ProductImage };\n/**\n * Union type for any WooCommerce image (product or cart item)\n * Both have the same structure: id, src, name, alt, thumbnail, srcset, sizes\n */\nexport type WooCommerceImage = ProductImage | CartItemImage;\n\n/**\n * Image size options\n */\nexport type ImageSize = 'thumbnail' | 'medium' | 'large' | 'full';\n\n/**\n * WordPress image size suffixes\n */\nconst SIZE_SUFFIXES: Record<ImageSize, string> = {\n thumbnail: '-150x150',\n medium: '-300x300',\n large: '-1024x1024',\n full: '',\n};\n\n/**\n * Get the primary image from an images array\n *\n * @param images - Array of product or cart item images\n * @returns Primary image or undefined\n *\n * @example\n * const mainImage = getPrimaryImage(product.images);\n * if (mainImage) {\n * return <Image source={{ uri: mainImage.src }} />;\n * }\n */\nexport function getPrimaryImage(images?: WooCommerceImage[] | null): WooCommerceImage | undefined {\n if (!images || images.length === 0) {\n return undefined;\n }\n\n return images[0];\n}\n\n/**\n * Get image URL from an images array\n *\n * @param images - Array of product or cart item images\n * @param size - Desired image size\n * @param fallback - Fallback URL if no images\n * @returns Image URL or fallback\n *\n * @example\n * const imageUrl = getImageUrl(product.images, 'medium');\n * <Image source={{ uri: imageUrl }} />\n */\nexport function getImageUrl(\n images?: WooCommerceImage[] | null,\n size: ImageSize = 'full',\n fallback?: string\n): string | undefined {\n const primary = getPrimaryImage(images);\n\n if (!primary) {\n return fallback;\n }\n\n return getSizedImageUrl(primary.src, size);\n}\n\n/**\n * Get a sized version of an image URL\n *\n * WordPress stores images with size suffixes like:\n * - image-150x150.jpg (thumbnail)\n * - image-300x300.jpg (medium)\n * - image-1024x1024.jpg (large)\n * - image.jpg (full)\n *\n * @param url - Original image URL\n * @param size - Desired size\n * @returns Sized image URL\n */\nexport function getSizedImageUrl(url: string, size: ImageSize = 'full'): string {\n if (!url || size === 'full') {\n return url;\n }\n\n // Check if URL already has a size suffix\n const hasSize = Object.values(SIZE_SUFFIXES).some((suffix) => suffix && url.includes(suffix));\n\n if (hasSize) {\n // Replace existing size with new size\n let result = url;\n Object.values(SIZE_SUFFIXES).forEach((suffix) => {\n if (suffix) {\n result = result.replace(suffix, SIZE_SUFFIXES[size]);\n }\n });\n return result;\n }\n\n // Add size suffix before extension\n const suffix = SIZE_SUFFIXES[size];\n const lastDot = url.lastIndexOf('.');\n\n if (lastDot === -1) {\n return url;\n }\n\n return `${url.slice(0, lastDot)}${suffix}${url.slice(lastDot)}`;\n}\n\n/**\n * Get all image URLs from an images array\n *\n * @param images - Array of product or cart item images\n * @param size - Desired image size\n * @returns Array of image URLs\n */\nexport function getAllImageUrls(\n images?: WooCommerceImage[] | null,\n size: ImageSize = 'full'\n): string[] {\n if (!images || images.length === 0) {\n return [];\n }\n\n return images.map((img) => getSizedImageUrl(img.src, size));\n}\n\n/**\n * Placeholder image URL for products without images\n */\nexport const PLACEHOLDER_IMAGE_URL = 'https://via.placeholder.com/300x300.png?text=No+Image';\n\n/**\n * Get image URL with fallback to placeholder\n *\n * @param images - Array of product or cart item images\n * @param size - Desired image size\n * @returns Image URL or placeholder\n */\nexport function getImageUrlOrPlaceholder(\n images?: WooCommerceImage[] | null,\n size: ImageSize = 'medium'\n): string {\n return getImageUrl(images, size, PLACEHOLDER_IMAGE_URL) ?? PLACEHOLDER_IMAGE_URL;\n}\n\n/**\n * Preload an image to cache it\n *\n * Note: In React Native, you should use React Native's Image.prefetch instead.\n * This is a no-op placeholder that resolves immediately.\n *\n * @param _url - Image URL to preload (unused in this implementation)\n * @returns Promise that resolves immediately\n *\n * @example\n * // In React Native, use:\n * // import { Image } from 'react-native';\nimport CartItemImage from '@atomic-solutions/woocommerce-utils';\n * // await Image.prefetch(url);\n */\nexport async function preloadImage(_url: string): Promise<void> {\n // No-op in this package - consumers should use React Native's Image.prefetch\n return Promise.resolve();\n}\n\n/**\n * Preload multiple images\n *\n * @param urls - Array of image URLs to preload\n * @returns Promise that resolves when all images are loaded\n */\nexport async function preloadImages(urls: string[]): Promise<void> {\n await Promise.all(urls.map(preloadImage));\n}\n","import { useCallback, useContext, useMemo } from 'react';\nimport type { Product, ProductCategory, ProductParams } from '@atomic-solutions/woocommerce-utils';\n\nimport { useInfiniteProducts, useProductCategoryTree } from '..';\nimport { DEFAULT_STORE_CONFIG } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\nimport { getImageUrl, type ImageSize } from '../utils/image';\nimport { formatStoreApiPriceIntl } from '../utils/price';\n\n/**\n * Processed product with formatted data ready for display\n */\nexport interface ProcessedProduct {\n id: number;\n name: string;\n slug: string;\n permalink: string;\n imageUrl: string | undefined;\n /** Formatted current price */\n price: string;\n /** Formatted regular price */\n regularPrice: string;\n /** Whether on sale */\n isOnSale: boolean;\n /** Whether can be added to cart */\n canAddToCart: boolean;\n /** Raw product data for advanced use cases */\n raw: Product;\n}\n\n/**\n * Category with subcategories for tree display\n */\nexport interface ProcessedCategory extends ProductCategory {\n subCategories?: ProcessedCategory[];\n}\n\n/**\n * Options for useProductsFeed hook\n */\nexport interface UseProductsFeedOptions {\n /** Query parameters for filtering products */\n params?: ProductParams;\n /**\n * Locale tag override (e.g., 'en-US', 'bs-BA')\n * If not provided, uses value from WooCommerceStoreProvider context\n */\n localeTag?: string;\n /**\n * Fallback image URL override\n * If not provided, uses value from WooCommerceStoreProvider config\n */\n fallbackImageUrl?: string;\n /** Image size to use (default: 'medium') */\n imageSize?: ImageSize;\n}\n\n/**\n * Return type for useProductsFeed hook\n */\nexport interface UseProductsFeedReturn {\n /** Processed products ready for display */\n products: ProcessedProduct[];\n /** Whether initial load is in progress */\n isLoading: boolean;\n /** Whether fetching next page */\n isFetchingNextPage: boolean;\n /** Error if any */\n error: Error | null;\n /** Whether there are more pages to load */\n hasNextPage: boolean;\n /** Load next page of products */\n fetchNextPage: () => void;\n /** Refresh the product list */\n refresh: () => Promise<void>;\n /** Whether refreshing */\n isRefreshing: boolean;\n /** Active category if filtering by category */\n activeCategory: ProcessedCategory | undefined;\n /** Category tree for filtering */\n categoryTree: ProcessedCategory[];\n /** Find category by ID */\n findCategoryById: (id: number) => ProcessedCategory | undefined;\n /** Total product count (approximate, from first page) */\n totalCount: number;\n}\n\n/**\n * Hook for managing infinite product listing with category filtering\n *\n * Provides all the logic needed to build a product feed UI:\n * - Infinite scroll pagination\n * - Product data processing (images, prices)\n * - Category tree for filtering\n * - Refresh functionality\n *\n * Uses locale configuration from WooCommerceStoreProvider context.\n *\n * @example\n * ```tsx\n * function ProductFeed() {\n * const {\n * products,\n * isLoading,\n * hasNextPage,\n * fetchNextPage,\n * refresh,\n * isRefreshing,\n * } = useProductsFeed({ params: { category: 123 } });\n *\n * return (\n * <FlatList\n * data={products}\n * renderItem={({ item }) => (\n * <ProductCard\n * name={item.name}\n * imageUrl={item.imageUrl}\n * price={item.price}\n * />\n * )}\n * onEndReached={() => hasNextPage && fetchNextPage()}\n * refreshing={isRefreshing}\n * onRefresh={refresh}\n * />\n * );\n * }\n * ```\n */\nexport function useProductsFeed(options: UseProductsFeedOptions = {}): UseProductsFeedReturn {\n const { params, imageSize = 'medium' } = options;\n\n // Get config from context (optional - hooks work without provider too)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeConfig = storeContext?.config;\n\n // Resolve locale tag: param override > context > default\n const localeTag =\n options.localeTag ?? storeConfig?.locale?.localeTag ?? DEFAULT_STORE_CONFIG.locale.localeTag;\n\n // Resolve fallback image: param override > context > undefined\n const fallbackImageUrl = options.fallbackImageUrl ?? storeConfig?.fallbackImageUrl;\n\n // Get image transformer from config\n const imageUrlTransformer = storeConfig?.imageUrlTransformer;\n\n // Fetch products with infinite pagination\n const {\n data: productsData,\n isLoading,\n isFetchingNextPage,\n error,\n hasNextPage = false,\n fetchNextPage,\n refetch,\n isRefetching,\n } = useInfiniteProducts(params);\n\n // Fetch category tree\n const { treeData: categoryTree = [], findById } = useProductCategoryTree();\n\n // Helper to get image URL with transformer support\n const getProcessedImageUrl = useCallback(\n (images: Product['images'] | undefined): string | undefined => {\n const baseUrl = getImageUrl(images, imageSize, fallbackImageUrl);\n\n // Apply custom transformer if provided\n if (baseUrl && imageUrlTransformer) {\n return imageUrlTransformer(baseUrl, imageSize);\n }\n\n return baseUrl;\n },\n [imageSize, fallbackImageUrl, imageUrlTransformer]\n );\n\n // Process products for display\n const products = useMemo<ProcessedProduct[]>(() => {\n if (!productsData) return [];\n\n // productsData is Product[] from useInfiniteProducts\n const productList: Product[] = Array.isArray(productsData) ? productsData : [];\n\n return productList.map((product): ProcessedProduct => {\n const currencyCode = product.prices?.currency_code;\n\n return {\n id: product.id,\n name: product.name,\n slug: product.slug,\n permalink: product.permalink,\n imageUrl: getProcessedImageUrl(product.images),\n price: formatStoreApiPriceIntl(product.prices?.price, currencyCode, localeTag),\n regularPrice: formatStoreApiPriceIntl(\n product.prices?.regular_price,\n currencyCode,\n localeTag\n ),\n isOnSale: product.on_sale,\n canAddToCart: product.is_purchasable && product.is_in_stock,\n raw: product,\n };\n });\n }, [productsData, localeTag, getProcessedImageUrl]);\n\n // Find active category from params\n const activeCategory = useMemo(() => {\n if (!params?.category) return undefined;\n return findById(params.category) as ProcessedCategory | undefined;\n }, [params, findById]);\n\n // Refresh handler\n const refresh = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n // Total count (use array length as approximation)\n const totalCount = products.length;\n\n return {\n products,\n isLoading,\n isFetchingNextPage,\n error: error as Error | null,\n hasNextPage,\n fetchNextPage,\n refresh,\n isRefreshing: isRefetching,\n activeCategory,\n categoryTree: categoryTree as ProcessedCategory[],\n findCategoryById: findById as (id: number) => ProcessedCategory | undefined,\n totalCount,\n };\n}\n","import { useCallback, useContext, useMemo, useState } from 'react';\nimport type { Product } from '@atomic-solutions/woocommerce-utils';\n\nimport { useAddToCart, useCart, useProduct, useRemoveFromCart, useUpdateCartItem } from '..';\nimport { DEFAULT_STORE_CONFIG } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\nimport { getAllImageUrls, getImageUrl, type ImageSize } from '../utils/image';\nimport { calculateDiscount, formatStoreApiPriceIntl } from '../utils/price';\nimport { getStockStatusText, isLowStock, isPurchasable, type StockStatus } from '../utils/stock';\n\n/**\n * Processed product details ready for display\n */\nexport interface ProcessedProductDetails {\n id: number;\n name: string;\n slug: string;\n permalink: string;\n description: string;\n shortDescription: string;\n sku: string;\n /** Primary image URL */\n imageUrl: string | undefined;\n /** All image URLs for gallery */\n imageUrls: string[];\n /** Formatted current price */\n price: string;\n /** Formatted regular price */\n regularPrice: string;\n /** Whether product is on sale */\n isOnSale: boolean;\n /** Discount percentage (e.g., 20 for 20% off) */\n discountPercent: number | null;\n /** Formatted discount badge (e.g., \"-20%\") */\n discountBadge: string | null;\n /** Stock status text for display */\n stockStatusText: string;\n /** Whether product can be purchased */\n isPurchasable: boolean;\n /** Whether stock is low */\n isLowStock: boolean;\n /** Maximum quantity that can be added to cart */\n maxQuantity: number;\n /** Minimum quantity */\n minQuantity: number;\n /** Raw product data */\n raw: Product;\n}\n\n/**\n * Cart state for the product\n */\nexport interface ProductCartState {\n /** Whether product is in cart */\n isInCart: boolean;\n /** Current quantity in cart */\n quantityInCart: number;\n /** Cart item key (for updates/removal) */\n cartItemKey: string | null;\n /** Quantity limits from cart item */\n cartQuantityLimits: {\n minimum: number;\n maximum: number;\n } | null;\n}\n\n/**\n * Options for useProductView hook\n */\nexport interface UseProductViewOptions {\n /** Product ID */\n productId: number;\n /**\n * Locale tag override (e.g., 'en-US', 'bs-BA')\n * If not provided, uses value from WooCommerceStoreProvider context\n */\n localeTag?: string;\n /**\n * Fallback image URL override\n * If not provided, uses value from WooCommerceStoreProvider config\n */\n fallbackImageUrl?: string;\n /** Image size for primary image (default: 'large') */\n imageSize?: ImageSize;\n /** Low stock threshold (default: 5) */\n lowStockThreshold?: number;\n}\n\n/**\n * Return type for useProductView hook\n */\nexport interface UseProductViewReturn {\n /** Processed product details */\n product: ProcessedProductDetails | null;\n /** Loading state */\n isLoading: boolean;\n /** Error if any */\n error: Error | null;\n /** Refresh product data */\n refresh: () => Promise<void>;\n\n // Cart state\n /** Cart state for this product */\n cartState: ProductCartState;\n\n // Cart actions\n /** Draft quantity for adding to cart */\n draftQuantity: number;\n /** Set draft quantity */\n setDraftQuantity: (quantity: number) => void;\n /** Add product to cart */\n addToCart: () => Promise<void>;\n /** Remove product from cart */\n removeFromCart: () => Promise<void>;\n /** Update quantity in cart */\n updateCartQuantity: (quantity: number) => Promise<void>;\n\n // Loading states for cart operations\n /** Whether adding to cart */\n isAddingToCart: boolean;\n /** Whether removing from cart */\n isRemovingFromCart: boolean;\n /** Whether updating cart */\n isUpdatingCart: boolean;\n /** Whether any cart operation is in progress */\n isCartBusy: boolean;\n}\n\n/**\n * Hook for managing product detail view with cart integration\n *\n * Uses locale configuration from WooCommerceStoreProvider context.\n *\n * @example\n * ```tsx\n * function ProductDetail({ productId }: { productId: number }) {\n * const {\n * product,\n * isLoading,\n * cartState,\n * draftQuantity,\n * setDraftQuantity,\n * addToCart,\n * removeFromCart,\n * isCartBusy,\n * } = useProductView({ productId });\n *\n * if (isLoading) return <Loader />;\n * if (!product) return <NotFound />;\n *\n * return (\n * <View>\n * <Image source={{ uri: product.imageUrl }} />\n * <Text>{product.name}</Text>\n * <Text>{product.price}</Text>\n * <Text>{product.stockStatusText}</Text>\n * {cartState.isInCart ? (\n * <Button onPress={removeFromCart} disabled={isCartBusy}>\n * Remove from Cart\n * </Button>\n * ) : (\n * <>\n * <QuantityInput\n * value={draftQuantity}\n * onChange={setDraftQuantity}\n * max={product.maxQuantity}\n * />\n * <Button onPress={addToCart} disabled={isCartBusy}>\n * Add to Cart\n * </Button>\n * </>\n * )}\n * </View>\n * );\n * }\n * ```\n */\nexport function useProductView(options: UseProductViewOptions): UseProductViewReturn {\n const { productId, imageSize = 'large', lowStockThreshold = 5 } = options;\n\n // Get config from context (optional)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeConfig = storeContext?.config;\n\n // Resolve locale tag\n const localeTag =\n options.localeTag ?? storeConfig?.locale?.localeTag ?? DEFAULT_STORE_CONFIG.locale.localeTag;\n\n // Resolve fallback image\n const fallbackImageUrl = options.fallbackImageUrl ?? storeConfig?.fallbackImageUrl;\n\n // Get image transformer from config\n const imageUrlTransformer = storeConfig?.imageUrlTransformer;\n\n // Local state for draft quantity\n const [draftQuantity, setDraftQuantity] = useState(1);\n\n // Fetch product\n const { data: productData, isLoading, error, refetch } = useProduct(productId);\n\n // Fetch cart\n const { data: cartData } = useCart();\n\n // Cart mutations\n const addToCartMutation = useAddToCart();\n const removeFromCartMutation = useRemoveFromCart();\n const updateCartMutation = useUpdateCartItem();\n\n // Helper to process image URL\n const processImageUrl = useCallback(\n (url: string | undefined): string | undefined => {\n if (!url) return url;\n if (imageUrlTransformer) {\n return imageUrlTransformer(url, imageSize);\n }\n return url;\n },\n [imageUrlTransformer, imageSize]\n );\n\n // Process product data\n const product = useMemo<ProcessedProductDetails | null>(() => {\n if (!productData) return null;\n\n const currencyCode = productData.prices?.currency_code;\n\n // Determine stock status from product flags\n const stockStatus: StockStatus = productData.is_on_backorder\n ? 'onbackorder'\n : productData.is_in_stock\n ? 'instock'\n : 'outofstock';\n\n // Get low stock remaining (can be null)\n const lowStockRemaining = productData.low_stock_remaining;\n\n // Get base image URLs\n const baseImageUrl = getImageUrl(productData.images, imageSize, fallbackImageUrl);\n\n const baseImageUrls = getAllImageUrls(productData.images, imageSize);\n\n return {\n id: productData.id,\n name: productData.name,\n slug: productData.slug,\n permalink: productData.permalink,\n description: productData.description,\n shortDescription: productData.short_description,\n sku: productData.sku,\n imageUrl: processImageUrl(baseImageUrl),\n imageUrls: baseImageUrls.map((url) => processImageUrl(url) ?? url),\n price: formatStoreApiPriceIntl(productData.prices?.price, currencyCode, localeTag),\n regularPrice: formatStoreApiPriceIntl(\n productData.prices?.regular_price,\n currencyCode,\n localeTag\n ),\n isOnSale: productData.on_sale,\n discountPercent: calculateDiscount(\n productData.prices?.regular_price ?? '0',\n productData.prices?.price ?? '0'\n ),\n discountBadge: productData.on_sale\n ? `-${calculateDiscount(\n productData.prices?.regular_price ?? '0',\n productData.prices?.price ?? '0'\n )}%`\n : null,\n stockStatusText: getStockStatusText(stockStatus, lowStockRemaining ?? undefined, {\n lowStockThreshold,\n }),\n isPurchasable: isPurchasable(\n stockStatus,\n lowStockRemaining ?? undefined,\n productData.sold_individually\n ),\n isLowStock: isLowStock(stockStatus, lowStockRemaining ?? undefined, lowStockThreshold),\n maxQuantity: productData.add_to_cart?.maximum ?? 999,\n minQuantity: productData.add_to_cart?.minimum ?? 1,\n raw: productData,\n };\n }, [productData, localeTag, fallbackImageUrl, imageSize, lowStockThreshold, processImageUrl]);\n\n // Find cart item for this product\n const cartItem = useMemo(() => {\n return cartData?.items.find((item) => item.id === productId);\n }, [cartData?.items, productId]);\n\n // Cart state\n const cartState = useMemo<ProductCartState>(\n () => ({\n isInCart: !!cartItem,\n quantityInCart: cartItem?.quantity ?? 0,\n cartItemKey: cartItem?.key ?? null,\n cartQuantityLimits: cartItem\n ? {\n minimum: cartItem.quantity_limits.minimum,\n maximum: cartItem.quantity_limits.maximum,\n }\n : null,\n }),\n [cartItem]\n );\n\n // Cart actions\n const addToCart = useCallback(async () => {\n await addToCartMutation.mutateAsync({\n id: productId,\n quantity: draftQuantity,\n });\n setDraftQuantity(1); // Reset after adding\n }, [addToCartMutation, productId, draftQuantity]);\n\n const removeFromCart = useCallback(async () => {\n if (!cartState.cartItemKey) return;\n await removeFromCartMutation.mutateAsync({\n key: cartState.cartItemKey,\n });\n }, [removeFromCartMutation, cartState.cartItemKey]);\n\n const updateCartQuantity = useCallback(\n async (quantity: number) => {\n if (!cartState.cartItemKey) return;\n await updateCartMutation.mutateAsync({\n key: cartState.cartItemKey,\n quantity,\n });\n },\n [updateCartMutation, cartState.cartItemKey]\n );\n\n const refresh = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n // Loading states\n const isAddingToCart = addToCartMutation.isPending;\n const isRemovingFromCart = removeFromCartMutation.isPending;\n const isUpdatingCart = updateCartMutation.isPending;\n const isCartBusy = isAddingToCart || isRemovingFromCart || isUpdatingCart;\n\n return {\n product,\n isLoading,\n error: error as Error | null,\n refresh,\n cartState,\n draftQuantity,\n setDraftQuantity,\n addToCart,\n removeFromCart,\n updateCartQuantity,\n isAddingToCart,\n isRemovingFromCart,\n isUpdatingCart,\n isCartBusy,\n };\n}\n","import { useCallback, useContext, useMemo } from 'react';\nimport type { Cart, CartItem } from '@atomic-solutions/woocommerce-utils';\n\nimport {\n useApplyCoupon,\n useCart,\n useRemoveCoupon,\n useRemoveFromCart,\n useSelectShippingRate,\n useUpdateCartItem,\n} from '..';\nimport { DEFAULT_STORE_CONFIG } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\nimport { getImageUrl, type ImageSize, type WooCommerceImage } from '../utils/image';\nimport { formatStoreApiPriceIntl } from '../utils/price';\n\n/**\n * Processed cart item ready for display\n */\nexport interface ProcessedCartItem {\n /** Unique cart item key */\n key: string;\n /** Product ID */\n id: number;\n /** Product name */\n name: string;\n /** Product image URL */\n imageUrl: string | undefined;\n /** Current quantity */\n quantity: number;\n /** Minimum quantity allowed */\n minQuantity: number;\n /** Maximum quantity allowed */\n maxQuantity: number;\n /** Formatted line total */\n lineTotal: string;\n /** Formatted unit price */\n unitPrice: string;\n /** Raw cart item */\n raw: CartItem;\n}\n\n/**\n * Cart totals for display\n */\nexport interface CartTotals {\n /** Formatted subtotal (items only) */\n subtotal: string;\n /** Formatted shipping total */\n shipping: string;\n /** Formatted tax total */\n tax: string;\n /** Formatted discount total */\n discount: string;\n /** Formatted grand total */\n total: string;\n /** Number of items in cart */\n itemCount: number;\n /** Currency code */\n currencyCode: string;\n}\n\n/**\n * Applied coupon info\n */\nexport interface AppliedCoupon {\n /** Coupon code */\n code: string;\n /** Formatted discount amount */\n discount: string;\n}\n\n/**\n * Shipping rate option\n */\nexport interface ShippingRate {\n /** Rate ID */\n rateId: string;\n /** Rate name (e.g., \"Free Shipping\") */\n name: string;\n /** Formatted price */\n price: string;\n /** Whether currently selected */\n isSelected: boolean;\n}\n\n/**\n * Payment method option\n * Note: WooCommerce Store API returns payment methods as string identifiers\n */\nexport interface PaymentMethod {\n /** Method ID (e.g., \"cod\", \"monri\") */\n id: string;\n /** Display title (derived from ID if not available) */\n title: string;\n}\n\n/**\n * Common payment method ID to display name mappings\n */\nconst PAYMENT_METHOD_TITLES: Record<string, string> = {\n cod: 'Cash on Delivery',\n monri: 'Monri',\n bacs: 'Bank Transfer',\n cheque: 'Check Payment',\n paypal: 'PayPal',\n stripe: 'Credit Card',\n};\n\n/**\n * Format payment method ID to human-readable title\n */\nfunction formatPaymentMethodTitle(methodId: string): string {\n // Check known mappings first\n const knownTitle = PAYMENT_METHOD_TITLES[methodId];\n if (knownTitle) {\n return knownTitle;\n }\n // Fallback: capitalize and replace underscores/dashes with spaces\n return methodId.replace(/[_-]/g, ' ').replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Options for useCartView hook\n */\nexport interface UseCartViewOptions {\n /**\n * Locale tag override (e.g., 'en-US', 'bs-BA')\n * If not provided, uses value from WooCommerceStoreProvider context\n */\n localeTag?: string;\n /**\n * Fallback image URL override\n * If not provided, uses value from WooCommerceStoreProvider config\n */\n fallbackImageUrl?: string;\n /** Image size for cart items (default: 'thumbnail') */\n imageSize?: ImageSize;\n}\n\n/**\n * Return type for useCartView hook\n */\nexport interface UseCartViewReturn {\n // Cart data\n /** Processed cart items */\n items: ProcessedCartItem[];\n /** Cart totals */\n totals: CartTotals;\n /** Applied coupons */\n coupons: AppliedCoupon[];\n /** Available shipping rates */\n shippingRates: ShippingRate[];\n /** Available payment methods */\n paymentMethods: PaymentMethod[];\n /** Whether cart is empty */\n isEmpty: boolean;\n /** Whether cart needs shipping */\n needsShipping: boolean;\n /** Raw cart data */\n raw: Cart | undefined;\n\n // Loading states\n /** Whether loading cart */\n isLoading: boolean;\n /** Error if any */\n error: Error | null;\n\n // Item actions\n /** Update item quantity */\n updateItemQuantity: (key: string, quantity: number) => Promise<void>;\n /** Remove item from cart */\n removeItem: (key: string) => Promise<void>;\n /** Whether updating an item */\n isUpdatingItem: boolean;\n /** Whether removing an item */\n isRemovingItem: boolean;\n\n // Coupon actions\n /** Apply a coupon code */\n applyCoupon: (code: string) => Promise<void>;\n /** Remove a coupon */\n removeCoupon: (code: string) => Promise<void>;\n /** Whether applying coupon */\n isApplyingCoupon: boolean;\n /** Whether removing coupon */\n isRemovingCoupon: boolean;\n\n // Shipping actions\n /** Select shipping rate */\n selectShippingRate: (rateId: string, packageId?: string | number) => Promise<void>;\n /** Whether updating shipping */\n isUpdatingShipping: boolean;\n\n // General\n /** Refresh cart */\n refresh: () => Promise<void>;\n /** Whether any operation is in progress */\n isBusy: boolean;\n}\n\n/**\n * Hook for managing cart view with all cart operations\n *\n * @example\n * ```tsx\n * const {\n * items,\n * totals,\n * isEmpty,\n * updateItemQuantity,\n * removeItem,\n * applyCoupon,\n * isBusy,\n * } = useCartView({ locale: 'en-US' });\n *\n * if (isEmpty) return <EmptyCart />;\n *\n * return (\n * <View>\n * {items.map(item => (\n * <CartItemCard\n * key={item.key}\n * name={item.name}\n * imageUrl={item.imageUrl}\n * quantity={item.quantity}\n * price={item.lineTotal}\n * onQuantityChange={(q) => updateItemQuantity(item.key, q)}\n * onRemove={() => removeItem(item.key)}\n * />\n * ))}\n * <Text>Total: {totals.total}</Text>\n * </View>\n * );\n * ```\n */\nexport function useCartView(options: UseCartViewOptions = {}): UseCartViewReturn {\n const { imageSize = 'thumbnail' } = options;\n\n // Get config from context (optional - hooks work without provider too)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeConfig = storeContext?.config;\n\n // Resolve locale tag: param override > context > default\n const localeTag =\n options.localeTag ?? storeConfig?.locale?.localeTag ?? DEFAULT_STORE_CONFIG.locale.localeTag;\n\n // Resolve fallback image: param override > context > undefined\n const fallbackImageUrl = options.fallbackImageUrl ?? storeConfig?.fallbackImageUrl;\n\n // Get image transformer from config\n const imageUrlTransformer = storeConfig?.imageUrlTransformer;\n\n // Fetch cart\n const { data: cartData, isLoading, error, refetch } = useCart();\n\n // Mutations\n const updateItemMutation = useUpdateCartItem();\n const removeItemMutation = useRemoveFromCart();\n const applyCouponMutation = useApplyCoupon();\n const removeCouponMutation = useRemoveCoupon();\n const selectShippingMutation = useSelectShippingRate();\n\n // Helper to process image URL with transformer\n const getProcessedImageUrl = useCallback(\n (images: WooCommerceImage[] | undefined): string | undefined => {\n const baseUrl = getImageUrl(images, imageSize, fallbackImageUrl);\n\n // Apply custom transformer if provided\n if (baseUrl && imageUrlTransformer) {\n return imageUrlTransformer(baseUrl, imageSize);\n }\n\n return baseUrl;\n },\n [imageSize, fallbackImageUrl, imageUrlTransformer]\n );\n\n // Process cart items\n const items = useMemo<ProcessedCartItem[]>(() => {\n if (!cartData?.items) return [];\n\n const currencyCode = cartData.totals.currency_code;\n\n return cartData.items.map(\n (item): ProcessedCartItem => ({\n key: item.key,\n id: item.id,\n name: item.name,\n imageUrl: getProcessedImageUrl(item.images),\n quantity: item.quantity,\n minQuantity: item.quantity_limits.minimum,\n maxQuantity: item.quantity_limits.maximum,\n lineTotal: formatStoreApiPriceIntl(item.totals.line_total, currencyCode, localeTag),\n unitPrice: formatStoreApiPriceIntl(item.prices.price, currencyCode, localeTag),\n raw: item,\n })\n );\n }, [cartData?.items, cartData?.totals.currency_code, localeTag, getProcessedImageUrl]);\n\n // Process totals\n const totals = useMemo<CartTotals>(() => {\n if (!cartData?.totals) {\n return {\n subtotal: '-',\n shipping: '-',\n tax: '-',\n discount: '-',\n total: '-',\n itemCount: 0,\n currencyCode: 'USD',\n };\n }\n\n const { totals: t } = cartData;\n const currencyCode = t.currency_code;\n\n return {\n subtotal: formatStoreApiPriceIntl(t.total_items, currencyCode, localeTag),\n shipping: formatStoreApiPriceIntl(t.total_shipping, currencyCode, localeTag),\n tax: formatStoreApiPriceIntl(t.total_tax, currencyCode, localeTag),\n discount: formatStoreApiPriceIntl(t.total_discount, currencyCode, localeTag),\n total: formatStoreApiPriceIntl(t.total_price, currencyCode, localeTag),\n itemCount: cartData.items_count,\n currencyCode,\n };\n }, [localeTag, cartData]);\n\n // Process coupons\n const coupons = useMemo<AppliedCoupon[]>(() => {\n if (!cartData?.coupons) return [];\n\n return cartData.coupons.map((coupon) => ({\n code: coupon.code,\n discount: formatStoreApiPriceIntl(\n coupon.totals.total_discount,\n coupon.totals.currency_code,\n localeTag\n ),\n }));\n }, [cartData?.coupons, localeTag]);\n\n // Process shipping rates\n const shippingRates = useMemo<ShippingRate[]>(() => {\n if (!cartData?.shipping_rates?.[0]?.shipping_rates) return [];\n\n const currencyCode = cartData.totals.currency_code;\n\n return cartData.shipping_rates[0].shipping_rates.map((rate) => ({\n rateId: rate.rate_id,\n name: rate.name,\n price: formatStoreApiPriceIntl(rate.price, currencyCode, localeTag),\n isSelected: rate.selected,\n }));\n }, [cartData?.shipping_rates, cartData?.totals.currency_code, localeTag]);\n\n // Process payment methods\n // Note: WooCommerce Store API returns payment_methods as string identifiers (e.g., \"cod\", \"monri\")\n const paymentMethods = useMemo<PaymentMethod[]>(() => {\n if (!cartData?.payment_methods) return [];\n\n return cartData.payment_methods.map((methodId) => {\n // Create a display-friendly title from the method ID\n const title = formatPaymentMethodTitle(methodId);\n return {\n id: methodId,\n title,\n };\n });\n }, [cartData?.payment_methods]);\n\n // Actions\n const updateItemQuantity = useCallback(\n async (key: string, quantity: number) => {\n await updateItemMutation.mutateAsync({ key, quantity });\n },\n [updateItemMutation]\n );\n\n const removeItem = useCallback(\n async (key: string) => {\n await removeItemMutation.mutateAsync({ key });\n },\n [removeItemMutation]\n );\n\n const applyCoupon = useCallback(\n async (code: string) => {\n await applyCouponMutation.mutateAsync({ code });\n },\n [applyCouponMutation]\n );\n\n const removeCoupon = useCallback(\n async (code: string) => {\n await removeCouponMutation.mutateAsync({ code });\n },\n [removeCouponMutation]\n );\n\n const selectShippingRate = useCallback(\n async (rateId: string, packageId: string | number = 0) => {\n await selectShippingMutation.mutateAsync({\n rate_id: rateId,\n package_id: packageId,\n });\n },\n [selectShippingMutation]\n );\n\n const refresh = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n // Loading states\n const isUpdatingItem = updateItemMutation.isPending;\n const isRemovingItem = removeItemMutation.isPending;\n const isApplyingCoupon = applyCouponMutation.isPending;\n const isRemovingCoupon = removeCouponMutation.isPending;\n const isUpdatingShipping = selectShippingMutation.isPending;\n\n const isBusy =\n isUpdatingItem || isRemovingItem || isApplyingCoupon || isRemovingCoupon || isUpdatingShipping;\n\n return {\n items,\n totals,\n coupons,\n shippingRates,\n paymentMethods,\n isEmpty: items.length === 0,\n needsShipping: cartData?.needs_shipping ?? false,\n raw: cartData,\n\n isLoading,\n error: error as Error | null,\n\n updateItemQuantity,\n removeItem,\n isUpdatingItem,\n isRemovingItem,\n\n applyCoupon,\n removeCoupon,\n isApplyingCoupon,\n isRemovingCoupon,\n\n selectShippingRate,\n isUpdatingShipping,\n\n refresh,\n isBusy,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/provider/WooCommerceContext.ts","../../src/hooks/useWooCommerceClient.ts","../../src/constants/stale-times.ts","../../src/hooks/useInfiniteWooQuery.ts","../../src/hooks/products.ts","../../src/events/EventContext.ts","../../src/events/types.ts","../../src/hooks/cart.ts","../../src/hooks/checkout.ts","../../src/hooks/orders.ts","../../src/hooks/queryKeys.ts","../../src/provider/WooCommerceStoreContext.ts","../../src/hooks/useStore.ts","../../src/provider/types.ts","../../src/utils/price.ts","../../src/utils/stock.ts","../../src/utils/image.ts","../../src/hooks/useProductsFeed.ts","../../src/hooks/useProductView.ts","../../src/hooks/useCartView.ts"],"names":["createContext","useContext","useQuery","useQueryClient","useMutation","WooCommerceApiError","suffix","useMemo","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * WooCommerce context\n */\n\nimport { createContext } from 'react';\nimport type { WooCommerceClient } from '@atomic-solutions/woocommerce-api-client';\n\nimport type { QueryKeys } from '../hooks/queryKeys';\n\n/**\n * WooCommerce context value\n */\nexport interface WooCommerceContextValue {\n client: WooCommerceClient;\n queryKeys: QueryKeys;\n}\n\n/**\n * WooCommerce context for accessing client and query keys from hooks\n */\nexport const WooCommerceContext = createContext<WooCommerceContextValue | null>(null);\n","/**\n * Hook for accessing WooCommerce client and query keys from context\n */\n\nimport { useContext } from 'react';\nimport type { WooCommerceClient } from '@atomic-solutions/woocommerce-api-client';\n\nimport { WooCommerceContext } from '../provider/WooCommerceContext';\nimport type { QueryKeys } from './queryKeys';\n\n/**\n * Get WooCommerce client from context\n *\n * @throws {Error} If used outside of WooCommerceProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useWooCommerceClient();\n *\n * // Use client directly\n * const handleClick = async () => {\n * const products = await client.products.list({ per_page: 10 });\n * };\n *\n * return <button onClick={handleClick}>Load Products</button>;\n * }\n * ```\n */\nexport const useWooCommerceClient = (): WooCommerceClient => {\n const context = useContext(WooCommerceContext);\n\n if (!context) {\n throw new Error(\n 'useWooCommerceClient must be used within WooCommerceProvider. ' +\n 'Wrap your app with <WooCommerceProvider client={client} queryKeys={queryKeys}>.'\n );\n }\n\n return context.client;\n};\n\n/**\n * Get WooCommerce query keys from context\n *\n * @throws {Error} If used outside of WooCommerceProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const queryKeys = useWooCommerceQueryKeys();\n * const queryClient = useQueryClient();\n *\n * // Manually invalidate cart queries\n * const handleInvalidate = () => {\n * queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n * };\n *\n * return <button onClick={handleInvalidate}>Refresh Cart</button>;\n * }\n * ```\n */\nexport const useWooCommerceQueryKeys = (): QueryKeys => {\n const context = useContext(WooCommerceContext);\n\n if (!context) {\n throw new Error(\n 'useWooCommerceQueryKeys must be used within WooCommerceProvider. ' +\n 'Wrap your app with <WooCommerceProvider client={client} queryKeys={queryKeys}>.'\n );\n }\n\n return context.queryKeys;\n};\n","/**\n * Query stale time constants (in milliseconds)\n *\n * staleTime: How long data is considered \"fresh\" before React Query\n * will refetch in the background.\n *\n * gcTime (cacheTime): How long inactive data stays in cache before\n * being garbage collected.\n */\n\n/** 1 minute */\nexport const STALE_TIME_SHORT = 60 * 1000;\n\n/** 5 minutes */\nexport const STALE_TIME_MEDIUM = 5 * 60 * 1000;\n\n/** 1 hour */\nexport const STALE_TIME_LONG = 60 * 60 * 1000;\n\n/** Always refetch */\nexport const STALE_TIME_NONE = 0;\n\n/** 5 minutes cache */\nexport const CACHE_TIME_SHORT = 5 * 60 * 1000;\n\n/** 30 minutes cache */\nexport const CACHE_TIME_MEDIUM = 30 * 60 * 1000;\n\n/** 1 hour cache */\nexport const CACHE_TIME_LONG = 60 * 60 * 1000;\n\n/**\n * Domain-specific stale times\n */\nexport const StaleTimes = {\n /** Cart data - always fresh */\n cart: STALE_TIME_NONE,\n\n /** Checkout data - always fresh */\n checkout: STALE_TIME_NONE,\n\n /** Product list - 1 minute */\n products: STALE_TIME_SHORT,\n\n /** Product detail - 1 minute */\n product: STALE_TIME_SHORT,\n\n /** Product categories - always fresh */\n categories: STALE_TIME_NONE,\n\n /** Orders - always fresh */\n orders: STALE_TIME_NONE,\n\n /** Default for infinite queries - 1 hour */\n infinite: STALE_TIME_LONG,\n} as const;\n\n/**\n * Domain-specific cache times (gcTime)\n */\nexport const CacheTimes = {\n /** Cart data - 5 minutes */\n cart: CACHE_TIME_SHORT,\n\n /** Checkout data - 5 minutes */\n checkout: CACHE_TIME_SHORT,\n\n /** Product list - 30 minutes */\n products: CACHE_TIME_MEDIUM,\n\n /** Product detail - 30 minutes */\n product: CACHE_TIME_MEDIUM,\n\n /** Product categories - 1 hour */\n categories: CACHE_TIME_LONG,\n\n /** Orders - 5 minutes */\n orders: CACHE_TIME_SHORT,\n\n /** Default for infinite queries - 30 minutes */\n infinite: CACHE_TIME_MEDIUM,\n} as const;\n","/**\n * Generic infinite query hook for WooCommerce/WordPress paginated endpoints\n *\n * Handles the common pagination pattern used by WooCommerce and WordPress REST APIs:\n * - Uses `page` and `per_page` params\n * - Returns PaginatedResponse with nextPage/prevPage\n * - Automatically flattens pages into a single array\n */\n\nimport type { PaginatedResponse } from '@atomic-solutions/woocommerce-api-client';\nimport { useInfiniteQuery, type InfiniteData } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\n\n/**\n * Base params that all paginated endpoints accept\n */\nexport interface InfiniteQueryParams {\n page?: number;\n per_page?: number;\n [key: string]: unknown;\n}\n\n/**\n * Options for useInfiniteWooQuery\n */\nexport interface UseInfiniteWooQueryOptions<TData, TParams extends InfiniteQueryParams> {\n /** Query key for caching */\n queryKey: readonly unknown[];\n\n /** Function to fetch a page of data */\n queryFn: (params: TParams) => Promise<PaginatedResponse<TData>>;\n\n /** Query parameters (excluding page, which is managed internally) */\n params?: Omit<TParams, 'page'>;\n\n /** Items per page (default: 10) */\n perPage?: number;\n\n /** Stale time in milliseconds (default: 1 hour) */\n staleTime?: number;\n\n /** Enable/disable the query */\n enabled?: boolean;\n}\n\n/**\n * Generic infinite query hook for WooCommerce/WordPress APIs\n *\n * @example\n * ```tsx\n * const { data, fetchNextPage, hasNextPage } = useInfiniteWooQuery({\n * queryKey: ['products', { category: 123 }],\n * queryFn: (params) => client.products.list(params),\n * params: { category: 123 },\n * perPage: 20,\n * });\n *\n * // Flattened array of items\n * const items = data ?? [];\n * ```\n */\nexport const useInfiniteWooQuery = <\n TData,\n TParams extends InfiniteQueryParams = InfiniteQueryParams,\n>({\n queryKey,\n queryFn,\n params,\n perPage = 10,\n staleTime = StaleTimes.infinite,\n enabled,\n}: UseInfiniteWooQueryOptions<TData, TParams>) => {\n const query = useInfiniteQuery<\n PaginatedResponse<TData>,\n Error,\n InfiniteData<PaginatedResponse<TData>>,\n readonly unknown[],\n number\n >({\n queryKey,\n queryFn: ({ pageParam }) =>\n queryFn({\n per_page: perPage,\n ...params,\n page: pageParam,\n } as TParams),\n initialPageParam: 1,\n getNextPageParam: (lastPage) => lastPage.pagination.nextPage,\n getPreviousPageParam: (firstPage) => firstPage.pagination.prevPage,\n staleTime,\n enabled,\n });\n\n // Flatten pages into single array\n const flatData = query.data?.pages.flatMap((page) => page.data) ?? [];\n\n return {\n ...query,\n data: flatData, // Override data with flattened array\n };\n};\n","/**\n * Product hooks\n */\n\nimport type { ProductCategory, ProductParams } from '@atomic-solutions/woocommerce-api-client';\nimport { useQuery } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useInfiniteWooQuery } from './useInfiniteWooQuery';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\n// Extended type for tree structure\nexport type ProductCategoryTreeNode = ProductCategory & {\n subCategories?: ProductCategoryTreeNode[];\n};\n\n/**\n * Fetch a single page of products\n */\nexport const useProducts = (params?: ProductParams) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.products.list(params),\n queryFn: () => client.products.list(params),\n staleTime: StaleTimes.products,\n });\n};\n\n/**\n * Fetch products with infinite scroll pagination\n *\n * @example\n * ```tsx\n * const { data, fetchNextPage, hasNextPage } = useInfiniteProducts({\n * category: 123,\n * per_page: 20,\n * });\n *\n * // Flattened products array\n * const products = data ?? [];\n *\n * // Load more\n * <Button onPress={() => fetchNextPage()} disabled={!hasNextPage}>\n * Load More\n * </Button>\n * ```\n */\nexport const useInfiniteProducts = (params?: ProductParams) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useInfiniteWooQuery({\n queryKey: queryKeys.products.list(params),\n queryFn: (p) => client.products.list({ ...p, page: p.page ?? 1 } as ProductParams),\n params,\n perPage: params?.per_page ?? 10,\n });\n};\n\nexport const useProduct = (id: number) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.products.detail(id),\n queryFn: () => client.products.get(id),\n staleTime: StaleTimes.product,\n });\n};\n\nexport const useProductCategories = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.products.categories(),\n queryFn: () => client.products.categories(),\n staleTime: StaleTimes.categories,\n });\n};\n\n/**\n * Simple groupBy implementation to avoid ramda dependency\n */\nconst groupBy = <T>(fn: (item: T) => string, list: T[]): Record<string, T[]> => {\n return list.reduce(\n (acc, item) => {\n const key = fn(item);\n if (!acc[key]) {\n acc[key] = [];\n }\n acc[key].push(item);\n return acc;\n },\n {} as Record<string, T[]>\n );\n};\n\nconst processCategoriesToTree = (data: ProductCategory[]): ProductCategoryTreeNode[] => {\n const rootCategories = data?.filter((item) => item.parent === 0);\n const indexedData = groupBy((item) => String(item.parent), data ?? []);\n\n const processCategory = (item: ProductCategory): ProductCategoryTreeNode => ({\n ...item,\n subCategories: indexedData[item.id]?.map(processCategory),\n });\n\n return rootCategories?.map(processCategory) ?? [];\n};\n\n/**\n * Fetch product categories and process them into a tree structure\n *\n * @example\n * ```tsx\n * const { data, treeData, findById } = useProductCategoryTree();\n *\n * // Flat array of categories\n * const flatCategories = data;\n *\n * // Tree structure of categories\n * const categoryTree = treeData;\n *\n * // Find a specific category by ID\n * const category = findById(123);\n * ```\n */\nexport const useProductCategoryTree = () => {\n const query = useProductCategories();\n\n // Flat data from query\n const flatData = query.data ?? [];\n\n // Process into tree structure\n const treeData = processCategoriesToTree(flatData);\n\n // Helper to find category by ID\n const findById = (id?: number | string) => {\n if (!id) return;\n const numId = typeof id === 'string' ? parseInt(id, 10) : id;\n return flatData.find((item) => item.id === numId);\n };\n\n return {\n ...query,\n data: flatData,\n treeData,\n findById,\n };\n};\n","/**\n * Event context for emitting WooCommerce events\n */\n\nimport { createContext, useContext } from 'react';\n\nimport type { WooCommerceEventHandler } from './types';\n\n/**\n * Context for the event emitter function\n */\nexport const EventContext = createContext<WooCommerceEventHandler | null>(null);\n\n/**\n * Hook to get the event emitter from context\n *\n * Returns null if no onEvent handler is configured (which is valid)\n */\nexport const useEventEmitter = (): WooCommerceEventHandler | null => {\n return useContext(EventContext);\n};\n","/**\n * WooCommerce event types\n *\n * Discriminated union types for all store events.\n * Each event type has both success and error variants with proper type inference.\n */\n\nimport type {\n Cart,\n CartItem,\n Checkout,\n StoreApiOrder,\n WooCommerceApiError,\n} from '@atomic-solutions/woocommerce-api-client';\n\n/**\n * All possible event types\n */\nexport type WooCommerceEventType =\n | 'cart:item_added'\n | 'cart:item_removed'\n | 'cart:item_updated'\n | 'cart:coupon_applied'\n | 'cart:coupon_removed'\n | 'cart:customer_updated'\n | 'cart:shipping_selected'\n | 'checkout:processed'\n | 'order:fetched';\n\n/**\n * Base success event structure\n */\ninterface BaseSuccessEvent<T extends WooCommerceEventType, D> {\n type: T;\n status: 'success';\n data: D;\n}\n\n/**\n * Base error event structure\n */\ninterface BaseErrorEvent<T extends WooCommerceEventType> {\n type: T;\n status: 'error';\n error: WooCommerceApiError;\n}\n\n// ============================================================================\n// Cart Events\n// ============================================================================\n\n/** Item added to cart */\nexport type CartItemAddedEvent =\n | BaseSuccessEvent<'cart:item_added', { item: CartItem; cart: Cart }>\n | BaseErrorEvent<'cart:item_added'>;\n\n/** Item removed from cart */\nexport type CartItemRemovedEvent =\n | BaseSuccessEvent<'cart:item_removed', { itemKey: string; cart: Cart }>\n | BaseErrorEvent<'cart:item_removed'>;\n\n/** Cart item quantity updated */\nexport type CartItemUpdatedEvent =\n | BaseSuccessEvent<'cart:item_updated', { item: CartItem; cart: Cart }>\n | BaseErrorEvent<'cart:item_updated'>;\n\n/** Coupon applied to cart */\nexport type CartCouponAppliedEvent =\n | BaseSuccessEvent<'cart:coupon_applied', { code: string; cart: Cart }>\n | BaseErrorEvent<'cart:coupon_applied'>;\n\n/** Coupon removed from cart */\nexport type CartCouponRemovedEvent =\n | BaseSuccessEvent<'cart:coupon_removed', { code: string; cart: Cart }>\n | BaseErrorEvent<'cart:coupon_removed'>;\n\n/** Customer billing/shipping updated */\nexport type CartCustomerUpdatedEvent =\n | BaseSuccessEvent<'cart:customer_updated', { cart: Cart }>\n | BaseErrorEvent<'cart:customer_updated'>;\n\n/** Shipping rate selected */\nexport type CartShippingSelectedEvent =\n | BaseSuccessEvent<'cart:shipping_selected', { cart: Cart }>\n | BaseErrorEvent<'cart:shipping_selected'>;\n\n// ============================================================================\n// Checkout Events\n// ============================================================================\n\n/** Checkout processed (order created) */\nexport type CheckoutProcessedEvent =\n | BaseSuccessEvent<'checkout:processed', { checkout: Checkout }>\n | BaseErrorEvent<'checkout:processed'>;\n\n// ============================================================================\n// Order Events\n// ============================================================================\n\n/** Order fetched */\nexport type OrderFetchedEvent =\n | BaseSuccessEvent<'order:fetched', { order: StoreApiOrder }>\n | BaseErrorEvent<'order:fetched'>;\n\n// ============================================================================\n// Union Type\n// ============================================================================\n\n/**\n * All WooCommerce events\n *\n * Use discriminated union pattern for type inference:\n *\n * @example\n * ```typescript\n * onEvent={(event) => {\n * if (event.type === 'cart:item_added') {\n * if (event.status === 'success') {\n * // TypeScript knows: event.data.item is CartItem\n * console.log(event.data.item.name);\n * } else {\n * // TypeScript knows: event.error is WooCommerceError\n * console.log(event.error.message);\n * }\n * }\n * }}\n * ```\n */\nexport type WooCommerceEvent =\n | CartItemAddedEvent\n | CartItemRemovedEvent\n | CartItemUpdatedEvent\n | CartCouponAppliedEvent\n | CartCouponRemovedEvent\n | CartCustomerUpdatedEvent\n | CartShippingSelectedEvent\n | CheckoutProcessedEvent\n | OrderFetchedEvent;\n\n/**\n * Event handler function type\n */\nexport type WooCommerceEventHandler = (event: WooCommerceEvent) => void;\n\n/**\n * Helper to create success events with type inference\n */\nexport function createSuccessEvent<T extends WooCommerceEventType, D>(\n type: T,\n data: D\n): BaseSuccessEvent<T, D> {\n return { type, status: 'success', data };\n}\n\n/**\n * Helper to create error events with type inference\n */\nexport function createErrorEvent<T extends WooCommerceEventType>(\n type: T,\n error: WooCommerceApiError\n): BaseErrorEvent<T> {\n return { type, status: 'error', error };\n}\n","/**\n * Cart hooks\n */\n\nimport {\n WooCommerceApiError,\n type AddToCartInput,\n type CouponInput,\n type RemoveCartItemInput,\n type SelectShippingRateInput,\n type UpdateCartItemInput,\n type UpdateCustomerInput,\n} from '@atomic-solutions/woocommerce-api-client';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useEventEmitter } from '../events/EventContext';\nimport { createErrorEvent, createSuccessEvent } from '../events/types';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\nexport const useCart = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n const query = useQuery({\n queryKey: queryKeys.cart.details(),\n queryFn: () => client.cart.get(),\n staleTime: StaleTimes.cart,\n });\n\n const cart = query.data;\n\n /**\n * Check if a product is in the cart\n */\n const isInCart = (productId: number): boolean => {\n return cart?.items.some((item) => item.id === productId) ?? false;\n };\n\n /**\n * Get cart item by product ID\n */\n const getCartItem = (productId: number) => {\n return cart?.items.find((item) => item.id === productId);\n };\n\n /**\n * Get quantity of a product in cart (0 if not in cart)\n */\n const getQuantity = (productId: number): number => {\n return getCartItem(productId)?.quantity ?? 0;\n };\n\n return {\n ...query,\n isInCart,\n getCartItem,\n getQuantity,\n };\n};\n\nexport const useAddToCart = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.addItem(),\n mutationFn: (input: AddToCartInput) => client.cart.addItem(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n // Find the added item (last item with matching product id)\n const addedItem = cart.items.find((item) => item.id === input.id);\n if (emitEvent && addedItem) {\n emitEvent(createSuccessEvent('cart:item_added', { item: addedItem, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:item_added', wooError));\n }\n },\n });\n};\n\nexport const useUpdateCartItem = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.updateItem(),\n mutationFn: (input: UpdateCartItemInput) => client.cart.updateItem(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n const updatedItem = cart.items.find((item) => item.key === input.key);\n if (emitEvent && updatedItem) {\n emitEvent(createSuccessEvent('cart:item_updated', { item: updatedItem, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:item_updated', wooError));\n }\n },\n });\n};\n\nexport const useRemoveFromCart = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.removeItem(),\n mutationFn: (input: RemoveCartItemInput) => client.cart.removeItem(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:item_removed', { itemKey: input.key, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:item_removed', wooError));\n }\n },\n });\n};\n\nexport const useApplyCoupon = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.applyCoupon(),\n mutationFn: (input: CouponInput) => client.cart.applyCoupon(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:coupon_applied', { code: input.code, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:coupon_applied', wooError));\n }\n },\n });\n};\n\nexport const useRemoveCoupon = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.removeCoupon(),\n mutationFn: (input: CouponInput) => client.cart.removeCoupon(input),\n onSuccess: (cart, input) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:coupon_removed', { code: input.code, cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:coupon_removed', wooError));\n }\n },\n });\n};\n\nexport const useUpdateCustomer = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.updateCustomer(),\n mutationFn: (input: UpdateCustomerInput) => client.cart.updateCustomer(input),\n onSuccess: (cart) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:customer_updated', { cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:customer_updated', wooError));\n }\n },\n });\n};\n\nexport const useSelectShippingRate = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.cart.mutations.selectShippingRate(),\n mutationFn: (input: SelectShippingRateInput) => client.cart.selectShippingRate(input),\n onSuccess: (cart) => {\n queryClient.setQueryData(queryKeys.cart.details(), cart);\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('cart:shipping_selected', { cart }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('cart:shipping_selected', wooError));\n }\n },\n });\n};\n","/**\n * Checkout hooks\n */\n\nimport { WooCommerceApiError, type CheckoutInput } from '@atomic-solutions/woocommerce-api-client';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useEventEmitter } from '../events/EventContext';\nimport { createErrorEvent, createSuccessEvent } from '../events/types';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\nexport const useCheckout = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.checkout.details(),\n queryFn: () => client.checkout.get(),\n staleTime: StaleTimes.checkout,\n });\n};\n\nexport const useProcessCheckout = () => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n const queryClient = useQueryClient();\n const emitEvent = useEventEmitter();\n\n return useMutation({\n mutationKey: queryKeys.checkout.mutations.process(),\n mutationFn: (input: CheckoutInput) => client.checkout.process(input),\n onSuccess: (checkout) => {\n // Invalidate cart and checkout queries\n queryClient.invalidateQueries({ queryKey: queryKeys.cart.all });\n queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all });\n\n if (emitEvent) {\n emitEvent(createSuccessEvent('checkout:processed', { checkout }));\n }\n },\n onError: (error) => {\n if (emitEvent) {\n const wooError =\n error instanceof WooCommerceApiError\n ? error\n : new WooCommerceApiError({\n code: 'unknown_error',\n message: error instanceof Error ? error.message : 'Unknown error',\n statusCode: 500,\n url: '',\n method: 'POST',\n originalCode: 'unknown_error',\n });\n emitEvent(createErrorEvent('checkout:processed', wooError));\n }\n },\n });\n};\n","/**\n * Order hooks\n */\n\nimport type { GetOrderInput } from '@atomic-solutions/woocommerce-api-client';\nimport { useQuery } from '@tanstack/react-query';\n\nimport { StaleTimes } from '../constants/stale-times';\nimport { useWooCommerceClient, useWooCommerceQueryKeys } from './useWooCommerceClient';\n\n/**\n * Fetch a single order by ID\n *\n * Supports both authenticated and guest order lookups:\n * - Authenticated: Just pass the order ID\n * - Guest: Pass billing_email + key for guest order verification\n *\n * @example\n * ```tsx\n * // Authenticated user\n * const { data: order } = useOrder({ id: 123 });\n *\n * // Guest order lookup\n * const { data: order } = useOrder({\n * id: 123,\n * billing_email: 'guest@example.com',\n * key: 'wc_order_abc123',\n * });\n * ```\n */\nexport const useOrder = (input: GetOrderInput) => {\n const client = useWooCommerceClient();\n const queryKeys = useWooCommerceQueryKeys();\n\n return useQuery({\n queryKey: queryKeys.orders.detail(input.id, input.billing_email, input.key),\n queryFn: () => client.orders.get(input),\n staleTime: StaleTimes.orders,\n });\n};\n","/**\n * Query keys factory\n */\n\nimport type { ProductParams } from '@atomic-solutions/woocommerce-api-client';\n\nexport const createQueryKeys = (prefix: string[] = ['woocommerce']) => ({\n // All keys start with prefix\n all: prefix as readonly string[],\n\n // Products\n products: {\n all: [...prefix, 'products'] as const,\n lists: () => [...prefix, 'products', 'list'] as const,\n list: (params?: ProductParams) => [...prefix, 'products', 'list', params] as const,\n details: () => [...prefix, 'products', 'detail'] as const,\n detail: (id: number) => [...prefix, 'products', 'detail', id] as const,\n categories: () => [...prefix, 'products', 'categories'] as const,\n },\n\n // Cart\n cart: {\n all: [...prefix, 'cart'] as const,\n details: () => [...prefix, 'cart', 'details'] as const,\n // Mutation keys\n mutations: {\n addItem: () => [...prefix, 'cart', 'mutation', 'addItem'] as const,\n updateItem: () => [...prefix, 'cart', 'mutation', 'updateItem'] as const,\n removeItem: () => [...prefix, 'cart', 'mutation', 'removeItem'] as const,\n applyCoupon: () => [...prefix, 'cart', 'mutation', 'applyCoupon'] as const,\n removeCoupon: () => [...prefix, 'cart', 'mutation', 'removeCoupon'] as const,\n updateCustomer: () => [...prefix, 'cart', 'mutation', 'updateCustomer'] as const,\n selectShippingRate: () => [...prefix, 'cart', 'mutation', 'selectShippingRate'] as const,\n },\n },\n\n // Checkout\n checkout: {\n all: [...prefix, 'checkout'] as const,\n details: () => [...prefix, 'checkout', 'details'] as const,\n // Mutation keys\n mutations: {\n process: () => [...prefix, 'checkout', 'mutation', 'process'] as const,\n },\n },\n\n // Orders\n orders: {\n all: [...prefix, 'orders'] as const,\n lists: () => [...prefix, 'orders', 'list'] as const,\n list: (params?: Record<string, unknown>) => [...prefix, 'orders', 'list', params] as const,\n details: () => [...prefix, 'orders', 'detail'] as const,\n detail: (id: number, billing_email?: string, key?: string) =>\n [...prefix, 'orders', 'detail', id, billing_email, key].filter(Boolean) as readonly (\n | string\n | number\n )[],\n },\n});\n\nexport type QueryKeys = ReturnType<typeof createQueryKeys>;\n","import { createContext } from 'react';\n\nimport type { StoreContextValue } from './types';\n\n/**\n * Context for accessing store configuration and state\n *\n * @internal Use the useStore hook instead of accessing this directly\n */\nexport const WooCommerceStoreContext = createContext<StoreContextValue | null>(null);\n\nWooCommerceStoreContext.displayName = 'WooCommerceStoreContext';\n","import { useContext, useMemo } from 'react';\n\nimport type { StoreContextValue, StoreTheme } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\n\n/**\n * Hook to access the store configuration and state\n *\n * Must be used within a WooCommerceStoreProvider\n *\n * @returns Store context value with config, validation state, and utilities\n * @throws Error if used outside of WooCommerceStoreProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { config, isValidated, validationError, revalidate } = useStore();\n *\n * if (!isValidated) {\n * return <Text>Connecting to store...</Text>;\n * }\n *\n * return <Text>Connected to: {config.storeUrl}</Text>;\n * }\n * ```\n */\nexport function useStore(): StoreContextValue {\n const context = useContext(WooCommerceStoreContext);\n\n if (!context) {\n throw new Error('useStore must be used within a WooCommerceStoreProvider');\n }\n\n return context;\n}\n\n/**\n * Hook to access store features configuration\n *\n * @returns Store features configuration\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const features = useStoreFeatures();\n *\n * return (\n * <View>\n * {features.search && <SearchBar />}\n * {features.categories && <CategoryNav />}\n * </View>\n * );\n * }\n * ```\n */\nexport function useStoreFeatures() {\n const { config } = useStore();\n return config.features!;\n}\n\n/**\n * Hook to access store locale/currency configuration\n *\n * @returns Store locale configuration\n *\n * @example\n * ```tsx\n * function PriceDisplay({ price }: { price: number }) {\n * const locale = useStoreLocale();\n * const formatted = formatPrice(price, locale);\n * return <Text>{formatted}</Text>;\n * }\n * ```\n */\nexport function useStoreLocale() {\n const { config } = useStore();\n return config.locale!;\n}\n\n/**\n * Resolved theme values with all required properties\n */\nexport interface ResolvedStoreTheme {\n /** Primary brand color */\n primary: string;\n /** Secondary brand color */\n secondary: string;\n /** Color mode */\n mode: 'light' | 'dark' | 'auto';\n /** Custom fonts */\n fonts: {\n heading: string | undefined;\n body: string | undefined;\n };\n}\n\n/**\n * Default theme values when no theme is configured\n */\nconst DEFAULT_THEME: ResolvedStoreTheme = {\n primary: '#007AFF', // iOS blue\n secondary: '#5856D6', // iOS purple\n mode: 'auto',\n fonts: {\n heading: undefined,\n body: undefined,\n },\n};\n\n/**\n * External theme values that can be merged with store theme\n * This allows integration with external theme providers (e.g., react-native-paper, tamagui)\n */\nexport interface ExternalThemeValues {\n primary?: string;\n secondary?: string;\n mode?: 'light' | 'dark' | 'auto';\n fonts?: {\n heading?: string;\n body?: string;\n };\n}\n\n/**\n * Options for useStoreTheme hook\n */\nexport interface UseStoreThemeOptions {\n /**\n * External theme values to merge with store theme\n * These take precedence over store config values\n *\n * @example\n * ```tsx\n * // With react-native-paper\n * const paperTheme = usePaperTheme();\n * const { theme } = useStoreTheme({\n * externalTheme: {\n * primary: paperTheme.colors.primary,\n * mode: paperTheme.dark ? 'dark' : 'light',\n * },\n * });\n * ```\n */\n externalTheme?: ExternalThemeValues;\n}\n\n/**\n * Return type for useStoreTheme hook\n */\nexport interface UseStoreThemeReturn {\n /** Resolved theme values */\n theme: ResolvedStoreTheme;\n /** Raw store theme config (may have undefined values) */\n storeTheme: StoreTheme | undefined;\n /** Whether external theme was provided */\n hasExternalTheme: boolean;\n}\n\n/**\n * Hook for accessing and merging store theme configuration\n *\n * This hook resolves theme values from multiple sources in order of precedence:\n * 1. External theme (from app's ThemeProvider via options)\n * 2. Store config theme (from WooCommerceStoreProvider)\n * 3. Default theme values\n *\n * Works both with and without WooCommerceStoreProvider context.\n *\n * @example\n * ```tsx\n * // Basic usage - uses store config or defaults\n * function ProductCard({ product }) {\n * const { theme } = useStoreTheme();\n *\n * return (\n * <View style={{ borderColor: theme.primary }}>\n * <Text style={{ fontFamily: theme.fonts.heading }}>\n * {product.name}\n * </Text>\n * </View>\n * );\n * }\n *\n * // Integration with external theme provider\n * function ThemedProductCard({ product }) {\n * const appTheme = useAppTheme(); // Your app's theme hook\n * const { theme } = useStoreTheme({\n * externalTheme: {\n * primary: appTheme.colors.brand,\n * secondary: appTheme.colors.accent,\n * mode: appTheme.isDark ? 'dark' : 'light',\n * },\n * });\n *\n * return (\n * <View style={{ borderColor: theme.primary }}>\n * {product.name}\n * </View>\n * );\n * }\n * ```\n */\nexport function useStoreTheme(options: UseStoreThemeOptions = {}): UseStoreThemeReturn {\n const { externalTheme } = options;\n\n // Get store theme from context (may be undefined if no provider)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeTheme = storeContext?.config?.theme;\n\n // Resolve theme with precedence: external > store config > defaults\n const theme = useMemo<ResolvedStoreTheme>(() => {\n return {\n primary: externalTheme?.primary ?? storeTheme?.primary ?? DEFAULT_THEME.primary,\n secondary: externalTheme?.secondary ?? storeTheme?.secondary ?? DEFAULT_THEME.secondary,\n mode: externalTheme?.mode ?? storeTheme?.mode ?? DEFAULT_THEME.mode,\n fonts: {\n heading:\n externalTheme?.fonts?.heading ??\n storeTheme?.fonts?.heading ??\n DEFAULT_THEME.fonts.heading,\n body: externalTheme?.fonts?.body ?? storeTheme?.fonts?.body ?? DEFAULT_THEME.fonts.body,\n },\n };\n }, [externalTheme, storeTheme]);\n\n return {\n theme,\n storeTheme,\n hasExternalTheme: !!externalTheme,\n };\n}\n\n/**\n * Type guard hook to check if running in a WooCommerceStoreProvider context\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * if (!useIsInStoreContext()) {\n * throw new Error('MyComponent must be used within WooCommerceStoreProvider');\n * }\n * // ... component logic\n * }\n * ```\n */\nexport function useIsInStoreContext(): boolean {\n const context = useContext(WooCommerceStoreContext);\n return context !== null;\n}\n","import type { WooCommerceEventHandler } from '../events/types';\n\n/**\n * Store feature configuration\n */\nexport interface StoreFeatures {\n /** Enable authentication screens (default: false) */\n auth?: boolean;\n /** Enable wishlist functionality (default: false) */\n wishlist?: boolean;\n /** Show product reviews (default: true) */\n reviews?: boolean;\n /** Enable search functionality (default: true) */\n search?: boolean;\n /** Show category navigation (default: true) */\n categories?: boolean;\n}\n\n/**\n * Theme configuration for the store\n */\nexport interface StoreTheme {\n /** Primary brand color (e.g., \"#007AFF\") */\n primary?: string;\n /** Secondary brand color */\n secondary?: string;\n /** Color mode */\n mode?: 'light' | 'dark' | 'auto';\n /** Custom fonts */\n fonts?: {\n heading?: string;\n body?: string;\n };\n}\n\n/**\n * Localization and currency configuration\n */\nexport interface StoreLocale {\n /** BCP 47 locale tag for Intl formatting (e.g., \"en-US\", \"bs-BA\") */\n localeTag?: string;\n /** Currency code (e.g., \"USD\", \"EUR\", \"BAM\") */\n currency?: string;\n /** Currency symbol position */\n currencyPosition?: 'before' | 'after';\n /** Thousands separator (e.g., \",\") */\n thousandsSeparator?: string;\n /** Decimal separator (e.g., \".\") */\n decimalSeparator?: string;\n /** Number of decimal places */\n decimals?: number;\n}\n\n/**\n * Function to transform image URLs (e.g., for custom sizing, CDN, optimization)\n */\nexport type ImageUrlTransformer = (\n url: string,\n size: 'thumbnail' | 'medium' | 'large' | 'full'\n) => string;\n\n/**\n * Rate limiting configuration\n */\nexport interface RateLimitConfig {\n /** Maximum requests per minute (default: 60) */\n requestsPerMinute?: number;\n /** Maximum requests per second (default: 10) */\n requestsPerSecond?: number;\n /** Burst limit for temporary spikes (default: 20) */\n burstLimit?: number;\n}\n\n/**\n * Guardrails configuration to prevent abuse\n */\nexport interface StoreGuardrails {\n /** Validate that the URL is a valid WooCommerce store (default: true) */\n validateStore?: boolean;\n /** Rate limiting configuration */\n rateLimit?: RateLimitConfig;\n /** Optional license key for production usage tracking */\n licenseKey?: string;\n}\n\n/**\n * Store validation result\n */\nexport interface StoreValidationResult {\n /** Whether the store is valid */\n valid: boolean;\n /** Store name (if available) */\n storeName?: string;\n /** Normalized store URL */\n storeUrl?: string;\n /** WooCommerce version (if detectable) */\n wcVersion?: string;\n /** Error message if validation failed */\n error?: string;\n}\n\n/**\n * Main store configuration\n */\nexport interface StoreConfig {\n /**\n * WooCommerce store URL\n * @example \"https://mystore.com\" or \"https://mystore.com/wp-json\"\n */\n storeUrl: string;\n\n /** Feature toggles */\n features?: StoreFeatures;\n\n /** Theme customization */\n theme?: StoreTheme;\n\n /** Localization settings */\n locale?: StoreLocale;\n\n /** Guardrails configuration */\n guardrails?: StoreGuardrails;\n\n /** Event handler for WooCommerce events */\n onEvent?: WooCommerceEventHandler;\n\n /** Enable debug logging (default: false in production) */\n debug?: boolean;\n\n /**\n * Custom image URL transformer for optimization\n * Use this to add CDN prefixes, size suffixes, or custom transformations\n *\n * @example\n * ```ts\n * imageUrlTransformer: (url, size) => {\n * // Add PNG optimization for ma-native\n * if (url.endsWith('.png') && !url.includes('unnamed.png')) {\n * return url.replace('.png', '-300x300.png');\n * }\n * return url;\n * }\n * ```\n */\n imageUrlTransformer?: ImageUrlTransformer;\n\n /** Fallback image URL when products have no images */\n fallbackImageUrl?: string;\n}\n\n/**\n * Store context value available via useStore hook\n */\nexport interface StoreContextValue {\n /** Current store configuration */\n config: StoreConfig;\n /** Whether the store has been validated */\n isValidated: boolean;\n /** Whether validation is in progress */\n isValidating: boolean;\n /** Validation error (if any) */\n validationError?: string;\n /** Store validation result */\n validationResult?: StoreValidationResult;\n /** Re-validate the store connection */\n revalidate: () => Promise<void>;\n}\n\n/**\n * Default store configuration values\n */\nexport const DEFAULT_STORE_CONFIG: Required<\n Pick<StoreConfig, 'features' | 'locale' | 'guardrails' | 'debug'>\n> = {\n features: {\n auth: false,\n wishlist: false,\n reviews: true,\n search: true,\n categories: true,\n },\n locale: {\n localeTag: 'en-US',\n currency: 'USD',\n currencyPosition: 'before',\n thousandsSeparator: ',',\n decimalSeparator: '.',\n decimals: 2,\n },\n guardrails: {\n validateStore: true,\n rateLimit: {\n requestsPerMinute: 60,\n requestsPerSecond: 10,\n burstLimit: 20,\n },\n },\n debug: process.env.NODE_ENV !== 'production',\n};\n","import type { StoreLocale } from '../provider/types';\n\n/**\n * Default locale configuration for price formatting\n */\nconst DEFAULT_LOCALE: Required<StoreLocale> = {\n localeTag: 'en-US',\n currency: 'USD',\n currencyPosition: 'before',\n thousandsSeparator: ',',\n decimalSeparator: '.',\n decimals: 2,\n};\n\n/**\n * Currency symbols for common currencies\n */\nconst CURRENCY_SYMBOLS: Record<string, string> = {\n USD: '$',\n EUR: '€',\n GBP: '£',\n CAD: 'CA$',\n AUD: 'A$',\n JPY: '¥',\n CNY: '¥',\n INR: '₹',\n BRL: 'R$',\n MXN: 'MX$',\n RUB: '₽',\n KRW: '₩',\n CHF: 'CHF',\n SEK: 'kr',\n NOK: 'kr',\n DKK: 'kr',\n PLN: 'zł',\n TRY: '₺',\n ZAR: 'R',\n NZD: 'NZ$',\n SGD: 'S$',\n HKD: 'HK$',\n THB: '฿',\n PHP: '₱',\n // Balkans\n BAM: 'KM',\n RSD: 'din',\n HRK: 'kn',\n MKD: 'ден',\n BGN: 'лв',\n RON: 'lei',\n};\n\n/**\n * Get the currency symbol for a currency code\n *\n * @param currencyCode - ISO 4217 currency code\n * @returns Currency symbol or the code itself if not found\n */\nexport function getCurrencySymbol(currencyCode: string): string {\n return CURRENCY_SYMBOLS[currencyCode.toUpperCase()] ?? currencyCode;\n}\n\n/**\n * Format a number with the specified locale settings\n *\n * @param value - Number to format\n * @param locale - Locale configuration\n * @returns Formatted number string\n */\nfunction formatNumber(value: number, locale: Required<StoreLocale>): string {\n const fixed = value.toFixed(locale.decimals);\n const [integerPart, decimalPart] = fixed.split('.');\n\n // Add thousands separators\n const formattedInteger = integerPart!.replace(/\\B(?=(\\d{3})+(?!\\d))/g, locale.thousandsSeparator);\n\n if (locale.decimals > 0 && decimalPart) {\n return `${formattedInteger}${locale.decimalSeparator}${decimalPart}`;\n }\n\n return formattedInteger;\n}\n\n/**\n * Format a price with currency symbol\n *\n * @param price - Price value (can be string or number)\n * @param locale - Locale configuration (optional)\n * @returns Formatted price string\n *\n * @example\n * formatPrice(99.99) // \"$99.99\"\n * formatPrice(99.99, { currency: \"EUR\", currencyPosition: \"after\" }) // \"99.99€\"\n * formatPrice(\"1234.50\", { currency: \"BAM\" }) // \"KM1,234.50\"\n */\nexport function formatPrice(price: string | number, locale: Partial<StoreLocale> = {}): string {\n const mergedLocale = { ...DEFAULT_LOCALE, ...locale };\n const numericPrice = typeof price === 'string' ? parseFloat(price) : price;\n\n if (isNaN(numericPrice)) {\n return '';\n }\n\n const symbol = getCurrencySymbol(mergedLocale.currency);\n const formattedNumber = formatNumber(numericPrice, mergedLocale);\n\n if (mergedLocale.currencyPosition === 'after') {\n return `${formattedNumber}${symbol}`;\n }\n\n return `${symbol}${formattedNumber}`;\n}\n\n/**\n * Format a price range (e.g., for variable products)\n *\n * @param minPrice - Minimum price\n * @param maxPrice - Maximum price\n * @param locale - Locale configuration\n * @returns Formatted price range string\n *\n * @example\n * formatPriceRange(10, 50) // \"$10.00 - $50.00\"\n * formatPriceRange(10, 10) // \"$10.00\" (same price, no range)\n */\nexport function formatPriceRange(\n minPrice: string | number,\n maxPrice: string | number,\n locale: Partial<StoreLocale> = {}\n): string {\n const min = typeof minPrice === 'string' ? parseFloat(minPrice) : minPrice;\n const max = typeof maxPrice === 'string' ? parseFloat(maxPrice) : maxPrice;\n\n if (isNaN(min) || isNaN(max)) {\n return '';\n }\n\n // If same price, just return single price\n if (min === max) {\n return formatPrice(min, locale);\n }\n\n return `${formatPrice(min, locale)} - ${formatPrice(max, locale)}`;\n}\n\n/**\n * Calculate discount percentage\n *\n * @param regularPrice - Original price\n * @param salePrice - Sale price\n * @returns Discount percentage (0-100) or null if no discount\n *\n * @example\n * calculateDiscount(100, 80) // 20\n * calculateDiscount(50, 50) // null\n */\nexport function calculateDiscount(\n regularPrice: string | number,\n salePrice: string | number\n): number | null {\n const regular = typeof regularPrice === 'string' ? parseFloat(regularPrice) : regularPrice;\n const sale = typeof salePrice === 'string' ? parseFloat(salePrice) : salePrice;\n\n if (isNaN(regular) || isNaN(sale) || regular <= 0 || sale >= regular) {\n return null;\n }\n\n return Math.round(((regular - sale) / regular) * 100);\n}\n\n/**\n * Format a price from WooCommerce Store API (minor units/cents)\n *\n * WooCommerce Store API returns prices as strings in minor units (cents).\n * This function converts and formats them properly.\n *\n * @param priceInMinorUnits - Price in minor units (e.g., \"9999\" for $99.99)\n * @param currencyCode - ISO 4217 currency code (e.g., \"USD\", \"BAM\")\n * @param locale - Additional locale configuration\n * @returns Formatted price string, or \"-\" if invalid\n *\n * @example\n * formatStoreApiPrice(\"9999\", \"USD\") // \"$99.99\"\n * formatStoreApiPrice(\"12345\", \"BAM\") // \"KM123.45\"\n * formatStoreApiPrice(undefined, \"USD\") // \"-\"\n */\nexport function formatStoreApiPrice(\n priceInMinorUnits: string | undefined | null,\n currencyCode: string | undefined | null,\n locale: Partial<Omit<StoreLocale, 'currency'>> = {}\n): string {\n if (!priceInMinorUnits || !currencyCode) {\n return '-';\n }\n\n const cents = parseInt(priceInMinorUnits, 10);\n if (isNaN(cents)) {\n return '-';\n }\n\n const decimalPrice = cents / 100;\n return formatPrice(decimalPrice, { ...locale, currency: currencyCode });\n}\n\n/**\n * Format a discount badge string\n *\n * @param regularPrice - Original price\n * @param salePrice - Sale price\n * @returns Formatted discount string or null\n *\n * @example\n * formatDiscountBadge(100, 80) // \"-20%\"\n * formatDiscountBadge(50, 50) // null\n */\nexport function formatDiscountBadge(\n regularPrice: string | number,\n salePrice: string | number\n): string | null {\n const discount = calculateDiscount(regularPrice, salePrice);\n return discount ? `-${discount}%` : null;\n}\n\n/**\n * Format a price from WooCommerce Store API using Intl.NumberFormat\n *\n * Uses the browser/runtime's Intl.NumberFormat for locale-aware formatting.\n * This is useful when you need formatting that matches the user's locale.\n *\n * @param priceInMinorUnits - Price in minor units (e.g., \"9999\" for $99.99)\n * @param currencyCode - ISO 4217 currency code (e.g., \"USD\", \"BAM\")\n * @param localeTag - BCP 47 locale tag (e.g., \"en-US\", \"bs-BA\")\n * @returns Formatted price string, or \"-\" if invalid\n *\n * @example\n * formatStoreApiPriceIntl(\"9999\", \"USD\", \"en-US\") // \"$99.99\"\n * formatStoreApiPriceIntl(\"9999\", \"BAM\", \"bs-BA\") // \"99,99 KM\"\n * formatStoreApiPriceIntl(undefined, \"USD\") // \"-\"\n */\nexport function formatStoreApiPriceIntl(\n priceInMinorUnits: string | undefined | null,\n currencyCode: string | undefined | null,\n localeTag: string = 'en-US'\n): string {\n if (!priceInMinorUnits || !currencyCode) {\n return '-';\n }\n\n const cents = parseInt(priceInMinorUnits, 10);\n if (isNaN(cents)) {\n return '-';\n }\n\n const decimalPrice = cents / 100;\n\n try {\n const formatter = new Intl.NumberFormat(localeTag, {\n style: 'currency',\n currency: currencyCode,\n });\n return formatter.format(decimalPrice);\n } catch {\n // Fallback to basic formatting if Intl fails\n return formatPrice(decimalPrice, { currency: currencyCode });\n }\n}\n\n/**\n * Parse a WooCommerce price string to number\n * Handles various formats like \"99.99\", \"$99.99\", \"99,99€\"\n *\n * @param priceString - Price string from WooCommerce\n * @returns Parsed number or NaN if invalid\n */\nexport function parseWooCommercePrice(priceString: string): number {\n if (!priceString || typeof priceString !== 'string') {\n return NaN;\n }\n\n // Remove currency symbols and whitespace\n const cleaned = priceString.replace(/[^\\d.,-]/g, '').trim();\n\n // Handle European format (1.234,56 -> 1234.56)\n if (cleaned.includes(',') && cleaned.includes('.')) {\n // Determine which is the decimal separator (last one)\n const lastComma = cleaned.lastIndexOf(',');\n const lastDot = cleaned.lastIndexOf('.');\n\n if (lastComma > lastDot) {\n // European: 1.234,56\n return parseFloat(cleaned.replace(/\\./g, '').replace(',', '.'));\n } else {\n // US: 1,234.56\n return parseFloat(cleaned.replace(/,/g, ''));\n }\n }\n\n // Only comma (could be decimal or thousands)\n if (cleaned.includes(',') && !cleaned.includes('.')) {\n // If comma is in last 3 positions and has 1-2 digits after, treat as decimal\n const commaPos = cleaned.lastIndexOf(',');\n const afterComma = cleaned.length - commaPos - 1;\n\n if (afterComma <= 2) {\n return parseFloat(cleaned.replace(',', '.'));\n }\n // Otherwise treat as thousands separator\n return parseFloat(cleaned.replace(/,/g, ''));\n }\n\n // Standard format or just dots\n return parseFloat(cleaned.replace(/,/g, ''));\n}\n","/**\n * Stock status types from WooCommerce\n */\nexport type StockStatus = 'instock' | 'outofstock' | 'onbackorder';\n\n/**\n * Stock display configuration\n */\nexport interface StockDisplayConfig {\n /** Text to show for in-stock items */\n inStockText?: string;\n /** Text to show for out-of-stock items */\n outOfStockText?: string;\n /** Text to show for backorder items */\n backorderText?: string;\n /** Whether to show quantity when in stock */\n showQuantity?: boolean;\n /** Threshold below which to show \"low stock\" warning */\n lowStockThreshold?: number;\n /** Text template for low stock (use {quantity} placeholder) */\n lowStockText?: string;\n}\n\nconst DEFAULT_CONFIG: Required<StockDisplayConfig> = {\n inStockText: 'In Stock',\n outOfStockText: 'Out of Stock',\n backorderText: 'Available on Backorder',\n showQuantity: false,\n lowStockThreshold: 5,\n lowStockText: 'Only {quantity} left',\n};\n\n/**\n * Get human-readable stock status text\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity (optional)\n * @param config - Display configuration\n * @returns Stock status text\n *\n * @example\n * getStockStatusText('instock') // \"In Stock\"\n * getStockStatusText('instock', 3, { lowStockThreshold: 5 }) // \"Only 3 left\"\n * getStockStatusText('outofstock') // \"Out of Stock\"\n */\nexport function getStockStatusText(\n status: StockStatus,\n quantity?: number | null,\n config: StockDisplayConfig = {}\n): string {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n\n switch (status) {\n case 'instock':\n // Check for low stock\n if (\n quantity !== null &&\n quantity !== undefined &&\n quantity <= mergedConfig.lowStockThreshold &&\n quantity > 0\n ) {\n return mergedConfig.lowStockText.replace('{quantity}', quantity.toString());\n }\n\n // Show quantity if enabled\n if (mergedConfig.showQuantity && quantity !== null && quantity !== undefined) {\n return `${mergedConfig.inStockText} (${quantity})`;\n }\n\n return mergedConfig.inStockText;\n\n case 'outofstock':\n return mergedConfig.outOfStockText;\n\n case 'onbackorder':\n return mergedConfig.backorderText;\n\n default:\n return mergedConfig.inStockText;\n }\n}\n\n/**\n * Check if a product is purchasable based on stock status\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity\n * @param manageStock - Whether stock is managed for this product\n * @returns Whether the product can be purchased\n */\nexport function isPurchasable(\n status: StockStatus,\n quantity?: number | null,\n manageStock = true\n): boolean {\n // Out of stock is never purchasable\n if (status === 'outofstock') {\n return false;\n }\n\n // Backorder is purchasable\n if (status === 'onbackorder') {\n return true;\n }\n\n // In stock - check quantity if managed\n if (manageStock && quantity !== null && quantity !== undefined) {\n return quantity > 0;\n }\n\n return true;\n}\n\n/**\n * Get stock status severity for styling\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity\n * @param lowStockThreshold - Threshold for low stock warning\n * @returns Severity level for styling\n */\nexport function getStockSeverity(\n status: StockStatus,\n quantity?: number | null,\n lowStockThreshold = 5\n): 'success' | 'warning' | 'error' | 'info' {\n switch (status) {\n case 'outofstock':\n return 'error';\n\n case 'onbackorder':\n return 'info';\n\n case 'instock':\n if (\n quantity !== null &&\n quantity !== undefined &&\n quantity <= lowStockThreshold &&\n quantity > 0\n ) {\n return 'warning';\n }\n return 'success';\n\n default:\n return 'info';\n }\n}\n\n/**\n * Check if stock is low based on threshold\n *\n * @param status - WooCommerce stock status\n * @param quantity - Stock quantity\n * @param threshold - Low stock threshold (default: 5)\n * @returns Whether stock is considered low\n */\nexport function isLowStock(status: StockStatus, quantity?: number | null, threshold = 5): boolean {\n return (\n status === 'instock' &&\n quantity !== null &&\n quantity !== undefined &&\n quantity <= threshold &&\n quantity > 0\n );\n}\n\n/**\n * Calculate max quantity that can be added to cart\n *\n * @param status - WooCommerce stock status\n * @param stockQuantity - Available stock\n * @param cartQuantity - Quantity already in cart\n * @param maxPurchaseQuantity - Maximum allowed purchase quantity (optional)\n * @returns Maximum quantity that can be added\n */\nexport function getMaxAddToCartQuantity(\n status: StockStatus,\n stockQuantity?: number | null,\n cartQuantity = 0,\n maxPurchaseQuantity?: number | null\n): number {\n // Out of stock - can't add any\n if (status === 'outofstock') {\n return 0;\n }\n\n // Backorder - theoretically unlimited, use max purchase qty or default high number\n if (status === 'onbackorder') {\n return maxPurchaseQuantity ?? 999;\n }\n\n // In stock - limited by available quantity\n let maxQty = stockQuantity ?? 999;\n\n // Apply max purchase quantity if set\n if (maxPurchaseQuantity && maxPurchaseQuantity < maxQty) {\n maxQty = maxPurchaseQuantity;\n }\n\n // Subtract what's already in cart\n return Math.max(0, maxQty - cartQuantity);\n}\n","import type { CartItemImage, ProductImage } from '@atomic-solutions/woocommerce-api-client';\n\nexport type { CartItemImage, ProductImage };\n/**\n * Union type for any WooCommerce image (product or cart item)\n * Both have the same structure: id, src, name, alt, thumbnail, srcset, sizes\n */\nexport type WooCommerceImage = ProductImage | CartItemImage;\n\n/**\n * Image size options\n */\nexport type ImageSize = 'thumbnail' | 'medium' | 'large' | 'full';\n\n/**\n * WordPress image size suffixes\n */\nconst SIZE_SUFFIXES: Record<ImageSize, string> = {\n thumbnail: '-150x150',\n medium: '-300x300',\n large: '-1024x1024',\n full: '',\n};\n\n/**\n * Get the primary image from an images array\n *\n * @param images - Array of product or cart item images\n * @returns Primary image or undefined\n *\n * @example\n * const mainImage = getPrimaryImage(product.images);\n * if (mainImage) {\n * return <Image source={{ uri: mainImage.src }} />;\n * }\n */\nexport function getPrimaryImage(images?: WooCommerceImage[] | null): WooCommerceImage | undefined {\n if (!images || images.length === 0) {\n return undefined;\n }\n\n return images[0];\n}\n\n/**\n * Get image URL from an images array\n *\n * @param images - Array of product or cart item images\n * @param size - Desired image size\n * @param fallback - Fallback URL if no images\n * @returns Image URL or fallback\n *\n * @example\n * const imageUrl = getImageUrl(product.images, 'medium');\n * <Image source={{ uri: imageUrl }} />\n */\nexport function getImageUrl(\n images?: WooCommerceImage[] | null,\n size: ImageSize = 'full',\n fallback?: string\n): string | undefined {\n const primary = getPrimaryImage(images);\n\n if (!primary) {\n return fallback;\n }\n\n return getSizedImageUrl(primary.src, size);\n}\n\n/**\n * Get a sized version of an image URL\n *\n * WordPress stores images with size suffixes like:\n * - image-150x150.jpg (thumbnail)\n * - image-300x300.jpg (medium)\n * - image-1024x1024.jpg (large)\n * - image.jpg (full)\n *\n * @param url - Original image URL\n * @param size - Desired size\n * @returns Sized image URL\n */\nexport function getSizedImageUrl(url: string, size: ImageSize = 'full'): string {\n if (!url || size === 'full') {\n return url;\n }\n\n // Check if URL already has a size suffix\n const hasSize = Object.values(SIZE_SUFFIXES).some((suffix) => suffix && url.includes(suffix));\n\n if (hasSize) {\n // Replace existing size with new size\n let result = url;\n Object.values(SIZE_SUFFIXES).forEach((suffix) => {\n if (suffix) {\n result = result.replace(suffix, SIZE_SUFFIXES[size]);\n }\n });\n return result;\n }\n\n // Add size suffix before extension\n const suffix = SIZE_SUFFIXES[size];\n const lastDot = url.lastIndexOf('.');\n\n if (lastDot === -1) {\n return url;\n }\n\n return `${url.slice(0, lastDot)}${suffix}${url.slice(lastDot)}`;\n}\n\n/**\n * Get all image URLs from an images array\n *\n * @param images - Array of product or cart item images\n * @param size - Desired image size\n * @returns Array of image URLs\n */\nexport function getAllImageUrls(\n images?: WooCommerceImage[] | null,\n size: ImageSize = 'full'\n): string[] {\n if (!images || images.length === 0) {\n return [];\n }\n\n return images.map((img) => getSizedImageUrl(img.src, size));\n}\n\n/**\n * Placeholder image URL for products without images\n */\nexport const PLACEHOLDER_IMAGE_URL = 'https://via.placeholder.com/300x300.png?text=No+Image';\n\n/**\n * Get image URL with fallback to placeholder\n *\n * @param images - Array of product or cart item images\n * @param size - Desired image size\n * @returns Image URL or placeholder\n */\nexport function getImageUrlOrPlaceholder(\n images?: WooCommerceImage[] | null,\n size: ImageSize = 'medium'\n): string {\n return getImageUrl(images, size, PLACEHOLDER_IMAGE_URL) ?? PLACEHOLDER_IMAGE_URL;\n}\n\n/**\n * Preload an image to cache it\n *\n * Note: In React Native, you should use React Native's Image.prefetch instead.\n * This is a no-op placeholder that resolves immediately.\n *\n * @param _url - Image URL to preload (unused in this implementation)\n * @returns Promise that resolves immediately\n *\n * @example\n * // In React Native, use:\n * // import { Image } from 'react-native';\nimport CartItemImage from '@atomic-solutions/woocommerce-api-client';\n * // await Image.prefetch(url);\n */\nexport async function preloadImage(_url: string): Promise<void> {\n // No-op in this package - consumers should use React Native's Image.prefetch\n return Promise.resolve();\n}\n\n/**\n * Preload multiple images\n *\n * @param urls - Array of image URLs to preload\n * @returns Promise that resolves when all images are loaded\n */\nexport async function preloadImages(urls: string[]): Promise<void> {\n await Promise.all(urls.map(preloadImage));\n}\n","import { useCallback, useContext, useMemo } from 'react';\nimport type { Product, ProductCategory, ProductParams } from '@atomic-solutions/woocommerce-api-client';\n\nimport { useInfiniteProducts, useProductCategoryTree } from '..';\nimport { DEFAULT_STORE_CONFIG } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\nimport { getImageUrl, type ImageSize } from '../utils/image';\nimport { formatStoreApiPriceIntl } from '../utils/price';\n\n/**\n * Processed product with formatted data ready for display\n */\nexport interface ProcessedProduct {\n id: number;\n name: string;\n slug: string;\n permalink: string;\n imageUrl: string | undefined;\n /** Formatted current price */\n price: string;\n /** Formatted regular price */\n regularPrice: string;\n /** Whether on sale */\n isOnSale: boolean;\n /** Whether can be added to cart */\n canAddToCart: boolean;\n /** Raw product data for advanced use cases */\n raw: Product;\n}\n\n/**\n * Category with subcategories for tree display\n */\nexport interface ProcessedCategory extends ProductCategory {\n subCategories?: ProcessedCategory[];\n}\n\n/**\n * Options for useProductsFeed hook\n */\nexport interface UseProductsFeedOptions {\n /** Query parameters for filtering products */\n params?: ProductParams;\n /**\n * Locale tag override (e.g., 'en-US', 'bs-BA')\n * If not provided, uses value from WooCommerceStoreProvider context\n */\n localeTag?: string;\n /**\n * Fallback image URL override\n * If not provided, uses value from WooCommerceStoreProvider config\n */\n fallbackImageUrl?: string;\n /** Image size to use (default: 'medium') */\n imageSize?: ImageSize;\n}\n\n/**\n * Return type for useProductsFeed hook\n */\nexport interface UseProductsFeedReturn {\n /** Processed products ready for display */\n products: ProcessedProduct[];\n /** Whether initial load is in progress */\n isLoading: boolean;\n /** Whether fetching next page */\n isFetchingNextPage: boolean;\n /** Error if any */\n error: Error | null;\n /** Whether there are more pages to load */\n hasNextPage: boolean;\n /** Load next page of products */\n fetchNextPage: () => void;\n /** Refresh the product list */\n refresh: () => Promise<void>;\n /** Whether refreshing */\n isRefreshing: boolean;\n /** Active category if filtering by category */\n activeCategory: ProcessedCategory | undefined;\n /** Category tree for filtering */\n categoryTree: ProcessedCategory[];\n /** Find category by ID */\n findCategoryById: (id: number) => ProcessedCategory | undefined;\n /** Total product count (approximate, from first page) */\n totalCount: number;\n}\n\n/**\n * Hook for managing infinite product listing with category filtering\n *\n * Provides all the logic needed to build a product feed UI:\n * - Infinite scroll pagination\n * - Product data processing (images, prices)\n * - Category tree for filtering\n * - Refresh functionality\n *\n * Uses locale configuration from WooCommerceStoreProvider context.\n *\n * @example\n * ```tsx\n * function ProductFeed() {\n * const {\n * products,\n * isLoading,\n * hasNextPage,\n * fetchNextPage,\n * refresh,\n * isRefreshing,\n * } = useProductsFeed({ params: { category: 123 } });\n *\n * return (\n * <FlatList\n * data={products}\n * renderItem={({ item }) => (\n * <ProductCard\n * name={item.name}\n * imageUrl={item.imageUrl}\n * price={item.price}\n * />\n * )}\n * onEndReached={() => hasNextPage && fetchNextPage()}\n * refreshing={isRefreshing}\n * onRefresh={refresh}\n * />\n * );\n * }\n * ```\n */\nexport function useProductsFeed(options: UseProductsFeedOptions = {}): UseProductsFeedReturn {\n const { params, imageSize = 'medium' } = options;\n\n // Get config from context (optional - hooks work without provider too)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeConfig = storeContext?.config;\n\n // Resolve locale tag: param override > context > default\n const localeTag =\n options.localeTag ?? storeConfig?.locale?.localeTag ?? DEFAULT_STORE_CONFIG.locale.localeTag;\n\n // Resolve fallback image: param override > context > undefined\n const fallbackImageUrl = options.fallbackImageUrl ?? storeConfig?.fallbackImageUrl;\n\n // Get image transformer from config\n const imageUrlTransformer = storeConfig?.imageUrlTransformer;\n\n // Fetch products with infinite pagination\n const {\n data: productsData,\n isLoading,\n isFetchingNextPage,\n error,\n hasNextPage = false,\n fetchNextPage,\n refetch,\n isRefetching,\n } = useInfiniteProducts(params);\n\n // Fetch category tree\n const { treeData: categoryTree = [], findById } = useProductCategoryTree();\n\n // Helper to get image URL with transformer support\n const getProcessedImageUrl = useCallback(\n (images: Product['images'] | undefined): string | undefined => {\n const baseUrl = getImageUrl(images, imageSize, fallbackImageUrl);\n\n // Apply custom transformer if provided\n if (baseUrl && imageUrlTransformer) {\n return imageUrlTransformer(baseUrl, imageSize);\n }\n\n return baseUrl;\n },\n [imageSize, fallbackImageUrl, imageUrlTransformer]\n );\n\n // Process products for display\n const products = useMemo<ProcessedProduct[]>(() => {\n if (!productsData) return [];\n\n // productsData is Product[] from useInfiniteProducts\n const productList: Product[] = Array.isArray(productsData) ? productsData : [];\n\n return productList.map((product): ProcessedProduct => {\n const currencyCode = product.prices?.currency_code;\n\n return {\n id: product.id,\n name: product.name,\n slug: product.slug,\n permalink: product.permalink,\n imageUrl: getProcessedImageUrl(product.images),\n price: formatStoreApiPriceIntl(product.prices?.price, currencyCode, localeTag),\n regularPrice: formatStoreApiPriceIntl(\n product.prices?.regular_price,\n currencyCode,\n localeTag\n ),\n isOnSale: product.on_sale,\n canAddToCart: product.is_purchasable && product.is_in_stock,\n raw: product,\n };\n });\n }, [productsData, localeTag, getProcessedImageUrl]);\n\n // Find active category from params\n const activeCategory = useMemo(() => {\n if (!params?.category) return undefined;\n return findById(params.category) as ProcessedCategory | undefined;\n }, [params, findById]);\n\n // Refresh handler\n const refresh = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n // Total count (use array length as approximation)\n const totalCount = products.length;\n\n return {\n products,\n isLoading,\n isFetchingNextPage,\n error: error as Error | null,\n hasNextPage,\n fetchNextPage,\n refresh,\n isRefreshing: isRefetching,\n activeCategory,\n categoryTree: categoryTree as ProcessedCategory[],\n findCategoryById: findById as (id: number) => ProcessedCategory | undefined,\n totalCount,\n };\n}\n","import { useCallback, useContext, useMemo, useState } from 'react';\nimport type { Product } from '@atomic-solutions/woocommerce-api-client';\n\nimport { useAddToCart, useCart, useProduct, useRemoveFromCart, useUpdateCartItem } from '..';\nimport { DEFAULT_STORE_CONFIG } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\nimport { getAllImageUrls, getImageUrl, type ImageSize } from '../utils/image';\nimport { calculateDiscount, formatStoreApiPriceIntl } from '../utils/price';\nimport { getStockStatusText, isLowStock, isPurchasable, type StockStatus } from '../utils/stock';\n\n/**\n * Processed product details ready for display\n */\nexport interface ProcessedProductDetails {\n id: number;\n name: string;\n slug: string;\n permalink: string;\n description: string;\n shortDescription: string;\n sku: string;\n /** Primary image URL */\n imageUrl: string | undefined;\n /** All image URLs for gallery */\n imageUrls: string[];\n /** Formatted current price */\n price: string;\n /** Formatted regular price */\n regularPrice: string;\n /** Whether product is on sale */\n isOnSale: boolean;\n /** Discount percentage (e.g., 20 for 20% off) */\n discountPercent: number | null;\n /** Formatted discount badge (e.g., \"-20%\") */\n discountBadge: string | null;\n /** Stock status text for display */\n stockStatusText: string;\n /** Whether product can be purchased */\n isPurchasable: boolean;\n /** Whether stock is low */\n isLowStock: boolean;\n /** Maximum quantity that can be added to cart */\n maxQuantity: number;\n /** Minimum quantity */\n minQuantity: number;\n /** Raw product data */\n raw: Product;\n}\n\n/**\n * Cart state for the product\n */\nexport interface ProductCartState {\n /** Whether product is in cart */\n isInCart: boolean;\n /** Current quantity in cart */\n quantityInCart: number;\n /** Cart item key (for updates/removal) */\n cartItemKey: string | null;\n /** Quantity limits from cart item */\n cartQuantityLimits: {\n minimum: number;\n maximum: number;\n } | null;\n}\n\n/**\n * Options for useProductView hook\n */\nexport interface UseProductViewOptions {\n /** Product ID */\n productId: number;\n /**\n * Locale tag override (e.g., 'en-US', 'bs-BA')\n * If not provided, uses value from WooCommerceStoreProvider context\n */\n localeTag?: string;\n /**\n * Fallback image URL override\n * If not provided, uses value from WooCommerceStoreProvider config\n */\n fallbackImageUrl?: string;\n /** Image size for primary image (default: 'large') */\n imageSize?: ImageSize;\n /** Low stock threshold (default: 5) */\n lowStockThreshold?: number;\n}\n\n/**\n * Return type for useProductView hook\n */\nexport interface UseProductViewReturn {\n /** Processed product details */\n product: ProcessedProductDetails | null;\n /** Loading state */\n isLoading: boolean;\n /** Error if any */\n error: Error | null;\n /** Refresh product data */\n refresh: () => Promise<void>;\n\n // Cart state\n /** Cart state for this product */\n cartState: ProductCartState;\n\n // Cart actions\n /** Draft quantity for adding to cart */\n draftQuantity: number;\n /** Set draft quantity */\n setDraftQuantity: (quantity: number) => void;\n /** Add product to cart */\n addToCart: () => Promise<void>;\n /** Remove product from cart */\n removeFromCart: () => Promise<void>;\n /** Update quantity in cart */\n updateCartQuantity: (quantity: number) => Promise<void>;\n\n // Loading states for cart operations\n /** Whether adding to cart */\n isAddingToCart: boolean;\n /** Whether removing from cart */\n isRemovingFromCart: boolean;\n /** Whether updating cart */\n isUpdatingCart: boolean;\n /** Whether any cart operation is in progress */\n isCartBusy: boolean;\n}\n\n/**\n * Hook for managing product detail view with cart integration\n *\n * Uses locale configuration from WooCommerceStoreProvider context.\n *\n * @example\n * ```tsx\n * function ProductDetail({ productId }: { productId: number }) {\n * const {\n * product,\n * isLoading,\n * cartState,\n * draftQuantity,\n * setDraftQuantity,\n * addToCart,\n * removeFromCart,\n * isCartBusy,\n * } = useProductView({ productId });\n *\n * if (isLoading) return <Loader />;\n * if (!product) return <NotFound />;\n *\n * return (\n * <View>\n * <Image source={{ uri: product.imageUrl }} />\n * <Text>{product.name}</Text>\n * <Text>{product.price}</Text>\n * <Text>{product.stockStatusText}</Text>\n * {cartState.isInCart ? (\n * <Button onPress={removeFromCart} disabled={isCartBusy}>\n * Remove from Cart\n * </Button>\n * ) : (\n * <>\n * <QuantityInput\n * value={draftQuantity}\n * onChange={setDraftQuantity}\n * max={product.maxQuantity}\n * />\n * <Button onPress={addToCart} disabled={isCartBusy}>\n * Add to Cart\n * </Button>\n * </>\n * )}\n * </View>\n * );\n * }\n * ```\n */\nexport function useProductView(options: UseProductViewOptions): UseProductViewReturn {\n const { productId, imageSize = 'large', lowStockThreshold = 5 } = options;\n\n // Get config from context (optional)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeConfig = storeContext?.config;\n\n // Resolve locale tag\n const localeTag =\n options.localeTag ?? storeConfig?.locale?.localeTag ?? DEFAULT_STORE_CONFIG.locale.localeTag;\n\n // Resolve fallback image\n const fallbackImageUrl = options.fallbackImageUrl ?? storeConfig?.fallbackImageUrl;\n\n // Get image transformer from config\n const imageUrlTransformer = storeConfig?.imageUrlTransformer;\n\n // Local state for draft quantity\n const [draftQuantity, setDraftQuantity] = useState(1);\n\n // Fetch product\n const { data: productData, isLoading, error, refetch } = useProduct(productId);\n\n // Fetch cart\n const { data: cartData } = useCart();\n\n // Cart mutations\n const addToCartMutation = useAddToCart();\n const removeFromCartMutation = useRemoveFromCart();\n const updateCartMutation = useUpdateCartItem();\n\n // Helper to process image URL\n const processImageUrl = useCallback(\n (url: string | undefined): string | undefined => {\n if (!url) return url;\n if (imageUrlTransformer) {\n return imageUrlTransformer(url, imageSize);\n }\n return url;\n },\n [imageUrlTransformer, imageSize]\n );\n\n // Process product data\n const product = useMemo<ProcessedProductDetails | null>(() => {\n if (!productData) return null;\n\n const currencyCode = productData.prices?.currency_code;\n\n // Determine stock status from product flags\n const stockStatus: StockStatus = productData.is_on_backorder\n ? 'onbackorder'\n : productData.is_in_stock\n ? 'instock'\n : 'outofstock';\n\n // Get low stock remaining (can be null)\n const lowStockRemaining = productData.low_stock_remaining;\n\n // Get base image URLs\n const baseImageUrl = getImageUrl(productData.images, imageSize, fallbackImageUrl);\n\n const baseImageUrls = getAllImageUrls(productData.images, imageSize);\n\n return {\n id: productData.id,\n name: productData.name,\n slug: productData.slug,\n permalink: productData.permalink,\n description: productData.description,\n shortDescription: productData.short_description,\n sku: productData.sku,\n imageUrl: processImageUrl(baseImageUrl),\n imageUrls: baseImageUrls.map((url) => processImageUrl(url) ?? url),\n price: formatStoreApiPriceIntl(productData.prices?.price, currencyCode, localeTag),\n regularPrice: formatStoreApiPriceIntl(\n productData.prices?.regular_price,\n currencyCode,\n localeTag\n ),\n isOnSale: productData.on_sale,\n discountPercent: calculateDiscount(\n productData.prices?.regular_price ?? '0',\n productData.prices?.price ?? '0'\n ),\n discountBadge: productData.on_sale\n ? `-${calculateDiscount(\n productData.prices?.regular_price ?? '0',\n productData.prices?.price ?? '0'\n )}%`\n : null,\n stockStatusText: getStockStatusText(stockStatus, lowStockRemaining ?? undefined, {\n lowStockThreshold,\n }),\n isPurchasable: isPurchasable(\n stockStatus,\n lowStockRemaining ?? undefined,\n productData.sold_individually\n ),\n isLowStock: isLowStock(stockStatus, lowStockRemaining ?? undefined, lowStockThreshold),\n maxQuantity: productData.add_to_cart?.maximum ?? 999,\n minQuantity: productData.add_to_cart?.minimum ?? 1,\n raw: productData,\n };\n }, [productData, localeTag, fallbackImageUrl, imageSize, lowStockThreshold, processImageUrl]);\n\n // Find cart item for this product\n const cartItem = useMemo(() => {\n return cartData?.items.find((item) => item.id === productId);\n }, [cartData?.items, productId]);\n\n // Cart state\n const cartState = useMemo<ProductCartState>(\n () => ({\n isInCart: !!cartItem,\n quantityInCart: cartItem?.quantity ?? 0,\n cartItemKey: cartItem?.key ?? null,\n cartQuantityLimits: cartItem\n ? {\n minimum: cartItem.quantity_limits.minimum,\n maximum: cartItem.quantity_limits.maximum,\n }\n : null,\n }),\n [cartItem]\n );\n\n // Cart actions\n const addToCart = useCallback(async () => {\n await addToCartMutation.mutateAsync({\n id: productId,\n quantity: draftQuantity,\n });\n setDraftQuantity(1); // Reset after adding\n }, [addToCartMutation, productId, draftQuantity]);\n\n const removeFromCart = useCallback(async () => {\n if (!cartState.cartItemKey) return;\n await removeFromCartMutation.mutateAsync({\n key: cartState.cartItemKey,\n });\n }, [removeFromCartMutation, cartState.cartItemKey]);\n\n const updateCartQuantity = useCallback(\n async (quantity: number) => {\n if (!cartState.cartItemKey) return;\n await updateCartMutation.mutateAsync({\n key: cartState.cartItemKey,\n quantity,\n });\n },\n [updateCartMutation, cartState.cartItemKey]\n );\n\n const refresh = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n // Loading states\n const isAddingToCart = addToCartMutation.isPending;\n const isRemovingFromCart = removeFromCartMutation.isPending;\n const isUpdatingCart = updateCartMutation.isPending;\n const isCartBusy = isAddingToCart || isRemovingFromCart || isUpdatingCart;\n\n return {\n product,\n isLoading,\n error: error as Error | null,\n refresh,\n cartState,\n draftQuantity,\n setDraftQuantity,\n addToCart,\n removeFromCart,\n updateCartQuantity,\n isAddingToCart,\n isRemovingFromCart,\n isUpdatingCart,\n isCartBusy,\n };\n}\n","import { useCallback, useContext, useMemo } from 'react';\nimport type { Cart, CartItem } from '@atomic-solutions/woocommerce-api-client';\n\nimport {\n useApplyCoupon,\n useCart,\n useRemoveCoupon,\n useRemoveFromCart,\n useSelectShippingRate,\n useUpdateCartItem,\n} from '..';\nimport { DEFAULT_STORE_CONFIG } from '../provider/types';\nimport { WooCommerceStoreContext } from '../provider/WooCommerceStoreContext';\nimport { getImageUrl, type ImageSize, type WooCommerceImage } from '../utils/image';\nimport { formatStoreApiPriceIntl } from '../utils/price';\n\n/**\n * Processed cart item ready for display\n */\nexport interface ProcessedCartItem {\n /** Unique cart item key */\n key: string;\n /** Product ID */\n id: number;\n /** Product name */\n name: string;\n /** Product image URL */\n imageUrl: string | undefined;\n /** Current quantity */\n quantity: number;\n /** Minimum quantity allowed */\n minQuantity: number;\n /** Maximum quantity allowed */\n maxQuantity: number;\n /** Formatted line total */\n lineTotal: string;\n /** Formatted unit price */\n unitPrice: string;\n /** Raw cart item */\n raw: CartItem;\n}\n\n/**\n * Cart totals for display\n */\nexport interface CartTotals {\n /** Formatted subtotal (items only) */\n subtotal: string;\n /** Formatted shipping total */\n shipping: string;\n /** Formatted tax total */\n tax: string;\n /** Formatted discount total */\n discount: string;\n /** Formatted grand total */\n total: string;\n /** Number of items in cart */\n itemCount: number;\n /** Currency code */\n currencyCode: string;\n}\n\n/**\n * Applied coupon info\n */\nexport interface AppliedCoupon {\n /** Coupon code */\n code: string;\n /** Formatted discount amount */\n discount: string;\n}\n\n/**\n * Shipping rate option\n */\nexport interface ShippingRate {\n /** Rate ID */\n rateId: string;\n /** Rate name (e.g., \"Free Shipping\") */\n name: string;\n /** Formatted price */\n price: string;\n /** Whether currently selected */\n isSelected: boolean;\n}\n\n/**\n * Payment method option\n * Note: WooCommerce Store API returns payment methods as string identifiers\n */\nexport interface PaymentMethod {\n /** Method ID (e.g., \"cod\", \"monri\") */\n id: string;\n /** Display title (derived from ID if not available) */\n title: string;\n}\n\n/**\n * Common payment method ID to display name mappings\n */\nconst PAYMENT_METHOD_TITLES: Record<string, string> = {\n cod: 'Cash on Delivery',\n monri: 'Monri',\n bacs: 'Bank Transfer',\n cheque: 'Check Payment',\n paypal: 'PayPal',\n stripe: 'Credit Card',\n};\n\n/**\n * Format payment method ID to human-readable title\n */\nfunction formatPaymentMethodTitle(methodId: string): string {\n // Check known mappings first\n const knownTitle = PAYMENT_METHOD_TITLES[methodId];\n if (knownTitle) {\n return knownTitle;\n }\n // Fallback: capitalize and replace underscores/dashes with spaces\n return methodId.replace(/[_-]/g, ' ').replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Options for useCartView hook\n */\nexport interface UseCartViewOptions {\n /**\n * Locale tag override (e.g., 'en-US', 'bs-BA')\n * If not provided, uses value from WooCommerceStoreProvider context\n */\n localeTag?: string;\n /**\n * Fallback image URL override\n * If not provided, uses value from WooCommerceStoreProvider config\n */\n fallbackImageUrl?: string;\n /** Image size for cart items (default: 'thumbnail') */\n imageSize?: ImageSize;\n}\n\n/**\n * Return type for useCartView hook\n */\nexport interface UseCartViewReturn {\n // Cart data\n /** Processed cart items */\n items: ProcessedCartItem[];\n /** Cart totals */\n totals: CartTotals;\n /** Applied coupons */\n coupons: AppliedCoupon[];\n /** Available shipping rates */\n shippingRates: ShippingRate[];\n /** Available payment methods */\n paymentMethods: PaymentMethod[];\n /** Whether cart is empty */\n isEmpty: boolean;\n /** Whether cart needs shipping */\n needsShipping: boolean;\n /** Raw cart data */\n raw: Cart | undefined;\n\n // Loading states\n /** Whether loading cart */\n isLoading: boolean;\n /** Error if any */\n error: Error | null;\n\n // Item actions\n /** Update item quantity */\n updateItemQuantity: (key: string, quantity: number) => Promise<void>;\n /** Remove item from cart */\n removeItem: (key: string) => Promise<void>;\n /** Whether updating an item */\n isUpdatingItem: boolean;\n /** Whether removing an item */\n isRemovingItem: boolean;\n\n // Coupon actions\n /** Apply a coupon code */\n applyCoupon: (code: string) => Promise<void>;\n /** Remove a coupon */\n removeCoupon: (code: string) => Promise<void>;\n /** Whether applying coupon */\n isApplyingCoupon: boolean;\n /** Whether removing coupon */\n isRemovingCoupon: boolean;\n\n // Shipping actions\n /** Select shipping rate */\n selectShippingRate: (rateId: string, packageId?: string | number) => Promise<void>;\n /** Whether updating shipping */\n isUpdatingShipping: boolean;\n\n // General\n /** Refresh cart */\n refresh: () => Promise<void>;\n /** Whether any operation is in progress */\n isBusy: boolean;\n}\n\n/**\n * Hook for managing cart view with all cart operations\n *\n * @example\n * ```tsx\n * const {\n * items,\n * totals,\n * isEmpty,\n * updateItemQuantity,\n * removeItem,\n * applyCoupon,\n * isBusy,\n * } = useCartView({ locale: 'en-US' });\n *\n * if (isEmpty) return <EmptyCart />;\n *\n * return (\n * <View>\n * {items.map(item => (\n * <CartItemCard\n * key={item.key}\n * name={item.name}\n * imageUrl={item.imageUrl}\n * quantity={item.quantity}\n * price={item.lineTotal}\n * onQuantityChange={(q) => updateItemQuantity(item.key, q)}\n * onRemove={() => removeItem(item.key)}\n * />\n * ))}\n * <Text>Total: {totals.total}</Text>\n * </View>\n * );\n * ```\n */\nexport function useCartView(options: UseCartViewOptions = {}): UseCartViewReturn {\n const { imageSize = 'thumbnail' } = options;\n\n // Get config from context (optional - hooks work without provider too)\n const storeContext = useContext(WooCommerceStoreContext);\n const storeConfig = storeContext?.config;\n\n // Resolve locale tag: param override > context > default\n const localeTag =\n options.localeTag ?? storeConfig?.locale?.localeTag ?? DEFAULT_STORE_CONFIG.locale.localeTag;\n\n // Resolve fallback image: param override > context > undefined\n const fallbackImageUrl = options.fallbackImageUrl ?? storeConfig?.fallbackImageUrl;\n\n // Get image transformer from config\n const imageUrlTransformer = storeConfig?.imageUrlTransformer;\n\n // Fetch cart\n const { data: cartData, isLoading, error, refetch } = useCart();\n\n // Mutations\n const updateItemMutation = useUpdateCartItem();\n const removeItemMutation = useRemoveFromCart();\n const applyCouponMutation = useApplyCoupon();\n const removeCouponMutation = useRemoveCoupon();\n const selectShippingMutation = useSelectShippingRate();\n\n // Helper to process image URL with transformer\n const getProcessedImageUrl = useCallback(\n (images: WooCommerceImage[] | undefined): string | undefined => {\n const baseUrl = getImageUrl(images, imageSize, fallbackImageUrl);\n\n // Apply custom transformer if provided\n if (baseUrl && imageUrlTransformer) {\n return imageUrlTransformer(baseUrl, imageSize);\n }\n\n return baseUrl;\n },\n [imageSize, fallbackImageUrl, imageUrlTransformer]\n );\n\n // Process cart items\n const items = useMemo<ProcessedCartItem[]>(() => {\n if (!cartData?.items) return [];\n\n const currencyCode = cartData.totals.currency_code;\n\n return cartData.items.map(\n (item): ProcessedCartItem => ({\n key: item.key,\n id: item.id,\n name: item.name,\n imageUrl: getProcessedImageUrl(item.images),\n quantity: item.quantity,\n minQuantity: item.quantity_limits.minimum,\n maxQuantity: item.quantity_limits.maximum,\n lineTotal: formatStoreApiPriceIntl(item.totals.line_total, currencyCode, localeTag),\n unitPrice: formatStoreApiPriceIntl(item.prices.price, currencyCode, localeTag),\n raw: item,\n })\n );\n }, [cartData?.items, cartData?.totals.currency_code, localeTag, getProcessedImageUrl]);\n\n // Process totals\n const totals = useMemo<CartTotals>(() => {\n if (!cartData?.totals) {\n return {\n subtotal: '-',\n shipping: '-',\n tax: '-',\n discount: '-',\n total: '-',\n itemCount: 0,\n currencyCode: 'USD',\n };\n }\n\n const { totals: t } = cartData;\n const currencyCode = t.currency_code;\n\n return {\n subtotal: formatStoreApiPriceIntl(t.total_items, currencyCode, localeTag),\n shipping: formatStoreApiPriceIntl(t.total_shipping, currencyCode, localeTag),\n tax: formatStoreApiPriceIntl(t.total_tax, currencyCode, localeTag),\n discount: formatStoreApiPriceIntl(t.total_discount, currencyCode, localeTag),\n total: formatStoreApiPriceIntl(t.total_price, currencyCode, localeTag),\n itemCount: cartData.items_count,\n currencyCode,\n };\n }, [localeTag, cartData]);\n\n // Process coupons\n const coupons = useMemo<AppliedCoupon[]>(() => {\n if (!cartData?.coupons) return [];\n\n return cartData.coupons.map((coupon) => ({\n code: coupon.code,\n discount: formatStoreApiPriceIntl(\n coupon.totals.total_discount,\n coupon.totals.currency_code,\n localeTag\n ),\n }));\n }, [cartData?.coupons, localeTag]);\n\n // Process shipping rates\n const shippingRates = useMemo<ShippingRate[]>(() => {\n if (!cartData?.shipping_rates?.[0]?.shipping_rates) return [];\n\n const currencyCode = cartData.totals.currency_code;\n\n return cartData.shipping_rates[0].shipping_rates.map((rate) => ({\n rateId: rate.rate_id,\n name: rate.name,\n price: formatStoreApiPriceIntl(rate.price, currencyCode, localeTag),\n isSelected: rate.selected,\n }));\n }, [cartData?.shipping_rates, cartData?.totals.currency_code, localeTag]);\n\n // Process payment methods\n // Note: WooCommerce Store API returns payment_methods as string identifiers (e.g., \"cod\", \"monri\")\n const paymentMethods = useMemo<PaymentMethod[]>(() => {\n if (!cartData?.payment_methods) return [];\n\n return cartData.payment_methods.map((methodId) => {\n // Create a display-friendly title from the method ID\n const title = formatPaymentMethodTitle(methodId);\n return {\n id: methodId,\n title,\n };\n });\n }, [cartData?.payment_methods]);\n\n // Actions\n const updateItemQuantity = useCallback(\n async (key: string, quantity: number) => {\n await updateItemMutation.mutateAsync({ key, quantity });\n },\n [updateItemMutation]\n );\n\n const removeItem = useCallback(\n async (key: string) => {\n await removeItemMutation.mutateAsync({ key });\n },\n [removeItemMutation]\n );\n\n const applyCoupon = useCallback(\n async (code: string) => {\n await applyCouponMutation.mutateAsync({ code });\n },\n [applyCouponMutation]\n );\n\n const removeCoupon = useCallback(\n async (code: string) => {\n await removeCouponMutation.mutateAsync({ code });\n },\n [removeCouponMutation]\n );\n\n const selectShippingRate = useCallback(\n async (rateId: string, packageId: string | number = 0) => {\n await selectShippingMutation.mutateAsync({\n rate_id: rateId,\n package_id: packageId,\n });\n },\n [selectShippingMutation]\n );\n\n const refresh = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n // Loading states\n const isUpdatingItem = updateItemMutation.isPending;\n const isRemovingItem = removeItemMutation.isPending;\n const isApplyingCoupon = applyCouponMutation.isPending;\n const isRemovingCoupon = removeCouponMutation.isPending;\n const isUpdatingShipping = selectShippingMutation.isPending;\n\n const isBusy =\n isUpdatingItem || isRemovingItem || isApplyingCoupon || isRemovingCoupon || isUpdatingShipping;\n\n return {\n items,\n totals,\n coupons,\n shippingRates,\n paymentMethods,\n isEmpty: items.length === 0,\n needsShipping: cartData?.needs_shipping ?? false,\n raw: cartData,\n\n isLoading,\n error: error as Error | null,\n\n updateItemQuantity,\n removeItem,\n isUpdatingItem,\n isRemovingItem,\n\n applyCoupon,\n removeCoupon,\n isApplyingCoupon,\n isRemovingCoupon,\n\n selectShippingRate,\n isUpdatingShipping,\n\n refresh,\n isBusy,\n };\n}\n"]}
|