@jay-framework/wix-stores 0.19.6 → 0.20.0
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/README.md +6 -11
- package/dist/agent-kit/aiditor/add-menu.template.yaml +43 -9
- package/dist/agent-kit/aiditor/thumbnails/wix-stores/category-list.svg +12 -0
- package/dist/agent-kit/aiditor/thumbnails/wix-stores/category-products.svg +15 -0
- package/dist/agent-kit/aiditor/thumbnails/wix-stores/product-page.svg +12 -0
- package/dist/agent-kit/aiditor/thumbnails/wix-stores/product-search.svg +17 -0
- package/dist/contracts/category-products.jay-contract +31 -0
- package/dist/contracts/category-products.jay-contract.d.ts +36 -0
- package/dist/contracts/product-spotlight.jay-contract +16 -0
- package/dist/contracts/product-spotlight.jay-contract.d.ts +61 -0
- package/dist/index.client.js +32 -4
- package/dist/index.d.ts +87 -12
- package/dist/index.js +158 -27
- package/package.json +18 -17
- package/plugin.yaml +8 -4
- package/dist/contracts/related-products.jay-contract +0 -31
- package/dist/contracts/related-products.jay-contract.d.ts +0 -36
package/README.md
CHANGED
|
@@ -64,9 +64,6 @@ Run `jay-stack agent-kit` (or `yarn agent-kit`) to index the live category tree
|
|
|
64
64
|
urls:
|
|
65
65
|
product: '/products/{slug}' # default
|
|
66
66
|
category: null # no category pages by default
|
|
67
|
-
|
|
68
|
-
# Fallback category for pages without category context
|
|
69
|
-
defaultCategory: 'all-products' # slug of the fallback category
|
|
70
67
|
```
|
|
71
68
|
|
|
72
69
|
URL templates use three placeholders:
|
|
@@ -114,7 +111,6 @@ src/pages/products/
|
|
|
114
111
|
urls:
|
|
115
112
|
product: '/products/{prefix}/{category}/{slug}'
|
|
116
113
|
category: '/products/{prefix}/{category}'
|
|
117
|
-
defaultCategory: 'all-products'
|
|
118
114
|
```
|
|
119
115
|
|
|
120
116
|
```
|
|
@@ -154,12 +150,12 @@ src/pages/products/polgat/
|
|
|
154
150
|
|
|
155
151
|
### Setting Params for Static Routes
|
|
156
152
|
|
|
157
|
-
Static route directories use `jay-params` to tell the component which
|
|
153
|
+
Static route directories use `jay-params` to tell the component which category they represent:
|
|
158
154
|
|
|
159
155
|
```html
|
|
160
|
-
<!-- src/pages/products/polgat/page.jay-html -->
|
|
156
|
+
<!-- src/pages/products/polgat/page.jay-html (root category) -->
|
|
161
157
|
<script type="application/jay-params">
|
|
162
|
-
|
|
158
|
+
category: polgat
|
|
163
159
|
</script>
|
|
164
160
|
<script
|
|
165
161
|
type="application/jay-headless"
|
|
@@ -171,11 +167,10 @@ Static route directories use `jay-params` to tell the component which prefix the
|
|
|
171
167
|
|
|
172
168
|
## Category Header
|
|
173
169
|
|
|
174
|
-
The category header is always loaded. The component resolves category metadata
|
|
170
|
+
The category header is always loaded. The component resolves category metadata:
|
|
175
171
|
|
|
176
|
-
1. **`category` param** → load category
|
|
177
|
-
2.
|
|
178
|
-
3. **Neither** → load `defaultCategory` from config
|
|
172
|
+
1. **`category` param** → load category (always the active category slug)
|
|
173
|
+
2. **No `category`** → load the "All Products" system category via `getAllProductsCategory()` (header only, no base filter)
|
|
179
174
|
|
|
180
175
|
If the resolved category is missing image, description, or SEO data, the component walks up the parent chain until it finds the data. Each field inherits independently.
|
|
181
176
|
|
|
@@ -5,7 +5,11 @@ items:
|
|
|
5
5
|
subCategory: Components
|
|
6
6
|
pluginName: wix-stores
|
|
7
7
|
packageName: "@jay-framework/wix-stores"
|
|
8
|
-
thumbnail: thumbnails/wix-stores/product-search.
|
|
8
|
+
thumbnail: thumbnails/wix-stores/product-search.svg
|
|
9
|
+
interaction:
|
|
10
|
+
mode: stage-place
|
|
11
|
+
stagePromptTemplate: |
|
|
12
|
+
Add a product search component at this marker location on the page.
|
|
9
13
|
prompt: |
|
|
10
14
|
Use headless component @jay-framework/wix-stores / contract product-search.
|
|
11
15
|
Read agent-kit/materialized-contracts/wix-stores/product-search.jay-contract.
|
|
@@ -18,26 +22,52 @@ items:
|
|
|
18
22
|
subCategory: Components
|
|
19
23
|
pluginName: wix-stores
|
|
20
24
|
packageName: "@jay-framework/wix-stores"
|
|
21
|
-
thumbnail: thumbnails/wix-stores/product-page.
|
|
25
|
+
thumbnail: thumbnails/wix-stores/product-page.svg
|
|
26
|
+
interaction:
|
|
27
|
+
mode: stage-place
|
|
28
|
+
stagePromptTemplate: |
|
|
29
|
+
Add a product page component at this marker location on the page.
|
|
22
30
|
prompt: |
|
|
23
31
|
Use headless component @jay-framework/wix-stores / contract product-page.
|
|
24
32
|
Read agent-kit/materialized-contracts/wix-stores/product-page.jay-contract.
|
|
25
33
|
Script key: p
|
|
26
34
|
Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md.
|
|
27
35
|
|
|
28
|
-
- id: wix-stores:
|
|
29
|
-
title:
|
|
36
|
+
- id: wix-stores:category-products
|
|
37
|
+
title: Category products
|
|
30
38
|
category: Store
|
|
31
39
|
subCategory: Components
|
|
32
40
|
pluginName: wix-stores
|
|
33
41
|
packageName: "@jay-framework/wix-stores"
|
|
34
|
-
thumbnail: thumbnails/wix-stores/
|
|
42
|
+
thumbnail: thumbnails/wix-stores/category-products.svg
|
|
43
|
+
interaction:
|
|
44
|
+
mode: stage-place
|
|
45
|
+
stagePromptTemplate: |
|
|
46
|
+
Add a category products grid at this marker location on the page.
|
|
35
47
|
prompt: |
|
|
36
|
-
Use headless component @jay-framework/wix-stores / contract
|
|
37
|
-
Read agent-kit/materialized-contracts/wix-stores/
|
|
48
|
+
Use headless component @jay-framework/wix-stores / contract category-products.
|
|
49
|
+
Read agent-kit/materialized-contracts/wix-stores/category-products.jay-contract.
|
|
38
50
|
Script key: r
|
|
39
51
|
Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md.
|
|
40
|
-
|
|
52
|
+
Pass categorySlug to show products from a category. Pass productId to exclude a product (e.g. on a product page).
|
|
53
|
+
|
|
54
|
+
- id: wix-stores:product-spotlight
|
|
55
|
+
title: Product spotlight
|
|
56
|
+
category: Store
|
|
57
|
+
subCategory: Components
|
|
58
|
+
pluginName: wix-stores
|
|
59
|
+
packageName: "@jay-framework/wix-stores"
|
|
60
|
+
thumbnail: thumbnails/wix-stores/product-spotlight.png
|
|
61
|
+
interaction:
|
|
62
|
+
mode: stage-place
|
|
63
|
+
stagePromptTemplate: |
|
|
64
|
+
Add a product spotlight at this marker location on the page.
|
|
65
|
+
prompt: |
|
|
66
|
+
Use headless component @jay-framework/wix-stores / contract product-spotlight.
|
|
67
|
+
Read agent-kit/materialized-contracts/wix-stores/product-spotlight.jay-contract.
|
|
68
|
+
Script key: spotlight
|
|
69
|
+
Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md.
|
|
70
|
+
Pass slug as a prop to specify which product to display.
|
|
41
71
|
|
|
42
72
|
- id: wix-stores:category-list
|
|
43
73
|
title: Category list
|
|
@@ -45,7 +75,11 @@ items:
|
|
|
45
75
|
subCategory: Components
|
|
46
76
|
pluginName: wix-stores
|
|
47
77
|
packageName: "@jay-framework/wix-stores"
|
|
48
|
-
thumbnail: thumbnails/wix-stores/category-list.
|
|
78
|
+
thumbnail: thumbnails/wix-stores/category-list.svg
|
|
79
|
+
interaction:
|
|
80
|
+
mode: stage-place
|
|
81
|
+
stagePromptTemplate: |
|
|
82
|
+
Add a category list at this marker location on the page.
|
|
49
83
|
prompt: |
|
|
50
84
|
Use headless component @jay-framework/wix-stores / contract category-list.
|
|
51
85
|
Read agent-kit/materialized-contracts/wix-stores/category-list.jay-contract.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240" fill="none">
|
|
2
|
+
<rect width="320" height="240" fill="#f8fafc"/>
|
|
3
|
+
<rect x="16" y="20" width="288" height="36" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
4
|
+
<rect x="28" y="32" width="120" height="12" rx="3" fill="#cbd5e1"/>
|
|
5
|
+
<rect x="16" y="72" width="136" height="14" rx="4" fill="#e2e8f0"/>
|
|
6
|
+
<rect x="16" y="98" width="288" height="1" fill="#e2e8f0"/>
|
|
7
|
+
<rect x="16" y="112" width="200" height="12" rx="3" fill="#cbd5e1"/>
|
|
8
|
+
<rect x="16" y="136" width="160" height="10" rx="3" fill="#e2e8f0"/>
|
|
9
|
+
<rect x="16" y="168" width="288" height="1" fill="#e2e8f0"/>
|
|
10
|
+
<rect x="16" y="182" width="184" height="12" rx="3" fill="#cbd5e1"/>
|
|
11
|
+
<rect x="16" y="206" width="128" height="10" rx="3" fill="#e2e8f0"/>
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240" fill="none">
|
|
2
|
+
<rect width="320" height="240" fill="#f8fafc"/>
|
|
3
|
+
<rect x="16" y="24" width="120" height="12" rx="3" fill="#cbd5e1"/>
|
|
4
|
+
<rect x="16" y="56" width="72" height="96" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
5
|
+
<rect x="24" y="64" width="56" height="48" rx="4" fill="#dbeafe"/>
|
|
6
|
+
<rect x="24" y="120" width="48" height="8" rx="2" fill="#cbd5e1"/>
|
|
7
|
+
<rect x="96" y="56" width="72" height="96" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
8
|
+
<rect x="104" y="64" width="56" height="48" rx="4" fill="#fce7f3"/>
|
|
9
|
+
<rect x="104" y="120" width="48" height="8" rx="2" fill="#cbd5e1"/>
|
|
10
|
+
<rect x="176" y="56" width="72" height="96" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
11
|
+
<rect x="184" y="64" width="56" height="48" rx="4" fill="#dcfce7"/>
|
|
12
|
+
<rect x="184" y="120" width="48" height="8" rx="2" fill="#cbd5e1"/>
|
|
13
|
+
<rect x="248" y="56" width="56" height="96" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
14
|
+
<rect x="256" y="64" width="40" height="48" rx="4" fill="#fef3c7"/>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240" fill="none">
|
|
2
|
+
<rect width="320" height="240" fill="#f4f7fb"/>
|
|
3
|
+
<rect x="16" y="16" width="288" height="28" rx="6" fill="#e2e8f0"/>
|
|
4
|
+
<rect x="16" y="56" width="120" height="12" rx="3" fill="#cbd5e1"/>
|
|
5
|
+
<rect x="16" y="76" width="88" height="10" rx="3" fill="#e2e8f0"/>
|
|
6
|
+
<rect x="16" y="104" width="136" height="120" rx="8" fill="#dbeafe" stroke="#93c5fd"/>
|
|
7
|
+
<rect x="168" y="104" width="136" height="16" rx="4" fill="#cbd5e1"/>
|
|
8
|
+
<rect x="168" y="128" width="96" height="10" rx="3" fill="#e2e8f0"/>
|
|
9
|
+
<rect x="168" y="148" width="72" height="10" rx="3" fill="#e2e8f0"/>
|
|
10
|
+
<rect x="168" y="180" width="88" height="28" rx="6" fill="#2563eb"/>
|
|
11
|
+
<text x="188" y="198" fill="#fff" font-family="system-ui,sans-serif" font-size="11">Add to cart</text>
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240" fill="none">
|
|
2
|
+
<rect width="320" height="240" fill="#f8fafc"/>
|
|
3
|
+
<rect x="16" y="16" width="200" height="24" rx="6" fill="#fff" stroke="#cbd5e1"/>
|
|
4
|
+
<rect x="24" y="24" width="64" height="8" rx="2" fill="#e2e8f0"/>
|
|
5
|
+
<g>
|
|
6
|
+
<rect x="16" y="56" width="88" height="88" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
7
|
+
<rect x="24" y="64" width="72" height="48" rx="4" fill="#dbeafe"/>
|
|
8
|
+
<rect x="24" y="120" width="56" height="8" rx="2" fill="#cbd5e1"/>
|
|
9
|
+
<rect x="112" y="56" width="88" height="88" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
10
|
+
<rect x="120" y="64" width="72" height="48" rx="4" fill="#fce7f3"/>
|
|
11
|
+
<rect x="120" y="120" width="56" height="8" rx="2" fill="#cbd5e1"/>
|
|
12
|
+
<rect x="208" y="56" width="88" height="88" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
13
|
+
<rect x="216" y="64" width="72" height="48" rx="4" fill="#dcfce7"/>
|
|
14
|
+
<rect x="216" y="120" width="56" height="8" rx="2" fill="#cbd5e1"/>
|
|
15
|
+
</g>
|
|
16
|
+
<rect x="16" y="160" width="288" height="64" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
17
|
+
</svg>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: category-products
|
|
2
|
+
description: Products from a specific category. Use for category product showcases, or as related products on a product page (pass productId to exclude the current product).
|
|
3
|
+
props:
|
|
4
|
+
- name: productId
|
|
5
|
+
type: string
|
|
6
|
+
description: Product ID to exclude from results (optional, use for related products)
|
|
7
|
+
- name: categorySlug
|
|
8
|
+
type: string
|
|
9
|
+
description: Category slug to filter products by
|
|
10
|
+
- name: limit
|
|
11
|
+
type: number
|
|
12
|
+
description: Maximum number of products to show (default 4)
|
|
13
|
+
tags:
|
|
14
|
+
- tag: products
|
|
15
|
+
type: sub-contract
|
|
16
|
+
repeated: true
|
|
17
|
+
trackBy: _id
|
|
18
|
+
phase: fast+interactive
|
|
19
|
+
description: Product cards from the category
|
|
20
|
+
link: ./product-card
|
|
21
|
+
|
|
22
|
+
- tag: hasProducts
|
|
23
|
+
type: variant
|
|
24
|
+
dataType: boolean
|
|
25
|
+
phase: fast+interactive
|
|
26
|
+
description: Whether there are products to show
|
|
27
|
+
|
|
28
|
+
- tag: categoryName
|
|
29
|
+
type: data
|
|
30
|
+
dataType: string
|
|
31
|
+
description: Name of the category these products belong to
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {JayContract} from "@jay-framework/runtime";
|
|
2
|
+
import {ProductCardViewState, ProductCardRefs, ProductCardRepeatedRefs} from "./product-card.jay-contract";
|
|
3
|
+
|
|
4
|
+
export interface CategoryProductsViewState {
|
|
5
|
+
products: Array<ProductCardViewState>,
|
|
6
|
+
hasProducts: boolean,
|
|
7
|
+
categoryName: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type CategoryProductsSlowViewState = Pick<CategoryProductsViewState, 'categoryName'>;
|
|
11
|
+
|
|
12
|
+
export type CategoryProductsFastViewState = Pick<CategoryProductsViewState, 'hasProducts'> & {
|
|
13
|
+
products: Array<CategoryProductsViewState['products'][number]>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type CategoryProductsInteractiveViewState = Pick<CategoryProductsViewState, 'hasProducts'> & {
|
|
17
|
+
products: Array<CategoryProductsViewState['products'][number]>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export interface CategoryProductsRefs {
|
|
22
|
+
products: ProductCardRepeatedRefs
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export interface CategoryProductsRepeatedRefs {
|
|
27
|
+
products: ProductCardRepeatedRefs
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CategoryProductsProps {
|
|
31
|
+
productId?: string;
|
|
32
|
+
categorySlug?: string;
|
|
33
|
+
limit?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type CategoryProductsContract = JayContract<CategoryProductsViewState, CategoryProductsRefs, CategoryProductsSlowViewState, CategoryProductsFastViewState, CategoryProductsInteractiveViewState, CategoryProductsProps>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: product-spotlight
|
|
2
|
+
description: A single product card by slug. Use to feature a specific product on any page (homepage, content pages, etc.).
|
|
3
|
+
props:
|
|
4
|
+
- name: slug
|
|
5
|
+
type: string
|
|
6
|
+
description: Product slug to display
|
|
7
|
+
tags:
|
|
8
|
+
- tag: product
|
|
9
|
+
type: sub-contract
|
|
10
|
+
description: The product card
|
|
11
|
+
link: ./product-card
|
|
12
|
+
|
|
13
|
+
- tag: hasProduct
|
|
14
|
+
type: variant
|
|
15
|
+
dataType: boolean
|
|
16
|
+
description: Whether the product was found
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {JayContract} from "@jay-framework/runtime";
|
|
2
|
+
import {ProductCardViewState, ProductCardRefs, ProductCardRepeatedRefs} from "./product-card.jay-contract";
|
|
3
|
+
|
|
4
|
+
export interface ProductSpotlightViewState {
|
|
5
|
+
product: ProductCardViewState,
|
|
6
|
+
hasProduct: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type ProductSpotlightSlowViewState = Pick<ProductSpotlightViewState, 'hasProduct'> & {
|
|
10
|
+
product: Pick<ProductSpotlightViewState['product'], '_id' | 'name' | 'slug' | 'productUrl' | 'categoryPrefix' | 'hasDiscount' | 'hasRibbon' | 'productType' | 'quickAddType'> & {
|
|
11
|
+
mainMedia: ProductSpotlightViewState['product']['mainMedia'];
|
|
12
|
+
thumbnail: ProductSpotlightViewState['product']['thumbnail'];
|
|
13
|
+
inventory: ProductSpotlightViewState['product']['inventory'];
|
|
14
|
+
ribbon: ProductSpotlightViewState['product']['ribbon'];
|
|
15
|
+
brand: ProductSpotlightViewState['product']['brand'];
|
|
16
|
+
quickOption: Pick<ProductSpotlightViewState['product']['quickOption'], '_id' | 'name' | 'optionRenderType'> & {
|
|
17
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
|
|
18
|
+
};
|
|
19
|
+
secondQuickOption: Pick<ProductSpotlightViewState['product']['secondQuickOption'], '_id' | 'name' | 'optionRenderType'> & {
|
|
20
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type ProductSpotlightFastViewState = {
|
|
26
|
+
product: Pick<ProductSpotlightViewState['product'], 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
|
|
27
|
+
quickOption: {
|
|
28
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
29
|
+
};
|
|
30
|
+
secondQuickOption: {
|
|
31
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type ProductSpotlightInteractiveViewState = {
|
|
37
|
+
product: Pick<ProductSpotlightViewState['product'], 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
|
|
38
|
+
quickOption: {
|
|
39
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
40
|
+
};
|
|
41
|
+
secondQuickOption: {
|
|
42
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
export interface ProductSpotlightRefs {
|
|
49
|
+
product: ProductCardRefs
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
export interface ProductSpotlightRepeatedRefs {
|
|
54
|
+
product: ProductCardRepeatedRefs
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ProductSpotlightProps {
|
|
58
|
+
slug?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type ProductSpotlightContract = JayContract<ProductSpotlightViewState, ProductSpotlightRefs, ProductSpotlightSlowViewState, ProductSpotlightFastViewState, ProductSpotlightInteractiveViewState, ProductSpotlightProps>
|
package/dist/index.client.js
CHANGED
|
@@ -886,7 +886,7 @@ function ProductSearchInteractive(props, refs, viewStateSignals, fastCarryForwar
|
|
|
886
886
|
};
|
|
887
887
|
}
|
|
888
888
|
const productSearch = makeJayStackComponent().withProps().withContexts(WIX_STORES_CONTEXT).withInteractive(ProductSearchInteractive);
|
|
889
|
-
function
|
|
889
|
+
function CategoryProductsInteractive(_props, refs, viewStateSignals, _fastCarryForward, storesContext) {
|
|
890
890
|
const { products: [products, setProducts], hasProducts: [hasProducts] } = viewStateSignals;
|
|
891
891
|
setupCardInteractions(refs.products, { get: products, set: setProducts }, storesContext);
|
|
892
892
|
return {
|
|
@@ -896,7 +896,34 @@ function RelatedProductsInteractive(_props, refs, viewStateSignals, _fastCarryFo
|
|
|
896
896
|
})
|
|
897
897
|
};
|
|
898
898
|
}
|
|
899
|
-
const
|
|
899
|
+
const categoryProducts = makeJayStackComponent().withProps().withContexts(WIX_STORES_CONTEXT).withInteractive(CategoryProductsInteractive);
|
|
900
|
+
function ProductSpotlightInteractive(_props, refs, viewStateSignals, fastCarryForward, storesContext) {
|
|
901
|
+
const { product: [product, setProduct] } = viewStateSignals;
|
|
902
|
+
const fullProduct = fastCarryForward.product;
|
|
903
|
+
refs.product.addToCartButton.onclick(async () => {
|
|
904
|
+
if (!fullProduct._id || fullProduct.quickAddType !== QuickAddType.SIMPLE)
|
|
905
|
+
return;
|
|
906
|
+
setProduct({ ...product(), isAddingToCart: true });
|
|
907
|
+
try {
|
|
908
|
+
await storesContext.addToCart(fullProduct._id, 1);
|
|
909
|
+
} catch (error) {
|
|
910
|
+
console.error("Failed to add to cart:", error);
|
|
911
|
+
} finally {
|
|
912
|
+
setProduct({ ...product(), isAddingToCart: false });
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
refs.product.viewOptionsButton.onclick(() => {
|
|
916
|
+
if (fullProduct.productUrl) {
|
|
917
|
+
window.location.href = fullProduct.productUrl;
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
return {
|
|
921
|
+
render: () => ({
|
|
922
|
+
product: product()
|
|
923
|
+
})
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
const productSpotlight = makeJayStackComponent().withProps().withContexts(WIX_STORES_CONTEXT).withInteractive(ProductSpotlightInteractive);
|
|
900
927
|
const categoryList = makeJayStackComponent().withProps();
|
|
901
928
|
const init = makeJayInit().withClient(async (data) => {
|
|
902
929
|
console.log("[wix-stores] Initializing client-side stores context...");
|
|
@@ -909,9 +936,10 @@ export {
|
|
|
909
936
|
cartIndicator,
|
|
910
937
|
cartPage,
|
|
911
938
|
categoryList,
|
|
939
|
+
categoryProducts,
|
|
912
940
|
init,
|
|
913
941
|
productPage,
|
|
914
942
|
productSearch,
|
|
915
|
-
|
|
916
|
-
|
|
943
|
+
productSpotlight,
|
|
944
|
+
provideWixStoresContext
|
|
917
945
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,13 @@ interface ProductOptionsViewState {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
interface ProductOptionsRefs {
|
|
45
|
+
choices: {
|
|
46
|
+
choiceButton: HTMLElementCollectionProxy<ChoiceOfProductOptionsViewState, HTMLButtonElement>
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
44
51
|
interface ProductOptionsRepeatedRefs {
|
|
45
52
|
choices: {
|
|
46
53
|
choiceButton: HTMLElementCollectionProxy<ChoiceOfProductOptionsViewState, HTMLButtonElement>
|
|
@@ -127,6 +134,16 @@ interface ProductCardViewState {
|
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
|
|
137
|
+
interface ProductCardRefs {
|
|
138
|
+
productLink: HTMLElementProxy<ProductCardViewState, HTMLAnchorElement>,
|
|
139
|
+
addToCartButton: HTMLElementProxy<ProductCardViewState, HTMLButtonElement>,
|
|
140
|
+
cardContainer: HTMLElementProxy<ProductCardViewState, HTMLElement>,
|
|
141
|
+
viewOptionsButton: HTMLElementProxy<ProductCardViewState, HTMLButtonElement>,
|
|
142
|
+
quickOption: ProductOptionsRefs,
|
|
143
|
+
secondQuickOption: ProductOptionsRefs
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
130
147
|
interface ProductCardRepeatedRefs {
|
|
131
148
|
productLink: HTMLElementCollectionProxy<ProductCardViewState, HTMLAnchorElement>,
|
|
132
149
|
addToCartButton: HTMLElementCollectionProxy<ProductCardViewState, HTMLButtonElement>,
|
|
@@ -470,6 +487,8 @@ interface WixStoresService {
|
|
|
470
487
|
getCustomizations(): Promise<Customization[]>;
|
|
471
488
|
/** Get cached data extension schemas for products. Lazily loaded. */
|
|
472
489
|
getDataExtensionSchemas(): Promise<DataExtensionSchema[]>;
|
|
490
|
+
/** Get the "All Products" system category ID. Lazily fetched and cached. */
|
|
491
|
+
getAllProductsCategoryId(): Promise<string | null>;
|
|
473
492
|
}
|
|
474
493
|
/**
|
|
475
494
|
* Server service marker for Wix Stores.
|
|
@@ -865,36 +884,92 @@ interface ProductFastCarryForward {
|
|
|
865
884
|
*/
|
|
866
885
|
declare const productPage: _jay_framework_fullstack_component.JayStackComponentDefinition<ProductPageRefs, ProductPageSlowViewState, ProductPageFastViewState, ProductPageInteractiveViewState, [ProductSlowCarryForward, WixStoresService], [Signals<ProductPageFastViewState>, ProductFastCarryForward, WixStoresContext], PageProps & ProductPageParams, ProductPageParams, _jay_framework_component.JayComponentCore<PageProps & ProductPageParams, ProductPageInteractiveViewState>>;
|
|
867
886
|
|
|
868
|
-
interface
|
|
887
|
+
interface CategoryProductsViewState {
|
|
869
888
|
products: Array<ProductCardViewState>,
|
|
870
889
|
hasProducts: boolean,
|
|
871
890
|
categoryName: string
|
|
872
891
|
}
|
|
873
892
|
|
|
874
|
-
type
|
|
893
|
+
type CategoryProductsSlowViewState = Pick<CategoryProductsViewState, 'categoryName'>;
|
|
875
894
|
|
|
876
|
-
type
|
|
877
|
-
products: Array<
|
|
895
|
+
type CategoryProductsFastViewState = Pick<CategoryProductsViewState, 'hasProducts'> & {
|
|
896
|
+
products: Array<CategoryProductsViewState['products'][number]>;
|
|
878
897
|
};
|
|
879
898
|
|
|
880
|
-
type
|
|
881
|
-
products: Array<
|
|
899
|
+
type CategoryProductsInteractiveViewState = Pick<CategoryProductsViewState, 'hasProducts'> & {
|
|
900
|
+
products: Array<CategoryProductsViewState['products'][number]>;
|
|
882
901
|
};
|
|
883
902
|
|
|
884
903
|
|
|
885
|
-
interface
|
|
904
|
+
interface CategoryProductsRefs {
|
|
886
905
|
products: ProductCardRepeatedRefs
|
|
887
906
|
}
|
|
888
907
|
|
|
889
|
-
interface
|
|
890
|
-
productId
|
|
908
|
+
interface CategoryProductsProps {
|
|
909
|
+
productId?: string;
|
|
891
910
|
categorySlug?: string;
|
|
892
911
|
limit?: number;
|
|
893
912
|
}
|
|
894
|
-
interface
|
|
913
|
+
interface SlowCarryForward {
|
|
895
914
|
products: ProductCardViewState[];
|
|
896
915
|
}
|
|
897
|
-
declare const
|
|
916
|
+
declare const categoryProducts: _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryProductsRefs, CategoryProductsSlowViewState, CategoryProductsFastViewState, CategoryProductsInteractiveViewState, [SlowCarryForward, WixStoresService], [Signals<CategoryProductsFastViewState>, Record<string, never>, WixStoresContext], PageProps & CategoryProductsProps, {}, _jay_framework_component.JayComponentCore<PageProps & CategoryProductsProps, CategoryProductsInteractiveViewState>>;
|
|
917
|
+
|
|
918
|
+
interface ProductSpotlightViewState {
|
|
919
|
+
product: ProductCardViewState,
|
|
920
|
+
hasProduct: boolean
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
type ProductSpotlightSlowViewState = Pick<ProductSpotlightViewState, 'hasProduct'> & {
|
|
924
|
+
product: Pick<ProductSpotlightViewState['product'], '_id' | 'name' | 'slug' | 'productUrl' | 'categoryPrefix' | 'hasDiscount' | 'hasRibbon' | 'productType' | 'quickAddType'> & {
|
|
925
|
+
mainMedia: ProductSpotlightViewState['product']['mainMedia'];
|
|
926
|
+
thumbnail: ProductSpotlightViewState['product']['thumbnail'];
|
|
927
|
+
inventory: ProductSpotlightViewState['product']['inventory'];
|
|
928
|
+
ribbon: ProductSpotlightViewState['product']['ribbon'];
|
|
929
|
+
brand: ProductSpotlightViewState['product']['brand'];
|
|
930
|
+
quickOption: Pick<ProductSpotlightViewState['product']['quickOption'], '_id' | 'name' | 'optionRenderType'> & {
|
|
931
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
|
|
932
|
+
};
|
|
933
|
+
secondQuickOption: Pick<ProductSpotlightViewState['product']['secondQuickOption'], '_id' | 'name' | 'optionRenderType'> & {
|
|
934
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
|
|
935
|
+
};
|
|
936
|
+
};
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
type ProductSpotlightFastViewState = {
|
|
940
|
+
product: Pick<ProductSpotlightViewState['product'], 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
|
|
941
|
+
quickOption: {
|
|
942
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
943
|
+
};
|
|
944
|
+
secondQuickOption: {
|
|
945
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
946
|
+
};
|
|
947
|
+
};
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
type ProductSpotlightInteractiveViewState = {
|
|
951
|
+
product: Pick<ProductSpotlightViewState['product'], 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
|
|
952
|
+
quickOption: {
|
|
953
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
954
|
+
};
|
|
955
|
+
secondQuickOption: {
|
|
956
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
957
|
+
};
|
|
958
|
+
};
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
interface ProductSpotlightRefs {
|
|
963
|
+
product: ProductCardRefs
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
interface ProductSpotlightProps {
|
|
967
|
+
slug: string;
|
|
968
|
+
}
|
|
969
|
+
interface SpotlightCarryForward {
|
|
970
|
+
product: ProductCardViewState;
|
|
971
|
+
}
|
|
972
|
+
declare const productSpotlight: _jay_framework_fullstack_component.JayStackComponentDefinition<ProductSpotlightRefs, ProductSpotlightSlowViewState, ProductSpotlightFastViewState, ProductSpotlightInteractiveViewState, [SpotlightCarryForward, WixStoresService], [Signals<ProductSpotlightFastViewState>, SpotlightCarryForward, WixStoresContext], PageProps & ProductSpotlightProps, {}, _jay_framework_component.JayComponentCore<PageProps & ProductSpotlightProps, ProductSpotlightInteractiveViewState>>;
|
|
898
973
|
|
|
899
974
|
interface CategoryOfCategoryListViewState {
|
|
900
975
|
_id: string,
|
|
@@ -1065,4 +1140,4 @@ declare function generateWixStoresReferences(ctx: PluginReferencesContext): Prom
|
|
|
1065
1140
|
*/
|
|
1066
1141
|
declare const generator: _jay_framework_fullstack_component.DynamicContractGenerator<[WixStoresService]>;
|
|
1067
1142
|
|
|
1068
|
-
export { type CategoryListParams, type CategoryTree, type GetProductBySlugInput, type ProductPageParams, type ProductSearchParams, type
|
|
1143
|
+
export { type CategoryListParams, type CategoryProductsProps, type CategoryTree, type GetProductBySlugInput, type ProductPageParams, type ProductSearchParams, type ProductSpotlightProps, WIX_STORES_CONTEXT, WIX_STORES_SERVICE_MARKER, type WixStoresContext, type WixStoresInitData, type WixStoresService, type WixStoresServiceOptions, buildCategoryUrl, buildProductUrl, categoryList, categoryProducts, findCategoryImage, findRootCategoryId, findRootCategorySlug, generateWixStoresReferences, getCategories, getProductBySlug, getVariantStock, init, productPage, generator as productPageContractGenerator, productSearch, productSpotlight, provideWixStoresService, searchProducts, setupWixStores };
|
package/dist/index.js
CHANGED
|
@@ -60,6 +60,7 @@ function provideWixStoresService(wixClient, options) {
|
|
|
60
60
|
let cachedTree = null;
|
|
61
61
|
let cachedCustomizations = null;
|
|
62
62
|
let cachedExtensionSchemas = null;
|
|
63
|
+
let cachedAllProductsCategoryId;
|
|
63
64
|
const categoriesClient = getCategoriesClient(wixClient);
|
|
64
65
|
const customizationsClient = getCustomizationsV3Client(wixClient);
|
|
65
66
|
const service = {
|
|
@@ -134,6 +135,17 @@ function provideWixStoresService(wixClient, options) {
|
|
|
134
135
|
cachedExtensionSchemas = [];
|
|
135
136
|
}
|
|
136
137
|
return cachedExtensionSchemas;
|
|
138
|
+
},
|
|
139
|
+
async getAllProductsCategoryId() {
|
|
140
|
+
if (cachedAllProductsCategoryId !== void 0) return cachedAllProductsCategoryId;
|
|
141
|
+
try {
|
|
142
|
+
const result = await service.products.getAllProductsCategory();
|
|
143
|
+
cachedAllProductsCategoryId = result.categoryId ?? null;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error("[wix-stores] Failed to get All Products category:", error);
|
|
146
|
+
cachedAllProductsCategoryId = null;
|
|
147
|
+
}
|
|
148
|
+
return cachedAllProductsCategoryId;
|
|
137
149
|
}
|
|
138
150
|
};
|
|
139
151
|
registerService(WIX_STORES_SERVICE_MARKER, service);
|
|
@@ -716,6 +728,7 @@ const getProductBySlug = makeJayQuery("wixStores.getProductBySlug").withServices
|
|
|
716
728
|
const fields = [
|
|
717
729
|
"MEDIA_ITEMS_INFO",
|
|
718
730
|
"VARIANT_OPTION_CHOICE_NAMES",
|
|
731
|
+
"CURRENCY",
|
|
719
732
|
...needsCategoryInfo(wixStores) ? ["ALL_CATEGORIES_INFO"] : []
|
|
720
733
|
];
|
|
721
734
|
const result = await wixStores.products.getProductBySlug(slug, {
|
|
@@ -878,7 +891,10 @@ const EMPTY_CATEGORY_HEADER = {
|
|
|
878
891
|
};
|
|
879
892
|
async function findCategoryBySlug$1(categoriesClient, slug) {
|
|
880
893
|
const result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("slug", slug).eq("visible", true).limit(1).find();
|
|
881
|
-
|
|
894
|
+
const cat = result.items?.[0];
|
|
895
|
+
if (!cat?._id)
|
|
896
|
+
return null;
|
|
897
|
+
return loadCategoryDetails(categoriesClient, cat._id);
|
|
882
898
|
}
|
|
883
899
|
async function loadCategoryDetails(categoriesClient, categoryId) {
|
|
884
900
|
try {
|
|
@@ -888,8 +904,7 @@ async function loadCategoryDetails(categoriesClient, categoryId) {
|
|
|
888
904
|
}
|
|
889
905
|
}
|
|
890
906
|
async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplate) {
|
|
891
|
-
const
|
|
892
|
-
const cat = details || category;
|
|
907
|
+
const cat = category;
|
|
893
908
|
const imageUrl = cat.image ? formatWixMediaUrl("", cat.image) : "";
|
|
894
909
|
const description = cat.description || "";
|
|
895
910
|
const categoryTree = await wixStoreService.getCategoryTree();
|
|
@@ -955,21 +970,19 @@ async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplat
|
|
|
955
970
|
}
|
|
956
971
|
return header;
|
|
957
972
|
}
|
|
958
|
-
async function renderSlowlyChanging$
|
|
973
|
+
async function renderSlowlyChanging$4(props, wixStores) {
|
|
959
974
|
const Pipeline = RenderPipeline.for();
|
|
960
975
|
const categorySlug = props.category ?? null;
|
|
961
|
-
const prefixSlug = props.prefix ?? null;
|
|
962
|
-
const defaultCategorySlug = wixStores.defaultCategory;
|
|
963
976
|
let activeCategory = null;
|
|
964
977
|
let baseCategoryId = null;
|
|
965
978
|
if (categorySlug) {
|
|
966
979
|
activeCategory = await findCategoryBySlug$1(wixStores.categories, categorySlug);
|
|
967
980
|
baseCategoryId = activeCategory?._id ?? null;
|
|
968
|
-
} else
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
981
|
+
} else {
|
|
982
|
+
const allProductsCategoryId = await wixStores.getAllProductsCategoryId();
|
|
983
|
+
if (allProductsCategoryId) {
|
|
984
|
+
activeCategory = await loadCategoryDetails(wixStores.categories, allProductsCategoryId);
|
|
985
|
+
}
|
|
973
986
|
}
|
|
974
987
|
const tree = await wixStores.getCategoryTree();
|
|
975
988
|
const categoryHeader = activeCategory ? await buildCategoryHeader(wixStores, activeCategory, wixStores.urls.category) : EMPTY_CATEGORY_HEADER;
|
|
@@ -1028,7 +1041,7 @@ async function renderSlowlyChanging$3(props, wixStores) {
|
|
|
1028
1041
|
};
|
|
1029
1042
|
});
|
|
1030
1043
|
}
|
|
1031
|
-
async function renderFastChanging$
|
|
1044
|
+
async function renderFastChanging$3(props, slowCarryForward, _wixStores) {
|
|
1032
1045
|
const Pipeline = RenderPipeline.for();
|
|
1033
1046
|
const urlFilters = parseUrlFilters(props.url);
|
|
1034
1047
|
const initialSort = parseSortParam(urlFilters.sort);
|
|
@@ -1155,12 +1168,13 @@ async function* loadSearchParams([wixStores]) {
|
|
|
1155
1168
|
if (rootSlug) {
|
|
1156
1169
|
params.push({ prefix: rootSlug, category: node.slug });
|
|
1157
1170
|
} else {
|
|
1158
|
-
params.push({
|
|
1171
|
+
params.push({ category: node.slug });
|
|
1159
1172
|
}
|
|
1160
1173
|
for (const child of node.children) {
|
|
1161
1174
|
collectParams(child, rootSlug ?? node.slug);
|
|
1162
1175
|
}
|
|
1163
1176
|
};
|
|
1177
|
+
const allProductsCategoryId = await wixStores.getAllProductsCategoryId();
|
|
1164
1178
|
const allCategories = [];
|
|
1165
1179
|
let result = await wixStores.categories.queryCategories({
|
|
1166
1180
|
treeReference: { appNamespace: "@wix/stores" }
|
|
@@ -1176,6 +1190,8 @@ async function* loadSearchParams([wixStores]) {
|
|
|
1176
1190
|
for (const cat of allCategories) {
|
|
1177
1191
|
if (!cat._id)
|
|
1178
1192
|
continue;
|
|
1193
|
+
if (cat._id === allProductsCategoryId)
|
|
1194
|
+
continue;
|
|
1179
1195
|
const node = {
|
|
1180
1196
|
slug: cat.slug || "",
|
|
1181
1197
|
itemCount: cat.itemCounter ?? 0,
|
|
@@ -1205,7 +1221,7 @@ async function* loadSearchParams([wixStores]) {
|
|
|
1205
1221
|
for (const root of roots) {
|
|
1206
1222
|
sumItems(root);
|
|
1207
1223
|
}
|
|
1208
|
-
const params = [];
|
|
1224
|
+
const params = [{}];
|
|
1209
1225
|
for (const root of roots) {
|
|
1210
1226
|
collectParams(root, null);
|
|
1211
1227
|
}
|
|
@@ -1215,7 +1231,7 @@ async function* loadSearchParams([wixStores]) {
|
|
|
1215
1231
|
yield [];
|
|
1216
1232
|
}
|
|
1217
1233
|
}
|
|
1218
|
-
const productSearch = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadSearchParams).withSlowlyRender(renderSlowlyChanging$
|
|
1234
|
+
const productSearch = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadSearchParams).withSlowlyRender(renderSlowlyChanging$4).withFastRender(renderFastChanging$3);
|
|
1219
1235
|
var ProductType = /* @__PURE__ */ ((ProductType2) => {
|
|
1220
1236
|
ProductType2[ProductType2["PHYSICAL"] = 0] = "PHYSICAL";
|
|
1221
1237
|
ProductType2[ProductType2["DIGITAL"] = 1] = "DIGITAL";
|
|
@@ -1449,7 +1465,7 @@ function mapVariants(variantsInfo) {
|
|
|
1449
1465
|
strikethroughPrice: variant.price.compareAtPrice?.formattedAmount || ""
|
|
1450
1466
|
})) || [];
|
|
1451
1467
|
}
|
|
1452
|
-
async function renderSlowlyChanging$
|
|
1468
|
+
async function renderSlowlyChanging$3(props, wixStores) {
|
|
1453
1469
|
const Pipeline = RenderPipeline.for();
|
|
1454
1470
|
const template = wixStores.urls.product;
|
|
1455
1471
|
const needsCategories = template.includes("{category}") || template.includes("{prefix}");
|
|
@@ -1505,7 +1521,7 @@ async function renderSlowlyChanging$2(props, wixStores) {
|
|
|
1505
1521
|
};
|
|
1506
1522
|
});
|
|
1507
1523
|
}
|
|
1508
|
-
async function renderFastChanging$
|
|
1524
|
+
async function renderFastChanging$2(props, slowCarryForward, wixStores) {
|
|
1509
1525
|
const Pipeline = RenderPipeline.for();
|
|
1510
1526
|
const { variants } = slowCarryForward;
|
|
1511
1527
|
const defaultVariant = variants.find((v) => v.inventoryStatus === StockStatus.IN_STOCK) || variants[0];
|
|
@@ -1555,9 +1571,9 @@ async function renderFastChanging$1(props, slowCarryForward, wixStores) {
|
|
|
1555
1571
|
}
|
|
1556
1572
|
}));
|
|
1557
1573
|
}
|
|
1558
|
-
const productPage = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadProductParams).withSlowlyRender(renderSlowlyChanging$
|
|
1574
|
+
const productPage = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadProductParams).withSlowlyRender(renderSlowlyChanging$3).withFastRender(renderFastChanging$2);
|
|
1559
1575
|
const DEFAULT_LIMIT = 4;
|
|
1560
|
-
async function renderSlowlyChanging$
|
|
1576
|
+
async function renderSlowlyChanging$2(props, wixStores) {
|
|
1561
1577
|
const Pipeline = RenderPipeline.for();
|
|
1562
1578
|
const limit = props.limit ?? DEFAULT_LIMIT;
|
|
1563
1579
|
const categorySlug = props.categorySlug;
|
|
@@ -1601,7 +1617,7 @@ async function renderSlowlyChanging$1(props, wixStores) {
|
|
|
1601
1617
|
carryForward: { products }
|
|
1602
1618
|
}));
|
|
1603
1619
|
}
|
|
1604
|
-
async function renderFastChanging(_props, slowCarryForward, _wixStores) {
|
|
1620
|
+
async function renderFastChanging$1(_props, slowCarryForward, _wixStores) {
|
|
1605
1621
|
const Pipeline = RenderPipeline.for();
|
|
1606
1622
|
const { products } = slowCarryForward;
|
|
1607
1623
|
return Pipeline.ok({
|
|
@@ -1609,7 +1625,95 @@ async function renderFastChanging(_props, slowCarryForward, _wixStores) {
|
|
|
1609
1625
|
hasProducts: products.length > 0
|
|
1610
1626
|
}).toPhaseOutput((viewState) => ({ viewState, carryForward: {} }));
|
|
1611
1627
|
}
|
|
1612
|
-
const
|
|
1628
|
+
const categoryProducts = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging$2).withFastRender(renderFastChanging$1);
|
|
1629
|
+
async function renderSlowlyChanging$1(props, _wixStores) {
|
|
1630
|
+
const Pipeline = RenderPipeline.for();
|
|
1631
|
+
return Pipeline.try(async () => {
|
|
1632
|
+
if (!props.slug) {
|
|
1633
|
+
throw new Error("No product slug provided");
|
|
1634
|
+
}
|
|
1635
|
+
const card = await getProductBySlug({ slug: props.slug });
|
|
1636
|
+
if (!card) {
|
|
1637
|
+
throw new Error(`Product not found: ${props.slug}`);
|
|
1638
|
+
}
|
|
1639
|
+
return card;
|
|
1640
|
+
}).recover((error) => {
|
|
1641
|
+
return handleError(error);
|
|
1642
|
+
}).toPhaseOutput((product) => {
|
|
1643
|
+
return {
|
|
1644
|
+
viewState: {
|
|
1645
|
+
hasProduct: true,
|
|
1646
|
+
product: {
|
|
1647
|
+
_id: product._id,
|
|
1648
|
+
name: product.name,
|
|
1649
|
+
slug: product.slug,
|
|
1650
|
+
productUrl: product.productUrl,
|
|
1651
|
+
categoryPrefix: product.categoryPrefix,
|
|
1652
|
+
mainMedia: product.mainMedia,
|
|
1653
|
+
thumbnail: product.thumbnail,
|
|
1654
|
+
hasDiscount: product.hasDiscount,
|
|
1655
|
+
inventory: product.inventory,
|
|
1656
|
+
ribbon: product.ribbon,
|
|
1657
|
+
hasRibbon: product.hasRibbon,
|
|
1658
|
+
brand: product.brand,
|
|
1659
|
+
productType: product.productType,
|
|
1660
|
+
quickAddType: product.quickAddType,
|
|
1661
|
+
quickOption: {
|
|
1662
|
+
_id: product.quickOption?._id,
|
|
1663
|
+
name: product.quickOption?.name,
|
|
1664
|
+
optionRenderType: product.quickOption?.optionRenderType,
|
|
1665
|
+
choices: (product.quickOption?.choices ?? []).map((c) => ({
|
|
1666
|
+
choiceId: c.choiceId,
|
|
1667
|
+
name: c.name,
|
|
1668
|
+
choiceType: c.choiceType,
|
|
1669
|
+
colorCode: c.colorCode
|
|
1670
|
+
}))
|
|
1671
|
+
},
|
|
1672
|
+
secondQuickOption: {
|
|
1673
|
+
_id: product.secondQuickOption?._id,
|
|
1674
|
+
name: product.secondQuickOption?.name,
|
|
1675
|
+
optionRenderType: product.secondQuickOption?.optionRenderType,
|
|
1676
|
+
choices: (product.secondQuickOption?.choices ?? []).map((c) => ({
|
|
1677
|
+
choiceId: c.choiceId,
|
|
1678
|
+
name: c.name,
|
|
1679
|
+
choiceType: c.choiceType,
|
|
1680
|
+
colorCode: c.colorCode
|
|
1681
|
+
}))
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
},
|
|
1685
|
+
carryForward: { product }
|
|
1686
|
+
};
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1689
|
+
async function renderFastChanging(_props, carryForward, _wixStores) {
|
|
1690
|
+
const Pipeline = RenderPipeline.for();
|
|
1691
|
+
const { product } = carryForward;
|
|
1692
|
+
return Pipeline.ok({
|
|
1693
|
+
product: {
|
|
1694
|
+
price: product.price,
|
|
1695
|
+
strikethroughPrice: product.strikethroughPrice,
|
|
1696
|
+
isAddingToCart: false,
|
|
1697
|
+
quickOption: {
|
|
1698
|
+
choices: (product.quickOption?.choices ?? []).map((c) => ({
|
|
1699
|
+
choiceId: c.choiceId,
|
|
1700
|
+
inStock: c.inStock,
|
|
1701
|
+
isSelected: c.isSelected
|
|
1702
|
+
}))
|
|
1703
|
+
},
|
|
1704
|
+
secondQuickOption: {
|
|
1705
|
+
choices: (product.secondQuickOption?.choices ?? []).map((c) => ({
|
|
1706
|
+
choiceId: c.choiceId,
|
|
1707
|
+
inStock: c.inStock,
|
|
1708
|
+
isSelected: c.isSelected
|
|
1709
|
+
}))
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
}).toPhaseOutput((viewState) => {
|
|
1713
|
+
return { viewState, carryForward: { product } };
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
const productSpotlight = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging$1).withFastRender(renderFastChanging);
|
|
1613
1717
|
async function findCategoryBySlug(categoriesClient, slug) {
|
|
1614
1718
|
const result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("slug", slug).eq("visible", true).limit(1).find();
|
|
1615
1719
|
return result.items?.[0] ?? null;
|
|
@@ -1807,12 +1911,12 @@ function buildCategoryPrompt(config, entry) {
|
|
|
1807
1911
|
);
|
|
1808
1912
|
}
|
|
1809
1913
|
lines.push(
|
|
1810
|
-
`
|
|
1914
|
+
` category-products — pass categorySlug="${node.slug}" to show products from this category; optionally pass productId to exclude a product`,
|
|
1811
1915
|
"",
|
|
1812
1916
|
"Contracts:",
|
|
1813
1917
|
" agent-kit/materialized-contracts/wix-stores/product-search.jay-contract",
|
|
1814
1918
|
" agent-kit/materialized-contracts/wix-stores/category-list.jay-contract",
|
|
1815
|
-
" agent-kit/materialized-contracts/wix-stores/
|
|
1919
|
+
" agent-kit/materialized-contracts/wix-stores/category-products.jay-contract",
|
|
1816
1920
|
"",
|
|
1817
1921
|
"Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md."
|
|
1818
1922
|
);
|
|
@@ -1843,16 +1947,39 @@ function buildCategoryAddMenuItems(roots, config) {
|
|
|
1843
1947
|
prompt: buildCategoryPrompt(config, entry)
|
|
1844
1948
|
}));
|
|
1845
1949
|
}
|
|
1950
|
+
const PUBLIC_THUMBNAIL_ROOT = path.join("public", "aiditor-add-menu-thumbnails");
|
|
1951
|
+
function copyAiditorAddMenuThumbnails(ctx, resolvePackagePath, pluginName) {
|
|
1952
|
+
const sourceDir = resolvePackagePath(
|
|
1953
|
+
path.join("agent-kit", "aiditor", "thumbnails", pluginName)
|
|
1954
|
+
);
|
|
1955
|
+
if (!fs.existsSync(sourceDir)) return [];
|
|
1956
|
+
const destDir = path.join(ctx.projectRoot, PUBLIC_THUMBNAIL_ROOT, pluginName);
|
|
1957
|
+
const created = [];
|
|
1958
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
1959
|
+
for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
1960
|
+
if (!entry.isFile()) continue;
|
|
1961
|
+
const src = path.join(sourceDir, entry.name);
|
|
1962
|
+
const dest = path.join(destDir, entry.name);
|
|
1963
|
+
if (!fs.existsSync(dest) || ctx.force) {
|
|
1964
|
+
fs.copyFileSync(src, dest);
|
|
1965
|
+
created.push(path.posix.join(PUBLIC_THUMBNAIL_ROOT, pluginName, entry.name));
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
return created;
|
|
1969
|
+
}
|
|
1846
1970
|
const CONFIG_FILE_NAME = ".wix-stores.yaml";
|
|
1847
1971
|
const ADD_MENU_OUTPUT_REL = "agent-kit/aiditor/add-menu/wix-stores.yaml";
|
|
1848
1972
|
const ADD_MENU_GENERATED_REL = "agent-kit/aiditor/add-menu/wix-stores.generated.yaml";
|
|
1849
|
-
function
|
|
1973
|
+
function resolvePackageAgentKitPath(relativePath) {
|
|
1850
1974
|
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
1851
|
-
const fromDist = path.join(thisDir,
|
|
1975
|
+
const fromDist = path.join(thisDir, relativePath);
|
|
1852
1976
|
if (fs.existsSync(fromDist)) {
|
|
1853
1977
|
return fromDist;
|
|
1854
1978
|
}
|
|
1855
|
-
return path.join(thisDir, "..",
|
|
1979
|
+
return path.join(thisDir, "..", relativePath);
|
|
1980
|
+
}
|
|
1981
|
+
function resolveAddMenuTemplatePath() {
|
|
1982
|
+
return resolvePackageAgentKitPath("agent-kit/aiditor/add-menu.template.yaml");
|
|
1856
1983
|
}
|
|
1857
1984
|
function writeAddMenuCatalog(ctx) {
|
|
1858
1985
|
const outputPath = path.join(ctx.projectRoot, ADD_MENU_OUTPUT_REL);
|
|
@@ -1933,6 +2060,9 @@ async function setupWixStores(ctx) {
|
|
|
1933
2060
|
if (addMenuCreated) {
|
|
1934
2061
|
configCreated.push(addMenuCreated);
|
|
1935
2062
|
}
|
|
2063
|
+
configCreated.push(
|
|
2064
|
+
...copyAiditorAddMenuThumbnails(ctx, resolvePackageAgentKitPath, "wix-stores")
|
|
2065
|
+
);
|
|
1936
2066
|
const message = `Wix Stores configured (product URL: ${service.urls.product})`;
|
|
1937
2067
|
return {
|
|
1938
2068
|
status: "configured",
|
|
@@ -2276,6 +2406,7 @@ export {
|
|
|
2276
2406
|
cartIndicator,
|
|
2277
2407
|
cartPage,
|
|
2278
2408
|
categoryList,
|
|
2409
|
+
categoryProducts,
|
|
2279
2410
|
findCategoryImage,
|
|
2280
2411
|
findRootCategoryId,
|
|
2281
2412
|
findRootCategorySlug,
|
|
@@ -2287,10 +2418,10 @@ export {
|
|
|
2287
2418
|
productPage,
|
|
2288
2419
|
generator as productPageContractGenerator,
|
|
2289
2420
|
productSearch,
|
|
2421
|
+
productSpotlight,
|
|
2290
2422
|
provideWixCartContext,
|
|
2291
2423
|
provideWixCartService,
|
|
2292
2424
|
provideWixStoresService,
|
|
2293
|
-
relatedProducts,
|
|
2294
2425
|
searchProducts,
|
|
2295
2426
|
setupWixStores
|
|
2296
2427
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/wix-stores",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Wix Stores API client for Jay Framework",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"./media.jay-contract": "./dist/contracts/media.jay-contract",
|
|
18
18
|
"./media-gallery.jay-contract": "./dist/contracts/media-gallery.jay-contract",
|
|
19
19
|
"./product-search.jay-contract": "./dist/contracts/product-search.jay-contract",
|
|
20
|
-
"./
|
|
20
|
+
"./category-products.jay-contract": "./dist/contracts/category-products.jay-contract",
|
|
21
|
+
"./product-spotlight.jay-contract": "./dist/contracts/product-spotlight.jay-contract",
|
|
21
22
|
"./category-list.jay-contract": "./dist/contracts/category-list.jay-contract",
|
|
22
23
|
"./search-products.jay-action": "./dist/actions/search-products.jay-action",
|
|
23
24
|
"./get-product-by-slug.jay-action": "./dist/actions/get-product-by-slug.jay-action",
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"validate": "jay-stack-cli validate-plugin",
|
|
31
32
|
"build:client": "vite build",
|
|
32
33
|
"build:server": "vite build --ssr",
|
|
33
|
-
"build:copy-contract": "mkdir -p dist/contracts && cp lib/contracts/*.jay-contract* dist/contracts/ && mkdir -p dist/actions && cp lib/actions/*.jay-action dist/actions/ && mkdir -p dist/agent-kit/aiditor && cp agent-kit/aiditor/add-menu.template.yaml dist/agent-kit/aiditor/",
|
|
34
|
+
"build:copy-contract": "mkdir -p dist/contracts && cp lib/contracts/*.jay-contract* dist/contracts/ && mkdir -p dist/actions && cp lib/actions/*.jay-action dist/actions/ && mkdir -p dist/agent-kit/aiditor && cp agent-kit/aiditor/add-menu.template.yaml dist/agent-kit/aiditor/ && cp -R agent-kit/aiditor/thumbnails dist/agent-kit/aiditor/",
|
|
34
35
|
"build:types": "tsup lib/index.ts --dts-only --format esm",
|
|
35
36
|
"build:check-types": "tsc",
|
|
36
37
|
"clean": "rimraf dist",
|
|
@@ -38,16 +39,16 @@
|
|
|
38
39
|
"test": "vitest run"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@jay-framework/component": "^0.
|
|
42
|
-
"@jay-framework/fullstack-component": "^0.
|
|
43
|
-
"@jay-framework/reactive": "^0.
|
|
44
|
-
"@jay-framework/runtime": "^0.
|
|
45
|
-
"@jay-framework/secure": "^0.
|
|
46
|
-
"@jay-framework/stack-client-runtime": "^0.
|
|
47
|
-
"@jay-framework/stack-server-runtime": "^0.
|
|
48
|
-
"@jay-framework/wix-cart": "^0.
|
|
49
|
-
"@jay-framework/wix-server-client": "^0.
|
|
50
|
-
"@jay-framework/wix-utils": "^0.
|
|
42
|
+
"@jay-framework/component": "^0.20.0",
|
|
43
|
+
"@jay-framework/fullstack-component": "^0.20.0",
|
|
44
|
+
"@jay-framework/reactive": "^0.20.0",
|
|
45
|
+
"@jay-framework/runtime": "^0.20.0",
|
|
46
|
+
"@jay-framework/secure": "^0.20.0",
|
|
47
|
+
"@jay-framework/stack-client-runtime": "^0.20.0",
|
|
48
|
+
"@jay-framework/stack-server-runtime": "^0.20.0",
|
|
49
|
+
"@jay-framework/wix-cart": "^0.20.0",
|
|
50
|
+
"@jay-framework/wix-server-client": "^0.20.0",
|
|
51
|
+
"@jay-framework/wix-utils": "^0.20.0",
|
|
51
52
|
"@wix/categories": "^1.0.185",
|
|
52
53
|
"@wix/data-extension-schema": "^1.0.221",
|
|
53
54
|
"@wix/sdk": "^1.21.5",
|
|
@@ -59,10 +60,10 @@
|
|
|
59
60
|
"@babel/core": "^7.23.7",
|
|
60
61
|
"@babel/preset-env": "^7.23.8",
|
|
61
62
|
"@babel/preset-typescript": "^7.23.3",
|
|
62
|
-
"@jay-framework/compiler-jay-stack": "^0.
|
|
63
|
-
"@jay-framework/jay-cli": "^0.
|
|
64
|
-
"@jay-framework/jay-stack-cli": "^0.
|
|
65
|
-
"@jay-framework/vite-plugin": "^0.
|
|
63
|
+
"@jay-framework/compiler-jay-stack": "^0.20.0",
|
|
64
|
+
"@jay-framework/jay-cli": "^0.20.0",
|
|
65
|
+
"@jay-framework/jay-stack-cli": "^0.20.0",
|
|
66
|
+
"@jay-framework/vite-plugin": "^0.20.0",
|
|
66
67
|
"nodemon": "^3.0.3",
|
|
67
68
|
"rimraf": "^5.0.5",
|
|
68
69
|
"tslib": "^2.6.2",
|
package/plugin.yaml
CHANGED
|
@@ -7,10 +7,14 @@ contracts:
|
|
|
7
7
|
component: productSearch
|
|
8
8
|
description: Headless product search page
|
|
9
9
|
# category-page removed — use product-search with prefix/category params instead
|
|
10
|
-
- name:
|
|
11
|
-
contract:
|
|
12
|
-
component:
|
|
13
|
-
description:
|
|
10
|
+
- name: category-products
|
|
11
|
+
contract: category-products.jay-contract
|
|
12
|
+
component: categoryProducts
|
|
13
|
+
description: Products from a category — use for showcases or as related products (exclude current product via productId)
|
|
14
|
+
- name: product-spotlight
|
|
15
|
+
contract: product-spotlight.jay-contract
|
|
16
|
+
component: productSpotlight
|
|
17
|
+
description: A single product card by product ID — use to feature a product on any page
|
|
14
18
|
- name: category-list
|
|
15
19
|
contract: category-list.jay-contract
|
|
16
20
|
component: categoryList
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
name: related-products
|
|
2
|
-
description: Related products grid showing products from the same category. Use on product pages alongside the product-page component.
|
|
3
|
-
props:
|
|
4
|
-
- name: productId
|
|
5
|
-
type: string
|
|
6
|
-
description: Product ID to exclude from results
|
|
7
|
-
- name: categorySlug
|
|
8
|
-
type: string
|
|
9
|
-
description: Category slug to filter related products by
|
|
10
|
-
- name: limit
|
|
11
|
-
type: number
|
|
12
|
-
description: Maximum number of related products to show (default 4)
|
|
13
|
-
tags:
|
|
14
|
-
- tag: products
|
|
15
|
-
type: sub-contract
|
|
16
|
-
repeated: true
|
|
17
|
-
trackBy: _id
|
|
18
|
-
phase: fast+interactive
|
|
19
|
-
description: Related product cards
|
|
20
|
-
link: ./product-card
|
|
21
|
-
|
|
22
|
-
- tag: hasProducts
|
|
23
|
-
type: variant
|
|
24
|
-
dataType: boolean
|
|
25
|
-
phase: fast+interactive
|
|
26
|
-
description: Whether there are related products to show
|
|
27
|
-
|
|
28
|
-
- tag: categoryName
|
|
29
|
-
type: data
|
|
30
|
-
dataType: string
|
|
31
|
-
description: Name of the category these products belong to
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {JayContract} from "@jay-framework/runtime";
|
|
2
|
-
import {ProductCardViewState, ProductCardRefs, ProductCardRepeatedRefs} from "./product-card.jay-contract";
|
|
3
|
-
|
|
4
|
-
export interface RelatedProductsViewState {
|
|
5
|
-
products: Array<ProductCardViewState>,
|
|
6
|
-
hasProducts: boolean,
|
|
7
|
-
categoryName: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export type RelatedProductsSlowViewState = Pick<RelatedProductsViewState, 'categoryName'>;
|
|
11
|
-
|
|
12
|
-
export type RelatedProductsFastViewState = Pick<RelatedProductsViewState, 'hasProducts'> & {
|
|
13
|
-
products: Array<RelatedProductsViewState['products'][number]>;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type RelatedProductsInteractiveViewState = Pick<RelatedProductsViewState, 'hasProducts'> & {
|
|
17
|
-
products: Array<RelatedProductsViewState['products'][number]>;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export interface RelatedProductsRefs {
|
|
22
|
-
products: ProductCardRepeatedRefs
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export interface RelatedProductsRepeatedRefs {
|
|
27
|
-
products: ProductCardRepeatedRefs
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface RelatedProductsProps {
|
|
31
|
-
productId?: string;
|
|
32
|
-
categorySlug?: string;
|
|
33
|
-
limit?: number;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export type RelatedProductsContract = JayContract<RelatedProductsViewState, RelatedProductsRefs, RelatedProductsSlowViewState, RelatedProductsFastViewState, RelatedProductsInteractiveViewState, RelatedProductsProps>
|