@jay-framework/wix-stores 0.19.6 → 0.19.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-kit/aiditor/add-menu.template.yaml +20 -6
- 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 +85 -12
- package/dist/index.js +102 -12
- package/package.json +17 -16
- 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
|
@@ -25,19 +25,33 @@ items:
|
|
|
25
25
|
Script key: p
|
|
26
26
|
Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md.
|
|
27
27
|
|
|
28
|
-
- id: wix-stores:
|
|
29
|
-
title:
|
|
28
|
+
- id: wix-stores:category-products
|
|
29
|
+
title: Category products
|
|
30
30
|
category: Store
|
|
31
31
|
subCategory: Components
|
|
32
32
|
pluginName: wix-stores
|
|
33
33
|
packageName: "@jay-framework/wix-stores"
|
|
34
|
-
thumbnail: thumbnails/wix-stores/
|
|
34
|
+
thumbnail: thumbnails/wix-stores/category-products.png
|
|
35
35
|
prompt: |
|
|
36
|
-
Use headless component @jay-framework/wix-stores / contract
|
|
37
|
-
Read agent-kit/materialized-contracts/wix-stores/
|
|
36
|
+
Use headless component @jay-framework/wix-stores / contract category-products.
|
|
37
|
+
Read agent-kit/materialized-contracts/wix-stores/category-products.jay-contract.
|
|
38
38
|
Script key: r
|
|
39
39
|
Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md.
|
|
40
|
-
|
|
40
|
+
Pass categorySlug to show products from a category. Pass productId to exclude a product (e.g. on a product page).
|
|
41
|
+
|
|
42
|
+
- id: wix-stores:product-spotlight
|
|
43
|
+
title: Product spotlight
|
|
44
|
+
category: Store
|
|
45
|
+
subCategory: Components
|
|
46
|
+
pluginName: wix-stores
|
|
47
|
+
packageName: "@jay-framework/wix-stores"
|
|
48
|
+
thumbnail: thumbnails/wix-stores/product-spotlight.png
|
|
49
|
+
prompt: |
|
|
50
|
+
Use headless component @jay-framework/wix-stores / contract product-spotlight.
|
|
51
|
+
Read agent-kit/materialized-contracts/wix-stores/product-spotlight.jay-contract.
|
|
52
|
+
Script key: spotlight
|
|
53
|
+
Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md.
|
|
54
|
+
Pass slug as a prop to specify which product to display.
|
|
41
55
|
|
|
42
56
|
- id: wix-stores:category-list
|
|
43
57
|
title: Category list
|
|
@@ -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>,
|
|
@@ -865,36 +882,92 @@ interface ProductFastCarryForward {
|
|
|
865
882
|
*/
|
|
866
883
|
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
884
|
|
|
868
|
-
interface
|
|
885
|
+
interface CategoryProductsViewState {
|
|
869
886
|
products: Array<ProductCardViewState>,
|
|
870
887
|
hasProducts: boolean,
|
|
871
888
|
categoryName: string
|
|
872
889
|
}
|
|
873
890
|
|
|
874
|
-
type
|
|
891
|
+
type CategoryProductsSlowViewState = Pick<CategoryProductsViewState, 'categoryName'>;
|
|
875
892
|
|
|
876
|
-
type
|
|
877
|
-
products: Array<
|
|
893
|
+
type CategoryProductsFastViewState = Pick<CategoryProductsViewState, 'hasProducts'> & {
|
|
894
|
+
products: Array<CategoryProductsViewState['products'][number]>;
|
|
878
895
|
};
|
|
879
896
|
|
|
880
|
-
type
|
|
881
|
-
products: Array<
|
|
897
|
+
type CategoryProductsInteractiveViewState = Pick<CategoryProductsViewState, 'hasProducts'> & {
|
|
898
|
+
products: Array<CategoryProductsViewState['products'][number]>;
|
|
882
899
|
};
|
|
883
900
|
|
|
884
901
|
|
|
885
|
-
interface
|
|
902
|
+
interface CategoryProductsRefs {
|
|
886
903
|
products: ProductCardRepeatedRefs
|
|
887
904
|
}
|
|
888
905
|
|
|
889
|
-
interface
|
|
890
|
-
productId
|
|
906
|
+
interface CategoryProductsProps {
|
|
907
|
+
productId?: string;
|
|
891
908
|
categorySlug?: string;
|
|
892
909
|
limit?: number;
|
|
893
910
|
}
|
|
894
|
-
interface
|
|
911
|
+
interface SlowCarryForward {
|
|
895
912
|
products: ProductCardViewState[];
|
|
896
913
|
}
|
|
897
|
-
declare const
|
|
914
|
+
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>>;
|
|
915
|
+
|
|
916
|
+
interface ProductSpotlightViewState {
|
|
917
|
+
product: ProductCardViewState,
|
|
918
|
+
hasProduct: boolean
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
type ProductSpotlightSlowViewState = Pick<ProductSpotlightViewState, 'hasProduct'> & {
|
|
922
|
+
product: Pick<ProductSpotlightViewState['product'], '_id' | 'name' | 'slug' | 'productUrl' | 'categoryPrefix' | 'hasDiscount' | 'hasRibbon' | 'productType' | 'quickAddType'> & {
|
|
923
|
+
mainMedia: ProductSpotlightViewState['product']['mainMedia'];
|
|
924
|
+
thumbnail: ProductSpotlightViewState['product']['thumbnail'];
|
|
925
|
+
inventory: ProductSpotlightViewState['product']['inventory'];
|
|
926
|
+
ribbon: ProductSpotlightViewState['product']['ribbon'];
|
|
927
|
+
brand: ProductSpotlightViewState['product']['brand'];
|
|
928
|
+
quickOption: Pick<ProductSpotlightViewState['product']['quickOption'], '_id' | 'name' | 'optionRenderType'> & {
|
|
929
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
|
|
930
|
+
};
|
|
931
|
+
secondQuickOption: Pick<ProductSpotlightViewState['product']['secondQuickOption'], '_id' | 'name' | 'optionRenderType'> & {
|
|
932
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
|
|
933
|
+
};
|
|
934
|
+
};
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
type ProductSpotlightFastViewState = {
|
|
938
|
+
product: Pick<ProductSpotlightViewState['product'], 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
|
|
939
|
+
quickOption: {
|
|
940
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
941
|
+
};
|
|
942
|
+
secondQuickOption: {
|
|
943
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
944
|
+
};
|
|
945
|
+
};
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
type ProductSpotlightInteractiveViewState = {
|
|
949
|
+
product: Pick<ProductSpotlightViewState['product'], 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
|
|
950
|
+
quickOption: {
|
|
951
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
952
|
+
};
|
|
953
|
+
secondQuickOption: {
|
|
954
|
+
choices: Array<Pick<ProductSpotlightViewState['product']['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
|
|
955
|
+
};
|
|
956
|
+
};
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
interface ProductSpotlightRefs {
|
|
961
|
+
product: ProductCardRefs
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
interface ProductSpotlightProps {
|
|
965
|
+
slug: string;
|
|
966
|
+
}
|
|
967
|
+
interface SpotlightCarryForward {
|
|
968
|
+
product: ProductCardViewState;
|
|
969
|
+
}
|
|
970
|
+
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
971
|
|
|
899
972
|
interface CategoryOfCategoryListViewState {
|
|
900
973
|
_id: string,
|
|
@@ -1065,4 +1138,4 @@ declare function generateWixStoresReferences(ctx: PluginReferencesContext): Prom
|
|
|
1065
1138
|
*/
|
|
1066
1139
|
declare const generator: _jay_framework_fullstack_component.DynamicContractGenerator<[WixStoresService]>;
|
|
1067
1140
|
|
|
1068
|
-
export { type CategoryListParams, type CategoryTree, type GetProductBySlugInput, type ProductPageParams, type ProductSearchParams, type
|
|
1141
|
+
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
|
@@ -716,6 +716,7 @@ const getProductBySlug = makeJayQuery("wixStores.getProductBySlug").withServices
|
|
|
716
716
|
const fields = [
|
|
717
717
|
"MEDIA_ITEMS_INFO",
|
|
718
718
|
"VARIANT_OPTION_CHOICE_NAMES",
|
|
719
|
+
"CURRENCY",
|
|
719
720
|
...needsCategoryInfo(wixStores) ? ["ALL_CATEGORIES_INFO"] : []
|
|
720
721
|
];
|
|
721
722
|
const result = await wixStores.products.getProductBySlug(slug, {
|
|
@@ -955,7 +956,7 @@ async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplat
|
|
|
955
956
|
}
|
|
956
957
|
return header;
|
|
957
958
|
}
|
|
958
|
-
async function renderSlowlyChanging$
|
|
959
|
+
async function renderSlowlyChanging$4(props, wixStores) {
|
|
959
960
|
const Pipeline = RenderPipeline.for();
|
|
960
961
|
const categorySlug = props.category ?? null;
|
|
961
962
|
const prefixSlug = props.prefix ?? null;
|
|
@@ -1028,7 +1029,7 @@ async function renderSlowlyChanging$3(props, wixStores) {
|
|
|
1028
1029
|
};
|
|
1029
1030
|
});
|
|
1030
1031
|
}
|
|
1031
|
-
async function renderFastChanging$
|
|
1032
|
+
async function renderFastChanging$3(props, slowCarryForward, _wixStores) {
|
|
1032
1033
|
const Pipeline = RenderPipeline.for();
|
|
1033
1034
|
const urlFilters = parseUrlFilters(props.url);
|
|
1034
1035
|
const initialSort = parseSortParam(urlFilters.sort);
|
|
@@ -1215,7 +1216,7 @@ async function* loadSearchParams([wixStores]) {
|
|
|
1215
1216
|
yield [];
|
|
1216
1217
|
}
|
|
1217
1218
|
}
|
|
1218
|
-
const productSearch = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadSearchParams).withSlowlyRender(renderSlowlyChanging$
|
|
1219
|
+
const productSearch = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadSearchParams).withSlowlyRender(renderSlowlyChanging$4).withFastRender(renderFastChanging$3);
|
|
1219
1220
|
var ProductType = /* @__PURE__ */ ((ProductType2) => {
|
|
1220
1221
|
ProductType2[ProductType2["PHYSICAL"] = 0] = "PHYSICAL";
|
|
1221
1222
|
ProductType2[ProductType2["DIGITAL"] = 1] = "DIGITAL";
|
|
@@ -1449,7 +1450,7 @@ function mapVariants(variantsInfo) {
|
|
|
1449
1450
|
strikethroughPrice: variant.price.compareAtPrice?.formattedAmount || ""
|
|
1450
1451
|
})) || [];
|
|
1451
1452
|
}
|
|
1452
|
-
async function renderSlowlyChanging$
|
|
1453
|
+
async function renderSlowlyChanging$3(props, wixStores) {
|
|
1453
1454
|
const Pipeline = RenderPipeline.for();
|
|
1454
1455
|
const template = wixStores.urls.product;
|
|
1455
1456
|
const needsCategories = template.includes("{category}") || template.includes("{prefix}");
|
|
@@ -1505,7 +1506,7 @@ async function renderSlowlyChanging$2(props, wixStores) {
|
|
|
1505
1506
|
};
|
|
1506
1507
|
});
|
|
1507
1508
|
}
|
|
1508
|
-
async function renderFastChanging$
|
|
1509
|
+
async function renderFastChanging$2(props, slowCarryForward, wixStores) {
|
|
1509
1510
|
const Pipeline = RenderPipeline.for();
|
|
1510
1511
|
const { variants } = slowCarryForward;
|
|
1511
1512
|
const defaultVariant = variants.find((v) => v.inventoryStatus === StockStatus.IN_STOCK) || variants[0];
|
|
@@ -1555,9 +1556,9 @@ async function renderFastChanging$1(props, slowCarryForward, wixStores) {
|
|
|
1555
1556
|
}
|
|
1556
1557
|
}));
|
|
1557
1558
|
}
|
|
1558
|
-
const productPage = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadProductParams).withSlowlyRender(renderSlowlyChanging$
|
|
1559
|
+
const productPage = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadProductParams).withSlowlyRender(renderSlowlyChanging$3).withFastRender(renderFastChanging$2);
|
|
1559
1560
|
const DEFAULT_LIMIT = 4;
|
|
1560
|
-
async function renderSlowlyChanging$
|
|
1561
|
+
async function renderSlowlyChanging$2(props, wixStores) {
|
|
1561
1562
|
const Pipeline = RenderPipeline.for();
|
|
1562
1563
|
const limit = props.limit ?? DEFAULT_LIMIT;
|
|
1563
1564
|
const categorySlug = props.categorySlug;
|
|
@@ -1601,7 +1602,7 @@ async function renderSlowlyChanging$1(props, wixStores) {
|
|
|
1601
1602
|
carryForward: { products }
|
|
1602
1603
|
}));
|
|
1603
1604
|
}
|
|
1604
|
-
async function renderFastChanging(_props, slowCarryForward, _wixStores) {
|
|
1605
|
+
async function renderFastChanging$1(_props, slowCarryForward, _wixStores) {
|
|
1605
1606
|
const Pipeline = RenderPipeline.for();
|
|
1606
1607
|
const { products } = slowCarryForward;
|
|
1607
1608
|
return Pipeline.ok({
|
|
@@ -1609,7 +1610,95 @@ async function renderFastChanging(_props, slowCarryForward, _wixStores) {
|
|
|
1609
1610
|
hasProducts: products.length > 0
|
|
1610
1611
|
}).toPhaseOutput((viewState) => ({ viewState, carryForward: {} }));
|
|
1611
1612
|
}
|
|
1612
|
-
const
|
|
1613
|
+
const categoryProducts = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging$2).withFastRender(renderFastChanging$1);
|
|
1614
|
+
async function renderSlowlyChanging$1(props, _wixStores) {
|
|
1615
|
+
const Pipeline = RenderPipeline.for();
|
|
1616
|
+
return Pipeline.try(async () => {
|
|
1617
|
+
if (!props.slug) {
|
|
1618
|
+
throw new Error("No product slug provided");
|
|
1619
|
+
}
|
|
1620
|
+
const card = await getProductBySlug({ slug: props.slug });
|
|
1621
|
+
if (!card) {
|
|
1622
|
+
throw new Error(`Product not found: ${props.slug}`);
|
|
1623
|
+
}
|
|
1624
|
+
return card;
|
|
1625
|
+
}).recover((error) => {
|
|
1626
|
+
return handleError(error);
|
|
1627
|
+
}).toPhaseOutput((product) => {
|
|
1628
|
+
return {
|
|
1629
|
+
viewState: {
|
|
1630
|
+
hasProduct: true,
|
|
1631
|
+
product: {
|
|
1632
|
+
_id: product._id,
|
|
1633
|
+
name: product.name,
|
|
1634
|
+
slug: product.slug,
|
|
1635
|
+
productUrl: product.productUrl,
|
|
1636
|
+
categoryPrefix: product.categoryPrefix,
|
|
1637
|
+
mainMedia: product.mainMedia,
|
|
1638
|
+
thumbnail: product.thumbnail,
|
|
1639
|
+
hasDiscount: product.hasDiscount,
|
|
1640
|
+
inventory: product.inventory,
|
|
1641
|
+
ribbon: product.ribbon,
|
|
1642
|
+
hasRibbon: product.hasRibbon,
|
|
1643
|
+
brand: product.brand,
|
|
1644
|
+
productType: product.productType,
|
|
1645
|
+
quickAddType: product.quickAddType,
|
|
1646
|
+
quickOption: {
|
|
1647
|
+
_id: product.quickOption?._id,
|
|
1648
|
+
name: product.quickOption?.name,
|
|
1649
|
+
optionRenderType: product.quickOption?.optionRenderType,
|
|
1650
|
+
choices: (product.quickOption?.choices ?? []).map((c) => ({
|
|
1651
|
+
choiceId: c.choiceId,
|
|
1652
|
+
name: c.name,
|
|
1653
|
+
choiceType: c.choiceType,
|
|
1654
|
+
colorCode: c.colorCode
|
|
1655
|
+
}))
|
|
1656
|
+
},
|
|
1657
|
+
secondQuickOption: {
|
|
1658
|
+
_id: product.secondQuickOption?._id,
|
|
1659
|
+
name: product.secondQuickOption?.name,
|
|
1660
|
+
optionRenderType: product.secondQuickOption?.optionRenderType,
|
|
1661
|
+
choices: (product.secondQuickOption?.choices ?? []).map((c) => ({
|
|
1662
|
+
choiceId: c.choiceId,
|
|
1663
|
+
name: c.name,
|
|
1664
|
+
choiceType: c.choiceType,
|
|
1665
|
+
colorCode: c.colorCode
|
|
1666
|
+
}))
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
},
|
|
1670
|
+
carryForward: { product }
|
|
1671
|
+
};
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
async function renderFastChanging(_props, carryForward, _wixStores) {
|
|
1675
|
+
const Pipeline = RenderPipeline.for();
|
|
1676
|
+
const { product } = carryForward;
|
|
1677
|
+
return Pipeline.ok({
|
|
1678
|
+
product: {
|
|
1679
|
+
price: product.price,
|
|
1680
|
+
strikethroughPrice: product.strikethroughPrice,
|
|
1681
|
+
isAddingToCart: false,
|
|
1682
|
+
quickOption: {
|
|
1683
|
+
choices: (product.quickOption?.choices ?? []).map((c) => ({
|
|
1684
|
+
choiceId: c.choiceId,
|
|
1685
|
+
inStock: c.inStock,
|
|
1686
|
+
isSelected: c.isSelected
|
|
1687
|
+
}))
|
|
1688
|
+
},
|
|
1689
|
+
secondQuickOption: {
|
|
1690
|
+
choices: (product.secondQuickOption?.choices ?? []).map((c) => ({
|
|
1691
|
+
choiceId: c.choiceId,
|
|
1692
|
+
inStock: c.inStock,
|
|
1693
|
+
isSelected: c.isSelected
|
|
1694
|
+
}))
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
}).toPhaseOutput((viewState) => {
|
|
1698
|
+
return { viewState, carryForward: { product } };
|
|
1699
|
+
});
|
|
1700
|
+
}
|
|
1701
|
+
const productSpotlight = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withSlowlyRender(renderSlowlyChanging$1).withFastRender(renderFastChanging);
|
|
1613
1702
|
async function findCategoryBySlug(categoriesClient, slug) {
|
|
1614
1703
|
const result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("slug", slug).eq("visible", true).limit(1).find();
|
|
1615
1704
|
return result.items?.[0] ?? null;
|
|
@@ -1807,12 +1896,12 @@ function buildCategoryPrompt(config, entry) {
|
|
|
1807
1896
|
);
|
|
1808
1897
|
}
|
|
1809
1898
|
lines.push(
|
|
1810
|
-
`
|
|
1899
|
+
` category-products — pass categorySlug="${node.slug}" to show products from this category; optionally pass productId to exclude a product`,
|
|
1811
1900
|
"",
|
|
1812
1901
|
"Contracts:",
|
|
1813
1902
|
" agent-kit/materialized-contracts/wix-stores/product-search.jay-contract",
|
|
1814
1903
|
" agent-kit/materialized-contracts/wix-stores/category-list.jay-contract",
|
|
1815
|
-
" agent-kit/materialized-contracts/wix-stores/
|
|
1904
|
+
" agent-kit/materialized-contracts/wix-stores/category-products.jay-contract",
|
|
1816
1905
|
"",
|
|
1817
1906
|
"Bind ViewState and refs per agent-kit/designer/INSTRUCTIONS.md."
|
|
1818
1907
|
);
|
|
@@ -2276,6 +2365,7 @@ export {
|
|
|
2276
2365
|
cartIndicator,
|
|
2277
2366
|
cartPage,
|
|
2278
2367
|
categoryList,
|
|
2368
|
+
categoryProducts,
|
|
2279
2369
|
findCategoryImage,
|
|
2280
2370
|
findRootCategoryId,
|
|
2281
2371
|
findRootCategorySlug,
|
|
@@ -2287,10 +2377,10 @@ export {
|
|
|
2287
2377
|
productPage,
|
|
2288
2378
|
generator as productPageContractGenerator,
|
|
2289
2379
|
productSearch,
|
|
2380
|
+
productSpotlight,
|
|
2290
2381
|
provideWixCartContext,
|
|
2291
2382
|
provideWixCartService,
|
|
2292
2383
|
provideWixStoresService,
|
|
2293
|
-
relatedProducts,
|
|
2294
2384
|
searchProducts,
|
|
2295
2385
|
setupWixStores
|
|
2296
2386
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/wix-stores",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.7",
|
|
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",
|
|
@@ -38,16 +39,16 @@
|
|
|
38
39
|
"test": "vitest run"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@jay-framework/component": "^0.19.
|
|
42
|
-
"@jay-framework/fullstack-component": "^0.19.
|
|
43
|
-
"@jay-framework/reactive": "^0.19.
|
|
44
|
-
"@jay-framework/runtime": "^0.19.
|
|
45
|
-
"@jay-framework/secure": "^0.19.
|
|
46
|
-
"@jay-framework/stack-client-runtime": "^0.19.
|
|
47
|
-
"@jay-framework/stack-server-runtime": "^0.19.
|
|
48
|
-
"@jay-framework/wix-cart": "^0.19.
|
|
49
|
-
"@jay-framework/wix-server-client": "^0.19.
|
|
50
|
-
"@jay-framework/wix-utils": "^0.19.
|
|
42
|
+
"@jay-framework/component": "^0.19.7",
|
|
43
|
+
"@jay-framework/fullstack-component": "^0.19.7",
|
|
44
|
+
"@jay-framework/reactive": "^0.19.7",
|
|
45
|
+
"@jay-framework/runtime": "^0.19.7",
|
|
46
|
+
"@jay-framework/secure": "^0.19.7",
|
|
47
|
+
"@jay-framework/stack-client-runtime": "^0.19.7",
|
|
48
|
+
"@jay-framework/stack-server-runtime": "^0.19.7",
|
|
49
|
+
"@jay-framework/wix-cart": "^0.19.7",
|
|
50
|
+
"@jay-framework/wix-server-client": "^0.19.7",
|
|
51
|
+
"@jay-framework/wix-utils": "^0.19.7",
|
|
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.19.
|
|
63
|
-
"@jay-framework/jay-cli": "^0.19.
|
|
64
|
-
"@jay-framework/jay-stack-cli": "^0.19.
|
|
65
|
-
"@jay-framework/vite-plugin": "^0.19.
|
|
63
|
+
"@jay-framework/compiler-jay-stack": "^0.19.7",
|
|
64
|
+
"@jay-framework/jay-cli": "^0.19.7",
|
|
65
|
+
"@jay-framework/jay-stack-cli": "^0.19.7",
|
|
66
|
+
"@jay-framework/vite-plugin": "^0.19.7",
|
|
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>
|