import { Component } from 'vue'; import { GraphQLClient, Product, Cluster, Cart, CartMainItem, AttributeFilter, ProductTextFilterInput, ProductsResponse, Category, Contact, Customer } from '@propeller-commerce/propeller-sdk-v2'; import { Availability } from '@propeller-commerce/propeller-v2-core-ui'; export interface ProductGridProps { /** * Initialised Propeller SDK GraphQL client. * Required when `products` is not provided — used for internal data fetching. */ graphqlClient?: GraphQLClient; /** * Pre-fetched products/clusters to display. * When provided the component skips internal API calls entirely. * Pass an empty array (not undefined) to show the empty state while the * parent controls loading. */ products?: (Product | Cluster)[]; /** Language code for product data. Defaults to 'NL'. */ language?: string; /** Tax zone used for price calculation. Defaults to 'NL'. */ taxZone?: string; /** * Category ID to list products for (category-page mode). * When omitted alongside `term` and `brand`, `config.baseCategoryId` is used. */ categoryId?: number; /** * Search term — passes `term` into categoryProductSearchInput and uses * `config.baseCategoryId` so the whole catalog is searched. */ term?: string; /** * Manufacturer/brand name — passes `manufacturers: [brand]` into * categoryProductSearchInput and uses `config.baseCategoryId`. */ brand?: string; /** Scope the product fetch to specific orderlist IDs (e.g. a chosen B2B contract). */ orderlistIds?: number[]; /** * Apply the orderlist filter. Defaults to `true` when `orderlistIds` is * non-empty, `false` otherwise — so an authenticated user without a contract * still sees the full catalogue. */ applyOrderlists?: boolean; /** * Attribute names to request per product, e.g. `['MPN']` — makes * `product.attributes` usable in card slots. Unset returns the first page of * ALL attributes (12 per product), so products with more than 12 silently * lose the rest. */ productTrackAttributes?: string[]; /** Number of columns in the grid. Accepts 2, 3, 4, 5, or 6. Defaults to 3. */ columns?: number; /** * Show a skeleton loader. * Useful when the parent controls loading state and passes `products` down. * The grid automatically shows a skeleton during internal fetches regardless * of this prop. Defaults to false. */ isLoading?: boolean; /** * Controls portal visibility mode. * 'open' — full e-commerce; AddToCart is visible in product cards. * 'semi-closed' — catalog-only; AddToCart is hidden. * Defaults to 'open'. */ portalMode?: string; /** Authenticated user passed through to ProductCard / AddToCart. */ user?: Contact | Customer | null; /** Active company ID from the company switcher. Overrides user's default company for price calculation. Triggers a re-fetch when changed. */ companyId?: number; /** * When true, tax-inclusive (gross) price is the leading price. * Defaults to false. */ includeTax?: boolean; /** * Enables stock validation inside AddToCart. * Blocks add when requested quantity exceeds available stock. * Defaults to false. */ stockValidation?: boolean; /** * When false, hides the AddToCart control in product cards. * ClusterCards always show their "View cluster" navigation button. * Defaults to true. */ allowAddToCart?: boolean; /** * Called after each internal data fetch with the filterable attributes * returned by the API (for driving a sibling FiltersSidebar). */ onFiltersChange?: (filters: AttributeFilter[]) => void; /** * Active text filters to apply — built by the parent from FiltersSidebar * `onFilterChange` callbacks. Each entry maps to a `textFilters` input * row in the CategoryService query. * When this prop changes the grid automatically re-fetches (page resets to 1). */ textFilters?: ProductTextFilterInput[]; /** * Active price range lower bound from the FiltersSidebar `onPriceChange`. * Triggers a re-fetch when changed. */ priceFilterMin?: number; /** * Active price range upper bound from the FiltersSidebar `onPriceChange`. * Triggers a re-fetch when changed. */ priceFilterMax?: number; /** * Active stock selection from the filters sidebar. Triggers a re-fetch when * changed. `'all'` or undefined means no stock filter. */ availability?: Availability; /** Minimum stock quantity for the `'in-stock'` selection. Defaults to the minimum threshold. */ minStock?: number; /** * Called when sort state changes internally (for syncing a sibling toolbar). */ onSortChange?: (sort: any) => void; /** * Called after each internal data fetch with the min/max price of the * current product set — use to populate a price range slider in the parent. */ onPriceBoundsChange?: (min: number, max: number) => void; /** * Called after each fetch with the total number of products found — * use to display a result count in the parent toolbar. */ onItemsFoundChange?: (count: number) => void; /** * Called after each fetch with the number of items visible on the current page * (after client-side language filtering). */ onPageItemCountChange?: (count: number) => void; /** * Called when the user clicks Previous / Next in the built-in pagination — * use to keep the parent URL / page state in sync. */ onPageChange?: (page: number) => void; /** * Called after each successful internal data fetch with the full * ProductsResponse object — use to drive an external GridPagination * component by passing the result as its `products` prop. */ onProductsResponse?: (products: ProductsResponse) => void; /** * Called after each successful internal data fetch with the full * Category object — use to populate sibling components like GridTitle, * CategoryDescription, and CategoryShortDescription. */ onCategoryChange?: (category: Category) => void; /** * Called whenever the internal loading state changes. * Use to disable sibling components (e.g. GridFilters) while a fetch is in flight. */ onLoadingChange?: (isLoading: boolean) => void; /** * Externally controlled current page. * When provided, the grid uses this value instead of its internal page * counter. Wire this to the `onPageChange` callback from a sibling * GridPagination so the two components stay in sync. * When changed the grid automatically re-fetches. */ page?: number; /** * Number of products per page. Defaults to 12. * When changed the grid automatically re-fetches (page resets to 1). */ pageSize?: number; /** * Sort field to use (e.g. 'NAME', 'PRICE'). * When provided overrides internal sort state. * When changed the grid automatically re-fetches (page resets to 1). */ sortField?: string; /** * Sort direction: 'ASC' or 'DESC'. * Only used when sortField is also provided. * When changed the grid automatically re-fetches (page resets to 1). */ sortOrder?: string; /** * Configuration object providing: * imageSearchFiltersGrid, imageVariantFiltersMedium — passed to CategoryService * baseCategoryId — used when querying by term or brand * urls.getProductUrl / urls.getClusterUrl — for card URL generation */ configuration?: any; /** ID of an existing cart to add items into. */ cartId?: string; /** * Auto-create a cart when none is available. * Always pair with `onCartCreated` to persist the new cart ID. */ createCart?: boolean; /** Called after AddToCart creates a new cart internally. */ onCartCreated?: (cart: Cart) => void; /** Called after every successful add-to-cart operation. */ afterAddToCart?: (cart: Cart, item?: CartMainItem) => void; /** * When true, AddToCart shows a success modal instead of a toast. * Defaults to false. */ showModal?: boolean; /** * Render − / + stepper buttons in AddToCart. * Defaults to true. */ allowIncrDecr?: boolean; /** Called when "Proceed to checkout" is clicked in the AddToCart modal. */ onProceedToCheckout?: () => void; /** Called when "Request a Quote" is clicked in the AddToCart modal. */ onRequestQuoteClick?: (cart: Cart) => void; /** * Called when an anonymous visitor clicks the log-in action that replaces * add-to-cart in a semi-closed portal. The host owns navigation. */ onLoginClick?: () => void; /** * Label overrides forwarded directly to the embedded AddToCart component. * Keys: add, adding, addedToCart, outOfStock, noCartId, errorAdding, * modalTitle, quantity, continueShopping, proceedToCheckout */ addToCartLabels?: Record; /** Translated labels forwarded to embedded `` instances. * See `ProductCardProps.labels` for slugs. */ productCardLabels?: Record; /** Translated labels forwarded to embedded `` instances. * See `ClusterCardProps.labels` for slugs. */ clusterCardLabels?: Record; /** * Show the stock / availability widget on each product card. * Forwarded directly to `ProductCard.showStock`. * Defaults to false. */ showStock?: boolean; /** * Show only the availability indicator inside the stock widget. * Forwarded to `ProductCard.showAvailability`. * Defaults to true. */ showAvailability?: boolean; /** * Show the price below the product name. * Defaults to true. */ showPrice?: boolean; /** * Label overrides forwarded to the embedded ItemStock component inside each card. * Keys: inStock, outOfStock, lowStock, available, notAvailable, pieces */ stockLabels?: Record; /** Translated labels forwarded to the embedded `` display * inside each ``. See `ProductPriceProps.labels` for slugs. */ priceLabels?: Record; /** Show a heart-icon favourite toggle on each card. */ enableAddFavorite?: boolean; /** * Called when a favourite is toggled on any card. * Receives the full Product or Cluster object and the new favourite state. */ onToggleFavorite?: (item: Product | Cluster, isFavorite: boolean) => void; /** * Called when a cluster card name, image, or "View cluster" button is * clicked — use for SPA-style routing instead of full-page navigation. */ onClusterClick?: (cluster: Cluster) => void; /** * Called when a product card name or image is clicked — use for SPA * routing instead of full-page navigation. */ onProductClick?: (product: Product) => void; /** Extra CSS class applied to the root element. */ className?: string; /** Translated labels keyed by the slugs used inside the component (see * `getLabel` calls). Missing keys fall back to the English defaults. */ labels?: Record; priceComponent?: Component; stockComponent?: Component; addToCartComponent?: Component; imageComponent?: Component; badgesComponent?: Component; favoriteComponent?: Component; productCardComponent?: Component; clusterCardComponent?: Component; /** * Render arbitrary content directly below each card's product name. Receives * the product as a prop; cascades to every ProductCard via ProductGridConfig. * Lets hosts surface extra per-product info (e.g. package descriptions) * across the whole grid without swapping the entire card. */ belowNameComponent?: Component; } declare function __VLS_template(): { attrs: Partial<{}>; slots: { beforeItem?(_: { item: Product | Cluster; index: number; }): any; afterItem?(_: { item: Product | Cluster; index: number; }): any; }; refs: {}; rootEl: HTMLDivElement; }; type __VLS_TemplateResult = ReturnType; declare const __VLS_component: import('vue').DefineComponent & Readonly<{}>, { applyOrderlists: boolean; showPrice: boolean; showStock: boolean; showAvailability: boolean; allowAddToCart: boolean; allowIncrDecr: boolean; isLoading: boolean; }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>; declare const _default: __VLS_WithTemplateSlots; export default _default; type __VLS_WithTemplateSlots = T & { new (): { $slots: S; }; };