@jay-framework/wix-stores 0.15.5 → 0.16.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.
@@ -1,4 +1,9 @@
1
1
  name: category-list
2
+ description: Displays a list of store categories. Use for category navigation grids and menus.
3
+ props:
4
+ - name: parentCategory
5
+ type: string
6
+ description: Parent category slug. When set, only direct children of this category are shown. Falls back to defaultCategory from config.
2
7
  tags:
3
8
  # List of visible categories
4
9
  - tag: categories
@@ -37,4 +37,8 @@ export interface CategoryListRepeatedRefs {
37
37
  }
38
38
  }
39
39
 
40
- export type CategoryListContract = JayContract<CategoryListViewState, CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState>
40
+ export interface CategoryListProps {
41
+ parentCategory?: string;
42
+ }
43
+
44
+ export type CategoryListContract = JayContract<CategoryListViewState, CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, CategoryListProps>
@@ -1,4 +1,5 @@
1
1
  name: mediaGallery
2
+ description: Image and video gallery with thumbnail navigation. Used as a sub-contract in product pages.
2
3
  tags:
3
4
  - tag: selectedMedia
4
5
  type: sub-contract
@@ -1,4 +1,5 @@
1
1
  name: media
2
+ description: Single media item with URL, type, and thumbnail. Used as a sub-contract in media galleries.
2
3
  tags:
3
4
  - {tag: url, type: data, dataType: string, description: Media Url}
4
5
  - {tag: mediaType, type: variant, dataType: "enum (IMAGE | VIDEO)", description: Media type}
@@ -1,4 +1,5 @@
1
1
  name: product-card
2
+ description: Single product card with image, price, and quick-add options. Used as a sub-contract in product grids and search results.
2
3
  tags:
3
4
  # Product basic info (from Wix Stores Product API)
4
5
  - tag: _id
@@ -1,4 +1,8 @@
1
1
  name: product-page
2
+ description: Full product detail page with variants, options, media gallery, and add-to-cart. Use for individual product pages.
3
+ params:
4
+ slug: string
5
+ category: string?
2
6
  tags:
3
7
  - {tag: _id, type: data, dataType: string, description: Product GUID}
4
8
  - {tag: productName, type: data, dataType: string, required: true, description: Product name}
@@ -31,6 +35,7 @@ tags:
31
35
  - {tag: addToCartButton, type: interactive, elementType: HTMLButtonElement, required: true, description: Add product to cart button}
32
36
  - {tag: buyNowButton, type: interactive, elementType: HTMLButtonElement, required: true, description: Buy now button}
33
37
  - {tag: actionsEnabled, type: variant, dataType: boolean, phase: fast+interactive, description: should the add to cart and buy now buttons be enabled}
38
+ - {tag: isAddingToCart, type: variant, dataType: boolean, phase: fast+interactive, description: Whether an add-to-cart request is currently in progress}
34
39
 
35
40
  - tag: options
36
41
  type: sub-contract
@@ -97,55 +102,4 @@ tags:
97
102
  - {tag: isSelected, type: variant, dataType: boolean, phase: fast+interactive, description: Whether this choice is currently selected (UI state)}
98
103
  - {tag: choiceButton, type: interactive, elementType: HTMLButtonElement, description: Button to select this choice}
99
104
 
100
- - tag: seoData
101
- type: sub-contract
102
- description: Product SEO data.
103
- tags:
104
- - tag: tags
105
- type: sub-contract
106
- repeated: true
107
- trackBy: position
108
- description: SEO tag information.
109
- tags:
110
- - {tag: position, type: data, dataType: string, description: the number of the tag, as two digit string.}
111
- - {tag: type, type: data, dataType: string, description: SEO tag type.}
112
- - tag: props
113
- type: sub-contract
114
- repeated: true
115
- trackBy: key
116
- description: A Key Value pair of SEO properties.
117
- tags:
118
- - tag: key
119
- type: data
120
- dataType: string
121
- - tag: value
122
- type: data
123
- dataType: string
124
- - tag: meta
125
- type: sub-contract
126
- repeated: true
127
- trackBy: key
128
- description: SEO tag metadata
129
- tags:
130
- - tag: key
131
- type: data
132
- dataType: string
133
- - tag: value
134
- type: data
135
- dataType: string
136
- - {tag: children, type: data, dataType: string, description: SEO tag inner content.}
137
-
138
- - tag: settings
139
- type: sub-contract
140
- description: SEO general settings.
141
- tags:
142
- - {tag: preventAutoRedirect, type: data, dataType: boolean, description: Whether the automatical redirect visits from the old URL to the new one is enabled.}
143
- - tag: keywords
144
- type: sub-contract
145
- repeated: true
146
- trackBy: term
147
- description: User-selected keyword terms for a specific page.
148
- tags:
149
- - {tag: term, type: data, dataType: string, description: Keyword value.}
150
- - {tag: isMain, type: data, dataType: boolean, description: Whether the keyword is the main focus keyword.}
151
- - {tag: origin, type: data, dataType: string, description: The source that added the keyword terms to the SEO settings. }
105
+ # SEO data is injected into <head> via headTags (Design Log #127), not part of the contract view state.
@@ -77,40 +77,6 @@ export interface ModifierOfProductPageViewState {
77
77
  choices: Array<ChoiceOfModifierOfProductPageViewState>
78
78
  }
79
79
 
