@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
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { defineService, implementService } from "@wix/services-definitions";
|
|
2
|
+
import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
|
|
3
|
+
import { categories } from "@wix/categories";
|
|
4
|
+
/**
|
|
5
|
+
* Service definition for the Categories List service.
|
|
6
|
+
* This defines the reactive API contract for managing a list of product categories.
|
|
7
|
+
*
|
|
8
|
+
* @constant
|
|
9
|
+
*/
|
|
10
|
+
export const CategoriesListServiceDefinition = defineService("categories-list");
|
|
11
|
+
/**
|
|
12
|
+
* Implementation of the Categories List service that manages reactive categories data.
|
|
13
|
+
* This service provides signals for categories data, loading state, and error handling.
|
|
14
|
+
* The service is initialized with pre-loaded categories and maintains them in reactive signals.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* import { CategoriesListService, CategoriesListServiceDefinition } from '@wix/stores/services';
|
|
19
|
+
* import { useService } from '@wix/services-manager-react';
|
|
20
|
+
*
|
|
21
|
+
* function CategoriesComponent({ categoriesConfig }) {
|
|
22
|
+
* return (
|
|
23
|
+
* <ServiceProvider services={createServicesMap([
|
|
24
|
+
* [CategoriesListServiceDefinition, CategoriesListService.withConfig(categoriesConfig)]
|
|
25
|
+
* ])}>
|
|
26
|
+
* <CategoriesDisplay />
|
|
27
|
+
* </ServiceProvider>
|
|
28
|
+
* );
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* function CategoriesDisplay() {
|
|
32
|
+
* const categoriesService = useService(CategoriesListServiceDefinition);
|
|
33
|
+
* const categories = categoriesService.categories.get();
|
|
34
|
+
* const isLoading = categoriesService.isLoading.get();
|
|
35
|
+
* const error = categoriesService.error.get();
|
|
36
|
+
*
|
|
37
|
+
* if (isLoading) return <div>Loading categories...</div>;
|
|
38
|
+
* if (error) return <div>Error: {error}</div>;
|
|
39
|
+
*
|
|
40
|
+
* return (
|
|
41
|
+
* <ul>
|
|
42
|
+
* {categories.map(category => (
|
|
43
|
+
* <li key={category._id}>{category.name}</li>
|
|
44
|
+
* ))}
|
|
45
|
+
* </ul>
|
|
46
|
+
* );
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export const CategoriesListService = implementService.withConfig()(CategoriesListServiceDefinition, ({ getService, config }) => {
|
|
51
|
+
const signalsService = getService(SignalsServiceDefinition);
|
|
52
|
+
const categoriesSignal = signalsService.signal(config.categories);
|
|
53
|
+
const isLoadingSignal = signalsService.signal(false);
|
|
54
|
+
const errorSignal = signalsService.signal(null);
|
|
55
|
+
return {
|
|
56
|
+
categories: categoriesSignal,
|
|
57
|
+
isLoading: isLoadingSignal,
|
|
58
|
+
error: errorSignal,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Loads categories list service configuration from the Wix Categories API for SSR initialization.
|
|
63
|
+
* This function is designed to be used during Server-Side Rendering (SSR) to preload
|
|
64
|
+
* all visible product categories. The "all-products" category is automatically moved to the front of the list.
|
|
65
|
+
*
|
|
66
|
+
* @returns {Promise<CategoriesListServiceConfig>} Promise that resolves to the categories configuration
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```astro
|
|
70
|
+
* ---
|
|
71
|
+
* // Astro page example - pages/categories.astro
|
|
72
|
+
* import { loadCategoriesListServiceConfig } from '@wix/stores/services';
|
|
73
|
+
* import { CategoryList } from '@wix/stores/components';
|
|
74
|
+
*
|
|
75
|
+
* // Load categories data during SSR
|
|
76
|
+
* const categoriesConfig = await loadCategoriesListServiceConfig();
|
|
77
|
+
* ---
|
|
78
|
+
*
|
|
79
|
+
* <CategoryList.Root categoriesConfig={categoriesConfig}>
|
|
80
|
+
* <CategoryList.ItemContent>
|
|
81
|
+
* {({ category }) => (
|
|
82
|
+
* <div>
|
|
83
|
+
* <h3>{category.name}</h3>
|
|
84
|
+
* <p>{category.description}</p>
|
|
85
|
+
* </div>
|
|
86
|
+
* )}
|
|
87
|
+
* </CategoryList.ItemContent>
|
|
88
|
+
* </CategoryList.Root>
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* // Next.js page example - pages/categories.tsx
|
|
94
|
+
* import { GetServerSideProps } from 'next';
|
|
95
|
+
* import { loadCategoriesListServiceConfig } from '@wix/stores/services';
|
|
96
|
+
* import { CategoryList } from '@wix/stores/components';
|
|
97
|
+
*
|
|
98
|
+
* interface CategoriesPageProps {
|
|
99
|
+
* categoriesConfig: Awaited<ReturnType<typeof loadCategoriesListServiceConfig>>;
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* export const getServerSideProps: GetServerSideProps<CategoriesPageProps> = async () => {
|
|
103
|
+
* const categoriesConfig = await loadCategoriesListServiceConfig();
|
|
104
|
+
*
|
|
105
|
+
* return {
|
|
106
|
+
* props: {
|
|
107
|
+
* categoriesConfig,
|
|
108
|
+
* },
|
|
109
|
+
* };
|
|
110
|
+
* };
|
|
111
|
+
*
|
|
112
|
+
* export default function CategoriesPage({ categoriesConfig }: CategoriesPageProps) {
|
|
113
|
+
* return (
|
|
114
|
+
* <CategoryList.Root categoriesConfig={categoriesConfig}>
|
|
115
|
+
* <CategoryList.ItemContent>
|
|
116
|
+
* {({ category }) => (
|
|
117
|
+
* <div>
|
|
118
|
+
* <h3>{category.name}</h3>
|
|
119
|
+
* <p>{category.description}</p>
|
|
120
|
+
* </div>
|
|
121
|
+
* )}
|
|
122
|
+
* </CategoryList.ItemContent>
|
|
123
|
+
* </CategoryList.Root>
|
|
124
|
+
* );
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export async function loadCategoriesListServiceConfig() {
|
|
129
|
+
const categoriesResponse = await categories
|
|
130
|
+
.queryCategories({
|
|
131
|
+
treeReference: {
|
|
132
|
+
appNamespace: "@wix/stores",
|
|
133
|
+
treeKey: null,
|
|
134
|
+
},
|
|
135
|
+
})
|
|
136
|
+
.eq("visible", true)
|
|
137
|
+
.find();
|
|
138
|
+
const fetchedCategories = categoriesResponse.items || [];
|
|
139
|
+
// Sort categories to put "all-products" first, keep the rest in original order
|
|
140
|
+
const allProductsCategory = fetchedCategories.find((cat) => cat.slug === "all-products");
|
|
141
|
+
const otherCategories = fetchedCategories.filter((cat) => cat.slug !== "all-products");
|
|
142
|
+
const allCategories = allProductsCategory
|
|
143
|
+
? [allProductsCategory, ...otherCategories]
|
|
144
|
+
: fetchedCategories;
|
|
145
|
+
return {
|
|
146
|
+
categories: allCategories,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -1,113 +1,158 @@
|
|
|
1
|
+
import { categories } from "@wix/categories";
|
|
1
2
|
import { type Signal } from "@wix/services-definitions/core-services/signals";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
3
|
+
/**
|
|
4
|
+
* Service definition for the Category service.
|
|
5
|
+
* This defines the reactive API contract for managing a single product category.
|
|
6
|
+
*
|
|
7
|
+
* @constant
|
|
8
|
+
*/
|
|
9
9
|
export declare const CategoryServiceDefinition: string & {
|
|
10
|
-
__api:
|
|
10
|
+
__api: {
|
|
11
|
+
/** Reactive signal containing the current category data */
|
|
12
|
+
category: Signal<categories.Category>;
|
|
13
|
+
};
|
|
11
14
|
__config: {};
|
|
12
15
|
isServiceDefinition?: boolean;
|
|
13
|
-
} &
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
} & {
|
|
17
|
+
/** Reactive signal containing the current category data */
|
|
18
|
+
category: Signal<categories.Category>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Configuration interface for the Category service.
|
|
22
|
+
* Contains the initial category data that will be loaded into the service.
|
|
23
|
+
*
|
|
24
|
+
* @interface CategoryServiceConfig
|
|
25
|
+
*/
|
|
26
|
+
export type CategoryServiceConfig = {
|
|
27
|
+
/** The category object to initialize the service with */
|
|
28
|
+
category: categories.Category;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Implementation of the Category service that manages reactive category data.
|
|
32
|
+
* This service provides a signal for category data and maintains it in a reactive state.
|
|
33
|
+
* The service is initialized with pre-loaded category data.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* import { CategoryService, CategoryServiceDefinition } from '@wix/stores/services';
|
|
38
|
+
* import { useService } from '@wix/services-manager-react';
|
|
39
|
+
*
|
|
40
|
+
* function CategoryComponent({ categoryConfig }) {
|
|
41
|
+
* return (
|
|
42
|
+
* <ServiceProvider services={createServicesMap([
|
|
43
|
+
* [CategoryServiceDefinition, CategoryService.withConfig(categoryConfig)]
|
|
44
|
+
* ])}>
|
|
45
|
+
* <CategoryDisplay />
|
|
46
|
+
* </ServiceProvider>
|
|
47
|
+
* );
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* function CategoryDisplay() {
|
|
51
|
+
* const categoryService = useService(CategoryServiceDefinition);
|
|
52
|
+
* const category = categoryService.category.get();
|
|
53
|
+
*
|
|
54
|
+
* return (
|
|
55
|
+
* <div>
|
|
56
|
+
* <h1>{category.name}</h1>
|
|
57
|
+
* <p>{category.description}</p>
|
|
58
|
+
* </div>
|
|
59
|
+
* );
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
19
63
|
export declare const CategoryService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
20
|
-
__api:
|
|
64
|
+
__api: {
|
|
65
|
+
/** Reactive signal containing the current category data */
|
|
66
|
+
category: Signal<categories.Category>;
|
|
67
|
+
};
|
|
21
68
|
__config: {};
|
|
22
69
|
isServiceDefinition?: boolean;
|
|
23
|
-
} &
|
|
70
|
+
} & {
|
|
71
|
+
/** Reactive signal containing the current category data */
|
|
72
|
+
category: Signal<categories.Category>;
|
|
73
|
+
}, CategoryServiceConfig>;
|
|
24
74
|
/**
|
|
25
|
-
* Loads
|
|
75
|
+
* Loads category service configuration from the Wix Categories API for SSR initialization.
|
|
26
76
|
* This function is designed to be used during Server-Side Rendering (SSR) to preload
|
|
27
|
-
*
|
|
28
|
-
* Fetches all visible categories and sorts them with "all-products" category first.
|
|
77
|
+
* a specific category by slug that will be used to configure the CategoryService.
|
|
29
78
|
*
|
|
30
|
-
* @
|
|
79
|
+
* @param {string} slug - The category slug to load
|
|
80
|
+
* @returns {Promise} Promise that resolves to either success with config or not-found result
|
|
31
81
|
*
|
|
32
82
|
* @example
|
|
33
83
|
* ```astro
|
|
34
84
|
* ---
|
|
35
|
-
* // Astro page example - pages/
|
|
36
|
-
* import {
|
|
85
|
+
* // Astro page example - pages/category/[slug].astro
|
|
86
|
+
* import { loadCategoryServiceConfig } from '@wix/stores/services';
|
|
37
87
|
* import { Category } from '@wix/stores/components';
|
|
38
88
|
*
|
|
39
|
-
* //
|
|
40
|
-
* const
|
|
89
|
+
* // Get category slug from URL params
|
|
90
|
+
* const { slug } = Astro.params;
|
|
91
|
+
*
|
|
92
|
+
* // Load category data during SSR
|
|
93
|
+
* const categoryResult = await loadCategoryServiceConfig(slug);
|
|
94
|
+
*
|
|
95
|
+
* // Handle not found case
|
|
96
|
+
* if (categoryResult.type === 'not-found') {
|
|
97
|
+
* return Astro.redirect('/404');
|
|
98
|
+
* }
|
|
41
99
|
* ---
|
|
42
100
|
*
|
|
43
|
-
* <Category.Root categoryConfig={
|
|
44
|
-
* <Category.
|
|
45
|
-
* {({
|
|
46
|
-
*
|
|
47
|
-
* <h2>Shop by Category</h2>
|
|
48
|
-
* {categories.map(category => (
|
|
49
|
-
* <button
|
|
50
|
-
* key={category.id}
|
|
51
|
-
* onClick={() => setSelectedCategory(category.id)}
|
|
52
|
-
* className={selectedCategory === category.id ? 'active' : ''}
|
|
53
|
-
* >
|
|
54
|
-
* {category.name}
|
|
55
|
-
* </button>
|
|
56
|
-
* ))}
|
|
57
|
-
* </nav>
|
|
58
|
-
* )}
|
|
59
|
-
* </Category.List>
|
|
101
|
+
* <Category.Root categoryConfig={categoryResult.config}>
|
|
102
|
+
* <Category.Name>
|
|
103
|
+
* {({ name }) => <h1>{name}</h1>}
|
|
104
|
+
* </Category.Name>
|
|
60
105
|
* </Category.Root>
|
|
61
106
|
* ```
|
|
62
107
|
*
|
|
63
108
|
* @example
|
|
64
109
|
* ```tsx
|
|
65
|
-
* // Next.js page example - pages/
|
|
110
|
+
* // Next.js page example - pages/category/[slug].tsx
|
|
66
111
|
* import { GetServerSideProps } from 'next';
|
|
67
|
-
* import {
|
|
112
|
+
* import { loadCategoryServiceConfig } from '@wix/stores/services';
|
|
68
113
|
* import { Category } from '@wix/stores/components';
|
|
69
114
|
*
|
|
70
115
|
* interface CategoryPageProps {
|
|
71
|
-
* categoryConfig: Awaited<ReturnType<typeof
|
|
116
|
+
* categoryConfig: Awaited<ReturnType<typeof loadCategoryServiceConfig>>['config'];
|
|
72
117
|
* }
|
|
73
118
|
*
|
|
74
|
-
* export const getServerSideProps: GetServerSideProps<CategoryPageProps> = async () => {
|
|
75
|
-
*
|
|
76
|
-
*
|
|
119
|
+
* export const getServerSideProps: GetServerSideProps<CategoryPageProps> = async ({ params }) => {
|
|
120
|
+
* const slug = params?.slug as string;
|
|
121
|
+
*
|
|
122
|
+
* // Load category data during SSR
|
|
123
|
+
* const categoryResult = await loadCategoryServiceConfig(slug);
|
|
124
|
+
*
|
|
125
|
+
* // Handle not found case
|
|
126
|
+
* if (categoryResult.type === 'not-found') {
|
|
127
|
+
* return {
|
|
128
|
+
* notFound: true,
|
|
129
|
+
* };
|
|
130
|
+
* }
|
|
77
131
|
*
|
|
78
132
|
* return {
|
|
79
133
|
* props: {
|
|
80
|
-
* categoryConfig,
|
|
134
|
+
* categoryConfig: categoryResult.config,
|
|
81
135
|
* },
|
|
82
136
|
* };
|
|
83
137
|
* };
|
|
84
138
|
*
|
|
85
139
|
* export default function CategoryPage({ categoryConfig }: CategoryPageProps) {
|
|
86
140
|
* return (
|
|
87
|
-
* <
|
|
88
|
-
* <
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* <nav className="category-nav">
|
|
93
|
-
* {categories.map(category => (
|
|
94
|
-
* <button
|
|
95
|
-
* key={category.id}
|
|
96
|
-
* onClick={() => setSelectedCategory(category.id)}
|
|
97
|
-
* className={`category-btn ${selectedCategory === category.id ? 'active' : ''}`}
|
|
98
|
-
* >
|
|
99
|
-
* {category.name}
|
|
100
|
-
* </button>
|
|
101
|
-
* ))}
|
|
102
|
-
* </nav>
|
|
103
|
-
* )}
|
|
104
|
-
* </Category.List>
|
|
105
|
-
* </Category.Root>
|
|
106
|
-
* </div>
|
|
141
|
+
* <Category.Root categoryConfig={categoryConfig}>
|
|
142
|
+
* <Category.Name>
|
|
143
|
+
* {({ name }) => <h1>{name}</h1>}
|
|
144
|
+
* </Category.Name>
|
|
145
|
+
* </Category.Root>
|
|
107
146
|
* );
|
|
108
147
|
* }
|
|
109
148
|
* ```
|
|
110
149
|
*/
|
|
111
|
-
export declare function
|
|
112
|
-
|
|
150
|
+
export declare function loadCategoryServiceConfig(slug: string): Promise<{
|
|
151
|
+
/** Type "success" means that the category was found and the config is valid */
|
|
152
|
+
type: "success";
|
|
153
|
+
/** The category config containing the loaded category data */
|
|
154
|
+
config: CategoryServiceConfig;
|
|
155
|
+
} | {
|
|
156
|
+
/** Type "not-found" means that the category was not found */
|
|
157
|
+
type: "not-found";
|
|
113
158
|
}>;
|
|
@@ -1,156 +1,147 @@
|
|
|
1
1
|
import { defineService, implementService } from "@wix/services-definitions";
|
|
2
|
+
import { categories } from "@wix/categories";
|
|
2
3
|
import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Service definition for the Category service.
|
|
6
|
+
* This defines the reactive API contract for managing a single product category.
|
|
7
|
+
*
|
|
8
|
+
* @constant
|
|
9
|
+
*/
|
|
10
|
+
export const CategoryServiceDefinition = defineService("category");
|
|
11
|
+
/**
|
|
12
|
+
* Implementation of the Category service that manages reactive category data.
|
|
13
|
+
* This service provides a signal for category data and maintains it in a reactive state.
|
|
14
|
+
* The service is initialized with pre-loaded category data.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* import { CategoryService, CategoryServiceDefinition } from '@wix/stores/services';
|
|
19
|
+
* import { useService } from '@wix/services-manager-react';
|
|
20
|
+
*
|
|
21
|
+
* function CategoryComponent({ categoryConfig }) {
|
|
22
|
+
* return (
|
|
23
|
+
* <ServiceProvider services={createServicesMap([
|
|
24
|
+
* [CategoryServiceDefinition, CategoryService.withConfig(categoryConfig)]
|
|
25
|
+
* ])}>
|
|
26
|
+
* <CategoryDisplay />
|
|
27
|
+
* </ServiceProvider>
|
|
28
|
+
* );
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* function CategoryDisplay() {
|
|
32
|
+
* const categoryService = useService(CategoryServiceDefinition);
|
|
33
|
+
* const category = categoryService.category.get();
|
|
34
|
+
*
|
|
35
|
+
* return (
|
|
36
|
+
* <div>
|
|
37
|
+
* <h1>{category.name}</h1>
|
|
38
|
+
* <p>{category.description}</p>
|
|
39
|
+
* </div>
|
|
40
|
+
* );
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
5
44
|
export const CategoryService = implementService.withConfig()(CategoryServiceDefinition, ({ getService, config }) => {
|
|
6
45
|
const signalsService = getService(SignalsServiceDefinition);
|
|
7
|
-
const
|
|
8
|
-
const categories = signalsService.signal(config?.categories);
|
|
9
|
-
const loadCategories = async () => {
|
|
10
|
-
const { categories: loadedCategories } = await loadCategoriesConfig();
|
|
11
|
-
categories.set(loadedCategories);
|
|
12
|
-
};
|
|
13
|
-
// Track if this is the initial load to prevent navigation on service creation
|
|
14
|
-
let isInitialLoad = true;
|
|
15
|
-
const setSelectedCategory = (categoryId) => {
|
|
16
|
-
selectedCategory.set(categoryId);
|
|
17
|
-
};
|
|
18
|
-
// Subscribe to category changes and handle navigation as a side effect
|
|
19
|
-
signalsService.effect(() => {
|
|
20
|
-
const categoryId = selectedCategory.get();
|
|
21
|
-
// Skip navigation on initial load (when service is first created)
|
|
22
|
-
if (isInitialLoad) {
|
|
23
|
-
isInitialLoad = false;
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
// If a navigation handler is provided, use it
|
|
27
|
-
if (config?.onCategoryChange) {
|
|
28
|
-
const category = categoryId
|
|
29
|
-
? config?.categories.find((cat) => cat._id === categoryId) || null
|
|
30
|
-
: null;
|
|
31
|
-
config.onCategoryChange(categoryId, category);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
46
|
+
const categorySignal = signalsService.signal(config.category);
|
|
34
47
|
return {
|
|
35
|
-
|
|
36
|
-
categories,
|
|
37
|
-
setSelectedCategory,
|
|
38
|
-
loadCategories,
|
|
48
|
+
category: categorySignal,
|
|
39
49
|
};
|
|
40
50
|
});
|
|
41
51
|
/**
|
|
42
|
-
* Loads
|
|
52
|
+
* Loads category service configuration from the Wix Categories API for SSR initialization.
|
|
43
53
|
* This function is designed to be used during Server-Side Rendering (SSR) to preload
|
|
44
|
-
*
|
|
45
|
-
* Fetches all visible categories and sorts them with "all-products" category first.
|
|
54
|
+
* a specific category by slug that will be used to configure the CategoryService.
|
|
46
55
|
*
|
|
47
|
-
* @
|
|
56
|
+
* @param {string} slug - The category slug to load
|
|
57
|
+
* @returns {Promise} Promise that resolves to either success with config or not-found result
|
|
48
58
|
*
|
|
49
59
|
* @example
|
|
50
60
|
* ```astro
|
|
51
61
|
* ---
|
|
52
|
-
* // Astro page example - pages/
|
|
53
|
-
* import {
|
|
62
|
+
* // Astro page example - pages/category/[slug].astro
|
|
63
|
+
* import { loadCategoryServiceConfig } from '@wix/stores/services';
|
|
54
64
|
* import { Category } from '@wix/stores/components';
|
|
55
65
|
*
|
|
56
|
-
* //
|
|
57
|
-
* const
|
|
66
|
+
* // Get category slug from URL params
|
|
67
|
+
* const { slug } = Astro.params;
|
|
68
|
+
*
|
|
69
|
+
* // Load category data during SSR
|
|
70
|
+
* const categoryResult = await loadCategoryServiceConfig(slug);
|
|
71
|
+
*
|
|
72
|
+
* // Handle not found case
|
|
73
|
+
* if (categoryResult.type === 'not-found') {
|
|
74
|
+
* return Astro.redirect('/404');
|
|
75
|
+
* }
|
|
58
76
|
* ---
|
|
59
77
|
*
|
|
60
|
-
* <Category.Root categoryConfig={
|
|
61
|
-
* <Category.
|
|
62
|
-
* {({
|
|
63
|
-
*
|
|
64
|
-
* <h2>Shop by Category</h2>
|
|
65
|
-
* {categories.map(category => (
|
|
66
|
-
* <button
|
|
67
|
-
* key={category.id}
|
|
68
|
-
* onClick={() => setSelectedCategory(category.id)}
|
|
69
|
-
* className={selectedCategory === category.id ? 'active' : ''}
|
|
70
|
-
* >
|
|
71
|
-
* {category.name}
|
|
72
|
-
* </button>
|
|
73
|
-
* ))}
|
|
74
|
-
* </nav>
|
|
75
|
-
* )}
|
|
76
|
-
* </Category.List>
|
|
78
|
+
* <Category.Root categoryConfig={categoryResult.config}>
|
|
79
|
+
* <Category.Name>
|
|
80
|
+
* {({ name }) => <h1>{name}</h1>}
|
|
81
|
+
* </Category.Name>
|
|
77
82
|
* </Category.Root>
|
|
78
83
|
* ```
|
|
79
84
|
*
|
|
80
85
|
* @example
|
|
81
86
|
* ```tsx
|
|
82
|
-
* // Next.js page example - pages/
|
|
87
|
+
* // Next.js page example - pages/category/[slug].tsx
|
|
83
88
|
* import { GetServerSideProps } from 'next';
|
|
84
|
-
* import {
|
|
89
|
+
* import { loadCategoryServiceConfig } from '@wix/stores/services';
|
|
85
90
|
* import { Category } from '@wix/stores/components';
|
|
86
91
|
*
|
|
87
92
|
* interface CategoryPageProps {
|
|
88
|
-
* categoryConfig: Awaited<ReturnType<typeof
|
|
93
|
+
* categoryConfig: Awaited<ReturnType<typeof loadCategoryServiceConfig>>['config'];
|
|
89
94
|
* }
|
|
90
95
|
*
|
|
91
|
-
* export const getServerSideProps: GetServerSideProps<CategoryPageProps> = async () => {
|
|
92
|
-
*
|
|
93
|
-
*
|
|
96
|
+
* export const getServerSideProps: GetServerSideProps<CategoryPageProps> = async ({ params }) => {
|
|
97
|
+
* const slug = params?.slug as string;
|
|
98
|
+
*
|
|
99
|
+
* // Load category data during SSR
|
|
100
|
+
* const categoryResult = await loadCategoryServiceConfig(slug);
|
|
101
|
+
*
|
|
102
|
+
* // Handle not found case
|
|
103
|
+
* if (categoryResult.type === 'not-found') {
|
|
104
|
+
* return {
|
|
105
|
+
* notFound: true,
|
|
106
|
+
* };
|
|
107
|
+
* }
|
|
94
108
|
*
|
|
95
109
|
* return {
|
|
96
110
|
* props: {
|
|
97
|
-
* categoryConfig,
|
|
111
|
+
* categoryConfig: categoryResult.config,
|
|
98
112
|
* },
|
|
99
113
|
* };
|
|
100
114
|
* };
|
|
101
115
|
*
|
|
102
116
|
* export default function CategoryPage({ categoryConfig }: CategoryPageProps) {
|
|
103
117
|
* return (
|
|
104
|
-
* <
|
|
105
|
-
* <
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* <nav className="category-nav">
|
|
110
|
-
* {categories.map(category => (
|
|
111
|
-
* <button
|
|
112
|
-
* key={category.id}
|
|
113
|
-
* onClick={() => setSelectedCategory(category.id)}
|
|
114
|
-
* className={`category-btn ${selectedCategory === category.id ? 'active' : ''}`}
|
|
115
|
-
* >
|
|
116
|
-
* {category.name}
|
|
117
|
-
* </button>
|
|
118
|
-
* ))}
|
|
119
|
-
* </nav>
|
|
120
|
-
* )}
|
|
121
|
-
* </Category.List>
|
|
122
|
-
* </Category.Root>
|
|
123
|
-
* </div>
|
|
118
|
+
* <Category.Root categoryConfig={categoryConfig}>
|
|
119
|
+
* <Category.Name>
|
|
120
|
+
* {({ name }) => <h1>{name}</h1>}
|
|
121
|
+
* </Category.Name>
|
|
122
|
+
* </Category.Root>
|
|
124
123
|
* );
|
|
125
124
|
* }
|
|
126
125
|
* ```
|
|
127
126
|
*/
|
|
128
|
-
export async function
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
.find();
|
|
139
|
-
const fetchedCategories = categoriesResponse.items || [];
|
|
140
|
-
// Sort categories to put "all-products" first, keep the rest in original order
|
|
141
|
-
const allProductsCategory = fetchedCategories.find((cat) => cat.slug === "all-products");
|
|
142
|
-
const otherCategories = fetchedCategories.filter((cat) => cat.slug !== "all-products");
|
|
143
|
-
const allCategories = allProductsCategory
|
|
144
|
-
? [allProductsCategory, ...otherCategories]
|
|
145
|
-
: fetchedCategories;
|
|
146
|
-
return {
|
|
147
|
-
categories: allCategories,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
console.warn("Failed to load categories:", error);
|
|
127
|
+
export async function loadCategoryServiceConfig(slug) {
|
|
128
|
+
const category = await categories
|
|
129
|
+
.queryCategories({
|
|
130
|
+
treeReference: {
|
|
131
|
+
appNamespace: "@wix/stores",
|
|
132
|
+
},
|
|
133
|
+
})
|
|
134
|
+
.eq("slug", slug)
|
|
135
|
+
.find();
|
|
136
|
+
if (category.items.length === 0) {
|
|
152
137
|
return {
|
|
153
|
-
|
|
138
|
+
type: "not-found",
|
|
154
139
|
};
|
|
155
140
|
}
|
|
141
|
+
return {
|
|
142
|
+
type: "success",
|
|
143
|
+
config: {
|
|
144
|
+
category: category.items[0],
|
|
145
|
+
},
|
|
146
|
+
};
|
|
156
147
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export { CollectionService, CollectionServiceDefinition, loadCollectionServiceConfig, } from "./collection-service.js";
|
|
4
|
-
export { FilterService, FilterServiceDefinition, Filter, AvailableOptions, } from "./filter-service.js";
|
|
1
|
+
export { CategoryService, CategoryServiceDefinition, loadCategoryServiceConfig, CategoryServiceConfig, } from "./category-service.js";
|
|
2
|
+
export { CategoriesListService, CategoriesListServiceDefinition, loadCategoriesListServiceConfig, CategoriesListServiceConfig, } from "./categories-list-service.js";
|
|
5
3
|
export { ProductModifiersService, ProductModifiersServiceDefinition, } from "./product-modifiers-service.js";
|
|
6
4
|
export { ProductService, ProductServiceDefinition, loadProductServiceConfig, } from "./product-service.js";
|
|
7
|
-
export { RelatedProductsService, RelatedProductsServiceDefinition, loadRelatedProductsServiceConfig, } from "./related-products-service.js";
|
|
8
5
|
export { SelectedVariantService, SelectedVariantServiceDefinition, } from "./selected-variant-service.js";
|
|
9
|
-
export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, } from "./products-list-service.js";
|
|
10
|
-
export {
|
|
6
|
+
export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, ProductsListServiceConfig, } from "./products-list-service.js";
|
|
7
|
+
export { SortType, ProductsListSortService, ProductsListSortServiceDefinition, } from "./products-list-sort-service.js";
|
|
8
|
+
export { InventoryStatusType, ProductsListFiltersService, ProductsListFiltersServiceDefinition, loadProductsListFiltersServiceConfig, ProductsListFiltersServiceConfig, } from "./products-list-filters-service.js";
|
|
9
|
+
export { ProductsListPaginationService, ProductsListPaginationServiceDefinition, } from "./products-list-pagination-service.js";
|