@wix/headless-stores 0.0.36 → 0.0.38
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/cjs/dist/react/Category.d.ts +65 -59
- package/cjs/dist/react/Category.js +50 -83
- package/cjs/dist/react/CategoryList.d.ts +184 -0
- package/cjs/dist/react/CategoryList.js +174 -0
- package/cjs/dist/react/Product.d.ts +3 -3
- package/cjs/dist/react/Product.js +6 -6
- package/{dist/react/ProductsList.d.ts → cjs/dist/react/ProductList.d.ts} +71 -38
- package/cjs/dist/react/{ProductsList.js → ProductList.js} +30 -26
- package/cjs/dist/react/ProductListFilters.d.ts +244 -0
- package/cjs/dist/react/ProductListFilters.js +216 -0
- package/cjs/dist/react/ProductListPagination.d.ts +246 -0
- package/cjs/dist/react/ProductListPagination.js +207 -0
- package/cjs/dist/react/ProductListSort.d.ts +87 -0
- package/cjs/dist/react/ProductListSort.js +85 -0
- package/cjs/dist/react/ProductModifiers.d.ts +5 -5
- package/cjs/dist/react/ProductModifiers.js +10 -10
- package/cjs/dist/react/ProductVariantSelector.d.ts +5 -5
- package/cjs/dist/react/ProductVariantSelector.js +13 -10
- package/cjs/dist/react/SelectedVariant.d.ts +66 -3
- package/cjs/dist/react/SelectedVariant.js +106 -7
- package/cjs/dist/react/index.d.ts +6 -9
- package/cjs/dist/react/index.js +6 -9
- package/cjs/dist/services/buy-now-service.d.ts +208 -0
- package/cjs/dist/services/buy-now-service.js +132 -1
- package/cjs/dist/services/categories-list-service.d.ts +163 -0
- package/cjs/dist/services/categories-list-service.js +148 -0
- package/cjs/dist/services/category-service.d.ts +115 -70
- package/cjs/dist/services/category-service.js +101 -110
- package/cjs/dist/services/index.d.ts +6 -7
- package/cjs/dist/services/index.js +5 -16
- package/cjs/dist/services/pay-now-service.d.ts +146 -0
- package/cjs/dist/services/pay-now-service.js +112 -1
- package/cjs/dist/services/product-service.d.ts +71 -0
- package/cjs/dist/services/product-service.js +47 -0
- package/cjs/dist/services/products-list-filters-service.d.ts +292 -0
- package/cjs/dist/services/products-list-filters-service.js +446 -0
- package/cjs/dist/services/products-list-pagination-service.d.ts +186 -0
- package/cjs/dist/services/products-list-pagination-service.js +179 -0
- package/cjs/dist/services/products-list-service.d.ts +138 -52
- package/cjs/dist/services/products-list-service.js +185 -54
- package/cjs/dist/services/products-list-sort-service.d.ts +117 -0
- package/cjs/dist/services/products-list-sort-service.js +144 -0
- package/cjs/dist/utils/url-params.d.ts +68 -0
- package/cjs/dist/utils/url-params.js +72 -4
- package/dist/react/Category.d.ts +65 -59
- package/dist/react/Category.js +50 -83
- package/dist/react/CategoryList.d.ts +184 -0
- package/dist/react/CategoryList.js +174 -0
- package/dist/react/Product.d.ts +3 -3
- package/dist/react/Product.js +6 -6
- package/{cjs/dist/react/ProductsList.d.ts → dist/react/ProductList.d.ts} +71 -38
- package/dist/react/{ProductsList.js → ProductList.js} +30 -26
- package/dist/react/ProductListFilters.d.ts +244 -0
- package/dist/react/ProductListFilters.js +216 -0
- package/dist/react/ProductListPagination.d.ts +246 -0
- package/dist/react/ProductListPagination.js +207 -0
- package/dist/react/ProductListSort.d.ts +87 -0
- package/dist/react/ProductListSort.js +85 -0
- package/dist/react/ProductModifiers.d.ts +5 -5
- package/dist/react/ProductModifiers.js +10 -10
- package/dist/react/ProductVariantSelector.d.ts +5 -5
- package/dist/react/ProductVariantSelector.js +13 -10
- package/dist/react/SelectedVariant.d.ts +66 -3
- package/dist/react/SelectedVariant.js +106 -7
- package/dist/react/index.d.ts +6 -9
- package/dist/react/index.js +6 -9
- package/dist/services/buy-now-service.d.ts +208 -0
- package/dist/services/buy-now-service.js +132 -1
- package/dist/services/categories-list-service.d.ts +163 -0
- package/dist/services/categories-list-service.js +148 -0
- package/dist/services/category-service.d.ts +115 -70
- package/dist/services/category-service.js +101 -110
- package/dist/services/index.d.ts +6 -7
- package/dist/services/index.js +5 -16
- package/dist/services/pay-now-service.d.ts +146 -0
- package/dist/services/pay-now-service.js +112 -1
- package/dist/services/product-service.d.ts +71 -0
- package/dist/services/product-service.js +47 -0
- package/dist/services/products-list-filters-service.d.ts +292 -0
- package/dist/services/products-list-filters-service.js +446 -0
- package/dist/services/products-list-pagination-service.d.ts +186 -0
- package/dist/services/products-list-pagination-service.js +179 -0
- package/dist/services/products-list-service.d.ts +138 -52
- package/dist/services/products-list-service.js +185 -54
- package/dist/services/products-list-sort-service.d.ts +117 -0
- package/dist/services/products-list-sort-service.js +144 -0
- package/dist/utils/url-params.d.ts +68 -0
- package/dist/utils/url-params.js +72 -4
- package/package.json +3 -3
- package/cjs/dist/react/Collection.d.ts +0 -294
- package/cjs/dist/react/Collection.js +0 -345
- package/cjs/dist/react/FilteredCollection.d.ts +0 -299
- package/cjs/dist/react/FilteredCollection.js +0 -352
- package/cjs/dist/react/ProductActions.d.ts +0 -70
- package/cjs/dist/react/ProductActions.js +0 -104
- package/cjs/dist/react/RelatedProducts.d.ts +0 -169
- package/cjs/dist/react/RelatedProducts.js +0 -180
- package/cjs/dist/react/Sort.d.ts +0 -37
- package/cjs/dist/react/Sort.js +0 -36
- package/cjs/dist/services/catalog-service.d.ts +0 -36
- package/cjs/dist/services/catalog-service.js +0 -193
- package/cjs/dist/services/collection-service.d.ts +0 -124
- package/cjs/dist/services/collection-service.js +0 -628
- package/cjs/dist/services/filter-service.d.ts +0 -35
- package/cjs/dist/services/filter-service.js +0 -119
- package/cjs/dist/services/related-products-service.d.ts +0 -100
- package/cjs/dist/services/related-products-service.js +0 -127
- package/cjs/dist/services/sort-service.d.ts +0 -20
- package/cjs/dist/services/sort-service.js +0 -27
- package/dist/react/Collection.d.ts +0 -294
- package/dist/react/Collection.js +0 -345
- package/dist/react/FilteredCollection.d.ts +0 -299
- package/dist/react/FilteredCollection.js +0 -352
- package/dist/react/ProductActions.d.ts +0 -70
- package/dist/react/ProductActions.js +0 -104
- package/dist/react/RelatedProducts.d.ts +0 -169
- package/dist/react/RelatedProducts.js +0 -180
- package/dist/react/Sort.d.ts +0 -37
- package/dist/react/Sort.js +0 -36
- package/dist/services/catalog-service.d.ts +0 -36
- package/dist/services/catalog-service.js +0 -193
- package/dist/services/collection-service.d.ts +0 -124
- package/dist/services/collection-service.js +0 -628
- package/dist/services/filter-service.d.ts +0 -35
- package/dist/services/filter-service.js +0 -119
- package/dist/services/related-products-service.d.ts +0 -100
- package/dist/services/related-products-service.js +0 -127
- package/dist/services/sort-service.d.ts +0 -20
- package/dist/services/sort-service.js +0 -27
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { defineService, implementService } from "@wix/services-definitions";
|
|
2
|
-
import { SignalsServiceDefinition } from "@wix/services-definitions/core-services/signals";
|
|
3
|
-
import { URLParamsUtils } from "../utils/url-params.js";
|
|
4
|
-
import { CatalogServiceDefinition, } from "./catalog-service.js";
|
|
5
|
-
export const FilterServiceDefinition = defineService("filtered-collection");
|
|
6
|
-
export const defaultFilter = {
|
|
7
|
-
priceRange: { min: 0, max: 0 },
|
|
8
|
-
selectedOptions: {},
|
|
9
|
-
};
|
|
10
|
-
export const FilterService = implementService.withConfig()(FilterServiceDefinition, ({ getService, config }) => {
|
|
11
|
-
const signalsService = getService(SignalsServiceDefinition);
|
|
12
|
-
const catalogService = getService(CatalogServiceDefinition);
|
|
13
|
-
const currentFilters = signalsService.signal((config?.initialFilters || defaultFilter));
|
|
14
|
-
// Use computed signal for availableOptions to automatically track dependencies
|
|
15
|
-
const availableOptions = signalsService.computed(() => {
|
|
16
|
-
const catalogPriceRange = catalogService.catalogPriceRange.get();
|
|
17
|
-
const catalogOptions = catalogService.catalogOptions.get();
|
|
18
|
-
const priceRange = catalogPriceRange &&
|
|
19
|
-
catalogPriceRange.minPrice < catalogPriceRange.maxPrice
|
|
20
|
-
? { min: catalogPriceRange.minPrice, max: catalogPriceRange.maxPrice }
|
|
21
|
-
: { min: 0, max: 0 };
|
|
22
|
-
const productOptions = catalogOptions && catalogOptions.length > 0 ? catalogOptions : [];
|
|
23
|
-
return {
|
|
24
|
-
productOptions,
|
|
25
|
-
priceRange,
|
|
26
|
-
};
|
|
27
|
-
});
|
|
28
|
-
// Use computed signal for isFullyLoaded to automatically track dependencies
|
|
29
|
-
const isFullyLoaded = signalsService.computed(() => {
|
|
30
|
-
const catalogPriceRange = catalogService.catalogPriceRange.get();
|
|
31
|
-
const catalogOptions = catalogService.catalogOptions.get();
|
|
32
|
-
// Price range data is considered loaded whether it's null (no prices) or has valid data
|
|
33
|
-
const hasPriceRangeData = catalogPriceRange !== undefined; // includes null case
|
|
34
|
-
const hasOptionsData = !!(catalogOptions && catalogOptions.length >= 0); // Even 0 options is valid
|
|
35
|
-
return hasPriceRangeData && hasOptionsData;
|
|
36
|
-
});
|
|
37
|
-
// Effect to update currentFilters when catalog data loads (only if filters are at defaults)
|
|
38
|
-
signalsService.effect(() => {
|
|
39
|
-
const catalogPriceRange = catalogService.catalogPriceRange.get();
|
|
40
|
-
if (catalogPriceRange &&
|
|
41
|
-
catalogPriceRange.minPrice < catalogPriceRange.maxPrice) {
|
|
42
|
-
const priceRange = {
|
|
43
|
-
min: catalogPriceRange.minPrice,
|
|
44
|
-
max: catalogPriceRange.maxPrice,
|
|
45
|
-
};
|
|
46
|
-
// Update current filters to use catalog price range
|
|
47
|
-
const currentFiltersValue = currentFilters.get();
|
|
48
|
-
// Only update if current filter range is at defaults (either 0-0 or 0-1000)
|
|
49
|
-
const isDefaultRange = (currentFiltersValue.priceRange.min === 0 &&
|
|
50
|
-
currentFiltersValue.priceRange.max === 0) ||
|
|
51
|
-
(currentFiltersValue.priceRange.min === 0 &&
|
|
52
|
-
currentFiltersValue.priceRange.max === 1000);
|
|
53
|
-
if (isDefaultRange) {
|
|
54
|
-
currentFilters.set({
|
|
55
|
-
...currentFiltersValue,
|
|
56
|
-
priceRange,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
// Apply filters by delegating to the collection service
|
|
62
|
-
const applyFilters = async (filters) => {
|
|
63
|
-
currentFilters.set(filters);
|
|
64
|
-
// Update URL with filter parameters
|
|
65
|
-
const urlParams = {};
|
|
66
|
-
const availableOpts = availableOptions.get();
|
|
67
|
-
// Add price filters if different from defaults
|
|
68
|
-
if (availableOpts?.priceRange) {
|
|
69
|
-
if (filters.priceRange.min > availableOpts.priceRange.min) {
|
|
70
|
-
urlParams["minPrice"] = filters.priceRange.min.toString();
|
|
71
|
-
}
|
|
72
|
-
if (filters.priceRange.max < availableOpts.priceRange.max) {
|
|
73
|
-
urlParams["maxPrice"] = filters.priceRange.max.toString();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// Add option filters using option names as keys
|
|
77
|
-
if (availableOpts?.productOptions) {
|
|
78
|
-
Object.entries(filters.selectedOptions).forEach(([optionId, choiceIds]) => {
|
|
79
|
-
const option = availableOpts.productOptions.find((opt) => opt.id === optionId);
|
|
80
|
-
if (option && choiceIds.length > 0) {
|
|
81
|
-
const selectedChoices = option.choices.filter((choice) => choiceIds.includes(choice.id));
|
|
82
|
-
if (selectedChoices.length > 0) {
|
|
83
|
-
// Use 'availability' as URL param for inventory filter
|
|
84
|
-
const paramName = optionId === "inventory-filter" ? "availability" : option.name;
|
|
85
|
-
urlParams[paramName] = selectedChoices.map((choice) => choice.name);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
// Preserve existing sort parameter
|
|
91
|
-
const currentParams = URLParamsUtils.getURLParams();
|
|
92
|
-
if (currentParams["sort"]) {
|
|
93
|
-
urlParams["sort"] = currentParams["sort"];
|
|
94
|
-
}
|
|
95
|
-
URLParamsUtils.updateURL(urlParams);
|
|
96
|
-
};
|
|
97
|
-
// Clear all filters by applying default filter state
|
|
98
|
-
const clearFilters = async () => {
|
|
99
|
-
const availablePriceRange = availableOptions.get()?.priceRange;
|
|
100
|
-
currentFilters.set({
|
|
101
|
-
...defaultFilter,
|
|
102
|
-
priceRange: availablePriceRange || { min: 0, max: 0 },
|
|
103
|
-
});
|
|
104
|
-
// Clear filter parameters from URL, keeping only sort parameter
|
|
105
|
-
const currentParams = URLParamsUtils.getURLParams();
|
|
106
|
-
const urlParams = {};
|
|
107
|
-
if (currentParams["sort"]) {
|
|
108
|
-
urlParams["sort"] = currentParams["sort"];
|
|
109
|
-
}
|
|
110
|
-
URLParamsUtils.updateURL(urlParams);
|
|
111
|
-
};
|
|
112
|
-
return {
|
|
113
|
-
currentFilters,
|
|
114
|
-
applyFilters,
|
|
115
|
-
clearFilters,
|
|
116
|
-
availableOptions,
|
|
117
|
-
isFullyLoaded,
|
|
118
|
-
};
|
|
119
|
-
});
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { type Signal } from "@wix/services-definitions/core-services/signals";
|
|
2
|
-
import * as productsV3 from "@wix/auto_sdk_stores_products-v-3";
|
|
3
|
-
export interface RelatedProductsServiceAPI {
|
|
4
|
-
relatedProducts: Signal<productsV3.V3Product[]>;
|
|
5
|
-
isLoading: Signal<boolean>;
|
|
6
|
-
error: Signal<string | null>;
|
|
7
|
-
hasRelatedProducts: Signal<boolean>;
|
|
8
|
-
loadRelatedProducts: (productId: string, limit?: number) => Promise<void>;
|
|
9
|
-
refreshRelatedProducts: () => Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
export declare const RelatedProductsServiceDefinition: string & {
|
|
12
|
-
__api: RelatedProductsServiceAPI;
|
|
13
|
-
__config: {};
|
|
14
|
-
isServiceDefinition?: boolean;
|
|
15
|
-
} & RelatedProductsServiceAPI;
|
|
16
|
-
export interface RelatedProductsServiceConfig {
|
|
17
|
-
productId: string;
|
|
18
|
-
limit?: number;
|
|
19
|
-
}
|
|
20
|
-
export declare const RelatedProductsService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
21
|
-
__api: RelatedProductsServiceAPI;
|
|
22
|
-
__config: {};
|
|
23
|
-
isServiceDefinition?: boolean;
|
|
24
|
-
} & RelatedProductsServiceAPI, RelatedProductsServiceConfig>;
|
|
25
|
-
/**
|
|
26
|
-
* Loads related products service configuration for SSR initialization.
|
|
27
|
-
* This function is designed to be used during Server-Side Rendering (SSR) to create
|
|
28
|
-
* configuration that tells the RelatedProductsService which product to load related products for.
|
|
29
|
-
* Unlike other loaders, this creates configuration rather than fetching data during SSR.
|
|
30
|
-
*
|
|
31
|
-
* @param productId The ID of the product to find related products for
|
|
32
|
-
* @param limit Optional number of related products to load (default: 4)
|
|
33
|
-
* @returns Promise that resolves to RelatedProductsServiceConfig
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```astro
|
|
37
|
-
* ---
|
|
38
|
-
* // Astro page example - pages/product/[slug].astro
|
|
39
|
-
* import { loadRelatedProductsServiceConfig } from '@wix/stores/services';
|
|
40
|
-
* import { RelatedProducts } from '@wix/stores/components';
|
|
41
|
-
*
|
|
42
|
-
* // Create related products config for a specific product
|
|
43
|
-
* const relatedProductsConfig = await loadRelatedProductsServiceConfig(
|
|
44
|
-
* 'product-id-123',
|
|
45
|
-
* 6
|
|
46
|
-
* );
|
|
47
|
-
* ---
|
|
48
|
-
*
|
|
49
|
-
* <RelatedProducts.Root relatedProductsConfig={relatedProductsConfig}>
|
|
50
|
-
* <RelatedProducts.List>
|
|
51
|
-
* {({ products, isLoading }) => (
|
|
52
|
-
* <div>
|
|
53
|
-
* {isLoading ? 'Loading...' : `${products.length} related products`}
|
|
54
|
-
* </div>
|
|
55
|
-
* )}
|
|
56
|
-
* </RelatedProducts.List>
|
|
57
|
-
* </RelatedProducts.Root>
|
|
58
|
-
* ```
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```tsx
|
|
62
|
-
* // Next.js page example - pages/product/[slug].tsx
|
|
63
|
-
* import { GetServerSideProps } from 'next';
|
|
64
|
-
* import { loadRelatedProductsServiceConfig } from '@wix/stores/services';
|
|
65
|
-
* import { RelatedProducts } from '@wix/stores/components';
|
|
66
|
-
*
|
|
67
|
-
* interface ProductPageProps {
|
|
68
|
-
* relatedProductsConfig: Awaited<ReturnType<typeof loadRelatedProductsServiceConfig>>;
|
|
69
|
-
* }
|
|
70
|
-
*
|
|
71
|
-
* export const getServerSideProps: GetServerSideProps<ProductPageProps> = async () => {
|
|
72
|
-
* // Create related products config for a specific product
|
|
73
|
-
* const relatedProductsConfig = await loadRelatedProductsServiceConfig(
|
|
74
|
-
* 'product-id-123',
|
|
75
|
-
* 6
|
|
76
|
-
* );
|
|
77
|
-
*
|
|
78
|
-
* return {
|
|
79
|
-
* props: {
|
|
80
|
-
* relatedProductsConfig,
|
|
81
|
-
* },
|
|
82
|
-
* };
|
|
83
|
-
* };
|
|
84
|
-
*
|
|
85
|
-
* export default function ProductPage({ relatedProductsConfig }: ProductPageProps) {
|
|
86
|
-
* return (
|
|
87
|
-
* <RelatedProducts.Root relatedProductsConfig={relatedProductsConfig}>
|
|
88
|
-
* <RelatedProducts.List>
|
|
89
|
-
* {({ products, isLoading }) => (
|
|
90
|
-
* <div>
|
|
91
|
-
* {isLoading ? 'Loading...' : `${products.length} related products`}
|
|
92
|
-
* </div>
|
|
93
|
-
* )}
|
|
94
|
-
* </RelatedProducts.List>
|
|
95
|
-
* </RelatedProducts.Root>
|
|
96
|
-
* );
|
|
97
|
-
* }
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
export declare function loadRelatedProductsServiceConfig(productId: string, limit?: number): Promise<RelatedProductsServiceConfig>;
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { defineService, implementService, } from "@wix/services-definitions";
|
|
2
|
-
import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
|
|
3
|
-
import * as productsV3 from "@wix/auto_sdk_stores_products-v-3";
|
|
4
|
-
export const RelatedProductsServiceDefinition = defineService("relatedProducts");
|
|
5
|
-
export const RelatedProductsService = implementService.withConfig()(RelatedProductsServiceDefinition, ({ getService, config }) => {
|
|
6
|
-
const signalsService = getService(SignalsServiceDefinition);
|
|
7
|
-
const relatedProducts = signalsService.signal([]);
|
|
8
|
-
const isLoading = signalsService.signal(false);
|
|
9
|
-
const error = signalsService.signal(null);
|
|
10
|
-
const hasRelatedProducts = signalsService.signal(false);
|
|
11
|
-
const loadRelatedProducts = async (productId, limit = 4) => {
|
|
12
|
-
isLoading.set(true);
|
|
13
|
-
error.set(null);
|
|
14
|
-
try {
|
|
15
|
-
let relatedQuery = productsV3.queryProducts().ne("_id", productId);
|
|
16
|
-
const relatedResult = await relatedQuery.limit(limit).find();
|
|
17
|
-
relatedProducts.set(relatedResult.items || []);
|
|
18
|
-
hasRelatedProducts.set((relatedResult.items || []).length > 0);
|
|
19
|
-
}
|
|
20
|
-
catch (err) {
|
|
21
|
-
const errorMessage = err instanceof Error
|
|
22
|
-
? err.message
|
|
23
|
-
: "Failed to load related products";
|
|
24
|
-
error.set(errorMessage);
|
|
25
|
-
relatedProducts.set([]);
|
|
26
|
-
hasRelatedProducts.set(false);
|
|
27
|
-
}
|
|
28
|
-
finally {
|
|
29
|
-
isLoading.set(false);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const refreshRelatedProducts = async () => {
|
|
33
|
-
await loadRelatedProducts(config.productId, config.limit);
|
|
34
|
-
};
|
|
35
|
-
if (config.productId) {
|
|
36
|
-
loadRelatedProducts(config.productId, config.limit);
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
relatedProducts,
|
|
40
|
-
isLoading,
|
|
41
|
-
error,
|
|
42
|
-
hasRelatedProducts,
|
|
43
|
-
loadRelatedProducts,
|
|
44
|
-
refreshRelatedProducts,
|
|
45
|
-
};
|
|
46
|
-
});
|
|
47
|
-
/**
|
|
48
|
-
* Loads related products service configuration for SSR initialization.
|
|
49
|
-
* This function is designed to be used during Server-Side Rendering (SSR) to create
|
|
50
|
-
* configuration that tells the RelatedProductsService which product to load related products for.
|
|
51
|
-
* Unlike other loaders, this creates configuration rather than fetching data during SSR.
|
|
52
|
-
*
|
|
53
|
-
* @param productId The ID of the product to find related products for
|
|
54
|
-
* @param limit Optional number of related products to load (default: 4)
|
|
55
|
-
* @returns Promise that resolves to RelatedProductsServiceConfig
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```astro
|
|
59
|
-
* ---
|
|
60
|
-
* // Astro page example - pages/product/[slug].astro
|
|
61
|
-
* import { loadRelatedProductsServiceConfig } from '@wix/stores/services';
|
|
62
|
-
* import { RelatedProducts } from '@wix/stores/components';
|
|
63
|
-
*
|
|
64
|
-
* // Create related products config for a specific product
|
|
65
|
-
* const relatedProductsConfig = await loadRelatedProductsServiceConfig(
|
|
66
|
-
* 'product-id-123',
|
|
67
|
-
* 6
|
|
68
|
-
* );
|
|
69
|
-
* ---
|
|
70
|
-
*
|
|
71
|
-
* <RelatedProducts.Root relatedProductsConfig={relatedProductsConfig}>
|
|
72
|
-
* <RelatedProducts.List>
|
|
73
|
-
* {({ products, isLoading }) => (
|
|
74
|
-
* <div>
|
|
75
|
-
* {isLoading ? 'Loading...' : `${products.length} related products`}
|
|
76
|
-
* </div>
|
|
77
|
-
* )}
|
|
78
|
-
* </RelatedProducts.List>
|
|
79
|
-
* </RelatedProducts.Root>
|
|
80
|
-
* ```
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```tsx
|
|
84
|
-
* // Next.js page example - pages/product/[slug].tsx
|
|
85
|
-
* import { GetServerSideProps } from 'next';
|
|
86
|
-
* import { loadRelatedProductsServiceConfig } from '@wix/stores/services';
|
|
87
|
-
* import { RelatedProducts } from '@wix/stores/components';
|
|
88
|
-
*
|
|
89
|
-
* interface ProductPageProps {
|
|
90
|
-
* relatedProductsConfig: Awaited<ReturnType<typeof loadRelatedProductsServiceConfig>>;
|
|
91
|
-
* }
|
|
92
|
-
*
|
|
93
|
-
* export const getServerSideProps: GetServerSideProps<ProductPageProps> = async () => {
|
|
94
|
-
* // Create related products config for a specific product
|
|
95
|
-
* const relatedProductsConfig = await loadRelatedProductsServiceConfig(
|
|
96
|
-
* 'product-id-123',
|
|
97
|
-
* 6
|
|
98
|
-
* );
|
|
99
|
-
*
|
|
100
|
-
* return {
|
|
101
|
-
* props: {
|
|
102
|
-
* relatedProductsConfig,
|
|
103
|
-
* },
|
|
104
|
-
* };
|
|
105
|
-
* };
|
|
106
|
-
*
|
|
107
|
-
* export default function ProductPage({ relatedProductsConfig }: ProductPageProps) {
|
|
108
|
-
* return (
|
|
109
|
-
* <RelatedProducts.Root relatedProductsConfig={relatedProductsConfig}>
|
|
110
|
-
* <RelatedProducts.List>
|
|
111
|
-
* {({ products, isLoading }) => (
|
|
112
|
-
* <div>
|
|
113
|
-
* {isLoading ? 'Loading...' : `${products.length} related products`}
|
|
114
|
-
* </div>
|
|
115
|
-
* )}
|
|
116
|
-
* </RelatedProducts.List>
|
|
117
|
-
* </RelatedProducts.Root>
|
|
118
|
-
* );
|
|
119
|
-
* }
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
122
|
-
export async function loadRelatedProductsServiceConfig(productId, limit = 4) {
|
|
123
|
-
return {
|
|
124
|
-
productId,
|
|
125
|
-
limit,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type Signal } from "@wix/services-definitions/core-services/signals";
|
|
2
|
-
import { SortType } from "../enums/sort-enums.js";
|
|
3
|
-
export type SortBy = SortType;
|
|
4
|
-
export interface SortServiceAPI {
|
|
5
|
-
currentSort: Signal<SortBy>;
|
|
6
|
-
setSortBy: (sortBy: SortBy) => Promise<void>;
|
|
7
|
-
}
|
|
8
|
-
export declare const SortServiceDefinition: string & {
|
|
9
|
-
__api: SortServiceAPI;
|
|
10
|
-
__config: {};
|
|
11
|
-
isServiceDefinition?: boolean;
|
|
12
|
-
} & SortServiceAPI;
|
|
13
|
-
export declare const defaultSort: SortBy;
|
|
14
|
-
export declare const SortService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
15
|
-
__api: SortServiceAPI;
|
|
16
|
-
__config: {};
|
|
17
|
-
isServiceDefinition?: boolean;
|
|
18
|
-
} & SortServiceAPI, {
|
|
19
|
-
initialSort?: SortBy;
|
|
20
|
-
}>;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { defineService, implementService } from "@wix/services-definitions";
|
|
2
|
-
import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
|
|
3
|
-
import { URLParamsUtils } from "../utils/url-params.js";
|
|
4
|
-
import { SortType, DEFAULT_SORT_TYPE } from "../enums/sort-enums.js";
|
|
5
|
-
export const SortServiceDefinition = defineService("sort");
|
|
6
|
-
export const defaultSort = DEFAULT_SORT_TYPE;
|
|
7
|
-
export const SortService = implementService.withConfig()(SortServiceDefinition, ({ getService, config }) => {
|
|
8
|
-
const signalsService = getService(SignalsServiceDefinition);
|
|
9
|
-
const currentSort = signalsService.signal((config?.initialSort || defaultSort));
|
|
10
|
-
const setSortBy = async (sortBy) => {
|
|
11
|
-
currentSort.set(sortBy);
|
|
12
|
-
// Update URL with sort parameter
|
|
13
|
-
const currentParams = URLParamsUtils.getURLParams();
|
|
14
|
-
const urlParams = { ...currentParams };
|
|
15
|
-
if (sortBy !== SortType.NEWEST) {
|
|
16
|
-
urlParams["sort"] = sortBy;
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
delete urlParams["sort"];
|
|
20
|
-
}
|
|
21
|
-
URLParamsUtils.updateURL(urlParams);
|
|
22
|
-
};
|
|
23
|
-
return {
|
|
24
|
-
currentSort,
|
|
25
|
-
setSortBy,
|
|
26
|
-
};
|
|
27
|
-
});
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import { type V3Product } from "@wix/auto_sdk_stores_products-v-3";
|
|
2
|
-
/**
|
|
3
|
-
* Props for Grid headless component
|
|
4
|
-
*/
|
|
5
|
-
export interface GridProps {
|
|
6
|
-
/** Render prop function that receives product grid data */
|
|
7
|
-
children: (props: GridRenderProps) => React.ReactNode;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Render props for Grid component
|
|
11
|
-
*/
|
|
12
|
-
export interface GridRenderProps {
|
|
13
|
-
/** Array of products */
|
|
14
|
-
products: V3Product[];
|
|
15
|
-
/** Whether products are loading */
|
|
16
|
-
isLoading: boolean;
|
|
17
|
-
/** Error message if any */
|
|
18
|
-
error: string | null;
|
|
19
|
-
/** Whether there are no products */
|
|
20
|
-
isEmpty: boolean;
|
|
21
|
-
/** Total number of products */
|
|
22
|
-
totalProducts: number;
|
|
23
|
-
/** Whether collection has products */
|
|
24
|
-
hasProducts: boolean;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Headless component for product grid
|
|
28
|
-
*
|
|
29
|
-
* @component
|
|
30
|
-
* @example
|
|
31
|
-
* ```tsx
|
|
32
|
-
* import { Collection } from '@wix/stores/components';
|
|
33
|
-
*
|
|
34
|
-
* function ProductGrid() {
|
|
35
|
-
* return (
|
|
36
|
-
* <Collection.Grid>
|
|
37
|
-
* {({ products, isLoading, error, isEmpty, totalProducts, hasProducts }) => (
|
|
38
|
-
* <div>
|
|
39
|
-
* {isLoading && <div>Loading products...</div>}
|
|
40
|
-
* {error && <div>Error: {error}</div>}
|
|
41
|
-
* {isEmpty && <div>No products found</div>}
|
|
42
|
-
* {hasProducts && (
|
|
43
|
-
* <div>
|
|
44
|
-
* <p>Showing {products.length} of {totalProducts} products</p>
|
|
45
|
-
* <div className="product-grid">
|
|
46
|
-
* {products.map(product => (
|
|
47
|
-
* <div key={product.id} className="product-card">
|
|
48
|
-
* <h3>{product.name}</h3>
|
|
49
|
-
* <p>{product.price?.price} {product.price?.currency}</p>
|
|
50
|
-
* </div>
|
|
51
|
-
* ))}
|
|
52
|
-
* </div>
|
|
53
|
-
* </div>
|
|
54
|
-
* )}
|
|
55
|
-
* </div>
|
|
56
|
-
* )}
|
|
57
|
-
* </Collection.Grid>
|
|
58
|
-
* );
|
|
59
|
-
* }
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
export declare const Grid: (props: GridProps) => import("react").ReactNode;
|
|
63
|
-
/**
|
|
64
|
-
* Props for Item headless component
|
|
65
|
-
*/
|
|
66
|
-
export interface ItemProps {
|
|
67
|
-
/** Product data */
|
|
68
|
-
product: V3Product;
|
|
69
|
-
/** Render prop function that receives product item data */
|
|
70
|
-
children: (props: ItemRenderProps) => React.ReactNode;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Render props for Item component
|
|
74
|
-
*/
|
|
75
|
-
export interface ItemRenderProps {
|
|
76
|
-
/** Product ID */
|
|
77
|
-
id: string;
|
|
78
|
-
/** Product title */
|
|
79
|
-
title: string;
|
|
80
|
-
/** Product slug for URL */
|
|
81
|
-
slug: string;
|
|
82
|
-
/** Main product image URL */
|
|
83
|
-
image: string | null;
|
|
84
|
-
/** Product price */
|
|
85
|
-
price: string;
|
|
86
|
-
/** Compare at price (for strikethrough) */
|
|
87
|
-
compareAtPrice: string | null;
|
|
88
|
-
/** Product description */
|
|
89
|
-
description: string;
|
|
90
|
-
/** Whether product is available */
|
|
91
|
-
available: boolean;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Headless component for individual product item
|
|
95
|
-
*
|
|
96
|
-
* @component
|
|
97
|
-
* @example
|
|
98
|
-
* ```tsx
|
|
99
|
-
* import { Collection } from '@wix/stores/components';
|
|
100
|
-
*
|
|
101
|
-
* function ProductCard({ product }) {
|
|
102
|
-
* return (
|
|
103
|
-
* <Collection.Item product={product}>
|
|
104
|
-
* {({ id, title, slug, image, price, compareAtPrice, description, available }) => (
|
|
105
|
-
* <div className={`product-card ${!available ? 'unavailable' : ''}`}>
|
|
106
|
-
* {image && <img src={image} alt={title} />}
|
|
107
|
-
* <h3>{title}</h3>
|
|
108
|
-
* <p>{description}</p>
|
|
109
|
-
* <div className="pricing">
|
|
110
|
-
* <span className="price">{price}</span>
|
|
111
|
-
* {compareAtPrice && (
|
|
112
|
-
* <span className="compare-price"><s>{compareAtPrice}</s></span>
|
|
113
|
-
* )}
|
|
114
|
-
* </div>
|
|
115
|
-
* {!available && <div className="badge">Out of Stock</div>}
|
|
116
|
-
* <a href={`/products/${slug}`}>View Product</a>
|
|
117
|
-
* </div>
|
|
118
|
-
* )}
|
|
119
|
-
* </Collection.Item>
|
|
120
|
-
* );
|
|
121
|
-
* }
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
export declare const Item: (props: ItemProps) => import("react").ReactNode;
|
|
125
|
-
/**
|
|
126
|
-
* Props for LoadMore headless component
|
|
127
|
-
*/
|
|
128
|
-
export interface LoadMoreProps {
|
|
129
|
-
/** Render prop function that receives load more data */
|
|
130
|
-
children: (props: LoadMoreRenderProps) => React.ReactNode;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Render props for LoadMore component
|
|
134
|
-
*/
|
|
135
|
-
export interface LoadMoreRenderProps {
|
|
136
|
-
/** Function to load more products */
|
|
137
|
-
loadMore: () => Promise<void>;
|
|
138
|
-
/** Function to refresh products */
|
|
139
|
-
refresh: () => Promise<void>;
|
|
140
|
-
/** Whether load more is currently loading */
|
|
141
|
-
isLoading: boolean;
|
|
142
|
-
/** Whether there are products */
|
|
143
|
-
hasProducts: boolean;
|
|
144
|
-
/** Total number of products currently loaded */
|
|
145
|
-
totalProducts: number;
|
|
146
|
-
/** Whether there are more products to load */
|
|
147
|
-
hasMoreProducts: boolean;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Headless component for load more products functionality
|
|
151
|
-
* Note: V3 API uses simplified loading without traditional pagination
|
|
152
|
-
*
|
|
153
|
-
* @component
|
|
154
|
-
* @example
|
|
155
|
-
* ```tsx
|
|
156
|
-
* import { Collection } from '@wix/stores/components';
|
|
157
|
-
*
|
|
158
|
-
* function LoadMoreButton() {
|
|
159
|
-
* return (
|
|
160
|
-
* <Collection.LoadMore>
|
|
161
|
-
* {({ loadMore, refresh, isLoading, hasProducts, totalProducts, hasMoreProducts }) => (
|
|
162
|
-
* <div className="load-more-section">
|
|
163
|
-
* {hasProducts && (
|
|
164
|
-
* <div>
|
|
165
|
-
* <p>Loaded {totalProducts} products</p>
|
|
166
|
-
* <div className="actions">
|
|
167
|
-
* {hasMoreProducts && (
|
|
168
|
-
* <button
|
|
169
|
-
* onClick={loadMore}
|
|
170
|
-
* disabled={isLoading}
|
|
171
|
-
* >
|
|
172
|
-
* {isLoading ? 'Loading...' : 'Load More Products'}
|
|
173
|
-
* </button>
|
|
174
|
-
* )}
|
|
175
|
-
* <button onClick={refresh}>Refresh Collection</button>
|
|
176
|
-
* </div>
|
|
177
|
-
* </div>
|
|
178
|
-
* )}
|
|
179
|
-
* </div>
|
|
180
|
-
* )}
|
|
181
|
-
* </Collection.LoadMore>
|
|
182
|
-
* );
|
|
183
|
-
* }
|
|
184
|
-
* ```
|
|
185
|
-
*/
|
|
186
|
-
export declare const LoadMore: (props: LoadMoreProps) => import("react").ReactNode;
|
|
187
|
-
/**
|
|
188
|
-
* Props for Header headless component
|
|
189
|
-
*/
|
|
190
|
-
export interface HeaderProps {
|
|
191
|
-
/** Render prop function that receives collection header data */
|
|
192
|
-
children: (props: HeaderRenderProps) => React.ReactNode;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Render props for Header component
|
|
196
|
-
*/
|
|
197
|
-
export interface HeaderRenderProps {
|
|
198
|
-
/** Total number of products */
|
|
199
|
-
totalProducts: number;
|
|
200
|
-
/** Whether collection is loading */
|
|
201
|
-
isLoading: boolean;
|
|
202
|
-
/** Whether collection has products */
|
|
203
|
-
hasProducts: boolean;
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Headless component for collection header with product count
|
|
207
|
-
*
|
|
208
|
-
* @component
|
|
209
|
-
* @example
|
|
210
|
-
* ```tsx
|
|
211
|
-
* import { Collection } from '@wix/stores/components';
|
|
212
|
-
*
|
|
213
|
-
* function CollectionHeader() {
|
|
214
|
-
* return (
|
|
215
|
-
* <Collection.Header>
|
|
216
|
-
* {({ totalProducts, isLoading, hasProducts }) => (
|
|
217
|
-
* <div className="collection-header">
|
|
218
|
-
* {isLoading && <div>Loading collection...</div>}
|
|
219
|
-
* {hasProducts && !isLoading && (
|
|
220
|
-
* <h2>Products ({totalProducts} items)</h2>
|
|
221
|
-
* )}
|
|
222
|
-
* {!hasProducts && !isLoading && (
|
|
223
|
-
* <h2>No products found</h2>
|
|
224
|
-
* )}
|
|
225
|
-
* </div>
|
|
226
|
-
* )}
|
|
227
|
-
* </Collection.Header>
|
|
228
|
-
* );
|
|
229
|
-
* }
|
|
230
|
-
* ```
|
|
231
|
-
*/
|
|
232
|
-
export declare const Header: (props: HeaderProps) => import("react").ReactNode;
|
|
233
|
-
/**
|
|
234
|
-
* Props for Actions headless component
|
|
235
|
-
*/
|
|
236
|
-
export interface ActionsProps {
|
|
237
|
-
/** Render prop function that receives collection actions data */
|
|
238
|
-
children: (props: ActionsRenderProps) => React.ReactNode;
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Render props for Actions component
|
|
242
|
-
*/
|
|
243
|
-
export interface ActionsRenderProps {
|
|
244
|
-
/** Function to refresh the collection */
|
|
245
|
-
refresh: () => Promise<void>;
|
|
246
|
-
/** Function to load more products */
|
|
247
|
-
loadMore: () => Promise<void>;
|
|
248
|
-
/** Whether actions are loading */
|
|
249
|
-
isLoading: boolean;
|
|
250
|
-
/** Error message if any */
|
|
251
|
-
error: string | null;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Headless component for collection actions (refresh, load more)
|
|
255
|
-
* Replaces traditional pagination for V3 API
|
|
256
|
-
*
|
|
257
|
-
* @component
|
|
258
|
-
* @example
|
|
259
|
-
* ```tsx
|
|
260
|
-
* import { Collection } from '@wix/stores/components';
|
|
261
|
-
*
|
|
262
|
-
* function CollectionActions() {
|
|
263
|
-
* return (
|
|
264
|
-
* <Collection.Actions>
|
|
265
|
-
* {({ refresh, loadMore, isLoading, error }) => (
|
|
266
|
-
* <div className="collection-actions">
|
|
267
|
-
* {error && (
|
|
268
|
-
* <div className="error">
|
|
269
|
-
* Error: {error}
|
|
270
|
-
* <button onClick={refresh}>Retry</button>
|
|
271
|
-
* </div>
|
|
272
|
-
* )}
|
|
273
|
-
* <div className="action-buttons">
|
|
274
|
-
* <button
|
|
275
|
-
* onClick={refresh}
|
|
276
|
-
* disabled={isLoading}
|
|
277
|
-
* >
|
|
278
|
-
* {isLoading ? 'Refreshing...' : 'Refresh'}
|
|
279
|
-
* </button>
|
|
280
|
-
* <button
|
|
281
|
-
* onClick={loadMore}
|
|
282
|
-
* disabled={isLoading}
|
|
283
|
-
* >
|
|
284
|
-
* Load More
|
|
285
|
-
* </button>
|
|
286
|
-
* </div>
|
|
287
|
-
* </div>
|
|
288
|
-
* )}
|
|
289
|
-
* </Collection.Actions>
|
|
290
|
-
* );
|
|
291
|
-
* }
|
|
292
|
-
* ```
|
|
293
|
-
*/
|
|
294
|
-
export declare const Actions: (props: ActionsProps) => import("react").ReactNode;
|