80
- export interface PropOfTagOfSeoDatumOfProductPageViewState {
81
- key: string,
82
- value: string
83
- }
84
-
85
- export interface MetaOfTagOfSeoDatumOfProductPageViewState {
86
- key: string,
87
- value: string
88
- }
89
-
90
- export interface TagOfSeoDatumOfProductPageViewState {
91
- position: string,
92
- type: string,
93
- props: Array<PropOfTagOfSeoDatumOfProductPageViewState>,
94
- meta: Array<MetaOfTagOfSeoDatumOfProductPageViewState>,
95
- children: string
96
- }
97
-
98
- export interface KeywordOfSettingOfSeoDatumOfProductPageViewState {
99
- term: string,
100
- isMain: boolean,
101
- origin: string
102
- }
103
-
104
- export interface SettingOfSeoDatumOfProductPageViewState {
105
- preventAutoRedirect: boolean,
106
- keywords: Array<KeywordOfSettingOfSeoDatumOfProductPageViewState>
107
- }
108
-
109
- export interface SeoDatumOfProductPageViewState {
110
- tags: Array<TagOfSeoDatumOfProductPageViewState>,
111
- settings: SettingOfSeoDatumOfProductPageViewState
112
- }
113
-
114
80
  export interface ProductPageViewState {
115
81
  _id: string,
116
82
  productName: string,
@@ -126,10 +92,10 @@ export interface ProductPageViewState {
126
92
  stockStatus: StockStatus,
127
93
  quantity: QuantityOfProductPageViewState,
128
94
  actionsEnabled: boolean,
95
+ isAddingToCart: boolean,
129
96
  options: Array<OptionOfProductPageViewState>,
130
97
  infoSections: Array<InfoSectionOfProductPageViewState>,
131
- modifiers: Array<ModifierOfProductPageViewState>,
132
- seoData: SeoDatumOfProductPageViewState
98
+ modifiers: Array<ModifierOfProductPageViewState>
133
99
  }
134
100
 
135
101
  export type ProductPageSlowViewState = Pick<ProductPageViewState, '_id' | 'productName' | 'description' | 'brand' | 'ribbon' | 'productType'> & {
@@ -140,10 +106,9 @@ export type ProductPageSlowViewState = Pick<ProductPageViewState, '_id' | 'produ
140
106
  modifiers: Array<Pick<ProductPageViewState['modifiers'][number], '_id' | 'name' | 'modifierType' | 'textInputLength' | 'textInputRequired'> & {
141
107
  choices: Array<Pick<ProductPageViewState['modifiers'][number]['choices'][number], 'choiceId' | 'choiceType' | 'name' | 'colorCode'>>;
142
108
  }>;
143
- seoData: ProductPageViewState['seoData'];
144
109
  };
145
110
 
146
- export type ProductPageFastViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled'> & {
111
+ export type ProductPageFastViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled' | 'isAddingToCart'> & {
147
112
  mediaGallery: ProductPageViewState['mediaGallery'];
148
113
  quantity: ProductPageViewState['quantity'];
149
114
  options: Array<Pick<ProductPageViewState['options'][number], '_id' | 'textChoiceSelection'> & {
@@ -154,7 +119,7 @@ export type ProductPageFastViewState = Pick<ProductPageViewState, 'sku' | 'price
154
119
  }>;
155
120
  };
156
121
 
157
- export type ProductPageInteractiveViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled'> & {
122
+ export type ProductPageInteractiveViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled' | 'isAddingToCart'> & {
158
123
  mediaGallery: ProductPageViewState['mediaGallery'];
159
124
  quantity: ProductPageViewState['quantity'];
160
125
  options: Array<Pick<ProductPageViewState['options'][number], '_id' | 'textChoiceSelection'> & {
@@ -215,4 +180,11 @@ export interface ProductPageRepeatedRefs {
215
180
  }
216
181
  }
217
182
 
183
+ import { UrlParams } from '@jay-framework/fullstack-component';
184
+
185
+ export interface ProductPageParams extends UrlParams {
186
+ slug: string;
187
+ category?: string;
188
+ }
189
+
218
190
  export type ProductPageContract = JayContract<ProductPageViewState, ProductPageRefs, ProductPageSlowViewState, ProductPageFastViewState, ProductPageInteractiveViewState>
@@ -1,4 +1,15 @@
1
1
  name: product-search
2
+ description: Product listing with filters, sorting, and pagination. Use for search results and category pages.
3
+ props:
4
+ - name: category
5
+ type: string
6
+ description: Top-level category slug. Scopes search to this category.
7
+ - name: subcategory
8
+ type: string
9
+ description: Sub-category slug. Further scopes within the category.
10
+ params:
11
+ category: string?
12
+ subcategory: string?
2
13
  tags:
3
14
  # Search input (matches Wix searchProducts search.search parameter)
4
15
  - tag: searchExpression
@@ -254,4 +254,16 @@ export interface ProductSearchRepeatedRefs {
254
254
  }
255
255
  }
256
256
 
257
- export type ProductSearchContract = JayContract<ProductSearchViewState, ProductSearchRefs, ProductSearchSlowViewState, ProductSearchFastViewState, ProductSearchInteractiveViewState>
257
+ export interface ProductSearchProps {
258
+ category?: string;
259
+ subcategory?: string;
260
+ }
261
+
262
+ import { UrlParams } from '@jay-framework/fullstack-component';
263
+
264
+ export interface ProductSearchParams extends UrlParams {
265
+ category?: string;
266
+ subcategory?: string;
267
+ }
268
+
269
+ export type ProductSearchContract = JayContract<ProductSearchViewState, ProductSearchRefs, ProductSearchSlowViewState, ProductSearchFastViewState, ProductSearchInteractiveViewState, ProductSearchProps>
@@ -301,6 +301,7 @@ function ProductPageInteractive(props, refs, viewStateSignals, fastCarryForward,
301
301
  quantity: quantity()
302
302
  },
303
303
  actionsEnabled: computedActionsEnabled,
304
+ isAddingToCart,
304
305
  options,
305
306
  modifiers,
306
307
  mediaGallery: interactiveMedia,
package/dist/index.d.ts CHANGED
@@ -560,10 +560,6 @@ interface ProductSearchParams extends UrlParams {
560
560
  /** Sub-category slug (e.g., 'shirts'). Further scopes within the category. */
561
561
  subcategory?: string;
562
562
  }
563
- /**
564
- * Search sort options
565
- */
566
- type SearchSortOption = 'relevance' | 'priceAsc' | 'priceDesc' | 'newest' | 'nameAsc' | 'nameDesc';
567
563
  /**
568
564
  * Category info carried forward from slow to fast phase
569
565
  */
@@ -710,40 +706,6 @@ interface ModifierOfProductPageViewState {
710
706
  choices: Array<ChoiceOfModifierOfProductPageViewState>
711
707
  }
712
708
 
713
- interface PropOfTagOfSeoDatumOfProductPageViewState {
714
- key: string,
715
- value: string
716
- }
717
-
718
- interface MetaOfTagOfSeoDatumOfProductPageViewState {
719
- key: string,
720
- value: string
721
- }
722
-
723
- interface TagOfSeoDatumOfProductPageViewState {
724
- position: string,
725
- type: string,
726
- props: Array<PropOfTagOfSeoDatumOfProductPageViewState>,
727
- meta: Array<MetaOfTagOfSeoDatumOfProductPageViewState>,
728
- children: string
729
- }
730
-
731
- interface KeywordOfSettingOfSeoDatumOfProductPageViewState {
732
- term: string,
733
- isMain: boolean,
734
- origin: string
735
- }
736
-
737
- interface SettingOfSeoDatumOfProductPageViewState {
738
- preventAutoRedirect: boolean,
739
- keywords: Array<KeywordOfSettingOfSeoDatumOfProductPageViewState>
740
- }
741
-
742
- interface SeoDatumOfProductPageViewState {
743
- tags: Array<TagOfSeoDatumOfProductPageViewState>,
744
- settings: SettingOfSeoDatumOfProductPageViewState
745
- }
746
-
747
709
  interface ProductPageViewState {
748
710
  _id: string,
749
711
  productName: string,
@@ -759,10 +721,10 @@ interface ProductPageViewState {
759
721
  stockStatus: StockStatus,
760
722
  quantity: QuantityOfProductPageViewState,
761
723
  actionsEnabled: boolean,
724
+ isAddingToCart: boolean,
762
725
  options: Array<OptionOfProductPageViewState>,
763
726
  infoSections: Array<InfoSectionOfProductPageViewState>,
764
- modifiers: Array<ModifierOfProductPageViewState>,
765
- seoData: SeoDatumOfProductPageViewState
727
+ modifiers: Array<ModifierOfProductPageViewState>
766
728
  }
767
729
 
768
730
  type ProductPageSlowViewState = Pick<ProductPageViewState, '_id' | 'productName' | 'description' | 'brand' | 'ribbon' | 'productType'> & {
@@ -773,10 +735,9 @@ type ProductPageSlowViewState = Pick<ProductPageViewState, '_id' | 'productName'
773
735
  modifiers: Array<Pick<ProductPageViewState['modifiers'][number], '_id' | 'name' | 'modifierType' | 'textInputLength' | 'textInputRequired'> & {
774
736
  choices: Array<Pick<ProductPageViewState['modifiers'][number]['choices'][number], 'choiceId' | 'choiceType' | 'name' | 'colorCode'>>;
775
737
  }>;
776
- seoData: ProductPageViewState['seoData'];
777
738
  };
778
739
 
779
- type ProductPageFastViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled'> & {
740
+ type ProductPageFastViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled' | 'isAddingToCart'> & {
780
741
  mediaGallery: ProductPageViewState['mediaGallery'];
781
742
  quantity: ProductPageViewState['quantity'];
782
743
  options: Array<Pick<ProductPageViewState['options'][number], '_id' | 'textChoiceSelection'> & {
@@ -787,7 +748,7 @@ type ProductPageFastViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'st
787
748
  }>;
788
749
  };
789
750
 
790
- type ProductPageInteractiveViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled'> & {
751
+ type ProductPageInteractiveViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled' | 'isAddingToCart'> & {
791
752
  mediaGallery: ProductPageViewState['mediaGallery'];
792
753
  quantity: ProductPageViewState['quantity'];
793
754
  options: Array<Pick<ProductPageViewState['options'][number], '_id' | 'textChoiceSelection'> & {
@@ -904,6 +865,14 @@ interface CategoryListRefs {
904
865
  }
905
866
  }
906
867
 
868
+ /**
869
+ * URL parameters for category list.
870
+ * Supports optional parentCategory to scope the list to direct children.
871
+ */
872
+ interface CategoryListParams extends UrlParams {
873
+ /** Parent category slug. When set, only direct children of this category are shown. */
874
+ parentCategory?: string;
875
+ }
907
876
  /**
908
877
  * Category List Full-Stack Component
909
878
  *
@@ -929,15 +898,15 @@ interface CategoryListRefs {
929
898
  * </div>
930
899
  * ```
931
900
  */
932
- declare const categoryList: _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [], PageProps, {}, _jay_framework_component.JayComponentCore<PageProps, CategoryListInteractiveViewState>> & {
933
- withFastRender<NewCarryForward extends object>(fastRender: _jay_framework_fullstack_component.RenderFast<[Record<string, never>, WixStoresService], PageProps, CategoryListFastViewState, NewCarryForward>): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], PageProps, {}, _jay_framework_component.JayComponentCore<PageProps, CategoryListInteractiveViewState>> & {
934
- withClientDefaults(fn: (props: PageProps) => {
901
+ declare const categoryList: _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [], PageProps & CategoryListParams, {}, _jay_framework_component.JayComponentCore<PageProps & CategoryListParams, CategoryListInteractiveViewState>> & {
902
+ withFastRender<NewCarryForward extends object>(fastRender: _jay_framework_fullstack_component.RenderFast<[Record<string, never>, WixStoresService], PageProps & CategoryListParams, CategoryListFastViewState, NewCarryForward>): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], PageProps & CategoryListParams, {}, _jay_framework_component.JayComponentCore<PageProps & CategoryListParams, CategoryListInteractiveViewState>> & {
903
+ withClientDefaults(fn: (props: PageProps & CategoryListParams) => {
935
904
  viewState: CategoryListFastViewState;
936
905
  carryForward?: any;
937
- }): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], PageProps, {}, _jay_framework_component.JayComponentCore<PageProps, CategoryListInteractiveViewState>> & /*elided*/ any;
938
- withInteractive(comp: _jay_framework_component.ComponentConstructor<PageProps, CategoryListRefs, CategoryListInteractiveViewState, [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], _jay_framework_component.JayComponentCore<PageProps, CategoryListInteractiveViewState>>): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], PageProps, {}, _jay_framework_component.JayComponentCore<PageProps, CategoryListInteractiveViewState>>;
906
+ }): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], PageProps & CategoryListParams, {}, _jay_framework_component.JayComponentCore<PageProps & CategoryListParams, CategoryListInteractiveViewState>> & /*elided*/ any;
907
+ withInteractive(comp: _jay_framework_component.ComponentConstructor<PageProps & CategoryListParams, CategoryListRefs, CategoryListInteractiveViewState, [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], _jay_framework_component.JayComponentCore<PageProps & CategoryListParams, CategoryListInteractiveViewState>>): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [_jay_framework_fullstack_component.Signals<CategoryListFastViewState>, NewCarryForward], PageProps & CategoryListParams, {}, _jay_framework_component.JayComponentCore<PageProps & CategoryListParams, CategoryListInteractiveViewState>>;
939
908
  };
940
- withInteractive(comp: _jay_framework_component.ComponentConstructor<PageProps, CategoryListRefs, CategoryListInteractiveViewState, [], _jay_framework_component.JayComponentCore<PageProps, CategoryListInteractiveViewState>>): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [], PageProps, {}, _jay_framework_component.JayComponentCore<PageProps, CategoryListInteractiveViewState>>;
909
+ withInteractive(comp: _jay_framework_component.ComponentConstructor<PageProps & CategoryListParams, CategoryListRefs, CategoryListInteractiveViewState, [], _jay_framework_component.JayComponentCore<PageProps & CategoryListParams, CategoryListInteractiveViewState>>): _jay_framework_fullstack_component.JayStackComponentDefinition<CategoryListRefs, CategoryListSlowViewState, CategoryListFastViewState, CategoryListInteractiveViewState, [Record<string, never>, WixStoresService], [], PageProps & CategoryListParams, {}, _jay_framework_component.JayComponentCore<PageProps & CategoryListParams, CategoryListInteractiveViewState>>;
941
910
  };
942
911
 
943
912
  /**
@@ -1021,4 +990,4 @@ declare function setupWixStores(ctx: PluginSetupContext): Promise<PluginSetupRes
1021
990
  */
1022
991
  declare function generateWixStoresReferences(ctx: PluginReferencesContext): Promise<PluginReferencesResult>;
1023
992
 
1024
- export { type CategoryTree, type GetProductBySlugInput, type ProductPageParams, type ProductSearchParams, type SearchSortOption, WIX_STORES_CONTEXT, WIX_STORES_SERVICE_MARKER, type WixStoresContext, type WixStoresInitData, type WixStoresService, type WixStoresServiceOptions, buildCategoryUrl, buildProductUrl, categoryList, findCategoryImage, findRootCategoryId, findRootCategorySlug, generateWixStoresReferences, getCategories, getProductBySlug, getVariantStock, init, productPage, productSearch, provideWixStoresService, searchProducts, setupWixStores };
993
+ export { type CategoryListParams, type CategoryTree, type GetProductBySlugInput, type ProductPageParams, type ProductSearchParams, WIX_STORES_CONTEXT, WIX_STORES_SERVICE_MARKER, type WixStoresContext, type WixStoresInitData, type WixStoresService, type WixStoresServiceOptions, buildCategoryUrl, buildProductUrl, categoryList, findCategoryImage, findRootCategoryId, findRootCategorySlug, generateWixStoresReferences, getCategories, getProductBySlug, getVariantStock, init, productPage, productSearch, provideWixStoresService, searchProducts, setupWixStores };
package/dist/index.js CHANGED
@@ -238,12 +238,16 @@ function buildProductUrl(urls, tree, slug, mainCategoryId) {
238
238
  function buildCategoryUrl(urls, tree, categorySlug, categoryId) {
239
239
  if (!urls.category) return null;
240
240
  let url = urls.category;
241
- url = url.replace("{category}", categorySlug);
242
241
  if (url.includes("{prefix}")) {
243
242
  const prefixSlug = findRootCategorySlug(categoryId, tree);
244
243
  if (!prefixSlug) return null;
245
244
  url = url.replace("{prefix}", prefixSlug);
245
+ const isRoot = tree.rootIds.has(categoryId);
246
+ url = url.replace("{category}", isRoot ? "" : categorySlug);
247
+ } else {
248
+ url = url.replace("{category}", categorySlug);
246
249
  }
250
+ url = url.replace(/\/\/+/g, "/").replace(/\/+$/, "/");
247
251
  return url.includes("{") ? null : url;
248
252
  }
249
253
  function mapAvailabilityStatus(status) {
@@ -835,7 +839,7 @@ const EMPTY_CATEGORY_HEADER = {
835
839
  breadcrumbs: [],
836
840
  seoData: { tags: [], settings: { preventAutoRedirect: false, keywords: [] } }
837
841
  };
838
- async function findCategoryBySlug(categoriesClient, slug) {
842
+ async function findCategoryBySlug$1(categoriesClient, slug) {
839
843
  const result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("slug", slug).eq("visible", true).limit(1).find();
840
844
  return result.items?.[0] ?? null;
841
845
  }
@@ -849,15 +853,23 @@ async function loadCategoryDetails(categoriesClient, categoryId) {
849
853
  async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplate) {
850
854
  const details = await loadCategoryDetails(wixStoreService.categories, category._id);
851
855
  const cat = details || category;
852
- const imageUrl = cat.image || "";
856
+ const imageUrl = cat.image ? formatWixMediaUrl("", cat.image) : "";
853
857
  const description = cat.description || "";
854
858
  const categoryTree = await wixStoreService.getCategoryTree();
855
- const breadcrumbs = (cat.breadcrumbsInfo?.breadcrumbs || []).map((b) => ({
856
- categoryId: b.categoryId,
857
- name: b.categoryName,
858
- slug: b.categorySlug,
859
- url: categoryUrlTemplate ? buildCategoryUrl(wixStoreService.urls, categoryTree, b.categorySlug, b.categoryId) : ""
860
- }));
859
+ const breadcrumbs = [
860
+ ...(cat.breadcrumbsInfo?.breadcrumbs || []).map((b) => ({
861
+ categoryId: b.categoryId,
862
+ name: b.categoryName,
863
+ slug: b.categorySlug,
864
+ url: categoryUrlTemplate ? buildCategoryUrl(wixStoreService.urls, categoryTree, b.categorySlug, b.categoryId) : ""
865
+ })),
866
+ {
867
+ categoryId: cat._id || "",
868
+ name: cat.name || "",
869
+ slug: cat.slug || "",
870
+ url: categoryUrlTemplate ? buildCategoryUrl(wixStoreService.urls, categoryTree, cat.slug || "", cat._id || "") : ""
871
+ }
872
+ ];
861
873
  const seoData = cat.seoData ? {
862
874
  tags: (cat.seoData.tags || []).map((tag, index) => ({
863
875
  position: index.toString().padStart(2, "0"),
@@ -897,7 +909,7 @@ async function buildCategoryHeader(wixStoreService, category, categoryUrlTemplat
897
909
  header = { ...header, description: parent.description };
898
910
  }
899
911
  if (!header.imageUrl) {
900
- const parentImage = parent.image || "";
912
+ const parentImage = parent.image ? formatWixMediaUrl("", parent.image) : "";
901
913
  if (parentImage) {
902
914
  header = { ...header, imageUrl: parentImage, hasImage: true };
903
915
  }
@@ -914,13 +926,13 @@ async function renderSlowlyChanging$2(props, wixStores) {
914
926
  let activeCategory = null;
915
927
  let baseCategoryId = null;
916
928
  if (subcategorySlug) {
917
- activeCategory = await findCategoryBySlug(wixStores.categories, subcategorySlug);
929
+ activeCategory = await findCategoryBySlug$1(wixStores.categories, subcategorySlug);
918
930
  baseCategoryId = activeCategory?._id ?? null;
919
931
  } else if (categorySlug) {
920
- activeCategory = await findCategoryBySlug(wixStores.categories, categorySlug);
932
+ activeCategory = await findCategoryBySlug$1(wixStores.categories, categorySlug);
921
933
  baseCategoryId = activeCategory?._id ?? null;
922
934
  } else if (defaultCategorySlug) {
923
- activeCategory = await findCategoryBySlug(wixStores.categories, defaultCategorySlug);
935
+ activeCategory = await findCategoryBySlug$1(wixStores.categories, defaultCategorySlug);
924
936
  }
925
937
  const tree = await wixStores.getCategoryTree();
926
938
  const categoryHeader = activeCategory ? await buildCategoryHeader(wixStores, activeCategory, wixStores.urls.category) : EMPTY_CATEGORY_HEADER;
@@ -1188,24 +1200,25 @@ function mapInfoSections(infoSections) {
1188
1200
  uniqueName: infoSection.uniqueName || ""
1189
1201
  }));
1190
1202
  }
1191
- function mapSeoData(seoData) {
1192
- return {
1193
- tags: seoData?.tags?.map((tag, index) => ({
1194
- position: index.toString().padStart(2, "0"),
1195
- type: tag.type,
1196
- props: Object.entries(tag.props || {}).map(([key, value]) => ({ key, value })),
1197
- meta: Object.entries(tag.meta || {}).map(([key, value]) => ({ key, value })),
1198
- children: tag.children
1199
- })),
1200
- settings: {
1201
- preventAutoRedirect: seoData?.settings?.preventAutoRedirect || false,
1202
- keywords: seoData?.settings?.keywords.map((keyword) => ({
1203
- isMain: keyword.isMain,
1204
- origin: keyword.origin,
1205
- term: keyword.term
1206
- }))
1203
+ function mapSeoHeadTags(seoData) {
1204
+ if (!seoData)
1205
+ return [];
1206
+ const headTags = (seoData.tags || []).map((tag) => ({
1207
+ tag: tag.type || "meta",
1208
+ attrs: Object.fromEntries(Object.entries(tag.props || {}).map(([key, value]) => [key, value])),
1209
+ children: tag.children || void 0
1210
+ }));
1211
+ const keywords = seoData.settings?.keywords;
1212
+ if (keywords?.length) {
1213
+ const terms = keywords.map((k) => k.term).filter(Boolean);
1214
+ if (terms.length) {
1215
+ headTags.push({
1216
+ tag: "meta",
1217
+ attrs: { name: "keywords", content: terms.join(", ") }
1218
+ });
1207
1219
  }
1208
- };
1220
+ }
1221
+ return headTags;
1209
1222
  }
1210
1223
  function mapMediaType(mediaType) {
1211
1224
  if (mediaType === "VIDEO")
@@ -1214,12 +1227,19 @@ function mapMediaType(mediaType) {
1214
1227
  return MediaType.IMAGE;
1215
1228
  }
1216
1229
  function mapMedia(media) {
1217
- const mainMediaType = mapMediaType(media.main.mediaType);
1230
+ const main = media?.main;
1231
+ if (!main) {
1232
+ return {
1233
+ selectedMedia: { url: "", mediaType: MediaType.IMAGE, thumbnail_50x50: "" },
1234
+ availableMedia: []
1235
+ };
1236
+ }
1237
+ const mainMediaType = mapMediaType(main.mediaType);
1218
1238
  return {
1219
1239
  selectedMedia: {
1220
- url: formatWixMediaUrl(media.main._id, media.main.url),
1240
+ url: formatWixMediaUrl(main._id, main.url),
1221
1241
  mediaType: mainMediaType,
1222
- thumbnail_50x50: formatWixMediaUrl(media.main._id, media.main.url, { w: 50, h: 50 })
1242
+ thumbnail_50x50: formatWixMediaUrl(main._id, main.url, { w: 50, h: 50 })
1223
1243
  },
1224
1244
  availableMedia: media.itemsInfo?.items?.map((item) => ({
1225
1245
  mediaId: item._id,
@@ -1228,7 +1248,7 @@ function mapMedia(media) {
1228
1248
  mediaType: item.mediaType === "IMAGE" ? MediaType.IMAGE : MediaType.VIDEO,
1229
1249
  thumbnail_50x50: formatWixMediaUrl(item._id, item.url, { w: 50, h: 50 })
1230
1250
  },
1231
- selected: item._id === media.main._id ? Selected.selected : Selected.notSelected
1251
+ selected: item._id === main._id ? Selected.selected : Selected.notSelected
1232
1252
  })) ?? []
1233
1253
  };
1234
1254
  }
@@ -1343,9 +1363,9 @@ async function renderSlowlyChanging$1(props, wixStores) {
1343
1363
  productType: mapProductType(productType),
1344
1364
  options: mapOptionsToSlowVS(options),
1345
1365
  infoSections: mapInfoSections(infoSections),
1346
- modifiers: mapModifiersToSlowVS(modifiers),
1347
- seoData: mapSeoData(seoData)
1366
+ modifiers: mapModifiersToSlowVS(modifiers)
1348
1367
  },
1368
+ headTags: mapSeoHeadTags(seoData),
1349
1369
  carryForward: {
1350
1370
  productId: _id,
1351
1371
  mediaGallery: mapMedia(media),
@@ -1355,7 +1375,7 @@ async function renderSlowlyChanging$1(props, wixStores) {
1355
1375
  price: actualPriceRange?.minValue?.formattedAmount || "",
1356
1376
  strikethroughPrice: actualPriceRange?.minValue?.amount !== product.compareAtPriceRange?.minValue?.amount ? compareAtPriceRange?.minValue?.formattedAmount || "" : "",
1357
1377
  pricePerUnit: physicalProperties?.pricePerUnitRange?.minValue?.description,
1358
- stockStatus: inventory?.availabilityStatus === "IN_STOCK" ? StockStatus.IN_STOCK : StockStatus.OUT_OF_STOCK,
1378
+ stockStatus: inventory?.availabilityStatus === "IN_STOCK" || inventory?.availabilityStatus === "PARTIALLY_OUT_OF_STOCK" ? StockStatus.IN_STOCK : StockStatus.OUT_OF_STOCK,
1359
1379
  variants: mapVariants(variantsInfo)
1360
1380
  }
1361
1381
  };
@@ -1363,17 +1383,45 @@ async function renderSlowlyChanging$1(props, wixStores) {
1363
1383
  }
1364
1384
  async function renderFastChanging(props, slowCarryForward, wixStores) {
1365
1385
  const Pipeline = RenderPipeline.for();
1386
+ const { variants } = slowCarryForward;
1387
+ const defaultVariant = variants.find((v) => v.inventoryStatus === StockStatus.IN_STOCK) || variants[0];
1388
+ const options = slowCarryForward.options.map((option) => {
1389
+ const variantChoice = defaultVariant.choices.find((c) => c.optionChoiceIds.optionId === option._id);
1390
+ if (!variantChoice)
1391
+ return option;
1392
+ return {
1393
+ ...option,
1394
+ choices: option.choices.map((choice) => ({
1395
+ ...choice,
1396
+ isSelected: choice.choiceId === variantChoice.optionChoiceIds.choiceId
1397
+ }))
1398
+ };
1399
+ });
1400
+ let mediaGallery = slowCarryForward.mediaGallery;
1401
+ if (defaultVariant.mediaId) {
1402
+ const mediaIndex = mediaGallery.availableMedia.findIndex((m) => m.mediaId === defaultVariant.mediaId);
1403
+ if (mediaIndex >= 0) {
1404
+ mediaGallery = {
1405
+ selectedMedia: mediaGallery.availableMedia[mediaIndex].media,
1406
+ availableMedia: mediaGallery.availableMedia.map((m, i) => ({
1407
+ ...m,
1408
+ selected: i === mediaIndex ? Selected.selected : Selected.notSelected
1409
+ }))
1410
+ };
1411
+ }
1412
+ }
1366
1413
  const isInStock = slowCarryForward.stockStatus === StockStatus.IN_STOCK;
1367
1414
  return Pipeline.ok({
1368
- actionsEnabled: isInStock,
1369
- options: slowCarryForward.options,
1415
+ actionsEnabled: isInStock && defaultVariant.inventoryStatus === StockStatus.IN_STOCK,
1416
+ options,
1370
1417
  modifiers: slowCarryForward.modifiers,
1371
- mediaGallery: slowCarryForward.mediaGallery,
1372
- sku: slowCarryForward.variants[0].sku,
1373
- price: slowCarryForward.variants[0].price,
1418
+ mediaGallery,
1419
+ sku: defaultVariant.sku,
1420
+ price: defaultVariant.price,
1374
1421
  pricePerUnit: slowCarryForward.pricePerUnit || "",
1375
- stockStatus: slowCarryForward.stockStatus,
1376
- strikethroughPrice: slowCarryForward.variants[0].strikethroughPrice,
1422
+ stockStatus: defaultVariant.inventoryStatus,
1423
+ strikethroughPrice: defaultVariant.strikethroughPrice,
1424
+ isAddingToCart: false,
1377
1425
  quantity: { quantity: 1 }
1378
1426
  }).toPhaseOutput((viewState) => ({
1379
1427
  viewState,
@@ -1384,14 +1432,28 @@ async function renderFastChanging(props, slowCarryForward, wixStores) {
1384
1432
  }));
1385
1433
  }
1386
1434
  const productPage = makeJayStackComponent().withProps().withServices(WIX_STORES_SERVICE_MARKER).withLoadParams(loadProductParams).withSlowlyRender(renderSlowlyChanging$1).withFastRender(renderFastChanging);
1435
+ async function findCategoryBySlug(categoriesClient, slug) {
1436
+ const result = await categoriesClient.queryCategories({ treeReference: { appNamespace: "@wix/stores" } }).eq("slug", slug).eq("visible", true).limit(1).find();
1437
+ return result.items?.[0] ?? null;
1438
+ }
1387
1439
  async function renderSlowlyChanging(props, wixStores) {
1388
1440
  const Pipeline = RenderPipeline.for();
1441
+ const parentCategorySlug = props.parentCategory ?? wixStores.defaultCategory;
1442
+ let parentCategoryId = null;
1443
+ if (parentCategorySlug) {
1444
+ const parentCat = await findCategoryBySlug(wixStores.categories, parentCategorySlug);
1445
+ parentCategoryId = parentCat?._id ?? null;
1446
+ }
1389
1447
  return Pipeline.try(async () => {
1390
- const result = await wixStores.categories.queryCategories({
1448
+ let query = wixStores.categories.queryCategories({
1391
1449
  treeReference: {
1392
1450
  appNamespace: "@wix/stores"
1393
1451
  }
1394
- }).eq("visible", true).find();
1452
+ }).eq("visible", true);
1453
+ if (parentCategoryId) {
1454
+ query = query.eq("parentCategory.id", parentCategoryId);
1455
+ }
1456
+ const result = await query.find();
1395
1457
  return result.items || [];
1396
1458
  }).recover((error) => {
1397
1459
  console.error("Failed to load categories:", error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/wix-stores",
3
- "version": "0.15.5",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "description": "Wix Stores API client for Jay Framework",
6
6
  "license": "Apache-2.0",
@@ -22,8 +22,9 @@
22
22
  "./get-variant-stock.jay-action": "./dist/actions/get-variant-stock.jay-action"
23
23
  },
24
24
  "scripts": {
25
- "build": "npm run clean && npm run definitions && npm run build:client && npm run build:server && npm run build:copy-contract && npm run build:types",
25
+ "build": "npm run clean && npm run definitions && npm run build:client && npm run build:server && npm run build:copy-contract && npm run build:types && npm run validate",
26
26
  "definitions": "jay-cli definitions lib",
27
+ "validate": "jay-stack-cli validate-plugin",
27
28
  "build:client": "vite build",
28
29
  "build:server": "vite build --ssr",
29
30
  "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/",
@@ -34,16 +35,16 @@
34
35
  "test": ":"
35
36
  },
36
37
  "dependencies": {
37
- "@jay-framework/component": "^0.15.5",
38
- "@jay-framework/fullstack-component": "^0.15.5",
39
- "@jay-framework/reactive": "^0.15.5",
40
- "@jay-framework/runtime": "^0.15.5",
41
- "@jay-framework/secure": "^0.15.5",
42
- "@jay-framework/stack-client-runtime": "^0.15.5",
43
- "@jay-framework/stack-server-runtime": "^0.15.5",
44
- "@jay-framework/wix-cart": "^0.15.5",
45
- "@jay-framework/wix-server-client": "^0.15.5",
46
- "@jay-framework/wix-utils": "^0.15.5",
38
+ "@jay-framework/component": "^0.16.0",
39
+ "@jay-framework/fullstack-component": "^0.16.0",
40
+ "@jay-framework/reactive": "^0.16.0",
41
+ "@jay-framework/runtime": "^0.16.0",
42
+ "@jay-framework/secure": "^0.16.0",
43
+ "@jay-framework/stack-client-runtime": "^0.16.0",
44
+ "@jay-framework/stack-server-runtime": "^0.16.0",
45
+ "@jay-framework/wix-cart": "^0.16.0",
46
+ "@jay-framework/wix-server-client": "^0.16.0",
47
+ "@jay-framework/wix-utils": "^0.16.0",
47
48
  "@wix/categories": "^1.0.185",
48
49
  "@wix/sdk": "^1.21.5",
49
50
  "@wix/sdk-runtime": "^1.0.11",
@@ -54,9 +55,10 @@
54
55
  "@babel/core": "^7.23.7",
55
56
  "@babel/preset-env": "^7.23.8",
56
57
  "@babel/preset-typescript": "^7.23.3",
57
- "@jay-framework/compiler-jay-stack": "^0.15.5",
58
- "@jay-framework/jay-cli": "^0.15.5",
59
- "@jay-framework/vite-plugin": "^0.15.5",
58
+ "@jay-framework/compiler-jay-stack": "^0.16.0",
59
+ "@jay-framework/jay-cli": "^0.16.0",
60
+ "@jay-framework/jay-stack-cli": "^0.16.0",
61
+ "@jay-framework/vite-plugin": "^0.16.0",
60
62
  "nodemon": "^3.0.3",
61
63
  "rimraf": "^5.0.5",
62
64
  "tslib": "^2.6.2",
package/plugin.yaml CHANGED
@@ -27,8 +27,15 @@ actions:
27
27
  - name: getVariantStock
28
28
  action: get-variant-stock.jay-action
29
29
 
30
- # Plugin initialization uses makeJayInit pattern in lib/init.ts
31
- # Export name defaults to 'init'
30
+ services:
31
+ - name: wix-stores
32
+ marker: WIX_STORES_SERVICE_MARKER
33
+ description: Wix Stores Catalog V3 API (products, categories, inventory, customizations) with lazy-loaded caching
34
+
35
+ contexts:
36
+ - name: wix-stores
37
+ marker: WIX_STORES_CONTEXT
38
+ description: Client-side stores access with product variant resolution and delegated cart operations
32
39
 
33
40
  setup:
34
41
  handler: setupWixStores
@@ -1,193 +0,0 @@
1
- name: category-page
2
- tags:
3
- # Category/Collection information (from Wix Stores Collection API)
4
- - tag: _id
5
- type: data
6
- dataType: string
7
- description: Collection GUID
8
-
9
- - tag: name
10
- type: data
11
- dataType: string
12
- required: true
13
- description: Collection name
14
-
15
- - tag: description
16
- type: data
17
- dataType: string
18
- description: Collection description
19
-
20
- - tag: slug
21
- type: data
22
- dataType: string
23
- description: Collection slug
24
-
25
- - tag: visible
26
- type: data
27
- dataType: boolean
28
- description: Collection visibility (impacts dynamic pages only)
29
-
30
- - tag: numberOfProducts
31
- type: data
32
- dataType: number
33
- description: Number of products in the collection
34
-
35
- # Media (from Wix Stores Collection API)
36
- - tag: media
37
- type: sub-contract
38
- description: Media items associated with this collection
39
- tags:
40
- - tag: mainMedia
41
- type: sub-contract
42
- description: Primary media for the collection
43
- tags:
44
- - tag: _id
45
- type: data
46
- dataType: string
47
- description: Media GUID
48
-
49
- - tag: url
50
- type: data
51
- dataType: string
52
- description: Media URL
53
-
54
- - tag: altText
55
- type: data
56
- dataType: string
57
- description: Media alt text
58
-
59
- - tag: mediaType
60
- type: data
61
- dataType: enum (IMAGE | VIDEO | AUDIO | DOCUMENT | ZIP)
62
- description: Media item type
63
-
64
- - tag: items
65
- type: sub-contract
66
- repeated: true
67
- trackBy: _id
68
- description: All media items
69
- tags:
70
- - tag: _id
71
- type: data
72
- dataType: string
73
- description: Media GUID
74
-
75
- - tag: url
76
- type: data
77
- dataType: string
78
- description: Media URL
79
-
80
- - tag: altText
81
- type: data
82
- dataType: string
83
- description: Media alt text
84
-
85
- - tag: title
86
- type: data
87
- dataType: string
88
- description: Media item title
89
-
90
- - tag: mediaType
91
- type: data
92
- dataType: enum (IMAGE | VIDEO | AUDIO | DOCUMENT | ZIP)
93
- description: Media item type
94
-
95
- - tag: thumbnail
96
- type: sub-contract
97
- description: Media thumbnail
98
- tags:
99
- - tag: url
100
- type: data
101
- dataType: string
102
- description: Thumbnail URL
103
-
104
- - tag: width
105
- type: data
106
- dataType: number
107
- description: Thumbnail width in pixels
108
-
109
- - tag: height
110
- type: data
111
- dataType: number
112
- description: Thumbnail height in pixels
113
-
114
- - tag: format
115
- type: data
116
- dataType: string
117
- description: Media format (mp4, png, etc.)
118
-
119
- # Breadcrumbs navigation
120
- - tag: breadcrumbs
121
- type: sub-contract
122
- repeated: true
123
- trackBy: categoryId
124
- description: Breadcrumb navigation path
125
- tags:
126
- - tag: categoryId
127
- type: data
128
- dataType: string
129
- description: Category GUID
130
-
131
- - tag: categoryName
132
- type: data
133
- dataType: string
134
- description: Category name in breadcrumb
135
-
136
- - tag: categorySlug
137
- type: data
138
- dataType: string
139
- description: Category slug for link
140
-
141
- - tag: categoryLink
142
- type: interactive
143
- elementType: HTMLAnchorElement
144
- description: Link to category
145
-
146
- # Initial products (SSR - loaded in slow phase)
147
- - tag: products
148
- type: sub-contract
149
- repeated: true
150
- trackBy: _id
151
- description: Initial products in this category (rendered server-side)
152
- link: ./product-card
153
-
154
- # Additional products (loaded on client via "load more")
155
- - tag: loadedProducts
156
- type: sub-contract
157
- repeated: true
158
- trackBy: _id
159
- phase: fast+interactive
160
- description: Additional products loaded on the client
161
- link: ./product-card
162
-
163
- # Load more functionality
164
- - tag: hasMore
165
- type: variant
166
- dataType: boolean
167
- phase: fast+interactive
168
- description: Whether there are more products to load
169
-
170
- - tag: loadMoreButton
171
- type: interactive
172
- elementType: HTMLButtonElement
173
- description: Button to load more products
174
-
175
- - tag: loadedCount
176
- type: data
177
- dataType: number
178
- phase: fast+interactive
179
- description: Number of products currently loaded
180
-
181
- # Loading state
182
- - tag: isLoading
183
- type: variant
184
- dataType: boolean
185
- phase: fast+interactive
186
- description: Whether products are currently loading
187
-
188
- # Empty state
189
- - tag: hasProducts
190
- type: variant
191
- dataType: boolean
192
- phase: fast+interactive
193
- description: Whether category has any products
@@ -1,133 +0,0 @@
1
- import {HTMLElementCollectionProxy, HTMLElementProxy, JayContract} from "@jay-framework/runtime";
2
- import {ProductCardViewState, ProductCardRefs, ProductCardRepeatedRefs} from "./product-card.jay-contract";
3
-
4
- export enum MediaType {
5
- IMAGE,
6
- VIDEO,
7
- AUDIO,
8
- DOCUMENT,
9
- ZIP
10
- }
11
-
12
- export interface MainMediaOfMediaOfCategoryPageViewState {
13
- _id: string,
14
- url: string,
15
- altText: string,
16
- mediaType: MediaType
17
- }
18
-
19
- export enum MediaType {
20
- IMAGE,
21
- VIDEO,
22
- AUDIO,
23
- DOCUMENT,
24
- ZIP
25
- }
26
-
27
- export interface ThumbnailOfItemOfMediaOfCategoryPageViewState {
28
- url: string,
29
- width: number,
30
- height: number,
31
- format: string
32
- }
33
-
34
- export interface ItemOfMediaOfCategoryPageViewState {
35
- _id: string,
36
- url: string,
37
- altText: string,
38
- title: string,
39
- mediaType: MediaType,
40
- thumbnail: ThumbnailOfItemOfMediaOfCategoryPageViewState
41
- }
42
-
43
- export interface MediaOfCategoryPageViewState {
44
- mainMedia: MainMediaOfMediaOfCategoryPageViewState,
45
- items: Array<ItemOfMediaOfCategoryPageViewState>
46
- }
47
-
48
- export interface BreadcrumbOfCategoryPageViewState {
49
- categoryId: string,
50
- categoryName: string,
51
- categorySlug: string
52
- }
53
-
54
- export interface CategoryPageViewState {
55
- _id: string,
56
- name: string,
57
- description: string,
58
- slug: string,
59
- visible: boolean,
60
- numberOfProducts: number,
61
- media: MediaOfCategoryPageViewState,
62
- breadcrumbs: Array<BreadcrumbOfCategoryPageViewState>,
63
- products: Array<ProductCardViewState>,
64
- loadedProducts: Array<ProductCardViewState>,
65
- hasMore: boolean,
66
- loadedCount: number,
67
- isLoading: boolean,
68
- hasProducts: boolean
69
- }
70
-
71
- export type CategoryPageSlowViewState = Pick<CategoryPageViewState, '_id' | 'name' | 'description' | 'slug' | 'visible' | 'numberOfProducts'> & {
72
- media: CategoryPageViewState['media'];
73
- breadcrumbs: Array<CategoryPageViewState['breadcrumbs'][number]>;
74
- products: Array<Pick<CategoryPageViewState['products'][number], '_id' | 'name' | 'slug' | 'productUrl' | 'categoryPrefix' | 'hasDiscount' | 'hasRibbon' | 'productType' | 'quickAddType'> & {
75
- mainMedia: CategoryPageViewState['products'][number]['mainMedia'];
76
- thumbnail: CategoryPageViewState['products'][number]['thumbnail'];
77
- inventory: CategoryPageViewState['products'][number]['inventory'];
78
- ribbon: CategoryPageViewState['products'][number]['ribbon'];
79
- brand: CategoryPageViewState['products'][number]['brand'];
80
- quickOption: Pick<CategoryPageViewState['products'][number]['quickOption'], '_id' | 'name' | 'optionRenderType'> & {
81
- choices: Array<Pick<CategoryPageViewState['products'][number]['quickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
82
- };
83
- secondQuickOption: Pick<CategoryPageViewState['products'][number]['secondQuickOption'], '_id' | 'name' | 'optionRenderType'> & {
84
- choices: Array<Pick<CategoryPageViewState['products'][number]['secondQuickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode'>>;
85
- };
86
- }>;
87
- };
88
-
89
- export type CategoryPageFastViewState = Pick<CategoryPageViewState, 'hasMore' | 'loadedCount' | 'isLoading' | 'hasProducts'> & {
90
- products: Array<Pick<CategoryPageViewState['products'][number], '_id' | 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
91
- quickOption: {
92
- choices: Array<Pick<CategoryPageViewState['products'][number]['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
93
- };
94
- secondQuickOption: {
95
- choices: Array<Pick<CategoryPageViewState['products'][number]['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
96
- };
97
- }>;
98
- loadedProducts: Array<CategoryPageViewState['loadedProducts'][number]>;
99
- };
100
-
101
- export type CategoryPageInteractiveViewState = Pick<CategoryPageViewState, 'hasMore' | 'loadedCount' | 'isLoading' | 'hasProducts'> & {
102
- products: Array<Pick<CategoryPageViewState['products'][number], '_id' | 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
103
- quickOption: {
104
- choices: Array<Pick<CategoryPageViewState['products'][number]['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
105
- };
106
- secondQuickOption: {
107
- choices: Array<Pick<CategoryPageViewState['products'][number]['secondQuickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
108
- };
109
- }>;
110
- loadedProducts: Array<CategoryPageViewState['loadedProducts'][number]>;
111
- };
112
-
113
-
114
- export interface CategoryPageRefs {
115
- loadMoreButton: HTMLElementProxy<CategoryPageViewState, HTMLButtonElement>,
116
- breadcrumbs: {
117
- categoryLink: HTMLElementCollectionProxy<BreadcrumbOfCategoryPageViewState, HTMLAnchorElement>
118
- },
119
- products: ProductCardRepeatedRefs,
120
- loadedProducts: ProductCardRepeatedRefs
121
- }
122
-
123
-
124
- export interface CategoryPageRepeatedRefs {
125
- loadMoreButton: HTMLElementCollectionProxy<CategoryPageViewState, HTMLButtonElement>,
126
- breadcrumbs: {
127
- categoryLink: HTMLElementCollectionProxy<BreadcrumbOfCategoryPageViewState, HTMLAnchorElement>
128
- },
129
- products: ProductCardRepeatedRefs,
130
- loadedProducts: ProductCardRepeatedRefs
131
- }
132
-
133
- export type CategoryPageContract = JayContract<CategoryPageViewState, CategoryPageRefs, CategoryPageSlowViewState, CategoryPageFastViewState, CategoryPageInteractiveViewState>